From 2334c05dca04166384e24737d1a9f609642cc7b4 Mon Sep 17 00:00:00 2001 From: svcmobrel-release Date: Tue, 28 Mar 2023 13:43:54 -0700 Subject: [PATCH] Updating prebuilts and/or headers e8aa3af98539680668d37659b7ba8f7e2becb16b - nvbuild.sh d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh 55bcfa0a03639a375c3f87b1d3286f526c41b207 - arm-trusted-firmware/.versionrc.js 5f8311228df51d284e4efc6c89e9d193dde99d11 - arm-trusted-firmware/.editorconfig 2b66445d7d00314222c238ee2f233a099ac6d838 - arm-trusted-firmware/.commitlintrc.js 1156a747abe8e5f2a639fe82c7e9b4b8c128428c - arm-trusted-firmware/package-lock.json d2180c4f81067554a4fa86baaebf7cd7722d0706 - arm-trusted-firmware/Makefile c10d9e3662b48b6da5c81ce00879a16fd8cf3d60 - arm-trusted-firmware/.cz.json 2d62a7583b85631859c4143f08e0dc332e1cb87e - arm-trusted-firmware/.gitreview da14c19baefee3959f7c02f68db6cbe8c25d408e - arm-trusted-firmware/readme.rst 7f3fadaf80e3c4745d24cb1a5881c7c5f4d898ba - arm-trusted-firmware/.checkpatch.conf 2da4fc2430e852f43b1ec376e4783a1d4658c039 - arm-trusted-firmware/package.json 1684b8fa062fcf155fb678c6e112cf5436423ba2 - arm-trusted-firmware/changelog.yaml d8da3627085908a5f974b45528b85dc0a41a8b75 - arm-trusted-firmware/license.rst 5c6a4c08a854ddd3d464e6d96f605ff5e28fcf28 - arm-trusted-firmware/bl31/ehf.c 75c196ade8ef57a9775c286e3c2f88b52c492e67 - arm-trusted-firmware/bl31/bl31_context_mgmt.c ae44163001e4ade4c2e29f6afb43316e7584ee41 - arm-trusted-firmware/bl31/interrupt_mgmt.c ccc40b094b337f6e60b8a4f2a7470ab4c1264f4f - arm-trusted-firmware/bl31/bl31_main.c 57600ae63b254bd5341c3728038049d1e9526b9a - arm-trusted-firmware/bl31/bl31.ld.S 64b21af0df86a3f591cbf9889b0990e313980048 - arm-trusted-firmware/bl31/aarch64/ea_delegate.S 7c846b0cc5af2d57b0a9ccac7bb940b95f682bce - arm-trusted-firmware/bl31/aarch64/crash_reporting.S a6aee212d05e2c649a137adf37160a8d24360040 - arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S 86ee5f1020a1ae3e8788204817e6b6fcb0da5922 - arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S 2c87153926f8a458cffc9a435e15571ba721c2fa - arm-trusted-firmware/licenses/LICENSE.MIT 8887d0d62a1b5248423fbc54ee536be3e5131d91 - arm-trusted-firmware/services/spd/opteed/opteed_private.h 04de846e914d22f5925ba665f709fd3b0793ea5c - arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h c7af1a7de6cb5d79bf42271e846f04a18df96b63 - arm-trusted-firmware/services/spd/opteed/opteed_pm.c c8ea87fefa1ecd86c162a85206e9427be8c93afb - arm-trusted-firmware/services/spd/opteed/opteed_helpers.S b4e16e85997824311dd82861c4c22d6ed046b817 - arm-trusted-firmware/services/spd/opteed/opteed_main.c e6df3878f8d4759c9f52ea98cbd0d6303bd2983b - arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h 4577f90d8a829f8cb934271e6991bd34844e1854 - arm-trusted-firmware/services/spd/opteed/opteed_common.c c41250dd18f5502066bab243f1a2f33acf9079f5 - arm-trusted-firmware/services/spd/tspd/tspd_private.h 36db67e2b644b85662e0440abdf6bb464032dfb1 - arm-trusted-firmware/services/spd/tspd/tspd_main.c d68051c573aae1f65601f9c9307d095259f8de63 - arm-trusted-firmware/services/spd/tspd/tspd_pm.c 45855bd72493c075e03c590cfade6075e5656654 - arm-trusted-firmware/services/spd/tspd/tspd_common.c f9cf95e919ab4903bc80205e402547ddebe078a8 - arm-trusted-firmware/services/spd/tspd/tspd_helpers.S 61ff410fd8dae3d3ecffc63595125321444d53c7 - arm-trusted-firmware/services/spd/tlkd/tlkd_main.c 176e5bf39535fbb39c81b2deb17ee470cac87159 - arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c c213fbde43c8075e8fe28297dd6934f2f7c5f6fa - arm-trusted-firmware/services/spd/tlkd/tlkd_common.c e4543798b8feb237167dc8c495b7aeb079d1b290 - arm-trusted-firmware/services/spd/tlkd/tlkd_private.h 14bc8b1de264fc27498c195073dcf7c1dd736c4d - arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S cb38cd65497ea7679a3c5ced33d2e833c2f82797 - arm-trusted-firmware/services/spd/trusty/trusty.c ba437dffc2a576e12cd8b8b5e8331a43244754b0 - arm-trusted-firmware/services/spd/trusty/trusty_helpers.S 405a4e398e27192766391869719c952a77d4e789 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c 912f672668f3beed13a6a55a3fab7666e147ea6c - arm-trusted-firmware/services/spd/trusty/sm_err.h 2bbaae4a856f5eba1f98688458729049af38a448 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h 55c35f079c4fec17128f7c644425b13fd516f2e8 - arm-trusted-firmware/services/spd/trusty/smcall.h 32f05b17684cd616a34fd51c98e75162d384217a - arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c 250540ab4306221c494658c2239ffed65aa3fbd9 - arm-trusted-firmware/services/std_svc/pci_svc.c bc64867c51e6a4f26dc11e07d3be01304f8b78e3 - arm-trusted-firmware/services/std_svc/std_svc_setup.c 3e424bb10206165d477d92627a1a6d8955152b74 - arm-trusted-firmware/services/std_svc/spmd/spmd_private.h 6da223d4cbc8ff07b002a40446860274397aa283 - arm-trusted-firmware/services/std_svc/spmd/spmd_main.c eb2fb622fab718a44678ea1273fb7df9d3dd49be - arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c eb5c9e4113243964f83a249807ed07711dc6f145 - arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S 45b49532e2610460e0fba1e6cbf18573f216da9e - arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c 26be0a6e880962cffc338be91ad0f344e8aee9ef - arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h 5d93ba8b111b69b7ef12b9a1ce621d9740284e41 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c 4268337ed8b89db9b3ad75537a8f1e2a008fc949 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h 51c4bc5d5a6c9b18e2f3f2c951d3f8abe0869ba2 - arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S 06bef6d6d25e76eef2278253f480a4afbaebabf3 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S 6b1ef22efba95bff3270de056f0a4e2484528dee - arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds 83a9c2e476136e139d80cac740c65fee111c0ba6 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h ca2e1ed2396b9c004b00095f04cbe848e743043d - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c 2fd31858f771c3fa2d49ac883b8e3bb8486cebae - arm-trusted-firmware/services/std_svc/sdei/sdei_event.c e020a86b0568edbbb8e8a93f2cee43fc4812d475 - arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c 0a593d9b9aca3739ab4d94c4aa2ecdf7481ad305 - arm-trusted-firmware/services/std_svc/sdei/sdei_main.c b8207b17922c0b2192565df4c3bc9e1e9e726afa - arm-trusted-firmware/services/std_svc/sdei/sdei_state.c 36f054958b6c01f03eed070113b49903ce936a5d - arm-trusted-firmware/services/std_svc/sdei/sdei_private.h ed3a4e16186524a88ed19aa95176bc233b0928fe - arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S 0f3a50749094ad519b427c0a9c94db4f8dd32988 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c 99c265f55fed0f586d388c5654338897d9e296e6 - arm-trusted-firmware/services/std_svc/trng/trng_main.c c53e4b9cdb4eaee27196d9759c484c4faeaf7d06 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h e3e6228d6ff51d8d1940c9d13b884a9699bc1a6e - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h 5ddc8c374ed249405453ffb9dd8519ddc8a7a34b - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c 79d13846ac86474d81cf97529b0dcb9876156531 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c 27e07360421aaf616722735cfdc19c90d91af4a0 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c 9f72d160e0732ed98d19b7f82e62c8434b043846 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h f3b6abb1b262ca29c81fe896193453e05ae2fd50 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S 92bbf065b55bbb16728230902e84c1ae124cdd26 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S 358ff3e13baa8507b20744e31468185b03077531 - arm-trusted-firmware/common/bl_common.c 91cec99e37b1e7e986e62eb3474f5b0d63516507 - arm-trusted-firmware/common/image_decompress.c 4e8e81d22968abbb440726d3094bc3a5bbab94c6 - arm-trusted-firmware/common/tf_crc32.c 567e84803ece6e7ea1401d347ecba84600dea543 - arm-trusted-firmware/common/uuid.c bb6318e6a4526a2e75ed8f74f629b22fad67317e - arm-trusted-firmware/common/fdt_wrappers.c d1831078ebc7756a3c141537c4f33b00ce2ffca0 - arm-trusted-firmware/common/fdt_fixup.c 54620aa80f910434a484672d917861106ecc2df1 - arm-trusted-firmware/common/runtime_svc.c f4efa0610d34dd7e2935e65e54d8226cf36f94ff - arm-trusted-firmware/common/desc_image_load.c 3ccdb5028aa976066c06527a27303c4a0db57ead - arm-trusted-firmware/common/tf_log.c b21d0924c4f52357b3815446ebd25cc4f58ad622 - arm-trusted-firmware/common/aarch64/early_exceptions.S 5354886f2c074fe74f50056321be3516724c7536 - arm-trusted-firmware/common/aarch64/debug.S e1451e78efe19651d81b93634da02b524c4ebcab - arm-trusted-firmware/common/backtrace/backtrace.c 8ce1f388b3852351c1fa8d8001d14910363ee672 - arm-trusted-firmware/common/aarch32/debug.S d006178768f88929b34ddd8b6f7caf6ffb1577b4 - arm-trusted-firmware/bl1/bl1_main.c 20113f49289a58e42b03525ea9427f94e093f58f - arm-trusted-firmware/bl1/bl1_private.h 653f6de57d95cb1d74a23acc6389ab9292ef0451 - arm-trusted-firmware/bl1/bl1_fwu.c f34fa7c71b4b146c22d99ea5e88650c232833b2b - arm-trusted-firmware/bl1/bl1.ld.S 587ecb158bf5940ddc7f95250a8802df39806ef0 - arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c d6181e93a353f492a54a5222fe53d793cc6d46d7 - arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S 5c5e2355ca375fa98ae30f56bcf2f57ea7056c71 - arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S 284a0afe619de982f2bd1d4b1c625831ef7b3b5e - arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c 095ac3b2483b968f263618a4bd6cdd8d6f66d321 - arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c 32bd99d2c29b908009a4aea495162f0bb76949db - arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S 6ef2d19cb4ab43cba39eb87d49604192b1f3b2bd - arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S 8d6e2008e280f848fb14017ba5ba559a10724421 - arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c 85b2afc44851dc57e79c264641730d0e2eca3016 - arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c 3793e73034176c719a8160e57d2216f834867aea - arm-trusted-firmware/drivers/scmi-msg/base.h d0830b0dd0dcad2627d7e25042e0b04f9172507d - arm-trusted-firmware/drivers/scmi-msg/common.h 9a06fcf18608dead4701ec10a63da3ace748fe3d - arm-trusted-firmware/drivers/scmi-msg/smt.c 6854b6e16a5d00e32471a842ac82a42307f4fd25 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.h 6494de9c4e6d28e03514a090db2224f8b96327ba - arm-trusted-firmware/drivers/scmi-msg/power_domain.h ed00d8b9bd19e5b6e1f8ecd2721a613d1a9043ef - arm-trusted-firmware/drivers/scmi-msg/power_domain.c a9219fa6261f43e472c7b1655189ae66022de0e2 - arm-trusted-firmware/drivers/scmi-msg/clock.h 20129a454f6019ae086f0fc760ccbe6441c75105 - arm-trusted-firmware/drivers/scmi-msg/clock.c 51f712caca20f1532dbd7a569fab515695f574f9 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.c 0f8a382f7d1dc362cfb9bf7d2a7189987b1bd9f4 - arm-trusted-firmware/drivers/scmi-msg/entry.c 5d761434daa9ee97981a3e3264d4196b1b9710f7 - arm-trusted-firmware/drivers/scmi-msg/base.c d53b18f9aba437cc5d23117338ddac6edd9ba447 - arm-trusted-firmware/drivers/clk/clk.c f1d5a7ca46b231b4291d715aa7312bc93c8c8d3c - arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S a8b2be0d9781815f941f3b5c54c06d66869ebbb8 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c cbb35d75dea21db6209d5ab41ce216af0acbd5f3 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c 7da82df0c542d1d8ae8e69affe9e30ba233590a2 - arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c d354d19d9f42611b3ad0f293660bac71ee3a801c - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h 0c3739bdd3d04953083299f803b7c30e40e3fa93 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h af21526870ded933cf4e5455fdd2935a82cea61b - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c ce75912d66d9d45c7fb5514c2d883363346b1a48 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c 396f26a188a6fb1077b280cdc459ee52ac4dec89 - arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c a4736e2e943ff2c95ee55ab5550d95dbf4e9fae5 - arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c fa805a963aca474eb7b99d376fc23bf898fe4457 - arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c d4cf1b07b3a081078c4e7da1e354adc42f41f7ca - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c e4343fd48fd3beed200fd430ec2f84482e7171bf - arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c bb9ccbfadb1dba83a0035f9bf7b3d22a48fa01ff - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c ba408ad853e9ef0e53ce8319419a8b3d8a3da7ed - arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c 32d20982227d5346d95e069f256ec3556d52ecfe - arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c eeaa299335bd10e0531ff65d6a24c6a4da294057 - arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c ff23fd02b2c8ce84423f099d2b1bea12faf82aec - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c eb5515126eb5fa4bef2f7976e79e3f9fd0944afa - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c 02475a8e210c6615aa5138943337551fc8b9087f - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c f29d54b17cb5dd1f602641d092227c883cb6a57b - arm-trusted-firmware/drivers/nxp/csu/csu.c bf7712fb75e6373abf6791b46d9a4563fd00feb7 - arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c 1d31a2492e42b2087d68ef756a91274f671987c7 - arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c 5579fdab0db3121aceafcaf39eab316e0253aee3 - arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c 3976af866b0f1353ade3d95b9d4ef92a7a2169ea - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h c7adb94bca0f7e2a86394a503007aacd278de299 - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c 85860d4c7284e5f15ce31d18787f687d6bde61b8 - arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c 9b849f025149e6cf51b2500c8f70b38703ed5078 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 9489f5c75aa894fc166bb99b848883d0413170cb - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 753107ce7c270d602a0018c1cabb0ef8e7d3c54a - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 58bff9b3422ffad20520362a80a6f322da632da3 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 8b7ec36599206f1c121cf2a9565bc043b6049dba - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c cb8400c786b03ab4685825c49454f7915622e629 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c e9bddb61157fc79a6db73771f3abc44b0fa2180e - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 aaaf596468de0e2b0f1fd9df798408ccae3ec67c - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c bc6fe6b33a974e9a9e2ae522e3ac00b9f7ff4967 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 dd7d454c97e1855bb1c228cacfecb6238f4e487d - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 5a7943b124da3fea7995adb004eff6a0b928e921 - arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c 06049b8071d1258dcc7829e02727d935c561fa1a - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c 73a87390ee3b46e2b5587087457d8a10a6f4cd35 - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c d3e9bd0226d74dffd59af6ef1c8f029ca195db90 - arm-trusted-firmware/drivers/nxp/console/console_16550.c f15b111b5f8ec4a947c36b642e6c6331bb5331a4 - arm-trusted-firmware/drivers/nxp/console/console_pl011.c 5128d83df7b28a2a4bd817b834e17b74206a84d7 - arm-trusted-firmware/drivers/nxp/console/16550_console.S fed7a4d64f892002dd30f1e1bf50d5fbf537281d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c 33929846548a6a6731c652caf6050b64dea2f9d7 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c 59117917987eb057fe4003d4da4c3125ea76dbc9 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c 442cb1d00ad113cbdc5ce076abc56124655dbe2d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c eaefee9029f7ccfd854a5813aae54ad816808645 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c e083ea048179544e9c8e52f7a48d7c315f03a475 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt 7547f7a2396ef42e0140f69a68424c714c210b19 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c 9c36d85b72ea62f1b3e6d8df34efe02d50c468ca - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h ac55bbcc1387d5092bdce1d236686694d82f2a87 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h 7c05bf68f35c9cbbeb751db67f075cc1bc864b72 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h 8ced20b50814e640a734b45571534428a03235aa - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h f222d8d69c33519c4908bafaaeb6a2482f35bb20 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h aac92f8b51eb5a99b8c6c1b861b65d8ed56c92b9 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h d9b4015568e26bddf900e57b2034588011dc76fe - arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c 6ba34d8cf6a1e66a6b8781b632305c8192f8c47f - arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c 7e7c03a074969dc0547afeb5dbe289ae008dae93 - arm-trusted-firmware/drivers/nxp/qspi/qspi.c 45cce82acdd1f75c2e31f56de0a27738ec712b09 - arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c 1c9fa968ab5e023d06dcdbe0d3d12847d4e13273 - arm-trusted-firmware/drivers/nxp/pmu/pmu.c e87ea077dcc89cfad504b38c454094873eb4bbae - arm-trusted-firmware/drivers/nxp/sfp/sfp.c 904d53ac1f2e9c98f1e176eae19be267e985db33 - arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c 3a182ddb4f6fa33eaf8b5ae0c60f6bdf113f4fcc - arm-trusted-firmware/drivers/nxp/i2c/i2c.c b0d5b078d9666eb577b6d96327526056a9c5ff46 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.h e7fdf9ac8aa8e62e2b82e935887ea9fa71277e50 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.c d92351086a1b0b0b82cfa7bab9e352d5725339d7 - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c 11d6bed45c0c1633f53d1a14e935db95a494322d - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h 30ead9b9f8c8e8a0d0443291726c90dcc10f24ef - arm-trusted-firmware/drivers/imx/uart/imx_uart.c 2b9b4163928ad22b375942df6a419ac25791d15b - arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S bf6cd6123996ffba448042a934561a9845514132 - arm-trusted-firmware/drivers/imx/uart/imx_uart.h 7ff3e84af33c3fcf6ee55936d6400a52d52203b4 - arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c c841aaad58e92f728c90bb7cab1771d2578be18a - arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c 5dda361745c9b337192dcd67fc63865e04a3a8a5 - arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c 304398c75526a767b8b3caaeb5722e41955e9803 - arm-trusted-firmware/drivers/allwinner/axp/common.c f3f36bb92d56df7e9785cc98f6b13594df6404c0 - arm-trusted-firmware/drivers/allwinner/axp/axp803.c 956dadae6d826687fecfa1b522fd8b5c4fdfc764 - arm-trusted-firmware/drivers/allwinner/axp/axp805.c a5328f6dfd065a9ddc6acad1d5ea28176f33e623 - arm-trusted-firmware/drivers/delay_timer/delay_timer.c 0d32873988a7299902bc11961218f9034c494f5b - arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c 53e86084002c599472f206bebfee855f6de44547 - arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c 4e52ca94a347a31cef85fc1cbbd480490ff065b1 - arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S 340b2a1703f14c42abdade167ac06919ec7deed5 - arm-trusted-firmware/drivers/brcm/chimp.c 99056505e9afb98d0bf6b55cbc9c64814734d610 - arm-trusted-firmware/drivers/brcm/sotp.c e8c6d05d166788f91925b45e27853f92f98251e5 - arm-trusted-firmware/drivers/brcm/scp.c 490663a4660be758e46f4878a43d7cb947b072e0 - arm-trusted-firmware/drivers/brcm/spi_sf.c 2f55d6018c61491a206aef1e089af2001db52b87 - arm-trusted-firmware/drivers/brcm/rng.c 9b9a1876a8dd35bdd34baeedd3e531617f4b2e03 - arm-trusted-firmware/drivers/brcm/iproc_gpio.c 9156a544c31c11073920be56fe54eb346a8b018b - arm-trusted-firmware/drivers/brcm/ocotp.c df0910b2680c7694f0b75737fda7682a8712fb64 - arm-trusted-firmware/drivers/brcm/spi_flash.c de63fe21caac7ce499c3a244965fca77766a1d19 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h 653b6a961a19436e1cdba80c2b3b153c1d89a954 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c 2dc1c9032a1e64aa390c69bcdf0a42359e402b5a - arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c c9c8847417d95e3ba03ff5c005edbe8a088cee14 - arm-trusted-firmware/drivers/brcm/mdio/mdio.c a70c96d7324a040b39217a657625b8b369ed65f9 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c f9de2aeddc61d9a8b63a2bb3d10edd5e5459ac61 - arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c 1e16b849ee30029570c17198cc65dd8c232fbd53 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c d89024f769cfa2a2d90ab6fb83691b494227d848 - arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c 26f0937fbff1f7b2effe7d035d4e6d2c2a9c463f - arm-trusted-firmware/drivers/brcm/i2c/i2c.c 279f67f2161b938ba13883aeab4439e24b76eaf2 - arm-trusted-firmware/drivers/mmc/mmc.c 2e8560e1fee7e0d9ba844f802772a8be3e6be7ad - arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c 150bd08bfbcc1de20e05b6d07950021df0a46322 - arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c 3325b2a520df18fb8bd8859eafba82aa1c89eec1 - arm-trusted-firmware/drivers/rambus/trng_ip_76.c 8e0afaebcd5d1ed41d30457bdb8543f3617640eb - arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c 1d5e94fb3b734e7c9eb7b1628230f3d140a8e958 - arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c 366c422651f720b64f0d606e537b12713c405d8e - arm-trusted-firmware/drivers/fwu/fwu.c e5c3d888d354f7edd20c09b85d55293a3302d4ad - arm-trusted-firmware/drivers/partition/partition.c 05e51189eff0f94ffa7616efa4a5cd4c11a90a81 - arm-trusted-firmware/drivers/partition/gpt.c bb264060cf147f5fd4feae216d66ad8c9c66f891 - arm-trusted-firmware/drivers/io/io_fip.c 78ab979470824d9703736ca6da3735d7c11fcba1 - arm-trusted-firmware/drivers/io/io_mtd.c 88a6a7b48a8b3da04a2a2bb9d5bcb70f03c372d3 - arm-trusted-firmware/drivers/io/io_encrypted.c fe0286bc53aeb4cae686fb9d63d9ffe2283cf119 - arm-trusted-firmware/drivers/io/io_dummy.c a28c85766eedc583fd38c5f1cb94aa9d5caf8935 - arm-trusted-firmware/drivers/io/io_block.c 858e3130488ef425faa5341098347a0cd446a49d - arm-trusted-firmware/drivers/io/io_memmap.c 2975f82e852f74ac877b00bfa9bcaa8c3baec7e2 - arm-trusted-firmware/drivers/io/io_storage.c 78d0bb21fe92f684f28119691c173b36006dbbb5 - arm-trusted-firmware/drivers/io/io_semihosting.c 5bf3028d91229a2bab7d9be2fbf3db5b63dbdac5 - arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c 46c3bb0a303498f1a79fd2bc48b1becffddbfd71 - arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c 47003ec4d5650ecd811ae9fe4404621c369f61c6 - arm-trusted-firmware/drivers/mtd/nand/raw_nand.c 010e3cc7bf5be7ac20119f77ab261bdf528f2d2d - arm-trusted-firmware/drivers/mtd/nand/core.c 122bf5d15d1cdbcad5bee82566c57049e3fc5bb5 - arm-trusted-firmware/drivers/mtd/nand/spi_nand.c eefd56420faeb9d836077b23eea175eb7e022871 - arm-trusted-firmware/drivers/mtd/nor/spi_nor.c b601addd7e20d9e7f019014eac336024a1e57b8f - arm-trusted-firmware/drivers/ufs/ufs.c 1fa3c347f937895d6e5869cff641faf35158d0e0 - arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c 639d42262958e84f1bd83a574ec62649802513a1 - arm-trusted-firmware/drivers/auth/img_parser_mod.c c16134fe5a7698bda76781fff2f959b23e9effe3 - arm-trusted-firmware/drivers/auth/auth_mod.c a7feb170a20eb5ee10c9d197dc0097785f67943b - arm-trusted-firmware/drivers/auth/crypto_mod.c bb94b0069937941cd0d158f609df28bc66e7f7df - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c aa57938a1ca87b1c2d69b27e2cb210dd52b72f92 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c ca516c7a1c11d4ea7d2a36636ad140645e6b3ef0 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c ea1ff4dd6466dd5bba2280092f7ad0037f0e3791 - arm-trusted-firmware/drivers/auth/dualroot/cot.c 98690b7915852b4a6a1950623e848b467186a09e - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c 62b38ec608a3b1763bbd31827be93360dc10c4d3 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c fbcbbd0aa417147f5e544e91c47edef162f6aa41 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c efedb0eaa10e440edf6b73b4b2df6a6d164066da - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c 0931c7209af239bcc95387de431d932bf01175ec - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c 1527e9ad692eabc3e379a8f7f0a4eecc68b9f9bb - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c 6e817c6fdbf62d3e636fe69752f1f0bb9281c3a8 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c 07632d2568b5990250c7539319c93e9b64c05004 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c 2802b6fb340525ddb96baca00341a6a25f703c74 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h 4186c27c3850565f08118234f39f3224a0094fb6 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h fa11d997720f3e8e38a41e393a485385f56a4981 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c 4fc3b8212dd33e6a33a9bbf4b96d0ffdb7032083 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h 7262dc7de38f8216be32a2cf973c4077da6a5ced - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h e074216ecbdf97f24cb3e12cc7f5d8e5c99721b5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h 1ebeec74f28d94d33ad88f9e3cb8abeb2ff4462b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h 49c7e8143b952aa89509efb296f2a3d848f1fcf1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h 3ebe3831af51ff6dd31f04c19ed726ea47d12ffb - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h ba3202740e2551524bc86abc295cc82374fea770 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h 17c66fa0e8ef76563d00547c6c281d4fcd025dbf - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h 4120c27434066995e75487d1311e78e2dcf57cb3 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c 5cf260b6fef6d9a6c0ddbe6c45bed9d54daf027e - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c c9bbbceaf55fd9cdcf0943b427f8b302c902199f - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h ae6bc783ddb0cb6feec22e234a5383965ad75a8b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h 046e1d3b18c291d99e7f1f95658f5a6bb9f7c207 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h 8146506bb0d47e4499b692d8a0b0d168c697db9a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c d1c7d38c66ff34e537261485132cb0beb3ab4765 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h 0d2a4685c4bd34d6ec121270bc38ec212c7b1e0a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h 2e4f2532cb1b9aee27f82677a76fc8598ae3e720 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h 05c9d8b400726b0d87a72783f40f17a2a061c31b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h 6a2add07f71f904a80881847adbb4576860c245d - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h a084e9fcbfdc195d063eee7f1561a5b311238aa2 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c 6bfed6bf0d3eb45780762fbb929d5d57eaeaaedd - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h d0a732f21ab78828c622303f2eb7f2ab8e85c92a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h 98bd2a7be1d0dcdf1cc534ac4dfa0adf7b3bd752 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c 635fa9d52596ee34cf2cbf85617657684fb653c1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h d1016ddc5354d7e63a3ef654ae6899c8c078ce00 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h 33416277d7d82e170d6f1d7ef205870c003c8aff - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h 282efe9d196e496f3be41e3be701e9dc02c1bfc5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h 330b138c5e24e14484fbdcc38db468c06168918a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h 80605fd39dfaf3536b1da46e80b450127a5ac723 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c 7c37eb45f9f11ee9f370e775f741dd1075944a69 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h 3ca890e94b8943ef7719c09f20c3a71ad9e60295 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h fe1e1e2a68a2409c85008f78bb7f4048be6dc1c9 - arm-trusted-firmware/drivers/renesas/rzg/board/board.c 8ae500671f7227739bb3b389ee74418bae4974ee - arm-trusted-firmware/drivers/renesas/rzg/board/board.h 45854b76c28a405b83a3ad2f7975038a6a8a34c1 - arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c fb75fabcb7a5cccd23dafcb83996362d131b28e4 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c 3e16dde8ddd77df4368ed97df8dedfcd363f2195 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h 08bed1ad3f35993a6b63c3a553c0cd1f817cdf72 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h 313d480f7fd9b09de41195d3fe75df7e06b8fad2 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c fa65175525fa82bac340b43f6d95f68574a6cd59 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h 987d099de106542df3c8adb7613b27edcfd5cb76 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c 42cec83a589b1e8282a06dc496c09fa4d8019bdf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h 9850cfe7fffb94712b5526ba4dd947a9cec6efbf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c 96023687d119cdc2a88f0f96847b71070be44d0e - arm-trusted-firmware/drivers/renesas/common/common.c d4b40e69b2bea69f35d8d12ed25d623c4bafc89e - arm-trusted-firmware/drivers/renesas/common/pfc_regs.h eb5eaa562bc901bbcea6e5e722e629a4ffe14fa3 - arm-trusted-firmware/drivers/renesas/common/ddr_regs.h b31c95edffddbecf9d51e7ba6d57f59b07381718 - arm-trusted-firmware/drivers/renesas/common/qos_reg.h 8e9c2ed157c641c0bec372759c5f0d1a29495392 - arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c f6c548f6ac120c9eae0551d5ca111a654a28e241 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c 04d76f4dff98e3290cc3b56689eea7eae6973401 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h 197394f4b9c3387bbbe8ade40aed6fd5ba67cd49 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c 81389d507ab4f6c15c8302b9d4a550e929350170 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h ba0424f1fb02f541d26148c808ee8576203fae19 - arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c db6311bc705a8c1d60a616425947adcee84d1063 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h 724917ae7e24d07722880d4b74d6a9730336be06 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c 648595ebf99d157ff5bec437919b34a18258b411 - arm-trusted-firmware/drivers/renesas/common/scif/scif.S 23d0235cda981605fc638d9031316ff71003ea9f - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c 5737620466366563b17443ac716f582a4a0e1e8b - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h 7c0cd66835bf24e2086572d390e9e42847b2cc7c - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h 7e6776a062962247d7356aa2a4e3db30e8ec9a35 - arm-trusted-firmware/drivers/renesas/common/io/io_common.h d954a56fdaa915b42433e7f02b933ff5a7f4d553 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h 2a9a321a7d2d3f302f63914ea61c0b24ef77ae46 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c 94592c6b00d8f46906214144913018912da2cdb1 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h cc69cc1cdbf38f685bfb8c4e843841fc12c17072 - arm-trusted-firmware/drivers/renesas/common/io/io_private.h ff8a273a7c0157436d3d58824bb0822c1e4c8880 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c 4c9c3edfff804648e78fdb6173511fedc8d655c9 - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c b95edfb86992c01b146085a6a3a6fa260f62cfb1 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h 1f0175831d01e9a83091abf339b764707fa15732 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c da6c00a918a45fb21f34a94a1153a619126f856e - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c 53d888462033b6fd9f510352b7ef5a997db98215 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h 1806c4fed1e8009245193be345f42a0bc99a88ff - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c d18f211fb0f471b7b72797133ccf3a89ff3fe561 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c e38e56acce60e8f8ba79bf52ebdccbfbb84e60e7 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c 7526f3b1661670d99bae978d76b826697f8eafcc - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h e3d0fe455add19648ab1dab17abbf8a036851187 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c 9c78d4764ec4942f586af7e70fa2906b79718e72 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h ae1066faf4581bdf2b74fc79c6880b4541c50262 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h 3a2172abc0cd0c826ca5c1f958e47c616e2d0c2c - arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c f81a020bdd63ac732719bf014ffb749bc0f35bba - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h e285ce8fb65a4579da74f1406d12000d292f45ad - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c 26bba8a723b7f85d907e8da853e41cb0ec1bc46c - arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S 3567bb0ce5e977a1fe4ee5a8fed4db8dc67ccca3 - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h bbe9ec354aa9a66731a4a68b1214e7c88433e78e - arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h f6092db4bdf15b55332ebf36fb13af42ee1b8f8e - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c 24c58c71c66617770ef83cfba554a31128de8f35 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c 55a51a3127d0a24e084fc5ad73c0ddc5d5b2fe3b - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h b5212a79f0a8c1abb0c5088b5730968747253bd9 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c f5798c0927729a362f779e583438e52a2da51faf - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c b014a41cf8b77ed434dc0aaeae7efd1a154065c4 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h 94ab11fdbe4c8a942cb23f6604e8a013e0c6c083 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c 178140849c7796c20b8a14ef9af086d4ffb485f1 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h 1f8f7c4a456ce374f80860dcefeb3a1eed7e1b7d - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h d8448100b460ddc591a2eefae6d2d0abecab166a - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h e40feff18e0868d48c4bdcc23024fa824eb612ad - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h 56a16c8b12428935f7d194f7bdbda33ebc432e4f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h fe75f352b6a7e1643f0857f578e85a4c301d504f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c fe518460e8298941fd3ff47df2330afba56085ca - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c 08b9d46b2389e6316b27218e1e80071e3891915b - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h c11df9b69a5d8144823fe6b09c8aee8c6dac3579 - arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S 11290dbdcaf0fc67e9947d59e3177ac503f1276c - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c 6173062885150750f1c102edb35796e50d6a012a - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h ba3873513a76a74ceff9f6818187870191d1faba - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h c2b1735bd5896fe759c99cc8b22c392af5bb841b - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c 50775f0e3315375d2b392a52b57df2e19834d985 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h cb0d0e4e929b276e850cc30884ddfd8846a9048f - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h bab2ef59fc4f4088c90466ebb4823889a1bf3996 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c bd60292a364659d7f11eeecac384213969357c04 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h 700940ac5d64f4902064fbf6670e6e59150d9fd0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h f5fd4a9a5d50b214bc6ebdebed3c35ae0f1f2be4 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h 8eea8028ec6b2cd4e6e1c5e0a8d8fd9af01ff4fd - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h f0db0106cc97b359f7a0ab316784658b79e9d544 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h 12e645da3e7fc81893eb36796412a928fc06e57e - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c 7131d3227d06785258892fe7a42df3c91cc8c9f9 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h 824a3717d01b009cea509c61015e64d1722fc212 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h a6934a3af85414d49cca5e5d99e162bbe9ca133b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h f8c08f7eee854de735ce3c60a3e23d3f74fd73f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h 23507b41fbfc9c3a39c4c3f5daf7562d67d10b1b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h 6ea58175e376d869ac3c2a4f103d934df3c2c465 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h 7c805660400d6f609148f8124439843b39232355 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c 59c0f7639b01b8af843d8142eb013348e6a1ba18 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h 7329eefcfc343e2cafffcbc3a208b34789e57968 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h b7890473a9576eca8081825037d037349512add5 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c 8dbbe234d937dcc1acc85648ecf831824fb5fa48 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c bc682493eeddc9cec3b24b5dd37418a00e0c064a - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h dae17d610957cce3799fa9c9946c0196c67d46ac - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h 8623a6e816d06c37ce20ab1b6e410fc23c052d43 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h 504bd76520d259ea03e8b93380c763a3c17ffeb0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h 630b48fd35a697ed4d1daa03bfc67d0d299a2776 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h 811eb1fecd60de207e7c92a5986acb80e7ecf0f3 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h 8b5287985d180436c31df99d29c586fa8ddf0f26 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c 6dea13df81dd5a2913039ff42dcb9216eb922586 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h 114cb09f888b76f0b1356fb126a483be754d2cd6 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c 81d4efe56b1d9f4c44c942700d01a9ede1677bae - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h 48f7ee0d258f661040d23d898a98d0bc9c066613 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h d50c2a6a6c4e4910f4fabd7c774ce1986b97ea19 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c 21ada158d24d4473b1e20f73c499f4d5600e3c8b - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h 70405034a321bd4ced206115508ab438f2f536f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h f1b2a6505d48a1a6566f88c1e80b4f27cb09896e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h 8c12bb78bc33032ca8926351b3eedbe5b2b4c81b - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c 8aa68f57355243a72231c3848caec899565cf5da - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h 7e2114420402542982a251fc6b54152f32b0dd88 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c 10f2fc91f336438e4f2073ea1a665d5d67fb79c7 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c 77f8e84524f8a31cd4e5261eca8974eec4bd131a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h 2717b8ac46d4da69ba6b99a7f25097f9e314aad3 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h 2a066b2fcd7583651082fa57bbf12dfe4352326f - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h a3a502f90241a6c8f8be7ed9af2e0b6cfe9e59e5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h 7cbcad70fd46dc5761bb14b31f104d6806752af8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h 758dc7396c31d1186836e5ed6c7cafd0a678b4f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h 6b699b1443429c5428b8a7056804ed3da10f02f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h bf20ed2160ab9535cba30cc680a7bf881b5a442a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h a6126e66f35f584f38379a6ee5529fed08edf8d8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h ec016158b5c3b5502240e5835181cf7929e6fb5e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h aa7f8d7b49fdee6efbfc48acf8e8bddb01fd52a4 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h 4c577e5e3e00506da4ab89990b8dae561786e20a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h 3d6b988f34914a47bf479526f1f10849a2ae3ae5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c 96354da81a56cb6373ff756124b8eee42409bfca - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h 60944cd086bb0354e4747ae185b5149ae3f85f72 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h 2bb5c4f7c8795b5aeecf3a8997f515c4890514ae - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h fb1b1122066b12b184582d53d643246b1a414b3b - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c b8ba25ef62d360d72dd17d26934062bc0eeea376 - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h c2f5bcbfd3751341e871e36cd4d2f278b2a4150d - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h cf8b9626df3b3f81ae4674acc1f379aaf9eea1b5 - arm-trusted-firmware/drivers/renesas/rcar/board/board.c ef114d85e930b49c92bef6398031e37cb6afcbb3 - arm-trusted-firmware/drivers/renesas/rcar/board/board.h 3ae8c8947fe42e322d70fb7903ada181bfd006ed - arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c 7a112959b420ec60382c2d5688ddced8ca0affd4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c 5eda21c234b108bb6ed5b65d5e58825ec9ac0210 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h 8472797f3f7c7a334dd21719d4dd718c5df01e47 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h 83dad15a244674be1d30dc0200428aa0e82090e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c c7dfaadbc4d96d1fceadc4fae5536b1e1a9cdd59 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c c248864592a61213518c8881be85e4f65fe0a3a2 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h b9d9644305cbbf1e06e176a46903dd18819761a4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h cc2f31ac87f68592bc44f9d3435c79d99e7dc0e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c 6fb897befbc4164b71d8975b2d5322b9e77412b4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c 3802b683cd17e49eba932611e33205446291cde4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h 1a2dd6951973faf90ec734331605c3fb336bde9f - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h ed9b151f951387e31b4a9fc5a26f0d4621beaf13 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c a7f9c2cb5010e2bfe1f501830a449d314d447ce7 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h 6465a6a55c524b8ffb1dca351757b9d96e79d203 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c c83fb1312ae05c6e624572806f085c6919f189af - arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S 1a38fc90bd2ad3b33e7c09de2e338d2f993efe99 - arm-trusted-firmware/drivers/console/multi_console.c 48cb55cb2ee35cd09c7a0759acecc0e5facfe576 - arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S b837201998c7093cf24c9131e39734b99ab455be - arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S c8524aa6f76d32913ffaffda10350b753e429b5b - arm-trusted-firmware/drivers/marvell/ddr_phy_access.c 77e98f136f88749eb01cf7092f9d086cae652384 - arm-trusted-firmware/drivers/marvell/thermal.c f00e9719e8be0259cb5e171298f2ffb0d09c4fef - arm-trusted-firmware/drivers/marvell/gwin.c e082e89bfcb90fcea87099285d6eb142fff1f589 - arm-trusted-firmware/drivers/marvell/io_win.c 857ba1731ec174905f4cccd68d02bdd3abf08b6e - arm-trusted-firmware/drivers/marvell/amb_adec.c b724830f0762dc7701cc9fd88c863c7b53f405c5 - arm-trusted-firmware/drivers/marvell/iob.c e352b30931747ba506a85329d7c6fe69935dd5b0 - arm-trusted-firmware/drivers/marvell/ccu.c a275b56587e6c0c05df6a7985ad0cf0e2216e4f8 - arm-trusted-firmware/drivers/marvell/comphy.h 6dc9f5af1b3c165888d4faae36b6da72adb6faf0 - arm-trusted-firmware/drivers/marvell/cache_llc.c c523b2dcff8e39c5cacc416584d42aa530a93315 - arm-trusted-firmware/drivers/marvell/mci.c 6256615787b3a1bb1f9b4fc3d64794006722b859 - arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c d0ef41df34b7a9ed1d587f10727ba0ee57d04c83 - arm-trusted-firmware/drivers/marvell/ddr_phy_access.h 6426cc04f9e4ae36d19a6624130d17fd035ba491 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h 282cbabd8ee584e3d6c2657cd202c11bbbf31685 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c cd9af6970ea49226ec63b2b04d0b06b86d503eae - arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c bb5f60fb041d3fbc6812ce56b8976c686be8105a - arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c 9a1f55dbc2fc4e8ca97f9af3e7d435f1bddfd83c - arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c db0bb43d5c002bc3633403571c9e8c06da7c0ead - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h 4fc44238fa459de070b3ffae100986f736c5e3d2 - arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h 041d0631d9cb0fe39ee3d1f8d20629d3d2225f86 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h 1ceb9ca7a78559ee70cb2833d391d99c2ccb3334 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h 52740dfd3574268d954c81e6a708c55188bca7e1 - arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h 6b20ef2ea4fdeded083ed64a100d2e10cc8c4fdb - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c dc409874b01f2f616b65f4f9e8497ba172fb2535 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c 02f2c79a0efffc643c301848b83a26b232291cec - arm-trusted-firmware/drivers/marvell/uart/a3700_console.S 10ce6fa5d5bbc4205013818f591e235cbcadccd1 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h f89de6e4fae5d6f6d1778f6c5a92d7f25ab403b9 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c e586fb95d55e301bd75a1db9d6ac7b843f45984f - arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c 5a1bf4459a810008901d22e77f2e66c2af4ca7f9 - arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h 12a1ccf32210f9e1106d8d27942f264ab96f58fd - arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c 627856de3e6c6e4ff2ba2bf3dc3803a13f08d1bb - arm-trusted-firmware/drivers/gpio/gpio.c b98ff0dbd7f6535bc154869089df5f242b23f799 - arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S cf240f037fbcd65fb3db19fb6994d2f4aaaa52f9 - arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S 0fc051c6d2c2e54cfe39b37cf1a1f85f883f31e3 - arm-trusted-firmware/drivers/usb/usb_device.c 5506b6895fb8d1c468b2bcaeb55a18fba8ecdcff - arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c ecd654f25b5590f6fd4dfb3c349577da03a78337 - arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c 1529e10e42582df4a41e7632598e85d97dd59ebb - arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c 9383db5e25bb3e3bb240d302eb1e2c81b067f1fd - arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c c8a2a84e6453323aa9b1b1cd2a29c6ad56036b5e - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h abd5092c485b60d2dc6d910618e64227d766ff87 - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c 09b3e4f32ad36ab93f598fd53971e18cdb4eed9f - arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c f0d5a528ed1a6d54f39bc84a21586d25029d60b2 - arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c 6bf9357dbb7589b0078e1896de5a58f760761979 - arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c dc5909c790f8267bcb9bbc047b904810550cb78b - arm-trusted-firmware/drivers/st/pmic/stpmic1.c 31f2612aff5d24d64b3826cbe5c7a9f93ff7eb70 - arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c a9d894b2465b17dff1217d99ed6752861aadc069 - arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c 2f6084a9d8f84bf599746cd3288b02a0d4755d3c - arm-trusted-firmware/drivers/st/bsec/bsec2.c 943095f905fcfc655c86f6aca5d3287192546feb - arm-trusted-firmware/drivers/st/spi/stm32_qspi.c f73a865d9abd49d6a37720d4000b86bc1f6b362c - arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c f71262877fdd2511c5cd086021c2af9d763f9ec1 - arm-trusted-firmware/drivers/st/crypto/stm32_hash.c 1c77b842fc094c883b8e6abc3522e2a5ed4ebb3d - arm-trusted-firmware/drivers/st/regulator/regulator_core.c f01b87c2b668e9cc15338565f21d115dbeaf62cc - arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c 27adf1000d6bd7ce04979d79256995a5fbb83b5f - arm-trusted-firmware/drivers/st/io/io_stm32image.c baededfb86b8f337d27173f84b9cc1bac0556f62 - arm-trusted-firmware/drivers/st/io/io_mmc.c 67125c1a18a170ed78552d01772ae577463e506a - arm-trusted-firmware/drivers/st/uart/stm32_uart.c ab1a40e17764664876964683ffac32bd86def125 - arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S 6b50346722811da8d96bca6f539f0d5e772d467e - arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c 76ef733f3d1d7b8a934c301f2e05724663827f36 - arm-trusted-firmware/drivers/st/etzpc/etzpc.c d45d152334200ea2acdee930619eff5f1fbbfb5a - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c 9e30ea137b7c1d34dfae32a3c5180396f6fa8bb1 - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c f5e59973fc84a601316882610f6aa00a70ec8e1f - arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c 88fb79719982f0a2687d7f693109e940e3cdba9f - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c 5ed9e1be8f844737db535ecd2e049e7d820af601 - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c 4a37a23560ebb26a66cba83a6a77aafee65a783a - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c 5324162d65037588a526042c0e40fab08cab0e73 - arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c 07bb0b5fe46d4ebca6c6e1feee9d8a9e7d83d6a5 - arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c def00bc3c52b54611ea6f11a6f5206cf0b3cc08a - arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c 9d7512560e4e1f8767fd18a115db9ee7ff100448 - arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c 1c35b7e5adf1b63d6732729e7c2113d1ea1a74fe - arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c 28b6eb0d5d5856997722ea707dd42c5ad7448dd1 - arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h 47db01b738865c987fa5dbb3656b6b1dab2df5d7 - arm-trusted-firmware/drivers/arm/gic/common/gic_common.c 0325f0421798955c9df7f963bd6f917152f3f9fc - arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c 20000ccb435ae8423c5a2294ecb47fd7961e90f2 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c ff4e151fab3e5a027139f8ccb78ada694380998a - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c 8f83171e122be92a8d5e4b0c5ecb35e4918ead83 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h 0cdfd59744b1db36c123258d6ed80a21b369e0cc - arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c 209b5b0ef79ee3104941281500febec4c3fa7e19 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h 51bb1f43fbcc00eb3e6ca46f5ac069a6a4af19db - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h 702d95a03697ab01bc50559d686681042cec6d16 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c 457472881d1edadb4da2a64ec3252636e576b054 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c e1cdb7a1b79c3634ed881efd97a423fca6741350 - arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c 1b9888584629f7d2bc9379be5294ff21dd7cf240 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c d424887230b1ad1f25384d0cc4cdf433911a1004 - arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c ba14a8e6c0af402979f522f4672707b451266d44 - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c d830753dc30671474545841791bb3ec230bcb2bf - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c 73bb04bd3b4d9fbaec23c129c93b2e89e276c7d5 - arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c 4d212a96f8ab9a54d15002b53f16df7bcd046e6c - arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c 79f4ef16ca7e0a07b86de03a9a04dcb9c6c3673d - arm-trusted-firmware/drivers/arm/ccn/ccn_private.h 9cb6b217ac9499219fd1bb05530709e1ed53c3ff - arm-trusted-firmware/drivers/arm/ccn/ccn.c 960e4d083c1d4f31df54f443dbe23554889af0de - arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c 7aaa9f31ec7c9d36e48fb2d95a6b3895cbef43ae - arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c cd0ed71ff125804ccf8f2d187005ce075bc2b8e6 - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c 80686a47331e2b609be783462ef53eb0ad73279e - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c 4faf8ddbac2e8bfc4ab77ba7365ff0c50187a2d4 - arm-trusted-firmware/drivers/arm/css/scp/css_sds.c 12e2ef4efff1bfd584d3424cee31bbcbaf0f9a1c - arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h 1530ff134d89ce18b2380b7d03828ec84c8eca25 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c e76c3b0b1252232e7854b8af9db8a9ce94192cd1 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c 50defd7dfa4e38cf230f830fa7e03358ccfcdbb0 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c b81d931e597cde97768e39fdad4325133c31b76d - arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c 13cf0f0a02adf3ae0f9e2bdbe493ba7c9b58ddf5 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c e4a68362e5109d4e46f1d720d9b02c8fb20a88c1 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h 9b45f1ebc9a189e59d1fdade91bde81f2ea110c0 - arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c 595853f3864138408a5e5b51034dd366cc9a3b7a - arm-trusted-firmware/drivers/arm/css/sds/sds.c 9fdd5749ba87bd5ded91306fd6826fa2cf990806 - arm-trusted-firmware/drivers/arm/css/sds/sds_private.h e609accbdf6501d2f83400b84b7690aaa2bca38a - arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S f55aeff6049754049ad1b23958094a7dd255200f - arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S 6dfee94cccd0efeaeda770f83e1d10227886d137 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c 4f259f1ca4437445346bfd338702c7c257c31470 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c fcdbc7d1ba6dd59840b82ac787ebf67cf36fe4eb - arm-trusted-firmware/drivers/arm/sp805/sp805.c c0c5af62081f2d6628a6de94cd6a9507723228e3 - arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S 91c557c46edc8be3bd2e4c2efcf9ef8693a9fc0e - arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S 3777989a45b625cf209fc89bcf8a91a468f52a3a - arm-trusted-firmware/drivers/arm/scu/scu.c 1c897f5bd19b9a4c18e905afda282375cbf4f5ba - arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c 64e24a32626429bd2dad6a02c91a123b79fe7528 - arm-trusted-firmware/drivers/arm/dcc/dcc_console.c 9697dd84615aa7c7da7ffe22eb0e3a38c6ace390 - arm-trusted-firmware/drivers/arm/sbsa/sbsa.c 668315548e4d6f930b744983a6542e01f81caae2 - arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c ed924dc3ed7f91ecff8a2e441fa5152d9fe2b9de - arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h 73c05b4fdb011d3783f2f3f3ed7285ca58a63cc9 - arm-trusted-firmware/drivers/arm/tzc/tzc400.c b2e58e1a761614ee8bb95e48797500fcd9f66c4c - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c 0e845129705069d3fce0df742ab8d56a7966edbc - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c d0a784c19a578becbc821a36080372d78af9b3b5 - arm-trusted-firmware/drivers/arm/tzc/tzc380.c 57712978c67a02cb381ba1e9203dc26e762d8b43 - arm-trusted-firmware/drivers/arm/dsu/ppu.c a9cab74a3aa9f59289ec4dac11558cb1e6e3c2a4 - arm-trusted-firmware/drivers/arm/cci/cci.c bf48b15b9f75300c1f11366746538bd62a99a5ef - arm-trusted-firmware/bl32/tsp/tsp.ld.S f2cd83bdbfed353fb47e384608fd41f7b78fc98c - arm-trusted-firmware/bl32/tsp/tsp_main.c 227ccd758b1cf98d27e14ac1ebd5e3b21275d6a1 - arm-trusted-firmware/bl32/tsp/tsp_interrupt.c f9227b30f6aa21bbf4a178697c37fa714ec54eb7 - arm-trusted-firmware/bl32/tsp/tsp_private.h 6727eccb78b649034342ffa087bb189e40734608 - arm-trusted-firmware/bl32/tsp/tsp_timer.c 8d77cc1453037a319f4a5da2e5b77b37bb406277 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S e94cc0b80bb21c55fc68026d8a981988414ab611 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S 18772624eeb332566bd8dfe2279187bec9b89fe0 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S 68e3f9565c5bf338271a1445ca22507fb2afc5af - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S 333a280c5264ca6c42b06d977d15e2fd4809f2d9 - arm-trusted-firmware/bl32/sp_min/sp_min_main.c abbd0cb6ee3ce9ca8584fa872468754316b868ce - arm-trusted-firmware/bl32/sp_min/sp_min_private.h 5ef0dab419f42df9935d7fbc4e30baa8ea83d75e - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S b224dca2e5ea95c46e1062767709b1bb1d7d766c - arm-trusted-firmware/bl32/sp_min/sp_min.ld.S c1854f51280eb002548e763a01a8af613c615ee2 - arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S 0cd1ab24947e0ea5ce307a171756d88683d36cde - arm-trusted-firmware/bl2u/bl2u_main.c 2d32dba27247198d6cd35d150dc8eeba3c8ed8ff - arm-trusted-firmware/bl2u/bl2u.ld.S 1df1aad13ba7e2ed5cb1ae4a6200d169a1715578 - arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S 738660771364acfab975427664536a581abb78df - arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S 4e66ff242f442cdfb5239bef53026c402990b912 - arm-trusted-firmware/docs/change-log.md d2e89e46ca5ae89064b0a9b0d7983272a60e60a6 - arm-trusted-firmware/docs/conf.py cdd7c87e02f5cae26200b35f5869f20aa1a526cc - arm-trusted-firmware/docs/Makefile 0b30444600f51212f5be53588f4f68cba0bf92fe - arm-trusted-firmware/docs/glossary.rst ea9ab85da5d526fc32f3436878dc80c33fbbe334 - arm-trusted-firmware/docs/index.rst 0677c6b28a895fccae194309f759b9f4e0f4c9f5 - arm-trusted-firmware/docs/requirements.in 0b02d28e0d9881fab1b08360d2d9bbef021685c0 - arm-trusted-firmware/docs/license.rst ff8ad4850057cbaba3caddae15b9429bb9c42b66 - arm-trusted-firmware/docs/perf/tsp.rst 3e1557ac89eff3ea7cb96e090dcc6cd147117008 - arm-trusted-firmware/docs/perf/psci-performance-juno.rst 840dcafe1996d0299a5922474d7980b6d2eb779c - arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst a19b41fb4dbff6144a8b5f04eb7c296b63c442d6 - arm-trusted-firmware/docs/perf/index.rst add0156b84b7d9f7760db313170bf81a672a66a6 - arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png 02a0166ec0c907a8725efa2ff467ea4d5984a35c - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png 80b81639bb1aa78723d3635f0359764c595e38c8 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.png 66f1f1fd09b5146cb2a5e1c538de29ea7f88ed7e - arm-trusted-firmware/docs/resources/diagrams/fwu_states.png d9a6dc06e1a28c0235940539e527ac285c179342 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png 7c4678ac4952c496df4536445b336d96139b0066 - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png 19e287ff6d7c25917fd56356da40bee3e5ef120e - arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png 04a65e98eceabb17ea534a6dea187021477a1fb2 - arm-trusted-firmware/docs/resources/diagrams/int_handling.dia d10eb3ff6f8cf071330205ec0d59126d79f939f4 - arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png 4d2668ab5814fb9b799f65b69b427db29952658b - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png 961fd0fc52b27792b27c6cc8b9f210be8959e285 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png a0ca882a9a47bf5642759780b006f69f3c667fff - arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png ada526023821d5e57e3e1aa979b38d2c8708227e - arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png 10d343a1dfde1e76a19cfc7a0f8a9ca28710ee17 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png 4ab0332c836fdf5e5596c2b7ecc6ea4bccb62b8c - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png 165d02fd6baf4c31ce0c1b034477b6596c724abe - arm-trusted-firmware/docs/resources/diagrams/Makefile 64d840596ae8dbdfb803bfdd471e3d4e7955ca82 - arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png 84f99bb590f5c8748bc6e47f3e7bd4bf5890447d - arm-trusted-firmware/docs/resources/diagrams/xlat_align.png 77da82b847d9c9a0cecaa2e43e40dac166a66399 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png aacd72a3c084647a884d67147510a1b0c26d8359 - arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia 9bd9241452f165fcc7e5018bf8a24204767fa036 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png c279d33545695cac4327bf14a8d84b4237dc8387 - arm-trusted-firmware/docs/resources/diagrams/MMU-600.png 08ebe00cb9823cd55d80c05b4aaaa64c103093ce - arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia 40ffa83fe202970879802b809b75c10ed360c7d4 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png 40dca2e6d5cf7cdc88398bf5e2df39f3fce31bab - arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png 2417a250f3f2552f5e881830e947024a92e55adf - arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png 763017cfa85171acb7422b0f8ef1c40ba69443a3 - arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png 2e886fd02f6b39a545824f0819608260e0671c14 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png d2522911e613a4005eb1e10931779a1bb350a363 - arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png 17e11d01f23f073cec01fb44acaa3c976495e982 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png d5775195107610d6a67d5d7f8af6590e4e53e570 - arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png a68fd21bb442987ce7a67e0eb08d150b81bfe901 - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png b42c9e2672802e26c9137df29eff6a1c68652ea6 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png c05984305daded35b5f3a14ea3c5ac88319f4292 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia 1586bdc989b8698512851e436d39fed8ad375030 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia a6a4256584fddbb776f1e274748edeff4289cf4a - arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png ad73cbcd10b1b5e45ca3a01df6c435b345686322 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg 2c5f1b895b01d75ebe2fd874d61f728fe18fca4a - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml 4eb0b99548ee5cdbff9d0e01b3455c7c1e1af275 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml a2eed4587b5987e97e3f8207a2c9783c5e322c90 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg cde708741ffdd39f92d8670aea4a93ef451cd611 - arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml 0cbedd3989e3d4fc11c3401d7b250d8b14411c50 - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml 9e7994a98a6d3531ff8f3c7e16b9e27ae0240805 - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml 2c516abafcee77f3889360526590d0764a35d61c - arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml 7ca50157b91a940fdcd61fed7da54e93501b2c3e - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml 89429fb35fc54ad81b4aab0c9d5860b228aab347 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml 0130e90e98cac66f9ac28a56d8fa17af801ead7a - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml 695a4bfc3f0c50586104d10e16a8527c37f3541f - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml e357fbb8d83445182b61abea380d1885e484c4cb - arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml 732ce8b12943c9ca218e89a1aa3eae1379952d12 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml 853a892ccba3dedfcb4491b7ad449b46d6a4d47c - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml 7eb6ecf49d5ec8a975cccdc3aeb0d994e07362a0 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml 1441246fa837376cb589e45510656ca210e18bb6 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst 266a8326bc618859a7a18572589b40f197ed1a82 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst 63e67342811855c2803be11bca43aa4c60543575 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst 5a8ee89be8b54261b0e207ca882fab66cb4db5b9 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst fab06483aeca0f68846039c9146a6d828ab12518 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst 1b8c8e49a1eac7ac65f01b730ef3d22dee6de50f - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst 48c2d42e738237365f9158ca022d56408ef538e9 - arm-trusted-firmware/docs/security_advisories/index.rst 939eb2b8d82c68d6c9a4e8c1271bd83151818553 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst b748a01e82c3ad35dacc68ae9295e4553d57beab - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst e03dee87868096ffa7982026e20837ddfc9a6aa3 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst 96e5d7607dc9d3c5db2cc3e15eb9b771a429b761 - arm-trusted-firmware/docs/getting_started/build-options.rst da2d29864297e0b06dc8f7ac1d17288a078ae5c6 - arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst 6914f4b323e042c91ae58018d9217b08f655997d - arm-trusted-firmware/docs/getting_started/image-terminology.rst 6cc854b04d58541fc0e9043f88c7ece6a68c925d - arm-trusted-firmware/docs/getting_started/tools-build.rst 34beaf5d32a409eabaabd8b492f4ffb95daf2b70 - arm-trusted-firmware/docs/getting_started/index.rst 32237d53d0db21dee6eedd6143e60e46dec6d79e - arm-trusted-firmware/docs/getting_started/docs-build.rst 6ea980565b00e400d102f63072c110d6471b0818 - arm-trusted-firmware/docs/getting_started/initial-build.rst 97122206fcc716ab5581232da8de4685ba9e7df9 - arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst 9c961219684a654a9367ffdf4856dd21080cfc97 - arm-trusted-firmware/docs/getting_started/porting-guide.rst e95ba49d1a46a2db605b69f5425a6bc6069d9a41 - arm-trusted-firmware/docs/getting_started/prerequisites.rst 3fe053ce17752ae01f7d815a5df51f4887d2749f - arm-trusted-firmware/docs/_static/css/custom.css a3f0b5a39e2120fdbcad8de599b7c1a18345cfcc - arm-trusted-firmware/docs/design/alt-boot-flows.rst f880dd25cbf380065e9d345752376e40bc756664 - arm-trusted-firmware/docs/design/interrupt-framework-design.rst 9937a50f3bac7c0a981d42b12b0308be265050ba - arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst b5b729e65177f7baad24fd693c9b5a9993c50776 - arm-trusted-firmware/docs/design/firmware-design.rst ff4749d1e71cf1665bbc340e11787c971b395fbc - arm-trusted-firmware/docs/design/trusted-board-boot-build.rst af63c8f1c70b2c589dba26872e3ba5244236722f - arm-trusted-firmware/docs/design/reset-design.rst d789165adbc9c0e0ace7d7326f1cf7512fa63c88 - arm-trusted-firmware/docs/design/index.rst 6e60dedac282498dc34de3ebcecd6f0119e7348d - arm-trusted-firmware/docs/design/trusted-board-boot.rst ffda28459589a0ec22cacc12c5b92103ed64fbbc - arm-trusted-firmware/docs/design/auth-framework.rst b15afee5cbc5225a2ef2f709e9761fa2cd73d65e - arm-trusted-firmware/docs/design/psci-pd-tree.rst 11abe92eab64d997319223639ad2693b7f7c8535 - arm-trusted-firmware/docs/components/arm-sip-service.rst 75d075c879040f97f06e2a7b3b6bd34df86b48ac - arm-trusted-firmware/docs/components/activity-monitors.rst 3018701b7ef2e5eca172d3608726f506c4b22909 - arm-trusted-firmware/docs/components/debugfs-design.rst a4af3a93464aafab3bb5428082fa9dec58ed73b5 - arm-trusted-firmware/docs/components/ras.rst 72ac59432a0693df36a09334d6f57a6f9491189f - arm-trusted-firmware/docs/components/granule-protection-tables-design.rst ec0ac249385853eeb84cc0e4151f612b9d23cadf - arm-trusted-firmware/docs/components/ffa-manifest-binding.rst 8a1dffa8292f295ef5014ac04a74011b4aeea398 - arm-trusted-firmware/docs/components/exception-handling.rst d2201aab60e237cccd20ad636c8ad4224d7f0571 - arm-trusted-firmware/docs/components/romlib-design.rst 9db58fa601138b8e16c395f19913a1f106be570c - arm-trusted-firmware/docs/components/realm-management-extension.rst 963a2ee9d3bf60564d3ab545fed12694fec33fff - arm-trusted-firmware/docs/components/cot-binding.rst 193002dc879b3270f34cff05228d20d88d099fce - arm-trusted-firmware/docs/components/index.rst b8d62ed8d8e52992c481b3f032a11c132ddc32ca - arm-trusted-firmware/docs/components/mpmm.rst 164b5be074959cef709b8de7cd264d2b720e0386 - arm-trusted-firmware/docs/components/secure-partition-manager.rst 5064b1a7d15e72b127c8fbacf8f11b087446958a - arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst aca3aea7df00338e307623d4735b027b76f48985 - arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst ca2c86b55376dc70e6bbbb76058286ac38e35ba0 - arm-trusted-firmware/docs/components/sdei.rst 602d20bd46337be44a23550620a7a1f748130fb9 - arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst e267bb8c86ec7cc1d683daacbb53bd387881178d - arm-trusted-firmware/docs/components/firmware-update.rst 1d91355dae9ce87dd6d332bfe96019333abb6da0 - arm-trusted-firmware/docs/components/fconf/fconf_properties.rst d795da44f403a2a0bc4010ba95915fcabbef3c31 - arm-trusted-firmware/docs/components/fconf/amu-bindings.rst 10529cbd50c1b2a10d7bf7669a515a30f564db2c - arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst c3411adb08049c0735f5b9be29bc976bbcde69c8 - arm-trusted-firmware/docs/components/fconf/index.rst e289a8345f0c801d0e1d079b94c6752a31a28396 - arm-trusted-firmware/docs/components/measured_boot/event_log.rst f39c4c5b080cb5537f0260d9f3e477e02aa63bfa - arm-trusted-firmware/docs/components/measured_boot/index.rst 68d992f28a446b0ffe6adad209b6189f9f0dd6a9 - arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst e583074d9e81fffee8804f560b145fa486f1aba8 - arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst ee5cface9280894c7d9860dccb78eda3849c9cab - arm-trusted-firmware/docs/components/spd/index.rst 5d7421fde74010efb451e6e515079f37ec3227e2 - arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst 53f0692ccc04d5d659e88ac1dc1080af6dcda94d - arm-trusted-firmware/docs/plat/qti.rst f8d9d0b4336229fecb1a12937b0f1a9b6060aa0b - arm-trusted-firmware/docs/plat/xilinx-versal.rst 2a492964dd82db785e381f828fae2b2a729f6749 - arm-trusted-firmware/docs/plat/meson-gxbb.rst 1fb07134c685f21246757d77653a8c6bb12d949c - arm-trusted-firmware/docs/plat/socionext-uniphier.rst 8b88e9d6cfe72a03efd7e226122d5cd33334fe66 - arm-trusted-firmware/docs/plat/ti-k3.rst 2ed0c805bd3cba59619101f0918aeac59d4e6fd3 - arm-trusted-firmware/docs/plat/rcar-gen3.rst b54be1ac4f13d0a724629f301e245bbcc4379d44 - arm-trusted-firmware/docs/plat/nvidia-tegra.rst a970558632482b93ee96aba756982061d20ea4e8 - arm-trusted-firmware/docs/plat/intel-agilex.rst 12b7c2db7722b49705438fabf8b96c0943d163bd - arm-trusted-firmware/docs/plat/meson-g12a.rst 15d03048959cdd154b540a3b91f7aa6b48f7a7ef - arm-trusted-firmware/docs/plat/allwinner.rst ddffb1cc078fd2d3c58ed8cde2b32388ccd532c9 - arm-trusted-firmware/docs/plat/meson-gxl.rst a6c4746123e21eba44253912da4e92f0fd31a6cc - arm-trusted-firmware/docs/plat/rz-g2.rst 0db6c8e13659db1d29238baa7d8a870a4e821546 - arm-trusted-firmware/docs/plat/stm32mp1.rst a928b648d0677930c926401b40e335f052e97be5 - arm-trusted-firmware/docs/plat/mt8195.rst 9085fb1504d30c5d3e75304a86dfa8a1225967b3 - arm-trusted-firmware/docs/plat/qemu.rst d714f1279de4aa5eb4519255578a2718fc8e3a1e - arm-trusted-firmware/docs/plat/imx8m.rst 4905e051c0a996867dcc2389b8bd5430b0741699 - arm-trusted-firmware/docs/plat/imx8.rst 9e85f6fbc5306c4b0604e98de5fcbddb385c4ce1 - arm-trusted-firmware/docs/plat/mt8192.rst df909307e45e07ec88f455e8ef27abedd18e3592 - arm-trusted-firmware/docs/plat/rockchip.rst f2bbe77ac618ba9be663de2bba3cee62eaf17f60 - arm-trusted-firmware/docs/plat/mt8186.rst a06622efc4dca7ce03e6ea2e305e8a0b8d422bef - arm-trusted-firmware/docs/plat/deprecated.rst 45f03fd73a50f2fe124a2bd1d70fb40243ba0e82 - arm-trusted-firmware/docs/plat/warp7.rst 028d90ceedfb507b0ee1532f28cb8842f1f5b19f - arm-trusted-firmware/docs/plat/index.rst 84cb8ce1de6f042d0693d8a1a4bb2265ef8a7ed0 - arm-trusted-firmware/docs/plat/meson-axg.rst 080191f60f9e441f7527257b977a2c8f6d8c5533 - arm-trusted-firmware/docs/plat/poplar.rst 9bfeb07c04a47aacac6ae649f75799c894e74067 - arm-trusted-firmware/docs/plat/mt8183.rst 05664e895ce6375be6ad98e9576013d1209cb012 - arm-trusted-firmware/docs/plat/hikey.rst a80443b8a04209092463f6005843be7eb0dc832d - arm-trusted-firmware/docs/plat/rpi3.rst 556090a5f980031e56bccbb5c6d93f41384aad09 - arm-trusted-firmware/docs/plat/intel-stratix10.rst d0ad3f088b7307bd002023c2fcda2de07a36f40f - arm-trusted-firmware/docs/plat/synquacer.rst 3cefd2238957aeadfec4d578846bb38b56ca5c26 - arm-trusted-firmware/docs/plat/hikey960.rst ed1a65471d042b402028616f2e38ed56b42dc891 - arm-trusted-firmware/docs/plat/qti-msm8916.rst 25ec8ee5167ea3d60afe26566de20782ee6aa44c - arm-trusted-firmware/docs/plat/qemu-sbsa.rst 4b9ecd5b7418c0a333435d823205f0569bf5e668 - arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst 01b97fb19ab7a8e8baa5a1a96d35f2cb5dc0a05c - arm-trusted-firmware/docs/plat/rpi4.rst de25efbc7acce27ba0385c2c51a59fbc0f7f7124 - arm-trusted-firmware/docs/plat/brcm-stingray.rst ed3ec7c6e5baceda79c359ce661ac80dbf660d61 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst 231fc05a0b2de9270bfe513d92b37243b1cc9601 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst 5d7bd6f5908ace2c36015e0535f2deacac9a2956 - arm-trusted-firmware/docs/plat/nxp/index.rst 7b3072f9759a1fe276a22dcb70d936006608d299 - arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst e5e2720a56dd4b68568aae99f664a7478121e8cf - arm-trusted-firmware/docs/plat/marvell/index.rst 5315af3195d5a7c46ec750dccbf4f684c0df4e81 - arm-trusted-firmware/docs/plat/marvell/armada/porting.rst c143e2ca6a4cf9f94d9017f083b9d5dac2a5167d - arm-trusted-firmware/docs/plat/marvell/armada/build.rst 3b71f880342eddec219418df7f6e6034cce505b5 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst 30afe5cabdcd30362317ee05e9fc4203912e1e30 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst 4496a36f12db50b8075c93550ad2b7a23c24e490 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst 0af03a25bc9938840be478afe1f0c3375e852dc7 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst bcb055e4f5b81eda0adb88f8b79f78b72b1332b9 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst aa2be0dce19adf3702025c84d42587a8d1febeb0 - arm-trusted-firmware/docs/plat/arm/index.rst 3abb2d351f8ba63685ce15c862339db9da2d3ce2 - arm-trusted-firmware/docs/plat/arm/arm-build-options.rst 839b91011a0ebdde7ac9b056ab0a3b087ef11114 - arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst 09ec3654ccddcc7942d92d28d1cf1ccc973ba893 - arm-trusted-firmware/docs/plat/arm/tc/index.rst e2a46aa8e82f95847753a68a0be016142edd63d4 - arm-trusted-firmware/docs/plat/arm/juno/index.rst a845be9736fc1cfcd3cefda5b6a0bde2419f9bc0 - arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst dc03d6c732257847d92bd05db0e2b93163870fd7 - arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst b2ee822aa3f35f04c12fdc9ab44cd66e70b96f38 - arm-trusted-firmware/docs/plat/arm/fvp/index.rst 46e0aef67518d4e85f7b3f9dc17b5e3a36fc9640 - arm-trusted-firmware/docs/plat/arm/morello/index.rst b10bad88c8647f9ecfe8b3bad163830573cfbdc0 - arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst 5d47110e0bea04401c509ac372927b21ea650e12 - arm-trusted-firmware/docs/process/contributing.rst bfb4f8dc9ec952cc5582f0a704de50db89072cf8 - arm-trusted-firmware/docs/process/code-review-guidelines.rst 3f4a6d7ff70fb05d5b604632a17c4f84f8c5ab3a - arm-trusted-firmware/docs/process/faq.rst 2e72ba549eae51afb536d262d8daa4d81aa9a18a - arm-trusted-firmware/docs/process/coding-guidelines.rst b69510d5984b9f3bc4ecb789acab9ba5308eb6b6 - arm-trusted-firmware/docs/process/index.rst 9fcde12a65498faac5c43825aec87d7fd0f2ecb2 - arm-trusted-firmware/docs/process/security-hardening.rst 642d7817092741083f4726c2c178f0c3d0e9bba2 - arm-trusted-firmware/docs/process/security.rst 3a4d85651ee64cc9eeb924af2325478bcf1f71e2 - arm-trusted-firmware/docs/process/coding-style.rst 0f5d2a3f45d1b5b5a634ea677c87983ab7a5e769 - arm-trusted-firmware/docs/process/platform-compatibility-policy.rst 947dfc47181528100c27204431008074dead97a4 - arm-trusted-firmware/docs/process/commit-style.rst 6fd5a13007e2c86b56b83ed08af9e4343890c44d - arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst 125013620e921736b4b48b912f62657eb06ae363 - arm-trusted-firmware/docs/threat_model/threat_model_spm.rst 6370cee0ae902a8040401edd8f2ce7aa0d67a170 - arm-trusted-firmware/docs/threat_model/threat_model.rst c39c2e4ba3f12fbad74aac5304a27e5b3c3fc272 - arm-trusted-firmware/docs/threat_model/index.rst 3c9105f13eb03be1b0c0035eb88daafdd219f4a1 - arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst b5585102476dfaccde6a472ab5485236468a4d14 - arm-trusted-firmware/docs/design_documents/cmake_framework.rst 1cf19041279928d9215bdd8c91a1559b37e426b4 - arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst 458dad419f00db20225a3987ea193db385391688 - arm-trusted-firmware/docs/design_documents/index.rst 3d4d6eeef77d8e11c9b5da38bf3008531d4cdff8 - arm-trusted-firmware/docs/about/acknowledgements.rst 4717f5ce955ade54d71c40eb4edc26c2ae63540a - arm-trusted-firmware/docs/about/release-information.rst d0aa75e869685b4dadea831588e9175113411e43 - arm-trusted-firmware/docs/about/features.rst bd485ae1fd78b7134ac1b633b73d320c4de37262 - arm-trusted-firmware/docs/about/index.rst b797ee1a8501bb526a8f4e22f7bf644d83ffc96d - arm-trusted-firmware/docs/about/maintainers.rst 15453cf4faa84e1c067c1b9125f90e625547f47d - arm-trusted-firmware/docs/about/contact.rst d04e79c7e2d1ff0546074efcfda2290f20c1c923 - arm-trusted-firmware/.husky/commit-msg fd32ceb86780ba4682d238401c5bdc6c51f6652f - arm-trusted-firmware/.husky/prepare-commit-msg.cz edf09f8f672ed108a22d57c3be9c64c542957347 - arm-trusted-firmware/.husky/commit-msg.commitlint 201f68ff32e77e6400dc5624a726bb46fafe1ac3 - arm-trusted-firmware/.husky/commit-msg.gerrit 11dae66f5031e4fc368d8b20d11916dbcc90b1c0 - arm-trusted-firmware/.husky/prepare-commit-msg 3a094362be710094e9435bc1e4d7eebfa468338d - arm-trusted-firmware/bl2/bl2_el3.ld.S 88bbfcb3f9b827bdab7f16cdfe892b2aa1470576 - arm-trusted-firmware/bl2/bl2_image_load_v2.c 0b07a71ab893d39e7884f11f46b95245ab0cf303 - arm-trusted-firmware/bl2/bl2.ld.S 991c05cee7a30247e2edcade94405aef95480121 - arm-trusted-firmware/bl2/bl2_private.h d8756b1a7295709e6757c7dbfc53741267823e2a - arm-trusted-firmware/bl2/bl2_main.c 62ef4221f56feaf0907dbe17cad47a9bab86bf03 - arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S c426fa02b617581d2495667828e9430110cf713a - arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S 247751d71fb2863f439cc217ac18c219dbf15453 - arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S 776c1699268eee43ba9230cb7e785e298e56a233 - arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c a34048b4cc67bca14b7594e2c1a53b4c0376d779 - arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S 777576955f2ae3959035c33791a33835fe6578f4 - arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S e514ace46685e16066700af9ec41ffbfa825b369 - arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S e7ec4f132c5a2ca9bb5f999f47079e4d473e77d9 - arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S f64693060b1ef904b4abfc04b8480a0f458494c5 - arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S 2534665e628b7612c3896fed4e659f3351601296 - arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c aac463ba1d35408d94f960ade6d2db95d68455ab - arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S b296aa0c1c6575bc1a961fcbf21420aa5e6c0d3b - arm-trusted-firmware/include/bl31/bl31.h 89971e627f1aaad3902b29c72eef83520766be40 - arm-trusted-firmware/include/bl31/ea_handle.h 40a0dcdf3add2805bf312c4548d2ee377fc8e4db - arm-trusted-firmware/include/bl31/ehf.h 6d533c4b5b87dfa62fc19f93ea9a2a7d91fa7e0a - arm-trusted-firmware/include/bl31/interrupt_mgmt.h f237c837e7f3ca6eb78a837961cc378136eb56a4 - arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h 5c7d53dffc9e4dbe1b29a7a3f2c66a36954dd32d - arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h 4b89cad3c01b7767a5a3a13de49705b2cb3e7f9e - arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h e0d1075d19bd35b9bf189dad00ef6b45991c1bf0 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h fd1e043f322c708de5aa529250ef0ca7430cc508 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h bd297c8c069baf4894e271462ecd0387ca142d2b - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h f8dfb28848429d1ddd93107a95f47d8c6701e359 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h 080c331a370bfcf9f9ce11ccdc89838ea7fd401c - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h f28db646c8bdd11bb9593e0d241d924482a7d3ad - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h b7307a0a106f93b2429fa105547d42bc65f8afc2 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h 0ca59c4b41f2264bcc0d4b45550b8a587211aece - arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h c5098c5b107f74cd689ca039a39721bc1ecb7523 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h 7efe8c0a3fbb4e9b29850fac16b475c45925c6e3 - arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h 56af3734637f9dcf2f75c88aad9614e515be1570 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h 3a4737826d5e90e262be765553886dc9b2cad966 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h eda413e9067c54fd7cb0718642eb3cb770fb5c79 - arm-trusted-firmware/include/services/ffa_svc.h 53e733abf11ec08954e5e64474973896323d428b - arm-trusted-firmware/include/services/arm_arch_svc.h bd59ae9370224873185cfa4dfc1459db223f86d3 - arm-trusted-firmware/include/services/spm_core_manifest.h d02d80eef605a92cc293597811496a9801e4761b - arm-trusted-firmware/include/services/rmmd_svc.h 583482e243ae52386041c084650c8579a1f113ab - arm-trusted-firmware/include/services/std_svc.h 3b7a4c6d6c8ce3c42694e589dd7dd5d4ed7a4ced - arm-trusted-firmware/include/services/spm_mm_svc.h 18b02402ab43e28399a4a595544148f960b65c9c - arm-trusted-firmware/include/services/sdei.h 30872b92c4859ac9f8e3a28f996c947b74edbb61 - arm-trusted-firmware/include/services/spmd_svc.h f9e8e6beb1285dc1b188488dc9a217ba805b04e1 - arm-trusted-firmware/include/services/pci_svc.h 6b3525de0de5c707191677733b6c49dba80eed96 - arm-trusted-firmware/include/services/sdei_flags.h d3bd4cf8e1c91ab4b8019456b7e19c3fd4675567 - arm-trusted-firmware/include/services/spm_mm_partition.h 5d3f25945b7e037c8732ee7c4702366e6ceef5a0 - arm-trusted-firmware/include/services/trng_svc.h 1f0f251429978e8646a05d91d3f3263364aac596 - arm-trusted-firmware/include/services/trp/platform_trp.h 718add17082d7b0f4631c4aa87879e2dbc634426 - arm-trusted-firmware/include/common/fdt_wrappers.h b46a10bce55c312c93a16f506296f5642158a823 - arm-trusted-firmware/include/common/asm_macros_common.S dc31b12d8e0fe348d049aab169721695d6414bc2 - arm-trusted-firmware/include/common/bl_common.h 835fd8c82abcfae1bf3c5dceb1123a8b2bfd587d - arm-trusted-firmware/include/common/ep_info.h 1fb3546ddcbbdb34f1bd8c5532fde531ed03e4fd - arm-trusted-firmware/include/common/runtime_svc.h 1d8edfcfadd6f5b8724ad6ef3530f09bac04d2b9 - arm-trusted-firmware/include/common/fdt_fixup.h 561b168245611d5de641a636b5d632f02dcab868 - arm-trusted-firmware/include/common/debug.h 816190a2de110539cf90ed91f279563c0bca9a18 - arm-trusted-firmware/include/common/uuid.h 9398e9281edb3916d9f8b25e4ac909538f93d5da - arm-trusted-firmware/include/common/interrupt_props.h b0aadb059bd035c38b54ce8f2f7690b49b417e5a - arm-trusted-firmware/include/common/param_header.h 0adc1932137e9f09ebf8948f60d0bb0258ad0249 - arm-trusted-firmware/include/common/tf_crc32.h cbf9eec4b4cde89881d2efe44be1dde85d9b6b0d - arm-trusted-firmware/include/common/bl_common.ld.h 9acd7a0a005acdb9eb6ee122677ee9528b36b6e0 - arm-trusted-firmware/include/common/nv_cntr_ids.h f3ec87cdd303cc80ab1975ee4c970c1d72f2a1d9 - arm-trusted-firmware/include/common/desc_image_load.h 3061ebcc5cc39e9b66461188d5eccd5bef4173d0 - arm-trusted-firmware/include/common/image_decompress.h 5afd89832d7eb27979b6864884c4c5564a60279d - arm-trusted-firmware/include/common/romlib.h 22b063584c188624815fe5a57f199b9bde282c6a - arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h b1bbf25afc02647d5cf3c2de70985599ed6bf6ea - arm-trusted-firmware/include/common/tbbr/cot_def.h 1d2a96df860280e160ab95e4e51e622a5f546aba - arm-trusted-firmware/include/arch/aarch64/arch_features.h 87e9fceb27f38ccf307b534c37594e96103b391f - arm-trusted-firmware/include/arch/aarch64/arch.h 40e8dcbc93cae746d0a5db7109f8c2d55204cc36 - arm-trusted-firmware/include/arch/aarch64/asm_macros.S 04b3308044a6768acf0bad187fc2b69cb69a1fe4 - arm-trusted-firmware/include/arch/aarch64/assert_macros.S ad144423428ec92ff7791f7e65475d8179b74ef7 - arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S d35ee46e0adae54b398a7fca1dfb048e883b5ad1 - arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S ed984eb0f0ed8079b711d378fe82a35a98c45803 - arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h 3b667906d524c05d363bb8341f5241bbe7d80fe4 - arm-trusted-firmware/include/arch/aarch64/arch_helpers.h 82b34ecc6637bf3745fec6a4d1cbc29e06e8e19e - arm-trusted-firmware/include/arch/aarch64/console_macros.S 6a8e3ed67bce468bf878dee9e257722a13c705de - arm-trusted-firmware/include/arch/aarch32/arch_features.h 1ac6bbd72fd5efcdea46d665f3b42539e55d19af - arm-trusted-firmware/include/arch/aarch32/smccc_macros.S e2b5aa5f3ed136a6b09905c047bcd4bba696b753 - arm-trusted-firmware/include/arch/aarch32/arch.h c2be1c93cd54c4e39aaf2aaa3a0efde1a237ae5d - arm-trusted-firmware/include/arch/aarch32/asm_macros.S 7473145f94c25355b413a071f083825a5bbf2ce8 - arm-trusted-firmware/include/arch/aarch32/assert_macros.S 19edcf9b1fb1a08230c93e3bfa026e7b33cd3ac9 - arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S 0e8c93e8e2069b7b80576b88757ad99a54dabc15 - arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h 68d3700bd1027d9b9ce6280954972329e2653b9e - arm-trusted-firmware/include/arch/aarch32/arch_helpers.h 707cddbbe6226e2efc883af7013f08afced5a708 - arm-trusted-firmware/include/arch/aarch32/console_macros.S 2953c9cd650429f472333ef0f7cb9ab6c69488c0 - arm-trusted-firmware/include/bl1/bl1.h f3d565fadbf6176b3034b8359d22fa8c03772f95 - arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h c8f57a02330fc21d063cbfa19b558cbd20de2787 - arm-trusted-firmware/include/drivers/generic_delay_timer.h c6f581c377a1a1670d1dd54c360deded41593d6f - arm-trusted-firmware/include/drivers/delay_timer.h 3fdd5f2bbd8585722f7176499884e963fcc1806f - arm-trusted-firmware/include/drivers/console.h 3d13f3cbff61918c53bb0a76876155dc82337fe5 - arm-trusted-firmware/include/drivers/console_assertions.h e52b9017a122dbf25d5764491104335c6a166dd2 - arm-trusted-firmware/include/drivers/usb_device.h 8709de3c5655138d78511772539fb29a8b660364 - arm-trusted-firmware/include/drivers/scmi-msg.h 32b681b12e18f054ea32d70a554e9c07ff59e4f5 - arm-trusted-firmware/include/drivers/spi_nor.h d73de0ba3c3a5f28ea6d778b2dcb3ccc7d76c74e - arm-trusted-firmware/include/drivers/mmc.h 1e85ce64c0bc0c37f1c87dab8859540aadd4d842 - arm-trusted-firmware/include/drivers/raw_nand.h 061a6a5d58a19fa40602dcb1c9d1042a206ad73e - arm-trusted-firmware/include/drivers/spi_mem.h 58d9040bd23a07f657047c01fbc92a62b9b04d45 - arm-trusted-firmware/include/drivers/clk.h 42c0f53bb57374cb007e6d5c3d4d536db4069f15 - arm-trusted-firmware/include/drivers/nand.h b11f7ad45072a13e91bd01040adca94742f7cff1 - arm-trusted-firmware/include/drivers/gpio.h beb3e629b953dd33bc44df27d3f0b251af4a75e5 - arm-trusted-firmware/include/drivers/scmi.h 9148c938d74351967390c1286566f167d1915b59 - arm-trusted-firmware/include/drivers/ufs.h 80ffbe42c480534b02989a02a37fe24a316746dc - arm-trusted-firmware/include/drivers/spi_nand.h bb163896fcf9655f45d24b8676ea0a79a6c28272 - arm-trusted-firmware/include/drivers/dw_ufs.h 41a9e785cff8ee17c58544900ad2cf351862fb31 - arm-trusted-firmware/include/drivers/cadence/cdns_uart.h ccb0701fec1000c00375edbf0318bdce6617b109 - arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h 3e33fa498602a762c87ce6d18b27e00fd4d9e153 - arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h 141c6ec9750c86044338eb19ee622331b9a6c0d8 - arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h aabedc9062342279b677c72861038190cfa65939 - arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h 7989591e2a2162069486ebab7e2728208c51b5c2 - arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h 69289264b7a28a5ce23aa04ce828d8b4af255860 - arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h ce837ddd809c0d8f381cefc82d212e9a1a20209b - arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h eb200bcc06472d689f3a7419f0710c4c3d8ce0c5 - arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h 460f93da77ff4c52f61d06eca41dc83c56a92b6d - arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h 66189a3d70ccfb57441e34458abfc9cd72c29d19 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h fc12ffe1d77603728f2c875a296218ae6cddb095 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h 91adf35b394ad394248624343b9c5b19fa0c2b09 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h bf836adf23266f3749b5e68af59a31d0ac0ea00a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h 57d421cf90453e8aa05285508bc43ed0e325a7a7 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h 2c95c38a7f65a3ef7eb3992c7136879ef75e4c7a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h 8308e3c4607508799254cc82d52ec5d4aba905e2 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h 2388bdc4442c2695122e844d49738f95b18a84cf - arm-trusted-firmware/include/drivers/nxp/csu/csu.h 46896393ac73e49d174031ad9db2b897a5a53cd5 - arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h 95b4d87dfcfc29bdf2b6cd0bbb06749112243507 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h 060901911b3564bae52c8476be0a91ea019b2283 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h 99694a5f2e9c541d163aa4fc3bae8f07cdd32b4c - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h e81281948e932f6635309e0cc817672144dd5cc1 - arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h 3d4947f956585eb9cfe3b8245ad4c1749cdc72b1 - arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h 7f0601b767be7522d2b3b053924b860224900737 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h cd9ce08e3ca357e9ac083fd384e2ffd154288032 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h 4453a2af06ed170ae6c69f42b415c69314fd3d9b - arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h 225ffbb6a71c970da33f40390a7828768770c824 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h b0e9643a90314ef89452944214806403f53b7b54 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h 4229b536f33d8f4775076953d8c91ea47ad378a5 - arm-trusted-firmware/include/drivers/nxp/console/plat_console.h 3b20fa259fde3f160db7996e9571edfc5ab34bc5 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h 90e8213c057c2449b5ba645b49e85458c0dc2e43 - arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h a38ba636dc7402ba5f0f12fac9db9813190a8c39 - arm-trusted-firmware/include/drivers/nxp/ddr/regs.h 2b66abb34254db06ee8c88f5e0596c908b2d2026 - arm-trusted-firmware/include/drivers/nxp/ddr/utility.h d0fc8c7cc714365c4b36dc3b12083432b0173dd3 - arm-trusted-firmware/include/drivers/nxp/ddr/immap.h 190e1845f17fd2f9c9e7fdcb31f62f22735c2401 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h f76687e9c42877c6684b9f0f42809be11e898f2e - arm-trusted-firmware/include/drivers/nxp/ddr/opts.h d8d9fce57d178fdfd41f5be63879bfa85d2e2e15 - arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h 07aabe0c38fbe8ae82313542589e8b6013f0a704 - arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h 26748e486ff05a3ed33d842cba65e4fecc362aae - arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h 56618eda200d872addc06447897a8b7ec619ffb8 - arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h 3584254639e10b77ffd6ccf07f7a59923b337ffe - arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h b6baa4f2facaae8fcb1873db219796f86e62cbbf - arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h f75c54f08edcc8069804184e40a6d8a74d3d1b42 - arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h be8a6b00a6db26fef151d90020cd12c856e4cacd - arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h 490bae640af8d15a10cc4a530a23cd51226ca709 - arm-trusted-firmware/include/drivers/mentor/mi2cv.h 1fad8ad24347aab9e6da6d46f5cf581f938d2ab8 - arm-trusted-firmware/include/drivers/allwinner/axp.h 0601d762e1bfda8d93d085ea44202fdbff2d1ad9 - arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h 1c35b8d1dd99e2556585b97e6c5f472b95565fd0 - arm-trusted-firmware/include/drivers/amlogic/meson_console.h 598adf21c9089a664c913fb3faf852fa36dddef8 - arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h 04cc0e519d24a6729fbf6f89e981eaf992fe19d5 - arm-trusted-firmware/include/drivers/brcm/sf.h 2a62cccb75603f1abe573a211d9b149826e87356 - arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h 2dedb1c6a08bb98fab574fbb49becf23a0a40b3d - arm-trusted-firmware/include/drivers/brcm/dmu.h 3b8d411ed511e8d5f5cd285a04229eb0779c2609 - arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h 907603dcc9f90f3393201ab4a2a5c8ce32f61543 - arm-trusted-firmware/include/drivers/brcm/sotp.h 542f2f80df9c9b264f0bfc9387e38e99ad2a9e7b - arm-trusted-firmware/include/drivers/brcm/spi_flash.h 823fbabdd578bbfbf92d8a2d68e8d7d2c3f652cd - arm-trusted-firmware/include/drivers/brcm/spi.h f1e9babc3d5e854ba472c64f889f2fb01138cff0 - arm-trusted-firmware/include/drivers/brcm/chimp.h 67ec9883d9b0ac3959b68dcf32dbf8d8fbc84bc8 - arm-trusted-firmware/include/drivers/brcm/scp.h 8c4e00a589a41eac59a1e3f7743e362f874b80cd - arm-trusted-firmware/include/drivers/brcm/fru.h 5afc35a13cf962ad7cd0f15b0532bbe11c7ad17a - arm-trusted-firmware/include/drivers/brcm/ocotp.h 5632d0130d0787f77618a2ca64d09d7bc3d2433b - arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h 281ab6dc0343aa92cc689456d9b8b56e7e853961 - arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h 5e1781b653944c224e65bec032fae482c1925591 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h 5657b1337210a575a742026dfa31f3136b5bb625 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h d6123ce1d15ed92eb457d0e0d13d66841deb34ea - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h 40a4365490452d1db063c69f305c46be1d20e9f5 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h af14073522c90e3d69b0abc31fd3a2820dc54d47 - arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h c3be01e418a0c44f650529178aabc99c5fdbef33 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h eafab2881a9d078ab544df13644c4b47b0670003 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h 869edd881664c3e2332d5b2e6765e7dacbb0afb7 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h 38ad4c8652f178df916a5a1622fad23851187ba2 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h ba4c82c4f42cf7c6060c7266d23de675e741a191 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h 829056e15314b731c22b87d62a2c8606e72e1fb8 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h b5e8788fcbe8f7e5a29ea20b0496f5b331fe6b4b - arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h bf12d4c88947dab864a8f411bd8b3d752bcece3f - arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h ddd09be972db2607bb424326a6c8fbb441dbfec2 - arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h 95f57bdb58eaa0c98d1495b69af4481368294101 - arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h 89a898543325d24449f04f9b4f73ab80fe43615a - arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h bd8eab4d0a2394ab277d17b70d1de2839a83ce04 - arm-trusted-firmware/include/drivers/fwu/fwu.h 53d9f7bd2b149b510835abe889d7520b7f40b916 - arm-trusted-firmware/include/drivers/partition/gpt.h 526e7a59fda5b797d17357c6594325b695dae294 - arm-trusted-firmware/include/drivers/partition/partition.h bd4bb47e71397b065ce00f2af2e6c24b3a8e1d45 - arm-trusted-firmware/include/drivers/partition/efi.h 1c27aa6ecf64d9c63f2e200bb4b4f34c1493e6b4 - arm-trusted-firmware/include/drivers/partition/mbr.h e65ada86295c449ba40e5e0d4d1558b8c57e24c5 - arm-trusted-firmware/include/drivers/io/io_mtd.h 53a57c8d46bdf6e3119f7da34bfab0df1ea5be9c - arm-trusted-firmware/include/drivers/io/io_storage.h fe49b84f7431a3680d29420770e6c5a8e81abd5c - arm-trusted-firmware/include/drivers/io/io_encrypted.h 37187b6d387c4c5065ca5fcf7fb76e54527943c2 - arm-trusted-firmware/include/drivers/io/io_dummy.h 10532a6db736e62308718e7ed4602bcdad21e3e0 - arm-trusted-firmware/include/drivers/io/io_block.h d44cfbded1853f569ae63d99598504a959d6be61 - arm-trusted-firmware/include/drivers/io/io_fip.h ea2dcfb76c08ec6fec8d8a369642b152753b0780 - arm-trusted-firmware/include/drivers/io/io_driver.h 65ea10cb954a4eafbc5c1b0e1f4118cece4ff74b - arm-trusted-firmware/include/drivers/io/io_semihosting.h f255bd6542ce1b5d70e6f1e8d795bf29367099a7 - arm-trusted-firmware/include/drivers/io/io_memmap.h 04830d2bd9eaac4d5ab2cf414e66ae7439c3832d - arm-trusted-firmware/include/drivers/cfi/v2m_flash.h 2a6f91687b0799d7e9d7d79ea9480d7b0f57c185 - arm-trusted-firmware/include/drivers/auth/crypto_mod.h c7235a5c0dc2db938ba5586b4a94294d0c1cef98 - arm-trusted-firmware/include/drivers/auth/img_parser_mod.h 21f2b4221f273c0afed79420c75126131f6cbd5a - arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h 125b1a75a3651ff04f7dd19ba665ccb6846f3a0b - arm-trusted-firmware/include/drivers/auth/auth_common.h 487e2e7025ad4207cb2dc1e52045c91796c5f00d - arm-trusted-firmware/include/drivers/auth/auth_mod.h 317b0bab814dd8e2cce909a57a2c8be90b0f5273 - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h 8990234b68caadc3262242514364a5e4326b0c2f - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h 6092827f0eb5f3c784b6a1da04df8d26918b01c5 - arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h 8d5bb836b8836f486476f20753a83ca09d64567e - arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h a3de98e4cc085d3cf7d5d52931b5b3623d0a619f - arm-trusted-firmware/include/drivers/marvell/mci.h 2a16f04ed2b2358e61aa3683ec3d1f2b3960dd2b - arm-trusted-firmware/include/drivers/marvell/cache_llc.h 15475b1e40e5c5bddbfabed61f7f24162136b1f7 - arm-trusted-firmware/include/drivers/marvell/amb_adec.h 000c88b50b95ab8b54fed58ab9f840b9bb69e06c - arm-trusted-firmware/include/drivers/marvell/i2c.h 69f49992d9c55ee0e777a11643d0b52001cb7622 - arm-trusted-firmware/include/drivers/marvell/aro.h 9b00b75ebe2ac0600a4eb5f6e9b76c2c77e19a94 - arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h 7f1222ae6a5838bc830b1300ab199a3d42290790 - arm-trusted-firmware/include/drivers/marvell/addr_map.h 6fb4915c93922ffd80c2b7082f5219b13d64a4a9 - arm-trusted-firmware/include/drivers/marvell/iob.h 5c2e0ca868faae2060e6a9f3bf20896783564942 - arm-trusted-firmware/include/drivers/marvell/ccu.h 02710fe143b7937c1b4fad8c1e757146513ac135 - arm-trusted-firmware/include/drivers/marvell/io_win.h d7bc8fa93e6253a8b9ef6c39613ea88489703b1f - arm-trusted-firmware/include/drivers/marvell/gwin.h fd4a5e7af241c3b0572f5c9e81decf1868f17fb4 - arm-trusted-firmware/include/drivers/marvell/thermal.h 80057d817a90e75ad1e4eab0e4c81c6a62aa3911 - arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h 9fe146fde5aec71f5cc47d07590e1f76602bc9cc - arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h 1bd923068f35229b4648825afdbe2d5ee74ba4fe - arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h d9fee9976962b8d9daffbf4d4cb1e7400e14c745 - arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h 898f43097b2545ca29358b143d6e97761f1dbce4 - arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h d3887ee8e4681e5e21d22c78756f8bb537359ef0 - arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h 8865e3a5b086a9f57937f94373c1488796422a75 - arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h affa2c8404660a48bcd956f29a50e79120b1cc3b - arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h a832f792f5fc9564b02d96f85430f190c3f57417 - arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h 431e908bb797e10b7839fe28a0ace7d8a9e7bf99 - arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h eae4fb4ef015039f57a757e732fbfa815bc9aeb1 - arm-trusted-firmware/include/drivers/st/bsec2_reg.h 16d36c74e72bc40e7ba15ea25ce38621a3dc3a9e - arm-trusted-firmware/include/drivers/st/stm32_console.h ae8d33f6e04e5baf46e8b00b1613dca79c462e1b - arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h b0e57331d216261ea6ec7814666ae64bd884dc05 - arm-trusted-firmware/include/drivers/st/io_mmc.h 51b50b86f5dea96ef59764df60f2d64a45d54bf1 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h eaf998cd31b2112d0a61198a5a7f14d484217251 - arm-trusted-firmware/include/drivers/st/regulator.h 1b6f5d6f48fb0ceab8d15c6308e31e78e85bddba - arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h 173981f3ca549df6d0e56fd0a16e4a055b9151eb - arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h 4cdb146eb6fe5439dec2c5039a903ed5baee6aa6 - arm-trusted-firmware/include/drivers/st/stm32mp_reset.h b6eb16d19f62ff88852eab346d51d719944f14ed - arm-trusted-firmware/include/drivers/st/stm32_i2c.h 4b9518a5dba55fc1c78dc216a36ce0bb0e045155 - arm-trusted-firmware/include/drivers/st/stm32_uart.h b6caa41ecb428bd2e6752e1a1f5a0c2ef3fcc953 - arm-trusted-firmware/include/drivers/st/io_stm32image.h c13f39e45ffdff80cfe87c12423322a15b959794 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h f2ca7edf66b0d71fec9b893659707c7675f9d0a6 - arm-trusted-firmware/include/drivers/st/regulator_fixed.h 58a87d375953ce331a480d18ecbe92da88b221df - arm-trusted-firmware/include/drivers/st/bsec.h 6c00673ea5fb61808caf3b77e422043972ecafc7 - arm-trusted-firmware/include/drivers/st/stm32_qspi.h 156ba43b85065027d400a1287fa794a828df162b - arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h 7574c3687634e56e414a47e0fb3f5a5d7b1fc708 - arm-trusted-firmware/include/drivers/st/stm32_gpio.h e02eff807301ff7775369975495cad2a2082972f - arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h 86a1ad6cd3ce837f820ba6c1b9f6ee7182e74956 - arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h 91bfb605e20bff6aead18279afab90eed7856ddd - arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h e6aa4130f95dc7da0f3a94482c2ee3325afdf0a0 - arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h 967e02371bf07f76cf015635f5a50c0956176296 - arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h 1735a240af4b99862e6cb202fc034231abeb53bd - arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h ac1cd6d311e2280721ba62f9e82c10322f6dad41 - arm-trusted-firmware/include/drivers/st/stm32mp_ram.h cfbc99b7bba5966e33409c31f9f47cb7de63f66f - arm-trusted-firmware/include/drivers/st/stm32_hash.h ff21abb6526ad91314e2f7cc58fa6fd6546c926f - arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h 45a56579470aa4ad7e007373a068f3285f046de0 - arm-trusted-firmware/include/drivers/st/stpmic1.h bcfc65cd26c42c404b6482da16cdacf6e95c5733 - arm-trusted-firmware/include/drivers/st/stm32_iwdg.h e86b4fde780cfae34213629b58ff8e1efd1eed73 - arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h e545051ef77d33ec66036fa94f2d53b51253d436 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h cacf83dd6e129df0a9ffedbd38bfb757074d1240 - arm-trusted-firmware/include/drivers/st/etzpc.h ec0355e035856ac49891ebbbfb6b249439fe6bc2 - arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h f18d30ed876fb854340d329c32144778921ba136 - arm-trusted-firmware/include/drivers/arm/tzc380.h cd54a5c35b74beeacb16c618204bb31eaa33126b - arm-trusted-firmware/include/drivers/arm/gic_common.h 0f5d3819208e8ad3ef2356f332aceaa4239dd8b3 - arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h c269f40255323bed655d0c076e5fc771bee91550 - arm-trusted-firmware/include/drivers/arm/cci.h ea619e78dc1630857e7bca57a8fb64b7d45583ba - arm-trusted-firmware/include/drivers/arm/pl061_gpio.h 3d28678861c6be73909a9fafa1e03dc8bed75dd5 - arm-trusted-firmware/include/drivers/arm/dsu.h 84502e34dabd2a899d93664cb540910ed8183f7a - arm-trusted-firmware/include/drivers/arm/gicv2.h cad3fc32b992ec321fb47398d69df28d800ddfda - arm-trusted-firmware/include/drivers/arm/gic600_multichip.h 3c63f525fa4ab772695c59df263364d15f606582 - arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h be5093d8f8d48610060e70ed9a8ee5602ad6739b - arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h 1f2f3ae5b2636732d8a2b76e04392deacdc51203 - arm-trusted-firmware/include/drivers/arm/ccn.h dcca36bec1c965c6413ab49729c23a771108058e - arm-trusted-firmware/include/drivers/arm/sbsa.h eb064e58fc5aaf99768b3c9f167e6a369c5d51b2 - arm-trusted-firmware/include/drivers/arm/pl011.h 742d685c4e3046c1a64e99c18d00be7f1f9066fa - arm-trusted-firmware/include/drivers/arm/ethosn.h 2fa5a8cfd7f005b8d48960df0fa9dab5568d8059 - arm-trusted-firmware/include/drivers/arm/dcc.h abaea50a4f3861dfaa3f55cba235dc00114b68f4 - arm-trusted-firmware/include/drivers/arm/sp805.h c313d8aea2aa56300528293ebb42d4b35d46b18c - arm-trusted-firmware/include/drivers/arm/nic_400.h 0282c52c2cf6a737b53c9bcebcd089c5bf35ab24 - arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h 8d3c051e8ba42150549dab299eca67bf73caf21d - arm-trusted-firmware/include/drivers/arm/tzc_common.h 8971a6e6b857b7b1e6544d6c3c9a52ca567a9e11 - arm-trusted-firmware/include/drivers/arm/scu.h e133eeee905e96159734525bddeb5951f44fe0c3 - arm-trusted-firmware/include/drivers/arm/gicv3.h 7ca64097543e0475ded88ff1b0c756ea3e68dce4 - arm-trusted-firmware/include/drivers/arm/tzc400.h ea5359158383d2c575b976cf638b586aa030cc49 - arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h 93e88fa1b74eaf244a0d0a7346c849ee43adbfee - arm-trusted-firmware/include/drivers/arm/smmu_v3.h cb3a4608dbc689332bbeee2134f523d78ea6fcb8 - arm-trusted-firmware/include/drivers/arm/css/css_scp.h c4e97cf187b8de349d494ab89ca4f5c1a83aadc7 - arm-trusted-firmware/include/drivers/arm/css/css_scpi.h fdc34a2731639423ad5caeb5261f3207a4183cb1 - arm-trusted-firmware/include/drivers/arm/css/css_mhu.h 2199dceebbe76121f35942566cde95a239340491 - arm-trusted-firmware/include/drivers/arm/css/sds.h faa54f13bf1956078c447ae298b4696adc11ec16 - arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h 644885f6d536f0b9fecf9b19db5324cebdb1cd00 - arm-trusted-firmware/include/drivers/arm/css/scmi.h 749ed7a2a602879315a2a407faa53d9fcc6f4242 - arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h 7d87f35690f4d41b9739eb995465900a8070b7d9 - arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h 3ffecadd4db08d4069780170baac205025ed7194 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h e14a50e8d5c68b36920485b6db04f106817437e3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h d82ceff72eee2f6f805404b84357273d1eb09561 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h 10652996fa07e69877d9fb73449f7ab46d59ffa3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h 260990d658ffc91bafbece3081bb60c30618fa38 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h fc07b65f9cc014a0b1524b0068e8beccf88374cc - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h e610cb68e48f78caf111024d142af863b6398636 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h 5d04efda071e5940b11e2d270b3dae82a55dc93d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h 6e4f8a88b84a4ce3b762b6c7f14ac5fec8744012 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h 4639b7108f03bef1a92e980f8ee8eff03be1d869 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h c55427770d64593e3cf15b3ed93e6488363b575d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h d73a1ca5bfea93a55e5c13b2b3f2051e3c0d7c12 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h 49417191c51d1d9274572285c8ba5a8c8146e57f - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h 5ff025817e96abd32dab9c26c2d10d5116b211f8 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h 93088698293330d0f56eaabb73e01615b19fed64 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h fb12a0265111fe6f1b941f06d20f54b9439c689a - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h a182cb9bf34d396f46abd93062d06ce6ee8889c1 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h bf88a456fd40edb9bb68b2450d6251cda06f2465 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h a8d2ea546937a35c7f822dd9e1a7e8eb3fd4438f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h f48f4abf712cac68d01844cb146aa3c6e787e97c - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h a9419e34fbc18ae5da0ef1566f5febc0cf829211 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h 513b5a19f2f0b580cf670eca60e57e793cac539f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h 13f5321936540bd85461ffa7ef611ca5d4082977 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h b69f3dd73cff9fd442b44ed25f2edbb0bc3baa5f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h cb4a166015b83acf19a78617be8e774abc6e1798 - arm-trusted-firmware/include/bl32/payloads/tlk.h 61531a0b7ca81943d7aebe7d3183f30c4b6b42b7 - arm-trusted-firmware/include/bl32/tsp/platform_tsp.h dc1975b639c5dc6b8eee34ada66bffcbd10d3047 - arm-trusted-firmware/include/bl32/tsp/tsp.h 0978d63d1beeeb3f432496ea56acf6f3cf4d2072 - arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h 11335e71ce700055225b4223bb4218122db63853 - arm-trusted-firmware/include/bl2u/bl2u.h 76f24b5df32a33ff953257acc268f140bef007d8 - arm-trusted-firmware/include/bl2/bl2.h cf5f556d440245d73b0f784be4662e7cd634f39b - arm-trusted-firmware/include/lib/coreboot.h 9637b2573e1df004bff5258027eee07e6d532cf9 - arm-trusted-firmware/include/lib/cassert.h 7ffbca071dbd690b9d0ac30e6b388a848c55cc16 - arm-trusted-firmware/include/lib/semihosting.h 90db5a8e9962b61142ef6eed7165cb5967d686be - arm-trusted-firmware/include/lib/optee_utils.h f68ef15137b41ae5e5fd646d5b7624ff9843b770 - arm-trusted-firmware/include/lib/smccc.h 1f698e99c775d463461fd358a896217604420ef6 - arm-trusted-firmware/include/lib/runtime_instr.h 0b8f22e03d35106f8213bb63f81feeefe40d0675 - arm-trusted-firmware/include/lib/bakery_lock.h de7b34ae4f5c2aa97efbb717d681f3f79f6b3a80 - arm-trusted-firmware/include/lib/mmio.h b1522d52a6103e87ea31e7207f54208dd2c5a6af - arm-trusted-firmware/include/lib/debugfs.h 94cb452f38b47933f36d4af26e71b749a5ce2efc - arm-trusted-firmware/include/lib/utils_def.h 73dc3acb5868e207313dcdae4f6884d5c179faaa - arm-trusted-firmware/include/lib/utils.h 06aee725316857addfb02415a55463647ed20701 - arm-trusted-firmware/include/lib/object_pool.h ed4976b8261e1ee44f4a2b7952563b6db8e63406 - arm-trusted-firmware/include/lib/spinlock.h fcc42874d57314ab77ad7f2a2c1b2eb3862a576b - arm-trusted-firmware/include/lib/extensions/amu.h 802b885838cc683c33d5bdf0db010936d1d60c40 - arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h d9ddc757d1632d6d25a30937684cae6ef3ee6a50 - arm-trusted-firmware/include/lib/extensions/spe.h cc7362066d33e226e7e9996002c683aeb7291017 - arm-trusted-firmware/include/lib/extensions/trf.h 09511d96743a49bd6a8ce53a10a7a63f66fa69eb - arm-trusted-firmware/include/lib/extensions/ras.h 49864e971e8571d9d0cb63bce06594f6c8b5d684 - arm-trusted-firmware/include/lib/extensions/mpam.h b60784e6b65f97973b6399350a6bb41d508cb993 - arm-trusted-firmware/include/lib/extensions/ras_arch.h 08342ec02a973e05865c7a200258f0949f7e0948 - arm-trusted-firmware/include/lib/extensions/trbe.h 5e43959b0322424d6c58374b9bf52ca3435e88c1 - arm-trusted-firmware/include/lib/extensions/sme.h a3c002de51adf7dd52647cf5c6e3f6e119634fc9 - arm-trusted-firmware/include/lib/extensions/pauth.h 84ebabfad9a6aea5b36eca181ecacd9f81feaf8b - arm-trusted-firmware/include/lib/extensions/sve.h 46afc6f495640a910a40703306195c7a6c3a0833 - arm-trusted-firmware/include/lib/extensions/twed.h 1c0e9271a240a44ae26fe23c9d0bf4f2aefdbaa8 - arm-trusted-firmware/include/lib/psci/psci.h 03fe8d1844f9117cf59adf7bb69cbcef990c16c3 - arm-trusted-firmware/include/lib/psci/psci_lib.h 84b28157b2cc81f5a9aa46c6edf2de6083f696bd - arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - arm-trusted-firmware/include/lib/libfdt/libfdt_env.h ec87fea0386b1dcc840a14b66f68bb20746774d2 - arm-trusted-firmware/include/lib/libfdt/libfdt.h 26e37a910f19c0fe0293821c838312e998579df1 - arm-trusted-firmware/include/lib/libfdt/fdt.h a9be03deeaf86090c4056f6844a1dafec0a14683 - arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h ff1f378cc136ea5bf58c5fe0df726e1d809c7efb - arm-trusted-firmware/include/lib/zlib/tf_gunzip.h 531877858c00a04ba41ba7d211235fcad2bf2f77 - arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h 1cc2ff30d9d45589c3c7fa34a79ab141314e4974 - arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h fad98eab51c54e641e9db5451eceb044f426276c - arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h d152cc84bd5ddb5c62bb91fe605ebd55b28b2585 - arm-trusted-firmware/include/lib/fconf/fconf.h b61fcbdcf35b00e7cf2a5c7feff04fc5d28e7e6c - arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h 0f9c6bddf555b127d0deea955abd911c85bc89b9 - arm-trusted-firmware/include/lib/mpmm/mpmm.h 58569d6f8289cc5c665cc6dd3455a31057e6209f - arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h 55da8ccc24cdd5cabba3e346f04694958ca9b84a - arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h d44192225758ac451b1c5bc5111f98c453327523 - arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h 7a7b59a035c26b0ced83b40114b596358f1bd2c4 - arm-trusted-firmware/include/lib/cpus/errata_report.h 3f7b45d32e48e60ee32229b7e8f5860b6e67747e - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h 055e82d4e76261ce1a2108d14cea7176cf18c0a9 - arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h b58c922be5d4bad0866dbb86570d6f9e94310f89 - arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h 7de432330be3e8f54c1e573f4ab59d51806e7365 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h ed260f8199efb4c6b1d32218c83039568c4ef425 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h 82d90eaba5c3e4a0d0d67cdc9bb41cf9f9d2aa35 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h 70560b6cca33e37badb4f0e52e2781166227184c - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h 42b29f7ea79198fbf5aa69a3aa080de56572fa3a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h 32b8e77c476293848bb5884355c7faf95069f8c8 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h e762cbd4ef8859eb8d8ebd03899ec10c085ce1b5 - arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h efc8411aa80d03690795c5caab5213f739c3dae2 - arm-trusted-firmware/include/lib/cpus/aarch64/generic.h b2ba28f5ae615b85d1e4f9417e53743767f749e5 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h 3c127123c7f793221554840dbafc9aecc3acb322 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h 43952567938e0452e6f1cd65b6fab276d3b628e0 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h b9a6a19c148f0fb9ef9b3e03b113a48c319f50ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h 9a1b5aa467e9d2d3b68dbfdc3d96397743562185 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h 4f1b3a7c5699c6ae409698b593edbc6ac8d2a861 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h 309db7cc6a48f2dfc2fc82dad3300ad2825efae6 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h 7c2b1650f6c338afe9ce5b81aaf9c15b6c358c98 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h fee71b3ac82a2185c4d87e46ee0883cd51017f0f - arm-trusted-firmware/include/lib/cpus/aarch64/denver.h e7bf4db6f79577db296e4c8444c731b2e3af4822 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h 26f966576d1ba5fe1e871578dea3ea004be5ee67 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h 7f4a54bf5113ee54ee16d5400921730610b81a5f - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h 80bf6905c50e6839862d8fc71c9406f081533252 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h cecb6b77ddae233e9012f44da229b0f25904b481 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h fe7e88bb537bded4caa68969291e0f7582e7abe1 - arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h fb525a4bddf12d5307fdd7d77fe2c90783b76d85 - arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h 22958de97bf4027cc040fc0ac360db1706c214e9 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h 316e8929890c4678843eeb9c9f055e3d7b37419b - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h 84e558d38ecba4e5f4d2f894a9291c5037ce66ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h e06ae7d94772d2e7df59aaed91759743f3614979 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h 6f80e2ceb55f9179c0e8b9d91d249e62d6b1face - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h 44559a7bdfb73f25458f7ca2b0e8c8785ef8827f - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h 31b87fd75812c21215587c76fc574207c546b735 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h b5de08d6bad3b4fa6d103de5fdccbe1dd027b1e2 - arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S e67d118e55ce590ff3f6428280713a78b8eed58a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h 03c06290a053bfb539077f235d6cbd00efa9839f - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h 7c549b2ab4e1d1d0e0a845e601e8778c8c5016d1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h 4f8e78fb1d10bb5da1ae6792f2775a2e3d34e739 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h b3f572f2b6af62ea012727754cd52c72ab76a8cb - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h bb26a1dad2c7e0bc860a422313a21fe96c5818e7 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h b4398b2cbe8c44396c14071dd547d3b4ae231f11 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h f05e12dd19967571232d263c83c6898dc9f9c9b1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h 7246c771a29d42ce8df39025143fedec1f1d22ea - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h 964ef94b44f29b27af9693592b55d5e045c68898 - arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h ab3b500c80e0bf48a6fa1b8aa0cedb3451312f73 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h 4f2016b0ee0a27a62e127a3e9e49889a8cb0d63e - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h a90685421214c1862d537af563def9b63894e740 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h b28242a3c70922add954edac6ef6a6cc27eef33f - arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S cfcb8f035cda18f894c8ee194d3136fc61406fe0 - arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h db010d01a2298bde5d192dc8ca42d487ad8023ac - arm-trusted-firmware/include/lib/el3_runtime/pubsub.h df57266f0878fdff7b3180dfc258dae3ca1859cc - arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h 926a8f99c7871413aa6c48ee91bcacf8ea07e438 - arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h 38bab004d095d8c31cc1bb191af9e3c4ee45ca02 - arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h 9c3df6c4d9ecf03368ef7a5cd150157123c12ed1 - arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h 147505a24c5c0680f8c21cd8b77aaa1ed3d9af0f - arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h 748f4763c6956e3a05b07a06f88394f925375806 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h a5b742f0a88671c56d4acb2c9f41a2859ccfe63c - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h 0ea4285dd4504af01f2379c11c6b04292b5224d0 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h ffd6aa77c205ba28fc3cdedfdf92ad949a1d2c4e - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h 64b082be684d2e9aac73592fc4658c81ded65fcc - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h d096d2c939939ac7e3ce5358c63127a2e48fc66d - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h 135853a26b41e70bb03df6feaa46157020f24f43 - arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h ef0a81e88f09c2c6ce252f01c0405fa13cf09822 - arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h 9b838f7bd9f2c4493efedef614f584d30c32546d - arm-trusted-firmware/include/lib/pmf/pmf.h bf81e2d1db65ed903ef83af8c902a2c570f7d8d7 - arm-trusted-firmware/include/lib/pmf/pmf_helpers.h 2e8bf007844002145509b02185c1cfb380c086c7 - arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S be45471818b5fb856ed0fc1c303a3439ac749d6c - arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S 72f4645c807c6915c0628b0d200b18fba404f91c - arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h 2f17e8f91531cbdb0dcb5638ffe35b4fc35169f4 - arm-trusted-firmware/include/lib/libc/endian.h 28d598da1ead2bf6ee9fd764635deb7d1a082fc9 - arm-trusted-firmware/include/lib/libc/stdbool.h 05293dcd9dcd66e6fbc14019807633a277c3a53f - arm-trusted-firmware/include/lib/libc/time.h 96064295890c1e484dfcf96039b0cf5c4babd361 - arm-trusted-firmware/include/lib/libc/setjmp.h 5e084e86fa5e4b5fdac774d1aa00b279f68d3c40 - arm-trusted-firmware/include/lib/libc/inttypes.h b37dff6a9fa0fe100e6e204676f60358dfde29eb - arm-trusted-firmware/include/lib/libc/stdlib.h 81fc18b0518ed12942398f24157b26767f2b5d58 - arm-trusted-firmware/include/lib/libc/stdio.h 83a3b49d103b8453fb98b0625c759bf39c09803e - arm-trusted-firmware/include/lib/libc/assert.h 1f519accd161baa49f478a735728f1b81dd9a443 - arm-trusted-firmware/include/lib/libc/stdarg.h d0d4318e609c76661d8f0144b559d4c7e5c43cce - arm-trusted-firmware/include/lib/libc/limits.h 0d835510f380ad8267995f98edca212d0c2d8f72 - arm-trusted-firmware/include/lib/libc/errno.h 3ad9051758ee29a3d96abe5881f5a7740eb10550 - arm-trusted-firmware/include/lib/libc/cdefs.h fec91d22fe696952ba93c2d1ed6cedfa714a5a7e - arm-trusted-firmware/include/lib/libc/stdint.h 167e84c7f69dda6dbee48fff38839436941dfe1c - arm-trusted-firmware/include/lib/libc/stddef.h de263df3e964aac45b0a9be4096eb2a12c63d72b - arm-trusted-firmware/include/lib/libc/arm_acle.h 38027460aea214583844c4cb07db44077673acc5 - arm-trusted-firmware/include/lib/libc/string.h 8741dd9ddf232520a7e68bd21382fd53539b8c5b - arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h 94f633f89b9ae70068fb70432456057bd04bb750 - arm-trusted-firmware/include/lib/libc/aarch64/endian_.h dec49d90238a3dc066022d9268b1172c93e6bd29 - arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h 81dc661e625cc7228b67c09aea60df34e729c283 - arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h a0ec98e34e93c55ac6fc9241cbaed06bc372bb39 - arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h c881950de56de06d14e10e06d219c0ad40613034 - arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h e3ba7ed7d41ae3a8c9dd07d94f7bbef48adf165a - arm-trusted-firmware/include/lib/libc/aarch64/limits_.h 8eaba3f90b7b124e01dd67a505f4e8dac6d42826 - arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h 5d60818c76a8f8d0645d40e13fb9c6bba183e2ac - arm-trusted-firmware/include/lib/libc/aarch32/endian_.h 5504c60845bc40c22309d19ad3a370854542606b - arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h 99fb55bd4f7021bebc906bdfbf7f2e0a32e198f9 - arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h 4ffa8f28ee204e4445f86ee9e68903c66fb5487d - arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h c6119d73104bf3ae1d27bac47db49a0fbbdcd112 - arm-trusted-firmware/include/lib/libc/aarch32/limits_.h d33d416f27b0a754a92dea111013ae91e9fe09fc - arm-trusted-firmware/include/plat/common/platform.h ec1ba9f6e5e5199a8174963440c8673120fd65e0 - arm-trusted-firmware/include/plat/common/common_def.h 9cd1950e6a5ff8b2dcd0143c1dfe498c7804a1f0 - arm-trusted-firmware/include/plat/common/plat_trng.h 0ad5bfa2837c10aafe72e696c238db4ebd82794f - arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h 5d91bb2b767050d467d072d4e6d7036d8c71d06a - arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h e639b2614ce8c77a52995ee2da45fe54fbb8dc2e - arm-trusted-firmware/include/plat/brcm/common/brcm_def.h d7f8e1c595627094eb1807e5f15cbb7674cb02d5 - arm-trusted-firmware/include/plat/brcm/common/bcm_console.h dc4318dff472842b4c63c7b87f23c3688def3c5a - arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h 9dd486928223e599a25bc6f13b414fc57c242b36 - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h 8cdfa6f8ca1d681ba760da2fe49c8f365ef0dcbe - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h e2d034b7bbecdf28360fcf107159eae0bf87de48 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S b7faf2c71aa5d9ab793eadfeb28cd9effe284930 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S 98c1515593c3e784076edd107c7aa20f26d00900 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h 618289fd2c98548dbc401a283df9d3c6386ce002 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h 71dfe89c5f0b7453c5e1af8a81c440aea8ecb34b - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h e6b0db0b8079bfb25c6c3257a0bc6403591a354f - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h 36e0657b50b40ad54b3ef6b8b6848377fa423ee2 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h 6e72bb219cdd7c32b97b3df3a2fd695dab5d6fc4 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h 8d91b9ddc816f6cc8b89cdde08ef32b86e76f779 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h 79fec062b150f074e53c3a4b1987aea42e5a4eff - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h 5eb5b60a95f1d5821d119a38a870719cd6345ca8 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h 48923d6fcb9d9e02790b158b5eaf6edb34db109d - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h 64f1e7c2408515cbabe2321cf6584901213dcf2b - arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h a4c302b222e019205abf65fd01745d571d810ce7 - arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h b6516d7703c189ab60f935aae9db8c643bb2d84b - arm-trusted-firmware/include/plat/arm/common/plat_arm.h 0afd9c0926d88821488dcd5686914fd1ccee3763 - arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h eb2f94f2fc7e75343b6ebf27607b356ad90cdb7f - arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h 62a021ac07cc197af73c3a77f81b2e3c269b7cb0 - arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h 1fd41daca5740b134bd9df3d981f66ab2fea4f52 - arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S 971368d067997c8cf7b990346646cedab7fb9189 - arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h 88fe915ca8ec7f1f3499a57f534e1396c6b7c98e - arm-trusted-firmware/include/plat/arm/common/smccc_def.h fdc727288dd453b4dcf18b744fc052a039bed405 - arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h b9070936733be0fa95be33772381b15e63ef79b2 - arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h 44ce8058a0b197c5c89e419bcebc0ddcd8434c36 - arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h 9437b8c5d8cf84ec02a69c03b1658cfe00ce9a70 - arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S 85db4d68c709e11a4b63da0a434f5aeeef2aadec - arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h 32a205b639eaf056873e852af9f2f925782878ef - arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h 36a2614776249ab76e9c86d1f08fd0057bab8263 - arm-trusted-firmware/include/plat/arm/common/arm_config.h 76e5f8f29adea5aef863105a24eb9d29d8be3952 - arm-trusted-firmware/include/plat/arm/common/arm_def.h f0fb541bb623a169168129c94b788f2a409ffb5b - arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h bcb4189176bf949ae7ccbb1fb72c9d29b366f7e4 - arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h 657f1176fd4f82dc1155d86438b6fbf624d2747a - arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S 3bb163e8411b70a5b6f5913631e64392b3154151 - arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S 0081d14a9dd87bdab5919da6391eb2275fa7e94a - arm-trusted-firmware/include/plat/arm/css/common/css_def.h 68405ab09471b8d13fcf6f7e2b8f07a8012d11b8 - arm-trusted-firmware/include/plat/arm/css/common/css_pm.h 406bbb095f6bf7f140e7814e98b0ea99062ad767 - arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S fe0efb2292b7b971908fcd44d634894276a51f1c - arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h 81ed90e8c99ac6343426728d9299d8ad48305d39 - arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h 40577c7bc2464cf873f1f2708e2db8112b51374f - arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h e1699b761cd12de148f701d78db5c24eb3aa7251 - arm-trusted-firmware/include/export/README 45ecabce41da084db92b27dd88e6e89f30506036 - arm-trusted-firmware/include/export/common/ep_info_exp.h 91e15bef63bb89bfd921b4d01d17b37dbeff291b - arm-trusted-firmware/include/export/common/bl_common_exp.h 60669a2cabdf40b63773d538d47861c1a584f800 - arm-trusted-firmware/include/export/common/param_header_exp.h c2a9a69314ba3b3f2369c8c876b39d8acda1b018 - arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h 9367cefce0520648ccdaad1fe3a402422becdf55 - arm-trusted-firmware/include/export/drivers/gpio_exp.h 5091c9e14c49f9799bc9985442295e882a14d3b0 - arm-trusted-firmware/include/export/lib/utils_def_exp.h 72b925e2450734e1991799db8cc30f6a8609462a - arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h 9bb9fdc2ec0963a6cbbd0188ae70e368e67755f2 - arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h dcd0ca426668c19ab921df2fefbf2d83ca5afdd8 - arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h a628d4b48c67b17cc32449aacf6052a52eea1705 - arm-trusted-firmware/include/tools_share/uuid.h 1fda7d8e566efd28aaedd2f5d1ae43b5bf4d2705 - arm-trusted-firmware/include/tools_share/tbbr_oid.h 58d6bf8cd75f220139c010d1d5fb6e0a96d4564a - arm-trusted-firmware/include/tools_share/dualroot_oid.h b279cf845b5ea6ce93f6563029c2dfbe6f85a541 - arm-trusted-firmware/include/tools_share/firmware_encrypted.h 3e0251958205aa29f860e4627e7f29098e266f1d - arm-trusted-firmware/include/tools_share/firmware_image_package.h 5219a8b9ae1ae1722063974c9bedee960cfa351f - arm-trusted-firmware/include/tools_share/sptool.h 7185228489bf2c4e562f37a9f927cbc31c18ced1 - arm-trusted-firmware/lib/aarch64/cache_helpers.S da63c15641cb6cf532770db54efc30b3f8122a7c - arm-trusted-firmware/lib/aarch64/misc_helpers.S 96718b39d24ee4ca5fd1eb4f87d53c45c9e4f079 - arm-trusted-firmware/lib/aarch64/armclang_printf.S 4ef2e504a667d7529f6e9f0629c04db77435a28a - arm-trusted-firmware/lib/utils/mem_region.c da13fbd30292be6162a14bb7866fc3da5fce2c10 - arm-trusted-firmware/lib/extensions/sve/sve.c afd6141e2e07c1fd692c8e845ce6e65899fbbb7d - arm-trusted-firmware/lib/extensions/amu/amu_private.h 7f3f609a1bb0c4b5287f43cd817a535c4e497353 - arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S 896aead96745f721f995de07ec7a83fc77ffc33f - arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c 3dbb067dc92b40dd63f5ee3b50d0e88978e7e528 - arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S 21d2bec3b0a822561dc68c9dab32b97d35ea848a - arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c 1e8ea4b9d81a41c874fd1c0e7b3915a5337cf966 - arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S aee505d9d1071c6c819d07bc02c1e963cf8c6025 - arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S 4125c51fd3f075d4d291f56b53175ca0683e12eb - arm-trusted-firmware/lib/extensions/spe/spe.c 672dc9ce8ca19e9bad297552bb38f03725d544b2 - arm-trusted-firmware/lib/extensions/mpam/mpam.c 20945ff7a4f02b5797f9043d0dd1dcb655476c0b - arm-trusted-firmware/lib/extensions/sme/sme.c ba76ca96162e88bc6bc13591b4dbe2d955320a45 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c ecb8e335fe4a2681e714ea9d5c5f2b8f5e1a8e07 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c ebe5066f50de32f019ea11419b6ef11da4604812 - arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S 785751601e97ed8f6b006cbe5a6e26dac81addf3 - arm-trusted-firmware/lib/extensions/ras/ras_common.c 9b56d2cedbd5417e75959a7c83b6361dc3c48f6e - arm-trusted-firmware/lib/extensions/ras/std_err_record.c 1acd16a1b33cf990f1093d8f0ba9c0ebd7a6f719 - arm-trusted-firmware/lib/extensions/trbe/trbe.c e3dc484cb8d981ceb0cdc03a7bdb8f24e2f9ae85 - arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c 5ccbd178b5c5eb953d97ca519229837a0537e821 - arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c 70011c90369b5b9a9d55faec233e60b90b31801e - arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S edf2b7a02784eccffa70a8f06817929dd1a8f993 - arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S b3453819b2250ed7f47a81d57ce565f8d644ddaa - arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c cf339f00e977a47612e93384a6a0b8e73d731c21 - arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c ddcc3c9570f910954693aa27a5b355d4a84f2ac5 - arm-trusted-firmware/lib/psci/psci_off.c dc70197a71b51add43f68a1708e572069b991b10 - arm-trusted-firmware/lib/psci/psci_common.c 96cf95201b14289b9fd8994f635436bd603c2e2c - arm-trusted-firmware/lib/psci/psci_stat.c 70484461d77679b66812b09dd8b56cb0c17acaf9 - arm-trusted-firmware/lib/psci/psci_mem_protect.c 829a7e8232b3efde8c6ad84aff7745c16582da77 - arm-trusted-firmware/lib/psci/psci_system_off.c bb2c6a22fccb6b37506ba1b0bc6ca6db53f60051 - arm-trusted-firmware/lib/psci/psci_suspend.c dc79080304d8fd3b4fee3f3ab53559b3a1008d90 - arm-trusted-firmware/lib/psci/psci_private.h 268386d92529e4c7ffed1ece69a88ebc933c34e2 - arm-trusted-firmware/lib/psci/psci_main.c 741cb1ca4722a4062052f5ec8cbb9d6f1d4ee468 - arm-trusted-firmware/lib/psci/psci_setup.c a45af64e61c40345d7034444490e7fd33b52606e - arm-trusted-firmware/lib/psci/psci_on.c 2c7b752ae78666bc171dbc6858abbe2c9cff4013 - arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S e3019770bfa11512ec7d2d6785e37d28c72cd2c9 - arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S ecf8ba50075277e075334d8bf2192d3a03b4d713 - arm-trusted-firmware/lib/gpt_rme/gpt_rme.c edbe27a26695b90b039ea42ae87e3756c047631a - arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h 7b5870894878b452bb2f89fe98f1e15591a599b9 - arm-trusted-firmware/lib/semihosting/semihosting.c 79d2f0e3c6477c7632a9d7b9d01b42625bf0cbb3 - arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S bed75bc5da772504027fb7c033a1c918acc82c48 - arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S 3af779f4c2869b4f4f96ca46039bbe9311cfefa4 - arm-trusted-firmware/lib/libfdt/fdt_rw.c d63d474ccc4d93be45267b9c0a32c3c88c4f42cf - arm-trusted-firmware/lib/libfdt/fdt_overlay.c c3bed95f695f7f9780ea064580ce245fa8dc6611 - arm-trusted-firmware/lib/libfdt/fdt_ro.c 3aae059b21ecd4f923c8f399d4c2dd101ce03502 - arm-trusted-firmware/lib/libfdt/libfdt_internal.h c7bf913dd7eabfba85f363d7a05851e84c786828 - arm-trusted-firmware/lib/libfdt/fdt.c c16e3571ab87b0ea9f8067989a5b0f97251ff8cb - arm-trusted-firmware/lib/libfdt/fdt_wip.c e01b7a0052b837a4650f2c9ac75ad38c40edc583 - arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c 6db863ac215fcf8880798469701f80b2fc197bcc - arm-trusted-firmware/lib/libfdt/fdt_strerror.c 55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - arm-trusted-firmware/lib/libfdt/fdt_addresses.c e6ac4a37689f70dd9fd01a67cabe4439d66dc4ea - arm-trusted-firmware/lib/libfdt/fdt_sw.c 655c16e59bc70c4782c58f76a458853aeb35f2f1 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c 3da3d4c987ce40660bb10580236ee870f603a567 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c c8e552a0ec8c6fbc0008de98e8cc7e6ac08f1980 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c 6d8e14259a3bddae74927623e68b6e95a578b3a2 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h 97a06786c9d53286c3d0d861d9e6578551650e5e - arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S 250ce42c1d1df6103d9a7eb84f739a52570e85c9 - arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c c3816ecbb18ec120734f1bea8e79ea2ce6e4f631 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c eaf23114b5279a2e5177c2d4a103265159f839d9 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h 499b3843cd918ded79d9b4067c70be77235a831e - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c c56014f913bcddf7eb4618bc48a2d7e188df93e8 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c 48fbcd0295e7c9d2581d235e6c80eced4a10a422 - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c 21604c58893e3fda032bac4d88417fff189d89ca - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S 990536d736898528cf4565171fb83f57604dd3d8 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c ade75a712dde9020d79686a61994595c14f73163 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S 5c1fdfd96d90cc2df42b24e37dc31a193219049b - arm-trusted-firmware/lib/optee/optee_utils.c f32dab3880d47eca1b71c308cf6542b32941b23c - arm-trusted-firmware/lib/zlib/zutil.h 8770ab43c9050b824c646f6e6cee8b3c0628cbda - arm-trusted-firmware/lib/zlib/inffixed.h 628d8395fc7f67e6d7a9a6cecba64f6594d64eb9 - arm-trusted-firmware/lib/zlib/inflate.h db9e88b8332953972c9120c73389fa2ce03dd8f8 - arm-trusted-firmware/lib/zlib/crc32.h a152b76b78f9245ca67db2729de72d51ecc234b0 - arm-trusted-firmware/lib/zlib/inftrees.c 3c63a7707d83991f3e074391c047b3136ff3e558 - arm-trusted-firmware/lib/zlib/inftrees.h 2f1fcc93488ac84acf984415b6ea0bd63c72aa49 - arm-trusted-firmware/lib/zlib/zutil.c 6c1114794db137af50f9b060aaade1a1a35ed784 - arm-trusted-firmware/lib/zlib/adler32.c d5cfffd5a037697867a78566d583e73f6d0f91b9 - arm-trusted-firmware/lib/zlib/inflate.c fe2fdfb8f51d9f84881cc453ba64f60e3d7c9cbc - arm-trusted-firmware/lib/zlib/inffast.c 4fc803c43a562b2b92a97e22300754ddfe44c603 - arm-trusted-firmware/lib/zlib/inffast.h 473b29ab06e2be461fe4aa74952fcb9bd08d9fa0 - arm-trusted-firmware/lib/zlib/zlib.h 0ef05b0d12bf2cfbbf1aa84cff0e8dcf4fc5b731 - arm-trusted-firmware/lib/zlib/zconf.h 88ea76a1b42bfc247680dd50b450923858f945fe - arm-trusted-firmware/lib/zlib/crc32.c 8bb206723f10a7635c07f3e77abad21e4e47f520 - arm-trusted-firmware/lib/zlib/tf_gunzip.c bcf80bf32003cb4ebf4b71fd3b62b2ec5210ba95 - arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c 18fdfde595d6c7a6409f3d91382d81f736bf775d - arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c 1720429b89e9cc8c7b5f6bde6381dcd8f1e4bf0b - arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c fd4c5030299c6c43d7dcde650254301c4a185c84 - arm-trusted-firmware/lib/fconf/fconf.c 3567bc768ff2f143e4933244eb221b010bd91f80 - arm-trusted-firmware/lib/fconf/fconf_amu_getter.c 06052beb76737879a3430c42f32068e7630ce940 - arm-trusted-firmware/lib/fconf/fconf_cot_getter.c 3c63f678cd78b3c4c10b6d13ffb32f245deb8ef6 - arm-trusted-firmware/lib/stack_protector/stack_protector.c 7c77f07a1d4fda36a4af38ed18da2e22607b53e9 - arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S c50c9ce39f46bbbfebd47c8645445585727f5b7d - arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S 35242ceafb8e7c1ac58158cde6672b601b1a88f9 - arm-trusted-firmware/lib/mpmm/mpmm.c 3ac2e5a07791e75f8ed81d0c1088a639a14142de - arm-trusted-firmware/lib/cpus/errata_report.c 23b71740924a2f46a4a3766dc7863240494c0c3e - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S d16bad3d9e6b6ed0a164467a3b25e5174c38de83 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S 67a71ce51804d2c0c43d0c5b928b429383691702 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S 62e253dfa61bf57bc7c8af97146dc643070630b6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c 03c0a2d3e033df508520b527dd03c5487d139556 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S 6c5232d349afaa099b1de4b8274de771a075d0ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S 27cb3501d1a82bf7a2962df5e632ceddc6099479 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S f382f5af3fd88a0d159f0fc27bf3ff89e6e6517b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S 4076b184f1c8b586d8b7e9c16daffa08e81812c6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S 3a0842db6538fada52fd0764e2942e9edcfa61e5 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S 8753b581e7bd70b0612f529761cb2e2f789d26ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S 6256de3b0f8cb82f4629e83dce1ebf3f3d101147 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S e0dbf2ba5bb288d057c7b39ac8c9217a8e9ef501 - arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S 6c59fcd106e14d7120f6a715ba57542d71f097d9 - arm-trusted-firmware/lib/cpus/aarch64/rainier.S 08801af78758ca580f3619f48f0d2b72b843b8b3 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S 50d6608eb167f02f6eef1948d919c767b8687797 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S 7cd2af73210355f0e23d3b78612b61f25b37cc87 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S 9745ddbfe3bad71ac283cf7afe3f3a58848729fe - arm-trusted-firmware/lib/cpus/aarch64/generic.S 87817fd4d0f4db7bb9527cfe0b1107c39d33bd8b - arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S 2395220984e4ebe2e10ec3658f908b7a208fb99a - arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S 0dc9a7f3f035cf6c322da9c77eacf5cdfd5be43b - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S bb044127b0f5b6908597c1915659ebabb4b9d8ff - arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S dd46ea61bba696867fb1ab60d0f54a5955c1f181 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S 4605a62d489dd9762cd96aedcfc0fe6101c14072 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S c2e3731d8a04eb0fe71b450fe59df2cca99da824 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S f751bc5c9ebc637d2973b137fe4020a9d2b49ef6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S 7ff21ebdc83ea3c05558a7c0798f1424648d5a34 - arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S e448fa0b2d060a91a00ce5b1747f0bb4963d83e4 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S e314809e018d3bcc1cb805e4412443d918934828 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S b6f5469c320d8cea71ed93f0779eb1706255e014 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S 5f3bf45f19baa196f8537ea9fa6db1c00692c35f - arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S 366cfe2c271409694f391a9092ce58f0d69d8eec - arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S 0183572f056c98431e9ee40e1ca22f149c8d1995 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S ce5deaffb5280914ff04e13a3c1e8d5e0a12e9b0 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S 527f0453b6bcc1e3cdbc68d25c5949e9c6d90d21 - arm-trusted-firmware/lib/cpus/aarch64/denver.S f245d765bc664b16acec02a6040885c8a59f9a54 - arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S 814012a88912a712842aaaf04053a1a8fc46c29c - arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S 006dee1e8ead4bf3e5c48a7374813cd8b78ae362 - arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S 5e64126fe122470b5f906cbd26adc7b19c2b1cbd - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S 516e5e5482ec47fb50a91b19c7c8d86572bd9844 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S fd801851b71a05fbc5920f6815d5ab8025a7f156 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c edb24154359f6a874c199325c9d7072c4dedba3b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c b6caa69a2838b35a3268cac6784f7f42060028c3 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S 4a3f95b9caa66e146e1a7057c238ce166bc17ae0 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S 4bd6136e7c566e86577b42f173af618fff3ec5ce - arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S dd4d708971e42cb6726bd6bcaeaaeb1ea62cc302 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S 28602f5410ff8b383fbca1c3d420dd85e9e2e12c - arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S 531b8790149c59c6d2a7528e480dc52235a0b5f3 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S d132a84afe31b0339e4451e7df450856572fd2fa - arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S dcc4327691c3788d4ca00df40256542be520f4a6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S 70588b0d27cc22a3c28dcf235cb80cb80658e875 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S 504aecaaa931ada33617064d0c95d4514d583971 - arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S 0011de1efcc751a018cb652d35bf6dfb77ee5da5 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S 33d1e02fb1f40c2b2147fdf1911b9f6d0de2592d - arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S bbcb12f3afb37a6763f26ed91a5859a16a9185f6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S 698a71205b1dfcca91b0dc7e75cd8633685859b4 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S dfe9d1459f2afc808df76389971581e7cd156c05 - arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT 58b4cf2c8174eb2d106886b7cb8a016d40b2d753 - arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c dd068590d2ed1fd41f248aa09a898df9da988c07 - arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c eb176115541305cb488d2be70cf8c519c16b494e - arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h 35e2f5c84e2e03c6a63abe1dcf1494fcf8ef9d7d - arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c 32a243925b1b44cce203fbb02b0a15210edf2c34 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c abf726b9d10381fc90d5c11654d391de96b8d950 - arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h e6b7517bd52e7cd7c50262aa9efbd0f8ae19a1c5 - arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h f0a970815c4d8d2aac30a5da63d63cc4c5ad824f - arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h 3a299c5cc089640cd5a4723e9f7ef8eb172386e0 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c 46a423cd744769dbf4c8a9bace21b176a9e737df - arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c 0740d888a28b420885866b396a4b4c3787fa5d9b - arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h 393af562fe70f1bc9366014f2afdaa0318c8e72a - arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c fa64ca197ba53f0e818a0f087349634fbd54640f - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S 534e0612fc60e5acdbd99194724c762a645b1a4c - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S 14efe65532640ad904e16c0fcfdf2a0aa8ef7892 - arm-trusted-firmware/lib/aarch32/cache_helpers.S c975d8abfe42e48d68e0e592ba3989ae3f7f0853 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S 8a00fe14195497b3dfb4323af7775b79c89a645c - arm-trusted-firmware/lib/aarch32/misc_helpers.S 50b2fea23411834a7cdb5cb61cc8559bcfd872b1 - arm-trusted-firmware/lib/aarch32/armclang_printf.S 00169552baea8da03759257b44162edf097abcd0 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c a9efa4120656b54bbfaf91befd1a82dafb8640a0 - arm-trusted-firmware/lib/romlib/romlib_generator.py 3a7bca01cf9d3b67b9d93fec625c4591ad106379 - arm-trusted-firmware/lib/romlib/Makefile bc8857833413ad776fefee7b3a4fe3ad74c7cd04 - arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh 0b4fe827956659566fa763cd1b1e15b1cdb505b6 - arm-trusted-firmware/lib/romlib/jmptbl.i aca0167af243d551e7068e10251ccc62e1b800ea - arm-trusted-firmware/lib/romlib/init.s 1a7d8adbdd571058f2d7cdf2dad5d51e735dfe8d - arm-trusted-firmware/lib/romlib/romlib.ld.S 5c8a013e889e7653f0cbff1346cd13128ff2fd69 - arm-trusted-firmware/lib/romlib/templates/wrapper.S f9c9050fd5c89b246d718f406a9d9a13f3388a5e - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S b022feb15f3e84d4eefd318657af38a3a523e363 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S fa26b89e848f7affd6fd3be71153b55961fbf971 - arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S e0406a34add19465d2ace2d60bc6c5048bf0a9ff - arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S 8bd9f16af17fc4a81e921654d50217d6ba334d4f - arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S 56fc8c8a2950a0303783ced6bd0e388176043a47 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S 91d0e6f060cd659ba73d0db8886497a823814c65 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S 2e63b0dd99041f913d992fc557f39d47f05937cc - arm-trusted-firmware/lib/coreboot/coreboot_table.c ccbf0a74a73d6eb9563cb282272e41c9decadde5 - arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c 0407aded26aa40484ccde01e8562c2db1c2ff939 - arm-trusted-firmware/lib/el3_runtime/aarch64/context.S 648e98ef419ac30a1fdfe6e9fdef5a45f6fb8926 - arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c a748c18c9c1bed5bfa7ad7bc2d42f1241b4eeb59 - arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S 72331f73e0f3f6540837815f472f78059a7fe275 - arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c c16b6a90e04aa66123dde223fa202f33ab70aa51 - arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S 489fa8c2a31654d4ab05e281acbabb0f8a64608d - arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h 57633f55f011eec32b09f4867a18db8725ad24d4 - arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c 83fd34388e89c93efcad1998551854558c28ad99 - arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c 08dd595ae97e585c165a02faaeecbc5c0615ecca - arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c bb710f3b156b87d08faaffa4bfdb60074c5bf5b0 - arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c b3f793c7bec8ccc037a4cb9796f2bcd15f5bf4eb - arm-trusted-firmware/lib/pmf/pmf_main.c 6b60742d3e420cad2de83925c184cc98fd66505b - arm-trusted-firmware/lib/pmf/pmf_smc.c 886c1e8212ddafb0663811837c76ce60a9afb42a - arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c 78982645d4d3008984c9307ee68bfa8eeb1a43a7 - arm-trusted-firmware/lib/debugfs/blobs.h 8102f862edb5ab07783993999c8781385e261628 - arm-trusted-firmware/lib/debugfs/dev.c 5260672b27f35a4368d3be1f6ee66ec91d4beb26 - arm-trusted-firmware/lib/debugfs/dev.h 9802d55cbbaff09010b37afad6d494d8e755eae2 - arm-trusted-firmware/lib/debugfs/devroot.c 758f3be3354709a4f69ee89cacf0db10dd68c75c - arm-trusted-firmware/lib/debugfs/debugfs_smc.c 7c85c537adcb24f5e03d6c71424a2618815086e3 - arm-trusted-firmware/lib/debugfs/devc.c db9f0e301c7178c315a1c6e72358bae572ce85db - arm-trusted-firmware/lib/debugfs/devfip.c 0e11c2ba3c9318cdcc4c28e3e3663337046128b8 - arm-trusted-firmware/lib/libc/memchr.c c72f1f1842a78fb427805c7447d370fc148dc89f - arm-trusted-firmware/lib/libc/strtoul.c 76e2ba1d1196be96fef786c3d7c5130fdac79ca7 - arm-trusted-firmware/lib/libc/snprintf.c 06782e2bb8b5e2b70cd089f061be9c1a08621523 - arm-trusted-firmware/lib/libc/memrchr.c a13fb76d1efd1532d6265ca7e3753be123c5fbef - arm-trusted-firmware/lib/libc/strnlen.c 07dbfb512cae53c03504d60ec4b02bfc74c2af8a - arm-trusted-firmware/lib/libc/strtol.c f5fe2af7f4f0cad25866aa2422d946f47a11943e - arm-trusted-firmware/lib/libc/abort.c c64e54b9d37e79c6a5ddf5440518980b4d8023d6 - arm-trusted-firmware/lib/libc/strrchr.c 1a98830ccfe805a879a87ff7eb90306cb197e72d - arm-trusted-firmware/lib/libc/strcmp.c 315e4d792f50e1a2f37ec14616fb2aaeaa866ae8 - arm-trusted-firmware/lib/libc/strncmp.c 8cd93cb80d43bbeeabb3a74bdc1e89d4e0821e6e - arm-trusted-firmware/lib/libc/printf.c 57ac7674f717f57cdd099f4ac2b3be174f71bdda - arm-trusted-firmware/lib/libc/assert.c 82032c79de7b24a84341c8bd5d72baba75337f1e - arm-trusted-firmware/lib/libc/strtoull.c be9487ae2df331c4b6d1e8eb831fe36f80300829 - arm-trusted-firmware/lib/libc/strlcpy.c 44c32455e06c8ee38e1d4774fa8f70de1d9e3f00 - arm-trusted-firmware/lib/libc/memcmp.c e99c723c3292973758d597558fd929976df82eff - arm-trusted-firmware/lib/libc/strlen.c e7eb31dbd9893d98f8ab6cbef6a11143aa052581 - arm-trusted-firmware/lib/libc/strtok.c 0a99e4e59337ea7c2c2fe6dd428552019fc1f053 - arm-trusted-firmware/lib/libc/memset.c cf851bb6ce469797f295f4789ce50110b175893f - arm-trusted-firmware/lib/libc/memcpy.c 0e2d7fd7063f4e253b3719a95edcfeb99d34044d - arm-trusted-firmware/lib/libc/putchar.c 6d62f8972d334e9b7016abfa5fd60039fd045392 - arm-trusted-firmware/lib/libc/strlcat.c e68d6a0053ae9810517f220d26386a2ae6290766 - arm-trusted-firmware/lib/libc/exit.c 2e041624618747b95a70ac92007814f04d42907c - arm-trusted-firmware/lib/libc/strchr.c a1876df5c0fef0a62bc57d6a13bab2234ad7b1ea - arm-trusted-firmware/lib/libc/memmove.c 045917a873ae9e6ad3f96e3d127eb474b0f0baf9 - arm-trusted-firmware/lib/libc/puts.c 8c9668a348c3ffbe4509aa2246941450a7b0de00 - arm-trusted-firmware/lib/libc/strtoll.c fd7697000146d99611e6aaf57e0f3856602daf6b - arm-trusted-firmware/lib/libc/aarch64/setjmp.S 02977fbcda3d55ed39cafa721d2bd2a901f0c637 - arm-trusted-firmware/lib/libc/aarch64/memset.S 75786d0b78f57474b1c6f960b2c8ecbc07ba830b - arm-trusted-firmware/lib/libc/aarch32/memset.S d317228143780c8f627a6814a3ca1ab9f1a0d69b - arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi 2a8ccec8476f0d4af01036dc6ecb636d1f2a1387 - arm-trusted-firmware/fdts/stm32mp13xf.dtsi 6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xd.dtsi 38c31e8b06ea5253a26b8393737ad72d81e1757d - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts 60954c960886d3c55a4f3e819b0ad2411afe194c - arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi 195376b3fa6a4af6db8e90af65ae62d649d506c1 - arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi abbe0e5a7c63995c207b1995649e3a6ed6b4221a - arm-trusted-firmware/fdts/stm32mp15xc.dtsi f92cb32ea29e10232721e9d596972e82444c21d2 - arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi ae59f1caa51f25a19cb7bc925c819f7b663c9ccf - arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts a6ef63af22c25465b4276c77535b30d8baaa1ea4 - arm-trusted-firmware/fdts/arm_fpga.dts d49435eb3b8dae9e0f687d74ac1343c3f6931d7b - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts a2179d252faf4859c7a7e68d3ba75a0955f53d37 - arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts 094f752c659ba4c70dae4bfdd3041ffdc45d6451 - arm-trusted-firmware/fdts/corstone700.dtsi 6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xa.dtsi 4fa3b6d4bddfb09bf8b8ac8f78bc5806a1063cf6 - arm-trusted-firmware/fdts/stm32mp157c-dk2.dts 397204dbf3a8d4f16b213cdf8810bb0c8409a3ea - arm-trusted-firmware/fdts/stm32mp151.dtsi c028d02d6d68dfd3c16c8ea9c6e247c72a911abc - arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi e61da20036fff26e3a39b09bcb92733e6c4c3743 - arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts fb6d607b811f2e027c9859345cf86eb565d31c20 - arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts 20769b04e4fa588ef10d7460a5b4a9061c70ebfa - arm-trusted-firmware/fdts/corstone700_fvp.dts ee5b8fc8401ffbd14d01f615b14a1bc2c6bc90ba - arm-trusted-firmware/fdts/stm32mp13xc.dtsi d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts 9082edd5658eb851151f8944760e3c2741fea749 - arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi 3cafe4429688d04735324b0c1ac24d6fd6df075c - arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts 910ac0ace6638b52d04843f12c3f0f521eb4f4e5 - arm-trusted-firmware/fdts/corstone700_fpga.dts d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts 7b3fc7115bcdc0c82b7a2cf02a4089f67d2402b9 - arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi 841830f5b4fb33dd8e11325e65d3e1ba854144f9 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts 4d121467e71a4bd15241201c1c23fbb169901959 - arm-trusted-firmware/fdts/a5ds.dts 09fc90f32545b712b63ea42e925122cabd78c262 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts fafc1a46bd195774df21a32f1e87a087f14e2c67 - arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi 390a6cef77d9095a9c98b9abe19eaaa6eedbdb73 - arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi c551d6d75e35b8e119cd5b31bb7d421eb5007e04 - arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi 3ebcaa602aafc62742776533b737f3eafdbcbeea - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi b724eb6fc96a68bbfe8f165c465341bbbf27bb27 - arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi 59f777f521b3de55f482d1b9623951a1dc5c0046 - arm-trusted-firmware/fdts/stm32mp157c-ev1.dts f99071420aca4da5f493b73afa3d3777206e23d7 - arm-trusted-firmware/fdts/n1sdp-single-chip.dts 901a3c633890935dc0ef5dda27689fe471371d5b - arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi 721faf693f101ff246d85ebc2d1772b555d84f20 - arm-trusted-firmware/fdts/stm32mp157c-ed1.dts 7afa8c643fcfe1d0d506c90c0ab7ced868c73040 - arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi 44c1cab21fcc9907b2d084dbac303eff0dfa00b3 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts ddb3d9266ce77ac3e0746820b562a07f35eafb01 - arm-trusted-firmware/fdts/n1sdp.dtsi 122430dfffc3d549a6991bc3154850d76b80c2bb - arm-trusted-firmware/fdts/stm32mp157a-dk1.dts 5061d53c21f2dec61bb9fb74fac882b6142d8931 - arm-trusted-firmware/fdts/juno-ethosn.dtsi d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts 44c646e57eb44bcfd7927514911f6cefb465cb23 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts 79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts a61a77e18f14a9ba0916b5d0c1d4c7b0e07d1441 - arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi 0e25cc4f38da64563038297dac19b2cc042284f8 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi 10bae29f18be4785b789ca4c08398643163c76be - arm-trusted-firmware/fdts/cot_descriptors.dtsi dd88ca9bc617b6bb318f6b74c35655db6ecff39d - arm-trusted-firmware/fdts/stm32mp135f-dk.dts 2d9983ae7b41417977f671f99eec7d6c8f5a99be - arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi c1a285215a44ab5a76667a51c9a7d2ce06e50659 - arm-trusted-firmware/fdts/morello.dtsi 394dc09a932c8f74fe7aff7d429da06d4bd07878 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts c1d24ce6492d52d78484c4b3cf9d2466dbf9c0b0 - arm-trusted-firmware/fdts/stm32mp157.dtsi f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts c49dfbfab50db6d0014130e8d213b6a8113c9525 - arm-trusted-firmware/fdts/stm32mp153.dtsi d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts 0fec14d4dc8c75bbdea73be1457f5ed47458cb9a - arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts ec214ebb9287a791def27fb1b8d74fceb843657f - arm-trusted-firmware/fdts/stm32mp135.dtsi 992348633a6518e2d0464e4afe90c22c87a617a6 - arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi dc0b8b61bededc06878dfb1e763b36611ea2382a - arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi 3340a6810424caf1eeec960dce9e7f673eca4150 - arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts fdc05334cd630b63cf2fd11add62d6580489d832 - arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi d9fadc7223cf3f5db0bfb1f4830e0bf0fbf138ad - arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi c078bf1220e11a54b0ae9d20bf948f1f4cb30d37 - arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi fec2d89a3727359109737596ca7c4c1165b7de38 - arm-trusted-firmware/fdts/n1sdp-multi-chip.dts dc880b2cbd39cde08860e8ebf3cb4b92bbb21748 - arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi bbe441adbb4706bbc2d792a33b888f441d489177 - arm-trusted-firmware/fdts/juno.dts c67b47c8582f0a092e22ed701f7ad5d9469dd6b4 - arm-trusted-firmware/fdts/fvp-defs.dtsi d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts ee1bb06de6ee0eba0fe695f5c7f9dbc12abb6f3e - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi 9ba3e2b8e2ffe38d252977d731187a52eac72c6b - arm-trusted-firmware/fdts/stm32mp133.dtsi dbed6c5c0e011af658818b570feee9c093e65a26 - arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts d72046fed6d7327744da75b395f335791022bfc4 - arm-trusted-firmware/fdts/morello-fvp.dts 708bcdeda398c49482ebc2c3bf4b25f2c71a1e3a - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts 2f05be7afa52d4db4c62e213a91e5efc3908193a - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts 3b4d8cfb55f06ed3418c0539f4d5d2bc33168635 - arm-trusted-firmware/fdts/stm32mp131.dtsi d6f0de7f00f3c5d3fc07703cda887ee3d8ea1d2e - arm-trusted-firmware/fdts/tc.dts 6c3fed10148b793fe9f9c4f44b878ccc12d99c3e - arm-trusted-firmware/fdts/morello-soc.dts 79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts 5d5ddb74e5499f300b5d1800520a4651078d347b - arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts ee87af83d314b14a8d8a41acb7fa47c97f7dda56 - arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c d66ad3c8e97d38face17234980203ac71836e11f - arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c 6883483605723caec745103ffaafc790ec284c8d - arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c 294a1e169dc8c2e940e56cad57a08e5d4adb3b9f - arm-trusted-firmware/tools/nxp/create_pbl/Makefile 2ec990b299f9fd69d0e0a85e98faba9055f56bab - arm-trusted-firmware/tools/nxp/create_pbl/README 621d8ec57a445f0149ebb8b216ef913ed05f8754 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h 46fb0f5a24245e631af2a4690c0d7202204c0e54 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h 3d16696dce452bf99b18bdd1a964fe7ad191477b - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h f328e450c8ae941e8109578f1721860acbfafbbe - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c 506a53ab2e813a5ce578765b25e1e3fe0f1e643e - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c 4065b3a492865b1f4525586a648df384bf7c961a - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c 12473d63d565d1782e4e3273a27c29c04adaf86f - arm-trusted-firmware/tools/amlogic/doimage.c 58ef2523c26b02365fb70cb1cebc29cba026be23 - arm-trusted-firmware/tools/amlogic/Makefile 495a7786c563fdb9134410b75a95c3e1c3149eb3 - arm-trusted-firmware/tools/memory/print_memory_map.py 30931543e94deea26c28007433bf6d837f1839aa - arm-trusted-firmware/tools/fiptool/tbbr_config.h 6dcc9e2c01e4d8e4c0b531154c0598192ba190c7 - arm-trusted-firmware/tools/fiptool/fiptool_platform.h 12207fca29ab69b8fccc71ef7a95f9d551ec744f - arm-trusted-firmware/tools/fiptool/win_posix.c 02dcc44205d31ccd5e69fd5008848cebfa14b775 - arm-trusted-firmware/tools/fiptool/tbbr_config.c 2b824a81f75e43fe0eb8f52e822974093ad0f246 - arm-trusted-firmware/tools/fiptool/fiptool d47913d50cdf551a4f0677629c59c1464b96f606 - arm-trusted-firmware/tools/fiptool/Makefile.msvc 022ce17862a03fb1b68881c15cc964cd56706532 - arm-trusted-firmware/tools/fiptool/Makefile 158eb04fba82028aacc8b3cc3884314b37d8a862 - arm-trusted-firmware/tools/fiptool/fiptool.c ff33081f63178813dd9c9235d17538954c29d7c6 - arm-trusted-firmware/tools/fiptool/fiptool.h 323e507fdf87c7d4a94d0bbbaa72bd905c2d641d - arm-trusted-firmware/tools/fiptool/win_posix.h 638ff14128d59a95756979954071615bb74eb3c4 - arm-trusted-firmware/tools/cert_create/Makefile 491ae06a09039151d3d2fbccaf89bf4de779dd5a - arm-trusted-firmware/tools/cert_create/include/ext.h 843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/cert_create/include/debug.h 0a307fbdd842fe9ae8212a2362b356addf0a38df - arm-trusted-firmware/tools/cert_create/include/sha.h 26baf6654b744217670bc74a0372533b7a9347d9 - arm-trusted-firmware/tools/cert_create/include/key.h f5c9fe91b01c2e36483376d6f0ef0c2794343406 - arm-trusted-firmware/tools/cert_create/include/cert.h 134c6c14b6a384f0e036827b128d4adf08612d9a - arm-trusted-firmware/tools/cert_create/include/cmd_opt.h 596785e69869c848d5fdb306b8084f282876abe7 - arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h 728ba9b1bbfe33e0ca3e33eb166f04922947e3e3 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h a015fcfd89d3e63781911e5134884343975d6284 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h 0c696ba78f7d568469b58576262a035b3074ae67 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h 1188485867e47cb5d105325c1736aafc8f6b0073 - arm-trusted-firmware/tools/cert_create/src/sha.c ba404574148313fc2ff134ae8bf798150a5cd0d5 - arm-trusted-firmware/tools/cert_create/src/cert.c 82813403f6e7250a54d55d8c1409be0c9c3538e0 - arm-trusted-firmware/tools/cert_create/src/ext.c a485a01a7aa89b241a4a2b28b2fbe50c469d51c4 - arm-trusted-firmware/tools/cert_create/src/main.c 29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/cert_create/src/cmd_opt.c 718afca8b5d04a3f76605646abacc1e597be801b - arm-trusted-firmware/tools/cert_create/src/key.c 87b7868a92308d1b74bbf003f8fb00f89c405d2c - arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c a71f6edc951824d84282d7f0262e1ebd260a5a38 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c c5571efb1999abfd481ddccdf9cfa8db65d5e440 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c 11fe1d417bcbf3a47d588f48d738d47a156b9c49 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c 1474476f05acda23a8bb1e859fcc314baf5a4fda - arm-trusted-firmware/tools/stm32image/Makefile 75e7e633ff5fcf6dca970eef0c2acd786d23f188 - arm-trusted-firmware/tools/stm32image/stm32image.c 9bdff25d946a2c61d8312e1f53c49802d66d3577 - arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js e9b252cbfa9bd844023146ac38470829ac72342a - arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json 5e9ebb4c1ffaf478200ddbd8bd5bbef2b0f2d2f6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs da39a3ee5e6b4b0d3255bfef95601890afd80709 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs 99f27ae0dfb07952b2130a819e32599cfc2d78c6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs 85453d72f48122ba14bd00512fac19ef0fc42d07 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs bdd671375b10dbdabd4f1f87941d3071e275ff64 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs 1d1032e5160d84f70af7f7ab6dddaf003244f768 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs 65198bc7a494eba7c91745808f3ada1e3034659a - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs 6a4752c84a78127a0b99ece7396ae317661ac61a - arm-trusted-firmware/tools/sptool/sp_mk_generator.py 37ff8b0160a90437e9b84efce7ef73833b96eb39 - arm-trusted-firmware/tools/sptool/Makefile.tmk 4a137ea4eb638729bda39a72491cc6519fc26da5 - arm-trusted-firmware/tools/sptool/Makefile ee49dbe19d032c60cf3e963764253c2d808b9de5 - arm-trusted-firmware/tools/sptool/sptool.c ba6ab775fd9474718d717b35f4220e716f7b7ae6 - arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile c6acebe37afdaba95dbaf9f814eb4bba5dd989a9 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S a728eb1898ea80778d60fcf57b727f977c29ec98 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S b4ecd67c81a19d47e59f9a72dd81fc392fff3aea - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c 213e1746ba029a55b6baf19ac0d8863713811b64 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c 3d9335fb1238d08df68e2770f69a0e1bec960069 - arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile 8c2b63db003e2e330f2af95b94c2132bc2fc9725 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S 01000b7d50599a58601322b9a12174d81bd80571 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S 4085a8d4104eac744977d5ec6feacf08b8a1283a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c f51f929a6294d60d681b03dbf0f3f1fe0835fa3a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c 0ec11eeb14668d925e198fc42145f8b0fd3d02d8 - arm-trusted-firmware/tools/marvell/doimage/doimage.c 2bbefb66f05e50612c3b0d215f0bd185e076cf20 - arm-trusted-firmware/tools/marvell/doimage/Makefile f35a6333e76f3fb2bed05bad996a131317f5ac9d - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key 954bc6cdf269e0eaa9581057657a1e2bf9621f38 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key c8f9244b21f28bb382b1befed8dce13e4eae06f9 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key 8fc012a12a4398216ad6fd4b97199ccd159711e5 - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg 8602871bb27d59d5b5ce180448e1ceb232027bad - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key f848ecb51058182d4c908f7c9a88561dbdce34bd - arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key 5b6535dd6c94832d3113588ea938b9526b06b0fc - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg 105f766aba0c8abdca2e88e258a34b28a656edd4 - arm-trusted-firmware/tools/encrypt_fw/Makefile f37ed62897799b6165569c0842904eb6fe5d21d5 - arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h 843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/encrypt_fw/include/debug.h 08dcc81abf0dd5a951f1d7cb36e2d05628055bec - arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h 5093ed93e150e683b735ad26979460536e2419f3 - arm-trusted-firmware/tools/encrypt_fw/src/main.c 93d36734d229d79068472d13bb173cb9b1537d9d - arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c 29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c 7c0bab3200267e448b5ee45b83104d2923cc17c8 - arm-trusted-firmware/plat/xilinx/common/ipi.c 05d21184a6dd62749ada768285e6b39b3dc5a1d4 - arm-trusted-firmware/plat/xilinx/common/plat_startup.c e7cc80e40c4b2aff0799c9db4c351cf1179cf347 - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c 453e987cd3b0c17b8ae79a6a0794d4fb44adcc3f - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h f5cda3dcfb0f4452e442cc526b8178b413b5a17a - arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c 3946a8e5b6578610dbcd1b1c9bb2ac02e357fd1a - arm-trusted-firmware/plat/xilinx/common/include/ipi.h 8ccd5942908d27505a9e0d68679df731210d75ca - arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h 604b0f5de53a36f974ce1926152c895a54796482 - arm-trusted-firmware/plat/xilinx/common/include/pm_client.h c879e06a73baec6538ce2dece09ae7a976f972df - arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h 3f5242b1d910a45ff664bc128a6e749aa019592c - arm-trusted-firmware/plat/xilinx/common/include/pm_common.h 04dac5fd40da85ec2a19ccf681ff7f4b708b31bc - arm-trusted-firmware/plat/xilinx/versal/plat_versal.c d25ef41e434700921c3427ff0dac7aba4b81e1ba - arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c d959b29c70b303c44eca6045c664945b0fe74852 - arm-trusted-firmware/plat/xilinx/versal/plat_topology.c b01dcfd7b061210199bce3d5632bc39be25a89fb - arm-trusted-firmware/plat/xilinx/versal/plat_psci.c f241ecfc0ce4c6677cbaca2991578232a4c20ad7 - arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c 415d7b76162c6a447101507b3181aa7434887756 - arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c 0f5013cb9f4dd7864aec9fdc3febb4a88c603b5f - arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c 6b87bc415258116316a3b89d124ff4be9d5fd944 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S 14340733608cc8031286a97ddc48222bc0ae7bb5 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c cb6dce6031f613ae2ad69be266bc3eb2a5095a0d - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h cfb673b998f65ad17832a2c1f376daa4ab836ebd - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c 939082dd0654e1c9d5097e4b088ada2eefc3cc46 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c 67797b5d7b79d4fe75c894faa289f6d4deac5929 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h 6aca4366f91416b1541836b7a999ff0873c61e53 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c a984b65e29e3ddb17d3c124890861519e0a53788 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h 06ac8403ef4a152a6d5257c08766c878afc2c3e2 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h 3efa1f0d849fb9568699ae3cc5e7cf111f1b8158 - arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h 34e333d135956229875de69051e5d541a789cb2d - arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h d43cd481e9d0acc960fc0f51fbeb274b0ec28712 - arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S 50268618a09434af24c4a339c20a1b7b4a2e4901 - arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h f22539e2e0c54efb87ad926699ecb40a60fb024d - arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h 23d939fae06d7a162821162cec379264613379ad - arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h 91da7e2e2aedb93811b290946f5b62a4b99a6e6e - arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c eed49df98140b8681bbbff7a1c514734c884b8aa - arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c fc6886e5619aabaff7153e268ba005d385a73e3a - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c fdef05d43dd39fc9b4d18e7933fadc3d7b388c0b - arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c e5c72cd4f7db3ba2c52afa5ea2a6f81048fa8876 - arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c 614b7c2d4fab5909e7df0076f873699e84b1737a - arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c 4018dd905c37ab4e205c88450ef0d6b0a1d45041 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c 9eafad8129f35d9d02d9cc93d60e653c41e3b321 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c e9430970a771c9add648211e2c05e63b0b2bf71b - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c bca57ae928a46e00c62d44205c7238c103d89723 - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S cd3edf132c54e7b51bf04235b10d9de35394acda - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c e1e42c17e346cb2bdd9bcedf9491e65dcf5a101f - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h 6a34f58d5ec913711c12c58c945dfa18659b999a - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h 4738dfbb7a3a9789e0e520c2d4c7f83b635e3e9b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h 7bfba4ae2b47e068f8f5ed8aeed42daad00743c8 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c 4b8489810a7c5bd8524f87d7c37edf02b747ab48 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c 620a7d35e7cfe3a416c79ab84094934f41b3821e - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c 4cadaaf7eb5f5f047bac44095d19052727b55a02 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c d55e25c027a7950b3a7d34551ba2af0a05e70ac4 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c 63045bc978271095cfdd4cb91e9d2c3d416cdb6b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h d6d44bea498c26d61f58d11284635f45c0d747fa - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h 4a69759072ab900e304081d6a5542761b628115d - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h 04358429a766678c1ea60bc976430714db3fac40 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h 8ede155c56692751835019579474fd5fbda5ba26 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S 6d98421b38c7e24ec53977e85b4776275af5d9c5 - arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h 719fc3fa9d14be22cfb4a79dd8838b27fef9f247 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h fcc8c8052c715326e932fd7e210fe0beefa2d175 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h 606bd0aedd3a81bf175ef81f028eae35e7511725 - arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h f82a0ba91d921f8782dbacd326cf93f93d406ff3 - arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c 2c5220969ad934f5e3904f8b72774332826fb89d - arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S fdb986fc3069c5b8c185c58c199bc5e56a6d1655 - arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S cb4accb6830f44fe050021fd6e32cca1a8acf7ee - arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c d736c2075e7e15a400e61a1db310a4d1b43bffd2 - arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c 475644583f7d46ef814913dcdcfddfa706f9f9bb - arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c 7159132c839b1d3568d7b7b03da30f6d03e5336e - arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c 98e57da5931c557522da93cce9fe3bfb911d2cb0 - arm-trusted-firmware/plat/nxp/common/setup/ls_err.c 6694d9cc9520a800f00a344d9cc1c534b6e88d91 - arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c e0dfec4c8847e15aeb7a774844188ab382bdd027 - arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c 91c2c52722651995a236e3f10e11504b1d87e098 - arm-trusted-firmware/plat/nxp/common/setup/ls_common.c 8094976b2b7aa5bbc113bbc852215f8e0513c202 - arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c 52c5991d0ead354cd375910f00aefc81953d5681 - arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h c8d60b0a7cea607dac9dc88673f41a4be9285d2e - arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S 9e4c6090807eed8550b5e6acaf048f870d04011b - arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h 4f9b26944e2ce37da586a62bdec3d03549edca60 - arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h 7deb5f8e4cedbb8f2f2faed66426dac4607d7f04 - arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h 6edca4ab32d5c19db4706b176997f9bc4f085702 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h ac50f0a2929a3c77c87203013245a30bab6a20b2 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c 3b5918338beab36f0f06c2b7e82c7f49a7b351bf - arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c 11b25502ea937dd88b3986d358aad3eff9f39c71 - arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S 187a0bff6625818b129b5ab42039158f8126ddb3 - arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h 08360ed6a8b3d051a5cad1cb6e001cf1600b7ac8 - arm-trusted-firmware/plat/nxp/common/ocram/ocram.h 5e45989256d4cb803eb129882666969d3d952ac6 - arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S f71b1c56189f5904469d9e69c7b5206a4bd12454 - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c 48b1c6e031a18037fbc338e8d3f6d0efbe6c0eca - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h 9c72b3ecd5d5982e63db876f7dfefb7cbac10bea - arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c be62a5510efe4bb10130935015fc6c12d3b02ed4 - arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S 27f86d14fd5ce72d0aaa417b4c893049acc97e1c - arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h 3a09baff31a554c63552bd51f6adea91aa05d3c1 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h 193a96b82a70ef052d501107a7358ccca4890c12 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c 9670a30b894318a795c85e5ee63edbe979b023b6 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h 5898658243b0a5f981f4c051061be8d7f7ff3a7f - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h fc286a6d896799156121d56095076ee1765cdd18 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h e41af019a383e1c29f6cfe79b98e6812ee9e71e8 - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c 0f0ae89b60dfac27f5f00ac6c76a3c1fbbf30e8c - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h 96bd522ef14fb5ff8a4247a028501ef7c4367f3a - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h 97667263a954ff77c695a93ec98b767bccf035cd - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c dcfd794664af1da07e241e7f44705b02a86955bb - arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h 1c0daba5be7bb7055a56df067ffc86d62af94382 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h 962eb919fbdac8edf23f3cca5303772adc4690b0 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h 3b4e4e380dbab1bf4ad037c20f705b6e42b5d992 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h 9fecb13f267ce5c792719b3969ef19e96064d75a - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h 2941f6674d8de1d2b22c22b91db3b63996c45d80 - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h 764ceec06291ed492b81348c85ad37e77f32eb3a - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h 254c94ec21e9680a13a88c1c24d884bfb8b9479c - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c c693c689d519e4697e033a4df6e7da75ecaca5b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c 5f62419793539e6fbda55df6e2b3fa9e0b21b776 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h 492965693fd60a384d16d12de2ecd89c7f522702 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h 2e0e20e6baddb412ce97b52be66cd32d6f8f367f - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c f925bc09cf5f24b92110d8e7eb81b6948bc855b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c 0b417a1d9881a05757a25db89aa6739867cc6cff - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c 9b61ef7f7b42a7a2448ff56ef3a4dde77d0a3c6a - arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c 99de11a8e1d6aa0d67bff400dc27222a3f67bda3 - arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c 003b4e0c6ab04fb9bd51037a2c976e8e9a1e90dc - arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S 1fc45a1f2166ae38c534bcf389857b89c441c5af - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c 0f6a22f1e28fcb385608a72a297b0cbd67935113 - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def 492d3f0900343c093e718ba1816eb94bfc3931e9 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S 764c8c04a6189e6992612672f9e41abde5000248 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S a7f75b9047c373fb59a317bd6d2995d70aa0aefa - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h 3328578a5401038f068eded4991d6a403c5276b7 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h 344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c 11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h e9f8a604d5a2d30bd7a467c0b5624df132c867ee - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c 992637daa6e8a443c6f0a176079ce731d593f699 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h 9c8add03dd402a33b546ebe338030483a6e30892 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h 344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c 11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h 30d19335e7872d98487de84b2cc1cfad32bc26ad - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c d1bd24409a0956382d617f97af627e582ec04d5c - arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h b971fa529d2080fd471b3ef7ec4466a972529aee - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c 189fa51ba04371ccab55ac105b7dfe77c07f3552 - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def ed1f52b1a3d4ce48135556f32d8667c7367494d8 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S 63c93614b627d3a013d8176aa4248010115eecf0 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S 3e9660b08500144943aee803a37816f45307d66b - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S e7b379eaa610c82050a0e57c194b10a794f23d91 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h f53ad9b2677286b07fdbc25c8c257e4891f15607 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c 0fe0002fb83ef9fcbbed68caa9cea3b775bfc529 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h 764850c7f4814c83fc8b48d4a353c5ae2836edf6 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c 353f72fa699efe7dc63602a04a220dd43adb85ba - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h 2881529cc073176412af0c380690bab77add20c5 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h d07e54f7cdb54922dac5c758dd79b5adb4d9e93f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c f856b32032e096e20ae0a454ad54d4fd64dfca0c - arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h ab191a3fce41d791a52ed732c81fa4c127537b13 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h 6701efe4878d9b4a7d1035d7d747426951d04e8b - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h 85eb1ecc310643c5e3edb3761897745f5f4eaa6a - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h e8ecd59dc257f4918515a132b0c4787bc1890021 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c 07fb6c57566e19aa44ef34559874dfd995b582b6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c 059b1c4ea6e6b540b7b01bdeb7153b4dfcacdb1b - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def b132e33ac02b41bfdd0b2ba27b1e5432e0f7ef08 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S 18db50ef3d11821179318d84b45c532d3b107226 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S 2e5c9db35f0a8446aa2a2a08f75f1488255df745 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h 60033abedd63947cfda10bf00d77951046e244c2 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h 859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c 802c1d23237eb5cc83388950a75fa13d076b0dbf - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h 2d532dcfca962bd50e2721dc90a3c5e8f3ef4c00 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c 69427e6f64ce96dfa6842364a758359b8fa821c6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h 9b815992ca7df805a51a7cdece2e7c074a0958fb - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h 7101b940d392636f546086caa2626d9a940d9eac - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c 490b7dbb3b819d5251283d9069f177092c665489 - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def 033fd89d203e44c446aba6134e51e46a7d9cf324 - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S e436d0bfcc7b7c83db0242b6ffefad0a2985a81e - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b435bed7113e72930be88bfe8f61e7da61994418 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h 264c5f8c566b8945850048aceba967dd8fd1e72b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h 859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c daffee032773c1420ec3c8da52a5bc9db4610aaa - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h 3268f346c7eb1578007b13a160c4c3d08efe2c0b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c d78024dda44030bb2c60a6c6f0f31b0cdf79c510 - arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h 8539e94b825c242859fa5c4a3c03901703c386f0 - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c 1e814209bd02d7457755dcf4493b05a3794c811c - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def 8cc150d9e1c9199572b24d0af559c82e4db71320 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S 06d4dda248389e306ea0cf1688bc9944d1511d03 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S 0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h 686ad098c68cbf424bb3e89e451ab64b8183a91c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h 5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c 0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h 2ea7db20f6633e1dbecd9a70ed4cac89d97c2a76 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c 0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h 39ce8f1f0afc76a2d1a98e86df076ef84d185da3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h 5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c 0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h 60e78557693ed12515227f051b8f55baf47ce8ae - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c 0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h dc407d2ead98e6d20e59ac0b6c5e75116a82ddd3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h 5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c 0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h 945ec23ee2ba0c79a5e6140d043290e9afde9b2c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c bfdacfdea0aa10e1ece5ae2925625ce34328672a - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h 9ed3d544ff5ab2cfa0ea13d1fb3b59534eb90e14 - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h 1e1f92bc6f801c91fde3bbe4ce99b62beb0eb7d2 - arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c 42143dbacac34a118b7b86673774e843e7e84fd8 - arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h 1e876f487cd25f4a6cd08d0a21926f5405676a07 - arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c 1b13f9e313e75353b45d6528629485488b180345 - arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h 8403135be33e11a4b696e90b5b253465b6838682 - arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S 81ea2015e04bbc53b7d42589a21821a183fc1c8a - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c 3bba3282b340c9896990c2ffcbf10d5bfb0070b2 - arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S 4d406209e8b278e9730968baee57f5106d424aef - arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c 7b5d73ec9d9c7e14fd48653c6e018d432654101d - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c bffe5bd7851f8d028c92d9d68dba7806be5bd662 - arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c 10003f2e608d5073c076ab1a446f4ba07c06086d - arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h d4e968db5e699bc36032dfe35d7fada27142c699 - arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h 1027e5173d316fd6d9dd6588b9666b53ed9d1116 - arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h 9026b30dd1244e0fa2416dac0e9f2b92c11bc83e - arm-trusted-firmware/plat/imx/common/lpuart_console.S 829a4463f8628c61fcb335a0dbd747a6050c8192 - arm-trusted-firmware/plat/imx/common/imx_sip_svc.c 03ff82e03dc9eb60e02c6e23f0c199fdd1753c9c - arm-trusted-firmware/plat/imx/common/imx_aips.c 83187f1c90615deae51e2febc0506394e8d4d444 - arm-trusted-firmware/plat/imx/common/imx_sip_handler.c c014188b6f4a48f9dc6d6fed678081f02f8d8e86 - arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c e03b60801f58711597b0bb457ecf6e3e84c9f44e - arm-trusted-firmware/plat/imx/common/imx8_psci.c 5225b741c941cba9f489d347aae2707d99896d7d - arm-trusted-firmware/plat/imx/common/imx_csu.c 1901b0c4a5e19926a9e1b5ae437ebbeb0dc0d181 - arm-trusted-firmware/plat/imx/common/imx7_clock.c ad339798ed1c81b2dfda72cc1cefaae7acb622d9 - arm-trusted-firmware/plat/imx/common/imx_io_storage.c e7ef15bdf83a7d4e3ca78dd0d0e9daf56414e55e - arm-trusted-firmware/plat/imx/common/imx_caam.c f30799014ffd50a32b0d021473b50cf5c4a28634 - arm-trusted-firmware/plat/imx/common/imx_clock.c da4b81f475ec53f2578ba031cd1f30f759bc5dde - arm-trusted-firmware/plat/imx/common/imx_snvs.c 1b219401b9b5eb5bd8c83fa92fc68c591d48a3da - arm-trusted-firmware/plat/imx/common/imx_io_mux.c b26cdffd75a0ba04b4a312520443d0c77b388242 - arm-trusted-firmware/plat/imx/common/imx8_topology.c 97029bcef11b7a8598834c9717cec7a5655b895a - arm-trusted-firmware/plat/imx/common/imx8_helpers.S 561b0822ac98206dceac588b536d745fc70829d9 - arm-trusted-firmware/plat/imx/common/imx_ehf.c 6ac985911e7e26d13c75d48a04457fbcb209b62f - arm-trusted-firmware/plat/imx/common/imx_sdei.c ac923dd7af0d3485eceae86115ea73150575ac4f - arm-trusted-firmware/plat/imx/common/imx_wdog.c d93d2cf3c9aafc65833374f51376f03bc2387ecd - arm-trusted-firmware/plat/imx/common/imx_uart_console.S 36d5f07566aad340b6ec06b01cfbe631023ca7f5 - arm-trusted-firmware/plat/imx/common/include/imx_wdog.h a3a14f38cbc846da3bc2498cf8e07b62479aa62a - arm-trusted-firmware/plat/imx/common/include/imx_snvs.h 8830c18819f942388c5badcb2c19eaea2ae058dd - arm-trusted-firmware/plat/imx/common/include/imx_caam.h 0b633d6b19c3fd7cb43c433d74b84ede423bab4f - arm-trusted-firmware/plat/imx/common/include/imx_hab.h 8ae002187ace1e1358c7af1e06ef7957179939f5 - arm-trusted-firmware/plat/imx/common/include/plat_macros.S bddfe7c6dc079e9f45c4a41601888d27f5d29c48 - arm-trusted-firmware/plat/imx/common/include/imx_csu.h 28b31b74552131c2ba5875fb7db44b22ca16b722 - arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h 2e84528c7d6b12beb2c64505a14d73bcfb03ef87 - arm-trusted-firmware/plat/imx/common/include/imx_aips.h a5fcaffa0e69f234b0620f32d3556bf79ace50f1 - arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h 816bfc02478ff083b5f3557753a4d0d4f2f32c9e - arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h b9d688fac07189d434ac636324a632e9bf78825c - arm-trusted-firmware/plat/imx/common/include/imx_clock.h f5724b26de0d68b4b37e1d580c6e30842eacd6c0 - arm-trusted-firmware/plat/imx/common/include/plat_imx8.h efda9e3617b99df89057880a566725ab2a7be20d - arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h 24f8d34fd7865c2235d12e87791c7ae77d55d281 - arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h 6f89a14dc12ddacabad367a7e69d8bf469274ec4 - arm-trusted-firmware/plat/imx/common/include/imx_uart.h 1d847530cd83143e4a50b94c5499ee8c11f9d3e1 - arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h 8a65436d5e0b335e9003a30f2da5f7892d23dc05 - arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h f6e6cd4d5b145f5abd0aa4d840fd7757d4b02c04 - arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h 19674e70669fa3f7fb7e509377e445f7fd4c7be4 - arm-trusted-firmware/plat/imx/common/include/sci/sci.h cc9366b07e946d7946bdfeae628f8a6c7ac3bed3 - arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h daeb14deb7c4f498330bb44186346cd1ac4eef92 - arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h 70210ef96ff1f0ccd4e790bb79a148f1bf02efcc - arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h 4be7f4400810802474258ed3e4b8f7a73170db33 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h cf9e73e1a62f99ecb17abeeda5efbdad0f7b1c21 - arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h d3b138328cc81b7fe0a830b3cec8bd87f7d62835 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h 2507eeb7a0cd662322ea96553146f0f0dc8c6e45 - arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h 8169135849017c45a81b2c0447e940e3e5396145 - arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S 985fca791927ad8088399ab8840bcbcfb8277a6e - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c f2ab11050d68bdc711e7c18f9437fba728ab77bb - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h 8c98c79db7801610b0bf01e1ea680ec8347be4f2 - arm-trusted-firmware/plat/imx/common/sci/ipc.c fdc0fc24ee38df2fd92f2f039664af39724513e7 - arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c 9162637c3ad8ef97f19a264c504c58d5886f9d7c - arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h a593348ba8dcf5a3577bb48cd9d9ab7fe88c6df7 - arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c 53b961e268ec00956cf3635d8561601e5c5bf70b - arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h 65f1e12aab1c7815ccb98973525d32d30e635a1d - arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c 1dc0e610322825b6f58ac08670b99a4598bc01f1 - arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h ada89ab08a1bfb90ad5b0e5ffb325268ddbc837e - arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c 99d10095088dddbbe81826dbf7827bdc9c6bffb8 - arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h 3f381087336a847b53323f6828aa61478b46a2cc - arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h 30cf1dfdd48ef57921bbd93789aaedbebd754c55 - arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c 7bd8d4e39f1f3905630b08a16be851097fa5ab67 - arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c 10fb6753c1ece21522f45f372d0cbf3b416b5190 - arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c 51949e20cb7aee1a68f0cc5eaa46f0eb3012c2dc - arm-trusted-firmware/plat/imx/imx8m/gpc_common.c ceb0518eca09618b3b642b96d4fb43d950bdfabb - arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c 996e00079997c54373e5acb4a6f39bfe8cbe346e - arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c 3065b6071ec153725ca0d9782a393ffd3f24745d - arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c 6253f7542bd4e5a6244779068845d717f8eca3f6 - arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c ee448951c5f07c67e8c374cb6a4077c505070081 - arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c a2af87335b959f57d6de74f40740b48de27a802e - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c 461d439b6ee554e1dce2786de8e131e60083bca6 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c ff7748fc70a67a41bd452b895f531d103d0b3cfa - arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c d1fa70b45e2971a3e4103d0b2ff864ec706c5af5 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h 2db42326b731e92225ca5c389557d0b944e8d3a7 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h 3fcc366713e1667476479363fd2d0fb74144e491 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c f9007785b7de40f327bd11a83c710c297b45e4ab - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c 060756d07ff95fa2e15ef2cab742c6f6fdfdc5e3 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S 5e7971c14f77e2f2450badad4a156ca33a9eb89f - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c a3afe5951fdd7ba0d6e5b64214a2183800a80132 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c 0e0933de6793e323f4c77e12a89455776a0dfe57 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c 1bb0ea0358213dbd45eb953fdbb45234606078d0 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c 0f9e1a9d6497a3ad4e415d483905f2ef16aaa423 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h 4a704d5f5cc4958ad509fe9771d30d6632cb1a0a - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h c81f2809571226d121ea1917bdbfe06afcd9b523 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h e7ded5d1571dcf2246b5480dea7517bbc0e45a87 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c 629b2fa411eef0f016ff98ec22caee2012cdf650 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c d50646f42ed68bca258b692593812b18c635dbb0 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c 82259d3c2b7d974ad94a42c37f37e0a8f0ce576f - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h a6e3b2e69300fabcd3a505525cc5d48d88345f7a - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h 47de7cdf356158f2b651bafb8659187db3a13e65 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h 4bc0eb69bf40f2ac07200a788f79ad6e9ec8b3f2 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h dbc9dbdd5e6269f4f08553a771a33f13a1fa884a - arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h 3bc736f072705dfa2d00383fe60d8497b3676fcc - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h a70728dd56a39269eebea0b5d96e9e82765e1e7a - arm-trusted-firmware/plat/imx/imx8m/include/gpc.h 5ec5413514abe79264b0bed81c75f811d2621d46 - arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h 0efee336c964d1973fec201980455aee08396081 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c be1935709a939c0480bc4cc27058482508f2596b - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c f822b4b589b5d418d0ea960b764bd311a32466ea - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c 49f3d2caa5e653fc6cdd99c140ff61ad9d83c9c0 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c 3d38c99169530f67aeba8526bd7cd4559981a349 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c 169ab98f3d4cd7620ffef0d78f7c2329be9c1586 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c 97a556f1fc780240a2ad81127c295bd39a0c6512 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S c65d55a5e1a73f615b9fe213427e4605f4b3806c - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h df0e3b50430ac47d2263ca8e0a4b83d46c8c0193 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h f7d6a1f75a510179a6e4a7084b3d70dd9bba5734 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h 399d2117be7573ef7ddc5afb0364b90fc66d9bb6 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c b9316c7a608b29b530aaf325e401e06f62647525 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c 06458d5a3b748df586e9ba2064614354842c162f - arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h 5f45eb6e98ea9c90548afd5ee153f8d14c105e48 - arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h 9561f3046a19b5489e0aa9025135c8bb6a7d2582 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c 08a0687e7c3b77de90198dc7e5d8ca2ec448ae90 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c 6beb54a392291f2d54d207842b2620c7c344af8e - arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h 1fdf9dd0a1e00cee360596ce35842f77598cbf1e - arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h 54eb696ef592336053f52bc556f47122b4e94fdc - arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c 793e163b5e60486c53f3ff36c98ab1c8f144a1bd - arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c 5e76d520f8ea85f6710a605e2c9a4db0d1a66640 - arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S b1c50f058d68ea165b6dd5f45af97d2b1dd33e64 - arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S 6a73f5496572d65332bbf4a50c3c9d4faa9af438 - arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h e2412e3cbdcc8daaecfab85f295ee3456cf1f98d - arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h 4d8d91a23a19a15ff7c18f8e6e523c26cd453f2f - arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S 11c87bf8a084123bf9a431cc289a66e23112bade - arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S e621f46501a2d1856f297145947d1c8d89d5f990 - arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c d2d1fd0fffc8a200fd42f1b74c8c7d54c483f219 - arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c 41feb9d914df818ac88209ee1569e1701d794248 - arm-trusted-firmware/plat/rpi/common/rpi3_common.c 46c13e3cff3d9c29a733d01629589bd31b37eb5e - arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c dc79372e77a81c53ff2886832f206db2f63873b7 - arm-trusted-firmware/plat/rpi/common/rpi3_topology.c 854bc00d3c5fce60726920c1e5b1b7cd9352568a - arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c 2880e20e8241800797f95dadcd5a206d82ba45ed - arm-trusted-firmware/plat/rpi/common/rpi3_pm.c d2456dd752e5376ca6049639fe93ef04bd5aa04f - arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S c3a79cfd4e400e0a2dfa7ee5e27e50f1bcd8464b - arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h fd5000ab9d2eac8341e267b879e1ef29eaebf5d7 - arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c 052815ff6a9d47f47e57d320313a74f10c8a34d3 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c 20b2e08539e950f86d86538ed688408f90574454 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c d9b070fbdda2cab75cc45e6dddd9a31f84baf594 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c 5a79ec05194636d3850044f358b4673a3f0b9fa0 - arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c 64987d2484ce3d48cc4431fee2de9e375235bb5a - arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S 7aeb3415e697151619997c1c184f380eb310be78 - arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h 94001fd4bfa1b8e08f4d51f437c7b006362f24fd - arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h c2785b4c0937862f1abb7251642a4028a913504d - arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c 2514153e63bbcc5513712db8766fd278fa3b0d44 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h 3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h 0b8b7ce5f06e24ad7b853125e17507934dfc45e5 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h 1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h 704da3ea1b61d5106a6172712ecf6a80b1528bf0 - arm-trusted-firmware/plat/allwinner/common/arisc_off.S e602a60b0fabfe8e91ecf654c16701712b20c3f1 - arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c a5e148901e32cb7feaef9ffbd00f43a2a661ea0c - arm-trusted-firmware/plat/allwinner/common/sunxi_common.c a7dce777afe91e3a8d68aaa84d55530a9b3b66b4 - arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c 385e3bbf7c85ef4e96b553e0f9760bfef1e94a3a - arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c f2bc1957fa87b9880744d070c964b7803c7bf295 - arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c b832fd1c1d7bc307d2c3698bf00ee15b93de8cb8 - arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c a9a0eca6a5cca079ee8007e0afa7f0ffd7a0cf1c - arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c 0ded87657ff47f0fe5896f1ab1d6d2f9b34f0429 - arm-trusted-firmware/plat/allwinner/common/plat_helpers.S a44feb979fffb71189cf9943a6d99946305122e2 - arm-trusted-firmware/plat/allwinner/common/sunxi_security.c 711ef06aa592d857ab47ecd0a9b7870c6fa1a5da - arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h 7d746a44b6a3bbaa1c3e923de0abdfc40393712e - arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S 77455765d6d80bf4a48d7744bf6f4770b7369215 - arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h cc00c1c7f46a2a8af976c1c0fb59681803b68d1c - arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h 4333584318d0a967851853f5fcd6c5287277246c - arm-trusted-firmware/plat/allwinner/common/include/platform_def.h 3fa3a563994fcf2710324634950265fc8f9d7850 - arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c d430caf710295e9e77a240b785740fdde6705e26 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h 1acbdb220cff8edffa7cc7fd4808f71574b90966 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h f8fae43c9902bbf818480c6633e05fc6b751aabd - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h 2870bd5728ae0e5857fadde22b048a6fcf6ee2d3 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h a38730b258e2c37f114fdb3c923369bade8e7a1a - arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c 54ee3b911a552e2cd6e3802820f5cf3e09575a01 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h 3f4f908a2f0a6a7660d40d79215077ee248f740e - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h 2c5ad97e48086e62d1d58d1d8289ac4ab3153179 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h a462f612d127344fc711a68e3751b31b2b7ce938 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h 65eec287284371a887adc4c9aa1952c26be66df7 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h 786942614a650ccd6930f2bd19bb42b2b539e1f9 - arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c d9eff8a29c53d38215c1d261922df8494c88d5aa - arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c 2b80f35aa1746d608c2eac4eec351c292e0298f0 - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h 3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h 0ba24eb82465b3d3ad4e293692984b972663d57c - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h 1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h 1c810633809eed169ef7ae47da01b6326b111a64 - arm-trusted-firmware/plat/amlogic/common/aml_console.c 887d16c962bbfdec5ddb366c33ffec0ad5697447 - arm-trusted-firmware/plat/amlogic/common/aml_thermal.c f1168dcf0c90f4d7a3456d82b909e287a16875ed - arm-trusted-firmware/plat/amlogic/common/aml_topology.c 1b86970e6e211ba1548f3469a4682db7c31577f1 - arm-trusted-firmware/plat/amlogic/common/aml_mhu.c fa91c2d51bbe34be89ba41e055f4e78eba6ac67e - arm-trusted-firmware/plat/amlogic/common/aml_efuse.c 2321fbf75d8e96d90a1b6f6a14160c91b949cabc - arm-trusted-firmware/plat/amlogic/common/aml_scpi.c 22fc306f5f9b6613312023233481baaf99493614 - arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c 61752908966c74b637938d2fa11e73c5d5373d9d - arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S 74bc476713af13ff5ee94c7bdad6c5763f99e9af - arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S 5240bdc42061a821a089cae1eeca3fb799e6aa1c - arm-trusted-firmware/plat/amlogic/common/include/aml_private.h 5ce07f2865d514a3a8979c638337a338fa110f74 - arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c 68a18488494ea52a108462ec30b6833447e75e62 - arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h 550ec6753c2e8a5f41a920ea9bfffec47ae78dc8 - arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c 8b93edbe34b51b737299797607de4e6ff0003917 - arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c 22603b51918b7c1f721eee33d26629b16cff6683 - arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h fe8712d8d4a3787c6c2456ffcc2cc468b12bfd7e - arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c 495f096204283e82b03abed56414e3d1a29f9b6f - arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h 03a70925292deabd473bf5ffcd0d0d95dd70456e - arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c 28726387d3750ce4724f9147e5e173131ee7164f - arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c 8e1154709ae343cd8d783739b29005ea2b9a7c7f - arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h 3389361e87f5cd5e4f7e606599032c3aa3a41b72 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h 704885551348b4b44d9b7b092aafc3c54533b7e0 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c 25d4db1b1e385a2e45f4ffea43edbfc8bf4fef89 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c 80fbc4757d8f389dc885b90a5eef8c0c4f6e23c2 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c d558f98c64955249d21b9227149b68808cb3e358 - arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h 7fdb79ffddbe1ee7f1b2c543a1eaa07f2671a2ca - arm-trusted-firmware/plat/amlogic/axg/axg_pm.c c60f26b9eb14d703065a758062f9c76e4e70f8ed - arm-trusted-firmware/plat/amlogic/axg/axg_def.h 3667781fa0058dcdd1cff5587b45c798978c7966 - arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c d3c822e681ab6d5016ae06adb88ca9aeb6073aba - arm-trusted-firmware/plat/amlogic/axg/axg_common.c faf31bdcea206b83c40fbe2d878c14fa8327a37a - arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h 5e22516412e81af7bbc52e0e460447cf2d1d63f3 - arm-trusted-firmware/plat/common/plat_log_common.c cd74e2d1ac7f09f4ced54eecf4bed38f973bbdfb - arm-trusted-firmware/plat/common/plat_gicv3.c c7afb73f40f0759cd775aec59723f92f7dd54435 - arm-trusted-firmware/plat/common/plat_bl1_common.c ebb8418a3c0ba1d0d9362005c17fc4a3fb03cf1f - arm-trusted-firmware/plat/common/plat_gicv2.c dd38f3a1079a17328d48c8cb719713d4de7361a6 - arm-trusted-firmware/plat/common/ubsan.c ca3750949173b2315d20907e7c6da4a66f32a5cf - arm-trusted-firmware/plat/common/plat_bl_common.c 8020a28923a271101b29516f4997bb7a1b8a6708 - arm-trusted-firmware/plat/common/plat_spmd_manifest.c ec9195d2ba3b66b6f4258c18a36b14a5cf41ac55 - arm-trusted-firmware/plat/common/plat_psci_common.c 6ae1755d17b7040c038dd8b2e6c6880e2bb60394 - arm-trusted-firmware/plat/common/aarch64/plat_common.c 8be9392135f6389b22910a9e22011c2e5abc6708 - arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S 8bf3a22931bb5a18034f1275429068834943cb9e - arm-trusted-firmware/plat/common/aarch64/plat_ehf.c 53568d8d4a43005d8a1be8a379cf0f4b7ddc5637 - arm-trusted-firmware/plat/common/aarch64/platform_helpers.S 1fe60996e262523b671b678aa41a510a2cfa2ce9 - arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S 785a7be686f124f8b30c5f96bbdc9670988f49c2 - arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S 05ebeff6ee2416ab2697799fb338367a03b0ba75 - arm-trusted-firmware/plat/common/aarch32/plat_common.c c8eab49f9d5326ffc974d2ba7c05bd411df90eb1 - arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S 01fc909940aee253c9e140248811b8c4fc5d25b4 - arm-trusted-firmware/plat/common/aarch32/platform_helpers.S f742befce701fed79ec16b324c92409b36838226 - arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c 79f7a0e7df796600cfad4b11f4bf7dbafb65a4ea - arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S 578b46ce0ccf74ba18ce1747df871537294d4ddf - arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S 36144ebe1637da9185e2256593f8aa7307d0cccb - arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c 43da4a7bd6435c6cc7d733e6363a59cacabb9ef5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.c c02bbae941528cbae0665016d62e54bfffb74444 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c 389238486613bb86c6032f788a4605c782e7475c - arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c 48faf64df1848d8493a3f273494ea883a4aafb0c - arm-trusted-firmware/plat/brcm/common/brcm_common.c 9b8db7387e47af68fc183fe909d3060d65438cb2 - arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c d083c67e189d3cd3712a827a23e28d0aaf2964d1 - arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c 02ea7c4006c2910720bf4a85c3766c293d4cb8e5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.h 2ef6d891873792dd5af17cc1091f369c0865c70d - arm-trusted-firmware/plat/brcm/common/brcm_image_load.c 6d6865834cfc5ce82506bf1ef6df2e3cb196e028 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.c 7c0af43209d486bb7d9b76b244d3fc5ec97b4328 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c 303c81103a6ebbdf9e4afc16b17d17195a5b9238 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.h 43088754fcc9a1fcbb6308988d79eca0c2771d5a - arm-trusted-firmware/plat/brcm/common/brcm_ccn.c a794cd95a890c951acc5192426abc008b4213a8f - arm-trusted-firmware/plat/brcm/board/common/chip_id.h eeff346a4c2b6893ad0fa417570e747058627c11 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h 2d3a08ac4729a455bffd5c4c70365350fec69e23 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h 779be799404c9562032c8c586f3a3b23835ad722 - arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c 801bb1cdab4baf3440ac23728e6190881af4264f - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c c0ecc823e4de1814edd6bf48321b6317c448b16d - arm-trusted-firmware/plat/brcm/board/common/sbl_util.c 2cf7d5accbb22d89a3c89c768604f667a23bef52 - arm-trusted-firmware/plat/brcm/board/common/sbl_util.h dfc2e7fae9dd66b664758412e1f4c06762246ed6 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c 5f45cc70d813bf16880f4f1f4a246ad6114fbb78 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h aaa8593ded989c77280d5a16f541eefd45c62067 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h eca89f1edcb0c3fc702ac123a55821cde16106bb - arm-trusted-firmware/plat/brcm/board/common/err.c 9eda9f547bdfb6e83ef3c8d82d849e1e4cb68252 - arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c b2a5352558dc92001c80e614a9b293a1eb19573a - arm-trusted-firmware/plat/brcm/board/common/plat_setup.c a731b4badf1cf5a90a0ab197b39a2723e4c85dd9 - arm-trusted-firmware/plat/brcm/board/common/platform_common.c 9635661f5e56e9ab172dcec943257465bf36e634 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c 500e36754a0240001fe7b400bf8d4806a06de6ee - arm-trusted-firmware/plat/brcm/board/common/timer_sync.c c124ba5ec6d9fc3e8f1f0b72d3852473ab67e998 - arm-trusted-firmware/plat/brcm/board/common/board_common.c 515e3aecc5237dcc8197e4e8ed7fd7d15765d808 - arm-trusted-firmware/plat/brcm/board/common/bcm_console.c ac2b64132debec3b54ae614c64dac69067b39291 - arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S b4637f982a40118b9d83d3908d0b189d3524bce0 - arm-trusted-firmware/plat/brcm/board/stingray/driver/plat_emmc.c 4573848f39ea4bfceb55e0932f0494af8b890d1d - arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h 7cc68c731d1d4e967a6b258c94afef74800e2c27 - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c 483849480279e54ca28e4177fea05d6bd3cd36d7 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c 1071f5589a11aaf7354868d034e149b27d48adc6 - arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c 13bbb4dc261e840997a59d4e914f071835d33fab - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c eed068af90592502021f8e15b556ae302cd8db87 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h d0dacd8fc79f78cee10bd8513550abf93624afe2 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c 46e832c20411ea4d2bcbcf1cc8968149375047f4 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h 76dbcdb10f12f01d94b3c70d2f8562b0cc8b233a - arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h a6bea74c09e847241ba6a156aff89b12670cc98b - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h 2c4acf78dfd7c25c281471b6717273ff7920fea8 - arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h 4bc4735b9e7c2a5eab8ae91a28d110dd24a42d75 - arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h eeabf0e8e4cda99b503b2ea41298aff2d87e1278 - arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h cc26d153c04427651e12bf00d19497e5bd8cb7a3 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h 1dea9a2af71a56fe60929b854a2c73220603d2be - arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h 10104d7d5d9eeeb545dea9ac306deb2c5cf46036 - arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S b0a1c672d4d7095f6e7ec5305e084cb3a29a790e - arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h bd25c5d9d7605649bc1d1dee9a734ccb130101c3 - arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h 8c57e437d9f4b2b49f005f899624af9b47121102 - arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h 90c98d478915f89433c419b06613a52965aeeef6 - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h 2817bede11ad2da4d5612a155f5a76e30b62de62 - arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h bbaec5f331d8cf8f24898a8d172190c5f7940b6a - arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h 491a5116f054df365b530dc8b09613f1178c2d8a - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h e7629876236e444ee69e40c96440f3f24b16fefe - arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h 0ef862af40a95d70feda6b8367e6e7452e90099b - arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h 2ef5c016a1130291e30fb58c1e1b397bb15a531c - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h d823df9c59408673229302e557a65ad1c404e047 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h 9765542d155d4fc37ee167eda672c6a33030ca8c - arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h 0228e24fbe8ff775ac7a709f272d375a8e7aa3bf - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h 1e67ee0873eb29816b418096b514d39c3aeb7d27 - arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h 77916c4c9e55da373b1b66dba19dfed0034cde48 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c 52a5e5247c12940390abe486ab490a1d8929feb4 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c 863c6f32899af28cd9a60fb273bdc02a29100114 - arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c 0283858faf5651d4db16f0e4b8bcaadd40bcabe1 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c d746f7070f366ac250b3766606d2de76a6192436 - arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c e9f5650def0bf0c03c50ad69056cf6ff9d71a715 - arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c d15b82eea2aaa023805036e829ee46cd08ea72ed - arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c f89deabe82fe9129f1dde3fb24e57c940e008913 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c 085cb8e4f6dd01efc01f633680e7db315718c304 - arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c 072e5bc5c72a860c50c3413898b60dd18931b100 - arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c c01d8b9f9c48a1185129c492ab1f8ce1134ed892 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c 1fd2e7122a0c63a14a64215ae5750097f050841b - arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c 062b1d173f23bc015ebb5c790f890e5f2a6934e1 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c 78d2915d5c3a6c4b75eb97c897cd4e58b4d5b962 - arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c 9b0afdae90ec3159bd428d4b9f586d84a0cb55b3 - arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c 75de08bf7cc548fc88463a459efa719ce9dae276 - arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c 16002a1a28f7ec581aae95aba10964655f89c5dc - arm-trusted-firmware/plat/qemu/common/qemu_pm.c c154631e1880ac14882cbb7ec28846bcac331126 - arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c 95a9e39672a85b16243df6db511e352e068b90ee - arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c 00fcc8b29bf97f9ede1c2dfbe40db7ef83c72695 - arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c 2085009221c46e8e62ac297e819084f4b6087615 - arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S 8ebb840a06cb6dddf6c0fd5fe4a612f832842576 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c ec654aff1a7a4e282bbbe2dc13b2042b9534eb61 - arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c d78bd11a3e46b66140586c01d9f834a788316251 - arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c 2154f29a91decb99dc45f21e790dd6e0d1da88e1 - arm-trusted-firmware/plat/qemu/common/qemu_private.h ce499ea5552f0a580d2d730cd86b20a544fb4759 - arm-trusted-firmware/plat/qemu/common/qemu_console.c fcbaa96813c363c3db4933b80039d532e1252dc7 - arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c 51d8305f79f4736a224811e549fd92ffee6e2134 - arm-trusted-firmware/plat/qemu/common/qemu_spm.c a58c658f18083c55761b946dd01b034df662dada - arm-trusted-firmware/plat/qemu/common/topology.c 854064daf74a72113baf3004985576f30ed85540 - arm-trusted-firmware/plat/qemu/common/qemu_image_load.c 3ca3d10548276087940fd7af8f274b1b68378322 - arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c 3a64a36aaab153d084cd63cb8041cb8e4554c206 - arm-trusted-firmware/plat/qemu/common/qemu_common.c 21efcb8ca3eeadb04af0ad8b5dbff0a548221482 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c b70358ad6ace724f6125a704a64bd882bb7e5e13 - arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c fe635c884df368ae689c259f9ac0787b17064bb4 - arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S f58716f140fa8f450f8073fca6f98a8eda79bbc2 - arm-trusted-firmware/plat/qemu/common/include/plat_macros.S 674a4514924db14c06277e39651b46250347d7a4 - arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S 553cd30299445b034280689989176963a39f2b4d - arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c dc0cb18de3dee5963f78466b58e002bc816d526b - arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h f2efe87ffe7cd41bf5ac442c75b40fb2593a8fbb - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c a3366d3ea9b4a5a823b365b0a4fe16dd24af7388 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h 151cea63605746875bff4fceaa296485033aa280 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c 46b611bd4d5b4370f104fdcc62cf5da040ec7970 - arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h e4e4584414cea9a632b613da62b76c3999974c0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h 006db753e22b1119a67d4f76bd213bf3de08be09 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c 30d16489f342eed522b276128737ad41acb82ba9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S 69a2371870f65a855d9ff7c728f2e9c32882aa2c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c 21ef9559c64415fef54f3373f28fde4fa86d92d3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c 2b022afd58ed2221e8abc99099867eab0c42c326 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c d342acec84b75ea4f64204404f0a54b4158920e1 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c 26621302eaceca62d3b0e8224c6c14d5ea08df38 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c 5fa3e198d6ad7a764cb058e6e88fa12a0d8ffe85 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c ab09cd5d8d3222857a607791bee8b31359314aa9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c 91e3ef5fbfd42b725b57f2608d1934a5c717de3b - arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c 516680ab29649a33ea07ffa922f3b18448e61e55 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c 05b8fac4f5d6b8cee9465b541e992f27f071fe8f - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S 7518b6009c736b543504a3f84be4cbd20e8d9f0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c eca523ec19dc113ddd19b9427a6651cd6ebe6bb3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c ad344a675d5f4bf3287a6e32451b462c3ea7d29c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S 8a0a08bd7b9292bd5b334bc91ad422838eb83118 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c 7cb14fc4ccfe79fe8ffb080b91337e263775111d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c d94b79f813abf374eef409d04968fce943a3ef84 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c 30db57b3d947cfae86d4cb1fbd7d79f7365fe01d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S dd16d7be9af0988718096ec4af552732207ad390 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c 98c1438c270db5db7bd6f971cb928420df53c1b7 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c 456820f5853d3f1676ee19bf63b9c360ed9a80a8 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c b445ddffd2167b6758d19874673ec99f3f2a1d30 - arm-trusted-firmware/plat/socionext/uniphier/uniphier.h 8bea3f2da202b83b97d9b86e32cb50d5c17cae7e - arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S e35ee40c042c15de97496be4f1d9c81b960cc3da - arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h d181839ef722d36e8a51c126deb67a2eae64c527 - arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c 72b5553a5bdc53509ecf17a4d93cbfa1e3d06c8c - arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S f43a62ef3a99346a097b8813441539c5354436fc - arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c 9b1262ca8c6950227a294b789fb3e53dfa2086b1 - arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c 8286dff95425dddb9a5b25ffda50460831781793 - arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c a32f17d7db01cfb7a14811a914ba2066581d29a1 - arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c 3db81e971dc630ca534efcd02840b2ee0fc01794 - arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c f9ac11a5c154783dbbb6fbdf6485867b754f511e - arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c b60ee8850906f76ada82b2db19c8656ed9c12d9a - arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c e431465e90b8b68ce2922ff400c2e6953eaeea9d - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c f57f50699d6a8f3902d4673f01ec3ff0d6931d29 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c f8fe95fbe1e35e8c328ec5a197b76c329feda4bd - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b6784404cec981a185e6f44ef689f28b7d9513e3 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c ebfc7926ca7e342e5cec3fed564e68be76a80fdd - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h 961c660b9e7a5641523d5d23b5396c2a2a67746e - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c 09ba9cfb7c8be52484c3cff427668fc7d2524219 - arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h 9f24e8fcbc08c61f43c8041c0464cae65fe01ce8 - arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S 25666183a169e48e144659003b018f40881b4590 - arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h ef74e9cda94f07bf3061b037195287d609c0c6b4 - arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S 09dd0d32acc68693a9cc4e6edda975b30b997a7d - arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c 4df6d997a517a03b7120733e3ff6f1a2634caa47 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c 077745456537a78c6a462ecaf23835c3ac381a92 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c 5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c 43b6cb88b4528db3610c0591b417afee9f8e086f - arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c 942f440e430db3a0fb9bafcb2877fa0f2b2b2206 - arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c 166469bcfd5bac8ca50e33d23d40607d532f7a9f - arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c 706af98521027fbfb3cb50742e9203904186ccfb - arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c 575e7801ee2435ca3d3bc588117235189cba8fa2 - arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c 5b726e62a784d7660009ac2235ebf2d76dc809ad - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S ef034cd3245b78dec24c714d8ffbb7e9b490427c - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c 54bc2fcf8fb31777a2eee36c5b61246cc0fa0a17 - arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h 2bc481728aac66acbe669f76aa6dd84c3f4e88a7 - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h 7309b02ef23609fb839b029b295bffaf714cdc1a - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S e8d837174e3274ddbcd923af88d3e19e1af8c06a - arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h 5333986fb9d6df5ca3e50aad616e8c1422eafdd2 - arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h b8ddcea3e66690f3932ae009921566fe249feccd - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S 1975a45f73616d0ceb03dab4a9397cbabc1e66ce - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c 0aace28e8f75168d13d7274d81f1f906cc1b2cae - arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S 030496606ff67ba16f47be9282a04338261e38ea - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c 126933334b9ebdde11859016f3bbcc6ac9bbef88 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c 3f90b73f27ba47848db784621dd350e6a5ec54d9 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c e90b7c0a59b785560e233605f2968b642d26fcdb - arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c bca37120bec0db88310c0e711220bd8301c8b932 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c 1dc25162c504805b378176ceb2a1fac39b8fa3e2 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c b0603f49d7b1252e6774be83ed95232695f1f263 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c e5479e33302a43e627013dbe10bbcca8ccdbf8b5 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c 33f9c2d61b7aa3242f22100ba2694ba2709f7a1b - arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c cfc7af573fbb40bb702a616d8f0bf02b017a3e0b - arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c 5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c 132b89dc419b19bfabb3eb2450a5e74317faea11 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c 8b11d0569d254ee10c03b8e7dfaebf823b7b1746 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c 1b333e35df79afc9319c45ded87fe22b1e5547fc - arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c 0472150350a0f6a23e8750e0fe14991d176d1a04 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c a68989337ee4c06cf76f89d69cfc5c3aca210b00 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h 0071214b6af7f5e24aa92d4e7849c79c3818ed05 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c f3431f5300aefc0065b1e6ad9f3e996878027bff - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c f4fe9f99f519b213b8d23015c37b2e4013ebb066 - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S fff863e589a15845fe768ee9bd16a482d5946db7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h ee2004c34a377b43d61f3fde4201ea86e1834fc7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h 31f012031e8dec3fe5dab7afc9ab89deffb7fe7c - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h 79f261b3e512eb92ef04e1b172276ba95108b6ac - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h 659dfae8f25d18bef4e2ac3c9b2cc07bbd255dd4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h 98509207554ab836b38f580d203793668061ce40 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h 5da379773f07f291d897ea36a13ac008c78bbbe4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h 4619ff482dfa91c976c3d58153ac694dd92a0abf - arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S e0f40190a4d2a13086e9b7c951d5301f744dd767 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h 42137e1b1e1f31a2b92b351765982cc8bcf28601 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h b9c87b1b0f989e816c65163d00ead7cd68b4b6bc - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h e2fd2bbe14a506ac8ab6eb8f4c65dd34827b33a8 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h 379cc0fd2c6486a2bfc850d19190835961783f16 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h eb1ee8f26e0a9e1d174893e2a80e0ea2be070df3 - arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h c54b714045ab12cfcff4363f00ce94952a40e2d6 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h 95b6af34fbda29b2cef5ecaa3ecf9deb1f7a48cb - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h 39568f02d9e541a653aaa3d8503e9976203e27b5 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c 0cd271eb1db1372ebacbc89a1ab7e6b858522177 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c 19471da73d6d6e0316b89091e8034b65252676ea - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c e7130fd49b764ab203b1f70d8c04929b17c338a1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c df960717d8f3e8b3111b85c464d02214767ffe67 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S 9921f6f68c3b333297fb84f0c74626e02e31182e - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c 3b43870e172a97e6682dc9e7adeb7ee54b219ce1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c b4ec4794171dff334edac55b287dbba42365301a - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c 6c598ab11230d9af7684a342f64de0ef3aafd2e7 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c 92c35daf2b450ff28a8d64da226b020489472149 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h e521b7127c97a6dc50d62a6fb23613467dfa5c91 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c a012da0cb3423fd96bd536ca33852c8fba58ac2d - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h 755c811030252ea484722f83c6773b03bcd1aecf - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c e5d1ee45233d19ae915b7dcde9d177ac30ff3c59 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c 1178b52937b1f59d49a4b24807fedf6800893f18 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c 33e4f92c8882961c556666d4e463a0cd932589bb - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S 00786f6204973e7255b3183326d7e2fb8a54f0a2 - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c 168bc920b2828c8478a977c1e6b9e597791c0e45 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c 4a0475ff7dac46ea547e623a9a83071f69b5a4b7 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h 4abee183dc860ea0fe600bb9b19e3c4a0a3d6773 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c 9b6172a308464c71e87f1f420cb1df10ceb7bfb4 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h 201bc8884be1cfb9b4f87f3fcc6ccf3aeec268d8 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h 390e28e24c8915a9f956b1a1de0cafa7306bf9ed - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h 930c77f84c5ef2c7971e52015e58fd9c314fbba5 - arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S ce594eaab37f132b152875858c98ea6a8cf2f005 - arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h d8da79f1ebd9b100b4d3dc915552f3d086d5eda9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h b1be891afebf5d255da6f6dcb865725241f566b9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h 8274c219bcba2090fe7e6e628abe65c7c3780d33 - arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c 3cb5ee19a3d0915879c602a240e4affb4a0d7c94 - arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c 03b9e95dd87fe5cdd436743fb8f5f59d4b2f2de3 - arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c 2f1976dda894f28a35f0cc50623e070a354d044c - arm-trusted-firmware/plat/mediatek/mt8183/scu.c e9bb8f5dfe42b8cfdd770db2301155ad00d93617 - arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c 7a7fbf6ac91e6e9ff86ac7350e8de64f834b5997 - arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c 9065f62c97422538ddfd15c89806f2869ffb98c5 - arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c c7ae3ce6e37f4d27b8733d9c3b1bafa8add40a8b - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c c5295d987eeadbc7fa82ddedb5266f20e7dd3cec - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S 214f922545d6899c3e5621df156f1712ebb3c009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h ddd6d454dc5e0a1dead801b5cb856c7f27a8065e - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h 1d535ab7f8d2fb5131a0ce0e6a7b11c4a188a009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c 51b89484342a85c2ee1e944fbbfc08a8bc663f63 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h 4ab8cc9c4d3ff197639f9b78f7b860ebb8879967 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c edd71b3e0aaea146cfadebca131cd7e6ee13d303 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h 888e5c6480da8cc9f0dd6d5febc12f7d0a8a16fd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c 264db153102d726c6a9455244b40d552d0960af2 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h ed39e8ba2090c26070e12def3287c0ff46721987 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c 316277d91acd7098ec6ac153e95c932aca46d3c5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h 2e1849b9de23cbd064f9e90e4c83cd761e284e18 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c 96ac9c853839aff7b9c19b8ce2bdd09ffee2c87d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h 1f21078b5dce77d5939c39ae046fcf15cf1bcc4d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h 23040542c3bf819fe42a45ea51427b1a39edfab5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c 0bae9ef296eeb3bf9ed2342aa58b2d505dc8f04f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h 7ac4fd4d1072962002d4b4a7439a7fc6fea85b48 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c b26d910796c32c24b2519666922a9991a16d3562 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c fe16bd5deb42a8c0e902c3a7547e11d7d5afa0bd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c 8156e8c4b7f219c9590cfcb2338d845c2b0c71b6 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h fdbc0bcded1a96ceeb994c74a3a48eec3af06df3 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c e92a0c648e09b96cd906a5e008c418d7d61fd577 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h f1a812bc872a1ac1c695c5485fba1a135307986c - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h 645f76b92e2714b452ae24edcd6a40cfa879ea61 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h fb3c91bb75b7fe6fff5323ead8dc73efc07f1289 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c 346960934a0779649e0412ae87abde963086ff8a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c 3a86fc89605145b3faa5aa385e8f7a11851b424a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h 94b038f0c7b76069f4f85185a375d4d2aa61a74f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h 62325eff3c956aa9ca90b298e958e8ed5941a8a4 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c 88c148094b3fac4149258b8fe4786fe4ac3f8f3a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h a52a6337e1e29bc64b0d301f31d88c42981a1105 - arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h 01e8de6953d79923463ea639e7d8e218ecdbc8e6 - arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h a4d241e1fe6a38acfd38a895dc29d0d3762c185f - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h f7b9354cce893182c4203079dc774a9b048d05d7 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S 97a99a4b4542d549efbe9122362e0ee8fcac89fa - arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h 16b7a7f8d62f9bc9d06c01d5e72b2ef5653e7455 - arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h 447f690a22efc00539cd931fc1d9aba592997a19 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h 387e06d0f2e4f36818ebd660cd1c4d429222a6fa - arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h 9ff5bdd1f6610dc5e442304399c97ab95361e3a3 - arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h 58b0e33d4a7460c72049a50f5cb8e8af5a5260d9 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h 9d567134def757007ff0196e1a84e96ff6772d7b - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h 4f1e69980b6fa0691ac24f320f777fa5f690c987 - arm-trusted-firmware/plat/mediatek/common/params_setup.c 4fc10ec9bb95247b13ba3d9b9edeafbb42ba4037 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c ffdbbcc522937a13b7f658754005673d0257f6dc - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c 311eaf7d7a3b040aee08231328317674a1db9975 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h 7858c40d5378047a8869189376fb70d934ed6f9b - arm-trusted-firmware/plat/mediatek/common/plat_params.h 91005aeae3d9de06561b65ab2fcbec18472bcdd3 - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h 561bde7d3dcce4eb570c0798866c49ac31db4cec - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c c272dea0838b85718c51563a46b3274a684e1b83 - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c 32e5d4c9af02cbaf4603a45ee6ecc742ae4e1a0c - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h eca4fbb32aaba0013f15b702c44892eef43998c1 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c 47b4f5bd98692841b45386f4ac1971904a86e5ef - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h 126307a49e31392042c3224d14fd15ba85a79b43 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c a439bfc1e0a18de64b665a1f9f1612c6c723b298 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c a183db6162649664bca3e1e3a7650f0c641ce3d0 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c ea57c5163cb9ad847760738ed46363d3b3e03dd0 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c c78b2291f89f3cb41916e636890a3b8263cb6250 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h 7370797acadbb4e47f7b8f407834dbb4c932cc16 - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h 8cd2ff88ff29bd0f9f3b205a057f4c9bd9601adf - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c bcc701f742bbbd6ccfbbc58e60fc17bd7ea2743d - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h db4a5136746026996b722adcae43bef2530ca8bf - arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S 72586b214f5212b1d0cb120063c07e8eca22b38a - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c 13f55b9e347d50eacc00a183d743c28419be6dea - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h 990b19477486a12883414d383890f2bebcebbd2a - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c 7203181ede278ce1fd73cf8b9f9204b6cd508282 - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h 37f3112de6efd829353735288a329458891db6f4 - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h dbff628762b596a369e7a96908226677ec6143ce - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c cdd4db5d5ea83958ff89700a430e1c54729bbe76 - arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c 2e61bf89860dc6368d6608e4d8447e685d7d88ce - arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c 975fa62263fb56cfc6d4832599aa8a421fbef3ea - arm-trusted-firmware/plat/mediatek/mt6795/scu.c 9a2cc2f4d94dcff8028cd56e4bcd01da0dbd4a6e - arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c f42fa6a617844b8c56879c8b1f3c34ae4b77aa8d - arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c e957b0cc082fc56d3b25fafcedf71e23b8fffcdb - arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c 41b33f806ea4e94c4dc6f91cf13b8fe2dd08272b - arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S c9da62c4ac9c51366c26ca27dccdc85fb8840e6e - arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c 5c5ff1370ff35d42d3c4d77b913247276a4bde02 - arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S affbb4d9599159566bd93871905eb54cfd7075d7 - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h b9ba707119860e36bdab2e1517f34832022480ec - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c 524f765609b42d6239efa9fbe9d123e031c011b2 - arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h 817e6a410e02d0889f5f69f3da13113cfb9648b7 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h 46009c0467b0d5f5a2b78837653ac6c1d8154100 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S f2440de976c6c344fcd2cb08353d0bbcf16d8e98 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h 9f36f3e719ea61b6f45d4f3e36e813e42cdac8e6 - arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h 948df1ebf0176a6b28197dd1f5a96ef7b3407200 - arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h dd9bcb0a34eb0f2806dd3d2764341217a12fca53 - arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h c585fe19743e984a106c899e16d61ef97416376c - arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h e90649554240f75d20e82bcaf1d5fc7f72308d84 - arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c abe0c66165b32a2f3dee830062f153c3c29738ce - arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c 322049a08a3981e4c34fb6991314537e02662946 - arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c 9b148285683f9f62babcdd92b4cbb3edf8d47275 - arm-trusted-firmware/plat/mediatek/mt8173/scu.c 6a2d3a421c077dcc608a94317ecf55a80c640d76 - arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c b49fda8c23d477e92d842bb950e93962c77a82cd - arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c 5b0d461df0d4936d87d5a3b87846da17b5bffdcd - arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c 314689d0bbe7b2567ccd667c6f70815679729e1f - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c fefea9a047dc27fa97fc660c62bc2a4b68539b35 - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S 27cbf1f064da3e18b5cd7c0e83fb1c9da349e00e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h 42adaa32fd22643561c090086db64c635fd6d686 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h b7e2ebfeb39fa655c846358a6439c708fba4b6d5 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c 0f16bd582feb0391ddd3b4685fab51a7e11667ca - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c 4535129d635202f3bf1b447e411bd1c7eda5f7db - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h bb6c45f6edb308171b205123bd682e3db84ec58f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h d86950fce5e4e2f48f1efc48472289033367e47e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c 9e687cd54be9aa08265355e1079ba5f6cd2a93cc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h 4af6a675f41b6d5566fcc13863c1507f5fe28f7f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c 4398c8e27acb0bc2b28771ed5c1a0689971fac4f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c f6fe2ef42009b0fa69b3957d63488b6192072275 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h d73f4f2080ec7098103c5209a4c302f80535dc77 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c b18c4af2e0471a0d5de267ac5c1e4a52b1c94ea6 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c f3ba2dabf2cabb2644ae09476c62fee2023d6abc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c 8ffb063b98ca22c66f9f96260216a31b1de20519 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h 0f38df7cc1b225ffb568e7df5c4981b0d29ee7ae - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h 9623b67d4f2dfac8dcc78ed711172fcb5f85511d - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h 3160163c493937b3bb0298d50d918627d0d0e4e4 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h 27287e7e69b6a6be66a87cf9e294f25a682e92fe - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c fb0128ee719cdbc40fa546319e2635e3e19f1e11 - arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h 3d43facf8bc958241dcaddfa4cd6f9e61362c87e - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h 95875d234df9d7f7a86bfda389367f298611eb38 - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S 755906af584459bc7964059a3022e624d4743b62 - arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h 12c0bb5878f5671aeb4bc9ea733ddd80cdb960da - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h 7848197b715dc7fd355b6bc2d2232123facb9994 - arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h 2bd6a37616bcda8ee48aa9917c65801ceeea804e - arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h 89bb4015a4309bd60ed5dc2f32033dd0a4f603cc - arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h 6bf419a65264c179e6faecb78b2c7f31faccfa6d - arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c 94708cfb8fd54fdc9e58c01699e1e9e8c26341e5 - arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c 02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c f6cbc785839b2fde5bb8c3d87190641b45997d2b - arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c 343bb93fce6c58d4c3497e7f662303320ea1ac83 - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c 1e5bead24560b23256aa9e306e5a4ece724bd6af - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S 79002203788efcbfc1db666914278df3cae585a4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h 71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c c925ae2549008a58fda62b34de221dd620c70d96 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c 5785dfb24000631b8d3ec2c8363f0de46908d763 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c dace58b25824fbc880b58670389d47358981547f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h e37292ff38e07fc925308e8d725c49e48fa0a085 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h fb86370251784e4a48a2bfe74baf2d7c56f3701b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h 98090ad034ce904969ba1583467f8e5ef565d2d8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c 17199f9bb411ca8735cf2bc4b22e8baa7bc2d152 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c 4168e0d14bbe98c0b575d2e572fdb4b73586f8c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h d83f926ab5ef0f16323281a34f12b358f3af50be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h b6ba63645f7269f8d27b087a36b742340630864b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c b1174b8477d0e126d9a35147161079391bf09ab0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h 79890abe09ae9210d94ce3c0f27c8e1d61ed6fae - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c e1b4cce4c465228019f6128073e4634dce0d2986 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h cb6cde28e9dcb269b456216c0e1b8d55c8ea996f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c f70563982bec81cd15b17e693da41e7d1f469c6d - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h 31705f56afab7b0bfb866eaec7cd621c05f6004e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h 1616d5f796bb92042ec501e01ff39403df39936e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h 670e89ed3e54a8fcab5f9bdc69b0710229d556a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h c4e2a5509c4bbef64807d58ddfea984f66031f26 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c 368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c 73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h 77b795f3ba595013340ed1473935df13b18992f0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c 3940dbadf2f6737dbe71207e2be2245fc24a2cf8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c 79676f45e5439628bef50912dcfdb60c2ab34e8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c 9aafb1c8544431a32f3d664beca24b47d9489f1f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h b24e7e4ca2cd9b25fdbad93fed94631f347b78f8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c 1c5969bf63da110696877497bf7bb035238af2c3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h 33b92edafecacba8aed5f6b12c0b051740d4aa8e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c 445db7752ab6359cd4ddfebded67f1dc59603220 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h f438fe8befd240fc23c7cc48c7e77e1e1a3cc0c8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c c5542e49f5d3326418606d161d9490c9dc3c7bcf - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h 6ef0f4493d19b357c77df1b5cd49696a5263d102 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c 28a7ecc5d35653b1b3e42ad19c1d1526f8b4ba13 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c 416b58dbb44fb50ec9cbdda2b4af6cc04bd48d20 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h a2ab35d6915d2ac73d85c1068d973a0d3514da41 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h d655b93e0b18efc8d5ac80ceae4a282c70d79c8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h 3e3b62df98d3d83eb2016c9d8dd1f67a641e95e4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h c997c26d9a441b3b550fa191f122a33d669d38b4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c 618680bf1155ee1bdf7f67df15cfeefeded70e66 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h 0a4ed6a9c901c1bc5b75371aa26917fe6d9b243e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h c13822b4c2268325ef4398fbd0d28eacdfb59602 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c 1e9fb5aa9c1bd6bfedf0be53b9f529290a141a9e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h 709be723f3bb2b8be34dabc19ffec007a928b060 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h 1209a457ffc9d4ceeebf3f3e24300146fecbd276 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h 2516c5016c27a7706bfb86cea698a6741d845eef - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c d21496a22308580c07df11ebe7adf41f274bfd59 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h 73de5db2e94313670371f83a648fe95de097e7f7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h 85497a05edddd868fbe7322a3621d2b7c88c9814 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c e3e6596065738a8b19bfde088f92c7a4bf51b851 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h a3456911635f8af4f989688a8a1ae80de5256fb3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c c24f82eb4ee80d7945922eac27dac514db2a49ac - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c 98f55522313c18575ac3b999f71ef98dd128d004 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h 6b5af500b6156d7283e6f315ae2fd1c33e95eeab - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c 872b3910dfca5bff8749f70e72fba760cf6289c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c 49758ae69918fd8c1b52c54bc298f1f3e80fe1b9 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c cd5607156fa9256dbf860561db48d3e74c800295 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h 1a8e74d1db7ceb847a8217c94620d6a73c28e8ba - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c 35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h 1244ea062e485744ad8d59bf66ba3a455bec7f13 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h 4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S 97ba7557af145fe931feafea204357431b957299 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h 5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h de6346b18cb5bf3c6727a99f6cc0d9a62be9f071 - arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h 9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h e1863524c093ea2e6d043b9f6c7dc1e219f08467 - arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c 0aaf3b723ed86200d3e2c0e83641074ae213c44c - arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c 653b82370d0b1ad6cebef8b6d7072051e934caa0 - arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c 5d84153e66efa37728948b5b1fe281913f5ea657 - arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c 5c6677206ac7ea4573dbb96868e106a55445d4f9 - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c 4a2ec93e8013a56c39ca18d0e283fc9cccb43b1c - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S 9d5ed44c58a8c942270d1e8cd54ff65f463b2336 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h 71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c 1b68266c3c155960dc03cba027a4d430c74473bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c cb930a7db51e4c8871ab7fcfa242466c2a8b36df - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h f7c1784f7532b244fe2bbca846d710d03061bed6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h 45377afc42584fa85f873fca2cd0e157c1a16b37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h f5cfe3883759a648f72458b1bd84bf01d3bb1657 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c 9b42c233c5ba1e6b8a384b28424da455c27a53a6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c 89fce0253e363a84cec3e3957ac8d951a80ebe74 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h 31d2ee83370c6c53704ab1a6ef9b905297491333 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h f1eb5fa4f4de22b769d0667ea9bea00613216cf9 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c 6710f6e1dfa15b331f9d813a5003b5198af81c04 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h 0652a5c416f4dd969f772d9774e55501993af032 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c a84fa1ee247e2005166d9018df2bcc75e63deaab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h 51222b809151abb01db2556abfba262c93f7f0e1 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b434a3c4454f2c705b0f3b7c565d85e147e7a7dc - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h cc63207972ae473d6a68bc41f3aa23093730183f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c d42c9ba8c699033bed7f64376149e25aaf0ba27b - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h 2dd99ac3ceb6063e89c9c016bf2e965abd2636c0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h 30341bebf59f92502ed0e0f772ffd6ff3f4691aa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h 6158a4631af76550355215276ddfb61772f11c91 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h c42e69a4b160aed3d646987f867de63fd6542f09 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c 368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c 73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h 965dec0900511bac7618f812c33f95620e3b1068 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c 0d3626281b65260b4b2e49cac33cf6bece32999f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c 9fc0480b22dccdbb2dad940666ba124a785ed285 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c 6c9c6446695fbbb9ef086f4f783aae57f24ff6af - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h b2f984f7c8707ce9470fc25ae8af0f7a041f1602 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c 26edcaa081665198f705a5d6e4a606c0b4e00689 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h 4b3e251e2f0c0e4796105e6d25927067e14a2a6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c aa2819aa55d76d63f05809805f6ebf6f84fb8f71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h 9858935fcdc71e5145d69b0d6b65410dfc4c6dd0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c bb750dd896f8785a87ba62867b0e862dbb4199c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c dd32e9eb6d0e8f5083df2bf5abfe28fcaf6f2c5c - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h 0f8fcf83ec923d192f61376370dd90635259a378 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h e3a261adfa46ae2657a455b7d25b7af56bb62a37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h 1f598d0b85f3b211c05adb41726664e4a2bbddc5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h 1637cf9d86b35aef31283240a30095022c0476cf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c c7e5e4cde0a05fa756e3fc6cd32654be3343cecb - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h e5e46ff7c9820b84c61e6bf2afdad854e42c6985 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h 9bd59c04a5dabacf5a9ce010eefebd393e814115 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c 905a72478cd919c732be2d3f3c066d27f34b489e - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h 9479c40f7955d1b8da21fece7877b3f970886a62 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h a65ccd601ba3861f13ec19d1ec6cc79d4295961d - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h ab677ba0b11817e784f6008456b3501b7438cfbf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c ec2b85d104ef0ad52faf88881e864e93c37e0ffa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h d2d41012d692a8857c6f842bcf2eb065142a90c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h ca56b6a499c7e44f09c1f020859f9e7d51b014a3 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c 067d8c516f8ce37edb7c8228d9d7fc4ba15ad7ed - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h 1e038ef0b716c1ba013366f2d656026ff4bacd71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c 345b11fdc0c85e312ed8e6a8643339d691fadf6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c b656247e4733dfab4d7db4f7361cd1b15a0c14bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h 8a1fe395632b1a162c7b9e75d46be042d64f5230 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c eefb0e4293a309d3eae668a9f4fff6b9d45d3597 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c fa7a5c1599cac3c19ca4cd64215b1938313806c5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c 319ec69ebc8189c0b9500805069cb9eab1288242 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h 7494ace1b19166bbf26931bbcce0c574629ee2ab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c a0c85124251b9cdae75734966ce95891397ca477 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h a6ce0baf4ebd3c81556e0945c2649f2efae6c879 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h c080e0d9285c2d3fd252d1b5d80f857f7b5f7ca5 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h 166890efce4ba83ab0783f4b56821c8576731a31 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S 5a59b5db38b291cdbebf71aa758859f99c35a751 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h 5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h 555f92b188335e740adcafa8f411f751f8aa9102 - arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h d3155938568a3ee3a31e1df08de79e5bf68dc877 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h 98b250fb48fc293e489948124f342093ba6dd423 - arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c 5317d798df3fa15f8fa7b2c33ba670b0a1ecfe42 - arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c 02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c e30b233c6a0d10cb0d058f63a7d68bced2033d08 - arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c e55a87f7c47f362fafe9a61204603c0aacd71ab9 - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c 2c9ea17eea925548d393c14f7f51d8bc2fbccdcf - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S 1e1932554b5dee8b5c9f6e42584b440f694fe206 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h 60b16e786121e9076be12c5a78ec91c7e33801be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h 8fdeee52467e248a082f45d92512e951f2611360 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c d2b7ae5854f6cb1abfe5c55f52385c86fe6752f0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c f0e1185e7fac539c5d2edbf5893678d2ca131f70 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h 9114133093483da052525a109b5ca5242a14cdc7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h 0bf3be2cc82c84d28437a838ec18ee32b52448a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c 982ba0c3e5b8772dbcb65fe9ec04f07cd66c03e3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h 3880fbedb01ad739666ead858ff32c11692d7ab0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c 8836e6535eaf80d79c28bc7e61f796c61f019c9a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h 26687de903046dca0b5e9750e8a59b9355a29ec0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c 514a984bcec8f805fbc3fc8b0213b8603009b717 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h 97a67051462aa2dc020abb4c615ec1b8d55798dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c acd408521525ea61a78ab71ab790b33f6c8835a5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h 68d0d1df925010bde7b53a36dd82ab05a0cc23dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h 680305a5142d3cda1b9ccc1bba0d1ca8dbf42b0e - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h 63bd27946e361d2e05b681e47abfc894e0b23e88 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c 3de0a5c82b6c6679381b6c8887a23b11e1ee49e5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c 391c8bd0413603fab7961273368ae142ef2e605d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h 0950b022f226cf400c633b938956424ef62156a9 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c b5dccfb4fbab4600a1576c8b74b6e2062cd13c6c - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c 63d1221a97ab18b30010ef6dd666592c84488052 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h 2f14e2189e22b58a7f814523923a82b761565793 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c a6cfe8969863b9001520ec912315467a2b1213e8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c c493de6825dedbe205476271578675f186aad0a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h 5ff4457e67f619c9e7562f12b5fd4772a6d34ada - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c 1b4a0d65fcaaccb28afc897aef9a76972b99b9f2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h c6cd4eccdc73fc94fe1d36f9c0d24adf82f6b762 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c 85a883d9102bcbda2f8b172b3428fa270a259858 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h 8e4cded7b48b70c4d63171d01619ea77582a15d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c 6afbc58701e19d1e4b949615eca0a6fee5c0eec7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c 9842a9ba9c2a948191518a1dcac7efa316141dd3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h 714e06306174609b86f6dfecb362e5d307815984 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h 23822f16c7741b8a82e6c1b2bf37723c9b661d23 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h ff8ca308a59e802f869d16233f792ae0e6d19a52 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h be59b0efd4cc9ca4eb6570a3a2fe1d3f0f812fc6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c c3913ece4d63b48d8aaa43aaaa4f7c5927073b30 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h 6fad70943b4e7bc9042ec608eca4905531b622d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h ed2f1e43ce8ff9065b95a274256a78d34d08b184 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c 2915d56fef4019217f23aeab0ebcf0ff98b2818d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h 302fea6e0fc2351dbc6ccda1ed9190941f2c0250 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h d252e68c77c34429d934422da1ce46e64553c23d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h b196a520bf04181913710fa0ad6c7e98df814be6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c 8d4291524d054f1b355580fb4254843ee94015f3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h 0c0e64bb4e502f8b06cddf4f5701a2004dae88bb - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h ec1e10ba1585046d426fcca0c8d6a0452015786a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h 27ef52baeedbc36413879fd421b276824b21ad58 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c 3b25bdf185a1377c793c31e212d50a0027fda91d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h 6dd95a8f29a4eb734a92736d768d92a35ce910f8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c d7be908565309c39ef0e37d464011c7340c16d6d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c 6dea64a1dcb62407a4021b892e2da1cdc50af221 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h 3035aa1efec0b288548d3a91426946653dc24b80 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c 97b36bd56cf9603b43fd2acace9ae94457d14776 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c 1cd2b844b96d5646b2f021f2b7a50358af7908a1 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c 175403c002e2bae8b4b5f15356300cbbf3a37aac - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h a0e2a71a095891a57e56e7e285c8f94dc9d312be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c 35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h 85515b62d8aa7cf44ac7f0b5a705f9507bc7da21 - arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h b7a9f887a8578d015d21dcfd1b009adab66f1f2b - arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h 80a7b771023f421a796b8da96a4d42a7672cb817 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h 4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S 567114b72dbc9398566aaf0389041fb7e12ecb12 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h f3091cf7bfc468b69812a8ad31b9b5d768775e88 - arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h c02f1fbfaf33a5bbf3351dff53710e6e70a59e74 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h 9d9e1a21208cd3b5491a40bacb421776e8c1b680 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h e4b12c87945362986c13896e2349ab872d556c61 - arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h 9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h 3b21be43300990b373aae5fc9fe86650293e6465 - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h ec2741df6c60880f2d8d7c157dcda59d0c50eacd - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c 180bf4b2deb975b6753f7b845e0055ea91a2aa13 - arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c 6e7e984a8e5dfab7008759c759d8244470f3dae2 - arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c e08f230adb59004c64e07444599554c275f1643a - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h 455f78881f3e452bc906dd8e2dd74d7e668f33dd - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c 2cfbd336aca6ffd917aac7811b326bc53c734d1c - arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c 91be000247752e30dfd222eef60029b13936f320 - arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S fd14d1c817b69bd4a42046e3a208b999bffc7e36 - arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S 8150ca146a9314d5192e1e394975bb932029bd0b - arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h e1247a97415e84032dab91e8daa6df51645413ac - arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S 07c3221b9d62d08349ed7bc9f4f1e779f524ec32 - arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h d2d25cc01ae69fbf7368f681a6be32083570007e - arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h 8b0399819af138f97f2f4270408c66b5d23b6052 - arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h d99874d76998c7025371fc6e19def1521bfacc2d - arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h a0b63dda5b240d0c16799712543a79c70bd462d0 - arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h e6926afd75dc641585601bff95a258034095c6e1 - arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c bea1c249fdc7e365ba7e5d773a7e312de9345fb8 - arm-trusted-firmware/plat/qti/common/src/spmi_arb.c ac89500a8d77a91b9b24a426b3394744bf74efb5 - arm-trusted-firmware/plat/qti/common/src/qti_topology.c f12c8a79f6141094db1aac3d48ac6ea34800ff6d - arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c 7fc1d5b81ce41fbda7e5fda0ba2e22acdf4d5934 - arm-trusted-firmware/plat/qti/common/src/qti_pm.c aeecda36338ac151632b50ce13795833a9f6ce3b - arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c 26a9cbddd8b9a236e5d0f3550807554e23563f18 - arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c a78d1e23bb28b3815e1e4ed90be36d9a18730edc - arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c 825f74a7f38dc32847afc499110e74db3937935f - arm-trusted-firmware/plat/qti/common/src/qti_syscall.c f3b7fa7c62db7248cf8b50316244b8239596f267 - arm-trusted-firmware/plat/qti/common/src/qti_rng.c d3fde1360e9da45d7d4f06fa00208544d41ad202 - arm-trusted-firmware/plat/qti/common/src/qti_common.c 7547a5ef92ec4ac40eed5a73041ef25902042bf2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S b6ee5b136c1d386d21bdb0c3944363930ea1c5d2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S 3d127b0f585eb4f2bfaaccd2f04f814fca7770c4 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S 35b43eea9fc4e1679a0349180b49fa1bb96e59b7 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S b6f69f64118c04b6b54e760cf7005ec1594689fc - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S a32c3f1d46d7c6cdcb2fa977d2899c8ff2bebb7a - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S 1d172cb4df58b173035b99b5855545b25fd764be - arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h 0b01452153b97f032c89b81698730bd0211ee4cf - arm-trusted-firmware/plat/qti/common/inc/qti_rng.h 2c7d5721030a2353cd649ad2cf4da49242ed3195 - arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h a492ca7a1a6a0dc9b988c09a6838be72f3a00cc3 - arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h af87d6c46e8e3304b92c90ed0111bb3066bac8e1 - arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h f00660ee7d40d5826515fe5266e50d2172c12bc1 - arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h 3030765ef51687943e02ca761d6d518826a6c438 - arm-trusted-firmware/plat/qti/common/inc/qti_plat.h 5901fe33e7d63a4a03e1b95469b48c8299d178f6 - arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S 576c57f662c322a2eac3565e848ea0179d7290a1 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h ce8e6c97e3af86cafccb6b9ffe857b9c1ec62598 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h 3591e68af17680a9c8b78bffb866c93838cc5b18 - arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h 0c6b7067545771534db6e2eae7bdf7694a939d12 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c 4e66aa575523181fefb5720d798a257e98a26003 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c a28527a439c34c2ff37a3bd1ace46fb9ddb4f357 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h 5db76531814dda261416dc016b511d807c3a4ba5 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h 186065ea9c6a4a2d16c200d4d07466514f5a1c29 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h 3e4d34962a59227a5d8d494f35e80b77fdf8d61e - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h 885aa0bbda57cb30366ac8f9ea09f3f8e7ad31da - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h 4bbfc2267980533e77f9d529ab7d174d48d90403 - arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c f1e4a10f906499fc859ce623d4571dc63e7d5273 - arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c 3c317104013baa1af66596ba8f1eef175f48843d - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c 3a9e2ef84999f167350febae7da7117e414fdaaf - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c 0701baf6d3a2c6d67485a189fa41e9c33fd20ca4 - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c f28f931b63cba463d5ec189bc42550444729edad - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c 592af310a2153553607e67158a137e3b7d297c79 - arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h c3fe6580aad543effa72713fb4d54e4fdcd7f76e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h 2cbef8a830bfec6a533910d7a00ca01de32629c3 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h e61cd2fc029895773c3e7781028ff30b7d863cb7 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h a86635994a276adad357b7b9a9408af38860c61c - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h fc798b0a8b41f3e6053be0d0669917e2a704807e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h 659bce34ee85d1001adb313d9a639d66d3a89deb - arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c a73994ba0863a0c9119b3e80c2f95fd3a67881de - arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c 98e7e0c1e8b661cfd05aacfbfc969aea710cf145 - arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c b1605e3612529c3ef25860a30a92276b1762eff8 - arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c 23e53289a40f4fdd5705ffc560d18e9e3086e32e - arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c 0c8169624b733658b1eee7afa553ac38e2f2660d - arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c cc4b0a911ae0f00cfc94310c6a9d60716e9a1064 - arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c c93b1e05180647b1752b51838d7b935bf554e073 - arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c ee464010f7478ad28450e239244175a97360cef4 - arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S 6a4cfd87ff051f635d35973a9d14d941e0dc377e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c 46033ef6c11ee3af5452b7fdf9b90c20050c0be8 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c 23d9dff6e9c23385b4ccea7791e18d709f29f6d0 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c 30326906ea4956c9a459d8a32363b2ca3de50733 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c dbb5c27c52afd2347aa5d78b423a051d694a5c1e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c 41479908d06f853d367898b86dda07763652f4c7 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c c9354b6d74c4a24fae2207b5b999882056d88e91 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h 4a2ceded30ce0c9be27082dc3e0a0f646e41c555 - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c 5e8868245cddc9cd3bff4ded0c90d2f8b356920d - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h 5c64677609f95ebafb78a49847ca9c07c1a3aa87 - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h c72a5bba918c6067f6a77a639c42bc477c71de2c - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c c02cf900011574561e4a40f32b4328ee9b4fc2dc - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h 55418579bc9725e40a61a81af232a46218f27291 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h ffac73fe826ff46223b2ddaebd9e7206528dfe33 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h 3eb20b0d72778ce95cdd02e0732ff2485fdcbe49 - arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S b117623bbdd5a56a0ff191770082cd80e5b860e4 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h 3886a4a113d64631d91373640cc1e9d6ad0f9de5 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h 987353d4fcf33b0589d816a77ed534bd4b0ee784 - arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h 90cc387dc45aa325c65a5f792054dbf87337d0c0 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h 04e0e1415877c38b1d5b29fd0db73a6ec1bbc63c - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h f10900dcc55350c0601a0fcddce82a8d8faeb902 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h def81ce5e821eeb00d79cf3474f11987dd6f1d5a - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c 8b1c7bd1975b587b7b972a8471ba45698080074c - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c 2f22a31fb6bf835c01bd19bb362bba1c8a3e4918 - arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c 66cbb2ab82f32d934dc4d303b958c70750303ca6 - arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c 70667783807950b851233233349f9cadef62b70d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c 4f2d7ac1b88723a36765c17fe3b6b524622ee49d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c 5a527e1803e29b659091fe8cf586adaf527a55dd - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c 05acb6f9fd3967467369875212f706741e9434c3 - arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h db28b2738f48c2d2751af6dee5456298ec578706 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h 2a726cacb7d9a01adbb5c593a0bf7a6f0e9d2c18 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h fbf4ab727479f904a0ae30ca600e339277fc9c11 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h 327e01f2a345b7d3b00f949c0785a60e4c03889f - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h 1e8b5a5e05d44ab9f8f3bcbdc873885fc49c39de - arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c 956551e3f043e449ce36fb1696d99d2ae5b925d3 - arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h 3d01d365783ad5b2ce0f76df72a4a10db3d9a10d - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c 8ba47e3eaf73ff3181e4874c764119b46c88baf2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c 4597342fc7f0ad8d99af644fbdc636abdee5edd3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c e6ee29b4c786d6d279e82a4066d13703168bd28e - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c b0c855a9e2b50bbe03f42d79ccd6a555853cfefa - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c c2cd522ab9668274cd7bf26fde63e9dbc9a94f28 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c 7641a42485d020517c692c523a29fe5be4136651 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h cc8a8d368611f86cdf1901163b06c0975be5ad93 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c 81037a214c1511f91f65b5793f9d5fc3668f3c79 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c ed3d0d97c20ace9c41ddac5ef51f81f75d2e7d59 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c 78e0e7699170ceb53b16257c0ef0c15fe08ba4ea - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h 46decb1b646ffba87d49eb22447f8e56ed5e0d44 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h 08aec0d0be276f69ddac5a77363f59f1ef42d88b - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h 595bafd552b05d81a25e9916fe91779e18beddda - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c d893793283c93ce6c488a51940c01574780f7333 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S c55c5c502ca4117b327d32cc3fef8203d3c64731 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c d1917ee3fc59b85d699e80636d7ddd7d4c99320d - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c d5aef4c8d30794a496c1c3bd18d000991bbae988 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c 84d20d5a07d53e649a1b8d130f5d4fdf6ba8f65a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c ba0a312824b0782a438e265e86a6e9d7638032db - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c 6d0c46a965f769a08b399225be6c77aa18f3a773 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c fa7909d4e0ccdeee6f0765cf68a95899ac8aec1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b3fb31a094585eeb27ecc82ba69416ca4d66b171 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c 0cdfadd153db5ee7d515adb01dd35d62e546226a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c ccebfe25a0f4bc54b5d08685ce74082118f713e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c 99d5d980ae032fa2dfb6e9da5fe48dd600b2a896 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S 8cec2a63b748c24a5fab3c7c47f114b8147894c4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h ee3f4b7a69c6c3dd475a88c55076077415fc76b7 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h 298abb9097e851023b914f09fe36c8cdaf367e22 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h 89808197706a2d7c9eedc24ca7666ded83f0e84a - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c ec24a0077b010c615c5e3a083e901d444aae2f20 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c bee19a74bce67a4d58e2f4deecb801e1a65bf631 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c 1ac68857bdb8a88c7770c006dfd2be48670a7011 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c 17ad1d9d60e3f6debc0329a42e28178fdd497e1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h 3b606d0fba33a0ea6729510a467dcb03e9750140 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c c7611d91a504dd3fe52ee769f9fa2d4f469010a8 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c 0dd6e3b7ed73b5e77f6ebc89320058cde70900c2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S 1cd4aab41ecfa796a41aecfc70e543cd82e2da72 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c 106e68f73e09c8f51c620c0dd840b42ea6dbd67f - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c d4052416878640cdb19e93edd44e4a7413289b6c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c 5b9c61a07970be31ce559c1b2c78acc41d5223e3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c bf02f90c1795b9e26f314ab310c0ba4e389257e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c d96974438f18123824bf23413d2d0d75452fb4da - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h 326d37fa1c2f92a2e56baf3391479c3dd1365396 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c 4588d011d8dbc1073379954dcdfb1c437cf9d4ce - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c cde1d7e2f8c3e1513d4828b37df69223bfb780be - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c 0a76eef9a0cb2d3c1fffc2a886eab6fdabb34997 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c 015badf34dbdf2955bc1dc9f4b22627bde8f9f9c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S 34e8d1c4e060805a3f55969aabbd211dc6b08fbd - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h 34309aaec4559a7c2094873802490b96b9cf9dc1 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h ce1df43aa2a9700b9c00f14be842646284b3ee3d - arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat 348ad39495b7209e9858421f7bd1a02f9712a410 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c 97542646c951833f68e49c013c2d309b885aab65 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c bbb547cc93729fd63ae5da22480a94dc84ad6fbf - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c 7832f9e627bdeb224b72a22840b7b4cd3354b962 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c 9a23652352c01545d80c980df50b0d1965df8131 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c c7104ef4a0ccb4a2ceb01951a0c8442349cf4ca7 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c c97649b9bd33d9e7f4268f6ddc79d603a3a317f2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c ab066b0f80239a20f5613a9c2bf4862d9c02e2c2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c 8617ceef396a9a7f9b5e9e1a4866cede187f6ba6 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c 6356a0b128a435ef5faa1bb6922a5fcc571926ea - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c 0c5a65d7362595eff6d472ba23ccde7af61d9ce8 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c e531e11712693e6095f810484cb2f8332646c1dc - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c e73b702494b764ebb0f546aae9de484a69c968f3 - arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S d25c56f572cf7b3618f7567d502c1ee11dec2bae - arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c 8d9b8ebe2f8407dfc849bee6942b55d0a9c76d41 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c 58fc3b165ee7a61397eef3e9f2065858876ce9de - arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S 4d04fd613146842b18904061da84f5958c44b16b - arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c fb218e655fd6a3d77f969fce9cd6cb5dd0a6c5b2 - arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c 2a6016cc527d04ca332373c0d14542d5176aebf8 - arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c 0f53c08fb6e10d933fd28d9f021ccfb0e48212fe - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c 4dbec584881036aa37e59b66185d958a695a455d - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c 6f1dca2fba8be7758cfe4395226b2e4be820e3f1 - arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c bbc86d9dee6c505651fa862133b686ea1e1af43e - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c ecf2d932f335bc64d226c7d6502806590af552b6 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c 91900a1e10f18554bc4c6b9f13d0e247da31062d - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h 458bed9c52c48caaa9c30822f0d20359e56e044f - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h e8e7dbe2842bffabc62ef459d5f4b037b5fc122a - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h 949736009adf4b730b592ef786e3d66eaf769d8c - arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S 61343b0647173b58eec236e5f6781f95ee64f5d2 - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h 11b45c0f4e3d96795a403b588930c354305a52d1 - arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h b76d085fd8bf62b29b2651fb2baafb167bbb3f37 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h 2aec61855e1e16a88683b573ae88e337484a01cb - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h 21b9ecfaf14f5a5aed16e18cf1643f78e890a096 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h 624f3a27eab52b8c97c1d391c9bf0aba2a48ff48 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h 2693485a6a4c24984696bab65e09494c4af953a6 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h 7eee98bf96c4e615e71244fad2270fe3ac7bca96 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h b01b1d6699848ec430ef6c7ff1fa536c611ac8d8 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h ecb6bb2512f5f946927baadc3238cacaf9e9c42f - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h dd094069cb1a5bb53cf55c4e87b2364925c1e25c - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h eccbd7dbdb2b149abd38a48ddd5f6b0f292373b7 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h fa073698981deb8685410d390184a2fea2477d8d - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h 0005633528a5228ce544a5fe3fc8b984d26eff95 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h 97366374236e04da0a203c6df1ed7e93325e40f5 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h d6acbb5f1eb851fbab413c7209bfba21509b4d31 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h e4e77bfcd8d045ecce243b060298bf229cbf3941 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h 4aa146b81da8a061bda6540907c37d5ec6569962 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h 1ad3acb2c35dab529632e51cfd8a1977d0a3e495 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h d99d1382679e0a53fedf1afb4781358524154b54 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h 0770b19832587bf494cdf6a16cf0af55ef4e3eba - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h 65dcb16996ba6f5480b25b088c00618a8401e2b0 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h 249831518e8554837fb8750d200cb4b786c2d683 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h 412a883e42794de7909b0a3076864c06874a0764 - arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h 68ec103aabc7cf1ba96e9f802589f232bf63e8fb - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h 80ba76cba14e63964ee35830536886c24581020c - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h 00ba4a09814b790749853248a68f57c1bf5d8a77 - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h fc8ce0bab3e269ab289babbc37c5ffea6c1105c1 - arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h fbecdf95d5fb90503336b712a6955a36a635aac0 - arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c d9c373f0351531965e8097178bbc13ede3af7485 - arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c ffd1e457886f1089d9c344f701ec17dc97f8f074 - arm-trusted-firmware/plat/renesas/common/rcar_common.c 716e1c7c79baa403b9c5d0ef120f23d8cac8e802 - arm-trusted-firmware/plat/renesas/common/plat_pm.c 514484b073de3f03a0c25885d1947529d0863273 - arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c ea086669ab75f559b2e65b291fea3af158c18bd2 - arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c ae71ad3a55f0e9c013697f9775e6c12c0ff7bd74 - arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c d414d4d769295e5a493cf3e77c9c51626ee0e6fb - arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c 12b42e58567a9ecd3d1d63318cb5ec7011a41573 - arm-trusted-firmware/plat/renesas/common/plat_storage.c a977937122b0a3096d2974c21e1d01713d54ef5b - arm-trusted-firmware/plat/renesas/common/plat_topology.c 5f9406be82d4cf619e442556228de3e2d1283e39 - arm-trusted-firmware/plat/renesas/common/plat_image_load.c 9e2b414041c35052396135ebdc28539af32c2593 - arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c 3c4b66c3e0e2ea740399f2ac87b9c61af5c45031 - arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c 2b4770445484da2ea7c1061c5e772905f5f9eda9 - arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S f99514b828a7a7fe6f0063a291c023d74a2c9bd2 - arm-trusted-firmware/plat/renesas/common/include/rcar_def.h 72226e12e556432cb547181aa73e0d55c5c8777f - arm-trusted-firmware/plat/renesas/common/include/plat_macros.S 2f021b7dce5115d413267052dd5b471ceff900cf - arm-trusted-firmware/plat/renesas/common/include/rcar_private.h aa601d2e26e65cab57efac1579ef07d5a4966f23 - arm-trusted-firmware/plat/renesas/common/include/rcar_version.h 939b904cc911a51e5bfd33fc817d5c5b22e55400 - arm-trusted-firmware/plat/renesas/common/include/platform_def.h f4aa97332efbbc8e20e48e338443fd3b9c208830 - arm-trusted-firmware/plat/renesas/common/include/plat.ld.S 64ef91e2bf3528ac94c8eb79c5c3f80113257721 - arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h f5943232ea7fe8a4717cdaa5d1f371ec634c8074 - arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h f773e9cbe28c8c27bd7013b66cd612cd63f790fc - arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h 954d720bbb952517040ea8c1648e94dcd01de552 - arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c 65b77a7dbb8e28f892af2bf3b76eff17c87a9cbd - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h 147f2e7e737cb6a5eb1dd98a0deed8c0462d2041 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c a1f884a99e9e14ac83551e73429b0cf7a2c5aa0d - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c 2311f962795291fdd649a3acb3d3fcee85e19d11 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h 60baba93a9e38f989d8f3fdfb045849d1edc2d69 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c 79f7407103c1059afb212382689fff9c6a4f4350 - arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c 6ea11f2ef3d7978e714cdf621aeb7c8719c7edf3 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c e8797c2639ec349e76fc1946c984275c010e4cc0 - arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c 2c689ed8bfb3abf1dc9ea37ffaa8aa9479649eac - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c c785e8c07a0fa5d01b9ecf8eee873f7a18697e3a - arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c 5f97ccaef3ab26b2710ad26fb0fdbd9facfd0b7d - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c 59510c739cc2d9619a9a5c21e1cbf1bb05094867 - arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c 69ee13cde36accbde0f355f89f9cc2b5d1aa2cb9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c 9fa0f4b8209945eb39ccee90bcc305efbe10f211 - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c c6e2fab47d050265fe94d5ce57fd1a3a684da2c9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c db23baf6374a79472a4b930f1fd68144d4f314a1 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c 0ff28a152c1c0997120e1e3a5fe654f1ae19ac60 - arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c 1a879218f61e83b5068e40a2b093fdb4ab851a4d - arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c ea896d0f1d011e14c4411020d73d083c22eac783 - arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c daa5b1a54bfa63c73acf8429940662cd450f1eb9 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c a71cc21b90eb5b1d29b125e9c98c3e50f9a145bc - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S 0842c4cae12a7c22367b83357a2c824d060dee67 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c 872e517062b5b548f6de42424dfb8290309f6773 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h 5cecfb1042c66b79c4c4c9bc5961fd91b34c880f - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h 44573513efade3da9aa2ca94c3d4069a8af646fd - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h 0bb02e303d4c696fe34379bc2d5dd9f2fe16229d - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c 56e5fda520a793a37c7e8daa1ecfe2354b26e99e - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c 42d2fb2461687118d1f9e79ed2ae2a274cc91c45 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h d00c0cf869839d6cd370b5b6c58e8d066705e2e1 - arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c 40c2d9f804ed183a8befa38d61bdd2164d711b34 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c 344f94187e37e08b2f532eb66281e7e28e7702c5 - arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c f1d76afaec515fb65236190a9aced6e0ae2b4d8b - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c 4e66aa51fabafab21b8e01fa4f3d49fc8fe6a97e - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c f0aaac82be8c1b465622b1b82d8514de62c2e937 - arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c a8ca841fb42e9bb5a9c071732f25138003b82d96 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c 1b64a7198143a5ec5cbe075762bfc0f47e7eded0 - arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c 6a97369a4a693cf002e5f5f6ece32516e5978068 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c 80f0ae31f4c2b57b330b01be44b293f6aa2cef72 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S 965bc32da1f0ff9aa830bcede48eaca19cbe3b29 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S 12bd9050e1d74b888a3866cf8ff79d17103fd0f2 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S 6c89be0e3e7e102687ce8d216227785edce4db33 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h 0e8b8f431e24f28a92fcd4fb9d46eb87a1113db4 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h 71cc1316bcad08255d76ad0ad858f47d681be60d - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h 58c7ff47a2230af870313a655dcab4f22dd64957 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h 61ab3a7cf4de99459f74b40ee4aa7c4c063f92ab - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h 6a269296c2d98fb8f6f4c1736696c4e6081cbc88 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h 2cecd73b6df5a49196420939a6810672640ce165 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h 716620282caf3210c15f6795e996035311a8ddd8 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c 8f4af50a0df849dd31970be55e943ee4302b0472 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c 9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h f1c6500edd19c1540f562c4ea2dba8443a7cd419 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c 4d33d263a3f05c3d8f3400a45afc2dd7f1792669 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c 7bdf0ea1da45eaab8f21dca700b29582ccc57d0a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c 266ed9c2a714504a190f6bdd10db0d40815a428a - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c 3f6403fd39850e34f4c3bd674ccf8170f74af43d - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c bc3edb20ef2a7baebacce2c631f800cb6d206bbc - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c f1e7a83b618d37eb2df8dcc4cff814b934a4ab74 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c c96d4c2fac061ca1e3be3600ee8748de11d20ed0 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c 4f7afd096359c9aad1f7852029a643db033fe7c7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c 01f390bd22a88039e1fc5f2d062ca126dae34478 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c 4b2131b48e6b858b49e7e4d819172c5bc729f213 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c 919f5232edc5f6c3ec1670dedf5bf25fbb59356f - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S 97ae958df0c9d8f54ff36a7803fe0ba27434e45c - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h 9acdf9fa5a506b13c376584f49b42a4f437af6c5 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c 392f1834ac5b4679e9ae724c7cf1f3a20c0e566a - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c cc11d9f29f29d9c9366f3e6c66183d38e3031ab7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c f83bec0cc962f915447a4582455414387713f7ac - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h 86c5d3b710ba9b63aaf82c0f9dc1606c22176f45 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S 9fe71c8db281a9fc253c959e2bf8d7ed5b59f658 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h 0f1625972d53fdedca61514318bdfd1ca806ac51 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h 3145664e80460f27bc2fd8cda127e916e518678f - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h eb840b0d5bb6e8cbd42b1ab32b72baec165926e7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h 29b7013d6e080d93a60b3780f10310e29aaa6bbb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c 04e2455b39d088cb56ccb73dac9c842fb6f6b7eb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S 8d8ccf9d72fb421744052b95f2dc698844542a67 - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S 29e2e91f84a20d0c2f220e0eba6c447909e5aab4 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h e26cc9cf2cffd853101d24b0e6cade82ff5f5cbe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c 8211399dfbf7994faafa28d85d5d232265c000fe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c 99aea1bcabb4f6d0d7452ad42116629d21bb2b61 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h 9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h 027eab15e763f75779fca4721b6612e1cef0f74a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c c0c43ed673f4f38bd78a3d145c4ff0f553bf3032 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c 80de920eee6f0214b1cfb2cf104cd6d295bb478b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h b79710e67347483f51ba3aa8fcb25a7f7dbb5083 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h a3184b54f314a3880b11bd80e9ace2a825e4e251 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c e0382b98cbf2ae3613453ec924646d5af8b1f11e - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c 9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h 586996360a2bcce38bf90fa0b1b7a20a45c6e26b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c 25524fffee705cfc27dd670e05523c5de9ef0ed6 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c c7d9738b5d030b72c12bb9649d2dfb58e180b5b8 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h 8eca9aa01df9af91fe07386e941d7557eae7d0ce - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c eecb4e28621a6ea2bbe58371406ef5f58590424c - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c 0b8ef1037611c38ba89966b1da4ef153e47b4fb4 - arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h 524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c 22974ca90d72fb96f260417ace863c692dad5cdc - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c cb622b7fdee1e5387ed783d371b6cfdd0400df92 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h edac1a959247a82db5f820097a9f8ded6c4665b4 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c 7a2d810a3f11780033972a9b1f3f2eb09adddfc5 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin a4fe0b238351912e5a3b7e1de16ea4b470dbcfe0 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h 985e72c79b58499d32fbf6ef6f46a741c6356e9d - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h 859692a896bf24f76093c6cc1a923f3bd7f06c49 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c 0ea97dd2ed72ec48826e4668463b1067b1e3e91a - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S 0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h 5817c26932930a69f20037fcfd33b6f700e518a0 - arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S 9213c21ad6f4d071ef85303d7f16f295b02bc212 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c 85d08d7cf74717daed56a0770f3c79bca90280dc - arm-trusted-firmware/plat/rockchip/common/plat_pm.c 4761873c26add12f8bff6e22a79c209ce1923023 - arm-trusted-firmware/plat/rockchip/common/params_setup.c 32f9de1c486103a42cf6a9d291f42989b42a98e4 - arm-trusted-firmware/plat/rockchip/common/plat_topology.c 1f63c15382d48351f3d1c1709e7428545ce2cb72 - arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c 3bb10820f3cac4793d72ccd0dbaa9513b9945d80 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c 4a1355d1645ef943a89aa54999041bd5a970c764 - arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c 91be87581dcd25681be045b39eb7934ec59a6fa9 - arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c d30876af46d1b3b1d2c18f43fa7894f8fda3c5f8 - arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c 258f177b9b9412883f714cff3406818288eca04f - arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S 47fca1d947e59a046afce81911f7f552c72c6ab5 - arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c aceb5792fbe22f18f421f2a754469db4f6f62cac - arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S e40967392bea64496e752401f887b55eae946bf3 - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h 5c96dda447934109fef22dbfc20108fea56100fe - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c 5b690165e56aee2f4e71841059154598362ce876 - arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h 5c6218088ea95aa4cdcffbabdfabcf2054405b9a - arm-trusted-firmware/plat/rockchip/common/include/plat_private.h 2360baef8c09eed0a7d7ca2b2f97f9405c9bfd92 - arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S c08e0dba86277197d207590daf335b7a863f4f32 - arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h e0b9109d2e15ba78290c67b35d231cc82990137e - arm-trusted-firmware/plat/rockchip/common/include/plat_params.h ba0fb41c4b6e827fc3092feb1e41d096daa7e77c - arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S 505eeb07bdc39ad3e19a4f6676774af764d3c300 - arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c 63a3ba51a470fe12e6026880ee67d6de178f8590 - arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S 23b124a5b49de1ae84aecc76669a8e76f9579f93 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h 4db0b70aecaf5352c4deda76075a44c7ed772f91 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S ef5a8ce281d95041b91f8f165ef782642d022de2 - arm-trusted-firmware/plat/rockchip/px30/px30_def.h 6fd13eff5a2d17a6f2e651b3eba6211a93d3522f - arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c 288f8f52c9a5423576d1fd403f776da8e5906395 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c dbc0dd67905cb60b55ff82d4f1d8bf96a7ec2514 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h 7129bd0759914b2bdbe0af12743e79277b990a3d - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h e5df7e7476f59e23d9c3c1097c64bad93fb273ca - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c 6940e4242af969ec608caab6d93dd03364b78580 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h 338871ee4d601414cf6ab0c718cb19938c37c7b5 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c 4661321c301694bb1cfb029693c60d50387885d6 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S 4abb3f49d90cc7242ff9d366432f9423ed190c44 - arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h 8b1c4b26a5cf109ec97a2bd711e46dc76c20891c - arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h be822c3b60a3f8f4215925d9c6aa8ff3d90ab56b - arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S 80988c6b4c1d5c128f556b4704d2a13dca1b94ac - arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c 07fcff2e4785739f2818730be2df2798395d6dd0 - arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h f10fc723b4f781fa92f52d189e12ab2599f2be33 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c d6f6a92953b02dda92949d05699b4a8c09ec1ab6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h 81bb90565c30ebb1d2a2074e665099c5df4b3f16 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c 912b3ac53149ee0912cdc571503cbe6f5d9e5e31 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h 1a0ef7b5013eea98c8892cc73f9acf7aadc6542b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c cc96ce897ce3dfd398d571f73d60df020e312a7f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h fde45271c5e9a03975a13a19aa58f7ce1627247b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c d4edbc276d8a41ceabeabd135ee44750077267fb - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h 91fa17de464bf17060f5d782d3addc2d250f2bcf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h 341cf7780e76c0eed9bb587ced84821148eaeba4 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c 455f3ca45423a7d3a17a25fa9a199ee6f33accdf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c 8bb28c62f323cba1149703071fa6c9cd723e7681 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h 2f72933afb37b859ea9a98d233ab11f81301c9db - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile 98a096aced18ab4c9a4b3ab325773ed273acd4cd - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h 222366fd88fa37c34896b96be4724020febaf122 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h 3832f35bf0192ab6299ed6f72d97ea798c64ec01 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c c651d2e10f915a285792aa7e66836e66a3fb3b68 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c 249a2bba707f4aae60e76e4d2ca07180426f3657 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c 9cfa6b80558dac90724c830c7c2b792099232962 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S 15ccafa1fb201c2bdc50eb32beb4d9331e95424b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c 34cef331645617d77f27ee050065b2678b021605 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h 12d0e498bcf7645b6d17eda0b6c88f9c68345720 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c 0e0164a1fd25ccd71404f643551fc197b6d3545f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h 8af098c906ff4222b7fb1b8a8e528a842931e11a - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c e4ba052fe71c1dbb0fd712a9e23751995fa17236 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin 1761d34cf2fa35e5eaf8e4707cde5f3fec7345ce - arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c a203f9155033bc4a154799d63ebe669baadb7c82 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c 8080df60a96f3ccb59e64a8c4468c29298a40160 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c fdf96b7b34ebbd88b6c053c20c493dfcd5d2eec6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h 26f96f6bfc5d8cd2811341eaa144693019daa5cf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h 21c19d18b927a98e453d2dd32fa075e1556c8d10 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c 4f34aa4fe829a116338b7c8cb363091b98b1df1c - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S 735db5fedc39c83875dd50d345431e840a75ce95 - arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h 0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h d037385198294976c392eaac15722c2bc43171e6 - arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h 33691c33d59c3cbf5321efb5e9cf1ce6f908b1b3 - arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S e27f9ab0eb7cc700bac4af81ef063675ddea3d16 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h f61d8134dfdbc2de01b130177e3623bfc96e582b - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h 514bb50a35bc277734414a501833d9cf9103b613 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h a3ec096942a7038a658d2de2da28c8d7772e2601 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h dffb716056a5cfe4289bde5769bacd0a9c517467 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h 37de06dae36b2c9133dfa3db58b9403eca97534e - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h d3a8c566b07530d947493f642a829c2173e7eb3c - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h 9eb41f0b086d93dd52f10cd88c871e9f872da485 - arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h aa37703bdb16d2d93c4cb6a1c3f5740f10400717 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c 888b9ca7b2dca798b061df341269bb1bf0cdc6a2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h 75d3fb351c1418d28d1be951921dde7cac623d53 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h d6fb6002e2f08bc736d1fbcfef5f7d518331e24a - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c 74e69a5d06c7c10f8fd04052bfd92c89a6b685c2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S d0cf327dcd15f8fc85f2c3c93e82fd6199973f0b - arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S 524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c 7d9851bfe1b3a6bff1b3fe3a5a42152bdbbdd641 - arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h 408d92dc22d97bff7148a2338e91746328b4bb4f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c 00a800ecdcad577d80ed2968cfee8abc2ff260d0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h 70ecc34e2c4236edbd52a088d6dc72300d1038e0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h 90e4b5914845f3238bde4617bcf04acabfc52406 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c 53d9e3936b39e758560745d492d1473ac9c98278 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h bcf5a24d5d284bc2b87c3b5299a9f548df4bc95f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c db1ef060ee221e9b61acbb781c42ed42e926b26e - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S 0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h 58f0ccc10fae70932566781c7c34457a239e027c - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S 0a2a001f434d83ab306c453b6d60f886a0b59a96 - arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h 1321792bce42c44c3fed91fea86cceca52486ffa - arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h a5a361643c76bc6ad4e5bf4bef498e6de89c4065 - arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c 4677f1e48833ef10dc9d9ed492dfe849c8466b05 - arm-trusted-firmware/plat/ti/k3/common/k3_console.c 170634ac25c995303394743ee26ab4f2265800ca - arm-trusted-firmware/plat/ti/k3/common/k3_topology.c 96d874b239805cfedc0fadfd9f07eed0e423a919 - arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S 55b3083cc472c5a3e1808d642b6c6516d19c34be - arm-trusted-firmware/plat/ti/k3/common/k3_psci.c fd1bbe596ff44d2104431c2924e172d0ef4c5b34 - arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c d3624f3dc097829d1b9f6b277bd1aebe77963d97 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c 27b2ba24623a62aa30daea138411571e17aeb579 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h 55f8380907084a69006d5211123aef60fc51400d - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h 3ebfed887a97b672cad608bc064e08075f4e2a29 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h e81feb55a2328c2ec32fadd561eaf24eb58ae202 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c da89ff4506058f3e90a127f4e7d79a7d86057bfd - arm-trusted-firmware/plat/ti/k3/include/plat_macros.S 015fe87701fa82cd48501c2915505c611e20e933 - arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h 33ec06e0674715932071745b37498c738414ee8f - arm-trusted-firmware/plat/ti/k3/include/platform_def.h f2111ae0b834107dddf37cb4846a7065472db0fe - arm-trusted-firmware/plat/ti/k3/include/k3_console.h c82ee96d8fb1841fd3068f489a697625a217aebe - arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h 85bfc710f2f6c79b7c0e025f6f6e653d16f39bb7 - arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h 3139c2b0c93ae17696224f59b5486f65e1649dc7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c 6a49ad3765ad1a5c42b66eea4f7aeed6c721fdc2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h c0910ed9fa547ff95728b0592ee3be13b3615d98 - arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c 10b1e53e6d0c0b259d531d284d6b2f64978ff33d - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c f171c1cd88d3ea2070a747ca519f7d6b9e8257f5 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c 743906eebddff48371349626564704fa54fcdd27 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S dacc55b49253b5d86f120fe7e2ed1de0aaadadcc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c 7b00ed042c247bac94b4766cb42dddc0e21764fc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c 4ee1c481f43d2f2b9798ffc1f9c6cafa4d1cc371 - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c c7727e6a5eb36a39432103f9641b5d1c522fb1a7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h 77c94644e0ef95316e08e0a339fb16a856ae5d97 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c 9ad0a2f43f8a0c69c26073e06425579f59986e7b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c e53bc6a3ed66be157fcca494d961241c4a067815 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c ec9fe0a8eec79fee1d3dd34bf1a969b8f0b93f4a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c 82d557ad976b6dfd8dcdce69b68986e9be70cd5a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S 0f0baced38fb65393cd300bdc024b68e707f5f4b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c b900c2f6ef836a0f77c00c851815a09220d8c5e3 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c 71c56ab2e235cc9495de74461f1e2035229c09c0 - arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c d0b4272a97d261d88b6bff05bd2162e0d939ffbb - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c 43753b990fdb953ffc38ef29474ef4af453444b7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c 3cdcc47dcc28c6e6de2c940df01b5c91d95af92c - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S edb672bfa3c76059c60544793fb08658398cb3b2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h 58a5d9c283fcb21c6328e65dda44190d07fe6bb2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c 406790007d4d597b108faf9871360acfa7cdcf23 - arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c 89ab811529f632c51fa5e732be395bac1ea89887 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c 3b882920ab056c9bbc38be63b2715e1d796109c4 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h 34bda94b3b92d9b971e0e52f26c98293f35800df - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h 7eaf59b974175885a0dfccf0b42c774580444f92 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h d12872b893bf8db2b51b7243dd638bf34e9d6cfa - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h 6d6391c62306978263be31d559221680ed9b6025 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h 0cbf680fead56b073a247b36589a06e814bf8995 - arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h 6a9fdf66f28b06f20ed4b08bed769e38d88e5995 - arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h 86477b53739886930268a20a1950ef8cb2a1c279 - arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c ad3aca5d4f9af9d21c376f972399e2cbbb7102e8 - arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c 46faa99b227394b11051186b86a163d67c081adc - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c 356f823bccc7081e026233c6fb511c0602208101 - arm-trusted-firmware/plat/st/common/usb_dfu.c 278442fbef0471df0addfc2b3ce1b10552541e65 - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c 0d0e487dbff201564fae2a5f2e0bc45059a3ad3d - arm-trusted-firmware/plat/st/common/stm32mp_common.c 79d69f4be6d9e1fc494884f41f92bede1b67c8ff - arm-trusted-firmware/plat/st/common/stm32mp_dt.c a0bc3acc4ac585d95f9023d8859733edb1ff9c9a - arm-trusted-firmware/plat/st/common/stm32mp_auth.c 7a33a3419c93c0bbb21a2c8df792965674477cbf - arm-trusted-firmware/plat/st/common/bl2_io_storage.c b6a6f8374d7f3eadc9cd9b6ad93f62ed12f6851f - arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c 2a0d6172df32ead3a019d2cbc33e260c3aeba294 - arm-trusted-firmware/plat/st/common/include/stm32mp_common.h a48402444da4bcb7bce60d2e3f9972f07bebc8a4 - arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h 8c442ea195baf9461f2165bae528286c5a71e7ca - arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h b270dbb723f5c002dbf393eb752ccb946afc5baf - arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h 4ca9fb0296b649411cecd45263ecadb41540d6e4 - arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h af93ef4188fb3950141bc4c2a6e971e965e5c071 - arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h 1125720a4a5573b7f8197d2dabdf308f51407896 - arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h 8bb1550cf77c8680e05ba46ad44ab77ff26bb8f3 - arm-trusted-firmware/plat/st/common/include/usb_dfu.h dd7ae18098736e737a0482a59de65f64d5edd503 - arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h 08fffa1ca580eaca04a26cfc974edd901c2997b1 - arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c 667de698f76e8d0b6d6f1b85f8012f3bed27e925 - arm-trusted-firmware/plat/arm/common/arm_ccn.c 9b812991736d46b06d462799a31eb49ffae96260 - arm-trusted-firmware/plat/arm/common/arm_gicv2.c c3c969f538ef3f3853d867a2c9c020723e5adc66 - arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c 1f2643d0dcc34c7b46895a5dd300de2674cc1274 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c 8d5a41b0cad025e83538d4508b8de54c96dd6be8 - arm-trusted-firmware/plat/arm/common/arm_pm.c e460d7f371f1102e3c39114a43c606937f3c9f92 - arm-trusted-firmware/plat/arm/common/arm_common.c 9ac215f26148ab94b630463319c086d3e8b88c31 - arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c e58481ddddf7e4632598a6ca543bfc9fcb6a7c48 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c 61b4b6215ec4cf4e050d7a14359bfdc2b64e2d8e - arm-trusted-firmware/plat/arm/common/arm_sip_svc.c 53d385569ada7ff06030853184930078d8a2e4d8 - arm-trusted-firmware/plat/arm/common/arm_cci.c 3b628c17fd98697338a0997a380df8a81c7d2e66 - arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c bb20b499eb4fed681f076d21eeabaaf686b1c7fe - arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c abdb20c16e5bae6df0e447b4a356eb5b9ed3eda0 - arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c d2c7c17798553c8d4e29f9b1bcad9e2754c97e6d - arm-trusted-firmware/plat/arm/common/arm_err.c 5f8fb896e304dbb204531641566de21b2e53a426 - arm-trusted-firmware/plat/arm/common/arm_tzc400.c 842368bd1a44c1ece633a1254dc3cdaa4983c6ae - arm-trusted-firmware/plat/arm/common/arm_topology.c f2f3b9e0893c37d6ecae1332b3df925e9ab4d30f - arm-trusted-firmware/plat/arm/common/arm_console.c 70afb2dd0a66c2a2b6eb5bfaf16df448d90e029d - arm-trusted-firmware/plat/arm/common/arm_io_storage.c 420e2c07ae07c6152cc914a3b464ec17f2f92843 - arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c 6e9da80beed8b267a6c15c88f8b25e81d8b7bda4 - arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c 845db666afafcf708e365edd5461d9071f72c738 - arm-trusted-firmware/plat/arm/common/arm_gicv3.c dd2c481628c54d07d905a85f08e527943473d31b - arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c d663fd87f45498acaee1a4325d0e44e561dd102a - arm-trusted-firmware/plat/arm/common/arm_image_load.c 6ee204b0e2a5012ad4dcef1cfe9fe884590bfb8c - arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c 1177013eddcf476b6a6d1f3367ae319363663450 - arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c 425d4b8c29564ce790babb9ea3fcc7ad80224fc6 - arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c cc6a2551546758984d250e491c5c077149044f98 - arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S 8543903cea745c6c6709fd524622d3d5d3fd8df2 - arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c 17e3af5dfebbe4a8933589c7b3c67e14faa7dc12 - arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c 361186531a919bdc7825945fec639bf0db44800f - arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c dce55e77a6a4b9da7a42be37f5bba717d0c353e0 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c ac62b3ab6e132e1747dbd2ffd6f40a72b4270235 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c a666a9d920e0637f17e51eff519cc94c115b1ef7 - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c fc971d9e587662fd23f35aa2dfbf0abf23c9da74 - arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c 3ddfbb8ae3448f315371d7a3a814bea1d055cd3a - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c cacda44b3716b65a5c30eedd17ed5a1335b8597b - arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c 43a64183c368a80bc24e370c93889989a49bfca3 - arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c 8c6171b381cfc6eca906ce2f7e2e6658895380ca - arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S 3237cf84bb44f0cc5b45b74d69d2934525543135 - arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c 5072fa161b5fff3742a05eb8b9def551087be013 - arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c bf1abf676327ef4b5c2fbe971bf5c59f9eea2511 - arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c 6986ea7e2525388afa6171359d9f0c71de119e6e - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c fc6ffe0f853fbf9871294d23c034cf4eb00a0b99 - arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c fb1634b97815fe2a2d9fcc807b394bdf1a034423 - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c 408a01ed446d78cc578fa633ca47d7068ede3735 - arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c 6a32e8055bf1477d80b315a472542bc3c28106d5 - arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c d55a2717a5f47927531e46527bd40fb912dd16f2 - arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S 883fce52c6e023b9718833ef01eff53d740f4b22 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h 21772c91952bd2813284b444505fc85183bed867 - arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S c9020cce76399dabf8d4bf04257761ee38ea4d60 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h 6c95a3344c3a15036b1db884d62a972e802699ed - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h 00d4810ce12b4356434c80bbf98203811ee07a32 - arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts 5e82b47a941edb5ba37196b7aefe2a54e3bd2f81 - arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c da446db6b40b974a31d66ba55f23047f28d3f748 - arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c a12ad9fe2e578f1c9186976a41033a398307aba6 - arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c 5c168081100ace91d38be064d9d21551630d21c0 - arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c c6341f0f666b8a901520e32310b18a323af9f925 - arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c 31824343e1235090b12b73c827b8cbf02ba4d0e4 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c 7a79c4c409726322831974860de49b71547d6feb - arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c b33a69c22fcc5e0d8abd886b78b557633834d721 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c aeb8a1b51452a7c1b9088cd2cc5f0c6ab2590b45 - arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S b30c67527c7802085733426c8c113a7ab2492ce8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h 3bb8192919eea022c0cfa99a7d87f8ecd4588256 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h 468e61508695c6dc9df856865e295b59c32a54e3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S f340bb1f1f4dcfde1ab65f3d67e26a33025f37a6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h 5972e7acb9e93b201406ff9cf0cbab522f942eb3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h 4e4ddcdd110f807b8dcbd6b440a4b4f5c2f9e83b - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h c388d0822e5ef0bf97db4c66ab46d4088421f0e6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h 7617a0e9164a7f90465861eedd913dabf15379f8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h 138c1bc36bb3c91d2b2d9f5ac1702aa0975c850c - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h f00b456e46701cc6a1e2b31fdd93091805ab0809 - arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c 3bc7caa521ce87bd672c20940f330d81613afdc1 - arm-trusted-firmware/plat/arm/css/common/css_topology.c 75cc05419580aa9e613157ed0cacf5e0447c7d7b - arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c c788e65cad1a1e84654d127315052a3bcbd35225 - arm-trusted-firmware/plat/arm/css/common/css_pm.c e35946648a3f4e38af67096b19e7cbe49324a3e2 - arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c 3ddcf64aa2f7a53edf4016ea4d4c636a371f4516 - arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S 29476751ce928c5170b93c840f4fd925619fb9f9 - arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S 795d97596b09631253539c8a66fa49d5d422d01d - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c 3693a7e757b2541552b2c91c91a0dba2d6a0a8de - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c 73d0e620495671f0ffa9cfdd536e8f3c97f6e384 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c 1cc6a4959dd00202735100b426201a00f18764ec - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c f8bee970c03b0a4da0d79dcc8895e970ff34ffa1 - arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h 3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts ed25350e5c803bac231eea3f950d3e7e5aee01d2 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts 77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts e12be214b71705c426b59f867e2c1e12d74eb660 - arm-trusted-firmware/plat/arm/board/tc/tc_topology.c ded1714043a17b1985c18754683ddcc8a2954d2a - arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c 4335b9a6f68fb49824b223397621a29f3d1030c9 - arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c 868cf0c3ac2a02db664b5bb1dc788646d79823a0 - arm-trusted-firmware/plat/arm/board/tc/tc_plat.c ae19b2b5534ecfc11125374e36d9e8f859a89eda - arm-trusted-firmware/plat/arm/board/tc/tc_security.c 1f68f4b41cf660f6aecbd9c91cffd25b5da791a9 - arm-trusted-firmware/plat/arm/board/tc/tc_err.c e359fea3cdefe52d1384eaf4e3657d1a8639ce5c - arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c 28488a6123a3f6e963e45167297c24b033c4ea20 - arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c 8ad72d03b3ba43d1683a1303fee28ea1c7be281d - arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S 12e15891d91866e073604872dd843da7a55ab1ca - arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S 9660ea0d565256c4b8a124a3b15c393be1d5f9b0 - arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h fbb9a21e701abf6a427a0a7a4f52bdfac2d65ae5 - arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h 46c4eb5b1105e6fcf9a5ebc8bb219b4f6250ef79 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts 6d8e682b0e92f3c4b0317af9db0cf378942f0637 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts dd7dfe59caab52d2698deda4e52c6508f481ea7a - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b6a0718fcdad5e07263ed41c89641a47d843eb14 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts ae7769a5c9c26af057b45ea638e7d3e8f7905d63 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c 20df07965dd541c0c14b55f71c827c0b992b608c - arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h 673d2aca63b2cddcb1fc087b3849b8459c60178a - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts 77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts 0edacdd0dc4a2af6f50c21ccdf98244fe72c6730 - arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c 885dbc360b97a82697b2978ae8f5665ba4878080 - arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S f63762c7a16038a4bc3a046a89d815cf9ae9089b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b48500f3591ea941f29e3cb482855cd947d886c3 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin 99b2edcf01ed68e8e25f2687d31ef61f0531f26f - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der 2b0cf90adf32af769b93e85764f195737286be65 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin c4cd605f9796351468c8e3427ec60a3ab5966a93 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S b22a3e04b7c492d96f48978250bd02b1de04304b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der 64194de14ee2424df1ca72d388c407f3d0c16184 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem aa5febfe9cf8a923785e2509c54c7e03032167e7 - arm-trusted-firmware/plat/arm/board/common/protpk/README ce90ae54534188e8ed455e84da4ee7656807dc45 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S a819075a49fd85dede74b56ddededf2f4c046f07 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem cdb90754cb9118d6571aad9c3846b2c410f708d1 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin d7941a7e9ec8fa11c4dd7580b57e1543e335d61b - arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S 0b886935846ab1d278829932851b6cc492f106cc - arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c 53c5a79a63bf1f5551016da97e29bf8702e32ad3 - arm-trusted-firmware/plat/arm/board/juno/juno_def.h ebbb9c3ccbc5ea001a213d0ba5a9b7744bd561dc - arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h 6cea3743018f1d02cac51c8d78a92561ea46ce14 - arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c 49553a7fbab54730a1b3de994aa92810c35025da - arm-trusted-firmware/plat/arm/board/juno/jmptbl.i d784833f267d4a24f2a529767e8892a4aa11df9d - arm-trusted-firmware/plat/arm/board/juno/juno_common.c 905aac590f6fdf10096fd3e0f4bb661a2953acfb - arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c 8a5716ff7852804effaf5810a335e69d3a788a50 - arm-trusted-firmware/plat/arm/board/juno/juno_trng.c 07f098d234d16533d40b505e91dbb1aae1712650 - arm-trusted-firmware/plat/arm/board/juno/juno_security.c 17d854b860806d6ad8af6ee63952524a3bcbd9e9 - arm-trusted-firmware/plat/arm/board/juno/juno_pm.c 419b6382a2607911be10024a6287e69289234326 - arm-trusted-firmware/plat/arm/board/juno/juno_topology.c 0ff3d7a6c51d9752cc2a86bb19e800a94245eea2 - arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c bef868e2dcb239da5ba7d1787c2f790e1f31d33a - arm-trusted-firmware/plat/arm/board/juno/juno_err.c 50963e02933b9165b4b2c2a4b8ce7f8cc758df7d - arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c 4780ddabb988fa673f07503011a00242d2ea9faa - arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S 53f8c45c8436fb9bb4378cd8782a0b7d8037e5d2 - arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S 821681f18e15e60a3d540f06924deb6c691c2d7b - arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h dfc9edcda0daf49b40451e94c30405aa901ef204 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts 805360ecd38e071b1f2e9b60704130be813557e2 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts 319dfb0515299119770970eb5953825ab7abd95c - arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S e3d086dd3e36ff5fd58f3282c011f6394739185c - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h 4497a7586471f072a94ff5a066931c86dcb6fd2d - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c e902fc33536870bb2460962782828919e301f53a - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c 7d80d6700188f44364662e46113af9036afedcbc - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c 7104250da7bca258ddb0bf081570d32f8900092b - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c 5a64604c368489c4585ba4e01e129b3687e5d8ff - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c 4b16feb977654bc82a89a104dc5b31b167bf17d1 - arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S eaeab6f905d711a8fa04d0ce9d2c2ec485934eaf - arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h af1f8d5af2ee91ba0dd180c42a7b8f73b7543474 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c 6733f3383940d86208b8239c1d08d9221c2c2929 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c a924444b8053fdd6d907961d26d25ef0d3a207f7 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c 300e69aa5df2f362bc3ddf1c430fe3fab03f11da - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h 4a175994a02eeb79a8ccc76f0b3be5ac2d45771d - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h b0261bd454617bc33a79aa98dcfa987149992300 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c 87d9fc22d1228a7faf0c17443f9d5afd194e4334 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c b370460e14d8e464d9f852b0e3f18cf2dca4950b - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c 103c2c1d17da9dfaab63bca2f61e6bd21aa82c19 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c 19f1b6fffc9b7e4d8a55730d5dc6740b06415c71 - arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h 996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts a857b4f74c6a05502271795dcd7a71f24a024b41 - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts 2ff5ebca71b32318bae21e3dbb7699236b9cbe61 - arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S d56cac77b62eee0ed50166d2264e0a00c8fe4ffa - arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c cdf2af8fe7e5ba8b9ff36e04a33ebff2cf20f79b - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c 007839db0f0e5c02b3362ce770b02771a47faa27 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c f2a71185ac9189cbe4310e27a7ead8d40c23c377 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c c8bea252a67bd4f3ad0910e3dadd0b76dc62c7f3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h 7d714f8f2b3f7274c9d2e73eaa5d46215c7d3911 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c be0cd4f5f48b5eb3a64885536643645036173809 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c c6fdde231ff1fe0ddb8f585bd3fead2a7f2f0f46 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c fabc6650d0d7860d4d615e5e997c72bed71aecb3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c 189ef1e9d436f631711b2a4bd2e75efb635a322a - arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h 996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts adc821bdac8aebcefb26e3f8cd54497b3b8dfab4 - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts 142d4bce7860550461e2498ba8c9f4ebb17d902d - arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S a8eb0724c2056ed80453ea31aa3ebc822e93ffa2 - arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b20640f66687a9edf5c361b2cf32bf1244777ecd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c 181e66fa9c41732917a323ee0fe465da3b5ce36d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c efd5139ee502cdc5570d9ec338ee84b3410067fd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S e985480b9d1aa1426a500f3c4869a1f32bb8b422 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c 860f2b3b1633322a3865add4e226f457c1a7237d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S 93cd93fd9277603c0a72cf1c730d6486a6247262 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b5fe2445bbd4cfd3d360d2d930d9358c4eed5555 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c 5f78d5ae0c4547371279bfc19196f01fb454e3b6 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c 2ce9cd0a5ef399a537316089ff1451da165bdd42 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S 1f85fcf3a3d2c0bd5a8c5e848a4841400b54f9fe - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h 486d3021b7aeeb557efb82cafa7337d3d3041fb7 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c 8e7bab3de835fbccc87f8d20b8acecc011d4fcaa - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S b1777d180724d85711393cf136ad5b34e80ce86a - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h deb3a6a31fba479e597c0ae722532692996e2372 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c db240cab0da9aaf6298ede4c8418abd28744a258 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c 61fa6bbfd2f41f1cc6fe1c4caacb1fa09461692c - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S e9c7e8c62f6a1ac8f4b8f79ebb080765f9244fbe - arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h 5356ccdf1172f23b213522e8c204e511fd9b8841 - arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h 1c209493074be7ae85b1aafe237784f10e2b7093 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c daecdf40f28b13596b217b424164a59b35baa192 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c 07a42e98f0211f264decd0d40369a5a22999a7a4 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c 39dd88b06678aa7f03906487a206a758c69bb621 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c 5a4591bc131dd662dddfaa201c233dc2e6f0a9a0 - arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h 3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts 4eee465e298e33cc2776504ed671b987022fb333 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts 77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts 3d1a55d785180dd11beb8473207268d04543695a - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S ed51f976efc9644368dd64840ed3d158c086650e - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c 90dbd482aecd4e6be49f62fed93a4b38e4d79784 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c df9742f665da99900fe4a3fdc0b6fbcc02209a0f - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c 8908fa02b1140f0d45e9bdcc3d5552190eb3af41 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c 5f0ac09b373c85fd1d635fb4f06ea45011389b19 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c 688520959b3077ac47e6c17fd87614f5400ec96f - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c 9f9f59bab890a50e0444edf12481248060aa9c1b - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h 3c1fd619c9a1da90f7af84b9c6e1b8eceb5e7a20 - arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h d2cf1d7868d3a048734caa91b018fb43f56c36dd - arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c bb5bde77d451942a4effe8cd36463c1dfc1df462 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c 4e3d6ef9cbb8925d20f8946cbf6f998ea3c4eb8f - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c 79e40d92dcde7f9d17195a4a63d0608730af9c4b - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c aa3d4b5a511124fc6ae5cd9244633af5ae0ab4a9 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c 7be90ba89049185165cc3d60d523a66fd7a1a0bf - arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h e5b638c1ab3d0ee37ca9b8702ee4262358c3559b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts 0397a242841f6193faacaba41c8326032a1e7729 - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts 1477905828689906107808c1098cccb0a22dc73b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts d4a49ec110e03192903aeabeae1df36bca1cae8a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c 3f70fab8ee8fcd7926df2c977d9380f53cbbb9f6 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c 04538cf26382d09d8e2c07c0b46f13a5b099236a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c 584cb4b05aeec673c6c04da7c3885037b079afa4 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c 05ecf6ab819a6a6ca826e872d3c1fa6a21c7e7ef - arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h c139b0b044ff0f3122d7f6e5b65703bc3fbee8d2 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts 77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts 3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c 95aa905a5aa0734b8993eaf65aa91924c6ba1ccd - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c 3aff6d693c63d2b2dc58205e075552c4f14e24c2 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c e717578fd539b138146efa385134192a8aa4055c - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c 4bcbaa1f0a092433b2d017ed4941be94943fa552 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c 127adaf6d9d5f7353a1893a6f2904417a96def85 - arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h 77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts a19b040188761f8bccb0937f9f397e3b191c143e - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts 9f8fd7d90d63ffe6d71473664ec09b7aa4cdf607 - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts 0e3644e6d15833cfd15ee928af181e156ec27e8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c 810d8a4c9a7dff63b504d43fa4691f19cdf86b3b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c fbb932100f4228bb8fe153a58d84898837188f8b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c b9f80852b169e9c137876fadebe0782792162fe4 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c dd206cc4d7ea74d0dcace11dc6c64faf0d687b8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c c10b97a1764fe4c02c0a7ae81b0a75313edeed05 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S 5562bd387d6506e0db4a62fe23b24cd1c5046754 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c 7bc7cf637e9751cbed26e48c65722c070a0f9d36 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c 1e7fe4ccc25d366dfe5f6a14851dab68001bdb13 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c a5086b67555acbdb3f4c3b25f837cbb372b0102a - arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h 16e3686521725b2e8cf355c2d990811fc260a02c - arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts 70913ecf05a6e846d99d63213b643de746a371e8 - arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S 86c2465abfadc0a5dfe9b561b0f5675db8fee013 - arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c 39be04c7a0d7f7559902b8813b1ded035b592985 - arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c 19591a34444effbe25bc3245bb68e6462bda0024 - arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c 1570105ddfc280d36e64641b556bc2da9a0529dc - arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c 10c7154aeb64129154f13657841ad8f9aee6af85 - arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c a6d08d07ea1ba1184a912ed5ef6a6287291ff743 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c b4b38f929ba25c093b95fc92938eb9b58213a4b8 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c a1e4c883f6912bad1724268901a148f96250854a - arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c fa75b4ccee6e6d8604b819da30a1ed892db70b15 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c 87220bf30d58a155c2f10f38418d094db212e5b6 - arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h df0b10a5b65cf57a485f5eb846e0cfa7e64c429b - arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c d25e9c719859733739581faecd38cfa80443aa83 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c 71418933f8bb76fa971723d4cb9bc6748a009f33 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c d62b302ac0bf1976ed0084160aeba061e325a6c3 - arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c a3147836e6e11bb9b651753fee98a99b2f81062b - arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c 394a425b1d229fbbad1173c1371edc737857d5f2 - arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i 0c3494f4c7e2590865b69abf91d4b49be1ea469d - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c 20e8179e5c61147fc2d627dbb503babac430603c - arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h 6f76c4d8ae1abb640a62785bfc535bcb485f9511 - arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c aed35e7aa732be73eef26face244c3acdee67640 - arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c 223e1339e343160feab72cff7621103ada50dbc9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c 1924351967826f1ad9898254b30419ba2e7fb9cc - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c 0a86ad28b6ae96f93bdbcc32be32335d3e8250e9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c d5a6187ffa8ab68518e9d896c2d50bbf600d68cd - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S 3f4bcd29ccbf7cd09dfe8275846469b38db62e2f - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c 83e404fdd5bc4dda0b68b92d365d6e9b047f13d3 - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c 10fc5531e7b7d5ac9ffba191f525b64179843eae - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c 84180022623ad574044b9436e62202ee5635c6ae - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h aed581dcf8acf86f277ecf028cc1eec4f0c081fc - arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S 12b7439bee5ead5da71eb5a42a9c5cc493f9c7fc - arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h aaff5cd1241ce58ab9627da89fb4860390a0864b - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h c7af81d092cd74c1eba0402a02368b53f801c235 - arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h 1f6772f1b9358e6acc890bc4475a57f68cebc72d - arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S df9f20c998402fb612824aeec7d618e97e023cb8 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts 7dd67253d1f53292fbdd750b1360cace93220e02 - arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts aba68daa32f394274fa0c7b3ebb2d77514e105da - arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi 33a1a8c0c5e1f8f806d0dbe69adab509f55301be - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts 5601a00daf6c8ba481f1addc03652d97efe84a3c - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b8ba7eb0ce440dedebafa08a9e3ffde066832d0a - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts b1406e98f75e782442a0fdfe50c8aad26cf5aeb5 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts 26761d08528feec31bb15a854b65dd46629135fe - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts 43a2362473fca426e3a62517552c20c2a629a563 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b59b8589b390aaea5c26a9621713fe3d78e47e8b - arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c 2c7ccf1e47b4fdac9dc7745e506f4194cce2e498 - arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S 6adce62f756dc0792fb3a4d6aa6cec60e0b54117 - arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c 561594e99d3e16d7826006d518e141e9a58eadec - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c ba9b8a6b4b36804eb8c8aee5b17845c85db8a845 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c 851570d1add4283d5a01ff4893f1558decb2d6e9 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c 7d37a6f29bbe666c9db7538d4d7a123d1ab40b17 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c 866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c 97f84a745ae8fccb804dc7e0ba50b85d46ed4198 - arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h 5d0744ed59fc75ba7204d9d0083fbc0cd64e74d6 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts 869fa43b401d5d394651f9d1bd9eb784b7ebb14d - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts a87583e95c695a2bf6af550cd6fbbffb3eae3961 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts d115cd145587e366c9c6d02d47cc7ea610f7791f - arm-trusted-firmware/plat/arm/board/morello/morello_security.c c855687b5adb537f1a56e37496a708864bd72650 - arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c 275ff8fd1cb66a02cc8ca9b9494035d3aa7f8ebf - arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c 59b5177c9b302f117bea58642d758d747224eaed - arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c ab6ec67031b519490edd2bdd7efb973f91af2453 - arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c 846d7f92ffe6c368d0d0b85ffa36409b0dd04caf - arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c 021dca0ec2928f72c45e98a602338d8a2bb08cc2 - arm-trusted-firmware/plat/arm/board/morello/morello_err.c 710e4ce5fe08ed123d1977361a4bbf49dff07ba9 - arm-trusted-firmware/plat/arm/board/morello/morello_def.h eae232f83e8fef4997f24f4cce1d598178a8eab0 - arm-trusted-firmware/plat/arm/board/morello/morello_plat.c 9e616a8e89120ae9b614d9bae16f0de9aa886778 - arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c 0105670429d8a205bc698cf69de09044501a55a1 - arm-trusted-firmware/plat/arm/board/morello/morello_topology.c 1c3ff5d4d35a2aa211380dea2b252236f3dae0b1 - arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S 5361abb465b0253014c38facafec374dd284699a - arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S e1eb7e2194a62fcfa63e0d92da3567386d98a24d - arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h a95b1476c52a6213400f2402811d15e5d82d7d83 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts bf30791c97940cf78bee90bb458a53b2480a4154 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts 9c4c899115425303ba08c836c2a6ca740418160b - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts 0ca4a4d2749cd227831e57d361b8c16ee0f3cf03 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c ef779e5f985f2ebef6d66a83442695603c463465 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h bdf16498e248d1d87d012aca5001940fb8328395 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h 15269f87cab6dfa65ce9cbaacbb13ee9cf2af583 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c 86553039cac69d2003776608e4a3172af5f6263d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c 1cfbd3237d5138875eda5a3f57ebd08f452c4992 - arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S 70fd1afdd7b31d55ddd95d7018ba66095315083e - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c 89a8aeb02e2a9467d783383e96d830647443b99d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c 78391ad4c170cb70d2db6ad5639108f4f6020dc6 - arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S fe445cbd11196fc3c69cdcbc6be5cdbc4354026b - arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S 205b5febc22c83179a2fc6c9005499ef61e8f347 - arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S 87820ef2083d1576c3d29546b46fb922eafa3737 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S 6631f2221faec011381242d2e2011d9eda3e9780 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h Change-Id: Ie3a9787db9bb56402235608a18c74dc1e6eb63be --- arm-trusted-firmware/.checkpatch.conf | 91 + arm-trusted-firmware/.commitlintrc.js | 74 + arm-trusted-firmware/.cz.json | 3 + arm-trusted-firmware/.editorconfig | 72 + arm-trusted-firmware/.gitreview | 5 + arm-trusted-firmware/.husky/commit-msg | 7 + .../.husky/commit-msg.commitlint | 3 + arm-trusted-firmware/.husky/commit-msg.gerrit | 194 + .../.husky/prepare-commit-msg | 6 + .../.husky/prepare-commit-msg.cz | 28 + arm-trusted-firmware/.versionrc.js | 113 + arm-trusted-firmware/Makefile | 1536 ++++ .../bl1/aarch32/bl1_arch_setup.c | 15 + .../bl1/aarch32/bl1_context_mgmt.c | 172 + .../bl1/aarch32/bl1_entrypoint.S | 99 + .../bl1/aarch32/bl1_exceptions.S | 157 + .../bl1/aarch64/bl1_arch_setup.c | 35 + .../bl1/aarch64/bl1_context_mgmt.c | 131 + .../bl1/aarch64/bl1_entrypoint.S | 108 + .../bl1/aarch64/bl1_exceptions.S | 289 + arm-trusted-firmware/bl1/bl1.ld.S | 149 + arm-trusted-firmware/bl1/bl1.mk | 32 + arm-trusted-firmware/bl1/bl1_fwu.c | 745 ++ arm-trusted-firmware/bl1/bl1_main.c | 287 + arm-trusted-firmware/bl1/bl1_private.h | 34 + arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c | 65 + .../bl2/aarch32/bl2_arch_setup.c | 16 + .../bl2/aarch32/bl2_el3_entrypoint.S | 57 + .../bl2/aarch32/bl2_el3_exceptions.S | 21 + .../bl2/aarch32/bl2_entrypoint.S | 136 + .../bl2/aarch32/bl2_run_next_image.S | 46 + .../bl2/aarch64/bl2_arch_setup.c | 19 + .../bl2/aarch64/bl2_el3_entrypoint.S | 72 + .../bl2/aarch64/bl2_el3_exceptions.S | 131 + .../bl2/aarch64/bl2_entrypoint.S | 141 + .../bl2/aarch64/bl2_rme_entrypoint.S | 67 + .../bl2/aarch64/bl2_run_next_image.S | 45 + arm-trusted-firmware/bl2/bl2.ld.S | 125 + arm-trusted-firmware/bl2/bl2.mk | 50 + arm-trusted-firmware/bl2/bl2_el3.ld.S | 187 + arm-trusted-firmware/bl2/bl2_image_load_v2.c | 110 + arm-trusted-firmware/bl2/bl2_main.c | 149 + arm-trusted-firmware/bl2/bl2_private.h | 24 + .../bl2u/aarch32/bl2u_entrypoint.S | 127 + .../bl2u/aarch64/bl2u_entrypoint.S | 129 + arm-trusted-firmware/bl2u/bl2u.ld.S | 118 + arm-trusted-firmware/bl2u/bl2u.mk | 15 + arm-trusted-firmware/bl2u/bl2u_main.c | 65 + .../bl31/aarch64/bl31_entrypoint.S | 240 + .../bl31/aarch64/crash_reporting.S | 477 ++ .../bl31/aarch64/ea_delegate.S | 317 + .../bl31/aarch64/runtime_exceptions.S | 621 ++ arm-trusted-firmware/bl31/bl31.ld.S | 195 + arm-trusted-firmware/bl31/bl31.mk | 151 + arm-trusted-firmware/bl31/bl31_context_mgmt.c | 66 + arm-trusted-firmware/bl31/bl31_main.c | 277 + arm-trusted-firmware/bl31/ehf.c | 526 ++ arm-trusted-firmware/bl31/interrupt_mgmt.c | 227 + arm-trusted-firmware/bl32/optee/optee.mk | 15 + .../bl32/sp_min/aarch32/entrypoint.S | 382 + arm-trusted-firmware/bl32/sp_min/sp_min.ld.S | 150 + arm-trusted-firmware/bl32/sp_min/sp_min.mk | 73 + .../bl32/sp_min/sp_min_main.c | 249 + .../bl32/sp_min/sp_min_private.h | 14 + .../bl32/sp_min/wa_cve_2017_5715_bpiall.S | 74 + .../bl32/sp_min/wa_cve_2017_5715_icache_inv.S | 75 + .../bl32/tsp/aarch64/tsp_entrypoint.S | 485 ++ .../bl32/tsp/aarch64/tsp_exceptions.S | 162 + .../bl32/tsp/aarch64/tsp_request.S | 30 + arm-trusted-firmware/bl32/tsp/tsp.ld.S | 123 + arm-trusted-firmware/bl32/tsp/tsp.mk | 36 + arm-trusted-firmware/bl32/tsp/tsp_interrupt.c | 117 + arm-trusted-firmware/bl32/tsp/tsp_main.c | 471 ++ arm-trusted-firmware/bl32/tsp/tsp_private.h | 153 + arm-trusted-firmware/bl32/tsp/tsp_timer.c | 91 + arm-trusted-firmware/changelog.yaml | 1017 +++ arm-trusted-firmware/common/aarch32/debug.S | 207 + arm-trusted-firmware/common/aarch64/debug.S | 221 + .../common/aarch64/early_exceptions.S | 129 + .../common/backtrace/backtrace.c | 273 + .../common/backtrace/backtrace.mk | 31 + arm-trusted-firmware/common/bl_common.c | 271 + arm-trusted-firmware/common/desc_image_load.c | 351 + arm-trusted-firmware/common/fdt_fixup.c | 481 ++ arm-trusted-firmware/common/fdt_wrappers.c | 620 ++ arm-trusted-firmware/common/fdt_wrappers.mk | 7 + .../common/image_decompress.c | 80 + arm-trusted-firmware/common/runtime_svc.c | 154 + arm-trusted-firmware/common/tf_crc32.c | 45 + arm-trusted-firmware/common/tf_log.c | 79 + arm-trusted-firmware/common/uuid.c | 134 + arm-trusted-firmware/dco.txt | 37 + arm-trusted-firmware/docs/Makefile | 25 + .../docs/_static/css/custom.css | 15 + .../docs/about/acknowledgements.rst | 22 + arm-trusted-firmware/docs/about/contact.rst | 56 + arm-trusted-firmware/docs/about/features.rst | 127 + arm-trusted-firmware/docs/about/index.rst | 13 + .../docs/about/maintainers.rst | 865 ++ .../docs/about/release-information.rst | 71 + arm-trusted-firmware/docs/change-log.md | 4746 +++++++++++ .../docs/components/activity-monitors.rst | 34 + .../docs/components/arm-sip-service.rst | 435 + .../docs/components/cot-binding.rst | 332 + .../docs/components/debugfs-design.rst | 125 + .../docs/components/exception-handling.rst | 619 ++ .../docs/components/fconf/amu-bindings.rst | 142 + .../components/fconf/fconf_properties.rst | 32 + .../docs/components/fconf/index.rst | 149 + .../docs/components/fconf/mpmm-bindings.rst | 48 + .../docs/components/ffa-manifest-binding.rst | 252 + .../docs/components/firmware-update.rst | 400 + .../granule-protection-tables-design.rst | 235 + .../docs/components/index.rst | 28 + .../components/measured_boot/event_log.rst | 35 + .../docs/components/measured_boot/index.rst | 12 + arm-trusted-firmware/docs/components/mpmm.rst | 30 + .../platform-interrupt-controller-API.rst | 309 + arm-trusted-firmware/docs/components/ras.rst | 241 + .../components/realm-management-extension.rst | 267 + .../docs/components/romlib-design.rst | 155 + arm-trusted-firmware/docs/components/sdei.rst | 369 + .../secure-partition-manager-mm.rst | 834 ++ .../components/secure-partition-manager.rst | 1291 +++ .../docs/components/spd/index.rst | 10 + .../docs/components/spd/optee-dispatcher.rst | 14 + .../docs/components/spd/tlk-dispatcher.rst | 76 + .../docs/components/spd/trusty-dispatcher.rst | 32 + .../components/xlat-tables-lib-v2-design.rst | 442 + arm-trusted-firmware/docs/conf.py | 94 + .../docs/design/alt-boot-flows.rst | 84 + .../docs/design/auth-framework.rst | 980 +++ .../docs/design/cpu-specific-build-macros.rst | 611 ++ .../docs/design/firmware-design.rst | 2743 ++++++ arm-trusted-firmware/docs/design/index.rst | 21 + .../design/interrupt-framework-design.rst | 1021 +++ .../docs/design/psci-pd-tree.rst | 304 + .../docs/design/reset-design.rst | 161 + .../docs/design/trusted-board-boot-build.rst | 115 + .../docs/design/trusted-board-boot.rst | 263 + .../docs/design_documents/cmake_framework.rst | 165 + .../design_documents/context_mgmt_rework.rst | 197 + .../docs/design_documents/index.rst | 15 + .../design_documents/measured_boot_poc.rst | 507 ++ .../docs/getting_started/build-options.rst | 974 +++ .../docs/getting_started/docs-build.rst | 115 + .../getting_started/image-terminology.rst | 183 + .../docs/getting_started/index.rst | 21 + .../docs/getting_started/initial-build.rst | 118 + .../docs/getting_started/porting-guide.rst | 3215 ++++++++ .../docs/getting_started/prerequisites.rst | 169 + .../psci-lib-integration-guide.rst | 546 ++ .../getting_started/rt-svc-writers-guide.rst | 320 + .../docs/getting_started/tools-build.rst | 167 + .../docs/global_substitutions.txt | 68 + arm-trusted-firmware/docs/glossary.rst | 225 + arm-trusted-firmware/docs/index.rst | 96 + arm-trusted-firmware/docs/license.rst | 90 + arm-trusted-firmware/docs/perf/index.rst | 15 + .../docs/perf/performance-monitoring-unit.rst | 158 + .../docs/perf/psci-performance-juno.rst | 292 + arm-trusted-firmware/docs/perf/tsp.rst | 27 + arm-trusted-firmware/docs/plat/allwinner.rst | 142 + .../docs/plat/arm/arm-build-options.rst | 159 + .../docs/plat/arm/arm_fpga/index.rst | 97 + .../docs/plat/arm/corstone1000/index.rst | 61 + .../docs/plat/arm/fvp-ve/index.rst | 84 + .../docs/plat/arm/fvp/index.rst | 652 ++ .../docs/plat/arm/fvp_r/index.rst | 46 + arm-trusted-firmware/docs/plat/arm/index.rst | 24 + .../docs/plat/arm/juno/index.rst | 253 + .../docs/plat/arm/morello/index.rst | 33 + .../docs/plat/arm/tc/index.rst | 56 + .../docs/plat/brcm-stingray.rst | 43 + arm-trusted-firmware/docs/plat/deprecated.rst | 20 + arm-trusted-firmware/docs/plat/hikey.rst | 155 + arm-trusted-firmware/docs/plat/hikey960.rst | 180 + arm-trusted-firmware/docs/plat/imx8.rst | 58 + arm-trusted-firmware/docs/plat/imx8m.rst | 70 + arm-trusted-firmware/docs/plat/index.rst | 66 + .../docs/plat/intel-agilex.rst | 86 + .../docs/plat/intel-stratix10.rst | 94 + .../docs/plat/marvell/armada/build.rst | 476 ++ .../armada/misc/mvebu-a8k-addr-map.rst | 49 + .../plat/marvell/armada/misc/mvebu-amb.rst | 58 + .../plat/marvell/armada/misc/mvebu-ccu.rst | 33 + .../plat/marvell/armada/misc/mvebu-io-win.rst | 46 + .../plat/marvell/armada/misc/mvebu-iob.rst | 52 + .../docs/plat/marvell/armada/porting.rst | 158 + .../docs/plat/marvell/index.rst | 14 + arm-trusted-firmware/docs/plat/meson-axg.rst | 27 + arm-trusted-firmware/docs/plat/meson-g12a.rst | 27 + arm-trusted-firmware/docs/plat/meson-gxbb.rst | 26 + arm-trusted-firmware/docs/plat/meson-gxl.rst | 27 + arm-trusted-firmware/docs/plat/mt8183.rst | 20 + arm-trusted-firmware/docs/plat/mt8186.rst | 21 + arm-trusted-firmware/docs/plat/mt8192.rst | 21 + arm-trusted-firmware/docs/plat/mt8195.rst | 21 + .../docs/plat/nvidia-tegra.rst | 148 + arm-trusted-firmware/docs/plat/nxp/index.rst | 17 + .../docs/plat/nxp/nxp-layerscape.rst | 473 ++ .../docs/plat/nxp/nxp-ls-fuse-prov.rst | 271 + .../docs/plat/nxp/nxp-ls-tbbr.rst | 210 + arm-trusted-firmware/docs/plat/poplar.rst | 176 + arm-trusted-firmware/docs/plat/qemu-sbsa.rst | 56 + arm-trusted-firmware/docs/plat/qemu.rst | 138 + .../docs/plat/qti-msm8916.rst | 116 + arm-trusted-firmware/docs/plat/qti.rst | 43 + arm-trusted-firmware/docs/plat/rcar-gen3.rst | 268 + arm-trusted-firmware/docs/plat/rockchip.rst | 55 + arm-trusted-firmware/docs/plat/rpi3.rst | 466 ++ arm-trusted-firmware/docs/plat/rpi4.rst | 84 + arm-trusted-firmware/docs/plat/rz-g2.rst | 228 + .../docs/plat/socionext-uniphier.rst | 116 + arm-trusted-firmware/docs/plat/stm32mp1.rst | 305 + arm-trusted-firmware/docs/plat/synquacer.rst | 117 + arm-trusted-firmware/docs/plat/ti-k3.rst | 57 + arm-trusted-firmware/docs/plat/warp7.rst | 210 + .../docs/plat/xilinx-versal.rst | 53 + .../docs/plat/xilinx-zynqmp.rst | 73 + .../docs/process/code-review-guidelines.rst | 216 + .../docs/process/coding-guidelines.rst | 474 ++ .../docs/process/coding-style.rst | 470 ++ .../docs/process/commit-style.rst | 162 + .../docs/process/contributing.rst | 304 + arm-trusted-firmware/docs/process/faq.rst | 80 + arm-trusted-firmware/docs/process/index.rst | 17 + .../process/platform-compatibility-policy.rst | 36 + .../docs/process/security-hardening.rst | 175 + .../docs/process/security.rst | 89 + arm-trusted-firmware/docs/requirements.in | 5 + arm-trusted-firmware/docs/requirements.txt | 91 + .../TrustedFirmware-Logo_standard-white.png | Bin 0 -> 5826 bytes .../resources/diagrams/FIP_in_a_GPT_image.png | Bin 0 -> 250286 bytes .../docs/resources/diagrams/MMU-600.png | Bin 0 -> 50836 bytes .../docs/resources/diagrams/Makefile | 74 + .../diagrams/arm-cca-software-arch.png | Bin 0 -> 20577 bytes .../diagrams/cmake_framework_structure.png | Bin 0 -> 73277 bytes .../diagrams/cmake_framework_workflow.png | Bin 0 -> 49898 bytes .../diagrams/context_management_abs.png | Bin 0 -> 10781 bytes .../diagrams/context_mgmt_existing.png | Bin 0 -> 52718 bytes .../diagrams/context_mgmt_proposed.png | Bin 0 -> 61841 bytes .../resources/diagrams/default_reset_code.png | Bin 0 -> 41796 bytes .../docs/resources/diagrams/draw.io/ehf.svg | 2 + .../docs/resources/diagrams/draw.io/ehf.xml | 1 + .../docs/resources/diagrams/draw.io/ras.svg | 2 + .../docs/resources/diagrams/draw.io/ras.xml | 1 + .../docs/resources/diagrams/ff-a-spm-sel2.png | Bin 0 -> 53363 bytes ...ffa-ns-interrupt-handling-managed-exit.png | Bin 0 -> 86234 bytes ...fa-ns-interrupt-handling-sp-preemption.png | Bin 0 -> 70490 bytes .../ffa-secure-interrupt-handling-nwd.png | Bin 0 -> 48073 bytes .../ffa-secure-interrupt-handling-swd.png | Bin 0 -> 48364 bytes .../docs/resources/diagrams/fwu_flow.png | Bin 0 -> 167225 bytes .../docs/resources/diagrams/fwu_states.png | Bin 0 -> 114222 bytes .../docs/resources/diagrams/int_handling.dia | Bin 0 -> 10623 bytes .../diagrams/non-sec-int-handling.png | Bin 0 -> 218768 bytes .../diagrams/plantuml/bl2-loading-sp.puml | 44 + .../plantuml/fconf_bl1_load_config.puml | 78 + .../diagrams/plantuml/fconf_bl2_populate.puml | 49 + .../plantuml/fip-secure-partitions.puml | 167 + .../plantuml/io_arm_class_diagram.puml | 109 + .../plantuml/io_dev_init_and_check.puml | 62 + .../plantuml/io_dev_registration.puml | 52 + .../plantuml/io_framework_usage_overview.puml | 59 + .../plantuml/sdei_explicit_dispatch.puml | 51 + .../diagrams/plantuml/sdei_general.puml | 43 + .../resources/diagrams/plantuml/spm_dfd.puml | 82 + .../resources/diagrams/plantuml/tfa_dfd.puml | 66 + .../diagrams/psci-suspend-sequence.png | Bin 0 -> 427800 bytes .../resources/diagrams/reset_code_flow.dia | Bin 0 -> 4399 bytes .../reset_code_no_boot_type_check.png | Bin 0 -> 42942 bytes .../diagrams/reset_code_no_checks.png | Bin 0 -> 39753 bytes .../diagrams/reset_code_no_cpu_check.png | Bin 0 -> 38566 bytes .../docs/resources/diagrams/romlib_design.dia | Bin 0 -> 2985 bytes .../docs/resources/diagrams/romlib_design.png | Bin 0 -> 17244 bytes .../resources/diagrams/romlib_wrapper.dia | Bin 0 -> 2543 bytes .../resources/diagrams/romlib_wrapper.png | Bin 0 -> 12085 bytes .../diagrams/rt-svc-descs-layout.png | Bin 0 -> 77894 bytes .../resources/diagrams/sec-int-handling.png | Bin 0 -> 173315 bytes .../resources/diagrams/secure_sw_stack_sp.png | Bin 0 -> 34909 bytes .../diagrams/secure_sw_stack_tos.png | Bin 0 -> 34202 bytes .../spm-threat-model-trust-boundaries.png | Bin 0 -> 66389 bytes .../docs/resources/diagrams/xlat_align.dia | Bin 0 -> 2346 bytes .../docs/resources/diagrams/xlat_align.png | Bin 0 -> 46712 bytes .../docs/security_advisories/index.rst | 17 + .../security-advisory-tfv-1.rst | 162 + .../security-advisory-tfv-2.rst | 61 + .../security-advisory-tfv-3.rst | 86 + .../security-advisory-tfv-4.rst | 124 + .../security-advisory-tfv-5.rst | 57 + .../security-advisory-tfv-6.rst | 148 + .../security-advisory-tfv-7.rst | 107 + .../security-advisory-tfv-8.rst | 103 + .../security-advisory-tfv-9.rst | 104 + .../docs/threat_model/index.rst | 22 + .../docs/threat_model/threat_model.rst | 788 ++ .../docs/threat_model/threat_model_fvp_r.rst | 97 + .../docs/threat_model/threat_model_spm.rst | 892 ++ .../drivers/allwinner/axp/axp803.c | 25 + .../drivers/allwinner/axp/axp805.c | 35 + .../drivers/allwinner/axp/common.c | 212 + .../drivers/allwinner/sunxi_msgbox.c | 95 + .../drivers/allwinner/sunxi_rsb.c | 138 + .../amlogic/console/aarch64/meson_console.S | 262 + .../drivers/amlogic/crypto/sha_dma.c | 182 + arm-trusted-firmware/drivers/arm/cci/cci.c | 186 + arm-trusted-firmware/drivers/arm/ccn/ccn.c | 621 ++ .../drivers/arm/ccn/ccn_private.h | 233 + .../drivers/arm/css/mhu/css_mhu.c | 100 + .../drivers/arm/css/mhu/css_mhu_doorbell.c | 40 + .../drivers/arm/css/scmi/scmi_ap_core_proto.c | 81 + .../drivers/arm/css/scmi/scmi_common.c | 210 + .../drivers/arm/css/scmi/scmi_private.h | 160 + .../drivers/arm/css/scmi/scmi_pwr_dmn_proto.c | 88 + .../drivers/arm/css/scmi/scmi_sys_pwr_proto.c | 78 + .../drivers/arm/css/scmi/vendor/scmi_sq.c | 62 + .../drivers/arm/css/scmi/vendor/scmi_sq.h | 25 + .../drivers/arm/css/scp/css_bom_bootloader.c | 195 + .../drivers/arm/css/scp/css_pm_scmi.c | 468 ++ .../drivers/arm/css/scp/css_pm_scpi.c | 165 + .../drivers/arm/css/scp/css_sds.c | 95 + .../drivers/arm/css/scpi/css_scpi.c | 272 + .../drivers/arm/css/sds/aarch32/sds_helpers.S | 64 + .../drivers/arm/css/sds/aarch64/sds_helpers.S | 62 + .../drivers/arm/css/sds/sds.c | 259 + .../drivers/arm/css/sds/sds_private.h | 100 + .../drivers/arm/dcc/dcc_console.c | 152 + arm-trusted-firmware/drivers/arm/dsu/ppu.c | 172 + .../drivers/arm/ethosn/ethosn_smc.c | 170 + .../drivers/arm/fvp/fvp_pwrc.c | 78 + .../drivers/arm/gic/common/gic_common.c | 342 + .../arm/gic/common/gic_common_private.h | 89 + .../drivers/arm/gic/v2/gicdv2_helpers.c | 340 + .../drivers/arm/gic/v2/gicv2.mk | 15 + .../drivers/arm/gic/v2/gicv2_helpers.c | 220 + .../drivers/arm/gic/v2/gicv2_main.c | 555 ++ .../drivers/arm/gic/v2/gicv2_private.h | 150 + .../drivers/arm/gic/v3/arm_gicv3_common.c | 115 + .../drivers/arm/gic/v3/gic-x00.c | 172 + .../drivers/arm/gic/v3/gic600_multichip.c | 254 + .../arm/gic/v3/gic600_multichip_private.h | 105 + .../drivers/arm/gic/v3/gic600ae_fmu.c | 392 + .../drivers/arm/gic/v3/gic600ae_fmu_helpers.c | 304 + .../drivers/arm/gic/v3/gicdv3_helpers.c | 244 + .../drivers/arm/gic/v3/gicrv3_helpers.c | 139 + .../drivers/arm/gic/v3/gicv3.mk | 50 + .../drivers/arm/gic/v3/gicv3_helpers.c | 410 + .../drivers/arm/gic/v3/gicv3_main.c | 1350 +++ .../drivers/arm/gic/v3/gicv3_private.h | 718 ++ .../drivers/arm/pl011/aarch32/pl011_console.S | 264 + .../drivers/arm/pl011/aarch64/pl011_console.S | 247 + .../drivers/arm/pl061/pl061_gpio.c | 142 + arm-trusted-firmware/drivers/arm/sbsa/sbsa.c | 42 + arm-trusted-firmware/drivers/arm/scu/scu.c | 51 + .../drivers/arm/smmu/smmu_v3.c | 96 + .../drivers/arm/sp804/sp804_delay_timer.c | 57 + .../drivers/arm/sp805/sp805.c | 51 + arm-trusted-firmware/drivers/arm/tzc/tzc380.c | 104 + arm-trusted-firmware/drivers/arm/tzc/tzc400.c | 360 + .../drivers/arm/tzc/tzc_common_private.h | 204 + .../drivers/arm/tzc/tzc_dmc500.c | 287 + .../drivers/arm/tzc/tzc_dmc620.c | 177 + arm-trusted-firmware/drivers/auth/auth_mod.c | 444 + .../drivers/auth/crypto_mod.c | 164 + .../auth/cryptocell/712/cryptocell_crypto.c | 306 + .../cryptocell/712/cryptocell_plat_helpers.c | 113 + .../auth/cryptocell/713/cryptocell_crypto.c | 274 + .../cryptocell/713/cryptocell_plat_helpers.c | 109 + .../auth/cryptocell/cryptocell_crypto.mk | 40 + .../drivers/auth/dualroot/cot.c | 959 +++ .../drivers/auth/img_parser_mod.c | 126 + .../drivers/auth/mbedtls/mbedtls_common.c | 72 + .../drivers/auth/mbedtls/mbedtls_common.mk | 126 + .../drivers/auth/mbedtls/mbedtls_crypto.c | 388 + .../drivers/auth/mbedtls/mbedtls_crypto.mk | 11 + .../drivers/auth/mbedtls/mbedtls_x509.mk | 9 + .../auth/mbedtls/mbedtls_x509_parser.c | 478 ++ .../drivers/auth/tbbr/tbbr_cot_bl1.c | 184 + .../drivers/auth/tbbr/tbbr_cot_bl1_r64.c | 177 + .../drivers/auth/tbbr/tbbr_cot_bl2.c | 688 ++ .../drivers/auth/tbbr/tbbr_cot_common.c | 126 + arm-trusted-firmware/drivers/brcm/chimp.c | 398 + .../drivers/brcm/emmc/emmc_chal_sd.c | 1017 +++ .../drivers/brcm/emmc/emmc_csl_sdcard.c | 1089 +++ .../drivers/brcm/emmc/emmc_csl_sdcmd.c | 842 ++ .../brcm/emmc/emmc_pboot_hal_memory_drv.c | 621 ++ arm-trusted-firmware/drivers/brcm/i2c/i2c.c | 886 ++ .../drivers/brcm/iproc_gpio.c | 232 + arm-trusted-firmware/drivers/brcm/mdio/mdio.c | 87 + arm-trusted-firmware/drivers/brcm/ocotp.c | 204 + arm-trusted-firmware/drivers/brcm/rng.c | 97 + arm-trusted-firmware/drivers/brcm/scp.c | 100 + arm-trusted-firmware/drivers/brcm/sotp.c | 323 + .../drivers/brcm/spi/iproc_qspi.c | 317 + .../drivers/brcm/spi/iproc_qspi.h | 107 + .../drivers/brcm/spi/iproc_spi.c | 31 + arm-trusted-firmware/drivers/brcm/spi_flash.c | 308 + arm-trusted-firmware/drivers/brcm/spi_sf.c | 60 + .../cadence/uart/aarch64/cdns_console.S | 220 + .../drivers/cfi/v2m/v2m_flash.c | 196 + arm-trusted-firmware/drivers/clk/clk.c | 65 + .../console/aarch32/skeleton_console.S | 170 + .../console/aarch64/skeleton_console.S | 170 + .../drivers/console/multi_console.c | 130 + .../cbmem_console/aarch64/cbmem_console.S | 98 + .../drivers/delay_timer/delay_timer.c | 82 + .../drivers/delay_timer/generic_delay_timer.c | 62 + arm-trusted-firmware/drivers/fwu/fwu.c | 194 + arm-trusted-firmware/drivers/fwu/fwu.mk | 11 + arm-trusted-firmware/drivers/gpio/gpio.c | 93 + .../drivers/imx/timer/imx_gpt.c | 62 + .../drivers/imx/timer/imx_gpt.h | 14 + .../drivers/imx/uart/imx_crash_uart.S | 131 + .../drivers/imx/uart/imx_uart.c | 181 + .../drivers/imx/uart/imx_uart.h | 163 + .../drivers/imx/usdhc/imx_usdhc.c | 302 + .../drivers/imx/usdhc/imx_usdhc.h | 137 + .../intel/soc/stratix10/io/s10_memmap_qspi.c | 253 + arm-trusted-firmware/drivers/io/io_block.c | 551 ++ arm-trusted-firmware/drivers/io/io_dummy.c | 155 + .../drivers/io/io_encrypted.c | 244 + arm-trusted-firmware/drivers/io/io_fip.c | 481 ++ arm-trusted-firmware/drivers/io/io_memmap.c | 251 + arm-trusted-firmware/drivers/io/io_mtd.c | 290 + .../drivers/io/io_semihosting.c | 201 + arm-trusted-firmware/drivers/io/io_storage.c | 328 + .../drivers/marvell/amb_adec.c | 160 + .../drivers/marvell/ap807_clocks_init.c | 109 + .../drivers/marvell/cache_llc.c | 189 + arm-trusted-firmware/drivers/marvell/ccu.c | 417 + arm-trusted-firmware/drivers/marvell/comphy.h | 472 ++ .../drivers/marvell/comphy/comphy-cp110.h | 914 ++ .../drivers/marvell/comphy/phy-comphy-3700.c | 1065 +++ .../drivers/marvell/comphy/phy-comphy-3700.h | 249 + .../marvell/comphy/phy-comphy-common.h | 167 + .../drivers/marvell/comphy/phy-comphy-cp110.c | 2528 ++++++ .../drivers/marvell/comphy/phy-comphy-cp110.h | 102 + .../comphy/phy-default-porting-layer.h | 59 + .../drivers/marvell/ddr_phy_access.c | 58 + .../drivers/marvell/ddr_phy_access.h | 15 + arm-trusted-firmware/drivers/marvell/gwin.c | 231 + arm-trusted-firmware/drivers/marvell/io_win.c | 271 + arm-trusted-firmware/drivers/marvell/iob.c | 214 + .../marvell/mc_trustzone/mc_trustzone.c | 76 + .../marvell/mc_trustzone/mc_trustzone.h | 27 + arm-trusted-firmware/drivers/marvell/mci.c | 834 ++ .../drivers/marvell/mg_conf_cm3/mg_conf_cm3.c | 97 + .../drivers/marvell/mg_conf_cm3/mg_conf_cm3.h | 9 + .../drivers/marvell/mochi/ap807_setup.c | 339 + .../drivers/marvell/mochi/apn806_setup.c | 297 + .../drivers/marvell/mochi/cp110_setup.c | 467 ++ .../secure_dfx_access/armada_thermal.c | 253 + .../drivers/marvell/secure_dfx_access/dfx.h | 22 + .../marvell/secure_dfx_access/misc_dfx.c | 123 + .../drivers/marvell/thermal.c | 54 + .../drivers/marvell/uart/a3700_console.S | 271 + .../measured_boot/event_log/event_log.c | 293 + .../measured_boot/event_log/event_log.mk | 36 + .../measured_boot/event_log/event_print.c | 265 + .../drivers/mentor/i2c/mi2cv.c | 614 ++ arm-trusted-firmware/drivers/mmc/mmc.c | 811 ++ arm-trusted-firmware/drivers/mtd/nand/core.c | 159 + .../drivers/mtd/nand/raw_nand.c | 443 + .../drivers/mtd/nand/spi_nand.c | 324 + .../drivers/mtd/nor/spi_nor.c | 387 + .../drivers/mtd/spi-mem/spi_mem.c | 289 + .../drivers/nxp/auth/csf_hdr_parser/cot.c | 284 + .../nxp/auth/csf_hdr_parser/csf_hdr.mk | 64 + .../nxp/auth/csf_hdr_parser/csf_hdr_parser.c | 365 + .../nxp/auth/csf_hdr_parser/input_bl2_ch2 | 89 + .../nxp/auth/csf_hdr_parser/input_bl2_ch3 | 65 + .../nxp/auth/csf_hdr_parser/input_bl2_ch3_2 | 65 + .../nxp/auth/csf_hdr_parser/input_blx_ch2 | 30 + .../nxp/auth/csf_hdr_parser/input_blx_ch3 | 37 + .../nxp/auth/csf_hdr_parser/input_pbi_ch3 | 43 + .../nxp/auth/csf_hdr_parser/input_pbi_ch3_2 | 43 + .../nxp/auth/csf_hdr_parser/plat_img_parser.c | 180 + .../drivers/nxp/auth/tbbr/tbbr_cot.c | 820 ++ .../drivers/nxp/console/16550_console.S | 319 + .../drivers/nxp/console/console.mk | 46 + .../drivers/nxp/console/console_16550.c | 33 + .../drivers/nxp/console/console_pl011.c | 35 + .../drivers/nxp/crypto/caam/caam.mk | 27 + .../drivers/nxp/crypto/caam/src/auth/auth.mk | 12 + .../drivers/nxp/crypto/caam/src/auth/hash.c | 155 + .../nxp/crypto/caam/src/auth/nxp_crypto.c | 123 + .../drivers/nxp/crypto/caam/src/auth/rsa.c | 179 + .../drivers/nxp/crypto/caam/src/caam.c | 339 + .../drivers/nxp/crypto/caam/src/hw_key_blob.c | 81 + .../drivers/nxp/crypto/caam/src/jobdesc.c | 236 + .../drivers/nxp/crypto/caam/src/rng.c | 251 + .../nxp/crypto/caam/src/sec_hw_specific.c | 635 ++ .../nxp/crypto/caam/src/sec_jr_driver.c | 241 + arm-trusted-firmware/drivers/nxp/csu/csu.c | 34 + arm-trusted-firmware/drivers/nxp/csu/csu.mk | 26 + arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c | 156 + arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk | 26 + .../drivers/nxp/ddr/fsl-mmdc/ddr.mk | 19 + .../drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c | 176 + .../drivers/nxp/ddr/nxp-ddr/README.odt | 31 + .../drivers/nxp/ddr/nxp-ddr/ddr.c | 931 +++ .../drivers/nxp/ddr/nxp-ddr/ddr.mk | 80 + .../drivers/nxp/ddr/nxp-ddr/ddrc.c | 594 ++ .../drivers/nxp/ddr/nxp-ddr/dimm.c | 399 + .../drivers/nxp/ddr/nxp-ddr/regs.c | 1394 ++++ .../drivers/nxp/ddr/nxp-ddr/utility.c | 288 + .../drivers/nxp/ddr/phy-gen1/phy.c | 97 + .../drivers/nxp/ddr/phy-gen2/csr.h | 151 + .../drivers/nxp/ddr/phy-gen2/ddr4fw.h | 2897 +++++++ .../drivers/nxp/ddr/phy-gen2/ddrphy.mk | 20 + .../drivers/nxp/ddr/phy-gen2/input.h | 106 + .../drivers/nxp/ddr/phy-gen2/messages.h | 2909 +++++++ .../drivers/nxp/ddr/phy-gen2/phy.c | 2673 ++++++ .../drivers/nxp/ddr/phy-gen2/phy.h | 334 + .../drivers/nxp/ddr/phy-gen2/pie.h | 632 ++ arm-trusted-firmware/drivers/nxp/drivers.mk | 99 + .../drivers/nxp/flexspi/nor/flexspi_nor.c | 25 + .../drivers/nxp/flexspi/nor/flexspi_nor.h | 15 + .../drivers/nxp/flexspi/nor/flexspi_nor.mk | 35 + .../drivers/nxp/flexspi/nor/fspi.c | 853 ++ .../drivers/nxp/flexspi/nor/fspi.h | 385 + .../drivers/nxp/flexspi/nor/test_fspi.c | 91 + arm-trusted-firmware/drivers/nxp/gic/gic.mk | 46 + .../drivers/nxp/gic/ls_gicv2.c | 76 + .../drivers/nxp/gic/ls_gicv3.c | 78 + arm-trusted-firmware/drivers/nxp/gpio/gpio.mk | 28 + .../drivers/nxp/gpio/nxp_gpio.c | 144 + arm-trusted-firmware/drivers/nxp/i2c/i2c.c | 257 + arm-trusted-firmware/drivers/nxp/i2c/i2c.mk | 25 + .../drivers/nxp/ifc/nand/ifc.h | 329 + .../drivers/nxp/ifc/nand/ifc_nand.c | 658 ++ .../drivers/nxp/ifc/nand/ifc_nand.mk | 29 + .../drivers/nxp/ifc/nor/ifc_nor.c | 18 + .../drivers/nxp/ifc/nor/ifc_nor.mk | 28 + .../drivers/nxp/interconnect/interconnect.mk | 44 + .../drivers/nxp/interconnect/ls_cci.c | 38 + .../drivers/nxp/interconnect/ls_ccn.c | 31 + arm-trusted-firmware/drivers/nxp/pmu/pmu.c | 45 + arm-trusted-firmware/drivers/nxp/pmu/pmu.mk | 26 + arm-trusted-firmware/drivers/nxp/qspi/qspi.c | 29 + arm-trusted-firmware/drivers/nxp/qspi/qspi.mk | 26 + arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c | 1496 ++++ arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk | 26 + .../drivers/nxp/sec_mon/sec_mon.mk | 25 + .../drivers/nxp/sec_mon/snvs.c | 186 + .../drivers/nxp/sfp/fuse_prov.c | 462 ++ arm-trusted-firmware/drivers/nxp/sfp/sfp.c | 167 + arm-trusted-firmware/drivers/nxp/sfp/sfp.mk | 33 + .../drivers/nxp/timer/nxp_timer.c | 143 + .../drivers/nxp/timer/timer.mk | 25 + .../drivers/nxp/tzc/plat_tzc380.c | 152 + .../drivers/nxp/tzc/plat_tzc400.c | 187 + arm-trusted-firmware/drivers/nxp/tzc/tzc.mk | 40 + arm-trusted-firmware/drivers/partition/gpt.c | 64 + .../drivers/partition/partition.c | 271 + .../drivers/rambus/trng_ip_76.c | 249 + .../drivers/renesas/common/auth/auth_mod.c | 172 + .../drivers/renesas/common/avs/avs_driver.c | 630 ++ .../drivers/renesas/common/avs/avs_driver.h | 20 + .../drivers/renesas/common/common.c | 38 + .../renesas/common/console/rcar_console.S | 93 + .../renesas/common/console/rcar_printf.c | 108 + .../renesas/common/console/rcar_printf.h | 15 + .../renesas/common/ddr/boot_init_dram.h | 18 + .../drivers/renesas/common/ddr/ddr.mk | 17 + .../common/ddr/ddr_a/boot_init_dram_regdef.h | 8 + .../drivers/renesas/common/ddr/ddr_a/ddr_a.mk | 13 + .../renesas/common/ddr/ddr_a/ddr_init_d3.c | 735 ++ .../renesas/common/ddr/ddr_a/ddr_init_e3.c | 1712 ++++ .../renesas/common/ddr/ddr_a/ddr_init_v3m.c | 339 + .../renesas/common/ddr/ddr_b/boot_init_dram.c | 4484 ++++++++++ .../common/ddr/ddr_b/boot_init_dram_config.c | 2108 +++++ .../common/ddr/ddr_b/boot_init_dram_regdef.h | 95 + .../drivers/renesas/common/ddr/ddr_b/ddr_b.mk | 7 + .../renesas/common/ddr/ddr_b/ddr_regdef.h | 5887 +++++++++++++ .../common/ddr/ddr_b/init_dram_tbl_h3.h | 441 + .../common/ddr/ddr_b/init_dram_tbl_h3ver2.h | 538 ++ .../common/ddr/ddr_b/init_dram_tbl_m3.h | 468 ++ .../common/ddr/ddr_b/init_dram_tbl_m3n.h | 587 ++ .../renesas/common/ddr/dram_sub_func.c | 165 + .../renesas/common/ddr/dram_sub_func.h | 17 + .../drivers/renesas/common/ddr_regs.h | 257 + .../renesas/common/delay/micro_delay.c | 31 + .../renesas/common/delay/micro_delay.h | 15 + .../drivers/renesas/common/dma/dma_driver.c | 153 + .../drivers/renesas/common/emmc/emmc_cmd.c | 493 ++ .../drivers/renesas/common/emmc/emmc_config.h | 20 + .../drivers/renesas/common/emmc/emmc_def.h | 78 + .../drivers/renesas/common/emmc/emmc_hal.h | 535 ++ .../drivers/renesas/common/emmc/emmc_init.c | 163 + .../renesas/common/emmc/emmc_interrupt.c | 217 + .../drivers/renesas/common/emmc/emmc_mount.c | 686 ++ .../drivers/renesas/common/emmc/emmc_read.c | 130 + .../renesas/common/emmc/emmc_registers.h | 215 + .../drivers/renesas/common/emmc/emmc_std.h | 475 ++ .../renesas/common/emmc/emmc_utility.c | 226 + .../renesas/common/iic_dvfs/iic_dvfs.c | 600 ++ .../renesas/common/iic_dvfs/iic_dvfs.h | 23 + .../drivers/renesas/common/io/io_common.h | 16 + .../drivers/renesas/common/io/io_emmcdrv.c | 179 + .../drivers/renesas/common/io/io_emmcdrv.h | 13 + .../drivers/renesas/common/io/io_memdrv.c | 154 + .../drivers/renesas/common/io/io_memdrv.h | 13 + .../drivers/renesas/common/io/io_private.h | 20 + .../drivers/renesas/common/io/io_rcar.c | 665 ++ .../drivers/renesas/common/io/io_rcar.h | 14 + .../drivers/renesas/common/pfc_regs.h | 230 + .../drivers/renesas/common/pwrc/call_sram.S | 48 + .../drivers/renesas/common/pwrc/pwrc.c | 917 +++ .../drivers/renesas/common/pwrc/pwrc.h | 78 + .../drivers/renesas/common/qos_reg.h | 133 + .../drivers/renesas/common/rom/rom_api.c | 106 + .../drivers/renesas/common/rom/rom_api.h | 31 + .../drivers/renesas/common/rpc/rpc_driver.c | 57 + .../renesas/common/rpc/rpc_registers.h | 25 + .../drivers/renesas/common/scif/scif.S | 341 + .../drivers/renesas/common/watchdog/swdt.c | 169 + .../drivers/renesas/rcar/board/board.c | 101 + .../drivers/renesas/rcar/board/board.h | 37 + .../drivers/renesas/rcar/cpld/ulcb_cpld.c | 114 + .../drivers/renesas/rcar/cpld/ulcb_cpld.h | 12 + .../drivers/renesas/rcar/pfc/D3/pfc_init_d3.c | 667 ++ .../drivers/renesas/rcar/pfc/D3/pfc_init_d3.h | 12 + .../drivers/renesas/rcar/pfc/E3/pfc_init_e3.c | 651 ++ .../drivers/renesas/rcar/pfc/E3/pfc_init_e3.h | 12 + .../renesas/rcar/pfc/H3/pfc_init_h3_v1.c | 1183 +++ .../renesas/rcar/pfc/H3/pfc_init_h3_v1.h | 12 + .../renesas/rcar/pfc/H3/pfc_init_h3_v2.c | 1216 +++ .../renesas/rcar/pfc/H3/pfc_init_h3_v2.h | 12 + .../drivers/renesas/rcar/pfc/M3/pfc_init_m3.c | 1311 +++ .../drivers/renesas/rcar/pfc/M3/pfc_init_m3.h | 12 + .../renesas/rcar/pfc/M3N/pfc_init_m3n.c | 1218 +++ .../renesas/rcar/pfc/M3N/pfc_init_m3n.h | 12 + .../renesas/rcar/pfc/V3M/pfc_init_v3m.c | 906 ++ .../renesas/rcar/pfc/V3M/pfc_init_v3m.h | 13 + .../drivers/renesas/rcar/pfc/pfc.mk | 69 + .../drivers/renesas/rcar/pfc/pfc_init.c | 199 + .../drivers/renesas/rcar/qos/D3/qos_init_d3.c | 147 + .../drivers/renesas/rcar/qos/D3/qos_init_d3.h | 13 + .../renesas/rcar/qos/D3/qos_init_d3_mstat.h | 244 + .../renesas/rcar/qos/E3/qos_init_e3_v10.c | 142 + .../renesas/rcar/qos/E3/qos_init_e3_v10.h | 12 + .../rcar/qos/E3/qos_init_e3_v10_mstat390.h | 241 + .../rcar/qos/E3/qos_init_e3_v10_mstat780.h | 241 + .../renesas/rcar/qos/H3/qos_init_h3_v10.c | 104 + .../renesas/rcar/qos/H3/qos_init_h3_v10.h | 12 + .../rcar/qos/H3/qos_init_h3_v10_mstat.h | 221 + .../renesas/rcar/qos/H3/qos_init_h3_v11.c | 200 + .../renesas/rcar/qos/H3/qos_init_h3_v11.h | 12 + .../rcar/qos/H3/qos_init_h3_v11_mstat.h | 221 + .../renesas/rcar/qos/H3/qos_init_h3_v20.c | 234 + .../renesas/rcar/qos/H3/qos_init_h3_v20.h | 12 + .../rcar/qos/H3/qos_init_h3_v20_mstat195.h | 231 + .../rcar/qos/H3/qos_init_h3_v20_mstat390.h | 231 + .../rcar/qos/H3/qos_init_h3_v20_qoswt195.h | 231 + .../rcar/qos/H3/qos_init_h3_v20_qoswt390.h | 231 + .../renesas/rcar/qos/H3/qos_init_h3_v30.c | 236 + .../renesas/rcar/qos/H3/qos_init_h3_v30.h | 12 + .../rcar/qos/H3/qos_init_h3_v30_mstat195.h | 231 + .../rcar/qos/H3/qos_init_h3_v30_mstat390.h | 231 + .../rcar/qos/H3/qos_init_h3_v30_qoswt195.h | 231 + .../rcar/qos/H3/qos_init_h3_v30_qoswt390.h | 231 + .../renesas/rcar/qos/H3/qos_init_h3n_v30.c | 230 + .../renesas/rcar/qos/H3/qos_init_h3n_v30.h | 12 + .../rcar/qos/H3/qos_init_h3n_v30_mstat195.h | 231 + .../rcar/qos/H3/qos_init_h3n_v30_mstat390.h | 231 + .../rcar/qos/H3/qos_init_h3n_v30_qoswt195.h | 231 + .../rcar/qos/H3/qos_init_h3n_v30_qoswt390.h | 231 + .../renesas/rcar/qos/M3/qos_init_m3_v10.c | 149 + .../renesas/rcar/qos/M3/qos_init_m3_v10.h | 12 + .../rcar/qos/M3/qos_init_m3_v10_mstat.h | 227 + .../renesas/rcar/qos/M3/qos_init_m3_v11.c | 223 + .../renesas/rcar/qos/M3/qos_init_m3_v11.h | 12 + .../rcar/qos/M3/qos_init_m3_v11_mstat195.h | 225 + .../rcar/qos/M3/qos_init_m3_v11_mstat390.h | 225 + .../rcar/qos/M3/qos_init_m3_v11_qoswt195.h | 225 + .../rcar/qos/M3/qos_init_m3_v11_qoswt390.h | 225 + .../renesas/rcar/qos/M3/qos_init_m3_v30.c | 209 + .../renesas/rcar/qos/M3/qos_init_m3_v30.h | 12 + .../rcar/qos/M3/qos_init_m3_v30_mstat195.h | 225 + .../rcar/qos/M3/qos_init_m3_v30_mstat390.h | 225 + .../rcar/qos/M3/qos_init_m3_v30_qoswt195.h | 225 + .../rcar/qos/M3/qos_init_m3_v30_qoswt390.h | 225 + .../renesas/rcar/qos/M3N/qos_init_m3n_v10.c | 203 + .../renesas/rcar/qos/M3N/qos_init_m3n_v10.h | 12 + .../rcar/qos/M3N/qos_init_m3n_v10_mstat195.h | 241 + .../rcar/qos/M3N/qos_init_m3n_v10_mstat390.h | 241 + .../rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h | 241 + .../rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h | 241 + .../renesas/rcar/qos/V3M/qos_init_v3m.c | 111 + .../renesas/rcar/qos/V3M/qos_init_v3m.h | 13 + .../renesas/rcar/qos/V3M/qos_init_v3m_mstat.h | 98 + .../drivers/renesas/rcar/qos/qos.mk | 106 + .../drivers/renesas/rcar/qos/qos_common.h | 142 + .../drivers/renesas/rcar/qos/qos_init.c | 394 + .../drivers/renesas/rcar/qos/qos_init.h | 13 + .../drivers/renesas/rzg/board/board.c | 97 + .../drivers/renesas/rzg/board/board.h | 33 + .../renesas/rzg/pfc/G2E/pfc_init_g2e.c | 700 ++ .../renesas/rzg/pfc/G2E/pfc_init_g2e.h | 12 + .../renesas/rzg/pfc/G2H/pfc_init_g2h.c | 1310 +++ .../renesas/rzg/pfc/G2H/pfc_init_g2h.h | 12 + .../renesas/rzg/pfc/G2M/pfc_init_g2m.c | 1300 +++ .../renesas/rzg/pfc/G2M/pfc_init_g2m.h | 12 + .../renesas/rzg/pfc/G2N/pfc_init_g2n.c | 1306 +++ .../renesas/rzg/pfc/G2N/pfc_init_g2n.h | 12 + .../drivers/renesas/rzg/pfc/pfc.mk | 41 + .../drivers/renesas/rzg/pfc/pfc_init.c | 129 + .../renesas/rzg/qos/G2E/qos_init_g2e_v10.c | 140 + .../renesas/rzg/qos/G2E/qos_init_g2e_v10.h | 12 + .../rzg/qos/G2E/qos_init_g2e_v10_mstat390.h | 245 + .../rzg/qos/G2E/qos_init_g2e_v10_mstat780.h | 246 + .../rzg/qos/G2H/qos_init_g2h_mstat195.h | 236 + .../rzg/qos/G2H/qos_init_g2h_mstat390.h | 236 + .../rzg/qos/G2H/qos_init_g2h_qoswt195.h | 236 + .../rzg/qos/G2H/qos_init_g2h_qoswt390.h | 236 + .../renesas/rzg/qos/G2H/qos_init_g2h_v30.c | 217 + .../renesas/rzg/qos/G2H/qos_init_g2h_v30.h | 12 + .../renesas/rzg/qos/G2M/qos_init_g2m_v10.c | 148 + .../renesas/rzg/qos/G2M/qos_init_g2m_v10.h | 12 + .../rzg/qos/G2M/qos_init_g2m_v10_mstat.h | 232 + .../renesas/rzg/qos/G2M/qos_init_g2m_v11.c | 218 + .../renesas/rzg/qos/G2M/qos_init_g2m_v11.h | 12 + .../rzg/qos/G2M/qos_init_g2m_v11_mstat195.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v11_mstat390.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h | 230 + .../renesas/rzg/qos/G2M/qos_init_g2m_v30.c | 210 + .../renesas/rzg/qos/G2M/qos_init_g2m_v30.h | 12 + .../rzg/qos/G2M/qos_init_g2m_v30_mstat195.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v30_mstat390.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h | 230 + .../rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h | 230 + .../renesas/rzg/qos/G2N/qos_init_g2n_v10.c | 196 + .../renesas/rzg/qos/G2N/qos_init_g2n_v10.h | 12 + .../rzg/qos/G2N/qos_init_g2n_v10_mstat195.h | 245 + .../rzg/qos/G2N/qos_init_g2n_v10_mstat390.h | 245 + .../rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h | 245 + .../rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h | 245 + .../drivers/renesas/rzg/qos/qos.mk | 60 + .../drivers/renesas/rzg/qos/qos_common.h | 105 + .../drivers/renesas/rzg/qos/qos_init.c | 267 + .../drivers/renesas/rzg/qos/qos_init.h | 13 + .../drivers/rpi3/gpio/rpi3_gpio.c | 163 + .../drivers/rpi3/mailbox/rpi3_mbox.c | 82 + .../drivers/rpi3/rng/rpi3_rng.c | 75 + .../drivers/rpi3/sdhost/rpi3_sdhost.c | 679 ++ arm-trusted-firmware/drivers/scmi-msg/base.c | 198 + arm-trusted-firmware/drivers/scmi-msg/base.h | 75 + arm-trusted-firmware/drivers/scmi-msg/clock.c | 381 + arm-trusted-firmware/drivers/scmi-msg/clock.h | 150 + .../drivers/scmi-msg/common.h | 144 + arm-trusted-firmware/drivers/scmi-msg/entry.c | 91 + .../drivers/scmi-msg/power_domain.c | 239 + .../drivers/scmi-msg/power_domain.h | 72 + .../drivers/scmi-msg/reset_domain.c | 197 + .../drivers/scmi-msg/reset_domain.h | 122 + arm-trusted-firmware/drivers/scmi-msg/smt.c | 206 + arm-trusted-firmware/drivers/st/bsec/bsec2.c | 961 +++ .../drivers/st/clk/clk-stm32-core.c | 1097 +++ .../drivers/st/clk/clk-stm32-core.h | 405 + .../drivers/st/clk/clk-stm32mp13.c | 2334 ++++++ .../drivers/st/clk/stm32mp1_clk.c | 2376 ++++++ .../drivers/st/clk/stm32mp_clkfunc.c | 378 + .../drivers/st/crypto/stm32_hash.c | 342 + .../drivers/st/ddr/stm32mp1_ddr.c | 764 ++ .../drivers/st/ddr/stm32mp1_ddr_helpers.c | 26 + .../drivers/st/ddr/stm32mp1_ram.c | 151 + .../drivers/st/ddr/stm32mp_ddr.c | 106 + .../drivers/st/ddr/stm32mp_ddr_test.c | 148 + .../drivers/st/ddr/stm32mp_ram.c | 60 + arm-trusted-firmware/drivers/st/etzpc/etzpc.c | 258 + .../drivers/st/fmc/stm32_fmc2_nand.c | 934 +++ .../drivers/st/gpio/stm32_gpio.c | 323 + .../drivers/st/i2c/stm32_i2c.c | 982 +++ arm-trusted-firmware/drivers/st/io/io_mmc.c | 143 + .../drivers/st/io/io_stm32image.c | 379 + .../drivers/st/iwdg/stm32_iwdg.c | 157 + .../drivers/st/mmc/stm32_sdmmc2.c | 776 ++ .../drivers/st/pmic/stm32mp_pmic.c | 526 ++ .../drivers/st/pmic/stpmic1.c | 937 +++ .../drivers/st/regulator/regulator_core.c | 560 ++ .../drivers/st/regulator/regulator_fixed.c | 87 + .../drivers/st/reset/stm32mp1_reset.c | 69 + .../drivers/st/spi/stm32_qspi.c | 513 ++ .../drivers/st/uart/aarch32/stm32_console.S | 255 + .../drivers/st/uart/stm32_uart.c | 404 + .../drivers/st/usb/stm32mp1_usb.c | 1091 +++ .../drivers/synopsys/emmc/dw_mmc.c | 432 + .../drivers/synopsys/ufs/dw_ufs.c | 202 + .../drivers/ti/uart/aarch32/16550_console.S | 274 + .../drivers/ti/uart/aarch64/16550_console.S | 267 + arm-trusted-firmware/drivers/ufs/ufs.c | 839 ++ arm-trusted-firmware/drivers/usb/usb_device.c | 845 ++ arm-trusted-firmware/fdts/a5ds.dts | 158 + arm-trusted-firmware/fdts/arm_fpga.dts | 108 + arm-trusted-firmware/fdts/corstone700.dtsi | 161 + .../fdts/corstone700_fpga.dts | 34 + arm-trusted-firmware/fdts/corstone700_fvp.dts | 40 + .../fdts/cot_descriptors.dtsi | 320 + .../fdts/fvp-base-gicv2-psci-aarch32.dts | 220 + .../fdts/fvp-base-gicv2-psci.dts | 173 + .../fdts/fvp-base-gicv3-psci-1t.dts | 14 + .../fdts/fvp-base-gicv3-psci-aarch32-1t.dts | 15 + .../fvp-base-gicv3-psci-aarch32-common.dtsi | 221 + .../fdts/fvp-base-gicv3-psci-aarch32.dts | 15 + .../fdts/fvp-base-gicv3-psci-common.dtsi | 244 + .../fdts/fvp-base-gicv3-psci-dynamiq-2t.dts | 18 + .../fvp-base-gicv3-psci-dynamiq-common.dtsi | 10 + .../fdts/fvp-base-gicv3-psci-dynamiq.dts | 18 + .../fdts/fvp-base-gicv3-psci.dts | 14 + .../fdts/fvp-defs-dynamiq.dtsi | 289 + arm-trusted-firmware/fdts/fvp-defs.dtsi | 400 + .../fdts/fvp-foundation-gicv2-psci.dts | 151 + .../fdts/fvp-foundation-gicv3-psci.dts | 160 + .../fdts/fvp-foundation-motherboard.dtsi | 184 + .../fdts/fvp-ve-Cortex-A5x1.dts | 144 + .../fdts/fvp-ve-Cortex-A7x1.dts | 76 + arm-trusted-firmware/fdts/juno-ethosn.dtsi | 27 + arm-trusted-firmware/fdts/juno.dts | 15 + arm-trusted-firmware/fdts/morello-fvp.dts | 170 + arm-trusted-firmware/fdts/morello-soc.dts | 271 + arm-trusted-firmware/fdts/morello.dtsi | 106 + .../fdts/n1sdp-multi-chip.dts | 113 + .../fdts/n1sdp-single-chip.dts | 92 + arm-trusted-firmware/fdts/n1sdp.dtsi | 210 + .../fdts/rtsm_ve-motherboard-aarch32.dtsi | 252 + .../fdts/rtsm_ve-motherboard.dtsi | 251 + arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi | 130 + arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi | 184 + .../fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi | 100 + .../fdts/stm32mp13-fw-config.dtsi | 55 + .../fdts/stm32mp13-pinctrl.dtsi | 97 + arm-trusted-firmware/fdts/stm32mp131.dtsi | 621 ++ arm-trusted-firmware/fdts/stm32mp133.dtsi | 21 + arm-trusted-firmware/fdts/stm32mp135.dtsi | 12 + .../fdts/stm32mp135f-dk-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp135f-dk.dts | 353 + arm-trusted-firmware/fdts/stm32mp13xa.dtsi | 5 + arm-trusted-firmware/fdts/stm32mp13xc.dtsi | 36 + arm-trusted-firmware/fdts/stm32mp13xd.dtsi | 5 + arm-trusted-firmware/fdts/stm32mp13xf.dtsi | 35 + arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi | 92 + arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi | 46 + arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi | 112 + .../fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi | 107 + .../fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi | 107 + .../fdts/stm32mp15-fw-config.dtsi | 80 + .../fdts/stm32mp15-pinctrl.dtsi | 386 + arm-trusted-firmware/fdts/stm32mp151.dtsi | 708 ++ arm-trusted-firmware/fdts/stm32mp153.dtsi | 19 + arm-trusted-firmware/fdts/stm32mp157.dtsi | 7 + .../fdts/stm32mp157a-avenger96-fw-config.dts | 7 + .../fdts/stm32mp157a-avenger96.dts | 307 + .../fdts/stm32mp157a-dk1-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp157a-dk1.dts | 27 + .../fdts/stm32mp157a-ed1-fw-config.dts | 7 + .../fdts/stm32mp157a-ev1-fw-config.dts | 7 + .../fdts/stm32mp157c-dk2-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp157c-dk2.dts | 33 + .../fdts/stm32mp157c-ed1-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp157c-ed1.dts | 363 + .../fdts/stm32mp157c-ev1-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp157c-ev1.dts | 63 + .../fdts/stm32mp157c-lxa-mc1-fw-config.dts | 7 + .../fdts/stm32mp157c-lxa-mc1.dts | 93 + .../fdts/stm32mp157c-odyssey-fw-config.dts | 7 + .../fdts/stm32mp157c-odyssey-som.dtsi | 325 + .../fdts/stm32mp157c-odyssey.dts | 40 + .../fdts/stm32mp157d-dk1-fw-config.dts | 7 + .../fdts/stm32mp157d-ed1-fw-config.dts | 7 + .../fdts/stm32mp157d-ev1-fw-config.dts | 7 + .../fdts/stm32mp157f-dk2-fw-config.dts | 7 + .../fdts/stm32mp157f-ed1-fw-config.dts | 7 + .../fdts/stm32mp157f-ev1-fw-config.dts | 7 + arm-trusted-firmware/fdts/stm32mp15xc.dtsi | 18 + .../fdts/stm32mp15xx-dkx.dtsi | 367 + .../fdts/stm32mp15xx-osd32.dtsi | 281 + .../fdts/stm32mp15xxaa-pinctrl.dtsi | 85 + .../fdts/stm32mp15xxab-pinctrl.dtsi | 57 + .../fdts/stm32mp15xxac-pinctrl.dtsi | 73 + .../fdts/stm32mp15xxad-pinctrl.dtsi | 57 + arm-trusted-firmware/fdts/tc.dts | 552 ++ .../include/arch/aarch32/arch.h | 778 ++ .../include/arch/aarch32/arch_features.h | 26 + .../include/arch/aarch32/arch_helpers.h | 470 ++ .../include/arch/aarch32/asm_macros.S | 237 + .../include/arch/aarch32/assert_macros.S | 26 + .../include/arch/aarch32/console_macros.S | 51 + .../include/arch/aarch32/el3_common_macros.S | 458 + .../include/arch/aarch32/smccc_helpers.h | 177 + .../include/arch/aarch32/smccc_macros.S | 241 + .../include/arch/aarch64/arch.h | 1273 +++ .../include/arch/aarch64/arch_features.h | 143 + .../include/arch/aarch64/arch_helpers.h | 671 ++ .../include/arch/aarch64/asm_macros.S | 231 + .../include/arch/aarch64/assert_macros.S | 29 + .../include/arch/aarch64/console_macros.S | 54 + .../include/arch/aarch64/el2_common_macros.S | 422 + .../include/arch/aarch64/el3_common_macros.S | 570 ++ .../include/arch/aarch64/smccc_helpers.h | 87 + arm-trusted-firmware/include/bl1/bl1.h | 102 + .../include/bl1/tbbr/tbbr_img_desc.h | 14 + arm-trusted-firmware/include/bl2/bl2.h | 18 + arm-trusted-firmware/include/bl2u/bl2u.h | 12 + arm-trusted-firmware/include/bl31/bl31.h | 27 + arm-trusted-firmware/include/bl31/ea_handle.h | 24 + arm-trusted-firmware/include/bl31/ehf.h | 92 + .../include/bl31/interrupt_mgmt.h | 147 + .../include/bl32/payloads/tlk.h | 72 + .../include/bl32/sp_min/platform_sp_min.h | 26 + .../include/bl32/tsp/platform_tsp.h | 17 + arm-trusted-firmware/include/bl32/tsp/tsp.h | 112 + .../include/common/asm_macros_common.S | 113 + .../include/common/bl_common.h | 190 + .../include/common/bl_common.ld.h | 216 + arm-trusted-firmware/include/common/debug.h | 118 + .../include/common/desc_image_load.h | 48 + arm-trusted-firmware/include/common/ep_info.h | 68 + .../include/common/fdt_fixup.h | 21 + .../include/common/fdt_wrappers.h | 59 + .../include/common/image_decompress.h | 24 + .../include/common/interrupt_props.h | 29 + .../include/common/nv_cntr_ids.h | 9 + .../include/common/param_header.h | 35 + arm-trusted-firmware/include/common/romlib.h | 16 + .../include/common/runtime_svc.h | 138 + .../include/common/tbbr/cot_def.h | 55 + .../include/common/tbbr/tbbr_img_def.h | 37 + .../include/common/tf_crc32.h | 16 + arm-trusted-firmware/include/common/uuid.h | 15 + .../include/drivers/allwinner/axp.h | 59 + .../include/drivers/allwinner/sunxi_rsb.h | 20 + .../include/drivers/amlogic/crypto/sha_dma.h | 36 + .../include/drivers/amlogic/meson_console.h | 30 + .../include/drivers/arm/arm_gicv3_common.h | 28 + .../include/drivers/arm/cci.h | 125 + .../include/drivers/arm/ccn.h | 113 + .../arm/cryptocell/712/cc_crypto_boot_defs.h | 34 + .../arm/cryptocell/712/cc_pal_sb_plat.h | 33 + .../drivers/arm/cryptocell/712/cc_pal_types.h | 40 + .../arm/cryptocell/712/cc_pal_types_plat.h | 25 + .../drivers/arm/cryptocell/712/cc_sec_defs.h | 34 + .../arm/cryptocell/712/crypto_driver.h | 35 + .../include/drivers/arm/cryptocell/712/nvm.h | 55 + .../drivers/arm/cryptocell/712/nvm_otp.h | 59 + .../include/drivers/arm/cryptocell/712/rsa.h | 57 + .../arm/cryptocell/712/sbrom_bsv_api.h | 72 + .../arm/cryptocell/712/secureboot_base_func.h | 49 + .../arm/cryptocell/712/secureboot_gen_defs.h | 66 + .../include/drivers/arm/cryptocell/712/util.h | 72 + .../drivers/arm/cryptocell/713/bsv_api.h | 221 + .../arm/cryptocell/713/bsv_crypto_api.h | 76 + .../arm/cryptocell/713/bsv_crypto_asym_api.h | 100 + .../arm/cryptocell/713/bsv_crypto_defs.h | 94 + .../drivers/arm/cryptocell/713/bsv_error.h | 161 + .../arm/cryptocell/713/cc_address_defs.h | 50 + .../drivers/arm/cryptocell/713/cc_boot_defs.h | 52 + .../drivers/arm/cryptocell/713/cc_pal_types.h | 100 + .../arm/cryptocell/713/cc_pal_types_plat.h | 25 + .../arm/cryptocell/713/cc_pka_hw_plat_defs.h | 62 + .../drivers/arm/cryptocell/713/cc_sec_defs.h | 70 + .../include/drivers/arm/cryptocell/cc_rotpk.h | 13 + .../include/drivers/arm/css/css_mhu.h | 19 + .../drivers/arm/css/css_mhu_doorbell.h | 44 + .../include/drivers/arm/css/css_scp.h | 52 + .../include/drivers/arm/css/css_scpi.h | 109 + .../include/drivers/arm/css/scmi.h | 176 + .../include/drivers/arm/css/sds.h | 90 + .../include/drivers/arm/dcc.h | 19 + .../include/drivers/arm/dsu.h | 133 + .../include/drivers/arm/ethosn.h | 61 + .../include/drivers/arm/fvp/fvp_pwrc.h | 55 + .../include/drivers/arm/gic600_multichip.h | 55 + .../include/drivers/arm/gic600ae_fmu.h | 157 + .../include/drivers/arm/gic_common.h | 105 + .../include/drivers/arm/gicv2.h | 196 + .../include/drivers/arm/gicv3.h | 547 ++ .../include/drivers/arm/nic_400.h | 16 + .../include/drivers/arm/pl011.h | 99 + .../include/drivers/arm/pl061_gpio.h | 15 + .../include/drivers/arm/sbsa.h | 24 + .../include/drivers/arm/scu.h | 20 + .../include/drivers/arm/smmu_v3.h | 36 + .../include/drivers/arm/sp804_delay_timer.h | 28 + .../include/drivers/arm/sp805.h | 36 + .../include/drivers/arm/tzc380.h | 164 + .../include/drivers/arm/tzc400.h | 160 + .../include/drivers/arm/tzc_common.h | 89 + .../include/drivers/arm/tzc_dmc500.h | 151 + .../include/drivers/arm/tzc_dmc620.h | 104 + .../include/drivers/auth/auth_common.h | 120 + .../include/drivers/auth/auth_mod.h | 92 + .../include/drivers/auth/crypto_mod.h | 138 + .../include/drivers/auth/img_parser_mod.h | 64 + .../drivers/auth/mbedtls/mbedtls_common.h | 12 + .../drivers/auth/mbedtls/mbedtls_config.h | 144 + .../include/drivers/auth/tbbr_cot_common.h | 29 + .../include/drivers/brcm/chimp.h | 94 + .../include/drivers/brcm/chimp_nv_defs.h | 419 + .../include/drivers/brcm/dmu.h | 35 + .../include/drivers/brcm/emmc/bcm_emmc.h | 104 + .../include/drivers/brcm/emmc/emmc_api.h | 47 + .../drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h | 1116 +++ .../include/drivers/brcm/emmc/emmc_chal_sd.h | 202 + .../drivers/brcm/emmc/emmc_chal_types.h | 20 + .../include/drivers/brcm/emmc/emmc_csl_sd.h | 96 + .../drivers/brcm/emmc/emmc_csl_sdcmd.h | 168 + .../drivers/brcm/emmc/emmc_csl_sdprot.h | 435 + .../brcm/emmc/emmc_pboot_hal_memory_drv.h | 94 + .../include/drivers/brcm/fru.h | 144 + .../include/drivers/brcm/i2c/i2c.h | 161 + .../include/drivers/brcm/i2c/i2c_regs.h | 271 + .../include/drivers/brcm/iproc_gpio.h | 20 + .../include/drivers/brcm/mdio/mdio.h | 31 + .../include/drivers/brcm/ocotp.h | 27 + .../include/drivers/brcm/scp.h | 14 + .../include/drivers/brcm/sf.h | 90 + .../include/drivers/brcm/sotp.h | 71 + .../include/drivers/brcm/spi.h | 21 + .../include/drivers/brcm/spi_flash.h | 18 + .../include/drivers/brcm/usbh_xhci_regs.h | 4809 +++++++++++ .../include/drivers/cadence/cdns_uart.h | 44 + .../include/drivers/cfi/v2m_flash.h | 45 + arm-trusted-firmware/include/drivers/clk.h | 28 + .../include/drivers/console.h | 83 + .../include/drivers/console_assertions.h | 29 + .../include/drivers/coreboot/cbmem_console.h | 25 + .../include/drivers/delay_timer.h | 53 + arm-trusted-firmware/include/drivers/dw_ufs.h | 110 + .../include/drivers/fwu/fwu.h | 16 + .../include/drivers/fwu/fwu_metadata.h | 74 + .../include/drivers/generic_delay_timer.h | 16 + arm-trusted-firmware/include/drivers/gpio.h | 40 + .../include/drivers/io/io_block.h | 28 + .../include/drivers/io/io_driver.h | 59 + .../include/drivers/io/io_dummy.h | 12 + .../include/drivers/io/io_encrypted.h | 15 + .../include/drivers/io/io_fip.h | 15 + .../include/drivers/io/io_memmap.h | 14 + .../include/drivers/io/io_mtd.h | 70 + .../include/drivers/io/io_semihosting.h | 14 + .../include/drivers/io/io_storage.h | 104 + .../include/drivers/marvell/addr_map.h | 21 + .../include/drivers/marvell/amb_adec.h | 36 + .../drivers/marvell/ap807_clocks_init.h | 14 + .../include/drivers/marvell/aro.h | 49 + .../include/drivers/marvell/cache_llc.h | 62 + .../include/drivers/marvell/ccu.h | 53 + .../include/drivers/marvell/gwin.h | 19 + .../include/drivers/marvell/i2c.h | 20 + .../include/drivers/marvell/io_win.h | 21 + .../include/drivers/marvell/iob.h | 31 + .../include/drivers/marvell/mci.h | 18 + .../include/drivers/marvell/mochi/ap_setup.h | 18 + .../drivers/marvell/mochi/cp110_setup.h | 66 + .../include/drivers/marvell/thermal.h | 31 + .../drivers/marvell/uart/a3700_console.h | 74 + .../measured_boot/event_log/event_log.h | 112 + .../drivers/measured_boot/event_log/tcg.h | 304 + .../include/drivers/mentor/mi2cv.h | 40 + arm-trusted-firmware/include/drivers/mmc.h | 244 + arm-trusted-firmware/include/drivers/nand.h | 65 + .../drivers/nxp/auth/csf_hdr_parser/csf_hdr.h | 155 + .../drivers/nxp/console/plat_console.h | 38 + .../include/drivers/nxp/crypto/caam/caam.h | 53 + .../include/drivers/nxp/crypto/caam/caam_io.h | 56 + .../include/drivers/nxp/crypto/caam/hash.h | 85 + .../include/drivers/nxp/crypto/caam/jobdesc.h | 56 + .../nxp/crypto/caam/jr_driver_config.h | 205 + .../include/drivers/nxp/crypto/caam/rsa.h | 40 + .../drivers/nxp/crypto/caam/sec_hw_specific.h | 503 ++ .../drivers/nxp/crypto/caam/sec_jr_driver.h | 178 + .../include/drivers/nxp/csu/csu.h | 42 + .../include/drivers/nxp/dcfg/dcfg.h | 103 + .../include/drivers/nxp/dcfg/dcfg_lsch2.h | 85 + .../include/drivers/nxp/dcfg/dcfg_lsch3.h | 80 + .../include/drivers/nxp/dcfg/scfg.h | 65 + .../include/drivers/nxp/ddr/ddr.h | 151 + .../include/drivers/nxp/ddr/ddr_io.h | 38 + .../include/drivers/nxp/ddr/dimm.h | 330 + .../drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h | 173 + .../include/drivers/nxp/ddr/immap.h | 125 + .../include/drivers/nxp/ddr/opts.h | 119 + .../include/drivers/nxp/ddr/regs.h | 109 + .../include/drivers/nxp/ddr/utility.h | 24 + .../include/drivers/nxp/flexspi/flash_info.h | 89 + .../include/drivers/nxp/flexspi/fspi_api.h | 122 + .../drivers/nxp/flexspi/xspi_error_codes.h | 28 + .../include/drivers/nxp/gic/gicv2/plat_gic.h | 72 + .../include/drivers/nxp/gic/gicv3/plat_gic.h | 121 + .../include/drivers/nxp/gpio/nxp_gpio.h | 53 + .../include/drivers/nxp/i2c/i2c.h | 52 + .../include/drivers/nxp/ifc/ifc_nand.h | 19 + .../include/drivers/nxp/ifc/ifc_nor.h | 14 + .../nxp/interconnect/ls_interconnect.h | 19 + .../include/drivers/nxp/pmu/pmu.h | 75 + .../include/drivers/nxp/qspi/qspi.h | 30 + .../include/drivers/nxp/sd/sd_mmc.h | 337 + .../include/drivers/nxp/sec_mon/snvs.h | 86 + .../include/drivers/nxp/sfp/fuse_prov.h | 83 + .../include/drivers/nxp/sfp/sfp.h | 100 + .../include/drivers/nxp/sfp/sfp_error_codes.h | 40 + .../include/drivers/nxp/smmu/nxp_smmu.h | 30 + .../include/drivers/nxp/timer/nxp_timer.h | 35 + .../include/drivers/nxp/tzc/plat_tzc380.h | 47 + .../include/drivers/nxp/tzc/plat_tzc400.h | 55 + .../include/drivers/partition/efi.h | 37 + .../include/drivers/partition/gpt.h | 52 + .../include/drivers/partition/mbr.h | 29 + .../include/drivers/partition/partition.h | 50 + .../include/drivers/rambus/trng_ip_76.h | 18 + .../include/drivers/raw_nand.h | 188 + .../drivers/renesas/rcar/console/console.h | 25 + .../include/drivers/rpi3/gpio/rpi3_gpio.h | 34 + .../include/drivers/rpi3/mailbox/rpi3_mbox.h | 39 + .../include/drivers/rpi3/rng/rpi3_rng.h | 12 + .../include/drivers/rpi3/sdhost/rpi3_sdhost.h | 123 + .../include/drivers/scmi-msg.h | 207 + arm-trusted-firmware/include/drivers/scmi.h | 29 + .../include/drivers/spi_mem.h | 130 + .../include/drivers/spi_nand.h | 49 + .../include/drivers/spi_nor.h | 58 + .../include/drivers/st/bsec.h | 129 + .../include/drivers/st/bsec2_reg.h | 106 + .../include/drivers/st/etzpc.h | 38 + .../include/drivers/st/io_mmc.h | 18 + .../include/drivers/st/io_stm32image.h | 32 + .../include/drivers/st/regulator.h | 108 + .../include/drivers/st/regulator_fixed.h | 12 + .../include/drivers/st/stm32_console.h | 27 + .../include/drivers/st/stm32_fmc2_nand.h | 12 + .../include/drivers/st/stm32_gpio.h | 63 + .../include/drivers/st/stm32_hash.h | 24 + .../include/drivers/st/stm32_i2c.h | 321 + .../include/drivers/st/stm32_iwdg.h | 19 + .../include/drivers/st/stm32_qspi.h | 12 + .../include/drivers/st/stm32_sdmmc2.h | 35 + .../include/drivers/st/stm32_uart.h | 170 + .../include/drivers/st/stm32_uart_regs.h | 199 + .../include/drivers/st/stm32mp13_rcc.h | 1878 +++++ .../include/drivers/st/stm32mp15_rcc.h | 2328 ++++++ .../include/drivers/st/stm32mp1_clk.h | 38 + .../include/drivers/st/stm32mp1_ddr.h | 134 + .../include/drivers/st/stm32mp1_ddr_helpers.h | 12 + .../include/drivers/st/stm32mp1_ddr_regs.h | 196 + .../include/drivers/st/stm32mp1_pwr.h | 32 + .../include/drivers/st/stm32mp1_ram.h | 12 + .../include/drivers/st/stm32mp1_rcc.h | 12 + .../include/drivers/st/stm32mp1_usb.h | 16 + .../include/drivers/st/stm32mp_clkfunc.h | 36 + .../include/drivers/st/stm32mp_ddr.h | 69 + .../include/drivers/st/stm32mp_ddr_test.h | 17 + .../include/drivers/st/stm32mp_ddrctrl_regs.h | 265 + .../include/drivers/st/stm32mp_pmic.h | 58 + .../include/drivers/st/stm32mp_ram.h | 33 + .../include/drivers/st/stm32mp_reset.h | 50 + .../include/drivers/st/stpmic1.h | 198 + .../include/drivers/synopsys/dw_mmc.h | 24 + .../include/drivers/ti/uart/uart_16550.h | 94 + arm-trusted-firmware/include/drivers/ufs.h | 559 ++ .../include/drivers/usb_device.h | 278 + .../include/dt-bindings/clock/stm32mp1-clks.h | 12 + .../dt-bindings/clock/stm32mp1-clksrc.h | 11 + .../dt-bindings/clock/stm32mp13-clks.h | 230 + .../dt-bindings/clock/stm32mp13-clksrc.h | 394 + .../dt-bindings/clock/stm32mp15-clks.h | 278 + .../dt-bindings/clock/stm32mp15-clksrc.h | 282 + .../interrupt-controller/arm-gic.h | 26 + .../dt-bindings/interrupt-controller/irq.h | 23 + .../dt-bindings/pinctrl/stm32-pinfunc.h | 42 + .../dt-bindings/reset/stm32mp1-resets.h | 11 + .../dt-bindings/reset/stm32mp13-resets.h | 96 + .../dt-bindings/reset/stm32mp15-resets.h | 123 + .../include/dt-bindings/soc/st,stm32-etzpc.h | 20 + .../dt-bindings/soc/stm32mp13-tzc400.h | 35 + .../dt-bindings/soc/stm32mp15-tzc400.h | 36 + arm-trusted-firmware/include/export/README | 33 + .../include/export/common/bl_common_exp.h | 95 + .../include/export/common/ep_info_exp.h | 119 + .../include/export/common/param_header_exp.h | 42 + .../export/common/tbbr/tbbr_img_def_exp.h | 110 + .../include/export/drivers/gpio_exp.h | 23 + .../lib/bl_aux_params/bl_aux_params_exp.h | 89 + .../include/export/lib/utils_def_exp.h | 37 + .../plat/mediatek/common/plat_params_exp.h | 19 + .../plat/rockchip/common/plat_params_exp.h | 35 + .../include/lib/bakery_lock.h | 105 + .../include/lib/bl_aux_params/bl_aux_params.h | 30 + arm-trusted-firmware/include/lib/cassert.h | 23 + arm-trusted-firmware/include/lib/coreboot.h | 45 + .../include/lib/cpus/aarch32/aem_generic.h | 15 + .../include/lib/cpus/aarch32/cortex_a12.h | 22 + .../include/lib/cpus/aarch32/cortex_a15.h | 30 + .../include/lib/cpus/aarch32/cortex_a17.h | 27 + .../include/lib/cpus/aarch32/cortex_a32.h | 22 + .../include/lib/cpus/aarch32/cortex_a5.h | 22 + .../include/lib/cpus/aarch32/cortex_a53.h | 73 + .../include/lib/cpus/aarch32/cortex_a57.h | 84 + .../include/lib/cpus/aarch32/cortex_a7.h | 22 + .../include/lib/cpus/aarch32/cortex_a72.h | 58 + .../include/lib/cpus/aarch32/cortex_a9.h | 33 + .../include/lib/cpus/aarch32/cpu_macros.S | 230 + .../include/lib/cpus/aarch64/aem_generic.h | 18 + .../include/lib/cpus/aarch64/cortex_a35.h | 29 + .../include/lib/cpus/aarch64/cortex_a510.h | 37 + .../include/lib/cpus/aarch64/cortex_a53.h | 85 + .../include/lib/cpus/aarch64/cortex_a55.h | 48 + .../include/lib/cpus/aarch64/cortex_a57.h | 88 + .../include/lib/cpus/aarch64/cortex_a65.h | 31 + .../include/lib/cpus/aarch64/cortex_a65ae.h | 31 + .../include/lib/cpus/aarch64/cortex_a710.h | 54 + .../include/lib/cpus/aarch64/cortex_a72.h | 79 + .../include/lib/cpus/aarch64/cortex_a73.h | 45 + .../include/lib/cpus/aarch64/cortex_a75.h | 55 + .../include/lib/cpus/aarch64/cortex_a76.h | 78 + .../include/lib/cpus/aarch64/cortex_a76ae.h | 28 + .../include/lib/cpus/aarch64/cortex_a77.h | 43 + .../include/lib/cpus/aarch64/cortex_a78.h | 54 + .../include/lib/cpus/aarch64/cortex_a78_ae.h | 40 + .../include/lib/cpus/aarch64/cortex_a78c.h | 30 + .../include/lib/cpus/aarch64/cortex_hayes.h | 23 + .../include/lib/cpus/aarch64/cortex_hunter.h | 23 + .../include/lib/cpus/aarch64/cortex_makalu.h | 23 + .../lib/cpus/aarch64/cortex_makalu_elp_arm.h | 23 + .../include/lib/cpus/aarch64/cortex_x2.h | 50 + .../include/lib/cpus/aarch64/cpu_macros.S | 314 + .../include/lib/cpus/aarch64/cpuamu.h | 48 + .../include/lib/cpus/aarch64/denver.h | 60 + .../include/lib/cpus/aarch64/dsu_def.h | 41 + .../include/lib/cpus/aarch64/generic.h | 18 + .../lib/cpus/aarch64/neoverse_demeter.h | 23 + .../include/lib/cpus/aarch64/neoverse_e1.h | 31 + .../include/lib/cpus/aarch64/neoverse_n1.h | 70 + .../include/lib/cpus/aarch64/neoverse_n2.h | 58 + .../lib/cpus/aarch64/neoverse_n_common.h | 18 + .../lib/cpus/aarch64/neoverse_poseidon.h | 24 + .../include/lib/cpus/aarch64/neoverse_v1.h | 38 + .../include/lib/cpus/aarch64/qemu_max.h | 22 + .../include/lib/cpus/aarch64/rainier.h | 66 + .../include/lib/cpus/errata_report.h | 36 + .../include/lib/cpus/wa_cve_2017_5715.h | 12 + .../include/lib/cpus/wa_cve_2018_3639.h | 12 + .../include/lib/cpus/wa_cve_2022_23960.h | 12 + arm-trusted-firmware/include/lib/debugfs.h | 83 + .../include/lib/el3_runtime/aarch32/context.h | 70 + .../include/lib/el3_runtime/aarch64/context.h | 526 ++ .../include/lib/el3_runtime/context_mgmt.h | 88 + .../include/lib/el3_runtime/cpu_data.h | 237 + .../include/lib/el3_runtime/pubsub.h | 106 + .../include/lib/el3_runtime/pubsub_events.h | 43 + .../include/lib/extensions/amu.h | 47 + .../include/lib/extensions/mpam.h | 14 + .../include/lib/extensions/pauth.h | 18 + .../include/lib/extensions/ras.h | 203 + .../include/lib/extensions/ras_arch.h | 267 + .../include/lib/extensions/sme.h | 27 + .../include/lib/extensions/spe.h | 16 + .../include/lib/extensions/sve.h | 15 + .../include/lib/extensions/sys_reg_trace.h | 18 + .../include/lib/extensions/trbe.h | 12 + .../include/lib/extensions/trf.h | 12 + .../include/lib/extensions/twed.h | 16 + .../include/lib/fconf/fconf.h | 69 + .../include/lib/fconf/fconf_amu_getter.h | 20 + .../include/lib/fconf/fconf_dyn_cfg_getter.h | 31 + .../include/lib/fconf/fconf_mpmm_getter.h | 20 + .../include/lib/fconf/fconf_tbbr_getter.h | 32 + .../include/lib/gpt_rme/gpt_rme.h | 280 + .../include/lib/libc/aarch32/endian_.h | 146 + .../include/lib/libc/aarch32/inttypes_.h | 21 + .../include/lib/libc/aarch32/limits_.h | 26 + .../include/lib/libc/aarch32/stddef_.h | 15 + .../include/lib/libc/aarch32/stdint_.h | 28 + .../include/lib/libc/aarch32/stdio_.h | 15 + .../include/lib/libc/aarch64/endian_.h | 128 + .../include/lib/libc/aarch64/inttypes_.h | 21 + .../include/lib/libc/aarch64/limits_.h | 26 + .../include/lib/libc/aarch64/setjmp_.h | 30 + .../include/lib/libc/aarch64/stddef_.h | 15 + .../include/lib/libc/aarch64/stdint_.h | 31 + .../include/lib/libc/aarch64/stdio_.h | 15 + .../include/lib/libc/arm_acle.h | 24 + .../include/lib/libc/assert.h | 41 + arm-trusted-firmware/include/lib/libc/cdefs.h | 37 + .../include/lib/libc/endian.h | 191 + arm-trusted-firmware/include/lib/libc/errno.h | 169 + .../include/lib/libc/inttypes.h | 47 + .../include/lib/libc/limits.h | 19 + .../include/lib/libc/setjmp.h | 20 + .../include/lib/libc/stdarg.h | 20 + .../include/lib/libc/stdbool.h | 17 + .../include/lib/libc/stddef.h | 27 + .../include/lib/libc/stdint.h | 122 + arm-trusted-firmware/include/lib/libc/stdio.h | 31 + .../include/lib/libc/stdlib.h | 32 + .../include/lib/libc/string.h | 32 + arm-trusted-firmware/include/lib/libc/time.h | 18 + arm-trusted-firmware/include/lib/libfdt/fdt.h | 66 + .../include/lib/libfdt/libfdt.h | 2080 +++++ .../include/lib/libfdt/libfdt_env.h | 96 + arm-trusted-firmware/include/lib/mmio.h | 76 + arm-trusted-firmware/include/lib/mpmm/mpmm.h | 57 + .../include/lib/object_pool.h | 79 + .../include/lib/optee_utils.h | 20 + .../include/lib/pmf/aarch32/pmf_asm_macros.S | 28 + .../include/lib/pmf/aarch64/pmf_asm_macros.S | 30 + arm-trusted-firmware/include/lib/pmf/pmf.h | 75 + .../include/lib/pmf/pmf_helpers.h | 256 + arm-trusted-firmware/include/lib/psci/psci.h | 355 + .../include/lib/psci/psci_lib.h | 96 + .../include/lib/runtime_instr.h | 25 + .../include/lib/semihosting.h | 60 + arm-trusted-firmware/include/lib/smccc.h | 211 + arm-trusted-firmware/include/lib/spinlock.h | 29 + arm-trusted-firmware/include/lib/utils.h | 94 + arm-trusted-firmware/include/lib/utils_def.h | 171 + .../include/lib/xlat_mpu/xlat_mpu.h | 27 + .../xlat_tables/aarch32/xlat_tables_aarch32.h | 72 + .../xlat_tables/aarch64/xlat_tables_aarch64.h | 96 + .../lib/xlat_tables/xlat_mmu_helpers.h | 94 + .../include/lib/xlat_tables/xlat_tables.h | 99 + .../lib/xlat_tables/xlat_tables_arch.h | 31 + .../lib/xlat_tables/xlat_tables_compat.h | 11 + .../lib/xlat_tables/xlat_tables_defs.h | 183 + .../include/lib/xlat_tables/xlat_tables_v2.h | 416 + .../lib/xlat_tables/xlat_tables_v2_helpers.h | 180 + .../include/lib/zlib/tf_gunzip.h | 16 + .../plat/arm/board/common/board_css_def.h | 79 + .../include/plat/arm/board/common/v2m_def.h | 140 + .../include/plat/arm/board/fvp_r/fvp_r_bl1.h | 13 + .../plat/arm/common/aarch64/arm_macros.S | 104 + .../plat/arm/common/aarch64/cci_macros.S | 37 + .../include/plat/arm/common/arm_config.h | 43 + .../include/plat/arm/common/arm_def.h | 737 ++ .../plat/arm/common/arm_dyn_cfg_helpers.h | 17 + .../plat/arm/common/arm_fconf_getter.h | 29 + .../plat/arm/common/arm_fconf_io_storage.h | 19 + .../include/plat/arm/common/arm_pas_def.h | 94 + .../plat/arm/common/arm_reclaim_init.ld.S | 43 + .../include/plat/arm/common/arm_sip_svc.h | 38 + .../include/plat/arm/common/arm_spm_def.h | 103 + .../include/plat/arm/common/arm_tzc_dram.ld.S | 30 + .../plat/arm/common/fconf_arm_sp_getter.h | 32 + .../plat/arm/common/fconf_ethosn_getter.h | 38 + .../plat/arm/common/fconf_nv_cntr_getter.h | 17 + .../plat/arm/common/fconf_sdei_getter.h | 31 + .../plat/arm/common/fconf_sec_intr_config.h | 27 + .../include/plat/arm/common/plat_arm.h | 361 + .../include/plat/arm/common/smccc_def.h | 13 + .../plat/arm/css/common/aarch64/css_macros.S | 25 + .../include/plat/arm/css/common/css_def.h | 205 + .../include/plat/arm/css/common/css_pm.h | 58 + .../include/plat/arm/soc/common/soc_css.h | 22 + .../include/plat/arm/soc/common/soc_css_def.h | 86 + .../include/plat/brcm/common/bcm_console.h | 15 + .../include/plat/brcm/common/bcm_elog.h | 38 + .../include/plat/brcm/common/brcm_def.h | 153 + .../include/plat/brcm/common/plat_brcm.h | 41 + .../include/plat/common/common_def.h | 127 + .../include/plat/common/plat_trng.h | 18 + .../include/plat/common/platform.h | 403 + .../marvell/armada/a3k/common/armada_common.h | 17 + .../armada/a3k/common/board_marvell_def.h | 74 + .../marvell/armada/a3k/common/marvell_def.h | 188 + .../marvell/armada/a3k/common/plat_marvell.h | 105 + .../marvell/armada/a8k/common/armada_common.h | 129 + .../armada/a8k/common/board_marvell_def.h | 74 + .../marvell/armada/a8k/common/efuse_def.h | 33 + .../marvell/armada/a8k/common/marvell_def.h | 222 + .../marvell/armada/a8k/common/plat_marvell.h | 137 + .../marvell/armada/a8k/common/plat_pm_trace.h | 99 + .../armada/common/aarch64/cci_macros.S | 39 + .../armada/common/aarch64/marvell_macros.S | 134 + .../marvell/armada/common/marvell_plat_priv.h | 34 + .../plat/marvell/armada/common/marvell_pm.h | 26 + .../plat/marvell/armada/common/mvebu.h | 39 + .../include/services/arm_arch_svc.h | 29 + .../include/services/ffa_svc.h | 212 + .../include/services/pci_svc.h | 59 + .../include/services/rmmd_svc.h | 142 + arm-trusted-firmware/include/services/sdei.h | 140 + .../include/services/sdei_flags.h | 56 + .../include/services/spm_core_manifest.h | 53 + .../include/services/spm_mm_partition.h | 50 + .../include/services/spm_mm_svc.h | 114 + .../include/services/spmd_svc.h | 25 + .../include/services/std_svc.h | 30 + .../include/services/trng_svc.h | 57 + .../include/services/trp/platform_trp.h | 15 + .../include/tools_share/dualroot_oid.h | 19 + .../include/tools_share/firmware_encrypted.h | 42 + .../tools_share/firmware_image_package.h | 104 + .../include/tools_share/sptool.h | 25 + .../include/tools_share/tbbr_oid.h | 166 + .../include/tools_share/uuid.h | 74 + .../lib/aarch32/arm32_aeabi_divmod.c | 156 + .../lib/aarch32/arm32_aeabi_divmod_a32.S | 30 + .../lib/aarch32/armclang_printf.S | 19 + .../lib/aarch32/cache_helpers.S | 233 + .../lib/aarch32/misc_helpers.S | 315 + .../lib/aarch64/armclang_printf.S | 25 + .../lib/aarch64/cache_helpers.S | 254 + .../lib/aarch64/misc_helpers.S | 613 ++ .../lib/bl_aux_params/bl_aux_params.c | 35 + .../lib/compiler-rt/LICENSE.TXT | 91 + .../compiler-rt/builtins/arm/aeabi_ldivmod.S | 46 + .../compiler-rt/builtins/arm/aeabi_uldivmod.S | 46 + .../lib/compiler-rt/builtins/assembly.h | 169 + .../lib/compiler-rt/builtins/ctzdi2.c | 29 + .../lib/compiler-rt/builtins/divdi3.c | 29 + .../lib/compiler-rt/builtins/divmoddi4.c | 25 + .../lib/compiler-rt/builtins/int_endianness.h | 116 + .../lib/compiler-rt/builtins/int_lib.h | 127 + .../lib/compiler-rt/builtins/int_math.h | 114 + .../lib/compiler-rt/builtins/int_types.h | 166 + .../lib/compiler-rt/builtins/lshrdi3.c | 45 + .../lib/compiler-rt/builtins/popcountdi2.c | 36 + .../lib/compiler-rt/builtins/popcountsi2.c | 33 + .../lib/compiler-rt/builtins/udivmoddi4.c | 231 + .../lib/compiler-rt/compiler-rt.mk | 42 + arm-trusted-firmware/lib/coreboot/coreboot.mk | 22 + .../lib/coreboot/coreboot_table.c | 156 + .../lib/cpus/aarch32/aem_generic.S | 55 + .../lib/cpus/aarch32/cortex_a12.S | 84 + .../lib/cpus/aarch32/cortex_a15.S | 181 + .../lib/cpus/aarch32/cortex_a17.S | 185 + .../lib/cpus/aarch32/cortex_a32.S | 132 + .../lib/cpus/aarch32/cortex_a5.S | 84 + .../lib/cpus/aarch32/cortex_a53.S | 316 + .../lib/cpus/aarch32/cortex_a57.S | 612 ++ .../lib/cpus/aarch32/cortex_a7.S | 84 + .../lib/cpus/aarch32/cortex_a72.S | 272 + .../lib/cpus/aarch32/cortex_a9.S | 121 + .../lib/cpus/aarch32/cpu_helpers.S | 264 + .../lib/cpus/aarch64/aem_generic.S | 113 + .../lib/cpus/aarch64/cortex_a35.S | 196 + .../lib/cpus/aarch64/cortex_a510.S | 380 + .../lib/cpus/aarch64/cortex_a53.S | 409 + .../lib/cpus/aarch64/cortex_a55.S | 351 + .../lib/cpus/aarch64/cortex_a57.S | 686 ++ .../lib/cpus/aarch64/cortex_a65.S | 81 + .../lib/cpus/aarch64/cortex_a65ae.S | 81 + .../lib/cpus/aarch64/cortex_a710.S | 456 + .../lib/cpus/aarch64/cortex_a72.S | 374 + .../lib/cpus/aarch64/cortex_a73.S | 305 + .../lib/cpus/aarch64/cortex_a75.S | 261 + .../lib/cpus/aarch64/cortex_a75_pubsub.c | 28 + .../lib/cpus/aarch64/cortex_a76.S | 812 ++ .../lib/cpus/aarch64/cortex_a76ae.S | 113 + .../lib/cpus/aarch64/cortex_a77.S | 317 + .../lib/cpus/aarch64/cortex_a78.S | 421 + .../lib/cpus/aarch64/cortex_a78_ae.S | 398 + .../lib/cpus/aarch64/cortex_a78c.S | 108 + .../lib/cpus/aarch64/cortex_hayes.S | 77 + .../lib/cpus/aarch64/cortex_hunter.S | 77 + .../lib/cpus/aarch64/cortex_makalu.S | 77 + .../lib/cpus/aarch64/cortex_makalu_elp_arm.S | 77 + .../lib/cpus/aarch64/cortex_x2.S | 358 + .../lib/cpus/aarch64/cpu_helpers.S | 456 + .../lib/cpus/aarch64/cpuamu.c | 70 + .../lib/cpus/aarch64/cpuamu_helpers.S | 99 + .../lib/cpus/aarch64/denver.S | 386 + .../lib/cpus/aarch64/dsu_helpers.S | 141 + .../lib/cpus/aarch64/generic.S | 89 + .../lib/cpus/aarch64/neoverse_demeter.S | 77 + .../lib/cpus/aarch64/neoverse_e1.S | 81 + .../lib/cpus/aarch64/neoverse_n1.S | 714 ++ .../lib/cpus/aarch64/neoverse_n1_pubsub.c | 28 + .../lib/cpus/aarch64/neoverse_n2.S | 523 ++ .../lib/cpus/aarch64/neoverse_n_common.S | 26 + .../lib/cpus/aarch64/neoverse_poseidon.S | 77 + .../lib/cpus/aarch64/neoverse_v1.S | 474 ++ .../lib/cpus/aarch64/qemu_max.S | 81 + .../lib/cpus/aarch64/rainier.S | 175 + .../cpus/aarch64/wa_cve_2017_5715_bpiall.S | 368 + .../lib/cpus/aarch64/wa_cve_2017_5715_mmu.S | 152 + .../lib/cpus/aarch64/wa_cve_2022_23960_bhb.S | 31 + .../aarch64/wa_cve_2022_23960_bhb_vector.S | 108 + arm-trusted-firmware/lib/cpus/cpu-ops.mk | 1128 +++ arm-trusted-firmware/lib/cpus/errata_report.c | 101 + arm-trusted-firmware/lib/debugfs/blobs.h | 12 + arm-trusted-firmware/lib/debugfs/debugfs.mk | 13 + .../lib/debugfs/debugfs_smc.c | 209 + arm-trusted-firmware/lib/debugfs/dev.c | 853 ++ arm-trusted-firmware/lib/debugfs/dev.h | 120 + arm-trusted-firmware/lib/debugfs/devc.c | 20 + arm-trusted-firmware/lib/debugfs/devfip.c | 321 + arm-trusted-firmware/lib/debugfs/devroot.c | 97 + .../lib/el3_runtime/aarch32/context_mgmt.c | 334 + .../lib/el3_runtime/aarch32/cpu_data.S | 42 + .../lib/el3_runtime/aarch64/context.S | 1014 +++ .../lib/el3_runtime/aarch64/context_mgmt.c | 878 ++ .../lib/el3_runtime/aarch64/cpu_data.S | 48 + .../lib/el3_runtime/cpu_data_array.c | 13 + .../lib/extensions/amu/aarch32/amu.c | 421 + .../lib/extensions/amu/aarch32/amu_helpers.S | 271 + .../lib/extensions/amu/aarch64/amu.c | 638 ++ .../lib/extensions/amu/aarch64/amu_helpers.S | 389 + .../lib/extensions/amu/amu.mk | 24 + .../lib/extensions/amu/amu_private.h | 38 + .../lib/extensions/mpam/mpam.c | 46 + .../lib/extensions/mtpmu/aarch32/mtpmu.S | 105 + .../lib/extensions/mtpmu/aarch64/mtpmu.S | 96 + .../lib/extensions/pauth/pauth_helpers.S | 141 + .../lib/extensions/ras/ras_common.c | 196 + .../lib/extensions/ras/std_err_record.c | 79 + arm-trusted-firmware/lib/extensions/sme/sme.c | 103 + arm-trusted-firmware/lib/extensions/spe/spe.c | 98 + arm-trusted-firmware/lib/extensions/sve/sve.c | 65 + .../sys_reg_trace/aarch32/sys_reg_trace.c | 36 + .../sys_reg_trace/aarch64/sys_reg_trace.c | 37 + .../lib/extensions/trbe/trbe.c | 63 + .../lib/extensions/trf/aarch32/trf.c | 35 + .../lib/extensions/trf/aarch64/trf.c | 36 + arm-trusted-firmware/lib/fconf/fconf.c | 78 + arm-trusted-firmware/lib/fconf/fconf.mk | 19 + .../lib/fconf/fconf_amu_getter.c | 142 + .../lib/fconf/fconf_cot_getter.c | 497 ++ .../lib/fconf/fconf_dyn_cfg_getter.c | 143 + .../lib/fconf/fconf_mpmm_getter.c | 80 + .../lib/fconf/fconf_tbbr_getter.c | 84 + arm-trusted-firmware/lib/gpt_rme/gpt_rme.c | 1255 +++ arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk | 8 + .../lib/gpt_rme/gpt_rme_private.h | 261 + .../lib/libc/aarch32/memset.S | 74 + .../lib/libc/aarch64/memset.S | 64 + .../lib/libc/aarch64/setjmp.S | 61 + arm-trusted-firmware/lib/libc/abort.c | 15 + arm-trusted-firmware/lib/libc/assert.c | 44 + arm-trusted-firmware/lib/libc/exit.c | 26 + arm-trusted-firmware/lib/libc/libc.mk | 41 + arm-trusted-firmware/lib/libc/libc_asm.mk | 44 + arm-trusted-firmware/lib/libc/memchr.c | 21 + arm-trusted-firmware/lib/libc/memcmp.c | 25 + arm-trusted-firmware/lib/libc/memcpy.c | 19 + arm-trusted-firmware/lib/libc/memmove.c | 31 + arm-trusted-firmware/lib/libc/memrchr.c | 24 + arm-trusted-firmware/lib/libc/memset.c | 51 + arm-trusted-firmware/lib/libc/printf.c | 200 + arm-trusted-firmware/lib/libc/putchar.c | 20 + arm-trusted-firmware/lib/libc/puts.c | 24 + arm-trusted-firmware/lib/libc/snprintf.c | 249 + arm-trusted-firmware/lib/libc/strchr.c | 53 + arm-trusted-firmware/lib/libc/strcmp.c | 52 + arm-trusted-firmware/lib/libc/strlcat.c | 56 + arm-trusted-firmware/lib/libc/strlcpy.c | 52 + arm-trusted-firmware/lib/libc/strlen.c | 17 + arm-trusted-firmware/lib/libc/strncmp.c | 53 + arm-trusted-firmware/lib/libc/strnlen.c | 46 + arm-trusted-firmware/lib/libc/strrchr.c | 49 + arm-trusted-firmware/lib/libc/strtok.c | 83 + arm-trusted-firmware/lib/libc/strtol.c | 133 + arm-trusted-firmware/lib/libc/strtoll.c | 134 + arm-trusted-firmware/lib/libc/strtoul.c | 112 + arm-trusted-firmware/lib/libc/strtoull.c | 112 + arm-trusted-firmware/lib/libfdt/fdt.c | 327 + .../lib/libfdt/fdt_addresses.c | 101 + .../lib/libfdt/fdt_empty_tree.c | 38 + arm-trusted-firmware/lib/libfdt/fdt_overlay.c | 882 ++ arm-trusted-firmware/lib/libfdt/fdt_ro.c | 859 ++ arm-trusted-firmware/lib/libfdt/fdt_rw.c | 492 ++ .../lib/libfdt/fdt_strerror.c | 59 + arm-trusted-firmware/lib/libfdt/fdt_sw.c | 384 + arm-trusted-firmware/lib/libfdt/fdt_wip.c | 94 + arm-trusted-firmware/lib/libfdt/libfdt.mk | 19 + .../lib/libfdt/libfdt_internal.h | 173 + .../lib/locks/bakery/bakery_lock_coherent.c | 168 + .../lib/locks/bakery/bakery_lock_normal.c | 250 + .../lib/locks/exclusive/aarch32/spinlock.S | 43 + .../lib/locks/exclusive/aarch64/spinlock.S | 75 + arm-trusted-firmware/lib/mpmm/mpmm.c | 86 + arm-trusted-firmware/lib/mpmm/mpmm.mk | 29 + arm-trusted-firmware/lib/optee/optee_utils.c | 234 + arm-trusted-firmware/lib/pmf/pmf_main.c | 256 + arm-trusted-firmware/lib/pmf/pmf_smc.c | 63 + .../lib/psci/aarch32/psci_helpers.S | 148 + .../lib/psci/aarch64/psci_helpers.S | 130 + arm-trusted-firmware/lib/psci/psci_common.c | 1027 +++ arm-trusted-firmware/lib/psci/psci_lib.mk | 35 + arm-trusted-firmware/lib/psci/psci_main.c | 545 ++ .../lib/psci/psci_mem_protect.c | 41 + arm-trusted-firmware/lib/psci/psci_off.c | 181 + arm-trusted-firmware/lib/psci/psci_on.c | 233 + arm-trusted-firmware/lib/psci/psci_private.h | 345 + arm-trusted-firmware/lib/psci/psci_setup.c | 315 + arm-trusted-firmware/lib/psci/psci_stat.c | 250 + arm-trusted-firmware/lib/psci/psci_suspend.c | 335 + .../lib/psci/psci_system_off.c | 85 + arm-trusted-firmware/lib/romlib/Makefile | 98 + .../lib/romlib/gen_combined_bl1_romlib.sh | 53 + arm-trusted-firmware/lib/romlib/init.s | 36 + arm-trusted-firmware/lib/romlib/jmptbl.i | 44 + arm-trusted-firmware/lib/romlib/romlib.ld.S | 44 + .../lib/romlib/romlib_generator.py | 277 + .../romlib/templates/jmptbl_entry_function.S | 6 + .../templates/jmptbl_entry_function_bti.S | 7 + .../romlib/templates/jmptbl_entry_reserved.S | 6 + .../templates/jmptbl_entry_reserved_bti.S | 7 + .../lib/romlib/templates/jmptbl_glob_var.S | 9 + .../lib/romlib/templates/jmptbl_header.S | 8 + .../lib/romlib/templates/wrapper.S | 12 + .../lib/romlib/templates/wrapper_bti.S | 13 + .../semihosting/aarch32/semihosting_call.S | 14 + .../semihosting/aarch64/semihosting_call.S | 14 + .../lib/semihosting/semihosting.c | 233 + .../aarch32/asm_stack_protector.S | 34 + .../aarch64/asm_stack_protector.S | 34 + .../lib/stack_protector/stack_protector.c | 32 + .../lib/stack_protector/stack_protector.mk | 28 + arm-trusted-firmware/lib/utils/mem_region.c | 139 + .../lib/xlat_mpu/aarch64/enable_mpu.S | 53 + .../lib/xlat_mpu/aarch64/xlat_mpu_arch.c | 69 + .../lib/xlat_mpu/ro_xlat_mpu.mk | 14 + arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk | 19 + .../lib/xlat_mpu/xlat_mpu_context.c | 65 + .../lib/xlat_mpu/xlat_mpu_core.c | 408 + .../lib/xlat_mpu/xlat_mpu_private.h | 103 + .../lib/xlat_mpu/xlat_mpu_utils.c | 83 + .../lib/xlat_tables/aarch32/nonlpae_tables.c | 566 ++ .../lib/xlat_tables/aarch32/xlat_tables.c | 141 + .../lib/xlat_tables/aarch64/xlat_tables.c | 227 + .../lib/xlat_tables/xlat_tables_common.c | 417 + .../lib/xlat_tables/xlat_tables_private.h | 41 + .../lib/xlat_tables_v2/aarch32/enable_mmu.S | 120 + .../xlat_tables_v2/aarch32/xlat_tables_arch.c | 260 + .../lib/xlat_tables_v2/aarch64/enable_mmu.S | 97 + .../xlat_tables_v2/aarch64/xlat_tables_arch.c | 324 + .../lib/xlat_tables_v2/ro_xlat_tables.mk | 37 + .../lib/xlat_tables_v2/xlat_tables.mk | 19 + .../lib/xlat_tables_v2/xlat_tables_context.c | 270 + .../lib/xlat_tables_v2/xlat_tables_core.c | 1244 +++ .../lib/xlat_tables_v2/xlat_tables_private.h | 110 + .../lib/xlat_tables_v2/xlat_tables_utils.c | 592 ++ arm-trusted-firmware/lib/zlib/adler32.c | 186 + arm-trusted-firmware/lib/zlib/crc32.c | 442 + arm-trusted-firmware/lib/zlib/crc32.h | 441 + arm-trusted-firmware/lib/zlib/inffast.c | 323 + arm-trusted-firmware/lib/zlib/inffast.h | 11 + arm-trusted-firmware/lib/zlib/inffixed.h | 94 + arm-trusted-firmware/lib/zlib/inflate.c | 1561 ++++ arm-trusted-firmware/lib/zlib/inflate.h | 125 + arm-trusted-firmware/lib/zlib/inftrees.c | 304 + arm-trusted-firmware/lib/zlib/inftrees.h | 62 + arm-trusted-firmware/lib/zlib/tf_gunzip.c | 115 + arm-trusted-firmware/lib/zlib/zconf.h | 534 ++ arm-trusted-firmware/lib/zlib/zlib.h | 1912 +++++ arm-trusted-firmware/lib/zlib/zlib.mk | 25 + arm-trusted-firmware/lib/zlib/zutil.c | 325 + arm-trusted-firmware/lib/zlib/zutil.h | 271 + arm-trusted-firmware/license.rst | 1 + arm-trusted-firmware/licenses/LICENSE.MIT | 21 + .../make_helpers/armv7-a-cpus.mk | 58 + .../make_helpers/build_env.mk | 72 + .../make_helpers/build_macros.mk | 614 ++ arm-trusted-firmware/make_helpers/cygwin.mk | 19 + arm-trusted-firmware/make_helpers/defaults.mk | 418 + arm-trusted-firmware/make_helpers/msys.mk | 20 + .../make_helpers/plat_helpers.mk | 38 + .../make_helpers/tbbr/tbbr_tools.mk | 115 + arm-trusted-firmware/make_helpers/unix.mk | 60 + arm-trusted-firmware/make_helpers/windows.mk | 90 + arm-trusted-firmware/package-lock.json | 7330 +++++++++++++++++ arm-trusted-firmware/package.json | 23 + .../plat/allwinner/common/allwinner-common.mk | 96 + .../plat/allwinner/common/arisc_off.S | 115 + .../common/include/mentor_i2c_plat.h | 28 + .../allwinner/common/include/plat_macros.S | 27 + .../allwinner/common/include/platform_def.h | 83 + .../plat/allwinner/common/include/sunxi_def.h | 23 + .../allwinner/common/include/sunxi_private.h | 52 + .../plat/allwinner/common/plat_helpers.S | 49 + .../plat/allwinner/common/sunxi_bl31_setup.c | 199 + .../plat/allwinner/common/sunxi_common.c | 159 + .../plat/allwinner/common/sunxi_cpu_ops.c | 108 + .../plat/allwinner/common/sunxi_native_pm.c | 81 + .../plat/allwinner/common/sunxi_pm.c | 49 + .../plat/allwinner/common/sunxi_scpi_pm.c | 222 + .../plat/allwinner/common/sunxi_security.c | 40 + .../plat/allwinner/common/sunxi_topology.c | 39 + .../sun50i_a64/include/core_off_arisc.h | 39 + .../allwinner/sun50i_a64/include/sunxi_ccu.h | 14 + .../sun50i_a64/include/sunxi_cpucfg.h | 39 + .../allwinner/sun50i_a64/include/sunxi_mmap.h | 74 + .../allwinner/sun50i_a64/include/sunxi_spc.h | 16 + .../plat/allwinner/sun50i_a64/platform.mk | 17 + .../plat/allwinner/sun50i_a64/sunxi_power.c | 259 + .../allwinner/sun50i_h6/include/sunxi_ccu.h | 14 + .../sun50i_h6/include/sunxi_cpucfg.h | 35 + .../allwinner/sun50i_h6/include/sunxi_mmap.h | 63 + .../allwinner/sun50i_h6/include/sunxi_spc.h | 16 + .../plat/allwinner/sun50i_h6/platform.mk | 14 + .../plat/allwinner/sun50i_h6/sunxi_power.c | 119 + .../allwinner/sun50i_h616/include/sunxi_ccu.h | 14 + .../sun50i_h616/include/sunxi_cpucfg.h | 35 + .../sun50i_h616/include/sunxi_mmap.h | 46 + .../allwinner/sun50i_h616/include/sunxi_spc.h | 16 + .../plat/allwinner/sun50i_h616/platform.mk | 24 + .../plat/allwinner/sun50i_h616/prepare_dtb.c | 43 + .../plat/allwinner/sun50i_h616/sunxi_power.c | 121 + .../allwinner/sun50i_r329/include/sunxi_ccu.h | 14 + .../sun50i_r329/include/sunxi_cpucfg.h | 31 + .../sun50i_r329/include/sunxi_mmap.h | 55 + .../allwinner/sun50i_r329/include/sunxi_spc.h | 17 + .../plat/allwinner/sun50i_r329/platform.mk | 20 + .../plat/allwinner/sun50i_r329/sunxi_power.c | 27 + .../plat/amlogic/axg/axg_bl31_setup.c | 170 + .../plat/amlogic/axg/axg_common.c | 115 + .../plat/amlogic/axg/axg_def.h | 129 + .../plat/amlogic/axg/axg_pm.c | 166 + .../plat/amlogic/axg/include/platform_def.h | 66 + .../plat/amlogic/axg/platform.mk | 95 + .../plat/amlogic/common/aarch64/aml_helpers.S | 97 + .../plat/amlogic/common/aml_console.c | 33 + .../plat/amlogic/common/aml_efuse.c | 25 + .../plat/amlogic/common/aml_mhu.c | 52 + .../plat/amlogic/common/aml_scpi.c | 234 + .../plat/amlogic/common/aml_sip_svc.c | 99 + .../plat/amlogic/common/aml_thermal.c | 27 + .../plat/amlogic/common/aml_topology.c | 53 + .../plat/amlogic/common/include/aml_private.h | 41 + .../plat/amlogic/common/include/plat_macros.S | 71 + .../plat/amlogic/g12a/g12a_bl31_setup.c | 142 + .../plat/amlogic/g12a/g12a_common.c | 125 + .../plat/amlogic/g12a/g12a_def.h | 135 + .../plat/amlogic/g12a/g12a_pm.c | 215 + .../plat/amlogic/g12a/include/platform_def.h | 63 + .../plat/amlogic/g12a/platform.mk | 91 + .../plat/amlogic/gxbb/gxbb_bl31_setup.c | 144 + .../plat/amlogic/gxbb/gxbb_common.c | 117 + .../plat/amlogic/gxbb/gxbb_def.h | 123 + .../plat/amlogic/gxbb/gxbb_pm.c | 191 + .../plat/amlogic/gxbb/include/platform_def.h | 66 + .../plat/amlogic/gxbb/platform.mk | 75 + .../plat/amlogic/gxl/gxl_bl31_setup.c | 162 + .../plat/amlogic/gxl/gxl_common.c | 117 + .../plat/amlogic/gxl/gxl_def.h | 133 + .../plat/amlogic/gxl/gxl_pm.c | 214 + .../plat/amlogic/gxl/include/platform_def.h | 63 + .../plat/amlogic/gxl/platform.mk | 91 + .../plat/arm/board/a5ds/a5ds_bl1_setup.c | 20 + .../plat/arm/board/a5ds/a5ds_bl2_setup.c | 18 + .../plat/arm/board/a5ds/a5ds_common.c | 56 + .../plat/arm/board/a5ds/a5ds_err.c | 17 + .../plat/arm/board/a5ds/a5ds_pm.c | 75 + .../plat/arm/board/a5ds/a5ds_private.h | 15 + .../plat/arm/board/a5ds/a5ds_security.c | 17 + .../plat/arm/board/a5ds/a5ds_topology.c | 53 + .../arm/board/a5ds/aarch32/a5ds_helpers.S | 126 + .../arm/board/a5ds/fdts/a5ds_fw_config.dts | 27 + .../arm/board/a5ds/fdts/a5ds_tb_fw_config.dts | 16 + .../arm/board/a5ds/include/platform_def.h | 376 + .../plat/arm/board/a5ds/platform.mk | 111 + .../arm/board/a5ds/sp_min/a5ds_sp_min_setup.c | 27 + .../plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk | 22 + .../arm/board/arm_fpga/aarch64/fpga_helpers.S | 167 + .../plat/arm/board/arm_fpga/build_axf.ld.S | 53 + .../plat/arm/board/arm_fpga/fpga_bl31_setup.c | 402 + .../plat/arm/board/arm_fpga/fpga_console.c | 38 + .../plat/arm/board/arm_fpga/fpga_def.h | 39 + .../plat/arm/board/arm_fpga/fpga_gicv3.c | 162 + .../plat/arm/board/arm_fpga/fpga_pm.c | 103 + .../plat/arm/board/arm_fpga/fpga_private.h | 34 + .../plat/arm/board/arm_fpga/fpga_topology.c | 77 + .../arm/board/arm_fpga/include/plat_macros.S | 13 + .../arm/board/arm_fpga/include/platform_def.h | 88 + .../arm/board/arm_fpga/kernel_trampoline.S | 35 + .../plat/arm/board/arm_fpga/platform.mk | 130 + .../plat/arm/board/arm_fpga/rom_trampoline.S | 24 + .../board/common/aarch32/board_arm_helpers.S | 32 + .../board/common/aarch64/board_arm_helpers.S | 34 + .../arm/board/common/board_arm_trusted_boot.c | 227 + .../plat/arm/board/common/board_common.mk | 91 + .../plat/arm/board/common/protpk/README | 14 + .../arm/board/common/protpk/arm_dev_protpk.S | 18 + .../common/protpk/arm_protpk_rsa_sha256.bin | 1 + .../board/common/protpk/arm_protprivk_rsa.pem | 27 + .../arm/board/common/rotpk/arm_dev_rotpk.S | 33 + .../board/common/rotpk/arm_rotpk_ecdsa.der | Bin 0 -> 91 bytes .../common/rotpk/arm_rotpk_ecdsa_sha256.bin | 1 + .../arm/board/common/rotpk/arm_rotpk_rsa.der | Bin 0 -> 294 bytes .../common/rotpk/arm_rotpk_rsa_sha256.bin | 1 + .../board/common/rotpk/arm_rotprivk_ecdsa.pem | 5 + .../board/common/rotpk/arm_rotprivk_rsa.pem | 28 + .../common/corstone1000_bl2_mem_params_desc.c | 85 + .../corstone1000/common/corstone1000_err.c | 17 + .../common/corstone1000_helpers.S | 67 + .../corstone1000/common/corstone1000_plat.c | 125 + .../corstone1000/common/corstone1000_pm.c | 37 + .../common/corstone1000_security.c | 16 + .../common/corstone1000_stack_protector.c | 35 + .../common/corstone1000_topology.c | 43 + .../common/corstone1000_trusted_boot.c | 53 + .../fdts/corstone1000_spmc_manifest.dts | 30 + .../common/include/platform_def.h | 436 + .../board/corstone1000/include/plat_macros.S | 22 + .../plat/arm/board/corstone1000/platform.mk | 83 + .../corstone700/common/corstone700_helpers.S | 100 + .../corstone700/common/corstone700_plat.c | 39 + .../board/corstone700/common/corstone700_pm.c | 22 + .../corstone700/common/corstone700_security.c | 16 + .../common/corstone700_stack_protector.c | 35 + .../corstone700/common/corstone700_topology.c | 43 + .../corstone700/common/drivers/mhu/mhu.c | 117 + .../corstone700/common/drivers/mhu/mhu.h | 37 + .../corstone700/common/include/platform_def.h | 282 + .../plat/arm/board/corstone700/platform.mk | 63 + .../sp_min/corstone700_sp_min_setup.c | 13 + .../corstone700/sp_min/sp_min-corstone700.mk | 24 + .../plat/arm/board/fvp/aarch32/fvp_helpers.S | 143 + .../plat/arm/board/fvp/aarch64/fvp_helpers.S | 177 + .../plat/arm/board/fvp/aarch64/fvp_ras.c | 16 + .../board/fvp/fconf/fconf_hw_config_getter.c | 299 + .../board/fvp/fconf/fconf_nt_config_getter.c | 64 + .../plat/arm/board/fvp/fdts/event_log.dtsi | 12 + .../plat/arm/board/fvp/fdts/fvp_fw_config.dts | 54 + .../arm/board/fvp/fdts/fvp_nt_fw_config.dts | 19 + .../arm/board/fvp/fdts/fvp_soc_fw_config.dts | 11 + .../arm/board/fvp/fdts/fvp_spmc_manifest.dts | 85 + .../fvp/fdts/fvp_spmc_optee_sp_manifest.dts | 64 + .../arm/board/fvp/fdts/fvp_tb_fw_config.dts | 124 + .../arm/board/fvp/fdts/fvp_tsp_fw_config.dts | 13 + .../arm/board/fvp/fdts/optee_sp_manifest.dts | 44 + .../arm/board/fvp/fvp_bl1_measured_boot.c | 45 + .../plat/arm/board/fvp/fvp_bl1_setup.c | 89 + .../plat/arm/board/fvp/fvp_bl2_el3_setup.c | 30 + .../arm/board/fvp/fvp_bl2_measured_boot.c | 187 + .../plat/arm/board/fvp/fvp_bl2_setup.c | 72 + .../plat/arm/board/fvp/fvp_bl2u_setup.c | 22 + .../plat/arm/board/fvp/fvp_bl31_setup.c | 108 + .../plat/arm/board/fvp/fvp_common.c | 517 ++ .../arm/board/fvp/fvp_common_measured_boot.c | 35 + .../plat/arm/board/fvp/fvp_console.c | 54 + .../plat/arm/board/fvp/fvp_def.h | 181 + .../plat/arm/board/fvp/fvp_err.c | 31 + .../plat/arm/board/fvp/fvp_gicv3.c | 173 + .../plat/arm/board/fvp/fvp_io_storage.c | 174 + .../arm/board/fvp/fvp_plat_attest_token.c | 317 + .../plat/arm/board/fvp/fvp_pm.c | 467 ++ .../plat/arm/board/fvp/fvp_private.h | 24 + .../plat/arm/board/fvp/fvp_realm_attest_key.c | 35 + .../plat/arm/board/fvp/fvp_security.c | 42 + .../plat/arm/board/fvp/fvp_stack_protector.c | 24 + .../plat/arm/board/fvp/fvp_topology.c | 123 + .../plat/arm/board/fvp/fvp_trusted_boot.c | 71 + .../fvp/include/fconf_hw_config_getter.h | 48 + .../fvp/include/fconf_nt_config_getter.h | 27 + .../arm/board/fvp/include/fvp_critical_data.h | 19 + .../plat/arm/board/fvp/include/plat.ld.S | 15 + .../plat/arm/board/fvp/include/plat_macros.S | 42 + .../plat/arm/board/fvp/include/platform_def.h | 363 + .../plat/arm/board/fvp/jmptbl.i | 61 + .../plat/arm/board/fvp/platform.mk | 401 + .../arm/board/fvp/sp_min/fvp_sp_min_setup.c | 60 + .../plat/arm/board/fvp/sp_min/sp_min-fvp.mk | 38 + .../plat/arm/board/fvp/trp/trp-fvp.mk | 12 + .../plat/arm/board/fvp/tsp/fvp_tsp_setup.c | 17 + .../plat/arm/board/fvp/tsp/tsp-fvp.mk | 14 + .../arm/board/fvp_r/fvp_r_bl1_arch_setup.c | 35 + .../arm/board/fvp_r/fvp_r_bl1_entrypoint.S | 93 + .../arm/board/fvp_r/fvp_r_bl1_exceptions.S | 120 + .../plat/arm/board/fvp_r/fvp_r_bl1_main.c | 268 + .../plat/arm/board/fvp_r/fvp_r_bl1_setup.c | 247 + .../plat/arm/board/fvp_r/fvp_r_common.c | 289 + .../plat/arm/board/fvp_r/fvp_r_context_mgmt.c | 53 + .../plat/arm/board/fvp_r/fvp_r_debug.S | 47 + .../plat/arm/board/fvp_r/fvp_r_def.h | 103 + .../plat/arm/board/fvp_r/fvp_r_err.c | 48 + .../plat/arm/board/fvp_r/fvp_r_helpers.S | 128 + .../plat/arm/board/fvp_r/fvp_r_io_storage.c | 105 + .../plat/arm/board/fvp_r/fvp_r_misc_helpers.S | 32 + .../plat/arm/board/fvp_r/fvp_r_private.h | 23 + .../arm/board/fvp_r/fvp_r_stack_protector.c | 24 + .../plat/arm/board/fvp_r/fvp_r_trusted_boot.c | 73 + .../board/fvp_r/include/fvp_r_arch_helpers.h | 28 + .../arm/board/fvp_r/include/platform_def.h | 268 + .../plat/arm/board/fvp_r/platform.mk | 99 + .../arm/board/fvp_ve/aarch32/fvp_ve_helpers.S | 62 + .../board/fvp_ve/fdts/fvp_ve_fw_config.dts | 27 + .../board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts | 16 + .../plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c | 33 + .../plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c | 41 + .../plat/arm/board/fvp_ve/fvp_ve_common.c | 63 + .../plat/arm/board/fvp_ve/fvp_ve_def.h | 84 + .../plat/arm/board/fvp_ve/fvp_ve_err.c | 17 + .../plat/arm/board/fvp_ve/fvp_ve_pm.c | 25 + .../plat/arm/board/fvp_ve/fvp_ve_private.h | 18 + .../plat/arm/board/fvp_ve/fvp_ve_security.c | 22 + .../plat/arm/board/fvp_ve/fvp_ve_topology.c | 37 + .../arm/board/fvp_ve/include/platform_def.h | 361 + .../plat/arm/board/fvp_ve/platform.mk | 139 + .../board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c | 15 + .../arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk | 22 + .../arm/board/juno/aarch32/juno_helpers.S | 176 + .../arm/board/juno/aarch64/juno_helpers.S | 275 + .../arm/board/juno/fdts/juno_fw_config.dts | 27 + .../arm/board/juno/fdts/juno_tb_fw_config.dts | 26 + .../plat/arm/board/juno/include/plat_macros.S | 24 + .../arm/board/juno/include/platform_def.h | 319 + .../plat/arm/board/juno/jmptbl.i | 60 + .../plat/arm/board/juno/juno_bl1_setup.c | 122 + .../plat/arm/board/juno/juno_bl2_setup.c | 73 + .../plat/arm/board/juno/juno_bl31_setup.c | 60 + .../plat/arm/board/juno/juno_common.c | 134 + .../plat/arm/board/juno/juno_def.h | 99 + .../plat/arm/board/juno/juno_err.c | 27 + .../plat/arm/board/juno/juno_pm.c | 17 + .../plat/arm/board/juno/juno_security.c | 166 + .../arm/board/juno/juno_stack_protector.c | 27 + .../plat/arm/board/juno/juno_topology.c | 78 + .../plat/arm/board/juno/juno_trng.c | 108 + .../plat/arm/board/juno/juno_trusted_boot.c | 126 + .../plat/arm/board/juno/juno_tzmp1_def.h | 83 + .../plat/arm/board/juno/platform.mk | 201 + .../plat/arm/board/juno/sp_min/sp_min-juno.mk | 22 + .../plat/arm/board/juno/tsp/tsp-juno.mk | 12 + .../board/morello/aarch64/morello_helper.S | 55 + .../board/morello/fdts/morello_fw_config.dts | 26 + .../morello/fdts/morello_nt_fw_config.dts | 26 + .../morello/fdts/morello_tb_fw_config.dts | 27 + .../arm/board/morello/include/plat_macros.S | 25 + .../arm/board/morello/include/platform_def.h | 194 + .../arm/board/morello/morello_bl1_setup.c | 19 + .../arm/board/morello/morello_bl2_setup.c | 27 + .../arm/board/morello/morello_bl31_setup.c | 243 + .../plat/arm/board/morello/morello_def.h | 92 + .../plat/arm/board/morello/morello_err.c | 17 + .../arm/board/morello/morello_image_load.c | 185 + .../arm/board/morello/morello_interconnect.c | 33 + .../plat/arm/board/morello/morello_plat.c | 59 + .../plat/arm/board/morello/morello_security.c | 12 + .../plat/arm/board/morello/morello_topology.c | 60 + .../arm/board/morello/morello_trusted_boot.c | 54 + .../plat/arm/board/morello/platform.mk | 108 + .../arm/board/n1sdp/aarch64/n1sdp_helper.S | 78 + .../arm/board/n1sdp/include/plat_macros.S | 24 + .../arm/board/n1sdp/include/platform_def.h | 149 + .../plat/arm/board/n1sdp/n1sdp_bl31_setup.c | 241 + .../plat/arm/board/n1sdp/n1sdp_def.h | 60 + .../plat/arm/board/n1sdp/n1sdp_interconnect.c | 33 + .../plat/arm/board/n1sdp/n1sdp_plat.c | 42 + .../plat/arm/board/n1sdp/n1sdp_security.c | 12 + .../plat/arm/board/n1sdp/n1sdp_topology.c | 59 + .../plat/arm/board/n1sdp/platform.mk | 76 + .../rde1edge/fdts/rde1edge_fw_config.dts | 27 + .../rde1edge/fdts/rde1edge_nt_fw_config.dts | 23 + .../rde1edge/fdts/rde1edge_tb_fw_config.dts | 28 + .../arm/board/rde1edge/include/platform_def.h | 45 + .../plat/arm/board/rde1edge/platform.mk | 66 + .../plat/arm/board/rde1edge/rde1edge_err.c | 17 + .../plat/arm/board/rde1edge/rde1edge_plat.c | 29 + .../arm/board/rde1edge/rde1edge_security.c | 36 + .../arm/board/rde1edge/rde1edge_topology.c | 36 + .../board/rde1edge/rde1edge_trusted_boot.c | 26 + .../rdn1edge/fdts/rdn1edge_fw_config.dts | 27 + .../rdn1edge/fdts/rdn1edge_nt_fw_config.dts | 22 + .../rdn1edge/fdts/rdn1edge_tb_fw_config.dts | 27 + .../arm/board/rdn1edge/include/platform_def.h | 49 + .../plat/arm/board/rdn1edge/platform.mk | 73 + .../plat/arm/board/rdn1edge/rdn1edge_err.c | 17 + .../plat/arm/board/rdn1edge/rdn1edge_plat.c | 97 + .../arm/board/rdn1edge/rdn1edge_security.c | 36 + .../arm/board/rdn1edge/rdn1edge_topology.c | 54 + .../board/rdn1edge/rdn1edge_trusted_boot.c | 26 + .../arm/board/rdn2/fdts/rdn2_fw_config.dts | 27 + .../arm/board/rdn2/fdts/rdn2_nt_fw_config.dts | 22 + .../arm/board/rdn2/fdts/rdn2_tb_fw_config.dts | 28 + .../arm/board/rdn2/include/platform_def.h | 98 + .../plat/arm/board/rdn2/platform.mk | 86 + .../plat/arm/board/rdn2/rdn2_err.c | 17 + .../plat/arm/board/rdn2/rdn2_plat.c | 138 + .../plat/arm/board/rdn2/rdn2_security.c | 63 + .../plat/arm/board/rdn2/rdn2_topology.c | 97 + .../plat/arm/board/rdn2/rdn2_trusted_boot.c | 26 + .../arm/board/rdv1/fdts/rdv1_fw_config.dts | 27 + .../arm/board/rdv1/fdts/rdv1_nt_fw_config.dts | 22 + .../arm/board/rdv1/fdts/rdv1_tb_fw_config.dts | 28 + .../arm/board/rdv1/include/platform_def.h | 65 + .../plat/arm/board/rdv1/platform.mk | 65 + .../plat/arm/board/rdv1/rdv1_err.c | 17 + .../plat/arm/board/rdv1/rdv1_plat.c | 30 + .../plat/arm/board/rdv1/rdv1_security.c | 22 + .../plat/arm/board/rdv1/rdv1_topology.c | 62 + .../plat/arm/board/rdv1/rdv1_trusted_boot.c | 26 + .../board/rdv1mc/fdts/rdv1mc_fw_config.dts | 27 + .../board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts | 22 + .../board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts | 28 + .../arm/board/rdv1mc/include/platform_def.h | 60 + .../plat/arm/board/rdv1mc/platform.mk | 76 + .../plat/arm/board/rdv1mc/rdv1mc_err.c | 17 + .../plat/arm/board/rdv1mc/rdv1mc_plat.c | 131 + .../plat/arm/board/rdv1mc/rdv1mc_security.c | 64 + .../plat/arm/board/rdv1mc/rdv1mc_topology.c | 78 + .../arm/board/rdv1mc/rdv1mc_trusted_boot.c | 26 + .../board/sgi575/fdts/sgi575_fw_config.dts | 27 + .../board/sgi575/fdts/sgi575_nt_fw_config.dts | 22 + .../board/sgi575/fdts/sgi575_tb_fw_config.dts | 28 + .../arm/board/sgi575/include/platform_def.h | 46 + .../plat/arm/board/sgi575/platform.mk | 65 + .../plat/arm/board/sgi575/sgi575_err.c | 17 + .../plat/arm/board/sgi575/sgi575_plat.c | 30 + .../plat/arm/board/sgi575/sgi575_security.c | 36 + .../plat/arm/board/sgi575/sgi575_topology.c | 32 + .../arm/board/sgi575/sgi575_trusted_boot.c | 26 + .../board/sgm775/fdts/sgm775_fw_config.dts | 21 + .../board/sgm775/fdts/sgm775_tb_fw_config.dts | 28 + .../arm/board/sgm775/include/platform_def.h | 29 + .../plat/arm/board/sgm775/platform.mk | 39 + .../plat/arm/board/sgm775/sgm775_err.c | 17 + .../arm/board/sgm775/sgm775_trusted_boot.c | 26 + .../plat/arm/board/sgm775/tsp/tsp-sgm775.mk | 7 + .../plat/arm/board/tc/fdts/tc_fw_config.dts | 33 + .../arm/board/tc/fdts/tc_spmc_manifest.dts | 125 + .../tc/fdts/tc_spmc_optee_sp_manifest.dts | 124 + .../arm/board/tc/fdts/tc_tb_fw_config.dts | 76 + .../plat/arm/board/tc/include/plat_macros.S | 24 + .../plat/arm/board/tc/include/platform_def.h | 277 + .../plat/arm/board/tc/include/tc_helpers.S | 61 + .../plat/arm/board/tc/include/tc_plat.h | 12 + .../plat/arm/board/tc/platform.mk | 161 + .../plat/arm/board/tc/tc_bl2_setup.c | 47 + .../plat/arm/board/tc/tc_bl31_setup.c | 73 + .../plat/arm/board/tc/tc_err.c | 17 + .../plat/arm/board/tc/tc_interconnect.c | 35 + .../plat/arm/board/tc/tc_plat.c | 156 + .../plat/arm/board/tc/tc_security.c | 23 + .../plat/arm/board/tc/tc_topology.c | 58 + .../plat/arm/board/tc/tc_trusted_boot.c | 26 + .../common/aarch32/arm_bl2_mem_params_desc.c | 90 + .../plat/arm/common/aarch32/arm_helpers.S | 77 + .../common/aarch64/arm_bl2_mem_params_desc.c | 223 + .../plat/arm/common/aarch64/arm_helpers.S | 136 + .../plat/arm/common/aarch64/arm_pauth.c | 28 + .../plat/arm/common/aarch64/arm_sdei.c | 66 + .../common/aarch64/execution_state_switch.c | 180 + .../plat/arm/common/arm_bl1_fwu.c | 102 + .../plat/arm/common/arm_bl1_setup.c | 257 + .../plat/arm/common/arm_bl2_el3_setup.c | 100 + .../plat/arm/common/arm_bl2_setup.c | 322 + .../plat/arm/common/arm_bl2u_setup.c | 97 + .../plat/arm/common/arm_bl31_setup.c | 427 + .../plat/arm/common/arm_cci.c | 50 + .../plat/arm/common/arm_ccn.c | 57 + .../plat/arm/common/arm_common.c | 239 + .../plat/arm/common/arm_common.mk | 429 + .../plat/arm/common/arm_console.c | 71 + .../plat/arm/common/arm_dyn_cfg.c | 205 + .../plat/arm/common/arm_dyn_cfg_helpers.c | 368 + .../plat/arm/common/arm_err.c | 15 + .../plat/arm/common/arm_gicv2.c | 114 + .../plat/arm/common/arm_gicv3.c | 246 + .../plat/arm/common/arm_image_load.c | 141 + .../plat/arm/common/arm_io_storage.c | 250 + .../arm/common/arm_nor_psci_mem_protect.c | 138 + arm-trusted-firmware/plat/arm/common/arm_pm.c | 210 + .../plat/arm/common/arm_sip_svc.c | 143 + .../plat/arm/common/arm_topology.c | 58 + .../plat/arm/common/arm_tzc400.c | 79 + .../plat/arm/common/arm_tzc_dmc500.c | 79 + .../plat/arm/common/fconf/arm_fconf_io.c | 360 + .../plat/arm/common/fconf/arm_fconf_sp.c | 165 + .../arm/common/fconf/fconf_ethosn_getter.c | 120 + .../arm/common/fconf/fconf_nv_cntr_getter.c | 62 + .../plat/arm/common/fconf/fconf_sdei_getter.c | 103 + .../arm/common/fconf/fconf_sec_intr_config.c | 131 + .../plat/arm/common/sp_min/arm_sp_min.mk | 20 + .../plat/arm/common/sp_min/arm_sp_min_setup.c | 241 + .../plat/arm/common/trp/arm_trp.mk | 10 + .../plat/arm/common/trp/arm_trp_setup.c | 40 + .../plat/arm/common/tsp/arm_tsp.mk | 10 + .../plat/arm/common/tsp/arm_tsp_setup.c | 86 + .../plat/arm/css/common/aarch32/css_helpers.S | 102 + .../plat/arm/css/common/aarch64/css_helpers.S | 120 + .../plat/arm/css/common/css_bl1_setup.c | 22 + .../plat/arm/css/common/css_bl2_setup.c | 86 + .../plat/arm/css/common/css_bl2u_setup.c | 56 + .../plat/arm/css/common/css_common.mk | 90 + .../plat/arm/css/common/css_pm.c | 362 + .../plat/arm/css/common/css_topology.c | 48 + .../plat/arm/css/common/sp_min/css_sp_min.mk | 21 + .../plat/arm/css/sgi/aarch64/sgi_helper.S | 106 + .../plat/arm/css/sgi/include/plat_macros.S | 24 + .../css/sgi/include/sgi_base_platform_def.h | 261 + .../css/sgi/include/sgi_dmc620_tzc_regions.h | 36 + .../plat/arm/css/sgi/include/sgi_plat.h | 13 + .../plat/arm/css/sgi/include/sgi_ras.h | 21 + .../plat/arm/css/sgi/include/sgi_sdei.h | 25 + .../arm/css/sgi/include/sgi_soc_css_def_v2.h | 222 + .../css/sgi/include/sgi_soc_platform_def.h | 33 + .../css/sgi/include/sgi_soc_platform_def_v2.h | 31 + .../plat/arm/css/sgi/include/sgi_variant.h | 49 + .../plat/arm/css/sgi/sgi-common.mk | 84 + .../plat/arm/css/sgi/sgi_bl31_setup.c | 127 + .../plat/arm/css/sgi/sgi_image_load.c | 90 + .../plat/arm/css/sgi/sgi_interconnect.c | 36 + .../plat/arm/css/sgi/sgi_plat.c | 175 + .../plat/arm/css/sgi/sgi_plat_v2.c | 174 + .../plat/arm/css/sgi/sgi_ras.c | 194 + .../plat/arm/css/sgi/sgi_topology.c | 29 + .../arm/css/sgm/aarch64/css_sgm_helpers.S | 82 + .../arm/css/sgm/fdts/sgm_tb_fw_config.dts | 27 + .../plat/arm/css/sgm/include/plat_macros.S | 24 + .../css/sgm/include/sgm_base_platform_def.h | 242 + .../arm/css/sgm/include/sgm_plat_config.h | 43 + .../plat/arm/css/sgm/include/sgm_variant.h | 17 + .../plat/arm/css/sgm/sgm-common.mk | 76 + .../plat/arm/css/sgm/sgm_bl1_setup.c | 45 + .../plat/arm/css/sgm/sgm_bl31_setup.c | 55 + .../plat/arm/css/sgm/sgm_interconnect.c | 34 + .../plat/arm/css/sgm/sgm_mmap_config.c | 89 + .../plat/arm/css/sgm/sgm_plat_config.c | 80 + .../plat/arm/css/sgm/sgm_security.c | 65 + .../plat/arm/css/sgm/sgm_topology.c | 33 + .../plat/arm/css/sgm/tsp/sgm_tsp_setup.c | 17 + .../plat/arm/css/sgm/tsp/tsp-sgm.mk | 11 + .../plat/arm/soc/common/soc_css.mk | 15 + .../plat/arm/soc/common/soc_css_security.c | 73 + .../plat/brcm/board/common/bcm_console.c | 65 + .../plat/brcm/board/common/bcm_elog.c | 268 + .../plat/brcm/board/common/bcm_elog_ddr.c | 133 + .../plat/brcm/board/common/bcm_elog_ddr.h | 107 + .../board/common/board_arm_trusted_boot.c | 625 ++ .../plat/brcm/board/common/board_common.c | 74 + .../plat/brcm/board/common/board_common.mk | 294 + .../plat/brcm/board/common/brcm_mbedtls.c | 12 + .../plat/brcm/board/common/chip_id.h | 37 + .../plat/brcm/board/common/cmn_plat_def.h | 84 + .../plat/brcm/board/common/cmn_plat_util.h | 43 + .../plat/brcm/board/common/cmn_sec.c | 49 + .../plat/brcm/board/common/cmn_sec.h | 19 + .../plat/brcm/board/common/err.c | 37 + .../plat/brcm/board/common/plat_setup.c | 27 + .../plat/brcm/board/common/platform_common.c | 94 + .../plat/brcm/board/common/sbl_util.c | 40 + .../plat/brcm/board/common/sbl_util.h | 19 + .../plat/brcm/board/common/timer_sync.c | 71 + .../board/stingray/aarch64/plat_helpers.S | 263 + .../brcm/board/stingray/bcm958742t-ns3.mk | 22 + .../plat/brcm/board/stingray/bcm958742t.mk | 19 + .../driver/ddr/soc/include/board_family.h | 33 + .../driver/ext_sram_init/ext_sram_init.c | 302 + .../driver/ext_sram_init/ext_sram_init.h | 11 + .../board/stingray/driver/ihost_pll_config.c | 287 + .../brcm/board/stingray/driver/plat_emmc.c | 109 + .../plat/brcm/board/stingray/driver/sr_usb.h | 135 + .../plat/brcm/board/stingray/driver/swreg.c | 375 + .../plat/brcm/board/stingray/driver/usb.c | 296 + .../plat/brcm/board/stingray/driver/usb_phy.c | 601 ++ .../brcm/board/stingray/include/bl33_info.h | 38 + .../brcm/board/stingray/include/board_info.h | 38 + .../brcm/board/stingray/include/crmu_def.h | 227 + .../brcm/board/stingray/include/ddr_init.h | 39 + .../plat/brcm/board/stingray/include/fsx.h | 37 + .../brcm/board/stingray/include/ihost_pm.h | 19 + .../plat/brcm/board/stingray/include/iommu.h | 19 + .../plat/brcm/board/stingray/include/ncsi.h | 32 + .../plat/brcm/board/stingray/include/paxb.h | 74 + .../plat/brcm/board/stingray/include/paxc.h | 23 + .../brcm/board/stingray/include/plat_macros.S | 52 + .../board/stingray/include/platform_def.h | 268 + .../board/stingray/include/platform_sotp.h | 36 + .../board/stingray/include/platform_usb.h | 19 + .../brcm/board/stingray/include/scp_cmd.h | 25 + .../brcm/board/stingray/include/scp_utils.h | 34 + .../plat/brcm/board/stingray/include/sdio.h | 247 + .../plat/brcm/board/stingray/include/sr_def.h | 624 ++ .../brcm/board/stingray/include/sr_utils.h | 42 + .../plat/brcm/board/stingray/include/swreg.h | 36 + .../brcm/board/stingray/include/timer_sync.h | 12 + .../brcm/board/stingray/include/usb_phy.h | 244 + .../plat/brcm/board/stingray/platform.mk | 304 + .../plat/brcm/board/stingray/src/bl2_setup.c | 743 ++ .../plat/brcm/board/stingray/src/bl31_setup.c | 1071 +++ .../brcm/board/stingray/src/brcm_pm_ops.c | 408 + .../plat/brcm/board/stingray/src/fsx.c | 477 ++ .../plat/brcm/board/stingray/src/ihost_pm.c | 355 + .../plat/brcm/board/stingray/src/iommu.c | 536 ++ .../plat/brcm/board/stingray/src/ncsi.c | 54 + .../plat/brcm/board/stingray/src/paxb.c | 911 ++ .../plat/brcm/board/stingray/src/paxc.c | 267 + .../plat/brcm/board/stingray/src/pm.c | 131 + .../plat/brcm/board/stingray/src/scp_cmd.c | 60 + .../plat/brcm/board/stingray/src/scp_utils.c | 227 + .../plat/brcm/board/stingray/src/sdio.c | 144 + .../brcm/board/stingray/src/sr_paxb_phy.c | 806 ++ .../plat/brcm/board/stingray/src/topology.c | 52 + .../plat/brcm/board/stingray/src/tz_sec.c | 153 + .../brcm/common/brcm_bl2_mem_params_desc.c | 106 + .../plat/brcm/common/brcm_bl2_setup.c | 202 + .../plat/brcm/common/brcm_bl31_setup.c | 291 + .../plat/brcm/common/brcm_ccn.c | 36 + .../plat/brcm/common/brcm_common.c | 59 + .../plat/brcm/common/brcm_gicv3.c | 91 + .../plat/brcm/common/brcm_image_load.c | 41 + .../plat/brcm/common/brcm_io_storage.c | 408 + .../plat/brcm/common/brcm_mhu.c | 131 + .../plat/brcm/common/brcm_mhu.h | 19 + .../plat/brcm/common/brcm_scpi.c | 252 + .../plat/brcm/common/brcm_scpi.h | 107 + .../common/aarch32/crash_console_helpers.S | 68 + .../plat/common/aarch32/plat_common.c | 21 + .../plat/common/aarch32/plat_sp_min_common.c | 25 + .../plat/common/aarch32/platform_helpers.S | 69 + .../plat/common/aarch32/platform_mp_stack.S | 47 + .../plat/common/aarch32/platform_up_stack.S | 47 + .../common/aarch64/crash_console_helpers.S | 187 + .../plat/common/aarch64/plat_common.c | 120 + .../plat/common/aarch64/plat_ehf.c | 37 + .../plat/common/aarch64/platform_helpers.S | 122 + .../plat/common/aarch64/platform_mp_stack.S | 61 + .../plat/common/aarch64/platform_up_stack.S | 50 + .../plat/common/plat_bl1_common.c | 117 + .../plat/common/plat_bl_common.c | 137 + arm-trusted-firmware/plat/common/plat_gicv2.c | 301 + arm-trusted-firmware/plat/common/plat_gicv3.c | 342 + .../plat/common/plat_log_common.c | 29 + .../plat/common/plat_psci_common.c | 167 + .../plat/common/plat_spmd_manifest.c | 214 + .../plat/common/tbbr/plat_tbbr.c | 52 + arm-trusted-firmware/plat/common/ubsan.c | 220 + .../hisilicon/hikey/aarch64/hikey_common.c | 128 + .../hisilicon/hikey/aarch64/hikey_helpers.S | 159 + .../plat/hisilicon/hikey/hikey_bl1_setup.c | 165 + .../hikey/hikey_bl2_mem_params_desc.c | 165 + .../plat/hisilicon/hikey/hikey_bl2_setup.c | 329 + .../plat/hisilicon/hikey/hikey_bl31_setup.c | 155 + .../plat/hisilicon/hikey/hikey_bl_common.c | 390 + .../plat/hisilicon/hikey/hikey_ddr.c | 1451 ++++ .../plat/hisilicon/hikey/hikey_image_load.c | 34 + .../plat/hisilicon/hikey/hikey_io_storage.c | 315 + .../plat/hisilicon/hikey/hikey_pm.c | 288 + .../plat/hisilicon/hikey/hikey_private.h | 77 + .../plat/hisilicon/hikey/hikey_rotpk.S | 16 + .../plat/hisilicon/hikey/hikey_security.c | 108 + .../plat/hisilicon/hikey/hikey_tbbr.c | 36 + .../plat/hisilicon/hikey/hikey_topology.c | 66 + .../plat/hisilicon/hikey/hisi_dvfs.c | 781 ++ .../plat/hisilicon/hikey/hisi_ipc.c | 207 + .../plat/hisilicon/hikey/hisi_mcu.c | 206 + .../plat/hisilicon/hikey/hisi_pwrc.c | 104 + .../plat/hisilicon/hikey/hisi_pwrc_sram.S | 70 + .../plat/hisilicon/hikey/hisi_sip_svc.c | 85 + .../plat/hisilicon/hikey/include/hi6220.h | 77 + .../hikey/include/hi6220_regs_acpu.h | 300 + .../hisilicon/hikey/include/hi6220_regs_ao.h | 334 + .../hikey/include/hi6220_regs_peri.h | 380 + .../hisilicon/hikey/include/hi6220_regs_pin.h | 43 + .../hikey/include/hi6220_regs_pmctrl.h | 101 + .../plat/hisilicon/hikey/include/hi6553.h | 82 + .../plat/hisilicon/hikey/include/hikey_def.h | 106 + .../hisilicon/hikey/include/hikey_layout.h | 122 + .../plat/hisilicon/hikey/include/hisi_ipc.h | 46 + .../plat/hisilicon/hikey/include/hisi_mcu.h | 16 + .../plat/hisilicon/hikey/include/hisi_pwrc.h | 22 + .../hisilicon/hikey/include/hisi_sip_svc.h | 21 + .../hisilicon/hikey/include/hisi_sram_map.h | 327 + .../hisilicon/hikey/include/plat_macros.S | 78 + .../hisilicon/hikey/include/platform_def.h | 85 + .../plat/hisilicon/hikey/platform.mk | 168 + .../hikey960/aarch64/hikey960_common.c | 124 + .../hikey960/aarch64/hikey960_helpers.S | 181 + .../hisilicon/hikey960/drivers/ipc/hisi_ipc.c | 206 + .../hikey960/drivers/pwrc/hisi_pwrc.c | 417 + .../hikey960/drivers/pwrc/hisi_pwrc.h | 57 + .../hisilicon/hikey960/hikey960_bl1_setup.c | 265 + .../hikey960/hikey960_bl2_mem_params_desc.c | 165 + .../hisilicon/hikey960/hikey960_bl2_setup.c | 325 + .../hisilicon/hikey960/hikey960_bl31_setup.c | 207 + .../hisilicon/hikey960/hikey960_bl_common.c | 480 ++ .../hisilicon/hikey960/hikey960_boardid.c | 167 + .../plat/hisilicon/hikey960/hikey960_def.h | 53 + .../hisilicon/hikey960/hikey960_image_load.c | 34 + .../hisilicon/hikey960/hikey960_io_storage.c | 311 + .../hisilicon/hikey960/hikey960_mcu_load.c | 54 + .../plat/hisilicon/hikey960/hikey960_pm.c | 337 + .../hisilicon/hikey960/hikey960_private.h | 42 + .../plat/hisilicon/hikey960/hikey960_rotpk.S | 16 + .../plat/hisilicon/hikey960/hikey960_tbbr.c | 36 + .../hisilicon/hikey960/hikey960_topology.c | 66 + .../plat/hisilicon/hikey960/include/hi3660.h | 392 + .../hisilicon/hikey960/include/hi3660_crg.h | 179 + .../hisilicon/hikey960/include/hi3660_hkadc.h | 61 + .../hikey960/include/hi3660_mem_map.h | 20 + .../hisilicon/hikey960/include/hisi_ipc.h | 24 + .../hisilicon/hikey960/include/plat_macros.S | 78 + .../hisilicon/hikey960/include/platform_def.h | 142 + .../plat/hisilicon/hikey960/platform.mk | 158 + .../poplar/aarch64/platform_common.c | 79 + .../hisilicon/poplar/aarch64/poplar_helpers.S | 87 + .../plat/hisilicon/poplar/bl1_plat_setup.c | 119 + .../poplar/bl2_plat_mem_params_desc.c | 166 + .../plat/hisilicon/poplar/bl2_plat_setup.c | 219 + .../plat/hisilicon/poplar/bl31_plat_setup.c | 137 + .../hisilicon/poplar/include/hi3798cv200.h | 105 + .../hisilicon/poplar/include/plat_macros.S | 10 + .../hisilicon/poplar/include/plat_private.h | 37 + .../hisilicon/poplar/include/platform_def.h | 171 + .../hisilicon/poplar/include/poplar_layout.h | 132 + .../plat/hisilicon/poplar/plat_pm.c | 173 + .../plat/hisilicon/poplar/plat_storage.c | 254 + .../plat/hisilicon/poplar/plat_topology.c | 33 + .../plat/hisilicon/poplar/platform.mk | 112 + .../plat/hisilicon/poplar/poplar_gicv2.c | 63 + .../plat/hisilicon/poplar/poplar_image_load.c | 34 + .../imx/common/aarch32/imx_uart_console.S | 50 + .../plat/imx/common/imx7_clock.c | 55 + .../plat/imx/common/imx8_helpers.S | 125 + .../plat/imx/common/imx8_psci.c | 62 + .../plat/imx/common/imx8_topology.c | 40 + .../plat/imx/common/imx_aips.c | 57 + .../plat/imx/common/imx_caam.c | 24 + .../plat/imx/common/imx_clock.c | 155 + .../plat/imx/common/imx_csu.c | 19 + .../plat/imx/common/imx_ehf.c | 22 + .../plat/imx/common/imx_io_mux.c | 24 + .../plat/imx/common/imx_io_storage.c | 301 + .../plat/imx/common/imx_sdei.c | 32 + .../plat/imx/common/imx_sip_handler.c | 255 + .../plat/imx/common/imx_sip_svc.c | 73 + .../plat/imx/common/imx_snvs.c | 22 + .../plat/imx/common/imx_uart_console.S | 88 + .../plat/imx/common/imx_wdog.c | 25 + .../plat/imx/common/include/imx8_iomux.h | 25 + .../plat/imx/common/include/imx8_lpuart.h | 61 + .../plat/imx/common/include/imx8qm_pads.h | 293 + .../plat/imx/common/include/imx8qx_pads.h | 198 + .../plat/imx/common/include/imx_aips.h | 22 + .../plat/imx/common/include/imx_caam.h | 70 + .../plat/imx/common/include/imx_clock.h | 1003 +++ .../plat/imx/common/include/imx_csu.h | 44 + .../plat/imx/common/include/imx_hab.h | 33 + .../plat/imx/common/include/imx_io_mux.h | 652 ++ .../plat/imx/common/include/imx_sip_svc.h | 67 + .../plat/imx/common/include/imx_snvs.h | 84 + .../plat/imx/common/include/imx_uart.h | 18 + .../plat/imx/common/include/imx_wdog.h | 62 + .../plat/imx/common/include/plat_imx8.h | 35 + .../plat/imx/common/include/plat_macros.S | 34 + .../plat/imx/common/include/sci/sci.h | 21 + .../plat/imx/common/include/sci/sci_ipc.h | 67 + .../plat/imx/common/include/sci/sci_rpc.h | 128 + .../plat/imx/common/include/sci/sci_scfw.h | 36 + .../plat/imx/common/include/sci/sci_types.h | 849 ++ .../include/sci/svc/misc/sci_misc_api.h | 539 ++ .../common/include/sci/svc/pad/sci_pad_api.h | 572 ++ .../common/include/sci/svc/pm/sci_pm_api.h | 684 ++ .../common/include/sci/svc/rm/sci_rm_api.h | 757 ++ .../include/sci/svc/timer/sci_timer_api.h | 358 + .../plat/imx/common/lpuart_console.S | 76 + .../plat/imx/common/plat_imx8_gic.c | 114 + .../plat/imx/common/sci/imx8_mu.c | 73 + .../plat/imx/common/sci/imx8_mu.h | 36 + .../plat/imx/common/sci/ipc.c | 120 + .../plat/imx/common/sci/sci_api.mk | 13 + .../imx/common/sci/svc/misc/misc_rpc_clnt.c | 506 ++ .../imx/common/sci/svc/misc/sci_misc_rpc.h | 76 + .../imx/common/sci/svc/pad/pad_rpc_clnt.c | 454 + .../plat/imx/common/sci/svc/pad/sci_pad_rpc.h | 66 + .../plat/imx/common/sci/svc/pm/pm_rpc_clnt.c | 459 ++ .../plat/imx/common/sci/svc/pm/sci_pm_rpc.h | 71 + .../plat/imx/common/sci/svc/rm/rm_rpc_clnt.c | 639 ++ .../plat/imx/common/sci/svc/rm/sci_rm_rpc.h | 81 + .../imx/common/sci/svc/timer/sci_timer_rpc.h | 69 + .../imx/common/sci/svc/timer/timer_rpc_clnt.c | 396 + .../plat/imx/imx7/common/imx7.mk | 112 + .../imx/imx7/common/imx7_bl2_el3_common.c | 198 + .../imx7/common/imx7_bl2_mem_params_desc.c | 81 + .../plat/imx/imx7/common/imx7_helpers.S | 59 + .../plat/imx/imx7/common/imx7_image_load.c | 24 + .../plat/imx/imx7/common/imx7_rotpk.S | 15 + .../plat/imx/imx7/common/imx7_trusted_boot.c | 36 + .../plat/imx/imx7/include/imx7_def.h | 20 + .../plat/imx/imx7/include/imx_hab_arch.h | 12 + .../plat/imx/imx7/include/imx_regs.h | 108 + .../imx/imx7/picopi/include/platform_def.h | 204 + .../imx/imx7/picopi/picopi_bl2_el3_setup.c | 134 + .../plat/imx/imx7/picopi/platform.mk | 40 + .../imx/imx7/warp7/include/platform_def.h | 218 + .../plat/imx/imx7/warp7/platform.mk | 37 + .../plat/imx/imx7/warp7/warp7_bl2_el3_setup.c | 143 + .../plat/imx/imx8m/gpc_common.c | 252 + .../plat/imx/imx8m/imx8m_caam.c | 40 + .../plat/imx/imx8m/imx8m_dyn_cfg_helpers.c | 200 + .../plat/imx/imx8m/imx8m_image_load.c | 26 + .../plat/imx/imx8m/imx8m_measured_boot.c | 85 + .../plat/imx/imx8m/imx8m_psci_common.c | 249 + .../plat/imx/imx8m/imx8mm/gpc.c | 91 + .../imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c | 143 + .../imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c | 94 + .../plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c | 186 + .../plat/imx/imx8m/imx8mm/imx8mm_psci.c | 45 + .../plat/imx/imx8m/imx8mm/imx8mm_rotpk.S | 15 + .../imx/imx8m/imx8mm/imx8mm_trusted_boot.c | 36 + .../plat/imx/imx8m/imx8mm/include/gpc_reg.h | 129 + .../imx/imx8m/imx8mm/include/imx8mm_private.h | 15 + .../imx/imx8m/imx8mm/include/platform_def.h | 158 + .../plat/imx/imx8m/imx8mm/platform.mk | 165 + .../plat/imx/imx8m/imx8mn/gpc.c | 94 + .../plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c | 186 + .../plat/imx/imx8m/imx8mn/imx8mn_psci.c | 44 + .../plat/imx/imx8m/imx8mn/include/gpc_reg.h | 111 + .../imx/imx8m/imx8mn/include/platform_def.h | 140 + .../plat/imx/imx8m/imx8mn/platform.mk | 61 + .../plat/imx/imx8m/imx8mp/gpc.c | 379 + .../imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c | 117 + .../imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c | 94 + .../plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c | 187 + .../plat/imx/imx8m/imx8mp/imx8mp_psci.c | 44 + .../plat/imx/imx8m/imx8mp/imx8mp_rotpk.S | 15 + .../imx/imx8m/imx8mp/imx8mp_trusted_boot.c | 36 + .../plat/imx/imx8m/imx8mp/include/gpc_reg.h | 151 + .../imx/imx8m/imx8mp/include/imx8mp_private.h | 15 + .../imx/imx8m/imx8mp/include/platform_def.h | 180 + .../plat/imx/imx8m/imx8mp/platform.mk | 153 + .../plat/imx/imx8m/imx8mq/gpc.c | 181 + .../plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c | 217 + .../plat/imx/imx8m/imx8mq/imx8mq_psci.c | 133 + .../plat/imx/imx8m/imx8mq/include/gpc_reg.h | 89 + .../imx/imx8m/imx8mq/include/platform_def.h | 126 + .../plat/imx/imx8m/imx8mq/platform.mk | 51 + .../plat/imx/imx8m/imx_aipstz.c | 24 + arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c | 37 + .../plat/imx/imx8m/include/gpc.h | 73 + .../plat/imx/imx8m/include/imx8m_caam.h | 35 + .../imx/imx8m/include/imx8m_measured_boot.h | 16 + .../plat/imx/imx8m/include/imx8m_psci.h | 24 + .../plat/imx/imx8m/include/imx_aipstz.h | 27 + .../plat/imx/imx8m/include/imx_rdc.h | 72 + .../plat/imx/imx8qm/imx8qm_bl31_setup.c | 415 + .../plat/imx/imx8qm/imx8qm_psci.c | 326 + .../plat/imx/imx8qm/include/platform_def.h | 79 + .../plat/imx/imx8qm/include/sec_rsrc.h | 32 + .../plat/imx/imx8qm/platform.mk | 48 + .../plat/imx/imx8qx/imx8qx_bl31_setup.c | 383 + .../plat/imx/imx8qx/imx8qx_psci.c | 246 + .../plat/imx/imx8qx/include/platform_def.h | 68 + .../plat/imx/imx8qx/include/sec_rsrc.h | 25 + .../plat/imx/imx8qx/platform.mk | 40 + .../plat/intel/soc/agilex/bl2_plat_setup.c | 186 + .../plat/intel/soc/agilex/bl31_plat_setup.c | 157 + .../soc/agilex/include/agilex_clock_manager.h | 131 + .../agilex/include/agilex_memory_controller.h | 163 + .../intel/soc/agilex/include/agilex_mmc.h | 7 + .../intel/soc/agilex/include/agilex_noc.h | 69 + .../intel/soc/agilex/include/agilex_pinmux.h | 20 + .../soc/agilex/include/socfpga_plat_def.h | 33 + .../plat/intel/soc/agilex/platform.mk | 78 + .../soc/agilex/soc/agilex_clock_manager.c | 389 + .../soc/agilex/soc/agilex_memory_controller.c | 399 + .../plat/intel/soc/agilex/soc/agilex_mmc.c | 19 + .../plat/intel/soc/agilex/soc/agilex_pinmux.c | 225 + .../intel/soc/common/aarch64/plat_helpers.S | 150 + .../soc/common/aarch64/platform_common.c | 60 + .../soc/common/bl2_plat_mem_params_desc.c | 96 + .../intel/soc/common/drivers/ccu/ncore_ccu.c | 131 + .../intel/soc/common/drivers/ccu/ncore_ccu.h | 109 + .../soc/common/drivers/qspi/cadence_qspi.c | 822 ++ .../soc/common/drivers/qspi/cadence_qspi.h | 178 + .../intel/soc/common/drivers/wdt/watchdog.c | 52 + .../intel/soc/common/drivers/wdt/watchdog.h | 39 + .../intel/soc/common/include/plat_macros.S | 22 + .../intel/soc/common/include/platform_def.h | 242 + .../intel/soc/common/include/socfpga_emac.h | 24 + .../intel/soc/common/include/socfpga_fcs.h | 41 + .../soc/common/include/socfpga_handoff.h | 135 + .../soc/common/include/socfpga_mailbox.h | 175 + .../soc/common/include/socfpga_private.h | 66 + .../common/include/socfpga_reset_manager.h | 108 + .../soc/common/include/socfpga_sip_svc.h | 87 + .../common/include/socfpga_system_manager.h | 126 + .../intel/soc/common/sip/socfpga_sip_ecc.c | 46 + .../intel/soc/common/sip/socfpga_sip_fcs.c | 120 + .../plat/intel/soc/common/soc/socfpga_emac.c | 38 + .../intel/soc/common/soc/socfpga_handoff.c | 39 + .../intel/soc/common/soc/socfpga_mailbox.c | 529 ++ .../soc/common/soc/socfpga_reset_manager.c | 146 + .../soc/common/soc/socfpga_system_manager.c | 107 + .../intel/soc/common/socfpga_delay_timer.c | 43 + .../intel/soc/common/socfpga_image_load.c | 58 + .../plat/intel/soc/common/socfpga_psci.c | 229 + .../plat/intel/soc/common/socfpga_sip_svc.c | 567 ++ .../plat/intel/soc/common/socfpga_storage.c | 193 + .../plat/intel/soc/common/socfpga_topology.c | 51 + .../plat/intel/soc/n5x/bl31_plat_setup.c | 165 + .../intel/soc/n5x/include/socfpga_plat_def.h | 32 + .../plat/intel/soc/n5x/platform.mk | 52 + .../plat/intel/soc/stratix10/bl2_plat_setup.c | 182 + .../intel/soc/stratix10/bl31_plat_setup.c | 170 + .../soc/stratix10/include/s10_clock_manager.h | 96 + .../stratix10/include/s10_memory_controller.h | 160 + .../intel/soc/stratix10/include/s10_noc.h | 63 + .../intel/soc/stratix10/include/s10_pinmux.h | 20 + .../soc/stratix10/include/socfpga_plat_def.h | 34 + .../plat/intel/soc/stratix10/platform.mk | 74 + .../soc/stratix10/soc/s10_clock_manager.c | 309 + .../soc/stratix10/soc/s10_memory_controller.c | 412 + .../plat/intel/soc/stratix10/soc/s10_pinmux.c | 217 + .../marvell/armada/a3k/a3700/board/pm_src.c | 37 + .../plat/marvell/armada/a3k/a3700/mvebu_def.h | 13 + .../armada/a3k/a3700/plat_bl31_setup.c | 70 + .../plat/marvell/armada/a3k/a3700/platform.mk | 10 + .../marvell/armada/a3k/common/a3700_common.mk | 247 + .../plat/marvell/armada/a3k/common/a3700_ea.c | 90 + .../marvell/armada/a3k/common/a3700_sip_svc.c | 84 + .../armada/a3k/common/aarch64/a3700_clock.S | 35 + .../armada/a3k/common/aarch64/a3700_common.c | 53 + .../armada/a3k/common/aarch64/plat_helpers.S | 68 + .../armada/a3k/common/cm3_system_reset.c | 62 + .../plat/marvell/armada/a3k/common/dram_win.c | 282 + .../a3k/common/include/a3700_plat_def.h | 169 + .../armada/a3k/common/include/a3700_pm.h | 53 + .../armada/a3k/common/include/ddr_info.h | 14 + .../armada/a3k/common/include/dram_win.h | 18 + .../armada/a3k/common/include/io_addr_dec.h | 66 + .../armada/a3k/common/include/plat_macros.S | 26 + .../armada/a3k/common/include/platform_def.h | 228 + .../marvell/armada/a3k/common/io_addr_dec.c | 175 + .../armada/a3k/common/marvell_plat_config.c | 34 + .../plat/marvell/armada/a3k/common/plat_cci.c | 35 + .../plat/marvell/armada/a3k/common/plat_pm.c | 822 ++ .../armada/a8k/a70x0/board/dram_port.c | 91 + .../a8k/a70x0/board/marvell_plat_config.c | 151 + .../plat/marvell/armada/a8k/a70x0/mvebu_def.h | 15 + .../plat/marvell/armada/a8k/a70x0/platform.mk | 20 + .../armada/a8k/a70x0_amc/board/dram_port.c | 91 + .../a8k/a70x0_amc/board/marvell_plat_config.c | 148 + .../marvell/armada/a8k/a70x0_amc/mvebu_def.h | 31 + .../marvell/armada/a8k/a70x0_amc/platform.mk | 20 + .../a8k/a70x0_mochabin/board/dram_port.c | 227 + .../board/marvell_plat_config.c | 145 + .../a70x0_mochabin/board/phy-porting-layer.h | 87 + .../armada/a8k/a70x0_mochabin/mvebu_def.h | 15 + .../armada/a8k/a70x0_mochabin/platform.mk | 20 + .../armada/a8k/a80x0/board/dram_port.c | 147 + .../a8k/a80x0/board/marvell_plat_config.c | 202 + .../a8k/a80x0/board/phy-porting-layer.h | 192 + .../plat/marvell/armada/a8k/a80x0/mvebu_def.h | 17 + .../plat/marvell/armada/a8k/a80x0/platform.mk | 20 + .../armada/a8k/a80x0_mcbin/board/dram_port.c | 131 + .../a80x0_mcbin/board/marvell_plat_config.c | 200 + .../armada/a8k/a80x0_mcbin/mvebu_def.h | 17 + .../armada/a8k/a80x0_mcbin/platform.mk | 20 + .../armada/a8k/a80x0_puzzle/board/dram_port.c | 140 + .../a80x0_puzzle/board/marvell_plat_config.c | 201 + .../a8k/a80x0_puzzle/board/system_power.c | 59 + .../armada/a8k/a80x0_puzzle/mvebu_def.h | 17 + .../armada/a8k/a80x0_puzzle/platform.mk | 20 + .../marvell/armada/a8k/common/a8k_common.mk | 192 + .../armada/a8k/common/aarch64/a8k_common.c | 70 + .../a8k/common/aarch64/plat_arch_config.c | 95 + .../armada/a8k/common/aarch64/plat_helpers.S | 112 + .../marvell/armada/a8k/common/ble/ble.ld.S | 76 + .../plat/marvell/armada/a8k/common/ble/ble.mk | 35 + .../marvell/armada/a8k/common/ble/ble_main.c | 99 + .../marvell/armada/a8k/common/ble/ble_mem.S | 30 + .../armada/a8k/common/include/a8k_plat_def.h | 195 + .../armada/a8k/common/include/ddr_info.h | 9 + .../a8k/common/include/mentor_i2c_plat.h | 33 + .../armada/a8k/common/include/plat_macros.S | 20 + .../armada/a8k/common/include/platform_def.h | 196 + .../marvell/armada/a8k/common/mss/mss_a8k.mk | 22 + .../armada/a8k/common/mss/mss_bl2_setup.c | 165 + .../armada/a8k/common/mss/mss_bl31_setup.c | 37 + .../marvell/armada/a8k/common/mss/mss_defs.h | 33 + .../armada/a8k/common/mss/mss_pm_ipc.c | 85 + .../armada/a8k/common/mss/mss_pm_ipc.h | 35 + .../armada/a8k/common/plat_bl1_setup.c | 19 + .../armada/a8k/common/plat_bl31_setup.c | 148 + .../armada/a8k/common/plat_ble_setup.c | 765 ++ .../plat/marvell/armada/a8k/common/plat_pm.c | 853 ++ .../marvell/armada/a8k/common/plat_pm_trace.c | 94 + .../marvell/armada/a8k/common/plat_thermal.c | 130 + .../aarch64/marvell_bl2_mem_params_desc.c | 168 + .../armada/common/aarch64/marvell_common.c | 137 + .../armada/common/aarch64/marvell_helpers.S | 259 + .../marvell/armada/common/marvell_bl1_setup.c | 105 + .../marvell/armada/common/marvell_bl2_setup.c | 158 + .../armada/common/marvell_bl31_setup.c | 237 + .../plat/marvell/armada/common/marvell_cci.c | 52 + .../marvell/armada/common/marvell_common.mk | 99 + .../marvell/armada/common/marvell_console.c | 77 + .../marvell/armada/common/marvell_ddr_info.c | 112 + .../marvell/armada/common/marvell_gicv2.c | 148 + .../marvell/armada/common/marvell_gicv3.c | 210 + .../armada/common/marvell_image_load.c | 36 + .../armada/common/marvell_io_storage.c | 227 + .../plat/marvell/armada/common/marvell_pm.c | 60 + .../marvell/armada/common/marvell_topology.c | 84 + .../plat/marvell/armada/common/mrvl_sip_svc.c | 188 + .../marvell/armada/common/mss/mss_common.mk | 20 + .../marvell/armada/common/mss/mss_ipc_drv.c | 113 + .../marvell/armada/common/mss/mss_ipc_drv.h | 120 + .../plat/marvell/armada/common/mss/mss_mem.h | 60 + .../armada/common/mss/mss_scp_bl2_format.h | 45 + .../armada/common/mss/mss_scp_bootloader.c | 368 + .../armada/common/mss/mss_scp_bootloader.h | 20 + .../marvell/armada/common/plat_delay_timer.c | 34 + arm-trusted-firmware/plat/marvell/marvell.mk | 21 + .../octeontx/otx2/t91/t9130/board/dram_port.c | 158 + .../t91/t9130/board/marvell_plat_config.c | 192 + .../otx2/t91/t9130/board/phy-porting-layer.h | 145 + .../octeontx/otx2/t91/t9130/mvebu_def.h | 25 + .../octeontx/otx2/t91/t9130/platform.mk | 20 + .../board/marvell_plat_config.c | 224 + .../otx2/t91/t9130_cex7_eval/platform.mk | 33 + .../plat/mediatek/common/custom/oem_svc.c | 100 + .../plat/mediatek/common/custom/oem_svc.h | 44 + .../common/drivers/gic600/mt_gic_v3.c | 196 + .../common/drivers/gic600/mt_gic_v3.h | 27 + .../common/drivers/gpio/mtgpio_common.c | 298 + .../common/drivers/gpio/mtgpio_common.h | 109 + .../common/drivers/pmic_wrap/pmic_wrap_init.c | 165 + .../drivers/pmic_wrap/pmic_wrap_init_v2.c | 143 + .../mediatek/common/drivers/rtc/rtc_common.c | 64 + .../mediatek/common/drivers/rtc/rtc_mt6359p.c | 148 + .../mediatek/common/drivers/rtc/rtc_mt6359p.h | 197 + .../mediatek/common/drivers/timer/mt_timer.c | 38 + .../mediatek/common/drivers/timer/mt_timer.h | 35 + .../common/drivers/uart/8250_console.S | 163 + .../plat/mediatek/common/drivers/uart/uart.c | 112 + .../plat/mediatek/common/drivers/uart/uart.h | 100 + .../mediatek/common/drivers/uart/uart8250.h | 38 + .../plat/mediatek/common/lpm/mt_lp_rm.c | 110 + .../plat/mediatek/common/lpm/mt_lp_rm.h | 42 + .../plat/mediatek/common/mtk_cirq.c | 549 ++ .../plat/mediatek/common/mtk_cirq.h | 122 + .../plat/mediatek/common/mtk_plat_common.c | 150 + .../plat/mediatek/common/mtk_plat_common.h | 81 + .../plat/mediatek/common/mtk_sip_svc.c | 129 + .../plat/mediatek/common/mtk_sip_svc.h | 61 + .../plat/mediatek/common/params_setup.c | 35 + .../plat/mediatek/common/plat_params.h | 17 + .../mediatek/mt6795/aarch64/plat_helpers.S | 148 + .../plat/mediatek/mt6795/bl31.ld.S | 116 + .../plat/mediatek/mt6795/bl31_plat_setup.c | 449 + .../mt6795/drivers/timer/mt_cpuxgpt.c | 67 + .../mt6795/drivers/timer/mt_cpuxgpt.h | 28 + .../plat/mediatek/mt6795/include/mcucfg.h | 155 + .../mediatek/mt6795/include/plat_macros.S | 85 + .../mediatek/mt6795/include/plat_private.h | 38 + .../mediatek/mt6795/include/plat_sip_calls.h | 15 + .../mediatek/mt6795/include/platform_def.h | 238 + .../mediatek/mt6795/include/power_tracer.h | 19 + .../plat/mediatek/mt6795/include/scu.h | 13 + .../plat/mediatek/mt6795/include/spm.h | 198 + .../plat/mediatek/mt6795/plat_delay_timer.c | 31 + .../plat/mediatek/mt6795/plat_mt_gic.c | 50 + .../plat/mediatek/mt6795/plat_pm.c | 473 ++ .../plat/mediatek/mt6795/plat_topology.c | 34 + .../plat/mediatek/mt6795/platform.mk | 67 + .../plat/mediatek/mt6795/power_tracer.c | 48 + .../plat/mediatek/mt6795/scu.c | 30 + .../mediatek/mt8173/aarch64/plat_helpers.S | 49 + .../mediatek/mt8173/aarch64/platform_common.c | 89 + .../plat/mediatek/mt8173/bl31_plat_setup.c | 146 + .../mediatek/mt8173/drivers/crypt/crypt.c | 123 + .../mediatek/mt8173/drivers/crypt/crypt.h | 16 + .../mediatek/mt8173/drivers/mtcmos/mtcmos.c | 274 + .../mediatek/mt8173/drivers/mtcmos/mtcmos.h | 18 + .../mt8173/drivers/pmic/pmic_wrap_init.h | 169 + .../plat/mediatek/mt8173/drivers/rtc/rtc.c | 26 + .../plat/mediatek/mt8173/drivers/rtc/rtc.h | 60 + .../plat/mediatek/mt8173/drivers/spm/spm.c | 370 + .../plat/mediatek/mt8173/drivers/spm/spm.h | 335 + .../mediatek/mt8173/drivers/spm/spm_hotplug.c | 275 + .../mediatek/mt8173/drivers/spm/spm_hotplug.h | 13 + .../mediatek/mt8173/drivers/spm/spm_mcdi.c | 503 ++ .../mediatek/mt8173/drivers/spm/spm_mcdi.h | 14 + .../mediatek/mt8173/drivers/spm/spm_suspend.c | 315 + .../mediatek/mt8173/drivers/spm/spm_suspend.h | 16 + .../mt8173/drivers/timer/mt_cpuxgpt.c | 34 + .../mt8173/drivers/timer/mt_cpuxgpt.h | 16 + .../plat/mediatek/mt8173/drivers/wdt/wdt.c | 115 + .../plat/mediatek/mt8173/drivers/wdt/wdt.h | 20 + .../plat/mediatek/mt8173/include/mcucfg.h | 220 + .../plat/mediatek/mt8173/include/mt8173_def.h | 140 + .../mediatek/mt8173/include/plat_macros.S | 78 + .../mediatek/mt8173/include/plat_private.h | 27 + .../mediatek/mt8173/include/plat_sip_calls.h | 23 + .../mediatek/mt8173/include/platform_def.h | 141 + .../mediatek/mt8173/include/power_tracer.h | 19 + .../plat/mediatek/mt8173/include/scu.h | 13 + .../plat/mediatek/mt8173/plat_mt_gic.c | 30 + .../plat/mediatek/mt8173/plat_pm.c | 603 ++ .../plat/mediatek/mt8173/plat_sip_calls.c | 115 + .../plat/mediatek/mt8173/plat_topology.c | 60 + .../plat/mediatek/mt8173/platform.mk | 74 + .../plat/mediatek/mt8173/power_tracer.c | 48 + .../plat/mediatek/mt8173/scu.c | 30 + .../mediatek/mt8183/aarch64/plat_helpers.S | 34 + .../mediatek/mt8183/aarch64/platform_common.c | 84 + .../plat/mediatek/mt8183/bl31_plat_setup.c | 181 + .../mediatek/mt8183/drivers/devapc/devapc.c | 231 + .../mediatek/mt8183/drivers/devapc/devapc.h | 499 ++ .../mediatek/mt8183/drivers/emi_mpu/emi_mpu.c | 147 + .../mediatek/mt8183/drivers/emi_mpu/emi_mpu.h | 106 + .../mediatek/mt8183/drivers/gpio/mtgpio.c | 439 + .../mediatek/mt8183/drivers/gpio/mtgpio.h | 154 + .../mediatek/mt8183/drivers/gpio/mtgpio_cfg.h | 208 + .../mediatek/mt8183/drivers/mcdi/mtk_mcdi.c | 259 + .../mediatek/mt8183/drivers/mcdi/mtk_mcdi.h | 34 + .../plat/mediatek/mt8183/drivers/mcsi/mcsi.c | 211 + .../plat/mediatek/mt8183/drivers/mcsi/mcsi.h | 116 + .../plat/mediatek/mt8183/drivers/pmic/pmic.c | 42 + .../plat/mediatek/mt8183/drivers/pmic/pmic.h | 30 + .../mt8183/drivers/pmic/pmic_wrap_init.h | 94 + .../plat/mediatek/mt8183/drivers/rtc/rtc.c | 133 + .../plat/mediatek/mt8183/drivers/rtc/rtc.h | 147 + .../plat/mediatek/mt8183/drivers/spm/spm.c | 363 + .../plat/mediatek/mt8183/drivers/spm/spm.h | 2552 ++++++ .../mt8183/drivers/spm/spm_pmic_wrap.c | 170 + .../mt8183/drivers/spm/spm_pmic_wrap.h | 50 + .../mediatek/mt8183/drivers/spm/spm_suspend.c | 255 + .../mediatek/mt8183/drivers/spm/spm_suspend.h | 13 + .../mediatek/mt8183/drivers/spmc/mtspmc.c | 366 + .../mediatek/mt8183/drivers/spmc/mtspmc.h | 42 + .../mt8183/drivers/spmc/mtspmc_private.h | 233 + .../plat/mediatek/mt8183/drivers/sspm/sspm.c | 159 + .../plat/mediatek/mt8183/drivers/sspm/sspm.h | 32 + .../mediatek/mt8183/drivers/timer/mt_timer.c | 29 + .../mediatek/mt8183/drivers/timer/mt_timer.h | 20 + .../plat/mediatek/mt8183/include/mcucfg.h | 568 ++ .../plat/mediatek/mt8183/include/mt_gic_v3.h | 34 + .../plat/mediatek/mt8183/include/plat_dcm.h | 53 + .../plat/mediatek/mt8183/include/plat_debug.h | 34 + .../mediatek/mt8183/include/plat_macros.S | 78 + .../mediatek/mt8183/include/plat_private.h | 28 + .../mediatek/mt8183/include/platform_def.h | 321 + .../mediatek/mt8183/include/power_tracer.h | 20 + .../plat/mediatek/mt8183/include/scu.h | 13 + .../plat/mediatek/mt8183/include/sspm_reg.h | 41 + .../plat/mediatek/mt8183/plat_dcm.c | 112 + .../plat/mediatek/mt8183/plat_debug.c | 58 + .../plat/mediatek/mt8183/plat_mt_gic.c | 160 + .../plat/mediatek/mt8183/plat_pm.c | 589 ++ .../plat/mediatek/mt8183/plat_topology.c | 59 + .../plat/mediatek/mt8183/platform.mk | 89 + .../plat/mediatek/mt8183/scu.c | 56 + .../mediatek/mt8186/aarch64/plat_helpers.S | 45 + .../mediatek/mt8186/aarch64/platform_common.c | 44 + .../plat/mediatek/mt8186/bl31_plat_setup.c | 113 + .../mediatek/mt8186/drivers/dcm/mtk_dcm.c | 66 + .../mediatek/mt8186/drivers/dcm/mtk_dcm.h | 14 + .../mt8186/drivers/dcm/mtk_dcm_utils.c | 490 ++ .../mt8186/drivers/dcm/mtk_dcm_utils.h | 58 + .../mediatek/mt8186/drivers/dfd/plat_dfd.c | 98 + .../mediatek/mt8186/drivers/dfd/plat_dfd.h | 64 + .../mediatek/mt8186/drivers/emi_mpu/emi_mpu.c | 100 + .../mediatek/mt8186/drivers/emi_mpu/emi_mpu.h | 98 + .../mediatek/mt8186/drivers/gpio/mtgpio.c | 44 + .../mediatek/mt8186/drivers/gpio/mtgpio.h | 230 + .../mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c | 149 + .../mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h | 34 + .../mt8186/drivers/mcdi/mt_cpu_pm_cpc.c | 269 + .../mt8186/drivers/mcdi/mt_cpu_pm_cpc.h | 102 + .../mt8186/drivers/mcdi/mt_lp_irqremain.c | 74 + .../mt8186/drivers/mcdi/mt_lp_irqremain.h | 15 + .../mediatek/mt8186/drivers/mcdi/mt_mcdi.c | 150 + .../mediatek/mt8186/drivers/mcdi/mt_mcdi.h | 12 + .../plat/mediatek/mt8186/drivers/pmic/pmic.c | 23 + .../plat/mediatek/mt8186/drivers/pmic/pmic.h | 19 + .../mt8186/drivers/pmic/pmic_wrap_init.h | 94 + .../plat/mediatek/mt8186/drivers/rtc/rtc.c | 133 + .../plat/mediatek/mt8186/drivers/rtc/rtc.h | 145 + .../plat/mediatek/mt8186/drivers/spm/build.mk | 78 + .../spm/constraints/mt_spm_rc_bus26m.c | 241 + .../spm/constraints/mt_spm_rc_cpu_buck_ldo.c | 105 + .../drivers/spm/constraints/mt_spm_rc_dram.c | 187 + .../spm/constraints/mt_spm_rc_internal.h | 48 + .../spm/constraints/mt_spm_rc_syspll.c | 197 + .../plat/mediatek/mt8186/drivers/spm/mt_spm.c | 110 + .../plat/mediatek/mt8186/drivers/spm/mt_spm.h | 82 + .../mediatek/mt8186/drivers/spm/mt_spm_cond.c | 212 + .../mediatek/mt8186/drivers/spm/mt_spm_cond.h | 60 + .../mt8186/drivers/spm/mt_spm_conservation.c | 165 + .../mt8186/drivers/spm/mt_spm_conservation.h | 21 + .../mt8186/drivers/spm/mt_spm_constraint.h | 64 + .../mt8186/drivers/spm/mt_spm_extern.c | 23 + .../mt8186/drivers/spm/mt_spm_extern.h | 12 + .../mediatek/mt8186/drivers/spm/mt_spm_idle.c | 240 + .../mediatek/mt8186/drivers/spm/mt_spm_idle.h | 24 + .../mt8186/drivers/spm/mt_spm_internal.c | 623 ++ .../mt8186/drivers/spm/mt_spm_internal.h | 620 ++ .../mt8186/drivers/spm/mt_spm_pmic_wrap.c | 166 + .../mt8186/drivers/spm/mt_spm_pmic_wrap.h | 39 + .../mediatek/mt8186/drivers/spm/mt_spm_reg.h | 2957 +++++++ .../mt8186/drivers/spm/mt_spm_resource_req.h | 26 + .../mt8186/drivers/spm/mt_spm_suspend.c | 286 + .../mt8186/drivers/spm/mt_spm_suspend.h | 28 + .../mt8186/drivers/spm/mt_spm_vcorefs.c | 533 ++ .../mt8186/drivers/spm/mt_spm_vcorefs.h | 316 + .../drivers/spm/notifier/mt_spm_notifier.h | 23 + .../drivers/spm/notifier/mt_spm_sspm_intc.h | 36 + .../spm/notifier/mt_spm_sspm_notifier.c | 41 + .../mediatek/mt8186/drivers/spm/pcm_def.h | 180 + .../mediatek/mt8186/drivers/spm/sleep_def.h | 146 + .../mediatek/mt8186/drivers/spmc/mtspmc.c | 172 + .../mediatek/mt8186/drivers/spmc/mtspmc.h | 31 + .../mt8186/drivers/spmc/mtspmc_private.h | 176 + .../plat/mediatek/mt8186/include/mcucfg.h | 255 + .../mt8186/include/mt_spm_resource_req.h | 32 + .../mediatek/mt8186/include/plat_helpers.h | 12 + .../mediatek/mt8186/include/plat_macros.S | 37 + .../mediatek/mt8186/include/plat_mtk_lpm.h | 49 + .../plat/mediatek/mt8186/include/plat_pm.h | 128 + .../mediatek/mt8186/include/plat_private.h | 18 + .../mediatek/mt8186/include/plat_sip_calls.h | 19 + .../plat/mediatek/mt8186/include/plat_uart.h | 25 + .../mediatek/mt8186/include/platform_def.h | 154 + .../plat/mediatek/mt8186/include/sspm_reg.h | 25 + .../plat/mediatek/mt8186/plat_pm.c | 400 + .../plat/mediatek/mt8186/plat_sip_calls.c | 42 + .../plat/mediatek/mt8186/plat_topology.c | 70 + .../plat/mediatek/mt8186/platform.mk | 104 + .../mediatek/mt8192/aarch64/plat_helpers.S | 49 + .../mediatek/mt8192/aarch64/platform_common.c | 56 + .../plat/mediatek/mt8192/bl31_plat_setup.c | 121 + .../mt8192/drivers/apusys/mtk_apusys.c | 68 + .../mt8192/drivers/apusys/mtk_apusys.h | 42 + .../mt8192/drivers/apusys/mtk_apusys_apc.c | 571 ++ .../mt8192/drivers/apusys/mtk_apusys_apc.h | 12 + .../drivers/apusys/mtk_apusys_apc_def.h | 110 + .../mediatek/mt8192/drivers/dcm/mtk_dcm.c | 63 + .../mediatek/mt8192/drivers/dcm/mtk_dcm.h | 14 + .../mt8192/drivers/dcm/mtk_dcm_utils.c | 562 ++ .../mt8192/drivers/dcm/mtk_dcm_utils.h | 68 + .../mediatek/mt8192/drivers/devapc/devapc.c | 2847 +++++++ .../mediatek/mt8192/drivers/devapc/devapc.h | 211 + .../mediatek/mt8192/drivers/dfd/plat_dfd.c | 139 + .../mediatek/mt8192/drivers/dfd/plat_dfd.h | 70 + .../mediatek/mt8192/drivers/emi_mpu/emi_mpu.c | 144 + .../mediatek/mt8192/drivers/emi_mpu/emi_mpu.h | 102 + .../mediatek/mt8192/drivers/gpio/mtgpio.c | 53 + .../mediatek/mt8192/drivers/gpio/mtgpio.h | 269 + .../mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c | 149 + .../mt8192/drivers/mcdi/mt_cpu_pm_cpc.c | 269 + .../mt8192/drivers/mcdi/mt_cpu_pm_cpc.h | 106 + .../mt8192/drivers/mcdi/mt_lp_irqremain.c | 150 + .../mt8192/drivers/mcdi/mt_lp_irqremain.h | 14 + .../mediatek/mt8192/drivers/mcdi/mt_mcdi.c | 151 + .../mediatek/mt8192/drivers/mcdi/mt_mcdi.h | 12 + .../plat/mediatek/mt8192/drivers/pmic/pmic.c | 13 + .../plat/mediatek/mt8192/drivers/pmic/pmic.h | 15 + .../mt8192/drivers/pmic/pmic_wrap_init.h | 76 + .../mt8192/drivers/ptp3/mtk_ptp3_common.h | 48 + .../mt8192/drivers/ptp3/mtk_ptp3_main.c | 84 + .../plat/mediatek/mt8192/drivers/spm/build.mk | 68 + .../spm/constraints/mt_spm_rc_bus26m.c | 230 + .../spm/constraints/mt_spm_rc_cpu_buck_ldo.c | 104 + .../drivers/spm/constraints/mt_spm_rc_dram.c | 191 + .../spm/constraints/mt_spm_rc_internal.h | 45 + .../spm/constraints/mt_spm_rc_syspll.c | 192 + .../plat/mediatek/mt8192/drivers/spm/mt_spm.c | 104 + .../plat/mediatek/mt8192/drivers/spm/mt_spm.h | 68 + .../mediatek/mt8192/drivers/spm/mt_spm_cond.c | 219 + .../mediatek/mt8192/drivers/spm/mt_spm_cond.h | 56 + .../mt8192/drivers/spm/mt_spm_conservation.c | 155 + .../mt8192/drivers/spm/mt_spm_conservation.h | 20 + .../mt8192/drivers/spm/mt_spm_constraint.h | 63 + .../mediatek/mt8192/drivers/spm/mt_spm_idle.c | 249 + .../mediatek/mt8192/drivers/spm/mt_spm_idle.h | 17 + .../mt8192/drivers/spm/mt_spm_internal.c | 588 ++ .../mt8192/drivers/spm/mt_spm_internal.h | 637 ++ .../mt8192/drivers/spm/mt_spm_pmic_wrap.c | 159 + .../mt8192/drivers/spm/mt_spm_pmic_wrap.h | 45 + .../mediatek/mt8192/drivers/spm/mt_spm_reg.h | 2919 +++++++ .../mt8192/drivers/spm/mt_spm_resource_req.h | 25 + .../mt8192/drivers/spm/mt_spm_suspend.c | 303 + .../mt8192/drivers/spm/mt_spm_suspend.h | 26 + .../mt8192/drivers/spm/mt_spm_vcorefs.c | 405 + .../mt8192/drivers/spm/mt_spm_vcorefs.h | 135 + .../drivers/spm/notifier/mt_spm_notifier.h | 21 + .../drivers/spm/notifier/mt_spm_sspm_intc.h | 33 + .../spm/notifier/mt_spm_sspm_notifier.c | 47 + .../mediatek/mt8192/drivers/spm/pcm_def.h | 179 + .../mediatek/mt8192/drivers/spm/sleep_def.h | 151 + .../mediatek/mt8192/drivers/spmc/mtspmc.c | 177 + .../mediatek/mt8192/drivers/spmc/mtspmc.h | 31 + .../mt8192/drivers/spmc/mtspmc_private.h | 184 + .../plat/mediatek/mt8192/include/mcucfg.h | 257 + .../mediatek/mt8192/include/plat_helpers.h | 12 + .../mediatek/mt8192/include/plat_macros.S | 38 + .../mediatek/mt8192/include/plat_mtk_lpm.h | 48 + .../plat/mediatek/mt8192/include/plat_pm.h | 38 + .../mediatek/mt8192/include/plat_private.h | 18 + .../mediatek/mt8192/include/plat_sip_calls.h | 19 + .../mediatek/mt8192/include/platform_def.h | 151 + .../plat/mediatek/mt8192/include/rtc.h | 12 + .../plat/mediatek/mt8192/plat_pm.c | 398 + .../plat/mediatek/mt8192/plat_sip_calls.c | 49 + .../plat/mediatek/mt8192/plat_topology.c | 75 + .../plat/mediatek/mt8192/platform.mk | 99 + .../mediatek/mt8195/aarch64/plat_helpers.S | 49 + .../mediatek/mt8195/aarch64/platform_common.c | 56 + .../plat/mediatek/mt8195/bl31_plat_setup.c | 117 + .../mediatek/mt8195/drivers/apusys/apupll.c | 581 ++ .../mt8195/drivers/apusys/apupwr_clkctl.c | 341 + .../mt8195/drivers/apusys/apupwr_clkctl.h | 23 + .../mt8195/drivers/apusys/apupwr_clkctl_def.h | 195 + .../mt8195/drivers/apusys/mtk_apusys.c | 83 + .../mt8195/drivers/apusys/mtk_apusys.h | 51 + .../mediatek/mt8195/drivers/dcm/mtk_dcm.c | 63 + .../mediatek/mt8195/drivers/dcm/mtk_dcm.h | 14 + .../mt8195/drivers/dcm/mtk_dcm_utils.c | 483 ++ .../mt8195/drivers/dcm/mtk_dcm_utils.h | 59 + .../mediatek/mt8195/drivers/dfd/plat_dfd.c | 156 + .../mediatek/mt8195/drivers/dfd/plat_dfd.h | 85 + .../plat/mediatek/mt8195/drivers/dp/mt_dp.c | 69 + .../plat/mediatek/mt8195/drivers/dp/mt_dp.h | 28 + .../mediatek/mt8195/drivers/emi_mpu/emi_mpu.c | 151 + .../mediatek/mt8195/drivers/emi_mpu/emi_mpu.h | 98 + .../mediatek/mt8195/drivers/gpio/mtgpio.c | 44 + .../mediatek/mt8195/drivers/gpio/mtgpio.h | 183 + .../mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c | 150 + .../mt8195/drivers/mcdi/mt_cpu_pm_cpc.c | 269 + .../mt8195/drivers/mcdi/mt_cpu_pm_cpc.h | 106 + .../mt8195/drivers/mcdi/mt_lp_irqremain.c | 70 + .../mt8195/drivers/mcdi/mt_lp_irqremain.h | 14 + .../mediatek/mt8195/drivers/mcdi/mt_mcdi.c | 151 + .../mediatek/mt8195/drivers/mcdi/mt_mcdi.h | 12 + .../plat/mediatek/mt8195/drivers/pmic/pmic.c | 13 + .../plat/mediatek/mt8195/drivers/pmic/pmic.h | 15 + .../mt8195/drivers/pmic/pmic_wrap_init.h | 76 + .../mt8195/drivers/ptp3/mtk_ptp3_common.h | 52 + .../mt8195/drivers/ptp3/mtk_ptp3_main.c | 137 + .../plat/mediatek/mt8195/drivers/spm/build.mk | 68 + .../spm/constraints/mt_spm_rc_bus26m.c | 241 + .../spm/constraints/mt_spm_rc_cpu_buck_ldo.c | 106 + .../drivers/spm/constraints/mt_spm_rc_dram.c | 201 + .../spm/constraints/mt_spm_rc_internal.h | 43 + .../spm/constraints/mt_spm_rc_syspll.c | 200 + .../plat/mediatek/mt8195/drivers/spm/mt_spm.c | 98 + .../plat/mediatek/mt8195/drivers/spm/mt_spm.h | 68 + .../mediatek/mt8195/drivers/spm/mt_spm_cond.c | 235 + .../mediatek/mt8195/drivers/spm/mt_spm_cond.h | 73 + .../mt8195/drivers/spm/mt_spm_conservation.c | 155 + .../mt8195/drivers/spm/mt_spm_conservation.h | 20 + .../mt8195/drivers/spm/mt_spm_constraint.h | 63 + .../mediatek/mt8195/drivers/spm/mt_spm_idle.c | 346 + .../mediatek/mt8195/drivers/spm/mt_spm_idle.h | 17 + .../mt8195/drivers/spm/mt_spm_internal.c | 550 ++ .../mt8195/drivers/spm/mt_spm_internal.h | 583 ++ .../mt8195/drivers/spm/mt_spm_pmic_wrap.c | 159 + .../mt8195/drivers/spm/mt_spm_pmic_wrap.h | 45 + .../mediatek/mt8195/drivers/spm/mt_spm_reg.h | 2859 +++++++ .../mt8195/drivers/spm/mt_spm_resource_req.h | 25 + .../mt8195/drivers/spm/mt_spm_suspend.c | 394 + .../mt8195/drivers/spm/mt_spm_suspend.h | 26 + .../mt8195/drivers/spm/mt_spm_vcorefs.c | 526 ++ .../mt8195/drivers/spm/mt_spm_vcorefs.h | 328 + .../drivers/spm/notifier/mt_spm_notifier.h | 21 + .../drivers/spm/notifier/mt_spm_sspm_intc.h | 33 + .../spm/notifier/mt_spm_sspm_notifier.c | 38 + .../mediatek/mt8195/drivers/spm/pcm_def.h | 179 + .../mediatek/mt8195/drivers/spm/sleep_def.h | 151 + .../mediatek/mt8195/drivers/spmc/mtspmc.c | 166 + .../mediatek/mt8195/drivers/spmc/mtspmc.h | 31 + .../mt8195/drivers/spmc/mtspmc_private.h | 183 + .../plat/mediatek/mt8195/include/mcucfg.h | 257 + .../mediatek/mt8195/include/plat_helpers.h | 12 + .../mediatek/mt8195/include/plat_macros.S | 37 + .../mediatek/mt8195/include/plat_mtk_lpm.h | 48 + .../plat/mediatek/mt8195/include/plat_pm.h | 38 + .../mediatek/mt8195/include/plat_private.h | 18 + .../mediatek/mt8195/include/plat_sip_calls.h | 27 + .../mediatek/mt8195/include/platform_def.h | 168 + .../plat/mediatek/mt8195/include/rtc.h | 12 + .../plat/mediatek/mt8195/plat_pm.c | 403 + .../plat/mediatek/mt8195/plat_sip_calls.c | 56 + .../plat/mediatek/mt8195/plat_topology.c | 70 + .../plat/mediatek/mt8195/platform.mk | 108 + .../tegra/common/aarch64/tegra_helpers.S | 453 + .../nvidia/tegra/common/tegra_bl31_setup.c | 348 + .../plat/nvidia/tegra/common/tegra_common.mk | 55 + .../nvidia/tegra/common/tegra_delay_timer.c | 57 + .../plat/nvidia/tegra/common/tegra_fiq_glue.c | 149 + .../plat/nvidia/tegra/common/tegra_gicv2.c | 94 + .../plat/nvidia/tegra/common/tegra_gicv3.c | 218 + .../nvidia/tegra/common/tegra_io_storage.c | 20 + .../plat/nvidia/tegra/common/tegra_pauth.c | 31 + .../plat/nvidia/tegra/common/tegra_platform.c | 369 + .../plat/nvidia/tegra/common/tegra_pm.c | 335 + .../plat/nvidia/tegra/common/tegra_sdei.c | 56 + .../nvidia/tegra/common/tegra_sip_calls.c | 158 + .../tegra/common/tegra_stack_protector.c | 28 + .../plat/nvidia/tegra/drivers/bpmp/bpmp.c | 231 + .../plat/nvidia/tegra/drivers/bpmp_ipc/intf.c | 367 + .../plat/nvidia/tegra/drivers/bpmp_ipc/intf.h | 142 + .../plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c | 654 ++ .../plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h | 50 + .../nvidia/tegra/drivers/flowctrl/flowctrl.c | 322 + .../plat/nvidia/tegra/drivers/gpcdma/gpcdma.c | 188 + .../nvidia/tegra/drivers/memctrl/memctrl_v1.c | 212 + .../nvidia/tegra/drivers/memctrl/memctrl_v2.c | 334 + .../plat/nvidia/tegra/drivers/pmc/pmc.c | 153 + .../nvidia/tegra/drivers/psc/psc_mailbox.c | 66 + .../plat/nvidia/tegra/drivers/smmu/smmu.c | 121 + .../nvidia/tegra/drivers/spe/shared_console.S | 206 + .../plat/nvidia/tegra/include/drivers/bpmp.h | 127 + .../nvidia/tegra/include/drivers/bpmp_ipc.h | 58 + .../nvidia/tegra/include/drivers/flowctrl.h | 98 + .../nvidia/tegra/include/drivers/gpcdma.h | 17 + .../plat/nvidia/tegra/include/drivers/mce.h | 76 + .../nvidia/tegra/include/drivers/memctrl.h | 18 + .../nvidia/tegra/include/drivers/memctrl_v1.h | 57 + .../nvidia/tegra/include/drivers/memctrl_v2.h | 107 + .../plat/nvidia/tegra/include/drivers/pmc.h | 72 + .../tegra/include/drivers/psc_mailbox.h | 13 + .../tegra/include/drivers/security_engine.h | 60 + .../plat/nvidia/tegra/include/drivers/smmu.h | 90 + .../plat/nvidia/tegra/include/drivers/spe.h | 23 + .../nvidia/tegra/include/drivers/tegra_gic.h | 36 + .../plat/nvidia/tegra/include/lib/profiler.h | 20 + .../plat/nvidia/tegra/include/plat_macros.S | 63 + .../plat/nvidia/tegra/include/platform_def.h | 128 + .../tegra/include/t186/tegra186_private.h | 12 + .../nvidia/tegra/include/t186/tegra_def.h | 338 + .../nvidia/tegra/include/t186/tegra_mc_def.h | 398 + .../tegra/include/t194/tegra194_private.h | 16 + .../tegra/include/t194/tegra194_ras_private.h | 263 + .../nvidia/tegra/include/t194/tegra_def.h | 337 + .../nvidia/tegra/include/t210/tegra_def.h | 306 + .../tegra/include/t234/tegra234_private.h | 14 + .../tegra/include/t234/tegra234_ras_private.h | 463 ++ .../nvidia/tegra/include/t234/tegra_def.h | 372 + .../nvidia/tegra/include/t234/tegra_mc_def.h | 685 ++ .../nvidia/tegra/include/tegra_platform.h | 73 + .../plat/nvidia/tegra/include/tegra_private.h | 159 + .../plat/nvidia/tegra/lib/debug/profiler.c | 144 + .../plat/nvidia/tegra/platform.mk | 111 + .../plat/nvidia/tegra/scat/bl31.scat | 284 + .../soc/t186/drivers/include/mce_private.h | 260 + .../tegra/soc/t186/drivers/include/t18x_ari.h | 437 + .../t186/drivers/mce/aarch64/nvg_helpers.S | 31 + .../nvidia/tegra/soc/t186/drivers/mce/ari.c | 564 ++ .../nvidia/tegra/soc/t186/drivers/mce/mce.c | 476 ++ .../nvidia/tegra/soc/t186/drivers/mce/nvg.c | 256 + .../nvidia/tegra/soc/t186/drivers/se/se.c | 276 + .../tegra/soc/t186/drivers/se/se_private.h | 100 + .../plat/nvidia/tegra/soc/t186/plat_memctrl.c | 715 ++ .../tegra/soc/t186/plat_psci_handlers.c | 472 ++ .../nvidia/tegra/soc/t186/plat_secondary.c | 41 + .../plat/nvidia/tegra/soc/t186/plat_setup.c | 422 + .../nvidia/tegra/soc/t186/plat_sip_calls.c | 159 + .../plat/nvidia/tegra/soc/t186/plat_smmu.c | 22 + .../nvidia/tegra/soc/t186/plat_trampoline.S | 41 + .../nvidia/tegra/soc/t186/platform_t186.mk | 80 + .../soc/t194/drivers/include/mce_private.h | 79 + .../tegra/soc/t194/drivers/include/se.h | 15 + .../tegra/soc/t194/drivers/include/t194_nvg.h | 429 + .../t194/drivers/mce/aarch64/nvg_helpers.S | 52 + .../nvidia/tegra/soc/t194/drivers/mce/mce.c | 255 + .../nvidia/tegra/soc/t194/drivers/mce/nvg.c | 262 + .../nvidia/tegra/soc/t194/drivers/se/se.c | 511 ++ .../tegra/soc/t194/drivers/se/se_private.h | 165 + .../plat/nvidia/tegra/soc/t194/plat_memctrl.c | 97 + .../tegra/soc/t194/plat_psci_handlers.c | 527 ++ .../plat/nvidia/tegra/soc/t194/plat_ras.c | 492 ++ .../nvidia/tegra/soc/t194/plat_secondary.c | 83 + .../plat/nvidia/tegra/soc/t194/plat_setup.c | 488 ++ .../nvidia/tegra/soc/t194/plat_sip_calls.c | 103 + .../plat/nvidia/tegra/soc/t194/plat_smmu.c | 35 + .../nvidia/tegra/soc/t194/plat_trampoline.S | 150 + .../nvidia/tegra/soc/t194/platform_t194.mk | 91 + .../tegra/soc/t210/drivers/se/se_private.h | 663 ++ .../soc/t210/drivers/se/security_engine.c | 1071 +++ .../tegra/soc/t210/plat_psci_handlers.c | 609 ++ .../nvidia/tegra/soc/t210/plat_secondary.c | 41 + .../plat/nvidia/tegra/soc/t210/plat_setup.c | 327 + .../nvidia/tegra/soc/t210/plat_sip_calls.c | 97 + .../nvidia/tegra/soc/t210/platform_t210.mk | 65 + .../soc/t234/drivers/include/mce_private.h | 92 + .../tegra/soc/t234/drivers/include/se.h | 13 + .../tegra/soc/t234/drivers/include/t234_ari.h | 265 + .../nvidia/tegra/soc/t234/drivers/mce/ari.c | 628 ++ .../nvidia/tegra/soc/t234/drivers/mce/mce.c | 501 ++ .../nvidia/tegra/soc/t234/drivers/se/se.c | 250 + .../tegra/soc/t234/drivers/se/se_private.h | 61 + .../plat/nvidia/tegra/soc/t234/plat_memctrl.c | 63 + .../tegra/soc/t234/plat_psci_handlers.c | 450 + .../plat/nvidia/tegra/soc/t234/plat_ras.c | 679 ++ .../nvidia/tegra/soc/t234/plat_secondary.c | 27 + .../plat/nvidia/tegra/soc/t234/plat_setup.c | 569 ++ .../nvidia/tegra/soc/t234/plat_sip_calls.c | 88 + .../nvidia/tegra/soc/t234/platform_t234.mk | 106 + .../plat/nxp/common/aarch64/bl31_data.S | 558 ++ .../plat/nxp/common/aarch64/ls_helpers.S | 220 + .../fip_handler/common/plat_def_fip_uuid.h | 51 + .../fip_handler/common/plat_tbbr_img_def.h | 53 + .../common/fip_handler/common/platform_oid.h | 16 + .../common/fip_handler/ddr_fip/ddr_fip_io.mk | 38 + .../fip_handler/ddr_fip/ddr_io_storage.c | 232 + .../fip_handler/ddr_fip/ddr_io_storage.h | 26 + .../nxp/common/fip_handler/fuse_fip/fuse.mk | 100 + .../nxp/common/fip_handler/fuse_fip/fuse_io.h | 27 + .../fip_handler/fuse_fip/fuse_io_storage.c | 223 + .../plat/nxp/common/img_loadr/img_loadr.mk | 21 + .../plat/nxp/common/img_loadr/load_img.c | 79 + .../plat/nxp/common/img_loadr/load_img.h | 14 + .../default/ch_2/soc_default_base_addr.h | 70 + .../default/ch_2/soc_default_helper_macros.h | 83 + .../default/ch_3/soc_default_base_addr.h | 100 + .../default/ch_3/soc_default_helper_macros.h | 98 + .../default/ch_3_2/soc_default_base_addr.h | 88 + .../ch_3_2/soc_default_helper_macros.h | 87 + .../common/include/default/plat_default_def.h | 172 + .../plat/nxp/common/nv_storage/nv_storage.mk | 29 + .../nxp/common/nv_storage/plat_nv_storage.c | 120 + .../nxp/common/nv_storage/plat_nv_storage.h | 40 + .../plat/nxp/common/ocram/aarch64/ocram.S | 71 + .../plat/nxp/common/ocram/ocram.h | 13 + .../plat/nxp/common/ocram/ocram.mk | 14 + .../plat_make_helper/plat_build_macros.mk | 11 + .../plat_make_helper/plat_common_def.mk | 103 + .../common/plat_make_helper/soc_common_def.mk | 117 + .../plat/nxp/common/psci/aarch64/psci_utils.S | 1155 +++ .../plat/nxp/common/psci/include/plat_psci.h | 145 + .../plat/nxp/common/psci/plat_psci.c | 475 ++ .../plat/nxp/common/psci/psci.mk | 35 + .../setup/aarch64/ls_bl2_mem_params_desc.c | 103 + .../plat/nxp/common/setup/common.mk | 105 + .../plat/nxp/common/setup/core.mk | 22 + .../plat/nxp/common/setup/include/bl31_data.h | 61 + .../common/setup/include/ls_interrupt_mgmt.h | 23 + .../plat/nxp/common/setup/include/mmu_def.h | 34 + .../nxp/common/setup/include/plat_common.h | 152 + .../nxp/common/setup/include/plat_macros.S | 22 + .../plat/nxp/common/setup/ls_bl2_el3_setup.c | 303 + .../plat/nxp/common/setup/ls_bl31_setup.c | 212 + .../plat/nxp/common/setup/ls_common.c | 264 + .../plat/nxp/common/setup/ls_err.c | 55 + .../plat/nxp/common/setup/ls_image_load.c | 33 + .../plat/nxp/common/setup/ls_interrupt_mgmt.c | 66 + .../plat/nxp/common/setup/ls_io_storage.c | 556 ++ .../nxp/common/setup/ls_stack_protector.c | 22 + .../plat/nxp/common/sip_svc/aarch64/sipsvc.S | 152 + .../plat/nxp/common/sip_svc/include/sipsvc.h | 80 + .../plat/nxp/common/sip_svc/sip_svc.c | 194 + .../plat/nxp/common/sip_svc/sipsvc.mk | 35 + .../plat/nxp/common/soc_errata/errata.c | 59 + .../plat/nxp/common/soc_errata/errata.h | 15 + .../plat/nxp/common/soc_errata/errata.mk | 26 + .../nxp/common/soc_errata/errata_a008850.c | 42 + .../nxp/common/soc_errata/errata_a009660.c | 14 + .../nxp/common/soc_errata/errata_a010539.c | 26 + .../nxp/common/soc_errata/errata_a050426.c | 201 + .../plat/nxp/common/soc_errata/errata_list.h | 28 + .../plat/nxp/common/tbbr/csf_tbbr.c | 81 + .../plat/nxp/common/tbbr/nxp_rotpk.S | 21 + .../plat/nxp/common/tbbr/tbbr.mk | 162 + .../plat/nxp/common/tbbr/x509_tbbr.c | 105 + .../nxp/common/warm_reset/plat_warm_reset.c | 121 + .../nxp/common/warm_reset/plat_warm_rst.h | 28 + .../plat/nxp/common/warm_reset/warm_reset.mk | 20 + .../plat/nxp/soc-ls1028a/aarch64/ls1028a.S | 1387 ++++ .../nxp/soc-ls1028a/aarch64/ls1028a_helpers.S | 70 + .../plat/nxp/soc-ls1028a/include/soc.h | 149 + .../nxp/soc-ls1028a/ls1028ardb/ddr_init.c | 185 + .../nxp/soc-ls1028a/ls1028ardb/plat_def.h | 76 + .../nxp/soc-ls1028a/ls1028ardb/platform.c | 28 + .../nxp/soc-ls1028a/ls1028ardb/platform.mk | 33 + .../nxp/soc-ls1028a/ls1028ardb/platform_def.h | 13 + .../plat/nxp/soc-ls1028a/ls1028ardb/policy.h | 16 + .../plat/nxp/soc-ls1028a/soc.c | 432 + .../plat/nxp/soc-ls1028a/soc.def | 97 + .../plat/nxp/soc-ls1028a/soc.mk | 113 + .../plat/nxp/soc-ls1043a/aarch64/ls1043a.S | 1637 ++++ .../nxp/soc-ls1043a/aarch64/ls1043a_helpers.S | 70 + .../plat/nxp/soc-ls1043a/include/ns_access.h | 175 + .../plat/nxp/soc-ls1043a/include/soc.h | 234 + .../nxp/soc-ls1043a/ls1043ardb/ddr_init.c | 159 + .../nxp/soc-ls1043a/ls1043ardb/plat_def.h | 79 + .../nxp/soc-ls1043a/ls1043ardb/platform.c | 28 + .../nxp/soc-ls1043a/ls1043ardb/platform.mk | 40 + .../nxp/soc-ls1043a/ls1043ardb/platform_def.h | 13 + .../plat/nxp/soc-ls1043a/ls1043ardb/policy.h | 16 + .../plat/nxp/soc-ls1043a/soc.c | 435 + .../plat/nxp/soc-ls1043a/soc.def | 107 + .../plat/nxp/soc-ls1043a/soc.mk | 114 + .../plat/nxp/soc-ls1046a/aarch64/ls1046a.S | 937 +++ .../nxp/soc-ls1046a/aarch64/ls1046a_helpers.S | 92 + .../plat/nxp/soc-ls1046a/include/ns_access.h | 174 + .../plat/nxp/soc-ls1046a/include/soc.h | 125 + .../nxp/soc-ls1046a/ls1046afrwy/ddr_init.c | 177 + .../nxp/soc-ls1046a/ls1046afrwy/plat_def.h | 79 + .../nxp/soc-ls1046a/ls1046afrwy/platform.c | 28 + .../nxp/soc-ls1046a/ls1046afrwy/platform.mk | 39 + .../soc-ls1046a/ls1046afrwy/platform_def.h | 13 + .../plat/nxp/soc-ls1046a/ls1046afrwy/policy.h | 16 + .../nxp/soc-ls1046a/ls1046aqds/ddr_init.c | 90 + .../nxp/soc-ls1046a/ls1046aqds/plat_def.h | 79 + .../nxp/soc-ls1046a/ls1046aqds/platform.c | 28 + .../nxp/soc-ls1046a/ls1046aqds/platform.mk | 39 + .../nxp/soc-ls1046a/ls1046aqds/platform_def.h | 13 + .../plat/nxp/soc-ls1046a/ls1046aqds/policy.h | 16 + .../nxp/soc-ls1046a/ls1046ardb/ddr_init.c | 267 + .../nxp/soc-ls1046a/ls1046ardb/plat_def.h | 79 + .../nxp/soc-ls1046a/ls1046ardb/platform.c | 28 + .../nxp/soc-ls1046a/ls1046ardb/platform.mk | 38 + .../nxp/soc-ls1046a/ls1046ardb/platform_def.h | 13 + .../plat/nxp/soc-ls1046a/ls1046ardb/policy.h | 16 + .../plat/nxp/soc-ls1046a/soc.c | 395 + .../plat/nxp/soc-ls1046a/soc.def | 107 + .../plat/nxp/soc-ls1046a/soc.mk | 114 + .../plat/nxp/soc-ls1088a/aarch64/ls1088a.S | 1817 ++++ .../nxp/soc-ls1088a/aarch64/ls1088a_helpers.S | 69 + .../plat/nxp/soc-ls1088a/include/soc.h | 229 + .../nxp/soc-ls1088a/ls1088aqds/ddr_init.c | 84 + .../nxp/soc-ls1088a/ls1088aqds/plat_def.h | 81 + .../nxp/soc-ls1088a/ls1088aqds/platform.c | 28 + .../nxp/soc-ls1088a/ls1088aqds/platform.mk | 31 + .../nxp/soc-ls1088a/ls1088aqds/platform_def.h | 13 + .../plat/nxp/soc-ls1088a/ls1088aqds/policy.h | 16 + .../nxp/soc-ls1088a/ls1088ardb/ddr_init.c | 86 + .../nxp/soc-ls1088a/ls1088ardb/plat_def.h | 80 + .../nxp/soc-ls1088a/ls1088ardb/platform.c | 28 + .../nxp/soc-ls1088a/ls1088ardb/platform.mk | 30 + .../nxp/soc-ls1088a/ls1088ardb/platform_def.h | 13 + .../plat/nxp/soc-ls1088a/ls1088ardb/policy.h | 15 + .../plat/nxp/soc-ls1088a/soc.c | 397 + .../plat/nxp/soc-ls1088a/soc.def | 87 + .../plat/nxp/soc-ls1088a/soc.mk | 110 + .../plat/nxp/soc-lx2160a/aarch64/lx2160a.S | 1816 ++++ .../nxp/soc-lx2160a/aarch64/lx2160a_helpers.S | 77 + .../soc-lx2160a/aarch64/lx2160a_warm_rst.S | 229 + .../plat/nxp/soc-lx2160a/ddr_fip.mk | 97 + .../plat/nxp/soc-lx2160a/ddr_sb.mk | 43 + .../plat/nxp/soc-lx2160a/ddr_tbbr.mk | 95 + .../plat/nxp/soc-lx2160a/include/soc.h | 141 + .../nxp/soc-lx2160a/lx2160aqds/ddr_init.c | 355 + .../nxp/soc-lx2160a/lx2160aqds/plat_def.h | 105 + .../nxp/soc-lx2160a/lx2160aqds/platform.c | 29 + .../nxp/soc-lx2160a/lx2160aqds/platform.mk | 51 + .../nxp/soc-lx2160a/lx2160aqds/platform_def.h | 14 + .../plat/nxp/soc-lx2160a/lx2160aqds/policy.h | 38 + .../nxp/soc-lx2160a/lx2160ardb/ddr_init.c | 212 + .../nxp/soc-lx2160a/lx2160ardb/plat_def.h | 105 + .../nxp/soc-lx2160a/lx2160ardb/platform.c | 29 + .../nxp/soc-lx2160a/lx2160ardb/platform.mk | 51 + .../nxp/soc-lx2160a/lx2160ardb/platform_def.h | 14 + .../plat/nxp/soc-lx2160a/lx2160ardb/policy.h | 38 + .../nxp/soc-lx2160a/lx2162aqds/ddr_init.c | 354 + .../nxp/soc-lx2160a/lx2162aqds/plat_def.h | 105 + .../nxp/soc-lx2160a/lx2162aqds/platform.c | 29 + .../nxp/soc-lx2160a/lx2162aqds/platform.mk | 52 + .../nxp/soc-lx2160a/lx2162aqds/platform_def.h | 14 + .../plat/nxp/soc-lx2160a/lx2162aqds/policy.h | 38 + .../plat/nxp/soc-lx2160a/soc.c | 509 ++ .../plat/nxp/soc-lx2160a/soc.def | 116 + .../plat/nxp/soc-lx2160a/soc.mk | 174 + .../plat/qemu/common/aarch32/plat_helpers.S | 139 + .../plat/qemu/common/aarch64/plat_helpers.S | 136 + .../plat/qemu/common/include/plat_macros.S | 26 + .../plat/qemu/common/qemu_bl1_setup.c | 62 + .../qemu/common/qemu_bl2_mem_params_desc.c | 150 + .../plat/qemu/common/qemu_bl2_setup.c | 247 + .../plat/qemu/common/qemu_bl31_setup.c | 113 + .../plat/qemu/common/qemu_common.c | 163 + .../plat/qemu/common/qemu_console.c | 23 + .../plat/qemu/common/qemu_gicv2.c | 44 + .../plat/qemu/common/qemu_gicv3.c | 52 + .../plat/qemu/common/qemu_image_load.c | 34 + .../plat/qemu/common/qemu_io_storage.c | 449 + .../plat/qemu/common/qemu_pm.c | 257 + .../plat/qemu/common/qemu_private.h | 37 + .../plat/qemu/common/qemu_rotpk.S | 15 + .../plat/qemu/common/qemu_spm.c | 147 + .../plat/qemu/common/qemu_spmd_manifest.c | 31 + .../plat/qemu/common/qemu_stack_protector.c | 32 + .../plat/qemu/common/qemu_trusted_boot.c | 36 + .../plat/qemu/common/sp_min/sp_min-qemu.mk | 22 + .../plat/qemu/common/sp_min/sp_min_setup.c | 147 + .../plat/qemu/common/topology.c | 57 + .../plat/qemu/qemu/include/platform_def.h | 273 + .../plat/qemu/qemu/platform.mk | 232 + .../qemu/qemu_sbsa/include/platform_def.h | 378 + .../plat/qemu/qemu_sbsa/platform.mk | 127 + .../plat/qemu/qemu_sbsa/sbsa_pm.c | 237 + .../plat/qemu/qemu_sbsa/sbsa_private.h | 17 + .../plat/qemu/qemu_sbsa/sbsa_topology.c | 63 + .../plat/qti/common/inc/aarch64/plat_macros.S | 106 + .../plat/qti/common/inc/qti_board_def.h | 37 + .../plat/qti/common/inc/qti_cpu.h | 22 + .../plat/qti/common/inc/qti_interrupt_svc.h | 12 + .../plat/qti/common/inc/qti_plat.h | 56 + .../plat/qti/common/inc/qti_rng.h | 14 + .../plat/qti/common/inc/qti_uart_console.h | 19 + .../plat/qti/common/inc/spmi_arb.h | 23 + .../plat/qti/common/src/aarch64/qti_helpers.S | 88 + .../qti/common/src/aarch64/qti_kryo4_gold.S | 83 + .../qti/common/src/aarch64/qti_kryo4_silver.S | 79 + .../qti/common/src/aarch64/qti_kryo6_gold.S | 83 + .../qti/common/src/aarch64/qti_kryo6_silver.S | 79 + .../qti/common/src/aarch64/qti_uart_console.S | 102 + .../plat/qti/common/src/pm_ps_hold.c | 41 + .../plat/qti/common/src/qti_bl31_setup.c | 155 + .../plat/qti/common/src/qti_common.c | 194 + .../plat/qti/common/src/qti_gic_v3.c | 169 + .../plat/qti/common/src/qti_interrupt_svc.c | 65 + .../plat/qti/common/src/qti_pm.c | 287 + .../plat/qti/common/src/qti_rng.c | 53 + .../plat/qti/common/src/qti_stack_protector.c | 26 + .../plat/qti/common/src/qti_syscall.c | 386 + .../plat/qti/common/src/qti_topology.c | 48 + .../plat/qti/common/src/spmi_arb.c | 113 + .../qti/msm8916/aarch64/msm8916_helpers.S | 164 + .../plat/qti/msm8916/aarch64/uartdm_console.S | 154 + .../plat/qti/msm8916/include/msm8916_mmap.h | 41 + .../plat/qti/msm8916/include/plat_macros.S | 27 + .../plat/qti/msm8916/include/platform_def.h | 57 + .../plat/qti/msm8916/include/uartdm_console.h | 12 + .../plat/qti/msm8916/msm8916_bl31_setup.c | 219 + .../plat/qti/msm8916/msm8916_cpu_boot.c | 66 + .../plat/qti/msm8916/msm8916_gicv2.c | 59 + .../plat/qti/msm8916/msm8916_gicv2.h | 12 + .../plat/qti/msm8916/msm8916_pm.c | 59 + .../plat/qti/msm8916/msm8916_pm.h | 12 + .../plat/qti/msm8916/msm8916_topology.c | 35 + .../plat/qti/msm8916/platform.mk | 62 + .../qtiseclib/inc/qtiseclib_cb_interface.h | 59 + .../plat/qti/qtiseclib/inc/qtiseclib_defs.h | 104 + .../qti/qtiseclib/inc/qtiseclib_interface.h | 99 + .../inc/sc7180/qtiseclib_defs_plat.h | 35 + .../inc/sc7280/qtiseclib_defs_plat.h | 45 + .../qtiseclib/src/qtiseclib_cb_interface.c | 211 + .../qtiseclib/src/qtiseclib_interface_stub.c | 114 + .../plat/qti/sc7180/inc/platform_def.h | 199 + .../plat/qti/sc7180/inc/qti_rng_io.h | 15 + .../plat/qti/sc7180/inc/qti_secure_io_cfg.h | 30 + .../plat/qti/sc7180/platform.mk | 119 + .../plat/qti/sc7280/inc/platform_def.h | 199 + .../plat/qti/sc7280/inc/qti_rng_io.h | 15 + .../plat/qti/sc7280/inc/qti_secure_io_cfg.h | 30 + .../plat/qti/sc7280/platform.mk | 119 + .../renesas/common/aarch64/plat_helpers.S | 396 + .../renesas/common/aarch64/platform_common.c | 271 + .../plat/renesas/common/bl2_cpg_init.c | 408 + .../plat/renesas/common/bl2_interrupt_error.c | 109 + .../renesas/common/bl2_plat_mem_params_desc.c | 88 + .../plat/renesas/common/bl2_secure_setting.c | 362 + .../plat/renesas/common/bl31_plat_setup.c | 133 + .../plat/renesas/common/common.mk | 144 + .../plat/renesas/common/include/plat.ld.S | 36 + .../plat/renesas/common/include/plat_macros.S | 88 + .../renesas/common/include/platform_def.h | 200 + .../plat/renesas/common/include/rcar_def.h | 313 + .../renesas/common/include/rcar_private.h | 108 + .../renesas/common/include/rcar_version.h | 17 + .../common/include/registers/axi_registers.h | 246 + .../common/include/registers/cpg_registers.h | 142 + .../include/registers/lifec_registers.h | 144 + .../plat/renesas/common/plat_image_load.c | 38 + .../plat/renesas/common/plat_pm.c | 321 + .../plat/renesas/common/plat_storage.c | 417 + .../plat/renesas/common/plat_topology.c | 47 + .../plat/renesas/common/rcar_common.c | 99 + .../plat/renesas/rcar/bl2_plat_setup.c | 1199 +++ .../plat/renesas/rcar/platform.mk | 371 + .../plat/renesas/rzg/bl2_plat_setup.c | 1020 +++ .../plat/renesas/rzg/platform.mk | 274 + .../rockchip/common/aarch32/plat_helpers.S | 164 + .../rockchip/common/aarch32/platform_common.c | 57 + .../common/aarch32/pmu_sram_cpus_on.S | 56 + .../rockchip/common/aarch64/plat_helpers.S | 163 + .../rockchip/common/aarch64/platform_common.c | 87 + .../common/aarch64/pmu_sram_cpus_on.S | 52 + .../plat/rockchip/common/bl31_plat_setup.c | 102 + .../common/drivers/parameter/ddr_parameter.c | 135 + .../common/drivers/parameter/ddr_parameter.h | 44 + .../rockchip/common/drivers/pmu/pmu_com.h | 122 + .../rockchip/common/include/plat_macros.S | 118 + .../rockchip/common/include/plat_params.h | 14 + .../rockchip/common/include/plat_private.h | 155 + .../common/include/rockchip_sip_svc.h | 27 + .../plat/rockchip/common/params_setup.c | 256 + .../plat/rockchip/common/plat_pm.c | 413 + .../plat/rockchip/common/plat_topology.c | 39 + .../common/pmusram/cpus_on_fixed_addr.S | 48 + .../common/pmusram/cpus_on_fixed_addr.h | 55 + .../plat/rockchip/common/rockchip_gicv2.c | 81 + .../plat/rockchip/common/rockchip_gicv3.c | 95 + .../plat/rockchip/common/rockchip_sip_svc.c | 84 + .../common/rockchip_stack_protector.c | 24 + .../plat/rockchip/common/sp_min_plat_setup.c | 103 + .../px30/drivers/pmu/plat_pmu_macros.S | 21 + .../plat/rockchip/px30/drivers/pmu/pmu.c | 1071 +++ .../plat/rockchip/px30/drivers/pmu/pmu.h | 331 + .../rockchip/px30/drivers/secure/secure.c | 103 + .../rockchip/px30/drivers/secure/secure.h | 65 + .../plat/rockchip/px30/drivers/soc/soc.c | 134 + .../plat/rockchip/px30/drivers/soc/soc.h | 118 + .../plat/rockchip/px30/include/plat.ld.S | 38 + .../rockchip/px30/include/plat_sip_calls.h | 12 + .../plat/rockchip/px30/include/platform_def.h | 118 + .../plat/rockchip/px30/plat_sip_calls.c | 25 + .../plat/rockchip/px30/platform.mk | 73 + .../plat/rockchip/px30/px30_def.h | 176 + .../rk3288/drivers/pmu/plat_pmu_macros.S | 17 + .../plat/rockchip/rk3288/drivers/pmu/pmu.c | 391 + .../plat/rockchip/rk3288/drivers/pmu/pmu.h | 151 + .../rockchip/rk3288/drivers/secure/secure.c | 165 + .../rockchip/rk3288/drivers/secure/secure.h | 102 + .../plat/rockchip/rk3288/drivers/soc/soc.c | 223 + .../plat/rockchip/rk3288/drivers/soc/soc.h | 110 + .../rockchip/rk3288/include/plat_sip_calls.h | 12 + .../rockchip/rk3288/include/plat_sp_min.ld.S | 72 + .../rockchip/rk3288/include/platform_def.h | 101 + .../rk3288/include/shared/bl32_param.h | 26 + .../plat/rockchip/rk3288/plat_sip_calls.c | 25 + .../plat/rockchip/rk3288/platform.mk | 69 + .../plat/rockchip/rk3288/rk3288_def.h | 127 + .../rockchip/rk3288/sp_min/sp_min-rk3288.mk | 8 + .../rk3328/drivers/pmu/plat_pmu_macros.S | 21 + .../plat/rockchip/rk3328/drivers/pmu/pmu.c | 667 ++ .../plat/rockchip/rk3328/drivers/pmu/pmu.h | 129 + .../plat/rockchip/rk3328/drivers/soc/soc.c | 158 + .../plat/rockchip/rk3328/drivers/soc/soc.h | 111 + .../plat/rockchip/rk3328/include/plat.ld.S | 37 + .../rockchip/rk3328/include/platform_def.h | 117 + .../plat/rockchip/rk3328/platform.mk | 75 + .../plat/rockchip/rk3328/rk3328_def.h | 151 + .../rockchip/rk3368/drivers/ddr/ddr_rk3368.c | 482 ++ .../rockchip/rk3368/drivers/ddr/ddr_rk3368.h | 247 + .../ddr/rk3368_ddr_reg_resume_V1.05.bin | 461 ++ .../rk3368/drivers/pmu/plat_pmu_macros.S | 17 + .../plat/rockchip/rk3368/drivers/pmu/pmu.c | 373 + .../plat/rockchip/rk3368/drivers/pmu/pmu.h | 207 + .../plat/rockchip/rk3368/drivers/soc/soc.c | 209 + .../plat/rockchip/rk3368/drivers/soc/soc.h | 141 + .../plat/rockchip/rk3368/include/plat.ld.S | 37 + .../rockchip/rk3368/include/plat_sip_calls.h | 12 + .../rockchip/rk3368/include/platform_def.h | 120 + .../plat/rockchip/rk3368/plat_sip_calls.c | 25 + .../plat/rockchip/rk3368/platform.mk | 67 + .../plat/rockchip/rk3368/rk3368_def.h | 116 + .../plat/rockchip/rk3399/drivers/dp/cdn_dp.c | 70 + .../plat/rockchip/rk3399/drivers/dp/cdn_dp.h | 49 + .../plat/rockchip/rk3399/drivers/dp/hdcp.bin | Bin 0 -> 864 bytes .../plat/rockchip/rk3399/drivers/dram/dfs.c | 2114 +++++ .../plat/rockchip/rk3399/drivers/dram/dfs.h | 50 + .../plat/rockchip/rk3399/drivers/dram/dram.c | 53 + .../plat/rockchip/rk3399/drivers/dram/dram.h | 156 + .../rk3399/drivers/dram/dram_spec_timing.c | 1324 +++ .../rk3399/drivers/dram/dram_spec_timing.h | 507 ++ .../rockchip/rk3399/drivers/dram/suspend.c | 852 ++ .../rockchip/rk3399/drivers/dram/suspend.h | 28 + .../rk3399/drivers/gpio/rk3399_gpio.c | 400 + .../plat/rockchip/rk3399/drivers/m0/Makefile | 125 + .../rk3399/drivers/m0/include/addressmap.h | 15 + .../rk3399/drivers/m0/include/rk3399_mcu.h | 32 + .../rockchip/rk3399/drivers/m0/src/dram.c | 84 + .../rk3399/drivers/m0/src/rk3399m0.ld.S | 26 + .../rockchip/rk3399/drivers/m0/src/startup.c | 92 + .../rk3399/drivers/m0/src/stopwatch.c | 74 + .../rockchip/rk3399/drivers/m0/src/suspend.c | 62 + .../plat/rockchip/rk3399/drivers/pmu/m0_ctl.c | 102 + .../plat/rockchip/rk3399/drivers/pmu/m0_ctl.h | 29 + .../rk3399/drivers/pmu/plat_pmu_macros.S | 136 + .../plat/rockchip/rk3399/drivers/pmu/pmu.c | 1626 ++++ .../plat/rockchip/rk3399/drivers/pmu/pmu.h | 141 + .../plat/rockchip/rk3399/drivers/pmu/pmu_fw.c | 22 + .../plat/rockchip/rk3399/drivers/pwm/pwm.c | 123 + .../plat/rockchip/rk3399/drivers/pwm/pwm.h | 13 + .../rockchip/rk3399/drivers/secure/secure.c | 167 + .../rockchip/rk3399/drivers/secure/secure.h | 105 + .../plat/rockchip/rk3399/drivers/soc/soc.c | 362 + .../plat/rockchip/rk3399/drivers/soc/soc.h | 289 + .../plat/rockchip/rk3399/include/addressmap.h | 19 + .../plat/rockchip/rk3399/include/plat.ld.S | 98 + .../rockchip/rk3399/include/plat_sip_calls.h | 12 + .../rockchip/rk3399/include/platform_def.h | 104 + .../rk3399/include/shared/addressmap_shared.h | 104 + .../rk3399/include/shared/bl31_param.h | 26 + .../rk3399/include/shared/dram_regs.h | 100 + .../rockchip/rk3399/include/shared/m0_param.h | 25 + .../rk3399/include/shared/misc_regs.h | 27 + .../rockchip/rk3399/include/shared/pmu_bits.h | 697 ++ .../rockchip/rk3399/include/shared/pmu_regs.h | 148 + .../plat/rockchip/rk3399/plat_sip_calls.c | 78 + .../plat/rockchip/rk3399/platform.mk | 113 + .../plat/rockchip/rk3399/rk3399_def.h | 65 + .../plat/rpi/common/aarch64/plat_helpers.S | 244 + .../plat/rpi/common/include/rpi_shared.h | 41 + .../plat/rpi/common/rpi3_common.c | 247 + .../plat/rpi/common/rpi3_image_load.c | 36 + .../plat/rpi/common/rpi3_io_storage.c | 271 + .../plat/rpi/common/rpi3_pm.c | 283 + .../plat/rpi/common/rpi3_rotpk.S | 15 + .../plat/rpi/common/rpi3_stack_protector.c | 29 + .../plat/rpi/common/rpi3_topology.c | 58 + .../plat/rpi/common/rpi3_trusted_boot.c | 36 + .../rpi3/aarch64/rpi3_bl2_mem_params_desc.c | 136 + .../plat/rpi/rpi3/include/plat_macros.S | 20 + .../plat/rpi/rpi3/include/platform_def.h | 263 + .../plat/rpi/rpi3/include/rpi_hw.h | 114 + .../plat/rpi/rpi3/platform.mk | 221 + .../plat/rpi/rpi3/rpi3_bl1_setup.c | 101 + .../plat/rpi/rpi3/rpi3_bl2_setup.c | 144 + .../plat/rpi/rpi3/rpi3_bl31_setup.c | 226 + .../plat/rpi/rpi3/rpi_mbox_board.c | 56 + .../plat/rpi/rpi4/aarch64/armstub8_header.S | 37 + .../plat/rpi/rpi4/include/plat.ld.S | 23 + .../plat/rpi/rpi4/include/plat_macros.S | 20 + .../plat/rpi/rpi4/include/platform_def.h | 140 + .../plat/rpi/rpi4/include/rpi_hw.h | 114 + .../plat/rpi/rpi4/platform.mk | 116 + .../plat/rpi/rpi4/rpi4_bl31_setup.c | 304 + .../plat/rpi/rpi4/rpi4_pci_svc.c | 215 + .../socionext/synquacer/drivers/mhu/sq_mhu.c | 98 + .../socionext/synquacer/drivers/mhu/sq_mhu.h | 19 + .../socionext/synquacer/drivers/scp/sq_scmi.c | 244 + .../socionext/synquacer/drivers/scp/sq_scp.c | 21 + .../synquacer/drivers/scpi/sq_scpi.c | 219 + .../synquacer/drivers/scpi/sq_scpi.h | 83 + .../socionext/synquacer/include/plat.ld.S | 31 + .../socionext/synquacer/include/plat_macros.S | 16 + .../synquacer/include/platform_def.h | 171 + .../socionext/synquacer/include/sq_common.h | 54 + .../plat/socionext/synquacer/platform.mk | 69 + .../plat/socionext/synquacer/sq_bl31_setup.c | 212 + .../plat/socionext/synquacer/sq_ccn.c | 45 + .../plat/socionext/synquacer/sq_gicv3.c | 94 + .../plat/socionext/synquacer/sq_helpers.S | 110 + .../plat/socionext/synquacer/sq_psci.c | 207 + .../plat/socionext/synquacer/sq_spm.c | 75 + .../plat/socionext/synquacer/sq_topology.c | 40 + .../plat/socionext/synquacer/sq_xlat_setup.c | 56 + .../socionext/uniphier/include/plat_macros.S | 13 + .../socionext/uniphier/include/platform_def.h | 76 + .../plat/socionext/uniphier/platform.mk | 140 + .../socionext/uniphier/tsp/tsp-uniphier.mk | 9 + .../uniphier/tsp/uniphier_tsp_setup.c | 34 + .../plat/socionext/uniphier/uniphier.h | 76 + .../socionext/uniphier/uniphier_bl2_setup.c | 166 + .../socionext/uniphier/uniphier_bl31_setup.c | 89 + .../socionext/uniphier/uniphier_boot_device.c | 189 + .../plat/socionext/uniphier/uniphier_cci.c | 81 + .../socionext/uniphier/uniphier_console.S | 65 + .../socionext/uniphier/uniphier_console.h | 25 + .../uniphier/uniphier_console_setup.c | 92 + .../plat/socionext/uniphier/uniphier_emmc.c | 308 + .../plat/socionext/uniphier/uniphier_gicv3.c | 116 + .../socionext/uniphier/uniphier_helpers.S | 34 + .../socionext/uniphier/uniphier_image_desc.c | 119 + .../socionext/uniphier/uniphier_io_storage.c | 373 + .../plat/socionext/uniphier/uniphier_nand.c | 283 + .../plat/socionext/uniphier/uniphier_psci.c | 167 + .../plat/socionext/uniphier/uniphier_rotpk.S | 16 + .../plat/socionext/uniphier/uniphier_scp.c | 107 + .../plat/socionext/uniphier/uniphier_smp.S | 29 + .../socionext/uniphier/uniphier_soc_info.c | 57 + .../plat/socionext/uniphier/uniphier_syscnt.c | 12 + .../plat/socionext/uniphier/uniphier_tbbr.c | 40 + .../socionext/uniphier/uniphier_topology.c | 40 + .../plat/socionext/uniphier/uniphier_usb.c | 183 + .../socionext/uniphier/uniphier_xlat_setup.c | 81 + .../plat/st/common/bl2_io_storage.c | 598 ++ .../plat/st/common/bl2_stm32_io_storage.c | 667 ++ .../st/common/include/stm32cubeprogrammer.h | 29 + .../plat/st/common/include/stm32mp_auth.h | 19 + .../plat/st/common/include/stm32mp_common.h | 134 + .../plat/st/common/include/stm32mp_dt.h | 46 + .../plat/st/common/include/stm32mp_efi.h | 15 + .../st/common/include/stm32mp_fconf_getter.h | 31 + .../st/common/include/stm32mp_io_storage.h | 23 + .../common/include/stm32mp_shared_resources.h | 58 + .../plat/st/common/include/usb_dfu.h | 80 + .../plat/st/common/stm32cubeprogrammer_uart.c | 521 ++ .../plat/st/common/stm32cubeprogrammer_usb.c | 196 + .../plat/st/common/stm32mp_auth.c | 95 + .../plat/st/common/stm32mp_common.c | 313 + .../plat/st/common/stm32mp_dt.c | 447 + .../plat/st/common/stm32mp_fconf_io.c | 145 + arm-trusted-firmware/plat/st/common/usb_dfu.c | 538 ++ .../plat/st/stm32mp1/bl2_plat_setup.c | 583 ++ .../plat/st/stm32mp1/include/boot_api.h | 373 + .../plat/st/stm32mp1/include/platform_def.h | 235 + .../st/stm32mp1/include/stm32mp1_dbgmcu.h | 16 + .../st/stm32mp1/include/stm32mp1_private.h | 42 + .../include/stm32mp1_shared_resources.h | 38 + .../plat/st/stm32mp1/include/stm32mp1_smc.h | 67 + .../st/stm32mp1/plat_bl2_mem_params_desc.c | 132 + .../stm32mp1/plat_bl2_stm32_mem_params_desc.c | 103 + .../plat/st/stm32mp1/plat_image_load.c | 48 + .../plat/st/stm32mp1/platform.mk | 494 ++ .../plat/st/stm32mp1/services/bsec_svc.c | 60 + .../plat/st/stm32mp1/services/bsec_svc.h | 19 + .../st/stm32mp1/services/stm32mp1_svc_setup.c | 100 + .../st/stm32mp1/sp_min/sp_min-stm32mp1.mk | 55 + .../plat/st/stm32mp1/sp_min/sp_min_setup.c | 197 + .../plat/st/stm32mp1/stm32mp1.S | 18 + .../plat/st/stm32mp1/stm32mp1.ld.S | 87 + .../plat/st/stm32mp1/stm32mp1_boot_device.c | 169 + .../plat/st/stm32mp1/stm32mp1_dbgmcu.c | 74 + .../plat/st/stm32mp1/stm32mp1_def.h | 636 ++ .../st/stm32mp1/stm32mp1_fconf_firewall.c | 128 + .../plat/st/stm32mp1/stm32mp1_fip_def.h | 106 + .../plat/st/stm32mp1/stm32mp1_gic.c | 92 + .../plat/st/stm32mp1/stm32mp1_helper.S | 269 + .../plat/st/stm32mp1/stm32mp1_pm.c | 243 + .../plat/st/stm32mp1/stm32mp1_private.c | 740 ++ .../plat/st/stm32mp1/stm32mp1_scmi.c | 479 ++ .../plat/st/stm32mp1/stm32mp1_security.c | 136 + .../st/stm32mp1/stm32mp1_shared_resources.c | 596 ++ .../st/stm32mp1/stm32mp1_stack_protector.c | 22 + .../st/stm32mp1/stm32mp1_stm32image_def.h | 73 + .../plat/st/stm32mp1/stm32mp1_syscfg.c | 411 + .../plat/st/stm32mp1/stm32mp1_topology.c | 57 + .../plat/st/stm32mp1/stm32mp1_usb_dfu.c | 423 + .../plat/ti/k3/board/generic/board.mk | 24 + .../ti/k3/board/generic/include/board_def.h | 43 + .../plat/ti/k3/board/lite/board.mk | 24 + .../plat/ti/k3/board/lite/include/board_def.h | 45 + .../k3/common/drivers/sec_proxy/sec_proxy.c | 341 + .../k3/common/drivers/sec_proxy/sec_proxy.h | 82 + .../plat/ti/k3/common/drivers/ti_sci/ti_sci.c | 1688 ++++ .../plat/ti/k3/common/drivers/ti_sci/ti_sci.h | 216 + .../common/drivers/ti_sci/ti_sci_protocol.h | 709 ++ .../plat/ti/k3/common/k3_bl31_setup.c | 197 + .../plat/ti/k3/common/k3_console.c | 21 + .../plat/ti/k3/common/k3_gicv3.c | 90 + .../plat/ti/k3/common/k3_helpers.S | 155 + .../plat/ti/k3/common/k3_psci.c | 256 + .../plat/ti/k3/common/k3_topology.c | 46 + .../plat/ti/k3/common/plat_common.mk | 91 + .../plat/ti/k3/include/k3_console.h | 12 + .../plat/ti/k3/include/k3_gicv3.h | 18 + .../plat/ti/k3/include/plat_macros.S | 21 + .../plat/ti/k3/include/platform_def.h | 191 + arm-trusted-firmware/plat/ti/k3/platform.mk | 14 + .../plat/xilinx/common/include/ipi.h | 77 + .../plat/xilinx/common/include/plat_startup.h | 22 + .../plat/xilinx/common/include/pm_client.h | 32 + .../plat/xilinx/common/include/pm_common.h | 57 + .../plat/xilinx/common/include/pm_ipi.h | 33 + arm-trusted-firmware/plat/xilinx/common/ipi.c | 216 + .../ipi_mailbox_service/ipi_mailbox_svc.c | 133 + .../ipi_mailbox_service/ipi_mailbox_svc.h | 39 + .../plat/xilinx/common/plat_startup.c | 272 + .../plat/xilinx/common/pm_service/pm_ipi.c | 291 + .../xilinx/versal/aarch64/versal_common.c | 54 + .../xilinx/versal/aarch64/versal_helpers.S | 73 + .../plat/xilinx/versal/bl31_versal_setup.c | 204 + .../plat/xilinx/versal/include/plat_ipi.h | 55 + .../plat/xilinx/versal/include/plat_macros.S | 110 + .../xilinx/versal/include/plat_pm_common.h | 26 + .../plat/xilinx/versal/include/plat_private.h | 32 + .../plat/xilinx/versal/include/platform_def.h | 104 + .../plat/xilinx/versal/include/versal_def.h | 144 + .../plat/xilinx/versal/plat_psci.c | 249 + .../plat/xilinx/versal/plat_topology.c | 14 + .../plat/xilinx/versal/plat_versal.c | 21 + .../plat/xilinx/versal/platform.mk | 94 + .../xilinx/versal/pm_service/pm_api_sys.c | 1133 +++ .../xilinx/versal/pm_service/pm_api_sys.h | 99 + .../plat/xilinx/versal/pm_service/pm_client.c | 258 + .../plat/xilinx/versal/pm_service/pm_defs.h | 192 + .../plat/xilinx/versal/pm_service/pm_node.h | 192 + .../xilinx/versal/pm_service/pm_svc_main.c | 436 + .../xilinx/versal/pm_service/pm_svc_main.h | 18 + .../plat/xilinx/versal/sip_svc_setup.c | 102 + .../plat/xilinx/versal/versal_gicv3.c | 186 + .../plat/xilinx/versal/versal_ipi.c | 82 + .../xilinx/zynqmp/aarch64/zynqmp_common.c | 380 + .../xilinx/zynqmp/aarch64/zynqmp_helpers.S | 86 + .../plat/xilinx/zynqmp/bl31_zynqmp_setup.c | 263 + .../plat/xilinx/zynqmp/include/plat_ipi.h | 56 + .../plat/xilinx/zynqmp/include/plat_macros.S | 28 + .../xilinx/zynqmp/include/plat_pm_common.h | 24 + .../plat/xilinx/zynqmp/include/plat_private.h | 33 + .../plat/xilinx/zynqmp/include/platform_def.h | 161 + .../plat/xilinx/zynqmp/include/zynqmp_def.h | 365 + .../plat/xilinx/zynqmp/plat_psci.c | 224 + .../plat/xilinx/zynqmp/plat_topology.c | 12 + .../plat/xilinx/zynqmp/plat_zynqmp.c | 21 + .../plat/xilinx/zynqmp/platform.mk | 125 + .../xilinx/zynqmp/pm_service/pm_api_clock.c | 3010 +++++++ .../xilinx/zynqmp/pm_service/pm_api_clock.h | 333 + .../xilinx/zynqmp/pm_service/pm_api_ioctl.c | 734 ++ .../xilinx/zynqmp/pm_service/pm_api_ioctl.h | 96 + .../xilinx/zynqmp/pm_service/pm_api_pinctrl.c | 2677 ++++++ .../xilinx/zynqmp/pm_service/pm_api_pinctrl.h | 723 ++ .../xilinx/zynqmp/pm_service/pm_api_sys.c | 1804 ++++ .../xilinx/zynqmp/pm_service/pm_api_sys.h | 212 + .../plat/xilinx/zynqmp/pm_service/pm_client.c | 344 + .../plat/xilinx/zynqmp/pm_service/pm_defs.h | 361 + .../xilinx/zynqmp/pm_service/pm_svc_main.c | 612 ++ .../xilinx/zynqmp/pm_service/pm_svc_main.h | 20 + .../plat/xilinx/zynqmp/sip_svc_setup.c | 105 + .../plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk | 8 + .../plat/xilinx/zynqmp/tsp/tsp_plat_setup.c | 65 + .../plat/xilinx/zynqmp/zynqmp_ehf.c | 24 + .../plat/xilinx/zynqmp/zynqmp_ipi.c | 100 + .../plat/xilinx/zynqmp/zynqmp_sdei.c | 37 + arm-trusted-firmware/readme.rst | 51 + .../arm_arch_svc/arm_arch_svc_setup.c | 195 + .../services/spd/opteed/opteed.mk | 18 + .../services/spd/opteed/opteed_common.c | 118 + .../services/spd/opteed/opteed_helpers.S | 79 + .../services/spd/opteed/opteed_main.c | 420 + .../services/spd/opteed/opteed_pm.c | 223 + .../services/spd/opteed/opteed_private.h | 162 + .../services/spd/opteed/teesmc_opteed.h | 123 + .../spd/opteed/teesmc_opteed_macros.h | 17 + .../services/spd/tlkd/tlkd.mk | 14 + .../services/spd/tlkd/tlkd_common.c | 165 + .../services/spd/tlkd/tlkd_helpers.S | 80 + .../services/spd/tlkd/tlkd_main.c | 558 ++ .../services/spd/tlkd/tlkd_pm.c | 109 + .../services/spd/tlkd/tlkd_private.h | 124 + .../spd/trusty/generic-arm64-smcall.c | 116 + .../spd/trusty/generic-arm64-smcall.h | 28 + .../services/spd/trusty/sm_err.h | 22 + .../services/spd/trusty/smcall.h | 82 + .../services/spd/trusty/trusty.c | 541 ++ .../services/spd/trusty/trusty.mk | 18 + .../services/spd/trusty/trusty_helpers.S | 69 + .../services/spd/tspd/tspd.mk | 46 + .../services/spd/tspd/tspd_common.c | 140 + .../services/spd/tspd/tspd_helpers.S | 79 + .../services/spd/tspd/tspd_main.c | 819 ++ .../services/spd/tspd/tspd_pm.c | 254 + .../services/spd/tspd/tspd_private.h | 233 + .../services/std_svc/pci_svc.c | 113 + .../std_svc/rmmd/aarch64/rmmd_helpers.S | 73 + .../services/std_svc/rmmd/rmmd.mk | 19 + .../services/std_svc/rmmd/rmmd_attest.c | 166 + .../std_svc/rmmd/rmmd_initial_context.h | 33 + .../services/std_svc/rmmd/rmmd_main.c | 385 + .../services/std_svc/rmmd/rmmd_private.h | 69 + .../services/std_svc/rmmd/trp/linker.lds | 71 + .../services/std_svc/rmmd/trp/trp.mk | 20 + .../services/std_svc/rmmd/trp/trp_entry.S | 92 + .../services/std_svc/rmmd/trp/trp_main.c | 135 + .../services/std_svc/rmmd/trp/trp_private.h | 63 + .../services/std_svc/sdei/sdei_dispatch.S | 26 + .../services/std_svc/sdei/sdei_event.c | 101 + .../services/std_svc/sdei/sdei_intr_mgmt.c | 774 ++ .../services/std_svc/sdei/sdei_main.c | 1114 +++ .../services/std_svc/sdei/sdei_private.h | 248 + .../services/std_svc/sdei/sdei_state.c | 150 + .../std_svc/spm_mm/aarch64/spm_mm_helpers.S | 74 + .../spm_mm/aarch64/spm_mm_shim_exceptions.S | 128 + .../services/std_svc/spm_mm/spm_mm.mk | 32 + .../services/std_svc/spm_mm/spm_mm_main.c | 353 + .../services/std_svc/spm_mm/spm_mm_private.h | 71 + .../services/std_svc/spm_mm/spm_mm_setup.c | 259 + .../std_svc/spm_mm/spm_mm_shim_private.h | 26 + .../services/std_svc/spm_mm/spm_mm_xlat.c | 159 + .../std_svc/spmd/aarch64/spmd_helpers.S | 73 + .../services/std_svc/spmd/spmd.mk | 26 + .../services/std_svc/spmd/spmd_main.c | 839 ++ .../services/std_svc/spmd/spmd_pm.c | 156 + .../services/std_svc/spmd/spmd_private.h | 105 + .../services/std_svc/std_svc_setup.c | 219 + .../services/std_svc/trng/trng_entropy_pool.c | 151 + .../services/std_svc/trng/trng_entropy_pool.h | 16 + .../services/std_svc/trng/trng_main.c | 143 + arm-trusted-firmware/tools/amlogic/Makefile | 49 + arm-trusted-firmware/tools/amlogic/doimage.c | 94 + .../tools/cert_create/Makefile | 90 + .../tools/cert_create/include/cert.h | 76 + .../tools/cert_create/include/cmd_opt.h | 33 + .../tools/cert_create/include/debug.h | 59 + .../tools/cert_create/include/dualroot/cot.h | 81 + .../tools/cert_create/include/ext.h | 94 + .../tools/cert_create/include/key.h | 92 + .../tools/cert_create/include/sha.h | 12 + .../tools/cert_create/include/tbbr/tbb_cert.h | 30 + .../tools/cert_create/include/tbbr/tbb_ext.h | 47 + .../tools/cert_create/include/tbbr/tbb_key.h | 25 + .../tools/cert_create/src/cert.c | 274 + .../tools/cert_create/src/cmd_opt.c | 59 + .../tools/cert_create/src/dualroot/cot.c | 583 ++ .../tools/cert_create/src/dualroot/cot.mk | 10 + .../tools/cert_create/src/ext.c | 317 + .../tools/cert_create/src/key.c | 240 + .../tools/cert_create/src/main.c | 634 ++ .../tools/cert_create/src/sha.c | 55 + .../tools/cert_create/src/tbbr/tbb_cert.c | 206 + .../tools/cert_create/src/tbbr/tbb_ext.c | 328 + .../tools/cert_create/src/tbbr/tbb_key.c | 59 + .../tools/cert_create/src/tbbr/tbbr.mk | 29 + .../conventional-changelog-tf-a/index.js | 222 + .../conventional-changelog-tf-a/package.json | 13 + .../templates/commit-section.hbs | 17 + .../templates/commit.hbs | 15 + .../templates/footer.hbs | 0 .../templates/header.hbs | 13 + .../templates/note-section.hbs | 13 + .../templates/note.hbs | 3 + .../templates/template.hbs | 9 + .../tools/encrypt_fw/Makefile | 65 + .../tools/encrypt_fw/include/cmd_opt.h | 32 + .../tools/encrypt_fw/include/debug.h | 59 + .../tools/encrypt_fw/include/encrypt.h | 19 + .../tools/encrypt_fw/src/cmd_opt.c | 59 + .../tools/encrypt_fw/src/encrypt.c | 167 + .../tools/encrypt_fw/src/main.c | 224 + arm-trusted-firmware/tools/fiptool/Makefile | 63 + .../tools/fiptool/Makefile.msvc | 37 + arm-trusted-firmware/tools/fiptool/fiptool | Bin 0 -> 56112 bytes arm-trusted-firmware/tools/fiptool/fiptool.c | 1266 +++ arm-trusted-firmware/tools/fiptool/fiptool.h | 54 + .../tools/fiptool/fiptool_platform.h | 31 + .../tools/fiptool/tbbr_config.c | 179 + .../tools/fiptool/tbbr_config.h | 28 + .../tools/fiptool/win_posix.c | 318 + .../tools/fiptool/win_posix.h | 188 + .../tools/marvell/doimage/Makefile | 48 + .../tools/marvell/doimage/doimage.c | 1764 ++++ .../tools/marvell/doimage/doimage.mk | 15 + .../tools/marvell/doimage/secure/aes_key.txt | 1 + .../marvell/doimage/secure/csk_priv_pem0.key | 27 + .../marvell/doimage/secure/csk_priv_pem1.key | 27 + .../marvell/doimage/secure/csk_priv_pem2.key | 27 + .../marvell/doimage/secure/csk_priv_pem3.key | 27 + .../marvell/doimage/secure/kak_priv_pem.key | 27 + .../marvell/doimage/secure/sec_img_7K.cfg | 29 + .../marvell/doimage/secure/sec_img_8K.cfg | 29 + .../tools/memory/print_memory_map.py | 79 + .../cert_create_helper/cert_create_tbbr.mk | 31 + .../include/pdef_tbb_cert.h | 21 + .../cert_create_helper/include/pdef_tbb_ext.h | 25 + .../cert_create_helper/include/pdef_tbb_key.h | 18 + .../cert_create_helper/src/pdef_tbb_cert.c | 62 + .../nxp/cert_create_helper/src/pdef_tbb_ext.c | 108 + .../nxp/cert_create_helper/src/pdef_tbb_key.c | 18 + .../tools/nxp/create_pbl/Makefile | 61 + .../tools/nxp/create_pbl/README | 65 + .../tools/nxp/create_pbl/byte_swap.c | 113 + .../tools/nxp/create_pbl/create_pbl.c | 998 +++ .../tools/nxp/create_pbl/create_pbl.mk | 52 + .../tools/nxp/create_pbl/pbl_ch2.mk | 60 + .../tools/nxp/create_pbl/pbl_ch3.mk | 71 + .../nxp/plat_fiptool/plat_def_uuid_config.c | 90 + .../tools/nxp/plat_fiptool/plat_fiptool.mk | 33 + .../tools/renesas/rcar_layout_create/makefile | 121 + .../tools/renesas/rcar_layout_create/sa0.c | 30 + .../tools/renesas/rcar_layout_create/sa0.ld.S | 28 + .../tools/renesas/rcar_layout_create/sa6.c | 185 + .../tools/renesas/rcar_layout_create/sa6.ld.S | 114 + .../tools/renesas/rzg_layout_create/makefile | 118 + .../tools/renesas/rzg_layout_create/sa0.c | 30 + .../tools/renesas/rzg_layout_create/sa0.ld.S | 28 + .../tools/renesas/rzg_layout_create/sa6.c | 236 + .../tools/renesas/rzg_layout_create/sa6.ld.S | 114 + arm-trusted-firmware/tools/sptool/Makefile | 60 + .../tools/sptool/Makefile.tmk | 30 + .../tools/sptool/sp_mk_generator.py | 157 + arm-trusted-firmware/tools/sptool/sptool.c | 360 + .../tools/stm32image/Makefile | 49 + .../tools/stm32image/stm32image.c | 361 + atf_and_optee_README.txt | 127 + commitFile.txt | 3601 ++++++++ nvbuild.sh | 97 + nvcommon_build.sh | 58 + push_info.txt | 1 + 3858 files changed, 659304 insertions(+) create mode 100644 arm-trusted-firmware/.checkpatch.conf create mode 100644 arm-trusted-firmware/.commitlintrc.js create mode 100644 arm-trusted-firmware/.cz.json create mode 100644 arm-trusted-firmware/.editorconfig create mode 100644 arm-trusted-firmware/.gitreview create mode 100755 arm-trusted-firmware/.husky/commit-msg create mode 100755 arm-trusted-firmware/.husky/commit-msg.commitlint create mode 100755 arm-trusted-firmware/.husky/commit-msg.gerrit create mode 100755 arm-trusted-firmware/.husky/prepare-commit-msg create mode 100755 arm-trusted-firmware/.husky/prepare-commit-msg.cz create mode 100644 arm-trusted-firmware/.versionrc.js create mode 100644 arm-trusted-firmware/Makefile create mode 100644 arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c create mode 100644 arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c create mode 100644 arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S create mode 100644 arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S create mode 100644 arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c create mode 100644 arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c create mode 100644 arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S create mode 100644 arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S create mode 100644 arm-trusted-firmware/bl1/bl1.ld.S create mode 100644 arm-trusted-firmware/bl1/bl1.mk create mode 100644 arm-trusted-firmware/bl1/bl1_fwu.c create mode 100644 arm-trusted-firmware/bl1/bl1_main.c create mode 100644 arm-trusted-firmware/bl1/bl1_private.h create mode 100644 arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c create mode 100644 arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c create mode 100644 arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S create mode 100644 arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S create mode 100644 arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S create mode 100644 arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S create mode 100644 arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S create mode 100644 arm-trusted-firmware/bl2/bl2.ld.S create mode 100644 arm-trusted-firmware/bl2/bl2.mk create mode 100644 arm-trusted-firmware/bl2/bl2_el3.ld.S create mode 100644 arm-trusted-firmware/bl2/bl2_image_load_v2.c create mode 100644 arm-trusted-firmware/bl2/bl2_main.c create mode 100644 arm-trusted-firmware/bl2/bl2_private.h create mode 100644 arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S create mode 100644 arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S create mode 100644 arm-trusted-firmware/bl2u/bl2u.ld.S create mode 100644 arm-trusted-firmware/bl2u/bl2u.mk create mode 100644 arm-trusted-firmware/bl2u/bl2u_main.c create mode 100644 arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S create mode 100644 arm-trusted-firmware/bl31/aarch64/crash_reporting.S create mode 100644 arm-trusted-firmware/bl31/aarch64/ea_delegate.S create mode 100644 arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S create mode 100644 arm-trusted-firmware/bl31/bl31.ld.S create mode 100644 arm-trusted-firmware/bl31/bl31.mk create mode 100644 arm-trusted-firmware/bl31/bl31_context_mgmt.c create mode 100644 arm-trusted-firmware/bl31/bl31_main.c create mode 100644 arm-trusted-firmware/bl31/ehf.c create mode 100644 arm-trusted-firmware/bl31/interrupt_mgmt.c create mode 100644 arm-trusted-firmware/bl32/optee/optee.mk create mode 100644 arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S create mode 100644 arm-trusted-firmware/bl32/sp_min/sp_min.ld.S create mode 100644 arm-trusted-firmware/bl32/sp_min/sp_min.mk create mode 100644 arm-trusted-firmware/bl32/sp_min/sp_min_main.c create mode 100644 arm-trusted-firmware/bl32/sp_min/sp_min_private.h create mode 100644 arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S create mode 100644 arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S create mode 100644 arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S create mode 100644 arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S create mode 100644 arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S create mode 100644 arm-trusted-firmware/bl32/tsp/tsp.ld.S create mode 100644 arm-trusted-firmware/bl32/tsp/tsp.mk create mode 100644 arm-trusted-firmware/bl32/tsp/tsp_interrupt.c create mode 100644 arm-trusted-firmware/bl32/tsp/tsp_main.c create mode 100644 arm-trusted-firmware/bl32/tsp/tsp_private.h create mode 100644 arm-trusted-firmware/bl32/tsp/tsp_timer.c create mode 100644 arm-trusted-firmware/changelog.yaml create mode 100644 arm-trusted-firmware/common/aarch32/debug.S create mode 100644 arm-trusted-firmware/common/aarch64/debug.S create mode 100644 arm-trusted-firmware/common/aarch64/early_exceptions.S create mode 100644 arm-trusted-firmware/common/backtrace/backtrace.c create mode 100644 arm-trusted-firmware/common/backtrace/backtrace.mk create mode 100644 arm-trusted-firmware/common/bl_common.c create mode 100644 arm-trusted-firmware/common/desc_image_load.c create mode 100644 arm-trusted-firmware/common/fdt_fixup.c create mode 100644 arm-trusted-firmware/common/fdt_wrappers.c create mode 100644 arm-trusted-firmware/common/fdt_wrappers.mk create mode 100644 arm-trusted-firmware/common/image_decompress.c create mode 100644 arm-trusted-firmware/common/runtime_svc.c create mode 100644 arm-trusted-firmware/common/tf_crc32.c create mode 100644 arm-trusted-firmware/common/tf_log.c create mode 100644 arm-trusted-firmware/common/uuid.c create mode 100644 arm-trusted-firmware/dco.txt create mode 100644 arm-trusted-firmware/docs/Makefile create mode 100644 arm-trusted-firmware/docs/_static/css/custom.css create mode 100644 arm-trusted-firmware/docs/about/acknowledgements.rst create mode 100644 arm-trusted-firmware/docs/about/contact.rst create mode 100644 arm-trusted-firmware/docs/about/features.rst create mode 100644 arm-trusted-firmware/docs/about/index.rst create mode 100644 arm-trusted-firmware/docs/about/maintainers.rst create mode 100644 arm-trusted-firmware/docs/about/release-information.rst create mode 100644 arm-trusted-firmware/docs/change-log.md create mode 100644 arm-trusted-firmware/docs/components/activity-monitors.rst create mode 100644 arm-trusted-firmware/docs/components/arm-sip-service.rst create mode 100644 arm-trusted-firmware/docs/components/cot-binding.rst create mode 100644 arm-trusted-firmware/docs/components/debugfs-design.rst create mode 100644 arm-trusted-firmware/docs/components/exception-handling.rst create mode 100644 arm-trusted-firmware/docs/components/fconf/amu-bindings.rst create mode 100644 arm-trusted-firmware/docs/components/fconf/fconf_properties.rst create mode 100644 arm-trusted-firmware/docs/components/fconf/index.rst create mode 100644 arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst create mode 100644 arm-trusted-firmware/docs/components/ffa-manifest-binding.rst create mode 100644 arm-trusted-firmware/docs/components/firmware-update.rst create mode 100644 arm-trusted-firmware/docs/components/granule-protection-tables-design.rst create mode 100644 arm-trusted-firmware/docs/components/index.rst create mode 100644 arm-trusted-firmware/docs/components/measured_boot/event_log.rst create mode 100644 arm-trusted-firmware/docs/components/measured_boot/index.rst create mode 100644 arm-trusted-firmware/docs/components/mpmm.rst create mode 100644 arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst create mode 100644 arm-trusted-firmware/docs/components/ras.rst create mode 100644 arm-trusted-firmware/docs/components/realm-management-extension.rst create mode 100644 arm-trusted-firmware/docs/components/romlib-design.rst create mode 100644 arm-trusted-firmware/docs/components/sdei.rst create mode 100644 arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst create mode 100644 arm-trusted-firmware/docs/components/secure-partition-manager.rst create mode 100644 arm-trusted-firmware/docs/components/spd/index.rst create mode 100644 arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst create mode 100644 arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst create mode 100644 arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst create mode 100644 arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst create mode 100644 arm-trusted-firmware/docs/conf.py create mode 100644 arm-trusted-firmware/docs/design/alt-boot-flows.rst create mode 100644 arm-trusted-firmware/docs/design/auth-framework.rst create mode 100644 arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst create mode 100644 arm-trusted-firmware/docs/design/firmware-design.rst create mode 100644 arm-trusted-firmware/docs/design/index.rst create mode 100644 arm-trusted-firmware/docs/design/interrupt-framework-design.rst create mode 100644 arm-trusted-firmware/docs/design/psci-pd-tree.rst create mode 100644 arm-trusted-firmware/docs/design/reset-design.rst create mode 100644 arm-trusted-firmware/docs/design/trusted-board-boot-build.rst create mode 100644 arm-trusted-firmware/docs/design/trusted-board-boot.rst create mode 100644 arm-trusted-firmware/docs/design_documents/cmake_framework.rst create mode 100644 arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst create mode 100644 arm-trusted-firmware/docs/design_documents/index.rst create mode 100644 arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst create mode 100644 arm-trusted-firmware/docs/getting_started/build-options.rst create mode 100644 arm-trusted-firmware/docs/getting_started/docs-build.rst create mode 100644 arm-trusted-firmware/docs/getting_started/image-terminology.rst create mode 100644 arm-trusted-firmware/docs/getting_started/index.rst create mode 100644 arm-trusted-firmware/docs/getting_started/initial-build.rst create mode 100644 arm-trusted-firmware/docs/getting_started/porting-guide.rst create mode 100644 arm-trusted-firmware/docs/getting_started/prerequisites.rst create mode 100644 arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst create mode 100644 arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst create mode 100644 arm-trusted-firmware/docs/getting_started/tools-build.rst create mode 100644 arm-trusted-firmware/docs/global_substitutions.txt create mode 100644 arm-trusted-firmware/docs/glossary.rst create mode 100644 arm-trusted-firmware/docs/index.rst create mode 100644 arm-trusted-firmware/docs/license.rst create mode 100644 arm-trusted-firmware/docs/perf/index.rst create mode 100644 arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst create mode 100644 arm-trusted-firmware/docs/perf/psci-performance-juno.rst create mode 100644 arm-trusted-firmware/docs/perf/tsp.rst create mode 100644 arm-trusted-firmware/docs/plat/allwinner.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/arm-build-options.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/fvp/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/juno/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/morello/index.rst create mode 100644 arm-trusted-firmware/docs/plat/arm/tc/index.rst create mode 100644 arm-trusted-firmware/docs/plat/brcm-stingray.rst create mode 100644 arm-trusted-firmware/docs/plat/deprecated.rst create mode 100644 arm-trusted-firmware/docs/plat/hikey.rst create mode 100644 arm-trusted-firmware/docs/plat/hikey960.rst create mode 100644 arm-trusted-firmware/docs/plat/imx8.rst create mode 100644 arm-trusted-firmware/docs/plat/imx8m.rst create mode 100644 arm-trusted-firmware/docs/plat/index.rst create mode 100644 arm-trusted-firmware/docs/plat/intel-agilex.rst create mode 100644 arm-trusted-firmware/docs/plat/intel-stratix10.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/build.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/armada/porting.rst create mode 100644 arm-trusted-firmware/docs/plat/marvell/index.rst create mode 100644 arm-trusted-firmware/docs/plat/meson-axg.rst create mode 100644 arm-trusted-firmware/docs/plat/meson-g12a.rst create mode 100644 arm-trusted-firmware/docs/plat/meson-gxbb.rst create mode 100644 arm-trusted-firmware/docs/plat/meson-gxl.rst create mode 100644 arm-trusted-firmware/docs/plat/mt8183.rst create mode 100644 arm-trusted-firmware/docs/plat/mt8186.rst create mode 100644 arm-trusted-firmware/docs/plat/mt8192.rst create mode 100644 arm-trusted-firmware/docs/plat/mt8195.rst create mode 100644 arm-trusted-firmware/docs/plat/nvidia-tegra.rst create mode 100644 arm-trusted-firmware/docs/plat/nxp/index.rst create mode 100644 arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst create mode 100644 arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst create mode 100644 arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst create mode 100644 arm-trusted-firmware/docs/plat/poplar.rst create mode 100644 arm-trusted-firmware/docs/plat/qemu-sbsa.rst create mode 100644 arm-trusted-firmware/docs/plat/qemu.rst create mode 100644 arm-trusted-firmware/docs/plat/qti-msm8916.rst create mode 100644 arm-trusted-firmware/docs/plat/qti.rst create mode 100644 arm-trusted-firmware/docs/plat/rcar-gen3.rst create mode 100644 arm-trusted-firmware/docs/plat/rockchip.rst create mode 100644 arm-trusted-firmware/docs/plat/rpi3.rst create mode 100644 arm-trusted-firmware/docs/plat/rpi4.rst create mode 100644 arm-trusted-firmware/docs/plat/rz-g2.rst create mode 100644 arm-trusted-firmware/docs/plat/socionext-uniphier.rst create mode 100644 arm-trusted-firmware/docs/plat/stm32mp1.rst create mode 100644 arm-trusted-firmware/docs/plat/synquacer.rst create mode 100644 arm-trusted-firmware/docs/plat/ti-k3.rst create mode 100644 arm-trusted-firmware/docs/plat/warp7.rst create mode 100644 arm-trusted-firmware/docs/plat/xilinx-versal.rst create mode 100644 arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst create mode 100644 arm-trusted-firmware/docs/process/code-review-guidelines.rst create mode 100644 arm-trusted-firmware/docs/process/coding-guidelines.rst create mode 100644 arm-trusted-firmware/docs/process/coding-style.rst create mode 100644 arm-trusted-firmware/docs/process/commit-style.rst create mode 100644 arm-trusted-firmware/docs/process/contributing.rst create mode 100644 arm-trusted-firmware/docs/process/faq.rst create mode 100644 arm-trusted-firmware/docs/process/index.rst create mode 100644 arm-trusted-firmware/docs/process/platform-compatibility-policy.rst create mode 100644 arm-trusted-firmware/docs/process/security-hardening.rst create mode 100644 arm-trusted-firmware/docs/process/security.rst create mode 100644 arm-trusted-firmware/docs/requirements.in create mode 100644 arm-trusted-firmware/docs/requirements.txt create mode 100644 arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/MMU-600.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/Makefile create mode 100755 arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg create mode 100644 arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg create mode 100644 arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png create mode 100755 arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png create mode 100755 arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/fwu_states.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/int_handling.dia create mode 100644 arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml create mode 100644 arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia create mode 100644 arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia create mode 100644 arm-trusted-firmware/docs/resources/diagrams/romlib_design.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia create mode 100644 arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png create mode 100644 arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia create mode 100644 arm-trusted-firmware/docs/resources/diagrams/xlat_align.png create mode 100644 arm-trusted-firmware/docs/security_advisories/index.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst create mode 100644 arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst create mode 100644 arm-trusted-firmware/docs/threat_model/index.rst create mode 100644 arm-trusted-firmware/docs/threat_model/threat_model.rst create mode 100644 arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst create mode 100644 arm-trusted-firmware/docs/threat_model/threat_model_spm.rst create mode 100644 arm-trusted-firmware/drivers/allwinner/axp/axp803.c create mode 100644 arm-trusted-firmware/drivers/allwinner/axp/axp805.c create mode 100644 arm-trusted-firmware/drivers/allwinner/axp/common.c create mode 100644 arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c create mode 100644 arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c create mode 100644 arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S create mode 100644 arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c create mode 100644 arm-trusted-firmware/drivers/arm/cci/cci.c create mode 100644 arm-trusted-firmware/drivers/arm/ccn/ccn.c create mode 100644 arm-trusted-firmware/drivers/arm/ccn/ccn_private.h create mode 100644 arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c create mode 100644 arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h create mode 100644 arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scp/css_sds.c create mode 100644 arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c create mode 100644 arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S create mode 100644 arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S create mode 100644 arm-trusted-firmware/drivers/arm/css/sds/sds.c create mode 100644 arm-trusted-firmware/drivers/arm/css/sds/sds_private.h create mode 100644 arm-trusted-firmware/drivers/arm/dcc/dcc_console.c create mode 100644 arm-trusted-firmware/drivers/arm/dsu/ppu.c create mode 100644 arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c create mode 100644 arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/common/gic_common.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h create mode 100644 arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk create mode 100644 arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c create mode 100644 arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h create mode 100644 arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S create mode 100644 arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S create mode 100644 arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c create mode 100644 arm-trusted-firmware/drivers/arm/sbsa/sbsa.c create mode 100644 arm-trusted-firmware/drivers/arm/scu/scu.c create mode 100644 arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c create mode 100644 arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c create mode 100644 arm-trusted-firmware/drivers/arm/sp805/sp805.c create mode 100644 arm-trusted-firmware/drivers/arm/tzc/tzc380.c create mode 100644 arm-trusted-firmware/drivers/arm/tzc/tzc400.c create mode 100644 arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h create mode 100644 arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c create mode 100644 arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c create mode 100644 arm-trusted-firmware/drivers/auth/auth_mod.c create mode 100644 arm-trusted-firmware/drivers/auth/crypto_mod.c create mode 100644 arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c create mode 100644 arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c create mode 100644 arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c create mode 100644 arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c create mode 100644 arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk create mode 100644 arm-trusted-firmware/drivers/auth/dualroot/cot.c create mode 100644 arm-trusted-firmware/drivers/auth/img_parser_mod.c create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk create mode 100644 arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c create mode 100644 arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c create mode 100644 arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c create mode 100644 arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c create mode 100644 arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c create mode 100644 arm-trusted-firmware/drivers/brcm/chimp.c create mode 100644 arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c create mode 100644 arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c create mode 100644 arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c create mode 100644 arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c create mode 100644 arm-trusted-firmware/drivers/brcm/i2c/i2c.c create mode 100644 arm-trusted-firmware/drivers/brcm/iproc_gpio.c create mode 100644 arm-trusted-firmware/drivers/brcm/mdio/mdio.c create mode 100644 arm-trusted-firmware/drivers/brcm/ocotp.c create mode 100644 arm-trusted-firmware/drivers/brcm/rng.c create mode 100644 arm-trusted-firmware/drivers/brcm/scp.c create mode 100644 arm-trusted-firmware/drivers/brcm/sotp.c create mode 100644 arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c create mode 100644 arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h create mode 100644 arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c create mode 100644 arm-trusted-firmware/drivers/brcm/spi_flash.c create mode 100644 arm-trusted-firmware/drivers/brcm/spi_sf.c create mode 100644 arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S create mode 100644 arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c create mode 100644 arm-trusted-firmware/drivers/clk/clk.c create mode 100644 arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S create mode 100644 arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S create mode 100644 arm-trusted-firmware/drivers/console/multi_console.c create mode 100644 arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S create mode 100644 arm-trusted-firmware/drivers/delay_timer/delay_timer.c create mode 100644 arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c create mode 100644 arm-trusted-firmware/drivers/fwu/fwu.c create mode 100644 arm-trusted-firmware/drivers/fwu/fwu.mk create mode 100644 arm-trusted-firmware/drivers/gpio/gpio.c create mode 100644 arm-trusted-firmware/drivers/imx/timer/imx_gpt.c create mode 100644 arm-trusted-firmware/drivers/imx/timer/imx_gpt.h create mode 100644 arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S create mode 100644 arm-trusted-firmware/drivers/imx/uart/imx_uart.c create mode 100644 arm-trusted-firmware/drivers/imx/uart/imx_uart.h create mode 100644 arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c create mode 100644 arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h create mode 100644 arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c create mode 100644 arm-trusted-firmware/drivers/io/io_block.c create mode 100644 arm-trusted-firmware/drivers/io/io_dummy.c create mode 100644 arm-trusted-firmware/drivers/io/io_encrypted.c create mode 100644 arm-trusted-firmware/drivers/io/io_fip.c create mode 100644 arm-trusted-firmware/drivers/io/io_memmap.c create mode 100644 arm-trusted-firmware/drivers/io/io_mtd.c create mode 100644 arm-trusted-firmware/drivers/io/io_semihosting.c create mode 100644 arm-trusted-firmware/drivers/io/io_storage.c create mode 100644 arm-trusted-firmware/drivers/marvell/amb_adec.c create mode 100644 arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c create mode 100644 arm-trusted-firmware/drivers/marvell/cache_llc.c create mode 100644 arm-trusted-firmware/drivers/marvell/ccu.c create mode 100644 arm-trusted-firmware/drivers/marvell/comphy.h create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h create mode 100644 arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h create mode 100644 arm-trusted-firmware/drivers/marvell/ddr_phy_access.c create mode 100644 arm-trusted-firmware/drivers/marvell/ddr_phy_access.h create mode 100644 arm-trusted-firmware/drivers/marvell/gwin.c create mode 100644 arm-trusted-firmware/drivers/marvell/io_win.c create mode 100644 arm-trusted-firmware/drivers/marvell/iob.c create mode 100644 arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c create mode 100644 arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h create mode 100644 arm-trusted-firmware/drivers/marvell/mci.c create mode 100644 arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c create mode 100644 arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h create mode 100644 arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c create mode 100644 arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c create mode 100644 arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c create mode 100644 arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c create mode 100644 arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h create mode 100644 arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c create mode 100644 arm-trusted-firmware/drivers/marvell/thermal.c create mode 100644 arm-trusted-firmware/drivers/marvell/uart/a3700_console.S create mode 100644 arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c create mode 100644 arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk create mode 100644 arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c create mode 100644 arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c create mode 100644 arm-trusted-firmware/drivers/mmc/mmc.c create mode 100644 arm-trusted-firmware/drivers/mtd/nand/core.c create mode 100644 arm-trusted-firmware/drivers/mtd/nand/raw_nand.c create mode 100644 arm-trusted-firmware/drivers/mtd/nand/spi_nand.c create mode 100644 arm-trusted-firmware/drivers/mtd/nor/spi_nor.c create mode 100644 arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 create mode 100644 arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c create mode 100644 arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c create mode 100644 arm-trusted-firmware/drivers/nxp/console/16550_console.S create mode 100644 arm-trusted-firmware/drivers/nxp/console/console.mk create mode 100644 arm-trusted-firmware/drivers/nxp/console/console_16550.c create mode 100644 arm-trusted-firmware/drivers/nxp/console/console_pl011.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c create mode 100644 arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c create mode 100644 arm-trusted-firmware/drivers/nxp/csu/csu.c create mode 100644 arm-trusted-firmware/drivers/nxp/csu/csu.mk create mode 100644 arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c create mode 100644 arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h create mode 100644 arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h create mode 100644 arm-trusted-firmware/drivers/nxp/drivers.mk create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h create mode 100644 arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c create mode 100644 arm-trusted-firmware/drivers/nxp/gic/gic.mk create mode 100644 arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c create mode 100644 arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c create mode 100644 arm-trusted-firmware/drivers/nxp/gpio/gpio.mk create mode 100644 arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c create mode 100644 arm-trusted-firmware/drivers/nxp/i2c/i2c.c create mode 100644 arm-trusted-firmware/drivers/nxp/i2c/i2c.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h create mode 100644 arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c create mode 100644 arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk create mode 100644 arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c create mode 100644 arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk create mode 100644 arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk create mode 100644 arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c create mode 100644 arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c create mode 100644 arm-trusted-firmware/drivers/nxp/pmu/pmu.c create mode 100644 arm-trusted-firmware/drivers/nxp/pmu/pmu.mk create mode 100644 arm-trusted-firmware/drivers/nxp/qspi/qspi.c create mode 100644 arm-trusted-firmware/drivers/nxp/qspi/qspi.mk create mode 100644 arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c create mode 100644 arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk create mode 100644 arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk create mode 100644 arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c create mode 100644 arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c create mode 100644 arm-trusted-firmware/drivers/nxp/sfp/sfp.c create mode 100644 arm-trusted-firmware/drivers/nxp/sfp/sfp.mk create mode 100644 arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c create mode 100644 arm-trusted-firmware/drivers/nxp/timer/timer.mk create mode 100644 arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c create mode 100644 arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c create mode 100644 arm-trusted-firmware/drivers/nxp/tzc/tzc.mk create mode 100644 arm-trusted-firmware/drivers/partition/gpt.c create mode 100644 arm-trusted-firmware/drivers/partition/partition.c create mode 100644 arm-trusted-firmware/drivers/rambus/trng_ip_76.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/common.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S create mode 100644 arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/ddr_regs.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_common.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_private.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/pfc_regs.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S create mode 100644 arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/qos_reg.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c create mode 100644 arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h create mode 100644 arm-trusted-firmware/drivers/renesas/common/scif/scif.S create mode 100644 arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/board/board.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/board/board.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c create mode 100644 arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/board/board.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/board/board.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c create mode 100644 arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h create mode 100644 arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c create mode 100644 arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c create mode 100644 arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c create mode 100644 arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/base.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/base.h create mode 100644 arm-trusted-firmware/drivers/scmi-msg/clock.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/clock.h create mode 100644 arm-trusted-firmware/drivers/scmi-msg/common.h create mode 100644 arm-trusted-firmware/drivers/scmi-msg/entry.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/power_domain.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/power_domain.h create mode 100644 arm-trusted-firmware/drivers/scmi-msg/reset_domain.c create mode 100644 arm-trusted-firmware/drivers/scmi-msg/reset_domain.h create mode 100644 arm-trusted-firmware/drivers/scmi-msg/smt.c create mode 100644 arm-trusted-firmware/drivers/st/bsec/bsec2.c create mode 100644 arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c create mode 100644 arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h create mode 100644 arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c create mode 100644 arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c create mode 100644 arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c create mode 100644 arm-trusted-firmware/drivers/st/crypto/stm32_hash.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c create mode 100644 arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c create mode 100644 arm-trusted-firmware/drivers/st/etzpc/etzpc.c create mode 100644 arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c create mode 100644 arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c create mode 100644 arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c create mode 100644 arm-trusted-firmware/drivers/st/io/io_mmc.c create mode 100644 arm-trusted-firmware/drivers/st/io/io_stm32image.c create mode 100644 arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c create mode 100644 arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c create mode 100644 arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c create mode 100644 arm-trusted-firmware/drivers/st/pmic/stpmic1.c create mode 100644 arm-trusted-firmware/drivers/st/regulator/regulator_core.c create mode 100644 arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c create mode 100644 arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c create mode 100644 arm-trusted-firmware/drivers/st/spi/stm32_qspi.c create mode 100644 arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S create mode 100644 arm-trusted-firmware/drivers/st/uart/stm32_uart.c create mode 100644 arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c create mode 100644 arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c create mode 100644 arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c create mode 100644 arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S create mode 100644 arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S create mode 100644 arm-trusted-firmware/drivers/ufs/ufs.c create mode 100644 arm-trusted-firmware/drivers/usb/usb_device.c create mode 100644 arm-trusted-firmware/fdts/a5ds.dts create mode 100644 arm-trusted-firmware/fdts/arm_fpga.dts create mode 100644 arm-trusted-firmware/fdts/corstone700.dtsi create mode 100644 arm-trusted-firmware/fdts/corstone700_fpga.dts create mode 100644 arm-trusted-firmware/fdts/corstone700_fvp.dts create mode 100644 arm-trusted-firmware/fdts/cot_descriptors.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts create mode 100644 arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts create mode 100644 arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-defs.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts create mode 100644 arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts create mode 100644 arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi create mode 100644 arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts create mode 100644 arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts create mode 100644 arm-trusted-firmware/fdts/juno-ethosn.dtsi create mode 100644 arm-trusted-firmware/fdts/juno.dts create mode 100644 arm-trusted-firmware/fdts/morello-fvp.dts create mode 100644 arm-trusted-firmware/fdts/morello-soc.dts create mode 100644 arm-trusted-firmware/fdts/morello.dtsi create mode 100644 arm-trusted-firmware/fdts/n1sdp-multi-chip.dts create mode 100644 arm-trusted-firmware/fdts/n1sdp-single-chip.dts create mode 100644 arm-trusted-firmware/fdts/n1sdp.dtsi create mode 100644 arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi create mode 100644 arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp131.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp133.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp135.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp135f-dk.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp13xa.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13xc.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13xd.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp13xf.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp151.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp153.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp157.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-dk1.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-dk2.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-ed1.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-ev1.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts create mode 100644 arm-trusted-firmware/fdts/stm32mp15xc.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi create mode 100644 arm-trusted-firmware/fdts/tc.dts create mode 100644 arm-trusted-firmware/include/arch/aarch32/arch.h create mode 100644 arm-trusted-firmware/include/arch/aarch32/arch_features.h create mode 100644 arm-trusted-firmware/include/arch/aarch32/arch_helpers.h create mode 100644 arm-trusted-firmware/include/arch/aarch32/asm_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch32/assert_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch32/console_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h create mode 100644 arm-trusted-firmware/include/arch/aarch32/smccc_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/arch.h create mode 100644 arm-trusted-firmware/include/arch/aarch64/arch_features.h create mode 100644 arm-trusted-firmware/include/arch/aarch64/arch_helpers.h create mode 100644 arm-trusted-firmware/include/arch/aarch64/asm_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/assert_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/console_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S create mode 100644 arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h create mode 100644 arm-trusted-firmware/include/bl1/bl1.h create mode 100644 arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h create mode 100644 arm-trusted-firmware/include/bl2/bl2.h create mode 100644 arm-trusted-firmware/include/bl2u/bl2u.h create mode 100644 arm-trusted-firmware/include/bl31/bl31.h create mode 100644 arm-trusted-firmware/include/bl31/ea_handle.h create mode 100644 arm-trusted-firmware/include/bl31/ehf.h create mode 100644 arm-trusted-firmware/include/bl31/interrupt_mgmt.h create mode 100644 arm-trusted-firmware/include/bl32/payloads/tlk.h create mode 100644 arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h create mode 100644 arm-trusted-firmware/include/bl32/tsp/platform_tsp.h create mode 100644 arm-trusted-firmware/include/bl32/tsp/tsp.h create mode 100644 arm-trusted-firmware/include/common/asm_macros_common.S create mode 100644 arm-trusted-firmware/include/common/bl_common.h create mode 100644 arm-trusted-firmware/include/common/bl_common.ld.h create mode 100644 arm-trusted-firmware/include/common/debug.h create mode 100644 arm-trusted-firmware/include/common/desc_image_load.h create mode 100644 arm-trusted-firmware/include/common/ep_info.h create mode 100644 arm-trusted-firmware/include/common/fdt_fixup.h create mode 100644 arm-trusted-firmware/include/common/fdt_wrappers.h create mode 100644 arm-trusted-firmware/include/common/image_decompress.h create mode 100644 arm-trusted-firmware/include/common/interrupt_props.h create mode 100644 arm-trusted-firmware/include/common/nv_cntr_ids.h create mode 100644 arm-trusted-firmware/include/common/param_header.h create mode 100644 arm-trusted-firmware/include/common/romlib.h create mode 100644 arm-trusted-firmware/include/common/runtime_svc.h create mode 100644 arm-trusted-firmware/include/common/tbbr/cot_def.h create mode 100644 arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h create mode 100644 arm-trusted-firmware/include/common/tf_crc32.h create mode 100644 arm-trusted-firmware/include/common/uuid.h create mode 100644 arm-trusted-firmware/include/drivers/allwinner/axp.h create mode 100644 arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h create mode 100644 arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h create mode 100644 arm-trusted-firmware/include/drivers/amlogic/meson_console.h create mode 100644 arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cci.h create mode 100644 arm-trusted-firmware/include/drivers/arm/ccn.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h create mode 100644 arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/css_mhu.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/css_scp.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/css_scpi.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/scmi.h create mode 100644 arm-trusted-firmware/include/drivers/arm/css/sds.h create mode 100644 arm-trusted-firmware/include/drivers/arm/dcc.h create mode 100644 arm-trusted-firmware/include/drivers/arm/dsu.h create mode 100644 arm-trusted-firmware/include/drivers/arm/ethosn.h create mode 100644 arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h create mode 100644 arm-trusted-firmware/include/drivers/arm/gic600_multichip.h create mode 100644 arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h create mode 100644 arm-trusted-firmware/include/drivers/arm/gic_common.h create mode 100644 arm-trusted-firmware/include/drivers/arm/gicv2.h create mode 100644 arm-trusted-firmware/include/drivers/arm/gicv3.h create mode 100644 arm-trusted-firmware/include/drivers/arm/nic_400.h create mode 100644 arm-trusted-firmware/include/drivers/arm/pl011.h create mode 100644 arm-trusted-firmware/include/drivers/arm/pl061_gpio.h create mode 100644 arm-trusted-firmware/include/drivers/arm/sbsa.h create mode 100644 arm-trusted-firmware/include/drivers/arm/scu.h create mode 100644 arm-trusted-firmware/include/drivers/arm/smmu_v3.h create mode 100644 arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h create mode 100644 arm-trusted-firmware/include/drivers/arm/sp805.h create mode 100644 arm-trusted-firmware/include/drivers/arm/tzc380.h create mode 100644 arm-trusted-firmware/include/drivers/arm/tzc400.h create mode 100644 arm-trusted-firmware/include/drivers/arm/tzc_common.h create mode 100644 arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h create mode 100644 arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h create mode 100644 arm-trusted-firmware/include/drivers/auth/auth_common.h create mode 100644 arm-trusted-firmware/include/drivers/auth/auth_mod.h create mode 100644 arm-trusted-firmware/include/drivers/auth/crypto_mod.h create mode 100644 arm-trusted-firmware/include/drivers/auth/img_parser_mod.h create mode 100644 arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h create mode 100644 arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h create mode 100644 arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/chimp.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/dmu.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/fru.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/ocotp.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/scp.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/sf.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/sotp.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/spi.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/spi_flash.h create mode 100644 arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h create mode 100644 arm-trusted-firmware/include/drivers/cadence/cdns_uart.h create mode 100644 arm-trusted-firmware/include/drivers/cfi/v2m_flash.h create mode 100644 arm-trusted-firmware/include/drivers/clk.h create mode 100644 arm-trusted-firmware/include/drivers/console.h create mode 100644 arm-trusted-firmware/include/drivers/console_assertions.h create mode 100644 arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h create mode 100644 arm-trusted-firmware/include/drivers/delay_timer.h create mode 100644 arm-trusted-firmware/include/drivers/dw_ufs.h create mode 100644 arm-trusted-firmware/include/drivers/fwu/fwu.h create mode 100644 arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h create mode 100644 arm-trusted-firmware/include/drivers/generic_delay_timer.h create mode 100644 arm-trusted-firmware/include/drivers/gpio.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_block.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_driver.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_dummy.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_encrypted.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_fip.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_memmap.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_mtd.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_semihosting.h create mode 100644 arm-trusted-firmware/include/drivers/io/io_storage.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/addr_map.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/amb_adec.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/aro.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/cache_llc.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/ccu.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/gwin.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/i2c.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/io_win.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/iob.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/mci.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/thermal.h create mode 100644 arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h create mode 100644 arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h create mode 100644 arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h create mode 100644 arm-trusted-firmware/include/drivers/mentor/mi2cv.h create mode 100644 arm-trusted-firmware/include/drivers/mmc.h create mode 100644 arm-trusted-firmware/include/drivers/nand.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/console/plat_console.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/csu/csu.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/immap.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/opts.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/regs.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ddr/utility.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h create mode 100644 arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h create mode 100644 arm-trusted-firmware/include/drivers/partition/efi.h create mode 100644 arm-trusted-firmware/include/drivers/partition/gpt.h create mode 100644 arm-trusted-firmware/include/drivers/partition/mbr.h create mode 100644 arm-trusted-firmware/include/drivers/partition/partition.h create mode 100644 arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h create mode 100644 arm-trusted-firmware/include/drivers/raw_nand.h create mode 100644 arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h create mode 100644 arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h create mode 100644 arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h create mode 100644 arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h create mode 100644 arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h create mode 100644 arm-trusted-firmware/include/drivers/scmi-msg.h create mode 100644 arm-trusted-firmware/include/drivers/scmi.h create mode 100644 arm-trusted-firmware/include/drivers/spi_mem.h create mode 100644 arm-trusted-firmware/include/drivers/spi_nand.h create mode 100644 arm-trusted-firmware/include/drivers/spi_nor.h create mode 100644 arm-trusted-firmware/include/drivers/st/bsec.h create mode 100644 arm-trusted-firmware/include/drivers/st/bsec2_reg.h create mode 100644 arm-trusted-firmware/include/drivers/st/etzpc.h create mode 100644 arm-trusted-firmware/include/drivers/st/io_mmc.h create mode 100644 arm-trusted-firmware/include/drivers/st/io_stm32image.h create mode 100644 arm-trusted-firmware/include/drivers/st/regulator.h create mode 100644 arm-trusted-firmware/include/drivers/st/regulator_fixed.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_console.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_gpio.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_hash.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_i2c.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_iwdg.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_qspi.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_uart.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_ram.h create mode 100644 arm-trusted-firmware/include/drivers/st/stm32mp_reset.h create mode 100644 arm-trusted-firmware/include/drivers/st/stpmic1.h create mode 100644 arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h create mode 100644 arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h create mode 100644 arm-trusted-firmware/include/drivers/ufs.h create mode 100644 arm-trusted-firmware/include/drivers/usb_device.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h create mode 100644 arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h create mode 100644 arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h create mode 100644 arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h create mode 100644 arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h create mode 100644 arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h create mode 100644 arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h create mode 100644 arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h create mode 100644 arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h create mode 100644 arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h create mode 100644 arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h create mode 100644 arm-trusted-firmware/include/export/README create mode 100644 arm-trusted-firmware/include/export/common/bl_common_exp.h create mode 100644 arm-trusted-firmware/include/export/common/ep_info_exp.h create mode 100644 arm-trusted-firmware/include/export/common/param_header_exp.h create mode 100644 arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h create mode 100644 arm-trusted-firmware/include/export/drivers/gpio_exp.h create mode 100644 arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h create mode 100644 arm-trusted-firmware/include/export/lib/utils_def_exp.h create mode 100644 arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h create mode 100644 arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h create mode 100644 arm-trusted-firmware/include/lib/bakery_lock.h create mode 100644 arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h create mode 100644 arm-trusted-firmware/include/lib/cassert.h create mode 100644 arm-trusted-firmware/include/lib/coreboot.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/denver.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/generic.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h create mode 100644 arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h create mode 100644 arm-trusted-firmware/include/lib/cpus/errata_report.h create mode 100644 arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h create mode 100644 arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h create mode 100644 arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h create mode 100644 arm-trusted-firmware/include/lib/debugfs.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/pubsub.h create mode 100644 arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h create mode 100644 arm-trusted-firmware/include/lib/extensions/amu.h create mode 100644 arm-trusted-firmware/include/lib/extensions/mpam.h create mode 100644 arm-trusted-firmware/include/lib/extensions/pauth.h create mode 100644 arm-trusted-firmware/include/lib/extensions/ras.h create mode 100644 arm-trusted-firmware/include/lib/extensions/ras_arch.h create mode 100644 arm-trusted-firmware/include/lib/extensions/sme.h create mode 100644 arm-trusted-firmware/include/lib/extensions/spe.h create mode 100644 arm-trusted-firmware/include/lib/extensions/sve.h create mode 100644 arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h create mode 100644 arm-trusted-firmware/include/lib/extensions/trbe.h create mode 100644 arm-trusted-firmware/include/lib/extensions/trf.h create mode 100644 arm-trusted-firmware/include/lib/extensions/twed.h create mode 100644 arm-trusted-firmware/include/lib/fconf/fconf.h create mode 100644 arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h create mode 100644 arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h create mode 100644 arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h create mode 100644 arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h create mode 100644 arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/endian_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/limits_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/endian_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/limits_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h create mode 100644 arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h create mode 100644 arm-trusted-firmware/include/lib/libc/arm_acle.h create mode 100644 arm-trusted-firmware/include/lib/libc/assert.h create mode 100644 arm-trusted-firmware/include/lib/libc/cdefs.h create mode 100644 arm-trusted-firmware/include/lib/libc/endian.h create mode 100644 arm-trusted-firmware/include/lib/libc/errno.h create mode 100644 arm-trusted-firmware/include/lib/libc/inttypes.h create mode 100644 arm-trusted-firmware/include/lib/libc/limits.h create mode 100644 arm-trusted-firmware/include/lib/libc/setjmp.h create mode 100644 arm-trusted-firmware/include/lib/libc/stdarg.h create mode 100644 arm-trusted-firmware/include/lib/libc/stdbool.h create mode 100644 arm-trusted-firmware/include/lib/libc/stddef.h create mode 100644 arm-trusted-firmware/include/lib/libc/stdint.h create mode 100644 arm-trusted-firmware/include/lib/libc/stdio.h create mode 100644 arm-trusted-firmware/include/lib/libc/stdlib.h create mode 100644 arm-trusted-firmware/include/lib/libc/string.h create mode 100644 arm-trusted-firmware/include/lib/libc/time.h create mode 100644 arm-trusted-firmware/include/lib/libfdt/fdt.h create mode 100644 arm-trusted-firmware/include/lib/libfdt/libfdt.h create mode 100644 arm-trusted-firmware/include/lib/libfdt/libfdt_env.h create mode 100644 arm-trusted-firmware/include/lib/mmio.h create mode 100644 arm-trusted-firmware/include/lib/mpmm/mpmm.h create mode 100644 arm-trusted-firmware/include/lib/object_pool.h create mode 100644 arm-trusted-firmware/include/lib/optee_utils.h create mode 100644 arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S create mode 100644 arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S create mode 100644 arm-trusted-firmware/include/lib/pmf/pmf.h create mode 100644 arm-trusted-firmware/include/lib/pmf/pmf_helpers.h create mode 100644 arm-trusted-firmware/include/lib/psci/psci.h create mode 100644 arm-trusted-firmware/include/lib/psci/psci_lib.h create mode 100644 arm-trusted-firmware/include/lib/runtime_instr.h create mode 100644 arm-trusted-firmware/include/lib/semihosting.h create mode 100644 arm-trusted-firmware/include/lib/smccc.h create mode 100644 arm-trusted-firmware/include/lib/spinlock.h create mode 100644 arm-trusted-firmware/include/lib/utils.h create mode 100644 arm-trusted-firmware/include/lib/utils_def.h create mode 100644 arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h create mode 100644 arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h create mode 100644 arm-trusted-firmware/include/lib/zlib/tf_gunzip.h create mode 100644 arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S create mode 100644 arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_config.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S create mode 100644 arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/plat_arm.h create mode 100644 arm-trusted-firmware/include/plat/arm/common/smccc_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S create mode 100644 arm-trusted-firmware/include/plat/arm/css/common/css_def.h create mode 100644 arm-trusted-firmware/include/plat/arm/css/common/css_pm.h create mode 100644 arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h create mode 100644 arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h create mode 100644 arm-trusted-firmware/include/plat/brcm/common/bcm_console.h create mode 100644 arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h create mode 100644 arm-trusted-firmware/include/plat/brcm/common/brcm_def.h create mode 100644 arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h create mode 100644 arm-trusted-firmware/include/plat/common/common_def.h create mode 100644 arm-trusted-firmware/include/plat/common/plat_trng.h create mode 100644 arm-trusted-firmware/include/plat/common/platform.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h create mode 100644 arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h create mode 100644 arm-trusted-firmware/include/services/arm_arch_svc.h create mode 100644 arm-trusted-firmware/include/services/ffa_svc.h create mode 100644 arm-trusted-firmware/include/services/pci_svc.h create mode 100644 arm-trusted-firmware/include/services/rmmd_svc.h create mode 100644 arm-trusted-firmware/include/services/sdei.h create mode 100644 arm-trusted-firmware/include/services/sdei_flags.h create mode 100644 arm-trusted-firmware/include/services/spm_core_manifest.h create mode 100644 arm-trusted-firmware/include/services/spm_mm_partition.h create mode 100644 arm-trusted-firmware/include/services/spm_mm_svc.h create mode 100644 arm-trusted-firmware/include/services/spmd_svc.h create mode 100644 arm-trusted-firmware/include/services/std_svc.h create mode 100644 arm-trusted-firmware/include/services/trng_svc.h create mode 100644 arm-trusted-firmware/include/services/trp/platform_trp.h create mode 100644 arm-trusted-firmware/include/tools_share/dualroot_oid.h create mode 100644 arm-trusted-firmware/include/tools_share/firmware_encrypted.h create mode 100644 arm-trusted-firmware/include/tools_share/firmware_image_package.h create mode 100644 arm-trusted-firmware/include/tools_share/sptool.h create mode 100644 arm-trusted-firmware/include/tools_share/tbbr_oid.h create mode 100644 arm-trusted-firmware/include/tools_share/uuid.h create mode 100644 arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c create mode 100644 arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S create mode 100644 arm-trusted-firmware/lib/aarch32/armclang_printf.S create mode 100644 arm-trusted-firmware/lib/aarch32/cache_helpers.S create mode 100644 arm-trusted-firmware/lib/aarch32/misc_helpers.S create mode 100644 arm-trusted-firmware/lib/aarch64/armclang_printf.S create mode 100644 arm-trusted-firmware/lib/aarch64/cache_helpers.S create mode 100644 arm-trusted-firmware/lib/aarch64/misc_helpers.S create mode 100644 arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c create mode 100644 arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk create mode 100644 arm-trusted-firmware/lib/coreboot/coreboot.mk create mode 100644 arm-trusted-firmware/lib/coreboot/coreboot_table.c create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/denver.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/generic.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/rainier.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S create mode 100644 arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S create mode 100644 arm-trusted-firmware/lib/cpus/cpu-ops.mk create mode 100644 arm-trusted-firmware/lib/cpus/errata_report.c create mode 100644 arm-trusted-firmware/lib/debugfs/blobs.h create mode 100644 arm-trusted-firmware/lib/debugfs/debugfs.mk create mode 100644 arm-trusted-firmware/lib/debugfs/debugfs_smc.c create mode 100644 arm-trusted-firmware/lib/debugfs/dev.c create mode 100644 arm-trusted-firmware/lib/debugfs/dev.h create mode 100644 arm-trusted-firmware/lib/debugfs/devc.c create mode 100644 arm-trusted-firmware/lib/debugfs/devfip.c create mode 100644 arm-trusted-firmware/lib/debugfs/devroot.c create mode 100644 arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c create mode 100644 arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S create mode 100644 arm-trusted-firmware/lib/el3_runtime/aarch64/context.S create mode 100644 arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c create mode 100644 arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S create mode 100644 arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c create mode 100644 arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c create mode 100644 arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S create mode 100644 arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c create mode 100644 arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S create mode 100644 arm-trusted-firmware/lib/extensions/amu/amu.mk create mode 100644 arm-trusted-firmware/lib/extensions/amu/amu_private.h create mode 100644 arm-trusted-firmware/lib/extensions/mpam/mpam.c create mode 100644 arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S create mode 100644 arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S create mode 100644 arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S create mode 100644 arm-trusted-firmware/lib/extensions/ras/ras_common.c create mode 100644 arm-trusted-firmware/lib/extensions/ras/std_err_record.c create mode 100644 arm-trusted-firmware/lib/extensions/sme/sme.c create mode 100644 arm-trusted-firmware/lib/extensions/spe/spe.c create mode 100644 arm-trusted-firmware/lib/extensions/sve/sve.c create mode 100644 arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c create mode 100644 arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c create mode 100644 arm-trusted-firmware/lib/extensions/trbe/trbe.c create mode 100644 arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c create mode 100644 arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf.mk create mode 100644 arm-trusted-firmware/lib/fconf/fconf_amu_getter.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf_cot_getter.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c create mode 100644 arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c create mode 100644 arm-trusted-firmware/lib/gpt_rme/gpt_rme.c create mode 100644 arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk create mode 100644 arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h create mode 100644 arm-trusted-firmware/lib/libc/aarch32/memset.S create mode 100644 arm-trusted-firmware/lib/libc/aarch64/memset.S create mode 100644 arm-trusted-firmware/lib/libc/aarch64/setjmp.S create mode 100644 arm-trusted-firmware/lib/libc/abort.c create mode 100644 arm-trusted-firmware/lib/libc/assert.c create mode 100644 arm-trusted-firmware/lib/libc/exit.c create mode 100644 arm-trusted-firmware/lib/libc/libc.mk create mode 100644 arm-trusted-firmware/lib/libc/libc_asm.mk create mode 100644 arm-trusted-firmware/lib/libc/memchr.c create mode 100644 arm-trusted-firmware/lib/libc/memcmp.c create mode 100644 arm-trusted-firmware/lib/libc/memcpy.c create mode 100644 arm-trusted-firmware/lib/libc/memmove.c create mode 100644 arm-trusted-firmware/lib/libc/memrchr.c create mode 100644 arm-trusted-firmware/lib/libc/memset.c create mode 100644 arm-trusted-firmware/lib/libc/printf.c create mode 100644 arm-trusted-firmware/lib/libc/putchar.c create mode 100644 arm-trusted-firmware/lib/libc/puts.c create mode 100644 arm-trusted-firmware/lib/libc/snprintf.c create mode 100644 arm-trusted-firmware/lib/libc/strchr.c create mode 100644 arm-trusted-firmware/lib/libc/strcmp.c create mode 100644 arm-trusted-firmware/lib/libc/strlcat.c create mode 100644 arm-trusted-firmware/lib/libc/strlcpy.c create mode 100644 arm-trusted-firmware/lib/libc/strlen.c create mode 100644 arm-trusted-firmware/lib/libc/strncmp.c create mode 100644 arm-trusted-firmware/lib/libc/strnlen.c create mode 100644 arm-trusted-firmware/lib/libc/strrchr.c create mode 100644 arm-trusted-firmware/lib/libc/strtok.c create mode 100644 arm-trusted-firmware/lib/libc/strtol.c create mode 100644 arm-trusted-firmware/lib/libc/strtoll.c create mode 100644 arm-trusted-firmware/lib/libc/strtoul.c create mode 100644 arm-trusted-firmware/lib/libc/strtoull.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_addresses.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_overlay.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_ro.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_rw.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_strerror.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_sw.c create mode 100644 arm-trusted-firmware/lib/libfdt/fdt_wip.c create mode 100644 arm-trusted-firmware/lib/libfdt/libfdt.mk create mode 100644 arm-trusted-firmware/lib/libfdt/libfdt_internal.h create mode 100644 arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c create mode 100644 arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c create mode 100644 arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S create mode 100644 arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S create mode 100644 arm-trusted-firmware/lib/mpmm/mpmm.c create mode 100644 arm-trusted-firmware/lib/mpmm/mpmm.mk create mode 100644 arm-trusted-firmware/lib/optee/optee_utils.c create mode 100644 arm-trusted-firmware/lib/pmf/pmf_main.c create mode 100644 arm-trusted-firmware/lib/pmf/pmf_smc.c create mode 100644 arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S create mode 100644 arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S create mode 100644 arm-trusted-firmware/lib/psci/psci_common.c create mode 100644 arm-trusted-firmware/lib/psci/psci_lib.mk create mode 100644 arm-trusted-firmware/lib/psci/psci_main.c create mode 100644 arm-trusted-firmware/lib/psci/psci_mem_protect.c create mode 100644 arm-trusted-firmware/lib/psci/psci_off.c create mode 100644 arm-trusted-firmware/lib/psci/psci_on.c create mode 100644 arm-trusted-firmware/lib/psci/psci_private.h create mode 100644 arm-trusted-firmware/lib/psci/psci_setup.c create mode 100644 arm-trusted-firmware/lib/psci/psci_stat.c create mode 100644 arm-trusted-firmware/lib/psci/psci_suspend.c create mode 100644 arm-trusted-firmware/lib/psci/psci_system_off.c create mode 100644 arm-trusted-firmware/lib/romlib/Makefile create mode 100755 arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh create mode 100644 arm-trusted-firmware/lib/romlib/init.s create mode 100644 arm-trusted-firmware/lib/romlib/jmptbl.i create mode 100644 arm-trusted-firmware/lib/romlib/romlib.ld.S create mode 100755 arm-trusted-firmware/lib/romlib/romlib_generator.py create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/wrapper.S create mode 100644 arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S create mode 100644 arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S create mode 100644 arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S create mode 100644 arm-trusted-firmware/lib/semihosting/semihosting.c create mode 100644 arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S create mode 100644 arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S create mode 100644 arm-trusted-firmware/lib/stack_protector/stack_protector.c create mode 100644 arm-trusted-firmware/lib/stack_protector/stack_protector.mk create mode 100644 arm-trusted-firmware/lib/utils/mem_region.c create mode 100644 arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S create mode 100644 arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c create mode 100644 arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk create mode 100644 arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk create mode 100644 arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c create mode 100644 arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c create mode 100644 arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h create mode 100644 arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c create mode 100644 arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c create mode 100644 arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c create mode 100644 arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c create mode 100644 arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c create mode 100644 arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h create mode 100644 arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c create mode 100644 arm-trusted-firmware/lib/zlib/adler32.c create mode 100644 arm-trusted-firmware/lib/zlib/crc32.c create mode 100644 arm-trusted-firmware/lib/zlib/crc32.h create mode 100644 arm-trusted-firmware/lib/zlib/inffast.c create mode 100644 arm-trusted-firmware/lib/zlib/inffast.h create mode 100644 arm-trusted-firmware/lib/zlib/inffixed.h create mode 100644 arm-trusted-firmware/lib/zlib/inflate.c create mode 100644 arm-trusted-firmware/lib/zlib/inflate.h create mode 100644 arm-trusted-firmware/lib/zlib/inftrees.c create mode 100644 arm-trusted-firmware/lib/zlib/inftrees.h create mode 100644 arm-trusted-firmware/lib/zlib/tf_gunzip.c create mode 100644 arm-trusted-firmware/lib/zlib/zconf.h create mode 100644 arm-trusted-firmware/lib/zlib/zlib.h create mode 100644 arm-trusted-firmware/lib/zlib/zlib.mk create mode 100644 arm-trusted-firmware/lib/zlib/zutil.c create mode 100644 arm-trusted-firmware/lib/zlib/zutil.h create mode 100644 arm-trusted-firmware/license.rst create mode 100644 arm-trusted-firmware/licenses/LICENSE.MIT create mode 100644 arm-trusted-firmware/make_helpers/armv7-a-cpus.mk create mode 100644 arm-trusted-firmware/make_helpers/build_env.mk create mode 100644 arm-trusted-firmware/make_helpers/build_macros.mk create mode 100644 arm-trusted-firmware/make_helpers/cygwin.mk create mode 100644 arm-trusted-firmware/make_helpers/defaults.mk create mode 100644 arm-trusted-firmware/make_helpers/msys.mk create mode 100644 arm-trusted-firmware/make_helpers/plat_helpers.mk create mode 100644 arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk create mode 100644 arm-trusted-firmware/make_helpers/unix.mk create mode 100644 arm-trusted-firmware/make_helpers/windows.mk create mode 100644 arm-trusted-firmware/package-lock.json create mode 100644 arm-trusted-firmware/package.json create mode 100644 arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk create mode 100644 arm-trusted-firmware/plat/allwinner/common/arisc_off.S create mode 100644 arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h create mode 100644 arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/allwinner/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h create mode 100644 arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h create mode 100644 arm-trusted-firmware/plat/allwinner/common/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_common.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_security.c create mode 100644 arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk create mode 100644 arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c create mode 100644 arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/amlogic/axg/axg_common.c create mode 100644 arm-trusted-firmware/plat/amlogic/axg/axg_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/axg/axg_pm.c create mode 100644 arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/axg/platform.mk create mode 100644 arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_console.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_efuse.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_mhu.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_scpi.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_thermal.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/aml_topology.c create mode 100644 arm-trusted-firmware/plat/amlogic/common/include/aml_private.h create mode 100644 arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/g12a/platform.mk create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/gxbb/platform.mk create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/amlogic/gxl/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S create mode 100644 arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/common/board_common.mk create mode 100644 arm-trusted-firmware/plat/arm/board/common/protpk/README create mode 100644 arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S create mode 100644 arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin create mode 100644 arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem create mode 100644 arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk create mode 100644 arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/juno/jmptbl.i create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_common.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_pm.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_trng.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/juno/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk create mode 100644 arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk create mode 100644 arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S create mode 100644 arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/morello/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk create mode 100644 arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts create mode 100644 arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h create mode 100644 arm-trusted-firmware/plat/arm/board/tc/platform.mk create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_err.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_plat.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_security.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_topology.c create mode 100644 arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c create mode 100644 arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c create mode 100644 arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_cci.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_ccn.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_common.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_common.mk create mode 100644 arm-trusted-firmware/plat/arm/common/arm_console.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_err.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_gicv2.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_gicv3.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_image_load.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_io_storage.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_pm.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_sip_svc.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_topology.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_tzc400.c create mode 100644 arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c create mode 100644 arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c create mode 100644 arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk create mode 100644 arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk create mode 100644 arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c create mode 100644 arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk create mode 100644 arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_common.mk create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_pm.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/css_topology.c create mode 100644 arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c create mode 100644 arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk create mode 100644 arm-trusted-firmware/plat/arm/soc/common/soc_css.mk create mode 100644 arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/bcm_console.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/board_common.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/board_common.mk create mode 100644 arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/chip_id.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/err.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/plat_setup.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/platform_common.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/sbl_util.c create mode 100644 arm-trusted-firmware/plat/brcm/board/common/sbl_util.h create mode 100644 arm-trusted-firmware/plat/brcm/board/common/timer_sync.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/plat_emmc.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/platform.mk create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c create mode 100644 arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_ccn.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_common.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_image_load.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_mhu.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_mhu.h create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_scpi.c create mode 100644 arm-trusted-firmware/plat/brcm/common/brcm_scpi.h create mode 100644 arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S create mode 100644 arm-trusted-firmware/plat/common/aarch32/plat_common.c create mode 100644 arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c create mode 100644 arm-trusted-firmware/plat/common/aarch32/platform_helpers.S create mode 100644 arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S create mode 100644 arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S create mode 100644 arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S create mode 100644 arm-trusted-firmware/plat/common/aarch64/plat_common.c create mode 100644 arm-trusted-firmware/plat/common/aarch64/plat_ehf.c create mode 100644 arm-trusted-firmware/plat/common/aarch64/platform_helpers.S create mode 100644 arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S create mode 100644 arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S create mode 100644 arm-trusted-firmware/plat/common/plat_bl1_common.c create mode 100644 arm-trusted-firmware/plat/common/plat_bl_common.c create mode 100644 arm-trusted-firmware/plat/common/plat_gicv2.c create mode 100644 arm-trusted-firmware/plat/common/plat_gicv3.c create mode 100644 arm-trusted-firmware/plat/common/plat_log_common.c create mode 100644 arm-trusted-firmware/plat/common/plat_psci_common.c create mode 100644 arm-trusted-firmware/plat/common/plat_spmd_manifest.c create mode 100644 arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c create mode 100644 arm-trusted-firmware/plat/common/ubsan.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey/platform.mk create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/platform.mk create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c create mode 100644 arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c create mode 100644 arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S create mode 100644 arm-trusted-firmware/plat/imx/common/imx7_clock.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx8_helpers.S create mode 100644 arm-trusted-firmware/plat/imx/common/imx8_psci.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx8_topology.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_aips.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_caam.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_clock.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_csu.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_ehf.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_io_mux.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_io_storage.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_sdei.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_sip_handler.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_sip_svc.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_snvs.c create mode 100644 arm-trusted-firmware/plat/imx/common/imx_uart_console.S create mode 100644 arm-trusted-firmware/plat/imx/common/imx_wdog.c create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_aips.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_caam.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_clock.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_csu.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_hab.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_snvs.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_uart.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/imx_wdog.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/plat_imx8.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/sci.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h create mode 100644 arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h create mode 100644 arm-trusted-firmware/plat/imx/common/lpuart_console.S create mode 100644 arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/ipc.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/sci_api.mk create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h create mode 100644 arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7.mk create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S create mode 100644 arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h create mode 100644 arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h create mode 100644 arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/gpc_common.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/gpc.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h create mode 100644 arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h create mode 100644 arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h create mode 100644 arm-trusted-firmware/plat/imx/imx8qm/platform.mk create mode 100644 arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c create mode 100644 arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h create mode 100644 arm-trusted-firmware/plat/imx/imx8qx/platform.mk create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/platform.mk create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c create mode 100644 arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h create mode 100644 arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c create mode 100644 arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c create mode 100644 arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h create mode 100644 arm-trusted-firmware/plat/intel/soc/n5x/platform.mk create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c create mode 100644 arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h create mode 100644 arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c create mode 100644 arm-trusted-firmware/plat/marvell/marvell.mk create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c create mode 100644 arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h create mode 100644 arm-trusted-firmware/plat/mediatek/common/params_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/common/plat_params.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt6795/scu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8173/scu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8183/scu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8186/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8192/platform.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c create mode 100644 arm-trusted-firmware/plat/mediatek/mt8195/platform.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/platform.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S create mode 100644 arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h create mode 100644 arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c create mode 100644 arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c create mode 100644 arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h create mode 100644 arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h create mode 100644 arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c create mode 100644 arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h create mode 100644 arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S create mode 100644 arm-trusted-firmware/plat/nxp/common/ocram/ocram.h create mode 100644 arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S create mode 100644 arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h create mode 100644 arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c create mode 100644 arm-trusted-firmware/plat/nxp/common/psci/psci.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/common.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/core.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_common.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_err.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c create mode 100644 arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c create mode 100644 arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S create mode 100644 arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h create mode 100644 arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c create mode 100644 arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c create mode 100644 arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h create mode 100644 arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c create mode 100644 arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S create mode 100644 arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk create mode 100644 arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c create mode 100644 arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c create mode 100644 arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h create mode 100644 arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def create mode 100644 arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def create mode 100644 arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk create mode 100644 arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/qemu/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_common.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_console.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_image_load.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_pm.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_private.h create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_spm.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c create mode 100644 arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk create mode 100644 arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/qemu/common/topology.c create mode 100644 arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/qemu/qemu/platform.mk create mode 100644 arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk create mode 100644 arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c create mode 100644 arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h create mode 100644 arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c create mode 100644 arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_plat.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_rng.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h create mode 100644 arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S create mode 100644 arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_common.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_pm.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_rng.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_syscall.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/qti_topology.c create mode 100644 arm-trusted-firmware/plat/qti/common/src/spmi_arb.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S create mode 100644 arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S create mode 100644 arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h create mode 100644 arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h create mode 100644 arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c create mode 100644 arm-trusted-firmware/plat/qti/msm8916/platform.mk create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c create mode 100644 arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c create mode 100644 arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h create mode 100644 arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h create mode 100644 arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h create mode 100644 arm-trusted-firmware/plat/qti/sc7180/platform.mk create mode 100644 arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h create mode 100644 arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h create mode 100644 arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h create mode 100644 arm-trusted-firmware/plat/qti/sc7280/platform.mk create mode 100644 arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c create mode 100644 arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c create mode 100644 arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c create mode 100644 arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/renesas/common/common.mk create mode 100644 arm-trusted-firmware/plat/renesas/common/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/renesas/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/renesas/common/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/rcar_def.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/rcar_private.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/rcar_version.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h create mode 100644 arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h create mode 100644 arm-trusted-firmware/plat/renesas/common/plat_image_load.c create mode 100644 arm-trusted-firmware/plat/renesas/common/plat_pm.c create mode 100644 arm-trusted-firmware/plat/renesas/common/plat_storage.c create mode 100644 arm-trusted-firmware/plat/renesas/common/plat_topology.c create mode 100644 arm-trusted-firmware/plat/renesas/common/rcar_common.c create mode 100644 arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/renesas/rcar/platform.mk create mode 100644 arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/renesas/rzg/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/include/plat_params.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/params_setup.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/plat_pm.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/plat_topology.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S create mode 100644 arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h create mode 100644 arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c create mode 100644 arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c create mode 100644 arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h create mode 100644 arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/rockchip/px30/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/px30/px30_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/platform.mk create mode 100644 arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h create mode 100644 arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S create mode 100644 arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_common.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_pm.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_topology.c create mode 100644 arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/platform.mk create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/platform.mk create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/platform.mk create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c create mode 100644 arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/platform.mk create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier.h create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c create mode 100644 arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c create mode 100644 arm-trusted-firmware/plat/st/common/bl2_io_storage.c create mode 100644 arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_common.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h create mode 100644 arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h create mode 100644 arm-trusted-firmware/plat/st/common/include/usb_dfu.h create mode 100644 arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c create mode 100644 arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c create mode 100644 arm-trusted-firmware/plat/st/common/stm32mp_auth.c create mode 100644 arm-trusted-firmware/plat/st/common/stm32mp_common.c create mode 100644 arm-trusted-firmware/plat/st/common/stm32mp_dt.c create mode 100644 arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c create mode 100644 arm-trusted-firmware/plat/st/common/usb_dfu.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/platform.mk create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c create mode 100644 arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c create mode 100644 arm-trusted-firmware/plat/ti/k3/board/generic/board.mk create mode 100644 arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h create mode 100644 arm-trusted-firmware/plat/ti/k3/board/lite/board.mk create mode 100644 arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h create mode 100644 arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h create mode 100644 arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h create mode 100644 arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_console.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_psci.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/k3_topology.c create mode 100644 arm-trusted-firmware/plat/ti/k3/common/plat_common.mk create mode 100644 arm-trusted-firmware/plat/ti/k3/include/k3_console.h create mode 100644 arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h create mode 100644 arm-trusted-firmware/plat/ti/k3/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/ti/k3/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/ti/k3/platform.mk create mode 100644 arm-trusted-firmware/plat/xilinx/common/include/ipi.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/include/pm_client.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/include/pm_common.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/ipi.c create mode 100644 arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c create mode 100644 arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h create mode 100644 arm-trusted-firmware/plat/xilinx/common/plat_startup.c create mode 100644 arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S create mode 100644 arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/plat_psci.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/plat_topology.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/plat_versal.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/platform.mk create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h create mode 100644 arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c create mode 100644 arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c create mode 100644 arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c create mode 100644 arm-trusted-firmware/readme.rst create mode 100644 arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed.mk create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed_common.c create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed_helpers.S create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed_main.c create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed_pm.c create mode 100644 arm-trusted-firmware/services/spd/opteed/opteed_private.h create mode 100644 arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h create mode 100644 arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd.mk create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd_common.c create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd_main.c create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c create mode 100644 arm-trusted-firmware/services/spd/tlkd/tlkd_private.h create mode 100644 arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c create mode 100644 arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h create mode 100644 arm-trusted-firmware/services/spd/trusty/sm_err.h create mode 100644 arm-trusted-firmware/services/spd/trusty/smcall.h create mode 100644 arm-trusted-firmware/services/spd/trusty/trusty.c create mode 100644 arm-trusted-firmware/services/spd/trusty/trusty.mk create mode 100644 arm-trusted-firmware/services/spd/trusty/trusty_helpers.S create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd.mk create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd_common.c create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd_helpers.S create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd_main.c create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd_pm.c create mode 100644 arm-trusted-firmware/services/spd/tspd/tspd_private.h create mode 100644 arm-trusted-firmware/services/std_svc/pci_svc.c create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c create mode 100644 arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_event.c create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_main.c create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_private.h create mode 100644 arm-trusted-firmware/services/std_svc/sdei/sdei_state.c create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h create mode 100644 arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c create mode 100644 arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S create mode 100644 arm-trusted-firmware/services/std_svc/spmd/spmd.mk create mode 100644 arm-trusted-firmware/services/std_svc/spmd/spmd_main.c create mode 100644 arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c create mode 100644 arm-trusted-firmware/services/std_svc/spmd/spmd_private.h create mode 100644 arm-trusted-firmware/services/std_svc/std_svc_setup.c create mode 100644 arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c create mode 100644 arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h create mode 100644 arm-trusted-firmware/services/std_svc/trng/trng_main.c create mode 100644 arm-trusted-firmware/tools/amlogic/Makefile create mode 100644 arm-trusted-firmware/tools/amlogic/doimage.c create mode 100644 arm-trusted-firmware/tools/cert_create/Makefile create mode 100644 arm-trusted-firmware/tools/cert_create/include/cert.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/cmd_opt.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/debug.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/ext.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/key.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/sha.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h create mode 100644 arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h create mode 100644 arm-trusted-firmware/tools/cert_create/src/cert.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/cmd_opt.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk create mode 100644 arm-trusted-firmware/tools/cert_create/src/ext.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/key.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/main.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/sha.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c create mode 100644 arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs create mode 100644 arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs create mode 100644 arm-trusted-firmware/tools/encrypt_fw/Makefile create mode 100644 arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h create mode 100644 arm-trusted-firmware/tools/encrypt_fw/include/debug.h create mode 100644 arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h create mode 100644 arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c create mode 100644 arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c create mode 100644 arm-trusted-firmware/tools/encrypt_fw/src/main.c create mode 100644 arm-trusted-firmware/tools/fiptool/Makefile create mode 100644 arm-trusted-firmware/tools/fiptool/Makefile.msvc create mode 100755 arm-trusted-firmware/tools/fiptool/fiptool create mode 100644 arm-trusted-firmware/tools/fiptool/fiptool.c create mode 100644 arm-trusted-firmware/tools/fiptool/fiptool.h create mode 100644 arm-trusted-firmware/tools/fiptool/fiptool_platform.h create mode 100644 arm-trusted-firmware/tools/fiptool/tbbr_config.c create mode 100644 arm-trusted-firmware/tools/fiptool/tbbr_config.h create mode 100644 arm-trusted-firmware/tools/fiptool/win_posix.c create mode 100644 arm-trusted-firmware/tools/fiptool/win_posix.h create mode 100644 arm-trusted-firmware/tools/marvell/doimage/Makefile create mode 100644 arm-trusted-firmware/tools/marvell/doimage/doimage.c create mode 100644 arm-trusted-firmware/tools/marvell/doimage/doimage.mk create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg create mode 100644 arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg create mode 100755 arm-trusted-firmware/tools/memory/print_memory_map.py create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c create mode 100644 arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/Makefile create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/README create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk create mode 100644 arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk create mode 100644 arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c create mode 100644 arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk create mode 100644 arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile create mode 100644 arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c create mode 100644 arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S create mode 100644 arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c create mode 100644 arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S create mode 100644 arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile create mode 100644 arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c create mode 100644 arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S create mode 100644 arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c create mode 100644 arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S create mode 100644 arm-trusted-firmware/tools/sptool/Makefile create mode 100644 arm-trusted-firmware/tools/sptool/Makefile.tmk create mode 100755 arm-trusted-firmware/tools/sptool/sp_mk_generator.py create mode 100644 arm-trusted-firmware/tools/sptool/sptool.c create mode 100644 arm-trusted-firmware/tools/stm32image/Makefile create mode 100644 arm-trusted-firmware/tools/stm32image/stm32image.c create mode 100644 atf_and_optee_README.txt create mode 100644 commitFile.txt create mode 100755 nvbuild.sh create mode 100755 nvcommon_build.sh create mode 100644 push_info.txt diff --git a/arm-trusted-firmware/.checkpatch.conf b/arm-trusted-firmware/.checkpatch.conf new file mode 100644 index 0000000..baa983d --- /dev/null +++ b/arm-trusted-firmware/.checkpatch.conf @@ -0,0 +1,91 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Configure how the Linux checkpatch script should be invoked in the context of +# the Trusted Firmware source tree. +# + +# This is not Linux so don't expect a Linux tree! +--no-tree + +# The Linux kernel expects the SPDX license tag in the first line of each file. +# We don't follow this in the Trusted Firmware. +--ignore SPDX_LICENSE_TAG + +# This clarifes the lines indications in the report. +# +# E.g.: +# Without this option, we have the following output: +# #333: FILE: drivers/arm/gic/arm_gic.c:160: +# So we have 2 lines indications (333 and 160), which is confusing. +# We only care about the position in the source file. +# +# With this option, it becomes: +# drivers/arm/gic/arm_gic.c:160: +--showfile + +# Don't show some messages like the list of ignored types or the suggestion to +# use "--fix" or report changes to the maintainers. +--quiet + +# +# Ignore the following message types, as they don't necessarily make sense in +# the context of the Trusted Firmware. +# + +# COMPLEX_MACRO generates false positives. +--ignore COMPLEX_MACRO + +# Commit messages might contain a Gerrit Change-Id. +--ignore GERRIT_CHANGE_ID + +# Do not check the format of commit messages, as Gerrit's merge commits do not +# preserve it. +--ignore GIT_COMMIT_ID + +# FILE_PATH_CHANGES reports this kind of message: +# "added, moved or deleted file(s), does MAINTAINERS need updating?" +# We do not use this MAINTAINERS file process in TF. +--ignore FILE_PATH_CHANGES + +# AVOID_EXTERNS reports this kind of messages: +# "externs should be avoided in .c files" +# We don't follow this convention in TF. +--ignore AVOID_EXTERNS + +# NEW_TYPEDEFS reports this kind of messages: +# "do not add new typedefs" +# We allow adding new typedefs in TF. +--ignore NEW_TYPEDEFS + +# Avoid "Does not appear to be a unified-diff format patch" message +--ignore NOT_UNIFIED_DIFF + +# VOLATILE reports this kind of messages: +# "Use of volatile is usually wrong: see Documentation/volatile-considered-harmful.txt" +# We allow the usage of the volatile keyword in TF. +--ignore VOLATILE + +# BRACES reports this kind of messages: +# braces {} are not necessary for any arm of this statement +--ignore BRACES + +# PREFER_KERNEL_TYPES reports this kind of messages (when using --strict): +# "Prefer kernel type 'u32' over 'uint32_t'" +--ignore PREFER_KERNEL_TYPES + +# USLEEP_RANGE reports this kind of messages (when using --strict): +# "usleep_range is preferred over udelay; see Documentation/timers/timers-howto.txt" +--ignore USLEEP_RANGE + +# COMPARISON_TO_NULL reports this kind of messages (when using --strict): +# Comparison to NULL could be written "" +--ignore COMPARISON_TO_NULL + +# UNNECESSARY_PARENTHESES reports this kind of messages (when using --strict): +# Unnecessary parentheses around "" +--ignore UNNECESSARY_PARENTHESES diff --git a/arm-trusted-firmware/.commitlintrc.js b/arm-trusted-firmware/.commitlintrc.js new file mode 100644 index 0000000..ed971a3 --- /dev/null +++ b/arm-trusted-firmware/.commitlintrc.js @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const fs = require("fs"); +const yaml = require("js-yaml"); + +const { "trailer-exists": trailerExists } = require("@commitlint/rules").default; + +/* + * The types and scopes accepted by both Commitlint and Commitizen are defined by the changelog + * configuration file - `changelog.yaml` - as they decide which section of the changelog commits + * with a given type and scope are placed in. + */ + +let changelog; + +try { + const contents = fs.readFileSync("changelog.yaml", "utf8"); + + changelog = yaml.load(contents); +} catch (err) { + console.log(err); + + throw err; +} + +function getTypes(sections) { + return sections.map(section => section.type) +} + +function getScopes(subsections) { + return subsections.flatMap(subsection => { + const scope = subsection.scope ? [ subsection.scope ] : []; + const subscopes = getScopes(subsection.subsections || []); + + return scope.concat(subscopes); + }) +}; + +const types = getTypes(changelog.sections).sort(); /* Sort alphabetically */ +const scopes = getScopes(changelog.subsections).sort(); /* Sort alphabetically */ + +module.exports = { + extends: ["@commitlint/config-conventional"], + plugins: [ + { + rules: { + "signed-off-by-exists": trailerExists, + "change-id-exists": trailerExists, + }, + }, + ], + rules: { + "header-max-length": [1, "always", 50], /* Warning */ + "body-max-line-length": [1, "always", 72], /* Warning */ + + "change-id-exists": [1, "always", "Change-Id:"], /* Warning */ + "signed-off-by-exists": [1, "always", "Signed-off-by:"], /* Warning */ + + "type-case": [2, "always", "lower-case" ], /* Error */ + "type-enum": [2, "always", types], /* Error */ + + "scope-case": [2, "always", "lower-case"], /* Error */ + "scope-empty": [2, "never"], /* Error */ + "scope-enum": [1, "always", scopes] /* Warning */ + }, +}; diff --git a/arm-trusted-firmware/.cz.json b/arm-trusted-firmware/.cz.json new file mode 100644 index 0000000..556c39f --- /dev/null +++ b/arm-trusted-firmware/.cz.json @@ -0,0 +1,3 @@ +{ + "path": "@commitlint/cz-commitlint" +} diff --git a/arm-trusted-firmware/.editorconfig b/arm-trusted-firmware/.editorconfig new file mode 100644 index 0000000..12f786d --- /dev/null +++ b/arm-trusted-firmware/.editorconfig @@ -0,0 +1,72 @@ +# +# Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Trusted Firmware-A Coding style spec for editors. + +# References: +# [EC] http://editorconfig.org/ +# [CONT] contributing.rst +# [LCS] Linux Coding Style +# (https://www.kernel.org/doc/html/v4.10/process/coding-style.html) +# [PEP8] Style Guide for Python Code +# (https://www.python.org/dev/peps/pep-0008) + + +root = true + +# set default to match [LCS] .c/.h settings. +# This will also apply to .S, .mk, .sh, Makefile, .dts, etc. +[*] +# Not specified, but fits current ARM-TF sources. +charset = utf-8 + +# Not specified, but implicit for "LINUX coding style". +end_of_line = lf + +# [LCS] Chapter 1: Indentation +# "and thus indentations are also 8 characters" +indent_size = 8 + +# [LCS] Chapter 1: Indentation +# "Outside of comments,...spaces are never used for indentation" +indent_style = tab + +# Not specified by [LCS], but sensible +insert_final_newline = true + +# [LCS] Chapter 2: Breaking long lines and strings +# "The limit on the length of lines is 100 columns" +# This is a "soft" requirement for Arm-TF, and should not be the sole +# reason for changes. +max_line_length = 100 + +# [LCS] Chapter 1: Indentation +# "Tabs are 8 characters" +tab_width = 8 + +# [LCS] Chapter 1: Indentation +# "Get a decent editor and don't leave whitespace at the end of lines." +# [LCS] Chapter 3.1: Spaces +# "Do not leave trailing whitespace at the ends of lines." +trim_trailing_whitespace = true + + +# Adjustment for ReStructuredText (RST) documentation +[*.{rst}] +indent_size = 4 +indent_style = space + + +# Adjustment for python which prefers a different style +[*.py] +# [PEP8] Indentation +# "Use 4 spaces per indentation level." +indent_size = 4 +indent_style = space + +# [PEP8] Maximum Line Length +# "Limit all lines to a maximum of 79 characters." +max_line_length = 79 diff --git a/arm-trusted-firmware/.gitreview b/arm-trusted-firmware/.gitreview new file mode 100644 index 0000000..afdb74d --- /dev/null +++ b/arm-trusted-firmware/.gitreview @@ -0,0 +1,5 @@ +[gerrit] +host=review.trustedfirmware.org +port=29418 +project=TF-A/trusted-firmware-a +defaultbranch=integration diff --git a/arm-trusted-firmware/.husky/commit-msg b/arm-trusted-firmware/.husky/commit-msg new file mode 100755 index 0000000..c1c9600 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg @@ -0,0 +1,7 @@ +#!/bin/sh + +# shellcheck source=./_/husky.sh +. "$(dirname "$0")/_/husky.sh" + +"$(dirname "$0")/commit-msg.gerrit" "$@" +"$(dirname "$0")/commit-msg.commitlint" "$@" diff --git a/arm-trusted-firmware/.husky/commit-msg.commitlint b/arm-trusted-firmware/.husky/commit-msg.commitlint new file mode 100755 index 0000000..ca25ce1 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg.commitlint @@ -0,0 +1,3 @@ +#!/bin/sh + +npx --no-install commitlint --edit "$1" diff --git a/arm-trusted-firmware/.husky/commit-msg.gerrit b/arm-trusted-firmware/.husky/commit-msg.gerrit new file mode 100755 index 0000000..b8ce477 --- /dev/null +++ b/arm-trusted-firmware/.husky/commit-msg.gerrit @@ -0,0 +1,194 @@ +#!/bin/sh +# From Gerrit Code Review 2.14.20 +# +# Part of Gerrit Code Review (https://www.gerritcodereview.com/) +# +# Copyright (C) 2009 The Android Open Source Project +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +unset GREP_OPTIONS + +CHANGE_ID_AFTER="Bug|Depends-On|Issue|Test|Feature|Fixes|Fixed" +MSG="$1" + +# Check for, and add if missing, a unique Change-Id +# +add_ChangeId() { + clean_message=`sed -e ' + /^diff --git .*/{ + s/// + q + } + /^Signed-off-by:/d + /^#/d + ' "$MSG" | git stripspace` + if test -z "$clean_message" + then + return + fi + + # Do not add Change-Id to temp commits + if echo "$clean_message" | head -1 | grep -q '^\(fixup\|squash\)!' + then + return + fi + + if test "false" = "`git config --bool --get gerrit.createChangeId`" + then + return + fi + + # Does Change-Id: already exist? if so, exit (no change). + if grep -i '^Change-Id:' "$MSG" >/dev/null + then + return + fi + + id=`_gen_ChangeId` + T="$MSG.tmp.$$" + AWK=awk + if [ -x /usr/xpg4/bin/awk ]; then + # Solaris AWK is just too broken + AWK=/usr/xpg4/bin/awk + fi + + # Get core.commentChar from git config or use default symbol + commentChar=`git config --get core.commentChar` + commentChar=${commentChar:-#} + + # How this works: + # - parse the commit message as (textLine+ blankLine*)* + # - assume textLine+ to be a footer until proven otherwise + # - exception: the first block is not footer (as it is the title) + # - read textLine+ into a variable + # - then count blankLines + # - once the next textLine appears, print textLine+ blankLine* as these + # aren't footer + # - in END, the last textLine+ block is available for footer parsing + $AWK ' + BEGIN { + if (match(ENVIRON["OS"], "Windows")) { + RS="\r?\n" # Required on recent Cygwin + } + # while we start with the assumption that textLine+ + # is a footer, the first block is not. + isFooter = 0 + footerComment = 0 + blankLines = 0 + } + + # Skip lines starting with commentChar without any spaces before it. + /^'"$commentChar"'/ { next } + + # Skip the line starting with the diff command and everything after it, + # up to the end of the file, assuming it is only patch data. + # If more than one line before the diff was empty, strip all but one. + /^diff --git / { + blankLines = 0 + while (getline) { } + next + } + + # Count blank lines outside footer comments + /^$/ && (footerComment == 0) { + blankLines++ + next + } + + # Catch footer comment + /^\[[a-zA-Z0-9-]+:/ && (isFooter == 1) { + footerComment = 1 + } + + /]$/ && (footerComment == 1) { + footerComment = 2 + } + + # We have a non-blank line after blank lines. Handle this. + (blankLines > 0) { + print lines + for (i = 0; i < blankLines; i++) { + print "" + } + + lines = "" + blankLines = 0 + isFooter = 1 + footerComment = 0 + } + + # Detect that the current block is not the footer + (footerComment == 0) && (!/^\[?[a-zA-Z0-9-]+:/ || /^[a-zA-Z0-9-]+:\/\//) { + isFooter = 0 + } + + { + # We need this information about the current last comment line + if (footerComment == 2) { + footerComment = 0 + } + if (lines != "") { + lines = lines "\n"; + } + lines = lines $0 + } + + # Footer handling: + # If the last block is considered a footer, splice in the Change-Id at the + # right place. + # Look for the right place to inject Change-Id by considering + # CHANGE_ID_AFTER. Keys listed in it (case insensitive) come first, + # then Change-Id, then everything else (eg. Signed-off-by:). + # + # Otherwise just print the last block, a new line and the Change-Id as a + # block of its own. + END { + unprinted = 1 + if (isFooter == 0) { + print lines "\n" + lines = "" + } + changeIdAfter = "^(" tolower("'"$CHANGE_ID_AFTER"'") "):" + numlines = split(lines, footer, "\n") + for (line = 1; line <= numlines; line++) { + if (unprinted && match(tolower(footer[line]), changeIdAfter) != 1) { + unprinted = 0 + print "Change-Id: I'"$id"'" + } + print footer[line] + } + if (unprinted) { + print "Change-Id: I'"$id"'" + } + }' "$MSG" > "$T" && mv "$T" "$MSG" || rm -f "$T" +} +_gen_ChangeIdInput() { + echo "tree `git write-tree`" + if parent=`git rev-parse "HEAD^0" 2>/dev/null` + then + echo "parent $parent" + fi + echo "author `git var GIT_AUTHOR_IDENT`" + echo "committer `git var GIT_COMMITTER_IDENT`" + echo + printf '%s' "$clean_message" +} +_gen_ChangeId() { + _gen_ChangeIdInput | + git hash-object -t commit --stdin +} + + +add_ChangeId diff --git a/arm-trusted-firmware/.husky/prepare-commit-msg b/arm-trusted-firmware/.husky/prepare-commit-msg new file mode 100755 index 0000000..593dfa8 --- /dev/null +++ b/arm-trusted-firmware/.husky/prepare-commit-msg @@ -0,0 +1,6 @@ +#!/bin/sh + +# shellcheck source=./_/husky.sh +. "$(dirname "$0")/_/husky.sh" + +"$(dirname "$0")/prepare-commit-msg.cz" "$@" diff --git a/arm-trusted-firmware/.husky/prepare-commit-msg.cz b/arm-trusted-firmware/.husky/prepare-commit-msg.cz new file mode 100755 index 0000000..724527d --- /dev/null +++ b/arm-trusted-firmware/.husky/prepare-commit-msg.cz @@ -0,0 +1,28 @@ +#!/bin/bash + +file="$1" +type="$2" + +if [ -z "$type" ]; then # only run on new commits + # + # Save any commit message trailers generated by Git. + # + + trailers=$(git interpret-trailers --parse "$file") + + # + # Execute the Commitizen hook. + # + + (exec < "/dev/tty" && npx --no-install git-cz --hook) || true + + # + # Restore any trailers that Commitizen might have overwritten. + # + + printf "\n" >> "$file" + + while IFS= read -r trailer; do + git interpret-trailers --in-place --trailer "$trailer" "$file" + done <<< "$trailers" +fi diff --git a/arm-trusted-firmware/.versionrc.js b/arm-trusted-firmware/.versionrc.js new file mode 100644 index 0000000..f699a07 --- /dev/null +++ b/arm-trusted-firmware/.versionrc.js @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const fs = require("fs"); +const yaml = require("js-yaml"); + +/* + * The types and scopes accepted by both Commitlint and Commitizen are defined by the changelog + * configuration file - `changelog.yaml` - as they decide which section of the changelog commits + * with a given type and scope are placed in. + */ + +let changelog; + +try { + const contents = fs.readFileSync("changelog.yaml", "utf8"); + + changelog = yaml.load(contents); +} catch (err) { + console.log(err); + + throw err; +} + +/* + * The next couple of functions are just used to transform the changelog YAML configuration + * structure into one accepted by the Conventional Changelog adapter (conventional-changelog-tf-a). + */ + +function getTypes(sections) { + return sections.map(section => { + return { + "type": section.type, + "section": section.hidden ? undefined : section.title, + "hidden": section.hidden || false, + }; + }) +} + +function getSections(subsections) { + return subsections.flatMap(subsection => { + const scope = subsection.scope ? [ subsection.scope ] : []; + + return { + "title": subsection.title, + "sections": getSections(subsection.subsections || []), + "scopes": scope.concat(subsection.deprecated || []), + }; + }) +}; + +const types = getTypes(changelog.sections); +const sections = getSections(changelog.subsections); + +module.exports = { + "header": "# Change Log & Release Notes\n\nThis document contains a summary of the new features, changes, fixes and known\nissues in each release of Trusted Firmware-A.\n", + "preset": { + "name": "tf-a", + "commitUrlFormat": "https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/{{hash}}", + "compareUrlFormat": "https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/{{previousTag}}..refs/tags/{{currentTag}}", + "userUrlFormat": "https://github.com/{{user}}", + + "types": types, + "sections": sections, + }, + "infile": "docs/change-log.md", + "skip": { + "commit": true, + "tag": true + }, + "bumpFiles": [ + { + "filename": "package.json", + "type": "json" + }, + { + "filename": "package-lock.json", + "type": "json" + }, + { + "filename": "tools/conventional-changelog-tf-a/package.json", + "type": "json" + }, + { + "filename": "Makefile", + "updater": { + "readVersion": function (contents) { + const major = contents.match(/^VERSION_MAJOR\s*:=\s*(\d+?)$/m)[1]; + const minor = contents.match(/^VERSION_MINOR\s*:=\s*(\d+?)$/m)[1]; + + return `${major}.${minor}.0`; + }, + + "writeVersion": function (contents, version) { + const major = version.split(".")[0]; + const minor = version.split(".")[1]; + + contents = contents.replace(/^(VERSION_MAJOR\s*:=\s*)(\d+?)$/m, `$1${major}`); + contents = contents.replace(/^(VERSION_MINOR\s*:=\s*)(\d+?)$/m, `$1${minor}`); + + return contents; + } + } + } + ] +}; diff --git a/arm-trusted-firmware/Makefile b/arm-trusted-firmware/Makefile new file mode 100644 index 0000000..95c9075 --- /dev/null +++ b/arm-trusted-firmware/Makefile @@ -0,0 +1,1536 @@ +# +# Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# Trusted Firmware Version +# +VERSION_MAJOR := 2 +VERSION_MINOR := 6 + +# Default goal is build all images +.DEFAULT_GOAL := all + +# Avoid any implicit propagation of command line variable definitions to +# sub-Makefiles, like CFLAGS that we reserved for the firmware images' +# usage. Other command line options like "-s" are still propagated as usual. +MAKEOVERRIDES = + +MAKE_HELPERS_DIRECTORY := make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +################################################################################ +# Default values for build configurations, and their dependencies +################################################################################ + +include ${MAKE_HELPERS_DIRECTORY}defaults.mk + +# Assertions enabled for DEBUG builds by default +ENABLE_ASSERTIONS := ${DEBUG} +ENABLE_PMF := ${ENABLE_RUNTIME_INSTRUMENTATION} +PLAT := ${DEFAULT_PLAT} + +################################################################################ +# Checkpatch script options +################################################################################ + +CHECKCODE_ARGS := --no-patch +# Do not check the coding style on imported library files or documentation files +INC_ARM_DIRS_TO_CHECK := $(sort $(filter-out \ + include/drivers/arm/cryptocell, \ + $(wildcard include/drivers/arm/*))) +INC_ARM_DIRS_TO_CHECK += include/drivers/arm/cryptocell/*.h +INC_DRV_DIRS_TO_CHECK := $(sort $(filter-out \ + include/drivers/arm, \ + $(wildcard include/drivers/*))) +INC_LIB_DIRS_TO_CHECK := $(sort $(filter-out \ + include/lib/libfdt \ + include/lib/libc, \ + $(wildcard include/lib/*))) +INC_DIRS_TO_CHECK := $(sort $(filter-out \ + include/lib \ + include/drivers, \ + $(wildcard include/*))) +LIB_DIRS_TO_CHECK := $(sort $(filter-out \ + lib/compiler-rt \ + lib/libfdt% \ + lib/libc, \ + $(wildcard lib/*))) +ROOT_DIRS_TO_CHECK := $(sort $(filter-out \ + lib \ + include \ + docs \ + %.rst, \ + $(wildcard *))) +CHECK_PATHS := ${ROOT_DIRS_TO_CHECK} \ + ${INC_DIRS_TO_CHECK} \ + ${INC_LIB_DIRS_TO_CHECK} \ + ${LIB_DIRS_TO_CHECK} \ + ${INC_DRV_DIRS_TO_CHECK} \ + ${INC_ARM_DIRS_TO_CHECK} + + +################################################################################ +# Process build options +################################################################################ + +# Verbose flag +ifeq (${V},0) + Q:=@ + ECHO:=@echo + CHECKCODE_ARGS += --no-summary --terse +else + Q:= + ECHO:=$(ECHO_QUIET) +endif + +ifneq ($(findstring s,$(filter-out --%,$(MAKEFLAGS))),) + Q:=@ + ECHO:=$(ECHO_QUIET) +endif + +export Q ECHO + +# The cert_create tool cannot generate certificates individually, so we use the +# target 'certificates' to create them all +ifneq (${GENERATE_COT},0) + FIP_DEPS += certificates + FWU_FIP_DEPS += fwu_certificates +endif + +# Process BRANCH_PROTECTION value and set +# Pointer Authentication and Branch Target Identification flags +ifeq (${BRANCH_PROTECTION},0) + # Default value turns off all types of branch protection + BP_OPTION := none +else ifneq (${ARCH},aarch64) + $(error BRANCH_PROTECTION requires AArch64) +else ifeq (${BRANCH_PROTECTION},1) + # Enables all types of branch protection features + BP_OPTION := standard + ENABLE_BTI := 1 + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},2) + # Return address signing to its standard level + BP_OPTION := pac-ret + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},3) + # Extend the signing to include leaf functions + BP_OPTION := pac-ret+leaf + ENABLE_PAUTH := 1 +else ifeq (${BRANCH_PROTECTION},4) + # Turn on branch target identification mechanism + BP_OPTION := bti + ENABLE_BTI := 1 +else + $(error Unknown BRANCH_PROTECTION value ${BRANCH_PROTECTION}) +endif + +# FEAT_RME +ifeq (${ENABLE_RME},1) +# RME doesn't support PIE +ifneq (${ENABLE_PIE},0) + $(error ENABLE_RME does not support PIE) +endif +# RME requires AARCH64 +ifneq (${ARCH},aarch64) + $(error ENABLE_RME requires AArch64) +endif +# RME requires el2 context to be saved for now. +CTX_INCLUDE_EL2_REGS := 1 +CTX_INCLUDE_AARCH32_REGS := 0 +ARM_ARCH_MAJOR := 8 +ARM_ARCH_MINOR := 6 +endif + +# USE_SPINLOCK_CAS requires AArch64 build +ifeq (${USE_SPINLOCK_CAS},1) +ifneq (${ARCH},aarch64) + $(error USE_SPINLOCK_CAS requires AArch64) +endif +endif + +# USE_DEBUGFS experimental feature recommended only in debug builds +ifeq (${USE_DEBUGFS},1) +ifeq (${DEBUG},1) + $(warning DEBUGFS experimental feature is enabled.) +else + $(warning DEBUGFS experimental, recommended in DEBUG builds ONLY) +endif +endif + +ifneq (${DECRYPTION_SUPPORT},none) +ENC_ARGS += -f ${FW_ENC_STATUS} +ENC_ARGS += -k ${ENC_KEY} +ENC_ARGS += -n ${ENC_NONCE} +FIP_DEPS += enctool +FWU_FIP_DEPS += enctool +endif + +################################################################################ +# Toolchain +################################################################################ + +HOSTCC := gcc +export HOSTCC + +CC := ${CROSS_COMPILE}gcc +CPP := ${CROSS_COMPILE}cpp +AS := ${CROSS_COMPILE}gcc +AR := ${CROSS_COMPILE}ar +LINKER := ${CROSS_COMPILE}ld +OC := ${CROSS_COMPILE}objcopy +OD := ${CROSS_COMPILE}objdump +NM := ${CROSS_COMPILE}nm +PP := ${CROSS_COMPILE}gcc -E +DTC := dtc + +# Use ${LD}.bfd instead if it exists (as absolute path or together with $PATH). +ifneq ($(strip $(wildcard ${LD}.bfd) \ + $(foreach dir,$(subst :, ,${PATH}),$(wildcard ${dir}/${LINKER}.bfd))),) +LINKER := ${LINKER}.bfd +endif + +ifeq (${ARM_ARCH_MAJOR},7) +target32-directive = -target arm-none-eabi +# Will set march32-directive from platform configuration +else +target32-directive = -target armv8a-none-eabi + +# Set the compiler's target architecture profile based on +# ARM_ARCH_MAJOR ARM_ARCH_MINOR options +ifeq (${ARM_ARCH_MINOR},0) +march32-directive = -march=armv${ARM_ARCH_MAJOR}-a +march64-directive = -march=armv${ARM_ARCH_MAJOR}-a +else +march32-directive = -march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a +march64-directive = -march=armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a +endif +endif + +# Memory tagging is supported in architecture Armv8.5-A AArch64 and onwards +ifeq ($(ARCH), aarch64) +# Check if revision is greater than or equal to 8.5 +ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +mem_tag_arch_support = yes +endif +endif + +# Get architecture feature modifiers +arch-features = ${ARM_ARCH_FEATURE} + +# Enable required options for memory stack tagging. +# Currently, these options are enabled only for clang and armclang compiler. +ifeq (${SUPPORT_STACK_MEMTAG},yes) +ifdef mem_tag_arch_support +# Check for armclang and clang compilers +ifneq ( ,$(filter $(notdir $(CC)),armclang clang)) +# Add "memtag" architecture feature modifier if not specified +ifeq ( ,$(findstring memtag,$(arch-features))) +arch-features := $(arch-features)+memtag +endif # memtag +ifeq ($(notdir $(CC)),armclang) +TF_CFLAGS += -mmemtag-stack +else ifeq ($(notdir $(CC)),clang) +TF_CFLAGS += -fsanitize=memtag +endif # armclang +endif # armclang clang +else +$(error "Error: stack memory tagging is not supported for architecture \ + ${ARCH},armv${ARM_ARCH_MAJOR}.${ARM_ARCH_MINOR}-a") +endif # mem_tag_arch_support +endif # SUPPORT_STACK_MEMTAG + +# Set the compiler's architecture feature modifiers +ifneq ($(arch-features), none) +# Strip "none+" from arch-features +arch-features := $(subst none+,,$(arch-features)) +ifeq ($(ARCH), aarch32) +march32-directive := $(march32-directive)+$(arch-features) +else +march64-directive := $(march64-directive)+$(arch-features) +endif +# Print features +$(info Arm Architecture Features specified: $(subst +, ,$(arch-features))) +endif # arch-features + +# Determine if FEAT_RNG is supported +ENABLE_FEAT_RNG = $(if $(findstring rng,${arch-features}),1,0) + +# Determine if FEAT_SB is supported +ENABLE_FEAT_SB = $(if $(findstring sb,${arch-features}),1,0) + +ifeq "8.5" "$(word 1, $(sort 8.5 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_SB = 1 +endif + +# Determine and enable FEAT_FGT to access HDFGRTR_EL2 register for v8.6 and higher versions. +ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_FGT = 1 +endif + +# Determine and enable FEAT_ECV to access CNTPOFF_EL2 register for v8.6 and higher versions. +ifeq "8.6" "$(word 1, $(sort 8.6 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_ECV = 1 +endif + +ifeq "8.4" "$(word 1, $(sort 8.4 $(ARM_ARCH_MAJOR).$(ARM_ARCH_MINOR)))" +ENABLE_FEAT_DIT = 1 +endif + +ifneq ($(findstring armclang,$(notdir $(CC))),) +TF_CFLAGS_aarch32 = -target arm-arm-none-eabi $(march32-directive) +TF_CFLAGS_aarch64 = -target aarch64-arm-none-eabi $(march64-directive) +LD = $(LINKER) +AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH)) +CPP = $(CC) -E $(TF_CFLAGS_$(ARCH)) +PP = $(CC) -E $(TF_CFLAGS_$(ARCH)) +else ifneq ($(findstring clang,$(notdir $(CC))),) +CLANG_CCDIR = $(if $(filter-out ./,$(dir $(CC))),$(dir $(CC)),) +TF_CFLAGS_aarch32 = $(target32-directive) $(march32-directive) +TF_CFLAGS_aarch64 = -target aarch64-elf $(march64-directive) +LD = $(CLANG_CCDIR)ld.lld +ifeq (, $(shell which $(LD))) +$(error "No $(LD) in PATH, make sure it is installed or set LD to a different linker") +endif +AS = $(CC) -c -x assembler-with-cpp $(TF_CFLAGS_$(ARCH)) +CPP = $(CC) -E +PP = $(CC) -E +else ifneq ($(findstring gcc,$(notdir $(CC))),) +TF_CFLAGS_aarch32 = $(march32-directive) +TF_CFLAGS_aarch64 = $(march64-directive) +ifeq ($(ENABLE_LTO),1) + # Enable LTO only for aarch64 + ifeq (${ARCH},aarch64) + LTO_CFLAGS = -flto + # Use gcc as a wrapper for the ld, recommended for LTO + LINKER := ${CROSS_COMPILE}gcc + endif +endif +LD = $(LINKER) +else +TF_CFLAGS_aarch32 = $(march32-directive) +TF_CFLAGS_aarch64 = $(march64-directive) +LD = $(LINKER) +endif + +# Process Debug flag +$(eval $(call add_define,DEBUG)) +ifneq (${DEBUG}, 0) + BUILD_TYPE := debug + TF_CFLAGS += -g + + ifneq ($(findstring clang,$(notdir $(CC))),) + ASFLAGS += -g + else + ASFLAGS += -g -Wa,--gdwarf-2 + endif + + # Use LOG_LEVEL_INFO by default for debug builds + LOG_LEVEL := 40 +else + BUILD_TYPE := release + # Use LOG_LEVEL_NOTICE by default for release builds + LOG_LEVEL := 20 +endif + +# Default build string (git branch and commit) +ifeq (${BUILD_STRING},) + BUILD_STRING := $(shell git describe --always --dirty --tags 2> /dev/null) +endif +VERSION_STRING := v${VERSION_MAJOR}.${VERSION_MINOR}(${BUILD_TYPE}):${BUILD_STRING} + +ifeq (${AARCH32_INSTRUCTION_SET},A32) +TF_CFLAGS_aarch32 += -marm +else ifeq (${AARCH32_INSTRUCTION_SET},T32) +TF_CFLAGS_aarch32 += -mthumb +else +$(error Error: Unknown AArch32 instruction set ${AARCH32_INSTRUCTION_SET}) +endif + +TF_CFLAGS_aarch32 += -mno-unaligned-access +TF_CFLAGS_aarch64 += -mgeneral-regs-only -mstrict-align + +ifneq (${BP_OPTION},none) +TF_CFLAGS_aarch64 += -mbranch-protection=${BP_OPTION} +endif + +ASFLAGS_aarch32 = $(march32-directive) +ASFLAGS_aarch64 = $(march64-directive) + +# General warnings +WARNINGS := -Wall -Wmissing-include-dirs -Wunused \ + -Wdisabled-optimization -Wvla -Wshadow \ + -Wno-unused-parameter -Wredundant-decls + +# Additional warnings +# Level 1 +WARNING1 := -Wextra +WARNING1 += -Wmissing-format-attribute +WARNING1 += -Wmissing-prototypes +WARNING1 += -Wold-style-definition + +# Level 2 +WARNING2 := -Waggregate-return +WARNING2 += -Wcast-align +WARNING2 += -Wnested-externs + +WARNING3 := -Wbad-function-cast +WARNING3 += -Wcast-qual +WARNING3 += -Wconversion +WARNING3 += -Wpacked +WARNING3 += -Wpointer-arith +WARNING3 += -Wswitch-default + +ifeq (${W},1) +WARNINGS += $(WARNING1) +else ifeq (${W},2) +WARNINGS += $(WARNING1) $(WARNING2) +else ifeq (${W},3) +WARNINGS += $(WARNING1) $(WARNING2) $(WARNING3) +endif + +# Compiler specific warnings +ifeq ($(findstring clang,$(notdir $(CC))),) +# not using clang +WARNINGS += -Wunused-but-set-variable -Wmaybe-uninitialized \ + -Wpacked-bitfield-compat -Wshift-overflow=2 \ + -Wlogical-op +else +# using clang +WARNINGS += -Wshift-overflow -Wshift-sign-overflow \ + -Wlogical-op-parentheses +endif + +ifneq (${E},0) +ERRORS := -Werror +endif + +CPPFLAGS = ${DEFINES} ${INCLUDES} ${MBEDTLS_INC} -nostdinc \ + $(ERRORS) $(WARNINGS) +ASFLAGS += $(CPPFLAGS) $(ASFLAGS_$(ARCH)) \ + -ffreestanding -Wa,--fatal-warnings +TF_CFLAGS += $(CPPFLAGS) $(TF_CFLAGS_$(ARCH)) \ + -ffunction-sections -fdata-sections \ + -ffreestanding -fno-builtin -fno-common \ + -Os -std=gnu99 + +ifeq (${SANITIZE_UB},on) +TF_CFLAGS += -fsanitize=undefined -fno-sanitize-recover +endif +ifeq (${SANITIZE_UB},trap) +TF_CFLAGS += -fsanitize=undefined -fno-sanitize-recover \ + -fsanitize-undefined-trap-on-error +endif + +GCC_V_OUTPUT := $(shell $(CC) -v 2>&1) + +# LD = armlink +ifneq ($(findstring armlink,$(notdir $(LD))),) +TF_LDFLAGS += --diag_error=warning --lto_level=O1 +TF_LDFLAGS += --remove --info=unused,unusedsymbols +TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH)) + +# LD = gcc (used when GCC LTO is enabled) +else ifneq ($(findstring gcc,$(notdir $(LD))),) +# Pass ld options with Wl or Xlinker switches +TF_LDFLAGS += -Wl,--fatal-warnings -O1 +TF_LDFLAGS += -Wl,--gc-sections +ifeq ($(ENABLE_LTO),1) + ifeq (${ARCH},aarch64) + TF_LDFLAGS += -flto -fuse-linker-plugin + endif +endif +# GCC automatically adds fix-cortex-a53-843419 flag when used to link +# which breaks some builds, so disable if errata fix is not explicitly enabled +ifneq (${ERRATA_A53_843419},1) + TF_LDFLAGS += -mno-fix-cortex-a53-843419 +endif +TF_LDFLAGS += -nostdlib +TF_LDFLAGS += $(subst --,-Xlinker --,$(TF_LDFLAGS_$(ARCH))) + +# LD = gcc-ld (ld) or llvm-ld (ld.lld) or other +else +TF_LDFLAGS += --fatal-warnings -O1 +TF_LDFLAGS += --gc-sections +# ld.lld doesn't recognize the errata flags, +# therefore don't add those in that case +ifeq ($(findstring ld.lld,$(notdir $(LD))),) +TF_LDFLAGS += $(TF_LDFLAGS_$(ARCH)) +endif +endif + +DTC_FLAGS += -I dts -O dtb +DTC_CPPFLAGS += -P -nostdinc -Iinclude -Ifdts -undef \ + -x assembler-with-cpp $(DEFINES) + +ifeq ($(MEASURED_BOOT),1) +DTC_CPPFLAGS += -DMEASURED_BOOT -DBL2_HASH_SIZE=${TCG_DIGEST_SIZE} +endif + +################################################################################ +# Common sources and include directories +################################################################################ +include lib/compiler-rt/compiler-rt.mk + +BL_COMMON_SOURCES += common/bl_common.c \ + common/tf_log.c \ + common/${ARCH}/debug.S \ + drivers/console/multi_console.c \ + lib/${ARCH}/cache_helpers.S \ + lib/${ARCH}/misc_helpers.S \ + plat/common/plat_bl_common.c \ + plat/common/plat_log_common.c \ + plat/common/${ARCH}/plat_common.c \ + plat/common/${ARCH}/platform_helpers.S \ + ${COMPILER_RT_SRCS} + +ifeq ($(notdir $(CC)),armclang) +BL_COMMON_SOURCES += lib/${ARCH}/armclang_printf.S +endif + +ifeq (${SANITIZE_UB},on) +BL_COMMON_SOURCES += plat/common/ubsan.c +endif + +INCLUDES += -Iinclude \ + -Iinclude/arch/${ARCH} \ + -Iinclude/lib/cpus/${ARCH} \ + -Iinclude/lib/el3_runtime/${ARCH} \ + ${PLAT_INCLUDES} \ + ${SPD_INCLUDES} + +include common/backtrace/backtrace.mk + +################################################################################ +# Generic definitions +################################################################################ + +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk + +ifeq (${BUILD_BASE},) + BUILD_BASE := ./build +endif +BUILD_PLAT := $(abspath ${BUILD_BASE})/${PLAT}/${BUILD_TYPE} + +SPDS := $(sort $(filter-out none, $(patsubst services/spd/%,%,$(wildcard services/spd/*)))) + +# Platforms providing their own TBB makefile may override this value +INCLUDE_TBBR_MK := 1 + + +################################################################################ +# Include SPD Makefile if one has been specified +################################################################################ + +ifneq (${SPD},none) + ifeq (${ARCH},aarch32) + $(error "Error: SPD is incompatible with AArch32.") + endif + + ifdef EL3_PAYLOAD_BASE + $(warning "SPD and EL3_PAYLOAD_BASE are incompatible build options.") + $(warning "The SPD and its BL32 companion will be present but ignored.") + endif + + ifeq (${SPD},spmd) + # SPMD is located in std_svc directory + SPD_DIR := std_svc + + ifeq ($(SPMD_SPM_AT_SEL2),1) + ifeq ($(CTX_INCLUDE_EL2_REGS),0) + $(error SPMD with SPM at S-EL2 requires CTX_INCLUDE_EL2_REGS option) + endif + endif + + ifeq ($(findstring optee_sp,$(ARM_SPMC_MANIFEST_DTS)),optee_sp) + DTC_CPPFLAGS += -DOPTEE_SP_FW_CONFIG + endif + + ifeq ($(TS_SP_FW_CONFIG),1) + DTC_CPPFLAGS += -DTS_SP_FW_CONFIG + endif + + ifneq ($(ARM_BL2_SP_LIST_DTS),) + DTC_CPPFLAGS += -DARM_BL2_SP_LIST_DTS=$(ARM_BL2_SP_LIST_DTS) + endif + + ifneq ($(SP_LAYOUT_FILE),) + BL2_ENABLE_SP_LOAD := 1 + endif + else + # All other SPDs in spd directory + SPD_DIR := spd + endif + + # We expect to locate an spd.mk under the specified SPD directory + SPD_MAKE := $(wildcard services/${SPD_DIR}/${SPD}/${SPD}.mk) + + ifeq (${SPD_MAKE},) + $(error Error: No services/${SPD_DIR}/${SPD}/${SPD}.mk located) + endif + $(info Including ${SPD_MAKE}) + include ${SPD_MAKE} + + # If there's BL32 companion for the chosen SPD, we expect that the SPD's + # Makefile would set NEED_BL32 to "yes". In this case, the build system + # supports two mutually exclusive options: + # * BL32 is built from source: then BL32_SOURCES must contain the list + # of source files to build BL32 + # * BL32 is a prebuilt binary: then BL32 must point to the image file + # that will be included in the FIP + # If both BL32_SOURCES and BL32 are defined, the binary takes precedence + # over the sources. +endif + +################################################################################ +# Include rmmd Makefile if RME is enabled +################################################################################ + +ifneq (${ENABLE_RME},0) +ifneq (${ARCH},aarch64) + $(error ENABLE_RME requires AArch64) +endif +include services/std_svc/rmmd/rmmd.mk +$(warning "RME is an experimental feature") +endif + +################################################################################ +# Include the platform specific Makefile after the SPD Makefile (the platform +# makefile may use all previous definitions in this file) +################################################################################ + +include ${PLAT_MAKEFILE_FULL} + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_PLAT})) + +ifeq (${ARM_ARCH_MAJOR},7) +include make_helpers/armv7-a-cpus.mk +endif + +PIE_FOUND := $(findstring --enable-default-pie,${GCC_V_OUTPUT}) +ifneq ($(PIE_FOUND),) + TF_CFLAGS += -fno-PIE +endif + +ifneq ($(findstring gcc,$(notdir $(LD))),) + PIE_LDFLAGS += -Wl,-pie -Wl,--no-dynamic-linker +else + PIE_LDFLAGS += -pie --no-dynamic-linker +endif + +ifeq ($(ENABLE_PIE),1) +ifeq ($(BL2_AT_EL3),1) +ifneq ($(BL2_IN_XIP_MEM),1) + BL2_CFLAGS += -fpie + BL2_LDFLAGS += $(PIE_LDFLAGS) +endif +endif + BL31_CFLAGS += -fpie + BL31_LDFLAGS += $(PIE_LDFLAGS) + BL32_CFLAGS += -fpie + BL32_LDFLAGS += $(PIE_LDFLAGS) +endif + +ifeq (${ARCH},aarch64) +BL1_CPPFLAGS += -DIMAGE_AT_EL3 +ifeq ($(BL2_AT_EL3),1) +BL2_CPPFLAGS += -DIMAGE_AT_EL3 +else +BL2_CPPFLAGS += -DIMAGE_AT_EL1 +endif +BL2U_CPPFLAGS += -DIMAGE_AT_EL1 +BL31_CPPFLAGS += -DIMAGE_AT_EL3 +BL32_CPPFLAGS += -DIMAGE_AT_EL1 +endif + +# Include the CPU specific operations makefile, which provides default +# values for all CPU errata workarounds and CPU specific optimisations. +# This can be overridden by the platform. +include lib/cpus/cpu-ops.mk + +ifeq (${ARCH},aarch32) +NEED_BL32 := yes + +################################################################################ +# Build `AARCH32_SP` as BL32 image for AArch32 +################################################################################ +ifneq (${AARCH32_SP},none) +# We expect to locate an sp.mk under the specified AARCH32_SP directory +AARCH32_SP_MAKE := $(wildcard bl32/${AARCH32_SP}/${AARCH32_SP}.mk) + +ifeq (${AARCH32_SP_MAKE},) + $(error Error: No bl32/${AARCH32_SP}/${AARCH32_SP}.mk located) +endif + +$(info Including ${AARCH32_SP_MAKE}) +include ${AARCH32_SP_MAKE} +endif + +endif + +################################################################################ +# Include libc if not overridden +################################################################################ +ifeq (${OVERRIDE_LIBC},0) +include lib/libc/libc.mk +endif + +################################################################################ +# Check incompatible options +################################################################################ + +ifdef EL3_PAYLOAD_BASE + ifdef PRELOADED_BL33_BASE + $(warning "PRELOADED_BL33_BASE and EL3_PAYLOAD_BASE are \ + incompatible build options. EL3_PAYLOAD_BASE has priority.") + endif + ifneq (${GENERATE_COT},0) + $(error "GENERATE_COT and EL3_PAYLOAD_BASE are incompatible build options.") + endif + ifneq (${TRUSTED_BOARD_BOOT},0) + $(error "TRUSTED_BOARD_BOOT and EL3_PAYLOAD_BASE are incompatible build options.") + endif +endif + +ifeq (${NEED_BL33},yes) + ifdef EL3_PAYLOAD_BASE + $(warning "BL33 image is not needed when option \ + BL33_PAYLOAD_BASE is used and won't be added to the FIP file.") + endif + ifdef PRELOADED_BL33_BASE + $(warning "BL33 image is not needed when option \ + PRELOADED_BL33_BASE is used and won't be added to the FIP \ + file.") + endif +endif + +# 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. +ifeq ($(HW_ASSISTED_COHERENCY)-$(USE_COHERENT_MEM),1-1) +$(error USE_COHERENT_MEM cannot be enabled with HW_ASSISTED_COHERENCY) +endif + +#For now, BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is 1. +ifeq ($(BL2_AT_EL3)-$(BL2_IN_XIP_MEM),0-1) +$(error "BL2_IN_XIP_MEM is only supported when BL2_AT_EL3 is enabled") +endif + +# For RAS_EXTENSION, require that EAs are handled in EL3 first +ifeq ($(RAS_EXTENSION),1) + ifneq ($(HANDLE_EA_EL3_FIRST),1) + $(error For RAS_EXTENSION, HANDLE_EA_EL3_FIRST must also be 1) + endif +endif + +# When FAULT_INJECTION_SUPPORT is used, require that RAS_EXTENSION is enabled +ifeq ($(FAULT_INJECTION_SUPPORT),1) + ifneq ($(RAS_EXTENSION),1) + $(error For FAULT_INJECTION_SUPPORT, RAS_EXTENSION must also be 1) + endif +endif + +# DYN_DISABLE_AUTH can be set only when TRUSTED_BOARD_BOOT=1 +ifeq ($(DYN_DISABLE_AUTH), 1) + ifeq (${TRUSTED_BOARD_BOOT}, 0) + $(error "TRUSTED_BOARD_BOOT must be enabled for DYN_DISABLE_AUTH to be set.") + endif +endif + +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) + CRYPTO_SUPPORT := 1 +else + CRYPTO_SUPPORT := 0 +endif + +# SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled. +ifeq ($(SDEI_SUPPORT)-$(SDEI_IN_FCONF),0-1) +$(error "SDEI_IN_FCONF is only supported when SDEI_SUPPORT is enabled") +endif + +# If pointer authentication is used in the firmware, make sure that all the +# registers associated to it are also saved and restored. +# Not doing it would leak the value of the keys used by EL3 to EL1 and S-EL1. +ifeq ($(ENABLE_PAUTH),1) + ifeq ($(CTX_INCLUDE_PAUTH_REGS),0) + $(error Pointer Authentication requires CTX_INCLUDE_PAUTH_REGS=1) + endif +endif + +ifeq ($(CTX_INCLUDE_PAUTH_REGS),1) + ifneq (${ARCH},aarch64) + $(error CTX_INCLUDE_PAUTH_REGS requires AArch64) + endif +endif + +ifeq ($(CTX_INCLUDE_MTE_REGS),1) + ifneq (${ARCH},aarch64) + $(error CTX_INCLUDE_MTE_REGS requires AArch64) + endif +endif + +ifeq ($(PSA_FWU_SUPPORT),1) + $(info PSA_FWU_SUPPORT is an experimental feature) +endif + +ifeq (${ARM_XLAT_TABLES_LIB_V1}, 1) + ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + $(error "ALLOW_RO_XLAT_TABLES requires translation tables library v2") + endif +endif + +ifneq (${DECRYPTION_SUPPORT},none) + ifeq (${TRUSTED_BOARD_BOOT}, 0) + $(error TRUSTED_BOARD_BOOT must be enabled for DECRYPTION_SUPPORT to be set) + endif +endif + +# SME/SVE only supported on AArch64 +ifeq (${ARCH},aarch32) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with ARCH=aarch32") + endif + ifeq (${ENABLE_SVE_FOR_NS},1) + # Warning instead of error due to CI dependency on this + $(error "ENABLE_SVE_FOR_NS cannot be used with ARCH=aarch32") + endif +endif + +# Ensure ENABLE_RME is not used with SME +ifeq (${ENABLE_RME},1) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with ENABLE_RME") + endif +endif + +# Secure SME/SVE requires the non-secure component as well +ifeq (${ENABLE_SME_FOR_SWD},1) + ifeq (${ENABLE_SME_FOR_NS},0) + $(error "ENABLE_SME_FOR_SWD requires ENABLE_SME_FOR_NS") + endif +endif +ifeq (${ENABLE_SVE_FOR_SWD},1) + ifeq (${ENABLE_SVE_FOR_NS},0) + $(error "ENABLE_SVE_FOR_SWD requires ENABLE_SVE_FOR_NS") + endif +endif + +# SVE and SME cannot be used with CTX_INCLUDE_FPREGS since secure manager does +# its own context management including FPU registers. +ifeq (${CTX_INCLUDE_FPREGS},1) + ifeq (${ENABLE_SME_FOR_NS},1) + $(error "ENABLE_SME_FOR_NS cannot be used with CTX_INCLUDE_FPREGS") + endif + ifeq (${ENABLE_SVE_FOR_NS},1) + # Warning instead of error due to CI dependency on this + $(warning "ENABLE_SVE_FOR_NS cannot be used with CTX_INCLUDE_FPREGS") + $(warning "Forced ENABLE_SVE_FOR_NS=0") + override ENABLE_SVE_FOR_NS := 0 + endif +endif + +################################################################################ +# Process platform overrideable behaviour +################################################################################ + +ifdef BL1_SOURCES +NEED_BL1 := yes +endif + +ifdef BL2_SOURCES + NEED_BL2 := yes + + # Using BL2 implies that a BL33 image also needs to be supplied for the FIP and + # Certificate generation tools. This flag can be overridden by the platform. + ifdef EL3_PAYLOAD_BASE + # If booting an EL3 payload there is no need for a BL33 image + # in the FIP file. + NEED_BL33 := no + else + ifdef PRELOADED_BL33_BASE + # If booting a BL33 preloaded image there is no need of + # another one in the FIP file. + NEED_BL33 := no + else + NEED_BL33 ?= yes + endif + endif +endif + +ifdef BL2U_SOURCES +NEED_BL2U := yes +endif + +# If SCP_BL2 is given, we always want FIP to include it. +ifdef SCP_BL2 + NEED_SCP_BL2 := yes +endif + +# For AArch32, BL31 is not currently supported. +ifneq (${ARCH},aarch32) + ifdef BL31_SOURCES + # When booting an EL3 payload, there is no need to compile the BL31 image nor + # put it in the FIP. + ifndef EL3_PAYLOAD_BASE + NEED_BL31 := yes + endif + endif +endif + +# Process TBB related flags +ifneq (${GENERATE_COT},0) + # Common cert_create options + ifneq (${CREATE_KEYS},0) + $(eval CRT_ARGS += -n) + $(eval FWU_CRT_ARGS += -n) + ifneq (${SAVE_KEYS},0) + $(eval CRT_ARGS += -k) + $(eval FWU_CRT_ARGS += -k) + endif + endif + # Include TBBR makefile (unless the platform indicates otherwise) + ifeq (${INCLUDE_TBBR_MK},1) + include make_helpers/tbbr/tbbr_tools.mk + endif +endif + +ifneq (${FIP_ALIGN},0) +FIP_ARGS += --align ${FIP_ALIGN} +endif + +ifdef FDT_SOURCES +NEED_FDT := yes +endif + +################################################################################ +# Include libraries' Makefile that are used in all BL +################################################################################ + +include lib/stack_protector/stack_protector.mk + +################################################################################ +# Auxiliary tools (fiptool, cert_create, etc) +################################################################################ + +# Variables for use with Certificate Generation Tool +CRTTOOLPATH ?= tools/cert_create +CRTTOOL ?= ${CRTTOOLPATH}/cert_create${BIN_EXT} + +# Variables for use with Firmware Encryption Tool +ENCTOOLPATH ?= tools/encrypt_fw +ENCTOOL ?= ${ENCTOOLPATH}/encrypt_fw${BIN_EXT} + +# Variables for use with Firmware Image Package +FIPTOOLPATH ?= tools/fiptool +FIPTOOL ?= ${FIPTOOLPATH}/fiptool${BIN_EXT} + +# Variables for use with sptool +SPTOOLPATH ?= tools/sptool +SPTOOL ?= ${SPTOOLPATH}/sptool${BIN_EXT} +SP_MK_GEN ?= ${SPTOOLPATH}/sp_mk_generator.py + +# Variables for use with ROMLIB +ROMLIBPATH ?= lib/romlib + +# Variable for use with Python +PYTHON ?= python3 + +# Variables for use with PRINT_MEMORY_MAP +PRINT_MEMORY_MAP_PATH ?= tools/memory +PRINT_MEMORY_MAP ?= ${PRINT_MEMORY_MAP_PATH}/print_memory_map.py + +# Variables for use with documentation build using Sphinx tool +DOCS_PATH ?= docs + +# Defination of SIMICS flag +SIMICS_BUILD ?= 0 + +################################################################################ +# Include BL specific makefiles +################################################################################ + +ifeq (${NEED_BL1},yes) +include bl1/bl1.mk +endif + +ifeq (${NEED_BL2},yes) +include bl2/bl2.mk +endif + +ifeq (${NEED_BL2U},yes) +include bl2u/bl2u.mk +endif + +ifeq (${NEED_BL31},yes) +include bl31/bl31.mk +endif + +################################################################################ +# Build options checks +################################################################################ + +$(eval $(call assert_booleans,\ + $(sort \ + ALLOW_RO_XLAT_TABLES \ + BL2_ENABLE_SP_LOAD \ + COLD_BOOT_SINGLE_CPU \ + CREATE_KEYS \ + CTX_INCLUDE_AARCH32_REGS \ + CTX_INCLUDE_FPREGS \ + CTX_INCLUDE_PAUTH_REGS \ + CTX_INCLUDE_MTE_REGS \ + CTX_INCLUDE_EL2_REGS \ + CTX_INCLUDE_NEVE_REGS \ + DEBUG \ + DISABLE_MTPMU \ + DYN_DISABLE_AUTH \ + EL3_EXCEPTION_HANDLING \ + ENABLE_AMU \ + ENABLE_AMU_AUXILIARY_COUNTERS \ + ENABLE_AMU_FCONF \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RME \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SME_FOR_NS \ + ENABLE_SME_FOR_SWD \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ENABLE_SVE_FOR_SWD \ + ERROR_DEPRECATED \ + FAULT_INJECTION_SUPPORT \ + GENERATE_COT \ + GICV2_G0_FOR_EL3 \ + HANDLE_EA_EL3_FIRST \ + HW_ASSISTED_COHERENCY \ + INVERTED_MEMMAP \ + MEASURED_BOOT \ + NS_TIMER_SWITCH \ + OVERRIDE_LIBC \ + PL011_GENERIC_UART \ + PROGRAMMABLE_RESET_ADDRESS \ + PSCI_EXTENDED_STATE_ID \ + RAS_EXTENSION \ + RESET_TO_BL31 \ + SAVE_KEYS \ + SEPARATE_CODE_AND_RODATA \ + SEPARATE_BL2_NOLOAD_REGION \ + SEPARATE_NOBITS_REGION \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + CRYPTO_SUPPORT \ + USE_COHERENT_MEM \ + USE_DEBUGFS \ + ARM_IO_IN_DTB \ + SDEI_IN_FCONF \ + SEC_INT_DESC_IN_FCONF \ + USE_ROMLIB \ + USE_TBBR_DEFS \ + WARMBOOT_ENABLE_DCACHE_EARLY \ + BL2_AT_EL3 \ + BL2_IN_XIP_MEM \ + BL2_INV_DCACHE \ + USE_SPINLOCK_CAS \ + ENCRYPT_BL31 \ + ENCRYPT_BL32 \ + ERRATA_SPECULATIVE_AT \ + RAS_TRAP_LOWER_EL_ERR_ACCESS \ + COT_DESC_IN_DTB \ + USE_SP804_TIMER \ + ENABLE_FEAT_RNG \ + ENABLE_FEAT_SB \ + ENABLE_FEAT_DIT \ + PSA_FWU_SUPPORT \ + ENABLE_TRBE_FOR_NS \ + ENABLE_SYS_REG_TRACE_FOR_NS \ + ENABLE_TRF_FOR_NS \ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ + ENABLE_FEAT_FGT \ + ENABLE_FEAT_AMUv1 \ + ENABLE_FEAT_ECV \ + SIMICS_BUILD \ +))) + +$(eval $(call assert_numerics,\ + $(sort \ + ARM_ARCH_MAJOR \ + ARM_ARCH_MINOR \ + BRANCH_PROTECTION \ + FW_ENC_STATUS \ + NR_OF_FW_BANKS \ + NR_OF_IMAGES_IN_FW_BANK \ +))) + +ifdef KEY_SIZE + $(eval $(call assert_numeric,KEY_SIZE)) +endif + +ifeq ($(filter $(SANITIZE_UB), on off trap),) + $(error "Invalid value for SANITIZE_UB: can be one of on, off, trap") +endif + +################################################################################ +# Add definitions to the cpp preprocessor based on the current build options. +# This is done after including the platform specific makefile to allow the +# platform to overwrite the default options +################################################################################ + +$(eval $(call add_defines,\ + $(sort \ + ALLOW_RO_XLAT_TABLES \ + ARM_ARCH_MAJOR \ + ARM_ARCH_MINOR \ + BL2_ENABLE_SP_LOAD \ + COLD_BOOT_SINGLE_CPU \ + CTX_INCLUDE_AARCH32_REGS \ + CTX_INCLUDE_FPREGS \ + CTX_INCLUDE_PAUTH_REGS \ + EL3_EXCEPTION_HANDLING \ + CTX_INCLUDE_MTE_REGS \ + CTX_INCLUDE_EL2_REGS \ + CTX_INCLUDE_NEVE_REGS \ + DECRYPTION_SUPPORT_${DECRYPTION_SUPPORT} \ + DISABLE_MTPMU \ + ENABLE_AMU \ + ENABLE_AMU_AUXILIARY_COUNTERS \ + ENABLE_AMU_FCONF \ + AMU_RESTRICT_COUNTERS \ + ENABLE_ASSERTIONS \ + ENABLE_BTI \ + ENABLE_MPAM_FOR_LOWER_ELS \ + ENABLE_PAUTH \ + ENABLE_PIE \ + ENABLE_PMF \ + ENABLE_PSCI_STAT \ + ENABLE_RME \ + ENABLE_RUNTIME_INSTRUMENTATION \ + ENABLE_SME_FOR_NS \ + ENABLE_SME_FOR_SWD \ + ENABLE_SPE_FOR_LOWER_ELS \ + ENABLE_SVE_FOR_NS \ + ENABLE_SVE_FOR_SWD \ + ENCRYPT_BL31 \ + ENCRYPT_BL32 \ + ERROR_DEPRECATED \ + FAULT_INJECTION_SUPPORT \ + GICV2_G0_FOR_EL3 \ + HANDLE_EA_EL3_FIRST \ + HW_ASSISTED_COHERENCY \ + LOG_LEVEL \ + MEASURED_BOOT \ + NS_TIMER_SWITCH \ + PL011_GENERIC_UART \ + PLAT_${PLAT} \ + PROGRAMMABLE_RESET_ADDRESS \ + PSCI_EXTENDED_STATE_ID \ + RAS_EXTENSION \ + RESET_TO_BL31 \ + SEPARATE_CODE_AND_RODATA \ + SEPARATE_BL2_NOLOAD_REGION \ + SEPARATE_NOBITS_REGION \ + RECLAIM_INIT_CODE \ + SPD_${SPD} \ + SPIN_ON_BL1_EXIT \ + SPM_MM \ + SPMD_SPM_AT_SEL2 \ + TRUSTED_BOARD_BOOT \ + CRYPTO_SUPPORT \ + TRNG_SUPPORT \ + USE_COHERENT_MEM \ + USE_DEBUGFS \ + ARM_IO_IN_DTB \ + SDEI_IN_FCONF \ + SEC_INT_DESC_IN_FCONF \ + USE_ROMLIB \ + USE_TBBR_DEFS \ + WARMBOOT_ENABLE_DCACHE_EARLY \ + BL2_AT_EL3 \ + BL2_IN_XIP_MEM \ + BL2_INV_DCACHE \ + USE_SPINLOCK_CAS \ + ERRATA_SPECULATIVE_AT \ + RAS_TRAP_LOWER_EL_ERR_ACCESS \ + COT_DESC_IN_DTB \ + USE_SP804_TIMER \ + ENABLE_FEAT_RNG \ + ENABLE_FEAT_SB \ + ENABLE_FEAT_DIT \ + NR_OF_FW_BANKS \ + NR_OF_IMAGES_IN_FW_BANK \ + PSA_FWU_SUPPORT \ + ENABLE_TRBE_FOR_NS \ + ENABLE_SYS_REG_TRACE_FOR_NS \ + ENABLE_TRF_FOR_NS \ + ENABLE_FEAT_HCX \ + ENABLE_MPMM \ + ENABLE_MPMM_FCONF \ + ENABLE_FEAT_FGT \ + ENABLE_FEAT_AMUv1 \ + ENABLE_FEAT_ECV \ + SIMICS_BUILD \ +))) + +ifeq (${SANITIZE_UB},trap) + $(eval $(call add_define,MONITOR_TRAPS)) +endif + +# Define the EL3_PAYLOAD_BASE flag only if it is provided. +ifdef EL3_PAYLOAD_BASE + $(eval $(call add_define,EL3_PAYLOAD_BASE)) +else + # Define the PRELOADED_BL33_BASE flag only if it is provided and + # EL3_PAYLOAD_BASE is not defined, as it has priority. + ifdef PRELOADED_BL33_BASE + $(eval $(call add_define,PRELOADED_BL33_BASE)) + endif +endif + +# Define the DYN_DISABLE_AUTH flag only if set. +ifeq (${DYN_DISABLE_AUTH},1) +$(eval $(call add_define,DYN_DISABLE_AUTH)) +endif + +ifneq ($(findstring armlink,$(notdir $(LD))),) +$(eval $(call add_define,USE_ARM_LINK)) +endif + +# Generate and include sp_gen.mk if SPD is spmd and SP_LAYOUT_FILE is defined +ifeq (${SPD},spmd) +ifdef SP_LAYOUT_FILE + -include $(BUILD_PLAT)/sp_gen.mk + FIP_DEPS += sp + CRT_DEPS += sp + NEED_SP_PKG := yes +else + ifeq (${SPMD_SPM_AT_SEL2},1) + $(error "SPMD with SPM at S-EL2 require SP_LAYOUT_FILE") + endif +endif +endif + +################################################################################ +# Build targets +################################################################################ + +.PHONY: all msg_start clean realclean distclean cscope locate-checkpatch checkcodebase checkpatch fiptool sptool fip sp fwu_fip certtool dtbs memmap doc enctool +.SUFFIXES: + +all: msg_start + +msg_start: + @echo "Building ${PLAT}" + +ifeq (${ERROR_DEPRECATED},0) +# Check if deprecated declarations and cpp warnings should be treated as error or not. +ifneq ($(findstring clang,$(notdir $(CC))),) + CPPFLAGS += -Wno-error=deprecated-declarations +else + CPPFLAGS += -Wno-error=deprecated-declarations -Wno-error=cpp +endif +endif # !ERROR_DEPRECATED + +$(eval $(call MAKE_LIB_DIRS)) +$(eval $(call MAKE_LIB,c)) + +# Expand build macros for the different images +ifeq (${NEED_BL1},yes) +BL1_SOURCES := $(sort ${BL1_SOURCES}) + +$(eval $(call MAKE_BL,bl1)) +endif + +ifeq (${NEED_BL2},yes) +ifeq (${BL2_AT_EL3}, 0) +FIP_BL2_ARGS := tb-fw +endif + +BL2_SOURCES := $(sort ${BL2_SOURCES}) + +$(if ${BL2}, $(eval $(call TOOL_ADD_IMG,bl2,--${FIP_BL2_ARGS})),\ + $(eval $(call MAKE_BL,bl2,${FIP_BL2_ARGS}))) +endif + +ifeq (${NEED_SCP_BL2},yes) +$(eval $(call TOOL_ADD_IMG,scp_bl2,--scp-fw)) +endif + +ifeq (${NEED_BL31},yes) +BL31_SOURCES += ${SPD_SOURCES} +# Sort BL31 source files to remove duplicates +BL31_SOURCES := $(sort ${BL31_SOURCES}) +ifneq (${DECRYPTION_SUPPORT},none) +$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw,,$(ENCRYPT_BL31))),\ + $(eval $(call MAKE_BL,bl31,soc-fw,,$(ENCRYPT_BL31)))) +else +$(if ${BL31}, $(eval $(call TOOL_ADD_IMG,bl31,--soc-fw)),\ + $(eval $(call MAKE_BL,bl31,soc-fw))) +endif +endif + +# If a BL32 image is needed but neither BL32 nor BL32_SOURCES is defined, the +# build system will call TOOL_ADD_IMG to print a warning message and abort the +# process. Note that the dependency on BL32 applies to the FIP only. +ifeq (${NEED_BL32},yes) +# Sort BL32 source files to remove duplicates +BL32_SOURCES := $(sort ${BL32_SOURCES}) +BUILD_BL32 := $(if $(BL32),,$(if $(BL32_SOURCES),1)) + +ifneq (${DECRYPTION_SUPPORT},none) +$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw,,$(ENCRYPT_BL32))),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw,,$(ENCRYPT_BL32)))) +else +$(if ${BUILD_BL32}, $(eval $(call MAKE_BL,bl32,tos-fw)),\ + $(eval $(call TOOL_ADD_IMG,bl32,--tos-fw))) +endif +endif + +# If RMM image is needed but RMM is not defined, Test Realm Payload (TRP) +# needs to be built from RMM_SOURCES. +ifeq (${NEED_RMM},yes) +# Sort RMM source files to remove duplicates +RMM_SOURCES := $(sort ${RMM_SOURCES}) +BUILD_RMM := $(if $(RMM),,$(if $(RMM_SOURCES),1)) + +$(if ${BUILD_RMM}, $(eval $(call MAKE_BL,rmm,rmm-fw)),\ + $(eval $(call TOOL_ADD_IMG,rmm,--rmm-fw))) +endif + +# Add the BL33 image if required by the platform +ifeq (${NEED_BL33},yes) +$(eval $(call TOOL_ADD_IMG,bl33,--nt-fw)) +endif + +ifeq (${NEED_BL2U},yes) +$(if ${BL2U}, $(eval $(call TOOL_ADD_IMG,bl2u,--ap-fwu-cfg,FWU_)),\ + $(eval $(call MAKE_BL,bl2u,ap-fwu-cfg,FWU_))) +endif + +# Expand build macros for the different images +ifeq (${NEED_FDT},yes) + $(eval $(call MAKE_DTBS,$(BUILD_PLAT)/fdts,$(FDT_SOURCES))) +endif + +# Add Secure Partition packages +ifeq (${NEED_SP_PKG},yes) +$(BUILD_PLAT)/sp_gen.mk: ${SP_MK_GEN} ${SP_LAYOUT_FILE} | ${BUILD_PLAT} + ${Q}${PYTHON} "$<" "$@" $(filter-out $<,$^) $(BUILD_PLAT) ${COT} +sp: $(SPTOOL) $(DTBS) $(BUILD_PLAT)/sp_gen.mk + ${Q}$(SPTOOL) $(SPTOOL_ARGS) + @${ECHO_BLANK_LINE} + @echo "Built SP Images successfully" + @${ECHO_BLANK_LINE} +endif + +locate-checkpatch: +ifndef CHECKPATCH + $(error "Please set CHECKPATCH to point to the Linux checkpatch.pl file, eg: CHECKPATCH=../linux/scripts/checkpatch.pl") +else +ifeq (,$(wildcard ${CHECKPATCH})) + $(error "The file CHECKPATCH points to cannot be found, use eg: CHECKPATCH=../linux/scripts/checkpatch.pl") +endif +endif + +clean: + @echo " CLEAN" + $(call SHELL_REMOVE_DIR,${BUILD_PLAT}) +ifdef UNIX_MK + ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) clean +endif + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} clean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} clean + ${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean + +realclean distclean: + @echo " REALCLEAN" + $(call SHELL_REMOVE_DIR,${BUILD_BASE}) + $(call SHELL_DELETE_ALL, ${CURDIR}/cscope.*) +ifdef UNIX_MK + ${Q}${MAKE} --no-print-directory -C ${FIPTOOLPATH} clean +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) realclean +endif + ${Q}${MAKE} --no-print-directory -C ${SPTOOLPATH} clean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${CRTTOOLPATH} realclean + ${Q}${MAKE} PLAT=${PLAT} --no-print-directory -C ${ENCTOOLPATH} realclean + ${Q}${MAKE} --no-print-directory -C ${ROMLIBPATH} clean + +checkcodebase: locate-checkpatch + @echo " CHECKING STYLE" + @if test -d .git ; then \ + git ls-files | grep -E -v 'libfdt|libc|docs|\.rst' | \ + while read GIT_FILE ; \ + do ${CHECKPATCH} ${CHECKCODE_ARGS} -f $$GIT_FILE ; \ + done ; \ + else \ + find . -type f -not -iwholename "*.git*" \ + -not -iwholename "*build*" \ + -not -iwholename "*libfdt*" \ + -not -iwholename "*libc*" \ + -not -iwholename "*docs*" \ + -not -iwholename "*.rst" \ + -exec ${CHECKPATCH} ${CHECKCODE_ARGS} -f {} \; ; \ + fi + +checkpatch: locate-checkpatch + @echo " CHECKING STYLE" + @if test -n "${CHECKPATCH_OPTS}"; then \ + echo " with ${CHECKPATCH_OPTS} option(s)"; \ + fi + ${Q}COMMON_COMMIT=$$(git merge-base HEAD ${BASE_COMMIT}); \ + for commit in `git rev-list --no-merges $$COMMON_COMMIT..HEAD`; \ + do \ + printf "\n[*] Checking style of '$$commit'\n\n"; \ + git log --format=email "$$commit~..$$commit" \ + -- ${CHECK_PATHS} | \ + ${CHECKPATCH} ${CHECKPATCH_OPTS} - || true; \ + git diff --format=email "$$commit~..$$commit" \ + -- ${CHECK_PATHS} | \ + ${CHECKPATCH} ${CHECKPATCH_OPTS} - || true; \ + done + +certtool: ${CRTTOOL} + +${CRTTOOL}: FORCE + ${Q}${MAKE} PLAT=${PLAT} USE_TBBR_DEFS=${USE_TBBR_DEFS} COT=${COT} OPENSSL_DIR=${OPENSSL_DIR} CRTTOOL=${CRTTOOL} --no-print-directory -C ${CRTTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +ifneq (${GENERATE_COT},0) +certificates: ${CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "Certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif + +${BUILD_PLAT}/${FIP_NAME}: ${FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_FIP_CMD}) + ${Q}${FIPTOOL} create ${FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +ifneq (${GENERATE_COT},0) +fwu_certificates: ${FWU_CRT_DEPS} ${CRTTOOL} + ${Q}${CRTTOOL} ${FWU_CRT_ARGS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @echo "FWU certificates can be found in ${BUILD_PLAT}" + @${ECHO_BLANK_LINE} +endif + +${BUILD_PLAT}/${FWU_FIP_NAME}: ${FWU_FIP_DEPS} ${FIPTOOL} + $(eval ${CHECK_FWU_FIP_CMD}) + ${Q}${FIPTOOL} create ${FWU_FIP_ARGS} $@ + ${Q}${FIPTOOL} info $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +fiptool: ${FIPTOOL} +fip: ${BUILD_PLAT}/${FIP_NAME} +fwu_fip: ${BUILD_PLAT}/${FWU_FIP_NAME} + +${FIPTOOL}: FORCE +ifdef UNIX_MK + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" FIPTOOL=${FIPTOOL} OPENSSL_DIR=${OPENSSL_DIR} --no-print-directory -C ${FIPTOOLPATH} +else +# Clear the MAKEFLAGS as we do not want +# to pass the gnumake flags to nmake. + ${Q}set MAKEFLAGS= && ${MSVC_NMAKE} /nologo /f ${FIPTOOLPATH}/Makefile.msvc FIPTOOLPATH=$(subst /,\,$(FIPTOOLPATH)) FIPTOOL=$(subst /,\,$(FIPTOOL)) +endif + +sptool: ${SPTOOL} +${SPTOOL}: FORCE + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" SPTOOL=${SPTOOL} --no-print-directory -C ${SPTOOLPATH} + +romlib.bin: libraries FORCE + ${Q}${MAKE} PLAT_DIR=${PLAT_DIR} BUILD_PLAT=${BUILD_PLAT} ENABLE_BTI=${ENABLE_BTI} ARM_ARCH_MINOR=${ARM_ARCH_MINOR} INCLUDES='${INCLUDES}' DEFINES='${DEFINES}' --no-print-directory -C ${ROMLIBPATH} all + +# Call print_memory_map tool +memmap: all + ${Q}${PYTHON} ${PRINT_MEMORY_MAP} ${BUILD_PLAT} ${INVERTED_MEMMAP} + +doc: + @echo " BUILD DOCUMENTATION" + ${Q}${MAKE} --no-print-directory -C ${DOCS_PATH} html + +enctool: ${ENCTOOL} + +${ENCTOOL}: FORCE + ${Q}${MAKE} PLAT=${PLAT} BUILD_INFO=0 OPENSSL_DIR=${OPENSSL_DIR} ENCTOOL=${ENCTOOL} --no-print-directory -C ${ENCTOOLPATH} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +cscope: + @echo " CSCOPE" + ${Q}find ${CURDIR} -name "*.[chsS]" > cscope.files + ${Q}cscope -b -q -k + +help: + @echo "usage: ${MAKE} [PLAT=] [OPTIONS] [TARGET]" + @echo "" + @echo "PLAT is used to specify which platform you wish to build." + @echo "If no platform is specified, PLAT defaults to: ${DEFAULT_PLAT}" + @echo "" + @echo "platform = ${PLATFORM_LIST}" + @echo "" + @echo "Please refer to the User Guide for a list of all supported options." + @echo "Note that the build system doesn't track dependencies for build " + @echo "options. Therefore, if any of the build options are changed " + @echo "from a previous build, a clean build must be performed." + @echo "" + @echo "Supported Targets:" + @echo " all Build all individual bootloader binaries" + @echo " bl1 Build the BL1 binary" + @echo " bl2 Build the BL2 binary" + @echo " bl2u Build the BL2U binary" + @echo " bl31 Build the BL31 binary" + @echo " bl32 Build the BL32 binary. If ARCH=aarch32, then " + @echo " this builds secure payload specified by AARCH32_SP" + @echo " certificates Build the certificates (requires 'GENERATE_COT=1')" + @echo " fip Build the Firmware Image Package (FIP)" + @echo " fwu_fip Build the FWU Firmware Image Package (FIP)" + @echo " checkcodebase Check the coding style of the entire source tree" + @echo " checkpatch Check the coding style on changes in the current" + @echo " branch against BASE_COMMIT (default origin/master)" + @echo " clean Clean the build for the selected platform" + @echo " cscope Generate cscope index" + @echo " distclean Remove all build artifacts for all platforms" + @echo " certtool Build the Certificate generation tool" + @echo " enctool Build the Firmware encryption tool" + @echo " fiptool Build the Firmware Image Package (FIP) creation tool" + @echo " sp Build the Secure Partition Packages" + @echo " sptool Build the Secure Partition Package creation tool" + @echo " dtbs Build the Device Tree Blobs (if required for the platform)" + @echo " memmap Print the memory map of the built binaries" + @echo " doc Build html based documentation using Sphinx tool" + @echo "" + @echo "Note: most build targets require PLAT to be set to a specific platform." + @echo "" + @echo "example: build all targets for the FVP platform:" + @echo " CROSS_COMPILE=aarch64-none-elf- make PLAT=fvp all" + +.PHONY: FORCE +FORCE:; diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c b/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c new file mode 100644 index 0000000..ce04aaa --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../bl1_private.h" + +/******************************************************************************* + * TODO: Function that does the first bit of architectural setup. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + +} diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c b/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c new file mode 100644 index 0000000..85d35a7 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "../bl1_private.h" + +/* + * Following arrays will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ +static cpu_context_t bl1_cpu_context[2]; +static smc_ctx_t bl1_smc_context[2]; + +/* Following contains the next cpu context pointer. */ +static void *bl1_next_cpu_context_ptr; + +/* Following contains the next smc context pointer. */ +static void *bl1_next_smc_context_ptr; + +/* Following functions are used for SMC context handling */ +void *smc_get_ctx(unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + return &bl1_smc_context[security_state]; +} + +void smc_set_next_ctx(unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_next_smc_context_ptr = &bl1_smc_context[security_state]; +} + +void *smc_get_next_ctx(void) +{ + return bl1_next_smc_context_ptr; +} + +/* Following functions are used for CPU context handling */ +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return &bl1_cpu_context[security_state]; +} + +void cm_set_next_context(void *context) +{ + assert(context != NULL); + bl1_next_cpu_context_ptr = context; +} + +void *cm_get_next_context(void) +{ + return bl1_next_cpu_context_ptr; +} + +/******************************************************************************* + * Following function copies GP regs r0-r4, lr and spsr, + * from the CPU context to the SMC context structures. + ******************************************************************************/ +static void copy_cpu_ctx_to_smc_ctx(const regs_t *cpu_reg_ctx, + smc_ctx_t *next_smc_ctx) +{ + next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0); + next_smc_ctx->r1 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R1); + next_smc_ctx->r2 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R2); + next_smc_ctx->r3 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R3); + next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR); + next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR); + next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR); +} + +/******************************************************************************* + * Following function flushes the SMC & CPU context pointer and its data. + ******************************************************************************/ +static void flush_smc_and_cpu_ctx(void) +{ + flush_dcache_range((uintptr_t)&bl1_next_smc_context_ptr, + sizeof(bl1_next_smc_context_ptr)); + flush_dcache_range((uintptr_t)bl1_next_smc_context_ptr, + sizeof(smc_ctx_t)); + + flush_dcache_range((uintptr_t)&bl1_next_cpu_context_ptr, + sizeof(bl1_next_cpu_context_ptr)); + flush_dcache_range((uintptr_t)bl1_next_cpu_context_ptr, + sizeof(cpu_context_t)); +} + +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to HYP(if supported) else SVC. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + unsigned int security_state, mode = MODE32_svc; + image_desc_t *desc; + entry_point_info_t *next_bl_ep; + + /* 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; + + /* Get the image security state. */ + security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); + + /* Prepare the SPSR for the next BL image. */ + if ((security_state != SECURE) && (GET_VIRT_EXT(read_id_pfr1()) != 0U)) { + mode = MODE32_hyp; + } + + next_bl_ep->spsr = SPSR_MODE32(mode, SPSR_T_ARM, + SPSR_E_LITTLE, DISABLE_ALL_EXCEPTIONS); + + /* Allow platform to make change */ + bl1_plat_set_ep_info(image_id, next_bl_ep); + + /* Prepare the cpu context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + cm_set_next_context(cm_get_context(security_state)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(security_state); + copy_cpu_ctx_to_smc_ctx(get_regs_ctx(cm_get_next_context()), + smc_get_next_ctx()); + + /* + * If the next image is non-secure, then we need to program the banked + * non secure sctlr. This is not required when the next image is secure + * because in AArch32, we expect the secure world to have the same + * SCTLR settings. + */ + if (security_state == NON_SECURE) { + cpu_context_t *ctx = cm_get_context(security_state); + u_register_t ns_sctlr; + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } + + /* + * Flush the SMC & CPU context and the (next)pointers, + * to access them after caches are disabled. + */ + flush_smc_and_cpu_ctx(); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S b/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S new file mode 100644 index 0000000..94dfd37 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + + .globl bl1_vector_table + .globl bl1_entrypoint + + /* ----------------------------------------------------- + * Setup the vector table to support SVC & MON mode. + * ----------------------------------------------------- + */ +vector_base bl1_vector_table + b bl1_entrypoint + b report_exception /* Undef */ + b bl1_aarch32_smc_handler /* SMC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + /* ----------------------------------------------------- + * 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. +* --------------------------------------------------------------------- +*/ + el3_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_vector_table \ + _pie_fixup_size=0 + + /* ----------------------------------------------------- + * Perform BL1 setup + * ----------------------------------------------------- + */ + bl bl1_setup + + /* ----------------------------------------------------- + * Jump to main function. + * ----------------------------------------------------- + */ + bl bl1_main + + /* ----------------------------------------------------- + * Jump to next image. + * ----------------------------------------------------- + */ + + /* + * Get the smc_context for next BL image, + * program the gp/system registers and save it in `r4`. + */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* + * MMU needs to be disabled because both BL1 and BL2/BL2U execute + * in PL1, and therefore share the same address space. + * BL2/BL2U will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + +skip_mmu_off: + /* Restore smc_context from `r4` and exit secure monitor mode. */ + mov r0, r4 + monitor_exit +endfunc bl1_entrypoint diff --git a/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S b/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S new file mode 100644 index 0000000..493d2ca --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl bl1_aarch32_smc_handler + + +func bl1_aarch32_smc_handler + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + + /* ------------------------------------------------ + * SMC in BL1 is handled assuming that the MMU is + * turned off by BL2. + * ------------------------------------------------ + */ + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov lr, #BL1_SMC_RUN_IMAGE + cmp lr, r0 + bne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + ldcopr r8, SCR + tst r8, #SCR_NS_BIT + blne report_exception + + /* --------------------------------------------------------------------- + * Pass control to next secure image. + * Here it expects r1 to contain the address of a entry_point_info_t + * structure describing the BL entrypoint. + * --------------------------------------------------------------------- + */ + mov r8, r1 + mov r0, r1 + bl bl1_print_next_bl_ep_info + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov r0, r8 + bl bl1_plat_prepare_exit + + stcopr r0, TLBIALL + dsb sy + isb + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr_xc, r1 + + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + exception_return +endfunc bl1_aarch32_smc_handler + + /* ----------------------------------------------------- + * Save Secure/Normal world context and jump to + * BL1 SMC handler. + * ----------------------------------------------------- + */ +func smc_handler + /* ----------------------------------------------------- + * Save the GP registers. + * ----------------------------------------------------- + */ + smccc_save_gp_mode_regs + + /* + * `sp` still points to `smc_ctx_t`. Save it to a register + * and restore the C runtime stack pointer to `sp`. + */ + mov r6, sp + ldr sp, [r6, #SMC_CTX_SP_MON] + + ldr r0, [r6, #SMC_CTX_SCR] + and r7, r0, #SCR_NS_BIT /* flags */ + + /* Switch to Secure Mode */ + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + /* If caller is from Secure world then turn on the MMU */ + tst r7, #SCR_NS_BIT + bne skip_mmu_on + + /* Turn on the MMU */ + mov r0, #DISABLE_DCACHE + bl enable_mmu_svc_mon + + /* Enable the data cache. */ + ldcopr r9, SCTLR + orr r9, r9, #SCTLR_C_BIT + stcopr r9, SCTLR + isb + +skip_mmu_on: + /* Prepare arguments for BL1 SMC wrapper. */ + ldr r0, [r6, #SMC_CTX_GPREG_R0] /* smc_fid */ + mov r1, #0 /* cookie */ + mov r2, r6 /* handle */ + mov r3, r7 /* flags */ + bl bl1_smc_wrapper + + /* Get the smc_context for next BL image */ + bl smc_get_next_ctx + mov r4, r0 + + /* Only turn-off MMU if going to secure world */ + ldr r5, [r4, #SMC_CTX_SCR] + tst r5, #SCR_NS_BIT + bne skip_mmu_off + + /* Disable the MMU */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + +skip_mmu_off: + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + mov r0, r4 + monitor_exit +endfunc smc_handler diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c b/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c new file mode 100644 index 0000000..0a1cb30 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "../bl1_private.h" + +/******************************************************************************* + * Function that does the first bit of architectural setup that affects + * execution in the non-secure address space. + ******************************************************************************/ +void bl1_arch_setup(void) +{ + /* Set the next EL to be AArch64 */ + write_scr_el3(read_scr_el3() | SCR_RW_BIT); +} + +/******************************************************************************* + * 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_el3() & SCTLR_EE_BIT); + + /* Set SCTLR Secure EL1 */ + next_sctlr |= SCTLR_EL1_RES1; + + write_sctlr_el1(next_sctlr); +} diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c b/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c new file mode 100644 index 0000000..b9a7e5b --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "../bl1_private.h" + +/* Following contains the cpu context pointers. */ +static void *bl1_cpu_context_ptr[2]; +entry_point_info_t *bl2_ep_info; + + +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + return bl1_cpu_context_ptr[security_state]; +} + +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + bl1_cpu_context_ptr[security_state] = context; +} + +#if ENABLE_RME +/******************************************************************************* + * This function prepares the entry point information to run BL2 in Root world, + * i.e. EL3, for the case when FEAT_RME is enabled. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + image_desc_t *bl2_desc; + + assert(image_id == BL2_IMAGE_ID); + + /* Get the image descriptor. */ + bl2_desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(bl2_desc != NULL); + + /* Get the entry point info. */ + bl2_ep_info = &bl2_desc->ep_info; + + bl2_ep_info->spsr = (uint32_t)SPSR_64(MODE_EL3, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + /* + * Flush cache since bl2_ep_info is accessed after MMU is disabled + * before jumping to BL2. + */ + flush_dcache_range((uintptr_t)bl2_ep_info, sizeof(entry_point_info_t)); + + /* Indicate that image is in execution state. */ + bl2_desc->state = IMAGE_STATE_EXECUTED; + + /* Print debug info and flush the console before running BL2. */ + print_entry_point_info(bl2_ep_info); +} +#else +/******************************************************************************* + * This function prepares the context for Secure/Normal world images. + * Normal world images are transitioned to EL2(if supported) else EL1. + ******************************************************************************/ +void bl1_prepare_next_image(unsigned int image_id) +{ + + /* + * Following array will be used for context management. + * There are 2 instances, for the Secure and Non-Secure contexts. + */ + static cpu_context_t bl1_cpu_context[2]; + + unsigned int security_state, 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 " + "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; + + /* Get the image security state. */ + security_state = GET_SECURITY_STATE(next_bl_ep->h.attr); + + /* Setup the Secure/Non-Secure context if not done already. */ + if (cm_get_context(security_state) == NULL) + cm_set_context(&bl1_cpu_context[security_state], security_state); + + /* Prepare the SPSR for the next BL image. */ + if ((security_state != SECURE) && (el_implemented(2) != EL_IMPL_NONE)) { + mode = MODE_EL2; + } + + 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 the context for the next BL image. */ + cm_init_my_context(next_bl_ep); + cm_prepare_el3_exit(security_state); + + /* Indicate that image is in execution state. */ + desc->state = IMAGE_STATE_EXECUTED; + + print_entry_point_info(next_bl_ep); +} +#endif /* ENABLE_RME */ diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S b/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S new file mode 100644 index 0000000..f61c060 --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl1_entrypoint + .globl bl1_run_bl2_in_root + + + /* ----------------------------------------------------- + * 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. + * --------------------------------------------------------------------- + */ + el3_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 + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- + * Initialize platform and jump to our c-entry point + * for this type of reset. + * -------------------------------------------------------------------- + */ + bl bl1_main + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Disable pointer authentication before jumping to next boot image. + * -------------------------------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------- + * Do the transition to next boot image. + * -------------------------------------------------- + */ +#if ENABLE_RME + b bl1_run_bl2_in_root +#else + b el3_exit +#endif +endfunc bl1_entrypoint + + /* ----------------------------------------------------- + * void bl1_run_bl2_in_root(); + * This function runs BL2 in root/EL3 when RME is enabled. + * ----------------------------------------------------- + */ + +func bl1_run_bl2_in_root + /* read bl2_ep_info */ + adrp x20, bl2_ep_info + add x20, x20, :lo12:bl2_ep_info + ldr x20, [x20] + + /* --------------------------------------------- + * MMU needs to be disabled because BL2 executes + * in EL3. It will initialize the address space + * according to its own requirements. + * --------------------------------------------- + */ + bl disable_mmu_icache_el3 + tlbi alle3 + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, 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_bl2_in_root diff --git a/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S b/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S new file mode 100644 index 0000000..c54219f --- /dev/null +++ b/arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * 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 + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Expect only SMC exceptions */ + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x30, #EC_AARCH64_SMC + b.ne unexpected_sync_exception + + b smc_handler64 +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 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 + + +func smc_handler64 + + /* ---------------------------------------------- + * Detect if this is a RUN_IMAGE or other SMC. + * ---------------------------------------------- + */ + mov x30, #BL1_SMC_RUN_IMAGE + cmp x30, x0 + b.ne smc_handler + + /* ------------------------------------------------ + * Make sure only Secure world reaches here. + * ------------------------------------------------ + */ + mrs x30, scr_el3 + tst x30, #SCR_NS_BIT + b.ne unexpected_sync_exception + + /* ---------------------------------------------- + * Handling RUN_IMAGE SMC. First switch back to + * SP_EL0 for the C runtime stack. + * ---------------------------------------------- + */ + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #MODE_SP_EL0 + mov sp, x30 + + /* --------------------------------------------------------------------- + * Pass EL3 control to next BL image. + * Here it expects X1 with the address of a entry_point_info_t + * structure describing the next BL image entrypoint. + * --------------------------------------------------------------------- + */ + mov x20, x1 + + mov x0, x20 + bl bl1_print_next_bl_ep_info + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, x1 + ubfx x0, x1, #MODE_EL_SHIFT, #2 + cmp x0, #MODE_EL3 + b.ne unexpected_sync_exception + + bl disable_mmu_icache_el3 + tlbi alle3 + dsb ish /* ERET implies ISB, so it is not needed here */ + +#if SPIN_ON_BL1_EXIT + bl print_debug_loop_message +debug_loop: + b debug_loop +#endif + + mov x0, x20 + bl bl1_plat_prepare_exit + + 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 smc_handler64 + +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. + * ----------------------------------------------------- + */ +smc_handler: + /* ----------------------------------------------------- + * Save x0-x29 and ARMv8.3-PAuth (if enabled) registers. + * If Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, save PMCR_EL0 and + * disable Cycle Counter. + * TODO: Revisit to store only SMCCC specified registers. + * ----------------------------------------------------- + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* ----------------------------------------------------- + * Load and program stored APIAKey firmware key. + * Re-enable pointer authentication in EL3, as it was + * disabled before jumping to the next boot image. + * ----------------------------------------------------- + */ + bl pauth_load_bl1_apiakey_enable +#endif + /* ----------------------------------------------------- + * Populate the parameters for the SMC handler. We + * already have x0-x4 in place. x5 will point to a + * cookie (not used now). x6 will point to the context + * structure (SP_EL3) and x7 will contain flags we need + * to pass to the handler. + * ----------------------------------------------------- + */ + mov x5, xzr + mov x6, sp + + /* ----------------------------------------------------- + * Restore the saved C runtime stack value which will + * become the new SP_EL0 i.e. EL3 runtime stack. It was + * saved in the 'cpu_context' structure prior to the last + * ERET from EL3. + * ----------------------------------------------------- + */ + ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* --------------------------------------------- + * Switch back to SP_EL0 for the C runtime stack. + * --------------------------------------------- + */ + msr spsel, #MODE_SP_EL0 + mov sp, x12 + + /* ----------------------------------------------------- + * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there + * is a world switch during SMC handling. + * ----------------------------------------------------- + */ + mrs x16, spsr_el3 + mrs x17, elr_el3 + mrs x18, scr_el3 + stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ + bfi x7, x18, #0, #1 + + /* ----------------------------------------------------- + * Go to BL1 SMC handler. + * ----------------------------------------------------- + */ + bl bl1_smc_handler + + /* ----------------------------------------------------- + * Do the transition to next BL image. + * ----------------------------------------------------- + */ + b el3_exit diff --git a/arm-trusted-firmware/bl1/bl1.ld.S b/arm-trusted-firmware/bl1/bl1.ld.S new file mode 100644 index 0000000..bc23828 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1.ld.S @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * The .data section gets copied from ROM to RAM at runtime. + * Its LMA should be 16-byte aligned to allow efficient copying of 16-bytes + * aligned regions in it. + * Its VMA must be page-aligned as it marks the first read/write page. + */ +#define DATA_ALIGN 16 + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl1_entrypoint) + +MEMORY { + ROM (rx): ORIGIN = BL1_RO_BASE, LENGTH = BL1_RO_LIMIT - BL1_RO_BASE + RAM (rwx): ORIGIN = BL1_RW_BASE, LENGTH = BL1_RW_LIMIT - BL1_RW_BASE +} + +SECTIONS +{ + . = BL1_RO_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL1_RO_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl1_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >ROM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >ROM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >ROM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* + * No need to pad out the .rodata section to a page boundary. Next is + * the .data section, which can mapped in ROM with the same memory + * attributes as the .rodata section. + * + * Pad out to 16 bytes though as .data section needs to be 16 byte + * aligned and lld does not align the LMA to the aligment specified + * on the .data section. + */ + __RODATA_END__ = .; + . = ALIGN(16); + } >ROM +#else + ro . : { + __RO_START__ = .; + *bl1_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END__ = .; + + /* + * Pad out to 16 bytes as .data section needs to be 16 byte aligned and + * lld does not align the LMA to the aligment specified on the .data + * section. + */ + . = ALIGN(16); + } >ROM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + . = BL1_RW_BASE; + ASSERT(BL1_RW_BASE == ALIGN(PAGE_SIZE), + "BL1_RW_BASE address is not aligned on a page boundary.") + + DATA_SECTION >RAM AT>ROM + __DATA_RAM_START__ = __DATA_START__; + __DATA_RAM_END__ = __DATA_END__; + + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + __BL1_RAM_START__ = ADDR(.data); + __BL1_RAM_END__ = .; + + __DATA_ROM_START__ = LOADADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + /* + * The .data section is the last PROGBITS section so its end marks the end + * of BL1's actual content in Trusted ROM. + */ + __BL1_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL1_ROM_END__ <= BL1_RO_LIMIT, + "BL1's ROM content has exceeded its limit.") + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL1_RW_LIMIT, "BL1's RW section has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl1/bl1.mk b/arm-trusted-firmware/bl1/bl1.mk new file mode 100644 index 0000000..9f63fd5 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1.mk @@ -0,0 +1,32 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL1_SOURCES += bl1/${ARCH}/bl1_arch_setup.c \ + bl1/${ARCH}/bl1_context_mgmt.c \ + bl1/${ARCH}/bl1_entrypoint.S \ + bl1/${ARCH}/bl1_exceptions.S \ + bl1/bl1_main.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c \ + lib/el3_runtime/${ARCH}/context_mgmt.c \ + plat/common/plat_bl1_common.c \ + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL1_SOURCES += lib/extensions/mtpmu/${ARCH}/mtpmu.S +endif + +ifeq (${ARCH},aarch64) +BL1_SOURCES += lib/cpus/aarch64/dsu_helpers.S \ + lib/el3_runtime/aarch64/context.S +endif + +ifeq (${TRUSTED_BOARD_BOOT},1) +BL1_SOURCES += bl1/bl1_fwu.c +endif + +BL1_LINKERFILE := bl1/bl1.ld.S diff --git a/arm-trusted-firmware/bl1/bl1_fwu.c b/arm-trusted-firmware/bl1/bl1_fwu.c new file mode 100644 index 0000000..b70bffd --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_fwu.c @@ -0,0 +1,745 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bl1_private.h" + +/* + * Function declarations. + */ +static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags); +static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags); +static int bl1_fwu_image_execute(unsigned int image_id, + void **handle, + unsigned int flags); +static register_t bl1_fwu_image_resume(register_t image_param, + void **handle, + unsigned int flags); +static int bl1_fwu_sec_image_done(void **handle, + unsigned int flags); +static int bl1_fwu_image_reset(unsigned int image_id, + unsigned int flags); +__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved); + +/* + * This keeps track of last executed secure image id. + */ +static unsigned int sec_exec_image_id = INVALID_IMAGE_ID; + +/******************************************************************************* + * Top level handler for servicing FWU SMCs. + ******************************************************************************/ +u_register_t bl1_fwu_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, + unsigned int flags) +{ + + switch (smc_fid) { + case FWU_SMC_IMAGE_COPY: + SMC_RET1(handle, bl1_fwu_image_copy((uint32_t)x1, x2, + (uint32_t)x3, (uint32_t)x4, flags)); + + case FWU_SMC_IMAGE_AUTH: + SMC_RET1(handle, bl1_fwu_image_auth((uint32_t)x1, x2, + (uint32_t)x3, flags)); + + case FWU_SMC_IMAGE_EXECUTE: + SMC_RET1(handle, bl1_fwu_image_execute((uint32_t)x1, &handle, + flags)); + + case FWU_SMC_IMAGE_RESUME: + SMC_RET1(handle, bl1_fwu_image_resume((register_t)x1, &handle, + flags)); + + case FWU_SMC_SEC_IMAGE_DONE: + SMC_RET1(handle, bl1_fwu_sec_image_done(&handle, flags)); + + case FWU_SMC_IMAGE_RESET: + SMC_RET1(handle, bl1_fwu_image_reset((uint32_t)x1, flags)); + + case FWU_SMC_UPDATE_DONE: + bl1_fwu_done((void *)x1, NULL); + + default: + assert(false); /* Unreachable */ + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/******************************************************************************* + * Utility functions to keep track of the images that are loaded at any time. + ******************************************************************************/ + +#ifdef PLAT_FWU_MAX_SIMULTANEOUS_IMAGES +#define FWU_MAX_SIMULTANEOUS_IMAGES PLAT_FWU_MAX_SIMULTANEOUS_IMAGES +#else +#define FWU_MAX_SIMULTANEOUS_IMAGES 10 +#endif + +static unsigned int bl1_fwu_loaded_ids[FWU_MAX_SIMULTANEOUS_IMAGES] = { + [0 ... FWU_MAX_SIMULTANEOUS_IMAGES-1] = INVALID_IMAGE_ID +}; + +/* + * Adds an image_id to the bl1_fwu_loaded_ids array. + * Returns 0 on success, 1 on error. + */ +static int bl1_fwu_add_loaded_id(unsigned int image_id) +{ + int i; + + /* Check if the ID is already in the list */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == image_id) + return 0; + } + + /* Find an empty slot */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) { + bl1_fwu_loaded_ids[i] = image_id; + return 0; + } + } + + return 1; +} + +/* + * Removes an image_id from the bl1_fwu_loaded_ids array. + * Returns 0 on success, 1 on error. + */ +static int bl1_fwu_remove_loaded_id(unsigned int image_id) +{ + int i; + + /* Find the ID */ + for (i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + if (bl1_fwu_loaded_ids[i] == image_id) { + bl1_fwu_loaded_ids[i] = INVALID_IMAGE_ID; + return 0; + } + } + + return 1; +} + +/******************************************************************************* + * This function checks if the specified image overlaps another image already + * loaded. It returns 0 if there is no overlap, a negative error code otherwise. + ******************************************************************************/ +static int bl1_fwu_image_check_overlaps(unsigned int image_id) +{ + const image_desc_t *desc, *checked_desc; + const image_info_t *info, *checked_info; + + uintptr_t image_base, image_end; + uintptr_t checked_image_base, checked_image_end; + + checked_desc = bl1_plat_get_image_desc(image_id); + checked_info = &checked_desc->image_info; + + /* Image being checked mustn't be empty. */ + assert(checked_info->image_size != 0); + + checked_image_base = checked_info->image_base; + checked_image_end = checked_image_base + checked_info->image_size - 1; + /* No need to check for overflows, it's done in bl1_fwu_image_copy(). */ + + for (int i = 0; i < FWU_MAX_SIMULTANEOUS_IMAGES; i++) { + + /* Skip INVALID_IMAGE_IDs and don't check image against itself */ + if ((bl1_fwu_loaded_ids[i] == INVALID_IMAGE_ID) || + (bl1_fwu_loaded_ids[i] == image_id)) + continue; + + desc = bl1_plat_get_image_desc(bl1_fwu_loaded_ids[i]); + + /* Only check images that are loaded or being loaded. */ + assert ((desc != NULL) && (desc->state != IMAGE_STATE_RESET)); + + info = &desc->image_info; + + /* There cannot be overlaps with an empty image. */ + if (info->image_size == 0) + continue; + + image_base = info->image_base; + image_end = image_base + info->image_size - 1; + /* + * Overflows cannot happen. It is checked in + * bl1_fwu_image_copy() when the image goes from RESET to + * COPYING or COPIED. + */ + assert (image_end > image_base); + + /* Check if there are overlaps. */ + if (!((image_end < checked_image_base) || + (checked_image_end < image_base))) { + VERBOSE("Image with ID %d overlaps existing image with ID %d", + checked_desc->image_id, desc->image_id); + return -EPERM; + } + } + + return 0; +} + +/******************************************************************************* + * This function is responsible for copying secure images in AP Secure RAM. + ******************************************************************************/ +static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags) +{ + uintptr_t dest_addr; + unsigned int remaining; + image_desc_t *desc; + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + if (desc == NULL) { + WARN("BL1-FWU: Invalid image ID %u\n", image_id); + return -EPERM; + } + + /* + * The request must originate from a non-secure caller and target a + * secure image. Any other scenario is invalid. + */ + if (GET_SECURITY_STATE(flags) == SECURE) { + WARN("BL1-FWU: Copy not allowed from secure world.\n"); + return -EPERM; + } + if (GET_SECURITY_STATE(desc->ep_info.h.attr) == NON_SECURE) { + WARN("BL1-FWU: Copy not allowed for non-secure images.\n"); + return -EPERM; + } + + /* Check whether the FWU state machine is in the correct state. */ + if ((desc->state != IMAGE_STATE_RESET) && + (desc->state != IMAGE_STATE_COPYING)) { + WARN("BL1-FWU: Copy not allowed at this point of the FWU" + " process.\n"); + return -EPERM; + } + + if ((image_src == 0U) || (block_size == 0U) || + check_uptr_overflow(image_src, block_size - 1)) { + WARN("BL1-FWU: Copy not allowed due to invalid image source" + " or block size\n"); + return -ENOMEM; + } + + if (desc->state == IMAGE_STATE_COPYING) { + /* + * There must have been at least 1 copy operation for this image + * previously. + */ + assert(desc->copied_size != 0U); + /* + * The image size must have been recorded in the 1st copy + * operation. + */ + image_size = desc->image_info.image_size; + assert(image_size != 0); + assert(desc->copied_size < image_size); + + INFO("BL1-FWU: Continuing image copy in blocks\n"); + } else { /* desc->state == IMAGE_STATE_RESET */ + INFO("BL1-FWU: Initial call to copy an image\n"); + + /* + * image_size is relevant only for the 1st copy request, it is + * then ignored for subsequent calls for this image. + */ + if (image_size == 0) { + WARN("BL1-FWU: Copy not allowed due to invalid image" + " size\n"); + return -ENOMEM; + } + + /* Check that the image size to load is within limit */ + if (image_size > desc->image_info.image_max_size) { + WARN("BL1-FWU: Image size out of bounds\n"); + return -ENOMEM; + } + + /* Save the given image size. */ + desc->image_info.image_size = image_size; + + /* Make sure the image doesn't overlap other images. */ + if (bl1_fwu_image_check_overlaps(image_id) != 0) { + desc->image_info.image_size = 0; + WARN("BL1-FWU: This image overlaps another one\n"); + return -EPERM; + } + + /* + * copied_size must be explicitly initialized here because the + * FWU code doesn't necessarily do it when it resets the state + * machine. + */ + desc->copied_size = 0; + } + + /* + * If the given block size is more than the total image size + * then clip the former to the latter. + */ + remaining = image_size - desc->copied_size; + if (block_size > remaining) { + WARN("BL1-FWU: Block size is too big, clipping it.\n"); + block_size = remaining; + } + + /* Make sure the source image is mapped in memory. */ + if (bl1_plat_mem_check(image_src, block_size, flags) != 0) { + WARN("BL1-FWU: Source image is not mapped.\n"); + return -ENOMEM; + } + + if (bl1_fwu_add_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Too many images loaded at the same time.\n"); + return -ENOMEM; + } + + /* Allow the platform to handle pre-image load before copying */ + if (desc->state == IMAGE_STATE_RESET) { + if (bl1_plat_handle_pre_image_load(image_id) != 0) { + ERROR("BL1-FWU: Failure in pre-image load of image id %d\n", + image_id); + return -EPERM; + } + } + + /* Everything looks sane. Go ahead and copy the block of data. */ + dest_addr = desc->image_info.image_base + desc->copied_size; + (void)memcpy((void *) dest_addr, (const void *) image_src, block_size); + flush_dcache_range(dest_addr, block_size); + + desc->copied_size += block_size; + desc->state = (block_size == remaining) ? + IMAGE_STATE_COPIED : IMAGE_STATE_COPYING; + + INFO("BL1-FWU: Copy operation successful.\n"); + return 0; +} + +/******************************************************************************* + * This function is responsible for authenticating Normal/Secure images. + ******************************************************************************/ +static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags) +{ + int result; + uintptr_t base_addr; + unsigned int total_size; + image_desc_t *desc; + + /* Get the image descriptor. */ + desc = bl1_plat_get_image_desc(image_id); + if (desc == NULL) + return -EPERM; + + if (GET_SECURITY_STATE(flags) == SECURE) { + if (desc->state != IMAGE_STATE_RESET) { + WARN("BL1-FWU: Authentication from secure world " + "while in invalid state\n"); + return -EPERM; + } + } else { + if (GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE) { + if (desc->state != IMAGE_STATE_COPIED) { + WARN("BL1-FWU: Authentication of secure image " + "from non-secure world while not in copied state\n"); + return -EPERM; + } + } else { + if (desc->state != IMAGE_STATE_RESET) { + WARN("BL1-FWU: Authentication of non-secure image " + "from non-secure world while in invalid state\n"); + return -EPERM; + } + } + } + + if (desc->state == IMAGE_STATE_COPIED) { + /* + * Image is in COPIED state. + * Use the stored address and size. + */ + base_addr = desc->image_info.image_base; + total_size = desc->image_info.image_size; + } else { + if ((image_src == 0U) || (image_size == 0U) || + check_uptr_overflow(image_src, image_size - 1)) { + WARN("BL1-FWU: Auth not allowed due to invalid" + " image source/size\n"); + return -ENOMEM; + } + + /* + * Image is in RESET state. + * Check the parameters and authenticate the source image in place. + */ + if (bl1_plat_mem_check(image_src, image_size, \ + desc->ep_info.h.attr) != 0) { + WARN("BL1-FWU: Authentication arguments source/size not mapped\n"); + return -ENOMEM; + } + + if (bl1_fwu_add_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Too many images loaded at the same time.\n"); + return -ENOMEM; + } + + base_addr = image_src; + total_size = image_size; + + /* Update the image size in the descriptor. */ + desc->image_info.image_size = total_size; + } + + /* + * Authenticate the image. + */ + INFO("BL1-FWU: Authenticating image_id:%d\n", image_id); + result = auth_mod_verify_img(image_id, (void *)base_addr, total_size); + if (result != 0) { + WARN("BL1-FWU: Authentication Failed err=%d\n", result); + + /* + * Authentication has failed. + * Clear the memory if the image was copied. + * This is to prevent an attack where this contains + * some malicious code that can somehow be executed later. + */ + if (desc->state == IMAGE_STATE_COPIED) { + /* Clear the memory.*/ + zero_normalmem((void *)base_addr, total_size); + flush_dcache_range(base_addr, total_size); + + /* Indicate that image can be copied again*/ + desc->state = IMAGE_STATE_RESET; + } + + /* + * Even if this fails it's ok because the ID isn't in the array. + * The image cannot be in RESET state here, it is checked at the + * beginning of the function. + */ + (void)bl1_fwu_remove_loaded_id(image_id); + return -EAUTH; + } + + /* Indicate that image is in authenticated state. */ + desc->state = IMAGE_STATE_AUTHENTICATED; + + /* Allow the platform to handle post-image load */ + result = bl1_plat_handle_post_image_load(image_id); + if (result != 0) { + ERROR("BL1-FWU: Failure %d in post-image load of image id %d\n", + result, image_id); + /* + * Panic here as the platform handling of post-image load is + * not correct. + */ + plat_error_handler(result); + } + + /* + * Flush image_info to memory so that other + * secure world images can see changes. + */ + flush_dcache_range((uintptr_t)&desc->image_info, + sizeof(image_info_t)); + + INFO("BL1-FWU: Authentication was successful\n"); + + return 0; +} + +/******************************************************************************* + * This function is responsible for executing Secure images. + ******************************************************************************/ +static int bl1_fwu_image_execute(unsigned int image_id, + void **handle, + unsigned int flags) +{ + /* Get the image descriptor. */ + image_desc_t *desc = bl1_plat_get_image_desc(image_id); + + /* + * Execution is NOT allowed if: + * image_id is invalid OR + * Caller is from Secure world OR + * Image is Non-Secure OR + * Image is Non-Executable OR + * Image is NOT in AUTHENTICATED state. + */ + if ((desc == NULL) || + (GET_SECURITY_STATE(flags) == SECURE) || + (GET_SECURITY_STATE(desc->ep_info.h.attr) == NON_SECURE) || + (EP_GET_EXE(desc->ep_info.h.attr) == NON_EXECUTABLE) || + (desc->state != IMAGE_STATE_AUTHENTICATED)) { + WARN("BL1-FWU: Execution not allowed due to invalid state/args\n"); + return -EPERM; + } + + INFO("BL1-FWU: Executing Secure image\n"); + +#ifdef __aarch64__ + /* Save NS-EL1 system registers. */ + cm_el1_sysregs_context_save(NON_SECURE); +#endif + + /* Prepare the image for execution. */ + bl1_prepare_next_image(image_id); + + /* Update the secure image id. */ + sec_exec_image_id = image_id; + +#ifdef __aarch64__ + *handle = cm_get_context(SECURE); +#else + *handle = smc_get_ctx(SECURE); +#endif + return 0; +} + +/******************************************************************************* + * This function is responsible for resuming execution in the other security + * world + ******************************************************************************/ +static register_t bl1_fwu_image_resume(register_t image_param, + void **handle, + unsigned int flags) +{ + image_desc_t *desc; + unsigned int resume_sec_state; + unsigned int caller_sec_state = GET_SECURITY_STATE(flags); + + /* Get the image descriptor for last executed secure image id. */ + desc = bl1_plat_get_image_desc(sec_exec_image_id); + if (caller_sec_state == NON_SECURE) { + if (desc == NULL) { + WARN("BL1-FWU: Resume not allowed due to no available" + "secure image\n"); + return -EPERM; + } + } else { + /* desc must be valid for secure world callers */ + assert(desc != NULL); + } + + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE); + assert(EP_GET_EXE(desc->ep_info.h.attr) == EXECUTABLE); + + if (caller_sec_state == SECURE) { + assert(desc->state == IMAGE_STATE_EXECUTED); + + /* Update the flags. */ + desc->state = IMAGE_STATE_INTERRUPTED; + resume_sec_state = NON_SECURE; + } else { + assert(desc->state == IMAGE_STATE_INTERRUPTED); + + /* Update the flags. */ + desc->state = IMAGE_STATE_EXECUTED; + resume_sec_state = SECURE; + } + + INFO("BL1-FWU: Resuming %s world context\n", + (resume_sec_state == SECURE) ? "secure" : "normal"); + +#ifdef __aarch64__ + /* Save the EL1 system registers of calling world. */ + cm_el1_sysregs_context_save(caller_sec_state); + + /* Restore the EL1 system registers of resuming world. */ + cm_el1_sysregs_context_restore(resume_sec_state); + + /* Update the next context. */ + cm_set_next_eret_context(resume_sec_state); + + *handle = cm_get_context(resume_sec_state); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(resume_sec_state)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(resume_sec_state); + + *handle = smc_get_ctx(resume_sec_state); +#endif + return image_param; +} + +/******************************************************************************* + * This function is responsible for resuming normal world context. + ******************************************************************************/ +static int bl1_fwu_sec_image_done(void **handle, unsigned int flags) +{ + image_desc_t *desc; + + /* Make sure caller is from the secure world */ + if (GET_SECURITY_STATE(flags) == NON_SECURE) { + WARN("BL1-FWU: Image done not allowed from normal world\n"); + return -EPERM; + } + + /* Get the image descriptor for last executed secure image id */ + desc = bl1_plat_get_image_desc(sec_exec_image_id); + + /* desc must correspond to a valid secure executing image */ + assert(desc != NULL); + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) == SECURE); + assert(EP_GET_EXE(desc->ep_info.h.attr) == EXECUTABLE); + assert(desc->state == IMAGE_STATE_EXECUTED); + +#if ENABLE_ASSERTIONS + int rc = bl1_fwu_remove_loaded_id(sec_exec_image_id); + assert(rc == 0); +#else + bl1_fwu_remove_loaded_id(sec_exec_image_id); +#endif + + /* Update the flags. */ + desc->state = IMAGE_STATE_RESET; + sec_exec_image_id = INVALID_IMAGE_ID; + + INFO("BL1-FWU: Resuming Normal world context\n"); +#ifdef __aarch64__ + /* + * Secure world is done so no need to save the context. + * Just restore the Non-Secure context. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + + /* Update the next context. */ + cm_set_next_eret_context(NON_SECURE); + + *handle = cm_get_context(NON_SECURE); +#else + /* Update the next context. */ + cm_set_next_context(cm_get_context(NON_SECURE)); + + /* Prepare the smc context for the next BL image. */ + smc_set_next_ctx(NON_SECURE); + + *handle = smc_get_ctx(NON_SECURE); +#endif + return 0; +} + +/******************************************************************************* + * This function provides the opportunity for users to perform any + * platform specific handling after the Firmware update is done. + ******************************************************************************/ +__dead2 static void bl1_fwu_done(void *client_cookie, void *reserved) +{ + NOTICE("BL1-FWU: *******FWU Process Completed*******\n"); + + /* + * Call platform done function. + */ + bl1_plat_fwu_done(client_cookie, reserved); + assert(false); +} + +/******************************************************************************* + * This function resets an image to IMAGE_STATE_RESET. It fails if the image is + * being executed. + ******************************************************************************/ +static int bl1_fwu_image_reset(unsigned int image_id, unsigned int flags) +{ + image_desc_t *desc = bl1_plat_get_image_desc(image_id); + + if ((desc == NULL) || (GET_SECURITY_STATE(flags) == SECURE)) { + WARN("BL1-FWU: Reset not allowed due to invalid args\n"); + return -EPERM; + } + + switch (desc->state) { + + case IMAGE_STATE_RESET: + /* Nothing to do. */ + break; + + case IMAGE_STATE_INTERRUPTED: + case IMAGE_STATE_AUTHENTICATED: + case IMAGE_STATE_COPIED: + case IMAGE_STATE_COPYING: + + if (bl1_fwu_remove_loaded_id(image_id) != 0) { + WARN("BL1-FWU: Image reset couldn't find the image ID\n"); + return -EPERM; + } + + if (desc->copied_size != 0U) { + /* Clear the memory if the image is copied */ + assert(GET_SECURITY_STATE(desc->ep_info.h.attr) + == SECURE); + + zero_normalmem((void *)desc->image_info.image_base, + desc->copied_size); + flush_dcache_range(desc->image_info.image_base, + desc->copied_size); + } + + /* Reset status variables */ + desc->copied_size = 0; + desc->image_info.image_size = 0; + desc->state = IMAGE_STATE_RESET; + + /* Clear authentication state */ + auth_img_flags[image_id] = 0; + + break; + + case IMAGE_STATE_EXECUTED: + default: + assert(false); /* Unreachable */ + break; + } + + return 0; +} diff --git a/arm-trusted-firmware/bl1/bl1_main.c b/arm-trusted-firmware/bl1/bl1_main.c new file mode 100644 index 0000000..7399bc8 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_main.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bl1_private.h" + +static void bl1_load_bl2(void); + +#if ENABLE_PAUTH +uint64_t bl1_apiakey[2]; +#endif + +/******************************************************************************* + * 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_RW_BASE > bl1_mem_layout->total_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)); +} + +/******************************************************************************* + * 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(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} + +/******************************************************************************* + * 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 + */ +#ifdef __aarch64__ + val = read_sctlr_el3(); +#else + val = read_sctlr(); +#endif + assert((val & SCTLR_M_BIT) != 0); + assert((val & SCTLR_C_BIT) != 0); + assert((val & SCTLR_I_BIT) != 0); + /* + * 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(CACHE_WRITEBACK_GRANULE == SIZE_FROM_LOG2_WORDS(val)); + else + assert(CACHE_WRITEBACK_GRANULE <= MAX_CACHE_LINE_SIZE); +#endif /* ENABLE_ASSERTIONS */ + + /* Perform remaining generic architectural setup from EL3 */ + bl1_arch_setup(); + + crypto_mod_init(); + + /* Initialize authentication module */ + auth_mod_init(); + + /* Initialize the measured boot */ + bl1_plat_mboot_init(); + + /* Perform platform setup in BL1. */ + bl1_platform_setup(); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + bl1_apiakey[0] = read_apiakeylo_el1(); + bl1_apiakey[1] = read_apiakeyhi_el1(); +#endif /* ENABLE_PAUTH */ + + /* 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 == BL2_IMAGE_ID) + bl1_load_bl2(); + else + NOTICE("BL1-FWU: *******FWU Process Started*******\n"); + + /* Teardown the measured boot driver */ + bl1_plat_mboot_finish(); + + bl1_prepare_next_image(image_id); + + console_flush(); +} + +/******************************************************************************* + * This function locates and loads the BL2 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. + ******************************************************************************/ +static void bl1_load_bl2(void) +{ + image_desc_t *desc; + image_info_t *info; + int err; + + /* Get the image descriptor */ + desc = bl1_plat_get_image_desc(BL2_IMAGE_ID); + assert(desc != NULL); + + /* Get the image info */ + info = &desc->image_info; + INFO("BL1: Loading BL2\n"); + + err = bl1_plat_handle_pre_image_load(BL2_IMAGE_ID); + if (err != 0) { + ERROR("Failure in pre image load handling of BL2 (%d)\n", err); + plat_error_handler(err); + } + + err = load_auth_image(BL2_IMAGE_ID, info); + if (err != 0) { + ERROR("Failed to load BL2 firmware.\n"); + plat_error_handler(err); + } + + /* Allow platform to handle image information. */ + err = bl1_plat_handle_post_image_load(BL2_IMAGE_ID); + if (err != 0) { + ERROR("Failure in post image load handling of BL2 (%d)\n", err); + plat_error_handler(err); + } + + NOTICE("BL1: Booting BL2\n"); +} + +/******************************************************************************* + * 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) +{ +#ifdef __aarch64__ + NOTICE("BL1: Booting BL31\n"); +#else + NOTICE("BL1: Booting BL32\n"); +#endif /* __aarch64__ */ + 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 + +/******************************************************************************* + * Top level handler for servicing BL1 SMCs. + ******************************************************************************/ +u_register_t bl1_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, + unsigned int flags) +{ + /* BL1 Service UUID */ + DEFINE_SVC_UUID2(bl1_svc_uid, + U(0xd46739fd), 0xcb72, 0x9a4d, 0xb5, 0x75, + 0x67, 0x15, 0xd6, 0xf4, 0xbb, 0x4a); + + +#if TRUSTED_BOARD_BOOT + /* + * Dispatch FWU calls to FWU SMC handler and return its return + * value + */ + if (is_fwu_fid(smc_fid)) { + return bl1_fwu_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + + switch (smc_fid) { + case BL1_SMC_CALL_COUNT: + SMC_RET1(handle, BL1_NUM_SMC_CALLS); + + case BL1_SMC_UID: + SMC_UUID_RET(handle, bl1_svc_uid); + + case BL1_SMC_VERSION: + SMC_RET1(handle, BL1_SMC_MAJOR_VER | BL1_SMC_MINOR_VER); + + default: + WARN("Unimplemented BL1 SMC Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/******************************************************************************* + * BL1 SMC wrapper. This function is only used in AArch32 mode to ensure ABI + * compliance when invoking bl1_smc_handler. + ******************************************************************************/ +u_register_t bl1_smc_wrapper(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags) +{ + u_register_t x1, x2, x3, x4; + + assert(handle != NULL); + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + return bl1_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, flags); +} diff --git a/arm-trusted-firmware/bl1/bl1_private.h b/arm-trusted-firmware/bl1/bl1_private.h new file mode 100644 index 0000000..e119ba7 --- /dev/null +++ b/arm-trusted-firmware/bl1/bl1_private.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL1_PRIVATE_H +#define BL1_PRIVATE_H + +#include + +#include + +extern entry_point_info_t *bl2_ep_info; + +/****************************************** + * Function prototypes + *****************************************/ +void bl1_arch_setup(void); +void bl1_arch_next_el_setup(void); + +void bl1_prepare_next_image(unsigned int image_id); +void bl1_run_bl2_in_root(void); + +u_register_t bl1_fwu_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, + unsigned int flags); + +#endif /* BL1_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c b/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c new file mode 100644 index 0000000..4836712 --- /dev/null +++ b/arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +image_desc_t bl1_tbbr_image_descs[] = { + { + .image_id = FWU_CERT_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_1, image_info_t, 0), + .image_info.image_base = BL2_BASE, + .image_info.image_max_size = BL2_LIMIT - BL2_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_1, entry_point_info_t, SECURE), + }, +#if NS_BL1U_BASE + { + .image_id = NS_BL1U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, NON_SECURE | EXECUTABLE), + .ep_info.pc = NS_BL1U_BASE, + }, +#endif +#if SCP_BL2U_BASE + { + .image_id = SCP_BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_IMAGE_BINARY, + VERSION_1, image_info_t, 0), + .image_info.image_base = SCP_BL2U_BASE, + .image_info.image_max_size = SCP_BL2U_LIMIT - SCP_BL2U_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_IMAGE_BINARY, + VERSION_1, entry_point_info_t, SECURE), + }, +#endif +#if BL2U_BASE + { + .image_id = BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, + VERSION_1, image_info_t, 0), + .image_info.image_base = BL2U_BASE, + .image_info.image_max_size = BL2U_LIMIT - BL2U_BASE, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, SECURE | EXECUTABLE), + .ep_info.pc = BL2U_BASE, + }, +#endif +#if NS_BL2U_BASE + { + .image_id = NS_BL2U_IMAGE_ID, + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, + VERSION_1, entry_point_info_t, NON_SECURE), + }, +#endif + BL2_IMAGE_DESC, + + { + .image_id = INVALID_IMAGE_ID, + } +}; diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c b/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c new file mode 100644 index 0000000..4fd8d07 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../bl2_private.h" + +/******************************************************************************* + * Place holder function to perform any Secure SVC specific architectural + * setup. At the moment there is nothing to do. + ******************************************************************************/ +void bl2_arch_setup(void) +{ + +} diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S b/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S new file mode 100644 index 0000000..40154aa --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl bl2_entrypoint + + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + el3_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=bl2_vector_table \ + _pie_fixup_size=0 + + /* + * Restore parameters of boot rom + */ + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S b/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S new file mode 100644 index 0000000..087b665 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S b/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S new file mode 100644 index 0000000..6e8e2c1 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_vector_table + .globl bl2_entrypoint + + +vector_base bl2_vector_table + b bl2_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + +func bl2_entrypoint + /*--------------------------------------------- + * Save arguments x0 - x3 from BL1 for future + * use. + * --------------------------------------------- + */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + ldr r0, =bl2_vector_table + stcopr r0, VBAR + isb + + /* -------------------------------------------------------- + * Enable the instruction cache - disable speculative loads + * -------------------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_I_BIT + bic r0, r0, #SCTLR_DSSBS_BIT + stcopr r0, SCTLR + isb + + /* --------------------------------------------- + * Since BL2 executes after BL1, it is assumed + * here that BL1 has already has done the + * necessary register initializations. + * --------------------------------------------- + */ + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2 + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. + * --------------------------------------------- + */ + ldr r0, =__RW_START__ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + +#if USE_COHERENT_MEM + ldr r0, =__COHERENT_RAM_START__ + ldr r1, =__COHERENT_RAM_END_UNALIGNED__ + sub r1, r1, r0 + bl zeromem +#endif + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + + bl bl2_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S b/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S new file mode 100644 index 0000000..0b3554e --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_run_next_image + + +func bl2_run_next_image + mov r8,r0 + + /* + * MMU needs to be disabled because both BL2 and BL32 execute + * in PL1, and therefore share the same address space. + * BL32 will initialize the address space according to its + * own requirement. + */ + bl disable_mmu_icache_secure + stcopr r0, TLBIALL + dsb sy + isb + mov r0, r8 + bl bl2_el3_plat_prepare_exit + + /* + * Extract PC and SPSR based on struct `entry_point_info_t` + * and load it in LR and SPSR registers respectively. + */ + ldr lr, [r8, #ENTRY_POINT_INFO_PC_OFFSET] + ldr r1, [r8, #(ENTRY_POINT_INFO_PC_OFFSET + 4)] + msr spsr_xc, r1 + + /* Some BL32 stages expect lr_svc to provide the BL33 entry address */ + cps #MODE32_svc + ldr lr, [r8, #ENTRY_POINT_INFO_LR_SVC_OFFSET] + cps #MODE32_mon + + add r8, r8, #ENTRY_POINT_INFO_ARGS_OFFSET + ldm r8, {r0, r1, r2, r3} + exception_return +endfunc bl2_run_next_image diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c b/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c new file mode 100644 index 0000000..54052f7 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "../bl2_private.h" + +/******************************************************************************* + * Place holder function to perform any S-EL1 specific architectural setup. At + * the moment there is nothing to do. + ******************************************************************************/ +void bl2_arch_setup(void) +{ + /* Give access to FP/SIMD registers */ + write_cpacr(CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); +} diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S new file mode 100644 index 0000000..45bac7d --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + + .globl bl2_entrypoint + +#if BL2_IN_XIP_MEM +#define FIXUP_SIZE 0 +#else +#define FIXUP_SIZE ((BL2_LIMIT) - (BL2_BASE)) +#endif + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + el3_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=bl2_el3_exceptions \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------- + * Restore parameters of boot rom + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_el3_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S b/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S new file mode 100644 index 0000000..3d58051 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2. + * ----------------------------------------------------------------------------- + */ + .globl bl2_el3_exceptions + +vector_base bl2_el3_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 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +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 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S new file mode 100644 index 0000000..a021e42 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + + .globl bl2_entrypoint + + + +func bl2_entrypoint + /*--------------------------------------------- + * Save arguments x0 - x3 from BL1 for future + * use. + * --------------------------------------------- + */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + msr vbar_el1, x0 + isb + + /* --------------------------------------------- + * Enable the SError interrupt now that the + * exception vectors have been setup. + * --------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks and disable + * speculative loads. + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + bic x0, x0, #SCTLR_DSSBS_BIT + msr sctlr_el1, x0 + isb + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2 + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. + * --------------------------------------------- + */ + adr x0, __RW_START__ + adr x1, __RW_END__ + sub x1, x1, x0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if USE_COHERENT_MEM + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12:__COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 + bl zeromem +#endif + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl bl2_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S b/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S new file mode 100644 index 0000000..076e326 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + + .globl bl2_entrypoint + + +func bl2_entrypoint + /* Save arguments x0-x3 from previous Boot loader */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=bl2_el3_exceptions \ + _pie_fixup_size=0 + + /* --------------------------------------------- + * Restore parameters of boot rom + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + + /* --------------------------------------------- + * Perform BL2 setup + * --------------------------------------------- + */ + bl bl2_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler +endfunc bl2_entrypoint diff --git a/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S b/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S new file mode 100644 index 0000000..f0a8be8 --- /dev/null +++ b/arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2_run_next_image + + +func bl2_run_next_image + 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. + * --------------------------------------------- + */ + bl disable_mmu_icache_el3 + tlbi alle3 + bl bl2_el3_plat_prepare_exit + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Disable pointer authentication before jumping + * to next boot image. + * --------------------------------------------- + */ + bl pauth_disable_el3 +#endif /* ENABLE_PAUTH */ + + ldp x0, x1, [x20, #ENTRY_POINT_INFO_PC_OFFSET] + msr elr_el3, x0 + msr spsr_el3, 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 bl2_run_next_image diff --git a/arm-trusted-firmware/bl2/bl2.ld.S b/arm-trusted-firmware/bl2/bl2.ld.S new file mode 100644 index 0000000..d332ec0 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2.ld.S @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +} + + +SECTIONS +{ + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; +#if ENABLE_RME + *bl2_rme_entrypoint.o(.text*) +#else /* ENABLE_RME */ + *bl2_entrypoint.o(.text*) +#endif /* ENABLE_RME */ + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >RAM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl2_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl2/bl2.mk b/arm-trusted-firmware/bl2/bl2.mk new file mode 100644 index 0000000..7a973e5 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2_SOURCES += bl2/bl2_image_load_v2.c \ + bl2/bl2_main.c \ + bl2/${ARCH}/bl2_arch_setup.c \ + lib/locks/exclusive/${ARCH}/spinlock.S \ + plat/common/${ARCH}/platform_up_stack.S \ + ${MBEDTLS_SOURCES} + +ifeq (${ARCH},aarch64) +BL2_SOURCES += common/aarch64/early_exceptions.S +endif + +ifeq (${ENABLE_RME},1) +# Using RME, run BL2 at EL3 +include lib/gpt_rme/gpt_rme.mk + +BL2_SOURCES += bl2/${ARCH}/bl2_rme_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + bl2/${ARCH}/bl2_run_next_image.S \ + ${GPT_LIB_SRCS} +BL2_LINKERFILE := bl2/bl2.ld.S + +else ifeq (${BL2_AT_EL3},0) +# Normal operation, no RME, no BL2 at EL3 +BL2_SOURCES += bl2/${ARCH}/bl2_entrypoint.S +BL2_LINKERFILE := bl2/bl2.ld.S + +else +# BL2 at EL3, no RME +BL2_SOURCES += bl2/${ARCH}/bl2_el3_entrypoint.S \ + bl2/${ARCH}/bl2_el3_exceptions.S \ + bl2/${ARCH}/bl2_run_next_image.S \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c + +ifeq (${DISABLE_MTPMU},1) +BL2_SOURCES += lib/extensions/mtpmu/${ARCH}/mtpmu.S +endif + +ifeq (${ARCH},aarch64) +BL2_SOURCES += lib/cpus/aarch64/dsu_helpers.S +endif + +BL2_LINKERFILE := bl2/bl2_el3.ld.S +endif diff --git a/arm-trusted-firmware/bl2/bl2_el3.ld.S b/arm-trusted-firmware/bl2/bl2_el3.ld.S new file mode 100644 index 0000000..6aa7afd --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_el3.ld.S @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2_entrypoint) + +MEMORY { +#if BL2_IN_XIP_MEM + ROM (rx): ORIGIN = BL2_RO_BASE, LENGTH = BL2_RO_LIMIT - BL2_RO_BASE + RAM (rwx): ORIGIN = BL2_RW_BASE, LENGTH = BL2_RW_LIMIT - BL2_RW_BASE +#else + RAM (rwx): ORIGIN = BL2_BASE, LENGTH = BL2_LIMIT - BL2_BASE +#if SEPARATE_BL2_NOLOAD_REGION + RAM_NOLOAD (rw!a): ORIGIN = BL2_NOLOAD_START, LENGTH = BL2_NOLOAD_LIMIT - BL2_NOLOAD_START +#else +#define RAM_NOLOAD RAM +#endif +#endif +} + +#if !BL2_IN_XIP_MEM +#define ROM RAM +#endif + +SECTIONS +{ +#if BL2_IN_XIP_MEM + . = BL2_RO_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_RO_BASE address is not aligned on a page boundary.") +#else + . = BL2_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2_BASE address is not aligned on a page boundary.") +#endif + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >ROM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >ROM + + ASSERT(__TEXT_RESIDENT_END__ - __TEXT_RESIDENT_START__ <= PAGE_SIZE, + "Resident part of BL2 has exceeded its limit.") +#else + ro . : { + __RO_START__ = .; + __TEXT_RESIDENT_START__ = .; + *bl2_el3_entrypoint.o(.text*) + *(.text.asm.*) + __TEXT_RESIDENT_END__ = .; + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + + __RO_END__ = .; + } >ROM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + +#if BL2_IN_XIP_MEM + . = BL2_RW_BASE; + ASSERT(BL2_RW_BASE == ALIGN(PAGE_SIZE), + "BL2_RW_BASE address is not aligned on a page boundary.") +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM AT>ROM + __DATA_RAM_START__ = __DATA_START__; + __DATA_RAM_END__ = __DATA_END__; + + RELA_SECTION >RAM +#if SEPARATE_BL2_NOLOAD_REGION + SAVED_ADDR = .; + . = BL2_NOLOAD_START; + __BL2_NOLOAD_START__ = .; +#endif + STACK_SECTION >RAM_NOLOAD + BSS_SECTION >RAM_NOLOAD + XLAT_TABLE_SECTION >RAM_NOLOAD +#if SEPARATE_BL2_NOLOAD_REGION + __BL2_NOLOAD_END__ = .; + . = SAVED_ADDR; +#endif + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + +#if BL2_IN_XIP_MEM + __BL2_RAM_START__ = ADDR(.data); + __BL2_RAM_END__ = .; + + __DATA_ROM_START__ = LOADADDR(.data); + __DATA_SIZE__ = SIZEOF(.data); + + /* + * The .data section is the last PROGBITS section so its end marks the end + * of BL2's RO content in XIP memory.. + */ + __BL2_ROM_END__ = __DATA_ROM_START__ + __DATA_SIZE__; + ASSERT(__BL2_ROM_END__ <= BL2_RO_LIMIT, + "BL2's RO content has exceeded its limit.") +#endif + __BSS_SIZE__ = SIZEOF(.bss); + + +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + +#if BL2_IN_XIP_MEM + ASSERT(. <= BL2_RW_LIMIT, "BL2's RW content has exceeded its limit.") +#else + ASSERT(. <= BL2_LIMIT, "BL2 image has exceeded its limit.") +#endif +} diff --git a/arm-trusted-firmware/bl2/bl2_image_load_v2.c b/arm-trusted-firmware/bl2/bl2_image_load_v2.c new file mode 100644 index 0000000..dee3fc2 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_image_load_v2.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include "bl2_private.h" +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * This function loads SCP_BL2/BL3x images and returns the ep_info for + * the next executable image. + ******************************************************************************/ +struct entry_point_info *bl2_load_images(void) +{ + bl_params_t *bl2_to_next_bl_params; + bl_load_info_t *bl2_load_info; + const bl_load_info_node_t *bl2_node_info; + int plat_setup_done = 0; + int err; + + /* + * Get information about the images to load. + */ + bl2_load_info = plat_get_bl_image_load_info(); + assert(bl2_load_info != NULL); + assert(bl2_load_info->head != NULL); + assert(bl2_load_info->h.type == PARAM_BL_LOAD_INFO); + assert(bl2_load_info->h.version >= VERSION_2); + bl2_node_info = bl2_load_info->head; + + while (bl2_node_info != NULL) { + /* + * Perform platform setup before loading the image, + * if indicated in the image attributes AND if NOT + * already done before. + */ + if ((bl2_node_info->image_info->h.attr & + IMAGE_ATTRIB_PLAT_SETUP) != 0U) { + if (plat_setup_done != 0) { + WARN("BL2: Platform setup already done!!\n"); + } else { + INFO("BL2: Doing platform setup\n"); + bl2_platform_setup(); + plat_setup_done = 1; + } + } + + err = bl2_plat_handle_pre_image_load(bl2_node_info->image_id); + if (err != 0) { + ERROR("BL2: Failure in pre image load handling (%i)\n", err); + plat_error_handler(err); + } + + if ((bl2_node_info->image_info->h.attr & + IMAGE_ATTRIB_SKIP_LOADING) == 0U) { + INFO("BL2: Loading image id %u\n", bl2_node_info->image_id); + err = load_auth_image(bl2_node_info->image_id, + bl2_node_info->image_info); + if (err != 0) { + ERROR("BL2: Failed to load image id %u (%i)\n", + bl2_node_info->image_id, err); + plat_error_handler(err); + } + } else { + INFO("BL2: Skip loading image id %u\n", bl2_node_info->image_id); + } + + /* Allow platform to handle image information. */ + err = bl2_plat_handle_post_image_load(bl2_node_info->image_id); + if (err != 0) { + ERROR("BL2: Failure in post image load handling (%i)\n", err); + plat_error_handler(err); + } + + /* Go to next image */ + bl2_node_info = bl2_node_info->next_load_info; + } + + /* + * Get information to pass to the next image. + */ + bl2_to_next_bl_params = plat_get_next_bl_params(); + assert(bl2_to_next_bl_params != NULL); + assert(bl2_to_next_bl_params->head != NULL); + assert(bl2_to_next_bl_params->h.type == PARAM_BL_PARAMS); + assert(bl2_to_next_bl_params->h.version >= VERSION_2); + assert(bl2_to_next_bl_params->head->ep_info != NULL); + + /* Populate arg0 for the next BL image if not already provided */ + if (bl2_to_next_bl_params->head->ep_info->args.arg0 == (u_register_t)0) + bl2_to_next_bl_params->head->ep_info->args.arg0 = + (u_register_t)bl2_to_next_bl_params; + + /* Flush the parameters to be passed to next image */ + plat_flush_next_bl_params(); + + return bl2_to_next_bl_params->head->ep_info; +} diff --git a/arm-trusted-firmware/bl2/bl2_main.c b/arm-trusted-firmware/bl2/bl2_main.c new file mode 100644 index 0000000..5da8037 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_main.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "bl2_private.h" + +#ifdef __aarch64__ +#define NEXT_IMAGE "BL31" +#else +#define NEXT_IMAGE "BL32" +#endif + +#if BL2_AT_EL3 +/******************************************************************************* + * Setup function for BL2 when BL2_AT_EL3=1 + ******************************************************************************/ +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_el3_early_platform_setup(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl2_el3_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} +#else /* BL2_AT_EL3 */ +/******************************************************************************* + * Setup function for BL2 when BL2_AT_EL3=0 + ******************************************************************************/ +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl2_early_platform_setup2(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl2_plat_arch_setup(); + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} +#endif /* BL2_AT_EL3 */ + +/******************************************************************************* + * The only thing to do in BL2 is to load further images and pass control to + * next BL. The memory occupied by BL2 will be reclaimed by BL3x stages. BL2 + * runs entirely in S-EL1. + ******************************************************************************/ +void bl2_main(void) +{ + entry_point_info_t *next_bl_ep_info; + + NOTICE("BL2: %s\n", version_string); + NOTICE("BL2: %s\n", build_message); + + /* Perform remaining generic architectural setup in S-EL1 */ + bl2_arch_setup(); + +#if PSA_FWU_SUPPORT + fwu_init(); +#endif /* PSA_FWU_SUPPORT */ + + crypto_mod_init(); + + /* Initialize authentication module */ + auth_mod_init(); + + /* Initialize the Measured Boot backend */ + bl2_plat_mboot_init(); + + /* Initialize boot source */ + bl2_plat_preload_setup(); + + /* Load the subsequent bootloader images. */ + next_bl_ep_info = bl2_load_images(); + + /* Teardown the Measured Boot backend */ + bl2_plat_mboot_finish(); + +#if !BL2_AT_EL3 && !ENABLE_RME +#ifndef __aarch64__ + /* + * For AArch32 state BL1 and BL2 share the MMU setup. + * Given that BL2 does not map BL1 regions, MMU needs + * to be disabled in order to go back to BL1. + */ + disable_mmu_icache_secure(); +#endif /* !__aarch64__ */ + + console_flush(); + +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el1(); +#endif /* ENABLE_PAUTH */ + + /* + * Run next BL image via an SMC to BL1. Information on how to pass + * control to the BL32 (if present) and BL33 software images will + * be passed to next BL image as an argument. + */ + smc(BL1_SMC_RUN_IMAGE, (unsigned long)next_bl_ep_info, 0, 0, 0, 0, 0, 0); +#else /* if BL2_AT_EL3 || ENABLE_RME */ + NOTICE("BL2: Booting " NEXT_IMAGE "\n"); + print_entry_point_info(next_bl_ep_info); + console_flush(); + +#if ENABLE_PAUTH + /* + * Disable pointer authentication before running next boot image + */ + pauth_disable_el3(); +#endif /* ENABLE_PAUTH */ + + bl2_run_next_image(next_bl_ep_info); +#endif /* BL2_AT_EL3 && ENABLE_RME */ +} diff --git a/arm-trusted-firmware/bl2/bl2_private.h b/arm-trusted-firmware/bl2/bl2_private.h new file mode 100644 index 0000000..b1704d2 --- /dev/null +++ b/arm-trusted-firmware/bl2/bl2_private.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2_PRIVATE_H +#define BL2_PRIVATE_H + +#include + +/****************************************** + * Forward declarations + *****************************************/ +struct entry_point_info; + +/****************************************** + * Function prototypes + *****************************************/ +void bl2_arch_setup(void); +struct entry_point_info *bl2_load_images(void); +void bl2_run_next_image(const struct entry_point_info *bl_ep_info); + +#endif /* BL2_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S b/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S new file mode 100644 index 0000000..e4dd03d --- /dev/null +++ b/arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2u_vector_table + .globl bl2u_entrypoint + + +vector_base bl2u_vector_table + b bl2u_entrypoint + b report_exception /* Undef */ + b report_exception /* SVC call */ + b report_exception /* Prefetch abort */ + b report_exception /* Data abort */ + b report_exception /* Reserved */ + b report_exception /* IRQ */ + b report_exception /* FIQ */ + + +func bl2u_entrypoint + /*--------------------------------------------- + * Save from r1 the extents of the trusted ram + * available to BL2U for future use. + * r0 is not currently used. + * --------------------------------------------- + */ + mov r11, r1 + mov r10, r2 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + ldr r0, =bl2u_vector_table + stcopr r0, VBAR + isb + + /* -------------------------------------------------------- + * Enable the instruction cache - disable speculative loads + * -------------------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_I_BIT + bic r0, r0, #SCTLR_DSSBS_BIT + stcopr r0, SCTLR + isb + + /* --------------------------------------------- + * Since BL2U executes after BL1, it is assumed + * here that BL1 has already has done the + * necessary register initializations. + * --------------------------------------------- + */ + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2U + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. + * --------------------------------------------- + */ + ldr r0, =__RW_START__ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform early platform setup & platform + * specific early arch. setup e.g. mmu setup + * --------------------------------------------- + */ + mov r0, r11 + mov r1, r10 + bl bl2u_early_platform_setup + bl bl2u_plat_arch_setup + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl bl2u_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2u_entrypoint diff --git a/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S b/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S new file mode 100644 index 0000000..15978b6 --- /dev/null +++ b/arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl bl2u_entrypoint + + +func bl2u_entrypoint + /*--------------------------------------------- + * Store the extents of the tzram available to + * BL2U and other platform specific information + * for future use. x0 is currently not used. + * --------------------------------------------- + */ + mov x20, x1 + mov x21, x2 + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, early_exceptions + msr vbar_el1, x0 + isb + + /* --------------------------------------------- + * Enable the SError interrupt now that the + * exception vectors have been setup. + * --------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks and disable + * speculative loads. + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + bic x0, x0, #SCTLR_DSSBS_BIT + msr sctlr_el1, x0 + isb + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL2U + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. + * --------------------------------------------- + */ + adr x0, __RW_START__ + adr x1, __RW_END__ + sub x1, x1, x0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform early platform setup & platform + * specific early arch. setup e.g. mmu setup + * --------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + bl bl2u_early_platform_setup + bl bl2u_plat_arch_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication. + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif + + /* --------------------------------------------- + * Jump to bl2u_main function. + * --------------------------------------------- + */ + bl bl2u_main + + /* --------------------------------------------- + * Should never reach this point. + * --------------------------------------------- + */ + no_ret plat_panic_handler + +endfunc bl2u_entrypoint diff --git a/arm-trusted-firmware/bl2u/bl2u.ld.S b/arm-trusted-firmware/bl2u/bl2u.ld.S new file mode 100644 index 0000000..a7752a4 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u.ld.S @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl2u_entrypoint) + +MEMORY { + RAM (rwx): ORIGIN = BL2U_BASE, LENGTH = BL2U_LIMIT - BL2U_BASE +} + + +SECTIONS +{ + . = BL2U_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL2U_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl2u_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >RAM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl2u_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL2U_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); + + ASSERT(. <= BL2U_LIMIT, "BL2U image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl2u/bl2u.mk b/arm-trusted-firmware/bl2u/bl2u.mk new file mode 100644 index 0000000..b4d7634 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2U_SOURCES += bl2u/bl2u_main.c \ + bl2u/${ARCH}/bl2u_entrypoint.S \ + plat/common/${ARCH}/platform_up_stack.S + +ifeq (${ARCH},aarch64) +BL2U_SOURCES += common/aarch64/early_exceptions.S +endif + +BL2U_LINKERFILE := bl2u/bl2u.ld.S diff --git a/arm-trusted-firmware/bl2u/bl2u_main.c b/arm-trusted-firmware/bl2u/bl2u_main.c new file mode 100644 index 0000000..fcb73b9 --- /dev/null +++ b/arm-trusted-firmware/bl2u/bl2u_main.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * This function is responsible to: + * Load SCP_BL2U if platform has defined SCP_BL2U_BASE + * Perform platform setup. + * Go back to EL3. + ******************************************************************************/ +void bl2u_main(void) +{ + NOTICE("BL2U: %s\n", version_string); + NOTICE("BL2U: %s\n", build_message); + +#if SCP_BL2U_BASE + int rc; + /* Load the subsequent bootloader images */ + rc = bl2u_plat_handle_scp_bl2u(); + if (rc != 0) { + ERROR("Failed to load SCP_BL2U (%i)\n", rc); + panic(); + } +#endif + + /* Perform platform setup in BL2U after loading SCP_BL2U */ + bl2u_platform_setup(); + + console_flush(); + +#ifndef __aarch64__ + /* + * For AArch32 state BL1 and BL2U share the MMU setup. + * Given that BL2U does not map BL1 regions, MMU needs + * to be disabled in order to go back to BL1. + */ + disable_mmu_icache_secure(); +#endif /* !__aarch64__ */ + + /* + * Indicate that BL2U is done and resume back to + * normal world via an SMC to BL1. + * x1 could be passed to Normal world, + * so DO NOT pass any secret information. + */ + smc(FWU_SMC_SEC_IMAGE_DONE, 0, 0, 0, 0, 0, 0, 0); + wfi(); +} diff --git a/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S b/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S new file mode 100644 index 0000000..ed05864 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + + .globl bl31_entrypoint + .globl bl31_warm_entrypoint + + /* ----------------------------------------------------- + * bl31_entrypoint() is the cold boot entrypoint, + * executed only by the primary cpu. + * ----------------------------------------------------- + */ + +func bl31_entrypoint + /* --------------------------------------------------------------- + * Stash the previous bootloader arguments x0 - x3 for later use. + * --------------------------------------------------------------- + */ + mov x20, x0 + mov x21, x1 + mov x22, x2 + mov x23, x3 + +#if !RESET_TO_BL31 + /* --------------------------------------------------------------------- + * For !RESET_TO_BL31 systems, only the primary CPU ever reaches + * bl31_entrypoint() during the cold boot flow, so the cold/warm boot + * and primary/secondary CPU logic should not be executed in this case. + * + * Also, assume that the previous bootloader has already initialised the + * SCTLR_EL3, including the endianness, and has initialised the memory. + * --------------------------------------------------------------------- + */ + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=runtime_exceptions \ + _pie_fixup_size=BL31_LIMIT - BL31_BASE +#else + + /* --------------------------------------------------------------------- + * For RESET_TO_BL31 systems which have a programmable reset address, + * bl31_entrypoint() is executed only on the cold boot path so we can + * skip the warm boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + el3_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=runtime_exceptions \ + _pie_fixup_size=BL31_LIMIT - BL31_BASE + + /* --------------------------------------------------------------------- + * For RESET_TO_BL31 systems, BL31 is the first bootloader to run so + * there's no argument to relay from a previous bootloader. Zero the + * arguments passed to the platform layer to reflect that. + * --------------------------------------------------------------------- + */ + mov x20, 0 + mov x21, 0 + mov x22, 0 + mov x23, 0 +#endif /* RESET_TO_BL31 */ + + /* -------------------------------------------------------------------- + * Perform BL31 setup + * -------------------------------------------------------------------- + */ + mov x0, x20 + mov x1, x21 + mov x2, x22 + mov x3, x23 + bl bl31_setup + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + /* -------------------------------------------------------------------- + * Jump to main function + * -------------------------------------------------------------------- + */ + bl bl31_main + + /* -------------------------------------------------------------------- + * Clean the .data & .bss sections to main memory. This ensures + * that any global data which was initialised by the primary CPU + * is visible to secondary CPUs before they enable their data + * caches and participate in coherency. + * -------------------------------------------------------------------- + */ + adrp x0, __DATA_START__ + add x0, x0, :lo12:__DATA_START__ + adrp x1, __DATA_END__ + add x1, x1, :lo12:__DATA_END__ + sub x1, x1, x0 + bl clean_dcache_range + + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl clean_dcache_range + + b el3_exit +endfunc bl31_entrypoint + + /* -------------------------------------------------------------------- + * This CPU has been physically powered up. It is either resuming from + * suspend or has simply been turned on. In both cases, call the BL31 + * warmboot entrypoint + * -------------------------------------------------------------------- + */ +func bl31_warm_entrypoint +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * This timestamp update happens with cache off. The next + * timestamp collection will need to do cache maintenance prior + * to timestamp update. + */ + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_HW_LOW_PWR + mrs x1, cntpct_el0 + str x1, [x0] +#endif + + /* + * On the warm boot path, most of the EL3 initialisations performed by + * 'el3_entrypoint_common' must be skipped: + * + * - Only when the platform bypasses the BL1/BL31 entrypoint by + * programming the reset address do we need to initialise SCTLR_EL3. + * In other cases, we assume this has been taken care by the + * entrypoint code. + * + * - No need to determine the type of boot, we know it is a warm boot. + * + * - Do not try to distinguish between primary and secondary CPUs, this + * notion only exists for a cold boot. + * + * - No need to initialise the memory or the C runtime environment, + * it has been done once and for all on the cold boot path. + */ + el3_entrypoint_common \ + _init_sctlr=PROGRAMMABLE_RESET_ADDRESS \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=0 \ + _exception_vectors=runtime_exceptions \ + _pie_fixup_size=0 + + /* + * We're about to enable MMU and participate in PSCI state coordination. + * + * The PSCI implementation invokes platform routines that enable CPUs to + * participate in coherency. On a system where CPUs are not + * cache-coherent without appropriate platform specific programming, + * having caches enabled until such time might lead to coherency issues + * (resulting from stale data getting speculatively fetched, among + * others). Therefore we keep data caches disabled even after enabling + * the MMU for such platforms. + * + * On systems with hardware-assisted coherency, or on single cluster + * platforms, such platform specific programming is not required to + * enter coherency (as CPUs already are); and there's no reason to have + * caches disabled either. + */ +#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY + mov x0, xzr +#else + mov x0, #DISABLE_DCACHE +#endif + bl bl31_plat_enable_mmu + +#if ENABLE_RME + /* + * At warm boot GPT data structures have already been initialized in RAM + * but the sysregs for this CPU need to be initialized. Note that the GPT + * accesses are controlled attributes in GPCCR and do not depend on the + * SCR_EL3.C bit. + */ + bl gpt_enable + cbz x0, 1f + no_ret plat_panic_handler +1: +#endif + +#if ENABLE_PAUTH + /* -------------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication + * -------------------------------------------------------------------- + */ + bl pauth_init_enable_el3 +#endif /* ENABLE_PAUTH */ + + bl psci_warmboot_entrypoint + +#if ENABLE_RUNTIME_INSTRUMENTATION + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_PSCI + mov x19, x0 + + /* + * Invalidate before updating timestamp to ensure previous timestamp + * updates on the same cache line with caches disabled are properly + * seen by the same core. Without the cache invalidate, the core might + * write into a stale cache line. + */ + mov x1, #PMF_TS_SIZE + mov x20, x30 + bl inv_dcache_range + mov x30, x20 + + mrs x0, cntpct_el0 + str x0, [x19] +#endif + b el3_exit +endfunc bl31_warm_entrypoint diff --git a/arm-trusted-firmware/bl31/aarch64/crash_reporting.S b/arm-trusted-firmware/bl31/aarch64/crash_reporting.S new file mode 100644 index 0000000..d56b513 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/crash_reporting.S @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + + .globl report_unhandled_exception + .globl report_unhandled_interrupt + .globl el3_panic + .globl elx_panic + +#if CRASH_REPORTING + + /* ------------------------------------------------------ + * The below section deals with dumping the system state + * when an unhandled exception is taken in EL3. + * The layout and the names of the registers which will + * be dumped during a unhandled exception is given below. + * ------------------------------------------------------ + */ +.section .rodata.crash_prints, "aS" +print_spacer: + .asciz " = 0x" + +gp_regs: + .asciz "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",\ + "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",\ + "x16", "x17", "x18", "x19", "x20", "x21", "x22",\ + "x23", "x24", "x25", "x26", "x27", "x28", "x29", "" +el3_sys_regs: + .asciz "scr_el3", "sctlr_el3", "cptr_el3", "tcr_el3",\ + "daif", "mair_el3", "spsr_el3", "elr_el3", "ttbr0_el3",\ + "esr_el3", "far_el3", "" + +non_el3_sys_regs: + .asciz "spsr_el1", "elr_el1", "spsr_abt", "spsr_und",\ + "spsr_irq", "spsr_fiq", "sctlr_el1", "actlr_el1", "cpacr_el1",\ + "csselr_el1", "sp_el1", "esr_el1", "ttbr0_el1", "ttbr1_el1",\ + "mair_el1", "amair_el1", "tcr_el1", "tpidr_el1", "tpidr_el0",\ + "tpidrro_el0", "par_el1", "mpidr_el1", "afsr0_el1", "afsr1_el1",\ + "contextidr_el1", "vbar_el1", "cntp_ctl_el0", "cntp_cval_el0",\ + "cntv_ctl_el0", "cntv_cval_el0", "cntkctl_el1", "sp_el0", "isr_el1", "" + +#if CTX_INCLUDE_AARCH32_REGS +aarch32_regs: + .asciz "dacr32_el2", "ifsr32_el2", "" +#endif /* CTX_INCLUDE_AARCH32_REGS */ + +panic_msg: + .asciz "PANIC in EL3.\nx30" +excpt_msg: + .asciz "Unhandled Exception in EL3.\nx30" +intr_excpt_msg: + .ascii "Unhandled Interrupt Exception in EL3.\n" +x30_msg: + .asciz "x30" +excpt_msg_el: + .asciz "Unhandled Exception from EL" + + /* + * Helper function to print from crash buf. + * The print loop is controlled by the buf size and + * ascii reg name list which is passed in x6. The + * function returns the crash buf address in x0. + * Clobbers : x0 - x7, sp + */ +func size_controlled_print + /* Save the lr */ + mov sp, x30 + /* load the crash buf address */ + mrs x7, tpidr_el3 +test_size_list: + /* Calculate x5 always as it will be clobbered by asm_print_hex */ + mrs x5, tpidr_el3 + add x5, x5, #CPU_DATA_CRASH_BUF_SIZE + /* Test whether we have reached end of crash buf */ + cmp x7, x5 + b.eq exit_size_print + ldrb w4, [x6] + /* Test whether we are at end of list */ + cbz w4, exit_size_print + mov x4, x6 + /* asm_print_str updates x4 to point to next entry in list */ + bl asm_print_str + /* x0 = number of symbols printed + 1 */ + sub x0, x4, x6 + /* update x6 with the updated list pointer */ + mov x6, x4 + bl print_alignment + ldr x4, [x7], #REGSZ + bl asm_print_hex + bl asm_print_newline + b test_size_list +exit_size_print: + mov x30, sp + ret +endfunc size_controlled_print + + /* ----------------------------------------------------- + * This function calculates and prints required number + * of space characters followed by "= 0x", based on the + * length of ascii register name. + * x0: length of ascii register name + 1 + * ------------------------------------------------------ + */ +func print_alignment + /* The minimum ascii length is 3, e.g. for "x0" */ + adr x4, print_spacer - 3 + add x4, x4, x0 + b asm_print_str +endfunc print_alignment + + /* + * Helper function to store x8 - x15 registers to + * the crash buf. The system registers values are + * copied to x8 to x15 by the caller which are then + * copied to the crash buf by this function. + * x0 points to the crash buf. It then calls + * size_controlled_print to print to console. + * Clobbers : x0 - x7, sp + */ +func str_in_crash_buf_print + /* restore the crash buf address in x0 */ + mrs x0, tpidr_el3 + stp x8, x9, [x0] + stp x10, x11, [x0, #REGSZ * 2] + stp x12, x13, [x0, #REGSZ * 4] + stp x14, x15, [x0, #REGSZ * 6] + b size_controlled_print +endfunc str_in_crash_buf_print + + /* ------------------------------------------------------ + * This macro calculates the offset to crash buf from + * cpu_data and stores it in tpidr_el3. It also saves x0 + * and x1 in the crash buf by using sp as a temporary + * register. + * ------------------------------------------------------ + */ + .macro prepare_crash_buf_save_x0_x1 + /* we can corrupt this reg to free up x0 */ + mov sp, x0 + /* tpidr_el3 contains the address to cpu_data structure */ + mrs x0, tpidr_el3 + /* Calculate the Crash buffer offset in cpu_data */ + add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET + /* Store crash buffer address in tpidr_el3 */ + msr tpidr_el3, x0 + str x1, [x0, #REGSZ] + mov x1, sp + str x1, [x0] + .endm + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when an unhandled exception + * occurs. It prints the CPU state via the crash console + * making use of the crash buf. This function will + * not return. + * ----------------------------------------------------- + */ +func report_unhandled_exception + prepare_crash_buf_save_x0_x1 + adr x0, excpt_msg + mov sp, x0 + /* This call will not return */ + b do_crash_reporting +endfunc report_unhandled_exception + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when an unhandled interrupt + * occurs. It prints the CPU state via the crash console + * making use of the crash buf. This function will + * not return. + * ----------------------------------------------------- + */ +func report_unhandled_interrupt + prepare_crash_buf_save_x0_x1 + adr x0, intr_excpt_msg + mov sp, x0 + /* This call will not return */ + b do_crash_reporting +endfunc report_unhandled_interrupt + + /* ----------------------------------------------------- + * This function allows to report a crash from the lower + * exception level (if crash reporting is enabled) when + * panic() is invoked from C Runtime. + * It prints the CPU state via the crash console making + * use of 'cpu_context' structure where general purpose + * registers are saved and the crash buf. + * This function will not return. + * + * x0: Exception level + * ----------------------------------------------------- + */ +func elx_panic + msr spsel, #MODE_SP_ELX + mov x8, x0 + + /* Print the crash message */ + adr x4, excpt_msg_el + bl asm_print_str + + /* Print exception level */ + add x0, x8, #'0' + bl plat_crash_console_putc + bl asm_print_newline + + /* Report x0 - x29 values stored in 'gpregs_ctx' structure */ + /* Store the ascii list pointer in x6 */ + adr x6, gp_regs + add x7, sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0 + +print_next: + ldrb w4, [x6] + /* Test whether we are at end of list */ + cbz w4, print_x30 + mov x4, x6 + /* asm_print_str updates x4 to point to next entry in list */ + bl asm_print_str + /* x0 = number of symbols printed + 1 */ + sub x0, x4, x6 + /* Update x6 with the updated list pointer */ + mov x6, x4 + bl print_alignment + ldr x4, [x7], #REGSZ + bl asm_print_hex + bl asm_print_newline + b print_next + +print_x30: + adr x4, x30_msg + bl asm_print_str + + /* Print spaces to align "x30" string */ + mov x0, #4 + bl print_alignment + + /* Report x30 */ + ldr x4, [x7] + + /* ---------------------------------------------------------------- + * Different virtual address space size can be defined for each EL. + * Ensure that we use the proper one by reading the corresponding + * TCR_ELx register. + * ---------------------------------------------------------------- + */ + cmp x8, #MODE_EL2 + b.lt from_el1 /* EL1 */ + mrs x2, sctlr_el2 + mrs x1, tcr_el2 + + /* ---------------------------------------------------------------- + * Check if pointer authentication is enabled at the specified EL. + * If it isn't, we can then skip stripping a PAC code. + * ---------------------------------------------------------------- + */ +test_pauth: + tst x2, #(SCTLR_EnIA_BIT | SCTLR_EnIB_BIT) + b.eq no_pauth + + /* Demangle address */ + and x1, x1, #0x3F /* T0SZ = TCR_ELx[5:0] */ + sub x1, x1, #64 + neg x1, x1 /* bottom_pac_bit = 64 - T0SZ */ + mov x2, #-1 + lsl x2, x2, x1 + bic x4, x4, x2 + +no_pauth: + bl asm_print_hex + bl asm_print_newline + + /* tpidr_el3 contains the address to cpu_data structure */ + mrs x0, tpidr_el3 + /* Calculate the Crash buffer offset in cpu_data */ + add x0, x0, #CPU_DATA_CRASH_BUF_OFFSET + /* Store crash buffer address in tpidr_el3 */ + msr tpidr_el3, x0 + + /* Print the rest of crash dump */ + b print_el3_sys_regs + +from_el1: + mrs x2, sctlr_el1 + mrs x1, tcr_el1 + b test_pauth +endfunc elx_panic + + /* ----------------------------------------------------- + * This function allows to report a crash (if crash + * reporting is enabled) when panic() is invoked from + * C Runtime. It prints the CPU state via the crash + * console making use of the crash buf. This function + * will not return. + * ----------------------------------------------------- + */ +func el3_panic + msr spsel, #MODE_SP_ELX + prepare_crash_buf_save_x0_x1 + adr x0, panic_msg + mov sp, x0 + /* Fall through to 'do_crash_reporting' */ + + /* ------------------------------------------------------------ + * The common crash reporting functionality. It requires x0 + * and x1 has already been stored in crash buf, sp points to + * crash message and tpidr_el3 contains the crash buf address. + * The function does the following: + * - Retrieve the crash buffer from tpidr_el3 + * - Store x2 to x6 in the crash buffer + * - Initialise the crash console. + * - Print the crash message by using the address in sp. + * - Print x30 value to the crash console. + * - Print x0 - x7 from the crash buf to the crash console. + * - Print x8 - x29 (in groups of 8 registers) using the + * crash buf to the crash console. + * - Print el3 sys regs (in groups of 8 registers) using the + * crash buf to the crash console. + * - Print non el3 sys regs (in groups of 8 registers) using + * the crash buf to the crash console. + * ------------------------------------------------------------ + */ +do_crash_reporting: + /* Retrieve the crash buf from tpidr_el3 */ + mrs x0, tpidr_el3 + /* Store x2 - x6, x30 in the crash buffer */ + stp x2, x3, [x0, #REGSZ * 2] + stp x4, x5, [x0, #REGSZ * 4] + stp x6, x30, [x0, #REGSZ * 6] + /* Initialize the crash console */ + bl plat_crash_console_init + /* Verify the console is initialized */ + cbz x0, crash_panic + /* Print the crash message. sp points to the crash message */ + mov x4, sp + bl asm_print_str + /* Print spaces to align "x30" string */ + mov x0, #4 + bl print_alignment + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Report x30 first from the crash buf */ + ldr x4, [x0, #REGSZ * 7] + +#if ENABLE_PAUTH + /* Demangle address */ + xpaci x4 +#endif + bl asm_print_hex + bl asm_print_newline + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Now mov x7 into crash buf */ + str x7, [x0, #REGSZ * 7] + + /* Report x0 - x29 values stored in crash buf */ + /* Store the ascii list pointer in x6 */ + adr x6, gp_regs + /* Print x0 to x7 from the crash buf */ + bl size_controlled_print + /* Store x8 - x15 in crash buf and print */ + bl str_in_crash_buf_print + /* Load the crash buf address */ + mrs x0, tpidr_el3 + /* Store the rest of gp regs and print */ + stp x16, x17, [x0] + stp x18, x19, [x0, #REGSZ * 2] + stp x20, x21, [x0, #REGSZ * 4] + stp x22, x23, [x0, #REGSZ * 6] + bl size_controlled_print + /* Load the crash buf address */ + mrs x0, tpidr_el3 + stp x24, x25, [x0] + stp x26, x27, [x0, #REGSZ * 2] + stp x28, x29, [x0, #REGSZ * 4] + bl size_controlled_print + + /* Print the el3 sys registers */ +print_el3_sys_regs: + adr x6, el3_sys_regs + mrs x8, scr_el3 + mrs x9, sctlr_el3 + mrs x10, cptr_el3 + mrs x11, tcr_el3 + mrs x12, daif + mrs x13, mair_el3 + mrs x14, spsr_el3 + mrs x15, elr_el3 + bl str_in_crash_buf_print + mrs x8, ttbr0_el3 + mrs x9, esr_el3 + mrs x10, far_el3 + bl str_in_crash_buf_print + + /* Print the non el3 sys registers */ + adr x6, non_el3_sys_regs + mrs x8, spsr_el1 + mrs x9, elr_el1 + mrs x10, spsr_abt + mrs x11, spsr_und + mrs x12, spsr_irq + mrs x13, spsr_fiq + mrs x14, sctlr_el1 + mrs x15, actlr_el1 + bl str_in_crash_buf_print + mrs x8, cpacr_el1 + mrs x9, csselr_el1 + mrs x10, sp_el1 + mrs x11, esr_el1 + mrs x12, ttbr0_el1 + mrs x13, ttbr1_el1 + mrs x14, mair_el1 + mrs x15, amair_el1 + bl str_in_crash_buf_print + mrs x8, tcr_el1 + mrs x9, tpidr_el1 + mrs x10, tpidr_el0 + mrs x11, tpidrro_el0 + mrs x12, par_el1 + mrs x13, mpidr_el1 + mrs x14, afsr0_el1 + mrs x15, afsr1_el1 + bl str_in_crash_buf_print + mrs x8, contextidr_el1 + mrs x9, vbar_el1 + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + mrs x14, cntkctl_el1 + mrs x15, sp_el0 + bl str_in_crash_buf_print + mrs x8, isr_el1 + bl str_in_crash_buf_print + +#if CTX_INCLUDE_AARCH32_REGS + /* Print the AArch32 registers */ + adr x6, aarch32_regs + mrs x8, dacr32_el2 + mrs x9, ifsr32_el2 + bl str_in_crash_buf_print +#endif /* CTX_INCLUDE_AARCH32_REGS */ + + /* Get the cpu specific registers to report */ + bl do_cpu_reg_dump + bl str_in_crash_buf_print + + /* Print some platform registers */ + plat_crash_print_regs + + bl plat_crash_console_flush + + /* Done reporting */ + no_ret plat_panic_handler +endfunc el3_panic + +#else /* CRASH_REPORTING */ +func report_unhandled_exception +report_unhandled_interrupt: + no_ret plat_panic_handler +endfunc report_unhandled_exception +#endif /* CRASH_REPORTING */ + +func crash_panic + no_ret plat_panic_handler +endfunc crash_panic diff --git a/arm-trusted-firmware/bl31/aarch64/ea_delegate.S b/arm-trusted-firmware/bl31/aarch64/ea_delegate.S new file mode 100644 index 0000000..fa6ede8 --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/ea_delegate.S @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include +#include +#include +#include +#include + + .globl handle_lower_el_ea_esb + .globl handle_lower_el_async_ea + .globl enter_lower_el_sync_ea + .globl enter_lower_el_async_ea + + +/* + * Function to delegate External Aborts synchronized by ESB instruction at EL3 + * vector entry. This function assumes GP registers x0-x29 have been saved, and + * are available for use. It delegates the handling of the EA to platform + * handler, and returns only upon successfully handling the EA; otherwise + * panics. On return from this function, the original exception handler is + * expected to resume. + */ +func handle_lower_el_ea_esb + mov x0, #ERROR_EA_ESB + mrs x1, DISR_EL1 + b ea_proceed +endfunc handle_lower_el_ea_esb + + +/* + * This function forms the tail end of Synchronous Exception entry from lower + * EL, and expects to handle Synchronous External Aborts from lower EL and CPU + * Implementation Defined Exceptions. If any other kind of exception is detected, + * then this function reports unhandled exception. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_sync_ea + /* + * Explicitly save x30 so as to free up a register and to enable + * branching. + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Check for I/D aborts from lower EL */ + cmp x30, #EC_IABORT_LOWER_EL + b.eq 1f + + cmp x30, #EC_DABORT_LOWER_EL + b.eq 1f + + /* Save GP registers */ + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + + /* Get the cpu_ops pointer */ + bl get_cpu_ops_ptr + + /* Get the cpu_ops exception handler */ + ldr x0, [x0, #CPU_E_HANDLER_FUNC] + + /* + * If the reserved function pointer is NULL, this CPU does not have an + * implementation defined exception handler function + */ + cbz x0, 2f + mrs x1, esr_el3 + ubfx x1, x1, #ESR_EC_SHIFT, #ESR_EC_LENGTH + blr x0 + b 2f + +1: + /* Test for EA bit in the instruction syndrome */ + mrs x30, esr_el3 + tbz x30, #ESR_ISS_EABORT_EA_BIT, 3f + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Setup exception class and syndrome arguments for platform handler */ + mov x0, #ERROR_EA_SYNC + mrs x1, esr_el3 + bl delegate_sync_ea + + /* el3_exit assumes SP_EL0 on entry */ + msr spsel, #MODE_SP_EL0 + b el3_exit +2: + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + +3: + /* Synchronous exceptions other than the above are assumed to be EA */ + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + no_ret report_unhandled_exception +endfunc enter_lower_el_sync_ea + + +/* + * This function handles SErrors from lower ELs. + * + * Since it's part of exception vector, this function doesn't expect any GP + * registers to have been saved. It delegates the handling of the EA to platform + * handler, and upon successfully handling the EA, exits EL3; otherwise panics. + */ +func enter_lower_el_async_ea + /* + * Explicitly save x30 so as to free up a register and to enable + * branching + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +handle_lower_el_async_ea: + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Setup exception class and syndrome arguments for platform handler */ + mov x0, #ERROR_EA_ASYNC + mrs x1, esr_el3 + bl delegate_async_ea + + /* el3_exit assumes SP_EL0 on entry */ + msr spsel, #MODE_SP_EL0 + b el3_exit +endfunc enter_lower_el_async_ea + + +/* + * Prelude for Synchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_sync_ea +#if RAS_EXTENSION + /* + * Check for Uncontainable error type. If so, route to the platform + * fatal error handler rather than the generic EA one. + */ + ubfx x2, x1, #EABORT_SET_SHIFT, #EABORT_SET_WIDTH + cmp x2, #ERROR_STATUS_SET_UC + b.ne 1f + + /* Check fault status code */ + ubfx x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH + cmp x3, #SYNC_EA_FSC + b.ne 1f + + no_ret plat_handle_uncontainable_ea +1: +#endif + + b ea_proceed +endfunc delegate_sync_ea + + +/* + * Prelude for Asynchronous External Abort handling. This function assumes that + * all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func delegate_async_ea +#if RAS_EXTENSION + /* + * Check for Implementation Defined Syndrome. If so, skip checking + * Uncontainable error type from the syndrome as the format is unknown. + */ + tbnz x1, #SERROR_IDS_BIT, 1f + + /* + * Check for Uncontainable error type. If so, route to the platform + * fatal error handler rather than the generic EA one. + */ + ubfx x2, x1, #EABORT_AET_SHIFT, #EABORT_AET_WIDTH + cmp x2, #ERROR_STATUS_UET_UC + b.ne 1f + + /* Check DFSC for SError type */ + ubfx x3, x1, #EABORT_DFSC_SHIFT, #EABORT_DFSC_WIDTH + cmp x3, #DFSC_SERROR + b.ne 1f + + no_ret plat_handle_uncontainable_ea +1: +#endif + + b ea_proceed +endfunc delegate_async_ea + + +/* + * Delegate External Abort handling to platform's EA handler. This function + * assumes that all GP registers have been saved by the caller. + * + * x0: EA reason + * x1: EA syndrome + */ +func ea_proceed + /* + * If the ESR loaded earlier is not zero, we were processing an EA + * already, and this is a double fault. + */ + ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] + cbz x5, 1f + no_ret plat_handle_double_fault + +1: + /* Save EL3 state */ + mrs x2, spsr_el3 + mrs x3, elr_el3 + stp x2, x3, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + + /* + * Save ESR as handling might involve lower ELs, and returning back to + * EL3 from there would trample the original ESR. + */ + mrs x4, scr_el3 + mrs x5, esr_el3 + stp x4, x5, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* + * Setup rest of arguments, and call platform External Abort handler. + * + * x0: EA reason (already in place) + * x1: Exception syndrome (already in place). + * x2: Cookie (unused for now). + * x3: Context pointer. + * x4: Flags (security state from SCR for now). + */ + mov x2, xzr + mov x3, sp + ubfx x4, x4, #0, #1 + + /* Switch to runtime stack */ + ldr x5, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + msr spsel, #MODE_SP_EL0 + mov sp, x5 + + mov x29, x30 +#if ENABLE_ASSERTIONS + /* Stash the stack pointer */ + mov x28, sp +#endif + bl plat_ea_handler + +#if ENABLE_ASSERTIONS + /* + * Error handling flows might involve long jumps; so upon returning from + * the platform error handler, validate that the we've completely + * unwound the stack. + */ + mov x27, sp + cmp x28, x27 + ASM_ASSERT(eq) +#endif + + /* Make SP point to context */ + msr spsel, #MODE_SP_ELX + + /* Restore EL3 state and ESR */ + ldp x1, x2, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + msr spsr_el3, x1 + msr elr_el3, x2 + + /* Restore ESR_EL3 and SCR_EL3 */ + ldp x3, x4, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + msr scr_el3, x3 + msr esr_el3, x4 + +#if ENABLE_ASSERTIONS + cmp x4, xzr + ASM_ASSERT(ne) +#endif + + /* Clear ESR storage */ + str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_ESR_EL3] + + ret x29 +endfunc ea_proceed diff --git a/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S b/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S new file mode 100644 index 0000000..bf5bd8d --- /dev/null +++ b/arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .globl runtime_exceptions + + .globl sync_exception_sp_el0 + .globl irq_sp_el0 + .globl fiq_sp_el0 + .globl serror_sp_el0 + + .globl sync_exception_sp_elx + .globl irq_sp_elx + .globl fiq_sp_elx + .globl serror_sp_elx + + .globl sync_exception_aarch64 + .globl irq_aarch64 + .globl fiq_aarch64 + .globl serror_aarch64 + + .globl sync_exception_aarch32 + .globl irq_aarch32 + .globl fiq_aarch32 + .globl serror_aarch32 + + /* + * Macro that prepares entry to EL3 upon taking an exception. + * + * With RAS_EXTENSION, this macro synchronizes pending errors with an ESB + * instruction. When an error is thus synchronized, the handling is + * delegated to platform EA handler. + * + * Without RAS_EXTENSION, this macro synchronizes pending errors using + * a DSB, unmasks Asynchronous External Aborts and saves X30 before + * setting the flag CTX_IS_IN_EL3. + */ + .macro check_and_unmask_ea +#if RAS_EXTENSION + /* Synchronize pending External Aborts */ + esb + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* + * Explicitly save x30 so as to free up a register and to enable + * branching + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Check for SErrors synchronized by the ESB instruction */ + mrs x30, DISR_EL1 + tbz x30, #DISR_A_BIT, 1f + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + + bl handle_lower_el_ea_esb + + /* Restore general purpose, PMCR_EL0 and ARMv8.3-PAuth registers */ + bl restore_gp_pmcr_pauth_regs +1: +#else + /* + * For SoCs which do not implement RAS, use DSB as a barrier to + * synchronize pending external aborts. + */ + dsb sy + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* Use ISB for the above unmask operation to take effect immediately */ + isb + + /* + * Refer Note 1. No need to restore X30 as both handle_sync_exception + * and handle_interrupt_exception macro which follow this macro modify + * X30 anyway. + */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x30, #1 + str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + dmb sy +#endif + .endm + +#if !RAS_EXTENSION + /* + * Note 1: The explicit DSB at the entry of various exception vectors + * for handling exceptions from lower ELs can inadvertently trigger an + * SError exception in EL3 due to pending asynchronous aborts in lower + * ELs. This will end up being handled by serror_sp_elx which will + * ultimately panic and die. + * The way to workaround is to update a flag to indicate if the exception + * truly came from EL3. This flag is allocated in the cpu_context + * structure and located at offset "CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3" + * This is not a bullet proof solution to the problem at hand because + * we assume the instructions following "isb" that help to update the + * flag execute without causing further exceptions. + */ + + /* --------------------------------------------------------------------- + * This macro handles Asynchronous External Aborts. + * --------------------------------------------------------------------- + */ + .macro handle_async_ea + /* + * Use a barrier to synchronize pending external aborts. + */ + dsb sy + + /* Unmask the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* Use ISB for the above unmask operation to take effect immediately */ + isb + + /* Refer Note 1 */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x30, #1 + str x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + dmb sy + + b handle_lower_el_async_ea + .endm + + /* + * This macro checks if the exception was taken due to SError in EL3 or + * because of pending asynchronous external aborts from lower EL that got + * triggered due to explicit synchronization in EL3. Refer Note 1. + */ + .macro check_if_serror_from_EL3 + /* Assumes SP_EL3 on entry */ + str x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + ldr x30, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] + cbnz x30, exp_from_EL3 + + /* Handle asynchronous external abort from lower EL */ + b handle_lower_el_async_ea + +exp_from_EL3: + /* Jump to plat_handle_el3_ea which does not return */ + .endm +#endif + + /* --------------------------------------------------------------------- + * This macro handles Synchronous exceptions. + * Only SMC exceptions are supported. + * --------------------------------------------------------------------- + */ + .macro handle_sync_exception +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * Read the timestamp value and store it in per-cpu data. The value + * will be extracted from per-cpu data by the C level SMC handler and + * saved to the PMF timestamp region. + */ + mrs x30, cntpct_el0 + str x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + mrs x29, tpidr_el3 + str x30, [x29, #CPU_DATA_PMF_TS0_OFFSET] + ldr x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] +#endif + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Handle SMC exceptions separately from other synchronous exceptions */ + cmp x30, #EC_AARCH32_SMC + b.eq smc_handler32 + + cmp x30, #EC_AARCH64_SMC + b.eq smc_handler64 + + /* Synchronous exceptions other than the above are assumed to be EA */ + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + b enter_lower_el_sync_ea + .endm + + + /* --------------------------------------------------------------------- + * This macro handles FIQ or IRQ interrupts i.e. EL3, S-EL1 and NS + * interrupts. + * --------------------------------------------------------------------- + */ + .macro handle_interrupt_exception label + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* Save the EL3 system registers needed to return from this exception */ + mrs x0, spsr_el3 + mrs x1, elr_el3 + stp x0, x1, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + + /* Switch to the runtime stack i.e. SP_EL0 */ + ldr x2, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + mov x20, sp + msr spsel, #MODE_SP_EL0 + mov sp, x2 + + /* + * Find out whether this is a valid interrupt type. + * If the interrupt controller reports a spurious interrupt then return + * to where we came from. + */ + bl plat_ic_get_pending_interrupt_type + cmp x0, #INTR_TYPE_INVAL + b.eq interrupt_exit_\label + + /* + * Get the registered handler for this interrupt type. + * A NULL return value could be 'cause of the following conditions: + * + * a. An interrupt of a type was routed correctly but a handler for its + * type was not registered. + * + * b. An interrupt of a type was not routed correctly so a handler for + * its type was not registered. + * + * c. An interrupt of a type was routed correctly to EL3, but was + * deasserted before its pending state could be read. Another + * interrupt of a different type pended at the same time and its + * type was reported as pending instead. However, a handler for this + * type was not registered. + * + * a. and b. can only happen due to a programming error. The + * occurrence of c. could be beyond the control of Trusted Firmware. + * It makes sense to return from this exception instead of reporting an + * error. + */ + bl get_interrupt_type_handler + cbz x0, interrupt_exit_\label + mov x21, x0 + + mov x0, #INTR_ID_UNAVAILABLE + + /* Set the current security state in the 'flags' parameter */ + mrs x2, scr_el3 + ubfx x1, x2, #0, #1 + + /* Restore the reference to the 'handle' i.e. SP_EL3 */ + mov x2, x20 + + /* x3 will point to a cookie (not used now) */ + mov x3, xzr + + /* Call the interrupt type handler */ + blr x21 + +interrupt_exit_\label: + /* Return from exception, possibly in a different security state */ + b el3_exit + + .endm + + +vector_base runtime_exceptions + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_sp_el0 +#ifdef MONITOR_TRAPS + stp x29, x30, [sp, #-16]! + + mrs x30, esr_el3 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + /* Check for BRK */ + cmp x30, #EC_BRK + b.eq brk_handler + + ldp x29, x30, [sp], #16 +#endif /* MONITOR_TRAPS */ + + /* We don't expect any synchronous exceptions from EL3 */ + b report_unhandled_exception +end_vector_entry sync_exception_sp_el0 + +vector_entry irq_sp_el0 + /* + * EL3 code is non-reentrant. Any asynchronous exception is a serious + * error. Loop infinitely. + */ + b report_unhandled_interrupt +end_vector_entry irq_sp_el0 + + +vector_entry fiq_sp_el0 + b report_unhandled_interrupt +end_vector_entry fiq_sp_el0 + + +vector_entry serror_sp_el0 + no_ret plat_handle_el3_ea +end_vector_entry serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_sp_elx + /* + * This exception will trigger if anything went wrong during a previous + * exception entry or exit or while handling an earlier unexpected + * synchronous exception. There is a high probability that SP_EL3 is + * corrupted. + */ + b report_unhandled_exception +end_vector_entry sync_exception_sp_elx + +vector_entry irq_sp_elx + b report_unhandled_interrupt +end_vector_entry irq_sp_elx + +vector_entry fiq_sp_elx + b report_unhandled_interrupt +end_vector_entry fiq_sp_elx + +vector_entry serror_sp_elx +#if !RAS_EXTENSION + check_if_serror_from_EL3 +#endif + no_ret plat_handle_el3_ea +end_vector_entry serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_aarch64 + /* + * This exception vector will be the entry point for SMCs and traps + * that are unhandled at lower ELs most commonly. SP_EL3 should point + * to a valid cpu context where the general purpose and system register + * state can be saved. + */ + apply_at_speculative_wa + check_and_unmask_ea + handle_sync_exception +end_vector_entry sync_exception_aarch64 + +vector_entry irq_aarch64 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception irq_aarch64 +end_vector_entry irq_aarch64 + +vector_entry fiq_aarch64 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception fiq_aarch64 +end_vector_entry fiq_aarch64 + +vector_entry serror_aarch64 + apply_at_speculative_wa +#if RAS_EXTENSION + msr daifclr, #DAIF_ABT_BIT + b enter_lower_el_async_ea +#else + handle_async_ea +#endif +end_vector_entry serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry sync_exception_aarch32 + /* + * This exception vector will be the entry point for SMCs and traps + * that are unhandled at lower ELs most commonly. SP_EL3 should point + * to a valid cpu context where the general purpose and system register + * state can be saved. + */ + apply_at_speculative_wa + check_and_unmask_ea + handle_sync_exception +end_vector_entry sync_exception_aarch32 + +vector_entry irq_aarch32 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception irq_aarch32 +end_vector_entry irq_aarch32 + +vector_entry fiq_aarch32 + apply_at_speculative_wa + check_and_unmask_ea + handle_interrupt_exception fiq_aarch32 +end_vector_entry fiq_aarch32 + +vector_entry serror_aarch32 + apply_at_speculative_wa +#if RAS_EXTENSION + msr daifclr, #DAIF_ABT_BIT + b enter_lower_el_async_ea +#else + handle_async_ea +#endif +end_vector_entry serror_aarch32 + +#ifdef MONITOR_TRAPS + .section .rodata.brk_string, "aS" +brk_location: + .asciz "Error at instruction 0x" +brk_message: + .asciz "Unexpected BRK instruction with value 0x" +#endif /* MONITOR_TRAPS */ + + /* --------------------------------------------------------------------- + * The following code handles secure monitor calls. + * Depending upon the execution state from where the SMC has been + * invoked, it frees some general purpose registers to perform the + * remaining tasks. They involve finding the runtime service handler + * that is the target of the SMC & switching to runtime stacks (SP_EL0) + * before calling the handler. + * + * Note that x30 has been explicitly saved and can be used here + * --------------------------------------------------------------------- + */ +func smc_handler +smc_handler32: + /* Check whether aarch32 issued an SMC64 */ + tbnz x0, #FUNCID_CC_SHIFT, smc_prohibited + +smc_handler64: + /* NOTE: The code below must preserve x0-x4 */ + + /* + * Save general purpose and ARMv8.3-PAuth registers (if enabled). + * If Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented, save PMCR_EL0 and disable Cycle Counter. + * Also set the PSTATE to a known state. + */ + bl prepare_el3_entry + +#if ENABLE_PAUTH + /* Load and program APIAKey firmware key */ + bl pauth_load_bl31_apiakey +#endif + + /* + * Populate the parameters for the SMC handler. + * We already have x0-x4 in place. x5 will point to a cookie (not used + * now). x6 will point to the context structure (SP_EL3) and x7 will + * contain flags we need to pass to the handler. + */ + mov x5, xzr + mov x6, sp + + /* + * Restore the saved C runtime stack value which will become the new + * SP_EL0 i.e. EL3 runtime stack. It was saved in the 'cpu_context' + * structure prior to the last ERET from EL3. + */ + ldr x12, [x6, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* Switch to SP_EL0 */ + msr spsel, #MODE_SP_EL0 + + /* + * Save the SPSR_EL3, ELR_EL3, & SCR_EL3 in case there is a world + * switch during SMC handling. + * TODO: Revisit if all system registers can be saved later. + */ + mrs x16, spsr_el3 + mrs x17, elr_el3 + mrs x18, scr_el3 + stp x16, x17, [x6, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + str x18, [x6, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + + /* Clear flag register */ + mov x7, xzr + +#if ENABLE_RME + /* Copy SCR_EL3.NSE bit to the flag to indicate caller's security */ + ubfx x7, x18, #SCR_NSE_SHIFT, 1 + + /* + * Shift copied SCR_EL3.NSE bit by 5 to create space for + * SCR_EL3.NS bit. Bit 5 of the flag correspondes to + * the SCR_EL3.NSE bit. + */ + lsl x7, x7, #5 +#endif /* ENABLE_RME */ + + /* Copy SCR_EL3.NS bit to the flag to indicate caller's security */ + bfi x7, x18, #0, #1 + + mov sp, x12 + + /* Get the unique owning entity number */ + ubfx x16, x0, #FUNCID_OEN_SHIFT, #FUNCID_OEN_WIDTH + ubfx x15, x0, #FUNCID_TYPE_SHIFT, #FUNCID_TYPE_WIDTH + orr x16, x16, x15, lsl #FUNCID_OEN_WIDTH + + /* Load descriptor index from array of indices */ + adrp x14, rt_svc_descs_indices + add x14, x14, :lo12:rt_svc_descs_indices + ldrb w15, [x14, x16] + + /* Any index greater than 127 is invalid. Check bit 7. */ + tbnz w15, 7, smc_unknown + + /* + * Get the descriptor using the index + * x11 = (base + off), w15 = index + * + * handler = (base + off) + (index << log2(size)) + */ + adr x11, (__RT_SVC_DESCS_START__ + RT_SVC_DESC_HANDLE) + lsl w10, w15, #RT_SVC_SIZE_LOG2 + ldr x15, [x11, w10, uxtw] + + /* + * Call the Secure Monitor Call handler and then drop directly into + * el3_exit() which will program any remaining architectural state + * prior to issuing the ERET to the desired lower EL. + */ +#if DEBUG + cbz x15, rt_svc_fw_critical_error +#endif + blr x15 + + b el3_exit + +smc_unknown: + /* + * Unknown SMC call. Populate return value with SMC_UNK and call + * el3_exit() which will restore the remaining architectural state + * i.e., SYS, GP and PAuth registers(if any) prior to issuing the ERET + * to the desired lower EL. + */ + mov x0, #SMC_UNK + str x0, [x6, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + b el3_exit + +smc_prohibited: + restore_ptw_el1_sys_regs + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + mov x0, #SMC_UNK + exception_return + +#if DEBUG +rt_svc_fw_critical_error: + /* Switch to SP_ELx */ + msr spsel, #MODE_SP_ELX + no_ret report_unhandled_exception +#endif +endfunc smc_handler + + /* --------------------------------------------------------------------- + * The following code handles exceptions caused by BRK instructions. + * Following a BRK instruction, the only real valid cause of action is + * to print some information and panic, as the code that caused it is + * likely in an inconsistent internal state. + * + * This is initially intended to be used in conjunction with + * __builtin_trap. + * --------------------------------------------------------------------- + */ +#ifdef MONITOR_TRAPS +func brk_handler + /* Extract the ISS */ + mrs x10, esr_el3 + ubfx x10, x10, #ESR_ISS_SHIFT, #ESR_ISS_LENGTH + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + adr x4, brk_location + bl asm_print_str + mrs x4, elr_el3 + bl asm_print_hex + bl asm_print_newline + + adr x4, brk_message + bl asm_print_str + mov x4, x10 + mov x5, #28 + bl asm_print_hex_bits + bl asm_print_newline + + no_ret plat_panic_handler +endfunc brk_handler +#endif /* MONITOR_TRAPS */ diff --git a/arm-trusted-firmware/bl31/bl31.ld.S b/arm-trusted-firmware/bl31/bl31.ld.S new file mode 100644 index 0000000..8a1573a --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31.ld.S @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl31_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_LIMIT - BL31_BASE +#if SEPARATE_NOBITS_REGION + NOBITS (rw!a): ORIGIN = BL31_NOBITS_BASE, LENGTH = BL31_NOBITS_LIMIT - BL31_NOBITS_BASE +#else +#define NOBITS RAM +#endif +} + +#ifdef PLAT_EXTRA_LD_SCRIPT +#include +#endif + +SECTIONS +{ + . = BL31_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31_BASE address is not aligned on a page boundary.") + + __BL31_START__ = .; + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *bl31_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(SORT(.text*))) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *bl31_entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + *(.vectors) + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as read-only, + * executable. No RW data from the next section must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + +#if SPM_MM +#ifndef SPM_SHIM_EXCEPTIONS_VMA +#define SPM_SHIM_EXCEPTIONS_VMA RAM +#endif + + /* + * 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 : ALIGN(PAGE_SIZE) { + __SPM_SHIM_EXCEPTIONS_START__ = .; + *(.spm_shim_exceptions) + . = ALIGN(PAGE_SIZE); + __SPM_SHIM_EXCEPTIONS_END__ = .; + } >SPM_SHIM_EXCEPTIONS_VMA AT>RAM + + PROVIDE(__SPM_SHIM_EXCEPTIONS_LMA__ = LOADADDR(spm_shim_exceptions)); + . = LOADADDR(spm_shim_exceptions) + SIZEOF(spm_shim_exceptions); +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + RELA_SECTION >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(. <= BL31_PROGBITS_LIMIT, "BL31 progbits has exceeded its limit.") +#endif + +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + . = ALIGN(PAGE_SIZE); + __RW_END__ = .; + __BL31_END__ = .; + + ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") + + . = BL31_NOBITS_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31 NOBITS base address is not aligned on a page boundary.") + + __NOBITS_START__ = .; +#endif + + STACK_SECTION >NOBITS + BSS_SECTION >NOBITS + XLAT_TABLE_SECTION >NOBITS + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + /* + * 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_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >NOBITS +#endif + +#if SEPARATE_NOBITS_REGION + /* + * Define a linker symbol to mark end of the NOBITS memory area for this + * image. + */ + __NOBITS_END__ = .; + + ASSERT(. <= BL31_NOBITS_LIMIT, "BL31 NOBITS region has exceeded its limit.") +#else + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL31_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + ASSERT(. <= BL31_LIMIT, "BL31 image has exceeded its limit.") +#endif +} diff --git a/arm-trusted-firmware/bl31/bl31.mk b/arm-trusted-firmware/bl31/bl31.mk new file mode 100644 index 0000000..e751824 --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31.mk @@ -0,0 +1,151 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################################################ +# Include Makefile for the SPM-MM implementation +################################################################################ +ifeq (${SUPPORT_UNKNOWN_MPID},1) + ifeq (${DEBUG},0) + $(warning WARNING: SUPPORT_UNKNOWN_MPID enabled) + endif +endif + +ifeq (${SPM_MM},1) + ifeq (${EL3_EXCEPTION_HANDLING},0) + $(error EL3_EXCEPTION_HANDLING must be 1 for SPM-MM support) + else + $(info Including SPM Management Mode (MM) makefile) + include services/std_svc/spm_mm/spm_mm.mk + endif +endif + +include lib/extensions/amu/amu.mk +include lib/mpmm/mpmm.mk +include lib/psci/psci_lib.mk + +BL31_SOURCES += bl31/bl31_main.c \ + bl31/interrupt_mgmt.c \ + bl31/aarch64/bl31_entrypoint.S \ + bl31/aarch64/crash_reporting.S \ + bl31/aarch64/ea_delegate.S \ + bl31/aarch64/runtime_exceptions.S \ + bl31/bl31_context_mgmt.c \ + common/runtime_svc.c \ + lib/cpus/aarch64/dsu_helpers.S \ + plat/common/aarch64/platform_mp_stack.S \ + services/arm_arch_svc/arm_arch_svc_setup.c \ + services/std_svc/std_svc_setup.c \ + ${PSCI_LIB_SOURCES} \ + ${SPMD_SOURCES} \ + ${SPM_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL31_SOURCES += lib/extensions/mtpmu/aarch64/mtpmu.S +endif + +ifeq (${ENABLE_PMF}, 1) +BL31_SOURCES += lib/pmf/pmf_main.c +endif + +include lib/debugfs/debugfs.mk +ifeq (${USE_DEBUGFS},1) + BL31_SOURCES += $(DEBUGFS_SRCS) +endif + +ifeq (${EL3_EXCEPTION_HANDLING},1) +BL31_SOURCES += bl31/ehf.c +endif + +ifeq (${SDEI_SUPPORT},1) +ifeq (${EL3_EXCEPTION_HANDLING},0) + $(error EL3_EXCEPTION_HANDLING must be 1 for SDEI support) +endif +BL31_SOURCES += services/std_svc/sdei/sdei_dispatch.S \ + services/std_svc/sdei/sdei_event.c \ + services/std_svc/sdei/sdei_intr_mgmt.c \ + services/std_svc/sdei/sdei_main.c \ + services/std_svc/sdei/sdei_state.c +endif + +ifeq (${TRNG_SUPPORT},1) +BL31_SOURCES += services/std_svc/trng/trng_main.c \ + services/std_svc/trng/trng_entropy_pool.c +endif + +ifeq (${ENABLE_SPE_FOR_LOWER_ELS},1) +BL31_SOURCES += lib/extensions/spe/spe.c +endif + +ifeq (${ENABLE_AMU},1) +BL31_SOURCES += ${AMU_SOURCES} +endif + +ifeq (${ENABLE_MPMM},1) +BL31_SOURCES += ${MPMM_SOURCES} +endif + +ifeq (${ENABLE_SME_FOR_NS},1) +BL31_SOURCES += lib/extensions/sme/sme.c +BL31_SOURCES += lib/extensions/sve/sve.c +else +ifeq (${ENABLE_SVE_FOR_NS},1) +BL31_SOURCES += lib/extensions/sve/sve.c +endif +endif + +ifeq (${ENABLE_MPAM_FOR_LOWER_ELS},1) +BL31_SOURCES += lib/extensions/mpam/mpam.c +endif + +ifeq (${ENABLE_TRBE_FOR_NS},1) +BL31_SOURCES += lib/extensions/trbe/trbe.c +endif + +ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1) +BL31_SOURCES += lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c +endif + +ifeq (${ENABLE_TRF_FOR_NS},1) +BL31_SOURCES += lib/extensions/trf/aarch64/trf.c +endif + +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL31_SOURCES += lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S \ + lib/cpus/aarch64/wa_cve_2017_5715_mmu.S +endif + +ifeq ($(SMC_PCI_SUPPORT),1) +BL31_SOURCES += services/std_svc/pci_svc.c +endif + +ifeq (${ENABLE_RME},1) +include lib/gpt_rme/gpt_rme.mk + +BL31_SOURCES += ${GPT_LIB_SRCS} \ + ${RMMD_SOURCES} +endif + +BL31_LINKERFILE := bl31/bl31.ld.S + +# Flag used to indicate if Crash reporting via console should be included +# in BL31. This defaults to being present in DEBUG builds only +ifndef CRASH_REPORTING +CRASH_REPORTING := $(DEBUG) +endif + +$(eval $(call assert_booleans,\ + $(sort \ + CRASH_REPORTING \ + EL3_EXCEPTION_HANDLING \ + SDEI_SUPPORT \ +))) + +$(eval $(call add_defines,\ + $(sort \ + CRASH_REPORTING \ + EL3_EXCEPTION_HANDLING \ + SDEI_SUPPORT \ +))) diff --git a/arm-trusted-firmware/bl31/bl31_context_mgmt.c b/arm-trusted-firmware/bl31/bl31_context_mgmt.c new file mode 100644 index 0000000..34f69ad --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31_context_mgmt.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the calling CPU that was set as the context for the specified security + * state. NULL is returned if no such structure has been specified. + ******************************************************************************/ +void *cm_get_context(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + + return get_cpu_data(cpu_context[get_cpu_context_index(security_state)]); +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the calling CPU + ******************************************************************************/ +void cm_set_context(void *context, uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + + set_cpu_data(cpu_context[get_cpu_context_index(security_state)], + context); +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the CPU identified by `cpu_idx` that was set as the context for the + * specified security state. NULL is returned if no such structure has been + * specified. + ******************************************************************************/ +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + + return get_cpu_data_by_index(cpu_idx, + cpu_context[get_cpu_context_index(security_state)]); +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the CPU identified by CPU index. + ******************************************************************************/ +void cm_set_context_by_index(unsigned int cpu_idx, void *context, + unsigned int security_state) +{ + assert(sec_state_is_valid(security_state)); + + set_cpu_data_by_index(cpu_idx, + cpu_context[get_cpu_context_index(security_state)], + context); +} diff --git a/arm-trusted-firmware/bl31/bl31_main.c b/arm-trusted-firmware/bl31/bl31_main.c new file mode 100644 index 0000000..9ac10e2 --- /dev/null +++ b/arm-trusted-firmware/bl31/bl31_main.c @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ENABLE_RUNTIME_INSTRUMENTATION +PMF_REGISTER_SERVICE_SMC(rt_instr_svc, PMF_RT_INSTR_SVC_ID, + RT_INSTR_TOTAL_IDS, PMF_STORE_ENABLE) +#endif + +/******************************************************************************* + * This function pointer is used to initialise the BL32 image. It's initialized + * by SPD calling bl31_register_bl32_init after setting up all things necessary + * for SP execution. In cases where both SPD and SP are absent, or when SPD + * finds it impossible to execute SP, this pointer is left as NULL + ******************************************************************************/ +static int32_t (*bl32_init)(void); + +/***************************************************************************** + * Function used to initialise RMM if RME is enabled + *****************************************************************************/ +#if ENABLE_RME +static int32_t (*rmm_init)(void); +#endif + +/******************************************************************************* + * Variable to indicate whether next image to execute after BL31 is BL33 + * (non-secure & default) or BL32 (secure). + ******************************************************************************/ +static uint32_t next_image_type = NON_SECURE; + +#ifdef SUPPORT_UNKNOWN_MPID +/* + * Flag to know whether an unsupported MPID has been detected. To avoid having it + * landing on the .bss section, it is initialized to a non-zero value, this way + * we avoid potential WAW hazards during system bring up. + * */ +volatile uint32_t unsupported_mpid_flag = 1; +#endif + +/* + * Implement the ARM Standard Service function to get arguments for a + * particular service. + */ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask) +{ + /* Setup the arguments for PSCI Library */ + DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, bl31_warm_entrypoint); + + /* PSCI is the only ARM Standard Service implemented */ + assert(svc_mask == PSCI_FID_MASK); + + return (uintptr_t)&psci_args; +} + +/******************************************************************************* + * Simple function to initialise all BL31 helper libraries. + ******************************************************************************/ +void __init bl31_lib_init(void) +{ + cm_init(); +} + +/******************************************************************************* + * Setup function for BL31. + ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3) +{ + /* Perform early platform-specific setup */ + bl31_early_platform_setup2(arg0, arg1, arg2, arg3); + + /* Perform late platform-specific setup */ + bl31_plat_arch_setup(); + +#if ENABLE_FEAT_HCX + /* + * Assert that FEAT_HCX is supported on this system, without this check + * an exception would occur during context save/restore if enabled but + * not supported. + */ + assert(is_feat_hcx_present()); +#endif /* ENABLE_FEAT_HCX */ + +#if CTX_INCLUDE_PAUTH_REGS + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* CTX_INCLUDE_PAUTH_REGS */ +} + +/******************************************************************************* + * BL31 is responsible for setting up the runtime services for the primary cpu + * before passing control to the bootloader or an Operating System. This + * function calls runtime_svc_init() which initializes all registered runtime + * services. The run time services would setup enough context for the core to + * switch to the next exception level. When this function returns, the core will + * switch to the programmed exception level via an ERET. + ******************************************************************************/ +void bl31_main(void) +{ + NOTICE("BL31: %s\n", version_string); + NOTICE("BL31: %s\n", build_message); + +#ifdef SUPPORT_UNKNOWN_MPID + if (unsupported_mpid_flag == 0) { + NOTICE("Unsupported MPID detected!\n"); + } +#endif + + /* Perform platform setup in BL31 */ + bl31_platform_setup(); + + /* Initialise helper libraries */ + bl31_lib_init(); + +#if EL3_EXCEPTION_HANDLING + INFO("BL31: Initialising Exception Handling Framework\n"); + ehf_init(); +#endif + + /* Initialize the runtime services e.g. psci. */ + INFO("BL31: Initializing runtime services\n"); + runtime_svc_init(); + + /* + * All the cold boot actions on the primary cpu are done. We now need to + * decide which is the next image and how to execute it. + * If the SPD runtime service is present, it would want to pass control + * to BL32 first in S-EL1. In that case, SPD would have registered a + * function to initialize bl32 where it takes responsibility of entering + * S-EL1 and returning control back to bl31_main. Similarly, if RME is + * enabled and a function is registered to initialize RMM, control is + * transferred to RMM in R-EL2. After RMM initialization, control is + * returned back to bl31_main. Once this is done we can prepare entry + * into BL33 as normal. + */ + + /* + * If SPD had registered an init hook, invoke it. + */ + if (bl32_init != NULL) { + INFO("BL31: Initializing BL32\n"); + + int32_t rc = (*bl32_init)(); + + if (rc == 0) { + WARN("BL31: BL32 initialization failed\n"); + } + } + + /* + * If RME is enabled and init hook is registered, initialize RMM + * in R-EL2. + */ +#if ENABLE_RME + if (rmm_init != NULL) { + INFO("BL31: Initializing RMM\n"); + + int32_t rc = (*rmm_init)(); + + if (rc == 0) { + WARN("BL31: RMM initialization failed\n"); + } + } +#endif + + /* + * We are ready to enter the next EL. Prepare entry into the image + * corresponding to the desired security state after the next ERET. + */ + bl31_prepare_next_image_entry(); + + console_flush(); + + /* + * Perform any platform specific runtime setup prior to cold boot exit + * from BL31 + */ + bl31_plat_runtime_setup(); +} + +/******************************************************************************* + * Accessor functions to help runtime services decide which image should be + * executed after BL31. This is BL33 or the non-secure bootloader image by + * default but the Secure payload dispatcher could override this by requesting + * an entry into BL32 (Secure payload) first. If it does so then it should use + * the same API to program an entry into BL33 once BL32 initialisation is + * complete. + ******************************************************************************/ +void bl31_set_next_image_type(uint32_t security_state) +{ + assert(sec_state_is_valid(security_state)); + next_image_type = security_state; +} + +uint32_t bl31_get_next_image_type(void) +{ + return next_image_type; +} + +/******************************************************************************* + * This function programs EL3 registers and performs other setup to enable entry + * into the next image after BL31 at the next ERET. + ******************************************************************************/ +void __init bl31_prepare_next_image_entry(void) +{ + entry_point_info_t *next_image_info; + uint32_t image_type; + +#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 " + "CTX_INCLUDE_AARCH32_REGS = 0\n"); + panic(); + } +#endif + + /* Determine which image to execute next */ + image_type = bl31_get_next_image_type(); + + /* Program EL3 registers to enable entry into the next EL */ + next_image_info = bl31_plat_get_next_image_ep_info(image_type); + assert(next_image_info != NULL); + assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("BL31: Preparing for EL3 exit to %s world\n", + (image_type == SECURE) ? "secure" : "normal"); + print_entry_point_info(next_image_info); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(image_type); +} + +/******************************************************************************* + * This function initializes the pointer to BL32 init function. This is expected + * to be called by the SPD after it finishes all its initialization + ******************************************************************************/ +void bl31_register_bl32_init(int32_t (*func)(void)) +{ + bl32_init = func; +} + +#if ENABLE_RME +/******************************************************************************* + * This function initializes the pointer to RMM init function. This is expected + * to be called by the RMMD after it finishes all its initialization + ******************************************************************************/ +void bl31_register_rmm_init(int32_t (*func)(void)) +{ + rmm_init = func; +} +#endif diff --git a/arm-trusted-firmware/bl31/ehf.c b/arm-trusted-firmware/bl31/ehf.c new file mode 100644 index 0000000..745f165 --- /dev/null +++ b/arm-trusted-firmware/bl31/ehf.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Exception handlers at EL3, their priority levels, and management. + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Output EHF logs as verbose */ +#define EHF_LOG(...) VERBOSE("EHF: " __VA_ARGS__) + +#define EHF_INVALID_IDX (-1) + +/* For a valid handler, return the actual function pointer; otherwise, 0. */ +#define RAW_HANDLER(h) \ + ((ehf_handler_t) ((((h) & EHF_PRI_VALID_) != 0U) ? \ + ((h) & ~EHF_PRI_VALID_) : 0U)) + +#define PRI_BIT(idx) (((ehf_pri_bits_t) 1u) << (idx)) + +/* + * Convert index into secure priority using the platform-defined priority bits + * field. + */ +#define IDX_TO_PRI(idx) \ + ((((unsigned) idx) << (7u - exception_data.pri_bits)) & 0x7fU) + +/* Check whether a given index is valid */ +#define IS_IDX_VALID(idx) \ + ((exception_data.ehf_priorities[idx].ehf_handler & EHF_PRI_VALID_) != 0U) + +/* Returns whether given priority is in secure priority range */ +#define IS_PRI_SECURE(pri) (((pri) & 0x80U) == 0U) + +/* To be defined by the platform */ +extern const ehf_priorities_t exception_data; + +/* Translate priority to the index in the priority array */ +static unsigned int pri_to_idx(unsigned int priority) +{ + unsigned int idx; + + idx = EHF_PRI_TO_IDX(priority, exception_data.pri_bits); + assert(idx < exception_data.num_priorities); + assert(IS_IDX_VALID(idx)); + + return idx; +} + +/* Return whether there are outstanding priority activation */ +static bool has_valid_pri_activations(pe_exc_data_t *pe_data) +{ + return pe_data->active_pri_bits != 0U; +} + +static pe_exc_data_t *this_cpu_data(void) +{ + return &get_cpu_data(ehf_data); +} + +/* + * Return the current priority index of this CPU. If no priority is active, + * return EHF_INVALID_IDX. + */ +static int get_pe_highest_active_idx(pe_exc_data_t *pe_data) +{ + if (!has_valid_pri_activations(pe_data)) + return EHF_INVALID_IDX; + + /* Current priority is the right-most bit */ + return (int) __builtin_ctz(pe_data->active_pri_bits); +} + +/* + * Mark priority active by setting the corresponding bit in active_pri_bits and + * programming the priority mask. + * + * This API is to be used as part of delegating to lower ELs other than for + * interrupts; e.g. while handling synchronous exceptions. + * + * This API is expected to be invoked before restoring context (Secure or + * Non-secure) in preparation for the respective dispatch. + */ +void ehf_activate_priority(unsigned int priority) +{ + int cur_pri_idx; + unsigned int old_mask, run_pri, idx; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* + * Query interrupt controller for the running priority, or idle priority + * if no interrupts are being handled. The requested priority must be + * less (higher priority) than the active running priority. + */ + run_pri = plat_ic_get_running_priority(); + if (priority >= run_pri) { + ERROR("Running priority higher (0x%x) than requested (0x%x)\n", + run_pri, priority); + panic(); + } + + /* + * If there were priority activations already, the requested priority + * must be less (higher priority) than the current highest priority + * activation so far. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + idx = pri_to_idx(priority); + if ((cur_pri_idx != EHF_INVALID_IDX) && + (idx >= ((unsigned int) cur_pri_idx))) { + ERROR("Activation priority mismatch: req=0x%x current=0x%x\n", + priority, IDX_TO_PRI(cur_pri_idx)); + panic(); + } + + /* Set the bit corresponding to the requested priority */ + pe_data->active_pri_bits |= PRI_BIT(idx); + + /* + * Program priority mask for the activated level. Check that the new + * priority mask is setting a higher priority level than the existing + * mask. + */ + old_mask = plat_ic_set_priority_mask(priority); + if (priority >= old_mask) { + ERROR("Requested priority (0x%x) lower than Priority Mask (0x%x)\n", + priority, old_mask); + panic(); + } + + /* + * If this is the first activation, save the priority mask. This will be + * restored after the last deactivation. + */ + if (cur_pri_idx == EHF_INVALID_IDX) + pe_data->init_pri_mask = (uint8_t) old_mask; + + EHF_LOG("activate prio=%d\n", get_pe_highest_active_idx(pe_data)); +} + +/* + * Mark priority inactive by clearing the corresponding bit in active_pri_bits, + * and programming the priority mask. + * + * This API is expected to be used as part of delegating to to lower ELs other + * than for interrupts; e.g. while handling synchronous exceptions. + * + * This API is expected to be invoked after saving context (Secure or + * Non-secure), having concluded the respective dispatch. + */ +void ehf_deactivate_priority(unsigned int priority) +{ + int cur_pri_idx; + pe_exc_data_t *pe_data = this_cpu_data(); + unsigned int old_mask, run_pri, idx; + + /* + * Query interrupt controller for the running priority, or idle priority + * if no interrupts are being handled. The requested priority must be + * less (higher priority) than the active running priority. + */ + run_pri = plat_ic_get_running_priority(); + if (priority >= run_pri) { + ERROR("Running priority higher (0x%x) than requested (0x%x)\n", + run_pri, priority); + panic(); + } + + /* + * Deactivation is allowed only when there are priority activations, and + * the deactivation priority level must match the current activated + * priority. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + idx = pri_to_idx(priority); + if ((cur_pri_idx == EHF_INVALID_IDX) || + (idx != ((unsigned int) cur_pri_idx))) { + ERROR("Deactivation priority mismatch: req=0x%x current=0x%x\n", + priority, IDX_TO_PRI(cur_pri_idx)); + panic(); + } + + /* Clear bit corresponding to highest priority */ + pe_data->active_pri_bits &= (pe_data->active_pri_bits - 1u); + + /* + * Restore priority mask corresponding to the next priority, or the + * one stashed earlier if there are no more to deactivate. + */ + cur_pri_idx = get_pe_highest_active_idx(pe_data); + if (cur_pri_idx == EHF_INVALID_IDX) + old_mask = plat_ic_set_priority_mask(pe_data->init_pri_mask); + else + old_mask = plat_ic_set_priority_mask(priority); + + if (old_mask > priority) { + ERROR("Deactivation priority (0x%x) lower than Priority Mask (0x%x)\n", + priority, old_mask); + panic(); + } + + EHF_LOG("deactivate prio=%d\n", get_pe_highest_active_idx(pe_data)); +} + +/* + * After leaving Non-secure world, stash current Non-secure Priority Mask, and + * set Priority Mask to the highest Non-secure priority so that Non-secure + * interrupts cannot preempt Secure execution. + * + * If the current running priority is in the secure range, or if there are + * outstanding priority activations, this function does nothing. + * + * This function subscribes to the 'cm_exited_normal_world' event published by + * the Context Management Library. + */ +static void *ehf_exited_normal_world(const void *arg) +{ + unsigned int run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If the running priority is in the secure range, do nothing */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return NULL; + + /* Do nothing if there are explicit activations */ + if (has_valid_pri_activations(pe_data)) + return NULL; + + assert(pe_data->ns_pri_mask == 0u); + + pe_data->ns_pri_mask = + (uint8_t) plat_ic_set_priority_mask(GIC_HIGHEST_NS_PRIORITY); + + /* The previous Priority Mask is not expected to be in secure range */ + if (IS_PRI_SECURE(pe_data->ns_pri_mask)) { + ERROR("Priority Mask (0x%x) already in secure range\n", + pe_data->ns_pri_mask); + panic(); + } + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", pe_data->ns_pri_mask, + GIC_HIGHEST_NS_PRIORITY); + + return NULL; +} + +/* + * Conclude Secure execution and prepare for return to Non-secure world. Restore + * the Non-secure Priority Mask previously stashed upon leaving Non-secure + * world. + * + * If there the current running priority is in the secure range, or if there are + * outstanding priority activations, this function does nothing. + * + * This function subscribes to the 'cm_entering_normal_world' event published by + * the Context Management Library. + */ +static void *ehf_entering_normal_world(const void *arg) +{ + unsigned int old_pmr, run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If the running priority is in the secure range, do nothing */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return NULL; + + /* + * If there are explicit activations, do nothing. The Priority Mask will + * be restored upon the last deactivation. + */ + if (has_valid_pri_activations(pe_data)) + return NULL; + + /* Do nothing if we don't have a valid Priority Mask to restore */ + if (pe_data->ns_pri_mask == 0U) + return NULL; + + old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask); + + /* + * When exiting secure world, the current Priority Mask must be + * GIC_HIGHEST_NS_PRIORITY (as set during entry), or the Non-secure + * priority mask set upon calling ehf_allow_ns_preemption() + */ + if ((old_pmr != GIC_HIGHEST_NS_PRIORITY) && + (old_pmr != pe_data->ns_pri_mask)) { + ERROR("Invalid Priority Mask (0x%x) restored\n", old_pmr); + panic(); + } + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask); + + pe_data->ns_pri_mask = 0; + + return NULL; +} + +/* + * Program Priority Mask to the original Non-secure priority such that + * Non-secure interrupts may preempt Secure execution (for example, during + * Yielding SMC calls). The 'preempt_ret_code' parameter indicates the Yielding + * SMC's return value in case the call was preempted. + * + * This API is expected to be invoked before delegating a yielding SMC to Secure + * EL1. I.e. within the window of secure execution after Non-secure context is + * saved (after entry into EL3) and Secure context is restored (before entering + * Secure EL1). + */ +void ehf_allow_ns_preemption(uint64_t preempt_ret_code) +{ + cpu_context_t *ns_ctx; + unsigned int old_pmr __unused; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* + * We should have been notified earlier of entering secure world, and + * therefore have stashed the Non-secure priority mask. + */ + assert(pe_data->ns_pri_mask != 0U); + + /* Make sure no priority levels are active when requesting this */ + if (has_valid_pri_activations(pe_data)) { + ERROR("PE %lx has priority activations: 0x%x\n", + read_mpidr_el1(), pe_data->active_pri_bits); + panic(); + } + + /* + * Program preempted return code to x0 right away so that, if the + * Yielding SMC was indeed preempted before a dispatcher gets a chance + * to populate it, the caller would find the correct return value. + */ + ns_ctx = cm_get_context(NON_SECURE); + assert(ns_ctx != NULL); + write_ctx_reg(get_gpregs_ctx(ns_ctx), CTX_GPREG_X0, preempt_ret_code); + + old_pmr = plat_ic_set_priority_mask(pe_data->ns_pri_mask); + + EHF_LOG("Priority Mask: 0x%x => 0x%x\n", old_pmr, pe_data->ns_pri_mask); + + pe_data->ns_pri_mask = 0; +} + +/* + * Return whether Secure execution has explicitly allowed Non-secure interrupts + * to preempt itself (for example, during Yielding SMC calls). + */ +unsigned int ehf_is_ns_preemption_allowed(void) +{ + unsigned int run_pri; + pe_exc_data_t *pe_data = this_cpu_data(); + + /* If running priority is in secure range, return false */ + run_pri = plat_ic_get_running_priority(); + if (IS_PRI_SECURE(run_pri)) + return 0; + + /* + * If Non-secure preemption was permitted by calling + * ehf_allow_ns_preemption() earlier: + * + * - There wouldn't have been priority activations; + * - We would have cleared the stashed the Non-secure Priority Mask. + */ + if (has_valid_pri_activations(pe_data)) + return 0; + if (pe_data->ns_pri_mask != 0U) + return 0; + + return 1; +} + +/* + * Top-level EL3 interrupt handler. + */ +static uint64_t ehf_el3_interrupt_handler(uint32_t id, uint32_t flags, + void *handle, void *cookie) +{ + int ret = 0; + uint32_t intr_raw; + unsigned int intr, pri, idx; + ehf_handler_t handler; + + /* + * Top-level interrupt type handler from Interrupt Management Framework + * doesn't acknowledge the interrupt; so the interrupt ID must be + * invalid. + */ + assert(id == INTR_ID_UNAVAILABLE); + + /* + * Acknowledge interrupt. Proceed with handling only for valid interrupt + * IDs. This situation may arise because of Interrupt Management + * Framework identifying an EL3 interrupt, but before it's been + * acknowledged here, the interrupt was either deasserted, or there was + * a higher-priority interrupt of another type. + */ + intr_raw = plat_ic_acknowledge_interrupt(); + intr = plat_ic_get_interrupt_id(intr_raw); + if (intr == INTR_ID_UNAVAILABLE) + return 0; + + /* Having acknowledged the interrupt, get the running priority */ + pri = plat_ic_get_running_priority(); + + /* Check EL3 interrupt priority is in secure range */ + assert(IS_PRI_SECURE(pri)); + + /* + * Translate the priority to a descriptor index. We do this by masking + * and shifting the running priority value (platform-supplied). + */ + idx = pri_to_idx(pri); + + /* Validate priority */ + assert(pri == IDX_TO_PRI(idx)); + + handler = (ehf_handler_t) RAW_HANDLER( + exception_data.ehf_priorities[idx].ehf_handler); + if (handler == NULL) { + ERROR("No EL3 exception handler for priority 0x%x\n", + IDX_TO_PRI(idx)); + panic(); + } + + /* + * Call registered handler. Pass the raw interrupt value to registered + * handlers. + */ + ret = handler(intr_raw, flags, handle, cookie); + + return (uint64_t) ret; +} + +/* + * Initialize the EL3 exception handling. + */ +void __init ehf_init(void) +{ + unsigned int flags = 0; + int ret __unused; + + /* Ensure EL3 interrupts are supported */ + assert(plat_ic_has_interrupt_type(INTR_TYPE_EL3) != 0); + + /* + * Make sure that priority water mark has enough bits to represent the + * whole priority array. + */ + assert(exception_data.num_priorities <= (sizeof(ehf_pri_bits_t) * 8U)); + + assert(exception_data.ehf_priorities != NULL); + + /* + * Bit 7 of GIC priority must be 0 for secure interrupts. This means + * platforms must use at least 1 of the remaining 7 bits. + */ + assert((exception_data.pri_bits >= 1U) || + (exception_data.pri_bits < 8U)); + + /* Route EL3 interrupts when in Secure and Non-secure. */ + 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, + ehf_el3_interrupt_handler, flags); + assert(ret == 0); +} + +/* + * Register a handler at the supplied priority. Registration is allowed only if + * a handler hasn't been registered before, or one wasn't provided at build + * time. The priority for which the handler is being registered must also accord + * with the platform-supplied data. + */ +void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler) +{ + unsigned int idx; + + /* Sanity check for handler */ + assert(handler != NULL); + + /* Handler ought to be 4-byte aligned */ + assert((((uintptr_t) handler) & 3U) == 0U); + + /* Ensure we register for valid priority */ + idx = pri_to_idx(pri); + assert(idx < exception_data.num_priorities); + assert(IDX_TO_PRI(idx) == pri); + + /* Return failure if a handler was already registered */ + if (exception_data.ehf_priorities[idx].ehf_handler != EHF_NO_HANDLER_) { + ERROR("Handler already registered for priority 0x%x\n", pri); + panic(); + } + + /* + * Install handler, and retain the valid bit. We assume that the handler + * is 4-byte aligned, which is usually the case. + */ + exception_data.ehf_priorities[idx].ehf_handler = + (((uintptr_t) handler) | EHF_PRI_VALID_); + + EHF_LOG("register pri=0x%x handler=%p\n", pri, handler); +} + +SUBSCRIBE_TO_EVENT(cm_entering_normal_world, ehf_entering_normal_world); +SUBSCRIBE_TO_EVENT(cm_exited_normal_world, ehf_exited_normal_world); diff --git a/arm-trusted-firmware/bl31/interrupt_mgmt.c b/arm-trusted-firmware/bl31/interrupt_mgmt.c new file mode 100644 index 0000000..b8cc3de --- /dev/null +++ b/arm-trusted-firmware/bl31/interrupt_mgmt.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/******************************************************************************* + * Local structure and corresponding array to keep track of the state of the + * registered interrupt handlers for each interrupt type. + * The field descriptions are: + * + * 'scr_el3[2]' : Mapping of the routing model in the 'flags' field to the + * value of the SCR_EL3.IRQ or FIQ bit for each security state. + * There are two instances of this field corresponding to the + * two security states. + * + * 'flags' : Bit[0], Routing model for this interrupt type when execution is + * not in EL3 in the secure state. '1' implies that this + * interrupt will be routed to EL3. '0' implies that this + * interrupt will be routed to the current exception level. + * + * Bit[1], Routing model for this interrupt type when execution is + * not in EL3 in the non-secure state. '1' implies that this + * interrupt will be routed to EL3. '0' implies that this + * interrupt will be routed to the current exception level. + * + * All other bits are reserved and SBZ. + ******************************************************************************/ +typedef struct intr_type_desc { + interrupt_type_handler_t handler; + u_register_t scr_el3[2]; + uint32_t flags; +} intr_type_desc_t; + +static intr_type_desc_t intr_type_descs[MAX_INTR_TYPES]; + +/******************************************************************************* + * This function validates the interrupt type. + ******************************************************************************/ +static int32_t validate_interrupt_type(uint32_t type) +{ + if ((type == INTR_TYPE_S_EL1) || (type == INTR_TYPE_NS) || + (type == INTR_TYPE_EL3)) + return 0; + + return -EINVAL; +} + +/******************************************************************************* +* This function validates the routing model for this type of interrupt + ******************************************************************************/ +static int32_t validate_routing_model(uint32_t type, uint32_t flags) +{ + uint32_t rm_flags = (flags >> INTR_RM_FLAGS_SHIFT) & INTR_RM_FLAGS_MASK; + + if (type == INTR_TYPE_S_EL1) + return validate_sel1_interrupt_rm(rm_flags); + + if (type == INTR_TYPE_NS) + return validate_ns_interrupt_rm(rm_flags); + + if (type == INTR_TYPE_EL3) + return validate_el3_interrupt_rm(rm_flags); + + return -EINVAL; +} + +/******************************************************************************* + * This function returns the cached copy of the SCR_EL3 which contains the + * routing model (expressed through the IRQ and FIQ bits) for a security state + * which was stored through a call to 'set_routing_model()' earlier. + ******************************************************************************/ +u_register_t get_scr_el3_from_routing_model(uint32_t security_state) +{ + u_register_t scr_el3; + + assert(sec_state_is_valid(security_state)); + scr_el3 = intr_type_descs[INTR_TYPE_NS].scr_el3[security_state]; + scr_el3 |= intr_type_descs[INTR_TYPE_S_EL1].scr_el3[security_state]; + scr_el3 |= intr_type_descs[INTR_TYPE_EL3].scr_el3[security_state]; + return scr_el3; +} + +/******************************************************************************* + * This function uses the 'interrupt_type_flags' parameter to obtain the value + * of the trap bit (IRQ/FIQ) in the SCR_EL3 for a security state for this + * interrupt type. It uses it to update the SCR_EL3 in the cpu context and the + * 'intr_type_desc' for that security state. + ******************************************************************************/ +static void set_scr_el3_from_rm(uint32_t type, + uint32_t interrupt_type_flags, + uint32_t security_state) +{ + uint32_t flag, bit_pos; + + flag = get_interrupt_rm_flag(interrupt_type_flags, security_state); + bit_pos = plat_interrupt_type_to_line(type, security_state); + intr_type_descs[type].scr_el3[security_state] = (u_register_t)flag << bit_pos; + + /* + * Update scr_el3 only if there is a context available. If not, it + * will be updated later during context initialization which will obtain + * the scr_el3 value to be used via get_scr_el3_from_routing_model() + */ + if (cm_get_context(security_state) != NULL) + cm_write_scr_el3_bit(security_state, bit_pos, flag); +} + +/******************************************************************************* + * This function validates the routing model specified in the 'flags' and + * updates internal data structures to reflect the new routing model. It also + * updates the copy of SCR_EL3 for each security state with the new routing + * model in the 'cpu_context' structure for this cpu. + ******************************************************************************/ +int32_t set_routing_model(uint32_t type, uint32_t flags) +{ + int32_t rc; + + rc = validate_interrupt_type(type); + if (rc != 0) + return rc; + + rc = validate_routing_model(type, flags); + if (rc != 0) + return rc; + + /* Update the routing model in internal data structures */ + intr_type_descs[type].flags = flags; + set_scr_el3_from_rm(type, flags, SECURE); + set_scr_el3_from_rm(type, flags, NON_SECURE); + + return 0; +} + +/****************************************************************************** + * This function disables the routing model of interrupt 'type' from the + * specified 'security_state' on the local core. The disable is in effect + * till the core powers down or till the next enable for that interrupt + * type. + *****************************************************************************/ +int disable_intr_rm_local(uint32_t type, uint32_t security_state) +{ + uint32_t bit_pos, flag; + + assert(intr_type_descs[type].handler != NULL); + + flag = get_interrupt_rm_flag(INTR_DEFAULT_RM, security_state); + + bit_pos = plat_interrupt_type_to_line(type, security_state); + cm_write_scr_el3_bit(security_state, bit_pos, flag); + + return 0; +} + +/****************************************************************************** + * This function enables the routing model of interrupt 'type' from the + * specified 'security_state' on the local core. + *****************************************************************************/ +int enable_intr_rm_local(uint32_t type, uint32_t security_state) +{ + uint32_t bit_pos, flag; + + assert(intr_type_descs[type].handler != NULL); + + flag = get_interrupt_rm_flag(intr_type_descs[type].flags, + security_state); + + bit_pos = plat_interrupt_type_to_line(type, security_state); + cm_write_scr_el3_bit(security_state, bit_pos, flag); + + return 0; +} + +/******************************************************************************* + * This function registers a handler for the 'type' of interrupt specified. It + * also validates the routing model specified in the 'flags' for this type of + * interrupt. + ******************************************************************************/ +int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler_t handler, + uint32_t flags) +{ + int32_t rc; + + /* Validate the 'handler' parameter */ + if (handler == NULL) + return -EINVAL; + + /* Validate the 'flags' parameter */ + if ((flags & INTR_TYPE_FLAGS_MASK) != 0U) + return -EINVAL; + + /* Check if a handler has already been registered */ + if (intr_type_descs[type].handler != NULL) + return -EALREADY; + + rc = set_routing_model(type, flags); + if (rc != 0) + return rc; + + /* Save the handler */ + intr_type_descs[type].handler = handler; + + return 0; +} + +/******************************************************************************* + * This function is called when an interrupt is generated and returns the + * handler for the interrupt type (if registered). It returns NULL if the + * interrupt type is not supported or its handler has not been registered. + ******************************************************************************/ +interrupt_type_handler_t get_interrupt_type_handler(uint32_t type) +{ + if (validate_interrupt_type(type) != 0) + return NULL; + + return intr_type_descs[type].handler; +} + diff --git a/arm-trusted-firmware/bl32/optee/optee.mk b/arm-trusted-firmware/bl32/optee/optee.mk new file mode 100644 index 0000000..c8aa7ce --- /dev/null +++ b/arm-trusted-firmware/bl32/optee/optee.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2019, Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# This makefile only aims at complying with Trusted Firmware-A build process so +# that "optee" is a valid TF-A AArch32 Secure Playload identifier. + +ifneq ($(ARCH),aarch32) +$(error This directory targets AArch32 support) +endif + +$(eval $(call add_define,AARCH32_SP_OPTEE)) + +$(info Trusted Firmware-A built for OP-TEE payload support) diff --git a/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S b/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S new file mode 100644 index 0000000..39f1065 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S @@ -0,0 +1,382 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + .globl sp_min_vector_table + .globl sp_min_entrypoint + .globl sp_min_warm_entrypoint + .globl sp_min_handle_smc + .globl sp_min_handle_fiq + +#define FIXUP_SIZE ((BL32_LIMIT) - (BL32_BASE)) + + .macro route_fiq_to_sp_min reg + /* ----------------------------------------------------- + * FIQs are secure interrupts trapped by Monitor and non + * secure is not allowed to mask the FIQs. + * ----------------------------------------------------- + */ + ldcopr \reg, SCR + orr \reg, \reg, #SCR_FIQ_BIT + bic \reg, \reg, #SCR_FW_BIT + stcopr \reg, SCR + .endm + + .macro clrex_on_monitor_entry +#if (ARM_ARCH_MAJOR == 7) + /* + * ARMv7 architectures need to clear the exclusive access when + * entering Monitor mode. + */ + clrex +#endif + .endm + +vector_base sp_min_vector_table + b sp_min_entrypoint + b plat_panic_handler /* Undef */ + b sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + b plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ + b plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + + +/* + * The Cold boot/Reset entrypoint for SP_MIN + */ +func sp_min_entrypoint +#if !RESET_TO_SP_MIN + /* --------------------------------------------------------------- + * Preceding bootloader has populated r0 with a pointer to a + * 'bl_params_t' structure & r1 with a pointer to platform + * specific structure + * --------------------------------------------------------------- + */ + mov r9, r0 + mov r10, r1 + mov r11, r2 + mov r12, r3 + + /* --------------------------------------------------------------------- + * For !RESET_TO_SP_MIN systems, only the primary CPU ever reaches + * sp_min_entrypoint() during the cold boot flow, so the cold/warm boot + * and primary/secondary CPU logic should not be executed in this case. + * + * Also, assume that the previous bootloader has already initialised the + * SCTLR, including the CPU endianness, and has initialised the memory. + * --------------------------------------------------------------------- + */ + el3_entrypoint_common \ + _init_sctlr=0 \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=1 \ + _exception_vectors=sp_min_vector_table \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------------------------------- + * Relay the previous bootloader's arguments to the platform layer + * --------------------------------------------------------------------- + */ +#else + /* --------------------------------------------------------------------- + * For RESET_TO_SP_MIN systems which have a programmable reset address, + * sp_min_entrypoint() is executed only on the cold boot path so we can + * skip the warm boot mailbox mechanism. + * --------------------------------------------------------------------- + */ + el3_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=sp_min_vector_table \ + _pie_fixup_size=FIXUP_SIZE + + /* --------------------------------------------------------------------- + * For RESET_TO_SP_MIN systems, BL32 (SP_MIN) is the first bootloader + * to run so there's no argument to relay from a previous bootloader. + * Zero the arguments passed to the platform layer to reflect that. + * --------------------------------------------------------------------- + */ + mov r9, #0 + mov r10, #0 + mov r11, #0 + mov r12, #0 + +#endif /* RESET_TO_SP_MIN */ + +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r4 +#endif + + mov r0, r9 + mov r1, r10 + mov r2, r11 + mov r3, r12 + bl sp_min_early_platform_setup2 + bl sp_min_plat_arch_setup + + /* Jump to the main function */ + bl sp_min_main + + /* ------------------------------------------------------------- + * Clean the .data & .bss sections to main memory. This ensures + * that any global data which was initialised by the primary CPU + * is visible to secondary CPUs before they enable their data + * caches and participate in coherency. + * ------------------------------------------------------------- + */ + ldr r0, =__DATA_START__ + ldr r1, =__DATA_END__ + sub r1, r1, r0 + bl clean_dcache_range + + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl clean_dcache_range + + bl smc_get_next_ctx + + /* r0 points to `smc_ctx_t` */ + /* The PSCI cpu_context registers have been copied to `smc_ctx_t` */ + b sp_min_exit +endfunc sp_min_entrypoint + + +/* + * SMC handling function for SP_MIN. + */ +func sp_min_handle_smc + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * Read the timestamp value and store it on top of the C runtime stack. + * The value will be saved to the per-cpu data once the C stack is + * available, as a valid stack is needed to call _cpu_data() + */ + strd r0, r1, [sp, #SMC_CTX_GPREG_R0] + ldcopr16 r0, r1, CNTPCT_64 + ldr lr, [sp, #SMC_CTX_SP_MON] + strd r0, r1, [lr, #-8]! + str lr, [sp, #SMC_CTX_SP_MON] + ldrd r0, r1, [sp, #SMC_CTX_GPREG_R0] +#endif + + smccc_save_gp_mode_regs + + clrex_on_monitor_entry + + /* + * `sp` still points to `smc_ctx_t`. Save it to a register + * and restore the C runtime stack pointer to `sp`. + */ + mov r2, sp /* handle */ + ldr sp, [r2, #SMC_CTX_SP_MON] + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* Save handle to a callee saved register */ + mov r6, r2 + + /* + * Restore the timestamp value and store it in per-cpu data. The value + * will be extracted from per-cpu data by the C level SMC handler and + * saved to the PMF timestamp region. + */ + ldrd r4, r5, [sp], #8 + bl _cpu_data + strd r4, r5, [r0, #CPU_DATA_PMF_TS0_OFFSET] + + /* Restore handle */ + mov r2, r6 +#endif + + ldr r0, [r2, #SMC_CTX_SCR] + and r3, r0, #SCR_NS_BIT /* flags */ + + /* Switch to Secure Mode*/ + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + ldr r0, [r2, #SMC_CTX_GPREG_R0] /* smc_fid */ + /* Check whether an SMC64 is issued */ + tst r0, #(FUNCID_CC_MASK << FUNCID_CC_SHIFT) + beq 1f + /* SMC32 is not detected. Return error back to caller */ + mov r0, #SMC_UNK + str r0, [r2, #SMC_CTX_GPREG_R0] + mov r0, r2 + b sp_min_exit +1: + /* SMC32 is detected */ + mov r1, #0 /* cookie */ + bl handle_runtime_svc + + /* `r0` points to `smc_ctx_t` */ + b sp_min_exit +endfunc sp_min_handle_smc + +/* + * Secure Interrupts handling function for SP_MIN. + */ +func sp_min_handle_fiq +#if !SP_MIN_WITH_SECURE_FIQ + b plat_panic_handler +#else + /* FIQ has a +4 offset for lr compared to preferred return address */ + sub lr, lr, #4 + /* On SMC entry, `sp` points to `smc_ctx_t`. Save `lr`. */ + str lr, [sp, #SMC_CTX_LR_MON] + + smccc_save_gp_mode_regs + + clrex_on_monitor_entry + + /* load run-time stack */ + mov r2, sp + ldr sp, [r2, #SMC_CTX_SP_MON] + + /* Switch to Secure Mode */ + ldr r0, [r2, #SMC_CTX_SCR] + bic r0, #SCR_NS_BIT + stcopr r0, SCR + isb + + push {r2, r3} + bl sp_min_fiq + pop {r0, r3} + + b sp_min_exit +#endif +endfunc sp_min_handle_fiq + +/* + * The Warm boot entrypoint for SP_MIN. + */ +func sp_min_warm_entrypoint +#if ENABLE_RUNTIME_INSTRUMENTATION + /* + * This timestamp update happens with cache off. The next + * timestamp collection will need to do cache maintenance prior + * to timestamp update. + */ + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_HW_LOW_PWR + ldcopr16 r2, r3, CNTPCT_64 + strd r2, r3, [r0] +#endif + /* + * On the warm boot path, most of the EL3 initialisations performed by + * 'el3_entrypoint_common' must be skipped: + * + * - Only when the platform bypasses the BL1/BL32 (SP_MIN) entrypoint by + * programming the reset address do we need to initialied the SCTLR. + * In other cases, we assume this has been taken care by the + * entrypoint code. + * + * - No need to determine the type of boot, we know it is a warm boot. + * + * - Do not try to distinguish between primary and secondary CPUs, this + * notion only exists for a cold boot. + * + * - No need to initialise the memory or the C runtime environment, + * it has been done once and for all on the cold boot path. + */ + el3_entrypoint_common \ + _init_sctlr=PROGRAMMABLE_RESET_ADDRESS \ + _warm_boot_mailbox=0 \ + _secondary_cold_boot=0 \ + _init_memory=0 \ + _init_c_runtime=0 \ + _exception_vectors=sp_min_vector_table \ + _pie_fixup_size=0 + + /* + * We're about to enable MMU and participate in PSCI state coordination. + * + * The PSCI implementation invokes platform routines that enable CPUs to + * participate in coherency. On a system where CPUs are not + * cache-coherent without appropriate platform specific programming, + * having caches enabled until such time might lead to coherency issues + * (resulting from stale data getting speculatively fetched, among + * others). Therefore we keep data caches disabled even after enabling + * the MMU for such platforms. + * + * On systems with hardware-assisted coherency, or on single cluster + * platforms, such platform specific programming is not required to + * enter coherency (as CPUs already are); and there's no reason to have + * caches disabled either. + */ +#if HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY + mov r0, #0 +#else + mov r0, #DISABLE_DCACHE +#endif + bl bl32_plat_enable_mmu + +#if SP_MIN_WITH_SECURE_FIQ + route_fiq_to_sp_min r0 +#endif + + bl sp_min_warm_boot + bl smc_get_next_ctx + /* r0 points to `smc_ctx_t` */ + /* The PSCI cpu_context registers have been copied to `smc_ctx_t` */ + +#if ENABLE_RUNTIME_INSTRUMENTATION + /* Save smc_ctx_t */ + mov r5, r0 + + pmf_calc_timestamp_addr rt_instr_svc, RT_INSTR_EXIT_PSCI + mov r4, r0 + + /* + * Invalidate before updating timestamp to ensure previous timestamp + * updates on the same cache line with caches disabled are properly + * seen by the same core. Without the cache invalidate, the core might + * write into a stale cache line. + */ + mov r1, #PMF_TS_SIZE + bl inv_dcache_range + + ldcopr16 r0, r1, CNTPCT_64 + strd r0, r1, [r4] + + /* Restore smc_ctx_t */ + mov r0, r5 +#endif + + b sp_min_exit +endfunc sp_min_warm_entrypoint + +/* + * The function to restore the registers from SMC context and return + * to the mode restored to SPSR. + * + * Arguments : r0 must point to the SMC context to restore from. + */ +func sp_min_exit + monitor_exit +endfunc sp_min_exit diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S b/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S new file mode 100644 index 0000000..475affa --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min.ld.S @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(elf32-littlearm) +OUTPUT_ARCH(arm) +ENTRY(sp_min_vector_table) + +MEMORY { + RAM (rwx): ORIGIN = BL32_BASE, LENGTH = BL32_LIMIT - BL32_BASE +} + +#ifdef PLAT_SP_MIN_EXTRA_LD_SCRIPT +#include +#endif + +SECTIONS +{ + . = BL32_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL32_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + /* .ARM.extab and .ARM.exidx are only added because Clang need them */ + .ARM.extab . : { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } >RAM + + .ARM.exidx . : { + *(.ARM.exidx* .gnu.linkonce.armexidx.*) + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *entrypoint.o(.text*) + *(SORT_BY_ALIGNMENT(.text*)) + *(SORT_BY_ALIGNMENT(.rodata*)) + + RODATA_COMMON + + /* Place pubsub sections for events */ + . = ALIGN(8); +#include + + *(.vectors) + __RO_END_UNALIGNED__ = .; + + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + RELA_SECTION >RAM + +#ifdef BL32_PROGBITS_LIMIT + ASSERT(. <= BL32_PROGBITS_LIMIT, "BL32 progbits has exceeded its limit.") +#endif + + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + + __BSS_SIZE__ = SIZEOF(.bss); + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + /* + * 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_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM + + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + + __BL32_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min.mk b/arm-trusted-firmware/bl32/sp_min/sp_min.mk new file mode 100644 index 0000000..590b032 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min.mk @@ -0,0 +1,73 @@ +# +# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH}, aarch32) + $(error SP_MIN is only supported on AArch32 platforms) +endif + +include lib/extensions/amu/amu.mk +include lib/psci/psci_lib.mk + +INCLUDES += -Iinclude/bl32/sp_min + +BL32_SOURCES += bl32/sp_min/sp_min_main.c \ + bl32/sp_min/aarch32/entrypoint.S \ + common/runtime_svc.c \ + plat/common/aarch32/plat_sp_min_common.c\ + services/std_svc/std_svc_setup.c \ + ${PSCI_LIB_SOURCES} + +ifeq (${DISABLE_MTPMU},1) +BL32_SOURCES += lib/extensions/mtpmu/aarch32/mtpmu.S +endif + +ifeq (${ENABLE_PMF}, 1) +BL32_SOURCES += lib/pmf/pmf_main.c +endif + +ifeq (${ENABLE_AMU},1) +BL32_SOURCES += ${AMU_SOURCES} +endif + +ifeq (${WORKAROUND_CVE_2017_5715},1) +BL32_SOURCES += bl32/sp_min/wa_cve_2017_5715_bpiall.S \ + bl32/sp_min/wa_cve_2017_5715_icache_inv.S +endif + +ifeq (${TRNG_SUPPORT},1) +BL32_SOURCES += services/std_svc/trng/trng_main.c \ + services/std_svc/trng/trng_entropy_pool.c +endif + +ifeq (${ENABLE_SYS_REG_TRACE_FOR_NS},1) +BL32_SOURCES += lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c +endif + +ifeq (${ENABLE_TRF_FOR_NS},1) +BL32_SOURCES += lib/extensions/trf/aarch32/trf.c +endif + +BL32_LINKERFILE := bl32/sp_min/sp_min.ld.S + +# Include the platform-specific SP_MIN Makefile +# If no platform-specific SP_MIN Makefile exists, it means SP_MIN is not supported +# on this platform. +SP_MIN_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/sp_min/sp_min-${PLAT}.mk) +ifeq (,${SP_MIN_PLAT_MAKEFILE}) + $(error SP_MIN is not supported on platform ${PLAT}) +else + include ${SP_MIN_PLAT_MAKEFILE} +endif + +RESET_TO_SP_MIN := 0 +$(eval $(call add_define,RESET_TO_SP_MIN)) +$(eval $(call assert_boolean,RESET_TO_SP_MIN)) + +# Flag to allow SP_MIN to handle FIQ interrupts in monitor mode. The platform +# port is free to override this value. It is default disabled. +SP_MIN_WITH_SECURE_FIQ ?= 0 +$(eval $(call add_define,SP_MIN_WITH_SECURE_FIQ)) +$(eval $(call assert_boolean,SP_MIN_WITH_SECURE_FIQ)) diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min_main.c b/arm-trusted-firmware/bl32/sp_min/sp_min_main.c new file mode 100644 index 0000000..f050160 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min_main.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sp_min_private.h" + +#if ENABLE_RUNTIME_INSTRUMENTATION +PMF_REGISTER_SERVICE_SMC(rt_instr_svc, PMF_RT_INSTR_SVC_ID, + RT_INSTR_TOTAL_IDS, PMF_STORE_ENABLE) +#endif + +/* Pointers to per-core cpu contexts */ +static void *sp_min_cpu_ctx_ptr[PLATFORM_CORE_COUNT]; + +/* SP_MIN only stores the non secure smc context */ +static smc_ctx_t sp_min_smc_context[PLATFORM_CORE_COUNT]; + +/****************************************************************************** + * Define the smccc helper library APIs + *****************************************************************************/ +void *smc_get_ctx(unsigned int security_state) +{ + assert(security_state == NON_SECURE); + return &sp_min_smc_context[plat_my_core_pos()]; +} + +void smc_set_next_ctx(unsigned int security_state) +{ + assert(security_state == NON_SECURE); + /* SP_MIN stores only non secure smc context. Nothing to do here */ +} + +void *smc_get_next_ctx(void) +{ + return &sp_min_smc_context[plat_my_core_pos()]; +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the calling CPU that was set as the context for the specified security + * state. NULL is returned if no such structure has been specified. + ******************************************************************************/ +void *cm_get_context(uint32_t security_state) +{ + assert(security_state == NON_SECURE); + return sp_min_cpu_ctx_ptr[plat_my_core_pos()]; +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the calling CPU + ******************************************************************************/ +void cm_set_context(void *context, uint32_t security_state) +{ + assert(security_state == NON_SECURE); + sp_min_cpu_ctx_ptr[plat_my_core_pos()] = context; +} + +/******************************************************************************* + * This function returns a pointer to the most recent 'cpu_context' structure + * for the CPU identified by `cpu_idx` that was set as the context for the + * specified security state. NULL is returned if no such structure has been + * specified. + ******************************************************************************/ +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state) +{ + assert(security_state == NON_SECURE); + return sp_min_cpu_ctx_ptr[cpu_idx]; +} + +/******************************************************************************* + * This function sets the pointer to the current 'cpu_context' structure for the + * specified security state for the CPU identified by CPU index. + ******************************************************************************/ +void cm_set_context_by_index(unsigned int cpu_idx, void *context, + unsigned int security_state) +{ + assert(security_state == NON_SECURE); + sp_min_cpu_ctx_ptr[cpu_idx] = context; +} + +static void copy_cpu_ctx_to_smc_stx(const regs_t *cpu_reg_ctx, + smc_ctx_t *next_smc_ctx) +{ + next_smc_ctx->r0 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R0); + next_smc_ctx->r1 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R1); + next_smc_ctx->r2 = read_ctx_reg(cpu_reg_ctx, CTX_GPREG_R2); + next_smc_ctx->lr_mon = read_ctx_reg(cpu_reg_ctx, CTX_LR); + next_smc_ctx->spsr_mon = read_ctx_reg(cpu_reg_ctx, CTX_SPSR); + next_smc_ctx->scr = read_ctx_reg(cpu_reg_ctx, CTX_SCR); +} + +/******************************************************************************* + * This function invokes the PSCI library interface to initialize the + * non secure cpu context and copies the relevant cpu context register values + * to smc context. These registers will get programmed during `smc_exit`. + ******************************************************************************/ +static void sp_min_prepare_next_image_entry(void) +{ + entry_point_info_t *next_image_info; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + u_register_t ns_sctlr; + + /* Program system registers to proceed to non-secure */ + next_image_info = sp_min_plat_get_bl33_ep_info(); + assert(next_image_info); + assert(NON_SECURE == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("SP_MIN: Preparing exit to normal world\n"); + + psci_prepare_next_non_secure_ctx(next_image_info); + smc_set_next_ctx(NON_SECURE); + + /* Copy r0, lr and spsr from cpu context to SMC context */ + copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)), + smc_get_next_ctx()); + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); +} + +/****************************************************************************** + * Implement the ARM Standard Service function to get arguments for a + * particular service. + *****************************************************************************/ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask) +{ + /* Setup the arguments for PSCI Library */ + DEFINE_STATIC_PSCI_LIB_ARGS_V1(psci_args, sp_min_warm_entrypoint); + + /* PSCI is the only ARM Standard Service implemented */ + assert(svc_mask == PSCI_FID_MASK); + + return (uintptr_t)&psci_args; +} + +/****************************************************************************** + * The SP_MIN main function. Do the platform and PSCI Library setup. Also + * initialize the runtime service framework. + *****************************************************************************/ +void sp_min_main(void) +{ + NOTICE("SP_MIN: %s\n", version_string); + NOTICE("SP_MIN: %s\n", build_message); + + /* Perform the SP_MIN platform setup */ + sp_min_platform_setup(); + + /* Initialize the runtime services e.g. psci */ + INFO("SP_MIN: Initializing runtime services\n"); + runtime_svc_init(); + + /* + * We are ready to enter the next EL. Prepare entry into the image + * corresponding to the desired security state after the next ERET. + */ + sp_min_prepare_next_image_entry(); + + /* + * Perform any platform specific runtime setup prior to cold boot exit + * from SP_MIN. + */ + sp_min_plat_runtime_setup(); + + console_flush(); +} + +/****************************************************************************** + * This function is invoked during warm boot. Invoke the PSCI library + * warm boot entry point which takes care of Architectural and platform setup/ + * restore. Copy the relevant cpu_context register values to smc context which + * will get programmed during `smc_exit`. + *****************************************************************************/ +void sp_min_warm_boot(void) +{ + smc_ctx_t *next_smc_ctx; + cpu_context_t *ctx = cm_get_context(NON_SECURE); + u_register_t ns_sctlr; + + psci_warmboot_entrypoint(); + + smc_set_next_ctx(NON_SECURE); + + next_smc_ctx = smc_get_next_ctx(); + zeromem(next_smc_ctx, sizeof(smc_ctx_t)); + + copy_cpu_ctx_to_smc_stx(get_regs_ctx(cm_get_context(NON_SECURE)), + next_smc_ctx); + + /* Temporarily set the NS bit to access NS SCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + ns_sctlr = read_ctx_reg(get_regs_ctx(ctx), CTX_NS_SCTLR); + write_sctlr(ns_sctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); +} + +#if SP_MIN_WITH_SECURE_FIQ +/****************************************************************************** + * This function is invoked on secure interrupts. By construction of the + * SP_MIN, secure interrupts can only be handled when core executes in non + * secure state. + *****************************************************************************/ +void sp_min_fiq(void) +{ + uint32_t id; + + id = plat_ic_acknowledge_interrupt(); + sp_min_plat_fiq_handler(id); + plat_ic_end_of_interrupt(id); +} +#endif /* SP_MIN_WITH_SECURE_FIQ */ diff --git a/arm-trusted-firmware/bl32/sp_min/sp_min_private.h b/arm-trusted-firmware/bl32/sp_min/sp_min_private.h new file mode 100644 index 0000000..628581a --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/sp_min_private.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP_MIN_PRIVATE_H +#define SP_MIN_PRIVATE_H + +void sp_min_main(void); +void sp_min_warm_boot(void); +void sp_min_fiq(void); + +#endif /* SP_MIN_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S new file mode 100644 index 0000000..385f3d4 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl wa_cve_2017_5715_bpiall_vbar + +vector_base wa_cve_2017_5715_bpiall_vbar + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the branch predictor, `r0` is a dummy register + * and is unused. + */ + stcopr r0, BPIALL + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + tst sp, #2 + bne 2f + + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S new file mode 100644 index 0000000..d0a4625 --- /dev/null +++ b/arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl wa_cve_2017_5715_icache_inv_vbar + +vector_base wa_cve_2017_5715_icache_inv_vbar + /* We encode the exception entry in the bottom 3 bits of SP */ + add sp, sp, #1 /* Reset: 0b111 */ + add sp, sp, #1 /* Undef: 0b110 */ + add sp, sp, #1 /* Syscall: 0b101 */ + add sp, sp, #1 /* Prefetch abort: 0b100 */ + add sp, sp, #1 /* Data abort: 0b011 */ + add sp, sp, #1 /* Reserved: 0b010 */ + add sp, sp, #1 /* IRQ: 0b001 */ + nop /* FIQ: 0b000 */ + + /* + * Invalidate the instruction cache, which we assume also + * invalidates the branch predictor. This may depend on + * other CPU specific changes (e.g. an ACTLR setting). + */ + stcopr r0, ICIALLU + isb + + /* + * As we cannot use any temporary registers and cannot + * clobber SP, we can decode the exception entry using + * an unrolled binary search. + * + * Note, if this code is re-used by other secure payloads, + * the below exception entry vectors must be changed to + * the vectors specific to that secure payload. + */ + + tst sp, #4 + bne 1f + + tst sp, #2 + bne 3f + + /* Expected encoding: 0x1 and 0x0 */ + tst sp, #1 + /* Restore original value of SP by clearing the bottom 3 bits */ + bic sp, sp, #0x7 + bne plat_panic_handler /* IRQ */ + b sp_min_handle_fiq /* FIQ */ + +1: + /* Expected encoding: 0x4 and 0x5 */ + tst sp, #2 + bne 2f + + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_handle_smc /* Syscall */ + b plat_panic_handler /* Prefetch abort */ + +2: + /* Expected encoding: 0x7 and 0x6 */ + tst sp, #1 + bic sp, sp, #0x7 + bne sp_min_entrypoint /* Reset */ + b plat_panic_handler /* Undef */ + +3: + /* Expected encoding: 0x2 and 0x3 */ + tst sp, #1 + bic sp, sp, #0x7 + bne plat_panic_handler /* Data abort */ + b plat_panic_handler /* Reserved */ diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S new file mode 100644 index 0000000..7d77f47 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S @@ -0,0 +1,485 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "../tsp_private.h" + + + .globl tsp_entrypoint + .globl tsp_vector_table + + + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TSP_ARG6] + ldp x4, x5, [x0, #TSP_ARG4] + ldp x2, x3, [x0, #TSP_ARG2] + ldp x0, x1, [x0, #TSP_ARG0] + smc #0 + .endm + + .macro save_eret_context reg1 reg2 + mrs \reg1, elr_el1 + mrs \reg2, spsr_el1 + stp \reg1, \reg2, [sp, #-0x10]! + stp x30, x18, [sp, #-0x10]! + .endm + + .macro restore_eret_context reg1 reg2 + ldp x30, x18, [sp], #0x10 + ldp \reg1, \reg2, [sp], #0x10 + msr elr_el1, \reg1 + msr spsr_el1, \reg2 + .endm + +func tsp_entrypoint _align=3 + +#if ENABLE_PIE + /* + * ------------------------------------------------------------ + * If PIE is enabled fixup the Global descriptor Table only + * once during primary core cold boot path. + * + * Compile time base address, required for fixup, is calculated + * using "pie_fixup" label present within first page. + * ------------------------------------------------------------ + */ + pie_fixup: + ldr x0, =pie_fixup + and x0, x0, #~(PAGE_SIZE_MASK) + mov_imm x1, (BL32_LIMIT - BL32_BASE) + add x1, x1, x0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, tsp_exceptions + msr vbar_el1, x0 + isb + + /* --------------------------------------------- + * Enable the SError interrupt now that the + * exception vectors have been setup. + * --------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks and disable + * speculative loads. + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + bic x0, x0, #SCTLR_DSSBS_BIT + msr sctlr_el1, x0 + isb + + /* --------------------------------------------- + * Invalidate the RW memory used by the BL32 + * image. This includes the data and NOBITS + * sections. This is done to safeguard against + * possible corruption of this memory by dirty + * cache lines in a system cache as a result of + * use by an earlier boot loader stage. If PIE + * is enabled however, RO sections including the + * GOT may be modified during pie fixup. + * Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * --------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + adrp x0, __TEXT_START__ + add x0, x0, :lo12:__TEXT_START__ +#else + adrp x0, __RO_START__ + add x0, x0, :lo12:__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ +#endif /* ENABLE_PIE */ + adrp x1, __RW_END__ + add x1, x1, :lo12:__RW_END__ + sub x1, x1, x0 + bl inv_dcache_range + + /* --------------------------------------------- + * Zero out NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section. + * --------------------------------------------- + */ + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if USE_COHERENT_MEM + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12:__COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 + bl zeromem +#endif + + /* -------------------------------------------- + * Allocate a stack whose memory will be marked + * as Normal-IS-WBWA when the MMU is enabled. + * There is no risk of reading stale stack + * memory after enabling the MMU as only the + * primary cpu is running at the moment. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* --------------------------------------------- + * Initialize the stack protector canary before + * any C code is called. + * --------------------------------------------- + */ +#if STACK_PROTECTOR_ENABLED + bl update_stack_protector_canary +#endif + + /* --------------------------------------------- + * Perform TSP setup + * --------------------------------------------- + */ + bl tsp_setup + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Jump to main function. + * --------------------------------------------- + */ + bl tsp_main + + /* --------------------------------------------- + * Tell TSPD that we are done initialising + * --------------------------------------------- + */ + mov x1, x0 + mov x0, #TSP_ENTRY_DONE + smc #0 + +tsp_entrypoint_panic: + b tsp_entrypoint_panic +endfunc tsp_entrypoint + + + /* ------------------------------------------- + * Table of entrypoint vectors provided to the + * TSPD for the various entrypoints + * ------------------------------------------- + */ +vector_base tsp_vector_table + b tsp_yield_smc_entry + b tsp_fast_smc_entry + b tsp_cpu_on_entry + b tsp_cpu_off_entry + b tsp_cpu_resume_entry + b tsp_cpu_suspend_entry + b tsp_sel1_intr_entry + b tsp_system_off_entry + b tsp_system_reset_entry + b tsp_abort_yield_smc_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be turned off through a CPU_OFF + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD expects the TSP to + * re-initialise its state so nothing is done + * here except for acknowledging the request. + * --------------------------------------------- + */ +func tsp_cpu_off_entry + bl tsp_cpu_off_main + restore_args_call_smc +endfunc tsp_cpu_off_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when the + * system is about to be switched off (through + * a SYSTEM_OFF psci call) to ask the TSP to + * perform any necessary bookkeeping. + * --------------------------------------------- + */ +func tsp_system_off_entry + bl tsp_system_off_main + restore_args_call_smc +endfunc tsp_system_off_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when the + * system is about to be reset (through a + * SYSTEM_RESET psci call) to ask the TSP to + * perform any necessary bookkeeping. + * --------------------------------------------- + */ +func tsp_system_reset_entry + bl tsp_system_reset_main + restore_args_call_smc +endfunc tsp_system_reset_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is turned on using a CPU_ON psci call to + * ask the TSP to initialise itself i.e. setup + * the mmu, stacks etc. Minimal architectural + * state will be initialised by the TSPD when + * this function is entered i.e. Caches and MMU + * will be turned off, the execution state + * will be aarch64 and exceptions masked. + * --------------------------------------------- + */ +func tsp_cpu_on_entry + /* --------------------------------------------- + * Set the exception vector to something sane. + * --------------------------------------------- + */ + adr x0, tsp_exceptions + msr vbar_el1, x0 + isb + + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------- + * Enable the instruction cache, stack pointer + * and data access alignment checks + * --------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el1 + orr x0, x0, x1 + msr sctlr_el1, x0 + isb + + /* -------------------------------------------- + * Give ourselves a stack whose memory will be + * marked as Normal-IS-WBWA when the MMU is + * enabled. + * -------------------------------------------- + */ + bl plat_set_my_stack + + /* -------------------------------------------- + * Enable MMU and D-caches together. + * -------------------------------------------- + */ + mov x0, #0 + bl bl32_plat_enable_mmu + +#if ENABLE_PAUTH + /* --------------------------------------------- + * Program APIAKey_EL1 + * and enable pointer authentication + * --------------------------------------------- + */ + bl pauth_init_enable_el1 +#endif /* ENABLE_PAUTH */ + + /* --------------------------------------------- + * Enter C runtime to perform any remaining + * book keeping + * --------------------------------------------- + */ + bl tsp_cpu_on_main + restore_args_call_smc + + /* Should never reach here */ +tsp_cpu_on_entry_panic: + b tsp_cpu_on_entry_panic +endfunc tsp_cpu_on_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu is to be suspended through a CPU_SUSPEND + * psci call to ask the TSP to perform any + * bookeeping necessary. In the current + * implementation, the TSPD saves and restores + * the EL1 state. + * --------------------------------------------- + */ +func tsp_cpu_suspend_entry + bl tsp_cpu_suspend_main + restore_args_call_smc +endfunc tsp_cpu_suspend_entry + + /*------------------------------------------------- + * This entrypoint is used by the TSPD to pass + * control for `synchronously` handling a S-EL1 + * Interrupt which was triggered while executing + * in normal world. 'x0' contains a magic number + * which indicates this. TSPD expects control to + * be handed back at the end of interrupt + * processing. This is done through an SMC. + * The handover agreement is: + * + * 1. PSTATE.DAIF are set upon entry. 'x1' has + * the ELR_EL3 from the non-secure state. + * 2. TSP has to preserve the callee saved + * general purpose registers, SP_EL1/EL0 and + * LR. + * 3. TSP has to preserve the system and vfp + * registers (if applicable). + * 4. TSP can use 'x0-x18' to enable its C + * runtime. + * 5. TSP returns to TSPD using an SMC with + * 'x0' = TSP_HANDLED_S_EL1_INTR + * ------------------------------------------------ + */ +func tsp_sel1_intr_entry +#if DEBUG + mov_imm x2, TSP_HANDLE_SEL1_INTR_AND_RETURN + cmp x0, x2 + b.ne tsp_sel1_int_entry_panic +#endif + /*------------------------------------------------- + * Save any previous context needed to perform + * an exception return from S-EL1 e.g. context + * from a previous Non secure Interrupt. + * Update statistics and handle the S-EL1 + * interrupt before returning to the TSPD. + * IRQ/FIQs are not enabled since that will + * complicate the implementation. Execution + * will be transferred back to the normal world + * in any case. The handler can return 0 + * if the interrupt was handled or TSP_PREEMPTED + * if the expected interrupt was preempted + * by an interrupt that should be handled in EL3 + * e.g. Group 0 interrupt in GICv3. In both + * the cases switch to EL3 using SMC with id + * TSP_HANDLED_S_EL1_INTR. Any other return value + * from the handler will result in panic. + * ------------------------------------------------ + */ + save_eret_context x2 x3 + bl tsp_update_sync_sel1_intr_stats + bl tsp_common_int_handler + /* Check if the S-EL1 interrupt has been handled */ + cbnz x0, tsp_sel1_intr_check_preemption + b tsp_sel1_intr_return +tsp_sel1_intr_check_preemption: + /* Check if the S-EL1 interrupt has been preempted */ + mov_imm x1, TSP_PREEMPTED + cmp x0, x1 + b.ne tsp_sel1_int_entry_panic +tsp_sel1_intr_return: + mov_imm x0, TSP_HANDLED_S_EL1_INTR + restore_eret_context x2 x3 + smc #0 + + /* Should never reach here */ +tsp_sel1_int_entry_panic: + no_ret plat_panic_handler +endfunc tsp_sel1_intr_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD when this + * cpu resumes execution after an earlier + * CPU_SUSPEND psci call to ask the TSP to + * restore its saved context. In the current + * implementation, the TSPD saves and restores + * EL1 state so nothing is done here apart from + * acknowledging the request. + * --------------------------------------------- + */ +func tsp_cpu_resume_entry + bl tsp_cpu_resume_main + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_cpu_resume_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD to ask + * the TSP to service a fast smc request. + * --------------------------------------------- + */ +func tsp_fast_smc_entry + bl tsp_smc_handler + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_fast_smc_entry + + /*--------------------------------------------- + * This entrypoint is used by the TSPD to ask + * the TSP to service a Yielding SMC request. + * We will enable preemption during execution + * of tsp_smc_handler. + * --------------------------------------------- + */ +func tsp_yield_smc_entry + msr daifclr, #DAIF_FIQ_BIT | DAIF_IRQ_BIT + bl tsp_smc_handler + msr daifset, #DAIF_FIQ_BIT | DAIF_IRQ_BIT + restore_args_call_smc + + /* Should never reach here */ + no_ret plat_panic_handler +endfunc tsp_yield_smc_entry + + /*--------------------------------------------------------------------- + * This entrypoint is used by the TSPD to abort a pre-empted Yielding + * SMC. It could be on behalf of non-secure world or because a CPU + * suspend/CPU off request needs to abort the preempted SMC. + * -------------------------------------------------------------------- + */ +func tsp_abort_yield_smc_entry + + /* + * Exceptions masking is already done by the TSPD when entering this + * hook so there is no need to do it here. + */ + + /* Reset the stack used by the pre-empted SMC */ + bl plat_set_my_stack + + /* + * Allow some cleanup such as releasing locks. + */ + bl tsp_abort_smc_handler + + restore_args_call_smc + + /* Should never reach here */ + bl plat_panic_handler +endfunc tsp_abort_yield_smc_entry diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S new file mode 100644 index 0000000..4c6a56a --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + /* ---------------------------------------------------- + * The caller-saved registers x0-x18 and LR are saved + * here. + * ---------------------------------------------------- + */ + +#define SCRATCH_REG_SIZE #(20 * 8) + + .macro save_caller_regs_and_lr + sub sp, sp, SCRATCH_REG_SIZE + stp x0, x1, [sp] + stp x2, x3, [sp, #0x10] + stp x4, x5, [sp, #0x20] + stp x6, x7, [sp, #0x30] + stp x8, x9, [sp, #0x40] + stp x10, x11, [sp, #0x50] + stp x12, x13, [sp, #0x60] + stp x14, x15, [sp, #0x70] + stp x16, x17, [sp, #0x80] + stp x18, x30, [sp, #0x90] + .endm + + .macro restore_caller_regs_and_lr + ldp x0, x1, [sp] + ldp x2, x3, [sp, #0x10] + ldp x4, x5, [sp, #0x20] + ldp x6, x7, [sp, #0x30] + ldp x8, x9, [sp, #0x40] + ldp x10, x11, [sp, #0x50] + ldp x12, x13, [sp, #0x60] + ldp x14, x15, [sp, #0x70] + ldp x16, x17, [sp, #0x80] + ldp x18, x30, [sp, #0x90] + add sp, sp, SCRATCH_REG_SIZE + .endm + + /* ---------------------------------------------------- + * Common TSP interrupt handling routine + * ---------------------------------------------------- + */ + .macro handle_tsp_interrupt label + /* Enable the SError interrupt */ + msr daifclr, #DAIF_ABT_BIT + + save_caller_regs_and_lr + bl tsp_common_int_handler + cbz x0, interrupt_exit_\label + + /* + * This interrupt was not targetted to S-EL1 so send it to + * the monitor and wait for execution to resume. + */ + smc #0 +interrupt_exit_\label: + restore_caller_regs_and_lr + exception_return + .endm + + .globl tsp_exceptions + + /* ----------------------------------------------------- + * TSP exception handlers. + * ----------------------------------------------------- + */ +vector_base tsp_exceptions + /* ----------------------------------------------------- + * Current EL with _sp_el0 : 0x0 - 0x200. No exceptions + * are expected and treated as irrecoverable errors. + * ----------------------------------------------------- + */ +vector_entry sync_exception_sp_el0 + b plat_panic_handler +end_vector_entry sync_exception_sp_el0 + +vector_entry irq_sp_el0 + b plat_panic_handler +end_vector_entry irq_sp_el0 + +vector_entry fiq_sp_el0 + b plat_panic_handler +end_vector_entry fiq_sp_el0 + +vector_entry serror_sp_el0 + b plat_panic_handler +end_vector_entry serror_sp_el0 + + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400. Only IRQs/FIQs + * are expected and handled + * ----------------------------------------------------- + */ +vector_entry sync_exception_sp_elx + b plat_panic_handler +end_vector_entry sync_exception_sp_elx + +vector_entry irq_sp_elx + handle_tsp_interrupt irq_sp_elx +end_vector_entry irq_sp_elx + +vector_entry fiq_sp_elx + handle_tsp_interrupt fiq_sp_elx +end_vector_entry fiq_sp_elx + +vector_entry serror_sp_elx + b plat_panic_handler +end_vector_entry serror_sp_elx + + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600. No exceptions + * are handled since TSP does not implement a lower EL + * ----------------------------------------------------- + */ +vector_entry sync_exception_aarch64 + b plat_panic_handler +end_vector_entry sync_exception_aarch64 + +vector_entry irq_aarch64 + b plat_panic_handler +end_vector_entry irq_aarch64 + +vector_entry fiq_aarch64 + b plat_panic_handler +end_vector_entry fiq_aarch64 + +vector_entry serror_aarch64 + b plat_panic_handler +end_vector_entry serror_aarch64 + + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800. No exceptions + * handled since the TSP does not implement a lower EL. + * ----------------------------------------------------- + */ +vector_entry sync_exception_aarch32 + b plat_panic_handler +end_vector_entry sync_exception_aarch32 + +vector_entry irq_aarch32 + b plat_panic_handler +end_vector_entry irq_aarch32 + +vector_entry fiq_aarch32 + b plat_panic_handler +end_vector_entry fiq_aarch32 + +vector_entry serror_aarch32 + b plat_panic_handler +end_vector_entry serror_aarch32 diff --git a/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S new file mode 100644 index 0000000..6e238ea --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl tsp_get_magic + +/* + * This function raises an SMC to retrieve arguments from secure + * monitor/dispatcher, saves the returned arguments the array received in x0, + * and then returns to the caller + */ +func tsp_get_magic + /* Load arguments */ + ldr w0, _tsp_fid_get_magic + + /* Raise SMC */ + smc #0 + + /* Return arguments in x1:x0 */ + ret +endfunc tsp_get_magic + + .align 2 +_tsp_fid_get_magic: + .word TSP_GET_ARGS diff --git a/arm-trusted-firmware/bl32/tsp/tsp.ld.S b/arm-trusted-firmware/bl32/tsp/tsp.ld.S new file mode 100644 index 0000000..d86ae55 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp.ld.S @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(tsp_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = TSP_SEC_MEM_BASE, LENGTH = TSP_SEC_MEM_SIZE +} + + +SECTIONS +{ + . = BL32_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "BL32_BASE address is not aligned on a page boundary.") + +#if SEPARATE_CODE_AND_RODATA + .text . : { + __TEXT_START__ = .; + *tsp_entrypoint.o(.text*) + *(.text*) + *(.vectors) + . = ALIGN(PAGE_SIZE); + __TEXT_END__ = .; + } >RAM + + .rodata . : { + __RODATA_START__ = .; + *(.rodata*) + + RODATA_COMMON + + . = ALIGN(PAGE_SIZE); + __RODATA_END__ = .; + } >RAM +#else + ro . : { + __RO_START__ = .; + *tsp_entrypoint.o(.text*) + *(.text*) + *(.rodata*) + + RODATA_COMMON + + *(.vectors) + + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as + * read-only, executable. No RW data from the next section must + * creep in. Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + RELA_SECTION >RAM + +#ifdef TSP_PROGBITS_LIMIT + ASSERT(. <= TSP_PROGBITS_LIMIT, "TSP progbits has exceeded its limit.") +#endif + + STACK_SECTION >RAM + BSS_SECTION >RAM + XLAT_TABLE_SECTION >RAM + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + *(tzfw_coherent_mem) + __COHERENT_RAM_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM +#endif + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __BL32_END__ = .; + + /DISCARD/ : { + *(.dynsym .dynstr .hash .gnu.hash) + } + + __BSS_SIZE__ = SIZEOF(.bss); +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= BL32_LIMIT, "BL32 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp.mk b/arm-trusted-firmware/bl32/tsp/tsp.mk new file mode 100644 index 0000000..3fd6d99 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp.mk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +INCLUDES += -Iinclude/bl32/tsp + +BL32_SOURCES += bl32/tsp/tsp_main.c \ + bl32/tsp/aarch64/tsp_entrypoint.S \ + bl32/tsp/aarch64/tsp_exceptions.S \ + bl32/tsp/aarch64/tsp_request.S \ + bl32/tsp/tsp_interrupt.c \ + bl32/tsp/tsp_timer.c \ + common/aarch64/early_exceptions.S \ + lib/locks/exclusive/aarch64/spinlock.S + +BL32_LINKERFILE := bl32/tsp/tsp.ld.S + +# This flag determines if the TSPD initializes BL32 in tspd_init() (synchronous +# method) or configures BL31 to pass control to BL32 instead of BL33 +# (asynchronous method). +TSP_INIT_ASYNC := 0 + +$(eval $(call assert_boolean,TSP_INIT_ASYNC)) +$(eval $(call add_define,TSP_INIT_ASYNC)) + +# Include the platform-specific TSP Makefile +# If no platform-specific TSP Makefile exists, it means TSP is not supported +# on this platform. +TSP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/tsp/tsp-${PLAT}.mk) +ifeq (,${TSP_PLAT_MAKEFILE}) + $(error TSP is not supported on platform ${PLAT}) +else + include ${TSP_PLAT_MAKEFILE} +endif diff --git a/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c b/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c new file mode 100644 index 0000000..430b5dd --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_interrupt.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2014-2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include + +#include "tsp_private.h" + +/******************************************************************************* + * This function updates the TSP statistics for S-EL1 interrupts handled + * synchronously i.e the ones that have been handed over by the TSPD. It also + * keeps count of the number of times control was passed back to the TSPD + * after handling the interrupt. In the future it will be possible that the + * TSPD hands over an S-EL1 interrupt to the TSP but does not expect it to + * return execution. This statistic will be useful to distinguish between these + * two models of synchronous S-EL1 interrupt handling. The 'elr_el3' parameter + * contains the address of the instruction in normal world where this S-EL1 + * interrupt was generated. + ******************************************************************************/ +void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3) +{ + uint32_t linear_id = plat_my_core_pos(); + + tsp_stats[linear_id].sync_sel1_intr_count++; + if (type == TSP_HANDLE_SEL1_INTR_AND_RETURN) + tsp_stats[linear_id].sync_sel1_intr_ret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx sync s-el1 interrupt request from 0x%" PRIx64 "\n", + read_mpidr(), elr_el3); + VERBOSE("TSP: cpu 0x%lx: %d sync s-el1 interrupt requests," + " %d sync s-el1 interrupt returns\n", + read_mpidr(), + tsp_stats[linear_id].sync_sel1_intr_count, + tsp_stats[linear_id].sync_sel1_intr_ret_count); + spin_unlock(&console_lock); +#endif +} + +/****************************************************************************** + * This function is invoked when a non S-EL1 interrupt is received and causes + * the preemption of TSP. This function returns TSP_PREEMPTED and results + * in the control being handed over to EL3 for handling the interrupt. + *****************************************************************************/ +int32_t tsp_handle_preemption(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + tsp_stats[linear_id].preempt_intr_count++; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx: %d preempt interrupt requests\n", + read_mpidr(), tsp_stats[linear_id].preempt_intr_count); + spin_unlock(&console_lock); +#endif + return TSP_PREEMPTED; +} + +/******************************************************************************* + * TSP interrupt handler is called as a part of both synchronous and + * asynchronous handling of TSP interrupts. Currently the physical timer + * interrupt is the only S-EL1 interrupt that this handler expects. It returns + * 0 upon successfully handling the expected interrupt and all other + * interrupts are treated as normal world or EL3 interrupts. + ******************************************************************************/ +int32_t tsp_common_int_handler(void) +{ + uint32_t linear_id = plat_my_core_pos(), id; + + /* + * Get the highest priority pending interrupt id and see if it is the + * secure physical generic timer interrupt in which case, handle it. + * Otherwise throw this interrupt at the EL3 firmware. + * + * There is a small time window between reading the highest priority + * pending interrupt and acknowledging it during which another + * interrupt of higher priority could become the highest pending + * interrupt. This is not expected to happen currently for TSP. + */ + id = plat_ic_get_pending_interrupt_id(); + + /* TSP can only handle the secure physical timer interrupt */ + if (id != TSP_IRQ_SEC_PHY_TIMER) + return tsp_handle_preemption(); + + /* + * Acknowledge and handle the secure timer interrupt. Also sanity check + * if it has been preempted by another interrupt through an assertion. + */ + id = plat_ic_acknowledge_interrupt(); + assert(id == TSP_IRQ_SEC_PHY_TIMER); + tsp_generic_timer_handler(); + plat_ic_end_of_interrupt(id); + + /* Update the statistics and print some messages */ + tsp_stats[linear_id].sel1_intr_count++; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + spin_lock(&console_lock); + VERBOSE("TSP: cpu 0x%lx handled S-EL1 interrupt %d\n", + read_mpidr(), id); + VERBOSE("TSP: cpu 0x%lx: %d S-EL1 requests\n", + read_mpidr(), tsp_stats[linear_id].sel1_intr_count); + spin_unlock(&console_lock); +#endif + return 0; +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp_main.c b/arm-trusted-firmware/bl32/tsp/tsp_main.c new file mode 100644 index 0000000..522c1b4 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_main.c @@ -0,0 +1,471 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tsp_private.h" + + +/******************************************************************************* + * Lock to control access to the console + ******************************************************************************/ +spinlock_t console_lock; + +/******************************************************************************* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + ******************************************************************************/ +static tsp_args_t tsp_smc_args[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Per cpu data structure to keep track of TSP activity + ******************************************************************************/ +work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * The TSP memory footprint starts at address BL32_BASE and ends with the + * linker symbol __BL32_END__. Use these addresses to compute the TSP image + * size. + ******************************************************************************/ +#define BL32_TOTAL_LIMIT BL32_END +#define BL32_TOTAL_SIZE (BL32_TOTAL_LIMIT - (unsigned long) BL32_BASE) + +static tsp_args_t *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id; + tsp_args_t *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = plat_my_core_pos(); + pcpu_smc_args = &tsp_smc_args[linear_id]; + write_sp_arg(pcpu_smc_args, TSP_ARG0, arg0); + write_sp_arg(pcpu_smc_args, TSP_ARG1, arg1); + write_sp_arg(pcpu_smc_args, TSP_ARG2, arg2); + write_sp_arg(pcpu_smc_args, TSP_ARG3, arg3); + write_sp_arg(pcpu_smc_args, TSP_ARG4, arg4); + write_sp_arg(pcpu_smc_args, TSP_ARG5, arg5); + write_sp_arg(pcpu_smc_args, TSP_ARG6, arg6); + write_sp_arg(pcpu_smc_args, TSP_ARG7, arg7); + + return pcpu_smc_args; +} + +/******************************************************************************* + * Setup function for TSP. + ******************************************************************************/ +void tsp_setup(void) +{ + /* Perform early platform-specific setup */ + tsp_early_platform_setup(); + + /* Perform late platform-specific setup */ + tsp_plat_arch_setup(); + +#if ENABLE_PAUTH + /* + * Assert that the ARMv8.3-PAuth registers are present or an access + * fault will be triggered when they are being saved or restored. + */ + assert(is_armv8_3_pauth_present()); +#endif /* ENABLE_PAUTH */ +} + +/******************************************************************************* + * TSP main entry point where it gets the opportunity to initialize its secure + * state/applications. Once the state is initialized, it must return to the + * SPD with a pointer to the 'tsp_vector_table' jump table. + ******************************************************************************/ +uint64_t tsp_main(void) +{ + NOTICE("TSP: %s\n", version_string); + NOTICE("TSP: %s\n", build_message); + INFO("TSP: Total memory base : 0x%lx\n", (unsigned long) BL32_BASE); + INFO("TSP: Total memory size : 0x%lx bytes\n", BL32_TOTAL_SIZE); + + uint32_t linear_id = plat_my_core_pos(); + + /* Initialize the platform */ + tsp_platform_setup(); + + /* Initialize secure/applications state here */ + tsp_generic_timer_start(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); +#endif + return (uint64_t) &tsp_vector_table; +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * after this cpu's architectural state has been setup in response to an earlier + * psci cpu_on request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_on_main(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Initialize secure/applications state here */ + tsp_generic_timer_start(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_on_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx turned on\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu on requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_on_count); + spin_unlock(&console_lock); +#endif + /* Indicate to the SPD that we have completed turned ourselves on */ + return set_smc_args(TSP_ON_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining book keeping in the test secure payload + * before this cpu is turned off in response to a psci cpu_off request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* + * This cpu is being turned off, so disable the timer to prevent the + * secure timer interrupt from interfering with power down. A pending + * interrupt will be lost but we do not care as we are turning off. + */ + tsp_generic_timer_stop(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_off_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx off request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu off requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_off_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload before + * this cpu's architectural state is saved in response to an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* + * Save the time context and disable it to prevent the secure timer + * interrupt from interfering with wakeup from the suspend state. + */ + tsp_generic_timer_save(); + tsp_generic_timer_stop(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_suspend_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu suspend requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_suspend_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SUSPEND_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any book keeping in the test secure payload after this + * cpu's architectural state has been restored after wakeup from an earlier psci + * cpu_suspend request. + ******************************************************************************/ +tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Restore the generic timer context */ + tsp_generic_timer_restore(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + tsp_stats[linear_id].cpu_resume_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx resumed. maximum off power level %" PRId64 "\n", + read_mpidr(), max_off_pwrlvl); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets %d cpu resume requests\n", + read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count, + tsp_stats[linear_id].cpu_resume_count); + spin_unlock(&console_lock); +#endif + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_RESUME_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining bookkeeping in the test secure payload + * before the system is switched off (in response to a psci SYSTEM_OFF request) + ******************************************************************************/ +tsp_args_t *tsp_system_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx SYSTEM_OFF request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SYSTEM_OFF_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * This function performs any remaining bookkeeping in the test secure payload + * before the system is reset (in response to a psci SYSTEM_RESET request) + ******************************************************************************/ +tsp_args_t *tsp_system_reset_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id = plat_my_core_pos(); + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx SYSTEM_RESET request\n", read_mpidr()); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets requests\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Indicate to the SPD that we have completed this request */ + return set_smc_args(TSP_SYSTEM_RESET_DONE, 0, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * TSP fast smc handler. The secure monitor jumps to this function by + * doing the ERET after populating X0-X7 registers. The arguments are received + * in the function arguments in order. Once the service is rendered, this + * function returns to Secure Monitor by raising SMC. + ******************************************************************************/ +tsp_args_t *tsp_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint128_t service_args; + uint64_t service_arg0; + uint64_t service_arg1; + uint64_t results[2]; + uint32_t linear_id = plat_my_core_pos(); + u_register_t dit; + + /* Update this cpu's statistics */ + tsp_stats[linear_id].smc_count++; + tsp_stats[linear_id].eret_count++; + +#if LOG_LEVEL >= LOG_LEVEL_INFO + spin_lock(&console_lock); + INFO("TSP: cpu 0x%lx received %s smc 0x%" PRIx64 "\n", read_mpidr(), + ((func >> 31) & 1) == 1 ? "fast" : "yielding", + func); + INFO("TSP: cpu 0x%lx: %d smcs, %d erets\n", read_mpidr(), + tsp_stats[linear_id].smc_count, + tsp_stats[linear_id].eret_count); + spin_unlock(&console_lock); +#endif + + /* Render secure services and obtain results here */ + results[0] = arg1; + results[1] = arg2; + + /* + * Request a service back from dispatcher/secure monitor. + * This call returns and thereafter resumes execution. + */ + service_args = tsp_get_magic(); + service_arg0 = (uint64_t)service_args; + service_arg1 = (uint64_t)(service_args >> 64U); + +#if CTX_INCLUDE_MTE_REGS + /* + * Write a dummy value to an MTE register, to simulate usage in the + * secure world + */ + write_gcr_el1(0x99); +#endif + + /* Determine the function to perform based on the function ID */ + switch (TSP_BARE_FID(func)) { + case TSP_ADD: + results[0] += service_arg0; + results[1] += service_arg1; + break; + case TSP_SUB: + results[0] -= service_arg0; + results[1] -= service_arg1; + break; + case TSP_MUL: + results[0] *= service_arg0; + results[1] *= service_arg1; + break; + case TSP_DIV: + results[0] /= service_arg0 ? service_arg0 : 1; + results[1] /= service_arg1 ? service_arg1 : 1; + break; + case TSP_CHECK_DIT: + if (!is_armv8_4_dit_present()) { +#if LOG_LEVEL >= LOG_LEVEL_ERROR + spin_lock(&console_lock); + ERROR("DIT not supported\n"); + spin_unlock(&console_lock); +#endif + results[0] = 0; + results[1] = 0xffff; + break; + } + dit = read_dit(); + results[0] = dit == service_arg0; + results[1] = dit; + /* Toggle the dit bit */ + write_dit(service_arg0 != 0U ? 0 : DIT_BIT); + break; + default: + break; + } + + return set_smc_args(func, 0, + results[0], + results[1], + 0, 0, 0, 0); +} + +/******************************************************************************* + * TSP smc abort handler. This function is called when aborting a preempted + * yielding SMC request. It should cleanup all resources owned by the SMC + * handler such as locks or dynamically allocated memory so following SMC + * request are executed in a clean environment. + ******************************************************************************/ +tsp_args_t *tsp_abort_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + return set_smc_args(TSP_ABORT_DONE, 0, 0, 0, 0, 0, 0, 0); +} diff --git a/arm-trusted-firmware/bl32/tsp/tsp_private.h b/arm-trusted-firmware/bl32/tsp/tsp_private.h new file mode 100644 index 0000000..38d9732 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_private.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSP_PRIVATE_H +#define TSP_PRIVATE_H + +/* Definitions to help the assembler access the SMC/ERET args structure */ +#define TSP_ARGS_SIZE 0x40 +#define TSP_ARG0 0x0 +#define TSP_ARG1 0x8 +#define TSP_ARG2 0x10 +#define TSP_ARG3 0x18 +#define TSP_ARG4 0x20 +#define TSP_ARG5 0x28 +#define TSP_ARG6 0x30 +#define TSP_ARG7 0x38 +#define TSP_ARGS_END 0x40 + + +#ifndef __ASSEMBLER__ + +#include + +#include /* For CACHE_WRITEBACK_GRANULE */ + +#include +#include +#include + +typedef struct work_statistics { + /* Number of s-el1 interrupts on this cpu */ + uint32_t sel1_intr_count; + /* Number of non s-el1 interrupts on this cpu which preempted TSP */ + uint32_t preempt_intr_count; + /* Number of sync s-el1 interrupts on this cpu */ + uint32_t sync_sel1_intr_count; + /* Number of s-el1 interrupts returns on this cpu */ + uint32_t sync_sel1_intr_ret_count; + uint32_t smc_count; /* Number of returns on this cpu */ + uint32_t eret_count; /* Number of entries on this cpu */ + uint32_t cpu_on_count; /* Number of cpu on requests */ + uint32_t cpu_off_count; /* Number of cpu off requests */ + uint32_t cpu_suspend_count; /* Number of cpu suspend requests */ + uint32_t cpu_resume_count; /* Number of cpu resume requests */ +} __aligned(CACHE_WRITEBACK_GRANULE) work_statistics_t; + +typedef struct tsp_args { + uint64_t _regs[TSP_ARGS_END >> 3]; +} __aligned(CACHE_WRITEBACK_GRANULE) tsp_args_t; + +/* Macros to access members of the above structure using their offsets */ +#define read_sp_arg(args, offset) ((args)->_regs[offset >> 3]) +#define write_sp_arg(args, offset, val) (((args)->_regs[offset >> 3]) \ + = val) +/* + * Ensure that the assembler's view of the size of the tsp_args is the + * same as the compilers + */ +CASSERT(TSP_ARGS_SIZE == sizeof(tsp_args_t), assert_sp_args_size_mismatch); + +uint128_t tsp_get_magic(void); + +tsp_args_t *tsp_cpu_resume_main(uint64_t max_off_pwrlvl, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); +tsp_args_t *tsp_cpu_suspend_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); +tsp_args_t *tsp_cpu_on_main(void); +tsp_args_t *tsp_cpu_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +/* Generic Timer functions */ +void tsp_generic_timer_start(void); +void tsp_generic_timer_handler(void); +void tsp_generic_timer_stop(void); +void tsp_generic_timer_save(void); +void tsp_generic_timer_restore(void); + +/* S-EL1 interrupt management functions */ +void tsp_update_sync_sel1_intr_stats(uint32_t type, uint64_t elr_el3); + + +/* Data structure to keep track of TSP statistics */ +extern spinlock_t console_lock; +extern work_statistics_t tsp_stats[PLATFORM_CORE_COUNT]; + +/* Vector table of jumps */ +extern tsp_vectors_t tsp_vector_table; + +/* functions */ +int32_t tsp_common_int_handler(void); +int32_t tsp_handle_preemption(void); + +tsp_args_t *tsp_abort_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_smc_handler(uint64_t func, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_system_reset_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +tsp_args_t *tsp_system_off_main(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7); + +uint64_t tsp_main(void); +#endif /* __ASSEMBLER__ */ + +#endif /* TSP_PRIVATE_H */ diff --git a/arm-trusted-firmware/bl32/tsp/tsp_timer.c b/arm-trusted-firmware/bl32/tsp/tsp_timer.c new file mode 100644 index 0000000..d1ff2b0 --- /dev/null +++ b/arm-trusted-firmware/bl32/tsp/tsp_timer.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "tsp_private.h" + +/******************************************************************************* + * Data structure to keep track of per-cpu secure generic timer context across + * power management operations. + ******************************************************************************/ +typedef struct timer_context { + uint64_t cval; + uint32_t ctl; +} timer_context_t; + +static timer_context_t pcpu_timer_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * This function initializes the generic timer to fire every 0.5 second + ******************************************************************************/ +void tsp_generic_timer_start(void) +{ + uint64_t cval; + uint32_t ctl = 0; + + /* The timer will fire every 0.5 second */ + cval = read_cntpct_el0() + (read_cntfrq_el0() >> 1); + write_cntps_cval_el1(cval); + + /* Enable the secure physical timer */ + set_cntp_ctl_enable(ctl); + write_cntps_ctl_el1(ctl); +} + +/******************************************************************************* + * This function deasserts the timer interrupt and sets it up again + ******************************************************************************/ +void tsp_generic_timer_handler(void) +{ + /* Ensure that the timer did assert the interrupt */ + assert(get_cntp_ctl_istatus(read_cntps_ctl_el1())); + + /* + * Disable the timer and reprogram it. The barriers ensure that there is + * no reordering of instructions around the reprogramming code. + */ + isb(); + write_cntps_ctl_el1(0); + tsp_generic_timer_start(); + isb(); +} + +/******************************************************************************* + * This function deasserts the timer interrupt prior to cpu power down + ******************************************************************************/ +void tsp_generic_timer_stop(void) +{ + /* Disable the timer */ + write_cntps_ctl_el1(0); +} + +/******************************************************************************* + * This function saves the timer context prior to cpu suspension + ******************************************************************************/ +void tsp_generic_timer_save(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + pcpu_timer_context[linear_id].cval = read_cntps_cval_el1(); + pcpu_timer_context[linear_id].ctl = read_cntps_ctl_el1(); + flush_dcache_range((uint64_t) &pcpu_timer_context[linear_id], + sizeof(pcpu_timer_context[linear_id])); +} + +/******************************************************************************* + * This function restores the timer context post cpu resumption + ******************************************************************************/ +void tsp_generic_timer_restore(void) +{ + uint32_t linear_id = plat_my_core_pos(); + + write_cntps_cval_el1(pcpu_timer_context[linear_id].cval); + write_cntps_ctl_el1(pcpu_timer_context[linear_id].ctl); +} diff --git a/arm-trusted-firmware/changelog.yaml b/arm-trusted-firmware/changelog.yaml new file mode 100644 index 0000000..939fb65 --- /dev/null +++ b/arm-trusted-firmware/changelog.yaml @@ -0,0 +1,1017 @@ +# +# Copyright (c) 2021-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# +# The following block describes the top-level sections of the changelog. Commits are categorized +# into these top-level sections based on the commit message "type": +# +# feat(xyz): add the xyz feature +# ^^^^ +# + +sections: + - title: New Features + description: A new feature + type: feat + + - title: Resolved Issues + description: A bug fix + type: fix + + - title: Build System + description: Changes that affect the build system or external dependencies + type: build + hidden: true + + - title: Continuous Integration + description: Changes to our CI configuration files and scripts + type: ci + hidden: true + + - title: Build System + description: Documentation-only changes + type: docs + hidden: true + + - title: Performance Improvements + description: A code change that improves performance + type: perf + hidden: true + + - title: Code Refactoring + description: A code change that neither fixes a bug nor adds a feature + type: refactor + hidden: true + + - title: Reverted Changes + description: Changes that revert a previous change + type: revert + hidden: true + + - title: Style + description: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc.) + type: style + hidden: true + + - title: Tests + description: Adding missing tests or correcting existing tests + type: test + hidden: true + + - title: Miscellaneous + description: Any other change + type: chore + hidden: true + +# +# The following block describes the sub-sections of the changelog. These sub-sections may appear in +# any of the top-level sections, and describe the individual components that a change may relate to. +# +# Sub-sections have an optional associated commit message "scope": +# +# feat(xyz): add the xyz feature +# ^^^ +# +# This file also describes deprecated scopes, which are scopes that were used before we introduced +# scope enforcement. These will not pass CI checks when used, but they will be used to generate the +# changelog. +# +# Please note that new scopes should be kebab-case: https://en.wiktionary.org/wiki/kebab_case +# + +subsections: + - title: Architecture + + subsections: + - title: Activity Monitors Extension (FEAT_AMU) + scope: amu + + - title: Support for the `HCRX_EL2` register (FEAT_HCX) + scope: hcx + + - title: Memory Partitioning and Monitoring (MPAM) Extension (FEAT_MPAM) + scope: mpam + + - title: Scalable Matrix Extension (FEAT_SME) + scope: sme + + - title: Scalable Vector Extension (FEAT_SVE) + scope: sve + + - title: System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1) + scope: sys-reg-trace + + deprecated: + - sys_reg_trace + + - title: Trace Buffer Extension (FEAT_TRBE) + scope: trbe + + - title: Self-hosted Trace Extensions (FEAT_TRF) + scope: trf + + - title: Statistical profiling Extension (FEAT_SPE) + scope: spe + + - title: Platforms + + subsections: + - title: Allwinner + scope: allwinner + + deprecated: + - plat/allwinner + + - title: Arm + scope: arm + + deprecated: + - plat/arm + + subsections: + - title: FPGA + scope: fpga + + deprecated: + - arm_fgpa + - arm_fpga + - plat/arm_fpga + + - title: FVP + scope: fvp + + deprecated: + - plat/fvp + + - title: FVP-R + scope: fvp-r + + deprecated: + - fvp_r + + - title: Juno + scope: juno + + - title: Morello + scope: morello + + - title: RD + scope: rd + + subsections: + - title: RD-N2 + scope: rdn2 + + deprecated: + - board/rdn2 + + - title: SGI + scope: sgi + + deprecated: + - plat/sgi + - plat/arm/sgi + + - title: TC + scope: tc + + subsections: + - title: TC0 + scope: tc0 + + deprecated: + - plat/tc0 + + - title: Intel + scope: intel + + subsections: + - title: SoC + scope: soc + + - title: Marvell + scope: marvell + + deprecated: + - plat/marvell + + subsections: + - title: Armada + scope: armada + + deprecated: + - plat/marvell/armada + + subsections: + - title: A3K + scope: a3k + + deprecated: + - plat/marvell/a3k + + - title: A8K + scope: a8k + + deprecated: + - plat/marvell/a8k + + - title: MediaTek + scope: mediatek + + deprecated: + - plat/mediatek/common + - plat/mediatek + + subsections: + - title: MT8183 + scope: mt8183 + + deprecated: + - plat/mediatek/mt8183 + + - title: MT8192 + scope: mt8192 + + deprecated: + - plat/mdeiatek/mt8192 + + - title: MT8195 + scope: mt8195 + + deprecated: + - plat/mediatek/me8195 + - plat/mediatek/mt8195 + - plat/mdeiatek/mt8195 + + - title: NVIDIA + scope: nvidia + + subsections: + - title: Tegra + scope: tegra + + deprecated: + - plat/tegra + + subsections: + - title: Tegra 132 + scope: tegra132 + + - title: NXP + scope: nxp + + deprecated: + - plat/nxp + - plat/nxp/common + + subsections: + - title: i.MX + scope: imx + + deprecated: + - plat/imx + - plat/imx/imx + + subsections: + - title: i.MX 8M + scope: imx8m + + deprecated: + - plat/imx8m + - plat/imx/imx8m + + subsections: + - title: i.MX 8M Mini + scope: imx8mm + + deprecated: + - plat/imx/imx8m/imx8mm + + - title: i.MX 8M Plus + scope: imx8mp + + deprecated: + - plat/imx/imx8m/imx8mp + + - title: Layerscape + scope: layerscape + + deprecated: + - docs/nxp/layerscape + + subsections: + - title: LS1028A + scope: ls1028a + + deprecated: + - plat/nxp/ls1028a + + subsections: + - title: LS1028ARDB + scope: ls1028ardb + + deprecated: + - plat/nxp/ls1028ardb + + - title: LX2 + scope: lx2 + + deprecated: + - plat/nxp/lx2 + + subsections: + - title: LX216 + scope: lx216 + + deprecated: + - plat/nxp/lx216x + + subsections: + - title: LX2160 + scope: lx2160 + + deprecated: + - plat/soc-lx2160 + + - title: LS1046A + scope: ls1046a + + subsections: + - title: LS1046ARDB + scope: ls1046ardb + + - title: LS1046AFRWY + scope: ls1046afrwy + + - title: LS1046AQDS + scope: ls1046aqds + + - title: LS1088A + scope: ls1088a + + subsections: + - title: LS1088ARDB + scope: ls1088ardb + + - title: LS1088AQDS + scope: ls1088aqds + + - title: QEMU + scope: qemu + + deprecated: + - plat/qemu + + - title: QTI + scope: qti + + subsections: + - title: SC1780 + scope: sc7180 + + deprecated: + - plat/qti/sc7180 + + - title: SC7280 + scope: sc7280 + + deprecated: + - plat/qti/sc7280 + + - title: MSM8916 + scope: msm8916 + + - title: Raspberry Pi + scope: rpi + + subsections: + - title: Raspberry Pi 4 + scope: rpi4 + + - title: Renesas + scope: renesas + + subsections: + - title: R-Car + scope: rcar + + deprecated: + - plat/rcar + + subsections: + - title: R-Car 3 + scope: rcar3 + + deprecated: + - plat/rcar3 + + - title: Rockchip + scope: rockchip + + subsections: + - title: RK3399 + scope: rk3399 + + deprecated: + - rockchip/rk3399 + - rk3399/suspend + + - title: Socionext + scope: socionext + + subsections: + - title: Synquacer + scope: synquacer + + deprecated: + - plat/synquacer + + - title: ST + scope: st + + deprecated: + - plat/st + + subsections: + - title: ST32MP1 + scope: stm32mp1 + + deprecated: + - plat/st/stm32mp1 + + - title: Xilinx + scope: xilinx + + deprecated: + - plat/xilinx + + subsections: + - title: Versal + scope: versal + + deprecated: + - plat/xilinx/versal/include + - plat/xilinx/versal + - plat/versal + + - title: ZynqMP + scope: zynqmp + + deprecated: + - plat/zynqmp + - plat/xilinx/zynqmp + + - title: Bootloader Images + scope: bl + + deprecated: + - bl_common + + subsections: + - title: BL1 + scope: bl1 + + - title: BL2 + scope: bl2 + + - title: Services + scope: services + + subsections: + - title: FF-A + scope: ff-a + + deprecated: + - ffa + + - title: RME + scope: rme + + - title: SPM + scope: spm + + deprecated: + - spmc + - spmd + - SPMD + + - title: SPM MM + scope: spm-mm + + - title: Libraries + + subsections: + - title: CPU Support + scope: cpus + + deprecated: + - cpu + - errata + - errata_report + + - title: EL3 Runtime + scope: el3-runtime + + deprecated: + - el3_runtime + + - title: FCONF + scope: fconf + + - title: MPMM + scope: mpmm + + - title: OP-TEE + scope: optee + + deprecated: + - lib/optee + + - title: PSCI + scope: psci + + - title: GPT + scope: gpt + + deprecated: + - gpt_rme + + - title: SMCCC + scope: smccc + + - title: Translation Tables + scope: xlat + + - title: Drivers + + subsections: + - title: Authentication + scope: auth + + deprecated: + - driver/auth + + subsections: + - title: CryptoCell-713 + scope: cc-713 + + - title: FWU + scope: fwu + + deprecated: + - fwu_metadata + + - title: I/O + scope: io + + subsections: + - title: MTD + scope: mtd + + deprecated: + - io_mtd + + - title: Measured Boot + scope: measured-boot + + deprecated: + - measured boot + - measured_boot + + - title: MMC + scope: mmc + + deprecated: + - drivers/mmc + + - title: MTD + scope: mtd + + deprecated: + - drivers/mtd + + subsections: + - title: NAND + scope: nand + + subsections: + - title: SPI NAND + scope: spi-nand + + deprecated: + - spi_nand + + - title: Partition + scope: partition + + - title: SCMI + scope: scmi + + deprecated: + - scmi_common + - drivers/scmi-msg + + - title: UFS + scope: ufs + + - title: Arm + scope: arm-drivers + + subsections: + - title: Ethos-N + scope: ethos-n + + deprecated: + - drivers/arm/ethosn + + - title: GIC + scope: gic + + subsections: + - title: GICv3 + scope: gicv3 + + subsections: + - title: GIC-600AE + scope: gic600ae + + - title: TZC + scope: tzc + + subsections: + - title: TZC-400 + scope: tzc400 + + deprecated: + - drivers/tzc400 + + - title: Marvell + scope: marvell-drivers + + subsections: + - title: COMPHY + scope: marvell-comphy + + deprecated: + - drivers/marvell/comphy + + subsections: + - title: Armada 3700 + scope: marvell-comphy-3700 + + deprecated: + - drivers/marvell/comphy-3700 + + - title: CP110 + scope: marvell-comphy-cp110 + + deprecated: + - drivers/marvell/comphy-cp110 + + - title: UART + scope: marvell-uart + + deprecated: + - plat/marvell/uart + + - title: Armada + scope: armada-drivers + + subsections: + - title: A3K + scope: a3k-drivers + + subsections: + - title: A3720 + scope: a3720-uart + + deprecated: + - plat/marvell/a3720/uart + + - title: MediaTek + scope: mediatek-drivers + + subsections: + - title: APU + scope: mediatek-apu + + deprecated: + - plat/mediatek/apu + + - title: EMI MPU + scope: mediatek-emi-mpu + + deprecated: + - plat/mediatek/mpu + + - title: PMIC Wrapper + scope: mediatek-pmic-wrapper + + deprecated: + - plat/mediatek/pmic_wrap + + - title: MT8192 + scope: mt8192-drivers + + subsections: + - title: SPM + scope: mt8192-spm + + deprecated: + - mediatek/mt8192/spm + + - title: NXP + scope: nxp-drivers + + subsections: + - title: DCFG + scope: nxp-dcfg + + deprecated: + - driver/nxp/dcfg + + - title: FLEXSPI + scope: flexspi + + deprecated: + - include/drivers/flexspi + - driver/nxp/xspi + + - title: SCFG + scope: nxp-scfg + + deprecated: + - nxp/scfg + + - title: SFP + scope: nxp-sfp + + deprecated: + - drivers/nxp/sfp + + - title: QSPI + scope: nxp-qspi + + - title: NXP Crypto + scope: nxp-crypto + + - title: DDR + scope: nxp-ddr + + - title: GIC + scope: nxp-gic + + - title: Renesas + scope: renesas-drivers + + subsections: + - title: R-Car3 + scope: rcar3-drivers + + deprecated: + - drivers/rcar3 + + - title: ST + scope: st-drivers + + deprecated: + - drivers/st + + subsections: + - title: BSEC + scope: st-bsec + + - title: Clock + scope: st-clock + + deprecated: + - stm32mp_clk + - drivers/st/clk + - stm32mp1_clk + + - title: Crypto + scope: st-crypto + + - title: DDR + scope: st-ddr + + - title: I/O + scope: st-io-drivers + + subsections: + - title: STM32 Image + scope: st-io-stm32image + + deprecated: + - io-stm32image + - io_stm32image + + - title: fiptool + scope: fiptool + + - title: I2C + scope: st-i2c + + - title: FMC + scope: st-fmc + + - title: GPIO + scope: st-gpio + + - title: SDMMC2 + scope: st-sdmmc2 + + deprecated: + - stm32_sdmmc2 + + - title: ST PMIC + scope: st-pmic + + deprecated: + - drivers/st/pmic + + - title: STPMIC1 + scope: stpmic1 + + - title: Regulator + scope: st-regulator + + - title: Reset + scope: st-reset + + - title: SPI + scope: st-spi + + - title: UART + scope: st-uart + + subsections: + - title: STM32 Console + scope: stm32-console + + deprecated: + - stm32_console + + - title: USB + scope: st-usb + + deprecated: + - drivers/st/usb + + - title: Watchdog + scope: st-iwdg + + - title: USB + scope: usb + + deprecated: + - drivers/usb + + - title: Miscellaneous + + subsections: + - title: AArch64 + scope: aarch64 + + - title: Debug + scope: debug + + deprecated: + - common/debug + + - title: CRC32 + scope: crc32 + + subsections: + - title: Hardware CRC32 + scope: hw-crc32 + + deprecated: + - hw_crc + - hw_crc32 + + - title: Software CRC32 + scope: sw-crc32 + + deprecated: + - sw_crc32 + + - title: DT Bindings + scope: dt-bindings + + - title: FDT Wrappers + scope: fdt-wrappers + + - title: FDTs + scope: fdts + + deprecated: + - fdt + + subsections: + - title: Morello + scope: morello-fdts + + deprecated: + - fdts/morello + + - title: STM32MP1 + scope: stm32mp1-fdts + + deprecated: + - fdts stm32mp1 + + - title: PIE + scope: pie + + - title: Security + scope: security + + - title: SDEI + scope: sdei + + - title: TBBR + scope: tbbr + + - title: NXP + + subsections: + - title: OCRAM + scope: nxp-ocram + + deprecated: + - nxp/common/ocram + + - title: PSCI + scope: nxp-psci + + deprecated: + - plat/nxp/common/psci + + - title: Documentation + scope: docs + + deprecated: + - doc + + subsections: + - title: Changelog + scope: changelog + + - title: Commit Style + scope: commit-style + + - title: Contribution Guidelines + scope: contributing + + deprecated: + - contribution-guidelines + - docs-contributing.rst + + - title: Maintainers + scope: maintainers + + - title: Prerequisites + scope: prerequisites + + - title: Build System + scope: build + + deprecated: + - makefile + - Makefile + + subsections: + - title: Git Hooks + scope: hooks + + - title: Tools + + subsections: + - title: STM32 Image + scope: stm32image + + deprecated: + - tools/stm32image + + - title: NXP Tools + scope: nxp-tools + + - title: Dependencies + scope: deps + + subsections: + - title: checkpatch + scope: checkpatch + + - title: commitlint + scope: commitlint + + - title: libfdt + scope: libfdt + + - title: Node Package Manager (NPM) + scope: npm diff --git a/arm-trusted-firmware/common/aarch32/debug.S b/arm-trusted-firmware/common/aarch32/debug.S new file mode 100644 index 0000000..9d410df --- /dev/null +++ b/arm-trusted-firmware/common/aarch32/debug.S @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl asm_print_str + .globl asm_print_hex + .globl asm_print_hex_bits + .globl asm_assert + .globl do_panic + .globl report_exception + +/* Since the max decimal input number is 65536 */ +#define MAX_DEC_DIVISOR 10000 +/* The offset to add to get ascii for numerals '0 - 9' */ +#define ASCII_OFFSET_NUM '0' + +#if ENABLE_ASSERTIONS +.section .rodata.assert_str, "aS" +assert_msg1: + .asciz "ASSERT: File " +assert_msg2: +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + .asciz " Line 0x" +#else + .asciz " Line " + + /* + * This macro is intended to be used to print the + * line number in decimal. Used by asm_assert macro. + * The max number expected is 65536. + * In: r4 = the decimal to print. + * Clobber: lr, r0, r1, r2, r5, r6 + */ + .macro asm_print_line_dec + mov r6, #10 /* Divide by 10 after every loop iteration */ + ldr r5, =MAX_DEC_DIVISOR +dec_print_loop: + udiv r0, r4, r5 /* Get the quotient */ + mls r4, r0, r5, r4 /* Find the remainder */ + add r0, r0, #ASCII_OFFSET_NUM /* Convert to ascii */ + bl plat_crash_console_putc + udiv r5, r5, r6 /* Reduce divisor */ + cmp r5, #0 + bne dec_print_loop + .endm +#endif + +/* --------------------------------------------------------------------------- + * Assertion support in assembly. + * The below function helps to support assertions in assembly where we do not + * have a C runtime stack. Arguments to the function are : + * r0 - File name + * r1 - Line no + * Clobber list : lr, r0 - r6 + * --------------------------------------------------------------------------- + */ +func asm_assert +#if LOG_LEVEL >= LOG_LEVEL_INFO + /* + * Only print the output if LOG_LEVEL is higher or equal to + * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. + */ + /* Stash the parameters already in r0 and r1 */ + mov r5, r0 + mov r6, r1 + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cmp r0, #0 + beq _assert_loop + + /* The console is initialized */ + ldr r4, =assert_msg1 + bl asm_print_str + mov r4, r5 + bl asm_print_str + ldr r4, =assert_msg2 + bl asm_print_str + + /* Check if line number higher than max permitted */ + ldr r4, =~0xffff + tst r6, r4 + bne _assert_loop + mov r4, r6 + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /****************************************************************** + * Virtualization comes with the UDIV/SDIV instructions. If missing + * write file line number in hexadecimal format. + ******************************************************************/ + bl asm_print_hex +#else + asm_print_line_dec +#endif + bl plat_crash_console_flush +_assert_loop: +#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */ + no_ret plat_panic_handler +endfunc asm_assert +#endif /* ENABLE_ASSERTIONS */ + +/* + * This function prints a string from address in r4 + * Clobber: lr, r0 - r4 + */ +func asm_print_str + mov r3, lr +1: + ldrb r0, [r4], #0x1 + cmp r0, #0 + beq 2f + bl plat_crash_console_putc + b 1b +2: + bx r3 +endfunc asm_print_str + +/* + * This function prints a hexadecimal number in r4. + * In: r4 = the hexadecimal to print. + * Clobber: lr, r0 - r3, r5 + */ +func asm_print_hex + mov r5, #32 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in r5 */ +asm_print_hex_bits: + mov r3, lr +1: + sub r5, r5, #4 + lsr r0, r4, r5 + and r0, r0, #0xf + cmp r0, #0xa + blo 2f + /* Add by 0x27 in addition to ASCII_OFFSET_NUM + * to get ascii for characters 'a - f'. + */ + add r0, r0, #0x27 +2: + add r0, r0, #ASCII_OFFSET_NUM + bl plat_crash_console_putc + cmp r5, #0 + bne 1b + bx r3 +endfunc asm_print_hex + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + panic_end: .asciz "\r\n" + +func do_panic + /* Have LR copy point to PC at the time of panic */ + sub r6, lr, #4 + + /* Initialize crash console and verify success */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cmp r0, #0 + beq _panic_handler + + /* The console is initialized */ + ldr r4, =panic_msg + bl asm_print_str + + /* Print LR in hex */ + mov r4, r6 + bl asm_print_hex + + /* Print new line */ + ldr r4, =panic_end + bl asm_print_str + + bl plat_crash_console_flush + +_panic_handler: + mov lr, r6 + b plat_panic_handler +endfunc do_panic + + /*********************************************************** + * This function is called from the vector table for + * unhandled exceptions. It reads the current mode and + * passes it to platform. + ***********************************************************/ +func report_exception + mrs r0, cpsr + and r0, #MODE32_MASK + bl plat_report_exception + no_ret plat_panic_handler +endfunc report_exception diff --git a/arm-trusted-firmware/common/aarch64/debug.S b/arm-trusted-firmware/common/aarch64/debug.S new file mode 100644 index 0000000..d105d08 --- /dev/null +++ b/arm-trusted-firmware/common/aarch64/debug.S @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl asm_print_str + .globl asm_print_hex + .globl asm_print_hex_bits + .globl asm_print_newline + .globl asm_assert + .globl do_panic + +/* Since the max decimal input number is 65536 */ +#define MAX_DEC_DIVISOR 10000 +/* The offset to add to get ascii for numerals '0 - 9' */ +#define ASCII_OFFSET_NUM 0x30 + +#if ENABLE_ASSERTIONS +.section .rodata.assert_str, "aS" +assert_msg1: + .asciz "ASSERT: File " +assert_msg2: + .asciz " Line " + + /* + * This macro is intended to be used to print the + * line number in decimal. Used by asm_assert macro. + * The max number expected is 65536. + * In: x4 = the decimal to print. + * Clobber: x30, x0, x1, x2, x5, x6 + */ + .macro asm_print_line_dec + mov x6, #10 /* Divide by 10 after every loop iteration */ + mov x5, #MAX_DEC_DIVISOR +dec_print_loop: + udiv x0, x4, x5 /* Get the quotient */ + msub x4, x0, x5, x4 /* Find the remainder */ + add x0, x0, #ASCII_OFFSET_NUM /* Convert to ascii */ + bl plat_crash_console_putc + udiv x5, x5, x6 /* Reduce divisor */ + cbnz x5, dec_print_loop + .endm + + +/* --------------------------------------------------------------------------- + * Assertion support in assembly. + * The below function helps to support assertions in assembly where we do not + * have a C runtime stack. Arguments to the function are : + * x0 - File name + * x1 - Line no + * Clobber list : x30, x0, x1, x2, x3, x4, x5, x6. + * --------------------------------------------------------------------------- + */ +func asm_assert +#if LOG_LEVEL >= LOG_LEVEL_INFO + /* + * Only print the output if LOG_LEVEL is higher or equal to + * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. + */ + mov x5, x0 + mov x6, x1 + + /* Ensure the console is initialized */ + bl plat_crash_console_init + + /* Check if the console is initialized */ + cbz x0, _assert_loop + + /* The console is initialized */ + adr x4, assert_msg1 + bl asm_print_str + mov x4, x5 + bl asm_print_str + adr x4, assert_msg2 + bl asm_print_str + + /* Check if line number higher than max permitted */ + tst x6, #~0xffff + b.ne _assert_loop + mov x4, x6 + asm_print_line_dec + bl plat_crash_console_flush +_assert_loop: +#endif /* LOG_LEVEL >= LOG_LEVEL_INFO */ + no_ret plat_panic_handler +endfunc asm_assert +#endif /* ENABLE_ASSERTIONS */ + +/* + * This function prints a string from address in x4. + * In: x4 = pointer to string. + * Clobber: x30, x0, x1, x2, x3 + */ +func asm_print_str + mov x3, x30 +1: + ldrb w0, [x4], #0x1 + cbz x0, 2f + bl plat_crash_console_putc + b 1b +2: + ret x3 +endfunc asm_print_str + +/* + * This function prints a hexadecimal number in x4. + * In: x4 = the hexadecimal to print. + * Clobber: x30, x0 - x3, x5 + */ +func asm_print_hex + mov x5, #64 /* No of bits to convert to ascii */ + + /* Convert to ascii number of bits in x5 */ +asm_print_hex_bits: + mov x3, x30 +1: + sub x5, x5, #4 + lsrv x0, x4, x5 + and x0, x0, #0xf + cmp x0, #0xA + b.lo 2f + /* Add by 0x27 in addition to ASCII_OFFSET_NUM + * to get ascii for characters 'a - f'. + */ + add x0, x0, #0x27 +2: + add x0, x0, #ASCII_OFFSET_NUM + bl plat_crash_console_putc + cbnz x5, 1b + ret x3 +endfunc asm_print_hex + +/* + * Helper function to print newline to console + * Clobber: x0 + */ +func asm_print_newline + mov x0, '\n' + b plat_crash_console_putc +endfunc asm_print_newline + + /*********************************************************** + * The common implementation of do_panic for all BL stages + ***********************************************************/ + +.section .rodata.panic_str, "aS" + panic_msg: .asciz "PANIC at PC : 0x" + +/* --------------------------------------------------------------------------- + * do_panic assumes that it is invoked from a C Runtime Environment ie a + * valid stack exists. This call will not return. + * Clobber list : if CRASH_REPORTING is not enabled then x30, x0 - x6 + * --------------------------------------------------------------------------- + */ + +/* This is for the non el3 BL stages to compile through */ + .weak el3_panic + .weak elx_panic + +func do_panic +#if CRASH_REPORTING + str x0, [sp, #-0x10]! + mrs x0, currentel + ubfx x0, x0, #MODE_EL_SHIFT, #MODE_EL_WIDTH + cmp x0, #MODE_EL3 +#if !HANDLE_EA_EL3_FIRST + ldr x0, [sp], #0x10 + b.eq el3_panic +#else + b.ne to_panic_common + + /* Check EL the exception taken from */ + mrs x0, spsr_el3 + ubfx x0, x0, #SPSR_EL_SHIFT, #SPSR_EL_WIDTH + cmp x0, #MODE_EL3 + b.ne elx_panic + ldr x0, [sp], #0x10 + b el3_panic + +to_panic_common: + ldr x0, [sp], #0x10 +#endif /* HANDLE_EA_EL3_FIRST */ +#endif /* CRASH_REPORTING */ + +panic_common: +/* + * el3_panic will be redefined by the BL31 + * crash reporting mechanism (if enabled) + */ +el3_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 + + /* Print new line */ + bl asm_print_newline + + bl plat_crash_console_flush + +_panic_handler: + /* Pass to plat_panic_handler the address from where el3_panic was + * called, not the address of the call from el3_panic. */ + mov x30, x6 + b plat_panic_handler +endfunc do_panic diff --git a/arm-trusted-firmware/common/aarch64/early_exceptions.S b/arm-trusted-firmware/common/aarch64/early_exceptions.S new file mode 100644 index 0000000..36a8724 --- /dev/null +++ b/arm-trusted-firmware/common/aarch64/early_exceptions.S @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by BL2 and BL31 stages. + * BL31 uses them before stacks are setup. BL2 uses them throughout. + * ----------------------------------------------------------------------------- + */ + .globl early_exceptions + +vector_base early_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 + mov x0, #SYNC_EXCEPTION_AARCH64 + bl plat_report_exception + no_ret plat_panic_handler +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 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32 + mov x0, #SYNC_EXCEPTION_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32 + mov x0, #IRQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry IrqA32 + +vector_entry FiqA32 + mov x0, #FIQ_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry FiqA32 + +vector_entry SErrorA32 + mov x0, #SERROR_AARCH32 + bl plat_report_exception + no_ret plat_panic_handler +end_vector_entry SErrorA32 diff --git a/arm-trusted-firmware/common/backtrace/backtrace.c b/arm-trusted-firmware/common/backtrace/backtrace.c new file mode 100644 index 0000000..25e2c70 --- /dev/null +++ b/arm-trusted-firmware/common/backtrace/backtrace.c @@ -0,0 +1,273 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +/* Maximum number of entries in the backtrace to display */ +#define UNWIND_LIMIT 20U + +/* + * If -fno-omit-frame-pointer is used: + * + * - AArch64: The AAPCS defines the format of the frame records and mandates the + * usage of r29 as frame pointer. + * + * - AArch32: The format of the frame records is not defined in the AAPCS. + * However, at least GCC and Clang use the same format. When they are forced + * to only generate A32 code (with -marm), they use r11 as frame pointer and a + * similar format as in AArch64. If interworking with T32 is enabled, the + * frame pointer is r7 and the format is different. This is not supported by + * this implementation of backtrace, so it is needed to use -marm. + */ + +/* Frame records form a linked list in the stack */ +struct frame_record { + /* Previous frame record in the list */ + struct frame_record *parent; + /* Return address of the function at this level */ + uintptr_t return_addr; +}; + +const char *get_el_str(unsigned int el) +{ + if (el == 3U) { + return "EL3"; + } else if (el == 2U) { + return "EL2"; + } else { + return "S-EL1"; + } +} + +/* + * Returns true if the address points to a virtual address that can be read at + * the current EL, false otherwise. + */ +#ifdef __aarch64__ +static bool is_address_readable(uintptr_t addr) +{ + unsigned int el = get_current_el(); + +#if ENABLE_PAUTH + /* + * When pointer authentication is enabled, the LR value saved on the + * stack contains a PAC. It must be stripped to retrieve the return + * address. + */ + xpaci(addr); +#endif + if (el == 3U) { + ats1e3r(addr); + } else if (el == 2U) { + ats1e2r(addr); + } else { + AT(ats1e1r, addr); + } + + isb(); + + /* If PAR.F == 1 the address translation was aborted. */ + if ((read_par_el1() & PAR_F_MASK) != 0U) + return false; + + return true; +} +#else /* !__aarch64__ */ +static bool is_address_readable(uintptr_t addr) +{ + unsigned int el = get_current_el(); + + if (el == 3U) { + write_ats1cpr(addr); + } else if (el == 2U) { + write_ats1hr(addr); + } else { + write_ats1cpr(addr); + } + + isb(); + + /* If PAR.F == 1 the address translation was aborted. */ + if ((read64_par() & PAR_F_MASK) != 0U) + return false; + + return true; +} +#endif /* __aarch64__ */ + +/* + * Returns true if all the bytes in a given object are in mapped memory and an + * LDR using this pointer would succeed, false otherwise. + */ +static bool is_valid_object(uintptr_t addr, size_t size) +{ + assert(size > 0U); + + if (addr == 0U) + return false; + + /* Detect overflows */ + if ((addr + size) < addr) + return false; + + /* A pointer not aligned properly could trigger an alignment fault. */ + if ((addr & (sizeof(uintptr_t) - 1U)) != 0U) + return false; + + /* Check that all the object is readable */ + for (size_t i = 0; i < size; i++) { + if (!is_address_readable(addr + i)) + return false; + } + + return true; +} + +/* + * Returns true if the specified address is correctly aligned and points to a + * valid memory region. + */ +static bool is_valid_jump_address(uintptr_t addr) +{ + if (addr == 0U) + return false; + + /* Check alignment. Both A64 and A32 use 32-bit opcodes */ + if ((addr & (sizeof(uint32_t) - 1U)) != 0U) + return false; + + if (!is_address_readable(addr)) + return false; + + return true; +} + +/* + * Returns true if the pointer points at a valid frame record, false otherwise. + */ +static bool is_valid_frame_record(struct frame_record *fr) +{ + return is_valid_object((uintptr_t)fr, sizeof(struct frame_record)); +} + +/* + * Adjust the frame-pointer-register value by 4 bytes on AArch32 to have the + * same layout as AArch64. + */ +static struct frame_record *adjust_frame_record(struct frame_record *fr) +{ +#ifdef __aarch64__ + return fr; +#else + return (struct frame_record *)((uintptr_t)fr - 4U); +#endif +} + +static void unwind_stack(struct frame_record *fr, uintptr_t current_pc, + uintptr_t link_register) +{ + uintptr_t call_site; + static const char *backtrace_str = "%u: %s: 0x%lx\n"; + const char *el_str = get_el_str(get_current_el()); + + if (!is_valid_frame_record(fr)) { + printf("ERROR: Corrupted frame pointer (frame record address = %p)\n", + fr); + return; + } + + if (fr->return_addr != link_register) { + printf("ERROR: Corrupted stack (frame record address = %p)\n", + fr); + return; + } + + /* The level 0 of the backtrace is the current backtrace function */ + printf(backtrace_str, 0U, el_str, current_pc); + + /* + * The last frame record pointer in the linked list at the beginning of + * the stack should be NULL unless stack is corrupted. + */ + for (unsigned int i = 1U; i < UNWIND_LIMIT; i++) { + /* If an invalid frame record is found, exit. */ + if (!is_valid_frame_record(fr)) + return; + /* + * A32 and A64 are fixed length so the address from where the + * call was made is the instruction before the return address, + * which is always 4 bytes before it. + */ + call_site = fr->return_addr - 4U; + +#if ENABLE_PAUTH + /* + * When pointer authentication is enabled, the LR value saved on + * the stack contains a PAC. It must be stripped to retrieve the + * return address. + */ + xpaci(call_site); +#endif + /* + * If the address is invalid it means that the frame record is + * probably corrupted. + */ + if (!is_valid_jump_address(call_site)) + return; + + printf(backtrace_str, i, el_str, call_site); + + fr = adjust_frame_record(fr->parent); + } + + printf("ERROR: Max backtrace depth reached\n"); +} + +/* + * Display a backtrace. The cookie string parameter is displayed along the + * trace to help filter the log messages. + * + * Many things can prevent displaying the expected backtrace. For example, + * compiler optimizations can use a branch instead of branch with link when it + * detects a tail call. The backtrace level for this caller will not be + * displayed, as it does not appear in the call stack anymore. Also, assembly + * functions will not be displayed unless they setup AAPCS compliant frame + * records on AArch64 and compliant with GCC-specific frame record format on + * AArch32. + * + * Usage of the trace: addr2line can be used to map the addresses to function + * and source code location when given the ELF file compiled with debug + * information. The "-i" flag is highly recommended to improve display of + * inlined function. The *.dump files generated when building each image can + * also be used. + * + * WARNING: In case of corrupted stack, this function could display security + * sensitive information past the beginning of the stack so it must not be used + * in production build. This function is only compiled in when ENABLE_BACKTRACE + * is set to 1. + */ +void backtrace(const char *cookie) +{ + uintptr_t return_address = (uintptr_t)__builtin_return_address(0U); + struct frame_record *fr = __builtin_frame_address(0U); + + /* Printing the backtrace may crash the system, flush before starting */ + console_flush(); + + fr = adjust_frame_record(fr); + + printf("BACKTRACE: START: %s\n", cookie); + + unwind_stack(fr, (uintptr_t)&backtrace, return_address); + + printf("BACKTRACE: END: %s\n", cookie); +} diff --git a/arm-trusted-firmware/common/backtrace/backtrace.mk b/arm-trusted-firmware/common/backtrace/backtrace.mk new file mode 100644 index 0000000..e669331 --- /dev/null +++ b/arm-trusted-firmware/common/backtrace/backtrace.mk @@ -0,0 +1,31 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Enable backtrace by default in DEBUG AArch64 builds +ifeq (${ARCH},aarch32) + ENABLE_BACKTRACE := 0 +else + ENABLE_BACKTRACE := ${DEBUG} +endif + +ifeq (${ENABLE_BACKTRACE},1) + # Force the compiler to include the frame pointer + TF_CFLAGS += -fno-omit-frame-pointer + + BL_COMMON_SOURCES += common/backtrace/backtrace.c +endif + +ifeq (${ARCH},aarch32) + ifeq (${ENABLE_BACKTRACE},1) + ifneq (${AARCH32_INSTRUCTION_SET},A32) + $(error Error: AARCH32_INSTRUCTION_SET=A32 is needed \ + for ENABLE_BACKTRACE when compiling for AArch32.) + endif + endif +endif + +$(eval $(call assert_boolean,ENABLE_BACKTRACE)) +$(eval $(call add_define,ENABLE_BACKTRACE)) diff --git a/arm-trusted-firmware/common/bl_common.c b/arm-trusted-firmware/common/bl_common.c new file mode 100644 index 0000000..9bfaafd --- /dev/null +++ b/arm-trusted-firmware/common/bl_common.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if TRUSTED_BOARD_BOOT +# ifdef DYN_DISABLE_AUTH +static int disable_auth; + +/****************************************************************************** + * API to dynamically disable authentication. Only meant for development + * systems. This is only invoked if DYN_DISABLE_AUTH is defined. + *****************************************************************************/ +void dyn_disable_auth(void) +{ + INFO("Disabling authentication of images dynamically\n"); + disable_auth = 1; +} +# endif /* DYN_DISABLE_AUTH */ + +/****************************************************************************** + * Function to determine whether the authentication is disabled dynamically. + *****************************************************************************/ +static int dyn_is_auth_disabled(void) +{ +# ifdef DYN_DISABLE_AUTH + return disable_auth; +# else + return 0; +# endif +} +#endif /* TRUSTED_BOARD_BOOT */ + +uintptr_t page_align(uintptr_t value, unsigned dir) +{ + /* Round up the limit to the next page boundary */ + if ((value & PAGE_SIZE_MASK) != 0U) { + value &= ~PAGE_SIZE_MASK; + if (dir == UP) + value += PAGE_SIZE; + } + + return value; +} + +/******************************************************************************* + * Internal function to load an image at a specific address given + * an image ID and extents of free memory. + * + * If the load is successful then the image information is updated. + * + * Returns 0 on success, a negative error code otherwise. + ******************************************************************************/ +static int load_image(unsigned int image_id, image_info_t *image_data) +{ + uintptr_t dev_handle; + uintptr_t image_handle; + uintptr_t image_spec; + uintptr_t image_base; + size_t image_size; + size_t bytes_read; + int io_result; + + assert(image_data != NULL); + assert(image_data->h.version >= VERSION_2); + + image_base = image_data->image_base; + + /* Obtain a reference to the image by querying the platform layer */ + io_result = plat_get_image_source(image_id, &dev_handle, &image_spec); + if (io_result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, io_result); + return io_result; + } + + /* Attempt to access the image */ + io_result = io_open(dev_handle, image_spec, &image_handle); + if (io_result != 0) { + WARN("Failed to access image id=%u (%i)\n", + image_id, io_result); + return io_result; + } + + INFO("Loading image id=%u at address 0x%lx\n", image_id, image_base); + + /* Find the size of the image */ + io_result = io_size(image_handle, &image_size); + if ((io_result != 0) || (image_size == 0U)) { + WARN("Failed to determine the size of the image id=%u (%i)\n", + image_id, io_result); + goto exit; + } + + /* Check that the image size to load is within limit */ + if (image_size > image_data->image_max_size) { + WARN("Image id=%u size out of bounds\n", image_id); + io_result = -EFBIG; + goto exit; + } + + /* + * image_data->image_max_size is a uint32_t so image_size will always + * fit in image_data->image_size. + */ + image_data->image_size = (uint32_t)image_size; + + /* We have enough space so load the image now */ + /* TODO: Consider whether to try to recover/retry a partially successful read */ + io_result = io_read(image_handle, image_base, image_size, &bytes_read); + if ((io_result != 0) || (bytes_read < image_size)) { + WARN("Failed to load image id=%u (%i)\n", image_id, io_result); + goto exit; + } + + INFO("Image id=%u loaded: 0x%lx - 0x%lx\n", image_id, image_base, + (uintptr_t)(image_base + image_size)); + +exit: + (void)io_close(image_handle); + /* Ignore improbable/unrecoverable error in 'close' */ + + /* TODO: Consider maintaining open device connection from this bootloader stage */ + (void)io_dev_close(dev_handle); + /* Ignore improbable/unrecoverable error in 'dev_close' */ + + return io_result; +} + +#if TRUSTED_BOARD_BOOT +/* + * This function uses recursion to authenticate the parent images up to the root + * of trust. + */ +static int load_auth_image_recursive(unsigned int image_id, + image_info_t *image_data, + int is_parent_image) +{ + int rc; + unsigned int parent_id; + + /* Use recursion to authenticate parent images */ + rc = auth_mod_get_parent_id(image_id, &parent_id); + if (rc == 0) { + rc = load_auth_image_recursive(parent_id, image_data, 1); + if (rc != 0) { + return rc; + } + } + + /* Load the image */ + rc = load_image(image_id, image_data); + if (rc != 0) { + return rc; + } + + /* Authenticate it */ + rc = auth_mod_verify_img(image_id, + (void *)image_data->image_base, + image_data->image_size); + if (rc != 0) { + /* Authentication error, zero memory and flush it right away. */ + zero_normalmem((void *)image_data->image_base, + image_data->image_size); + flush_dcache_range(image_data->image_base, + image_data->image_size); + return -EAUTH; + } + + return 0; +} +#endif /* TRUSTED_BOARD_BOOT */ + +static int load_auth_image_internal(unsigned int image_id, + image_info_t *image_data) +{ +#if TRUSTED_BOARD_BOOT + if (dyn_is_auth_disabled() == 0) { + return load_auth_image_recursive(image_id, image_data, 0); + } +#endif + + return load_image(image_id, image_data); +} + +/******************************************************************************* + * Generic function to load and authenticate an image. The image is actually + * loaded by calling the 'load_image()' function. Therefore, it returns the + * same error codes if the loading operation failed, or -EAUTH if the + * authentication failed. In addition, this function uses recursion to + * authenticate the parent images up to the root of trust (if TBB is enabled). + ******************************************************************************/ +int load_auth_image(unsigned int image_id, image_info_t *image_data) +{ + int err; + +/* + * All firmware banks should be part of the same non-volatile storage as per + * PSA FWU specification, hence don't check for any alternate boot source + * when PSA FWU is enabled. + */ +#if PSA_FWU_SUPPORT + err = load_auth_image_internal(image_id, image_data); +#else + do { + err = load_auth_image_internal(image_id, image_data); + } while ((err != 0) && (plat_try_next_boot_source() != 0)); +#endif /* PSA_FWU_SUPPORT */ + + if (err == 0) { + /* + * If loading of the image gets passed (along with its + * authentication in case of Trusted-Boot flow) then measure + * it (if MEASURED_BOOT flag is enabled). + */ + err = plat_mboot_measure_image(image_id, image_data); + if (err != 0) { + return err; + } + + /* + * Flush the image to main memory so that it can be executed + * later by any CPU, regardless of cache and MMU state. + */ + flush_dcache_range(image_data->image_base, + image_data->image_size); + } + + return err; +} + +/******************************************************************************* + * Print the content of an entry_point_info_t structure. + ******************************************************************************/ +void print_entry_point_info(const entry_point_info_t *ep_info) +{ + INFO("Entry point address = 0x%lx\n", ep_info->pc); + INFO("SPSR = 0x%x\n", ep_info->spsr); + +#define PRINT_IMAGE_ARG(n) \ + VERBOSE("Argument #" #n " = 0x%llx\n", \ + (unsigned long long) ep_info->args.arg##n) + + PRINT_IMAGE_ARG(0); + PRINT_IMAGE_ARG(1); + PRINT_IMAGE_ARG(2); + PRINT_IMAGE_ARG(3); +#ifdef __aarch64__ + PRINT_IMAGE_ARG(4); + PRINT_IMAGE_ARG(5); + PRINT_IMAGE_ARG(6); + PRINT_IMAGE_ARG(7); +#endif +#undef PRINT_IMAGE_ARG +} diff --git a/arm-trusted-firmware/common/desc_image_load.c b/arm-trusted-firmware/common/desc_image_load.c new file mode 100644 index 0000000..30b97e0 --- /dev/null +++ b/arm-trusted-firmware/common/desc_image_load.c @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +static bl_load_info_t bl_load_info; +static bl_params_t next_bl_params; + + +/******************************************************************************* + * This function flushes the data structures so that they are visible + * in memory for the next BL image. + ******************************************************************************/ +void flush_bl_params_desc(void) +{ + flush_bl_params_desc_args(bl_mem_params_desc_ptr, + bl_mem_params_desc_num, + &next_bl_params); +} + +/******************************************************************************* + * This function flushes the data structures specified as arguments so that they + * are visible in memory for the next BL image. + ******************************************************************************/ +void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, + unsigned int mem_params_desc_num, + bl_params_t *next_bl_params_ptr) +{ + assert(mem_params_desc_ptr != NULL); + assert(mem_params_desc_num != 0U); + assert(next_bl_params_ptr != NULL); + + flush_dcache_range((uintptr_t)mem_params_desc_ptr, + sizeof(*mem_params_desc_ptr) * mem_params_desc_num); + + flush_dcache_range((uintptr_t)next_bl_params_ptr, + sizeof(*next_bl_params_ptr)); +} + +/******************************************************************************* + * This function returns the index for given image_id, within the + * image descriptor array provided by bl_image_info_descs_ptr, if the + * image is found else it returns -1. + ******************************************************************************/ +int get_bl_params_node_index(unsigned int image_id) +{ + unsigned int index; + assert(image_id != INVALID_IMAGE_ID); + + for (index = 0U; index < bl_mem_params_desc_num; index++) { + if (bl_mem_params_desc_ptr[index].image_id == image_id) + return (int)index; + } + + return -1; +} + +/******************************************************************************* + * This function returns the pointer to `bl_mem_params_node_t` object for + * given image_id, within the image descriptor array provided by + * bl_mem_params_desc_ptr, if the image is found else it returns NULL. + ******************************************************************************/ +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id) +{ + int index; + assert(image_id != INVALID_IMAGE_ID); + + index = get_bl_params_node_index(image_id); + if (index >= 0) + return &bl_mem_params_desc_ptr[index]; + else + return NULL; +} + +/******************************************************************************* + * This function creates the list of loadable images, by populating and + * linking each `bl_load_info_node_t` type node, using the internal array + * of image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_load_info_t` type structure that contains head of the list + * of loadable images. + ******************************************************************************/ +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void) +{ + unsigned int index = 0; + + /* If there is no image to start with, return NULL */ + if (bl_mem_params_desc_num == 0U) + return NULL; + + /* Assign initial data structures */ + bl_load_info_node_t *bl_node_info = + &bl_mem_params_desc_ptr[index].load_node_mem; + bl_load_info.head = bl_node_info; + SET_PARAM_HEAD(&bl_load_info, PARAM_BL_LOAD_INFO, VERSION_2, 0U); + + /* Go through the image descriptor array and create the list */ + for (; index < bl_mem_params_desc_num; index++) { + + /* Populate the image information */ + bl_node_info->image_id = bl_mem_params_desc_ptr[index].image_id; + bl_node_info->image_info = &bl_mem_params_desc_ptr[index].image_info; + + /* Link next image if present */ + if ((index + 1U) < bl_mem_params_desc_num) { + /* Get the memory and link the next node */ + bl_node_info->next_load_info = + &bl_mem_params_desc_ptr[index + 1U].load_node_mem; + bl_node_info = bl_node_info->next_load_info; + } + } + + return &bl_load_info; +} + +/******************************************************************************* + * This function creates the list of executable images, by populating and + * linking each `bl_params_node_t` type node, using the internal array of + * image descriptor provided by bl_mem_params_desc_ptr. It also populates + * and returns `bl_params_t` type structure that contains head of the list + * of executable images. + ******************************************************************************/ +bl_params_t *get_next_bl_params_from_mem_params_desc(void) +{ + unsigned int count; + unsigned int img_id = 0U; + unsigned int link_index = 0U; + bl_params_node_t *bl_current_exec_node = NULL; + bl_params_node_t *bl_last_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; + + /* Get the list HEAD */ + for (count = 0U; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[count]; + + if ((EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE) && + (EP_GET_FIRST_EXE(desc_ptr->ep_info.h.attr) == EP_FIRST_EXE)) { + next_bl_params.head = &desc_ptr->params_node_mem; + link_index = count; + break; + } + } + + /* Make sure we have a HEAD node */ + assert(next_bl_params.head != NULL); + + /* Populate the HEAD information */ + SET_PARAM_HEAD(&next_bl_params, PARAM_BL_PARAMS, VERSION_2, 0U); + + /* + * Go through the image descriptor array and create the list. + * This bounded loop is to make sure that we are not looping forever. + */ + for (count = 0U; count < bl_mem_params_desc_num; count++) { + + desc_ptr = &bl_mem_params_desc_ptr[link_index]; + + /* Make sure the image is executable */ + assert(EP_GET_EXE(desc_ptr->ep_info.h.attr) == EXECUTABLE); + + /* Get the memory for current node */ + bl_current_exec_node = &desc_ptr->params_node_mem; + + /* Populate the image information */ + bl_current_exec_node->image_id = desc_ptr->image_id; + bl_current_exec_node->image_info = &desc_ptr->image_info; + bl_current_exec_node->ep_info = &desc_ptr->ep_info; + + if (bl_last_exec_node != NULL) { + /* Assert if loop detected */ + assert(bl_last_exec_node->next_params_info == NULL); + + /* Link the previous node to the current one */ + bl_last_exec_node->next_params_info = bl_current_exec_node; + } + + /* Update the last node */ + bl_last_exec_node = bl_current_exec_node; + + /* 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); + assert((link_index > 0U) && + (link_index < bl_mem_params_desc_num)); + } + + /* Invalid image is expected to terminate the loop */ + assert(img_id == INVALID_IMAGE_ID); + + return &next_bl_params; +} + +/******************************************************************************* + * This function populates the entry point information with the corresponding + * config file for all executable BL images described in bl_params. + ******************************************************************************/ +void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params) +{ + bl_params_node_t *params_node; + unsigned int fw_config_id; + uintptr_t fw_config_base; + bl_mem_params_node_t *mem_params; + uintptr_t hw_config_base = 0; + + assert(bl2_to_next_bl_params != NULL); + + /* + * Get the `bl_mem_params_node_t` corresponding to HW_CONFIG + * if available. + */ + mem_params = get_bl_mem_params_node(HW_CONFIG_ID); + + if (mem_params != NULL) + hw_config_base = mem_params->image_info.image_base; + + for (params_node = bl2_to_next_bl_params->head; params_node != NULL; + params_node = params_node->next_params_info) { + + fw_config_base = 0; + + switch (params_node->image_id) { + case BL31_IMAGE_ID: + fw_config_id = SOC_FW_CONFIG_ID; + break; + case BL32_IMAGE_ID: + /* + * At the moment, OPTEE cannot accept a DTB in secure memory, + * so fall back and use NT_FW_CONFIG instead. + * This MUST be fixed as soon as OPTEE has support to + * receive DTBs in secure memory. + */ +#ifndef SPD_opteed + fw_config_id = TOS_FW_CONFIG_ID; + break; +#endif + case BL33_IMAGE_ID: + fw_config_id = NT_FW_CONFIG_ID; + break; + default: + fw_config_id = INVALID_IMAGE_ID; + break; + } + + if (fw_config_id != INVALID_IMAGE_ID) { + mem_params = get_bl_mem_params_node(fw_config_id); + if (mem_params != NULL) { + fw_config_base = mem_params->image_info.image_base; + } + } + +#ifdef SPD_opteed + /* + * If SPD_opteed is enabled, arg[0,2] are populated by + * parse_optee_header(), which is called by + * arm_bl2_handle_post_image_load(). The meaning of the + * arguments are: + * arg0 <-- MODE_RW + * arg1 <-- Paged image base + * arg2 <-- Paged image size + */ + if (params_node->image_id == BL32_IMAGE_ID) { + params_node->ep_info->args.arg3 = fw_config_base; + } else { +#endif + /* + * Pass hw and tb_fw config addresses to next images. + * NOTE - for EL3 runtime images (BL31 for AArch64 + * and BL32 for AArch32), arg0 is already used by + * generic code. Take care of not overwriting the + * previous initialisations. + */ + if (params_node == bl2_to_next_bl_params->head) { + if (params_node->ep_info->args.arg1 == 0U) + params_node->ep_info->args.arg1 = + fw_config_base; + if (params_node->ep_info->args.arg2 == 0U) + params_node->ep_info->args.arg2 = + hw_config_base; + } else { + if (params_node->ep_info->args.arg0 == 0U) + params_node->ep_info->args.arg0 = + fw_config_base; + if (params_node->ep_info->args.arg1 == 0U) + params_node->ep_info->args.arg1 = + hw_config_base; + } +#ifdef SPD_opteed + } +#endif + } +} + +/******************************************************************************* + * Helper to extract BL32/BL33 entry point info from arg0 passed to BL31, for + * platforms that are only interested in those. Platforms that need to extract + * more information can parse the structures themselves. + ******************************************************************************/ + +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out) +{ + bl_params_node_t *node; + bl_params_t *v2 = (void *)(uintptr_t)param; + +#if !ERROR_DEPRECATED + if (v2->h.version == PARAM_VERSION_1) { + struct { /* Deprecated version 1 parameter structure. */ + 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; + } *v1 = (void *)(uintptr_t)param; + assert(v1->h.type == PARAM_BL31); + if (bl32_ep_info_out != NULL) + *bl32_ep_info_out = *v1->bl32_ep_info; + if (bl33_ep_info_out != NULL) + *bl33_ep_info_out = *v1->bl33_ep_info; + return; + } +#endif /* !ERROR_DEPRECATED */ + + assert(v2->h.version == PARAM_VERSION_2); + assert(v2->h.type == PARAM_BL_PARAMS); + for (node = v2->head; node != NULL; node = node->next_params_info) { + if (node->image_id == BL32_IMAGE_ID) + if (bl32_ep_info_out != NULL) + *bl32_ep_info_out = *node->ep_info; + if (node->image_id == BL33_IMAGE_ID) + if (bl33_ep_info_out != NULL) + *bl33_ep_info_out = *node->ep_info; + } +} diff --git a/arm-trusted-firmware/common/fdt_fixup.c b/arm-trusted-firmware/common/fdt_fixup.c new file mode 100644 index 0000000..de02b46 --- /dev/null +++ b/arm-trusted-firmware/common/fdt_fixup.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Contains generic routines to fix up the device tree blob passed on to + * payloads like BL32 and BL33 (and further down the boot chain). + * This allows to easily add PSCI nodes, when the original DT does not have + * it or advertises another method. + * Also it supports to add reserved memory nodes to describe memory that + * is used by the secure world, so that non-secure software avoids using + * that. + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + + +static int append_psci_compatible(void *fdt, int offs, const char *str) +{ + return fdt_appendprop(fdt, offs, "compatible", str, strlen(str) + 1); +} + +/* + * Those defines are for PSCI v0.1 legacy clients, which we expect to use + * the same execution state (AArch32/AArch64) as TF-A. + * Kernels running in AArch32 on an AArch64 TF-A should use PSCI v0.2. + */ +#ifdef __aarch64__ +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH64 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH64 +#else +#define PSCI_CPU_SUSPEND_FNID PSCI_CPU_SUSPEND_AARCH32 +#define PSCI_CPU_ON_FNID PSCI_CPU_ON_AARCH32 +#endif + +/******************************************************************************* + * dt_add_psci_node() - Add a PSCI node into an existing device tree + * @fdt: pointer to the device tree blob in memory + * + * Add a device tree node describing PSCI into the root level of an existing + * device tree blob in memory. + * This will add v0.1, v0.2 and v1.0 compatible strings and the standard + * function IDs for v0.1 compatibility. + * An existing PSCI node will not be touched, the function will return success + * in this case. This function will not touch the /cpus enable methods, use + * dt_add_psci_cpu_enable_methods() for that. + * + * Return: 0 on success, -1 otherwise. + ******************************************************************************/ +int dt_add_psci_node(void *fdt) +{ + int offs; + + if (fdt_path_offset(fdt, "/psci") >= 0) { + WARN("PSCI Device Tree node already exists!\n"); + return 0; + } + + offs = fdt_path_offset(fdt, "/"); + if (offs < 0) + return -1; + offs = fdt_add_subnode(fdt, offs, "psci"); + if (offs < 0) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-1.0")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci-0.2")) + return -1; + if (append_psci_compatible(fdt, offs, "arm,psci")) + return -1; + if (fdt_setprop_string(fdt, offs, "method", "smc")) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_suspend", PSCI_CPU_SUSPEND_FNID)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_off", PSCI_CPU_OFF)) + return -1; + if (fdt_setprop_u32(fdt, offs, "cpu_on", PSCI_CPU_ON_FNID)) + return -1; + return 0; +} + +/* + * Find the first subnode that has a "device_type" property with the value + * "cpu" and which's enable-method is not "psci" (yet). + * Returns 0 if no such subnode is found, so all have already been patched + * or none have to be patched in the first place. + * Returns 1 if *one* such subnode has been found and successfully changed + * to "psci". + * Returns negative values on error. + * + * Call in a loop until it returns 0. Recalculate the node offset after + * it has returned 1. + */ +static int dt_update_one_cpu_node(void *fdt, int offset) +{ + int offs; + + /* Iterate over all subnodes to find those with device_type = "cpu". */ + for (offs = fdt_first_subnode(fdt, offset); offs >= 0; + offs = fdt_next_subnode(fdt, offs)) { + const char *prop; + int len; + int ret; + + prop = fdt_getprop(fdt, offs, "device_type", &len); + if (prop == NULL) + continue; + if ((strcmp(prop, "cpu") != 0) || (len != 4)) + continue; + + /* Ignore any nodes which already use "psci". */ + prop = fdt_getprop(fdt, offs, "enable-method", &len); + if ((prop != NULL) && + (strcmp(prop, "psci") == 0) && (len == 5)) + continue; + + ret = fdt_setprop_string(fdt, offs, "enable-method", "psci"); + if (ret < 0) + return ret; + /* + * Subnode found and patched. + * Restart to accommodate potentially changed offsets. + */ + return 1; + } + + if (offs == -FDT_ERR_NOTFOUND) + return 0; + + return offs; +} + +/******************************************************************************* + * dt_add_psci_cpu_enable_methods() - switch CPU nodes in DT to use PSCI + * @fdt: pointer to the device tree blob in memory + * + * Iterate over all CPU device tree nodes (/cpus/cpu@x) in memory to change + * the enable-method to PSCI. This will add the enable-method properties, if + * required, or will change existing properties to read "psci". + * + * Return: 0 on success, or a negative error value otherwise. + ******************************************************************************/ + +int dt_add_psci_cpu_enable_methods(void *fdt) +{ + int offs, ret; + + do { + offs = fdt_path_offset(fdt, "/cpus"); + if (offs < 0) + return offs; + + ret = dt_update_one_cpu_node(fdt, offs); + } while (ret > 0); + + return ret; +} + +#define HIGH_BITS(x) ((sizeof(x) > 4) ? ((x) >> 32) : (typeof(x))0) + +/******************************************************************************* + * fdt_add_reserved_memory() - reserve (secure) memory regions in DT + * @dtb: pointer to the device tree blob in memory + * @node_name: name of the subnode to be used + * @base: physical base address of the reserved region + * @size: size of the reserved region + * + * Add a region of memory to the /reserved-memory node in a device tree in + * memory, creating that node if required. Each region goes into a subnode + * of that node and has a @node_name, a @base address and a @size. + * This will prevent any device tree consumer from using that memory. It + * can be used to announce secure memory regions, as it adds the "no-map" + * property to prevent mapping and speculative operations on that region. + * + * See reserved-memory/reserved-memory.txt in the (Linux kernel) DT binding + * documentation for details. + * According to this binding, the address-cells and size-cells must match + * those of the root node. + * + * Return: 0 on success, a negative error value otherwise. + ******************************************************************************/ +int fdt_add_reserved_memory(void *dtb, const char *node_name, + uintptr_t base, size_t size) +{ + int offs = fdt_path_offset(dtb, "/reserved-memory"); + uint32_t addresses[4]; + int ac, sc; + unsigned int idx = 0; + + ac = fdt_address_cells(dtb, 0); + sc = fdt_size_cells(dtb, 0); + if (offs < 0) { /* create if not existing yet */ + offs = fdt_add_subnode(dtb, 0, "reserved-memory"); + if (offs < 0) { + return offs; + } + fdt_setprop_u32(dtb, offs, "#address-cells", ac); + fdt_setprop_u32(dtb, offs, "#size-cells", sc); + fdt_setprop(dtb, offs, "ranges", NULL, 0); + } + + if (ac > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(base)); + idx++; + } + addresses[idx] = cpu_to_fdt32(base & 0xffffffff); + idx++; + if (sc > 1) { + addresses[idx] = cpu_to_fdt32(HIGH_BITS(size)); + idx++; + } + addresses[idx] = cpu_to_fdt32(size & 0xffffffff); + idx++; + offs = fdt_add_subnode(dtb, offs, node_name); + fdt_setprop(dtb, offs, "no-map", NULL, 0); + fdt_setprop(dtb, offs, "reg", addresses, idx * sizeof(uint32_t)); + + return 0; +} + +/******************************************************************************* + * fdt_add_cpu() Add a new CPU node to the DT + * @dtb: Pointer to the device tree blob in memory + * @parent: Offset of the parent node + * @mpidr: MPIDR for the current CPU + * + * Create and add a new cpu node to a DTB. + * + * Return the offset of the new node or a negative value in case of error + ******************************************************************************/ + +static int fdt_add_cpu(void *dtb, int parent, u_register_t mpidr) +{ + int cpu_offs; + int err; + char snode_name[15]; + uint64_t reg_prop; + + reg_prop = mpidr & MPID_MASK & ~MPIDR_MT_MASK; + + snprintf(snode_name, sizeof(snode_name), "cpu@%x", + (unsigned int)reg_prop); + + cpu_offs = fdt_add_subnode(dtb, parent, snode_name); + if (cpu_offs < 0) { + ERROR ("FDT: add subnode \"%s\" failed: %i\n", + snode_name, cpu_offs); + return cpu_offs; + } + + err = fdt_setprop_string(dtb, cpu_offs, "compatible", "arm,armv8"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "compatible", cpu_offs); + return err; + } + + err = fdt_setprop_u64(dtb, cpu_offs, "reg", reg_prop); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "reg", cpu_offs); + return err; + } + + err = fdt_setprop_string(dtb, cpu_offs, "device_type", "cpu"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "device_type", cpu_offs); + return err; + } + + err = fdt_setprop_string(dtb, cpu_offs, "enable-method", "psci"); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "enable-method", cpu_offs); + return err; + } + + return cpu_offs; +} + +/****************************************************************************** + * fdt_add_cpus_node() - Add the cpus node to the DTB + * @dtb: pointer to the device tree blob in memory + * @afflv0: Maximum number of threads per core (affinity level 0). + * @afflv1: Maximum number of CPUs per cluster (affinity level 1). + * @afflv2: Maximum number of clusters (affinity level 2). + * + * Iterate over all the possible MPIDs given the maximum affinity levels and + * add a cpus node to the DTB with all the valid CPUs on the system. + * If there is already a /cpus node, exit gracefully + * + * A system with two CPUs would generate a node equivalent or similar to: + * + * cpus { + * #address-cells = <2>; + * #size-cells = <0>; + * + * cpu0: cpu@0 { + * compatible = "arm,armv8"; + * reg = <0x0 0x0>; + * device_type = "cpu"; + * enable-method = "psci"; + * }; + * cpu1: cpu@10000 { + * compatible = "arm,armv8"; + * reg = <0x0 0x100>; + * device_type = "cpu"; + * enable-method = "psci"; + * }; + * }; + * + * Full documentation about the CPU bindings can be found at: + * https://www.kernel.org/doc/Documentation/devicetree/bindings/arm/cpus.txt + * + * Return the offset of the node or a negative value on error. + ******************************************************************************/ + +int fdt_add_cpus_node(void *dtb, unsigned int afflv0, + unsigned int afflv1, unsigned int afflv2) +{ + int offs; + int err; + unsigned int i, j, k; + u_register_t mpidr; + int cpuid; + + if (fdt_path_offset(dtb, "/cpus") >= 0) { + return -EEXIST; + } + + offs = fdt_add_subnode(dtb, 0, "cpus"); + if (offs < 0) { + ERROR ("FDT: add subnode \"cpus\" node to parent node failed"); + return offs; + } + + err = fdt_setprop_u32(dtb, offs, "#address-cells", 2); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "#address-cells", offs); + return err; + } + + err = fdt_setprop_u32(dtb, offs, "#size-cells", 0); + if (err < 0) { + ERROR ("FDT: write to \"%s\" property of node at offset %i failed\n", + "#size-cells", offs); + return err; + } + + /* + * Populate the node with the CPUs. + * As libfdt prepends subnodes within a node, reverse the index count + * so the CPU nodes would be better ordered. + */ + for (i = afflv2; i > 0U; i--) { + for (j = afflv1; j > 0U; j--) { + for (k = afflv0; k > 0U; k--) { + mpidr = ((i - 1) << MPIDR_AFF2_SHIFT) | + ((j - 1) << MPIDR_AFF1_SHIFT) | + ((k - 1) << MPIDR_AFF0_SHIFT) | + (read_mpidr_el1() & MPIDR_MT_MASK); + + cpuid = plat_core_pos_by_mpidr(mpidr); + if (cpuid >= 0) { + /* Valid MPID found */ + err = fdt_add_cpu(dtb, offs, mpidr); + if (err < 0) { + ERROR ("FDT: %s 0x%08x\n", + "error adding CPU", + (uint32_t)mpidr); + return err; + } + } + } + } + } + + return offs; +} + +/** + * fdt_adjust_gic_redist() - Adjust GICv3 redistributor size + * @dtb: Pointer to the DT blob in memory + * @nr_cores: Number of CPU cores on this system. + * @gicr_base: Base address of the first GICR frame, or ~0 if unchanged + * @gicr_frame_size: Size of the GICR frame per core + * + * On a GICv3 compatible interrupt controller, the redistributor provides + * a number of 64k pages per each supported core. So with a dynamic topology, + * this size cannot be known upfront and thus can't be hardcoded into the DTB. + * + * Find the DT node describing the GICv3 interrupt controller, and adjust + * the size of the redistributor to match the number of actual cores on + * this system. + * A GICv4 compatible redistributor uses four 64K pages per core, whereas GICs + * without support for direct injection of virtual interrupts use two 64K pages. + * The @gicr_frame_size parameter should be 262144 and 131072, respectively. + * Also optionally allow adjusting the GICR frame base address, when this is + * different due to ITS frames between distributor and redistributor. + * + * Return: 0 on success, negative error value otherwise. + */ +int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, + uintptr_t gicr_base, unsigned int gicr_frame_size) +{ + int offset = fdt_node_offset_by_compatible(dtb, 0, "arm,gic-v3"); + uint64_t reg_64; + uint32_t reg_32; + void *val; + int parent, ret; + int ac, sc; + + if (offset < 0) { + return offset; + } + + parent = fdt_parent_offset(dtb, offset); + if (parent < 0) { + return parent; + } + ac = fdt_address_cells(dtb, parent); + sc = fdt_size_cells(dtb, parent); + if (ac < 0 || sc < 0) { + return -EINVAL; + } + + if (gicr_base != INVALID_BASE_ADDR) { + if (ac == 1) { + reg_32 = cpu_to_fdt32(gicr_base); + val = ®_32; + } else { + reg_64 = cpu_to_fdt64(gicr_base); + val = ®_64; + } + /* + * The redistributor base address is the second address in + * the "reg" entry, so we have to skip one address and one + * size cell. + */ + ret = fdt_setprop_inplace_namelen_partial(dtb, offset, + "reg", 3, + (ac + sc) * 4, + val, ac * 4); + if (ret < 0) { + return ret; + } + } + + if (sc == 1) { + reg_32 = cpu_to_fdt32(nr_cores * gicr_frame_size); + val = ®_32; + } else { + reg_64 = cpu_to_fdt64(nr_cores * (uint64_t)gicr_frame_size); + val = ®_64; + } + + /* + * The redistributor is described in the second "reg" entry. + * So we have to skip one address and one size cell, then another + * address cell to get to the second size cell. + */ + return fdt_setprop_inplace_namelen_partial(dtb, offset, "reg", 3, + (ac + sc + ac) * 4, + val, sc * 4); +} diff --git a/arm-trusted-firmware/common/fdt_wrappers.c b/arm-trusted-firmware/common/fdt_wrappers.c new file mode 100644 index 0000000..2a9673f --- /dev/null +++ b/arm-trusted-firmware/common/fdt_wrappers.c @@ -0,0 +1,620 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Helper functions to offer easier navigation of Device Tree Blob */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include + +/* + * Read cells from a given property of the given node. Any number of 32-bit + * cells of the property can be read. Returns 0 on success, or a negative + * FDT error value otherwise. + */ +int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name, + unsigned int cells, uint32_t *value) +{ + const fdt32_t *prop; + int value_len; + + assert(dtb != NULL); + assert(prop_name != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + prop = fdt_getprop(dtb, node, prop_name, &value_len); + if (prop == NULL) { + VERBOSE("Couldn't find property %s in dtb\n", prop_name); + return -FDT_ERR_NOTFOUND; + } + + /* Verify that property length can fill the entire array. */ + if (NCELLS((unsigned int)value_len) < cells) { + WARN("Property length mismatch\n"); + return -FDT_ERR_BADVALUE; + } + + for (unsigned int i = 0U; i < cells; i++) { + value[i] = fdt32_to_cpu(prop[i]); + } + + return 0; +} + +int fdt_read_uint32(const void *dtb, int node, const char *prop_name, + uint32_t *value) +{ + return fdt_read_uint32_array(dtb, node, prop_name, 1, value); +} + +uint32_t fdt_read_uint32_default(const void *dtb, int node, + const char *prop_name, uint32_t dflt_value) +{ + uint32_t ret = dflt_value; + int err = fdt_read_uint32(dtb, node, prop_name, &ret); + + if (err < 0) { + return dflt_value; + } + + return ret; +} + +int fdt_read_uint64(const void *dtb, int node, const char *prop_name, + uint64_t *value) +{ + uint32_t array[2] = {0, 0}; + int ret; + + ret = fdt_read_uint32_array(dtb, node, prop_name, 2, array); + if (ret < 0) { + return ret; + } + + *value = ((uint64_t)array[0] << 32) | array[1]; + return 0; +} + +/* + * Read bytes from a given property of the given node. Any number of + * bytes of the property can be read. The fdt pointer is updated. + * Returns 0 on success, and -1 on error. + */ +int fdtw_read_bytes(const void *dtb, int node, const char *prop, + unsigned int length, void *value) +{ + const void *ptr; + int value_len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* Access property and obtain its length (in bytes) */ + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), + &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + (void)memcpy(value, ptr, length); + + return 0; +} + +/* + * Read string from a given property of the given node. Up to 'size - 1' + * characters are read, and a NUL terminator is added. Returns 0 on success, + * and -1 upon error. + */ +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size) +{ + const char *ptr; + size_t len; + + assert(dtb != NULL); + assert(node >= 0); + assert(prop != NULL); + assert(str != NULL); + assert(size > 0U); + + ptr = fdt_getprop_namelen(dtb, node, prop, (int)strlen(prop), NULL); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + len = strlcpy(str, ptr, size); + if (len >= size) { + WARN("String of property %s in dtb has been truncated\n", prop); + return -1; + } + + return 0; +} + +/* + * Read UUID from a given property of the given node. Returns 0 on success, + * and a negative value upon error. + */ +int fdtw_read_uuid(const void *dtb, int node, const char *prop, + unsigned int length, uint8_t *uuid) +{ + /* Buffer for UUID string (plus NUL terminator) */ + char uuid_string[UUID_STRING_LENGTH + 1U]; + int err; + + assert(dtb != NULL); + assert(prop != NULL); + assert(uuid != NULL); + assert(node >= 0); + + if (length < UUID_BYTES_LENGTH) { + return -EINVAL; + } + + err = fdtw_read_string(dtb, node, prop, uuid_string, + UUID_STRING_LENGTH + 1U); + if (err != 0) { + return err; + } + + if (read_uuid(uuid, uuid_string) != 0) { + return -FDT_ERR_BADVALUE; + } + + return 0; +} + +/* + * Write cells in place to a given property of the given node. At most 2 cells + * of the property are written. Returns 0 on success, and -1 upon error. + */ +int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, + unsigned int cells, void *value) +{ + int err, len; + + assert(dtb != NULL); + assert(prop != NULL); + assert(value != NULL); + assert(node >= 0); + + /* We expect either 1 or 2 cell property */ + assert(cells <= 2U); + + if (cells == 2U) + *(uint64_t *)value = cpu_to_fdt64(*(uint64_t *)value); + else + *(uint32_t *)value = cpu_to_fdt32(*(uint32_t *)value); + + len = (int)cells * 4; + + /* Set property value in place */ + err = fdt_setprop_inplace(dtb, node, prop, value, len); + if (err != 0) { + WARN("Modify property %s failed with error %d\n", prop, err); + return -1; + } + + return 0; +} + +/* + * Write bytes in place to a given property of the given node. + * Any number of bytes of the property can be written. + * Returns 0 on success, and < 0 on error. + */ +int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, + unsigned int length, const void *data) +{ + const void *ptr; + int namelen, value_len, err; + + assert(dtb != NULL); + assert(prop != NULL); + assert(data != NULL); + assert(node >= 0); + + namelen = (int)strlen(prop); + + /* Access property and obtain its length in bytes */ + ptr = fdt_getprop_namelen(dtb, node, prop, namelen, &value_len); + if (ptr == NULL) { + WARN("Couldn't find property %s in dtb\n", prop); + return -1; + } + + /* Verify that property length is not less than number of bytes */ + if ((unsigned int)value_len < length) { + WARN("Property length mismatch\n"); + return -1; + } + + /* Set property value in place */ + err = fdt_setprop_inplace_namelen_partial(dtb, node, prop, + namelen, 0, + data, (int)length); + if (err != 0) { + WARN("Set property %s failed with error %d\n", prop, err); + } + + return err; +} + +static uint64_t fdt_read_prop_cells(const fdt32_t *prop, int nr_cells) +{ + uint64_t reg = fdt32_to_cpu(prop[0]); + + if (nr_cells > 1) { + reg = (reg << 32) | fdt32_to_cpu(prop[1]); + } + + return reg; +} + +int fdt_get_reg_props_by_index(const void *dtb, int node, int index, + uintptr_t *base, size_t *size) +{ + const fdt32_t *prop; + int parent, len; + int ac, sc; + int cell; + + parent = fdt_parent_offset(dtb, node); + if (parent < 0) { + return -FDT_ERR_BADOFFSET; + } + + ac = fdt_address_cells(dtb, parent); + sc = fdt_size_cells(dtb, parent); + + cell = index * (ac + sc); + + prop = fdt_getprop(dtb, node, "reg", &len); + if (prop == NULL) { + WARN("Couldn't find \"reg\" property in dtb\n"); + return -FDT_ERR_NOTFOUND; + } + + if (((cell + ac + sc) * (int)sizeof(uint32_t)) > len) { + return -FDT_ERR_BADVALUE; + } + + if (base != NULL) { + *base = (uintptr_t)fdt_read_prop_cells(&prop[cell], ac); + } + + if (size != NULL) { + *size = (size_t)fdt_read_prop_cells(&prop[cell + ac], sc); + } + + return 0; +} + +/******************************************************************************* + * This function fills reg node info (base & size) with an index found by + * checking the reg-names node. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +int fdt_get_reg_props_by_name(const void *dtb, int node, const char *name, + uintptr_t *base, size_t *size) +{ + int index; + + index = fdt_stringlist_search(dtb, node, "reg-names", name); + if (index < 0) { + return index; + } + + return fdt_get_reg_props_by_index(dtb, node, index, base, size); +} + +/******************************************************************************* + * This function gets the stdout path node. + * It reads the value indicated inside the device tree. + * Returns node offset on success and a negative FDT error code on failure. + ******************************************************************************/ +int fdt_get_stdout_node_offset(const void *dtb) +{ + int node; + const char *prop, *path; + int len; + + /* The /secure-chosen node takes precedence over the standard one. */ + node = fdt_path_offset(dtb, "/secure-chosen"); + if (node < 0) { + node = fdt_path_offset(dtb, "/chosen"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + } + + prop = fdt_getprop(dtb, node, "stdout-path", NULL); + if (prop == NULL) { + return -FDT_ERR_NOTFOUND; + } + + /* Determine the actual path length, as a colon terminates the path. */ + path = strchr(prop, ':'); + if (path == NULL) { + len = strlen(prop); + } else { + len = path - prop; + } + + /* Aliases cannot start with a '/', so it must be the actual path. */ + if (prop[0] == '/') { + return fdt_path_offset_namelen(dtb, prop, len); + } + + /* Lookup the alias, as this contains the actual path. */ + path = fdt_get_alias_namelen(dtb, prop, len); + if (path == NULL) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_path_offset(dtb, path); +} + + +/******************************************************************************* + * Only devices which are direct children of root node use CPU address domain. + * All other devices use addresses that are local to the device node and cannot + * directly used by CPU. Device tree provides an address translation mechanism + * through "ranges" property which provides mappings from local address space to + * parent address space. Since a device could be a child of a child node to the + * root node, there can be more than one level of address translation needed to + * map the device local address space to CPU address space. + * fdtw_translate_address() API performs address translation of a local address + * to a global address with help of various helper functions. + ******************************************************************************/ + +static bool fdtw_xlat_hit(const uint32_t *value, int child_addr_size, + int parent_addr_size, int range_size, uint64_t base_address, + uint64_t *translated_addr) +{ + uint64_t local_address, parent_address, addr_range; + + local_address = fdt_read_prop_cells(value, child_addr_size); + parent_address = fdt_read_prop_cells(value + child_addr_size, + parent_addr_size); + addr_range = fdt_read_prop_cells(value + child_addr_size + + parent_addr_size, + range_size); + VERBOSE("DT: Address %" PRIx64 " mapped to %" PRIx64 " with range %" PRIx64 "\n", + local_address, parent_address, addr_range); + + /* Perform range check */ + if ((base_address < local_address) || + (base_address >= local_address + addr_range)) { + return false; + } + + /* Found hit for the addr range that needs to be translated */ + *translated_addr = parent_address + (base_address - local_address); + VERBOSE("DT: child address %" PRIx64 "mapped to %" PRIx64 " in parent bus\n", + local_address, parent_address); + return true; +} + +#define ILLEGAL_ADDR ULL(~0) + +static uint64_t fdtw_search_all_xlat_entries(const void *dtb, + const struct fdt_property *ranges_prop, + int local_bus, uint64_t base_address) +{ + uint64_t translated_addr; + const uint32_t *next_entry; + int parent_bus_node, nxlat_entries, length; + int self_addr_cells, parent_addr_cells, self_size_cells, ncells_xlat; + + /* + * The number of cells in one translation entry in ranges is the sum of + * the following values: + * self#address-cells + parent#address-cells + self#size-cells + * Ex: the iofpga ranges property has one translation entry with 4 cells + * They represent iofpga#addr-cells + motherboard#addr-cells + iofpga#size-cells + * = 1 + 2 + 1 + */ + + parent_bus_node = fdt_parent_offset(dtb, local_bus); + self_addr_cells = fdt_address_cells(dtb, local_bus); + self_size_cells = fdt_size_cells(dtb, local_bus); + parent_addr_cells = fdt_address_cells(dtb, parent_bus_node); + + /* Number of cells per translation entry i.e., mapping */ + ncells_xlat = self_addr_cells + parent_addr_cells + self_size_cells; + + assert(ncells_xlat > 0); + + /* + * Find the number of translations(mappings) specified in the current + * `ranges` property. Note that length represents number of bytes and + * is stored in big endian mode. + */ + length = fdt32_to_cpu(ranges_prop->len); + nxlat_entries = (length/sizeof(uint32_t))/ncells_xlat; + + assert(nxlat_entries > 0); + + next_entry = (const uint32_t *)ranges_prop->data; + + /* Iterate over the entries in the "ranges" */ + for (int i = 0; i < nxlat_entries; i++) { + if (fdtw_xlat_hit(next_entry, self_addr_cells, + parent_addr_cells, self_size_cells, base_address, + &translated_addr)){ + return translated_addr; + } + next_entry = next_entry + ncells_xlat; + } + + INFO("DT: No translation found for address %" PRIx64 " in node %s\n", + base_address, fdt_get_name(dtb, local_bus, NULL)); + return ILLEGAL_ADDR; +} + + +/******************************************************************************* + * address mapping needs to be done recursively starting from current node to + * root node through all intermediate parent nodes. + * Sample device tree is shown here: + +smb@0,0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; + #size-cells = <1>; + ranges; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + }; +}; + + * As seen above, there are 3 levels of address translations needed. An empty + * `ranges` property denotes identity mapping (as seen in `motherboard` node). + * Each ranges property can map a set of child addresses to parent bus. Hence + * there can be more than 1 (translation) entry in the ranges property as seen + * in the `smb` node which has 6 translation entries. + ******************************************************************************/ + +/* Recursive implementation */ +uint64_t fdtw_translate_address(const void *dtb, int node, + uint64_t base_address) +{ + int length, local_bus_node; + const char *node_name; + uint64_t global_address; + + local_bus_node = fdt_parent_offset(dtb, node); + node_name = fdt_get_name(dtb, local_bus_node, NULL); + + /* + * In the example given above, starting from the leaf node: + * uart@a000 represents the current node + * iofpga@3,00000000 represents the local bus + * motherboard represents the parent bus + */ + + /* Read the ranges property */ + const struct fdt_property *property = fdt_get_property(dtb, + local_bus_node, "ranges", &length); + + if (property == NULL) { + if (local_bus_node == 0) { + /* + * root node doesn't have range property as addresses + * are in CPU address space. + */ + return base_address; + } + INFO("DT: Couldn't find ranges property in node %s\n", + node_name); + return ILLEGAL_ADDR; + } else if (length == 0) { + /* empty ranges indicates identity map to parent bus */ + return fdtw_translate_address(dtb, local_bus_node, base_address); + } + + VERBOSE("DT: Translation lookup in node %s at offset %d\n", node_name, + local_bus_node); + global_address = fdtw_search_all_xlat_entries(dtb, property, + local_bus_node, base_address); + + if (global_address == ILLEGAL_ADDR) { + return ILLEGAL_ADDR; + } + + /* Translate the local device address recursively */ + return fdtw_translate_address(dtb, local_bus_node, global_address); +} + +/* + * For every CPU node (`/cpus/cpu@n`) in an FDT, execute a callback passing a + * pointer to the FDT and the offset of the CPU node. If the return value of the + * callback is negative, it is treated as an error and the loop is aborted. In + * this situation, the value of the callback is returned from the function. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +int fdtw_for_each_cpu(const void *dtb, + int (*callback)(const void *dtb, int node, uintptr_t mpidr)) +{ + int ret = 0; + int parent, node = 0; + + parent = fdt_path_offset(dtb, "/cpus"); + if (parent < 0) { + return parent; + } + + fdt_for_each_subnode(node, dtb, parent) { + const char *name; + int len; + + uintptr_t mpidr = 0U; + + name = fdt_get_name(dtb, node, &len); + if (strncmp(name, "cpu@", 4) != 0) { + continue; + } + + ret = fdt_get_reg_props_by_index(dtb, node, 0, &mpidr, NULL); + if (ret < 0) { + break; + } + + ret = callback(dtb, node, mpidr); + if (ret < 0) { + break; + } + } + + return ret; +} diff --git a/arm-trusted-firmware/common/fdt_wrappers.mk b/arm-trusted-firmware/common/fdt_wrappers.mk new file mode 100644 index 0000000..62b8c6e --- /dev/null +++ b/arm-trusted-firmware/common/fdt_wrappers.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +FDT_WRAPPERS_SOURCES := common/fdt_wrappers.c diff --git a/arm-trusted-firmware/common/image_decompress.c b/arm-trusted-firmware/common/image_decompress.c new file mode 100644 index 0000000..a4586ae --- /dev/null +++ b/arm-trusted-firmware/common/image_decompress.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +static uintptr_t decompressor_buf_base; +static uint32_t decompressor_buf_size; +static decompressor_t *decompressor; +static struct image_info saved_image_info; + +void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, + decompressor_t *_decompressor) +{ + decompressor_buf_base = buf_base; + decompressor_buf_size = buf_size; + decompressor = _decompressor; +} + +void image_decompress_prepare(struct image_info *info) +{ + /* + * If the image is compressed, it should be loaded into the temporary + * buffer instead of its final destination. We save image_info, then + * override ->image_base and ->image_max_size so that load_image() will + * transfer the compressed data to the temporary buffer. + */ + saved_image_info = *info; + info->image_base = decompressor_buf_base; + info->image_max_size = decompressor_buf_size; +} + +int image_decompress(struct image_info *info) +{ + uintptr_t compressed_image_base, image_base, work_base; + uint32_t compressed_image_size, work_size; + int ret; + + /* + * The size of compressed data has been filled by load_image(). + * Read it out before restoring image_info. + */ + compressed_image_size = info->image_size; + compressed_image_base = info->image_base; + *info = saved_image_info; + + assert(compressed_image_size <= decompressor_buf_size); + + image_base = info->image_base; + + /* + * Use the rest of the temporary buffer as workspace of the + * decompressor since the decompressor may need additional memory. + */ + work_base = compressed_image_base + compressed_image_size; + work_size = decompressor_buf_size - compressed_image_size; + + ret = decompressor(&compressed_image_base, compressed_image_size, + &image_base, info->image_max_size, + work_base, work_size); + if (ret) { + ERROR("Failed to decompress image (err=%d)\n", ret); + return ret; + } + + /* image_base is updated to the final pos when decompressor() exits. */ + info->image_size = image_base - info->image_base; + + flush_dcache_range(info->image_base, info->image_size); + + return 0; +} diff --git a/arm-trusted-firmware/common/runtime_svc.c b/arm-trusted-firmware/common/runtime_svc.c new file mode 100644 index 0000000..a2c0c09 --- /dev/null +++ b/arm-trusted-firmware/common/runtime_svc.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * The 'rt_svc_descs' array holds the runtime service descriptors exported by + * services by placing them in the 'rt_svc_descs' linker section. + * The 'rt_svc_descs_indices' array holds the index of a descriptor in the + * 'rt_svc_descs' array. When an SMC arrives, the OEN[29:24] bits and the call + * type[31] bit in the function id are combined to get an index into the + * 'rt_svc_descs_indices' array. This gives the index of the descriptor in the + * 'rt_svc_descs' array which contains the SMC handler. + ******************************************************************************/ +uint8_t rt_svc_descs_indices[MAX_RT_SVCS]; + +#define RT_SVC_DECS_NUM ((RT_SVC_DESCS_END - RT_SVC_DESCS_START)\ + / sizeof(rt_svc_desc_t)) + +/******************************************************************************* + * Function to invoke the registered `handle` corresponding to the smc_fid in + * AArch32 mode. + ******************************************************************************/ +uintptr_t handle_runtime_svc(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags) +{ + u_register_t x1, x2, x3, x4; + unsigned int index; + unsigned int idx; + const rt_svc_desc_t *rt_svc_descs; + + assert(handle != NULL); + idx = get_unique_oen_from_smc_fid(smc_fid); + assert(idx < MAX_RT_SVCS); + + index = rt_svc_descs_indices[idx]; + if (index >= RT_SVC_DECS_NUM) + SMC_RET1(handle, SMC_UNK); + + rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; + + get_smc_params_from_ctx(handle, x1, x2, x3, x4); + + return rt_svc_descs[index].handle(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); +} + +/******************************************************************************* + * Simple routine to sanity check a runtime service descriptor before using it + ******************************************************************************/ +static int32_t validate_rt_svc_desc(const rt_svc_desc_t *desc) +{ + if (desc == NULL) + return -EINVAL; + + if (desc->start_oen > desc->end_oen) + return -EINVAL; + + if (desc->end_oen >= OEN_LIMIT) + return -EINVAL; + + if ((desc->call_type != SMC_TYPE_FAST) && + (desc->call_type != SMC_TYPE_YIELD)) + return -EINVAL; + + /* A runtime service having no init or handle function doesn't make sense */ + if ((desc->init == NULL) && (desc->handle == NULL)) + return -EINVAL; + + return 0; +} + +/******************************************************************************* + * This function calls the initialisation routine in the descriptor exported by + * a runtime service. Once a descriptor has been validated, its start & end + * owning entity numbers and the call type are combined to form a unique oen. + * The unique oen is used as an index into the 'rt_svc_descs_indices' array. + * The index of the runtime service descriptor is stored at this index. + ******************************************************************************/ +void __init runtime_svc_init(void) +{ + int rc = 0; + uint8_t index, start_idx, end_idx; + rt_svc_desc_t *rt_svc_descs; + + /* Assert the number of descriptors detected are less than maximum indices */ + assert((RT_SVC_DESCS_END >= RT_SVC_DESCS_START) && + (RT_SVC_DECS_NUM < MAX_RT_SVCS)); + + /* If no runtime services are implemented then simply bail out */ + if (RT_SVC_DECS_NUM == 0U) + return; + + /* Initialise internal variables to invalid state */ + (void)memset(rt_svc_descs_indices, -1, sizeof(rt_svc_descs_indices)); + + rt_svc_descs = (rt_svc_desc_t *) RT_SVC_DESCS_START; + for (index = 0U; index < RT_SVC_DECS_NUM; index++) { + rt_svc_desc_t *service = &rt_svc_descs[index]; + + /* + * An invalid descriptor is an error condition since it is + * difficult to predict the system behaviour in the absence + * of this service. + */ + rc = validate_rt_svc_desc(service); + if (rc != 0) { + ERROR("Invalid runtime service descriptor %p\n", + (void *) service); + panic(); + } + + /* + * The runtime service may have separate rt_svc_desc_t + * for its fast smc and yielding smc. Since the service itself + * need to be initialized only once, only one of them will have + * an initialisation routine defined. Call the initialisation + * routine for this runtime service, if it is defined. + */ + if (service->init != NULL) { + rc = service->init(); + if (rc != 0) { + ERROR("Error initializing runtime service %s\n", + service->name); + continue; + } + } + + /* + * Fill the indices corresponding to the start and end + * owning entity numbers with the index of the + * descriptor which will handle the SMCs for this owning + * entity range. + */ + start_idx = (uint8_t)get_unique_oen(service->start_oen, + service->call_type); + end_idx = (uint8_t)get_unique_oen(service->end_oen, + service->call_type); + assert(start_idx <= end_idx); + assert(end_idx < MAX_RT_SVCS); + for (; start_idx <= end_idx; start_idx++) + rt_svc_descs_indices[start_idx] = index; + } +} diff --git a/arm-trusted-firmware/common/tf_crc32.c b/arm-trusted-firmware/common/tf_crc32.c new file mode 100644 index 0000000..b33d36e --- /dev/null +++ b/arm-trusted-firmware/common/tf_crc32.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +/* compute CRC using Arm intrinsic function + * + * This function is useful for the platforms with the CPU ARMv8.0 + * (with CRC instructions supported), and onwards. + * Platforms with CPU ARMv8.0 should make sure to add a compile switch + * '-march=armv8-a+crc" for successful compilation of this file. + * + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: the size of the buffer + * + * Return calculated CRC value + */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + assert(buf != NULL); + + uint32_t calc_crc = ~crc; + const unsigned char *local_buf = buf; + size_t local_size = size; + + /* + * calculate CRC over byte data + */ + while (local_size != 0UL) { + calc_crc = __crc32b(calc_crc, *local_buf); + local_buf++; + local_size--; + } + + return ~calc_crc; +} diff --git a/arm-trusted-firmware/common/tf_log.c b/arm-trusted-firmware/common/tf_log.c new file mode 100644 index 0000000..68f1be4 --- /dev/null +++ b/arm-trusted-firmware/common/tf_log.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* Set the default maximum log level to the `LOG_LEVEL` build flag */ +static unsigned int max_log_level = LOG_LEVEL; + +/* + * The common log function which is invoked by TF-A code. + * This function should not be directly invoked and is meant to be + * only used by the log macros defined in debug.h. The function + * expects the first character in the format string to be one of the + * LOG_MARKER_* macros defined in debug.h. + */ +void tf_log(const char *fmt, ...) +{ + unsigned int log_level; + va_list args; + const char *prefix_str; + + /* We expect the LOG_MARKER_* macro as the first character */ + log_level = fmt[0]; + + /* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */ + assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE)); + assert((log_level % 10U) == 0U); + + if (log_level > max_log_level) + return; + + prefix_str = plat_log_get_prefix(log_level); + + while (*prefix_str != '\0') { + (void)putchar(*prefix_str); + prefix_str++; + } + + va_start(args, fmt); + (void)vprintf(fmt + 1, args); + va_end(args); +} + +void tf_log_newline(const char log_fmt[2]) +{ + unsigned int log_level = log_fmt[0]; + + /* Verify that log_level is one of LOG_MARKER_* macro defined in debug.h */ + assert((log_level > 0U) && (log_level <= LOG_LEVEL_VERBOSE)); + assert((log_level % 10U) == 0U); + + if (log_level > max_log_level) + return; + + putchar('\n'); +} + +/* + * The helper function to set the log level dynamically by platform. The + * maximum log level is determined by `LOG_LEVEL` build flag at compile time + * and this helper can set a lower (or equal) log level than the one at compile. + */ +void tf_log_set_max_level(unsigned int log_level) +{ + assert(log_level <= LOG_LEVEL_VERBOSE); + assert((log_level % 10U) == 0U); + + /* Cap log_level to the compile time maximum. */ + if (log_level <= (unsigned int)LOG_LEVEL) + max_log_level = log_level; +} diff --git a/arm-trusted-firmware/common/uuid.c b/arm-trusted-firmware/common/uuid.c new file mode 100644 index 0000000..ac6db50 --- /dev/null +++ b/arm-trusted-firmware/common/uuid.c @@ -0,0 +1,134 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +/* Return the hex nibble value of a char */ +static int8_t hex_val(char hex) +{ + int8_t val = 0; + + if ((hex >= '0') && (hex <= '9')) { + val = (int8_t)(hex - '0'); + } else if ((hex >= 'a') && (hex <= 'f')) { + val = (int8_t)(hex - 'a' + 0xa); + } else if ((hex >= 'A') && (hex <= 'F')) { + val = (int8_t)(hex - 'A' + 0xa); + } else { + val = -1; + } + + return val; +} + +/* + * Read hex_src_len hex characters from hex_src, convert to bytes and + * store in buffer pointed to by dest + */ +static int read_hex(uint8_t *dest, char *hex_src, unsigned int hex_src_len) +{ + int8_t nibble; + uint8_t byte; + + /* + * The string length must be a multiple of 2 to represent an + * exact number of bytes. + */ + assert((hex_src_len % 2U) == 0U); + + for (unsigned int i = 0U; i < (hex_src_len / 2U); i++) { + nibble = 0; + byte = 0U; + + nibble = hex_val(hex_src[2U * i]); + if (nibble < 0) { + return -1; + } + byte = (uint8_t)nibble; + byte <<= 4U; + + nibble = hex_val(hex_src[(2U * i) + 1U]); + if (nibble < 0) { + return -1; + } + byte |= (uint8_t)nibble; + + *dest = byte; + dest++; + } + + return 0; +} + +/* Parse UUIDs of the form aabbccdd-eeff-4099-8877-665544332211 */ +int read_uuid(uint8_t *dest, char *uuid) +{ + int err; + uint8_t *dest_start = dest; + + /* Check that we have enough characters */ + if (strnlen(uuid, UUID_STRING_LENGTH) != UUID_STRING_LENGTH) { + WARN("UUID string is too short\n"); + return -EINVAL; + } + + /* aabbccdd */ + err = read_hex(dest, uuid, 8); + uuid += 8; + dest += 4; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* eeff */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 4099 */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 8877 */ + err |= read_hex(dest, uuid, 4); + uuid += 4; + dest += 2; + + /* Check for '-' */ + err |= ((*uuid == '-') ? 0 : -1); + uuid++; + + /* 665544332211 */ + err |= read_hex(dest, uuid, 12); + uuid += 12; + dest += 6; + + if (err < 0) { + WARN("Error parsing UUID\n"); + /* Clear the buffer on error */ + memset((void *)dest_start, '\0', UUID_BYTES_LENGTH * sizeof(uint8_t)); + return -EINVAL; + } + + return 0; +} + diff --git a/arm-trusted-firmware/dco.txt b/arm-trusted-firmware/dco.txt new file mode 100644 index 0000000..8201f99 --- /dev/null +++ b/arm-trusted-firmware/dco.txt @@ -0,0 +1,37 @@ +Developer Certificate of Origin +Version 1.1 + +Copyright (C) 2004, 2006 The Linux Foundation and its contributors. +1 Letterman Drive +Suite D4700 +San Francisco, CA, 94129 + +Everyone is permitted to copy and distribute verbatim copies of this +license document, but changing it is not allowed. + + +Developer's Certificate of Origin 1.1 + +By making a contribution to this project, I certify that: + +(a) The contribution was created in whole or in part by me and I + have the right to submit it under the open source license + indicated in the file; or + +(b) The contribution is based upon previous work that, to the best + of my knowledge, is covered under an appropriate open source + license and I have the right under that license to submit that + work with modifications, whether created in whole or in part + by me, under the same open source license (unless I am + permitted to submit under a different license), as indicated + in the file; or + +(c) The contribution was provided directly to me by some other + person who certified (a), (b) or (c) and I have not modified + it. + +(d) I understand and agree that this project and the contribution + are public and that a record of the contribution (including all + personal information I submit with it, including my sign-off) is + maintained indefinitely and may be redistributed consistent with + this project or the open source license(s) involved. diff --git a/arm-trusted-firmware/docs/Makefile b/arm-trusted-firmware/docs/Makefile new file mode 100644 index 0000000..3dd7ebc --- /dev/null +++ b/arm-trusted-firmware/docs/Makefile @@ -0,0 +1,25 @@ +# +# Copyright (c) 2019-2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Minimal makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = -W +SPHINXBUILD = sphinx-build +SPHINXPROJ = TrustedFirmware-A +SOURCEDIR = . +BUILDDIR = build + +# Put it first so that "make" without argument is like "make help". +help: + @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) + +.PHONY: help Makefile + +# Catch-all target: route all unknown targets to Sphinx using the new +# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS). +%: Makefile + @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O) diff --git a/arm-trusted-firmware/docs/_static/css/custom.css b/arm-trusted-firmware/docs/_static/css/custom.css new file mode 100644 index 0000000..f6f5fa0 --- /dev/null +++ b/arm-trusted-firmware/docs/_static/css/custom.css @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Set the white-space property of tables to normal. + * With this setting sequences of whitespace inside + * a table will collapse into a single whitespace, + * and text will wrap when necessary. + */ +.wy-table-responsive table td { +white-space: normal; +} diff --git a/arm-trusted-firmware/docs/about/acknowledgements.rst b/arm-trusted-firmware/docs/about/acknowledgements.rst new file mode 100644 index 0000000..dfc66c8 --- /dev/null +++ b/arm-trusted-firmware/docs/about/acknowledgements.rst @@ -0,0 +1,22 @@ +Contributor Acknowledgements +============================ + +.. note:: + This file is only relevant for legacy contributions, to acknowledge the + specific contributors referred to in "Arm Limited and Contributors" copyright + notices. As contributors are now encouraged to put their name or company name + directly into the copyright notices, this file is not relevant for new + contributions. See the :ref:`License` document for the correct template to + use for new contributions. + +- Linaro Limited +- Marvell International Ltd. +- NVIDIA Corporation +- NXP Semiconductors +- Socionext Inc. +- STMicroelectronics +- Xilinx, Inc. + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/contact.rst b/arm-trusted-firmware/docs/about/contact.rst new file mode 100644 index 0000000..4440a37 --- /dev/null +++ b/arm-trusted-firmware/docs/about/contact.rst @@ -0,0 +1,56 @@ +Support & Contact +----------------- + +We welcome any feedback on |TF-A| and there are several methods for providing +it or for obtaining support. + +.. warning:: + If you think you have found a security vulnerability, please report this using + the process defined in the :ref:`Security Handling` document. + +Mailing Lists +^^^^^^^^^^^^^ + +Public mailing lists for TF-A and the wider Trusted Firmware project are +hosted on TrustedFirmware.org. The mailing lists can be used for general +enquiries, enhancement requests and issue reports, or to follow and participate +in technical or organizational discussions around the project. These discussions +include design proposals, advance notice of changes and upcoming events. + +The relevant lists for the TF-A project are: + +- `TF-A development`_ +- `TF-A-Tests development`_ + +You can see a `summary of all the lists`_ on the TrustedFirmware.org website. + +Open Tech Forum Call +^^^^^^^^^^^^^^^^^^^^ + +Every other week, we organize a call with all interested TF-A contributors. +Anyone is welcome to join. This is an opportunity to discuss any technical +topic within the community. More details can be found `here`_. + +.. _here: https://www.trustedfirmware.org/meetings/tf-a-technical-forum/ + +Issue Tracker +^^^^^^^^^^^^^ + +Bug reports may be filed on the `issue tracker`_ on the TrustedFirmware.org +website. Using this tracker gives everyone visibility of the known issues in +TF-A. + +Arm Licensees +^^^^^^^^^^^^^ + +Arm licensees have an additional support conduit - they may contact Arm directly +via their partner managers. + +.. _`issue tracker`: https://developer.trustedfirmware.org +.. _`TF-A development`: https://lists.trustedfirmware.org/pipermail/tf-a/ +.. _`TF-A-Tests development`: https://lists.trustedfirmware.org/pipermail/tf-a-tests/ +.. _`summary of all the lists`: https://lists.trustedfirmware.org + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/features.rst b/arm-trusted-firmware/docs/about/features.rst new file mode 100644 index 0000000..4b7fbe5 --- /dev/null +++ b/arm-trusted-firmware/docs/about/features.rst @@ -0,0 +1,127 @@ +Feature Overview +================ + +This page provides an overview of the current |TF-A| feature set. For a full +description of these features and their implementation details, please see +the documents that are part of the *Components* and *System Design* chapters. + +The :ref:`Change Log & Release Notes` provides details of changes made since the +last release. + +Current features +---------------- + +- Initialization of the secure world, for example exception vectors, control + registers and interrupts for the platform. + +- Library support for CPU specific reset and power down sequences. This + includes support for errata workarounds and the latest Arm DynamIQ CPUs. + +- Drivers to enable standard initialization of Arm System IP, for example + Generic Interrupt Controller (GIC), Cache Coherent Interconnect (CCI), + Cache Coherent Network (CCN), Network Interconnect (NIC) and TrustZone + Controller (TZC). + +- A generic |SCMI| driver to interface with conforming power controllers, for + example the Arm System Control Processor (SCP). + +- SMC (Secure Monitor Call) handling, conforming to the `SMC Calling + Convention`_ using an EL3 runtime services framework. + +- |PSCI| library support for CPU, cluster and system power management + use-cases. + This library is pre-integrated with the AArch64 EL3 Runtime Software, and + is also suitable for integration with other AArch32 EL3 Runtime Software, + for example an AArch32 Secure OS. + +- A minimal AArch32 Secure Payload (*SP_MIN*) to demonstrate |PSCI| library + integration with AArch32 EL3 Runtime Software. + +- Secure Monitor library code such as world switching, EL1 context management + and interrupt routing. + When a Secure-EL1 Payload (SP) is present, for example a Secure OS, the + AArch64 EL3 Runtime Software must be integrated with a Secure Payload + Dispatcher (SPD) component to customize the interaction with the SP. + +- A Test SP and SPD to demonstrate AArch64 Secure Monitor functionality and SP + interaction with PSCI. + +- SPDs for the `OP-TEE Secure OS`_, `NVIDIA Trusted Little Kernel`_ + and `Trusty Secure OS`_. + +- A Trusted Board Boot implementation, conforming to all mandatory TBBR + requirements. This includes image authentication, Firmware Update (or + recovery mode), and packaging of the various firmware images into a + Firmware Image Package (FIP). + +- Pre-integration of TBB with the Arm CryptoCell product, to take advantage of + its hardware Root of Trust and crypto acceleration services. + +- Reliability, Availability, and Serviceability (RAS) functionality, including + + - A Secure Partition Manager (SPM) to manage Secure Partitions in + Secure-EL0, which can be used to implement simple management and + security services. + + - An |SDEI| dispatcher to route interrupt-based |SDEI| events. + + - An Exception Handling Framework (EHF) that allows dispatching of EL3 + interrupts to their registered handlers, to facilitate firmware-first + error handling. + +- A dynamic configuration framework that enables each of the firmware images + to be configured at runtime if required by the platform. It also enables + loading of a hardware configuration (for example, a kernel device tree) + as part of the FIP, to be passed through the firmware stages. + This feature is now incorporated inside the firmware configuration framework + (fconf). + +- Support for alternative boot flows, for example to support platforms where + the EL3 Runtime Software is loaded using other firmware or a separate + secure system processor, or where a non-TF-A ROM expects BL2 to be loaded + at EL3. + +- Support for the GCC, LLVM and Arm Compiler 6 toolchains. + +- Support for combining several libraries into a "romlib" image that may be + shared across images to reduce memory footprint. The romlib image is stored + in ROM but is accessed through a jump-table that may be stored + in read-write memory, allowing for the library code to be patched. + +- Support for the Secure Partition Manager Dispatcher (SPMD) component as a + new standard service. + +- Support for ARMv8.3 pointer authentication in the normal and secure worlds. + The use of pointer authentication in the normal world is enabled whenever + architectural support is available, without the need for additional build + flags. + +- Position-Independent Executable (PIE) support. Currently for BL2, BL31, and + TSP, with further support to be added in a future release. + +Still to come +------------- + +- Support for additional platforms. + +- Refinements to Position Independent Executable (PIE) support. + +- Continued support for the FF-A v1.0 (formally known as SPCI) specification, to enable the + use of secure partition management in the secure world. + +- Documentation enhancements. + +- Ongoing support for new architectural features, CPUs and System IP. + +- Ongoing support for new Arm system architecture specifications. + +- Ongoing security hardening, optimization and quality improvements. + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _OP-TEE Secure OS: https://github.com/OP-TEE/optee_os +.. _NVIDIA Trusted Little Kernel: http://nv-tegra.nvidia.com/gitweb/?p=3rdparty/ote_partner/tlk.git;a=summary +.. _Trusty Secure OS: https://source.android.com/security/trusty + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/about/index.rst b/arm-trusted-firmware/docs/about/index.rst new file mode 100644 index 0000000..3a10266 --- /dev/null +++ b/arm-trusted-firmware/docs/about/index.rst @@ -0,0 +1,13 @@ +About +===== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + features + release-information + maintainers + contact + acknowledgements diff --git a/arm-trusted-firmware/docs/about/maintainers.rst b/arm-trusted-firmware/docs/about/maintainers.rst new file mode 100644 index 0000000..b58ea71 --- /dev/null +++ b/arm-trusted-firmware/docs/about/maintainers.rst @@ -0,0 +1,865 @@ +Project Maintenance +=================== + +Trusted Firmware-A (TF-A) is an open governance community project. All +contributions are ultimately merged by the maintainers listed below. Technical +ownership of most parts of the codebase falls on the code owners listed +below. An acknowledgement from these code owners is required before the +maintainers merge a contribution. + +More details may be found in the `Project Maintenance Process`_ document. + +.. |M| replace:: **Mail** +.. |G| replace:: **GitHub ID** +.. |F| replace:: **Files** + +.. _maintainers: + +Maintainers +----------- + +:|M|: Dan Handley +:|G|: `danh-arm`_ +:|M|: Soby Mathew +:|G|: `soby-mathew`_ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Bipin Ravi +:|G|: `bipinravi-arm`_ +:|M|: Joanna Farley +:|G|: `joannafarley-arm`_ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Raghu Krishnamurthy +:|G|: `raghuncstate`_ + + +.. _code owners: + +Code owners +----------- + +Common Code +~~~~~~~~~~~ + +Armv7-A architecture port +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Etienne Carriere +:|G|: `etienne-lms`_ + +Build Definitions for CMake Build System +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: / + +Software Delegated Exception Interface (SDEI) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: services/std_svc/sdei/ + +Trusted Boot +^^^^^^^^^^^^ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: drivers/auth/ + +Secure Partition Manager (SPM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Maksims Svecovs +:|G|: `max-shvetsov`_ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: services/std_svc/spm\* + +Exception Handling Framework (EHF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: bl31/ehf.c + +Realm Management Extension (RME) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Bipin Ravi +:|G|: `bipinravi-arm`_ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ + +Drivers, Libraries and Framework Code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Console API framework +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: drivers/console/ +:|F|: include/drivers/console.h +:|F|: plat/common/aarch64/crash_console_helpers.S + +coreboot support libraries +^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: drivers/coreboot/ +:|F|: include/drivers/coreboot/ +:|F|: include/lib/coreboot.h +:|F|: lib/coreboot/ + +eMMC/UFS drivers +^^^^^^^^^^^^^^^^ +:|M|: Haojian Zhuang +:|G|: `hzhuang1`_ +:|F|: drivers/partition/ +:|F|: drivers/synopsys/emmc/ +:|F|: drivers/synopsys/ufs/ +:|F|: drivers/ufs/ +:|F|: include/drivers/dw_ufs.h +:|F|: include/drivers/ufs.h +:|F|: include/drivers/synopsys/dw_mmc.h + +JTAG DCC console driver +^^^^^^^^^^^^^^^^^^^^^^^ +:M: Michal Simek +:G: `michalsimek`_ +:M: Venkatesh Yadav Abbarapu +:G: `venkatesh`_ +:F: drivers/arm/dcc/ +:F: include/drivers/arm/dcc.h + +Power State Coordination Interface (PSCI) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|F|: lib/psci/ + +DebugFS +^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: lib/debugfs/ + +Firmware Configuration Framework (FCONF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|F|: lib/fconf/ + +Performance Measurement Framework (PMF) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/pmf/ + +Arm CPU libraries +^^^^^^^^^^^^^^^^^ +:|M|: Lauren Wehrmeister +:|G|: `laurenw-arm`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/cpus/ + +Reliability Availability Serviceabilty (RAS) framework +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: lib/extensions/ras/ + +Activity Monitors Unit (AMU) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: lib/extensions/amu/ + +Memory Partitioning And Monitoring (MPAM) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/mpam/ + +Pointer Authentication (PAuth) and Branch Target Identification (BTI) extensions +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|F|: lib/extensions/pauth/ + +Statistical Profiling Extension (SPE) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/spe/ + +Scalable Vector Extension (SVE) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jimmy Brisson +:|G|: `theotherjimmy`_ +:|F|: lib/extensions/sve/ + +Standard C library +^^^^^^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/libc/ + +Library At ROM (ROMlib) +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|F|: lib/romlib/ + +Translation tables (``xlat_tables``) library +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: lib/xlat\_tables_\*/ + +IO abstraction layer +^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: drivers/io/ + +GIC driver +^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Olivier Deprez +:|G|: `odeprez`_ +:|F|: drivers/arm/gic/ + +Libfdt wrappers +^^^^^^^^^^^^^^^ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: common/fdt_wrappers.c + +Firmware Encryption Framework +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: drivers/io/io_encrypted.c +:|F|: include/drivers/io/io_encrypted.h +:|F|: include/tools_share/firmware_encrypted.h + +Measured Boot +^^^^^^^^^^^^^ +:|M|: Alexei Fedorov +:|G|: `AlexeiFedorov`_ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|F|: drivers/measured_boot +:|F|: include/drivers/measured_boot +:|F|: plat/arm/board/fvp/fvp_measured_boot.c + +System Control and Management Interface (SCMI) Server +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Etienne Carriere +:|G|: `etienne-lms`_ +:|M|: Peng Fan +:|G|: `MrVan`_ +:|F|: drivers/scmi-msg +:|F|: include/drivers/scmi\* + +Max Power Mitigation Mechanism (MPMM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: include/lib/mpmm/ +:|F|: lib/mpmm/ + +Granule Protection Tables Library (GPT-RME) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Mark Dykes +:|G|: `mardyk01`_ +:|M|: John Powell +:|G|: `john-powell-arm`_ +:|F|: lib/gpt_rme +:|F|: include/lib/gpt_rme + +Platform Ports +~~~~~~~~~~~~~~ + +Allwinner ARMv8 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Samuel Holland +:|G|: `smaeul`_ +:|F|: docs/plat/allwinner.rst +:|F|: plat/allwinner/ +:|F|: drivers/allwinner/ + +Amlogic Meson S905 (GXBB) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|F|: docs/plat/meson-gxbb.rst +:|F|: drivers/amlogic/ +:|F|: plat/amlogic/gxbb/ + +Amlogic Meson S905x (GXL) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Remi Pommarel +:|G|: `remi-triplefault`_ +:|F|: docs/plat/meson-gxl.rst +:|F|: plat/amlogic/gxl/ + +Amlogic Meson S905X2 (G12A) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Carlo Caione +:|G|: `carlocaione`_ +:|F|: docs/plat/meson-g12a.rst +:|F|: plat/amlogic/g12a/ + +Amlogic Meson A113D (AXG) platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Carlo Caione +:|G|: `carlocaione`_ +:|F|: docs/plat/meson-axg.rst +:|F|: plat/amlogic/axg/ + +Arm FPGA platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|M|: Javier Almansa Sobrino +:|G|: `javieralso-arm`_ +:|F|: plat/arm/board/arm_fpga + +Arm FVP Platform port +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Madhukar Pappireddy +:|G|: `madhukar-Arm`_ +:|F|: plat/arm/board/fvp + +Arm Juno Platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: plat/arm/board/juno + +Arm Morello and N1SDP Platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manoj Kumar +:|G|: `manojkumar-arm`_ +:|M|: Chandni Cherukuri +:|G|: `chandnich`_ +:|F|: plat/arm/board/morello +:|F|: plat/arm/board/n1sdp + +Arm Rich IoT Platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Abdellatif El Khlifi +:|G|: `abdellatif-elkhlifi`_ +:|M|: Vishnu Banavath +:|G|: `vishnu-banavath`_ +:|F|: plat/arm/board/corstone700 +:|F|: plat/arm/board/a5ds +:|F|: plat/arm/board/corstone1000 + +Arm Reference Design platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Thomas Abraham +:|G|: `thomas-arm`_ +:|M|: Vijayenthiran Subramaniam +:|G|: `vijayenthiran-arm`_ +:|F|: plat/arm/css/sgi/ +:|F|: plat/arm/board/rde1edge/ +:|F|: plat/arm/board/rdn1edge/ +:|F|: plat/arm/board/rdn2/ +:|F|: plat/arm/board/rdv1/ +:|F|: plat/arm/board/rdv1mc/ +:|F|: plat/arm/board/sgi575/ + +Arm Total Compute platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Arunachalam Ganapathy +:|G|: `arugan02`_ +:|M|: Usama Arif +:|G|: `uarif1`_ +:|F|: plat/arm/board/tc + +HiSilicon HiKey and HiKey960 platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Haojian Zhuang +:|G|: `hzhuang1`_ +:|F|: docs/plat/hikey.rst +:|F|: docs/plat/hikey960.rst +:|F|: plat/hisilicon/hikey/ +:|F|: plat/hisilicon/hikey960/ + +HiSilicon Poplar platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Shawn Guo +:|G|: `shawnguo2`_ +:|F|: docs/plat/poplar.rst +:|F|: plat/hisilicon/poplar/ + +Intel SocFPGA platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Tien Hock Loh +:|G|: `thloh85-intel`_ +:|M|: Hadi Asyrafi +:|G|: mabdulha +:|F|: plat/intel/soc +:|F|: drivers/intel/soc/ + +MediaTek platform ports +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Rex-BC Chen +:|G|: `mtk-rex-bc-chen`_ +:|M|: Leon Chen +:|G|: `leon-chen-mtk`_ +:|F|: docs/plat/mt\*.rst +:|F|: plat/mediatek/ + +Marvell platform ports and SoC drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Konstantin Porotchkin +:|G|: `kostapr`_ +:|F|: docs/plat/marvell/ +:|F|: plat/marvell/ +:|F|: drivers/marvell/ +:|F|: tools/marvell/ + +NVidia platform ports +^^^^^^^^^^^^^^^^^^^^^ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/plat/nvidia-tegra.rst +:|F|: include/lib/cpus/aarch64/denver.h +:|F|: lib/cpus/aarch64/denver.S +:|F|: plat/nvidia/ + +NXP i.MX 7 WaRP7 platform port and SoC drivers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Bryan O'Donoghue +:|G|: `bryanodonoghue`_ +:|M|: Jun Nie +:|G|: `niej`_ +:|F|: docs/plat/warp7.rst +:|F|: plat/imx/common/ +:|F|: plat/imx/imx7/ +:|F|: drivers/imx/timer/ +:|F|: drivers/imx/uart/ +:|F|: drivers/imx/usdhc/ + +NXP i.MX 8 platform port +^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Peng Fan +:|G|: `MrVan`_ +:|F|: docs/plat/imx8.rst +:|F|: plat/imx/ + +NXP i.MX8M platform port +^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jacky Bai +:|G|: `JackyBai`_ +:|F|: docs/plat/imx8m.rst +:|F|: plat/imx/imx8m/ + +NXP QorIQ Layerscape common code for platform ports +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Pankaj Gupta +:|G|: `pangupta`_ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: docs/plat/nxp/ +:|F|: plat/nxp/ +:|F|: drivers/nxp/ +:|F|: tools/nxp/ + +NXP SoC Part LX2160A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Pankaj Gupta +:|G|: `pangupta`_ +:|F|: plat/nxp/soc-lx2160a +:|F|: plat/nxp/soc-lx2160a/lx2162aqds +:|F|: plat/nxp/soc-lx2160a/lx2160aqds +:|F|: plat/nxp/soc-lx2160a/lx2160ardb + +NXP SoC Part LS1028A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1028a +:|F|: plat/nxp/soc-ls1028a/ls1028ardb + +NXP SoC Part LS1043A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1043a +:|F|: plat/nxp/soc-ls1043a/ls1043ardb + +NXP SoC Part LS1046A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1046a +:|F|: plat/nxp/soc-ls1046a/ls1046ardb +:|F|: plat/nxp/soc-ls1046a/ls1046afrwy +:|F|: plat/nxp/soc-ls1046a/ls1046aqds + +NXP SoC Part LS1088A and its platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jiafei Pan +:|G|: `JiafeiPan`_ +:|F|: plat/nxp/soc-ls1088a +:|F|: plat/nxp/soc-ls1088a/ls1088ardb +:|F|: plat/nxp/soc-ls1088a/ls1088aqds + +QEMU platform port +^^^^^^^^^^^^^^^^^^ +:|M|: Jens Wiklander +:|G|: `jenswi-linaro`_ +:|F|: docs/plat/qemu.rst +:|F|: plat/qemu/ + +QTI platform port +^^^^^^^^^^^^^^^^^ +:|M|: Saurabh Gorecha +:|G|: `sgorecha`_ +:|M|: Lachit Patel +:|G|: `lachitp`_ +:|M|: Sreevyshanavi Kare +:|G|: `sreekare`_ +:|M|: QTI TF Maintainers +:|F|: docs/plat/qti.rst +:|F|: plat/qti/ + +QTI MSM8916 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Stephan Gerhold +:|G|: `stephan-gh`_ +:|M|: Nikita Travkin +:|G|: `TravMurav`_ +:|F|: docs/plat/qti-msm8916.rst +:|F|: plat/qti/msm8916/ + +Raspberry Pi 3 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Ying-Chun Liu (PaulLiu) +:|G|: `grandpaul`_ +:|F|: docs/plat/rpi3.rst +:|F|: plat/rpi/rpi3/ +:|F|: plat/rpi/common/ +:|F|: drivers/rpi3/ +:|F|: include/drivers/rpi3/ + +Raspberry Pi 4 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Andre Przywara +:|G|: `Andre-ARM`_ +:|F|: docs/plat/rpi4.rst +:|F|: plat/rpi/rpi4/ +:|F|: plat/rpi/common/ +:|F|: drivers/rpi3/ +:|F|: include/drivers/rpi3/ + +Renesas rcar-gen3 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Jorge Ramirez-Ortiz +:|G|: `ldts`_ +:|M|: Marek Vasut +:|G|: `marex`_ +:|F|: docs/plat/rcar-gen3.rst +:|F|: plat/renesas/common +:|F|: plat/renesas/rcar +:|F|: drivers/renesas/common +:|F|: drivers/renesas/rcar +:|F|: tools/renesas/rcar_layout_create + +Renesas RZ/G2 platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Biju Das +:|G|: `bijucdas`_ +:|M|: Marek Vasut +:|G|: `marex`_ +:|M|: Lad Prabhakar +:|G|: `prabhakarlad`_ +:|F|: docs/plat/rz-g2.rst +:|F|: plat/renesas/common +:|F|: plat/renesas/rzg +:|F|: drivers/renesas/common +:|F|: drivers/renesas/rzg +:|F|: tools/renesas/rzg_layout_create + +RockChip platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Tony Xie +:|G|: `TonyXie06`_ +:|G|: `rockchip-linux`_ +:|M|: Heiko Stuebner +:|G|: `mmind`_ +:|M|: Julius Werner +:|G|: `jwerner-chromium`_ +:|F|: plat/rockchip/ + +STM32MP1 platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Yann Gautier +:|G|: `Yann-lms`_ +:|F|: docs/plat/stm32mp1.rst +:|F|: drivers/st/ +:|F|: fdts/stm32\* +:|F|: include/drivers/st/ +:|F|: include/dt-bindings/\*/stm32\* +:|F|: plat/st/ +:|F|: tools/stm32image/ + +Synquacer platform port +^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: docs/plat/synquacer.rst +:|F|: plat/socionext/synquacer/ + +Texas Instruments platform port +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Nishanth Menon +:|G|: `nmenon`_ +:|F|: docs/plat/ti-k3.rst +:|F|: plat/ti/ + +UniPhier platform port +^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Orphan +:|F|: docs/plat/socionext-uniphier.rst +:|F|: plat/socionext/uniphier/ + +Xilinx platform port +^^^^^^^^^^^^^^^^^^^^ +:|M|: Michal Simek +:|G|: `michalsimek`_ +:|M|: Venkatesh Yadav Abbarapu +:|G|: `venkatesh`_ +:|F|: docs/plat/xilinx-zynqmp.rst +:|F|: plat/xilinx/ + + +Secure Payloads and Dispatchers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +OP-TEE dispatcher +^^^^^^^^^^^^^^^^^ +:|M|: Jens Wiklander +:|G|: `jenswi-linaro`_ +:|F|: docs/components/spd/optee-dispatcher.rst +:|F|: services/spd/opteed/ + +TLK/Trusty secure payloads +^^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/components/spd/tlk-dispatcher.rst +:|F|: docs/components/spd/trusty-dispatcher.rst +:|F|: include/bl32/payloads/tlk.h +:|F|: services/spd/tlkd/ +:|F|: services/spd/trusty/ + +Test Secure Payload (TSP) +^^^^^^^^^^^^^^^^^^^^^^^^^ +:|M|: Manish Badarkhe +:|G|: `ManishVB-Arm`_ +:|F|: bl32/tsp/ +:|F|: services/spd/tspd/ + +Tools +~~~~~ + +Fiptool +^^^^^^^ +:|M|: Joao Alves +:|G|: `J-Alves`_ +:|F|: tools/fiptool/ + +Cert_create tool +^^^^^^^^^^^^^^^^ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|F|: tools/cert_create/ + +Encrypt_fw tool +^^^^^^^^^^^^^^^ +:|M|: Sumit Garg +:|G|: `b49020`_ +:|F|: tools/encrypt_fw/ + +Sptool +^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: tools/sptool/ + +Build system +^^^^^^^^^^^^ +:|M|: Manish Pandey +:|G|: `manish-pandey-arm`_ +:|F|: Makefile +:|F|: make_helpers/ + +Threat Model +~~~~~~~~~~~~~ +:|M|: Zelalem Aweke +:|G|: `zelalem-aweke`_ +:|M|: Sandrine Bailleux +:|G|: `sandrine-bailleux-arm`_ +:|M|: Joanna Farley +:|G|: `joannafarley-arm`_ +:|M|: Raghu Krishnamurthy +:|G|: `raghuncstate`_ +:|M|: Varun Wadekar +:|G|: `vwadekar`_ +:|F|: docs/threat_model/ + +Conventional Changelog Extensions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +:|M|: Chris Kay +:|G|: `CJKay`_ +:|F|: tools/conventional-changelog-tf-a + +.. _AlexeiFedorov: https://github.com/AlexeiFedorov +.. _Andre-ARM: https://github.com/Andre-ARM +.. _Anson-Huang: https://github.com/Anson-Huang +.. _bijucdas: https://github.com/bijucdas +.. _bryanodonoghue: https://github.com/bryanodonoghue +.. _b49020: https://github.com/b49020 +.. _carlocaione: https://github.com/carlocaione +.. _danh-arm: https://github.com/danh-arm +.. _etienne-lms: https://github.com/etienne-lms +.. _glneo: https://github.com/glneo +.. _grandpaul: https://github.com/grandpaul +.. _hzhuang1: https://github.com/hzhuang1 +.. _JackyBai: https://github.com/JackyBai +.. _jenswi-linaro: https://github.com/jenswi-linaro +.. _jwerner-chromium: https://github.com/jwerner-chromium +.. _kostapr: https://github.com/kostapr +.. _lachitp: https://github.com/lachitp +.. _ldts: https://github.com/ldts +.. _marex: https://github.com/marex +.. _masahir0y: https://github.com/masahir0y +.. _michalsimek: https://github.com/michalsimek +.. _mmind: https://github.com/mmind +.. _MrVan: https://github.com/MrVan +.. _mtk-rex-bc-chen: https://github.com/mtk-rex-bc-chen +.. _leon-chen-mtk: https://github.com/leon-chen-mtk +.. _niej: https://github.com/niej +.. _npoushin: https://github.com/npoushin +.. _prabhakarlad: https://github.com/prabhakarlad +.. _remi-triplefault: https://github.com/repk +.. _rockchip-linux: https://github.com/rockchip-linux +.. _sandrine-bailleux-arm: https://github.com/sandrine-bailleux-arm +.. _sgorecha: https://github.com/sgorecha +.. _shawnguo2: https://github.com/shawnguo2 +.. _smaeul: https://github.com/smaeul +.. _soby-mathew: https://github.com/soby-mathew +.. _sreekare: https://github.com/sreekare +.. _stephan-gh: https://github.com/stephan-gh +.. _thloh85-intel: https://github.com/thloh85-intel +.. _thomas-arm: https://github.com/thomas-arm +.. _TonyXie06: https://github.com/TonyXie06 +.. _TravMurav: https://github.com/TravMurav +.. _vwadekar: https://github.com/vwadekar +.. _venkatesh: https://github.com/vabbarap +.. _Yann-lms: https://github.com/Yann-lms +.. _manish-pandey-arm: https://github.com/manish-pandey-arm +.. _mardyk01: https://github.com/mardyk01 +.. _odeprez: https://github.com/odeprez +.. _bipinravi-arm: https://github.com/bipinravi-arm +.. _joannafarley-arm: https://github.com/joannafarley-arm +.. _ManishVB-Arm: https://github.com/ManishVB-Arm +.. _max-shvetsov: https://github.com/max-shvetsov +.. _javieralso-arm: https://github.com/javieralso-arm +.. _laurenw-arm: https://github.com/laurenw-arm +.. _zelalem-aweke: https://github.com/zelalem-aweke +.. _theotherjimmy: https://github.com/theotherjimmy +.. _J-Alves: https://github.com/J-Alves +.. _madhukar-Arm: https://github.com/madhukar-Arm +.. _john-powell-arm: https://github.com/john-powell-arm +.. _raghuncstate: https://github.com/raghuncstate +.. _CJKay: https://github.com/cjkay +.. _nmenon: https://github.com/nmenon +.. _manojkumar-arm: https://github.com/manojkumar-arm +.. _chandnich: https://github.com/chandnich +.. _abdellatif-elkhlifi: https://github.com/abdellatif-elkhlifi +.. _vishnu-banavath: https://github.com/vishnu-banavath +.. _vijayenthiran-arm: https://github.com/vijayenthiran-arm +.. _arugan02: https://github.com/arugan02 +.. _uarif1: https://github.com/uarif1 +.. _pangupta: https://github.com/pangupta +.. _JiafeiPan: https://github.com/JiafeiPan + +.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/ diff --git a/arm-trusted-firmware/docs/about/release-information.rst b/arm-trusted-firmware/docs/about/release-information.rst new file mode 100644 index 0000000..b3553ae --- /dev/null +++ b/arm-trusted-firmware/docs/about/release-information.rst @@ -0,0 +1,71 @@ +Release Processes +================= + +Project Release Cadence +----------------------- + +The project currently aims to do a release once every 6 months which will be +tagged on the master branch. There will be a code freeze (stop merging +non-essential changes) up to 4 weeks prior to the target release date. The release +candidates will start appearing after this and only bug fixes or updates +required for the release will be merged. The maintainers are free to use their +judgement on what changes are essential for the release. A release branch may be +created after code freeze if there are significant changes that need merging onto +the integration branch during the merge window. + +The release testing will be performed on release candidates and depending on +issues found, additional release candidates may be created to fix the issues. + +:: + + |<----------6 months---------->| + |<---4 weeks--->| |<---4 weeks--->| + +-----------------------------------------------------------> time + | | | | + code freeze ver w.x code freeze ver y.z + + +Upcoming Releases +~~~~~~~~~~~~~~~~~ + +These are the estimated dates for the upcoming release. These may change +depending on project requirement and partner feedback. + ++-----------------+---------------------------+------------------------------+ +| Release Version | Target Date | Expected Code Freeze | ++=================+===========================+==============================+ +| v2.0 | 1st week of Oct '18 | 1st week of Sep '18 | ++-----------------+---------------------------+------------------------------+ +| v2.1 | 5th week of Mar '19 | 1st week of Mar '19 | ++-----------------+---------------------------+------------------------------+ +| v2.2 | 4th week of Oct '19 | 1st week of Oct '19 | ++-----------------+---------------------------+------------------------------+ +| v2.3 | 4th week of Apr '20 | 1st week of Apr '20 | ++-----------------+---------------------------+------------------------------+ +| v2.4 | 2nd week of Nov '20 | 4th week of Oct '20 | ++-----------------+---------------------------+------------------------------+ +| v2.5 | 3rd week of May '21 | 5th week of Apr '21 | ++-----------------+---------------------------+------------------------------+ +| v2.6 | 4th week of Nov '21 | 2nd week of Nov '21 | ++-----------------+---------------------------+------------------------------+ +| v2.7 | 2nd week of May '22 | 4th week of Apr '22 | ++-----------------+---------------------------+------------------------------+ + +Removal of Deprecated Interfaces +-------------------------------- + +As mentioned in the :ref:`Platform Compatibility Policy`, this is a live +document cataloging all the deprecated interfaces in TF-A project and the +Release version after which it will be removed. + ++--------------------------------+-------------+---------+---------------------------------------------------------+ +| Interface | Deprecation | Removed | Comments | +| | Date | after | | +| | | Release | | ++================================+=============+=========+=========================================================+ +| STM32MP_USE_STM32IMAGE macro | Dec '21 | 2.7 | FIP is the recommended boot method for STM32MP | ++--------------------------------+-------------+---------+---------------------------------------------------------+ + +-------------- + +*Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/change-log.md b/arm-trusted-firmware/docs/change-log.md new file mode 100644 index 0000000..ab50968 --- /dev/null +++ b/arm-trusted-firmware/docs/change-log.md @@ -0,0 +1,4746 @@ +# Change Log & Release Notes + +This document contains a summary of the new features, changes, fixes and known +issues in each release of Trusted Firmware-A. + +## [2.6.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.5..refs/tags/v2.6) (2021-11-22) + +### âš  BREAKING CHANGES + +- **Architecture** + + - **Activity Monitors Extension (FEAT_AMU)** + + - The public AMU API has been reduced to enablement only + to facilitate refactoring work. These APIs were not previously used. + + **See:** privatize unused AMU APIs ([b4b726e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b4b726ea868359cf683c07337b69fe91a2a6929a)) + + - The `PLAT_AMU_GROUP1_COUNTERS_MASK` platform definition + has been removed. Platforms should specify per-core AMU counter masks + via FCONF or a platform-specific mechanism going forward. + + **See:** remove `PLAT_AMU_GROUP1_COUNTERS_MASK` ([6c8dda1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c8dda19e5f484f8544365fd71d965f0afc39244)) + +- **Libraries** + + - **FCONF** + + - FCONF is no longer added to BL1 and BL2 automatically + when the FCONF Makefile (`fconf.mk`) is included. When including this + Makefile, consider whether you need to add `${FCONF_SOURCES}` and + `${FCONF_DYN_SOURCES}` to `BL1_SOURCES` and `BL2_SOURCES`. + + **See:** clean up source collection ([e04da4c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e04da4c8e132f43218f18ad3b41479ca54bb9263)) + +- **Drivers** + + - **Arm** + + - **Ethos-N** + + - multi-device support + + **See:** multi-device support ([1c65989](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c65989e70c9734defc666e824628620b2060b92)) + +### New Features + +- **Architecture** + + - **Activity Monitors Extension (FEAT_AMU)** + + - enable per-core AMU auxiliary counters ([742ca23](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/742ca2307f4e9f82cb2c21518819425e5bcc0f90)) + + - **Support for the `HCRX_EL2` register (FEAT_HCX)** + + - add build option to enable FEAT_HCX ([cb4ec47](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cb4ec47b5c73e04472984acf821e6be41b98064f)) + + - **Scalable Matrix Extension (FEAT_SME)** + + - enable SME functionality ([dc78e62](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dc78e62d80e64bf4fe5d5bf4844a7bd1696b7c92)) + + - **Scalable Vector Extension (FEAT_SVE)** + + - enable SVE for the secure world ([0c5e7d1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0c5e7d1ce376cabcebebc43dbf238fe4482ab2dc)) + + - **System Register Trace Extensions (FEAT_ETMv4, FEAT_ETE and FEAT_ETEv1.1)** + + - enable trace system registers access from lower NS ELs ([d4582d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4582d30885673987240cf01fd4f5d2e6780e84c)) + - initialize trap settings of trace system registers access ([2031d61](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2031d6166a58623ae59034bc2353fcd2fabe9c30)) + + - **Trace Buffer Extension (FEAT_TRBE)** + + - enable access to trace buffer control registers from lower NS EL ([813524e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/813524ea9d2e4138246b8f77a772299e52fb33bc)) + - initialize trap settings of trace buffer control registers access ([40ff907](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/40ff90747098ed9d2a09894d1a886c10ca76cee6)) + + - **Self-hosted Trace Extension (FEAT_TRF)** + + - enable trace filter control register access from lower NS EL ([8fcd3d9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8fcd3d9600bb2cb6809c6fc68f945ce3ad89633d)) + - initialize trap settings of trace filter control registers access ([5de20ec](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5de20ece38f782c8459f546a08c6a97b9e0f5bc5)) + + - **RME** + + - add context management changes for FEAT_RME ([c5ea4f8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c5ea4f8a6679131010636eb524d2a15b709d0196)) + - add ENABLE_RME build option and support for RMM image ([5b18de0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5b18de09e80f87963df9a2e451c47e2321b8643a)) + - add GPT Library ([1839012](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1839012d5b5d431f7ec307230eae9890a5fe7477)) + - add Realm security state definition ([4693ff7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4693ff7225faadc5ad1bcd1c2fb3fbbb8fe1aed0)) + - add register definitions and helper functions for FEAT_RME ([81c272b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/81c272b3b71af38bc5cfb10bbe5722e328a1578e)) + - add RMM dispatcher (RMMD) ([77c2775](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77c2775323a5ff8b77230f05c0cc57f830e9f153)) + - add Test Realm Payload (TRP) ([50a3056](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/50a3056a3cd33d395e8712e1d1e67a8840bf3db1)) + - add xlat table library changes for FEAT_RME ([3621823](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/362182386bafbda9e6671be921fa30cc20610d30)) + - disable Watchdog for Arm platforms if FEAT_RME enabled ([07e96d1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/07e96d1d2958b6f121476fd391ac67bf8c2c4735)) + - run BL2 in root world when FEAT_RME is enabled ([6c09af9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c09af9f8b36cdfa1dc4d5052f7e4792f63fa88a)) + +- **Platforms** + + - **Allwinner** + + - add R329 support ([13bacd3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/13bacd3bc3e6b76009adf9183e5396b6457eb12c)) + + - **Arm** + + - add FWU support in Arm platforms ([2f1177b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2f1177b2b9ebec3b2fe92607cd771bda1dc9cbfc)) + - add GPT initialization code for Arm platforms ([deb4b3a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/deb4b3a63e3a52f2e9823865a1932f6289ccb7ac)) + - add GPT parser support ([ef1daa4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef1daa420f7b2920b2ee35379de2aefed6ab2605)) + - enable PIE when RESET_TO_SP_MIN=1 ([7285fd5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7285fd5f9aa6d9cc0e0f1dc9c71785b46a88d999)) + + - **FPGA** + + - add ITS autodetection ([d7e39c4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d7e39c43f2f58aabb085ed7b8f461f9ece6002d0)) + - add kernel trampoline ([de9fdb9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/de9fdb9b5925ae08137d4212a85e9a1d319509c9)) + - determine GICR base by probing ([93b785f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/93b785f5ae66a6418581c304c83a346e8baa5aa3)) + - query PL011 to learn system frequency ([d850169](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d850169c9c233c4bc413d8319196557b54683688)) + - support GICv4 images ([c69f815](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c69f815b09ab85d3ace8fd2979ffafb1184ec76c)) + - write UART baud base clock frequency into DTB ([422b44f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/422b44fb56db7ca8b1a2f9f706733d7d4c2fdeb1)) + + - **FVP** + + - enable external SP images in BL2 config ([33993a3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/33993a3737737a03ee5a9d386d0a027bdc947c9c)) + - add memory map for FVP platform for FEAT_RME ([c872072](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c8720729726faffc39ec64f3a02440a48c8c305a)) + - add RMM image support for FVP platform ([9d870b7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d870b79c16ef09b0c4a9db18e071c2fa235d1ad)) + - enable trace extension features by default ([cd3f0ae](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cd3f0ae6f855b2998bc09e5c3a458528c92acb90)) + - pass Event Log addr and size from BL1 to BL2 ([0500f44](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0500f4479eb1d0d5ab9e83dac42b633a5ff677dd)) + + - **FVP-R** + + - support for TB-R has been added + - configure system registers to boot rich OS ([28bbbf3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/28bbbf3bf583e0c85004727e694455dfcabd50a4)) + + - **RD** + + - **RD-N2** + + - add support for variant 1 of rd-n2 platform ([fe5d5bb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fe5d5bbfe6bd0f386f92bdc419a7e04d885d5b43)) + - add tzc master source ids for soc dma ([3139270](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3139270693ab0fc6d66fed4fe11e183829b47e2e)) + + - **SGI** + + - add CPU specific handler for Neoverse N2 ([d932a58](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d932a5831e26620d61d171d0fd8bc2f14938e6f1)) + - add CPU specific handler for Neoverse V1 ([cbee43e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cbee43ebd69377bce1c4fa8d40c6fd67f2be2ee4)) + - increase max BL2 size ([7186a29](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7186a29bbfe3044d5e8001ddfe1d9238578e0944)) + - enable AMU for RD-V1-MC ([e8b119e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e8b119e03ad9de5fc440e5929287c94c22fc3946)) + - enable use of PSCI extended state ID format ([7bd64c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7bd64c70e91f73a236b84fb51d5045e308479b5a)) + - introduce platform variant build option ([cfe1506](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cfe1506ee8303d9e0714b3a5b2cd165f76ad5d11)) + + - **TC** + + - enable MPMM ([c19a82b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c19a82bef08df58350f1b6668e0604ff8a5bd46d)) + - Enable SVE for both secure and non-secure world ([10198ea](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10198eab3aa7b0eeba10d9667197816b052ba3e4)) + - populate HW_CONFIG in BL31 ([34a87d7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34a87d74d9fbbe8037431ea5101110a9f1cf30e1)) + - introduce TC1 platform ([6ec0c65](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6ec0c65b09745fd0f4cee44ee3aa99870303f448)) + - add DRAM2 to TZC non-secure region ([76b4a6b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/76b4a6bb208c22b1c5971964a209ff7d54982348)) + + - add bootargs node ([4a840f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4a840f27cd7a05d8e3687aa325adcd019c0d22ee)) + - add cpu capacity to provide scheduling information ([309f593](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/309f5938e610c73cb51b3ba175fed971f49d0888)) + - add Ivy partition ([a19bd32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a19bd32ed14c33571f3715198d47bac9d0f2808e)) + - add support for trusted services ([ca93248](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ca9324819ee308f9b3a4bb004f02a512c8f301f6)) + - update Matterhorn ELP DVFS clock index ([a2f6294](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2f6294c98935895d4592ef7e30058ca6e995f4b)) + - update mhuv2 dts node to align with upstream driver ([63067ce](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/63067ce87e4afa193b2c7f6a4917d1e54b61b000)) + + - **Diphda** + + - adding the diphda platform ([bf3ce99](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bf3ce9937182e5d8d91e058baabb8213acedacdb)) + - disabling non volatile counters in diphda ([7f70cd2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f70cd29235cc5e96ff6b5f509c7e4260bec5610)) + - enabling stack protector for diphda ([c7e4f1c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c7e4f1cfb84136a7521f26e403a6635ffdce4a2b)) + + - **Marvell** + + - introduce t9130_cex7_eval ([d01139f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d01139f3b59a1bc6542e74f52ff3fb26eea23c69)) + + - **Armada** + + - **A8K** + + - allow overriding default paths ([0b702af](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0b702afc3aabc349a513a5b00397b58a62fea634)) + + - **MediaTek** + + - enable software reset for CIRQ ([b3b162f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b3b162f3b48e087f6656513862a6f9e1fa0757b1)) + + - **MT8192** + + - add DFD control in SiP service ([5183e63](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5183e637a0496ad8dfbd8c892bc874ac6a1531bf)) + + - **MT8195** + + - add DFD control in SiP service ([3b994a7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3b994a75306cc487144dd8e2e15433799e62e6f2)) + - add display port control in SiP service ([7eb4223](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7eb42237575eb3f241c9b22efc5fe91368470aa6)) + - remove adsp event from wakeup source ([c260b32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c260b3246b6be27c7463d36ce7f76368c94a8540)) + - add DCM driver ([49d3bd8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49d3bd8c4c80ecd19ecfd74812ff1eaa01478cdd)) + - add EMI MPU basic drivers ([75edd34](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/75edd34ade8efaa8a76c5fd59103454023632989)) + - add SPM suspend driver ([859e346](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/859e346b89461f31df17b76ef25ce9e8d2a7279d)) + - add support for PTP3 ([0481896](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/048189637ead887787bd5bc47b1dfab98f321705)) + - add vcore-dvfs support ([d562130](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d562130ea9637b885135a5efe41cb98f2365754f)) + - support MCUSYS off when system suspend ([d336e09](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d336e093dd9ec917ce69484eae8914d98efa328d)) + + - **NXP** + + - add build macro for BOOT_MODE validation checking ([cd1280e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cd1280ea2e5c8be6f28485a2d5054d06e54e74c1)) + - add CCI and EPU address definition ([6cad59c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6cad59c429b4382ad62aee3a67fa1b3fd4ad38b7)) + - add EESR register definition ([8bfb168](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8bfb16813aff9b3dcbeaa2f77027d44b97f04b6d)) + - add SecMon register definition for ch_3_2 ([66f7884](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/66f7884b5229b1d2977d73d105af1c34cb55f95d)) + - define common macro for ARM registers ([35efe7a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/35efe7a4cea4b3c55b661aac49ef1a85ca8feaa9)) + - define default PSCI features if not defined ([a204785](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2047853224083328ef67cacbc17a2001ba14701)) + - define default SD buffer ([4225ce8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4225ce8b87635287ecf5cd3baaf31ea703a2640b)) + + - **i.MX** + + - **i.MX 8M** + + - add sdei support for i.MX8MN ([ce2be32](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ce2be321e8a5865871810b36c580181ea95a1a64)) + - add sdei support for i.MX8MP ([6b63125](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6b63125c415491417e1c389e4015be5ebdee2841)) + - add SiP call for secondary boot ([9ce232f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ce232fe985a0bb308af459ede8a22629255d4e7)) + - add system_reset2 implementation ([60a0dde](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/60a0dde91bd03f4011c1d52d4d3aea8166e939a0)) + + - **i.MX 8M Mini** + + - enlarge BL33 (U-boot) size in FIP ([d53c9db](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d53c9dbf9ff9c435552b62f47fb95bfe86d025e3)) + + - **i.MX 8M Plus** + + - add imx8mp_private.h to the build ([91566d6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/91566d663b26434813fa674412bb695be1965557)) + - add in BL2 with FIP ([75fbf55](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/75fbf5546b7beca93e4782bc35906f9536392e04)) + - add initial definition to facilitate FIP layout ([f696843](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f696843eab5cf0547b6c6307eaccea25678654c4)) + - enable Trusted Boot ([a16ecd2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a16ecd2cff36b3a8a76d223f4e272e165c941b31)) + + - **Layerscape** + + - add ls1028a soc and board support ([52a1e9f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/52a1e9ff37251987b71b743951038cd8d1fa0ba4)) + + - **LX2** + + - add SUPPORTED_BOOT_MODE definition ([28b3221](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/28b3221aebdd48577e2288a75cd2f7547da514e9)) + + - **LS1028A** + + - add ls1028a soc support ([9d250f0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d250f03d7a38cac86655495879b2151b877db0d)) + + - **LS1028ARDB** + + - add ls1028ardb board support ([34e2112](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34e2112d1a3a8e4ea33a24bdc6505518266333a9)) + + - **QTI** + + - **SC7280** + + - add support for pmk7325 ([b8a0511](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b8a05116ed2a87a9689c4f9be6218a4bce88034a)) + - support for qti sc7280 plat ([46ee50e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/46ee50e0b34e19d383a28bc3b3dadbfb4c07b270)) + + - **Renesas** + + - **R-Car** + + - change process for Suspend To RAM ([731aa26](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/731aa26f38d76645b6d50077c28dffb9b02dd08a)) + + - **R-Car 3** + + - add a DRAM size setting for M3N ([f95d551](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f95d551217a287bd909aa3c82f4ade4986ad7244)) + - add new board revision for Salvator-XS/H3ULCB ([4379a3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4379a3e9744cf3b0844446335aca40357a889b9a)) + - add optional support for gzip-compressed BL33 ([ddf2ca0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ddf2ca03979ea9fad305b1bc59beb6e27f0e1c02)) + - add process of SSCG setting for R-Car D3 ([14f0a08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/14f0a0817297905c03ddf2c4c6040482ef71d744)) + - add process to back up X6 and X7 register's value ([7d58aed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7d58aed3b05fa8c677a7c823c1ca5017a462a3d3)) + - add SYSCEXTMASK bit set/clear in scu_power_up ([63a7a34](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/63a7a34706eedba4d13ce6fc661a634801cf8909)) + - apply ERRATA_A53_1530924 and ERRATA_A57_1319537 ([2892fed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2892fedaf27d8bbc68780a4a2c506c768e81b9f1)) + - change the memory map for OP-TEE ([a4d821a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4d821a5a625d941f95ec39fb51ac4fc07c46c5c)) + - emit RPC status to DT fragment if RPC unlocked ([12c75c8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/12c75c8886a0ee69d7e279a48cbeb8d1602826b3)) + - keep RWDT enabled ([8991086](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/899108601a0c3b08ead5e686d92ea0794700ff35)) + - modify LifeC register setting for R-Car D3 ([5460f82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5460f82806752e419fdd6862e8ca9c5fefbee3f2)) + - modify operation register from SYSCISR to SYSCISCR ([d10f876](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d10f87674ecee54cffe1ab554cc05733fd16c7f0)) + - modify SWDT counter setting for R-Car D3 ([053c134](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/053c134683cf74fbf4efad311815b806821f1436)) + - remove access to RMSTPCRn registers in R-Car D3 ([71f2239](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/71f2239f53cd3137ad6abdaf0334dc53f2f21cb1)) + - update DDR setting for R-Car D3 ([042d710](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/042d710d1d917357c5142b340c79978264d3afb1)) + - update IPL and Secure Monitor Rev.3.0.0 ([c5f5bb1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c5f5bb17abfcf6c0eeb3e6c3d70499de0bd6abc0)) + - use PRR cut to determine DRAM size on M3 ([42ffd27](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/42ffd279dd1a686b19e2f1b69d2e35413d5efeba)) + + - **ST** + + - add a new DDR firewall management ([4584e01](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4584e01dc643665038004f6c8a4f8bd64e14dacb)) + - add a USB DFU stack ([efbd65f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/efbd65fa7b5cf70f20d6b18152741ccdf8a65bb6)) + - add helper to save boot interface ([7e87ba2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7e87ba2598a07facdeb73237dcb350a261ac17b6)) + - add STM32CubeProgrammer support on USB ([afad521](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/afad5214a79259f56bc2003b00859abfe8a18d4d)) + - add STM32MP_EMMC_BOOT option ([214c8a8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/214c8a8d08b2b3c24f12cbc69f497f44851ca524)) + - create new helper for DT access ([ea97bbf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ea97bbf6a001b270fd0a25b4b0d0c382e277f3f8)) + - implement platform functions for SMCCC_ARCH_SOC_ID ([3d20178](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3d201787e8246022b1f193283c12e7cb4bfc83ff)) + - improve FIP image loading from MMC ([18b415b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/18b415be9d631b3e0c3a3caacc5f02edb9413f6b)) + - manage io_policies with FCONF ([d5a84ee](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d5a84eeaac2c8ce14d3f2662dc9523b4abf41516)) + - use FCONF to configure platform ([29332bc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/29332bcd680ce7e5f864813d9a900360f5e35d41)) + - use FIP to load images ([1d204ee](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1d204ee4ab12893fceb12097bd4f0a074be253b2)) + + - **ST32MP1** + + - add STM32MP_USB_PROGRAMMER target ([fa92fef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fa92fef0a024cdb537fe56c84a0156cc48c1ac2d)) + - add USB DFU support for STM32MP1 ([942f6be](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/942f6be211d4816ad2568d30d807b8fd53d7f981)) + + - **Xilinx** + + - **Versal** + + - add support for SLS mitigation ([302b4df](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/302b4dfb8fb0041959b8593a098ccae6c61e3238)) + + - **ZynqMP** + + - add support for runtime feature config ([578f468](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/578f468ac058bbb60b08f78e2aa2c20cdc601620)) + - sync IOCTL IDs ([38c0b25](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/38c0b2521a0ea0951f4e1ee678ccdbce5fc07a98)) + - add SDEI support ([4143268](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4143268a5ca8f91f1014e0d83edf766946ffff76)) + - add support for XCK26 silicon ([7a30e08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7a30e08b70e7fbb745554d500182bb6e258c5ab8)) + - extend DT description by TF-A ([0a8143d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0a8143dd636d4234dd2e79d32cb49dc80675c68f)) + +- **Bootloader Images** + + - import BL_NOBITS_{BASE,END} when defined ([9aedca0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9aedca021d917c7435aa2a0405972aa9d44493a2)) + +- **Services** + + - **FF-A** + + - adding notifications SMC IDs ([fc3f480](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fc3f480023e3a52460add25f18dd550dde44d9ff)) + - change manifest messaging method ([bb320db](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bb320dbc4751f7ea0c37ffba07d14628e58081d0)) + - feature retrieval through FFA_FEATURES call ([96b71eb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/96b71eb9597efbf4857216cac1caeefc9e8bbf3e)) + - update FF-A version to v1.1 ([e1c732d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e1c732d46fa91231b39209621ead1e5a5fb2c497)) + - add Ivy partition to tb fw config ([1bc02c2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1bc02c2e0f63b6a7863e10cf6189292d42e693db)) + - add support for FFA_SPM_ID_GET ([70c121a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/70c121a258e43dc2462ed528b44d92594ffb27b3)) + - route secure interrupts to SPMC ([8cb99c3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8cb99c3fc3539bb9926e73a1c33fd72f424fc453)) + +- **Libraries** + + - **CPU Support** + + - add support for Hayes CPU ([7bd8dfb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7bd8dfb85a8bf5c22d6a39f4538b89cc748090d1)) + - add support for Hunter CPU ([fb9e5f7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb9e5f7bb76e9764b3ecd7973668c851015fa1b4)) + - add support for Demeter CPU ([f4616ef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f4616efafbc1004f1330f515b898e7617e338875)) + - workaround for Cortex A78 AE erratum 1941500 ([47d6f5f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/47d6f5ff16d1f2ad009d630a381054b10fa0a06f)) + - workaround for Cortex A78 AE erratum 1951502 ([8913047](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8913047a52e646877812617a2d98cff99494487b)) + + - **MPMM** + + - add support for MPMM ([6812078](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/68120783d6d6f99c605e9f746ee0e91e2908feb1)) + + - **OP-TEE** + + - introduce optee_header_is_valid() ([b84a850](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b84a850864c05fef587fcbb301f955428966de64)) + + - **PSCI** + + - require validate_power_state to expose CPU_SUSPEND ([a1d5ac6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a1d5ac6a5aa5d9d18a481de20d272f64a71391f7)) + + - **SMCCC** + + - add bit definition for SMCCC_ARCH_SOC_ID ([96b0596](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/96b0596ea25e1f03b862a5bfaa92add6c3e51a33)) + +- **Drivers** + + - **FWU** + + - add FWU metadata header and build options ([5357f83](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5357f83d4ee89fb831d7e4f6149ae2f652e1b9af)) + - add FWU driver ([0ec3ac6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0ec3ac60d86b75d132e7a63fc09ea47e67f90bbd)) + - avoid booting with an alternate boot source ([4b48f7b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4b48f7b56577a78cdc9a2b47280cb62cbae0f7c3)) + - avoid NV counter upgrade in trial run state ([c0bfc88](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c0bfc88f8e8e03974834cbcacbbfbd5f202a2857)) + - initialize FWU driver in BL2 ([396b339](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/396b339dc20b97ddd75146e03467a255e28f31b9)) + - introduce FWU platform-specific functions declarations ([efb2ced](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/efb2ced256dacbab71ca11cbc87f70f413ca6729)) + + - **I/O** + + - **MTD** + + - offset management for FIP usage ([9a9ea82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9a9ea82948fd2f1459b6351cb0641f3f77b4e6de)) + + - **Measured Boot** + + - add documentation to build and run PoC ([a125c55](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a125c556230501ee0f5ec9f8b0b721625d484a41)) + - move init and teardown functions to platform layer ([47bf3ac](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/47bf3ac31ec84d4b221fdef760c04b5f4416cba4)) + - image hash measurement and recording in BL1 ([48ba034](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/48ba0345f7b42880ec4442d7e90e3e1af95feadd)) + - update tb_fw_config with event log properties ([e742bcd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e742bcdae0d28dc14a2aa0b4ca30f50420bb5ebe)) + + - **MMC** + + - boot partition read support ([5014b52](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5014b52dec0c2527ca85c0fbe9c9281a24cc7b10)) + + - **MTD** + + - **NAND** + + - count bad blocks before a given offset ([bc3eebb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bc3eebb25d5ee340e56047d0e46b81d5af85ff17)) + + - **SCMI** + + - add power domain protocol ([7e4833c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7e4833cdde8235d228f1f1c40f52b989ad5aa98a)) + + - **Arm** + + - **Ethos-N** + + - multi-device support ([1c65989](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c65989e70c9734defc666e824628620b2060b92)) + + - **GIC** + + - **GICv3** + + - detect GICv4 feature at runtime ([858f40e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/858f40e379684fefc8b52c7b9e60576bc3794a69)) + - introduce GIC component identification ([73a643e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/73a643eed9d88910a09ca666bc7ab7f5e532324e)) + - multichip: detect GIC-700 at runtime ([feb7081](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/feb7081863f454b9e465efc074ca669f7a4c783d)) + + - **GIC-600AE** + + - introduce support for Fault Management Unit ([2c248ad](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2c248ade2e958eed33127b4ea767fbb7499f31a7)) + + - **TZC** + + - **TZC-400** + + - update filters by region ([ce7ef9d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ce7ef9d146ce5ca6b9be5ef049377b3817d53d10)) + + - **MediaTek** + + - **APU** + + - add mt8192 APU device apc driver ([f46e1f1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f46e1f18539d6d992c82ae605c2cd2a1d0757fa4)) + - add mt8192 APU iommap regions ([2671f31](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2671f3187249d641c55929c812d6691aeeff502a)) + - add mt8192 APU SiP call support ([ca4c0c2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ca4c0c2e78eb19d442de4608d9096a755b540a37)) + - setup mt8192 APU_S_S_4 and APU_S_S_5 permission ([77b6801](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77b6801966d203e09ca118fad42543e934d73e6f)) + + - **EMI MPU** + + - add MPU support for DSP ([6c4973b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c4973b0a9a75aa83233b696c97d573426eebd98)) + + - **NXP** + + - **DCFG** + + - define RSTCR_RESET_REQ ([6c5d140](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6c5d140ed99cfec47b239acc242c0f3db1e3bf7c)) + + - **FLEXSPI** + + - add MT35XU02G flash info ([a4f5015](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4f5015a0080134251e9272719f5dad1ce2aa842)) + + - **Renesas** + + - **R-Car3** + + - add extra offset if booting B-side ([993d809](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/993d809cc115ce23dd2df1df19dc8bb548cc19cd)) + - add function to judge a DDR rank ([726050b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/726050b8e2d2ee2234e103e2df55f9c7f262c851)) + + - **ST** + + - manage boot part in io_mmc ([f3d2750](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f3d2750aa2293c0279bc447a85771827ca8b74c1)) + + - **USB** + + - add device driver for STM32MP1 ([9a138eb](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9a138eb5f29f6747e181a1b3b4199ad57721a3e0)) + + - **USB** + + - add a USB device stack ([859bfd8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/859bfd8d42341c6dea2b193db79dc4828e074ad7)) + +- **Miscellaneous** + + - **Debug** + + - add new macro ERROR_NL() to print just a newline ([fd1360a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fd1360a339e84ccd49f8a2d8a42e4c131a681b3c)) + + - **CRC32** + + - **Hardware CRC32** + + - add support for HW computed CRC ([a1cedad](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a1cedadf73863ff103fecd64fa188334e1541337)) + + - **Software CRC32** + + - add software CRC32 support ([f216937](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f21693704a7bac275e12b44ae30fd210bc317175)) + + - **DT Bindings** + + - add STM32MP1 TZC400 bindings ([43de546](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/43de546b909947ab44f104aaee02b98fba70f44c)) + + - **FDT Wrappers** + + - add CPU enumeration utility function ([2d9ea36](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2d9ea360350303e37a8dd39f3599ac88aaef0ff9)) + + - **FDTs** + + - add for_each_compatible_node macro ([ff76614](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ff766148b52bfecf09728a83fc3becc7941d943c)) + - introduce wrapper function to read DT UUIDs ([d13dbb6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d13dbb6f1d5e28737a3319af035a6cb991bc6f8f)) + - add firewall regions into STM32MP1 DT ([86b43c5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/86b43c58a4105c8cef13d860dd73fa9bd560526a)) + - add IO policies for STM32MP1 ([21e002f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21e002fb777fad9d02a94dc961f077fb444517fa)) + - add STM32MP1 fw-config DT files ([d9e0586](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d9e0586b619b331eb2db75911ca82f927e20bd1c)) + + - **STM32MP1** + + - align DT with latest kernel ([e8a953a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e8a953a9b85806f7324c8c7245435d5b9226c279)) + - delete nodes for non-used boot devices ([4357db5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4357db5b17ce6ba7357dd99276f34ab497ce60ef)) + + - **NXP** + + - **OCRAM** + + - add driver for OCRAM initialization ([10b1e13](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10b1e13bd200849ff134dd8d2fde341a8526f563)) + + - **PSCI** + + - define CPUECTLR_TIMER_2TICKS ([3a2cc2e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3a2cc2e262890cffee1fc46835e85be6055189e8)) + +- **Dependencies** + + - **libfdt** + + - also allow changing base address ([4d585fe](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4d585fe52feb231d5e73ec50a505122d5e9bf450)) + +### Resolved Issues + +- **Architecture** + +- **Platforms** + + - print newline before fatal abort error message ([a5fea81](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a5fea8105887d0dd15edf94aebd591b1b6b5ef05)) + + - **Allwinner** + + - delay after enabling CPU power ([86a7429](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/86a7429e477786dad6fab002538aef825f4ca35a)) + + - **Arm** + + - correct UUID strings in FVP DT ([748bdd1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/748bdd19aa27c15438d829bdba42fe4062a265a1)) + - fix a VERBOSE trace ([5869ebd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5869ebd0e87f1de987e51994103440fa8c77b26f)) + - remove unused memory node ([be42c4b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/be42c4b4bf3c44f2970b7a1658c46b8d5863cad1)) + + - **FPGA** + + - allow build after MAKE_* changes ([9d38a3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9d38a3e698331e3c8192cc3e0cc8584e6ed987d9)) + - avoid re-linking from executable ELF file ([a67ac76](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a67ac7648cd814ed8f8d4ece1b265c6d48c6dc81)) + - Change PL011 UART IRQ ([195381a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/195381a91313bc0bce2cfa087f3c55136a9e8496)) + - limit BL31 memory usage ([d457230](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d4572303ed45faceffed859955b0e71724fddfd2)) + - reserve BL31 memory ([13e16fe](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/13e16fee86451e2f871c2aac757b32299fe5ead6)) + - streamline generated axf file ([9177e4f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9177e4fd9356b0f249be8b6fe14f222e10f1e6cd)) + - enable AMU extension ([d810e30](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d810e30dd6b47e0725dccbcb42ca0a0c5215ee34)) + - increase initrd size ([c3ce73b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3ce73be0bfe31fa28805fe92b3e727232ffd37a)) + + - **FVP** + + - fix fvp_cpu_standby() function ([3202ce8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3202ce8bbb4af8580736d2a1634ad45c3f89d931)) + - spmc optee manifest remove SMC allowlist ([183725b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/183725b39d75e362a32b3c5d0be110c255c56bdd)) + - allow changing the kernel DTB load address ([672d669](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/672d669d6c72f92c6b81464d1d421e392bc1aa3e)) + - bump BL2 stack size ([d22f1d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d22f1d358731f0f55f2f392fa587f0fa8d315aa5)) + - provide boot files via semihosting ([749d0fa](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/749d0fa80d1c7ca30b4092a381a06deeeaf1747f)) + - OP-TEE SP manifest per latest SPMC changes ([b7bc51a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b7bc51a7a747bf40d219b2041e5b3ce56737a71b)) + + - **FVP-R** + + - fix compilation error in release mode ([7d96e79](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7d96e79a1a2efdf85f1ed46cdd5c577b58054f53)) + + - **Morello** + + - initialise CNTFRQ in Non Secure CNTBaseN ([7f2d23d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f2d23d9d790df90021de6c5165ef10fe5cc5590)) + + - **TC** + + - enable AMU extension ([b5863ca](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b5863cab9adb3fed0c1e4dfb92cf906794e7bdb4)) + - change UUID to string format ([1c19536](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1c1953653c20b4a8c61a7deb3fc493d496d8c478)) + - remove "arm,psci" from psci node ([814646b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/814646b4cb792ab14df04e28360fefd168399b3c)) + - remove ffa and optee device tree node ([f1b44a9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f1b44a9050fbc12e8c260107bfff2930476df062)) + - set cactus-tertiary vcpu count to 1 ([05f667f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/05f667f0c670ba9682050714561309f00210c282)) + + - **SGI** + + - avoid redefinition of 'efi_guid' structure ([f34322c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f34322c1cea1e355aeb4133df6aa601d719be5a3)) + + - **Marvell** + + - Check the required libraries before building doimage ([dd47809](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dd47809e9ea75188060bf8b294efa8578d255c63)) + + - **Armada** + + - select correct pcie reference clock source ([371648e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/371648e1c76b5230bf8e153629064c02086365c9)) + - fix MSS loader for A8K family ([dceac43](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dceac436f620e60cd0149194377871b225216079)) + + - **A3K** + + - disable HANDLE_EA_EL3_FIRST by default ([3017e93](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3017e932768c7357a1a41493c58323419e9a1ec9)) + - enable workaround for erratum 1530924 ([975563d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/975563dbfc012b6e8a7765dd8e48220e1bc53dec)) + - Fix building uart-images.tgz.bin archive ([d3f8db0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d3f8db07b618e79c05805a1598e5e834e42fea98)) + - Fix check for external dependences ([2baf503](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2baf50385ba2b460afef4a7919b13b3a350fd03a)) + - fix printing info messages on output ([9f6d154](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9f6d15408340af07ed3c2500202b147189eaa7ef)) + - update information about PCIe abort hack ([068fe91](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/068fe919613197bf221c00fb84a1d94c66a7a8ca)) + - Remove encryption password ([076374c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/076374c9b97d47b10ba5c6034817866c08d66ed4)) + + - **A8K** + + - Add missing build dependency for BLE target ([04738e6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/04738e69917f8e8790bf4cf83ceb05f85e1f45bb)) + - Correctly set include directories for individual targets ([559ab2d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/559ab2df4a35cd82b2a67a0bebeb3028544a6766)) + - Require that MV_DDR_PATH is correctly set ([528dafc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/528dafc367c4f49d4904c4335422502dacf469bf)) + - fix number of CPU power switches. ([5cf6faf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5cf6fafe223da89c60e2323c242ea188b17e98c3)) + + - **MediaTek** + + - **MT8183** + + - fix out-of-bound access ([420c26b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/420c26b33a29c8328a1806ccb2f5a5885041fdfc)) + + - **MT8195** + + - use correct print format for uint64_t ([964ee4e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/964ee4e6be70ef638d6c875a761ab5ca359d84fe)) + - fix error setting for SPM ([1f81ccc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1f81cccedd40cb397813b0fa826ea1d793b02089)) + - extend MMU region size ([9ff8b8c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ff8b8ca9393e31e790eb2c8e7ea5c5f41f45198)) + - fix coverity fail ([85e4d14](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/85e4d14df157b5641421ea2b844c146ddc230152)) + + - **NXP** + + - **i.MX** + + - do not keep mmc_device_info in stack ([99d37c8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/99d37c8cb8196a7296311fb4f97f80f086021c74)) + + - **i.MX 8M** + + - **i.MX 8M Mini** + + - fix FTBFS on SPD=opteed ([10bfc77](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/10bfc77e7b3afce17185114ac66361a0914f7784)) + + - **Layerscape** + + - **LX2** + + - **LS1028A** + + - define endianness of scfg and gpio ([2475f63](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2475f63bdec6c24c13f7d6ec7f70275b1bde5c15)) + - fix compile error when enable fuse provision ([a0da9c4](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a0da9c4bd296ec1a47683a1ee05f5d1ed71828c7)) + + - **QEMU** + + - (NS_DRAM0_BASE + NS_DRAM0_SIZE) ADDR overflow 32bit ([325716c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/325716c97b7835b8d249f12c1461556bab8c53a0)) + - reboot/shutdown with low to high gpio ([bd2ad12](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bd2ad12ef10f558a5b15f5768b66e7b2606c6498)) + + - **QTI** + + - **SC1780** + + - qti smc addition ([cc35a37](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cc35a3771d28a96906f8d0f393ff664924a2d4dc)) + + - **Raspberry Pi** + + - **Raspberry Pi 4** + + - drop /memreserve/ region ([5d2793a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5d2793a61aded9602af86e90a571f64ff07f93b3)) + + - **Renesas** + + - **R-Car** + + - change process that copy code to system ram ([49593cc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49593cc1ce0d0471aeef7ca24a5415da2dd55bea)) + - fix cache maintenance process of reading cert header ([c77ab18](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c77ab18ec7c8e0f3d953177b835e004a9b53515f)) + - fix to load image when option BL2_DCACHE_ENABLE is enabled ([d2ece8d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d2ece8dba2f31091b1fa6c302d4255495bb15705)) + + - **R-Car 3** + + - fix disabling MFIS write protection for R-Car D3 ([a8c0c3e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a8c0c3e9d0df2215ed3b9ef66f4596787d957566)) + - fix eMMC boot support for R-Car D3 ([77ab366](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77ab3661e55c39694c7ee81de2d1615775711b64)) + - fix source file to make about GICv2 ([fb3406b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb3406b6b573cb0b35138ca3c89c5641d3d7b790)) + - fix version judgment for R-Car D3 ([c3d192b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3d192b8e52823dcbc32e21e47c30693d38bb49f)) + - generate two memory nodes for larger than 2 GiB channel 0 ([21924f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21924f2466b9b5e1243c142932e6f498da5633e9)) + + - **Rockchip** + + - **RK3399** + + - correct LPDDR4 resume sequence ([2c4b0c0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2c4b0c05c6546e24eb7209ffb3bb465d4feed164)) + - fix dram section placement ([f943b7c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f943b7c8e292e3aad2fcbdd0a37505f62b3b4c87)) + + - **Socionext** + + - **Synquacer** + + - update scmi power domain off handling ([f7f5d2c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f7f5d2c4cd209c2d21244da4fa442050eb4531ab)) + + - **ST** + + - add STM32IMAGE_SRC ([f223505](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f22350583c2e26ea291eae3dc54db867fdf0d9af)) + - add UART reset in crash console init ([b38e2ed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b38e2ed29ef791dad0cb61fed81b74d612f58b01)) + - apply security at the end of BL2 ([99080bd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/99080bd1273331007f0b2d6f64fed51ac6861bcd)) + - correct BSEC error code management ([72c7884](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/72c7884092684af4cc3c49e08f913b3ffed783ba)) + - correct IO compensation disabling ([c2d18ca](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c2d18ca80f4bd32f58ba07f53d9bb2586df18fc0)) + - correct signedness comparison issue ([5657dec](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5657decc7ffa1376c0a97b6d14ea1428877f5af4)) + - improve DDR get size function ([91ffc1d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/91ffc1deffa2c1c64efe4dfaf27b78f2621a8b0b)) + - only check header major when booting ([8ce8918](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8ce89187459ec77dd9ffdffba3a2b77838d51b6d)) + - panic if boot interface is wrong ([71693a6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/71693a66341e7d9d683ef32981243cb4c4439351)) + - remove double space ([306dcd6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/306dcd6b0d1981b75e103c560a4034bdaa6862d5)) + + - **ST32MP1** + + - add bl prefix for internal linker script ([7684ddd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7684dddcfb14c45bad33b091410a0bf14a3a9830)) + + - **Xilinx** + + - **Versal** + + - correct IPI buffer offset ([e1e5b13](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e1e5b1339b9f73f7f1893d8a6d4dfe4b19ba0ad1)) + - use sync method for blocking calls ([fa58171](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fa58171534976f94b93a44184afd050d8225e404)) + + - **ZynqMP** + + - use sync method for blocking calls ([c063c5a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c063c5a4f92d5787536e595ca4906b458b0f26cb)) + +- **Services** + + - drop warning on unimplemented calls ([67fad51](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/67fad514ee974dcf0252fa0e9219eb3c580eb714)) + + - **RME** + + - fixes a shift by 64 bits bug in the RME GPT library ([322b344](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/322b344e30cb87b9293060d5946b3c17fe3b9133)) + + - **SPM** + + - do not compile if SVE/SME is enabled ([4333f95](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4333f95bedb5f2b53dcb62e0e9c563794ec33c07)) + - error macro to use correct print format ([0c23e6f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0c23e6f44d41593b6e7f97594c12b5791bd75189)) + - revert workaround hafnium as hypervisor ([3221fce](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3221fce842c0b5aea984bb8dbc1393082bd88a58)) + - fixing coverity issue for SPM Core. ([f7fb0bf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/f7fb0bf77f3434bfb67411cad65e704fdef27f76)) + +- **Libraries** + + - **LIBC** + + - use long for 64-bit types on aarch64 ([4ce3e99](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4ce3e99a336b74611349595ea7fd5ed0277c3eeb)) + + - **CPU Support** + + - correct Demeter CPU name ([4cb576a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4cb576a0c5bd2e7669606996a9f79602596df07c)) + - workaround for Cortex A78 erratum 2242635 ([1ea9190](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1ea9190c6a4d2299c6dc19adc0bbe93d4f051eff)) + - workaround for Cortex-A710 erratum 2058056 ([744bdbf](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/744bdbf732ffd2abf84b2431624051e93bc29f7b)) + - workaround for Neoverse V1 erratum 2216392 ([4c8fe6b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4c8fe6b17fa994a630b2a30f8666df103f2e370d)) + - workaround for Neoverse-N2 erratum 2138953 ([ef8f0c5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef8f0c52ddf83e815a029319971682d7a26b6a6f)) + - workaround for Neoverse-N2 erratum 2138958 ([c948185](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c948185c973c13df36c62c4bcb50e22b14d6e06a)) + - workaround for Neoverse-N2 erratum 2242400 ([603806d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/603806d1376c4b18211fb1d4cc338153de026c32)) + - workaround for Neoverse-N2 erratum 2242415 ([5819e23](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5819e23bc47c860872141caf42bddddb1b8679a5)) + - workaround for Neoverse-N2 erratum 2280757 ([0d2d999](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0d2d99924e1be548e75c46cfd536f7503cf863e0)) + - rename Matterhorn, Matterhorn ELP, and Klein CPUs ([c6ac4df](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c6ac4df622befb5bb42ac136745094e1498c91d8)) + + - **EL3 Runtime** + + - correct CASSERT for pauth ([b4f8d44](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b4f8d44597faf641177134ee08db7c3fcef5aa14)) + - fix SVE and AMU extension enablement flags ([68ac5ed](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/68ac5ed0493b24e6a0a178171a47db75a31cc423)) + - random typos in tf-a code base ([2e61d68](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2e61d6871cc310e9404fe5cfa10b9828f1c869a7)) + - Remove save/restore of EL2 timer registers ([a7cf274](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a7cf2743f3eb487912302aafc748c81bbd1fc603)) + + - **OP-TEE** + + - correct signedness comparison ([21d2be8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/21d2be83a2eabb328071e857e538ced3c8351874)) + + - **GPT** + + - add necessary barriers and remove cache clean ([77612b9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77612b90acaffc82cea712f4a431c727bbb968ec)) + - use correct print format for uint64_t ([2461bd3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/2461bd3a89f7f2cdf4a7302536746733970cfe53)) + + - **Translation Tables** + + - remove always true check in assert ([74d720a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/74d720a026735263d2f290fd05370dad0d4c7219)) + +- **Drivers** + + - **Authentication** + + - avoid NV counter upgrade without certificate validation ([a2a5a94](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a2a5a9456969266dc68d5845f31e05be0c3ff2e3)) + + - **CryptoCell-713** + + - fix a build failure with CC-713 library ([e5fbee5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e5fbee5085c682ac3438e6f66c8bdaffb6076fa2)) + + - **MTD** + + - fix MISRA issues and logic improvement ([5130ad1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5130ad14d52a0196422fed8a7d08e25659890b15)) + - macronix quad enable bit issue ([c332740](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c3327408eb4b5852c0ed9d8933c35aaa6de34c21)) + + - **NAND** + + - **SPI NAND** + + - check correct manufacturer id ([4490b79](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4490b7963303fbe59b07a66c8498a803eb5c239c)) + - check that parameters have been set ([bc453ab](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bc453ab1b2fd4267d34f2b9587f73b8940ee1538)) + + - **SCMI** + + - entry: add weak functions ([b3c8fd5](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b3c8fd5d778144340d289ad4825123106aac4a96)) + - smt: fix build for aarch64 ([0e223c6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0e223c6a9e5a2d92cae00fdd16a02a3f8971b114)) + - mention "SCMI" in driver initialisation message ([e0baae7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/e0baae7316bfdf3e49e5e158f79eb80cd51fc700)) + - relax requirement for exact protocol version ([125868c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/125868c94150f52ff85cdb59aee623ab1f9f259d)) + + - **UFS** + + - add reset before DME_LINKSTARTUP ([905635d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/905635d5e74e3c7b7b2412a673009c8aaabb73e1)) + + - **Arm** + + - **GIC** + + - **GICv3** + + - add dsb in both disable and enable function of gicv3_cpuif ([5a5e0aa](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5a5e0aac398989536dc4be790820af89da3d093a)) + + - **GIC-600AE** + + - fix timeout calculation ([7f322f2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7f322f228e76caa5480f827af0aa6751f00fc1c4)) + + - **TZC** + + - **TZC-400** + + - never disable filter 0 ([ef378d3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ef378d3ec1ef9d7c28baef32ed409688e962542b)) + + - **Marvell** + + - **COMPHY** + + - fix name of 3.125G SerDes mode ([a669983](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a669983c78828e3f4a4f14b9e5a6ee79dcfde20f)) + + - **Armada 3700** + + - configure phy selector also for PCIe ([0f3a122](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0f3a1221093256999af5f2a80e9b3d7231b9f5fb)) + - fix address overflow ([c074f70](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c074f70ce5d85e1735b589b323fac99d7eb988b5)) + - handle failures in power functions ([49b664e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49b664e75f43fda08dddef4f0510d346bdd25565)) + + - **CP110** + + - fix error code in pcie power on ([c0a909c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c0a909cdcce2d9a2ceefe672ad2fc1cae7e39ec4)) + + - **Armada** + + - **A3K** + + - **A3720** + + - fix configuring UART clock ([b9185c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b9185c75f7ec2b600ebe0d49281e216a2456b764)) + - fix UART clock rate value and divisor calculation ([66a7752](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/66a7752834382595d26214783ae4698fd1f00bd6)) + - fix UART parent clock rate determination ([5a91c43](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5a91c439cbeb1f64b8b9830de91efad5113d3c89)) + + - **MediaTek** + + - **PMIC Wrapper** + + - update idle flow ([9ed4e6f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/9ed4e6fb669b8fcafc4e8acfa6a36db305d27ac8)) + + - **MT8192** + + - **SPM** + + - add missing bit define for debug purpose ([310c3a2](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/310c3a26e17d99aafc73b3504d0b6dfbdb97fd4c)) + + - **NXP** + + - **FLEXSPI** + + - fix warm boot wait time for MT35XU512A ([1ff7e46](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/1ff7e46b092b74891bc2dc7263e4dfae947b2223)) + + - **SCFG** + + - fix endianness checking ([fb90cfd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/fb90cfd4eee504f1d16aa143728af427dc6e0ed8)) + + - **SFP** + + - fix compile warning ([3239a17](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3239a17561c124df7095391c0d64e86910660cdc)) + + - **Renesas** + + - **R-Car3** + + - console: fix a return value of console_rcar_init ([bb273e3](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bb273e3be1c4f1cddeac9ceaac95fb56e41e6b98)) + - ddr: update DDR setting for H3, M3, M3N ([ec767c1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ec767c1b99675fbb50ef1b2fdb2d38e881e4789d)) + - emmc: remove CPG_CPGWPR redefinition ([36d5645](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/36d5645aec947ab00b925b21141e59e58e1efd8c)) + - fix CPG registers redefinition ([0dae56b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0dae56bb2f0aa1f89ec98ebe3931fb19751a5c72)) + - i2c_dvfs: fix I2C operation ([b757d3a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b757d3a1d901bee9b7ad430702575adba04889ba)) + + - **ST** + + - **Clock** + + - use correct return value ([8f97c4f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8f97c4fab1769b3f7f37a2a7a01ade36e5c94eaa)) + - correctly manage RTC clock source ([1550909](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/15509093f0ba9a10f97c6f92bc3bb9fcf79a48ce)) + - fix MCU/AXI parent clock ([b8fe48b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/b8fe48b6f2b07fce49363cb3c0f8dac9e286439b)) + - fix MPU clock rate ([602ae2f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/602ae2f23c2bc9d79a9ab2b7c5dde1932fffc984)) + - fix RTC clock rating ([cbd2e8a](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cbd2e8a6afdd05c4b404d7998134a3f60cc15518)) + - keep RTC clock always on ([5b111c7](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/5b111c74795ea5e9c8a12d0e6b18d77e431311ed)) + - keep RTCAPB clock always on ([373f06b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/373f06be4ee1114369b96763481b58885623aea4)) + - set other clocks as always on ([bf39318](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/bf39318d93c270ff72bda4b46e4771aba7aea313)) + + - **I/O** + + - **STM32 Image** + + - invalidate cache on local buf ([a5bcf82](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a5bcf82402ff415326b4dba42aae95c499821e94)) + - uninitialized variable warning ([c1d732d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c1d732d0db2463998036c678619007da79a25b3f)) + + - **ST PMIC** + + - initialize i2c_state ([4282284](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/42822844bfed2e9ffaeae850cc60f5c3d4d9d654)) + - missing error check ([a4bcfe9](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a4bcfe94e73db89ce2ebbb23c8e33e51eea5026a)) + + - **STPMIC1** + + - fix power switches activation ([0161991](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0161991184e5feacacc679bdb9c92681b85235eb)) + - update error cases return ([ed6a852](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/ed6a85234653c5ee2520389b769ff47e321df8a4)) + + - **UART** + + - **STM32 Console** + + - do not skip init for crash console ([49c7f0c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49c7f0cef4cc864185828750f1f61f3f33f284f7)) + + - **USB** + + - add a optional ops get_other_speed_config_desc ([216c122](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/216c1223c2c65bd1c119a28b9406f70a9ee7b063)) + - fix Null pointer dereferences in usb_core_set_config ([0cb9870](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0cb9870ddfa1b2fec50debe6d6333cbcb3df1e7e)) + - remove deadcode when USBD_EP_NB = 1 ([7ca4928](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7ca49284be083b03ae11aa348b40358876ee5d4b)) + - remove unnecessary cast ([025f5ef](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/025f5ef201a39ba7285f368139e690bbd7a44653)) + +- **Miscellaneous** + + - use correct printf format for uint64_t ([4ef449c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4ef449c15a4055d92632cb7e72267f525a7e2fca)) + + - **DT Bindings** + + - fix static checks ([0861fcd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/0861fcdd3e3f2625e133de3dae9c548de7c1ee48)) + + - **FDTs** + + - avoid output on missing DT property ([49e789e](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/49e789e353efaf97f84eca016c6a1b8a2b3e3d98)) + - fix OOB write in uuid parsing function ([d0d6424](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d0d642450f1f3a0f43e0e156ef57a0c460dd48cf)) + + - **Morello** + + - fix scmi clock specifier to cluster mappings ([387a906](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/387a9065a271ecde0e47dc5a9f9d037637502beb)) + + - **STM32MP1** + + - correct copyright dates ([8d26029](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8d26029168fe70a86de524ed68c56e8666823714)) + - set ETH clock on PLL4P on ST boards ([3e881a8](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/3e881a8834a955f1e552300bdbf1dafd02ea8f1c)) + - update PLL nodes for ED1/EV1 boards ([cdbbb9f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/cdbbb9f7ecd4687fa52e1c655b631377c24862b9)) + - use 'kHz' as kilohertz abbreviation ([4955d08](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4955d08de7aa664387d2e5f690e78b85ac23a402)) + + - **PIE** + + - invalidate data cache in the entire image range if PIE is enabled ([596d20d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/596d20d9e4d50c02b5a0cce8cad2a1c205cd687a)) + + - **Security** + + - Set MDCR_EL3.MCCD bit ([12f6c06](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/12f6c0649732a35a7ed45ba350a963f09a5710ca)) + + - **SDEI** + + - fix assert while kdump issue ([d39db26](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d39db2695ba626b9c0ee38652fe160b4e84b15d9)) + - print event number in hex format ([6b94356](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6b94356b577744d425476a029c47bd35eb13c148)) + - set SPSR for SDEI based on TakeException ([37596fc](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/37596fcb43e34ed4bcf1bd3e86d8dec1011edab8)) + +- **Documentation** + + - fix TF-A v2.6 release date in the release information page ([c90fa47](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/c90fa47202b762fe8f54e9c0561e94d37907b6ad)) + - fix `FF-A` substitution ([a61940c](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/a61940ca739eb89be7c1bb2408a9178c2da5cb70)) + - fix typos in v2.5 release documentation ([481c7b6](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/481c7b6b9107a3f71ee750f89cacdd8f9c729838)) + - remove "experimental" tag for stable features ([700e768](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/700e7685dd4682a929645a79de39f503c9140b2d)) + + - **Contribution Guidelines** + + - fix formatting for code snippet ([d0bbe81](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/d0bbe8150eb35fe2bac1567751bf84a8f073dd39)) + +- **Build System** + + - use space in WARNINGS list ([34b508b](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/34b508be9f021831423a8a14f56dff547e24c743)) + + - **Git Hooks** + + - downgrade `package-lock.json` version ([7434b65](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/7434b65208175bdf3f44e0e62aaaeabc9c494ee3)) + +- **Tools** + + - **STM32 Image** + + - improve the tool ([8d0036d](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/8d0036d3d8c8ac1524539ea90382acafb1e524c0)) + + - **SPTOOL** + + - SP UUID little to big endian in TF-A build ([dcdbcdd](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/dcdbcddebdee8d4d2c6c8316f615b428758b22ac)) + + - **DOIMAGE** + + - Fix doimage syntax breaking secure mode build ([6d55ef1](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/6d55ef1a24dc92a3b737aaa02141f550caaace06)) + +- **Dependencies** + + - **checkpatch** + + - do not check merge commits ([77a0a7f](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/77a0a7f1d96b188849d1d8d8884b3c93857d3f69)) + +## [2.5.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.4..refs/tags/v2.5) (2021-05-17) + +### New Features + +- Architecture support + + - Added support for speculation barrier(`FEAT_SB`) for non-Armv8.5 platforms + starting from Armv8.0 + - Added support for Activity Monitors Extension version 1.1(`FEAT_AMUv1p1`) + - Added helper functions for Random number generator(`FEAT_RNG`) registers + - Added support for Armv8.6 Multi-threaded PMU extensions (`FEAT_MTPMU`) + - Added support for MTE Asymmetric Fault Handling extensions(`FEAT_MTE3`) + - Added support for Privileged Access Never extensions(`FEAT_PANx`) + +- Bootloader images + + - Added PIE support for AArch32 builds + - Enable Trusted Random Number Generator service for BL32(sp_min) + +- Build System + + - Added build option for Arm Feature Modifiers + +- Drivers + + - Added support for interrupts in TZC-400 driver + - Broadcom + - Added support for I2C, MDIO and USB drivers + - Marvell + - Added support for secure read/write of dfc register-set + - Added support for thermal sensor driver + - Implement a3700_core_getc API in console driver + - Added rx training on 10G port + - Marvell Mochi + - Added support for cn913x in PCIe mode + - Marvell Armada A8K + - Added support for TRNG-IP-76 driver and accessing RNG register + - Mediatek MT8192 + - Added support for following drivers + - MPU configuration for SCP/PCIe + - SPM suspend + - Vcore DVFS + - LPM + - PTP3 + - UART save and restore + - Power-off + - PMIC + - CPU hotplug and MCDI support + - SPMC + - MPU + - Mediatek MT8195 + - Added support for following drivers + - GPIO, NCDI, SPMC drivers + - Power-off + - CPU hotplug, reboot and MCDI + - Delay timer and sys timer + - GIC + - NXP + - Added support for + - non-volatile storage API + - chain of trust and trusted board boot using two modes: MBEDTLS and CSF + - fip-handler necessary for DDR initialization + - SMMU and console drivers + - crypto hardware accelerator driver + - following drivers: SD, EMMC, QSPI, FLEXSPI, GPIO, GIC, CSU, PMU, DDR + - NXP Security Monitor and SFP driver + - interconnect config APIs using ARM CCN-CCI driver + - TZC APIs to configure DDR region + - generic timer driver + - Device configuration driver + - IMX + - Added support for image loading and io-storage driver for TBBR fip booting + - Renesas + - Added support for PFC and EMMC driver + - RZ Family: + - G2N, G2E and G2H SoCs + - Added support for watchdog, QoS, PFC and DRAM initialization + - RZG Family: + - G2M + - Added support for QoS and DRAM initialization + - Xilinx + - Added JTAG DCC support for Versal and ZynqMP SoC family. + +- Libraries + + - C standard library + - Added support to print `%` in `snprintf()` and `printf()` APIs + - Added support for strtoull, strtoll, strtoul, strtol APIs from FreeBSD + project + - CPU support + - Added support for + - Cortex_A78C CPU + - Makalu ELP CPU + - Makalu CPU + - Matterhorn ELP CPU + - Neoverse-N2 CPU + - CPU Errata + - Arm Cortex-A76: Added workaround for erratum 1946160 + - Arm Cortex-A77: Added workaround for erratum 1946167 + - Arm Cortex-A78: Added workaround for erratum 1941498 and 1951500 + - Arm Neoverse-N1: Added workaround for erratum 1946160 + - Flattened device tree(libfdt) + - Added support for wrapper function to read UUIDs in string format from dtb + +- Platforms + + - Added support for MediaTek MT8195 + - Added support for Arm RD-N2 board + - Allwinner + - Added support for H616 SoC + - Arm + - Added support for GPT parser + - Protect GICR frames for fused/unused cores + - Arm Morello + - Added VirtIO network device to Morello FVP fdts + - Arm RD-N2 + - Added support for variant 1 of RD-N2 platform + - Enable AMU support + - Arm RD-V1 + - Enable AMU support + - Arm SGI + - Added support for platform variant build option + - Arm TC0 + - Added Matterhorn ELP CPU support + - Added support for opteed + - Arm Juno + - Added support to use hw_config in BL31 + - Use TRNG entropy source for SMCCC TRNG interface + - Condition Juno entropy source with CRC instructions + - Marvell Mochi + - Added support for detection of secure mode + - Marvell ARMADA + - Added support for new compile option A3720_DB_PM_WAKEUP_SRC + - Added support doing system reset via CM3 secure coprocessor + - Made several makefile enhancements required to build WTMI_MULTI_IMG and + TIMDDRTOOL + - Added support for building DOIMAGETOOL tool + - Added new target mrvl_bootimage + - Mediatek MT8192 + - Added support for rtc power off sequence + - Mediatek MT8195 + - Added support for SiP service + - STM32MP1 + - Added support for + - Seeed ODYSSEY SoM and board + - SDMMC2 and I2C2 pins in pinctrl + - I2C2 peripheral in DTS + - PIE for BL32 + - TZC-400 interrupt managament + - Linux Automation MC-1 board + - Renesas RZG + - Added support for identifying EK874 RZ/G2E board + - Added support for identifying HopeRun HiHope RZ/G2H and RZ/G2H boards + - Rockchip + - Added support for stack protector + - QEMU + - Added support for `max` CPU + - Added Cortex-A72 support to `virt` platform + - Enabled trigger reboot from secure pl061 + - QEMU SBSA + - Added support for sbsa-ref Embedded Controller + - NXP + - Added support for warm reset to retain ddr content + - Added support for image loader necessary for loading fip image + - lx2160a SoC Family + - Added support for + - new platform lx2160a-aqds + - new platform lx2160a-rdb + - new platform lx2162a-aqds + - errata handling + - IMX imx8mm + - Added support for trusted board boot + - TI K3 + - Added support for lite device board + - Enabled Cortex-A72 erratum 1319367 + - Enabled Cortex-A53 erratum 1530924 + - Xilinx ZynqMP + - Added support for PS and system reset on WDT restart + - Added support for error management + - Enable support for log messages necessary for debug + - Added support for PM API SMC call for efuse and register access + +- Processes + + - Introduced process for platform deprecation + - Added documentation for TF-A threat model + - Provided a copy of the MIT license to comply with the license requirements + of the arm-gic.h source file (originating from the Linux kernel project and + re-distributed in TF-A). + +- Services + + - Added support for TRNG firmware interface service + - Arm + - Added SiP service to configure Ethos-N NPU + - SPMC + - Added documentation for SPM(Hafnium) SMMUv3 driver + - SPMD + - Added support for + - FFA_INTERRUPT forwading ABI + - FFA_SECONDARY_EP_REGISTER ABI + - FF-A v1.0 boot time power management, SPMC secondary core boot and early + run-time power management + +- Tools + + - FIPTool + - Added mechanism to allow platform specific image UUID + - git hooks + - Added support for conventional commits through commitlint hook, commitizen + hook and husky configuration files. + - NXP tool + - Added support for a tool that creates pbl file from BL2 + - Renesas RZ/G2 + - Added tool support for creating bootparam and cert_header images + - CertCreate + - Added support for platform-defined certificates, keys, and extensions + using the platform's makefile + - shared tools + - Added EFI_GUID representation to uuid helper data structure + +### Changed + +- Common components + + - Print newline after hex address in aarch64 el3_panic function + - Use proper `#address-cells` and `#size-cells` for reserved-memory in dtbs + +- Drivers + + - Move SCMI driver from ST platform directory and make it common to all + platforms + - Arm GICv3 + - Shift eSPI register offset in GICD_OFFSET_64() + - Use mpidr to probe GICR for current CPU + - Arm TZC-400 + - Adjust filter tag if it set to FILTER_BIT_ALL + - Cadence + - Enhance UART driver APIs to put characters to fifo + - Mediatek MT8192 + - Move timer driver to common folder + - Enhanced sys_cirq driver to add more IC services + - Renesas + - Move ddr and delay driver to common directory + - Renesas rcar + - Treat log as device memory in console driver + - Renesas RZ Family: + - G2N and G2H SoCs + - Select MMC_CH1 for eMMC channel + - Marvell + - Added support for checking if TRNG unit is present + - Marvell A3K + - Set TXDCLK_2X_SEL bit during PCIe initialization + - Set mask parameter for every reg_set call + - Marvell Mochi + - Added missing stream IDs configurations + - MbedTLS + - Migrated to Mbed TLS v2.26.0 + - IMX imx8mp + - Change the bl31 physical load address + - QEMU SBSA + - Enable secure variable storage + - SCMI + - Update power domain protocol version to 2.0 + - STM32 + - Remove dead code from nand FMC driver + +- Libraries + + - C Standard Library + - Use macros to reduce duplicated code between snprintf and printf + - CPU support + - Sanity check pointers before use in AArch32 builds + - Arm Cortex-A78 + - Remove rainier cpu workaround for errata 1542319 + - Arm Makalu ELP + - Added "\_arm" suffix to Makalu ELP CPU lib + +- Miscellaneous + + - Editorconfig + - set max line length to 100 + +- Platforms + + - Allwinner + - Added reserved-memory node to DT + - Express memmap more dynamically + - Move SEPARATE_NOBITS_REGION to platforms + - Limit FDT checks to reduce code size + - Use CPUIDLE hardware when available + - Allow conditional compilation of SCPI and native PSCI ops + - Always use a 3MHz RSB bus clock + - Enable workaround for Cortex-A53 erratum 1530924 + - Fixed non-default PRELOADED_BL33_BASE + - Leave CPU power alone during BL31 setup + - Added several psci hooks enhancements to improve system shutdown/reset + sequence + - Return the PMIC to I2C mode after use + - Separate code to power off self and other CPUs + - Split native and SCPI-based PSCI implementations + - Allwinner H6 + - Added R_PRCM security setup for H6 board + - Added SPC security setup for H6 board + - Use RSB for the PMIC connection on H6 + - Arm + - Store UUID as a string, rather than ints + - Replace FIP base and size macro with a generic name + - Move compile time switch from source to dt file + - Don't provide NT_FW_CONFIG when booting hafnium + - Do not setup 'disabled' regulator + - Increase SP max size + - Remove false dependency of ARM_LINUX_KERNEL_AS_BL33 on RESET_TO_BL31 and + allow it to be enabled independently + - Arm FVP + - Do not map GIC region in BL1 and BL2 + - Arm Juno + - Refactor juno_getentropy() to return 64 bits on each call + - Arm Morello + - Remove "virtio-rng" from Morello FVP + - Enable virtIO P9 device for Morello fvp + - Arm RDV1 + - Allow all PSCI callbacks on RD-V1 + - Rename rddaniel to rdv1 + - Arm RDV1MC + - Rename rddanielxlr to rdv1mc + - Initialize TZC-400 controllers + - Arm TC0 + - Updated GICR base address + - Use scmi_dvfs clock index 1 for cores 4-7 through fdt + - Added reserved-memory node for OP-TEE fdts + - Enabled Theodul DSU in TC platform + - OP-TEE as S-EL1 SP with SPMC at S-EL2 + - Update Matterhorm ELP DVFS clock index + - Arm SGI + - Allow access to TZC controller on all chips + - Define memory regions for multi-chip platforms + - Allow access to nor2 flash and system registers from S-EL0 + - Define default list of memory regions for DMC-620 TZC + - Improve macros defining cper buffer memory region + - Refactor DMC-620 error handling SMC function id + - Refactor SDEI specific macros + - Added platform id value for RDN2 platform + - Refactored header file inclusions and inclusion of memory mapping + - Arm RDN2 + - Allow usage of secure partitions on RDN2 platform + - Update GIC redistributor and TZC base address + - Arm SGM775 + - Deprecate Arm sgm775 FVP platform + - Marvell + - Increase TX FIFO EMPTY timeout from 2ms to 3ms + - Update delay code to be compatible with 1200 MHz CPU + - Marvell ARMADA + - Postpone MSS CPU startup to BL31 stage + - Allow builds without MSS support + - Use MSS SRAM in secure mode + - Added missing FORCE, .PHONY and clean targets + - Cleanup MSS SRAM if used for copy + - Move definition of mrvl_flash target to common marvell_common.mk file + - Show informative build messages and blank lines + - Marvell ARMADA A3K + - Added a new target mrvl_uart which builds UART image + - Added checks that WTP, MV_DDR_PATH and CRYPTOPP_PATH are correctly defined + - Allow use of the system Crypto++ library + - Build \$(WTMI_ENC_IMG) in \$(BUILD_PLAT) directory + - Build intermediate files in \$(BUILD_PLAT) directory + - Build UART image files directly in \$(BUILD_UART) subdirectory + - Correctly set DDR_TOPOLOGY and CLOCKSPRESET for WTMI + - Do not use 'echo -e' in Makefile + - Improve 4GB DRAM usage from 3.375 GB to 3.75 GB + - Remove unused variable WTMI_SYSINIT_IMG from Makefile + - Simplify check if WTP variable is defined + - Split building \$(WTMI_MULTI_IMG) and \$(TIMDDRTOOL) + - Marvell ARMADA A8K + - Allow CP1/CP2 mapping at BLE stage + - Mediatek MT8183 + - Added timer V20 compensation + - Nvidia Tegra + - Rename SMC API + - TI K3 + - Make plat_get_syscnt_freq2 helper check CNT_FID0 register + - Fill non-message data fields in sec_proxy with 0x0 + - Update ti_sci_msg_req_reboot ABI to include domain + - Enable USE_COHERENT_MEM only for the generic board + - Explicitly map SEC_SRAM_BASE to 0x0 + - Use BL31_SIZE instead of computing + - Define the correct number of max table entries and increase SRAM size to + account for additional table + - Raspberry Pi4 + - Switch to gicv2.mk and GICV2_SOURCES + - Renesas + - Move headers and assembly files to common folder + - Renesas rzg + - Added device tree memory node enhancements + - Rockchip + - Switch to using common gicv3.mk + - STM32MP1 + - Set BL sizes regardless of flags + - QEMU + - Include gicv2.mk for compiling GICv2 source files + - Change DEVICE2 definition for MMU + - Added helper to calculate the position shift from MPIDR + - QEMU SBSA + - Include libraries for Cortex-A72 + - Increase SHARED_RAM_SIZE + - Addes support in spm_mm for upto 512 cores + - Added support for topology handling + - QTI + - Mandate SMC implementation + - Xilinx + - Rename the IPI CRC checksum macro + - Use fno-jump-tables flag in CPPFLAGS + - Xilinx versal + - Added the IPI CRC checksum macro support + - Mark IPI calls secure/non-secure + - Enable sgi to communicate with linux using IPI + - Remove Cortex-A53 compilation + - Xilinx ZynqMP + - Configure counter frequency during initialization + - Filter errors related to clock gate permissions + - Implement pinctrl request/release EEMI API + - Reimplement pinctrl get/set config parameter EEMI API calls + - Reimplement pinctrl set/get function EEMI API + - Update error codes to match Linux and PMU Firmware + - Update PM version and support PM version check + - Update return type in query functions + - Added missing ids for 43/46/47dr devices + - Checked for DLL status before doing reset + - Disable ITAPDLYENA bit for zero ITAP delay + - Include GICv2 makefile + - Remove the custom crash implementation + +- Services + + - SPMD + - Lock the g_spmd_pm structure + - Declare third cactus instance as UP SP + - Provide number of vCPUs and VM size for first SP + - Remove `chosen` node from SPMC manifests + - Move OP-TEE SP manifest DTS to FVP platform + - Update OP-TEE SP manifest with device-regions node + - Remove device-memory node from SPMC manifests + - SPM_MM + - Use sp_boot_info to set SP context + - SDEI + - Updata the affinity of shared event + +- Tools + + - FIPtool + - Do not print duplicate verbose lines about building fiptool + - CertCreate + - Updated tool for platform defined certs, keys & extensions + - Create only requested certificates + - Avoid duplicates in extension stack + +### Resolved Issues + +- Several fixes for typos and mis-spellings in documentation + +- Build system + + - Fixed \$\{FIP_NAME} to be rebuilt only when needed in Makefile + - Do not mark file targets as .PHONY target in Makefile + +- Drivers + + - Authorization + - Avoid NV counter upgrade without certificate validation + - Arm GICv3 + - Fixed logical issue for num_eints + - Limit SPI ID to avoid misjudgement in GICD_OFFSET() + - Fixed potential GICD context override with ESPI enabled + - Marvell A3700 + - Fixed configuring polarity invert bits + - Arm TZC-400 + - Correct FAIL_CONTROL Privileged bit + - Fixed logical error in FILTER_BIT definitions + - Renesas rcar + - Fixed several coding style violations reported by checkpatch + +- Libraries + + - Arch helpers + - Fixed assertions in processing dynamic relocations for AArch64 builds + - C standard library + - Fixed MISRA issues in memset() ABI + - RAS + - Fixed bug of binary search in RAS interrupt handler + +- Platforms + + - Arm + - Fixed missing copyrights in arm-gic.h file + - Fixed the order of header files in several dts files + - Fixed error message printing in board makefile + - Fixed bug of overriding the last node in image load helper API + - Fixed stdout-path in fdts files of TC0 and N1SDP platforms + - Turn ON/OFF redistributor in sync with GIC CPU interface ON/OFF for css + platforms + - Arm FVP + - Fixed Generic Timer interrupt types in platform dts files + - Arm Juno + - Fixed parallel build issue for romlib config + - Arm SGI + - Fixed bug in SDEI receive event of RAS handler + - Intel Agilex + - Fixed PLAT_MAX_PWR_LVL value + - Marvell + - Fixed SPD handling in dram port + - Marvell ARMADA + - Fixed TRNG return SMC handling + - Fixed the logic used for LD selector mask + - Fixed MSS firmware loader for A8K family + - ST + - Fixed few violations reported by coverity static checks + - STM32MP1 + - Fixed SELFREF_TO_X32 mask in ddr driver + - Do not keep mmc_device_info in stack + - Correct plat_crash_console_flush() + - QEMU SBSA + - Fixed memory type of secure NOR flash + - QTI + - Fixed NUM_APID and REG_APID_MAP() argument in SPMI driver + - Intel + - Do not keep mmc_device_info in stack + - Hisilicon + - Do not keep mmc_device_info in stack + +- Services + + - EL3 runtime + - Fixed the EL2 context save/restore routine by removing EL2 generic timer + system registers + - Added fix for exception handler in BL31 by synchronizing pending EA using + DSB barrier + - SPMD + - Fixed error codes to use int32_t type + - TSPD + - Added bug fix in tspd interrupt handling when TSP_NS_INTR_ASYNC_PREEMPT is + enabled + - TRNG + - Fixed compilation errors with -O0 compile option + - DebugFS + - Checked channel index before calling clone function + - PSCI + - Fixed limit of 256 CPUs caused by cast to unsigned char + - TSP + - Fixed compilation erros when built with GCC 11.0.0 toolchain + +- Tools + + - FIPtool + - Do not call `make clean` for `all` target + - CertCreate + - Fixed bug to avoid cleaning when building the binary + - Used preallocated parts of the HASH struct to avoid leaking HASH struct + fields + - Free arguments copied with strdup + - Free keys after use + - Free X509_EXTENSION structures on stack to avoid leaking them + - Optimized the code to avoid unnecessary attempts to create non-requested + certificates + +## [2.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.3..refs/tags/v2.4) (2020-11-17) + +### New Features + +- Architecture support + - Armv8.6-A + - Added support for Armv8.6 Enhanced Counter Virtualization (ECV) + - Added support for Armv8.6 Fine Grained Traps (FGT) + - Added support for Armv8.6 WFE trap delays +- Bootloader images + - Added support for Measured Boot +- Build System + - Added build option `COT_DESC_IN_DTB` to create Chain of Trust at runtime + - Added build option `OPENSSL_DIR` to direct tools to OpenSSL libraries + - Added build option `RAS_TRAP_LOWER_EL_ERR_ACCESS` to enable trapping RAS + register accesses from EL1/EL2 to EL3 + - Extended build option `BRANCH_PROTECTION` to support branch target + identification +- Common components + - Added support for exporting CPU nodes to the device tree + - Added support for single and dual-root Chains of Trust in secure partitions +- Drivers + - Added Broadcom RNG driver + - Added Marvell `mg_conf_cm3` driver + - Added System Control and Management Interface (SCMI) driver + - Added STMicroelectronics ETZPC driver + - Arm GICv3 + - Added support for detecting topology at runtime + - Dual Root + - Added support for platform certificates + - Marvell Cache LLC + - Added support for mapping the entire LLC into SRAM + - Marvell CCU + - Added workaround for erratum 3033912 + - Marvell CP110 COMPHY + - Added support for SATA COMPHY polarity inversion + - Added support for USB COMPHY polarity inversion + - Added workaround for erratum IPCE_COMPHY-1353 + - STM32MP1 Clocks + - Added `RTC` as a gateable clock + - Added support for shifted clock selector bit masks + - Added support for using additional clocks as parents +- Libraries + - C standard library + - Added support for hexadecimal and pointer format specifiers in `snprint()` + - Added assembly alternatives for various library functions + - CPU support + - Arm Cortex-A53 + - Added workaround for erratum 1530924 + - Arm Cortex-A55 + - Added workaround for erratum 1530923 + - Arm Cortex-A57 + - Added workaround for erratum 1319537 + - Arm Cortex-A76 + - Added workaround for erratum 1165522 + - Added workaround for erratum 1791580 + - Added workaround for erratum 1868343 + - Arm Cortex-A72 + - Added workaround for erratum 1319367 + - Arm Cortex-A77 + - Added workaround for erratum 1508412 + - Added workaround for erratum 1800714 + - Added workaround for erratum 1925769 + - Arm Neoverse-N1 + - Added workaround for erratum 1868343 + - EL3 Runtime + - Added support for saving/restoring registers related to nested + virtualization in EL2 context switches if the architecture supports it + - FCONF + - Added support for Measured Boot + - Added support for populating Chain of Trust properties + - Added support for loading the `fw_config` image + - Measured Boot + - Added support for event logging +- Platforms + - Added support for Arm Morello + - Added support for Arm TC0 + - Added support for iEi PUZZLE-M801 + - Added support for Marvell OCTEON TX2 T9130 + - Added support for MediaTek MT8192 + - Added support for NXP i.MX 8M Nano + - Added support for NXP i.MX 8M Plus + - Added support for QTI CHIP SC7180 + - Added support for STM32MP151F + - Added support for STM32MP153F + - Added support for STM32MP157F + - Added support for STM32MP151D + - Added support for STM32MP153D + - Added support for STM32MP157D + - Arm + - Added support for platform-owned SPs + - Added support for resetting to BL31 + - Arm FPGA + - Added support for Klein + - Added support for Matterhorn + - Added support for additional CPU clusters + - Arm FVP + - Added support for performing SDEI platform setup at runtime + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Added an `id` field under the NV-counter node in the device tree to + differentiate between trusted and non-trusted NV-counters + - Added support for extracting the clock frequency from the timer node in + the device tree + - Arm Juno + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Arm N1SDP + - Added support for cross-chip PCI-e + - Marvell + - Added support for AVS reduction + - Marvell ARMADA + - Added support for twin-die combined memory device + - Marvell ARMADA A8K + - Added support for DDR with 32-bit bus width (both ECC and non-ECC) + - Marvell AP806 + - Added workaround for erratum FE-4265711 + - Marvell AP807 + - Added workaround for erratum 3033912 + - Nvidia Tegra + - Added debug printouts indicating SC7 entry sequence completion + - Added support for SDEI + - Added support for stack protection + - Added support for GICv3 + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - Nvidia Tegra194 + - Added support for RAS exception handling + - Added support for SPM + - NXP i.MX + - Added support for SDEI + - QEMU SBSA + - Added support for the Secure Partition Manager + - QTI + - Added RNG driver + - Added SPMI PMIC arbitrator driver + - Added support for SMCCC's `SMCCC_ARCH_SOC_ID` command + - STM32MP1 + - Added support for exposing peripheral interfaces to the non-secure world + at runtime + - Added support for SCMI clock and reset services + - Added support for STM32MP15x CPU revision Z + - Added support for SMCCC services in `SP_MIN` +- Services + - Secure Payload Dispatcher + - Added a provision to allow clients to retrieve the service UUID + - SPMC + - Added secondary core endpoint information to the SPMC context structure + - SPMD + - Added support for booting OP-TEE as a guest S-EL1 Secure Partition on top + of Hafnium in S-EL2 + - Added a provision for handling SPMC messages to register secondary core + entry points + - Added support for power management operations +- Tools + - CertCreate + - Added support for secure partitions + - CertTool + - Added support for the `fw_config` image + - FIPTool + - Added support for the `fw_config` image + +### Changed + +- Architecture support +- Bootloader images +- Build System + - The top-level Makefile now supports building FipTool on Windows + - The default value of `KEY_SIZE` has been changed to to 2048 when RSA is in + use + - The previously-deprecated macro `__ASSEMBLY__` has now been removed +- Common components + - Certain functions that flush the console will no longer return error + information +- Drivers + - Arm GIC + - Usage of `drivers/arm/gic/common/gic_common.c` has now been deprecated in + favour of `drivers/arm/gic/vX/gicvX.mk` + - Added support for detecting the presence of a GIC600-AE + - Added support for detecting the presence of a GIC-Clayton + - Marvell MCI + - Now performs link tuning for all MCI interfaces to improve performance + - Marvell MoChi + - PIDI masters are no longer forced into a non-secure access level when + `LLC_SRAM` is enabled + - The SD/MMC controllers are now accessible from guest virtual machines + - Mbed TLS + - Migrated to Mbed TLS v2.24.0 + - STM32 FMC2 NAND + - Adjusted FMC node bindings to include an EBI controller node + - STM32 Reset + - Added an optional timeout argument to assertion functions + - STM32MP1 Clocks + - Enabled several additional system clocks during initialization +- Libraries + - C Standard Library + - Improved `memset` performance by avoiding single-byte writes + - Added optimized assembly variants of `memset` + - CPU support + - Renamed Cortex-Hercules to Cortex-A78 + - Renamed Cortex-Hercules AE to Cortex-A78 AE + - Renamed Neoverse Zeus to Neoverse V1 + - Coreboot + - Updated ‘coreboot_get_memory_type’ API to take an extra argument as a + ’memory size’ that used to return a valid memory type. + - libfdt + - Updated to latest upstream version +- Platforms + - Allwinner + - Disabled non-secure access to PRCM power control registers + - Arm + - `BL32_BASE` is now platform-dependent when `SPD_spmd` is enabled + - Added support for loading the Chain of Trust from the device tree + - The firmware update check is now executed only once + - NV-counter base addresses are now loaded from the device tree when + `COT_DESC_IN_DTB` is enabled + - Now loads and populates `fw_config` and `tb_fw_config` + - FCONF population now occurs after caches have been enabled in order to + reduce boot times + - Arm Corstone-700 + - Platform support has been split into both an FVP and an FPGA variant + - Arm FPGA + - DTB and BL33 load addresses have been given sensible default values + - Now reads generic timer counter frequency, GICD and GICR base addresses, + and UART address from DT + - Now treats the primary PL011 UART as an SBSA Generic UART + - Arm FVP + - Secure interrupt descriptions, UART parameters, clock frequencies and + GICv3 parameters are now queried through FCONF + - UART parameters are now queried through the device tree + - Added an owner field to Cactus secure partitions + - Increased the maximum size of BL2 when the Chain of Trust is loaded from + the device tree + - Reduces the maximum size of BL31 + - The `FVP_USE_SP804_TIMER` and `FVP_VE_USE_SP804_TIMER` build options have + been removed in favour of a common `USE_SP804_TIMER` option + - Added a third Cactus partition to manifests + - Device tree nodes now store UUIDs in big-endian + - Arm Juno + - Increased the maximum size of BL2 when optimizations have not been applied + - Reduced the maximum size of BL31 and BL32 + - Marvell AP807 + - Enabled snoop filters + - Marvell ARMADA A3K + - UART recovery images are now suffixed with `.bin` + - Marvell ARMADA A8K + - Option `BL31_CACHE_DISABLE` is now disabled (`0`) by default + - Nvidia Tegra + - Added VPR resize supported check when processing video memory resize + requests + - Added SMMU verification to prevent potential issues caused by undetected + corruption of the SMMU configuration during boot + - The GIC CPU interface is now properly disabled after CPU off + - The GICv2 sources list and the `BL31_SIZE` definition have been made + platform-specific + - The SPE driver will no longer flush the console when writing individual + characters + - Nvidia Tegra194 + - TZDRAM setup has been moved to platform-specific early boot handlers + - Increased verbosity of debug prints for RAS SErrors + - Support for powering down CPUs during CPU suspend has been removed + - Now verifies firewall settings before using resources + - TI K3 + - The UART number has been made configurable through `K3_USART` + - Rockchip RK3368 + - The maximum number of memory map regions has been increased to 20 + - Socionext Uniphier + - The maximum size of BL33 has been increased to support larger bootloaders + - STM32 + - Removed platform-specific DT functions in favour of using existing generic + alternatives + - STM32MP1 + - Increased verbosity of exception reports in debug builds + - Device trees have been updated to align with the Linux kernel + - Now uses the ETZPC driver to configure secure-aware interfaces for + assignment to the non-secure world + - Finished good variants have been added to the board identifier + enumerations + - Non-secure access to clocks and reset domains now depends on their state + of registration + - NEON is now disabled in `SP_MIN` + - The last page of `SYSRAM` is now used as SCMI shared memory + - Checks to verify platform compatibility have been added to verify that an + image is compatible with the chip ID of the running platform + - QEMU SBSA + - Removed support for Arm's Cortex-A53 +- Services + - Renamed SPCI to FF-A + - SPMD + - No longer forwards requests to the non-secure world when retrieving + partition information + - SPMC manifest size is now retrieved directly from SPMD instead of the + device tree + - The FF-A version handler now returns SPMD's version when the origin of the + call is secure, and SPMC's version when the origin of the call is + non-secure + - SPMC + - Updated the manifest to declare CPU nodes in descending order as per the + SPM (Hafnium) multicore requirement + - Updated the device tree to mark 2GB as device memory for the first + partition excluding trusted DRAM region (which is reserved for SPMC) + - Increased the number of EC contexts to the maximum number of PEs as per + the FF-A specification +- Tools + - FIPTool + - Now returns `0` on `help` and `help ` + - Marvell DoImage + - Updated Mbed TLS support to v2.8 + - SPTool + - Now appends CertTool arguments + +### Resolved Issues + +- Bootloader images + - Fixed compilation errors for dual-root Chains of Trust caused by symbol + collision + - BL31 + - Fixed compilation errors on platforms with fewer than 4 cores caused by + initialization code exceeding the end of the stacks + - Fixed compilation errors when building a position-independent image +- Build System + - Fixed invalid empty version strings + - Fixed compilation errors on Windows caused by a non-portable architecture + revision comparison +- Drivers + - Arm GIC + - Fixed spurious interrupts caused by a missing barrier + - STM32 Flexible Memory Controller 2 (FMC2) NAND driver + - Fixed runtime instability caused by incorrect error detection logic + - STM32MP1 Clock driver + - Fixed incorrectly-formatted log messages + - Fixed runtime instability caused by improper clock gating procedures + - STMicroelectronics Raw NAND driver + - Fixed runtime instability caused by incorrect unit conversion when waiting + for NAND readiness +- Libraries + - AMU + - Fixed timeout errors caused by excess error logging + - EL3 Runtime + - Fixed runtime instability caused by improper register save/restore routine + in EL2 + - FCONF + - Fixed failure to initialize GICv3 caused by overly-strict device tree + requirements + - Measured Boot + - Fixed driver errors caused by a missing default value for the `HASH_ALG` + build option + - SPE + - Fixed feature detection check that prevented CPUs supporting SVE from + detecting support for SPE in the non-secure world + - Translation Tables + - Fixed various MISRA-C 2012 static analysis violations +- Platforms + - Allwinner A64 + - Fixed USB issues on certain battery-powered device caused by improperly + activated USB power rail + - Arm + - Fixed compilation errors caused by increase in BL2 size + - Fixed compilation errors caused by missing Makefile dependencies to + generated files when building the FIP + - Fixed MISRA-C 2012 static analysis violations caused by unused structures + in include directives intended to be feature-gated + - Arm FPGA + - Fixed initialization issues caused by incorrect MPIDR topology mapping + logic + - Arm RD-N1-edge + - Fixed compilation errors caused by mismatched parentheses in Makefile + - Arm SGI + - Fixed crashes due to the flash memory used for cold reboot attack + protection not being mapped + - Intel Agilex + - Fixed initialization issues caused by several compounding bugs + - Marvell + - Fixed compilation warnings caused by multiple Makefile inclusions + - Marvell ARMADA A3K + - Fixed boot issue in debug builds caused by checks on the BL33 load address + that are not appropriate for this platform + - Nvidia Tegra + - Fixed incorrect delay timer reads + - Fixed spurious interrupts in the non-secure world during cold boot caused + by the arbitration bit in the memory controller not being cleared + - Fixed faulty video memory resize sequence + - Nvidia Tegra194 + - Fixed incorrect alignment of TZDRAM base address + - NXP iMX8M + - Fixed CPU hot-plug issues caused by race condition + - STM32MP1 + - Fixed compilation errors in highly-parallel builds caused by incorrect + Makefile dependencies + - STM32MP157C-ED1 + - Fixed initialization issues caused by missing device tree hash node + - Raspberry Pi 3 + - Fixed compilation errors caused by incorrect dependency ordering in + Makefile + - Rockchip + - Fixed initialization issues caused by non-critical errors when parsing FDT + being treated as critical + - Rockchip RK3368 + - Fixed runtime instability caused by incorrect CPUID shift value + - QEMU + - Fixed compilation errors caused by incorrect dependency ordering in + Makefile + - QEMU SBSA + - Fixed initialization issues caused by FDT exceeding reserved memory size + - QTI + - Fixed compilation errors caused by inclusion of a non-existent file +- Services + - FF-A (previously SPCI) + - Fixed SPMD aborts caused by incorrect behaviour when the manifest is + page-aligned +- Tools + - Fixed compilation issues when compiling tools from within their respective + directories + - FIPTool + - Fixed command line parsing issues on Windows when using arguments whose + names also happen to be a subset of another's + - Marvell DoImage + - Fixed PKCS signature verification errors at boot on some platforms caused + by generation of misaligned images + +### Known Issues + +- Platforms + - NVIDIA Tegra + - Signed comparison compiler warnings occurring in libfdt are currently + being worked around by disabling the warning for the platform until the + underlying issue is resolved in libfdt + +## [2.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.2..refs/tags/v2.3) (2020-04-20) + +### New Features + +- Arm Architecture + - Add support for Armv8.4-SecEL2 extension through the SPCI defined SPMD/SPMC + components. + - Build option to support EL2 context save and restore in the secure world + (CTX_INCLUDE_EL2_REGS). + - Add support for SMCCC v1.2 (introducing the new SMCCC_ARCH_SOC_ID SMC). Note + that the support is compliant, but the SVE registers save/restore will be + done as part of future S-EL2/SPM development. +- BL-specific + - Enhanced BL2 bootloader flow to load secure partitions based on firmware + configuration data (fconf). + - Changes necessary to support SEPARATE_NOBITS_REGION feature + - TSP and BL2_AT_EL3: Add Position Independent Execution `PIE` support +- Build System + - Add support for documentation build as a target in Makefile + - Add `COT` build option to select the Chain of Trust to use when the Trusted + Boot feature is enabled (default: `tbbr`). + - Added creation and injection of secure partition packages into the FIP. + - Build option to support SPMC component loading and run at S-EL1 or S-EL2 + (SPMD_SPM_AT_SEL2). + - Enable MTE support + - Enable Link Time Optimization in GCC + - Enable -Wredundant-decls warning check + - Makefile: Add support to optionally encrypt BL31 and BL32 + - Add support to pass the nt_fw_config DTB to OP-TEE. + - Introduce per-BL `CPPFLAGS`, `ASFLAGS`, and `LDFLAGS` + - build_macros: Add CREATE_SEQ function to generate sequence of numbers +- CPU Support + - cortex-a57: Enable higher performance non-cacheable load forwarding + - Hercules: Workaround for Errata 1688305 + - Klein: Support added for Klein CPU + - Matterhorn: Support added for Matterhorn CPU +- Drivers + - auth: Add `calc_hash` function for hash calculation. Used for authentication + of images when measured boot is enabled. + - cryptocell: Add authenticated decryption framework, and support for + CryptoCell-713 and CryptoCell-712 RSA 3K + - gic600: Add support for multichip configuration and Clayton + - gicv3: Introduce makefile, Add extended PPI and SPI range, Add support for + probing multiple GIC Redistributor frames + - gicv4: Add GICv4 extension for GIC driver + - io: Add an IO abstraction layer to load encrypted firmwares + - mhu: Derive doorbell base address + - mtd: Add SPI-NOR, SPI-NAND, SPI-MEM, and raw NAND framework + - scmi: Allow use of multiple SCMI channels + - scu: Add a driver for snoop control unit +- Libraries + - coreboot: Add memory range parsing and use generic base address + - compiler_rt: Import popcountdi2.c and popcountsi2.c files, aeabi_ldivmode.S + file and dependencies + - debugFS: Add DebugFS functionality + - el3_runtime: Add support for enabling S-EL2 + - fconf: Add Firmware Configuration Framework (fconf) (experimental). + - libc: Add memrchr function + - locks: bakery: Use is_dcache_enabled() helper and add a DMB to the + 'read_cache_op' macro + - psci: Add support to enable different personality of the same soc. + - xlat_tables_v2: Add support to pass shareability attribute for normal memory + region, use get_current_el_maybe_constant() in is_dcache_enabled(), + read-only xlat tables for BL31 memory, and add enable_mmu() +- New Platforms Support + - arm/arm_fpga: New platform support added for FPGA + - arm/rddaniel: New platform support added for rd-daniel platform + - brcm/stingray: New platform support added for Broadcom stingray platform + - nvidia/tegra194: New platform support for Nvidia Tegra194 platform +- Platforms + - allwinner: Implement PSCI system suspend using SCPI, add a msgbox driver for + use with SCPI, and reserve and map space for the SCP firmware + - allwinner: axp: Add AXP805 support + - allwinner: power: Add DLDO4 power rail + - amlogic: axg: Add a build flag when using ATOS as BL32 and support for the + A113D (AXG) platform + - arm/a5ds: Add ethernet node and L2 cache node in devicetree + - arm/common: Add support for the new `dualroot` chain of trust + - arm/common: Add support for SEPARATE_NOBITS_REGION + - arm/common: Re-enable PIE when RESET_TO_BL31=1 + - arm/common: Allow boards to specify second DRAM Base address and to define + PLAT_ARM_TZC_FILTERS + - arm/corstone700: Add support for mhuv2 and stack protector + - arm/fvp: Add support for fconf in BL31 and SP_MIN. Populate power domain + descriptor dynamically by leveraging fconf APIs. + - arm/fvp: Add Cactus/Ivy Secure Partition information and use two instances + of Cactus at S-EL1 + - arm/fvp: Add support to run BL32 in TDRAM and BL31 in secure DRAM + - arm/fvp: Add support for GICv4 extension and BL2 hash calculation in BL1 + - arm/n1sdp: Setup multichip gic routing table, update platform macros for + dual-chip setup, introduce platform information SDS region, add support to + update presence of External LLC, and enable the NEOVERSE_N1_EXTERNAL_LLC + flag + - arm/rdn1edge: Add support for dual-chip configuration and use CREATE_SEQ + helper macro to compare chip count + - arm/sgm: Always use SCMI for SGM platforms + - arm/sgm775: Add support for dynamic config using fconf + - arm/sgi: Add multi-chip mode parameter in HW_CONFIG dts, macros for remote + chip device region, chip_id and multi_chip_mode to platform variant info, + and introduce number of chips macro + - brcm: Add BL2 and BL31 support common across Broadcom platforms + - brcm: Add iproc SPI Nor flash support, spi driver, emmc driver, and support + to retrieve plat_toc_flags + - hisilicon: hikey960: Enable system power off callback + - intel: Enable bridge access, SiP SMC secure register access, and uboot + entrypoint support + - intel: Implement platform specific system reset 2 + - intel: Introduce mailbox response length handling + - imx: console: Use CONSOLE_T_BASE for UART base address and generic console_t + data structure + - imx8mm: Provide uart base as build option and add the support for opteed spd + on imx8mq/imx8mm + - imx8qx: Provide debug uart num as build + - imx8qm: Apply clk/pinmux configuration for DEBUG_CONSOLE and provide debug + uart num as build param + - marvell: a8k: Implement platform specific power off and add support for + loading MG CM3 images + - mediatek: mt8183: Add Vmodem/Vcore DVS init level + - qemu: Support optional encryption of BL31 and BL32 images and + ARM_LINUX_KERNEL_AS_BL33 to pass FDT address + - qemu: Define ARMV7_SUPPORTS_VFP + - qemu: Implement PSCI_CPU_OFF and qemu_system_off via semihosting + - renesas: rcar_gen3: Add new board revision for M3ULCB + - rockchip: Enable workaround for erratum 855873, claim a macro to enable hdcp + feature for DP, enable power domains of rk3399 before reset, add support for + UART3 as serial output, and initialize reset and poweroff GPIOs with known + invalid value + - rpi: Implement PSCI CPU_OFF, use MMIO accessor, autodetect Mini-UART vs. + PL011 configuration, and allow using PL011 UART for RPi3/RPi4 + - rpi3: Include GPIO driver in all BL stages and use same "clock-less" setup + scheme as RPi4 + - rpi3/4: Add support for offlining CPUs + - st: stm32mp1: platform.mk: Support generating multiple images in one build, + migrate to implicit rules, derive map file name from target name, generate + linker script with fixed name, and use PHONY for the appropriate targets + - st: stm32mp1: Add support for SPI-NOR, raw NAND, and SPI-NAND boot device, + QSPI, FMC2 driver + - st: stm32mp1: Use stm32mp_get_ddr_ns_size() function, set XN attribute for + some areas in BL2, dynamically map DDR later and non-cacheable during its + test, add a function to get non-secure DDR size, add DT helper for reg by + name, and add compilation flags for boot devices + - socionext: uniphier: Turn on ENABLE_PIE + - ti: k3: Add PIE support + - xilinx: versal: Add set wakeup source, client wakeup, query data, request + wakeup, PM_INIT_FINALIZE, PM_GET_TRUSTZONE_VERSION, PM IOCTL, support for + suspend related, and Get_ChipID APIs + - xilinx: versal: Implement power down/restart related EEMI, SMC handler for + EEMI, PLL related PM, clock related PM, pin control related PM, reset + related PM, device related PM , APIs + - xilinx: versal: Enable ipi mailbox service + - xilinx: versal: Add get_api_version support and support to send PM API to + PMC using IPI + - xilinx: zynqmp: Add checksum support for IPI data, GET_CALLBACK_DATA + function, support to query max divisor, CLK_SET_RATE_PARENT in gem clock + node, support for custom type flags, LPD WDT clock to the pm_clock + structure, idcodes for new RFSoC silicons ZU48DR and ZU49DR, and id for new + RFSoC device ZU39DR +- Security + - Use Speculation Barrier instruction for v8.5+ cores + - Add support for optional firmware encryption feature (experimental). + - Introduce a new `dualroot` chain of trust. + - aarch64: Prevent speculative execution past ERET + - aarch32: Stop speculative execution past exception returns. +- SPCI + - Introduced the Secure Partition Manager Dispatcher (SPMD) component as a new + standard service. +- Tools + - cert_create: Introduce CoT build option and TBBR CoT makefile, and define + the dualroot CoT + - encrypt_fw: Add firmware authenticated encryption tool + - memory: Add show_memory script that prints a representation of the memory + layout for the latest build + +### Changed + +- Arm Architecture + - PIE: Make call to GDT relocation fixup generalized +- BL-Specific + - Increase maximum size of BL2 image + - BL31: Discard .dynsym .dynstr .hash sections to make ENABLE_PIE work + - BL31: Split into two separate memory regions + - Unify BL linker scripts and reduce code duplication. +- Build System + - Changes to drive cert_create for dualroot CoT + - Enable -Wlogical-op always + - Enable -Wshadow always + - Refactor the warning flags + - PIE: Pass PIE options only to BL31 + - Reduce space lost to object alignment + - Set lld as the default linker for Clang builds + - Remove -Wunused-const-variable and -Wpadded warning + - Remove -Wmissing-declarations warning from WARNING1 level +- Drivers + - authentication: Necessary fix in drivers to upgrade to mbedtls-2.18.0 + - console: Integrate UART base address in generic console_t + - gicv3: Change API for GICR_IPRIORITYR accessors and separate GICD and GICR + accessor functions + - io: Change seek offset to signed long long and panic in case of io setup + failure + - smmu: SMMUv3: Changed retry loop to delay timer + - tbbr: Reduce size of hash and ECDSA key buffers when possible +- Library Code + - libc: Consolidate the size_t, unified, and NULL definitions, and unify + intmax_t and uintmax_t on AArch32/64 + - ROMLIB: Optimize memory layout when ROMLIB is used + - xlat_tables_v2: Use ARRAY_SIZE in REGISTER_XLAT_CONTEXT_FULL_SPEC, merge + REGISTER_XLAT_CONTEXT\_{FULL_SPEC,RO_BASE_TABLE}, and simplify end address + checks in mmap_add_region_check() +- Platforms + - allwinner: Adjust SRAM A2 base to include the ARISC vectors, clean up MMU + setup, reenable USE_COHERENT_MEM, remove unused include path, move the + NOBITS region to SRAM A1, convert AXP803 regulator setup code into a driver, + enable clock before resetting I2C/RSB + - allwinner: h6: power: Switch to using the AXP driver + - allwinner: a64: power: Use fdt_for_each_subnode, remove obsolete register + check, remove duplicate DT check, and make sunxi_turn_off_soc static + - allwinner: Build PMIC bus drivers only in BL31, clean up PMIC-related error + handling, and synchronize PMIC enumerations + - arm/a5ds: Change boot address to point to DDR address + - arm/common: Check for out-of-bound accesses in the platform io policies + - arm/corstone700: Updating the kernel arguments to support initramfs, use + fdts DDR memory and XIP rootfs, and set UART clocks to 32MHz + - arm/fvp: Modify multithreaded dts file of DynamIQ FVPs, slightly bump the + stack size for bl1 and bl2, remove re-definition of topology related build + options, stop reclaiming init code with Clang builds, and map only the + needed DRAM region statically in BL31/SP_MIN + - arm/juno: Maximize space allocated to SCP_BL2 + - arm/sgi: Bump bl1 RW limit, mark remote chip shared ram as non-cacheable, + move GIC related constants to board files, include AFF3 affinity in core + position calculation, move bl31_platform_setup to board file, and move + topology information to board folder + - common: Refactor load_auth_image_internal(). + - hisilicon: Remove uefi-tools in hikey and hikey960 documentation + - intel: Modify non secure access function, BL31 address mapping, mailbox's + get_config_status, and stratix10 BL31 parameter handling + - intel: Remove un-needed checks for qspi driver r/w and s10 unused source + code + - intel: Change all global sip function to static + - intel: Refactor common platform code + - intel: Create SiP service header file + - marvell: armada: scp_bl2: Allow loading up to 8 images + - marvell: comphy-a3700: Support SGMII COMPHY power off and fix USB3 powering + on when on lane 2 + - marvell: Consolidate console register calls + - mediatek: mt8183: Protect 4GB~8GB dram memory, refine GIC driver for low + power scenarios, and switch PLL/CLKSQ/ck_off/axi_26m control to SPM + - qemu: Update flash address map to keep FIP in secure FLASH0 + - renesas: rcar_gen3: Update IPL and Secure Monitor Rev.2.0.6, update DDR + setting for H3, M3, M3N, change fixed destination address of BL31 and BL32, + add missing #{address,size}-cells into generated DT, pass DT to OpTee OS, + and move DDR drivers out of staging + - rockchip: Make miniloader ddr_parameter handling optional, cleanup securing + of ddr regions, move secure init to separate file, use base+size for secure + ddr regions, bring TZRAM_SIZE values in lined, and prevent macro expansion + in paths + - rpi: Move plat_helpers.S to common + - rpi3: gpio: Simplify GPIO setup + - rpi4: Skip UART initialisation + - st: stm32m1: Use generic console_t data structure, remove second QSPI flash + instance, update for FMC2 pin muxing, and reduce MAX_XLAT_TABLES to 4 + - socionext: uniphier: Make on-chip SRAM and I/O register regions configurable + - socionext: uniphier: Make PSCI related, counter control, UART, pinmon, NAND + controller, and eMMC controller base addresses configurable + - socionext: uniphier: Change block_addressing flag and the return value type + of .is_usb_boot() to bool + - socionext: uniphier: Run BL33 at EL2, call uniphier_scp_is_running() only + when on-chip STM is supported, define PLAT_XLAT_TABLES_DYNAMIC only for BL2, + support read-only xlat tables, use enable_mmu() in common function, shrink + UNIPHIER_ROM_REGION_SIZE, prepare uniphier_soc_info() for next SoC, extend + boot device detection for future SoCs, make all BL images completely + position-independent, make uniphier_mmap_setup() work with PIE, pass SCP + base address as a function parameter, set buffer offset and length for + io_block dynamically, and use more mmap_add_dynamic_region() for loading + images + - spd/trusty: Disable error messages seen during boot, allow gic base to be + specified with GICD_BASE, and allow getting trusty memsize from + BL32_MEM_SIZE instead of TSP_SEC_MEM_SIZE + - ti: k3: common: Enable ARM cluster power down and rename device IDs to be + more consistent + - ti: k3: drivers: ti_sci: Put sequence number in coherent memory and remove + indirect structure of const data + - xilinx: Move ipi mailbox svc to xilinx common + - xilinx: zynqmp: Use GIC framework for warm restart + - xilinx: zynqmp: pm: Move custom clock flags to typeflags, remove + CLK_TOPSW_LSBUS from invalid clock list and rename FPD WDT clock ID + - xilinx: versal: Increase OCM memory size for DEBUG builds and adjust cpu + clock, Move versal_def.h and versal_private to include directory +- Tools + - sptool: Updated sptool to accommodate building secure partition packages. + +### Resolved Issues + +- Arm Architecture + - Fix crash dump for lower EL +- BL-Specific + - Bug fix: Protect TSP prints with lock + - Fix boot failures on some builds linked with ld.lld. +- Build System + - Fix clang build if CC is not in the path. + - Fix 'BL stage' comment for build macros +- Code Quality + - coverity: Fix various MISRA violations including null pointer violations, C + issues in BL1/BL2/BL31 and FDT helper functions, using boolean essential, + type, and removing unnecessary header file and comparisons to LONG_MAX in + debugfs devfip + - Based on coding guidelines, replace all `unsigned long` depending on if + fixed based on AArch32 or AArch64. + - Unify type of "cpu_idx" and Platform specific defines across PSCI module. +- Drivers + - auth: Necessary fix in drivers to upgrade to mbedtls-2.18.0 + - delay_timer: Fix non-standard frequency issue in udelay + - gicv3: Fix compiler dependent behavior + - gic600: Fix include ordering according to the coding style and power up + sequence +- Library Code + - el3_runtime: Fix stack pointer maintenance on EA handling path, fixup + 'cm_setup_context' prototype, and adds TPIDR_EL2 register to the context + save restore routines + - libc: Fix SIZE_MAX on AArch32 + - locks: T589: Fix insufficient ordering guarantees in bakery lock + - pmf: Fix 'tautological-constant-compare' error, Make the runtime + instrumentation work on AArch32, and Simplify PMF helper macro definitions + across header files + - xlat_tables_v2: Fix assembler warning of PLAT_RO_XLAT_TABLES +- Platforms + - allwinner: Fix H6 GPIO and CCU memory map addresses and incorrect ARISC code + patch offset check + - arm/a5ds: Correct system freq and Cache Writeback Granule, and cleanup + enable-method in devicetree + - arm/fvp: Fix incorrect GIC mapping, BL31 load address and image size for + RESET_TO_BL31=1, topology description of cpus for DynamIQ based FVP, and + multithreaded FVP power domain tree + - arm/fvp: spm-mm: Correcting instructions to build SPM for FVP + - arm/common: Fix ROTPK hash generation for ECDSA encryption, BL2 bug in + dynamic configuration initialisation, and current RECLAIM_INIT_CODE behavior + - arm/rde1edge: Fix incorrect topology tree description + - arm/sgi: Fix the incorrect check for SCMI channel ID + - common: Flush dcache when storing timestamp + - intel: Fix UEFI decompression issue, memory calibration, SMC SIP service, + mailbox config return status, mailbox driver logic, FPGA manager on + reconfiguration, and mailbox send_cmd issue + - imx: Fix shift-overflow errors, the rdc memory region slot's offset, + multiple definition of ipc_handle, missing inclusion of cdefs.h, and correct + the SGIs that used for secure interrupt + - mediatek: mt8183: Fix AARCH64 init fail on CPU0 + - rockchip: Fix definition of struct param_ddr_usage + - rpi4: Fix documentation of armstub config entry + - st: Correct io possible NULL pointer dereference and device_size type, nand + xor_ecc.val assigned value, static analysis tool issues, and fix incorrect + return value and correctly check pwr-regulators node + - xilinx: zynqmp: Correct syscnt freq for QEMU and fix clock models and IDs of + GEM-related clocks + +### Known Issues + +- Build System + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. + + - Intermittent assertion firing `ASSERT: services/spd/tspd/tspd_main.c:105` +- Coverity + - Intermittent Race condition in Coverity Jenkins Build Job +- Platforms + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - mediatek/mt6795: This platform does not build in this release + +## [2.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.1..refs/tags/v2.2) (2019-10-22) + +### New Features + +- Architecture + - Enable Pointer Authentication (PAuth) support for Secure World + + - Adds support for ARMv8.3-PAuth in BL1 SMC calls and BL2U image for + firmware updates. + + - Enable Memory Tagging Extension (MTE) support in both secure and non-secure + worlds + + - Adds support for the new Memory Tagging Extension arriving in ARMv8.5. MTE + support is now enabled by default on systems that support it at EL0. + - To enable it at ELx for both the non-secure and the secure world, the + compiler flag `CTX_INCLUDE_MTE_REGS` includes register saving and + restoring when necessary in order to prevent information leakage between + the worlds. + + - Add support for Branch Target Identification (BTI) +- Build System + - Modify FVP makefile for CPUs that support both AArch64/32 + - AArch32: Allow compiling with soft-float toolchain + - Makefile: Add default warning flags + - Add Makefile check for PAuth and AArch64 + - Add compile-time errors for HW_ASSISTED_COHERENCY flag + - Apply compile-time check for AArch64-only CPUs + - build_macros: Add mechanism to prevent bin generation. + - Add support for default stack-protector flag + - spd: opteed: Enable NS_TIMER_SWITCH + - plat/arm: Skip BL2U if RESET_TO_SP_MIN flag is set + - Add new build option to let each platform select which implementation of + spinlocks it wants to use +- CPU Support + - DSU: Workaround for erratum 798953 and 936184 + - Neoverse N1: Force cacheable atomic to near atomic + - Neoverse N1: Workaround for erratum 1073348, 1130799, 1165347, 1207823, + 1220197, 1257314, 1262606, 1262888, 1275112, 1315703, 1542419 + - Neoverse Zeus: Apply the MSR SSBS instruction + - cortex-Hercules/HerculesAE: Support added for Cortex-Hercules and + Cortex-HerculesAE CPUs + - cortex-Hercules/HerculesAE: Enable AMU for Cortex-Hercules and + Cortex-HerculesAE + - cortex-a76AE: Support added for Cortex-A76AE CPU + - cortex-a76: Workaround for erratum 1257314, 1262606, 1262888, 1275112, + 1286807 + - cortex-a65/a65AE: Support added for Cortex-A65 and Cortex-A65AE CPUs + - cortex-a65: Enable AMU for Cortex-A65 + - cortex-a55: Workaround for erratum 1221012 + - cortex-a35: Workaround for erratum 855472 + - cortex-a9: Workaround for erratum 794073 +- Drivers + - console: Allow the console to register multiple times + + - delay: Timeout detection support + + - gicv3: Enabled multi-socket GIC redistributor frame discovery and migrated + ARM platforms to the new API + + - Adds `gicv3_rdistif_probe` function that delegates the responsibility of + discovering the corresponding redistributor base frame to each CPU itself. + + - sbsa: Add SBSA watchdog driver + + - st/stm32_hash: Add HASH driver + + - ti/uart: Add an AArch32 variant +- Library at ROM (romlib) + - Introduce BTI support in Library at ROM (romlib) +- New Platforms Support + - amlogic: g12a: New platform support added for the S905X2 (G12A) platform + - amlogic: meson/gxl: New platform support added for Amlogic Meson S905x (GXL) + - arm/a5ds: New platform support added for A5 DesignStart + - arm/corstone: New platform support added for Corstone-700 + - intel: New platform support added for Agilex + - mediatek: New platform support added for MediaTek mt8183 + - qemu/qemu_sbsa: New platform support added for QEMU SBSA platform + - renesas/rcar_gen3: plat: New platform support added for D3 + - rockchip: New platform support added for px30 + - rockchip: New platform support added for rk3288 + - rpi: New platform support added for Raspberry Pi 4 +- Platforms + - arm/common: Introduce wrapper functions to setup secure watchdog + - arm/fvp: Add Delay Timer driver to BL1 and BL31 and option for defining + platform DRAM2 base + - arm/fvp: Add Linux DTS files for 32 bit threaded FVPs + - arm/n1sdp: Add code for DDR ECC enablement and BL33 copy to DDR, Initialise + CNTFRQ in Non Secure CNTBaseN + - arm/juno: Use shared mbedtls heap between BL1 and BL2 and add basic support + for dynamic config + - imx: Basic support for PicoPi iMX7D, rdc module init, caam module init, + aipstz init, IMX_SIP_GET_SOC_INFO, IMX_SIP_BUILDINFO added + - intel: Add ncore ccu driver + - mediatek/mt81\*: Use new bl31_params_parse() helper + - nvidia: tegra: Add support for multi console interface + - qemu/qemu_sbsa: Adding memory mapping for both FLASH0/FLASH1 + - qemu: Added gicv3 support, new console interface in AArch32, and + sub-platforms + - renesas/rcar_gen3: plat: Add R-Car V3M support, new board revision for + H3ULCB, DBSC4 setting before self-refresh mode + - socionext/uniphier: Support console based on multi-console + - st: stm32mp1: Add OP-TEE, Avenger96, watchdog, LpDDR3, authentication + support and general SYSCFG management + - ti/k3: common: Add support for J721E, Use coherent memory for shared data, + Trap all asynchronous bus errors to EL3 + - xilinx/zynqmp: Add support for multi console interface, Initialize IPI table + from zynqmp_config_setup() +- PSCI + - Adding new optional PSCI hook `pwr_domain_on_finish_late` + - This PSCI hook `pwr_domain_on_finish_late` is similar to + `pwr_domain_on_finish` but is guaranteed to be invoked when the respective + core and cluster are participating in coherency. +- Security + - Speculative Store Bypass Safe (SSBS): Further enhance protection against + Spectre variant 4 by disabling speculative loads/stores (SPSR.SSBS bit) by + default. + - UBSAN support and handlers + - Adds support for the Undefined Behaviour sanitizer. There are two types of + support offered - minimalistic trapping support which essentially + immediately crashes on undefined behaviour and full support with full + debug messages. +- Tools + - cert_create: Add support for bigger RSA key sizes (3KB and 4KB), previously + the maximum size was 2KB. + - fiptool: Add support to build fiptool on Windows. + +### Changed + +- Architecture + - Refactor ARMv8.3 Pointer Authentication support code + - backtrace: Strip PAC field when PAUTH is enabled + - Prettify crash reporting output on AArch64. + - Rework smc_unknown return code path in smc_handler + - Leverage the existing `el3_exit()` return routine for smc_unknown return + path rather than a custom set of instructions. +- BL-Specific + - Invalidate dcache build option for BL2 entry at EL3 + - Add missing support for BL2_AT_EL3 in XIP memory +- Boot Flow + - Add helper to parse BL31 parameters (both versions) + - Factor out cross-BL API into export headers suitable for 3rd party code + - Introduce lightweight BL platform parameter library +- Drivers + - auth: Memory optimization for Chain of Trust (CoT) description + - bsec: Move bsec_mode_is_closed_device() service to platform + - cryptocell: Move Cryptocell specific API into driver + - gicv3: Prevent pending G1S interrupt from becoming G0 interrupt + - mbedtls: Remove weak heap implementation + - mmc: Increase delay between ACMD41 retries + - mmc: stm32_sdmmc2: Correctly manage block size + - mmc: stm32_sdmmc2: Manage max-frequency property from DT + - synopsys/emmc: Do not change FIFO TH as this breaks some platforms + - synopsys: Update synopsys drivers to not rely on undefined overflow + behaviour + - ufs: Extend the delay after reset to wait for some slower chips +- Platforms + - amlogic/meson/gxl: Remove BL2 dependency from BL31 + - arm/common: Shorten the Firmware Update (FWU) process + - arm/fvp: Remove GIC initialisation from secondary core cold boot + - arm/sgm: Temporarily disable shared Mbed TLS heap for SGM + - hisilicon: Update hisilicon drivers to not rely on undefined overflow + behaviour + - imx: imx8: Replace PLAT_IMX8\* with PLAT_imx8\*, remove duplicated linker + symbols and deprecated code include, keep only IRQ 32 unmasked, enable all + power domain by default + - marvell: Prevent SError accessing PCIe link, Switch to xlat_tables_v2, do + not rely on argument passed via smc, make sure that comphy init will use + correct address + - mediatek: mt8173: Refactor RTC and PMIC drivers + - mediatek: mt8173: Apply MULTI_CONSOLE framework + - nvidia: Tegra: memctrl_v2: fix "overflow before widen" coverity issue + - qemu: Simplify the image size calculation, Move and generalise FDT PSCI + fixup, move gicv2 codes to separate file + - renesas/rcar_gen3: Convert to multi-console API, update QoS setting, Update + IPL and Secure Monitor Rev2.0.4, Change to restore timer counter value at + resume, Update DDR setting rev.0.35, qos: change subslot cycle, Change + periodic write DQ training option. + - rockchip: Allow SOCs with undefined wfe check bits, Streamline and complete + UARTn_BASE macros, drop rockchip-specific imported linker symbols for bl31, + Disable binary generation for all SOCs, Allow console device to be set by + DTB, Use new bl31_params_parse functions + - rpi/rpi3: Move shared rpi3 files into common directory + - socionext/uniphier: Set CONSOLE_FLAG_TRANSLATE_CRLF and clean up console + driver + - socionext/uniphier: Replace DIV_ROUND_UP() with div_round_up() from + utils_def.h + - st/stm32mp: Split stm32mp_io_setup function, move + stm32_get_gpio_bank_clock() to private file, correctly handle Clock + Spreading Generator, move oscillator functions to generic file, realign + device tree files with internal devs, enable RTCAPB clock for dual-core + chips, use a common function to check spinlock is available, move + check_header() to common code + - ti/k3: Enable SEPARATE_CODE_AND_RODATA by default, Remove shared RAM space, + Drop \_ADDRESS from K3_USART_BASE to match other defines, Remove MSMC port + definitions, Allow USE_COHERENT_MEM for K3, Set L2 latency on A72 cores +- PSCI + - PSCI: Lookup list of parent nodes to lock only once +- Secure Partition Manager (SPM): SPCI Prototype + - Fix service UUID lookup + - Adjust size of virtual address space per partition + - Refactor xlat context creation + - Move shim layer to TTBR1_EL1 + - Ignore empty regions in resource description +- Security + - Refactor SPSR initialisation code + - SMMUv3: Abort DMA transactions + - For security DMA should be blocked at the SMMU by default unless + explicitly enabled for a device. SMMU is disabled after reset with all + streams bypassing the SMMU, and abortion of all incoming transactions + implements a default deny policy on reset. + - Moves `bl1_platform_setup()` function from arm_bl1_setup.c to FVP + platforms' fvp_bl1_setup.c and fvp_ve_bl1_setup.c files. +- Tools + - cert_create: Remove RSA PKCS#1 v1.5 support + +### Resolved Issues + +- Architecture + - Fix the CAS spinlock implementation by adding a missing DSB in + `spin_unlock()` + - AArch64: Fix SCTLR bit definitions + - Removes incorrect `SCTLR_V_BIT` definition and adds definitions for + ARMv8.3-Pauth `EnIB`, `EnDA` and `EnDB` bits. + - Fix restoration of PAuth context + - Replace call to `pauth_context_save()` with `pauth_context_restore()` in + case of unknown SMC call. +- BL-Specific Issues + - Fix BL31 crash reporting on AArch64 only platforms +- Build System + - Remove several warnings reported with W=2 and W=1 +- Code Quality Issues + - SCTLR and ACTLR are 32-bit for AArch32 and 64-bit for AArch64 + - Unify type of "cpu_idx" across PSCI module. + - Assert if power level value greater then PSCI_INVALID_PWR_LVL + - Unsigned long should not be used as per coding guidelines + - Reduce the number of memory leaks in cert_create + - Fix type of cot_desc_ptr + - Use explicit-width data types in AAPCS parameter structs + - Add python configuration for editorconfig + - BL1: Fix type consistency + - Enable -Wshift-overflow=2 to check for undefined shift behavior + - Updated upstream platforms to not rely on undefined overflow behaviour +- Coverity Quality Issues + - Remove GGC ignore -Warray-bounds + - Fix Coverity #261967, Infinite loop + - Fix Coverity #343017, Missing unlock + - Fix Coverity #343008, Side affect in assertion + - Fix Coverity #342970, Uninitialized scalar variable +- CPU Support + - cortex-a12: Fix MIDR mask +- Drivers + - console: Remove Arm console unregister on suspend + - gicv3: Fix support for full SPI range + - scmi: Fix wrong payload length +- Library Code + - libc: Fix sparse warning for \_\_assert() + - libc: Fix memchr implementation +- Platforms + - rpi: rpi3: Fix compilation error when stack protector is enabled + - socionext/uniphier: Fix compilation fail for SPM support build config + - st/stm32mp1: Fix TZC400 configuration against non-secure DDR + - ti/k3: common: Fix RO data area size calculation +- Security + - AArch32: Disable Secure Cycle Counter + - Changes the implementation for disabling Secure Cycle Counter. For ARMv8.5 + the counter gets disabled by setting `SDCR.SCCD` bit on CPU cold/warm + boot. For the earlier architectures PMCR register is saved/restored on + secure world entry/exit from/to Non-secure state, and cycle counting gets + disabled by setting PMCR.DP bit. + - AArch64: Disable Secure Cycle Counter + - For ARMv8.5 the counter gets disabled by setting `MDCR_El3.SCCD` bit on + CPU cold/warm boot. For the earlier architectures PMCR_EL0 register is + saved/restored on secure world entry/exit from/to Non-secure state, and + cycle counting gets disabled by setting PMCR_EL0.DP bit. + +### Deprecations + +- Common Code + - Remove MULTI_CONSOLE_API flag and references to it + - Remove deprecated `plat_crash_console_*` + - Remove deprecated interfaces `get_afflvl_shift`, `mpidr_mask_lower_afflvls`, + `eret` + - AARCH32/AARCH64 macros are now deprecated in favor of `__aarch64__` + - `__ASSEMBLY__` macro is now deprecated in favor of `__ASSEMBLER__` +- Drivers + - console: Removed legacy console API + - console: Remove deprecated finish_console_register + - tzc: Remove deprecated types `tzc_action_t` and `tzc_region_attributes_t` +- Secure Partition Manager (SPM): + - Prototype SPCI-based SPM (services/std_svc/spm) will be replaced with + alternative methods of secure partitioning support. + +### Known Issues + +- Build System Issues + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. +- Platform Issues + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - mediatek/mt6795: This platform does not build in this release + +## [2.1.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v2.0..refs/tags/v2.1) (2019-03-29) + +### New Features + +- Architecture + + - Support for ARMv8.3 pointer authentication in the normal and secure worlds + + The use of pointer authentication in the normal world is enabled whenever + architectural support is available, without the need for additional build + flags. + + Use of pointer authentication in the secure world remains an experimental + configuration at this time. Using both the `ENABLE_PAUTH` and + `CTX_INCLUDE_PAUTH_REGS` build flags, pointer authentication can be enabled + in EL3 and S-EL1/0. + + See the {ref}`Firmware Design` document for additional details on the use of + pointer authentication. + + - Enable Data Independent Timing (DIT) in EL3, where supported + +- Build System + + - Support for BL-specific build flags + + - Support setting compiler target architecture based on `ARM_ARCH_MINOR` build + option. + + - New `RECLAIM_INIT_CODE` build flag: + + A significant amount of the code used for the initialization of BL31 is not + needed again after boot time. In order to reduce the runtime memory + footprint, the memory used for this code can be reclaimed after + initialization. + + Certain boot-time functions were marked with the `__init` attribute to + enable this reclamation. + +- CPU Support + + - cortex-a76: Workaround for erratum 1073348 + - cortex-a76: Workaround for erratum 1220197 + - cortex-a76: Workaround for erratum 1130799 + - cortex-a75: Workaround for erratum 790748 + - cortex-a75: Workaround for erratum 764081 + - cortex-a73: Workaround for erratum 852427 + - cortex-a73: Workaround for erratum 855423 + - cortex-a57: Workaround for erratum 817169 + - cortex-a57: Workaround for erratum 814670 + - cortex-a55: Workaround for erratum 903758 + - cortex-a55: Workaround for erratum 846532 + - cortex-a55: Workaround for erratum 798797 + - cortex-a55: Workaround for erratum 778703 + - cortex-a55: Workaround for erratum 768277 + - cortex-a53: Workaround for erratum 819472 + - cortex-a53: Workaround for erratum 824069 + - cortex-a53: Workaround for erratum 827319 + - cortex-a17: Workaround for erratum 852423 + - cortex-a17: Workaround for erratum 852421 + - cortex-a15: Workaround for erratum 816470 + - cortex-a15: Workaround for erratum 827671 + +- Documentation + + - Exception Handling Framework documentation + - Library at ROM (romlib) documentation + - RAS framework documentation + - Coding Guidelines document + +- Drivers + + - ccn: Add API for setting and reading node registers + + - Adds `ccn_read_node_reg` function + - Adds `ccn_write_node_reg` function + + - partition: Support MBR partition entries + + - scmi: Add `plat_css_get_scmi_info` function + + Adds a new API `plat_css_get_scmi_info` which lets the platform register a + platform-specific instance of `scmi_channel_plat_info_t` and remove the + default values + + - tzc380: Add TZC-380 TrustZone Controller driver + + - tzc-dmc620: Add driver to manage the TrustZone Controller within the DMC-620 + Dynamic Memory Controller + +- Library at ROM (romlib) + + - Add platform-specific jump table list + + - Allow patching of romlib functions + + This change allows patching of functions in the romlib. This can be done by + adding "patch" at the end of the jump table entry for the function that + needs to be patched in the file jmptbl.i. + +- Library Code + + - Support non-LPAE-enabled MMU tables in AArch32 + - mmio: Add `mmio_clrsetbits_16` function + - 16-bit variant of `mmio_clrsetbits` + - object_pool: Add Object Pool Allocator + - Manages object allocation using a fixed-size static array + - Adds `pool_alloc` and `pool_alloc_n` functions + - Does not provide any functions to free allocated objects (by design) + - libc: Added `strlcpy` function + - libc: Import `strrchr` function from FreeBSD + - xlat_tables: Add support for ARMv8.4-TTST + - xlat_tables: Support mapping regions without an explicitly specified VA + +- Math + + - Added softudiv macro to support software division + +- Memory Partitioning And Monitoring (MPAM) + + - Enabled MPAM EL2 traps (`MPAMHCR_EL2` and `MPAM_EL2`) + +- Platforms + + - amlogic: Add support for Meson S905 (GXBB) + + - arm/fvp_ve: Add support for FVP Versatile Express platform + + - arm/n1sdp: Add support for Neoverse N1 System Development platform + + - arm/rde1edge: Add support for Neoverse E1 platform + + - arm/rdn1edge: Add support for Neoverse N1 platform + + - arm: Add support for booting directly to Linux without an intermediate + loader (AArch32) + + - arm/juno: Enable new CPU errata workarounds for A53 and A57 + + - arm/juno: Add romlib support + + Building a combined BL1 and ROMLIB binary file with the correct page + alignment is now supported on the Juno platform. When `USE_ROMLIB` is set + for Juno, it generates the combined file `bl1_romlib.bin` which needs to be + used instead of bl1.bin. + + - intel/stratix: Add support for Intel Stratix 10 SoC FPGA platform + + - marvell: Add support for Armada-37xx SoC platform + + - nxp: Add support for i.MX8M and i.MX7 Warp7 platforms + + - renesas: Add support for R-Car Gen3 platform + + - xilinx: Add support for Versal ACAP platforms + +- Position-Independent Executable (PIE) + + PIE support has initially been added to BL31. The `ENABLE_PIE` build flag is + used to enable or disable this functionality as required. + +- Secure Partition Manager + + - New SPM implementation based on SPCI Alpha 1 draft specification + + A new version of SPM has been implemented, based on the SPCI (Secure + Partition Client Interface) and SPRT (Secure Partition Runtime) draft + specifications. + + The new implementation is a prototype that is expected to undergo intensive + rework as the specifications change. It has basic support for multiple + Secure Partitions and Resource Descriptions. + + The older version of SPM, based on MM (ARM Management Mode Interface + Specification), is still present in the codebase. A new build flag, `SPM_MM` + has been added to allow selection of the desired implementation. This flag + defaults to 1, selecting the MM-based implementation. + +- Security + + - Spectre Variant-1 mitigations (`CVE-2017-5753`) + + - Use Speculation Store Bypass Safe (SSBS) functionality where available + + Provides mitigation against `CVE-2018-19440` (Not saving x0 to x3 registers + can leak information from one Normal World SMC client to another) + +### Changed + +- Build System + + - Warning levels are now selectable with `W=<1,2,3>` + - Removed unneeded include paths in PLAT_INCLUDES + - "Warnings as errors" (Werror) can be disabled using `E=0` + - Support totally quiet output with `-s` flag + - Support passing options to checkpatch using `CHECKPATCH_OPTS=` + - Invoke host compiler with `HOSTCC / HOSTCCFLAGS` instead of `CC / CFLAGS` + - Make device tree pre-processing similar to U-boot/Linux by: + - Creating separate `CPPFLAGS` for DT preprocessing so that compiler options + specific to it can be accommodated. + - Replacing `CPP` with `PP` for DT pre-processing + +- CPU Support + + - Errata report function definition is now mandatory for CPU support files + + CPU operation files must now define a `_errata_report` function to + print errata status. This is no longer a weak reference. + +- Documentation + + - Migrated some content from GitHub wiki to `docs/` directory + - Security advisories now have CVE links + - Updated copyright guidelines + +- Drivers + + - console: The `MULTI_CONSOLE_API` framework has been rewritten in C + + - console: Ported multi-console driver to AArch32 + + - gic: Remove 'lowest priority' constants + + Removed `GIC_LOWEST_SEC_PRIORITY` and `GIC_LOWEST_NS_PRIORITY`. Platforms + should define these if required, or instead determine the correct priority + values at runtime. + + - delay_timer: Check that the Generic Timer extension is present + + - mmc: Increase command reply timeout to 10 milliseconds + + - mmc: Poll eMMC device status to ensure `EXT_CSD` command completion + + - mmc: Correctly check return code from `mmc_fill_device_info` + +- External Libraries + + - libfdt: Upgraded from 1.4.2 to 1.4.6-9 + + > + + - mbed TLS: Upgraded from 2.12 to 2.16 + + > + + This change incorporates fixes for security issues that should be reviewed to + determine if they are relevant for software implementations using Trusted + Firmware-A. See the [mbed TLS releases] page for details on changes from the + 2.12 to the 2.16 release. + +- Library Code + + - compiler-rt: Updated `lshrdi3.c` and `int_lib.h` with changes from LLVM + master branch (r345645) + - cpu: Updated macro that checks need for `CVE-2017-5715` mitigation + - libc: Made setjmp and longjmp C standard compliant + - libc: Allowed overriding the default libc (use `OVERRIDE_LIBC`) + - libc: Moved setjmp and longjmp to the `libc/` directory + +- Platforms + + - Removed Mbed TLS dependency from plat_bl_common.c + + - arm: Removed unused `ARM_MAP_BL_ROMLIB` macro + + - arm: Removed `ARM_BOARD_OPTIMISE_MEM` feature and build flag + + - arm: Moved several components into `drivers/` directory + + This affects the SDS, SCP, SCPI, MHU and SCMI components + + - arm/juno: Increased maximum BL2 image size to `0xF000` + + This change was required to accommodate a larger `libfdt` library + +- SCMI + + - Optimized bakery locks when hardware-assisted coherency is enabled using the + `HW_ASSISTED_COHERENCY` build flag + +- SDEI + + - Added support for unconditionally resuming secure world execution after {{ + SDEI }} event processing completes + + {{ SDEI }} interrupts, although targeting EL3, occur on behalf of the + non-secure world, and may have higher priority than secure world interrupts. + Therefore they might preempt secure execution and yield execution to the + non-secure {{ SDEI }} handler. Upon completion of {{ SDEI }} event handling, + resume secure execution if it was preempted. + +- Translation Tables (XLAT) + + - Dynamically detect need for `Common not Private (TTBRn_ELx.CnP)` bit + + Properly handle the case where `ARMv8.2-TTCNP` is implemented in a CPU that + does not implement all mandatory v8.2 features (and so must claim to + implement a lower architecture version). + +### Resolved Issues + +- Architecture + - Incorrect check for SSBS feature detection + - Unintentional register clobber in AArch32 reset_handler function +- Build System + - Dependency issue during DTB image build + - Incorrect variable expansion in Arm platform makefiles + - Building on Windows with verbose mode (`V=1`) enabled is broken + - AArch32 compilation flags is missing `$(march32-directive)` +- BL-Specific Issues + - bl2: `uintptr_t is not defined` error when `BL2_IN_XIP_MEM` is defined + - bl2: Missing prototype warning in `bl2_arch_setup` + - bl31: Omission of Global Offset Table (GOT) section +- Code Quality Issues + - Multiple MISRA compliance issues + - Potential NULL pointer dereference (Coverity-detected) +- Drivers + - mmc: Local declaration of `scr` variable causes a cache issue when + invalidating after the read DMA transfer completes + - mmc: `ACMD41` does not send voltage information during initialization, + resulting in the command being treated as a query. This prevents the command + from initializing the controller. + - mmc: When checking device state using `mmc_device_state()` there are no + retries attempted in the event of an error + - ccn: Incorrect Region ID calculation for RN-I nodes + - console: `Fix MULTI_CONSOLE_API` when used as a crash console + - partition: Improper NULL checking in gpt.c + - partition: Compilation failure in `VERBOSE` mode (`V=1`) +- Library Code + - common: Incorrect check for Address Authentication support + + - xlat: Fix XLAT_V1 / XLAT_V2 incompatibility + + The file `arm_xlat_tables.h` has been renamed to `xlat_tables_compat.h` and + has been moved to a common folder. This header can be used to guarantee + compatibility, as it includes the correct header based on + `XLAT_TABLES_LIB_V2`. + + - xlat: armclang unused-function warning on `xlat_clean_dcache_range` + + - xlat: Invalid `mm_cursor` checks in `mmap_add` and `mmap_add_ctx` + + - sdei: Missing `context.h` header +- Platforms + - common: Missing prototype warning for `plat_log_get_prefix` + + - arm: Insufficient maximum BL33 image size + + - arm: Potential memory corruption during BL2-BL31 transition + + On Arm platforms, the BL2 memory can be overlaid by BL31/BL32. The memory + descriptors describing the list of executable images are created in BL2 R/W + memory, which could be possibly corrupted later on by BL31/BL32 due to + overlay. This patch creates a reserved location in SRAM for these + descriptors and are copied over by BL2 before handing over to next BL image. + + - juno: Invalid behaviour when `CSS_USE_SCMI_SDS_DRIVER` is not set + + In `juno_pm.c` the `css_scmi_override_pm_ops` function was used regardless + of whether the build flag was set. The original behaviour has been restored + in the case where the build flag is not set. +- Tools + - fiptool: Incorrect UUID parsing of blob parameters + - doimage: Incorrect object rules in Makefile + +### Deprecations + +- Common Code + - `plat_crash_console_init` function + - `plat_crash_console_putc` function + - `plat_crash_console_flush` function + - `finish_console_register` macro +- AArch64-specific Code + - helpers: `get_afflvl_shift` + - helpers: `mpidr_mask_lower_afflvls` + - helpers: `eret` +- Secure Partition Manager (SPM) + - Boot-info structure + +### Known Issues + +- Build System Issues + - dtb: DTB creation not supported when building on a Windows host. + + This step in the build process is skipped when running on a Windows host. A + known issue from the 1.6 release. +- Platform Issues + - arm/juno: System suspend from Linux does not function as documented in the + user guide + + Following the instructions provided in the user guide document does not + result in the platform entering system suspend state as expected. A message + relating to the hdlcd driver failing to suspend will be emitted on the Linux + terminal. + + - arm/juno: The firmware update use-cases do not work with motherboard + firmware version \< v1.5.0 (the reset reason is not preserved). The Linaro + 18.04 release has MB v1.4.9. The MB v1.5.0 is available in Linaro 18.10 + release. + + - mediatek/mt6795: This platform does not build in this release + +## [2.0.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.6..refs/tags/v2.0) (2018-10-02) + +### New Features + +- Removal of a number of deprecated APIs + + - A new Platform Compatibility Policy document has been created which + references a wiki page that maintains a listing of deprecated interfaces and + the release after which they will be removed. + - All deprecated interfaces except the MULTI_CONSOLE_API have been removed + from the code base. + - Various Arm and partner platforms have been updated to remove the use of + removed APIs in this release. + - This release is otherwise unchanged from 1.6 release + +### Issues resolved since last release + +- No issues known at 1.6 release resolved in 2.0 release + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. Known issue from 1.6 + version. +- As a result of removal of deprecated interfaces the Nvidia Tegra, Marvell + Armada 8K and MediaTek MT6795 platforms do not build in this release. Also + MediaTek MT8173, NXP QorIQ LS1043A, NXP i.MX8QX, NXP i.MX8QMa, Rockchip + RK3328, Rockchip RK3368 and Rockchip RK3399 platforms have not been confirmed + to be working after the removal of the deprecated interfaces although they do + build. + +## [1.6.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.5..refs/tags/v1.6) (2018-09-21) + +### New Features + +- Addressing Speculation Security Vulnerabilities + + - Implement static workaround for CVE-2018-3639 for AArch32 and AArch64 + - Add support for dynamic mitigation for CVE-2018-3639 + - Implement dynamic mitigation for CVE-2018-3639 on Cortex-A76 + - Ensure {{ SDEI }} handler executes with CVE-2018-3639 mitigation enabled + +- Introduce RAS handling on AArch64 + + - Some RAS extensions are mandatory for Armv8.2 CPUs, with others mandatory + for Armv8.4 CPUs however, all extensions are also optional extensions to the + base Armv8.0 architecture. + - The Armv8 RAS Extensions introduced Standard Error Records which are a set + of standard registers to configure RAS node policy and allow RAS Nodes to + record and expose error information for error handling agents. + - Capabilities are provided to support RAS Node enumeration and iteration + along with individual interrupt registrations and fault injections support. + - Introduce handlers for Uncontainable errors, Double Faults and EL3 External + Aborts + +- Enable Memory Partitioning And Monitoring (MPAM) for lower EL's + + - Memory Partitioning And Monitoring is an Armv8.4 feature that enables + various memory system components and resources to define partitions. + Software running at various ELs can then assign themselves to the desired + partition to control their performance aspects. + - When ENABLE_MPAM_FOR_LOWER_ELS is set to 1, EL3 allows lower ELs to access + their own MPAM registers without trapping to EL3. This patch however, + doesn't make use of partitioning in EL3; platform initialisation code should + configure and use partitions in EL3 if required. + +- Introduce ROM Lib Feature + + - Support combining several libraries into a self-called "romlib" image, that + may be shared across images to reduce memory footprint. The romlib image is + stored in ROM but is accessed through a jump-table that may be stored in + read-write memory, allowing for the library code to be patched. + +- Introduce Backtrace Feature + + - This function displays the backtrace, the current EL and security state to + allow a post-processing tool to choose the right binary to interpret the + dump. + - Print backtrace in assert() and panic() to the console. + +- Code hygiene changes and alignment with MISRA C-2012 guideline with fixes + addressing issues complying to the following rules: + + - MISRA rules 4.9, 5.1, 5.3, 5.7, 8.2-8.5, 8.8, 8.13, 9.3, 10.1, 10.3-10.4, + 10.8, 11.3, 11.6, 12.1, 14.4, 15.7, 16.1-16.7, 17.7-17.8, 20.7, 20.10, + 20.12, 21.1, 21.15, 22.7 + - Clean up the usage of void pointers to access symbols + - Increase usage of static qualifier to locally used functions and data + - Migrated to use of u_register_t for register read/write to better match + AArch32 and AArch64 type sizes + - Use int-ll64 for both AArch32 and AArch64 to assist in consistent format + strings between architectures + - Clean up TF-A libc by removing non arm copyrighted implementations and + replacing them with modified FreeBSD and SCC implementations + +- Various changes to support Clang linker and assembler + + - The clang assembler/preprocessor is used when Clang is selected. However, + the clang linker is not used because it is unable to link TF-A objects due + to immaturity of clang linker functionality at this time. + +- Refactor support APIs into Libraries + + - Evolve libfdt, mbed TLS library and standard C library sources as proper + libraries that TF-A may be linked against. + +- CPU Enhancements + + - Add CPU support for Cortex-Ares and Cortex-A76 + - Add AMU support for Cortex-Ares + - Add initial CPU support for Cortex-Deimos + - Add initial CPU support for Cortex-Helios + - Implement dynamic mitigation for CVE-2018-3639 on Cortex-A76 + - Implement Cortex-Ares erratum 1043202 workaround + - Implement DSU erratum 936184 workaround + - Check presence of fix for errata 843419 in Cortex-A53 + - Check presence of fix for errata 835769 in Cortex-A53 + +- Translation Tables Enhancements + + - The xlat v2 library has been refactored in order to be reused by different + TF components at different EL's including the addition of EL2. Some + refactoring to make the code more generic and less specific to TF, in order + to reuse the library outside of this project. + +- SPM Enhancements + + - General cleanups and refactoring to pave the way to multiple partitions + support + +- SDEI Enhancements + + - Allow platforms to define explicit events + - Determine client EL from NS context's SCR_EL3 + - Make dispatches synchronous + - Introduce jump primitives for BL31 + - Mask events after CPU wakeup in {{ SDEI }} dispatcher to conform to the + specification + +- Misc TF-A Core Common Code Enhancements + + - Add support for eXecute In Place (XIP) memory in BL2 + - Add support for the SMC Calling Convention 2.0 + - Introduce External Abort handling on AArch64 External Abort routed to EL3 + was reported as an unhandled exception and caused a panic. This change + enables Trusted Firmware-A to handle External Aborts routed to EL3. + - Save value of ACTLR_EL1 implementation-defined register in the CPU context + structure rather than forcing it to 0. + - Introduce ARM_LINUX_KERNEL_AS_BL33 build option, which allows BL31 to + directly jump to a Linux kernel. This makes for a quicker and simpler boot + flow, which might be useful in some test environments. + - Add dynamic configurations for BL31, BL32 and BL33 enabling support for + Chain of Trust (COT). + - Make TF UUID RFC 4122 compliant + +- New Platform Support + + - Arm SGI-575 + - Arm SGM-775 + - Allwinner sun50i_64 + - Allwinner sun50i_h6 + - NXP QorIQ LS1043A + - NXP i.MX8QX + - NXP i.MX8QM + - NXP i.MX7Solo WaRP7 + - TI K3 + - Socionext Synquacer SC2A11 + - Marvell Armada 8K + - STMicroelectronics STM32MP1 + +- Misc Generic Platform Common Code Enhancements + + - Add MMC framework that supports both eMMC and SD card devices + +- Misc Arm Platform Common Code Enhancements + + - Demonstrate PSCI MEM_PROTECT from el3_runtime + - Provide RAS support + - Migrate AArch64 port to the multi console driver. The old API is deprecated + and will eventually be removed. + - Move BL31 below BL2 to enable BL2 overlay resulting in changes in the layout + of BL images in memory to enable more efficient use of available space. + - Add cpp build processing for dtb that allows processing device tree with + external includes. + - Extend FIP io driver to support multiple FIP devices + - Add support for SCMI AP core configuration protocol v1.0 + - Use SCMI AP core protocol to set the warm boot entrypoint + - Add support to Mbed TLS drivers for shared heap among different BL images to + help optimise memory usage + - Enable non-secure access to UART1 through a build option to support a serial + debug port for debugger connection + +- Enhancements for Arm Juno Platform + + - Add support for TrustZone Media Protection 1 (TZMP1) + +- Enhancements for Arm FVP Platform + + - Dynamic_config: remove the FVP dtb files + - Set DYNAMIC_WORKAROUND_CVE_2018_3639=1 on FVP by default + - Set the ability to dynamically disable Trusted Boot Board authentication to + be off by default with DYN_DISABLE_AUTH + - Add librom enhancement support in FVP + - Support shared Mbed TLS heap between BL1 and BL2 that allow a reduction in + BL2 size for FVP + +- Enhancements for Arm SGI/SGM Platform + + - Enable ARM_PLAT_MT flag for SGI-575 + - Add dts files to enable support for dynamic config + - Add RAS support + - Support shared Mbed TLS heap for SGI and SGM between BL1 and BL2 + +- Enhancements for Non Arm Platforms + + - Raspberry Pi Platform + - Hikey Platforms + - Xilinx Platforms + - QEMU Platform + - Rockchip rk3399 Platform + - TI Platforms + - Socionext Platforms + - Allwinner Platforms + - NXP Platforms + - NVIDIA Tegra Platform + - Marvell Platforms + - STMicroelectronics STM32MP1 Platform + +### Issues resolved since last release + +- No issues known at 1.5 release resolved in 1.6 release + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. Known issue from 1.5 + version. + +## [1.5.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.4..refs/tags/v1.5) (2018-03-20) + +### New features + +- Added new firmware support to enable RAS (Reliability, Availability, and + Serviceability) functionality. + + - Secure Partition Manager (SPM): A Secure Partition is a software execution + environment instantiated in S-EL0 that can be used to implement simple + management and security services. The SPM is the firmware component that is + responsible for managing a Secure Partition. + + - SDEI dispatcher: Support for interrupt-based {{ SDEI }} events and all + interfaces as defined by the {{ SDEI }} specification v1.0, see + [SDEI Specification] + + - Exception Handling Framework (EHF): Framework that allows dispatching of EL3 + interrupts to their registered handlers which are registered based on their + priorities. Facilitates firmware-first error handling policy where + asynchronous exceptions may be routed to EL3. + + Integrated the TSPD with EHF. + +- Updated PSCI support: + + - Implemented PSCI v1.1 optional features `MEM_PROTECT` and `SYSTEM_RESET2`. + The supported PSCI version was updated to v1.1. + + - Improved PSCI STAT timestamp collection, including moving accounting for + retention states to be inside the locks and fixing handling of wrap-around + when calculating residency in AArch32 execution state. + + - Added optional handler for early suspend that executes when suspending to a + power-down state and with data caches enabled. + + This may provide a performance improvement on platforms where it is safe to + perform some or all of the platform actions from `pwr_domain_suspend` with + the data caches enabled. + +- Enabled build option, BL2_AT_EL3, for BL2 to allow execution at EL3 without + any dependency on TF BL1. + + This allows platforms which already have a non-TF Boot ROM to directly load + and execute BL2 and subsequent BL stages without need for BL1. This was not + previously possible because BL2 executes at S-EL1 and cannot jump straight to + EL3. + +- Implemented support for SMCCC v1.1, including `SMCCC_VERSION` and + `SMCCC_ARCH_FEATURES`. + + Additionally, added support for `SMCCC_VERSION` in PSCI features to enable + discovery of the SMCCC version via PSCI feature call. + +- Added Dynamic Configuration framework which enables each of the boot loader + stages to be dynamically configured at runtime if required by the platform. + The boot loader stage may optionally specify a firmware configuration file + and/or hardware configuration file that can then be shared with the next boot + loader stage. + + Introduced a new BL handover interface that essentially allows passing of 4 + arguments between the different BL stages. + + Updated cert_create and fip_tool to support the dynamic configuration files. + The COT also updated to support these new files. + +- Code hygiene changes and alignment with MISRA guideline: + + - Fix use of undefined macros. + - Achieved compliance with Mandatory MISRA coding rules. + - Achieved compliance for following Required MISRA rules for the default build + configurations on FVP and Juno platforms : 7.3, 8.3, 8.4, 8.5 and 8.8. + +- Added support for Armv8.2-A architectural features: + + - Updated translation table set-up to set the CnP (Common not Private) bit for + secure page tables so that multiple PEs in the same Inner Shareable domain + can use the same translation table entries for a given stage of translation + in a particular translation regime. + - Extended the supported values of ID_AA64MMFR0_EL1.PARange to include the + 52-bit Physical Address range. + - Added support for the Scalable Vector Extension to allow Normal world + software to access SVE functionality but disable access to SVE, SIMD and + floating point functionality from the Secure world in order to prevent + corruption of the Z-registers. + +- Added support for Armv8.4-A architectural feature Activity Monitor Unit (AMU) + + extensions. + + In addition to the v8.4 architectural extension, AMU support on Cortex-A75 was + implemented. + +- Enhanced OP-TEE support to enable use of pageable OP-TEE image. The Arm + standard platforms are updated to load up to 3 images for OP-TEE; header, + pager image and paged image. + + The chain of trust is extended to support the additional images. + +- Enhancements to the translation table library: + + - Introduced APIs to get and set the memory attributes of a region. + - Added support to manage both privilege levels in translation regimes that + describe translations for 2 Exception levels, specifically the EL1&0 + translation regime, and extended the memory map region attributes to include + specifying Non-privileged access. + - Added support to specify the granularity of the mappings of each region, for + instance a 2MB region can be specified to be mapped with 4KB page tables + instead of a 2MB block. + - Disabled the higher VA range to avoid unpredictable behaviour if there is an + attempt to access addresses in the higher VA range. + - Added helpers for Device and Normal memory MAIR encodings that align with + the Arm Architecture Reference Manual for Armv8-A (Arm DDI0487B.b). + - Code hygiene including fixing type length and signedness of constants, + refactoring of function to enable the MMU, removing all instances where the + virtual address space is hardcoded and added comments that document + alignment needed between memory attributes and attributes specified in + TCR_ELx. + +- Updated GIC support: + + - Introduce new APIs for GICv2 and GICv3 that provide the capability to + specify interrupt properties rather than list of interrupt numbers alone. + The Arm platforms and other upstream platforms are migrated to use interrupt + properties. + + - Added helpers to save / restore the GICv3 context, specifically the + Distributor and Redistributor contexts and architectural parts of the ITS + power management. The Distributor and Redistributor helpers also support the + implementation-defined part of GIC-500 and GIC-600. + + Updated the Arm FVP platform to save / restore the GICv3 context on system + suspend / resume as an example of how to use the helpers. + + Introduced a new TZC secured DDR carve-out for use by Arm platforms for + storing EL3 runtime data such as the GICv3 register context. + +- Added support for Armv7-A architecture via build option ARM_ARCH_MAJOR=7. This + includes following features: + + - Updates GICv2 driver to manage GICv1 with security extensions. + - Software implementation for 32bit division. + - Enabled use of generic timer for platforms that do not set + ARM_CORTEX_Ax=yes. + - Support for Armv7-A Virtualization extensions \[DDI0406C_C\]. + - Support for both Armv7-A platforms that only have 32-bit addressing and + Armv7-A platforms that support large page addressing. + - Included support for following Armv7 CPUs: Cortex-A12, Cortex-A17, + Cortex-A7, Cortex-A5, Cortex-A9, Cortex-A15. + - Added support in QEMU for Armv7-A/Cortex-A15. + +- Enhancements to Firmware Update feature: + + - Updated the FWU documentation to describe the additional images needed for + Firmware update, and how they are used for both the Juno platform and the + Arm FVP platforms. + +- Enhancements to Trusted Board Boot feature: + + - Added support to cert_create tool for RSA PKCS1# v1.5 and SHA384, SHA512 and + SHA256. + - For Arm platforms added support to use ECDSA keys. + - Enhanced the mbed TLS wrapper layer to include support for both RSA and + ECDSA to enable runtime selection between RSA and ECDSA keys. + +- Added support for secure interrupt handling in AArch32 sp_min, hardcoded to + only handle FIQs. + +- Added support to allow a platform to load images from multiple boot sources, + for example from a second flash drive. + +- Added a logging framework that allows platforms to reduce the logging level at + runtime and additionally the prefix string can be defined by the platform. + +- Further improvements to register initialisation: + + - Control register PMCR_EL0 / PMCR is set to prohibit cycle counting in the + secure world. This register is added to the list of registers that are saved + and restored during world switch. + - When EL3 is running in AArch32 execution state, the Non-secure version of + SCTLR is explicitly initialised during the warmboot flow rather than relying + on the hardware to set the correct reset values. + +- Enhanced support for Arm platforms: + + - Introduced driver for Shared-Data-Structure (SDS) framework which is used + for communication between SCP and the AP CPU, replacing Boot-Over_MHU (BOM) + protocol. + + The Juno platform is migrated to use SDS with the SCMI support added in v1.3 + and is set as default. + + The driver can be found in the plat/arm/css/drivers folder. + + - Improved memory usage by only mapping TSP memory region when the TSPD has + been included in the build. This reduces the memory footprint and avoids + unnecessary memory being mapped. + + - Updated support for multi-threading CPUs for FVP platforms - always check + the MT field in MPDIR and access the bit fields accordingly. + + - Support building for platforms that model DynamIQ configuration by + implementing all CPUs in a single cluster. + + - Improved nor flash driver, for instance clearing status registers before + sending commands. Driver can be found plat/arm/board/common folder. + +- Enhancements to QEMU platform: + + - Added support for TBB. + - Added support for using OP-TEE pageable image. + - Added support for LOAD_IMAGE_V2. + - Migrated to use translation table library v2 by default. + - Added support for SEPARATE_CODE_AND_RODATA. + +- Applied workarounds CVE-2017-5715 on Arm Cortex-A57, -A72, -A73 and -A75, and + for Armv7-A CPUs Cortex-A9, -A15 and -A17. + +- Applied errata workaround for Arm Cortex-A57: 859972. + +- Applied errata workaround for Arm Cortex-A72: 859971. + +- Added support for Poplar 96Board platform. + +- Added support for Raspberry Pi 3 platform. + +- Added Call Frame Information (CFI) assembler directives to the vector entries + which enables debuggers to display the backtrace of functions that triggered a + synchronous abort. + +- Added ability to build dtb. + +- Added support for pre-tool (cert_create and fiptool) image processing enabling + compression of the image files before processing by cert_create and fiptool. + + This can reduce fip size and may also speed up loading of images. The image + verification will also get faster because certificates are generated based on + compressed images. + + Imported zlib 1.2.11 to implement gunzip() for data compression. + +- Enhancements to fiptool: + + - Enabled the fiptool to be built using Visual Studio. + - Added padding bytes at the end of the last image in the fip to be facilitate + transfer by DMA. + +### Issues resolved since last release + +- TF-A can be built with optimisations disabled (-O0). +- Memory layout updated to enable Trusted Board Boot on Juno platform when + running TF-A in AArch32 execution mode (resolving [tf-issue#501]). + +### Known Issues + +- DTB creation not supported when building on a Windows host. This step in the + build process is skipped when running on a Windows host. + +## [1.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.3..refs/tags/v1.4) (2017-07-07) + +### New features + +- Enabled support for platforms with hardware assisted coherency. + + A new build option HW_ASSISTED_COHERENCY allows platforms to take advantage of + the following optimisations: + + - Skip performing cache maintenance during power-up and power-down. + - Use spin-locks instead of bakery locks. + - Enable data caches early on warm-booted CPUs. + +- Added support for Cortex-A75 and Cortex-A55 processors. + + Both Cortex-A75 and Cortex-A55 processors use the Arm DynamIQ Shared Unit + (DSU). The power-down and power-up sequences are therefore mostly managed in + hardware, reducing complexity of the software operations. + +- Introduced Arm GIC-600 driver. + + Arm GIC-600 IP complies with Arm GICv3 architecture. For FVP platforms, the + GIC-600 driver is chosen when FVP_USE_GIC_DRIVER is set to FVP_GIC600. + +- Updated GICv3 support: + + - Introduced power management APIs for GICv3 Redistributor. These APIs allow + platforms to power down the Redistributor during CPU power on/off. Requires + the GICv3 implementations to have power management operations. + + Implemented the power management APIs for FVP. + + - GIC driver data is flushed by the primary CPU so that secondary CPU do not + read stale GIC data. + +- Added support for Arm System Control and Management Interface v1.0 (SCMI). + + The SCMI driver implements the power domain management and system power + management protocol of the SCMI specification (Arm DEN 0056ASCMI) for + communicating with any compliant power controller. + + Support is added for the Juno platform. The driver can be found in the + plat/arm/css/drivers folder. + +- Added support to enable pre-integration of TBB with the Arm TrustZone + CryptoCell product, to take advantage of its hardware Root of Trust and crypto + acceleration services. + +- Enabled Statistical Profiling Extensions for lower ELs. + + The firmware support is limited to the use of SPE in the Non-secure state and + accesses to the SPE specific registers from S-EL1 will trap to EL3. + + The SPE are architecturally specified for AArch64 only. + +- Code hygiene changes aligned with MISRA guidelines: + + - Fixed signed / unsigned comparison warnings in the translation table + library. + - Added U(\_x) macro and together with the existing ULL(\_x) macro fixed some + of the signed-ness defects flagged by the MISRA scanner. + +- Enhancements to Firmware Update feature: + + - The FWU logic now checks for overlapping images to prevent execution of + unauthenticated arbitrary code. + - Introduced new FWU_SMC_IMAGE_RESET SMC that changes the image loading state + machine to go from COPYING, COPIED or AUTHENTICATED states to RESET state. + Previously, this was only possible when the authentication of an image + failed or when the execution of the image finished. + - Fixed integer overflow which addressed TFV-1: Malformed Firmware Update SMC + can result in copy of unexpectedly large data into secure memory. + +- Introduced support for Arm Compiler 6 and LLVM (clang). + + TF-A can now also be built with the Arm Compiler 6 or the clang compilers. The + assembler and linker must be provided by the GNU toolchain. + + Tested with Arm CC 6.7 and clang 3.9.x and 4.0.x. + +- Memory footprint improvements: + + - Introduced `tf_snprintf`, a reduced version of `snprintf` which has support + for a limited set of formats. + + The mbedtls driver is updated to optionally use `tf_snprintf` instead of + `snprintf`. + + - The `assert()` is updated to no longer print the function name, and + additional logging options are supported via an optional platform define + `PLAT_LOG_LEVEL_ASSERT`, which controls how verbose the assert output is. + +- Enhancements to TF-A support when running in AArch32 execution state: + + - Support booting SP_MIN and BL33 in AArch32 execution mode on Juno. Due to + hardware limitations, BL1 and BL2 boot in AArch64 state and there is + additional trampoline code to warm reset into SP_MIN in AArch32 execution + state. + - Added support for Arm Cortex-A53/57/72 MPCore processors including the + errata workarounds that are already implemented for AArch64 execution state. + - For FVP platforms, added AArch32 Trusted Board Boot support, including the + Firmware Update feature. + +- Introduced Arm SiP service for use by Arm standard platforms. + + - Added new Arm SiP Service SMCs to enable the Non-secure world to read PMF + timestamps. + + Added PMF instrumentation points in TF-A in order to quantify the overall + time spent in the PSCI software implementation. + + - Added new Arm SiP service SMC to switch execution state. + + This allows the lower exception level to change its execution state from + AArch64 to AArch32, or vice verse, via a request to EL3. + +- Migrated to use SPDX\[0\] license identifiers to make software license + auditing simpler. + + \:::\{note} Files that have been imported by FreeBSD have not been modified. + \::: + + \[0\]: + +- Enhancements to the translation table library: + + - Added version 2 of translation table library that allows different + translation tables to be modified by using different 'contexts'. Version 1 + of the translation table library only allows the current EL's translation + tables to be modified. + + Version 2 of the translation table also added support for dynamic regions; + regions that can be added and removed dynamically whilst the MMU is enabled. + Static regions can only be added or removed before the MMU is enabled. + + The dynamic mapping functionality is enabled or disabled when compiling by + setting the build option PLAT_XLAT_TABLES_DYNAMIC to 1 or 0. This can be + done per-image. + + - Added support for translation regimes with two virtual address spaces such + as the one shared by EL1 and EL0. + + The library does not support initializing translation tables for EL0 + software. + + - Added support to mark the translation tables as non-cacheable using an + additional build option `XLAT_TABLE_NC`. + +- Added support for GCC stack protection. A new build option + ENABLE_STACK_PROTECTOR was introduced that enables compilation of all BL + images with one of the GCC -fstack-protector-\* options. + + A new platform function plat_get_stack_protector_canary() was introduced that + returns a value used to initialize the canary for stack corruption detection. + For increased effectiveness of protection platforms must provide an + implementation that returns a random value. + +- Enhanced support for Arm platforms: + + - Added support for multi-threading CPUs, indicated by `MT` field in MPDIR. A + new build flag `ARM_PLAT_MT` is added, and when enabled, the functions + accessing MPIDR assume that the `MT` bit is set for the platform and access + the bit fields accordingly. + + Also, a new API `plat_arm_get_cpu_pe_count` is added when `ARM_PLAT_MT` is + enabled, returning the Processing Element count within the physical CPU + corresponding to `mpidr`. + + - The Arm platforms migrated to use version 2 of the translation tables. + + - Introduced a new Arm platform layer API `plat_arm_psci_override_pm_ops` + which allows Arm platforms to modify `plat_arm_psci_pm_ops` and therefore + dynamically define PSCI capability. + + - The Arm platforms migrated to use IMAGE_LOAD_V2 by default. + +- Enhanced reporting of errata workaround status with the following policy: + + - If an errata workaround is enabled: + + - If it applies (i.e. the CPU is affected by the errata), an INFO message is + printed, confirming that the errata workaround has been applied. + - If it does not apply, a VERBOSE message is printed, confirming that the + errata workaround has been skipped. + + - If an errata workaround is not enabled, but would have applied had it been, + a WARN message is printed, alerting that errata workaround is missing. + +- Added build options ARM_ARCH_MAJOR and ARM_ARM_MINOR to choose the + architecture version to target TF-A. + +- Updated the spin lock implementation to use the more efficient CAS (Compare + And Swap) instruction when available. This instruction was introduced in + Armv8.1-A. + +- Applied errata workaround for Arm Cortex-A53: 855873. + +- Applied errata workaround for Arm-Cortex-A57: 813419. + +- Enabled all A53 and A57 errata workarounds for Juno, both in AArch64 and + AArch32 execution states. + +- Added support for Socionext UniPhier SoC platform. + +- Added support for Hikey960 and Hikey platforms. + +- Added support for Rockchip RK3328 platform. + +- Added support for NVidia Tegra T186 platform. + +- Added support for Designware emmc driver. + +- Imported libfdt v1.4.2 that addresses buffer overflow in fdt_offset_ptr(). + +- Enhanced the CPU operations framework to allow power handlers to be registered + on per-level basis. This enables support for future CPUs that have multiple + threads which might need powering down individually. + +- Updated register initialisation to prevent unexpected behaviour: + + - Debug registers MDCR-EL3/SDCR and MDCR_EL2/HDCR are initialised to avoid + unexpected traps into the higher exception levels and disable secure + self-hosted debug. Additionally, secure privileged external debug on Juno is + disabled by programming the appropriate Juno SoC registers. + - EL2 and EL3 configurable controls are initialised to avoid unexpected traps + in the higher exception levels. + - Essential control registers are fully initialised on EL3 start-up, when + initialising the non-secure and secure context structures and when preparing + to leave EL3 for a lower EL. This gives better alignment with the Arm ARM + which states that software must initialise RES0 and RES1 fields with 0 / 1. + +- Enhanced PSCI support: + + - Introduced new platform interfaces that decouple PSCI stat residency + calculation from PMF, enabling platforms to use alternative methods of + capturing timestamps. + - PSCI stat accounting performed for retention/standby states when requested + at multiple power levels. + +- Simplified fiptool to have a single linked list of image descriptors. + +- For the TSP, resolved corruption of pre-empted secure context by aborting any + pre-empted SMC during PSCI power management requests. + +### Issues resolved since last release + +- TF-A can be built with the latest mbed TLS version (v2.4.2). The earlier + version 2.3.0 cannot be used due to build warnings that the TF-A build system + interprets as errors. +- TBBR, including the Firmware Update feature is now supported on FVP platforms + when running TF-A in AArch32 state. +- The version of the AEMv8 Base FVP used in this release has resolved the issue + of the model executing a reset instead of terminating in response to a + shutdown request using the PSCI SYSTEM_OFF API. + +### Known Issues + +- Building TF-A with compiler optimisations disabled (-O0) fails. +- Trusted Board Boot currently does not work on Juno when running Trusted + Firmware in AArch32 execution state due to error when loading the sp_min to + memory because of lack of free space available. See [tf-issue#501] for more + details. +- The errata workaround for A53 errata 843419 is only available from binutils + 2.26 and is not present in GCC4.9. If this errata is applicable to the + platform, please use GCC compiler version of at least 5.0. See [PR#1002] for + more details. + +## [1.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.2..refs/tags/v1.3) (2016-10-13) + +### New features + +- Added support for running TF-A in AArch32 execution state. + + The PSCI library has been refactored to allow integration with **EL3 Runtime + Software**. This is software that is executing at the highest secure privilege + which is EL3 in AArch64 or Secure SVC/Monitor mode in AArch32. See + \{ref}`PSCI Library Integration guide for Armv8-A AArch32 systems`. + + Included is a minimal AArch32 Secure Payload, **SP-MIN**, that illustrates the + usage and integration of the PSCI library with EL3 Runtime Software running in + AArch32 state. + + Booting to the BL1/BL2 images as well as booting straight to the Secure + Payload is supported. + +- Improvements to the initialization framework for the PSCI service and Arm + Standard Services in general. + + The PSCI service is now initialized as part of Arm Standard Service + initialization. This consolidates the initializations of any Arm Standard + Service that may be added in the future. + + A new function `get_arm_std_svc_args()` is introduced to get arguments + corresponding to each standard service and must be implemented by the EL3 + Runtime Software. + + For PSCI, a new versioned structure `psci_lib_args_t` is introduced to + initialize the PSCI Library. **Note** this is a compatibility break due to the + change in the prototype of `psci_setup()`. + +- To support AArch32 builds of BL1 and BL2, implemented a new, alternative + firmware image loading mechanism that adds flexibility. + + The current mechanism has a hard-coded set of images and execution order + (BL31, BL32, etc). The new mechanism is data-driven by a list of image + descriptors provided by the platform code. + + Arm platforms have been updated to support the new loading mechanism. + + The new mechanism is enabled by a build flag (`LOAD_IMAGE_V2`) which is + currently off by default for the AArch64 build. + + **Note** `TRUSTED_BOARD_BOOT` is currently not supported when `LOAD_IMAGE_V2` + is enabled. + +- Updated requirements for making contributions to TF-A. + + Commits now must have a 'Signed-off-by:' field to certify that the + contribution has been made under the terms of the + {download}`Developer Certificate of Origin <../dco.txt>`. + + A signed CLA is no longer required. + + The {ref}`Contributor's Guide` has been updated to reflect this change. + +- Introduced Performance Measurement Framework (PMF) which provides support for + capturing, storing, dumping and retrieving time-stamps to measure the + execution time of critical paths in the firmware. This relies on defining + fixed sample points at key places in the code. + +- To support the QEMU platform port, imported libfdt v1.4.1 from + + +- Updated PSCI support: + + - Added support for PSCI NODE_HW_STATE API for Arm platforms. + - New optional platform hook, `pwr_domain_pwr_down_wfi()`, in `plat_psci_ops` + to enable platforms to perform platform-specific actions needed to enter + powerdown, including the 'wfi' invocation. + - PSCI STAT residency and count functions have been added on Arm platforms by + using PMF. + +- Enhancements to the translation table library: + + - Limited memory mapping support for region overlaps to only allow regions to + overlap that are identity mapped or have the same virtual to physical + address offset, and overlap completely but must not cover the same area. + + This limitation will enable future enhancements without having to support + complex edge cases that may not be necessary. + + - The initial translation lookup level is now inferred from the virtual + address space size. Previously, it was hard-coded. + + - Added support for mapping Normal, Inner Non-cacheable, Outer Non-cacheable + memory in the translation table library. + + This can be useful to map a non-cacheable memory region, such as a DMA + buffer. + + - Introduced the MT_EXECUTE/MT_EXECUTE_NEVER memory mapping attributes to + specify the access permissions for instruction execution of a memory region. + +- Enabled support to isolate code and read-only data on separate memory pages, + allowing independent access control to be applied to each. + +- Enabled SCR_EL3.SIF (Secure Instruction Fetch) bit in BL1 and BL31 common + architectural setup code, preventing fetching instructions from non-secure + memory when in secure state. + +- Enhancements to FIP support: + + - Replaced `fip_create` with `fiptool` which provides a more consistent and + intuitive interface as well as additional support to remove an image from a + FIP file. + - Enabled printing the SHA256 digest with info command, allowing quick + verification of an image within a FIP without having to extract the image + and running sha256sum on it. + - Added support for unpacking the contents of an existing FIP file into the + working directory. + - Aligned command line options for specifying images to use same naming + convention as specified by TBBR and already used in cert_create tool. + +- Refactored the TZC-400 driver to also support memory controllers that + integrate TZC functionality, for example Arm CoreLink DMC-500. Also added + DMC-500 specific support. + +- Implemented generic delay timer based on the system generic counter and + migrated all platforms to use it. + +- Enhanced support for Arm platforms: + + - Updated image loading support to make SCP images (SCP_BL2 and SCP_BL2U) + optional. + - Enhanced topology description support to allow multi-cluster topology + definitions. + - Added interconnect abstraction layer to help platform ports select the right + interconnect driver, CCI or CCN, for the platform. + - Added support to allow loading BL31 in the TZC-secured DRAM instead of the + default secure SRAM. + - Added support to use a System Security Control (SSC) Registers Unit enabling + TF-A to be compiled to support multiple Arm platforms and then select one at + runtime. + - Restricted mapping of Trusted ROM in BL1 to what is actually needed by BL1 + rather than entire Trusted ROM region. + - Flash is now mapped as execute-never by default. This increases security by + restricting the executable region to what is strictly needed. + +- Applied following erratum workarounds for Cortex-A57: 833471, 826977, 829520, + 828024 and 826974. + +- Added support for Mediatek MT6795 platform. + +- Added support for QEMU virtualization Armv8-A target. + +- Added support for Rockchip RK3368 and RK3399 platforms. + +- Added support for Xilinx Zynq UltraScale+ MPSoC platform. + +- Added support for Arm Cortex-A73 MPCore Processor. + +- Added support for Arm Cortex-A72 processor. + +- Added support for Arm Cortex-A35 processor. + +- Added support for Arm Cortex-A32 MPCore Processor. + +- Enabled preloaded BL33 alternative boot flow, in which BL2 does not load BL33 + from non-volatile storage and BL31 hands execution over to a preloaded BL33. + The User Guide has been updated with an example of how to use this option with + a bootwrapped kernel. + +- Added support to build TF-A on a Windows-based host machine. + +- Updated Trusted Board Boot prototype implementation: + + - Enabled the ability for a production ROM with TBBR enabled to boot test + software before a real ROTPK is deployed (e.g. manufacturing mode). Added + support to use ROTPK in certificate without verifying against the platform + value when `ROTPK_NOT_DEPLOYED` bit is set. + - Added support for non-volatile counter authentication to the Authentication + Module to protect against roll-back. + +- Updated GICv3 support: + + - Enabled processor power-down and automatic power-on using GICv3. + - Enabled G1S or G0 interrupts to be configured independently. + - Changed FVP default interrupt driver to be the GICv3-only driver. **Note** + the default build of TF-A will not be able to boot Linux kernel with GICv2 + FDT blob. + - Enabled wake-up from CPU_SUSPEND to stand-by by temporarily re-routing + interrupts and then restoring after resume. + +### Issues resolved since last release + +### Known issues + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- Building TF-A with compiler optimisations disabled (`-O0`) fails. +- TF-A cannot be built with mbed TLS version v2.3.0 due to build warnings that + the TF-A build system interprets as errors. +- TBBR is not currently supported when running TF-A in AArch32 state. + +## [1.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.1..refs/tags/v1.2) (2015-12-22) + +### New features + +- The Trusted Board Boot implementation on Arm platforms now conforms to the + mandatory requirements of the TBBR specification. + + In particular, the boot process is now guarded by a Trusted Watchdog, which + will reset the system in case of an authentication or loading error. On Arm + platforms, a secure instance of Arm SP805 is used as the Trusted Watchdog. + + Also, a firmware update process has been implemented. It enables authenticated + firmware to update firmware images from external interfaces to SoC + Non-Volatile memories. This feature functions even when the current firmware + in the system is corrupt or missing; it therefore may be used as a recovery + mode. + +- Improvements have been made to the Certificate Generation Tool (`cert_create`) + as follows. + + - Added support for the Firmware Update process by extending the Chain of + Trust definition in the tool to include the Firmware Update certificate and + the required extensions. + - Introduced a new API that allows one to specify command line options in the + Chain of Trust description. This makes the declaration of the tool's + arguments more flexible and easier to extend. + - The tool has been reworked to follow a data driven approach, which makes it + easier to maintain and extend. + +- Extended the FIP tool (`fip_create`) to support the new set of images involved + in the Firmware Update process. + +- Various memory footprint improvements. In particular: + + - The bakery lock structure for coherent memory has been optimised. + - The mbed TLS SHA1 functions are not needed, as SHA256 is used to generate + the certificate signature. Therefore, they have been compiled out, reducing + the memory footprint of BL1 and BL2 by approximately 6 KB. + - On Arm development platforms, each BL stage now individually defines the + number of regions that it needs to map in the MMU. + +- Added the following new design documents: + + - {ref}`Authentication Framework & Chain of Trust` + - {ref}`Firmware Update (FWU)` + - {ref}`CPU Reset` + - {ref}`PSCI Power Domain Tree Structure` + +- Applied the new image terminology to the code base and documentation, as + described in the {ref}`Image Terminology` document. + +- The build system has been reworked to improve readability and facilitate + adding future extensions. + +- On Arm standard platforms, BL31 uses the boot console during cold boot but + switches to the runtime console for any later logs at runtime. The TSP uses + the runtime console for all output. + +- Implemented a basic NOR flash driver for Arm platforms. It programs the device + using CFI (Common Flash Interface) standard commands. + +- Implemented support for booting EL3 payloads on Arm platforms, which reduces + the complexity of developing EL3 baremetal code by doing essential baremetal + initialization. + +- Provided separate drivers for GICv3 and GICv2. These expect the entire + software stack to use either GICv2 or GICv3; hybrid GIC software systems are + no longer supported and the legacy Arm GIC driver has been deprecated. + +- Added support for Juno r1 and r2. A single set of Juno TF-A binaries can run + on Juno r0, r1 and r2 boards. Note that this TF-A version depends on a Linaro + release that does *not* contain Juno r2 support. + +- Added support for MediaTek mt8173 platform. + +- Implemented a generic driver for Arm CCN IP. + +- Major rework of the PSCI implementation. + + - Added framework to handle composite power states. + - Decoupled the notions of affinity instances (which describes the + hierarchical arrangement of cores) and of power domain topology, instead of + assuming a one-to-one mapping. + - Better alignment with version 1.0 of the PSCI specification. + +- Added support for the SYSTEM_SUSPEND PSCI API on Arm platforms. When invoked + on the last running core on a supported platform, this puts the system into a + low power mode with memory retention. + +- Unified the reset handling code as much as possible across BL stages. Also + introduced some build options to enable optimization of the reset path on + platforms that support it. + +- Added a simple delay timer API, as well as an SP804 timer driver, which is + enabled on FVP. + +- Added support for NVidia Tegra T210 and T132 SoCs. + +- Reorganised Arm platforms ports to greatly improve code shareability and + facilitate the reuse of some of this code by other platforms. + +- Added support for Arm Cortex-A72 processor in the CPU specific framework. + +- Provided better error handling. Platform ports can now define their own error + handling, for example to perform platform specific bookkeeping or post-error + actions. + +- Implemented a unified driver for Arm Cache Coherent Interconnects used for + both CCI-400 & CCI-500 IPs. Arm platforms ports have been migrated to this + common driver. The standalone CCI-400 driver has been deprecated. + +### Issues resolved since last release + +- The Trusted Board Boot implementation has been redesigned to provide greater + modularity and scalability. See the + \{ref}`Authentication Framework & Chain of Trust` document. All missing + mandatory features are now implemented. +- The FVP and Juno ports may now use the hash of the ROTPK stored in the Trusted + Key Storage registers to verify the ROTPK. Alternatively, a development public + key hash embedded in the BL1 and BL2 binaries might be used instead. The + location of the ROTPK is chosen at build-time using the `ARM_ROTPK_LOCATION` + build option. +- GICv3 is now fully supported and stable. + +### Known issues + +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- While this version has low on-chip RAM requirements, there are further RAM + usage enhancements that could be made. +- The upstream documentation could be improved for structural consistency, + clarity and completeness. In particular, the design documentation is + incomplete for PSCI, the TSP(D) and the Juno platform. +- Building TF-A with compiler optimisations disabled (`-O0`) fails. + +## [1.1.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v1.0..refs/tags/v1.1) (2015-02-04) + +### New features + +- A prototype implementation of Trusted Board Boot has been added. Boot loader + images are verified by BL1 and BL2 during the cold boot path. BL1 and BL2 use + the PolarSSL SSL library to verify certificates and images. The OpenSSL + library is used to create the X.509 certificates. Support has been added to + `fip_create` tool to package the certificates in a FIP. + +- Support for calling CPU and platform specific reset handlers upon entry into + BL3-1 during the cold and warm boot paths has been added. This happens after + another Boot ROM `reset_handler()` has already run. This enables a developer + to perform additional actions or undo actions already performed during the + first call of the reset handlers e.g. apply additional errata workarounds. + +- Support has been added to demonstrate routing of IRQs to EL3 instead of S-EL1 + when execution is in secure world. + +- The PSCI implementation now conforms to version 1.0 of the PSCI specification. + All the mandatory APIs and selected optional APIs are supported. In + particular, support for the `PSCI_FEATURES` API has been added. A capability + variable is constructed during initialization by examining the `plat_pm_ops` + and `spd_pm_ops` exported by the platform and the Secure Payload Dispatcher. + This is used by the PSCI FEATURES function to determine which PSCI APIs are + supported by the platform. + +- Improvements have been made to the PSCI code as follows. + + - The code has been refactored to remove redundant parameters from internal + functions. + - Changes have been made to the code for PSCI `CPU_SUSPEND`, `CPU_ON` and + `CPU_OFF` calls to facilitate an early return to the caller in case a + failure condition is detected. For example, a PSCI `CPU_SUSPEND` call + returns `SUCCESS` to the caller if a pending interrupt is detected early in + the code path. + - Optional platform APIs have been added to validate the `power_state` and + `entrypoint` parameters early in PSCI `CPU_ON` and `CPU_SUSPEND` code paths. + - PSCI migrate APIs have been reworked to invoke the SPD hook to determine the + type of Trusted OS and the CPU it is resident on (if applicable). Also, + during a PSCI `MIGRATE` call, the SPD hook to migrate the Trusted OS is + invoked. + +- It is now possible to build TF-A without marking at least an extra page of + memory as coherent. The build flag `USE_COHERENT_MEM` can be used to choose + between the two implementations. This has been made possible through these + changes. + + - An implementation of Bakery locks, where the locks are not allocated in + coherent memory has been added. + - Memory which was previously marked as coherent is now kept coherent through + the use of software cache maintenance operations. + + Approximately, 4K worth of memory is saved for each boot loader stage when + `USE_COHERENT_MEM=0`. Enabling this option increases the latencies associated + with acquire and release of locks. It also requires changes to the platform + ports. + +- It is now possible to specify the name of the FIP at build time by defining + the `FIP_NAME` variable. + +- Issues with dependencies on the 'fiptool' makefile target have been rectified. + The `fip_create` tool is now rebuilt whenever its source files change. + +- The BL3-1 runtime console is now also used as the crash console. The crash + console is changed to SoC UART0 (UART2) from the previous FPGA UART0 (UART0) + on Juno. In FVP, it is changed from UART0 to UART1. + +- CPU errata workarounds are applied only when the revision and part number + match. This behaviour has been made consistent across the debug and release + builds. The debug build additionally prints a warning if a mismatch is + detected. + +- It is now possible to issue cache maintenance operations by set/way for a + particular level of data cache. Levels 1-3 are currently supported. + +- The following improvements have been made to the FVP port. + + - The build option `FVP_SHARED_DATA_LOCATION` which allowed relocation of + shared data into the Trusted DRAM has been deprecated. Shared data is now + always located at the base of Trusted SRAM. + - BL2 Translation tables have been updated to map only the region of DRAM + which is accessible to normal world. This is the region of the 2GB DDR-DRAM + memory at 0x80000000 excluding the top 16MB. The top 16MB is accessible to + only the secure world. + - BL3-2 can now reside in the top 16MB of DRAM which is accessible only to the + secure world. This can be done by setting the build flag + `FVP_TSP_RAM_LOCATION` to the value `dram`. + +- Separate translation tables are created for each boot loader image. The + `IMAGE_BLx` build options are used to do this. This allows each stage to + create mappings only for areas in the memory map that it needs. + +- A Secure Payload Dispatcher (OPTEED) for the OP-TEE Trusted OS has been added. + Details of using it with TF-A can be found in {ref}`OP-TEE Dispatcher` + +### Issues resolved since last release + +- The Juno port has been aligned with the FVP port as follows. + + - Support for reclaiming all BL1 RW memory and BL2 memory by overlaying the + BL3-1/BL3-2 NOBITS sections on top of them has been added to the Juno port. + - The top 16MB of the 2GB DDR-DRAM memory at 0x80000000 is configured using + the TZC-400 controller to be accessible only to the secure world. + - The Arm GIC driver is used to configure the GIC-400 instead of using a GIC + driver private to the Juno port. + - PSCI `CPU_SUSPEND` calls that target a standby state are now supported. + - The TZC-400 driver is used to configure the controller instead of direct + accesses to the registers. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support enabled. + +- DS-5 v5.19 did not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in CADI + server mode. This issue is not seen with DS-5 v5.20 and Version 6.2 of the + Cortex-A57-A53 Base FVPs. + +### Known issues + +- The Trusted Board Boot implementation is a prototype. There are issues with + the modularity and scalability of the design. Support for a Trusted Watchdog, + firmware update mechanism, recovery images and Trusted debug is absent. These + issues will be addressed in future releases. +- The FVP and Juno ports do not use the hash of the ROTPK stored in the Trusted + Key Storage registers to verify the ROTPK in the `plat_match_rotpk()` + function. This prevents the correct establishment of the Chain of Trust at the + first step in the Trusted Board Boot process. +- The version of the AEMv8 Base FVP used in this release resets the model + instead of terminating its execution in response to a shutdown request using + the PSCI `SYSTEM_OFF` API. This issue will be fixed in a future version of the + model. +- GICv3 support is experimental. There are known issues with GICv3 + initialization in the TF-A. +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. +- The Juno-specific firmware design documentation is incomplete. + +## [1.0.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.4..refs/tags/v1.0) (2014-08-28) + +### New features + +- It is now possible to map higher physical addresses using non-flat virtual to + physical address mappings in the MMU setup. + +- Wider use is now made of the per-CPU data cache in BL3-1 to store: + + - Pointers to the non-secure and secure security state contexts. + - A pointer to the CPU-specific operations. + - A pointer to PSCI specific information (for example the current power + state). + - A crash reporting buffer. + +- The following RAM usage improvements result in a BL3-1 RAM usage reduction + from 96KB to 56KB (for FVP with TSPD), and a total RAM usage reduction across + all images from 208KB to 88KB, compared to the previous release. + + - Removed the separate `early_exception` vectors from BL3-1 (2KB code size + saving). + - Removed NSRAM from the FVP memory map, allowing the removal of one (4KB) + translation table. + - Eliminated the internal `psci_suspend_context` array, saving 2KB. + - Correctly dimensioned the PSCI `aff_map_node` array, saving 1.5KB in the FVP + port. + - Removed calling CPU mpidr from the bakery lock API, saving 160 bytes. + - Removed current CPU mpidr from PSCI common code, saving 160 bytes. + - Inlined the mmio accessor functions, saving 360 bytes. + - Fully reclaimed all BL1 RW memory and BL2 memory on the FVP port by + overlaying the BL3-1/BL3-2 NOBITS sections on top of these at runtime. + - Made storing the FP register context optional, saving 0.5KB per context (8KB + on the FVP port, with TSPD enabled and running on 8 CPUs). + - Implemented a leaner `tf_printf()` function, allowing the stack to be + greatly reduced. + - Removed coherent stacks from the codebase. Stacks allocated in normal memory + are now used before and after the MMU is enabled. This saves 768 bytes per + CPU in BL3-1. + - Reworked the crash reporting in BL3-1 to use less stack. + - Optimized the EL3 register state stored in the `cpu_context` structure so + that registers that do not change during normal execution are re-initialized + each time during cold/warm boot, rather than restored from memory. This + saves about 1.2KB. + - As a result of some of the above, reduced the runtime stack size in all BL + images. For BL3-1, this saves 1KB per CPU. + +- PSCI SMC handler improvements to correctly handle calls from secure states and + from AArch32. + +- CPU contexts are now initialized from the `entry_point_info`. BL3-1 fully + determines the exception level to use for the non-trusted firmware (BL3-3) + based on the SPSR value provided by the BL2 platform code (or otherwise + provided to BL3-1). This allows platform code to directly run non-trusted + firmware payloads at either EL2 or EL1 without requiring an EL2 stub or OS + loader. + +- Code refactoring improvements: + + - Refactored `fvp_config` into a common platform header. + - Refactored the fvp gic code to be a generic driver that no longer has an + explicit dependency on platform code. + - Refactored the CCI-400 driver to not have dependency on platform code. + - Simplified the IO driver so it's no longer necessary to call `io_init()` and + moved all the IO storage framework code to one place. + - Simplified the interface the the TZC-400 driver. + - Clarified the platform porting interface to the TSP. + - Reworked the TSPD setup code to support the alternate BL3-2 initialization + flow where BL3-1 generic code hands control to BL3-2, rather than expecting + the TSPD to hand control directly to BL3-2. + - Considerable rework to PSCI generic code to support CPU specific operations. + +- Improved console log output, by: + + - Adding the concept of debug log levels. + - Rationalizing the existing debug messages and adding new ones. + - Printing out the version of each BL stage at runtime. + - Adding support for printing console output from assembler code, including + when a crash occurs before the C runtime is initialized. + +- Moved up to the latest versions of the FVPs, toolchain, EDK2, kernel, Linaro + file system and DS-5. + +- On the FVP port, made the use of the Trusted DRAM region optional at build + time (off by default). Normal platforms will not have such a "ready-to-use" + DRAM area so it is not a good example to use it. + +- Added support for PSCI `SYSTEM_OFF` and `SYSTEM_RESET` APIs. + +- Added support for CPU specific reset sequences, power down sequences and + register dumping during crash reporting. The CPU specific reset sequences + include support for errata workarounds. + +- Merged the Juno port into the master branch. Added support for CPU hotplug and + CPU idle. Updated the user guide to describe how to build and run on the Juno + platform. + +### Issues resolved since last release + +- Removed the concept of top/bottom image loading. The image loader now + automatically detects the position of the image inside the current memory + layout and updates the layout to minimize fragmentation. This resolves the + image loader limitations of previously releases. There are currently no plans + to support dynamic image loading. +- CPU idle now works on the publicized version of the Foundation FVP. +- All known issues relating to the compiler version used have now been resolved. + This TF-A version uses Linaro toolchain 14.07 (based on GCC 4.9). + +### Known issues + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in the + TF-A. + +- While this version greatly reduces the on-chip RAM requirements, there are + further RAM usage enhancements that could be made. + +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +- The Juno-specific firmware design documentation is incomplete. + +- Some recent enhancements to the FVP port have not yet been translated into the + Juno port. These will be tracked via the tf-issues project. + +- The Linux kernel version referred to in the user guide has DVFS and HMP + support disabled due to some known instabilities at the time of this release. + A future kernel version will re-enable these features. + +- DS-5 v5.19 does not detect Version 5.8 of the Cortex-A57-A53 Base FVPs in CADI + server mode. This is because the `` reported by the FVP in this + version has changed. For example, for the Cortex-A57x4-A53x4 Base FVP, the + `` reported by the FVP is `FVP_Base_Cortex_A57x4_A53x4`, while DS-5 + expects it to be `FVP_Base_A57x4_A53x4`. + + The temporary fix to this problem is to change the name of the FVP in + `sw/debugger/configdb/Boards/ARM FVP/Base_A57x4_A53x4/cadi_config.xml`. Change + the following line: + + ``` + System Generator:FVP_Base_A57x4_A53x4 + ``` + + to System Generator:FVP_Base_Cortex-A57x4_A53x4 + + A similar change can be made to the other Cortex-A57-A53 Base FVP variants. + +## [0.4.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.3..refs/tags/v0.4) (2014-06-03) + +### New features + +- Makefile improvements: + + - Improved dependency checking when building. + - Removed `dump` target (build now always produces dump files). + - Enabled platform ports to optionally make use of parts of the Trusted + Firmware (e.g. BL3-1 only), rather than being forced to use all parts. Also + made the `fip` target optional. + - Specified the full path to source files and removed use of the `vpath` + keyword. + +- Provided translation table library code for potential re-use by platforms + other than the FVPs. + +- Moved architectural timer setup to platform-specific code. + +- Added standby state support to PSCI cpu_suspend implementation. + +- SRAM usage improvements: + + - Started using the `-ffunction-sections`, `-fdata-sections` and + `--gc-sections` compiler/linker options to remove unused code and data from + the images. Previously, all common functions were being built into all + binary images, whether or not they were actually used. + - Placed all assembler functions in their own section to allow more unused + functions to be removed from images. + - Updated BL1 and BL2 to use a single coherent stack each, rather than one per + CPU. + - Changed variables that were unnecessarily declared and initialized as + non-const (i.e. in the .data section) so they are either uninitialized (zero + init) or const. + +- Moved the Test Secure-EL1 Payload (BL3-2) to execute in Trusted SRAM by + default. The option for it to run in Trusted DRAM remains. + +- Implemented a TrustZone Address Space Controller (TZC-400) driver. A default + configuration is provided for the Base FVPs. This means the model parameter + `-C bp.secure_memory=1` is now supported. + +- Started saving the PSCI cpu_suspend 'power_state' parameter prior to + suspending a CPU. This allows platforms that implement multiple power-down + states at the same affinity level to identify a specific state. + +- Refactored the entire codebase to reduce the amount of nesting in header files + and to make the use of system/user includes more consistent. Also split + platform.h to separate out the platform porting declarations from the required + platform porting definitions and the definitions/declarations specific to the + platform port. + +- Optimized the data cache clean/invalidate operations. + +- Improved the BL3-1 unhandled exception handling and reporting. Unhandled + exceptions now result in a dump of registers to the console. + +- Major rework to the handover interface between BL stages, in particular the + interface to BL3-1. The interface now conforms to a specification and is more + future proof. + +- Added support for optionally making the BL3-1 entrypoint a reset handler + (instead of BL1). This allows platforms with an alternative image loading + architecture to re-use BL3-1 with fewer modifications to generic code. + +- Reserved some DDR DRAM for secure use on FVP platforms to avoid future + compatibility problems with non-secure software. + +- Added support for secure interrupts targeting the Secure-EL1 Payload (SP) + (using GICv2 routing only). Demonstrated this working by adding an interrupt + target and supporting test code to the TSP. Also demonstrated non-secure + interrupt handling during TSP processing. + +### Issues resolved since last release + +- Now support use of the model parameter `-C bp.secure_memory=1` in the Base + FVPs (see **New features**). +- Support for secure world interrupt handling now available (see **New + features**). +- Made enough SRAM savings (see **New features**) to enable the Test Secure-EL1 + Payload (BL3-2) to execute in Trusted SRAM by default. +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.04) now correctly reports progress in the console. +- Improved the Makefile structure to make it easier to separate out parts of the + TF-A for re-use in platform ports. Also, improved target dependency checking. + +### Known issues + +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in the + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- TF-A still uses too much on-chip Trusted SRAM. A number of RAM usage + enhancements have been identified to rectify this situation. +- CPU idle does not work on the advertised version of the Foundation FVP. Some + FVP fixes are required that are not available externally at the time of + writing. This can be worked around by disabling CPU idle in the Linux kernel. +- Various bugs in TF-A, UEFI and the Linux kernel have been observed when using + Linaro toolchain versions later than 13.11. Although most of these have been + fixed, some remain at the time of writing. These mainly seem to relate to a + subtle change in the way the compiler converts between 64-bit and 32-bit + values (e.g. during casting operations), which reveals previously hidden bugs + in client code. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +## [0.3.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/refs/tags/v0.2..refs/tags/v0.3) (2014-02-28) + +### New features + +- Support for Foundation FVP Version 2.0 added. The documented UEFI + configuration disables some devices that are unavailable in the Foundation + FVP, including MMC and CLCD. The resultant UEFI binary can be used on the + AEMv8 and Cortex-A57-A53 Base FVPs, as well as the Foundation FVP. + + \:::\{note} The software will not work on Version 1.0 of the Foundation FVP. + \::: + +- Enabled third party contributions. Added a new contributing.md containing + instructions for how to contribute and updated copyright text in all files to + acknowledge contributors. + +- The PSCI CPU_SUSPEND API has been stabilised to the extent where it can be + used for entry into power down states with the following restrictions: + + - Entry into standby states is not supported. + - The API is only supported on the AEMv8 and Cortex-A57-A53 Base FVPs. + +- The PSCI AFFINITY_INFO api has undergone limited testing on the Base FVPs to + allow experimental use. + +- Required C library and runtime header files are now included locally in TF-A + instead of depending on the toolchain standard include paths. The local + implementation has been cleaned up and reduced in scope. + +- Added I/O abstraction framework, primarily to allow generic code to load + images in a platform-independent way. The existing image loading code has been + reworked to use the new framework. Semi-hosting and NOR flash I/O drivers are + provided. + +- Introduced Firmware Image Package (FIP) handling code and tools. A FIP + combines multiple firmware images with a Table of Contents (ToC) into a single + binary image. The new FIP driver is another type of I/O driver. The Makefile + builds a FIP by default and the FVP platform code expect to load a FIP from + NOR flash, although some support for image loading using semi- hosting is + retained. + + \:::\{note} Building a FIP by default is a non-backwards-compatible change. ::: + + \:::\{note} Generic BL2 code now loads a BL3-3 (non-trusted firmware) image + into DRAM instead of expecting this to be pre-loaded at known location. This + is also a non-backwards-compatible change. ::: + + \:::\{note} Some non-trusted firmware (e.g. UEFI) will need to be rebuilt so + that it knows the new location to execute from and no longer needs to copy + particular code modules to DRAM itself. ::: + +- Reworked BL2 to BL3-1 handover interface. A new composite structure + (bl31_args) holds the superset of information that needs to be passed from BL2 + to BL3-1, including information on how handover execution control to BL3-2 (if + present) and BL3-3 (non-trusted firmware). + +- Added library support for CPU context management, allowing the saving and + restoring of + + - Shared system registers between Secure-EL1 and EL1. + - VFP registers. + - Essential EL3 system registers. + +- Added a framework for implementing EL3 runtime services. Reworked the PSCI + implementation to be one such runtime service. + +- Reworked the exception handling logic, making use of both SP_EL0 and SP_EL3 + stack pointers for determining the type of exception, managing general purpose + and system register context on exception entry/exit, and handling SMCs. SMCs + are directed to the correct EL3 runtime service. + +- Added support for a Test Secure-EL1 Payload (TSP) and a corresponding + Dispatcher (TSPD), which is loaded as an EL3 runtime service. The TSPD + implements Secure Monitor functionality such as world switching and EL1 + context management, and is responsible for communication with the TSP. + + \:::\{note} The TSPD does not yet contain support for secure world interrupts. + \::: + + \:::\{note} The TSP/TSPD is not built by default. ::: + +### Issues resolved since last release + +- Support has been added for switching context between secure and normal worlds + in EL3. +- PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` have now been tested (to a + limited extent). +- The TF-A build artifacts are now placed in the `./build` directory and + sub-directories instead of being placed in the root of the project. +- TF-A is now free from build warnings. Build warnings are now treated as + errors. +- TF-A now provides C library support locally within the project to maintain + compatibility between toolchains/systems. +- The PSCI locking code has been reworked so it no longer takes locks in an + incorrect sequence. +- The RAM-disk method of loading a Linux file-system has been confirmed to work + with the TF-A and Linux kernel version (based on version 3.13) used in this + release, for both Foundation and Base FVPs. + +### Known issues + +The following is a list of issues which are expected to be fixed in the future +releases of TF-A. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed yet. + Use of model parameter `-C bp.secure_memory=1` is not supported. +- No support yet for secure world interrupt handling. +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- TF-A uses too much on-chip Trusted SRAM. Currently the Test Secure-EL1 Payload + (BL3-2) executes in Trusted DRAM since there is not enough SRAM. A number of + RAM usage enhancements have been identified to rectify this situation. +- CPU idle does not work on the advertised version of the Foundation FVP. Some + FVP fixes are required that are not available externally at the time of + writing. +- Various bugs in TF-A, UEFI and the Linux kernel have been observed when using + Linaro toolchain versions later than 13.11. Although most of these have been + fixed, some remain at the time of writing. These mainly seem to relate to a + subtle change in the way the compiler converts between 64-bit and 32-bit + values (e.g. during casting operations), which reveals previously hidden bugs + in client code. +- The tested filesystem used for this release (Linaro AArch64 OpenEmbedded + 14.01) does not report progress correctly in the console. It only seems to + produce error output, not standard output. It otherwise appears to function + correctly. Other filesystem versions on the same software stack do not exhibit + the problem. +- The Makefile structure doesn't make it easy to separate out parts of the TF-A + for re-use in platform ports, for example if only BL3-1 is required in a + platform port. Also, dependency checking in the Makefile is flawed. +- The firmware design documentation for the Test Secure-EL1 Payload (TSP) and + its dispatcher (TSPD) is incomplete. Similarly for the PSCI section. + +## [0.2.0](https://review.trustedfirmware.org/plugins/gitiles/TF-A/trusted-firmware-a/+/4b825dc642cb6eb9a060e54bf8d69288fbee4904..refs/tags/v0.2) (2013-10-25) + +### New features + +- First source release. +- Code for the PSCI suspend feature is supplied, although this is not enabled by + default since there are known issues (see below). + +### Issues resolved since last release + +- The "psci" nodes in the FDTs provided in this release now fully comply with + the recommendations made in the PSCI specification. + +### Known issues + +The following is a list of issues which are expected to be fixed in the future +releases of TF-A. + +- The TrustZone Address Space Controller (TZC-400) is not being programmed yet. + Use of model parameter `-C bp.secure_memory=1` is not supported. +- No support yet for secure world interrupt handling or for switching context + between secure and normal worlds in EL3. +- GICv3 support is experimental. The Linux kernel patches to support this are + not widely available. There are known issues with GICv3 initialization in + TF-A. +- Dynamic image loading is not available yet. The current image loader + implementation (used to load BL2 and all subsequent images) has some + limitations. Changing BL2 or BL3-1 load addresses in certain ways can lead to + loading errors, even if the images should theoretically fit in memory. +- Although support for PSCI `CPU_SUSPEND` is present, it is not yet stable and + ready for use. +- PSCI API calls `AFFINITY_INFO` & `PSCI_VERSION` are implemented but have not + been tested. +- The TF-A make files result in all build artifacts being placed in the root of + the project. These should be placed in appropriate sub-directories. +- The compilation of TF-A is not free from compilation warnings. Some of these + warnings have not been investigated yet so they could mask real bugs. +- TF-A currently uses toolchain/system include files like stdio.h. It should + provide versions of these within the project to maintain compatibility between + toolchains/systems. +- The PSCI code takes some locks in an incorrect sequence. This may cause + problems with suspend and hotplug in certain conditions. +- The Linux kernel used in this release is based on version 3.12-rc4. Using this + kernel with the TF-A fails to start the file-system as a RAM-disk. It fails to + execute user-space `init` from the RAM-disk. As an alternative, the + VirtioBlock mechanism can be used to provide a file-system to the kernel. + +______________________________________________________________________ + +*Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved.* + +[mbed tls releases]: https://tls.mbed.org/tech-updates/releases +[pr#1002]: https://github.com/ARM-software/arm-trusted-firmware/pull/1002#issuecomment-312650193 +[sdei specification]: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +[tf-issue#501]: https://github.com/ARM-software/tf-issues/issues/501 diff --git a/arm-trusted-firmware/docs/components/activity-monitors.rst b/arm-trusted-firmware/docs/components/activity-monitors.rst new file mode 100644 index 0000000..dd45c43 --- /dev/null +++ b/arm-trusted-firmware/docs/components/activity-monitors.rst @@ -0,0 +1,34 @@ +Activity Monitors +================= + +FEAT_AMUv1 of the Armv8-A architecture introduces the Activity Monitors +extension. This extension describes the architecture for the Activity Monitor +Unit (|AMU|), an optional non-invasive component for monitoring core events +through a set of 64-bit counters. + +When the ``ENABLE_AMU=1`` build option is provided, Trusted Firmware-A sets up +the |AMU| prior to its exit from EL3, and will save and restore architected +|AMU| counters as necessary upon suspend and resume. + +.. _Activity Monitor Auxiliary Counters: + +Auxiliary counters +------------------ + +FEAT_AMUv1 describes a set of implementation-defined auxiliary counters (also +known as group 1 counters), controlled by the ``ENABLE_AMU_AUXILIARY_COUNTERS`` +build option. + +As a security precaution, Trusted Firmware-A does not enable these by default. +Instead, platforms may configure their auxiliary counters through one of two +possible mechanisms: + +- |FCONF|, controlled by the ``ENABLE_AMU_FCONF`` build option. +- A platform implementation of the ``plat_amu_topology`` function (the default). + +See :ref:`Activity Monitor Unit (AMU) Bindings` for documentation on the |FCONF| +device tree bindings. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/arm-sip-service.rst b/arm-trusted-firmware/docs/components/arm-sip-service.rst new file mode 100644 index 0000000..b51a94d --- /dev/null +++ b/arm-trusted-firmware/docs/components/arm-sip-service.rst @@ -0,0 +1,435 @@ +Arm SiP Services +================ + +This document enumerates and describes the Arm SiP (Silicon Provider) services. + +SiP services are non-standard, platform-specific services offered by the silicon +implementer or platform provider. They are accessed via ``SMC`` ("SMC calls") +instruction executed from Exception Levels below EL3. SMC calls for SiP +services: + +- Follow `SMC Calling Convention`_; +- Use SMC function IDs that fall in the SiP range, which are ``0xc2000000`` - + ``0xc200ffff`` for 64-bit calls, and ``0x82000000`` - ``0x8200ffff`` for 32-bit + calls. + +The Arm SiP implementation offers the following services: + +- Performance Measurement Framework (PMF) +- Execution State Switching service +- DebugFS interface + +Source definitions for Arm SiP service are located in the ``arm_sip_svc.h`` header +file. + +Performance Measurement Framework (PMF) +--------------------------------------- + +The :ref:`Performance Measurement Framework ` +allows callers to retrieve timestamps captured at various paths in TF-A +execution. + +Execution State Switching service +--------------------------------- + +Execution State Switching service provides a mechanism for a non-secure lower +Exception Level (either EL2, or NS EL1 if EL2 isn't implemented) to request to +switch its execution state (a.k.a. Register Width), either from AArch64 to +AArch32, or from AArch32 to AArch64, for the calling CPU. This service is only +available when Trusted Firmware-A (TF-A) is built for AArch64 (i.e. when build +option ``ARCH`` is set to ``aarch64``). + +``ARM_SIP_SVC_EXE_STATE_SWITCH`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t Function ID + uint32_t PC hi + uint32_t PC lo + uint32_t Cookie hi + uint32_t Cookie lo + + Return: + uint32_t + +The function ID parameter must be ``0x82000020``. It uniquely identifies the +Execution State Switching service being requested. + +The parameters *PC hi* and *PC lo* defines upper and lower words, respectively, +of the entry point (physical address) at which execution should start, after +Execution State has been switched. When calling from AArch64, *PC hi* must be 0. + +When execution starts at the supplied entry point after Execution State has been +switched, the parameters *Cookie hi* and *Cookie lo* are passed in CPU registers +0 and 1, respectively. When calling from AArch64, *Cookie hi* must be 0. + +This call can only be made on the primary CPU, before any secondaries were +brought up with ``CPU_ON`` PSCI call. Otherwise, the call will always fail. + +The effect of switching execution state is as if the Exception Level were +entered for the first time, following power on. This means CPU registers that +have a defined reset value by the Architecture will assume that value. Other +registers should not be expected to hold their values before the call was made. +CPU endianness, however, is preserved from the previous execution state. Note +that this switches the execution state of the calling CPU only. This is not a +substitute for PSCI ``SYSTEM_RESET``. + +The service may return the following error codes: + +- ``STATE_SW_E_PARAM``: If any of the parameters were deemed invalid for + a specific request. +- ``STATE_SW_E_DENIED``: If the call is not successful, or when TF-A is + built for AArch32. + +If the call is successful, the caller wouldn't observe the SMC returning. +Instead, execution starts at the supplied entry point, with the CPU registers 0 +and 1 populated with the supplied *Cookie hi* and *Cookie lo* values, +respectively. + +DebugFS interface +----------------- + +The optional DebugFS interface is accessed through an SMC SiP service. Refer +to the component documentation for details. + +String parameters are passed through a shared buffer using a specific union: + +.. code:: c + + union debugfs_parms { + struct { + char fname[MAX_PATH_LEN]; + } open; + + struct mount { + char srv[MAX_PATH_LEN]; + char where[MAX_PATH_LEN]; + char spec[MAX_PATH_LEN]; + } mount; + + struct { + char path[MAX_PATH_LEN]; + dir_t dir; + } stat; + + struct { + char oldpath[MAX_PATH_LEN]; + char newpath[MAX_PATH_LEN]; + } bind; + }; + +Format of the dir_t structure as such: + +.. code:: c + + typedef struct { + char name[NAMELEN]; + long length; + unsigned char mode; + unsigned char index; + unsigned char dev; + qid_t qid; + } dir_t; + + +* Identifiers + +======================== ============================================= +SMC_OK 0 +SMC_UNK -1 +DEBUGFS_E_INVALID_PARAMS -2 +======================== ============================================= + +======================== ============================================= +MOUNT 0 +CREATE 1 +OPEN 2 +CLOSE 3 +READ 4 +WRITE 5 +SEEK 6 +BIND 7 +STAT 8 +INIT 10 +VERSION 11 +======================== ============================================= + +MOUNT +~~~~~ + +Description +^^^^^^^^^^^ +This operation mounts a blob of data pointed to by path stored in `src`, at +filesystem location pointed to by path stored in `where`, using driver pointed +to by path in `spec`. + +Parameters +^^^^^^^^^^ +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``MOUNT`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if mount operation failed +=============== ========================================================== + +OPEN +~~~~ + +Description +^^^^^^^^^^^ +This operation opens the file path pointed to by `fname`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``OPEN`` +uint32_t mode +======== ============================================================ + +mode can be one of: + +.. code:: c + + enum mode { + O_READ = 1 << 0, + O_WRITE = 1 << 1, + O_RDWR = 1 << 2, + O_BIND = 1 << 3, + O_DIR = 1 << 4, + O_STAT = 1 << 5 + }; + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if open operation failed + +uint32_t w1: file descriptor id on success. +=============== ========================================================== + +CLOSE +~~~~~ + +Description +^^^^^^^^^^^ + +This operation closes a file described by a file descriptor obtained by a +previous call to OPEN. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``CLOSE`` +uint32_t File descriptor id returned by OPEN +======== ============================================================ + +Return values +^^^^^^^^^^^^^ +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if close operation failed +=============== ========================================================== + +READ +~~~~ + +Description +^^^^^^^^^^^ + +This operation reads a number of bytes from a file descriptor obtained by +a previous call to OPEN. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``READ`` +uint32_t File descriptor id returned by OPEN +uint32_t Number of bytes to read +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +On success, the read data is retrieved from the shared buffer after the +operation. + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if read operation failed + +uint32_t w1: number of bytes read on success. +=============== ========================================================== + +SEEK +~~~~ + +Description +^^^^^^^^^^^ + +Move file pointer for file described by given `file descriptor` of given +`offset` related to `whence`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``SEEK`` +uint32_t File descriptor id returned by OPEN +sint32_t offset in the file relative to whence +uint32_t whence +======== ============================================================ + +whence can be one of: + +========= ============================================================ +KSEEK_SET 0 +KSEEK_CUR 1 +KSEEK_END 2 +========= ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if seek operation failed +=============== ========================================================== + +BIND +~~~~ + +Description +^^^^^^^^^^^ + +Create a link from `oldpath` to `newpath`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``BIND`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if bind operation failed +=============== ========================================================== + +STAT +~~~~ + +Description +^^^^^^^^^^^ + +Perform a stat operation on provided file `name` and returns the directory +entry statistics into `dir`. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``STAT`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ========================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if stat operation failed +=============== ========================================================== + +INIT +~~~~ + +Description +^^^^^^^^^^^ +Initial call to setup the shared exchange buffer. Notice if successful once, +subsequent calls fail after a first initialization. The caller maps the same +page frame in its virtual space and uses this buffer to exchange string +parameters with filesystem primitives. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``INIT`` +uint64_t Physical address of the shared buffer. +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ====================================================== +int32_t w0 == SMC_OK on success + + w0 == DEBUGFS_E_INVALID_PARAMS if already initialized, + or internal error occurred. +=============== ====================================================== + +VERSION +~~~~~~~ + +Description +^^^^^^^^^^^ +Returns the debugfs interface version if implemented in TF-A. + +Parameters +^^^^^^^^^^ + +======== ============================================================ +uint32_t FunctionID (0x82000030 / 0xC2000030) +uint32_t ``VERSION`` +======== ============================================================ + +Return values +^^^^^^^^^^^^^ + +=============== ====================================================== +int32_t w0 == SMC_OK on success + + w0 == SMC_UNK if interface is not implemented + +uint32_t w1: On success, debugfs interface version, 32 bits + value with major version number in upper 16 bits and + minor version in lower 16 bits. +=============== ====================================================== + +* CREATE(1) and WRITE (5) command identifiers are unimplemented and + return `SMC_UNK`. + +-------------- + +*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest diff --git a/arm-trusted-firmware/docs/components/cot-binding.rst b/arm-trusted-firmware/docs/components/cot-binding.rst new file mode 100644 index 0000000..4f8c8b7 --- /dev/null +++ b/arm-trusted-firmware/docs/components/cot-binding.rst @@ -0,0 +1,332 @@ +Chain of trust bindings +======================= + +The device tree allows to describe the chain of trust with the help of +'cot' node which contain 'manifests' and 'images' as sub-nodes. +'manifests' and 'images' nodes contains number of sub-nodes (i.e. 'certificate' +and 'image' nodes) mentioning properties of the certificate and image respectively. + +Also, device tree describes 'non-volatile-counters' node which contains number of +sub-nodes mentioning properties of all non-volatile-counters used in the chain of trust. + +cot +------------------------------------------------------------------ +This is root node which contains 'manifests' and 'images' as sub-nodes + + +Manifests and Certificate node bindings definition +---------------------------------------------------------------- + +- Manifests node + Description: Container of certificate nodes. + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, cert-descs" + +- Certificate node + Description: + + Describes certificate properties which are used + during the authentication process. + + PROPERTIES + + - root-certificate + Usage: + + Required for the certificate with no parent. + In other words, certificates which are validated + using root of trust public key. + + Value type: + + - image-id + Usage: Required for every certificate with unique id. + + Value type: + + - parent + Usage: + + It refers to their parent image, which typically contains + information to authenticate the certificate. + This property is required for all non-root certificates. + + This property is not required for root-certificates + as root-certificates are validated using root of trust + public key provided by platform. + + Value type: + + - signing-key + Usage: + + This property is used to refer public key node present in + parent certificate node and it is required property for all + non-root certificates which are authenticated using public-key + present in parent certificate. + + This property is not required for root-certificates + as root-certificates are validated using root of trust + public key provided by platform. + + Value type: + + - antirollback-counter + Usage: + + This property is used by all certificates which are + protected against rollback attacks using a non-volatile + counter and it is an optional property. + + This property is used to refer one of the non-volatile + counter sub-node present in 'non-volatile counters' node. + + Value type: + + + SUBNODES + - Description: + + Hash and public key information present in the certificate + are shown by these nodes. + + - public key node + Description: Provide public key information in the certificate. + + PROPERTIES + + - oid + Usage: + + This property provides the Object ID of public key + provided in the certificate which the help of which + public key information can be extracted. + + Value type: + + - hash node + Description: Provide the hash information in the certificate. + + PROPERTIES + + - oid + Usage: + + This property provides the Object ID of hash provided in + the certificate which the help of which hash information + can be extracted. + + Value type: + +Example: + +.. code:: c + + cot { + manifests { + compatible = "arm, cert-descs†+ + trusted-key-cert: trusted-key-cert { + root-certificate; + image-id = ; + antirollback-counter = <&trusted_nv_counter>; + + trusted-world-pk: trusted-world-pk { + oid = TRUSTED_WORLD_PK_OID; + }; + non-trusted-world-pk: non-trusted-world-pk { + oid = NON_TRUSTED_WORLD_PK_OID; + }; + }; + + scp_fw_key_cert: scp_fw_key_cert { + image-id = ; + parent = <&trusted-key-cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_content_pk: scp_fw_content_pk { + oid = SCP_FW_CONTENT_CERT_PK_OID; + }; + }; + . + . + . + + next-certificate { + + }; + }; + }; + +Images and Image node bindings definition +----------------------------------------- + +- Images node + Description: Container of image nodes + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, img-descs" + +- Image node + Description: + + Describes image properties which will be used during + authentication process. + + PROPERTIES + + - image-id + Usage: Required for every image with unique id. + + Value type: + + - parent + Usage: + + Required for every image to provide a reference to + its parent image, which contains the necessary information + to authenticate it. + + Value type: + + - hash + Usage: + + Required for all images which are validated using + hash method. This property is used to refer hash + node present in parent certificate node. + + Value type: + + Note: + + Currently, all images are validated using 'hash' + method. In future, there may be multiple methods can + be used to validate the image. + +Example: + +.. code:: c + + cot { + images { + compatible = "arm, img-descs"; + + scp_bl2_image { + image-id = ; + parent = <&scp_fw_content_cert>; + hash = <&scp_fw_hash>; + }; + + . + . + . + + next-img { + + }; + }; + }; + +non-volatile counter node binding definition +-------------------------------------------- + +- non-volatile counters node + Description: Contains properties for non-volatile counters. + + PROPERTIES + + - compatible: + Usage: required + + Value type: + + Definition: must be "arm, non-volatile-counter" + + - #address-cells + Usage: required + + Value type: + + Definition: + + Must be set according to address size + of non-volatile counter register + + - #size-cells + Usage: required + + Value type: + + Definition: must be set to 0 + + SUBNODE + - counters node + Description: Contains various non-volatile counters present in the platform. + + PROPERTIES + - id + Usage: Required for every nv-counter with unique id. + + Value type: + + - reg + Usage: + + Register base address of non-volatile counter and it is required + property. + + Value type: + + - oid + Usage: + + This property provides the Object ID of non-volatile counter + provided in the certificate and it is required property. + + Value type: + +Example: +Below is non-volatile counters example for ARM platform + +.. code:: c + + non_volatile_counters: non_volatile_counters { + compatible = "arm, non-volatile-counter"; + #address-cells = <1>; + #size-cells = <0>; + + trusted-nv-counter: trusted_nv_counter { + id = ; + reg = ; + oid = TRUSTED_FW_NVCOUNTER_OID; + }; + + non_trusted_nv_counter: non_trusted_nv_counter { + id = ; + reg = ; + oid = NON_TRUSTED_FW_NVCOUNTER_OID; + }; + }; + +Future update to chain of trust binding +--------------------------------------- + +This binding document needs to be revisited to generalise some terminologies +which are currently specific to X.509 certificates for e.g. Object IDs. + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/debugfs-design.rst b/arm-trusted-firmware/docs/components/debugfs-design.rst new file mode 100644 index 0000000..2536515 --- /dev/null +++ b/arm-trusted-firmware/docs/components/debugfs-design.rst @@ -0,0 +1,125 @@ +======== +Debug FS +======== + +.. contents:: + +Overview +-------- + +The *DebugFS* feature is primarily aimed at exposing firmware debug data to +higher SW layers such as a non-secure component. Such component can be the +TFTF test payload or a Linux kernel module. + +Virtual filesystem +------------------ + +The core functionality lies in a virtual file system based on a 9p file server +interface (`Notes on the Plan 9 Kernel Source`_ and +`Linux 9p remote filesystem protocol`_). +The implementation permits exposing virtual files, firmware drivers, and file blobs. + +Namespace +~~~~~~~~~ + +Two namespaces are exposed: + + - # is used as root for drivers (e.g. #t0 is the first uart) + - / is used as root for virtual "files" (e.g. /fip, or /dev/uart) + +9p interface +~~~~~~~~~~~~ + +The associated primitives are: + +- Unix-like: + + - open(): create a file descriptor that acts as a handle to the file passed as + an argument. + - close(): close the file descriptor created by open(). + - read(): read from a file to a buffer. + - write(): write from a buffer to a file. + - seek(): set the file position indicator of a file descriptor either to a + relative or an absolute offset. + - stat(): get information about a file (type, mode, size, ...). + +.. code:: c + + int open(const char *name, int flags); + int close(int fd); + int read(int fd, void *buf, int n); + int write(int fd, void *buf, int n); + int seek(int fd, long off, int whence); + int stat(char *path, dir_t *dir); + +- Specific primitives : + + - mount(): create a link between a driver and spec. + - create(): create a file in a specific location. + - bind(): expose the content of a directory to another directory. + +.. code:: c + + int mount(char *srv, char *mnt, char *spec); + int create(const char *name, int flags); + int bind(char *path, char *where); + +This interface is embedded into the BL31 run-time payload when selected by build +options. The interface multiplexes drivers or emulated "files": + +- Debug data can be partitioned into different virtual files e.g. expose PMF + measurements through a file, and internal firmware state counters through + another file. +- This permits direct access to a firmware driver, mainly for test purposes + (e.g. a hardware device that may not be accessible to non-privileged/ + non-secure layers, or for which no support exists in the NS side). + +SMC interface +------------- + +The communication with the 9p layer in BL31 is made through an SMC conduit +(`SMC Calling Convention`_), using a specific SiP Function Id. An NS +shared buffer is used to pass path string parameters, or e.g. to exchange +data on a read operation. Refer to :ref:`ARM SiP Services ` +for a description of the SMC interface. + +Security considerations +----------------------- + +- Due to the nature of the exposed data, the feature is considered experimental + and importantly **shall only be used in debug builds**. +- Several primitive imply string manipulations and usage of string formats. +- Special care is taken with the shared buffer to avoid TOCTOU attacks. + +Limitations +----------- + +- In order to setup the shared buffer, the component consuming the interface + needs to allocate a physical page frame and transmit its address. +- In order to map the shared buffer, BL31 requires enabling the dynamic xlat + table option. +- Data exchange is limited by the shared buffer length. A large read operation + might be split into multiple read operations of smaller chunks. +- On concurrent access, a spinlock is implemented in the BL31 service to protect + the internal work buffer, and re-entrancy into the filesystem layers. +- Notice, a physical device driver if exposed by the firmware may conflict with + the higher level OS if the latter implements its own driver for the same + physical device. + +Applications +------------ + +The SMC interface is accessible from an NS environment, that is: + +- a test payload, bootloader or hypervisor running at NS-EL2 +- a Linux kernel driver running at NS-EL1 +- a Linux userspace application through the kernel driver + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Notes on the Plan 9 Kernel Source: http://lsub.org/who/nemo/9.pdf +.. _Linux 9p remote filesystem protocol: https://www.kernel.org/doc/Documentation/filesystems/9p.txt +.. _ARM SiP Services: arm-sip-service.rst diff --git a/arm-trusted-firmware/docs/components/exception-handling.rst b/arm-trusted-firmware/docs/components/exception-handling.rst new file mode 100644 index 0000000..6f223c6 --- /dev/null +++ b/arm-trusted-firmware/docs/components/exception-handling.rst @@ -0,0 +1,619 @@ +Exception Handling Framework +============================ + +This document describes various aspects of handling exceptions by Runtime +Firmware (BL31) that are targeted at EL3, other than SMCs. The |EHF| takes care +of the following exceptions when targeted at EL3: + +- Interrupts +- Synchronous External Aborts +- Asynchronous External Aborts + +|TF-A|'s handling of synchronous ``SMC`` exceptions raised from lower ELs is +described in the :ref:`Firmware Design document `. However, the +|EHF| changes the semantics of `Interrupt handling`_ and :ref:`synchronous +exceptions ` other than SMCs. + +The |EHF| is selected by setting the build option ``EL3_EXCEPTION_HANDLING`` to +``1``, and is only available for AArch64 systems. + +Introduction +------------ + +Through various control bits in the ``SCR_EL3`` register, the Arm architecture +allows for asynchronous exceptions to be routed to EL3. As described in the +:ref:`Interrupt Management Framework` document, depending on the chosen +interrupt routing model, TF-A appropriately sets the ``FIQ`` and ``IRQ`` bits of +``SCR_EL3`` register to effect this routing. For most use cases, other than for +the purpose of facilitating context switch between Normal and Secure worlds, +FIQs and IRQs routed to EL3 are not required to be handled in EL3. + +However, the evolving system and standards landscape demands that various +exceptions are targeted at and handled in EL3. For instance: + +- Starting with ARMv8.2 architecture extension, many RAS features have been + introduced to the Arm architecture. With RAS features implemented, various + components of the system may use one of the asynchronous exceptions to signal + error conditions to PEs. These error conditions are of critical nature, and + it's imperative that corrective or remedial actions are taken at the earliest + opportunity. Therefore, a *Firmware-first Handling* approach is generally + followed in response to RAS events in the system. + +- The Arm `SDEI specification`_ defines interfaces through which Normal world + interacts with the Runtime Firmware in order to request notification of + system events. The |SDEI| specification requires that these events are + notified even when the Normal world executes with the exceptions masked. This + too implies that firmware-first handling is required, where the events are + first received by the EL3 firmware, and then dispatched to Normal world + through purely software mechanism. + +For |TF-A|, firmware-first handling means that asynchronous exceptions are +suitably routed to EL3, and the Runtime Firmware (BL31) is extended to include +software components that are capable of handling those exceptions that target +EL3. These components—referred to as *dispatchers* [#spd]_ in general—may +choose to: + +.. _delegation-use-cases: + +- Receive and handle exceptions entirely in EL3, meaning the exceptions + handling terminates in EL3. + +- Receive exceptions, but handle part of the exception in EL3, and delegate the + rest of the handling to a dedicated software stack running at lower Secure + ELs. In this scheme, the handling spans various secure ELs. + +- Receive exceptions, but handle part of the exception in EL3, and delegate + processing of the error to dedicated software stack running at lower secure + ELs (as above); additionally, the Normal world may also be required to + participate in the handling, or be notified of such events (for example, as + an |SDEI| event). In this scheme, exception handling potentially and + maximally spans all ELs in both Secure and Normal worlds. + +On any given system, all of the above handling models may be employed +independently depending on platform choice and the nature of the exception +received. + +.. [#spd] Not to be confused with :ref:`Secure Payload Dispatcher + `, which is an EL3 component that operates in EL3 + on behalf of Secure OS. + +The role of Exception Handling Framework +---------------------------------------- + +Corollary to the use cases cited above, the primary role of the |EHF| is to +facilitate firmware-first handling of exceptions on Arm systems. The |EHF| thus +enables multiple exception dispatchers in runtime firmware to co-exist, register +for, and handle exceptions targeted at EL3. This section outlines the basics, +and the rest of this document expands the various aspects of the |EHF|. + +In order to arbitrate exception handling among dispatchers, the |EHF| operation +is based on a priority scheme. This priority scheme is closely tied to how the +Arm GIC architecture defines it, although it's applied to non-interrupt +exceptions too (SErrors, for example). + +The platform is required to `partition`__ the Secure priority space into +priority levels as applicable for the Secure software stack. It then assigns the +dispatchers to one or more priority levels. The dispatchers then register +handlers for the priority levels at runtime. A dispatcher can register handlers +for more than one priority level. + +.. __: `Partitioning priority levels`_ + + +.. _ehf-figure: + +.. image:: ../resources/diagrams/draw.io/ehf.svg + +A priority level is *active* when a handler at that priority level is currently +executing in EL3, or has delegated the execution to a lower EL. For interrupts, +this is implicit when an interrupt is targeted and acknowledged at EL3, and the +priority of the acknowledged interrupt is used to match its registered handler. +The priority level is likewise implicitly deactivated when the interrupt +handling concludes by EOIing the interrupt. + +Non-interrupt exceptions (SErrors, for example) don't have a notion of priority. +In order for the priority arbitration to work, the |EHF| provides APIs in order +for these non-interrupt exceptions to assume a priority, and to interwork with +interrupts. Dispatchers handling such exceptions must therefore explicitly +activate and deactivate the respective priority level as and when they're +handled or delegated. + +Because priority activation and deactivation for interrupt handling is implicit +and involves GIC priority masking, it's impossible for a lower priority +interrupt to preempt a higher priority one. By extension, this means that a +lower priority dispatcher cannot preempt a higher-priority one. Priority +activation and deactivation for non-interrupt exceptions, however, has to be +explicit. The |EHF| therefore disallows for lower priority level to be activated +whilst a higher priority level is active, and would result in a panic. +Likewise, a panic would result if it's attempted to deactivate a lower priority +level when a higher priority level is active. + +In essence, priority level activation and deactivation conceptually works like a +stack—priority levels stack up in strictly increasing fashion, and need to be +unstacked in strictly the reverse order. For interrupts, the GIC ensures this is +the case; for non-interrupts, the |EHF| monitors and asserts this. See +`Transition of priority levels`_. + +.. _interrupt-handling: + +Interrupt handling +------------------ + +The |EHF| is a client of *Interrupt Management Framework*, and registers the +top-level handler for interrupts that target EL3, as described in the +:ref:`Interrupt Management Framework` document. This has the following +implications: + +- On GICv3 systems, when executing in S-EL1, pending Non-secure interrupts of + sufficient priority are signalled as FIQs, and therefore will be routed to + EL3. As a result, S-EL1 software cannot expect to handle Non-secure + interrupts at S-EL1. Essentially, this deprecates the routing mode described + as :ref:`CSS=0, TEL3=0 `. + + In order for S-EL1 software to handle Non-secure interrupts while having + |EHF| enabled, the dispatcher must adopt a model where Non-secure interrupts + are received at EL3, but are then :ref:`synchronously ` + handled over to S-EL1. + +- On GICv2 systems, it's required that the build option ``GICV2_G0_FOR_EL3`` is + set to ``1`` so that *Group 0* interrupts target EL3. + +- While executing in Secure world, |EHF| sets GIC Priority Mask Register to the + lowest Secure priority. This means that no Non-secure interrupts can preempt + Secure execution. See `Effect on SMC calls`_ for more details. + +As mentioned above, with |EHF|, the platform is required to partition *Group 0* +interrupts into distinct priority levels. A dispatcher that chooses to receive +interrupts can then *own* one or more priority levels, and register interrupt +handlers for them. A given priority level can be assigned to only one handler. A +dispatcher may register more than one priority level. + +Dispatchers are assigned interrupt priority levels in two steps: + +.. _Partitioning priority levels: + +Partitioning priority levels +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupts are associated to dispatchers by way of grouping and assigning +interrupts to a priority level. In other words, all interrupts that are to +target a particular dispatcher should fall in a particular priority level. For +priority assignment: + +- Of the 8 bits of priority that Arm GIC architecture permits, bit 7 must be 0 + (secure space). + +- Depending on the number of dispatchers to support, the platform must choose + to use the top *n* of the 7 remaining bits to identify and assign interrupts + to individual dispatchers. Choosing *n* bits supports up to 2\ :sup:`n` + distinct dispatchers. For example, by choosing 2 additional bits (i.e., bits + 6 and 5), the platform can partition into 4 secure priority ranges: ``0x0``, + ``0x20``, ``0x40``, and ``0x60``. See `Interrupt handling example`_. + +.. note:: + + The Arm GIC architecture requires that a GIC implementation that supports two + security states must implement at least 32 priority levels; i.e., at least 5 + upper bits of the 8 bits are writeable. In the scheme described above, when + choosing *n* bits for priority range assignment, the platform must ensure + that at least ``n+1`` top bits of GIC priority are writeable. + +The priority thus assigned to an interrupt is also used to determine the +priority of delegated execution in lower ELs. Delegated execution in lower EL is +associated with a priority level chosen with ``ehf_activate_priority()`` API +(described `later`__). The chosen priority level also determines the interrupts +masked while executing in a lower EL, therefore controls preemption of delegated +execution. + +.. __: `ehf-apis`_ + +The platform expresses the chosen priority levels by declaring an array of +priority level descriptors. Each entry in the array is of type +``ehf_pri_desc_t``, and declares a priority level, and shall be populated by the +``EHF_PRI_DESC()`` macro. + +.. warning:: + + The macro ``EHF_PRI_DESC()`` installs the descriptors in the array at a + computed index, and not necessarily where the macro is placed in the array. + The size of the array might therefore be larger than what it appears to be. + The ``ARRAY_SIZE()`` macro therefore should be used to determine the size of + array. + +Finally, this array of descriptors is exposed to |EHF| via the +``EHF_REGISTER_PRIORITIES()`` macro. + +Refer to the `Interrupt handling example`_ for usage. See also: `Interrupt +Prioritisation Considerations`_. + +Programming priority +~~~~~~~~~~~~~~~~~~~~ + +The text in `Partitioning priority levels`_ only describes how the platform +expresses the required levels of priority. It however doesn't choose interrupts +nor program the required priority in GIC. + +The :ref:`Firmware Design guide` explains methods +for configuring secure interrupts. |EHF| requires the platform to enumerate +interrupt properties (as opposed to just numbers) of Secure interrupts. The +priority of secure interrupts must match that as determined in the +`Partitioning priority levels`_ section above. + +See `Limitations`_, and also refer to `Interrupt handling example`_ for +illustration. + +Registering handler +------------------- + +Dispatchers register handlers for their priority levels through the following +API: + +.. code:: c + + int ehf_register_priority_handler(int pri, ehf_handler_t handler) + +The API takes two arguments: + +- The priority level for which the handler is being registered; + +- The handler to be registered. The handler must be aligned to 4 bytes. + +If a dispatcher owns more than one priority levels, it has to call the API for +each of them. + +The API will succeed, and return ``0``, only if: + +- There exists a descriptor with the priority level requested. + +- There are no handlers already registered by a previous call to the API. + +Otherwise, the API returns ``-1``. + +The interrupt handler should have the following signature: + +.. code:: c + + typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); + +The parameters are as obtained from the top-level :ref:`EL3 interrupt handler +`. + +The :ref:`SDEI dispatcher`, for +example, expects the platform to allocate two different priority levels— +``PLAT_SDEI_CRITICAL_PRI``, and ``PLAT_SDEI_NORMAL_PRI`` —and registers the +same handler to handle both levels. + +Interrupt handling example +-------------------------- + +The following annotated snippet demonstrates how a platform might choose to +assign interrupts to fictitious dispatchers: + +.. code:: c + + #include + #include + #include + + ... + + /* + * This platform uses 2 bits for interrupt association. In total, 3 upper + * bits are in use. + * + * 7 6 5 3 0 + * .-.-.-.----------. + * |0|b|b| ..0.. | + * '-'-'-'----------' + */ + #define PLAT_PRI_BITS 2 + + /* Priorities for individual dispatchers */ + #define DISP0_PRIO 0x00 /* Not used */ + #define DISP1_PRIO 0x20 + #define DISP2_PRIO 0x40 + #define DISP3_PRIO 0x60 + + /* Install priority level descriptors for each dispatcher */ + ehf_pri_desc_t plat_exceptions[] = { + EHF_PRI_DESC(PLAT_PRI_BITS, DISP1_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP2_PRIO), + EHF_PRI_DESC(PLAT_PRI_BITS, DISP3_PRIO), + }; + + /* Expose priority descriptors to Exception Handling Framework */ + EHF_REGISTER_PRIORITIES(plat_exceptions, ARRAY_SIZE(plat_exceptions), + PLAT_PRI_BITS); + + ... + + /* List interrupt properties for GIC driver. All interrupts target EL3 */ + const interrupt_prop_t plat_interrupts[] = { + /* Dispatcher 1 owns interrupts d1_0 and d1_1, so assigns priority DISP1_PRIO */ + INTR_PROP_DESC(d1_0, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d1_1, DISP1_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 2 owns interrupts d2_0 and d2_1, so assigns priority DISP2_PRIO */ + INTR_PROP_DESC(d2_0, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d2_1, DISP2_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + + /* Dispatcher 3 owns interrupts d3_0 and d3_1, so assigns priority DISP3_PRIO */ + INTR_PROP_DESC(d3_0, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(d3_1, DISP3_PRIO, INTR_TYPE_EL3, GIC_INTR_CFG_LEVEL), + }; + + ... + + /* Dispatcher 1 registers its handler */ + ehf_register_priority_handler(DISP1_PRIO, disp1_handler); + + /* Dispatcher 2 registers its handler */ + ehf_register_priority_handler(DISP2_PRIO, disp2_handler); + + /* Dispatcher 3 registers its handler */ + ehf_register_priority_handler(DISP3_PRIO, disp3_handler); + + ... + +See also the `Build-time flow`_ and the `Run-time flow`_. + +.. _Activating and Deactivating priorities: + +Activating and Deactivating priorities +-------------------------------------- + +A priority level is said to be *active* when an exception of that priority is +being handled: for interrupts, this is implied when the interrupt is +acknowledged; for non-interrupt exceptions, such as SErrors or :ref:`SDEI +explicit dispatches `, this has to be done via +calling ``ehf_activate_priority()``. See `Run-time flow`_. + +Conversely, when the dispatcher has reached a logical resolution for the cause +of the exception, the corresponding priority level ought to be deactivated. As +above, for interrupts, this is implied when the interrupt is EOId in the GIC; +for other exceptions, this has to be done via calling +``ehf_deactivate_priority()``. + +Thanks to `different provisions`__ for exception delegation, there are +potentially more than one work flow for deactivation: + +.. __: `delegation-use-cases`_ + +.. _deactivation workflows: + +- The dispatcher has addressed the cause of the exception, and decided to take + no further action. In this case, the dispatcher's handler deactivates the + priority level before returning to the |EHF|. Runtime firmware, upon exit + through an ``ERET``, resumes execution before the interrupt occurred. + +- The dispatcher has to delegate the execution to lower ELs, and the cause of + the exception can be considered resolved only when the lower EL returns + signals complete (via an ``SMC``) at a future point in time. The following + sequence ensues: + + #. The dispatcher calls ``setjmp()`` to setup a jump point, and arranges to + enter a lower EL upon the next ``ERET``. + + #. Through the ensuing ``ERET`` from runtime firmware, execution is delegated + to a lower EL. + + #. The lower EL completes its execution, and signals completion via an + ``SMC``. + + #. The ``SMC`` is handled by the same dispatcher that handled the exception + previously. Noticing the conclusion of exception handling, the dispatcher + does ``longjmp()`` to resume beyond the previous jump point. + +As mentioned above, the |EHF| provides the following APIs for activating and +deactivating interrupt: + +.. _ehf-apis: + +- ``ehf_activate_priority()`` activates the supplied priority level, but only + if the current active priority is higher than the given one; otherwise + panics. Also, to prevent interruption by physical interrupts of lower + priority, the |EHF| programs the *Priority Mask Register* corresponding to + the PE to the priority being activated. Dispatchers typically only need to + call this when handling exceptions other than interrupts, and it needs to + delegate execution to a lower EL at a desired priority level. + +- ``ehf_deactivate_priority()`` deactivates a given priority, but only if the + current active priority is equal to the given one; otherwise panics. |EHF| + also restores the *Priority Mask Register* corresponding to the PE to the + priority before the call to ``ehf_activate_priority()``. Dispatchers + typically only need to call this after handling exceptions other than + interrupts. + +The calling of APIs are subject to allowed `transitions`__. See also the +`Run-time flow`_. + +.. __: `Transition of priority levels`_ + +Transition of priority levels +----------------------------- + +The |EHF| APIs ``ehf_activate_priority()`` and ``ehf_deactivate_priority()`` can +be called to transition the current priority level on a PE. A given sequence of +calls to these APIs are subject to the following conditions: + +- For activation, the |EHF| only allows for the priority to increase (i.e. + numeric value decreases); + +- For deactivation, the |EHF| only allows for the priority to decrease (i.e. + numeric value increases). Additionally, the priority being deactivated is + required to be the current priority. + +If these are violated, a panic will result. + +.. _Effect on SMC calls: + +Effect on SMC calls +------------------- + +In general, Secure execution is regarded as more important than Non-secure +execution. As discussed elsewhere in this document, EL3 execution, and any +delegated execution thereafter, has the effect of raising GIC's priority +mask—either implicitly by acknowledging Secure interrupts, or when dispatchers +call ``ehf_activate_priority()``. As a result, Non-secure interrupts cannot +preempt any Secure execution. + +SMCs from Non-secure world are synchronous exceptions, and are mechanisms for +Non-secure world to request Secure services. They're broadly classified as +*Fast* or *Yielding* (see `SMCCC`__). + +.. __: https://developer.arm.com/docs/den0028/latest + +- *Fast* SMCs are atomic from the caller's point of view. I.e., they return + to the caller only when the Secure world has finished serving the request. + Any Non-secure interrupts that become pending meanwhile cannot preempt Secure + execution. + +- *Yielding* SMCs carry the semantics of a preemptible, lower-priority request. + A pending Non-secure interrupt can preempt Secure execution handling a + Yielding SMC. I.e., the caller might observe a Yielding SMC returning when + either: + + #. Secure world completes the request, and the caller would find ``SMC_OK`` + as the return code. + + #. A Non-secure interrupt preempts Secure execution. Non-secure interrupt is + handled, and Non-secure execution resumes after ``SMC`` instruction. + + The dispatcher handling a Yielding SMC must provide a different return code + to the Non-secure caller to distinguish the latter case. This return code, + however, is not standardised (unlike ``SMC_UNKNOWN`` or ``SMC_OK``, for + example), so will vary across dispatchers that handle the request. + +For the latter case above, dispatchers before |EHF| expect Non-secure interrupts +to be taken to S-EL1 [#irq]_, so would get a chance to populate the designated +preempted error code before yielding to Non-secure world. + +The introduction of |EHF| changes the behaviour as described in `Interrupt +handling`_. + +When |EHF| is enabled, in order to allow Non-secure interrupts to preempt +Yielding SMC handling, the dispatcher must call ``ehf_allow_ns_preemption()`` +API. The API takes one argument, the error code to be returned to the Non-secure +world upon getting preempted. + +.. [#irq] In case of GICv2, Non-secure interrupts while in S-EL1 were signalled + as IRQs, and in case of GICv3, FIQs. + +Build-time flow +--------------- + +Please refer to the `figure`__ above. + +.. __: `ehf-figure`_ + +The build-time flow involves the following steps: + +#. Platform assigns priorities by installing priority level descriptors for + individual dispatchers, as described in `Partitioning priority levels`_. + +#. Platform provides interrupt properties to GIC driver, as described in + `Programming priority`_. + +#. Dispatcher calling ``ehf_register_priority_handler()`` to register an + interrupt handler. + +Also refer to the `Interrupt handling example`_. + +Run-time flow +------------- + +.. _interrupt-flow: + +The following is an example flow for interrupts: + +#. The GIC driver, during initialization, iterates through the platform-supplied + interrupt properties (see `Programming priority`_), and configures the + interrupts. This programs the appropriate priority and group (Group 0) on + interrupts belonging to different dispatchers. + +#. The |EHF|, during its initialisation, registers a top-level interrupt handler + with the :ref:`Interrupt Management Framework` for EL3 + interrupts. This also results in setting the routing bits in ``SCR_EL3``. + +#. When an interrupt belonging to a dispatcher fires, GIC raises an EL3/Group 0 + interrupt, and is taken to EL3. + +#. The top-level EL3 interrupt handler executes. The handler acknowledges the + interrupt, reads its *Running Priority*, and from that, determines the + dispatcher handler. + +#. The |EHF| programs the *Priority Mask Register* of the PE to the priority of + the interrupt received. + +#. The |EHF| marks that priority level *active*, and jumps to the dispatcher + handler. + +#. Once the dispatcher handler finishes its job, it has to immediately + *deactivate* the priority level before returning to the |EHF|. See + `deactivation workflows`_. + +.. _non-interrupt-flow: + +The following is an example flow for exceptions that targets EL3 other than +interrupt: + +#. The platform provides handlers for the specific kind of exception. + +#. The exception arrives, and the corresponding handler is executed. + +#. The handler calls ``ehf_activate_priority()`` to activate the required + priority level. This also has the effect of raising GIC priority mask, thus + preventing interrupts of lower priority from preempting the handling. The + handler may choose to do the handling entirely in EL3 or delegate to a lower + EL. + +#. Once exception handling concludes, the handler calls + ``ehf_deactivate_priority()`` to deactivate the priority level activated + earlier. This also has the effect of lowering GIC priority mask to what it + was before. + +Interrupt Prioritisation Considerations +--------------------------------------- + +The GIC priority scheme, by design, prioritises Secure interrupts over Normal +world ones. The platform further assigns relative priorities amongst Secure +dispatchers through |EHF|. + +As mentioned in `Partitioning priority levels`_, interrupts targeting distinct +dispatchers fall in distinct priority levels. Because they're routed via the +GIC, interrupt delivery to the PE is subject to GIC prioritisation rules. In +particular, when an interrupt is being handled by the PE (i.e., the interrupt is +in *Active* state), only interrupts of higher priority are signalled to the PE, +even if interrupts of same or lower priority are pending. This has the side +effect of one dispatcher being starved of interrupts by virtue of another +dispatcher handling its (higher priority) interrupts. + +The |EHF| doesn't enforce a particular prioritisation policy, but the platform +should carefully consider the assignment of priorities to dispatchers integrated +into runtime firmware. The platform should sensibly delineate priority to +various dispatchers according to their nature. In particular, dispatchers of +critical nature (RAS, for example) should be assigned higher priority than +others (|SDEI|, for example); and within |SDEI|, Critical priority +|SDEI| should be assigned higher priority than Normal ones. + +Limitations +----------- + +The |EHF| has the following limitations: + +- Although there could be up to 128 Secure dispatchers supported by the GIC + priority scheme, the size of descriptor array exposed with + ``EHF_REGISTER_PRIORITIES()`` macro is currently limited to 32. This serves most + expected use cases. This may be expanded in the future, should use cases + demand so. + +- The platform must ensure that the priority assigned to the dispatcher in the + exception descriptor and the programmed priority of interrupts handled by the + dispatcher match. The |EHF| cannot verify that this has been followed. + +-------------- + +*Copyright (c) 2018-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf diff --git a/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst b/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst new file mode 100644 index 0000000..047f75e --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/amu-bindings.rst @@ -0,0 +1,142 @@ +Activity Monitor Unit (AMU) Bindings +==================================== + +To support platform-defined Activity Monitor Unit (|AMU|) auxiliary counters +through FCONF, the ``HW_CONFIG`` device tree accepts several |AMU|-specific +nodes and properties. + +Bindings +^^^^^^^^ + +.. contents:: + :local: + +``/cpus/cpus/cpu*`` node properties +""""""""""""""""""""""""""""""""""" + +The ``cpu`` node has been augmented to support a handle to an associated |AMU| +view, which should describe the counters offered by the core. + ++---------------+-------+---------------+-------------------------------------+ +| Property name | Usage | Value type | Description | ++===============+=======+===============+=====================================+ +| ``amu`` | O | ```` | If present, indicates that an |AMU| | +| | | | is available and its counters are | +| | | | described by the node provided. | ++---------------+-------+---------------+-------------------------------------+ + +``/cpus/amus`` node properties +"""""""""""""""""""""""""""""" + +The ``amus`` node describes the |AMUs| implemented by the cores in the system. +This node does not have any properties. + +``/cpus/amus/amu*`` node properties +""""""""""""""""""""""""""""""""""" + +An ``amu`` node describes the layout and meaning of the auxiliary counter +registers of one or more |AMUs|, and may be shared by multiple cores. + ++--------------------+-------+------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++====================+=======+============+====================================+ +| ``#address-cells`` | R | ```` | Value shall be 1. Specifies that | +| | | | the ``reg`` property array of | +| | | | children of this node uses a | +| | | | single cell. | ++--------------------+-------+------------+------------------------------------+ +| ``#size-cells`` | R | ```` | Value shall be 0. Specifies that | +| | | | no size is required in the ``reg`` | +| | | | property in children of this node. | ++--------------------+-------+------------+------------------------------------+ + +``/cpus/amus/amu*/counter*`` node properties +"""""""""""""""""""""""""""""""""""""""""""" + +A ``counter`` node describes an auxiliary counter belonging to the parent |AMU| +view. + ++-------------------+-------+-------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++===================+=======+=============+====================================+ +| ``reg`` | R | array | Represents the counter register | +| | | | index, and must be a single cell. | ++-------------------+-------+-------------+------------------------------------+ +| ``enable-at-el3`` | O | ```` | The presence of this property | +| | | | indicates that this counter should | +| | | | be enabled prior to EL3 exit. | ++-------------------+-------+-------------+------------------------------------+ + +Example +^^^^^^^ + +An example system offering four cores made up of two clusters, where the cores +of each cluster share different |AMUs|, may use something like the following: + +.. code-block:: + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + amus { + amu0: amu-0 { + #address-cells = <1>; + #size-cells = <0>; + + counterX: counter@0 { + reg = <0>; + + enable-at-el3; + }; + + counterY: counter@1 { + reg = <1>; + + enable-at-el3; + }; + }; + + amu1: amu-1 { + #address-cells = <1>; + #size-cells = <0>; + + counterZ: counter@0 { + reg = <0>; + + enable-at-el3; + }; + }; + }; + + cpu0@00000 { + ... + + amu = <&amu0>; + }; + + cpu1@00100 { + ... + + amu = <&amu0>; + }; + + cpu2@10000 { + ... + + amu = <&amu1>; + }; + + cpu3@10100 { + ... + + amu = <&amu1>; + }; + } + +In this situation, ``cpu0`` and ``cpu1`` (the two cores in the first cluster), +share the view of their AMUs defined by ``amu0``. Likewise, ``cpu2`` and +``cpu3`` (the two cores in the second cluster), share the view of their |AMUs| +defined by ``amu1``. This will cause ``counterX`` and ``counterY`` to be enabled +for both ``cpu0`` and ``cpu1``, and ``counterZ`` to be enabled for both ``cpu2`` +and ``cpu3``. diff --git a/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst b/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst new file mode 100644 index 0000000..5c28a7a --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/fconf_properties.rst @@ -0,0 +1,32 @@ +DTB binding for FCONF properties +================================ + +This document describes the device tree format of |FCONF| properties. These +properties are not related to a specific platform and can be queried from +common code. + +Dynamic configuration +~~~~~~~~~~~~~~~~~~~~~ + +The |FCONF| framework expects a *dtb-registry* node with the following field: + +- compatible [mandatory] + - value type: + - Must be the string "fconf,dyn_cfg-dtb_registry". + +Then a list of subnodes representing a configuration |DTB|, which can be used +by |FCONF|. Each subnode should be named according to the information it +contains, and must be formed with the following fields: + +- load-address [mandatory] + - value type: + - Physical loading base address of the configuration. + +- max-size [mandatory] + - value type: + - Maximum size of the configuration. + +- id [mandatory] + - value type: + - Image ID of the configuration. + diff --git a/arm-trusted-firmware/docs/components/fconf/index.rst b/arm-trusted-firmware/docs/components/fconf/index.rst new file mode 100644 index 0000000..029f324 --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/index.rst @@ -0,0 +1,149 @@ +Firmware Configuration Framework +================================ + +This document provides an overview of the |FCONF| framework. + +Introduction +~~~~~~~~~~~~ + +The Firmware CONfiguration Framework (|FCONF|) is an abstraction layer for +platform specific data, allowing a "property" to be queried and a value +retrieved without the requesting entity knowing what backing store is being used +to hold the data. + +It is used to bridge new and old ways of providing platform-specific data. +Today, information like the Chain of Trust is held within several, nested +platform-defined tables. In the future, it may be provided as part of a device +blob, along with the rest of the information about images to load. +Introducing this abstraction layer will make migration easier and will preserve +functionality for platforms that cannot / don't want to use device tree. + +Accessing properties +~~~~~~~~~~~~~~~~~~~~ + +Properties defined in the |FCONF| are grouped around namespaces and +sub-namespaces: a.b.property. +Examples namespace can be: + +- (|TBBR|) Chain of Trust data: tbbr.cot.trusted_boot_fw_cert +- (|TBBR|) dynamic configuration info: tbbr.dyn_config.disable_auth +- Arm io policies: arm.io_policies.bl2_image +- GICv3 properties: hw_config.gicv3_config.gicr_base + +Properties can be accessed with the ``FCONF_GET_PROPERTY(a,b,property)`` macro. + +Defining properties +~~~~~~~~~~~~~~~~~~~ + +Properties composing the |FCONF| have to be stored in C structures. If +properties originate from a different backend source such as a device tree, +then the platform has to provide a ``populate()`` function which essentially +captures the property and stores them into a corresponding |FCONF| based C +structure. + +Such a ``populate()`` function is usually platform specific and is associated +with a specific backend source. For example, a populator function which +captures the hardware topology of the platform from the HW_CONFIG device tree. +Hence each ``populate()`` function must be registered with a specific +``config_type`` identifier. It broadly represents a logical grouping of +configuration properties which is usually a device tree file. + +Example: + - FW_CONFIG: properties related to base address, maximum size and image id + of other DTBs etc. + - TB_FW: properties related to trusted firmware such as IO policies, + mbedtls heap info etc. + - HW_CONFIG: properties related to hardware configuration of the SoC + such as topology, GIC controller, PSCI hooks, CPU ID etc. + +Hence the ``populate()`` callback must be registered to the (|FCONF|) framework +with the ``FCONF_REGISTER_POPULATOR()`` macro. This ensures that the function +would be called inside the generic ``fconf_populate()`` function during +initialization. + +:: + + int fconf_populate_topology(uintptr_t config) + { + /* read hw config dtb and fill soc_topology struct */ + } + + FCONF_REGISTER_POPULATOR(HW_CONFIG, topology, fconf_populate_topology); + +Then, a wrapper has to be provided to match the ``FCONF_GET_PROPERTY()`` macro: + +:: + + /* generic getter */ + #define FCONF_GET_PROPERTY(a,b,property) a##__##b##_getter(property) + + /* my specific getter */ + #define hw_config__topology_getter(prop) soc_topology.prop + +This second level wrapper can be used to remap the ``FCONF_GET_PROPERTY()`` to +anything appropriate: structure, array, function, etc.. + +To ensure a good interpretation of the properties, this documentation must +explain how the properties are described for a specific backend. Refer to the +:ref:`binding-document` section for more information and example. + +Loading the property device tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``fconf_load_config(image_id)`` must be called to load fw_config and +tb_fw_config devices tree containing the properties' values. This must be done +after the io layer is initialized, as the |DTB| is stored on an external +device (FIP). + +.. uml:: ../../resources/diagrams/plantuml/fconf_bl1_load_config.puml + +Populating the properties +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Once a valid device tree is available, the ``fconf_populate(config)`` function +can be used to fill the C data structure with the data from the config |DTB|. +This function will call all the ``populate()`` callbacks which have been +registered with ``FCONF_REGISTER_POPULATOR()`` as described above. + +.. uml:: ../../resources/diagrams/plantuml/fconf_bl2_populate.puml + +Namespace guidance +~~~~~~~~~~~~~~~~~~ + +As mentioned above, properties are logically grouped around namespaces and +sub-namespaces. The following concepts should be considered when adding new +properties/namespaces. +The framework differentiates two types of properties: + + - Properties used inside common code. + - Properties used inside platform specific code. + +The first category applies to properties being part of the firmware and shared +across multiple platforms. They should be globally accessible and defined +inside the ``lib/fconf`` directory. The namespace must be chosen to reflect the +feature/data abstracted. + +Example: + - |TBBR| related properties: tbbr.cot.bl2_id + - Dynamic configuration information: dyn_cfg.dtb_info.hw_config_id + +The second category should represent the majority of the properties defined +within the framework: Platform specific properties. They must be accessed only +within the platform API and are defined only inside the platform scope. The +namespace must contain the platform name under which the properties defined +belong. + +Example: + - Arm io framework: arm.io_policies.bl31_id + +.. _binding-document: + +Properties binding information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + fconf_properties + amu-bindings + mpmm-bindings diff --git a/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst b/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst new file mode 100644 index 0000000..d3cc857 --- /dev/null +++ b/arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst @@ -0,0 +1,48 @@ +Maximum Power Mitigation Mechanism (MPMM) Bindings +================================================== + +|MPMM| support cannot be determined at runtime by the firmware. Instead, these +DTB bindings allow the platform to communicate per-core support for |MPMM| via +the ``HW_CONFIG`` device tree blob. + +Bindings +^^^^^^^^ + +.. contents:: + :local: + +``/cpus/cpus/cpu*`` node properties +""""""""""""""""""""""""""""""""""" + +The ``cpu`` node has been augmented to allow the platform to indicate support +for |MPMM| on a given core. + ++-------------------+-------+-------------+------------------------------------+ +| Property name | Usage | Value type | Description | ++===================+=======+=============+====================================+ +| ``supports-mpmm`` | O | ```` | If present, indicates that |MPMM| | +| | | | is available on this core. | ++-------------------+-------+-------------+------------------------------------+ + +Example +^^^^^^^ + +An example system offering two cores, one with support for |MPMM| and one +without, can be described as follows: + +.. code-block:: + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0@00000 { + ... + + supports-mpmm; + }; + + cpu1@00100 { + ... + }; + } diff --git a/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst b/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst new file mode 100644 index 0000000..df2985c --- /dev/null +++ b/arm-trusted-firmware/docs/components/ffa-manifest-binding.rst @@ -0,0 +1,252 @@ +FF-A manifest binding to device tree +======================================== + +This document defines the nodes and properties used to define a partition, +according to the FF-A specification. + +Version 1.0 +----------- + +Partition Properties +^^^^^^^^^^^^^^^^^^^^ + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-X.Y" which specifies the major and + minor versions of the device tree binding for the FFA manifest represented + by this node. The minor number is incremented if the binding changes in a + backwards compatible manner. + + - X is an integer representing the major version number of this document. + - Y is an integer representing the minor version number of this document. + +- ffa-version [mandatory] + - value type: + - Must be two 16 bits values (X, Y), concatenated as 31:16 -> X, + 15:0 -> Y, where: + + - X is the major version of FF-A expected by the partition at the FFA + instance it will execute. + - Y is the minor version of FF-A expected by the partition at the FFA + instance it will execute. + +- uuid [mandatory] + - value type: + - An array consisting of 4 values, identifying the UUID of the service + implemented by this partition. The UUID format is described in RFC 4122. + +- id + - value type: + - Pre-allocated partition ID. + +- auxiliary-id + - value type: + - Pre-allocated ID that could be used in memory management transactions. + +- description + - value type: + - Name of the partition e.g. for debugging purposes. + +- execution-ctx-count [mandatory] + - value type: + - Number of vCPUs that a VM or SP wants to instantiate. + + - In the absence of virtualization, this is the number of execution + contexts that a partition implements. + - If value of this field = 1 and number of PEs > 1 then the partition is + treated as UP & migrate capable. + - If the value of this field > 1 then the partition is treated as a MP + capable partition irrespective of the number of PEs. + +- exception-level [mandatory] + - value type: + - The target exception level for the partition: + + - 0x0: EL1 + - 0x1: S_EL0 + - 0x2: S_EL1 + +- execution-state [mandatory] + - value type: + - The target execution state of the partition: + + - 0: AArch64 + - 1: AArch32 + +- load-address + - value type: + - Physical base address of the partition in memory. Absence of this field + indicates that the partition is position independent and can be loaded at + any address chosen at boot time. + +- entrypoint-offset + - value type: + - Offset from the base of the partition's binary image to the entry point of + the partition. Absence of this field indicates that the entry point is at + offset 0x0 from the base of the partition's binary. + +- xlat-granule [mandatory] + - value type: + - Translation granule used with the partition: + + - 0x0: 4k + - 0x1: 16k + - 0x2: 64k + +- boot-order + - value type: + - A unique number amongst all partitions that specifies if this partition + must be booted before others. The partition with the smaller number will be + booted first. + +- rx-tx-buffer + - value type: "memory-regions" node + - Specific "memory-regions" nodes that describe the RX/TX buffers expected + by the partition. + The "compatible" must be the string "arm,ffa-manifest-rx_tx-buffer". + +- messaging-method [mandatory] + - value type: + - Specifies which messaging methods are supported by the partition, set bit + means the feature is supported, clear bit - not supported: + + - Bit[0]: partition can receive direct requests if set + - Bit[1]: partition can send direct requests if set + - Bit[2]: partition can send and receive indirect messages + +- managed-exit + - value type: + - Specifies if managed exit is supported. + +- has-primary-scheduler + - value type: + - Presence of this field indicates that the partition implements the primary + scheduler. If so, run-time EL must be EL1. + +- run-time-model + - value type: + - Run time model that the SPM must enforce for this SP: + + - 0x0: Run to completion + - 0x1: Preemptible + +- time-slice-mem + - value type: + - Presence of this field indicates that the partition doesn't expect the + partition manager to time slice long running memory management functions. + +- gp-register-num + - value type: + - Presence of this field indicates that the partition expects the + ffa_init_info structure to be passed in via the specified general purpose + register. + The field specifies the general purpose register number but not its width. + The width is derived from the partition's execution state, as specified in + the partition properties. For example, if the number value is 1 then the + general-purpose register used will be x1 in AArch64 state and w1 in AArch32 + state. + +- stream-endpoint-ids + - value type: + - List of tuples, identifying the IDs this partition is acting as + proxy for. + +Memory Regions +-------------- + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-memory-regions". + +- description + - value type: + - Name of the memory region e.g. for debugging purposes. + +- pages-count [mandatory] + - value type: + - Count of pages of memory region as a multiple of the translation granule + size + +- attributes [mandatory] + - value type: + - Mapping modes: ORed to get required permission + + - 0x1: Read + - 0x2: Write + - 0x4: Execute + +- base-address + - value type: + - Base address of the region. The address must be aligned to the translation + granule size. + The address given may be a Physical Address (PA), Virtual Address (VA), or + Intermediate Physical Address (IPA). Refer to the FFA specification for + more information on the restrictions around the address type. + If the base address is omitted then the partition manager must map a memory + region of the specified size into the partition's translation regime and + then communicate the region properties (including the base address chosen + by the partition manager) to the partition. + +Device Regions +-------------- + +- compatible [mandatory] + - value type: + - Must be the string "arm,ffa-manifest-device-regions". + +- description + - value type: + - Name of the device region e.g. for debugging purposes. + +- reg [mandatory] + - value type: + - A (address, num-pages) pair describing the device, where: + + - address: The physical base address value of the device MMIO + region. + - num-pages: The number of pages of the region. The total size of + the region is this value multiplied by the translation granule size. + +- attributes [mandatory] + - value type: + - Mapping modes: ORed to get required permission + + - 0x1: Read + - 0x2: Write + - 0x4: Execute + +- smmu-id + - value type: + - On systems with multiple System Memory Management Units (SMMUs) this + identifier is used to inform the partition manager which SMMU the device is + upstream of. If the field is omitted then it is assumed that the device is + not upstream of any SMMU. + +- stream-ids + - value type: + - A list of (id, mem-manage) pair, where: + + - id: A unique value amongst all devices assigned to the partition. + +- interrupts [mandatory] + - value type: + - A list of (id, attributes) pair describing the device interrupts, where: + + - id: The interrupt IDs. + - attributes: A value, + containing the attributes for each interrupt ID: + + - Interrupt type: SPI, PPI, SGI + - Interrupt configuration: Edge triggered, Level triggered + - Interrupt security state: Secure, Non-secure + - Interrupt priority value + - Target execution context/vCPU for each SPI + +- exclusive-access + - value type: + - Presence of this field implies that this endpoint must be granted exclusive + access and ownership of this device's MMIO region. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/firmware-update.rst b/arm-trusted-firmware/docs/components/firmware-update.rst new file mode 100644 index 0000000..a591565 --- /dev/null +++ b/arm-trusted-firmware/docs/components/firmware-update.rst @@ -0,0 +1,400 @@ +Firmware Update (FWU) +===================== + +Introduction +------------ + +This document describes the design of the Firmware Update (FWU) feature, which +enables authenticated firmware to update firmware images from external +interfaces such as USB, UART, SD-eMMC, NAND, NOR or Ethernet to SoC Non-Volatile +memories such as NAND Flash, LPDDR2-NVM or any memory determined by the +platform. This feature functions even when the current firmware in the system +is corrupt or missing; it therefore may be used as a recovery mode. It may also +be complemented by other, higher level firmware update software. + +FWU implements a specific part of the Trusted Board Boot Requirements (TBBR) +specification, Arm DEN0006C-1. It should be used in conjunction with the +:ref:`Trusted Board Boot` design document, which describes the image +authentication parts of the Trusted Firmware-A (TF-A) TBBR implementation. + +Scope +~~~~~ + +This document describes the secure world FWU design. It is beyond its scope to +describe how normal world FWU images should operate. To implement normal world +FWU images, please refer to the "Non-Trusted Firmware Updater" requirements in +the TBBR. + +FWU Overview +------------ + +The FWU boot flow is primarily mediated by BL1. Since BL1 executes in ROM, and +it is usually desirable to minimize the amount of ROM code, the design allows +some parts of FWU to be implemented in other secure and normal world images. +Platform code may choose which parts are implemented in which images but the +general expectation is: + +- BL1 handles: + + - Detection and initiation of the FWU boot flow. + - Copying images from non-secure to secure memory + - FWU image authentication + - Context switching between the normal and secure world during the FWU + process. + +- Other secure world FWU images handle platform initialization required by + the FWU process. +- Normal world FWU images handle loading of firmware images from external + interfaces to non-secure memory. + +The primary requirements of the FWU feature are: + +#. Export a BL1 SMC interface to interoperate with other FWU images executing + at other Exception Levels. +#. Export a platform interface to provide FWU common code with the information + it needs, and to enable platform specific FWU functionality. See the + :ref:`Porting Guide` for details of this interface. + +TF-A uses abbreviated image terminology for FWU images like for other TF-A +images. See the :ref:`Image Terminology` document for an explanation of these +terms. + +The following diagram shows the FWU boot flow for Arm development platforms. +Arm CSS platforms like Juno have a System Control Processor (SCP), and these +use all defined FWU images. Other platforms may use a subset of these. + +|Flow Diagram| + +Image Identification +-------------------- + +Each FWU image and certificate is identified by a unique ID, defined by the +platform, which BL1 uses to fetch an image descriptor (``image_desc_t``) via a +call to ``bl1_plat_get_image_desc()``. The same ID is also used to prepare the +Chain of Trust (Refer to the :ref:`Authentication Framework & Chain of Trust` +document for more information). + +The image descriptor includes the following information: + +- Executable or non-executable image. This indicates whether the normal world + is permitted to request execution of a secure world FWU image (after + authentication). Secure world certificates and non-AP images are examples + of non-executable images. +- Secure or non-secure image. This indicates whether the image is + authenticated/executed in secure or non-secure memory. +- Image base address and size. +- Image entry point configuration (an ``entry_point_info_t``). +- FWU image state. + +BL1 uses the FWU image descriptors to: + +- Validate the arguments of FWU SMCs +- Manage the state of the FWU process +- Initialize the execution state of the next FWU image. + +FWU State Machine +----------------- + +BL1 maintains state for each FWU image during FWU execution. FWU images at lower +Exception Levels raise SMCs to invoke FWU functionality in BL1, which causes +BL1 to update its FWU image state. The BL1 image states and valid state +transitions are shown in the diagram below. Note that secure images have a more +complex state machine than non-secure images. + +|FWU state machine| + +The following is a brief description of the supported states: + +- RESET: This is the initial state of every image at the start of FWU. + Authentication failure also leads to this state. A secure + image may yield to this state if it has completed execution. + It can also be reached by using ``FWU_SMC_IMAGE_RESET``. + +- COPYING: This is the state of a secure image while BL1 is copying it + in blocks from non-secure to secure memory. + +- COPIED: This is the state of a secure image when BL1 has completed + copying it to secure memory. + +- AUTHENTICATED: This is the state of an image when BL1 has successfully + authenticated it. + +- EXECUTED: This is the state of a secure, executable image when BL1 has + passed execution control to it. + +- INTERRUPTED: This is the state of a secure, executable image after it has + requested BL1 to resume normal world execution. + +BL1 SMC Interface +----------------- + +BL1_SMC_CALL_COUNT +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x0 + + Return: + uint32_t + +This SMC returns the number of SMCs supported by BL1. + +BL1_SMC_UID +~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x1 + + Return: + UUID : 32 bits in each of w0-w3 (or r0-r3 for AArch32 callers) + +This SMC returns the 128-bit `Universally Unique Identifier`_ for the +BL1 SMC service. + +BL1_SMC_VERSION +~~~~~~~~~~~~~~~ + +:: + + Argument: + uint32_t function ID : 0x3 + + Return: + uint32_t : Bits [31:16] Major Version + Bits [15:0] Minor Version + +This SMC returns the current version of the BL1 SMC service. + +BL1_SMC_RUN_IMAGE +~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x4 + entry_point_info_t *ep_info + + Return: + void + + Pre-conditions: + if (normal world caller) synchronous exception + if (ep_info not EL3) synchronous exception + +This SMC passes execution control to an EL3 image described by the provided +``entry_point_info_t`` structure. In the normal TF-A boot flow, BL2 invokes +this SMC for BL1 to pass execution control to BL31. + +FWU_SMC_IMAGE_COPY +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x10 + unsigned int image_id + uintptr_t image_addr + unsigned int block_size + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id state is not (RESET or COPYING)) return -EPERM + if (secure world caller) return -EPERM + if (image_addr + block_size overflows) return -ENOMEM + if (image destination address + image_size overflows) return -ENOMEM + if (source block is in secure memory) return -ENOMEM + if (source block is not mapped into BL1) return -ENOMEM + if (image_size > free secure memory) return -ENOMEM + if (image overlaps another image) return -EPERM + +This SMC copies the secure image indicated by ``image_id`` from non-secure memory +to secure memory for later authentication. The image may be copied in a single +block or multiple blocks. In either case, the total size of the image must be +provided in ``image_size`` when invoking this SMC for the first time for each +image; it is ignored in subsequent calls (if any) for the same image. + +The ``image_addr`` and ``block_size`` specify the source memory block to copy from. +The destination address is provided by the platform code. + +If ``block_size`` is greater than the amount of remaining bytes to copy for this +image then the former is truncated to the latter. The copy operation is then +considered as complete and the FWU state machine transitions to the "COPIED" +state. If there is still more to copy, the FWU state machine stays in or +transitions to the COPYING state (depending on the previous state). + +When using multiple blocks, the source blocks do not necessarily need to be in +contiguous memory. + +Once the SMC is handled, BL1 returns from exception to the normal world caller. + +FWU_SMC_IMAGE_AUTH +~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x11 + unsigned int image_id + uintptr_t image_addr + unsigned int image_size + + Return: + int : 0 (Success) + : -ENOMEM + : -EPERM + : -EAUTH + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is not mapped into BL1) return -ENOMEM + else // normal world caller + if (image_id is secure image) + if (image_id state is not COPIED) return -EPERM + else // image_id is non-secure image + if (image_id state is not RESET) return -EPERM + if (image_addr/image_size is in secure memory) return -ENOMEM + if (image_addr/image_size not mapped into BL1) return -ENOMEM + +This SMC authenticates the image specified by ``image_id``. If the image is in the +RESET state, BL1 authenticates the image in place using the provided +``image_addr`` and ``image_size``. If the image is a secure image in the COPIED +state, BL1 authenticates the image from the secure memory that BL1 previously +copied the image into. + +BL1 returns from exception to the caller. If authentication succeeds then BL1 +sets the image state to AUTHENTICATED. If authentication fails then BL1 returns +the -EAUTH error and sets the image state back to RESET. + +FWU_SMC_IMAGE_EXECUTE +~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x12 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (image_id is invalid) return -EPERM + if (secure world caller) return -EPERM + if (image_id is non-secure image) return -EPERM + if (image_id is non-executable image) return -EPERM + if (image_id state is not AUTHENTICATED) return -EPERM + +This SMC initiates execution of a previously authenticated image specified by +``image_id``, in the other security world to the caller. The current +implementation only supports normal world callers initiating execution of a +secure world image. + +BL1 saves the normal world caller's context, sets the secure image state to +EXECUTED, and returns from exception to the secure image. + +FWU_SMC_IMAGE_RESUME +~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x13 + register_t image_param + + Return: + register_t : image_param (Success) + : -EPERM + + Pre-conditions: + if (normal world caller and no INTERRUPTED secure image) return -EPERM + +This SMC resumes execution in the other security world while there is a secure +image in the EXECUTED/INTERRUPTED state. + +For normal world callers, BL1 sets the previously interrupted secure image state +to EXECUTED. For secure world callers, BL1 sets the previously executing secure +image state to INTERRUPTED. In either case, BL1 saves the calling world's +context, restores the resuming world's context and returns from exception into +the resuming world. If the call is successful then the caller provided +``image_param`` is returned to the resumed world, otherwise an error code is +returned to the caller. + +FWU_SMC_SEC_IMAGE_DONE +~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x14 + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (normal world caller) return -EPERM + +This SMC indicates completion of a previously executing secure image. + +BL1 sets the previously executing secure image state to the RESET state, +restores the normal world context and returns from exception into the normal +world. + +FWU_SMC_UPDATE_DONE +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x15 + register_t client_cookie + + Return: + N/A + +This SMC completes the firmware update process. BL1 calls the platform specific +function ``bl1_plat_fwu_done``, passing the optional argument ``client_cookie`` as +a ``void *``. The SMC does not return. + +FWU_SMC_IMAGE_RESET +~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments: + uint32_t function ID : 0x16 + unsigned int image_id + + Return: + int : 0 (Success) + : -EPERM + + Pre-conditions: + if (secure world caller) return -EPERM + if (image in EXECUTED) return -EPERM + +This SMC sets the state of an image to RESET and zeroes the memory used by it. + +This is only allowed if the image is not being executed. + +-------------- + +*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Universally Unique Identifier: https://tools.ietf.org/rfc/rfc4122.txt +.. |Flow Diagram| image:: ../resources/diagrams/fwu_flow.png +.. |FWU state machine| image:: ../resources/diagrams/fwu_states.png diff --git a/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst b/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst new file mode 100644 index 0000000..07637dd --- /dev/null +++ b/arm-trusted-firmware/docs/components/granule-protection-tables-design.rst @@ -0,0 +1,235 @@ +Granule Protection Tables Library +================================= + +This document describes the design of the granule protection tables (GPT) +library used by Trusted Firmware-A (TF-A). This library provides the APIs needed +to initialize the GPTs based on a data structure containing information about +the systems memory layout, configure the system registers to enable granule +protection checks based on these tables, and transition granules between +different PAS (physical address spaces) at runtime. + +Arm CCA adds two new security states for a total of four: root, realm, secure, and +non-secure. In addition to new security states, corresponding physical address +spaces have been added to control memory access for each state. The PAS access +allowed to each security state can be seen in the table below. + +.. list-table:: Security states and PAS access rights + :widths: 25 25 25 25 25 + :header-rows: 1 + + * - + - Root state + - Realm state + - Secure state + - Non-secure state + * - Root PAS + - yes + - no + - no + - no + * - Realm PAS + - yes + - yes + - no + - no + * - Secure PAS + - yes + - no + - yes + - no + * - Non-secure PAS + - yes + - yes + - yes + - yes + +The GPT can function as either a 1 level or 2 level lookup depending on how a +PAS region is configured. The first step is the level 0 table, each entry in the +level 0 table controls access to a relatively large region in memory (block +descriptor), and the entire region can belong to a single PAS when a one step +mapping is used, or a level 0 entry can link to a level 1 table where relatively +small regions (granules) of memory can be assigned to different PAS with a 2 +step mapping. The type of mapping used for each PAS is determined by the user +when setting up the configuration structure. + +Design Concepts and Interfaces +------------------------------ + +This section covers some important concepts and data structures used in the GPT +library. + +There are three main parameters that determine how the tables are organized and +function: the PPS (protected physical space) which is the total amount of +protected physical address space in the system, PGS (physical granule size) +which is how large each level 1 granule is, and L0GPTSZ (level 0 GPT size) which +determines how much physical memory is governed by each level 0 entry. A granule +is the smallest unit of memory that can be independently assigned to a PAS. + +L0GPTSZ is determined by the hardware and is read from the GPCCR_EL3 register. +PPS and PGS are passed into the APIs at runtime and can be determined in +whatever way is best for a given platform, either through some algorithm or hard +coded in the firmware. + +GPT setup is split into two parts: table creation and runtime initialization. In +the table creation step, a data structure containing information about the +desired PAS regions is passed into the library which validates the mappings, +creates the tables in memory, and enables granule protection checks. In the +runtime initialization step, the runtime firmware locates the existing tables in +memory using the GPT register configuration and saves important data to a +structure used by the granule transition service which will be covered more +below. + +In the reference implementation for FVP models, you can find an example of PAS +region definitions in the file ``include/plat/arm/common/arm_pas_def.h``. Table +creation API calls can be found in ``plat/arm/common/arm_bl2_setup.c`` and +runtime initialization API calls can be seen in +``plat/arm/common/arm_bl31_setup.c``. + +Defining PAS regions +~~~~~~~~~~~~~~~~~~~~ + +A ``pas_region_t`` structure is a way to represent a physical address space and +its attributes that can be used by the GPT library to initialize the tables. + +This structure is composed of the following: + +#. The base physical address +#. The region size +#. The desired attributes of this memory region (mapping type, PAS type) + +See the ``pas_region_t`` type in ``include/lib/gpt_rme/gpt_rme.h``. + +The programmer should provide the API with an array containing ``pas_region_t`` +structures, then the library will check the desired memory access layout for +validity and create tables to implement it. + +``pas_region_t`` is a public type, however it is recommended that the macros +``GPT_MAP_REGION_BLOCK`` and ``GPT_MAP_REGION_GRANULE`` be used to populate +these structures instead of doing it manually to reduce the risk of future +compatibility issues. These macros take the base physical address, region size, +and PAS type as arguments to generate the pas_region_t structure. As the names +imply, ``GPT_MAP_REGION_BLOCK`` creates a region using only L0 mapping while +``GPT_MAP_REGION_GRANULE`` creates a region using L0 and L1 mappings. + +Level 0 and Level 1 Tables +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The GPT initialization APIs require memory to be passed in for the tables to be +constructed, ``gpt_init_l0_tables`` takes a memory address and size for building +the level 0 tables and ``gpt_init_pas_l1_tables`` takes an address and size for +building the level 1 tables which are linked from level 0 descriptors. The +tables should have PAS type ``GPT_GPI_ROOT`` and a typical system might place +its level 0 table in SRAM and its level 1 table(s) in DRAM. + +Granule Transition Service +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Granule Transition Service allows memory mapped with GPT_MAP_REGION_GRANULE +ownership to be changed using SMC calls. Non-secure granules can be transitioned +to either realm or secure space, and realm and secure granules can be +transitioned back to non-secure. This library only allows memory mapped as +granules to be transitioned, memory mapped as blocks have their GPIs fixed after +table creation. + +Library APIs +------------ + +The public APIs and types can be found in ``include/lib/gpt_rme/gpt_rme.h`` and this +section is intended to provide additional details and clarifications. + +To create the GPTs and enable granule protection checks the APIs need to be +called in the correct order and at the correct time during the system boot +process. + +#. Firmware must enable the MMU. +#. Firmware must call ``gpt_init_l0_tables`` to initialize the level 0 tables to + a default state, that is, initializing all of the L0 descriptors to allow all + accesses to all memory. The PPS is provided to this function as an argument. +#. DDR discovery and initialization by the system, the discovered DDR region(s) + are then added to the L1 PAS regions to be initialized in the next step and + used by the GTSI at runtime. +#. Firmware must call ``gpt_init_pas_l1_tables`` with a pointer to an array of + ``pas_region_t`` structures containing the desired memory access layout. The + PGS is provided to this function as an argument. +#. Firmware must call ``gpt_enable`` to enable granule protection checks by + setting the correct register values. +#. In systems that make use of the granule transition service, runtime + firmware must call ``gpt_runtime_init`` to set up the data structures needed + by the GTSI to find the tables and transition granules between PAS types. + +API Constraints +~~~~~~~~~~~~~~~ + +The values allowed by the API for PPS and PGS are enumerated types +defined in the file ``include/lib/gpt_rme/gpt_rme.h``. + +Allowable values for PPS along with their corresponding size. + +* ``GPCCR_PPS_4GB`` (4GB protected space, 0x100000000 bytes) +* ``GPCCR_PPS_64GB`` (64GB protected space, 0x1000000000 bytes) +* ``GPCCR_PPS_1TB`` (1TB protected space, 0x10000000000 bytes) +* ``GPCCR_PPS_4TB`` (4TB protected space, 0x40000000000 bytes) +* ``GPCCR_PPS_16TB`` (16TB protected space, 0x100000000000 bytes) +* ``GPCCR_PPS_256TB`` (256TB protected space, 0x1000000000000 bytes) +* ``GPCCR_PPS_4PB`` (4PB protected space, 0x10000000000000 bytes) + +Allowable values for PGS along with their corresponding size. + +* ``GPCCR_PGS_4K`` (4KB granules, 0x1000 bytes) +* ``GPCCR_PGS_16K`` (16KB granules, 0x4000 bytes) +* ``GPCCR_PGS_64K`` (64KB granules, 0x10000 bytes) + +Allowable values for L0GPTSZ along with the corresponding size. + +* ``GPCCR_L0GPTSZ_30BITS`` (1GB regions, 0x40000000 bytes) +* ``GPCCR_L0GPTSZ_34BITS`` (16GB regions, 0x400000000 bytes) +* ``GPCCR_L0GPTSZ_36BITS`` (64GB regions, 0x1000000000 bytes) +* ``GPCCR_L0GPTSZ_39BITS`` (512GB regions, 0x8000000000 bytes) + +Note that the value of the PPS, PGS, and L0GPTSZ definitions is an encoded value +corresponding to the size, not the size itself. The decoded hex representations +of the sizes have been provided for convenience. + +The L0 table memory has some constraints that must be taken into account. + +* The L0 table must be aligned to either the table size or 4096 bytes, whichever + is greater. L0 table size is the total protected space (PPS) divided by the + size of each L0 region (L0GPTSZ) multiplied by the size of each L0 descriptor + (8 bytes). ((PPS / L0GPTSZ) * 8) +* The L0 memory size must be greater than or equal to the table size. +* The L0 memory must fall within a PAS of type GPT_GPI_ROOT. + +The L1 memory also has some constraints. + +* The L1 tables must be aligned to their size. The size of each L1 table is the + size of each L0 region (L0GPTSZ) divided by the granule size (PGS) divided by + the granules controlled in each byte (2). ((L0GPTSZ / PGS) / 2) +* There must be enough L1 memory supplied to build all requested L1 tables. +* The L1 memory must fall within a PAS of type GPT_GPI_ROOT. + +If an invalid combination of parameters is supplied, the APIs will print an +error message and return a negative value. The return values of APIs should be +checked to ensure successful configuration. + +Sample Calculation for L0 memory size and alignment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let PPS=GPCCR_PPS_4GB and L0GPTSZ=GPCCR_L0GPTSZ_30BITS + +We can find the total L0 table size with ((PPS / L0GPTSZ) * 8) + +Substitute values to get this: ((0x100000000 / 0x40000000) * 8) + +And solve to get 32 bytes. In this case, 4096 is greater than 32, so the L0 +tables must be aligned to 4096 bytes. + +Sample calculation for L1 table size and alignment +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Let PGS=GPCCR_PGS_4K and L0GPTSZ=GPCCR_L0GPTSZ_30BITS + +We can find the size of each L1 table with ((L0GPTSZ / PGS) / 2). + +Substitute values: ((0x40000000 / 0x1000) / 2) + +And solve to get 0x20000 bytes per L1 table. diff --git a/arm-trusted-firmware/docs/components/index.rst b/arm-trusted-firmware/docs/components/index.rst new file mode 100644 index 0000000..95fe42c --- /dev/null +++ b/arm-trusted-firmware/docs/components/index.rst @@ -0,0 +1,28 @@ +Components +========== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + spd/index + activity-monitors + arm-sip-service + debugfs-design + exception-handling + fconf/index + firmware-update + measured_boot/index + mpmm + platform-interrupt-controller-API + ras + romlib-design + sdei + secure-partition-manager + secure-partition-manager-mm + ffa-manifest-binding + xlat-tables-lib-v2-design + cot-binding + realm-management-extension + granule-protection-tables-design diff --git a/arm-trusted-firmware/docs/components/measured_boot/event_log.rst b/arm-trusted-firmware/docs/components/measured_boot/event_log.rst new file mode 100644 index 0000000..0881248 --- /dev/null +++ b/arm-trusted-firmware/docs/components/measured_boot/event_log.rst @@ -0,0 +1,35 @@ +DTB binding for Event Log properties +==================================== + +This document describes the device tree format of Event Log properties. +These properties are not related to a specific platform and can be queried +from common code. + +Dynamic configuration for Event Log +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Measured Boot driver expects a *tpm_event_log* node with the following field +in 'tb_fw_config', 'nt_fw_config' and 'tsp_fw_config' DTS files: + +- compatible [mandatory] + - value type: + - Must be the string "arm,tpm_event_log". + +Then a list of properties representing Event Log configuration, which +can be used by Measured Boot driver. Each property is named according +to the information it contains: + +- tpm_event_log_sm_addr [fvp_nt_fw_config.dts with OP-TEE] + - value type: + - Event Log base address in secure memory. + +Note. Currently OP-TEE does not support reading DTBs from Secure memory +and this property should be removed when this feature is supported. + +- tpm_event_log_addr [mandatory] + - value type: + - Event Log base address in non-secure memory. + +- tpm_event_log_size [mandatory] + - value type: + - Event Log size. diff --git a/arm-trusted-firmware/docs/components/measured_boot/index.rst b/arm-trusted-firmware/docs/components/measured_boot/index.rst new file mode 100644 index 0000000..e7f2634 --- /dev/null +++ b/arm-trusted-firmware/docs/components/measured_boot/index.rst @@ -0,0 +1,12 @@ +Measured Boot Driver (MBD) +========================== + +.. _measured-boot-document: + +Properties binding information +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. toctree:: + :maxdepth: 1 + + event_log diff --git a/arm-trusted-firmware/docs/components/mpmm.rst b/arm-trusted-firmware/docs/components/mpmm.rst new file mode 100644 index 0000000..1b1c6d8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/mpmm.rst @@ -0,0 +1,30 @@ +Maximum Power Mitigation Mechanism (MPMM) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +|MPMM| is an optional microarchitectural power management mechanism supported by +some Arm Armv9-A cores, beginning with the Cortex-X2, Cortex-A710 and +Cortex-A510 cores. This mechanism detects and limits high-activity events to +assist in |SoC| processor power domain dynamic power budgeting and limit the +triggering of whole-rail (i.e. clock chopping) responses to overcurrent +conditions. + +|MPMM| is enabled on a per-core basis by the EL3 runtime firmware. The presence +of |MPMM| cannot be determined at runtime by the firmware, and therefore the +platform must expose this information through one of two possible mechanisms: + +- |FCONF|, controlled by the ``ENABLE_MPMM_FCONF`` build option. +- A platform implementation of the ``plat_mpmm_topology`` function (the + default). + +See :ref:`Maximum Power Mitigation Mechanism (MPMM) Bindings` for documentation +on the |FCONF| device tree bindings. + +.. warning:: + + |MPMM| exposes gear metrics through the auxiliary |AMU| counters. An + external power controller can use these metrics to budget SoC power by + limiting the number of cores that can execute higher-activity workloads or + switching to a different DVFS operating point. When this is the case, the + |AMU| counters that make up the |MPMM| gears must be enabled by the EL3 + runtime firmware - please see :ref:`Activity Monitor Auxiliary Counters` for + documentation on enabling auxiliary |AMU| counters. diff --git a/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst b/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst new file mode 100644 index 0000000..069c87b --- /dev/null +++ b/arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst @@ -0,0 +1,309 @@ +Platform Interrupt Controller API +================================= + +This document lists the optional platform interrupt controller API that +abstracts the runtime configuration and control of interrupt controller from the +generic code. The mandatory APIs are described in the +:ref:`Porting Guide `. + +Function: unsigned int plat_ic_get_running_priority(void); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This API should return the priority of the interrupt the PE is currently +servicing. This must be be called only after an interrupt has already been +acknowledged via ``plat_ic_acknowledge_interrupt``. + +In the case of Arm standard platforms using GIC, the *Running Priority Register* +is read to determine the priority of the interrupt. + +Function: int plat_ic_is_spi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Shared Peripheral Interrupt. Shared Peripheral Interrupts are typically +associated to system-wide peripherals, and these interrupts can target any PE in +the system. + +Function: int plat_ic_is_ppi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Private Peripheral Interrupt. Private Peripheral Interrupts are typically +associated with peripherals that are private to each PE. Interrupts from private +peripherals target to that PE only. + +Function: int plat_ic_is_sgi(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +The API should return whether the interrupt ID (first parameter) is categorized +as a Software Generated Interrupt. Software Generated Interrupts are raised by +explicit programming by software, and are typically used in inter-PE +communication. Secure SGIs are reserved for use by Secure world software. + +Function: unsigned int plat_ic_get_interrupt_active(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return the *active* status of the interrupt ID specified by the +first parameter, ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API reads +the GIC *Set Active Register* to read and return the active status of the +interrupt. + +Function: void plat_ic_enable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should enable the interrupt ID specified by the first parameter, +``id``. PEs in the system are expected to receive only enabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before enabling interrupt, and +then writes to GIC *Set Enable Register* to enable the interrupt. + +Function: void plat_ic_disable_interrupt(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should disable the interrupt ID specified by the first parameter, +``id``. PEs in the system are not expected to receive disabled interrupts. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Clear Enable Register* to disable the interrupt, and inserts +barrier to make memory updates visible afterwards. + +Function: void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the priority of the interrupt specified by first parameter +``id`` to the value set by the second parameter ``priority``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to GIC *Priority Register* set interrupt priority. + +Function: int plat_ic_has_interrupt_type(unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should return whether the platform supports a given interrupt type. The +parameter ``type`` shall be one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, or +``INTR_TYPE_NS``. + +In case of Arm standard platforms using GICv3, the implementation of the API +returns ``1`` for all interrupt types. + +In case of Arm standard platforms using GICv2, the API always return ``1`` for +``INTR_TYPE_NS``. Return value for other types depends on the value of build +option ``GICV2_G0_FOR_EL3``: + +- For interrupt type ``INTR_TYPE_EL3``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``0``, indicating no support + for EL3 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``1``, indicating support for + EL3 interrupts. + +- For interrupt type ``INTR_TYPE_S_EL1``: + + - When ``GICV2_G0_FOR_EL3`` is ``0``, it returns ``1``, indicating support for + Secure EL1 interrupts. + + - When ``GICV2_G0_FOR_EL3`` is ``1``, it returns ``0``, indicating no support + for Secure EL1 interrupts. + +Function: void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to the +type specified by second parameter ``type``. The ``type`` parameter can be +one of: + +- ``INTR_TYPE_NS``: interrupt is meant to be consumed by the Non-secure world. + +- ``INTR_TYPE_S_EL1``: interrupt is meant to be consumed by Secure EL1. + +- ``INTR_TYPE_EL3``: interrupt is meant to be consumed by EL3. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Group Register* and *Group Modifier Register* (only GICv3) to +assign the interrupt to the right group. + +For GICv3: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- ``INTR_TYPE_S_EL1`` maps to Secure Group 1 interrupt. + +- ``INTR_TYPE_EL3`` maps to Secure Group 0 interrupt. + +For GICv2: + +- ``INTR_TYPE_NS`` maps to Group 1 interrupt. + +- When the build option ``GICV2_G0_FOR_EL3`` is set to ``0`` (the default), + ``INTR_TYPE_S_EL1`` maps to Group 0. Otherwise, ``INTR_TYPE_EL3`` maps to + Group 0 interrupt. + +Function: void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : u_register_t + Return : void + +This API should raise an EL3 SGI. The first parameter, ``sgi_num``, specifies +the ID of the SGI. The second parameter, ``target``, must be the MPIDR of the +target PE. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before raising SGI, then writes +to appropriate *SGI Register* in order to raise the EL3 SGI. + +Function: void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, u_register_t mpidr); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Argument : unsigned int + Argument : u_register_t + Return : void + +This API should set the routing mode of Share Peripheral Interrupt (SPI) +specified by first parameter ``id`` to that specified by the second parameter +``routing_mode``. + +The ``routing_mode`` parameter can be one of: + +- ``INTR_ROUTING_MODE_ANY`` means the interrupt can be routed to any PE in the + system. The ``mpidr`` parameter is ignored in this case. + +- ``INTR_ROUTING_MODE_PE`` means the interrupt is routed to the PE whose MPIDR + value is specified by the parameter ``mpidr``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Target Register* (GICv2) or *Route Register* (GICv3) to set +the routing. + +Function: void plat_ic_set_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should set the interrupt specified by first parameter ``id`` to +*Pending*. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts barrier to make memory updates visible before setting interrupt pending, +and writes to the GIC *Set Pending Register* to set the interrupt pending +status. + +Function: void plat_ic_clear_interrupt_pending(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +This API should clear the *Pending* status of the interrupt specified by first +parameter ``id``. + +In case of Arm standard platforms using GIC, the implementation of the API +writes to the GIC *Clear Pending Register* to clear the interrupt pending +status, and inserts barrier to make memory updates visible afterwards. + +Function: unsigned int plat_ic_set_priority_mask(unsigned int id); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This API should set the priority mask (first parameter) in the interrupt +controller such that only interrupts of higher priority than the supplied one +may be signalled to the PE. The API should return the current priority value +that it's overwriting. + +In case of Arm standard platforms using GIC, the implementation of the API +inserts to order memory updates before updating mask, then writes to the GIC +*Priority Mask Register*, and make sure memory updates are visible before +potential trigger due to mask update. + +.. _plat_ic_get_interrupt_id: + +Function: unsigned int plat_ic_get_interrupt_id(unsigned int raw); [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : unsigned int + +This API should extract and return the interrupt number from the raw value +obtained by the acknowledging the interrupt (read using +``plat_ic_acknowledge_interrupt()``). If the interrupt ID is invalid, this API +should return ``INTR_ID_UNAVAILABLE``. + +In case of Arm standard platforms using GIC, the implementation of the API +masks out the interrupt ID field from the acknowledged value from GIC. + +-------------- + +*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/ras.rst b/arm-trusted-firmware/docs/components/ras.rst new file mode 100644 index 0000000..02207d8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/ras.rst @@ -0,0 +1,241 @@ +Reliability, Availability, and Serviceability (RAS) Extensions +============================================================== + +This document describes |TF-A| support for Arm Reliability, Availability, and +Serviceability (RAS) extensions. RAS is a mandatory extension for Armv8.2 and +later CPUs, and also an optional extension to the base Armv8.0 architecture. + +In conjunction with the |EHF|, support for RAS extension enables firmware-first +paradigm for handling platform errors: exceptions resulting from errors are +routed to and handled in EL3. Said errors are Synchronous External Abort (SEA), +Asynchronous External Abort (signalled as SErrors), Fault Handling and Error +Recovery interrupts. The |EHF| document mentions various :ref:`error handling +use-cases ` . + +For the description of Arm RAS extensions, Standard Error Records, and the +precise definition of RAS terminology, please refer to the Arm Architecture +Reference Manual. The rest of this document assumes familiarity with +architecture and terminology. + +Overview +-------- + +As mentioned above, the RAS support in |TF-A| enables routing to and handling of +exceptions resulting from platform errors in EL3. It allows the platform to +define an External Abort handler, and to register RAS nodes and interrupts. RAS +framework also provides `helpers`__ for accessing Standard Error Records as +introduced by the RAS extensions. + +.. __: `Standard Error Record helpers`_ + +The build option ``RAS_EXTENSION`` when set to ``1`` includes the RAS in run +time firmware; ``EL3_EXCEPTION_HANDLING`` and ``HANDLE_EA_EL3_FIRST`` must also +be set ``1``. ``RAS_TRAP_LOWER_EL_ERR_ACCESS`` controls the access to the RAS +error record registers from lower ELs. + +.. _ras-figure: + +.. image:: ../resources/diagrams/draw.io/ras.svg + +See more on `Engaging the RAS framework`_. + +Platform APIs +------------- + +The RAS framework allows the platform to define handlers for External Abort, +Uncontainable Errors, Double Fault, and errors rising from EL3 execution. Please +refer to :ref:`RAS Porting Guide `. + +Registering RAS error records +----------------------------- + +RAS nodes are components in the system capable of signalling errors to PEs +through one one of the notification mechanisms—SEAs, SErrors, or interrupts. RAS +nodes contain one or more error records, which are registers through which the +nodes advertise various properties of the signalled error. Arm recommends that +error records are implemented in the Standard Error Record format. The RAS +architecture allows for error records to be accessible via system or +memory-mapped registers. + +The platform should enumerate the error records providing for each of them: + +- A handler to probe error records for errors; +- When the probing identifies an error, a handler to handle it; +- For memory-mapped error record, its base address and size in KB; for a system + register-accessed record, the start index of the record and number of + continuous records from that index; +- Any node-specific auxiliary data. + +With this information supplied, when the run time firmware receives one of the +notification mechanisms, the RAS framework can iterate through and probe error +records for error, and invoke the appropriate handler to handle it. + +The RAS framework provides the macros to populate error record information. The +macros are versioned, and the latest version as of this writing is 1. These +macros create a structure of type ``struct err_record_info`` from its arguments, +which are later passed to probe and error handlers. + +For memory-mapped error records: + +.. code:: c + + ERR_RECORD_MEMMAP_V1(base_addr, size_num_k, probe, handler, aux) + +And, for system register ones: + +.. code:: c + + ERR_RECORD_SYSREG_V1(idx_start, num_idx, probe, handler, aux) + +The probe handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_probe_t)(const struct err_record_info *info, + int *probe_data); + +The probe handler must return a non-zero value if an error was detected, or 0 +otherwise. The ``probe_data`` output parameter can be used to pass any useful +information resulting from probe to the error handler (see `below`__). For +example, it could return the index of the record. + +.. __: `Standard Error Record helpers`_ + +The error handler must have the following prototype: + +.. code:: c + + typedef int (*err_record_handler_t)(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data); + +The ``data`` constant parameter describes the various properties of the error, +including the reason for the error, exception syndrome, and also ``flags``, +``cookie``, and ``handle`` parameters from the :ref:`top-level exception handler +`. + +The platform is expected populate an array using the macros above, and register +the it with the RAS framework using the macro ``REGISTER_ERR_RECORD_INFO()``, +passing it the name of the array describing the records. Note that the macro +must be used in the same file where the array is defined. + +Standard Error Record helpers +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TF-A| RAS framework provides probe handlers for Standard Error Records, for +both memory-mapped and System Register accesses: + +.. code:: c + + int ras_err_ser_probe_memmap(const struct err_record_info *info, + int *probe_data); + + int ras_err_ser_probe_sysreg(const struct err_record_info *info, + int *probe_data); + +When the platform enumerates error records, for those records in the Standard +Error Record format, these helpers maybe used instead of rolling out their own. +Both helpers above: + +- Return non-zero value when an error is detected in a Standard Error Record; +- Set ``probe_data`` to the index of the error record upon detecting an error. + +Registering RAS interrupts +-------------------------- + +RAS nodes can signal errors to the PE by raising Fault Handling and/or Error +Recovery interrupts. For the firmware-first handling paradigm for interrupts to +work, the platform must setup and register with |EHF|. See `Interaction with +Exception Handling Framework`_. + +For each RAS interrupt, the platform has to provide structure of type ``struct +ras_interrupt``: + +- Interrupt number; +- The associated error record information (pointer to the corresponding + ``struct err_record_info``); +- Optionally, a cookie. + +The platform is expected to define an array of ``struct ras_interrupt``, and +register it with the RAS framework using the macro +``REGISTER_RAS_INTERRUPTS()``, passing it the name of the array. Note that the +macro must be used in the same file where the array is defined. + +The array of ``struct ras_interrupt`` must be sorted in the increasing order of +interrupt number. This allows for fast look of handlers in order to service RAS +interrupts. + +Double-fault handling +--------------------- + +A Double Fault condition arises when an error is signalled to the PE while +handling of a previously signalled error is still underway. When a Double Fault +condition arises, the Arm RAS extensions only require for handler to perform +orderly shutdown of the system, as recovery may be impossible. + +The RAS extensions part of Armv8.4 introduced new architectural features to deal +with Double Fault conditions, specifically, the introduction of ``NMEA`` and +``EASE`` bits to ``SCR_EL3`` register. These were introduced to assist EL3 +software which runs part of its entry/exit routines with exceptions momentarily +masked—meaning, in such systems, External Aborts/SErrors are not immediately +handled when they occur, but only after the exceptions are unmasked again. + +|TF-A|, for legacy reasons, executes entire EL3 with all exceptions unmasked. +This means that all exceptions routed to EL3 are handled immediately. |TF-A| +thus is able to detect a Double Fault conditions in software, without needing +the intended advantages of Armv8.4 Double Fault architecture extensions. + +Double faults are fatal, and terminate at the platform double fault handler, and +doesn't return. + +Engaging the RAS framework +-------------------------- + +Enabling RAS support is a platform choice constructed from three distinct, but +related, build options: + +- ``RAS_EXTENSION=1`` includes the RAS framework in the run time firmware; + +- ``EL3_EXCEPTION_HANDLING=1`` enables handling of exceptions at EL3. See + `Interaction with Exception Handling Framework`_; + +- ``HANDLE_EA_EL3_FIRST=1`` enables routing of External Aborts and SErrors to + EL3. + +The RAS support in |TF-A| introduces a default implementation of +``plat_ea_handler``, the External Abort handler in EL3. When ``RAS_EXTENSION`` +is set to ``1``, it'll first call ``ras_ea_handler()`` function, which is the +top-level RAS exception handler. ``ras_ea_handler`` is responsible for iterating +to through platform-supplied error records, probe them, and when an error is +identified, look up and invoke the corresponding error handler. + +Note that, if the platform chooses to override the ``plat_ea_handler`` function +and intend to use the RAS framework, it must explicitly call +``ras_ea_handler()`` from within. + +Similarly, for RAS interrupts, the framework defines +``ras_interrupt_handler()``. The RAS framework arranges for it to be invoked +when a RAS interrupt taken at EL3. The function bisects the platform-supplied +sorted array of interrupts to look up the error record information associated +with the interrupt number. That error handler for that record is then invoked to +handle the error. + +Interaction with Exception Handling Framework +--------------------------------------------- + +As mentioned in earlier sections, RAS framework interacts with the |EHF| to +arbitrate handling of RAS exceptions with others that are routed to EL3. This +means that the platform must partition a :ref:`priority level ` for handling RAS exceptions. The platform must then define +the macro ``PLAT_RAS_PRI`` to the priority level used for RAS exceptions. +Platforms would typically want to allocate the highest secure priority for +RAS handling. + +Handling of both :ref:`interrupt ` and :ref:`non-interrupt +` exceptions follow the sequences outlined in the |EHF| +documentation. I.e., for interrupts, the priority management is implicit; but +for non-interrupt exceptions, they're explicit using :ref:`EHF APIs +`. + +-------------- + +*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/realm-management-extension.rst b/arm-trusted-firmware/docs/components/realm-management-extension.rst new file mode 100644 index 0000000..5fa5140 --- /dev/null +++ b/arm-trusted-firmware/docs/components/realm-management-extension.rst @@ -0,0 +1,267 @@ + +Realm Management Extension (RME) +==================================== + +FEAT_RME (or RME for short) is an Armv9-A extension and is one component of the +`Arm Confidential Compute Architecture (Arm CCA)`_. TF-A supports RME starting +from version 2.6. This chapter discusses the changes to TF-A to support RME and +provides instructions on how to build and run TF-A with RME. + +RME support in TF-A +--------------------- + +The following diagram shows an Arm CCA software architecture with TF-A as the +EL3 firmware. In the Arm CCA architecture there are two additional security +states and address spaces: ``Root`` and ``Realm``. TF-A firmware runs in the +Root world. In the realm world, a Realm Management Monitor firmware (RMM) +manages the execution of Realm VMs and their interaction with the hypervisor. + +.. image:: ../resources/diagrams/arm-cca-software-arch.png + +RME is the hardware extension to support Arm CCA. To support RME, various +changes have been introduced to TF-A. We discuss those changes below. + +Changes to translation tables library +*************************************** +RME adds Root and Realm Physical address spaces. To support this, two new +memory type macros, ``MT_ROOT`` and ``MT_REALM``, have been added to the +:ref:`Translation (XLAT) Tables Library`. These macros are used to configure +memory regions as Root or Realm respectively. + +.. note:: + + Only version 2 of the translation tables library supports the new memory + types. + +Changes to context management +******************************* +A new CPU context for the Realm world has been added. The existing +:ref:`CPU context management API` can be used to manage Realm context. + +Boot flow changes +******************* +In a typical TF-A boot flow, BL2 runs at Secure-EL1. However when RME is +enabled, TF-A runs in the Root world at EL3. Therefore, the boot flow is +modified to run BL2 at EL3 when RME is enabled. In addition to this, a +Realm-world firmware (RMM) is loaded by BL2 in the Realm physical address +space. + +The boot flow when RME is enabled looks like the following: + +1. BL1 loads and executes BL2 at EL3 +2. BL2 loads images including RMM +3. BL2 transfers control to BL31 +4. BL31 initializes SPM (if SPM is enabled) +5. BL31 initializes RMM +6. BL31 transfers control to Normal-world software + +Granule Protection Tables (GPT) library +***************************************** +Isolation between the four physical address spaces is enforced by a process +called Granule Protection Check (GPC) performed by the MMU downstream any +address translation. GPC makes use of Granule Protection Table (GPT) in the +Root world that describes the physical address space assignment of every +page (granule). A GPT library that provides APIs to initialize GPTs and to +transition granules between different physical address spaces has been added. +More information about the GPT library can be found in the +:ref:`Granule Protection Tables Library` chapter. + +RMM Dispatcher (RMMD) +************************ +RMMD is a new standard runtime service that handles the switch to the Realm +world. It initializes the RMM and handles Realm Management Interface (RMI) +SMC calls from Non-secure and Realm worlds. + +Test Realm Payload (TRP) +************************* +TRP is a small test payload that runs at R-EL2 and implements a subset of +the Realm Management Interface (RMI) commands to primarily test EL3 firmware +and the interface between R-EL2 and EL3. When building TF-A with RME enabled, +if a path to an RMM image is not provided, TF-A builds the TRP by default +and uses it as RMM image. + +Building and running TF-A with RME +------------------------------------ + +This section describes how you can build and run TF-A with RME enabled. +We assume you have all the :ref:`Prerequisites` to build TF-A. + +To enable RME, you need to set the ENABLE_RME build flag when building +TF-A. Currently, this feature is only supported for the FVP platform. + +The following instructions show you how to build and run TF-A with RME +for two scenarios: TF-A with TF-A Tests, and four-world execution with +Hafnium and TF-A Tests. The instructions assume you have already obtained +TF-A. You can use the following command to clone TF-A. + +.. code:: shell + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + +To run the tests, you need an FVP model. Please use the :ref:`latest version +` of *FVP_Base_RevC-2xAEMvA* model. + +.. note:: + + ENABLE_RME build option is currently experimental. + +Building TF-A with TF-A Tests +******************************************** +Use the following instructions to build TF-A with `TF-A Tests`_ as the +non-secure payload (BL33). + +**1. Obtain and build TF-A Tests** + +.. code:: shell + + git clone https://git.trustedfirmware.org/TF-A/tf-a-tests.git + cd tf-a-tests + make CROSS_COMPILE=aarch64-none-elf- PLAT=fvp DEBUG=1 + +This produces a TF-A Tests binary (*tftf.bin*) in the *build/fvp/debug* directory. + +**2. Build TF-A** + +.. code:: shell + + cd trusted-firmware-a + make CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + ENABLE_RME=1 \ + FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \ + DEBUG=1 \ + BL33= \ + all fip + +This produces *bl1.bin* and *fip.bin* binaries in the *build/fvp/debug* directory. +The above command also builds TRP. The TRP binary is packaged in *fip.bin*. + +Four-world execution with Hafnium and TF-A Tests +**************************************************** +Four-world execution involves software components at each security state: root, +secure, realm and non-secure. This section describes how to build TF-A +with four-world support. We use TF-A as the root firmware, `Hafnium`_ as the +secure component, TRP as the realm-world firmware and TF-A Tests as the +non-secure payload. + +Before building TF-A, you first need to build the other software components. +You can find instructions on how to get and build TF-A Tests above. + +**1. Obtain and build Hafnium** + +.. code:: shell + + git clone --recurse-submodules https://git.trustedfirmware.org/hafnium/hafnium.git + cd hafnium + # Use the default prebuilt LLVM/clang toolchain + PATH=$PWD/prebuilts/linux-x64/clang/bin:$PWD/prebuilts/linux-x64/dtc:$PATH + make PROJECT=reference + +The Hafnium binary should be located at +*out/reference/secure_aem_v8a_fvp_clang/hafnium.bin* + +**2. Build TF-A** + +Build TF-A with RME as well as SPM enabled. + +.. code:: shell + + make CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + ENABLE_RME=1 \ + FVP_HW_CONFIG_DTS=fdts/fvp-base-gicv3-psci-1t.dts \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=1 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + DEBUG=1 \ + SP_LAYOUT_FILE=/build/fvp/debug/sp_layout.json> \ + BL32= \ + BL33= \ + all fip + +Running the tests +********************* +Use the following command to run the tests on FVP. TF-A Tests should boot +and run the default tests including RME tests. + +.. code:: shell + + FVP_Base_RevC-2xAEMvA \ + -C bp.flashloader0.fname= \ + -C bp.secureflashloader.fname= \ + -C bp.refcounter.non_arch_start_at_default=1 \ + -C bp.refcounter.use_real_time=0 \ + -C bp.ve_sysregs.exit_on_shutdown=1 \ + -C cache_state_modelled=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster0.PA_SIZE=48 \ + -C cluster0.ecv_support_level=2 \ + -C cluster0.gicv3.cpuintf-mmap-access-level=2 \ + -C cluster0.gicv3.without-DS-support=1 \ + -C cluster0.gicv4.mask-virtual-interrupt=1 \ + -C cluster0.has_arm_v8-6=1 \ + -C cluster0.has_branch_target_exception=1 \ + -C cluster0.has_rme=1 \ + -C cluster0.has_rndr=1 \ + -C cluster0.has_amu=1 \ + -C cluster0.has_v8_7_pmu_extension=2 \ + -C cluster0.max_32bit_el=-1 \ + -C cluster0.restriction_on_speculative_execution=2 \ + -C cluster0.restriction_on_speculative_execution_aarch32=2 \ + -C cluster1.NUM_CORES=4 \ + -C cluster1.PA_SIZE=48 \ + -C cluster1.ecv_support_level=2 \ + -C cluster1.gicv3.cpuintf-mmap-access-level=2 \ + -C cluster1.gicv3.without-DS-support=1 \ + -C cluster1.gicv4.mask-virtual-interrupt=1 \ + -C cluster1.has_arm_v8-6=1 \ + -C cluster1.has_branch_target_exception=1 \ + -C cluster1.has_rme=1 \ + -C cluster1.has_rndr=1 \ + -C cluster1.has_amu=1 \ + -C cluster1.has_v8_7_pmu_extension=2 \ + -C cluster1.max_32bit_el=-1 \ + -C cluster1.restriction_on_speculative_execution=2 \ + -C cluster1.restriction_on_speculative_execution_aarch32=2 \ + -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B \ + -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0475 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \ + -C bp.pl011_uart0.out_file=uart0.log \ + -C bp.pl011_uart1.out_file=uart1.log \ + -C bp.pl011_uart2.out_file=uart2.log \ + -C pctl.startup=0.0.0.0 \ + -Q 1000 \ + "$@" + +The bottom of the output from *uart0* should look something like the following. + +.. code-block:: shell + + ... + + > Test suite 'FF-A Interrupt' + Passed + > Test suite 'SMMUv3 tests' + Passed + > Test suite 'PMU Leakage' + Passed + > Test suite 'DebugFS' + Passed + > Test suite 'Realm payload tests' + Passed + > Test suite 'Invalid memory access' + Passed + ... + + +.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture +.. _Arm Architecture Models website: https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models +.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io/en/latest +.. _Hafnium: https://www.trustedfirmware.org/projects/hafnium diff --git a/arm-trusted-firmware/docs/components/romlib-design.rst b/arm-trusted-firmware/docs/components/romlib-design.rst new file mode 100644 index 0000000..d34b3cc --- /dev/null +++ b/arm-trusted-firmware/docs/components/romlib-design.rst @@ -0,0 +1,155 @@ +Library at ROM +============== + +This document provides an overview of the "library at ROM" implementation in +Trusted Firmware-A (TF-A). + +Introduction +~~~~~~~~~~~~ + +The "library at ROM" feature allows platforms to build a library of functions to +be placed in ROM. This reduces SRAM usage by utilising the available space in +ROM. The "library at ROM" contains a jump table with the list of functions that +are placed in ROM. The capabilities of the "library at ROM" are: + +1. Functions can be from one or several libraries. + +2. Functions can be patched after they have been programmed into ROM. + +3. Platform-specific libraries can be placed in ROM. + +4. Functions can be accessed by one or more BL images. + +Index file +~~~~~~~~~~ + +.. image:: ../resources/diagrams/romlib_design.png + :width: 600 + +Library at ROM is described by an index file with the list of functions to be +placed in ROM. The index file is platform specific and its format is: + +:: + + lib function [patch] + + lib -- Name of the library the function belongs to + function -- Name of the function to be placed in library at ROM + [patch] -- Option to patch the function + +It is also possible to insert reserved spaces in the list by using the keyword +"reserved" rather than the "lib" and "function" names as shown below: + +:: + + reserved + +The reserved spaces can be used to add more functions in the future without +affecting the order and location of functions already existing in the jump +table. Also, for additional flexibility and modularity, the index file can +include other index files. + +For an index file example, refer to ``lib/romlib/jmptbl.i``. + +Wrapper functions +~~~~~~~~~~~~~~~~~ + +.. image:: ../resources/diagrams/romlib_wrapper.png + :width: 600 + +When invoking a function of the "library at ROM", the calling sequence is as +follows: + +BL image --> wrapper function --> jump table entry --> library at ROM + +The index file is used to create a jump table which is placed in ROM. Then, the +wrappers refer to the jump table to call the "library at ROM" functions. The +wrappers essentially contain a branch instruction to the jump table entry +corresponding to the original function. Finally, the original function in the BL +image(s) is replaced with the wrapper function. + +The "library at ROM" contains a necessary init function that initialises the +global variables defined by the functions inside "library at ROM". + +Script +~~~~~~ + +There is a ``romlib_generate.py`` Python script that generates the necessary +files for the "library at ROM" to work. It implements multiple functions: + +1. ``romlib_generate.py gentbl [args]`` - Generates the jump table by parsing + the index file. + +2. ``romlib_generator.py genvar [args]`` - Generates the jump table global + variable (**not** the jump table itself) with the absolute address in ROM. + This global variable is, basically, a pointer to the jump table. + +3. ``romlib_generator.py genwrappers [args]`` - Generates a wrapper function for + each entry in the index file except for the ones that contain the keyword + ``patch``. The generated wrapper file is called ``.s``. + +4. ``romlib_generator.py pre [args]`` - Preprocesses the index file which means + it resolves all the include commands in the file recursively. It can also + generate a dependency file of the included index files which can be directly + used in makefiles. + +Each ``romlib_generate.py`` function has its own manual which is accessible by +runing ``romlib_generator.py [function] --help``. + +``romlib_generate.py`` requires Python 3 environment. + + +Patching of functions in library at ROM +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``romlib_generator.py genwrappers`` does not generate wrappers for the +entries in the index file that contain the keyword ``patch``. Thus, it allows +calling the function from the actual library by breaking the link to the +"library at ROM" version of this function. + +The calling sequence for a patched function is as follows: + +BL image --> function + +Memory impact +~~~~~~~~~~~~~ + +Using library at ROM will modify the memory layout of the BL images: + +- The ROM library needs a page aligned RAM section to hold the RW data. This + section is defined by the ROMLIB_RW_BASE and ROMLIB_RW_END macros. + On Arm platforms a section of 1 page (0x1000) is allocated at the top of SRAM. + This will have for effect to shift down all the BL images by 1 page. + +- Depending on the functions moved to the ROM library, the size of the BL images + will be reduced. + For example: moving MbedTLS function into the ROM library reduces BL1 and + BL2, but not BL31. + +- This change in BL images size can be taken into consideration to optimize the + memory layout when defining the BLx_BASE macros. + +Build library at ROM +~~~~~~~~~~~~~~~~~~~~~ + +The environment variable ``CROSS_COMPILE`` must be set appropriately. Refer to +:ref:`Performing an Initial Build` for more information about setting this +variable. + +In the below example the usage of ROMLIB together with mbed TLS is demonstrated +to showcase the benefits of library at ROM - it's not mandatory. + +.. code:: shell + + make PLAT=fvp \ + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33= \ + USE_ROMLIB=1 \ + all fip + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/sdei.rst b/arm-trusted-firmware/docs/components/sdei.rst new file mode 100644 index 0000000..60259c8 --- /dev/null +++ b/arm-trusted-firmware/docs/components/sdei.rst @@ -0,0 +1,369 @@ +SDEI: Software Delegated Exception Interface +============================================ + +This document provides an overview of the SDEI dispatcher implementation in +Trusted Firmware-A (TF-A). + +Introduction +------------ + +Software Delegated Exception Interface (|SDEI|) is an Arm specification for +Non-secure world to register handlers with firmware to receive notifications +about system events. Firmware will first receive the system events by way of +asynchronous exceptions and, in response, arranges for the registered handler to +execute in the Non-secure EL. + +Normal world software that interacts with the SDEI dispatcher (makes SDEI +requests and receives notifications) is referred to as the *SDEI Client*. A +client receives the event notification at the registered handler even when it +was executing with exceptions masked. The list of SDEI events available to the +client are specific to the platform [#std-event]_. See also `Determining client +EL`_. + +.. _general SDEI dispatch: + +The following figure depicts a general sequence involving SDEI client executing +at EL2 and an event dispatch resulting from the triggering of a bound interrupt. +A commentary is provided below: + +.. uml:: ../resources/diagrams/plantuml/sdei_general.puml + +As part of initialisation, the SDEI client binds a Non-secure interrupt [1], and +the SDEI dispatcher returns a platform dynamic event number [2]. The client then +registers a handler for that event [3], enables the event [5], and unmasks all +events on the current PE [7]. This sequence is typical of an SDEI client, but it +may involve additional SDEI calls. + +At a later point in time, when the bound interrupt triggers [9], it's trapped to +EL3. The interrupt is handed over to the SDEI dispatcher, which then arranges to +execute the registered handler [10]. The client terminates its execution with +``SDEI_EVENT_COMPLETE`` [11], following which the dispatcher resumes the +original EL2 execution [13]. Note that the SDEI interrupt remains active until +the client handler completes, at which point EL3 does EOI [12]. + +Other than events bound to interrupts, as depicted in the sequence above, SDEI +events can be explicitly dispatched in response to other exceptions, for +example, upon receiving an *SError* or *Synchronous External Abort*. See +`Explicit dispatch of events`_. + +The remainder of this document only discusses the design and implementation of +SDEI dispatcher in TF-A, and assumes that the reader is familiar with the SDEI +specification, the interfaces, and their requirements. + +Defining events +--------------- + +A platform choosing to include the SDEI dispatcher must also define the events +available on the platform, along with their attributes. + +The platform is expected to provide two arrays of event descriptors: one for +private events, and another for shared events. The SDEI dispatcher provides +``SDEI_PRIVATE_EVENT()`` and ``SDEI_SHARED_EVENT()`` macros to populate the +event descriptors. Both macros take 3 arguments: + +- The event number: this must be a positive 32-bit integer. + +- For an event that has a backing interrupt, the interrupt number the event is + bound to: + + - If it's not applicable to an event, this shall be left as ``0``. + + - If the event is dynamic, this should be specified as ``SDEI_DYN_IRQ``. + +- A bit map of `Event flags`_. + +To define event 0, the macro ``SDEI_DEFINE_EVENT_0()`` should be used. This +macro takes only one parameter: an SGI number to signal other PEs. + +To define an event that's meant to be explicitly dispatched (i.e., not as a +result of receiving an SDEI interrupt), the macro ``SDEI_EXPLICIT_EVENT()`` +should be used. It accepts two parameters: + +- The event number (as above); + +- Event priority: ``SDEI_MAPF_CRITICAL`` or ``SDEI_MAPF_NORMAL``, as described + below. + +Once the event descriptor arrays are defined, they should be exported to the +SDEI dispatcher using the ``REGISTER_SDEI_MAP()`` macro, passing it the pointers +to the private and shared event descriptor arrays, respectively. Note that the +``REGISTER_SDEI_MAP()`` macro must be used in the same file where the arrays are +defined. + +Regarding event descriptors: + +- For Event 0: + + - There must be exactly one descriptor in the private array, and none in the + shared array. + + - The event should be defined using ``SDEI_DEFINE_EVENT_0()``. + + - Must be bound to a Secure SGI on the platform. + +- Explicit events should only be used in the private array. + +- Statically bound shared and private interrupts must be bound to shared and + private interrupts on the platform, respectively. See the section on + `Configuration within Exception Handling Framework`_. + +- Both arrays should be one-dimensional. The ``REGISTER_SDEI_MAP()`` macro + takes care of replicating private events for each PE on the platform. + +- Both arrays must be sorted in the increasing order of event number. + +The SDEI specification doesn't have provisions for discovery of available events +on the platform. The list of events made available to the client, along with +their semantics, have to be communicated out of band; for example, through +Device Trees or firmware configuration tables. + +See also `Event definition example`_. + +Event flags +~~~~~~~~~~~ + +Event flags describe the properties of the event. They are bit maps that can be +``OR``\ ed to form parameters to macros that define events (see +`Defining events`_). + +- ``SDEI_MAPF_DYNAMIC``: Marks the event as dynamic. Dynamic events can be + bound to (or released from) any Non-secure interrupt at runtime via the + ``SDEI_INTERRUPT_BIND`` and ``SDEI_INTERRUPT_RELEASE`` calls. + +- ``SDEI_MAPF_BOUND``: Marks the event as statically bound to an interrupt. + These events cannot be re-bound at runtime. + +- ``SDEI_MAPF_NORMAL``: Marks the event as having *Normal* priority. This is + the default priority. + +- ``SDEI_MAPF_CRITICAL``: Marks the event as having *Critical* priority. + +Event definition example +------------------------ + +.. code:: c + + static sdei_ev_map_t plat_private_sdei[] = { + /* Event 0 definition */ + SDEI_DEFINE_EVENT_0(8), + + /* PPI */ + SDEI_PRIVATE_EVENT(8, 23, SDEI_MAPF_BOUND), + + /* Dynamic private events */ + SDEI_PRIVATE_EVENT(100, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_PRIVATE_EVENT(101, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + + /* Events for explicit dispatch */ + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_NORMAL); + SDEI_EXPLICIT_EVENT(2000, SDEI_MAPF_CRITICAL); + }; + + /* Shared event mappings */ + static sdei_ev_map_t plat_shared_sdei[] = { + SDEI_SHARED_EVENT(804, 0, SDEI_MAPF_DYNAMIC), + + /* Dynamic shared events */ + SDEI_SHARED_EVENT(3000, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), + SDEI_SHARED_EVENT(3001, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + }; + + /* Export SDEI events */ + REGISTER_SDEI_MAP(plat_private_sdei, plat_shared_sdei); + +Configuration within Exception Handling Framework +------------------------------------------------- + +The SDEI dispatcher functions alongside the Exception Handling Framework. This +means that the platform must assign priorities to both Normal and Critical SDEI +interrupts for the platform: + +- Install priority descriptors for Normal and Critical SDEI interrupts. + +- For those interrupts that are statically bound (i.e. events defined as having + the ``SDEI_MAPF_BOUND`` property), enumerate their properties for the GIC + driver to configure interrupts accordingly. + + The interrupts must be configured to target EL3. This means that they should + be configured as *Group 0*. Additionally, on GICv2 systems, the build option + ``GICV2_G0_FOR_EL3`` must be set to ``1``. + +See also :ref:`porting_guide_sdei_requirements`. + +Determining client EL +--------------------- + +The SDEI specification requires that the *physical* SDEI client executes in the +highest Non-secure EL implemented on the system. This means that the dispatcher +will only allow SDEI calls to be made from: + +- EL2, if EL2 is implemented. The Hypervisor is expected to implement a + *virtual* SDEI dispatcher to support SDEI clients in Guest Operating Systems + executing in Non-secure EL1. + +- Non-secure EL1, if EL2 is not implemented or disabled. + +See the function ``sdei_client_el()`` in ``sdei_private.h``. + +.. _explicit-dispatch-of-events: + +Explicit dispatch of events +--------------------------- + +Typically, an SDEI event dispatch is caused by the PE receiving interrupts that +are bound to an SDEI event. However, there are cases where the Secure world +requires dispatch of an SDEI event as a direct or indirect result of a past +activity, such as receiving a Secure interrupt or an exception. + +The SDEI dispatcher implementation provides ``sdei_dispatch_event()`` API for +this purpose. The API has the following signature: + +.. code:: c + + int sdei_dispatch_event(int ev_num); + +The parameter ``ev_num`` is the event number to dispatch. The API returns ``0`` +on success, or ``-1`` on failure. + +The following figure depicts a scenario involving explicit dispatch of SDEI +event. A commentary is provided below: + +.. uml:: ../resources/diagrams/plantuml/sdei_explicit_dispatch.puml + +As part of initialisation, the SDEI client registers a handler for a platform +event [1], enables the event [3], and unmasks the current PE [5]. Note that, +unlike in `general SDEI dispatch`_, this doesn't involve interrupt binding, as +bound or dynamic events can't be explicitly dispatched (see the section below). + +At a later point in time, a critical event [#critical-event]_ is trapped into +EL3 [7]. EL3 performs a first-level triage of the event, and a RAS component +assumes further handling [8]. The dispatch completes, but intends to involve +Non-secure world in further handling, and therefore decides to explicitly +dispatch an event [10] (which the client had already registered for [1]). The +rest of the sequence is similar to that in the `general SDEI dispatch`_: the +requested event is dispatched to the client (assuming all the conditions are +met), and when the handler completes, the preempted execution resumes. + +Conditions for event dispatch +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +All of the following requirements must be met for the API to return ``0`` and +event to be dispatched: + +- SDEI events must be unmasked on the PE. I.e. the client must have called + ``PE_UNMASK`` beforehand. + +- Event 0 can't be dispatched. + +- The event must be declared using the ``SDEI_EXPLICIT_EVENT()`` macro + described above. + +- The event must be private to the PE. + +- The event must have been registered for and enabled. + +- A dispatch for the same event must not be outstanding. I.e. it hasn't already + been dispatched and is yet to be completed. + +- The priority of the event (either Critical or Normal, as configured by the + platform at build-time) shouldn't cause priority inversion. This means: + + - If it's of Normal priority, neither Normal nor Critical priority dispatch + must be outstanding on the PE. + + - If it's of a Critical priority, no Critical priority dispatch must be + outstanding on the PE. + +Further, the caller should be aware of the following assumptions made by the +dispatcher: + +- The caller of the API is a component running in EL3; for example, a RAS + driver. + +- The requested dispatch will be permitted by the Exception Handling Framework. + I.e. the caller must make sure that the requested dispatch has sufficient + priority so as not to cause priority level inversion within Exception + Handling Framework. + +- The caller must be prepared for the SDEI dispatcher to restore the Non-secure + context, and mark that the active context. + +- The call will block until the SDEI client completes the event (i.e. when the + client calls either ``SDEI_EVENT_COMPLETE`` or ``SDEI_COMPLETE_AND_RESUME``). + +- The caller must be prepared for this API to return failure and handle + accordingly. + +Porting requirements +-------------------- + +The porting requirements of the SDEI dispatcher are outlined in the +:ref:`Porting Guide `. + +Note on writing SDEI event handlers +----------------------------------- + +*This section pertains to SDEI event handlers in general, not just when using +the TF-A SDEI dispatcher.* + +The SDEI specification requires that event handlers preserve the contents of all +registers except ``x0`` to ``x17``. This has significance if event handler is +written in C: compilers typically adjust the stack frame at the beginning and +end of C functions. For example, AArch64 GCC typically produces the following +function prologue and epilogue: + +:: + + c_event_handler: + stp x29, x30, [sp,#-32]! + mov x29, sp + + ... + + bl ... + + ... + + ldp x29, x30, [sp],#32 + ret + +The register ``x29`` is used as frame pointer in the prologue. Because neither a +valid ``SDEI_EVENT_COMPLETE`` nor ``SDEI_EVENT_COMPLETE_AND_RESUME`` calls +return to the handler, the epilogue never gets executed, and registers ``x29`` +and ``x30`` (in the case above) are inadvertently corrupted. This violates the +SDEI specification, and the normal execution thereafter will result in +unexpected behaviour. + +To work this around, it's advised that the top-level event handlers are +implemented in assembly, following a similar pattern as below: + +:: + + asm_event_handler: + /* Save link register whilst maintaining stack alignment */ + stp xzr, x30, [sp, #-16]! + bl c_event_handler + + /* Restore link register */ + ldp xzr, x30, [sp], #16 + + /* Complete call */ + ldr x0, =SDEI_EVENT_COMPLETE + smc #0 + b . + +-------------- + +*Copyright (c) 2017-2019, Arm Limited and Contributors. All rights reserved.* + +.. rubric:: Footnotes + +.. [#std-event] Except event 0, which is defined by the SDEI specification as a + standard event. + +.. [#critical-event] Examples of critical events are *SError*, *Synchronous + External Abort*, *Fault Handling interrupt* or *Error + Recovery interrupt* from one of RAS nodes in the system. + +.. _SDEI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Software Delegated Exception Interface: `SDEI specification`_ diff --git a/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst b/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst new file mode 100644 index 0000000..4cdb96c --- /dev/null +++ b/arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst @@ -0,0 +1,834 @@ +Secure Partition Manager (MM) +***************************** + +Foreword +======== + +Two implementations of a Secure Partition Manager co-exist in the TF-A codebase: + +- SPM based on the FF-A specification (:ref:`Secure Partition Manager`). +- SPM based on the MM interface. + +Both implementations differ in their architectures and only one can be selected +at build time. + +This document describes the latter implementation where the Secure Partition Manager +resides at EL3 and management services run from isolated Secure Partitions at S-EL0. +The communication protocol is established through the Management Mode (MM) interface. + +Background +========== + +In some market segments that primarily deal with client-side devices like mobile +phones, tablets, STBs and embedded devices, a Trusted OS instantiates trusted +applications to provide security services like DRM, secure payment and +authentication. The Global Platform TEE Client API specification defines the API +used by Non-secure world applications to access these services. A Trusted OS +fulfils the requirements of a security service as described above. + +Management services are typically implemented at the highest level of privilege +in the system, i.e. EL3 in Trusted Firmware-A (TF-A). The service requirements are +fulfilled by the execution environment provided by TF-A. + +The following diagram illustrates the corresponding software stack: + +|Image 1| + +In other market segments that primarily deal with server-side devices (e.g. data +centres and enterprise servers) the secure software stack typically does not +include a Global Platform Trusted OS. Security functions are accessed through +other interfaces (e.g. ACPI TCG TPM interface, UEFI runtime variable service). + +Placement of management and security functions with diverse requirements in a +privileged Exception Level (i.e. EL3 or S-EL1) makes security auditing of +firmware more difficult and does not allow isolation of unrelated services from +each other either. + +Introduction +============ + +A **Secure Partition** is a software execution environment instantiated in +S-EL0 that can be used to implement simple management and security services. +Since S-EL0 is an unprivileged Exception Level, a Secure Partition relies on +privileged firmware (i.e. TF-A) to be granted access to system and processor +resources. Essentially, it is a software sandbox in the Secure world that runs +under the control of privileged software, provides one or more services and +accesses the following system resources: + +- Memory and device regions in the system address map. + +- PE system registers. + +- A range of synchronous exceptions (e.g. SMC function identifiers). + +Note that currently TF-A only supports handling one Secure Partition. + +A Secure Partition enables TF-A to implement only the essential secure +services in EL3 and instantiate the rest in a partition in S-EL0. +Furthermore, multiple Secure Partitions can be used to isolate unrelated +services from each other. + +The following diagram illustrates the place of a Secure Partition in a typical +Armv8-A software stack. A single or multiple Secure Partitions provide secure +services to software components in the Non-secure world and other Secure +Partitions. + +|Image 2| + +The TF-A build system is responsible for including the Secure Partition image +in the FIP. During boot, BL2 includes support to authenticate and load the +Secure Partition image. A BL31 component called **Secure Partition Manager +(SPM)** is responsible for managing the partition. This is semantically +similar to a hypervisor managing a virtual machine. + +The SPM is responsible for the following actions during boot: + +- Allocate resources requested by the Secure Partition. + +- Perform architectural and system setup required by the Secure Partition to + fulfil a service request. + +- Implement a standard interface that is used for initialising a Secure + Partition. + +The SPM is responsible for the following actions during runtime: + +- Implement a standard interface that is used by a Secure Partition to fulfil + service requests. + +- Implement a standard interface that is used by the Non-secure world for + accessing the services exported by a Secure Partition. A service can be + invoked through a SMC. + +Alternatively, a partition can be viewed as a thread of execution running under +the control of the SPM. Hence common programming concepts described below are +applicable to a partition. + +Description +=========== + +The previous section introduced some general aspects of the software +architecture of a Secure Partition. This section describes the specific choices +made in the current implementation of this software architecture. Subsequent +revisions of the implementation will include a richer set of features that +enable a more flexible architecture. + +Building TF-A with Secure Partition support +------------------------------------------- + +SPM is supported on the Arm FVP exclusively at the moment. The current +implementation supports inclusion of only a single Secure Partition in which a +service always runs to completion (e.g. the requested services cannot be +preempted to give control back to the Normal world). + +It is not currently possible for BL31 to integrate SPM support and a Secure +Payload Dispatcher (SPD) at the same time; they are mutually exclusive. In the +SPM bootflow, a Secure Partition image executing at S-EL0 replaces the Secure +Payload image executing at S-EL1 (e.g. a Trusted OS). Both are referred to as +BL32. + +A working prototype of a SP has been implemented by re-purposing the EDK2 code +and tools, leveraging the concept of the *Standalone Management Mode (MM)* in +the UEFI specification (see the PI v1.6 Volume 4: Management Mode Core +Interface). This will be referred to as the *Standalone MM Secure Partition* in +the rest of this document. + +To enable SPM support in TF-A, the source code must be compiled with the build +flag ``SPM_MM=1``, along with ``EL3_EXCEPTION_HANDLING=1`` and ``ENABLE_SVE_FOR_NS=0``. +On Arm platforms the build option ``ARM_BL31_IN_DRAM`` must be set to 1. Also, the +location of the binary that contains the BL32 image +(``BL32=path/to/image.bin``) must be specified. + +First, build the Standalone MM Secure Partition. To build it, refer to the +`instructions in the EDK2 repository`_. + +Then build TF-A with SPM support and include the Standalone MM Secure Partition +image in the FIP: + +.. code:: shell + + BL32=path/to/standalone/mm/sp BL33=path/to/bl33.bin \ + make PLAT=fvp SPM_MM=1 EL3_EXCEPTION_HANDLING=1 ENABLE_SVE_FOR_NS=0 ARM_BL31_IN_DRAM=1 all fip + +Describing Secure Partition resources +------------------------------------- + +TF-A exports a porting interface that enables a platform to specify the system +resources required by the Secure Partition. Some instructions are given below. +However, this interface is under development and it may change as new features +are implemented. + +- A Secure Partition is considered a BL32 image, so the same defines that apply + to BL32 images apply to a Secure Partition: ``BL32_BASE`` and ``BL32_LIMIT``. + +- The following defines are needed to allocate space for the translation tables + used by the Secure Partition: ``PLAT_SP_IMAGE_MMAP_REGIONS`` and + ``PLAT_SP_IMAGE_MAX_XLAT_TABLES``. + +- The functions ``plat_get_secure_partition_mmap()`` and + ``plat_get_secure_partition_boot_info()`` have to be implemented. The file + ``plat/arm/board/fvp/fvp_common.c`` can be used as an example. It uses the + defines in ``include/plat/arm/common/arm_spm_def.h``. + + - ``plat_get_secure_partition_mmap()`` returns an array of mmap regions that + describe the memory regions that the SPM needs to allocate for a Secure + Partition. + + - ``plat_get_secure_partition_boot_info()`` returns a + ``spm_mm_boot_info_t`` struct that is populated by the platform + with information about the memory map of the Secure Partition. + +For an example of all the changes in context, you may refer to commit +``e29efeb1b4``, in which the port for FVP was introduced. + +Accessing Secure Partition services +----------------------------------- + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) describes SMCs as a conduit for +accessing services implemented in the Secure world. The ``MM_COMMUNICATE`` +interface defined in the `Management Mode Interface Specification`_ (*Arm DEN +0060A*) is used to invoke a Secure Partition service as a Fast Call. + +The mechanism used to identify a service within the partition depends on the +service implementation. It is assumed that the caller of the service will be +able to discover this mechanism through standard platform discovery mechanisms +like ACPI and Device Trees. For example, *Volume 4: Platform Initialisation +Specification v1.6. Management Mode Core Interface* specifies that a GUID is +used to identify a management mode service. A client populates the GUID in the +``EFI_MM_COMMUNICATE_HEADER``. The header is populated in the communication +buffer shared with the Secure Partition. + +A Fast Call appears to be atomic from the perspective of the caller and returns +when the requested operation has completed. A service invoked through the +``MM_COMMUNICATE`` SMC will run to completion in the partition on a given CPU. +The SPM is responsible for guaranteeing this behaviour. This means that there +can only be a single outstanding Fast Call in a partition on a given CPU. + +Exchanging data with the Secure Partition +----------------------------------------- + +The exchange of data between the Non-secure world and the partition takes place +through a shared memory region. The location of data in the shared memory area +is passed as a parameter to the ``MM_COMMUNICATE`` SMC. The shared memory area +is statically allocated by the SPM and is expected to be either implicitly known +to the Non-secure world or discovered through a platform discovery mechanism +e.g. ACPI table or device tree. It is possible for the Non-secure world to +exchange data with a partition only if it has been populated in this shared +memory area. The shared memory area is implemented as per the guidelines +specified in Section 3.2.3 of the `Management Mode Interface Specification`_ +(*Arm DEN 0060A*). + +The format of data structures used to encapsulate data in the shared memory is +agreed between the Non-secure world and the Secure Partition. For example, in +the `Management Mode Interface specification`_ (*Arm DEN 0060A*), Section 4 +describes that the communication buffer shared between the Non-secure world and +the Management Mode (MM) in the Secure world must be of the type +``EFI_MM_COMMUNICATE_HEADER``. This data structure is defined in *Volume 4: +Platform Initialisation Specification v1.6. Management Mode Core Interface*. +Any caller of a MM service will have to use the ``EFI_MM_COMMUNICATE_HEADER`` +data structure. + +Runtime model of the Secure Partition +===================================== + +This section describes how the Secure Partition interfaces with the SPM. + +Interface with SPM +------------------ + +In order to instantiate one or more secure services in the Secure Partition in +S-EL0, the SPM should define the following types of interfaces: + +- Interfaces that enable access to privileged operations from S-EL0. These + operations typically require access to system resources that are either shared + amongst multiple software components in the Secure world or cannot be directly + accessed from an unprivileged Exception Level. + +- Interfaces that establish the control path between the SPM and the Secure + Partition. + +This section describes the APIs currently exported by the SPM that enable a +Secure Partition to initialise itself and export its services in S-EL0. These +interfaces are not accessible from the Non-secure world. + +Conduit +^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the SMC +and HVC conduits for accessing firmware services and their availability +depending on the implemented Exception levels. In S-EL0, the Supervisor Call +exception (SVC) is the only architectural mechanism available for unprivileged +software to make a request for an operation implemented in privileged software. +Hence, the SVC conduit must be used by the Secure Partition to access interfaces +implemented by the SPM. + +A SVC causes an exception to be taken to S-EL1. TF-A assumes ownership of S-EL1 +and installs a simple exception vector table in S-EL1 that relays a SVC request +from a Secure Partition as a SMC request to the SPM in EL3. Upon servicing the +SMC request, Trusted Firmware-A returns control directly to S-EL0 through an +ERET instruction. + +Calling conventions +^^^^^^^^^^^^^^^^^^^ + +The `SMC Calling Convention`_ (*Arm DEN 0028B*) specification describes the +32-bit and 64-bit calling conventions for the SMC and HVC conduits. The SVC +conduit introduces the concept of SVC32 and SVC64 calling conventions. The SVC32 +and SVC64 calling conventions are equivalent to the 32-bit (SMC32) and the +64-bit (SMC64) calling conventions respectively. + +Communication initiated by SPM +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A service request is initiated from the SPM through an exception return +instruction (ERET) to S-EL0. Later, the Secure Partition issues an SVC +instruction to signal completion of the request. Some example use cases are +given below: + +- A request to initialise the Secure Partition during system boot. + +- A request to handle a runtime service request. + +Communication initiated by Secure Partition +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +A request is initiated from the Secure Partition by executing a SVC instruction. +An ERET instruction is used by TF-A to return to S-EL0 with the result of the +request. + +For instance, a request to perform privileged operations on behalf of a +partition (e.g. management of memory attributes in the translation tables for +the Secure EL1&0 translation regime). + +Interfaces +^^^^^^^^^^ + +The current implementation reserves function IDs for Fast Calls in the Standard +Secure Service calls range (see `SMC Calling Convention`_ (*Arm DEN 0028B*) +specification) for each API exported by the SPM. This section defines the +function prototypes for each function ID. The function IDs specify whether one +or both of the SVC32 and SVC64 calling conventions can be used to invoke the +corresponding interface. + +Secure Partition Event Management +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Secure Partition provides an Event Management interface that is used by the +SPM to delegate service requests to the Secure Partition. The interface also +allows the Secure Partition to: + +- Register with the SPM a service that it provides. +- Indicate completion of a service request delegated by the SPM + +Miscellaneous interfaces +------------------------ + +``SPM_MM_VERSION_AARCH32`` +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Returns the version of the interface exported by SPM. + +- Parameters + + - **uint32** - Function ID + + - SVC32 Version: **0x84000060** + +- Return parameters + + - **int32** - Status + + On success, the format of the value is as follows: + + - Bit [31]: Must be 0 + - Bits [30:16]: Major Version. Must be 0 for this revision of the SPM + interface. + - Bits [15:0]: Minor Version. Must be 1 for this revision of the SPM + interface. + + On error, the format of the value is as follows: + + - ``NOT_SUPPORTED``: SPM interface is not supported or not available for the + client. + +- Usage + + This function returns the version of the Secure Partition Manager + implementation. The major version is 0 and the minor version is 1. The version + number is a 31-bit unsigned integer, with the upper 15 bits denoting the major + revision, and the lower 16 bits denoting the minor revision. The following + rules apply to the version numbering: + + - Different major revision values indicate possibly incompatible functions. + + - For two revisions, A and B, for which the major revision values are + identical, if the minor revision value of revision B is greater than the + minor revision value of revision A, then every function in revision A must + work in a compatible way with revision B. However, it is possible for + revision B to have a higher function count than revision A. + +- Implementation responsibilities + + If this function returns a valid version number, all the functions that are + described subsequently must be implemented, unless it is explicitly stated + that a function is optional. + +See `Error Codes`_ for integer values that are associated with each return +code. + +Secure Partition Initialisation +------------------------------- + +The SPM is responsible for initialising the architectural execution context to +enable initialisation of a service in S-EL0. The responsibilities of the SPM are +listed below. At the end of initialisation, the partition issues a +``MM_SP_EVENT_COMPLETE_AARCH64`` call (described later) to signal readiness for +handling requests for services implemented by the Secure Partition. The +initialisation event is executed as a Fast Call. + +Entry point invocation +^^^^^^^^^^^^^^^^^^^^^^ + +The entry point for service requests that should be handled as Fast Calls is +used as the target of the ERET instruction to start initialisation of the Secure +Partition. + +Architectural Setup +^^^^^^^^^^^^^^^^^^^ + +At cold boot, system registers accessible from S-EL0 will be in their reset +state unless otherwise specified. The SPM will perform the following +architectural setup to enable execution in S-EL0 + +MMU setup +^^^^^^^^^ + +The platform port of a Secure Partition specifies to the SPM a list of regions +that it needs access to and their attributes. The SPM validates this resource +description and initialises the Secure EL1&0 translation regime as follows. + +1. Device regions are mapped with nGnRE attributes and Execute Never + instruction access permissions. + +2. Code memory regions are mapped with RO data and Executable instruction access + permissions. + +3. Read Only data memory regions are mapped with RO data and Execute Never + instruction access permissions. + +4. Read Write data memory regions are mapped with RW data and Execute Never + instruction access permissions. + +5. If the resource description does not explicitly describe the type of memory + regions then all memory regions will be marked with Code memory region + attributes. + +6. The ``UXN`` and ``PXN`` bits are set for regions that are not executable by + S-EL0 or S-EL1. + +System Register Setup +^^^^^^^^^^^^^^^^^^^^^ + +System registers that influence software execution in S-EL0 are setup by the SPM +as follows: + +1. ``SCTLR_EL1`` + + - ``UCI=1`` + - ``EOE=0`` + - ``WXN=1`` + - ``nTWE=1`` + - ``nTWI=1`` + - ``UCT=1`` + - ``DZE=1`` + - ``I=1`` + - ``UMA=0`` + - ``SA0=1`` + - ``C=1`` + - ``A=1`` + - ``M=1`` + +2. ``CPACR_EL1`` + + - ``FPEN=b'11`` + +3. ``PSTATE`` + + - ``D,A,I,F=1`` + - ``CurrentEL=0`` (EL0) + - ``SpSel=0`` (Thread mode) + - ``NRW=0`` (AArch64) + +General Purpose Register Setup +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +SPM will invoke the entry point of a service by executing an ERET instruction. +This transition into S-EL0 is special since it is not in response to a previous +request through a SVC instruction. This is the first entry into S-EL0. The +general purpose register usage at the time of entry will be as specified in the +"Return State" column of Table 3-1 in Section 3.1 "Register use in AArch64 SMC +calls" of the `SMC Calling Convention`_ (*Arm DEN 0028B*) specification. In +addition, certain other restrictions will be applied as described below. + +1. ``SP_EL0`` + + A non-zero value will indicate that the SPM has initialised the stack pointer + for the current CPU. + + The value will be 0 otherwise. + +2. ``X4-X30`` + + The values of these registers will be 0. + +3. ``X0-X3`` + + Parameters passed by the SPM. + + - ``X0``: Virtual address of a buffer shared between EL3 and S-EL0. The + buffer will be mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + - ``X1``: Size of the buffer in bytes. + + - ``X2``: Cookie value (*IMPLEMENTATION DEFINED*). + + - ``X3``: Cookie value (*IMPLEMENTATION DEFINED*). + +Runtime Event Delegation +------------------------ + +The SPM receives requests for Secure Partition services through a synchronous +invocation (i.e. a SMC from the Non-secure world). These requests are delegated +to the partition by programming a return from the last +``MM_SP_EVENT_COMPLETE_AARCH64`` call received from the partition. The last call +was made to signal either completion of Secure Partition initialisation or +completion of a partition service request. + +``MM_SP_EVENT_COMPLETE_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Signal completion of the last SP service request. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000061** + + - **int32** - Event Status Code + + Zero or a positive value indicates that the event was handled successfully. + The values depend upon the original event that was delegated to the Secure + partition. They are described as follows. + + - ``SUCCESS`` : Used to indicate that the Secure Partition was initialised + or a runtime request was handled successfully. + + - Any other value greater than 0 is used to pass a specific Event Status + code in response to a runtime event. + + A negative value indicates an error. The values of Event Status code depend + on the original event. + +- Return parameters + + - **int32** - Event ID/Return Code + + Zero or a positive value specifies the unique ID of the event being + delegated to the partition by the SPM. + + In the current implementation, this parameter contains the function ID of + the ``MM_COMMUNICATE`` SMC. This value indicates to the partition that an + event has been delegated to it in response to an ``MM_COMMUNICATE`` request + from the Non-secure world. + + A negative value indicates an error. The format of the value is as follows: + + - ``NOT_SUPPORTED``: Function was called from the Non-secure world. + + See `Error Codes`_ for integer values that are associated with each return + code. + + - **uint32** - Event Context Address + + Address of a buffer shared between the SPM and Secure Partition to pass + event specific information. The format of the data populated in the buffer + is implementation defined. + + The buffer is mapped in the Secure EL1&0 translation regime with read-only + memory attributes described earlier. + + For the SVC64 version, this parameter is a 64-bit Virtual Address (VA). + + For the SVC32 version, this parameter is a 32-bit Virtual Address (VA). + + - **uint32** - Event context size + + Size of the memory starting at Event Address. + + - **uint32/uint64** - Event Cookie + + This is an optional parameter. If unused its value is SBZ. + +- Usage + + This function signals to the SPM that the handling of the last event delegated + to a partition has completed. The partition is ready to handle its next event. + A return from this function is in response to the next event that will be + delegated to the partition. The return parameters describe the next event. + +- Caller responsibilities + + A Secure Partition must only call ``MM_SP_EVENT_COMPLETE_AARCH64`` to signal + completion of a request that was delegated to it by the SPM. + +- Callee responsibilities + + When the SPM receives this call from a Secure Partition, the corresponding + syndrome information can be used to return control through an ERET + instruction, to the instruction immediately after the call in the Secure + Partition context. This syndrome information comprises of general purpose and + system register values when the call was made. + + The SPM must save this syndrome information and use it to delegate the next + event to the Secure Partition. The return parameters of this interface must + specify the properties of the event and be populated in ``X0-X3/W0-W3`` + registers. + +Secure Partition Memory Management +---------------------------------- + +A Secure Partition executes at S-EL0, which is an unprivileged Exception Level. +The SPM is responsible for enabling access to regions of memory in the system +address map from a Secure Partition. This is done by mapping these regions in +the Secure EL1&0 Translation regime with appropriate memory attributes. +Attributes refer to memory type, permission, cacheability and shareability +attributes used in the Translation tables. The definitions of these attributes +and their usage can be found in the `Armv8-A ARM`_ (*Arm DDI 0487*). + +All memory required by the Secure Partition is allocated upfront in the SPM, +even before handing over to the Secure Partition for the first time. The initial +access permissions of the memory regions are statically provided by the platform +port and should allow the Secure Partition to run its initialisation code. + +However, they might not suit the final needs of the Secure Partition because its +final memory layout might not be known until the Secure Partition initialises +itself. As the Secure Partition initialises its runtime environment it might, +for example, load dynamically some modules. For instance, a Secure Partition +could implement a loader for a standard executable file format (e.g. an PE-COFF +loader for loading executable files at runtime). These executable files will be +a part of the Secure Partition image. The location of various sections in an +executable file and their permission attributes (e.g. read-write data, read-only +data and code) will be known only when the file is loaded into memory. + +In this case, the Secure Partition needs a way to change the access permissions +of its memory regions. The SPM provides this feature through the +``MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64`` SVC interface. This interface is +available to the Secure Partition during a specific time window: from the first +entry into the Secure Partition up to the first ``SP_EVENT_COMPLETE`` call that +signals the Secure Partition has finished its initialisation. Once the +initialisation is complete, the SPM does not allow changes to the memory +attributes. + +This section describes the standard SVC interface that is implemented by the SPM +to determine and change permission attributes of memory regions that belong to a +Secure Partition. + +``MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Request the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** Function ID + + - SVC64 Version: **0xC4000064** + + - **uint64** Base Address + + This parameter is a 64-bit Virtual Address (VA). + + There are no alignment restrictions on the Base Address. The permission + attributes of the translation granule it lies in are returned. + +- Return parameters + + - **int32** - Memory Attributes/Return Code + + On success the format of the Return Code is as follows: + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2]: Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bit[30:3] : Reserved. SBZ. + + - Bit[31] : Must be 0 + + On failure the following error codes are returned: + + - ``INVALID_PARAMETERS``: The Secure Partition is not allowed to access the + memory region the Base Address lies in. + + - ``NOT_SUPPORTED`` : The SPM does not support retrieval of attributes of + any memory page that is accessible by the Secure Partition, or the + function was called from the Non-secure world. Also returned if it is + used after ``MM_SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to request the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to retrieve other memory region attributes are + not currently supported. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must not return the memory access controls for a page of memory that + is not accessible from a Secure Partition. + +``MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +- Description + + Set the permission attributes of a memory region from S-EL0. + +- Parameters + + - **uint32** - Function ID + + - SVC64 Version: **0xC4000065** + + - **uint64** - Base Address + + This parameter is a 64-bit Virtual Address (VA). + + The alignment of the Base Address must be greater than or equal to the size + of the Translation Granule Size used in the Secure EL1&0 translation + regime. + + - **uint32** - Page count + + Number of pages starting from the Base Address whose memory attributes + should be changed. The page size is equal to the Translation Granule Size. + + - **uint32** - Memory Access Controls + + - Bits[1:0] : Data access permission + + - b'00 : No access + - b'01 : Read-Write access + - b'10 : Reserved + - b'11 : Read-only access + + - Bit[2] : Instruction access permission + + - b'0 : Executable + - b'1 : Non-executable + + - Bits[31:3] : Reserved. SBZ. + + A combination of attributes that mark the region with RW and Executable + permissions is prohibited. A request to mark a device memory region with + Executable permissions is prohibited. + +- Return parameters + + - **int32** - Return Code + + - ``SUCCESS``: The Memory Access Controls were changed successfully. + + - ``DENIED``: The SPM is servicing a request to change the attributes of a + memory region that overlaps with the region specified in this request. + + - ``INVALID_PARAMETER``: An invalid combination of Memory Access Controls + has been specified. The Base Address is not correctly aligned. The Secure + Partition is not allowed to access part or all of the memory region + specified in the call. + + - ``NO_MEMORY``: The SPM does not have memory resources to change the + attributes of the memory region in the translation tables. + + - ``NOT_SUPPORTED``: The SPM does not permit change of attributes of any + memory region that is accessible by the Secure Partition. Function was + called from the Non-secure world. Also returned if it is used after + ``MM_SP_EVENT_COMPLETE_AARCH64``. + + See `Error Codes`_ for integer values that are associated with each return + code. + +- Usage + + This function is used to change the permission attributes for S-EL0 on a + memory region accessible from a Secure Partition. The size of the memory + region is equal to the Translation Granule size used in the Secure EL1&0 + translation regime. Requests to change other memory region attributes are not + currently supported. + + This function is only available at boot time. This interface is revoked after + the Secure Partition sends the first ``MM_SP_EVENT_COMPLETE_AARCH64`` to + signal that it is initialised and ready to receive run-time requests. + +- Caller responsibilities + + The caller must obtain the Translation Granule Size of the Secure EL1&0 + translation regime from the SPM through an implementation defined method. + +- Callee responsibilities + + The SPM must preserve the original memory access controls of the region of + memory in case of an unsuccessful call.  The SPM must preserve the consistency + of the S-EL1 translation regime if this function is called on different PEs + concurrently and the memory regions specified overlap. + +Error Codes +----------- + +.. csv-table:: + :header: "Name", "Value" + + ``SUCCESS``,0 + ``NOT_SUPPORTED``,-1 + ``INVALID_PARAMETER``,-2 + ``DENIED``,-3 + ``NO_MEMORY``,-5 + ``NOT_PRESENT``,-7 + +-------------- + +*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Armv8-A ARM: https://developer.arm.com/docs/ddi0487/latest/arm-architecture-reference-manual-armv8-for-armv8-a-architecture-profile +.. _instructions in the EDK2 repository: https://github.com/tianocore/edk2-staging/blob/AArch64StandaloneMm/HowtoBuild.MD +.. _Management Mode Interface Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0060a/DEN0060A_ARM_MM_Interface_Specification.pdf +.. _SDEI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest + +.. |Image 1| image:: ../resources/diagrams/secure_sw_stack_tos.png +.. |Image 2| image:: ../resources/diagrams/secure_sw_stack_sp.png diff --git a/arm-trusted-firmware/docs/components/secure-partition-manager.rst b/arm-trusted-firmware/docs/components/secure-partition-manager.rst new file mode 100644 index 0000000..af298e3 --- /dev/null +++ b/arm-trusted-firmware/docs/components/secure-partition-manager.rst @@ -0,0 +1,1291 @@ +Secure Partition Manager +************************ + +.. contents:: + +Acronyms +======== + ++--------+--------------------------------------+ +| CoT | Chain of Trust | ++--------+--------------------------------------+ +| DMA | Direct Memory Access | ++--------+--------------------------------------+ +| DTB | Device Tree Blob | ++--------+--------------------------------------+ +| DTS | Device Tree Source | ++--------+--------------------------------------+ +| EC | Execution Context | ++--------+--------------------------------------+ +| FIP | Firmware Image Package | ++--------+--------------------------------------+ +| FF-A | Firmware Framework for Arm A-profile | ++--------+--------------------------------------+ +| IPA | Intermediate Physical Address | ++--------+--------------------------------------+ +| NWd | Normal World | ++--------+--------------------------------------+ +| ODM | Original Design Manufacturer | ++--------+--------------------------------------+ +| OEM | Original Equipment Manufacturer | ++--------+--------------------------------------+ +| PA | Physical Address | ++--------+--------------------------------------+ +| PE | Processing Element | ++--------+--------------------------------------+ +| PM | Power Management | ++--------+--------------------------------------+ +| PVM | Primary VM | ++--------+--------------------------------------+ +| SMMU | System Memory Management Unit | ++--------+--------------------------------------+ +| SP | Secure Partition | ++--------+--------------------------------------+ +| SPD | Secure Payload Dispatcher | ++--------+--------------------------------------+ +| SPM | Secure Partition Manager | ++--------+--------------------------------------+ +| SPMC | SPM Core | ++--------+--------------------------------------+ +| SPMD | SPM Dispatcher | ++--------+--------------------------------------+ +| SiP | Silicon Provider | ++--------+--------------------------------------+ +| SWd | Secure World | ++--------+--------------------------------------+ +| TLV | Tag-Length-Value | ++--------+--------------------------------------+ +| TOS | Trusted Operating System | ++--------+--------------------------------------+ +| VM | Virtual Machine | ++--------+--------------------------------------+ + +Foreword +======== + +Two implementations of a Secure Partition Manager co-exist in the TF-A codebase: + +- SPM based on the FF-A specification `[1]`_. +- SPM based on the MM interface to communicate with an S-EL0 partition `[2]`_. + +Both implementations differ in their architectures and only one can be selected +at build time. + +This document: + +- describes the FF-A implementation where the Secure Partition Manager + resides at EL3 and S-EL2 (or EL3 and S-EL1). +- is not an architecture specification and it might provide assumptions + on sections mandated as implementation-defined in the specification. +- covers the implications to TF-A used as a bootloader, and Hafnium + used as a reference code base for an S-EL2 secure firmware on + platforms implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) + architecture extension. + +Terminology +----------- + +- The term Hypervisor refers to the NS-EL2 component managing Virtual Machines + (or partitions) in the normal world. +- The term SPMC refers to the S-EL2 component managing secure partitions in + the secure world when the FEAT_SEL2 architecture extension is implemented. +- Alternatively, SPMC can refer to an S-EL1 component, itself being a secure + partition and implementing the FF-A ABI on platforms not implementing the + FEAT_SEL2 architecture extension. +- The term VM refers to a normal world Virtual Machine managed by an Hypervisor. +- The term SP refers to a secure world "Virtual Machine" managed by an SPMC. + +Support for legacy platforms +---------------------------- + +In the implementation, the SPM is split into SPMD and SPMC components. +The SPMD is located at EL3 and mainly relays FF-A messages from +NWd (Hypervisor or OS kernel) to SPMC located either at S-EL1 or S-EL2. + +Hence TF-A supports both cases where the SPMC is located either at: + +- S-EL1 supporting platforms not implementing the FEAT_SEL2 architecture + extension. The SPMD relays the FF-A protocol from EL3 to S-EL1. +- or S-EL2 supporting platforms implementing the FEAT_SEL2 architecture + extension. The SPMD relays the FF-A protocol from EL3 to S-EL2. + +The same TF-A SPMD component is used to support both configurations. +The SPMC exception level is a build time choice. + +Sample reference stack +====================== + +The following diagram illustrates a possible configuration when the +FEAT_SEL2 architecture extension is implemented, showing the SPMD +and SPMC, one or multiple secure partitions, with an optional +Hypervisor: + +.. image:: ../resources/diagrams/ff-a-spm-sel2.png + +TF-A build options +================== + +This section explains the TF-A build options involved in building with +support for an FF-A based SPM where the SPMD is located at EL3 and the +SPMC located at S-EL1 or S-EL2: + +- **SPD=spmd**: this option selects the SPMD component to relay the FF-A + protocol from NWd to SWd back and forth. It is not possible to + enable another Secure Payload Dispatcher when this option is chosen. +- **SPMD_SPM_AT_SEL2**: this option adjusts the SPMC exception + level to being S-EL1 or S-EL2. It defaults to enabled (value 1) when + SPD=spmd is chosen. +- **CTX_INCLUDE_EL2_REGS**: this option permits saving (resp. + restoring) the EL2 system register context before entering (resp. + after leaving) the SPMC. It is mandatorily enabled when + ``SPMD_SPM_AT_SEL2`` is enabled. The context save/restore routine + and exhaustive list of registers is visible at `[4]`_. +- **SP_LAYOUT_FILE**: this option specifies a text description file + providing paths to SP binary images and manifests in DTS format + (see `Describing secure partitions`_). It + is required when ``SPMD_SPM_AT_SEL2`` is enabled hence when multiple + secure partitions are to be loaded on behalf of the SPMC. + ++---------------+----------------------+------------------+ +| | CTX_INCLUDE_EL2_REGS | SPMD_SPM_AT_SEL2 | ++---------------+----------------------+------------------+ +| SPMC at S-EL1 | 0 | 0 | ++---------------+----------------------+------------------+ +| SPMC at S-EL2 | 1 | 1 (default when | +| | | SPD=spmd) | ++---------------+----------------------+------------------+ + +Other combinations of such build options either break the build or are not +supported. + +Notes: + +- Only Arm's FVP platform is supported to use with the TF-A reference software + stack. +- The reference software stack uses FEAT_PAuth (formerly Armv8.3-PAuth) and + FEAT_BTI (formerly Armv8.5-BTI) architecture extensions by default at EL3 + and S-EL2. +- The ``CTX_INCLUDE_EL2_REGS`` option provides the generic support for + barely saving/restoring EL2 registers from an Arm arch perspective. As such + it is decoupled from the ``SPD=spmd`` option. +- BL32 option is re-purposed to specify the SPMC image. It can specify either + the Hafnium binary path (built for the secure world) or the path to a TEE + binary implementing FF-A interfaces. +- BL33 option can specify the TFTF binary or a normal world loader + such as U-Boot or the UEFI framework. + +Sample TF-A build command line when SPMC is located at S-EL1 +(e.g. when the FEAT_EL2 architecture extension is not implemented): + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=0 \ + BL32= \ + BL33= \ + PLAT=fvp \ + all fip + +Sample TF-A build command line for a FEAT_SEL2 enabled system where the SPMC is +located at S-EL2: + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + SPD=spmd \ + CTX_INCLUDE_EL2_REGS=1 \ + ARM_ARCH_MINOR=5 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + BL32= \ + BL33= \ + SP_LAYOUT_FILE=sp_layout.json \ + all fip + +Same as above with enabling secure boot in addition: + +.. code:: shell + + make \ + CROSS_COMPILE=aarch64-none-elf- \ + PLAT=fvp \ + SPD=spmd \ + CTX_INCLUDE_EL2_REGS=1 \ + ARM_ARCH_MINOR=5 \ + BRANCH_PROTECTION=1 \ + CTX_INCLUDE_PAUTH_REGS=1 \ + BL32= \ + BL33= \ + SP_LAYOUT_FILE=sp_layout.json \ + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + COT=dualroot \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + GENERATE_COT=1 \ + all fip + +FVP model invocation +==================== + +The FVP command line needs the following options to exercise the S-EL2 SPMC: + ++---------------------------------------------------+------------------------------------+ +| - cluster0.has_arm_v8-5=1 | Implements FEAT_SEL2, FEAT_PAuth, | +| - cluster1.has_arm_v8-5=1 | and FEAT_BTI. | ++---------------------------------------------------+------------------------------------+ +| - pci.pci_smmuv3.mmu.SMMU_AIDR=2 | Parameters required for the | +| - pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B | SMMUv3.2 modeling. | +| - pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 | | +| - pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 | | +| - pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 | | +| - pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 | | ++---------------------------------------------------+------------------------------------+ +| - cluster0.has_branch_target_exception=1 | Implements FEAT_BTI. | +| - cluster1.has_branch_target_exception=1 | | ++---------------------------------------------------+------------------------------------+ +| - cluster0.restriction_on_speculative_execution=2 | Required by the EL2 context | +| - cluster1.restriction_on_speculative_execution=2 | save/restore routine. | ++---------------------------------------------------+------------------------------------+ + +Sample FVP command line invocation: + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A -C pctl.startup=0.0.0.0 + -C cluster0.NUM_CORES=4 -C cluster1.NUM_CORES=4 -C bp.secure_memory=1 \ + -C bp.secureflashloader.fname=trusted-firmware-a/build/fvp/debug/bl1.bin \ + -C bp.flashloader0.fname=trusted-firmware-a/build/fvp/debug/fip.bin \ + -C bp.pl011_uart0.out_file=fvp-uart0.log -C bp.pl011_uart1.out_file=fvp-uart1.log \ + -C bp.pl011_uart2.out_file=fvp-uart2.log \ + -C cluster0.has_arm_v8-5=1 -C cluster1.has_arm_v8-5=1 -C pci.pci_smmuv3.mmu.SMMU_AIDR=2 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR0=0x0046123B -C pci.pci_smmuv3.mmu.SMMU_IDR1=0x00600002 \ + -C pci.pci_smmuv3.mmu.SMMU_IDR3=0x1714 -C pci.pci_smmuv3.mmu.SMMU_IDR5=0xFFFF0472 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR1=0xA0000002 -C pci.pci_smmuv3.mmu.SMMU_S_IDR2=0 \ + -C pci.pci_smmuv3.mmu.SMMU_S_IDR3=0 \ + -C cluster0.has_branch_target_exception=1 \ + -C cluster1.has_branch_target_exception=1 \ + -C cluster0.restriction_on_speculative_execution=2 \ + -C cluster1.restriction_on_speculative_execution=2 + +Boot process +============ + +Loading Hafnium and secure partitions in the secure world +--------------------------------------------------------- + +TF-A BL2 is the bootlader for the SPMC and SPs in the secure world. + +SPs may be signed by different parties (SiP, OEM/ODM, TOS vendor, etc.). +Thus they are supplied as distinct signed entities within the FIP flash +image. The FIP image itself is not signed hence this provides the ability +to upgrade SPs in the field. + +Booting through TF-A +-------------------- + +SP manifests +~~~~~~~~~~~~ + +An SP manifest describes SP attributes as defined in `[1]`_ +(partition manifest at virtual FF-A instance) in DTS format. It is +represented as a single file associated with the SP. A sample is +provided by `[5]`_. A binding document is provided by `[6]`_. + +Secure Partition packages +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Secure partitions are bundled as independent package files consisting +of: + +- a header +- a DTB +- an image payload + +The header starts with a magic value and offset values to SP DTB and +image payload. Each SP package is loaded independently by BL2 loader +and verified for authenticity and integrity. + +The SP package identified by its UUID (matching FF-A uuid property) is +inserted as a single entry into the FIP at end of the TF-A build flow +as shown: + +.. code:: shell + + Trusted Boot Firmware BL2: offset=0x1F0, size=0x8AE1, cmdline="--tb-fw" + EL3 Runtime Firmware BL31: offset=0x8CD1, size=0x13000, cmdline="--soc-fw" + Secure Payload BL32 (Trusted OS): offset=0x1BCD1, size=0x15270, cmdline="--tos-fw" + Non-Trusted Firmware BL33: offset=0x30F41, size=0x92E0, cmdline="--nt-fw" + HW_CONFIG: offset=0x3A221, size=0x2348, cmdline="--hw-config" + TB_FW_CONFIG: offset=0x3C569, size=0x37A, cmdline="--tb-fw-config" + SOC_FW_CONFIG: offset=0x3C8E3, size=0x48, cmdline="--soc-fw-config" + TOS_FW_CONFIG: offset=0x3C92B, size=0x427, cmdline="--tos-fw-config" + NT_FW_CONFIG: offset=0x3CD52, size=0x48, cmdline="--nt-fw-config" + B4B5671E-4A90-4FE1-B81F-FB13DAE1DACB: offset=0x3CD9A, size=0xC168, cmdline="--blob" + D1582309-F023-47B9-827C-4464F5578FC8: offset=0x48F02, size=0xC168, cmdline="--blob" + +.. uml:: ../resources/diagrams/plantuml/fip-secure-partitions.puml + +Describing secure partitions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A json-formatted description file is passed to the build flow specifying paths +to the SP binary image and associated DTS partition manifest file. The latter +is processed by the dtc compiler to generate a DTB fed into the SP package. +This file also specifies the SP owner (as an optional field) identifying the +signing domain in case of dual root CoT. +The SP owner can either be the silicon or the platform provider. The +corresponding "owner" field value can either take the value of "SiP" or "Plat". +In absence of "owner" field, it defaults to "SiP" owner. +The UUID of the partition can be specified as a field in the description file or +if it does not exist there the UUID is extracted from the DTS partition +manifest. + +.. code:: shell + + { + "tee1" : { + "image": "tee1.bin", + "pm": "tee1.dts", + "owner": "SiP", + "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f" + }, + + "tee2" : { + "image": "tee2.bin", + "pm": "tee2.dts", + "owner": "Plat" + } + } + +SPMC manifest +~~~~~~~~~~~~~ + +This manifest contains the SPMC *attribute* node consumed by the SPMD at boot +time. It implements `[1]`_ (SP manifest at physical FF-A instance) and serves +two different cases: + +- The SPMC resides at S-EL1: the SPMC manifest is used by the SPMD to setup a + SP that co-resides with the SPMC and executes at S-EL1 or Secure Supervisor + mode. +- The SPMC resides at S-EL2: the SPMC manifest is used by the SPMD to setup + the environment required by the SPMC to run at S-EL2. SPs run at S-EL1 or + S-EL0. + +.. code:: shell + + attribute { + spmc_id = <0x8000>; + maj_ver = <0x1>; + min_ver = <0x0>; + exec_state = <0x0>; + load_address = <0x0 0x6000000>; + entrypoint = <0x0 0x6000000>; + binary_size = <0x60000>; + }; + +- *spmc_id* defines the endpoint ID value that SPMC can query through + ``FFA_ID_GET``. +- *maj_ver/min_ver*. SPMD checks provided version versus its internal + version and aborts if not matching. +- *exec_state* defines the SPMC execution state (AArch64 or AArch32). + Notice Hafnium used as a SPMC only supports AArch64. +- *load_address* and *binary_size* are mostly used to verify secondary + entry points fit into the loaded binary image. +- *entrypoint* defines the cold boot primary core entry point used by + SPMD (currently matches ``BL32_BASE``) to enter the SPMC. + +Other nodes in the manifest are consumed by Hafnium in the secure world. +A sample can be found at [7]: + +- The *hypervisor* node describes SPs. *is_ffa_partition* boolean attribute + indicates a FF-A compliant SP. The *load_address* field specifies the load + address at which TF-A loaded the SP package. +- *cpus* node provide the platform topology and allows MPIDR to VMPIDR mapping. + Note the primary core is declared first, then secondary core are declared + in reverse order. +- The *memory* node provides platform information on the ranges of memory + available to the SPMC. + +SPMC boot +~~~~~~~~~ + +The SPMC is loaded by BL2 as the BL32 image. + +The SPMC manifest is loaded by BL2 as the ``TOS_FW_CONFIG`` image `[9]`_. + +BL2 passes the SPMC manifest address to BL31 through a register. + +At boot time, the SPMD in BL31 runs from the primary core, initializes the core +contexts and launches the SPMC (BL32) passing the following information through +registers: + +- X0 holds the ``TOS_FW_CONFIG`` physical address (or SPMC manifest blob). +- X1 holds the ``HW_CONFIG`` physical address. +- X4 holds the currently running core linear id. + +Loading of SPs +~~~~~~~~~~~~~~ + +At boot time, BL2 loads SPs sequentially in addition to the SPMC as depicted +below: + +.. uml:: ../resources/diagrams/plantuml/bl2-loading-sp.puml + +Note this boot flow is an implementation sample on Arm's FVP platform. +Platforms not using TF-A's *Firmware CONFiguration* framework would adjust to a +different implementation. + +Secure boot +~~~~~~~~~~~ + +The SP content certificate is inserted as a separate FIP item so that BL2 loads SPMC, +SPMC manifest, secure partitions and verifies them for authenticity and integrity. +Refer to TBBR specification `[3]`_. + +The multiple-signing domain feature (in current state dual signing domain `[8]`_) allows +the use of two root keys namely S-ROTPK and NS-ROTPK: + +- SPMC (BL32) and SPMC manifest are signed by the SiP using the S-ROTPK. +- BL33 may be signed by the OEM using NS-ROTPK. +- An SP may be signed either by SiP (using S-ROTPK) or by OEM (using NS-ROTPK). + +Also refer to `Describing secure partitions`_ and `TF-A build options`_ sections. + +Hafnium in the secure world +=========================== + +General considerations +---------------------- + +Build platform for the secure world +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In the Hafnium reference implementation specific code parts are only relevant to +the secure world. Such portions are isolated in architecture specific files +and/or enclosed by a ``SECURE_WORLD`` macro. + +Secure partitions CPU scheduling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FF-A v1.0 specification `[1]`_ provides two ways to relinquinsh CPU time to +secure partitions. For this a VM (Hypervisor or OS kernel), or SP invokes one of: + +- the FFA_MSG_SEND_DIRECT_REQ interface. +- the FFA_RUN interface. + +Platform topology +~~~~~~~~~~~~~~~~~ + +The *execution-ctx-count* SP manifest field can take the value of one or the +total number of PEs. The FF-A v1.0 specification `[1]`_ recommends the +following SP types: + +- Pinned MP SPs: an execution context matches a physical PE. MP SPs must + implement the same number of ECs as the number of PEs in the platform. +- Migratable UP SPs: a single execution context can run and be migrated on any + physical PE. Such SP declares a single EC in its SP manifest. An UP SP can + receive a direct message request originating from any physical core targeting + the single execution context. + +Parsing SP partition manifests +------------------------------ + +Hafnium consumes SP manifests as defined in `[1]`_ and `SP manifests`_. +Note the current implementation may not implement all optional fields. + +The SP manifest may contain memory and device regions nodes. In case of +an S-EL2 SPMC: + +- Memory regions are mapped in the SP EL1&0 Stage-2 translation regime at + load time (or EL1&0 Stage-1 for an S-EL1 SPMC). A memory region node can + specify RX/TX buffer regions in which case it is not necessary for an SP + to explicitly invoke the ``FFA_RXTX_MAP`` interface. +- Device regions are mapped in the SP EL1&0 Stage-2 translation regime (or + EL1&0 Stage-1 for an S-EL1 SPMC) as peripherals and possibly allocate + additional resources (e.g. interrupts). + +For the S-EL2 SPMC, base addresses for memory and device region nodes are IPAs +provided the SPMC identity maps IPAs to PAs within SP EL1&0 Stage-2 translation +regime. + +Note: in the current implementation both VTTBR_EL2 and VSTTBR_EL2 point to the +same set of page tables. It is still open whether two sets of page tables shall +be provided per SP. The memory region node as defined in the specification +provides a memory security attribute hinting to map either to the secure or +non-secure EL1&0 Stage-2 table if it exists. + +Passing boot data to the SP +--------------------------- + +In `[1]`_ , the "Protocol for passing data" section defines a method for passing +boot data to SPs (not currently implemented). + +Provided that the whole secure partition package image (see +`Secure Partition packages`_) is mapped to the SP secure EL1&0 Stage-2 +translation regime, an SP can access its own manifest DTB blob and extract its +partition manifest properties. + +SP Boot order +------------- + +SP manifests provide an optional boot order attribute meant to resolve +dependencies such as an SP providing a service required to properly boot +another SP. SPMC boots the SPs in accordance to the boot order attribute, +lowest to the highest value. If the boot order attribute is absent from the FF-A +manifest, the SP is treated as if it had the highest boot order value +(i.e. lowest booting priority). + +It is possible for an SP to call into another SP through a direct request +provided the latter SP has already been booted. + +Boot phases +----------- + +Primary core boot-up +~~~~~~~~~~~~~~~~~~~~ + +Upon boot-up, BL31 hands over to the SPMC (BL32) on the primary boot physical +core. The SPMC performs its platform initializations and registers the SPMC +secondary physical core entry point physical address by the use of the +`FFA_SECONDARY_EP_REGISTER`_ interface (SMC invocation from the SPMC to the SPMD +at secure physical FF-A instance). + +The SPMC then creates secure partitions based on SP packages and manifests. Each +secure partition is launched in sequence (`SP Boot order`_) on their "primary" +execution context. If the primary boot physical core linear id is N, an MP SP is +started using EC[N] on PE[N] (see `Platform topology`_). If the partition is a +UP SP, it is started using its unique EC0 on PE[N]. + +The SP primary EC (or the EC used when the partition is booted as described +above): + +- Performs the overall SP boot time initialization, and in case of a MP SP, + prepares the SP environment for other execution contexts. +- In the case of a MP SP, it invokes the FFA_SECONDARY_EP_REGISTER at secure + virtual FF-A instance (SMC invocation from SP to SPMC) to provide the IPA + entry point for other execution contexts. +- Exits through ``FFA_MSG_WAIT`` to indicate successful initialization or + ``FFA_ERROR`` in case of failure. + +Secondary cores boot-up +~~~~~~~~~~~~~~~~~~~~~~~ + +Once the system is started and NWd brought up, a secondary physical core is +woken up by the ``PSCI_CPU_ON`` service invocation. The TF-A SPD hook mechanism +calls into the SPMD on the newly woken up physical core. Then the SPMC is +entered at the secondary physical core entry point. + +In the current implementation, the first SP is resumed on the coresponding EC +(the virtual CPU which matches the physical core). The implication is that the +first SP must be a MP SP. + +In a linux based system, once secure and normal worlds are booted but prior to +a NWd FF-A driver has been loaded: + +- The first SP has initialized all its ECs in response to primary core boot up + (at system initialization) and secondary core boot up (as a result of linux + invoking PSCI_CPU_ON for all secondary cores). +- Other SPs have their first execution context initialized as a result of secure + world initialization on the primary boot core. Other ECs for those SPs have to + be run first through ffa_run to complete their initialization (which results + in the EC completing with FFA_MSG_WAIT). + +Refer to `Power management`_ for further details. + +Notifications +------------- + +The FF-A v1.1 specification `[1]`_ defines notifications as an asynchronous +communication mechanism with non-blocking semantics. It allows for one FF-A +endpoint to signal another for service provision, without hindering its current +progress. + +Hafnium currently supports 64 notifications. The IDs of each notification define +a position in a 64-bit bitmap. + +The signaling of notifications can interchangeably happen between NWd and SWd +FF-A endpoints. + +The SPMC is in charge of managing notifications from SPs to SPs, from SPs to +VMs, and from VMs to SPs. An hypervisor component would only manage +notifications from VMs to VMs. Given the SPMC has no visibility of the endpoints +deployed in NWd, the Hypervisor or OS kernel must invoke the interface +FFA_NOTIFICATION_BITMAP_CREATE to allocate the notifications bitmap per FF-A +endpoint in the NWd that supports it. + +A sender can signal notifications once the receiver has provided it with +permissions. Permissions are provided by invoking the interface +FFA_NOTIFICATION_BIND. + +Notifications are signaled by invoking FFA_NOTIFICATION_SET. Henceforth +they are considered to be in a pending sate. The receiver can retrieve its +pending notifications invoking FFA_NOTIFICATION_GET, which, from that moment, +are considered to be handled. + +Per the FF-A v1.1 spec, each FF-A endpoint must be associated with a scheduler +that is in charge of donating CPU cycles for notifications handling. The +FF-A driver calls FFA_NOTIFICATION_INFO_GET to retrieve the information about +which FF-A endpoints have pending notifications. The receiver scheduler is +called and informed by the FF-A driver, and it should allocate CPU cycles to the +receiver. + +There are two types of notifications supported: +- Global, which are targeted to a FF-A endpoint and can be handled within any of +its execution contexts, as determined by the scheduler of the system. +- Per-vCPU, which are targeted to a FF-A endpoint and to be handled within a +a specific execution context, as determined by the sender. + +The type of a notification is set when invoking FFA_NOTIFICATION_BIND to give +permissions to the sender. + +Notification signaling resorts to two interrupts: +- Schedule Receiver Interrupt: Non-secure physical interrupt to be handled by +the FF-A 'transport' driver within the receiver scheduler. At initialization +the SPMC (as suggested by the spec) configures a secure SGI, as non-secure, and +triggers it when there are pending notifications, and the respective receivers +need CPU cycles to handle them. +- Notifications Pending Interrupt: Virtual Interrupt to be handled by the +receiver of the notification. Set when there are pending notifications. For +per-vCPU the NPI is pended at the handling of FFA_NOTIFICATION_SET interface. + +The notifications receipt support is enabled in the partition FF-A manifest. + +The subsequent section provides more details about the each one of the +FF-A interfaces for notifications support. + +Mandatory interfaces +-------------------- + +The following interfaces are exposed to SPs: + +- ``FFA_VERSION`` +- ``FFA_FEATURES`` +- ``FFA_RX_RELEASE`` +- ``FFA_RXTX_MAP`` +- ``FFA_RXTX_UNMAP`` +- ``FFA_PARTITION_INFO_GET`` +- ``FFA_ID_GET`` +- ``FFA_MSG_WAIT`` +- ``FFA_MSG_SEND_DIRECT_REQ`` +- ``FFA_MSG_SEND_DIRECT_RESP`` +- ``FFA_MEM_DONATE`` +- ``FFA_MEM_LEND`` +- ``FFA_MEM_SHARE`` +- ``FFA_MEM_RETRIEVE_REQ`` +- ``FFA_MEM_RETRIEVE_RESP`` +- ``FFA_MEM_RELINQUISH`` +- ``FFA_MEM_RECLAIM`` + +As part of the support of FF-A v1.1, the following interfaces were added: + + - ``FFA_NOTIFICATION_BITMAP_CREATE`` + - ``FFA_NOTIFICATION_BITMAP_DESTROY`` + - ``FFA_NOTIFICATION_BIND`` + - ``FFA_NOTIFICATION_UNBIND`` + - ``FFA_NOTIFICATION_SET`` + - ``FFA_NOTIFICATION_GET`` + - ``FFA_NOTIFICATION_INFO_GET`` + - ``FFA_SPM_ID_GET`` + - ``FFA_SECONDARY_EP_REGISTER`` + +FFA_VERSION +~~~~~~~~~~~ + +``FFA_VERSION`` requires a *requested_version* parameter from the caller. +The returned value depends on the caller: + +- Hypervisor or OS kernel in NS-EL1/EL2: the SPMD returns the SPMC version + specified in the SPMC manifest. +- SP: the SPMC returns its own implemented version. +- SPMC at S-EL1/S-EL2: the SPMD returns its own implemented version. + +FFA_FEATURES +~~~~~~~~~~~~ + +FF-A features supported by the SPMC may be discovered by secure partitions at +boot (that is prior to NWd is booted) or run-time. + +The SPMC calling FFA_FEATURES at secure physical FF-A instance always get +FFA_SUCCESS from the SPMD. + +The request made by an Hypervisor or OS kernel is forwarded to the SPMC and +the response relayed back to the NWd. + +FFA_RXTX_MAP/FFA_RXTX_UNMAP +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When invoked from a secure partition FFA_RXTX_MAP maps the provided send and +receive buffers described by their IPAs to the SP EL1&0 Stage-2 translation +regime as secure buffers in the MMU descriptors. + +When invoked from the Hypervisor or OS kernel, the buffers are mapped into the +SPMC EL2 Stage-1 translation regime and marked as NS buffers in the MMU +descriptors. + +The FFA_RXTX_UNMAP unmaps the RX/TX pair from the translation regime of the +caller, either it being the Hypervisor or OS kernel, as well as a secure +partition. + +FFA_PARTITION_INFO_GET +~~~~~~~~~~~~~~~~~~~~~~ + +Partition info get call can originate: + +- from SP to SPMC +- from Hypervisor or OS kernel to SPMC. The request is relayed by the SPMD. + +FFA_ID_GET +~~~~~~~~~~ + +The FF-A id space is split into a non-secure space and secure space: + +- FF-A ID with bit 15 clear relates to VMs. +- FF-A ID with bit 15 set related to SPs. +- FF-A IDs 0, 0xffff, 0x8000 are assigned respectively to the Hypervisor, SPMD + and SPMC. + +The SPMD returns: + +- The default zero value on invocation from the Hypervisor. +- The ``spmc_id`` value specified in the SPMC manifest on invocation from + the SPMC (see `SPMC manifest`_) + +This convention helps the SPMC to determine the origin and destination worlds in +an FF-A ABI invocation. In particular the SPMC shall filter unauthorized +transactions in its world switch routine. It must not be permitted for a VM to +use a secure FF-A ID as origin world by spoofing: + +- A VM-to-SP direct request/response shall set the origin world to be non-secure + (FF-A ID bit 15 clear) and destination world to be secure (FF-A ID bit 15 + set). +- Similarly, an SP-to-SP direct request/response shall set the FF-A ID bit 15 + for both origin and destination IDs. + +An incoming direct message request arriving at SPMD from NWd is forwarded to +SPMC without a specific check. The SPMC is resumed through eret and "knows" the +message is coming from normal world in this specific code path. Thus the origin +endpoint ID must be checked by SPMC for being a normal world ID. + +An SP sending a direct message request must have bit 15 set in its origin +endpoint ID and this can be checked by the SPMC when the SP invokes the ABI. + +The SPMC shall reject the direct message if the claimed world in origin endpoint +ID is not consistent: + +- It is either forwarded by SPMD and thus origin endpoint ID must be a "normal + world ID", +- or initiated by an SP and thus origin endpoint ID must be a "secure world ID". + + +FFA_MSG_SEND_DIRECT_REQ/FFA_MSG_SEND_DIRECT_RESP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is a mandatory interface for secure partitions consisting in direct request +and responses with the following rules: + +- An SP can send a direct request to another SP. +- An SP can receive a direct request from another SP. +- An SP can send a direct response to another SP. +- An SP cannot send a direct request to an Hypervisor or OS kernel. +- An Hypervisor or OS kernel can send a direct request to an SP. +- An SP can send a direct response to an Hypervisor or OS kernel. + +FFA_NOTIFICATION_BITMAP_CREATE/FFA_NOTIFICATION_BITMAP_DESTROY +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The secure partitions notifications bitmap are statically allocated by the SPMC. +Hence, this interface is not to be issued by secure partitions. + +At initialization, the SPMC is not aware of VMs/partitions deployed in the +normal world. Hence, the Hypervisor or OS kernel must use both ABIs for SPMC +to be prepared to handle notifications for the provided VM ID. + +FFA_NOTIFICATION_BIND/FFA_NOTIFICATION_UNBIND +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Pair of interfaces to manage permissions to signal notifications. Prior to +handling notifications, an FF-A endpoint must allow a given sender to signal a +bitmap of notifications. + +If the receiver doesn't have notification support enabled in its FF-A manifest, +it won't be able to bind notifications, hence forbidding it to receive any +notifications. + +FFA_NOTIFICATION_SET/FFA_NOTIFICATION_GET +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the notifications set are per-vCPU, the NPI interrupt is set as pending +for a given receiver partition. + +The FFA_NOTIFICATION_GET will retrieve all pending global notifications and all +pending per-vCPU notifications targeted to the current vCPU. + +Hafnium keeps the global counting of the pending notifications, which is +incremented and decremented at the handling of FFA_NOTIFICATION_SET and +FFA_NOTIFICATION_GET, respectively. If the counter reaches zero, prior to SPMC +triggering the SRI, it won't be triggered. + +FFA_NOTIFICATION_INFO_GET +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Hafnium keeps the global counting of pending notifications whose info has been +retrieved by this interface. The counting is incremented and decremented at the +handling of FFA_NOTIFICATION_INFO_GET and FFA_NOTIFICATION_GET, respectively. +It also tracks the notifications whose info has been retrieved individually, +such that it avoids duplicating returned information for subsequent calls to +FFA_NOTIFICATION_INFO_GET. For each notification, this state information is +reset when receiver called FFA_NOTIFICATION_GET to retrieve them. + +FFA_SPM_ID_GET +~~~~~~~~~~~~~~ + +Returns the FF-A ID allocated to the SPM component (which includes SPMC + SPMD). +At initialization, the SPMC queries the SPMD for the SPM ID, using this +same interface, and saves it. + +The call emitted at NS and secure physical FF-A instances returns the SPM ID +specified in the SPMC manifest. + +Secure partitions call this interface at the virtual instance, to which the SPMC +shall return the priorly retrieved SPM ID. + +The Hypervisor or OS kernel can issue an FFA_SPM_ID_GET call handled by the +SPMD, which returns the SPM ID. + +FFA_SECONDARY_EP_REGISTER +~~~~~~~~~~~~~~~~~~~~~~~~~ + +When the SPMC boots, all secure partitions are initialized on their primary +Execution Context. + +The interface FFA_SECONDARY_EP_REGISTER is to be used by a secure partitions +from its first execution context, to provide the entry point address for +secondary execution contexts. + +A secondary EC is first resumed either upon invocation of PSCI_CPU_ON from +the NWd or by invocation of FFA_RUN. + +SPMC-SPMD direct requests/responses +----------------------------------- + +Implementation-defined FF-A IDs are allocated to the SPMC and SPMD. +Using those IDs in source/destination fields of a direct request/response +permits SPMD to SPMC communication and either way. + +- SPMC to SPMD direct request/response uses SMC conduit. +- SPMD to SPMC direct request/response uses ERET conduit. + +PE MMU configuration +-------------------- + +With secure virtualization enabled, two IPA spaces are output from the secure +EL1&0 Stage-1 translation (secure and non-secure). The EL1&0 Stage-2 translation +hardware is fed by: + +- A single secure IPA space when the SP EL1&0 Stage-1 MMU is disabled. +- Two IPA spaces (secure and non-secure) when the SP EL1&0 Stage-1 MMU is + enabled. + +``VTCR_EL2`` and ``VSTCR_EL2`` provide configuration bits for controlling the +NS/S IPA translations. +``VSTCR_EL2.SW`` = 0, ``VSTCR_EL2.SA`` = 0,``VTCR_EL2.NSW`` = 0, ``VTCR_EL2.NSA`` = 1: + +- Stage-2 translations for the NS IPA space access the NS PA space. +- Stage-2 translation table walks for the NS IPA space are to the secure PA space. + +Secure and non-secure IPA regions use the same set of Stage-2 page tables within +a SP. + +Interrupt management +-------------------- + +GIC ownership +~~~~~~~~~~~~~ + +The SPMC owns the GIC configuration. Secure and non-secure interrupts are +trapped at S-EL2. The SPMC manages interrupt resources and allocates interrupt +IDs based on SP manifests. The SPMC acknowledges physical interrupts and injects +virtual interrupts by setting the use of vIRQ/vFIQ bits before resuming a SP. + +Non-secure interrupt handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The following illustrate the scenarios of non secure physical interrupts trapped +by the SPMC: + +- The SP handles a managed exit operation: + +.. image:: ../resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png + +- The SP is pre-empted without managed exit: + +.. image:: ../resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png + +Secure interrupt handling +------------------------- + +This section documents the support implemented for secure interrupt handling in +SPMC as per the guidance provided by FF-A v1.1 Beta0 specification. +The following assumptions are made about the system configuration: + + - In the current implementation, S-EL1 SPs are expected to use the para + virtualized ABIs for interrupt management rather than accessing virtual GIC + interface. + - Unless explicitly stated otherwise, this support is applicable only for + S-EL1 SPs managed by SPMC. + - Secure interrupts are configured as G1S or G0 interrupts. + - All physical interrupts are routed to SPMC when running a secure partition + execution context. + +A physical secure interrupt could preempt normal world execution. Moreover, when +the execution is in secure world, it is highly likely that the target of a +secure interrupt is not the currently running execution context of an SP. It +could be targeted to another FF-A component. Consequently, secure interrupt +management depends on the state of the target execution context of the SP that +is responsible for handling the interrupt. Hence, the spec provides guidance on +how to signal start and completion of secure interrupt handling as discussed in +further sections. + +Secure interrupt signaling mechanisms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Signaling refers to the mechanisms used by SPMC to indicate to the SP execution +context that it has a pending virtual interrupt and to further run the SP +execution context, such that it can handle the virtual interrupt. SPMC uses +either the FFA_INTERRUPT interface with ERET conduit or vIRQ signal for signaling +to S-EL1 SPs. When normal world execution is preempted by a secure interrupt, +the SPMD uses the FFA_INTERRUPT ABI with ERET conduit to signal interrupt to SPMC +running in S-EL2. + ++-----------+---------+---------------+---------------------------------------+ +| SP State | Conduit | Interface and | Description | +| | | parameters | | ++-----------+---------+---------------+---------------------------------------+ +| WAITING | ERET, | FFA_INTERRUPT,| SPMC signals to SP the ID of pending | +| | vIRQ | Interrupt ID | interrupt. It pends vIRQ signal and | +| | | | resumes execution context of SP | +| | | | through ERET. | ++-----------+---------+---------------+---------------------------------------+ +| BLOCKED | ERET, | FFA_INTERRUPT | SPMC signals to SP that an interrupt | +| | vIRQ | | is pending. It pends vIRQ signal and | +| | | | resumes execution context of SP | +| | | | through ERET. | ++-----------+---------+---------------+---------------------------------------+ +| PREEMPTED | vIRQ | NA | SPMC pends the vIRQ signal but does | +| | | | not resume execution context of SP. | ++-----------+---------+---------------+---------------------------------------+ +| RUNNING | ERET, | NA | SPMC pends the vIRQ signal and resumes| +| | vIRQ | | execution context of SP through ERET. | ++-----------+---------+---------------+---------------------------------------+ + +Secure interrupt completion mechanisms +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SP signals secure interrupt handling completion to the SPMC through the +following mechanisms: + + - ``FFA_MSG_WAIT`` ABI if it was in WAITING state. + - ``FFA_RUN`` ABI if its was in BLOCKED state. + +In the current implementation, S-EL1 SPs use para-virtualized HVC interface +implemented by SPMC to perform priority drop and interrupt deactivation (we +assume EOImode = 0, i.e. priority drop and deactivation are done together). + +If normal world execution was preempted by secure interrupt, SPMC uses +FFA_NORMAL_WORLD_RESUME ABI to indicate completion of secure interrupt handling +and further return execution to normal world. If the current SP execution +context was preempted by a secure interrupt to be handled by execution context +of target SP, SPMC resumes current SP after signal completion by target SP +execution context. + +An action is broadly a set of steps taken by the SPMC in response to a physical +interrupt. In order to simplify the design, the current version of secure +interrupt management support in SPMC (Hafnium) does not fully implement the +Scheduling models and Partition runtime models. However, the current +implementation loosely maps to the following actions that are legally allowed +by the specification. Please refer to the Table 8.4 in the spec for further +description of actions. The action specified for a type of interrupt when the +SP is in the message processing running state cannot be less permissive than the +action specified for the same type of interrupt when the SP is in the interrupt +handling running state. + ++--------------------+--------------------+------------+-------------+ +| Runtime Model | NS-Int | Self S-Int | Other S-Int | ++--------------------+--------------------+------------+-------------+ +| Message Processing | Signalable with ME | Signalable | Signalable | ++--------------------+--------------------+------------+-------------+ +| Interrupt Handling | Queued | Queued | Queued | ++--------------------+--------------------+------------+-------------+ + +Abbreviations: + + - NS-Int: A Non-secure physical interrupt. It requires a switch to the Normal + world to be handled. + - Other S-Int: A secure physical interrupt targeted to an SP different from + the one that is currently running. + - Self S-Int: A secure physical interrupt targeted to the SP that is currently + running. + +The following figure describes interrupt handling flow when secure interrupt +triggers while in normal world: + +.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-nwd.png + +A brief description of the events: + + - 1) Secure interrupt triggers while normal world is running. + - 2) FIQ gets trapped to EL3. + - 3) SPMD signals secure interrupt to SPMC at S-EL2 using FFA_INTERRUPT ABI. + - 4) SPMC identifies target vCPU of SP and injects virtual interrupt (pends + vIRQ). + - 5) Since SP1 vCPU is in WAITING state, SPMC signals using FFA_INTERRUPT with + interrupt id as argument and resume it using ERET. + - 6) Execution traps to vIRQ handler in SP1 provided that interrupt is not + masked i.e., PSTATE.I = 0 + - 7) SP1 services the interrupt and invokes the de-activation HVC call. + - 8) SPMC does internal state management and further de-activates the physical + interrupt and resumes SP vCPU. + - 9) SP performs secure interrupt completion through FFA_MSG_WAIT ABI. + - 10) SPMC returns control to EL3 using FFA_NORMAL_WORLD_RESUME. + - 11) EL3 resumes normal world execution. + +The following figure describes interrupt handling flow when secure interrupt +triggers while in secure world: + +.. image:: ../resources/diagrams/ffa-secure-interrupt-handling-swd.png + +A brief description of the events: + + - 1) Secure interrupt triggers while SP2 is running and SP1 is blocked. + - 2) Gets trapped to SPMC as IRQ. + - 3) SPMC finds the target vCPU of secure partition responsible for handling + this secure interrupt. In this scenario, it is SP1. + - 4) SPMC pends vIRQ for SP1 and signals through FFA_INTERRUPT interface. + SPMC further resumes SP1 through ERET conduit. + - 5) Execution traps to vIRQ handler in SP1 provided that interrupt is not + masked i.e., PSTATE.I = 0 + - 6) SP1 services the secure interrupt and invokes the de-activation HVC call. + - 7) SPMC does internal state management, de-activates the physical interrupt + and resumes SP1 vCPU. + - 8) Assuming SP1 is in BLOCKED state, SP1 performs secure interrupt completion + through FFA_RUN ABI. + - 9) SPMC resumes the pre-empted vCPU of SP2. + + +Power management +---------------- + +In platforms with or without secure virtualization: + +- The NWd owns the platform PM policy. +- The Hypervisor or OS kernel is the component initiating PSCI service calls. +- The EL3 PSCI library is in charge of the PM coordination and control + (eventually writing to platform registers). +- While coordinating PM events, the PSCI library calls backs into the Secure + Payload Dispatcher for events the latter has statically registered to. + +When using the SPMD as a Secure Payload Dispatcher: + +- A power management event is relayed through the SPD hook to the SPMC. +- In the current implementation only cpu on (svc_on_finish) and cpu off + (svc_off) hooks are registered. +- The behavior for the cpu on event is described in `Secondary cores boot-up`_. + The SPMC is entered through its secondary physical core entry point. +- The cpu off event occurs when the NWd calls PSCI_CPU_OFF. The method by which + the PM event is conveyed to the SPMC is implementation-defined in context of + FF-A v1.0 (`SPMC-SPMD direct requests/responses`_). It consists in a SPMD-to-SPMC + direct request/response conveying the PM event details and SPMC response. + The SPMD performs a synchronous entry into the SPMC. The SPMC is entered and + updates its internal state to reflect the physical core is being turned off. + In the current implementation no SP is resumed as a consequence. This behavior + ensures a minimal support for CPU hotplug e.g. when initiated by the NWd linux + userspace. + +SMMUv3 support in Hafnium +========================= + +An SMMU is analogous to an MMU in a CPU. It performs address translations for +Direct Memory Access (DMA) requests from system I/O devices. +The responsibilities of an SMMU include: + +- Translation: Incoming DMA requests are translated from bus address space to + system physical address space using translation tables compliant to + Armv8/Armv7 VMSA descriptor format. +- Protection: An I/O device can be prohibited from read, write access to a + memory region or allowed. +- Isolation: Traffic from each individial device can be independently managed. + The devices are differentiated from each other using unique translation + tables. + +The following diagram illustrates a typical SMMU IP integrated in a SoC with +several I/O devices along with Interconnect and Memory system. + +.. image:: ../resources/diagrams/MMU-600.png + +SMMU has several versions including SMMUv1, SMMUv2 and SMMUv3. Hafnium provides +support for SMMUv3 driver in both normal and secure world. A brief introduction +of SMMUv3 functionality and the corresponding software support in Hafnium is +provided here. + +SMMUv3 features +--------------- + +- SMMUv3 provides Stage1, Stage2 translation as well as nested (Stage1 + Stage2) + translation support. It can either bypass or abort incoming translations as + well. +- Traffic (memory transactions) from each upstream I/O peripheral device, + referred to as Stream, can be independently managed using a combination of + several memory based configuration structures. This allows the SMMUv3 to + support a large number of streams with each stream assigned to a unique + translation context. +- Support for Armv8.1 VMSA where the SMMU shares the translation tables with + a Processing Element. AArch32(LPAE) and AArch64 translation table format + are supported by SMMUv3. +- SMMUv3 offers non-secure stream support with secure stream support being + optional. Logically, SMMUv3 behaves as if there is an indepdendent SMMU + instance for secure and non-secure stream support. +- It also supports sub-streams to differentiate traffic from a virtualized + peripheral associated with a VM/SP. +- Additionally, SMMUv3.2 provides support for PEs implementing Armv8.4-A + extensions. Consequently, SPM depends on Secure EL2 support in SMMUv3.2 + for providing Secure Stage2 translation support to upstream peripheral + devices. + +SMMUv3 Programming Interfaces +----------------------------- + +SMMUv3 has three software interfaces that are used by the Hafnium driver to +configure the behaviour of SMMUv3 and manage the streams. + +- Memory based data strutures that provide unique translation context for + each stream. +- Memory based circular buffers for command queue and event queue. +- A large number of SMMU configuration registers that are memory mapped during + boot time by Hafnium driver. Except a few registers, all configuration + registers have independent secure and non-secure versions to configure the + behaviour of SMMUv3 for translation of secure and non-secure streams + respectively. + +Peripheral device manifest +-------------------------- + +Currently, SMMUv3 driver in Hafnium only supports dependent peripheral devices. +These devices are dependent on PE endpoint to initiate and receive memory +management transactions on their behalf. The acccess to the MMIO regions of +any such device is assigned to the endpoint during boot. Moreover, SMMUv3 driver +uses the same stage 2 translations for the device as those used by partition +manager on behalf of the PE endpoint. This ensures that the peripheral device +has the same visibility of the physical address space as the endpoint. The +device node of the corresponding partition manifest (refer to `[1]`_ section 3.2 +) must specify these additional properties for each peripheral device in the +system : + +- smmu-id: This field helps to identify the SMMU instance that this device is + upstream of. +- stream-ids: List of stream IDs assigned to this device. + +.. code:: shell + + smmuv3-testengine { + base-address = <0x00000000 0x2bfe0000>; + pages-count = <32>; + attributes = <0x3>; + smmu-id = <0>; + stream-ids = <0x0 0x1>; + interrupts = <0x2 0x3>, <0x4 0x5>; + exclusive-access; + }; + +SMMUv3 driver limitations +------------------------- + +The primary design goal for the Hafnium SMMU driver is to support secure +streams. + +- Currently, the driver only supports Stage2 translations. No support for + Stage1 or nested translations. +- Supports only AArch64 translation format. +- No support for features such as PCI Express (PASIDs, ATS, PRI), MSI, RAS, + Fault handling, Performance Monitor Extensions, Event Handling, MPAM. +- No support for independent peripheral devices. + +S-EL0 Partition support +========================= +The SPMC (Hafnium) has limited capability to run S-EL0 FF-A partitions using +FEAT_VHE (mandatory with ARMv8.1 in non-secure state, and in secure world +with ARMv8.4 and FEAT_SEL2). + +S-EL0 partitions are useful for simple partitions that don't require full +Trusted OS functionality. It is also useful to reduce jitter and cycle +stealing from normal world since they are more lightweight than VMs. + +S-EL0 partitions are presented, loaded and initialized the same as S-EL1 VMs by +the SPMC. They are differentiated primarily by the 'exception-level' property +and the 'execution-ctx-count' property in the SP manifest. They are host apps +under the single EL2&0 Stage-1 translation regime controlled by the SPMC and +call into the SPMC through SVCs as opposed to HVCs and SMCs. These partitions +can use FF-A defined services (FFA_MEM_PERM_*) to update or change permissions +for memory regions. + +S-EL0 partitions are required by the FF-A specification to be UP endpoints, +capable of migrating, and the SPMC enforces this requirement. The SPMC allows +a S-EL0 partition to accept a direct message from secure world and normal world, +and generate direct responses to them. + +Memory sharing between and with S-EL0 partitions is supported. +Indirect messaging, Interrupt handling and Notifications are not supported with +S-EL0 partitions and is work in progress, planned for future releases. +All S-EL0 partitions must use AArch64. AArch32 S-EL0 partitions are not +supported. + + +References +========== + +.. _[1]: + +[1] `Arm Firmware Framework for Arm A-profile `__ + +.. _[2]: + +[2] :ref:`Secure Partition Manager using MM interface` + +.. _[3]: + +[3] `Trusted Boot Board Requirements +Client `__ + +.. _[4]: + +[4] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/lib/el3_runtime/aarch64/context.S#n45 + +.. _[5]: + +[5] https://git.trustedfirmware.org/TF-A/tf-a-tests.git/tree/spm/cactus/plat/arm/fvp/fdts/cactus.dts + +.. _[6]: + +[6] https://trustedfirmware-a.readthedocs.io/en/latest/components/ffa-manifest-binding.html + +.. _[7]: + +[7] https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts + +.. _[8]: + +[8] https://lists.trustedfirmware.org/pipermail/tf-a/2020-February/000296.html + +.. _[9]: + +[9] https://trustedfirmware-a.readthedocs.io/en/latest/design/firmware-design.html#dynamic-configuration-during-cold-boot + +-------------- + +*Copyright (c) 2020-2022, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/components/spd/index.rst b/arm-trusted-firmware/docs/components/spd/index.rst new file mode 100644 index 0000000..25d0124 --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/index.rst @@ -0,0 +1,10 @@ +Secure Payload Dispatcher (SPD) +=============================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + optee-dispatcher + tlk-dispatcher + trusty-dispatcher diff --git a/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst new file mode 100644 index 0000000..63baccc --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst @@ -0,0 +1,14 @@ +OP-TEE Dispatcher +================= + +`OP-TEE OS`_ is a Trusted OS running as Secure EL1. + +To build and execute OP-TEE follow the instructions at +`OP-TEE build.git`_ + +-------------- + +*Copyright (c) 2014-2018, Arm Limited and Contributors. All rights reserved.* + +.. _OP-TEE OS: https://github.com/OP-TEE/build +.. _OP-TEE build.git: https://github.com/OP-TEE/build diff --git a/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst new file mode 100644 index 0000000..a6c658c --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst @@ -0,0 +1,76 @@ +Trusted Little Kernel (TLK) Dispatcher +====================================== + +TLK dispatcher (TLK-D) adds support for NVIDIA's Trusted Little Kernel (TLK) +to work with Trusted Firmware-A (TF-A). TLK-D can be compiled by including it +in the platform's makefile. TLK is primarily meant to work with Tegra SoCs, +so while TF-A only supports TLK on Tegra, the dispatcher code can only be +compiled for other platforms. + +In order to compile TLK-D, we need a BL32 image to be present. Since, TLKD +just needs to compile, any BL32 image would do. To use TLK as the BL32, please +refer to the "Build TLK" section. + +Once a BL32 is ready, TLKD can be included in the image by adding "SPD=tlkd" +to the build command. + +Trusted Little Kernel (TLK) +--------------------------- + +TLK is a Trusted OS running as Secure EL1. It is a Free Open Source Software +(FOSS) release of the NVIDIA® Trusted Little Kernel (TLK) technology, which +extends technology made available with the development of the Little Kernel (LK). +You can download the LK modular embedded preemptive kernel for use on Arm, +x86, and AVR32 systems from https://github.com/travisg/lk + +NVIDIA implemented its Trusted Little Kernel (TLK) technology, designed as a +free and open-source trusted execution environment (OTE). + +TLK features include: + +• Small, pre-emptive kernel +• Supports multi-threading, IPCs, and thread scheduling +• Added TrustZone features +• Added Secure Storage +• Under MIT/FreeBSD license + +NVIDIA extensions to Little Kernel (LK) include: + +• User mode +• Address-space separation for TAs +• TLK Client Application (CA) library +• TLK TA library +• Crypto library (encrypt/decrypt, key handling) via OpenSSL +• Linux kernel driver +• Cortex A9/A15 support +• Power Management +• TrustZone memory carve-out (reconfigurable) +• Page table management +• Debugging support over UART (USB planned) + +TLK is hosted by NVIDIA on http://nv-tegra.nvidia.com under the +3rdparty/ote\_partner/tlk.git repository. Detailed information about +TLK and OTE can be found in the Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf +manual located under the "documentation" directory\_. + +Build TLK +--------- + +To build and execute TLK, follow the instructions from "Building a TLK Device" +section from Tegra\_BSP\_for\_Android\_TLK\_FOSS\_Reference.pdf manual. + +Input parameters to TLK +----------------------- + +TLK expects the TZDRAM size and a structure containing the boot arguments. BL2 +passes this information to the EL3 software as members of the bl32\_ep\_info +struct, where bl32\_ep\_info is part of bl31\_params\_t (passed by BL2 in X0) + +Example +~~~~~~~ + +:: + + bl32_ep_info->args.arg0 = TZDRAM size available for BL32 + bl32_ep_info->args.arg1 = unused (used only on Armv7-A) + bl32_ep_info->args.arg2 = pointer to boot args diff --git a/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst b/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst new file mode 100644 index 0000000..a3cb829 --- /dev/null +++ b/arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst @@ -0,0 +1,32 @@ +Trusty Dispatcher +================= + +Trusty is a a set of software components, supporting a Trusted Execution +Environment (TEE) on mobile devices, published and maintained by Google. + +Detailed information and build instructions can be found on the Android +Open Source Project (AOSP) webpage for Trusty hosted at +https://source.android.com/security/trusty + +Boot parameters +--------------- + +Custom boot parameters can be passed to Trusty by providing a platform +specific function: + +.. code:: c + + void plat_trusty_set_boot_args(aapcs64_params_t *args) + +If this function is provided ``args->arg0`` must be set to the memory +size allocated to trusty. If the platform does not provide this +function, but defines ``TSP_SEC_MEM_SIZE``, a default implementation +will pass the memory size from ``TSP_SEC_MEM_SIZE``. ``args->arg1`` +can be set to a platform specific parameter block, and ``args->arg2`` +should then be set to the size of that block. + +Supported platforms +------------------- + +Out of all the platforms supported by Trusted Firmware-A, Trusty is only +verified and supported by NVIDIA's Tegra SoCs. diff --git a/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst b/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst new file mode 100644 index 0000000..cac32f5 --- /dev/null +++ b/arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst @@ -0,0 +1,442 @@ +Translation (XLAT) Tables Library +================================= + +This document describes the design of the translation tables library (version 2) +used by Trusted Firmware-A (TF-A). This library provides APIs to create page +tables based on a description of the memory layout, as well as setting up system +registers related to the Memory Management Unit (MMU) and performing the +required Translation Lookaside Buffer (TLB) maintenance operations. + +More specifically, some use cases that this library aims to support are: + +#. Statically allocate translation tables and populate them (at run-time) based + upon a description of the memory layout. The memory layout is typically + provided by the platform port as a list of memory regions; + +#. Support for generating translation tables pertaining to a different + translation regime than the exception level the library code is executing at; + +#. Support for dynamic mapping and unmapping of regions, even while the MMU is + on. This can be used to temporarily map some memory regions and unmap them + later on when no longer needed; + +#. Support for non-identity virtual to physical mappings to compress the virtual + address space; + +#. Support for changing memory attributes of memory regions at run-time. + + +About version 1, version 2 and MPU libraries +-------------------------------------------- + +This document focuses on version 2 of the library, whose sources are available +in the ``lib/xlat_tables_v2`` directory. Version 1 of the library can still be +found in ``lib/xlat_tables`` directory but it is less flexible and doesn't +support dynamic mapping. ``lib/xlat_mpu``, which configures Arm's MPU +equivalently, is also addressed here. The ``lib/xlat_mpu`` is experimental, +meaning that its API may change. It currently strives for consistency and +code-reuse with xlat_tables_v2. Future versions may be more MPU-specific (e.g., +removing all mentions of virtual addresses). Although potential bug fixes will +be applied to all versions of the xlat_* libs, future feature enhancements will +focus on version 2 and might not be back-ported to version 1 and MPU versions. +Therefore, it is recommended to use version 2, especially for new platform +ports (unless the platform uses an MPU). + +However, please note that version 2 and the MPU version are still in active +development and is not considered stable yet. Hence, compatibility breaks might +be introduced. + +From this point onwards, this document will implicitly refer to version 2 of the +library, unless stated otherwise. + + +Design concepts and interfaces +------------------------------ + +This section presents some of the key concepts and data structures used in the +translation tables library. + +`mmap` regions +~~~~~~~~~~~~~~ + +An ``mmap_region`` is an abstract, concise way to represent a memory region to +map. It is one of the key interfaces to the library. It is identified by: + +- its physical base address; +- its virtual base address; +- its size; +- its attributes; +- its mapping granularity (optional). + +See the ``struct mmap_region`` type in ``xlat_tables_v2.h``. + +The user usually provides a list of such mmap regions to map and lets the +library transpose that in a set of translation tables. As a result, the library +might create new translation tables, update or split existing ones. + +The region attributes specify the type of memory (for example device or cached +normal memory) as well as the memory access permissions (read-only or +read-write, executable or not, secure or non-secure, and so on). In the case of +the EL1&0 translation regime, the attributes also specify whether the region is +a User region (EL0) or Privileged region (EL1). See the ``MT_xxx`` definitions +in ``xlat_tables_v2.h``. Note that for the EL1&0 translation regime the Execute +Never attribute is set simultaneously for both EL1 and EL0. + +The granularity controls the translation table level to go down to when mapping +the region. For example, assuming the MMU has been configured to use a 4KB +granule size, the library might map a 2MB memory region using either of the two +following options: + +- using a single level-2 translation table entry; +- using a level-2 intermediate entry to a level-3 translation table (which + contains 512 entries, each mapping 4KB). + +The first solution potentially requires less translation tables, hence +potentially less memory. However, if part of this 2MB region is later remapped +with different memory attributes, the library might need to split the existing +page tables to refine the mappings. If a single level-2 entry has been used +here, a level-3 table will need to be allocated on the fly and the level-2 +modified to point to this new level-3 table. This has a performance cost at +run-time. + +If the user knows upfront that such a remapping operation is likely to happen +then they might enforce a 4KB mapping granularity for this 2MB region from the +beginning; remapping some of these 4KB pages on the fly then becomes a +lightweight operation. + +The region's granularity is an optional field; if it is not specified the +library will choose the mapping granularity for this region as it sees fit (more +details can be found in `The memory mapping algorithm`_ section below). + +The MPU library also uses ``struct mmap_region`` to specify translations, but +the MPU's translations are limited to specification of valid addresses and +access permissions. If the requested virtual and physical addresses mismatch +the system will panic. Being register-based for deterministic memory-reference +timing, the MPU hardware does not involve memory-resident translation tables. + +Currently, the MPU library is also limited to MPU translation at EL2 with no +MMU translation at other ELs. These limitations, however, are expected to be +overcome in future library versions. + +Translation Context +~~~~~~~~~~~~~~~~~~~ + +The library can create or modify translation tables pertaining to a different +translation regime than the exception level the library code is executing at. +For example, the library might be used by EL3 software (for instance BL31) to +create translation tables pertaining to the S-EL1&0 translation regime. + +This flexibility comes from the use of *translation contexts*. A *translation +context* constitutes the superset of information used by the library to track +the status of a set of translation tables for a given translation regime. + +The library internally allocates a default translation context, which pertains +to the translation regime of the current exception level. Additional contexts +may be explicitly allocated and initialized using the +``REGISTER_XLAT_CONTEXT()`` macro. Separate APIs are provided to act either on +the default translation context or on an alternative one. + +To register a translation context, the user must provide the library with the +following information: + +* A name. + + The resulting translation context variable will be called after this name, to + which ``_xlat_ctx`` is appended. For example, if the macro name parameter is + ``foo``, the context variable name will be ``foo_xlat_ctx``. + +* The maximum number of `mmap` regions to map. + + Should account for both static and dynamic regions, if applicable. + +* The number of sub-translation tables to allocate. + + Number of translation tables to statically allocate for this context, + excluding the initial lookup level translation table, which is always + allocated. For example, if the initial lookup level is 1, this parameter would + specify the number of level-2 and level-3 translation tables to pre-allocate + for this context. + +* The size of the virtual address space. + + Size in bytes of the virtual address space to map using this context. This + will incidentally determine the number of entries in the initial lookup level + translation table : the library will allocate as many entries as is required + to map the entire virtual address space. + +* The size of the physical address space. + + Size in bytes of the physical address space to map using this context. + +The default translation context is internally initialized using information +coming (for the most part) from platform-specific defines: + +- name: hard-coded to ``tf`` ; hence the name of the default context variable is + ``tf_xlat_ctx``; +- number of `mmap` regions: ``MAX_MMAP_REGIONS``; +- number of sub-translation tables: ``MAX_XLAT_TABLES``; +- size of the virtual address space: ``PLAT_VIRT_ADDR_SPACE_SIZE``; +- size of the physical address space: ``PLAT_PHY_ADDR_SPACE_SIZE``. + +Please refer to the :ref:`Porting Guide` for more details about these macros. + + +Static and dynamic memory regions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library optionally supports dynamic memory mapping. This feature may be +enabled using the ``PLAT_XLAT_TABLES_DYNAMIC`` platform build flag. + +When dynamic memory mapping is enabled, the library categorises mmap regions as +*static* or *dynamic*. + +- *Static regions* are fixed for the lifetime of the system. They can only be + added early on, before the translation tables are created and populated. They + cannot be removed afterwards. + +- *Dynamic regions* can be added or removed any time. + +When the dynamic memory mapping feature is disabled, only static regions exist. + +The dynamic memory mapping feature may be used to map and unmap transient memory +areas. This is useful when the user needs to access some memory for a fixed +period of time, after which the memory may be discarded and reclaimed. For +example, a memory region that is only required at boot time while the system is +initializing, or to temporarily share a memory buffer between the normal world +and trusted world. Note that it is up to the caller to ensure that these regions +are not accessed concurrently while the regions are being added or removed. + +Although this feature provides some level of dynamic memory allocation, this +does not allow dynamically allocating an arbitrary amount of memory at an +arbitrary memory location. The user is still required to declare at compile-time +the limits of these allocations ; the library will deny any mapping request that +does not fit within this pre-allocated pool of memory. + + +Library APIs +------------ + +The external APIs exposed by this library are declared and documented in the +``xlat_tables_v2.h`` header file. This should be the reference point for +getting information about the usage of the different APIs this library +provides. This section just provides some extra details and clarifications. + +Although the ``mmap_region`` structure is a publicly visible type, it is not +recommended to populate these structures by hand. Instead, wherever APIs expect +function arguments of type ``mmap_region_t``, these should be constructed using +the ``MAP_REGION*()`` family of helper macros. This is to limit the risk of +compatibility breaks, should the ``mmap_region`` structure type evolve in the +future. + +The ``MAP_REGION()`` and ``MAP_REGION_FLAT()`` macros do not allow specifying a +mapping granularity, which leaves the library implementation free to choose +it. However, in cases where a specific granularity is required, the +``MAP_REGION2()`` macro might be used instead. Using ``MAP_REGION_FLAT()`` only +to define regions for the MPU library is strongly recommended. + +As explained earlier in this document, when the dynamic mapping feature is +disabled, there is no notion of dynamic regions. Conceptually, there are only +static regions. For this reason (and to retain backward compatibility with the +version 1 of the library), the APIs that map static regions do not embed the +word *static* in their functions names (for example ``mmap_add_region()``), in +contrast with the dynamic regions APIs (for example +``mmap_add_dynamic_region()``). + +Although the definition of static and dynamic regions is not based on the state +of the MMU, the two are still related in some way. Static regions can only be +added before ``init_xlat_tables()`` is called and ``init_xlat_tables()`` must be +called while the MMU is still off. As a result, static regions cannot be added +once the MMU has been enabled. Dynamic regions can be added with the MMU on or +off. In practice, the usual call flow would look like this: + +#. The MMU is initially off. + +#. Add some static regions, add some dynamic regions. + +#. Initialize translation tables based on the list of mmap regions (using one of + the ``init_xlat_tables*()`` APIs). + +#. At this point, it is no longer possible to add static regions. Dynamic + regions can still be added or removed. + +#. Enable the MMU. + +#. Dynamic regions can continue to be added or removed. + +Because static regions are added early on at boot time and are all in the +control of the platform initialization code, the ``mmap_add*()`` family of APIs +are not expected to fail. They do not return any error code. + +Nonetheless, these APIs will check upfront whether the region can be +successfully added before updating the translation context structure. If the +library detects that there is insufficient memory to meet the request, or that +the new region will overlap another one in an invalid way, or if any other +unexpected error is encountered, they will print an error message on the UART. +Additionally, when asserts are enabled (typically in debug builds), an assertion +will be triggered. Otherwise, the function call will just return straight away, +without adding the offending memory region. + + +Library limitations +------------------- + +Dynamic regions are not allowed to overlap each other. Static regions are +allowed to overlap as long as one of them is fully contained inside the other +one. This is allowed for backwards compatibility with the previous behaviour in +the version 1 of the library. + + +Implementation details +---------------------- + +Code structure +~~~~~~~~~~~~~~ + +The library is divided into 4 modules: + +- **Core module** + + Provides the main functionality of the library, such as the initialization of + translation tables contexts and mapping/unmapping memory regions. This module + provides functions such as ``mmap_add_region_ctx`` that let the caller specify + the translation tables context affected by them. + + See ``xlat_tables_core.c``. + +- **Active context module** + + Instantiates the context that is used by the current BL image and provides + helpers to manipulate it, abstracting it from the rest of the code. + This module provides functions such as ``mmap_add_region``, that directly + affect the BL image using them. + + See ``xlat_tables_context.c``. + +- **Utilities module** + + Provides additional functionality like debug print of the current state of the + translation tables and helpers to query memory attributes and to modify them. + + See ``xlat_tables_utils.c``. + +- **Architectural module** + + Provides functions that are dependent on the current execution state + (AArch32/AArch64), such as the functions used for TLB invalidation, setup the + MMU, or calculate the Physical Address Space size. They do not need a + translation context to work on. + + See ``aarch32/xlat_tables_arch.c`` and ``aarch64/xlat_tables_arch.c``. + +From mmap regions to translation tables +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A translation context contains a list of ``mmap_region_t``, which holds the +information of all the regions that are mapped at any given time. Whenever there +is a request to map (resp. unmap) a memory region, it is added to (resp. removed +from) the ``mmap_region_t`` list. + +The mmap regions list is a conceptual way to represent the memory layout. At +some point, the library has to convert this information into actual translation +tables to program into the MMU. + +Before the ``init_xlat_tables()`` API is called, the library only acts on the +mmap regions list. Adding a static or dynamic region at this point through one +of the ``mmap_add*()`` APIs does not affect the translation tables in any way, +they only get registered in the internal mmap region list. It is only when the +user calls the ``init_xlat_tables()`` that the translation tables are populated +in memory based on the list of mmap regions registered so far. This is an +optimization that allows creation of the initial set of translation tables in +one go, rather than having to edit them every time while the MMU is disabled. + +After the ``init_xlat_tables()`` API has been called, only dynamic regions can +be added. Changes to the translation tables (as well as the mmap regions list) +will take effect immediately. + +The memory mapping algorithm +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The mapping function is implemented as a recursive algorithm. It is however +bound by the level of depth of the translation tables (the Armv8-A architecture +allows up to 4 lookup levels). + +By default [#granularity]_, the algorithm will attempt to minimize the +number of translation tables created to satisfy the user's request. It will +favour mapping a region using the biggest possible blocks, only creating a +sub-table if it is strictly necessary. This is to reduce the memory footprint of +the firmware. + +The most common reason for needing a sub-table is when a specific mapping +requires a finer granularity. Misaligned regions also require a finer +granularity than what the user may had originally expected, using a lot more +memory than expected. The reason is that all levels of translation are +restricted to address translations of the same granularity as the size of the +blocks of that level. For example, for a 4 KiB page size, a level 2 block entry +can only translate up to a granularity of 2 MiB. If the Physical Address is not +aligned to 2 MiB then additional level 3 tables are also needed. + +Note that not every translation level allows any type of descriptor. Depending +on the page size, levels 0 and 1 of translation may only allow table +descriptors. If a block entry could be able to describe a translation, but that +level does not allow block descriptors, a table descriptor will have to be used +instead, as well as additional tables at the next level. + +|Alignment Example| + +The mmap regions are sorted in a way that simplifies the code that maps +them. Even though this ordering is only strictly needed for overlapping static +regions, it must also be applied for dynamic regions to maintain a consistent +order of all regions at all times. As each new region is mapped, existing +entries in the translation tables are checked to ensure consistency. Please +refer to the comments in the source code of the core module for more details +about the sorting algorithm in use. + +This mapping algorithm does not apply to the MPU library, since the MPU hardware +directly maps regions by "base" and "limit" (bottom and top) addresses. + +TLB maintenance operations +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The library takes care of performing TLB maintenance operations when required. +For example, when the user requests removing a dynamic region, the library +invalidates all TLB entries associated to that region to ensure that these +changes are visible to subsequent execution, including speculative execution, +that uses the changed translation table entries. + +A counter-example is the initialization of translation tables. In this case, +explicit TLB maintenance is not required. The Armv8-A architecture guarantees +that all TLBs are disabled from reset and their contents have no effect on +address translation at reset [#tlb-reset-ref]_. Therefore, the TLBs invalidation +is deferred to the ``enable_mmu*()`` family of functions, just before the MMU is +turned on. + +Regarding enabling and disabling memory management, for the MPU library, to +reduce confusion, calls to enable or disable the MPU use ``mpu`` in their names +in place of ``mmu``. For example, the ``enable_mmu_el2()`` call is changed to +``enable_mpu_el2()``. + +TLB invalidation is not required when adding dynamic regions either. Dynamic +regions are not allowed to overlap existing memory region. Therefore, if the +dynamic mapping request is deemed legitimate, it automatically concerns memory +that was not mapped in this translation regime and the library will have +initialized its corresponding translation table entry to an invalid +descriptor. Given that the TLBs are not architecturally permitted to hold any +invalid translation table entry [#tlb-no-invalid-entry]_, this means that this +mapping cannot be cached in the TLBs. + +.. rubric:: Footnotes + +.. [#granularity] That is, when mmap regions do not enforce their mapping + granularity. + +.. [#tlb-reset-ref] See section D4.9 ``Translation Lookaside Buffers (TLBs)``, + subsection ``TLB behavior at reset`` in Armv8-A, rev C.a. + +.. [#tlb-no-invalid-entry] See section D4.10.1 ``General TLB maintenance + requirements`` in Armv8-A, rev C.a. + +-------------- + +*Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved.* + +.. |Alignment Example| image:: ../resources/diagrams/xlat_align.png diff --git a/arm-trusted-firmware/docs/conf.py b/arm-trusted-firmware/docs/conf.py new file mode 100644 index 0000000..ef77f6b --- /dev/null +++ b/arm-trusted-firmware/docs/conf.py @@ -0,0 +1,94 @@ +# -*- coding: utf-8 -*- +# +# Copyright (c) 2019-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +# Configuration file for the Sphinx documentation builder. +# +# See the options documentation at http://www.sphinx-doc.org/en/master/config + +import os + +# -- Project information ----------------------------------------------------- + +project = 'Trusted Firmware-A' + +# -- General configuration --------------------------------------------------- + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. +extensions = ['myst_parser', 'sphinx.ext.autosectionlabel', 'sphinxcontrib.plantuml'] + +# Add any paths that contain templates here, relative to this directory. +templates_path = ['_templates'] + +# The suffix(es) of source filenames. +source_suffix = ['.md', '.rst'] + +# The master toctree document. +master_doc = 'index' + +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = None + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path . +exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. +pygments_style = 'sphinx' + +# Load the contents of the global substitutions file into the 'rst_prolog' +# variable. This ensures that the substitutions are all inserted into each page. +with open('global_substitutions.txt', 'r') as subs: + rst_prolog = subs.read() + +# Minimum version of sphinx required +needs_sphinx = '2.0' + +# -- Options for HTML output ------------------------------------------------- + +# Don't show the "Built with Sphinx" footer +html_show_sphinx = False + +# Don't show copyright info in the footer (we have this content in the page) +html_show_copyright = False + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +html_theme = "sphinx_rtd_theme" + +# The logo to display in the sidebar +html_logo = 'resources/TrustedFirmware-Logo_standard-white.png' + +# Options for the "sphinx-rtd-theme" theme +html_theme_options = { + 'collapse_navigation': False, # Can expand and collapse sidebar entries + 'prev_next_buttons_location': 'both', # Top and bottom of the page + 'style_external_links': True # Display an icon next to external links +} + +# Path to _static directory +html_static_path = ['_static'] + +# Path to css file relative to html_static_path +html_css_files = [ + 'css/custom.css', +] + +# -- Options for autosectionlabel -------------------------------------------- + +# Only generate automatic section labels for document titles +autosectionlabel_maxdepth = 1 + +# -- Options for plantuml ---------------------------------------------------- + +plantuml_output_format = 'svg_img' diff --git a/arm-trusted-firmware/docs/design/alt-boot-flows.rst b/arm-trusted-firmware/docs/design/alt-boot-flows.rst new file mode 100644 index 0000000..b44c061 --- /dev/null +++ b/arm-trusted-firmware/docs/design/alt-boot-flows.rst @@ -0,0 +1,84 @@ +Alternative Boot Flows +====================== + +EL3 payloads alternative boot flow +---------------------------------- + +On a pre-production system, the ability to execute arbitrary, bare-metal code at +the highest exception level is required. It allows full, direct access to the +hardware, for example to run silicon soak tests. + +Although it is possible to implement some baremetal secure firmware from +scratch, this is a complex task on some platforms, depending on the level of +configuration required to put the system in the expected state. + +Rather than booting a baremetal application, a possible compromise is to boot +``EL3 payloads`` through TF-A instead. This is implemented as an alternative +boot flow, where a modified BL2 boots an EL3 payload, instead of loading the +other BL images and passing control to BL31. It reduces the complexity of +developing EL3 baremetal code by: + +- putting the system into a known architectural state; +- taking care of platform secure world initialization; +- loading the SCP_BL2 image if required by the platform. + +When booting an EL3 payload on Arm standard platforms, the configuration of the +TrustZone controller is simplified such that only region 0 is enabled and is +configured to permit secure access only. This gives full access to the whole +DRAM to the EL3 payload. + +The system is left in the same state as when entering BL31 in the default boot +flow. In particular: + +- Running in EL3; +- Current state is AArch64; +- Little-endian data access; +- All exceptions disabled; +- MMU disabled; +- Caches disabled. + +.. _alt_boot_flows_el3_payload: + +Booting an EL3 payload +~~~~~~~~~~~~~~~~~~~~~~ + +The EL3 payload image is a standalone image and is not part of the FIP. It is +not loaded by TF-A. Therefore, there are 2 possible scenarios: + +- The EL3 payload may reside in non-volatile memory (NVM) and execute in + place. In this case, booting it is just a matter of specifying the right + address in NVM through ``EL3_PAYLOAD_BASE`` when building TF-A. + +- The EL3 payload needs to be loaded in volatile memory (e.g. DRAM) at + run-time. + +To help in the latter scenario, the ``SPIN_ON_BL1_EXIT=1`` build option can be +used. The infinite loop that it introduces in BL1 stops execution at the right +moment for a debugger to take control of the target and load the payload (for +example, over JTAG). + +It is expected that this loading method will work in most cases, as a debugger +connection is usually available in a pre-production system. The user is free to +use any other platform-specific mechanism to load the EL3 payload, though. + + +Preloaded BL33 alternative boot flow +------------------------------------ + +Some platforms have the ability to preload BL33 into memory instead of relying +on TF-A to load it. This may simplify packaging of the normal world code and +improve performance in a development environment. When secure world cold boot +is complete, TF-A simply jumps to a BL33 base address provided at build time. + +For this option to be used, the ``PRELOADED_BL33_BASE`` build option has to be +used when compiling TF-A. For example, the following command will create a FIP +without a BL33 and prepare to jump to a BL33 image loaded at address +0x80000000: + +.. code:: shell + + make PRELOADED_BL33_BASE=0x80000000 PLAT=fvp all fip + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/auth-framework.rst b/arm-trusted-firmware/docs/design/auth-framework.rst new file mode 100644 index 0000000..6913e66 --- /dev/null +++ b/arm-trusted-firmware/docs/design/auth-framework.rst @@ -0,0 +1,980 @@ +Authentication Framework & Chain of Trust +========================================= + +The aim of this document is to describe the authentication framework +implemented in Trusted Firmware-A (TF-A). This framework fulfills the +following requirements: + +#. It should be possible for a platform port to specify the Chain of Trust in + terms of certificate hierarchy and the mechanisms used to verify a + particular image/certificate. + +#. The framework should distinguish between: + + - The mechanism used to encode and transport information, e.g. DER encoded + X.509v3 certificates to ferry Subject Public Keys, hashes and non-volatile + counters. + + - The mechanism used to verify the transported information i.e. the + cryptographic libraries. + +The framework has been designed following a modular approach illustrated in the +next diagram: + +:: + + +---------------+---------------+------------+ + | Trusted | Trusted | Trusted | + | Firmware | Firmware | Firmware | + | Generic | IO Framework | Platform | + | Code i.e. | (IO) | Port | + | BL1/BL2 (GEN) | | (PP) | + +---------------+---------------+------------+ + ^ ^ ^ + | | | + v v v + +-----------+ +-----------+ +-----------+ + | | | | | Image | + | Crypto | | Auth | | Parser | + | Module |<->| Module |<->| Module | + | (CM) | | (AM) | | (IPM) | + | | | | | | + +-----------+ +-----------+ +-----------+ + ^ ^ + | | + v v + +----------------+ +-----------------+ + | Cryptographic | | Image Parser | + | Libraries (CL) | | Libraries (IPL) | + +----------------+ +-----------------+ + | | + | | + | | + v v + +-----------------+ + | Misc. Libs e.g. | + | ASN.1 decoder | + | | + +-----------------+ + + DIAGRAM 1. + +This document describes the inner details of the authentication framework and +the abstraction mechanisms available to specify a Chain of Trust. + +Framework design +---------------- + +This section describes some aspects of the framework design and the rationale +behind them. These aspects are key to verify a Chain of Trust. + +Chain of Trust +~~~~~~~~~~~~~~ + +A CoT is basically a sequence of authentication images which usually starts with +a root of trust and culminates in a single data image. The following diagram +illustrates how this maps to a CoT for the BL31 image described in the +`TBBR-Client specification`_. + +:: + + +------------------+ +-------------------+ + | ROTPK/ROTPK Hash |------>| Trusted Key | + +------------------+ | Certificate | + | (Auth Image) | + /+-------------------+ + / | + / | + / | + / | + L v + +------------------+ +-------------------+ + | Trusted World |------>| BL31 Key | + | Public Key | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Content |------>| BL31 Content | + | Certificate PK | | Certificate | + +------------------+ | (Auth Image) | + +-------------------+ + / | + / | + / | + / | + / v + +------------------+ L +-------------------+ + | BL31 Hash |------>| BL31 Image | + | | | (Data Image) | + +------------------+ | | + +-------------------+ + + DIAGRAM 2. + +The root of trust is usually a public key (ROTPK) that has been burnt in the +platform and cannot be modified. + +Image types +~~~~~~~~~~~ + +Images in a CoT are categorised as authentication and data images. An +authentication image contains information to authenticate a data image or +another authentication image. A data image is usually a boot loader binary, but +it could be any other data that requires authentication. + +Component responsibilities +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For every image in a Chain of Trust, the following high level operations are +performed to verify it: + +#. Allocate memory for the image either statically or at runtime. + +#. Identify the image and load it in the allocated memory. + +#. Check the integrity of the image as per its type. + +#. Authenticate the image as per the cryptographic algorithms used. + +#. If the image is an authentication image, extract the information that will + be used to authenticate the next image in the CoT. + +In Diagram 1, each component is responsible for one or more of these operations. +The responsibilities are briefly described below. + +TF-A Generic code and IO framework (GEN/IO) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +These components are responsible for initiating the authentication process for a +particular image in BL1 or BL2. For each BL image that requires authentication, +the Generic code asks recursively the Authentication module what is the parent +image until either an authenticated image or the ROT is reached. Then the +Generic code calls the IO framework to load the image and calls the +Authentication module to authenticate it, following the CoT from ROT to Image. + +TF-A Platform Port (PP) +^^^^^^^^^^^^^^^^^^^^^^^ + +The platform is responsible for: + +#. Specifying the CoT for each image that needs to be authenticated. Details of + how a CoT can be specified by the platform are explained later. The platform + also specifies the authentication methods and the parsing method used for + each image. + +#. Statically allocating memory for each parameter in each image which is + used for verifying the CoT, e.g. memory for public keys, hashes etc. + +#. Providing the ROTPK or a hash of it. + +#. Providing additional information to the IPM to enable it to identify and + extract authentication parameters contained in an image, e.g. if the + parameters are stored as X509v3 extensions, the corresponding OID must be + provided. + +#. Fulfill any other memory requirements of the IPM and the CM (not currently + described in this document). + +#. Export functions to verify an image which uses an authentication method that + cannot be interpreted by the CM, e.g. if an image has to be verified using a + NV counter, then the value of the counter to compare with can only be + provided by the platform. + +#. Export a custom IPM if a proprietary image format is being used (described + later). + +Authentication Module (AM) +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It is responsible for: + +#. Providing the necessary abstraction mechanisms to describe a CoT. Amongst + other things, the authentication and image parsing methods must be specified + by the PP in the CoT. + +#. Verifying the CoT passed by GEN by utilising functionality exported by the + PP, IPM and CM. + +#. Tracking which images have been verified. In case an image is a part of + multiple CoTs then it should be verified only once e.g. the Trusted World + Key Certificate in the TBBR-Client spec. contains information to verify + SCP_BL2, BL31, BL32 each of which have a separate CoT. (This + responsibility has not been described in this document but should be + trivial to implement). + +#. Reusing memory meant for a data image to verify authentication images e.g. + in the CoT described in Diagram 2, each certificate can be loaded and + verified in the memory reserved by the platform for the BL31 image. By the + time BL31 (the data image) is loaded, all information to authenticate it + will have been extracted from the parent image i.e. BL31 content + certificate. It is assumed that the size of an authentication image will + never exceed the size of a data image. It should be possible to verify this + at build time using asserts. + +Cryptographic Module (CM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The CM is responsible for providing an API to: + +#. Verify a digital signature. +#. Verify a hash. + +The CM does not include any cryptography related code, but it relies on an +external library to perform the cryptographic operations. A Crypto-Library (CL) +linking the CM and the external library must be implemented. The following +functions must be provided by the CL: + +.. code:: c + + void (*init)(void); + int (*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); + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +These functions are registered in the CM using the macro: + +.. code:: c + + REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash); + +``_name`` must be a string containing the name of the CL. This name is used for +debugging purposes. + +Image Parser Module (IPM) +^^^^^^^^^^^^^^^^^^^^^^^^^ + +The IPM is responsible for: + +#. Checking the integrity of each image loaded by the IO framework. +#. Extracting parameters used for authenticating an image based upon a + description provided by the platform in the CoT descriptor. + +Images may have different formats (for example, authentication images could be +x509v3 certificates, signed ELF files or any other platform specific format). +The IPM allows to register an Image Parser Library (IPL) for every image format +used in the CoT. This library must implement the specific methods to parse the +image. The IPM obtains the image format from the CoT and calls the right IPL to +check the image integrity and extract the authentication parameters. + +See Section "Describing the image parsing methods" for more details about the +mechanism the IPM provides to define and register IPLs. + +Authentication methods +~~~~~~~~~~~~~~~~~~~~~~ + +The AM supports the following authentication methods: + +#. Hash +#. Digital signature + +The platform may specify these methods in the CoT in case it decides to define +a custom CoT instead of reusing a predefined one. + +If a data image uses multiple methods, then all the methods must be a part of +the same CoT. The number and type of parameters are method specific. These +parameters should be obtained from the parent image using the IPM. + +#. Hash + + Parameters: + + #. A pointer to data to hash + #. Length of the data + #. A pointer to the hash + #. Length of the hash + + The hash will be represented by the DER encoding of the following ASN.1 + type: + + :: + + DigestInfo ::= SEQUENCE { + digestAlgorithm DigestAlgorithmIdentifier, + digest Digest + } + + This ASN.1 structure makes it possible to remove any assumption about the + type of hash algorithm used as this information accompanies the hash. This + should allow the Cryptography Library (CL) to support multiple hash + algorithm implementations. + +#. Digital Signature + + Parameters: + + #. A pointer to data to sign + #. Length of the data + #. Public Key Algorithm + #. Public Key value + #. Digital Signature Algorithm + #. Digital Signature value + + The Public Key parameters will be represented by the DER encoding of the + following ASN.1 type: + + :: + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier{PUBLIC-KEY,{PublicKeyAlgorithms}}, + subjectPublicKey BIT STRING } + + The Digital Signature Algorithm will be represented by the DER encoding of + the following ASN.1 types. + + :: + + AlgorithmIdentifier {ALGORITHM:IOSet } ::= SEQUENCE { + algorithm ALGORITHM.&id({IOSet}), + parameters ALGORITHM.&Type({IOSet}{@algorithm}) OPTIONAL + } + + The digital signature will be represented by: + + :: + + signature ::= BIT STRING + +The authentication framework will use the image descriptor to extract all the +information related to authentication. + +Specifying a Chain of Trust +--------------------------- + +A CoT can be described as a set of image descriptors linked together in a +particular order. The order dictates the sequence in which they must be +verified. Each image has a set of properties which allow the AM to verify it. +These properties are described below. + +The PP is responsible for defining a single or multiple CoTs for a data image. +Unless otherwise specified, the data structures described in the following +sections are populated by the PP statically. + +Describing the image parsing methods +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The parsing method refers to the format of a particular image. For example, an +authentication image that represents a certificate could be in the X.509v3 +format. A data image that represents a boot loader stage could be in raw binary +or ELF format. The IPM supports three parsing methods. An image has to use one +of the three methods described below. An IPL is responsible for interpreting a +single parsing method. There has to be one IPL for every method used by the +platform. + +#. Raw format: This format is effectively a nop as an image using this method + is treated as being in raw binary format e.g. boot loader images used by + TF-A. This method should only be used by data images. + +#. X509V3 method: This method uses industry standards like X.509 to represent + PKI certificates (authentication images). It is expected that open source + libraries will be available which can be used to parse an image represented + by this method. Such libraries can be used to write the corresponding IPL + e.g. the X.509 parsing library code in mbed TLS. + +#. Platform defined method: This method caters for platform specific + proprietary standards to represent authentication or data images. For + example, The signature of a data image could be appended to the data image + raw binary. A header could be prepended to the combined blob to specify the + extents of each component. The platform will have to implement the + corresponding IPL to interpret such a format. + +The following enum can be used to define these three methods. + +.. code:: c + + typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, + } img_type_t; + +An IPL must provide functions with the following prototypes: + +.. code:: c + + void init(void); + int check_integrity(void *img, unsigned int img_len); + int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); + +An IPL for each type must be registered using the following macro: + +.. code:: c + + REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) + +- ``_type``: one of the types described above. +- ``_name``: a string containing the IPL name for debugging purposes. +- ``_init``: initialization function pointer. +- ``_check_int``: check image integrity function pointer. +- ``_get_param``: extract authentication parameter function pointer. + +The ``init()`` function will be used to initialize the IPL. + +The ``check_integrity()`` function is passed a pointer to the memory where the +image has been loaded by the IO framework and the image length. It should ensure +that the image is in the format corresponding to the parsing method and has not +been tampered with. For example, RFC-2459 describes a validation sequence for an +X.509 certificate. + +The ``get_auth_param()`` function is passed a parameter descriptor containing +information about the parameter (``type_desc`` and ``cookie``) to identify and +extract the data corresponding to that parameter from an image. This data will +be used to verify either the current or the next image in the CoT sequence. + +Each image in the CoT will specify the parsing method it uses. This information +will be used by the IPM to find the right parser descriptor for the image. + +Describing the authentication method(s) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As part of the CoT, each image has to specify one or more authentication methods +which will be used to verify it. As described in the Section "Authentication +methods", there are three methods supported by the AM. + +.. code:: c + + typedef enum { + AUTH_METHOD_NONE, + AUTH_METHOD_HASH, + AUTH_METHOD_SIG, + AUTH_METHOD_NUM + } auth_method_type_t; + +The AM defines the type of each parameter used by an authentication method. It +uses this information to: + +#. Specify to the ``get_auth_param()`` function exported by the IPM, which + parameter should be extracted from an image. + +#. Correctly marshall the parameters while calling the verification function + exported by the CM and PP. + +#. Extract authentication parameters from a parent image in order to verify a + child image e.g. to verify the certificate image, the public key has to be + obtained from the parent image. + +.. code:: c + + typedef enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ + } auth_param_type_t; + +The AM defines the following structure to identify an authentication parameter +required to verify an image. + +.. code:: c + + typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; + } auth_param_type_desc_t; + +``cookie`` is used by the platform to specify additional information to the IPM +which enables it to uniquely identify the parameter that should be extracted +from an image. For example, the hash of a BL3x image in its corresponding +content certificate is stored in an X509v3 custom extension field. An extension +field can only be identified using an OID. In this case, the ``cookie`` could +contain the pointer to the OID defined by the platform for the hash extension +field while the ``type`` field could be set to ``AUTH_PARAM_HASH``. A value of 0 for +the ``cookie`` field means that it is not used. + +For each method, the AM defines a structure with the parameters required to +verify the image. + +.. code:: c + + /* + * Parameters for authentication by hash matching + */ + typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ + } auth_method_param_hash_t; + + /* + * Parameters for authentication by signature + */ + typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *tbs; /* Data signed */ + } auth_method_param_sig_t; + +The AM defines the following structure to describe an authentication method for +verifying an image + +.. code:: c + + /* + * Authentication method descriptor + */ + typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + } param; + } auth_method_desc_t; + +Using the method type specified in the ``type`` field, the AM finds out what field +needs to access within the ``param`` union. + +Storing Authentication parameters +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A parameter described by ``auth_param_type_desc_t`` to verify an image could be +obtained from either the image itself or its parent image. The memory allocated +for loading the parent image will be reused for loading the child image. Hence +parameters which are obtained from the parent for verifying a child image need +to have memory allocated for them separately where they can be stored. This +memory must be statically allocated by the platform port. + +The AM defines the following structure to store the data corresponding to an +authentication parameter. + +.. code:: c + + typedef struct auth_param_data_desc_s { + void *auth_param_ptr; + unsigned int auth_param_len; + } auth_param_data_desc_t; + +The ``auth_param_ptr`` field is initialized by the platform. The ``auth_param_len`` +field is used to specify the length of the data in the memory. + +For parameters that can be obtained from the child image itself, the IPM is +responsible for populating the ``auth_param_ptr`` and ``auth_param_len`` fields +while executing the ``img_get_auth_param()`` function. + +The AM defines the following structure to enable an image to describe the +parameters that should be extracted from it and used to verify the next image +(child) in a CoT. + +.. code:: c + + typedef struct auth_param_desc_s { + auth_param_type_desc_t type_desc; + auth_param_data_desc_t data; + } auth_param_desc_t; + +Describing an image in a CoT +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +An image in a CoT is a consolidation of the following aspects of a CoT described +above. + +#. A unique identifier specified by the platform which allows the IO framework + to locate the image in a FIP and load it in the memory reserved for the data + image in the CoT. + +#. A parsing method which is used by the AM to find the appropriate IPM. + +#. Authentication methods and their parameters as described in the previous + section. These are used to verify the current image. + +#. Parameters which are used to verify the next image in the current CoT. These + parameters are specified only by authentication images and can be extracted + from the current image once it has been verified. + +The following data structure describes an image in a CoT. + +.. code:: c + + typedef struct auth_img_desc_s { + unsigned int img_id; + const struct auth_img_desc_s *parent; + img_type_t img_type; + const auth_method_desc_t *const img_auth_methods; + const auth_param_desc_t *const authenticated_data; + } auth_img_desc_t; + +A CoT is defined as an array of pointers to ``auth_image_desc_t`` structures +linked together by the ``parent`` field. Those nodes with no parent must be +authenticated using the ROTPK stored in the platform. + +Implementation example +---------------------- + +This section is a detailed guide explaining a trusted boot implementation using +the authentication framework. This example corresponds to the Applicative +Functional Mode (AFM) as specified in the TBBR-Client document. It is +recommended to read this guide along with the source code. + +The TBBR CoT +~~~~~~~~~~~~ + +CoT specific to BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_bl1.c`` +and ``drivers/auth/tbbr/tbbr_cot_bl2.c`` respectively. The common CoT used across +BL1 and BL2 can be found in ``drivers/auth/tbbr/tbbr_cot_common.c``. +This CoT consists of an array of pointers to image descriptors and it is +registered in the framework using the macro ``REGISTER_COT(cot_desc)``, where +``cot_desc`` must be the name of the array (passing a pointer or any other +type of indirection will cause the registration process to fail). + +The number of images participating in the boot process depends on the CoT. +There is, however, a minimum set of images that are mandatory in TF-A and thus +all CoTs must present: + +- ``BL2`` +- ``SCP_BL2`` (platform specific) +- ``BL31`` +- ``BL32`` (optional) +- ``BL33`` + +The TBBR specifies the additional certificates that must accompany these images +for a proper authentication. Details about the TBBR CoT may be found in the +:ref:`Trusted Board Boot` document. + +Following the :ref:`Porting Guide`, a platform must provide unique +identifiers for all the images and certificates that will be loaded during the +boot process. If a platform is using the TBBR as a reference for trusted boot, +these identifiers can be obtained from ``include/common/tbbr/tbbr_img_def.h``. +Arm platforms include this file in ``include/plat/arm/common/arm_def.h``. Other +platforms may also include this file or provide their own identifiers. + +**Important**: the authentication module uses these identifiers to index the +CoT array, so the descriptors location in the array must match the identifiers. + +Each image descriptor must specify: + +- ``img_id``: the corresponding image unique identifier defined by the platform. +- ``img_type``: the image parser module uses the image type to call the proper + parsing library to check the image integrity and extract the required + authentication parameters. Three types of images are currently supported: + + - ``IMG_RAW``: image is a raw binary. No parsing functions are available, + other than reading the whole image. + - ``IMG_PLAT``: image format is platform specific. The platform may use this + type for custom images not directly supported by the authentication + framework. + - ``IMG_CERT``: image is an x509v3 certificate. + +- ``parent``: pointer to the parent image descriptor. The parent will contain + the information required to authenticate the current image. If the parent + is NULL, the authentication parameters will be obtained from the platform + (i.e. the BL2 and Trusted Key certificates are signed with the ROT private + key, whose public part is stored in the platform). +- ``img_auth_methods``: this points to an array which defines the + authentication methods that must be checked to consider an image + authenticated. Each method consists of a type and a list of parameter + descriptors. A parameter descriptor consists of a type and a cookie which + will point to specific information required to extract that parameter from + the image (i.e. if the parameter is stored in an x509v3 extension, the + cookie will point to the extension OID). Depending on the method type, a + different number of parameters must be specified. This pointer should not be + NULL. + Supported methods are: + + - ``AUTH_METHOD_HASH``: the hash of the image must match the hash extracted + from the parent image. The following parameter descriptors must be + specified: + + - ``data``: data to be hashed (obtained from current image) + - ``hash``: reference hash (obtained from parent image) + + - ``AUTH_METHOD_SIG``: the image (usually a certificate) must be signed with + the private key whose public part is extracted from the parent image (or + the platform if the parent is NULL). The following parameter descriptors + must be specified: + + - ``pk``: the public key (obtained from parent image) + - ``sig``: the digital signature (obtained from current image) + - ``alg``: the signature algorithm used (obtained from current image) + - ``data``: the data to be signed (obtained from current image) + +- ``authenticated_data``: this array pointer indicates what authentication + parameters must be extracted from an image once it has been authenticated. + Each parameter consists of a parameter descriptor and the buffer + address/size to store the parameter. The CoT is responsible for allocating + the required memory to store the parameters. This pointer may be NULL. + +In the ``tbbr_cot*.c`` file, a set of buffers are allocated to store the parameters +extracted from the certificates. In the case of the TBBR CoT, these parameters +are hashes and public keys. In DER format, an RSA-4096 public key requires 550 +bytes, and a hash requires 51 bytes. Depending on the CoT and the authentication +process, some of the buffers may be reused at different stages during the boot. + +Next in that file, the parameter descriptors are defined. These descriptors will +be used to extract the parameter data from the corresponding image. + +Example: the BL31 Chain of Trust +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Four image descriptors form the BL31 Chain of Trust: + +.. code:: c + + static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } + }; + static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } + }; + static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } + }; + +The **Trusted Key certificate** is signed with the ROT private key and contains +the Trusted World public key and the Non-Trusted World public key as x509v3 +extensions. This must be specified in the image descriptor using the +``img_auth_methods`` and ``authenticated_data`` arrays, respectively. + +The Trusted Key certificate is authenticated by checking its digital signature +using the ROTPK. Four parameters are required to check a signature: the public +key, the algorithm, the signature and the data that has been signed. Therefore, +four parameter descriptors must be specified with the authentication method: + +- ``subject_pk``: parameter descriptor of type ``AUTH_PARAM_PUB_KEY``. This type + is used to extract a public key from the parent image. If the cookie is an + OID, the key is extracted from the corresponding x509v3 extension. If the + cookie is NULL, the subject public key is retrieved. In this case, because + the parent image is NULL, the public key is obtained from the platform + (this key will be the ROTPK). +- ``sig``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to extract + the signature from the certificate. +- ``sig_alg``: parameter descriptor of type ``AUTH_PARAM_SIG``. It is used to + extract the signature algorithm from the certificate. +- ``raw_data``: parameter descriptor of type ``AUTH_PARAM_RAW_DATA``. It is used + to extract the data to be signed from the certificate. + +Once the signature has been checked and the certificate authenticated, the +Trusted World public key needs to be extracted from the certificate. A new entry +is created in the ``authenticated_data`` array for that purpose. In that entry, +the corresponding parameter descriptor must be specified along with the buffer +address to store the parameter value. In this case, the ``trusted_world_pk`` +descriptor is used to extract the public key from an x509v3 extension with OID +``TRUSTED_WORLD_PK_OID``. The BL31 key certificate will use this descriptor as +parameter in the signature authentication method. The key is stored in the +``trusted_world_pk_buf`` buffer. + +The **BL31 Key certificate** is authenticated by checking its digital signature +using the Trusted World public key obtained previously from the Trusted Key +certificate. In the image descriptor, we specify a single authentication method +by signature whose public key is the ``trusted_world_pk``. Once this certificate +has been authenticated, we have to extract the BL31 public key, stored in the +extension specified by ``soc_fw_content_pk``. This key will be copied to the +``content_pk_buf`` buffer. + +The **BL31 certificate** is authenticated by checking its digital signature +using the BL31 public key obtained previously from the BL31 Key certificate. +We specify the authentication method using ``soc_fw_content_pk`` as public key. +After authentication, we need to extract the BL31 hash, stored in the extension +specified by ``soc_fw_hash``. This hash will be copied to the +``soc_fw_hash_buf`` buffer. + +The **BL31 image** is authenticated by calculating its hash and matching it +with the hash obtained from the BL31 certificate. The image descriptor contains +a single authentication method by hash. The parameters to the hash method are +the reference hash, ``soc_fw_hash``, and the data to be hashed. In this case, +it is the whole image, so we specify ``raw_data``. + +The image parser library +~~~~~~~~~~~~~~~~~~~~~~~~ + +The image parser module relies on libraries to check the image integrity and +extract the authentication parameters. The number and type of parser libraries +depend on the images used in the CoT. Raw images do not need a library, so +only an x509v3 library is required for the TBBR CoT. + +Arm platforms will use an x509v3 library based on mbed TLS. This library may be +found in ``drivers/auth/mbedtls/mbedtls_x509_parser.c``. It exports three +functions: + +.. code:: c + + void init(void); + int check_integrity(void *img, unsigned int img_len); + int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); + +The library is registered in the framework using the macro +``REGISTER_IMG_PARSER_LIB()``. Each time the image parser module needs to access +an image of type ``IMG_CERT``, it will call the corresponding function exported +in this file. + +The build system must be updated to include the corresponding library and +mbed TLS sources. Arm platforms use the ``arm_common.mk`` file to pull the +sources. + +The cryptographic library +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The cryptographic module relies on a library to perform the required operations, +i.e. verify a hash or a digital signature. Arm platforms will use a library +based on mbed TLS, which can be found in +``drivers/auth/mbedtls/mbedtls_crypto.c``. This library is registered in the +authentication framework using the macro ``REGISTER_CRYPTO_LIB()`` and exports +four functions: + +.. code:: c + + void init(void); + int 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); + int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + int 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) + +The mbedTLS library algorithm support is configured by both the +``TF_MBEDTLS_KEY_ALG`` and ``TF_MBEDTLS_KEY_SIZE`` variables. + +- ``TF_MBEDTLS_KEY_ALG`` can take in 3 values: `rsa`, `ecdsa` or `rsa+ecdsa`. + This variable allows the Makefile to include the corresponding sources in + the build for the various algorithms. Setting the variable to `rsa+ecdsa` + enables support for both rsa and ecdsa algorithms in the mbedTLS library. + +- ``TF_MBEDTLS_KEY_SIZE`` sets the supported RSA key size for TFA. Valid values + include 1024, 2048, 3072 and 4096. + +- ``TF_MBEDTLS_USE_AES_GCM`` enables the authenticated decryption support based + on AES-GCM algorithm. Valid values are 0 and 1. + +.. note:: + If code size is a concern, the build option ``MBEDTLS_SHA256_SMALLER`` can + be defined in the platform Makefile. It will make mbed TLS use an + implementation of SHA-256 with smaller memory footprint (~1.5 KB less) but + slower (~30%). + +-------------- + +*Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved.* + +.. _TBBR-Client specification: https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst b/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst new file mode 100644 index 0000000..012eefb --- /dev/null +++ b/arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst @@ -0,0 +1,611 @@ +Arm CPU Specific Build Macros +============================= + +This document describes the various build options present in the CPU specific +operations framework to enable errata workarounds and to enable optimizations +for a specific CPU on a platform. + +Security Vulnerability Workarounds +---------------------------------- + +TF-A exports a series of build flags which control which security +vulnerability workarounds should be applied at runtime. + +- ``WORKAROUND_CVE_2017_5715``: Enables the security workaround for + `CVE-2017-5715`_. This flag can be set to 0 by the platform if none + of the PEs in the system need the workaround. Setting this flag to 0 provides + no performance benefit for non-affected platforms, it just helps to comply + with the recommendation in the spec regarding workaround discovery. + Defaults to 1. + +- ``WORKAROUND_CVE_2018_3639``: Enables the security workaround for + `CVE-2018-3639`_. Defaults to 1. The TF-A project recommends to keep + the default value of 1 even on platforms that are unaffected by + CVE-2018-3639, in order to comply with the recommendation in the spec + regarding workaround discovery. + +- ``DYNAMIC_WORKAROUND_CVE_2018_3639``: Enables dynamic mitigation for + `CVE-2018-3639`_. This build option should be set to 1 if the target + platform contains at least 1 CPU that requires dynamic mitigation. + Defaults to 0. + +- ``WORKAROUND_CVE_2022_23960``: Enables mitigation for `CVE-2022-23960`_. + This build option should be set to 1 if the target platform contains at + least 1 CPU that requires this mitigation. Defaults to 1. + +.. _arm_cpu_macros_errata_workarounds: + +CPU Errata Workarounds +---------------------- + +TF-A exports a series of build flags which control the errata workarounds that +are applied to each CPU by the reset handler. The errata details can be found +in the CPU specific errata documents published by Arm: + +- `Cortex-A53 MPCore Software Developers Errata Notice`_ +- `Cortex-A57 MPCore Software Developers Errata Notice`_ +- `Cortex-A72 MPCore Software Developers Errata Notice`_ + +The errata workarounds are implemented for a particular revision or a set of +processor revisions. This is checked by the reset handler at runtime. Each +errata workaround is identified by its ``ID`` as specified in the processor's +errata notice document. The format of the define used to enable/disable the +errata workaround is ``ERRATA__``, where the ``Processor name`` +is for example ``A57`` for the ``Cortex_A57`` CPU. + +Refer to :ref:`firmware_design_cpu_errata_reporting` for information on how to +write errata workaround functions. + +All workarounds are disabled by default. The platform is responsible for +enabling these workarounds according to its requirement by defining the +errata workaround build flags in the platform specific makefile. In case +these workarounds are enabled for the wrong CPU revision then the errata +workaround is not applied. In the DEBUG build, this is indicated by +printing a warning to the crash console. + +In the current implementation, a platform which has more than 1 variant +with different revisions of a processor has no runtime mechanism available +for it to specify which errata workarounds should be enabled or not. + +The value of the build flags is 0 by default, that is, disabled. A value of 1 +will enable it. + +For Cortex-A9, the following errata build flags are defined : + +- ``ERRATA_A9_794073``: This applies errata 794073 workaround to Cortex-A9 + CPU. This needs to be enabled for all revisions of the CPU. + +For Cortex-A15, the following errata build flags are defined : + +- ``ERRATA_A15_816470``: This applies errata 816470 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +- ``ERRATA_A15_827671``: This applies errata 827671 workaround to Cortex-A15 + CPU. This needs to be enabled only for revision >= r3p0 of the CPU. + +For Cortex-A17, the following errata build flags are defined : + +- ``ERRATA_A17_852421``: This applies errata 852421 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A17_852423``: This applies errata 852423 workaround to Cortex-A17 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +For Cortex-A35, the following errata build flags are defined : + +- ``ERRATA_A35_855472``: This applies errata 855472 workaround to Cortex-A35 + CPUs. This needs to be enabled only for revision r0p0 of Cortex-A35. + +For Cortex-A53, the following errata build flags are defined : + +- ``ERRATA_A53_819472``: This applies errata 819472 workaround to all + CPUs. This needs to be enabled only for revision <= r0p1 of Cortex-A53. + +- ``ERRATA_A53_824069``: This applies errata 824069 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_826319``: This applies errata 826319 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p2 of the CPU. + +- ``ERRATA_A53_827319``: This applies errata 827319 workaround to all + CPUs. This needs to be enabled only for revision <= r0p2 of Cortex-A53. + +- ``ERRATA_A53_835769``: This applies erratum 835769 workaround at compile and + link time to Cortex-A53 CPU. This needs to be enabled for some variants of + revision <= r0p4. This workaround can lead the linker to create ``*.stub`` + sections. + +- ``ERRATA_A53_836870``: This applies errata 836870 workaround to Cortex-A53 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. From + r0p4 and onwards, this errata is enabled by default in hardware. + +- ``ERRATA_A53_843419``: This applies erratum 843419 workaround at link time + to Cortex-A53 CPU. This needs to be enabled for some variants of revision + <= r0p4. This workaround can lead the linker to emit ``*.stub`` sections + which are 4kB aligned. + +- ``ERRATA_A53_855873``: This applies errata 855873 workaround to Cortex-A53 + CPUs. Though the erratum is present in every revision of the CPU, + this workaround is only applied to CPUs from r0p3 onwards, which feature + a chicken bit in CPUACTLR_EL1 to enable a hardware workaround. + Earlier revisions of the CPU have other errata which require the same + workaround in software, so they should be covered anyway. + +- ``ERRATA_A53_1530924``: This applies errata 1530924 workaround to all + revisions of Cortex-A53 CPU. + +For Cortex-A55, the following errata build flags are defined : + +- ``ERRATA_A55_768277``: This applies errata 768277 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_778703``: This applies errata 778703 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_798797``: This applies errata 798797 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A55_846532``: This applies errata 846532 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A55_903758``: This applies errata 903758 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A55_1221012``: This applies errata 1221012 workaround to Cortex-A55 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A55_1530923``: This applies errata 1530923 workaround to all + revisions of Cortex-A55 CPU. + +For Cortex-A57, the following errata build flags are defined : + +- ``ERRATA_A57_806969``: This applies errata 806969 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813419``: This applies errata 813419 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_813420``: This applies errata 813420 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_814670``: This applies errata 814670 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A57_817169``: This applies errata 817169 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +- ``ERRATA_A57_826974``: This applies errata 826974 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_826977``: This applies errata 826977 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_828024``: This applies errata 828024 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A57_829520``: This applies errata 829520 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_833471``: This applies errata 833471 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p2 of the CPU. + +- ``ERRATA_A57_859972``: This applies errata 859972 workaround to Cortex-A57 + CPU. This needs to be enabled only for revision <= r1p3 of the CPU. + +- ``ERRATA_A57_1319537``: This applies errata 1319537 workaround to all + revisions of Cortex-A57 CPU. + +For Cortex-A72, the following errata build flags are defined : + +- ``ERRATA_A72_859971``: This applies errata 859971 workaround to Cortex-A72 + CPU. This needs to be enabled only for revision <= r0p3 of the CPU. + +- ``ERRATA_A72_1319367``: This applies errata 1319367 workaround to all + revisions of Cortex-A72 CPU. + +For Cortex-A73, the following errata build flags are defined : + +- ``ERRATA_A73_852427``: This applies errata 852427 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A73_855423``: This applies errata 855423 workaround to Cortex-A73 + CPU. This needs to be enabled only for revision <= r0p1 of the CPU. + +For Cortex-A75, the following errata build flags are defined : + +- ``ERRATA_A75_764081``: This applies errata 764081 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +- ``ERRATA_A75_790748``: This applies errata 790748 workaround to Cortex-A75 + CPU. This needs to be enabled only for revision r0p0 of the CPU. + +For Cortex-A76, the following errata build flags are defined : + +- ``ERRATA_A76_1073348``: This applies errata 1073348 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A76_1130799``: This applies errata 1130799 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1220197``: This applies errata 1220197 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_A76_1257314``: This applies errata 1257314 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262606``: This applies errata 1262606 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1262888``: This applies errata 1262888 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1275112``: This applies errata 1275112 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_A76_1791580``: This applies errata 1791580 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_A76_1165522``: This applies errata 1165522 workaround to all + revisions of Cortex-A76 CPU. This errata is fixed in r3p0 but due to + limitation of errata framework this errata is applied to all revisions + of Cortex-A76 CPU. + +- ``ERRATA_A76_1868343``: This applies errata 1868343 workaround to Cortex-A76 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_A76_1946160``: This applies errata 1946160 workaround to Cortex-A76 + CPU. This needs to be enabled only for revisions r3p0 - r4p1 of the CPU. + +For Cortex-A77, the following errata build flags are defined : + +- ``ERRATA_A77_1508412``: This applies errata 1508412 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p0 of the CPU. + +- ``ERRATA_A77_1925769``: This applies errata 1925769 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A77_1946167``: This applies errata 1946167 workaround to Cortex-A77 + CPU. This needs to be enabled only for revision <= r1p1 of the CPU. + +- ``ERRATA_A77_1791578``: This applies errata 1791578 workaround to Cortex-A77 + CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open. + +For Cortex-A78, the following errata build flags are defined : + +- ``ERRATA_A78_1688305``: This applies errata 1688305 workaround to Cortex-A78 + CPU. This needs to be enabled only for revision r0p0 - r1p0 of the CPU. + +- ``ERRATA_A78_1941498``: This applies errata 1941498 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU. + +- ``ERRATA_A78_1951500``: This applies errata 1951500 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r1p0 and r1p1, r0p0 has the same + issue but there is no workaround for that revision. + +- ``ERRATA_A78_1821534``: This applies errata 1821534 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0 and r1p0. + +- ``ERRATA_A78_1952683``: This applies errata 1952683 workaround to Cortex-A78 + CPU. This needs to be enabled for revision r0p0, it is fixed in r1p0. + +- ``ERRATA_A78_2132060``: This applies errata 2132060 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r0p0, r1p0, r1p1, and r1p2. It + is still open. + +- ``ERRATA_A78_2242635``: This applies errata 2242635 workaround to Cortex-A78 + CPU. This needs to be enabled for revisions r1p0, r1p1, and r1p2. The issue + is present in r0p0 but there is no workaround. It is still open. + +For Cortex-A78 AE, the following errata build flags are defined : + +- ``ERRATA_A78_AE_1941500`` : This applies errata 1941500 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. + This erratum is still open. + +- ``ERRATA_A78_AE_1951502`` : This applies errata 1951502 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +- ``ERRATA_A78_AE_2376748`` : This applies errata 2376748 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +- ``ERRATA_A78_AE_2395408`` : This applies errata 2395408 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions r0p0 and r0p1. This + erratum is still open. + +- ``ERRATA_A78_AE_2743093``: This applies errata 2743093 workaround to Cortex-A78 AE + CPU. This needs to be enabled for revisions r0p0, r0p1 and r0p2. + +- ``ERRATA_A78_AE_2743229`` : This applies errata 2743229 workaround to + Cortex-A78 AE CPU. This needs to be enabled for revisions <= r0p2. + +For Neoverse N1, the following errata build flags are defined : + +- ``ERRATA_N1_1073348``: This applies errata 1073348 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision r0p0 and r1p0 of the CPU. + +- ``ERRATA_N1_1130799``: This applies errata 1130799 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1165347``: This applies errata 1165347 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1207823``: This applies errata 1207823 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1220197``: This applies errata 1220197 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r2p0 of the CPU. + +- ``ERRATA_N1_1257314``: This applies errata 1257314 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1262606``: This applies errata 1262606 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1262888``: This applies errata 1262888 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1275112``: This applies errata 1275112 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1315703``: This applies errata 1315703 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r3p0 of the CPU. + +- ``ERRATA_N1_1542419``: This applies errata 1542419 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revisions r3p0 - r4p0 of the CPU. + +- ``ERRATA_N1_1868343``: This applies errata 1868343 workaround to Neoverse-N1 + CPU. This needs to be enabled only for revision <= r4p0 of the CPU. + +- ``ERRATA_N1_1946160``: This applies errata 1946160 workaround to Neoverse-N1 + CPU. This needs to be enabled for revisions r3p0, r3p1, r4p0, and r4p1, for + revisions r0p0, r1p0, and r2p0 there is no workaround. + +For Neoverse V1, the following errata build flags are defined : + +- ``ERRATA_V1_1774420``: This applies errata 1774420 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1791573``: This applies errata 1791573 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1852267``: This applies errata 1852267 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revisions r0p0 and r1p0, it is fixed + in r1p1. + +- ``ERRATA_V1_1925756``: This applies errata 1925756 workaround to Neoverse-V1 + CPU. This needs to be enabled for r0p0, r1p0, and r1p1, it is still open. + +- ``ERRATA_V1_1940577``: This applies errata 1940577 workaround to Neoverse-V1 + CPU. This needs to be enabled only for revision r1p0 and r1p1 of the + CPU. + +- ``ERRATA_V1_1966096``: This applies errata 1966096 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the + issue is present in r0p0 as well but there is no workaround for that + revision. It is still open. + +- ``ERRATA_V1_2139242``: This applies errata 2139242 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the + CPU. It is still open. + +- ``ERRATA_V1_2108267``: This applies errata 2108267 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r1p1 of the CPU. + It is still open. + +- ``ERRATA_V1_2216392``: This applies errata 2216392 workaround to Neoverse-V1 + CPU. This needs to be enabled for revisions r1p0 and r1p1 of the CPU, the + issue is present in r0p0 as well but there is no workaround for that + revision. It is still open. + +For Cortex-A710, the following errata build flags are defined : + +- ``ERRATA_A710_1987031``: This applies errata 1987031 workaround to + Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU. It is still open. + +- ``ERRATA_A710_2081180``: This applies errata 2081180 workaround to + Cortex-A710 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU. It is still open. + +- ``ERRATA_A710_2055002``: This applies errata 2055002 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r1p0, r2p0 of the CPU + and is still open. + +- ``ERRATA_A710_2017096``: This applies errata 2017096 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is still open. + +- ``ERRATA_A710_2083908``: This applies errata 2083908 workaround to + Cortex-A710 CPU. This needs to be enabled for revision r2p0 of the CPU and + is still open. + +- ``ERRATA_A710_2058056``: This applies errata 2058056 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is still open. + +- ``ERRATA_A710_2267065``: This applies errata 2267065 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +- ``ERRATA_A710_2136059``: This applies errata 2136059 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +- ``ERRATA_A710_2282622``: This applies errata 2282622 workaround to + Cortex-A710 CPU. This needs to be enabled for revisions r0p0, r1p0 and r2p0 + of the CPU and is fixed in r2p1. + +For Neoverse N2, the following errata build flags are defined : + +- ``ERRATA_N2_2002655``: This applies errata 2002655 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU, it is still open. + +- ``ERRATA_N2_2067956``: This applies errata 2067956 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2025414``: This applies errata 2025414 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2189731``: This applies errata 2189731 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138956``: This applies errata 2138956 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138953``: This applies errata 2138953 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2242415``: This applies errata 2242415 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2138958``: This applies errata 2138958 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2242400``: This applies errata 2242400 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +- ``ERRATA_N2_2280757``: This applies errata 2280757 workaround to Neoverse-N2 + CPU. This needs to be enabled for revision r0p0 of the CPU and is still open. + +For Cortex-X2, the following errata build flags are defined : + +- ``ERRATA_X2_2002765``: This applies errata 2002765 workaround to Cortex-X2 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU, + it is still open. + +- ``ERRATA_X2_2058056``: This applies errata 2058056 workaround to Cortex-X2 + CPU. This needs to be enabled for revisions r0p0, r1p0, and r2p0 of the CPU, + it is still open. + +- ``ERRATA_X2_2083908``: This applies errata 2083908 workaround to Cortex-X2 + CPU. This needs to be enabled for revision r2p0 of the CPU, it is still open. + +- ``ERRATA_X2_2017096``: This applies errata 2017096 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +- ``ERRATA_X2_2081180``: This applies errata 2081180 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +- ``ERRATA_X2_2216384``: This applies errata 2216384 workaround to + Cortex-X2 CPU. This needs to be enabled only for revisions r0p0, r1p0 and + r2p0 of the CPU, it is fixed in r2p1. + +For Cortex-A510, the following errata build flags are defined : + +- ``ERRATA_A510_1922240``: This applies errata 1922240 workaround to + Cortex-A510 CPU. This needs to be enabled only for revision r0p0, it is + fixed in r0p1. + +- ``ERRATA_A510_2288014``: This applies errata 2288014 workaround to + Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1, + r0p2, r0p3 and r1p0, it is fixed in r1p1. + +- ``ERRATA_A510_2042739``: This applies errata 2042739 workaround to + Cortex-A510 CPU. This needs to be enabled only for revisions r0p0, r0p1 and + r0p2, it is fixed in r0p3. + +- ``ERRATA_A510_2041909``: This applies errata 2041909 workaround to + Cortex-A510 CPU. This needs to be enabled only for revision r0p2 and is fixed + in r0p3. The issue is also present in r0p0 and r0p1 but there is no + workaround for those revisions. + +- ``ERRATA_A510_2250311``: This applies errata 2250311 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. This workaround disables MPMM even if + ENABLE_MPMM=1. + +- ``ERRATA_A510_2218950``: This applies errata 2218950 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. + +- ``ERRATA_A510_2172148``: This applies errata 2172148 workaround to + Cortex-A510 CPU. This needs to be enabled for revisions r0p0, r0p1, r0p2, + r0p3 and r1p0, it is fixed in r1p1. + +DSU Errata Workarounds +---------------------- + +Similar to CPU errata, TF-A also implements workarounds for DSU (DynamIQ +Shared Unit) errata. The DSU errata details can be found in the respective Arm +documentation: + +- `Arm DSU Software Developers Errata Notice`_. + +Each erratum is identified by an ``ID``, as defined in the DSU errata notice +document. Thus, the build flags which enable/disable the errata workarounds +have the format ``ERRATA_DSU_``. The implementation and application logic +of DSU errata workarounds are similar to `CPU errata workarounds`_. + +For DSU errata, the following build flags are defined: + +- ``ERRATA_DSU_798953``: This applies errata 798953 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + revision is r0p0 (on r0p1 it is fixed). However, please note that this + workaround results in increased DSU power consumption on idle. + +- ``ERRATA_DSU_936184``: This applies errata 936184 workaround for the + affected DSU configurations. This errata applies only for those DSUs that + contain the ACP interface **and** the DSU revision is older than r2p0 (on + r2p0 it is fixed). However, please note that this workaround results in + increased DSU power consumption on idle. + +CPU Specific optimizations +-------------------------- + +This section describes some of the optimizations allowed by the CPU micro +architecture that can be enabled by the platform as desired. + +- ``SKIP_A57_L1_FLUSH_PWR_DWN``: This flag enables an optimization in the + Cortex-A57 cluster power down sequence by not flushing the Level 1 data + cache. The L1 data cache and the L2 unified cache are inclusive. A flush + of the L2 by set/way flushes any dirty lines from the L1 as well. This + is a known safe deviation from the Cortex-A57 TRM defined power down + sequence. Each Cortex-A57 based platform must make its own decision on + whether to use the optimization. + +- ``A53_DISABLE_NON_TEMPORAL_HINT``: This flag disables the cache non-temporal + hint. The LDNP/STNP instructions as implemented on Cortex-A53 do not behave + in a way most programmers expect, and will most probably result in a + significant speed degradation to any code that employs them. The Armv8-A + architecture (see Arm DDI 0487A.h, section D3.4.3) allows cores to ignore + the non-temporal hint and treat LDNP/STNP as LDP/STP instead. Enabling this + flag enforces this behaviour. This needs to be enabled only for revisions + <= r0p3 of the CPU and is enabled by default. + +- ``A57_DISABLE_NON_TEMPORAL_HINT``: This flag has the same behaviour as + ``A53_DISABLE_NON_TEMPORAL_HINT`` but for Cortex-A57. This needs to be + enabled only for revisions <= r1p2 of the CPU and is enabled by default, + as recommended in section "4.7 Non-Temporal Loads/Stores" of the + `Cortex-A57 Software Optimization Guide`_. + +- ''A57_ENABLE_NON_CACHEABLE_LOAD_FWD'': This flag enables non-cacheable + streaming enhancement feature for Cortex-A57 CPUs. Platforms can set + this bit only if their memory system meets the requirement that cache + line fill requests from the Cortex-A57 processor are atomic. Each + Cortex-A57 based platform must make its own decision on whether to use + the optimization. This flag is disabled by default. + +- ``NEOVERSE_Nx_EXTERNAL_LLC``: This flag indicates that an external last + level cache(LLC) is present in the system, and that the DataSource field + on the master CHI interface indicates when data is returned from the LLC. + This is used to control how the LL_CACHE* PMU events count. + Default value is 0 (Disabled). + +-------------- + +*Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.* + +.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 +.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 +.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960 +.. _Cortex-A53 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm048406/index.html +.. _Cortex-A57 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm049219/index.html +.. _Cortex-A72 MPCore Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm012079/index.html +.. _Cortex-A57 Software Optimization Guide: http://infocenter.arm.com/help/topic/com.arm.doc.uan0015b/Cortex_A57_Software_Optimization_Guide_external.pdf +.. _Arm DSU Software Developers Errata Notice: http://infocenter.arm.com/help/topic/com.arm.doc.epm138168/index.html diff --git a/arm-trusted-firmware/docs/design/firmware-design.rst b/arm-trusted-firmware/docs/design/firmware-design.rst new file mode 100644 index 0000000..0831dc0 --- /dev/null +++ b/arm-trusted-firmware/docs/design/firmware-design.rst @@ -0,0 +1,2743 @@ +Firmware Design +=============== + +Trusted Firmware-A (TF-A) implements a subset of the Trusted Board Boot +Requirements (TBBR) Platform Design Document (PDD) for Arm reference +platforms. + +The TBB sequence starts when the platform is powered on and runs up +to the stage where it hands-off control to firmware running in the normal +world in DRAM. This is the cold boot path. + +TF-A also implements the `Power State Coordination Interface PDD`_ as a +runtime service. PSCI is the interface from normal world software to firmware +implementing power management use-cases (for example, secondary CPU boot, +hotplug and idle). Normal world software can access TF-A runtime services via +the Arm SMC (Secure Monitor Call) instruction. The SMC instruction must be +used as mandated by the SMC Calling Convention (`SMCCC`_). + +TF-A implements a framework for configuring and managing interrupts generated +in either security state. The details of the interrupt management framework +and its design can be found in :ref:`Interrupt Management Framework`. + +TF-A also implements a library for setting up and managing the translation +tables. The details of this library can be found in +:ref:`Translation (XLAT) Tables Library`. + +TF-A can be built to support either AArch64 or AArch32 execution state. + +.. note:: + + The descriptions in this chapter are for the Arm TrustZone architecture. + For changes to the firmware design for the + `Arm Confidential Compute Architecture (Arm CCA)`_ please refer to the + chapter :ref:`Realm Management Extension (RME)`. + +Cold boot +--------- + +The cold boot path starts when the platform is physically turned on. If +``COLD_BOOT_SINGLE_CPU=0``, one of the CPUs released from reset is chosen as the +primary CPU, and the remaining CPUs are considered secondary CPUs. The primary +CPU is chosen through platform-specific means. The cold boot path is mainly +executed by the primary CPU, other than essential CPU initialization executed by +all CPUs. The secondary CPUs are kept in a safe platform-specific state until +the primary CPU has performed enough initialization to boot them. + +Refer to the :ref:`CPU Reset` for more information on the effect of the +``COLD_BOOT_SINGLE_CPU`` platform build option. + +The cold boot path in this implementation of TF-A depends on the execution +state. For AArch64, it is divided into five steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-1 (BL31) *EL3 Runtime Software* +- Boot Loader stage 3-2 (BL32) *Secure-EL1 Payload* (optional) +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +For AArch32, it is divided into four steps (in order of execution): + +- Boot Loader stage 1 (BL1) *AP Trusted ROM* +- Boot Loader stage 2 (BL2) *Trusted Boot Firmware* +- Boot Loader stage 3-2 (BL32) *EL3 Runtime Software* +- Boot Loader stage 3-3 (BL33) *Non-trusted Firmware* + +Arm development platforms (Fixed Virtual Platforms (FVPs) and Juno) implement a +combination of the following types of memory regions. Each bootloader stage uses +one or more of these memory regions. + +- Regions accessible from both non-secure and secure states. For example, + non-trusted SRAM, ROM and DRAM. +- Regions accessible from only the secure state. For example, trusted SRAM and + ROM. The FVPs also implement the trusted DRAM which is statically + configured. Additionally, the Base FVPs and Juno development platform + configure the TrustZone Controller (TZC) to create a region in the DRAM + which is accessible only from the secure state. + +The sections below provide the following details: + +- dynamic configuration of Boot Loader stages +- initialization and execution of the first three stages during cold boot +- specification of the EL3 Runtime Software (BL31 for AArch64 and BL32 for + AArch32) entrypoint requirements for use by alternative Trusted Boot + Firmware in place of the provided BL1 and BL2 + +Dynamic Configuration during cold boot +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each of the Boot Loader stages may be dynamically configured if required by the +platform. The Boot Loader stage may optionally specify a firmware +configuration file and/or hardware configuration file as listed below: + +- FW_CONFIG - The firmware configuration file. Holds properties shared across + all BLx images. + An example is the "dtb-registry" node, which contains the information about + the other device tree configurations (load-address, size, image_id). +- HW_CONFIG - The hardware configuration file. Can be shared by all Boot Loader + stages and also by the Normal World Rich OS. +- TB_FW_CONFIG - Trusted Boot Firmware configuration file. Shared between BL1 + and BL2. +- SOC_FW_CONFIG - SoC Firmware configuration file. Used by BL31. +- TOS_FW_CONFIG - Trusted OS Firmware configuration file. Used by Trusted OS + (BL32). +- NT_FW_CONFIG - Non Trusted Firmware configuration file. Used by Non-trusted + firmware (BL33). + +The Arm development platforms use the Flattened Device Tree format for the +dynamic configuration files. + +Each Boot Loader stage can pass up to 4 arguments via registers to the next +stage. BL2 passes the list of the next images to execute to the *EL3 Runtime +Software* (BL31 for AArch64 and BL32 for AArch32) via `arg0`. All the other +arguments are platform defined. The Arm development platforms use the following +convention: + +- BL1 passes the address of a meminfo_t structure to BL2 via ``arg1``. This + structure contains the memory layout available to BL2. +- When dynamic configuration files are present, the firmware configuration for + the next Boot Loader stage is populated in the first available argument and + the generic hardware configuration is passed the next available argument. + For example, + + - FW_CONFIG is loaded by BL1, then its address is passed in ``arg0`` to BL2. + - TB_FW_CONFIG address is retrieved by BL2 from FW_CONFIG device tree. + - If HW_CONFIG is loaded by BL1, then its address is passed in ``arg2`` to + BL2. Note, ``arg1`` is already used for meminfo_t. + - If SOC_FW_CONFIG is loaded by BL2, then its address is passed in ``arg1`` + to BL31. Note, ``arg0`` is used to pass the list of executable images. + - Similarly, if HW_CONFIG is loaded by BL1 or BL2, then its address is + passed in ``arg2`` to BL31. + - For other BL3x images, if the firmware configuration file is loaded by + BL2, then its address is passed in ``arg0`` and if HW_CONFIG is loaded + then its address is passed in ``arg1``. + +BL1 +~~~ + +This stage begins execution from the platform's reset vector at EL3. The reset +address is platform dependent but it is usually located in a Trusted ROM area. +The BL1 data section is copied to trusted SRAM at runtime. + +On the Arm development platforms, BL1 code starts execution from the reset +vector defined by the constant ``BL1_RO_BASE``. The BL1 data section is copied +to the top of trusted SRAM as defined by the constant ``BL1_RW_BASE``. + +The functionality implemented by this stage is as follows. + +Determination of boot path +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Whenever a CPU is released from reset, BL1 needs to distinguish between a warm +boot and a cold boot. This is done using platform-specific mechanisms (see the +``plat_get_my_entrypoint()`` function in the :ref:`Porting Guide`). In the case +of a warm boot, a CPU is expected to continue execution from a separate +entrypoint. In the case of a cold boot, the secondary CPUs are placed in a safe +platform-specific state (see the ``plat_secondary_cold_boot_setup()`` function in +the :ref:`Porting Guide`) while the primary CPU executes the remaining cold boot +path as described in the following sections. + +This step only applies when ``PROGRAMMABLE_RESET_ADDRESS=0``. Refer to the +:ref:`CPU Reset` for more information on the effect of the +``PROGRAMMABLE_RESET_ADDRESS`` platform build option. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL1 performs minimal architectural initialization as follows. + +- Exception vectors + + BL1 sets up simple exception vectors for both synchronous and asynchronous + exceptions. The default behavior upon receiving an exception is to populate + a status code in the general purpose register ``X0/R0`` and call the + ``plat_report_exception()`` function (see the :ref:`Porting Guide`). The + status code is one of: + + For AArch64: + + :: + + 0x0 : Synchronous exception from Current EL with SP_EL0 + 0x1 : IRQ exception from Current EL with SP_EL0 + 0x2 : FIQ exception from Current EL with SP_EL0 + 0x3 : System Error exception from Current EL with SP_EL0 + 0x4 : Synchronous exception from Current EL with SP_ELx + 0x5 : IRQ exception from Current EL with SP_ELx + 0x6 : FIQ exception from Current EL with SP_ELx + 0x7 : System Error exception from Current EL with SP_ELx + 0x8 : Synchronous exception from Lower EL using aarch64 + 0x9 : IRQ exception from Lower EL using aarch64 + 0xa : FIQ exception from Lower EL using aarch64 + 0xb : System Error exception from Lower EL using aarch64 + 0xc : Synchronous exception from Lower EL using aarch32 + 0xd : IRQ exception from Lower EL using aarch32 + 0xe : FIQ exception from Lower EL using aarch32 + 0xf : System Error exception from Lower EL using aarch32 + + For AArch32: + + :: + + 0x10 : User mode + 0x11 : FIQ mode + 0x12 : IRQ mode + 0x13 : SVC mode + 0x16 : Monitor mode + 0x17 : Abort mode + 0x1a : Hypervisor mode + 0x1b : Undefined mode + 0x1f : System mode + + The ``plat_report_exception()`` implementation on the Arm FVP port programs + the Versatile Express System LED register in the following format to + indicate the occurrence of an unexpected exception: + + :: + + SYS_LED[0] - Security state (Secure=0/Non-Secure=1) + SYS_LED[2:1] - Exception Level (EL3=0x3, EL2=0x2, EL1=0x1, EL0=0x0) + For AArch32 it is always 0x0 + SYS_LED[7:3] - Exception Class (Sync/Async & origin). This is the value + of the status code + + A write to the LED register reflects in the System LEDs (S6LED0..7) in the + CLCD window of the FVP. + + BL1 does not expect to receive any exceptions other than the SMC exception. + For the latter, BL1 installs a simple stub. The stub expects to receive a + limited set of SMC types (determined by their function IDs in the general + purpose register ``X0/R0``): + + - ``BL1_SMC_RUN_IMAGE``: This SMC is raised by BL2 to make BL1 pass control + to EL3 Runtime Software. + - All SMCs listed in section "BL1 SMC Interface" in the :ref:`Firmware Update (FWU)` + Design Guide are supported for AArch64 only. These SMCs are currently + not supported when BL1 is built for AArch32. + + Any other SMC leads to an assertion failure. + +- CPU initialization + + BL1 calls the ``reset_handler()`` function which in turn calls the CPU + specific reset handler function (see the section: "CPU specific operations + framework"). + +- Control register setup (for AArch64) + + - ``SCTLR_EL3``. Instruction cache is enabled by setting the ``SCTLR_EL3.I`` + bit. Alignment and stack alignment checking is enabled by setting the + ``SCTLR_EL3.A`` and ``SCTLR_EL3.SA`` bits. Exception endianness is set to + little-endian by clearing the ``SCTLR_EL3.EE`` bit. + + - ``SCR_EL3``. The register width of the next lower exception level is set + to AArch64 by setting the ``SCR.RW`` bit. The ``SCR.EA`` bit is set to trap + both External Aborts and SError Interrupts in EL3. The ``SCR.SIF`` bit is + also set to disable instruction fetches from Non-secure memory when in + secure state. + + - ``CPTR_EL3``. Accesses to the ``CPACR_EL1`` register from EL1 or EL2, or the + ``CPTR_EL2`` register from EL2 are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TCPAC`` bit. Access to the trace functionality is + configured not to trap to EL3 by clearing the ``CPTR_EL3.TTA`` bit. + Instructions that access the registers associated with Floating Point + and Advanced SIMD execution are configured to not trap to EL3 by + clearing the ``CPTR_EL3.TFP`` bit. + + - ``DAIF``. The SError interrupt is enabled by clearing the SError interrupt + mask bit. + + - ``MDCR_EL3``. The trap controls, ``MDCR_EL3.TDOSA``, ``MDCR_EL3.TDA`` and + ``MDCR_EL3.TPM``, are set so that accesses to the registers they control + do not trap to EL3. AArch64 Secure self-hosted debug is disabled by + setting the ``MDCR_EL3.SDD`` bit. Also ``MDCR_EL3.SPD32`` is set to + disable AArch32 Secure self-hosted privileged debug from S-EL1. + +- Control register setup (for AArch32) + + - ``SCTLR``. Instruction cache is enabled by setting the ``SCTLR.I`` bit. + Alignment checking is enabled by setting the ``SCTLR.A`` bit. + Exception endianness is set to little-endian by clearing the + ``SCTLR.EE`` bit. + + - ``SCR``. The ``SCR.SIF`` bit is set to disable instruction fetches from + Non-secure memory when in secure state. + + - ``CPACR``. Allow execution of Advanced SIMD instructions at PL0 and PL1, + by clearing the ``CPACR.ASEDIS`` bit. Access to the trace functionality + is configured not to trap to undefined mode by clearing the + ``CPACR.TRCDIS`` bit. + + - ``NSACR``. Enable non-secure access to Advanced SIMD functionality and + system register access to implemented trace registers. + + - ``FPEXC``. Enable access to the Advanced SIMD and floating-point + functionality from all Exception levels. + + - ``CPSR.A``. The Asynchronous data abort interrupt is enabled by clearing + the Asynchronous data abort interrupt mask bit. + + - ``SDCR``. The ``SDCR.SPD`` field is set to disable AArch32 Secure + self-hosted privileged debug. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL1 performs the following platform initializations: + +- Enable the Trusted Watchdog. +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Configure any required platform storage to load the next bootloader image + (BL2). +- If the BL1 dynamic configuration file, ``TB_FW_CONFIG``, is available, then + load it to the platform defined address and make it available to BL2 via + ``arg0``. +- Configure the system timer and program the `CNTFRQ_EL0` for use by NS-BL1U + and NS-BL2U firmware update images. + +Firmware Update detection and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +After performing platform setup, BL1 common code calls +``bl1_plat_get_next_image_id()`` to determine if :ref:`Firmware Update (FWU)` is +required or to proceed with the normal boot process. If the platform code +returns ``BL2_IMAGE_ID`` then the normal boot sequence is executed as described +in the next section, else BL1 assumes that :ref:`Firmware Update (FWU)` is +required and execution passes to the first image in the +:ref:`Firmware Update (FWU)` process. In either case, BL1 retrieves a descriptor +of the next image by calling ``bl1_plat_get_image_desc()``. The image descriptor +contains an ``entry_point_info_t`` structure, which BL1 uses to initialize the +execution state of the next image. + +BL2 image load and execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In the normal boot flow, BL1 execution continues as follows: + +#. BL1 prints the following string from the primary CPU to indicate successful + execution of the BL1 stage: + + :: + + "Booting Trusted Firmware" + +#. BL1 loads a BL2 raw binary image from platform storage, at a + platform-specific base address. Prior to the load, BL1 invokes + ``bl1_plat_handle_pre_image_load()`` which allows the platform to update or + use the image information. If the BL2 image file is not present or if + there is not enough free trusted SRAM the following error message is + printed: + + :: + + "Failed to load BL2 firmware." + +#. BL1 invokes ``bl1_plat_handle_post_image_load()`` which again is intended + for platforms to take further action after image load. This function must + populate the necessary arguments for BL2, which may also include the memory + layout. Further description of the memory layout can be found later + in this document. + +#. BL1 passes control to the BL2 image at Secure EL1 (for AArch64) or at + Secure SVC mode (for AArch32), starting from its load address. + +BL2 +~~~ + +BL1 loads and passes control to BL2 at Secure-EL1 (for AArch64) or at Secure +SVC mode (for AArch32) . BL2 is linked against and loaded at a platform-specific +base address (more information can be found later in this document). +The functionality implemented by BL2 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For AArch64, BL2 performs the minimal architectural initialization required +for subsequent stages of TF-A and normal world software. EL1 and EL0 are given +access to Floating Point and Advanced SIMD registers by setting the +``CPACR.FPEN`` bits. + +For AArch32, the minimal architectural initialization required for subsequent +stages of TF-A and normal world software is taken care of in BL1 as both BL1 +and BL2 execute at PL1. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +On Arm platforms, BL2 performs the following platform initializations: + +- Initialize the console. +- Configure any required platform storage to allow loading further bootloader + images. +- Enable the MMU and map the memory it needs to access. +- Perform platform security setup to allow access to controlled components. +- Reserve some memory for passing information to the next bootloader image + EL3 Runtime Software and populate it. +- Define the extents of memory available for loading each subsequent + bootloader image. +- If BL1 has passed TB_FW_CONFIG dynamic configuration file in ``arg0``, + then parse it. + +Image loading in BL2 +^^^^^^^^^^^^^^^^^^^^ + +BL2 generic code loads the images based on the list of loadable images +provided by the platform. BL2 passes the list of executable images +provided by the platform to the next handover BL image. + +The list of loadable images provided by the platform may also contain +dynamic configuration files. The files are loaded and can be parsed as +needed in the ``bl2_plat_handle_post_image_load()`` function. These +configuration files can be passed to next Boot Loader stages as arguments +by updating the corresponding entrypoint information in this function. + +SCP_BL2 (System Control Processor Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some systems have a separate System Control Processor (SCP) for power, clock, +reset and system control. BL2 loads the optional SCP_BL2 image from platform +storage into a platform-specific region of secure memory. The subsequent +handling of SCP_BL2 is platform specific. For example, on the Juno Arm +development platform port the image is transferred into SCP's internal memory +using the Boot Over MHU (BOM) protocol after being loaded in the trusted SRAM +memory. The SCP executes SCP_BL2 and signals to the Application Processor (AP) +for BL2 execution to continue. + +EL3 Runtime Software image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the EL3 Runtime Software image from platform storage into a platform- +specific address in trusted SRAM. If there is not enough memory to load the +image or image is missing it leads to an assertion failure. + +AArch64 BL32 (Secure-EL1 Payload) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the optional BL32 image from platform storage into a platform- +specific region of secure memory. The image executes in the secure world. BL2 +relies on BL31 to pass control to the BL32 image, if present. Hence, BL2 +populates a platform-specific area of memory with the entrypoint/load-address +of the BL32 image. The value of the Saved Processor Status Register (``SPSR``) +for entry into BL32 is not determined by BL2, it is initialized by the +Secure-EL1 Payload Dispatcher (see later) within BL31, which is responsible for +managing interaction with BL32. This information is passed to BL31. + +BL33 (Non-trusted Firmware) image load +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 loads the BL33 image (e.g. UEFI or other test or boot software) from +platform storage into non-secure memory as defined by the platform. + +BL2 relies on EL3 Runtime Software to pass control to BL33 once secure state +initialization is complete. Hence, BL2 populates a platform-specific area of +memory with the entrypoint and Saved Program Status Register (``SPSR``) of the +normal world software image. The entrypoint is the load address of the BL33 +image. The ``SPSR`` is determined as specified in Section 5.13 of the +`Power State Coordination Interface PDD`_. This information is passed to the +EL3 Runtime Software. + +AArch64 BL31 (EL3 Runtime Software) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL2 execution continues as follows: + +#. BL2 passes control back to BL1 by raising an SMC, providing BL1 with the + BL31 entrypoint. The exception is handled by the SMC exception handler + installed by BL1. + +#. BL1 turns off the MMU and flushes the caches. It clears the + ``SCTLR_EL3.M/I/C`` bits, flushes the data cache to the point of coherency + and invalidates the TLBs. + +#. BL1 passes control to BL31 at the specified entrypoint at EL3. + +Running BL2 at EL3 execution level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have a non-TF-A Boot ROM that expects the next boot stage +to execute at EL3. On these platforms, TF-A BL1 is a waste of memory +as its only purpose is to ensure TF-A BL2 is entered at S-EL1. To avoid +this waste, a special mode enables BL2 to execute at EL3, which allows +a non-TF-A Boot ROM to load and jump directly to BL2. This mode is selected +when the build flag BL2_AT_EL3 is enabled. The main differences in this +mode are: + +#. BL2 includes the reset code and the mailbox mechanism to differentiate + cold boot and warm boot. It runs at EL3 doing the arch + initialization required for EL3. + +#. BL2 does not receive the meminfo information from BL1 anymore. This + information can be passed by the Boot ROM or be internal to the + BL2 image. + +#. Since BL2 executes at EL3, BL2 jumps directly to the next image, + instead of invoking the RUN_IMAGE SMC call. + + +We assume 3 different types of BootROM support on the platform: + +#. The Boot ROM always jumps to the same address, for both cold + and warm boot. In this case, we will need to keep a resident part + of BL2 whose memory cannot be reclaimed by any other image. The + linker script defines the symbols __TEXT_RESIDENT_START__ and + __TEXT_RESIDENT_END__ that allows the platform to configure + correctly the memory map. +#. The platform has some mechanism to indicate the jump address to the + Boot ROM. Platform code can then program the jump address with + psci_warmboot_entrypoint during cold boot. +#. The platform has some mechanism to program the reset address using + the PROGRAMMABLE_RESET_ADDRESS feature. Platform code can then + program the reset address with psci_warmboot_entrypoint during + cold boot, bypassing the boot ROM for warm boot. + +In the last 2 cases, no part of BL2 needs to remain resident at +runtime. In the first 2 cases, we expect the Boot ROM to be able to +differentiate between warm and cold boot, to avoid loading BL2 again +during warm boot. + +This functionality can be tested with FVP loading the image directly +in memory and changing the address where the system jumps at reset. +For example: + + -C cluster0.cpu0.RVBAR=0x4022000 + --data cluster0.cpu0=bl2.bin@0x4022000 + +With this configuration, FVP is like a platform of the first case, +where the Boot ROM jumps always to the same address. For simplification, +BL32 is loaded in DRAM in this case, to avoid other images reclaiming +BL2 memory. + + +AArch64 BL31 +~~~~~~~~~~~~ + +The image for this stage is loaded by BL2 and BL1 passes control to BL31 at +EL3. BL31 executes solely in trusted SRAM. BL31 is linked against and +loaded at a platform-specific base address (more information can be found later +in this document). The functionality implemented by BL31 is as follows. + +Architectural initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Currently, BL31 performs a similar architectural initialization to BL1 as +far as system register settings are concerned. Since BL1 code resides in ROM, +architectural initialization in BL31 allows override of any previous +initialization done by BL1. + +BL31 initializes the per-CPU data framework, which provides a cache of +frequently accessed per-CPU data optimised for fast, concurrent manipulation +on different CPUs. This buffer includes pointers to per-CPU contexts, crash +buffer, CPU reset and power down operations, PSCI data, platform data and so on. + +It then replaces the exception vectors populated by BL1 with its own. BL31 +exception vectors implement more elaborate support for handling SMCs since this +is the only mechanism to access the runtime services implemented by BL31 (PSCI +for example). BL31 checks each SMC for validity as specified by the +`SMC Calling Convention`_ before passing control to the required SMC +handler routine. + +BL31 programs the ``CNTFRQ_EL0`` register with the clock frequency of the system +counter, which is provided by the platform. + +Platform initialization +^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 performs detailed platform initialization, which enables normal world +software to function correctly. + +On Arm platforms, this consists of the following: + +- Initialize the console. +- Configure the Interconnect to enable hardware coherency. +- Enable the MMU and map the memory it needs to access. +- Initialize the generic interrupt controller. +- Initialize the power controller device. +- Detect the system topology. + +Runtime services initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +BL31 is responsible for initializing the runtime services. One of them is PSCI. + +As part of the PSCI initializations, BL31 detects the system topology. It also +initializes the data structures that implement the state machine used to track +the state of power domain nodes. The state can be one of ``OFF``, ``RUN`` or +``RETENTION``. All secondary CPUs are initially in the ``OFF`` state. The cluster +that the primary CPU belongs to is ``ON``; any other cluster is ``OFF``. It also +initializes the locks that protect them. BL31 accesses the state of a CPU or +cluster immediately after reset and before the data cache is enabled in the +warm boot path. It is not currently possible to use 'exclusive' based spinlocks, +therefore BL31 uses locks based on Lamport's Bakery algorithm instead. + +The runtime service framework and its initialization is described in more +detail in the "EL3 runtime services framework" section below. + +Details about the status of the PSCI implementation are provided in the +"Power State Coordination Interface" section below. + +AArch64 BL32 (Secure-EL1 Payload) image initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If a BL32 image is present then there must be a matching Secure-EL1 Payload +Dispatcher (SPD) service (see later for details). During initialization +that service must register a function to carry out initialization of BL32 +once the runtime services are fully initialized. BL31 invokes such a +registered function to initialize BL32 before running BL33. This initialization +is not necessary for AArch32 SPs. + +Details on BL32 initialization and the SPD's role are described in the +:ref:`firmware_design_sel1_spd` section below. + +BL33 (Non-trusted Firmware) execution +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +EL3 Runtime Software initializes the EL2 or EL1 processor context for normal- +world cold boot, ensuring that no secure state information finds its way into +the non-secure execution state. EL3 Runtime Software uses the entrypoint +information provided by BL2 to jump to the Non-trusted firmware image (BL33) +at the highest available Exception Level (EL2 if available, otherwise EL1). + +Using alternative Trusted Boot Firmware in place of BL1 & BL2 (AArch64 only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Some platforms have existing implementations of Trusted Boot Firmware that +would like to use TF-A BL31 for the EL3 Runtime Software. To enable this +firmware architecture it is important to provide a fully documented and stable +interface between the Trusted Boot Firmware and BL31. + +Future changes to the BL31 interface will be done in a backwards compatible +way, and this enables these firmware components to be independently enhanced/ +updated to develop and exploit new functionality. + +Required CPU state when calling ``bl31_entrypoint()`` during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch64 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +X0 and X1 can be used to pass information from the Trusted Boot Firmware to the +platform code in BL31: + +:: + + X0 : Reserved for common TF-A information + X1 : Platform specific information + +BL31 zero-init sections (e.g. ``.bss``) should not contain valid data on entry, +these will be zero filled prior to invoking platform setup code. + +Use of the X0 and X1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and passed from ``bl31_entrypoint()`` to +``bl31_early_platform_setup()``. The value of these parameters is never directly +used by the common BL31 code. + +The convention is that ``X0`` conveys information regarding the BL31, BL32 and +BL33 images from the Trusted Boot firmware and ``X1`` can be used for other +platform specific purpose. This convention allows platforms which use TF-A's +BL1 and BL2 images to transfer additional platform specific information from +Secure Boot without conflicting with future evolution of TF-A using ``X0`` to +pass a ``bl31_params`` structure. + +BL31 common and SPD initialization code depends on image and entrypoint +information about BL33 and BL32, which is provided via BL31 platform APIs. +This information is required until the start of execution of BL33. This +information can be provided in a platform defined manner, e.g. compiled into +the platform code in BL31, or provided in a platform defined memory location +by the Trusted Boot firmware, or passed from the Trusted Boot Firmware via the +Cold boot Initialization parameters. This data may need to be cleaned out of +the CPU caches if it is provided by an earlier boot stage and then accessed by +BL31 platform code before the caches are enabled. + +TF-A's BL2 implementation passes a ``bl31_params`` structure in +``X0`` and the Arm development platforms interpret this in the BL31 platform +code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +BL31 does not depend on the enabled state of the MMU, data caches or +interconnect coherency on entry to ``bl31_entrypoint()``. If these are disabled +on entry, these should be enabled during ``bl31_plat_arch_setup()``. + +Data structures used in the BL31 cold boot interface +'''''''''''''''''''''''''''''''''''''''''''''''''''' + +These structures are designed to support compatibility and independent +evolution of the structures and the firmware images. For example, a version of +BL31 that can interpret the BL3x image information from different versions of +BL2, a platform that uses an extended entry_point_info structure to convey +additional register information to BL31, or a ELF image loader that can convey +more details about the firmware images. + +To support these scenarios the structures are versioned and sized, which enables +BL31 to detect which information is present and respond appropriately. The +``param_header`` is defined to capture this information: + +.. code:: c + + typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ + } param_header_t; + +The structures using this format are ``entry_point_info``, ``image_info`` and +``bl31_params``. The code that allocates and populates these structures must set +the header fields appropriately, and the ``SET_PARAM_HEAD()`` a macro is defined +to simplify this action. + +Required CPU state for BL31 Warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, TF-A provides +the platform power management code with a Warm boot initialization +entry-point, to be invoked by the CPU immediately after the reset handler. +On entry to the Warm boot initialization function the calling CPU must be in +AArch64 EL3, little-endian data access and all interrupt sources masked: + +:: + + PSTATE.EL = 3 + PSTATE.RW = 1 + PSTATE.DAIF = 0xf + SCTLR_EL3.EE = 0 + +The PSCI implementation will initialize the processor state and ensure that the +platform power management code is then invoked as required to initialize all +necessary system, cluster and CPU resources. + +AArch32 EL3 Runtime Software entrypoint interface +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To enable this firmware architecture it is important to provide a fully +documented and stable interface between the Trusted Boot Firmware and the +AArch32 EL3 Runtime Software. + +Future changes to the entrypoint interface will be done in a backwards +compatible way, and this enables these firmware components to be independently +enhanced/updated to develop and exploit new functionality. + +Required CPU state when entering during cold boot +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This function must only be called by the primary CPU. + +On entry to this function the calling primary CPU must be executing in AArch32 +EL3, little-endian data access, and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +R0 and R1 are used to pass information from the Trusted Boot Firmware to the +platform code in AArch32 EL3 Runtime Software: + +:: + + R0 : Reserved for common TF-A information + R1 : Platform specific information + +Use of the R0 and R1 parameters +''''''''''''''''''''''''''''''' + +The parameters are platform specific and the convention is that ``R0`` conveys +information regarding the BL3x images from the Trusted Boot firmware and ``R1`` +can be used for other platform specific purpose. This convention allows +platforms which use TF-A's BL1 and BL2 images to transfer additional platform +specific information from Secure Boot without conflicting with future +evolution of TF-A using ``R0`` to pass a ``bl_params`` structure. + +The AArch32 EL3 Runtime Software is responsible for entry into BL33. This +information can be obtained in a platform defined manner, e.g. compiled into +the AArch32 EL3 Runtime Software, or provided in a platform defined memory +location by the Trusted Boot firmware, or passed from the Trusted Boot Firmware +via the Cold boot Initialization parameters. This data may need to be cleaned +out of the CPU caches if it is provided by an earlier boot stage and then +accessed by AArch32 EL3 Runtime Software before the caches are enabled. + +When using AArch32 EL3 Runtime Software, the Arm development platforms pass a +``bl_params`` structure in ``R0`` from BL2 to be interpreted by AArch32 EL3 Runtime +Software platform code. + +MMU, Data caches & Coherency +'''''''''''''''''''''''''''' + +AArch32 EL3 Runtime Software must not depend on the enabled state of the MMU, +data caches or interconnect coherency in its entrypoint. They must be explicitly +enabled if required. + +Data structures used in cold boot interface +''''''''''''''''''''''''''''''''''''''''''' + +The AArch32 EL3 Runtime Software cold boot interface uses ``bl_params`` instead +of ``bl31_params``. The ``bl_params`` structure is based on the convention +described in AArch64 BL31 cold boot interface section. + +Required CPU state for warm boot initialization +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When requesting a CPU power-on, or suspending a running CPU, AArch32 EL3 +Runtime Software must ensure execution of a warm boot initialization entrypoint. +If TF-A BL1 is used and the PROGRAMMABLE_RESET_ADDRESS build flag is false, +then AArch32 EL3 Runtime Software must ensure that BL1 branches to the warm +boot entrypoint by arranging for the BL1 platform function, +plat_get_my_entrypoint(), to return a non-zero value. + +In this case, the warm boot entrypoint must be in AArch32 EL3, little-endian +data access and all interrupt sources masked: + +:: + + PSTATE.AIF = 0x7 + SCTLR.EE = 0 + +The warm boot entrypoint may be implemented by using TF-A +``psci_warmboot_entrypoint()`` function. In that case, the platform must fulfil +the pre-requisites mentioned in the +:ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + +EL3 runtime services framework +------------------------------ + +Software executing in the non-secure state and in the secure state at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +returned. + +The EL3 runtime services framework enables the development of services by +different providers that can be easily integrated into final product firmware. +The following sections describe the framework which facilitates the +registration, initialization and use of runtime services in EL3 Runtime +Software (BL31). + +The design of the runtime services depends heavily on the concepts and +definitions described in the `SMCCC`_, in particular SMC Function IDs, Owning +Entity Numbers (OEN), Fast and Yielding calls, and the SMC32 and SMC64 calling +conventions. Please refer to that document for more detailed explanation of +these terms. + +The following runtime services are expected to be implemented first. They have +not all been instantiated in the current implementation. + +#. Standard service calls + + This service is for management of the entire system. The Power State + Coordination Interface (`PSCI`_) is the first set of standard service calls + defined by Arm (see PSCI section later). + +#. Secure-EL1 Payload Dispatcher service + + If a system runs a Trusted OS or other Secure-EL1 Payload (SP) then + it also requires a *Secure Monitor* at EL3 to switch the EL1 processor + context between the normal world (EL1/EL2) and trusted world (Secure-EL1). + The Secure Monitor will make these world switches in response to SMCs. The + `SMCCC`_ provides for such SMCs with the Trusted OS Call and Trusted + Application Call OEN ranges. + + The interface between the EL3 Runtime Software and the Secure-EL1 Payload is + not defined by the `SMCCC`_ or any other standard. As a result, each + Secure-EL1 Payload requires a specific Secure Monitor that runs as a runtime + service - within TF-A this service is referred to as the Secure-EL1 Payload + Dispatcher (SPD). + + TF-A provides a Test Secure-EL1 Payload (TSP) and its associated Dispatcher + (TSPD). Details of SPD design and TSP/TSPD operation are described in the + :ref:`firmware_design_sel1_spd` section below. + +#. CPU implementation service + + This service will provide an interface to CPU implementation specific + services for a given platform e.g. access to processor errata workarounds. + This service is currently unimplemented. + +Additional services for Arm Architecture, SiP and OEM calls can be implemented. +Each implemented service handles a range of SMC function identifiers as +described in the `SMCCC`_. + +Registration +~~~~~~~~~~~~ + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. This macro instantiates a ``const struct rt_svc_desc`` for the service with these details (see ``runtime_svc.h``). +This structure is allocated in a special ELF section ``rt_svc_descs``, enabling +the framework to find all service descriptors included into BL31. + +The specific service for a SMC Function is selected based on the OEN and call +type of the Function ID, and the framework uses that information in the service +descriptor to identify the handler for the SMC Call. + +The service descriptors do not include information to identify the precise set +of SMC function identifiers supported by this service implementation, the +security state from which such calls are valid nor the capability to support +64-bit and/or 32-bit callers (using SMC32 or SMC64). Responding appropriately +to these aspects of a SMC call is the responsibility of the service +implementation, the framework is focused on integration of services from +different providers and minimizing the time taken by the framework before the +service handler is invoked. + +Details of the parameters, requirements and behavior of the initialization and +call handling functions are provided in the following sections. + +Initialization +~~~~~~~~~~~~~~ + +``runtime_svc_init()`` in ``runtime_svc.c`` initializes the runtime services +framework running on the primary CPU during cold boot as part of the BL31 +initialization. This happens prior to initializing a Trusted OS and running +Normal world boot firmware that might in turn use these services. +Initialization involves validating each of the declared runtime service +descriptors, calling the service initialization function and populating the +index used for runtime lookup of the service. + +The BL31 linker script collects all of the declared service descriptors into a +single array and defines symbols that allow the framework to locate and traverse +the array, and determine its size. + +The framework does basic validation of each descriptor to halt firmware +initialization if service declaration errors are detected. The framework does +not check descriptors for the following error conditions, and may behave in an +unpredictable manner under such scenarios: + +#. Overlapping OEN ranges +#. Multiple descriptors for the same range of OENs and ``call_type`` +#. Incorrect range of owning entity numbers for a given ``call_type`` + +Once validated, the service ``init()`` callback is invoked. This function carries +out any essential EL3 initialization before servicing requests. The ``init()`` +function is only invoked on the primary CPU during cold boot. If the service +uses per-CPU data this must either be initialized for all CPUs during this call, +or be done lazily when a CPU first issues an SMC call to that service. If +``init()`` returns anything other than ``0``, this is treated as an initialization +error and the service is ignored: this does not cause the firmware to halt. + +The OEN and call type fields present in the SMC Function ID cover a total of +128 distinct services, but in practice a single descriptor can cover a range of +OENs, e.g. SMCs to call a Trusted OS function. To optimize the lookup of a +service handler, the framework uses an array of 128 indices that map every +distinct OEN/call-type combination either to one of the declared services or to +indicate the service is not handled. This ``rt_svc_descs_indices[]`` array is +populated for all of the OENs covered by a service after the service ``init()`` +function has reported success. So a service that fails to initialize will never +have it's ``handle()`` function invoked. + +The following figure shows how the ``rt_svc_descs_indices[]`` index maps the SMC +Function ID call type and OEN onto a specific service handler in the +``rt_svc_descs[]`` array. + +|Image 1| + +.. _handling-an-smc: + +Handling an SMC +~~~~~~~~~~~~~~~ + +When the EL3 runtime services framework receives a Secure Monitor Call, the SMC +Function ID is passed in W0 from the lower exception level (as per the +`SMCCC`_). If the calling register width is AArch32, it is invalid to invoke an +SMC Function which indicates the SMC64 calling convention: such calls are +ignored and return the Unknown SMC Function Identifier result code ``0xFFFFFFFF`` +in R0/X0. + +Bit[31] (fast/yielding call) and bits[29:24] (owning entity number) of the SMC +Function ID are combined to index into the ``rt_svc_descs_indices[]`` array. The +resulting value might indicate a service that has no handler, in this case the +framework will also report an Unknown SMC Function ID. Otherwise, the value is +used as a further index into the ``rt_svc_descs[]`` array to locate the required +service and handler. + +The service's ``handle()`` callback is provided with five of the SMC parameters +directly, the others are saved into memory for retrieval (if needed) by the +handler. The handler is also provided with an opaque ``handle`` for use with the +supporting library for parameter retrieval, setting return values and context +manipulation; and with ``flags`` indicating the security state of the caller. The +framework finally sets up the execution stack for the handler, and invokes the +services ``handle()`` function. + +On return from the handler the result registers are populated in X0-X7 as needed +before restoring the stack and CPU state and returning from the original SMC. + +Exception Handling Framework +---------------------------- + +Please refer to the :ref:`Exception Handling Framework` document. + +Power State Coordination Interface +---------------------------------- + +TODO: Provide design walkthrough of PSCI implementation. + +The PSCI v1.1 specification categorizes APIs as optional and mandatory. All the +mandatory APIs in PSCI v1.1, PSCI v1.0 and in PSCI v0.2 draft specification +`Power State Coordination Interface PDD`_ are implemented. The table lists +the PSCI v1.1 APIs and their support in generic code. + +An API implementation might have a dependency on platform code e.g. CPU_SUSPEND +requires the platform to export a part of the implementation. Hence the level +of support of the mandatory APIs depends upon the support exported by the +platform port as well. The Juno and FVP (all variants) platforms export all the +required support. + ++-----------------------------+-------------+-------------------------------+ +| PSCI v1.1 API | Supported | Comments | ++=============================+=============+===============================+ +| ``PSCI_VERSION`` | Yes | The version returned is 1.1 | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_ON`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``AFFINITY_INFO`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_TYPE`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MIGRATE_INFO_CPU`` | Yes\*\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_OFF`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_FEATURES`` | Yes | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_FREEZE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``CPU_DEFAULT_SUSPEND`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``NODE_HW_STATE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_SUSPEND`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_SET_SUSPEND_MODE`` | No | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_RESIDENCY`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``PSCI_STAT_COUNT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``SYSTEM_RESET2`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ +| ``MEM_PROTECT_CHECK_RANGE`` | Yes\* | | ++-----------------------------+-------------+-------------------------------+ + +\*Note : These PSCI APIs require platform power management hooks to be +registered with the generic PSCI code to be supported. + +\*\*Note : These PSCI APIs require appropriate Secure Payload Dispatcher +hooks to be registered with the generic PSCI code to be supported. + +The PSCI implementation in TF-A is a library which can be integrated with +AArch64 or AArch32 EL3 Runtime Software for Armv8-A systems. A guide to +integrating PSCI library with AArch32 EL3 Runtime Software can be found +at :ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + +.. _firmware_design_sel1_spd: + +Secure-EL1 Payloads and Dispatchers +----------------------------------- + +On a production system that includes a Trusted OS running in Secure-EL1/EL0, +the Trusted OS is coupled with a companion runtime service in the BL31 +firmware. This service is responsible for the initialisation of the Trusted +OS and all communications with it. The Trusted OS is the BL32 stage of the +boot flow in TF-A. The firmware will attempt to locate, load and execute a +BL32 image. + +TF-A uses a more general term for the BL32 software that runs at Secure-EL1 - +the *Secure-EL1 Payload* - as it is not always a Trusted OS. + +TF-A provides a Test Secure-EL1 Payload (TSP) and a Test Secure-EL1 Payload +Dispatcher (TSPD) service as an example of how a Trusted OS is supported on a +production system using the Runtime Services Framework. On such a system, the +Test BL32 image and service are replaced by the Trusted OS and its dispatcher +service. The TF-A build system expects that the dispatcher will define the +build flag ``NEED_BL32`` to enable it to include the BL32 in the build either +as a binary or to compile from source depending on whether the ``BL32`` build +option is specified or not. + +The TSP runs in Secure-EL1. It is designed to demonstrate synchronous +communication with the normal-world software running in EL1/EL2. Communication +is initiated by the normal-world software + +- either directly through a Fast SMC (as defined in the `SMCCC`_) + +- or indirectly through a `PSCI`_ SMC. The `PSCI`_ implementation in turn + informs the TSPD about the requested power management operation. This allows + the TSP to prepare for or respond to the power state change + +The TSPD service is responsible for. + +- Initializing the TSP + +- Routing requests and responses between the secure and the non-secure + states during the two types of communications just described + +Initializing a BL32 Image +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Secure-EL1 Payload Dispatcher (SPD) service is responsible for initializing +the BL32 image. It needs access to the information passed by BL2 to BL31 to do +so. This is provided by: + +.. code:: c + + entry_point_info_t *bl31_plat_get_next_image_ep_info(uint32_t); + +which returns a reference to the ``entry_point_info`` structure corresponding to +the image which will be run in the specified security state. The SPD uses this +API to get entry point information for the SECURE image, BL32. + +In the absence of a BL32 image, BL31 passes control to the normal world +bootloader image (BL33). When the BL32 image is present, it is typical +that the SPD wants control to be passed to BL32 first and then later to BL33. + +To do this the SPD has to register a BL32 initialization function during +initialization of the SPD service. The BL32 initialization function has this +prototype: + +.. code:: c + + int32_t init(void); + +and is registered using the ``bl31_register_bl32_init()`` function. + +TF-A supports two approaches for the SPD to pass control to BL32 before +returning through EL3 and running the non-trusted firmware (BL33): + +#. In the BL32 setup function, use ``bl31_set_next_image_type()`` to + request that the exit from ``bl31_main()`` is to the BL32 entrypoint in + Secure-EL1. BL31 will exit to BL32 using the asynchronous method by + calling ``bl31_prepare_next_image_entry()`` and ``el3_exit()``. + + When the BL32 has completed initialization at Secure-EL1, it returns to + BL31 by issuing an SMC, using a Function ID allocated to the SPD. On + receipt of this SMC, the SPD service handler should switch the CPU context + from trusted to normal world and use the ``bl31_set_next_image_type()`` and + ``bl31_prepare_next_image_entry()`` functions to set up the initial return to + the normal world firmware BL33. On return from the handler the framework + will exit to EL2 and run BL33. + +#. The BL32 setup function registers an initialization function using + ``bl31_register_bl32_init()`` which provides a SPD-defined mechanism to + invoke a 'world-switch synchronous call' to Secure-EL1 to run the BL32 + entrypoint. + + .. note:: + The Test SPD service included with TF-A provides one implementation + of such a mechanism. + + On completion BL32 returns control to BL31 via a SMC, and on receipt the + SPD service handler invokes the synchronous call return mechanism to return + to the BL32 initialization function. On return from this function, + ``bl31_main()`` will set up the return to the normal world firmware BL33 and + continue the boot process in the normal world. + +Crash Reporting in BL31 +----------------------- + +BL31 implements a scheme for reporting the processor state when an unhandled +exception is encountered. The reporting mechanism attempts to preserve all the +register contents and report it via a dedicated UART (PL011 console). BL31 +reports the general purpose, EL3, Secure EL1 and some EL2 state registers. + +A dedicated per-CPU crash stack is maintained by BL31 and this is retrieved via +the per-CPU pointer cache. The implementation attempts to minimise the memory +required for this feature. The file ``crash_reporting.S`` contains the +implementation for crash reporting. + +The sample crash output is shown below. + +:: + + x0 = 0x000000002a4a0000 + x1 = 0x0000000000000001 + x2 = 0x0000000000000002 + x3 = 0x0000000000000003 + x4 = 0x0000000000000004 + x5 = 0x0000000000000005 + x6 = 0x0000000000000006 + x7 = 0x0000000000000007 + x8 = 0x0000000000000008 + x9 = 0x0000000000000009 + x10 = 0x0000000000000010 + x11 = 0x0000000000000011 + x12 = 0x0000000000000012 + x13 = 0x0000000000000013 + x14 = 0x0000000000000014 + x15 = 0x0000000000000015 + x16 = 0x0000000000000016 + x17 = 0x0000000000000017 + x18 = 0x0000000000000018 + x19 = 0x0000000000000019 + x20 = 0x0000000000000020 + x21 = 0x0000000000000021 + x22 = 0x0000000000000022 + x23 = 0x0000000000000023 + x24 = 0x0000000000000024 + x25 = 0x0000000000000025 + x26 = 0x0000000000000026 + x27 = 0x0000000000000027 + x28 = 0x0000000000000028 + x29 = 0x0000000000000029 + x30 = 0x0000000088000b78 + scr_el3 = 0x000000000003073d + sctlr_el3 = 0x00000000b0cd183f + cptr_el3 = 0x0000000000000000 + tcr_el3 = 0x000000008080351c + daif = 0x00000000000002c0 + mair_el3 = 0x00000000004404ff + spsr_el3 = 0x0000000060000349 + elr_el3 = 0x0000000088000114 + ttbr0_el3 = 0x0000000004018201 + esr_el3 = 0x00000000be000000 + far_el3 = 0x0000000000000000 + spsr_el1 = 0x0000000000000000 + elr_el1 = 0x0000000000000000 + spsr_abt = 0x0000000000000000 + spsr_und = 0x0000000000000000 + spsr_irq = 0x0000000000000000 + spsr_fiq = 0x0000000000000000 + sctlr_el1 = 0x0000000030d00800 + actlr_el1 = 0x0000000000000000 + cpacr_el1 = 0x0000000000000000 + csselr_el1 = 0x0000000000000000 + sp_el1 = 0x0000000000000000 + esr_el1 = 0x0000000000000000 + ttbr0_el1 = 0x0000000000000000 + ttbr1_el1 = 0x0000000000000000 + mair_el1 = 0x0000000000000000 + amair_el1 = 0x0000000000000000 + tcr_el1 = 0x0000000000000000 + tpidr_el1 = 0x0000000000000000 + tpidr_el0 = 0x0000000000000000 + tpidrro_el0 = 0x0000000000000000 + par_el1 = 0x0000000000000000 + mpidr_el1 = 0x0000000080000000 + afsr0_el1 = 0x0000000000000000 + afsr1_el1 = 0x0000000000000000 + contextidr_el1 = 0x0000000000000000 + vbar_el1 = 0x0000000000000000 + cntp_ctl_el0 = 0x0000000000000000 + cntp_cval_el0 = 0x0000000000000000 + cntv_ctl_el0 = 0x0000000000000000 + cntv_cval_el0 = 0x0000000000000000 + cntkctl_el1 = 0x0000000000000000 + sp_el0 = 0x0000000004014940 + isr_el1 = 0x0000000000000000 + dacr32_el2 = 0x0000000000000000 + ifsr32_el2 = 0x0000000000000000 + icc_hppir0_el1 = 0x00000000000003ff + icc_hppir1_el1 = 0x00000000000003ff + icc_ctlr_el3 = 0x0000000000080400 + gicd_ispendr regs (Offsets 0x200-0x278) + Offset Value + 0x200: 0x0000000000000000 + 0x208: 0x0000000000000000 + 0x210: 0x0000000000000000 + 0x218: 0x0000000000000000 + 0x220: 0x0000000000000000 + 0x228: 0x0000000000000000 + 0x230: 0x0000000000000000 + 0x238: 0x0000000000000000 + 0x240: 0x0000000000000000 + 0x248: 0x0000000000000000 + 0x250: 0x0000000000000000 + 0x258: 0x0000000000000000 + 0x260: 0x0000000000000000 + 0x268: 0x0000000000000000 + 0x270: 0x0000000000000000 + 0x278: 0x0000000000000000 + +Guidelines for Reset Handlers +----------------------------- + +TF-A implements a framework that allows CPU and platform ports to perform +actions very early after a CPU is released from reset in both the cold and warm +boot paths. This is done by calling the ``reset_handler()`` function in both +the BL1 and BL31 images. It in turn calls the platform and CPU specific reset +handling functions. + +Details for implementing a CPU specific reset handler can be found in +Section 8. Details for implementing a platform specific reset handler can be +found in the :ref:`Porting Guide` (see the ``plat_reset_handler()`` function). + +When adding functionality to a reset handler, keep in mind that if a different +reset handling behavior is required between the first and the subsequent +invocations of the reset handling code, this should be detected at runtime. +In other words, the reset handler should be able to detect whether an action has +already been performed and act as appropriate. Possible courses of actions are, +e.g. skip the action the second time, or undo/redo it. + +.. _configuring-secure-interrupts: + +Configuring secure interrupts +----------------------------- + +The GIC driver is responsible for performing initial configuration of secure +interrupts on the platform. To this end, the platform is expected to provide the +GIC driver (either GICv2 or GICv3, as selected by the platform) with the +interrupt configuration during the driver initialisation. + +Secure interrupt configuration are specified in an array of secure interrupt +properties. In this scheme, in both GICv2 and GICv3 driver data structures, the +``interrupt_props`` member points to an array of interrupt properties. Each +element of the array specifies the interrupt number and its attributes +(priority, group, configuration). Each element of the array shall be populated +by the macro ``INTR_PROP_DESC()``. The macro takes the following arguments: + +- 10-bit interrupt number, + +- 8-bit interrupt priority, + +- Interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1``, + ``INTR_TYPE_NS``), + +- Interrupt configuration (either ``GIC_INTR_CFG_LEVEL`` or + ``GIC_INTR_CFG_EDGE``). + +.. _firmware_design_cpu_ops_fwk: + +CPU specific operations framework +--------------------------------- + +Certain aspects of the Armv8-A architecture are implementation defined, +that is, certain behaviours are not architecturally defined, but must be +defined and documented by individual processor implementations. TF-A +implements a framework which categorises the common implementation defined +behaviours and allows a processor to export its implementation of that +behaviour. The categories are: + +#. Processor specific reset sequence. + +#. Processor specific power down sequences. + +#. Processor specific register dumping as a part of crash reporting. + +#. Errata status reporting. + +Each of the above categories fulfils a different requirement. + +#. allows any processor specific initialization before the caches and MMU + are turned on, like implementation of errata workarounds, entry into + the intra-cluster coherency domain etc. + +#. allows each processor to implement the power down sequence mandated in + its Technical Reference Manual (TRM). + +#. allows a processor to provide additional information to the developer + in the event of a crash, for example Cortex-A53 has registers which + can expose the data cache contents. + +#. allows a processor to define a function that inspects and reports the status + of all errata workarounds on that processor. + +Please note that only 2. is mandated by the TRM. + +The CPU specific operations framework scales to accommodate a large number of +different CPUs during power down and reset handling. The platform can specify +any CPU optimization it wants to enable for each CPU. It can also specify +the CPU errata workarounds to be applied for each CPU type during reset +handling by defining CPU errata compile time macros. Details on these macros +can be found in the :ref:`Arm CPU Specific Build Macros` document. + +The CPU specific operations framework depends on the ``cpu_ops`` structure which +needs to be exported for each type of CPU in the platform. It is defined in +``include/lib/cpus/aarch64/cpu_macros.S`` and has the following fields : ``midr``, +``reset_func()``, ``cpu_pwr_down_ops`` (array of power down functions) and +``cpu_reg_dump()``. + +The CPU specific files in ``lib/cpus`` export a ``cpu_ops`` data structure with +suitable handlers for that CPU. For example, ``lib/cpus/aarch64/cortex_a53.S`` +exports the ``cpu_ops`` for Cortex-A53 CPU. According to the platform +configuration, these CPU specific files must be included in the build by +the platform makefile. The generic CPU specific operations framework code exists +in ``lib/cpus/aarch64/cpu_helpers.S``. + +CPU specific Reset Handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +After a reset, the state of the CPU when it calls generic reset handler is: +MMU turned off, both instruction and data caches turned off and not part +of any coherency domain. + +The BL entrypoint code first invokes the ``plat_reset_handler()`` to allow +the platform to perform any system initialization required and any system +errata workarounds that needs to be applied. The ``get_cpu_ops_ptr()`` reads +the current CPU midr, finds the matching ``cpu_ops`` entry in the ``cpu_ops`` +array and returns it. Note that only the part number and implementer fields +in midr are used to find the matching ``cpu_ops`` entry. The ``reset_func()`` in +the returned ``cpu_ops`` is then invoked which executes the required reset +handling for that CPU and also any errata workarounds enabled by the platform. +This function must preserve the values of general purpose registers x20 to x29. + +Refer to Section "Guidelines for Reset Handlers" for general guidelines +regarding placement of code in a reset handler. + +CPU specific power down sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During the BL31 initialization sequence, the pointer to the matching ``cpu_ops`` +entry is stored in per-CPU data by ``init_cpu_ops()`` so that it can be quickly +retrieved during power down sequences. + +Various CPU drivers register handlers to perform power down at certain power +levels for that specific CPU. The PSCI service, upon receiving a power down +request, determines the highest power level at which to execute power down +sequence for a particular CPU. It uses the ``prepare_cpu_pwr_dwn()`` function to +pick the right power down handler for the requested level. The function +retrieves ``cpu_ops`` pointer member of per-CPU data, and from that, further +retrieves ``cpu_pwr_down_ops`` array, and indexes into the required level. If the +requested power level is higher than what a CPU driver supports, the handler +registered for highest level is invoked. + +At runtime the platform hooks for power down are invoked by the PSCI service to +perform platform specific operations during a power down sequence, for example +turning off CCI coherency during a cluster power down. + +CPU specific register reporting during crash +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +If the crash reporting is enabled in BL31, when a crash occurs, the crash +reporting framework calls ``do_cpu_reg_dump`` which retrieves the matching +``cpu_ops`` using ``get_cpu_ops_ptr()`` function. The ``cpu_reg_dump()`` in +``cpu_ops`` is invoked, which then returns the CPU specific register values to +be reported and a pointer to the ASCII list of register names in a format +expected by the crash reporting framework. + +.. _firmware_design_cpu_errata_reporting: + +CPU errata status reporting +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Errata workarounds for CPUs supported in TF-A are applied during both cold and +warm boots, shortly after reset. Individual Errata workarounds are enabled as +build options. Some errata workarounds have potential run-time implications; +therefore some are enabled by default, others not. Platform ports shall +override build options to enable or disable errata as appropriate. The CPU +drivers take care of applying errata workarounds that are enabled and applicable +to a given CPU. Refer to :ref:`arm_cpu_macros_errata_workarounds` for more +information. + +Functions in CPU drivers that apply errata workaround must follow the +conventions listed below. + +The errata workaround must be authored as two separate functions: + +- One that checks for errata. This function must determine whether that errata + applies to the current CPU. Typically this involves matching the current + CPUs revision and variant against a value that's known to be affected by the + errata. If the function determines that the errata applies to this CPU, it + must return ``ERRATA_APPLIES``; otherwise, it must return + ``ERRATA_NOT_APPLIES``. The utility functions ``cpu_get_rev_var`` and + ``cpu_rev_var_ls`` functions may come in handy for this purpose. + +For an errata identified as ``E``, the check function must be named +``check_errata_E``. + +This function will be invoked at different times, both from assembly and from +C run time. Therefore it must follow AAPCS, and must not use stack. + +- Another one that applies the errata workaround. This function would call the + check function described above, and applies errata workaround if required. + +CPU drivers that apply errata workaround can optionally implement an assembly +function that report the status of errata workarounds pertaining to that CPU. +For a driver that registers the CPU, for example, ``cpux`` via ``declare_cpu_ops`` +macro, the errata reporting function, if it exists, must be named +``cpux_errata_report``. This function will always be called with MMU enabled; it +must follow AAPCS and may use stack. + +In a debug build of TF-A, on a CPU that comes out of reset, both BL1 and the +runtime firmware (BL31 in AArch64, and BL32 in AArch32) will invoke errata +status reporting function, if one exists, for that type of CPU. + +To report the status of each errata workaround, the function shall use the +assembler macro ``report_errata``, passing it: + +- The build option that enables the errata; + +- The name of the CPU: this must be the same identifier that CPU driver + registered itself with, using ``declare_cpu_ops``; + +- And the errata identifier: the identifier must match what's used in the + errata's check function described above. + +The errata status reporting function will be called once per CPU type/errata +combination during the software's active life time. + +It's expected that whenever an errata workaround is submitted to TF-A, the +errata reporting function is appropriately extended to report its status as +well. + +Reporting the status of errata workaround is for informational purpose only; it +has no functional significance. + +Memory layout of BL images +-------------------------- + +Each bootloader image can be divided in 2 parts: + +- the static contents of the image. These are data actually stored in the + binary on the disk. In the ELF terminology, they are called ``PROGBITS`` + sections; + +- the run-time contents of the image. These are data that don't occupy any + space in the binary on the disk. The ELF binary just contains some + metadata indicating where these data will be stored at run-time and the + corresponding sections need to be allocated and initialized at run-time. + In the ELF terminology, they are called ``NOBITS`` sections. + +All PROGBITS sections are grouped together at the beginning of the image, +followed by all NOBITS sections. This is true for all TF-A images and it is +governed by the linker scripts. This ensures that the raw binary images are +as small as possible. If a NOBITS section was inserted in between PROGBITS +sections then the resulting binary file would contain zero bytes in place of +this NOBITS section, making the image unnecessarily bigger. Smaller images +allow faster loading from the FIP to the main memory. + +For BL31, a platform can specify an alternate location for NOBITS sections +(other than immediately following PROGBITS sections) by setting +``SEPARATE_NOBITS_REGION`` to 1 and defining ``BL31_NOBITS_BASE`` and +``BL31_NOBITS_LIMIT``. + +Linker scripts and symbols +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each bootloader stage image layout is described by its own linker script. The +linker scripts export some symbols into the program symbol table. Their values +correspond to particular addresses. TF-A code can refer to these symbols to +figure out the image memory layout. + +Linker symbols follow the following naming convention in TF-A. + +- ``__
_START__`` + + Start address of a given section named ``
``. + +- ``__
_END__`` + + End address of a given section named ``
``. If there is an alignment + constraint on the section's end address then ``__
_END__`` corresponds + to the end address of the section's actual contents, rounded up to the right + boundary. Refer to the value of ``__
_UNALIGNED_END__`` to know the + actual end address of the section's contents. + +- ``__
_UNALIGNED_END__`` + + End address of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. + +- ``__
_SIZE__`` + + Size (in bytes) of a given section named ``
``. If there is an + alignment constraint on the section's end address then ``__
_SIZE__`` + corresponds to the size of the section's actual contents, rounded up to the + right boundary. In other words, ``__
_SIZE__ = __
_END__ - _
_START__``. Refer to the value of ``__
_UNALIGNED_SIZE__`` + to know the actual size of the section's contents. + +- ``__
_UNALIGNED_SIZE__`` + + Size (in bytes) of a given section named ``
`` without any padding or + rounding up due to some alignment constraint. In other words, + ``__
_UNALIGNED_SIZE__ = __
_UNALIGNED_END__ - __
_START__``. + +Some of the linker symbols are mandatory as TF-A code relies on them to be +defined. They are listed in the following subsections. Some of them must be +provided for each bootloader stage and some are specific to a given bootloader +stage. + +The linker scripts define some extra, optional symbols. They are not actually +used by any code but they help in understanding the bootloader images' memory +layout as they are easy to spot in the link map files. + +Common linker symbols +^^^^^^^^^^^^^^^^^^^^^ + +All BL images share the following requirements: + +- The BSS section must be zero-initialised before executing any C code. +- The coherent memory section (if enabled) must be zero-initialised as well. +- The MMU setup code needs to know the extents of the coherent and read-only + memory regions to set the right memory attributes. When + ``SEPARATE_CODE_AND_RODATA=1``, it needs to know more specifically how the + read-only memory region is divided between code and data. + +The following linker symbols are defined for this purpose: + +- ``__BSS_START__`` +- ``__BSS_SIZE__`` +- ``__COHERENT_RAM_START__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_END__`` Must be aligned on a page-size boundary. +- ``__COHERENT_RAM_UNALIGNED_SIZE__`` +- ``__RO_START__`` +- ``__RO_END__`` +- ``__TEXT_START__`` +- ``__TEXT_END__`` +- ``__RODATA_START__`` +- ``__RODATA_END__`` + +BL1's linker symbols +^^^^^^^^^^^^^^^^^^^^ + +BL1 being the ROM image, it has additional requirements. BL1 resides in ROM and +it is entirely executed in place but it needs some read-write memory for its +mutable data. Its ``.data`` section (i.e. its allocated read-write data) must be +relocated from ROM to RAM before executing any C code. + +The following additional linker symbols are defined for BL1: + +- ``__BL1_ROM_END__`` End address of BL1's ROM contents, covering its code + and ``.data`` section in ROM. +- ``__DATA_ROM_START__`` Start address of the ``.data`` section in ROM. Must be + aligned on a 16-byte boundary. +- ``__DATA_RAM_START__`` Address in RAM where the ``.data`` section should be + copied over. Must be aligned on a 16-byte boundary. +- ``__DATA_SIZE__`` Size of the ``.data`` section (in ROM or RAM). +- ``__BL1_RAM_START__`` Start address of BL1 read-write data. +- ``__BL1_RAM_END__`` End address of BL1 read-write data. + +How to choose the right base addresses for each bootloader stage image +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +There is currently no support for dynamic image loading in TF-A. This means +that all bootloader images need to be linked against their ultimate runtime +locations and the base addresses of each image must be chosen carefully such +that images don't overlap each other in an undesired way. As the code grows, +the base addresses might need adjustments to cope with the new memory layout. + +The memory layout is completely specific to the platform and so there is no +general recipe for choosing the right base addresses for each bootloader image. +However, there are tools to aid in understanding the memory layout. These are +the link map files: ``build///bl/bl.map``, with ```` +being the stage bootloader. They provide a detailed view of the memory usage of +each image. Among other useful information, they provide the end address of +each image. + +- ``bl1.map`` link map file provides ``__BL1_RAM_END__`` address. +- ``bl2.map`` link map file provides ``__BL2_END__`` address. +- ``bl31.map`` link map file provides ``__BL31_END__`` address. +- ``bl32.map`` link map file provides ``__BL32_END__`` address. + +For each bootloader image, the platform code must provide its start address +as well as a limit address that it must not overstep. The latter is used in the +linker scripts to check that the image doesn't grow past that address. If that +happens, the linker will issue a message similar to the following: + +:: + + aarch64-none-elf-ld: BLx has exceeded its limit. + +Additionally, if the platform memory layout implies some image overlaying like +on FVP, BL31 and TSP need to know the limit address that their PROGBITS +sections must not overstep. The platform code must provide those. + +TF-A does not provide any mechanism to verify at boot time that the memory +to load a new image is free to prevent overwriting a previously loaded image. +The platform must specify the memory available in the system for all the +relevant BL images to be loaded. + +For example, in the case of BL1 loading BL2, ``bl1_plat_sec_mem_layout()`` will +return the region defined by the platform where BL1 intends to load BL2. The +``load_image()`` function performs bounds check for the image size based on the +base and maximum image size provided by the platforms. Platforms must take +this behaviour into account when defining the base/size for each of the images. + +Memory layout on Arm development platforms +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following list describes the memory layout on the Arm development platforms: + +- A 4KB page of shared memory is used for communication between Trusted + Firmware and the platform's power controller. This is located at the base of + Trusted SRAM. The amount of Trusted SRAM available to load the bootloader + images is reduced by the size of the shared memory. + + The shared memory is used to store the CPUs' entrypoint mailbox. On Juno, + this is also used for the MHU payload when passing messages to and from the + SCP. + +- Another 4 KB page is reserved for passing memory layout between BL1 and BL2 + and also the dynamic firmware configurations. + +- On FVP, BL1 is originally sitting in the Trusted ROM at address ``0x0``. On + Juno, BL1 resides in flash memory at address ``0x0BEC0000``. BL1 read-write + data are relocated to the top of Trusted SRAM at runtime. + +- BL2 is loaded below BL1 RW + +- EL3 Runtime Software, BL31 for AArch64 and BL32 for AArch32 (e.g. SP_MIN), + is loaded at the top of the Trusted SRAM, such that its NOBITS sections will + overwrite BL1 R/W data and BL2. This implies that BL1 global variables + remain valid only until execution reaches the EL3 Runtime Software entry + point during a cold boot. + +- On Juno, SCP_BL2 is loaded temporarily into the EL3 Runtime Software memory + region and transferred to the SCP before being overwritten by EL3 Runtime + Software. + +- BL32 (for AArch64) can be loaded in one of the following locations: + + - Trusted SRAM + - Trusted DRAM (FVP only) + - Secure region of DRAM (top 16MB of DRAM configured by the TrustZone + controller) + + When BL32 (for AArch64) is loaded into Trusted SRAM, it is loaded below + BL31. + +The location of the BL32 image will result in different memory maps. This is +illustrated for both FVP and Juno in the following diagrams, using the TSP as +an example. + +.. note:: + Loading the BL32 image in TZC secured DRAM doesn't change the memory + layout of the other images in Trusted SRAM. + +CONFIG section in memory layouts shown below contains: + +:: + + +--------------------+ + |bl2_mem_params_descs| + |--------------------| + | fw_configs | + +--------------------+ + +``bl2_mem_params_descs`` contains parameters passed from BL2 to next the +BL image during boot. + +``fw_configs`` includes soc_fw_config, tos_fw_config, tb_fw_config and fw_config. + +**FVP with TSP in Trusted SRAM with firmware configs :** +(These diagrams only cover the AArch64 case) + +:: + + DRAM + 0xffffffff +----------+ + : : + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + 0x04003000 +----------+ +----------------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**FVP with TSP in Trusted DRAM with firmware configs (default option):** + +:: + + DRAM + 0xffffffff +--------------+ + : : + |--------------| + | HW_CONFIG | + 0x83000000 |--------------| (non-secure) + | | + 0x80000000 +--------------+ + + Trusted DRAM + 0x08000000 +--------------+ + | BL32 | + 0x06000000 +--------------+ + + Trusted SRAM + 0x04040000 +--------------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |--------------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04003000 +--------------+ + | CONFIG | + 0x04001000 +--------------+ + | Shared | + 0x04000000 +--------------+ + + Trusted ROM + 0x04000000 +--------------+ + | BL1 (ro) | + 0x00000000 +--------------+ + +**FVP with TSP in TZC-Secured DRAM with firmware configs :** + +:: + + DRAM + 0xffffffff +----------+ + | BL32 | (secure) + 0xff000000 +----------+ + | | + |----------| + |HW_CONFIG | + 0x83000000 |----------| (non-secure) + | | + 0x80000000 +----------+ + + Trusted SRAM + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04003000 +----------+ + | CONFIG | + 0x04001000 +----------+ + | Shared | + 0x04000000 +----------+ + + Trusted ROM + 0x04000000 +----------+ + | BL1 (ro) | + 0x00000000 +----------+ + +**Juno with BL32 in Trusted SRAM :** + +:: + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + | | <<<<<<<<<<<<< |----------------| + | | <<<<<<<<<<<<< | BL32 | + | | +----------------+ + | | + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +**Juno with BL32 in TZC-secured DRAM :** + +:: + + DRAM + 0xFFE00000 +----------+ + | BL32 | (secure) + 0xFF000000 |----------| + | | + : : (non-secure) + | | + 0x80000000 +----------+ + + Flash0 + 0x0C000000 +----------+ + : : + 0x0BED0000 |----------| + | BL1 (ro) | + 0x0BEC0000 |----------| + : : + 0x08000000 +----------+ BL31 is loaded + after SCP_BL2 has + Trusted SRAM been sent to SCP + 0x04040000 +----------+ loaded by BL2 +----------------+ + | BL1 (rw) | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< | BL31 NOBITS | + | BL2 | <<<<<<<<<<<<< | | + |----------| <<<<<<<<<<<<< |----------------| + | SCP_BL2 | <<<<<<<<<<<<< | BL31 PROGBITS | + | | +----------------+ + 0x04001000 +----------+ + | MHU | + 0x04000000 +----------+ + +.. _firmware_design_fip: + +Firmware Image Package (FIP) +---------------------------- + +Using a Firmware Image Package (FIP) allows for packing bootloader images (and +potentially other payloads) into a single archive that can be loaded by TF-A +from non-volatile platform storage. A driver to load images from a FIP has +been added to the storage layer and allows a package to be read from supported +platform storage. A tool to create Firmware Image Packages is also provided +and described below. + +Firmware Image Package layout +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP layout consists of a table of contents (ToC) followed by payload data. +The ToC itself has a header followed by one or more table entries. The ToC is +terminated by an end marker entry, and since the size of the ToC is 0 bytes, +the offset equals the total size of the FIP file. All ToC entries describe some +payload data that has been appended to the end of the binary package. With the +information provided in the ToC entry the corresponding payload data can be +retrieved. + +:: + + ------------------ + | ToC Header | + |----------------| + | ToC Entry 0 | + |----------------| + | ToC Entry 1 | + |----------------| + | ToC End Marker | + |----------------| + | | + | Data 0 | + | | + |----------------| + | | + | Data 1 | + | | + ------------------ + +The ToC header and entry formats are described in the header file +``include/tools_share/firmware_image_package.h``. This file is used by both the +tool and TF-A. + +The ToC header has the following fields: + +:: + + `name`: The name of the ToC. This is currently used to validate the header. + `serial_number`: A non-zero number provided by the creation tool + `flags`: Flags associated with this data. + Bits 0-31: Reserved + Bits 32-47: Platform defined + Bits 48-63: Reserved + +A ToC entry has the following fields: + +:: + + `uuid`: All files are referred to by a pre-defined Universally Unique + IDentifier [UUID] . The UUIDs are defined in + `include/tools_share/firmware_image_package.h`. The platform translates + the requested image name into the corresponding UUID when accessing the + package. + `offset_address`: The offset address at which the corresponding payload data + can be found. The offset is calculated from the ToC base address. + `size`: The size of the corresponding payload data in bytes. + `flags`: Flags associated with this entry. None are yet defined. + +Firmware Image Package creation tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The FIP creation tool can be used to pack specified images into a binary +package that can be loaded by TF-A from platform storage. The tool currently +only supports packing bootloader images. Additional image definitions can be +added to the tool as required. + +The tool can be found in ``tools/fiptool``. + +Loading from a Firmware Image Package (FIP) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The Firmware Image Package (FIP) driver can load images from a binary package on +non-volatile platform storage. For the Arm development platforms, this is +currently NOR FLASH. + +Bootloader images are loaded according to the platform policy as specified by +the function ``plat_get_image_source()``. For the Arm development platforms, this +means the platform will attempt to load images from a Firmware Image Package +located at the start of NOR FLASH0. + +The Arm development platforms' policy is to only allow loading of a known set of +images. The platform policy can be modified to allow additional images. + +Use of coherent memory in TF-A +------------------------------ + +There might be loss of coherency when physical memory with mismatched +shareability, cacheability and memory attributes is accessed by multiple CPUs +(refer to section B2.9 of `Arm ARM`_ for more details). This possibility occurs +in TF-A during power up/down sequences when coherency, MMU and caches are +turned on/off incrementally. + +TF-A defines coherent memory as a region of memory with Device nGnRE attributes +in the translation tables. The translation granule size in TF-A is 4KB. This +is the smallest possible size of the coherent memory region. + +By default, all data structures which are susceptible to accesses with +mismatched attributes from various CPUs are allocated in a coherent memory +region (refer to section 2.1 of :ref:`Porting Guide`). The coherent memory +region accesses are Outer Shareable, non-cacheable and they can be accessed with +the Device nGnRE attributes when the MMU is turned on. Hence, at the expense of +at least an extra page of memory, TF-A is able to work around coherency issues +due to mismatched memory attributes. + +The alternative to the above approach is to allocate the susceptible data +structures in Normal WriteBack WriteAllocate Inner shareable memory. This +approach requires the data structures to be designed so that it is possible to +work around the issue of mismatched memory attributes by performing software +cache maintenance on them. + +Disabling the use of coherent memory in TF-A +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +It might be desirable to avoid the cost of allocating coherent memory on +platforms which are memory constrained. TF-A enables inclusion of coherent +memory in firmware images through the build flag ``USE_COHERENT_MEM``. +This flag is enabled by default. It can be disabled to choose the second +approach described above. + +The below sections analyze the data structures allocated in the coherent memory +region and the changes required to allocate them in normal memory. + +Coherent memory usage in PSCI implementation +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``psci_non_cpu_pd_nodes`` data structure stores the platform's power domain +tree information for state management of power domains. By default, this data +structure is allocated in the coherent memory region in TF-A because it can be +accessed by multiple CPUs, either with caches enabled or disabled. + +.. code:: c + + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* + * Index of the parent power domain node. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + unsigned char lock_index; + } non_cpu_pd_node_t; + +In order to move this data structure to normal memory, the use of each of its +fields must be analyzed. Fields like ``cpu_start_idx``, ``ncpus``, ``parent_node`` +``level`` and ``lock_index`` are only written once during cold boot. Hence removing +them from coherent memory involves only doing a clean and invalidate of the +cache lines after these fields are written. + +The field ``local_state`` can be concurrently accessed by multiple CPUs in +different cache states. A Lamport's Bakery lock ``psci_locks`` is used to ensure +mutual exclusion to this field and a clean and invalidate is needed after it +is written. + +Bakery lock data +~~~~~~~~~~~~~~~~ + +The bakery lock data structure ``bakery_lock_t`` is allocated in coherent memory +and is accessed by multiple CPUs with mismatched attributes. ``bakery_lock_t`` is +defined as follows: + +.. code:: c + + typedef struct bakery_lock { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; + } bakery_lock_t; + +It is a characteristic of Lamport's Bakery algorithm that the volatile per-CPU +fields can be read by all CPUs but only written to by the owning CPU. + +Depending upon the data cache line size, the per-CPU fields of the +``bakery_lock_t`` structure for multiple CPUs may exist on a single cache line. +These per-CPU fields can be read and written during lock contention by multiple +CPUs with mismatched memory attributes. Since these fields are a part of the +lock implementation, they do not have access to any other locking primitive to +safeguard against the resulting coherency issues. As a result, simple software +cache maintenance is not enough to allocate them in coherent memory. Consider +the following example. + +CPU0 updates its per-CPU field with data cache enabled. This write updates a +local cache line which contains a copy of the fields for other CPUs as well. Now +CPU1 updates its per-CPU field of the ``bakery_lock_t`` structure with data cache +disabled. CPU1 then issues a DCIVAC operation to invalidate any stale copies of +its field in any other cache line in the system. This operation will invalidate +the update made by CPU0 as well. + +To use bakery locks when ``USE_COHERENT_MEM`` is disabled, the lock data structure +has been redesigned. The changes utilise the characteristic of Lamport's Bakery +algorithm mentioned earlier. The bakery_lock structure only allocates the memory +for a single CPU. The macro ``DEFINE_BAKERY_LOCK`` allocates all the bakery locks +needed for a CPU into a section ``bakery_lock``. The linker allocates the memory +for other cores by using the total size allocated for the bakery_lock section +and multiplying it with (PLATFORM_CORE_COUNT - 1). This enables software to +perform software cache maintenance on the lock data structure without running +into coherency issues associated with mismatched attributes. + +The bakery lock data structure ``bakery_info_t`` is defined for use when +``USE_COHERENT_MEM`` is disabled as follows: + +.. code:: c + + typedef struct bakery_info { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data; + } bakery_info_t; + +The ``bakery_info_t`` represents a single per-CPU field of one lock and +the combination of corresponding ``bakery_info_t`` structures for all CPUs in the +system represents the complete bakery lock. The view in memory for a system +with n bakery locks are: + +:: + + bakery_lock section start + |----------------| + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU0 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU0 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU0 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | <--- Calculate PERCPU_BAKERY_LOCK_SIZE, allocate + | Granule | continuous memory for remaining CPUs. + ------------------ + | `bakery_info_t`| <-- Lock_0 per-CPU field + | Lock_0 | for CPU1 + |----------------| + | `bakery_info_t`| <-- Lock_1 per-CPU field + | Lock_1 | for CPU1 + |----------------| + | .... | + |----------------| + | `bakery_info_t`| <-- Lock_N per-CPU field + | Lock_N | for CPU1 + ------------------ + | XXXXX | + | Padding to | + | next Cache WB | + | Granule | + ------------------ + +Consider a system of 2 CPUs with 'N' bakery locks as shown above. For an +operation on Lock_N, the corresponding ``bakery_info_t`` in both CPU0 and CPU1 +``bakery_lock`` section need to be fetched and appropriate cache operations need +to be performed for each access. + +On Arm Platforms, bakery locks are used in psci (``psci_locks``) and power controller +driver (``arm_lock``). + +Non Functional Impact of removing coherent memory +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Removal of the coherent memory region leads to the additional software overhead +of performing cache maintenance for the affected data structures. However, since +the memory where the data structures are allocated is cacheable, the overhead is +mostly mitigated by an increase in performance. + +There is however a performance impact for bakery locks, due to: + +- Additional cache maintenance operations, and +- Multiple cache line reads for each lock operation, since the bakery locks + for each CPU are distributed across different cache lines. + +The implementation has been optimized to minimize this additional overhead. +Measurements indicate that when bakery locks are allocated in Normal memory, the +minimum latency of acquiring a lock is on an average 3-4 micro seconds whereas +in Device memory the same is 2 micro seconds. The measurements were done on the +Juno Arm development platform. + +As mentioned earlier, almost a page of memory can be saved by disabling +``USE_COHERENT_MEM``. Each platform needs to consider these trade-offs to decide +whether coherent memory should be used. If a platform disables +``USE_COHERENT_MEM`` and needs to use bakery locks in the porting layer, it can +optionally define macro ``PLAT_PERCPU_BAKERY_LOCK_SIZE`` (see the +:ref:`Porting Guide`). Refer to the reference platform code for examples. + +Isolating code and read-only data on separate memory pages +---------------------------------------------------------- + +In the Armv8-A VMSA, translation table entries include fields that define the +properties of the target memory region, such as its access permissions. The +smallest unit of memory that can be addressed by a translation table entry is +a memory page. Therefore, if software needs to set different permissions on two +memory regions then it needs to map them using different memory pages. + +The default memory layout for each BL image is as follows: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +.. note:: + The 2KB alignment for the exception vectors is an architectural + requirement. + +The read-write data start on a new memory page so that they can be mapped with +read-write permissions, whereas the code and read-only data below are configured +as read-only. + +However, the read-only data are not aligned on a page boundary. They are +contiguous to the code. Therefore, the end of the code section and the beginning +of the read-only data one might share a memory page. This forces both to be +mapped with the same memory attributes. As the code needs to be executable, this +means that the read-only data stored on the same memory page as the code are +executable as well. This could potentially be exploited as part of a security +attack. + +TF provides the build flag ``SEPARATE_CODE_AND_RODATA`` to isolate the code and +read-only data on separate memory pages. This in turn allows independent control +of the access permissions for the code and read-only data. In this case, +platform code gets a finer-grained view of the image layout and can +appropriately map the code region as executable and the read-only data as +execute-never. + +This has an impact on memory footprint, as padding bytes need to be introduced +between the code and read-only data to ensure the segregation of the two. To +limit the memory cost, this flag also changes the memory layout such that the +code and exception vectors are now contiguous, like so: + +:: + + | ... | + +-------------------+ + | Read-write data | + +-------------------+ Page boundary + | | + +-------------------+ + | Read-only data | + +-------------------+ Page boundary + | | + +-------------------+ + | Exception vectors | + +-------------------+ 2 KB boundary + | | + +-------------------+ + | Code | + +-------------------+ BLx_BASE + +With this more condensed memory layout, the separation of read-only data will +add zero or one page to the memory footprint of each BL image. Each platform +should consider the trade-off between memory footprint and security. + +This build flag is disabled by default, minimising memory footprint. On Arm +platforms, it is enabled. + +Publish and Subscribe Framework +------------------------------- + +The Publish and Subscribe Framework allows EL3 components to define and publish +events, to which other EL3 components can subscribe. + +The following macros are provided by the framework: + +- ``REGISTER_PUBSUB_EVENT(event)``: Defines an event, and takes one argument, + the event name, which must be a valid C identifier. All calls to + ``REGISTER_PUBSUB_EVENT`` macro must be placed in the file + ``pubsub_events.h``. + +- ``PUBLISH_EVENT_ARG(event, arg)``: Publishes a defined event, by iterating + subscribed handlers and calling them in turn. The handlers will be passed the + parameter ``arg``. The expected use-case is to broadcast an event. + +- ``PUBLISH_EVENT(event)``: Like ``PUBLISH_EVENT_ARG``, except that the value + ``NULL`` is passed to subscribed handlers. + +- ``SUBSCRIBE_TO_EVENT(event, handler)``: Registers the ``handler`` to + subscribe to ``event``. The handler will be executed whenever the ``event`` + is published. + +- ``for_each_subscriber(event, subscriber)``: Iterates through all handlers + subscribed for ``event``. ``subscriber`` must be a local variable of type + ``pubsub_cb_t *``, and will point to each subscribed handler in turn during + iteration. This macro can be used for those patterns that none of the + ``PUBLISH_EVENT_*()`` macros cover. + +Publishing an event that wasn't defined using ``REGISTER_PUBSUB_EVENT`` will +result in build error. Subscribing to an undefined event however won't. + +Subscribed handlers must be of type ``pubsub_cb_t``, with following function +signature: + +.. code:: c + + typedef void* (*pubsub_cb_t)(const void *arg); + +There may be arbitrary number of handlers registered to the same event. The +order in which subscribed handlers are notified when that event is published is +not defined. Subscribed handlers may be executed in any order; handlers should +not assume any relative ordering amongst them. + +Publishing an event on a PE will result in subscribed handlers executing on that +PE only; it won't cause handlers to execute on a different PE. + +Note that publishing an event on a PE blocks until all the subscribed handlers +finish executing on the PE. + +TF-A generic code publishes and subscribes to some events within. Platform +ports are discouraged from subscribing to them. These events may be withdrawn, +renamed, or have their semantics altered in the future. Platforms may however +register, publish, and subscribe to platform-specific events. + +Publish and Subscribe Example +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A publisher that wants to publish event ``foo`` would: + +- Define the event ``foo`` in the ``pubsub_events.h``. + + .. code:: c + + REGISTER_PUBSUB_EVENT(foo); + +- Depending on the nature of event, use one of ``PUBLISH_EVENT_*()`` macros to + publish the event at the appropriate path and time of execution. + +A subscriber that wants to subscribe to event ``foo`` published above would +implement: + +.. code:: c + + void *foo_handler(const void *arg) + { + void *result; + + /* Do handling ... */ + + return result; + } + + SUBSCRIBE_TO_EVENT(foo, foo_handler); + + +Reclaiming the BL31 initialization code +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A significant amount of the code used for the initialization of BL31 is never +needed again after boot time. In order to reduce the runtime memory +footprint, the memory used for this code can be reclaimed after initialization +has finished and be used for runtime data. + +The build option ``RECLAIM_INIT_CODE`` can be set to mark this boot time code +with a ``.text.init.*`` attribute which can be filtered and placed suitably +within the BL image for later reclamation by the platform. The platform can +specify the filter and the memory region for this init section in BL31 via the +plat.ld.S linker script. For example, on the FVP, this section is placed +overlapping the secondary CPU stacks so that after the cold boot is done, this +memory can be reclaimed for the stacks. The init memory section is initially +mapped with ``RO``, ``EXECUTE`` attributes. After BL31 initialization has +completed, the FVP changes the attributes of this section to ``RW``, +``EXECUTE_NEVER`` allowing it to be used for runtime data. The memory attributes +are changed within the ``bl31_plat_runtime_setup`` platform hook. The init +section section can be reclaimed for any data which is accessed after cold +boot initialization and it is upto the platform to make the decision. + +.. _firmware_design_pmf: + +Performance Measurement Framework +--------------------------------- + +The Performance Measurement Framework (PMF) facilitates collection of +timestamps by registered services and provides interfaces to retrieve them +from within TF-A. A platform can choose to expose appropriate SMCs to +retrieve these collected timestamps. + +By default, the global physical counter is used for the timestamp +value and is read via ``CNTPCT_EL0``. The framework allows to retrieve +timestamps captured by other CPUs. + +Timestamp identifier format +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A PMF timestamp is uniquely identified across the system via the +timestamp ID or ``tid``. The ``tid`` is composed as follows: + +:: + + Bits 0-7: The local timestamp identifier. + Bits 8-9: Reserved. + Bits 10-15: The service identifier. + Bits 16-31: Reserved. + +#. The service identifier. Each PMF service is identified by a + service name and a service identifier. Both the service name and + identifier are unique within the system as a whole. + +#. The local timestamp identifier. This identifier is unique within a given + service. + +Registering a PMF service +~~~~~~~~~~~~~~~~~~~~~~~~~ + +To register a PMF service, the ``PMF_REGISTER_SERVICE()`` macro from ``pmf.h`` +is used. The arguments required are the service name, the service ID, +the total number of local timestamps to be captured and a set of flags. + +The ``flags`` field can be specified as a bitwise-OR of the following values: + +:: + + PMF_STORE_ENABLE: The timestamp is stored in memory for later retrieval. + PMF_DUMP_ENABLE: The timestamp is dumped on the serial console. + +The ``PMF_REGISTER_SERVICE()`` reserves memory to store captured +timestamps in a PMF specific linker section at build time. +Additionally, it defines necessary functions to capture and +retrieve a particular timestamp for the given service at runtime. + +The macro ``PMF_REGISTER_SERVICE()`` only enables capturing PMF timestamps +from within TF-A. In order to retrieve timestamps from outside of TF-A, the +``PMF_REGISTER_SERVICE_SMC()`` macro must be used instead. This macro +accepts the same set of arguments as the ``PMF_REGISTER_SERVICE()`` +macro but additionally supports retrieving timestamps using SMCs. + +Capturing a timestamp +~~~~~~~~~~~~~~~~~~~~~ + +PMF timestamps are stored in a per-service timestamp region. On a +system with multiple CPUs, each timestamp is captured and stored +in a per-CPU cache line aligned memory region. + +Having registered the service, the ``PMF_CAPTURE_TIMESTAMP()`` macro can be +used to capture a timestamp at the location where it is used. The macro +takes the service name, a local timestamp identifier and a flag as arguments. + +The ``flags`` field argument can be zero, or ``PMF_CACHE_MAINT`` which +instructs PMF to do cache maintenance following the capture. Cache +maintenance is required if any of the service's timestamps are captured +with data cache disabled. + +To capture a timestamp in assembly code, the caller should use +``pmf_calc_timestamp_addr`` macro (defined in ``pmf_asm_macros.S``) to +calculate the address of where the timestamp would be stored. The +caller should then read ``CNTPCT_EL0`` register to obtain the timestamp +and store it at the determined address for later retrieval. + +Retrieving a timestamp +~~~~~~~~~~~~~~~~~~~~~~ + +From within TF-A, timestamps for individual CPUs can be retrieved using either +``PMF_GET_TIMESTAMP_BY_MPIDR()`` or ``PMF_GET_TIMESTAMP_BY_INDEX()`` macros. +These macros accept the CPU's MPIDR value, or its ordinal position +respectively. + +From outside TF-A, timestamps for individual CPUs can be retrieved by calling +into ``pmf_smc_handler()``. + +:: + + Interface : pmf_smc_handler() + Argument : 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 + Return : uintptr_t + + smc_fid: Holds the SMC identifier which is either `PMF_SMC_GET_TIMESTAMP_32` + when the caller of the SMC is running in AArch32 mode + or `PMF_SMC_GET_TIMESTAMP_64` when the caller is running in AArch64 mode. + x1: Timestamp identifier. + x2: The `mpidr` of the CPU for which the timestamp has to be retrieved. + This can be the `mpidr` of a different core to the one initiating + the SMC. In that case, service specific cache maintenance may be + required to ensure the updated copy of the timestamp is returned. + x3: A flags value that is either 0 or `PMF_CACHE_MAINT`. If + `PMF_CACHE_MAINT` is passed, then the PMF code will perform a + cache invalidate before reading the timestamp. This ensures + an updated copy is returned. + +The remaining arguments, ``x4``, ``cookie``, ``handle`` and ``flags`` are unused +in this implementation. + +PMF code structure +~~~~~~~~~~~~~~~~~~ + +#. ``pmf_main.c`` consists of core functions that implement service registration, + initialization, storing, dumping and retrieving timestamps. + +#. ``pmf_smc.c`` contains the SMC handling for registered PMF services. + +#. ``pmf.h`` contains the public interface to Performance Measurement Framework. + +#. ``pmf_asm_macros.S`` consists of macros to facilitate capturing timestamps in + assembly code. + +#. ``pmf_helpers.h`` is an internal header used by ``pmf.h``. + +Armv8-A Architecture Extensions +------------------------------- + +TF-A makes use of Armv8-A Architecture Extensions where applicable. This +section lists the usage of Architecture Extensions, and build flags +controlling them. + +In general, and unless individually mentioned, the build options +``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` select the Architecture Extension to +target when building TF-A. Subsequent Arm Architecture Extensions are backward +compatible with previous versions. + +The build system only requires that ``ARM_ARCH_MAJOR`` and ``ARM_ARCH_MINOR`` have a +valid numeric value. These build options only control whether or not +Architecture Extension-specific code is included in the build. Otherwise, TF-A +targets the base Armv8.0-A architecture; i.e. as if ``ARM_ARCH_MAJOR`` == 8 +and ``ARM_ARCH_MINOR`` == 0, which are also their respective default values. + +.. seealso:: :ref:`Build Options` + +For details on the Architecture Extension and available features, please refer +to the respective Architecture Extension Supplement. + +Armv8.1-A +~~~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` >= 8, or when +``ARM_ARCH_MAJOR`` == 8 and ``ARM_ARCH_MINOR`` >= 1. + +- By default, a load-/store-exclusive instruction pair is used to implement + spinlocks. The ``USE_SPINLOCK_CAS`` build option when set to 1 selects the + spinlock implementation using the ARMv8.1-LSE Compare and Swap instruction. + Notice this instruction is only available in AArch64 execution state, so + the option is only available to AArch64 builds. + +Armv8.2-A +~~~~~~~~~ + +- The presence of ARMv8.2-TTCNP is detected at runtime. When it is present, the + Common not Private (TTBRn_ELx.CnP) bit is enabled to indicate that multiple + Processing Elements in the same Inner Shareable domain use the same + translation table entries for a given stage of translation for a particular + translation regime. + +Armv8.3-A +~~~~~~~~~ + +- Pointer authentication features of Armv8.3-A are unconditionally enabled in + the Non-secure world so that lower ELs are allowed to use them without + causing a trap to EL3. + + In order to enable the Secure world to use it, ``CTX_INCLUDE_PAUTH_REGS`` + must be set to 1. This will add all pointer authentication system registers + to the context that is saved when doing a world switch. + + The TF-A itself has support for pointer authentication at runtime + that can be enabled by setting ``BRANCH_PROTECTION`` option to non-zero and + ``CTX_INCLUDE_PAUTH_REGS`` to 1. This enables pointer authentication in BL1, + BL2, BL31, and the TSP if it is used. + + Note that Pointer Authentication is enabled for Non-secure world irrespective + of the value of these build flags if the CPU supports it. + + If ``ARM_ARCH_MAJOR == 8`` and ``ARM_ARCH_MINOR >= 3`` the code footprint of + enabling PAuth is lower because the compiler will use the optimized + PAuth instructions rather than the backwards-compatible ones. + +Armv8.5-A +~~~~~~~~~ + +- Branch Target Identification feature is selected by ``BRANCH_PROTECTION`` + option set to 1. This option defaults to 0. + +- Memory Tagging Extension feature is unconditionally enabled for both worlds + (at EL0 and S-EL0) if it is only supported at EL0. If instead it is + implemented at all ELs, it is unconditionally enabled for only the normal + world. To enable it for the secure world as well, the build option + ``CTX_INCLUDE_MTE_REGS`` is required. If the hardware does not implement + MTE support at all, it is always disabled, no matter what build options + are used. + +Armv7-A +~~~~~~~ + +This Architecture Extension is targeted when ``ARM_ARCH_MAJOR`` == 7. + +There are several Armv7-A extensions available. Obviously the TrustZone +extension is mandatory to support the TF-A bootloader and runtime services. + +Platform implementing an Armv7-A system can to define from its target +Cortex-A architecture through ``ARM_CORTEX_A = yes`` in their +``platform.mk`` script. For example ``ARM_CORTEX_A15=yes`` for a +Cortex-A15 target. + +Platform can also set ``ARM_WITH_NEON=yes`` to enable neon support. +Note that using neon at runtime has constraints on non secure world context. +TF-A does not yet provide VFP context management. + +Directive ``ARM_CORTEX_A`` and ``ARM_WITH_NEON`` are used to set +the toolchain target architecture directive. + +Platform may choose to not define straight the toolchain target architecture +directive by defining ``MARCH32_DIRECTIVE``. +I.e: + +.. code:: make + + MARCH32_DIRECTIVE := -mach=armv7-a + +Code Structure +-------------- + +TF-A code is logically divided between the three boot loader stages mentioned +in the previous sections. The code is also divided into the following +categories (present as directories in the source code): + +- **Platform specific.** Choice of architecture specific code depends upon + the platform. +- **Common code.** This is platform and architecture agnostic code. +- **Library code.** This code comprises of functionality commonly used by all + other code. The PSCI implementation and other EL3 runtime frameworks reside + as Library components. +- **Stage specific.** Code specific to a boot stage. +- **Drivers.** +- **Services.** EL3 runtime services (eg: SPD). Specific SPD services + reside in the ``services/spd`` directory (e.g. ``services/spd/tspd``). + +Each boot loader stage uses code from one or more of the above mentioned +categories. Based upon the above, the code layout looks like this: + +:: + + Directory Used by BL1? Used by BL2? Used by BL31? + bl1 Yes No No + bl2 No Yes No + bl31 No No Yes + plat Yes Yes Yes + drivers Yes No Yes + common Yes Yes Yes + lib Yes Yes Yes + services No No Yes + +The build system provides a non configurable build option IMAGE_BLx for each +boot loader stage (where x = BL stage). e.g. for BL1 , IMAGE_BL1 will be +defined by the build system. This enables TF-A to compile certain code only +for specific boot loader stages + +All assembler files have the ``.S`` extension. The linker source files for each +boot stage have the extension ``.ld.S``. These are processed by GCC to create the +linker scripts which have the extension ``.ld``. + +FDTs provide a description of the hardware platform and are used by the Linux +kernel at boot time. These can be found in the ``fdts`` directory. + +.. rubric:: References + +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D)`_ + +- `Power State Coordination Interface PDD`_ + +- `SMC Calling Convention`_ + +- :ref:`Interrupt Management Framework` + +-------------- + +*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Power State Coordination Interface PDD: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT) Armv8-A (ARM DEN0006D): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _Arm Confidential Compute Architecture (Arm CCA): https://www.arm.com/why-arm/architecture/security-features/arm-confidential-compute-architecture + +.. |Image 1| image:: ../resources/diagrams/rt-svc-descs-layout.png diff --git a/arm-trusted-firmware/docs/design/index.rst b/arm-trusted-firmware/docs/design/index.rst new file mode 100644 index 0000000..e3b8f74 --- /dev/null +++ b/arm-trusted-firmware/docs/design/index.rst @@ -0,0 +1,21 @@ +System Design +============= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + alt-boot-flows + auth-framework + cpu-specific-build-macros + firmware-design + interrupt-framework-design + psci-pd-tree + reset-design + trusted-board-boot + trusted-board-boot-build + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/interrupt-framework-design.rst b/arm-trusted-firmware/docs/design/interrupt-framework-design.rst new file mode 100644 index 0000000..dfb2eac --- /dev/null +++ b/arm-trusted-firmware/docs/design/interrupt-framework-design.rst @@ -0,0 +1,1021 @@ +Interrupt Management Framework +============================== + +This framework is responsible for managing interrupts routed to EL3. It also +allows EL3 software to configure the interrupt routing behavior. Its main +objective is to implement the following two requirements. + +#. It should be possible to route interrupts meant to be handled by secure + software (Secure interrupts) to EL3, when execution is in non-secure state + (normal world). The framework should then take care of handing control of + the interrupt to either software in EL3 or Secure-EL1 depending upon the + software configuration and the GIC implementation. This requirement ensures + that secure interrupts are under the control of the secure software with + respect to their delivery and handling without the possibility of + intervention from non-secure software. + +#. It should be possible to route interrupts meant to be handled by + non-secure software (Non-secure interrupts) to the last executed exception + level in the normal world when the execution is in secure world at + exception levels lower than EL3. This could be done with or without the + knowledge of software executing in Secure-EL1/Secure-EL0. The choice of + approach should be governed by the secure software. This requirement + ensures that non-secure software is able to execute in tandem with the + secure software without overriding it. + +Concepts +-------- + +Interrupt types +~~~~~~~~~~~~~~~ + +The framework categorises an interrupt to be one of the following depending upon +the exception level(s) it is handled in. + +#. Secure EL1 interrupt. This type of interrupt can be routed to EL3 or + Secure-EL1 depending upon the security state of the current execution + context. It is always handled in Secure-EL1. + +#. Non-secure interrupt. This type of interrupt can be routed to EL3, + Secure-EL1, Non-secure EL1 or EL2 depending upon the security state of the + current execution context. It is always handled in either Non-secure EL1 + or EL2. + +#. EL3 interrupt. This type of interrupt can be routed to EL3 or Secure-EL1 + depending upon the security state of the current execution context. It is + always handled in EL3. + +The following constants define the various interrupt types in the framework +implementation. + +.. code:: c + + #define INTR_TYPE_S_EL1 0 + #define INTR_TYPE_EL3 1 + #define INTR_TYPE_NS 2 + +Routing model +~~~~~~~~~~~~~ + +A type of interrupt can be either generated as an FIQ or an IRQ. The target +exception level of an interrupt type is configured through the FIQ and IRQ bits +in the Secure Configuration Register at EL3 (``SCR_EL3.FIQ`` and ``SCR_EL3.IRQ`` +bits). When ``SCR_EL3.FIQ``\ =1, FIQs are routed to EL3. Otherwise they are routed +to the First Exception Level (FEL) capable of handling interrupts. When +``SCR_EL3.IRQ``\ =1, IRQs are routed to EL3. Otherwise they are routed to the +FEL. This register is configured independently by EL3 software for each security +state prior to entry into a lower exception level in that security state. + +A routing model for a type of interrupt (generated as FIQ or IRQ) is defined as +its target exception level for each security state. It is represented by a +single bit for each security state. A value of ``0`` means that the interrupt +should be routed to the FEL. A value of ``1`` means that the interrupt should be +routed to EL3. A routing model is applicable only when execution is not in EL3. + +The default routing model for an interrupt type is to route it to the FEL in +either security state. + +Valid routing models +~~~~~~~~~~~~~~~~~~~~ + +The framework considers certain routing models for each type of interrupt to be +incorrect as they conflict with the requirements mentioned in Section 1. The +following sub-sections describe all the possible routing models and specify +which ones are valid or invalid. EL3 interrupts are currently supported only +for GIC version 3.0 (Arm GICv3) and only the Secure-EL1 and Non-secure interrupt +types are supported for GIC version 2.0 (Arm GICv2) (see `Assumptions in +Interrupt Management Framework`_). The terminology used in the following +sub-sections is explained below. + +#. **CSS**. Current Security State. ``0`` when secure and ``1`` when non-secure + +#. **TEL3**. Target Exception Level 3. ``0`` when targeted to the FEL. ``1`` when + targeted to EL3. + +Secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This is a valid routing model as secure software is in + control of handling secure interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can + handover the interrupt to Secure-EL1 for handling. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handover the interrupt to Secure-EL1 for handling. + +Non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + secure state. This allows the secure software to trap non-secure + interrupts, perform its book-keeping and hand the interrupt to the + non-secure software through EL3. This is a valid routing model as secure + software is in control of how its execution is preempted by non-secure + interrupts. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in secure + state. This is a valid routing model as secure software in EL3 can save + the state of software in Secure-EL1/Secure-EL0 before handing the + interrupt to non-secure software. This model requires additional + coordination between Secure-EL1 and EL3 software to ensure that the + former's state is correctly saved by the latter. + +#. **CSS=1, TEL3=0**. Interrupt is routed to FEL when execution is in + non-secure state. This is a valid routing model as a non-secure interrupt + is handled by non-secure software. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is an invalid routing model as there is no valid + reason to route the interrupt to EL3 software and then hand it back to + non-secure software for handling. + +.. _EL3 interrupts: + +EL3 interrupts +^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. Interrupt is routed to the FEL when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in Secure-EL1/Secure-EL0 is in control of how its execution is preempted + by EL3 interrupt and can handover the interrupt to EL3 for handling. + + However, when ``EL3_EXCEPTION_HANDLING`` is ``1``, this routing model is + invalid as EL3 interrupts are unconditionally routed to EL3, and EL3 + interrupts will always preempt Secure EL1/EL0 execution. See :ref:`exception + handling` documentation. + +#. **CSS=0, TEL3=1**. Interrupt is routed to EL3 when execution is in + Secure-EL1/Secure-EL0. This is a valid routing model as secure software + in EL3 can handle the interrupt. + +#. **CSS=1, TEL3=0**. Interrupt is routed to the FEL when execution is in + non-secure state. This is an invalid routing model as a secure interrupt + is not visible to the secure software which violates the motivation behind + the Arm Security Extensions. + +#. **CSS=1, TEL3=1**. Interrupt is routed to EL3 when execution is in + non-secure state. This is a valid routing model as secure software in EL3 + can handle the interrupt. + +Mapping of interrupt type to signal +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The framework is meant to work with any interrupt controller implemented by a +platform. A interrupt controller could generate a type of interrupt as either an +FIQ or IRQ signal to the CPU depending upon the current security state. The +mapping between the type and signal is known only to the platform. The framework +uses this information to determine whether the IRQ or the FIQ bit should be +programmed in ``SCR_EL3`` while applying the routing model for a type of +interrupt. The platform provides this information through the +``plat_interrupt_type_to_line()`` API (described in the +:ref:`Porting Guide`). For example, on the FVP port when the platform uses an +Arm GICv2 interrupt controller, Secure-EL1 interrupts are signaled through the +FIQ signal while Non-secure interrupts are signaled through the IRQ signal. +This applies when execution is in either security state. + +Effect of mapping of several interrupt types to one signal +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It should be noted that if more than one interrupt type maps to a single +interrupt signal, and if any one of the interrupt type sets **TEL3=1** for a +particular security state, then interrupt signal will be routed to EL3 when in +that security state. This means that all the other interrupt types using the +same interrupt signal will be forced to the same routing model. This should be +borne in mind when choosing the routing model for an interrupt type. + +For example, in Arm GICv3, when the execution context is Secure-EL1/ +Secure-EL0, both the EL3 and the non secure interrupt types map to the FIQ +signal. So if either one of the interrupt type sets the routing model so +that **TEL3=1** when **CSS=0**, the FIQ bit in ``SCR_EL3`` will be programmed to +route the FIQ signal to EL3 when executing in Secure-EL1/Secure-EL0, thereby +effectively routing the other interrupt type also to EL3. + +Assumptions in Interrupt Management Framework +--------------------------------------------- + +The framework makes the following assumptions to simplify its implementation. + +#. Although the framework has support for 2 types of secure interrupts (EL3 + and Secure-EL1 interrupt), only interrupt controller architectures + like Arm GICv3 has architectural support for EL3 interrupts in the form of + Group 0 interrupts. In Arm GICv2, all secure interrupts are assumed to be + handled in Secure-EL1. They can be delivered to Secure-EL1 via EL3 but they + cannot be handled in EL3. + +#. Interrupt exceptions (``PSTATE.I`` and ``F`` bits) are masked during execution + in EL3. + +#. Interrupt management: the following sections describe how interrupts are + managed by the interrupt handling framework. This entails: + + #. Providing an interface to allow registration of a handler and + specification of the routing model for a type of interrupt. + + #. Implementing support to hand control of an interrupt type to its + registered handler when the interrupt is generated. + +Both aspects of interrupt management involve various components in the secure +software stack spanning from EL3 to Secure-EL1. These components are described +in the section `Software components`_. The framework stores information +associated with each type of interrupt in the following data structure. + +.. code:: c + + typedef struct intr_type_desc { + interrupt_type_handler_t handler; + uint32_t flags; + uint32_t scr_el3[2]; + } intr_type_desc_t; + +The ``flags`` field stores the routing model for the interrupt type in +bits[1:0]. Bit[0] stores the routing model when execution is in the secure +state. Bit[1] stores the routing model when execution is in the non-secure +state. As mentioned in Section `Routing model`_, a value of ``0`` implies that +the interrupt should be targeted to the FEL. A value of ``1`` implies that it +should be targeted to EL3. The remaining bits are reserved and SBZ. The helper +macro ``set_interrupt_rm_flag()`` should be used to set the bits in the +``flags`` parameter. + +The ``scr_el3[2]`` field also stores the routing model but as a mapping of the +model in the ``flags`` field to the corresponding bit in the ``SCR_EL3`` for each +security state. + +The framework also depends upon the platform port to configure the interrupt +controller to distinguish between secure and non-secure interrupts. The platform +is expected to be aware of the secure devices present in the system and their +associated interrupt numbers. It should configure the interrupt controller to +enable the secure interrupts, ensure that their priority is always higher than +the non-secure interrupts and target them to the primary CPU. It should also +export the interface described in the :ref:`Porting Guide` to enable +handling of interrupts. + +In the remainder of this document, for the sake of simplicity a Arm GICv2 system +is considered and it is assumed that the FIQ signal is used to generate Secure-EL1 +interrupts and the IRQ signal is used to generate non-secure interrupts in either +security state. EL3 interrupts are not considered. + +Software components +------------------- + +Roles and responsibilities for interrupt management are sub-divided between the +following components of software running in EL3 and Secure-EL1. Each component is +briefly described below. + +#. EL3 Runtime Firmware. This component is common to all ports of TF-A. + +#. Secure Payload Dispatcher (SPD) service. This service interfaces with the + Secure Payload (SP) software which runs in Secure-EL1/Secure-EL0 and is + responsible for switching execution between secure and non-secure states. + A switch is triggered by a Secure Monitor Call and it uses the APIs + exported by the Context management library to implement this functionality. + Switching execution between the two security states is a requirement for + interrupt management as well. This results in a significant dependency on + the SPD service. TF-A implements an example Test Secure Payload Dispatcher + (TSPD) service. + + An SPD service plugs into the EL3 runtime firmware and could be common to + some ports of TF-A. + +#. Secure Payload (SP). On a production system, the Secure Payload corresponds + to a Secure OS which runs in Secure-EL1/Secure-EL0. It interfaces with the + SPD service to manage communication with non-secure software. TF-A + implements an example secure payload called Test Secure Payload (TSP) + which runs only in Secure-EL1. + + A Secure payload implementation could be common to some ports of TF-A, + just like the SPD service. + +Interrupt registration +---------------------- + +This section describes in detail the role of each software component (see +`Software components`_) during the registration of a handler for an interrupt +type. + +.. _el3-runtime-firmware: + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +This component declares the following prototype for a handler of an interrupt type. + +.. code:: c + + typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +The ``id`` is parameter is reserved and could be used in the future for passing +the interrupt id of the highest pending interrupt only if there is a foolproof +way of determining the id. Currently it contains ``INTR_ID_UNAVAILABLE``. + +The ``flags`` parameter contains miscellaneous information as follows. + +#. Security state, bit[0]. This bit indicates the security state of the lower + exception level when the interrupt was generated. A value of ``1`` means + that it was in the non-secure state. A value of ``0`` indicates that it was + in the secure state. This bit can be used by the handler to ensure that + interrupt was generated and routed as per the routing model specified + during registration. + +#. Reserved, bits[31:1]. The remaining bits are reserved for future use. + +The ``handle`` parameter points to the ``cpu_context`` structure of the current CPU +for the security state specified in the ``flags`` parameter. + +Once the handler routine completes, execution will return to either the secure +or non-secure state. The handler routine must return a pointer to +``cpu_context`` structure of the current CPU for the target security state. On +AArch64, this return value is currently ignored by the caller as the +appropriate ``cpu_context`` to be used is expected to be set by the handler +via the context management library APIs. +A portable interrupt handler implementation must set the target context both in +the structure pointed to by the returned pointer and via the context management +library APIs. The handler should treat all error conditions as critical errors +and take appropriate action within its implementation e.g. use assertion +failures. + +The runtime firmware provides the following API for registering a handler for a +particular type of interrupt. A Secure Payload Dispatcher service should use +this API to register a handler for Secure-EL1 and optionally for non-secure +interrupts. This API also requires the caller to specify the routing model for +the type of interrupt. + +.. code:: c + + int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler handler, + uint64_t flags); + +The ``type`` parameter can be one of the three interrupt types listed above i.e. +``INTR_TYPE_S_EL1``, ``INTR_TYPE_NS`` & ``INTR_TYPE_EL3``. The ``flags`` parameter +is as described in Section 2. + +The function will return ``0`` upon a successful registration. It will return +``-EALREADY`` in case a handler for the interrupt type has already been +registered. If the ``type`` is unrecognised or the ``flags`` or the ``handler`` are +invalid it will return ``-EINVAL``. + +Interrupt routing is governed by the configuration of the ``SCR_EL3.FIQ/IRQ`` bits +prior to entry into a lower exception level in either security state. The +context management library maintains a copy of the ``SCR_EL3`` system register for +each security state in the ``cpu_context`` structure of each CPU. It exports the +following APIs to let EL3 Runtime Firmware program and retrieve the routing +model for each security state for the current CPU. The value of ``SCR_EL3`` stored +in the ``cpu_context`` is used by the ``el3_exit()`` function to program the +``SCR_EL3`` register prior to returning from the EL3 exception level. + +.. code:: c + + uint32_t cm_get_scr_el3(uint32_t security_state); + void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); + +``cm_get_scr_el3()`` returns the value of the ``SCR_EL3`` register for the specified +security state of the current CPU. ``cm_write_scr_el3_bit()`` writes a ``0`` or ``1`` +to the bit specified by ``bit_pos``. ``register_interrupt_type_handler()`` invokes +``set_routing_model()`` API which programs the ``SCR_EL3`` according to the routing +model using the ``cm_get_scr_el3()`` and ``cm_write_scr_el3_bit()`` APIs. + +It is worth noting that in the current implementation of the framework, the EL3 +runtime firmware is responsible for programming the routing model. The SPD is +responsible for ensuring that the routing model has been adhered to upon +receiving an interrupt. + +.. _spd-int-registration: + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +A SPD service is responsible for determining and maintaining the interrupt +routing model supported by itself and the Secure Payload. It is also responsible +for ferrying interrupts between secure and non-secure software depending upon +the routing model. It could determine the routing model at build time or at +runtime. It must use this information to register a handler for each interrupt +type using the ``register_interrupt_type_handler()`` API in EL3 runtime firmware. + +If the routing model is not known to the SPD service at build time, then it must +be provided by the SP as the result of its initialisation. The SPD should +program the routing model only after SP initialisation has completed e.g. in the +SPD initialisation function pointed to by the ``bl32_init`` variable. + +The SPD should determine the mechanism to pass control to the Secure Payload +after receiving an interrupt from the EL3 runtime firmware. This information +could either be provided to the SPD service at build time or by the SP at +runtime. + +Test secure payload dispatcher behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. note:: + Where this document discusses ``TSP_NS_INTR_ASYNC_PREEMPT`` as being + ``1``, the same results also apply when ``EL3_EXCEPTION_HANDLING`` is ``1``. + +The TSPD only handles Secure-EL1 interrupts and is provided with the following +routing model at build time. + +- Secure-EL1 interrupts are routed to EL3 when execution is in non-secure + state and are routed to the FEL when execution is in the secure state + i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=1** for Secure-EL1 interrupts + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is zero, the default routing + model is used for non-secure interrupts. They are routed to the FEL in + either security state i.e **CSS=0, TEL3=0** & **CSS=1, TEL3=0** for + Non-secure interrupts. + +- When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, then the + non secure interrupts are routed to EL3 when execution is in secure state + i.e **CSS=0, TEL3=1** for non-secure interrupts. This effectively preempts + Secure-EL1. The default routing model is used for non secure interrupts in + non-secure state. i.e **CSS=1, TEL3=0**. + +It performs the following actions in the ``tspd_init()`` function to fulfill the +requirements mentioned earlier. + +#. It passes control to the Test Secure Payload to perform its + initialisation. The TSP provides the address of the vector table + ``tsp_vectors`` in the SP which also includes the handler for Secure-EL1 + interrupts in the ``sel1_intr_entry`` field. The TSPD passes control to the TSP at + this address when it receives a Secure-EL1 interrupt. + + The handover agreement between the TSP and the TSPD requires that the TSPD + masks all interrupts (``PSTATE.DAIF`` bits) when it calls + ``tsp_sel1_intr_entry()``. The TSP has to preserve the callee saved general + purpose, SP_EL1/Secure-EL0, LR, VFP and system registers. It can use + ``x0-x18`` to enable its C runtime. + +#. The TSPD implements a handler function for Secure-EL1 interrupts. This + function is registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_secure_el1_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_secure_el1_interrupt_handler, + flags); + if (rc) + panic(); + +#. When the build flag ``TSP_NS_INTR_ASYNC_PREEMPT`` is defined to 1, the TSPD + implements a handler function for non-secure interrupts. This function is + registered with the EL3 runtime firmware using the + ``register_interrupt_type_handler()`` API as follows + + .. code:: c + + /* Forward declaration */ + interrupt_type_handler tspd_ns_interrupt_handler; + int32_t rc, flags = 0; + set_interrupt_rm_flag(flags, SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + +.. _sp-int-registration: + +Secure payload +~~~~~~~~~~~~~~ + +A Secure Payload must implement an interrupt handling framework at Secure-EL1 +(Secure-EL1 IHF) to support its chosen interrupt routing model. Secure payload +execution will alternate between the below cases. + +#. In the code where IRQ, FIQ or both interrupts are enabled, if an interrupt + type is targeted to the FEL, then it will be routed to the Secure-EL1 + exception vector table. This is defined as the **asynchronous mode** of + handling interrupts. This mode applies to both Secure-EL1 and non-secure + interrupts. + +#. In the code where both interrupts are disabled, if an interrupt type is + targeted to the FEL, then execution will eventually migrate to the + non-secure state. Any non-secure interrupts will be handled as described + in the routing model where **CSS=1 and TEL3=0**. Secure-EL1 interrupts + will be routed to EL3 (as per the routing model where **CSS=1 and + TEL3=1**) where the SPD service will hand them to the SP. This is defined + as the **synchronous mode** of handling interrupts. + +The interrupt handling framework implemented by the SP should support one or +both these interrupt handling models depending upon the chosen routing model. + +The following list briefly describes how the choice of a valid routing model +(see `Valid routing models`_) effects the implementation of the Secure-EL1 +IHF. If the choice of the interrupt routing model is not known to the SPD +service at compile time, then the SP should pass this information to the SPD +service at runtime during its initialisation phase. + +As mentioned earlier, an Arm GICv2 system is considered and it is assumed that +the FIQ signal is used to generate Secure-EL1 interrupts and the IRQ signal +is used to generate non-secure interrupts in either security state. + +Secure payload IHF design w.r.t secure-EL1 interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.F=0``, Secure-EL1 interrupts will be + triggered at one of the Secure-EL1 FIQ exception vectors. The Secure-EL1 + IHF should implement support for handling FIQ interrupts asynchronously. + + If ``PSTATE.F=1`` then Secure-EL1 interrupts will be handled as per the + synchronous interrupt handling model. The SP could implement this scenario + by exporting a separate entrypoint for Secure-EL1 interrupts to the SPD + service during the registration phase. The SPD service would also need to + know the state of the system, general purpose and the ``PSTATE`` registers + in which it should arrange to return execution to the SP. The SP should + provide this information in an implementation defined way during the + registration phase if it is not known to the SPD service at build time. + +#. **CSS=1, TEL3=1**. Interrupts are routed to EL3 when execution is in + non-secure state. They should be handled through the synchronous interrupt + handling model as described in 1. above. + +#. **CSS=0, TEL3=1**. Secure-EL1 interrupts are routed to EL3 when execution + is in secure state. They will not be visible to the SP. The ``PSTATE.F`` bit + in Secure-EL1/Secure-EL0 will not mask FIQs. The EL3 runtime firmware will + call the handler registered by the SPD service for Secure-EL1 interrupts. + Secure-EL1 IHF should then handle all Secure-EL1 interrupt through the + synchronous interrupt handling model described in 1. above. + +Secure payload IHF design w.r.t non-secure interrupts +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. **CSS=0, TEL3=0**. If ``PSTATE.I=0``, non-secure interrupts will be + triggered at one of the Secure-EL1 IRQ exception vectors . The Secure-EL1 + IHF should co-ordinate with the SPD service to transfer execution to the + non-secure state where the interrupt should be handled e.g the SP could + allocate a function identifier to issue a SMC64 or SMC32 to the SPD + service which indicates that the SP execution has been preempted by a + non-secure interrupt. If this function identifier is not known to the SPD + service at compile time then the SP could provide it during the + registration phase. + + If ``PSTATE.I=1`` then the non-secure interrupt will pend until execution + resumes in the non-secure state. + +#. **CSS=0, TEL3=1**. Non-secure interrupts are routed to EL3. They will not + be visible to the SP. The ``PSTATE.I`` bit in Secure-EL1/Secure-EL0 will + have not effect. The SPD service should register a non-secure interrupt + handler which should save the SP state correctly and resume execution in + the non-secure state where the interrupt will be handled. The Secure-EL1 + IHF does not need to take any action. + +#. **CSS=1, TEL3=0**. Non-secure interrupts are handled in the FEL in + non-secure state (EL1/EL2) and are not visible to the SP. This routing + model does not affect the SP behavior. + +A Secure Payload must also ensure that all Secure-EL1 interrupts are correctly +configured at the interrupt controller by the platform port of the EL3 runtime +firmware. It should configure any additional Secure-EL1 interrupts which the EL3 +runtime firmware is not aware of through its platform port. + +Test secure payload behavior +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The routing model for Secure-EL1 and non-secure interrupts chosen by the TSP is +described in Section `Secure Payload Dispatcher`__. It is known to the TSPD +service at build time. + +.. __: #spd-int-registration + +The TSP implements an entrypoint (``tsp_sel1_intr_entry()``) for handling Secure-EL1 +interrupts taken in non-secure state and routed through the TSPD service +(synchronous handling model). It passes the reference to this entrypoint via +``tsp_vectors`` to the TSPD service. + +The TSP also replaces the default exception vector table referenced through the +``early_exceptions`` variable, with a vector table capable of handling FIQ and IRQ +exceptions taken at the same (Secure-EL1) exception level. This table is +referenced through the ``tsp_exceptions`` variable and programmed into the +VBAR_EL1. It caters for the asynchronous handling model. + +The TSP also programs the Secure Physical Timer in the Arm Generic Timer block +to raise a periodic interrupt (every half a second) for the purpose of testing +interrupt management across all the software components listed in `Software +components`_. + +Interrupt handling +------------------ + +This section describes in detail the role of each software component (see +Section `Software components`_) in handling an interrupt of a particular type. + +EL3 runtime firmware +~~~~~~~~~~~~~~~~~~~~ + +The EL3 runtime firmware populates the IRQ and FIQ exception vectors referenced +by the ``runtime_exceptions`` variable as follows. + +#. IRQ and FIQ exceptions taken from the current exception level with + ``SP_EL0`` or ``SP_EL3`` are reported as irrecoverable error conditions. As + mentioned earlier, EL3 runtime firmware always executes with the + ``PSTATE.I`` and ``PSTATE.F`` bits set. + +#. The following text describes how the IRQ and FIQ exceptions taken from a + lower exception level using AArch64 or AArch32 are handled. + +When an interrupt is generated, the vector for each interrupt type is +responsible for: + +#. Saving the entire general purpose register context (x0-x30) immediately + upon exception entry. The registers are saved in the per-cpu ``cpu_context`` + data structure referenced by the ``SP_EL3``\ register. + +#. Saving the ``ELR_EL3``, ``SP_EL0`` and ``SPSR_EL3`` system registers in the + per-cpu ``cpu_context`` data structure referenced by the ``SP_EL3`` register. + +#. Switching to the C runtime stack by restoring the ``CTX_RUNTIME_SP`` value + from the per-cpu ``cpu_context`` data structure in ``SP_EL0`` and + executing the ``msr spsel, #0`` instruction. + +#. Determining the type of interrupt. Secure-EL1 interrupts will be signaled + at the FIQ vector. Non-secure interrupts will be signaled at the IRQ + vector. The platform should implement the following API to determine the + type of the pending interrupt. + + .. code:: c + + uint32_t plat_ic_get_interrupt_type(void); + + It should return either ``INTR_TYPE_S_EL1`` or ``INTR_TYPE_NS``. + +#. Determining the handler for the type of interrupt that has been generated. + The following API has been added for this purpose. + + .. code:: c + + interrupt_type_handler get_interrupt_type_handler(uint32_t interrupt_type); + + It returns the reference to the registered handler for this interrupt + type. The ``handler`` is retrieved from the ``intr_type_desc_t`` structure as + described in Section 2. ``NULL`` is returned if no handler has been + registered for this type of interrupt. This scenario is reported as an + irrecoverable error condition. + +#. Calling the registered handler function for the interrupt type generated. + The ``id`` parameter is set to ``INTR_ID_UNAVAILABLE`` currently. The id along + with the current security state and a reference to the ``cpu_context_t`` + structure for the current security state are passed to the handler function + as its arguments. + + The handler function returns a reference to the per-cpu ``cpu_context_t`` + structure for the target security state. + +#. Calling ``el3_exit()`` to return from EL3 into a lower exception level in + the security state determined by the handler routine. The ``el3_exit()`` + function is responsible for restoring the register context from the + ``cpu_context_t`` data structure for the target security state. + +Secure payload dispatcher +~~~~~~~~~~~~~~~~~~~~~~~~~ + +Interrupt entry +^^^^^^^^^^^^^^^ + +The SPD service begins handling an interrupt when the EL3 runtime firmware calls +the handler function for that type of interrupt. The SPD service is responsible +for the following: + +#. Validating the interrupt. This involves ensuring that the interrupt was + generated according to the interrupt routing model specified by the SPD + service during registration. It should use the security state of the + exception level (passed in the ``flags`` parameter of the handler) where + the interrupt was taken from to determine this. If the interrupt is not + recognised then the handler should treat it as an irrecoverable error + condition. + + An SPD service can register a handler for Secure-EL1 and/or Non-secure + interrupts. A non-secure interrupt should never be routed to EL3 from + from non-secure state. Also if a routing model is chosen where Secure-EL1 + interrupts are routed to S-EL1 when execution is in Secure state, then a + S-EL1 interrupt should never be routed to EL3 from secure state. The handler + could use the security state flag to check this. + +#. Determining whether a context switch is required. This depends upon the + routing model and interrupt type. For non secure and S-EL1 interrupt, + if the security state of the execution context where the interrupt was + generated is not the same as the security state required for handling + the interrupt, a context switch is required. The following 2 cases + require a context switch from secure to non-secure or vice-versa: + + #. A Secure-EL1 interrupt taken from the non-secure state should be + routed to the Secure Payload. + + #. A non-secure interrupt taken from the secure state should be routed + to the last known non-secure exception level. + + The SPD service must save the system register context of the current + security state. It must then restore the system register context of the + target security state. It should use the ``cm_set_next_eret_context()`` API + to ensure that the next ``cpu_context`` to be restored is of the target + security state. + + If the target state is secure then execution should be handed to the SP as + per the synchronous interrupt handling model it implements. A Secure-EL1 + interrupt can be routed to EL3 while execution is in the SP. This implies + that SP execution can be preempted while handling an interrupt by a + another higher priority Secure-EL1 interrupt or a EL3 interrupt. The SPD + service should be able to handle this preemption or manage secure interrupt + priorities before handing control to the SP. + +#. Setting the return value of the handler to the per-cpu ``cpu_context`` if + the interrupt has been successfully validated and ready to be handled at a + lower exception level. + +The routing model allows non-secure interrupts to interrupt Secure-EL1 when in +secure state if it has been configured to do so. The SPD service and the SP +should implement a mechanism for routing these interrupts to the last known +exception level in the non-secure state. The former should save the SP context, +restore the non-secure context and arrange for entry into the non-secure state +so that the interrupt can be handled. + +Interrupt exit +^^^^^^^^^^^^^^ + +When the Secure Payload has finished handling a Secure-EL1 interrupt, it could +return control back to the SPD service through a SMC32 or SMC64. The SPD service +should handle this secure monitor call so that execution resumes in the +exception level and the security state from where the Secure-EL1 interrupt was +originally taken. + +Test secure payload dispatcher Secure-EL1 interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The example TSPD service registers a handler for Secure-EL1 interrupts taken +from the non-secure state. During execution in S-EL1, the TSPD expects that the +Secure-EL1 interrupts are handled in S-EL1 by TSP. Its handler +``tspd_secure_el1_interrupt_handler()`` expects only to be invoked for Secure-EL1 +originating from the non-secure state. It takes the following actions upon being +invoked. + +#. It uses the security state provided in the ``flags`` parameter to ensure + that the secure interrupt originated from the non-secure state. It asserts + if this is not the case. + +#. It saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE);``. + +#. It sets the ``ELR_EL3`` system register to ``tsp_sel1_intr_entry`` and sets the + ``SPSR_EL3.DAIF`` bits in the secure CPU context. It sets ``x0`` to + ``TSP_HANDLE_SEL1_INTR_AND_RETURN``. If the TSP was preempted earlier by a non + secure interrupt during ``yielding`` SMC processing, save the registers that + will be trashed, which is the ``ELR_EL3`` and ``SPSR_EL3``, in order to be able + to re-enter TSP for Secure-EL1 interrupt processing. It does not need to + save any other secure context since the TSP is expected to preserve it + (see section `Test secure payload dispatcher behavior`_). + +#. It restores the system register context for the secure state by calling + ``cm_el1_sysregs_context_restore(SECURE);``. + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE);``. + +#. It returns the per-cpu ``cpu_context`` to indicate that the interrupt can + now be handled by the SP. ``x1`` is written with the value of ``elr_el3`` + register for the non-secure state. This information is used by the SP for + debugging purposes. + +The figure below describes how the interrupt handling is implemented by the TSPD +when a Secure-EL1 interrupt is generated when execution is in the non-secure +state. + +|Image 1| + +The TSP issues an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier to +signal completion of interrupt handling. + +The TSPD service takes the following actions in ``tspd_smc_handler()`` function +upon receiving an SMC with ``TSP_HANDLED_S_EL1_INTR`` as the function identifier: + +#. It ensures that the call originated from the secure state otherwise + execution returns to the non-secure state with ``SMC_UNK`` in ``x0``. + +#. It restores the saved ``ELR_EL3`` and ``SPSR_EL3`` system registers back to + the secure CPU context (see step 3 above) in case the TSP had been preempted + by a non secure interrupt earlier. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the non-secure ``cpu_context`` + as the return value. + +Test secure payload dispatcher non-secure interrupt handling +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSP in Secure-EL1 can be preempted by a non-secure interrupt during +``yielding`` SMC processing or by a higher priority EL3 interrupt during +Secure-EL1 interrupt processing. When ``EL3_EXCEPTION_HANDLING`` is ``0``, only +non-secure interrupts can cause preemption of TSP since there are no EL3 +interrupts in the system. With ``EL3_EXCEPTION_HANDLING=1`` however, any EL3 +interrupt may preempt Secure execution. + +It should be noted that while TSP is preempted, the TSPD only allows entry into +the TSP either for Secure-EL1 interrupt handling or for resuming the preempted +``yielding`` SMC in response to the ``TSP_FID_RESUME`` SMC from the normal world. +(See Section `Implication of preempted SMC on Non-Secure Software`_). + +The non-secure interrupt triggered in Secure-EL1 during ``yielding`` SMC +processing can be routed to either EL3 or Secure-EL1 and is controlled by build +option ``TSP_NS_INTR_ASYNC_PREEMPT`` (see Section `Test secure payload +dispatcher behavior`_). If the build option is set, the TSPD will set the +routing model for the non-secure interrupt to be routed to EL3 from secure state +i.e. **TEL3=1, CSS=0** and registers ``tspd_ns_interrupt_handler()`` as the +non-secure interrupt handler. The ``tspd_ns_interrupt_handler()`` on being +invoked ensures that the interrupt originated from the secure state and disables +routing of non-secure interrupts from secure state to EL3. This is to prevent +further preemption (by a non-secure interrupt) when TSP is reentered for +handling Secure-EL1 interrupts that triggered while execution was in the normal +world. The ``tspd_ns_interrupt_handler()`` then invokes +``tspd_handle_sp_preemption()`` for further handling. + +If the ``TSP_NS_INTR_ASYNC_PREEMPT`` build option is zero (default), the default +routing model for non-secure interrupt in secure state is in effect +i.e. **TEL3=0, CSS=0**. During ``yielding`` SMC processing, the IRQ +exceptions are unmasked i.e. ``PSTATE.I=0``, and a non-secure interrupt will +trigger at Secure-EL1 IRQ exception vector. The TSP saves the general purpose +register context and issues an SMC with ``TSP_PREEMPTED`` as the function +identifier to signal preemption of TSP. The TSPD SMC handler, +``tspd_smc_handler()``, ensures that the SMC call originated from the +secure state otherwise execution returns to the non-secure state with +``SMC_UNK`` in ``x0``. It then invokes ``tspd_handle_sp_preemption()`` for +further handling. + +The ``tspd_handle_sp_preemption()`` takes the following actions upon being +invoked: + +#. It saves the system register context for the secure state by calling + ``cm_el1_sysregs_context_save(SECURE)``. + +#. It restores the system register context for the non-secure state by + calling ``cm_el1_sysregs_context_restore(NON_SECURE)``. + +#. It ensures that the non-secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(NON_SECURE)``. + +#. ``SMC_PREEMPTED`` is set in x0 and return to non secure state after + restoring non secure context. + +The Normal World is expected to resume the TSP after the ``yielding`` SMC +preemption by issuing an SMC with ``TSP_FID_RESUME`` as the function identifier +(see section `Implication of preempted SMC on Non-Secure Software`_). The TSPD +service takes the following actions in ``tspd_smc_handler()`` function upon +receiving this SMC: + +#. It ensures that the call originated from the non secure state. An + assertion is raised otherwise. + +#. Checks whether the TSP needs a resume i.e check if it was preempted. It + then saves the system register context for the non-secure state by calling + ``cm_el1_sysregs_context_save(NON_SECURE)``. + +#. Restores the secure context by calling + ``cm_el1_sysregs_context_restore(SECURE)`` + +#. It ensures that the secure CPU context is used to program the next + exception return from EL3 by calling ``cm_set_next_eret_context(SECURE)``. + +#. ``tspd_smc_handler()`` returns a reference to the secure ``cpu_context`` as the + return value. + +The figure below describes how the TSP/TSPD handle a non-secure interrupt when +it is generated during execution in the TSP with ``PSTATE.I`` = 0 when the +``TSP_NS_INTR_ASYNC_PREEMPT`` build flag is 0. + +|Image 2| + +.. _sp-synchronous-int: + +Secure payload interrupt handling +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The SP should implement one or both of the synchronous and asynchronous +interrupt handling models depending upon the interrupt routing model it has +chosen (as described in section :ref:`Secure Payload `). + +In the synchronous model, it should begin handling a Secure-EL1 interrupt after +receiving control from the SPD service at an entrypoint agreed upon during build +time or during the registration phase. Before handling the interrupt, the SP +should save any Secure-EL1 system register context which is needed for resuming +normal execution in the SP later e.g. ``SPSR_EL1``, ``ELR_EL1``. After handling +the interrupt, the SP could return control back to the exception level and +security state where the interrupt was originally taken from. The SP should use +an SMC32 or SMC64 to ask the SPD service to do this. + +In the asynchronous model, the Secure Payload is responsible for handling +non-secure and Secure-EL1 interrupts at the IRQ and FIQ vectors in its exception +vector table when ``PSTATE.I`` and ``PSTATE.F`` bits are 0. As described earlier, +when a non-secure interrupt is generated, the SP should coordinate with the SPD +service to pass control back to the non-secure state in the last known exception +level. This will allow the non-secure interrupt to be handled in the non-secure +state. + +Test secure payload behavior +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The TSPD hands control of a Secure-EL1 interrupt to the TSP at the +``tsp_sel1_intr_entry()``. The TSP handles the interrupt while ensuring that the +handover agreement described in Section `Test secure payload dispatcher +behavior`_ is maintained. It updates some statistics by calling +``tsp_update_sync_sel1_intr_stats()``. It then calls +``tsp_common_int_handler()`` which. + +#. Checks whether the interrupt is the secure physical timer interrupt. It + uses the platform API ``plat_ic_get_pending_interrupt_id()`` to get the + interrupt number. If it is not the secure physical timer interrupt, then + that means that a higher priority interrupt has preempted it. Invoke + ``tsp_handle_preemption()`` to handover control back to EL3 by issuing + an SMC with ``TSP_PREEMPTED`` as the function identifier. + +#. Handles the secure timer interrupt interrupt by acknowledging it using the + ``plat_ic_acknowledge_interrupt()`` platform API, calling + ``tsp_generic_timer_handler()`` to reprogram the secure physical generic + timer and calling the ``plat_ic_end_of_interrupt()`` platform API to signal + end of interrupt processing. + +The TSP passes control back to the TSPD by issuing an SMC64 with +``TSP_HANDLED_S_EL1_INTR`` as the function identifier. + +The TSP handles interrupts under the asynchronous model as follows. + +#. Secure-EL1 interrupts are handled by calling the ``tsp_common_int_handler()`` + function. The function has been described above. + +#. Non-secure interrupts are handled by calling the ``tsp_common_int_handler()`` + function which ends up invoking ``tsp_handle_preemption()`` and issuing an + SMC64 with ``TSP_PREEMPTED`` as the function identifier. Execution resumes at + the instruction that follows this SMC instruction when the TSPD hands control + to the TSP in response to an SMC with ``TSP_FID_RESUME`` as the function + identifier from the non-secure state (see section `Test secure payload + dispatcher non-secure interrupt handling`_). + +Other considerations +-------------------- + +Implication of preempted SMC on Non-Secure Software +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +A ``yielding`` SMC call to Secure payload can be preempted by a non-secure +interrupt and the execution can return to the non-secure world for handling +the interrupt (For details on ``yielding`` SMC refer `SMC calling convention`_). +In this case, the SMC call has not completed its execution and the execution +must return back to the secure payload to resume the preempted SMC call. +This can be achieved by issuing an SMC call which instructs to resume the +preempted SMC. + +A ``fast`` SMC cannot be preempted and hence this case will not happen for +a fast SMC call. + +In the Test Secure Payload implementation, ``TSP_FID_RESUME`` is designated +as the resume SMC FID. It is important to note that ``TSP_FID_RESUME`` is a +``yielding`` SMC which means it too can be be preempted. The typical non +secure software sequence for issuing a ``yielding`` SMC would look like this, +assuming ``P.STATE.I=0`` in the non secure state : + +.. code:: c + + int rc; + rc = smc(TSP_YIELD_SMC_FID, ...); /* Issue a Yielding SMC call */ + /* The pending non-secure interrupt is handled by the interrupt handler + and returns back here. */ + while (rc == SMC_PREEMPTED) { /* Check if the SMC call is preempted */ + rc = smc(TSP_FID_RESUME); /* Issue resume SMC call */ + } + +The ``TSP_YIELD_SMC_FID`` is any ``yielding`` SMC function identifier and the smc() +function invokes a SMC call with the required arguments. The pending non-secure +interrupt causes an IRQ exception and the IRQ handler registered at the +exception vector handles the non-secure interrupt and returns. The return value +from the SMC call is tested for ``SMC_PREEMPTED`` to check whether it is +preempted. If it is, then the resume SMC call ``TSP_FID_RESUME`` is issued. The +return value of the SMC call is tested again to check if it is preempted. +This is done in a loop till the SMC call succeeds or fails. If a ``yielding`` +SMC is preempted, until it is resumed using ``TSP_FID_RESUME`` SMC and +completed, the current TSPD prevents any other SMC call from re-entering +TSP by returning ``SMC_UNK`` error. + +-------------- + +*Copyright (c) 2014-2020, Arm Limited and Contributors. All rights reserved.* + +.. _SMC calling convention: https://developer.arm.com/docs/den0028/latest + +.. |Image 1| image:: ../resources/diagrams/sec-int-handling.png +.. |Image 2| image:: ../resources/diagrams/non-sec-int-handling.png diff --git a/arm-trusted-firmware/docs/design/psci-pd-tree.rst b/arm-trusted-firmware/docs/design/psci-pd-tree.rst new file mode 100644 index 0000000..56a6d6f --- /dev/null +++ b/arm-trusted-firmware/docs/design/psci-pd-tree.rst @@ -0,0 +1,304 @@ +PSCI Power Domain Tree Structure +================================ + +Requirements +------------ + +#. A platform must export the ``plat_get_aff_count()`` and + ``plat_get_aff_state()`` APIs to enable the generic PSCI code to + populate a tree that describes the hierarchy of power domains in the + system. This approach is inflexible because a change to the topology + requires a change in the code. + + It would be much simpler for the platform to describe its power domain tree + in a data structure. + +#. The generic PSCI code generates MPIDRs in order to populate the power domain + tree. It also uses an MPIDR to find a node in the tree. The assumption that + a platform will use exactly the same MPIDRs as generated by the generic PSCI + code is not scalable. The use of an MPIDR also restricts the number of + levels in the power domain tree to four. + + Therefore, there is a need to decouple allocation of MPIDRs from the + mechanism used to populate the power domain topology tree. + +#. The current arrangement of the power domain tree requires a binary search + over the sibling nodes at a particular level to find a specified power + domain node. During a power management operation, the tree is traversed from + a 'start' to an 'end' power level. The binary search is required to find the + node at each level. The natural way to perform this traversal is to + start from a leaf node and follow the parent node pointer to reach the end + level. + + Therefore, there is a need to define data structures that implement the tree in + a way which facilitates such a traversal. + +#. The attributes of a core power domain differ from the attributes of power + domains at higher levels. For example, only a core power domain can be identified + using an MPIDR. There is no requirement to perform state coordination while + performing a power management operation on the core power domain. + + Therefore, there is a need to implement the tree in a way which facilitates this + distinction between a leaf and non-leaf node and any associated + optimizations. + +-------------- + +Design +------ + +Describing a power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 1., the existing platform APIs +``plat_get_aff_count()`` and ``plat_get_aff_state()`` have been +removed. A platform must define an array of unsigned chars such that: + +#. The first entry in the array specifies the number of power domains at the + highest power level implemented in the platform. This caters for platforms + where the power domain tree does not have a single root node, for example, + the FVP has two cluster power domains at the highest level (1). + +#. Each subsequent entry corresponds to a power domain and contains the number + of power domains that are its direct children. + +#. The size of the array minus the first entry will be equal to the number of + non-leaf power domains. + +#. The value in each entry in the array is used to find the number of entries + to consider at the next level. The sum of the values (number of children) of + all the entries at a level specifies the number of entries in the array for + the next level. + +The following example power domain topology tree will be used to describe the +above text further. The leaf and non-leaf nodes in this tree have been numbered +separately. + +:: + + +-+ + |0| + +-+ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + / \ + +-+ +-+ + |1| |2| + +-+ +-+ + / \ / \ + / \ / \ + / \ / \ + / \ / \ + +-+ +-+ +-+ +-+ + |3| |4| |5| |6| + +-+ +-+ +-+ +-+ + +---+-----+ +----+----| +----+----+ +----+-----+-----+ + | | | | | | | | | | | | | + | | | | | | | | | | | | | + v v v v v v v v v v v v v + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + |0| |1| |2| |3| |4| |5| |6| |7| |8| |9| |10| |11| |12| + +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +-+ +--+ +--+ +--+ + +This tree is defined by the platform as the array described above as follows: + +.. code:: c + + #define PLAT_NUM_POWER_DOMAINS 20 + #define PLATFORM_CORE_COUNT 13 + #define PSCI_NUM_NON_CPU_PWR_DOMAINS \ + (PLAT_NUM_POWER_DOMAINS - PLATFORM_CORE_COUNT) + + unsigned char plat_power_domain_tree_desc[] = { 1, 2, 2, 2, 3, 3, 3, 4}; + +Removing assumptions about MPIDRs used in a platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 2., it is assumed that the platform assigns a +unique number (core index) between ``0`` and ``PLAT_CORE_COUNT - 1`` to each core +power domain. MPIDRs could be allocated in any manner and will not be used to +populate the tree. + +``plat_core_pos_by_mpidr(mpidr)`` will return the core index for the core +corresponding to the MPIDR. It will return an error (-1) if an MPIDR is passed +which is not allocated or corresponds to an absent core. The semantics of this +platform API have changed since it is required to validate the passed MPIDR. It +has been made a mandatory API as a result. + +Another mandatory API, ``plat_my_core_pos()`` has been added to return the core +index for the calling core. This API provides a more lightweight mechanism to get +the index since there is no need to validate the MPIDR of the calling core. + +The platform should assign the core indices (as illustrated in the diagram above) +such that, if the core nodes are numbered from left to right, then the index +for a core domain will be the same as the index returned by +``plat_core_pos_by_mpidr()`` or ``plat_my_core_pos()`` for that core. This +relationship allows the core nodes to be allocated in a separate array +(requirement 4.) during ``psci_setup()`` in such an order that the index of the +core in the array is the same as the return value from these APIs. + +Dealing with holes in MPIDR allocation +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For platforms where the number of allocated MPIDRs is equal to the number of +core power domains, for example, Juno and FVPs, the logic to convert an MPIDR to +a core index should remain unchanged. Both Juno and FVP use a simple collision +proof hash function to do this. + +It is possible that on some platforms, the allocation of MPIDRs is not +contiguous or certain cores have been disabled. This essentially means that the +MPIDRs have been sparsely allocated, that is, the size of the range of MPIDRs +used by the platform is not equal to the number of core power domains. + +The platform could adopt one of the following approaches to deal with this +scenario: + +#. Implement more complex logic to convert a valid MPIDR to a core index while + maintaining the relationship described earlier. This means that the power + domain tree descriptor will not describe any core power domains which are + disabled or absent. Entries will not be allocated in the tree for these + domains. + +#. Treat unallocated MPIDRs and disabled cores as absent but still describe them + in the power domain descriptor, that is, the number of core nodes described + is equal to the size of the range of MPIDRs allocated. This approach will + lead to memory wastage since entries will be allocated in the tree but will + allow use of a simpler logic to convert an MPIDR to a core index. + +Traversing through and distinguishing between core and non-core power domains +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To fulfill requirement 3 and 4, separate data structures have been defined +to represent leaf and non-leaf power domain nodes in the tree. + +.. code:: c + + /******************************************************************************* + * The following two data structures implement the power domain tree. The tree + * is used to track the state of all the nodes i.e. power domain instances + * described by the platform. The tree consists of nodes that describe CPU power + * domains i.e. leaf nodes and all other power domains which are parents of a + * CPU power domain i.e. non-leaf nodes. + ******************************************************************************/ + typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } non_cpu_pd_node_t; + + typedef struct cpu_pwr_domain_node { + u_register_t mpidr; + + /* Index of the parent power domain node */ + unsigned int parent_node; + + ----- + } cpu_pd_node_t; + +The power domain tree is implemented as a combination of the following data +structures. + +.. code:: c + + non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; + cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; + +Populating the power domain tree +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``populate_power_domain_tree()`` function in ``psci_setup.c`` implements the +algorithm to parse the power domain descriptor exported by the platform to +populate the two arrays. It is essentially a breadth-first-search. The nodes for +each level starting from the root are laid out one after another in the +``psci_non_cpu_pd_nodes`` and ``psci_cpu_pd_nodes`` arrays as follows: + +:: + + psci_non_cpu_pd_nodes -> [[Level 3 nodes][Level 2 nodes][Level 1 nodes]] + psci_cpu_pd_nodes -> [Level 0 nodes] + +For the example power domain tree illustrated above, the ``psci_cpu_pd_nodes`` +will be populated as follows. The value in each entry is the index of the parent +node. Other fields have been ignored for simplicity. + +:: + + +-------------+ ^ + CPU0 | 3 | | + +-------------+ | + CPU1 | 3 | | + +-------------+ | + CPU2 | 3 | | + +-------------+ | + CPU3 | 4 | | + +-------------+ | + CPU4 | 4 | | + +-------------+ | + CPU5 | 4 | | PLATFORM_CORE_COUNT + +-------------+ | + CPU6 | 5 | | + +-------------+ | + CPU7 | 5 | | + +-------------+ | + CPU8 | 5 | | + +-------------+ | + CPU9 | 6 | | + +-------------+ | + CPU10 | 6 | | + +-------------+ | + CPU11 | 6 | | + +-------------+ | + CPU12 | 6 | v + +-------------+ + +The ``psci_non_cpu_pd_nodes`` array will be populated as follows. The value in +each entry is the index of the parent node. + +:: + + +-------------+ ^ + PD0 | -1 | | + +-------------+ | + PD1 | 0 | | + +-------------+ | + PD2 | 0 | | + +-------------+ | + PD3 | 1 | | PLAT_NUM_POWER_DOMAINS - + +-------------+ | PLATFORM_CORE_COUNT + PD4 | 1 | | + +-------------+ | + PD5 | 2 | | + +-------------+ | + PD6 | 2 | | + +-------------+ v + +Each core can find its node in the ``psci_cpu_pd_nodes`` array using the +``plat_my_core_pos()`` function. When a core is turned on, the normal world +provides an MPIDR. The ``plat_core_pos_by_mpidr()`` function is used to validate +the MPIDR before using it to find the corresponding core node. The non-core power +domain nodes do not need to be identified. + +-------------- + +*Copyright (c) 2017-2018, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design/reset-design.rst b/arm-trusted-firmware/docs/design/reset-design.rst new file mode 100644 index 0000000..7b10c95 --- /dev/null +++ b/arm-trusted-firmware/docs/design/reset-design.rst @@ -0,0 +1,161 @@ +CPU Reset +========= + +This document describes the high-level design of the framework to handle CPU +resets in Trusted Firmware-A (TF-A). It also describes how the platform +integrator can tailor this code to the system configuration to some extent, +resulting in a simplified and more optimised boot flow. + +This document should be used in conjunction with the :ref:`Firmware Design` +document which provides greater implementation details around the reset code, +specifically for the cold boot path. + +General reset code flow +----------------------- + +The TF-A reset code is implemented in BL1 by default. The following high-level +diagram illustrates this: + +|Default reset code flow| + +This diagram shows the default, unoptimised reset flow. Depending on the system +configuration, some of these steps might be unnecessary. The following sections +guide the platform integrator by indicating which build options exclude which +steps, depending on the capability of the platform. + +.. note:: + If BL31 is used as the TF-A entry point instead of BL1, the diagram + above is still relevant, as all these operations will occur in BL31 in + this case. Please refer to section 6 "Using BL31 entrypoint as the reset + address" for more information. + +Programmable CPU reset address +------------------------------ + +By default, TF-A assumes that the CPU reset address is not programmable. +Therefore, all CPUs start at the same address (typically address 0) whenever +they reset. Further logic is then required to identify whether it is a cold or +warm boot to direct CPUs to the right execution path. + +If the reset vector address (reflected in the reset vector base address register +``RVBAR_EL3``) is programmable then it is possible to make each CPU start directly +at the right address, both on a cold and warm reset. Therefore, the boot type +detection can be skipped, resulting in the following boot flow: + +|Reset code flow with programmable reset address| + +To enable this boot flow, compile TF-A with ``PROGRAMMABLE_RESET_ADDRESS=1``. +This option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, the reset vector address is not programmable +so both ports use ``PROGRAMMABLE_RESET_ADDRESS=0``. + +Cold boot on a single CPU +------------------------- + +By default, TF-A assumes that several CPUs may be released out of reset. +Therefore, the cold boot code has to arbitrate access to hardware resources +shared amongst CPUs. This is done by nominating one of the CPUs as the primary, +which is responsible for initialising shared hardware and coordinating the boot +flow with the other CPUs. + +If the platform guarantees that only a single CPU will ever be brought up then +no arbitration is required. The notion of primary/secondary CPU itself no longer +applies. This results in the following boot flow: + +|Reset code flow with single CPU released out of reset| + +To enable this boot flow, compile TF-A with ``COLD_BOOT_SINGLE_CPU=1``. This +option only affects the TF-A reset image, which is BL1 by default or BL31 if +``RESET_TO_BL31=1``. + +On both the FVP and Juno platforms, although only one core is powered up by +default, there are platform-specific ways to release any number of cores out of +reset. Therefore, both platform ports use ``COLD_BOOT_SINGLE_CPU=0``. + +Programmable CPU reset address, Cold boot on a single CPU +--------------------------------------------------------- + +It is obviously possible to combine both optimisations on platforms that have +a programmable CPU reset address and which release a single CPU out of reset. +This results in the following boot flow: + + +|Reset code flow with programmable reset address and single CPU released out of reset| + +To enable this boot flow, compile TF-A with both ``COLD_BOOT_SINGLE_CPU=1`` +and ``PROGRAMMABLE_RESET_ADDRESS=1``. These options only affect the TF-A reset +image, which is BL1 by default or BL31 if ``RESET_TO_BL31=1``. + +Using BL31 entrypoint as the reset address +------------------------------------------ + +On some platforms the runtime firmware (BL3x images) for the application +processors are loaded by some firmware running on a secure system processor +on the SoC, rather than by BL1 and BL2 running on the primary application +processor. For this type of SoC it is desirable for the application processor +to always reset to BL31 which eliminates the need for BL1 and BL2. + +TF-A provides a build-time option ``RESET_TO_BL31`` that includes some additional +logic in the BL31 entry point to support this use case. + +In this configuration, the platform's Trusted Boot Firmware must ensure that +BL31 is loaded to its runtime address, which must match the CPU's ``RVBAR_EL3`` +reset vector base address, before the application processor is powered on. +Additionally, platform software is responsible for loading the other BL3x images +required and providing entry point information for them to BL31. Loading these +images might be done by the Trusted Boot Firmware or by platform code in BL31. + +Although the Arm FVP platform does not support programming the reset base +address dynamically at run-time, it is possible to set the initial value of the +``RVBAR_EL3`` register at start-up. This feature is provided on the Base FVP +only. + +It allows the Arm FVP port to support the ``RESET_TO_BL31`` configuration, in +which case the ``bl31.bin`` image must be loaded to its run address in Trusted +SRAM and all CPU reset vectors be changed from the default ``0x0`` to this run +address. See the :ref:`Arm Fixed Virtual Platforms (FVP)` for details of running +the FVP models in this way. + +Although technically it would be possible to program the reset base address with +the right support in the SCP firmware, this is currently not implemented so the +Juno port doesn't support the ``RESET_TO_BL31`` configuration. + +The ``RESET_TO_BL31`` configuration requires some additions and changes in the +BL31 functionality: + +Determination of boot path +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, BL31 uses the same reset framework and code as the one +described for BL1 above. Therefore, it is affected by the +``PROGRAMMABLE_RESET_ADDRESS`` and ``COLD_BOOT_SINGLE_CPU`` build options in the +same way. + +In the default, unoptimised BL31 reset flow, on a warm boot a CPU is directed +to the PSCI implementation via a platform defined mechanism. On a cold boot, +the platform must place any secondary CPUs into a safe state while the primary +CPU executes a modified BL31 initialization, as described below. + +Platform initialization +~~~~~~~~~~~~~~~~~~~~~~~ + +In this configuration, when the CPU resets to BL31 there are no parameters that +can be passed in registers by previous boot stages. Instead, the platform code +in BL31 needs to know, or be able to determine, the location of the BL32 (if +required) and BL33 images and provide this information in response to the +``bl31_plat_get_next_image_ep_info()`` function. + +Additionally, platform software is responsible for carrying out any security +initialisation, for example programming a TrustZone address space controller. +This might be done by the Trusted Boot Firmware or by platform code in BL31. + +-------------- + +*Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved.* + +.. |Default reset code flow| image:: ../resources/diagrams/default_reset_code.png +.. |Reset code flow with programmable reset address| image:: ../resources/diagrams/reset_code_no_boot_type_check.png +.. |Reset code flow with single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_cpu_check.png +.. |Reset code flow with programmable reset address and single CPU released out of reset| image:: ../resources/diagrams/reset_code_no_checks.png diff --git a/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst b/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst new file mode 100644 index 0000000..dd61b61 --- /dev/null +++ b/arm-trusted-firmware/docs/design/trusted-board-boot-build.rst @@ -0,0 +1,115 @@ +Building FIP images with support for Trusted Board Boot +======================================================= + +Trusted Board Boot primarily consists of the following two features: + +- Image Authentication, described in :ref:`Trusted Board Boot`, and +- Firmware Update, described in :ref:`Firmware Update (FWU)` + +The following steps should be followed to build FIP and (optionally) FWU_FIP +images with support for these features: + +#. Fulfill the dependencies of the ``mbedtls`` cryptographic and image parser + modules by checking out a recent version of the `mbed TLS Repository`_. It + is important to use a version that is compatible with TF-A and fixes any + known security vulnerabilities. See `mbed TLS Security Center`_ for more + information. See the :ref:`Prerequisites` document for the appropriate + version of mbed TLS to use. + + The ``drivers/auth/mbedtls/mbedtls_*.mk`` files contain the list of mbed TLS + source files the modules depend upon. + ``include/drivers/auth/mbedtls/mbedtls_config.h`` contains the configuration + options required to build the mbed TLS sources. + + Note that the mbed TLS library is licensed under the Apache version 2.0 + license. Using mbed TLS source code will affect the licensing of TF-A + binaries that are built using this library. + +#. To build the FIP image, ensure the following command line variables are set + while invoking ``make`` to build TF-A: + + - ``MBEDTLS_DIR=`` + - ``TRUSTED_BOARD_BOOT=1`` + - ``GENERATE_COT=1`` + + By default, this will use the Chain of Trust described in the TBBR-client + document. To select a different one, use the ``COT`` build option. + + In the case of Arm platforms, the location of the ROTPK hash must also be + specified at build time. The following locations are currently supported (see + ``ARM_ROTPK_LOCATION`` build option): + + - ``ARM_ROTPK_LOCATION=regs``: the ROTPK hash is obtained from the Trusted + root-key storage registers present in the platform. On Juno, these + registers are read-only. On FVP Base and Cortex models, the registers + are also read-only, but the value can be specified using the command line + option ``bp.trusted_key_storage.public_key`` when launching the model. + On Juno board, the default value corresponds to an ECDSA-SECP256R1 public + key hash, whose private part is not currently available. + + - ``ARM_ROTPK_LOCATION=devel_rsa``: use the default hash located in + ``plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin``. Enforce + generation of the new hash if ``ROT_KEY`` is specified. + + - ``ARM_ROTPK_LOCATION=devel_ecdsa``: use the default hash located in + ``plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin``. Enforce + generation of the new hash if ``ROT_KEY`` is specified. + + Example of command line using RSA development keys: + + .. code:: shell + + MBEDTLS_DIR= \ + make PLAT= TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + all fip + + The result of this build will be the bl1.bin and the fip.bin binaries. This + FIP will include the certificates corresponding to the selected Chain of + Trust. These certificates can also be found in the output build directory. + +#. The optional FWU_FIP contains any additional images to be loaded from + Non-Volatile storage during the :ref:`Firmware Update (FWU)` process. To build the + FWU_FIP, any FWU images required by the platform must be specified on the + command line. On Arm development platforms like Juno, these are: + + - NS_BL2U. The AP non-secure Firmware Updater image. + - SCP_BL2U. The SCP Firmware Update Configuration image. + + Example of Juno command line for generating both ``fwu`` and ``fwu_fip`` + targets using RSA development: + + :: + + MBEDTLS_DIR= \ + make PLAT=juno TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL33=/ \ + SCP_BL2=/ \ + SCP_BL2U=/ \ + NS_BL2U=/ \ + all fip fwu_fip + + .. note:: + The BL2U image will be built by default and added to the FWU_FIP. + The user may override this by adding ``BL2U=/`` + to the command line above. + + .. note:: + Building and installing the non-secure and SCP FWU images (NS_BL1U, + NS_BL2U and SCP_BL2U) is outside the scope of this document. + + The result of this build will be bl1.bin, fip.bin and fwu_fip.bin binaries. + Both the FIP and FWU_FIP will include the certificates corresponding to the + selected Chain of Trust. These certificates can also be found in the output + build directory. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _mbed TLS Repository: https://github.com/ARMmbed/mbedtls.git +.. _mbed TLS Security Center: https://tls.mbed.org/security diff --git a/arm-trusted-firmware/docs/design/trusted-board-boot.rst b/arm-trusted-firmware/docs/design/trusted-board-boot.rst new file mode 100644 index 0000000..46177d7 --- /dev/null +++ b/arm-trusted-firmware/docs/design/trusted-board-boot.rst @@ -0,0 +1,263 @@ +Trusted Board Boot +================== + +The Trusted Board Boot (TBB) feature prevents malicious firmware from running on +the platform by authenticating all firmware images up to and including the +normal world bootloader. It does this by establishing a Chain of Trust using +Public-Key-Cryptography Standards (PKCS). + +This document describes the design of Trusted Firmware-A (TF-A) TBB, which is an +implementation of the `Trusted Board Boot Requirements (TBBR)`_ specification, +Arm DEN0006D. It should be used in conjunction with the +:ref:`Firmware Update (FWU)` design document, which implements a specific aspect +of the TBBR. + +Chain of Trust +-------------- + +A Chain of Trust (CoT) starts with a set of implicitly trusted components. On +the Arm development platforms, these components are: + +- A SHA-256 hash of the Root of Trust Public Key (ROTPK). It is stored in the + trusted root-key storage registers. Alternatively, a development ROTPK might + be used and its hash embedded into the BL1 and BL2 images (only for + development purposes). + +- The BL1 image, on the assumption that it resides in ROM so cannot be + tampered with. + +The remaining components in the CoT are either certificates or boot loader +images. The certificates follow the `X.509 v3`_ standard. This standard +enables adding custom extensions to the certificates, which are used to store +essential information to establish the CoT. + +In the TBB CoT all certificates are self-signed. There is no need for a +Certificate Authority (CA) because the CoT is not established by verifying the +validity of a certificate's issuer but by the content of the certificate +extensions. To sign the certificates, different signature schemes are available, +please refer to the :ref:`Build Options` for more details. + +The certificates are categorised as "Key" and "Content" certificates. Key +certificates are used to verify public keys which have been used to sign content +certificates. Content certificates are used to store the hash of a boot loader +image. An image can be authenticated by calculating its hash and matching it +with the hash extracted from the content certificate. Various hash algorithms +are supported to calculate all hashes, please refer to the :ref:`Build Options` +for more details.. The public keys and hashes are included as non-standard +extension fields in the `X.509 v3`_ certificates. + +The keys used to establish the CoT are: + +- **Root of trust key** + + The private part of this key is used to sign the BL2 content certificate and + the trusted key certificate. The public part is the ROTPK. + +- **Trusted world key** + + The private part is used to sign the key certificates corresponding to the + secure world images (SCP_BL2, BL31 and BL32). The public part is stored in + one of the extension fields in the trusted world certificate. + +- **Non-trusted world key** + + The private part is used to sign the key certificate corresponding to the + non secure world image (BL33). The public part is stored in one of the + extension fields in the trusted world certificate. + +- **BL3X keys** + + For each of SCP_BL2, BL31, BL32 and BL33, the private part is used to + sign the content certificate for the BL3X image. The public part is stored + in one of the extension fields in the corresponding key certificate. + +The following images are included in the CoT: + +- BL1 +- BL2 +- SCP_BL2 (optional) +- BL31 +- BL33 +- BL32 (optional) + +The following certificates are used to authenticate the images. + +- **BL2 content certificate** + + It is self-signed with the private part of the ROT key. It contains a hash + of the BL2 image. + +- **Trusted key certificate** + + It is self-signed with the private part of the ROT key. It contains the + public part of the trusted world key and the public part of the non-trusted + world key. + +- **SCP_BL2 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the SCP_BL2 key. + +- **SCP_BL2 content certificate** + + It is self-signed with the SCP_BL2 key. It contains a hash of the SCP_BL2 + image. + +- **BL31 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL31 key. + +- **BL31 content certificate** + + It is self-signed with the BL31 key. It contains a hash of the BL31 image. + +- **BL32 key certificate** + + It is self-signed with the trusted world key. It contains the public part of + the BL32 key. + +- **BL32 content certificate** + + It is self-signed with the BL32 key. It contains a hash of the BL32 image. + +- **BL33 key certificate** + + It is self-signed with the non-trusted world key. It contains the public + part of the BL33 key. + +- **BL33 content certificate** + + It is self-signed with the BL33 key. It contains a hash of the BL33 image. + +The SCP_BL2 and BL32 certificates are optional, but they must be present if the +corresponding SCP_BL2 or BL32 images are present. + +Trusted Board Boot Sequence +--------------------------- + +The CoT is verified through the following sequence of steps. The system panics +if any of the steps fail. + +- BL1 loads and verifies the BL2 content certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If they match, the BL2 hash is read from the certificate. + + .. note:: + The matching operation is platform specific and is currently + unimplemented on the Arm development platforms. + +- BL1 loads the BL2 image. Its hash is calculated and compared with the hash + read from the certificate. Control is transferred to the BL2 image if all + the comparisons succeed. + +- BL2 loads and verifies the trusted key certificate. The issuer public key is + read from the verified certificate. A hash of that key is calculated and + compared with the hash of the ROTPK read from the trusted root-key storage + registers. If the comparison succeeds, BL2 reads and saves the trusted and + non-trusted world public keys from the verified certificate. + +The next two steps are executed for each of the SCP_BL2, BL31 & BL32 images. +The steps for the optional SCP_BL2 and BL32 images are skipped if these images +are not present. + +- BL2 loads and verifies the BL3x key certificate. The certificate signature + is verified using the trusted world public key. If the signature + verification succeeds, BL2 reads and saves the BL3x public key from the + certificate. + +- BL2 loads and verifies the BL3x content certificate. The signature is + verified using the BL3x public key. If the signature verification succeeds, + BL2 reads and saves the BL3x image hash from the certificate. + +The next two steps are executed only for the BL33 image. + +- BL2 loads and verifies the BL33 key certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 public key from the + certificate. + +- BL2 loads and verifies the BL33 content certificate. If the signature + verification succeeds, BL2 reads and saves the BL33 image hash from the + certificate. + +The next step is executed for all the boot loader images. + +- BL2 calculates the hash of each image. It compares it with the hash obtained + from the corresponding content certificate. The image authentication succeeds + if the hashes match. + +The Trusted Board Boot implementation spans both generic and platform-specific +BL1 and BL2 code, and in tool code on the host build machine. The feature is +enabled through use of specific build flags as described in +:ref:`Build Options`. + +On the host machine, a tool generates the certificates, which are included in +the FIP along with the boot loader images. These certificates are loaded in +Trusted SRAM using the IO storage framework. They are then verified by an +Authentication module included in TF-A. + +The mechanism used for generating the FIP and the Authentication module are +described in the following sections. + +Authentication Framework +------------------------ + +The authentication framework included in TF-A provides support to implement +the desired trusted boot sequence. Arm platforms use this framework to +implement the boot requirements specified in the +`Trusted Board Boot Requirements (TBBR)`_ document. + +More information about the authentication framework can be found in the +:ref:`Authentication Framework & Chain of Trust` document. + +Certificate Generation Tool +--------------------------- + +The ``cert_create`` tool is built and runs on the host machine as part of the +TF-A build process when ``GENERATE_COT=1``. It takes the boot loader images +and keys as inputs (keys must be in PEM format) and generates the +certificates (in DER format) required to establish the CoT. New keys can be +generated by the tool in case they are not provided. The certificates are then +passed as inputs to the ``fiptool`` utility for creating the FIP. + +The certificates are also stored individually in the output build directory. + +The tool resides in the ``tools/cert_create`` directory. It uses the OpenSSL SSL +library version to generate the X.509 certificates. The specific version of the +library that is required is given in the :ref:`Prerequisites` document. + +Instructions for building and using the tool can be found at +:ref:`tools_build_cert_create`. + +Authenticated Encryption Framework +---------------------------------- + +The authenticated encryption framework included in TF-A provides support to +implement the optional firmware encryption feature. This feature can be +optionally enabled on platforms to implement the optional requirement: +R060_TBBR_FUNCTION as specified in the `Trusted Board Boot Requirements (TBBR)`_ +document. + +Firmware Encryption Tool +------------------------ + +The ``encrypt_fw`` tool is built and runs on the host machine as part of the +TF-A build process when ``DECRYPTION_SUPPORT != none``. It takes the plain +firmware image as input and generates the encrypted firmware image which can +then be passed as input to the ``fiptool`` utility for creating the FIP. + +The encrypted firmwares are also stored individually in the output build +directory. + +The tool resides in the ``tools/encrypt_fw`` directory. It uses OpenSSL SSL +library version 1.0.1 or later to do authenticated encryption operation. +Instructions for building and using the tool can be found in the +:ref:`tools_build_enctool`. + +-------------- + +*Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved.* + +.. _X.509 v3: https://tools.ietf.org/rfc/rfc5280.txt +.. _Trusted Board Boot Requirements (TBBR): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a diff --git a/arm-trusted-firmware/docs/design_documents/cmake_framework.rst b/arm-trusted-firmware/docs/design_documents/cmake_framework.rst new file mode 100644 index 0000000..d88942e --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/cmake_framework.rst @@ -0,0 +1,165 @@ +TF-A CMake buildsystem +====================== + +:Author: Balint Dobszay +:Organization: Arm Limited +:Contact: Balint Dobszay +:Status: Accepted + +.. contents:: Table of Contents + +Abstract +-------- +This document presents a proposal for a new buildsystem for TF-A using CMake, +and as part of this a reusable CMake framework for embedded projects. For a +summary about the proposal, please see the `Phabricator wiki page +`_. As +mentioned there, the proposal consists of two phases. The subject of this +document is the first phase only. + +Introduction +------------ +The current Makefile based buildsystem of TF-A has become complicated and hard +to maintain, there is a need for a new, more flexible solution. The proposal is +to use CMake language for the new buildsystem. The main reasons of this decision +are the following: + +* It is a well-established, mature tool, widely accepted by open-source + projects. +* TF-M is already using CMake, reducing fragmentation for tf.org projects can be + beneficial. +* CMake has various advantages over Make, e.g.: + + * Host and target system agnostic project. + * CMake project is scalable, supports project modularization. + * Supports software integration. + * Out-of-the-box support for integration with several tools (e.g. project + generation for various IDEs, integration with cppcheck, etc). + +Of course there are drawbacks too: + +* Language is problematic (e.g. variable scope). +* Not embedded approach. + +To overcome these and other problems, we need to create workarounds for some +tasks, wrap CMake functions, etc. Since this functionality can be useful in +other embedded projects too, it is beneficial to collect the new code into a +reusable framework and store this in a separate repository. The following +diagram provides an overview of the framework structure: + +|Framework structure| + +Main features +------------- + +Structured configuration description +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +In the current Makefile system the build configuration description, validation, +processing, and the target creation, source file description are mixed and +spread across several files. One of the goals of the framework is to organize +this. + +The framework provides a solution to describe the input build parameters, flags, +macros, etc. in a structured way. It contains two utilities for this purpose: + +* Map: simple key-value pair implementation. +* Group: collection of related maps. + +The related parameters shall be packed into a group (or "setting group"). The +setting groups shall be defined and filled with content in config files. +Currently the config files are created and edited manually, but later a +configuration management tool (e.g. Kconfig) shall be used to generate these +files. Therefore, the framework does not contain parameter validation and +conflict checking, these shall be handled by the configuration tool. + +Target description +^^^^^^^^^^^^^^^^^^ +The framework provides an API called STGT ('simple target') to describe the +targets, i.e. what is the build output, what source files are used, what +libraries are linked, etc. The API wraps the CMake target functions, and also +extends the built-in functionality, it can use the setting groups described in +the previous section. A group can be applied onto a target, i.e. a collection of +macros, flags, etc. can be applied onto the given output executable/library. +This provides a more granular way than the current Makefile system where most of +these are global and applied onto each target. + +Compiler abstraction +^^^^^^^^^^^^^^^^^^^^ +Apart from the built-in CMake usage of the compiler, there are some common tasks +that CMake does not solve (e.g. preprocessing a file). For these tasks the +framework uses wrapper functions instead of direct calls to the compiler. This +way it is not tied to one specific compiler. + +External tools +^^^^^^^^^^^^^^ +In the TF-A buildsystem some external tools are used, e.g. fiptool for image +generation or dtc for device tree compilation. These tools have to be found +and/or built by the framework. For this, the CMake find_package functionality is +used, any other necessary tools can be added later. + +Workflow +-------- +The following diagram demonstrates the development workflow using the framework: + +|Framework workflow| + +The process can be split into two main phases: + +In the provisioning phase, first we have to obtain the necessary resources, i.e. +clone the code repository and other dependencies. Next we have to do the +configuration, preferably using a config tool like KConfig. + +In the development phase first we run CMake, which will generate the buildsystem +using the selected generator backend (currently only the Makefile generator is +supported). After this we run the selected build tool which in turn calls the +compiler, linker, packaging tool, etc. Finally we can run and debug the output +executables. + +Usually during development only the steps in this second phase have to be +repeated, while the provisioning phase needs to be done only once (or rarely). + +Example +------- +This is a short example for the basic framework usage. + +First, we create a setting group called *mem_conf* and fill it with several +parameters. It is worth noting the difference between *CONFIG* and *DEFINE* +types: the former is only a CMake domain option, the latter is only a C language +macro. + +Next, we create a target called *fw1* and add the *mem_conf* setting group to +it. This means that all source and header files used by the target will have all +the parameters declared in the setting group. Then we set the target type to +executable, and add some source files. Since the target has the parameters from +the settings group, we can use it for conditionally adding source files. E.g. +*dram_controller.c* will only be added if MEM_TYPE equals dram. + +.. code-block:: cmake + + group_new(NAME mem_conf) + group_add(NAME mem_conf TYPE DEFINE KEY MEM_SIZE VAL 1024) + group_add(NAME mem_conf TYPE CONFIG DEFINE KEY MEM_TYPE VAL dram) + group_add(NAME mem_conf TYPE CFLAG KEY -Os) + + stgt_create(NAME fw1) + stgt_add_setting(NAME fw1 GROUPS mem_conf) + stgt_set_target(NAME fw1 TYPE exe) + + stgt_add_src(NAME fw1 SRC + ${CMAKE_SOURCE_DIR}/main.c + ) + + stgt_add_src_cond(NAME fw1 KEY MEM_TYPE VAL dram SRC + ${CMAKE_SOURCE_DIR}/dram_controller.c + ) + +.. |Framework structure| image:: + ../resources/diagrams/cmake_framework_structure.png + :width: 75 % + +.. |Framework workflow| image:: + ../resources/diagrams/cmake_framework_workflow.png + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst b/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst new file mode 100644 index 0000000..59f9d4e --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst @@ -0,0 +1,197 @@ +Enhance Context Management library for EL3 firmware +=================================================== + +:Authors: Soby Mathew & Zelalem Aweke +:Organization: Arm Limited +:Contact: Soby Mathew & Zelalem Aweke +:Status: RFC + +.. contents:: Table of Contents + +Introduction +------------ +The context management library in TF-A provides the basic CPU context +initialization and management routines for use by different components +in EL3 firmware. The original design of the library was done keeping in +mind the 2 world switch and hence this design pattern has been extended to +keep up with growing requirements of EL3 firmware. With the introduction +of a new Realm world and a separate Root world for EL3 firmware, it is clear +that this library needs to be refactored to cater for future enhancements and +reduce chances of introducing error in code. This also aligns with the overall +goal of reducing EL3 firmware complexity and footprint. + +It is expected that the suggestions below could have legacy implications and +hence we are mainly targeting SPM/RMM based systems. It is expected that these +legacy issues will need to be sorted out as part of implementation on a case +by case basis. + +Design Principles +----------------- +The below section lays down the design principles for re-factoring the context +management library : + +(1) **Decentralized model for context mgmt** + + Both the Secure and Realm worlds have associated dispatcher component in + EL3 firmware to allow management of their respective worlds. Allowing the + dispatcher to own the context for their respective world and moving away + from a centralized policy management by context management library will + remove the world differentiation code in the library. This also means that + the library will not be responsible for CPU feature enablement for + Secure and Realm worlds. See point 3 and 4 for more details. + + The Non Secure world does not have a dispatcher component and hence EL3 + firmware (BL31)/context management library needs to have routines to help + initialize the Non Secure world context. + +(2) **EL3 should only initialize immediate used lower EL** + + Due to the way TF-A evolved, from EL3 interacting with an S-EL1 payload to + SPM in S-EL2, there is some code initializing S-EL1 registers which is + probably redundant when SPM is present in S-EL2. As a principle, EL3 + firmware should only initialize the next immediate lower EL in use. + If EL2 needs to be skipped and is not to be used at runtime, then + EL3 can do the bare minimal EL2 init and init EL1 to prepare for EL3 exit. + It is expected that this skip EL2 configuration is only needed for NS + world to support legacy Android deployments. It is worth removing this + `skip EL2 for Non Secure` config support if this is no longer used. + +(3) **Maintain EL3 sysregs which affect lower EL within CPU context** + + The CPU context contains some EL3 sysregs and gets applied on a per-world + basis (eg: cptr_el3, scr_el3, zcr_el3 is part of the context + because different settings need to be applied between each world). + But this design pattern is not enforced in TF-A. It is possible to directly + modify EL3 sysreg dynamically during the transition between NS and Secure + worlds. Having multiple ways of manipulating EL3 sysregs for different + values between the worlds is flaky and error prone. The proposal is to + enforce the rule that any EL3 sysreg which can be different between worlds + is maintained in the CPU Context. Once the context is initialized the + EL3 sysreg values corresponding to the world being entered will be restored. + +(4) **Allow more flexibility for Dispatchers to select feature set to save and restore** + + The current functions for EL2 CPU context save and restore is a single + function which takes care of saving and restoring all the registers for + EL2. This method is inflexible and it does not allow to dynamically detect + CPU features to select registers to save and restore. It also assumes that + both Realm and Secure world will have the same feature set enabled from + EL3 at runtime and makes it hard to enable different features for each + world. The framework should cater for selective save and restore of CPU + registers which can be controlled by the dispatcher. + + For the implementation, this could mean that there is a separate assembly + save and restore routine corresponding to Arch feature. The memory allocation + within the CPU Context for each set of registers will be controlled by a + FEAT_xxx build option. It is a valid configuration to have + context memory allocated but not used at runtime based on feature detection + at runtime or the platform owner has decided not to enable the feature + for the particular world. + +Context Allocation and Initialization +------------------------------------- + +|context_mgmt_abs| + +.. |context_mgmt_abs| image:: + ../resources/diagrams/context_management_abs.png + +The above figure shows how the CPU context is allocated within TF-A. The +allocation for Secure and Realm world is by the respective dispatcher. In the case +of NS world, the context is allocated by the PSCI lib. This scheme allows TF-A +to be built in various configurations (with or without Secure/Realm worlds) and +will result in optimal memory footprint. The Secure and Realm world contexts are +initialized by invoking context management library APIs which then initialize +each world based on conditional evaluation of the security state of the +context. The proposal here is to move the conditional initialization +of context for Secure and Realm worlds to their respective dispatchers and +have the library do only the common init needed. The library can export +helpers to initialize registers corresponding to certain features but +should not try to do different initialization between the worlds. The library +can also export helpers for initialization of NS CPU Context since there is no +dispatcher for that world. + +This implies that any world specific code in context mgmt lib should now be +migrated to the respective "owners". To maintain compatibility with legacy, the +current functions can be retained in the lib and perhaps define new ones for +use by SPMD and RMMD. The details of this can be worked out during +implementation. + +Introducing Root Context +------------------------ +Till now, we have been ignoring the fact that Root world (or EL3) itself could +have some settings which are distinct from NS/S/Realm worlds. In this case, +Root world itself would need to maintain some sysregs settings for its own +execution and would need to use sysregs of lower EL (eg: PAuth, pmcr) to enable +some functionalities in EL3. The current sequence for context save and restore +in TF-A is as given below: + +|context_mgmt_existing| + +.. |context_mgmt_existing| image:: + ../resources/diagrams/context_mgmt_existing.png + +Note1: The EL3 CPU context is not a homogenous collection of EL3 sysregs but +a collection of EL3 and some other lower EL registers. The save and restore +is also not done homogenously but based on the objective of using the +particular register. + +Note2: The EL1 context save and restore can possibly be removed when switching +to S-EL2 as SPM can take care of saving the incoming NS EL1 context. + +It can be seen that the EL3 sysreg values applied while the execution is in Root +world corresponds to the world it came from (eg: if entering EL3 from NS world, +the sysregs correspond to the values in NS context). There is a case that EL3 +itself may have some settings to apply for various reasons. A good example for +this is the cptr_el3 regsiter. Although FPU traps need to be disabled for +Non Secure, Secure and Realm worlds, the EL3 execution itself may keep the trap +enabled for the sake of robustness. Another example is, if the MTE feature +is enabled for a particular world, this feature will be enabled for Root world +as well when entering EL3 from that world. The firmware at EL3 may not +be expecting this feature to be enabled and may cause unwanted side-effects +which could be problematic. Thus it would be more robust if Root world is not +subject to EL3 sysreg values from other worlds but maintains its own values +which is stable and predictable throughout root world execution. + +There is also the case that when EL3 would like to make use of some +Architectural feature(s) or do some security hardening, it might need +programming of some lower EL sysregs. For example, if EL3 needs to make +use of Pointer Authentication (PAuth) feature, it needs to program +its own PAuth Keys during execution at EL3. Hence EL3 needs its +own copy of PAuth registers which needs to be restored on every +entry to EL3. A similar case can be made for DIT bit in PSTATE, +or use of SP_EL0 for C Runtime Stack at EL3. + +The proposal here is to maintain a separate root world CPU context +which gets applied for Root world execution. This is not the full +CPU_Context, but subset of EL3 sysregs (`el3_sysreg`) and lower EL +sysregs (`root_exc_context`) used by EL3. The save and restore +sequence for this Root context would need to be done in +an optimal way. The `el3_sysreg` does not need to be saved +on EL3 Exit and possibly only some registers in `root_exc_context` +of Root world context would need to be saved on EL3 exit (eg: SP_EL0). + +The new sequence for world switch including Root world context would +be as given below : + +|context_mgmt_proposed| + +.. |context_mgmt_proposed| image:: + ../resources/diagrams/context_mgmt_proposed.png + +Having this framework in place will allow Root world to make use of lower EL +registers easily for its own purposes and also have a fixed EL3 sysreg setting +which is not affected by the settings of other worlds. This will unify the +Root world register usage pattern for its own execution and remove some +of the adhoc usages in code. + +Conclusion +---------- +Of all the proposals, the introduction of Root world context would likely need +further prototyping to confirm the design and we will need to measure the +performance and memory impact of this change. Other changes are incremental +improvements which are thought to have negligible impact on EL3 performance. + +-------------- + +*Copyright (c) 2022, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/index.rst b/arm-trusted-firmware/docs/design_documents/index.rst new file mode 100644 index 0000000..257a510 --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/index.rst @@ -0,0 +1,15 @@ +Design Documents +================ + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + cmake_framework + context_mgmt_rework + measured_boot_poc + +-------------- + +*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst b/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst new file mode 100644 index 0000000..3ae539b --- /dev/null +++ b/arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst @@ -0,0 +1,507 @@ +Interaction between Measured Boot and an fTPM (PoC) +=================================================== + +Measured Boot is the process of cryptographically measuring the code and +critical data used at boot time, for example using a TPM, so that the +security state can be attested later. + +The current implementation of the driver included in Trusted Firmware-A +(TF-A) stores the measurements into a `TGC event log`_ in secure +memory. No other means of recording measurements (such as a discrete TPM) is +supported right now. + +The driver also provides mechanisms to pass the Event Log to normal world if +needed. + +This manual provides instructions to build a proof of concept (PoC) with the +sole intention of showing how Measured Boot can be used in conjunction with +a firmware TPM (fTPM) service implemented on top of OP-TEE. + +.. note:: + The instructions given in this document are meant to be used to build + a PoC to show how Measured Boot on TF-A can interact with a third + party (f)TPM service and they try to be as general as possible. Different + platforms might have different needs and configurations (e.g. different + SHA algorithms) and they might also use different types of TPM services + (or even a different type of service to provide the attestation) + and therefore the instuctions given here might not apply in such scenarios. + +Components +~~~~~~~~~~ + +The PoC is built on top of the `OP-TEE Toolkit`_, which has support to build +TF-A with support for Measured Boot enabled (and run it on a Foundation Model) +since commit cf56848. + +The aforementioned toolkit builds a set of images that contain all the components +needed to test that the Event Log was properly created. One of these images will +contain a third party fTPM service which in turn will be used to process the +Event Log. + +The reason to choose OP-TEE Toolkit to build our PoC around it is mostly +for convenience. As the fTPM service used is an OP-TEE TA, it was easy to add +build support for it to the toolkit and then build the PoC around it. + +The most relevant components installed in the image that are closely related to +Measured Boot/fTPM functionality are: + + - **OP-TEE**: As stated earlier, the fTPM service used in this PoC is built as an + OP-TEE TA and therefore we need to include the OP-TEE OS image. + Support to interfacing with Measured Boot was added to version 3.9.0 of + OP-TEE by implementing the ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` syscall, which + allows the former to pass a copy of the Event Log to any TA requesting it. + OP-TEE knows the location of the Event Log by reading the DTB bindings + received from TF-A. Visit :ref:`DTB binding for Event Log properties` + for more details on this. + + - **fTPM Service**: We use a third party fTPM service in order to validate + the Measured Boot functionality. The chosen fTPM service is a sample + implementation for Aarch32 architecture included on the `ms-tpm-20-ref`_ + reference implementation from Microsoft. The service was updated in order + to extend the Measured Boot Event Log at boot up and it uses the + aforementioned ``PTA_SYSTEM_GET_TPM_EVENT_LOG`` call to retrieve a copy + of the former. + + .. note:: + Arm does not provide an fTPM implementation. The fTPM service used here + is a third party one which has been updated to support Measured Boot + service as provided by TF-A. As such, it is beyond the scope of this + manual to test and verify the correctness of the output generated by the + fTPM service. + + - **TPM Kernel module**: In order to interact with the fTPM service, we need + a kernel module to forward the request from user space to the secure world. + + - `tpm2-tools`_: This is a set of tools that allow to interact with the + fTPM service. We use this in order to read the PCRs with the measurements. + +Building the PoC for the Arm FVP platform +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +As mentioned before, this PoC is based on the OP-TEE Toolkit with some +extensions to enable Measured Boot and an fTPM service. Therefore, we can rely +on the instructions to build the original OP-TEE Toolkit. As a general rule, +the following steps should suffice: + +(1) Start by following the `Get and build the solution`_ instructions to build + the OP-TEE toolkit. On step 3, you need to get the manifest for FVP + platform from the main branch: + + .. code:: shell + + $ repo init -u https://github.com/OP-TEE/manifest.git -m fvp.xml + + Then proceed synching the repos as stated in step 3. Continue following + the instructions and stop before step 5. + +(2) Next you should obtain the `Armv8-A Foundation Platform (For Linux Hosts Only)`_. + The binary should be untar'ed to the root of the repo tree, i.e., like + this: ``/Foundation_Platformpkg``. In the end, after cloning + all source code, getting the toolchains and "installing" + Foundation_Platformpkg, you should have a folder structure that looks like + this: + + .. code:: shell + + $ ls -la + total 80 + drwxrwxr-x 20 tf-a_user tf-a_user 4096 Jul 1 12:16 . + drwxr-xr-x 23 tf-a_user tf-a_user 4096 Jul 1 10:40 .. + drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 10:45 build + drwxrwxr-x 16 tf-a_user tf-a_user 4096 Jul 1 12:16 buildroot + drwxrwxr-x 51 tf-a_user tf-a_user 4096 Jul 1 10:45 edk2 + drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 12:14 edk2-platforms + drwxr-xr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:52 Foundation_Platformpkg + drwxrwxr-x 17 tf-a_user tf-a_user 4096 Jul 2 10:40 grub + drwxrwxr-x 25 tf-a_user tf-a_user 4096 Jul 2 10:39 linux + drwxrwxr-x 15 tf-a_user tf-a_user 4096 Jul 1 10:45 mbedtls + drwxrwxr-x 6 tf-a_user tf-a_user 4096 Jul 1 10:45 ms-tpm-20-ref + drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_client + drwxrwxr-x 10 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_examples + drwxrwxr-x 12 tf-a_user tf-a_user 4096 Jul 1 12:13 optee_os + drwxrwxr-x 8 tf-a_user tf-a_user 4096 Jul 1 10:45 optee_test + drwxrwxr-x 7 tf-a_user tf-a_user 4096 Jul 1 10:45 .repo + drwxrwxr-x 4 tf-a_user tf-a_user 4096 Jul 1 12:12 toolchains + drwxrwxr-x 21 tf-a_user tf-a_user 4096 Jul 1 12:15 trusted-firmware-a + +(3) Now enter into ``ms-tpm-20-ref`` and get its dependencies: + + .. code:: shell + + $ cd ms-tpm-20-ref + $ git submodule init + $ git submodule update + Submodule path 'external/wolfssl': checked out '9c87f979a7f1d3a6d786b260653d566c1d31a1c4' + +(4) Now, you should be able to continue with step 5 in "`Get and build the solution`_" + instructions. In order to enable support for Measured Boot, you need to + set the ``MEASURED_BOOT`` build option: + + .. code:: shell + + $ MEASURED_BOOT=y make -j `nproc` + + .. note:: + The build process will likely take a long time. It is strongly recommended to + pass the ``-j`` option to make to run the process faster. + + After this step, you should be ready to run the image. + +Running and using the PoC on the Armv8-A Foundation AEM FVP +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +With everything built, you can now run the image: + +.. code:: shell + + $ make run-only + +.. note:: + Using ``make run`` will build and run the image and it can be used instead + of simply ``make``. However, once the image is built, it is recommended to + use ``make run-only`` to avoid re-running all the building rules, which + would take time. + +When FVP is launched, two terminal windows will appear. ``FVP terminal_0`` +is the userspace terminal whereas ``FVP terminal_1`` is the counterpart for +the secure world (where TAs will print their logs, for instance). + +Log into the image shell with user ``root``, no password will be required. +Then we can issue the ``ftpm`` command, which is an alias that + +(1) loads the ftpm kernel module and + +(2) calls ``tpm2_pcrread``, which will access the fTPM service to read the + PCRs. + +When loading the ftpm kernel module, the fTPM TA is loaded into the secure +world. This TA then requests a copy of the Event Log generated during the +booting process so it can retrieve all the entries on the log and record them +first thing. + +.. note:: + For this PoC, nothing loaded after BL33 and NT_FW_CONFIG is recorded + in the Event Log. + +The secure world terminal should show the debug logs for the fTPM service, +including all the measurements available in the Event Log as they are being +processed: + +.. code:: shell + + M/TA: Preparing to extend the following TPM Event Log: + M/TA: TCG_EfiSpecIDEvent: + M/TA: PCRIndex : 0 + M/TA: EventType : 3 + M/TA: Digest : 00 + M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: : 00 00 00 + M/TA: EventSize : 33 + M/TA: Signature : Spec ID Event03 + M/TA: PlatformClass : 0 + M/TA: SpecVersion : 2.0.2 + M/TA: UintnSize : 1 + M/TA: NumberOfAlgorithms : 1 + M/TA: DigestSizes : + M/TA: #0 AlgorithmId : SHA256 + M/TA: DigestSize : 32 + M/TA: VendorInfoSize : 0 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 3 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + M/TA: EventSize : 17 + M/TA: Signature : StartupLocality + M/TA: StartupLocality : 0 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 + M/TA: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 + M/TA: EventSize : 5 + M/TA: Event : BL_2 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 + M/TA: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c + M/TA: EventSize : 6 + M/TA: Event : BL_31 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 + M/TA: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 + M/TA: EventSize : 10 + M/TA: Event : HW_CONFIG + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a + M/TA: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 + M/TA: EventSize : 14 + M/TA: Event : SOC_FW_CONFIG + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 + M/TA: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 + M/TA: EventSize : 6 + M/TA: Event : BL_32 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e + M/TA: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 + M/TA: EventSize : 18 + M/TA: Event : BL32_EXTRA1_IMAGE + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 + M/TA: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 + M/TA: EventSize : 6 + M/TA: Event : BL_33 + M/TA: PCR_Event2: + M/TA: PCRIndex : 0 + M/TA: EventType : 1 + M/TA: Digests Count : 1 + M/TA: #0 AlgorithmId : SHA256 + M/TA: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 + M/TA: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a + M/TA: EventSize : 13 + M/TA: Event : NT_FW_CONFIG + +These logs correspond to the measurements stored by TF-A during the measured +boot process and therefore, they should match the logs dumped by the former +during the boot up process. These can be seen on the terminal_0: + +.. code:: shell + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v2.5(release):v2.5 + NOTICE: BL1: Built : 10:41:20, Jul 2 2021 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v2.5(release):v2.5 + NOTICE: BL2: Built : 10:41:20, Jul 2 2021 + NOTICE: TCG_EfiSpecIDEvent: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 3 + NOTICE: Digest : 00 + NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: : 00 00 00 + NOTICE: EventSize : 33 + NOTICE: Signature : Spec ID Event03 + NOTICE: PlatformClass : 0 + NOTICE: SpecVersion : 2.0.2 + NOTICE: UintnSize : 1 + NOTICE: NumberOfAlgorithms : 1 + NOTICE: DigestSizes : + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: DigestSize : 32 + NOTICE: VendorInfoSize : 0 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 3 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + NOTICE: EventSize : 17 + NOTICE: Signature : StartupLocality + NOTICE: StartupLocality : 0 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 58 26 32 6e 64 45 64 da 45 de 35 db 96 fd ed 63 + NOTICE: : 2a 6a d4 0d aa 94 b0 b1 55 e4 72 e7 1f 0a e0 d5 + NOTICE: EventSize : 5 + NOTICE: Event : BL_2 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : cf f9 7d a3 5c 73 ac cb 7b a0 25 80 6a 6e 50 a5 + NOTICE: : 6b 2e d2 8c c9 36 92 7d 46 c5 b9 c3 a4 6c 51 7c + NOTICE: EventSize : 6 + NOTICE: Event : BL_31 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 23 b0 a3 5d 54 d9 43 1a 5c b9 89 63 1c da 06 c2 + NOTICE: : e5 de e7 7e 99 17 52 12 7d f7 45 ca 4f 4a 39 c0 + NOTICE: EventSize : 10 + NOTICE: Event : HW_CONFIG + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 4e e4 8e 5a e6 50 ed e0 b5 a3 54 8a 1f d6 0e 8a + NOTICE: : ea 0e 71 75 0e a4 3f 82 76 ce af cd 7c b0 91 e0 + NOTICE: EventSize : 14 + NOTICE: Event : SOC_FW_CONFIG + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 01 b0 80 47 a1 ce 86 cd df 89 d2 1f 2e fc 6c 22 + NOTICE: : f8 19 ec 6e 1e ec 73 ba 5a be d0 96 e3 5f 6d 75 + NOTICE: EventSize : 6 + NOTICE: Event : BL_32 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 5d c6 ef 35 5a 90 81 b4 37 e6 3b 52 da 92 ab 8e + NOTICE: : d9 6e 93 98 2d 40 87 96 1b 5a a7 ee f1 f4 40 63 + NOTICE: EventSize : 18 + NOTICE: Event : BL32_EXTRA1_IMAGE + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 39 b7 13 b9 93 db 32 2f 1b 48 30 eb 2c f2 5c 25 + NOTICE: : 00 0f 38 dc 8e c8 02 cd 79 f2 48 d2 2c 25 ab e2 + NOTICE: EventSize : 6 + NOTICE: Event : BL_33 + NOTICE: PCR_Event2: + NOTICE: PCRIndex : 0 + NOTICE: EventType : 1 + NOTICE: Digests Count : 1 + NOTICE: #0 AlgorithmId : SHA256 + NOTICE: Digest : 25 10 60 5d d4 bc 9d 82 7a 16 9f 8a cc 47 95 a6 + NOTICE: : fd ca a0 c1 2b c9 99 8f 51 20 ff c6 ed 74 68 5a + NOTICE: EventSize : 13 + NOTICE: Event : NT_FW_CONFIG + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v2.5(release):v2.5 + NOTICE: BL31: Built : 10:41:20, Jul 2 2021 + +Following up with the fTPM startup process, we can see that all the +measurements in the Event Log are extended and recorded in the appropriate PCR: + +.. code:: shell + + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: TPM2_PCR_EXTEND_COMMAND returned value: + M/TA: ret_tag = 0x8002, size = 0x00000013, rc = 0x00000000 + M/TA: 9 Event logs processed + +After the fTPM TA is loaded, the call to ``insmod`` issued by the ``ftpm`` +alias to load the ftpm kernel module returns, and then the TPM PCRs are read +by means of ``tpm_pcrread`` command. Note that we are only interested in the +SHA256 logs here, as this is the algorithm we used on TF-A for the measurements +(see the field ``AlgorithmId`` on the logs above): + +.. code:: shell + + sha256: + 0 : 0xA6EB3A7417B8CFA9EBA2E7C22AD5A4C03CDB8F3FBDD7667F9C3EF2EA285A8C9F + 1 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 2 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 3 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 4 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 5 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 6 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 7 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 8 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 9 : 0x0000000000000000000000000000000000000000000000000000000000000000 + 10: 0x0000000000000000000000000000000000000000000000000000000000000000 + 11: 0x0000000000000000000000000000000000000000000000000000000000000000 + 12: 0x0000000000000000000000000000000000000000000000000000000000000000 + 13: 0x0000000000000000000000000000000000000000000000000000000000000000 + 14: 0x0000000000000000000000000000000000000000000000000000000000000000 + 15: 0x0000000000000000000000000000000000000000000000000000000000000000 + 16: 0x0000000000000000000000000000000000000000000000000000000000000000 + 17: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 18: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 19: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 20: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 21: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 22: 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF + 23: 0x0000000000000000000000000000000000000000000000000000000000000000 + +In this PoC we are only interested in PCR0, which must be non-null. This is +because the boot process records all the images in this PCR (see field ``PCRIndex`` +on the Event Log above). The rest of the records must be 0 at this point. + +.. note:: + The fTPM service used has support only for 16 PCRs, therefore the content + of PCRs above 15 can be ignored. + +.. note:: + As stated earlier, Arm does not provide an fTPM implementation and therefore + we do not validate here if the content of PCR0 is correct or not. For this + PoC, we are only focused on the fact that the event log could be passed to a third + party fTPM and its records were properly extended. + +Fine-tuning the fTPM TA +~~~~~~~~~~~~~~~~~~~~~~~ + +As stated earlier, the OP-TEE Toolkit includes support to build a third party fTPM +service. The build options for this service are tailored for the PoC and defined in +the build environment variable ``FTPM_FLAGS`` (see ``/build/common.mk``) +but they can be modified if needed to better adapt it to a specific scenario. + +The most relevant options for Measured Boot support are: + + - **CFG_TA_DEBUG**: Enables debug logs in the Terminal_1 console. + - **CFG_TEE_TA_LOG_LEVEL**: Defines the log level used for the debug messages. + - **CFG_TA_MEASURED_BOOT**: Enables support for measured boot on the fTPM. + - **CFG_TA_EVENT_LOG_SIZE**: Defines the size, in bytes, of the larger event log that + the fTPM is able to store, as this buffer is allocated at build time. This must be at + least the same as the size of the event log generated by TF-A. If this build option + is not defined, the fTPM falls back to a default value of 1024 bytes, which is enough + for this PoC, so this variable is not defined in FTPM_FLAGS. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _OP-TEE Toolkit: https://github.com/OP-TEE/build +.. _ms-tpm-20-ref: https://github.com/microsoft/ms-tpm-20-ref +.. _Get and build the solution: https://optee.readthedocs.io/en/latest/building/gits/build.html#get-and-build-the-solution +.. _Armv8-A Foundation Platform (For Linux Hosts Only): https://developer.arm.com/tools-and-software/simulation-models/fixed-virtual-platforms/arm-ecosystem-models +.. _tpm2-tools: https://github.com/tpm2-software/tpm2-tools +.. _TGC event log: https://trustedcomputinggroup.org/resource/tcg-efi-platform-specification/ diff --git a/arm-trusted-firmware/docs/getting_started/build-options.rst b/arm-trusted-firmware/docs/getting_started/build-options.rst new file mode 100644 index 0000000..adc05e6 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/build-options.rst @@ -0,0 +1,974 @@ +Build Options +============= + +The TF-A build system supports the following build options. Unless mentioned +otherwise, these options are expected to be specified at the build command +line and are not to be modified in any component makefiles. Note that the +build system doesn't track dependency for build options. Therefore, if any of +the build options are changed from a previous build, a clean build must be +performed. + +.. _build_options_common: + +Common build options +-------------------- + +- ``AARCH32_INSTRUCTION_SET``: Choose the AArch32 instruction set that the + compiler should use. Valid values are T32 and A32. It defaults to T32 due to + code having a smaller resulting size. + +- ``AARCH32_SP`` : Choose the AArch32 Secure Payload component to be built as + as the BL32 image when ``ARCH=aarch32``. The value should be the path to the + directory containing the SP source, relative to the ``bl32/``; the directory + is expected to contain a makefile called ``.mk``. + +- ``AMU_RESTRICT_COUNTERS``: Register reads to the group 1 counters will return + zero at all but the highest implemented exception level. Reads from the + memory mapped view are unaffected by this control. + +- ``ARCH`` : Choose the target build architecture for TF-A. It can take either + ``aarch64`` or ``aarch32`` as values. By default, it is defined to + ``aarch64``. + +- ``ARM_ARCH_FEATURE``: Optional Arm Architecture build option which specifies + one or more feature modifiers. This option has the form ``[no]feature+...`` + and defaults to ``none``. It translates into compiler option + ``-march=armvX[.Y]-a+[no]feature+...``. See compiler's documentation for the + list of supported feature modifiers. + +- ``ARM_ARCH_MAJOR``: The major version of Arm Architecture to target when + compiling TF-A. Its value must be numeric, and defaults to 8 . See also, + *Armv8 Architecture Extensions* and *Armv7 Architecture Extensions* in + :ref:`Firmware Design`. + +- ``ARM_ARCH_MINOR``: The minor version of Arm Architecture to target when + compiling TF-A. Its value must be a numeric, and defaults to 0. See also, + *Armv8 Architecture Extensions* in :ref:`Firmware Design`. + +- ``BL2``: This is an optional build option which specifies the path to BL2 + image for the ``fip`` target. In this case, the BL2 in the TF-A will not be + built. + +- ``BL2U``: This is an optional build option which specifies the path to + BL2U image. In this case, the BL2U in TF-A will not be built. + +- ``BL2_AT_EL3``: This is an optional build option that enables the use of + BL2 at EL3 execution level. + +- ``BL2_ENABLE_SP_LOAD``: Boolean option to enable loading SP packages from the + FIP. Automatically enabled if ``SP_LAYOUT_FILE`` is provided. + +- ``BL2_IN_XIP_MEM``: In some use-cases BL2 will be stored in eXecute In Place + (XIP) memory, like BL1. In these use-cases, it is necessary to initialize + the RW sections in RAM, while leaving the RO sections in place. This option + enable this use-case. For now, this option is only supported when BL2_AT_EL3 + is set to '1'. + +- ``BL31``: This is an optional build option which specifies the path to + BL31 image for the ``fip`` target. In this case, the BL31 in TF-A will not + be built. + +- ``BL31_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL31 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL32``: This is an optional build option which specifies the path to + BL32 image for the ``fip`` target. In this case, the BL32 in TF-A will not + be built. + +- ``BL32_EXTRA1``: This is an optional build option which specifies the path to + Trusted OS Extra1 image for the ``fip`` target. + +- ``BL32_EXTRA2``: This is an optional build option which specifies the path to + Trusted OS Extra2 image for the ``fip`` target. + +- ``BL32_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL32 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BL33``: Path to BL33 image in the host file system. This is mandatory for + ``fip`` target in case TF-A BL2 is used. + +- ``BL33_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the BL33 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``BRANCH_PROTECTION``: Numeric value to enable ARMv8.3 Pointer Authentication + and ARMv8.5 Branch Target Identification support for TF-A BL images themselves. + If enabled, it is needed to use a compiler that supports the option + ``-mbranch-protection``. Selects the branch protection features to use: +- 0: Default value turns off all types of branch protection +- 1: Enables all types of branch protection features +- 2: Return address signing to its standard level +- 3: Extend the signing to include leaf functions +- 4: Turn on branch target identification mechanism + + The table below summarizes ``BRANCH_PROTECTION`` values, GCC compilation options + and resulting PAuth/BTI features. + + +-------+--------------+-------+-----+ + | Value | GCC option | PAuth | BTI | + +=======+==============+=======+=====+ + | 0 | none | N | N | + +-------+--------------+-------+-----+ + | 1 | standard | Y | Y | + +-------+--------------+-------+-----+ + | 2 | pac-ret | Y | N | + +-------+--------------+-------+-----+ + | 3 | pac-ret+leaf | Y | N | + +-------+--------------+-------+-----+ + | 4 | bti | N | Y | + +-------+--------------+-------+-----+ + + This option defaults to 0. + Note that Pointer Authentication is enabled for Non-secure world + irrespective of the value of this option if the CPU supports it. + +- ``BUILD_MESSAGE_TIMESTAMP``: String used to identify the time and date of the + compilation of each build. It must be set to a C string (including quotes + where applicable). Defaults to a string that contains the time and date of + the compilation. + +- ``BUILD_STRING``: Input string for VERSION_STRING, which allows the TF-A + build to be uniquely identified. Defaults to the current git commit id. + +- ``BUILD_BASE``: Output directory for the build. Defaults to ``./build`` + +- ``CFLAGS``: Extra user options appended on the compiler's command line in + addition to the options set by the build system. + +- ``COLD_BOOT_SINGLE_CPU``: This option indicates whether the platform may + release several CPUs out of reset. It can take either 0 (several CPUs may be + brought up) or 1 (only one CPU will ever be brought up during cold reset). + Default is 0. If the platform always brings up a single CPU, there is no + need to distinguish between primary and secondary CPUs and the boot path can + be optimised. The ``plat_is_my_cpu_primary()`` and + ``plat_secondary_cold_boot_setup()`` platform porting interfaces do not need + to be implemented in this case. + +- ``COT``: When Trusted Boot is enabled, selects the desired chain of trust. + Defaults to ``tbbr``. + +- ``CRASH_REPORTING``: A non-zero value enables a console dump of processor + register state when an unexpected exception occurs during execution of + BL31. This option defaults to the value of ``DEBUG`` - i.e. by default + this is only enabled for a debug build of the firmware. + +- ``CREATE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to create new keys in case no valid keys are + present or specified. Allowed options are '0' or '1'. Default is '1'. + +- ``CTX_INCLUDE_AARCH32_REGS`` : Boolean option that, when set to 1, will cause + the AArch32 system registers to be included when saving and restoring the + CPU context. The option must be set to 0 for AArch64-only platforms (that + is on hardware that does not implement AArch32, or at least not at EL1 and + higher ELs). Default value is 1. + +- ``CTX_INCLUDE_EL2_REGS`` : This boolean option provides context save/restore + operations when entering/exiting an EL2 execution context. This is of primary + interest when Armv8.4-SecEL2 extension is implemented. Default is 0 (disabled). + This option must be equal to 1 (enabled) when ``SPD=spmd`` and + ``SPMD_SPM_AT_SEL2`` is set. + +- ``CTX_INCLUDE_FPREGS``: Boolean option that, when set to 1, will cause the FP + registers to be included when saving and restoring the CPU context. Default + is 0. + +- ``CTX_INCLUDE_NEVE_REGS``: Boolean option that, when set to 1, will cause the + Armv8.4-NV registers to be saved/restored when entering/exiting an EL2 + execution context. Default value is 0. + +- ``CTX_INCLUDE_PAUTH_REGS``: Boolean option that, when set to 1, enables + Pointer Authentication for Secure world. This will cause the ARMv8.3-PAuth + registers to be included when saving and restoring the CPU context as + part of world switch. Default value is 0. + Note that Pointer Authentication is enabled for Non-secure world irrespective + of the value of this flag if the CPU supports it. + +- ``DEBUG``: Chooses between a debug and release build. It can take either 0 + (release) or 1 (debug) as values. 0 is the default. + +- ``DECRYPTION_SUPPORT``: This build flag enables the user to select the + authenticated decryption algorithm to be used to decrypt firmware/s during + boot. It accepts 2 values: ``aes_gcm`` and ``none``. The default value of + this flag is ``none`` to disable firmware decryption which is an optional + feature as per TBBR. + +- ``DISABLE_BIN_GENERATION``: Boolean option to disable the generation + of the binary image. If set to 1, then only the ELF image is built. + 0 is the default. + +- ``DISABLE_MTPMU``: Boolean option to disable FEAT_MTPMU if implemented + (Armv8.6 onwards). Its default value is 0 to keep consistency with platforms + that do not implement FEAT_MTPMU. For more information on FEAT_MTPMU, + check the latest Arm ARM. + +- ``DYN_DISABLE_AUTH``: Provides the capability to dynamically disable Trusted + Board Boot authentication at runtime. This option is meant to be enabled only + for development platforms. ``TRUSTED_BOARD_BOOT`` flag must be set if this + flag has to be enabled. 0 is the default. + +- ``E``: Boolean option to make warnings into errors. Default is 1. + +- ``EL3_PAYLOAD_BASE``: This option enables booting an EL3 payload instead of + the normal boot flow. It must specify the entry point address of the EL3 + payload. Please refer to the "Booting an EL3 payload" section for more + details. + +- ``ENABLE_AMU``: Boolean option to enable Activity Monitor Unit extensions. + This is an optional architectural feature available on v8.4 onwards. Some + v8.2 implementations also implement an AMU and this option can be used to + enable this feature on those systems as well. Default is 0. + +- ``ENABLE_AMU_AUXILIARY_COUNTERS``: Enables support for AMU auxiliary counters + (also known as group 1 counters). These are implementation-defined counters, + and as such require additional platform configuration. Default is 0. + +- ``ENABLE_AMU_FCONF``: Enables configuration of the AMU through FCONF, which + allows platforms with auxiliary counters to describe them via the + ``HW_CONFIG`` device tree blob. Default is 0. + +- ``ENABLE_ASSERTIONS``: This option controls whether or not calls to ``assert()`` + are compiled out. For debug builds, this option defaults to 1, and calls to + ``assert()`` are left in place. For release builds, this option defaults to 0 + and calls to ``assert()`` function are compiled out. This option can be set + independently of ``DEBUG``. It can also be used to hide any auxiliary code + that is only required for the assertion and does not fit in the assertion + itself. + +- ``ENABLE_BACKTRACE``: This option controls whether to enable backtrace + dumps or not. It is supported in both AArch64 and AArch32. However, in + AArch32 the format of the frame records are not defined in the AAPCS and they + are defined by the implementation. This implementation of backtrace only + supports the format used by GCC when T32 interworking is disabled. For this + reason enabling this option in AArch32 will force the compiler to only + generate A32 code. This option is enabled by default only in AArch64 debug + builds, but this behaviour can be overridden in each platform's Makefile or + in the build command line. + +- ``ENABLE_FEAT_AMUv1``: Boolean option to enable access to the HAFGRTR_EL2 + (Hypervisor Activity Monitors Fine-Grained Read Trap Register) during EL2 + to EL3 context save/restore operations. It is an optional feature available + on v8.4 and onwards and must be set to 1 alongside ``ENABLE_FEAT_FGT``, to + access the HAFGRTR_EL2 register. Defaults to ``0``. + +- ``ENABLE_FEAT_ECV``: Boolean option to enable support for the Enhanced Counter + Virtualization feature, allowing for access to the CNTPOFF_EL2 (Counter-timer + Physical Offset register) during EL2 to EL3 context save/restore operations. + Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for + v8.6 or later CPUs. + +- ``ENABLE_FEAT_FGT``: Boolean option to enable support for FGT (Fine Grain Traps) + feature allowing for access to the HDFGRTR_EL2 (Hypervisor Debug Fine-Grained + Read Trap Register) during EL2 to EL3 context save/restore operations. + Its a mandatory architectural feature in Armv8.6 and defaults to ``1`` for + v8.6 or later CPUs. + +- ``ENABLE_FEAT_HCX``: This option sets the bit SCR_EL3.HXEn in EL3 to allow + access to HCRX_EL2 (extended hypervisor control register) from EL2 as well as + adding HCRX_EL2 to the EL2 context save/restore operations. + +- ``ENABLE_LTO``: Boolean option to enable Link Time Optimization (LTO) + support in GCC for TF-A. This option is currently only supported for + AArch64. Default is 0. + +- ``ENABLE_MPAM_FOR_LOWER_ELS``: Boolean option to enable lower ELs to use MPAM + feature. MPAM is an optional Armv8.4 extension that enables various memory + system components and resources to define partitions; software running at + various ELs can assign themselves to desired partition to control their + performance aspects. + + When this option is set to ``1``, EL3 allows lower ELs to access their own + MPAM registers without trapping into EL3. This option doesn't make use of + partitioning in EL3, however. Platform initialisation code should configure + and use partitions in EL3 as required. This option defaults to ``0``. + +- ``ENABLE_MPMM``: Boolean option to enable support for the Maximum Power + Mitigation Mechanism supported by certain Arm cores, which allows the SoC + firmware to detect and limit high activity events to assist in SoC processor + power domain dynamic power budgeting and limit the triggering of whole-rail + (i.e. clock chopping) responses to overcurrent conditions. Defaults to ``0``. + +- ``ENABLE_MPMM_FCONF``: Enables configuration of MPMM through FCONF, which + allows platforms with cores supporting MPMM to describe them via the + ``HW_CONFIG`` device tree blob. Default is 0. + +- ``ENABLE_PIE``: Boolean option to enable Position Independent Executable(PIE) + support within generic code in TF-A. This option is currently only supported + in BL2_AT_EL3, BL31, and BL32 (TSP) for AARCH64 binaries, and in BL32 + (SP_min) for AARCH32. Default is 0. + +- ``ENABLE_PMF``: Boolean option to enable support for optional Performance + Measurement Framework(PMF). Default is 0. + +- ``ENABLE_PSCI_STAT``: Boolean option to enable support for optional PSCI + functions ``PSCI_STAT_RESIDENCY`` and ``PSCI_STAT_COUNT``. Default is 0. + In the absence of an alternate stat collection backend, ``ENABLE_PMF`` must + be enabled. If ``ENABLE_PMF`` is set, the residency statistics are tracked in + software. + +- ``ENABLE_RME``: Boolean option to enable support for the ARMv9 Realm + Management Extension. Default value is 0. This is currently an experimental + feature. + +- ``ENABLE_RUNTIME_INSTRUMENTATION``: Boolean option to enable runtime + instrumentation which injects timestamp collection points into TF-A to + allow runtime performance to be measured. Currently, only PSCI is + instrumented. Enabling this option enables the ``ENABLE_PMF`` build option + as well. Default is 0. + +- ``ENABLE_SME_FOR_NS``: Boolean option to enable Scalable Matrix Extension + (SME), SVE, and FPU/SIMD for the non-secure world only. These features share + registers so are enabled together. Using this option without + ENABLE_SME_FOR_SWD=1 will cause SME, SVE, and FPU/SIMD instructions in secure + world to trap to EL3. SME is an optional architectural feature for AArch64 + and TF-A support is experimental. At this time, this build option cannot be + used on systems that have SPD=spmd/SPM_MM or ENABLE_RME, and attempting to + build with these options will fail. Default is 0. + +- ``ENABLE_SME_FOR_SWD``: Boolean option to enable the Scalable Matrix + Extension for secure world use along with SVE and FPU/SIMD, ENABLE_SME_FOR_NS + must also be set to use this. If enabling this, the secure world MUST + handle context switching for SME, SVE, and FPU/SIMD registers to ensure that + no data is leaked to non-secure world. This is experimental. Default is 0. + +- ``ENABLE_SPE_FOR_LOWER_ELS`` : Boolean option to enable Statistical Profiling + extensions. This is an optional architectural feature for AArch64. + The default is 1 but is automatically disabled when the target architecture + is AArch32. + +- ``ENABLE_SVE_FOR_NS``: Boolean option to enable Scalable Vector Extension + (SVE) for the Non-secure world only. SVE is an optional architectural feature + for AArch64. Note that when SVE is enabled for the Non-secure world, access + to SIMD and floating-point functionality from the Secure world is disabled by + default and controlled with ENABLE_SVE_FOR_SWD. + This is to avoid corruption of the Non-secure world data in the Z-registers + which are aliased by the SIMD and FP registers. The build option is not + compatible with the ``CTX_INCLUDE_FPREGS`` build option, and will raise an + assert on platforms where SVE is implemented and ``ENABLE_SVE_FOR_NS`` set to + 1. The default is 1 but is automatically disabled when ENABLE_SME_FOR_NS=1 + since SME encompasses SVE. At this time, this build option cannot be used on + systems that have SPM_MM enabled. + +- ``ENABLE_SVE_FOR_SWD``: Boolean option to enable SVE for the Secure world. + SVE is an optional architectural feature for AArch64. Note that this option + requires ENABLE_SVE_FOR_NS to be enabled. The default is 0 and it is + automatically disabled when the target architecture is AArch32. + +- ``ENABLE_STACK_PROTECTOR``: String option to enable the stack protection + checks in GCC. Allowed values are "all", "strong", "default" and "none". The + default value is set to "none". "strong" is the recommended stack protection + level if this feature is desired. "none" disables the stack protection. For + all values other than "none", the ``plat_get_stack_protector_canary()`` + platform hook needs to be implemented. The value is passed as the last + component of the option ``-fstack-protector-$ENABLE_STACK_PROTECTOR``. + +- ``ENCRYPT_BL31``: Binary flag to enable encryption of BL31 firmware. This + flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENCRYPT_BL32``: Binary flag to enable encryption of Secure BL32 payload. + This flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENC_KEY``: A 32-byte (256-bit) symmetric key in hex string format. It could + either be SSK or BSSK depending on ``FW_ENC_STATUS`` flag. This value depends + on ``DECRYPTION_SUPPORT`` build flag. + +- ``ENC_NONCE``: A 12-byte (96-bit) encryption nonce or Initialization Vector + (IV) in hex string format. This value depends on ``DECRYPTION_SUPPORT`` + build flag. + +- ``ERROR_DEPRECATED``: This option decides whether to treat the usage of + deprecated platform APIs, helper functions or drivers within Trusted + Firmware as error. It can take the value 1 (flag the use of deprecated + APIs as error) or 0. The default is 0. + +- ``EL3_EXCEPTION_HANDLING``: When set to ``1``, enable handling of exceptions + targeted at EL3. When set ``0`` (default), no exceptions are expected or + handled at EL3, and a panic will result. This is supported only for AArch64 + builds. + +- ``EVENT_LOG_LEVEL``: Chooses the log level to use for Measured Boot when + ``MEASURED_BOOT`` is enabled. For a list of valid values, see ``LOG_LEVEL``. + Default value is 40 (LOG_LEVEL_INFO). + +- ``FAULT_INJECTION_SUPPORT``: ARMv8.4 extensions introduced support for fault + injection from lower ELs, and this build option enables lower ELs to use + Error Records accessed via System Registers to inject faults. This is + applicable only to AArch64 builds. + + This feature is intended for testing purposes only, and is advisable to keep + disabled for production images. + +- ``FIP_NAME``: This is an optional build option which specifies the FIP + filename for the ``fip`` target. Default is ``fip.bin``. + +- ``FWU_FIP_NAME``: This is an optional build option which specifies the FWU + FIP filename for the ``fwu_fip`` target. Default is ``fwu_fip.bin``. + +- ``FW_ENC_STATUS``: Top level firmware's encryption numeric flag, values: + + :: + + 0: Encryption is done with Secret Symmetric Key (SSK) which is common + for a class of devices. + 1: Encryption is done with Binding Secret Symmetric Key (BSSK) which is + unique per device. + + This flag depends on ``DECRYPTION_SUPPORT`` build flag. + +- ``GENERATE_COT``: Boolean flag used to build and execute the ``cert_create`` + tool to create certificates as per the Chain of Trust described in + :ref:`Trusted Board Boot`. The build system then calls ``fiptool`` to + include the certificates in the FIP and FWU_FIP. Default value is '0'. + + Specify both ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=1`` to include support + for the Trusted Board Boot feature in the BL1 and BL2 images, to generate + the corresponding certificates, and to include those certificates in the + FIP and FWU_FIP. + + Note that if ``TRUSTED_BOARD_BOOT=0`` and ``GENERATE_COT=1``, the BL1 and BL2 + images will not include support for Trusted Board Boot. The FIP will still + include the corresponding certificates. This FIP can be used to verify the + Chain of Trust on the host machine through other mechanisms. + + Note that if ``TRUSTED_BOARD_BOOT=1`` and ``GENERATE_COT=0``, the BL1 and BL2 + images will include support for Trusted Board Boot, but the FIP and FWU_FIP + will not include the corresponding certificates, causing a boot failure. + +- ``GICV2_G0_FOR_EL3``: Unlike GICv3, the GICv2 architecture doesn't have + inherent support for specific EL3 type interrupts. Setting this build option + to ``1`` assumes GICv2 *Group 0* interrupts are expected to target EL3, both + by :ref:`platform abstraction layer` and + :ref:`Interrupt Management Framework`. + This allows GICv2 platforms to enable features requiring EL3 interrupt type. + This also means that all GICv2 Group 0 interrupts are delivered to EL3, and + the Secure Payload interrupts needs to be synchronously handed over to Secure + EL1 for handling. The default value of this option is ``0``, which means the + Group 0 interrupts are assumed to be handled by Secure EL1. + +- ``HANDLE_EA_EL3_FIRST``: When set to ``1``, External Aborts and SError + Interrupts will be always trapped in EL3 i.e. in BL31 at runtime. When set to + ``0`` (default), these exceptions will be trapped in the current exception + level (or in EL1 if the current exception level is EL0). + +- ``HW_ASSISTED_COHERENCY``: On most Arm systems to-date, platform-specific + software operations are required for CPUs to enter and exit coherency. + However, newer systems exist where CPUs' entry to and exit from coherency + is managed in hardware. Such systems require software to only initiate these + operations, and the rest is managed in hardware, minimizing active software + management. In such systems, this boolean option enables TF-A to carry out + build and run-time optimizations during boot and power management operations. + This option defaults to 0 and if it is enabled, then it implies + ``WARMBOOT_ENABLE_DCACHE_EARLY`` is also enabled. + + If this flag is disabled while the platform which TF-A is compiled for + includes cores that manage coherency in hardware, then a compilation error is + generated. This is based on the fact that a system cannot have, at the same + time, cores that manage coherency in hardware and cores that don't. In other + words, a platform cannot have, at the same time, cores that require + ``HW_ASSISTED_COHERENCY=1`` and cores that require + ``HW_ASSISTED_COHERENCY=0``. + + Note that, when ``HW_ASSISTED_COHERENCY`` is enabled, version 2 of + translation library (xlat tables v2) must be used; version 1 of translation + library is not supported. + +- ``INVERTED_MEMMAP``: memmap tool print by default lower addresses at the + bottom, higher addresses at the top. This build flag can be set to '1' to + invert this behavior. Lower addresses will be printed at the top and higher + addresses at the bottom. + +- ``JUNO_AARCH32_EL3_RUNTIME``: This build flag enables you to execute EL3 + runtime software in AArch32 mode, which is required to run AArch32 on Juno. + By default this flag is set to '0'. Enabling this flag builds BL1 and BL2 in + AArch64 and facilitates the loading of ``SP_MIN`` and BL33 as AArch32 executable + images. + +- ``KEY_ALG``: This build flag enables the user to select the algorithm to be + used for generating the PKCS keys and subsequent signing of the certificate. + It accepts 3 values: ``rsa``, ``rsa_1_5`` and ``ecdsa``. The option + ``rsa_1_5`` is the legacy PKCS#1 RSA 1.5 algorithm which is not TBBR + compliant and is retained only for compatibility. The default value of this + flag is ``rsa`` which is the TBBR compliant PKCS#1 RSA 2.1 scheme. + +- ``KEY_SIZE``: This build flag enables the user to select the key size for + the algorithm specified by ``KEY_ALG``. The valid values for ``KEY_SIZE`` + depend on the chosen algorithm and the cryptographic module. + + +-----------+------------------------------------+ + | KEY_ALG | Possible key sizes | + +===========+====================================+ + | rsa | 1024 , 2048 (default), 3072, 4096* | + +-----------+------------------------------------+ + | ecdsa | unavailable | + +-----------+------------------------------------+ + + * Only 2048 bits size is available with CryptoCell 712 SBROM release 1. + Only 3072 bits size is available with CryptoCell 712 SBROM release 2. + +- ``HASH_ALG``: This build flag enables the user to select the secure hash + algorithm. It accepts 3 values: ``sha256``, ``sha384`` and ``sha512``. + The default value of this flag is ``sha256``. + +- ``LDFLAGS``: Extra user options appended to the linkers' command line in + addition to the one set by the build system. + +- ``LOG_LEVEL``: Chooses the log level, which controls the amount of console log + output compiled into the build. This should be one of the following: + + :: + + 0 (LOG_LEVEL_NONE) + 10 (LOG_LEVEL_ERROR) + 20 (LOG_LEVEL_NOTICE) + 30 (LOG_LEVEL_WARNING) + 40 (LOG_LEVEL_INFO) + 50 (LOG_LEVEL_VERBOSE) + + All log output up to and including the selected log level is compiled into + the build. The default value is 40 in debug builds and 20 in release builds. + +- ``MEASURED_BOOT``: Boolean flag to include support for the Measured Boot + feature. This flag can be enabled with ``TRUSTED_BOARD_BOOT`` in order to + provide trust that the code taking the measurements and recording them has + not been tampered with. + + This option defaults to 0. + +- ``NON_TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Non-Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``NS_BL2U``: Path to NS_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``NS_TIMER_SWITCH``: Enable save and restore for non-secure timer register + contents upon world switch. It can take either 0 (don't save and restore) or + 1 (do save and restore). 0 is the default. An SPD may set this to 1 if it + wants the timer registers to be saved and restored. + +- ``OVERRIDE_LIBC``: This option allows platforms to override the default libc + for the BL image. It can be either 0 (include) or 1 (remove). The default + value is 0. + +- ``PL011_GENERIC_UART``: Boolean option to indicate the PL011 driver that + the underlying hardware is not a full PL011 UART but a minimally compliant + generic UART, which is a subset of the PL011. The driver will not access + any register that is not part of the SBSA generic UART specification. + Default value is 0 (a full PL011 compliant UART is present). + +- ``PLAT``: Choose a platform to build TF-A for. The chosen platform name + must be subdirectory of any depth under ``plat/``, and must contain a + platform makefile named ``platform.mk``. For example, to build TF-A for the + Arm Juno board, select PLAT=juno. + +- ``PRELOADED_BL33_BASE``: This option enables booting a preloaded BL33 image + instead of the normal boot flow. When defined, it must specify the entry + point address for the preloaded BL33 image. This option is incompatible with + ``EL3_PAYLOAD_BASE``. If both are defined, ``EL3_PAYLOAD_BASE`` has priority + over ``PRELOADED_BL33_BASE``. + +- ``PROGRAMMABLE_RESET_ADDRESS``: This option indicates whether the reset + vector address can be programmed or is fixed on the platform. It can take + either 0 (fixed) or 1 (programmable). Default is 0. If the platform has a + programmable reset address, it is expected that a CPU will start executing + code directly at the right address, both on a cold and warm reset. In this + case, there is no need to identify the entrypoint on boot and the boot path + can be optimised. The ``plat_get_my_entrypoint()`` platform porting interface + does not need to be implemented in this case. + +- ``PSCI_EXTENDED_STATE_ID``: As per PSCI1.0 Specification, there are 2 formats + possible for the PSCI power-state parameter: original and extended State-ID + formats. This flag if set to 1, configures the generic PSCI layer to use the + extended format. The default value of this flag is 0, which means by default + the original power-state format is used by the PSCI implementation. This flag + should be specified by the platform makefile and it governs the return value + of PSCI_FEATURES API for CPU_SUSPEND smc function id. When this option is + enabled on Arm platforms, the option ``ARM_RECOM_STATE_ID_ENC`` needs to be + set to 1 as well. + +- ``RAS_EXTENSION``: When set to ``1``, enable Armv8.2 RAS features. RAS features + are an optional extension for pre-Armv8.2 CPUs, but are mandatory for Armv8.2 + or later CPUs. + + When ``RAS_EXTENSION`` is set to ``1``, ``HANDLE_EA_EL3_FIRST`` must also be + set to ``1``. + + This option is disabled by default. + +- ``RESET_TO_BL31``: Enable BL31 entrypoint as the CPU reset vector instead + of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to BL31 entrypoint). + The default value is 0. + +- ``RESET_TO_SP_MIN``: SP_MIN is the minimal AArch32 Secure Payload provided + in TF-A. This flag configures SP_MIN entrypoint as the CPU reset vector + instead of the BL1 entrypoint. It can take the value 0 (CPU reset to BL1 + entrypoint) or 1 (CPU reset to SP_MIN entrypoint). The default value is 0. + +- ``ROT_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the ROT private key in PEM format and enforces public key + hash generation. If ``SAVE_KEYS=1``, this + file name will be used to save the key. + +- ``SAVE_KEYS``: This option is used when ``GENERATE_COT=1``. It tells the + certificate generation tool to save the keys used to establish the Chain of + Trust. Allowed options are '0' or '1'. Default is '0' (do not save). + +- ``SCP_BL2``: Path to SCP_BL2 image in the host file system. This image is optional. + If a SCP_BL2 image is present then this option must be passed for the ``fip`` + target. + +- ``SCP_BL2_KEY``: This option is used when ``GENERATE_COT=1``. It specifies the + file that contains the SCP_BL2 private key in PEM format. If ``SAVE_KEYS=1``, + this file name will be used to save the key. + +- ``SCP_BL2U``: Path to SCP_BL2U image in the host file system. This image is + optional. It is only needed if the platform makefile specifies that it + is required in order to build the ``fwu_fip`` target. + +- ``SDEI_SUPPORT``: Setting this to ``1`` enables support for Software + Delegated Exception Interface to BL31 image. This defaults to ``0``. + + When set to ``1``, the build option ``EL3_EXCEPTION_HANDLING`` must also be + set to ``1``. + +- ``SEPARATE_CODE_AND_RODATA``: Whether code and read-only data should be + isolated on separate memory pages. This is a trade-off between security and + memory usage. See "Isolating code and read-only data on separate memory + pages" section in :ref:`Firmware Design`. This flag is disabled by default + and affects all BL images. + +- ``SEPARATE_NOBITS_REGION``: Setting this option to ``1`` allows the NOBITS + sections of BL31 (.bss, stacks, page tables, and coherent memory) to be + allocated in RAM discontiguous from the loaded firmware image. When set, the + platform is expected to provide definitions for ``BL31_NOBITS_BASE`` and + ``BL31_NOBITS_LIMIT``. When the option is ``0`` (the default), NOBITS + sections are placed in RAM immediately following the loaded firmware image. + +- ``SEPARATE_BL2_NOLOAD_REGION``: Setting this option to ``1`` allows the + NOLOAD sections of BL2 (.bss, stacks, page tables) to be allocated in RAM + discontiguous from loaded firmware images. When set, the platform need to + provide definitions of ``BL2_NOLOAD_START`` and ``BL2_NOLOAD_LIMIT``. This + flag is disabled by default and NOLOAD sections are placed in RAM immediately + following the loaded firmware image. + +- ``SMC_PCI_SUPPORT``: This option allows platforms to handle PCI configuration + access requests via a standard SMCCC defined in `DEN0115`_. When combined with + UEFI+ACPI this can provide a certain amount of OS forward compatibility + with newer platforms that aren't ECAM compliant. + +- ``SPD``: Choose a Secure Payload Dispatcher component to be built into TF-A. + This build option is only valid if ``ARCH=aarch64``. The value should be + the path to the directory containing the SPD source, relative to + ``services/spd/``; the directory is expected to contain a makefile called + ``.mk``. The SPM Dispatcher standard service is located in + services/std_svc/spmd and enabled by ``SPD=spmd``. The SPM Dispatcher + cannot be enabled when the ``SPM_MM`` option is enabled. + +- ``SPIN_ON_BL1_EXIT``: This option introduces an infinite loop in BL1. It can + take either 0 (no loop) or 1 (add a loop). 0 is the default. This loop stops + execution in BL1 just before handing over to BL31. At this point, all + firmware images have been loaded in memory, and the MMU and caches are + turned off. Refer to the "Debugging options" section for more details. + +- ``SPMD_SPM_AT_SEL2`` : this boolean option is used jointly with the SPM + Dispatcher option (``SPD=spmd``). When enabled (1) it indicates the SPMC + component runs at the S-EL2 execution state provided by the Armv8.4-SecEL2 + extension. This is the default when enabling the SPM Dispatcher. When + disabled (0) it indicates the SPMC component runs at the S-EL1 execution + state. This latter configuration supports pre-Armv8.4 platforms (aka not + implementing the Armv8.4-SecEL2 extension). + +- ``SPM_MM`` : Boolean option to enable the Management Mode (MM)-based Secure + Partition Manager (SPM) implementation. The default value is ``0`` + (disabled). This option cannot be enabled (``1``) when SPM Dispatcher is + enabled (``SPD=spmd``). + +- ``SP_LAYOUT_FILE``: Platform provided path to JSON file containing the + description of secure partitions. The build system will parse this file and + package all secure partition blobs into the FIP. This file is not + necessarily part of TF-A tree. Only available when ``SPD=spmd``. + +- ``SP_MIN_WITH_SECURE_FIQ``: Boolean flag to indicate the SP_MIN handles + secure interrupts (caught through the FIQ line). Platforms can enable + this directive if they need to handle such interruption. When enabled, + the FIQ are handled in monitor mode and non secure world is not allowed + to mask these events. Platforms that enable FIQ handling in SP_MIN shall + implement the api ``sp_min_plat_fiq_handler()``. The default value is 0. + +- ``TRUSTED_BOARD_BOOT``: Boolean flag to include support for the Trusted Board + Boot feature. When set to '1', BL1 and BL2 images include support to load + and verify the certificates and images in a FIP, and BL1 includes support + for the Firmware Update. The default value is '0'. Generation and inclusion + of certificates in the FIP and FWU_FIP depends upon the value of the + ``GENERATE_COT`` option. + + .. warning:: + This option depends on ``CREATE_KEYS`` to be enabled. If the keys + already exist in disk, they will be overwritten without further notice. + +- ``TRUSTED_WORLD_KEY``: This option is used when ``GENERATE_COT=1``. It + specifies the file that contains the Trusted World private key in PEM + format. If ``SAVE_KEYS=1``, this file name will be used to save the key. + +- ``TSP_INIT_ASYNC``: Choose BL32 initialization method as asynchronous or + synchronous, (see "Initializing a BL32 Image" section in + :ref:`Firmware Design`). It can take the value 0 (BL32 is initialized using + synchronous method) or 1 (BL32 is initialized using asynchronous method). + Default is 0. + +- ``TSP_NS_INTR_ASYNC_PREEMPT``: A non zero value enables the interrupt + routing model which routes non-secure interrupts asynchronously from TSP + to EL3 causing immediate preemption of TSP. The EL3 is responsible + for saving and restoring the TSP context in this routing model. The + default routing model (when the value is 0) is to route non-secure + interrupts to TSP allowing it to save its context and hand over + synchronously to EL3 via an SMC. + + .. note:: + When ``EL3_EXCEPTION_HANDLING`` is ``1``, ``TSP_NS_INTR_ASYNC_PREEMPT`` + must also be set to ``1``. + +- ``USE_ARM_LINK``: This flag determines whether to enable support for ARM + linker. When the ``LINKER`` build variable points to the armlink linker, + this flag is enabled automatically. To enable support for armlink, platforms + will have to provide a scatter file for the BL image. Currently, Tegra + platforms use the armlink support to compile BL3-1 images. + +- ``USE_COHERENT_MEM``: This flag determines whether to include the coherent + memory region in the BL memory map or not (see "Use of Coherent memory in + TF-A" section in :ref:`Firmware Design`). It can take the value 1 + (Coherent memory region is included) or 0 (Coherent memory region is + excluded). Default is 1. + +- ``USE_DEBUGFS``: When set to 1 this option activates an EXPERIMENTAL feature + exposing a virtual filesystem interface through BL31 as a SiP SMC function. + Default is 0. + +- ``ARM_IO_IN_DTB``: This flag determines whether to use IO based on the + firmware configuration framework. This will move the io_policies into a + configuration device tree, instead of static structure in the code base. + +- ``COT_DESC_IN_DTB``: This flag determines whether to create COT descriptors + at runtime using fconf. If this flag is enabled, COT descriptors are + statically captured in tb_fw_config file in the form of device tree nodes + and properties. Currently, COT descriptors used by BL2 are moved to the + device tree and COT descriptors used by BL1 are retained in the code + base statically. + +- ``SDEI_IN_FCONF``: This flag determines whether to configure SDEI setup in + runtime using firmware configuration framework. The platform specific SDEI + shared and private events configuration is retrieved from device tree rather + than static C structures at compile time. This is only supported if + SDEI_SUPPORT build flag is enabled. + +- ``SEC_INT_DESC_IN_FCONF``: This flag determines whether to configure Group 0 + and Group1 secure interrupts using the firmware configuration framework. The + platform specific secure interrupt property descriptor is retrieved from + device tree in runtime rather than depending on static C structure at compile + time. + +- ``USE_ROMLIB``: This flag determines whether library at ROM will be used. + This feature creates a library of functions to be placed in ROM and thus + reduces SRAM usage. Refer to :ref:`Library at ROM` for further details. Default + is 0. + +- ``V``: Verbose build. If assigned anything other than 0, the build commands + are printed. Default is 0. + +- ``VERSION_STRING``: String used in the log output for each TF-A image. + Defaults to a string formed by concatenating the version number, build type + and build string. + +- ``W``: Warning level. Some compiler warning options of interest have been + regrouped and put in the root Makefile. This flag can take the values 0 to 3, + each level enabling more warning options. Default is 0. + +- ``WARMBOOT_ENABLE_DCACHE_EARLY`` : Boolean option to enable D-cache early on + the CPU after warm boot. This is applicable for platforms which do not + require interconnect programming to enable cache coherency (eg: single + cluster platforms). If this option is enabled, then warm boot path + enables D-caches immediately after enabling MMU. This option defaults to 0. + +- ``SUPPORT_STACK_MEMTAG``: This flag determines whether to enable memory + tagging for stack or not. It accepts 2 values: ``yes`` and ``no``. The + default value of this flag is ``no``. Note this option must be enabled only + for ARM architecture greater than Armv8.5-A. + +- ``ERRATA_SPECULATIVE_AT``: This flag determines whether to enable ``AT`` + speculative errata workaround or not. It accepts 2 values: ``1`` and ``0``. + The default value of this flag is ``0``. + + ``AT`` speculative errata workaround disables stage1 page table walk for + lower ELs (EL1 and EL0) in EL3 so that ``AT`` speculative fetch at any point + produces either the correct result or failure without TLB allocation. + + This boolean option enables errata for all below CPUs. + + +---------+--------------+-------------------------+ + | Errata | CPU | Workaround Define | + +=========+==============+=========================+ + | 1165522 | Cortex-A76 | ``ERRATA_A76_1165522`` | + +---------+--------------+-------------------------+ + | 1319367 | Cortex-A72 | ``ERRATA_A72_1319367`` | + +---------+--------------+-------------------------+ + | 1319537 | Cortex-A57 | ``ERRATA_A57_1319537`` | + +---------+--------------+-------------------------+ + | 1530923 | Cortex-A55 | ``ERRATA_A55_1530923`` | + +---------+--------------+-------------------------+ + | 1530924 | Cortex-A53 | ``ERRATA_A53_1530924`` | + +---------+--------------+-------------------------+ + + .. note:: + This option is enabled by build only if platform sets any of above defines + mentioned in ’Workaround Define' column in the table. + If this option is enabled for the EL3 software then EL2 software also must + implement this workaround due to the behaviour of the errata mentioned + in new SDEN document which will get published soon. + +- ``RAS_TRAP_LOWER_EL_ERR_ACCESS``: This flag enables/disables the SCR_EL3.TERR + bit, to trap access to the RAS ERR and RAS ERX registers from lower ELs. + This flag is disabled by default. + +- ``OPENSSL_DIR``: This flag is used to provide the installed openssl directory + path on the host machine which is used to build certificate generation and + firmware encryption tool. + +- ``USE_SP804_TIMER``: Use the SP804 timer instead of the Generic Timer for + functions that wait for an arbitrary time length (udelay and mdelay). The + default value is 0. + +- ``ENABLE_TRBE_FOR_NS``: This flag is used to enable access of trace buffer + control registers from NS ELs, NS-EL2 or NS-EL1(when NS-EL2 is implemented + but unused) when FEAT_TRBE is implemented. TRBE is an optional architectural + feature for AArch64. The default is 0 and it is automatically disabled when + the target architecture is AArch32. + +- ``ENABLE_SYS_REG_TRACE_FOR_NS``: Boolean option to enable trace system + registers access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented + but unused). This feature is available if trace unit such as ETMv4.x, and + ETE(extending ETM feature) is implemented. This flag is disabled by default. + +- ``ENABLE_TRF_FOR_NS``: Boolean option to enable trace filter control registers + access from NS ELs, NS-EL2 or NS-EL1 (when NS-EL2 is implemented but unused), + if FEAT_TRF is implemented. This flag is disabled by default. + +GICv3 driver options +-------------------- + +GICv3 driver files are included using directive: + +``include drivers/arm/gic/v3/gicv3.mk`` + +The driver can be configured with the following options set in the platform +makefile: + +- ``GICV3_SUPPORT_GIC600``: Add support for the GIC-600 variants of GICv3. + Enabling this option will add runtime detection support for the + GIC-600, so is safe to select even for a GIC500 implementation. + This option defaults to 0. + +- ``GICV3_SUPPORT_GIC600AE_FMU``: Add support for the Fault Management Unit + for GIC-600 AE. Enabling this option will introduce support to initialize + the FMU. Platforms should call the init function during boot to enable the + FMU and its safety mechanisms. This option defaults to 0. + +- ``GICV3_IMPL_GIC600_MULTICHIP``: Selects GIC-600 variant with multichip + functionality. This option defaults to 0 + +- ``GICV3_OVERRIDE_DISTIF_PWR_OPS``: Allows override of default implementation + of ``arm_gicv3_distif_pre_save`` and ``arm_gicv3_distif_post_restore`` + functions. This is required for FVP platform which need to simulate GIC save + and restore during SYSTEM_SUSPEND without powering down GIC. Default is 0. + +- ``GIC_ENABLE_V4_EXTN`` : Enables GICv4 related changes in GICv3 driver. + This option defaults to 0. + +- ``GIC_EXT_INTID``: When set to ``1``, GICv3 driver will support extended + PPI (1056-1119) and SPI (4096-5119) range. This option defaults to 0. + +Debugging options +----------------- + +To compile a debug version and make the build more verbose use + +.. code:: shell + + make PLAT= DEBUG=1 V=1 all + +AArch64 GCC uses DWARF version 4 debugging symbols by default. Some tools (for +example DS-5) might not support this and may need an older version of DWARF +symbols to be emitted by GCC. This can be achieved by using the +``-gdwarf-`` flag, with the version being set to 2 or 3. Setting the +version to 2 is recommended for DS-5 versions older than 5.16. + +When debugging logic problems it might also be useful to disable all compiler +optimizations by using ``-O0``. + +.. warning:: + Using ``-O0`` could cause output images to be larger and base addresses + might need to be recalculated (see the **Memory layout on Arm development + platforms** section in the :ref:`Firmware Design`). + +Extra debug options can be passed to the build system by setting ``CFLAGS`` or +``LDFLAGS``: + +.. code:: shell + + CFLAGS='-O0 -gdwarf-2' \ + make PLAT= DEBUG=1 V=1 all + +Note that using ``-Wl,`` style compilation driver options in ``CFLAGS`` will be +ignored as the linker is called directly. + +It is also possible to introduce an infinite loop to help in debugging the +post-BL2 phase of TF-A. This can be done by rebuilding BL1 with the +``SPIN_ON_BL1_EXIT=1`` build flag. Refer to the :ref:`build_options_common` +section. In this case, the developer may take control of the target using a +debugger when indicated by the console output. When using DS-5, the following +commands can be used: + +:: + + # Stop target execution + interrupt + + # + # Prepare your debugging environment, e.g. set breakpoints + # + + # Jump over the debug loop + set var $AARCH64::$Core::$PC = $AARCH64::$Core::$PC + 4 + + # Resume execution + continue + +Firmware update options +----------------------- + +- ``NR_OF_FW_BANKS``: Define the number of firmware banks. This flag is used + in defining the firmware update metadata structure. This flag is by default + set to '2'. + +- ``NR_OF_IMAGES_IN_FW_BANK``: Define the number of firmware images in each + firmware bank. Each firmware bank must have the same number of images as per + the `PSA FW update specification`_. + This flag is used in defining the firmware update metadata structure. This + flag is by default set to '1'. + +- ``PSA_FWU_SUPPORT``: Enable the firmware update mechanism as per the + `PSA FW update specification`_. The default value is 0, and this is an + experimental feature. + PSA firmware update implementation has some limitations, such as BL2 is + not part of the protocol-updatable images, if BL2 needs to be updated, then + it should be done through another platform-defined mechanism, and it assumes + that the platform's hardware supports CRC32 instructions. + +-------------- + +*Copyright (c) 2019-2022, Arm Limited. All rights reserved.* + +.. _DEN0115: https://developer.arm.com/docs/den0115/latest +.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/ diff --git a/arm-trusted-firmware/docs/getting_started/docs-build.rst b/arm-trusted-firmware/docs/getting_started/docs-build.rst new file mode 100644 index 0000000..87c677f --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/docs-build.rst @@ -0,0 +1,115 @@ +Building Documentation +====================== + +To create a rendered copy of this documentation locally you can use the +`Sphinx`_ tool to build and package the plain-text documents into HTML-formatted +pages. + +If you are building the documentation for the first time then you will need to +check that you have the required software packages, as described in the +*Prerequisites* section that follows. + +.. note:: + An online copy of the documentation is available at + https://www.trustedfirmware.org/docs/tf-a, if you want to view a rendered + copy without doing a local build. + +Prerequisites +------------- + +For building a local copy of the |TF-A| documentation you will need, at minimum: + +- Python 3 (3.5 or later) +- PlantUML (1.2017.15 or later) + +Optionally, the `Dia`_ application can be installed if you need to edit +existing ``.dia`` diagram files, or create new ones. + +You must also install the Python modules that are specified in the +``requirements.txt`` file in the root of the ``docs`` directory. These modules +can be installed using ``pip3`` (the Python Package Installer). Passing this +requirements file as an argument to ``pip3`` automatically installs the specific +module versions required by |TF-A|. + +An example set of installation commands for Ubuntu 18.04 LTS follows, assuming +that the working directory is ``docs``: + +.. code:: shell + + sudo apt install python3 python3-pip plantuml [dia] + pip3 install [--user] -r requirements.txt + +.. note:: + Several other modules will be installed as dependencies. Please review + the list to ensure that there will be no conflicts with other modules already + installed in your environment. + +Passing the optional ``--user`` argument to ``pip3`` will install the Python +packages only for the current user. Omitting this argument will attempt to +install the packages globally and this will likely require the command to be run +as root or using ``sudo``. + +.. note:: + More advanced usage instructions for *pip* are beyond the scope of this + document but you can refer to the `pip homepage`_ for detailed guides. + +Building rendered documentation +------------------------------- + +Documents can be built into HTML-formatted pages from project root directory by +running the following command. + +.. code:: shell + + make doc + +Output from the build process will be placed in: + +:: + + docs/build/html + +We also support building documentation in other formats. From the ``docs`` +directory of the project, run the following command to see the supported +formats. It is important to note that you will not get the correct result if +the command is run from the project root directory, as that would invoke the +top-level Makefile for |TF-A| itself. + +.. code:: shell + + make help + +Building rendered documentation from a container +------------------------------------------------ + +There may be cases where you can not either install or upgrade required +dependencies to generate the documents, so in this case, one way to +create the documentation is through a docker container. The first step is +to check if `docker`_ is installed in your host, otherwise check main docker +page for installation instructions. Once installed, run the following script +from project root directory + +.. code:: shell + + docker run --rm -v $PWD:/TF sphinxdoc/sphinx \ + bash -c 'cd /TF && \ + pip3 install plantuml -r ./docs/requirements.txt && make doc' + +The above command fetches the ``sphinxdoc/sphinx`` container from `docker +hub`_, launches the container, installs documentation requirements and finally +creates the documentation. Once done, exit the container and output from the +build process will be placed in: + +:: + + docs/build/html + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* + +.. _Sphinx: http://www.sphinx-doc.org/en/master/ +.. _pip homepage: https://pip.pypa.io/en/stable/ +.. _Dia: https://wiki.gnome.org/Apps/Dia +.. _docker: https://www.docker.com/ +.. _docker hub: https://hub.docker.com/repository/docker/sphinxdoc/sphinx diff --git a/arm-trusted-firmware/docs/getting_started/image-terminology.rst b/arm-trusted-firmware/docs/getting_started/image-terminology.rst new file mode 100644 index 0000000..a90ec0b --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/image-terminology.rst @@ -0,0 +1,183 @@ +Image Terminology +================= + +This page contains the current name, abbreviated name and purpose of the various +images referred to in the Trusted Firmware project. + +General Notes +------------- + +- Some of the names and abbreviated names have changed to accommodate new + requirements. The changed names are as backward compatible as possible to + minimize confusion. Where applicable, the previous names are indicated. Some + code, documentation and build artefacts may still refer to the previous names; + these will inevitably take time to catch up. + +- The main name change is to prefix each image with the processor it corresponds + to (for example ``AP_``, ``SCP_``, ...). In situations where there is no + ambiguity (for example, within AP specific code/documentation), it is + permitted to omit the processor prefix (for example, just BL1 instead of + ``AP_BL1``). + +- Previously, the format for 3rd level images had 2 forms; ``BL3`` was either + suffixed with a dash ("-") followed by a number (for example, ``BL3-1``) or a + subscript number, depending on whether rich text formatting was available. + This was confusing and often the dash gets omitted in practice. Therefore the + new form is to just omit the dash and not use subscript formatting. + +- The names no longer contain dash ("-") characters at all. In some places (for + example, function names) it's not possible to use this character. All dashes + are either removed or replaced by underscores ("_"). + +- The abbreviation BL stands for BootLoader. This is a historical anomaly. + Clearly, many of these images are not BootLoaders, they are simply firmware + images. However, the BL abbreviation is now widely used and is retained for + backwards compatibility. + +- The image names are not case sensitive. For example, ``bl1`` is + interchangeable with ``BL1``, although mixed case should be avoided. + +Trusted Firmware Images +----------------------- + +AP Boot ROM: ``AP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the AP and cannot be modified. +Its primary purpose is to perform the minimum initialization necessary to load +and authenticate an updateable AP firmware image into an executable RAM +location, then hand-off control to that image. + +AP RAM Firmware: ``AP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP firmware. It is currently also known as the "Trusted +Boot Firmware". Its primary purpose is to perform any additional initialization +required to load and authenticate all 3rd level firmware images into their +executable RAM locations, then hand-off control to the EL3 Runtime Firmware. + +EL3 Runtime Firmware: ``AP_BL31`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Also known as "SoC AP firmware" or "EL3 monitor firmware". Its primary purpose +is to handle transitions between the normal and secure world. + +Secure-EL1 Payload (SP): ``AP_BL32`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically this is a TEE or Trusted OS, providing runtime secure services to the +normal world. However, it may refer to a more abstract Secure-EL1 Payload (SP). +Note that this abbreviation should only be used in systems where there is a +single or primary image executing at Secure-EL1. In systems where there are +potentially multiple SPs and there is no concept of a primary SP, this +abbreviation should be avoided; use the recommended **Other AP 3rd level +images** abbreviation instead. + +AP Normal World Firmware: ``AP_BL33`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For example, UEFI or uboot. Its primary purpose is to boot a normal world OS. + +Other AP 3rd level images: ``AP_BL3_XXX`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The abbreviated names of the existing 3rd level images imply a load/execution +ordering (for example, ``AP_BL31 -> AP_BL32 -> AP_BL33``). Some systems may +have additional images and/or a different load/execution ordering. The +abbreviated names of the existing images are retained for backward compatibility +but new 3rd level images should be suffixed with an underscore followed by text +identifier, not a number. + +In systems where 3rd level images are provided by different vendors, the +abbreviated name should identify the vendor as well as the image +function. For example, ``AP_BL3_ARM_RAS``. + +Realm Monitor Management Firmware: ``RMM`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the Realm-EL2 firmware. It is required if +:ref:`Realm Management Extension (RME)` feature is enabled. If a path to RMM +image is not provided, TF-A builds Test Realm Payload (TRP) image by default +and uses it as the RMM image. + +SCP Boot ROM: ``SCP_BL1`` (previously ``BL0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first code to execute on the SCP and cannot be modified. +Its primary purpose is to perform the minimum initialization necessary to load +and authenticate an updateable SCP firmware image into an executable RAM +location, then hand-off control to that image. This may be performed in +conjunction with other processor firmware (for example, ``AP_BL1`` and +``AP_BL2``). + +This image was previously abbreviated as ``BL0`` but in some systems, the SCP +may directly load/authenticate its own firmware. In these systems, it doesn't +make sense to interleave the image terminology for AP and SCP; both AP and SCP +Boot ROMs are ``BL1`` from their own point of view. + +SCP RAM Firmware: ``SCP_BL2`` (previously ``BL3-0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage SCP firmware. It is currently also known as the "SCP +runtime firmware" but it could potentially be an intermediate firmware if the +SCP needs to load/authenticate multiple 3rd level images in future. + +This image was previously abbreviated as BL3-0 but from the SCP's point of view, +this has always been the 2nd stage firmware. The previous name is too +AP-centric. + +Firmware Update (FWU) Images +---------------------------- + +The terminology for these images has not been widely adopted yet but they have +to be considered in a production Trusted Board Boot solution. + +AP Firmware Update Boot ROM: ``AP_NS_BL1U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Typically, this is the first normal world code to execute on the AP during a +firmware update operation, and cannot be modified. Its primary purpose is to +load subsequent firmware update images from an external interface and communicate +with ``AP_BL1`` to authenticate those images. + +During firmware update, there are (potentially) multiple transitions between the +secure and normal world. The "level" of the BL image is relative to the world +it's in so it makes sense to encode "NS" in the normal world images. The absence +of "NS" implies a secure world image. + +AP Firmware Update Config: ``AP_BL2U`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary AP secure world configuration required to +complete the firmware update operation. It is potentially a subset of ``AP_BL2`` +functionality. + +SCP Firmware Update Config: ``SCP_BL2U`` (previously ``BL2-U0``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This image does the minimum necessary SCP secure world configuration required to +complete the firmware update operation. It is potentially a subset of +``SCP_BL2`` functionality. + +AP Firmware Updater: ``AP_NS_BL2U`` (previously ``BL3-U``) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the 2nd stage AP normal world firmware updater. Its primary purpose is +to load a new set of firmware images from an external interface and write them +into non-volatile storage. + +Other Processor Firmware Images +------------------------------- + +Some systems may have additional processors to the AP and SCP. For example, a +Management Control Processor (MCP). Images for these processors should follow +the same terminology, with the processor abbreviation prefix, followed by +underscore and the level of the firmware image. + +For example, + +MCP Boot ROM: ``MCP_BL1`` +~~~~~~~~~~~~~~~~~~~~~~~~~ + +MCP RAM Firmware: ``MCP_BL2`` +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/arm-trusted-firmware/docs/getting_started/index.rst b/arm-trusted-firmware/docs/getting_started/index.rst new file mode 100644 index 0000000..817beaf --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/index.rst @@ -0,0 +1,21 @@ +Getting Started +=============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + prerequisites + docs-build + tools-build + initial-build + build-options + image-terminology + porting-guide + psci-lib-integration-guide + rt-svc-writers-guide + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/getting_started/initial-build.rst b/arm-trusted-firmware/docs/getting_started/initial-build.rst new file mode 100644 index 0000000..d4a8f01 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/initial-build.rst @@ -0,0 +1,118 @@ +Performing an Initial Build +=========================== + +- Before building TF-A, the environment variable ``CROSS_COMPILE`` must point + to the Linaro cross compiler. + + For AArch64: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + For AArch32: + + .. code:: shell + + export CROSS_COMPILE=/bin/arm-none-eabi- + + It is possible to build TF-A using Clang or Arm Compiler 6. To do so + ``CC`` needs to point to the clang or armclang binary, which will + also select the clang or armclang assembler. Be aware that for Arm Compiler, + the GNU linker is used by default. However for Clang LLVM linker (LLD) + is used by default. In case of being needed the linker can be overridden + using the ``LD`` variable. LLVM linker (LLD) version 9 is + known to work with TF-A. + + In both cases ``CROSS_COMPILE`` should be set as described above. + + Arm Compiler 6 will be selected when the base name of the path assigned + to ``CC`` matches the string 'armclang'. + + For AArch64 using Arm Compiler 6: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + make CC=/bin/armclang PLAT= all + + Clang will be selected when the base name of the path assigned to ``CC`` + contains the string 'clang'. This is to allow both clang and clang-X.Y + to work. + + For AArch64 using clang: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + make CC=/bin/clang PLAT= all + +- Change to the root directory of the TF-A source tree and build. + + For AArch64: + + .. code:: shell + + make PLAT= all + + For AArch32: + + .. code:: shell + + make PLAT= ARCH=aarch32 AARCH32_SP=sp_min all + + Notes: + + - If ``PLAT`` is not specified, ``fvp`` is assumed by default. See the + :ref:`Build Options` document for more information on available build + options. + + - (AArch32 only) Currently only ``PLAT=fvp`` is supported. + + - (AArch32 only) ``AARCH32_SP`` is the AArch32 EL3 Runtime Software and it + corresponds to the BL32 image. A minimal ``AARCH32_SP``, sp_min, is + provided by TF-A to demonstrate how PSCI Library can be integrated with + an AArch32 EL3 Runtime Software. Some AArch32 EL3 Runtime Software may + include other runtime services, for example Trusted OS services. A guide + to integrate PSCI library with AArch32 EL3 Runtime Software can be found + at :ref:`PSCI Library Integration guide for Armv8-A AArch32 systems`. + + - (AArch64 only) The TSP (Test Secure Payload), corresponding to the BL32 + image, is not compiled in by default. Refer to the + :ref:`Test Secure Payload (TSP) and Dispatcher (TSPD)` document for + details on building the TSP. + + - By default this produces a release version of the build. To produce a + debug version instead, refer to the "Debugging options" section below. + + - The build process creates products in a ``build`` directory tree, building + the objects and binaries for each boot loader stage in separate + sub-directories. The following boot loader binary files are created + from the corresponding ELF files: + + - ``build///bl1.bin`` + - ``build///bl2.bin`` + - ``build///bl31.bin`` (AArch64 only) + - ``build///bl32.bin`` (mandatory for AArch32) + + where ```` is the name of the chosen platform and ```` + is either ``debug`` or ``release``. The actual number of images might differ + depending on the platform. + +- Build products for a specific build variant can be removed using: + + .. code:: shell + + make DEBUG= PLAT= clean + + ... where ```` is ``0`` or ``1``, as specified when building. + + The build tree can be removed completely using: + + .. code:: shell + + make realclean + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/getting_started/porting-guide.rst b/arm-trusted-firmware/docs/getting_started/porting-guide.rst new file mode 100644 index 0000000..3d3b2e3 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/porting-guide.rst @@ -0,0 +1,3215 @@ +Porting Guide +============= + +Introduction +------------ + +Porting Trusted Firmware-A (TF-A) to a new platform involves making some +mandatory and optional modifications for both the cold and warm boot paths. +Modifications consist of: + +- Implementing a platform-specific function or variable, +- Setting up the execution context in a certain way, or +- Defining certain constants (for example #defines). + +The platform-specific functions and variables are declared in +``include/plat/common/platform.h``. The firmware provides a default +implementation of variables and functions to fulfill the optional requirements. +These implementations are all weakly defined; they are provided to ease the +porting effort. Each platform port can override them with its own implementation +if the default implementation is inadequate. + +Some modifications are common to all Boot Loader (BL) stages. Section 2 +discusses these in detail. The subsequent sections discuss the remaining +modifications for each BL stage in detail. + +Please refer to the :ref:`Platform Compatibility Policy` for the policy +regarding compatibility and deprecation of these porting interfaces. + +Only Arm development platforms (such as FVP and Juno) may use the +functions/definitions in ``include/plat/arm/common/`` and the corresponding +source files in ``plat/arm/common/``. This is done so that there are no +dependencies between platforms maintained by different people/companies. If you +want to use any of the functionality present in ``plat/arm`` files, please +create a pull request that moves the code to ``plat/common`` so that it can be +discussed. + +Common modifications +-------------------- + +This section covers the modifications that should be made by the platform for +each BL stage to correctly port the firmware stack. They are categorized as +either mandatory or optional. + +Common mandatory modifications +------------------------------ + +A platform port must enable the Memory Management Unit (MMU) as well as the +instruction and data caches for each BL stage. Setting up the translation +tables is the responsibility of the platform port because memory maps differ +across platforms. A memory translation library (see ``lib/xlat_tables/``) is +provided to help in this setup. + +Note that although this library supports non-identity mappings, this is intended +only for re-mapping peripheral physical addresses and allows platforms with high +I/O addresses to reduce their virtual address space. All other addresses +corresponding to code and data must currently use an identity mapping. + +Also, the only translation granule size supported in TF-A is 4KB, as various +parts of the code assume that is the case. It is not possible to switch to +16 KB or 64 KB granule sizes at the moment. + +In Arm standard platforms, each BL stage configures the MMU in the +platform-specific architecture setup function, ``blX_plat_arch_setup()``, and uses +an identity mapping for all addresses. + +If the build option ``USE_COHERENT_MEM`` is enabled, each platform can allocate a +block of identity mapped secure memory with Device-nGnRE attributes aligned to +page boundary (4K) for each BL stage. All sections which allocate coherent +memory are grouped under ``coherent_ram``. For ex: Bakery locks are placed in a +section identified by name ``bakery_lock`` inside ``coherent_ram`` so that its +possible for the firmware to place variables in it using the following C code +directive: + +:: + + __section("bakery_lock") + +Or alternatively the following assembler code directive: + +:: + + .section bakery_lock + +The ``coherent_ram`` section is a sum of all sections like ``bakery_lock`` which are +used to allocate any data structures that are accessed both when a CPU is +executing with its MMU and caches enabled, and when it's running with its MMU +and caches disabled. Examples are given below. + +The following variables, functions and constants must be defined by the platform +for the firmware to work correctly. + +File : platform_def.h [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure that a header file of this name is in the system +include path with the following constants defined. This will require updating +the list of ``PLAT_INCLUDES`` in the ``platform.mk`` file. + +Platform ports may optionally use the file ``include/plat/common/common_def.h``, +which provides typical values for some of the constants below. These values are +likely to be suitable for all platform ports. + +- **#define : PLATFORM_LINKER_FORMAT** + + Defines the linker format used by the platform, for example + ``elf64-littleaarch64``. + +- **#define : PLATFORM_LINKER_ARCH** + + Defines the processor architecture for the linker by the platform, for + example ``aarch64``. + +- **#define : PLATFORM_STACK_SIZE** + + Defines the normal stack memory available to each CPU. This constant is used + by ``plat/common/aarch64/platform_mp_stack.S`` and + ``plat/common/aarch64/platform_up_stack.S``. + +- **#define : CACHE_WRITEBACK_GRANULE** + + Defines the size in bits of the largest cache line across all the cache + levels in the platform. + +- **#define : FIRMWARE_WELCOME_STR** + + Defines the character string printed by BL1 upon entry into the ``bl1_main()`` + function. + +- **#define : PLATFORM_CORE_COUNT** + + Defines the total number of CPUs implemented by the platform across all + clusters in the system. + +- **#define : PLAT_NUM_PWR_DOMAINS** + + Defines the total number of nodes in the power domain topology + tree at all the power domain levels used by the platform. + This macro is used by the PSCI implementation to allocate + data structures to represent power domain topology. + +- **#define : PLAT_MAX_PWR_LVL** + + Defines the maximum power domain level that the power management operations + should apply to. More often, but not always, the power domain level + corresponds to affinity level. This macro allows the PSCI implementation + to know the highest power domain level that it should consider for power + management operations in the system that the platform implements. For + example, the Base AEM FVP implements two clusters with a configurable + number of CPUs and it reports the maximum power domain level as 1. + +- **#define : PLAT_MAX_OFF_STATE** + + Defines the local power state corresponding to the deepest power down + possible at every power domain level in the platform. The local power + states for each level may be sparsely allocated between 0 and this value + with 0 being reserved for the RUN state. The PSCI implementation uses this + value to initialize the local power states of the power domain nodes and + to specify the requested power state for a PSCI_CPU_OFF call. + +- **#define : PLAT_MAX_RET_STATE** + + Defines the local power state corresponding to the deepest retention state + possible at every power domain level in the platform. This macro should be + a value less than PLAT_MAX_OFF_STATE and greater than 0. It is used by the + PSCI implementation to distinguish between retention and power down local + power states within PSCI_CPU_SUSPEND call. + +- **#define : PLAT_MAX_PWR_LVL_STATES** + + Defines the maximum number of local power states per power domain level + that the platform supports. The default value of this macro is 2 since + most platforms just support a maximum of two local power states at each + power domain level (power-down and retention). If the platform needs to + account for more local power states, then it must redefine this macro. + + Currently, this macro is used by the Generic PSCI implementation to size + the array used for PSCI_STAT_COUNT/RESIDENCY accounting. + +- **#define : BL1_RO_BASE** + + Defines the base address in secure ROM where BL1 originally lives. Must be + aligned on a page-size boundary. + +- **#define : BL1_RO_LIMIT** + + Defines the maximum address in secure ROM that BL1's actual content (i.e. + excluding any data section allocated at runtime) can occupy. + +- **#define : BL1_RW_BASE** + + Defines the base address in secure RAM where BL1's read-write data will live + at runtime. Must be aligned on a page-size boundary. + +- **#define : BL1_RW_LIMIT** + + Defines the maximum address in secure RAM that BL1's read-write data can + occupy at runtime. + +- **#define : BL2_BASE** + + Defines the base address in secure RAM where BL1 loads the BL2 binary image. + Must be aligned on a page-size boundary. This constant is not applicable + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_LIMIT** + + Defines the maximum address in secure RAM that the BL2 image can occupy. + This constant is not applicable when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_BASE** + + Defines the base address in secure XIP memory where BL2 RO section originally + lives. Must be aligned on a page-size boundary. This constant is only needed + when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RO_LIMIT** + + Defines the maximum address in secure XIP memory that BL2's actual content + (i.e. excluding any data section allocated at runtime) can occupy. This + constant is only needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_BASE** + + Defines the base address in secure RAM where BL2's read-write data will live + at runtime. Must be aligned on a page-size boundary. This constant is only + needed when BL2_IN_XIP_MEM is set to '1'. + +- **#define : BL2_RW_LIMIT** + + Defines the maximum address in secure RAM that BL2's read-write data can + occupy at runtime. This constant is only needed when BL2_IN_XIP_MEM is set + to '1'. + +- **#define : BL31_BASE** + + Defines the base address in secure RAM where BL2 loads the BL31 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL31_LIMIT** + + Defines the maximum address in secure RAM that the BL31 image can occupy. + +For every image, the platform must define individual identifiers that will be +used by BL1 or BL2 to load the corresponding image into memory from non-volatile +storage. For the sake of performance, integer numbers will be used as +identifiers. The platform will use those identifiers to return the relevant +information about the image to be loaded (file handler, load address, +authentication information, etc.). The following image identifiers are +mandatory: + +- **#define : BL2_IMAGE_ID** + + BL2 image identifier, used by BL1 to load BL2. + +- **#define : BL31_IMAGE_ID** + + BL31 image identifier, used by BL2 to load BL31. + +- **#define : BL33_IMAGE_ID** + + BL33 image identifier, used by BL2 to load BL33. + +If Trusted Board Boot is enabled, the following certificate identifiers must +also be defined: + +- **#define : TRUSTED_BOOT_FW_CERT_ID** + + BL2 content certificate identifier, used by BL1 to load the BL2 content + certificate. + +- **#define : TRUSTED_KEY_CERT_ID** + + Trusted key certificate identifier, used by BL2 to load the trusted key + certificate. + +- **#define : SOC_FW_KEY_CERT_ID** + + BL31 key certificate identifier, used by BL2 to load the BL31 key + certificate. + +- **#define : SOC_FW_CONTENT_CERT_ID** + + BL31 content certificate identifier, used by BL2 to load the BL31 content + certificate. + +- **#define : NON_TRUSTED_FW_KEY_CERT_ID** + + BL33 key certificate identifier, used by BL2 to load the BL33 key + certificate. + +- **#define : NON_TRUSTED_FW_CONTENT_CERT_ID** + + BL33 content certificate identifier, used by BL2 to load the BL33 content + certificate. + +- **#define : FWU_CERT_ID** + + Firmware Update (FWU) certificate identifier, used by NS_BL1U to load the + FWU content certificate. + +- **#define : PLAT_CRYPTOCELL_BASE** + + This defines the base address of Arm® TrustZone® CryptoCell and must be + defined if CryptoCell crypto driver is used for Trusted Board Boot. For + capable Arm platforms, this driver is used if ``ARM_CRYPTOCELL_INTEG`` is + set. + +If the AP Firmware Updater Configuration image, BL2U is used, the following +must also be defined: + +- **#define : BL2U_BASE** + + Defines the base address in secure memory where BL1 copies the BL2U binary + image. Must be aligned on a page-size boundary. + +- **#define : BL2U_LIMIT** + + Defines the maximum address in secure memory that the BL2U image can occupy. + +- **#define : BL2U_IMAGE_ID** + + BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to BL2U. + +If the SCP Firmware Update Configuration Image, SCP_BL2U is used, the following +must also be defined: + +- **#define : SCP_BL2U_IMAGE_ID** + + SCP_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to SCP_BL2U. + + .. note:: + TF-A does not provide source code for this image. + +If the Non-Secure Firmware Updater ROM, NS_BL1U is used, the following must +also be defined: + +- **#define : NS_BL1U_BASE** + + Defines the base address in non-secure ROM where NS_BL1U executes. + Must be aligned on a page-size boundary. + + .. note:: + TF-A does not provide source code for this image. + +- **#define : NS_BL1U_IMAGE_ID** + + NS_BL1U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL1U. + +If the Non-Secure Firmware Updater, NS_BL2U is used, the following must also +be defined: + +- **#define : NS_BL2U_BASE** + + Defines the base address in non-secure memory where NS_BL2U executes. + Must be aligned on a page-size boundary. + + .. note:: + TF-A does not provide source code for this image. + +- **#define : NS_BL2U_IMAGE_ID** + + NS_BL2U image identifier, used by BL1 to fetch an image descriptor + corresponding to NS_BL2U. + +For the the Firmware update capability of TRUSTED BOARD BOOT, the following +macros may also be defined: + +- **#define : PLAT_FWU_MAX_SIMULTANEOUS_IMAGES** + + Total number of images that can be loaded simultaneously. If the platform + doesn't specify any value, it defaults to 10. + +If a SCP_BL2 image is supported by the platform, the following constants must +also be defined: + +- **#define : SCP_BL2_IMAGE_ID** + + SCP_BL2 image identifier, used by BL2 to load SCP_BL2 into secure memory + from platform storage before being transferred to the SCP. + +- **#define : SCP_FW_KEY_CERT_ID** + + SCP_BL2 key certificate identifier, used by BL2 to load the SCP_BL2 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : SCP_FW_CONTENT_CERT_ID** + + SCP_BL2 content certificate identifier, used by BL2 to load the SCP_BL2 + content certificate (mandatory when Trusted Board Boot is enabled). + +If a BL32 image is supported by the platform, the following constants must +also be defined: + +- **#define : BL32_IMAGE_ID** + + BL32 image identifier, used by BL2 to load BL32. + +- **#define : TRUSTED_OS_FW_KEY_CERT_ID** + + BL32 key certificate identifier, used by BL2 to load the BL32 key + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : TRUSTED_OS_FW_CONTENT_CERT_ID** + + BL32 content certificate identifier, used by BL2 to load the BL32 content + certificate (mandatory when Trusted Board Boot is enabled). + +- **#define : BL32_BASE** + + Defines the base address in secure memory where BL2 loads the BL32 binary + image. Must be aligned on a page-size boundary. + +- **#define : BL32_LIMIT** + + Defines the maximum address that the BL32 image can occupy. + +If the Test Secure-EL1 Payload (TSP) instantiation of BL32 is supported by the +platform, the following constants must also be defined: + +- **#define : TSP_SEC_MEM_BASE** + + Defines the base address of the secure memory used by the TSP image on the + platform. This must be at the same address or below ``BL32_BASE``. + +- **#define : TSP_SEC_MEM_SIZE** + + Defines the size of the secure memory used by the BL32 image on the + platform. ``TSP_SEC_MEM_BASE`` and ``TSP_SEC_MEM_SIZE`` must fully + accommodate the memory required by the BL32 image, defined by ``BL32_BASE`` + and ``BL32_LIMIT``. + +- **#define : TSP_IRQ_SEC_PHY_TIMER** + + Defines the ID of the secure physical generic timer interrupt used by the + TSP's interrupt handling code. + +If the platform port uses the translation table library code, the following +constants must also be defined: + +- **#define : PLAT_XLAT_TABLES_DYNAMIC** + + Optional flag that can be set per-image to enable the dynamic allocation of + regions even when the MMU is enabled. If not defined, only static + functionality will be available, if defined and set to 1 it will also + include the dynamic functionality. + +- **#define : MAX_XLAT_TABLES** + + 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 ``PLAT_XLAT_TABLES_DYNAMIC`` flag is enabled for a BL + image, ``MAX_XLAT_TABLES`` must be defined to accommodate the dynamic regions + as well. + +- **#define : MAX_MMAP_REGIONS** + + 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. If ``PLAT_XLAT_TABLES_DYNAMIC`` flag is + enabled for a BL image, ``MAX_MMAP_REGIONS`` must be defined to accommodate + the dynamic regions as well. + +- **#define : PLAT_VIRT_ADDR_SPACE_SIZE** + + Defines the total size of the virtual address space in bytes. For example, + for a 32 bit virtual address space, this value should be ``(1ULL << 32)``. + +- **#define : PLAT_PHY_ADDR_SPACE_SIZE** + + Defines the total size of the physical address space in bytes. For example, + for a 32 bit physical address space, this value should be ``(1ULL << 32)``. + +If the platform port uses the IO storage framework, the following constants +must also be defined: + +- **#define : MAX_IO_DEVICES** + + Defines the maximum number of registered IO devices. Attempting to register + more devices than this value using ``io_register_device()`` will fail with + -ENOMEM. + +- **#define : MAX_IO_HANDLES** + + Defines the maximum number of open IO handles. Attempting to open more IO + entities than this value using ``io_open()`` will fail with -ENOMEM. + +- **#define : MAX_IO_BLOCK_DEVICES** + + Defines the maximum number of registered IO block devices. Attempting to + register more devices this value using ``io_dev_open()`` will fail + with -ENOMEM. MAX_IO_BLOCK_DEVICES should be less than MAX_IO_DEVICES. + With this macro, multiple block devices could be supported at the same + time. + +If the platform needs to allocate data within the per-cpu data framework in +BL31, it should define the following macro. Currently this is only required if +the platform decides not to use the coherent memory section by undefining the +``USE_COHERENT_MEM`` build flag. In this case, the framework allocates the +required memory within the the per-cpu data to minimize wastage. + +- **#define : PLAT_PCPU_DATA_SIZE** + + Defines the memory (in bytes) to be reserved within the per-cpu data + structure for use by the platform layer. + +The following constants are optional. They should be defined when the platform +memory layout implies some image overlaying like in Arm standard platforms. + +- **#define : BL31_PROGBITS_LIMIT** + + Defines the maximum address in secure RAM that the BL31's progbits sections + can occupy. + +- **#define : TSP_PROGBITS_LIMIT** + + Defines the maximum address that the TSP's progbits sections can occupy. + +If the platform port uses the PL061 GPIO driver, the following constant may +optionally be defined: + +- **PLAT_PL061_MAX_GPIOS** + Maximum number of GPIOs required by the platform. This allows control how + much memory is allocated for PL061 GPIO controllers. The default value is + + #. $(eval $(call add_define,PLAT_PL061_MAX_GPIOS)) + +If the platform port uses the partition driver, the following constant may +optionally be defined: + +- **PLAT_PARTITION_MAX_ENTRIES** + Maximum number of partition entries required by the platform. This allows + control how much memory is allocated for partition entries. The default + value is 128. + For example, define the build flag in ``platform.mk``: + PLAT_PARTITION_MAX_ENTRIES := 12 + $(eval $(call add_define,PLAT_PARTITION_MAX_ENTRIES)) + +- **PLAT_PARTITION_BLOCK_SIZE** + The size of partition block. It could be either 512 bytes or 4096 bytes. + The default value is 512. + For example, define the build flag in ``platform.mk``: + PLAT_PARTITION_BLOCK_SIZE := 4096 + $(eval $(call add_define,PLAT_PARTITION_BLOCK_SIZE)) + +The following constant is optional. It should be defined to override the default +behaviour of the ``assert()`` function (for example, to save memory). + +- **PLAT_LOG_LEVEL_ASSERT** + If ``PLAT_LOG_LEVEL_ASSERT`` is higher or equal than ``LOG_LEVEL_VERBOSE``, + ``assert()`` prints the name of the file, the line number and the asserted + expression. Else if it is higher than ``LOG_LEVEL_INFO``, it prints the file + name and the line number. Else if it is lower than ``LOG_LEVEL_INFO``, it + doesn't print anything to the console. If ``PLAT_LOG_LEVEL_ASSERT`` isn't + defined, it defaults to ``LOG_LEVEL``. + +File : plat_macros.S [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Each platform must ensure a file of this name is in the system include path with +the following macro defined. In the Arm development platforms, this file is +found in ``plat/arm/board//include/plat_macros.S``. + +- **Macro : plat_crash_print_regs** + + This macro allows the crash reporting routine to print relevant platform + registers in case of an unhandled exception in BL31. This aids in debugging + and this macro can be defined to be empty in case register reporting is not + desired. + + For instance, GIC or interconnect registers may be helpful for + troubleshooting. + +Handling Reset +-------------- + +BL1 by default implements the reset vector where execution starts from a cold +or warm boot. BL31 can be optionally set as a reset vector using the +``RESET_TO_BL31`` make variable. + +For each CPU, the reset vector code is responsible for the following tasks: + +#. Distinguishing between a cold boot and a warm boot. + +#. In the case of a cold boot and the CPU being a secondary CPU, ensuring that + the CPU is placed in a platform-specific state until the primary CPU + performs the necessary steps to remove it from this state. + +#. In the case of a warm boot, ensuring that the CPU jumps to a platform- + specific address in the BL31 image in the same processor mode as it was + when released from reset. + +The following functions need to be implemented by the platform port to enable +reset vector code to perform the above tasks. + +Function : plat_get_my_entrypoint() [mandatory when PROGRAMMABLE_RESET_ADDRESS == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function is 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. + +This function fulfills requirement 1 and 3 listed above. + +Note that for platforms that support programming the reset address, it is +expected that a CPU will start executing code directly at the right address, +both on a cold and warm reset. In this case, there is no need to identify the +type of reset nor to query the warm reset entrypoint. Therefore, implementing +this function is not required on such platforms. + +Function : plat_secondary_cold_boot_setup() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + +This function is called with the MMU and data caches disabled. It is responsible +for placing the executing secondary CPU in a platform-specific state until the +primary CPU performs the necessary actions to bring it out of that state and +allow entry into the OS. This function must not return. + +In the Arm FVP port, when using the normal boot flow, each secondary CPU powers +itself off. The primary CPU is responsible for powering up the secondary CPUs +when normal world software requires them. When booting an EL3 payload instead, +they stay powered on and are put in a holding pen until their mailbox gets +populated. + +This function fulfills requirement 2 above. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, implementing this +function is not required on such platforms. + +Function : plat_is_my_cpu_primary() [mandatory when COLD_BOOT_SINGLE_CPU == 0] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This function identifies whether the current CPU is the primary CPU or a +secondary CPU. A return value of zero indicates that the CPU is not the +primary CPU, while a non-zero return value indicates that the CPU is the +primary CPU. + +Note that for platforms that can't release secondary CPUs out of reset, only the +primary CPU will execute the cold boot code. Therefore, there is no need to +distinguish between primary and secondary CPUs and implementing this function is +not required. + +Function : platform_mem_init() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called before any access to data is made by the firmware, in +order to carry out any essential memory initialization. + +Function: plat_get_rotpk_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, void **, unsigned int *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns a +pointer to the ROTPK stored in the platform (or a hash of it) and its length. +The ROTPK must be encoded in DER format according to the following ASN.1 +structure: + +:: + + AlgorithmIdentifier ::= SEQUENCE { + algorithm OBJECT IDENTIFIER, + parameters ANY DEFINED BY algorithm OPTIONAL + } + + SubjectPublicKeyInfo ::= SEQUENCE { + algorithm AlgorithmIdentifier, + subjectPublicKey BIT STRING + } + +In case the function returns a hash of the key: + +:: + + 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 : Indicates that the ROTPK returned by the platform is a + hash. + ROTPK_NOT_DEPLOYED : This allows the platform to skip certificate ROTPK + verification while the platform ROTPK is not deployed. + When this flag is set, the function does not need to + return a platform ROTPK, and the authentication + framework uses the ROTPK in the certificate without + verifying it against the platform value. This flag + must not be used in a deployed production environment. + +Function: plat_get_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int * + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It returns the +non-volatile counter value stored in the platform in the second argument. The +cookie in the first argument may be used to select the counter in case the +platform provides more than one (for example, on platforms that use the default +TBBR CoT, the cookie will correspond to the OID values defined in +TRUSTED_FW_NVCOUNTER_OID or NON_TRUSTED_FW_NVCOUNTER_OID). + +The function returns 0 on success. Any other value means the counter value could +not be retrieved from the platform. + +Function: plat_set_nv_ctr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, unsigned int + Return : int + +This function is mandatory when Trusted Board Boot is enabled. It sets a new +counter value in the platform. The cookie in the first argument may be used to +select the counter (as explained in plat_get_nv_ctr()). The second argument is +the updated counter value to be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value could +not be updated. + +Function: plat_set_nv_ctr2() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void *, const auth_img_desc_t *, unsigned int + Return : int + +This function is optional when Trusted Board Boot is enabled. If this +interface is defined, then ``plat_set_nv_ctr()`` need not be defined. The +first argument passed is a cookie and is typically used to +differentiate between a Non Trusted NV Counter and a Trusted NV +Counter. The second argument is a pointer to an authentication image +descriptor and may be used to decide if the counter is allowed to be +updated or not. The third argument is the updated counter value to +be written to the NV counter. + +The function returns 0 on success. Any other value means the counter value +either could not be updated or the authentication image descriptor indicates +that it is not allowed to be updated. + +Common mandatory function modifications +--------------------------------------- + +The following functions are mandatory functions which need to be implemented +by the platform port. + +Function : plat_my_core_pos() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +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 availability 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 +:ref:`PSCI Power Domain Tree Structure`. + +Function : plat_core_pos_by_mpidr() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int + +This function validates the ``MPIDR`` of a CPU and converts it to an index, +which can be used as a CPU-specific linear index into blocks of memory. In +case the ``MPIDR`` is invalid, this function returns -1. This function will only +be invoked by BL31 after the power domain topology is initialized and can +utilize the C runtime environment. For further details about how TF-A +represents the power domain topology and how this relates to the linear CPU +index, please refer :ref:`PSCI Power Domain Tree Structure`. + +Function : plat_get_mbedtls_heap() [when TRUSTED_BOARD_BOOT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments : void **heap_addr, size_t *heap_size + Return : int + +This function is invoked during Mbed TLS library initialisation to get a heap, +by means of a starting address and a size. This heap will then be used +internally by the Mbed TLS library. Hence, each BL stage that utilises Mbed TLS +must be able to provide a heap to it. + +A helper function can be found in `drivers/auth/mbedtls/mbedtls_common.c` in +which a heap is statically reserved during compile time inside every image +(i.e. every BL stage) that utilises Mbed TLS. In this default implementation, +the function simply returns the address and size of this "pre-allocated" heap. +For a platform to use this default implementation, only a call to the helper +from inside plat_get_mbedtls_heap() body is enough and nothing else is needed. + +However, by writting their own implementation, platforms have the potential to +optimise memory usage. For example, on some Arm platforms, the Mbed TLS heap is +shared between BL1 and BL2 stages and, thus, the necessary space is not reserved +twice. + +On success the function should return 0 and a negative error code otherwise. + +Function : plat_get_enc_key_info() [when FW_ENC_STATUS == 0 or 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Arguments : 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 + Return : int + +This function provides a symmetric key (either SSK or BSSK depending on +fw_enc_status) which is invoked during runtime decryption of encrypted +firmware images. `plat/common/plat_bl_common.c` provides a dummy weak +implementation for testing purposes which must be overridden by the platform +trying to implement a real world firmware encryption use-case. + +It also allows the platform to pass symmetric key identifier rather than +actual symmetric key which is useful in cases where the crypto backend provides +secure storage for the symmetric key. So in this case ``ENC_KEY_IS_IDENTIFIER`` +flag must be set in ``flags``. + +In addition to above a platform may also choose to provide an image specific +symmetric key/identifier using img_id. + +On success the function should return 0 and a negative error code otherwise. + +Note that this API depends on ``DECRYPTION_SUPPORT`` build flag. + +Function : plat_fwu_set_images_source() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const struct fwu_metadata *metadata + Return : void + +This function is mandatory when PSA_FWU_SUPPORT is enabled. +It provides a means to retrieve image specification (offset in +non-volatile storage and length) of active/updated images using the passed +FWU metadata, and update I/O policies of active/updated images using retrieved +image specification information. +Further I/O layer operations such as I/O open, I/O read, etc. on these +images rely on this function call. + +In Arm platforms, this function is used to set an I/O policy of the FIP image, +container of all active/updated secure and non-secure images. + +Function : plat_fwu_set_metadata_image_source() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t *dev_handle, + uintptr_t *image_spec + Return : int + +This function is mandatory when PSA_FWU_SUPPORT is enabled. It is +responsible for setting up the platform I/O policy of the requested metadata +image (either FWU_METADATA_IMAGE_ID or BKUP_FWU_METADATA_IMAGE_ID) that will +be used to load this image from the platform's non-volatile storage. + +FWU metadata can not be always stored as a raw image in non-volatile storage +to define its image specification (offset in non-volatile storage and length) +statically in I/O policy. +For example, the FWU metadata image is stored as a partition inside the GUID +partition table image. Its specification is defined in the partition table +that needs to be parsed dynamically. +This function provides a means to retrieve such dynamic information to set +the I/O policy of the FWU metadata image. +Further I/O layer operations such as I/O open, I/O read, etc. on FWU metadata +image relies on this function call. + +It returns '0' on success, otherwise a negative error value on error. +Alongside, returns device handle and image specification from the I/O policy +of the requested FWU metadata image. + +Function : plat_fwu_get_boot_idx() [when PSA_FWU_SUPPORT == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This function is mandatory when PSA_FWU_SUPPORT is enabled. It provides the +means to retrieve the boot index value from the platform. The boot index is the +bank from which the platform has booted the firmware images. + +By default, the platform will read the metadata structure and try to boot from +the active bank. If the platform fails to boot from the active bank due to +reasons like an Authentication failure, or on crossing a set number of watchdog +resets while booting from the active bank, the platform can then switch to boot +from a different bank. This function then returns the bank that the platform +should boot its images from. + +Common optional modifications +----------------------------- + +The following are helper functions implemented by the firmware that perform +common platform-specific tasks. A platform may choose to override these +definitions. + +Function : plat_set_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function sets the current stack pointer to the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in ``plat/common/aarch64/platform_up_stack.S`` and +``plat/common/aarch64/platform_mp_stack.S`` + +Function : plat_get_my_stack() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uintptr_t + +This function returns the base address of the normal memory stack that +has been allocated for the current CPU. For BL images that only require a +stack for the primary CPU, the UP version of the function is used. The size +of the stack allocated to each CPU is specified by the platform defined +constant ``PLATFORM_STACK_SIZE``. + +Common implementations of this function for the UP and MP BL images are +provided in ``plat/common/aarch64/platform_up_stack.S`` and +``plat/common/aarch64/platform_mp_stack.S`` + +Function : plat_report_exception() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : void + +A platform may need to report various information about its status when an +exception is taken, for example the current exception level, the CPU security +state (secure/non-secure), the exception type, and so on. This function is +called in the following circumstances: + +- In BL1, whenever an exception is taken. +- In BL2, whenever an exception is taken. + +The default implementation doesn't do anything, to avoid making assumptions +about the way the platform displays its status information. + +For AArch64, this function receives the exception type as its argument. +Possible values for exceptions types are listed in the +``include/common/bl_common.h`` header file. Note that these constants are not +related to any architectural exception code; they are just a TF-A convention. + +For AArch32, this function receives the exception mode as its argument. +Possible values for exception modes are listed in the +``include/lib/aarch32/arch.h`` header file. + +Function : plat_reset_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +A platform may need to do additional initialization after reset. This function +allows the platform to do the platform specific initializations. Platform +specific errata workarounds could also be implemented here. The API should +preserve the values of callee saved registers x19 to x29. + +The default implementation doesn't do anything. If a platform needs to override +the default implementation, refer to the :ref:`Firmware Design` for general +guidelines. + +Function : plat_disable_acp() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API allows a platform to disable the Accelerator Coherency Port (if +present) during a cluster power down sequence. The default weak implementation +doesn't do anything. Since this API is called during the power down sequence, +it has restrictions for stack usage and it can use the registers x0 - x17 as +scratch registers. It should preserve the value in x18 register as it is used +by the caller to store the return address. + +Function : plat_error_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : void + +This API is called when the generic code encounters an error situation from +which it cannot continue. It allows the platform to perform error reporting or +recovery actions (for example, reset the system). This function must not return. + +The parameter indicates the type of error using standard codes from ``errno.h``. +Possible errors reported by the generic code are: + +- ``-EAUTH``: a certificate or image could not be authenticated (when Trusted + Board Boot is enabled) +- ``-ENOENT``: the requested image or certificate could not be found or an IO + error was detected +- ``-ENOMEM``: resources exhausted. TF-A does not use dynamic memory, so this + error is usually an indication of an incorrect array size + +The default implementation simply spins. + +Function : plat_panic_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is called when the generic code encounters an unexpected error +situation from which it cannot recover. This function must not return, +and must be implemented in assembly because it may be called before the C +environment is initialized. + +.. note:: + The address from where it was called is stored in x30 (Link Register). + The default implementation simply spins. + +Function : plat_get_bl_image_load_info() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_load_info_t * + +This function returns pointer to the list of images that the platform has +populated to load. This function is invoked in BL2 to load the +BL3xx images. + +Function : plat_get_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : bl_params_t * + +This function returns a pointer to the shared memory that the platform has +kept aside to pass TF-A related information that next BL image needs. This +function is invoked in BL2 to pass this information to the next BL +image. + +Function : plat_get_stack_protector_canary() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : u_register_t + +This function returns a random value that is used to initialize the canary used +when the stack protector is enabled with ENABLE_STACK_PROTECTOR. A predictable +value will weaken the protection as the attacker could easily write the right +value as part of the attack most of the time. Therefore, it should return a +true random number. + +.. warning:: + For the protection to be effective, the global data need to be placed at + a lower address than the stack bases. Failure to do so would allow an + attacker to overwrite the canary as part of the stack buffer overflow attack. + +Function : plat_flush_next_bl_params() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function flushes to main memory all the image params that are passed to +next image. This function is invoked in BL2 to flush this information +to the next BL image. + +Function : plat_log_get_prefix() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : const char * + +This function defines the prefix string corresponding to the `log_level` to be +prepended to all the log output from TF-A. The `log_level` (argument) will +correspond to one of the standard log levels defined in debug.h. The platform +can override the common implementation to define a different prefix string for +the log output. The implementation should be robust to future changes that +increase the number of log levels. + +Function : plat_get_soc_version() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int32_t + +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[15:0] = Implementation defined SoC ID + +Function : plat_get_soc_revision() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int32_t + +This function returns soc revision in below format + +:: + + soc_revision[0:30] = SOC revision of specific SOC + +Function : plat_is_smccc_feature_available() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t + Return : int32_t + +This function returns SMC_ARCH_CALL_SUCCESS if the platform supports +the SMCCC function specified in the argument; otherwise returns +SMC_ARCH_CALL_NOT_SUPPORTED. + +Function : plat_mboot_measure_image() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, image_info_t * + Return : int + +When the MEASURED_BOOT flag is enabled: + +- This function measures the given image and records its measurement using + the measured boot backend driver. +- On the Arm FVP port, this function measures the given image using its + passed id and information and then records that measurement in the + Event Log buffer. +- This function must return 0 on success, a signed integer error code + otherwise. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : plat_mboot_measure_critical_data() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const void *, size_t + Return : int + +When the MEASURED_BOOT flag is enabled: + +- This function measures the given critical data structure and records its + measurement using the measured boot backend driver. +- This function must return 0 on success, a signed integer error code + otherwise. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Modifications specific to a Boot Loader stage +--------------------------------------------- + +Boot Loader Stage 1 (BL1) +------------------------- + +BL1 implements the reset vector where execution starts from after a cold or +warm boot. For each CPU, BL1 is responsible for the following tasks: + +#. Handling the reset as described in section 2.2 + +#. In the case of a cold boot and the CPU being the primary CPU, ensuring that + only this CPU executes the remaining BL1 code, including loading and passing + control to the BL2 stage. + +#. Identifying and starting the Firmware Update process (if required). + +#. Loading the BL2 image from non-volatile storage into secure memory at the + address specified by the platform defined constant ``BL2_BASE``. + +#. Populating a ``meminfo`` structure with the following information in memory, + accessible by BL2 immediately upon entry. + + :: + + meminfo.total_base = Base address of secure RAM visible to BL2 + meminfo.total_size = Size of secure RAM visible to BL2 + + By default, BL1 places this ``meminfo`` structure at the end of secure + memory visible to BL2. + + It is possible for the platform to decide where it wants to place the + ``meminfo`` structure for BL2 or restrict the amount of memory visible to + BL2 by overriding the weak default implementation of + ``bl1_plat_handle_post_image_load`` API. + +The following functions need to be implemented by the platform port to enable +BL1 to perform the above tasks. + +Function : bl1_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +On Arm standard platforms, this function: + +- Enables a secure instance of SP805 to act as the Trusted Watchdog. + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL1. + +- Enables issuing of snoop and DVM (Distributed Virtual Memory) requests to + the CCI slave interface corresponding to the cluster that includes the + primary CPU. + +Function : bl1_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs any platform-specific and architectural setup that the +platform requires. Platform-specific setup might include configuration of +memory controllers and the interconnect. + +In Arm standard platforms, this function enables the MMU. + +This function helps fulfill requirement 2 above. + +Function : bl1_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches enabled. It is responsible +for performing any remaining platform-specific setup that can occur after the +MMU and data cache have been enabled. + +if support for multiple boot sources is required, it initializes the boot +sequence used by plat_try_next_boot_source(). + +In Arm standard platforms, this function initializes the storage abstraction +layer used to load the next bootloader image. + +This function helps fulfill requirement 4 above. + +Function : bl1_plat_sec_mem_layout() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : meminfo * + +This function should only be called on the cold boot path. It executes with the +MMU and data caches enabled. The pointer returned by this function must point to +a ``meminfo`` structure containing the extents and availability of secure RAM for +the BL1 stage. + +:: + + meminfo.total_base = Base address of secure RAM visible to BL1 + meminfo.total_size = Size of secure RAM visible to BL1 + +This information is used by BL1 to load the BL2 image in secure RAM. BL1 also +populates a similar structure to tell BL2 the extents of memory available for +its own use. + +This function helps fulfill requirements 4 and 5 above. + +Function : bl1_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t * + Return : void + +This function is called prior to exiting BL1 in response to the +``BL1_SMC_RUN_IMAGE`` SMC request raised by BL2. It should be used to perform +platform specific clean up or bookkeeping operations before transferring +control to the next image. It receives the address of the ``entry_point_info_t`` +structure passed from BL2. This function runs with MMU disabled. + +Function : bl1_plat_set_ep_info() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, entry_point_info_t *ep_info + Return : void + +This function allows platforms to override ``ep_info`` for the given ``image_id``. + +The default implementation just returns. + +Function : bl1_plat_get_next_image_id() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +This and the following function must be overridden to enable the FWU feature. + +BL1 calls this function after platform setup to identify the next image to be +loaded and executed. If the platform returns ``BL2_IMAGE_ID`` then BL1 proceeds +with the normal boot sequence, which loads and executes BL2. If the platform +returns a different image id, BL1 assumes that Firmware Update is required. + +The default implementation always returns ``BL2_IMAGE_ID``. The Arm development +platforms override this function to detect if firmware update is required, and +if so, return the first image in the firmware update process. + +Function : bl1_plat_get_image_desc() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : image_desc_t * + +BL1 calls this function to get the image descriptor information ``image_desc_t`` +for the provided ``image_id`` from the platform. + +The default implementation always returns a common BL2 image descriptor. Arm +standard platforms return an image descriptor corresponding to BL2 or one of +the firmware update images defined in the Trusted Board Boot Requirements +specification. + +Function : bl1_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, before loading the image. + +Function : bl1_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id + Return : int + +This function can be used by the platforms to update/use image information +corresponding to ``image_id``. This function is invoked in BL1, both in cold +boot and FWU code path, after loading and authenticating the image. + +The default weak implementation of this function calculates the amount of +Trusted SRAM that can be used by BL2 and allocates a ``meminfo_t`` +structure at the beginning of this free memory and populates it. The address +of ``meminfo_t`` structure is updated in ``arg1`` of the entrypoint +information to BL2. + +Function : bl1_plat_fwu_done() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int image_id, uintptr_t image_src, + unsigned int image_size + Return : void + +BL1 calls this function when the FWU process is complete. It must not return. +The platform may override this function to take platform specific action, for +example to initiate the normal boot flow. + +The default implementation spins forever. + +Function : bl1_plat_mem_check() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t mem_base, unsigned int mem_size, + unsigned int flags + Return : int + +BL1 calls this function while handling FWU related SMCs, more specifically when +copying or authenticating an image. Its responsibility is to ensure that the +region of memory identified by ``mem_base`` and ``mem_size`` is mapped in BL1, and +that this memory corresponds to either a secure or non-secure memory region as +indicated by the security state of the ``flags`` argument. + +This function can safely assume that the value resulting from the addition of +``mem_base`` and ``mem_size`` fits into a ``uintptr_t`` type variable and does not +overflow. + +This function must return 0 on success, a non-null error code otherwise. + +The default implementation of this function asserts therefore platforms must +override it when using the FWU feature. + +Function : bl1_plat_mboot_init() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to initialize the backend driver(s) of measured boot. +- On the Arm FVP port, this function is used to initialize the Event Log + backend driver, and also to write header information in the Event Log buffer. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : bl1_plat_mboot_finish() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to finalize the measured boot backend driver(s), + and also, set the information for the next bootloader component to + extend the measurement if needed. +- On the Arm FVP port, this function is used to pass the base address of + the Event Log buffer and its size to BL2 via tb_fw_config to extend the + Event Log buffer with the measurement of various images loaded by BL2. + It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Boot Loader Stage 2 (BL2) +------------------------- + +The BL2 stage is executed only by the primary CPU, which is determined in BL1 +using the ``platform_is_primary_cpu()`` function. BL1 passed control to BL2 at +``BL2_BASE``. BL2 executes in Secure EL1 and and invokes +``plat_get_bl_image_load_info()`` to retrieve the list of images to load from +non-volatile storage to secure/non-secure RAM. After all the images are loaded +then BL2 invokes ``plat_get_next_bl_params()`` to get the list of executable +images to be passed to the next BL image. + +The following functions must be implemented by the platform port to enable BL2 +to perform the above tasks. + +Function : bl2_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. The 4 arguments are passed by BL1 to BL2 and these arguments +are platform specific. + +On Arm standard platforms, the arguments received are : + + arg0 - Points to load address of FW_CONFIG + + arg1 - ``meminfo`` structure populated by BL1. The platform copies + the contents of ``meminfo`` as it may be subsequently overwritten by BL2. + +On Arm standard platforms, this function also: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +Function : bl2_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2_plat_handle_pre_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 before +loading each image. + +Function : bl2_plat_handle_post_image_load() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int + Return : int + +This function can be used by the platforms to update/use image information +for given ``image_id``. This function is currently invoked in BL2 after +loading each image. + +Function : bl2_plat_preload_setup [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This optional function performs any BL2 platform initialization +required before image loading, that is not done later in +bl2_platform_setup(). Specifically, if support for multiple +boot sources is required, it initializes the boot sequence used by +plat_try_next_boot_source(). + +Function : plat_try_next_boot_source() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This optional function passes to the next boot source in the redundancy +sequence. + +This function moves the current boot redundancy source to the next +element in the boot sequence. If there are no more boot sources then it +must return 0, otherwise it must return 1. The default implementation +of this always returns 0. + +Boot Loader Stage 2 (BL2) at EL3 +-------------------------------- + +When the platform has a non-TF-A Boot ROM it is desirable to jump +directly to BL2 instead of TF-A BL1. In this case BL2 is expected to +execute at EL3 instead of executing at EL1. Refer to the :ref:`Firmware Design` +document for more information. + +All mandatory functions of BL2 must be implemented, except the functions +bl2_early_platform_setup and bl2_el3_plat_arch_setup, because +their work is done now by bl2_el3_early_platform_setup and +bl2_el3_plat_arch_setup. These functions should generally implement +the bl1_plat_xxx() and bl2_plat_xxx() functionality combined. + + +Function : bl2_el3_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. This function receives four parameters which can be used +by the platform to pass any needed information from the Boot ROM to BL2. + +On Arm standard platforms, this function does the following: + +- Initializes a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL2. + +- Initializes the storage abstraction layer used to load further bootloader + images. It is necessary to do this early on platforms with a SCP_BL2 image, + since the later ``bl2_platform_setup`` must be done after SCP_BL2 is loaded. + +- Initializes the private variables that define the memory layout used. + +Function : bl2_el3_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl2_el3_plat_prepare_exit() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function is called prior to exiting BL2 and run the next image. +It should be used to perform platform specific clean up or bookkeeping +operations before transferring control to the next image. This function +runs with MMU disabled. + +FWU Boot Loader Stage 2 (BL2U) +------------------------------ + +The AP Firmware Updater Configuration, BL2U, is an optional part of the FWU +process and is executed only by the primary CPU. BL1 passes control to BL2U at +``BL2U_BASE``. BL2U executes in Secure-EL1 and is responsible for: + +#. (Optional) Transferring the optional SCP_BL2U binary image from AP secure + memory to SCP RAM. BL2U uses the SCP_BL2U ``image_info`` passed by BL1. + ``SCP_BL2U_BASE`` defines the address in AP secure memory where SCP_BL2U + should be copied from. Subsequent handling of the SCP_BL2U image is + implemented by the platform specific ``bl2u_plat_handle_scp_bl2u()`` function. + If ``SCP_BL2U_BASE`` is not defined then this step is not performed. + +#. Any platform specific setup required to perform the FWU process. For + example, Arm standard platforms initialize the TZC controller so that the + normal world can access DDR memory. + +The following functions must be implemented by the platform port to enable +BL2U to perform the tasks mentioned above. + +Function : bl2u_early_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : meminfo *mem_info, void *plat_info + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. The arguments to this function is the address +of the ``meminfo`` structure and platform specific info provided by BL1. + +The platform may copy the contents of the ``mem_info`` and ``plat_info`` into +private storage as the original memory may be subsequently overwritten by BL2U. + +On Arm CSS platforms ``plat_info`` is interpreted as an ``image_info_t`` structure, +to extract SCP_BL2U image information, which is then copied into a private +variable. + +Function : bl2u_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only +called by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms, for example enabling the MMU (since the memory +map differs across platforms). + +Function : bl2u_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl2u_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to perform any platform initialization +specific to BL2U. + +In Arm standard platforms, this function performs security setup, including +configuration of the TrustZone controller to allow non-secure masters access +to most of DRAM. Part of DRAM is reserved for secure world use. + +Function : bl2u_plat_handle_scp_bl2u() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This function is used to perform any platform-specific actions required to +handle the SCP firmware. Typically it transfers the image into SCP memory using +a platform-specific protocol and waits until SCP executes it and signals to the +Application Processor (AP) for BL2U execution to continue. + +This function returns 0 on success, a negative error code otherwise. +This function is included if SCP_BL2U_BASE is defined. + +Function : bl2_plat_mboot_init() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to initialize the backend driver(s) of measured boot. +- On the Arm FVP port, this function is used to initialize the Event Log + backend driver with the Event Log buffer information (base address and + size) received from BL1. It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Function : bl2_plat_mboot_finish() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +When the MEASURED_BOOT flag is enabled: + +- This function is used to finalize the measured boot backend driver(s), + and also, set the information for the next bootloader component to extend + the measurement if needed. +- On the Arm FVP port, this function is used to pass the Event Log buffer + information (base address and size) to non-secure(BL33) and trusted OS(BL32) + via nt_fw and tos_fw config respectively. It results in panic on error. + +When the MEASURED_BOOT flag is disabled, this function doesn't do anything. + +Boot Loader Stage 3-1 (BL31) +---------------------------- + +During cold boot, the BL31 stage is executed only by the primary CPU. This is +determined in BL1 using the ``platform_is_primary_cpu()`` function. BL1 passes +control to BL31 at ``BL31_BASE``. During warm boot, BL31 is executed by all +CPUs. BL31 executes at EL3 and is responsible for: + +#. Re-initializing all architectural and platform state. Although BL1 performs + some of this initialization, BL31 remains resident in EL3 and must ensure + that EL3 architectural and platform state is completely initialized. It + should make no assumptions about the system state when it receives control. + +#. Passing control to a normal world BL image, pre-loaded at a platform- + specific address by BL2. On ARM platforms, BL31 uses the ``bl_params`` list + populated by BL2 in memory to do this. + +#. Providing runtime firmware services. Currently, BL31 only implements a + subset of the Power State Coordination Interface (PSCI) API as a runtime + service. See Section 3.3 below for details of porting the PSCI + implementation. + +#. Optionally passing control to the BL32 image, pre-loaded at a platform- + specific address by BL2. BL31 exports a set of APIs that allow runtime + services to specify the security state in which the next image should be + executed and run the corresponding image. On ARM platforms, BL31 uses the + ``bl_params`` list populated by BL2 in memory to do this. + +If BL31 is a reset vector, It also needs to handle the reset as specified in +section 2.2 before the tasks described above. + +The following functions must be implemented by the platform port to enable BL31 +to perform the above tasks. + +Function : bl31_early_platform_setup2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : u_register_t, u_register_t, u_register_t, u_register_t + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. BL2 can pass 4 arguments to BL31 and these arguments are +platform specific. + +In Arm standard platforms, the arguments received are : + + arg0 - The pointer to the head of `bl_params_t` list + which is list of executable images following BL31, + + arg1 - Points to load address of SOC_FW_CONFIG if present + except in case of Arm FVP and Juno platform. + + In case of Arm FVP and Juno platform, points to load address + of FW_CONFIG. + + arg2 - Points to load address of HW_CONFIG if present + + arg3 - A special value to verify platform parameters from BL2 to BL31. Not + used in release builds. + +The function runs through the `bl_param_t` list and extracts the entry point +information for BL32 and BL33. It also performs the following: + +- Initialize a UART (PL011 console), which enables access to the ``printf`` + family of functions in BL31. + +- Enable issuing of snoop and DVM (Distributed Virtual Memory) requests to the + CCI slave interface corresponding to the cluster that includes the primary + CPU. + +Function : bl31_plat_arch_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function executes with the MMU and data caches disabled. It is only called +by the primary CPU. + +The purpose of this function is to perform any architectural initialization +that varies across platforms. + +On Arm standard platforms, this function enables the MMU. + +Function : bl31_platform_setup() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initialization in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +The purpose of this function is to complete platform initialization so that both +BL31 runtime services and normal world software can function correctly. + +On Arm standard platforms, this function does the following: + +- Initialize the generic interrupt controller. + + Depending on the GIC driver selected by the platform, the appropriate GICv2 + or GICv3 initialization will be done, which mainly consists of: + + - Enable secure interrupts in the GIC CPU interface. + - Disable the legacy interrupt bypass mechanism. + - Configure the priority mask register to allow interrupts of all priorities + to be signaled to the CPU interface. + - Mark SGIs 8-15 and the other secure interrupts on the platform as secure. + - Target all secure SPIs to CPU0. + - Enable these secure interrupts in the GIC distributor. + - Configure all other interrupts as non-secure. + - Enable signaling of secure interrupts in the GIC distributor. + +- Enable system-level implementation of the generic timer counter through the + memory mapped interface. + +- Grant access to the system counter timer module + +- Initialize the power controller device. + + In particular, initialise the locks that prevent concurrent accesses to the + power controller device. + +Function : bl31_plat_runtime_setup() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +The purpose of this function is allow the platform to perform any BL31 runtime +setup just prior to BL31 exit during cold boot. The default weak +implementation of this function will invoke ``console_switch_state()`` to switch +console output to consoles marked for use in the ``runtime`` state. + +Function : bl31_plat_get_next_image_ep_info() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : entry_point_info * + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. + +This function is called by ``bl31_main()`` to retrieve information provided by +BL2 for the next image in the security state specified by the argument. BL31 +uses this information to pass control to that image in the specified security +state. This function must return a pointer to the ``entry_point_info`` structure +(that was copied during ``bl31_early_platform_setup()``) if the image exists. It +should return NULL otherwise. + +Function : plat_get_cca_attest_token() [mandatory when ENABLE_RME == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, size_t *, uintptr_t, size_t + Return : int + +This function returns the Platform attestation token. + +The parameters of the function are: + + arg0 - A pointer to the buffer where the Platform token should be copied by + this function. The buffer must be big enough to hold the Platform + token. + + arg1 - Contains the size (in bytes) of the buffer passed in arg0. The + function returns the platform token length in this parameter. + + arg2 - A pointer to the buffer where the challenge object is stored. + + arg3 - The length of the challenge object in bytes. Possible values are 32, + 48 and 64. + +The function returns 0 on success, -EINVAL on failure. + +Function : plat_get_cca_realm_attest_key() [mandatory when ENABLE_RME == 1] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, size_t *, unsigned int + Return : int + +This function returns the delegated realm attestation key which will be used to +sign Realm attestation token. The API currently only supports P-384 ECC curve +key. + +The parameters of the function are: + + arg0 - A pointer to the buffer where the attestation key should be copied + by this function. The buffer must be big enough to hold the + attestation key. + + arg1 - Contains the size (in bytes) of the buffer passed in arg0. The + function returns the attestation key length in this parameter. + + arg2 - The type of the elliptic curve to which the requested attestation key + belongs. + +The function returns 0 on success, -EINVAL on failure. + +Function : bl31_plat_enable_mmu [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This function enables the MMU. The boot code calls this function with MMU and +caches disabled. This function should program necessary registers to enable +translation, and upon return, the MMU on the calling PE must be enabled. + +The function must honor flags passed in the first argument. These flags are +defined by the translation library, and can be found in the file +``include/lib/xlat_tables/xlat_mmu_helpers.h``. + +On DynamIQ systems, this function must not use stack while enabling MMU, which +is how the function in xlat table library version 2 is implemented. + +Function : plat_init_apkey [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint128_t + +This function returns the 128-bit value which can be used to program ARMv8.3 +pointer authentication keys. + +The value should be obtained from a reliable source of randomness. + +This function is only needed if ARMv8.3 pointer authentication is used in the +Trusted Firmware by building with ``BRANCH_PROTECTION`` option set to non-zero. + +Function : plat_get_syscnt_freq2() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : unsigned int + +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. + +Function : plat_arm_set_twedel_scr_el3() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This function is used in v8.6+ systems to set the WFE trap delay value in +SCR_EL3. If this function returns TWED_DISABLED or is left unimplemented, this +feature is not enabled. The only hook provided is to set the TWED fields in +SCR_EL3, there are similar fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 to adjust +the WFE trap delays in lower ELs and these fields should be set by the +appropriate EL2 or EL1 code depending on the platform configuration. + +#define : PLAT_PERCPU_BAKERY_LOCK_SIZE [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +When ``USE_COHERENT_MEM = 0``, this constant defines the total memory (in +bytes) aligned to the cache line boundary that should be allocated per-cpu to +accommodate all the bakery locks. + +If this constant is not defined when ``USE_COHERENT_MEM = 0``, the linker +calculates the size of the ``bakery_lock`` input section, aligns it to the +nearest ``CACHE_WRITEBACK_GRANULE``, multiplies it with ``PLATFORM_CORE_COUNT`` +and stores the result in a linker symbol. This constant prevents a platform +from relying on the linker and provide a more efficient mechanism for +accessing per-cpu bakery lock information. + +If this constant is defined and its value is not equal to the value +calculated by the linker then a link time assertion is raised. A compile time +assertion is raised if the value of the constant is not aligned to the cache +line boundary. + +.. _porting_guide_sdei_requirements: + +SDEI porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |SDEI| dispatcher requires the platform to provide the following macros +and functions, of which some are optional, and some others mandatory. + +Macros +...... + +Macro: PLAT_SDEI_NORMAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Normal |SDEI| events on the platform. This must have a higher value +(therefore of lower priority) than ``PLAT_SDEI_CRITICAL_PRI``. + +Macro: PLAT_SDEI_CRITICAL_PRI [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This macro must be defined to the EL3 exception priority level associated with +Critical |SDEI| events on the platform. This must have a lower value +(therefore of higher priority) than ``PLAT_SDEI_NORMAL_PRI``. + +**Note**: |SDEI| exception priorities must be the lowest among Secure +priorities. Among the |SDEI| exceptions, Critical |SDEI| priority must +be higher than Normal |SDEI| priority. + +Functions +......... + +Function: int plat_sdei_validate_entry_point() [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uintptr_t ep, unsigned int client_mode + Return: int + +This function validates the entry point address of the event handler provided by +the client for both event registration and *Complete and Resume* |SDEI| calls. +The function ensures that the address is valid in the client translation regime. + +The second argument is the exception level that the client is executing in. It +can be Non-Secure EL1 or Non-Secure EL2. + +The function must return ``0`` for successful validation, or ``-1`` upon failure. + +The default implementation always returns ``0``. On Arm platforms, this function +translates the entry point address within the client translation regime and +further ensures that the resulting physical address is located in Non-secure +DRAM. + +Function: void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr) [optional] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t + Argument: unsigned int + Return: void + +|SDEI| specification requires that a PE comes out of reset with the events +masked. The client therefore is expected to call ``PE_UNMASK`` to unmask +|SDEI| events on the PE. No |SDEI| events can be dispatched until such +time. + +Should a PE receive an interrupt that was bound to an |SDEI| event while the +events are masked on the PE, the dispatcher implementation invokes the function +``plat_sdei_handle_masked_trigger``. The MPIDR of the PE that received the +interrupt and the interrupt ID are passed as parameters. + +The default implementation only prints out a warning message. + +.. _porting_guide_trng_requirements: + +TRNG porting requirements +~~~~~~~~~~~~~~~~~~~~~~~~~ + +The |TRNG| backend requires the platform to provide the following values +and mandatory functions. + +Values +...... + +value: uuid_t plat_trng_uuid [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +This value must be defined to the UUID of the TRNG backend that is specific to +the hardware after ``plat_trng_setup`` function is called. This value must +conform to the SMCCC calling convention; The most significant 32 bits of the +UUID must not equal ``0xffffffff`` or the signed integer ``-1`` as this value in +w0 indicates failure to get a TRNG source. + +Functions +......... + +Function: void plat_entropy_setup(void) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: none + Return: none + +This function is expected to do platform-specific initialization of any TRNG +hardware. This may include generating a UUID from a hardware-specific seed. + +Function: bool plat_get_entropy(uint64_t \*out) [mandatory] +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:: + + Argument: uint64_t * + Return: bool + Out : when the return value is true, the entropy has been written into the + storage pointed to + +This function writes entropy into storage provided by the caller. If no entropy +is available, it must return false and the storage must not be written. + +Power State Coordination Interface (in BL31) +-------------------------------------------- + +The TF-A implementation of the PSCI API is based around the concept of a +*power domain*. A *power domain* is a CPU or a logical group of CPUs which +share some state on which power management operations can be performed as +specified by `PSCI`_. Each CPU in the system is assigned a cpu index which is +a unique number between ``0`` and ``PLATFORM_CORE_COUNT - 1``. The +*power domains* are arranged in a hierarchical tree structure and each +*power domain* can be identified in a system by the cpu index of any CPU that +is part of that domain and a *power domain level*. A processing element (for +example, a CPU) is at level 0. If the *power domain* node above a CPU is a +logical grouping of CPUs that share some state, then level 1 is that group of +CPUs (for example, a cluster), and level 2 is a group of clusters (for +example, the system). More details on the power domain topology and its +organization can be found in :ref:`PSCI Power Domain Tree Structure`. + +BL31's platform initialization code exports a pointer to the platform-specific +power management operations required for the PSCI implementation to function +correctly. This information is populated in the ``plat_psci_ops`` structure. The +PSCI implementation calls members of the ``plat_psci_ops`` structure for performing +power management operations on the power domains. For example, the target +CPU is specified by its ``MPIDR`` in a PSCI ``CPU_ON`` call. The ``pwr_domain_on()`` +handler (if present) is called for the CPU power domain. + +The ``power-state`` parameter of a PSCI ``CPU_SUSPEND`` call can be used to +describe composite power states specific to a platform. The PSCI implementation +defines a generic representation of the power-state parameter, which is an +array of local power states where each index corresponds to a power domain +level. Each entry contains the local power state the power domain at that power +level could enter. It depends on the ``validate_power_state()`` handler to +convert the power-state parameter (possibly encoding a composite power state) +passed in a PSCI ``CPU_SUSPEND`` call to this representation. + +The following functions form part of platform port of PSCI functionality. + +Function : plat_psci_stat_accounting_start() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting before entering a low power state. The ``pwr_domain_state`` field of +``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_accounting_stop() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_power_state_t * + Return : void + +This is an optional hook that platforms can implement for residency statistics +accounting after exiting from a low power state. The ``pwr_domain_state`` field +of ``state_info`` (first argument) can be inspected if stat accounting is done +differently at CPU level versus higher levels. As an example, if the element at +index 0 (CPU power level) in the ``pwr_domain_state`` array indicates a power down +state, special hardware logic may be programmed in order to keep track of the +residency statistics. For higher levels (array indices > 0), the residency +statistics could be tracked in software using PMF. If ``ENABLE_PMF`` is set, the +default implementation will use PMF to capture timestamps. + +Function : plat_psci_stat_get_residency() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const psci_power_state_t *, unsigned int + Return : u_register_t + +This is an optional interface that is is invoked after resuming from a low power +state and provides the time spent resident in that low power state by the power +domain at a particular power domain level. When a CPU wakes up from suspend, +all its parent power domain levels are also woken up. The generic PSCI code +invokes this function for each parent power domain that is resumed and it +identified by the ``lvl`` (first argument) parameter. The ``state_info`` (second +argument) describes the low power state that the power domain has resumed from. +The current CPU is the first CPU in the power domain to resume from the low +power state and the ``last_cpu_idx`` (third parameter) is the index of the last +CPU in the power domain to suspend and may be needed to calculate the residency +for that power domain. + +Function : plat_get_target_pwr_state() [optional] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : unsigned int, const plat_local_state_t *, unsigned int + Return : plat_local_state_t + +The PSCI generic code uses this function to let the platform participate in +state coordination during a power management operation. The function is passed +a pointer to an array of platform specific local power state ``states`` (second +argument) which contains the requested power state for each CPU at a particular +power domain level ``lvl`` (first argument) within the power domain. The function +is expected to traverse this array of upto ``ncpus`` (third argument) and return +a coordinated target power state by the comparing all the requested power +states. The target power state should not be deeper than any of the requested +power states. + +A weak definition of this API is provided by default wherein it assumes +that the platform assigns a local state value 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 state values. + +Function : plat_get_power_domain_tree_desc() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : const unsigned char * + +This function returns a pointer to the byte array containing the power domain +topology tree description. The format and method to construct this array are +described in :ref:`PSCI Power Domain Tree Structure`. The BL31 PSCI +initialization code requires this array to be described by the platform, either +statically or dynamically, to initialize the power domain topology tree. In case +the array is populated dynamically, then plat_core_pos_by_mpidr() and +plat_my_core_pos() should also be implemented suitably so that the topology tree +description matches the CPU indices returned by these APIs. These APIs together +form the platform interface for the PSCI topology framework. + +Function : plat_setup_psci_ops() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uintptr_t, const plat_psci_ops ** + Return : int + +This function may execute with the MMU and data caches enabled if the platform +port does the necessary initializations in ``bl31_plat_arch_setup()``. It is only +called by the primary CPU. + +This function is called by PSCI initialization code. Its purpose is to let +the platform layer know about the warm boot entrypoint through the +``sec_entrypoint`` (first argument) and to export handler routines for +platform-specific psci power management actions by populating the passed +pointer with a pointer to BL31's private ``plat_psci_ops`` structure. + +A description of each member of this structure is given below. Please refer to +the Arm FVP specific implementation of these handlers in +``plat/arm/board/fvp/fvp_pm.c`` as an example. For each PSCI function that the +platform wants to support, the associated operation or operations in this +structure must be provided and implemented (Refer section 4 of +:ref:`Firmware Design` for the PSCI API supported in TF-A). To disable a PSCI +function in a platform port, the operation should be removed from this +structure instead of providing an empty implementation. + +plat_psci_ops.cpu_standby() +........................... + +Perform the platform-specific actions to enter the standby state for a cpu +indicated by the passed argument. This provides a fast path for CPU standby +wherein overheads of PSCI state management and lock acquisition is avoided. +For this handler to be invoked by the PSCI ``CPU_SUSPEND`` API implementation, +the suspend state type specified in the ``power-state`` parameter should be +STANDBY and the target power domain level specified should be the CPU. The +handler should put the CPU into a low power retention state (usually by +issuing a wfi instruction) and ensure that it can be woken up from that +state by a normal interrupt. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_on() +............................. + +Perform the platform specific actions to power on a CPU, specified +by the ``MPIDR`` (first argument). The generic code expects the platform to +return PSCI_E_SUCCESS on success or PSCI_E_INTERN_FAIL for any failure. + +plat_psci_ops.pwr_domain_off() +.............................. + +Perform the platform specific actions to prepare to power off the calling CPU +and its higher parent power domain levels as indicated by the ``target_state`` +(first argument). It is called by the PSCI ``CPU_OFF`` API implementation. + +The ``target_state`` encodes the platform coordinated target local power states +for the CPU power domain and its parent power domain levels. The handler +needs to perform power management operation corresponding to the local state +at each power level. + +For this handler, the local power state for the CPU power domain will be a +power down state where as it could be either power down, retention or run state +for the higher power domain levels depending on the result of state +coordination. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_pwrdown_early() [optional] +........................................................... + +This optional function may be used as a performance optimization to replace +or complement pwr_domain_suspend() on some platforms. Its calling semantics +are identical to pwr_domain_suspend(), except the PSCI implementation only +calls this function when suspending to a power down state, and it guarantees +that data caches are enabled. + +When HW_ASSISTED_COHERENCY = 0, the PSCI implementation disables data caches +before calling pwr_domain_suspend(). If the target_state corresponds to a +power down state and it is safe to perform some or all of the platform +specific actions in that function with data caches enabled, it may be more +efficient to move those actions to this function. When HW_ASSISTED_COHERENCY += 1, data caches remain enabled throughout, and so there is no advantage to +moving platform specific actions to this function. + +plat_psci_ops.pwr_domain_suspend() +.................................. + +Perform the platform specific actions to prepare to suspend the calling +CPU and its higher parent power domain levels as indicated by the +``target_state`` (first argument). It is called by the PSCI ``CPU_SUSPEND`` +API implementation. + +The ``target_state`` has a similar meaning as described in +the ``pwr_domain_off()`` operation. It encodes the platform coordinated +target local power states for the CPU power domain and its parent +power domain levels. The handler needs to perform power management operation +corresponding to the local state at each power level. The generic code +expects the handler to succeed. + +The difference between turning a power domain off versus suspending it is that +in the former case, the power domain is expected to re-initialize its state +when it is next powered on (see ``pwr_domain_on_finish()``). In the latter +case, the power domain is expected to save enough state so that it can resume +execution by restoring this state when its powered on (see +``pwr_domain_suspend_finish()``). + +When suspending a core, the platform can also choose to power off the GICv3 +Redistributor and ITS through an implementation-defined sequence. To achieve +this safely, the ITS context must be saved first. The architectural part is +implemented by the ``gicv3_its_save_disable()`` helper, but most of the needed +sequence is implementation defined and it is therefore the responsibility of +the platform code to implement the necessary sequence. Then the GIC +Redistributor context can be saved using the ``gicv3_rdistif_save()`` helper. +Powering off the Redistributor requires the implementation to support it and it +is the responsibility of the platform code to execute the right implementation +defined sequence. + +When a system suspend is requested, the platform can also make use of the +``gicv3_distif_save()`` helper to save the context of the GIC Distributor after +it has saved the context of the Redistributors and ITS of all the cores in the +system. The context of the Distributor can be large and may require it to be +allocated in a special area if it cannot fit in the platform's global static +data, for example in DRAM. The Distributor can then be powered down using an +implementation-defined sequence. + +plat_psci_ops.pwr_domain_pwr_down_wfi() +....................................... + +This is an optional function and, if implemented, is expected to perform +platform specific actions including the ``wfi`` invocation which allows the +CPU to powerdown. Since this function is invoked outside the PSCI locks, +the actions performed in this hook must be local to the CPU or the platform +must ensure that races between multiple CPUs cannot occur. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_off()`` +operation and it encodes the platform coordinated target local power states for +the CPU power domain and its parent power domain levels. This function must +not return back to the caller. + +If this function is not implemented by the platform, PSCI generic +implementation invokes ``psci_power_down_wfi()`` for power down. + +plat_psci_ops.pwr_domain_on_finish() +.................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an earlier PSCI ``CPU_ON`` call. +It performs the platform-specific setup required to initialize enough state for +this CPU to enter the normal world and also provide secure runtime firmware +services. + +The ``target_state`` (first argument) is the prior state of the power domains +immediately before the CPU was turned on. It indicates which power domains +above the CPU might require initialization due to having previously been in +low power states. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_on_finish_late() [optional] +........................................................... + +This optional function is called by the PSCI implementation after the calling +CPU is fully powered on with respective data caches enabled. The calling CPU and +the associated cluster are guaranteed to be participating in coherency. This +function gives the flexibility to perform any platform-specific actions safely, +such as initialization or modification of shared data structures, without the +overhead of explicit cache maintainace operations. + +The ``target_state`` has a similar meaning as described in the ``pwr_domain_on_finish()`` +operation. The generic code expects the handler to succeed. + +plat_psci_ops.pwr_domain_suspend_finish() +......................................... + +This function is called by the PSCI implementation after the calling CPU is +powered on and released from reset in response to an asynchronous wakeup +event, for example a timer interrupt that was programmed by the CPU during the +``CPU_SUSPEND`` call or ``SYSTEM_SUSPEND`` call. It performs the platform-specific +setup required to restore the saved state for this CPU to resume execution +in the normal world and also provide secure runtime firmware services. + +The ``target_state`` (first argument) has a similar meaning as described in +the ``pwr_domain_on_finish()`` operation. The generic code expects the platform +to succeed. + +If the Distributor, Redistributors or ITS have been powered off as part of a +suspend, their context must be restored in this function in the reverse order +to how they were saved during suspend sequence. + +plat_psci_ops.system_off() +.......................... + +This function is called by PSCI implementation in response to a ``SYSTEM_OFF`` +call. It performs the platform-specific system poweroff sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.system_reset() +............................ + +This function is called by PSCI implementation in response to a ``SYSTEM_RESET`` +call. It performs the platform-specific system reset sequence after +notifying the Secure Payload Dispatcher. + +plat_psci_ops.validate_power_state() +.................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND`` +call to validate the ``power_state`` parameter of the PSCI API and if valid, +populate it in ``req_state`` (second argument) array as power domain level +specific local states. If the ``power_state`` is invalid, the platform must +return PSCI_E_INVALID_PARAMS as error, which is propagated back to the +normal world PSCI client. + +plat_psci_ops.validate_ns_entrypoint() +...................................... + +This function is called by the PSCI implementation during the ``CPU_SUSPEND``, +``SYSTEM_SUSPEND`` and ``CPU_ON`` calls to validate the non-secure ``entry_point`` +parameter passed by the normal world. If the ``entry_point`` is invalid, +the platform must return PSCI_E_INVALID_ADDRESS as error, which is +propagated back to the normal world PSCI client. + +plat_psci_ops.get_sys_suspend_power_state() +........................................... + +This function is called by the PSCI implementation during the ``SYSTEM_SUSPEND`` +call to get the ``req_state`` parameter from platform which encodes the power +domain level specific local states to suspend to system affinity level. The +``req_state`` will be utilized to do the PSCI state coordination and +``pwr_domain_suspend()`` will be invoked with the coordinated target state to +enter system suspend. + +plat_psci_ops.get_pwr_lvl_state_idx() +..................................... + +This is an optional function and, if implemented, is invoked by the PSCI +implementation to convert the ``local_state`` (first argument) at a specified +``pwr_lvl`` (second argument) to an index between 0 and +``PLAT_MAX_PWR_LVL_STATES`` - 1. This function is only needed if the platform +supports more than two local power states at each power domain level, that is +``PLAT_MAX_PWR_LVL_STATES`` is greater than 2, and needs to account for these +local power states. + +plat_psci_ops.translate_power_state_by_mpidr() +.............................................. + +This is an optional function and, if implemented, verifies the ``power_state`` +(second argument) parameter of the PSCI API corresponding to a target power +domain. The target power domain is identified by using both ``MPIDR`` (first +argument) and the power domain level encoded in ``power_state``. The power domain +level specific local states are to be extracted from ``power_state`` and be +populated in the ``output_state`` (third argument) array. The functionality +is similar to the ``validate_power_state`` function described above and is +envisaged to be used in case the validity of ``power_state`` depend on the +targeted power domain. If the ``power_state`` is invalid for the targeted power +domain, the platform must return PSCI_E_INVALID_PARAMS as error. If this +function is not implemented, then the generic implementation relies on +``validate_power_state`` function to translate the ``power_state``. + +This function can also be used in case the platform wants to support local +power state encoding for ``power_state`` parameter of PSCI_STAT_COUNT/RESIDENCY +APIs as described in Section 5.18 of `PSCI`_. + +plat_psci_ops.get_node_hw_state() +................................. + +This is an optional function. If implemented this function is intended to return +the power state of a node (identified by the first parameter, the ``MPIDR``) in +the power domain topology (identified by the second parameter, ``power_level``), +as retrieved from a power controller or equivalent component on the platform. +Upon successful completion, the implementation must map and return the final +status among ``HW_ON``, ``HW_OFF`` or ``HW_STANDBY``. Upon encountering failures, it +must return either ``PSCI_E_INVALID_PARAMS`` or ``PSCI_E_NOT_SUPPORTED`` as +appropriate. + +Implementations are not expected to handle ``power_levels`` greater than +``PLAT_MAX_PWR_LVL``. + +plat_psci_ops.system_reset2() +............................. + +This is an optional function. If implemented this function is +called during the ``SYSTEM_RESET2`` call to perform a reset +based on the first parameter ``reset_type`` as specified in +`PSCI`_. The parameter ``cookie`` can be used to pass additional +reset information. If the ``reset_type`` is not supported, the +function must return ``PSCI_E_NOT_SUPPORTED``. For architectural +resets, all failures must return ``PSCI_E_INVALID_PARAMETERS`` +and vendor reset can return other PSCI error codes as defined +in `PSCI`_. On success this function will not return. + +plat_psci_ops.write_mem_protect() +................................. + +This is an optional function. If implemented it enables or disables the +``MEM_PROTECT`` functionality based on the value of ``val``. +A non-zero value enables ``MEM_PROTECT`` and a value of zero +disables it. Upon encountering failures it must return a negative value +and on success it must return 0. + +plat_psci_ops.read_mem_protect() +................................ + +This is an optional function. If implemented it returns the current +state of ``MEM_PROTECT`` via the ``val`` parameter. Upon encountering +failures it must return a negative value and on success it must +return 0. + +plat_psci_ops.mem_protect_chk() +............................... + +This is an optional function. If implemented it checks if a memory +region defined by a base address ``base`` and with a size of ``length`` +bytes is protected by ``MEM_PROTECT``. If the region is protected +then it must return 0, otherwise it must return a negative number. + +.. _porting_guide_imf_in_bl31: + +Interrupt Management framework (in BL31) +---------------------------------------- + +BL31 implements an Interrupt Management Framework (IMF) to manage interrupts +generated in either security state and targeted to EL1 or EL2 in the non-secure +state or EL3/S-EL1 in the secure state. The design of this framework is +described in the :ref:`Interrupt Management Framework` + +A platform should export the following APIs to support the IMF. The following +text briefly describes each API and its implementation in Arm standard +platforms. The API implementation depends upon the type of interrupt controller +present in the platform. Arm standard platform layer supports both +`Arm Generic Interrupt Controller version 2.0 (GICv2)`_ +and `3.0 (GICv3)`_. Juno builds the Arm platform layer to use GICv2 and the +FVP can be configured to use either GICv2 or GICv3 depending on the build flag +``FVP_USE_GIC_DRIVER`` (See :ref:`build_options_arm_fvp_platform` for more +details). + +See also: :ref:`Interrupt Controller Abstraction APIs`. + +Function : plat_interrupt_type_to_line() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t, uint32_t + Return : uint32_t + +The Arm processor signals an interrupt exception either through the IRQ or FIQ +interrupt line. The specific line that is signaled depends on how the interrupt +controller (IC) reports different interrupt types from an execution context in +either security state. The IMF uses this API to determine which interrupt line +the platform IC uses to signal each type of interrupt supported by the framework +from a given security state. This API must be invoked at EL3. + +The first parameter will be one of the ``INTR_TYPE_*`` values (see +:ref:`Interrupt Management Framework`) indicating the target type of the +interrupt, the second parameter is the security state of the originating +execution context. The return result is the bit position in the ``SCR_EL3`` +register of the respective interrupt trap: IRQ=1, FIQ=2. + +In the case of Arm standard platforms using GICv2, S-EL1 interrupts are +configured as FIQs and Non-secure interrupts as IRQs from either security +state. + +In the case of Arm standard platforms using GICv3, the interrupt line to be +configured depends on the security state of the execution context when the +interrupt is signalled and are as follows: + +- The S-EL1 interrupts are signaled as IRQ in S-EL0/1 context and as FIQ in + NS-EL0/1/2 context. +- The Non secure interrupts are signaled as FIQ in S-EL0/1 context and as IRQ + in the NS-EL0/1/2 context. +- The EL3 interrupts are signaled as FIQ in both S-EL0/1 and NS-EL0/1/2 + context. + +Function : plat_ic_get_pending_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the type of the highest priority pending interrupt at the +platform IC. The IMF uses the interrupt type to retrieve the corresponding +handler function. ``INTR_TYPE_INVAL`` is returned when there is no interrupt +pending. The valid interrupt types that can be returned are ``INTR_TYPE_EL3``, +``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``. This API must be invoked at EL3. + +In the case of Arm standard platforms using 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. + +#. id < 1022 is reported as a S-EL1 interrupt +#. id = 1022 is reported as a Non-secure interrupt. +#. id = 1023 is reported as an invalid interrupt type. + +In the case of Arm standard platforms using GICv3, the system register +``ICC_HPPIR0_EL1``, *Highest Priority Pending group 0 Interrupt Register*, +is read to determine the id of the pending interrupt. The type of interrupt +depends upon the id value as follows. + +#. id = ``PENDING_G1S_INTID`` (1020) is reported as a S-EL1 interrupt +#. id = ``PENDING_G1NS_INTID`` (1021) is reported as a Non-secure interrupt. +#. id = ``GIC_SPURIOUS_INTERRUPT`` (1023) is reported as an invalid interrupt type. +#. All other interrupt id's are reported as EL3 interrupt. + +Function : plat_ic_get_pending_interrupt_id() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API returns the id of the highest priority pending interrupt at the +platform IC. ``INTR_ID_UNAVAILABLE`` is returned when there is no interrupt +pending. + +In the case of Arm standard platforms using GICv2, the *Highest Priority +Pending Interrupt Register* (``GICC_HPPIR``) is read to determine the id of the +pending interrupt. The id that is returned by API depends upon the value of +the id read from the interrupt controller as follows. + +#. id < 1022. id is returned as is. +#. id = 1022. The *Aliased Highest Priority Pending Interrupt Register* + (``GICC_AHPPIR``) is read to determine the id of the non-secure interrupt. + This id is returned by the API. +#. id = 1023. ``INTR_ID_UNAVAILABLE`` is returned. + +In the case of Arm standard platforms using GICv3, if the API is invoked from +EL3, the system register ``ICC_HPPIR0_EL1``, *Highest Priority Pending Interrupt +group 0 Register*, is read to determine the id of the pending interrupt. The id +that is returned by API depends upon the value of the id read from the +interrupt controller as follows. + +#. id < ``PENDING_G1S_INTID`` (1020). id is returned as is. +#. id = ``PENDING_G1S_INTID`` (1020) or ``PENDING_G1NS_INTID`` (1021). The system + register ``ICC_HPPIR1_EL1``, *Highest Priority Pending Interrupt group 1 + Register* is read to determine the id of the group 1 interrupt. This id + is returned by the API as long as it is a valid interrupt id +#. If the id is any of the special interrupt identifiers, + ``INTR_ID_UNAVAILABLE`` is returned. + +When the API invoked from S-EL1 for GICv3 systems, the id read from system +register ``ICC_HPPIR1_EL1``, *Highest Priority Pending group 1 Interrupt +Register*, is returned if is not equal to GIC_SPURIOUS_INTERRUPT (1023) else +``INTR_ID_UNAVAILABLE`` is returned. + +Function : plat_ic_acknowledge_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : uint32_t + +This API is used by the CPU to indicate to the platform IC that processing of +the highest pending interrupt has begun. It should return the raw, unmodified +value obtained from the interrupt controller when acknowledging an interrupt. +The actual interrupt number shall be extracted from this raw value using the API +`plat_ic_get_interrupt_id()`. + +This function in Arm standard platforms using GICv2, reads the *Interrupt +Acknowledge Register* (``GICC_IAR``). This changes the state of the highest +priority pending interrupt from pending to active in the interrupt controller. +It returns the value read from the ``GICC_IAR``, unmodified. + +In the case of Arm standard platforms using GICv3, if the API is invoked +from EL3, the function reads the system register ``ICC_IAR0_EL1``, *Interrupt +Acknowledge Register group 0*. If the API is invoked from S-EL1, the function +reads the system register ``ICC_IAR1_EL1``, *Interrupt Acknowledge Register +group 1*. The read changes the state of the highest pending interrupt from +pending to active in the interrupt controller. The value read is returned +unmodified. + +The TSP uses this API to start processing of the secure physical timer +interrupt. + +Function : plat_ic_end_of_interrupt() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : void + +This API is used by the CPU to indicate to the platform IC that processing of +the interrupt corresponding to the id (passed as the parameter) has +finished. The id should be the same as the id returned by the +``plat_ic_acknowledge_interrupt()`` API. + +Arm standard platforms write the id to the *End of Interrupt Register* +(``GICC_EOIR``) in case of GICv2, and to ``ICC_EOIR0_EL1`` or ``ICC_EOIR1_EL1`` +system register in case of GICv3 depending on where the API is invoked from, +EL3 or S-EL1. This deactivates the corresponding interrupt in the interrupt +controller. + +The TSP uses this API to finish processing of the secure physical timer +interrupt. + +Function : plat_ic_get_interrupt_type() [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : uint32_t + Return : uint32_t + +This API returns the type of the interrupt id passed as the parameter. +``INTR_TYPE_INVAL`` is returned if the id is invalid. If the id is valid, a valid +interrupt type (one of ``INTR_TYPE_EL3``, ``INTR_TYPE_S_EL1`` and ``INTR_TYPE_NS``) is +returned depending upon how the interrupt has been configured by the platform +IC. This API must be invoked at EL3. + +Arm standard platforms using GICv2 configures S-EL1 interrupts as Group0 interrupts +and Non-secure interrupts as Group1 interrupts. It reads the group value +corresponding to the interrupt id from the relevant *Interrupt Group Register* +(``GICD_IGROUPRn``). It uses the group value to determine the type of interrupt. + +In the case of Arm standard platforms using GICv3, both the *Interrupt Group +Register* (``GICD_IGROUPRn``) and *Interrupt Group Modifier Register* +(``GICD_IGRPMODRn``) is read to figure out whether the interrupt is configured +as Group 0 secure interrupt, Group 1 secure interrupt or Group 1 NS interrupt. + +Crash Reporting mechanism (in BL31) +----------------------------------- + +BL31 implements a crash reporting mechanism which prints the various registers +of the CPU to enable quick crash analysis and debugging. This mechanism relies +on the platform implementing ``plat_crash_console_init``, +``plat_crash_console_putc`` and ``plat_crash_console_flush``. + +The file ``plat/common/aarch64/crash_console_helpers.S`` contains sample +implementation of all of them. Platforms may include this file to their +makefiles in order to benefit from them. By default, they will cause the crash +output to be routed over the normal console infrastructure and get printed on +consoles configured to output in crash state. ``console_set_scope()`` can be +used to control whether a console is used for crash output. + +.. note:: + Platforms are responsible for making sure that they only mark consoles for + use in the crash scope that are able to support this, i.e. that are written + in assembly and conform with the register clobber rules for putc() + (x0-x2, x16-x17) and flush() (x0-x3, x16-x17) crash callbacks. + +In some cases (such as debugging very early crashes that happen before the +normal boot console can be set up), platforms may want to control crash output +more explicitly. These platforms may instead provide custom implementations for +these. They are executed outside of a C environment and without a stack. Many +console drivers provide functions named ``console_xxx_core_init/putc/flush`` +that are designed to be used by these functions. See Arm platforms (like juno) +for an example of this. + +Function : plat_crash_console_init [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : int + +This API is used by the crash reporting mechanism to initialize the crash +console. It must only use the general purpose registers x0 through x7 to do the +initialization and returns 1 on success. + +Function : plat_crash_console_putc [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Return : int + +This API is used by the crash reporting mechanism to print a character on the +designated crash console. It must only use general purpose registers x1 and +x2 to do its work. The parameter and the return value are in general purpose +register x0. + +Function : plat_crash_console_flush [mandatory] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This API is used by the crash reporting mechanism to force write of all buffered +data on the designated crash console. It should only use general purpose +registers x0 through x5 to do its work. + +.. _External Abort handling and RAS Support: + +External Abort handling and RAS Support +--------------------------------------- + +Function : plat_ea_handler +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Argument : void * + Argument : void * + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework for the platform to handle an +External Abort received at EL3. The intention of the function is to attempt to +resolve the cause of External Abort and return; if that's not possible, to +initiate orderly shutdown of the system. + +The first parameter (``int ea_reason``) indicates the reason for External Abort. +Its value is one of ``ERROR_EA_*`` constants defined in ``ea_handle.h``. + +The second parameter (``uint64_t syndrome``) is the respective syndrome +presented to EL3 after having received the External Abort. Depending on the +nature of the abort (as can be inferred from the ``ea_reason`` parameter), this +can be the content of either ``ESR_EL3`` or ``DISR_EL1``. + +The third parameter (``void *cookie``) is unused for now. The fourth parameter +(``void *handle``) is a pointer to the preempted context. The fifth parameter +(``uint64_t flags``) indicates the preempted security state. These parameters +are received from the top-level exception handler. + +If ``RAS_EXTENSION`` is set to ``1``, the default implementation of this +function iterates through RAS handlers registered by the platform. If any of the +RAS handlers resolve the External Abort, no further action is taken. + +If ``RAS_EXTENSION`` is set to ``0``, or if none of the platform RAS handlers +could resolve the External Abort, the default implementation prints an error +message, and panics. + +Function : plat_handle_uncontainable_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when an External Abort of +Uncontainable type is received at EL3. Due to the critical nature of +Uncontainable errors, the intention of this function is to initiate orderly +shutdown of the system, and is not expected to return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_double_fault +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : int + Argument : uint64_t + Return : void + +This function is invoked by the RAS framework when another External Abort is +received at EL3 while one is already being handled. I.e., a call to +``plat_ea_handler`` is outstanding. Due to its critical nature, the intention of +this function is to initiate orderly shutdown of the system, and is not expected +recover or return. + +This function must be implemented in assembly. + +The first and second parameters are the same as that of ``plat_ea_handler``. + +The default implementation of this function calls +``report_unhandled_exception``. + +Function : plat_handle_el3_ea +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Return : void + +This function is invoked when an External Abort is received while executing in +EL3. Due to its critical nature, the intention of this function is to initiate +orderly shutdown of the system, and is not expected recover or return. + +This function must be implemented in assembly. + +The default implementation of this function calls +``report_unhandled_exception``. + +Build flags +----------- + +There are some build flags which can be defined by the platform to control +inclusion or exclusion of certain BL stages from the FIP image. These flags +need to be defined in the platform makefile which will get included by the +build system. + +- **NEED_BL33** + By default, this flag is defined ``yes`` by the build system and ``BL33`` + build option should be supplied as a build option. The platform has the + option of excluding the BL33 image in the ``fip`` image by defining this flag + to ``no``. If any of the options ``EL3_PAYLOAD_BASE`` or ``PRELOADED_BL33_BASE`` + are used, this flag will be set to ``no`` automatically. + +Platform include paths +---------------------- + +Platforms are allowed to add more include paths to be passed to the compiler. +The ``PLAT_INCLUDES`` variable is used for this purpose. This is needed in +particular for the file ``platform_def.h``. + +Example: + +.. code:: c + + PLAT_INCLUDES += -Iinclude/plat/myplat/include + +C Library +--------- + +To avoid subtle toolchain behavioral dependencies, the header files provided +by the compiler are not used. The software is built with the ``-nostdinc`` flag +to ensure no headers are included from the toolchain inadvertently. Instead the +required headers are included in the TF-A source tree. The library only +contains those C library definitions required by the local implementation. If +more functionality is required, the needed library functions will need to be +added to the local implementation. + +Some C headers have been obtained from `FreeBSD`_ and `SCC`_, while others have +been written specifically for TF-A. Some implementation files have been obtained +from `FreeBSD`_, others have been written specifically for TF-A as well. The +files can be found in ``include/lib/libc`` and ``lib/libc``. + +SCC can be found in http://www.simple-cc.org/. A copy of the `FreeBSD`_ sources +can be obtained from http://github.com/freebsd/freebsd. + +Storage abstraction layer +------------------------- + +In order to improve platform independence and portability a storage abstraction +layer is used to load data from non-volatile platform storage. Currently +storage access is only required by BL1 and BL2 phases and performed inside the +``load_image()`` function in ``bl_common.c``. + +.. uml:: ../resources/diagrams/plantuml/io_framework_usage_overview.puml + +It is mandatory to implement at least one storage driver. For the Arm +development platforms the Firmware Image Package (FIP) driver is provided as +the default means to load data from storage (see :ref:`firmware_design_fip`). +The storage layer is described in the header file +``include/drivers/io/io_storage.h``. The implementation of the common library is +in ``drivers/io/io_storage.c`` and the driver files are located in +``drivers/io/``. + +.. uml:: ../resources/diagrams/plantuml/io_arm_class_diagram.puml + +Each IO driver must provide ``io_dev_*`` structures, as described in +``drivers/io/io_driver.h``. These are returned via a mandatory registration +function that is called on platform initialization. The semi-hosting driver +implementation in ``io_semihosting.c`` can be used as an example. + +Each platform should register devices and their drivers via the storage +abstraction layer. These drivers then need to be initialized by bootloader +phases as required in their respective ``blx_platform_setup()`` functions. + +.. uml:: ../resources/diagrams/plantuml/io_dev_registration.puml + +The storage abstraction layer provides mechanisms (``io_dev_init()``) to +initialize storage devices before IO operations are called. + +.. uml:: ../resources/diagrams/plantuml/io_dev_init_and_check.puml + +The basic operations supported by the layer +include ``open()``, ``close()``, ``read()``, ``write()``, ``size()`` and ``seek()``. +Drivers do not have to implement all operations, but each platform must +provide at least one driver for a device capable of supporting generic +operations such as loading a bootloader image. + +The current implementation only allows for known images to be loaded by the +firmware. These images are specified by using their identifiers, as defined in +``include/plat/common/common_def.h`` (or a separate header file included from +there). The platform layer (``plat_get_image_source()``) then returns a reference +to a device and a driver-specific ``spec`` which will be understood by the driver +to allow access to the image data. + +The layer is designed in such a way that is it possible to chain drivers with +other drivers. For example, file-system drivers may be implemented on top of +physical block devices, both represented by IO devices with corresponding +drivers. In such a case, the file-system "binding" with the block device may +be deferred until the file-system device is initialised. + +The abstraction currently depends on structures being statically allocated +by the drivers and callers, as the system does not yet provide a means of +dynamically allocating memory. This may also have the affect of limiting the +amount of open resources per driver. + +-------------- + +*Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.* + +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _Arm Generic Interrupt Controller version 2.0 (GICv2): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0048b/index.html +.. _3.0 (GICv3): http://infocenter.arm.com/help/topic/com.arm.doc.ihi0069b/index.html +.. _FreeBSD: https://www.freebsd.org +.. _SCC: http://www.simple-cc.org/ diff --git a/arm-trusted-firmware/docs/getting_started/prerequisites.rst b/arm-trusted-firmware/docs/getting_started/prerequisites.rst new file mode 100644 index 0000000..ee30128 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/prerequisites.rst @@ -0,0 +1,169 @@ +Prerequisites +============= + +This document describes the software requirements for building |TF-A| for +AArch32 and AArch64 target platforms. + +It may possible to build |TF-A| with combinations of software packages that are +different from those listed below, however only the software described in this +document can be officially supported. + +Build Host +---------- + +|TF-A| can be built using either a Linux or a Windows machine as the build host. + +A relatively recent Linux distribution is recommended for building |TF-A|. We +have performed tests using Ubuntu 16.04 LTS (64-bit) but other distributions +should also work fine as a base, provided that the necessary tools and libraries +can be installed. + +.. _prerequisites_toolchain: + +Toolchain +--------- + +|TF-A| can be built with any of the following *cross-compiler* toolchains that +target the Armv7-A or Armv8-A architectures: + +- GCC >= 10.3-2021.07 (from the `Arm Developer website`_) +- Clang >= 4.0 +- Arm Compiler >= 6.0 + +In addition, a native compiler is required to build the supporting tools. + +.. note:: + The software has also been built on Windows 7 Enterprise SP1, using CMD.EXE, + Cygwin, and Msys (MinGW) shells, using version 5.3.1 of the GNU toolchain. + +.. note:: + For instructions on how to select the cross compiler refer to + :ref:`Performing an Initial Build`. + +.. _prerequisites_software_and_libraries: + +Software and Libraries +---------------------- + +The following tools are required to obtain and build |TF-A|: + +- An appropriate toolchain (see :ref:`prerequisites_toolchain`) +- GNU Make +- Git + +The following libraries must be available to build one or more components or +supporting tools: + +- OpenSSL >= 1.0.1 + + Required to build the cert_create tool. + +The following libraries are required for Trusted Board Boot support: + +- mbed TLS == 2.26.0 (tag: ``mbedtls-2.26.0``) + +These tools are optional: + +- Device Tree Compiler (DTC) >= 1.4.6 + + Needed if you want to rebuild the provided Flattened Device Tree (FDT) + source files (``.dts`` files). DTC is available for Linux through the package + repositories of most distributions. + +- Arm `Development Studio 5 (DS-5)`_ + + The standard software package used for debugging software on Arm development + platforms and |FVP| models. + +- Node.js >= 16 + + Highly recommended, and necessary in order to install and use the packaged + Git hooks and helper tools. Without these tools you will need to rely on the + CI for feedback on commit message conformance. + +Package Installation (Linux) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are using the recommended Ubuntu distribution then you can install the +required packages with the following command: + +.. code:: shell + + sudo apt install build-essential git libssl-dev + +The optional packages can be installed using: + +.. code:: shell + + sudo apt install device-tree-compiler + +Additionally, to install an up-to-date version of Node.js, you can use the `Node +Version Manager`_ to install a version of your choosing (we recommend 16, but +later LTS versions might offer a more stable experience): + +.. code:: shell + + curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.0/install.sh | "$SHELL" + exec "$SHELL" -ic "nvm install 16; exec $SHELL" + +.. _Node Version Manager: https://github.com/nvm-sh/nvm#install--update-script + +Supporting Files +---------------- + +TF-A has been tested with pre-built binaries and file systems from `Linaro +Release 20.01`_. Alternatively, you can build the binaries from source using +instructions in :ref:`Performing an Initial Build`. + +.. _prerequisites_get_source: + +Getting the TF-A Source +----------------------- + +Source code for |TF-A| is maintained in a Git repository hosted on +TrustedFirmware.org. To clone this repository from the server, run the following +in your shell: + +.. code:: shell + + git clone "https://review.trustedfirmware.org/TF-A/trusted-firmware-a" + +Additional Steps for Contributors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you are planning on contributing back to TF-A, there are some things you'll +want to know. + +TF-A is hosted by a `Gerrit Code Review`_ server. Gerrit requires that all +commits include a ``Change-Id`` footer, and this footer is typically +automatically generated by a Git hook installed by you, the developer. + +If you have Node.js installed already, you can automatically install this hook, +along with any additional hooks and Javascript-based tooling that we use, by +running from within your newly-cloned repository: + +.. code:: shell + + npm install --no-save + +If you have opted **not** to install Node.js, you can install the Gerrit hook +manually by running: + +.. code:: shell + + curl -Lo $(git rev-parse --git-dir)/hooks/commit-msg https://review.trustedfirmware.org/tools/hooks/commit-msg + chmod +x $(git rev-parse --git-dir)/hooks/commit-msg + +You can read more about Git hooks in the *githooks* page of the Git +documentation, available `here `_. + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _Arm Developer website: https://developer.arm.com/open-source/gnu-toolchain/gnu-a/downloads +.. _Gerrit Code Review: https://www.gerritcodereview.com/ +.. _Linaro Release Notes: https://community.arm.com/dev-platforms/w/docs/226/old-release-notes +.. _Linaro instructions: https://community.arm.com/dev-platforms/w/docs/304/arm-reference-platforms-deliverables +.. _Development Studio 5 (DS-5): https://developer.arm.com/products/software-development-tools/ds-5-development-studio +.. _Linaro Release 20.01: http://releases.linaro.org/members/arm/platforms/20.01 diff --git a/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst b/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst new file mode 100644 index 0000000..3735265 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst @@ -0,0 +1,546 @@ +PSCI Library Integration guide for Armv8-A AArch32 systems +========================================================== + +This document describes the PSCI library interface with a focus on how to +integrate with a suitable Trusted OS for an Armv8-A AArch32 system. The PSCI +Library implements the PSCI Standard as described in `PSCI spec`_ and is meant +to be integrated with EL3 Runtime Software which invokes the PSCI Library +interface appropriately. **EL3 Runtime Software** refers to software executing +at the highest secure privileged mode, which is EL3 in AArch64 or Secure SVC/ +Monitor mode in AArch32, and provides runtime services to the non-secure world. +The runtime service request is made via SMC (Secure Monitor Call) and the call +must adhere to `SMCCC`_. In AArch32, EL3 Runtime Software may additionally +include Trusted OS functionality. A minimal AArch32 Secure Payload, SP-MIN, is +provided in Trusted Firmware-A (TF-A) to illustrate the usage and integration +of the PSCI library. The description of PSCI library interface and its +integration with EL3 Runtime Software in this document is targeted towards +AArch32 systems. + +Generic call sequence for PSCI Library interface (AArch32) +---------------------------------------------------------- + +The generic call sequence of PSCI Library interfaces (see +`PSCI Library Interface`_) during cold boot in AArch32 +system is described below: + +#. After cold reset, the EL3 Runtime Software performs its cold boot + initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_, and also the necessary platform + setup. + +#. Call ``psci_setup()`` in Monitor mode. + +#. Optionally call ``psci_register_spd_pm_hook()`` to register callbacks to + do bookkeeping for the EL3 Runtime Software during power management. + +#. Call ``psci_prepare_next_non_secure_ctx()`` to initialize the non-secure CPU + context. + +#. Get the non-secure ``cpu_context_t`` for the current CPU by calling + ``cm_get_context()`` , then programming the registers in the non-secure + context and exiting to non-secure world. If the EL3 Runtime Software needs + additional configuration to be set for non-secure context, like routing + FIQs to the secure world, the values of the registers can be modified prior + to programming. See `PSCI CPU context management`_ for more + details on CPU context management. + +The generic call sequence of PSCI library interfaces during warm boot in +AArch32 systems is described below: + +#. After warm reset, the EL3 Runtime Software performs the necessary warm + boot initialization including the PSCI library pre-requisites mentioned in + `PSCI Library Interface`_ (Note that the Data cache + **must not** be enabled). + +#. Call ``psci_warmboot_entrypoint()`` in Monitor mode. This interface + initializes/restores the non-secure CPU context as well. + +#. Do step 5 of the cold boot call sequence described above. + +The generic call sequence of PSCI library interfaces on receipt of a PSCI SMC +on an AArch32 system is described below: + +#. On receipt of an SMC, save the register context as per `SMCCC`_. + +#. If the SMC function identifier corresponds to a SMC32 PSCI API, construct + the appropriate arguments and call the ``psci_smc_handler()`` interface. + The invocation may or may not return back to the caller depending on + whether the PSCI API resulted in power down of the CPU. + +#. If ``psci_smc_handler()`` returns, populate the return value in R0 (AArch32)/ + X0 (AArch64) and restore other registers as per `SMCCC`_. + +PSCI CPU context management +--------------------------- + +PSCI library is in charge of initializing/restoring the non-secure CPU system +registers according to `PSCI specification`_ during cold/warm boot. +This is referred to as ``PSCI CPU Context Management``. Registers that need to +be preserved across CPU power down/power up cycles are maintained in +``cpu_context_t`` data structure. The initialization of other non-secure CPU +system registers which do not require coordination with the EL3 Runtime +Software is done directly by the PSCI library (see ``cm_prepare_el3_exit()``). + +The EL3 Runtime Software is responsible for managing register context +during switch between Normal and Secure worlds. The register context to be +saved and restored depends on the mechanism used to trigger the world switch. +For example, if the world switch was triggered by an SMC call, then the +registers need to be saved and restored according to `SMCCC`_. In AArch64, +due to the tight integration with BL31, both BL31 and PSCI library +use the same ``cpu_context_t`` data structure for PSCI CPU context management +and register context management during world switch. This cannot be assumed +for AArch32 EL3 Runtime Software since most AArch32 Trusted OSes already implement +a mechanism for register context management during world switch. Hence, when +the PSCI library is integrated with a AArch32 EL3 Runtime Software, the +``cpu_context_t`` is stripped down for just PSCI CPU context management. + +During cold/warm boot, after invoking appropriate PSCI library interfaces, it +is expected that the EL3 Runtime Software will query the ``cpu_context_t`` and +write appropriate values to the corresponding system registers. This mechanism +resolves 2 additional problems for AArch32 EL3 Runtime Software: + +#. Values for certain system registers like SCR and SCTLR cannot be + unilaterally determined by PSCI library and need inputs from the EL3 + Runtime Software. Using ``cpu_context_t`` as an intermediary data store + allows EL3 Runtime Software to modify the register values appropriately + before programming them. + +#. The PSCI library provides appropriate LR and SPSR values (entrypoint + information) for exit into non-secure world. Using ``cpu_context_t`` as an + intermediary data store allows the EL3 Runtime Software to store these + values safely until it is ready for exit to non-secure world. + +Currently the ``cpu_context_t`` data structure for AArch32 stores the following +registers: R0 - R3, LR (R14), SCR, SPSR, SCTLR. + +The EL3 Runtime Software must implement accessors to get/set pointers +to CPU context ``cpu_context_t`` data and these are described in +`CPU Context management API`_. + +PSCI Library Interface +---------------------- + +The PSCI library implements the `PSCI Specification`_. The interfaces +to this library are declared in ``psci_lib.h`` and are as listed below: + +.. code:: c + + u_register_t psci_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); + int psci_setup(const psci_lib_args_t *lib_args); + void psci_warmboot_entrypoint(void); + void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); + void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info); + +The CPU context data 'cpu_context_t' is programmed to the registers differently +when PSCI is integrated with an AArch32 EL3 Runtime Software compared to +when the PSCI is integrated with an AArch64 EL3 Runtime Software (BL31). For +example, in the case of AArch64, there is no need to retrieve ``cpu_context_t`` +data and program the registers as it will done implicitly as part of +``el3_exit``. The description below of the PSCI interfaces is targeted at +integration with an AArch32 EL3 Runtime Software. + +The PSCI library is responsible for initializing/restoring the non-secure world +to an appropriate state after boot and may choose to directly program the +non-secure system registers. The PSCI generic code takes care not to directly +modify any of the system registers affecting the secure world and instead +returns the values to be programmed to these registers via ``cpu_context_t``. +The EL3 Runtime Software is responsible for programming those registers and +can use the proposed values provided in the ``cpu_context_t``, modifying the +values if required. + +PSCI library needs the flexibility to access both secure and non-secure +copies of banked registers. Hence it needs to be invoked in Monitor mode +for AArch32 and in EL3 for AArch64. The NS bit in SCR (in AArch32) or SCR_EL3 +(in AArch64) must be set to 0. Additional requirements for the PSCI library +interfaces are: + +- Instruction cache must be enabled +- Both IRQ and FIQ must be masked for the current CPU +- The page tables must be setup and the MMU enabled +- The C runtime environment must be setup and stack initialized +- The Data cache must be enabled prior to invoking any of the PSCI library + interfaces except for ``psci_warmboot_entrypoint()``. For + ``psci_warmboot_entrypoint()``, if the build option ``HW_ASSISTED_COHERENCY`` + is enabled however, data caches are expected to be enabled. + +Further requirements for each interface can be found in the interface +description. + +Interface : psci_setup() +~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const psci_lib_args_t *lib_args + Return : void + +This function is to be called by the primary CPU during cold boot before +any other interface to the PSCI library. It takes ``lib_args``, a const pointer +to ``psci_lib_args_t``, as the argument. The ``psci_lib_args_t`` is a versioned +structure and is declared in ``psci_lib.h`` header as follows: + +.. code:: c + + typedef struct psci_lib_args { + /* The version information of PSCI Library Interface */ + param_header_t h; + /* The warm boot entrypoint function */ + mailbox_entrypoint_t mailbox_ep; + } psci_lib_args_t; + +The first field ``h``, of ``param_header_t`` type, provides the version +information. The second field ``mailbox_ep`` is the warm boot entrypoint address +and is used to configure the platform mailbox. Helper macros are provided in +``psci_lib.h`` to construct the ``lib_args`` argument statically or during +runtime. Prior to calling the ``psci_setup()`` interface, the platform setup for +cold boot must have completed. Major actions performed by this interface are: + +- Initializes architecture. +- Initializes PSCI power domain and state coordination data structures. +- Calls ``plat_setup_psci_ops()`` with warm boot entrypoint ``mailbox_ep`` as + argument. +- Calls ``cm_set_context_by_index()`` (see + `CPU Context management API`_) for all the CPUs in the + platform + +Interface : psci_prepare_next_non_secure_ctx() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : entry_point_info_t *next_image_info + Return : void + +After ``psci_setup()`` and prior to exit to the non-secure world, this function +must be called by the EL3 Runtime Software to initialize the non-secure world +context. The non-secure world entrypoint information ``next_image_info`` (first +argument) will be used to determine the non-secure context. After this function +returns, the EL3 Runtime Software must retrieve the ``cpu_context_t`` (using +cm_get_context()) for the current CPU and program the registers prior to exit +to the non-secure world. + +Interface : psci_register_spd_pm_hook() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : const spd_pm_ops_t * + Return : void + +As explained in `Secure payload power management callback`_, +the EL3 Runtime Software may want to perform some bookkeeping during power +management operations. This function is used to register the ``spd_pm_ops_t`` +(first argument) callbacks with the PSCI library which will be called +appropriately during power management. Calling this function is optional and +need to be called by the primary CPU during the cold boot sequence after +``psci_setup()`` has completed. + +Interface : psci_smc_handler() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : 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 + Return : u_register_t + +This function is the top level handler for SMCs which fall within the +PSCI service range specified in `SMCCC`_. The function ID ``smc_fid`` (first +argument) determines the PSCI API to be called. The ``x1`` to ``x4`` (2nd to 5th +arguments), are the values of the registers r1 - r4 (in AArch32) or x1 - x4 +(in AArch64) when the SMC is received. These are the arguments to PSCI API as +described in `PSCI spec`_. The 'flags' (8th argument) is a bit field parameter +and is detailed in 'smccc.h' header. It includes whether the call is from the +secure or non-secure world. The ``cookie`` (6th argument) and the ``handle`` +(7th argument) are not used and are reserved for future use. + +The return value from this interface is the return value from the underlying +PSCI API corresponding to ``smc_fid``. This function may not return back to the +caller if PSCI API causes power down of the CPU. In this case, when the CPU +wakes up, it will start execution from the warm reset address. + +Interface : psci_warmboot_entrypoint() +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +:: + + Argument : void + Return : void + +This function performs the warm boot initialization/restoration as mandated by +`PSCI spec`_. For AArch32, on wakeup from power down the CPU resets to secure SVC +mode and the EL3 Runtime Software must perform the prerequisite initializations +mentioned at top of this section. This function must be called with Data cache +disabled (unless build option ``HW_ASSISTED_COHERENCY`` is enabled) but with MMU +initialized and enabled. The major actions performed by this function are: + +- Invalidates the stack and enables the data cache. +- Initializes architecture and PSCI state coordination. +- Restores/Initializes the peripheral drivers to the required state via + appropriate ``plat_psci_ops_t`` hooks +- Restores the EL3 Runtime Software context via appropriate ``spd_pm_ops_t`` + callbacks. +- Restores/Initializes the non-secure context and populates the + ``cpu_context_t`` for the current CPU. + +Upon the return of this function, the EL3 Runtime Software must retrieve the +non-secure ``cpu_context_t`` using ``cm_get_context()`` and program the registers +prior to exit to the non-secure world. + +EL3 Runtime Software dependencies +--------------------------------- + +The PSCI Library includes supporting frameworks like context management, +cpu operations (cpu_ops) and per-cpu data framework. Other helper library +functions like bakery locks and spin locks are also included in the library. +The dependencies which must be fulfilled by the EL3 Runtime Software +for integration with PSCI library are described below. + +General dependencies +~~~~~~~~~~~~~~~~~~~~ + +The PSCI library being a Multiprocessor (MP) implementation, EL3 Runtime +Software must provide an SMC handling framework capable of MP adhering to +`SMCCC`_ specification. + +The EL3 Runtime Software must also export cache maintenance primitives +and some helper utilities for assert, print and memory operations as listed +below. The TF-A source tree provides implementations for all +these functions but the EL3 Runtime Software may use its own implementation. + +**Functions : assert(), memcpy(), memset(), printf()** + +These must be implemented as described in ISO C Standard. + +**Function : flush_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function cleans and invalidates (flushes) the data cache for memory +at address ``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : inv_dcache_range()** + +:: + + Argument : uintptr_t addr, size_t size + Return : void + +This function invalidates (flushes) the data cache for memory at address +``addr`` (first argument) address and of size ``size`` (second argument). + +**Function : do_panic()** + +:: + + Argument : void + Return : void + +This function will be called by the PSCI library on encountering a critical +failure that cannot be recovered from. This function **must not** return. + +CPU Context management API +~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The CPU context management data memory is statically allocated by PSCI library +in BSS section. The PSCI library requires the EL3 Runtime Software to implement +APIs to store and retrieve pointers to this CPU context data. SP-MIN +demonstrates how these APIs can be implemented but the EL3 Runtime Software can +choose a more optimal implementation (like dedicating the secure TPIDRPRW +system register (in AArch32) for storing these pointers). + +**Function : cm_set_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, void *context, unsigned int security_state + Return : void + +This function is called during cold boot when the ``psci_setup()`` PSCI library +interface is called. + +This function must store the pointer to the CPU context data, ``context`` (2nd +argument), for the specified ``security_state`` (3rd argument) and CPU identified +by ``cpu_idx`` (first argument). The ``security_state`` will always be non-secure +when called by PSCI library and this argument is retained for compatibility +with BL31. The ``cpu_idx`` will correspond to the index returned by the +``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +The actual method of storing the ``context`` pointers is implementation specific. +For example, SP-MIN stores the pointers in the array ``sp_min_cpu_ctx_ptr`` +declared in ``sp_min_main.c``. + +**Function : cm_get_context()** + +:: + + Argument : uint32_t security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (first argument) for the current CPU. The caller +must ensure that ``cm_set_context_by_index`` is called first and the appropriate +context pointers are stored prior to invoking this API. The ``security_state`` +will always be non-secure when called by PSCI library and this argument +is retained for compatibility with BL31. + +**Function : cm_get_context_by_index()** + +:: + + Argument : unsigned int cpu_idx, unsigned int security_state + Return : void * + +This function must return the pointer to the ``cpu_context_t`` structure for +the specified ``security_state`` (second argument) for the CPU identified by +``cpu_idx`` (first argument). The caller must ensure that +``cm_set_context_by_index`` is called first and the appropriate context +pointers are stored prior to invoking this API. The ``security_state`` will +always be non-secure when called by PSCI library and this argument is +retained for compatibility with BL31. The ``cpu_idx`` will correspond to the +index returned by the ``plat_core_pos_by_mpidr()`` for ``mpidr`` of the CPU. + +Platform API +~~~~~~~~~~~~ + +The platform layer abstracts the platform-specific details from the generic +PSCI library. The following platform APIs/macros must be defined by the EL3 +Runtime Software for integration with the PSCI library. + +The mandatory platform APIs are: + +- plat_my_core_pos +- plat_core_pos_by_mpidr +- plat_get_syscnt_freq2 +- plat_get_power_domain_tree_desc +- plat_setup_psci_ops +- plat_reset_handler +- plat_panic_handler +- plat_get_my_stack + +The mandatory platform macros are: + +- PLATFORM_CORE_COUNT +- PLAT_MAX_PWR_LVL +- PLAT_NUM_PWR_DOMAINS +- CACHE_WRITEBACK_GRANULE +- PLAT_MAX_OFF_STATE +- PLAT_MAX_RET_STATE +- PLAT_MAX_PWR_LVL_STATES (optional) +- PLAT_PCPU_DATA_SIZE (optional) + +The details of these APIs/macros can be found in the :ref:`Porting Guide`. + +All platform specific operations for power management are done via +``plat_psci_ops_t`` callbacks registered by the platform when +``plat_setup_psci_ops()`` API is called. The description of each of +the callbacks in ``plat_psci_ops_t`` can be found in PSCI section of the +:ref:`Porting Guide`. If any these callbacks are not registered, then the +PSCI API associated with that callback will not be supported by PSCI +library. + +Secure payload power management callback +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +During PSCI power management operations, the EL3 Runtime Software may +need to perform some bookkeeping, and PSCI library provides +``spd_pm_ops_t`` callbacks for this purpose. These hooks must be +populated and registered by using ``psci_register_spd_pm_hook()`` PSCI +library interface. + +Typical bookkeeping during PSCI power management calls include save/restore +of the EL3 Runtime Software context. Also if the EL3 Runtime Software makes +use of secure interrupts, then these interrupts must also be managed +appropriately during CPU power down/power up. Any secure interrupt targeted +to the current CPU must be disabled or re-targeted to other running CPU prior +to power down of the current CPU. During power up, these interrupt can be +enabled/re-targeted back to the current CPU. + +.. code:: c + + typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __unused); + void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); + int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); + int32_t (*svc_migrate_info)(u_register_t *resident_cpu); + void (*svc_system_off)(void); + void (*svc_system_reset)(void); + } spd_pm_ops_t; + +A brief description of each callback is given below: + +- svc_on, svc_off, svc_on_finish + + The ``svc_on``, ``svc_off`` callbacks are called during PSCI_CPU_ON, + PSCI_CPU_OFF APIs respectively. The ``svc_on_finish`` is called when the + target CPU of PSCI_CPU_ON API powers up and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. + +- svc_suspend, svc_suspend_finish + + The ``svc_suspend`` callback is called during power down bu either + PSCI_SUSPEND or PSCI_SYSTEM_SUSPEND APIs. The ``svc_suspend_finish`` is + called when the CPU wakes up from suspend and executes the + ``psci_warmboot_entrypoint()`` PSCI library interface. The ``max_off_pwrlvl`` + (first parameter) denotes the highest power domain level being powered down + to or woken up from suspend. + +- svc_system_off, svc_system_reset + + These callbacks are called during PSCI_SYSTEM_OFF and PSCI_SYSTEM_RESET + PSCI APIs respectively. + +- svc_migrate_info + + This callback is called in response to PSCI_MIGRATE_INFO_TYPE or + PSCI_MIGRATE_INFO_UP_CPU APIs. The return value of this callback must + correspond to the return value of PSCI_MIGRATE_INFO_TYPE API as described + in `PSCI spec`_. If the secure payload is a Uniprocessor (UP) + implementation, then it must update the mpidr of the CPU it is resident in + via ``resident_cpu`` (first argument). The updates to ``resident_cpu`` is + ignored if the secure payload is a multiprocessor (MP) implementation. + +- svc_migrate + + This callback is only relevant if the secure payload in EL3 Runtime + Software is a Uniprocessor (UP) implementation and supports migration from + the current CPU ``from_cpu`` (first argument) to another CPU ``to_cpu`` + (second argument). This callback is called in response to PSCI_MIGRATE + API. This callback is never called if the secure payload is a + Multiprocessor (MP) implementation. + +CPU operations +~~~~~~~~~~~~~~ + +The CPU operations (cpu_ops) framework implement power down sequence specific +to the CPU and the details of which can be found at +:ref:`firmware_design_cpu_ops_fwk`. The TF-A tree implements the ``cpu_ops`` +for various supported CPUs and the EL3 Runtime Software needs to include the +required ``cpu_ops`` in its build. The start and end of the ``cpu_ops`` +descriptors must be exported by the EL3 Runtime Software via the +``__CPU_OPS_START__`` and ``__CPU_OPS_END__`` linker symbols. + +The ``cpu_ops`` descriptors also include reset sequences and may include errata +workarounds for the CPU. The EL3 Runtime Software can choose to call this +during cold/warm reset if it does not implement its own reset sequence/errata +workarounds. + +-------------- + +*Copyright (c) 2016-2020, Arm Limited and Contributors. All rights reserved.* + +.. _PSCI spec: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf +.. _PSCI Specification: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf diff --git a/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst b/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst new file mode 100644 index 0000000..5a4be4d --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst @@ -0,0 +1,320 @@ +EL3 Runtime Service Writer's Guide +===================================================== + +Introduction +------------ + +This document describes how to add a runtime service to the EL3 Runtime +Firmware component of Trusted Firmware-A (TF-A), BL31. + +Software executing in the normal world and in the trusted world at exception +levels lower than EL3 will request runtime services using the Secure Monitor +Call (SMC) instruction. These requests will follow the convention described in +the SMC Calling Convention PDD (`SMCCC`_). The `SMCCC`_ assigns function +identifiers to each SMC request and describes how arguments are passed and +results are returned. + +SMC Functions are grouped together based on the implementor of the service, for +example a subset of the Function IDs are designated as "OEM Calls" (see `SMCCC`_ +for full details). The EL3 runtime services framework in BL31 enables the +independent implementation of services for each group, which are then compiled +into the BL31 image. This simplifies the integration of common software from +Arm to support `PSCI`_, Secure Monitor for a Trusted OS and SoC specific +software. The common runtime services framework ensures that SMC Functions are +dispatched to their respective service implementation - the +:ref:`Firmware Design` document provides details of how this is achieved. + +The interface and operation of the runtime services depends heavily on the +concepts and definitions described in the `SMCCC`_, in particular SMC Function +IDs, Owning Entity Numbers (OEN), Fast and Standard calls, and the SMC32 and +SMC64 calling conventions. Please refer to that document for a full explanation +of these terms. + +Owning Entities, Call Types and Function IDs +-------------------------------------------- + +The SMC Function Identifier includes a OEN field. These values and their +meaning are described in `SMCCC`_ and summarized in table 1 below. Some entities +are allocated a range of of OENs. The OEN must be interpreted in conjunction +with the SMC call type, which is either *Fast* or *Yielding*. Fast calls are +uninterruptible whereas Yielding calls can be pre-empted. The majority of +Owning Entities only have allocated ranges for Fast calls: Yielding calls are +reserved exclusively for Trusted OS providers or for interoperability with +legacy 32-bit software that predates the `SMCCC`_. + +:: + + Type OEN Service + Fast 0 Arm Architecture calls + Fast 1 CPU Service calls + Fast 2 SiP Service calls + Fast 3 OEM Service calls + Fast 4 Standard Service calls + Fast 5-47 Reserved for future use + Fast 48-49 Trusted Application calls + Fast 50-63 Trusted OS calls + + Yielding 0- 1 Reserved for existing Armv7-A calls + Yielding 2-63 Trusted OS Standard Calls + +*Table 1: Service types and their corresponding Owning Entity Numbers* + +Each individual entity can allocate the valid identifiers within the entity +range as they need - it is not necessary to coordinate with other entities of +the same type. For example, two SoC providers can use the same Function ID +within the SiP Service calls OEN range to mean different things - as these +calls should be specific to the SoC. The Standard Runtime Calls OEN is used for +services defined by Arm standards, such as `PSCI`_. + +The SMC Function ID also indicates whether the call has followed the SMC32 +calling convention, where all parameters are 32-bit, or the SMC64 calling +convention, where the parameters are 64-bit. The framework identifies and +rejects invalid calls that use the SMC64 calling convention but that originate +from an AArch32 caller. + +The EL3 runtime services framework uses the call type and OEN to identify a +specific handler for each SMC call, but it is expected that an individual +handler will be responsible for all SMC Functions within a given service type. + +Getting started +--------------- + +TF-A has a ``services`` directory in the source tree under which +each owning entity can place the implementation of its runtime service. The +`PSCI`_ implementation is located here in the ``lib/psci`` directory. + +Runtime service sources will need to include the ``runtime_svc.h`` header file. + +Registering a runtime service +----------------------------- + +A runtime service is registered using the ``DECLARE_RT_SVC()`` macro, specifying +the name of the service, the range of OENs covered, the type of service and +initialization and call handler functions. + +.. code:: c + + #define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) + +- ``_name`` is used to identify the data structure declared by this macro, and + is also used for diagnostic purposes + +- ``_start`` and ``_end`` values must be based on the ``OEN_*`` values defined in + ``smccc.h`` + +- ``_type`` must be one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` + +- ``_setup`` is the initialization function with the ``rt_svc_init`` signature: + + .. code:: c + + typedef int32_t (*rt_svc_init)(void); + +- ``_smch`` is the SMC handler function with the ``rt_svc_handle`` signature: + + .. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(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); + +Details of the requirements and behavior of the two callbacks is provided in +the following sections. + +During initialization the services framework validates each declared service +to ensure that the following conditions are met: + +#. The ``_start`` OEN is not greater than the ``_end`` OEN +#. The ``_end`` OEN does not exceed the maximum OEN value (63) +#. The ``_type`` is one of ``SMC_TYPE_FAST`` or ``SMC_TYPE_YIELD`` +#. ``_setup`` and ``_smch`` routines have been specified + +``std_svc_setup.c`` provides an example of registering a runtime service: + +.. code:: c + + /* Register Standard Service Calls as runtime service */ + DECLARE_RT_SVC( + std_svc, + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler + ); + +Initializing a runtime service +------------------------------ + +Runtime services are initialized once, during cold boot, by the primary CPU +after platform and architectural initialization is complete. The framework +performs basic validation of the declared service before calling +the service initialization function (``_setup`` in the declaration). This +function must carry out any essential EL3 initialization prior to receiving a +SMC Function call via the handler function. + +On success, the initialization function must return ``0``. Any other return value +will cause the framework to issue a diagnostic: + +:: + + Error initializing runtime service + +and then ignore the service - the system will continue to boot but SMC calls +will not be passed to the service handler and instead return the *Unknown SMC +Function ID* result ``0xFFFFFFFF``. + +If the system must not be allowed to proceed without the service, the +initialization function must itself cause the firmware boot to be halted. + +If the service uses per-CPU data this must either be initialized for all CPUs +during this call, or be done lazily when a CPU first issues an SMC call to that +service. + +Handling runtime service requests +--------------------------------- + +SMC calls for a service are forwarded by the framework to the service's SMC +handler function (``_smch`` in the service declaration). This function must have +the following signature: + +.. code:: c + + typedef uintptr_t (*rt_svc_handle_t)(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); + +The handler is responsible for: + +#. Determining that ``smc_fid`` is a valid and supported SMC Function ID, + otherwise completing the request with the *Unknown SMC Function ID*: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Determining if the requested function is valid for the calling security + state. SMC Calls can be made from Non-secure, Secure or Realm worlds and + the framework will forward all calls to the service handler. + + The ``flags`` parameter to this function indicates the caller security state + in bits 0 and 5. The ``is_caller_secure(flags)``, ``is_caller_non_secure(flags)`` + and ``is_caller_realm(flags)`` helper functions can be used to determine whether + the caller's security state is Secure, Non-secure or Realm respectively. + + If invalid, the request should be completed with: + + .. code:: c + + SMC_RET1(handle, SMC_UNK); + +#. Truncating parameters for calls made using the SMC32 calling convention. + Such calls can be determined by checking the CC field in bit[30] of the + ``smc_fid`` parameter, for example by using: + + :: + + if (GET_SMC_CC(smc_fid) == SMC_32) ... + + For such calls, the upper bits of the parameters x1-x4 and the saved + parameters X5-X7 are UNDEFINED and must be explicitly ignored by the + handler. This can be done by truncating the values to a suitable 32-bit + integer type before use, for example by ensuring that functions defined + to handle individual SMC Functions use appropriate 32-bit parameters. + +#. Providing the service requested by the SMC Function, utilizing the + immediate parameters x1-x4 and/or the additional saved parameters X5-X7. + The latter can be retrieved using the ``SMC_GET_GP(handle, ref)`` function, + supplying the appropriate ``CTX_GPREG_Xn`` reference, e.g. + + .. code:: c + + uint64_t x6 = SMC_GET_GP(handle, CTX_GPREG_X6); + +#. Implementing the standard SMC32 Functions that provide information about + the implementation of the service. These are the Call Count, Implementor + UID and Revision Details for each service documented in section 6 of the + `SMCCC`_. + + TF-A expects owning entities to follow this recommendation. + +#. Returning the result to the caller. Based on `SMCCC`_ spec, results are + returned in W0-W7(X0-X7) registers for SMC32(SMC64) calls from AArch64 + state. Results are returned in R0-R7 registers for SMC32 calls from AArch32 + state. The framework provides a family of macros to set the multi-register + return value and complete the handler: + + .. code:: c + + AArch64 state: + + SMC_RET1(handle, x0); + SMC_RET2(handle, x0, x1); + SMC_RET3(handle, x0, x1, x2); + SMC_RET4(handle, x0, x1, x2, x3); + SMC_RET5(handle, x0, x1, x2, x3, x4); + SMC_RET6(handle, x0, x1, x2, x3, x4, x5); + SMC_RET7(handle, x0, x1, x2, x3, x4, x5, x6); + SMC_RET8(handle, x0, x1, x2, x3, x4, x5, x6, x7); + + AArch32 state: + + SMC_RET1(handle, r0); + SMC_RET2(handle, r0, r1); + SMC_RET3(handle, r0, r1, r2); + SMC_RET4(handle, r0, r1, r2, r3); + SMC_RET5(handle, r0, r1, r2, r3, r4); + SMC_RET6(handle, r0, r1, r2, r3, r4, r5); + SMC_RET7(handle, r0, r1, r2, r3, r4, r5, r6); + SMC_RET8(handle, r0, r1, r2, r3, r4, r5, r6, r7); + +The ``cookie`` parameter to the handler is reserved for future use and can be +ignored. The ``handle`` is returned by the SMC handler - completion of the +handler function must always be via one of the ``SMC_RETn()`` macros. + +.. note:: + The PSCI and Test Secure-EL1 Payload Dispatcher services do not follow + all of the above requirements yet. + +Services that contain multiple sub-services +------------------------------------------- + +It is possible that a single owning entity implements multiple sub-services. For +example, the Standard calls service handles ``0x84000000``-``0x8400FFFF`` and +``0xC4000000``-``0xC400FFFF`` functions. Within that range, the `PSCI`_ service +handles the ``0x84000000``-``0x8400001F`` and ``0xC4000000``-``0xC400001F`` functions. +In that respect, `PSCI`_ is a 'sub-service' of the Standard calls service. In +future, there could be additional such sub-services in the Standard calls +service which perform independent functions. + +In this situation it may be valuable to introduce a second level framework to +enable independent implementation of sub-services. Such a framework might look +very similar to the current runtime services framework, but using a different +part of the SMC Function ID to identify the sub-service. TF-A does not provide +such a framework at present. + +Secure-EL1 Payload Dispatcher service (SPD) +------------------------------------------- + +Services that handle SMC Functions targeting a Trusted OS, Trusted Application, +or other Secure-EL1 Payload are special. These services need to manage the +Secure-EL1 context, provide the *Secure Monitor* functionality of switching +between the normal and secure worlds, deliver SMC Calls through to Secure-EL1 +and generally manage the Secure-EL1 Payload through CPU power-state transitions. + +TODO: Provide details of the additional work required to implement a SPD and +the BL31 support for these services. Or a reference to the document that will +provide this information.... + +-------------- + +*Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved.* + +.. _SMCCC: https://developer.arm.com/docs/den0028/latest +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022c/DEN0022C_Power_State_Coordination_Interface.pdf diff --git a/arm-trusted-firmware/docs/getting_started/tools-build.rst b/arm-trusted-firmware/docs/getting_started/tools-build.rst new file mode 100644 index 0000000..c050f58 --- /dev/null +++ b/arm-trusted-firmware/docs/getting_started/tools-build.rst @@ -0,0 +1,167 @@ +Building Supporting Tools +========================= + +Building and using the FIP tool +------------------------------- + +Firmware Image Package (FIP) is a packaging format used by TF-A to package +firmware images in a single binary. The number and type of images that should +be packed in a FIP is platform specific and may include TF-A images and other +firmware images required by the platform. For example, most platforms require +a BL33 image which corresponds to the normal world bootloader (e.g. UEFI or +U-Boot). + +The TF-A build system provides the make target ``fip`` to create a FIP file +for the specified platform using the FIP creation tool included in the TF-A +project. Examples below show how to build a FIP file for FVP, packaging TF-A +and BL33 images. + +For AArch64: + +.. code:: shell + + make PLAT=fvp BL33=/bl33.bin fip + +For AArch32: + +.. code:: shell + + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=/bl33.bin fip + +The resulting FIP may be found in: + +:: + + build/fvp//fip.bin + +For advanced operations on FIP files, it is also possible to independently build +the tool and create or modify FIPs using this tool. To do this, follow these +steps: + +It is recommended to remove old artifacts before building the tool: + +.. code:: shell + + make -C tools/fiptool clean + +Build the tool: + +.. code:: shell + + make [DEBUG=1] [V=1] fiptool + +The tool binary can be located in: + +:: + + ./tools/fiptool/fiptool + +Invoking the tool with ``help`` will print a help message with all available +options. + +Example 1: create a new Firmware package ``fip.bin`` that contains BL2 and BL31: + +.. code:: shell + + ./tools/fiptool/fiptool create \ + --tb-fw build///bl2.bin \ + --soc-fw build///bl31.bin \ + fip.bin + +Example 2: view the contents of an existing Firmware package: + +.. code:: shell + + ./tools/fiptool/fiptool info /fip.bin + +Example 3: update the entries of an existing Firmware package: + +.. code:: shell + + # Change the BL2 from Debug to Release version + ./tools/fiptool/fiptool update \ + --tb-fw build//release/bl2.bin \ + build//debug/fip.bin + +Example 4: unpack all entries from an existing Firmware package: + +.. code:: shell + + # Images will be unpacked to the working directory + ./tools/fiptool/fiptool unpack /fip.bin + +Example 5: remove an entry from an existing Firmware package: + +.. code:: shell + + ./tools/fiptool/fiptool remove \ + --tb-fw build//debug/fip.bin + +Note that if the destination FIP file exists, the create, update and +remove operations will automatically overwrite it. + +The unpack operation will fail if the images already exist at the +destination. In that case, use -f or --force to continue. + +More information about FIP can be found in the :ref:`Firmware Design` document. + +.. _tools_build_cert_create: + +Building the Certificate Generation Tool +---------------------------------------- + +The ``cert_create`` tool is built as part of the TF-A build process when the +``fip`` make target is specified and TBB is enabled (as described in the +previous section), but it can also be built separately with the following +command: + +.. code:: shell + + make PLAT= [DEBUG=1] [V=1] certtool + +For platforms that require their own IDs in certificate files, the generic +'cert_create' tool can be built with the following command. Note that the target +platform must define its IDs within a ``platform_oid.h`` header file for the +build to succeed. + +.. code:: shell + + make PLAT= USE_TBBR_DEFS=0 [DEBUG=1] [V=1] certtool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +.. code:: shell + + ./tools/cert_create/cert_create -h + +.. _tools_build_enctool: + +Building the Firmware Encryption Tool +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``encrypt_fw`` tool is built as part of the TF-A build process when the +``fip`` make target is specified, DECRYPTION_SUPPORT and TBB are enabled, but +it can also be built separately with the following command: + +.. code:: shell + + make PLAT= [DEBUG=1] [V=1] enctool + +``DEBUG=1`` builds the tool in debug mode. ``V=1`` makes the build process more +verbose. The following command should be used to obtain help about the tool: + +.. code:: shell + + ./tools/encrypt_fw/encrypt_fw -h + +Note that the enctool in its current implementation only supports encryption +key to be provided in plain format. A typical implementation can very well +extend this tool to support custom techniques to protect encryption key. + +Also, a user may choose to provide encryption key or nonce as an input file +via using ``cat `` instead of a hex string. + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/global_substitutions.txt b/arm-trusted-firmware/docs/global_substitutions.txt new file mode 100644 index 0000000..0cf2946 --- /dev/null +++ b/arm-trusted-firmware/docs/global_substitutions.txt @@ -0,0 +1,68 @@ +.. |AArch32| replace:: :term:`AArch32` +.. |AArch64| replace:: :term:`AArch64` +.. |AMU| replace:: :term:`AMU` +.. |AMUs| replace:: :term:`AMUs ` +.. |API| replace:: :term:`API` +.. |BTI| replace:: :term:`BTI` +.. |CoT| replace:: :term:`CoT` +.. |COT| replace:: :term:`COT` +.. |CSS| replace:: :term:`CSS` +.. |CVE| replace:: :term:`CVE` +.. |DTB| replace:: :term:`DTB` +.. |DS-5| replace:: :term:`DS-5` +.. |DSU| replace:: :term:`DSU` +.. |DT| replace:: :term:`DT` +.. |EL| replace:: :term:`EL` +.. |EHF| replace:: :term:`EHF` +.. |FCONF| replace:: :term:`FCONF` +.. |FDT| replace:: :term:`FDT` +.. |FF-A| replace:: :term:`FF-A` +.. |FIP| replace:: :term:`FIP` +.. |FVP| replace:: :term:`FVP` +.. |FWU| replace:: :term:`FWU` +.. |GIC| replace:: :term:`GIC` +.. |ISA| replace:: :term:`ISA` +.. |Linaro| replace:: :term:`Linaro` +.. |MMU| replace:: :term:`MMU` +.. |MPAM| replace:: :term:`MPAM` +.. |MPMM| replace:: :term:`MPMM` +.. |MPIDR| replace:: :term:`MPIDR` +.. |MTE| replace:: :term:`MTE` +.. |OEN| replace:: :term:`OEN` +.. |OP-TEE| replace:: :term:`OP-TEE` +.. |OTE| replace:: :term:`OTE` +.. |PDD| replace:: :term:`PDD` +.. |PAUTH| replace:: :term:`PAUTH` +.. |PMF| replace:: :term:`PMF` +.. |PSCI| replace:: :term:`PSCI` +.. |RAS| replace:: :term:`RAS` +.. |ROT| replace:: :term:`ROT` +.. |SCMI| replace:: :term:`SCMI` +.. |SCP| replace:: :term:`SCP` +.. |SDEI| replace:: :term:`SDEI` +.. |SDS| replace:: :term:`SDS` +.. |SEA| replace:: :term:`SEA` +.. |SiP| replace:: :term:`SiP` +.. |SIP| replace:: :term:`SIP` +.. |SMC| replace:: :term:`SMC` +.. |SMCCC| replace:: :term:`SMCCC` +.. |SoC| replace:: :term:`SoC` +.. |SP| replace:: :term:`SP` +.. |SPD| replace:: :term:`SPD` +.. |SPM| replace:: :term:`SPM` +.. |SSBS| replace:: :term:`SSBS` +.. |SVE| replace:: :term:`SVE` +.. |TBB| replace:: :term:`TBB` +.. |TBBR| replace:: :term:`TBBR` +.. |TEE| replace:: :term:`TEE` +.. |TF-A| replace:: :term:`TF-A` +.. |TF-M| replace:: :term:`TF-M` +.. |TLB| replace:: :term:`TLB` +.. |TLK| replace:: :term:`TLK` +.. |TRNG| replace:: :term:`TRNG` +.. |TSP| replace:: :term:`TSP` +.. |TZC| replace:: :term:`TZC` +.. |UBSAN| replace:: :term:`UBSAN` +.. |UEFI| replace:: :term:`UEFI` +.. |WDOG| replace:: :term:`WDOG` +.. |XLAT| replace:: :term:`XLAT` diff --git a/arm-trusted-firmware/docs/glossary.rst b/arm-trusted-firmware/docs/glossary.rst new file mode 100644 index 0000000..aeeb133 --- /dev/null +++ b/arm-trusted-firmware/docs/glossary.rst @@ -0,0 +1,225 @@ +Glossary +======== + +This glossary provides definitions for terms and abbreviations used in the TF-A +documentation. + +You can find additional definitions in the `Arm Glossary`_. + +.. glossary:: + :sorted: + + AArch32 + 32-bit execution state of the ARMv8 ISA + + AArch64 + 64-bit execution state of the ARMv8 ISA + + AMU + Activity Monitor Unit, a hardware monitoring unit introduced by FEAT_AMUv1 + that exposes CPU core runtime metrics as a set of counter registers. + + API + Application Programming Interface + + AT + Address Translation + + BTI + Branch Target Identification. An Armv8.5 extension providing additional + control flow integrity around indirect branches and their targets. + + CoT + COT + Chain of Trust + + CSS + Compute Sub-System + + CVE + Common Vulnerabilities and Exposures. A CVE document is commonly used to + describe a publicly-known security vulnerability. + + DS-5 + Arm Development Studio 5 + + DSU + DynamIQ Shared Unit + + DT + Device Tree + + DTB + Device Tree Blob + + EL + Exception Level + + EHF + Exception Handling Framework + + FCONF + Firmware Configuration Framework + + FDT + Flattened Device Tree + + FF-A + Firmware Framework for Arm A-profile + + FIP + Firmware Image Package + + FVP + Fixed Virtual Platform + + FWU + FirmWare Update + + GIC + Generic Interrupt Controller + + ISA + Instruction Set Architecture + + Linaro + A collaborative engineering organization consolidating + and optimizing open source software and tools for the Arm architecture. + + MMU + Memory Management Unit + + MPAM + Memory Partitioning And Monitoring. An optional Armv8.4 extension. + + MPMM + Maximum Power Mitigation Mechanism, an optional power management mechanism + supported by some Arm Armv9-A cores. + + MPIDR + Multiprocessor Affinity Register + + MTE + Memory Tagging Extension. An optional Armv8.5 extension that enables + hardware-assisted memory tagging. + + OEN + Owning Entity Number + + OP-TEE + Open Portable Trusted Execution Environment. An example of a :term:`TEE` + + OTE + Open-source Trusted Execution Environment + + PDD + Platform Design Document + + PAUTH + Pointer Authentication. An optional extension introduced in Armv8.3. + + PMF + Performance Measurement Framework + + PSA + Platform Security Architecture + + PSCI + Power State Coordination Interface + + RAS + Reliability, Availability, and Serviceability extensions. A mandatory + extension for the Armv8.2 architecture and later. An optional extension to + the base Armv8 architecture. + + ROT + Root of Trust + + SCMI + System Control and Management Interface + + SCP + System Control Processor + + SDEI + Software Delegated Exception Interface + + SDS + Shared Data Storage + + SEA + Synchronous External Abort + + SiP + SIP + Silicon Provider + + SMC + Secure Monitor Call + + SMCCC + :term:`SMC` Calling Convention + + SoC + System on Chip + + SP + Secure Partition + + SPD + Secure Payload Dispatcher + + SPM + Secure Partition Manager + + SSBS + Speculative Store Bypass Safe. Introduced in Armv8.5, this configuration + bit can be set by software to allow or prevent the hardware from + performing speculative operations. + + SVE + Scalable Vector Extension + + TBB + Trusted Board Boot + + TBBR + Trusted Board Boot Requirements + + TEE + Trusted Execution Environment + + TF-A + Trusted Firmware-A + + TF-M + Trusted Firmware-M + + TLB + Translation Lookaside Buffer + + TLK + Trusted Little Kernel. A Trusted OS from NVIDIA. + + TRNG + True Randon Number Generator (hardware based) + + TSP + Test Secure Payload + + TZC + TrustZone Controller + + UBSAN + Undefined Behavior Sanitizer + + UEFI + Unified Extensible Firmware Interface + + WDOG + Watchdog + + XLAT + Translation (abbr.). For example, "XLAT table". + +.. _`Arm Glossary`: https://developer.arm.com/support/arm-glossary diff --git a/arm-trusted-firmware/docs/index.rst b/arm-trusted-firmware/docs/index.rst new file mode 100644 index 0000000..edc2535 --- /dev/null +++ b/arm-trusted-firmware/docs/index.rst @@ -0,0 +1,96 @@ +Trusted Firmware-A Documentation +================================ + +.. toctree:: + :maxdepth: 1 + :hidden: + + Home + about/index + getting_started/index + process/index + components/index + design/index + plat/index + perf/index + security_advisories/index + design_documents/index + threat_model/index + change-log + glossary + license + +Trusted Firmware-A (TF-A) provides a reference implementation of secure world +software for `Armv7-A and Armv8-A`_, including a `Secure Monitor`_ executing +at Exception Level 3 (EL3). It implements various Arm interface standards, +such as: + +- The `Power State Coordination Interface (PSCI)`_ +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_ +- `SMC Calling Convention`_ +- `System Control and Management Interface (SCMI)`_ +- `Software Delegated Exception Interface (SDEI)`_ +- `PSA FW update specification`_ + +Where possible, the code is designed for reuse or porting to other Armv7-A and +Armv8-A model and hardware platforms. + +This release provides a suitable starting point for productization of secure +world boot and runtime firmware, in either the AArch32 or AArch64 execution +states. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from TF-A. + +In collaboration with interested parties, we will continue to enhance |TF-A| +with reference implementations of Arm standards to benefit developers working +with Armv7-A and Armv8-A TrustZone technology. + +Getting Started +--------------- + +The |TF-A| documentation contains guidance for obtaining and building the +software for existing, supported platforms, as well as supporting information +for porting the software to a new platform. + +The **About** chapter gives a high-level overview of |TF-A| features as well as +some information on the project and how it is organized. + +Refer to the documents in the **Getting Started** chapter for information about +the prerequisites and requirements for building |TF-A|. + +The **Processes & Policies** chapter explains the project's release schedule +and process, how security disclosures are handled, and the guidelines for +contributing to the project (including the coding style). + +The **Components** chapter holds documents that explain specific components +that make up the |TF-A| software, the :ref:`Exception Handling Framework`, for +example. + +In the **System Design** chapter you will find documents that explain the +design of portions of the software that involve more than one component, such +as the :ref:`Trusted Board Boot` process. + +**Platform Ports** provides a list of the supported hardware and software-model +platforms that are supported upstream in |TF-A|. Most of these platforms also +have additional documentation that has been provided by the maintainers of the +platform. + +The results of any performance evaluations are added to the +**Performance & Testing** chapter. + +**Security Advisories** holds a list of documents relating to |CVE| entries that +have previously been raised against the software. + +-------------- + +*Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved.* + +.. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _Power State Coordination Interface (PSCI): http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _System Control and Management Interface (SCMI): http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf +.. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _PSA FW update specification: https://developer.arm.com/documentation/den0118/a/ diff --git a/arm-trusted-firmware/docs/license.rst b/arm-trusted-firmware/docs/license.rst new file mode 100644 index 0000000..80f1118 --- /dev/null +++ b/arm-trusted-firmware/docs/license.rst @@ -0,0 +1,90 @@ +License +======= + +The software is provided under a BSD-3-Clause license (below). Contributions to +this project are accepted under the same license with developer sign-off as +described in the :ref:`Contributor's Guide`. + +:: + + Copyright (c) [XXXX-]YYYY, . All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + - Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + - Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + - Neither the name of Arm nor the names of its contributors may be used to + endorse or promote products derived from this software without specific + prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND + ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR + ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON + ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +SPDX Identifiers +---------------- + +Individual files contain the following tag instead of the full license text. + +:: + + SPDX-License-Identifier: BSD-3-Clause + +This enables machine processing of license information based on the SPDX +License Identifiers that are here available: http://spdx.org/licenses/ + + +Other Projects +-------------- + +This project contains code from other projects as listed below. The original +license text is included in those source files. + +- The libc source code is derived from `FreeBSD`_ and `SCC`_. FreeBSD uses + various BSD licenses, including BSD-3-Clause and BSD-2-Clause. The SCC code + is used under the BSD-3-Clause license with the author's permission. + +- The libfdt source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-2-Clause). It is used by this project under the terms of + the BSD-2-Clause license. Any contributions to this code must be made under + the terms of both licenses. + +- The LLVM compiler-rt source code is disjunctively dual licensed + (NCSA OR MIT). It is used by this project under the terms of the NCSA + license (also known as the University of Illinois/NCSA Open Source License), + which is a permissive license compatible with BSD-3-Clause. Any + contributions to this code must be made under the terms of both licenses. + +- The zlib source code is licensed under the Zlib license, which is a + permissive license compatible with BSD-3-Clause. + +- Some STMicroelectronics platform source code is disjunctively dual licensed + (GPL-2.0+ OR BSD-3-Clause). It is used by this project under the terms of the + BSD-3-Clause license. Any contributions to this code must be made under the + terms of both licenses. + +- Some source files originating from the Linux source tree, which are + disjunctively dual licensed (GPL-2.0 OR MIT), are redistributed under the + terms of the MIT license. These files are: + + - ``include/dt-bindings/interrupt-controller/arm-gic.h`` + - ``include/dt-bindings/interrupt-controller/irq.h`` + + See the original `Linux MIT license`_. + +.. _FreeBSD: http://www.freebsd.org +.. _Linux MIT license: https://raw.githubusercontent.com/torvalds/linux/master/LICENSES/preferred/MIT +.. _SCC: http://www.simple-cc.org/ diff --git a/arm-trusted-firmware/docs/perf/index.rst b/arm-trusted-firmware/docs/perf/index.rst new file mode 100644 index 0000000..1482b80 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/index.rst @@ -0,0 +1,15 @@ +Performance & Testing +===================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + psci-performance-juno + tsp + performance-monitoring-unit + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst b/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst new file mode 100644 index 0000000..5dd1af5 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst @@ -0,0 +1,158 @@ +Performance Monitoring Unit +=========================== + +The Performance Monitoring Unit (PMU) allows recording of architectural and +microarchitectural events for profiling purposes. + +This document gives an overview of the PMU counter configuration to assist with +implementation and to complement the PMU security guidelines given in the +:ref:`Secure Development Guidelines` document. + +.. note:: + This section applies to Armv8-A implementations which have version 3 + of the Performance Monitors Extension (PMUv3). + +PMU Counters +------------ + +The PMU makes 32 counters available at all privilege levels: + +- 31 programmable event counters: ``PMEVCNTR``, where ``n`` is ``0`` to + ``30``. +- A dedicated cycle counter: ``PMCCNTR``. + +Architectural mappings +~~~~~~~~~~~~~~~~~~~~~~ + ++--------------+---------+----------------------------+ +| Counters | State | System Register Name | ++==============+=========+============================+ +| | AArch64 | ``PMEVCNTR_EL0[63*:0]`` | +| Programmable +---------+----------------------------+ +| | AArch32 | ``PMEVCNTR[31:0]`` | ++--------------+---------+----------------------------+ +| | AArch64 | ``PMCCNTR_EL0[63:0]`` | +| Cycle +---------+----------------------------+ +| | AArch32 | ``PMCCNTR[63:0]`` | ++--------------+---------+----------------------------+ + +.. note:: + Bits [63:32] are only available if ARMv8.5-PMU is implemented. Refer to the + `Arm ARM`_ for a detailed description of ARMv8.5-PMU features. + +Configuring the PMU for counting events +--------------------------------------- + +Each programmable counter has an associated register, ``PMEVTYPER`` which +configures it. The cycle counter has the ``PMCCFILTR_EL0`` register, which has +an identical function and bit field layout as ``PMEVTYPER``. In addition, +the counters are enabled (permitted to increment) via the ``PMCNTENSET`` and +``PMCR`` registers. These can be accessed at all privilege levels. + +Architectural mappings +~~~~~~~~~~~~~~~~~~~~~~ + ++-----------------------------+------------------------+ +| AArch64 | AArch32 | ++=============================+========================+ +| ``PMEVTYPER_EL0[63*:0]`` | ``PMEVTYPER[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCCFILTR_EL0[63*:0]`` | ``PMCCFILTR[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCNTENSET_EL0[63*:0]`` | ``PMCNTENSET[31:0]`` | ++-----------------------------+------------------------+ +| ``PMCR_EL0[63*:0]`` | ``PMCR[31:0]`` | ++-----------------------------+------------------------+ + +.. note:: + Bits [63:32] are reserved. + +Relevant register fields +~~~~~~~~~~~~~~~~~~~~~~~~ + +For ``PMEVTYPER_EL0``/``PMEVTYPER`` and ``PMCCFILTR_EL0/PMCCFILTR``, the +most important fields are: + +- ``P``: + + - Bit 31. + - If set to ``0``, will increment the associated ``PMEVCNTR`` at EL1. + +- ``NSK``: + + - Bit 29. + - If equal to the ``P`` bit it enables the associated ``PMEVCNTR`` at + Non-secure EL1. + - Reserved if EL3 not implemented. + +- ``NSH``: + + - Bit 27. + - If set to ``1``, will increment the associated ``PMEVCNTR`` at EL2. + - Reserved if EL2 not implemented. + +- ``SH``: + + - Bit 24. + - If different to the ``NSH`` bit it enables the associated ``PMEVCNTR`` + at Secure EL2. + - Reserved if Secure EL2 not implemented. + +- ``M``: + + - Bit 26. + - If equal to the ``P`` bit it enables the associated ``PMEVCNTR`` at + EL3. + +- ``evtCount[15:10]``: + + - Extension to ``evtCount[9:0]``. Reserved unless ARMv8.1-PMU implemented. + +- ``evtCount[9:0]``: + + - The event number that the associated ``PMEVCNTR`` will count. + +For ``PMCNTENSET_EL0``/``PMCNTENSET``, the most important fields are: + +- ``P[30:0]``: + + - Setting bit ``P[n]`` to ``1`` enables counter ``PMEVCNTR``. + - The effects of ``PMEVTYPER`` are applied on top of this. + In other words, the counter will not increment at any privilege level or + security state unless it is enabled here. + +- ``C``: + + - Bit 31. + - If set to ``1`` enables the cycle counter ``PMCCNTR``. + +For ``PMCR``/``PMCR_EL0``, the most important fields are: + +- ``DP``: + + - Bit 5. + - If set to ``1`` it disables the cycle counter ``PMCCNTR`` where event + counting (by ``PMEVCNTR``) is prohibited (e.g. EL2 and the Secure + world). + - If set to ``0``, ``PMCCNTR`` will not be affected by this bit and + therefore will be able to count where the programmable counters are + prohibited. + +- ``E``: + + - Bit 0. + - Enables/disables counting altogether. + - The effects of ``PMCNTENSET`` and ``PMCR.DP`` are applied on top of this. + In other words, if this bit is ``0`` then no counters will increment + regardless of how the other PMU system registers or bit fields are + configured. + +.. rubric:: References + +- `Arm ARM`_ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest diff --git a/arm-trusted-firmware/docs/perf/psci-performance-juno.rst b/arm-trusted-firmware/docs/perf/psci-performance-juno.rst new file mode 100644 index 0000000..eab3e4d --- /dev/null +++ b/arm-trusted-firmware/docs/perf/psci-performance-juno.rst @@ -0,0 +1,292 @@ +PSCI Performance Measurements on Arm Juno Development Platform +============================================================== + +This document summarises the findings of performance measurements of key +operations in the Trusted Firmware-A Power State Coordination Interface (PSCI) +implementation, using the in-built Performance Measurement Framework (PMF) and +runtime instrumentation timestamps. + +Method +------ + +We used the `Juno R1 platform`_ for these tests, which has 4 x Cortex-A53 and 2 +x Cortex-A57 clusters running at the following frequencies: + ++-----------------+--------------------+ +| Domain | Frequency (MHz) | ++=================+====================+ +| Cortex-A57 | 900 (nominal) | ++-----------------+--------------------+ +| Cortex-A53 | 650 (underdrive) | ++-----------------+--------------------+ +| AXI subsystem | 533 | ++-----------------+--------------------+ + +Juno supports CPU, cluster and system power down states, corresponding to power +levels 0, 1 and 2 respectively. It does not support any retention states. + +We used the upstream `TF master as of 31/01/2017`_, building the platform using +the ``ENABLE_RUNTIME_INSTRUMENTATION`` option: + +.. code:: shell + + make PLAT=juno ENABLE_RUNTIME_INSTRUMENTATION=1 \ + SCP_BL2= \ + BL33= \ + all fip + +When using the debug build of TF, there was no noticeable difference in the +results. + +The tests are based on an ARM-internal test framework. The release build of this +framework was used because the results in the debug build became skewed; the +console output prevented some of the tests from executing in parallel. + +The tests consist of both parallel and sequential tests, which are broadly +described as follows: + +- **Parallel Tests** This type of test powers on all the non-lead CPUs and + brings them and the lead CPU to a common synchronization point. The lead CPU + then initiates the test on all CPUs in parallel. + +- **Sequential Tests** This type of test powers on each non-lead CPU in + sequence. The lead CPU initiates the test on a non-lead CPU then waits for the + test to complete before proceeding to the next non-lead CPU. The lead CPU then + executes the test on itself. + +In the results below, CPUs 0-3 refer to CPUs in the little cluster (A53) and +CPUs 4-5 refer to CPUs in the big cluster (A57). In all cases CPU 4 is the lead +CPU. + +``PSCI_ENTRY`` refers to the time taken from entering the TF PSCI implementation +to the point the hardware enters the low power state (WFI). Referring to the TF +runtime instrumentation points, this corresponds to: +``(RT_INSTR_ENTER_HW_LOW_PWR - RT_INSTR_ENTER_PSCI)``. + +``PSCI_EXIT`` refers to the time taken from the point the hardware exits the low +power state to exiting the TF PSCI implementation. This corresponds to: +``(RT_INSTR_EXIT_PSCI - RT_INSTR_EXIT_HW_LOW_PWR)``. + +``CFLUSH_OVERHEAD`` refers to the part of ``PSCI_ENTRY`` taken to flush the +caches. This corresponds to: ``(RT_INSTR_EXIT_CFLUSH - RT_INSTR_ENTER_CFLUSH)``. + +Note there is very little variance observed in the values given (~1us), although +the values for each CPU are sometimes interchanged, depending on the order in +which locks are acquired. Also, there is very little variance observed between +executing the tests sequentially in a single boot or rebooting between tests. + +Given that runtime instrumentation using PMF is invasive, there is a small +(unquantified) overhead on the results. PMF uses the generic counter for +timestamps, which runs at 50MHz on Juno. + +Results and Commentary +---------------------- + +``CPU_SUSPEND`` to deepest power level on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 27 | 20 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 86 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 202 | 58 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 375 | 29 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 20 | 22 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 290 | 18 | 206 | ++-------+---------------------+--------------------+--------------------------+ + +A large variance in ``PSCI_ENTRY`` and ``PSCI_EXIT`` times across CPUs is +observed due to TF PSCI lock contention. In the worst case, CPU 3 has to wait +for the 3 other CPUs in the cluster (0-2) to complete ``PSCI_ENTRY`` and release +the lock before proceeding. + +The ``CFLUSH_OVERHEAD`` times for CPUs 3 and 5 are higher because they are the +last CPUs in their respective clusters to power down, therefore both the L1 and +L2 caches are flushed. + +The ``CFLUSH_OVERHEAD`` time for CPU 5 is a lot larger than that for CPU 3 +because the L2 cache size for the big cluster is lot larger (2MB) compared to +the little cluster (1MB). + +``CPU_SUSPEND`` to power level 0 on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 116 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 204 | 14 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 287 | 13 | 8 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 376 | 13 | 9 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 29 | 15 | 7 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 15 | 8 | ++-------+---------------------+--------------------+--------------------------+ + +There is no lock contention in TF generic code at power level 0 but the large +variance in ``PSCI_ENTRY`` times across CPUs is due to lock contention in Juno +platform code. The platform lock is used to mediate access to a single SCP +communication channel. This is compounded by the SCP firmware waiting for each +AP CPU to enter WFI before making the channel available to other CPUs, which +effectively serializes the SCP power down commands from all CPUs. + +On platforms with a more efficient CPU power down mechanism, it should be +possible to make the ``PSCI_ENTRY`` times smaller and consistent. + +The ``PSCI_EXIT`` times are consistent across all CPUs because TF does not +require locks at power level 0. + +The ``CFLUSH_OVERHEAD`` times for all CPUs are small and consistent since only +the cache associated with power level 0 is flushed (L1). + +``CPU_SUSPEND`` to deepest power level on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 114 | 20 | 94 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 180 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 21 | 17 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CFLUSH_OVERHEAD`` times for lead CPU 4 and all CPUs in the non-lead cluster +are large because all other CPUs in the cluster are powered down during the +test. The ``CPU_SUSPEND`` call powers down to the cluster level, requiring a +flush of both L1 and L2 caches. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are low because lead +CPU 4 continues to run while CPU 5 is suspended. Hence CPU 5 only powers down to +level 0, which only requires L1 cache flush. + +``CPU_SUSPEND`` to power level 0 on all CPUs in sequence +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 21 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 22 | 14 | 5 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 17 | 14 | 6 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 18 | 15 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +Here the times are small and consistent since there is no contention and it is +only necessary to flush the cache to power level 0 (L1). This is the best case +scenario. + +The ``PSCI_ENTRY`` times for CPUs in the big cluster are slightly smaller than +for the CPUs in little cluster due to greater CPU performance. + +The ``PSCI_EXIT`` times are generally lower than in the last test because the +cluster remains powered on throughout the test and there is less code to execute +on power on (for example, no need to enter CCI coherency) + +``CPU_OFF`` on all non-lead CPUs in sequence then ``CPU_SUSPEND`` on lead CPU to deepest power level +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The test sequence here is as follows: + +1. Call ``CPU_ON`` and ``CPU_OFF`` on each non-lead CPU in sequence. + +2. Program wake up timer and suspend the lead CPU to the deepest power level. + +3. Call ``CPU_ON`` on non-lead CPU to get the timestamps from each CPU. + ++-------+---------------------+--------------------+--------------------------+ +| CPU | ``PSCI_ENTRY`` (us) | ``PSCI_EXIT`` (us) | ``CFLUSH_OVERHEAD`` (us) | ++=======+=====================+====================+==========================+ +| 0 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 1 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 2 | 110 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 3 | 111 | 28 | 93 | ++-------+---------------------+--------------------+--------------------------+ +| 4 | 195 | 22 | 181 | ++-------+---------------------+--------------------+--------------------------+ +| 5 | 20 | 23 | 6 | ++-------+---------------------+--------------------+--------------------------+ + +The ``CFLUSH_OVERHEAD`` times for all little CPUs are large because all other +CPUs in that cluster are powerered down during the test. The ``CPU_OFF`` call +powers down to the cluster level, requiring a flush of both L1 and L2 caches. + +The ``PSCI_ENTRY`` and ``CFLUSH_OVERHEAD`` times for CPU 5 are small because +lead CPU 4 is running and CPU 5 only powers down to level 0, which only requires +an L1 cache flush. + +The ``CFLUSH_OVERHEAD`` time for CPU 4 is a lot larger than those for the little +CPUs because the L2 cache size for the big cluster is lot larger (2MB) compared +to the little cluster (1MB). + +The ``PSCI_EXIT`` times for CPUs in the big cluster are slightly smaller than +for CPUs in the little cluster due to greater CPU performance. These times +generally are greater than the ``PSCI_EXIT`` times in the ``CPU_SUSPEND`` tests +because there is more code to execute in the "on finisher" compared to the +"suspend finisher" (for example, GIC redistributor register programming). + +``PSCI_VERSION`` on all CPUs in parallel +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since very little code is associated with ``PSCI_VERSION``, this test +approximates the round trip latency for handling a fast SMC at EL3 in TF. + ++-------+-------------------+ +| CPU | TOTAL TIME (ns) | ++=======+===================+ +| 0 | 3020 | ++-------+-------------------+ +| 1 | 2940 | ++-------+-------------------+ +| 2 | 2980 | ++-------+-------------------+ +| 3 | 3060 | ++-------+-------------------+ +| 4 | 520 | ++-------+-------------------+ +| 5 | 720 | ++-------+-------------------+ + +The times for the big CPUs are less than the little CPUs due to greater CPU +performance. + +We suspect the time for lead CPU 4 is shorter than CPU 5 due to subtle cache +effects, given that these measurements are at the nano-second level. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved.* + +.. _Juno R1 platform: https://static.docs.arm.com/100122/0100/arm_versatile_express_juno_r1_development_platform_(v2m_juno_r1)_technical_reference_manual_100122_0100_05_en.pdf +.. _TF master as of 31/01/2017: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/?id=c38b36d diff --git a/arm-trusted-firmware/docs/perf/tsp.rst b/arm-trusted-firmware/docs/perf/tsp.rst new file mode 100644 index 0000000..f8b0048 --- /dev/null +++ b/arm-trusted-firmware/docs/perf/tsp.rst @@ -0,0 +1,27 @@ +Test Secure Payload (TSP) and Dispatcher (TSPD) +=============================================== + +Building the Test Secure Payload +-------------------------------- + +The TSP is coupled with a companion runtime service in the BL31 firmware, +called the TSPD. Therefore, if you intend to use the TSP, the BL31 image +must be recompiled as well. For more information on SPs and SPDs, see the +:ref:`firmware_design_sel1_spd` section in the :ref:`Firmware Design`. + +First clean the TF-A build directory to get rid of any previous BL31 binary. +Then to build the TSP image use: + +.. code:: shell + + make PLAT= SPD=tspd all + +An additional boot loader binary file is created in the ``build`` directory: + +:: + + build///bl32.bin + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/allwinner.rst b/arm-trusted-firmware/docs/plat/allwinner.rst new file mode 100644 index 0000000..3e9ce51 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/allwinner.rst @@ -0,0 +1,142 @@ +Allwinner ARMv8 SoCs +==================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Allwinner +SoCs with ARMv8 cores. Only BL31 is used to provide proper EL3 setup and +PSCI runtime services. + +Building TF-A +------------- + +There is one build target per supported SoC: + ++------+-------------------+ +| SoC | TF-A build target | ++======+===================+ +| A64 | sun50i_a64 | ++------+-------------------+ +| H5 | sun50i_a64 | ++------+-------------------+ +| H6 | sun50i_h6 | ++------+-------------------+ +| H616 | sun50i_h616 | ++------+-------------------+ +| H313 | sun50i_h616 | ++------+-------------------+ +| R329 | sun50i_r329 | ++------+-------------------+ + +To build with the default settings for a particular SoC: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT= DEBUG=1 + +So for instance to build for a board with the Allwinner A64 SoC:: + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sun50i_a64 DEBUG=1 + +Platform-specific build options +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The default build options should generate a working firmware image. There are +some build options that allow to fine-tune the firmware, or to disable support +for optional features. + +- ``SUNXI_PSCI_USE_NATIVE`` : Support direct control of the CPU cores powerdown + and powerup sequence by BL31. This requires either support for a code snippet + to be loaded into the ARISC SCP (A64, H5), or the power sequence control + registers to be programmed directly (H6, H616). This supports only basic + control, like core on/off and system off/reset. + This option defaults to 1. If an active SCP supporting the SCPI protocol + is detected at runtime, this control scheme will be ignored, and SCPI + will be used instead, unless support has been explicitly disabled. + +- ``SUNXI_PSCI_USE_SCPI`` : Support control of the CPU cores powerdown and + powerup sequence by talking to the SCP processor via the SCPI protocol. + This allows more advanced power saving techniques, like suspend to RAM. + This option defaults to 1 on SoCs that feature an SCP. If no SCP firmware + using the SCPI protocol is detected, the native sequence will be used + instead. If both native and SCPI methods are included, SCPI will be favoured + if SCP support is detected. + +- ``SUNXI_SETUP_REGULATORS`` : On SoCs that typically ship with a PMIC + power management controller, BL31 tries to set up all needed power rails, + programming them to their respective voltages. That allows bootloader + software like U-Boot to ignore power control via the PMIC. + This setting defaults to 1. In some situations that enables too many + regulators, or some regulators need to be enabled in a very specific + sequence. To avoid problems with those boards, ``SUNXI_SETUP_REGULATORS`` + can bet set to ``0`` on the build command line, to skip the PMIC setup + entirely. Any bootloader or OS would need to setup the PMIC on its own then. + +Installation +------------ + +U-Boot's SPL acts as a loader, loading both BL31 and BL33 (typically U-Boot). +Loading is done from SD card, eMMC or SPI flash, also via an USB debug +interface (FEL). + +After building bl31.bin, the binary must be fed to the U-Boot build system +to include it in the FIT image that the SPL loader will process. +bl31.bin can be either copied (or sym-linked) into U-Boot's root directory, +or the environment variable BL31 must contain the binary's path. +See the respective `U-Boot documentation`_ for more details. + +.. _U-Boot documentation: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/sunxi/README.sunxi64 + +Memory layout +------------- + +A64, H5 and H6 SoCs +~~~~~~~~~~~~~~~~~~~ + +BL31 lives in SRAM A2, which is documented to be accessible from secure +world only. Since this SRAM region is very limited (48 KB), we take +several measures to reduce memory consumption. One of them is to confine +BL31 to only 28 bits of virtual address space, which reduces the number +of required page tables (each occupying 4KB of memory). +The mapping we use on those SoCs is as follows: + +:: + + 0 64K 16M 1GB 1G+160M physical address + +-+------+-+---+------+--...---+-------+----+------+---------- + |B| |S|///| |//...///| |////| | + |R| SRAM |C|///| dev |//...///| (sec) |////| BL33 | DRAM ... + |O| |P|///| MMIO |//...///| DRAM |////| | + |M| | |///| |//...///| (32M) |////| | + +-+------+-+---+------+--...---+-------+----+------+---------- + | | | | | | / / / / + | | | | | | / / / / + | | | | | | / / / / + | | | | | | / // / + | | | | | | / / / + +-+------+-+---+------+--+-------+------+ + |B| |S|///| |//| | | + |R| SRAM |C|///| dev |//| sec | BL33 | + |O| |P|///| MMIO |//| DRAM | | + |M| | |///| |//| | | + +-+------+-+---+------+--+-------+------+ + 0 64K 16M 160M 192M 256M virtual address + + +H616 SoC +~~~~~~~~ + +The H616 lacks the secure SRAM region present on the other SoCs, also +lacks the "ARISC" management processor (SCP) we use. BL31 thus needs to +run from DRAM, which prevents our compressed virtual memory map described +above. Since running in DRAM also lifts the restriction of the limited +SRAM size, we use the normal 1:1 mapping with 32 bits worth of virtual +address space. So the virtual addresses used in BL31 match the physical +addresses as presented above. + +Trusted OS dispatcher +--------------------- + +One can boot Trusted OS(OP-TEE OS, bl32 image) along side bl31 image on Allwinner A64. + +In order to include the 'opteed' dispatcher in the image, pass 'SPD=opteed' on the command line +while compiling the bl31 image and make sure the loader (SPL) loads the Trusted OS binary to +the beginning of DRAM (0x40000000). diff --git a/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst b/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst new file mode 100644 index 0000000..339ebbe --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/arm-build-options.rst @@ -0,0 +1,159 @@ +Arm Development Platform Build Options +====================================== + +Arm Platform Build Options +-------------------------- + +- ``ARM_BL31_IN_DRAM``: Boolean option to select loading of BL31 in TZC secured + DRAM. By default, BL31 is in the secure SRAM. Set this flag to 1 to load + BL31 in TZC secured DRAM. If TSP is present, then setting this option also + sets the TSP location to DRAM and ignores the ``ARM_TSP_RAM_LOCATION`` build + flag. + +- ``ARM_CONFIG_CNTACR``: boolean option to unlock access to the ``CNTBase`` + frame registers by setting the ``CNTCTLBase.CNTACR`` register bits. The + frame number ```` is defined by ``PLAT_ARM_NSTIMER_FRAME_ID``, which + should match the frame used by the Non-Secure image (normally the Linux + kernel). Default is true (access to the frame is allowed). + +- ``ARM_DISABLE_TRUSTED_WDOG``: boolean option to disable the Trusted Watchdog. + By default, Arm platforms use a watchdog to trigger a system reset in case + an error is encountered during the boot process (for example, when an image + could not be loaded or authenticated). The watchdog is enabled in the early + platform setup hook at BL1 and disabled in the BL1 prepare exit hook. The + Trusted Watchdog may be disabled at build time for testing or development + purposes. + +- ``ARM_LINUX_KERNEL_AS_BL33``: The Linux kernel expects registers x0-x3 to + have specific values at boot. This boolean option allows the Trusted Firmware + to have a Linux kernel image as BL33 by preparing the registers to these + values before jumping to BL33. This option defaults to 0 (disabled). For + AArch64 ``RESET_TO_BL31`` and for AArch32 ``RESET_TO_SP_MIN`` must be 1 when + using it. If this option is set to 1, ``ARM_PRELOADED_DTB_BASE`` must be set + to the location of a device tree blob (DTB) already loaded in memory. The + Linux Image address must be specified using the ``PRELOADED_BL33_BASE`` + option. + +- ``ARM_PLAT_MT``: This flag determines whether the Arm platform layer has to + cater for the multi-threading ``MT`` bit when accessing MPIDR. When this flag + is set, the functions which deal with MPIDR assume that the ``MT`` bit in + MPIDR is set and access the bit-fields in MPIDR accordingly. Default value of + this flag is 0. Note that this option is not used on FVP platforms. + +- ``ARM_RECOM_STATE_ID_ENC``: The PSCI1.0 specification recommends an encoding + for the construction of composite state-ID in the power-state parameter. + The existing PSCI clients currently do not support this encoding of + State-ID yet. Hence this flag is used to configure whether to use the + recommended State-ID encoding or not. The default value of this flag is 0, + in which case the platform is configured to expect NULL in the State-ID + field of power-state parameter. + +- ``ARM_ROTPK_LOCATION``: used when ``TRUSTED_BOARD_BOOT=1``. It specifies the + location of the ROTPK hash returned by the function ``plat_get_rotpk_info()`` + for Arm platforms. Depending on the selected option, the proper private key + must be specified using the ``ROT_KEY`` option when building the Trusted + Firmware. This private key will be used by the certificate generation tool + to sign the BL2 and Trusted Key certificates. Available options for + ``ARM_ROTPK_LOCATION`` are: + + - ``regs`` : return the ROTPK hash stored in the Trusted root-key storage + registers. + - ``devel_rsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the RSA public key + ``arm_rotpk_rsa.der``, located in ``plat/arm/board/common/rotpk``. To use + this option, ``arm_rotprivk_rsa.pem`` must be specified as ``ROT_KEY`` + when creating the certificates. + - ``devel_ecdsa`` : return a development public key hash embedded in the BL1 + and BL2 binaries. This hash has been obtained from the ECDSA public key + ``arm_rotpk_ecdsa.der``, located in ``plat/arm/board/common/rotpk``. To + use this option, ``arm_rotprivk_ecdsa.pem`` must be specified as + ``ROT_KEY`` when creating the certificates. + +- ``ARM_ROTPK_HASH``: used when ``ARM_ROTPK_LOCATION=devel_*``. Specifies the + location of the ROTPK hash. Not expected to be a build option. This defaults to + ``plat/arm/board/common/rotpk/*_sha256.bin`` depending on the specified algorithm. + Providing ``ROT_KEY`` enforces generation of the hash from the ``ROT_KEY`` and + overwrites the default hash file. + +- ``ARM_TSP_RAM_LOCATION``: location of the TSP binary. Options: + + - ``tsram`` : Trusted SRAM (default option when TBB is not enabled) + - ``tdram`` : Trusted DRAM (if available) + - ``dram`` : Secure region in DRAM (default option when TBB is enabled, + configured by the TrustZone controller) + +- ``ARM_XLAT_TABLES_LIB_V1``: boolean option to compile TF-A with version 1 + of the translation tables library instead of version 2. It is set to 0 by + default, which selects version 2. + +- ``ARM_CRYPTOCELL_INTEG`` : bool option to enable TF-A to invoke Arm® + TrustZone® CryptoCell functionality for Trusted Board Boot on capable Arm + platforms. If this option is specified, then the path to the CryptoCell + SBROM library must be specified via ``CCSBROM_LIB_PATH`` flag. + +- ``ARM_ETHOSN_NPU_DRIVER``: boolean option to enable a SiP service that can + configure an Arm Ethos-N NPU. To use this service the target platform's + ``HW_CONFIG`` must include the device tree nodes for the NPU. Currently, only + the Arm Juno platform has this included in its ``HW_CONFIG`` and the platform + only loads the ``HW_CONFIG`` in AArch64 builds. Default is 0. + +- ``ARM_SPMC_MANIFEST_DTS`` : path to an alternate manifest file used as the + SPMC Core manifest. Valid when ``SPD=spmd`` is selected. + +- ``ARM_BL2_SP_LIST_DTS``: Path to DTS file snippet to override the hardcoded + SP nodes in tb_fw_config. + +- ``OPTEE_SP_FW_CONFIG``: DTC build flag to include OP-TEE as SP in tb_fw_config + device tree. This flag is defined only when ``ARM_SPMC_MANIFEST_DTS`` manifest + file name contains pattern optee_sp. + +- ``TS_SP_FW_CONFIG``: DTC build flag to include Trusted Services (Crypto and + internal-trusted-storage) as SP in tb_fw_config device tree. + +- ``ARM_GPT_SUPPORT``: Enable GPT parser to get the entry address and length of + the various partitions present in the GPT image. This support is available + only for the BL2 component, and it is disabled by default. + The following diagram shows the view of the FIP partition inside the GPT + image: + + |FIP in a GPT image| + +For a better understanding of these options, the Arm development platform memory +map is explained in the :ref:`Firmware Design`. + +.. _build_options_arm_css_platform: + +Arm CSS Platform-Specific Build Options +--------------------------------------- + +- ``CSS_DETECT_PRE_1_7_0_SCP``: Boolean flag to detect SCP version + incompatibility. Version 1.7.0 of the SCP firmware made a non-backwards + compatible change to the MTL protocol, used for AP/SCP communication. + TF-A no longer supports earlier SCP versions. If this option is set to 1 + then TF-A will detect if an earlier version is in use. Default is 1. + +- ``CSS_LOAD_SCP_IMAGES``: Boolean flag, which when set, adds SCP_BL2 and + SCP_BL2U to the FIP and FWU_FIP respectively, and enables them to be loaded + during boot. Default is 1. + +- ``CSS_USE_SCMI_SDS_DRIVER``: Boolean flag which selects SCMI/SDS drivers + instead of SCPI/BOM driver for communicating with the SCP during power + management operations and for SCP RAM Firmware transfer. If this option + is set to 1, then SCMI/SDS drivers will be used. Default is 0. + + - ``CSS_SGI_CHIP_COUNT``: Configures the number of chips on a SGI/RD platform + which supports multi-chip operation. If ``CSS_SGI_CHIP_COUNT`` is set to any + valid value greater than 1, the platform code performs required configuration + to support multi-chip operation. + +- ``CSS_SGI_PLATFORM_VARIANT``: Selects the variant of a SGI/RD platform. A + particular SGI/RD platform may have multiple variants which may differ in + core count, cluster count or other peripherals. This build option is used + to select the appropriate platform variant for the build. The range of + valid values is platform specific. + +-------------- + +.. |FIP in a GPT image| image:: ../../resources/diagrams/FIP_in_a_GPT_image.png + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst b/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst new file mode 100644 index 0000000..5427c1d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst @@ -0,0 +1,97 @@ +Arm FPGA Platform +================= + +This platform supports FPGA images used internally in Arm Ltd., for +testing and bringup of new cores. With that focus, peripheral support is +minimal: there is no mass storage or display output, for instance. Also +this port ignores any power management features of the platform. +Some interconnect setup is done internally by the platform, so the TF-A code +just needs to setup UART and GIC. + +The FPGA platform requires to pass on a DTB for the non-secure payload +(mostly Linux), so we let TF-A use information from the DTB for dynamic +configuration: the UART and GIC base addresses are read from there. + +As a result this port is a fairly generic BL31-only port, which can serve +as a template for a minimal new (and possibly DT-based) platform port. + +The aim of this port is to support as many FPGA images as possible with +a single build. Image specific data must be described in the DTB or should +be auto-detected at runtime. + +As the number and topology layout of the CPU cores differs significantly +across the various images, this is detected at runtime by BL31. +The /cpus node in the DT will be added and filled accordingly, as long as +it does not exist already. + +Platform-specific build options +------------------------------- + +- ``SUPPORT_UNKNOWN_MPID`` : Boolean option to allow unknown MPIDR registers. + Normally TF-A panics if it encounters a MPID value not matched to its + internal list, but for new or experimental cores this creates a lot of + churn. With this option, the code will fall back to some basic CPU support + code (only architectural system registers, and no errata). + Default value of this flag is 1. + +- ``PRELOADED_BL33_BASE`` : Physical address of the BL33 non-secure payload. + It must have been loaded into DRAM already, typically this is done by + the script that also loads BL31 and the DTB. + It defaults to 0x80080000, which is the traditional load address for an + arm64 Linux kernel. + +- ``FPGA_PRELOADED_DTB_BASE`` : Physical address of the flattened device + tree blob (DTB). This DT will be used by TF-A for dynamic configuration, + so it must describe at least the UART and a GICv3 interrupt controller. + The DT gets amended by the code, to potentially add a command line and + fill the CPU topology nodes. It will also be passed on to BL33, by + putting its address into the x0 register before jumping to the entry + point (following the Linux kernel boot protocol). + It defaults to 0x80070000, which is 64KB before the BL33 load address. + +- ``FPGA_PRELOADED_CMD_LINE`` : Physical address of the command line to + put into the devicetree blob. Due to the lack of a proper bootloader, + a command line can be put somewhere into memory, so that BL31 will + detect it and copy it into the DTB passed on to BL33. + To avoid random garbage, there needs to be a "CMD:" signature before the + actual command line. + Defaults to 0x1000, which is normally in the "ROM" space of the typical + FPGA image (which can be written by the FPGA payload uploader, but is + read-only to the CPU). The FPGA payload tool should be given a text file + containing the desired command line, prefixed by the "CMD:" signature. + +Building the TF-A image +----------------------- + + .. code:: shell + + make PLAT=arm_fgpa DEBUG=1 + + This will use the default load addresses as described above. When those + addresses need to differ for a certain setup, they can be passed on the + make command line: + + .. code:: shell + + make PLAT=arm_fgpa DEBUG=1 PRELOADED_BL33_BASE=0x80200000 FPGA_PRELOADED_DTB_BASE=0x80180000 bl31 + +Running the TF-A image +---------------------- + +After building TF-A, the actual TF-A code will be located in ``bl31.bin`` in +the build directory. +Additionally there is a ``bl31.axf`` ELF file, which contains BL31, as well +as some simple ROM trampoline code (required by the Arm FPGA boot flow) and +a generic DTB to support most of the FPGA images. This can be simply handed +over to the FPGA payload uploader, which will take care of loading the +components at their respective load addresses. In addition to this file +you need at least a BL33 payload (typically a Linux kernel image), optionally +a Linux initrd image file and possibly a command line: + + .. code:: shell + + fpga-run ... -m bl31.axf -l auto -m Image -l 0x80080000 -m initrd.gz -l 0x84000000 -m cmdline.txt -l 0x1000 + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst b/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst new file mode 100644 index 0000000..b889b7f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst @@ -0,0 +1,61 @@ +Corstone1000 Platform +========================== + +Some of the features of the Corstone1000 platform referenced in TF-A include: + +- Cortex-A35 application processor (64-bit mode) +- Secure Enclave +- GIC-400 +- Trusted Board Boot + +Boot Sequence +------------- + +The board boot relies on CoT (chain of trust). The trusted-firmware-a +BL2 is extracted from the FIP and verified by the Secure Enclave +processor. BL2 verification relies on the signature area at the +beginning of the BL2 image. This area is needed by the SecureEnclave +bootloader. + +Then, the application processor is released from reset and starts by +executing BL2. + +BL2 performs the actions described in the trusted-firmware-a TBB design +document. + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain AArch64 ELF bare-metal target `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make LD=aarch64-none-elf-ld \ + CC=aarch64-none-elf-gcc \ + V=1 \ + BUILD_BASE= \ + PLAT=corstone1000 \ + SPD=spmd \ + SPMD_SPM_AT_SEL2=0 \ + DEBUG=1 \ + MBEDTLS_DIR=mbedtls \ + OPENSSL_DIR= \ + RUNTIME_SYSROOT= \ + ARCH=aarch64 \ + TARGET_PLATFORM= \ + ENABLE_PIE=1 \ + BL2_AT_EL3=1 \ + CREATE_KEYS=1 \ + GENERATE_COT=1 \ + TRUSTED_BOARD_BOOT=1 \ + COT=tbbr \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem \ + BL32= \ + BL33= \ + bl2 + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst new file mode 100644 index 0000000..8ac0741 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst @@ -0,0 +1,84 @@ +Arm Versatile Express +===================== + +Versatile Express (VE) family development platform provides an ultra fast +environment for prototyping Armv7 System-on-Chip designs. VE Fixed Virtual +Platforms (FVP) are simulations of Versatile Express boards. The platform in +Trusted Firmware-A has been verified with Arm Cortex-A5 and Cortex-A7 VE FVP's. +This platform is tested on and only expected to work with single core models. + +Boot Sequence +------------- + +BL1 --> BL2 --> BL32(sp_min) --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ +- `U-boot `__ + +- `Trusted Firmware-A `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Obtain arm toolchain. The software stack has been verified with linaro 6.2 + `arm-linux-gnueabihf `__. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Fetch and build u-boot. + Make the .config file using the command: + + .. code:: shell + + make ARCH=arm vexpress_aemv8a_aarch32_config + + Make the u-boot binary for Cortex-A5 using the command: + + .. code:: shell + + make ARCH=arm SUPPORT_ARCH_TIMER=no + + Make the u-boot binary for Cortex-A7 using the command: + + .. code:: shell + + make ARCH=arm + + +- Build TF-A: + + The make command for Cortex-A5 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A5=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A5x1.dts \ + ARM_XLAT_TABLES_LIB_V1=1 BL33= all fip + + The make command for Cortex-A7 is: + + .. code:: shell + + make PLAT=fvp_ve ARCH=aarch32 ARM_ARCH_MAJOR=7 ARM_CORTEX_A7=yes \ + AARCH32_SP=sp_min FVP_HW_CONFIG_DTS=fdts/fvp-ve-Cortex-A7x1.dts \ + BL33= all fip + +Run Procedure +~~~~~~~~~~~~~ + +The following model parameters should be used to boot Linux using the build of +Trusted Firmware-A made using the above make commands: + + .. code:: shell + + ./ \ + -C motherboard.flashloader1.fname= \ + --data cluster.cpu0=@0x80080000 \ + --data cluster.cpu0=@0x84000000 + +-------------- + +*Copyright (c) 2019, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/fvp/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp/index.rst new file mode 100644 index 0000000..2aaf195 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp/index.rst @@ -0,0 +1,652 @@ +Arm Fixed Virtual Platforms (FVP) +================================= + +Fixed Virtual Platform (FVP) Support +------------------------------------ + +This section lists the supported Arm |FVP| platforms. Please refer to the FVP +documentation for a detailed description of the model parameter options. + +The latest version of the AArch64 build of TF-A has been tested on the following +Arm FVPs without shifted affinities, and that do not support threaded CPU cores +(64-bit host machine only). + +.. note:: + The FVP models used are Version 11.16 Build 16, unless otherwise stated. + +- ``Foundation_Platform`` +- ``FVP_Base_AEMv8A-AEMv8A-AEMv8A-AEMv8A-CCN502`` +- ``FVP_Base_AEMv8A-AEMv8A`` (For certain configurations also uses 11.14/21) +- ``FVP_Base_AEMv8A-GIC600AE`` +- ``FVP_Base_AEMvA`` (For certain configurations also uses 0.0/6684) +- ``FVP_Base_Cortex-A32x4`` (Version 11.12/38) +- ``FVP_Base_Cortex-A35x4`` +- ``FVP_Base_Cortex-A53x4`` +- ``FVP_Base_Cortex-A55x4`` +- ``FVP_Base_Cortex-A55x4+Cortex-A75x4`` +- ``FVP_Base_Cortex-A57x1-A53x1`` +- ``FVP_Base_Cortex-A57x2-A53x4`` +- ``FVP_Base_Cortex-A57x4-A53x4`` +- ``FVP_Base_Cortex-A57x4`` +- ``FVP_Base_Cortex-A65AEx8`` +- ``FVP_Base_Cortex-A65x4`` +- ``FVP_Base_Cortex-A710x4`` +- ``FVP_Base_Cortex-A72x4-A53x4`` +- ``FVP_Base_Cortex-A72x4`` +- ``FVP_Base_Cortex-A73x4-A53x4`` +- ``FVP_Base_Cortex-A73x4`` +- ``FVP_Base_Cortex-A75x4`` +- ``FVP_Base_Cortex-A76AEx4`` +- ``FVP_Base_Cortex-A76AEx8`` +- ``FVP_Base_Cortex-A76x4`` +- ``FVP_Base_Cortex-A77x4`` +- ``FVP_Base_Cortex-A78x4`` +- ``FVP_Base_Neoverse-E1x1`` +- ``FVP_Base_Neoverse-E1x2`` +- ``FVP_Base_Neoverse-E1x4`` +- ``FVP_Base_Neoverse-N1x4`` +- ``FVP_Base_Neoverse-N2x4`` (Version 11.12 build 38) +- ``FVP_Base_Neoverse-V1x4`` +- ``FVP_Base_RevC-2xAEMvA`` (For certain configurations also uses 0.0/6557) +- ``FVP_CSS_SGI-575`` (Version 11.15/26) +- ``FVP_Morello`` (Version 0.11/19) +- ``FVP_RD_E1_edge`` (Version 11.15/26) +- ``FVP_RD_N1_edge_dual`` (Version 11.15/26) +- ``FVP_RD_N1_edge`` (Version 11.15/26) +- ``FVP_RD_V1`` (Version 11.15/26) +- ``FVP_TC0`` +- ``FVP_TC1`` + +The latest version of the AArch32 build of TF-A has been tested on the +following Arm FVPs without shifted affinities, and that do not support threaded +CPU cores (64-bit host machine only). + +- ``FVP_Base_AEMvA`` +- ``FVP_Base_AEMv8A-AEMv8A`` +- ``FVP_Base_Cortex-A32x4`` + +.. note:: + The ``FVP_Base_RevC-2xAEMv8A`` FVP only supports shifted affinities, which + is not compatible with legacy GIC configurations. Therefore this FVP does not + support these legacy GIC configurations. + +The *Foundation* and *Base* FVPs can be downloaded free of charge. See the `Arm +FVP website`_. The Cortex-A models listed above are also available to download +from `Arm's website`_. + +.. note:: + The build numbers quoted above are those reported by launching the FVP + with the ``--version`` parameter. + +.. note:: + Linaro provides a ramdisk image in prebuilt FVP configurations and full + file systems that can be downloaded separately. To run an FVP with a virtio + file system image an additional FVP configuration option + ``-C bp.virtioblockdevice.image_path="/`` can be + used. + +.. note:: + The software will not work on Version 1.0 of the Foundation FVP. + The commands below would report an ``unhandled argument`` error in this case. + +.. note:: + FVPs can be launched with ``--cadi-server`` option such that a + CADI-compliant debugger (for example, Arm DS-5) can connect to and control + its execution. + +.. warning:: + Since FVP model Version 11.0 Build 11.0.34 and Version 8.5 Build 0.8.5202 + the internal synchronisation timings changed compared to older versions of + the models. The models can be launched with ``-Q 100`` option if they are + required to match the run time characteristics of the older versions. + +All the above platforms have been tested with `Linaro Release 20.01`_. + +.. _build_options_arm_fvp_platform: + +Arm FVP Platform Specific Build Options +--------------------------------------- + +- ``FVP_CLUSTER_COUNT`` : Configures the cluster count to be used to + build the topology tree within TF-A. By default TF-A is configured for dual + cluster topology and this option can be used to override the default value. + +- ``FVP_INTERCONNECT_DRIVER``: Selects the interconnect driver to be built. The + default interconnect driver depends on the value of ``FVP_CLUSTER_COUNT`` as + explained in the options below: + + - ``FVP_CCI`` : The CCI driver is selected. This is the default + if 0 < ``FVP_CLUSTER_COUNT`` <= 2. + - ``FVP_CCN`` : The CCN driver is selected. This is the default + if ``FVP_CLUSTER_COUNT`` > 2. + +- ``FVP_MAX_CPUS_PER_CLUSTER``: Sets the maximum number of CPUs implemented in + a single cluster. This option defaults to 4. + +- ``FVP_MAX_PE_PER_CPU``: Sets the maximum number of PEs implemented on any CPU + in the system. This option defaults to 1. Note that the build option + ``ARM_PLAT_MT`` doesn't have any effect on FVP platforms. + +- ``FVP_USE_GIC_DRIVER`` : Selects the GIC driver to be built. Options: + + - ``FVP_GICV2`` : The GICv2 only driver is selected + - ``FVP_GICV3`` : The GICv3 only driver is selected (default option) + +- ``FVP_HW_CONFIG_DTS`` : Specify the path to the DTS file to be compiled + to DTB and packaged in FIP as the HW_CONFIG. See :ref:`Firmware Design` for + details on HW_CONFIG. By default, this is initialized to a sensible DTS + file in ``fdts/`` folder depending on other build options. But some cases, + like shifted affinity format for MPIDR, cannot be detected at build time + and this option is needed to specify the appropriate DTS file. + +- ``FVP_HW_CONFIG`` : Specify the path to the HW_CONFIG blob to be packaged in + FIP. See :ref:`Firmware Design` for details on HW_CONFIG. This option is + similar to the ``FVP_HW_CONFIG_DTS`` option, but it directly specifies the + HW_CONFIG blob instead of the DTS file. This option is useful to override + the default HW_CONFIG selected by the build system. + +- ``FVP_GICR_REGION_PROTECTION``: Mark the redistributor pages of + inactive/fused CPU cores as read-only. The default value of this option + is ``0``, which means the redistributor pages of all CPU cores are marked + as read and write. + +Booting Firmware Update images +------------------------------ + +When Firmware Update (FWU) is enabled there are at least 2 new images +that have to be loaded, the Non-Secure FWU ROM (NS-BL1U), and the +FWU FIP. + +The additional fip images must be loaded with: + +:: + + --data cluster0.cpu0="/ns_bl1u.bin"@0x0beb8000 [ns_bl1u_base_address] + --data cluster0.cpu0="/fwu_fip.bin"@0x08400000 [ns_bl2u_base_address] + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE. + +Booting an EL3 payload +---------------------- + +The EL3 payloads boot flow requires the CPU's mailbox to be cleared at reset for +the secondary CPUs holding pen to work properly. Unfortunately, its reset value +is undefined on the FVP platform and the FVP platform code doesn't clear it. +Therefore, one must modify the way the model is normally invoked in order to +clear the mailbox at start-up. + +One way to do that is to create an 8-byte file containing all zero bytes using +the following command: + +.. code:: shell + + dd if=/dev/zero of=mailbox.dat bs=1 count=8 + +and pre-load it into the FVP memory at the mailbox address (i.e. ``0x04000000``) +using the following model parameters: + +:: + + --data cluster0.cpu0=mailbox.dat@0x04000000 [Base FVPs] + --data=mailbox.dat@0x04000000 [Foundation FVP] + +To provide the model with the EL3 payload image, the following methods may be +used: + +#. If the EL3 payload is able to execute in place, it may be programmed into + flash memory. On Base Cortex and AEM FVPs, the following model parameter + loads it at the base address of the NOR FLASH1 (the NOR FLASH0 is already + used for the FIP): + + :: + + -C bp.flashloader1.fname="/" + + On Foundation FVP, there is no flash loader component and the EL3 payload + may be programmed anywhere in flash using method 3 below. + +#. When using the ``SPIN_ON_BL1_EXIT=1`` loading method, the following DS-5 + command may be used to load the EL3 payload ELF image over JTAG: + + :: + + load /el3-payload.elf + +#. The EL3 payload may be pre-loaded in volatile memory using the following + model parameters: + + :: + + --data cluster0.cpu0="/el3-payload>"@address [Base FVPs] + --data="/"@address [Foundation FVP] + + The address provided to the FVP must match the ``EL3_PAYLOAD_BASE`` address + used when building TF-A. + +Booting a preloaded kernel image (Base FVP) +------------------------------------------- + +The following example uses a simplified boot flow by directly jumping from the +TF-A to the Linux kernel, which will use a ramdisk as filesystem. This can be +useful if both the kernel and the device tree blob (DTB) are already present in +memory (like in FVP). + +For example, if the kernel is loaded at ``0x80080000`` and the DTB is loaded at +address ``0x82000000``, the firmware can be built like this: + +.. code:: shell + + CROSS_COMPILE=aarch64-none-elf- \ + make PLAT=fvp DEBUG=1 \ + RESET_TO_BL31=1 \ + ARM_LINUX_KERNEL_AS_BL33=1 \ + PRELOADED_BL33_BASE=0x80080000 \ + ARM_PRELOADED_DTB_BASE=0x82000000 \ + all fip + +Now, it is needed to modify the DTB so that the kernel knows the address of the +ramdisk. The following script generates a patched DTB from the provided one, +assuming that the ramdisk is loaded at address ``0x84000000``. Note that this +script assumes that the user is using a ramdisk image prepared for U-Boot, like +the ones provided by Linaro. If using a ramdisk without this header,the ``0x40`` +offset in ``INITRD_START`` has to be removed. + +.. code:: bash + + #!/bin/bash + + # Path to the input DTB + KERNEL_DTB=/ + # Path to the output DTB + PATCHED_KERNEL_DTB=/ + # Base address of the ramdisk + INITRD_BASE=0x84000000 + # Path to the ramdisk + INITRD=/ + + # Skip uboot header (64 bytes) + INITRD_START=$(printf "0x%x" $((${INITRD_BASE} + 0x40)) ) + INITRD_SIZE=$(stat -Lc %s ${INITRD}) + INITRD_END=$(printf "0x%x" $((${INITRD_BASE} + ${INITRD_SIZE})) ) + + CHOSEN_NODE=$(echo \ + "/ { \ + chosen { \ + linux,initrd-start = <${INITRD_START}>; \ + linux,initrd-end = <${INITRD_END}>; \ + }; \ + };") + + echo $(dtc -O dts -I dtb ${KERNEL_DTB}) ${CHOSEN_NODE} | \ + dtc -O dtb -o ${PATCHED_KERNEL_DTB} - + +And the FVP binary can be run with the following command: + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04001000 \ + -C cluster0.cpu1.RVBAR=0x04001000 \ + -C cluster0.cpu2.RVBAR=0x04001000 \ + -C cluster0.cpu3.RVBAR=0x04001000 \ + -C cluster1.cpu0.RVBAR=0x04001000 \ + -C cluster1.cpu1.RVBAR=0x04001000 \ + -C cluster1.cpu2.RVBAR=0x04001000 \ + -C cluster1.cpu3.RVBAR=0x04001000 \ + --data cluster0.cpu0="/bl31.bin"@0x04001000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Obtaining the Flattened Device Trees +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Depending on the FVP configuration and Linux configuration used, different +FDT files are required. FDT source files for the Foundation and Base FVPs can +be found in the TF-A source directory under ``fdts/``. The Foundation FVP has +a subset of the Base FVP components. For example, the Foundation FVP lacks +CLCD and MMC support, and has only one CPU cluster. + +.. note:: + It is not recommended to use the FDTs built along the kernel because not + all FDTs are available from there. + +The dynamic configuration capability is enabled in the firmware for FVPs. +This means that the firmware can authenticate and load the FDT if present in +FIP. A default FDT is packaged into FIP during the build based on +the build configuration. This can be overridden by using the ``FVP_HW_CONFIG`` +or ``FVP_HW_CONFIG_DTS`` build options (refer to +:ref:`build_options_arm_fvp_platform` for details on the options). + +- ``fvp-base-gicv2-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration. + +- ``fvp-base-gicv2-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration. + +- ``fvp-base-gicv3-psci.dts`` + + For use with models such as the Cortex-A57-A53 Base FVPs without shifted + affinities and with Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-1t.dts`` + + For use with models such as the AEMv8-RevC Base FVP with shifted affinities, + single threaded CPUs, Base memory map configuration and Linux GICv3 support. + +- ``fvp-base-gicv3-psci-dynamiq.dts`` + + For use with models as the Cortex-A55-A75 Base FVPs with shifted affinities, + single cluster, single threaded CPUs, Base memory map configuration and Linux + GICv3 support. + +- ``fvp-base-gicv3-psci-aarch32.dts`` + + For use with models such as the Cortex-A32 Base FVPs without shifted + affinities and running Linux in AArch32 state with Base memory map + configuration and Linux GICv3 support. + +- ``fvp-foundation-gicv2-psci.dts`` + + For use with Foundation FVP with Base memory map configuration. + +- ``fvp-foundation-gicv3-psci.dts`` + + (Default) For use with Foundation FVP with Base memory map configuration + and Linux GICv3 support. + + +Running on the Foundation FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``Foundation_Platform`` parameters should be used to boot Linux with +4 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /Foundation_Platform \ + --cores=4 \ + --arm-v8.0 \ + --secure-memory \ + --visualization \ + --gicv3 \ + --data="/"@0x0 \ + --data="/"@0x08000000 \ + --data="/"@0x80080000 \ + --data="/"@0x84000000 + +Notes: + +- BL1 is loaded at the start of the Trusted ROM. +- The Firmware Image Package is loaded at the start of NOR FLASH0. +- The firmware loads the FDT packaged in FIP to the DRAM. The FDT load address + is specified via the ``hw_config_addr`` property in `TB_FW_CONFIG for FVP`_. +- The default use-case for the Foundation FVP is to use the ``--gicv3`` option + and enable the GICv3 device in the model. Note that without this option, + the Foundation FVP defaults to legacy (Versatile Express) memory map which + is not supported by TF-A. +- In order for TF-A to run correctly on the Foundation FVP, the architecture + versions must match. The Foundation FVP defaults to the highest v8.x + version it supports but the default build for TF-A is for v8.0. To avoid + issues either start the Foundation FVP to use v8.0 architecture using the + ``--arm-v8.0`` option, or build TF-A with an appropriate value for + ``ARM_ARCH_MINOR``. + +Running on the AEMv8 Base FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +.. note:: + The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires + a specific DTS for all the CPUs to be loaded. + +Running on the AEMv8 Base FVP (AArch32) with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A57-A53 Base FVP with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to BL1 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C bp.secureflashloader.fname="/" \ + -C bp.flashloader0.fname="/" \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + + +Running on the AEMv8 Base FVP with reset to BL31 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_RevC-2xAEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_RevC-2xAEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBAR=0x04010000 \ + -C cluster0.cpu1.RVBAR=0x04010000 \ + -C cluster0.cpu2.RVBAR=0x04010000 \ + -C cluster0.cpu3.RVBAR=0x04010000 \ + -C cluster1.cpu0.RVBAR=0x04010000 \ + -C cluster1.cpu1.RVBAR=0x04010000 \ + -C cluster1.cpu2.RVBAR=0x04010000 \ + -C cluster1.cpu3.RVBAR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Notes: + +- Position Independent Executable (PIE) support is enabled in this + config allowing BL31 to be loaded at any valid address for execution. + +- Since a FIP is not loaded when using BL31 as reset entrypoint, the + ``--data=""@`` + parameter is needed to load the individual bootloader images in memory. + BL32 image is only needed if BL31 has been built to expect a Secure-EL1 + Payload. For the same reason, the FDT needs to be compiled from the DT source + and loaded via the ``--data cluster0.cpu0="/"@0x82000000`` + parameter. + +- The ``FVP_Base_RevC-2xAEMv8A`` has shifted affinities and requires a + specific DTS for all the CPUs to be loaded. + +- The ``-C cluster.cpu.RVBAR=@`` parameter, where + X and Y are the cluster and CPU numbers respectively, is used to set the + reset vector for each core. + +- Changing the default value of ``ARM_TSP_RAM_LOCATION`` will also require + changing the value of + ``--data=""@`` to the new value of + ``BL32_BASE``. + + +Running on the AEMv8 Base FVP (AArch32) with reset to SP_MIN entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_AEMv8A-AEMv8A`` parameters should be used to boot Linux +with 8 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_AEMv8A-AEMv8A \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cluster0.NUM_CORES=4 \ + -C cluster1.NUM_CORES=4 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.CONFIG64=0 \ + -C cluster0.cpu1.CONFIG64=0 \ + -C cluster0.cpu2.CONFIG64=0 \ + -C cluster0.cpu3.CONFIG64=0 \ + -C cluster1.cpu0.CONFIG64=0 \ + -C cluster1.cpu1.CONFIG64=0 \ + -C cluster1.cpu2.CONFIG64=0 \ + -C cluster1.cpu3.CONFIG64=0 \ + -C cluster0.cpu0.RVBAR=0x04002000 \ + -C cluster0.cpu1.RVBAR=0x04002000 \ + -C cluster0.cpu2.RVBAR=0x04002000 \ + -C cluster0.cpu3.RVBAR=0x04002000 \ + -C cluster1.cpu0.RVBAR=0x04002000 \ + -C cluster1.cpu1.RVBAR=0x04002000 \ + -C cluster1.cpu2.RVBAR=0x04002000 \ + -C cluster1.cpu3.RVBAR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +.. note:: + Position Independent Executable (PIE) support is enabled in this + config allowing SP_MIN to be loaded at any valid address for execution. + +Running on the Cortex-A57-A53 Base FVP with reset to BL31 entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A57x4-A53x4`` model parameters should be used to +boot Linux with 8 CPUs using the AArch64 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A57x4-A53x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04010000 \ + -C cluster0.cpu1.RVBARADDR=0x04010000 \ + -C cluster0.cpu2.RVBARADDR=0x04010000 \ + -C cluster0.cpu3.RVBARADDR=0x04010000 \ + -C cluster1.cpu0.RVBARADDR=0x04010000 \ + -C cluster1.cpu1.RVBARADDR=0x04010000 \ + -C cluster1.cpu2.RVBARADDR=0x04010000 \ + -C cluster1.cpu3.RVBARADDR=0x04010000 \ + --data cluster0.cpu0="/"@0x04010000 \ + --data cluster0.cpu0="/"@0xff000000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +Running on the Cortex-A32 Base FVP (AArch32) with reset to SP_MIN entrypoint +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The following ``FVP_Base_Cortex-A32x4`` model parameters should be used to +boot Linux with 4 CPUs using the AArch32 build of TF-A. + +.. code:: shell + + /FVP_Base_Cortex-A32x4 \ + -C pctl.startup=0.0.0.0 \ + -C bp.secure_memory=1 \ + -C bp.tzc_400.diagnostics=1 \ + -C cache_state_modelled=1 \ + -C cluster0.cpu0.RVBARADDR=0x04002000 \ + -C cluster0.cpu1.RVBARADDR=0x04002000 \ + -C cluster0.cpu2.RVBARADDR=0x04002000 \ + -C cluster0.cpu3.RVBARADDR=0x04002000 \ + --data cluster0.cpu0="/"@0x04002000 \ + --data cluster0.cpu0="/"@0x88000000 \ + --data cluster0.cpu0="/"@0x82000000 \ + --data cluster0.cpu0="/"@0x80080000 \ + --data cluster0.cpu0="/"@0x84000000 + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* + +.. _TB_FW_CONFIG for FVP: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/tree/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +.. _Arm's website: `FVP models`_ +.. _FVP models: https://developer.arm.com/products/system-design/fixed-virtual-platforms +.. _Linaro Release 20.01: http://releases.linaro.org/members/arm/platforms/20.01 +.. _Arm FVP website: https://developer.arm.com/products/system-design/fixed-virtual-platforms diff --git a/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst b/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst new file mode 100644 index 0000000..8af16ba --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst @@ -0,0 +1,46 @@ +ARM V8-R64 Fixed Virtual Platform (FVP) +======================================= + +Some of the features of Armv8-R AArch64 FVP platform referenced in Trusted +Boot R-class include: + +- Secure World Support Only +- EL2 as Maximum EL support (No EL3) +- MPU Support only at EL2 +- MPU or MMU Support at EL0/EL1 +- AArch64 Support Only +- Trusted Board Boot + +Further information on v8-R64 FVP is available at `info `_ + +Boot Sequence +------------- + +BL1 –> BL33 + +The execution begins from BL1 which loads the BL33 image, a boot-wrapped (bootloader + Operating System) +Operating System, from FIP to DRAM. + +Build Procedure +~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make PLAT=fvp_r BL33= all fip + + Enable TBBR by adding the following options to the make command: + + .. code:: shell + + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/index.rst b/arm-trusted-firmware/docs/plat/arm/index.rst new file mode 100644 index 0000000..2f68522 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/index.rst @@ -0,0 +1,24 @@ +Arm Development Platforms +========================= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + juno/index + fvp/index + fvp_r/index + fvp-ve/index + tc/index + arm_fpga/index + arm-build-options + morello/index + corstone1000/index + +This chapter holds documentation related to Arm's development platforms, +including both software models (FVPs) and hardware development boards +such as Juno. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/juno/index.rst b/arm-trusted-firmware/docs/plat/arm/juno/index.rst new file mode 100644 index 0000000..8b9d453 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/juno/index.rst @@ -0,0 +1,253 @@ +Arm Juno Development Platform +============================= + +Platform-specific build options +------------------------------- + +- ``JUNO_TZMP1`` : Boolean option to configure Juno to be used for TrustZone + Media Protection (TZ-MP1). Default value of this flag is 0. + +Running software on Juno +------------------------ + +This version of TF-A has been tested on variants r0, r1 and r2 of Juno. + +To run TF-A on Juno, you need to first prepare an SD card with Juno software +stack that includes TF-A. This version of TF-A is tested with pre-built +`Linaro release software stack`_ version 20.01. You can alternatively +build the software stack yourself by following the +`Juno platform software user guide`_. Once you prepare the software stack +on an SD card, you can replace the ``bl1.bin`` and ``fip.bin`` +binaries in the ``SOFTWARE/`` directory with custom built TF-A binaries. + +Preparing TF-A images +--------------------- + +This section provides Juno and FVP specific instructions to build Trusted +Firmware, obtain the additional required firmware, and pack it all together in +a single FIP binary. It assumes that a Linaro release software stack has been +installed. + +.. note:: + Pre-built binaries for AArch32 are available from Linaro Release 16.12 + onwards. Before that release, pre-built binaries are only available for + AArch64. + +.. warning:: + Follow the full instructions for one platform before switching to a + different one. Mixing instructions for different platforms may result in + corrupted binaries. + +.. warning:: + The uboot image downloaded by the Linaro workspace script does not always + match the uboot image packaged as BL33 in the corresponding fip file. It is + recommended to use the version that is packaged in the fip file using the + instructions below. + +.. note:: + For the FVP, the kernel FDT is packaged in FIP during build and loaded + by the firmware at runtime. + +#. Clean the working directory + + .. code:: shell + + make realclean + +#. Obtain SCP binaries (Juno) + + This version of TF-A is tested with SCP version 2.8.0 on Juno. You can + download pre-built SCP binaries (``scp_bl1.bin`` and ``scp_bl2.bin``) + from `TF-A downloads page`_. Alternatively, you can `build + the binaries from source`_. + +#. Obtain BL33 (all platforms) + + Use the fiptool to extract the BL33 image from the FIP + package included in the Linaro release: + + .. code:: shell + + # Build the fiptool + make [DEBUG=1] [V=1] fiptool + + # Unpack firmware images from Linaro FIP + ./tools/fiptool/fiptool unpack /[SOFTWARE]/fip.bin + + The unpack operation will result in a set of binary images extracted to the + current working directory. BL33 corresponds to ``nt-fw.bin``. + + .. note:: + The fiptool will complain if the images to be unpacked already + exist in the current directory. If that is the case, either delete those + files or use the ``--force`` option to overwrite. + + .. note:: + For AArch32, the instructions below assume that nt-fw.bin is a + normal world boot loader that supports AArch32. + +#. Build TF-A images and create a new FIP for FVP + + .. code:: shell + + # AArch64 + make PLAT=fvp BL33=nt-fw.bin all fip + + # AArch32 + make PLAT=fvp ARCH=aarch32 AARCH32_SP=sp_min BL33=nt-fw.bin all fip + +#. Build TF-A images and create a new FIP for Juno + + For AArch64: + + Building for AArch64 on Juno simply requires the addition of ``SCP_BL2`` + as a build parameter. + + .. code:: shell + + make PLAT=juno BL33=nt-fw.bin SCP_BL2=scp_bl2.bin all fip + + For AArch32: + + Hardware restrictions on Juno prevent cold reset into AArch32 execution mode, + therefore BL1 and BL2 must be compiled for AArch64, and BL32 is compiled + separately for AArch32. + + - Before building BL32, the environment variable ``CROSS_COMPILE`` must point + to the AArch32 Linaro cross compiler. + + .. code:: shell + + export CROSS_COMPILE=/bin/arm-linux-gnueabihf- + + - Build BL32 in AArch32. + + .. code:: shell + + make ARCH=aarch32 PLAT=juno AARCH32_SP=sp_min \ + RESET_TO_SP_MIN=1 JUNO_AARCH32_EL3_RUNTIME=1 bl32 + + - Save ``bl32.bin`` to a temporary location and clean the build products. + + :: + + cp /bl32.bin + make realclean + + - Before building BL1 and BL2, the environment variable ``CROSS_COMPILE`` + must point to the AArch64 Linaro cross compiler. + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + - The following parameters should be used to build BL1 and BL2 in AArch64 + and point to the BL32 file. + + .. code:: shell + + make ARCH=aarch64 PLAT=juno JUNO_AARCH32_EL3_RUNTIME=1 \ + BL33=nt-fw.bin SCP_BL2=scp_bl2.bin \ + BL32=/bl32.bin all fip + +The resulting BL1 and FIP images may be found in: + +:: + + # Juno + ./build/juno/release/bl1.bin + ./build/juno/release/fip.bin + + # FVP + ./build/fvp/release/bl1.bin + ./build/fvp/release/fip.bin + +After building TF-A, the files ``bl1.bin``, ``fip.bin`` and ``scp_bl1.bin`` +need to be copied to the ``SOFTWARE/`` directory on the Juno SD card. + +Booting Firmware Update images +------------------------------ + +The new images must be programmed in flash memory by adding +an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. User should ensure these do not +overlap with any other entries in the file. + +:: + + NOR10UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR10ADDRESS: 0x00400000 ;Image Flash Address [ns_bl2u_base_address] + NOR10FILE: \SOFTWARE\fwu_fip.bin ;Image File Name + NOR10LOAD: 00000000 ;Image Load Address + NOR10ENTRY: 00000000 ;Image Entry Point + + NOR11UPDATE: AUTO ;Image Update:NONE/AUTO/FORCE + NOR11ADDRESS: 0x03EB8000 ;Image Flash Address [ns_bl1u_base_address] + NOR11FILE: \SOFTWARE\ns_bl1u.bin ;Image File Name + NOR11LOAD: 00000000 ;Image Load Address + +The address ns_bl1u_base_address is the value of NS_BL1U_BASE - 0x8000000. +In the same way, the address ns_bl2u_base_address is the value of +NS_BL2U_BASE - 0x8000000. + +.. _plat_juno_booting_el3_payload: + +Booting an EL3 payload +---------------------- + +If the EL3 payload is able to execute in place, it may be programmed in flash +memory by adding an entry in the ``SITE1/HBI0262x/images.txt`` configuration file +on the Juno SD card (where ``x`` depends on the revision of the Juno board). +Refer to the `Juno Getting Started Guide`_, section 2.3 "Flash memory +programming" for more information. + +Alternatively, the same DS-5 command mentioned in the FVP section above can +be used to load the EL3 payload's ELF file over JTAG on Juno. + +For more information on EL3 payloads in general, see +:ref:`alt_boot_flows_el3_payload`. + +Booting a preloaded kernel image +-------------------------------- + +The Trusted Firmware must be compiled in a similar way as for FVP explained +above. The process to load binaries to memory is the one explained in +`plat_juno_booting_el3_payload`_. + +Testing System Suspend +---------------------- + +The SYSTEM SUSPEND is a PSCI API which can be used to implement system suspend +to RAM. For more details refer to section 5.16 of `PSCI`_. To test system suspend +on Juno, at the linux shell prompt, issue the following command: + +.. code:: shell + + echo +10 > /sys/class/rtc/rtc0/wakealarm + echo -n mem > /sys/power/state + +The Juno board should suspend to RAM and then wakeup after 10 seconds due to +wakeup interrupt from RTC. + +Additional Resources +-------------------- + +Please visit the `Arm Platforms Portal`_ to get support and obtain any other Juno +software information. Please also refer to the `Juno Getting Started Guide`_ to +get more detailed information about the Juno Arm development platform and how to +configure it. + +-------------- + +*Copyright (c) 2019-2021, Arm Limited. All rights reserved.* + +.. _Linaro release software stack: http://releases.linaro.org/members/arm/platforms/ +.. _Juno platform software user guide: https://git.linaro.org/landing-teams/working/arm/arm-reference-platforms.git/about/docs/juno/user-guide.rst +.. _TF-A downloads page: https://downloads.trustedfirmware.org/tf-a/css_scp_2.8.0/juno/ +.. _build the binaries from source: https://github.com/ARM-software/SCP-firmware/blob/master/user_guide.md#scp-firmware-user-guide +.. _Arm Platforms Portal: https://community.arm.com/dev-platforms/ +.. _Juno Getting Started Guide: http://infocenter.arm.com/help/topic/com.arm.doc.dui0928e/DUI0928E_juno_arm_development_platform_gsg.pdf +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Juno Arm Development Platform: http://www.arm.com/products/tools/development-boards/versatile-express/juno-arm-development-platform.php diff --git a/arm-trusted-firmware/docs/plat/arm/morello/index.rst b/arm-trusted-firmware/docs/plat/arm/morello/index.rst new file mode 100644 index 0000000..b18001c --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/morello/index.rst @@ -0,0 +1,33 @@ +Morello Platform +================ + +Morello is an ARMv8-A platform that implements the capability architecture extension. +The platform port present at `site `_ +provides ARMv8-A architecture enablement. + +Capability architecture specific changes will be added `here `_ + +Further information on Morello Platform is available at `info `_ + +Boot Sequence +------------- + +The execution begins from SCP_BL1 which loads the SCP_BL2 and starts its +execution. SCP_BL2 powers up the AP which starts execution at AP_BL31. The AP +then continues executing and hands off execution to Non-secure world (UEFI). + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + export CROSS_COMPILE=/bin/aarch64-none-elf- + + make PLAT=morello all + +*Copyright (c) 2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/arm/tc/index.rst b/arm-trusted-firmware/docs/plat/arm/tc/index.rst new file mode 100644 index 0000000..20d3e56 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/arm/tc/index.rst @@ -0,0 +1,56 @@ +TC Total Compute Platform +========================== + +Some of the features of TC platform referenced in TF-A include: + +- A `System Control Processor `_ + to abstract power and system management tasks away from application + processors. The RAM firmware for SCP is included in the TF-A FIP and is + loaded by AP BL2 from FIP in flash to SRAM for copying by SCP (SCP has access + to AP SRAM). +- GICv4 +- Trusted Board Boot +- SCMI +- MHUv2 + +Currently, the main difference between TC0 (TARGET_PLATFORM=0) and TC1 +(TARGET_PLATFORM=1) platforms w.r.t to TF-A is the CPUs supported. TC0 has +support for Cortex A510, Cortex A710 and Cortex X2, while TC1 has support for +Cortex A510, Cortex Makalu and Cortex Makalu ELP Arm CPUs. + + +Boot Sequence +------------- + +The execution begins from SCP_BL1. SCP_BL1 powers up the AP which starts +executing AP_BL1 and then executes AP_BL2 which loads the SCP_BL2 from +FIP to SRAM. The SCP has access to AP SRAM. The address and size of SCP_BL2 +is communicated to SCP using SDS. SCP copies SCP_BL2 from SRAM to its own +RAM and starts executing it. The AP then continues executing the rest of TF-A +stages including BL31 runtime stage and hands off executing to +Non-secure world (u-boot). + +Build Procedure (TF-A only) +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Obtain arm `toolchain `_. + Set the CROSS_COMPILE environment variable to point to the toolchain folder. + +- Build TF-A: + + .. code:: shell + + make PLAT=tc BL33= \ + SCP_BL2= TARGET_PLATFORM={0,1} all fip + + Enable TBBR by adding the following options to the make command: + + .. code:: shell + + MBEDTLS_DIR= \ + TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 \ + ARM_ROTPK_LOCATION=devel_rsa \ + ROT_KEY=plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem + +*Copyright (c) 2020-2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/brcm-stingray.rst b/arm-trusted-firmware/docs/plat/brcm-stingray.rst new file mode 100644 index 0000000..95029cc --- /dev/null +++ b/arm-trusted-firmware/docs/plat/brcm-stingray.rst @@ -0,0 +1,43 @@ +Broadcom Stingray +================= + +Description +----------- +Broadcom's Stingray(BCM958742t) is a multi-core processor with 8 Cortex-A72 cores. +Trusted Firmware-A (TF-A) is used to implement secure world firmware, supporting +BL2 and BL31 for Broadcom Stingray SoCs. + +On Poweron, Boot ROM will load bl2 image and Bl2 will initialize the hardware, +then loads bl31 and bl33 into DDR and boots to bl33. + +Boot Sequence +------------- + +Bootrom --> TF-A BL2 --> TF-A BL31 --> BL33(u-boot) + +Code Locations +~~~~~~~~~~~~~~ +- Trusted Firmware-A: + `link `__ + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build u-boot first, and get the binary image: u-boot.bin, + +- Build TF-A + + Build fip: + + .. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=stingray BOARD_CFG=bcm958742t all fip BL33=u-boot.bin + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ +The u-boot will be upstreamed soon, this doc will be updated once they are ready, and the link will be posted. diff --git a/arm-trusted-firmware/docs/plat/deprecated.rst b/arm-trusted-firmware/docs/plat/deprecated.rst new file mode 100644 index 0000000..7cc4258 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/deprecated.rst @@ -0,0 +1,20 @@ +Deprecated platforms +==================== + +Process of deprecating a platform +--------------------------------- + +Platform can be deprecated and its source can be kept in repository for a cooling +off period before deleting it or it can be deleted straight away. For later types +Deprecated/Deleted version would be same. + +List of deprecated platforms +---------------------------- + ++----------------+----------------+--------------------+--------------------+ +| Platform | Vendor | Deprecated version | Deleted version | ++================+================+====================+====================+ +| sgm775 | Arm | 2.5 | 2.7 | ++----------------+----------------+--------------------+--------------------+ +| mt6795 | MTK | 2.5 | 2.7 | ++----------------+----------------+--------------------+--------------------+ diff --git a/arm-trusted-firmware/docs/plat/hikey.rst b/arm-trusted-firmware/docs/plat/hikey.rst new file mode 100644 index 0000000..6c488b8 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/hikey.rst @@ -0,0 +1,155 @@ +HiKey +===== + +HiKey is one of 96boards. Hisilicon Kirin6220 processor is installed on HiKey. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- OP-TEE + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +- atf-fastboot: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + + .. code:: shell + + git clone https://github.com/ARM-software/arm-trusted-firmware -b integration + git clone https://github.com/OP-TEE/optee_os + git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5 + git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4 + git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2 + git clone https://github.com/96boards-hikey/atf-fastboot + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 && AARCH32 toolchain. Prepare python. + +- If your hikey hardware is built by CircuitCo, update *OpenPlatformPkg/Platforms/Hisilicon/HiKey/HiKey.dsc* first. *(optional)* + console on hikey.** + + .. code:: shell + + DEFINE SERIAL_BASE=0xF8015000 + + If your hikey hardware is built by LeMaker, nothing to do. + +- Build it as debug mode. Create your own build script file or you could refer to **build\_uefi.sh** in l-loader git repository. + + .. code:: shell + + cd {BUILD_PATH}/arm-trusted-firmware + sh ../l-loader/build_uefi.sh hikey + +- Generate l-loader.bin and partition table for aosp. The eMMC capacity is either 8GB or 4GB. Just change "aosp-8g" to "linux-8g" for debian. + + .. code:: shell + + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl2.bin + ln -sf ${BUILD_PATH}/atf-fastboot/build/hikey/${FASTBOOT_BUILD_OPTION}/bl1.bin fastboot.bin + make hikey PTABLE_LST=aosp-8g + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI fails to display Boot Manager GUI in minicom. **If you don't need Boot Manager GUI, just ignore this section.** + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in below. + *#ser2net.conf* + + .. code:: shell + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Start ser2net + + .. code:: shell + + $sudo killall ser2net + $sudo ser2net -u + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Flash images in recovery mode +----------------------------- + +- Make sure Pin3-Pin4 on J15 are connected for recovery mode. Then power on HiKey. + +- Remove the modemmanager package. This package may cause the idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download recovery.bin into HiKey. + + .. code:: shell + + $sudo python hisi-idt.py -d /dev/ttyUSB1 --img1 recovery.bin + +- Update images. All aosp or debian images could be fetched from `link `__. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash loader l-loader.bin + $sudo fastboot flash fastboot fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +Boot UEFI in normal mode +------------------------ + +- Make sure Pin3-Pin4 on J15 are open for normal boot mode. Then power on HiKey. + +- Reference `link `__ + +.. _link: https://www.96boards.org/documentation/consumer/hikey/ diff --git a/arm-trusted-firmware/docs/plat/hikey960.rst b/arm-trusted-firmware/docs/plat/hikey960.rst new file mode 100644 index 0000000..982c2c8 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/hikey960.rst @@ -0,0 +1,180 @@ +HiKey960 +======== + +HiKey960 is one of 96boards. Hisilicon Hi3660 processor is installed on HiKey960. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- OP-TEE: + `link `__ + +- edk2: + `link `__ + +- OpenPlatformPkg: + `link `__ + +- l-loader: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 5 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + + .. code:: shell + + git clone https://github.com/ARM-software/arm-trusted-firmware -b integration + git clone https://github.com/OP-TEE/optee_os + git clone https://github.com/96boards-hikey/edk2 -b testing/hikey960_v2.5 + git clone https://github.com/96boards-hikey/OpenPlatformPkg -b testing/hikey960_v1.3.4 + git clone https://github.com/96boards-hikey/l-loader -b testing/hikey960_v1.2 + +- Create the symbol link to OpenPlatformPkg in edk2. + + .. code:: shell + + $cd ${BUILD_PATH}/edk2 + $ln -sf ../OpenPlatformPkg + +- Prepare AARCH64 toolchain. + +- If your hikey960 hardware is v1, update *OpenPlatformPkg/Platforms/Hisilicon/HiKey960/HiKey960.dsc* first. *(optional)* + + .. code:: shell + + DEFINE SERIAL_BASE=0xFDF05000 + + If your hikey960 hardware is v2 or newer, nothing to do. + +- Build it as debug mode. Create script file for build. + + .. code:: shell + + cd {BUILD_PATH}/arm-trusted-firmware + sh ../l-loader/build_uefi.sh hikey960 + +- Generate l-loader.bin and partition table. + *Make sure that you're using the sgdisk in the l-loader directory.* + + .. code:: shell + + cd ${BUILD_PATH}/l-loader + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl1.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/bl2.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/fip.bin + ln -sf ${EDK2_OUTPUT_DIR}/FV/BL33_AP_UEFI.fd + make hikey960 + +Setup Console +------------- + +- Install ser2net. Use telnet as the console since UEFI will output window + that fails to display in minicom. + + .. code:: shell + + $sudo apt-get install ser2net + +- Configure ser2net. + + .. code:: shell + + $sudo vi /etc/ser2net.conf + + Append one line for serial-over-USB in *#ser2net.conf* + + :: + + 2004:telnet:0:/dev/ttyUSB0:115200 8DATABITS NONE 1STOPBIT banner + +- Start ser2net + + .. code:: shell + + $sudo killall ser2net + $sudo ser2net -u + +- Open the console. + + .. code:: shell + + $telnet localhost 2004 + + And you could open the console remotely, too. + +Boot UEFI in recovery mode +-------------------------- + +- Fetch that are used in recovery mode. The code location is in below. + `link `__ + +- Prepare recovery binary. + + .. code:: shell + + $cd tools-images-hikey960 + $ln -sf ${BUILD_PATH}/l-loader/l-loader.bin + $ln -sf ${BUILD_PATH}/l-loader/fip.bin + $ln -sf ${BUILD_PATH}/l-loader/recovery.bin + +- Prepare config file. + + .. code:: shell + + $vi config + # The content of config file + ./sec_usb_xloader.img 0x00020000 + ./sec_uce_boot.img 0x6A908000 + ./recovery.bin 0x1AC00000 + +- Remove the modemmanager package. This package may causes hikey\_idt tool failure. + + .. code:: shell + + $sudo apt-get purge modemmanager + +- Run the command to download recovery.bin into HiKey960. + + .. code:: shell + + $sudo ./hikey_idt -c config -p /dev/ttyUSB1 + +- UEFI running in recovery mode. + When prompt '.' is displayed on console, press hotkey 'f' in keyboard. Then Android fastboot app is running. + The timeout of prompt '.' is 10 seconds. + +- Update images. + + .. code:: shell + + $sudo fastboot flash ptable prm_ptable.img + $sudo fastboot flash xloader sec_xloader.img + $sudo fastboot flash fastboot l-loader.bin + $sudo fastboot flash fip fip.bin + $sudo fastboot flash boot boot.img + $sudo fastboot flash cache cache.img + $sudo fastboot flash system system.img + $sudo fastboot flash userdata userdata.img + +- Notice: UEFI could also boot kernel in recovery mode, but BL31 isn't loaded in + recovery mode. + +Boot UEFI in normal mode +------------------------ + +- Make sure "Boot Mode" switch is OFF for normal boot mode. Then power on HiKey960. + +- Reference `link `__ + +.. _link: https://www.96boards.org/documentation/consumer/hikey/hikey960 diff --git a/arm-trusted-firmware/docs/plat/imx8.rst b/arm-trusted-firmware/docs/plat/imx8.rst new file mode 100644 index 0000000..49ba374 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/imx8.rst @@ -0,0 +1,58 @@ +NXP i.MX 8 Series +================= + +The i.MX 8 series of applications processors is a feature- and +performance-scalable multi-core platform that includes single-, +dual-, and quad-core families based on the Arm® Cortex® +architecture—including combined Cortex-A72 + Cortex-A53, +Cortex-A35, and Cortex-M4 based solutions for advanced graphics, +imaging, machine vision, audio, voice, video, and safety-critical +applications. + +The i.MX8QM is with 2 Cortex-A72 ARM core, 4 Cortex-A53 ARM core +and 1 Cortex-M4 system controller. + +The i.MX8QX is with 4 Cortex-A35 ARM core and 1 Cortex-M4 system +controller. + +The System Controller (SC) represents the evolution of centralized +control for system-level resources on i.MX8. The heart of the system +controller is a Cortex-M4 that executes system controller firmware. + +Boot Sequence +------------- + +Bootrom --> BL31 --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build System Controller Firmware and u-boot firstly, and get binary images: scfw_tcm.bin and u-boot.bin + +- Build TF-A + + Build bl31: + + .. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT= bl31 + + Target_SoC should be "imx8qm" for i.MX8QM SoC. + Target_SoC should be "imx8qx" for i.MX8QX SoC. + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ + +TF-A binary(bl31.bin), scfw_tcm.bin and u-boot.bin are combined together +to generate a binary file called flash.bin, the imx-mkimage tool is used +to generate flash.bin, and flash.bin needs to be flashed into SD card +with certain offset for BOOT ROM. The system controller firmware, +u-boot and imx-mkimage will be upstreamed soon, this doc will be updated +once they are ready, and the link will be posted. + +.. _i.MX8: https://www.nxp.com/products/processors-and-microcontrollers/applications-processors/i.mx-applications-processors/i.mx-8-processors/i.mx-8-family-arm-cortex-a53-cortex-a72-virtualization-vision-3d-graphics-4k-video:i.MX8 diff --git a/arm-trusted-firmware/docs/plat/imx8m.rst b/arm-trusted-firmware/docs/plat/imx8m.rst new file mode 100644 index 0000000..101d52b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/imx8m.rst @@ -0,0 +1,70 @@ +NXP i.MX 8M Series +================== + +The i.MX 8M family of applications processors based on Arm Corte-A53 and Cortex-M4 +cores provide high-performance computing, power efficiency, enhanced system +reliability and embedded security needed to drive the growth of fast-growing +edge node computing, streaming multimedia, and machine learning applications. + +imx8mq is dropped in TF-A CI build due to the small OCRAM size, but still actively +maintained in NXP official release. + +Boot Sequence +------------- + +Bootrom --> SPL --> BL31 --> BL33(u-boot) --> Linux kernel + +How to build +------------ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Prepare AARCH64 toolchain. + +- Build spl and u-boot firstly, and get binary images: u-boot-spl.bin, + u-boot-nodtb.bin and dtb for the target board. + +- Build TF-A + + Build bl31: + + .. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT= bl31 + + Target_SoC should be "imx8mq" for i.MX8MQ SoC. + Target_SoC should be "imx8mm" for i.MX8MM SoC. + Target_SoC should be "imx8mn" for i.MX8MN SoC. + Target_SoC should be "imx8mp" for i.MX8MP SoC. + +Deploy TF-A Images +~~~~~~~~~~~~~~~~~~ + +TF-A binary(bl31.bin), u-boot-spl.bin u-boot-nodtb.bin and dtb are combined +together to generate a binary file called flash.bin, the imx-mkimage tool is +used to generate flash.bin, and flash.bin needs to be flashed into SD card +with certain offset for BOOT ROM. the u-boot and imx-mkimage will be upstreamed +soon, this doc will be updated once they are ready, and the link will be posted. + +TBBR Boot Sequence +------------------ + +When setting NEED_BL2=1 on imx8mm. We support an alternative way of +boot sequence to support TBBR. + +Bootrom --> SPL --> BL2 --> BL31 --> BL33(u-boot with UEFI) --> grub + +This helps us to fulfill the SystemReady EBBR standard. +BL2 will be in the FIT image and SPL will verify it. +All of the BL3x will be put in the FIP image. BL2 will verify them. +In U-boot we turn on the UEFI secure boot features so it can verify +grub. And we use grub to verify linux kernel. + +Measured Boot +------------- + +When setting MEASURED_BOOT=1 on imx8mm we can let TF-A generate event logs +with a DTB overlay. The overlay will be put at PLAT_IMX8M_DTO_BASE with +maximum size PLAT_IMX8M_DTO_MAX_SIZE. Then in U-boot we can apply the DTB +overlay and let U-boot to parse the event log and update the PCRs. diff --git a/arm-trusted-firmware/docs/plat/index.rst b/arm-trusted-firmware/docs/plat/index.rst new file mode 100644 index 0000000..0cef16a --- /dev/null +++ b/arm-trusted-firmware/docs/plat/index.rst @@ -0,0 +1,66 @@ +Platform Ports +============== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + :hidden: + + allwinner + arm/index + deprecated + meson-axg + meson-gxbb + meson-gxl + meson-g12a + hikey + hikey960 + intel-agilex + intel-stratix10 + marvell/index + mt8183 + mt8186 + mt8192 + mt8195 + nvidia-tegra + warp7 + imx8 + imx8m + nxp/index + poplar + qemu + qemu-sbsa + qti + qti-msm8916 + rpi3 + rpi4 + rcar-gen3 + rz-g2 + rockchip + socionext-uniphier + synquacer + stm32mp1 + ti-k3 + xilinx-versal + xilinx-zynqmp + brcm-stingray + +This section provides a list of supported upstream *platform ports* and the +documentation associated with them. + +.. note:: + In addition to the platforms ports listed within the table of contents, there + are several additional platforms that are supported upstream but which do not + currently have associated documentation: + + - Arm Neoverse N1 System Development Platform (N1SDP) + - Arm Neoverse Reference Design N1 Edge (RD-N1-Edge) FVP + - Arm Neoverse Reference Design E1 Edge (RD-E1-Edge) FVP + - Arm SGI-575 and SGM-775 + - MediaTek MT6795 and MT8173 SoCs + - Arm Morello Platform + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/intel-agilex.rst b/arm-trusted-firmware/docs/plat/intel-agilex.rst new file mode 100644 index 0000000..ff27b6b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/intel-agilex.rst @@ -0,0 +1,86 @@ +Intel Agilex SoCFPGA +======================== + +Agilex SoCFPGA is a FPGA with integrated quad-core 64-bit Arm Cortex A53 processor. + +Upon boot, Boot ROM loads bl2 into OCRAM. Bl2 subsequently initializes +the hardware, then loads bl31 and bl33 (UEFI) into DDR and boots to bl33. + +:: + + Boot ROM --> Trusted Firmware-A --> UEFI + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- UEFI (to be updated with new upstreamed UEFI): + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 2 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build UEFI using Agilex platform as configuration + This will be updated to use an updated UEFI using the latest EDK2 source + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- device=agx + +- Build atf providing the previously generated UEFI as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- bl2 fip PLAT=agilex + BL33=PEI.ROM + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- dd fip.bin to a A2 partition on the MMC drive to be booted in Agilex + board. + +- Generate a SOF containing bl2 + +.. code:: bash + + aarch64-linux-gnu-objcopy -I binary -O ihex --change-addresses 0xffe00000 bl2.bin bl2.hex + quartus_cpf --bootloader bl2.hex + +- Configure SOF to board + +.. code:: bash + + nios2-configure-sof + +Boot trace +---------- + +:: + + INFO: DDR: DRAM calibration success. + INFO: ECC is disabled. + NOTICE: BL2: v2.1(debug) + NOTICE: BL2: Built + INFO: BL2: Doing platform setup + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0xffe1c000 + INFO: SPSR = 0x3cd + NOTICE: BL31: v2.1(debug) + NOTICE: BL31: Built + INFO: ARM GICv2 driver initialized + INFO: BL31: Initializing runtime services + WARNING: BL31: cortex_a53 + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x50000 + INFO: SPSR = 0x3c9 diff --git a/arm-trusted-firmware/docs/plat/intel-stratix10.rst b/arm-trusted-firmware/docs/plat/intel-stratix10.rst new file mode 100644 index 0000000..7f8d18e --- /dev/null +++ b/arm-trusted-firmware/docs/plat/intel-stratix10.rst @@ -0,0 +1,94 @@ +Intel Stratix 10 SoCFPGA +======================== + +Stratix 10 SoCFPGA is a FPGA with integrated quad-core 64-bit Arm Cortex A53 processor. + +Upon boot, Boot ROM loads bl2 into OCRAM. Bl2 subsequently initializes +the hardware, then loads bl31 and bl33 (UEFI) into DDR and boots to bl33. + +:: + + Boot ROM --> Trusted Firmware-A --> UEFI + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- UEFI (to be updated with new upstreamed UEFI): + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 2 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build UEFI using Stratix 10 platform as configuration + This will be updated to use an updated UEFI using the latest EDK2 source + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- device=s10 + +- Build atf providing the previously generated UEFI as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- bl2 fip PLAT=stratix10 + BL33=PEI.ROM + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- dd fip.bin to a A2 partition on the MMC drive to be booted in Stratix 10 + board. + +- Generate a SOF containing bl2 + +.. code:: bash + + aarch64-linux-gnu-objcopy -I binary -O ihex --change-addresses 0xffe00000 bl2.bin bl2.hex + quartus_cpf --bootloader bl2.hex + +- Configure SOF to board + +.. code:: bash + + nios2-configure-sof + +Boot trace +---------- + +:: + + INFO: DDR: DRAM calibration success. + INFO: ECC is disabled. + INFO: Init HPS NOC's DDR Scheduler. + NOTICE: BL2: v2.0(debug):v2.0-809-g7f8474a-dirty + NOTICE: BL2: Built : 17:38:19, Feb 18 2019 + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + INFO: Loading image id=3 at address 0xffe1c000 + INFO: Image id=3 loaded: 0xffe1c000 - 0xffe24034 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000 + INFO: Image id=5 loaded: 0x50000 - 0x550000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0xffe1c000 + INFO: SPSR = 0x3cd + NOTICE: BL31: v2.0(debug):v2.0-810-g788c436-dirty + NOTICE: BL31: Built : 15:17:16, Feb 20 2019 + INFO: ARM GICv2 driver initialized + INFO: BL31: Initializing runtime services + WARNING: BL31: cortex_a53: CPU workaround for 855873 was missing! + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x50000 + INFO: SPSR = 0x3c9 + UEFI firmware (version 1.0 built at 11:26:18 on Nov 7 2018) diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/build.rst b/arm-trusted-firmware/docs/plat/marvell/armada/build.rst new file mode 100644 index 0000000..adb9603 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/build.rst @@ -0,0 +1,476 @@ +TF-A Build Instructions for Marvell Platforms +============================================= + +This section describes how to compile the Trusted Firmware-A (TF-A) project for Marvell's platforms. + +Build Instructions +------------------ +(1) Set the cross compiler + + .. code:: shell + + > export CROSS_COMPILE=/path/to/toolchain/aarch64-linux-gnu- + +(2) Set path for FIP images: + +Set U-Boot image path (relatively to TF-A root or absolute path) + + .. code:: shell + + > export BL33=path/to/u-boot.bin + +For example: if U-Boot project (and its images) is located at ``~/project/u-boot``, +BL33 should be ``~/project/u-boot/u-boot.bin`` + + .. note:: + + *u-boot.bin* should be used and not *u-boot-spl.bin* + +Set MSS/SCP image path (mandatory only for A7K/8K/CN913x when MSS_SUPPORT=1) + + .. code:: shell + + > export SCP_BL2=path/to/mrvl_scp_bl2*.img + +(3) Armada-37x0 build requires WTP tools installation. + +See below in the section "Tools and external components installation". +Install ARM 32-bit cross compiler, which is required for building WTMI image for CM3 + + .. code:: shell + + > sudo apt-get install gcc-arm-linux-gnueabi + +(4) Clean previous build residuals (if any) + + .. code:: shell + + > make distclean + +(5) Build TF-A + +There are several build options: + +- PLAT + + Supported Marvell platforms are: + + - a3700 - A3720 DB, EspressoBin and Turris MOX + - a70x0 + - a70x0_amc - AMC board + - a70x0_mochabin - Globalscale MOCHAbin + - a80x0 + - a80x0_mcbin - MacchiatoBin + - a80x0_puzzle - IEI Puzzle-M801 + - t9130 - CN913x + - t9130_cex7_eval - CN913x CEx7 Evaluation Board + +- DEBUG + + Default is without debug information (=0). in order to enable it use ``DEBUG=1``. + Can be enabled also when building UART recovery images, there is no issue with it. + + Production TF-A images should be built without this debug option! + +- LOG_LEVEL + + Defines the level of logging which will be purged to the default output port. + + - 0 - LOG_LEVEL_NONE + - 10 - LOG_LEVEL_ERROR + - 20 - LOG_LEVEL_NOTICE (default for DEBUG=0) + - 30 - LOG_LEVEL_WARNING + - 40 - LOG_LEVEL_INFO (default for DEBUG=1) + - 50 - LOG_LEVEL_VERBOSE + +- USE_COHERENT_MEM + + This flag determines whether to include the coherent memory region in the + BL memory map or not. Enabled by default. + +- LLC_ENABLE + + Flag defining the LLC (L3) cache state. The cache is enabled by default (``LLC_ENABLE=1``). + +- LLC_SRAM + + Flag enabling the LLC (L3) cache SRAM support. The LLC SRAM is activated and used + by Trusted OS (OP-TEE OS, BL32). The TF-A only prepares CCU address translation windows + for SRAM address range at BL31 execution stage with window target set to DRAM-0. + When Trusted OS activates LLC SRAM, the CCU window target is changed to SRAM. + There is no reason to enable this feature if OP-TEE OS built with CFG_WITH_PAGER=n. + Only set LLC_SRAM=1 if OP-TEE OS is built with CFG_WITH_PAGER=y. + +- MARVELL_SECURE_BOOT + + Build trusted(=1)/non trusted(=0) image, default is non trusted. + This parameter is used only for ``mrvl_flash`` and ``mrvl_uart`` targets. + +- MV_DDR_PATH + + This parameter is required for ``mrvl_flash`` and ``mrvl_uart`` targets. + For A7K/8K/CN913x it is used for BLE build and for Armada37x0 it used + for ddr_tool build. + + Specify path to the full checkout of Marvell mv-ddr-marvell git + repository. Checkout must contain also .git subdirectory because + mv-ddr build process calls git commands. + + Do not remove any parts of git checkout becuase build process and other + applications need them for correct building and version determination. + + +CN913x specific build options: + +- CP_NUM + + Total amount of CPs (South Bridge) connected to AP. When the parameter is omitted, + the build uses the default number of CPs, which is a number of embedded CPs inside the + package: 1 or 2 depending on the SoC used. The parameter is valid for OcteonTX2 CN913x SoC + family (PLAT=t9130), which can have external CPs connected to the MCI ports. Valid + values with CP_NUM are in a range of 1 to 3. + + +A7K/8K/CN913x specific build options: + +- BLE_PATH + + Points to BLE (Binary ROM extension) sources folder. + The parameter is optional, its default value is ``plat/marvell/armada/a8k/common/ble`` + which uses TF-A in-tree BLE implementation. + +- MSS_SUPPORT + + When ``MSS_SUPPORT=1``, then TF-A includes support for Management SubSystem (MSS). + When enabled it is required to specify path to the MSS firmware image via ``SCP_BL2`` + option. + + This option is by default enabled. + +- SCP_BL2 + + Specify path to the MSS fimware image binary which will run on Cortex-M3 coprocessor. + It is available in Marvell binaries-marvell git repository. Required when ``MSS_SUPPORT=1``. + +Globalscale MOCHAbin specific build options: + +- DDR_TOPOLOGY + + The DDR topology map index/name, default is 0. + + Supported Options: + - 0 - DDR4 1CS 2GB + - 1 - DDR4 1CS 4GB + - 2 - DDR4 2CS 8GB + +Armada37x0 specific build options: + +- HANDLE_EA_EL3_FIRST + + When ``HANDLE_EA_EL3_FIRST=1``, External Aborts and SError Interrupts will be always trapped + in TF-A. TF-A in this case enables dirty hack / workaround for a bug found in U-Boot and + Linux kernel PCIe controller driver pci-aardvark.c, traps and then masks SError interrupt + caused by AXI SLVERR on external access (syndrome 0xbf000002). + + Otherwise when ``HANDLE_EA_EL3_FIRST=0``, these exceptions will be trapped in the current + exception level (or in EL1 if the current exception level is EL0). So exceptions caused by + U-Boot will be trapped in U-Boot, exceptions caused by Linux kernel (or user applications) + will be trapped in Linux kernel. + + Mentioned bug in pci-aardvark.c driver is fixed in U-Boot version v2021.07 and Linux kernel + version v5.13 (workarounded since Linux kernel version 5.9) and also backported in Linux + kernel stable releases since versions v5.12.13, v5.10.46, v5.4.128, v4.19.198, v4.14.240. + + If target system has already patched version of U-Boot and Linux kernel then it is strongly + recommended to not enable this workaround as it disallows propagating of all External Aborts + to running Linux kernel and makes correctable errors as fatal aborts. + + This option is now disabled by default. In past this option was enabled by default in + TF-A versions v2.2, v2.3, v2.4 and v2.5. + +- CM3_SYSTEM_RESET + + When ``CM3_SYSTEM_RESET=1``, the Cortex-M3 secure coprocessor will be used for system reset. + + TF-A will send command 0x0009 with a magic value via the rWTM mailbox interface to the + Cortex-M3 secure coprocessor. + The firmware running in the coprocessor must either implement this functionality or + ignore the 0x0009 command (which is true for the firmware from A3700-utils-marvell + repository). If this option is enabled but the firmware does not support this command, + an error message will be printed prior trying to reboot via the usual way. + + This option is needed on Turris MOX as a workaround to a HW bug which causes reset to + sometime hang the board. + +- A3720_DB_PM_WAKEUP_SRC + + For Armada 3720 Development Board only, when ``A3720_DB_PM_WAKEUP_SRC=1``, + TF-A will setup PM wake up src configuration. This option is disabled by default. + + +Armada37x0 specific build options for ``mrvl_flash`` and ``mrvl_uart`` targets: + +- DDR_TOPOLOGY + + The DDR topology map index/name, default is 0. + + Supported Options: + - 0 - DDR3 1CS 512MB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5) + - 1 - DDR4 1CS 512MB (DB-88F3720-DDR4-Modular) + - 2 - DDR3 2CS 1GB (EspressoBin V3-V5) + - 3 - DDR4 2CS 4GB (DB-88F3720-DDR4-Modular) + - 4 - DDR3 1CS 1GB (DB-88F3720-DDR3-Modular, EspressoBin V3-V5) + - 5 - DDR4 1CS 1GB (EspressoBin V7, EspressoBin-Ultra) + - 6 - DDR4 2CS 2GB (EspressoBin V7) + - 7 - DDR3 2CS 2GB (EspressoBin V3-V5) + - CUST - CUSTOMER BOARD (Customer board settings) + +- CLOCKSPRESET + + The clock tree configuration preset including CPU and DDR frequency, + default is CPU_800_DDR_800. + + - CPU_600_DDR_600 - CPU at 600 MHz, DDR at 600 MHz + - CPU_800_DDR_800 - CPU at 800 MHz, DDR at 800 MHz + - CPU_1000_DDR_800 - CPU at 1000 MHz, DDR at 800 MHz + - CPU_1200_DDR_750 - CPU at 1200 MHz, DDR at 750 MHz + + Look at Armada37x0 chip package marking on board to identify correct CPU frequency. + The last line on package marking (next line after the 88F37x0 line) should contain: + + - C080 or I080 - chip with 800 MHz CPU - use ``CLOCKSPRESET=CPU_800_DDR_800`` + - C100 or I100 - chip with 1000 MHz CPU - use ``CLOCKSPRESET=CPU_1000_DDR_800`` + - C120 - chip with 1200 MHz CPU - use ``CLOCKSPRESET=CPU_1200_DDR_750`` + +- BOOTDEV + + The flash boot device, default is ``SPINOR``. + + Currently, Armada37x0 only supports ``SPINOR``, ``SPINAND``, ``EMMCNORM`` and ``SATA``: + + - SPINOR - SPI NOR flash boot + - SPINAND - SPI NAND flash boot + - EMMCNORM - eMMC Download Mode + + Download boot loader or program code from eMMC flash into CM3 or CA53 + Requires full initialization and command sequence + + - SATA - SATA device boot + + Image needs to be stored at disk LBA 0 or at disk partition with + MBR type 0x4d (ASCII 'M' as in Marvell) or at disk partition with + GPT partition type GUID ``6828311A-BA55-42A4-BCDE-A89BB5EDECAE``. + +- PARTNUM + + The boot partition number, default is 0. + + To boot from eMMC, the value should be aligned with the parameter in + U-Boot with name of ``CONFIG_SYS_MMC_ENV_PART``, whose value by default is + 1. For details about CONFIG_SYS_MMC_ENV_PART, please refer to the U-Boot + build instructions. + +- WTMI_IMG + + The path of the binary can point to an image which + does nothing, an image which supports EFUSE or a customized CM3 firmware + binary. The default image is ``fuse.bin`` that built from sources in WTP + folder, which is the next option. If the default image is OK, then this + option should be skipped. + + Please note that this is not a full WTMI image, just a main loop without + hardware initialization code. Final WTMI image is built from this WTMI_IMG + binary and sys-init code from the WTP directory which sets DDR and CPU + clocks according to DDR_TOPOLOGY and CLOCKSPRESET options. + + CZ.NIC as part of Turris project released free and open source WTMI + application firmware ``wtmi_app.bin`` for all Armada 3720 devices. + This firmware includes additional features like access to Hardware + Random Number Generator of Armada 3720 SoC which original Marvell's + ``fuse.bin`` image does not have. + + CZ.NIC's Armada 3720 Secure Firmware is available at website: + + https://gitlab.nic.cz/turris/mox-boot-builder/ + +- WTP + + Specify path to the full checkout of Marvell A3700-utils-marvell git + repository. Checkout must contain also .git subdirectory because WTP + build process calls git commands. + + WTP build process uses also Marvell mv-ddr-marvell git repository + specified in MV_DDR_PATH option. + + Do not remove any parts of git checkout becuase build process and other + applications need them for correct building and version determination. + +- CRYPTOPP_PATH + + Use this parameter to point to Crypto++ source code + directory. If this option is specified then Crypto++ source code in + CRYPTOPP_PATH directory will be automatically compiled. Crypto++ library + is required for building WTP image tool. Either CRYPTOPP_PATH or + CRYPTOPP_LIBDIR with CRYPTOPP_INCDIR needs to be specified for Armada37x0. + +- CRYPTOPP_LIBDIR + + Use this parameter to point to the directory with + compiled Crypto++ library. By default it points to the CRYPTOPP_PATH. + + On Debian systems it is possible to install system-wide Crypto++ library + via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_LIBDIR + to ``/usr/lib/``. + +- CRYPTOPP_INCDIR + + Use this parameter to point to the directory with + header files of Crypto++ library. By default it points to the CRYPTOPP_PATH. + + On Debian systems it is possible to install system-wide Crypto++ library + via command ``apt install libcrypto++-dev`` and specify CRYPTOPP_INCDIR + to ``/usr/include/crypto++/``. + + +For example, in order to build the image in debug mode with log level up to 'notice' level run + +.. code:: shell + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 PLAT= mrvl_flash + +And if we want to build a Armada37x0 image in debug mode with log level up to 'notice' level, +the image has the preset CPU at 1000 MHz, preset DDR3 at 800 MHz, the DDR topology of DDR4 2CS, +the image boot from SPI NOR flash partition 0, and the image is non trusted in WTP, the command +line is as following + +.. code:: shell + + > make DEBUG=1 USE_COHERENT_MEM=0 LOG_LEVEL=20 CLOCKSPRESET=CPU_1000_DDR_800 \ + MARVELL_SECURE_BOOT=0 DDR_TOPOLOGY=3 BOOTDEV=SPINOR PARTNUM=0 PLAT=a3700 \ + MV_DDR_PATH=/path/to/mv-ddr-marvell/ WTP=/path/to/A3700-utils-marvell/ \ + CRYPTOPP_PATH=/path/to/cryptopp/ BL33=/path/to/u-boot.bin \ + all fip mrvl_bootimage mrvl_flash mrvl_uart + +To build just TF-A without WTMI image (useful for A3720 Turris MOX board), run following command: + +.. code:: shell + + > make USE_COHERENT_MEM=0 PLAT=a3700 CM3_SYSTEM_RESET=1 BL33=/path/to/u-boot.bin \ + CROSS_COMPILE=aarch64-linux-gnu- mrvl_bootimage + +Here is full example how to build production release of Marvell firmware image (concatenated +binary of Marvell's A3720 sys-init, CZ.NIC's Armada 3720 Secure Firmware, TF-A and U-Boot) for +EspressoBin board (PLAT=a3700) with 1GHz CPU (CLOCKSPRESET=CPU_1000_DDR_800) and +1GB DDR4 RAM (DDR_TOPOLOGY=5): + +.. code:: shell + + > git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git + > git clone https://source.denx.de/u-boot/u-boot.git + > git clone https://github.com/weidai11/cryptopp.git + > git clone https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + > git clone https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git + > git clone https://gitlab.nic.cz/turris/mox-boot-builder.git + > make -C u-boot CROSS_COMPILE=aarch64-linux-gnu- mvebu_espressobin-88f3720_defconfig u-boot.bin + > make -C mox-boot-builder CROSS_CM3=arm-linux-gnueabi- wtmi_app.bin + > make -C trusted-firmware-a CROSS_COMPILE=aarch64-linux-gnu- CROSS_CM3=arm-linux-gnueabi- \ + USE_COHERENT_MEM=0 PLAT=a3700 CLOCKSPRESET=CPU_1000_DDR_800 DDR_TOPOLOGY=5 \ + MV_DDR_PATH=$PWD/mv-ddr-marvell/ WTP=$PWD/A3700-utils-marvell/ \ + CRYPTOPP_PATH=$PWD/cryptopp/ BL33=$PWD/u-boot/u-boot.bin \ + WTMI_IMG=$PWD/mox-boot-builder/wtmi_app.bin FIP_ALIGN=0x100 mrvl_flash + +Produced Marvell firmware flash image: ``trusted-firmware-a/build/a3700/release/flash-image.bin`` + +Special Build Flags +-------------------- + +- PLAT_RECOVERY_IMAGE_ENABLE + When set this option to enable secondary recovery function when build atf. + In order to build UART recovery image this operation should be disabled for + A7K/8K/CN913x because of hardware limitation (boot from secondary image + can interrupt UART recovery process). This MACRO definition is set in + ``plat/marvell/armada/a8k/common/include/platform_def.h`` file. + +- DDR32 + In order to work in 32bit DDR, instead of the default 64bit ECC DDR, + this flag should be set to 1. + +For more information about build options, please refer to the +:ref:`Build Options` document. + + +Build output +------------ +Marvell's TF-A compilation generates 8 files: + + - ble.bin - BLe image (not available for Armada37x0) + - bl1.bin - BL1 image + - bl2.bin - BL2 image + - bl31.bin - BL31 image + - fip.bin - FIP image (contains BL2, BL31 & BL33 (U-Boot) images) + - boot-image.bin - TF-A image (contains BL1 and FIP images) + - flash-image.bin - Flashable Marvell firmware image. For Armada37x0 it + contains TIM, WTMI and boot-image.bin images. For other platforms it contains + BLe and boot-image.bin images. Should be placed on the boot flash/device. + - uart-images.tgz.bin - GZIPed TAR archive which contains Armada37x0 images + for booting via UART. Could be loaded via Marvell's WtpDownload tool from + A3700-utils-marvell repository. + +Additional make target ``mrvl_bootimage`` produce ``boot-image.bin`` file. Target +``mrvl_flash`` produce final ``flash-image.bin`` file and target ``mrvl_uart`` +produce ``uart-images.tgz.bin`` file. + + +Tools and external components installation +------------------------------------------ + +Armada37x0 Builds require installation of additional components +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) ARM cross compiler capable of building images for the service CPU (CM3). + This component is usually included in the Linux host packages. + On Debian/Ubuntu hosts the default GNU ARM tool chain can be installed + using the following command + + .. code:: shell + + > sudo apt-get install gcc-arm-linux-gnueabi + + Only if required, the default tool chain prefix ``arm-linux-gnueabi-`` can be + overwritten using the environment variable ``CROSS_CM3``. + Example for BASH shell + + .. code:: shell + + > export CROSS_CM3=/opt/arm-cross/bin/arm-linux-gnueabi + +(2) DDR initialization library sources (mv_ddr) available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + +(3) Armada3700 tools available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/A3700-utils-marvell.git + +(4) Crypto++ library available at the following repository: + + https://github.com/weidai11/cryptopp.git + +(5) Optional CZ.NIC's Armada 3720 Secure Firmware: + + https://gitlab.nic.cz/turris/mox-boot-builder.git + +Armada70x0, Armada80x0 and CN913x Builds require installation of additional components +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +(1) DDR initialization library sources (mv_ddr) available at the following repository + (use the "master" branch): + + https://github.com/MarvellEmbeddedProcessors/mv-ddr-marvell.git + +(2) MSS Management SubSystem Firmware available at the following repository + (use the "binaries-marvell-armada-SDK10.0.1.0" branch): + + https://github.com/MarvellEmbeddedProcessors/binaries-marvell.git diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst new file mode 100644 index 0000000..e88a458 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst @@ -0,0 +1,49 @@ +Address decoding flow and address translation units of Marvell Armada 8K SoC family +=================================================================================== + +:: + + +--------------------------------------------------------------------------------------------------+ + | +-------------+ +--------------+ | + | | Memory +----- DRAM CS | | + |+------------+ +-----------+ +-----------+ | Controller | +--------------+ | + || AP DMA | | | | | +-------------+ | + || SD/eMMC | | CA72 CPUs | | AP MSS | +-------------+ | + || MCI-0/1 | | | | | | Memory | | + |+------+-----+ +--+--------+ +--------+--+ +------------+ | Controller | +-------------+ | + | | | | | +----- Translaton | |AP | | + | | | | | | +-------------+ |Configuration| | + | | | +-----+ +-------------------------Space | | + | | | +-------------+ | CCU | +-------------+ | + | | | | MMU +---------+ Windows | +-----------+ +-------------+ | + | | +-| translation | | Lookup +---- +--------- AP SPI | | + | | +-------------+ | | | | +-------------+ | + | | +-------------+ | | | IO | +-------------+ | + | +------------| SMMU +---------+ | | Windows +--------- AP MCI0/1 | | + | | translation | +------------+ | Lookup | +-------------+ | + | +---------+---+ | | +-------------+ | + | - | | +--------- AP STM | | + | +----------------- | | +-------------+ | + | AP | | +-+---------+ | + +---------------------------------------------------------------|----------------------------------+ + +-------------|-------------------------------------------------|----------------------------------+ + | CP | +-------------+ +------+-----+ +-------------------+ | + | | | | | +------- SB CFG Space | | + | | | DIOB | | | +-------------------+ | + | | | Windows ----------------- IOB | +-------------------+ | + | | | Control | | Windows +------| SB PCIe-0 - PCIe2 | | + | | | | | Lookup | +-------------------+ | + | | +------+------+ | | +-------------------+ | + | | | | +------+ SB NAND | | + | | | +------+-----+ +-------------------+ | + | | | | | + | | | | | + | +------------------+ +------------+ +------+-----+ +-------------------+ | + | | Network Engine | | | | +------- SB SPI-0/SPI-1 | | + | | Security Engine | | PCIe, MSS | | RUNIT | +-------------------+ | + | | SATA, USB | | DMA | | Windows | +-------------------+ | + | | SD/eMMC | | | | Lookup +------- SB Device Bus | | + | | TDM, I2C | | | | | +-------------------+ | + | +------------------+ +------------+ +------------+ | + | | + +--------------------------------------------------------------------------------------------------+ diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst new file mode 100644 index 0000000..d734003 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst @@ -0,0 +1,58 @@ +AMB - AXI MBUS address decoding +=============================== + +AXI to M-bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs. + +The Runit offers a second level of address windows lookup. It is used to map +transaction towards the CD BootROM, SPI0, SPI1 and Device bus (NOR). + +The Runit contains eight configurable windows. Each window defines a contiguous, +address space and the properties associated with that address space. + +:: + + Unit Bank ATTR + Device-Bus DEV_BOOT_CS 0x2F + DEV_CS0 0x3E + DEV_CS1 0x3D + DEV_CS2 0x3B + DEV_CS3 0x37 + SPI-0 SPI_A_CS0 0x1E + SPI_A_CS1 0x5E + SPI_A_CS2 0x9E + SPI_A_CS3 0xDE + SPI_A_CS4 0x1F + SPI_A_CS5 0x5F + SPI_A_CS6 0x9F + SPI_A_CS7 0xDF + SPI SPI_B_CS0 0x1A + SPI_B_CS1 0x5A + SPI_B_CS2 0x9A + SPI_B_CS3 0xDA + BOOT_ROM BOOT_ROM 0x1D + UART UART 0x01 + +Mandatory functions +------------------- + +- marvell_get_amb_memory_map + Returns the AMB windows configuration and the number of windows + +Mandatory structures +-------------------- + +- amb_memory_map + Array that include the configuration of the windows. Every window/entry is a + struct which has 2 parameters: + + - Base address of the window + - Attribute of the window + +Examples +-------- + +.. code:: c + + struct addr_map_win amb_memory_map[] = { + {0xf900, AMB_DEV_CS0_ID}, + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst new file mode 100644 index 0000000..12118e9 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst @@ -0,0 +1,33 @@ +Marvell CCU address decoding bindings +===================================== + +CCU configuration driver (1st stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The CCU node includes a description of the address decoding configuration. + +Mandatory functions +------------------- + +- marvell_get_ccu_memory_map + Return the CCU windows configuration and the number of windows of the + specific AP. + +Mandatory structures +-------------------- + +- ccu_memory_map + Array that includes the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Example +------- + +.. code:: c + + struct addr_map_win ccu_memory_map[] = { + {0x00000000f2000000, 0x00000000e000000, IO_0_TID}, /* IO window */ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst new file mode 100644 index 0000000..7498291 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst @@ -0,0 +1,46 @@ +Marvell IO WIN address decoding bindings +======================================== + +IO Window configuration driver (2nd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IO WIN includes a description of the address decoding configuration. + +Transactions that are decoded by CCU windows as IO peripheral, have an additional +layer of decoding. This additional address decoding layer defines one of the +following targets: + +- **0x0** = BootRom +- **0x1** = STM (Serial Trace Macro-cell, a programmer's port into trace stream) +- **0x2** = SPI direct access +- **0x3** = PCIe registers +- **0x4** = MCI Port +- **0x5** = PCIe port + +Mandatory functions +------------------- + +- marvell_get_io_win_memory_map + Returns the IO windows configuration and the number of windows of the + specific AP. + +Mandatory structures +-------------------- + +- io_win_memory_map + Array that include the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Example +------- + +.. code:: c + + struct addr_map_win io_win_memory_map[] = { + {0x00000000fe000000, 0x000000001f00000, PCIE_PORT_TID}, /* PCIe window 31Mb for PCIe port*/ + {0x00000000ffe00000, 0x000000000100000, PCIE_REGS_TID}, /* PCI-REG window 64Kb for PCIe-reg*/ + {0x00000000f6000000, 0x000000000100000, MCIPHY_TID}, /* MCI window 1Mb for PHY-reg*/ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst new file mode 100644 index 0000000..aa41822 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst @@ -0,0 +1,52 @@ +Marvell IOB address decoding bindings +===================================== + +IO bridge configuration driver (3rd stage address translation) for Marvell Armada 8K and 8K+ SoCs. + +The IOB includes a description of the address decoding configuration. + +IOB supports up to n (in CP110 n=24) windows for external memory transaction. +When a transaction passes through the IOB, its address is compared to each of +the enabled windows. If there is a hit and it passes the security checks, it is +advanced to the target port. + +Mandatory functions +------------------- + +- marvell_get_iob_memory_map + Returns the IOB windows configuration and the number of windows + +Mandatory structures +-------------------- + +- iob_memory_map + Array that includes the configuration of the windows. Every window/entry is + a struct which has 3 parameters: + + - Base address of the window + - Size of the window + - Target-ID of the window + +Target ID options +----------------- + +- **0x0** = Internal configuration space +- **0x1** = MCI0 +- **0x2** = PEX1_X1 +- **0x3** = PEX2_X1 +- **0x4** = PEX0_X4 +- **0x5** = NAND flash +- **0x6** = RUNIT (NOR/SPI/BootRoom) +- **0x7** = MCI1 + +Example +------- + +.. code:: c + + struct addr_map_win iob_memory_map[] = { + {0x00000000f7000000, 0x0000000001000000, PEX1_TID}, /* PEX1_X1 window */ + {0x00000000f8000000, 0x0000000001000000, PEX2_TID}, /* PEX2_X1 window */ + {0x00000000f6000000, 0x0000000001000000, PEX0_TID}, /* PEX0_X4 window */ + {0x00000000f9000000, 0x0000000001000000, NAND_TID} /* NAND window */ + }; diff --git a/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst b/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst new file mode 100644 index 0000000..ba8736d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/armada/porting.rst @@ -0,0 +1,158 @@ +TF-A Porting Guide for Marvell Platforms +======================================== + +This section describes how to port TF-A to a customer board, assuming that the +SoC being used is already supported in TF-A. + + +Source Code Structure +--------------------- + +- The customer platform specific code shall reside under ``plat/marvell/armada//_cust`` + (e.g. 'plat/marvell/armada/a8k/a7040_cust'). +- The platform name for build purposes is called ``_cust`` (e.g. ``a7040_cust``). +- The build system will reuse all files from within the soc directory, and take only the porting + files from the customer platform directory. + +Files that require porting are located at ``plat/marvell/armada//_cust`` directory. + + +Armada-70x0/Armada-80x0 Porting +------------------------------- + +SoC Physical Address Map (marvell_plat_config.c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This file describes the SoC physical memory mapping to be used for the CCU, +IOWIN, AXI-MBUS and IOB address decode units (Refer to the functional spec for +more details). + +In most cases, using the default address decode windows should work OK. + +In cases where a special physical address map is needed (e.g. Special size for +PCIe MEM windows, large memory mapped SPI flash...), then porting of the SoC +memory map is required. + +.. note:: + For a detailed information on how CCU, IOWIN, AXI-MBUS & IOB work, please + refer to the SoC functional spec, and under + ``docs/plat/marvell/armada/misc/mvebu-[ccu/iob/amb/io-win].rst`` files. + +boot loader recovery (marvell_plat_config.c) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Background: + + Boot rom can skip the current image and choose to boot from next position if a + specific value (``0xDEADB002``) is returned by the ble main function. This + feature is used for boot loader recovery by booting from a valid flash-image + saved in next position on flash (e.g. address 2M in SPI flash). + + Supported options to implement the skip request are: + - GPIO + - I2C + - User defined + +- Porting: + + Under marvell_plat_config.c, implement struct skip_image that includes + specific board parameters. + + .. warning:: + To disable this feature make sure the struct skip_image is not implemented. + +- Example: + +In A7040-DB specific implementation +(``plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c``), the image skip is +implemented using GPIO: mpp 33 (SW5). + +Before resetting the board make sure there is a valid image on the next flash +address: + + -tftp [valid address] flash-image.bin + -sf update [valid address] 0x2000000 [size] + +Press reset and keep pressing the button connected to the chosen GPIO pin. A +skip image request message is printed on the screen and boot rom boots from the +saved image at the next position. + +DDR Porting (dram_port.c) +~~~~~~~~~~~~~~~~~~~~~~~~~ + +This file defines the dram topology and parameters of the target board. + +The DDR code is part of the BLE component, which is an extension of ARM Trusted +Firmware (TF-A). + +The DDR driver called mv_ddr is released separately apart from TF-A sources. + +The BLE and consequently, the DDR init code is executed at the early stage of +the boot process. + +Each supported platform of the TF-A has its own DDR porting file called +dram_port.c located at ``atf/plat/marvell/armada/a8k//board`` directory. + +Please refer to '/doc/porting_guide.txt' for detailed +porting description. + +The build target directory is "build//release/ble". + +Comphy Porting (phy-porting-layer.h or phy-default-porting-layer.h) +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Background: + Some of the comphy's parameters value depend on the HW connection between + the SoC and the PHY. Every board type has specific HW characteristics like + wire length. Due to those differences some comphy parameters vary between + board types. Therefore each board type can have its own list of values for + all relevant comphy parameters. The PHY porting layer specifies which + parameters need to be suited and the board designer should provide relevant + values. + + The PHY porting layer simplifies updating static values per board type, + which are now grouped in one place. + + .. note:: + The parameters for the same type of comphy may vary even for the same + board type, it is because the lanes from comphy-x to some PHY may have + different HW characteristic than lanes from comphy-y to the same + (multiplexed) or other PHY. + +- Porting: + The porting layer for PHY was introduced in TF-A. There is one file + ``drivers/marvell/comphy/phy-default-porting-layer.h`` which contains the + defaults. Those default parameters are used only if there is no appropriate + phy-porting-layer.h file under: ``plat/marvell/armada///board/phy-porting-layer.h``. If the phy-porting-layer.h + exists, the phy-default-porting-layer.h is not going to be included. + + .. warning:: + Not all comphy types are already reworked to support the PHY porting + layer, currently the porting layer is supported for XFI/SFI and SATA + comphy types. + + The easiest way to prepare the PHY porting layer for custom board is to copy + existing example to a new platform: + + - cp ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h`` "plat/marvell/armada///board/phy-porting-layer.h" + - adjust relevant parameters or + - if different comphy index is used for specific feature, move it to proper table entry and then adjust. + + .. note:: + The final table size with comphy parameters can be different, depending + on the CP module count for given SoC type. + +- Example: + Example porting layer for armada-8040-db is under: + ``plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h`` + + .. note:: + If there is no PHY porting layer for new platform (missing + phy-porting-layer.h), the default values are used + (drivers/marvell/comphy/phy-default-porting-layer.h) and the user is + warned: + + .. warning:: + "Using default comphy parameters - it may be required to suit them for + your board". diff --git a/arm-trusted-firmware/docs/plat/marvell/index.rst b/arm-trusted-firmware/docs/plat/marvell/index.rst new file mode 100644 index 0000000..0d33432 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/marvell/index.rst @@ -0,0 +1,14 @@ +Marvell +======= + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + armada/build + armada/porting + armada/misc/mvebu-a8k-addr-map + armada/misc/mvebu-amb + armada/misc/mvebu-ccu + armada/misc/mvebu-io-win + armada/misc/mvebu-iob diff --git a/arm-trusted-firmware/docs/plat/meson-axg.rst b/arm-trusted-firmware/docs/plat/meson-axg.rst new file mode 100644 index 0000000..6f6732e --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-axg.rst @@ -0,0 +1,27 @@ +Amlogic Meson A113D (AXG) +=========================== + +The Amlogic Meson A113D is a SoC with a quad core Arm Cortex-A53 running at +~1.2GHz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-none-elf- make DEBUG=1 PLAT=axg [SPD=opteed] + [AML_USE_ATOS=1 when using ATOS as BL32] + +This port has been tested on a A113D board. After building it, follow the +instructions in the `U-Boot repository`_, replacing the mentioned **bl31.img** +by the one built from this port. + +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/s400.rst diff --git a/arm-trusted-firmware/docs/plat/meson-g12a.rst b/arm-trusted-firmware/docs/plat/meson-g12a.rst new file mode 100644 index 0000000..9588ec4 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-g12a.rst @@ -0,0 +1,27 @@ +Amlogic Meson S905X2 (G12A) +=========================== + +The Amlogic Meson S905X2 is a SoC with a quad core Arm Cortex-A53 running at +~1.8GHz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=g12a + +This port has been tested on a SEI510 board. After building it, follow the +instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the +mentioned **bl31.img** by the one built from this port. + +.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README.g12a +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/sei510.rst diff --git a/arm-trusted-firmware/docs/plat/meson-gxbb.rst b/arm-trusted-firmware/docs/plat/meson-gxbb.rst new file mode 100644 index 0000000..dbd83e0 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-gxbb.rst @@ -0,0 +1,26 @@ +Amlogic Meson S905 (GXBB) +========================= + +The Amlogic Meson S905 is a SoC with a quad core Arm Cortex-A53 running at +1.5Ghz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxbb bl31 + +This port has been tested in a ODROID-C2. After building it, follow the +instructions in the `U-Boot repository`_, replacing the mentioned **bl31.bin** +by the one built from this port. + +.. _U-Boot repository: https://gitlab.denx.de/u-boot/u-boot/-/blob/master/board/amlogic/p200/README.odroid-c2 diff --git a/arm-trusted-firmware/docs/plat/meson-gxl.rst b/arm-trusted-firmware/docs/plat/meson-gxl.rst new file mode 100644 index 0000000..0751f1d --- /dev/null +++ b/arm-trusted-firmware/docs/plat/meson-gxl.rst @@ -0,0 +1,27 @@ +Amlogic Meson S905x (GXL) +========================= + +The Amlogic Meson S905x is a SoC with a quad core Arm Cortex-A53 running at +1.5Ghz. It also contains a Cortex-M3 used as SCP. + +This port is a minimal implementation of BL31 capable of booting mainline U-Boot +and Linux: + +- SCPI support. +- Basic PSCI support (CPU_ON, CPU_OFF, SYSTEM_RESET, SYSTEM_OFF). Note that CPU0 + can't be turned off, so there is a workaround to hide this from the caller. +- GICv2 driver set up. +- Basic SIP services (read efuse data, enable/disable JTAG). + +In order to build it: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make DEBUG=1 PLAT=gxl + +This port has been tested on a Lepotato. After building it, follow the +instructions in the `gxlimg repository`_ or `U-Boot repository`_, replacing the +mentioned **bl31.img** by the one built from this port. + +.. _gxlimg repository: https://github.com/repk/gxlimg/blob/master/README +.. _U-Boot repository: https://github.com/u-boot/u-boot/blob/master/doc/board/amlogic/p212.rst diff --git a/arm-trusted-firmware/docs/plat/mt8183.rst b/arm-trusted-firmware/docs/plat/mt8183.rst new file mode 100644 index 0000000..c639be1 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8183.rst @@ -0,0 +1,20 @@ +MediaTek 8183 +============= + +MediaTek 8183 (MT8183) is a 64-bit ARM SoC introduced by MediaTek in early 2018. +The chip incorporates eight cores - four Cortex-A53 little cores and Cortex-A73. +Both clusters can operate at up to 2 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8183 DEBUG=1 diff --git a/arm-trusted-firmware/docs/plat/mt8186.rst b/arm-trusted-firmware/docs/plat/mt8186.rst new file mode 100644 index 0000000..16b833a --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8186.rst @@ -0,0 +1,21 @@ +MediaTek 8186 +============= + +MediaTek 8186 (MT8186) is a 64-bit ARM SoC introduced by MediaTek in 2021. +The chip incorporates eight cores - six Cortex-A55 little cores and two Cortex-A76. +Cortex-A76 can operate at up to 2.05 GHz. +Cortex-A55 can operate at up to 2.0 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8186 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/mt8192.rst b/arm-trusted-firmware/docs/plat/mt8192.rst new file mode 100644 index 0000000..369afcf --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8192.rst @@ -0,0 +1,21 @@ +MediaTek 8192 +============= + +MediaTek 8192 (MT8192) is a 64-bit ARM SoC introduced by MediaTek in 2020. +The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76. +Cortex-A76 can operate at up to 2.2 GHz. +Cortex-A55 can operate at up to 2 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8192 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/mt8195.rst b/arm-trusted-firmware/docs/plat/mt8195.rst new file mode 100644 index 0000000..b2aeea2 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/mt8195.rst @@ -0,0 +1,21 @@ +MediaTek 8195 +============= + +MediaTek 8195 (MT8195) is a 64-bit ARM SoC introduced by MediaTek in 2021. +The chip incorporates eight cores - four Cortex-A55 little cores and Cortex-A76. +Cortex-A76 can operate at up to 2.2 GHz. +Cortex-A55 can operate at up to 2.0 GHz. + +Boot Sequence +------------- + +:: + + Boot Rom --> Coreboot --> TF-A BL31 --> Depthcharge --> Linux Kernel + +How to Build +------------ + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=mt8195 DEBUG=1 COREBOOT=1 diff --git a/arm-trusted-firmware/docs/plat/nvidia-tegra.rst b/arm-trusted-firmware/docs/plat/nvidia-tegra.rst new file mode 100644 index 0000000..99e3bbc --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nvidia-tegra.rst @@ -0,0 +1,148 @@ +NVIDIA Tegra +============ + +- .. rubric:: T194 + :name: t194 + +T194 has eight NVIDIA Carmel CPU cores in a coherent multi-processor +configuration. The Carmel cores support the ARM Architecture version 8.2, +executing both 64-bit AArch64 code, and 32-bit AArch32 code. The Carmel +processors are organized as four dual-core clusters, where each cluster has +a dedicated 2 MiB Level-2 unified cache. A high speed coherency fabric connects +these processor complexes and allows heterogeneous multi-processing with all +eight cores if required. + +- .. rubric:: T186 + :name: t186 + +The NVIDIA® Parker (T186) series system-on-chip (SoC) delivers a heterogeneous +multi-processing (HMP) solution designed to optimize performance and +efficiency. + +T186 has Dual NVIDIA Denver2 ARM® CPU cores, plus Quad ARM Cortex®-A57 cores, +in a coherent multiprocessor configuration. The Denver 2 and Cortex-A57 cores +support ARMv8, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy ARMv7 applications. The Denver 2 processors each have 128 KB +Instruction and 64 KB Data Level 1 caches; and have a 2MB shared Level 2 +unified cache. The Cortex-A57 processors each have 48 KB Instruction and 32 KB +Data Level 1 caches; and also have a 2 MB shared Level 2 unified cache. A +high speed coherency fabric connects these two processor complexes and allows +heterogeneous multi-processing with all six cores if required. + +Denver is NVIDIA's own custom-designed, 64-bit, dual-core CPU which is +fully Armv8-A architecture compatible. Each of the two Denver cores +implements a 7-way superscalar microarchitecture (up to 7 concurrent +micro-ops can be executed per clock), and includes a 128KB 4-way L1 +instruction cache, a 64KB 4-way L1 data cache, and a 2MB 16-way L2 +cache, which services both cores. + +Denver implements an innovative process called Dynamic Code Optimization, +which optimizes frequently used software routines at runtime into dense, +highly tuned microcode-equivalent routines. These are stored in a +dedicated, 128MB main-memory-based optimization cache. After being read +into the instruction cache, the optimized micro-ops are executed, +re-fetched and executed from the instruction cache as long as needed and +capacity allows. + +Effectively, this reduces the need to re-optimize the software routines. +Instead of using hardware to extract the instruction-level parallelism +(ILP) inherent in the code, Denver extracts the ILP once via software +techniques, and then executes those routines repeatedly, thus amortizing +the cost of ILP extraction over the many execution instances. + +Denver also features new low latency power-state transitions, in addition +to extensive power-gating and dynamic voltage and clock scaling based on +workloads. + +- .. rubric:: T210 + :name: t210 + +T210 has Quad Arm® Cortex®-A57 cores in a switched configuration with a +companion set of quad Arm Cortex-A53 cores. The Cortex-A57 and A53 cores +support Armv8-A, executing both 64-bit Aarch64 code, and 32-bit Aarch32 code +including legacy Armv7-A applications. The Cortex-A57 processors each have +48 KB Instruction and 32 KB Data Level 1 caches; and have a 2 MB shared +Level 2 unified cache. The Cortex-A53 processors each have 32 KB Instruction +and 32 KB Data Level 1 caches; and have a 512 KB shared Level 2 unified cache. + +Directory structure +------------------- + +- plat/nvidia/tegra/common - Common code for all Tegra SoCs +- plat/nvidia/tegra/soc/txxx - Chip specific code + +Trusted OS dispatcher +--------------------- + +Tegra supports multiple Trusted OS'. + +- Trusted Little Kernel (TLK): In order to include the 'tlkd' dispatcher in + the image, pass 'SPD=tlkd' on the command line while preparing a bl31 image. +- Trusty: In order to include the 'trusty' dispatcher in the image, pass + 'SPD=trusty' on the command line while preparing a bl31 image. + +This allows other Trusted OS vendors to use the upstream code and include +their dispatchers in the image without changing any makefiles. + +These are the supported Trusted OS' by Tegra platforms. + +- Tegra210: TLK and Trusty +- Tegra186: Trusty +- Tegra194: Trusty + +Scatter files +------------- + +Tegra platforms currently support scatter files and ld.S scripts. The scatter +files help support ARMLINK linker to generate BL31 binaries. For now, there +exists a common scatter file, plat/nvidia/tegra/scat/bl31.scat, for all Tegra +SoCs. The `LINKER` build variable needs to point to the ARMLINK binary for +the scatter file to be used. Tegra platforms have verified BL31 image generation +with ARMCLANG (compilation) and ARMLINK (linking) for the Tegra186 platforms. + +Preparing the BL31 image to run on Tegra SoCs +--------------------------------------------- + +.. code:: shell + + CROSS_COMPILE=/bin/aarch64-none-elf- make PLAT=tegra \ + TARGET_SOC= SPD= + bl31 + +Platforms wanting to use different BL31\_BASE, can add ``PLAT_BL31_BASE=`` +to the build command line. + +The Tegra platform code expects a pointer to the following platform specific +structure via 'x1' register from the BL2 layer which is used by the +bl31\_early\_platform\_setup() handler to extract the TZDRAM carveout base and +size for loading the Trusted OS and the UART port ID to be used. The Tegra +memory controller driver programs this base/size in order to restrict NS +accesses. + +typedef struct plat\_params\_from\_bl2 { +/\* TZ memory size */ +uint64\_t tzdram\_size; +/* TZ memory base */ +uint64\_t tzdram\_base; +/* UART port ID \*/ +int uart\_id; +/* L2 ECC parity protection disable flag \*/ +int l2\_ecc\_parity\_prot\_dis; +/* SHMEM base address for storing the boot logs \*/ +uint64\_t boot\_profiler\_shmem\_base; +} plat\_params\_from\_bl2\_t; + +Power Management +---------------- + +The PSCI implementation expects each platform to expose the 'power state' +parameter to be used during the 'SYSTEM SUSPEND' call. The state-id field +is implementation defined on Tegra SoCs and is preferably defined by +tegra\_def.h. + +Tegra configs +------------- + +- 'tegra\_enable\_l2\_ecc\_parity\_prot': This flag enables the L2 ECC and Parity + Protection bit, for Arm Cortex-A57 CPUs, during CPU boot. This flag will + be enabled by Tegrs SoCs during 'Cluster power up' or 'System Suspend' exit. diff --git a/arm-trusted-firmware/docs/plat/nxp/index.rst b/arm-trusted-firmware/docs/plat/nxp/index.rst new file mode 100644 index 0000000..8546887 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/index.rst @@ -0,0 +1,17 @@ +NXP Reference Development Platforms +=================================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + + nxp-layerscape + nxp-ls-fuse-prov + nxp-ls-tbbr + +This chapter holds documentation related to NXP reference development platforms. +It includes details on image flashing, fuse provisioning and trusted board boot-up. + +-------------- + +*Copyright (c) 2021, NXP Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst new file mode 100644 index 0000000..cd5874b --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst @@ -0,0 +1,473 @@ +NXP SoCs - Overview +===================== +.. section-numbering:: + :suffix: . + +The QorIQ family of ARM based SoCs that are supported on TF-A are: + +1. LX2160A + +- SoC Overview: + +The LX2160A multicore processor, the highest-performance member of the +Layerscape family, combines FinFET process technology's low power and +sixteen Arm® Cortex®-A72 cores with datapath acceleration optimized for +L2/3 packet processing, together with security offload, robust traffic +management and quality of service. + +Details about LX2160A can be found at `lx2160a`_. + +- LX2160ARDB Board: + +The LX2160A reference design board provides a comprehensive platform +that enables design and evaluation of the LX2160A or LX2162A processors. It +comes preloaded with a board support package (BSP) based on a standard Linux +kernel. + +Board details can be fetched from the link: `lx2160ardb`_. + +2. LS1028A + +- SoC Overview: + +The Layerscape LS1028A applications processor for industrial and +automotive includes a time-sensitive networking (TSN) -enabled Ethernet +switch and Ethernet controllers to support converged IT and OT networks. +Two powerful 64-bit Arm®v8 cores support real-time processing for +industrial control and virtual machines for edge computing in the IoT. +The integrated GPU and LCD controller enable Human-Machine Interface +(HMI) systems with next-generation interfaces. + +Details about LS1028A can be found at `ls1028a`_. + +- LS1028ARDB Board: + +The LS1028A reference design board (RDB) is a computing, evaluation, +and development platform that supports industrial IoT applications, human +machine interface solutions, and industrial networking. + +Details about LS1028A RDB board can be found at `ls1028ardb`_. + +3. LS1043A + +- SoC Overview: + +The Layerscape LS1043A processor is NXP's first quad-core, 64-bit Arm®-based +processor for embedded networking. The LS1023A (two core version) and the +LS1043A (four core version) deliver greater than 10 Gbps of performance +in a flexible I/O package supporting fanless designs. This SoC is a +purpose-built solution for small-form-factor networking and industrial +applications with BOM optimizations for economic low layer PCB, lower cost +power supply and single clock design. The new 0.9V versions of the LS1043A +and LS1023A deliver addition power savings for applications such as Wireless +LAN and to Power over Ethernet systems. + +Details about LS1043A can be found at `ls1043a`_. + +- LS1043ARDB Board: + +The LS1043A reference design board (RDB) is a computing, evaluation, and +development platform that supports the Layerscape LS1043A architecture +processor. The LS1043A-RDB can help shorten your time to market by providing +the following features: + +Memory subsystem: + * 2GByte DDR4 SDRAM (32bit bus) + * 128 Mbyte NOR flash single-chip memory + * 512 Mbyte NAND flash + * 16 Mbyte high-speed SPI flash + * SD connector to interface with the SD memory card + +Ethernet: + * XFI 10G port + * QSGMII with 4x 1G ports + * Two RGMII ports + +PCIe: + * PCIe2 (Lanes C) to mini-PCIe slot + * PCIe3 (Lanes D) to PCIe slot + +USB 3.0: two super speed USB 3.0 type A ports + +UART: supports two UARTs up to 115200 bps for console + +Details about LS1043A RDB board can be found at `ls1043ardb`_. + +4. LS1046A + +- SoC Overview: + +The LS1046A is a cost-effective, power-efficient, and highly integrated +system-on-chip (SoC) design that extends the reach of the NXP value-performance +line of QorIQ communications processors. Featuring power-efficient 64-bit +Arm Cortex-A72 cores with ECC-protected L1 and L2 cache memories for high +reliability, running up to 1.8 GHz. + +Details about LS1046A can be found at `ls1046a`_. + +- LS1046ARDB Board: + +The LS1046A reference design board (RDB) is a high-performance computing, +evaluation, and development platform that supports the Layerscape LS1046A +architecture processor. The LS1046ARDB board supports the Layerscape LS1046A +processor and is optimized to support the DDR4 memory and a full complement +of high-speed SerDes ports. + +Details about LS1046A RDB board can be found at `ls1046ardb`_. + +- LS1046AFRWY Board: + +The LS1046A Freeway board (FRWY) is a high-performance computing, evaluation, +and development platform that supports the LS1046A architecture processor +capable of support more than 32,000 CoreMark performance. The FRWY-LS1046A +board supports the LS1046A processor, onboard DDR4 memory, multiple Gigabit +Ethernet, USB3.0 and M2_Type_E interfaces for Wi-Fi, FRWY-LS1046A-AC includes +the Wi-Fi card. + +Details about LS1046A FRWY board can be found at `ls1046afrwy`_. + +5. LS1088A + +- SoC Overview: + +The LS1088A family of multicore communications processors combines up to and eight +Arm Cortex-A53 cores with the advanced, high-performance data path and network +peripheral interfaces required for wireless access points, networking infrastructure, +intelligent edge access, including virtual customer premise equipment (vCPE) and +high-performance industrial applications. + +Details about LS1088A can be found at `ls1088a`_. + +- LS1088ARDB Board: + +The LS1088A reference design board provides a comprehensive platform that +enables design and evaluation of the product (LS1088A processor). This RDB +comes pre-loaded with a board support package (BSP) based on a standard +Linux kernel. + +Details about LS1088A RDB board can be found at `ls1088ardb`_. + +Table of supported boot-modes by each platform & platform that needs FIP-DDR: +----------------------------------------------------------------------------- + ++---------------------+---------------------------------------------------------------------+-----------------+ +| | BOOT_MODE | | +| PLAT +-------+--------+-------+-------+-------+-------------+--------------+ fip_ddr_needed | +| | sd | qspi | nor | nand | emmc | flexspi_nor | flexspi_nand | | ++=====================+=======+========+=======+=======+=======+=============+==============+=================+ +| lx2160ardb | yes | | | | yes | yes | | yes | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1028ardb | yes | | | | yes | yes | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1043ardb | yes | | yes | yes | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1046ardb | yes | yes | | | yes | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1046afrwy | yes | yes | | | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ +| ls1088ardb | yes | yes | | | | | | no | ++---------------------+-------+--------+-------+-------+-------+-------------+--------------+-----------------+ + + +Boot Sequence +------------- +:: + ++ Secure World | Normal World ++ EL0 | ++ | ++ EL1 BL32(Tee OS) | kernel ++ ^ | | ^ ++ | | | | ++ EL2 | | | BL33(u-boot) ++ | | | ^ ++ | v | / ++ EL3 BootROM --> BL2 --> BL31 ---------------/ ++ + +Boot Sequence with FIP-DDR +-------------------------- +:: + ++ Secure World | Normal World ++ EL0 | ++ | ++ EL1 fip-ddr BL32(Tee OS) | kernel ++ ^ | ^ | | ^ ++ | | | | | | ++ EL2 | | | | | BL33(u-boot) ++ | | | | | ^ ++ | v | v | / ++ EL3 BootROM --> BL2 -----> BL31 ---------------/ ++ + +DDR Memory Layout +-------------------------- + +NXP Platforms divide DRAM into banks: + +- DRAM0 Bank: Maximum size of this bank is fixed to 2GB, DRAM0 size is defined in platform_def.h if it is less than 2GB. + +- DRAM1 ~ DRAMn Bank: Greater than 2GB belongs to DRAM1 and following banks, and size of DRAMn Bank varies for one platform to others. + +The following diagram is default DRAM0 memory layout in which secure memory is at top of DRAM0. + +:: + + high +---------------------------------------------+ + | | + | Secure EL1 Payload Shared Memory (2 MB) | + | | + +---------------------------------------------+ + | | + | Secure Memory (64 MB) | + | | + +---------------------------------------------+ + | | + | Non Secure Memory | + | | + low +---------------------------------------------+ + +How to build +============= + +Code Locations +-------------- + +- OP-TEE: + `link `__ + +- U-Boot: + `link `__ + +- RCW: + `link `__ + +- ddr-phy-binary: Required by platforms that need fip-ddr. + `link `__ + +- cst: Required for TBBR. + `link `__ + +Build Procedure +--------------- + +- Fetch all the above repositories into local host. + +- Prepare AARCH64 toolchain and set the environment variable "CROSS_COMPILE". + + .. code:: shell + + export CROSS_COMPILE=.../bin/aarch64-linux-gnu- + +- Build RCW. Refer README from the respective cloned folder for more details. + +- Build u-boot and OPTee firstly, and get binary images: u-boot.bin and tee.bin. + For u-boot you can use the _tfa_defconfig for build. + +- Copy/clone the repo "ddr-phy-binary" to the tfa directory for platform needing ddr-fip. + +- Below are the steps to build TF-A images for the supported platforms. + +Compilation steps without BL32 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BUILD BL2: + +-To compile + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + pbl + +BUILD FIP: + + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Compilation steps with BL32 +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +BUILD BL2: + +-To compile + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + pbl + +BUILD FIP: + + .. code:: shell + + make PLAT=$PLAT \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + + +BUILD fip-ddr (Mandatory for certain platforms, refer table above): +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +-To compile additional fip-ddr for selected platforms(Refer above table if the platform needs fip-ddr). + .. code:: shell + + make PLAT= fip-ddr + + +Deploy ATF Images +================= + +Note: The size in the standard uboot commands for copy to nor, qspi, nand or sd +should be modified based on the binary size of the image to be copied. + +- Deploy ATF images on flexspi-Nor or QSPI flash Alt Bank from U-Boot prompt. + + -- Commands to flash images for bl2_xxx.pbl and fip.bin + + Notes: ls1028ardb has no flexspi-Nor Alt Bank, so use "sf probe 0:0" for current bank. + + .. code:: shell + + tftp 82000000 $path/bl2_xxx.pbl; + + i2c mw 66 50 20;sf probe 0:1; sf erase 0 +$filesize; sf write 0x82000000 0x0 $filesize; + + tftp 82000000 $path/fip.bin; + i2c mw 66 50 20;sf probe 0:1; sf erase 0x100000 +$filesize; sf write 0x82000000 0x100000 $filesize; + + -- Next step is valid for platform where FIP-DDR is needed. + + .. code:: shell + + tftp 82000000 $path/ddr_fip.bin; + i2c mw 66 50 20;sf probe 0:1; sf erase 0x800000 +$filesize; sf write 0x82000000 0x800000 $filesize; + + -- Then reset to alternate bank to boot up ATF. + + Command for lx2160a, ls1088a and ls1028a platforms: + + .. code:: shell + + qixisreset altbank; + + Command for ls1046a platforms: + + .. code:: shell + + cpld reset altbank; + +- Deploy ATF images on SD/eMMC from U-Boot prompt. + -- file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512) + + .. code:: shell + + mmc dev ; (idx = 1 for eMMC; idx = 0 for SD) + + tftp 82000000 $path/bl2__or_.pbl; + mmc write 82000000 8 ; + + tftp 82000000 $path/fip.bin; + mmc write 82000000 0x800 ; + + -- Next step is valid for platform that needs FIP-DDR. + + .. code:: shell + + tftp 82000000 $path/ddr_fip.bin; + mmc write 82000000 0x4000 ; + + -- Then reset to sd/emmc to boot up ATF from sd/emmc as boot-source. + + Command for lx2160A, ls1088a and ls1028a platforms: + + .. code:: shell + + qixisreset ; + + Command for ls1043a and ls1046a platform: + + .. code:: shell + + cpld reset ; + +- Deploy ATF images on IFC nor flash from U-Boot prompt. + + .. code:: shell + + tftp 82000000 $path/bl2_nor.pbl; + protect off 64000000 +$filesize; erase 64000000 +$filesize; cp.b 82000000 64000000 $filesize; + + tftp 82000000 $path/fip.bin; + protect off 64100000 +$filesize; erase 64100000 +$filesize; cp.b 82000000 64100000 $filesize; + + -- Then reset to alternate bank to boot up ATF. + + Command for ls1043a platform: + + .. code:: shell + + cpld reset altbank; + +- Deploy ATF images on IFC nand flash from U-Boot prompt. + + .. code:: shell + + tftp 82000000 $path/bl2_nand.pbl; + nand erase 0x0 $filesize; nand write 82000000 0x0 $filesize; + + tftp 82000000 $path/fip.bin; + nand erase 0x100000 $filesize;nand write 82000000 0x100000 $filesize; + + -- Then reset to nand flash to boot up ATF. + + Command for ls1043a platform: + + .. code:: shell + + cpld reset nand; + + + +Trusted Board Boot: +=================== + +For TBBR, the binary name changes: + ++-------------+--------------------------+---------+-------------------+ +| Boot Type | BL2 | FIP | FIP-DDR | ++=============+==========================+=========+===================+ +| Normal Boot | bl2_.pbl | fip.bin | ddr_fip.bin | ++-------------+--------------------------+---------+-------------------+ +| TBBR Boot | bl2__sec.pbl | fip.bin | ddr_fip_sec.bin | ++-------------+--------------------------+---------+-------------------+ + +Refer `nxp-ls-tbbr.rst`_ for detailed user steps. + + +.. _lx2160a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-lx2160a-lx2120a-lx2080a-processors:LX2160A +.. _lx2160ardb: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-communication-process/layerscape-lx2160a-multicore-communications-processor:LX2160A +.. _ls1028a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1028a-applications-processor:LS1028A +.. _ls1028ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1028a-reference-design-board:LS1028ARDB +.. _ls1043a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1043a-and-1023a-processors:LS1043A +.. _ls1043ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1043a-reference-design-board:LS1043A-RDB +.. _ls1046a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1046a-and-1026a-processors:LS1046A +.. _ls1046ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1046a-reference-design-board:LS1046A-RDB +.. _ls1046afrwy: https://www.nxp.com/design/qoriq-developer-resources/ls1046a-freeway-board:FRWY-LS1046A +.. _ls1088a: https://www.nxp.com/products/processors-and-microcontrollers/arm-processors/layerscape-processors/layerscape-1088a-and-1048a-processor:LS1088A +.. _ls1088ardb: https://www.nxp.com/design/qoriq-developer-resources/layerscape-ls1088a-reference-design-board:LS1088A-RDB +.. _nxp-ls-tbbr.rst: ./nxp-ls-tbbr.rst diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst new file mode 100644 index 0000000..64e1c6f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst @@ -0,0 +1,271 @@ + +Steps to blow fuses on NXP LS SoC: +================================== + + +- Enable POVDD + -- Refer board GSG(Getting Started Guide) for the steps to enable POVDD. + -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk. + ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| | Platform | Jumper | Switch | LED to Verify | Through GPIO Pin (=number) | ++===+=================+===========+============+=================+=============================+ +| 1.| lx2160ardb | J9 | | | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| 2.| lx2160aqds | J35 | | | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ +| 3.| lx2162aqds | J35 | SW9[4] = 1 | D15 | no | ++---+-----------------+-----------+------------+-----------------+-----------------------------+ + +- SFP registers to be written to: + ++---+----------------------------------+----------------------+----------------------+ +| | Platform | OTPMKR0..OTPMKR7 | SRKHR0..SRKHR7 | ++===+==================================+======================+======================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x1e80234..0x1e80250 | 0x1e80254..0x1e80270 | ++---+----------------------------------+----------------------+----------------------+ + +- At U-Boot prompt, verify that SNVS register - HPSR, whether OTPMK was written, already: + ++---+----------------------------------+-------------------------------------------+---------------+ +| | Platform | OTPMK_ZERO_BIT(=value) | SNVS_HPSR_REG | ++===+==================================+===========================================+===============+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 27 (= 1 means not blown, =0 means blown) | 0x01E90014 | ++---+----------------------------------+-------------------------------------------+---------------+ + +From u-boot prompt: + + -- Check for the OTPMK. + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 88000900 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 88000900 + + Note: OTPMK_ZERO_BIT is 1, indicating that the OTPMK is not blown. + + -- Check for the SRK Hash. + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: 00000000 00000000 00000000 00000000 ................ + 01e80264: 00000000 00000000 00000000 00000000 ................ + + Note: Zero means that SRK hash is not blown. + +- If not blown, then from the U-Boot prompt, using following commands: + -- Provision the OTPMK. + + .. code:: shell + + mw.l $OTPMKR0 + mw.l $OTPMKR1 + mw.l $OTPMKR2 + mw.l $OTPMKR3 + mw.l $OTPMKR4 + mw.l $OTPMKR5 + mw.l $OTPMKR6 + mw.l $OTPMKR7 + + -- Provision the SRK Hash. + + .. code:: shell + + mw.l $SRKHR0 + mw.l $SRKHR1 + mw.l $SRKHR2 + mw.l $SRKHR3 + mw.l $SRKHR4 + mw.l $SRKHR5 + mw.l $SRKHR6 + mw.l $SRKHR7 + + Note: SRK Hash should be carefully written keeping in mind the SFP Block Endianness. + +- At U-Boot prompt, verify that SNVS registers for OTPMK are correctly written: + + -- Check for the OTPMK. + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 80000900 + + OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown. + + Note: In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + + .. code:: shell + + md $OTPMKR0 0x10 + + Command Output: + 01e80234: ffffffff ffffffff ffffffff ffffffff ................ + 01e80244: ffffffff ffffffff ffffffff ffffffff ................ + + Note: OTPMK will never be visible in plain. + + -- Check for the SRK Hash. For example, if following SRK hash is written: + + SFP SRKHR0 = fdc2fed4 + SFP SRKHR1 = 317f569e + SFP SRKHR2 = 1828425c + SFP SRKHR3 = e87b5cfd + SFP SRKHR4 = 34beab8f + SFP SRKHR5 = df792a70 + SFP SRKHR6 = 2dff85e1 + SFP SRKHR7 = 32a29687, + + then following would be the value on dumping SRK hash. + + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\. + 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2... + + Note: SRK Hash is visible in plain based on the SFP Block Endianness. + +- Caution: Donot proceed to the next step, until you are sure that OTPMK and SRKH are correctly blown from above steps. + -- After the next step, there is no turning back. + -- Fuses will be burnt, which cannot be undo. + +- Write SFP_INGR[INST] with the PROGFB(0x2) instruction to blow the fuses. + -- User need to save the SRK key pair and OTPMK Key forever, to continue using this board. + ++---+----------------------------------+-------------------------------------------+-----------+ +| | Platform | SFP_INGR_REG | SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE | ++===+==================================+=======================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | 0x01E80020 | 0x2 | ++---+----------------------------------+--------------+----------------------------------------+ + + .. code:: shell + + md $SFP_INGR_REG $SFP_WRITE_DATE_FRM_MIRROR_REG_TO_FUSE + +- On reset, if the SFP register were read from u-boot, it will show the following: + -- Check for the OTPMK. + + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 01e90014: 80000900 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 80000900 + + Note: OTPMK_ZERO_BIT is zero, indicating that the OTPMK is blown. + + .. code:: shell + + md $OTPMKR0 0x10 + + Command Output: + 01e80234: ffffffff ffffffff ffffffff ffffffff ................ + 01e80244: ffffffff ffffffff ffffffff ffffffff ................ + + Note: OTPMK will never be visible in plain. + + -- SRK Hash + + .. code:: shell + + md $SRKHR0 0x10 + + Command Output: + 01e80254: d4fec2fd 9e567f31 5c422818 fd5c7be8 ....1.V..(B\.{\. + 01e80264: 8fabbe34 702a79df e185ff2d 8796a232 4....y*p-...2... + + Note: SRK Hash is visible in plain based on the SFP Block Endianness. + +Second method to do the fuse provsioning: +========================================= + +This method is used for quick way to provision fuses. +Typically used by those who needs to provision number of boards. + +- Enable POVDD: + -- Refer the table above to enable POVDD. + + Note: If GPIO Pin supports enabling POVDD, it can be done through the below input_fuse_file. + + -- Once the POVDD is enabled, make sure to set variable POVDD_ENABLE := yes, in the platform.mk. + +- User need to populate the "input_fuse_file", corresponding to the platform for: + + -- OTPMK + -- SRKH + + Table of fuse provisioning input file for every supported platform: + ++---+----------------------------------+-----------------------------------------------------------------+ +| | Platform | FUSE_PROV_FILE | ++===+==================================+=================================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | ${CST_DIR}/input_files/gen_fusescr/ls2088_1088/input_fuse_file | ++---+----------------------------------+--------------+--------------------------------------------------+ + +- Create the TF-A binary with FUSE_PROG=1. + + .. code:: shell + + make PLAT=$PLAT FUSE_PROG=1\ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip \ + fip_fuse \ + FUSE_PROV_FILE=../../apps/security/cst/input_files/gen_fusescr/ls2088_1088/input_fuse_file + +- Deployment: + -- Refer the nxp-layerscape.rst for deploying TF-A images. + -- Deploying fip_fuse.bin: + + For Flexspi-Nor: + + .. code:: shell + + tftp 82000000 $path/fuse_fip.bin; + i2c mw 66 50 20;sf probe 0:0; sf erase 0x880000 +$filesize; sf write 0x82000000 0x880000 $filesize; + + For SD or eMMC [file_size_in_block_sizeof_512 = (Size_of_bytes_tftp / 512)]: + + .. code:: shell + + tftp 82000000 $path/fuse_fip.bin; + mmc write 82000000 0x4408 ; + +- Valiation: + ++---+----------------------------------+---------------------------------------------------+ +| | Platform | Error_Register | Error_Register_Address | ++===+==================================+===================================================+ +| 1.| lx2160ardb/lx2160aqds/lx2162aqds | DCFG scratch 4 register | 0x01EE020C | ++---+----------------------------------+---------------------------------------------------+ + + At the U-Boot prompt, check DCFG scratch 4 register for any error. + + .. code:: shell + + md $Error_Register_Address 1 + + Command Ouput: + 01ee020c: 00000000 + + Note: + - 0x00000000 shows no error, then fuse provisioning is successful. + - For non-zero value, refer the code header file ".../drivers/nxp/sfp/sfp_error_codes.h" diff --git a/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst new file mode 100644 index 0000000..43e15f7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst @@ -0,0 +1,210 @@ + +-------------- +NXP Platforms: +-------------- +TRUSTED_BOARD_BOOT option can be enabled by specifying TRUSTED_BOARD_BOOT=1 on command line during make. + + + +Bare-Minimum Preparation to run TBBR on NXP Platforms: +======================================================= +- OTPMK(One Time Programable Key) needs to be burnt in fuses. + -- It is the 256 bit key that stores a secret value used by the NXP SEC 4.0 IP in Trusted or Secure mode. + + Note: It is primarily for the purpose of decrypting additional secrets stored in system non-volatile memory. + + -- NXP CST tool gives an option to generate it. + + Use the below command from directory 'cst', with correct options. + + .. code:: shell + + ./gen_otpmk_drbg + +- SRKH (Super Root Key Hash) needs to be burnt in fuses. + -- It is the 256 bit hash of the list of the public keys of the SRK key pair. + -- NXP CST tool gives an option to generate the RSA key pair and its hash. + + Use the below command from directory 'cst', with correct options. + + .. code:: shell + + ./gen_keys + +Refer fuse frovisioning readme 'nxp-ls-fuse-prov.rst' for steps to blow these keys. + + + +Two options are provided for TRUSTED_BOARD_BOOT: +================================================ + +------------------------------------------------------------------------- +Option 1: CoT using X 509 certificates +------------------------------------------------------------------------- + +- This CoT is as provided by ARM. + +- To use this option user needs to specify mbedtld dir path in MBEDTLS_DIR. + +- To generate CSF header, path of CST repository needs to be specified as CST_DIR + +- CSF header is embedded to each of the BL2 image. + +- GENERATE_COT=1 adds the tool 'cert_create' to the build environment to generate: + -- X509 Certificates as (.crt) files. + -- X509 Pem key file as (.pem) files. + +- SAVE_KEYS=1 saves the keys and certificates, if GENERATE_COT=1. + -- For this to work, file name for cert and keys are provided as part of compilation or build command. + + --- default file names will be used, incase not provided as part compilation or build command. + --- default folder 'BUILD_PLAT' will be used to store them. + +- ROTPK for x.509 certificates is generated and embedded in bl2.bin and + verified as part of CoT by Boot ROM during secure boot. + +- Compilation steps: + +All Images + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Additional FIP_DDR Image (For NXP platforms like lx2160a) + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR=$MBEDTLS_PATH fip_ddr + + Note: make target 'fip_ddr' should never be combine with other make target 'fip', 'pbl' & 'bl2'. + +------------------------------------------------------------------------- +Option 2: CoT using NXP CSF headers. +------------------------------------------------------------------------- + +- This option is automatically selected when TRUSTED_BOARD_BOOT is set but MBEDTLS_DIR path is not specified. + +- CSF header is embedded to each of the BL31, BL32 and BL33 image. + +- To generate CSF header, path of CST repository needs to be specified as CST_DIR + +- Default input files for CSF header generation is added in this repo. + +- Default input file requires user to generate RSA key pair named + -- srk.pri, and + -- srk.pub, and add them in ATF repo. + -- These keys can be generated using gen_keys tool of CST. + +- To change the input file , user can use the options BL33_INPUT_FILE, BL32_INPUT_FILE, BL31_INPUT_FILE + +- There are 2 paths in secure boot flow : + -- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0) + + --- In this flow , even on ROTPK comparison failure, flow would continue. + --- However SNVS is transitioned to non-secure state + + -- Production mode (SFP->OSPR, ITS = 1) + + --- Any failure is fatal failure + +- Compilation steps: + +All Images + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + pbl \ + fip + +Additional FIP_DDR Image (For NXP platforms like lx2160a) + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH fip_ddr + +- Compilation Steps with build option for generic image processing filters to prepend CSF header: + -- Generic image processing filters to prepend CSF header + + BL32_INPUT_FILE = < file name> + BL33_INPUT_FILE = + + .. code:: shell + + make PLAT=$PLAT TRUSTED_BOARD_BOOT=1 CST_DIR=$CST_DIR_PATH \ + BOOT_MODE= \ + RCW=$RCW_BIN \ + BL32=$TEE_BIN SPD=opteed\ + BL33=$UBOOT_SECURE_BIN \ + BL33_INPUT_FILE = \ + BL32_INPUT_FILE = \ + BL31_INPUT_FILE = \ + pbl \ + fip + + +Deploy ATF Images +================= +Same steps as mentioned in the readme "nxp-layerscape.rst". + + + +Verification to check if Secure state is achieved: +================================================== + ++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+ +| | Platform | SNVS_HPSR_REG | SYS_SECURE_BIT(=value) | SYSTEM_SECURE_CONFIG_BIT(=value) | SSM_STATE | ++===+================+=================+========================+==================================+===============================+ +| 1.| lx2160ardb or | 0x01E90014 | 15 | 14-12 | 11-8 | +| | lx2160aqds or | | ( = 1, BootROM Booted) | ( = 010 means Intent to Secure, | (=1111 means secure boot) | +| | lx2162aqds | | | ( = 000 Unsecure) | (=1011 means Non-secure Boot) | ++---+----------------+-----------------+------------------------+----------------------------------+-------------------------------+ + +- Production mode (SFP->OSPR, ITS = 1) + -- Linux prompt will successfully come. if the TBBR is successful. + + --- Else, Linux boot will be successful. + + -- For secure-boot status, read SNVS Register $SNVS_HPSR_REG from u-boot prompt: + + .. code:: shell + + md $SNVS_HPSR_REG + + Command Output: + 1e90014: 8000AF00 + + In case it is read as 00000000, then read this register using jtag (in development mode only through CW tap). + +0 +4 +8 +C + [0x01E90014] 8000AF00 + + +- Development Mode (sb_en in RCW = 1, SFP->OSPR, ITS = 0) + -- Refer the SoC specific table to read the register to interpret whether the secure boot is achieved or not. + -- Using JTAG (in development environment only, using CW tap): + + --- For secure-boot status, read SNVS Register $SNVS_HPSR_REG + + .. code:: shell + + ccs::display_regs 86 0x01E90014 4 0 1 + + Command Output: + Using the SAP chain position number 86, following is the output. + + +0 +4 +8 +C + [0x01E90014] 8000AF00 + + Note: Chain position number will vary from one SoC to other SoC. + +- Interpretation of the value: + + -- 0xA indicates BootROM booted, with intent to secure. + -- 0xF = secure boot, as SSM_STATE. diff --git a/arm-trusted-firmware/docs/plat/poplar.rst b/arm-trusted-firmware/docs/plat/poplar.rst new file mode 100644 index 0000000..215f551 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/poplar.rst @@ -0,0 +1,176 @@ +Poplar +====== + +Poplar is the first development board compliant with the 96Boards Enterprise +Edition TV Platform specification. + +The board features the Hi3798C V200 with an integrated quad-core 64-bit +Arm Cortex A53 processor and high performance Mali T720 GPU, making it capable +of running any commercial set-top solution based on Linux or Android. + +It supports a premium user experience with up to H.265 HEVC decoding of 4K +video at 60 frames per second. + +:: + + SOC Hisilicon Hi3798CV200 + CPU Quad-core Arm Cortex-A53 64 bit + DRAM DDR3/3L/4 SDRAM interface, maximum 32-bit data width 2 GB + USB Two USB 2.0 ports One USB 3.0 ports + CONSOLE USB-micro port for console support + ETHERNET 1 GBe Ethernet + PCIE One PCIe 2.0 interfaces + JTAG 8-Pin JTAG + EXPANSION INTERFACE Linaro 96Boards Low Speed Expansion slot + DIMENSION Standard 160×120 mm 96Boards Enterprice Edition form factor + WIFI 802.11AC 2*2 with Bluetooth + CONNECTORS One connector for Smart Card One connector for TSI + +At the start of the boot sequence, the bootROM executes the so called l-loader +binary whose main role is to change the processor state to 64bit mode. This +must happen prior to invoking Trusted Firmware-A: + +:: + + l-loader --> Trusted Firmware-A --> u-boot + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- l-loader: + `link `__ + +- u-boot: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +- Fetch all the above 3 repositories into local host. + Make all the repositories in the same ${BUILD\_PATH}. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using poplar_defconfig + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- poplar_defconfig + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build atf providing the previously generated u-boot.bin as the BL33 image + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- all fip SPD=none PLAT=poplar + BL33=u-boot.bin + +- Build l-loader (generated the final fastboot.bin) + 1. copy the atf generated files fip.bin and bl1.bin to l-loader/atf/ + 2. export ARM_TRUSTED_FIRMWARE=${ATF_SOURCE_PATH) + 3. make + +Install Procedure +----------------- + +- Copy l-loader/fastboot.bin to a FAT partition on a USB pen drive. + +- Plug the USB pen drive to any of the USB2 ports + +- Power the board while keeping S3 pressed (usb_boot) + +The system will boot into a u-boot shell which you can then use to write the +working firmware to eMMC. + +Boot trace +---------- + +:: + + Bootrom start + Boot Media: eMMC + Decrypt auxiliary code ...OK + + lsadc voltage min: 000000FE, max: 000000FF, aver: 000000FE, index: 00000000 + + Entry boot auxiliary code + + Auxiliary code - v1.00 + DDR code - V1.1.2 20160205 + Build: Mar 24 2016 - 17:09:44 + Reg Version: v134 + Reg Time: 2016/03/18 09:44:55 + Reg Name: hi3798cv2dmb_hi3798cv200_ddr3_2gbyte_8bitx4_4layers.reg + + Boot auxiliary code success + Bootrom success + + LOADER: Switched to aarch64 mode + LOADER: Entering ARM TRUSTED FIRMWARE + LOADER: CPU0 executes at 0x000ce000 + + INFO: BL1: 0xe1000 - 0xe7000 [size = 24576] + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL1: Built : 17:51:33, Apr 30 2017 + INFO: BL1: RAM 0xe1000 - 0xe7000 + INFO: BL1: Loading BL2 + INFO: Loading image id=1 at address 0xe9000 + INFO: Image id=1 loaded at address 0xe9000, size = 0x5008 + NOTICE: BL1: Booting BL2 + INFO: Entry point address = 0xe9000 + INFO: SPSR = 0x3c5 + NOTICE: BL2: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL2: Built : 17:51:33, Apr 30 2017 + INFO: BL2: Loading BL31 + INFO: Loading image id=3 at address 0x129000 + INFO: Image id=3 loaded at address 0x129000, size = 0x8038 + INFO: BL2: Loading BL33 + INFO: Loading image id=5 at address 0x37000000 + INFO: Image id=5 loaded at address 0x37000000, size = 0x58f17 + NOTICE: BL1: Booting BL31 + INFO: Entry point address = 0x129000 + INFO: SPSR = 0x3cd + INFO: Boot bl33 from 0x37000000 for 364311 Bytes + NOTICE: BL31: v1.3(debug):v1.3-372-g1ba9c60 + NOTICE: BL31: Built : 17:51:33, Apr 30 2017 + INFO: BL31: Initializing runtime services + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x37000000 + INFO: SPSR = 0x3c9 + + + U-Boot 2017.05-rc2-00130-gd2255b0 (Apr 30 2017 - 17:51:28 +0200)poplar + + Model: HiSilicon Poplar Development Board + BOARD: Hisilicon HI3798cv200 Poplar + DRAM: 1 GiB + MMC: Hisilicon DWMMC: 0 + In: serial@f8b00000 + Out: serial@f8b00000 + Err: serial@f8b00000 + Net: Net Initialization Skipped + No ethernet found. + + Hit any key to stop autoboot: 0 + starting USB... + USB0: USB EHCI 1.00 + scanning bus 0 for devices... 1 USB Device(s) found + USB1: USB EHCI 1.00 + scanning bus 1 for devices... 4 USB Device(s) found + scanning usb for storage devices... 1 Storage Device(s) found + scanning usb for ethernet devices... 1 Ethernet Device(s) found + + USB device 0: + Device 0: Vendor: SanDisk Rev: 1.00 Prod: Cruzer Blade + Type: Removable Hard Disk + Capacity: 7632.0 MB = 7.4 GB (15630336 x 512) + ... is now current device + Scanning usb 0:1... + => diff --git a/arm-trusted-firmware/docs/plat/qemu-sbsa.rst b/arm-trusted-firmware/docs/plat/qemu-sbsa.rst new file mode 100644 index 0000000..bc82ae5 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qemu-sbsa.rst @@ -0,0 +1,56 @@ +QEMU SBSA Target +================ + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QEMU SBSA +Armv8-A. While running Qemu from command line, we need to supply two Flash +images. First Secure BootRom is supplied by -pflash argument. This Flash image +is made by EDK2 build system by composing BL1 and FIP. Second parameter for Qemu +is responsible for Non-secure rom which also given with -pflash argument and +contains of UEFI and EFI variables (also made by EDK2 build system). Semihosting +is not used + +When QEMU starts all CPUs are released simultaneously, BL1 selects a +primary CPU to handle the boot and the secondaries are placed in a polling +loop to be released by normal world via PSCI. + +BL2 edits the FDT, generated by QEMU at run-time to add a node describing PSCI +and also enable methods for the CPUs. + +Current limitations: + +- Only cold boot is supported + +To build TF-A: + +:: + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa + cd tfa + export CROSS_COMPILE=aarch64-none-elf- + make PLAT=qemu_sbsa all fip + +To build TF-A with BL32 and SPM enabled(StandaloneMM as a Secure Payload): + +:: + + git clone https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git tfa + cd tfa + export CROSS_COMPILE=aarch64-none-elf- + make PLAT=qemu_sbsa BL32=../STANDALONE_MM.fd SPM_MM=1 EL3_EXCEPTION_HANDLING=1 all fip + +Images will be placed at build/qemu_sbsa/release (bl1.bin and fip.bin). +Need to copy them into top directory for EDK2 compilation. + +:: + + cp build/qemu_sbsa/release/bl1.bin ../ + cp build/qemu_sbsa/release/fip.bin ../ + +Those images cannot be used by itself (no semihosing support). Flash images are built by +EDK2 build system, refer to edk2-platform repo for full build instructions. + +:: + + git clone https://github.com/tianocore/edk2-platforms.git + Platform/Qemu/SbsaQemu/Readme.md + diff --git a/arm-trusted-firmware/docs/plat/qemu.rst b/arm-trusted-firmware/docs/plat/qemu.rst new file mode 100644 index 0000000..66b8247 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qemu.rst @@ -0,0 +1,138 @@ +QEMU virt Armv8-A +================= + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QEMU virt +Armv8-A. BL1 is used as the BootROM, supplied with the -bios argument. +When QEMU starts all CPUs are released simultaneously, BL1 selects a +primary CPU to handle the boot and the secondaries are placed in a polling +loop to be released by normal world via PSCI. + +BL2 edits the Flattened Device Tree, FDT, generated by QEMU at run-time to +add a node describing PSCI and also enable methods for the CPUs. + +If ``ARM_LINUX_KERNEL_AS_BL33`` is set to 1 then this FDT will be passed to BL33 +via register x0, as expected by a Linux kernel. This allows a Linux kernel image +to be booted directly as BL33 rather than using a bootloader. + +An ARM64 defconfig v5.5 Linux kernel is known to boot, FDT doesn't need to be +provided as it's generated by QEMU. + +Current limitations: + +- Only cold boot is supported + +Getting non-TF images +--------------------- + +``QEMU_EFI.fd`` can be downloaded from +http://snapshots.linaro.org/components/kernel/leg-virt-tianocore-edk2-upstream/latest/QEMU-KERNEL-AARCH64/RELEASE_GCC5/QEMU_EFI.fd + +or, can be built as follows: + +.. code:: shell + + git clone https://github.com/tianocore/edk2.git + cd edk2 + git submodule update --init + make -C BaseTools + source edksetup.sh + export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- + build -a AARCH64 -t GCC5 -p ArmVirtPkg/ArmVirtQemuKernel.dsc + +```` + +Then, you will get ``Build/ArmVirtQemuKernel-AARCH64/DEBUG_GCC5/FV/QEMU_EFI.fd`` + +Please note you do not need to use GCC 5 in spite of the environment variable +``GCC5_AARCH64_PREFIX`` + +The rootfs can be built by using Buildroot as follows: + +.. code:: shell + + git clone git://git.buildroot.net/buildroot.git + cd buildroot + make qemu_aarch64_virt_defconfig + utils/config -e BR2_TARGET_ROOTFS_CPIO + utils/config -e BR2_TARGET_ROOTFS_CPIO_GZIP + make olddefconfig + make + +Then, you will get ``output/images/rootfs.cpio.gz``. + +Booting via semi-hosting option +------------------------------- + +Boot binaries, except BL1, are primarily loaded via semi-hosting so all +binaries has to reside in the same directory as QEMU is started from. This +is conveniently achieved with symlinks the local names as: + +- ``bl2.bin`` -> BL2 +- ``bl31.bin`` -> BL31 +- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``) +- ``Image`` -> linux/arch/arm64/boot/Image + +To build: + +.. code:: shell + + make CROSS_COMPILE=aarch64-none-elf- PLAT=qemu + +To start (QEMU v5.0.0): + +.. code:: shell + + qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ + -kernel Image \ + -append "console=ttyAMA0,38400 keep_bootcon" \ + -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios bl1.bin \ + -d unimp -semihosting-config enable,target=native + +Booting via flash based firmwares +--------------------------------- + +Boot firmwares are loaded via secure FLASH0 device so ``bl1.bin`` and +``fip.bin`` should be concatenated to create a ``flash.bin`` that is flashed +onto secure FLASH0. + +- ``bl32.bin`` -> BL32 (``tee-header_v2.bin``) +- ``bl32_extra1.bin`` -> BL32 Extra1 (``tee-pager_v2.bin``) +- ``bl32_extra2.bin`` -> BL32 Extra2 (``tee-pageable_v2.bin``) +- ``bl33.bin`` -> BL33 (``QEMU_EFI.fd``) +- ``Image`` -> linux/arch/arm64/boot/Image + +To build: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \ + BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \ + BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip + +To build with TBBR enabled, BL31 and BL32 encrypted with test key: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=qemu BL32=bl32.bin \ + BL32_EXTRA1=bl32_extra1.bin BL32_EXTRA2=bl32_extra2.bin \ + BL33=bl33.bin BL32_RAM_LOCATION=tdram SPD=opteed all fip \ + MBEDTLS_DIR= TRUSTED_BOARD_BOOT=1 \ + GENERATE_COT=1 DECRYPTION_SUPPORT=aes_gcm FW_ENC_STATUS=0 \ + ENCRYPT_BL31=1 ENCRYPT_BL32=1 + +To build flash.bin: + +.. code:: shell + + dd if=build/qemu/release/bl1.bin of=flash.bin bs=4096 conv=notrunc + dd if=build/qemu/release/fip.bin of=flash.bin seek=64 bs=4096 conv=notrunc + +To start (QEMU v5.0.0): + +.. code:: shell + + qemu-system-aarch64 -nographic -machine virt,secure=on -cpu cortex-a57 \ + -kernel Image -no-acpi \ + -append 'console=ttyAMA0,38400 keep_bootcon' \ + -initrd rootfs.cpio.gz -smp 2 -m 1024 -bios flash.bin \ + -d unimp diff --git a/arm-trusted-firmware/docs/plat/qti-msm8916.rst b/arm-trusted-firmware/docs/plat/qti-msm8916.rst new file mode 100644 index 0000000..09a79b7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qti-msm8916.rst @@ -0,0 +1,116 @@ +Qualcomm Snapdragon 410 (MSM8916/APQ8016) +========================================= + +The `Qualcomm Snapdragon 410`_ is Qualcomm's first 64-bit SoC, released in 2014 +with four ARM Cortex-A53 cores. There are differents variants (MSM8916, +APQ8016(E), ...) that are all very similar. A popular device based on APQ8016E +is the `DragonBoard 410c`_ single-board computer, but the SoC is also used in +various mid-range smartphones/tablets. + +The TF-A/BL31 port for MSM8916 provides a minimal, community-maintained +EL3 firmware. It is primarily based on information from the public +`Snapdragon 410E Technical Reference Manual`_ combined with a lot of +trial and error to actually make it work. + +.. note:: + Unlike the :doc:`QTI SC7180/SC7280 ` ports, this port does **not** + make use of a proprietary binary components (QTISECLIB). It is fully + open-source but therefore limited to publicly documented hardware + components. + +Functionality +------------- + +The BL31 port is much more minimal compared to the original firmware and +therefore expects the non-secure world (e.g. Linux) to manage more hardware, +such as the SMMUs and all remote processors (RPM, WCNSS, Venus, Modem). +Everything except modem is currently functional with a slightly modified version +of mainline Linux. + +.. warning:: + This port is **not secure**. There is no special secure memory and the + used DRAM is available from both the non-secure and secure worlds. + Unfortunately, the hardware used for memory protection is not described + in the APQ8016E documentation. + +The port is primarily intended as a minimal PSCI implementation (without a +separate secure world) where this limitation is not a big problem. Booting +secondary CPU cores (PSCI ``CPU_ON``) is supported. Basic CPU core power +management (``CPU_SUSPEND``) is functional but still work-in-progress and +will be added later once ready. + +Boot Flow +--------- +BL31 replaces the original ``tz`` firmware in the boot flow:: + + Boot ROM (PBL) -> SBL -> BL31 (EL3) -> U-Boot (EL2) -> Linux (EL2) + +By default, BL31 enters the non-secure world in EL2 AArch64 state at address +``0x8f600000``. The original hypervisor firmware (``hyp``) is not used, you can +use KVM or another hypervisor. The entry address is fixed in the BL31 binary +but can be changed using the ``PRELOADED_BL33_BASE`` make file parameter. + +Using an AArch64 bootloader (such as `U-Boot for DragonBoard 410c`_) is +recommended. AArch32 bootloaders (such as the original Little Kernel bootloader +from Qualcomm) are not directly supported, although it is possible to use an EL2 +shim loader to temporarily switch to AArch32 state. + +Installation +------------ +First, setup the cross compiler for AArch64 and build TF-A for ``msm8916``:: + + $ make CROSS_COMPILE=aarch64-linux-gnu- PLAT=msm8916 + +The BL31 ELF image is generated in ``build/msm8916/release/bl31/bl31.elf``. +This image must be "signed" before flashing it, even if the board has secure +boot disabled. In this case the signature does not provide any security, +but it provides the firmware with required metadata. + +The `DragonBoard 410c`_ does not have secure boot enabled by default. In this +case you can simply sign the ELF image using a randomly generated key. You can +use e.g. `qtestsign`_:: + + $ ./qtestsign.py tz build/msm8916/release/bl31/bl31.elf + +Then install the resulting ``build/msm8916/release/bl31/bl31-test-signed.mbn`` +to the ``tz`` partition on the device. BL31 should be running after a reboot. + +.. warning:: + Do not flash incorrectly signed firmware on devices that have secure + boot enabled! Make sure that you have a way to recover the board in case + of problems (e.g. using EDL). + +Boot Trace +---------- +BL31 prints some lines on the debug console UART2, which will usually look like +this (with ``DEBUG=1``, otherwise only the ``NOTICE`` lines are shown):: + + ... + S - DDR Frequency, 400 MHz + NOTICE: BL31: v2.6(debug):v2.6 + NOTICE: BL31: Built : 20:00:00, Dec 01 2021 + INFO: BL31: Platform setup start + INFO: ARM GICv2 driver initialized + INFO: BL31: Platform setup done + INFO: BL31: Initializing runtime services + INFO: BL31: cortex_a53: CPU workaround for 819472 was applied + INFO: BL31: cortex_a53: CPU workaround for 824069 was applied + INFO: BL31: cortex_a53: CPU workaround for 826319 was applied + INFO: BL31: cortex_a53: CPU workaround for 827319 was applied + INFO: BL31: cortex_a53: CPU workaround for 835769 was applied + INFO: BL31: cortex_a53: CPU workaround for disable_non_temporal_hint was applied + INFO: BL31: cortex_a53: CPU workaround for 843419 was applied + INFO: BL31: cortex_a53: CPU workaround for 1530924 was applied + INFO: BL31: Preparing for EL3 exit to normal world + INFO: Entry point address = 0x8f600000 + INFO: SPSR = 0x3c9 + + U-Boot 2021.10 (Dec 01 2021 - 20:00:00 +0000) + Qualcomm-DragonBoard 410C + ... + +.. _Qualcomm Snapdragon 410: https://www.qualcomm.com/products/snapdragon-processors-410 +.. _DragonBoard 410c: https://www.96boards.org/product/dragonboard410c/ +.. _Snapdragon 410E Technical Reference Manual: https://developer.qualcomm.com/download/sd410/snapdragon-410e-technical-reference-manual.pdf +.. _U-Boot for DragonBoard 410c: https://u-boot.readthedocs.io/en/latest/board/qualcomm/dragonboard410c.html +.. _qtestsign: https://github.com/msm8916-mainline/qtestsign diff --git a/arm-trusted-firmware/docs/plat/qti.rst b/arm-trusted-firmware/docs/plat/qti.rst new file mode 100644 index 0000000..1d483e7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/qti.rst @@ -0,0 +1,43 @@ +Qualcomm Technologies, Inc. +=========================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for QTI SC7180, +SC7280. + +Boot Trace +------------- + +Bootrom --> BL1/BL2 --> BL31 --> BL33 --> Linux kernel + +BL1/2 and BL33 can currently be supplied from Coreboot + Depthcharge + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +Build Procedure +~~~~~~~~~~~~~~~ + +QTI SoC expects TF-A's BL31 to get integrated with other boot software +Coreboot, so only bl31.elf need to get build from the TF-A repository. + +The build command looks like + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=sc7180 COREBOOT=1 + +update value of CROSS_COMPILE argument with your cross-compilation toolchain. + +Additional QTISECLIB_PATH= can be added in build command. +if QTISECLIB_PATH is not added in build command stub implementation of qtiseclib +is picked. qtiseclib with stub implementation doesn't boot device. This was +added to satisfy compilation. + +QTISELIB for SC7180 is available at +`link `__ +QTISELIB for SC7280 is available at +`link `__ diff --git a/arm-trusted-firmware/docs/plat/rcar-gen3.rst b/arm-trusted-firmware/docs/plat/rcar-gen3.rst new file mode 100644 index 0000000..7107bea --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rcar-gen3.rst @@ -0,0 +1,268 @@ +Renesas R-Car +============= + +"R-Car" is the nickname for Renesas' system-on-chip (SoC) family for +car information systems designed for the next-generation of automotive +computing for the age of autonomous vehicles. + +The scalable R-Car hardware platform and flexible software platform +cover the full product range, from the premium class to the entry +level. Plug-ins are available for multiple open-source software tools. + + +Renesas R-Car Gen3 evaluation boards: +------------------------------------- + ++------------+-----------------+-----------------------------+ +| | Standard | Low Cost Boards (LCB) | ++============+=================+=============================+ +| R-Car H3 | - Salvator-X | - R-Car Starter Kit Premier | +| | - Salvator-XS | | ++------------+-----------------+-----------------------------+ +| R-Car M3-W | - Salvator-X | | +| | - Salvator-XS | - R-Car Starter Kit Pro | ++------------+-----------------+-----------------------------+ +| R-Car M3-N | - Salvator-X | | +| | - Salvator-XS | | ++------------+-----------------+-----------------------------+ +| R-Car V3M | - Eagle | - Starter Kit | ++------------+-----------------+-----------------------------+ +| R-Car V3H | - Condor | - Starter Kit | ++------------+-----------------+-----------------------------+ +| R-Car D3 | - Draak | | ++------------+-----------------+-----------------------------+ + +`boards info `__ + +The current TF-A port has been tested on the R-Car H3 Salvator-X +Soc_id r8a7795 revision ES1.1 (uses a Secure Payload Dispatcher) + + +:: + + ARM CA57 (ARMv8) 1.5 GHz quad core, with NEON/VFPv4, L1$ I/D + 48K/32K, L2$ 2MB + ARM CA53 (ARMv8) 1.2 GHz quad core, with NEON/VFPv4, L1$ I/D 32K/32K, + L2$ 512K + Memory controller for LPDDR4-3200 4GB in 2 channels, each 64-bit wide + Two- and three-dimensional graphics engines, + Video processing units, + 3 channels Display Output, + 6 channels Video Input, + SD card host interface, + USB3.0 and USB2.0 interfaces, + CAN interfaces + Ethernet AVB + PCI Express Interfaces + Memories + INTERNAL 384KB SYSTEM RAM + DDR 4 GB LPDDR4 + HYPERFLASH 64 MB HYPER FLASH (512 MBITS, 160 MHZ, 320 MBYTES/S) + QSPI FLASH 16MB QSPI (128 MBITS,80 MHZ,80 MBYTES/S)1 HEADER QSPI + MODULE + EMMC 32 GB EMMC (HS400 240 MBYTES/S) + MICROSD-CARD SLOT (SDR104 100 MBYTES/S) + + +Overview +-------- +On the rcar-gen3 the BOOTROM starts the cpu at EL3; for this port BL2 +will therefore be entered at this exception level (the Renesas' ATF +reference tree [1] resets into EL1 before entering BL2 - see its +bl2.ld.S) + +BL2 initializes DDR (and on some platforms i2c to interface to the +PMIC) before determining the boot reason (cold or warm). + +During suspend all CPUs are switched off and the DDR is put in backup +mode (some kind of self-refresh mode). This means that BL2 is always +entered in a cold boot scenario. + +Once BL2 boots, it determines the boot reason, writes it to shared +memory (BOOT_KIND_BASE) together with the BL31 parameters +(PARAMS_BASE) and jumps to BL31. + +To all effects, BL31 is as if it is being entered in reset mode since +it still needs to initialize the rest of the cores; this is the reason +behind using direct shared memory access to BOOT_KIND_BASE _and_ +PARAMS_BASE instead of using registers to get to those locations (see +el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use +case). + +Depending on the boot reason BL31 initializes the rest of the cores: +in case of suspend, it uses a MBOX memory region to recover the +program counters. + +[1] https://github.com/renesas-rcar/arm-trusted-firmware + + +How to build +------------ + +The TF-A build options depend on the target board so you will have to +refer to those specific instructions. What follows is customized to +the H3 SiP Salvator-X development system used in this port. + +Build Tested: +~~~~~~~~~~~~~ +RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1" +MBEDTLS_DIR=$mbedtls_src + +$ MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar_layout_tool \ +PLAT=rcar ${RCAR_OPT} SPD=opteed + +System Tested: +~~~~~~~~~~~~~~ +* mbed_tls: + git@github.com:ARMmbed/mbedtls.git [devel] + + commit 552754a6ee82bab25d1bdf28c8261a4518e65e4d + Merge: 68dbc94 f34a4c1 + Author: Simon Butcher + Date: Thu Aug 30 00:57:28 2018 +0100 + +* optee_os: + https://github.com/BayLibre/optee_os + + Until it gets merged into OP-TEE, the port requires Renesas' + Trusted Environment with a modification to support power + management. + commit 80105192cba9e704ebe8df7ab84095edc2922f84 + + Author: Jorge Ramirez-Ortiz + Date: Thu Aug 30 16:49:49 2018 +0200 + plat-rcar: cpu-suspend: handle the power level + Signed-off-by: Jorge Ramirez-Ortiz + +* u-boot: + The port has beent tested using mainline uboot. + + commit 4cdeda511f8037015b568396e6dcc3d8fb41e8c0 + Author: Fabio Estevam + Date: Tue Sep 4 10:23:12 2018 -0300 + +* linux: + The port has beent tested using mainline kernel. + + commit 7876320f88802b22d4e2daf7eb027dd14175a0f8 + Author: Linus Torvalds + Date: Sun Sep 16 11:52:37 2018 -0700 + Linux 4.19-rc4 + +TF-A Build Procedure +~~~~~~~~~~~~~~~~~~~~ + +- Fetch all the above 4 repositories. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using r8a7795_salvator-x_defconfig. + Result: u-boot-elf.srec + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- + r8a7795_salvator-x_defconfig + + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build atf + Result: bootparam_sa0.srec, cert_header_sa6.srec, bl2.srec, bl31.srec + +.. code:: bash + + RCAR_OPT="LSI=H3 RCAR_DRAM_SPLIT=1 RCAR_LOSSY_ENABLE=1" + + MBEDTLS_DIR=$mbedtls_src_tree make clean bl2 bl31 rcar \ + PLAT=rcar ${RCAR_OPT} SPD=opteed + +- Build optee-os + Result: tee.srec + +.. code:: bash + + make -j8 PLATFORM="rcar" CFG_ARM64_core=y + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- Boot the board in Mini-monitor mode and enable access to the + Hyperflash. + + +- Use the XSL2 Mini-monitor utility to accept all the SREC ascii + transfers over serial. + + +Boot trace +---------- + +Notice that BL31 traces are not accessible via the console and that in +order to verbose the BL2 output you will have to compile TF-A with +LOG_LEVEL=50 and DEBUG=1 + +:: + + Initial Program Loader(CA57) Rev.1.0.22 + NOTICE: BL2: PRR is R-Car H3 Ver.1.1 + NOTICE: BL2: Board is Salvator-X Rev.1.0 + NOTICE: BL2: Boot device is HyperFlash(80MHz) + NOTICE: BL2: LCM state is CM + NOTICE: AVS setting succeeded. DVFS_SetVID=0x53 + NOTICE: BL2: DDR1600(rev.0.33)NOTICE: [COLD_BOOT]NOTICE: ..0 + NOTICE: BL2: DRAM Split is 4ch + NOTICE: BL2: QoS is default setting(rev.0.37) + NOTICE: BL2: Lossy Decomp areas + NOTICE: Entry 0: DCMPAREACRAx:0x80000540 DCMPAREACRBx:0x570 + NOTICE: Entry 1: DCMPAREACRAx:0x40000000 DCMPAREACRBx:0x0 + NOTICE: Entry 2: DCMPAREACRAx:0x20000000 DCMPAREACRBx:0x0 + NOTICE: BL2: v2.0(release):v2.0-rc0-32-gbcda69a + NOTICE: BL2: Built : 16:41:23, Oct 2 2018 + NOTICE: BL2: Normal boot + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + NOTICE: BL2: dst=0xe6322000 src=0x8180000 len=512(0x200) + NOTICE: BL2: dst=0x43f00000 src=0x8180400 len=6144(0x1800) + WARNING: r-car ignoring the BL31 size from certificate,using + RCAR_TRUSTED_SRAM_SIZE instead + INFO: Loading image id=3 at address 0x44000000 + NOTICE: rcar_file_len: len: 0x0003e000 + NOTICE: BL2: dst=0x44000000 src=0x81c0000 len=253952(0x3e000) + INFO: Image id=3 loaded: 0x44000000 - 0x4403e000 + INFO: BL2: Loading image id 4 + INFO: Loading image id=4 at address 0x44100000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x44100000 src=0x8200000 len=1048576(0x100000) + INFO: Image id=4 loaded: 0x44100000 - 0x44200000 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x50000000 src=0x8640000 len=1048576(0x100000) + INFO: Image id=5 loaded: 0x50000000 - 0x50100000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0x44000000 + INFO: SPSR = 0x3cd + VERBOSE: Argument #0 = 0xe6325578 + VERBOSE: Argument #1 = 0x0 + VERBOSE: Argument #2 = 0x0 + VERBOSE: Argument #3 = 0x0 + VERBOSE: Argument #4 = 0x0 + VERBOSE: Argument #5 = 0x0 + VERBOSE: Argument #6 = 0x0 + VERBOSE: Argument #7 = 0x0 + + + U-Boot 2018.09-rc3-00028-g3711616 (Sep 27 2018 - 18:50:24 +0200) + + CPU: Renesas Electronics R8A7795 rev 1.1 + Model: Renesas Salvator-X board based on r8a7795 ES2.0+ + DRAM: 3.5 GiB + Flash: 64 MiB + MMC: sd@ee100000: 0, sd@ee140000: 1, sd@ee160000: 2 + Loading Environment from MMC... OK + In: serial@e6e88000 + Out: serial@e6e88000 + Err: serial@e6e88000 + Net: eth0: ethernet@e6800000 + Hit any key to stop autoboot: 0 + => diff --git a/arm-trusted-firmware/docs/plat/rockchip.rst b/arm-trusted-firmware/docs/plat/rockchip.rst new file mode 100644 index 0000000..b7c43fb --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rockchip.rst @@ -0,0 +1,55 @@ +Rockchip SoCs +============= + +Trusted Firmware-A supports a number of Rockchip ARM SoCs from both +AARCH32 and AARCH64 fields. + +This includes right now: +- px30: Quad-Core Cortex-A53 +- rk3288: Quad-Core Cortex-A17 (past A12) +- rk3328: Quad-Core Cortex-A53 +- rk3368: Octa-Core Cortex-A53 +- rk3399: Hexa-Core Cortex-A53/A72 + + +Boot Sequence +------------- + +For AARCH32: + Bootrom --> BL1/BL2 --> BL32 --> BL33 --> Linux kernel + +For AARCH64: + Bootrom --> BL1/BL2 --> BL31 --> BL33 --> Linux kernel + +BL1/2 and BL33 can currently be supplied from either: +- Coreboot + Depthcharge +- U-Boot - either separately as TPL+SPL or only SPL + + +How to build +------------ + +Rockchip SoCs expect TF-A's BL31 (AARCH64) or BL32 (AARCH32) to get +integrated with other boot software like U-Boot or Coreboot, so only +these images need to get build from the TF-A repository. + +For AARCH64 architectures the build command looks like + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=rk3399 bl32 + +while AARCH32 needs a slightly different command + + make ARCH=aarch32 CROSS_COMPILE=arm-linux-gnueabihf- PLAT=rk3288 AARCH32_SP=sp_min bl32 + +Both need replacing the PLAT argument with the platform from above you +want to build for and the CROSS_COMPILE argument with you cross- +compilation toolchain. + + +How to deploy +------------- + +Both upstream U-Boot and Coreboot projects contain instructions on where +to put the built images during their respective build process. +So after successfully building TF-A just follow their build instructions +to continue. diff --git a/arm-trusted-firmware/docs/plat/rpi3.rst b/arm-trusted-firmware/docs/plat/rpi3.rst new file mode 100644 index 0000000..38c3dfa --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rpi3.rst @@ -0,0 +1,466 @@ +Raspberry Pi 3 +============== + +The `Raspberry Pi 3`_ is an inexpensive single-board computer that contains four +Arm Cortex-A53 cores. + +The following instructions explain how to use this port of the TF-A with the +default distribution of `Raspbian`_ because that's the distribution officially +supported by the Raspberry Pi Foundation. At the moment of writing this, the +officially supported kernel is a AArch32 kernel. This doesn't mean that this +port of TF-A can't boot a AArch64 kernel. The `Linux tree fork`_ maintained by +the Foundation can be compiled for AArch64 by following the steps in +`AArch64 kernel build instructions`_. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. This port +shouldn't be considered more than a prototype to play with and implement +elements like PSCI to support the Linux kernel. + +Design +------ + +The SoC used by the Raspberry Pi 3 is the Broadcom BCM2837. It is a SoC with a +VideoCore IV that acts as primary processor (and loads everything from the SD +card) and is located between all Arm cores and the DRAM. Check the `Raspberry Pi +3 documentation`_ for more information. + +This explains why it is possible to change the execution state (AArch64/AArch32) +depending on a few files on the SD card. We only care about the cases in which +the cores boot in AArch64 mode. + +The rules are simple: + +- If a file called ``kernel8.img`` is located on the ``boot`` partition of the + SD card, it will load it and execute in EL2 in AArch64. Basically, it executes + a `default AArch64 stub`_ at address **0x0** that jumps to the kernel. + +- If there is also a file called ``armstub8.bin``, it will load it at address + **0x0** (instead of the default stub) and execute it in EL3 in AArch64. All + the cores are powered on at the same time and start at address **0x0**. + +This means that we can use the default AArch32 kernel provided in the official +`Raspbian`_ distribution by renaming it to ``kernel8.img``, while TF-A and +anything else we need is in ``armstub8.bin``. This way we can forget about the +default bootstrap code. When using a AArch64 kernel, it is only needed to make +sure that the name on the SD card is ``kernel8.img``. + +Ideally, we want to load the kernel and have all cores available, which means +that we need to make the secondary cores work in the way the kernel expects, as +explained in `Secondary cores`_. In practice, a small bootstrap is needed +between TF-A and the kernel. + +To get the most out of a AArch32 kernel, we want to boot it in Hypervisor mode +in AArch32. This means that BL33 can't be in EL2 in AArch64 mode. The +architecture specifies that AArch32 Hypervisor mode isn't present when AArch64 +is used for EL2. When using a AArch64 kernel, it should simply start in EL2. + +Placement of images +~~~~~~~~~~~~~~~~~~~ + +The file ``armstub8.bin`` contains BL1 and the FIP. It is needed to add padding +between them so that the addresses they are loaded to match the ones specified +when compiling TF-A. This is done automatically by the build system. + +The device tree block is loaded by the VideoCore loader from an appropriate +file, but we can specify the address it is loaded to in ``config.txt``. + +The file ``kernel8.img`` contains a kernel image that is loaded to the address +specified in ``config.txt``. The `Linux kernel tree`_ has information about how +a AArch32 Linux kernel image is loaded in ``Documentation/arm/Booting``: + +:: + + The zImage may also be placed in system RAM and called there. The + kernel should be placed in the first 128MiB of RAM. It is recommended + that it is loaded above 32MiB in order to avoid the need to relocate + prior to decompression, which will make the boot process slightly + faster. + +There are no similar restrictions for AArch64 kernels, as specified in the file +``Documentation/arm64/booting.txt``. + +This means that we need to avoid the first 128 MiB of RAM when placing the +TF-A images (and specially the first 32 MiB, as they are directly used to +place the uncompressed AArch32 kernel image. This way, both AArch32 and +AArch64 kernels can be placed at the same address. + +In the end, the images look like the following diagram when placed in memory. +All addresses are Physical Addresses from the point of view of the Arm cores. +Again, note that this is all just part of the same DRAM that goes from +**0x00000000** to **0x3F000000**, it just has different names to simulate a real +secure platform! + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00020000 +-----------------+ + | FIP | + 0x00200000 +-----------------+ + | | + | ... | + | | + 0x01000000 +-----------------+ + | DTB | (Loaded by the VideoCore) + +-----------------+ + | | + | ... | + | | + 0x02000000 +-----------------+ + | Kernel | (Loaded by the VideoCore) + +-----------------+ + | | + | ... | + | | + 0x10000000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x10100000 +-----------------+ + | Secure DRAM | BL32 (Secure payload) + 0x11000000 +-----------------+ + | Non-secure DRAM | BL33 + +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + 0x40000000 +-----------------+ + +The area between **0x10000000** and **0x11000000** has to be manually protected +so that the kernel doesn't use it. The current port tries to modify the live DTB +to add a memreserve region that reserves the previously mentioned area. + +If this is not possible, the user may manually add ``memmap=16M$256M`` to the +command line passed to the kernel in ``cmdline.txt``. See the `Setup SD card`_ +instructions to see how to do it. This system is strongly discouraged. + +The last 16 MiB of DRAM can only be accessed by the VideoCore, that has +different mappings than the Arm cores in which the I/O addresses don't overlap +the DRAM. The memory reserved to be used by the VideoCore is always placed at +the end of the DRAM, so this space isn't wasted. + +Considering the 128 MiB allocated to the GPU and the 16 MiB allocated for +TF-A, there are 880 MiB available for Linux. + +Boot sequence +~~~~~~~~~~~~~ + +The boot sequence of TF-A is the usual one except when booting an AArch32 +kernel. In that case, BL33 is booted in AArch32 Hypervisor mode so that it +can jump to the kernel in the same mode and let it take over that privilege +level. If BL33 was running in EL2 in AArch64 (as in the default bootflow of +TF-A) it could only jump to the kernel in AArch32 in Supervisor mode. + +The `Linux kernel tree`_ has instructions on how to jump to the Linux kernel +in ``Documentation/arm/Booting`` and ``Documentation/arm64/booting.txt``. The +bootstrap should take care of this. + +This port support a direct boot of the Linux kernel from the firmware (as a BL33 +image). Alternatively, U-Boot or other bootloaders may be used. + +Secondary cores +~~~~~~~~~~~~~~~ + +This port of the Trusted Firmware-A supports ``PSCI_CPU_ON``, +``PSCI_SYSTEM_RESET`` and ``PSCI_SYSTEM_OFF``. The last one doesn't really turn +the system off, it simply reboots it and asks the VideoCore firmware to keep it +in a low power mode permanently. + +The kernel used by `Raspbian`_ doesn't have support for PSCI, so it is needed to +use mailboxes to trap the secondary cores until they are ready to jump to the +kernel. This mailbox is located at a different address in the AArch32 default +kernel than in the AArch64 kernel. + +Kernels with PSCI support can use the PSCI calls instead for a cleaner boot. + +Also, this port of TF-A has another Trusted Mailbox in Shared BL RAM. During +cold boot, all secondary cores wait in a loop until they are given given an +address to jump to in this Mailbox (``bl31_warm_entrypoint``). + +Once BL31 has finished and the primary core has jumped to the BL33 payload, it +has to call ``PSCI_CPU_ON`` to release the secondary CPUs from the wait loop. +The payload then makes them wait in another waitloop listening from messages +from the kernel. When the primary CPU jumps into the kernel, it will send an +address to the mailbox so that the secondary CPUs jump to it and are recognised +by the kernel. + +Build Instructions +------------------ + +To boot a AArch64 kernel, only the AArch64 toolchain is required. + +To boot a AArch32 kernel, both AArch64 and AArch32 toolchains are required. The +AArch32 toolchain is needed for the AArch32 bootstrap needed to load a 32-bit +kernel. + +The build system concatenates BL1 and the FIP so that the addresses match the +ones in the memory map. The resulting file is ``armstub8.bin``, located in the +build folder (e.g. ``build/rpi3/debug/armstub8.bin``). To know how to use this +file, follow the instructions in `Setup SD card`_. + +The following build options are supported: + +- ``RPI3_BL33_IN_AARCH32``: This port can load a AArch64 or AArch32 BL33 image. + By default this option is 0, which means that TF-A will jump to BL33 in EL2 + in AArch64 mode. If set to 1, it will jump to BL33 in Hypervisor in AArch32 + mode. + +- ``PRELOADED_BL33_BASE``: Used to specify the address of a BL33 binary that has + been preloaded by any other system than using the firmware. ``BL33`` isn't + needed in the build command line if this option is used. Specially useful + because the file ``kernel8.img`` can be loaded anywhere by modifying the file + ``config.txt``. It doesn't have to contain a kernel, it could have any + arbitrary payload. + +- ``RPI3_DIRECT_LINUX_BOOT``: Disabled by default. Set to 1 to enable the direct + boot of the Linux kernel from the firmware. Option ``RPI3_PRELOADED_DTB_BASE`` + is mandatory when the direct Linux kernel boot is used. Options + ``PRELOADED_BL33_BASE`` will most likely be needed as well because it is + unlikely that the kernel image will fit in the space reserved for BL33 images. + This option can be combined with ``RPI3_BL33_IN_AARCH32`` in order to boot a + 32-bit kernel. The only thing this option does is to set the arguments in + registers x0-x3 or r0-r2 as expected by the kernel. + +- ``RPI3_PRELOADED_DTB_BASE``: Auxiliary build option needed when using + ``RPI3_DIRECT_LINUX_BOOT=1``. This option allows to specify the location of a + DTB in memory. + +- ``RPI3_RUNTIME_UART``: Indicates whether the UART should be used at runtime + or disabled. ``-1`` (default) disables the runtime UART. Any other value + enables the default UART (currently UART1) for runtime messages. + +- ``RPI3_USE_UEFI_MAP``: Set to 1 to build ATF with the altername memory + mapping required for an UEFI firmware payload. These changes are needed + to be able to run Windows on ARM64. This option, which is disabled by + default, results in the following memory mappings: + +:: + + 0x00000000 +-----------------+ + | ROM | BL1 + 0x00010000 +-----------------+ + | DTB | (Loaded by the VideoCore) + 0x00020000 +-----------------+ + | FIP | + 0x00030000 +-----------------+ + | | + | UEFI PAYLOAD | + | | + 0x00200000 +-----------------+ + | Secure SRAM | BL2, BL31 + 0x00300000 +-----------------+ + | Secure DRAM | BL32 (Secure payload) + 0x00400000 +-----------------+ + | | + | | + | Non-secure DRAM | BL33 + | | + | | + 0x01000000 +-----------------+ + | | + | ... | + | | + 0x3F000000 +-----------------+ + | I/O | + +- ``BL32``: This port can load and run OP-TEE. The OP-TEE image is optional. + Please use the code from `here `__. + Build the Trusted Firmware with option ``BL32=tee-header_v2.bin + BL32_EXTRA1=tee-pager_v2.bin BL32_EXTRA2=tee-pageable_v2.bin`` + to put the binaries into the FIP. + + .. warning:: + If OP-TEE is used it may be needed to add the following options to the + Linux command line so that the USB driver doesn't use FIQs: + ``dwc_otg.fiq_enable=0 dwc_otg.fiq_fsm_enable=0 dwc_otg.nak_holdoff=0``. + This will unfortunately reduce the performance of the USB driver. It is + needed when using Raspbian, for example. + +- ``TRUSTED_BOARD_BOOT``: This port supports TBB. Set this option to 1 to enable + it. In order to use TBB, you might want to set ``GENERATE_COT=1`` to let the + contents of the FIP automatically signed by the build process. The ROT key + will be generated and output to ``rot_key.pem`` in the build directory. It is + able to set ROT_KEY to your own key in PEM format. Also in order to build, + you need to clone mbed TLS from `here `__. + ``MBEDTLS_DIR`` must point at the mbed TLS source directory. + +- ``ENABLE_STACK_PROTECTOR``: Disabled by default. It uses the hardware RNG of + the board. + +The following is not currently supported: + +- AArch32 for TF-A itself. + +- ``EL3_PAYLOAD_BASE``: The reason is that you can already load anything to any + address by changing the file ``armstub8.bin``, so there's no point in using + TF-A in this case. + +- ``MULTI_CONSOLE_API=0``: The multi console API must be enabled. Note that the + crash console uses the internal 16550 driver functions directly in order to be + able to print error messages during early crashes before setting up the + multi console API. + +Building the firmware for kernels that don't support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +This is the case for the 32-bit image of Raspbian, for example. 64-bit kernels +always support PSCI, but they may not know that the system understands PSCI due +to an incorrect DTB file. + +First, clone and compile the 32-bit version of the `Raspberry Pi 3 TF-A +bootstrap`_. Choose the one needed for the architecture of your kernel. + +Then compile TF-A. For a 32-bit kernel, use the following command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + RPI3_BL33_IN_AARCH32=1 \ + BL33=../rpi3-arm-tf-bootstrap/aarch32/el2-bootstrap.bin + +For a 64-bit kernel, use this other command line: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + BL33=../rpi3-arm-tf-bootstrap/aarch64/el2-bootstrap.bin + +However, enabling PSCI support in a 64-bit kernel is really easy. In the +repository `Raspberry Pi 3 TF-A bootstrap`_ there is a patch that can be applied +to the Linux kernel tree maintained by the Raspberry Pi foundation. It modifes +the DTS to tell the kernel to use PSCI. Once this patch is applied, follow the +instructions in `AArch64 kernel build instructions`_ to get a working 64-bit +kernel image and supporting files. + +Building the firmware for kernels that support PSCI +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +For a 64-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 + +For a 32-bit kernel: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi3 \ + PRELOADED_BL33_BASE=0x02000000 \ + RPI3_PRELOADED_DTB_BASE=0x01000000 \ + RPI3_DIRECT_LINUX_BOOT=1 \ + RPI3_BL33_IN_AARCH32=1 + +AArch64 kernel build instructions +--------------------------------- + +The following instructions show how to install and run a AArch64 kernel by +using a SD card with the default `Raspbian`_ install as base. Skip them if you +want to use the default 32-bit kernel. + +Note that this system won't be fully 64-bit because all the tools in the +filesystem are 32-bit binaries, but it's a quick way to get it working, and it +allows the user to run 64-bit binaries in addition to 32-bit binaries. + +1. Clone the `Linux tree fork`_ maintained by the Raspberry Pi Foundation. To + speed things up, do a shallow clone of the desired branch. + +.. code:: shell + + git clone --depth=1 -b rpi-4.18.y https://github.com/raspberrypi/linux + cd linux + +2. Configure and compile the kernel. Adapt the number after ``-j`` so that it is + 1.5 times the number of CPUs in your computer. This may take some time to + finish. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- bcmrpi3_defconfig + make -j 6 ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- + +3. Copy the kernel image and the device tree to the SD card. Replace the path + by the corresponding path in your computers to the ``boot`` partition of the + SD card. + +.. code:: shell + + cp arch/arm64/boot/Image /path/to/boot/kernel8.img + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b.dtb /path/to/boot/ + cp arch/arm64/boot/dts/broadcom/bcm2710-rpi-3-b-plus.dtb /path/to/boot/ + +4. Install the kernel modules. Replace the path by the corresponding path to the + filesystem partition of the SD card on your computer. + +.. code:: shell + + make ARCH=arm64 CROSS_COMPILE=aarch64-linux-gnu- \ + INSTALL_MOD_PATH=/path/to/filesystem modules_install + +5. Follow the instructions in `Setup SD card`_ except for the step of renaming + the existing ``kernel7.img`` (we have already copied a AArch64 kernel). + +Setup SD card +------------- + +The instructions assume that you have an SD card with a fresh install of +`Raspbian`_ (or that, at least, the ``boot`` partition is untouched, or nearly +untouched). They have been tested with the image available in 2018-03-13. + +1. Insert the SD card and open the ``boot`` partition. + +2. Rename ``kernel7.img`` to ``kernel8.img``. This tricks the VideoCore + bootloader into booting the Arm cores in AArch64 mode, like TF-A needs, + even though the kernel is not compiled for AArch64. + +3. Copy ``armstub8.bin`` here. When ``kernel8.img`` is available, The VideoCore + bootloader will look for a file called ``armstub8.bin`` and load it at + address **0x0** instead of a predefined one. + +4. To enable the serial port "Mini UART" in Linux, open ``cmdline.txt`` and add + ``console=serial0,115200 console=tty1``. + +5. Open ``config.txt`` and add the following lines at the end (``enable_uart=1`` + is only needed to enable debugging through the Mini UART): + +:: + + enable_uart=1 + kernel_address=0x02000000 + device_tree_address=0x01000000 + +If you connect a serial cable to the Mini UART and your computer, and connect +to it (for example, with ``screen /dev/ttyUSB0 115200``) you should see some +text. In the case of an AArch32 kernel, you should see something like this: + +:: + + NOTICE: Booting Trusted Firmware + NOTICE: BL1: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL1: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL2 + NOTICE: BL2: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL2: Built : 00:09:25, Nov 6 2017 + NOTICE: BL1: Booting BL31 + NOTICE: BL31: v1.4(release):v1.4-329-g61e94684-dirty + NOTICE: BL31: Built : 00:09:25, Nov 6 2017 + [ 0.266484] bcm2835-aux-uart 3f215040.serial: could not get clk: -517 + + Raspbian GNU/Linux 9 raspberrypi ttyS0 + raspberrypi login: + +Just enter your credentials, everything should work as expected. Note that the +HDMI output won't show any text during boot. + +.. _default Arm stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub7.S +.. _default AArch64 stub: https://github.com/raspberrypi/tools/blob/master/armstubs/armstub8.S +.. _Linux kernel tree: https://github.com/torvalds/linux +.. _Linux tree fork: https://github.com/raspberrypi/linux +.. _Raspberry Pi 3: https://www.raspberrypi.org/products/raspberry-pi-3-model-b/ +.. _Raspberry Pi 3 TF-A bootstrap: https://github.com/AntonioND/rpi3-arm-tf-bootstrap +.. _Raspberry Pi 3 documentation: https://www.raspberrypi.org/documentation/ +.. _Raspbian: https://www.raspberrypi.org/downloads/raspbian/ diff --git a/arm-trusted-firmware/docs/plat/rpi4.rst b/arm-trusted-firmware/docs/plat/rpi4.rst new file mode 100644 index 0000000..6e83fd7 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rpi4.rst @@ -0,0 +1,84 @@ +Raspberry Pi 4 +============== + +The `Raspberry Pi 4`_ is an inexpensive single-board computer that contains four +Arm Cortex-A72 cores. Also in contrast to previous Raspberry Pi versions this +model has a GICv2 interrupt controller. + +This port is a minimal port to support loading non-secure EL2 payloads such +as a 64-bit Linux kernel. Other payloads such as U-Boot or EDK-II should work +as well, but have not been tested at this point. + +**IMPORTANT NOTE**: This port isn't secure. All of the memory used is DRAM, +which is available from both the Non-secure and Secure worlds. The SoC does +not seem to feature a secure memory controller of any kind, so portions of +DRAM can't be protected properly from the Non-secure world. + +Build Instructions +------------------ + +There are no real configuration options at this point, so there is only +one universal binary (bl31.bin), which can be built with: + +.. code:: shell + + CROSS_COMPILE=aarch64-linux-gnu- make PLAT=rpi4 DEBUG=1 + +Copy the generated build/rpi4/debug/bl31.bin to the SD card, adding an entry +starting with ``armstub=``, then followed by the respective file name to +``config.txt``. You should have AArch64 code in the file loaded as the +"kernel", as BL31 will drop into AArch64/EL2 to the respective load address. +arm64 Linux kernels are known to work this way. + +Other options that should be set in ``config.txt`` to properly boot 64-bit +kernels are: + +:: + + enable_uart=1 + arm_64bit=1 + enable_gic=1 + +The BL31 code will patch the provided device tree blob in memory to advertise +PSCI support, also will add a reserved-memory node to the DT to tell the +non-secure payload to not touch the resident TF-A code. + +If you connect a serial cable between the Mini UART and your computer, and +connect to it (for example, with ``screen /dev/ttyUSB0 115200``) you should +see some text from BL31, followed by the output of the EL2 payload. +The command line provided is read from the ``cmdline.txt`` file on the SD card. + +TF-A port design +---------------- + +In contrast to the existing Raspberry Pi 3 port this one here is a BL31-only +port, also it deviates quite a lot from the RPi3 port in many other ways. +There is not so much difference between the two models, so eventually those +two could be (more) unified in the future. + +As with the previous models, the GPU and its firmware are the first entity to +run after the SoC gets its power. The on-chip Boot ROM loads the next stage +(bootcode.bin) from flash (EEPROM), which is again GPU code. +This part knows how to access the MMC controller and how to parse a FAT +filesystem, so it will load further components and configuration files +from the first FAT partition on the SD card. + +To accommodate this existing way of configuring and setting up the board, +we use as much of this workflow as possible. +If bootcode.bin finds a file called ``armstub8.bin`` on the SD card or it gets +pointed to such code by finding a ``armstub=`` key in ``config.txt``, it will +load this file to the beginning of DRAM (address 0) and execute it in +AArch64 EL3. +But before doing that, it will also load a "kernel" and the device tree into +memory. The load addresses have a default, but can also be changed by +setting them in ``config.txt``. If the GPU firmware finds a magic value in the +armstub image file, it will put those two load addresses in memory locations +near the beginning of memory, where TF-A code picks them up. + +To keep things simple, we will just use the kernel load address as the BL33 +entry point, also put the DTB address in the x0 register, as requested by +the arm64 Linux kernel boot protocol. This does not necessarily mean that +the EL2 payload needs to be a Linux kernel, a bootloader or any other kernel +would work as well, as long as it can cope with having the DT address in +register x0. If the payload has other means of finding the device tree, it +could ignore this address as well. diff --git a/arm-trusted-firmware/docs/plat/rz-g2.rst b/arm-trusted-firmware/docs/plat/rz-g2.rst new file mode 100644 index 0000000..e7ae620 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/rz-g2.rst @@ -0,0 +1,228 @@ +Renesas RZ/G +============ + +The "RZ/G" Family of high-end 64-bit Arm®-based microprocessors (MPUs) +enables the solutions required for the smart society of the future. +Through a variety of Arm Cortex®-A53 and A57-based devices, engineers can +easily implement high-resolution human machine interfaces (HMI), embedded +vision, embedded artificial intelligence (e-AI) and real-time control and +industrial ethernet connectivity. + +The scalable RZ/G hardware platform and flexible software platform +cover the full product range, from the premium class to the entry +level. Plug-ins are available for multiple open-source software tools. + + +Renesas RZ/G2 reference platforms: +---------------------------------- + ++--------------+----------------------------------------------------------------------------------+ +| Board | Details | ++==============+===============+==================================================================+ +| hihope-rzg2h | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2H SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| hihope-rzg2m | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2M SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| hihope-rzg2n | "96 boards" compatible board from Hoperun equipped with Renesas RZ/G2N SoC | +| +----------------------------------------------------------------------------------+ +| | http://hihope.org/product/musashi | ++--------------+----------------------------------------------------------------------------------+ +| ek874 | "96 boards" compatible board from Silicon Linux equipped with Renesas RZ/G2E SoC | +| +----------------------------------------------------------------------------------+ +| | https://www.si-linux.co.jp/index.php?CAT%2FCAT874 | ++--------------+----------------------------------------------------------------------------------+ + +`boards info `__ + +The current TF-A port has been tested on the HiHope RZ/G2M +SoC_id r8a774a1 revision ES1.3. + + +:: + + ARM CA57 (ARMv8) 1.5 GHz dual core, with NEON/VFPv4, L1$ I/D 48K/32K, L2$ 1MB + ARM CA53 (ARMv8) 1.2 GHz quad core, with NEON/VFPv4, L1$ I/D 32K/32K, L2$ 512K + Memory controller for LPDDR4-3200 4GB in 2 channels(32-bit bus mode) + Two- and three-dimensional graphics engines, + Video processing units, + Display Output, + Video Input, + SD card host interface, + USB3.0 and USB2.0 interfaces, + CAN interfaces, + Ethernet AVB, + Wi-Fi + BT, + PCI Express Interfaces, + Memories + INTERNAL 384KB SYSTEM RAM + DDR 4 GB LPDDR4 + QSPI FLASH 64MB + EMMC 32 GB EMMC (HS400 240 MBYTES/S) + MICROSD-CARD SLOT (SDR104 100 MBYTES/S) + +Overview +-------- +On RZ/G2 SoCs the BOOTROM starts the cpu at EL3; for this port BL2 +will therefore be entered at this exception level (the Renesas' ATF +reference tree [1] resets into EL1 before entering BL2 - see its +bl2.ld.S) + +BL2 initializes DDR before determining the boot reason (cold or warm). + +Once BL2 boots, it determines the boot reason, writes it to shared +memory (BOOT_KIND_BASE) together with the BL31 parameters +(PARAMS_BASE) and jumps to BL31. + +To all effects, BL31 is as if it is being entered in reset mode since +it still needs to initialize the rest of the cores; this is the reason +behind using direct shared memory access to BOOT_KIND_BASE _and_ +PARAMS_BASE instead of using registers to get to those locations (see +el3_common_macros.S and bl31_entrypoint.S for the RESET_TO_BL31 use +case). + +[1] https://github.com/renesas-rz/meta-rzg2/tree/BSP-1.0.5/recipes-bsp/arm-trusted-firmware/files + + +How to build +------------ + +The TF-A build options depend on the target board so you will have to +refer to those specific instructions. What follows is customized to +the HiHope RZ/G2M development kit used in this port. + +Build Tested: +~~~~~~~~~~~~~ + +.. code:: bash + + make bl2 bl31 rzg LOG_LEVEL=40 PLAT=rzg LSI=G2M RCAR_DRAM_SPLIT=2\ + RCAR_LOSSY_ENABLE=1 SPD="none" MBEDTLS_DIR=$mbedtls + +System Tested: +~~~~~~~~~~~~~~ +* mbed_tls: + git@github.com:ARMmbed/mbedtls.git [devel] + +| commit 72ca39737f974db44723760623d1b29980c00a88 +| Merge: ef94c4fcf dd9ec1c57 +| Author: Janos Follath +| Date: Wed Oct 7 09:21:01 2020 +0100 + +* u-boot: + The port has beent tested using mainline uboot with HiHope RZ/G2M board + specific patches. + +| commit 46ce9e777c1314ccb78906992b94001194eaa87b +| Author: Heiko Schocher +| Date: Tue Nov 3 15:22:36 2020 +0100 + +* linux: + The port has beent tested using mainline kernel. + +| commit f8394f232b1eab649ce2df5c5f15b0e528c92091 +| Author: Linus Torvalds +| Date: Sun Nov 8 16:10:16 2020 -0800 +| Linux 5.10-rc3 + +TF-A Build Procedure +~~~~~~~~~~~~~~~~~~~~ + +- Fetch all the above 3 repositories. + +- Prepare the AARCH64 toolchain. + +- Build u-boot using hihope_rzg2_defconfig. + + Result: u-boot-elf.srec + +.. code:: bash + + make CROSS_COMPILE=aarch64-linux-gnu- + hihope_rzg2_defconfig + + make CROSS_COMPILE=aarch64-linux-gnu- + +- Build TF-A + + Result: bootparam_sa0.srec, cert_header_sa6.srec, bl2.srec, bl31.srec + +.. code:: bash + + make bl2 bl31 rzg LOG_LEVEL=40 PLAT=rzg LSI=G2M RCAR_DRAM_SPLIT=2\ + RCAR_LOSSY_ENABLE=1 SPD="none" MBEDTLS_DIR=$mbedtls + + +Install Procedure +~~~~~~~~~~~~~~~~~ + +- Boot the board in Mini-monitor mode and enable access to the + QSPI flash. + + +- Use the flash_writer utility[2] to flash all the SREC files. + +[2] https://github.com/renesas-rz/rzg2_flash_writer + + +Boot trace +---------- +:: + + INFO: ARM GICv2 driver initialized + NOTICE: BL2: RZ/G2 Initial Program Loader(CA57) Rev.2.0.6 + NOTICE: BL2: PRR is RZ/G2M Ver.1.3 + NOTICE: BL2: Board is HiHope RZ/G2M Rev.4.0 + NOTICE: BL2: Boot device is QSPI Flash(40MHz) + NOTICE: BL2: LCM state is unknown + NOTICE: BL2: DDR3200(rev.0.40) + NOTICE: BL2: [COLD_BOOT] + NOTICE: BL2: DRAM Split is 2ch + NOTICE: BL2: QoS is default setting(rev.0.19) + NOTICE: BL2: DRAM refresh interval 1.95 usec + NOTICE: BL2: Periodic Write DQ Training + NOTICE: BL2: CH0: 400000000 - 47fffffff, 2 GiB + NOTICE: BL2: CH2: 600000000 - 67fffffff, 2 GiB + NOTICE: BL2: Lossy Decomp areas + NOTICE: Entry 0: DCMPAREACRAx:0x80000540 DCMPAREACRBx:0x570 + NOTICE: Entry 1: DCMPAREACRAx:0x40000000 DCMPAREACRBx:0x0 + NOTICE: Entry 2: DCMPAREACRAx:0x20000000 DCMPAREACRBx:0x0 + NOTICE: BL2: FDT at 0xe631db30 + NOTICE: BL2: v2.3(release):v2.4-rc0-2-g1433701e5 + NOTICE: BL2: Built : 13:45:26, Nov 7 2020 + NOTICE: BL2: Normal boot + INFO: BL2: Doing platform setup + INFO: BL2: Loading image id 3 + NOTICE: BL2: dst=0xe631d200 src=0x8180000 len=512(0x200) + NOTICE: BL2: dst=0x43f00000 src=0x8180400 len=6144(0x1800) + WARNING: r-car ignoring the BL31 size from certificate,using RCAR_TRUSTED_SRAM_SIZE instead + INFO: Loading image id=3 at address 0x44000000 + NOTICE: rcar_file_len: len: 0x0003e000 + NOTICE: BL2: dst=0x44000000 src=0x81c0000 len=253952(0x3e000) + INFO: Image id=3 loaded: 0x44000000 - 0x4403e000 + INFO: BL2: Loading image id 5 + INFO: Loading image id=5 at address 0x50000000 + NOTICE: rcar_file_len: len: 0x00100000 + NOTICE: BL2: dst=0x50000000 src=0x8300000 len=1048576(0x100000) + INFO: Image id=5 loaded: 0x50000000 - 0x50100000 + NOTICE: BL2: Booting BL31 + INFO: Entry point address = 0x44000000 + INFO: SPSR = 0x3cd + + + U-Boot 2021.01-rc1-00244-gac37e14fbd (Nov 04 2020 - 20:03:34 +0000) + + CPU: Renesas Electronics R8A774A1 rev 1.3 + Model: HopeRun HiHope RZ/G2M with sub board + DRAM: 3.9 GiB + MMC: mmc@ee100000: 0, mmc@ee160000: 1 + Loading Environment from MMC... OK + In: serial@e6e88000 + Out: serial@e6e88000 + Err: serial@e6e88000 + Net: eth0: ethernet@e6800000 + Hit any key to stop autoboot: 0 + => diff --git a/arm-trusted-firmware/docs/plat/socionext-uniphier.rst b/arm-trusted-firmware/docs/plat/socionext-uniphier.rst new file mode 100644 index 0000000..9288193 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/socionext-uniphier.rst @@ -0,0 +1,116 @@ +Socionext UniPhier +================== + +Socionext UniPhier Armv8-A SoCs use Trusted Firmware-A (TF-A) as the secure +world firmware, supporting BL2 and BL31. + +UniPhier SoC family implements its internal boot ROM, which loads 64KB [1]_ +image from a non-volatile storage to the on-chip SRAM, and jumps over to it. +TF-A provides a special mode, BL2-AT-EL3, which enables BL2 to execute at EL3. +It is useful for platforms with non-TF-A boot ROM, like UniPhier. Here, a +problem is BL2 does not fit in the 64KB limit if +:ref:`Trusted Board Boot (TBB) ` is enabled. +To solve this issue, Socionext provides a first stage loader called +`UniPhier BL`_. This loader runs in the on-chip SRAM, initializes the DRAM, +expands BL2 there, and hands the control over to it. Therefore, all images +of TF-A run in DRAM. + +The UniPhier platform works with/without TBB. See below for the build process +of each case. The image authentication for the UniPhier platform fully +complies with the Trusted Board Boot Requirements (TBBR) specification. + +The UniPhier BL does not implement the authentication functionality, that is, +it can not verify the BL2 image by itself. Instead, the UniPhier BL assures +the BL2 validity in a different way; BL2 is GZIP-compressed and appended to +the UniPhier BL. The concatenation of the UniPhier BL and the compressed BL2 +fits in the 64KB limit. The concatenated image is loaded by the internal boot +ROM (and verified if the chip fuses are blown). + + +Boot Flow +--------- + +1. The Boot ROM + + This is hard-wired ROM, so never corrupted. It loads the UniPhier BL (with + compressed-BL2 appended) into the on-chip SRAM. If the SoC fuses are blown, + the image is verified by the SoC's own method. + +2. UniPhier BL + + This runs in the on-chip SRAM. After the minimum SoC initialization and DRAM + setup, it decompresses the appended BL2 image into the DRAM, then jumps to + the BL2 entry. + +3. BL2 (at EL3) + + This runs in the DRAM. It extracts more images such as BL31, BL33 (optionally + SCP_BL2, BL32 as well) from Firmware Image Package (FIP). If TBB is enabled, + they are all authenticated by the standard mechanism of TF-A. + After loading all the images, it jumps to the BL31 entry. + +4. BL31, BL32, and BL33 + + They all run in the DRAM. See :ref:`Firmware Design` for details. + + +Basic Build +----------- + +BL2 must be compressed for the reason above. The UniPhier's platform makefile +provides a build target ``bl2_gzip`` for this. + +For a non-secure boot loader (aka BL33), U-Boot is well supported for UniPhier +SoCs. The U-Boot image (``u-boot.bin``) must be built in advance. For the build +procedure of U-Boot, refer to the document in the `U-Boot`_ project. + +To build minimum functionality for UniPhier (without TBB):: + + make CROSS_COMPILE= PLAT=uniphier BL33= bl2_gzip fip + +Output images: + +- ``bl2.bin.gz`` +- ``fip.bin`` + + +Optional features +----------------- + +- Trusted Board Boot + + `mbed TLS`_ is needed as the cryptographic and image parser modules. + Refer to the :ref:`Prerequisites` document for the appropriate version of + mbed TLS. + + To enable TBB, add the following options to the build command:: + + TRUSTED_BOARD_BOOT=1 GENERATE_COT=1 MBEDTLS_DIR= + +- System Control Processor (SCP) + + If desired, FIP can include an SCP BL2 image. If BL2 finds an SCP BL2 image + in FIP, BL2 loads it into DRAM and kicks the SCP. Most of UniPhier boards + still work without SCP, but SCP provides better power management support. + + To include SCP BL2, add the following option to the build command:: + + SCP_BL2= + +- BL32 (Secure Payload) + + To enable BL32, add the following options to the build command:: + + SPD= BL32= + + If you use TSP for BL32, ``BL32=`` is not required. Just add the + following:: + + SPD=tspd + + +.. [1] Some SoCs can load 80KB, but the software implementation must be aligned + to the lowest common denominator. +.. _UniPhier BL: https://github.com/uniphier/uniphier-bl +.. _U-Boot: https://www.denx.de/wiki/U-Boot +.. _mbed TLS: https://tls.mbed.org/ diff --git a/arm-trusted-firmware/docs/plat/stm32mp1.rst b/arm-trusted-firmware/docs/plat/stm32mp1.rst new file mode 100644 index 0000000..7ae98b1 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/stm32mp1.rst @@ -0,0 +1,305 @@ +STMicroelectronics STM32MP1 +=========================== + +STM32MP1 is a microprocessor designed by STMicroelectronics +based on Arm Cortex-A7. +It is an Armv7-A platform, using dedicated code from TF-A. +More information can be found on `STM32MP1 Series`_ page. + + +STM32MP1 Versions +----------------- + +There are 2 variants for STM32MP1: STM32MP13 and STM32MP15 + +STM32MP13 Versions +~~~~~~~~~~~~~~~~~~ +The STM32MP13 series is available in 3 different lines which are pin-to-pin compatible: + +- STM32MP131: Single Cortex-A7 core +- STM32MP133: STM32MP131 + 2*CAN, ETH2(GMAC), ADC1 +- STM32MP135: STM32MP133 + DCMIPP, LTDC + +Each line comes with a security option (cryptography & secure boot) and a Cortex-A frequency option: + +- A Cortex-A7 @ 650 MHz +- C Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz +- D Cortex-A7 @ 900 MHz +- F Secure Boot + HW Crypto + Cortex-A7 @ 900 MHz + +STM32MP15 Versions +~~~~~~~~~~~~~~~~~~ +The STM32MP15 series is available in 3 different lines which are pin-to-pin compatible: + +- STM32MP157: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz, 3D GPU, DSI display interface and CAN FD +- STM32MP153: Dual Cortex-A7 cores, Cortex-M4 core @ 209 MHz and CAN FD +- STM32MP151: Single Cortex-A7 core, Cortex-M4 core @ 209 MHz + +Each line comes with a security option (cryptography & secure boot) and a Cortex-A frequency option: + +- A Basic + Cortex-A7 @ 650 MHz +- C Secure Boot + HW Crypto + Cortex-A7 @ 650 MHz +- D Basic + Cortex-A7 @ 800 MHz +- F Secure Boot + HW Crypto + Cortex-A7 @ 800 MHz + +The `STM32MP1 part number codification`_ page gives more information about part numbers. + +Design +------ +The STM32MP1 resets in the ROM code of the Cortex-A7. +The primary boot core (core 0) executes the boot sequence while +secondary boot core (core 1) is kept in a holding pen loop. +The ROM code boot sequence loads the TF-A binary image from boot device +to embedded SRAM. + +The TF-A image must be properly formatted with a STM32 header structure +for ROM code is able to load this image. +Tool stm32image can be used to prepend this header to the generated TF-A binary. + +Boot with FIP +~~~~~~~~~~~~~ +The use of FIP is now the recommended way to boot STM32MP1 platform. +Only BL2 (with STM32 header) is loaded by ROM code. The other binaries are +inside the FIP binary: BL32 (SP_min or OP-TEE), U-Boot and their respective +device tree blobs. + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +Although still supported, this way of booting is not recommended. +Pease use FIP instead. +At compilation step, BL2, BL32 and DTB file are linked together in a single +binary. The stm32image tool is also generated and the header is added to TF-A +binary. This binary file with header is named tf-a-stm32mp157c-ev1.stm32. +It can then be copied in the first partition of the boot device. + + +Memory mapping +~~~~~~~~~~~~~~ + +:: + + 0x00000000 +-----------------+ + | | ROM + 0x00020000 +-----------------+ + | | + | ... | + | | + 0x2FFC0000 +-----------------+ \ + | BL32 DTB | | + 0x2FFC5000 +-----------------+ | + | BL32 | | + 0x2FFDF000 +-----------------+ | + | ... | | + 0x2FFE3000 +-----------------+ | + | BL2 DTB | | Embedded SRAM + 0x2FFEA000 +-----------------+ | + | BL2 | | + 0x2FFFF000 +-----------------+ | + | SCMI mailbox | | + 0x30000000 +-----------------+ / + | | + | ... | + | | + 0x40000000 +-----------------+ + | | + | | Devices + | | + 0xC0000000 +-----------------+ \ + | | | + 0xC0100000 +-----------------+ | + | BL33 | | Non-secure RAM (DDR) + | ... | | + | | | + 0xFFFFFFFF +-----------------+ / + + +Boot sequence +~~~~~~~~~~~~~ + +ROM code -> BL2 (compiled with BL2_AT_EL3) -> BL32 (SP_min) -> BL33 (U-Boot) + +or if Op-TEE is used: + +ROM code -> BL2 (compiled with BL2_AT_EL3) -> OP-TEE -> BL33 (U-Boot) + + +Build Instructions +------------------ +Boot media(s) supported by BL2 must be specified in the build command. +Available storage medias are: + +- ``STM32MP_SDMMC`` +- ``STM32MP_EMMC`` +- ``STM32MP_RAW_NAND`` +- ``STM32MP_SPI_NAND`` +- ``STM32MP_SPI_NOR`` + +Serial boot devices: + +- ``STM32MP_UART_PROGRAMMER`` +- ``STM32MP_USB_PROGRAMMER`` + + +Other configuration flags: + +- | ``DTB_FILE_NAME``: to precise board device-tree blob to be used. + | Default: stm32mp157c-ev1.dtb +- | ``STM32MP_EARLY_CONSOLE``: to enable early traces before clock driver is setup. + | Default: 0 (disabled) +- | ``STM32MP_UART_BAUDRATE``: to select UART baud rate. + | Default: 115200 +- | ``STM32_TF_VERSION``: to manage BL2 monotonic counter. + | Default: 0 +- | ``STM32MP13``: to select STM32MP13 variant configuration. + | Default: 0 +- | ``STM32MP15``: to select STM32MP15 variant configuration. + | Default: 1 + + +Boot with FIP +~~~~~~~~~~~~~ +You need to build BL2, BL32 (SP_min or OP-TEE) and BL33 (U-Boot) before building FIP binary. + +U-Boot +______ + +.. code:: bash + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + +OP-TEE (optional) +_________________ + +.. code:: bash + + cd + make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \ + CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts + + +TF-A BL32 (SP_min) +__________________ +If you choose not to use OP-TEE, you can use TF-A SP_min. +To build TF-A BL32, and its device tree file: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min DTB_FILE_NAME=stm32mp157c-ev1.dtb bl32 dtbs + +TF-A BL2 +________ +To build TF-A BL2 with its STM32 header for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb STM32MP_SDMMC=1 + +For other boot devices, you have to replace STM32MP_SDMMC in the previous command +with the desired device flag. + +This BL2 is independent of the BL32 used (SP_min or OP-TEE) + + +FIP +___ +With BL32 SP_min: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + BL33=/u-boot-nodtb.bin \ + BL33_CFG=/u-boot.dtb \ + fip + +With OP-TEE: + +.. code:: bash + + make CROSS_COMPILE=arm-none-eabi- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=optee \ + DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + BL33=/u-boot-nodtb.bin \ + BL33_CFG=/u-boot.dtb \ + BL32=/tee-header_v2.bin \ + BL32_EXTRA1=/tee-pager_v2.bin + BL32_EXTRA2=/tee-pageable_v2.bin + fip + + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +You need to add the following flag to the make command: +``STM32MP_USE_STM32IMAGE=1`` + +To build with SP_min and support for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=sp_min STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + STM32MP_USE_STM32IMAGE=1 + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + +To build TF-A with OP-TEE support for SD-card boot: + +.. code:: bash + + make CROSS_COMPILE=arm-linux-gnueabihf- PLAT=stm32mp1 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + AARCH32_SP=optee STM32MP_SDMMC=1 DTB_FILE_NAME=stm32mp157c-ev1.dtb \ + STM32MP_USE_STM32IMAGE=1 + + cd + make CROSS_COMPILE=arm-linux-gnueabihf- ARCH=arm PLATFORM=stm32mp1 \ + CFG_EMBED_DTB_SOURCE_FILE=stm32mp157c-ev1.dts + + cd + make stm32mp15_trusted_defconfig + make DEVICE_TREE=stm32mp157c-ev1 all + + +The following build options are supported: + +- ``ENABLE_STACK_PROTECTOR``: To enable the stack protection. + + +Populate SD-card +---------------- + +Boot with FIP +~~~~~~~~~~~~~ +The SD-card has to be formatted with GPT. +It should contain at least those partitions: + +- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary (BL2) +- fip: which contains the FIP binary + +Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. + +STM32IMAGE bootchain +~~~~~~~~~~~~~~~~~~~~ +The SD-card has to be formatted with GPT. +It should contain at least those partitions: + +- fsbl: to copy the tf-a-stm32mp157c-ev1.stm32 binary +- ssbl: to copy the u-boot.stm32 binary + +Usually, two copies of fsbl are used (fsbl1 and fsbl2) instead of one partition fsbl. + +OP-TEE artifacts go into separate partitions as follows: + +- teeh: tee-header_v2.stm32 +- teed: tee-pageable_v2.stm32 +- teex: tee-pager_v2.stm32 + + +.. _STM32MP1 Series: https://www.st.com/en/microcontrollers-microprocessors/stm32mp1-series.html +.. _STM32MP1 part number codification: https://wiki.st.com/stm32mpu/wiki/STM32MP15_microprocessor#Part_number_codification diff --git a/arm-trusted-firmware/docs/plat/synquacer.rst b/arm-trusted-firmware/docs/plat/synquacer.rst new file mode 100644 index 0000000..dd29d29 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/synquacer.rst @@ -0,0 +1,117 @@ +Socionext Synquacer +=================== + +Socionext's Synquacer SC2A11 is a multi-core processor with 24 cores of Arm +Cortex-A53. The Developerbox, of 96boards, is a platform that contains this +processor. This port of the Trusted Firmware only supports this platform at +the moment. + +More information are listed in `link`_. + +How to build +------------ + +Code Locations +~~~~~~~~~~~~~~ + +- Trusted Firmware-A: + `link `__ + +- edk2: + `link `__ + +- edk2-platforms: + `link `__ + +- edk2-non-osi: + `link `__ + +Boot Flow +~~~~~~~~~ + +SCP firmware --> TF-A BL31 --> UEFI(edk2) + +Build Procedure +~~~~~~~~~~~~~~~ + +- Firstly, in addition to the “normal†build tools you will also need a + few specialist tools. On a Debian or Ubuntu operating system try: + + .. code:: shell + + sudo apt install acpica-tools device-tree-compiler uuid-dev + +- Secondly, create a new working directory and store the absolute path to this + directory in an environment variable, WORKSPACE. It does not matter where + this directory is created but as an example: + + .. code:: shell + + export WORKSPACE=$HOME/build/developerbox-firmware + mkdir -p $WORKSPACE + +- Run the following commands to clone the source code: + + .. code:: shell + + cd $WORKSPACE + git clone https://github.com/ARM-software/arm-trusted-firmware -b master + git clone https://github.com/tianocore/edk2.git -b master + git clone https://github.com/tianocore/edk2-platforms.git -b master + git clone https://github.com/tianocore/edk2-non-osi.git -b master + +- Build ATF: + + .. code:: shell + + cd $WORKSPACE/arm-trusted-firmware + make -j`nproc` PLAT=synquacer PRELOADED_BL33_BASE=0x8200000 bl31 fiptool + tools/fiptool/fiptool create \ + --tb-fw ./build/synquacer/release/bl31.bin \ + --soc-fw ./build/synquacer/release/bl31.bin \ + --scp-fw ./build/synquacer/release/bl31.bin \ + ../edk2-non-osi/Platform/Socionext/DeveloperBox/fip_all_arm_tf.bin + +- Build EDK2: + + .. code:: shell + + cd $WORKSPACE + export PACKAGES_PATH=$WORKSPACE/edk2:$WORKSPACE/edk2-platforms:$WORKSPACE/edk2-non-osi + export ACTIVE_PLATFORM="Platform/Socionext/DeveloperBox/DeveloperBox.dsc" + export GCC5_AARCH64_PREFIX=aarch64-linux-gnu- + unset ARCH + + . edk2/edksetup.sh + make -C edk2/BaseTools + + build -p $ACTIVE_PLATFORM -b RELEASE -a AARCH64 -t GCC5 -n `nproc` -D DO_X86EMU=TRUE + +- The firmware image, which comprises the option ROM, ARM trusted firmware and + EDK2 itself, can be found $WORKSPACE/../Build/DeveloperBox/RELEASE_GCC5/FV/. + Use SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap for UEFI capsule update and + SPI_NOR_IMAGE.fd for the serial flasher. + + Note #1: -t GCC5 can be loosely translated as “enable link-time-optimizationâ€; + any version of gcc >= 5 will support this feature and may be used to build EDK2. + + Note #2: Replace -b RELEASE with -b DEBUG to build a debug. + +Install the System Firmware +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +- Providing your Developerbox is fully working and has on operating system + installed then you can adopt your the newly compiled system firmware using + the capsule update method:. + + .. code:: shell + + sudo apt install fwupdate + sudo fwupdate --apply {50b94ce5-8b63-4849-8af4-ea479356f0e3} \ + SYNQUACERFIRMWAREUPDATECAPSULEFMPPKCS7.Cap + sudo reboot + +- Alternatively you can install SPI_NOR_IMAGE.fd using the `board recovery method`_. + +.. _link: https://www.96boards.org/product/developerbox/ +.. _board recovery method: https://www.96boards.org/documentation/enterprise/developerbox/installation/board-recovery.md.html diff --git a/arm-trusted-firmware/docs/plat/ti-k3.rst b/arm-trusted-firmware/docs/plat/ti-k3.rst new file mode 100644 index 0000000..4843227 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/ti-k3.rst @@ -0,0 +1,57 @@ +Texas Instruments K3 +==================== + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Texas Instruments K3 SoCs. + +Boot Flow +--------- + +:: + + R5(U-Boot) --> TF-A BL31 --> BL32(OP-TEE) --> TF-A BL31 --> BL33(U-Boot) --> Linux + \ + Optional direct to Linux boot + \ + --> BL33(Linux) + +Texas Instruments K3 SoCs contain an R5 processor used as the boot master, it +loads the needed images for A53 startup, because of this we do not need BL1 or +BL2 TF-A stages. + +Build Instructions +------------------ + +https://github.com/ARM-software/arm-trusted-firmware.git + +TF-A: + +.. code:: shell + + make CROSS_COMPILE=aarch64-linux-gnu- PLAT=k3 SPD=opteed all + +OP-TEE: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE64=aarch64-linux-gnu- PLATFORM=k3 CFG_ARM64_core=y all + +R5 U-Boot: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- am65x_evm_r5_defconfig + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- SYSFW= + +A53 U-Boot: + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- am65x_evm_a53_defconfig + make ARCH=arm CROSS_COMPILE=aarch64-linux-gnu- ATF= TEE= + +Deploy Images +------------- + +.. code:: shell + + cp tiboot3.bin tispl.bin u-boot.img /sdcard/boot/ diff --git a/arm-trusted-firmware/docs/plat/warp7.rst b/arm-trusted-firmware/docs/plat/warp7.rst new file mode 100644 index 0000000..f98a76f --- /dev/null +++ b/arm-trusted-firmware/docs/plat/warp7.rst @@ -0,0 +1,210 @@ +NXP i.MX7 WaRP7 +=============== + +The Trusted Firmware-A port for the i.MX7Solo WaRP7 implements BL2 at EL3. +The i.MX7S contains a BootROM with a High Assurance Boot (HAB) functionality. +This functionality provides a mechanism for establishing a root-of-trust from +the reset vector to the command-line in user-space. + +Boot Flow +--------- + +BootROM --> TF-A BL2 --> BL32(OP-TEE) --> BL33(U-Boot) --> Linux + +In the WaRP7 port we encapsulate OP-TEE, DTB and U-Boot into a FIP. This FIP is +expected and required + +Build Instructions +------------------ + +We need to use a file generated by u-boot in order to generate a .imx image the +BootROM will boot. It is therefore _required_ to build u-boot before TF-A and +furthermore it is _recommended_ to use the mkimage in the u-boot/tools directory +to generate the TF-A .imx image. + +U-Boot +~~~~~~ + +https://git.linaro.org/landing-teams/working/mbl/u-boot.git + +.. code:: shell + + git checkout -b rms-atf-optee-uboot linaro-mbl/rms-atf-optee-uboot + make warp7_bl33_defconfig; + make u-boot.imx arch=ARM CROSS_COMPILE=arm-linux-gnueabihf- + +OP-TEE +~~~~~~ + +https://github.com/OP-TEE/optee_os.git + +.. code:: shell + + make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- PLATFORM=imx PLATFORM_FLAVOR=mx7swarp7 ARCH=arm CFG_PAGEABLE_ADDR=0 CFG_DT_ADDR=0x83000000 CFG_NS_ENTRY_ADDR=0x87800000 + +TF-A +~~~~ + +https://github.com/ARM-software/arm-trusted-firmware.git + +The following commands assume that a directory exits in the top-level TFA build +directory "fiptool_images". "fiptool_images" contains + +- u-boot.bin + The binary output from the u-boot instructions above + +- tee-header_v2.bin +- tee-pager_v2.bin +- tee-pageable_v2.bin + Binary outputs from the previous OPTEE build steps + +It is also assumed copy of mbedtls is available on the path path ../mbedtls + https://github.com/ARMmbed/mbedtls.git + At the time of writing HEAD points to 0592ea772aee48ca1e6d9eb84eca8e143033d973 + +.. code:: shell + + mkdir fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-header_v2.bin fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-pager_v2.bin fiptool_images + cp /path/to/optee/out/arm-plat-imx/core/tee-pageable_v2.bin fiptool_images + + make CROSS_COMPILE=${CROSS_COMPILE} PLAT=warp7 ARCH=aarch32 ARM_ARCH_MAJOR=7 \ + ARM_CORTEX_A7=yes AARCH32_SP=optee PLAT_WARP7_UART=1 GENERATE_COT=1 \ + TRUSTED_BOARD_BOOT=1 USE_TBBR_DEFS=1 MBEDTLS_DIR=../mbedtls \ + NEED_BL32=yes BL32=fiptool_images/tee-header_v2.bin \ + BL32_EXTRA1=fiptool_images/tee-pager_v2.bin \ + BL32_EXTRA2=fiptool_images/tee-pageable_v2.bin \ + BL33=fiptool_images/u-boot.bin certificates all + + /path/to/u-boot/tools/mkimage -n /path/to/u-boot/u-boot.cfgout -T imximage -e 0x9df00000 -d ./build/warp7/debug/bl2.bin ./build/warp7/debug/bl2.bin.imx + +FIP +~~~ + +.. code:: shell + + cp /path/to/uboot/u-boot.bin fiptool_images + cp /path/to/linux/arch/boot/dts/imx7s-warp.dtb fiptool_images + + tools/cert_create/cert_create -n --rot-key "build/warp7/debug/rot_key.pem" \ + --tfw-nvctr 0 \ + --ntfw-nvctr 0 \ + --trusted-key-cert fiptool_images/trusted-key-cert.key-crt \ + --tb-fw=build/warp7/debug/bl2.bin \ + --tb-fw-cert fiptool_images/trusted-boot-fw.key-crt\ + --tos-fw fiptool_images/tee-header_v2.bin \ + --tos-fw-cert fiptool_images/tee-header_v2.bin.crt \ + --tos-fw-key-cert fiptool_images/tee-header_v2.bin.key-crt \ + --tos-fw-extra1 fiptool_images/tee-pager_v2.bin \ + --tos-fw-extra2 fiptool_images/tee-pageable_v2.bin \ + --nt-fw fiptool_images/u-boot.bin \ + --nt-fw-cert fiptool_images/u-boot.bin.crt \ + --nt-fw-key-cert fiptool_images/u-boot.bin.key-crt \ + --hw-config fiptool_images/imx7s-warp.dtb + + tools/fiptool/fiptool create --tos-fw fiptool_images/tee-header_v2.bin \ + --tos-fw-extra1 fiptool_images/tee-pager_v2.bin \ + --tos-fw-extra2 fiptool_images/tee-pageable_v2.bin \ + --nt-fw fiptool_images/u-boot.bin \ + --hw-config fiptool_images/imx7s-warp.dtb \ + --tos-fw-cert fiptool_images/tee-header_v2.bin.crt \ + --tos-fw-key-cert fiptool_images/tee-header_v2.bin.key-crt \ + --nt-fw-cert fiptool_images/u-boot.bin.crt \ + --nt-fw-key-cert fiptool_images/u-boot.bin.key-crt \ + --trusted-key-cert fiptool_images/trusted-key-cert.key-crt \ + --tb-fw-cert fiptool_images/trusted-boot-fw.key-crt warp7.fip + +Deploy Images +------------- + +First place the WaRP7 into UMS mode in u-boot this should produce an entry in +/dev like /dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 + +.. code:: shell + + => ums 0 mmc 0 + +Next flash bl2.imx and warp7.fip + +bl2.imx is flashed @ 1024 bytes +warp7.fip is flash @ 1048576 bytes + +.. code:: shell + + sudo dd if=bl2.bin.imx of=/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 bs=512 seek=2 conv=notrunc + # Offset is 1MB 1048576 => 1048576 / 512 = 2048 + sudo dd if=./warp7.fip of=/dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0 bs=512 seek=2048 conv=notrunc + +Remember to umount the USB device pefore proceeding + +.. code:: shell + + sudo umount /dev/disk/by-id/usb-Linux_UMS_disk_0_WaRP7-0xf42400d3000001d4-0\:0* + + +Signing BL2 +----------- + +A further step is to sign BL2. + +The image_sign.sh and bl2_sign.csf files alluded to blow are available here. + +https://github.com/bryanodonoghue/atf-code-signing + +It is suggested you use this script plus the example CSF file in order to avoid +hard-coding data into your CSF files. + +Download both "image_sign.sh" and "bl2_sign.csf" to your +arm-trusted-firmware top-level directory. + +.. code:: shell + + #!/bin/bash + SIGN=image_sign.sh + TEMP=`pwd`/temp + BL2_CSF=bl2_sign.csf + BL2_IMX=bl2.bin.imx + CST_PATH=/path/to/cst-2.3.2 + CST_BIN=${CST_PATH}/linux64/cst + + #Remove temp + rm -rf ${TEMP} + mkdir ${TEMP} + + # Generate IMX header + /path/to/u-boot/tools/mkimage -n u-boot.cfgout.warp7 -T imximage -e 0x9df00000 -d ./build/warp7/debug/bl2.bin ./build/warp7/debug/bl2.bin.imx > ${TEMP}/${BL2_IMX}.log + + # Copy required items to $TEMP + cp build/warp7/debug/bl2.bin.imx ${TEMP} + cp ${CST_PATH}/keys/* ${TEMP} + cp ${CST_PATH}/crts/* ${TEMP} + cp ${BL2_CSF} ${TEMP} + + # Generate signed BL2 image + ./${SIGN} image_sign_mbl_binary ${TEMP} ${BL2_CSF} ${BL2_IMX} ${CST_BIN} + + # Copy signed BL2 to top-level directory + cp ${TEMP}/${BL2_IMX}-signed . + cp ${BL2_RECOVER_CSF} ${TEMP} + + +The resulting bl2.bin.imx-signed can replace bl2.bin.imx in the Deploy +Images section above, once done. + +Suggested flow for verifying. + +1. Followed all previous steps above and verify a non-secure ATF boot +2. Down the NXP Code Singing Tool +3. Generate keys +4. Program the fuses on your board +5. Replace bl2.bin.imx with bl2.bin.imx-signed +6. Verify inside u-boot that "hab_status" shows no events +7. Subsequently close your board. + +If you have HAB events @ step 6 - do not lock your board. + +To get a good over-view of generating keys and programming the fuses on the +board read "High Assurance Boot for Dummies" by Boundary Devices. + +https://boundarydevices.com/high-assurance-boot-hab-dummies/ diff --git a/arm-trusted-firmware/docs/plat/xilinx-versal.rst b/arm-trusted-firmware/docs/plat/xilinx-versal.rst new file mode 100644 index 0000000..d65b048 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/xilinx-versal.rst @@ -0,0 +1,53 @@ +Xilinx Versal +============= + +Trusted Firmware-A implements the EL3 firmware layer for Xilinx Versal. +The platform only uses the runtime part of TF-A as Xilinx Versal already has a +BootROM (BL1) and PMC FW (BL2). + +BL31 is TF-A. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 +``` + +To build ATF for different platform (supported are "silicon"(default) and "versal_virt") +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal VERSAL_PLATFORM=versal_virt bl31 +``` + +To build TF-A for JTAG DCC console +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 VERSAL_CONSOLE=dcc +``` + +To build TF-A with Straight-Line Speculation(SLS) +```bash +make RESET_TO_BL31=1 CROSS_COMPILE=aarch64-none-elf- PLAT=versal bl31 HARDEN_SLS_ALL=1 +``` + +Xilinx Versal platform specific build options +--------------------------------------------- + +* `VERSAL_ATF_MEM_BASE`: Specifies the base address of the bl31 binary. +* `VERSAL_ATF_MEM_SIZE`: Specifies the size of the memory region of the bl31 binary. +* `VERSAL_BL32_MEM_BASE`: Specifies the base address of the bl32 binary. +* `VERSAL_BL32_MEM_SIZE`: Specifies the size of the memory region of the bl32 binary. + +* `VERSAL_CONSOLE`: Select the console driver. Options: + - `pl011`, `pl011_0`: ARM pl011 UART 0 + - `pl011_1` : ARM pl011 UART 1 + +* `VERSAL_PLATFORM`: Select the platform. Options: + - `versal_virt` : Versal Virtual platform + +# PLM->TF-A Parameter Passing +------------------------------ +The PLM populates a data structure with image information for the TF-A. The TF-A +uses that data to hand off to the loaded images. The address of the handoff +data structure is passed in the ```PMC_GLOBAL_GLOB_GEN_STORAGE4``` register. +The register is free to be used by other software once the TF-A is bringing up +further firmware images. diff --git a/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst b/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst new file mode 100644 index 0000000..79c2535 --- /dev/null +++ b/arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst @@ -0,0 +1,73 @@ +Xilinx Zynq UltraScale+ MPSoC +============================= + +Trusted Firmware-A (TF-A) implements the EL3 firmware layer for Xilinx Zynq +UltraScale + MPSoC. +The platform only uses the runtime part of TF-A as ZynqMP already has a +BootROM (BL1) and FSBL (BL2). + +BL31 is TF-A. +BL32 is an optional Secure Payload. +BL33 is the non-secure world software (U-Boot, Linux etc). + +To build: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp bl31 + +To build bl32 TSP you have to rebuild bl31 too: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp SPD=tspd bl31 bl32 + +To build TF-A for JTAG DCC console: + +.. code:: bash + + make CROSS_COMPILE=aarch64-none-elf- PLAT=zynqmp RESET_TO_BL31=1 bl31 ZYNQMP_CONSOLE=dcc + +ZynqMP platform specific build options +-------------------------------------- + +- ``ZYNQMP_ATF_MEM_BASE``: Specifies the base address of the bl31 binary. +- ``ZYNQMP_ATF_MEM_SIZE``: Specifies the size of the memory region of the bl31 binary. +- ``ZYNQMP_BL32_MEM_BASE``: Specifies the base address of the bl32 binary. +- ``ZYNQMP_BL32_MEM_SIZE``: Specifies the size of the memory region of the bl32 binary. + +- ``ZYNQMP_CONSOLE``: Select the console driver. Options: + + - ``cadence``, ``cadence0``: Cadence UART 0 + - ``cadence1`` : Cadence UART 1 + +FSBL->TF-A Parameter Passing +---------------------------- + +The FSBL populates a data structure with image information for TF-A. TF-A uses +that data to hand off to the loaded images. The address of the handoff data +structure is passed in the ``PMU_GLOBAL.GLOBAL_GEN_STORAGE6`` register. The +register is free to be used by other software once TF-A has brought up +further firmware images. + +Power Domain Tree +----------------- + +The following power domain tree represents the power domain model used by TF-A +for ZynqMP: + +:: + + +-+ + |0| + +-+ + +-------+---+---+-------+ + | | | | + | | | | + v v v v + +-+ +-+ +-+ +-+ + |0| |1| |2| |3| + +-+ +-+ +-+ +-+ + +The 4 leaf power domains represent the individual A53 cores, while resources +common to the cluster are grouped in the power domain on the top. diff --git a/arm-trusted-firmware/docs/process/code-review-guidelines.rst b/arm-trusted-firmware/docs/process/code-review-guidelines.rst new file mode 100644 index 0000000..67a211f --- /dev/null +++ b/arm-trusted-firmware/docs/process/code-review-guidelines.rst @@ -0,0 +1,216 @@ +Code Review Guidelines +====================== + +This document provides TF-A specific details about the project's code review +process. It should be read in conjunction with the `Project Maintenance +Process`_, which it supplements. + + +Why do we do code reviews? +-------------------------- + +The main goal of code reviews is to improve the code quality. By reviewing each +other's code, we can help catch issues that were missed by the author +before they are integrated in the source tree. Different people bring different +perspectives, depending on their past work, experiences and their current use +cases of TF-A in their products. + +Code reviews also play a key role in sharing knowledge within the +community. People with more expertise in one area of the code base can +help those that are less familiar with it. + +Code reviews are meant to benefit everyone through team work. It is not about +unfairly criticizing or belittling the work of any contributor. + + +Good practices +-------------- + +To ensure the code review gives the greatest possible benefit, participants in +the project should: + +- Be considerate of other people and their needs. Participants may be working + to different timescales, and have different priorities. Keep this in + mind - be gracious while waiting for action from others, and timely in your + actions when others are waiting for you. + +- Review other people's patches where possible. The more active reviewers there + are, the more quickly new patches can be reviewed and merged. Contributing to + code review helps everyone in the long run, as it creates a culture of + participation which serves everyone's interests. + + +Guidelines for patch contributors +--------------------------------- + +In addition to the rules outlined in the :ref:`Contributor's Guide`, as a patch +contributor you are expected to: + +- Answer all comments from people who took the time to review your + patches. + +- Be patient and resilient. It is quite common for patches to go through + several rounds of reviews and rework before they get approved, especially + for larger features. + + In the event that a code review takes longer than you would hope for, you + may try the following actions to speed it up: + + - Ping the reviewers on Gerrit or on the mailing list. If it is urgent, + explain why. Please remain courteous and do not abuse this. + + - If one code owner has become unresponsive, ask the other code owners for + help progressing the patch. + + - If there is only one code owner and they have become unresponsive, ask one + of the project maintainers for help. + +- Do the right thing for the project, not the fastest thing to get code merged. + + For example, if some existing piece of code - say a driver - does not quite + meet your exact needs, go the extra mile and extend the code with the missing + functionality you require - as opposed to copying the code into some other + directory to have the freedom to change it in any way. This way, your changes + benefit everyone and will be maintained over time. + + +Guidelines for all reviewers +---------------------------- + +There are no good or bad review comments. If you have any doubt about a patch or +need some clarifications, it's better to ask rather than letting a potential +issue slip. Examples of review comments could be: + +- Questions ("Why do you need to do this?", "What if X happens?") +- Bugs ("I think you need a logical \|\| rather than a bitwise \|.") +- Design issues ("This won't scale well when we introduce feature X.") +- Improvements ("Would it be better if we did Y instead?") + + +Guidelines for code owners +-------------------------- + +Code owners are listed on the :ref:`Project Maintenance` page, +along with the module(s) they look after. + +When reviewing a patch, code owners are expected to check the following: + +- The patch looks good from a technical point of view. For example: + + - The structure of the code is clear. + + - It complies with the relevant standards or technical documentation (where + applicable). + + - It leverages existing interfaces rather than introducing new ones + unnecessarily. + + - It fits well in the design of the module. + + - It adheres to the security model of the project. In particular, it does not + increase the attack surface (e.g. new SMCs) without justification. + +- The patch adheres to the TF-A :ref:`Coding Style`. The CI system should help + catch coding style violations. + +- (Only applicable to generic code) The code is MISRA-compliant (see + :ref:`misra-compliance`). The CI system should help catch violations. + +- Documentation is provided/updated (where applicable). + +- The patch has had an appropriate level of testing. Testing details are + expected to be provided by the patch author. If they are not, do not hesitate + to request this information. + +- All CI automated tests pass. + +If a code owner is happy with a patch, they should give their approval +through the ``Code-Owner-Review+1`` label in Gerrit. If instead, they have +concerns, questions, or any other type of blocking comment, they should set +``Code-Owner-Review-1``. + +Code owners are expected to behave professionally and responsibly. Here are some +guidelines for them: + +- Once you are engaged in a review, make sure you stay involved until the patch + is merged. Rejecting a patch and going away is not very helpful. You are + expected to monitor the patch author's answers to your review comments, + answer back if needed and review new revisions of their patch. + +- Provide constructive feedback. Just saying, "This is wrong, you should do X + instead." is usually not very helpful. The patch author is unlikely to + understand why you are requesting this change and might feel personally + attacked. + +- Be mindful when reviewing a patch. As a code owner, you are viewed as + the expert for the relevant module. By approving a patch, you are partially + responsible for its quality and the effects it has for all TF-A users. Make + sure you fully understand what the implications of a patch might be. + + +Guidelines for maintainers +-------------------------- + +Maintainers are listed on the :ref:`Project Maintenance` page. + +When reviewing a patch, maintainers are expected to check the following: + +- The general structure of the patch looks good. This covers things like: + + - Code organization. + + - Files and directories, names and locations. + + For example, platform code should be added under the ``plat/`` directory. + + - Naming conventions. + + For example, platform identifiers should be properly namespaced to avoid + name clashes with generic code. + + - API design. + +- Interaction of the patch with other modules in the code base. + +- The patch aims at complying with any standard or technical documentation + that applies. + +- New files must have the correct license and copyright headers. See :ref:`this + paragraph` for more information. The CI system + should help catch files with incorrect or no copyright/license headers. + +- There is no third party code or binary blobs with potential IP concerns. + Maintainers should look for copyright or license notices in code, and use + their best judgement. If they are unsure about a patch, they should ask + other maintainers for help. + +- Generally speaking, new driver code should be placed in the generic + layer. There are cases where a driver has to stay into the platform layer but + this should be the exception, rather than the rule. + +- Existing common drivers (in particular for Arm IPs like the GIC driver) should + not be copied into the platform layer to cater for platform quirks. This + type of code duplication hurts the maintainability of the project. The + duplicate driver is less likely to benefit from bug fixes and future + enhancements. In most cases, it is possible to rework a generic driver to + make it more flexible and fit slightly different use cases. That way, these + enhancements benefit everyone. + +- When a platform specific driver really is required, the burden lies with the + patch author to prove the need for it. A detailed justification should be + posted via the commit message or on the mailing list. + +- Before merging a patch, verify that all review comments have been addressed. + If this is not the case, encourage the patch author and the relevant + reviewers to resolve these together. + +If a maintainer is happy with a patch, they should give their approval +through the ``Maintainer-Review+1`` label in Gerrit. If instead, they have +concerns, questions, or any other type of blocking comment, they should set +``Maintainer-Review-1``. + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* + +.. _Project Maintenance Process: https://developer.trustedfirmware.org/w/collaboration/project-maintenance-process/ diff --git a/arm-trusted-firmware/docs/process/coding-guidelines.rst b/arm-trusted-firmware/docs/process/coding-guidelines.rst new file mode 100644 index 0000000..ef319e4 --- /dev/null +++ b/arm-trusted-firmware/docs/process/coding-guidelines.rst @@ -0,0 +1,474 @@ +Coding Guidelines +================= + +This document provides some additional guidelines to consider when writing +|TF-A| code. These are not intended to be strictly-enforced rules like the +contents of the :ref:`Coding Style`. + +Automatic Editor Configuration +------------------------------ + +Many of the rules given below (such as indentation size, use of tabs, and +newlines) can be set automatically using the `EditorConfig`_ configuration file +in the root of the repository: ``.editorconfig``. With a supported editor, the +rules set out in this file can be automatically applied when you are editing +files in the |TF-A| repository. + +Several editors include built-in support for EditorConfig files, and many others +support its functionality through plugins. + +Use of the EditorConfig file is suggested but is not required. + +.. _automatic-compliance-checking: + +Automatic Compliance Checking +----------------------------- + +To assist with coding style compliance, the project Makefile contains two +targets which both utilise the `checkpatch.pl` script that ships with the Linux +source tree. The project also defines certain *checkpatch* options in the +``.checkpatch.conf`` file in the top-level directory. + +.. note:: + Checkpatch errors will gate upstream merging of pull requests. + Checkpatch warnings will not gate merging but should be reviewed and fixed if + possible. + +To check the entire source tree, you must first download copies of +``checkpatch.pl``, ``spelling.txt`` and ``const_structs.checkpatch`` available +in the `Linux master tree`_ *scripts* directory, then set the ``CHECKPATCH`` +environment variable to point to ``checkpatch.pl`` (with the other 2 files in +the same directory) and build the `checkcodebase` target: + +.. code:: shell + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkcodebase + +To just check the style on the files that differ between your local branch and +the remote master, use: + +.. code:: shell + + make CHECKPATCH=/linux/scripts/checkpatch.pl checkpatch + +If you wish to check your patch against something other than the remote master, +set the ``BASE_COMMIT`` variable to your desired branch. By default, +``BASE_COMMIT`` is set to ``origin/master``. + +Ignored Checkpatch Warnings +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Some checkpatch warnings in the TF codebase are deliberately ignored. These +include: + +- ``**WARNING: line over 80 characters**``: Although the codebase should + generally conform to the 80 character limit this is overly restrictive in some + cases. + +- ``**WARNING: Use of volatile is usually wrong``: see + `Why the “volatile†type class should not be used`_ . Although this document + contains some very useful information, there are several legimate uses of the + volatile keyword within the TF codebase. + +Performance considerations +-------------------------- + +Avoid printf and use logging macros +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +``debug.h`` provides logging macros (for example, ``WARN`` and ``ERROR``) +which wrap ``tf_log`` and which allow the logging call to be compiled-out +depending on the ``make`` command. Use these macros to avoid print statements +being compiled unconditionally into the binary. + +Each logging macro has a numerical log level: + +.. code:: c + + #define LOG_LEVEL_NONE 0 + #define LOG_LEVEL_ERROR 10 + #define LOG_LEVEL_NOTICE 20 + #define LOG_LEVEL_WARNING 30 + #define LOG_LEVEL_INFO 40 + #define LOG_LEVEL_VERBOSE 50 + +By default, all logging statements with a log level ``<= LOG_LEVEL_INFO`` will +be compiled into debug builds and all statements with a log level +``<= LOG_LEVEL_NOTICE`` will be compiled into release builds. This can be +overridden from the command line or by the platform makefile (although it may be +necessary to clean the build directory first). + +For example, to enable ``VERBOSE`` logging on FVP: + +.. code:: shell + + make PLAT=fvp LOG_LEVEL=50 all + +Use const data where possible +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following code: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(struct my_struct *ptr); + + void main(void) + { + struct my_struct x; + x.arg1 = 1; + x.arg2 = 2; + init(&x); + } + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + + void init(const struct my_struct *ptr); + + void main(void) + { + const struct my_struct x = { 1, 2 }; + init(&x); + } + +This allows the linker to put the data in a read-only data section instead of a +writeable data section, which may result in a smaller and faster binary. Note +that this may require dependent functions (``init()`` in the above example) to +have ``const`` arguments, assuming they don't need to modify the data. + +Libc functions that are banned or to be used with caution +--------------------------------------------------------- + +Below is a list of functions that present security risks and either must not be +used (Banned) or are discouraged from use and must be used with care (Caution). + ++------------------------+-----------+--------------------------------------+ +| libc function | Status | Comments | ++========================+===========+======================================+ +| ``strcpy, wcscpy``, | Banned | use strlcpy instead | +| ``strncpy`` | | | ++------------------------+-----------+--------------------------------------+ +| ``strcat, wcscat``, | Banned | use strlcat instead | +| ``strncat`` | | | ++------------------------+-----------+--------------------------------------+ +| ``sprintf, vsprintf`` | Banned | use snprintf, vsnprintf | +| | | instead | ++------------------------+-----------+--------------------------------------+ +| ``snprintf`` | Caution | ensure result fits in buffer | +| | | i.e : snprintf(buf,size...) < size | ++------------------------+-----------+--------------------------------------+ +| ``vsnprintf`` | Caution | inspect va_list match types | +| | | specified in format string | ++------------------------+-----------+--------------------------------------+ +| ``strtok`` | Banned | use strtok_r or strsep instead | ++------------------------+-----------+--------------------------------------+ +| ``strtok_r, strsep`` | Caution | inspect for terminated input buffer | ++------------------------+-----------+--------------------------------------+ +| ``ato*`` | Banned | use equivalent strto* functions | ++------------------------+-----------+--------------------------------------+ +| ``*toa`` | Banned | Use snprintf instead | ++------------------------+-----------+--------------------------------------+ + +The `libc` component in the codebase will not add support for the banned APIs. + +Error handling and robustness +----------------------------- + +Using CASSERT to check for compile time data errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Where possible, use the ``CASSERT`` macro to check the validity of data known at +compile time instead of checking validity at runtime, to avoid unnecessary +runtime code. + +For example, this can be used to check that the assembler's and compiler's views +of the size of an array is the same. + +.. code:: c + + #include + + define MY_STRUCT_SIZE 8 /* Used by assembler source files */ + + struct my_struct { + uint32_t arg1; + uint32_t arg2; + }; + + CASSERT(MY_STRUCT_SIZE == sizeof(struct my_struct), assert_my_struct_size_mismatch); + + +If ``MY_STRUCT_SIZE`` in the above example were wrong then the compiler would +emit an error like this: + +:: + + my_struct.h:10:1: error: size of array ‘assert_my_struct_size_mismatch’ is negative + + +Using assert() to check for programming errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In general, each secure world TF image (BL1, BL2, BL31 and BL32) should be +treated as a tightly integrated package; the image builder should be aware of +and responsible for all functionality within the image, even if code within that +image is provided by multiple entities. This allows us to be more aggressive in +interpreting invalid state or bad function arguments as programming errors using +``assert()``, including arguments passed across platform porting interfaces. +This is in contrast to code in a Linux environment, which is less tightly +integrated and may attempt to be more defensive by passing the error back up the +call stack. + +Where possible, badly written TF code should fail early using ``assert()``. This +helps reduce the amount of untested conditional code. By default these +statements are not compiled into release builds, although this can be overridden +using the ``ENABLE_ASSERTIONS`` build flag. + +Examples: + +- Bad argument supplied to library function +- Bad argument provided by platform porting function +- Internal secure world image state is inconsistent + + +Handling integration errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Each secure world image may be provided by a different entity (for example, a +Trusted Boot vendor may provide the BL2 image, a TEE vendor may provide the BL32 +image and the OEM/SoC vendor may provide the other images). + +An image may contain bugs that are only visible when the images are integrated. +The system integrator may not even have access to the debug variants of all the +images in order to check if asserts are firing. For example, the release variant +of BL1 may have already been burnt into the SoC. Therefore, TF code that detects +an integration error should _not_ consider this a programming error, and should +always take action, even in release builds. + +If an integration error is considered non-critical it should be treated as a +recoverable error. If the error is considered critical it should be treated as +an unexpected unrecoverable error. + +Handling recoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** crash when supplied with bad data from an external +source. For example, data from the normal world or a hardware device. Similarly, +the secure world **must not** crash if it detects a non-critical problem within +itself or the system. It must make every effort to recover from the problem by +emitting a ``WARN`` message, performing any necessary error handling and +continuing. + +Examples: + +- Secure world receives SMC from normal world with bad arguments. +- Secure world receives SMC from normal world at an unexpected time. +- BL31 receives SMC from BL32 with bad arguments. +- BL31 receives SMC from BL32 at unexpected time. +- Secure world receives recoverable error from hardware device. Retrying the + operation may help here. +- Non-critical secure world service is not functioning correctly. +- BL31 SPD discovers minor configuration problem with corresponding SP. + +Handling unrecoverable errors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +In some cases it may not be possible for the secure world to recover from an +error. This situation should be handled in one of the following ways: + +1. If the unrecoverable error is unexpected then emit an ``ERROR`` message and + call ``panic()``. This will end up calling the platform-specific function + ``plat_panic_handler()``. +2. If the unrecoverable error is expected to occur in certain circumstances, + then emit an ``ERROR`` message and call the platform-specific function + ``plat_error_handler()``. + +Cases 1 and 2 are subtly different. A platform may implement +``plat_panic_handler`` and ``plat_error_handler`` in the same way (for example, +by waiting for a secure watchdog to time-out or by invoking an interface on the +platform's power controller to reset the platform). However, +``plat_error_handler`` may take additional action for some errors (for example, +it may set a flag so the platform resets into a different mode). Also, +``plat_panic_handler()`` may implement additional debug functionality (for +example, invoking a hardware breakpoint). + +Examples of unexpected unrecoverable errors: + +- BL32 receives an unexpected SMC response from BL31 that it is unable to + recover from. +- BL31 Trusted OS SPD code discovers that BL2 has not loaded the corresponding + Trusted OS, which is critical for platform operation. +- Secure world discovers that a critical hardware device is an unexpected and + unrecoverable state. +- Secure world receives an unexpected and unrecoverable error from a critical + hardware device. +- Secure world discovers that it is running on unsupported hardware. + +Examples of expected unrecoverable errors: + +- BL1/BL2 fails to load the next image due to missing/corrupt firmware on disk. +- BL1/BL2 fails to authenticate the next image due to an invalid certificate. +- Secure world continuously receives recoverable errors from a hardware device + but is unable to proceed without a valid response. + +Handling critical unresponsiveness +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the secure world is waiting for a response from an external source (for +example, the normal world or a hardware device) which is critical for continued +operation, it must not wait indefinitely. It must have a mechanism (for example, +a secure watchdog) for resetting itself and/or the external source to prevent +the system from executing in this state indefinitely. + +Examples: + +- BL1 is waiting for the normal world to raise an SMC to proceed to the next + stage of the secure firmware update process. +- A Trusted OS is waiting for a response from a proxy in the normal world that + is critical for continued operation. +- Secure world is waiting for a hardware response that is critical for continued + operation. + +Use of built-in *C* and *libc* data types +----------------------------------------- + +The |TF-A| codebase should be kept as portable as possible, especially since +both 64-bit and 32-bit platforms are supported. To help with this, the following +data type usage guidelines should be followed: + +- Where possible, use the built-in *C* data types for variable storage (for + example, ``char``, ``int``, ``long long``, etc) instead of the standard *C99* + types. Most code is typically only concerned with the minimum size of the + data stored, which the built-in *C* types guarantee. + +- Avoid using the exact-size standard *C99* types in general (for example, + ``uint16_t``, ``uint32_t``, ``uint64_t``, etc) since they can prevent the + compiler from making optimizations. There are legitimate uses for them, + for example to represent data of a known structure. When using them in struct + definitions, consider how padding in the struct will work across architectures. + For example, extra padding may be introduced in |AArch32| systems if a struct + member crosses a 32-bit boundary. + +- Use ``int`` as the default integer type - it's likely to be the fastest on all + systems. Also this can be assumed to be 32-bit as a consequence of the + `Procedure Call Standard for the Arm Architecture`_ and the `Procedure Call + Standard for the Arm 64-bit Architecture`_ . + +- Avoid use of ``short`` as this may end up being slower than ``int`` in some + systems. If a variable must be exactly 16-bit, use ``int16_t`` or + ``uint16_t``. + +- Avoid use of ``long``. This is guaranteed to be at least 32-bit but, given + that `int` is 32-bit on Arm platforms, there is no use for it. For integers of + at least 64-bit, use ``long long``. + +- Use ``char`` for storing text. Use ``uint8_t`` for storing other 8-bit data. + +- Use ``unsigned`` for integers that can never be negative (counts, + indices, sizes, etc). TF intends to comply with MISRA "essential type" coding + rules (10.X), where signed and unsigned types are considered different + essential types. Choosing the correct type will aid this. MISRA static + analysers will pick up any implicit signed/unsigned conversions that may lead + to unexpected behaviour. + +- For pointer types: + + - If an argument in a function declaration is pointing to a known type then + simply use a pointer to that type (for example: ``struct my_struct *``). + + - If a variable (including an argument in a function declaration) is pointing + to a general, memory-mapped address, an array of pointers or another + structure that is likely to require pointer arithmetic then use + ``uintptr_t``. This will reduce the amount of casting required in the code. + Avoid using ``unsigned long`` or ``unsigned long long`` for this purpose; it + may work but is less portable. + + - For other pointer arguments in a function declaration, use ``void *``. This + includes pointers to types that are abstracted away from the known API and + pointers to arbitrary data. This allows the calling function to pass a + pointer argument to the function without any explicit casting (the cast to + ``void *`` is implicit). The function implementation can then do the + appropriate casting to a specific type. + + - Avoid pointer arithmetic generally (as this violates MISRA C 2012 rule + 18.4) and especially on void pointers (as this is only supported via + language extensions and is considered non-standard). In TF-A, setting the + ``W`` build flag to ``W=3`` enables the *-Wpointer-arith* compiler flag and + this will emit warnings where pointer arithmetic is used. + + - Use ``ptrdiff_t`` to compare the difference between 2 pointers. + +- Use ``size_t`` when storing the ``sizeof()`` something. + +- Use ``ssize_t`` when returning the ``sizeof()`` something from a function that + can also return an error code; the signed type allows for a negative return + code in case of error. This practice should be used sparingly. + +- Use ``u_register_t`` when it's important to store the contents of a register + in its native size (32-bit in |AArch32| and 64-bit in |AArch64|). This is not a + standard *C99* type but is widely available in libc implementations, + including the FreeBSD version included with the TF codebase. Where possible, + cast the variable to a more appropriate type before interpreting the data. For + example, the following struct in ``ep_info.h`` could use this type to minimize + the storage required for the set of registers: + +.. code:: c + + typedef struct aapcs64_params { + u_register_t arg0; + u_register_t arg1; + u_register_t arg2; + u_register_t arg3; + u_register_t arg4; + u_register_t arg5; + u_register_t arg6; + u_register_t arg7; + } aapcs64_params_t; + +If some code wants to operate on ``arg0`` and knows that it represents a 32-bit +unsigned integer on all systems, cast it to ``unsigned int``. + +These guidelines should be updated if additional types are needed. + +Favor C language over assembly language +--------------------------------------- + +Generally, prefer code written in C over assembly. Assembly code is less +portable, harder to understand, maintain and audit security wise. Also, static +analysis tools generally don't analyze assembly code. + +There are, however, legitimate uses of assembly language. These include: + + - Early boot code executed before the C runtime environment is setup. + + - Exception handling code. + + - Low-level code where the exact sequence of instructions executed on the CPU + matters, such as CPU reset sequences. + + - Low-level code where specific system-level instructions must be used, such + as cache maintenance operations. + +-------------- + +*Copyright (c) 2020, Arm Limited and Contributors. All rights reserved.* + +.. _`Linux master tree`: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/ +.. _`Procedure Call Standard for the Arm Architecture`: https://developer.arm.com/docs/ihi0042/latest/ +.. _`Procedure Call Standard for the Arm 64-bit Architecture`: https://developer.arm.com/docs/ihi0055/latest/ +.. _`EditorConfig`: http://editorconfig.org/ +.. _`Why the “volatile†type class should not be used`: https://www.kernel.org/doc/html/latest/process/volatile-considered-harmful.html +.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx +.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods diff --git a/arm-trusted-firmware/docs/process/coding-style.rst b/arm-trusted-firmware/docs/process/coding-style.rst new file mode 100644 index 0000000..be13b14 --- /dev/null +++ b/arm-trusted-firmware/docs/process/coding-style.rst @@ -0,0 +1,470 @@ +Coding Style +============ + +The following sections outline the |TF-A| coding style for *C* code. The style +is based on the `Linux kernel coding style`_, with a few modifications. + +The style should not be considered *set in stone*. Feel free to provide feedback +and suggestions. + +.. note:: + You will almost certainly find code in the |TF-A| repository that does not + follow the style. The intent is for all code to do so eventually. + +File Encoding +------------- + +The source code must use the **UTF-8** character encoding. Comments and +documentation may use non-ASCII characters when required (e.g. Greek letters +used for units) but code itself is still limited to ASCII characters. + +Newlines must be in **Unix** style, which means that only the Line Feed (``LF``) +character is used to break a line and reset to the first column. + +Language +-------- + +The primary language for comments and naming must be International English. In +cases where there is a conflict between the American English and British English +spellings of a word, the American English spelling is used. + +Exceptions are made when referring directly to something that does not use +international style, such as the name of a company. In these cases the existing +name should be used as-is. + +C Language Standard +------------------- + +The C language mode used for TF-A is *GNU99*. This is the "GNU dialect of ISO +C99", which implies the *ISO C99* standard with GNU extensions. + +Both GCC and Clang compiler toolchains have support for *GNU99* mode, though +Clang does lack support for a small number of GNU extensions. These +missing extensions are rarely used, however, and should not pose a problem. + +.. _misra-compliance: + +MISRA Compliance +---------------- + +TF-A attempts to comply with the `MISRA C:2012 Guidelines`_. Coverity +Static Analysis is used to regularly generate a report of current MISRA defects +and to prevent the addition of new ones. + +It is not possible for the project to follow all MISRA guidelines. We maintain +`a spreadsheet`_ that lists all rules and directives and whether we aim to +comply with them or not. A rationale is given for each deviation. + +.. note:: + Enforcing a rule does not mean that the codebase is free of defects + of that rule, only that they would ideally be removed. + +.. note:: + Third-party libraries are not considered in our MISRA analysis and we do not + intend to modify them to make them MISRA compliant. + +Indentation +----------- + +Use **tabs** for indentation. The use of spaces for indentation is forbidden +except in the case where a term is being indented to a boundary that cannot be +achieved using tabs alone. + +Tab spacing should be set to **8 characters**. + +Trailing whitespace is not allowed and must be trimmed. + +Spacing +------- + +Single spacing should be used around most operators, including: + +- Arithmetic operators (``+``, ``-``, ``/``, ``*``) +- Assignment operators (``=``, ``+=``, etc) +- Boolean operators (``&&``, ``||``) +- Comparison operators (``<``, ``>``, ``==``, etc) + +A space should also be used to separate parentheses and braces when they are not +already separated by a newline, such as for the ``if`` statement in the +following example: + +.. code:: c + + int function_foo(bool bar) + { + if (bar) { + function_baz(); + } + } + +Note that there is no space between the name of a function and the following +parentheses. + +Control statements (``if``, ``for``, ``switch``, ``while``, etc) must be +separated from the following open parenthesis by a single space. The previous +example illustrates this for an ``if`` statement. + +Line Length +----------- + +Line length *should* be at most **80 characters**. This limit does not include +non-printing characters such as the line feed. + +This rule is a *should*, not a must, and it is acceptable to exceed the limit +**slightly** where the readability of the code would otherwise be significantly +reduced. Use your judgement in these cases. + +Blank Lines +----------- + +Functions are usually separated by a single blank line. In certain cases it is +acceptable to use additional blank lines for clarity, if required. + +The file must end with a single newline character. Many editors have the option +to insert this automatically and to trim multiple blank lines at the end of the +file. + +Braces +------ + +Opening Brace Placement +^^^^^^^^^^^^^^^^^^^^^^^ + +Braces follow the **Kernighan and Ritchie (K&R)** style, where the opening brace +is **not** placed on a new line. + +Example for a ``while`` loop: + +.. code:: c + + while (condition) { + foo(); + bar(); + } + +This style applies to all blocks except for functions which, following the Linux +style, **do** place the opening brace on a new line. + +Example for a function: + +.. code:: c + + int my_function(void) + { + int a; + + a = 1; + return a; + } + +Conditional Statement Bodies +^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Where conditional statements (such as ``if``, ``for``, ``while`` and ``do``) are +used, braces must be placed around the statements that form the body of the +conditional. This is the case regardless of the number of statements in the +body. + +.. note:: + This is a notable departure from the Linux coding style that has been + adopted to follow MISRA guidelines more closely and to help prevent errors. + +For example, use the following style: + +.. code:: c + + if (condition) { + foo++; + } + +instead of omitting the optional braces around a single statement: + +.. code:: c + + /* This is violating MISRA C 2012: Rule 15.6 */ + if (condition) + foo++; + +The reason for this is to prevent accidental changes to control flow when +modifying the body of the conditional. For example, at a quick glance it is easy +to think that the value of ``bar`` is only incremented if ``condition`` +evaluates to ``true`` but this is not the case - ``bar`` will always be +incremented regardless of the condition evaluation. If the developer forgets to +add braces around the conditional body when adding the ``bar++;`` statement then +the program execution will not proceed as intended. + +.. code:: c + + /* This is violating MISRA C 2012: Rule 15.6 */ + if (condition) + foo++; + bar++; + +Naming +------ + +Functions +^^^^^^^^^ + +Use lowercase for function names, separating multiple words with an underscore +character (``_``). This is sometimes referred to as *Snake Case*. An example is +given below: + +.. code:: c + + void bl2_arch_setup(void) + { + ... + } + +Local Variables and Parameters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Local variables and function parameters use the same format as function names: +lowercase with underscore separation between multiple words. An example is +given below: + +.. code:: c + + static void set_scr_el3_from_rm(uint32_t type, + uint32_t interrupt_type_flags, + uint32_t security_state) + { + uint32_t flag, bit_pos; + + ... + + } + +Preprocessor Macros +^^^^^^^^^^^^^^^^^^^ + +Identifiers that are defined using preprocessor macros are written in all +uppercase text. + +.. code:: c + + #define BUFFER_SIZE_BYTES 64 + +Function Attributes +------------------- + +Place any function attributes after the function type and before the function +name. + +.. code:: c + + void __init plat_arm_interconnect_init(void); + +Alignment +--------- + +Alignment should be performed primarily with tabs, adding spaces if required to +achieve a granularity that is smaller than the tab size. For example, with a tab +size of eight columns it would be necessary to use one tab character and two +spaces to indent text by ten columns. + +Switch Statement Alignment +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +When using ``switch`` statements, align each ``case`` statement with the +``switch`` so that they are in the same column. + +.. code:: c + + switch (condition) { + case A: + foo(); + case B: + bar(); + default: + baz(); + } + +Pointer Alignment +^^^^^^^^^^^^^^^^^ + +The reference and dereference operators (ampersand and *pointer star*) must be +aligned with the name of the object on which they are operating, as opposed to +the type of the object. + +.. code:: c + + uint8_t *foo; + + foo = &bar; + + +Comments +-------- + +The general rule for comments is that the double-slash style of comment (``//``) +is not allowed. Examples of the allowed comment formats are shown below: + +.. code:: c + + /* + * This example illustrates the first allowed style for multi-line comments. + * + * Blank lines within multi-lines are allowed when they add clarity or when + * they separate multiple contexts. + * + */ + +.. code:: c + + /************************************************************************** + * This is the second allowed style for multi-line comments. + * + * In this style, the first and last lines use asterisks that run the full + * width of the comment at its widest point. + * + * This style can be used for additional emphasis. + * + *************************************************************************/ + +.. code:: c + + /* Single line comments can use this format */ + +.. code:: c + + /*************************************************************************** + * This alternative single-line comment style can also be used for emphasis. + **************************************************************************/ + +Headers and inclusion +--------------------- + +Header guards +^^^^^^^^^^^^^ + +For a header file called "some_driver.h" the style used by |TF-A| is: + +.. code:: c + + #ifndef SOME_DRIVER_H + #define SOME_DRIVER_H + +
+ + #endif /* SOME_DRIVER_H */ + +Include statement ordering +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +All header files that are included by a source file must use the following, +grouped ordering. This is to improve readability (by making it easier to quickly +read through the list of headers) and maintainability. + +#. *System* includes: Header files from the standard *C* library, such as + ``stddef.h`` and ``string.h``. + +#. *Project* includes: Header files under the ``include/`` directory within + |TF-A| are *project* includes. + +#. *Platform* includes: Header files relating to a single, specific platform, + and which are located under the ``plat/`` directory within + |TF-A|, are *platform* includes. + +Within each group, ``#include`` statements must be in alphabetical order, +taking both the file and directory names into account. + +Groups must be separated by a single blank line for clarity. + +The example below illustrates the ordering rules using some contrived header +file names; this type of name reuse should be otherwise avoided. + +.. code:: c + + #include + + #include + #include + #include + #include + + #include "a_header.h" + +Include statement variants +^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Two variants of the ``#include`` directive are acceptable in the |TF-A| +codebase. Correct use of the two styles improves readability by suggesting the +location of the included header and reducing ambiguity in cases where generic +and platform-specific headers share a name. + +For header files that are in the same directory as the source file that is +including them, use the ``"..."`` variant. + +For header files that are **not** in the same directory as the source file that +is including them, use the ``<...>`` variant. + +Example (bl1_fwu.c): + +.. code:: c + + #include + #include + #include + + #include "bl1_private.h" + +Typedefs +-------- + +Avoid anonymous typedefs of structs/enums in headers +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For example, the following definition: + +.. code:: c + + typedef struct { + int arg1; + int arg2; + } my_struct_t; + + +is better written as: + +.. code:: c + + struct my_struct { + int arg1; + int arg2; + }; + +This allows function declarations in other header files that depend on the +struct/enum to forward declare the struct/enum instead of including the +entire header: + +.. code:: c + + struct my_struct; + void my_func(struct my_struct *arg); + +instead of: + +.. code:: c + + #include + void my_func(my_struct_t *arg); + +Some TF definitions use both a struct/enum name **and** a typedef name. This +is discouraged for new definitions as it makes it difficult for TF to comply +with MISRA rule 8.3, which states that "All declarations of an object or +function shall use the same names and type qualifiers". + +The Linux coding standards also discourage new typedefs and checkpatch emits +a warning for this. + +Existing typedefs will be retained for compatibility. + +-------------- + +*Copyright (c) 2020, Arm Limited. All rights reserved.* + +.. _`Linux kernel coding style`: https://www.kernel.org/doc/html/latest/process/coding-style.html +.. _`MISRA C:2012 Guidelines`: https://www.misra.org.uk/Activities/MISRAC/tabid/160/Default.aspx +.. _`a spreadsheet`: https://developer.trustedfirmware.org/file/download/lamajxif3w7c4mpjeoo5/PHID-FILE-fp7c7acszn6vliqomyhn/MISRA-and-TF-Analysis-v1.3.ods diff --git a/arm-trusted-firmware/docs/process/commit-style.rst b/arm-trusted-firmware/docs/process/commit-style.rst new file mode 100644 index 0000000..de899ab --- /dev/null +++ b/arm-trusted-firmware/docs/process/commit-style.rst @@ -0,0 +1,162 @@ +Commit Style +============ + +When writing commit messages, please think carefully about the purpose and scope +of the change you are making: describe briefly what the change does, and +describe in detail why it does it. This helps to ensure that changes to the +code-base are transparent and approachable to reviewers, and it allows us to +keep a more accurate changelog. You may use Markdown in commit messages. + +A good commit message provides all the background information needed for +reviewers to understand the intent and rationale of the patch. This information +is also useful for future reference. + +For example: + +- What does the patch do? +- What motivated it? +- What impact does it have? +- How was it tested? +- Have alternatives been considered? Why did you choose this approach over + another one? +- If it fixes an `issue`_, include a reference. + +|TF-A| follows the `Conventional Commits`_ specification. All commits to the +main repository are expected to adhere to these guidelines, so it is +**strongly** recommended that you read at least the `quick summary`_ of the +specification. + +To briefly summarize, commit messages are expected to be of the form: + +.. code:: + + [optional scope]: + + [optional body] + + [optional footer(s)] + +The following example commit message demonstrates the use of the +``refactor`` type and the ``amu`` scope: + +.. code:: + + refactor(amu): factor out register accesses + + This change introduces a small set of register getters and setters to + avoid having to repeatedly mask and shift in complex code. + + Change-Id: Ia372f60c5efb924cd6eeceb75112e635ad13d942 + Signed-off-by: Chris Kay + +The following `types` are permissible and are strictly enforced: + ++--------------+---------------------------------------------------------------+ +| Scope | Description | ++==============+===============================================================+ +| ``feat`` | A new feature | ++--------------+---------------------------------------------------------------+ +| ``fix`` | A bug fix | ++--------------+---------------------------------------------------------------+ +| ``build`` | Changes that affect the build system or external dependencies | ++--------------+---------------------------------------------------------------+ +| ``ci`` | Changes to our CI configuration files and scripts | ++--------------+---------------------------------------------------------------+ +| ``docs`` | Documentation-only changes | ++--------------+---------------------------------------------------------------+ +| ``perf`` | A code change that improves performance | ++--------------+---------------------------------------------------------------+ +| ``refactor`` | A code change that neither fixes a bug nor adds a feature | ++--------------+---------------------------------------------------------------+ +| ``revert`` | Changes that revert a previous change | ++--------------+---------------------------------------------------------------+ +| ``style`` | Changes that do not affect the meaning of the code | +| | (white-space, formatting, missing semi-colons, etc.) | ++--------------+---------------------------------------------------------------+ +| ``test`` | Adding missing tests or correcting existing tests | ++--------------+---------------------------------------------------------------+ +| ``chore`` | Any other change | ++--------------+---------------------------------------------------------------+ + +The permissible `scopes` are more flexible, and we maintain a list of them in +our :download:`changelog configuration file <../../changelog.yaml>`. Scopes in +this file are organized by their changelog section, where each changelog section +has a single scope that is considered to be blessed, and possibly several +deprecated scopes. Please avoid using deprecated scopes. + +While we don't enforce scopes strictly, we do ask that commits use these if they +can, or add their own if no appropriate one exists (see :ref:`Adding Scopes`). + +It's highly recommended that you use the tooling installed by the optional steps +in the :ref:`prerequisites ` guide to validate commit messages +locally, as commitlint reports a live list of the acceptable scopes. + +.. _Adding Scopes: + +Adding Scopes +------------- + +Scopes that are either a) unblessed in the configuration file, or b) do not +exist in the configuration file at all are considered to be deprecated. If you +are adding a new component that does not yet have a designated scope, please +feel free to add one. + +For example, if you are adding or making modifications to `Foo`'s latest and +greatest new platform `Bar`, you would add it to the `Platforms` changelog +section, and the hierarchy should look something like this: + +.. code:: json + + { + "sections": [ + { + "title": "Platforms", + "sections": [ + { + "title": "Foo", + "scopes": ["foo"], + "sections": [ + { + "title": "Bar", + "scopes": ["bar"] + } + ] + } + ] + } + ] + } + +When creating new scopes, try to keep them short and succinct, and use kebab +case (``this-is-kebab-case``). Components with a product name (i.e. most +platforms and some drivers) should use that name (e.g. ``gic600ae``, +``flexspi``, ``stpmic1``), otherwise use a name that uniquely represents the +component (e.g. ``marvell-comphy-3700``, ``rcar3-drivers``, ``a3720-uart``). + +Mandated Trailers +----------------- + +Commits are expected to be signed off with the ``Signed-off-by:`` trailer using +your real name and email address. You can do this automatically by committing +with Git's ``-s`` flag. + +There may be multiple ``Signed-off-by:`` lines depending on the history of the +patch, but one **must** be the committer. More details may be found in the +`Gerrit Signed-off-by Lines guidelines`_. + +Ensure that each commit also has a unique ``Change-Id:`` line. If you have +followed optional steps in the prerequisites to either install the Node.js tools +or clone the repository using the "`Clone with commit-msg hook`" clone method, +then this should be done automatically for you. + +More details may be found in the `Gerrit Change-Ids documentation`_. + +-------------- + +*Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.* + +.. _Conventional Commits: https://www.conventionalcommits.org/en/v1.0.0 +.. _Gerrit Change-Ids documentation: https://review.trustedfirmware.org/Documentation/user-changeid.html +.. _Gerrit Signed-off-by Lines guidelines: https://review.trustedfirmware.org/Documentation/user-signedoffby.html +.. _issue: https://developer.trustedfirmware.org/project/board/1/ +.. _quick summary: https://www.conventionalcommits.org/en/v1.0.0/#summary diff --git a/arm-trusted-firmware/docs/process/contributing.rst b/arm-trusted-firmware/docs/process/contributing.rst new file mode 100644 index 0000000..f80389d --- /dev/null +++ b/arm-trusted-firmware/docs/process/contributing.rst @@ -0,0 +1,304 @@ +Contributor's Guide +******************* + +Getting Started +=============== + +- Make sure you have a Github account and you are logged on both + `developer.trustedfirmware.org`_ and `review.trustedfirmware.org`_. + +- If you plan to contribute a major piece of work, it is usually a good idea to + start a discussion around it on the mailing list. This gives everyone + visibility of what is coming up, you might learn that somebody else is + already working on something similar or the community might be able to + provide some early input to help shaping the design of the feature. + + If you intend to include Third Party IP in your contribution, please mention + it explicitly in the email thread and ensure that the changes that include + Third Party IP are made in a separate patch (or patch series). + +- Clone `Trusted Firmware-A`_ on your own machine as described in + :ref:`prerequisites_get_source`. + +- Create a local topic branch based on the `Trusted Firmware-A`_ ``master`` + branch. + +Making Changes +============== + +- Ensure commits adhere to the the project's :ref:`Commit Style`. + +- Make commits of logical units. See these general `Git guidelines`_ for + contributing to a project. + +- Keep the commits on topic. If you need to fix another bug or make another + enhancement, please address it on a separate topic branch. + +- Split the patch in manageable units. Small patches are usually easier to + review so this will speed up the review process. + +- Avoid long commit series. If you do have a long series, consider whether + some commits should be squashed together or addressed in a separate topic. + +- Follow the :ref:`Coding Style` and :ref:`Coding Guidelines`. + + - Use the checkpatch.pl script provided with the Linux source tree. A + Makefile target is provided for convenience, see :ref:`this + section` for more details. + +- Where appropriate, please update the documentation. + + - Consider whether the :ref:`Porting Guide`, :ref:`Firmware Design` document + or other in-source documentation needs updating. + + - If you are submitting new files that you intend to be the code owner for + (for example, a new platform port), then also update the + :ref:`code owners` file. + + - For topics with multiple commits, you should make all documentation changes + (and nothing else) in the last commit of the series. Otherwise, include + the documentation changes within the single commit. + +.. _copyright-license-guidance: + +- Ensure that each changed file has the correct copyright and license + information. Files that entirely consist of contributions to this project + should have a copyright notice and BSD-3-Clause SPDX license identifier of + the form as shown in :ref:`license`. Files that contain changes to imported + Third Party IP files should retain their original copyright and license + notices. + + For significant contributions you may add your own copyright notice in the + following format: + + :: + + Portions copyright (c) [XXXX-]YYYY, . All rights reserved. + + where XXXX is the year of first contribution (if different to YYYY) and YYYY + is the year of most recent contribution. is your name or your company + name. + +- Ensure that each patch in the patch series compiles in all supported + configurations. Patches which do not compile will not be merged. + +- Please test your changes. As a minimum, ensure that Linux boots on the + Foundation FVP. See :ref:`Arm Fixed Virtual Platforms (FVP)` for more + information. For more extensive testing, consider running the `TF-A Tests`_ + against your patches. + +- Ensure that all CI automated tests pass. Failures should be fixed. They might + block a patch, depending on how critical they are. + +Submitting Changes +================== + +- Submit your changes for review at https://review.trustedfirmware.org + targeting the ``integration`` branch. + +- Add reviewers for your patch: + + - At least one code owner for each module modified by the patch. See the list + of modules and their :ref:`code owners`. + + - At least one maintainer. See the list of :ref:`maintainers`. + + - If some module has no code owner, try to identify a suitable (non-code + owner) reviewer. Running ``git blame`` on the module's source code can + help, as it shows who has been working the most recently on this area of + the code. + + Alternatively, if it is impractical to identify such a reviewer, you might + send an email to the `TF-A mailing list`_ to broadcast your review request + to the community. + + Note that self-reviewing a patch is prohibited, even if the patch author is + the only code owner of a module modified by the patch. Getting a second pair + of eyes on the code is essential to keep up with the quality standards the + project aspires to. + +- The changes will then undergo further review by the designated people. Any + review comments will be made directly on your patch. This may require you to + do some rework. For controversial changes, the discussion might be moved to + the `TF-A mailing list`_ to involve more of the community. + + Refer to the `Gerrit Uploading Changes documentation`_ for more details. + +- The patch submission rules are the following. For a patch to be approved + and merged in the tree, it must get: + + - One ``Code-Owner-Review+1`` for each of the modules modified by the patch. + - A ``Maintainer-Review+1``. + + In the case where a code owner could not be found for a given module, + ``Code-Owner-Review+1`` is substituted by ``Code-Review+1``. + + In addition to these various code review labels, the patch must also get a + ``Verified+1``. This is usually set by the Continuous Integration (CI) bot + when all automated tests passed on the patch. Sometimes, some of these + automated tests may fail for reasons unrelated to the patch. In this case, + the maintainers might (after analysis of the failures) override the CI bot + score to certify that the patch has been correctly tested. + + In the event where the CI system lacks proper tests for a patch, the patch + author or a reviewer might agree to perform additional manual tests + in their review and the reviewer incorporates the review of the additional + testing in the ``Code-Review+1`` or ``Code-Owner-Review+1`` as applicable to + attest that the patch works as expected. Where possible additional tests should + be added to the CI system as a follow up task. For example, for a + platform-dependent patch where the said platform is not available in the CI + system's board farm. + +- When the changes are accepted, the :ref:`maintainers` will integrate them. + + - Typically, the :ref:`maintainers` will merge the changes into the + ``integration`` branch. + + - If the changes are not based on a sufficiently-recent commit, or if they + cannot be automatically rebased, then the :ref:`maintainers` may rebase it + on the ``integration`` branch or ask you to do so. + + - After final integration testing, the changes will make their way into the + ``master`` branch. If a problem is found during integration, the + :ref:`maintainers` will request your help to solve the issue. They may + revert your patches and ask you to resubmit a reworked version of them or + they may ask you to provide a fix-up patch. + +Add CI Configurations +===================== + +- TF-A uses Jenkins tool for Continuous Integration and testing activities. + Various CI Jobs are deployed which run tests on every patch before being + merged. So each of your patches go through a series of checks before they + get merged on to the master branch. Kindly ensure, that everytime you add + new files under your platform, they are covered under the following two sections: + +Coverity Scan +------------- + +- ``Coverity Scan analysis`` is one of the tests we perform on our source code + at regular intervals. We maintain a build script ``tf-cov-make`` which contains the + build configurations of various platforms in order to cover the entire source + code being analysed by Coverity. + +- When you submit your patches for review containing new source files, please + ensure to include them for the ``Coverity Scan analysis`` by adding the + respective build configurations in the ``tf-cov-make`` build script. + +- In this section you find the details on how to append your new build + configurations for Coverity scan analysis illustrated with examples: + +#. We maintain a separate repository named `tf-a-ci-scripts repository`_ + for placing all the test scripts which will be executed by the CI Jobs. + +#. In this repository, ``tf-cov-make`` script is located at + ``tf-a-ci-scripts/script/tf-coverity/tf-cov-make`` + +#. Edit `tf-cov-make`_ script by appending all the possible build configurations with + the specific ``build-flags`` relevant to your platform, so that newly added + source files get built and analysed by Coverity. + +#. For better understanding follow the below specified examples listed in the + ``tf-cov-make`` script. + +.. code:: shell + + Example 1: + #Intel + make PLAT=stratix10 $(common_flags) all + make PLAT=agilex $(common_flags) all + +- In the above example there are two different SoCs ``stratix`` and ``agilex`` + under the Intel platform and the build configurations has been added suitably + to include most of their source files. + +.. code:: shell + + Example 2: + #Hikey + make PLAT=hikey $(common_flags) ${TBB_OPTIONS} ENABLE_PMF=1 all + make PLAT=hikey960 $(common_flags) ${TBB_OPTIONS} all + make PLAT=poplar $(common_flags) all + +- In this case for ``Hikey`` boards additional ``build-flags`` has been included + along with the ``commom_flags`` to cover most of the files relevant to it. + +- Similar to this you can still find many other different build configurations + of various other platforms listed in the ``tf-cov-make`` script. Kindly refer + them and append your build configurations respectively. + +Test Build Configuration (``tf-l1-build-plat``) +----------------------------------------------- + +- Coverity Scan analysis, runs on a daily basis and will not be triggered for + every individual trusted-firmware patch. + +- Considering this, we have other distinguished CI jobs which run a set of test + configurations on every patch, before they are being passed to ``Coverity scan analysis``. + +- ``tf-l1-build-plat`` is the test group, which holds the test configurations + to build all the platforms. So be kind enough to verify that your newly added + files are built as part of one of the existing platform configurations present + in ``tf-l1-build-plat`` test group. + +- In this section you find the details on how to add the appropriate files, + needed to build your newly introduced platform as part of ``tf-l1-build-plat`` + test group, illustrated with an example: + +- Lets consider ``Hikey`` platform: + In the `tf-a-ci-scripts repository`_ we need to add a build configuration file ``hikey-default`` + under tf_config folder, ``tf_config/hikey-default`` listing all the build parameters + relevant to it. + +.. code:: shell + + #Hikey Build Parameters + CROSS_COMPILE=aarch64-none-elf- + PLAT=hikey + +- Further a test-configuration file ``hikey-default:nil`` need to be added under the + test group, ``tf-l1-build-plat`` located at ``tf-a-ci-scripts/group/tf-l1-build-plat``, + to allow the platform to be built as part of this group. + +.. code:: shell + + # + # Copyright (c) 2019-2022 Arm Limited. All rights reserved. + # + # SPDX-License-Identifier: BSD-3-Clause + # + +- As illustrated above, you need to add the similar files supporting your platform. + +Binary Components +================= + +- Platforms may depend on binary components submitted to the `Trusted Firmware + binary repository`_ if they require code that the contributor is unable or + unwilling to open-source. This should be used as a rare exception. +- All binary components must follow the contribution guidelines (in particular + licensing rules) outlined in the `readme.rst `_ file of + the binary repository. +- Binary components must be restricted to only the specific functionality that + cannot be open-sourced and must be linked into a larger open-source platform + port. The majority of the platform port must still be implemented in open + source. Platform ports that are merely a thin wrapper around a binary + component that contains all the actual code will not be accepted. +- Only platform port code (i.e. in the ``plat/`` directory) may rely on + binary components. Generic code must always be fully open-source. + +-------------- + +*Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved.* + +.. _developer.trustedfirmware.org: https://developer.trustedfirmware.org +.. _review.trustedfirmware.org: https://review.trustedfirmware.org +.. _Trusted Firmware-A: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git +.. _Git guidelines: http://git-scm.com/book/ch5-2.html +.. _Gerrit Uploading Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html +.. _TF-A Tests: https://trustedfirmware-a-tests.readthedocs.io +.. _Trusted Firmware binary repository: https://review.trustedfirmware.org/admin/repos/tf-binaries +.. _tf-binaries-readme: https://git.trustedfirmware.org/tf-binaries.git/tree/readme.rst +.. _TF-A mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a +.. _tf-a-ci-scripts repository: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/ +.. _tf-cov-make: https://git.trustedfirmware.org/ci/tf-a-ci-scripts.git/tree/script/tf-coverity/tf-cov-make diff --git a/arm-trusted-firmware/docs/process/faq.rst b/arm-trusted-firmware/docs/process/faq.rst new file mode 100644 index 0000000..daab198 --- /dev/null +++ b/arm-trusted-firmware/docs/process/faq.rst @@ -0,0 +1,80 @@ +Frequently-Asked Questions (FAQ) +================================ + +How do I update my changes? +--------------------------- + +Often it is necessary to update your patch set before it is merged. Refer to the +`Gerrit Upload Patch Set documentation`_ on how to do so. + +If you need to modify an existing patch set with multiple commits, refer to the +`Gerrit Replace Changes documentation`_. + +How long will my changes take to merge into ``integration``? +------------------------------------------------------------ + +This can vary a lot, depending on: + +* How important the patch set is considered by the TF maintainers. Where + possible, you should indicate the required timescales for merging the patch + set and the impact of any delay. Feel free to add a comment to your patch set + to get an estimate of when it will be merged. + +* The quality of the patch set. Patches are likely to be merged more quickly if + they follow the coding guidelines, have already had some code review, and have + been appropriately tested. + +* The impact of the patch set. For example, a patch that changes a key generic + API is likely to receive much greater scrutiny than a local change to a + specific platform port. + +* How much opportunity for external review is required. For example, the TF + maintainers may not wait for external review comments to merge trivial + bug-fixes but may wait up to a week to merge major changes, or ones requiring + feedback from specific parties. + +* How many other patch sets are waiting to be integrated and the risk of + conflict between the topics. + +* If there is a code freeze in place in preparation for the release. Please + refer the :ref:`Release Processes` document for more details. + +* The workload of the TF maintainers. + +How long will it take for my changes to go from ``integration`` to ``master``? +------------------------------------------------------------------------------ + +This depends on how many concurrent patches are being processed at the same +time. In simple cases where all potential regressions have already been tested, +the delay will be less than 1 day. If the TF maintainers are trying to merge +several things over the course of a few days, it might take up to a week. +Typically, it will be 1-2 days. + +The worst case is if the TF maintainers are trying to make a release while also +receiving patches that will not be merged into the release. In this case, the +patches will be merged onto ``integration``, which will temporarily diverge from +the release branch. The ``integration`` branch will be rebased onto ``master`` +after the release, and then ``master`` will be fast-forwarded to ``integration`` +1-2 days later. This whole process could take up 4 weeks. Please refer to the +:ref:`Release Processes` document for code freeze dates. The TF maintainers +will inform the patch owner if this is going to happen. + +It is OK to create a patch based on commits that are only available in +``integration`` or another patch set, rather than ``master``. There is a risk +that the dependency commits will change (for example due to patch set rework or +integration problems). If this happens, the dependent patch will need reworking. + +What are these strange comments in my changes? +---------------------------------------------- + +All the comments from ``ci-bot-user`` are associated with Continuous Integration +infrastructure. The links published on the comment are not currently accessible, +but would be after the CI has been transitioned to `trustedfirmware.org`_. + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _Gerrit Upload Patch Set documentation: https://review.trustedfirmware.org/Documentation/intro-user.html#upload-patch-set +.. _Gerrit Replace Changes documentation: https://review.trustedfirmware.org/Documentation/user-upload.html#push_replace +.. _trustedfirmware.org: https://www.trustedfirmware.org/ diff --git a/arm-trusted-firmware/docs/process/index.rst b/arm-trusted-firmware/docs/process/index.rst new file mode 100644 index 0000000..bba2b40 --- /dev/null +++ b/arm-trusted-firmware/docs/process/index.rst @@ -0,0 +1,17 @@ +Processes & Policies +==================== + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + security + platform-compatibility-policy + commit-style + coding-style + coding-guidelines + contributing + code-review-guidelines + faq + security-hardening diff --git a/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst b/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst new file mode 100644 index 0000000..be1f9ba --- /dev/null +++ b/arm-trusted-firmware/docs/process/platform-compatibility-policy.rst @@ -0,0 +1,36 @@ +Platform Compatibility Policy +============================= + +Introduction +------------ + +This document clarifies the project's policy around compatibility for upstream +platforms. + +Platform compatibility policy +----------------------------- + +Platform compatibility is mainly affected by changes to Platform APIs (as +documented in the :ref:`Porting Guide`), driver APIs (like the GICv3 drivers) or +library interfaces (like xlat_table library). The project will try to maintain +compatibility for upstream platforms. Due to evolving requirements and +enhancements, there might be changes affecting platform compatibility which +means the previous interface needs to be deprecated and a new interface +introduced to replace it. In case the migration to the new interface is trivial, +the contributor of the change is expected to make good effort to migrate the +upstream platforms to the new interface. + +The deprecated interfaces are listed inside :ref:`Release Processes` as well as +the release after which each one will be removed. When an interface is +deprecated, the page must be updated to indicate the release after which the +interface will be removed. This must be at least 1 full release cycle in future. +For non-trivial interface changes, an email should be sent out to the `TF-A +public mailing list`_ to notify platforms that they should migrate away from the +deprecated interfaces. Platforms are expected to migrate before the removal of +the deprecated interface. + +-------------- + +*Copyright (c) 2018-2019, Arm Limited and Contributors. All rights reserved.* + +.. _TF-A public mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a diff --git a/arm-trusted-firmware/docs/process/security-hardening.rst b/arm-trusted-firmware/docs/process/security-hardening.rst new file mode 100644 index 0000000..507046f --- /dev/null +++ b/arm-trusted-firmware/docs/process/security-hardening.rst @@ -0,0 +1,175 @@ +Secure Development Guidelines +============================= + +This page contains guidance on what to check for additional security measures, +including build options that can be modified to improve security or catch issues +early in development. + +Security considerations +----------------------- + +Part of the security of a platform is handling errors correctly, as described in +the previous section. There are several other security considerations covered in +this section. + +Do not leak secrets to the normal world +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **must not** leak secrets to the normal world, for example in +response to an SMC. + +Handling Denial of Service attacks +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The secure world **should never** crash or become unusable due to receiving too +many normal world requests (a *Denial of Service* or *DoS* attack). It should +have a mechanism for throttling or ignoring normal world requests. + +Preventing Secure-world timing information leakage via PMU counters +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +The Secure world needs to implement some defenses to prevent the Non-secure +world from making it leak timing information. In general, higher privilege +levels must defend from those below when the PMU is treated as an attack +vector. + +Refer to the :ref:`Performance Monitoring Unit` guide for detailed information +on the PMU registers. + +Timing leakage attacks from the Non-secure world +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Since the Non-secure world has access to the ``PMCR`` register, it can +configure the PMU to increment counters at any exception level and in both +Secure and Non-secure state. Thus, it attempts to leak timing information from +the Secure world. + +Shown below is an example of such a configuration: + +- ``PMEVTYPER0_EL0`` and ``PMCCFILTR_EL0``: + + - Set ``P`` to ``0``. + - Set ``NSK`` to ``1``. + - Set ``M`` to ``0``. + - Set ``NSH`` to ``0``. + - Set ``SH`` to ``1``. + +- ``PMCNTENSET_EL0``: + + - Set ``P[0]`` to ``1``. + - Set ``C`` to ``1``. + +- ``PMCR_EL0``: + + - Set ``DP`` to ``0``. + - Set ``E`` to ``1``. + +This configuration instructs ``PMEVCNTR0_EL0`` and ``PMCCNTR_EL0`` to increment +at Secure EL1, Secure EL2 (if implemented) and EL3. + +Since the Non-secure world has fine-grained control over where (at which +exception levels) it instructs counters to increment, obtaining event counts +would allow it to carry out side-channel timing attacks against the Secure +world. Examples include Spectre, Meltdown, as well as extracting secrets from +cryptographic algorithms with data-dependent variations in their execution +time. + +Secure world mitigation strategies +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +The ``MDCR_EL3`` register allows EL3 to configure the PMU (among other things). +The `Arm ARM`_ details all of the bit fields in this register, but for the PMU +there are two bits which determine the permissions of the counters: + +- ``SPME`` for the programmable counters. +- ``SCCD`` for the cycle counter. + +Depending on the implemented features, the Secure world can prohibit counting +in AArch64 state via the following: + +- ARMv8.2-Debug not implemented: + + - Prohibit general event counters and the cycle counter: + ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1 && !ExternalSecureNoninvasiveDebugEnabled()``. + + - ``MDCR_EL3.SPME`` resets to ``0``, so by default general events should + not be counted in the Secure world. + - The ``PMCR_EL0.DP`` bit therefore needs to be set to ``1`` when EL3 is + entered and ``PMCR_EL0`` needs to be saved and restored in EL3. + - ``ExternalSecureNoninvasiveDebugEnabled()`` is an authentication + interface which is implementation-defined unless ARMv8.4-Debug is + implemented. The `Arm ARM`_ has detailed information on this topic. + + - The only other way is to disable the ``PMCR_EL0.E`` bit upon entering + EL3, which disables counting altogether. + +- ARMv8.2-Debug implemented: + + - Prohibit general event counters: ``MDCR_EL3.SPME == 0``. + - Prohibit cycle counter: ``MDCR_EL3.SPME == 0 && PMCR_EL0.DP == 1``. + ``PMCR_EL0`` therefore needs to be saved and restored in EL3. + +- ARMv8.5-PMU implemented: + + - Prohibit general event counters: as in ARMv8.2-Debug. + - Prohibit cycle counter: ``MDCR_EL3.SCCD == 1`` + +In Aarch32 execution state the ``MDCR_EL3`` alias is the ``SDCR`` register, +which has some of the bit fields of ``MDCR_EL3``, most importantly the ``SPME`` +and ``SCCD`` bits. + +Build options +------------- + +Several build options can be used to check for security issues. Refer to the +:ref:`Build Options` for detailed information on these. + +- The ``BRANCH_PROTECTION`` build flag can be used to enable Pointer + Authentication and Branch Target Identification. + +- The ``ENABLE_STACK_PROTECTOR`` build flag can be used to identify buffer + overflows. + +- The ``W`` build flag can be used to enable a number of compiler warning + options to detect potentially incorrect code. + + - W=0 (default value) + + The ``Wunused`` with ``Wno-unused-parameter``, ``Wdisabled-optimization`` + and ``Wvla`` flags are enabled. + + The ``Wunused-but-set-variable``, ``Wmaybe-uninitialized`` and + ``Wpacked-bitfield-compat`` are GCC specific flags that are also enabled. + + - W=1 + + Adds ``Wextra``, ``Wmissing-format-attribute``, ``Wmissing-prototypes``, + ``Wold-style-definition`` and ``Wunused-const-variable``. + + - W=2 + + Adds ``Waggregate-return``, ``Wcast-align``, ``Wnested-externs``, + ``Wshadow``, ``Wlogical-op``. + + - W=3 + + Adds ``Wbad-function-cast``, ``Wcast-qual``, ``Wconversion``, ``Wpacked``, + ``Wpointer-arith``, ``Wredundant-decls`` and + ``Wswitch-default``. + + Refer to the GCC or Clang documentation for more information on the individual + options: https://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html and + https://clang.llvm.org/docs/DiagnosticsReference.html. + + NB: The ``Werror`` flag is enabled by default in TF-A and can be disabled by + setting the ``E`` build flag to 0. + +.. rubric:: References + +- `Arm ARM`_ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* + +.. _Arm ARM: https://developer.arm.com/docs/ddi0487/latest diff --git a/arm-trusted-firmware/docs/process/security.rst b/arm-trusted-firmware/docs/process/security.rst new file mode 100644 index 0000000..a3b9971 --- /dev/null +++ b/arm-trusted-firmware/docs/process/security.rst @@ -0,0 +1,89 @@ +Security Handling +================= + +Security Disclosures +-------------------- + +We disclose all security vulnerabilities we find, or are advised about, that are +relevant to Trusted Firmware-A. We encourage responsible disclosure of +vulnerabilities and inform users as best we can about all possible issues. + +We disclose TF-A vulnerabilities as Security Advisories, all of which are listed +at the bottom of this page. Any new ones will, additionally, be announced as +issues in the project's `issue tracker`_ with the ``security-advisory`` tag. You +can receive notification emails for these by watching the "Trusted Firmware-A" +project at https://developer.trustedfirmware.org/. + +Found a Security Issue? +----------------------- + +Although we try to keep TF-A secure, we can only do so with the help of the +community of developers and security researchers. + +.. warning:: + If you think you have found a security vulnerability, please **do not** + report it in the `issue tracker`_ or on the `mailing list`_. Instead, please + follow the `TrustedFirmware.org security incident process`_. + +One of the goals of this process is to ensure providers of products that use +TF-A have a chance to consider the implications of the vulnerability and its +remedy before it is made public. As such, please follow the disclosure plan +outlined in the process. We do our best to respond and fix any issues quickly. + +Afterwards, we encourage you to write-up your findings about the TF-A source +code. + +Attribution +----------- + +We will name and thank you in the :ref:`Change Log & Release Notes` distributed +with the source code and in any published security advisory. + +Security Advisories +------------------- + ++-----------+------------------------------------------------------------------+ +| ID | Title | ++===========+==================================================================+ +| |TFV-1| | Malformed Firmware Update SMC can result in copy of unexpectedly | +| | large data into secure memory | ++-----------+------------------------------------------------------------------+ +| |TFV-2| | Enabled secure self-hosted invasive debug interface can allow | +| | normal world to panic secure world | ++-----------+------------------------------------------------------------------+ +| |TFV-3| | RO memory is always executable at AArch64 Secure EL1 | ++-----------+------------------------------------------------------------------+ +| |TFV-4| | Malformed Firmware Update SMC can result in copy or | +| | authentication of unexpected data in secure memory in AArch32 | +| | state | ++-----------+------------------------------------------------------------------+ +| |TFV-5| | Not initializing or saving/restoring PMCR_EL0 can leak secure | +| | world timing information | ++-----------+------------------------------------------------------------------+ +| |TFV-6| | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities using cache timing side-channels | ++-----------+------------------------------------------------------------------+ +| |TFV-7| | Trusted Firmware-A exposure to cache speculation vulnerability | +| | Variant 4 | ++-----------+------------------------------------------------------------------+ +| |TFV-8| | Not saving x0 to x3 registers can leak information from one | +| | Normal World SMC client to another | ++-----------+------------------------------------------------------------------+ + +.. _issue tracker: https://developer.trustedfirmware.org/project/board/1/ +.. _mailing list: https://lists.trustedfirmware.org/mailman/listinfo/tf-a + +.. |TFV-1| replace:: :ref:`Advisory TFV-1 (CVE-2016-10319)` +.. |TFV-2| replace:: :ref:`Advisory TFV-2 (CVE-2017-7564)` +.. |TFV-3| replace:: :ref:`Advisory TFV-3 (CVE-2017-7563)` +.. |TFV-4| replace:: :ref:`Advisory TFV-4 (CVE-2017-9607)` +.. |TFV-5| replace:: :ref:`Advisory TFV-5 (CVE-2017-15031)` +.. |TFV-6| replace:: :ref:`Advisory TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754)` +.. |TFV-7| replace:: :ref:`Advisory TFV-7 (CVE-2018-3639)` +.. |TFV-8| replace:: :ref:`Advisory TFV-8 (CVE-2018-19440)` + +.. _TrustedFirmware.org security incident process: https://developer.trustedfirmware.org/w/collaboration/security_center/ + +-------------- + +*Copyright (c) 2019-2020, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/requirements.in b/arm-trusted-firmware/docs/requirements.in new file mode 100644 index 0000000..5d771e5 --- /dev/null +++ b/arm-trusted-firmware/docs/requirements.in @@ -0,0 +1,5 @@ +myst-parser==0.15.2 +pip-tools==6.4.0 +sphinx==4.2.0 +sphinx-rtd-theme==1.0.0 +sphinxcontrib-plantuml==0.22 diff --git a/arm-trusted-firmware/docs/requirements.txt b/arm-trusted-firmware/docs/requirements.txt new file mode 100644 index 0000000..03b1189 --- /dev/null +++ b/arm-trusted-firmware/docs/requirements.txt @@ -0,0 +1,91 @@ +# +# This file is autogenerated by pip-compile with python 3.8 +# To update, run: +# +# pip-compile +# +alabaster==0.7.12 + # via sphinx +attrs==21.2.0 + # via markdown-it-py +babel==2.9.1 + # via sphinx +certifi==2021.5.30 + # via requests +charset-normalizer==2.0.4 + # via requests +click==8.0.1 + # via pip-tools +docutils==0.16 + # via + # myst-parser + # sphinx + # sphinx-rtd-theme +idna==3.2 + # via requests +imagesize==1.2.0 + # via sphinx +jinja2==3.0.1 + # via + # myst-parser + # sphinx +markdown-it-py==1.1.0 + # via + # mdit-py-plugins + # myst-parser +markupsafe==2.0.1 + # via jinja2 +mdit-py-plugins==0.2.8 + # via myst-parser +myst-parser==0.15.2 + # via -r requirements.in +packaging==21.0 + # via sphinx +pep517==0.11.0 + # via pip-tools +pip-tools==6.4.0 + # via -r requirements.in +pygments==2.10.0 + # via sphinx +pyparsing==2.4.7 + # via packaging +pytz==2021.1 + # via babel +pyyaml==6.0 + # via myst-parser +requests==2.26.0 + # via sphinx +snowballstemmer==2.1.0 + # via sphinx +sphinx==4.2.0 + # via + # -r requirements.in + # myst-parser + # sphinx-rtd-theme + # sphinxcontrib-plantuml +sphinx-rtd-theme==1.0.0 + # via -r requirements.in +sphinxcontrib-applehelp==1.0.2 + # via sphinx +sphinxcontrib-devhelp==1.0.2 + # via sphinx +sphinxcontrib-htmlhelp==2.0.0 + # via sphinx +sphinxcontrib-jsmath==1.0.1 + # via sphinx +sphinxcontrib-plantuml==0.22 + # via -r requirements.in +sphinxcontrib-qthelp==1.0.3 + # via sphinx +sphinxcontrib-serializinghtml==1.1.5 + # via sphinx +tomli==1.2.1 + # via pep517 +urllib3==1.26.6 + # via requests +wheel==0.37.0 + # via pip-tools + +# The following packages are considered to be unsafe in a requirements file: +# pip +# setuptools diff --git a/arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png b/arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png new file mode 100644 index 0000000000000000000000000000000000000000..e7bff7128fe6abb3341f63622769a0a5b94e8717 GIT binary patch literal 5826 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%0A`RfNs3=B? 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

sp@IveZ_|tpX_msJ|Cpb#;{FV{gt@74# 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

av$QR=;Yq60<{DiVOs96y> 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Ш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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/MMU-600.png b/arm-trusted-firmware/docs/resources/diagrams/MMU-600.png new file mode 100644 index 0000000000000000000000000000000000000000..9cbc2437ee918cf48d3115aaf61a3408f9279d11 GIT binary patch literal 50836 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

1o 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png b/arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png new file mode 100644 index 0000000000000000000000000000000000000000..6006f1c3006b1bd65a64a7f8744698476715b9d2 GIT binary patch literal 73277 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÷FR)}sVq#Sb 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 V4ji`9*#lrc3Qv_~OP;{|{~H&}+I;{3 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png b/arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png new file mode 100644 index 0000000000000000000000000000000000000000..5170960cf7415d3131008e0827f7b4202d4d4e78 GIT binary patch literal 52718 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png b/arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png new file mode 100644 index 0000000000000000000000000000000000000000..d8675e4a3f81b7e8bfedfb9c39c48f7f9b286344 GIT binary patch literal 41796 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg new file mode 100644 index 0000000..c98090f --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg @@ -0,0 +1,2 @@ + +
Interrupt Management Framework
Interrupt Management Framework
Interrupt
Type
[Not supported by viewer]
Interrupt
Interrupt
NS
NS
S-EL1
S-EL1
EL3
EL3
SPD handlers
SPD handlers
Exception Handling Framework
Exception Handling Framework
GIC PMR
GIC PMR
RAS
RAS
SPM
[Not supported by viewer]
SDEI Critical
SDEI Critical
SDEI Normal
SDEI Normal
NS priorities
NS priorities
0xFF
0xFF
0x0
[Not supported by viewer]
Interrupt Priority
[Not supported by viewer]
EHF APIs
EHF APIs
Non-interrupt exceptions use EHF APIs to program GIC PMR to arbitrate priority levels
Non-interrupt exceptions use EHF APIs to program GIC PMR to arbitrate priority levels
Decreasing Priority
Decreasing Priority
Secure Priority levels
Secure Priority levels
\ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml new file mode 100644 index 0000000..db1f91d --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg new file mode 100644 index 0000000..ff58198 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg @@ -0,0 +1,2 @@ + +

<div><br></div>
plat_ea_handler()
plat_ea_handler()
ras_ea_handler()
ras_ea_handler()
ras_interrupt_handler()
ras_interrupt_handler()
Exception Handling Framework
Exception Handling Framework
RAS
priority level handler
[Not supported by viewer]
RAS error records
RAS error records
RAS interrupts array
RAS interrupts array
RAS framework
RAS framework
Iterate and probe
<i>Iterate and probe</i>
Error handler
Error handler
Bisect and lookup
<i>Bisect and lookup</i>
Error handler
Error handler
SER helpers
SER helpers
External Abort
External Abort
Interrupt
[Not supported by viewer]
Interrupt Priority
Interrupt Priority
EHF APIs
EHF APIs
\ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml new file mode 100644 index 0000000..ce6df3a --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml @@ -0,0 +1 @@ +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 \ No newline at end of file diff --git a/arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png b/arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png new file mode 100644 index 0000000000000000000000000000000000000000..605fd9b21d33eaafbf06bafbc4646191baa91093 GIT binary patch literal 53363 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 ZfQ#E+2iHH+{?Y|9(9_k=Wt~$(69BZ~({BI( literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png new file mode 100644 index 0000000000000000000000000000000000000000..0619cf260bad85fbc60b933bfb64df1d55ca6ae4 GIT binary patch literal 86234 zcmc$`bx>Se^fd^9;1b*+cnIze4+{`nLU4C?mjrkB#+~5q?$WrsyE`;8otM0s-#=3` zHBri(uhWFc%Zei-;3GglKp;y>h$=!rKu<$JybFPY0lyNXY_ko1 zfOZg;RE7f&PdLM1@N+yzF;zz;8)HWoJ$oYv6KfkQBYFn|dm|%j2U8ozbEpmh2#Ajm zlA=P&u4yN$E}jXyFK?Igi_{(>Fz}>MaHMgRX8~DT!eYlq^XkuLCG|_c8r4k{ERO4o z%GB#nL~VZ{8ht{MukJzd5V_;wK7M^c`zQJX)H~Qg(4*^4_D=hlm(N*TblUZvgI3ZI z6A~2Kf8$YY?;o6xWPgW!o_sRZe@~{w5T-@{8_k3G2k(AAL8-M`u2)c0oH|Sn4@Xi| zQbLsx`hAA|%%4-m)7`H3nB8vEaANSq$-m#nZ4;7{d_ zuD4qLA}J|ZXu!h4A|WHg&-VWJVg?mN{^u0UQVaig&iDVPQRe<D|we!j-@@k(}p zf|3%Agv2NKGdkD?F}VRezoD{I#OiXU34=@1OI3F#fI6-kCGfNE@+HCu*5JT2EqD-3R&eBB@b18E z84UFuB@a{z52Vmb!lYzT_517L~=6 zj@Gzoe0T!U+Hl3j8A8h%~PAPOZk+W|Oi0LF2^k^DU_|gbM zESIa^;Cs=rT(F`l4pQT!FmOs6t~q|*c*)?cwuDZ9c_%3SN=}_0h^FW&XvDk6eI_L% z*z`7>W4|Y=fa8hpopL4!qr*+%(qc~D60iTlDwR6+7fw`{u6~Tmef1}MHTJP76G&;ieK52L3&m*b4aNjJ2pidr zuv8#>T7=Rpn&*7iCbny-*Lj>*P;7o5do^@y)^Dmg+RYBbOn+{-KO)=Tc0o&5ijM|hEq9m|eLnCJ^ zHj2t;H=DBZED6=AZT`x-t&=&Je`###XT86jqmM1!7IKov@>S&lew_YePexbc{2d|d z1j3gdhHbikq?n`9*~1;q-$Ey@Nj7ff_L&@xwl%TYqs03&hS|?8dr>D^s;t_Y@Z26>2*3ie54DH$^`9z2KnkfGNSLkO!JBT_JSQaebVhW{=RkNw4T$qCV$Ad zX>RA8#We0C=`n$0OndhQ7rf(K^DTBw!J&<-Vx7ya1EOivAcyCw$RA{jSBGI!xAwbJj=C?4+NxVX8Y$w)UG4&Ki-WWocVq z86zx}K5knb_+^R2QUxuTGgYO)&1^ctgeS z9~U6Ulf>d%$_#P#bU6d2X~*gYa3SRS7`APduI?=wK~l6htvq23j8aRlgsA(CdR@v! znxi{D;LK}aP3fe-yvqQUbZAHn5cs*d3_xPFX;0lIPVd>r3Nt0wu`v~+_&AgDC-aIY zMhjbKXbVlo4?Mh>@vFWaI;^sLrpx3<=Mju20H?h+MEbV{;T!%Th4+0#8+9 zUDTM3B8*uO?coP>EzD?+pY_t*K&ONq#}i(~#Zc|P^uHb>S$f5Wl& zmAJUx{9?uBG$UwZNa@Usa;Oy?%owntZXc z{J2*T;duMyM;tG$;f@Z#a6(-svq1#ve5l3&j=fY+VO1usNG)C~7Wh@W9pCvTvgrQa*1|i_0wN+jE_-p*{?pn#9(=5Uv5&FOQVQna%n=KYzE*sc%BgT<^T_ zumh1dvT&BgrFto2B`KQ7=6+-}2ko!M<9y$$L(OGcZcbwMh`df5Hyp!eHTxc}-zk@A z;6siq<6X&Hxn1BX#7zv6ALF7lzu&i!d@t3i0<&X$2rLbT4)=cjx3n0H0b!E*K4#LK{uyg|tcGo{`W*DIp>X7 zmpzozD`e+XQmKX388k%z*$7tIyzeu*O`b*^j9_x&EAX>BoBdXLtH#Am8@HM(k>$pW zMeDT?h?G@fhV@2U)|I9%;eAtH_n@k!In1F%X3*f$8xjod`?qN1CTmpj>6kEaPR&(NnL^j zH_A%{Z&w2;XB@w==D6gg3-Qr&PyN7+<5AMsl%~+MDr$oj@!&qrMYCUErWV$KAfM9W zLL+MTgmzqCxgs+x?zz(_dGB+pAM*1flwDx!kt`mm=%!Z>%=_=1t_KDExwM z$v@Qy9%AE&tz&O5Ii;C!Ge)%hAkZ$;1s$1lDNRdMyQ*on!;O#qw8j>6p&Zyl-RqZ2 zz4&gEy<|g1N9LKtspvh|b_+57{h@LfGuG<;`4-u*I{gjfDCq$;<ngWxW6wR@r@OG_d}9&|YW~h%7RI|YA*7Q$|kI z9EH7V7G2OnWWOWZSW3E_Pf1d2)3xbJo%DCSaX!9))W++^!%)X?F|qhM)dQXA7SQ#+ zmau{v>s))lPJl}-uOHY7*`q)N^;h6Em= z-34Cpm0mBA_HP@1D35>LYrmyC=MarG{>kG)bj&$3QJs_;vG*kv$*&+5)$K(KM@?j$ z6dWjLUvXuDa$QId_qYxWJ#jM1Z-#_W-aQY9)b@)$728w(u#IM-_;*WR3k016ffVU{FcJ zIi`?R3wmmVyD>&^GVrp`ON794SYpTN)d%2CwpE93?uWCU`Q#2R?7i4Ec2uoAtY?n1 zA}Em|7tWe<F;<06hU|#7SU*NZaJ5L!gl8R<|JH3&1hr) zCBN{6I1+a4c56m`I zlB$O(yi?5Ww?SdoZVspM_}v`~4XC7(J0C8$Q5D2~zhPfHk^29Nw9ftJxiPt8{SgEy zye`&-2KM&$2kRYgq`xG7C&WnX|4G;-{?=x{-)a8;K$lB@GW_%VT+v7rxmKlKll2NR z4zf=Z`4XJ<-WnJrvRs+Eh4d5oV50l=FVQ9ZAT>Y7vezpeIUfN`n4_= zZ=O>3=wgR*h4UHrjMm;jaNAAAhb1zD2!*dVysXvH*{0vi2cD$VE2SnK_7(m0myhl9 zk4xn@JBEZPq-h;GFfBbyB;-JR@eq%j<>mQ3Z)_4G^aFI!olk}A)6IAquS^K(0xCE- zHNb_Dj|Pb6YfdCOY$moZ+dfn-PH6cu*rh6{SYo@4yq?jS-xyc>w~Ykos1S?ayY&*H z2;u)|@ptR9QgwidGZExUVp@?*dukE9Dnx`m(}>;!Ge}>iF;{PL50L#|+CR7{qNmPj z5Q^J7;jO}Fg!t*03oF;|&Tr*$OeMD5HQYlMDZ8pPdDoE1Q`t6_?kY8x&-d`K-sF7H{!E)J1pGr8MS^;r zR!*sZqYFHOuma3hBPjhy{c^Gk{BshB^7PO2Umy2z)XCaD+`#CB`BVQlXP zrB#)sn~n=n%{PyO&Ua4drXO#IP<{blJ`EzDwW9d2i&d=mEf|1eaW{MMGX8nPsMzR2 z{a$%}vqsYB@B?|jXumiOgt-mQ^W*Zckr#%6ny+l@oF{7|Ml)EKQzT%C z$~7Q9+iTJ29ox05)Unk!$y>mQvj1R^t2TeHx#ns888y>`o;fU(#s#lYn)-U-1|A93 zN>F4E_}yV8*Wsa6AI)mVpigcV(MP}A#aPy3&+FC0OWos?I%BXh3(HVj055mI6y~;S z#YZOp2*dZ|s_ z?YMCbAR`uh-qxpjyLLJwaG)*5`j7d+@@W+>$IDf4;Q%bM29jga)T76R)W`m7Wukm^ zDsU2+^X|dLG^;EqGE91wYj4QIwtmr5D&A!Nqp>G z;NIdz{97Zu(6aA9zcWcw4z3itEC?O5tasOr|aq_#J@u?9y#lQTy`Vs#g4E!Jh! zu2B_EP{f8fNW?xGAI${grNHDCyG4 z|DZ(;eUEKYpH;W&SUxs*#X-G2sd-jSNIeYYa??28A3q+O7hh`}uonF=jRS<{eDy@5 zc9;thT>RA85kWueJ*rS83h2@hh~w56&5I!H`;oa8-VqZ>CAdJeV5g+588V+CqF0Y~ zV7@BwD^#kOwNN1%Cm#s=Z+--4$PcM|i$p2zOs*22_ZY*}D!T^;+iBfi=cqqLH3z?~ z3dRnm4@D-4i5WGXG$9Swzth{nHtbdsQ*QKfee)uaV;I^?{9c|NwK)DXg+7-u)kMZ= zS+N=IGHb8$n3i@oLCxp-D>rwmviFX1QMC_{&z`J=I25&ZYY9$YN!7sk!G&k&(H|a? zlwelKat-sLcDd=F@BzdE)D*rwdJ^+)UPlBi z2C6JSKR^b+;lxA5!;?BVI4GhV^BVw!^fwIc8sLKd;G?h?iDG?a0{yPb^+Xc3tk0Pq z!&#FQgrQ|_ts!!rmaugmd}XvkvXrU8drC@@%QbR`5YXwsN~{g+(kI4Woj4r6-J@+j z8hHPMvfcAU7L3!VpOBj>L$;X6Fbs!bZ#t!oZk(3fdRY7_z6XSaMlQ9@PIde=I|uey zjhIMie_%^cY8?$TGv(52$@hX;Humi0Yw*i1%>0LI;)s(8qGqU8oN0l{gGZ-s0nhPH z0$m+PzPeX@kUQX}?wyR0R>^Wr^!xlW)oPfS`JrjBP69HSD^&|8=5L;62G_;9&kvVD zMP$Fl2X1xKR1;1tWv+0|k}xczIJcWM8aC9HIG)L2g~}JEm{`;(X}kB3x>}* zrG3J0zALLOz*ebGpDp^A8lqb-?vh8)@xN9M4K%YKU!D@0R=O?m^YPW-Ie3x=4DH=T zK&m6RhJ}5ySlmssGHSgzK}ya2atR2FWri9%@qE%~iyuuF-!7kbNw^&CQ7Q`IjRKTQ z45(^~ri={#=qB{N%eMZ%SlglDw$ktQf(LhN5o;NMg&M`!wz{j= z?@=X5UeSuQk+P?ExaDM0*6nmnD6+DW;5KESfU8Qx(_mh^JZ!yx1O1MnqJucFNGN$LJt+04fK zdT(2E1*6_uzT4afsc^5b)<$5WuX&l1hspHwWAyyGQw;l!W*{}~GWK7~tQ@X-xEPJ- zsp@?wt3#%ExyxMPFdTPg`L2c*_F}h#L-FUVua1zR)b59Yntb*Y2G*{rj|xc_D<|B1%q-X##GkR_x9d^zmMwK!lz1yFDJ{OL`#g*&E-5xAAU99VffD`@*_R%o|Y_qNfJ zT=FnJufuxTDmv;~L|5KvFp|wQ00WY5;5I_y)Jl*W?0&PoCdt?Y@Vp6lUj7Y`6!Ox6 zdbmFsgm<#88TYHUVQs~))1NChw6A93Xvpl90RmplU~&Wh1CW^k44^i#_mox4l8UiD zNxMA1+_EAMjzWQV1Rof$Xp-uPTDFVHc!d_5E=~<1|65%LJAz4wBjQ?qUp%|oK~iP} z`9$Bp0clfxRe;0N0>KdvT+%>h6B8Z6AmI;(6<>+lt6AIBx)p$r8hkagyuDa~P4K*! zMPIRIT<@@T%aQ^MTiiRC1(KY)WKX|P&6++>IQ@IY6!X*-K9Dze=D1D>&{$9R3mR<|P^bDG=5ibM+T9 z@%DR(rBqxCLLH+N-95f8#4auT6uqW}qW|MiI0%b|I`E;2?erQVrlud%USi=9k(UfK z!$xF0)g2)|W1^wK^Zk|iR#!r0Wcb+Y;?HU4(a^9*J4@I6{kiUW+Ovnma(*jyd4Rvd z>XZz<+Ipvw($`PgtuaM|AM9(C;8E^iD(y5H)W?x97VJ`hbJ?e2vP5g!z5; z;${XNyKF&N(-Qi9(;*j8y%&#oG*CLa=W8^1r48ko8wfcS5bp)Rd^e(Ks)~|E-j>T<^#Z%zL9%oTUK@Vk&pMihE2z*ygW?w4aI&rQOuaBs)!tv*V z2nKf0(5|kPD4_J#w#xYKh47@lTjiT*Li=4!+b!JFi!OJCzEvK41??dEh5H8lWDvO% z8A)|iDWy{aE6(C{0cNmW&1EutkFsbT#OxozG?%a{BSo$(=MooVzxf{0xI*s9UG{;Jv6ahW935AUnLXVo8L~7srbWZ)0WQ?}xLqkKO>2X>IUPPo~os9MC>z=3keduzNs?Qho zcV*?c0*q^&9y;{46?WD60Z{nBAlil{?a*pQCOW&eIybRHT$!KQffSYLP_FAMrmgY%Q%V?aB!7 zX>=K+2u<203v(lvom~}xQ~3SrY9L|7QBQz8C{LdUE+uu{hRNzxUHi4jmwq;af=ZON zmI)(lcf+xdy}lNWr0lmSeAxciuN=Elt$=)jb^hVC&?k49K6pgL*wV7jpX;1to?lMM zGTtiF1fz(0?YKi=^N2Iob%!}iTutkU;=n2$6Db-zOj_oqJ#8}v^3R!v;e*LwkZsfudPshq`szbQOtS$gW|zCRuk z22ahw6AsikYP=j$Go%u?8!!@)kULs>GO(`5d;@BZ@v`DfFHC*0SETb|_0Z$Nbr8QN z>ox8-^sUqdk+v9%CzjiMca+5g35`XhX3t|I1ss2^m zhiSWXSS6*Br17wM<`zRD#P8O*RYPK~u1wius9Mc*&cW4-d|hDgv+8Sk?_eGrbZpw_zr|S=vY^7=GLkUE@C| z_AVXn!`46G5Xc(#{sb(UasVX029vgnV;*xTv)-*8rfEixk}!V$$Uz48V~&I5?a`6> z+@}e%VP5=e1=p5-Hxzo#sqPghBnm~~V4fMNNcCHf`1SYeo-LWub} zMEzmUJ&DynWfv`oSXQ{RAY$vYfKc7N$jGMJ{y;0{1)bP(|ChpI>$MTq;)_yn2ntl^ z_NBu7#Awnk!K3b(eX9V8S%?DC;d&e^OyLA0_fgh~xf_$TYe{hP7o7J^X0W@@*kLJa zLv|GX;z~`ndbLN%JfKu=NkbxCvBTqGn8axS4w|EzF~)! z(--VGWBTm!b~ls#M4&M#165k%DP;8WX?}Tj3SQrF3ZDl}pkDMOZD_XIWg0VA%1!U! zKWp9EUTRe-l4D6Yy2)S@j+p89GrL|ldwCQ zV4r)=*LXY$Vvna=9qlhehKA)14n?9YljGCN7VG_|><`V0y68mYOptOI5_IAY`c>5w;jdE}x8I+t zQZTO5$GJ0vCSaOQ>PidVt(M##5<(#X!YD3TqfNG z{V5(E#l~=BhkXQo8D1yyxZgcIGOz~qd>L<)aPO~+a%x(cndM|PIz!OT(2fL}XX~8f z2AWVa*~_zBGQ(PzRhKt|b{}26U?fABgPxayYL)_3&<$E%Z*4tZJik?ijN_E%x0)j^ zn*-nwk;y)j#e1i;!66^I%bRheNQ6~gzNQ5{yYE0?R}?EmgVkur>_2hZ8!Zn0tjQji zlaD*Balv-f_*#H}?XVW(ycT1f72!wX9LLcSz|CWhMccIlv#{r@iaFhYF*TFEEsNbU z&Vit6fp<+PxD-){24GM0y`pkbVOW+~P`;Y*OxJVNUXFsWMl~8^5(vzhAr%z#di%e` z#$@>SRokqSK#-!)lGZYxmS9OY-nk;McwCH2BHmrgg6-vv_s7An!glipV&jNMnvrMo zZbCs~`v@rZ9|(6oGPiqKmG5EWEQ6=!)UTi6)(||Q%M10?3ob6n3b80Ku=cnVkhl z^!5rTytyi+57Z<4~ zt9Ym{^~gBGts)%0Vw{|ZFF5UnOLkahEAN@Ymq^QF2$U(8SZR67fp9&Is(vb7y##|p z%Q?roHLhf8?Sz4cChTbVDWJ)W3&j>Ev&Wc90Cx@06n&Y53ZBajl)E=ryU-EVThcSt zu!5qUpNDBi;(n)EimixY5P~A;*b)xbOW^s4QDtOg(j(y!5V{X%#>b&f3lOjI_+RNmk(o3W*rdeggp1n3|G7I*);k2l7`_+g#j&A=@xi z8@1<;=&px>FxoGTX`?s245yzKiR#>u(YJF$!XiHM(H&%!QR843=N1=4+9b~ZrWz85 zc;52m zanv6k16R=dneXhk6CL{*jhqQO5;Vmz2b&MMO~S|*a0K7=bY2j)KYJ=8KzyU zF{Z#62fj*g$K+;X##bAOU;-mUOp7~1rsXr=a_q#A;-K51pcPYN-o zM5Y3nnNNYnzJBSdbg5V$KG6div{N-8I~~pwu2(#E1&P^yu9`0zsGHeF`#q9`Lv~s+ zGr3&tvI1U`c~jafSU^?k;j%CfRZBdNu+niqXZNyeQYx@ZVB?y$EnK}AmX=m-hO~TF z7whli!0b&==np|5v?UL^*~^dmyjYtb`OxEPA`PCAqq1t&$N^Y;MhQeYLhN7rE$T%< zK0L#`%0?1+3kvv94ARLsvG+Q|V>d4{$<1q1{2bd#TJn^R4T?oaKcLQ+b= zB33XV$KG(u?=2M0gD`|HtJP1jeX;V;K*=v%p!%QsU> zkqq8S^buCzYnbP?ugQrx!Kt(aT`b&{*J!KN`G1)$IhF>CV7cGfes}rpCn$RTnU0d# z_UIRdjotOZQ&{w&Vk{@pGLb2pnO`uqvPZ|(l5>?Nl1yPo!qxWUm$1kHo8t7(3g9N% zo!zzK0COCuVCtc+Nt~*sjjyrN$R_~)UEAzc+uX|5;08`VwYAM=*AI3cp0&+wu3p|t zORcV+-mTgs))f^mnN4qOjE{fV#K!fY+AZ1v5>Hg_BL9>o^sx%oh;k-PB*H&3=YcT=nD$-T>|t*ec@ z2Q#bdtvgH9`W1oJ_PdLb?d#3!$4ghQhnLe9yi}m^s4<307+&0>f1iGrK8GGhN~J3O z>04bgv&Lw$3{~l}phLLGR#-MBy8-a-ZHQH=@BX&G5_YY`9A=7$@ zj%sA$#Bn4IK2XT?8m5-!+3jP(4qkAiG00$;PO;V{wu_kC2G+tfD}oIz{MXP($iPq& z)45L^DxBAQIAM<$04$0Daddn%S@~%4iQN#w`sac#sjCF0mgV``T~b~$9|HB37M&7P zRHVSjF%Dy#$Oqd1?T=DCs7FUi<*(6?qQ7!LSm4=|*3hmh?OGI9lq?}E><6WlA)%Y{ z+!!IlR&QAVCWC?Q7&1=T&_SH&c;BTo&(&FAW>=kpq| zQ3f@kOl@Z9pr9?=1@LkQA*T?szEs(l$>VCp6#hl96+Y37U3q09eH z7;-sTx-1WTbn)tR8!&-xrU0|#{(n7pP=T7CKYiJz1KdF&v}fKFdOmyRD;Hn|pthH9 z`LJRe)TjkVgpsk)QGjpnGnq$;GKz5fyUMXs=iSq(lgQ;~I60)JB6m*z1i-ZU0Vt0TZy+_6~cV5PZpwn-MkT^iT`G`dpnMODWZnu6>9*Gg4$y}EhWTl z9}vhjgcto)MhoMcnCu)K;XnOZB*DQYD2`@=dX={cc&%4oiC!55x-k>_`{H1x2kJ+t z0dtp|SnJi5W1T9hgEnt5LX8}kSZMHYZN9(vu^+4JaNrgo9%$h{|CcY1V!{* zcz9ImPZ9vE!5CT|miU7~X%4I6d`ssK3j9YBBy5>k6N&#M)yI)jMuu+-FF3LMQc&s% z?JL8LiMhf1&|MC?NbM$rUo87MlVvxDkjSYTBF(0xQy&}p?T~O;+$=R%;^QBX9Da%Q z@V5i)iah%4@BRh=6;S=Fv>_bYB$~fJ^!w&k=Q63{G)EGLc1`~gID<|SW2VnGBv68H z!h35DSl65nooT}xylY#%NCQy=072a&lDFZn+l!dom7qa-~OHREIqMR6D19kFhx;k(D*V3_w?`x6YRC;XR0sKMNqU!PpHAv^Vv zL@av21jFkpv~r0bvV2tZq4>R~?a^80E$}6>@JtPiNWU6lY4W@p&Czv<-CBBAVGp}* zCyu?97T?gQUwC(*g;ilLa8O~p0cn9N_&kD8B&UnzNp5M69Zv>+%D5xoES*k$VE+>p z61jX>lZTo5gUuS~IKh+0gOuS7@>fqs>eSG=;_@LOub@-STQ5LPK+^4zWyyC+Vpt%s z_u-=^L8uzb3!}9A6|y-GZxBs#(JOU~wk-=yh~A0Axcmr?bcfvsIl1R|>+J$}wrCq3 zOaLIbA~Ue{)@emn^SoY5DJ>@qUiUHVIK8CT6k25Q%Q8?LSMLr~#>ZD#r1 z5KaGgx6W$vs`+N?_B8i>qhouy>iBUceNK)(D@~g|JThvJKDR%qe@AFFCsp+?`lRlX ztHr1Ok)*r!mawM2}P`<&xA$UJ%D`=h1V0z$ z_6CHq{i=kji0D!2EW|BU*edLO2BdIiGnmm4m&%1qt_%=2SjJ;p4CZ^)_D)y~B`<)L z^`IW_kt=k|KwV#RpuFZ#J#e^fLArkl;?5k^cPLBB%EQ2O>?6V~2>R*6zAos9rc-uN zpJ}p|>1Lmieq&)`zsBrc@A<;F?)mzjfJ0@wt{)xX#V`=w7FfG*S~3m7xx9@$etufN z(RhWZ*)JnKIIwL9@9$fzh*y!ta!*9V37_b0hsXA~|N-WU&Ro!bki z=D$4qG{w3d11Yqg3H>x}u2xqbXV~ze^V7OFMr?9F))}AQGx6;}c#__aF*TXqT4fdI zCl*lQMBEyu9{Je?)}j+DiLZCv`ispIWeefU*JQ+2XeOhBn3*cP6iuG-+Cl)zUBApM zige9a`O+Z+5s zLsfnWwxzfnF&h5U#pG^;@{xzmH`qV;rLmEy1PJ|5^l~LDV2(^~)>(y1$+}Q^WU$AF zBYm@eMm0+;^n9Tcv-U*wjle4zLzY62F``k_kDg?;GtXt@0{XV_4bK2>nImq>jqzeL zm1pd2REpdKP|Dkoa$c0S-cT6;R;Whp3rTX@gZFph^rI2&cP z{u(7lTfhvGMD4m?Z%^{5d^uUX59l!_9YqP8AE93Vwh6cR)xe7>@*~dXq?3Q&%rt9T zWaWW7oys|6o3k$N%vh2Bx3H9js^Sw@9+@@|RwfTL9p%zIPd6%R!_P7pXx#CCQ;8Uo zu0~rJJ3^?9hkV5Gnwp_QxkmAq2t}Nxp^_;Fg=pItFSf##zj>-j;L^qrVj=-VRRW% ze-a2<3)q*p?Keg5zBg)eVLdHQk9rD}W_UPW%?nJvK#ADsh-wq_TAeRdJ*2Gjp%^M$ z|6%cH_>1GIGB2$MJ}E6Q|52&HOEVJiQIWwtO#$39Vqu`@cMu@Kk=bpjsGu+sMW>=m z9zC5eUd10D1nC(4b8|;Mu~?u(8nZ3*^b^NjJQWEU2rCDBb=H7gpY5&WrC`gW_sV z1JL#x$M5Mx+Y}7!Eco!0Iq6q1%%N~OsS@~>9kjLp<^jS_DYU<71oR~cd2YV8($kBm zgoC}>Sc)9*3s78clV3h0rW8hyIUY5AX`nhsoXmZQg*NwU0{VH1&GVcBhwn)w!qRRy zc7^A8J(-`E-nRcqYU_Qt_kk-%f~U~8N0(A9_5MVlQ?0dT=hmSZ-OHZEm$h3aHD=IK zz6lkZ3ntBSgGFt@-Ukb}Fn1gNGN8x$WM@Y~azq(SGJ5c_-h^@s9#gRNS%jMqC4e@} zjF&%zxhdM`IW|-Rx29dI(Xv0DCNK-T4xr57Vk?!j+#z!R>n8SwOW0L zonY=ry#~K7@Nb~-lP1*eb5=JmHB7hn|5Gyx-L&j@#vs4iTA@oeDjuCvdeO$<>3YFxKTVAfEqO(A=0` zX0h^`31DioyPUut`OuYwF8H7b;fXw=dOPbdn#vOtxRf#qs0;SSF{-hNiHG;FJ&5wD zU2Jf%d_1(=R_>XV06^l>s$MLp(LEggNJVDDJ3%in_n)U?nT(yZUe985BLTZO|78lW1d#Ix+_aqLdXP`)%0_XT#*w zQNKR(rtN}DN}w4zA4_;+#w6H5OXqZ0+{!`K#+tw?Kf$fs$39O%`k!1S@GGYSt#t{d zYSqE1sc=u>ghHctg$w8zl22+b6UvY5I&@c4s%`K6PDB(dXt)T2;8zOP40YUCQxpV4 zz7o>-zxdpp@$&s*vDtpOmj>qDfB5*pJqcw>6dD>DO$<|LKC;}1-om5ILJf5G%VMC; zC0{}TQ^6fA9wl2u7~bFihGVzY2b#%0(chnR=T-AN!yxxK_dch|-dE!@zI@A%t~qSG z!Cr}e>!}ZX)}wwcK;P0>i1TDm%soRQ>oB(>ll1oU zG%;QW1Yq@xtT!{aTL30@Q`KTAG#62jA4}o1tf(^ArIXaFP2Ca3rCrKl-e^YW7#*Cc zJ3P@+e}Z5yGntw9p%b0XC5iJJvtPGj!{Q2iNalL_KMdKHPU6fbTe8sV5Yj6id(~bI zIF%o;H5!)O-w1gs)RLo?{eL_Wg}8Xh$i6~`5?Yz92q0X)O$T~(jqdU)B%XBIeuwGgxhaT1SL zZX2p=>x`l9h-KBbZ0`Mrsc{svnCa~L7nR>tKDQM@*ox(PoZACPC1M*68MO;<Fs`xLQkD2l3XGT{Q*p)5?phgGDlv{={mlS_gfuuVu_-TmTvE3Vi zH;wl6l<;}PAan!|0N`NR3yn4L#CU%PfGb#ovZCHoK3)UrAPNduVQAlic{*c`3KdfEO z9kJ9`V|gxnh0Wgweg9sx<$G)_(N}-0DH)9GBIY9OcdZVOmy2x_9CoqoTR3;_(&537 zjtBUDKksp)HY*$jsecLQC-|G+N(tBXEu#jS(>FTHA1`72!a6h9jaq!L)T<>zcX|#W zECv68*%#X|t;T6Z!mlx#jg1}{8al8-_0%%T8gvc;njbSb9(J?Ts`=?jqU%1mSf6FMd_-|2YoyNrp*chH z^gR_O$&J8rCc6(v;?Uqpe@FS^$=_k;_c9Zj6642r#7#8G{Fs& zC5kV4*QeA@r{{#9D$#gPI>MhuO!516YAiOBN>yW_LvSXK%UurFNw+Y|_w!!!8Eu8e zo&CA&B{cXm*#^Xro{m*>tYGBB?~C5EAp4HJ2tK*gM>p#edpJPBSun>!y1bFd_(g2< z!RX}gD+^% ziQ>Z~?~JYv@0CugJnA+;9T*S=Db~I)y-B9yJ#`C`qJs zWZtTjp5-NHFUE96Eutv5Pp1Mp+82_udJGJ&)n4yO9?Y5o3Q&>tcCvn8WWd%W=M}b_ z3|lh7`w(;=NI{K11i)!>^AD}eWxTDpdDo@AZ3R)WzW)3<6N2{>g*MA-ri`_i4+Dk>Wl5o{P1OS`gOCdYvyxn`}X4%`^0TM zaCzGu;!{|`3d5uhfUrL9yhsy8rULX5+YozRDcFS9T%0?S|QQU6ME zF{~1nq94iKIgLcm3tYXZO6v2fY=PF;WsAVET21`fu#XfJa3?4y&TR>C)16bnXL5A; zEgi?7w#Vh^19#H(=vF48{jrBAYPECa!5f8tC9M4%f_GhfdIW#h8)&T_5kTWU>jnc=I#+2ZMr=Clx7OEpQ0cXn+L_P3xUovzs+HN0$m$ev z6XwV&EyC>Ji@PICo1@*o){VZ}VTY+uR9W47+aq|XLJ5bI&j+gzc`)lvxYdU9T}pLh zV@f)PM={MGra9L~mpK$v56=c|t{$1ftAj67mm{o&bUK-w&5ys$DiiB$SZRA|ja|M5 zOk7o?m_w$fV}qOC>)f0W{-Vf_UG_CwDvV2*3`ueNdcoymW*h7kJVNF6Woob3do%*P z@M*ms^BO&T%AWu;)nDuv$c{urzbM({3WO{I%)$7o!z`FZ5Th7(2PCZnM80N+=%HrI z`Wdq!Ic)$J#joymN0)A3JEQ^q0S$tKK>qDY;%hz?bViTR21Z`su1CYgh=~q!g@{t% zzbZRqr#^12YX09MamK7R!7rK zW|*8PRvx`~Hz)6i-93oY)qBy<&^y<{1^w!0!ueRL5#iw-Kj0maQ4EIAc1BL?4d~Ou zudGnvCK_}gmIaGss|yJs@j3@q*&09{(JF%*XP@(!PD}U6t;S0D9{2Q7aM5Zzo~f*H zC(~hseA=_`b}4IIw>-i#TLUw-AF0PC_M6I2Q)=?+ZO&mhj31u00>SzR9zEM&S7$jg z-a;K|0X)EkNcVDypH96cDB(C3ya-AbGH6Sb6L6>~?A&v#HeAif?XE47$LV5#J;fKF zZqaJXjl6!8o~l7yh|}gV95Ffn>9=mO6PKVNDryR`*#+qj%?O!8 zXMSYN^L-`SH{g5TMM)gh?i=LTM|W3F-7~tr+>^dGsyR%Ol+L&%IF6kj{6F}5>$oW2 zpl{Sf8j+F?3F+<<5NQyQ?(Xhfq#NljDe3O+&ZWB>mXKKTy-|P9d!ElZpTmF4-Z9r) zGvAqOYAX;-g`^gwpw$pi_S)bGq)NWLb565PLd-_>kBHA2aC9d24c?Ovp?HEo-zO zSisu;rK%HQ*H(PG%!VAR#q|j?L0Xj9=#)}j3M$-!LFe0jQ{#M|;P?(xUq!uo8F z$#w!a3=4YTu;Ypi!%|2nPfgE18dkAE6+D$bel2 ztlJ9spn_;2FR(v&txX4|%LJj@1ff%PpH+kFo5V8qNJkiwsBxO0;K3C96c9_3L(ff} zlAPEc)iyz%Ra5T?dl`W|@vxb3nuBs`3c@OveU5PuYnWTPd(nG6dibr#VI*^O^*qR7 zyVB@F5L43G&!E+6V=eDNuu=OZL)n5kV6xRu8D;1eKCfq>F7mMaSmzytdUlLTx{&$( z98;>xY4+*CQtz!UQE|T^f2n<2yeaUPTL? z1^dxJk6Vk>L0(2_^`T$hSOpGS_A>AuCO>k?m~*soVuk5120lBB25ki7+g<-o#}xx@ z3R{{I`pO1f0+!_geYa}7R>(?@8g$U-S>7WH5k*b<#q9 zx???)jt_VikCF#&TPs6dMI88jyQLvc60}Iz^mq_rEPCj`=8+ zSZJPkGb6Tj?rX6#Z_nk`H$`r&){o>AGsiCUll&YOwOkwEhWjsJ zyV~^HHW^FVV#=&GO8If9uC!IkAb)rmBc$j>+&%~(TpbKsVcd!csVh`_Mn)DpS+!T& ztp2cA8EUdmW3p1ozI1R~ce@gj0NolzG;@MGjSH^D0^DGEz?MF4KUeSt5P#jra_NuIAkZAfF&y167uuzS;d(K z`Y}D+0{pqgbrWVyiIn!i{Hr7fRS6$OHR+wsx2TaghcSHHZk`}tHpiEpAA93j{c(-Z z32joEFFI)o`v|`eNh*5YfYiq;vCG?$4@bVPs{v)TX=xqX-tsP_MwBa_a#!_?VPE$t zK7W%zp*(*U0@4%@N9}jXqK7hzzGUz=v6~~Sa=Mx2wPHIM%T@4>n`YI%k%R&rQMUK^VfKbXbK z!2Y8ft;^s1i}jbQm}7^Ji8*)zc3s`_XUw_77AVFWdTqIoltm-fDtFmkaXh{}h}II@ z8Be>=qT1ZvYg7aVP7*0hFb}_*Na4FzMfLny)dQQOcSx!4wEf((xs?#>(GA0oSZdc{ z%^2s6L8Z>}sQb-z&K<*!)*aK4<^1b!5ATfd!BVn}+8j2ozk#)dAjoW%v^`a9KMk07 zWE;bNU{;k_tzB8D%|>l!Y20PX6%DpBE1@TyyUF3@frfxDDpKA$+n#Q|*Wd?SLj#2>%3Dvyj`PdVO4mrQJ zam&vz-9{V%95jSrtw9xV0d+j_=^N*;R-(S7rIC-x~!=_fv z-|Cp>i#JcZ(eEnc^?DF`|v!QrA-=UT}`Tg^{7tff}o0?4b zi4|hR9KXXI8#FmynFYi?S`d(Us~hfqUQeHGs@HLI_&N^l-@T3#wv3? z(6n7LOk6!wejYC%YJ4(YO4up(Q(<_eSdW{RiKatUlPlh?^n)e$lOn-C7KTz@*GgfAJ);aw{Gd@kCc|)VkdYon5 z{{Hpi;4wD++3vN%=4-Nv+o?`2Z1qgt#?6AN;B|L$F1)J6VN zelvSIA6qBMh_!WSE?{qWQ23=@#Qw0p1>2ABQiMix4O$7!x2W^vzpPZ@D2nH6+v>GB z7q%Y;rq^c1COy5k4RIt|)B?v1h%^q~#98^~dDF#^2Tv)s%!HX#0|T9ya)TbcK9Z1B zix0zs&)6%8=R#1YQVhp?uca)^#0SaQLXnb{TjyTFC4H{-6>yFq{(Wal)|%};%B|(J z)z3%^$FrTBs_Q7}kvhY#DK#!gPtOm+MjD6~Q$;hG?rR^Vt|{}>L%rvYPpuje@+=AP zTJ-|6-_>Z-=O^-oX2hj{t0Z~1JrzqtIi<6A^dQ@``pHrpKhZRFm=-Rt8O$BT0&7o< zh?JL~Ebx>b$PpDHtu;6*QM+*g{Y6M93?{!QSB^1H2|H9oFk?U3_79m~|E2wPzf8>p z{4tm<>_NR@Y2%{YLIzWen+X{OZ3&QyF(L{Z*>+!;#g@e;qgZUpsA2V3k>{)7eG%)^b_+f*sf!gdZj^*; zSu7&jaGPbN96Nc!*y^W4={McEuN#-X2&OW4s-+h^)iapJ7QlfkqOT2fC*V}y`!;JsMkETn=SV?Dtn}*e*8L>m`p{2Qv4hXE=6G_}SUJmePWu3fj|j9J z`*D5pY^ceD)M`O04)<^zzy1btWo@z%{QHm@_Q(OBoql1+%#PyZdg)+qDvS2Cov%Vp zvC{bzhN&p5&VIK3vjP);Mb8YyvTnuE)u_wqaM+|BOZMZ%OB44d{=WHzv05b>JCOQd zo=mIgJhT}0{Lp9+f}kQh8|`LU+`B+8Y4rHB6iUPvd)$00%YmgX%rlVJMWnLUGpa(#|2{1<%C*Z8f=4qX_Ah7!V35DqEZuJrt9m7 zBVqSxpiu0GQWaR*GXSpq-VEj1NzJ{=>!Ovk?~rdwI)ERWuVdQP$ROd&BJ224>xOS4 zf;AXCL`F+X2!1DG9z#CQOQ5DNaT8`K);hk$+abQeSbBDpz+cPKyzS7^y!~E^R)>Yq znHB}H>5_D(>MNuI3wl|xaainxO&_~t;yZRZ(CczOa5jy^abUN65n;Q0(L0Yl3I*Mw z>^vTgU1`?P@%#qimZyHPvC5O(YWm8#urRu{OiylW#W_kvLh^#a;*>4Ty>&DGTXP-5 z$id?K!YOZ^@>N!kYe@zq1j~qgmkH@gzzzrGd70SNo(&B*?@o{)duf=|4{1hr9Bxq- zsiX^L-Jre-c%|d;O1oOol1?GMb0A8gf03(+H;&mj_YpWPdd$z9J3Y0y@x9_!k4Xd>)Rc&6+0;eoxS{P}OemAm^ zZf_v$^a`=F&9r*`G?r%2_&rRwCK}qy$_bCb`_5+tjp^U+VJXa_er0|h?P?ymd&%|gT|I^I&s__UdrCP8)tMacFHf0Rm-Ap&3=Ka2S5a=ftS2!D*@;bH1YOYw@oC};u{ltQetxq7Q`bOspaFBMYcHd*aKc5 zSV1C}rGn@)_UX;H&b#t%0(!r0vgTEIlmLfr^hOVKbT{OOl|czDnh#u5hm~GMt1i=$+El>#sMP%JDMX{h{NCkHkCmx3Tj|?HNt+J5;$DyKYZJ`Ln@xuAqG#Vorj67Po%}h+p_o9&5DB*$!@LS|!@|eGk60TqiA?-mdeKs*T64o%riwQI z&OY=lF#KuuZCX<%1-D$Ki`9)OW)VQYkFsE=-~dK}3Jpvc$)P*D5xyQw)jGY8suJ|8 zL`Zjr{JAn0YsA(vHCJ>@N;?2ALz*qoWFYfg4{!qfmG{$pp?wFSOtbi$U*+Jzs2io| z(B{>Id6%9$(|Wl$-czcdWQvldPfUQ-&qOgqK+rcedzh?~vlMs2Kg5lV(=bp`v6Cy4 z$3u_4=BQuyZgPr7#m@NJ=p*J}c?1eVl^*&QlinJeX59r3kl@VU53rY{#r-@{AwXKI zIgu9Q!TIWSN(*u2li2dH>i-?}$_W;5D{xxBzN(*z*d1O8-_wJ_#cO6ovTP*!& z>Oxuf_oLwl!*Lpkq3JbA24*!A48;CpWj{U$R>R0jKPWf*0P4o)Vh^h$FjC+yx)t{p zcRl_9D4y>N`qynmg^Ite3qDSv;+)BRYq2r?&6BVDZE+F#MTg5n9H04oVt=E&V!7@x z+q-=cG;HiI8+}nasWa-cN#!rqOkPVpWfg<}_V47sV_f@=p1#g7Izc=?D9;@ktg1+&_2V!8LFo!ppa?v0((-Q=c((Xt7;=I2Xq8Z*oh1j!XYR); zUtkc+QKfk>EqyN_POS?R)Pr%vTfV>a4+qZ2(YyJfaaI^P4GFxBpM$b#(Qs383h+{L{uU#N z#@fu9eF=0FwYO)%#>Rfi^#PdvR!S3S)&S0diu(H5e`w2p`?rW&&I}(OED8SYMES&6 zp?{239WH8+uQs1&i}cp zyQ`}V^ymqC>K7ql{nx{uKgBWxwCetkY)qQ|k+W=)f6FM&pTtnmP2I& z{TVMVH-*Du+*W6^Aw8Qb6o8zUkHZQ6U*s93Iv&lRj&MV+0X`G67(I>m{^slN0%$3a zPQ^q+6H--8Y8?cUVv#t4yx@^fm?5#DJh=5OL_n;_sLrDv1_;CdS%X~G>o;#UPMtr} z(2x=lwXJLcPw2yz)|totrFY=p#BG4VN#I9ntD9IaY;U5{`y>#7lg_fTvikb^Uu!Kj z{=}Y0j5z#Ej55Zts0mwkb!03Lszs1O%BFevY+Bj{v*YN-L=?ArM;F##s zyKM*lV-FTSez7pDY2eRw!H1h6*1H|O9}>tA45Zu|1m$g72%07`KGN8H`MG) z_F%Y$MbP8@qU%9%UOq`a9P)57CIP|m6K6heBIf>~W`qk0g_4hnyZvlz|q0p!wr3CHU%EN%H4AwWku ze_|7=Kqn7Sp$iQ0cfYniJ3ki_7e9021aukWp9Og3XOcI#-W`I?X8s;v_@6z_?)g_f zEZCo70{lJDZ4_PJLRy)fPgXxDmTR?oHWN|<#W(qYRsoM9A^Bu%{83m~SoJPHsYtat zSilD+GB(zs>+)!!R$f_oH?QCcd!+x`r9J_ieHC7S6}?{1Uy91e@SCQO?&xjwgn9lF z2l!_Dk8gO{48^YQr`=cyxh{+M2h+veVN-w*rr`X0m z#(cHfW7J!A^V!wBfu}c)Y(xJ1%E9LmbN~?c6BVV36sbLKFLSI`TFe(}!bVcL<<-@P zvc;mSegXsiCqMoX@XaDLLc-BsvRMGQ84Sh&;Fd4OGE{l9wY7D6P}+L77C;D~^$1vo zzj)aT0L837FdkVcohO}oeREI>Xv^fM$jHdUl~%w$rA&F=or*L#L8P6Xuh%R93H2-j z<~wHV{?+ZkJ^|og@Zf?ufQq`qiorkN^q)CGv5Y{1M@!Xs3QIDB?Of@pX%D$*#YmF)O`tqxVn=LGF)x@4k!&k^MLV4)&9mg zG=a$gzS3y)@{bw&b8Ad&Z1-xrPyfKcnG>a4NEkM=f2L3XU}OOWq{`7rn=F{~!B&BbmgqM?`!jP-1jFhYb&W0RNSq?ZeKm*>UHHS4YGdA+N9&(Smzh7O*$XZHnuNu|}QJGX*WTvt~ z_#eXm!eVxe(0MMUWFeQ?bW!_}BN$*VC|*tqQE;AOBHtrl>K2L3BSz5C9iK~m{#h^T zkyHgT0oHgkW$FmGCWGUlnZn(BU}MB@;Aoz7MK0LiRk0a}S~2Q&!TvRIWdGI?^OK=? zKXvImCn!+VBI}RIB_YZAzk7zWP-|s0Q=;*Ee`;_gCnb`H({IxNFE7HUTl`ZUz8MA{ z(CDi0&ovaK4A_>8E?{&y)2C~>)-6)(<`!XWHup5aDJ3+jMP2fxZrzm>x}_v|y64}_ zPf<#oZIx;OV!M1$_;vvyk@WZTEp)TBY}C7AV#fR46?@;Mn5YLxg7{u<(G%xIDFHzT zKza%gbPPbp~Moz zNQ{}%{5Y(*V$#ZiRtn#Wz7y1Z_T+WU^|8^t7acF*B(1@voFrI3|stY zI$h0(Rt4RBp9_-zTKh;KudfgW(37^@?Dj`gqsxuv zkk+ec z)IkU7^@vy6^o`~GLRDnUNx$*{pPXEiHRsQ&pEgj>BX)N+Fz9UR$QM@PoJzk^=SL@- z<3mT7IM{19xCPos28C~z7C){Ij-SRRh2$G=F)6yOI+t>w=Bp+#|Cyzj9dmN>WPEHI zmmcVHdZ?(V*7MRmb+1p>o{aH}#UhUjWKHFzgoX6_?_csJ+XqQKI?#Anxue_CWEi0v z3j?oAo?&)yFL#KnJOs3cF>l3L9x-DeOGUG9OUWgB9?lqWl1>g*TdM(aVYJrmpq|2`N2IpMyo&r zRlWqSa~-E2YflY&JdSE#L>LS{CSfYaRpMig=3SoHaj4w51u+zu36ZEHzsO3S*tvPE z;8-eZ^Psk}ctgF&=(AJ8ov!F02xkq03NB*TOHb>m>4;YEsZ5nAHTGIcYuh5USi5#A zoa7bN=nioDou{DAFyh64V^26p9fG_%sMc$Ag`BCe^!3Gy4$)m(GWwB)(a4B~hGQ4u zV-1yd^Ddp?tgayJ{y<1s(`%gzH~ajIlBP zWu&g2(khW3X*irD+~{}|7#4N`fcDn*+%>t=ogL+cB{WFH)qHzEo-@(Ki?HQ74NJO%MXZGHLzLEJ96YL=g74wkIZ7=om071 z?Hk@RGON#vqZ;XlTX($=y+^5nCKKD&gcs-AkAyGj+!Lj2u&luvqvOQOV#m{3(B0vk zdeb$w>wD%eQ;g4E26TR3TN+Vf57z}P;kxV(iUgjU8{F7AosagG60v)-%3BphyzWcA z1tHcSu9%1OrK>$cQ5t&DE1)|l@9l(P$G1|vTJEa9TkXWF&+Oo|j97H`B@?WbUJx5x z_BNeIpbn{=!-cfg1>f}U^XVI&90+}=GtlMpNK5bUonhl_cXtRlZfE0b-cvkWf@~L4 zj()9L=RIz{dU=eyp(C*)Rb*z5^_X^zVy;GU(zWu?-KpefBR$cGh+MMlrWtt~dw%c| zkpPOL_S4l4jD`Z{W%9{M=N}nkW<^zL-{g)#onLr?&$ytkXtcHw#hOc)NSL>|63JPo?!@ zjclKWm-sC7THh<+*B5nOG(DU&h9-mfhZ|9{9uJKeLtnD&GNz#V$W*C&2Mklo1s>QE zXQd@~p?M&uUKxI&AjsIGMRPe{NDXcJ@Ek!~8PU2_UuE`{Vv9|GJLgivM7<^xe~rrz zEs9Z+bAPiSefpKAYh;HOhn9WC z%-bh7UQyZs+@(1izZ}(>*K9O3Y&q#KKDvdGOgA(7Q)|shhPdUO9j$P`bB-zyKW?XD zW4rf@jYw6RXmP`}^-S%<(DE3Z;cd}f3W<+jOt#}*yYnE~X}&>Yj%&nT?A7$RTKv`K zGW@N@^OTqEM%8A;7rSXTYg1Os=?FFnWv_>KkM9tM?5d2Ulvm9th1xd zRONZiE%?x>i7Bhx-u;XX^YU zgSV5)2TabNBjnoEh{BR4yG>tBIDOu8)B8|vLc*qnlYiS3P^&P=TiWM>5Px#8?p`!Z zZ(u(ocbb{?nw_5`sUasiGq~xpVAG{EaRjIX{^O!>j*pLL=jGithT@o9oEc0ODn)d4 zeFhviIl7i5t<$T=+vmN%MqM7(jS*KTjod19tDk8?B8lO==o4pdST{=QyG1OWkagY9 zP!`e6Ru>x6vh4|vd1WTDmZN)Hd@U%r9bGalUw3jr_%Opk{#eWDBR?G|vv(R#@jcrV z-!&Uh)l3s-S|;wcS+CpUtlDfmcXz8T|FF`PG#k^!B;PrgRF$2NG%z(&no@u-Bt4%}#5x*6E8}D~a8@if%rdo4yulV<&PP z?7D8Mh!wksGfz$rhhpawgFM`7qf@MO%@$L745SbCCw!1Eolr{Osz=VGmDUBPUE%y2 zye^6z;O`>dJ$!HA@9!)=taGe)_VS8(t|- znD#tUYoeMee(>ie^W+OuW_j`0*m#i^xXY5OlRbH?cdkWd@9EwptFHYrK#(R)_lrQ* zZ$mhMJ+PyWXaX^&;(S@Hz;RY=?)YV+MR3p_^U8-p8*@`$+k4G+jmixrmF@-2R(<(a z>G04X@yx3atM6yHF-PGw8%$8^>-j>fD-&wZ=~P+sMe%ewM|jJ$Irp4f_v?2s8nj+R z(Gy_4XcIj*7}0$t{Py_zoLq6U+9+4C`&^UxZ%ho85}0+qHJr-o(@SvubheK15$m}^ zv4beN{C2r~KEmu&X}8nPyZ7cJOM856x(2rs>U$gs_1)9FeE#5KR^CQGJ#+PeE9NW4 zV|tq$e-faE4pIt+SZ|P!YhHAt>Lj7!36?#d-JjU&XlE%dfJ>^#JKtX@q_lK@lP&`a z^K1tlQ;ooN7U{?Hd?50A_HxMk1-v9IZER+O%iN~(pv^k`q~WXB#dM$^cekGjw=(dD zCeWKN#a(Z7n7jz;r2d`avI2+Y|BGqLew5n2HANcFKS)Jclo1d67lwYchAAf)kbn0? z1pw2&{^zhD4ks#d-a1-#7*Db!yZS-5w z$8}R23et(IdJGV9F?BoJ~?MT?y*`4W7JLRU;HQg&$87Nhx0~X3jv2m zQO-GIht5WKb_Xi?L3b(WZ)vVMz*}^W5|gJmzpNfEe}SG`p|b_AXfe!TQitjM@S%yN zfv*Lr)UNwPB%!5vb@z)Ocj9diEe~h&vkxCr%7l1x@OGHaqF&LcfL*qRr_kfLx+Iea zQZ@GFAnRANHVh2q%7_dhA3t)K`qz9=?)U&#>*aJMeHjC<20z`>eouJVX23{E^RehU z#ir!=_uhI}qXYa34JC$b;%&ms$c)Hqjy(0`tT*w@I8o?^hci|BMa_gsPugY9LHVa6zRdjTqub5s1I%* z38Kx80!4u!goXWoVq5dj)r><`5(Rd+`a0#e`-yAep31_8IDN8w;(-d3? zU27%0iyuTOCB^B3M%)LOdEyO=$f%1x7CW8ApW|ptsf}zpEpG)Z!7X0jkg=3KQw|dQ z6%mqicRj(&Q(H_4=V7_FUqURxzn*|lUu5->8RVH}2C=nPgIF^udW=5uiR-T7%IFcg zy;*s@MlSVy-syiq`B+>vxl!O&y4_v>xG@#^vj6S?!#;SxXd^V@nynP~UbjWB#AV$N zpGr{;MCX3@n(lUui+pi1fEb~~K%3++;fj+`YDFq_kZ*lC4LM_X7vZ)2>i4U3L&b>J z^A%i3)?<_tHjajeotwf8Z|STHz4l@12WOihb{@Na*oxx@?@Quam9sriA^~R#f;Yd; z@fx$zX0_8kpf3u^o^ns2?7$dcl4i&>4#E%JG-V!2JeATJ*_q zwHDP8FWlvw;VTLzyHm-Qgy^td>@W7I{#E#%>>ykl47~s+(%hjuJBd^YY<`Fl7wjY zi@)2IvX@WaLOidXN<8R&{Zj+ZW=27qX?)1rOSfdLtvr5t1WbVk;N&`6{;xiPnWan{ zVC!Shv0aPjB_AJx>8G7Fr_-ZHu2YLr%AwP`)0B@2`Cl!t#;9~?(nmrvHqhu#PHX8; z`<|n;!{OKOo(A2Wx37_=5J}Y3Hbg%*-!U&)LcMI9ejDxWWaX=AY+M!`q$!|~+lT}s94{hxL& zU1PuSWPT8z(~8Fx>Vjgarj*TTq)!_&GqcHT8L^6rN}hV5sKLLe7L()Q?1!2FKfm!R z6Yz%`U~qaEm&5+I-8+q5kDdvqULc7Z*vI())jAcGWH?oz5Q@(oH&v)~+Zcnhu@$ei z9Szw&?Mb$p0D3n}8%NyGw02@;(z)-Nfw=u6Zi8ZfJpvZ(mXC-N>iHD{wu|iQxIovb z{?YcW4T5qihIl}L8}n*YMilY)fV%V9lYO3CsZlarN&W|0JMtDF?+rPwW2s3g_bx+Fb13Qp z-@^_mSM|OkD;9@;2w~FD^&1#D3Z`H4CB(Kh3|FnAV>j%KZYRBmY3{7RS^k&*Sjyjk zu)${$5wqvs@JSptBvK>!ZDnQ5Ve}zegvUg+mLFV^5xW@9p&My%O&sRL2bF_tY;(7* zgf4sDCPV7S#1<1c)5n!xuafM5riW*T0#$XD+%HQlC9aN3&ZhKc^SR3iWHIU8ruF6K z@&n*8={HgzR?b>$C&ClTmg6ge=>0uA%}^}Jz;C{o3%MdAkzegN6wPKnV6Kb!pYFu- zU#7<{7U6)oYX=3nnXtxFRTsaU0`*(i@xyzQ7jO+wGv$2>R)^b+O=!p=sB7W*3llyf|2gWbsNZUg#V|2R zLyLA^*_?AhxDb)JxkS0Uu-iG=70vIm*UEHRCEb??0@O;5kFa@2 z!mP+2+JCmZ++CQ5Z{bmFsqsfQ;`Lu%2((7<^1Bv53W7S)nt5`4s!F7s46Zv)8R%=pP;?bCHrww-i2j{(+eaE$q9KTa0zo`p z`q9OHRiQUR0Dr^Y--&9V$vai3 z_Fx(KB)7y~g)hLMlyrRkV*1sH>PQp6d6jDunuYG;VX7W!SERBLtwj70*+#DD&)D4l zJ^Lc7K#H-W$~FNIK_I)J_h1Q9l2g&VwCe9Mil8Xb$w!INaWJtfNgWPx zs$gv-w&-}~e)!-(kvJ_nLipCd8^BMbFBvaI$T}%xq={XyK?H}?H2RMfv_rV9SWc2J z8<608IASkO)W?5&mXUEEi?8R^HoY2_?q;mRdO1Q}S@4}UboL9Ty97#E>-(RD7UM4? z^*A&$94ayj8?Mq>%_onX=r?Yc4j_Uf@P89)pTpP2zK(tg!+|!&FsmvmVuoPR8+Q1@ z4LxS~U&68?^h>cbcBsGN7KfC9jX!C;04<44tdqHVJ-}WqU$gd3 zl>eNGLd7FJ@Vf$Fd5pBMIir8AIay~_DJ@0R(4hh_IQDkiT@eFF1ppjYf zLP;W!>!-&1l7gFvjq8KO!L$LnMR?AEMKxIgVOardNRfK1fr+J^A@bx<>^8xc_@~7r zwV|Q(#JDW$keA)GeRWq457xf0eZQ^O&fR&AH&CxaA-9Vswxc_qZ$OY{=_)6l0w^`D=sfEHbpe+hb;+BMCQ7XHGYcy5>@5Ffz6eOcCUH=h7oV zCX_6ELzJ^vyKK(Wd;3vtSh}o_AjXJ>H5?e??p5Cd zTJbjGn_&i!3#7uloj6#aEbO{kyuyM-1n9KnVj(tyu*8}_Ze25}q6^TjxtBlP1K)aF`=B_ep5q#BzXF( z__x*ccgSP7EO*RXU>RqDe^zlcTkb=pP_VkY`^zy#a$99Zd31j-zlItTm?1#5|O9jm)^!kq9lsTkY+O; z;!X4*GZ{aZ!b^|O*{BXd%B?JhId=tfrccMuSqEsOw}vRRxJvS1rUs>q2j+FExaW=tYydE+l5?vXjiO$E~SK$baKPgE>|h?#lGqZ(V-Ud5Y&fvaMW(^JMEV1 z^hWcXg0-EqrWhCv!#&315qvV;8~btR_niw`aFbFjl^?-*?<7Cx)#_fQKXs&f6Ed^_ zqfOu#omoKWdvKV^zDBApW{~Uk-Uuoe>yI&Ojh=9sLY7*+&&!i$@l?DsGaiyxoHHix z>%7|)iXIm91NC*7%@$#NPsMkp^=nmR4f<@!-99r^E>PUL3k{g`d;w}RIDf#z=Yr=d z3Q!CPj`hD*)(qV-Cl<6$C*ttJFz>$P-;bsD_c5W7jh8O7y5}L6*60p$3tIUh`HSg+ zqc!Yf2i2pTyOJ)S#Fv^)3$Vj0^gAyJp@_5A@f>BeuU?~;O`}~_H{%8V+~K+7iyR(a ztn&U0u2Yl*Kt0RT4!p;G^X5%BK6kETC>}L2@pr&+Wc0jqu10Bsnf!eC@^NV9nmBspd~u2Y<}W z5wokw)!7>2bcz}OSZ2+^`Spu+I9_%~_06~_LKMi|!~u!CWIi{GZ?Ra~l!&>`O&?`l zEF>b`&Ga5EnxC(DVmbWOS-w=m6j3%45xQ{6)nH1op|OG{!LR|thITJ3(u+{CH%xE$b((sV-^{g33efr#)yElP9cZ0}z!@ zkrivHPEP3~m}Xm^a3M5oC^4?#{`N|~LSHNxo${w+Oi^Za-kDoB2j2}(fMc`pfngkJ zOKIw)^-;(pK|}35bpYuE!p@@MD_;8GG;{ioPNCftN&(x%UUt0#d|{HgJG7xUhXxS~lCr0d+rKxtHMeWQl) z=4|>X=PWR=2*}Gyu;(Y5p#=+w?wAoemtNbU1w>>xdc;~Bfq0*ZTYEX!V34wH4>kQ+ zQMBjFMf#6-CLO6(oa`tbPTunrvgFK+l|l^{wU@671VgYvdWxrZ+sK8`iMP_J(r*&R zGeqzmt4q9%@-%-Rv8U_7X^$N|XKr%+X5`a~#Y;hFsL|)DD0w8YAnO)1g`Vdz|o1g-DctHK-~T_@B^N_|{p4O9zi zWuDQ}2`WWXJ+H+sgAkXFEI34LdB!P2X?Mbp*+M*qWF^JNK#$ZfU!;qi)1=(x}XQ@8FIdGqUxCx&&20FaA&!oRN$F_|ue!mjb zlb>^p1|Iwob6EL(VzyBG##B}Lw=(0Km+V^R!G;dF66g{jMRmS`re!3`4c)NBdZgC_ ztlL>o5tn&-;>uF|PdxE8p_v*N>zlPKodf;&5m!bw98~!DglUI*59_TAO-o^E7mv8h zCMuQOgl-8Zw@wgd_YIGSlyk}~HsMpnJU$kaF)}|350j^#95&-|bI2=tcol+)w<V`wK)WJu^H{VNOWT9i%&K=7Xd9C*d)pfhE%Qml2!3*bhqSE zdPb1$Yy15#&5;3f_vS$)KJCvwCZsBlRC!!Q@m~4RGAG#aoGzNXmJo7w2&ZD@EG|-J zd=K#tt)>US2X=$RE;naLo8c`U-Vjjt0@(R#bOdpbX7aqxW##z+$T~&czgudiWg?o| zL||aHwsoa9F;%2EpEn2IYKvlYd<8bwsX4sJ`D+key8Eyf(`A>&eQE~ud=GqrHDb>9 zDI<>;n&jTOxXf+x&>8POH5>v--WFb`Es*nLwp%0?L7sr=_Pg-mof8L=y={< znK2}nP}Vt}=G=wkver%Rc4XkB?l$EzSMx7P6s=kCB|Uyfk9V6c?r3!zSV&{cUkxZ- zAbr8^Z>`@zaZyGy?xUY$ocj$W+%i|0AtH__4I`1Dhz54ET*Mlu^v1EjoRFvZ_rOL)bqKXarAPcDAbA^pt(XdAiJu5|*U4KmMeRF^L)nZ=LmC#h+ z_KIB23SwNKlGAeZI{Iuf-y}k3O2?D8G|Mw_k#SVRk^-n23C}2}_ufiJGdYzuQ61(G z6U@I-u6Up}ohPlVj71n>!znZFuV{op^e2t*1xprL!sB46YeYQ+W6-ThfUbk2}keav1!Kdw8-to;G2!uZccdU%4YX7MC6BHX*2q z2l6Z0Hupo7JeEU-$ZiEOel6c}fq+aaolWmmLhiZ?tJ+^E_ zdYk@CXknuD_w()Q>)`bGlswNo40X}Fw4XCsZxC%LRJh3knJGP5Sa~*gFS4y#V19FH zz;{=%h&$c7SWmzKE)xmXSM)7m2#b-CQT4{=M*#r=8m+Wt&yRweJU7XCoM<@|4>!uD zSOm#;(&S3@=$Sr(l`I~c%(31G2Se8#}KYsc}Ep||ECnQt< zcq?OSknme$=ln8QZhn{v>LI@nM=-x0unAAUDF*LM2!zMGsZi2?}8$nY5i0=(E?blxj{HZ1p^-%Cn zHPeNMtoED?W}JI5k`IJBZR*EFVV`n?P2e7J1-eyNtf^?b{|{Sl9ahyBv<)jrN(m?p z(%m2pN_TfkOLw<)gCHd#-5}ka(kb2DDIMQB{@&+$pX>VGKm5nT*=O&yX3gAl&por1 zA~A?8qdqIJR$=u$Ui@M5<~u{4p7<^}nnrrD``jV#{cw-)y^Vh)_KgiG0deFH;twgi zJ8fcT&y~MCC=iTr1BRlbB`r^oDsHmZ|g!hPKbmFmX{fjGTNCW66%@ z%GJ?kSnGnqPO?z^#|Zl`Z&I_GFRbcnk}FR8dJmSy$$}b`HCB6>6`j4@dm_|H$v-l& z(@)7hI9$62C4DhK`l-(Uqmq)@L5hyetR7Z~uA%}~eklDNgI;FOp@^5Xgd&}kmDc)B z#=9{C!?=+;O8X+ZhQXQHgx;owK&<5cD)spcRn&E(ew zYjE$4ur!Gf+?`A-Ha(lS)}=|d&u+}k{*>49ydi0Hq3K$thc>&if?v@o8WqzbVaB$u z)Ze3MJ+l@IW){)_DY6i-0 zZ>e8LB1_*Fb$LXbQ7plTB^@bE~aGdA>IR-VSE z4{8|ZtnLd$hsl3nuS<3nY3w@1q_B>+i+khR+v)lwm#k`d zSsSUYN%h`;=RD@s2)$c$l=1biEh*GqxX1RuyOWBmfwzAy3x<2V{IM@viDW#GbE|Uw z#5g){4VO4!Wz%~b+lWl8GySG^RjgO~50{z}feu-*%0xz5I%3C447i*agZaU){{Cij zmAMamSPda>k=yPPtQUAHEvq>qM|>o&?|R0T@BCwK1%Cb2RNzlt3Nyfc|HM{x7q#~D zPxu^bqkz`$iO6NvHUpK&j)*-Tyo@wG`44l)W}2zt?>fG%%n{zeU@+DzO=Y8kx4W90 z{mogFO(|y;8Y(!R`PzAb^~-Y%OF3mME$k|q6V%HmQQqd)b|IkPA(bx^CCBG29#ycJ zd4;vUd}|lNFEZxBI*X;`TPt)gzfAVm!ku15pBs61ApSA@rc4Io*lQ}CCTjel$_ht7 zpv*7-0`>||cjj6q+~X*v-u5eL@DoW#o%^46is(<Z_ch<|casgseH)v@J9*@iOS zP6%6nJ8gT@Y*_U9?#ebQ@5ZW!?+UprqDItT<9As}%XvvsQTS$Ep#K-GIwY7QIwtlS zGM{mmvwi-cnsUra$J8`!4A!1h?#Yo%xr+~DY01LKtT0vPE4JKr1RTRhl(vV(=Sei% zuEPy?1Gg7nDdp1T%XRti2?)%li{4h541XgehNQ%u7clVMO2ov(EWDbV+$mpQ(s7=? zUin)lIW%JCIer0s=k>_?#(L?-dFSPJt*t0=`efA|%l7*zJoY%<&@e)ZtvhB5ag}w{ zh|JNF$($(x`ivFZ-n)iuf!fq|n?#3IN$pzC+jK=9v!;=VsOeR` zdVZ5NWW9G~xZ-blV1%^s?Ial0H>3|ve6|Nke3)!(8JAB4{DtNlJsVx&!nqq;snm@g zYLxm{)_H16@x`mYVrkqDCnDk3#AM47U0m$HRIXNHBI}MjO^HjMzRC|QPCp&SyQQTU z5}G7lE0_Neh-YiHCs!H~UG>&RJpohs@0$*!y;Ia%rH91)&niCf;R3}b!a8dKXd1b8 z8@-qe+DRcH@Pa}@2*}7VKgDB7*sK?Cda^(ILD5jYg}8(5!^0sUO9o+s6hu+G!&&C$ zmX_%#65#|^yT7ZGT!fz7l(~G;)Eu9QP+`gHhEpX;qtW=z+e|gf-7ohOcU4txcsJ=X z+CD_OecKrR()b>I>8p`5`^9!J9=Er+Ay0YR$V_$O{0DL(c7BcSR=IaAm4*Aaukt7t z5?=Pyq7w}*cfeICg~qSVptOfo5T9KbVt*sroMR<}K2ghjdMugGI1`Xrh1s4nP%n zhym-+a`^zNlNybV)KZBIx#rVFpd0Unl$6wWMMMC}%D?HSKhM?Mkw)UOe`}i-4B_pM zA9xg-^j3gNh}3G|LB6|CeHYO`7076`cutGC`zvacW_xOjR@lDMC@Ei}LH~i!rv0<{ zUgpjdqJUAX8u57<_+7L}irYGT7Z;aW>m?eZkw7%TO-@DW`)H&yOuEanrfvp77@jgrw0nK$5YJ&;SE(w)R{d!J$2od=jM`2wd&Rn z4@(4TAV|`Q#dKaNnvl<6G@b9}?yiV{d^7~9O>F3KRyvJz{e&v(#P}FrFl2`fbDt^E zn5e1J#g-!vKivC~m^y4Ny8RewUMs|VaA%@5Cf+0>@_`6Lu$kHG?$T|~l$MtE;qlSV z&Q5_k7UW~G+yJdwue6prBTZYaw5Dm+nCsivlsm`s8a@LtFi%Q00VpofvlwBCpBdcfhRlCxgqX(+nwzC7mR@2HE!XQ?^$mk)mP_y>_V zA}u-^RU{1a<;UXb^NnZ$18eK3;9xk=7ofzI2JYaD250+L8Pq7i0;uu?i3bn%kv4ep zeiIPv%ymgY6EtF`&O;zxPTG0>=EYD7`)eN`ABa2{z=1-gd=${cqR5pAxeN=~bW9Oq zZf@2tw+JmyPhQYU(mOgTcSJ=((3!yhsQnfzuKmQ~ziZ~wX=p3C7!&AKbNfA7+)<>c zKE;!7q!`5IZB)k}J`k)pG5EoT2t3g9_rz7BekR zHcLjK@C{VAMatADthOvow z^x1rsDJp2y>6xBZ0e2Ufel6*7tZvIWy^z>JlR<|7DmNO$QekF6Vr%$|=uh*HLmQ7F zfml7&Q_-xM27k|X-R8YyiR_YA{~m-gH#g5LwYi{QURM!G(<<%JLSqh(8N(BURv(ct zChvzEwe*wu8rrh5vTBQ&DA0RT93u?^o%r&F+ho|g;U7dS{$IZuh2+O_)o-38dV4SP zlzuuvocpug&^1%xP|?{CKU7Q^(ErGyBF$RJ?bo(Jne*I^gm1cRf;@i5zGou^ug?aW z!MXuQV>X@zBdH+wGkiW4FgPK+d^Rb%<&Na*;UKxy92Fzhr1$+1 zM`~)St&58qPndXiPRm64;BmtwO)XVVb^-PXL2J5|6+E%9EO8GTv2c_UI9&sGQR}Q+hqyKz3{UF~l&Bk(Rt5Q5M}qho_ozPBtslu( z6z3*_fERfMNEpFQ^>^>ymFTvlyo82bU0dr&pw~J-+#D4QxvZ$H%u+6#vf0e}$T%_3 z(cw3k$XHCU5y|6rPR5-UHSnDlvd#+QVI!EOyASI-a2(lOjZZ5anzQE*1teft-{w(o z4^vhAf()_nG1-Z=UHSbY&%9g@9ve82=_uj|>5hq8YTcedQi~DA@;)B(zBhs)mc$O=v_^D-W;u8y zB+$A+0h-;!jyOR;I!6O}%s*EX!NEXACLCr)BDC*w!_fEjX>0rlyCxfKU2Tj(3R>qE z$K5eM;MF0mOF-RH>WmLr;()j~rSu=HN1cJMfi@a~7Qk0Xjnvx1!sw;!KA-8Ci~YL+ zu=xQB5FrfcATa2UAqG`omH%$w1*m8oFE(U5M{v-Pk-ZWS5MaY?&_TmdDwg5`)+0N$ z75wiSbd){>Aj;%>-kt+dMTO_B{oVCRv~IZ?&o^M$+H~dbCN=AnI9x9b7oIJAf z*74Rnq5|%8%jhK(_<0(|9Qga|lYBs(fDX^}@3d+L`udswOr;^l-yhoLWLczqW+yaV z6Eq~Ha@s*LGBVa==SU27sn?G3lsHGwxg4DHMOkqP-JD6`@QZ0XLdg;K7GB+9U&2}k ztcX<9_VxB?e@6npNRX365x}H*d%k73P;1qEz3k!Y;ZddE1$(|TTK?ZJMu=t;`#e1? zHaNghQc~7z7&VQJ$)|j<3TtRM!xUII#F&bT*+O!MMmTGf*3l9yL4k%<(aZR{byR;l z18vEh_DO*rSf^3p;`4M08i^Xv8Et@um@MFiAyR9pM3$$cQb;WM*334=%E`$ohI+=v z%AQV=@j^@OH5&!uHG^22>qzf_YL77ZD>sOdWAlk9Knw&d1mqe5&kssR;=oAklbaQ# zJx*6&!l4p&_w|V#QBj*KXH(byaR#S!PySSgheS?5xSUnK!P04&MpYH^rC4f~Atm@& zi_4Rh3}74^M@Pfa0#D*VMKK*k27+m#t)t`SfBB-bR-JWER~NL_Lh6D;fvul`<&8C? zN0jA`g7mQtwf**%8{1`(SYXi>t7jBX-3iN{&*W{^!YQ3}0<(a$UZ<9r_-;=xqYyDr^egtv~1bBFPo?eRvPRyS| zRmUK8RqY6`UDs(Mr`N3RKjmW3YaKc)$2!$-r_@NIGsIP~{`7Z$x`Ahn5H!~+^F)E= z4@0^D@PeC=knnK1cm7uuC$Y~&Czm{3_Bdg7 zzx?v=Xyr*T%fQFdwme=fK#bb`uQ^B;gJtuTAVv*Ont&B%1`bS?U?5_BeSHCe$fhEx zSd>v$5OONFljJ|!rvB%hGy@Ue8azKert*0t)LJc|V_;-ElY#RoIxs#S3zoN#fK&?x z1_q}GO-{cVILJPr%)wzX3Yk{`TcHFo*8b_k!^2tNYCe4U06;6J+>i??`0Rj-hi7NM zjTm^cNIZ^ppt^R(j2-lPIO|L0_e#-eaxNqgfhT5>29;64O?ML$6FR-t)U~c)CD1kx zfS4p`*_@6d4?yb-*}T$E*VosFKxD8AM*F-KXWS#&jsDqb#(!Q7b`kb;JCL6f=QA2V zTp!=ncyv?lvN}Z_p6<2BdS2bW_!D$2nEm_iiGbsncjVjwkyzN^--9EBWii>U3xmSk zSAbtKGc%P76-AEJAz6yBHDjLfG)?+RydxRgA^!bya|%r1dF^S4N6CUig3!z%FsHt2 z>$CUV38Az;gPlei?W>)oaA%h|yvd5+n=2nK8E#8|Recyezd$7Jc2JaN6}-B-T5NKW zJHi(HWj;+)Lz=Tdnc*q8)){E_rv!&qwdAMSWS+Sgx}cFiXdY$pxH?q62A?Dkp^{Gw z{r*j@Hk$kn9lf(R5|7m@T@H%oOyXlMoj9516L)Ylw{o_~>kOof4X`_|B{fF3ArTp* zP59>nVgOCeHhAJEBuvC9!0T)0B$)(YiYV}WMH3xfSs}v0!kVu(>jGVkd*j)`kSMQl z2rlt(+J#zpys^6a9>^X{qN1W2YE9>fd>;G?3#qpT6G5o%7Xk-E2te>8WeJqSYWDh2W123?TY<#L%h*0S+)B5H5fQ(&l-&H|gM1 zE(Zx-kO-fyk|&MR+1UvXIBGC1W7mFKr>S%8cG11Ay`-(@SZgo zZT82OXjBD(HsT_P6;4QpnE{A1+S?lhvDMvO@odpZ`=v-od?<;<+mQjhdB^A|YNV+3 zYkOP_3=DL1bdZQ00qlXp?MMZNP^j>Pfi*~en8p-@Z=afq?+M2Oj!Pzu+lkZVIQ1Wd z+GJ|5OER^!W%>^p_ium$+jq9nH&9uN& zF1Cjuu^c{DXtS1U5@eWW%gtPQdBEJ>d_^JP{z-)hI3-oc{foS{wfr9~Kyw1b9g^U* zwzdWY1x*yIF}`EaF8CL^xjtI|V5O&`5?4LL8CvM40#^$ZfgFC3?mCJ~B_{2Uz_OEM8vT0_8$h5k}WmO6&FkKeVWDErj9U2z)-`B+< zUq8cTU|;}PB^aa)>pMGrpg=VRi5`OBZRR7@0QBIjQ`_fEY86G6zd0P)y= z&x~ABT8aRS&~~j8{EYp@w#+|6bnOD$?I2>4oRowO=8FWDmzRTW6aNEx_0=2f$=BA_ z{-F&ch+`(6=m$A1@bzPr#!~x#N(Vti{Lio2$Xjdpe(sARP%c(Q1^@;)^H@5Nw80|d zb_3T668ZqN-`@ai63m$dP#1^alM@-2Z54Fi|J%f~Al?kt;aRL41Qe9sl@&eUP;!cV zo}cjf+~a{6{`0B25WpPJ?~BTR;|uI?vPgyYgXQece|u-+t6EI1*Xk*{#6$m|3IyEl zrYnG`5kvy%e$a5ZUN5!aWADWw55dyk*B3negX7|?kBHS~nHRFV=*;Zw=CUKZ6kMdM1Wz?uXkaE@9E6E1FKP<#7F_rLpr85u;|+uQ%n z!AExhNQLvh)2M`j!4=LY%Q7IZ4v7Yy269*}*TL3S)4Jm#!Gf!NS!%3-Y!R!RoE$*Y zeE>22TVF=;(Q5qTC6^Ty;0sBRK@KuoV}X^%&PCi=qC5W&qU2q(jc0N=ZqHdYd<&wY4?d zmoeXinet)+31GVKShw}l0rdsm1yn#F6yiv$R)!B;0Yqa7F&y}hVP;%mmj-VdVza2! zwX`6az_@vh=kw!rwbeobn5SZYcWL&YOBC$YmVS+h2+V{@)37%}AJkn_1$=ZNVV$_A zIyDC%U6vB1O>S^_-74jI!SD?*%flZe03eM1=LZ*;X$eZ*Omq5uAcaPDTF~jsp9DX%y@$&;@5XBN4Oo3=D)- z81}JzZhwJ7$P4jF!h{rEyn$#WKUB)JlYxPqK3=bYaUq|PVEzBOUZWW1cavq>4V~aP z6za9L0;A}!2GBZMESm5QCT0#WQg8{#sd0stjHl}8@Q34a+(iQ*g`9yw_83oPSlftF|oTi33=qZ&>V*1pYiYZti_|F3dnbl~T zjHF6{fC)yEFo1b8b&w0$$antr8oI0J`X0X3H!*~7k^fEk;xWRlZCNm}!-4-{oJdOK zlf+;BsF~E_-3)^4`vZ%jBx-dwy`iHVC9eG}&Q=qs7B35h`DsEaC8Z&&R4Uy}VglF^ zgZqX)Gt_(@vE8YUf?cfcPF&H<$bXTLk#hmARoB#nxO%$3$4w{e2M2=ybU;pGzrPW? z9C3jB@1LLiskG~vfN2;2;LXBZjppY2G+^F1b274De5GtY{oU_vns~jVuT!zf#aUTP z>dL#`_`6yh-X_=`&9q(RNd)q_BZ_8~@ehGk&&-ReRY*Bz#Grwe72>cukGA)dT2Fp5!vyEs>k25JiTOm zLaO3^#pG;*WKFPBX|Bpx#7)8A+hgx`|7!W*gI^8Ny}{l&Ubt36j^@ws#|tV-jP@fZ zs{=!~EY`kGw(PYPe2}PQ?L({AVzoV-zXk`#2>1zzgD}E+q(9c0>0Y>g9pvnzD-JDhYdI0s8-*zM#MN{Ass;)- zM4RJlg~y5hf-QRH;2i~Z&dVgFl09|7KbP6n_MzYX^G_|pl!BKG8#2gMy$2hzn}!XD z95Cb1FIR|AyDM9>*>Q`VOB$Nv-sqD5Vs%+<8B_n*7x`FqlVi*-$+hs=#5^i8oTp|X z^7B&iE}4~ZRbwQ1Sgrsq1Cg=rNl?69MeopJ5Y!g##rQ+^q6}}qUkOgUUZ>o(g}~pY zW?_ZK{D^HE64wYnI5VQC#{k_?@312~k1GEgq&NjC#qR(d2R@f%0ST8agwNyZwC(xv zzccu6J7b}h3*`O$;ZQ4W*92jauzfpX9HB^w1I8!gbGjnl*9IZwm$`kjvWs@ZxA9&sK zGPhX%#;VtfvhglBBCRGSkX3B5rIYVNG-CTfoXn!chE{n6CM4d%L(*Ab;sf*ZDZsU! zgU%obF#bOl(oY=rmbMqffYa;ie8avdkg4H2T;#Yc3Wij3I&32Ws$Rw^0}>1YsOG?+ zQsHKJsP?r&r7xJzWY3*WQKfr&CHCYBRqJG?y+HHV>-$$%H??lZg*Q=z4Zb7AbmhGt zGQSKbu+85ihuJ3@)I6Trm|Q))N=ix2>JF@UJk$0@ee})3^?mh}>Jc6IMsy8vhcm+OL)snBAUIRP(G{+(}AmNp~}IzgogrqTI6b*0U zd>@cuBQAHI3aSV!kQjUX9n0eP<&rx1x? zb!@>C)VrPUt-1#w>4+Dzz*3RYAV&JbuHwJ;g8=(FyuBQi4J`(Y^?$EubB!z3KYvKgM?Chx+{ zDnNBxomBe2RnFc|_xkO=U$dODXNF=Ql#S8!kdDN&$-Oznui2)-thES07F2xhfa1T~ zC52#edoD;#MHnS#{L2lPF?S38L5e9_wU%rDKyCsWN%1b}9BUagK^sa}^DUcm=|e=3 zb8-vb%&KxW-%&9Sg_fH7hFjPr;{`}`GYKDHwYSU8=tn1teu*fioZ-;K= z;d;<%2fNL(x!5WZA}KREm$Mm3-`y+bx_Z;qARgH@({2FxWI@bfxQ ze+uOY&KkVfI);`mv$)QpV#{%oE4pLUcmB)-ec;?htrh->%OO`oe6_oTxujJiewo&N z{i*s}Z!XucS^b3Hh?o0n2}j4~8O|TMxYQNxDzXqDYm@8MV1{3HX@?Iv@E*D-NFbms# z9?j^scrD)|8d`#va`%~aWtc}oyU_cg+KnPTlv}!oubQ$));0(`%kY~u+kc`S8RcJ9 zIm(lx$xiiGxGA|A6p?-mJo%!2 z{Mx&mFOIe8ZY>759M{}A8w8y{9LX>&>E&!587VTR751l??(9D#)25aY|3`+*m->HY z$a?d=BPYu{t9sXN2Ith-=I#^qN_r{p-1)JmaYuERsGDp_fB^aPDV^K|r=+@3w&Zu3 zHINF%Q!7DI!D&cR&;#c50zbJnUuQF#!fvrURftinTB-SdR0uxuxd#&iPD4rV>rSJb-d9f>ws1&&Ls8t&W(W| zwo1~e@K#ZQ*3Sp!NzzCX!}C8y5TihT^ycC%+-^+|l?q+5eMST87Ovyw;EBtx+6T1=FRMs;Y-Qxwm6alVQJgA5 zcmz*-izT+TCmpCA`NY;szKk`n_f+o7k`Ah+c+niseEy)LWNWh~1sZ}-{uB5X4yv;> z^UFpta4x8C z{}ogN-h2Ti5(tU|EC4wZlRN~RA~D;t76|Z}r1yBWkCx!6zg?K>{mIwRF((l1u>L@> zJmff!2*Vw*Hn^|KyU3C1t4quINM&Zj$aft*nk{xO@sLR?TSx6*@Ha&><^L#!jJCO@ z8g2OD&dol$9MQ~RsF)c%rFZ=#Py987?TUU8pvGN*b6jP(=T3r7kllpVJu0@&OuY~T z8_3puh$9-AW$mcx#QOUT5f}NVy1v!-+KMPHuO!p|TH1bFPxdWudCuCyI^uSHnw0eX zP))$Fhr3>wDPD{+RTr^kdzzQ1>u{L}uj3QIiO0xYV?W%e!oXTNQF6RJ`Q1cmQ9slaEMhnk=gv>_$^I(Kq)_uFUTVJ_V2@iPg~Cq zg&grWcb9uz{jsF~vXUPA0hdgWO6z8WL>iyl5uS*Ms7$wI01%er<|&G}K}QoDH2$!KO| z*?bhi&yss{xrB7pgZcAlj6a^^rA$rURMl<5iTj_ektb`ma&1g4Li;TrVmeJ{lpoxF zj-~On(Y;&^VAyy!f+IHp;9T6@gcecUu`cvGWca8))N?$?tB3`SU-g71IfoS!5%9wO zGIU}3QGT6kvzEUydcYW1`6SMJMbEQ#kQ&(bYg8?TJ|z}xlqNApx`XLx>`$j`pzw|B zJyYv9A5q2b7-875wcw4SaDvuwaD6e|jNYdEe+p&ohWOBWbFHg0Ql4Gj-)q)i&-zqKaHHERO^8u8(_520O1F*K2a}oD zwaCep7I-~1$$1qV@dXRU7oSBE)vC!5d) zE{N05Zp|he+`diI1MO7R|CSVYaR2``#cmT>KVTETj(oYK42|#%czIEB5J}0>GcppT zkS)smW$eB4@nRu_j$t6{skW5w{~eT0zr3aIxPQS0+9*H#^iruI-Bbs;7i9b?A)otL zjsyl^CVl;d{z#wE1@wz*=7 zBTK$HleNH`jc*p+z6M&Ms3s??{&Un~%+ymcprD@PGe4QXd)sWrRhsk;bf^p^v+6DV zq!$W4TbX$I0{Ytf9=9#e@aAVEpLHKai*x<)AZBWcOHRcSMJF6ZC?1!i__tcEs|D=*muZbL_E-g!j+w69OB%@z|WDs|_ ziff30E>o+f&aKXc={k<5{qqaQT^1IX)^E{y1fKmwRT*Pxb@iCI-LU~#)yK+2gVNeU z=T^pD;I8Qz7!s)N#H|+xb{Q+vwK%LZ)k?tR<5=Q!u9)(2Mo<}`)2I}NaBkY75c)=c zlmGsZ)nq8iudc3c=rxJ3?qxGt!tBM@*$c6EmM1Olcn%(aI_`#O=q$Cd&y!Jmst1Y# z8+bbbQ`FxtUSrry#>tuF>+6dpV1d}M;d)K<^h6z#{OoZ#(R#MyZM1d;N9C+isBop> zQ{hzRH*~uMXn_q)5AVGkV9V^q}0XrgneY^xIle;P@ z;@aOfW+v?|mTeY`W)NLX>;yX+4LWaE>;8pj=kDj?;@T=mH-qREc-_z$8Oxv3*~$lF z3YTVQ?QpX3R1Ng-1k4kw$&crWEFaxo`z#Gc&(x8gd3@;6XjF@-u@VkW70=mw$`S0{6s`D+qDJyJT4!nz5cRQ{ zPlbRCg~enD`(OS7`r1MM!k_?*9Kz^>iWQiw`+4@4K7{fQ(WcEuzF7RF4?Ud1F2&-K z2s`5ogFmknF5xFNSMBr??zlUvhT7Mo#@h3755D!(LC%Z+Sy^Lat|J;s%ICeHR;)Jx zt?|LIh-x{Th3Z1ayRr+7W;arw$a2|S#~`^I+IX2YSZ$A6CEBL25E3cCqWXb8?y-D1 zB5fU=f1nfwQ>e&7^fl;V_%Kth2bpI*RR-RpRAurzpov6|+x7H4sMHl6vpVj|Q^=;? z1fhp6n*1rzcmVG%0unc=BdQl{Hp{6Hhu7-m0Zt}YsA|fi?Zw<>Ihz!3Uu%(MX(;Mm z&4$gkt48j|>=$RBbCl)RhuC(TRED(1&1A{nKs{wFOXM{-C?&2rXt#ReprWFJ|BDa& z9We<)9MC_#3x7usDSwe*#c)CDc8PXQPR5|D9}pZ2s%3a!#Q4ARS3^`>97dh>k|Gc6 z3sgeh_jGhfL_`@JE3WGef0r+vd;DZSU5_7-s;?S$=~YnUXOJk-Tm$8GA}t+Wov+Vi z1)4vDC-FvtUgpPOW=~aS(Bn;V0E&?jpw4J}zA5n!kG}kGGmR`P20?}IS6yA-;9xiy zT@EQ-2$zB4YLa1)oAq2}AgF(Wg37%K-pIC!(PTB>+6or!a6+B@4UO%*5A85TUA^dp zlr7@tfy)oGfsxtIS+8>n)AO3z*Pk}vt1JdDf0x=0{jjjbCh+j^0COxmfHV3B-(ddL z9~b@+!Djy`DSI(wm%Yv6${E1hA zo6ZAC4;d}@Na5@I>o1-%=0s0q(CFS9oTw{&{8-^j{;njn#V}guS0c9ZR0ut;2i<4l zf)JAT&XFl8wg6L8ssk%FH6CIY6| zc~i5?8T#1Uw7qut33M7?Loq0`tQKnP-TxL9DH&h~-O?z>8)#~3;sRa*1{F2>+^YVk zhEbK?7MPSLU3G1!g!tS_l1i*S^ANasLp5ZnJzHb=i!Ne*WKW!tMv_*Fw;a!KA!rI2IKv{ZgSHzXPCVq z8C|J7BzRhEgYV*5$PP+InGz-uuZ~nG&3p|zG#^%gwP*j@bhWb@7wugxeUyLB(tNZ_ zO+tZtYjOzt-1#6%|EaHhx=(cMarkxo~e5kC$ z;TVr7>l3f-NNHZ-nc#Oa3epCv-1zivPaM?lq$;JI6p96@9gcSE-zU;-VYf(b8*v{qpzI zm4d8da-3@H0i3twPcBbv-g?fk9?%~Q2hvH^|8!vTzAD%}<)bia7LgS;gNyqgEkI<1 zft}k4p>{}d7)n=Dr>r%FZl(w5d`8*J>t_k4E4E8%1g{1@zCyL=;#iFz>M

&X_PLM7GDz?EJwWAx9r2!#Nv@1T^9Mat|x*>H;+sVM0{`piE<*IVF-O+mvz-K zpKx<@V20F;N z-OdQ-bekaB_=>tQR11Gdq+S}*wi5V02pp6jb^rshu(RiaQ&PzNHb_5-F;Eq+C(i#VrYQG)3r)AD0@N5p|AE7pTf|KS*U;UOr+cC-D?7ye^D|C$n3T zv@sS55fc{v?bx@H7U3FI&25vdR!Oq`En^6-x-jm|S!zfLuTS1Z`Gu!ag1FDoji0%N zZTCUbI3sG#ZFhr6E3(KdcGP(sy{X=d#QMRwDOU{hdQ79A`70B!s z2I9?{sPp%0lcv=9qTjeiy1t#e{SrqVzXAU9k`oR8~a*7Ewun?(z&h zJUSY0bg}?%XONsO+$0t<@FWSD^h>wq;uof46O7Z>dehhSFmrpkOZ96MU zv#a-K6@T!iMWSt!@+dC)di4G0<4|?+l%Y?n%MxFVzwHq7$l^J{!mPFnx=h(vMonQM zgb{_)VZ7qGW++Ja#N|O1=rffIQ^Xf^Cg|cBM6s>-zV%xwXvXD)M3h316je?cYv+*# z)sRE)q47fP@Z!LKK;x)~FeMsh?QHBz&5KWMk)M>hny)p_#w^&-c~I{3FGJqgG7moR zGUh4(M8v4I;=#T}I znC__tfe;i!vjFu)Gw7$^syvuL-vwknXLo-sRPsqE518e2vF^Be-^+*&Rpq-9#^p>^ zq+@P;o*#x=9u^UAYK6PEq0JOAqhQH>B}*0XOSz^)ICb6&)8=!?F)QWISaWmm<+` zAz$!JTA|KC^vk#@lRM{3P%IizxP!-YJ5SQjzDtFIdyS4gj2cnHUr$(i5w_KI3(T$Y zwWU&HL?T%ze0=P-@n1JFx8gN4m?Oc#!!t55fvBt2fpX{c@={n)@e_0&3sM(TSb_Uu z_0OO0oz*loBwh;(SP_2vAh4k?f}fvGT?6_-4Ng}(k_3EOi|eM9@1;420fcD0je*Mzb? z%kla^B&zQ$A%m3@?PfO-nPtS&5UwLHuh?MkAO@k3ID1HJ}QIRa%PvLG#bgB*5sK9!I(@Uo$B^BtCXTI<>JZFQW z&ywdNw9q!60b>4dHi0n7f zF(%Wm7v6c$V8;t!aCqT<+>Fz+B*wkb?wY>+OB~v%Ud;J${-Q-sj`SQaFGG7)x>SkWKIOteteO)rm@8{hXEEV;=YUTJ z%RbiKfkV)E)#=MGTTqr5Y)A^unMZ+?Mu_fRHb6Ht zW*Pdeuy=QNNg#)Yyy66($60!M??ozuw#i9HM}>RA!FoUnmy#4p_ZWZVSVNC+z#T(R zs9#%FxT;^QWJpYG>`N%PO!1DAxQy5}ryEf^q|tkRI6nh)``@UAadsAHm;9^afr(W!}c+Gkx3k|Ax z$qT*c>0x`(tRNME5Yk?tB4_ugjoq0&vf*h&Mj`}-Mu6!X$g1_ZGhwA7%fcA`{mm?q zBFrPP$JZKJ_Emz|^m{J}I7@Hzulf|^^sV1Pv@_%x^eI+34*HQa?!nl&z ztrG)Bn+L%i8=O)8Ah89CEYR%l3xvMy%gegcX5b@b*CM(+7+Ba!Fo<8MNPQ$jH)P$6h4qAf{h{B zp(8@nxwbU>_P_vn+EZz=QU~t0%CSBsQwYMv4(hr1>sDx{6*ib{XyGv%C#+UfJ zUvY#`3`}PgIh|CyhWR|~qz*%nS5#g`Uv>(8(a18}IT^3MxK2X+c=bfwSvT5ugVVIe zVf)Jb(Fwn6h^8a!+l$LxX2L#nd5JOsPWq_}?5Nn9N;tf@^|oIG@Lrnp-)Z-18G4;n zFORY=#kLNe-IBPY+C!Y@+M4h={oqqz6AC7Kk&p0_vV7OJ!ZLoK8-f*K()*>~6{HXR z?k?!00W@OSz9V*!J`FD^DJf7fiIQ7kl_n(wWkWl46km5QtJVGT()O5Qnf@v)gQYrr zZ}>Nmv;W)i=W8REDb^XkloSTKA6Fe={Ykur1*@J&r;jBiTaf|0Oek)(Oo{%A6-%vl)G%wd4lLpGn!oOF(MLTU zBxF)N&WF|L@QN)C)c4t%1{K(l^at<*@8eW9U!Hd}F-^Uc`zD7UT;NABFv~HwMSr+%W^_j0CJcu z(-n5Wh`WuQktzK81cTw|Q(NZVhZjpjlBzE@Yl^$v9#ky}w4lFs+v2~LdlgVKKA?-L zefRd^%^k({Qwpo^WW3XCy`AA73j)y(DkcaLvKp2Lf>ejmav7aNc5K_XH|>3WaQyri z%s$6-(gZwc$C3;=UX~!L1nE~o3gxEwH9(VC%uN71D&jC8V8~ta9)UOyOlP9))al0W zHelx5^O-__$5%ma=)!?jZrajq65-J{^OcG`i-Wzs{U`PZ~74f-9eOu|9d zeK#p`c3*UDkQSckb_DBp?fkAy^Ro>{VcOCJ=zn^~k^IP|YM z8$@j*p7HW)_r>ylr?;Yot@p<~1%-wB09?@w`=eWLh_}`D?XWxoz{E7kyyQsk_~pLL45syRa(QcC&(z8}$$>`@!7I z%*SA%o_}}Nl-+teZI?Cp1-JYBs(4Vur8FAb+PN2z`dKKvM&qkBgd&=!#Ex191)lKuB27405!(|A> z{o`V?pE15|n~fUC$7pM34f&|bJG>Fw*Qo{cd6JzmqnVVL%z8kLndW7F&ChC&>UoV| zPT%fQwQ*?bHwx&1QMDv~nylw73`B|Icb0H&xMyT$67=)hjC?bF$#qzYq;JI6TfZ+4grP-;upB=LTd{GWD-+22G!J?)Xw162 z{l=e}#y1oKCwE7mC%^ib!<*5TZShjqsJJ(_y-0w-HFlK9dYk^-ii)JbZEWNw>qB~5 zw@!La@80B3!;D%r$(vV26fAir!&c&!{1JluMn2ypgYV4I^Z)o?nY2-Q3I14e3f=hI zukTIPq7vggpACK45*foO;h^cwVX+~lH|F=0K(^}2V$Ks6B_RFu5Kb+(x7gUBtoMU* z`6uclp<1QG9l!|RtarX$iiOV8kbf}2g}`VWJUl!w$Tu4}G1sd@93ZfGkN&-979Zlm z8K9w|fe)@{jY7p7@)T{prB}Zrlww% zwYmGvu(W@akEkz9w7oK5c~!eKUYER>ZMvR<{bZRUtva7JeF=f30e~(KcFXa{boQB$UdmoCX_KboD#j(~TS>ypPS33RivS!XV zH*q<0KY-qLg6^~aGWtrnR&bSdSA~losrjK*ILe5Oe3vv{XT&SsHW!3UO2$>Yus5lR zrG4s6C6S|Qoh~ms)HB90;!x>CW;C@FW;zhA*kv-Q?|nI}aO&(sN=Bc-eu(mmajjd@po;-QC^N-AK2jba!`ybR!*tNOyyTAgy#rcZu{}`*+TnxjFaF{m;?a^0D^% z)_ULPeWH!zjoxyfG{SquhhZlDW)y&_4uVp}#LliJ1m$&wfHgWxX5GMNEkS3q9#ZkO zH(W|~KU)|5YVx_?3Lhg?O<+q$@Tx6;rC>OcNr;p+B*pPyW^-DDiX&deRfE&?GwKGN)S_3sfk_Y?M=U(9X@D^c#t zp-#Jph{uR3a5i{F@+Tg6^=5RPG9GC;uv$`*@jrWv{U872go!-qzf=Fd)qe={^+?a$ z5BDot53z9MRga^Xi8z654J_q&w)L-%08%A^ud^I(L*~oAVRLywZAJMVfx3)Fd2L4b zH(x=rOcGbxQcHEwoPx&fN<1)8T6M`%tD?}}@bSc8>zU4~CUck#W#A8B9lrr)OnAaR zTtJZF{P@oqkjN|lYp{^sy#+oSu&_mdus77HpBX8(sYD?3Puy`$R{EMqyOpU2#xPPX zv+D~Zf%bG{dyvHLm-&5evx1N_giD*c56<+|`1FIpvp<9M^67HRM6L%5SaRv<5l3G~ zWh?d9!aDp^o8u}^sN#9`v-(2`MsH=cgz#BYizKnFA8a0b57$uUxtyH4!7SSa^h1BrYV7_xVXU8LB`g}nz0(zgeMKmC22 zIe&(^M_%a6oBBET=zO4FT`2uMIdqb!{-m6S@n3(y28)I8`d6dP8zA9{0@;_8KrP$c z++3v`Yl%r%jA(>R+eVl=yM7cRFL3F~zU6|2I7k$% zu91xPhoz#FibBmH$yQl`P>%?zh@YUtJxmE&N?5m(V2&?HT|G%WD8b+)E(PntXw35Z z5$8u1C%lJ;2Oh5jk?lfF<)K?9D>QA-mFm~^iv0rI@G93D1poip$*@Urc%B+))*9dg z8n}ds37KA_bs z@mALI@Fuo3>*An4inlUcZ&;}R%xJhtGDNACJp_T&Y@3XSD+mwD(JXw-mWV~9JyAxz zSMzj??&{QjW&HIODhC(WAP}fV;d5G&0piX40ox8eCw{ctflFczZdj;}1}=dai>Gr$ z^*>SC;Sv9vBb}N8g{c3Is!WOpfC#Hrs#AM;d6|H*7r;t1-Q`h=e*(P{o4IsfV$eh; zd+6KQO!aXR-Y-HiHY16ok$~mJ#l?kWtRv?o46}a`bUnn`nF_t2>*-Va=qOzFbdPr^ zM9xk9cBqSq{=Gqbne}h6FbVC1&F`!D75cnKn2T|N_3pn(gg!YJu-FbV|D2u0g6?^3 zeiN~Lo~tFgr_AHyi?V&lh8ajRAqP;I{8JW zIluT)wOIeXAmdx%aEuM4Agl)%IwsJ@fZu-*_>Qvym8(|yAR9_C$L~ZRpc(I)SVlrZ z5(hQ!cqg%UZatw-TL_AgqS;JIMSC#uG=4Z@^xxhf8j<3+$WIrT zk{B_DbRW9?u%cfpq%-vaN}CgakDV@YcPF$JR(#N&qlgkFD4wRTTCEmedBlh?)W{b1 zPxXYmYmV(n_5ROA;I^3o@!pug5McyJbLv4Ds>kP1fE!kJ4l60h$-UFj!Q*jUGuXA? z>DTW2YJ9sr--`dM(H{xUaauZ!CXd}`N>0%QgVNz;1X!V>%9 z^QXHd$i)jpJil5TNr7*MW*(Xb8s8Iv^>lkg)hwOHdcQzAZi1{_aUG-=SkDEd0=I)1 zSa2XgM8tz;^^jQ>l$fTbW>MlU*#0n}0AwzY%dFD^8{&2cq2w*p8de`_;zd-N z{0DMH(7$zecZYDwz+GXz+{|p$?NV}su;#=pAk$U~$-kSPZP#(PC` z@L$R+kztqsf$sil2QP4f0Ui8Vl>jyP9bME&h8lt05RjP-^!I-TKk9qq67$GGQUP1V zf*_GTJ0fL-ulZ=7RmGYkwfLmHm=z_D1FZ%RIKHDr{O=)&^i|5?^s;(n_cm8ajd%Fy z7CUQvXudYV8GNRzvo4OEA2gSYjo~4WQHJ6d44*nv^&P&%Wx{@UBJ2F-CLA1LK)^KC z%ns?{dx0iq;!Fn-prSy_H`W**qk`aCKKhHu2YG5s127aqTFYB7+AWZl^uO}YXMW=b zQpDq>Cgj_*b!~SB#qhy_#$aTDR_@TWYy(r{dnlPez3AfG(kg{`dQMO?XsRA~xtQU@ z2`=?1%AjJ|Yy9F5NPJsfK-mz6SsKVJZq5$hq`Ztl$$K*Vu)10}>AZ2-?L{KaZJ(*b zD^-rki1A29UC>+q&-KMDZhz@jbDCQb3)Z{O7GVrG#M4$WqRJw&4ALpa<7m7EF!J;k zj*Ldj(4wn9_ISy!7%b;;-mSPHo>~e8_Y@O&slohP(QNb+=pWGzPI^;39kQ%CcSKJc zQJfMK8BhQttGbl!w+h*rKpu-K>~q~)BoPT-A8;W=` zya9tEv*=JW6G<*?fincd#ST^|PSo(>d;Uvs!Cp;oGVAkFf?C)UVPs_x$AwcQ?h+cR z_-A*S>syi_`O3iU!PBnH=^ZSiFoTeSPiU#WoTBKTc-FTc7KUA%5wk|?y}Y=wX1=I9k1dd4;Y6wRu}3DqVs972eIvNpBf8Cng_gbGAS1IsS}C& zGH@i`ki_)Ovvt9}Yt!_KI`J{tU5vhX|C*d2wyUL3<~yAxYekM1a;rxT`es`WAMxMU zR|J|YVazW5x`@ z_yV3$%qpZ9tvChx$&$kBt|+(R%jhY3hLD|?U=(_?_3_4aRslm zs2)c=#ETgsex_EuTOK6%yGmm|zVl0H?*ZTIF%sQ}yZV*CJ3CjL-Nt#SD9f&JBCF)) z3Fekc{5#ZS3>+A=z3zl0;h{Ric(SCq;Xkft7k3!E7yo`p5EGE}Z02#nEw4~-glTOO ztDVCdOy3u_F4y2arTLJ`;GhJV+avE+#*(QohDs6BqUiY%q0fpKKkARf*eJqM4irD- zU|<;|KH)q^;Vc!5;Zo>3h7ENNh~{(*6dF_$99D4Kp$Htg%65Aows1lPo$vPA{fiip zSa!xwIK>O6iSTwzPU)=*Wexe87|MK$*HKp28}8>R4twG>>r_!k;}vi8>xBxtA+K6o z#w@5$rXlq0O<{VRzwmrtrRTsTt#-Y07^Q8twK&sshz&Dt99nC3hpcW@p3NGJytC&$ zEE(Dj?VYJk6CY6?Ka9-f`|p<+3nvJ?3M7@d%9{pewPIfWG}tYwxLqR9BZGMXf5$tsk91|BDOo4h%L~3|b*VVM<|P zLyI=hlBL2zc9#FdC*iG8wzo2Xc9fi+9s%@o>1xRT|KL~~JM}rm)>d!xaeLubU)G`f z_-7ryPJDG`)==#SQ@-<<%f?%ThseMEW1bE=Us+L-i@-Q?SA!^fk#L|{be#SVwlK^2 z^Rb)TaT`?d6w|cTvtG>&anK>}UXiP4;EFPtlQ?FW?xNc_?O?p=Vc1XTgP;47q<*!U z6TVlu4Z3)F#WpjII6Fo22OC*baw5z(5ti?Ah5!Z^-lSn2yY;)rXXCS*R^!3?;MfHc zc;Q9rUu>TV){YBe+RC>YT*x|6bA$QG&rEq)pt?^Q-!>M)mj8bE8lZ}bz)##dAsEyv zk;7J_{EQBV(}f<>@*`%&7&~&q`DEI)PmYS05Xtz3`PVlO5xDt8ne)z5ClX(xvtKVm zu9Oj#vLD#5KU#5bUEiy1L?$}QX}qClVNWY5MalE_CFjNpraIL>_;Nh^5ZxgphbnHn z;rfZ=^5HU4?67Vmx$sg)AV*p9n|9-nVJKhl+jul3h7Wo9v%3j;gNO{X`(Nk$aK;L0 zaYL=23JIwGxP7-+gGNFTkZUpfAekyJ1AmA`>s0`3t9^#*d5A;vZiz9ZTlFG#b zSP6sgPi!Xon;LBtpq_-PS-F31%bA=?_4G^_{nixtB@@b5#N1?U6si~hTTG^ZO5+cy zzKx6in=NmcL%j2IbJ6j&>5HQGR2X<_4ewlSZgx)^{b#4RiXA05Ho`S6_Ss|7b{ZIT z?THVo<#K-|KNiSF)5VKN;9;`bD(2_MSKjR3xN%)_7z%VG?zUwm2hA2M>*wRN$G`FP zP9bmOOr&wwC+}2#U5HW4yjZ{Usl?&#gkk~S@vf4DeJ1^;&}zTih5J_!=~i6wtcZ- zk3CtzyB`&LAFXW5`jT637<^Q}$6)*CyscYLP1e_ylanjT7xqm7+`FNXk!l*m-5e}@ zd^sp2zaN?G67x13#)w6#vIhqT@`(>XiJAzA-Lf={=Y`{brGO(R1IjiQtvFD-f;{=O z6b`efsL5P@iG_uQ)b#ZCaMQEelYSzD`Q)=N#{ zE=9szhuxIG8LPCxZ-u29wNHGe_5kVj{F3UC_+Ib`1O9tn294UjH6vC9H|6@#rE_%2 zlt)rIrb-G98%Vsh<1jI~}V2*By+t{I!N82hD zeMgu4_D_SWsy%7Yy-a=Z;n;Dv>n}OQSc&iWvD_fxbW&1(fOgC$4fbYT=X=H*K2)9! z+2h89{IS~trhMheeX&Vl?V0dY@%P(=1K@ZbN^wpuTSk(bGZ6_dFqV;6)=8$B!sH`A z&~z4EwrYo9ODv7=aLZ$z1-mA?W#{5gj}pPIab z1tTZtCmO{}G2kjyY&Df%$%46?1KLPMZw_|$BJDaOdf`*xhHDMVBKbspffyEotZ(3- z-)e)7=KIuC9SVh2-UA|&&5G{bD}Ok{JguCtT%4Pw7o$^ueBt$<`Bb@ZH~g6|qiu@W za#{HJsYItrTClIa(gf zFr0Y9yS-#r#mv-y=it0Fez^S)ESyA%bo`#oOxA(BEK{Y#EX7WX1bwW{&{!qjat+^8 z+C4lf`<9%EaBj%@SASo%uZRelF;X~@zxeP!(8IHrWuS2P6hwcSo#^Z840)=4!eHx% zMW12WNMvu8&li@6(BAAZfzI0X`Ky~w5DSkR>ddu;IaA|fx@@Mh?+m5BzTw`9(rICl z8H*hIqd27$HY^v#(WpBZ#e?p2?iJApv}&mNi_zDK8>eOr)Zr6wf2f=#DI#UX6QZ%_p%7Wxoe(3e6(n?HP(KqLX z7JkE4W?|?Sv)zJFUa5>=VpF=s=H4+hZtmctI-`vy6gE2Bz4P7u4i{*TeEiUxH}88H zmvEKluvx3-7l_dad@+e|Vmh+Es2L-a7^6!46J*zGbcA7ELr9o(@4Jg2KQ^X6{)iaV zIF2Bk0hM_Z>}x(fA_fKdLh1)zD`^A`*WWCUpG|Un zhaC=Jh;9T?+;VC<Jc_>Ol>Ld z9{p3uIW>hjku?46*c2l&dVJF#@GA`MFno{!2j3{taj^fq^UM_^ zlRI>=#vAWU7~}77$Z?B8m^`OWWiM9q0@C~TU-07$Uz;ZVG2qH!6cqfOX7;=;4Ulv) zrY9RK;154XRP$g5G=G?A-+C9>K;xlP9+680o8RoN{HaK}Fl%NyeC zh8`9m2o8nfUJ@)C^9u~i_m3w1s1NwRRg2`ZfxVVj7?iwC{Q04 zx$KNNIXm|O*DXlk*?$0rd@0kglJEUBJ>XEH0C9BbFthLwr$@$6+#d`6@w-LNP=R8k zrjLu#0L6n~TaVYXDi%Lqp$GR*|L{H!Pw>f)+vl%!(hY!bM=NIY)z{{#{fzDo9XX+2 zJ^gV|1a=+s&#cktmbyHLdK64~QE=zW(Jt3b5$&@Z_d7W`SsJl9J1h@or_hAYW&G}% zO_)JO)Rf^+%7(;;-mJ1zhpOAiJ@WL*z6Ajb;RA&v74^>er%tFp8w!NEknJn?V=^>6 zrW?=g|2hj|H}%Z@bXr0*s3e8zLG8fAZY8ktsD1T%>8l5EczOkrswQR)hMBxx?#xOo}xYDjYhxI~tb(>F{; zKZ+@EI^qxwVzKkdOW6_>9eb2X@vGuSVl)kZ>6;V&Qg2ev%X2Ff%>Et;XM18}rk-80 z+;L;>cT1)YH@?-tGn`#nKYjHjmF-WGleovPqSr)QGPhF4S)8q`^C2>{@YWx~>DQp? zMJ-%IigQ=S5`iZOkRL%*5dR(?ih-}=|7foVy|JHDKij@@8>>!H|Z#Kmiq;`H$gc**Xz4-;l+Axl_2R z>)Up^iHjB$#xM^vt!)IJl`=>V@A7t(sR*U`nd&#@MHSd7fL%MzP+@e>UZ%l zbkwl)ulK*_t*NV1tSKNHw{10MP;R3=me-7|M>MG_+~dAiS%Iq4SgX+8;5L~~qbvVB zsKw|ISXt~78GU}nhWTvc=zMF27jkRgJEb2OqFt_ux1xh=wX>RZJ7nJA&G9z27ipde zR`t;s7ZU}=y-x#cjW%sSlS1!=%`+UAfjW0Em)`f>AfWk;n*T3eO&F0}8EZH7K4&_d zWGhDs36mJhzgn?RQC7h&Xtu@mw7*E#x>h%ScH%<}I)~>k`E}HhQZz0D#AM}^;hYIv zU^{B^4w4zY2(GYRkk@114iHk%AJcldXD4uyUc$Y{lrvW}c5%IJD2eVab|OpERbfZx3#xOM{2fCE^MXCsQG@I%-@YP z@pAA-r!V1c%z37Q^U?zyjORi^h+`v-&%f}k#J8sy(vt%fH@B+2MzuOI1sZDG>7RS3 zhAZZ4S<9YXka`jupr1TnzgtXg8vYN;0fFf?X$DVH4F0tU{qA{P@I3 z>w}~G>Fo!{^9@sq53d+CThvugt2YESek?T9`&erY5*I|{2VY<)i1Z*Us8++QR3Rog zu_I{%$U{CGZK?g&_AJh{ls>L+lvy#RGd0p)ZOOZpMoNP}a2Xo^vz1TIVSp%K00Q=_ z*`5&CFTT#I2_x=h^F|04-#E`c3bDUvffJX*rl=~4x@@@XzYlf`9FtubZ)i-rDKyFy z-?_PQ0Z-PNLrs@+AGn{}&%ZGFRU==PH9y3c46xZ>LcS49NS5B=nKk`Zo{>$(yS~Scn8PnCS zkh(~(d>A@Zdirpx_Y=7>5E#nEgXWm|%VyK9d;U7=>9!I}E*uv(!@?()s$r6=4-9zh zdML;69meUVSC7W*R8D*~4GslL&sVs1e0i@;->bcbO1ei1e0f5$S$Yp5JH+mKes)sB zeaQ_so>Cs@rf-;Dr-wSdCxSvN^Y>$Of3len=0#qOB-~1Rfts61S?~LvbiPLux8H@r zTcUOT1Z?Td9e0)u)I3{%kMHqU=vvL=Aq(lKzf!gr4cp5PHBD~nyzUv`^WujQ7nEt_ z+)Df zGdV9>8^lEem`E2kce_NN6+cM_)WK>==tFlm35&aS`vqv5z(KIGT%CnelQRM*H~;x3Dxm>PtV}PHz3dHo1cGcYg1%Gn+7&!XycqWrtjR5j&c z!oJ$A!JZ6c1Z{7b%+J8A3gEB_YWQ%Wy%q^C{343>BJg+C+2a=mpVmp}&db_>sEy%I zanlLKmB%Z3#hmt{#Tl^)&+kSBoBR6QXgrkY<^z3J`}~twLVQt!6ix?w&Kx!{wM4`e zywMsWcV%zcd3o$GK1oSPzyQ}jfarn*WePAmfC}RDkVy0pKoIUi3GEufo0UdCb9f5= zB6!;8{v;lCpEy8D3-i^I^=GNV^vDOM|F>zWN>?fLNLv7&*Ed#=2~UZK$ZhtDFK=Hv zI+D?uyb(9jG20hV(Yb&!fvy{c`AT8NxNz+z^|-%gZI>ArsC?YpN9D_hPx|h4QPS1E zS!0GX?sKsp2DQ_0`+VrPzvK&e^&TvLmsBFBD%_pW^Ii*vC;B3p*y-XQwuXFSq%}PV zy!Jb3+a+=fO&SjXI@3H5bhH!VZoqGn-x<*8C~yHF|P_thDNr z*CU@T8?PPmy(>!-t&4M5oI5d_NLtc8&K}|)t!_#qa8PaZe)=3%jV2c!dN!J=(5=cT z-tk#9{7hJCtdedLDxb|h>9E<0_&wKEM&sOxf3tKIQX(lCZDo^^7v_cf(S>kFq8g@o zW+7<)4`+We6SdGmv!PUADWgs>k#~6{iwW_J@{E&4z9g#u!F!Qe2P*}Lz$sS*RUo}; zLxWy;byH4S2mvZOo9Wq(;H<=a{S!MYMSUi%^HG6l0gvD|g;LAg6dej0Wt~XNy}a?9 z57(#v*s3W0$XYMOMBLYu-8?IN?{HQ6=5(ygGAtCW|K;-o><=2l8vAs;xBv}t2Zr?Q zYz9{+V)+to23simcrrB#_zW-@2*I;qoX(u z);N5zE~L4rsJ?9Es=pMHOA8^^L~5MpgrLbw#nOMWRJW9dqmJ~|&x_HUUq~P#U(I4^RBDSsI*K&;N-%E*cK77elH+H&{Gkr_ zTx3OsNJ@OPfmkfXy!rwuuWjdCjnyYRvZhp$RBj_a)KXIvWkc(>kjRSW`6{XF5`|B> zlexOH+vwhWCRWjiaZfP1ZdIqyePy`Lk-fB>l~kq^e_h2@oZo;xv+n$kODvMIe!%u# z<#dW^Tk7=};@M~d-GfiSDf*quWgso7rt6~FRIV9sNnSYEr;nCf%M z$3J^E3O-owGj#@u(nK*uAuPJF3-Ci-wG2Li7DA#5)iUm%Y3Ac(HK@pfB_k(nn~Ovm zJZ67{iL*5Kyo1bQ6=(3;vDxwkxGNOfZ7I}en@S?`hG!!7d8q|bKeRmyR5%wS_q1@}ge_AceO$LT4*^Ta}0vDy9X6sg~f_9@0y zRbg^zRPg5%Z{74leXZuWWM~+L633Sl={L>mpC#KQ6$S=%1dt=SN?V znN@f2$htjRtn1D(DRMTZOA4)(hnLlnNmHZXTDK>>wU^#IXT#VmzmS!a~_|`%q!u{w# zC_=U>O;bSQt7_`^Bq0E z<(i@V4@ok$2DwI2sxWcvF6FSGdQzRQ7H#~h@u30 z)2R#}5u;$D-dKN98nJQPC`f%}Ml*efe~)fNLV1xx3n=jPF53_sj-h9y zJUwAe$vwq09-U|}6mUxM0Ec)T9i85xA=rn%C!q}u4gU$PM=gM%uDDB+Y37wgJd$8O>i{+^ zAP=siC5#(x&{Y?d-eUf2gT+!&mZ9G3z+3o&);M>#F@ktn)2mLf)AW>j!>M80<#Q7P zT;hFhPve2pa}ltm{tq;uiIk-117==7f#pN)ZDUgtJ2=d-Mif<4WPtJ0`!9N>aoBx1 zbC5o66Vk^~^hv7(T$1$z7&i(P_1vaC2xUcA5UG1Qd%vC&n^9e+=-}KNuc;eGS*bBp z{RqUnS)$a<*AnVgEJkiGQ6jWABTb%&)IIJ@M6HUv;MX&cQS4Ae4ZCIC^F02vSG+4lq(B$&3&@_e*u3LbPJH} z*v!@uU!yoiW=!{(ZC+RYa}E)F9{UiUj>R~2QeHEKUkafC0pEKz-@kS>I`!g!KnPf_ zTc@W94y)}uk3voxz3PTSqJIA{fEhI#$R3vV32KG)@zD!WK^Q(nZAoUh#q1J}xKR3G zI_-{3GA`1c;k-y%>|acN(D=IgUZ?P|a9(F)klgH-oVGR zBO%UHe-U%9wM=iT!O3Xd5d8YLJNf_t>IY(|%cqH-KQTb^2BU|fxw$zCK1T_c4Z9S^ zn>V3AuSiBmM^~N%2SqC4r)v7XiYBaW_JbW-SGd(hB~azOTbb2ISml5{Vg4m7Jdu(3 zgu}TW@rXnm{#H!>AAk8GHYIO3OpZvGcFTtBj#vnZuc+Aje<5#G_#H({{U_<9z*!6N zYyeq5h+umUfwPSq<10K2U{c`)Jl|PCQdTM}EAaqxwbJbO@86ri{Xu>V1&V8fZxJ0v z{%>T6g#@$bkAC}4QWNFp|D_%HGDU1~4>(R=g|YILaoYvIXj zf%tz{cs7dat9RMJH%?y;WSf4uU@;>T;QkiIv$lQEL}s^o0j2lly_wiRVg_BokliYx z@X`U<^)&~|UmSBqLgCJi8~EnaR`|smWb#8%w7^`H-s~B)Po5Wthtl0Ba;dgm;sA-3tkBPrYKpet^CVs^nI+yeH^Kkn z0z`0F4ziG~&-}17@&Q>B_jc;Y5)u;fii%8E%~>hHlpOhBfB%o5`6;+XH1jA1*err5 z&05}r?agK!aeeIu_S0){cJ_l~)6~SI@IMqeDLXp`FhKjKr`6^w*^Hs#;Uf(^%b$R` zMnXcB-Y>T22}Ob~gxASNB~hQT)qLJoQke989EvcLsMDT1l9C)^`5W=1!Gu63C0V5| z*%u=J1{xN-tw(ivJY#&t1o?6v#ID8qoSiXPg>R?hL9lYBom~5NeQG-VdCOi zC70RF_5{B8_lT}E&A5Hgs?kXX6~o2g8x;&(+?I9M9032RGRX0daww&wR=<7)O%m|W z6qwFQ0Mqk-z!jTgF3Ozswtjc7-y}0wi)o-qCu{eKR_EK`wC`p?DErTwtwyI0Sdb-}GoOi56b^^yV*C}s`3MH|GdaXJrvH{zzzE0Km?{6!_aPj1XQUoxI zdRyRkDc3%d>vLF{8*qOhLzhe?mvV_T&LyXwuiEZrQ>L6J4>sBU!WTk_H6n;EfP7H5 z(~Eu4$k)Do>>Q2a4S9VfS7gm*S-mJ5X=OG>>)v8OI#_oNd(yx~MHX$mIwdSl`d2eBDPMt`twEChSH z8pU_9PIz97QkU)v)S#Z#c%?q7tc`U!Dw?ewzDCM*;;^st3F`AK>vnk66Yn1scpI39 zDEc&7`)a3h@y?ROeE$1=Jps z#;d8%PkLE|UY2bPJeDO4>L0X4{CB)XI`{mV)1Q;ow9}~(>~cJ4?I(TWjJNci=YNFq z-Tc#OX33h!nG%(p!dEbz6wK8YfO-vHK=P!L!f2<1^<>3*^1no+-!vsgE`DQ z7c9sFW+RIh+@vCxSjZ{1=V$06=ijq@Ykfz1tUWaRC$mXJ2AkWLv)tC1JDa|tz2vZm zzvMOZE=n0pUvahP`M^%C-Eb@_cI3SY)g@LKBYYJMb-NxY3J$wcF#3xl;!gn-RY`&L z61zs9)q>;%@V>YdHRUXPxFhJUT~K3@rNbjTxFyZ(V3}{M62qJ%;7W)dc=q3?KqYe` z+FNlO>IQ#mfA4?zCvs3L@T&kmS&RTLip5r=^FvIdlM9wyv>di@JzQx>G?Q_2NXgUI z(Ck4Y)h@BBqto1>l7nRgty9HYxI6VcgUqswf~n}psz%Q#lV9K8zW(UB zQS(m;*p1k(*Y$|UAN-;d?dW-ki>@BfB~=(R2Lq+0AdLu zPRcvuGyFdQ2 z>WLFRD?pc&7^5W-rfp%*L|^UN&G_JY0(p8GEdETd@q(a7$&I7YZ3ZIGDSX8S#+j8qJi=^Qi~Tm3G3U@-j6ZIjPZ(eH^V- zfy?imHG2NF!mOyb6BA{$3#5!U7kIQ*Mos@~qQWP#M!e zEGjy3QuiX=ZIYQM=#g^JW_U+1(-^=cry#O9pu7C??DdaTy6YOchnDzJ6UuC|@PU5^ z!GU04V=s{E=Fi-Dw%UqL4+^atNx$RhZ?<$d6gr)+WZ*hQ1a{bscE3}4p6?+W4f0$R zzu%WpPqyWJ`V8~>75=}s45Mk=9%r6LZeKbw^Rjd~5AF-jR0 z%gxVd@m`i|kMA3?P45m{isky!{G7DRC%YY>RJtAs>bf4WVQPhQkPDvDLgH(8w=^2| zc)o~@Hta8SvLQB*Y<|&ga=FDQS(sdT$+$|aZ~mW@vFM4zK%6h&>daX4 z$stc%m){%4y;vaK;cL0&Per#J(V3|yXJCi{Zkv$O1QLU~HRSMv9Q^w9=HLA5Gfj%# z*erdck($k6!ls+BDgE|yo0@4iKL1Obm)(ZsPu|W; zvb9w{-{0=JH!{wJ$j~Gd_xH+pKQvgiJ;N7}Br~SYBRnmr+rUnJlXhdE0t; zbF1qvA!-z`&BH>d9))xx;Ii6LFx_HD9@lNgZOL@Bwoyo;80@GSM@cnuLI*Z2O3)mjyOQM9y{C)v8F?t|gH zZ0;-CcIY_e`Y#X9EHhA_8C}*+GSoO3vfLYbws3LvGpH=YfEgP;5RifrkeRjT(FIb? zQppL#SUlM0^RqY+y%03#$6|p<4ZPc_a%7y(VoZ$ZN7-<70r=rQnn(d_GSG3>Cr%+S?*C&Xc4?u{s zAW#j2$U&-p$hy)jAC>({qio#{k-`?-&$)xXtM?!#z`VlH1Ypq0+FxmrOoi26cc|JT<<@i5-_138n+@120mYr5Pstdwu= z=WIE9LO+HK9jzWG1+IzN!xYB%mgGEBN)Q-9+$E)S+y?Mqhj?3pu(k+b04O7n&H-sW z9>HH9kZ1sM0A;E)cvx?_<_sG(ZqAk*tA!JjzL%TL&Z9MxfZ+Elw+HYm^Cf(>E|hX( zF{*Tf3anj&z=qjorIj7DE~Nm=2bDKUOl)j1U=JlHfETMoh|aT)A^jSD`}DYPC~=D7 zV(!TMWnkpMh@WSs68x<1!nZ3DpyaX!VZOQB(Ncj6;tixL0iPqoO}8=S@$(VXMtP2IZJy%T zvH_LfOfrPt(*1a;0P(5^h@01WA3Wk~gHjFfA%XM{zFFywj}rI!oEa36UiO&&OYxln z#)3$e`<)nREIu*iELE~>2e=U{FFZZ8k#sHILQgEYnSY_wXk89A9uCw6Zr4T`wR)uGNkFZ?u4X9Te!`r_5lcoLK029hsHI8~T0UHha_l75Q(P%|QXK zR303R99+og$A7L`6q`<1JyS%ZXYhn%_b8LCqPYi;;Po4G9w8nHLwwV^|2cO5S3M@B{6BAWD3=R zHFlh?1e?!O_sBfMoXOxP__lF&kYZs=Czq0-RiqkaRp6fvO0OhHk|ls6Wn~~MoI2pL z3HKU2lOcre3~&P*-~db-@Q++6hbR7jeBJzmpl>d*bGjJ9)c{Q$@Ko#rML95;6aKGp zE*2x&A#^LW%8}-(F-mqBd0Qmr7BrZruhU`)dli^HlsQd$bx@}-3r99M+GVueg*=9N zKho4sMSE(woX*Xp|46Apld$np#$-9$9UlAa?JzTj-nyTSdq;lJ`!T%2{SHIqSaC3E`djomuz8U*w4R{9eza7xthM zp^5*VdsjtEU2&b&SjiDa zibJC65za7k828Nv+oN*uec=)6%XWTq8l98avuYofX02|>828l1ifad_-FX*EZhK0Y z+m*r?BLq?ylXgFxGX)(zB(51GeO~PsCj#9#n*V3;BFYDu{qUI$R7u8J>xwxrmu9;k zS=a4glr8%A#%8r%khlt)3eR7NxUMICbRG4>aoOA=uxK5XG`hRI6{gk?QZ-;_n0Jso z(kqQZmUMo^U*!Bcerq6PclRu1z!zQehpb2yUoTHLs}C9X=hb|=Nn;X;voGF`}BwbNQ4$%n<=Bk%JL`__Si z)LY#$u&sVDXjb%s>x6GF*A=qOy|&|dqkyFtWQ!*hVl=5#OKd`kVJXP0jkwpb$a1@W zq}eW;G+%ZN-B+_C476vEPIH<5YV*=&gQ!q`e%ZnK%W+G0!##WLnu67XFJF}`{ZkH4 z*~6M0tDexT`gkoRI%iOD+0YxKSvQc%C_)ouOXM0mSM~*$av7~{b=ckjQNJBWq@~bS@9se}V zUO|o4Jf7;OKW;xl^_{F=40WzHR+1_-aT2Q8?5pF@!bgdAu{RaJ3iEvVp6b}*w3G&) zn-IUO{g(WZmP#i2^zORK4OSssn`9ljdc<&9FDtvt_6N!72rPcydB&IkV2! zATWCtT{Q=X<_HMTOMpBz95vJC$&2BSP7mCl)&2?u+RVxZWMXv2h*fzrVYcO5o1MtD z=6hAYJMSLf2yuSoepr{oFElxN$XdQPfeDk-6HF@?xsT>@#86u6#pMhz)9&&a)Up+? zeiQM{OUhY~t4d0dY@)WHjNRQla~6${8RLz@akrqT=QsbzTL<~2f);Q26t^$~ug!22 zVu4gpom_&@YAJyPDmi{uXJXf3A(aBc$?a?8S`ZQ=GDdk8Z~2(W_$w6;?$uzLLofG> ze^QREg;_(s6UE0p|B1kR;r`4}7R~gD?7H#`e{no z&bBghdhelmoIZIKLWLv!`=&edoSQ`huE#l$z6w!EM4}Nx4&9bj4}Hj?>n3@;b}i^? z`8=7MRqzS}HxQ0@#T&QF7KaK?BN@4!Yh%cpQzH-4axoF^N;Q4 z@ZERr#2sktmX}Lee%%`a1o>D>KknTt8|$IVhh8JlPHbQ4ev~V_6jfQeqwN7UlQZuS z(l<*OU=f*qOD?4u2DMU1A=s@&z4=vQ9%+#cZdx5+bpc5W`=5=n5WtLIhjt$^%Z*8x zB^KN6$ZN7_Cm^Z)Z|(hMP#w<`KMLa>AVBZ~B*EP^cp$h#aF^h2!JXjl?(P~Kg1ZHG z3+@)|?jhgb^W3Ui|F`$mrKo~)c6N4Wrn{&6(>>jicYmgdRlNij>g=z-e!6^?8arJ} z==Ontl}OC~1^EIZr%mr3J{=Q#U>^%ZsMNc-f?c+~p!${O0{8W}NTgjLX$84}$<-1U zb=e()eOe&}12Uv|b1PD*K4kdo8tb96VKzwbFDtiwp95O?-n`ed+MpSQ(jFqrohMZdegNs>U-u6w&Fa^fn?JdQV}uW82UXB zMBe;(G0b&XR(p516-lL1rkZB}h$16#$^Ns&GJD*aBFe6!iz~u2>Oyz6cn0hW-QycW zeWdt2v*Us^tx8&XNRrn0%J#d!a6QiVskNk)8H4^h75P@>ltPdQ6tueCUrWUen(I8A z7~F#(dt~?GFH6vI2EL5aKjEzyGU<45WEv4TV<_iAIUdgDi&lSw65!P1I^}&JuSIiQ zE6)4W1>XJF-8SM#eSzKwq0;^e(o5Ve@xNeK4xO_@fbi>{pOJoSF;ITI*^g zLCo{8@Lsymk0OZb-cle-2V2Ui7s;Ro4%5{SNR*V?9g@Qm@gZ~YMjuioK+lUTvg1uVw?v zUvxyQIamh-^2issNdch;KvnFCw-R|rPWvl+7srp4x4bekloA&wcL?NQr8QS~1mAb^ z@RqkiB^&NzMp{z7IX4S1{kdX*q6i>pd##saTh;wUTbrQ_5#Wspb;&IIsqUokP#58J(MRN3s#E(h-N#2=j3%8W47$N8+>>t)xQXUa*40Zn+;%$Odfw7 zxE=m<0yY5dCl|(SIaJyqT5$zbu~O9%Ta{r46T6-GJ-V5^)^Rpq_PIkWS6h<-*RFh% zjUKqjD^Q>lXJ4$@*SuiIqXH0HG0Yz*eoG-6v&8{A85f|E8z0SAgKP5wuE8q6AQR36 zUYwMwAH3rNNFU&lDsNoP0W4=QME##f3b-<2HwwVhc0Ryb3#0LV25Z&8T7%IYAOq;D z3Pie}v^4^56HQ>%AOtye*HM=## z^q~%UxnsqJ8ACww+G*YbAbrOd%5dPVE-(PM3jhX-hU0_t$Ab+cV08C@7m8qC>`S~a zEV2S%@Qd|F0V0EF`*mAZ08*oy07wA1E-7$`C^jw*>(%U1$S?usLV;cd?81>s?gsD( z&f8`C1)zcgScC&AX$p7&nl-b90stp47Esx@5C}Q|3Q&^2LRNX7hQW;YiG-UwWlqN{ z9UNB%WS#VUx}N)IbX<^fkVKJEMIyjJp%8LL{SWVmAQT6T{D1b*G*04lZp zY1^$R;4lQ_(;*j_Fh7AYYT%51I#6^IppvgKK;-qm;a3>H_KpLT(cT`6RRjE7fD(%e zc;WsTL{xJZ?6QF32MLRWwZ0X}UjUrYs56@l0V;&N1*%o;s{$ff)cV)$4>Iv7AAlul zpHf~)`y-GS01UVQ$VC>=7HseW^*BVh6XGoGHiL`+lN=hXIy;2z1Nl?HMIV7G7huF6 z3@~uV#F+x*H1!s+Jeh`?&j3#G1B`m`s3ib|`ffW`7I6Cw)nU@iggL+fV?+CU)2Y??*N*e00xC}?P>FQ+$I>3V)$+hU0tB>TrE>La1TtW16}0t$ znTt_vaiRl42y%d>X}uVt0TKy*;Z{hH`hN-&U@`JqyTP1^K_(HW3k3F9%vbpU@~|4< zrGKOnApxE{MDNG@OK@>)>aP`2K&~cWO_cwU;upXdCLU8KONq4^fTNuSq?G})B2fMP z^XpnWDA{rVYjuU@yyn3Hbea$3O$XNy2K=C$|7bPWmj!sfLJED$5%cQzLpq??cOQ_Y z0qoNS#!e09^gKUqV2cCi(BfEez#Qj$uz2;r?pdt-WCK>jC3x93<8sox z*R&PEgAmm7x<6MW#>M>#=U5$>{i*}nr;K3+yP-)z3cVrklKDKifowy2F_QG)oTC4l z*BcFE1KD#%0Bo##n4yCZAnJd&7>NNDi0*-)$AxMGcwW}Wo&UuG08A6&KnO5@K7grD z0LUTO_5y0vPywZMfms?Nb-o1T8D0W|4jKRY(Gef1kimNyFh4_rK&F9R zK&l%6*cx!gfnmy))F>J}9l%8{5-O@68dl8#;BqqteJDeT48#C~)%g5(eZc~7`D@yA z!IDx?umEzL13&5l{q!_Y=1O zefM*%DS`XW>)DP-pQ`Q$FADh6I{4Gz8wBtT;Hf)`i_ij-An?)1m&Zw>pZ%p53;@N% z37*VTy{;v28_Il(!Cn%R!E&`Cci{it8Wp%X?p0I*?cp~f(qmA!!B`8>Rel$Uhb+JM zzlTBtZ<*(Z=-;zplPCNqv*A?2@E1}oaqxxn+I;(CtqEYVDO^* zw<9g_CBnVL*Ib87n)!DqK-5N_MV!|cp$464!1;fdFJ#O9E+pIm1>E%zPXdGQ##6Qk znp4A3SD@HlblmY!#j4Ogn?~*Rs~80)+hAOlWuvWs<56QhjyziCBNYzVS_5teX%x7_ z#PWHY6Z_jyh;oPLY4-h_VFwE_nZS+lu1bD^HIppWVlfIpLjJc*7wuY08{s}tgn=3v zf%A{iGNe?AHUIkCu_T!59DWH1Vax6h2M8mkrt@Eaan5u)Fv8F9bl(MriNJ4w_8*Du zNCQMc1rL@Q;C)u9U5>CrYm#z`>4PzlUH=pN4J=>ABNq_o778$|8%#z9);@w-Lb;Lp zW?D95ZKT`xC#Jaov)$0^NLP8YXi52>Ph8Jup)DKko|kKH;l(#W#po)Mb{k!rJ3K!|0m0&qd*MjwDS4 zvX$W=hvMDQ&JrGn1#P7C-?;X|Uqm-xN^@O3h}DVKJdotx+N#4C#23Uisp_lmf8>y+Qy=KMZzy#w5?ruU_1zgnWwd<>vP))&#T zjAz#N;#(2^Y9ZozMB4T%Bwg^0JQ4l2^0q<2qJp2*5ID47Z<1<_ZgL}Pz5f6+<}FD- zKqj(CbT1)rZWt{26tIL?8ziVnQ=~O|PNgQx zdQ!%nK<+Pn!ptB*D0LRDPLX?HMX>N&>j=VQ=(??44-CqZ5>>BWVSGls`v^zh1Q}xV ze(o)fFMFh5DsaxR4xz6VcD8g+AQ=uuQaDokY(UrL1=Mssw5%*3;hGG{C2n6klVogK z$wbJ?$sH0|Yn^7_>p@8U;e?ORXQ!m`0BbenjIIw!jW7<^X`L-hS8*eb;X>@O1-4n^ zl2`hn{q6qB-+7m8<60}MW3^Iv*2~QK{DG5~uTY3s?QplNAWZ7*CzKXvK`B}+Yj|nV zPXB1e(vPfE=`35~L!7TOvoppFB*7}zOclh75vdufJD+&y63nIN&sweX7OU%i-nhtfBGi`R@ z(XZc!;URmK1^wBSYy0T%f`g?Ay`|%?X0Ll`MX8C0uLWy)aKdjjg`f0H(=p=p+f zE~zXD;-+eiA&agNLp--PVLH%X+n^6Kyw7z673`Zjh(C)6Z_zVePnCF0e>8z3CH>0G!j4FhntfSdgqX#*_Kj8aiXK9&`1$%_^iwk49Xwr_yq zdgE}m-KwjXI(G>vdETR&lq4W-9{8YpB|r-nF%hO*iUpS1op~F`Q(PYeHrx}V;^-iu zu*xTWQ9;x-Mo&oCBkALDjYJea9|&Lm?4&776q|x)1c{>OM!9NT@y_MLuUY@v6wps8 z4K@OHa^c>;FPc4c=nxniLG?BdPjc?EeoDEF%g)5K?jV`gx8E~s3pLGVcTZCOg>TysU=2p3uMU-$p>i8t{jI zJ@-`a22JiMjFm5&ByHv$hL;r8bc8h&9sbeN2O~a7Mg-E%vdoR4#4PnL=yuWGEK#;3 zeqwA|zaeF`bJ#=&)j(e8`f=~Y@SB$=fH6a=2&txX%vJ|Snz@=&P0ZexXx)4u)=9Xa zbe)!MoxX*t@YttbEDtppbK|Aj`UxIp5;cy{<-r2u{OS^6V&SJSAWu$3 z!0&YCs#FtP6dokXHGL>5;;7$nY8ShT#Dkr0%YnDrG(>t4*BfNG0 z2D$ometJYmN{u(Z{5==F=oKl=QZcBOOU6mOkh@ae1VlkdY>Ip*z_u6xV-l?6lm4J&q>mz5pE<=7+0b#X*PH_+rmwOJ$_coxwJYk=RN6 z1HA-kXPWYMv!npa-itP%BPOeRwe>xv;(2C&|E_Ga=Vrx7qG?b%8NyBpv3uF3k%IAh z`OC-4WKz&#nQc@R&CYG*8?oki`(ZfeBdIz1J6BSvRH)&voek;e$`B!6{TI`-q|FC# zytf0+Cc>!*7LPE!by>0aAWIs3YFmWQc~AL{oZZn=c;QwK^MC*_^FYUj;n%CLOj z(cF6&F~8axY1m$GuZ9O#J}Dx1?|W=q@uE4?2E2vV>ocgLgQK^OmubcfEZ0z|kguBP z3JR7nNY8;l4-TC0!I8b@L^)c8LDUPThO#w^W-m?c|=8;rH zt;0tx-+;zWS^oUXHbw~B-fUf3(o_G@QoRjoRaV6IpXe1wu=L}3n&i$2rY(h+a*-MC zaq}T2I1zh)?cg70QmXuQJSBZ~5hdc!hyV*Nu79T#W^VX>YrD%64ylm# z0E8fMS3QZWoX7os#YyXG<0aHM zbm1UpNse|zzQOYL{ZaKy0~}UXnx8H>eniDS_4e)6eF&_(oISj~km`0f=^=39b9_T=5B%fU#=6aQ745ij7F#rom`Tap%t%z3>uPBiFWojpOW)w z&1O%|WxHJXh>sAK!YL@^Jqe-;J=gk6D!Nh$u zf<GT9818tA*$@34tF*3U<*~aq!!sZ=1n3FP5>w-6i%(JR_>Z^IUaQ|@ zuP7|URuz%*Z#_+Q$B)xBZkA8*63428sFYxbM0*%QHyYFBc-EfBtu-LbV@Mj1eg%17 z4Rz$Q4mU_s1?@6eB$FEzveD>m9QpC{dtfP*Ll@R_>POoJ=!#GhAR{|<=egRtBhO_%7!z51kIb0lVcwVw67h~S zQg;X#P;!+ZLbJ=sk@<&i>!sba@tO@;1o#_^&rw>L-lXk>$;^lLl>!hEl`yk1(o~Zr zX;84t>L?&#D6(t~VwZb0)fQCaw&V*M^f&otT~sE5mkn~1Z9I(_dK-*)bcj&zi!^C= z9yAUXOnVOmA2q7X$jk0=2swy%t^M6cv+UH(wF`3B5u=Fb(@+TJpc71ocx&pVLQ8HT z_$fX`-D9F%whBxtHh=5X&}1dK6qW#t?9y<>jd-#kdX*ukfSWhWF52h^*FN9#6|sj- z-7z0;NFL8%Xz@_vX@qBFRQYgzTlgfEOgudbABACi*H8$p6R4ge`^%2`FjGQYSNdgo z`ZQN|ZSnU|)sxh{^Sp=h)OvHCo^9}S1Zw!~iV�9BB}9WqMs~1`NyS@+;d0=F}5XKW4sSlkM7AWqZc)4K$e&qXB$u5 z0c!pwF}LvkcR2@2+DvGT@c<#N2{_o{PNVVeI_Hg4HAW+Le}gO+Oj7x3^P@bo?OrFp~LGc1GMr z9WUt$`mqTc|JdU#ra$|*U@GevVw^W$CWus#z=bwER){R?UV7qD&Swe_hoqh2(O2z{XL~`VnhIw3ZqKyL3=*OV(%mqCb(-3Jrr_Nv06(D#MXC=0vKp8S5;b zZ&7xH;KoQvbqHw&MEVzR&Sglv(@X10Qb<#0gRBt{dIrPZ4 zvM+x`3R&6DOoSy-Fr;d^ITZ+2im4$%!p}rz;?Y~gwZW{H67$C+78W98J+uqfFe3x3 zc{c1-B9z=r|8Xy=`a}ub=f6lQWYyNABV|al-s=5b5t)ik8)Y-NNXEt-+t-ZO@003K zx&@2eAPG&_vX^@sr+`O9i1gP773At|irxK$PE(_v`e7IJW@}?O-^N{*v!}O)3`AC< zgW_n?(^$Gb-OgB#g+&8{NT7TCH_ooyh31A{C%m{cJ6rq+4s;CzP2cw2*r(wkkh@PYV@6NprwEy(fBp@hXfp5_&F0hQ{@_zqVD6lVH0t_2;^*O71+X)&Hd zCgB8H0ceYDG%Bh112VQBOQraI{E6-CM#Xt@lNEk{Kdb)(#nDUk7DFHfz09?bRK&-f z53k@{f6bKEMps3&Of>Q@q13{uwIqR<547&~haMehpV*k@co}xE|3mS1>^4$0PQS|S zH1sQ2f&B=;hND2Apu+Ud#Z3PvOIO6rUVd)!e;8%+d{;=3@H?e150_Ju)VTW)Kx1%w zt5={K{J&Aue@y{E@V_UBE5N<-H4ynAD89i+LHsoeZE-FFILMLX;DZZbFQE=$7XNkN zI^p|fY5$WM{e4dBdq5Iw@K0lZ;TCH6hbI9+dR&CYS5x)ikUiH3Yx!3&5WsR@S?d4% z`2V1-|5HQxXw|mT9HoWby(#SLTcL_AzItmV~ z1Ad1{hU;?W+UF^eeu;eH4*WM4845Muo@sS@n2#y3kl^l4^WV_Tyk3c^5l_Z|Z7%LN zRcn_4L$$THw5)?mCE{6yw~|Noa@oFDux zmEV8hGl07OhtvIk4S|LEKTnU5whJ$&HCOVZNGju>rDL_G38!|CDkc%6v~J5-4)n1G z@0h8^)bR>>5z1W$BK0V&ea7aHSE{Zd?_ntN=%U>L4L;s)TxB-H+MNdBxnjo8@P+?KUC|BCEN5`-;C+rZN0g~=}<T;4zdn-OqyNE-wFjTaNmF!$@`cf#ORaw%J@d2U zy6_&2p&q@Tqb)5J@k=^8 zk!tH673&w4ZW+I0)gS{_!!QsWhhoJ08QNI3Xv#3=v#9GWn17)zr3|iZ%?R2I>Eq2JO$N51n)xx zR~}FKZexG)+zgUs{(GtY7VjIHf*Kbo_(yX?6U|w<$8^LIjx1bDc6AecHtJvd2wr{V zry~jNWHpo@%qh3{lE+sRKgGF6c%QOg^gNkeCAWF=Ihks#cuoDTyDjYMosCT1ZwTF* z>s>M3z!|%u>bhFu^41?3Zg9iH<1HL&BZhVL?d(QtZq65+9M&kKp{g2Y25N*GzI5stnn-@c=f@E5i1W`&GU;p86oY9fiK7 zG=$&vZ}+7LL|ZmxE6c0%XLX6Gy?9c0h9emDTiYHPcphzYnt)11C2^eW+5<$PzD< z{WlkH!HK9}xMT0EnUtHYVPuQ~MoGWHQ%GQ2>w+V>=Vta}QNk{-8KtHhrJzQP?cFXM zTe{<)K{^j>(@DE@XqJ9PCL0EmT+9KTR&pypldARHh9=6dcQrr>PGaj$U&$cc>%P!R zbuZWVbfxZ{k>MTN`oF|hCj`1@ZTMacQA>Md?eArnVI}AKM)y7%hn;?2@al?4=V?eq z2QSiqTL$bwyD7AzJ+h}Jr?)td!M*F?!`*2}_GazGBPrwIc#Zo)beXj+Yx2;FmSQpn zk)PvABqHMTdan?^w?b5-JJiCbHeR*^ED9jA{acS_Uc_J#ETSg|Uwc#Tpdr|+#^8F( zV2wSryMaB^_iqHc+K*eB7HNLH+#q`y&TPav zM}tmHb!sUc(7^CQ(3@imKmze79xu@6cNGg-_jzIe8WN|osdDbFmU|NjUt#d$Mee)H z)wu2=y5^aj$6E*pv@7w?f=Y^{=Arl}4)m30w`0d?BjFD-lHw#xI_6Njw|!*XNw&`q z&8c(Tky5|2B~|2UX{#6uP`?4yA$M|Z^a!xnBEHyiRmIHm93ifbTBiMB*Hh&VsN1tJ zi_{&Qo5r20QKIJ_jQX{|e}b~A7!_f#ch)-+&05Rdze~l7S9id0l``dUZ4n~9DK6wx za3U!;K08sKCN(m?)b>+e9r|wv`$UJU2_I^kq+{mbNcx`a%YpMe*R0>}lkfeZ&V*Mg z*0lfY5{ZYQ&5R4%kHPG^9ckbUNgwTV+hWzTlwGPSI7;D~pq3dr)PCq&u}j*5oD@r` zaiO2@%Q%kxW|nTIz9~#ZUi9rKL^n~7x+?4ExB$Ke{|Dx8&|Z0XN7Cc*(t?EUy3#$6 zPesXYG1&v`gP%b>GIi>~aMC6DRB)tE4RJmn(d18Sg<%{!e7!mr(!R%C*O}0kOy*^S z4(hiaqi&!R8;hyGxA}VPsg0ah?G0T_j&S}xQ|_St_-WI9UBCN;3d?dbMIG++w4lKa zQ5=WUlNx)r1}dIryA$)kbE7bGtMeycd8(0vuseMLPtU5C`-1Z~F2$!n7X3#PizUto zvqe=@%gFVLl59g9S@mtnb(aD9XBjn=X&o|$Lvak`y1tfBWF)i&eveP7m2F*B(m@NH zx5A>~f1_MAKB_L(Bg{4atv&m^S{XOIAp;glLP_hcSvO;}a^sPP1Jw~%M;xif(V23m z`>+2C}`su@7o$cZ8iiu+Ll{ ziRMeGbQF}~_$@!)dpe_=kKHrT?GQ*m$2*pKkz{)lw6_fnC;y!j!syWX3rcVJWUV6R zaWDO0uhDv4A$;)YR4d@30j zErYu!7u@VMt@qhiEoDgy0o@^7i^*zsgfE|;It$ctlf1NLnZ|F=Xyc*Rr2c9w-+hVH z|C+W5E9K!=V8y~BceKxJ2Jueuh%!O>P@aWfGpxPu4KJ3XZGY`7?hOd#{n1~>z<8Hd z?dz|?3*VU$TVz%poRmn;ao_V)3NA2RdGPdBf3+=GGHJ2FFD^9fU3R${*)y#3thNe;mcYZ#h91?si%z$Oh~3e=(wTd(}Hz2PvXHh(5lQec7JnS`SP)P zdgh=DwGLGq|8mBfv2E>(Sp6teslBmaj?nh|W4u04_90U7)PBpDu%r*sq<=;PiN;Kp z^OtpQmjp7_>FD23-s%R=M^N-a-5x6^7f;S)=GN{ge37b&Ji?r=P9@LEA-1$vyZ_pJ z?JoMfe>2vv3=bF*P~TH7xzcy(+=?~w zi(O9V%t8zf=Cyg>%C=i5zwJ21&~ab>2^xN0?#VJ?n3%CNhFesKV~9PtFzO9-zsH&& z%Z8Rq`?I}};@g6Tj)6To@xE6+V|6oG$^WE{TTTh`DO^%BWYR#s4Z}$Bn2+5Ee^Z^D zXH{S~Qs#8+!d1%%dlL`6mEb|O#7)lB!(4ra}lt!j%Du3v?i;uGRu<(YUq zT;1}NBZsHeT!xS%mxO5!G+j$0ChhmvoNR=Tq5sfHZ=j8+ zF6<>C#?QMSa)ZL(_l;BK<)dLrd z1?v-C$a6w12xtq^SL=dJMUmF$Qg&B;OULK(0v;}z@YIy-_XD>KeElE3(1GO&f?jJP z(u^!I3pu0TWVYItl&uNf!Rgng$4I1J>3d~svnp0mR9MO?+3@!#taK4Z5JMH`nNGFokju{S)Y$@Z1?cqp>5Hdo)tty>n1 zTpOE5I=X*y;svqaX8XTyu`D>oLc*#O5gboXTKZ!vev71b{rtx2lY+d&yDs|CpOfp$ zcAU@6dUd*?C9I}$xI2x+3vDmt!tNpYO>Nbb<$d%8v$e^X^Shul878`0#gK;n(sa;L zkI=mRbmDWQ(870xAjuc)I;t~6q9tD}xeT0HsdmOsiLoCO|B<8ifq-QlA;JiDys2s< zqr|4T(@As2iCEnDpWOTFL=8jMq8;Q6n9qsxZNOVUg@Ty&R0h3j4OAt$rCyS2avLvu z*!g>qO(9g}Momb<%TKD@X4!L;<2AAckHV^RCcQmp1{eqVs8ngSM>emXv1JPEWv)y} zN4`)6$13t+JxS+S8}$e2jF`14L9Ee**~SSP4C)N*=|_KdD4T?_M`a+_XdKO@a$ z7K?D%1Y@F|@#W|)7_D)Q*=A;IWRVK1Tt0M49n>L8IHc?FC0@g=hch~_tKABky8R+V z&Dg^B_*C3V`Z% z#7yj`Lxhgv%0fvf5{1p+oCW_aNx#m|=D}#m*R2cpG#}bg2F6$eC~PQ$I0}6;j;OnK z9M&BkQDg*ds+|i}fy{tsBUx13b@5K#fRnNPW1GsaiO1=uqs%!U403-3X*>q^6{Pb& z6QV*dKLzLepqCleLn@uQ5Z_h4lca7{Lk-;?)(nvt`Rk&zUn zkkkNqdFIsK6^K~Nl>#cAA!N-zOXm1N&OSHK=)}C?jPm$T(!w2b=0L~ZwLLgA|!bfA9dUt4JoI) zH{~pl4H6A*vr}ZV8!{Xmg0}`v!YvkUW47&h&#clm^OBSeemdFtm@ldR1d@wlsvTH% zo4ncJ?HK1IOod-_p|0#|jQvMp9ZEhwLm)xcZ6qd8wU()aBL_8po=XXnr3R2HWp6rj z-9y9*I(qi4*LvI>IGrW0^bN;DlAZfrW@5dYE+$;q!_uWrReb6gVhAcJ<(sQVBcFA& zbGnl}EQmBXE?X`(bDJHgQv7}Mi`6Usgz5>}b{j;&V>(&tUk>f4e(Bqoa75QKTKAa? zOF#-I*!-m?L&OtVVefGnD6s+?ksd5!YbBOzx4<}LO`pg4ozYE&q8t85HwG z_9ZKf?2(qA1LDg~mzpplexHASx!{FI)!A++U?mFu%~EVdMA`mL^Uqt{zL>m|u!T>l zW6BAN<*qdNt!gM5PtaD{yyHJ|O`7Z&l7+0V^(Ti!u3YrC@h`1wE##}-WTX?S5i`f$ zqd6+!?}(G#z*U*;b!YGO9k6m4nHCKG$r+>YFQnTSYzRS1Ht<9Td88 z{%b}zIiVPmy4Fd3=)07@QZ2vg-MMH5ReteX;=ZFFdi%6LSwVd$g#m58CsT8+8VufR z>hN}K?g+gKbWKsI468=JYh1>pSjF>kxvR9`pwWW8SW5ed92^i0MdoG3WGiLqSPCRo z?&X|BiknbwvgB9Cm*9Zy>UK{`19NZyy4qO1AVZ^n?tJHbWVbpmB9|d|iJPEFir_#x zDbm`;ErH%6Gg+G=X?i~Du$S4&M7f&3tI%w-eH~flDA;iP072hT1&d1l2e${Gp7+{= z%Wvuw=L*mI^0A3<6B|&IZ>5Tb!OQs*3~_tV*di+Y9!JqGUy3}@>XlPvxIxMjIZuO{ zQ&oO^Ay2Q0N6*?~O4wCN{O(;P)og10mk_y!SXs3;Bcj;TKa_GM?4ZX+rb}Vx=XcJx zrLX3ph-L^J&h(Dib{!oh^ho7s>tSY`8am3nGbsq*;=EfAk|(D(C<)w;c~ zl}c0wlWc00*%`D*Ue@*Wyj#K|!+VqB-^sRuvv|v65|)o@aVdlyY94dsp+*|)3VTnt z=P|L*Ta_w}0`*SFO1aY&7|P0yfXB36NfLH8=ciY}(n{1d#YM^I>%z#=(u76kgJ6U$ z{#!h^BGE9)Tr)cJqGuC~(I(CJ{)`MF$}9vyDzCCJIE>WxyMz}0X#4oO2af90;slW; zk?mPqqm712@F0aOQ+a|>L%YO#|NG(>i+t-hvJGET#*-2FsZ%zfrnie2OcmWwUasdy z7G|}o6M2FI2Jj?8(&^eTco@{wDdhG{2bbo$Xc1sFg&C=578u}gaXy-|C z>XzQ%c3|*T<|XrsIFt12AX;HQLf04j+$+D#b8Nrl1y#!4VL%Cl>%IJG+{aK#qJqC= zs*Wh$qU*CYjvy#6=w~KjjTv9U8ZCJ18J<{GN=$!J%4BgSLGaT$STEGXir87faHoFZ z1n*tL_O@ce|3;x5(dD!FtMifC>xh8qsUA^Bs8w`^=Vj*?1IGkjosPLp(Q@z*YV&pp zw;uDt$p@PM;W^zXr0$3SH&?<_6@dT#qcQ|N60Udursv;RKL2~p|Jxs*(LPj0VCemQ R*@6Im#6@I2R|x6){$H86Ys~-v literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png new file mode 100644 index 0000000000000000000000000000000000000000..f110028897e017127fa0296c2645a4f3fbe15a4b GIT binary patch literal 70490 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%0AHLA+9p8U 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 bCpy?mDOn23zb;y;V$!CfGarB&f-!YllA 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%0A$zyp{6XoSwLz)cs&3iK42=1ZijnE*D#aVA%drhu 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 LhGLPtY2g0>#y|#4 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png new file mode 100755 index 0000000000000000000000000000000000000000..c3186107bdc6984f3a41e0253e2f928f0d223b59 GIT binary patch literal 48073 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png b/arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png new file mode 100755 index 0000000000000000000000000000000000000000..b62000d63d2b132edbb531f9a3142815a4164682 GIT binary patch literal 48364 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 a3*SwhUoYfVF0&PBuX#%MWR{wFz`p_J6uFH6 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png b/arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png new file mode 100644 index 0000000000000000000000000000000000000000..534095f509b737a6758334fc347c5fb41ba1500b GIT binary patch literal 167225 zcmeFZWmJ`07dA|%bSfz!U5a#y(%lV;w3JB4CImzfq>)xiy1PL@y1PN7yEm};?hT^n zoaZ_3zi*899pm}I(7pG))|zYPwdS1b4pfwvz(Bi)1_J|wAtm`#83qPv1o#U^fdjtT zX?q(E`~z#REb#;;zn63k_<&$4Dklm9QxuAR@f;EOjA|>XWe)>G-VFVNweEKif`Pe8 zmwGCy>a4$cxpiPIp|=vckDP$KV#Cv!dhla-X8^~gQC2Qp{=?lU*{C1h;(n^AkRu<|wi z9GlUyQ3r<;SG_1{j}wQZ^`o;|p*q(*&jJM};bl}IY%drDN*Gua5g53C{I~r6ZlqOq zy83_l>DK^-6yZUX|2~)!#ybxsMcDdTwCnxxFPFT_!L zK_p53opdTMNF{;Ry5GOe-%nu<|Bvnd-bbT4LO(?Xl}z2gJpcoyw)zil-3}jr4+CCO zf0;$}Pj=ouAOcFm_)lj4`c(%<1T_7g`RK{N&A%F2`rl-AJ=~B9ZZ%XVEM5O!C3YFc z^>4yJdG!qD(vGQk82#Vo2ZW7uvkn^qx%0fY1i8ygw%J9~1B7A9BbU|B0dW)TdueT1jb^(*YE_z2~Zj z?suFC7Na`}Je(=C%%CuEm3-E1x=jG@$^BGhOA%vGh(BgZ|6-A7YIzNm1Uby)#%GcB z7MVgw%d6}PaMPVCy4TJ(X0s6*UAIU$^!iPql?@=p6GFR-na8ko$*LBCjIf|r{`p0W+Kf7qB3u1yh;H&)`@9IaKaz@=U#XFnYrst}9p5`s0nhkBzO(#{ zlzVG0MhWPYWU7}4Hv-MQ^#|Gzm#L{)!qcB~zF~&ds26q^9=-NSsmRjjs>?5>2GmoF z;Ynoc4PX7Npnk?X6G872hpICI6EY>Q04iq|OWyrK;0^go&&bj`Myj`BWDxRMSijbJ z;4EEu__am6&GEKP0YMj=W{)k_WM*(~86!P~F3$VS`vmK-56(+d9}UX!exF{#G`FeY zQ=fUZxLDjvLoO;yWnloCZecOe$RjdE1`LEp1l#U88^Yq6xoEcJu7aQlg4xBrd&x{i zF)8IMD=*}}QCx72R};s}VX6#yyz?AUOw%1UE8w*;4x39TzO#~6+B!C=uAlft|0@3n zy1j+N9?K>^Qoe03&w0ji9Am@zhAyr2;!8hTWliO;pW7LnQo ztvRao$i6bA?pNrOG_$)AIl$gMeQEE;+E0qbvv^?8Txc3)8luE-Squ)VG{SnX0b zH!wvQY{!1|&2doku@IB0dQM{2ig|w!BX&+eYV^WO#<@kyyv~zobf(s}4{u4_&5O|Z zX#LwywkPqwPu76SAsuK$eeZXdR%J*6(hAhqLLCPab3U$y=I9pYseK9RN}@%>!!0?E z*$8#iO0V%VS`XDI&@aR2EYAMwTNt1t%e9E_C1MGvj!qEDv4~-`m$2dYUKwR?o|a~o z#@uYo1d?Y7;{N?}D_c=@dUFfV!WegzVu# z0o~Ge=v#?8TEvp81Z8!H`!9DOdx-Hr@5=hysr&nzo@HZ2QR&N!$MJ6-MDg6ZLgtjt3^xmeWXX`TXRJ%`;YPoPIRhYc3U?5e4==37w#kTZ-F~PfYd%>3VpLsdL+Y5w4W-YDEDBXB~ zyK@jpA%UZ%{%D=h)US@pOfH!J<@+m%SLWh4thhh*61DTgW-P+iW9^3cAt>%^Db(ue$3Ko=;7Zs(?79%Ucva z@8szrT283U78N*%uk*rrk093LUMhK-7u$cN6+D9}tajO054CiVkU-(g^lJ13g3~tL zsPm+tcQcOUiRWUY6e_c)F25~yP1%qHc|1#7iju1N)4=b#yk&)oREI! zQNh+-1otK-rZ1}{uj;z?YZ{VwQd55}5`0DSq_ki=c&Zj4TfQsD*zsYc3J$fHvE|K- zzeo6FC;xFoY`atpj;7u`(=Z_J!u*XN*+Dt+0g%evL|c3WKES_>D;2Uk>>zYXP`c6i zT_Iy@=Az_&`A%x+{Ij1rw1?1WI>ald3e9hBEAlIhL?Nh&LH!q9gdcgg?ziB*LtcR( zs^uR>&0VJBL`o)jKZhu(F|i<^CRxZ^ww9`cO1YVYzSi|L=dX_|xGmTpzlO^}cV7ml z26yW#LP^n_<)TORmPbtycD%>aJxlGqkMo_BtO7MRNqBL_e3O1kkCi?Jw63I&w3^x^ z^-+C38)G(PvRT$Kl8lFYTG`Kf3_WVNYH(_bms$n^r=qAWp$jwSr)^a;sy|w}#lDnvyWmt%jjWm6QTxz? z;367%xzW|2Z7g2cE>q4hS%&vi>p|W__-eFPI06yzPF1qX&3l1M{8D08LM(H+#3AEp z&7(>6i-fwC0jY{?G3A{OzO-(^)&7Zjqlu;LtZQgkHb!<5X=nZxs*V-PW``%mM)Vz^#8un2aoS-B+6v(C<-^%<^UO6AVF3k9n z-~J%~$6B*A>-I$spCkWR+74B+^V2&%W!o4Y`>+h20=qk#-hz%Bdj*T(T-d6`JP6sD z*pkhDDP^ZI7Q2*6`!J*ix@zFmWCcNnRlp~`Pi+K;g7Y)w<~kF{>N&vtDGSzjFK1uq zvf)faI&~b*3N4GrFtqDukh|t0qV90e!@~lAA?+^Iz?P{$^2S`Whg2aGIT3Pm?gzj| zYvKs_osLYFR6-~y9=qhCAy4U^R*_5;MWAKcd{FZhOtuyHilScrzG8;+;o87=xLQc1 zpuX80x0tEH?pLzXXh15s&)V3Qd^XCBL&Hp5szrx&-SBKl&WJ*KFa!5>WkN2cbGtHf zI&1=(ih2{ps`H-UJEG0S=2E7^`ZMrEXasD)cIueN`7;hz{mj*-CACkG(RSk!R~wtW zPmgB5xcDy9t;AT$9&$-FAdf#G<&{&)A?!Ztxj0c%Y&Eev`)SK*EaW9SVvXV&Q^Pq? zdAH_c%|i4K4MHtH;9EFW4EQ&Nat^8D-?tX)WcOt&K4lG@_f7<Mq4N6 z%=IrJr|~{uyen|tYUx$Io$j7DLLfG8Eo*=B?c0oi2i8$d58|X^6eN~K_lvN$kqm#j z0o@!gqUB`t^h0o6Yo!F7(>asPh+0ej>1-TNn4lSpnfZhSCE8{*fb*=yLYFRa=v_SJ z+|<&Ao~uJA z(qn~}V{ZAd_~q-_IjPbpth%rVA9XAm8JVbJ3I%Hq*mlOz3z~Ab3&9wI&LW);?ebW^ zyXCpAaGy0(UZUmwsEc%9o|x)SI-CUm5%Z_<()VB7T7i@wsF9sed!9~w!q?V8st z_Q0)bX!Zr%Wl^n~sawgRm{H(&w|OJe@|MiTe5iwFoaUM0_FmcuZL+Vu!%l(=P6ain zK98ruX*g3YGW?#&r}ofONx-F#$t6ys5dP?CG#zfig+#RB@Rn)rI9^rH*T+R_AcWA^ zz_%z@d)3$lqyyApSDdeqRyU6W50JYKx)x<#?5!3(4MQCaxp=VkwJnc!ZyGOPd<3tQ z_DVN`fSla;1H$G#R3xlznUnS(Zor`;%R%d%m9lK0kJey23rR*svJm`Crzbp zWa{c~jSS;1L#%v=!#x$sR1=Dpj|)huPVy9+2kV-Bpby^O}%1v>w+NMacE@u6|@>0MdGpENroHmeZ$@V;-> z8+)lCtz+#Q+xUBAbTerhSfV0>*6$)Jn#b8Iu%Cjpo;aA4?VM`o3{rS7M<|p})OhXq z1cmU~d%SvsEijFQw9(WJ^4Xu0MOIMHkKZ~W1jOQ(r`?MrI6GZvx$S89_OhZ1?Sr7p zd~7nk zWVs%BXfa{S`d8Y<-qRIARpK}MVkgoQOj#n*`ja)nQ1;>7OCBcn&v4AvBlaHVQkH$Q zT++GP=zepJ()u4OE$yw{b;1>E(O`34&Tw&!;hde^yVR>JH7KXXSkIDXD(^(!fi!(A zqrsb_P$T5RePk|g$O6dAALq?yz|B+WK3=Lk*ISN`>p?&8kQL6)9XX46v+4b=z)+4W ze7>Ide0E^yMY-eCh9?;Sx#S~u{G>^7QU}p9%Fit0 z#-qLDGNx2~0&`jP7T1`v9|4Mhnn%Oqoh~k7dVJr}CUuag?S}V|_x?;mDUl+D6uMi7 z8`i?;F2b^2;-^b|d8Pc>W^h{19d>p;%iS?#D05Oia+kN2gG-^;ddP@8hR-& z?{o1GxAk#^8n0HVSExt&HrcC#?vP5AmLh&q;ixc-wP35hR7kM?WG(N#9=59?j2PNg zzxUBGz6jhmrbbay&EXVlm^|g zZT(;$rDJi%m$bHakI4~23rLM`KxL`_vvHqBkfRO~bg zJNVkN0yH$XFC8zI!A9)K=E`-Q>!HypF_twTg8oqNuI=zf~$`vLgscqht_Q35B(V53DAEp`!U z0f-5=>~8Yx&-G8TTnX;I2bMY)(FHHL{Slon+iMPWN#=r{zE=Uipa<#l>w;uMK|Tzx z_ju9-;Ax#l6_UAoGHE)?05^$f9B;rEm64Vig#3Y3g&IQLJM&HFLSUo;6(`p zoR*!5EE;viTZ5yu$9K|)g48!JO29@bZ%u~WF5B2$hVJC2!rQERLt>q2v6-X8o#k+c zd0l+R=@9}?Hb&LarxeuZbJpWjD-}1!s|@m;jtBlW&rRk1-6nJ)8e@3NM-B4XOB>z8{cb~EZvN%Gu03b zNt3{Vz<&^ii6zAVBNi7}$j}7hN|hqmEMm#-R(r)}rL(NPdp;!IYmRO5QDmR>$ zKBmM-phelQNLpDyU?*1^6lt|jYo~;O`hfN_cgIHYz$Yt zeW=4V-~Ss~344ZCnx~+jwr|cOyCu!NXzi~{X(TQ06G6wbs!6BjG`?-va|L5{pOLo& zE~Oh+qU$|N@Km_ayt5PIr=B~@{Hz1ZK1g0K8B@}woU-<%eawR6ux-AzYucL?^MXK}F_&OaHGb2(sZ%!aZr;UP8eSJo6_d7IdpN6jkF?H6H zSExh^BY8CD)ADSb*8p<@QER&Iw86%}vanLs#FHOaN z@|5F~QLLbmq7K*R;tQ$V+E3{eilL-%6q3(pjd>$B9}@@{<-86%6b3&awp>k)z{~c@ zUuz60{noQz)b@k@eo?bHbwzBMcG(uuU{Hj_4 z3r*|~2e-R1ygOTpQtpnQCmotT+~TtuA*8?XLMn*4uvXk^8k2kBH$YK@U!M_&phFyU zn3K^FH^eIxVDL21Q91UrZaUk!chC`>K_s&~^2bU%K?=(rnV7zN zpOUndrZ9(=OUlkf`{ae*CDSj)j7~gykVHVY^I#cEa@kIndrX@M^Nu$bO?-fvU)QIX z1q@8{$=sJhEg2u_Ue*xwFxi#3=PoGXmq&nXOEW5AY1;-f=T#}8+$?fRo0LCoW1g4 z1TunP_)Cd^s?wNT71$}p0ba$R=*Qvv$SIA(xT5UmH2A}xh`)@ftLZ>K(su>D4&Jj) z;$_(|s5nosG+C3+BYjqD<>Btlwi<&QG-up?P-ICPSfVMt5RP- zjvgPqeu7FqyvotKbd#|?Sp$X*N67MEY)xBa%#_ZjeVDFg4ux6Cid>z(!0KI z8U&Z^FKT>|x7K`&D4#nH3ylnVMFR zf`ZsM(RIT9rJ8$5*HoW_{W5(n(p=2x3*CM;+U9E6H{T}}$wQjm#NxrJ!uM1U-nn^w zE7!ve>wOb|yhM0oy@O~rj;@xE z?gZ}|4nV!qr5({eYbNEt zq$LWXrf^~0oQJfozS&)hM`_$t2K{WGg`?>olSmcWUuK`r$`PE{YLcobf)eRP80>{rQ&eE+sujqsB|s3lSW)wCd^ithNEn9cJ<+Mlg! z4uLDChZ4RK(OwnAj%!C93F7YaL2b?DPm3V|z_Rkm5A?sdd<+T*93N(E_Uz$X7O4ntVs} zOO7HVaa60h@3;djl7~8^%dG%p_w^39jY&aS- za|ZLR3C*-T?UaVdl-*_AOhzzK+y=?zr2AfaIi8FyeQ;N`)hm_D0q!!cMBah9XzX3z zuPQ{=6aw6nCw;4vQd00t!R8|)O5+5YiOV(7QFJb}xpHP@6HMuf-krt8aDW0qR8#~C z8jjVK>k-wTynRp6fvIE>a@Xfu#6i|R1s3SXcdmUA_u;!E1Bh6CVAFE)0j9gn2p`dF zQo}L1zVcq8XuFx`PGwtCcwFwU|7hi{4dJk~;2FWM1TJUhhEAO{f^Np9mTF7xy*ZTqP|kuMunQ=7XQLAp#@65VP# z5ARnagxQ$Bc%{e$W2{j3B69i3f=Yq(C|Z`Eoh*LWmv^Bo!xZT8W>mT8aRyQ{^jH%2 zXTu{*au~-b&|_@Y%?6EIMJ}&8dZBdt=*52&u_y?BF!{!&{ei*+wX`jdb_J$a;)Ow!!XogH2EBO>@CeWfUcVK$G+(B;kr)=Hhuc2G=yd;~8$Znf+{4 zW*sgFU4ogm;w*gV%$X>(iI96^^Jk|0<8$v=66+|+{SAfOP<5)ZQ?+XrIn3@4DCJQH zQEy;&e*xfdKLruzz_;MmO_;~!c~4JSp*&Li5?yXVjUU1AsyBST^FyX~pIj&F4?=vV zYn|GgXWuX?eD#GY_VV=Y5=k__(ZY=I_g1D){bcmL+rjnyxnY?d7PKb?&9NrWSy5cs znUjB1$e1f%xB>gM40S0ghekDNwaw zLLe02N6Ltqu9YE&BUH5vP!-H0)W$715sv9v5-yo6skiCV^;bGuG7og}ljm*r{9Y{M znm4H2B~jS4c5%#m5?zBZFg?H0C`$;!X*p%En4#DB5Tfe*(8DCkOkQ1?#ILcLvNFO& z*?bAlXmS%N%dQ9Y@elzkD3|S<{;VM`K}OyrO6$v|H#n$18z=drVtnyfF*2QO5e`$D zTZvx_r4X8}U71R%^sTqKR6S1=Y8hh%%&9^=&s9+_kUnW*zRI(-@>X2!TZ}Z}1HxFv zaEE!T-wBw2|LRryc5)6)x~sJZ$=JtYQ&|BT*?cZVl)Tyv#g0w;9S*U1c!puvu21;K zs(vdhxhz(*J|Rp4)W%|Wr*y~39={G^C@oJ@W2={h_oubA#^)k(gLL-ei0mZwE|xtR{W{l?%SYs%rx_NU%PUC;{2KDJwL@atxI3MR58-{h<<4S{ zKbmY+lr|e@dK98c3w^2D`&=RrTZM;APfSjyi`kZ*w-&k_LW(=u+LtP7>nl$D{iXfb zz)Q`gj78ziY`>Qplo*|TiFFr6^&fX}4%1P2Dq=S;g~&ElVzwz6uX<9IpVwJstpM>DoEMNQoCOjb^u_@0n=|RhJG{ zyjV&0fMa+?!piA+*0JF+L*n|pg!7;?Uh5e4DE9ttyvJuu&DU8b1sR9{$L#N17KQ0_ zzt3~sJJ2UR8PPF(KJ;b05jZ~~W3uLd5KnPOc(~$n%$vJ@)|Z%`rp=V#A#}{b*06%e z&sYh+WUPB}a^_mj+Of<)bWi#xLnQyQV(zJ}uCo-vhM(!<6cKva?qXDbCUew>U600B zI6qUKkM;iGv)mBpB_>PHB+Ihh-DEOCqb|$U95E&iUZ<1zEHry~hwSR8ar*TW$g%(( z6;FE!9(b|If{T<^wTnddOZldu5juWx`wo(^Z_O;7(aI}D<_rJ0EkbE_6VyuSQ7a?0 z7?D8gCRzi;%$IYqKuTY6N|(`fA(4KS*Gj4D@UcGm5a&4KrPA7#ca~pG2SL4IS2^sJ zUIv6!OJj0fx9Fg+eBDsqLz|ezJbGicKPO4J>y~#U%6X9389d%8={%7I7j#ReF$%m5 zMnc9VbY?aiI+p1doq0Xw7DV;0Dn4SoS?HnC!9t{*haw4LD3SmwDhV<`&_r~K3%BS= z%O-hVMcah7$R!@v)qIfSpo5Txd|&8HYVS$t5yW2X#as35Nc0ye+s5rOj0H`7_dkV; zE=Fa&RStPD6-9B0a9jzSwt#%k%n{$J+o)j4ZcX=%dT?<xVCwV?O(k0K5&r7A1+bWN9*f=;VjAq#yQ4HF|{7S3I0}cG#cVO@k){Qi+IW-?Q^> zdM<*6kvO4d_UI#d+kzg~wDh5*pH=P!?)P#8ChTt2JijFa;|M|bk(s$nzL*ScXF4=i zjv!BMJ(f`OIIBPieed1_)Ur=UIn&C%Nb}p)=6Rzi(1cg1g#oeLD|(!1?iFpNT;blP zg1XOrGh~>Xd_VPt$Q~i|`aOAUb;R8dnDQogP*6(B0KfFZ(^aBwWX7G4QIBATDq^GN zu3WhWWjUQMy}FHfk6%WlpiiN;QqDuGje=04R-^uytIFxrz(5*(dX%gSIt&<^Sb=oF zs=2n*%wwNz_{V^$N6kh@D3#3m9YQNJ2LC7I?s^-I`>6Re(Fk`Lv0&RDlyvS_kv$%+_*-tNfL1 ztQi3^+VsR>a&`^qBe4*JKjG}EuP4K~KLg6p{ff^bxbM&DtFTX$iVJ_Vb^{(&%1HX* z^Re{{8Epr5-kNsQ4Q=1^jA!oh3I><{`s2(waatYl>l|W=fIIOht09<_W3QQ)nzkfU z0RAl(u>|#R^0^#DR?{vghtLlmBmF|h0m%#)9Y>xd%NcKjB zVo08jj)H@7m|qjV5M6w3o`^tFcoLy)t7xTe98dE|ONx(=Nqhq4!JYUwjLynVtliIe zWlZud<4HJspN(p3KXLB{lW<49vZA$WQH$>})W!}u{IFnl!^HL6b)==}1o=w(hRkTJ z3cy9sO3PIddA8?sX;JYaMw!ydjm=(O?nk&zKm05)Yg|w^8QW{ex;DP#S?~U~7R>V4 z`EIoOHe3NT&8}1SK5A}asNx7nuXn{6gPT$nvv^HVn8AL0^FK%^$M%Wdv_cgarsRGQ zTj^<-xbd_V>*cG2N)mZ;%_*`dC;qj7FU>(5Ub@y+&vVo-&1EiP)JDJlBa9~5uVHaXA|AjGOkBr-^v{MT=E>~oUJid5+S6j(3&%-*F`-CR5 z$$nv};C)nRsjscZTIgs3+Db$;y>YQXj!MmfmSci0RWK{2#NtEV42T)^2!T?pfv6uU zFTZ@W?#DNeP)pn^moW{}Kd8+F7S|c~6Qi+3r)Ue4+BImnovMerapddnk58WiDF1FI>o^&22W~f#xSqi)yF6lY z*%tIf$<=TgAF{z)DIKUvJ391J^qdVx&!%~~)-G8id-1gP&}Ahl?7`jWiU`7MeXLjq z9IwZBjdw)fr)fU~JglJwn!%>}mz+Teuc~tdE!ax*@yH$AR4~9-(?8k~O&PLA?~KA% z-KYM8IXC-XlQ(WJF3vzA}roEx!dM^BU&pS;6MqGm}q*Ff0vIa zgOej(7QceC=Jj&xi{$~Ej%>!gFxbVy`KJ+it-SgJ3}5io?&Ov=8gr+der1H)-ffwRJuoA1+N|@d5r}Cj%6jLR{*CRU zg$?Ng_Non5uB_}Q8kIDMT`%tGnAtSodPK^nap|5uG-9RSm{lec*5*0DT)VK;aah#l z>foLV*J$`0!`-!Sq7L!0fRM8wY*VRG_pS4D-5nM5?Qy`L_?YE|m3ACbTS;ek882Ma z0(xSv9(BjoCxCOqjn3xz^42$}E!B$H*Opy64jm=Z%?6($J$M+*9U{HG6aa-jhIXH& z#Ceg|95IZ|WGg7zdi7eHkn+GV@r*PO+L`M9bOX!f9(?UgOWA$@S*wUqr_Qd)C;`5H zeq4+_|Mg~dTg}g++^sWm7R+`=P0WIq&+r3C>?iL5ww!t7SCSmvC}o|68WTEE9wR72 zy5R3Q`M|Cl8{gF;ue8wCw>7$~lvg5Tmvq*UWSld11IbK9C9Bo|z|WU$m|f5|#W&)V zg1T$nce{Tz4sJ%la39u*lQ%$rWTpf3D1i)U^8{M^L<)0AIzFEJwTqa zv`t4N^83{-X$3quYoc3-23@NQcu*$r;o$L8p%f;;C+L2=z5hDbbBA71R6Ora}j;Y@U0qK}43J=>oUynIEtL zdL=2@;i2@h0ra{B;yeCJ7h{Srl;y2=f`0AwpM947=s-&ZdjfJnai+66R!uIk~@H(O}$NEje{11Qy3gmEi{%j8$xS?@wVDs0DDIy#I zAum+%-~JKj>IYzL8=RKkcPWr)fQEWQMLX0#cHIcg>EQm}QDX-n$|L~<;=fS&pVwIE z0dS}p{NCp`i7;?=0K+#~UX0(~ylC_Sh(^A{$O^@3zX&IWmg3=lZG+T*5`GAccYJ%Q2tEf zEss)oaO%8!6 z>Ngtoz6b31aVh;RzoDCiUN_2b_A9y_7c2$nR(Ith!5^xB6$5Xj`~R=F0b_ck_!mwm zK-*2t&+Hv;p z12~x95_)he;!?n=7Jc9`M7-Ib;UlT0Z58Si#bsYV7X&+D0 z_0y_BCM^r<)-vL^>(8xGW8x z1%`%GQh1&&Ad>6WxgJ5zcN%OLeBR2aIUMwG&$;c?p|3Asqa?fq=9DV5SN<*QUy02d zci>O8yP6t0>oBGlPDV=vS)hO{WC|T+U6stPpc|Yv>&$`Gr9Mi(kE}eK_r=0&#WWSC zNr{}rnQ5l`JzqZ_pzcXu{PJ#i;f(;x5ZY;93juG~G+Z7#7`JOSUUX{IQ`sGy^?~YD z<@4~RbpN4n-OvJx)h`XLrc22hofH@ET#BE&_<0mg7Gwb)Zx_l?Nqyot=WqMRjX}*3 z7&v{0h2WRTmeZxw8Al$_pY0^>xSNLQSIXU2xgUku5xlu&)O+`@i}v3Ii0*~+ulglG z2@yAC%f$Aj6@gy!SPIB)0IjHno}`tQSS)2f3hXH86%BUmZNO|y0{qK1FZdMm+T+yW z_A7@fgG=ekMxReVNVRjx(6e z?hk-CRvA2sGNEJ;=Wu+|L9otWO;_PE1GMH zMS=kOb%N2jeno3m{o2$0m-ApX;^gJ=lp7jqxuXn#W@<3V{BOe>J2V#Cy$Gbco`)R?mL>G-Gu$%O#jlI0 zXGaIZR|l^G1jU1_rqPcZtOZ13Z{uqtIRI6*?{}V}T=QfGyTAF}N^j!%JhJd9dc!XI z+*#t>*_MLmVSAAN;THuEc<73=e5j1($szaO$}m`q>^e#o71ElevaxJrjHs&hxN=d36DI&Pjko+PJe9 zJJzj@2tp&YSmYkg^%r2u-EpH(!40iG*U6zIlg=fQxl{3o-C6Kx1!NcNs<6I;(G?vn zwm$1k7h*fPCrU}-xmlc`P9S95{;-hjc1}@X$C$X1)7MDB8y02S{h+77W6P3dN-54L zWt%~1&$f;&f1wn-WGZ|VU($<=Lcv-JHMgEh!{33w1`4ZkY?qj?WmqaB!gOC~ zg|}}&)l9}ySHnWJ3@pnS3v>`iCzall9!)82-mCgq4+8WCw9xG52=8kQ^#Gd!Ua?r$ zya!T(D1gF9yrUAjR-Z-~gwoBWsX2(_5XF&QM1j$LW&3n1z3-=V=I+N4cxZWrBUz#4 z#de>fnij*4`%<(CAhSD{`XCJH%SZi$psg`aImE-d%_5h@ZCz{Qj;bApcU)fva_xHr zDJb7n_EQ21gXHTYb*r+QP_#Bn71D71ML!j+jORr=op8q7+SQKR-1%nw{K0Mumd>Y& z+GUm|g}5dws#Fh~E7j*#$$1TO2yYrDA(IesZb$*&MF{_Pp+UonTfIa;4zB5xFP6}% z{FZz++SX>i$-#?#H3a zU_Ki-@EvuIeVJC$bAwgp7ju-)G1ZUmiW^AAj|0az?F$SDDvG}rgF8|Vu>asmF=PS^G}JV zv+2*ZpUW-QpKsSFkfO@piuDF=y#k6}cJNg_fyV37r69T!bR-{8C-m6F!`eT zBu0C6g$r!Jn98nrM@}brh(_j6LZ(Re$Fu6Sg{HI}O16jncaJt+o`rfIrgG0Z8)0yD z{>HAqd>Wup)bhXl7d&47@KT@q&qwxJ@0B-nS<|@E?OK^@`je5ZTHT)wCU>$pynfAi zq64YXlZHViRI&2;%ufoLg!>L`!)OG9B0+yVbxihN`0jSQ%| z_3meWZ0^rp-xObg4W=i}p&% z0db{hw^@apKDQtNLF!Us*lYBjRo+>=M5wwvmoOdHE(>-FP+t5`44QEVk`Uq-L3s>>4hSFid zBK^_SKW{~te~FM*CS`ZqFQa)u!jv=YP4kn zlgZI)#MgFtZm0a$MuQpA7p`3_6}r`L%!9F)o}nW|woUom{mb#@7<#Dc8)$dBHUu78 zZy*+$)vVx3u`2ykxH?o|p;N+L@K$^L`gBA8qAFE7rQNE1|SbSoaT4;Q3@eT*w4SA-o|+_;5WyeE(*zS zf-|jcCB*riIa%?i?PVtd(F93pGM$F=iVoH!dZi|1l{ub7ub^*G(A~=txUlKTPEeH ztVFuDOgTKLbgqEr)71_4`lv?gP=VKgZ+lF}8@%zpabiMCLd=nC2kGSJNtu0Jj-xIDADhUi&&Y0LW!CvFW+fH&W& zcYuMa;O{)d60kHWU9>aYO%TIzJ{*upKFT#!lk%pxm`6^2cyxAbb9D^0itOy{iRMmJ zH4`&~&)+7aQ41lz>y^+6fy&~g9i4ZZ-1RQZ!Wtis=^iYzfvR-TRI^h%LIG@RFZEHu zZE|R{YX`Eu!&+dG8m=r!>%X2V9G&=t_jBhRD-P}PVLBjtvHi$e^X8~2tcFj zy;c(u0|e{Zy*6lQFkphzp3m%XWhsG9k)=XPcXp~)k`_C;794$z0Sj(_cmLc)&m8mEPu%q+Wz2Np`onZKmIAAwaOCw+ zEWyKm4DRXv7hemrpa-ZKf6SKO$`t@87f;bQyc^{TXqk};6jBVr%oPYP9AGA28^n!#o#3-{XMh>#;A%~ z$;-K6k@HN*ZjgBcQGESYOjzw|Oc>SOm;r7m=*f*OVHu~S`%1U9)_2j}H|;d%!Qzh= zUkzl>$E{Y`Nq;Gaw;jNx5Ih-yn;JPeD!t&Y2M{y8!Ks11gM_}W%p^(;)jLrm#31vz z)5&yPl1omhz+m-;>s%U9ZoO;UdUlz(6Ps*(oj_Eng0ItFI?K2U5?&b4T|F0 z;(IQ}tf>9`d^Y*H$9HgOr+Y1MqSU^F%XI`zi?6Ic|D9Cxg=#p>$I6?uLn5wX_1q)i zJvI&JH4Wz$O)F6U$6hl5Ir9}h^-aFqH1$Q}+|v@S+x24$X5#8lE}Kv|?whi%u^N1f zlGzc!!g8Dks@cc_ixkfYv6youK2f z+F^U2$F_Z(dmbXk)CauizvQ6-!w3ST#oF8^dSlt%M<`~qMaOzsgA|vWPiTeZf6~Q$ zk3Bt&lJt4AoK6R}$e`tYAf$XBs}D3RaHwNb=OFlX_!fxVxQ0?_y*^6P@Foy!Mtg-r z@*5!F2FON3uk=Uzl6X13NX6ALLj!5eVWmBZl5F3h%MpXiC<|N0w3l*BhTzotiC!Q3=3SAWCnRW6a+KgKJBMK|q4$j%{u2ZgR)f_frI)>jUwNb(F#i&Y|$>QX2gy zK|i$0$u!CJWNV7}aHE*DP#cd89UzN1Cs)c|$^@5tHLh04e&YavCIAi~u7=#zsJ#xh z-t{Q>86v$|Zn$W2R);HcQ?;)^c5S$@19M?*uSxWl_Xa;k5FiD~L?=Z4Xs?g6G#D+u zaxmCy*1qw=FbMw8>cUG+J7~KH3<8)s1^>H7?IHmv`NAw+QYSzOgn-zv#9uEqw{f+7 zE)&D5wV=@e9Z0?^GH5^ZdwgNS{Z)h^VT?;g|T==<_^AGWwxfX4ZS~8ZDbk;Ck50Ea5ki^;q8& z`E}=Vyn54BGW{gODb6jv&S(We#`V6l-&VD}_n=l!q#|&`L4DM5@o~VFks0HDrV(yH zQX%o3$vOJKlz||wa_2JiZENG52|}VrWRE1hBRSWSIr2LT&akd_u_lhI$BrihXI4WK z5zrp}-V@N_vh;nRmHU^w^fIBc6nd@g6HI5I<6_LPp6UFgv|h~< z^AgEKfM$-0W9o7(pBH^Qb*fz=?0l=6H;Vw^#^^ph(3W^TEJRwQGxZ@t6dg}2Le`9l z=OUfwB9M5ONbl&ljU(4_-+Kti_6m@>_5SLUlEhW?p9gI8l`(n8+2XKhm{8y~d_!R-bPW2RLVH9Vl?ZUH(a10ZwXYmy?j#FPhHx;x2-hzvq zvir8mYlsEN{si0D{TgR_<3KAH&-h<7TwU($Ncs#D^0B!N1dZF8ygeSv!}>oV0pg@a zAXnzNJzWKa6yen;J{R95gkA$e)US7UIjx*G{A=$RR3wFeOFlMIB9y*e%&VBqUhDoK z^ASk#PQ-PBNZ;~XzkvqMss87`z3AW3+xh(zxgyYJyQeIwKSuV)K~gr|%9I(CQqvPp zDxb_AfLE`$IDbc`->+M`(S0$T{@R~Fg=Imlz;y%wx%xzX& zyT2*#-%>w^aw4wD>TfUVch2jf5>CFlSP5l&8n^%TgWb4A#!mFxqu;9n%0BK7coHt% zEP@-bVyg?M?VuDts0+G0f~FINkFpfVMExR1vnEFAL)$+*GQAZs)KEk~fSAvN?h^h| z)1N5xMEl3UL2x^gC7YAIL(x-tdp83UsTeM2B8V$d%QI(fECs+ z`jy>s@D8+$`n_-w{|0_h(xkk3))O_VJB&`mO7E>?9z1Bgd9ZVJ*)Vo>HPdkJv>k7m zUnOqLS*N|c1DI0)g(qHdosOSUfl{+9GZGo=G;TPkxAj(M*HM*T@~^e(rylH zvv?ScnyphqvRlMg1MP4KVqc>9MT4kFRtS*Y`ltkr;PcPm)EhPMI)N*wST-m3H{gkZaH|3 zUm6{OH7bl`dTze;76JmoF%Dhs?J4zI*OH;S7EGf4OV>t$1Y0G!jKyEG0Wb(pfIXJ} zI@>qSLURLkhAXHw6oL%Hta<(=Sd;K}&WaERT~DfX<2JzjZkLd6A}f z9dP)Wc0(tg1OZ(gEkX9TJ2-^$FO=sw?G678`GLu&iqd~Z0M84!ps+)Uzw!S-JH^c# zCSl;*pv|@?gzTljX;>_PXyrDltoj1FKw;M`eWMG%8AAs=@4Sy~_$QD6<;mOkY#z%4 zTDZevXm&L~5rE0oduv$z$bh;EEx!F#(DB{^*lOJ#9j5?1zxU&QBh0PB0UGrCZKIos zfJ2zoY3zq2CnjQSQT(0_#v2nFr?F{de~IN46db73s@~)?eu?hy^+2yiywy-nxZmqQ z6VV0s4j^%c4L zKP&QNh|cZVLXvy3L(5=?bP!DZ{8GSo#1j+Z|9-?G2y1%~D0KP6D(WHuyOPsD9|z1h z|D?kpoqY^h)PMROzr{euAe~11=iY?Bx9H^QvCt>?gZBTwZ~9>GPTgt1{r$Kn`+{|J z@)W={eSCmTlG5tv{INw!@Bp>$X zp<(3Ce;jb06u7Hs)V~U#7hsv@9n&vU~d zn9O9jWdCkH9D869$lLtF_dYn;0~W9!xc~Vb;Gq6Env*O3S3Iyq2-Y%8fRgOYZ&$1j zr3Jf`_P0;MvIm%WOKCMV;0_v-AAMQeYGO8^Z&<9uPnLPXGb`{2i-K{1XzwV@M?wk^KoW z;F^D>@|u88FyqFN{SRm#xFrENxxLIMulPUVDDOzn!NrdBJ|1)wcat3zlZi_8(0C#c{D1rZRWmvev(6-!p!-JXlGZe9c z||-|k~s+i5Cru%(FrVN7!Ny} z$DV994ZRSE0OfqR$R~!Qod3cN;PZWXL~yV8CP5K{?4q?!1$>N1hBr6hoVbPB^zCzqojC&HsaEcq-`A z5zP$&>Uss!#?7zXKd89W>Gk*uyij_oYPrC^WV;m_OmBR@-~4@PAopc!1oiRn-QF2C ztU6o=mw@_YPt;fYp+R%k%N!4!su7_nFwOa3;|EYK-y+#HkQOja41QD!JfaKk=LF0n zN?uDYF6b}#HUHI;DkCMDq^iU<5Wiu^6^uGWHus~nZT4>+{rGnKVC1V8028_Mj?Lol zhOR-wZ&nIu!UYhAS#U8hkE`8#4){+EH*k6@83iYwej?eqdw2Z`ggmS_UC2_>mYkZE zV#Ot`sD0g+sGL|-WiWARo8*e1YtV5%Eq)E`7Y!k<$+2@3KaHElX7Tjka2}>-sGF_3 z?lCWNbT(;+z+=UbKK#rTnY$qUF#7KB)cna+TnmEhpACoBL ziFbt_bL>z{l<5u|p4#iQ$>GIxWra7an75D$Op=!K-QKC=c&dHw0oltY4h6pOx7*Wa z;V$dfIusA1*{)dMCGvA1GM;}I-S1J#W6#+M^2ifFp?TA|+1Z1DnU9n!O( zHl5qKwSE#ZLN8TP}{8tsQBQa z1?D_`_qD{aITw*(caD{E8uKMN&-=FUjz<$^)6&XN#nn`*(4@p+vi!8P0Ilu2+-K8Z z?{0_mTx6$HLHz`Ml=h&N$wGw{C=fpY@bu!}j6UGLO1e`0C1u@J-?vcBh}JyCjcCnT zp=oPBE4DYqrS)qq@g97ooNz(SC*Q46b$J8%^H%+SCsD!R5&()?)GJ)*IQB5fV6JH> z#4d|z1#l4zzpx|;M&C-ZBRp)@JM`N*ukv_+Yjmp)x*IP#?rFZ&T+%^h(m{Ove!Sg5 zO0E0Ob|D;94qAN!7jM#4w+3E_hwj@C8a8=Ml9*(dD%N}OvJdq+7M zwX*E)@3}iaM{kjXnSm3f9#fO~D)B1M2ZWc|`eV>2NQ%I1drvi?n@I&V`;tLd*^raB z{WuPTR%e9GF9;R4ZrGT(e>7NLr)FRL$lq!>7XTK^yDg@5jg#3WTupU*3MK|bU~^Sr zZzji@Umv5?mw+1>+<1qOA6 zB?=84th|C1I^NAORN`xw8tSBzs-3%-*q`6!2u(_H;mFzbF1^C&ByTG zbZ}1PWRx-aM9a10^C3-A!A_FYJGE<$g$I7NsKb3Q0tcMSSQ+|bu$M7xGZYbVZm&1G z&gkMYB5ZRaG88v^CwXqZ#d6677w}1-?vTn6V%#uGqlDDDz+JU9OYdmvESf<;UUVLs zkE|bdt@j^o@9K~+T~^y3HhC&j$`-y>+$nMirlDOXo^px!b?pq@x*#0w(ZNZ984T)U zg9C!sEr@&U$nmcv*CM`cMwN3=(eb;#k_=LcMcxLEVn9$xK>J&+OPja4uMvA50=LtI zkk%~b#uNTaNh5Gyo#~36Q`q_5S0;}3Z29ZJoOno>Z`&#y=bf-5iY>HfUG4B~_jYN{ z6P1iFPEu;3Wx|u2mj%ZR|7QsxPfhPPldz!5EJ8)I`qxqx5BoLL! zKOFg2PChy+o_ip>3 zwNy;J-TLve2s^h4v6biPeuHF=S3R4}f!2_1Sb*elkSrC`Aqo-~Po)mFF1sv7SC6j5 z&IxARCd|+>-IlsFIY^~VC^k28t9942`DS|`H2ZtuA98jDKJk?1O*?nK-s_{+l(w#F z8L%o2X=~U;TAF2q8))C%Te`j-zA?=drMf-Lgfw(TBt}wxz>}rDopy%UfX`#q0IDH; zn1FFbKbXPrXBOhTDfapt>LKXJ5#P8}M^@~;ESSf<7zBy}o&V~(`k4@s!}V3U;G6T( zS(k%*zwNc$%4yJ<`=os6FHyhAUjJ<4dvn2Ft?I$!6i+s$S-(%q4Moxazto zSsI#N^ZS<6ZmozBXMC>PO4#L!npS~z2jZAtOxpUK1OaXlRJrlnpkF;`a;k;x*o9|- zR-UF`;781X!olYJxm%AOIuiakyttPsedYle!_^TprGA^KuIahNqyz(~P=j%i20R3M z*yJ21p=auHd72grbKQ2nZRwCe<8rJJidUUYPVv^GjGWejRUaTvxM@(Txjk zt?MzL_2ZA4c>i`#0E)<^TeT%uza^(OlN3Vql|<0mo0Cu_;Emcoq8iAA>?NTWlPq4o ztBV&I3_lvSpb^}6XMn}_s4#2?f13fCWzZ~2i7hg4{k)p!j@Y(T@c>auTxqw3L<`sP zgIBr^ofJsK@UjXqa4;C@+wo#Q{aW_WdGHsQ`ztAo)u0Io8F2i4J_*7Bv` zR{4Z{o0qR^e(8BegW5i4h*F;LLuxJy$QidH0nnl4v4qU$-OwQxCP}7XH(zBf|7%Pl3)_LBfRsfT2M=1X=h3}X~ z<_;JKwl1)M<5D(wZbh`a?cj7Dz3%!hpqTd{KT*~$+&78$dM`6loXs}loWJ%)D-%5O z=w(6O$(nFVdjV78eqnd%W27YH%hPqr2V;s)AN#0waL=d@?=WS-mcrCWKjNbq_#r~V zUwoBbL};o%n)-4)(Z1-nU!rxC3y6^zi}75)C8Q1VpbWjTV)YGcbaOI{UfbpDg$0D- zQ`JJK+{oOPVtF8Z5tzkD7bDk$0mJo2@C(A`gDM4M7M+@y+=m~$drLEA%%Hf6DS1|k z#0_-GkGvYs6{kv&o$A*E!)t!R&BoL84wr$}AMUP(*PI5J{S8}>wLT@_yEg>}1V{Pb zkojTDHp@4P(OEaOqRk8pt{(M_FsJt}^~`hHy2|Bu0yFE{mNFj%z%5bMHzc}WVjx^i zGWZ;bArsH*Nxy9ld(vWa^7YvzJyt?Nd5d)p)-@Mq0{pyi1 zTQyeoB@OM;O6M%dTYL{55gNvjE3ERZFz2%SJTkSSm|D_)=;m=#F$>@)G$jJxAKP&^ zC-$P0N@&^T?zc7QoSru!i7S3|=GTy^6CC44zhWw_Ki{l8oU_BZkTeJ3KWzaChdJ(sB*w5rfsc1H zp~c`TYR|uU#)y*sRpx(Gvs=4fI!lK-FSs1$P(u6mpe=nh;*E^z<7X~I#$JojUW>iy za<%*(D=2(`aka{%yG{Z5Kbl3N1T@ufs(HUnsSf$ndwdPYG%ss4Q77xO37knh+U!xo zg<2KYmeD;#W<)z6pbROxw~+nM4hwK3SfzRqAp(-Z(*Zy56Kq0nkg$6G%JJ_U=~*G9 z`-bcXJO}u@*$gi2qqSg@qh+VK27vJSxq*OtEa#RMp@mS&FWL8d7^U^#hd*D!@+7>D zcHywBZ=1NBp+!IY3pCXbx?`tIJL2b%d)( zM=qAQ0`H|xJ)4`z+I(E-LpK(T9+v(|@42OHjZ@Zhu_}2KKmoFQtgTiz!ST#V>fc`U zdx2hmy_iI71w!FGQO8}v45yvZ%VXAWQ(?2u#mJZv9~KW+HMBaO?fG$k^kY^ibMU3( zwf&VB1N0{K;qZ6Q<&fv2d7TRHo!UfpUbci&CtEzAi&@1_y5oAwcP!Xt2FKc@)rvBj zvStb|npBs z({u(5zh2y_{*EVF#x00^loa>!ao`rgTqG=)V^lJZ@1#hAD1dA_7mj;!fb%mBsz+{s zc|!1TS1&PW;=ex9&gK&!%P6@3GvMcA_q{uZ98MHOd4#pO2&DE zH`ZKQnWwmniWt4^?9xq+)P0vuv}9i)tubJzL_t~wE#!e2QJE_vXX!?W?xT|Sbn7%V zLkw#t0#wKxruSuzt!*K!;RMyUOTQ;R#e<{eu+l-bwa$z&JQc(yydI`3T#e;q%Y`%~ zR+s{a!h?|{)X1m8#uiJ!b*lUM%Q)%VLG3ro@o1CIgAXtei*#@3?Io1yMxCOK&As&m+%6-dAgR6e!DF*hNo%92de$LFV z0Tgb?j9azlksU=FvW$14JfNzVe@(jMM`-_eyI(LJWVjYk9n$>{1Hjyp6nFQ(y<7R! z+LhMNn(q7qoao*Pw`zhSN}NoVB6?JDDrvsn!ybAixQrn-l#986UfA{*K}?qbdFAQ; z<{V_qsF3$XHLN(0Q;PjE_H_V}PIA6t|3^H8FU;UF4O)!$F2m^ySt2R5mB+y2aKMf5 z-dx9kC?_CLg7b@!!AryX4B7S4OCVB|{C|UP=HZ7fWKmTA7%;5t~ zwc><}OqgO48V-quaK@KjLKW9@O$D&T?4-D~M@cvMzlcgwi%i%HwmxUEnR6l?q1W{CTnBQW-DLeWyv@fnt zf^)Q5kGi#!w77_b_o@TF?%fQODHz|Q&4P2^2s8Y2|hA(*!{t;Y2!gl&JH1x9yi+%KE{V7L|F6#OZ)FlPYL{rSsF z=m5|N05C{Xe#*gP2=m4-S6`+4dt?C>dksG*Ki z67XozWNS>{3Ww(_a{5=ZekoIy+@E{dpWU_3s^t3GN+d1pGGYSh^b<;w0F~7?Ma}Tk zu^p>I&-C&B6U;Lq8We6#q@~y*QY*;fA()}I#JK(ns`0GXPtlw7^T@c&Lex++wFyGB7Y%ChJcYAJ=*;p$XIA`U?d$>Yn#tbVx9`-e4xiR44hzp2hLE1y zJ}MXG+H->(yGHlMBEP;>G*ymmL+Y~Vm=)zVA@|$9z8~|UGagXXs@`6max8S80Ijvj zySXj+$4mSx!SAN`0gW|KejauWNgjH9Cr>IWE?*zFeEf@=#BE*-M5}7uY3Mk!WgM{# z*8ps+8p_KWnJL-7aYbNwa72m`MUo_TIDPgTz`CP!v8v1WK&rNTM)B;_Mk{@^N4?v; z{zRg1lCfv9qs`Ks`r;{H*}TpA!;borb=|Ld>l4xFD@zHSdN;B%Ysf=ti`<*WR~wvb zW}T*%qAyqubWMl})Y8?g7;{&96B%6FWXa`wI0?7Ag^Q<3rCjM_2IzI^7m&U8=&3A|z2FOZukjv=JXL{j zdG>rmW_9hA_R*^4+OIh=Tq<62j38PjHTa@i8lE}1<&-QsSMouJy^~r5GJo-80E9Q> zWh27W$w{~o&Z(Sc5aKvrWX(E7fQIm!{a4XqG!;uv6Mpmpg6tLyIJEuNQRVRMu`JC? zw>TRfP5A!~xxcP9SP&$<^|rqA;k%zuELH(B(JV$(BLJOM&h3@NeE(~R>~8U(5)vor zLpv$rVKd9N6gzFrdZ_4~c2jlu*3EC^vNlhIYu1QI##$xIeP3R7d(~;G2$zHPW!^Yy$aq0?!h0v`J)Mq{}UHC!jak`I*af zVUu2?hn|zLf6~R+mY!yUbgg2Blmc$GkkfJjTEbsRJd*J#NF%jvD$_l_4Bl`1)H*qW zJs7W_l!wap8ro{>aqQuK8nVI(bhU^t7_G|{D0q8;KL2NeTCljb ziGPIU;!v#sY641uRmm#=DV{&xWh8QeoaF~brEF<^^oAFp=DEjPzjEIkkG28Z(;(QuQqvRSExuA=>clx<@g0wp zF@s5AW{C4@zU&M6a1oF3vAZNAn*x+v}b$>Smh!Ak(Tx=S}$FejNP~rjo#B--SoPfGdcnWZt4}tui_u=WsS9zODz=M zb0me(IZu(w{iM#Gb$XDiQQ$7pJ!=^NUdCYmTo5mmBmDLH9OR+G8A3)*&rDKSNPo$( zH|J*~_W++?Ih~*$AbG%r_v}V>>sPouqjZ^gVY~lX&jksHwAi}pwVRO&6BxivqnEiK z7NzQVsl|^xJg?)RK?~KxDbBk~%AETeiA>E^cvv>4e;3|g7$!0o{qPFP?R&xFU)8}e z)ejeR?(k}~$Wly_Qp~~%97Vd%;CC9DKDu*_=V@-g;+-Qf1jAvD0IYN6`S~nT&G6^{HYUv^(^fsIt+>-|j3|62- zvIxkm&)}HRVvcYvnWpi0JYDwXOmC7^#domL&-Tv}ZkrC+#pHQW0NNFuySw$;Fp3e9 zC6O+X6sL>6kS@VB{6ed|3cb+Ox-}LDT9=#~lBO!~3)tl3YW9`rEXvz{vc|+nLyz#B z-~+%de(Z#0xk}b@8S<}xwd4U8i^>1+J2%>3buY7VGh@rV$^G!K71YL$VD^t(8cN4 z|23~|Sv!nz2!FqmTiBgh0Bo7W?!zkLVp-|U)X~H$WV1rYO_X7KSX?Y;7$m198%mPt zcr}=jKV(3PX@WuMvIz_RFlTr|$*M7+w16`3z-B@7tWO!?0!b^)lX zz%J!uJ6Htm(_B$FpU5zNt`9k+nPE*UvfrcG6M1y@Xd0Fl*m<%0%_gJ(a^`Eg(ax7` znld@^9zl2-e!Z!l=27v;g5{mZtLs}(&G!f~J=q8XSmF}p?u)@@CZgdhZt=#Z|a2Ps`bG6%-k$8q6DAY6~Hw zf8vP}8uf2wn+UNnGAmg|YZMt7FqDQh!oIiGM>;hl8<)UIbJQH|b*Cl=O-Jpaz2W6 zD=iR{^15#cvnWTpCx#a>F4(F~CuBMmXlklP=Y|Zq={q(DTy}Z?;{`FgQr6})q0akp znc_MI_s^?SFfg|80OA>C<8H+mI?G=k`^DLY`mFCNz&rOCJ8cmb%!(~+`8|J z0y(c2y(Dy}m4tnP0E2wGHtI9t@Kx9Zg-(BP&966NSp}L$dQ%_YyrlIKIp!09WSwu) zf%oijL-pUkB4i_5yT2d>8(k#$`IC3@b;uY&&3RsjSUnYSF8~Z*0S!*toXGXbOIxiw z@eSYcc&&(b+WhJzjk=9dlN3^PE+Q_VBVQ1(zgn)%fx*GEfqL|hsA?*PAP8tuK#wA6 z(%_8K3t{U!1rk3h@{QB1)yd@>wR1OT`ae0;_i(MVpzgp|uI6cxNbK8`YE%i+F1uQs z)hVuFzL!hBGo+$Zys4NgJnNKv>$w~E_10>$@)KI*Us1S)G5LI+q{uq_=%BuLy4Alf z?vIL1-L55%emph0 zyVI)#9CdVuEw+dL6voWIic^UxjQfH+$%Jvhk(qEU`=19ExhI&1zcN02jP%E4u53QtGmp;R zQh5f68F4JS{xqqz-95)&6ca zOR{UlXsD#Q-Rjw~qNlvr#v0~vnX^AOX!tJQO_soMV^1DB)gF+W7+71OG}SOe-mR4c zLGhWyAlw9 zE@9XrMX)6&E@TJ#>9sFDLm#)#^CGaV%Zv6PS_6Kd>p24TI7Jh}@+L#NbQigZFr)1d z0_m(?+6HJ;L6$?sK`Jgz=KtbMuuJShd1?oh#sN$6ZDZXs*$4=I0TY*cLF`tXIpprv zmKm^vx}|g*YLsC4sDQPmr(MTjJr5Y49s$Y=zZ!+j_RZ<7FGOtt>0*&*_O3UW)5J-{00Q?#-X@>+~v`q$4xV3jh4NZ1=tnqeLQ#&edT>l!+1TZ{ z7a1nYzkfBkZFFq=Za)W(mj*|pa`|2BpUuljqB;)88a{uaD*(HZ(OdE+5GP!e!6~t( zzAJ@mR`7?&@UQi>Fg7GRL&A0dr*D(2IA`2Wq!Me-C$q2pkx@(s<<%cx1p^NcHh%4?)6Vk+#b_WHD6Y5GcX9VOw9Mxj zIDK<@*H1WdR8d&IlTRe7-CNDZs%>#Zv6CzRqxSK)bRbm(xb)7cKy9V&GILzI^U0Ne zXnH<>#jvO_eEr>8&}vN-YE&AF-R}qDbYRB#gK~f-a|HxJs85Y87Nlb`z`?1~{1&~Hd0>!*qGpf0(I#Y2uP)n|H?`Ss~_3i!Gq*s7PNSffKk>wQC5#rwHTW1tR(vy>;Y`+^QIzKE$ z4(zrnUPzKN{$iq``6D}~F4R>x+dNe9F6WaAR08v<@ZMxC)*wZ!V5NLpqv)k1NMl4D?y%;sS`P51J_C)WG+f|nmg`GB^ z(q$R2B|KG%Tv#!QWZN(exO}QzxvMdG_j*jch)h2E`swcxwWqeF6z)Y@u}pMk0)4Om zJG-j%q}MT`?oO!I3V$|whu^!2uIaAoc_)uIvg-4+&i90)w zJ<*Nx{6Sd$MDB<8?_GxO+#<`b3 zIJeXKD%ylNM=K9D>Vw9yRv}MN4~yi^{a#{Yt(Ixht?g$S^N~4se;I}p*6(JBj5F1G zQiP`vAQ0V6&*CVvo36X(wfXF+@Wb7$x$!vgF#|ePv;COGw2n6XqA0W=OFwDf(o;r; zDY-WzKZryz4inIafus)!tqEiuRN>;n8!TwGQ(n;=i{zpHWY-A*vpSwQcG&r9KGo7w zy^4gO*!GIHnalzD(o1)xlHzUa9{sWqL5>5MbF?-R5;U@S6ZLf&emH1D(yME*BgOIS z5tCPOTPf)eqtZ6ZK5nbZFE*hs_QFcM8mwNG&vy|C`=H9=72JB-K&MmxVH|I@d(9?+ zAmNQMoyHS=g1=~dhGf#q2xghRDsN9ib1C$hPM7iAcKBWAb&2)yL$lU$;(gwjN z{e0&Muiw#%t&6BgrDYdUhqG9S+%4i?u$H0i7<&e)ASXt#cGc40jM)kIwaV7n=6mQ= z-A5L+$WJ?wWo1jZq%)O~+Pc-mjoh)_^nLpsRZbqAyo23E65Uhx~N z?n~n7g-xZK^!b-(^4L?doxHwz?#^*{Mae>#V5tR|hLE4kn*~H}LmCDLVD?Y!^a0bG zL3$Ro`vIhOWvLg))#mJV@?ctPk&FTQp2BKe?&E{y%ypWV2u}+quF9s==gTLkn>-8h z;-~y!A);uh-|bG@rI5(Po{RT9j(=sUyJ3VDYCpn zyhWYbjGI;2iOfWTG9RPw8~7Ojc*%!qk1Us8%axb<8fQDjUF}#k!n2L+JBITcoa=}n zSbo_fS9SG3Jbv;%)K-fX6X>iZo5y`#fSa>lSxA+ieStQce;>9+t&V?3eC*(PB87CA7uN zJ|Q@S>2}vTQQN|9Y7*B@GM(~`F=Kq&Eh`{b1B@GDkzY33mrIJkZ3XZz_n zZwm*qrYQ=`U-xIrGcZY`n+~MJ9)rBd;b*ZsZj8VRLeJWSA(0OoEw)p`)Q9FJG|a zQMuz4YX#vgDK75}f(l10c_wFi=SK=lh>Y!OD>03L`lBGU)0mn_^gKAwi!I@lc_TCI zzB|Fy-5esloE;DDij;i|%ia#)SBL8oI14SSz4WvVSvcBJI$G&c?D?R#YV0qz@$vnL zO;Hnf`_|nCO8Oq~*#l~)<5$@L4XKHf?Ff$d+UkC?(UkQEZiQD{50m64isq)jXNTC2 zzU1r_sMK9g2(JqbN2W5FBOMjH>O+QnuN~Rt`rog;3B=FvzNexA0m1wg($vFo;d=R* zT-INuUqx9$Ow}&nc`>klKmDLX3H%*k_@MQiDGq1NMoC|p$X*z?D zYkGUgAH|?RH8_UW-)%PKb*a~SEvgB&8AGdzn+&p}@QLe1Ln=MbDHRNrI;Dsb^BzZ5V}5 zWNLE(@hpU$Gf=P#`g(UlUb|;Y_=cLW<2#1PL-_&1>m8t zcrCq4RNh`T+<$NfojO+C!b%!&yS1Whj?Xg0s9PH#wb;pvXj_8&KW!lq?C#H=I&z?0 zcs`1;#asY8c0h0$!z*pL3U(~8$nG3w$0U;P!5!?c7*2FwXsNu%mhHtXScRBVX4dJc zeE(9@CiRicO*N*}Vdb6lPW=Ix+!pvjYw4Gz?_if--ZYJ6)TeZ;x!QQ8B5hqWBW2X7 zNFW{c!D7Hqf`b+2L`*tonmNl$m;i%6uGVceO=A}`xgdxU(4Yk(qcgnb_87?I=W|7| zL677&c1WG1+i2zK*eC8R`EJq^|H@a*r+Zf!9{w_mEw{V;_TG)3az{Zd&STTzrN*(e zn%;NTeXxWM#c@<7hjd-Vqho5Z9*mX2o-5Vdo%7+M^>V4nYnpackJca0-7|9FE=4I5wT30D6SsWcVs-1dzosa|TuK5irPhi#;ia6B1(zoKG;<1U zC6jF314T`y*%S8T_t*~ze0eGNADt96$xu;4tvP-dP?P@;UFi0GW#tUf|6ikFdj9|S z)@c6=<)NsZlM_B3!PZ@1nSZqB{zCM4H+VyqNu{a-7^-g9Ky9ks1b|GCbCiWpv|;aP zkIh+JUmvPXF@);cbD-S*LryIP>8E9YGKSX0z{3EQ+xQowL2#cW=)Sm1!MlQa<9{`} z&QZmHs@TW3+I|Rp4`7}onR|Eff9HwJXE7V&dmcj2ts_E2k%2k8|HSWL69mbCvm0aA zoO{gp6@@wotXjhul@fmFk$wYt8F;RPNAks|D2EvD|6jlGt)PgAFAnbi#?A>OfCxka zz*hbi3GmSZ5u>!}`icH6P$Tr6#P)qHcg|bf7C2V-K&l`jT4oY zc}IY9-5q`4(CpbvY>8<>{gd4URI#8I)NuFOB=6|XTD-UtmRW)5ePV6Qr9hX(kc6}S z_%}cY47#+t;X4KRmIFC<)%QQ*_75PfNYD>I{v#|LUo!n}5sa8Cz_IDtDfN6*$MmWG ziEGC4IZp`X{g9B{tGCnS!1{gOf-cQ}*#`=3NJWUbp|*z*3zx*8xz{mB?!Ue{R5lJk zeF&i3w9xPJSrzIi#Gbf*QaL!aZ@gchD5&m)Hm>F6qIE9xl31*(O9{2#uc;n5R z+b2yLNG4L6$-b4DtsanLk~SkUYgVmo?OWS}_6+O09%ZdNzTR8OQQtn`SE2}?Orzd9 z!mG=@8<5$X+#`t%7e%;rH$4^Ca!bC0cL9#F5K$CjN@qjp5=_*p@=_D^^^e z`W)G+cr|0vmJp3tx}=YHM9x`#JoC#_@mZp!VnL_oULHztchzByW%s3soK6F&b8sJQ z(67bQ+|#e^d!38!D2ei#46toJ++)L_0*Vs4D%;t>uM2{{wy%P^34&lVDE<$Mu*lsw z{uur-FF+>)uAul>pr@1ZvK}_yHe1(dc*Cp;s{-35LN@EgcS{r8HeasB?jc^a;Rue* zk^Ed(9Mh)otEzK&?;a#jo zO!4L+K7-~TJ|<$bFClyc1us#P zUt$Tk#HaT)G2+YfwvIbQMgmXOkTX~Gfo5`F_m@;-ARQYMbMDd%b8Qd5piwE1pYgw# zdAuTVu%JI;#w_AZk(E&guKvdpcQl|O(0G)ts-o!3`R+m_PBat_Iu|XN8o!Pcs zS(<$Epxtq}FPu77$E-MeMz$ae7B_UK%2-^ub}NPHWtHn1A*#ptp%zh^0?Vyahvu7= zf~H2*5)I(Gs65I_ak%QjOq59z88Q{S@OeV;M=v5E-NQ2I0);AlTd=TQ3cJITg!Bb& z0@?*Y(u=3%pB(UnHkW*C)49(g61PUqac5yRUL4Nn$w`N&oy04x1y-fV^DJX@#g?TF z??XO|MpRIn5mWxuxp=F$lL?H8NmL2EB1fZVo_e;eb zKr^4UJ5$GWutXArxdLx)3gu%ncXod?Xzb5GjeQ>!NP)+d@-{9UrxOf33gXC_4{x{g z005lD$--Y(UcACexTrIYl)}{^>_NiSd6rjrNJE*c@rxpNC{jGlTlVNp%UI(T5A0p7 zGfad_vn-6;@&qWw**Ca2(_`cBpbcw|}b11w1JL(%%yEx4U}&kG1R>mljxhUugSxEw!X>lOB)MebEvfLf z-d}~jwBk2KM2@tK6J$&fW9%b}7W?sa)+2G2pcS{>A~VJ8uCPW`uo?cV&|0xLxw#rv z{ZO7cIO<+aQ>*duZj#A;2*JfGITg9jABz+F86HILB`5f>1w_1)?_2$?IEaOlj%$T# z1$}9TJ5g8T*`g;+M`TnpHY*%=aZtrZ*Jj$bw`I4aGH+J#6Lp>qzvgHWPjxx(Ys{PQ zFMC^VA!2MIp)gk={Mg6WZk!u^AE%WJV}5`1e}wBRjM zRjJ`j^s9B3twR2-cE2(!WZZGo2-)}BE;P}vW#rZeC;kG zKk_o1Xi;{TG%1&{;-0}~u+kexX@ANTak=w$SiBeS4obZA2*u0kZ!*?qLk!NKz?L91 z6V`VD5#!TKs?#TV#w8p@xT+B2=dd4F?RXTC#7!0A6?O&>d1{5b=^dRqQdO;eaI+8Z z-QpHe_d9-7OFtRNyMu;~So#LPeAbsTlpBy|x!J;_@N%H?FfkfWDpDkzqm5TEv3>cv z=Xzmn%s@Z*v&8GgkL;&egC28g$|Y=-KX4}I9<;%qqo{D;e5h(%L(cReM4lo>PD)_` zp|0dc;uDr@m1GQj#U=ll;-4>>8C62h97() z^b6;)4s*%7!Lrq=U!ERD{Q5=+7<2?q*x8v z8|-aNJnfWYxZ^ot4b(|P@{Y!{S~aY}jB=5zGNpaR_Dr4rLYBlzb_ANu%D5a{@8SsV zlo_`x3?#ed<#@-K&o#D278{}@=PnEj4sJRZU^j8XECukO8sXR`d2WMPJ1r69dt#wy ze1NFOa}F!Mu-6fJ&ad<%#6kz?ql-tzAC(q&2Z~aDNUPU$7`quR;ZYuW{n4Qvuf!%j zW$KLhv3oLuvf~--kGCIn92LUP@ga9h%>CRuZUB>h6y&q1w{k-5Mw=>#Xs8a)1bIDZVyeXDR5Cfbtyf_#{Q4kr#qx+ zbrLzip<)2SC(`i{LgMf5x)njdJA+emEn{4_;mUr8UuVL6F-34W3oG8N@F`y)98R@R+R^yC`k`&%XX zA9CWVL()*fDr^{lk|c160%QbVpfzFnJi-~h_R&ZTrAL-_a8RP1XHhB=n|7p)PCYP1 z_&@>-7Q;Hyp!_&@p;-$OLizJus4|E(i>J1Px#<9bnLEkD%cWz5xvFrvSGQLsPnY54 zuV=QU=DK<{y#`qjLHt7~3yJ~uFFk|#?SHBl@(^INy7kg~ZtzaWTxbKx`s>U4Y#)u2 zVeNNEMiwtvZM9m(ryQ^N8i>ZXaf}o(L`oJAdR)j>5-_p(H9khdEG3dqig@d;K``VLsT@O%fjmq|))Wn}>w1qM)nTF1{a=t*j=u9R+ShNN{ zNXZIAWcz0c02EH8Z$-3Z9%UvL)5@3!_Ode(#NEh(SEb6sOI9sQoP))jUgeIEZVX6p za>Y)nNct(*M}(M17KW+2h83m2-r~ADvkctt$^JM=w-kJ4tsF5*AniNw4zQyy$REpU z`KW=dDR>?#d%WZNtT4RYu0AM{uNEt}eb|w%zV}UOai==mjn4mCnO}c4Q8ir$ zwr$go#CSV^thb-<0;5#uD~b4P$Fo7`;|L9n&HRuPnIOMD;?eR$>~w)v2BKpijy8dP ztcQ|`Gqz{;VxI_E_G9#Sgb(hc>$rRuX|`H3K2FmZa*j|}9@#C$m)@%PM)gI{_eN&% zR>wIeXD_X#S~ji(Ty$m6Q)1vBUG(tlDc~PS=H4#u$n@YU`tXhPmfZ7)nz1h`e&BYu zJ!FY;`&{?hEM)_CB7`;nj*d}gZOjugPvR@#B;n9{bsYL_Rcp)57~4;}1(&taWaB*UZj ztI#nb*W!Jb_#%P-W9B<8+TR?`<8QT^e2R!9W%2uvjBU!^wuFefMR|Rb`E(OL?stv6 zp`qTlC9pTLePZp>am*zFXr^ zZ`hTCRpMDY>OZxrvd<+UnLEpJPWp{50JZ40PkZQ)EFjoFrXA}o{C(nO31bQ(vBDx>pyUCQcf?I<-Hr z+rhRAL+1@#CNKFlBs0(CK}d$OU`Ih|`D3bgH%ICqr&w;^LpKk|m~TR2go+?0=b2 z?3HV`fat`x1mB0ksj7D~hju?fkbl26{FJ<QO{6+j(6)$D>osL=j{-*nQl}U zQ?8DN{+WrYgh2%%8nz-f$<|mN}8a#^WtY;rof}lQftfF;xe0S_T{{CMUENIN+Q2KhgE%-lf?De#vN^!9@^}QdsoZ!wsEyP`O*Qd0bX?VMd(&Gn-T95cJ=rp zK}wwZGQrfE5jlOBe=M$$KRW9mc{wC6mEeVRsf9ClnHZ= ztXpJ|GXOQ13d*Mp0uVvzm~&%I=EcyHgM($(Mm8UvZ{Pc>uJR7nGJt&Moqi>rM;Pb< zxOeEhy?MjV9Ct^qov-rY(OG6s)471uIT-%h9_v_miSD39ceqs=EDkphe^Ax8mFime z59^QRY@EB*oJIXPYP|}iPs?@5$tM!<-G!$0YHYN8Iiunh#z#&4{EpMEDX5O2!o&p+ zoVkaj)(PZtScW&R0$ll?Ngwk0tYCQYA+8Jyfk~-QWI{Y#G}iTk$D+DHVjn%pdux~uWZgHC&vf}gKPYR9uWV62QijpQG!fWr5ag; zf1fDUeVwH(NCrN2(P4l8le|a&g_X%)^qh{olMS8qT81`_evdXk8s6Vi#Zu3AJBl-GW|VY%cj)IPd*1mbTbK8dEd zh7)GLQX3*Wva{f?nZy2Fikh-AQ>lNr$oq*8LX0E>2Hf45Yge+pe4bLcm=Y zY#g^3X)3IxgYPslRr}*WRB36R^;T;rwLl%z8+ZkB++Mb0Bf_W?4_gt(j0;PCa?D%+ zQ}rmHg&n~zXxyLwQT$;{!Zq`qy?wWx;4M6IYO9+>o-^z3!hg_@*;@E5Z8(<{*{*P` z8S;-6JXHMgh6K#iYZUv#@6J=c9d}{r!tcDn*LXj2?9eh%5iSz&puQ?8C?+Y$yve96 zxzhM5IWjefmqg2yu)nvGb*J+&jv)=jE5xS-L}T+Db=v*D(V}|7YVPDQ%b+cP4a0Jx z8YnC0VFT8td@WG#*xG*MjYA%HeZ9_izfH`>rI5GgNa<#Gl!3#jI`EZIq_L`lRto=v zx37+>vfJKOIu$`eq?A+|q?JudgLH>Gw*IaYW`ON33ki= z8!7GAjkNsfe4~)*~ z4MEe{WH^B6-T2M*#lNoB>>!3Uy83fXo2J-MA@RM$c>Bs;xrg&T9Hp3pv9YNxL)7Au z`fJ-_DWpNYgv^ua9~~2-N~a)EKFtXX!Zz{J;BQmC^r6T)DD=8I;D~S@7+h-IRJX^MJaiIoU|pZ6u~x z``KL~k0Q+{YIg$Byni*DwXT$>u=ph^|MLjh8mSa zjyK1@bs0iFeE5T|bCdzhi;SgOe`!*$p{pB0A4F3>L-QG-a!x(BP^QAzPf|t2@`l6qb!-}<@Ra@6EE)vRsi^eB0Ssbl?}oUC6r;njnD2E zPMQN=3C-+~GjC=Ptph@IR#sO)T9Yz^L-bPO4j7u$lbe^f(7+wwNxUifh|qbCLE@{^ zCmQrcd)3Xhv{uvRh)y~c=;$-Aqh|N*g|q$Rooh9{O_PR_T*D3tsZ1wBt+Bfj2CyuVIxhREuXXCBQd z_82`Fu?z&gzn=+;l;5xBnW~7y5u+x(G8JSsO!K3=(+gjWExL#~;3T4K4{_nc8|k8! z#RFr8_=v>~`A=x=_kW^sJkfalaGs}VVx+(UJbCe$T5CHP%M$keA4^hiNf%Qz)>oXT ziJWUTGS^}Gnur`!sktc66{g(*Pc`<8i?g2@1J3hn61q)F!?C+NO2=<#>1<4=!cv$K z(+Ww|=O0~y8+paNiWhFWch+T?A~7v~>9~Lhw1DyBWq|b0E;sZ=o~!j$6nevn0&)_v z)D^Zzs?ak;ata8H*U#m8X<~Ek6%AHCguboOv8!~6wa)YSr1w79&PFI?G@45#G&a#T z1B9TMNOfF;e$lK{dFRiwb_Wfp>bA!|1e&a5r!ba@&x#S25-x}1e{S-QZvY*0H5nmC zH?Z2iyP0T1yNc%t3RYz!%})i<(~^S^Qullh-d}(m8`;$W=7D>`ZmkwipswDuwwiUb zI)XV6MD)k(uM6<*Lwd{@WdxCin94x}B!@{fY@`&c?p?ePb>2Jgcq_k?o7JS3R=F8< zB}f&fK3&xRU}E+)T_<|y5CIUJ+X=}c1Nxm7WTmg-48}UT7E+McxMpFJplg(RfV@F%?$gFZ@cRy+(9&W(S>LZ)r$ZV3Bwx6BEB~ z2Mqv~1ea-|f0VCS8O`johLMgo0Y$Hdy5$2Ch;$6i`eT)%!iy1tfIhO5D3jGn7M0BF#lJn6HV|d^v z(omViv;Lt=5#)2g$5b5ZEeNAu&~|>pGKA$o&QMdszEFcQ70)mevOzNMc;+|qJ`3Xf zHlasN>5AkkP^kAK4;+IRTwLpGm@JQzIM5hu;uaIzJ`-LyDQTH`-g*C_5N5N^W0T(l zeH5NYrcI|l%1|YtrU-s9Hipi_cZN6GizaBk%z0cC5|D*lx~G3q7h2=jhTO!&?q`;r zimIkEH>a-ZVH$@Prb1~G>&;PFueoA4%yB8dHHk|(NMEK(-0ou(5Q^ryzuMmkY~JV} zo5NF#*oWkBb|__0Jr$E_!f96N@%(jT^`Nuc&qvT(v?nRwud<)+H!Ih72&UZmGjhqR z1^u@i>znIf$R$+WA&ZOt@jbBk693SEaeaspV_3d+&{7^DD84%pS}8Ksm||lUq~5aB z%<|opg^IC#AYl_GiPO1+;(u|g&TjFu?@)(cR0OU|Ot>!H9p5#W+{?aus_+1)x? zWt9c>uql;i8f>0F0ERocKc+Vuh`oT;{Xt*TI> z0cTdlly;T9x12tEA2&eBVQ--3VW4M`P7tb=LSe)1Jz9=2Sm!Az77IR&KD2VeY^NbZ zx%^&teCaP6#tsD}C^zcF!6zRn;2@)vaDW$<_yzK=elP~0ZUo=~@RzS2p}K5_liKS` zY?&E**QRU2=A>qdQ5`Mu9nCl9r0b=8)ZT! z)l~9;_4jv>s~3`&*c;q)HQ9qiX1yu)=!Kj*E;T3202dr1@n1ax|03f)0eFo{Ni#-} ztMYWCUv(&5D=nfiFQCHRGiQ+Nz&1*)I{U_Ct#HQ6iySI+PiOEL$nw-5|bn`}#YK)2bClO4~xr!)zx+18_iauu>y>TX=~$A zc?3oIUdQQmfO)soXOAAY&de1|;~Ki}PxnWw-k(u7EW$uy@Ig!gQvu<1{1`_#Bmz3Gs;>X3*H}=W)RsTrq)vnC?4z+GOic|wf zG@9#rhkefXulO$%AFatMG~MI^x3$RbD(;$nn}>yftd? zk)KCi>VbXs?c`oe493TRb(a{YDv+eDPWA8xZ%7Ak_*aPuEbjTGx&fNKD3Ag#MFv_K zM}MfUXmO>bG2x~#uH0l)j!3fdy@p>vh_P3GLjpeHq`jWiQx%alX3hE*vSXB^i*tLl zi!tEVw=Gq%s=gPIfAYPTndUzLV+k|#-a4Mc_zi+}+u-I6#G>1bM$l7pn+=28TH4RK zlcxyo{lO`5g3E*B9fH5e(MW`ufzQw!UY$XkNTWiACNk>EUx=b|@W_f#HngV(7DR=v zy}+)HKPJ`|>pNOw6!cM)7%^rQLavRbS|mS8MCCd6PO-;B3lJd)xWc1YC1GgWdv&QwHDqUOPx`^gJ3)CbX zH2WT(cMPe{Z*cOz1(SZ@K7L%*Wgcv}9c+hE-g#~Z;hbI^)@kwao{~CLwMp`nv7(vD zcsaT7`k3^l`88BsBz-m@cWA{8{#xfMFIB#MZKi{;SaO3z;KNoUu|27W)#&%29wbE` zf}ApSVj{wE{`G=IJy)MG!%@H&{$TALDHpE}nnGr7B@Yk3SygMu#}Zqch+xPw$&Ud- znCA1Vt=oba*9NSlR%z~5@QiB|g_m+M2bPV?^UqDCO}BhSIt7()LRsKFmRAdUKD{63 zo9%=|dBwdsXz2WfG!R=fLs&TY{>37y3hFl?8z&-w9(lkG9u-OIcj;ml8^Q0k7ik4& zyF?g1D*EqQ86(xdI^I^_7*--r}k?xOxZgC(8IgF~7&0@KPBAS#&Qwzki5aU6WV zC81fXtQJuv$j?nd65z#grvu}&o1aruXh2J3b zeC(&fCpQ=30=}*4mR=L9`q@ofhbxnL?bwA#tnGdpp@^97{Bb32RTyU@i5z<BWSmZs{Uj8a(CYk-eeKDX0<6Cb(g9Q=V$L*M3$HxPi8#T>M(RTQdyBs@Ffge z$HQMAXY%dS@IxR(@W5omHmJ`Cn$xt-$MQ(6W7fccgJbGg^nT(&{;%0}<&xtOPSz5J z)u6cR$w{9qyu+{ua7@2QusP$fT-dZ6p^0kt+kPgs7m3HEZfrgtFj4c@C=8fXBX*BKR3g>>gh8!rB?j`wE-&FTuB<`Ywc$-=%5cg%USSrJn58)BCf|9} z{8K@L4^&{CU!GZ~TY^?;G)237g~vduERpJ!FJBa04uo#kwSpkuc)~zd1x@U$UZ*bdjLHRuIve zzRoCEdd%PTGnH7U51OLXwHIKBj(3cgAa}*%jk;B{lBRFBfyTYB)riywWVR2+F-G7l zlWp4>%AePhOLx9u)$DhKrIgjyJx67EJkzKqOW8T-)cYtf;aC?YVNvzF&bm4irN{Tl zKM5r~!7&2rEgJUS%+=F;Yp{CaN0I15lPV2VihkeekVHGcB9g8i?=ljLI{p@h@z|Tt z$43T;EVzH_W9!_Q;+x!pHn=!P@&{!uEE889@5pv7qd(J>vwA7Ll`{9&CsI@Vw})b6 z%-hWhNM5IoY=*>fdX=j_c5&mQDm&M&MF?bh9d<4tTP$C!Z6GX4w+d-$et+aoMY361 ziS?3rzH5;x%wpMBKo&NWAIf>yJ2$9%bgJ46`J|iiJHz>%k?kDJL2#z)aq-OR{VpRDPjz-Ebz~PIVe2wBi!##82urRl(4m$HsCw6s+ zA}!2d#I371zqi+5KpP>$-2<)r!YB|LsJfW*y?*vZaNNncen$%i#^oZ!I9YQk4Lz+^ zmL8#4j7gTEE3gPG^v*!pPLvERtD&lBe(aHxv$PNTPSqxfPKd;E#OZAo-WzgnOP?!N z^bZlL_K-!EwS6kIr=jF&BHbkF^Lo8oY>sJsU|0u2eRBPcKe%;G^il4GB@98I1G6Mu z8?eUVJ7F!~Zh7u&V;T=HoK~D;q*QH~aD=q&c8iiy@;KSL(^eV~*4T18BRkQ$>Y!K8 zFva{tlv8O!!6J}!=^Nj*Deu86q$=&aMu6VEC@`pabhG? z8i(@42c3z&FOj+<=CrOPMC(WiJ(?V}?*b!|Ut$*c2mYf4rg!~@xaiZR7EB6 znKL8HidFine_43-^&1@eL5M4gbPJygS!lOoyjR`Whpm)NGx78iEEN%?vxXV~MhgMXiWI!Vs@vA_E5XVCdO>CH=|#IM=Q zJhv>#YPcS(wK!gPAge;dwMy+RmW7HS+{2MOu{C3>$-n>{Z3(`$Dn{;y+nS_I7|7d`Lo{WR3ss1fGmA6B!^P1ug4pw zM~bYex%6v)YPXI}>f^!HK62F>!#4v{5npXxJX4r=bkDvXnt7zDz74}i@_zTW+pVgu z!5sPfQJ$oC;`>ufGnP!l-RX#csSGO1q`WHNq&jXi^a?dWYw zWi{AVGWG{e9l3@kmq7?ymTosWu@55nYHz3!xHcXv4(dC&C1;?XFuMKB=?;}#j@f%c zLpb>hs!-VT__6oji!N-{id9pM zj;6lw-%b2;eZ(aLsukMzKKuYw(f&Yr=z8&sC4w!AFR5=l!o>_TXS`QupZ3Q{{k|qr zxV#6**Q++@tLXj}K1rBjakN0)Ri#ZMA6RiBEHr;~Q7xKchAD)^U(LqQHsm_M!uZpI zVWy1%8aD?RcGdOY7o@%I8NXu|7O3q2FZTE;=`h4d@lZFSsK^(tLTS7k@l`7XC9KTm zhJ^tq9o+2RipW$UrfPHtFfOSG0EHSW+Bk@zuc&a(mKtVuBF9I2T~Vfm71<8W+->-y z>v15xc5U$sWsJ&vw>S|E@tgi;d4KA8E#r7@J@zA8U$47Rw=lEy$7icK&uXjEGFQh* zJ(h?5K<5r*n@!EKH$vV`-%~$*?08ygJP2wBX5r}9s%#vHQ6CD}hQpuaXn;$a5k|GY z;m?ZI6t{y;y4#Hgj$)Xwxx>z*+s#Xv?@)Y^EjH0#+R+d+_x)P zhWRDYyR_Ys_T)ZYCD=Uky)IW1lE*ogo@Q)yCX2)77?Z9Nr1%kixBU+xuD{g+=ZQfp zLz$%kCb%w7;Q=bm6fiFtpA}MD&NsE={maLm%`~dE&?7$a;2ZU1ZTs?{CK-Oqyq{H( zo$loatv`RlS#U#4fRfHInDK|~qJyr}@Kzpxl6^<3ss^+@%Qcw;2mrA|ni?^*fZ5YQ zo?947c(sAK%U9|oZ3Ve=EsegkF+`r~fX!}LdD+nIterd0OWQc;E5&;tARPAG4jOwq z@%^@uw%a4aO<36pn*~d5aW84E@xVIl2$@!s`#oP@6Tr*||0PrUFLh97AP(tBd)mV~;ogho%{nk$(u-z>Gu`y0OD$JTEj$bnM-sco9?4E)TzU?%C+r!0Sg3W}50 z#6kIJn<@nL95>>(qv-V8!V@r;Z%CJX@jRuP)1jO($eUdU))lxLFzOqIY5fK%T5%hN zMJkvZdzjaSd;=#y0~asnJs3()>eC0l&qqJI2M~|%8gx7B?=kt-M+^5*&a&7%#TB*A zq^uB`YN?CNfLP}$_41hNeR+PkVN{AVl&YS3Z9tTR&XBMHOrzeFu)FAa5JZC}Ma)&N z1PbC|AuLXTQ*2CMo(NRr@zs_r$BQL!b*O zu^&EshNNq}v8;(XBz}Lg;N3}V{W#wD9jdlHkFfWM3&a)w<_|PbaxxLvFO5Sd^QvRInLZB5RT?mNC zSRdg}LwjQf+=YIfn>b2FpJK>d@^3B(1Fr!4T6bKbHz0L%G*u5zopQ0`uv^q-s4p?g z-SM%hPAg!|okdqP6^UL0Q8+-`Al^cs|Lv3GGQz^(7vTe}RMDu&#Z6ebhsLZDmLlbbnaZU% z@37tX1HoS>2 z1Z8*o>jv2-oyTU^smU~1)PPlq>UQ?k_&UG4!1L)|1wXW41~yV55hWk@=6d|)V~^W~ zp|?WaSHa3Dv4oBt-K$#eReyr!>ut6Jac5dQ6tQ)bu|=U?4#ChL07M>TpxIRtW~^w~_vuc7Ma-<% zkI*^#qD?NrV~T#Y`)}##j5t`x=oU|-0QD#t{o`6Sxvgn^Px(ABk+1FUH`T<^+S9tL{=OT&V9FW z%OH2hCSsm*(GhWK=9+BLu~b)UUWjIT;ACM|aN<^@YXHO(UiSTpZ^~S)Yy3>f z`YstdB4owFRpN#_(-o*gO$962l9GAea8yI$0SZ%;+M{&_WW4sZzE=3YVln5lcK(@& zq%IwPa-U8G+v@zvB<6?4G6io`nczTQPnf8Vg~3RYI6}V+hbX>_ zs|9&=wHF-S&%Uu3<6y2vufqaSdX455=FeqHm3(z{WatH%RX^ zQfKzt>^k{#`x?l(DeFFc#cdsyymk@}Y0JQl&s8W}My~GA9p0}AjI;Z%dlJRhzEoG8 z&UVtjY`+t^teXqzQ2KQiR^V;cJ?Pf|SlL(sqY>~z$y)?AtKu<%<@4k9wb06hAbuKj z6S6|EhnuWw^|G0Vy5GmCc@qg%s}#J|pDis#o&b3x3MsKKREWhNMDT(;zB>optfqk0 zTaV4njtA+M^vVF^E#GByg2vjoN7x_AHQeD3>xXK`7q#K_^*2?QJ#j7ZL}Xnf8lbZE z=XxrsPt|L(fPF;&bI}cC+%Vf!)U4uf)efJTE83Q^7uIym~M9|g&QLL2Wd zj9WKEx<-yWalA)#dC&B^yY&gf6#LRekVDxW3~yQ|=(n$a1tmoR@fw*3$0ub|BAPKI z7=8o-<5}ylmhq0=XT-^zz057VQSo{OfP&ec?@jwbXI*;aM4^bLOf!@Gfm|{UmbVl` zQ7tyvJLHW3oe4w1CAC#@>#@(m_WEK&^ghF*0YXFcokWNflwKNk>T>49-p)J8?o3j* z5a!;-&smCyk|}4mcE>>uE&}wSZJYFR9VU3NJaRKoY^V0?j&t>4#aWx$cH;?^TJ~?V)Z?|tsEk#?@HSH z7?EY5t64;A5h2klMCb_cIOBKU_n+*0SZRIlr|XIgPat*=xO!)c3F)9d>B z!B}Jks(W>UhR{~jsPOWRlv6*q;$uwrt%bJw2M;4V`&9 z*6?oKrC>KWF*xxusb@2}6TiHv3+_lYv`D9Am zBBC(ZEBPv|6Lj6ZwV<4ehR~EKbsBG2l)GsOXfExyZN$*z?W zH-_QXGjSCLz_CX0g-@>|*L`9H!!!MNmlf~?+xCR2#~~HeoA`%vsRk?9=^0_QcVaFo zgHg4uA*0^pEaLVAfN9AImtd2jlp3T9^Y~8{GnGI;igL;HTH0g(R9@fH)$l7GYS*@) z4F-nC_odLzlf`R;x6*R#XyK8j9J9;#%OU!BHs>(OmuXun1OsSfxl}9qV>~wF$C{_n01Z zree_w-FX7&$cbmyZQ~zSMxhcDC2l3EvoTn1A52T!c}J>r{%lh!7pl4pi2GeP?KRFm@i zIHL}ijzKU+y;TPxY5I9q-y6%(_Q0+wpl4zzEH{B@^~)H=Z!uf3aF{g06);94kXHj;wTN__E_-z{_Rx$ z#^6|8`^cdAQOo9}7BYlO#BWX|n`X*<|AltBqV~G0;r5u2-`>+lzm>@I;e$UAO{R4m zZr4D9njn0>qU#1GJEqZ8Xem}>>^I8k?0Zk{p>u9kAoeL%@$3h|59Q1O=8t=35hLYW9`GnCFhGCOhqkqz6CEu8+`8BqqsY0VqUxR@^4 z;fT2n{q~3m^q*BnSE)LE6WNjMHNmV;x_g90ju$DIIGP};1BDZ|z-JjGR8_S@8cAtc zRf{L}J{3euFofr#K0iK? zgTiJG3_SkK)aSou3RQJ;2~!otAJBmPDZKIJ8l64To-Fv4-f>E$+?Z;P(||r{dH^F* zeTX2s()gQL*j?Y5d8Y4|rm#?p4%d6@cN{+}Od{D%Y7H!#X3pMxFb2~kq+wrRJbn4 zlGK}D8r!Y#nisd`B*K%e=2MNryOw9ERQWyI#xAZDNPfK@>%ErlG*&{JZ(~(jin^qs zz+@y)7R<75r89Ifz)j%&!zDG6l-t?$J!C%Y^eNl|%EfQvwKu7U=mW$?M5O=BK;`8O zXs3S0IWM+U4be*S&D3<%e5mhNEM=S$*8kM;eN4QJwzN4+>2_Y<*n-KFOD^QIq*hp| zVL8F74(H3~=v${Fpw)1@T`WCj9~^VAFEReK_pFyf?AcZLf}l-@khSGQansZ$HfNuN0!wEFmM(_=Y@V5;`PKf}h@fY$?1WozNMl?k z%I#?p7CxN6nQ*c|^VgXqt2S(5?l7l+dv#( z%z{+0H988z1t_<@=JA+XyuaQH6n+5uMp#{^;UA}P= zPEO~(qitVNg9ukCj|iTcID6y!=vm?Z&!zan9qLQouRkzzMZE9u*68SEE2gEoxLd3j zwkqotH5JR(1ht1*+_?SZrehf~ZwI3QIL3__Lp<<406(f0Q|UCyPc5Y?)dZW}U7Qgw zXaJD#Ik8>6IUO;4>qmf^YkNut`jFaQ^^Zm8>a19ck!{LWUa|MinBfUkdM4#VZt5uJRNU&T&3>VnALp8GbN$ zmA!6@%;RZ;adFg6?F-(6&MadXfTT(HhoO%)a7w%bwIIg_Jc*zIVGAwdJ%ABef5!Zz z0P;2#!ub7F*MWIk^cahcliJR+_bgIFAT;&B)K6mSE{0-NtP zF_ATBh!jJ&i&nf`+WgtBRQL~^r%JsP(*MSr zN|?EV10@)j>KK@zD!MpB%GUR%AJiWFVXR9SJz7xZ_>V@Be~^5>{6~u`V7384D9yv> zGw)xQ>ZQLMS;1reC%T-+ASWVhuC=>vipQ`vcvJMQgvU0UUg96(BW*Clf2+r$xttC< z(ZoLUOfNH}4c9`i^jBq>J-rXM&sDsCP|Krfqz38HY|LotV$r{oe&}Jm1tX+*n)!!b z4$ULA2E)XqoFMVE#iadjw8;Pow)j%A{i6%1#NY=`Pnnl1Q-8A~{6mlcO$7~}2{@Fq%*t4iLq*g#Uesnt^`0AK?7I zzDC6*3H;-f1R7&jPe9pm38ngn%nATKD=Yv_)|$EJo9~N%+(bYA|DOfq1z@P5#Uv0* za!?xQZNMRIt~-sUPx1{JMZ2jCD=@j7a=6pifUSFg{&on<)#S~;2?>SK2vdvU6{Fjv z?~P7kSs?%)F(ThqId$-CArSXk$$M(_B3FXMZ`tyi*>oV*z`($@!oaV0Tpxhv{_S!W zy1?|ni2SQY8URmI%wy|xw6@rnIW!-X_b6KJ2efe8wgmPNb3it10ZQ^OBB(`>U8dpA z@kMi|qua_m^Pciw?!s7LmmD8P&69v$M=e&vUIgS*{0_4`l2`&B$NPFI+hc~Mp$$X5sh2+S@Yq9Ly`enCdq($`7Jk%;N3`6?G3$rP@_6R z*BP#>&lSP&MC*wIV38w6ei77y(q>*5z1H-IQ-x*rqHbS14CgN;NdpD-9%dnbo}c01 zCq{!T`xUC|rQGrpHr^iVsr*7tr)uJe_XjwsV+7F%LL6|s3F}F?b+Q7->-TTRTg|xe zt%F^Giccx1J94=$1{D}`Tgh?N&uIVi+aI5+Xk)%!S(SoriG{xCWQyb2j$kiDwf{0N zr`6Q{p?Osn`jGtD0H_lZp+Eg4!_QV4;0>l8|E(ENN_!RJk;n8@J|63AzG(VH;^#$Eai=ju-R_g`>o7C?Hq$1KQuRJC{1%xsXIjod_q0O)cbEW8dz zmaiJ{2+!Y+?>K#|+iAqVas^|aVZp(Y`j-vaYtPUUqC}Y|wX&~p+Eq2!zEwT6P8ruG znkd>%q`?uUL|DvA63w|YiLyX<<%(AI8nd(JqpUPJWHphxUwYqhM_bQ-t)&}u`c@=< z_j{coIgY(`9g6Lyo0A~nowecsRmW*^5TCQg<@KSy^k5=8Uc~wm{9k;8S8to-Vwoi7iD2!_^c=mGz zQxqnx;H)T0DKZ|}C|G}U&$lhQw2e=Rp3hAVI#n@`OROoqZvp-Q@6x8cZKF;tUpK^L zENGiZn!ZoA^y=HEkBz9cg7oU3Z1Ih7FUQ~RECn%&J47-a&0Td#i=ZjZlnFf_OCWAo z!P~uTL$CmD?jerVz|}xHJS^!gPnN7EYXhES)iZ-k{Jt@sI-9R|Y_)$Zadb+#_81zQBr7YOO@_d2z=C1Rb4w$ z+lVjjdixSE{Ct;jEN|_uo14^x4Zi*jO7P!>fMEo5(*L@11;}=SHdRvmt(Ov*Sm*fR z>&lOX=xW>oPGdJ(MWU{~eue#RE%-F(NG-sWZ`Lrfmebz23Nc(G^4&XAkvG=aq3V=; zBSQ6AUVc%a4o@sT=zV)Nl5oMIEtQMF7PY9h*gMOrBflN|$n}ARX#Z%52Ol;cATJNf z5z_@in%YyZ;;EGY6*;336WT8_fsHdPae4579bFc}W`>DHeP@AnFgxL;r?fHq3aoa- zP}mZ8=vv5QoADo06Clr>K@C^|FB zjHuP5Z6yYwx=y!_8Djj5;|}DOXERfU>Z4`BS#jK3Z9kGjF`!YCkAd#ve-(~J4cpNNG_@1iAot;VudLJDIwo%+bQHiMcz5b1F%sq#D zw`{Vo1fuxq;G>4F+Is=*JSuCSWH0viQ@?Lqk=Jm!&}=DJ3_RXs3soFJiHEC4Xk+H- zvF{CvV>I<9-sH6~d9g~)YIg<{*mO*p5f)CVjhdkOzsi>gIMF|uarF&{P_Un+Tbg5O zfRsrjNt3jhDb{)5z7b0nB(LU!Ln&=P4Ik90vQ0ufjUf-yDx#=357sdi7?DWT4jx<@ z0dMjua`6a5tvOJ#a8LQW(mK@3o&01$EPg7!3n1iCrl()r6Rz|h z)_xJWjb*^PKxpG}PZAssD;nJlkLs!6+RNA9d3DX)g|(<&_aM|!WqF9RVUuwm0Fm?= zt-MoO_0zUTpG&W|iG%Hj5y#J8<~BC-6Xw==lL^tT#NVcKbLAB-ZjSEotN~P+JMe~2 z`4VKsfW8R?sk0y^-4cH#%%gTi^3C|r-(oK`ffC-^e5UpXt544C7c5aKqU7Cm6k9o| zbkt|8#4Atg2`rGjVh_Iot%SYBnaG=NcUcjOH>OIV;FiURIltiex8;cPr8kN#Mxde4T2d)hWb7$Vhz!RN) zMIfE-8?>Ux4z4U180*^<=TTlfP9hBwNstOZXGO2l$n44xN6&M6){heNsZyuh@C&_i z#hePG$*97M#CMC20ris*hF_39QfYRXhm`{A$)f75j1qg*mLJ)>M~|HRxyuK%EYmU$ zT@?Y`WF7>9$FvtM4RV9G9yVLl$$8MSr}<(AlH;9ZE$R&^0Vm5IP}Z8L!`kl*wSh|& z4MHs4394PjW@Of18W=!{SfXuYhYOSIr26vA0laciSjEDffAats&ADZ#)-e70cPoU& zbD>1egU%_H&q>fn10jK|;E=ltW*kHQ=6W316eUs9A7>v-7{8{?z4QL=`?!bl@EfQiyRO9za0TsxXxj}k0Jm|8fS}}uR`D=?A-c#*< zr;6pm5@Q2(+#Is(nsNHci|5Pna$ewd7hs%cusd{pq-bK=Yk-&*)O#)^eL9(VYLX6t zomv}8CGKk`u;|)VQV-in$6y69Gb|>>!Z%>d3dw*L((!Xk-Q_Ehnz*zv&|OxUnv-{L zAr4~ov~kd3nbqYl{Veh>fas6EQR(?d?Af1)AK8!5m%mOBtom{cr=XGT5}<>JaT`ET zL-G5zZ^40O+)o0O>727U7+{$|rfkbuh6o6l0Nptmd$OsD+F#o1`1r#r;-2zkCymiK$t`&Q*lB$dsAnpflNl8X!CUUpxtdaRC;^X*U!QWAc@Ej#E&~VS1>$IEBKa zkFFeGoGp!5;wvJ^hohGl5f1Fch7qXmuC5eG)xyEwe&H!U?=6m5yG^BLSWP|C+5PND z&fF0G?m(^y=G~#3%(^=YWtT!NX2y3(0uxgMlYyp+*8v%ePgsw4HAyq-(xSyzUrT(& z@{jA+s*t)hG=H~sIJ&%|nidDr&sOCAS=wLwsXO2D1|sX1x`7Q3V?YZQ@Lwu)mre{~ zoYJkw#)zPe>GlY@H$K3u@K*A*MTUr|K7Z;;Ln?|*(?TeKk@KELJMcX&pHk3eJ;1FZDZN*`uke2Z=$Kfn6od6|3*=MX#K zwnm0UI4AXXo8jt%BUG-D34KvLr^+2+UOiTsbZ&Lz`!Rg25)fhh$Y#x#nVruju=BFE z37Wo*Z}V6o-8TNDF5a$Z&w+1Jb7m&R4f(^7E#=jVh(Y&j=$$wX;{Wu2S0r=8 zc+6yOfur~qtD>YC4C@?8blyb9PdF<-X@zlWIBK1Hf7A6sCX9J>O9sW}r%FC61tro# zPP}rD#S>$lQ8%GAG%9PLgw>rqW8xlr25dc)0%5lOpkhW^B4FMLwn? zyr%i}B6i{>ldK*LxXI@npFW8If8QU16}*B!Xk!d5r5A)xA1j)FIG}LJ zCx3g2r&%OfGxcu6(qR{f&_gSvw)N8%azZU;HotIHbv9!G-A}8fNFL@ z@`g~-bCH@!>F44npah#qtxTT&;F~Mx%iFjM0_Q)sKClcVwjsbe*rS>wiSa;Q%jpTb zwiMt?TZ6&PKtV4;s(Jp?*g@46a6!)*jN&a-aQaw;)bSpOL#0DRmZsNXfWubdE(JYO zVR8+Y`x#I$s>!D9|J5{SfOhPPOlZZdf5*%3SsB7qJkmdAtY0j{tL|fKOnp3%3~=;& zeV&w~xF#W1-*i^c@5wdeFGcoIJ2*+*Irvry=IT+rn>G+ECqLpGoxjSaohc(9P+k>h zDBn#AKK1YRa}uf~u%2B*?Lr`XgN6+w+X$2{p_UnFs0uB&;$;#JP#B?a0Vc}3APKk@ z1^xn4|7v}iQDy_5tS1$Ai9-MZEShRNl4f@HtOEhNRDT1Z(f>pVe;2IGjjXq77g8W@ z${GASZbDD;|0a@m6+9MAu#aFt-?sm&Lf>WX?eP=(lX@uK*C?+Bu<8jmPo^17FCf>A zk@N60bKSTRqkpwCE*Aoa0{Ivos;A(Phki+@e8hsifzC@mgx;eqi_|G$L6T29H zc`yOUW^Z5SjVjUH=&5>U_?N#)EIa_nqRytX&I^wnX;a8M$$+%OpIH|t2WKdgyBWyi zlwQ;Qv1XgO3+;eU7-5!Wl+cq+Z$}Qsxzlx*PexS@+xr(w9>eO0;Q&Sp0P?<`YK$Gr zVz+{wsQvUw7`s{gG=$s#ryEl90+wYd&J~(wr{}R&*qRYRunAu<3Y;j{cNUfG{GG4t z8XI7m_9$O8Ae%tt$%od}1bk&L^=d^+%Psl%5A(x?(ZY9iE-bYJLqs1oYtUI~3rwbz zb3OUbZs-3bWdr9hAPOC)hde)oUO?x(5BCxhzZv#C+3VLt{Z=A1&*oB41uWeYaR+MT zgV09BwF$1%Z}x*1n4HR0lWK^s+Qlv@v38vZsl>OFccSBGpsF4zS~-?=w4^5-76%Pt zeabi4WsmyZMSJ9I?&g@nZgR0(Xr!X}@xL|hs!{qC@sWB)d&QY6-v@71Vh#6sK6_dv!v_(nKfM+#b*UMRBe>X6i!X-vM{{@G)^pOyl6 z&ZmQJw?GU7FgPGZ#xz*_mt0{YGvLMkh5QM*fX<&Dr=Q<<_^e%di!9oI_DO3z_gbx` z5Rz9!X^KgS>?-oPGQI{<_hQ{}MW+CW)Ng;+3xg{a^5b)KwN-Ls(rS7oUsatc)W|8v zQaLAx=56oPwd*gRF7*SbQL-=^pSw5XJJ;gQ4A^o8e+8yLmyW3d^P` zY5UE0$54I^viP5HKY4yLTT zWwA3&@%-v`?%Fb@&=k%4Dmzh;WO?#Ax;cl13Wuykkf}S3c{Y6MhL9m#l2EvIj~2D1 z!p?^{e2RL{F&u-rY^R)b(W?^>yRfT`gk`Ff!g_ZpIzcC1f&5_jq4PeoPO;LII|tUp zV-cNZr2(ZRz}(1KgmGEK_&*H1`Ji(ZwLCHDnsZZMYhWBY3Qe9A)ej?!V8Iq(od<9{ zl}^>JWYL5$IY|u@184*`x1qZFJp5TpPxQLTKqEDkGN#&oN(v4g4Qbw+mXbhtj0vtr zYPw^sgn&nZ5NN2Ie4sZ;zX=PY`6lwRCCu?x2186`8&$!4(2h`r0g~4Q*JJl%u z^w#4#XZMf}5fNb1Fsf4^=F)Q=+;E%DUQ0)OOXv&o6qzP$|ML4I8<_+$?yf`JCz(yQ z8(qUz<%q1hTcNGa4YF?<^6~454Q2Y~1x4Ysb~gCt8{QLPLMy6S74g;=lk+V>Y0SP} zZ+)rj9p1$7_p^TNAiY;du;)ye^uE$zC+lx~o3Z@P zko#?3+_wxx<(TAjC>+p(`n{aZ;4qA|w~vJ<(}t^TZ^Gj7ZQ}`BFMd(FT<5y7&#Sjv znh$@kxTz&CB-W@1eL&bRj}%G}6tjsV%)8fHOlR80F-qSb#n4$T*wdJo-}`jZt4;mx z?~5FD1CqQD)dp@4vi$_1)jlrqk4mlKE3Szk$N83BIlK?yg3vrC(Bu z-f3kOfYQuPTGH9V%;w8(Xn_qMw4ZjzdMlY?{id?1N2QVKMMPDPR!}}~w{y{=Masdf zosFuOfSp=qnh{)?t-$!yZI}>#xYZ`s>!_mV5LbI^#yZ~sg1YuT;7s_V5<~JGt*ewObYh{1Jw>xNjl?H8 zwXeQD``W2ZhL#*MgQOXQy7wY}L0h`Slgb^mdgI0YzAoo>Bgaw8NL9Fc zL>&43tu9l6fkULe^K)GECb7&v1rs360ABSu`b@A%!5)Zl=-gHeiss78=FBk4x2o>t zr4N>< zRkn95oT}8i+{w%FIp7ak7{qw3->eR&6#C2D_oP+jkL>{x1<`Q4+Z$Ihmo6P7@3sR0U`4F*GHD=w^t5x?M6Y;38 z1%TERwyKqj3XCi@UAk`^lsa!|7rEx^JlGy?*XaJM#^k2LHm3aHsAuO9LlC^1kGUY2 z=~1bWWdSNStY0<4&9qim%15)m^>}Cu^#Bzu#k(=~-det9&#D*izBrpjz+j^BuWUh9 zGz5BSHJ7bNX|Tdqlm7Ix(Ep^Ymtl%w83XkdiL!JN-m2d5oos~Z@=D&$ym_pT@ZC6A zc^=PR|8YY1&0}x**=&hj$%wV(iqq-*H7(R{v0C`RVS;HopNwu6Pe8YB2K3^5lqyYR z-{?#tQmF{+MpEi7QkF|ghJcd@15f9WO$*fWCw?^H98m#j8&@@urVRotR@2XPO5Mm($A zy>VVE$B1bAia-j3zNzqBolL#zyz8!uo z;(1>DvU=<^3)Zs>#%vJ@7Ws4G%+E6y1zpGmu55X)qnEanMYlc>*vqf}A^gc?==DY$ z4u?l2>x#ZzJauZ%8`Dr?F)O0B+dh(*ziwk$mJkI|-wCnHNd6 z`Rv2D0T*VVg|F)cbG5h9sFQ>&O2i$74#kqLHONcv8C(JfU8jZiU`)auW?T%;Eh=Y9 ztr62K9oH~0)9T)<7qvN46(8pGs9mRq^{OJaCY{SB1KqE~nX3M?$2aIw1S;s8cSl4q zz%*d7Q*HxanCJq&Ht^$bft==q^M>;+3|miQOc4ps8mNF`{`b7KM=!U3?k>Zz8+iu; zWSB+d={C=d>r?QR^X^%GjlZs>P_=OO;ozWmlw@UeAZy<)5UxVrboc(g)g>CgY(v(} zfF1n-s0}NO;hj@>oq)@<4s!;_DjW|*qKqSB-P;(tNZI9vIe8oVjKn5rc3W^Z9!Aid zCqAW}Zt$D%8|PDy3ly%z_mX!xKPMaTh6bqIr{4xYuv7z8edqQ2<~C?D*Z0KhHr;*3 z=Rg54Q(+*${gha0oVBT}+Nb0xM_(3u82CzH-li~3jskji_df)O)Xxu8h0~b{RlzW^ zN&7Chy4XKt*kMxRZZX(i!Tc?t={F2by|1xtqx~C>=S$x>M2)>oN$Zu^+C@jqp+J~` zYGy!r8I_Ed2+m9G?1D(*W7ukH^_s{^750pTVXzFK@RE3L3O)dTri)Q!Iyw;bn;m+P z5m<;?w{IJ|df$>H2 z3ry)Dc@?(^qf$ZFP{3PXg0T&(z;G!5J6Vk*nibHRKg>>&`44`u((gkDAr}7Znr#yr zdRfn1Si@a+JC7TdP&xR_9*Yek>{<#r#oXg<>GQ^@`1*3Rjz&~A>+jC)S=2TWe}qof zb9HN*b|!vC;{Azzmes{ZE29sDpyS2w5KXqLFC!>g-5-du%X|Ud*X;=LW$qhjsnQP;X>2@qd>P{}(;crr@im8nW# zqH1kfaw5uYH@W_{_u|dL%w*LMoh-|TWW2}l1DlEqf(CJ*m5Ns)$rF!L&2IJfe3vQV zaa5o%XEfM>5J)0Mj5R#>0VV!vIwx&@0Z*Ad{I6!|!Pr&S@qCc0@9L#DbT-t}UX}Ti z)PG$qDdOouH@x7dGRwEi@8`bf#HD2Tr+p|I#V@60bZYhuD_6P`Hu|{1nsE756d);9gDwIbN)sfQ~!tmr-<`9(%J& z!DSP?9eCHQvXXu#HM7b=je{MR@yq(3a3;pJ{9X1LRR#$C#1fm_FKzIM{&W>NP6_Wf z&x{{R%!oKgPkD63bxcecLL-0XILfdmJNni@ZkgVSv2@N2PF8(hzkG8)uc$}ao`^*) zPd&=j@-=Pyjw`ZrMrkJ+F?Qg(RZx_3ad{uJ`Q#%0J0&cG7heTr(&f=Q3y19$rJJ_U z5N{}z-Q?$?{V(-mRP$Er9WFj^GJIUp7mVpvpBa%o_(aZ5{9PVTB~0DM2rp59+DVM9 zl#%-JCH9~8Kl1DcUURZ$?i0sKH(XT`W{4(Ntr@px=!|)i5R>VQFT~(rbF}LCwKi20 zJ&fK%&gO24&QrS#WN#)I8XDSl)9PxR=FSeyJQ#_gJx5**F z>YV4d{h;}lcR!qUZxFk}hCn3$Mee4XDu})w`Z*?{vd;fXzqW!Y(G-Gm7R$R9Bk>(F z_AF!3EiI}_+h@5*SC^esyKQ0q!3l(M8|EGm$CVhs8)P;bP;dQ*cDv(Pp|91|L6of? zVNy(~%B|EhA2-WDb@6N3a1)Ai>4Os>Mc9 ze=PyR$Y|-fmxXJ0{_q`Bzi11mC#_3!ZieWI8ziCIV^v71qy2*XnA+6K#)6<7#?5`o z?@!Zwo>rQQL zTSS~+6?wZGkGd6_ILjdTWX{*;_(gqXQ4zQIUPQQ;_u3V~>bEzgFmVAuG z+;|5FpAf1(j5vx=`Y&qr%v=1-ZL+Twc=3V7j=XutE^_m*F5~IOUZ~H{`(B)u>G&(M znIk<{1D#%>HhZMDtE+!K+umX|xT$u-POzu&pgnv>V%1_RrZz29kFObGH6#@gyokP{ zjLtrqr9)bqRUiLu+`h97OJ!u8^GHfYiwr}og1QQ>3BJye-3!thpu1O!OjqZp>4KKm ztG-Q)MSJvcce}f=s?IoYAGXCn$_`ziPjS$TQ9Z2?R0C@BtImP&o3L{=Hc#FNN$NR+ zJ7HSbz**;`Loyg9Gw!xi6dz<4g_rV6UASYSwWOj|FmvNG{$VhOJ;Pm?txU0^;jAIs zrRCFP-;=M}fx74(^b8cW{q3%RTq3JMtbvULPeuQU0>mtT3<+Q;r*2sqE5^@O=T)pd z5i@99k=Di1`rxS+h{+oh(0F9taCZY1r=X6$c1Ps5^+ee$H?8M?I zITo44qR%DE7zN9HNrmE-eCczWaAvU6>w1X3!WHbOszh*4W|}`E8L@;_Wie-eZBC3^TlZVel=T?VO|+8FdHN`Me??;Tw(Gpj zpTBfCR2)IjI?{#1uHf9Jeu&o#e*uI;dH55wfgW|wXI14RHr5x)q*iA8tto9ei}XIt zEK$fOBB<=!dmi_Xv%UL^1n>19K+q8gtLxN9~A~lQdJY_h04c z@29Y;XM3K^#BGOkV8Qw7IOwWFQc{f528t8cKal*w4^~G1>DhJ}He1fk&MoU!<$b0% zu=Pda$cid02%7I6D^VnI8(E~tv67hg_|Jw7a}$c!=Q%;P6p?jPM$rcz*`)QaGYP&2 z!G=3Xj#I6oGD)t7;~9}(RIe0A80lQ!DpbAgia73G*J~K4?cN=e!krl7O|)<4r`Ias zY|wggpy~5U@o9MF7c+jw+eSd~oaQSZg$w8TPzul(WWBa;fwTmNWNES7vG9Fw)MHA{ zIXk1t%2ehi9no_^3_!-|0&!5AA{J^ISU)e^Z&2yb)AV`2b=`>Cv+7Tyo)}8ogJ*7)hEbbjGx_Hylr+v<5QoqaY7QsqAq)c zec79hDEP#HaSj#yFx$pD4v{@o9kE%leidz`MU@)t&W$ghTz>%ka`W><)J-^HC`!bQ~o0?$8r=BDi>#;si!C?Vm1(H_5}S zcd|Yo^jjzB1f*Z9c%YXlqkyvDY$})J6sOEGgzbqAy=$T6)y>v0?oX-D>Qug2;F1S) zR6*-{wh8y7iIBOZS?SM~m0_JHi4!|-9w>0jiboZH$s&7pxYSm*@RW*6#AGzpa*e)qN+N&HVjqw z;iuW7g%z*)pF3@sJlVDia@&T$Kc?JZ+L2Wzh?2YyFbB zV+z~yB%82HGz%8)E>sWZV;?>&Qo*Z@Elfj|bQ-Gkq^59hGl4NWo`w{K#+X$e2?h1y3y8%_FaP@m8Rc=O^iBR4Yd)_&T7GMymVJ0p`k( zLK(Blhyw%%3!4naSrd5+h)U>Te74(w)aDHis^sI7bn;08_uH=25|=R}&5NKb;}-o% zEqhNfi}xsSXMuxVZXLaVcQne{kWnk2DVQBR#9WMupT~3n1%YWJWX*@*BPQ<*l%5k8 zm_Ri_b^TMk_+K{^6l_R6uK5ESE0<^~bu?Vg`ZBWgQ~NW{o*(YKlgUzs^p9uoN|-)z zNX+3~NV<*rLOgJH?XB1r&)bVm%K{!J|L#nK`7gOEE6otDF) z)B($y`{AHIFJfEaUIZ`E%KM)mJVFGn1phg*Oxj!nFo8Gi{igs!JjM+E?3Mi@_Umb2 zCiFfRd!bnVz{uh)06 zEd303VS691L>HAm4D;91PC_p;y1EM(ylZ#0B*yyZ(s^Kr1)-d$n9iuhlDKUOqhdba zJhr(tKFI60nONn7Qf-4hLG^VV z#6u1GmnSoA3suFwc$eWvh!2M6dKFYI2wEK`+H7fW=4pfKc@sBL@-!dPQ!H4h*j=p;?nyDSnJVU((=5%<|3-VIc znR3K+mF6E7n(fw|jLqLszhsVHI6^Ausx~ZzgD{f8@MPwXVootV7=>5M8%6mmJSGZc znqc@~Vch}AtC0Ro_LxEGl7~q}7`u$6$(dSR5f|2q48EpKWB2vj8*z7&a;Oe`E8*yS zbNhW3=Jgdx6X_{!(d;1~7+3HSlals#1bp)?H+LELMHk+YRSD^yXEAgpgz~Wy*7L139E%x8h;_G`j z5QC0AR4`eHAN+DtOL)efZn7vDK0>WFqE7r5VmK_%%o5jU^qT%R1C@euz%FU;P9ZDx z9sfoi|BeHN`AL!&JpKCe(B@2Isfn)aCyej=PBkw6P>j)j_BmLugW{|^U)1Gkuz^4Y zyX%Emjj`()#fO(y_OhYn1e_!Zd+^7~=6cYfn%pg|HIep~f~;ivr{R@io!TPiCN~z*amBad{Pe;zrqu>X6x`&{3 z7Aw4AXG-Y^wlDL`VN8gSS3RoL!iEj&FTY((^^ zBkz(GoNu0Ir$yS$E9lvB_YT?xAJsQI^YRkUiCG(UOgGvt3Gy7f^#un{8xS$;(U-Ht zZYQJpc((C-gPWEG(V4pi^9-kpKRWV|MFM^oPG>gef>HL-j&rfT{r65SI0?Dm_Pl&( z6^wZIjxSpQp3e2_|27i%2RpyvCnqzPvbv z#6@SnFWsJ?la9wzLd`7kM_t6wyOY%qn%EP3?@XnJN!K{uGqSjmOf$3xb1rn9XVH$? zgsHcOg@mX^aDFWTu5$s?v7uZ4Z-7EmnH|4wjz%~fB9A!15D>o;eTwLNhou|gMk$dh zbnj~?4lky-TzL?kFsfgG9{a;!-6e1pgAu8c07hdr4tWQoZbb6_l>{>eo1g zh%-$u&i|BQzObSD1NQ>Mu~crZnaR!5HV!*Usg6UJ$etT+j#evHv(3ZK z2G;S_i#imOGb|Dw>J%Z{xI1BaCT=z$ef1|}%i&5shim03ZNXOs^VP*%h!JQ_W7zug z#&$MT$HB))o|rHMO<--7%R2e-Wes%4tbb>PR!|LP;jKaB1$IISNCOkq$k>l{ttv>v zY>)}4`avUQ970L!m>8d{{aGJW%NNN51T!qZ6e-_x?&-Le!3ftNv+jGAHMNlHTEqr5 zZhLwEA+5ZSb{F4C&Id&o>2Ho>40$+rb{RLmVxwH**w z>|q34{3g4}_w8y2Ce-#}n_t@?onj}3Z^M(I1r5O<4~>3HctNxe;`Kyk@9Rx;6(UZf z6Id29AY?F}_8m;gJ9 zp>j<#JF3s_R%z65ec}n?o2thju(y<04*1sDzcc?iFPRv42AOhA1YGQ{v@MFmTo0#z zAO*WTS2~zg#eY?!XN>vaj=XuE0}wAInM%87vieT^C=FuFp7MC~b8s7;4@XlR~5R#Hz2xq|;m>%ln!(Z_%c=8dC!U-yjY4z&Emc*xJnjrKr5t8iW8 zv3r}rj$y!q27^wCq^h2K%U7bDt`Mj*Ic=9EBW0Lj^#_YcuKC=^#==vkhv)DnYDPck zGcW9LaR@@yQ;-nUsI}DobkR3=SAmG*WG;zL*`ktN>sB*-Pwb|JCEg$2%&|@99KwWcZ1PMYj?7=gSxuYIOIUj+!O* z&S!s5{?)-VkWEi3q@byEcsM2FevxIyDZWTFHK8dc616G(0yS#}J(}BQ5Wlea=l7sl zDqR?1%1MxAn6J7?(t2Nv@4|8reg7;+L>Fb(^C^a?5>=a1KpJKWnK)=#o; zC>Th6EZu^Gl)|u+;l)JRBqQ!qeY3{LL75b0h4;T9PIsjveRM|P`};)Ee>&yU>n7mJ z3ishSxDp|cAw6DXF0UkJjWvWeFV^G-3Ix2?RW&r>x)rzQb>tLty$+S-04MvyuuMnw z1uFyo+Zc!EpJS$-uKGU`+Possfzz+BnXkIHIF|es$sLuvi~H->ZEc*#?y(&^A8+I& zXMg|vEM}jbBq$2^w%b*tc2V2O%q7$gH)=i^{WB0UnvnnMxwwOAmS;jpt+DEo^AGYI z1G6uQgBn7}XHAlA$gKBk19U2^>Fv+T3N>!p;!G%89Z9sQoZekEm0DExi5qRKZpyz} z@JO7TC+l9Z&DZs~ib$xd;-ZS$9{1IU-7oJqOZ1LHGBuz*U(_poB+Ay<6bARx-->S> zrBNau(`pHxGIVkt_%MmQlA^1VKy6Nw`(e&UAhn4Fmh<=b3_FbYEiq63O$lSk(E5B( z?D=s(F{-a;5rHbkIpQfQ3j64j6UiLfdH?;U>TI_k)OASr_1IULRyyR`$qah)IQj68 z*}*$Xvte;>j-bv6PwCfzH#m07Yo8v^5th2HRnPrSe_)r^$qEvJU$qRk6a!Qiy_B<} zdai3}Uu@s>{#e7oom|ISUX=?ir=UOR@xQikkFp?!P8q#m%Oml*)T@0s`sG!kI#i@) zRDkvO{mbe!uI+?CFaCGIRCavh0;?{Rf_q=~W_MTIA3H6s3?t6jA5JI>`D#LQGt{QH z?=f;;YCmUK@pa<%3i~$Yv4rM)`F^A}^X&CG+z@Itk9Nyrd_pq=sa)^6geP+_PI(RW z4+#%=DPcyk(He)3uXf%qTw*Xm`kfRK%Bl)n3Lqv7QNR}!LKl(d_-l=zy z52L@|VnXd_DT^3TgMZEC1N_%!U%u%3gchoCHNS%lzAF5)vI5Nlr!+Tnq75j2eTJUY zn0bcaTdR8{i7eVPYVywcA+PX%ziTo(|6q=h4;H8E`mi4g9}OKvZV=oQ z@f%nZ4CfX9_WR2H!c~UTDYDOt6O``C?Z1@|VbOhyv}pG4KXKeXEp|t?bgxQvtaOkk zsTse4KKpM1-A97BQ1$LTg`f|t91UB@Qtj+ahBul*>HIXMgE{1Hoi`}S$@k4}nl^j3 zZF&#Spi$`4zb{ZP7<^B|Ln;TNzwT|Ld}eo4ZaorRs6n(yxQLOnnr0wiB-4RP~FX9d} z3-(hBx>WvvgbtDS3qjtWM^_h7B@-<=YMtQ?YdZ6bOGt4!r4uHXvtZN^lbUdQwn&Ac z_}G=7mprb7a+3Aae%VeBE!Us5p7}^6&#Wg=qYPQ-h_iY8V_23bU94i#h^C)wivhh3 zIb`jgp0VTdhaN(GP);t7`R8vKUdiCQ2giT>-mu1drVZq_DBP(R_2Zl8@|zUND;u{W z?!X(94(G=k{q?_adLjk7g_Ec@U`vtT3T|idYV5-*2amQo`}Do?4;SuvWI;PQ;uaVz zdfHbq4hYZ-)#>xi6Is`1)uy3!d)Lw)YG6ZqVBYC5Su&C5Ke4Bjk>Tz6SPqT+?CG=( zkLe7Uo!My~7P{;xS8 zRPsx9Jc(-zNGgWU$-Yj}wU6Bu$~p>Ob$@$8mTz9F9bD=eZu(1fg8UVs2>S7mJJDZA zrDXjM<{aV1&tUX0iK871mPPso!JQB`$~E9~K7K#E6E(c%IY+shIw>S$_IXdR490 z;TXBSxfyln?F#f~^;i`C^gGJHZH5lFq4@)aT`nWB)!+2$Q>L4N+% zYOTJTrE9B5UfMSz`Oj(^<9~4p{Z}z8leMZUDy`Stf48XnEu*~n&?04l`Hwo)O<1%@ znN}ekbe=iw3AgF=ScRR2)ZyQ4hU04#fA83riAH#S5t%b^;Z)OI7Ds!D+%H6uhGb4R zYu@gbQTHw|`LR(d7o!2;O?Pq& zkr3jZZ+zD~5cO&|t-o8N5pt%I8?Yer^y}CxTXq;w-alk+-^E-h+zs=MUh81)tO{0+ z)(iy>ur_`giubSW{NW9hhndu0qG66r*wn7c)b6kSdi|xS{wu=<9P9uT8#s1IHd)^>9 zGcl7*hG_x;IvGXU=_m~I6#iwfo`n#1D1>P183h~P{XWPO{hL8EjFnK~F5yx7;)sqw zF2}7fW=)|c@%@4Ailf4he~%n4KD?44E+ikMokUCau(CPb$IJ|zRvOPgM+eJ~cuO~# z%V(JYZ_<{c$X$C!*|QIWvpS0_u2ZG1Ki=0?nzw&sXH2zyvEsKb)eel8SAaA#{;DO3 zTBI|NUUpJ8$F%s&y&FYk)3rbPT$lBju^kt;ICd2~-`T3w1w{droiS^0?)J z49VhKFL%!qL-`Dq2{WJd<#kaX(fP4{NUqT8g+t4>wRiIaJr#M^6{+?L$9iQr_OCAU z&rZu2$O*#(jp}{rLz)gxoBtD8kfILQT?`SBjUg+L%^0TMMF#F+iTiMcl=b|j?dOuG zOWldJ0zHKiKW2AY^s4&D#S0&84sh&WCcPr%=89?k`C(9{QUZ~*(pdS~aoSXOrtec-s$cpnNOgyAgb-EoUekvCeRs%(neJ$>8Z9%N zs_P?1dCia^h`j7&>`b!A0Dz(;Bo8~W6n8uyasDG;xQmJRB`#_P)aILF+p8E|&y9)O z&M-Is)f8jmO~7$8I$DvKB1AC@_#N+>a}ztXN{m(rmvT7Y_w*dZPx((MK0IN@gF#RS z%7WVW2`E8&&6tiI+i(mtyZ}L96d}Qr^B7Br3A|4zNrZV{5fg3_|L-gg9@PdmDJ%R7 z9Y*&Eg5SgGDwEg;iSlv7l4pL+)N9E^$jtBLb z=Bz^bU+V^7EqK7hoH=rWVj|Wf(CzhFS7L80?7SWJop)=?Sy6eFD_r_%_MtPZxk zpWLf|lKb8`Uv_IJ`So7?JR~E%&O>p(^>rKcPzBbFmt!|s)3CD)3L2_&#$jxRnwr z&m~9@R5^x3I9~j`%gtgP>61ZU%$cGvd)!Z7t-1g~PwQ0aT#IhLW1`-#ESN6V&!=K$ zscbU0LJ@2fb7$b8qqD%{qF~5L+Dzx&O!`}-0j54He%fA+a=C@uzLMqI=xnJ^T0(gj zWL`<_0LYj4I0^O0{>ffe1*!O|2x`+0=?99tp!^3i2s1Jl;~mfUE_i_<=E3RQ10JK& zWVHwqZ-kkYuH5Sg-s__+L=xtX<*NsY<~6Fmvg+=(;<=wTQmXRa!i6C%nD3s6b$q+< zG{aytmp-ng+EHMB^;_Vsh%t$ZF|#@0;%&i7!}>@;g0|E44A?6K%6bz7;vwgM%y9>Z zh7Hdz+V*T7j%#eZJjf3KuGWQ%HW)H*%MNbkbK%*BksC2kzo`chJb>%@b~3SBw91g7 z2WQS@Xy08du`#jKl35u^SFrG}9%{ZsN@NpVo^7Yg*PgyyH2LnMsGoq{pvzn4kqXJF zimOI;CAV&%N-FzqpB?sP@CmRAd-%ZFxr?MD_W*NNFbQ+4XI54BDNmeAp%>h0N5z)I zg7pj+-v?(vIbH5r<8sfuinorJ6|F;w#T$)7YSz`ucV4cK1ooxS`FTe^*iL(sPg^>O zwCo&J%s};d8`s!=4bKc6qso$hIVAnagBedOK;F7C+x%?%Vpj)-v%=YSJv@zW|f##U{QFC2a1b47(vUg4C(IRk8;yZO{c!BO3cHePZcS+VV{cT#0f}mH)(M?d42&!aE-vaNf!22(S8*ug$`3M~P zdKUSWm}j&vM(9<7ox{rT)B6Rd@EfLc49KWTIBiGN&*u~MuB}hdu}43(_-fRxx80Ix z3f2z(+AUY-SN_g=w8$_CFAvW>v6#D8KsC91@JZWw;uV7X!sDb){w0QQxnko){0Xd% z%#ybAo3Phbg|SE_c9*Qp%2_mQ3f&oM%KVq%1yMT{baM^;rT0vu`bkp(W3he4=$OPD zfYzM~KX|eFClHM|mXgwk+Z&nAt90Jr{moEzf>_xI6Zoq6rpNoT6?u(@h*fj!c z7q~-Xme9ke?RMz#z!z}icK{Xfa_kKKtOBaprtu=HSY3oe@SLf*_5?A8Q%Kd5E!KH8 zGSKW^B>;V)MNyhD?a}*jil+~~+ECrPn2at` z;VcuYbLJnAjsS_WsAv)zhU79)x)`R?!D$PAG9Pa-d>g6WK3OimF-Ur?QJa53?KU#O z{C2}jb=@nrcB!s*7oE@y-`sk2v4+BBD3c>aPeE>v+e zd*1IsSF4e+x^Tmw6nFd;)wIJ`kd3xs)Yi3IKOjQmM9NFD1?$*CAr!5 zzH`+2XX#-4`rU{5388lIzy&jH+$DTv;+H7-fkBCWAfG|ZMa#)l^ISl8F`V~AFmZT6l|My?BsMce=l@z>xk z5+#|VG3ubmw{Gd8%cy*CzK3PvVD`wJkiM*=$ZLO1#ux141Su&@KQ-P0g&d+nbUL^p`UB*WZM-4IV2-uOJpmO)ejwS7*gip<%Ola~1 z?)5@qf}AR@igeMaE^}_rz3x`EW`RHN=7>?#zMkBEFI~z-*iSYlo%QQZ#(Gp%ZMH({ zg${+|JDR6HY9eYc3n5)KnTqOuJf7`4l%ONjc2mkl@`F-q$l(bB^(EaO`s_W{vHO>F zG;oJiL24&ac`19gjv&?t|J#OW`CNTw(?nU_{$Q=umuA2;k^d9Z0Hg`|QS$0tk>8&- z?m*h==SQz#N#WjTMLI1`Z+6Y!clA{tZq@CMGp1k#4=9`;rz@FWr+ z29=&Wl9XU(Ms&JIJDzx#Z)N@nz070s3ZP%k08VA#o7TU-ob82>PLToMym%>!>zfiz zYLoE@8E)os=*6H%XH_IhFcVH=iu1CKfFh_OO{erTgUAe=W4QqnrxSQ^MoT4d74aV} zO#wvc#G>h~%5Y&}p&x)lVG3QA=^sG*LtxM60JXZAA$xqr2yjc*!b_z7~9*AP9 zdYqY_V{cIdk)pGfJ%jc7Nsoi)9AMnvfEC<(0G^BaeCMoA6bouwA~Dpn*bxKZ3}E+4 zp)Wh2zs?9N7`_xDB>QYKiD1nV|D*A#1F!`kqjhQh)-iOEEI85`0#w#ql2kjA(RI^9U%W6+mF;n%G;77)-bblk#~)ImQB> z^L|b8OMDM1aX>JlzrP7Prse)}hTT~NR6#!0#GI=Ge9vAG%UUGNC>Q-=^y__c=l>hD zXLOCdCVr>Ub+XT#?5rmy?y`oY#maN7F@?3hmY%b8ws2BUQT zkM6|fYT&uO1NypGD`=06E5$`?GYtEJrm|;x7zwD7Rrci^Ihg`*iU=V@l<7AapcrNU zANYRy`z40gsKfc2E7T?cKl)h|^g%g5m=IBYKcf~QxS}a$`v+nQvIr$@PcpPw08_F2 z|BR`2Sp4(y?wL!QbAy%ereVh*JwQ^X8eF-2)TBR`D}Yb1IKzbc`v8r(<}&et7JI7& ztO9~Y^E_|>EeTI7#%EO4!5987nvwPI-Ut-zQZml*k`&6>Y(}p9jQas%#98c~@_9f$ zhEb+2#*2eDfihKn_irgvuLzt6fz|(>tNnz* zK)4cE8z7w`2qrZoABpKCevGks^HpS+#)qJHI50Dz{9n%FffNVuTqPpr7slE7zh_3K z-tLEUnZ_$1&zi`rL ze^NtY^Jl)w5_fPf4RxB`aG^Cf;g!((x;hA7TNz5vPj@|(I5+ZVnU2@Q;mO$)u zrYk{smc`HQ2_AR-!Jo7jzmj~97Rz^I%zPiif{8z2a494BQF(P-b*q)*IxK~5x}#mN zJ-II`VoZ^LmDBor;A0(RNiB6nui|<=*Sd_xkmYid43_PRJ7E{U)S2n;>W(}XiC@T9 zi`fyRs30Q95!*gv!z%|+!#%uj6UdB;huzo)PUo} z2w(n8#eJH)_-qV+6MTmx{bkxd)+h*{_99r?BPqG*Keexev%_`b7WF5!zRk{+CU845 zKc@C-4NxJEiH@Pwjw>(7R(P_UD)mZ;hv}l1bt+S`<8ZXQ0`IeM;hO2E#Nq*?qt3c~ z5?r=_;c5~)y$@~UaAi3%J^Diz<~i+jPnVjqf3SNhNO4ra_Khd<5eHx+GV;t#28U;& ztN6@w&qDh1OM%W!{%K!LZG zY3+@pElZ|Fnaj?7j#mf=MgBUgq`rj&IL%1u6%!G^RuXoPS9cTL#F#UW6)K`=+A@=L z#8(LaPj)=)2$7ZKrQFayEHE)8R+~v!^?LxK!hBrBX~LD5VjOO7$kO^+DPEa|;AzUF zSNvCz#5dMP@d3Aqth-`ng=(ByyDU#277;71tog zJ6)`|-Y3rnMz?rILtPDRrua6*k~xVK0?r%=j0t!P1RS{9y*_6OrqL__`g*I4mBI7x z=V3GGEw&ieY1vBu8M6l*Zd|x}jWuRb1}0G|?*lJHaP$mmlicGGj`5VAWTMj3n=K4z zFdBjo-+kvrTDH<*|Ez4FxqF1u+QO!kqV;hb4Aj|PS@p{Q&iclt&1Zdx=p;7tokKna zSoYS}7`G0zOa@BH=+=na|vC568%@PE?#m%amRy{UrqPq!0UxS6ywKALNf`+BM z)f|@?SmX1xSVB!>*~<*RuWt04s%oqy)S_o>!elbn4Q{#w$$}j`Bcn|FUgiqjFEd?* zcyDPwPTh4p`U{_Bm<;IN8M%=usvC*{x5!}~>wnoP07jL0{owtJgZHoMW^Tdf$utVy zyi_6maO=vqS~ERMMP}9=%kF#Xur`pS8y0IS_iqoUQ5Z}zdGhQ+%jRf3Pq1muSISOk zVt;LS0ms{il%0Nbs^p4k>rGLw`n&g_!IE^yfnm)9+b+wC3!Lce+!4H&AG6l^+(6Ok zx8i-Q^?SqsEQ62516k}9j(^AXgK_Bb3uv?c>wr?m>H-DnOx2rYdy|pSC0_j!kueb! zC6$cuSB8X4(MeAe4-wtlTBV1&T%&rpQ;U(ERT=&K~1cuJa#9n$dPnoFLf0 z9UDQHUl7^ni>@#XD%@=0lPr#Ci)3~56EvL?s6q-)aegFHjp9sKAB?p!TbgF?YN;O& zxhb5v^O=touuoEO=ryduPI(CwUi+mF8|N`f9=XTy_!LUlY*%+3iax$nhfe}mlJ>S! z--OZIGpNI7?`EQS0aU^b+Hs^1mm_k;5c2Haj`oY$N!DA?Tm|IF$-0GrWQ>W%+)xD2ieAHVvs%Ea4Q6Q2vdoqZ6ll z47P>P#uXHF|DkP#($(`2M>}&ptE3!nh*oI^MQm*^YxKygVwhd)LV(+#F6c&>SZQBf zcKlc&^FRSs>&THvv>=MwtP|}RoWIV9-ZXw=e6|6r0vPxqF}|PYY+glyn+!>diehV3 zxt%xJ6DN-^V>hKUP!pLwVc7K9XLBgn# z;hn~E>rdP-BmWYfh+~o^{}BvHo8Q30KoIga;Cea3C-RT)w|3n%sm>nSe-;#^f@ags z$<RBOMq^=v&RxMX8VQ z`|2yZ#ZVopQe+$QKs=#Uy_$yD0szel6tAgiXu`Vg@UPl^mL%OMKUB%F1pd+gLF^Py znXYb?t~B(nu9Vl(x>0(v)d{yg!>*lwqUQ;2H5&3)e;?r6#Qvd93I;CsKqT#w}>?Y;On zp;OTWo+Wri=?nO&ZkY3jUe|$0V;FGPB`XKceCKh%>W&@BL+5#zadNiPv>Sh$NFa4S zPO?s9c%~)efA37><>du2p1fvKKS`|pbP`Txcsbx(v;*PDr%?y>4#P~kFz)iMTW>Q6;Yh4R4Hj8&2uMq_F(38zu3K|QSKoUk` z#1CnL8OS9dcM`qkNZm6^NP~PF6FCMyApP&-zJVit23!YND3B49I3i3zpBX6dF)S|d z-}=~i^U+oZcf-M-pz#Wgj``~zYt{4J1#g!1fod|Q;Tb$j6j_1!B&23NIUnyC6hU_O z$%OCm>i*;_vsoE>{yGH)ADuLQ`#@%f7qzREtVte!Vn6Kl+x?%@69%gvIA$N2=G2+g zx_9xKHTX*U?1YN1h280t7;s{S?;_xuQFT!(gGdd?t^76MK;J;_2Pbj$osy+8R4@i5 z_`<^iII= zy2nZh!qjs%YQ+~o6xWXMZ;IuH6sIi+>G2jIBKQ`ZO4> zSH5!4Z2jHiZ5%W*M0aGgDw}dL&9U@@FWrKia@|h9%Kj7-4eWaV&<2d^i3SsPMT>EP z(YV-ad!BoH1a_)h=r(=6$e%l?>^vviJn%C_@B00{Y9VVzWv0xM$6jI?CBdR@o|ZJT znjANs@9gpUPDTuhPAGT_Geg=R(0_+SUmeM|q#r!Br(+GpYaU`uvHp&6**p1rWWla# zK@sh<#N+_j6JXH9MvB?Th7maxAc6N6Nh&3CiN(qHt*WcbLG{}P8pBmTq`L>R#ECm8 z-4?SReZl&UbKuFN{!rq2jn4bA=xmhO_eWE@4$=16W*4--cHfnSaJ;3n&7z0DeBxIA z2hSFjMqm0i+Ik>hv?AkLq5BrY-D2SQp8gJG2z_S>KnN{xEC}I$G53~XQMPT{C;}=L zh@c39gDBnI3G(r<0@$O&Am6RE=$~E-_aLd2f87VyxtEHJeA{|b z+LdwPT7V)^nsE2IZJ9iS(i6?KSxdj?-11s_0Juf{@uEmoW(mHtV>6jxsVWbN_8qm~4j>o_g{9LU2!1#=8-z1y=EsG56t5EN! znd{gUq>GI)dUp#UAK%Y5YPP>*f_m%r2*x=9v%xbv=+ui7w0RLS&7g;owg1f&mz3LB zvfaFu3P7GUJ4iC6%ou)2as&VBFaWNszlj`$QTRPLQWtr6159_o^E>yC-OnIk&ke|b z$NgMr>L?Nt&fW;0S=f(hsYSKRN*|cad>UFoq6TBU39RG13EznF%&%Ch8~ilnn9Xg3 zN9xM!w42i?W$YR)wPbJ$;<#TrKXtL0YUgt_r#I`NTj^9)YJe+_P&wxar5_0)(B|WV zK|lL2<9P9b{GIENbCkr!)2uhu6G*sij=2Rz>Bf`!PPmRlq$vBL%1vZfDpq+~SwS~= zYwBudFuShBJA&3|HlGanc|~s|{h0brUB@kv0d8HtglR76ZmW`deJ!xyHNxH-75{P{ zCp}R?yF5oibd)3fAM!8tpr&XqQ>?>~mi@Vdu;Jn}RYhNnE+Rhjr%}WZX7L<7<=%c0 zXSiXZc=Iz*0@vQxR+710h7HQ8YC(l9?OzoY6S=`h{ONO&laIAWXR8Om5m+L6tHXDg zaBdSn-_%_CFmX88f7NS_&H7Oqs{d14x(4f%np^ct*P>7+_qT{}nZghNP`8o`O>w;K z3LCB5M$0m6Iq2fj)qBs$`y4}X9F zZx+Ixx#$3)l$Oaa@-c5Tc;;Y%tyOQEic3VUPz3IW&NV)X8pr6hiH}Y+vfqr-N6;j2 z4}9VlP3b314OETdb}e8@v3D_cnY^#_03)rhYvo_4n&bUo=In26hNAu%DHFc{FSV)_ zh$+MaPC@9~--42c*5dhDF%jtk=3s*~gwv@DX-M82`TVE^}}`uPe@nSSnp+;s%*q7`KA_EFpWzE3oZ8s&>hm%k6#7+G1|=GRp9( zg$uw3oi2jc`WKKJN+LmMgnsvT=H${=ACWaK&7r}Vyh^k#_lp6loLi_oIgwxQk)!}LKcs5_Y`^UhpgPH1u`PT-E!ZQJ*!568_chzxE$WE_bqra(XFE6QdT;U1Nr>c zf%YsI!eb$e4M@mCvK;);;#+p{LmU<;(SiYt`}s=ca4><(uNTExeB?#CfC~pcrgGCI3wbzr_%{hBsUi1uz^-Zts|=s*0X-gx?1R8H9M3{z=WhA7WjN}+%nSpH6t9j1 z(*KDpl@ujpgGH=IyI|U7VCo{KqVa=8jN5eztLSYMsFi@B-I4+-5)_~b%h4Q=f;o_S ze*0)4KD^XcVBJvnDsy!TB%^^NF3k-R)Ilu5ItxN4SCDm-^8{PuA04Z2kJv@Uq+b@WUsGAZD-B8bl$JA;Zi59g5)_@`3GV}IZCA8c#l9o{C_ju%_^B$Km~Ijbg^ z=sjk}I1jSqEtkCGpzYE!*G9?fJh&+zWP6l8q=x_&-~KNE3%zh((@#If?XybW2-*z? zKbp$4foUi0B?WJO3Qt*PmP(75k`n!@Y_eVVrW(CK56TT3w_^mZ(6x0qb^T zt5>}M*0tXj2qOnzCLR!U%&3YGB!1F3A}x$9BtD0~$`x~o?5s;xdx+}K58E>nq6fkv z0%)pM{z{aYGr)Tr;kN7g0b4^McyNY8P-iugd3TsHbjzVT z5r~5w;663|cGjjKRx4NgodLBe!Xx|#P^(kU=ry89kPTkyCR#6Kk-Gl;p+}nRT+g;! z>O%d-ng=C2DJ9n7%0pUXzdYZQJRB8U-8Zfzse(|I#2Sxy7{`(vYasXp%RxE90!P#vM1|aK$id z0(j|ZLWjt5x3KE=eUtsgZeo`1mzGo$zKG5_f2X16g8B_u>z9bhS5N}%0}C)CnJ=Cj z9Zo+j<3k_X2H6d7iI{S%PS-9$ute8(;8SkRteWS4SY|*cabQ;_hkywe6NOLB{()@Z zMHJ0F8|*}az>JMjM^P;R=Mr0M-vBklutZQv@|yNi%?*^iL+)dR-GK3{- z$YIO&pbrPGTx20CexGIgJtJn3c4svZ*%MF2Gn>+~tA4_l9zVSV)%gAXg$vCWIRR74 zQQ~Qo@3go)wDG*u>*>I5dJ;a1IegaUV}Zhr3CEC}6f669?G4*3^7kwPs7qeX7qj?* z6}!NG*-ptw{9~c_$jcAH`11-qesJSegaj_63qGSKbUw-K6INml;mI+YbB&-1H!}lA zV+j_k$}D4^WH&lV;SLmB9TOsOS}yPQ>!uT6PN2aFXuSeTZFR_5$k%u@J+xp(nxB9(U5XA3CL-I(`oyCVf+* zn=uJd@hP|gu2bAiwHwF+v+;C9FgokNReOntCIEwN$Em6%VL*IGmCAQWEGGhXgW)K) zTX^9sF))jMDM4Y@R5^HJC_{;shALL(4Dv{UsX^ad@xj zJn8cj+WJ^Y$8)2rJ1Ac9c=;6{mI&d^V8NApu>1I-Ru)_mj5mP`5u2h> z1*V^IVqv=xHy~WY&F`^0lZZVt6D*a+>T$uZ(lu3t7}vKbhG0OyBs(w}5q93L`!U0K z$eR#?6zQlv^p2nm1YK#=4-=;rt^^JTXzs=P7 zd<2{8&4&FXn#9VcGjr2b5g(Z%l3ZqA=`fj91aP0k=93^ zk09ZO@U5Z7OkUf(F_v}eVpffr*ULjrK5P&7C$8SOKEmx+2Sa$(wUh0BBYH9glS4!` zii%b`IsSAya2`o)DceC(&B+VB-IY15!J)m9-5`(=oH6-}uCRiEM4)|^16tA-K$=w0 zSMfM_aK|S*IbQoH3W?~tawygD6dG5uGkU}DxjX}x&fq)F-H3g3F1fp+T5xs)54vs6 z-U(>xEO%H&eC{{ug-B?d-)~1+73=9pI5;sKDGL4Tqww(A!8ew0z21NtY{LDD50bnL zJ$Siv;TW;yt#mS@uN5Y4)u0?8%{hcqj?yAWof-n&lD1_QnK5pi8t$egS?V^H%~(O> z?O)k47&vKsG^YB~WzJi6n|x&laDv$rAce*Qj>4uSxsl^oOBH$7!fn$MFv=eF6cD}gm$mpnVgwByHZZPF1iSU4d6pNVsjX%=K@9q0 znDl5fQpbQbTc4yfa_j__5`|-x*H!_P=BvZRDPIn0$t)UgmS=XKDPjrQbfh@Vsp}a# zKHV|YwYq0^D$2Z!v=RK|{-SL^DzXXyGUfAG_IkGRKh%G8BqyV^o-b|jw5FEhL)DG@?c ziDQ49z!g1bVqm$1H@+P65oY?ylk@Hs})NOd^2FPHU1*t^wO`2;WjWdD@2jpQw#J!(BCTW2TtDeyQ7!`WmA|GX)iX@uFS$@Z8zX)7YqP`J z+hS(?@p4caK5CGqFz%W+w!PxMMU;{x!-#uhb&mci+!q1kxg))2i)#HPQXts%o91HyB$?@VYJ z=*PK>E0?NT_=9IUE2ZPfCMX5i$XKJt`@&b*QZezL zxNG(MNl_*wN>8(DoCK@W8OwPKUt@|kaExlzV`idqshezo1+Ho>LdNSl28(ce?Ec=I zR`EAd(f5}Dllc^UE5(aLs3F7ZEZ7Oar94V)h=Wjb$)WS*VFRd?GeX>T9410hnVbcc zB&FbeDYhSbueDQBelAEzvAQ13XSjOVaJ8C%#J+zsB~jDPMya)+-mR;UZ6KFhPbJ1P zngP!o>+rgIjXpkBKz7j`hBu;uv2496dUbp9igW!p|J98kX_V?D7|x))Uma8&a%h7= zxCpCoIi^J$GiLeTQ7z)l_wX^tx?jTUKR_HJg?&}9xc+!K2f+LO(xUVRVOaA8Xtpn2 zWxPl!O#pjbsAEcfM`SjTEBfgPOm5JPbGL{m*-l-dnrHDwY4|-2EJ$ygS1Rnx_v;3P zq0ac%$&NIiO3m0z+UOm8Ui!4OOkJcj6f(0(a%~F=mC$$;*>e@v@~Jk;t08LkE@x>D zkr;M+;$!PLo5>r`E%{dqC2YzZ3V33DaP!uaJz>lxYIbJYVJsLK8@#(F5nEo`xLN8wE?}H3wmHf9Y(S^zwxhGhxsWlEMHh~c{fLZJWdp6&*noYc~ldvw#uC4R$Z1PlGyc8^v! z`)4M-cA^kvYp_E9@du&Eg^oAZ5`>Oa()^1UjNY?K_u4;`rz0D z&G+XhL*@f9qH+oE=H}(deQ}>Z#=WlNDiG$~?*)-iO?}Jfb^ktPoKPI@aVwqFC*+7N z>wz2W9Lqt>V0p3`<+I$|zgh2J&i5snZ}0KIfFxSf+c}o5iy`Sg&ghJ&VFjKpLcrY` z?&R$5P#kP-Z>b;YdKjZnwmsQ_MZ)$+Pe(XCf2J3=*l^i=iP`bNs&&c8BL=dA`IUq- zK#{pEAQP^hg5?ZIAm0jA#p)Z&Ivyk$QuFLB8=~E|#$j@cqCeoMU<0ehm=_4KoxajB zpc;8$49$0VCTBy!iYx{!hh;TomCsZyzGOT!hJ+Byd^K3za#X>$}WBvP# zLYn868BaTo>%N&@-?x^Th z3nK)pBC6eC75(@8Dtod{M7aB4lXP11k-IV!vrTr3^YMnp1zC?e=iJXy^8(g9cU`;z zl%5cRlINt-F%l4RQYhZ{K#JvDV{5L(Zru}Z6NZN(5%+eLtI*`8<3Oj)sdB8=w5DaS zp?U2*bwIo8&(A*_?tB|(&{yqayr&53pOoE`8S;Ck=RY$j8}6dRa!bjVYqXE-TSh<& zRxXb{j8gow+(=qz!eYFt^=m{h#c7MvX%$<%MM@13IOn$FDHKLI*t@bL624e)!*o|- zXr9*EniR;;i=rS^mtq@h7ug#frA^IA2N{{IhHj`$I^D)^DQhQjbvGQa373y%`bZyDVqjwycj znVx&*;kzvbpwjPg_7g294!EKsFsbpFY4YzxsZP=yVcN?b@SnNQSU^BH{xY_gJD)rN zpiUmGlie^W|&H@>%`K{=99GqzxDi79UDjW|&G5|21+1nR3 z=kvchia@-zvCy!CBx~#f`vj20%QtU75ygC=A0+R4a*OD)8%AA zD}Er&F_x``CHY2Z9tOYg0=#bBH31!NUJ7i_jrO9!cW6Kk^0CDCN9OKuiY7}k0G z+#UQuL-3I zZiO}%nhfX96bIjH)%&JrS?bR(ay`%4T1_#&5Nx@>Xh{GPk9GLNap91y7X7d}HE1?a zlaYT?+YO~+vCZqgE#xZw+f@6`)G3##pEg#k-RUANPd0ytcQ>6wzhINTOD@84dU>x& zS{0vLZA!wmMqAl(=VD&&FAEvdrY?#YGKk!}gu0}F-LNcnHx%1BZ5u1oD~~7f@$qQ- zlDP*e=q&(dbITJRB~KZl*cb1O+~GO&A=a1t=WMt0%)(c&tsQ5T$_71GoToW9hhR50 zNu$g23=Pkt5O0!MKK*1MBt+`Ei3@zkcwo*4IeK51lEX>J4-^S37Dgp@aLM zwAuf;SpWZCW8siL4Y&wL8Q*{AZ-H4mQU+jdgp&MP5dB60)p?|9pbMNk+Xsmy$5Gk8 z^2WG&YRD%35BSL=&*$|D3L4WRufx!+u{?cTnf#cwV3i|Y`0lOw{t3N1U-W%<^ z6JkdGAT{a*^1v@dTUHhyJ^Eh<9uHpuKwG-S;yR>N3+^CZ0FxExOAKA?NPz5g}5NRSxL~gdHTiG}{y+Ajt3#|8@ zC$|Rd>Sz;Rd3uSKfM3bB5+VXU&7rS8#wVolGq2O% zFAftwpOZ*Li<1Hmmg>-h{cm6vBv_&UHBLVP-QA&UI;kzzz`CQXEo@z>mU2NeRKvPB zYM4yC5)=z~oG(j!Ry~<|f=MhOnJNyK9_X|<>oNAYf3=C==T!I0%zQSq;JvdQw?J|J zWF~Ky@~+lURA9ySz0_~E_$kjo4NdcC7yL7Q4u&TcEE`37=hdelhj(>2$bK&*sAvl5 zJW!K(H=lO4aN*9#gj`2Js~OhBeUa^**}g1gEWm#%r3AQ4o3lj!T!ZbQF!a3{rSbe1 z$qk-MrqZq=ttC^BD1QF}j_=)kxFF-&m|z>>>e*Q0ktD1azc*VpF-)9C_N-tab-}ch zTylRxq2c?jyGkkaF<;+U8%Irh>VvZxY;gr4QoiiK#{$|Coxv+R;xoHIMYJGey8F-^Ig_qfH7<1bmON4|>AF@Q)8Xr0VfAoruDy9P zd2c?2BtC{yz!e2iBg(aQWcQQOJW6Z@%`-Ib)+NR7Ap3?x3h`X-2>tqOPz@JhR8vB5 z{w7|fa?jv+C#-G3kjk8L!(P zLePGJ+L{2o_Ne5$Mz}ww%`AYCaOex6Xet#c`zh6;wKC(rsoX93=*PSuZy?VoOkaY7 z)A_l_gs7-0n1(Q!^3`X3-GPc}3RB7gXExvc(k#Q7EF@}aT)GH2z!EFhrUZ+Pz#kP7A1=jO;pXGcU3G3FtT_% zwmIK(lSV7RVrs~1X8-W`gIjWILJWG_y4*=)-{f!S|POra;ZS|CHRJ1?~U0R*m)HGBah-VY@J5C3 zWk0`6*}ak{SQCtWO{>UGr{JDU)x`$Q-H~fk^J5-ZWwPuNVI?s-`yPGQU)ZeXlgAc$ z4vcdaj1C|2d>_L6jB&F{O_vB`I$y>SbBYz^*vqQ9T(?F!zdv`6CnV+W>st{tnZi%A z>29)Js7YKIvdysUuxe`Emyk}97mtm8Fj=h$Ys1I%NU&KV{EGj12E-W%NeBTr%V6JQ2GfmPO(rIG-?rhx? z*3x={vxXRX=^pq3Og|MJ;ig)@@iO>+&s;6}l`ikj0LwJ5hK>EYmYcr7+$glYn4{^k znz|+CZdY45qd0QV$6FtJep@?rW;;KMGqIlFdH3lXIi}>{^ULc<1K1FyV`A9ixi5wL zE4U{enRHTo*Z@#Enmr@ld0G5zj#b%hDjupC?go1FJoSnrRH#GS%etNX6g??HNIXcgaE92-JL(&8bJ z?Y;^SGmOSARPy&rnRi}z=l&uS(&g5t@;a@0-B2g6~i8?OgrfN57)o@GAaOZ$BvGR^TT3ZIq#uF;rM210l9TKAH&{S8uYb zzYuD__uU6zq3HN4CS#88MPqy-uU{cc+mT@u+~J%1BK*B&i19Ka5;yzi=1>wJwJoK>`Gu51i^Zv@K43PW*^j|1@~9`%aFR^akl- z@JMUjcG~w^3F4Q+a2T4#WK$m5gW?n5f4{^T5-`+|AO5|PMZlD)@2p99gZ&R{Wxjar zA1(gY6eY3}W8`Z=&A*=uTv}5;sDod3y3}R^+27Mpg0GquEd~9MBa1GGf} zxbi;R@zM)>!H{-Ye7!`3(}ftPd9TcVc5^KE{4+#+Zgu1K0Z*v8lgk!2d73X_1z+?A zCXZ^ot0CaPdh0BMMh)&J#^h?bfydo5uq)*H_CY@NuerQeSFHmo>%NIf!wZ}3kMUj42@WXU%N8{e z_li)-oa~?D!dSFX!s_%gsoko@jLaDC%U)>pnzYuaje_k>>zFdVt%q}j~=~WC)wF&OKrQPPg|hDrlp#aMFA^KSq{YiTTqDKxHjj23Va}Lep8+C4%%>p=#hO{k)tVOvFq@qjf?D_2Vh;mlL?h1X;R?UTWuC zq&nD#cGyR<)lh72z>2cWxBhbwfYE-%Yh^6a?61_s7#TxSYx+LV4_>8OUO|_pi>!yDogPNHreqhmjqqbZh?0I@@;dp)maWS6Ou>bn@;ULn#)o>`NZCQH zjs=Xu-z+h}*M(xAqk7tQt>*@1n-eZCHy2pwc*1z5PmL}vCQX4K zK5qqx8{Bj}R@nj)OTyXPOHKxsMLp7s;`JEcV=-~?_ zwx0SXs1iWW0%d+Mdh)*e|Lg+vXN+Qo6-ex?CUU=yr_%c(cuk3)ub7nRsy8Ig zT%)kL3sgfcxau5{vNyrB_gKjPnRwKhl~<)pt2a=EL|hfE-|K!v(N{ZFu-WMxiGDSK zu-D)%Kl?FUaqbqFRY-{P%8lv`1HzjTpf4DD^RK>O|1C0==r&J9@<}@!5ACTOr&huN z;BqLhj3Xdm3Ba)pz7=Ob2Ka%^0q*_Nk4Xc%_es`>T}h z>===!=L=?t6EB7Vx z|JDCX9YP|CixC2~5omRO!2>(Z0FOrj`f-)MI%}1Q?(E^RtyTn2cNMYsKh}cO3I=Td^zgvkO>uzJ=}t5xP-1yARAQBd&uy2tFty`}QJf)7L%b%YS$Pjuo z-}+Bi0er)U3;6MgZg#_8-52|d1w_6WbDCQDueJ-?0#^CGE3aTwCBi6KGXt;H9|aUO z5%Zw~w&m{BT zt9=^%_{Xhr%sr|%(m`fOk&G?w2fE7WR`K6@+E0y$^m@r2l(vL)99X5;eL(NoRUNn_ zZ+UPsgQj-9Dv(q#w1~h)`?HV0Po)q0wX8eaqt8i(zc`rejc!r<1tU%0-1<Ce?45F%pD9+3O8F#y$TfC5?W;9-Lk}$`t(e9!!2<8Mrnp~f-;byI?8snB zuqYgc`CfS=-<>T@*2+X7JI;jEi^@tkZ)=}Ahr{IvQ+l}B^DlxE^jtue)|>(ei1<|xt2`BqoB6|VAj7V%X($y@BmgutRd2Z_19)jRVy+~QaY zr9<>^mHSo;`E8JKt~tc@6kY1(BgjB}Op&dK7P-xsm-48c-_<-TAk8s`&CY>VibL*( z6W&-E&*!P{8Pz(2aN@~Rjl8Ktu1bvke7~*FR=>h>$DgZA4)*$xX{pLwT7hC|f_I4% zJkMfu?td7)`o$5j!*x?a6M89LL%KpdcMlise{-QM&OnJ9E4^1zDS-T}qe$*a<2HJRkDPhp&Go3(;OG$8? z-R!=jnU`~2DEh~lP{q2YExwI@i!>#uTx~hWcdv$`pEq^>ef;$FN=HiH@Chz;ABrtx z$hVpEzn=7Mrz7I<^Pl3hbb6TM*Uta$ly%erPnR&MT;QFJE*|>}2=T8jJdjDaCz@OuCNfecJ}3{(;nbgQEM<1)G8Lb=gr}M>#}X`s9L<~5 z)c$ISw@HCyh;%5i`(pWBMZzy%5S`TbCop1dU+peY+35|(;E4{wb@@Xr~c_$Pl~Iz>|s?P6@D*7rwvc;X6Dz!3Ok2mu6Sl( zuPH1!%J7(6b=7H3DV4C!==^^FseB>x;&MTF&5r|dERegVj z2UfH;a<|}-=*-7lh0`r?CF*C{cS6`s&-3Ag@=GzYt*JNFg8l|()Ik`!KadSj)}|nu zCF3mpaR#ca`}GE@>Rt=7>kwq*ZBw^lKt@ zaH|AP?4Yn)z^>gzMB?Ep#lv3&2l3zT4lNhbS7H$`*&z9fXjjSLWQYXfg5%r9}&!(CrYwI$seqW$B}^h@&UoO z)m)*737^r5@c?X_xSd-cwuw%x!D8qR&CI`4y}=Qrdd3Y`clx^9XpBWdjK_tkX|j4Y zCG#(LQnYhZP?;M59=+_`pRO!5#V4=L68JvnbZNPhU-oZr{&LmA&H+#j-s`h3rhLPU zbs!&=ob--oZ%r0RIT0c3aLKtO+K-B6kjIQir?tZlo$jTc`g|x!TdtmQEBw)4uHe7A zF@m{K!^hU{?at@H_g8BAzBgy6KeWXM>7>WS7G2S1%wX4UrG@)u-q4^+oQA1C*X`4 z@1c-vfsqV^oRea5Wr8C0qt_Q8*Z6=M*{^{Xh8R zYoBx1O#QKAH2%a8UjFfk;9boWhDU-A4n9nO(n5uq_zS6Nz<|QUDz4pS7uQZ!Tls)-}My-U@=jpbYNbj;R#yy$DGpg5<(Sr8x z<>&|ezHLUQ#!5x*(|paZ%}wGqY1&Yin|m_wODch1?SJml0Zv4D`gh*r-bdOPq$zh5 zD-xdS6RLz*2!;!P0OjMDmN8#F2Mny{LIBwY$;a0nWG3c2bwXmOPW7cbBV`;sNRH7K zVv6gVNaY9nqjC#FJU7j4QDyQoJ3Y+Q5tJuqGqah|*UjGYFV+JDs3&>Qdzk>sQ{7eO zk4o8+JO}U1+(q$beS1=fb|ssY+N{Xq-{q?jQU1WNcC)GbIS75>y})D4$M9$@ZG4yTkp>93tN{V{mYy(}o=E{4PH=UiZD zwAFl^j;eGd&p(isKuHd0E;=BSq(Kuj$dmP>KjY*x?mZSjQA9Ht`s-nj*_rUY`vxW6 zIVTMPSVN|CaKf%8!Ajh&?DQiK zrJ3(@7YHil(Q8Oi5vO5Y^@NfFERWdl;j?)^Jz=-UkD?CXGs{f>jq=>C9hf`c*7AJw zRyRZv*A@R*A_BXD(WH(oyl?Zv@%-K!=GyHX(Ed}w7S*M5EK4mh<_h8b>ppwy*}J6Qs-oIr1=Nt<145<)`KYE z(5nRP+7jK65(Mv;;Al`Zu*q?h?>W|;0?+)bEPBz`7tC5z4B$Yfy4E}&FzAWSU3|kV ze$+XQj20IXb2QWcKZ)ZJ&dyyq~%d1r^1-pMN^y;{D;)gQ5JB7=UQ^ zk~H9{xhB*vkL1}R0pd(AftmkUFU{rN=w^>$)q0DlD>>K4J4ROkkqJ^A9DoYSf0P-F z#6gtzm+LQSbea&NsCzC~xSsaAL`SGd=i4Uy{}e612KI>cI`ti0U%WdOCtj*KFav2q zxsX(v!$oqeaErcvI5K~;KCUqOwrPVl1GzFFpuMhZbyT0W0rx7MQkp+rhkrz24P(Hq z&8pR^Zh=@ilrQ6`&w>?H5VquddGauAL2D1m3kKax`xbOba#oLA@J&3pwa0aM?$NCw zCHZ-pYjl5yr$^m6?}A3V00*|A2j04@mgz{T<=+}-kVeUNoqE2CB|ji8b)7%y7ffb^ z`b!-R(#u>ObnwKaL?s}wJAmXT&-0~%l8PSoQgx_ChKvfFRY{y*Vlo`EG4{8>*W7%wMY`9BMaocb4sB85z6^Z4X@B@~ zSAk|7HU0*W8hD&h3@JM(R$MbqBMkqt3uy0;7sWiC);geVNDIC$=DZD=?sbiDW|a|SG1mEKpuu=xncz)!X&QFDA57dUOT61o^V*lVzWejE$atLQp{+Xh z?qO*?MDY{B&IICSC;_gQPDdF@5wLsUNGaVDR{TqO2mN_8vK8&xWZR>s;py!Nu<+et z4ktkp3=#qH?nhK`n{cQ7az&whPX&^8^)Q-fkF+{R8C@IcF&8Z=H=eOTjN-D04xPm|x{U0lb6+ld%C)N1Yg6`I110!)^B19S!N&Fkws>%l=+aRkZ-Z2*2+R{2XbuK*0N&BF!C$2du&P3ZxJ9aYZb;ifa zOzCrR-BUsODdLjO=R*|l%&0?(E!DTdFp==IIRS=mIz&dra?>6402O*u{qZ14Q5;)+ zTEd?DbFtCgkK|QTx|Q^yw0CLEJM3QrCV`@7r$SdFmyV42tFR;whob6d)Eb#{7Kkki zNc;_*psWY+^Nd`STahig&@7!DZE3LfWS@N1h(>fQU&gP z-VT*|%2{-1cTit^;o0C4-3NY%tyU~$ow1S^&Bv>tieL?9MxO-s4GB($V7gC|;(*V* z8GJJ2(BZ2tAbdLub4Jx``b=s1tc4|J*E+^u{OPNr*9LdV{0VrC@ZBUh>i4i`AJNl3 zO=>G}g0KLinr;7($nrKgJwWgIu6}SwYqC_ILu=Ffx|;MLNz)+F=wPlaxfPBbY(0nz zBa0vc0N#lx@4hG+VVp8v6>hHzH?-{YTSG~)A4;LxLkpkzkKA)13+vh&Tb5BirPCkxLYADb7OL|M=>QlAg=hU2jA_2>u*GBAOP32q?ibHs9j|Jl95eIom;~8uC zAIa&dC%QAv?U_zJK0U#7ZA$HWH#~DfHbVXTldM+6p;VtFoc9XZ+hU$em{d5$l2jcd*Y9Dd_a@;lu{YM;I#Syz{2#*uOZhj0JYsg3>N*ttWyesU{DslZc3kri-F?!|R zCwN%-S3RqKdx9lyXVYqMh=k0C8u8Fw&492}|Mj-Y`$@#XK0tTK^v1v!?@-BP+c2C7uXMH&v#iAK?9~U=vkT-nrkTedg;~Jek{_4{(8HR#V~w%T z;oHxj(5jEgUA+M+GBY5Jnb7)<%8H>narwPWVDCTJ(nYePOxRTb{=?S5_iN1cw3wuJ zDmSJF?|LhlSsNPbr<)Y~xTV72Y^?DS5n{1qe1nHO9xvZGK5 z!*a6e#T$fPBx7-xG~P$mftMFs@lK?&qW`oSgFefwP)BUf()OYdvU+d$w?s_$TJh-g zuh^%?IhE4M2ObcbbP**LlkJ;7n-JVANl(|OjTod<7eClQH==<0QKmOXnX?DIxWUh` z7im^Q8W!C8xkOEV8oC~{{%2M|->!hl7o2e_)BdTfRg<8Vm+KvWr~$NS!cOfXd~X$M z=T+MTRWE4R`9Is&{5aA^CIfoQXn;fix85@G7;G6epNsU_NSeuD%zaUvR{Re5$jhw> zMzZ)_@ldjGvv$DJ_?56WoH=&kN&zS9XuwXtH~-?YBz=LK<*!Py3P!%fIneXHc$a^O zPqHdgK9$sYhQ@WU{fr?CZ`O@-x(Zo7Ck+j9MK;^mPP&h*Cx$YVFN(v^Q9f;X+E4>B z;Ri)U!9L!r(}t+t;t_X!k`zNs5}Adj#&e&Ds-|4$^WK+VEEleM?kY*dMyeGR_?<2O zy8qD-p+F+#T7bVaV*KNy%9XucDa$+6 zZf8=U(wyFB{_5G9^67`OBx@s{zqvo`(yjjfledn$hPWqZ@S*F3;{vnEYxpH0=uBm0_Qc zu$QudR`KmK?`G zFfCH2VU5t{7TW04zDeW?lS9l&`vQd6A|?05IikSpzr1y>idLM(eL?%(TzCZ{L$ce- z*{47lNhR%f^(e%;fWNp`_q+0U#Tv~QULv+Tqt`0Ou7M!YUHmc>vMrv>NOJCW)6vkK zNf%jQ%m0F4qc9B8N<_#P@}J%}`8inPZ~^z2Rq)-QMX6S9z2Z%_g9hS$Mnbmgd zc-S3KosLxt(L>u#ER_P=Kci0=?(UB%z(CMV)|be4I?g6ovSdrcJn}$b!%zH*A-p4(w)W6uMv(zVXY-{AOR@(A|Hl^@lu+SG+? zrh($(WZGaZXOT!}2n~k03vrt>8Ri?r(BgPYg= zkpGRGnv!tv3|Y4*dfErL)Mu?-y=19OFtCVm!Kv>~yJkB`gKy&AxVk3{d)rY?`a2Cf z$f*G0F83slPU{Mj)h~KEmrb8oSbAnHSE}lx)%#<4SROnt)$Yz7-gI1V9$iIR;7=Y> z-Q|GOz#$dtaX8N(1i(DYu%mXq!S=sJzg`*u34@iZJjb1ENE#LiNYJou=)XsJPd^&XB%S7%yLWI<{_N#yZ!^H-5N z_p?gdCt`VVOgoPYyWM-8Mht0Y&iA+NSg40C-V^pdC?>eyn)ta*Y-~S95f^Rq(lRg> z{Mkp8ybFtKSzQY914i^}MM+g3>yPIMy)$fGkT>|RJ}rmM0c1!mHXKRuM>Z5jHUL5N zG9=tfKVengP@KaEQ+M31YhTZc2bMpl#7%ogdp=K&wX>91qzU0PXI7Hy@(Ho=jX$Pb zuNywc>HjtQq&5pRP=1<_y`#6VeIsb&^5gu@fdEx+P)|E8S(RQEeT`8wfD(d_BO6)o6+gQ0I{|i5rKB zQrNO4|2Rl0XFeCxSHs+tZZom~qvzh7U-1cvN9fCn&+vC|8T^>J8tas5Yr={0nXnY++j@&J}iDJ8=P-g6B#{*~gw510~0Z=A*t1!}}IX89y zLu*V|Hp<;jWt53J=ihWzv^6niz}CXU$Q%y1iLI~OHJK%WG@7^|ZWYw)qKtW`8W2y+ znK1Vmf#oDK`A^Haf|R?@JSTJ>$o-1ff%mB3a<7I*p3Gh}y)hABSrlrFOCP!=s!Fpb z5TItP*<0#h${;N|mDG5C;gXi^72$bxtpL^enVcJ%{7ylPP&tI;W3-j69lCe7zf-4%81*a)!eb1bxwX)n9)s(&5#<^M4Do>5V4 z+qSSE3PwOTQJ_FYBr6~wsSpq(OU|I=oO3Es0TBd5f`lSi*NuG@kZJ>-MRxG1fr{i3#uKk)?O5?c z>_#A!;eJigVa@0LyFxWw1YYF;F&k2DKF#(`#cfol$(u_lji$hK6#k>s&0(THu34!n z`_gT-9Ux&%%mYI)%{%9gm!rFP#%s!YOxk_TEb0W6?Aa3@(5^}jeDd(-~zN=*i*ohQL^Qp;bloPq-?$JW|$ePdN&v~JmM3KpG${lJa+fH;c4Z6v(OH{2`2E*9ld z8DTPvYP{ub_}BYDA_Cwsxs((cwMfn2VFX&SI^b(RnzF*m+}nBEk{N~V%gdF=Ez~`l z^4$;fe>IvP-_OIvdUtU`I6MsQS=<)F=1Xz) zq$p;CzvMN3s$x~#YW!uUZ9!+9|i6wZJC0Ck7zMVr?-6icyX0~Rwd>@OJC_g>b{sV&i|E&8bq zdgo{uc0JhQOqz|bgN`WM4L8Ah^N}$fL#zsYyvFx!cWyOR_9B?)&wypL_w6&R1S~pg zKc0t#`}Cutu&m6YhprZ{>iXmwo)ksp^`A$MzF%d{kuf{1=9X<#Ce>0J*6#E4<8_WM z)LI*xifnwVW04s_>;2-sbp7}FALx_1Q2v|(%F#sSIbp`m7HQEr02oSbFiS})V+(mhCMbcwgS^hcXDzi zz+OI292kiK&R+4?@GH^F79hDVLr<~!iPV2xO}Os3d+jK^9BHq!4B41Z9VH?LX!IKH z*E$+gmDvnJT@0zd?0B=AhVG4~nUdgl@AC1j3#L{P8#W2J1G&Dqd)I>U%Qyzqhy3dJ3Di{gMP(+Tr^Ky0ng}|-h{Nw}-w5QB2 zmgy}LvtU}mbHj%%UQ z27gWhuzY;1SR&&dS(K@9R`*hLR9Q`BDk2)CZZ{sJN)U#T%W_dNViC(zv!NQk;@>j0 zc;OSnVMbDg?S*fmyT)(cchFxe^BJ~ujc{9>Iwz;8VYtQc!ieAeXr@#o2NE=CY6JKH z3u@*B)XPq4QaPG|IslN0kKMxx+v6zjZuZXH3Q-Z3P{#+j?3R&%z0mFUjgV_{To<;E z#<44n$5jAYs%1xrU4>dN0aroJr~K?IGqgR20U2Na1)Cd`2tex3;nOfT=MCW>8{x{U zi*xUa0N~kpH&kd?IAtOc#K?P6Vl!WYq&pA`k}&51kkK@XlyrN)_S?}yR8Ve?tfw>M zVT=w?nL=bk>l;njh>ABP8yEkB2_Ul(LE8x06Z3lr+}_fL4(jc;j)aX^mNXm6u{^o7 zNfWE`R%&zZ+*1e7HV7lHtg0^<(jtI>COTjixAF68>cQ#_*96#ftk5@CJ1ai)1^nhr zC%XI_*0@yLu!PxJx+augt*AG2+{}F>;q?oSk-^>WPSi~Jt$$(61M3!Rb3dWy{Tcp@ zx`-R2$}VrYeK0f;-1PE&{igf@ks|MnLWj6?t(oUg#uVAt;6@b<7t zj&l}5U347RN82Z$^9>!EFmM5NmPI|2Txlc3rDJUnZars-?ew(1Y7~pEa_gvrt288z7s^fj;#lR(#U+2*^(UhetfwR|lT)gF1 z(vMN4^u+Din>$A)w}b?Ki)2`3bg_Bu681>rDU8Ly$9m@0sMWSHcn>N`Mag;4tAY@b zlT1~Kuyr#+Dd6Y}gFS$>!U{h4Q@`2!-gx}oVBg{BP2;a-43na*0<0f}SSdQbH;Kv% zvT?6q6QO-}L4kFx>3Vm_JqPV&W!$#%8YE|FB*)T5Ivy|aU~KVM-t09NAQ^Zk4Dcx7s~E{e?|CR@$8za0STh;m-9$LtAN zYeRx6gi2#Qci-5_9iU|sY#5Om^H3@ww%&C5CcF?sCo5jAV@qHTKx|tp8=iQ6)N1v{oHPwGha+)<;4wRR>*UV253JN zl)mT74!FI>!{A1pE3(>$Vij<(zJDy9*ufh?Ss{U=U-N9ez+Kn7$eZF1efEFk+yeeB z({L)F1;X%Oqk1S*xJ)amaGOThP&)(KUt2wJqhve!VFzQQWtgyol?x7Igj;Gbe*MX= zrSChE8Hb(19a=r&q8m{PbAM+%wQD!E3-qBmvA!sLEc} z^xzKQ4j-y+@ms6xZ^3a}I$k-lvv9fJ2e(upq2&;_-1k&Y9zWDI%r6Ru=A5N^N4k%O6OLdT15~ z0RXcBD20mJsc6IqQ1sf493wMJi`1@vA1kZI7cqs0`!Ps-WrAy%0N(+?{ zM`ACs@aAVRf%oWHdJT&^1MKmts-JV6QdCPbc)WGy+=?;?GPr3#U0opI=N;ih90gn4v289WL?FV3}jG&9520&`U20i)n6oDhR7%7;Q(`ho+R9|9s zBsj-+M8}X;>dtm5x5_+oS=dHMu{s4`W*aom^Ju)he5*F+*#(PI)xD01gQzGCUBhtY z7FBwhS&Arzgbc<4#mU0Ptb4W1%dzhIih0%f@7dnskYdx!%nyg=?=sVwoi<5te?M7h znw`hFv@uJb%*JuLS2UoniJMU<>#AN|`tHHdR71J$(adyYPB9zE)F8>pAdt1jGyR>Z zp$=u<iB-q!!( zH&^9|M#cU0+u`V|gKu3!;=ozvwZ#i|(o&!S-I#9pEu;J6Tq1 z6VuLgmH$%J;>GnW|HUjm3}`njDy4iSzW9C9K6NHm-*861@UnXpswYzR7&U1W|7wI) zU_dw+Jn$plOPnJ~U2$$VT{3s}Wh8|W4quc!=sG^U$jz|Jy3G++m>9)psdI1++oxDn zPXxqjPHzGS6I+ikgviglh5vh#o9f$bm=x@*>#h?rJSy;X@*IPU#HwX>4 z*i}ZWbSylxmDFgI*tR0DZu<%pd0#uNE+5JSbTt=uY@J_Fa5Fn=_W-w0d3Jfx@kdI0 zR!6^b;vK*0yvy9-7kNq=Y!xHaZ%e41PaeyR&G|)7&+68W;`R0Hv+^riXRAMzo3-D1 zJ~$|n5-11jkloTKPy{5K|4^WF*~Hw0VyhkOctJ+1)IeR2lmOYZ9uEAj+E`L17SUBt zYJ0>Em($z}U2BqVzHN}_kBMcwsa3r@Hs+$K9*>}NH)Pv+2;}R7 z-`HV9n&Ih2bYcS&eo z|sCyuRefW)?T+g?Lp_HJ7?KVo2j zH@WJHwNs?4cKV=cj;Z&moO{g%Sjdd)>Q@_hg*EPr#xU=MVefxXJfl-h=&ggZw0E*} ztBjlgI(|5z$K2DfvNTyE#6a-b*9TFZgcj&X^ec-;!ZNw~POzx$jaJy+yCo6<)^F8o zOn#_se^70Yw;zoE6Fg~{Z{_| z`^u-T56r(5GfEuGbA4L0qqd*feGKdPTr?0_N~=oG@0;tqFFY?H&2GrFYNT=NdkTQN z7vB5n%Ga>@j@~iPSE9~zw(OTH4O}UE-e$b@D$z6xLC3&K`bB(q7Hsu{TCWI}4QoI||beEM3MwFYM57jd7 z3G8gIQ=KcwC+yfNmB+n5mro#1JrZOAsLvnam(jbVNcLJ`Kb?eG0j$KZ#)qwMaSgep z%~=(Kk)sP3)Zu4rU&PnTi5b`4pk6AiM<_iO4Mz-?+SK#=LpO?*NxKIArYVMuL;zm! zKWZjPd~`x|I_!ENl{PH+evDni`DgU4jC`SIbLLEm6CAcr=J~b;HZIGh-OCq#!R}e+ z6tXeLO~z`WGv{e7ezaf1d0lemCzo)`XdRJ?XT{zXK`koppEs#Do_0_sOMz*=d(bUnKWa|y>AR6 zfAm>cnF(9pPmAr5rxQTj+3q_+nWjuUuCXv$cnD9CZ!-&xE9`S`>({Gh3n_Npldhmv zEmb1{)^JR+yu`VONb<2b7cFZwgK0sT5%SgxNzKE|=(iIeqRq&|&nwRK?`@}Ex%6_C z#;}~>sVhe2;cSB1J=*~7nxBFg5&G2bieGcFZr1IO+}P&45Nz(MN#K%EMPa*FDGKsZ2@snQRD1k_7vEWGu8$BrfT zE^WvQ+b zQxoc69<8`uQjx8h5YBzWgJF_C%~$g3roUp>TvJ|duykDLdwaR2ut)7?YrmfFNJe`^ zs(rnCnOS*&4FJS_Nc1aL`wg$@l-IAhFC1i3Z$wa#{*}fF0P3<+Qn|o#E^{g4(ZC5U z4U#%?BAAwA=wo=>9vZ!?dOpNKu0gojE9cs-%F7p(L`nPb!{xHBEFt&q5!8XqgUFSr zvaLnkoNU`3DT+u5xp!#S2;1n@PQLhd*G#f@X|%tM;Bh1}BA+s&ygygJK}7ogHSX5O zmA9|{K0M?|KJV$~o-P|}z~INJwiG^5#SyF?_x-GSl`~Cgst)bAgi_C^?WTvPHeP&K zl+3aZO1-!iZ!T6dqQuyhU+5FvX56u~8C%e<95Z`+RFv}3>essfADzs1B$b53gXy5L5_|TT!96pU{wUcQNaf_dt;7^~^)0+PMh55%ksyIos zG1=PY+wU8|ZsYCs;tcTXV!^C66(hiU|BMBm3Qz>_iNGgA0~C+}2r^X?-*3HN9?QBk z*l4!+AvS^J_Kd3Y!OQLb1fjcELftQ`jQi`p+8Gh16_XGRI3+PpWT{_D0ajk~x7CTk z%`jwimAEdp*a}}YN%H>i1#alSU-$4y_0PS{w;vyJKU}LdxRqEGMBP2_5HvqhRs`@l z$i5IMe=3bPj(S!A0MV0VVu~lgSS~n|dDD}MKxKRKqJ~x~5RC|0Gwuk;+Aci1rzLq& zP5V-GU$bdjt23gFH?IKad}MNLBK2~fOne~;NJw)7p11eYpL{1nmQ;XkP)EI(d#xFo zyfpdr3)V`qAqdSufhzpSGVz&GwoUDe?LuY{U1O!+HJsGpcr(wBkgnE}7ofiFtdoln z@k1myUlJ0iCVd9LmH2aiGH%cU%)236WCZA^b!_Z!5c#&^B*cWm(CF*fGjc9K`2j_g zNv(-|4;07&bsW2~z{`jo$*mFwg%qRU?j!JbT2*eClMG4%Czl>=vU7lp;Rqh+h4QHy zh%5NVQp7`ghAk|j9Q_FvtjA;W6WGAyG;T+JVco(pE`6|9y z;Ynf(=@A}~ku~Ll_>niAv1tYhi2t6!C^5SU8C9iB@?$q_U#g!9kOWi|2Jd~+Uayzk z1ZS&}Ts#KfY2>{L!SkIWbO3%6rqUCD06eiH0w^8c`y>p6iQp&f#fXTC*#JtE>zU)L z15hF}FV$;!r0dVi+R^}8kUYks>J38V8WV;1&tCBPgBh@=T^Z6`o;|S73RM_!{~DEy z|1eE@(87~ff$i%dN(u;l3}VlNo94hzB$5&k0NKm5G9Y_t6btfgo#eq27498?+YR$l z>PbIGOhjSF>}Fs+(vQxN3G#t3nHG#Yg_K#KdlLB_eSM$;S(46z|ETMlVD!QK3n%yn z20f>bW(tENelh`T$)lM$N%2#8fOnVwI<6g>qc#A<68z*eVBrDKIjkl2Eu=|?aR0vF zT1Ku)Ky(@S!h0_Kf{V|CY5vQ-@-?G?iez%*wCta29dhzf{l6?6*e>G#no#&7%!M4` zKAI6RjEVUQ*W_n>c{%_IF}`e@NWfvVi~}jRVwQ-nS5y^3 z0#?RfE(Fv-e+3%3PXO;~^R{(-ADkiwSp9zr zP@h6+ixMj%8s7Y00_g|-91 zs8Y0HvOY1HP=7AIU zX>b}k9+9&U0nZymzKcE=WlVvQyZjbe8DV=j`^u;|a~0{2^zRdDL#%7Dm3cwFR#w}C zNvq1_qQF7CM&{l^CQO}?fu2IBA7K{OF4-B>WOnxJ!<}q{Gmj1Pd|d6k8m(Q7`o+vQ zjBIc9_RgN00HYN^;a-8__kwG^Z)EwOQJg=F#KSyOx$`&MB7A7H{`g5g2Bw)N$QkGO z>}XEQrz7*Q4#HvIO+WHqj?7W^PG!yVYaxShAW(btG1C}JCQsj+#WeLZi@H?rz6^G8 z@myh&2~_$53#dlh(r*La$5Xx}CETc2TjHgyNU;by-jhsy+wjnBN%z6u3b=dSDKw>C!&z4D`${- zH$wOQMAj{X70V@*L{?c4;3xsHj7I-S{$ULy8m6Hwu95ZRJCDB( z|85`n6g*`-6ZN~*?-CoZahZ8oPL>UL%O#cM)utk-%~c+(3hpZXBWKt1rffTmT-ZDjj(Vx+MmJbU(y8ws9G_%mb#yq|C%uZ;Sse~*Wbkl0!7 zkSn;4wM;jjkf?)PNqfjqU+{f5%B0^#tF%mKT4B*u@+)Mhh;q~O-VfuFrBC`|%tjB4!% z_)}#e`3O6+dN%AC(_^yZO`gJb;8Hkjvc7)rYLbTH7{-h1ixgRgeXgqsn- zLA0@yfNQr#N)n$B0K;++6Ago0>I+Pv4KysQe*E_BKUrH7w(l_9NiXJEd9z&ibh-5u z;K;q<9>jI1 z2=}i2oZUN%TzN0sHX5%o-reG=;hx6ThbnRPp2kLud9Rp_7_lokD0m%Xc3c~(XV3v~ ze^!6?o(*;H_zzV2u7`TCt4}uUo{J~l8^hCLUIzSuW$t3mIsV{?pjVE6Wx z#l&OpEmncoa9xjN6hg5jyA!267HhYS@;g))`s|9q#>A!Ymw)6408@4fIj0I;Tx+<# z^PS|Br--}5?cH>%;XOr8RiYW-XR?ejS-fsm%8WcpALE+%p^dN#uK1JuXS(P@c zNFD!J0>pPz8j}8D98}L|&qdd&E#r0Vt9nmM$;e_LOm5&J2-^9#J%-a9a(O4cRSWcz z%>^=K#{*(X(aD|JU%O*6S2Wwv^Mf5^sxrwbU3&(&Lj)M5uuvSCi|>7aUoOiS@gc0! z_OWpuN}@4=rFePbD-Z#Fy1+;T(jtUDg~M@-{JL3N1m>QG1EwPS8Czsw7(;<+^yg;@ zboIk$=p=PK#~Q1zzM$b64&mb}QR-TrzrLa>Ye)100B&MioxE1+6iOrGspKa%)yvW1 zE7%Q}3C7;*0cKPB(=ZPVMt+nm8}RH)q5=dxsg*D;LcdC@%y4sD*Yqsxq9TwiL;9&! z38P6(tC>r4U+^W{DWYAlaYsK)d{7>`s=eFAjCJDX{`low05l7>L>G5jde)C3Zsnt< z_>x26p5AgD=l6+&im}h;EQ?7-ocERkn@SzX_xf$7PgLA*fOw$kkV{hhkg%hn8YrUv zYDo~2_%^{RGBjNoLN z4C>x;wsT_CMNi)Gn*W7RaJa==2RXl4zn>zfh8=C$}NKRQdNGTk?`+ zzVh#}b@6x5zaPDMT?m?;Izf}#C!GCuF$vt|B`>AB=6_BXOoqc`>A2ALo z$&>#COK+0FRTwVn8jdc_m8a3NH6^{%rqG{@RY4c_)T|JmS^ z{&!O$_!fH6dfPePC#$-O(RdFPUI7s4*qdfd0hYQJ>PM9C3 zh?GFd{qLs~S(%N<1J4FBKc1`Ow~CjiCMtFMYP&$S3)KqvP!|vbqRhYlWZ^dEQ3ctb zh=3`c)ZcYjeR{Wl1Co<64B{;~sY7SMgH{P>G~(JC_gl2!TZstl*oq|6b9r+7*4o(Q zMwXKV#6rKDRuQ9mMSItQ>m?H?gfo{wA$&6Jz<(3W9^9^A`82ZU#yT@N*&!iH96^B!s+1F4C5Xs+F9K2Wg_9`dp3yF|e1+7FticVR zl>L0;LnD7|rm^Q@gdy%t1SgHGHUE%V#fMv^x2Lf3DGI+9=GTt8l&iy@%RWG-ZTE%L z9}6@d>*|E8DsXFsvRz%dEMuu@MMJFl6=i&SNGS|aZ;U?^_WQJQ17wzfaa0oUARV|! z&xv2d@2j&{y-yfOc4UBo6#e~m(YmEmk9W9L`P>d&d`2=7rF#Izi>;26?u$*Lc#L*G zDKDtR_4U-WKJO_RyN~IZ&ESwZq&Pztq>z0k&%a_-T~7y)g%>uRs!#Xs0jjZt(5Gyr zwL`}?{OWx7yq`%$HVT~z_RVr18fbOu6*|kEwE-US`LZZIzVH=+_*jEPZH8`{9h|c< z=0m(m7=gUp{Nmb!5@iH`J^WaMwnXg~_BYITyk!}tHkNg0N18Qn6-yr-*qKZJEHxc01BPCgfe2{M9{macKoDolz^DlJ;!V+)jPj!PMrB zY=8HLw1%a5SB=v41+B@VBHM~mYqh6E>6&_Mj|+2$CH*wJH#{fzii0_iQF@)FRKW&% zS$f-1TdW5WX0u8GB2)0!xrfI47`cqxeZi@LqYeV3F?Aa#nJ%#V1vfQ-&5M_$i)#X0 zxe58(qyhh7_EgLdV$=M+w{aNn#^%8;9Z#M3`-jR(Y=cqE$ihu#uGF=h&eHk**+Qm# zBVDojsio(W##66N4toPcY3%q9hvjM$b4)nR#=t-@Uox_$U_0W6CXbmQ`?+$3CJ|2D zU1{F4Tp~q(xvWPJAb-q;SUZEo{0%QWmXJLr1MC@W$;w8C2S^jbNjMHEon+`))K4xa zAVaWm0o%utF)A4--g)KX0R0t{x1}5!@5S=!2aC{s+gh_)m$R^ABGTPRS8ekvpTnya zD!+}#u>04RHJDgP4^V^4JTW<$^!+Msfs>IFs|p9QM&kxtA8{z_j$LHf?5{qVN!|o@ zp}zZ>E%FU@VUt6A$OM zsW@{uXLS7A@kIn;Kh`kX)V0I{?rkIRx#$4rcfDS2N9HQ5`hey*iQ-jr+K*|5CHaad z&G#+K7>zB*>{2(Sl=8B}YWR_B^xpA#|J1V{ip&Pm6**L97QrTt#AVz=TNXurO#4?P zjF7R7G)d9!-f1&hvwjtBl#W+f*$r01Emo56-;IM}x&C2b6o#o6d`*+@GxBTT+37(L zRPBG6 zQ_%WTdcVGfb#LaOjDgvwc^F2@+KBq8+lyp_ko6mmk;EI54EsHJM|h(pmLH3&ep z?+XD`iyzh?8;t~O@C~l}CgU0oxeS{OYcWb!j$P~u=lPDfGoUwr*t(v3n)OXQv&e%I zbd*w+B`-Dlr5a}`9CW!zF-Sb+dD{r zq6)E}Y+!sem_LxwD?l$5RdhUE+%KK6k=u!_t}gbsTATv9N;-F~YM*X=kPyC?A&_}* z=?YpTu_5LN^-S<8uj`Lz2z6VfM|7ic1CKN;+Pnn4c$Ef}hH_uXR#kKKAv2B3^1wNg z#m+Psx`$8_{wZC*lyL;$bGmC44;XJWxthu0?_Tjd=pIYa!OWHEx9h?V-sp*~zCdiE zx6|Upum>@XrEYAgHh$Iq?ssEGG&b_q6cQg3z`lRr$^F95nc#>To7GIpmD*d9Z`2k1 zsxek%W@NZu*5fd_@Qgkp#z$vMNlfxRw(k^i+FvsQSf33}xz*eWq+eB7 zS-di-7OO7l{jDU2$?Z<_0O>CR^<#}Tl7@nAhvUIsu?9a|b#?ukF) zKgo8zV!##L4NzK{vt zvy*%@f1Ww!5o56o_`Raxw0A+iqX<$iPUCm47XHH5v&#UrB0im*-I!dc>*%?^*_q2P?ut~aQcG<#mNhnB*&>=4`^ZlVQNp% z`U{xw=aYs0z2fx`YA1EN8ezp@>qzy3)IXKM>h?}tG1FtfV>Mwu{eYUC90azQCe;;M z=!W-7&iC4e}C=FLf+ z4nZ>7^*Ps@D9>>m&H+fEf9b}M#7{;LyohNQKD)bs=n>rVsFfQCt$NdRm!EWN;y^3Q zR>i(AYw_f#JP+cObYF`9jq|dC|0+P$Oa{R80XG1qU&hw}*8uMR?~3QYvb)pJx4vLa zk}n6I?~nHwuvz`Dg#N#N=zmQKvnS#H33@w3{wqTx*pVrW>CRJsj0f&$U}~e8WqXI0 z8)3a=iNCsRXJ+3U{(B%DJog^Y-GTO}AjKyY-o^|1i*G@c>WsGhl(QEH#pAb`(3N|* zzK@?(OUfS(-AS$YKe|zMelNyJgU9l8Ro>LWp!lUF8i9M>-+jdR&wRUn_vi)b#Nfz8 z?r*xr1q-Z5!<=D*=K(&iOhja4zJOK<>jbqN?n9r*{s%oF$W8_-PO=lwgi(N|v|(@$ zwQ!E@cmBho@#;}S{l_W_@S`r=?grU&%vi+NIO}(tOT22EPC5tq&C3!)bA)DrQ4!?Y zMlP|>{O)lS_Vl0UUWSRjB5#s`Z;b!7gZ|_;H&gu8AVx#I0l!z?8ht?v|1*X@r~sXy zxpm+s$_mv;%_knCKwb@+O2#V3vBlOMW`zuy8N5P<6V7WtJIlofPRY-JTt|RDfC@*A{w#Da` zwvxUxD~?4mCp74p3B4cusPk)#Gxu3-lE#8%86i>@`MR|vLw<5H(3aKJ+8~RFCJqQ8 zeh!uT_mdp5bse8eU*^mmft zQ9vTFbb<8{o~r^2Q00#vuTuI{ z?WF8;FvIqz1^TiQib_>>n%nj+;QoYCLwuj^2{R#>#keBQqiC3ym_e55?$E@g^YGw^ zCL~wzacz%6%)C+F&So*KaFM!PY$nH>UU-&G8?t}lTkx^TSZ#hCFAP#EEVUJ#um@Z? z$BXkzlmiu={O^%DIY?x?Qq=u1cx=+=rp(}E3)T<&tucln+2AzcGcd`0K0gA`*SsK} z8Il1gIRDbL4>)}wlXxS=8kt$$wHYxSS8}RaBv0r_-5cw66CQhwBvwx-R=#+Er0n5T zd>t6hqs5tI7fAX8UrEF`!@KO?OD^WBh;+QP2R7mlr2 z0WLB53g4wudO0tk8LBT>VZoc7-=xF6FBIKNt*z9KeuJ3kv!O`?Cy)iyvdLlL7d#$- zemrDZ1V%RgsKx^+KjNJTGwG+Xds=MYoN=wcL_YSzbzR*VzD8kMiyc%DbFlhboP74~4V|)sMowPcJc=)+Hj9~S*Sr=K_kOFU z(LSVO5eYSjVgIZ66d9B{78ST$K+P{UZXZ`^nl5#hR=}$dSf^;f5QNk(*uW^JPA^1I>VY7(ROF@j zA88Mi>hJ8uk$6D-RxnoTiBGbq86lV`C%Wcgb#CYB_EX+NW!w7S9#FjVe|<(0KAXwh!AK;z?PDwFizrt>wTM&=6K3M%S4 z%9m(?EBzmOM?kBcmQ#}8?;Zr%i8v*P(oZsMpSQ|%XN{r|cN8731`F%0#7rKxq;u^o zMm26vTsc}944&i>vZb`$o6PZ9rlaT=543V=Kd;_q8(+D|%D!fM_mW23qjhx0h$T#&S5fRvo}W!8#yFl#4&)fkpUpWXV(rIMwQQC9z^|ae;zsi2;pkt< z8s;Ev&Tlk4ig|mU>E8`(Ybb^NlHem}i_Z=n`JiZ3HbEB1RQxCRjo58gL@*U|fFk>U z#^pe2=;=(Y|91ly>VVnxNgb0dFrMUw(?wzGBmt73$H!p(5zPU5_Po$VKRlskd_qM) zkwawh5FnLfjhXl|ld2%yJnp*%ar+XT{pU#KVb7>^L15GDSd7;5*(v%M965&_al zAG&+S$$0E);CseRA|=2l6D6QM@ds|=0_AF+fCka%-w6GNwfsMwb*AEn0HP7_cpC}k z+WkNw@W&|`PiOg8!fTSp-Mf8(Fb<^obr&sk$6iB4N7dq)6^56bl38ubB??H**D(#t1Bg)Uvx;ScbCVb72B%SJx+n2Q`v;2e3XVo7$X^0X*OadUV zZ{noo3FOl9#uaN0rbD@N-OlwY>ZW|ZjdkKGY43nz7Em!Vp1;;XR_*ia=aQ`w_lRD7 z&G0$XPucGaFEpovdl4|vvH__1@1ns(qbQfig^(bp25=P=r;Pj$X0LLMFkj&U!Z;m; z^oY1Lb1?J0z$0Fhh>sgn!!VddRuvEZI$!aML0L)?fT>WY`wjj)(5 z2pk(3nL2WS;d)b)8p59Ik^S?TIo-xmOk&uw*I4u_m4-ZNaM=+{^HO4Fw__~Q8x&Z* zbO8o@n^=Wya$pfYu7QcnKgeg=T4^|3l|Q$jbt(J&Mc-I==Xm>!C;eN@c_Q!3bfya~ zsz^m)QzQA@gv(qto=&;2AYW4=kv%#xo(UX|k;v-Legt{k=OvXTd$fs%JzR#9Q!0@( zz739;^c|Zxd!RbhQ`nwdP58m*sF8AV4mjrvzFM*nxRHs1uVnasZz+8ngq zRg6L}+#bW1ic1fMO+T(T(qIf}hL>*K!yi4M+6G9E-&knGy_y_+u`{PDg1O51j%0B2 zRO!D=a3h@Wve(eFMi{J~8+LT9VYd7Bdczd%i{0A6`*Dp5D~&u?2j`5}U+T*!j?<>F zQtmm;?u|knBu_+s(+<|Qz0oo_DeKLQD05btiPBBB(|{$=f)S@H7*P&oBj}VoXz6?V;c{YN;OhmD7NV|?C8Qzf5T4{KnROCz&*?o! z5bf2L&60c}epQ9QOIDu!yR25BkHmv^esdiwez|@HC9f^cPUrb|-31G=T^huc-S)A0 z34+Q;QzSAPVo!|?u7%AD^G?7x{I5rfY5gBA z*F}2kVw^+Ko&4RjYGtBbJjzL=tsIpgw#HCj7I~p*tupkX?r)0}E>N_8tjj1pKNuIS zW3-}b#l_fiD~s}S_pDn4gQ7v=YcvD8uHn32NP=MlJZpGCEZ63>qLF*4m0ADWpr1UI zZ)#Y+)~Mx z2u&4LRg&l3>1^}Xfy1(H&$bG-MK^=CZEBRwNEihQ^sL=W=dP<0Q(k&lqrZLKRYUOk z0%r%(Ab88ypP|YhQBu9ZR528W9lxxuTs5(XJpkcxF?n zT^51i($O?O$`M6Zs@}40DPLXN2J&!pJNAWJRE9ZVEIq0;g7uP~Za}+ntZ(O$iEfiR zvB>h~=W3-l_#RN@G0&v?TE8o2mYA9BQzXp!h-u9FYqb*g+sZ_t_8GLWK^ARkZ`)1e znSf}yn?xC~Ih5PsnUr_$bk7>RXVz|EIqJNpEzf%POnzQc-Q1_09`YB7j@;=Kr9T3X zOX4e@R4{S!rrlCX9)w?qu}Cbj^FKlOhFmb^;x6d=oS?M1-Tce7y5I5Ap^R{sLQl>W zpC*p99v4CLeGaXAZ*yri*mXXb>HCx-d=I}*C7%I`MT1vcZzS3$zsJZFC3CslWQkHK z>3)Cg{I>gbAB|v>%j)~scc$JRx5s24(1+dWE4+{>)*7NRlq*8fK7{@Uc3gQ%4s$pQ zZ4VQ4!63Y=js@wD59IsR!2lCU%$@>`~$I z*F;5m>s<0yS6uMF_jb}XV(n-}3!X-ps|o+oRS~0=5tA+MnpT!YnVIYL?1gZKAS$ex z?DbRc+V?#FTJ2KTg3WhZ*@%nx)clL9d=-=*eOufMUfFyc=$L8`^etKs`@=pe#6OAg z=UG$F`z2eJev^u;jH4|6iL2EQwJ~JKJC>sxn@-nD0*rSboF;z%GGozI;OTE(+`?h7 zn!epfo)^IJ5G0)FtTnSB^Z9|Sq=V;bawV)!25{1*g#&RZ%dn2d>d-@(K&p_uzA+wL zNhcdp!aVhG)@IHX=V^{b5$kp-t`Rb4f!NMD9Zjixo3{mynetD#iE$Y|h!WHl$1(QF z2jCpC7&j(a!v4Z%8PHYd^i+>IjZ#-JL7|kxrisS)^AAoy)w=2Cs1xY@t)qU1Jw1y{ zUBmuvMZhn1JN^|(wa?i`I~k0qXa14y+kp*IM!I(=gL_nVLL_XyTv5{00~D?&?SU6a z7tarILhzaPP#)VS1(qjqacmS>w*mXEdpjaN+O^R5+m~+A9yCi5Xdf8dYk|kwSOv41 zrIbp~DC|gOkM*+u@i>YbgmlFJ|FI|mbv+cSTv&0==-$tWCi z!!I{-FcRSwx?##OJ2#bC zXxVvb8$tEWu=YdHM>?Em^CKrfD?b&G3sN;IcX?+-+ECKz>@}-v?$)2%Ui^Y(eUsBj zo`na=mgf${DSTK?Ye?#+_P}Tf#MLxMhIJ>n%J{}e^fSXTzw{;twX8XXSJHBwYtdb@ zsbUQ7SM!S+2{-&U)ZEFHyEAakbHxIK)?y79%ZfHTHkorh%K4gtn4XJJI4!+K zgcD3){_Qs0PjLB$UY3p_LrA>YI?FO4D{db-b%3N3IFFTa=R8Prmw1tgz*IZ4mO5GUZhFnDDM@0E04u>*l zOn;U|Y^JW53sQTLa_2M01@x+gKwtv0RW)9fC9@n^21Jqah4*=QBqH@J z$Oi)_qo|B(`@373)%y21h>+&Drv#Y4G^jrqibOXmWub?9Rd_UAWCj{oE`5Dq?tbsW z(2%aZoX%I2)$@7rwNj;!tToxZ1j4N5lLI}xZY+0^h3rw;wWIhk*qwe-oXuftH&OP! zNTWJr^RdmuTXXQmbh4Bqf&iy&?tpZpTk-j^1qo+c$YdEb0`71WJ;e_ogH8b_PfDar z$Z_xyi?H=2i75Novk?)GqT2zSDMZWF?z{JN%9JYOjpfU`WckBDA>Wgli_f=8kCRf8Sn_o|jn_Gr4lk*zCE+@GKhGMW?}ZMv++;g_pV%)0dvsU*Wu`sS~UJB;KAY zD0oxG|F=v7n7nqCIf%&X?rdT2$+St~lv6f3S4-tGWPJNO>D>!MW~I#aYDXrXU%_(S z3zk{u=z1wJpT8T3mtB^xnB6iVmpOE=X#|PrEx`rzs6iq3Zqk~ z3~?qvlAGk}QM&k2Njn74$W&mTcb#iD`g+(aw{KJ9ICd!Oi`5Q+HvGPLV>3KA>?-Nh zZYV;m^V1Oa2v(P&TakBIc0qV;Fi=eSYv2lO-~zp>ZX<(@z(0g9lttkiVOl&$r_SYP$jLiAsC z!||6%GI?f;@XP9Mig)5{kCnFzl&eIiw0jw7?7btkoe)ZTw(Fi%86+$wq8fgnVI! zQLJSTu5bRDD#0-jb3KeyRyao4{md=}r&WGqK6~3w6lXb4EjEab#LeE2#9YA%Zk!>+ z36lTSvdHu}IV16F>;WzJo$}k;Ec46MHU>+iyj)i$0R3}OVy%AR!c4FZK%k?vWpZen z4a^I&E>&0Wd&U~B)}wi^R3IjTR!aJq?XkP^*+2P)4(NP|Ll;pZzh zJ-?LdYO+urIo;~_<2%uFk9uxh*yf4T^Z?9&Uo;eYv6S#+>}7FC&(N=A|M~FMJ$Wd86L}7$j4tt)=$T%$#c8TPPyJX z35viF66ydNk5sH_6CkFJ{?G*PStTSvU&qY{U zvf{E0W$X$EUh^)Y#=Bm#D)L1Af9$<=RMgS;HY$in2+}P>NT(nnh(iddlysL$cOwEL z3L+9CO1E@(O9=`HNH@|*cS+66Jp+8}z2A4e_n*7gUF-h-6lXqjKIiPS&pvxU`*~!t zj^s7Px$jWY&d74e$ykd`i0yJW--zKYbmCX?}JOa0;}LYl)}@4Sh^5V@=UtI@?k-JzP^UPRKZ- zsgV9%K?bh9<){olktSF8qWjx@(R)FMYq& zFTYh$sUuofs-x(!(5iwKFVE*=`G6Q+qsWhkKuN1|(J?Y=!ei<{^{?X6L2#&&C)vM3_WGe!!SV*Z^-T=&@B5 zyX~mVFjG&))|EcSu?iebzCNzIsjPRQp#jg+Shn z_jzP`*FxV3$3gOYa%~N6~UJO!hjfwS=3*iyDJ);?vT%YyH)hxsujivLf9s6x`o1SF%kQa{s z?e?Fp(7%6g$-~Qp;#)jJBK-m@%Z8eWRqcjcG$_l{=XJfyLaK(Ya(o^?+=X57D#6QG z{tZLKHJG%bgy)QLave?B{13dITu8E>QRgfVc|SYWh9@v!(U<=T zOn$=9-GFnf{1wbR5_D2G;a^GJ+@eo_tY;C|^`vd_)ui?HdaaVAsh82MeiPTEC5{~m zcNHT)yZJqw5s2hAWS@N5esryx;O?yEp34Z_fp*VG5BjopGvn>|3usj!$PNE{^4D`z z+fj_rPZoV)_@?uiWooe~>7aQ^#&O0S!yaH+44G#pkL8uhR@j#ErSfOR){+YeTC!{| zP!OB|?r@O#;fnqR0(kx(BL$>nkh!-Wj-b?WJ@E105s+^+jORbNNP=mBB-p>>lB>Kh zG7NFbr2qt@RkT0&0UALQAozcSwf-jtnzrFx|6ME^&{t_|LbTF+1)ZFILj&f{q_z+= zZCL$Jstd?U%~_mPQB;o;>vISMi;0f+H>@5Hv#5l-nk?+`neazKOvFPjOY|{ z=XXV}KmfXxSnnM;m#g`O?mAu!q(-0unlKRQKB%qINg&Uviz zy6M{gl2PZ|)_Y7!WC_3^C9~f$z$61i7CM`1?8A29w$34u|DH{s;2YTIWpM;;5EIkY zD}fEAhVQ-jJ+4Z$NuLr-yKCyXCQ*1k`Rag{pmp26Z<`RqlVu zOZ^07VfnZg13PRqzifhr!ts5}9*&@Mln%Pmt^;sE4#boS!wkjF%;ZJ1pZF(R7i9X1C(s8oF+4+4p*RLV3n0F+g)*$j|M3M5OdnxHv zVZQufuan%`iDrWU&)5<~^9$ZubLS0$b0ifyq2I)gzV(I)%b!D2z`uWh`TBPlx6wNJ z=Xb(vCMfn`?bVttXzhzAX&rMV5W)=dbV!@K5gy4`L<(nlt;-C&cnsQl1wUK~lLR#p zIDf~leJ2o$x9IH4KY{(|`0Z_&(O7o!SKq6Kg6PQDsrHwlN{W|8e9^(56Iw&wTfK-e z*h>GE@^ndfEw*ebN+1(n%a;iIGqf*R@vDnY42`%+@df6#szi=a`N-t_3^*~i4sztc zto(37_QEB)@Ll&=+AT8+^SSRPPpWh>SqP8XN+V18kxp|uPj7%K1wfB)-V1l+!IHx@ zaIQTmQnRS_seC56*~4`uA9c1>t_w5ud2Fz0Ecj#WuZU{zGhFHN!seVe`x9@w-L8&J zyzOI5`3GDGous;BPsxausyTw51){dE!?v$eT7}9zs60<{J}H80=rdx#ntCnhQ6J6i zToe;KTg*NUW=O(DRQm3rBxD;p;r@mEqDP*E~+SbXCLQY&f z^J@Fs^)Ds=0GcJsF&w~=?PT#{k@)%P*Pj1~`Vi_X&?Ei9hFRi!@<9KyfjtO9ic6p7 z9qhgx4c$iWU3m`k=Urz{Cww0T96YVW)zf0-+`-OSxwErk`?segD3|N;k|W)k2B&Xi zm#{$@L-54!`A7krlZyKc4O_V6((k0-9p@eWl30i7)9-$WWp-q8AK*q`)+l zinT}BktMZ^K++!RM99;z883NAJrRHZgjszWTcsb*ltl2AXjilL@tMu!IzuTUmlg1} ztG6i4L;gzK;v=tTOZux6tiK+=*fSe-ts#=Mf_whcaD-FlLxXr>GR}d@JDS=_D6>Tk z4!-qi%?C+JY_{|k4lxg?+349FzNCd6QIFI-{yp_ab_H@ROVMqx(R2`@HfdzdJD_~s zPf^N#4uX*9^pQ40_QC89$dXQz>y{l4|0;8qo#BuE6)8zyjE-@44bzM;8d!G`ZW$?tR5d z>_Fd#oXopt9}(fc?S*cfA_~Plv7t5ww0O>3sAX8>kG=8%^;eYFP=b7~gs9BafLVNT zPK9xQhRk#H)|9j?1Lrft0TLHrU4qe3;TxyFk?5v<|BH_L9;T->fuoeL{j067jh91A ziBZc>PKJHN7uB$iT88q6=F0fZ19sp`y!pahaQfW+Oqp1tT-F;& zbk-O+ICtRpP; zQHX-fDCjl$0-$M4{D4|oSpwZ7VQaCQxc3#LqEu8GbJJ0=F>{dm1D9h|$Td_zasQFp zMFs}&Ph9;E{)uGS6c?v#sDK%=OFb?}??tGsctHAu0b-Q1UwvlkIuyw*O5ttq%MNk+$9% zIcF+c>~9Azf+OVr1jJRxz`C}_*I#(h#J!r$FYFGbSv-;dyuK%2Sm3hH2d%Oyxt;QN zVJv8LO_g(m;E0?dtP*1B)iJ~DDv5(iz zscTm*+lVkG!MZcCWPd$Y%5k7Jqdw*tHSZ#%jIr3L>wBKnDU_l_!MsMm3+Q1W<4h`k zy_~z__jR+@X1MdnDnR@%PY_gp=Qhu00&$fh`mitFUQv-Z?gs?^NsB-Hqg$T1c0;-4 z#{~_SBP;NAARAso2gqIgzMnI%_}XDU@HO4g>Mk-qG|dwQ9X+rktpZb>JTvDG{LgL* zGGZ`f&1nc2iDhdPl% zB}p&?w<)z_E35=mcED(s;e)l@?xl)=#DQ$Xc=ICEwYkPDukampPc5c0wnm%YUs}@=E#^FRrgd)$8AW+3_nQv*@OVS4x}KF}x&SsEjQ(GlHdLO|?<^ z0j#y@lx%zd=hNf8)Suh?gT1cxA>JWuwvPpbv3F#=j%O3$jQ6K>H{%4$KFh$h7^#s`O^;f;Y+sX2(Ye4Y8#qc))xHIKJg-o-6V z8a}ciNKQ4&pbWFsExWWYNVdLm~K4!ZS+SISY54Q2vW|bqE`*nS#P?ir9zuxU4 zsQ7HUbh73bv{d-grd=m4F{(!yi<9=&A>8GU>Ytu);pWfYb=$`yUIoi8F1653>cRUO zCtu9tSod&O{JVEl9R6fSnlaU>{f<6{7d|aHE~@*?G7&?&kER0vt#zPbC1k#)9$;D& z90%5R;PG==I|$-!)=yWfKEszMA;BU{fHLNRqYEOfHZ9{dOCX|4}Ff%`0@n8dpa0HC0wE>U(X>8Gnu+{MWwNGW;x*ZJP?+LGjKTS-jOA#tf z+Bjf}*~hXAzNeYmaVuBIKDPayt^X-i>!K^39CPZH+-#qRi*GxvROW^l$u(BX2J1oS z35n)fLmORZm-(O1D2CYp@BLT1J_ogYf_FBjwLQ>6wcsco22G>}@QozvR_LZx`3Iey z{~#Iq=6JH#J!Lh^x0S^}HZ%jG!6Re!c zOex@0x>>CyrVLWn|8#2X(2rW@{<`!e|LF!(Cn30uJa|XQ%sJ9iLO5>Wb)-6=FlpI) zm}Z0>U#Uizz$P~qtZZX&tet#({3kD^kqb%C{ZN58MU9x-)6Is`;0nO){7fDb5K z!azEWw8(E0jiS+FdyJ#9SC(FJIc&N&cRN|^-edft=wyDv_slVF;ojG~HypQpy?x$e zyRWUuL=2geN~|sH2+q13S9nraU%3)`>+wS=4Sqkx2b)0O#D1LWC)}rpne_r~M+X2{ zJFnkP^_l(mA3d~R@mezUudnV651cG&{4A^_f<4)ZBTTmh*hUi)-F@EhI>g*Gynv}) zbjbc1IDG@VpJ;eZ8*C^lENRfx2l@s)?t4ZP_=FDD_4RL(?a&g z5D`B5_YaC(^jr74%hEF6^pN(d8UJk4Z9_I~?t(28ZJ``|0oA+EFD$GlKYPBxe3uIH zpVP~51?|6BfqAo{W6sy0EomEG5Vl_DI}2Ib$<4ouEGflcq{CSc0jptgRjwL*m%d5sm=QUUNbYw43?2zJ~W2$pEBq+L^_VBHlgM;Wt?>I-L4B2 z=6~@(?f&H8sX$~!_I=N)^J=uS{+W%n#`#-aR z9l~$k-@fu+2-|+rfJDwnc9a-nF*aC48jTzvWeS{$HONBco03(+XF)}_jZF>TI4@els*>2Yz}> zoGI{s&yf!DU2ZRy4)9T;aBZ`U9e5-G&a9+~1uz?NTK;BmksU|p_dIM@sL?->1`<>B zKG@YjNbSEeoPj2#3%agt`2Wy#{V#M~%z|_O)#Ea})&v_*3v{n`f@C9FJmLZufF_ys zYJJxEXdABI5B+L)Ha~`wa|JUHIFI}L+mMt!oW!d)oW%`a)K&^c?O*V{Ora?VL;g1u zgrL(nZZ>aN|Z2j=+U2dpIzMF3P5tNQml0EBmkDsmRH(; z)YgIR@5oS$CW1>Opqd34!433B#4Go20P6=*@qoYO!PVbD=KBA3IH9Ks(6L^S0v@&f z|CbbySnN90f_p8H0I}d+K?8I!aOyxqSva*5x&k<|2e1+6odC9ILZ1H5Kh^B ze@}_&25f0qi2h;OU5sDb8F}dsaPrXvniRUL=p@<|zXD(mRrG$Hm3(=gJraMH6P12X z9adI7elX?pcd|hq8Wj}>3@o5wF^BUM2(K3wcX3* zCGlUO1&A}mIIA`#wqEwgLr?lT5@=^#iHs<~6917@Q)m8={zP$wh)kVx=bD`PHcyJV92aI4VWvi^ zD`X_o=fyobRe|Sf$^;#*mhbUBZtxD$~jP>apcJR$qHM5LsKZRj+Nlrk6bQ zYWgqIvA{^?P`?rD(_9^VlloaUef1OqiicpO^B8G zP_olgbDQ1oparOG9WN!f?S+Onp^596oQZ}&HoBj-ndEtnI_Be@c@oL%b{}ALWY9zz zlYL+!ddr#c+zRy$b8#K(Ku$>I^9`J69qFf7ux4_2n;0_uT$KV~A zA|Aj1H^mzmFRw=O{=DydkY}8+==6+!4}b&;Ht}m-?kxf_5`UP%;t!F6$|07IWY926 zzzlgl7|C~Fl+?<29Bz-Ud>LR=ls-^;-C5z#{2lZKt&;Y-vyAI6?j?iPR~0CNGAxLs z8gV$m0@HF)e*`#hwWkO5w4x=|&O}p>Tfsw1ACY5HgCUxWa-L)mm-I#t@LEGX*j-hKl`CC0Kd+|?SJ~gt0x+*9^Qwu$h)vQz~(ZXXU zeVhfkE2x->kdG==fGT!!_qJXUR<*&a9}143sKM$d@#-)EhCG&s)BorP4SDvPIe$jS z&9WC|`%}R4Fv?dF)GnU4`2Xa2gcuueZ$RXjEb8>^!D?tYjUSqiTeb)>NeGacOV>pI z2wUOa{sB*mcQ~70&J6Kq{74R}j9LRy0*RzL`uc14Suq%U0Z-|36%$+lN*QEK@hPm} z*{v8c3Wmq?_)Vjbf7L#6zAkY2#ytU2aoi<26)Fl09KLjubn_5-5wqJj{PIB=sVt80 z6YzzL;94QNG-k0*L>2YA>vg3xat97Ovj}@h>Ir0@cx#taACTQfI*pEaQq%{cm(~0Z zivp`3%z%XI7igf;2JX;V3LV_F1EQ)spMw|(aJoLeu7n&PRyEc?+dGUb^8RCtIxs${ z$e-@<*>th~_yA4!xx6D%zoL|t=spglh#NlO;LE@G(k#>GdsvoCo^+IFjCjHmsp+Qk zLn9uD8{7gotImE>N7=llhT?C{eL^-sRjtsYK5s8z^r(%xq2#*^;rScRU-N^}&F6;; zV(o(Vnl208b`WO7pb2fe_^!OW>GuUEoAt3cgNTb}XwRok@jniMbk9r^fHHxm5)*B9 z>!GLTGO=zW_RmMp=>k<*NnW|ypEap| zYbNRnzpNEQ_I0JK8x87IeE21&x_m^|A@-qEZy8X9M(Rfd(ciJ4;rVWKK7d!l4>j@k zzIt6V+kj|>WlevhBZ{H-vsX~sfg9E{l3d5!1FbI!OLaXKgE)!DT?bfl9e>399>2gL zq9Vqy^Yj5`W}UGSEJK(3HR98&Up7X2zypFM18@t$01+zsHJek!tD^^-(mm47Yy0Qp+#NigS+>{DQ9Jp02J_@&=k zejvc>KKBRP-qU6pnYBlnA2-$@K3R#6;(56p3`SFaHLWFcJ?7DzM1E?8nmgn^a{Pc* zi8nue$P)i~qsHL8?qfg6Z4O{LZMsXT+h__TLvo!^#qLs4gl)4x^T zp)-&y_9`m%!^_{?_4zo!$nOGdD%SYQXNYfAqYE267=uvZb*GySa-Y!en5cKEjMC6m z_3F)`S&ncRcirP>vy=3i%vNxZXN>hJYSW{p-|!W<;|m%qU+X=m@6*3DDIYEEdB`Zob)7r6>+QOegO|5jyvTH}T(RY;D z>&c%eQ=Oh-Ut_dp1J9A))$6Hc27FPn`lBhnG#mQ9%QBEpmG&-oKt%HIQ?RJ?(FN2P z&X`A<%5n1x3Y1>G4zYg%=7-ej$qOnVa@Wgo};lZjG|+>5v}J zwG)ryXdm3+$d|5(u3O2BSCi3mS#QugD@#V$dUZ(GR~JkDx+`XN7zjNx1-J$_l_Xnl z4j=&{qIp|X7IPBm6a=$9BWw=>1npoxYHpyT>HHYUv85_|)I)=vlx0Fp;A1fAQ3-Ct zy3UUiMRSCu@DR^6Fm<(1REJ#9Wv)!x1@+k@?tDC+_+xp3UZ!g0TW*N7Pa}4BJT`xi z9f^T}Pu2cT<~pwHX&Vc&WJjEV4S0$p`NH$-R32MO4@&Q>+HOL414?^Hj|}o$A1yKb z>TdVD`i^zkiR}t8@VX=zlWseREg0;o%E&PXFu(d3qPuI_ZP47<4)Ovl0mGbn{tZ0T zvO*Ruz?1Lx$>(C_ju=O;bOy+*)qT5q^S&e4WFo%z768Xy7lt1PIP!&kd*&X3BiRKL zP;Z7syhi69C`g{-1|b;+OYA3WmEwi1nDr*PB%$CRn$Xp&NfLQ&l0Bo^ixyBrYemj6siy=IVUdEXu`v;~;eN}72%KL_;LKDE{&UBQdX@jPq~ zXFe#ZDh7zx56;1N%s^UWbe$l$3_S2(#t4#E-ivP(r7=1EKx8kdB%lR?Gv_gIDo&Dk z?!`~%{}}PYr#Y+MsGP8U9(9+L96El;$2v1uDyAR%BoAgVDiAsk1iRJUU4HV*h`bv* z*7$xyWxxDDiKaIh2==|Yp3JQxDN<@%heeBu0W>Jz(39bQst{p`PKbkTD7-H!0t1!- zn#k*3h%#YYe#JvpGsQQ62k8d!F~V!R9x)rKRWJ#O&xitgDok0;Zc(Vs!`98 zjVnKiFz<`8B4lsb^fNeOz)Tt=I&H!Nn zdER$cq|3k|mh0ZB9U}c`%Do3y`<&MkNDmHYE7IP2vn_DFBVWrc-ONR#)x|3`^^OHJ z_m!uuw43kVAxWfvYPg2O1+gQm%?YjwYPh3r#nr||DEt1krR$1rCbM7!{0VXzxiPKL zI6V{j2G%vD5k5l(wu~+gYILR^t`7Dk+CM0wos|b`FV!L^ZUj0?sP52B;lt_jd;MZq zfBIxtaUm^(@tUqvn;c8N1^$*V`-El28?o_e`o4Y~INnaQaHae@84os}%~J`TP-(6P zyNAvZFXQCnD`@Sjr5+1={`@!Z%9SQi>GP#?953lUNm5bJ!Ko@FCXcFRgjIMU2Cn&wA7jZNTM^Q{jRcJFVD?9mZf z%FhI`CH0c5V;AN8M$F??-psMQEay(&U zYZR#W_-~u8fTaYhYj79}KfGMs2UxD88OJxG!o#8^b-;z@dFM;pElA6pl!9C-w_aZY zYmOVJLv!!L@je|U9sY6B2&Ag1Ylp^h<&&1(c=biU+)ECc(G1NrEx;C3#6^wn#_`=Z zMA6DPaL=x~AsPt^IyZYBn~@w>6#3X45b`6}RbVFriq7f; zuj|^R{7wxRGTq&T6eRG|Jz9Whz8ZDL6+}7>^5GTK9Cj*h@u%$>5RfzgfZc71H9CSf zE+2@icRRRf&rpVE^CWtYX-PEKU!+S`N~n90ZMH3h=6Trk6VUW4P3L_cmN0YEs8Y>R zup`T8J*oeL=R7tLopSbMpkbabUS(-x2cCxHQQjqrp#lNdch-nm;NzKD801r+#4?OR z{eCx++*ct3Z^T)sHMhs$?l#hoB~Fd-`X8p#mq<4+cL(`ujb?6Zy<6?mV$vsiEOEoz%JbDcY^u+SN2R~->_>SMszMrG4ECmZ2dqp?US`n z!U$@#H;Hjs5XV(|#>V(m@9nhKQ5#EFKM0-UK8P9B)C?$#7Zm#`-}oACAU+==*la1L znpDD19$cfb@r6lVA~XCK+ptJ{IIyOD7WT&e@~xxJ#etWv&Yl-FKEnk(SlsB878x%M z8n3z>^m+{A17u>}ZXI%P++Jlq{KPs>?#5PO46l2o@a((pOv26wv6O|4!m?DczfPRi zU85sckbC5_Zqf|ua)Zk*cM$%aM|xc!^+_n1{i2Zb1?{+nRi231HJ%Og>{;f+ z2w^Kdssi1slSh&g)>pI5vnF)K45d!0p*FDaiIA!-mmT=t+0$>?j33dG21$F;T86~n zfV0=uCB6<;3NERQ?9071z}W~w%^`0yg)Dr;^YL&uJ@Y@mOKLIh7Fi@xoXF#6o11g0 zU)8yD%gQcoPKP|*K~l90+1HKNDVrz%1o2#(k91N&gO(y0M2|kOZWg2>m@#d!KDV=Z zk;Y@C`g-e}3JcZ^Dv4756;>I{v}js7+DBFUssN4!&!jp7%Rn4EnOlE39v+sqmGsBG0qB71)@EdvZNGt2ay zQ>v;syF{VoY9Tb^tK%?*@bY09(W$Y=L2#@nQ4DzZ`TI*g57IWl+3sC^M-3+=y6FZY zjkWV{Y|b`ZIBSUO>%dDs*WkXm9dM03;W4;kREBh_8(AohRd`@OUcPcT;m`)((AET1<2UVmltJW#hLn_cbk zc$xK9mj6^4KY_!{HwhM4$9k45;1f#r$};s5{#b6VzB(+pFUt7%z%mX0XZC>o;@36y zNneU)DB&q>;uIslI|$fHdKiwi(Xk0{IWWmH+#72U+Wbb|-}G$UR*JEd6xeY;6exq_ zvqqc(W;p^jnA`E6$9dmy$fR~x)xxkA3AQc%C5zNv=@7Vk?72N7HQBFZv;7rmpimb} z((8j+QE^fl?X>w9*5xihc_P1OuZnAAeVdZ7_~{u(7#{hCfgACVhFlGKVPhD5#DTh` zcE;}8sN5{=4M>aX!!S+LmLH20S7u{dat6A%}k#KMs&8H3BEUkQ=Y+L;0+(7`31N-7+5I z6BGld7Axr26phV!!GM;|FrXre!Nr&iekwu{;h``>c}m##$tjoX?!-_eOoNW&(O1&c z*ze5+2|g6wS1HWqoO|8hIZagaE02W|7eol`!#{8{b6|?e20E~+qjDXGEQwvInx58W z+6{KeS*VO*=B#SU_dY`~zHQiM6vzbDY zYzvdT-Re=Bw1ds35d{wXd5s12>%J;>g>}0fNoQ$Yi=_@2;3(* zH+2>v8B)xs>`iVHoGh^x_6?$Z!NHF$`~AX&9)>~h?xjZ!<9Z6}D|C}jg-CKj$Sr^r zC8y3xi~UN=5$*I*YnnX#kho5%3oX{H9pP+4`XXd$JmfwQijiO`8d+@cIgP3p-GLL3 zs|Uaoqp4m&+~=DI6|`=v%AdK-K{RVEotjVCc>h2O7*w57XP0-_ZI{_?PTDkV^g`34 z)xrRqEF#UmrElX~sA`nYDLS$S`Hgd|(R5YM`Y;;OQq{)1$Yb- zGOYgGpQ`Cfp9WZq%{rr+1DwR&*N=KoXFc7}sc|-^p<(~D#BpG<|15VXG|t zm1FslE-SqvZe4ND^q#A9m2nDw8fFj@HpPs3oQP#m5b@=G!Y84;mEij<(ZY-5j%q#w?*rvt2X{IloA$xQb<);pl9 z1iWX))JJXDMKEP_dCvqT=>2zdGUXg*0B)crx|nH)aIJ1#C$eE}-r)C#AU`#?20M<1 zy)0a7DW5U)m?X!pypCTVPnTR(cQCB4#IYJ*TGv(L-?uI=VI)B&h}};-#eFvh2-%r< z)gBy_zyY=(xt_rN4h_gb$Ja5hH#Yl^_DxmF6HPe@g{XvO zytWdWVl9%6Pp450GK?&g=H~n#tUlR)d6G8|DH!cVWY&F|5c%o@pF0rC22H!46Z`jX#^T%$LL&xBTrnaGG*|b?vpm}`H^0QW` z`w9fn+%M8M`{#S^opN(6?B$a>D9Z9pe>(6$i=kM_Hd4Cx4SS>XeNdJ~pB>vb@#<~9 zV&pz?lWF_(fPq_uV#$690(}*)X*#b zN|PX|H+TIJ|MD)i_Lq%#@TWLZP!Idr{kW)NCgjAVUH_3gSN zwKnoTX%MBi@5-3(IIz=M&GH}c&h!qJ5?Sr1#L4;`cxeva1QNP|h%joo-WXc1K4c#*!|4@Wn8V=wYppg;JQ07REod8F_{+9F39%IwiZ*=DBd|{Y-9kIH4er-&yBIa8 z&1j3^>%&twWIy2cYyPU%@mtsJ#p)v1m#IRmmHa~>u`->}odq^@*AE#K5*w>fUQdXqac zUC13(z5P3`ms|OkE9Zh@TQz^^DmJKUPk~G>g^_sxf%9KDPoJY0*6wXE9CHVq1dx;3 zmwF9AiPRaieLTR1m&;!L~q5yUj58|4Oo`&tkXut$UDQ4a7(M) z;iAc=5=Vy2vr79(y;%qgsrq#EiM&W8UiM*WRHxpf;2albGP9K&-Ndn+w}sL~BP&dH zd!Q}M8b7Udgdg09-MimNa$$N?Sf3^R00~^lC2;yAGP9UyVI3vL54nE4=!?FgFauIs zur1BcNqCu(^p5!$ikXWBGs!!jD)9SucVFMrAAj2i!@kFO_gdG>V@=rdWT2j z3v6)S`OSk=GoJJxiZ_3745r;Wk#C82AM{-H07+WAiON<=FpfJfmHj1M{?Fr3mZVsL zBIluTusFm-EIC(j=PD#EwGkWKOO+^BWji}_nKiv)34sf-Hi5I7SHK3#N@I5mz69jg znAhba?;M0A7B#xpc}%^uI9-V<1DaxplILwS#!W|Uhh>sjINVCFd!$3B%S1uOco_gX zOI*^ix;|WKbh)fff;8(lTuVxtpxXr*h9@rTc`7=~5Xz`s9?)CBSMZTvukF_2pZEtO zJ8)L6N%N>7=({iZtAhDl<*V(>+v?bLsQFUQyrS#(Y+~1hwH-hLlNz1CypkL+UT5dT z3tT4;*cDaxgQ93Le3ur5nHMeqLvKk(Yh0FqAl}q&+Tk<`F|E+DVnegEg#^4%gJ`6| zD(~Uuqz$jiG`Hd+&>JjoJ;}^3!9xs6)>8@>=chK%MIVI(k5mUiQT!c z;j@CP@$|!|eB58%xo^8Ca5|;yh6sR86Y=@*qIr=ef4G66#u3ewJ&mv8=>~w3S^#ES zk7Da{W-hL*jM9H{IX-l)_F;c(DD4)=%&{h$quj$ZF$-IvwcZ+8qhx~y*a*@NqyeuImX*m^Z2X zU*N3Jhl`w)B+VvTqbt6rDwmX-OE^DgX_ah;qs75{o>uEvhn2#IY`94AnGb5&49=;S z5CgkgF+K(DPvrUL zgyfUGf+lE(YMiD4JA`ZZ&Mn<)q#k@CNI1$8;Wn%1;9y)r^84EI>jOCJdwhJ2=-uw! z!MK1!N@1jvmvu04C|ZC85l=}BY^D&r(pRR(bmxdr^byI=gn9iY{r#=FJ>(I%`I)8F z?I8Y68=LR1I~7DmRecECHu5(@v4?Aqc76T$P(fxT95nfN?Wtm}ec=D^Oyn?Lw8By)ysjI%{$Sg$HMv?T)@M;LIf!X= zJ|Hk@w-tK)QzbWE_nPq!Cr}Z2b$87bg+!ROlwhykwPPS(yO*bKL-ZiqVx#y)`XQ$n z-h4b3w|FxHc`x@8p1}vmn+h!MnRCy)_X>2s+K!j!{HYZ54WEb5s$j86r=W}DGmVyy zK`il)l=%$En4{x=ba)}DfC=Kf(Mmi0vYS=?FaZP95gbL8SjhCyyxTiNgRCq^)&B>chZW4aqX|6Fp*1 zjS}m8)tHDIU$Z|KR~=7o`DQ772&22#zl%v53Oggcj+OZc_y)uJ0CZ}@5?yymVkCBE z1t(U5Md0uA6N}+GrhcVu4Je^SeNrFR@hvXiEtJZR%F>B7)e9OESoc&ZVt&CThjx5_ z>y{+06VfejpLErOQqF479jO@=Z;I7z!;q)vZwYjfuiTSxL7xZSZywz|kF2oSQm$3z zx_(_N{7SPdtiQlTJT~*YP`MuTm9owso`j{t94%Vq7S|nbD@re^(^} z%f+4Ls_s|wzaH2AS^5O)wWSo= z4nUV^9?4FUG(|MEiaW0vb%wWPPgjS^uUmNfj1#ZAK%AMKDDnu7zTg}`M<{fMoU}`o7-?MY-J!dg#LNI zI`E*qxSORbaaUe7xG6<=Uf8WV<~Yr(wy;~{U6T3(-~^aXp>uw?ySo_gFziFGxtHB| zCgk+i;M-A~RPg}E#cME7g6TCde{=r?Kyuatxl}J!yaCH~&GEBtZu;pQWn=p!;~rUf zt_A}6x3MT-PpuWS=z|AVd^vut&4YB3JaQ#CpAaG{0O@o(y2tSL0Wkm5bOqaU4<93h zq1nIkfUQ=1L4RsD3az5%99~;8!&5}3;*=lNXD-t1-L>AJxxL{DPyv>+XPgeZ zIy+uX(C(98Z@!%qGh9Ju0p&7s^hro9b}3Eo5MOp|Ev0Px$4+GJ}wv?%VC~XZV=jA1yK9 z>X(1tV`@q!K>QLxmOv{XqP6CL<%EEf&1nAS8nRCKU!ab#PdN$n=RoS&e7LiSzPTjKHt_@84!y zD)riZ<;$(!6?_FIye|TfmH*}ED;b)u2T^Q`g5o#&h4}f-r{DX(zWD!()Bpd80o&Nv z{ErR%j}82f4g8M{{JRaXJ~9D8#6+c?xa;!MyOo1b`g_hVKw-feDutJKiv;OZQMW>H z;XXeC1?uPKq|##laOuE@BS=JF?k<2FBgaIwX$v-@r~^?%x7vR;5ArViY2|52L(Eyp zz9-c@RU3u>z2kVu742OW0ZP9dJyhJW;$n zCN0s&q@d>QOU?1~1Bw`f&o5sKppo6bpEd%VY4~lz%M&C5oFHil!k-G2UY|mTsl2f!}E3S6Bc|rL?-j7HzQ?Z|avrS}cA) z>Q=3MddKaoZWG!07HA>P-O02~3biD%ghC$}jA{ zyFd7T8-5NkJ^z*@1sI^N;?>9d0CPS{tA}|RdSptbXri6#{o>NlBNCl zpD#07YNn9Rph++5M zfnUB1jL{>*zFiCeh(G1Yr3qtN{J*wBl|7xQX)dkc4u~(F$(3LJFnZ!+#4x!0z*}U! zY=s_TMHOGpi4(Y=g*{JdC%ITU5IvoRzIL|=J5-pJ$5~L6)aFKpi|}7gdOlbK3kifE z)&0M)gm1S60T%HJW*KwSrgd5TZum_d@L{I~mq#a;&vpk>x^d*>zKM0@A9Z>o9CAK5 z0Of0(G@5(e`QRr^-Fv@~9v^7^!GaH}3g$}TX_d~Rl z;8*9gg?KL4_8;+gZAFC;!}%V_f)R(s4b}e+MUb1PE$X4F$Ly%tcy88$9e1+ zV+l|fNt65Ff8I8j_M$~f!OSpR#RPXIsPn=j?4XaB7k@+Bwmm>bwPNEvJWn9^D_xus(n3PjMpBXq!X(JIZ{H%gZqKu0&>6-ZZpKYIR8ZBR75w* z2lgx0>jDU(*0+m(@zpGRQdhnwi!2#ikx0zQf0(vi4Khpl12Tbxx>tQjGo8BcE%~!0 zIki%MShUb&`%Su##O_8#fod10y4+}+Sa^u}o%yy5+{LhWJ2EDzSer)^;bAI0+!4Cg z%uAZBnM_9jLzxCo`2t`A4v@rb$bp;&R3-qgESKtilAiUmYu{b+s643z?`MQq=)TKQ z$xlgFo<0MR_)WJWed~vJ!3~d9GQ|%TAuteM+z|CRBY+@oEISIhQ>h(hZm6BW0^y_y z2*eZKcz9q#(2RBVZQmfMJ>cab)=SgIw<5r%XY2wQFE^DQ@gqbU60-GQ{{wOCe z8(5TM;_B^Yd=-fU4OIJW2l8=AM0VDo3CI_l)#%gS$_Wzx``e{u<^DBTT;(v5V@yn6)ne!k;0ES1qN=(z}IR~WeGASY{0BtCCV6Y2d~(=@K!c8Uv7 z4m%$Pz(?^c&j_zG1Nsg+6631~U!c%Tgy3XP2uo?k=Ou7m&lP^mVDgiKZfnI9?P9T@ zaZzC(w*x&H67F&8HjV6if6f0ES_z_3`GrQTgyt^F9VpklWmvIOYN_VFY_lZ1U#Wl8 zszp5u(VJrM)N zGF$i=n7V(MOJjgtZWDEPa{Y(~Hrlvf>D}8uTDC*L)Av@`Zyrh2V&oq!AL*LV2b#1M z?Z)CQJlo~abRO@i3`58@TPTpQYM|1ujh?1I%_ovE-o&SebRm6#@!40!m0k`Jn=0b< zlMTmrugDsCvX{Z@4tTHgU!1yTO3i1#dXfazp(vKgY|Elg=m90WT~kMusHNhDmV8`? zgdUn*K#;Yusct@zVkB|()+az)tBf)B%Fdf9W#?sRT&f}RP!KE1$U?9t<(Q*~~Pq&*dq z-;N+4@H(#0ku;8{}2dV8xS5;1zxp^z2JoNQ+D~l?tSW7 z5(E)eeaREf7n@}R0lAtEQu#kxRkhX24o56z@yw1;Xz0Njq4FO-l+NFaEP6M|fu6Hz z5H6V+g(TlWm>m~{rS@R&%;8b@TRd03(RnhuIk#3mRDUX%l)8=I5p2n)dnh(9ji=lilq_ns3 z*l06^1Z9V+L=Is^o~NRe`*2`7a#F;Ik-3*hYbPK^4lY0MHcO3ReuG(mQLl6ilC5{* zWL+iDw-PYCQoVC59h*lLsnMl*D6QT=@*>In@wyBJ>~k7PCsE)uo$#bFhMUJu_ZMr1>e>8AH1uAwkeI*pshE^q$OBtQ1? zh@Li|9EG2q>=962C*JVAYu~tbgLybWYt?d{8ew%c-y@2Jsc$Dq6YmqO~VQqsq4VNg+sB`=xH+XO-l%p$b>mF$-KQEj-l(&sW)moz%lVIEYTGSs!EQ_eletFvav{lAl3}T>Wy7BvF%@-+N5_N%^FyNB#1KTf z^6F`Zb3}4=nOg4B-$uP`Ss3ls^5CkEhz#>>?DP>Nqmx<3g$QTB9cwLuWo$$#87NxGNDIAT0R4AIBnoFHi_A-dlY|3e(7k78Wh zEeYDxKd}7O_z0F4u)FdYE6)iL?<(oUcN(-eIt=gsSmpRQtN7-DqIJuLUH(SP*Zv0T z)h^ZeiC_m`Yy5QcL=|awj%lnZrP#sG!Xxo`6Cf0bKa@6NF`y#u+;6(=h(+wct!{Z% znJ6m2E=b@YItYiuj<2;&o1f_p0jA*kV+Xk*>oHg=)KziqTlVVG*+QJT-Ja)5W-Acg z8DO4A#cUoZ3lx%9uRl7F_uuY?iBv*&3**f{w@h+K!TTAo#YN*^FyXy$b9d)y$SHod zBaP{BHCl6yreT%CdMrh$WGl**)Iq+ouT?kGY)M=lv1Ctj(ryze(3GEuBmU$ks+o%t zlUMzAsAEOqadeWUjRHb^g48p@)LU*hO1`ba{CEgRzwM8etD`l@guj43M(uhU7}47C znTGwe5~R6;1~GlC$3gY#lJBlR_U+Ev1=p~6r+!5E5mySQed87-CUDGyysEza-n{e| z1sy!*^VY@91QWdmDj~{ZCV34Ij-S6uvNNc0d}`Bozkk7`f91FD+A=dsj9r(*J`e0 z!D8LHh}epLz|v7gwa#hU1i0gd_! zFWI|`ER(AUr=w(LieCLE&F} zJJ**zOspdB0PTpMwy#+@Z>2A9Myz!y@2g)Llcw&oho(fbH0l}~*xmNaIJG4$F%ArS zcDk|JsvFu`*Q`VbKHDUe(H}{3)?1s~ejazVk-TcBOAEoZNU}I=5BrXShP>_|d+Htt z1k)&`d0#%zM|c$?MH7Vx{ssN3a!#k7MT%|B7DW>-Zr5%nSH ze(O{D@)%>7w^nzW%_mnLx3q-J)dXhVd&aE&%kD+lc=pfLcPi6w8BFN5nDcs7JXg(D z9nY=AdEXK}5oEX2GBw1Z(A;?E%=BfV?g*JcH$X=0&_R6iPNE7`Kr@_{!tGUXaYJ5z zGKS)Z>O1!7*JDR_zSO^aH>*fKtp+(WebBNddN07%U)|D15*pB^&h3Y}dOv%Pq5;nC z+D=R3wnR$38Kz@e-Qew;O;WquN9EnAvAL3~0R*Y#e(97KM%p4$sA`CuIak)N%z9O3 zQ8c+CDfCzOn;hhde(juwh2CqYnaby7d3_UHIdPF!PW^Ohyce{orw-4Lg)qEU3#${< zT&u0JYa(tSq;;Bl%mi;m)*5jFi|4^Ncb5#_k+ICwX$27 znD8>hll>C;3Q|ovK_aGzhnf#!@#G$Uqk9y5~#`^NJdEKv-{b}%p|cr6%LwA@@pwiM!h{N)hu zxIF>J$QZmfpdzl`>|{X!J$1IFtj^i@9=Xk4QGTCIz8Mw zk0JBWxjFw0kc8v;@54*O^ySY?lgh0k>8>(TGc&pF-TQXZNrvDX^0|I?5d=L&j(|Ds z*K`U1lRT@rd!9`TL_z_*`_QSUoy=7eb%>&+R1Xw)Iz`CWo8+F9Yikp>#g&pH$5~Ae z0Pfjn)W>@fZQKM8A+zu&I|g9T-^}Kdhu~AV!ng+YcTkY1Q8Cnh0e5C*8&s*cDcyyGaRIq1}ooXeianB2l>`XSsbVkfFoYktM*-{ zuc<);Lug-WTpR*m+^|r}9`#;8A>4)|T$fQt0ziER20MRT{$(5`7!%Jf()dQC$Hu2> zsz6{$gxsujkTu@u^^v#vi@$vd@FtVJHXys=J50QRBwrxk?gk*GlX;>nHClojZK-AR zt3R8z|5YUBXa4;w0fMi264l^hu*v|I(`CailjVZ42A#e{aGQT1?|yt22-E-l*@x}P zS8>VDe-W8xhIvsB#sUE9re|V`{5iJve}{*`!!Kc`+wd&W^De&P?~nX$@|C(xB&hcP z-s;2lo`}1kWC-%b>A)0&USOm*p@Wp?{r0@M8T{Zi>5vx?WH@zJh*c&tImD?*T0mkd_lUKPmvv5C`mrU|c_a=aM<^YDzXX@ZDxy zkpsa$CM&f!&!2q-RSOBionw!hP11emAg%}{FZlYD#Vg;-!G12n4X{Tfg$DSbNzV*k zeC`5L9q&)@n-4GUiP%Jdhx>0*R2>lgzQ||0g5MeAR{eQ_7lL!-8EEx6n!9#z&wuG6 zE<6RF?tGx;uoDNz9Fkh}=X0bW>{rbi>G)5I9bY;s#`9roUI9}@yFDQ}kg^#*Dz1{P z{O9wf*yqna3Vyljzl~fp9_yvJd!RnHGDZ3-N*1`JpayF{O~hkNCdHN+5Z?W+g)S4m)4O<791PJmUoDKp#rhV)E#=oILy3T2` z-}1+BbDM3TGps&{Z>2LNp)J?;7W6>4WY6rr_ z;Bdn6BkA)HO@>O{`@D4P5v8LZb&tnKi!n(IFMev|caasX$F$Dv%7R@OX-g3W*7Z~N zi{%W4^b=^x%?~f)X`k2>J8eCcN;*twGy7h@38A69P9OWgIOFl2shetYZFU*dK$d^+ zou-$;0=%D=rXrp}RYA}c#D+xKVNkNu35V0PAD=G~`00rW670WkcLg;Nutv#Z5WYUe zTQCMaTcePXxB}D<8PRwd(lrYntV{*A>ZbE+h=Mo0&^0*{cOBBPIAu?hKR@)!D2D{d zr&`p3T*$b1U5Pe{5($03pR3?_cs@za_pCVpSjYA1cQHm{Ao!Tj%4KHLrV{{S_K{9? zOnt1adFKGu-*@8x7OLuUAJrSlV#R0ubh!q=xP#Urwef7I45#TEF+?*6RbgH3w8tsv ztY>jrcq=$f)~4R=Qo~6{<@^oa>~3+1t{G=FLuU^eB~l$|a#5KqxUkQNMhtAeKKm&0 zmQ%0JHiFT?Hph77L(krJojiBRh$9!-RrF;^UiMx3lHsMsv`4>TJfi)zJg5SU4ZLX< z-PTKxLfayd*x&3-{a;cnW+EC7X7!}2?oYyrQDff?6UH?ub^P=^OMjx9xXT|>WWPFn z^w8hfFm#vS2TbL0Ba|!WZ*j45n!w6A`%U9b?2myU!p~in=H?NwxY5C-Z`C(-cj7i% z){0o7>GXJckV-@A+mPsJkq(0Kx1B{dStG5qrF+TV1u^+B(3ERG{6*# zPR#-k?8Q!~0+KCXE5Yi>JWYSg9Q&Nsxy6J(QaUer=Tn9a(@=zQXUlftqcQ`ldgs|9 zYV+*upg~tXoms01F5k~3ak`;-n0qn-iI_LZS0wWvhFq~xnGNH&0X5_#%T1fr@2nEn zA+RLvhk`jm$k|U8iu$VZ!=|j>@EV{wiesuKlDYEU!^sEtbw7W}a(!n+yNYjOB-UWC z5*PK_Cql!R)_SdFw;Q0dIpgLacOuS;K|b!*`Pl`Q*JH5V?Zmx4GA}KF-U|MzFjqSw zyE*poed-cBRul`IIo%A3+Mm99K}mKtFTKy*n%Lkq z&;u%_NxDHdCtzeXK(OV{&Yw_0xJ~Ddaaqx0z zKh{+ru-;d!TH}x5s;C7OoI{r8^Pyp#JPnW$;bTFrb<)-T(J!p^rWRk$C~oFLT}kqO za$(k%2ziVXlB`o<-{sryh~NM*IRIc@k)vjT+Dv?*US@dbXE31HC5V(leSZhU@=Uv! z3|*r>>Oyy2qEK`TI4+i;DZCl8`|Lx(od3+o0T!J7mOhbcT7PYcs@pPd#h9jZ+ zIvkLkbp?ThZ``CgP}Ozg_(krJW$q`zx$5-9Ce=!Xc76Nt>{?k{1Cy*-lT8vJA>cZk zgXuUAsmW{bK6B$^A@xxVHQeFPAV$59RP7*bX8=95%(9oh*~EXg*xtO(B(ColZ&zdTGIQd&N@*hn|w zrrk=ii}0$;=_q#6?aW(bsu5gWEjWY2_TLQeE~~&)$w=P_>Qp&Cy@s%AVebME+iDpA z6s`&|7L0QRkVxIePxTVF{o!3*x7Am&6eUCL{oaay!0K62lz}6Gu`!ADdr$`0HMlF_ zXEZN15dAmHQBHHl_=#_u(p8|pLr11H6*#D{{=Na59!l|V*w^-P!<+dOHF+~FNfGNl z`61;7aSd`T$Ng%WFL$*|Z4qvQ?;P$mYSCfk{9jP$e5(c%R$8H)SE$03NdekMxt$`TV zYdtn+rtZ>G{C#~S68&Td6~00d0ZUJoyac9(=qOu}Vq)6W_Eeh7VDo(W`SYV1?t>2F z&#*d|>tM&-@-IU=-qCS>x%C-PpQTxD{Cz$fpTBxI>}BuO%UhL}0@5MU8a<;b3*t=T zdea{t`w3zdUnC3j?{`!be?%cR5zq;q$ay1WR5(~DH5eDsOD)bhiw2O~<=sg>BYy-%*G>GP*(syVC0v? z#bp8fSs%53)3NmGZ2d-`zwwMg)8s50SS!j>A+ov({eq*9iUcKOD zx4YI(LPsiLx6f_s@N0i3N*t#@3gRJI_1SiB-MzW@wQT$NxO^bCcU*Y4ig)bSj`&^I z(7VRp(x`@2y7HoaYsPRxT6NK8v-lv8FUu!k1@68%Q)sW#1FAg7b3^igv)HnTkdNrRc+O?>; zb0OZ+(0$w-DFOnXytA=<7E(WuK0K_@Bl#og@x{H>(N)?wAZ^j<#+PBeoI=PJ!~sIY zuYxRr@1I84IgTuZT`hPi{8W>-4}**AEKz{itODr1P`Y+pH3b~LH%^-m0;@3r&e=96 zd2})%-$MZ7xX~0|pYSqlHTyTrU?#DHEjY}1gf@;7UfP`@CzLm&+QNS81=Q}P#^S!V zzs{dtjL~WHIR;b+b8^jJ`@_Z0qSd6i%&z;>C42q^icf#$R!f6@Pov+)3xGF6vh(%f zoj&c@*ZSSyjEP6Senb}6{|#UI#S2h0_2w3~@cjkJTc6y=B8%KgY0U z*{wSIq2N))5DzsFH?i#;0=OxChEgT+xz>EXhF0g!IGOL7BiXcL;^9Z~_Fv<_mM)Hvy9T&EB}m+no&N>;fQic04oK^+1WWl6menbu`dLLE5~ z;gx(Ei|^SbYfQ|Bw>gJ`EGjFqnf!O9f=FHjRNm+}q_KwgYq1dwCO}@f-b}{MO%B!4 zVH6+FVY_)UgXVc=$`|A+j?azx==CE!Ipbh0+P%ldq!G_<`7_qQ$Ln)M$71i6-(3H^ z^!trP_fx0eLAbi|9}b*;1jGh;2EL-^i-1;iQg?kGEHP_&pZ|zRXP(&bX@7Y7%&_C$ zUQFjlk!N03j>PfOnnEi|Q0_w9ZeVq#!kl3s#*o^*i9(l-WTjQI^3j@!^B^W^g+v364?mhd9gBlIe6 zMBKrMrAmBW{xv9N3d44_>prAqMVom#Y1x@31)5c-AU9!5oS?}0C6_|n-&{zw+wN-& zRAdtP)ogW<^m6mbCjDc}LuP?*u) z^Er!sDK86Odu@0y9}5xqp9I;i2!Mu!mCqc-nZM{t4~Uqih(AN0PtsnGK9VliFs}V@ zLMZU%-k=!5D!>9?JS-zoH{mv>@{ms2)vS4IiG8b)7w6NK+A9rm9iU zbX(eZOx&7uzTl9cqfBnnR%KbjN6XsFB5!M8a4=ZfIj^0(P!rab5km$XADp4>h(3@z%^p9SIE>419E7=SQ6G zmLJ)sTj^>Gu zCE*dR55u0rNbqpu@BwVukCgDZUCbYU;$deW`8HImm&iSvYDwA=TQIS%NhT=ZKvv&V z`125gAng8o`eNK$(#E%YVi}~9V>{YvxB8Tqjq zrymh5jJvQ1bU+0jE*dZ4`jJ9@&-&$RVH=~{v7%W3(2yU;_xfhJtV)QW@%aPa@7H-n z=IRMJ4XJ?f%mvA~WIQ)(0N5y-znt;js2C`v-VE~2ZpyVs(jVU%@AlT}Dds$_n&e2B z#CU}CdZQU%;k|iF`xlEwPLUPk3dOW=RyrCZ*)&zmaHcm0t-@aKx1j^rvmH5Q+PY0M zJ~Qo@5x%@k=3Q9-%K#L1?~+oeU03Rau$GY{qu-~+iTJ9UP$+KXPQnehP4%TzHN)I`y&8BOTPxdBl0o+pNEMttBtDGy zu2VnBI_7)RCK5*H@2Xv{?1uSUmk#0)o##0SIyLJ`kT z(ptO?2vgVB{wtk6vwJaLJ~pSwT8&pSfH;`3-@)~_Flw^*3O!_#S~~2O_tD@5mGwND zmO`FIFJwD}B_{>O7+VUodhkPP$ol|)*T4YlhIxseN(O&%Ky|OYcSfqqBVrZ zNOjvXHs^Zvd;Go?8ekQifUSsG=&+80(N7pfz2EO@x#z1|@Nki>e0)Ki8Y+A9_ep483)eoVXXzP)Me! z50~Be#zI9~I|b@g(r41OC1z7NyajaZ89;h-DCToMq4F-;Rcfb6`|8|N_eyQShQClg z@`_^y77BG@N!MVsOOzD-RKa-A#M<~S`HQkg%YmHUDmJp&89v4WH-oL)6y>ebDUaFp z4-8~j1v}>qT+_(k=AjICacYn(m-Ew*IpT3*>BKeJm%h89+-~wv3}yKt#-o#=H}3qH zJPJE+F=VddtgUEafG39q&-a5`?ei5XeV zg-0dlNp&;0z#<@f62E3`ugb}tc3i~cyAR^zI}Gh*a|vou?Lxx(WVP~d8lF&5fXP{R zQKw&=3dpP57R*5DdzO#VspA+H#tt@hB<9pS0pU2kJC z6M=H~9!iyhC(|!btiU`=cOh5Ma^`rXTIhHwo%Jb_=G`lFQm~&Ef$QjH?BY!Un&ziM zL;H7bT_oOuNueiOn2vd+3U1Dnx+0W!P#AnFCT$lYdVVr(!Gehu(*hh$4r_b;SgvhK zU|=6I`cs@ONdu{Q{O3+vo0kAhv6mvgbNN(ifRC>|8(?Wdcrkz85MsfhV#D@tNff&s zC12>U`apj%CZUo)y&oG@A-!C>%U=T;SH~7AA(= zyIf6VE+{}({2zh47KrPj`kiDVaOX!>Rx^4e~Ewo0Va^Sd|2#PFOQ_d7V)X8dD1PfK-Shm5(y#b z`i9QD0G94ZLc_>u&&u@MPyhL@267DD0!~jHKOmZmlQ$XpovHfn`SWi2><=Zvhd@1; zc7#dl?q-XRa>boEuUGP$K8Do8Ih?&Na?7$y`d;(V6XP$hp~U0X?DPnLn;>7N_V=9j z7ntOGyAc;cpDQSX04H5DCvVzc!d%_-EQ;+zwU>A@8bR0Z~_lTq{H4bqrRM zQs)X!hx&nPv=?4JV2Onugwc)vYCNk{=Y3Iy-v|oha1tu}Wq1Hj_4n=**1)IQ@z;;n zx9_Q;-aF26##Yh~YKB-QxdH34Izry{;|CxE={G>bbGdA=b3nFR2Xjy@G$Y7$vK<#s zl38+nICOsWLAfsK8)a_pENHHdhWa?KAPtr!;`|IS)-BNr_dLB;wV=2VI$*SzE?3qj*K1-I;Nla%XNx5YAzTyz=Zy3u} z@lY$^0_03MVxha9ar6lTVf9FZNZeMXDsQw+&A^B_Oo?S!oVc3nX{s{QOMN~8F`MII zGzkN%gx!L=Fs%r^WSfEqd!fn0OKUzpQ;o8NS{^nKqQVlt@p&s}jQCgRIS}LDKqisc zLT~Eko`3K{`$N6;U>2wnv$%d1F+wT-3OMqtWF1Bh;sE72&H5>dZEkaP&KrSna*s=gvcATAMse7$(oErY+c{ z$c$WT42?Lh`1%e4a%~Lk`HodqTKRVR1WnK4Q>Uv2GE&t;m0+jog*Oi>=Z@RnMt3U_ zO?f+iTg~tE>qr|=5-fVaZ79$`l!v9R(fT#Z55JG~iXf@dtMAakcg0y|$-HD154i-d zI>wmXIZI~`DZ(JdBOR*nmPS*G>G1jqOtu~U^qs%pXSEK<{5CO6&&FaLxM9(a@gc8g z^=B|E%W6f>^MdcldFw_(SOrp`6+EH|dxkvjk+lK1{RQc5mJR!r#hSFo6MSOhZ-Hy_ z2H2iIdZS}!g9N&%sq6cH&H$H~BR{o@79wXt+(l&JZH8OdriP=N$?A&+#Z-7Od6cA_ z+q<`H^A@*RR)z>XKJqcoK@ba~2%Jx+Dr!_$vAw0VVWRid*46 zk5jCb{4g-5t|-Fq_A{vwhJ94>*SwafKL}mGX114aRU2NG>$MOjdsA7BA;+Cl!^V_w zXYfnrwL7>fasktT#k-ZKvy>p<)7?cG9{tWO?KP+?lFWg-NZt`dmcF4d`z==RbgQ+~ z;ssPe@E5QJ;fuN(npG@}I843cX9WO8PEY>@A&FDd4Ni$?m)Dstq>$@I+2=IP3T$9f|64RLcA-)f;lFLR4`<+@gm+XFmaSCE6y+Sr_G5QYD{ zk~Bnfv(i9Ek$B!nX0qLZu`ylGIE&`JwQ<(lp&YdSTXu&jpI{abLbW`;g@v9pDL@Qt1;qJ0S>Ujvsr!f8~{PWTN3wmkxy_2z{}5FbW5jY`v@<`|j$ z`qC1XUNRF68al#UKJUJsO7nUSTXM*J%zi;FkDp^ZuUwu2J6s z$SF^cAEx?AFkw$q6_I0Sf3@tMjS;~}yGi${jDdZeX1q_~2ens2FBzZ4xf>hUpla=k z`4v$3xwnXNt8@k6rV7NYG-fjT<@P~vkoo)z#UThdhyeS;d5fMB6v4^GVT^+C5Bi#X zG1$i_RGCW#sK@%?31=X@|9w_9`yG6Ojc7=A0=)l?%qb*0;3&tVIvhW^5A#3bWQRq&ZALdP+ z*WRG!2;M(iRQ8hQ=WY3!|5Y%mXOAUqZ&dYHUu2#NSBM?XK!h$UzPkDXAZM1AP54_flR+)59N$R{ zZ(yCK8`<4xa?*d)I41RO5HMkd_Hvco<|(>;B}cjx-dl_AXsHrEVW26jV%asxQ&u3{ zk+Xm}aT>Y5lJo^sO2Tzfbd^Xyhe5IRr7zJ%cz`k+>%Bp<_a@U!daUw6t{_p^P^OK} z@-lbov%1F8f|eOfx|}{?{+t~50f8VJnb71|8eL9vBCWT1={Z&X6L>;Pxi*wS<~-aH zpY2?R4WMUx6HhE3uyPFi$6e&P2n_7Qf-N+zrYPpXKRn$?$0yEx@nb?<3nn4}KP-Uz zUB3YdrtJ-T%S9E0=81Gu{tq>?f~hivoFjX7Oj80m5zHmYbR2uq+zFYSqcaxLlXlnG zl?p3%-Sk3#u6!sLN&*h47|95U#-X%urazQx(aM6Sjv*$&frRjGxMLl#jGv54am}rq z)5y84C>C$TX+VTgBW4bXQ#S4lIuQmI&9RSP6Lf*fDzUN2w%7fP7h*CPzp}j$jMGx7 z`|OHtWt@(`Dn&0S*z(hKl-GUi>1NPlgD>7WIfp|gS&T~!4fvowty!9{d7h%W`P6VU zG9pnpsoF{V#|uPmL`c=T_6O+Z5Do^($W!V+COwk= z?)bT?)%^`Pf$%hS^&x^chx4m2H#L^7c8(amPRF#?t2MVGB`t1J5{GD=6*k>wPw-}8 z!mPBV)h%}uLih-AGLrRAmA0>*n_1`rhEwe6DAszRgEaRwd zVSX!qeZiZ354O^o(1&Qlz z)%D)GK2&(9EO{JEGS%0P2Lz`+4se@tll>8cXV&P7*i}Ixa?QuFKVK_lTRz z1hnh$u||!gQSVnpykjhYa-Be$;QiS2mQBp28t<3ry)w;oIEarWD002JTt5=Yk0pnO zRaoI6#=Zq}Em8slxW#cQ-piYg1yV*E`IdZ~ZCXwCS}kftKpTgEw-#(QfB0^U{S^aM z5^FabhhsIwl6U{7On5(`$Lrx(;46!wYqFw&Gk3CP5p3vY_3fd!PY20IQ*P}gI^El< zxfXom3%K3e-##uIVE~k`QMi)1u}V=RE$C~@I6YGcffkW5WNExTtX-9ycw>ietgSEjCt z%ea|J%(#*IJV9miiz5-WY~PvmvL$SobeZgGAI-MlWR|PTv`Uj$kPbT%#9$D(Csf_y z6o&tlry@4jq0Pd|%GV^dcD3zqLB$Z2T&*drQM;Nx8naEGKiqv75GQYwbRs?8;FMeD zM-lTYVBX)_E#sT$_dH2Mh4sS5V$ri-&*7y`rRBwI`=2G+u;bTuHVFxYV+sY89odPi zc1;GB5-YA~IZq)1J$yo{qGYcHrf$J%>wA1Uul?5}0$efbz;@s!+wZW4nqi00oq!sX zp`1~w^}+Cj+@2CR@Kr^3C-0TFoCsrBNH*uB2fXUE$Yz_(taCuuiq}RPca7VNAChI7 zxc;$+z9Lur2{1{HHS}J7t8_)9u2+i#6a*yA~ zkc>;Rm6K2IX^fZ)G9l<_6hkceN#fuQ24UnI%mA*54+~+Cl3T{^T5eELcSC}cD;_3| zHSrb)VyQ}Xdc1bVQL&tOpD1@MQzOf1I5rxyIKRYSE7uX}z!!V%YAj$e>cmPj-{^0f;T6prIp2<4+W?jso1X0gF>1nYB#Gwbzj?jdmhg&G<@2eqEk6ami3)DCl{Z3nXQnyx1R|Z?U%`AvRkf_QQ)nn9ZGCFL-kAtm z;1BOSO(&h{i_uLrH=a(jl}oB|S?tNNb$OF25yo)8bw5H*sZ(Y(BwvZNutPg9(pNUj zR^_nWxtnnO5|m(*1syD_#Q5?>vl03ji{RcU^|d0btJBV9J=4OIuI!U8fJo#8?6*hR zh2$&IJ?LdSNeiv|ZySw~wt0-x`O^^7buS7CWDmdC;2+kZtJ{eBP{!g~G%hGes;NJ6 z05cTJQD;gZZQy!yM@9MDcZiSWT>>fw*`~#GPWJAE5nU;Dm01dP?N!Fy(7+r9EYg7E zr@ySFbPV*a1*cQ*zH=~eE3%qI9lw%3?tDAQ)Gw2;Rc$nyw-M;k57sAnCu8k}uC)s< za1xrKTns?79k_5?3hdoNPMPL7wD(>M@xb2BA_p zP`!{6$S#AMNK(7hrG5HK zf-c7R68dGM1%1xmO;Gy>g=6*y@|-1>@Lo5+spAf3fL!6<82L4llBQRAG{)Et?6u9i z*9vy=9KFu=MzecYT!SNp^a!@L+bOiAk>2ByTok$x?4*3kk;*VGmn5qRrD@4~N3=Y{ zgKDBRw;bc%JKsN5G6`NV-DNvoy&>&sxq%Um6WT}KB~DilyHW-BhScj! zb2E;n3^PJ5#3AQP@}g7&a`#}njWRJYAH-M`S35>xcE}M@b)h;SBekeu077?*O7AX%Xu_Z{orJTX% zh;ny+V4m8?O_3KABywGhiTFEPNI+-wE8xHVvt*x-r~+b!-;7Og|Dw_l!luJ7!133s za^akM9e!R$8=Q^hU}Ji}KEw&C)dFrGwbR-dd$b4=60c=^_&br^|IV|mmvx9=hlU1& z-9Y^}U2AT3xxO=x@6j)4=7QpFuOz63B-F7o>y6oO0Cyx{BI;yVs6ki{-u9R zpaAF!N-;-R@==CU_#?};0@5VeYQAln7tl}gm)`n|313U-X|(6?7FdlX500(2F-7Mb&zA|Z0(V-*W~zlK}emDCKppsMUA+d40l zXBQj03>f}ehCd_uBnp+saR&SX!gFIFczaP4IJT0jC~g2|i}aE1ee2864f)5r|J9_3 z2&2w<^EgZ$f{K*7-+@?21Vz`SP(H%m^4KdC_rjJC`Fl?=z=^INC)xJrf09vw1#a4U zAY$va@U5lfB@z^*XDcx8sl!4S=#qU zxQG3)XBj8qJx9a5K|lcezyBT+n%#8W9-s*&m7|%i<(z>6rWY&n<2voqpN<((ia3_uQI$#d{HNr)1CVvZ=ApeKZAJ}zT3nTzH zm+sL}_TS0qR;5k1qo;aSGr1Rl8Cd&cpScSy-ScJ%z$2&Qh`4o*l7;}R|7Hc-K0sa8 zAmTXB+)*ngblvq%?rrP-F)ylF2)4W265}3#Ry@d#7DY}#;7jUtpI(OfT~ZR2X>$Wk z4Ja+aYd2N`MZh6V6>X0WL8`-o? z^^J=Aa+&@Qqar|b3iq0-vQKna&la>1+5uDyklbpTkI{PuGM~a<*zcg!Wv1`b4&1k$ zCU*trXW78hLA=LGzYS0jeBZ3ifp7GAm>Pm~h0@=VtorjoAN$pH)pD0bCHt5{tg!ji z42E4zCArrGvn$eJ=-8f}dNU?24AXY4{mi13yb)RpEBh(;jMQFrh5)TvIXcz7zimaH z%k2=$u0Kyz5k*!6c&f$^_6L+4YiuL~QjS;IR3an|xG0(WX;u7#P6WX`_-AqUCst|& z$*9}HH_a|~xaZAl$jAwbe&u}TAh$1tSnw8gE}dU5k1!%EFqN&cf+Q~IHhA5b|2+o2 z{MvI77SxJP6_(s^pfdOy+%mJx3l^Wwizu2m;qPZgJb~K76e-E^)AaxAR$G^2AKnr(} z=i_2Mr_JTup=84Z&w(g#zPy|je?0*&8wlE@iw!iew$41+mlp)kHLieIGImu$?Ellj z|Ayl~G1h;2^75Y|MqvB!i=Y9e6)r!z7~+eGhO994?_t<+Ovq9C{~rMmUD5dW|GOEw zB0Yr#)$jkO2WS*E|wx#C{{4v4=cDv+l*(r|6(y@%9=Pc?W&3#4Ww z*xDlea^B1VfoI&oY52W=eItS#rhhiY$o>a&bPP*6?LYl*CiBGJp1HL^=HH|MB{Ja7 zT7%tB{{^w}?KYSl?$Mi7i;|&qL-YeigSxF^{BC#hg{tthw B+Ef4l literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/fwu_states.png b/arm-trusted-firmware/docs/resources/diagrams/fwu_states.png new file mode 100644 index 0000000000000000000000000000000000000000..fda4d8fd1e44d81c7e41d421649a27e5538289d7 GIT binary patch literal 114222 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�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� zxH=F)R^z^Z2UFN_`L0-ZA&^x~$yV+iP11BR_2N6sNpWGkNr^&DkRd-#D))!jX8(sh z@-vl53pqw&6M`lTw8KF0-(X(0?b;Gz$Vi2(-(}*t#q03%$Bpiw!~poY2v`+}zRoIdeQ+Qo^BGNqu&&h7!gGbNDcyu;9Y zsJ$*2w)vOeGMN=|_mw?^;n3Ri!>=6pa9kZ4ee@L3v5uX^@iM>C_v|{l!lU=X0LkDg*nD>NQtPYxgLkm$La*boC;{4eL-{IfPSXo);VOZw*3Bh+(g~lp1u?xA6o4g zC-?1e8b#=zjC8xQjvQ=4M;63AN2K-13m=HUbTsW{O`ZUg8ip)!F8e?b@z8JukIS~RT6A+-|w6pB@Rx;SW26nW)-Ci3Ir@p zTl|hcw>Tn9O!9~%w8042z!`7{8CNoA6(hBXi6mTI3?vqFLj)}f{j32^k5>PUMSnJ@l&R$=)Q1%HTFRE zUdCR1)TJ*}N&F7I^sWKYZL)2|?Bw768O*Ae^zjoH#t$iRP`;Tw+kmcNmL`D?q ze;@<(<+fE;n3BDd=lP{jmY-$zg>RAHUT;c=1_x22Gi|lb)JNP{Zc~$duFatvdb}FW zADn90hXP8$8htflMl*zlF#NGdH{yN+GK%i_g}yip*rE{Fjh~-seM!tJurauR_B?k> zo{mzAaIzik1Y1EX42*ZJj9c(!;JgXtN#rM%in2JHi!z&FL=FR@9+X$_Su7D*zK#b; z5#=$K{)mk@x7S$yLPC4>2&*QFomlQhWgWjl*_Si}C?8U9#f3hnDqNg&+Ra(im8sCY zl2A%`#hsiKvEbhg1GFk-m7^!1VgY0vQ;nLp`H{JYOD#gN5)xdLs!zwoDjb(B`|%4? zpZf3o=}aeV$)qQE8;caFk-q{u8EYahsz!V}cx|7D%=Rj2o7!ViSqKoImsYv2w28oy zPFnjiDc>on+_BfGYGvYbb^KTDmf$Jd*T5Mqj9lE?CXJnQ%AczetsEv~ME)vDzh)#7 zZnM9c$?O_~i)SsdnhNH3epcwG_pN8wzCU23x(QoV+_KMJ&|hrDMMC?AsCq`VUgqzA zu-PEo=*g^Hr;Bb8)(jmVzuFiQGda=Ew(QW(6o4H`lTUHoE8F_7<*22rRxn^I!|RaH z_b;JM0nxr#k`RnZ01N^FIcZ$1?@D{XRN>1*EBdTXjhonTzl)V{1kATehiD?p9sj=J zoqKgrf!mJdefMGP`KEpgmnIb!6_Wji?^P$oGvT0X?ET zIXx1SaW?Sb2t}W>6KZ+Er%2WN0`wd^8i#gaYQ*Qzd2I-PofQ-%_HczmBY`eg6o0>F(JryGl#$78SlG{% z?;lSKu&};|`@0?U`nH`WRG{;lMr+|C4dp|Zy`9%(mC`F05`%ia?UqYCo4BzP&=ucJm!-y;vp zVO$`bkjIoFzuDx(?+(%+!%V|fQhrT+_L#{0ZZppx6bDe$ut#5Kl&uQ*i*F<)5QJ4ll@20$||5_g5O3 zH+Zu0J#bE2r^vga9e`(T(*#$ByX_gLA2DaJB~(DAAqm%{CyGKE8{HXTJU;mWg<`R4 zMMB~D+yW6H&U)Y$9H7ZLmL`!LukbDD_o1iR<^`u2{8D0Wdbd)BHeE^+z2*vXas#jT z=XF2uI7LYxY<*CFOQ{8N+Nz+*uQD*#gU9%jK@xI9QJd$0FdV+kXUG4Q58`U6V17!E zH2gw;6!Y|9njU3b-1t4n4cVw^Bz)pUR2>IbqZ4_ZV;{y-_^Og+Xk%RAnVO__uQp+q zAG{+4rTQ`MNh^1TBrwGJv#>Y&UBo>@DYc<7*7ro;EHm&{`6??++!X?DD zHMP1$4x)bheZ0I6Q`|E%f%Vbq&Nlqlm5^ zOuWF4|TK246(1<^e+nK9VbrGbZ?L_As~pF zQY|w{?N$t+3jGrYsqw=k3N1Y;_V7~G`eVB@fo zU?krjwJMDBekkhj!D~+ygqw?0s_??)8ixrpX8DljT z=|2-hJ!PUk{ywX?ncuy~dmBGv!!&u_n4bvVjyTcgK2u3$X$>2~6Ef=mNQxyS{+^B@ zy73Vohx_%qZKiBNpnpn|r>F~g{%p!bD1zDnX7miqRFQ6>cJAP1x zVo2UB%m_2ZrGHF7-5w1E$#jXCni;0cIoZ}d*q8O6z@5x5=Wz;1T znp?c{g0ZEc8 zG$N6?m)(kJxh-ug(mh(^(kOHP$hjF<#o> zVkyUq9hi&569T0LriEzEeWir3?ioa9PjV)2(?3GAI#*O40mY*!OvZ9ltJ9KL)qjVG zfm;CnCJOSO#yy1vttJlAmW61lrEHEPet4}Wzu-hX?30?h=$w9O{{^m*K8cC)rcK!i z4DDqxdVN^4MFs)B=_@)_8pz71b4UfIz|Dxf4Uvq?1Yy@kl98cj>&=qak-DI zEx(7Ye0%0XhqH_nz3qj-kCIs#z^dwt>%p1V40IqKUzsJxl?EU*3>ZTR_=CDXS1lV# zs*lGslvon>8-?yjS*S8b&XtlADS)Kd1V}kTl!C4`WrZfLXfQiilRt=*a32j zHEiQB>c1)4r=pw8m=&Ckq{!?6CvWLBCSG&!o{BIJGbsh9=&_9&kVy^J99deAa7 zNTTPbE)LsXzO;2NUDgEe?2AHPOM<-|jm}uK^X{}NTYJiP>|m)ti!)TnFm!v`InBw77I5@Rxbz*k+$nO7hXj2MxkNxyym;{>Fsrz6bnERO0p|$+T@@_75i?4WuR2FkG(=Z~KEN(p!Kft!4MZ3}~+2oXp zv(g!gix}3|AF+9_Hb)EOqn!W?=PZSty8`&{v2S`cpJ@ARpl3dh7pP`LR;B7MDAGc1(8yO zf0n}+21A_d^D*`NF@YedBoFznGVh*%F@c0uv=?8cJ`!)lfJ_>yYl+vD1O(zf9IaQY zq#t&0_?^~!&65nY?L4oWBMMbCa8OwT{a2%{cCxq<4!=kY^`qSlE#D29{bxaUltfrq zGCrdj9k67te7pdiB*^G~SLej+_vEvHMO3Rv!ZzqrMZq%Dhp*F`Gn09*x@a=$S6(oa z4|NpRV$*k6{&YsDc`;^)_l;B?;I`t_=i?c`A6%HBQ)*3zOw1Pz3e^U9s~VQ&@HX*{M&Fxg$Cc#N1!}4!obH zxykcxb1F&fsuFXvc{`ufy^Y{8E9(o80ss(DijcXe>G}tsInixSj4;IlRMd5GarMsb z2+}a4)VBMDw)8XJWG%!+H^+r#?RI@TuqNMD7~aq85gXc~Dw~s!(1w$4Qs>Xaswge4!c1U}$@f*u%-6yx=J*=nGp8a<)kae%gd7PE~W)oYwPb zYY^;puE&mQv>BS5&0kJmn6rhoPc1OG%jfnp**!p{g>Socw&t#hd`+X`Bu7$S<DO`RnEpjkb)NFUV@DDHHF#N;Gx^$4tc^j7<}0BZ)tob;+4;MFoqefq~Ls=@ptH4HhbDIHB5Kp!ZXKaoBTZgI^Y$9|*wKDZ+QZ zIqpCcFMz~ZO4E4hiQ)m+r=0EMm(c;vB-r?RAuvH4EfTQ+N%e5>ML-xwYXd(KUM5$c z4k#f|+!6#7q3|P(Q+O26!m-u<0@sU=r~Zt>x7N9ELk4y5t#~2J(!bV!mB3!H(uqrb z)s>;c{0e|IfK_=5IVJdf(nYACL`ld1slh?W*KPsBD914=DM9(L*IaI-M?+G>3be<) zG*R9_7GU1(FV2J%@`@A+dovB$f9jpeSt#g1GidrFK(og^VEQVfI)$wi)#_Fr{$4i< ziy1SZ29*-R`F95E^GX0p=%q+l97(Elz50Q!P&7Zp>@)w{ zlwdRRvO(rdvK{+sSEo%+GppxSAGAMSr2va4;+X|(Ffjs*40U^oj|a!?M-&_)r)&F& zK%KblgXNA*lt|sMPE28^FYStee@h-GeL6-1+-|nOD3MxAvNE5GDIKG&K!4e+BJlyt zteX)hx9;!7h50ik9Z8kvohL8 z?iWW)_NQT*F)u+UIN~w!R}#XF9_5U;tOt0PoIKFE=Arp}4}P#Vjj;tFREQ1TloZ$3{p_Z1?-D}-I>Bz( z`_UZwEkBy%G^KB0#syd*eLMJav6UiP9h~?>yyqW%juaDC`(VUQrAR<__C)0p#Eu9oUQEAIT)b~u*VM+ zR_55|2x;*5q<}w4*u=uYG;eksmSh-7%m6r&9IX#-g&6}%SjhoTyC1-U9sRen%KK)J zv*OLNXD~$e&FQ($Vnwti^uSa~_^$>pYPj4AQ1!l_ zpJ|;o;dNA~1K%vb_VxV+1{a^m%h*CtT}fjr(390#emGdR5V|b>i~{2Jey{zkIU5Dz zTEe&(%;~(xx#l?F6oFutt_O0;Y>|m-9XeH;{W_o9%luX>Mkv@5=)m+}!YF-BJ#ML- z)mFIxkbD1|n0lTY!M?WVfq%Xl_TJso_6bMOljRGegF3NiD@{?l@ovqp#%?%X~*76YyLdYltj{8%n>o=*GCA##%uH!bNm<6 z@AF88NP2T!I@^>VO60F80bJOZ_CMen&8yP38Kc;?Ml?w#JU$#fw({c;m|V_X z4|PNUZ33gkyHS33Yh*H5_2S}s<#-FQB~Ffck3Uk-Vh40ZRMxNlQn+qzDK||372SEQ zJ3?V+Hy#&+g%zL<)n2~agf=UI78CH1*kU)hMO8`h9(hhah#{l> zCKxrlJ#Xfle_}ciT?~0+srdkja64q?11=C}xXqdS&?6lVh58fpbyfGp{CfmMlQ%uC zAcG}quMOwKZgRz#-KeG|V@6)!If#R};YqlI9kK+(z%7(;$Y0RD=wl)GD%S*na(*g2 zqkUZ=vz)grk0Hpgy@;AjnwUk1_`DXug&70<>Z9_k*H1{VlPw^j755(lhCd{# zi`gYis9J}F_Q7>Z>-O?sPvColh%@Mv(R)PXA6|2QI#ohd0mWV0(%m|jkUq0lJ(3WQ zu7t5BNRNo|3rMIrMaBKTw8DG~NSV29jOd&JJ_i=4p>kJjEv6H=y1He~q&%Emc&NR+mw#1T_8IC|e5DI2LkMwQFTY1!YoU3kVD^(#w z*OKo)p2F3*jQYAm*7?^ILiU>lnKTqM0GT_|e>li)=~v3TXCM(Yt2yGvl;^nsO&RNH z7ksH6{!%=cj1c=TIMW>K_+999MdmTOjYU?ex-T+;RyDh1K>%;_2Zv{9**AB_Z2Bs$}71$xBVHk*PVEgpP)+J_~qpF z6S}a!_|qilVI&zSMtr1Kbup!TPDd>CFAb?dL=u#G_I$3SoAh))h#C)p=PJb5@>|ku zHdM1wEa2%XNf^bVL%pI3pJ5Tf{Vm4YZkyZo!~%PfKy4TLZFDmX5>W}G7CmwYV)tjH z9BmuF8cjC&E}t8sv-< zI&3hNU{GA9YOrWJ`K!OYN@b)JiQ*Ic;r{F3k@&dqFYB zabnkT9(+`_Ei9JNLXNUbAcq}S^;ldgo8N0Ep79NU(0`| z!da}PycM4Dc@+&=2pmlPX(K_$DTlh&I`D>8Dr;LPqt{e&$k$^tSK5gZ5+6(%W`f=# z>B18F)rm3A5?6f>*qrpcz+t@}PD-ZEaWpG}F2T>yb3uyX{`>xB80+0%Uq?@Whuuu* zV*c_zi|hHIIgyXa*q_OX^s3E> z-Nb5JHQNQ{*&nkvROve}bNeL$sQ(gJj^kcQ=Gu}WOILGYUlN1jG{7I#iXZ_Jy|++h z4k*XpJ$vQ;hTnIk7c&U%BmuPHMhTyOzbqoG9JXB{$kAUCoslmh5hA?n{?|Gy>W zG4u?i_?MK!V8Aq5r(S8fV)W*tpIU~ax_hWS4AOc8NN<`jguJ5R*vE*b^vB~;Hb6b5 zpr{~rDG?IMXipFRwB3ydr* zU*h}AXCl>>U!>PYTE170{fg6YId9u`Sz8go71_&U38J{2?Qz?mH3@oKD61a|i(TLo zi43d%I!vdFcY8X(;dirB=uAF8>4OeBm1%K5T4D{xO8C;AgNjGiL#LhQ(JjU0GtA(55(>qaMAzFi@HBmr8z{{Q_jEF{Yq-YZJ#&Ox+Z)31poB(H9# zmu-q0sOs6Qc6+Of1TFIrJA>c&rYM5^f2qlmwy=+MD3?Z+LK^DM!TEiRDmVeP}`$A^y0MIMx zj9REFh!j>Rb(Wb=xA-M#{ORd8Sx*!Qf5Wd02Cy4oovRPB!7^EskJL zya&)|o}WYNw7_ecR){VqUMFYtcr!!1`vf;$deR8%^R66Iv7oX>`oH!;Q4jhO%M~o< zVIj8y%zt_5sq@98OeF+%`bZXk@nqV0?08Cqk&#j!!7Y2Kwm)~2%_f&wDlx{ zO9sp1t+<03ab70S3WbG;UPw+NkY52%=mgf^qrpJF_*9nx-1XPj7@-&ev}lWf$L#3I z3Y3cAy6fYS1U;E$((@msKbn~999;k%p!jcDW$w#9?!opl2|biqG_+lv1CM|ByJi3^rASWyBBjJP#lV~q_UjrM zCTP9OiN9bGyn($0AiqmXze_*gJE)?|1l0r(9tqf?&_jWKU*n^tmMcyZJ<=%uedKjM z%YOEuY9Q6}1a*z(1%7&R)h%aFE0Xgvzx9#}zVi9;U z^CU>%k~h}*p#o@IZ@Yc`AZ$ZH?~JM_BW}{=@=FNc1LpwCN2UOALwRtI@l~)|Caj!bKVxx9oYV_h{R+VZ+sfqN9ueS?7Dtj9*%;Bmh~e=?7z?MNR)H zxukgL^t&3PxF5^BDbCbWZDDWT=f3U>$?McW2S8GBp^1RWEV`kbTLguvzDIHe0kB@*ViHJ0!b&(( z@fo5!A1>M+W-QYjgUNZXYWNI;_tpRKECJuJhKEcJqwQg@O?2s)LdY^NxDw61SIoEg zZ{BvD<65^dE$hs_QD(dzv8I6@bQ^w<{f&HgG;wkKn}4`}C^@eOngk^=Xm`m6xp(%T z=)=`o>dk&~`|ZKy+@Z*kOG(smIA`LIj`eFN(g$SOEmgg5{YssOd3K{C z61VZs@)Nr$Q@(O(%sg6bX~YI~;>-ekKZuE8)n0GO_yRzKUq5a*6Hk8VPPSCrf#D7= zDc~VoCgosx!3SsS0Hp0gql$-!CMobsx>gyKvUzW0bTn<+(@^@sC2UzhO-tosW6OAt zL$%=IUckYthZXC^?t#{E^vRvdL2!_~HctSS*4( zyY#&|LhI%>hNOmfA-U9k z0H!KrrlvTS#U=rc4ynW|oSQ9BN*Lw%S)k-sQm@ko0RBNTmCd1TN6T*ZPEV{&rDT?O z4q>>6Wa%WvCKHlH3)DDd&;*v;R4YocN$QJF@WMYFkTfc^pZqwQhkR3EoJtYf1>^l* zF+4X#mEF*|m(BCuVQvZ^ss&Oqw&}G#?&QEl?Iu0kj+X3?817eY)Dvt9mi1HJTlNgP z>Qh}9?^|~(lv~tE3=T~PVPj$j!9Qpd#|=tlxhX=3B>eQ?Bfqf337L zAn_5|g$BGY9#Ob=avQTB=vceNXpB8CFnDPl&o%Om>xfILmkm&iQ*(iv&rfQu6_CLN z5Mt>!6n|@WEOemXY~?5aeAMunLbnbnytZK$-3a!Py+^CgKYudJcZ(zUAJTHm-ZR&i z40;eqyTEO~pL{^glgPTlXjptUeI}1#uL!^A$JDBrKhHy+!-{9tI|>PtRB_Q?o z!PFoWt<3H4`3R02;aRD6s?2zXwT&-T(2@Amu&Ad2B#a^y@klD9vez3T>wgk}dZi9TR2ahS# zGOaS$djAmfLk?l1aF^zvv-$nu!|2vdq0++cC_1iU$xY!)-2GH3h&^%{Z|=Oq;)9f9 zEGwdYTlm(s;iNsLK5(uoVrt>?U_t9NpVcBKT^b{cP1kR?(6=PM5Irp&MFk#Ry7{SD zMDFPKKC7CG*ZG)iMa$*<>y}h~z)J%z9iavU|Rr+2z9r zZ#bvCfA`2SoGC&4VZV^se!yqD>3XPY>gb+$WVgu3<}K`OkrLVrEy}_d{oSWcuzeaj z&aWYzV7zKQG5F0@z|me}!lJ#uMQU-;FpXgg;>=UGC44Tw^F`P6qKhkg_3r1Vx>Tf*qy0pe~dM4L~( zY~X+q`FHi>hmGR+fRHp6#osw_-t=VIw`-;OyL)4zUqTHR@>Ei$0YT0=12<63d1oKF zjtvqaUTxd<^ro(MSk5gUi=yh+j}c|jtv|L3L;eg7?K*XtRwVdJPQT%gI3pcbqSuna z(sC|tR>Mt2rx+wsa&U+4SifaKHv0rh^c`hokQ6|Ctn19bC4d+?veRZ7oqCQ9J=naM zc82IQZxL+p=wLHk7Ykl0B=kE)hY~J$sY*8iT_~iMB}F)j!uB@gb>)#VsMyMI>9KPD z+8d3HeGAw{GajUMiT4klE_dCDmR?4$fK*D!$rqqLX5ZbHy_L%lN3vLB$5Wm7hhAy+W{wb1^Ih6TwYv4l z=jc^lFqx2BIHF}?%P*L=JS8~VXNf!<>|UZvq0>qxb&@-_jB|clxx9A&;@jS$ zh1uVdGG7Yswd>O~hw1FXtCWT}=eH}_KL~gN4<5IBfn857zVR$mAEISWG5DWq>-)>> z_by@6;~FZD6+L{LI2YFFkam9O-xOS0nf zb_HzvSnSaL=DZ4)R-7Zxc~Ya>23?5@`83ZO3QJX+qVi#}Se`8(`XwS^Ior?-OUlvo z)Q{dKxMtO(Yifj;ISxpWQt_D}`#Is-8H=dZB9nj8BV{V3OGQ@UGzNGH1q_s1L}&~D z!Wke}1!Ad9_keVXmyx%)4JW^Ju>^(Hg!@$qLq;W#u^7`9{h?_AG4$3gsSh5ky(oQI z|B~q*=j?)C=c{^4Sxq2>$%jqI>aR{|b2 z(#?yMwqmO~rU%j*4mC07n{jPb%Jd(ZWm&4OzWZ#g7BV5BxkoDa>JC7?OK}GsSVVp+ zeX#%aqbUuMr-^?sNna!0S5lAS=y$Op2HhjTIFXN7*#+uI`GeCe5^9Kjk}_kdcH-vp zKOX&m9xERA2!A|Im-0kLCXknpac$J-Ha-4Tfj^{7pcW40Y+E>+V&U|>A;BA3+)U-; z_?&m}W#@GoP@GPG%H4!E+IQ~CfWr-pq;c7G#!55z**2r!)D$SJPQsgcXpxXNn)j;) zERIIgUybtPoCoOaH?&@9-A$e+Sp2&tNp>V?TP}Nf;gsQQhqo_C&(t(0ch%34 z#XsTMAVrm9PEzpSkLVvo9oJ~qk94Wq4`fCo>~?HDV5@BSSBqZ=<<^#^ z)`g|p5Y=vDmkj~JuNXrw_l>l2_Bx5zh_)OXAMzoX9~)!da=A1izH?N7IGFFpaId2CG)!0ok3?R(*=%>{y}cYc(rmnHY0om$IRHqxlTK%WSN)^Iev zAYJPa^I7{|BB$c}>#NK_v$qsfSGc(Fe%p&L?cc+r+2j4`bEAonb z@R`Bn0ba?yl<{@ZAN$|hi?XeHRTE6$BW*YJ7DLsG5f|2hZFPO4PV6FHEGs;h zp_!g{RtiJV)3toqDN`+|^hVzLuEEL3#kUS21tsL{aIerd&*h5WE(mRQ7|xk3G-<&3 z0Xx;*YJNDthd-Pjj}goE$VW|!|EP2!HJxXTkT%wcn41D-ZzjC-?y`2vx2`TYmKc^W z*spL_f|!7g_QfEwoL$@tZiQz`d_>}57P@P2}MbGT$obT`MWSu7!V|O4tC|+p3^p>am3FauJ(q*mK+=U;`{Ov|UKodwS1$ zf^HLS<1-C5TcIbkY>3b$47#h!%zlP}?1#NEpP)WQMG8HFx7nIH+#bqk`{()1`)7k+ zQ6T!k?Qj+AU_jZsR4+m6tC!Un?a;&e?PcBaIUa)Ec48cb4p*)t-Oz}MTm0$VP#nT? z;D&J>JsAVPtfa-Vwh361<^zN?x!4IpTqR}_kV zdsl6Rq5!S-Ih#p)7YYNbC)+BoGyxP$ zZp;tPj=b{F`pldj{lTfNw2W=O{Tk~~za4_#D^K=h^Q|;gDFjl`!Tvc=%!HlM(;Cvfsp9OoE)IL;`t|@{U zVs%imb)z1nzd!?N&<+#vEH+d?>p8hViK4jr5awj`;p{n6jZp!ZW&&E^Ow;jb?nN3( z3+S>#6%<{Zm76aP*4spV#)iDVp`fu=-uHiG~+*q&53YcF;TBQl&$=mI7TAJI`5^*G{Pal2g zHOuV_5`yn|Jr)xp78mtdgX7u<-;7M-K3HqW+A)p|nTbM4o8KSdLY2Ptu$_=rIaYi; zw$?a{-GOb&j}KW~4y>Mxe=ZpM8VY*~X^VkSq<-!T@fN%ERCKsE0b4?+_Ehg8*l@S# z761~BAf2zz7FO!L@Ar(B0fP0s9&&9^J2fgGy{1zeiy$`q_QKA>+q zVw)gg@{^1xO^45zuF6H!hZml@J|7Hi^_CsswswW$w*_>qtOlM*FwBhYFj$j;sa>jv z*<>LwNlU3A?6W@qZPmC#owyMTiSAVnJl(fMuvfPxHtst4e!T7cV!L^iU1q!bPXPQt zW|G}7!z+=T>kdJf#{-j;+Zg2hJC@D*x3+Fv(H zdDkXpIHVrTgwXqhl%+7lm=;>NGj^j@+;{>^WyW_6IkSn)fy=1w2n>l%6ck7~mk}$% zAC|RVPIi4ZfTnMLaBA1ja?^BA|4HL?sa8->M%}Y9rSi`%DLR}uf%4#< z49qwDD>zpSic{_m%?EszNZFZwcRhZKiv&&QH-)gV%!f^f2bs3X$NPqtH*@*teih9% zXPZtBi(8_WvT5-NMweCy-#m{-}%rOn-3q*V1|pxVX|!$ywxKy&~iN~ z{eao#(=S0%$rT6iwQiTABb?yoPXxsKKPq=pX{H*^N$)WE%3plF1L|G4@Ed^GN>7nL zV|0HG6mrwx3`YPY`l!Q0?I%q%i!?rjqWN_5i3(in%&&6&;wXkms2$^W3EQne4OU&% zm%cahus_l*&@Zomf5y5i1#MeT%|w*#jdZg|Y`W<;6U?-yRw6iDE7}6fQ#;q}`o(Um z#hyxZ08S$eC_NWZt9s5e4HxHDYR0|8*mRtAd7dD@cP8E=Zi7lvIy+S36ltlMk)0Dy zP+2+Bm6GL43;vjRQ`rVa+YbqSM3;glwG;O4uT2{bSxw>4GH!nO(0@gprEo+@sr&$N z+ryh(#@I3>6y9~ytPCgC#V?f6#zt+(QqEHm?=u2&|JP@+6&2UjMH6}6m{t!3fm8E{ z)h|3lKW_4G-%rsJ$bA-NZ=-#v`EWA}T)m0N`+r>hbwJeH_XY~f zFd!h(pi+V~f*{=t(%qdRAvH7z(kLk<-QC?VD53(=9TEdbqY{!*^6r82{k`|z^Pi4q ze|D|4*Is))&tvJiJ=JOk%7|Ydly#p>+0)fl?IY~V1#f#tHD>L#! zcQav1dncoDL#05Agu82Sk*Oi|S+Z+?Whycwd~?dmC>CI5OKsTuH8~J>nR&Ig3FdSZ)C>wj{%*epIngfSntoE`#Kyd*meZ}iEz^I`^OkSL zTNFu$aAS_*pV1`Du4PL%w*7W0$*waY8Q*vryHFulCdPFnC9G|$n}{aYFKE7C@l##; zGa*`PN0*z?~S(&<;Tu8y0Z@VbOS&ev+xD^zb~oHzSr(0*}FTCZ%Y{+XHI zW0m0J`6Zg-bs7KVGDLsk%nZ%6&qOJw2V|nUl<&k|jKlZMYbp{9F?Rg{Bk`7u3*8sV z(_!8PP<*k!OHup_-*f$4`W2ule1^-2laXHlhf{B9E}r^<7*&o!cQ;3PBACF1A-sXj68Cl5_L-u0#7h8GWT1&oMSIEUnB&u{o@@ka~R8=@ZK#?A<7`kQT ztaZTftK9^RV8-XBIGnsWR_dAc6Kbr8Ep&&yp?Sft@p*;{bkDmbdh+eCUP{uXI523q z?KIAR&w_pIm060f@@*=>#VUEdA%YIgn=50^SZv0A=QYS#V2hu>AU|JrM9wE#T*#R2 zk-{e{O?B#Z@jTSweBOH~Z~I|_eBZF&aXn7ZQ(IN=Gy}_F2+W&sIzf6`bKO%Pw883e zm0mp-Ws>GUwZc<4HNE=fpNUDJ+WRJ8eJUr0eTeQ={|Qd-KD`qFxQU;x#;4+LnDf5& zdoo+<-}^j@&sh}P&VLM79Nk~$i6PTf;_T-mAMfG0Ba?Pe1Gi6UIwABFGV30Ho|r}V zsCMr4P+s`xrfDVxyyf|~XsYnLlx64u^N)Hf4j%3>y__`N79Rje|LB0|V5qN>hNITX zS^>a*JeFWdCe@3;yC;q|SSj&vB|}S#813zrJWPFzB#CB4?XY!X&M;dVX-QI|wwyBtSxj!T zCMFQsc-{%R(e-xRM(`lk{t4>c;w+_Lp(JEMepESqLxSbrPxy-}tM%3>)cYgl;Zq+6 zDPBUglq~QNwkA>JOjD4SGrW;^Kw^k1!HxN35xt7O$((JP)zk3>iB+Kp=m>X37FFUL zEnw!~M%ZY27yirkSr)5*x$h*Tr8bqI?sX9Ud|n+BNYBBjX+c*2TanxS>3K*X01$z` ze6MU?5Yi3h@ZACZ!Tc`mZ^*+6#iY+^<=uQS*X$T$ORshx>yWkvJSJx-uOTvurBP%ZfG)prE@70NYX8~JlmS)BYFHFcbOM39&{s`%vMV7OQaL%kZ*rdbQck~hr8*p6h9AT0un4@Hve{qwej6=qc@ zDhz&`2^kPg%H?pP5K5P)AR<QSGDl<6)lT{J*OE74LCb^y>O7F z{*5qoLkUKWzQ$jpdT-4Ht5Xv8`lCy0;z3x^PCk*^-jmbVh~lrHSRV$PIt!c)h!0dR z{#?N|J>;g|A2G<#4`w{MX(YIgsE@yVNXXXm>Tk@Iz^3s%Q=g~R53%TFU?0gfPt~p8 zXK-&&aMf--I`~!RXw83`78MO+mf~T`3$xdI&~b_2TJ#h z3%mF>Rl?zK_6KuihqS+$i^SPgwK6uv!Mtcj;sd-J-wADyTZ-^IK=$u5e+m?BV+JG) zpsJ^p;hUiizM(DuJv5Bnh;1`<5y_bMFf%epL^g5HBY_7gb|Ff;tr3>@4y&+?>oP!L zvE*rcH%1^W7RgHZJa`kUANVUm0+2Fl2^pw2sr%-gvA3bmz*oW^4*bF75L5+~KObFQ zd{IMHXp?+U6e}p&okZdGOCHsL!bBKZTzufoBR>oRA8C8!*6X6+HcsZPrgO^FS2I|$ ze;{azWjwGr(!lMx=0!mCor>>JCXN~S>7xJBJPQ8! zG4l(6Iz(h^UQkcGqFaFYMXeA91BL!pJpezov zE&v-$0D>c+^RAF{Oa#_+ifXJZol49{peffA)G5?9aFD!%R`Bg_Rj*7oY>q@x^?bKN z>*FRt^CB3T5MOxtXhQ^4CMBMf=X$f8!ocGyj@7sD2$78jb-PMenYz;Of_U&k4eKBr zc_bK1zFO@uF%vN0N<&kA`Zu5XB}oPuG6E0J^1NIB7p2gz688kx4v>*7{(~6=3f{pB ze3q);etbS2GuLoz0AFY=o{CF%&j$^hA6?-QxJ(V|Inp1?V0^4k41k(ryP=M z(MGfQr&yZ*uK19F^_T=xc@bZ2WUlS%nQc;QR_HS`2qaBG9G-lnC#4*dxRUXS5_4G|wcl0ZA~vW9X`O&fmApp*^D3x8TE3uu_W0f)8FUk}|10h=6k)O{=JL z-nTeTHI&p?%z{QZE4sVrf3#cvH@HH>c?a$7kk`eZZ?Ewl!G|+I39H=$A;sJ4xdbWi z0?06h91a1V)xTc+_#!HWR{Zswvr>@73O>%c+&h) zk1%|hrvi`E;Kr@0zE_}-R-)*O1P9`1%JB8jC`fP?64cx;^2H=Pu~J#;x@Vd|^amWL zY=y&`Dp+oeIhGrs;4JYpw)o5!Ym-izm{GVb^BWESGcyH<%U2B^kGW6&{@L;Yuj?P> zNV}-phRuI(m2!I=^*mz6TF1E6+H%q`%ur};F4DS724)cMLw-ytJDV?Pl=nVnAHw>;9u^6tge5Q)A3YhCbA+Sg8%ax>A zERcCVG|Y^`vHb!zii(IF@1$YSzkI5m&&Bp!Z(sw^f)qLa2Ntk6`4A|)P_gQZ_1GU${91{PzZ2Yq%|gN6fq?>O7kvsJ);^YhYQ&IJdR17JS@6Gn?*2Fm z;p9koVUoh)>5%7p$7ihHvje6ErMJEMli2fzkQR7>-?8ML#=*z@VR4{#-|dWGBsi1xgek|eSZYrC#2*JAK=%N6#U*Od{~1l_Dt1pcOx-p%JEG^d zdh2FUy?Pg*@A73_48L8PGc^bv(?453(w^F(2qyyeCDIHbsEi z=aB7Kz>t=LO)2JcpF6a|suk^V`7o&5e?g5*xC`iT3jx2)3cdh$tacgHZ^P5Cn3=cJ z@wd?vgpIwC|K*W{?`mEcevek$uG*0XzPdQJceGNN*CLEY5;CS-kcG?J(!=x+^6+Bm z_Q~&=_#d&keS*Z_8*GTJ@J(kx}g~AZ& z`@*^r@O^1r5<+Z_M2i!u8jYW{U2r<&^KcIIK3rfkBnj(Ge#=all%^Jm=z-rJ`WwNu zUmuIYLpzoM#No6a3l|y$MYd{Ww-a5iB?$=wAd)W?|nqy&5n7ijubi-}jMtW`k{5$#NpF4Z-ZkK{O zQv?k_o701cUJ+QqdsVTtYC-@e0$dt9i&Y_-Gd$V=ByC~_+6-eq^*UL0|U$BUp-rYKpT4dKPOWdbk%qE`g>69aG`?rp_)zv1&> zC-IQ{%rCPYWdX!d-YEyTy1!6O>|OojR+>9Bru?-+D=1eu#xL$(*1MzJNw^OHo&zlVU>uJ2xI>#c<)805tjuW_#X8D z9l{GO;F7b8T^^~gcNT^wsldkSp)ZT>U`-H=h>@vhC5w%*h(q6@FqE=C1_BA3prAnK zBj~?AQ02@itZ_s7Lp<|p9=6%E9ZC-gZf+l`(ezkDv=eQi>a9C^?jSqzJ(vHZ1&7}kw zlO};Finmw~XLXxML4fCC0YJeJ6fkz1Pti%23u>{)T>lMP5CT4vSUWd-bur8|o~Knn z5omgvX!?1;fu)+KPmlxUa!mkg4v9(b$)E&_X02*nPxBIHQVoUKLqRq6=SSQ>ysBL% z+b`BQ7C{AVt-Ed?3KT;RU|Gl9;Lyw5z=10TcQ^tUS47JT;FUl$6a_{$&-C1xPnC(( zh{S_h{4o7Z#1$w40=41Pm%(al7(1?bnrkMUen$-*}hHA zLJVqWk3c1RGVLjkZ%i@F%o*D7r8C*%i|dkt_V^Z#Z%9p#(L8fe2f<5K;2vUU+sBL~ zmU*yxQo+eEQs$WJ=JI`vynzAaNiyLclV zV~!*K01egl$N6x0$$Mh)=XHeNf@wH80yRn{($3Z5u}=ZCeSm^Eo?M3v3DEUF*VRJr z-Wz>GQYVhq+Q7#9$_P*zcr88_5jBJuXmDB|XGfA{qW>YTqxz@iqYarh^%re#xF?D{ zViWm8tV6|B5Zd8_g73GGZwkge+4R8psibPFr|&j?Ux)HUgMc!{K+SQ-NGo%nSyT_9 zRvgmr%cQ<9O}sRqwZXz1MKP#3nRm|lHWb8k4TZ%u#=~Og_T*o)4Js6tbp6(JSD*XV z{p$_}`^*cQ1}wOIQG$tBg#v!k6Jy)WM+h5A0HY}_Y5NGk{FlH-b7YSgl@g77IYEE; z7goDP8ta^^a(BbGbnh?&`!}*pcWR$pvsC5YM0rF2U&$e!<y|UgiRm2s3ymYbhT;#8t-WG~CMm*-_x-O<{IgjY z03oAsE_OV@a6eU30wn~AC1=|L3W?&#>(chLXNG;&xw~Yh9RZkOyppcVRabUYnG}H5 zU$c+^+6%lG4PE$8bRxXvt&s#MV6ZT2kI=~EDbbA!XetWZ|4<>JU_(bsv!a$7)~A*b z&Oi*QgC_T)&mrP)VG(G7;n**0-%P~z+B;5Opb)>a%PzfK&WjW)&PZwg#PuXYc&W=y zlJ>pc+&b;5`I^&*FZAA912cd9lEQT5aj4B3AzMv_DWOw0M_U|J^_-Lzq1>Lu`(7hf zMW-hBP$~%!_E-`!M_H87>HKalI3X)}Pu?)oRH0(1J!=B$Fd!S9?%tPTCF+Tf`MYWv z%x%bt(Hc|YZUHuk>}QohEiUQK34b;%u$Jc8lt+n}WYrl2t`?$ThAz)@~GOBkj$d_cWaOG}oz9t`aBW^?QZj0_6zeV(10+ok1d@e3&rh?jPFJnJ_^{rve~ibLxa=H9e)=1EdYJge z&R}hnGwNXS!z2v>Hd;m-gGgkVZHr5!MUMJAD5{g&Geo*@Y+Q{p6icy|py&A-pd4*r z`l@7`96rGruvsLb{c~P9No_W2prEb5U=T2gs&2pfgK>}Y!uslW=L75cBaW-JHviw> z4%01$bn*Wx&^!hy!JJ{-)RC2W_TE;lU)UZjXYcTK-ojw8Z){?Ff%xFFz1W(sk7tL9 zhXMT&I9U}k+qQzWewEXscpoe^B>yO=qIh7+U3M6QpxnkgHO@a2IIiLz#w}Z2ecV&M z+T!@J0vJ>c^zgyyXM8_`gD49|jY=k9 zb+gZfv0DN3Kn8V}6KaXtNg8-l8nXe8sl*+Wq(hEePG4(!yS63c`vIO5RcT1+XB)h+ zhrnRs7YObvxe=42?OT#(XNrmJZ%JZL9Hs+kEGntkF`;=3e|>c-E?(J|={^-Myd&o* zr$&c0pa>&o34BSEBCU;4$yCr{^V(y9x@(*^mNO9CQkGPNqp&rF5BV2fz4+prSOz)< zu#nb>iB8!wbd9fdCQuN~v*5e@n6A(6^g55tOSjcq+fu`cUV2i_Z((TQl{j1TTypF5 zXS@ktlf58q>-Iy{^elm^3*z(Ru9;RAQYe`MY@K2ZS(h0!R?=ePfPU^k{oI!jQ!4j5G7(=@OH`|BHey|)q}pdUBQ=@Qy9$)+IF(=`ks*cs=hr7 z{65C8m=p6YXcE|BowrMAXPf1tCSoNAYHOwVqf9FO6x{hQ-)pPeuSh7oOkAE4!Cf6! z&O&A!GR8RWpLYYEHCzc8BK?@tJpC!NDht|qfRr;u-b(y!s174djM*&R#pU9aFJp-` zz*pXnnCttPK>?08fBKvi8o*AUvaKyAf46Yx??e!n$I$28jj+7*J^AWVa@_3m`HiG8 z#rGT=$p8vp_PplV=EpfWT?b@W0`S=_0XoSz|K^Qsf3efnm!qT&_;Mu8PeX2bJ4EN`mC!`{~Xh^;D?d5*0QIl=`|09GRgzWM4D%4KQ0Duc5odR;e%o zok|$q(?)f|Z8wR})ZUx4m7LtCBR?0jQDo31v}*Znw7i{rh`3zRh;*U7mb~;WIB#&E z_UMOTiJiQ%kU)dV{L+-ea(62-iv0;U*UEMG_PRwQx0{K>;mfFR&#!&SjxEx}!_0i+4dCjglax5Oxt07E z>O*hc`5H@q59@*stra(3J@FY_Rq(}L1uLX3bp!qVC^oPi6e$-4>F?h%T%lL{99R2h zj|X0!Q(^#4RI5jTQU!4B70=S8V!JYj6oi1csCSn0+?uz4oqh+jillDf0Z$w6e3Etc zUtjLMAro1Q<1!lzWj)b0tykxR{GaGLzP!DcrPiPc=uC4Sqis{MjKnNw4~V6%8r|Y1 zOCt1~wptYfaS;w=wj?&&s&#wVt3B=G&X{PS9~^KHMKGcSSYTC9izTCjIK_9FHVYU> z8o~BN2fwr8BjC^2nx(+oi*w>$Z^&v%aPGp8W_&_XnR-Ydgw4op6s)&gIH1T!eVZ7q z6~7J81zGaKUcOb|7$_ScEzv?0H^m7xQu71n8&C8K(AHVd3=HkC)fZB;c4;DtEAW^c z+^GSc#zG#ZsT?&Cpj)nP3Vlyba$KpfF}fSdzoW0hlx^Tf{9s$i1XQAGZ_^q|>C;Eg z((Vs@0DT!B-~5$p9`H6(IGJ06nFX3hM^lbgNiAS2^e3SzY*=I7qJ_{nGzVyoz@BQ4muEC$;-^@^$C-Qq1496~ThQ|YdeT>owutA-Q9J1dS6 zjhzkjVWt8ut3Vna-tyW8kI6Ps2+iS%%Y<7U_IPx{awq$dy7VOt0bQU>sl+)NCE0^L zcQyZlLvXdRuJ)!L9h50v=;TGDi(J0gpYrDn`=NT#sXE~_b$VPXPGh;`vEWr)*jzuX zqZ{V@rAUcD4}un*cAU*Lx7ram#_$fa4=WH8LdomEjXYBQ8mAHR2-HmogHHv*qA#sq zv&XpqE|RfT>!>X)44HXtqK~#tg4Ckk7Mh~u)jq#m2K+&upU#oVtvXCJ@H|~^ObajJ zB;sa1Ut>6ONaUd5kg?eDHeN$(3=f!C6q_g#sF?iJ#PH-HUXo)8#)GgBjwFBgKU2L5 zU$Z=zpJwSQ7QeKKPAK9rDY=6Rsqd@+E@H8sSNGh~woJtU3<}R5aQq2rq}3BQn@tR` zAxe3oj#f`6o)YdZ{QhVy=fF|jcUX&7*;CS&U9?R-$_rR98#c4zFQRMqz< zcvI>3_(}0$*`R7`C4;W8-ot?!FYpKU%W>V?CaXR#_T=d{a6kP!s=oSm_4lEmhLDdx z0}$N=CXAbNqY}!z@=?h6ebUF?LT| z{m`?2$yfWPdL|xOobJ>hHT^9NaV)U|d{hxlj&^NR;jd2#jb1sK!9(%SXZdI0Zut`( zZ8;76vh;{jpIP?=08(yBP#AoL71E#+!DUiDy{laJPRO%{RpDvO0B6gxJM%XJb#YoBjWB;YbfbGvnor8W$D5n=q{Z;FSWTXG1Q~sD z1`U@JI~6NWPfZE=D6e_k*^t-WHJ?Wdbi-;HFB0Ik;XZZE;>oO1Ri=r3fX3}4WBXEY zvN?|2se4Qy1hAM_jBqJe#PFF*NAvZ8}>j=$74(2Zdu<-F^hR5FoF` zscF4mL{qG>47BP4RiGBN4ES|iG99CalZG&tbdNo^&47b~OvHVD2^uQM+5PeM>H%Zt z9nF;isYSCiPC>~8l~2Wt1U)eUxEXQewySYTpzv)hy2~|vl(-t;=$Zu`Y{xWo`ty@q z<{(4yQzs*ByI`H)9t_cSJWHolCI`eIBOhpG9pxN9?||KE%iJI z^efrtek;xKr>ydAulK!ATR@2*f!ne{79a29Y@c^Ib3mA&uH%7XKP^Gyrj`3kuUV}X zlsl}hAk`2Ju8jH0;q&88)Q@LMZ;i&h#?q?F^l)^I{zTupGi?mIk@O6uEb>*QFApRpKYD!whV^7XSeq zw_L+Z{XrX&$&`4o+3EeIWKut1)9T27HBOeEzHtj`^|wfcE|E2mqZ`nUs$_o~n>L&h zl?c89?tgnumWmWSA2eXUY^5^v{ z+H=tIgR%dB)+LfRL?lh*5G+K|K2VNaav!NI=8$pwMe|WVV|;B#wGS=6Z_(veio0Rm zKi+6+(XA4dDX?84-0MX+KOf2B{EwFoURQ1iG^~q#e%TvbE`tu*| zBgKv!pjLOxFg=B?D$@RYjfAm6dFbD1dDh&%QlNFit~{p%AEz8Ge#o}6;0tOD&3;tW zW7X8W3&~F)B#u2S+T8MvDYBrU^jT!}sL!NNY>n_>bdn}<_Ahuz5SAA3h3&gV-ob5y z$}P4pM3W6?T>Xx5$1g}i6fs9#c&Oc9s|lc}Q0WLptle*yN_>+|dc^zky{Wb>n4S83 zb`7_Bq4esg3#VcrS|1IO!ry`ch?P@GGga}(GQ868s~0s zE_r}z5AL#s&u1wURmSAhiw%b}2>0@JZNaQq8;UBEt<`H4qeFQ{Wd-8(JXNi~Khu>? z*~03Bnn8#X)xjm{PPz|Z!ek0LQ4>z!5@El;H?dfO^BIW=sOV@&E{u^+6?{3Gv*kQn>KssP0|d67NAeUU*PjuY?9MGTU6n!T3-1)q#If)OK_GQ6*_njZM6*^)i6HOpCBY;@UU} z+2nHnt#?|}N#6k>j9SE(mM{~@rL3{kVt` zA*gYtFu`bYK9bGeRUIB*dXZw!bK-}g2l(AK)|9CicUtmKpJ)KndQ4QaEB`TZ`?UrI zt^ss2UPGARERSMNN3zJnJ2tCCf3%6mBFqy|L_W{2HRpa$2_Z-c3SgsiGcY|!6dOLY zw47_6Et(YJJGL*qXvCdrdXvTM3z+i^RO`5(N|zsisuUW0$U07I@g`qw%@Xy7RI~p< zZp<&Lxax0Z*ypx&dFfAiuB48`1$3Kt_KXsB<_gGfNzE8OXCpyplY6%U$eOxob9Uu@ zCwgzkPEkhK&CkVNfUdY7JQoZ0WhIg_hq*Y z7X1^%DZx>ANn)sjpa;R1?)I(=g3>o{zW-V{TD$c(;;~Bl2OH`SAY}s8+r&!{rmcaX z&3p#Kpf4I0@%_E^l}j&3F2(hD?;pO#uM2D){#gceKh%hPURRIc(!T|{1Q;w*R2dXP zjl8kpHmMPs?ED-5@L%b})}xqzj{b)q#G?Mq+{>=D85jSWn~i)^>f_dF;#K#~=-IiZ z3|Iqfh{uS+hLZoL`GP)wOeKX|kEuqmhi`+zblw?2mMgo>x$M0n8mtLWu%JhrR^~1g zy^VhRdUwPQ$*%ob!C<|#IK5FE&KpAc7^isYww}NSC4>z(Joy97NMeAJ=aGcohk_~h z!T0AV6_x^dv;Ohwix94a!(9!pN|c$7?Tpn#*@ z3+OPVnzzmkit-F^8ARS+{QaqrspZ$z;HS8z%B$uF_)Qe0wZ)ZkqLKCLE648o&Ar{* z1Kg^HAA2Dx9!~$KCk~@Ahkyd!10etB?lPBp@~Hy9Am35i$UFkv=wLLe5K_>*r1gce ztmg)AEe>s|74r&(rDY>;-Ovj#$mokJMC`Cw`aa9-0X5^0g6?u*Z`+(?n@mDG82hZlrM1ef^k zhjF23zx9aJ0K6pl{42yqx8Di3?mTV2X9;3w)Z$o3ngQkKjJ6lZUWfM!^c|L(uUTz%s+rEpe42rTNS)iJJg#5A zJGe)FMd~c|%TiX< zZ#+P@vT!tdWf}tXKD(v4`QIURiUqEynvuuAjo&ko3wV1<@s{Ynr5$6aIk@eZ1&Fd# z;PHiXgR0cR5x#~9b`_M`eF92Td>$b=b$8T3I!)UOe!r~}iz{Lkr^cz5VHc~$>FZr4 zH)tY2Ok8&hr1fM`ydc%De)BH+&H-t(t>mwwff?7+X=VU4O~?05cE$;iI`(a>*ZqP% zPno1hQEt$$!*mJF1D;68L6R-#b-cxpF9eNpaOO zr$QV9^4F~_53he|pbscCR8*T`l612}V$7z1j!cnTf53KZKczw=dx9tt>-dtWYtjlz zmtU1j0ug|lex<|)B=Bz8wa+siDU;8?kzP{2oNQ1-5Hy$;5}MQwa$tq()Eys3$MK6e$uiOR8lVa5AzAt z?4in3(;7@|c~#y$&QF(trt#*-!tld%HOmZSxwnhO>mmGOQSS-y60Xdeg~I zewM3lCX0Unh2%h${F~w>VjdKyo}cWR%4{<;{IB_spyKEF80?SJ4SCdNxvcZ-wz&B+ zArMB5Y;n$GCC@XATz9g93t7DanI2FI)#=cj8S5OMDzSBSrvGVl_ei(!^Y==O2?hrB z01Q)i?Z}5h^uPF6;B{_>rly|mPamj!nn$?*de17SkJ2-_-Vd1pxHItYo`(bHrXCSM zHU1N8eDkF1GTzOv8^0T^NxRuem;^7SO!cmkEnTDkx6>oSsR<7md%Hpm|GsY_#@#&ii%;C)c;^9wxAxYLQhp!=b z{Q{Lk>cx9k*^d!wAh~$6frSXwn8yJ9&LlW5#*}|3kTx`ETFs*z@-0X|eZXeZfJb`! zL>OE&WjYcr%C$ZP>a2v^P52%q=n7*6ORr(mTl*_;b1IlK&k+Ar|3__1xYg)-*^-68sV8?c9Au?T z;21!q>HlT`rLg`~K6BY)C;A9jA{z7chk6oj^BMzG zizFuwf;^(`s3>Rzc55{1$yhY#rLan2DFM>E!*IFM!;J^)z1ctH@$O&ElJM$k)cM$yzd<+Npd5pntBmP@#B08rN?&|Ez zrN=7p@!>ONbN2!uOo{4iBFHwPBZ4zvQ^P_P^D-CC~^7aQPJTZan zuV+0oj*vy!th{$UbPQQh_fKL1TBb_+-!iih3i$kXIJG-KHut8d`=x47l>*!tXc1Qi z9BZ5j;nr_J-@wu4-J!UoGt-!O=BYV($Q1v*368Yoy^EKJIjQT-;>Pt>@zx#f{|*vB zx0e^k$_ShpNx2rG;yv9vI5)F94xD~^^if?ls?AH((kSi%Ruh`-0o?gR|H!JG@>c|t z)$M}bAZ6ff97KNOw=SSf;^*Cfr#Ew+acdjs0`Wv8Fz|r+>CbRH-1}lPvKr*H zhSu}6P)qWNE?|>PKUm6;5^O}};LRy?6Ypk&45*EDo!x<*^(bkEHU9}yrbr`Q31Sr5 zwp3&59aaLAxKT?$g9*`?LTQ==(F=4b|D0=g|H9BYB9H(chESmp4T8NO*NTG?^pp{X z>S?bb(n~{ESlG49&es=NT^DI~d;6@iL&Q^8bPeFg9on{JmcnbqLJTx)$%k-J$-A3IH(~$Z$bqVE8Gy}DzOF+a7|mhujnS|wgR=+S z1g|-5n$P-^m9?C*>G+yR3rnE1@ZFT2>2yDvN14bH$>AeJ_LV1^`q zf(6dy5#KvUlNt}0V!^jp6>p8QFE*K0u7|X@7oBkz{_2pLCX)K@=Mwy2iP;!sT8ohB(VATYi?e3y=>2V?l3*$!C=Q>Gu z8@Y=!xC>3M_x>$t1hk;S!TX|Qw_W*XI*)+fe}5eU&ImsG!Gr^_=SLBGVCBD6M#BiC zKMyQk1Qeq^?sY&EGNRf4H-kV8YD+zn*8Q68+WiZUD#-*YJ_naq2GGotMK>2&&`c8O z&XRLEA!i$3CR3xof!f-iSjC+w2ImVR9b!Mzc}mN zGvF^sDzL49*h;=SYU`}%(B*{Tv>T^O3%Ca=D<{Tp8!pWc7F**jkyr(y7rU|EG#T6R zPZf6DT&1Ej++UgqRv{A<9OgI8XlsKt$AB0eUdy^d|>+JxD@|l z?4T5XeFz8{@LNEXHpsT}8;5Nv;Ktby$ff*$0|o?$mKlvKfd~ca)3soIBMTYKIc@`! zBttom7(*(wMPWn0XJS$3%dOAO>BTLo@+l!TearL6%GnGA`>0)4Ah86jF#BM{=ET8e z%>%ghVs&0ywCgtS&;W}Jkcr3(1CyDC2E4EcoSnf;3`w6&dS!c-w%a}!T_oi1gpdw# zBwAMr2?o5KC?leg|G(QIz;(E_?O@M0Gt5i??HF)+cLLY`2%b?A5dx-G5al*krdT0X zHDsMKvAjk!-SS!7bIr@Cns}+8Xz0Jz0L}h!(YKhhojE|`zS=?fg@Jx%_NKXc(A+XS z`;|f{Xpa4V%@q}$j*_~$O&s!WoGG8A{V*(5ru^Uj*&=M&-g*%s|C6NI)wANUxsCT^ zfy~WD#|2B&|FZa05dd@Z@7^><4gtXgpR)2*@=V%H`{}Wr)n6-xjIm8E7LorpWGPW> z3uE};%^k1MK>sJGDgZ0ekD9%A9%-Kv!0gQeK_oDH4)ipMgGviZzOGxDKhphTx6>mX z%KZ7(1pq{pzP~yF$v>-H5IDX>Bxp&N+1LwjVwK;( zhg(jsQauL8HQ{{k+|6j=P`CFyoIdqFKu(}L{=Wry1_9CuXV-3<@6u;CcbblkN&2Q0 zA8=-^%^jCdQjR+Cn(WF&0gp)C>_KOCTLrwkAdo}<^FJxrJxSXap&(z7&W5zuWi00h zZ$j6Ryb)>zZDU?3f&(hw;eXvQ8qrXiL!hnR{Hw5dlwI|krth{p0FBneegQ?r(wp7k z3D&IjB%tX?*3C|_jGpS+ux3*OK*nfZLp;l7V;)tCit<+A9W*^#q$s68#TiKP8WSp7 zbC6=7egLzpMFiZV>;KC=wlw0SrMBt|U_59)60v1va^Cdxoeg?@z34gk|GUnC+a`x!??gV{tU%+6&qFL&o~)5f0yLa$R-O`5lv7tdqYKcnpP7{I`S3 ziM}`go01le`MV*{FY0&LH7%%$V3ixYxnoj-30lu-@3aPs{*o8vxm(;#AisY7()d-- z*lVuRm-!C4&W^8oZP9@~SpSd9eW~Nv(mpLr`NjkN0S%EYz9H5|ZN`^34aq>bZ0ngz z)=5>w6+P2yMMQ3V={{}E+R`7O7uwb904O>7K8BhM7oSa#T+bvCEjU=^B%@94f;Pgg zz2j6XmOTsk81}+d(P;iehuv|F1SvGmA^mG81K2JA3?kaT;n- zh)`#=UU0My6=>?^O;ZwBasq}dA*FXdErHXNtW1jk@{=BQ>ZjhVIhr+k;_Gb#^yvO` zwBRhcn&5D?dWO6iO64Gxx5vY;gw!0Z50fY=YR~c6mLqwa40dKxJ)w=oe{N(mp zTv8~;JdJ}CBdRMdj5Lybsr9`jgEuF$;gC{^@Qvw#D4hMRPDUOcSWaeCWb&<2l2Fgk zkegRo#~vp}Ev<4nBaN6}ktJ7|JfpB7zv#2^S@~r<>(^WyRk7>6S0e=}JRa?e=+RF% zY69_Y)%@y+L-9T+V6}V=O#@ol*BV#?~GJmd( zLCj3;375o-N^sKI9{ z|MjY7{r&z8s0SDkgoOlT(oas_Hn*lCL`<)OhOuDfXF2GRBt-xYA0 z_gwt%j`q~s=GBdL!pyu;hbOn`Ix!(~wkdu4S5n%Q9#r1A{naR+>6nBW6e4u4c{rit z6OEU|n(A0)M&_g)lu07$ifgSu`a|}mP#r47Cb)+-cu|PK#gw}vT>}{2HYzKH(fQ>a zBeDr}m6`8ej}c}D1D`_wq9pWKs<~;#HJDupX$h}yK>-^iNHE+TO*J3ud~SXh z|BXL#LCyQaOTx+G*y|ZkQ|+ioS8UcBxEDAV@`tn;+~yAVp3XOqwq6gC#s;)4&%Yax z2ofN7#_fZGCW<<@R1IPb2zoowB1_=Ivk&?+vN}1wTMh6^Wp`Ro;500S!Y7*l7w$kw$2h-dL z!UAAXg@)P*LXR7LedWC$`;|$nu}7d{hg*wG}3_C z2RNRsVa8AHR0{a=A3U~D*1(d2b!5`ISmCLdJ~`5Q8NCpJCR4%M_h!6^uz^(?HGVbu z4s%$l#kybBA9}UI3Vp^x36eqk( zaIMW}x;Y7nOKD<>(TJ0ed>J$wS@}ghQV@MVKPL#YAzgm*P5`}WJzO+bO+$nEv<|GJ z_ZdEfY(@V_Zq5jrk!;X8{}8WLFaxr}nu=Js3ONh0%Chlne~~%E^xW5O{C)^5s!m7z zBXPM~3MS3H>%Wr&32j42lz==b$V`|g{fMDzvHO5kFp|WwMWzUv7#u205;_^(r1^q0 zPtQcv^yCBxO%q?H`ZjVBx>rD(on|r48-dn$;Y7!t|A3LxB zqc4z4778qLPaAZ<4_NnwC14Q#fFAK1&V2~MB4QB&ENHveRqw< zv`Q#Z(-e;NvaT{h{Y89@|H2}NrmxwXvNpyt(wOVKG01zPg5M#J@H#CpQR&iY&k}V> zlHXF5j$h4LDF|WFOXMu9HTmvpw+1RgZY84ZhLZ^`^Q<{Pr|{d=FJs$T(^{#l`pZ{0 z`8GCiVVzq}vu}scAqKx?F-g*pLU_^ke_M>(RKr5?v;W3D6s&c%X4NjHM$PUzQ;zZ7 zbenPyfq@KVLz+TMzybXUn+4Fl0`q4BS+BXeS-YvRM~K0Q>`+M>cLu|4nuwhaW9cgLT7>Z!Iap?wBdke#LZ_w{&#H`(708f3wd50#U_UZP_y7 zJi~i621r}onGYXqY|1U+iFAoiT3zv>8njE_xJC7uO6@l?0iyv(z!L-Q%H@UEnx&7A zu7^&6)|%{2h;OvId35Cd30CNLE1^i?U3w*#2&g|n{R;wdu%rLZF{cqdLR3zXjLrW3 zE9114tg#q`v16+rPY$smEIEASb}-0vUG(QMD$V4!o^bQH;!RNF9%gBl#S^Tjx^tp2 z)8NURIfRk&w3L|yz6w? z@B8?E|G__A@7Fl{JkL4DnIF}{@fm7BD@BA4>6bg(V9Yr+uDw-0IkgdIwQ6ZYf9FHN z$G=j(lsL10P+ZUYJa^b&RzLXG7y9Dwte8q$rwjTK`^{@XuoiJuN%;N^z`47G4D$#u zmW)K7t1cy2mVh>4V!j_7;58VXbv0XQ@SubkRlC?Lo@U7zcyU1j^AbDn!29;kDaqJ% z{KpEnPTetx7dcA}7o2__J>&}LbHq^!wiG&CKjDcco?ESoXJ^6>e)znSUo2Z#s}@qb zCJo`&93#GQ0o+qa$ZmK4sF_#Klc(h!=;+6J)mbD4Z%*Q)oXpH(4bNMbi-$E`*`cB| zyZsZUyw8UsfnY2fD67;x96*(B-W$W4K&K!wK5r#|jp5T*ADDQ5KXdon5V$Rp1Zl*N zX>WkmOW+FK&i5UeX8sO0{&}eTfUycWa;V_S66jetl4lW+;jNHUWS*c~&nbu;d-uoU zh)8oAZ+OrJ+H?cDgqfk9|e7og`FuH3%s1(QsbFMhsCP3{T?G)X(Ww`clmNxFa=eTTdy zJmhhetl)5k41J?s3&|C)-%)N*i+fxC`~A%+onR1Cfj24^ysgX(PmslxTsBKVU}eBf z#*{r`6gwjFa#SL*_DC77^3QyPZ;@g(6~XuE6xpq4RYO%$8$$LdHRf8-W~GAmRVIGU z1DVkKbWE7)#qH-NRZi9C5gy~2%4?#ZtIrgbV)eLYGg z?wUob5qgrN1ocPcb)NFCYiz?7suUwN(BkOEtVCsWa(&S{eGJgWs^A@Te?F$O@Kx9w z0-cF?ZJ~R~nb%0}m08yUBwVwwc5Kg^T=$suE#{j)!048Ni+fQ=)Eq3NM4qEbVMI~^S1N{m5-cN`s$ErM@(=6}vU zdOBxTeALuIzMuv`HwqzPQH-{*0TE+_WqiYrnJ-xn7Gsa{@{3~TISw^k7HUL=a)b1K zv18P>1HiP6Krnn;{d>StZnjY&^&$(X!lFB!mK{J!X25{`m~fjJ-#i6xXEfX8r?a7-A;R>UjOG z2wcPd23vns=9#t8%C`Q7NTClVVR6$TBGm@cR;t_GM>Q%;+sg$n3aK*qbQgHAgbuwVo#mi1N+h`Ad;zT&N0 zbMA4c-0|Z^$s!8k%Qt*=EceUq$BuE{a`rH-C^Rbv;x%bzaV%f!ecr6z#1_&}gykk- zGbeK*+$;lI^p^I+n%jI|$7Rf};CQp(#ofP~U@oB~D2!b#gk$2pJ84T7ZE5|AhGWKQ zbywn(IXfGlA)X=JerkeF9oHeC9H!i|MP8E+8aze|3sZoV#}c%#QSqq|N)BIdQn= zL&sMcPkq2=xf|gLrW^K7CRmpxx>#yr=I32O>!vUHypC_5!@J&}K8G{BYFDT9b_@?R z#ov1fF@H}5v}thTbYInojBq+*I(8-HB}CrJ3j*@@Aanmm%iybjOyV;%v51;ES|+xE zPalFL1BTp~ZE(kKx9bx$9i+xdL z31zff0DX-T@Oi(%IOZy zq($wc&T`)uI} z=wWj~bBbkM2?9);?jL#ptZb7l{UDDm=gyVTn*l#t+>kF!=K0aPOUTYQ>YlM%U^HYH zokeQ7ywwc|XH>kpo%h0L3Ap}K(KfLx2?;nRvv?Qn6z)=Q-*m$w|CPvZGe|x)BIIZD zK`N;RiIwAkTaWQ-d#;MsH->0n%QL~q1jVlex&y=T345w5sX_>m1&iFQlRL7gf(h*< zG8Vgq(kZ;{qVz&}gO{8eba0ll^Y~~dx36JAH{0JYVZUv638_D8%jBG<|C^pp5yr4j zGJaSbxct7%rl`zi2Nia!4mszLUe!Uq}ZxxiCT7G)?1^TaIQOS@BP#o;D5NfB!_ulQCLA3b48e z1#`oviy!%nLJZi$)bGc=xorhTDtj*%qL&DZZcKFa`}nQskqq+D{X8YH0=T`?JYr%2`A+3OOJzLmG7S%9x3g&RAFjw7R`!1vk|K^PwfQof5_izYYz6Gm zOx?rF{Ab#S3v<5Yf@a%K+4_i zY>6%2|A;Cji%xAcQV91Hl+E3rn_kii{T)g9qZ0DKH+v+2S$U2)^NN+i8AQxeY7qtL z9%g^4B+yB0*MGp!SgpI=>Wxm59R&4?#%E}Yal#4d;2Me)pF>zAKx4|=+9!sKoK&?* z|7x}egq{e4Y_)^ew>RT$!?=)QbqQBZ`ikY@3z^RlN>m(j!0s`F1pIshYD)V!UGUcX zT5X1a^Zvt|+x_~|+IygX(wsn%8}a3v{#)}%mjsmG!OoALtBS2##IH$^MS9T!X8n8h zLra6AVuhZ8)U=cBnlq+^*+Xi7v$yPO4daVHi!5KdVZ68R6mT7;#-H1N(DzFlK;e=$ zl>q|H2!h7Zo-vVhwHkzM`&TQ*sk_OzPBuuoQ`NlXOqDFT?l+U;P<(`0M^+km^-xBT zAtJLT^FUEdxh>3hfJgQZ(=$6k%G_eJkaf$@Kv;KY5`0H$8(L|SJ}~aS4>DZXs#tqk zCSHg4{ejr|+tT2(f_Q=dmE&$mSPg04c8#>2Kd1r>UebRT!$dne3@Wk^?)?=`PoYz? zg#;Cy31fD>FdYt9=Tf3sq7&m-g}A_#JGb?x`Lnu7asX5pxL>o-2BOQq2GA<6qmv@f zWq%OpbabgXya0SoEJa-faHkbOYmeD14KB?t$(jD(NYauL01e5NyC`?CE^1As?M5i+ zh>81gQ&lP}*|dUC#y+np|Cl;Rfy0B-)YRU)-r-} zQXDRwX4xD#@~RhK>wEvM2gPKL!&g5D8nY=yY~;6Y{O;lO1SwMMETq3rW7j`SOU zRhgzr18C46Do9%+a2mzi(%SVyMZ%|iV{8@N zG%?0V8J3s4p-7ht0KB#h(@a#f=M9+$y8Gz{4M`{%U~P)Qf;Jh}OPq08G6eb^{Ia=0 zFZ&X#Ej~y{U@!e#9cn))3?MlP{+$Y~CfP}ck*CT#g*0p{8yLDJAeyY(ZeMLn`@sOB zF=R0PGP-Zlr5c7cXCbB(FI$21b30@5avD`aB0WGKKCXQ2dB~mjfncaRPVhM7jvBcz zQ^#&3_Z8}Gr8vh924&95`Z8x|x{waZAJ&y8A)vy&VVJz3(RfwkXZ6o>D%)gNeN77>$}+z->s z&oK=+f6+xn9s)wr^PZvtxzG@@7m=f^SX(#+<(+mySSMvx1&u%D-#j?23bW4X1j^u4 z6K4UtbrBicArL0kz|sz)&a;uAvs9&t`Qt*YdAQRbk~!yHrFKaR3?cgJeJlEc;Wls* zraoUiTAzuQyOK7p{OWS3_Je6ESe5goyq>T2*CF1_{TF#1ivwh?Sj%YydPpaSaeHAu zd9x0Db?vpVku|=4$?(b_z!s>`34u2yF);Ty@&skI3%a;9X%%eZV@f)k&vP_1T(w?Q z{N74($homjneU(`a1))7O#V@r7f(xctJ=}rz0u)D|Yx^QNxQ&{9s=I*xYRI>qWl#Aa=$?I2Y0N_HDeZ?|LdV8qZrl zmZ5Ro#4U?gFt9F!+~Fz+dGCu}W9r~>E3*_i%e@zsB6q%hq$K#=hXLQectg;RZATUv z<89rg=n1P)c+`ODjBRVZ;{RwdRYK7??V=hbSAxP?t5LRw(r@btt~$i4V@pxIHkbY?lzEYL64=+r-x63R2*!=&6rUM}JME zmZ*@VW~5P8e8@=T;#vD=RB%tC;Gu3)%wl5E>?^(}8s8nBAwE~6UVWA*D05EVJroRY z1&;TaM;j>l`4WvUWR&q)Q~qEk4W!Elzks$D#{4bv-V0ijQD|+u z#j^sHw-(?Ci`cWltd~w?HQ>=Ix$H27Tpu26Y#+^(uKuP${kp?h1k<(HD6vHbt+bIgJH(zTaRBw zKez{4T@*6Ddn`gee6+%d&yfOjou`7v;apjv@}m+Gk+_&!C;I@!s^!7OQiFCccn*9Q z$`gKVeP$exhpj3*q3B4OWt)IurBNKUU9Iis6uZq=l9L4UT zEb~syGmXdvr$ssa?B#S~IFTyPUWVMzq86C&$`qA!bgcE!O$pE^iB#czB3PLUfSuYI zx1S*#D%dK4lWxb6dW!6L|JWiMH2p9NR3?%-jv*^)+~Ul$A*2rb2_g@y*ZT{UwzfWl zbm76uSxYx}{NQ`9PyL4@olho5*khX0>Hm7X^u(|0OePVE`C(Qct-hv%7QJ5bi%tsW z{Fjx_<;3!z21bhAzz^qbm51yVb1Krr_f#euLaAZ~mZEUthyq3T^+|;eVd;ox>Y)Bm z?s!wq_`&mnX6486<^gL_pgtgF3|}iSaWGq&;S$CnmM!ppjm=ph;;$rq9Tp-L1gFMn zPDMD9+@&x+%~Vn$_zW@QB>>`P&Ttw8<78RyY>67o6@;8N2wz+Yyd~Vnun3125-Uxq zXH^G+UUO=OF6kDkllt%W`fvUki#@mxisL|s`Z~8?PJhs%2KD>`g@dhGQ+3k?41cg4 z!0iUDT2+eeRW#7VftZnx!wuO02h`_cutOp|ze@~M*{Hd6>3Q}@+JblCKT098F^V8i zr8jn9Lb~0I0I?;-#R)%(8!S|YFH%X%HBVi?S9^D&N923(2oK_$+`$q6-AQTO1x=Fv z2Cd0BQg6Cb5scC7WC%M|OJ*d}YOKLllf*8!Hv8VB>VexdikBZ^>VV3;~6_dhPRe7TF^H|!Om)*^R7%D+nD)M z^Gy(g)PVdN$F6(&g>QCQ zcC>ehR%;0A{&b(K0)weROU4@>6uh68X2uHLe7Du`H7qW_ad4|K=C>|f=6S5KuzBtz zWbylJ@_)>^IuS$ga6j}+3trcPuz{c^Fmxh0Q$0|mF{#G@iar}`e8){MrZ2e6iSOnE z|L=7XUp7EfmZ|ea2gH}9+-LDN0T2#!xVahr1Gx6pKSd0+HURxH!_WJVT!1Uo5(-@P zL?iEX-S?JSps?ui9Pc*o)MxJ^rAglSI#I3~UjS(OR zh4jm5gHhJeOD`AKwOK(q|KIo?$K;2@j#1Q-URe(DBDqCiD9$p=McHs8j`R@-vO4k7 zhHE{Rnt;=yNl4SWrIZl=1<$hxw^oI0BpgiE%BWnLCX|V~l_k_@gQPmv3wMw?>TmV#g6MJ; z%3}m&kuS@;E%3>=0nVp{m+hPoN>ldA+pY?}4;zf@_Xd`W>w{2lt9QPP|Es0h+60gr z%Lj!y_>{+Q3e=_K_V*g{Yi}q5%a7z+r^6;a$H71m=cb8v3vfVy?5q-7y^*`+yzAx^ za1kHLCw?CrqD-qMumB|&hFslkx#bOJa&Vi5hd7UP{>I|~xc*N>ng5@}%I~kRf%GpU ziSvaKkT8MUR#bs3A_y=Tko$saY}vh@=yVB%1`6i%PwM4O{}YiFf1Typ$yUit;z3p{ zukrSG;9Pqxo|87o^XR#Lbs)l_>Wgko%%qj zrmSE<@a_}^jaerlK=b}V?2nIPSQDz=C;o-Cfo-N<1epift?Tt*Vp8P==0NC2s)$kz z&mB(?;?JK`0g-NIE{G54l+ozF#Ys#^_$;Se^1O5K&nN)++h4=3NxHuOA$U@E1h_g4 z@7c^<-cg4|XiFrK6WJ-nNP3=cig*A4?9S&&a-KI9yA|AID6Ao2F8DS#s7BG79XMrW zEb<406;%unWrLh#lAne3UOk;`Kq>=m82H1hGuBSTOHcQ&V{w@%WoWHp!J+QL(DndB``LORoer^qbjeILrx5Uh^e0P%p4bI;}@)c-5k z!iQdyzq1qlyKH*UBG73oNlsZScAh0rr?=7F@RQnI=!P)RGOxEg?qpS)(w6ncfx6}i zI8p}CMW`o<)%=seLC_3SA{g?&Alcb6N;-ei^FSGcJh6YKX!FAl<(k*wv96(^up0sZ z_FN^9iE`*4$WEZuI!2Jid4jEj?w?UHR3yq^Q7DN_@cKN!q%8eG);`V{M%#+O{$0im z!1B`$kt&IVz)|0%DIC7%#2epHKcPG~nFzls4_Jg*1!6b<6AU=`&`A_(21#P9W%^sE zvxeQ$KD^#!8Y=zQYho@r1zw5lekKPs1z3)cMg`rwz)r@L1m^*XByy8iA?;(b$Gcr@ z5(=s3LvKXk?zM1wh+nFdYJxT+uKU5cASsww@&vxCq+ssrhR@j*l%DuW<%a?@rCvG?)=#4*$vH zxPf$TWVt!5F+f~bL96b5J`;rjSpy#>FrDwA06BN2fPSw6NEriS{r3HE{5uP;LMjIV zlhWYbdk&Sk(a&SI^||$k*a2!163=@l_hG`kj?WVDUyTH)58R_mhDsbcIJgKLhcSGZ ze8$3c_ZQzVq(=h_;b0=v<8nRNaUiH552jC-Mm39%L#`0;MsEc9~FrNEXh* z4C!^u8b)2epfzOkx3UIA;>M}vSn3@0*iOWIFM!l0sLFI&kSU`_kRcEt^+_mwL8^&5 zoRWkD!bE&KKi(SIn**vqR-6w&#>1PO!SKn%Y z=58eI|%bsY5odh^4s9^T&-dKl*`p1 zImtmQGjN>^NK8{Ay%I^1?Zo%*cPX^6zr6`&0SIWL&ci}Y-Xl$=(+yj!(zr^6FUUHc z7_Vy@Hy_;p@U1s8@NSu4!q?HSKdqDC;4ixUPwlVkkSmStjdr~3PE}u@oJljaPW%+C zUKnCn5@D25C0WRtq7_NS_cU(@ZI!l>t**dr)cR3RqerjlXh1LYhzG8_aMUogyS4aT zH0axpgP^W}OcvWMAK$k_--Ux_MBaXetx3;Miyt1&+go1p&*GMY5Hp9If)Fcnry9BJ zp^7!FOuUTuP%-((9rAsj?>c;oPv|aOaWfc1jcByJZ;5Y9F1rk2qZzJr8oDL7*E1SQ z#>Wc6tTn5y#TP4WVV=htf(U&LiAo>+d0TV?tXQN}$=htrQSrL-UpCTY6m(-AVi&xBNu`_X;M>Qjg zW+TMJorm$3-vw7W2v|Brz;iRvs2bJX5k1`dJq{<`#uCzCLa3D@UFrK{8a!IA+T}jwO8-)cUqlh{3XE3XQJVSi< z#@LE5FA8CTEOe{u>H4?*UIt9J505fMwBP7(^)*C7fBd-=`BR|`kfanW|L3xK8?ma9 zF5aMp`JeauRPtuSEdmdzd1C6wG4VIM!S!UBTnK$eRN#_}66O?FOs#1E)9IDg?&gJ4 z6!~ssa;mw8BRRFZsYxj&PUT4dy@=;`n3*uSb;t>Ok>R~;B?;TGoAv^iTWt4>6e(P`AtU@E?y!WS! zReconS^hq%{3JgC9VY9Wq0SbHp3g*x4#P2TSYirIGES>KeQUvJ(8!*J%i5GbL5bOj zpo7q}O#n?!&(fU`@^<{fWl8e>?XAgo$9tXo7Vd6HGmLrN_s3>+KNL^yTvbR|M#c$u zd)rciNdaJWWmwe*DLIBbQ0bq0u9oE*zw9ntAYa%ox6qfnO%49(32VuN-3_jH56TJ~ z!d98r!3YF=Py5g}$D3T1wX>yEN9%A6pZWrc(>zz2eiJ4Bhcu1S~zDvuWt5#5C?a^)I}o)_r@Zk-CXA`*>5p7CVkQcP7LxJg-P zQRlz(?L9+T;972Ma%?{b;`?xEDyNIS5IxbqulSR@Lb22o+<}bhS0$IvEt}1rXXRL# zy8rV%nWBUu`mMH<_tS>^MBZy-ejvqBNnc&U16fM!|caCv{cia2ULq ze?7|OflVI@dehQeeefU2^-9>f-lThkW5LU+-^|A>e4haSeT8=o)K@}v2b_L6di1d96FB;ESQd*kE6BX(TDv&lL@ZS;yr1v#Nks4`}G*+dCnNG!Z zRn@b}<}B?o(WwUb{jo_#aK zM1vpN=}v~7Y)n}&wYwFnE}Ys8o$0Q*WK0$TT^PhILKjrQuaTw%if6Y&2yoV&O_-v9 zi=Qza?;gMx*Afq>u!0X}ZR;-eh-n&9{C&>Q%LEfK4JNPuN)U70z7BU> zL@la|IXHYBFg^EIFp@u0mQNdySCSwKdyLSR(;xv8cS0ZDtwRO9tJ19|9nyVO@o17(r7M^3{vuYXu=!6>Bn*puoH5=2a|3n4dMfFr4#80sbs&_M+-rSo+j(k({r(M+~NM74VQ@K&E>g+sWOOlH8YlAv@7ym%BkOBXFodS{p)LTU2e*X`rewij%{Zc=9Bsm^Aq zDcU&ei19(Wz!)cnlbeyZN^e+MDM)_Kb6!VVa$8)$7dmFpMON)+Omm-_I>5EO>}UJ% zJs%+4x1IBF*M*vS_?=qaiJzZ!OqFdSx z+g#gRN+y{7xkhUs-S8SWC|FM{vJYufbCh%Tgc-YQLYi;s=a){)%aeIpyjYUywwZ0b zZ1c>c+$iyNCjLh(% zVdW-sB?~xol_QUI=~Ho>Mw=tvkfX$#Bx@I`VpG9Hu{u&5HQICwz<+**=Np(eh!;I@ ze3k}to1!tzv$)RRmtK+wBfhh(D52u8*eLMhg{p^)@4*0txvK%u2`LimHk=70E4>%n zYJdvu$%LAUvVFySp433DjqAItJRM#YiWN zS_-~j|729g63oVS0cVCzuKpO#Gu$X(U}iPFwpM?9WSDQXYya+v-R4;*4U|i{&=ER- zPSl1ck^h7aL*y@l@7-j+=tc)V8=ZUxYLIFqe0>@)^OlPAa2i$HVC)>Zd}_LUQa3b( zwJ-_UE3wQoqH7QzT3P|XK{j}WK0>2!L7*M%9cC5cIsX>>$z^}o9+7UUIv$1 zHMb{)T(EEGF%JHBpfSru(Ooya2A^m7rD(!ciT)Yopb;b)ImS!iM)xWe#!$x9vBhp8 zVPL7lUv^o@e?*3%uW)qU1jv{tLc-TPJpwfZUbr1QUAi;hHZ8&-xfl%17BOpw_PpGQ zoOs)5`J;B?un3vlVAK;sz?l$KkxS5nPpoTLnSJjOkn>6WW? zzS6FXpxS>rAqZ%&X0bKrv|#IueKoW&{|T`LKKxO>g&`aXzVWVk&yN4l*9hoKC^gHG zMyScTR=E8-=#cJGzQJ{tu6aZp_c}01;F6)KT-nwSCU?7DUK2S_{raBpO|EL9@dw`` z(N}|PsS_FE|49rKTWYh!;5=&5_Q#-SYht;vEp@E=A^M5(V+4*#QW3pZ#V`j?)rSlf zi#V}{$g5ic_uNs_f*fP|U@qBy zSg?EP-9s%o;SOv{1p0mtYf2!n4h?19JT&rTc!vc4;|U*#r_gGrcQ=gFlW}V*W1W~; zI52d&8~RG!?!MuhYhDZ(hnYpK9Z<>Ut&9*Ma* z5)CbtI4&3ovpkVm2+CQC85Bje9g$v_CBt2~QrulC`l>?!ceoL5oE==J1Nmpz!~w?7 zxKYr-r?Ox)qH}(%|FeN{oLGPV3Mr$wbE=Dj?XBMguvGnPqW*a6*sEo* zl}l@$!(Go%8qyXQBJ%LFv=hToY#|9Ss(wkg#ww9~_ZLw?=a0V!+D8q|e{pod1!>~6 zR=dKY-xu&uuXLf5vPBD!he>j~quhcry#G`fA(#9D?HCJ5hWum1z>7!Ch;j$2UZFrH zy(`9W5B{iAkViB+32CoCXI;TwtbddAJ##-{)cR=l^&*YTdE9lIl=dT};I($A>j{GP zKOUbV+GOcpu#k4U|2{k%N!!Aw=cY0?rEii@L+5n%oBcB)ff-J_2UU^3EOz9Cj&~`% zguGai?F{Hwh?GD6vp{u8$T3k%u2sgD6w#y!jzcIRU2*tBGqi)eL|y+9urJ35QKEkN zr&`mA&*{iBZN>TTxFOxq$3bmEmMyJg5wM84?S&Og7Hqe> z(PbN3ySvh?>Xen%7}{__GzVYI*Xic_n@Z?u1Gnjwth^UNqf-7`3#Wt_BL1m0WftLX zQTeE+_vQL=BHjKLRo2uhG4afRAAA*@k`bKL)^UDeMjNl*NVph00=wwx zPs$@J@O9W0ANXZ2=Eqm7i?=09h(y;9+Nr))L(ApY{HC_6J1qW+zh2!)#(B$*l(?RI zA0ob;>$sd*&phBrxqJ_GJE@$H`eNK5c%B=V!Ys9nUwLMH@=t@!A7nONKmWzEuf#u+ zPUynEdz$CJ=#C`O#u;zzgMy-_hk5mo2+wIdTdnunz}pFB^W<{^vY@Z3;gJdPWL zTI6#eXQS)$s#l?~E=L?njb%G1y(Qr1N(~r=-508n)ESLX)rbA}8k{nTCuMZqT_>co7RAQT4k=5GvHsaBH&vt{_EMO#wM1FfI za_gZ!<+o4O52I>B$2XoNwM7n$iTCl%cT8E;^Pwb69+<$L9wQXS1-PmIl9DoSs>`8& zk^Z!J^&S;w`#}qE3m)dzWx1o@n^HUTc~7klmu9S}nqD9vRHW3&*7aiAo)M3l@otLc z8u(g~`g(J7QzL<2%I#-cm@=53AwhKtFoalaBO)PGX?-#M{*92#HsF2L-~|2zGnO`LVMZM zpS~3?BuD4c7y0f*!lB2NWh9N~-+fchZ@M#$3O4lGxDW+5eQE^)AV*78P^MRnx`QnG zq1zvrWPZ8V>X)u|Tz@){Fb3jDAke#Cbd6V>EAW`km1|{ zEq^&2SH^;k6L1hhYu0r`^J}fz#Perc;=hbLaCq_wK2R|GcGf=Vqk*^_o5$NC(lc|P zK6oz7doSIfBFQMLBCMXOmY_;QE-lby%--ejMEagDJF%jfyUT&!&^7rP$CL&Ov$2nj z%@aeR)O8x|M3V9}a+9kT-#I(0*y-lrB_O~H&9qq3;*MjkqU+|0Y?j~2`msuR!Vsp> zAjFbT611KTm zSR_S#uMpcGQr5c1IK&$+`PEPucTo7%VuRG>{Fki_>}gCy+lXb4Fcnc>#D{FeP~Iy& zsc-L0-Bi+#Sh|l zzo(HFzD=uRkoj7*xV?nO1zDwT7hzCLFL<^>z*s;#D`imdJs<4j+8cY0H`fil1BA+L z1@!HZK`KEzpRWQ;p!X=<`TbibBthFZ(x-X;RuT#^irp7eT)$cTojEp?t;?4i(;Dd2`>$TN29}tW6_e&WV zzawb2g9Nw>kF`lBF?_1CKn6x05T@=CE3>3t$zVW1A64$UA)mNAT|r-(08QdP?Bl*0 zwd$DAgZ^9qf%Fw5?=!0J_U#)ipROXi>gPA{DW8evxI0aW?vAU%?zu1y z3eYH@;Xy9_Qsp1n{haghW5nuZ zVXr0c*pP~Hm8yrQAOl1ft^{w#eCdq9QrGby`t}DTjNnngF*l6R1&^=+kvo{W2)u3B z>hpUJ|DEmyAu&$+A=8W<2`>4HVF#(R8}cZBp>T2DcEd5$PlV&P zkyAjtv00V#h`#nsLs`|kY9O|MzfnGl(PTIC9?^e`3W7y3I!ue=B)Fxk!y_Z6j0;dV zJ)Zfj45ulKIa`F`i>9cMgCnHNAPOr&5Oq5F8Ft)#=voszSut(o z$#Ov*C~{+TdH=)Kg4mP!&%!C2FpP3hS0n%5BJtsPxm zLZ)TxKOa2X^I=}^R=U{H-d^EzzLev?%e4beLB~P584@V_sj8z)@dwzoPsV?Ai~)sC z+0UOf9d*e)Qj!ZU6$1lu!rGczjmxovbAbv-!%B5*_ahe2`=p5`h)fM4oZloDn}i z2l)Eay}pB(WZSYw{bA5%KG)e6it`J!^Ca52Ckuw&2Evo|=DJrNbiwFW6nMMTybw+n z-Jz8jCx<;4Fx&>&fDJ1yq;Oo##mBhquIyko*_AT8JgEP_L!)pbw zvo-qt$b0f=g*!Xclz-oNniA;zWnYOrfixJKtdZ)ePzXU29C3zn4&k_BR8lfsmBgj> z-eK9)4GVmw2kSferxoo?&^c6P7kIlu5T`K*JiLE}Vk0Z?mD*k*(%u4*LNOrHnY^U= z0P5VP@0|z&doPJVZ2lE_8RyDcgT~sF_=SLA*I*R5t}k*iWM?S>cTWn@n~>0zf?4P`iGs2YMe;vxq{HI_7F+ zL|_lzW=3H9$DxJeXB<72`gzVT{{(ZO8|f)@zf}>5hIWlsI-T_w06k6rK9W@h-dVj_ zv1?9I=fNuzo3 zG`1~Zi2b^=#{JJBAt#1~bPKG^P#G-ZmC%LX2~WD%kVq_bQPvlPK31Zx*y&c`_*U_t z3=F3Qy&ZV_xGUgAVesB;I7>&I@a}@y#Xc|!>qt_Fkb$@x?YYs^O!?2FFaRup`Xt+) z0ycaTBoIJWQt$!+9eS}>Cl2K*;6X|uk@Bz!-bD5Kg{sz!E6+8Dm*^5+$QQiW{ytJ} zFG@#5^Uuy~W&>C7)@H;H3U*2f(vvFZS}8zCw1BxSO0hvtB;{c6aR=tbQvIIg(BqEc z95L^{cuKV~J1=9S^v1_y#G#{*`rQr}kfxH32sra!phguq>*5%tQS&gc?r7e}7Zyz# zeBnChUX6@ruOL7gHH4@jGRIxC4R;V@7JzQQ*TGObV)o;`D8mq#TMLu%xZBi1gn0j> z84QnU_Ndd*|3@9S0d*)zo9PSkrD5YPo~pfNB@Y>N77z)1J3K5{n#u#+> zmMzZ`HVI0h;p_e@3 z+%d1#;=GbzqLB~VM28pNdb*s~s9dAA+8#z@Lknt7gFtjXV(RTd+~t!c>1%+2*mBVo zIl$)Wl)5{Jek=R!P2Zl75TPp9%OS>ovkKcMwo4C^CCZSnwkCMQx8CxU7n*Ln8*|z> zekiw3QFs+|x#GNr;3H+W_YzMJ{GSiRKu(1bYp@x3NyN|AM%G07#HG9$kz@#di06J< zm=UMaL8NbGTC99B>mj`X%3_lhrxtoLSSDDx8UGnel|W|oKdm>LBf;hQrBsTh!A{>W zI&Ug(u1q#v{%{IgPztj{iOb03kKvo!vKYSyGySB!)E7zmc$6964dm|t!zlx!Ia;?c z%y6=3_kV&A_UN?Q!r-ZB!$*`l#o8RU{xud^_@PH5hYPeJ;C5=Nqq8h(Pj>SPGT zZ*q|(>bHabNJ=i;rGR}r$SiUuDx3l_-fh!Lg_Smj+Cz{J=JZr#)}H(#cXX{|?2Ma~ z{_PWXn-ooB9pwr1J>;B@<;}Ow(>p6&v{}q8%;l1;7pgoz&8nRCk~_42^Zfyfs!z z?=7I3-Nfs1ugloN{d1#`g-EGX*w8k^!cT`4)deGFc@cD|#Sk^)-}__5yUAM(L%HH< zFs91-LZ!cJb`uh-w^F~HTWw*jxh`_Wq*h#D#llP?W!lR;Bh4jvra1~!Cb0%6GP9%x zebGo1G~}1r5_z-n&t)kkCdV|nXToy00Dma|CZ5r-kUe1xIW)L*-oa0%j3~lhXnSa& zdB9q$c)ErTlQSe)<+s$IYulD^xHnYK>802}x3gqipXVpu>=vU>c5ql6V~_LGjtt2HoB>(yy#_EGi>|^_OCsNVUu9KV^}rMf|#9 zF46LX(@;^15NTfYiTQI*Go%}Cb=En#32ZnOM6|$TGLmLKH7F;9ZgTCwyf+gt_3TC! zuF&J9c`h#zVQNn(++^pqvArtMv^ZD80m-!q(j1w;#Bt69tk!V0_ zNx}wzX49_J@WcW0mO%Qqm@DL(WGHhm(@R8+psp)P)Vb)I{aC9oRdHcxgbIoI+1T~^ z-^!jfV`y+{ilB*>JMx{))t?=(KYAQ9L>BoE8u1ZCeTjT-e-a>1gFUkOLveg0+(aI1 zWi>SMaXf70mu_$Sz`)=nvYGoeMkMc-!+x!dY))MamfYy)nO_nKRvb#C$NsZIr15q$ zxsNjvF9DSQu$US!{2U+I6%K%DYGaKr;iJ!-HWG%?p|IP>vFFE7UK+HIn#|~QA{Dnq zqNIEys@9fF@>;yWaQeb`2F~RF373oD5@h3Um0biRd^QGL#FhL63RgGS$7jx?FPt{) zY|sMy{Osb0j4D$b2?=e;X>`04AxSP(XPbhytYSg_K}DPMBT$i@vW1usG4=-GVj}^W59D3A0GH&1RURGU*7*0;v~P%E59&kAe_F9 zR|C$!IoV8=*+a4liNNsOq(#bkIaog=LbDZ`*k$wgm4}@1+5d^IXVPA$hC@MMs#OPZ z)AG&=h%o-)rUhkiY^p&wL>xG_8=!oks5poYzz&l~JhPTKl1*?IaVzhfRq9$s)%CQU zuAT9TWPf7Ajdn1%UZFc#<-RFc#kTvJ%L}kd&&euxY$Og^_rFiL9^9EH6R)<>2On}ZcEFn#U z`E^+(j#W7HotGFRx91m|HgobegT75|e*W>TFZDkR%KxFtRI2lyn3oHt8!Abd0s-S` zsY^HR(6$&l&Z>OHKYpkX=7WW!qa;Hk3LTSg+yzW`_QGZQy(G2W|GdghAc@_?<7k;Z z`JnL@ATCW{VUUjjZna6B!eD=Cf3Ng6R5euXO__K{V6Ft8SV|;muxq?|xm^cnigO7j zDb~8j>sC7*!3Ti;V%4!PA^&7NF*Tqzx1c{ut1JwL@Xj0J9%K-)mBs(iwX%=G0Vk;u zTEplDyHrOYknvU1xY*(__T9m~I4J{z_+I8fhCCPfZ&y_Qi?nca0FxskJj?ztq09AYVUXV@lMg+@23pzJS;wPatiRr<$b zIXqxFD#7LfAhR!f;YruV+zX&YYbShnX)0dx>&`I<^!Ec*3oo$OO1Dr?jjLV7qFwIk z8n6%ayrE~5Ks=wlla>6BVmtxG^e}Dg(Qta^yZ9u7s~q1k@;Z&qy_sww-k)6O%s@Ca z422K!%jUnTjp~YGm?OFWp)DyXDf?Z}9(}O_$ym_-Do_J+jsJ-O`a)p$-oFUnrvY}a zl{(M@E}Hpy=13r+1r!x+D74?VO2fG0`i}Y)(U{I zM9;0OOgeyDbzQ2b&Wu)Xdpne{ohVx?M{s2QjH}}>@Z2wgzrqaD0kb0Lo1}hQk4nC` z^jt+hy-nO)Aq;1shniyV94hV(GV>lSY6qJs)tp~jNpCp0y;G2Q5IW$EZK{Rf#Xer& zxm?aSi$jeGluPd!2ltCRtr%q(=SC3>wNmHISVfo6w&IM6E$RSZM4?f;lx71UY4CIi z0CTicNow&YBpyl+*0sK|B(|&xUVCjD|JsvLHijJclT2TiiK{rb&WL&=^K(`G%Ga{O zF;4W=@7Z5mn{0M_TcH=JpRL8?)A#ajsft6Ydlj|fPJi`o} zv5-g9>J<2EAi-b5XEU+l|HssI$5Z|N{|Ff=*-?b-Rc6^MviF{m&6TX|8Bs`9-0Z!{ zzGfk1WN#PAxVCH;*YDio^Zotn;l9Utzs@jswQvm?)*X-qOEV4Z}{A?$8wJbaO~SB`@vf%KQ9LyQ_ngsx@R*%KQzlml8yQ2}9LStb_lU#rGcE1#z)b zck^W#dg-GEH*Cx(E);-7eB-#MxC|M!&^k}nP1)lkI8ZSm5jfE`s3lz7`>6AnUwaeu zOb!IxRGuC_wonbY*IJ3f^l+`K!Sa=p|IOl$AS0g|MugQ`fY;~*7zD;lfR1)fP%87FYcmjCCo{yuVL_)Yam=Y?|QVqe}SznhwYely1)z;xIFa( zuSfmsn3pTR#Jxx0;pcA1*J0CxHNpY?v9asy%s;E^N(qYFT5Vdnux97Um5(@j4F%=C zzz|Z)&cL-%7~;1d?H{S?d-@X=_p`T`aPfY|r~gIf2AD6^PC}EM=xwtKJzt~@wH+sj zVLVu0+r7^|c(TJ%puR|p~Ls=wrhi0S%*E9-$kc7TURkOOBG*<#g z0m5LAb>}=3z3`w%;gw{`>dondO_svB9-!N2BHJ%AbFzErc6WpW-%Fo3&tu0c6^Bvc z84f47XsL@JEbaypGXpRjF7~Q!5FMPsQJyZ~*`m-9(wMGO-LLGa4-ya%fgcRp6A&79 zj*AW-uqav?C!4Xg?eTe;FxKplU?w8b`tBIrB1}N(zGAG<=~|&iarvz21>p3g`Q^Ti%RrH~-lX z2y3HR4Z`gBi5bo+FZI-Mtl?9@JQgSEV5&X+iEw~U`^nx=v;LHB1$Xg zuB*{1>zP$++qA8GCQnxDI9;cXXC?oF{C~R!Wk&0%k9!W_2wl6WqWk-xt?Z5n$_{oN za08ux-Zbe?1KiY{b2m^um_i*Tt|a*Qc%uhT2|alG^@Yuk4WC<`_kNmaja*8AtXnZO zvzm5aUngxVU^Pk`d1i_mN19%1JJKJC%4SsM{NH^uiR#V{hLEHF`y+WIbOt7f-1m?( z!+ zpUuwrbQ`LqJ$mRC;<5fpRAwkm(9zd<;Ea2vk4!c7)ZZPo(R(PiH`qhMyq6pF*bwwO zuU$JDekmz<{A0=>OE*jrX^ z_D;hdS%A-!k3PSxxoZ2qRq1?QdY1fBkos*ej&o%qE#S%75llv%v1b_Ob-s-}WJpKf z<`l5`6b0O~k_A-?xh+f4+i|uY1N?Hgij&eX1!yr_YKezlRr2{9h zF+~Y_`uf}*9Z zM8d(C!SzAr)B1PJZWbljuIHNT$!Rs6Zsv%RMjPJ)Zp=tsbc1;-D_O!>zHdoZ#*~^! zcd%IiLy|N=W3Hg8E3gavsCoVJC9VVp;wd?-lbi4gk^opU(h8E28Ucpu)!#{4X_qNp z;GRrb+#B)hrC@JGzv`E90!$42{9n*-kAT5RlB~~Ae5NN(D70Dhbi2*2J+IiYHyKSA z#<0`8|G#_CUEbq&%EdjxF7M$6TLrUItYT{+Tvyf5Lhy+bYLl2Zc2c~=s2**wuu-Mu za0iG)ZQ5%IsRi<<3Xm44sg^Uek&OxE*EMwA0PZncQmpLzRJT|!gJxdo!-F`@sF(DY zr0=UlEH>-pcD#a`oHpo?C{+bC6P&MqCz8Sb+#g+TpM^y*3Dsli%lwhq2j*EdtiCSZ zJr3)m>Yjl89Zas~-vh8=wpK6Tuy|Gx?W;8QGgZ_(sB0FrmnRMftbbGFVB!o2&LU$d zla=;pE|Yh#Ro;Jl(iKcPd{RDlg6bsbLvlWJpp02lfk1hN4wRBIm=mA`DeFT|cKsd1 z4-&^vqiI!2pyS)ycAQ(3kpWD|>3WyE~pBL&dxdc9h?-K_*yS%%$(F$jL8*RDD(2tbQ_L!;3{!>+bB?eeG zxjV1mRWQ2XQ_%e60z}I1Wv7YfFOlfFF?Sg&-uk1R#3zR>3!uhWzc#*{Dzq{$z)o={ zpXcf`?nsKc+Fc-)mmDa$F&FpRR)l}i+%7mbK#6dkG@(8*G)yxn!EXhBpJFKDK!aVN zsY;n}DEE!B@1D~v|S9V<)Tiyqs1@5BO1kaDf*mxJLs9-WLxlZJd?KIxyUdZ z!+0x5lDhPave;co#9fcw+O!=08O7s#y1!2zsS-TM-bn+qg$VmrgM|S4Qmp@DE7Lbg!$VLdQ_+q> z?TNco3B{MultO@D#yS)ZS@N#nR=1-lUY0(i%1~!Llk5D@BB;lJ>pj7J$J221l$SKIztfbjTKmwaw|^iURUKE%YPu^NyPDv(6OUe9(k~*oflC#yYMd7$6UsP@@#9U#vXCJ$u$5ma(kbjAq!8I8P12xrde;?LBKQL19a* zVM9$$Dvlyxi{R%9oI*3ioy2y&GjNFxQ+(&a

5#U^`QK!q*7!KZA*TvCOJB&X)XV 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 MB@M+=d8^R>1>`;6;{X5v literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/int_handling.dia b/arm-trusted-firmware/docs/resources/diagrams/int_handling.dia new file mode 100644 index 0000000000000000000000000000000000000000..12aa186c09737ebaaf957d257ab4e7b7c1b32f8f GIT binary patch literal 10623 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 Zy|R2^|J+Q6cmI6z{{hyAg}lKr0|5LOh@Jod literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png b/arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png new file mode 100644 index 0000000000000000000000000000000000000000..64082c95235b79d521d43a606ae9b0fd22669728 GIT binary patch literal 218768 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 z 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 FIP : read(FW_CONFIG) +create FW_CONFIG +bl1 -> FW_CONFIG : load + +bl1 -> FIP : read(bl2) +create bl2 +bl1 -> bl2 : load +bl1 --> bl2 : hand off (FW_CONFIG) + +bl2 -> FW_CONFIG : read_node(SPKs) +loop for each spkg subnode + bl2 -> FW_CONFIG : read(UUID) + bl2 -> FW_CONFIG : read(load_address) + bl2 -> FIP : read(spkg@UUID) + create SPKG + bl2 -> SPKG : load +end loop + +bl2 -> FW_CONFIG : read_node(TOS_FW_CONFIG) +create TOS_FW_CONFIG +bl2 -> TOS_FW_CONFIG : load + +bl2 -> FIP : read(bl32/SPMC) +create SPMC +bl2 -> SPMC : load + +bl2 -> FIP : read(bl31) +create bl31 +bl2 -> bl31 : load +bl2 --> bl31 : hand off (TOS_FW_CONFIG) + +bl31 --> SPMC : hand off (TOS_FW_CONFIG) + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml new file mode 100644 index 0000000..e513ed4 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml @@ -0,0 +1,78 @@ +@startuml + +box "BL1 common code" + participant bl1_main + participant bl_common +end box + +box "arm platform code" #LightBlue + participant fvp_bl1_setup + participant arm_bl1_setup + participant arm_io_storage +end box + +box "platform common code" + participant plat_bl1_common + participant fconf_dyn_cfg_getter + participant fconf +end box + +bl1_main -> fvp_bl1_setup : bl1_platform_setup() +fvp_bl1_setup -> arm_bl1_setup : arm_bl1_platform_setup() +arm_bl1_setup -> arm_io_storage : plat_arm_io_setup() +note over arm_io_storage : register and setup fip +arm_bl1_setup -> fconf : set_fw_config_info(fw_config_base, max_size) +note over fconf + set fw_config information + (address, size, image_id) + in global dtb_infos array. +end note +activate fconf + arm_bl1_setup -> fconf : fconf_load_config(FW_CONFIG_ID) + fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID) + fconf_dyn_cfg_getter -> fconf: fw_config_info + fconf -> bl_common : load_auth_image(FW_CONFIG_ID, &image_info) + activate bl_common + note over bl_common + load and auth image from fip + with info from plat_io_policy + end note + bl_common -> arm_io_storage + arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, FW_CONFIG_ID) + note over fconf: use statically defined policies in bl1 + fconf <- bl_common : image_info + deactivate bl_common + note over fconf : get fw_config_dtb from image_info + arm_bl1_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(FW_CONFIG_ID) + fconf_dyn_cfg_getter -> arm_bl1_setup: fw_config_info + arm_bl1_setup -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb) + arm_bl1_setup -> fconf: fconf_load_config(TB_FW_CONFIG_ID) + fconf -> fconf : FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID) + fconf_dyn_cfg_getter -> fconf: tb_fw_config_info + fconf -> bl_common : load_auth_image(TB_FW_CONFIG_ID, &image_info) + activate bl_common + note over bl_common + load and auth image from fip + with info from plat_io_policy + end note + bl_common -> arm_io_storage + arm_io_storage -> fconf: FCONF_GET_PROPERTY(arm, arm_io_policies, TB_FW_CONFIG_ID) + note over fconf: use statically defined policies in bl1 + fconf <- bl_common : image_info + deactivate bl_common + note over fconf : get tb_fw_config_dtb from image_info + fconf -> arm_bl1_setup + arm_bl1_setup -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) + arm_bl1_setup <- plat_bl1_common : BL2_IMAGE_DESC + note over arm_bl1_setup + set ep_info.args.arg0 of BL2_IMAGE_DESC + to FW_CONFIG base address + end note +deactivate fconf + +== load & auth, prepare and jump to BL2 == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml new file mode 100644 index 0000000..c536ee0 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml @@ -0,0 +1,49 @@ +@startuml + +box "BL2 common code" + participant bl2_entrypoint + participant bl2_main +end box + +box "platform common code" + participant fconf + participant fconf_tbbr_getter +participant fconf_dyn_cfg_getter +end box + +box "arm platform code" #LightBlue + participant arm_bl2_setup + participant arm_io_storage + participant arm_fconf_io +end box + +== bl2 setup == +bl2_entrypoint -> bl2_main : bl2_setup() +bl2_main -> arm_bl2_setup : bl2_early_platform_setup2(\n\t arg0, arg1, arg2, arg3) +note over arm_bl2_setup + arg0 = fw_config + arg1 = mem_layout +end note +arm_bl2_setup -> arm_bl2_setup : arm_bl2_early_platform_setup(\n\t fw_config, mem_layout) +activate arm_bl2_setup + arm_bl2_setup -> fconf: fconf_populate("FW_CONFIG", fw_config) + activate fconf + fconf -> fconf_dyn_cfg_getter: populate_dtb_registry(uintptr_t dtb) + note over fconf_dyn_cfg_getter: read dtb_registry properties from dtb + fconf_dyn_cfg_getter -> arm_bl2_setup + arm_bl2_setup -> fconf: FCONF_GET_PROPERTY(dyn_cfg, dtb, TB_FW_CONFIG_ID) + fconf -> fconf_dyn_cfg_getter: dyn_cfg_dtb_info_getter(TB_FW_CONFIG_ID) + fconf_dyn_cfg_getter -> arm_bl2_setup: tb_fw_config_info + arm_bl2_setup -> fconf: fconf_populate("TB_FW_CONFIG", tb_fw_config) + fconf -> fconf_tbbr_getter: fconf_populate_tbbr_dyn_config(uintptr_t dtb) + note over fconf_tbbr_getter: read tbbr properties from dtb + fconf -> arm_fconf_io: fconf_populate_arm_io_policies(uintptr_t dtb) + note over arm_fconf_io: read arm io propeties from dtb + deactivate fconf + arm_bl2_setup -> arm_io_storage : plat_arm_io_setup() + note over arm_io_storage: use populated properties +deactivate arm_bl2_setup + +== bl2 main == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml new file mode 100644 index 0000000..9457e32 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml @@ -0,0 +1,167 @@ +/' + ' Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +folder SP_vendor_1 { + artifact sp_binary_1 + artifact sp_manifest_1 [ + sp_manifest_1 + === + UUID = xxx + load_address = 0xaaa + owner = "Sip" + ... + ] +} + +folder SP_vendor_2 { + artifact sp_binary_2 + artifact sp_manifest_2 [ + sp_manifest_2 + === + UUID = yyy + load_address = 0xbbb + owner = "Plat" + ] +} + +artifact tb_fw_config.dts [ + tb_fw_config.dts + ---- + secure-partitions + === + spkg_1 UUID + spkg_1 load_address + --- + spkg_2 UUID + spkg_2 load_address + --- + ... + === + ... +] + +artifact config.json [ + SP_LAYOUT.json + === + path to sp_binary_1 + path to sp_manifest_1 + --- + path to sp_binary_2 + path to sp_manifest_2 + --- + ... +] + +control sp_mk_generator + +artifact sp_gen [ + sp_gen.mk + === + FDT_SOURCE = ... + SPTOOL_ARGS = ... + FIP_ARGS = ... + CRT_ARGS = ... +] + +control dtc +control sptool + +artifact tb_fw_config.dtb + +artifact spkg_1 [ + sp1.pkg + === + header + --- + manifest + --- + binary +] + +artifact spkg_2 [ + sp2.pkg + === + header + --- + manifest + --- + binary +] + +artifact signed_tb_fw_config.dtb [ + tb_fw_config.dtb (signed) +] + +artifact signed_spkg_1 [ + sp1.pkg (signed) + === + header + --- + manifest + --- + binary + --- + signature +] + +artifact signed_spkg_2 [ + sp2.pkg (signed) + === + header + --- + manifest + --- + binary + --- + signature +] + +control crttool +control fiptool + +artifact fip [ + fip.bin + === + tb_fw_config.dtb (signed) + --- + ... + --- + sp1.pkg (signed & SiP owned) + --- + sp2.pkg (signed & Platform owned) + --- + ... +] + +config.json .up.> SP_vendor_1 +config.json .up.> SP_vendor_2 +config.json --> sp_mk_generator +sp_mk_generator --> sp_gen +sp_gen --> fiptool +sp_gen --> cert_create +sp_gen --> sptool + +sptool --> spkg_1 +sptool --> spkg_2 + +spkg_1 --> cert_create +spkg_2 --> cert_create +cert_create --> signed_spkg_1 +cert_create --> signed_spkg_2 + +tb_fw_config.dts --> dtc +dtc --> tb_fw_config.dtb +tb_fw_config.dtb --> cert_create +cert_create --> signed_tb_fw_config.dtb + +signed_tb_fw_config.dtb --> fiptool +signed_spkg_1 -down-> fiptool +signed_spkg_2 -down-> fiptool +fiptool -down-> fip + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml new file mode 100644 index 0000000..53594c2 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml @@ -0,0 +1,109 @@ +@startuml + +package arm_io_storage { + + class plat_io_policy { + dev_handle : uintptr_t* + image_spec : uintptr_t + {abstract} check() : fctptr + } + + class FIP_IMAGE_ID { + memmap_dev_handle + fip_block_spec + open_memmap() + } + + class BL2_IMAGE_ID{ + fip_dev_handle + bl2_uuid_spec + open_fip() + } + + class xxx_IMAGE_ID{ + fip_dev_handle + xxx_uuid_spec + open_fip() + } + + class arm_io_storage { + fip_dev_con : io_dev_connector_t* + fip_dev_handle : uintptr_t + memmap_dev_con : io_dev_connector_t* + memmap_dev_handle : uintptr_t + + fip_block_spec : io_block_spec_t + + policies : plat_io_policy[1..*] + + -open_fip() + -open_memmap() + + +arm_io_setup() + +plat_get_image_source() + } + + FIP_IMAGE_ID -up-|> plat_io_policy + BL2_IMAGE_ID -up-|> plat_io_policy + xxx_IMAGE_ID -up-|> plat_io_policy + + arm_io_storage *-"1..*" plat_io_policy +} + +package IO { + class io_storage { + io_dev_open() + io_dev_init() + io_dev_close() + + .. synchronous operations .. + io_open() + io_seek() + io_size() + io_read() + io_write() + io_close() + + io_register_device() + } + + class io_fip { + register_io_dev_fip() + .. io_dev_funcs_t interface .. + fip_dev_funcs : io_dev_funcs_t + } + + class io_memmap { + register_io_dev_memmap() + .. io_dev_funcs_t interface .. + memmap_dev_funcs : io_dev_funcs_t + } + + interface io_driver { + io_entity_t + io_dev_info_t + + .. io_dev_connector_t interface .. + dev_open() + + .. io_dev_funcs_t interface .. + type() + open() + seek() + size() + read() + write() + close() + dev_init() + dev_close() + + io_register_device() + } +} +arm_io_storage .. io_driver +arm_io_storage .. io_fip +arm_io_storage .. io_memmap +arm_io_storage .. io_storage + + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml new file mode 100644 index 0000000..b7289a2 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml @@ -0,0 +1,62 @@ +@startuml + +participant arm_io_storage +participant io_storage + + -> arm_io_storage : plat_get_image_source(image_id, &dev_handle, &image_spec) + +group init and check device (image_id) + +alt image_id = BL2_IMAGE_ID +note over arm_io_storage + get BL2_IMAGE_ID policy: + - fip_dev_handle + - open_fip() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_fip(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(fip_dev_handle, FIP_IMAGE_ID) + ref over io_storage : dev_init() on fip device + + arm_io_storage -> io_storage : io_open(fip_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on fip device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on fip device + + hnote over arm_io_storage + fip_dev_handle ready + end note +end opt +deactivate arm_io_storage + +else image_id = FIP_IMAGE_ID +activate arm_io_storage +note over arm_io_storage + get FIP_IMAGE_ID policy: + - memmap_dev_handle + - open_memmap() +end note +opt policy->check() + arm_io_storage -> arm_io_storage : open_memmap(spec) + activate arm_io_storage + arm_io_storage -> io_storage : io_dev_init(memmap_dev_handle, NULL) + ref over io_storage : dev_init() on memmap device + + arm_io_storage -> io_storage : io_open(memmap_dev_handle, spec, &local_image_handle) + ref over io_storage : io_open() on memmap device + + arm_io_storage -> io_storage : io_close(local_image_handle) + ref over io_storage : io_close() on memmap device + + hnote over arm_io_storage + memmap_dev_handle ready + end note + deactivate arm_io_storage +end opt +deactivate arm_io_storage +end alt + +end group +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml new file mode 100644 index 0000000..c6f330e --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml @@ -0,0 +1,52 @@ +@startuml + +participant arm_io_storage +participant io_storage +participant io_fip +participant io_memmap + + -> arm_io_storage : arm_io_setup() + +group io dev registration + +arm_io_storage -> io_fip : register_io_dev_fip(&fip_dev_con) +io_fip -> io_storage : io_register_device(&dev_info_pool[]) +note over io_storage + devices[dev_count] = (fip_)dev_info_pool + dev_count++ +end note + +arm_io_storage -> io_memmap : register_io_dev_memmap(&memmap_dev_con) +io_memmap -> io_storage : io_register_device(&memmap_dev_info) +note over io_storage + devices[dev_count] = memmap_dev_info + dev_count++ +end note + +arm_io_storage -> io_storage : io_dev_open(fip_dev_con, NULL, fip_dev_handle) + io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on fip device + io_storage -> io_fip : fip_dev_open(dev_spec, dev_info) + note over io_fip + dev_info = one of the + "fip_dev_info" from + dev_info_pool[] + end note +end opt +deactivate io_storage + + +arm_io_storage -> io_storage : io_dev_open(memmap_dev_con, NULL, memmap_dev_handle) +io_storage -> io_storage : dev_open(dev_con, dev_spec, handle) +activate io_storage +opt dev_open() on memmap device + io_storage -> io_memmap : memmap_dev_open(dev_spec, dev_info) + note over io_memmap + dev_info = memmap_dev_info + end note +end opt +deactivate io_storage + +end group +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml new file mode 100644 index 0000000..b21a0ae --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml @@ -0,0 +1,59 @@ +@startuml + +participant bl_common +participant arm_io_storage +participant io_storage + +== Platform Setup == + +bl1_main -> xxx_bl1_setup : bl1_platform_setup() +xxx_bl1_setup -> arm_io_storage : plat_arm_io_setup() + +arm_io_storage -> arm_io_storage : arm_io_setup() +ref over arm_io_storage, io_storage : io device registration + +== Get Image == +bl1_main -> xxx_bl1_setup : bl1_plat_get_next_image_id() +bl1_main <-- xxx_bl1_setup : BL2_IMAGE_ID + +bl1_main -> bl1_main : bl1_load_bl2() +activate bl1_main +bl1_main -> plat_bl1_common : bl1_plat_get_image_desc(BL2_IMAGE_ID) +bl1_main <-- plat_bl1_common : BL2_IMAGE_DESC + +bl1_main -> plat_bl1_common : bl1_plat_handle_pre_image_load(BL2_IMAGE_ID) + +bl1_main -> bl_common : load_auth_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> bl_common : load_auth_image_internal(BL2_IMAGE_ID, image_info, is_parent_image) +activate bl_common +bl_common -> bl_common : load_image(BL2_IMAGE_ID, image_info) +activate bl_common +bl_common -> arm_io_storage : plat_get_image_source(BL2_IMAGE_ID, &dev_handle, &image_spec) +ref over arm_io_storage, io_storage : init and check device (BL2_IMAGE_ID) +bl_common <-- arm_io_storage : dev_handle + +bl_common -> io_storage : io_open(dev_handle, image_spec, &image_handle) +ref over io_storage : io_open() on fip device +bl_common <-- io_storage : image_handle +bl_common -> io_storage : io_size(image_handle, &image_size) +ref over io_storage : io_size() on fip device +bl_common -> io_storage : io_read(image_handle, image_base, image_size, &bytes_read) +ref over io_storage : io_read() on fip device +bl_common -> io_storage : io_close(image_handle) +ref over io_storage : io_close() on fip device +bl_common -> io_storage : io_dev_close(dev_handle) +ref over io_storage : io_dev_close() on fip device + +deactivate bl_common +deactivate bl_common +deactivate bl_common + +== Prepare Next Image == +bl1_main -> plat_bl1_common : bl1_plat_handle_post_image_load(BL2_IMAGE_ID) + +deactivate bl1_main + +== Jump to next Image == + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml new file mode 100644 index 0000000..90ff23c --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml @@ -0,0 +1,51 @@ +/' + ' Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +autonumber "[#]" +participant "SDEI client" as EL2 +participant EL3 +participant SDEI +participant "RAS Driver" as RAS + +activate EL2 +EL2->EL3: **SDEI_EVENT_REGISTER**(ev, handler, ...) +EL3->EL2: success +EL2->EL3: **SDEI_EVENT_ENABLE**(ev) +EL3->EL2: success +EL2->EL3: **SDEI_PE_UNMASK**() +EL3->EL2: 1 + +... <> ... + +EL3<--]: **CRITICAL EVENT** +activate EL3 #red +note over EL3: Critical event triage +EL3->RAS: dispatch to handle +deactivate EL3 +activate RAS #salmon +note over RAS: Critical event handling +RAS-->SDEI: sdei_dispatch_event(ev) +deactivate RAS +activate SDEI #salmon +note over SDEI: Prepare SDEI dispatch +SDEI->EL2: dispatch +activate EL2 #salmon +note over EL2: SDEI handler +EL2->SDEI: **SDEI_EVENT_COMPLETE()** +deactivate EL2 +note over SDEI: Complete SDEI dispatch +SDEI-->RAS: return +deactivate SDEI +activate RAS #salmon +RAS->EL3: error handling done +deactivate RAS +EL3->EL2: resumes preempted execution + +... <> ... + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml new file mode 100644 index 0000000..ab6929a --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml @@ -0,0 +1,43 @@ +/' + ' Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +@startuml + +autonumber "[#]" +participant "SDEI client" as EL2 +participant EL3 +participant "SDEI interrupt source" as SDEI + +activate EL2 +EL2->EL3: **SDEI_INTERRUPT_BIND**(irq) +EL3->EL2: event number: ev +EL2->EL3: **SDEI_EVENT_REGISTER**(ev, handler, ...) +EL3->EL2: success +EL2->EL3: **SDEI_EVENT_ENABLE**(ev) +EL3->EL2: success +EL2->EL3: **SDEI_PE_UNMASK**() +EL3->EL2: 1 + +... <> ... + +SDEI-->EL3: SDEI interrupt +activate SDEI #salmon +activate EL3 #red +note over EL3: Prepare SDEI dispatch +EL3->EL2: dispatch +activate EL2 #salmon +note over EL2: SDEI handler +EL2->EL3: **SDEI_EVENT_COMPLETE()** +deactivate EL2 +note over EL3: Complete SDEI dispatch +EL3-->SDEI: EOI +deactivate SDEI +EL3->EL2: resumes preempted execution +deactivate EL3 + +... <> ... + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml new file mode 100644 index 0000000..ad4996e --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml @@ -0,0 +1,82 @@ +/' + ' Copyright (c) 2021, Arm Limited. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +/' +TF-A SPMC Data Flow Diagram +'/ + +@startuml +digraph tfa_dfd { + + # Allow arrows to end on cluster boundaries + compound=true + + # Default settings for edges and nodes + edge [minlen=2 color="#8c1b07"] + node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7] + + # Nodes outside of the trust boundary + nsec [label="NS Client"] + ddr [label="External memory (DDR)"] + + # Trust boundary cluster + subgraph cluster_trusted { + graph [style=dashed color="#f22430"] + + # HW IPs cluster + subgraph cluster_ip { + label ="Hardware IPs"; + graph [style=filled color="#000000" fillcolor="#ffd29e"] + + rank="same" + gic [label="GIC" width=1.2 height=0.5] + smmu [label="SMMU" width=1.2 height=0.5] + uart [label="UART" width=1.2 height=0.5] + pe [label="PE" width=1.2 height=0.5] + } + + # TF-A cluster + subgraph cluster_tfa { + label ="EL3 monitor"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + bl31 [label="BL31" fillcolor="#ddffb3"]; + spmd [label="SPMD" fillcolor="#ddffb3" height=1] + } + + # SPMC cluster + subgraph cluster_spmc { + label ="SPMC"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + spmc [label="SPMC" fillcolor="#ddffb3" height=1] + } + bl2 [label="BL2" width=1.2 height=0.5] + } + + # Secure Partitions cluster + subgraph cluster_sp { + label ="Secure Partitions"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + sp1 [label="SP1" fillcolor="#ddffb3" height=1] + sp2 [label="SP2" fillcolor="#ddffb3" height=1] + spn [label="SP..." fillcolor="#ddffb3" height=1] + } + + # Interactions between nodes + sp1 -> spmc [dir="both" label="DF1"] + spmc -> spmd [dir="both" label="DF2"] + spmd -> nsec [dir="both" label="DF3"] + sp1 -> sp2 [dir="both" label="DF4"] + spmc -> smmu [lhead=cluster_spmc label="DF5"] + bl2 -> spmc [lhead=cluster_spmc label="DF6"] + bl2 -> spn [lhead=cluster_spmc label="DF6"] + sp1 -> ddr [dir="both" label="DF7"] + spmc -> ddr [dir="both" label="DF7"] +} + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml b/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml new file mode 100644 index 0000000..0007911 --- /dev/null +++ b/arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml @@ -0,0 +1,66 @@ +/' + ' Copyright (c) 2021, Arm Limited. All rights reserved. + ' + ' SPDX-License-Identifier: BSD-3-Clause + '/ + +/' +TF-A Data Flow Diagram +'/ + +@startuml +digraph tfa_dfd { + + # Arrange nodes from left to right + rankdir="LR" + + # Allow arrows to end on cluster boundaries + compound=true + + # Default settings for edges and nodes + edge [minlen=2 color="#8c1b07"] + node [fillcolor="#ffb866" style=filled shape=box fixedsize=true width=1.6 height=0.7] + + # Nodes outside of the trust boundary + nsec [label="Non-secure\nClients"] + sec [label="Secure\nClients"] + dbg [label="Debug & Trace"] + logs [label="Logs\n(UART)"] + nvm [label="Non-volatile\nMemory"] + + # Trust boundary cluster + subgraph cluster_trusted{ + graph [style=dashed color="#f22430"] + + # HW IPs cluster + subgraph cluster_ip{ + label ="Hardware IPs"; + graph [style=filled color="#000000" fillcolor="#ffd29e"] + + rank="same" + gic [label="GIC" width=1.2 height=0.5] + tzc [label="TZ\nController" width=1.2 height=0.5] + etc [label="..." shape=none style=none height=0.5] + } + + # TF-A cluster + subgraph cluster_tfa{ + label ="TF-A"; + graph [style=filled color="#000000" fillcolor="#faf9cd"] + + bl1 [label="Boot ROM\n(BL1)" fillcolor="#ddffb3"]; + bl2 [label="Trusted Boot\nFirmware\n(BL2)" fillcolor="#ddffb3" height=1] + bl31 [label="TF-A Runtime\n(BL31)" fillcolor="#ddffb3"] + } + } + + # Interactions between nodes + nvm -> bl31 [lhead=cluster_tfa label="DF1"] + logs -> bl31 [dir="back" lhead=cluster_tfa label="DF2"] + dbg -> bl2 [dir="both" lhead=cluster_tfa label="DF3"] + sec -> bl2 [dir="both" lhead=cluster_tfa label="DF4"] + nsec -> bl1 [dir="both" lhead=cluster_tfa, label="DF5"] + bl2 -> tzc [dir="both" ltail=cluster_tfa lhead=cluster_ip label="DF6" minlen=1] +} + +@enduml diff --git a/arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png b/arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png new file mode 100644 index 0000000000000000000000000000000000000000..1703ea68ab158365effc0403beb88f02448dd421 GIT binary patch literal 427800 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 z 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.EZkPQzsY8gs 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%0DBK;+o~jKeB7ixx#3G|C2z=&0^higR9qZ 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%0A(UbU!Kc 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�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

U2dfetTI@gbAy%-NB`9(RbXbpLNz_sc{w; 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 bKT&w=XU{A#Bz=&feypvjr%`e3&g1_8h`-qZ literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia b/arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia new file mode 100644 index 0000000000000000000000000000000000000000..133c9cf69cb3e597d62aa30b55b0dfd0fe293065 GIT binary patch literal 4399 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png new file mode 100644 index 0000000000000000000000000000000000000000..23e865f62f98d86556eb45c409eb8cac3fc156c0 GIT binary patch literal 42942 zcmc$`2UL^$moAKY#Da(*f^)i|y?4#%wp!(-LAwm2GOr5_ zN9ju5Bl(h_U%I4j+{}21otoRq zZ5CvmPqIwy8{;HB@pKjnUV2Yv^1+Mna|8vvgkQqIX5G3R{6BO_!E|YHQOvgK-kQ>M z+7C%z^Lu9Zn(B7LcSppVZpnFK1z5|sBl11ZqzPB+`fg?{T6^;OaxTOv;{&U=sB%40 zXsA`Z2G3_Lz4K@z#1ZH5B{^Lhbvs{@OP1$I%ko9iBdG!dwtFHEB?w&k=kKRI z2>CRb-adXXyt&vsva0Z>p*q32ycI_nHII;NYcJ7i+;6Tzij5FIY_2{$gh#9xBWaPT zgzm~FGhb|^)9%>laz0<*ekPkSF?e8(HmYAed%>neYM=19K{wq+yTe~#Y=*wqi@Qp^ zZoAo5_Q#&+0F8AGeib{qbO+{}D>O@tSYR3v5}dgg!HC4+Gen?~lPI-M9If{N;T4yedJ?M2}`$Q;{*}w(` z_^+TRO~A4uGQ%^G-nVOlU%F8|ChCmk*Z+`7q&k?st@k!x-73L1z`ZApYEyh6H5?_; zw7j>!zATpXX87X5JKNT3Y#)7C(>n&q^%?WP#=VTG%K^ffZG1A)iUjF`-{Wm9c-lCMP#JI#fq3b9oex80~4}YpCC- ze2$*>6PlS!;1X-B?`!5a`D72f;YJHbQHLAsqOl&??Hg0ZYvm5mAoKG->IS(hO|I>9 zlE-{uwsEXBR@GNExMPsopw(dNk^f_Ti8i&r(i43!z7V)w-pujak)G9~Xf~Ef@&P=w zqDC|n6{?lEJ^u~wggo36OQ*M?8y;D3iJU3kX-R^;fSLU!Zz~G4Y-sp;Ki&ehIu)+K zMTLyzt=n8;jG-wfM4Bpn=)PZtY!R*Uby4#-Z^&wmN{;ef8F-=FuKQ2Ju`n~FcnX#n zSe%C;y%I8ub>Ev9R(v$@^w>-;5470Zf^i}kRqpxy8DG5yh3f25y7 zP|{L+);&Q7*tO*!rtUON9iIxR;yOSKMVkB>dIxULhy&ktGeI&U`_7S~$>+N2UVfO| zf5P`~cvVTEJ3d`4&&O)wmb`zZja6+q)*3e-x5ti+ICTeZ;Dk1I6^3%r=%Jp_6vD=#3~m8+AAeU4#!i~r*TsT2^0k`^F89`N zoBkP3S~F~!3Vj_ZnX08y^yr7sBcIX!<}fLPI%Io%keu9J>r1grqEgr1?vLYK^m`9l zs5;g=%c*RuK6t_Nwgm+uF`>cSnL@Ki`JQFvMvkqu#@EMquU54RFxNhrc=;?Bm43Zb zz<07zMf5OWokedsc$R^kgCdBZIZbx2w^f0D(;}GR-1<+cNc_&YjOk(Zknu7ztS4XY z&V{HVCr8|BcSQf_UDrHsFX9T!JipHFC$g#$7g`=>yZ!Igedk}Zc>CfBaRoHLmpa>*ZTWp$x5@EHTWX_ zWaP^EW0>t6Yp042M+jMRhu<+c;tbpV4#C%gP1v%xWb2Ul^%;ee?21hX?ix53yDqyP zT8lEAvP(9$;rFi#Q4N<*j7q)Nt%_@jTPJpR%B0z=f6Dhi>+?XT*^GxnqRk~#fR4)B zN;T^!tN;h62x*4nOpq5fjG`<*S^K@=VOJ&#Kz-`j1a z`2~8V1L>>u-N zsIve1{FF$X$S!(0eRH)!S?am~H+|GwM|QNyzYM;z@$0crzlKdryMx`&v6kT$oSwYH zxV2`}ttS2`bK2D3we|w#Vc#>tgHZJ~Q{eugnfeI^Tw_r`9jcnySQ^*L;zK~-|CaVD>? z9EK^C23Lxkb1T>vHuXa|Aev?9Qm&ng>SfJ9dy12emy_jzxv6iBxngE?7Om2?cD@}C zd=;xGE7+S;$pL<}Y9`6tSflUSd5hHQ{UUt&;q>~~A73FkF0GD=G~J7-;Tlj#Cv9o* zmWQ=NS6+U>wI95DR!dwVo>yv>lVBYamrYjft;T5jgnrAV?MFh^q&Q7+`V8fwP_4Fs zb6j0`kOu1~%Y)Yee|BqiRG*|AM#OO#U0d&wqfXGQ?B6H;XeEIz!_t@Ae3N6f()T zg<&fMl>dF`brDnd)T1}6vN7|uP0Am8Uw~*uH|+jzfTw>2)O^zS7bEuMa4`hG*;lq* z5>1-d#**jID&8AT7d2(oD-XmDL9j`VN&8+!VU>sZuAt$LTg z`-7=Qs*+t2aFT859XpQD9Qt+0v%UUdV$eALl=_+YcbGlBDeQP&yDTD{K8^c!p zR55*O1ZFN3XN3CZvQT%}{xLW$MMcvRmtl+hy94jB0d_lM@|9l%d~VHN4y4J| zQ)JGTP+CaKmu=AO+dZD6Q98O6`kVe|-Z7QcS6`{p^V;{6okC94B9nGyu4M{wODfzN zucM3#sgwxX-+kkXZmQeNbRV#Hjl6$ftih|vo&mm=P{8hd`z{oEbVYIBqS}JX?4(cN-ExWEOkKF z)PHZ;{dn#WyQSxToqd(;Ms44)*hU6ADD&CF37v(dPW%ZL2EPF;7 zh!cXT*Y1tC(7E(H50xqWW;~8aPFkriPrD=WZI-zDs?fr7j={RurGMEXE3-1+_leei zzG42JP>1C3sl)0fI5&lw&%g2S>H~NV?DWy9VMgucsbw9qQHkUTOJdIqWiVrXSW8ue>SmzMt$nxt5gvQ^=F?GL5ElbLeo7 z3#OCBIzdge@d0bn7`HKF-PN6zGuN@iq+s!dMQdz)&3KI7{6b1Z5@s|j?u6WC*!*&F zV9)N*39Q|^pvmfS7!0AHXevN4>uE8meW2?a;Iy>t*zO}+@n9&B@ncy)-!UcKuYncA z#(IhScm0+MU%b)XFFGGD?C-Pv$i6_^p<^G{L=ue4mJ*Dv}b-cAvO zg@78}>Bb%b8%z?{P}V^Z12@6AuAC=&r4WmOWD zg}S>C%Os1+{gU^eWJNbBJdZRMif$oRbIb9GQmGz@LbZ*oM- z2(-HN99{2iYxE89$L$!me$TDi-clp@AYldQa9vZe6oPl>p#mGt5OOo)T>{0|emUWn zoE4s$tP%j7km{lzCHDfoojx#Rk-MeV2-)1e|C4I0P@t!7m^3j6__B z=nwO8z1O>Ph=v*4`F4N(@c9{)Q95RxyK{YExTILTQ*?oe!0tQUy(bqDnUbd8kp01m@ z?b4uU+0Zm=U*dD64-cjkh`rT$HMyyqq0i%}=!()WNItH?Xb(k&N6GET(?7U|+rW0( z2Ve+^0!mj7Q-k&$+Nsy&oMUIE4(HOy3Evd8_6ymCi?8n9ItZ;h6Xk#Og!BhleQ$(6 zI=5>6hb19SX=FVU;^0MOJICF!1^nmRk$a}a7xKF#7P-3xsdg;?95aknri|N_)!9&1 z@DdQHPXcp6K0kHJk-N57s8O&bk{h?t(Xt~Wz&~qVv#bE|N7~fg?a}Oq3viYX&p=?d z8!GFWFI1mD-J{R8Yd?GWu!t&z27*O=CRIp5S7)j1(i#6JiQTjxmmgBp*xqhQGx+_{ zXzQHt+BNg1N{UB`I3riflHkE<>%o+9WX+*xXy5pQaJ=BOv5~~H7grg+{#Mf6dq|!b zlw*|sbJB+!F{z&_p`qyZZ20rD^PQeWwA8kmN>c}sKbiwZXG@uyzZ8lYCh2OH+TEn znJ2@Bcl=W!EYn}ip{NL`@>g^+GBOAnPH;57>nWk98%vzOd-$!)XnxVfI`?*SI`2J+ zK9}Xpj$`&4!%I2UmYQd;%PY>SecC@TFt`lY7o$Z@ZBO6TxLvHQ)=k%9#)h*raY%#Hz}*T%V3W0W_MC3 zam`NzH*DUmf99%DCh}k6IuChF@L} zDqY?F(u7*qE#v$+H}*ieeWt0HNBYmla`ZH7P5m_2=8sfXqA->JM?W-nh`|EV;=<`3 zTK_c)IK1%Jd60xKELo^7y}hFgg=(h_Wqxya-#v3Ri%(*&ZGn1juCN%u0m5VoIivOmAP>X{@peA+^p7f!vlVuTTE2HMdw`+wdJUSSpm619_cKh zpyL}g17LrJjju`muHk&&n9v@?%VRRECeu^eJ=ySMK}rs~G-?kOCNZms$ot0Titol1%pX)D-HY-TgZTPh2{`5RIrML4I$ z9A_p#OF*zb0{HtsE+LXqEPi72&1Uh0g%7WNQJVkEMbfdI`L_hj**C6$-EY}em^@xS zT`{{0_-u4rT5>;Q0JyAAl>ip8qFY9Zg z4db{AQC%ul8f%_a34T}o1K7XF#aAeQu^cRpVON>L40NuS(r%xT83UFZ#6S+-||oek5Ab zqN8By$6aGFy|i7O?#Y^>55w$%a#wQKtrVA+O;}B?E5Aqy(A?yI>z^pNAft^h$yFam zc*~dzCbSpikNHPo*htFRd!>G&zZj^_d2i-;sLemv2Q!Ov?RKj@j(fATi?fM&eaG)5 zcj%eWm<`=ebKm1wb0XqO-}88;vvRfHq?r`ZQ&tN|{1JHX$JH8{J4Cmb{lqTXl{FtY z*zqjEfGBAZWk)DeaC=Y-*)VKY2e*SQ-W*d!~P$LG;uhXN?Yb^4ZQ= zD{9gX4N#Bx>634sE8MB;8eWdWT15Y}{m>?~mfIC=;gcPt9OG>6*>$z-Rj}3$+C1=D zp<~Wd3(a#gyT84(BO0zJM|M!yD=L2C4;#5cZQh8z%6_-NKKuO-WF3l{#D+~iRB6@* zwYT|BDi)7o^c1gDmN>|Am`13XG%cgruf^YKO7Ny?ud#Mn+7fjCD9p@dkmTWmcMH9u z)PC&6R7?X0$IXnpmQ6J8g($vR#jZT4!gFK}IFb!6MZv?pu-_u~&sNaZ;S zn)v^I8YB)#@aI;uUp~s%OPFKo$JUZ>bNtzhq_7T@BIaKpTHJ3{uka?PfK zv+rw|S?+lTAlwyi=`;C4=!!z$K+H6mC1xQz&+~=+#pgUE^!HoRb!iA}w2u1r=Sn-T zZZFxkK^2KM;FXurbV!*KXEVv`vpH`jJcSQ4K7L$5IA_;RhcGBU|8XSdE$K}&6SsD9 z&zj*mH=1j`Hqt3hehJiMWUA_!$nuP5I$@i?mqss>#C+{OL*3XM=PwBgNO$+j{*?O- zKDY-x$4;ExTWO{$nY(u4Ec40Jr|mFlNlBPe6jz#;ydpUj>)x2}GVVcCs#^JsWw|Xc zq<`tr?n-yDd)TCwQSQLN!%v?C37f~Lqsi5u0`)f*db)Ytg>=$EqfGH$6@~J`0?Y38ds^kr{at}mdA=@F?rn|K742iqmN`1xqj)=gURnv zBO@bWbbRxeN(h19qB+%NiL+Tpj*;hS`%Nd>zERF%Trw)TFXJ|=Lv8%Y>Q1_>|MM3w z{`~$;$8Ywt^o_EVi>HokH*N)4M+-U_#we^&d6-=uss7QTDFEidz`&57pWo&9XHwi;~_C?h1~I#gi5A!ywZtDeA*A8$I`+gWF4 zXOEQGd`H{}Vha$zdiAQ9*j9OutZAcPP1U^LF1{*3z#=U@osEVjIw{G-(9mQ0N22?} zu*}w|tBlWvxZn1ZfPlte2Ta8^ett(R3OSFjs1T+O2?^O*usAd^F(D>2?M-bp9q!k< zFO1^9<8Hg3Op;InqYp=1#fUPl_TNRklXSPcckf*g^~*?-Cmy zbxSU{?QtBfc5Vs1@axyFBS(&uG!o}+)BO$a-i?lmD)Zf18sA^?JUBQgD=X`f-TheC zz-#>J%AQ5z{wB6?cxPikn~RI<#PQ>riGrMRa)AeXJ2vGzn^>pifn04vLqj#Sj_Iys zR~MJi(9j&sWYpt{V@GdG_)PT&mJ(kFL3LN@!7 zv8QtAN%4iKygcq6rYl#j)bB3UIn}SWK8lp_=;W*VkuG-_A+?04(6mY8y?OH=y#O{j zncNDm&p21UeEHJK)^=uc^5v^n#zlseWuD7pOPgzxG1>=f2~GM=D$2_DE49$(2h$S;-3QK|P*V*Pfq` z56<7AT&7Mc@9o=jo+`gyFlshf_k-?~8lI~ziV&a^{vq?_%a@^{p?Uo4bu})n6mjR@ z-wFx}vegr0S3Vzm_3BkFHXY%i`i- zF*&c??;DtyV6+2?1GTlaWsll&K75#*nks^T@hzAdj!Z&ABIc?lac{k+?F~Z~cSnkZ zt5%xy$YR7Oi+<3+B7G+WFRoRm^E8qMSF5MuO=b5t^r-WTi|?Zx5;0zT+pAs4Vp#m< z)2B~^gHNI}kBBDoUB0Z)fCJNzTCQIY;Y$17-cB90x3^bmj}BD@mxpt^?~50qF2mxB zWlgd8s`0eAIKpZhTW)stwNOEyjahKe!gA`tl32p>xP@+P7`;I8{RWIV*V5U7tOfmC zVL+?9B7%6z5z$YGzRdmItz7Wx?CcsF7JUPQu0$a&K|w)b;fvQZMwk3926&_FBPg@|c@hN;?@@dU@@Ttm>X@(_C@2pq)D7Q=97D7Z4s1reVXCa6g&f-^lXc zMh1%OeenWuV)hfCpRomOXOy@P$-g*36|mf}CG9k@X;4X{^#IyPa(Vg;3n>C5QoAu2 z%w}0SpJaS+@1jb8pkz&utiuC2=>zL{rDj ze-(xE!n+)$Ap&QqL~5nW%JB2^%g8kJEsYY=V`Dcg4ha@;VF_I_KJn!R6^rDcgArw6 zs*%g!{n7y}GEGuQWxMqF@u|>Rj^Cl$3 zn>d%t!^1PQX>{M)8Uj38-{8bhpSC%iI4)NCkx5d`69ot^eTdOocYBCS!K1#*4a!-o zVBaw#4rvmuHXa_EuPK>G9s`cPINsC*;Tx8mtDO#Kn~X#9azK{!TdJ9X#4+mTxs(5W8<%gS$p!@^9<9x5p*wY;E`g@}1L)tM0X9d^dH zJ7wnu+ur*r19zPyiJ&87NneM)V_tq~eiYg-zU{%Qm#byqiXSPr6>}W*n(NPAS$RV3 zO&Bubqf@_gC*;e6C*sVzTg%Iks#H~jlk9OwW*VB`jw)&CYlC{)#=LaYHOq~=_x)B| z3JvWmO<+FNE>j)gOGf(oej9x%frq=}$^M~*Gb(KU8#^=UE#}6-Sy(&zyA6Q92CNucd?;jn%`Rc)|hVz z3gyw2B!a8+WD|9`SFT+);y~$S3qRJ@iCxnWQz~z=vuD)SVnn1eGw2M5%7i7&r8d}X zp!O;0#aLa@VDi^lQ_3#B}l%-r1EG&D5e1R;GUISL60XPH-_PW<(kqN3u(aAhi{ zu;4D6&hOt5-iNH!3msGKTlf$sI2_@_3K8$uqjN?fU0~XT*+#4ab&sauu+m8#kuc0 zk-=l&<3ofTvDC12AHDcI2O{F;_Mgb0SFiT*PJz3SuVEuHx#9CgA3wf{jARo==o}vG zC-55guNlo180=hifh4Bmo#fE#kisckK^fFc&BC(ZEww!AjyCUdd>b2E0Rj8e`KuMq zma?z(XvumlOXcO0S2lFr%c*bc#zx3K$FkSM6an~3Nx4W=&oW>=ZiH9b^lg=1Mid7@~y9o%-z+*a-lGQ zn8aijb+~>;63TIu|^cRE#UT*31U`J#|4pM zsmjvWi^ZXe@Se$U<*Xw0=9SwfE#a5DVRH6Ul?bd(mX3VClKNX~fLWAwaR_Yi%y;<} zy!6QuP!|j;l`04yN2<#|B8++Pj<4O7c?hHOlv#d@{llR?GngH2lKgc9?F@P2zq3v7 zf0%Fm&(`w)gUMSWmX8W+>C#d`d1z$2?`L-RFz*QfG@VfCGS`|BQ8XYK?C1Zl`LU?@ z)v+p4z#|*I^pC1LmabUxN$1_zd9rcISz4$2W%Yu!ml*o@~hHKhEBDV~A{Awn}6C}wHl+I%gfNCZ0k^_=Mb z13S|M`1E@|MXcfAjXqHx5s{%vN)i<<(V@+5P)C^R`K@}D_*@${l&>H(+MGw)+1Zsd z)nVGJKN}n}{>A9LWx*qvtd(Fb^<3FWEt%6ivj}abmq{q)goiw(;~4ayotGLSKazm( z&2qfa=i|lCK%aX4&lAL{*6rJQ_+ZSX2^wTc4ElUg(Af8CKDS?AUyY8AvMapK^MuF< zKS5_%7)iYD!i5XIn~Myxe%0+(cG*XPaHRsgWn~R`vA>9`6B88`6%_2}F*x$H)l6g% zh33^3p8SQh8+xi<(IAR^i;&sSZYBJ%t4x#iug%G6?dj201l<3_##L80iV-=)#Me`) zl^er;gly#+>w)RjZer5wWz}*gGoIsSnaHpTby$&#pkw*-=g;3LKXP_=Lj{iBu!NKp<~p3CFk>C?r7RVyN`C+w)YR0#JS!_JfgwQ> znH?@Ny?y&O@SP`5o{Ts83z*l&#>Gv!Nj`e?s16uG#p{la4*%Uv14Bb{a`Mf&fi?%x zFjY;>uJ#x%$cpZg=3ZW2^77B`mw2KB)+XCwH8EV;fKgf>mR;fGtnBMNLDtx1Ud%a2 zlqJZx&_8L|Jxha>S&dR$$RHPVyi6CS6pjMu0!$zyBO_NUm4-TZz!)-it~Q&yP)z$E zkTKxwYinzP2kYt2o;`#4&np1s1%M;W7(S0nNlBTUw1QgzsWOW{xg;pKHf-v|$HOD# zwekSwcI(!ytfTz*>)%C3(_Fmh1sFyl=qx3Rq<-!Ii>%+z@$o>&AZLUAto&*Q_@t$w zK^tX*1yW~z_wHBd(s{x@X!oM-=>pD8y#o2V=PD*=)OxhY)W2e4*rw7%z^wWb2Lxcc zuoi?cac2kemsF}&Q1dUwO84y6_wO$ycNyyIPllp&b#;rOFRibyZ~i-E7IW=1X$E@w zT<*}8ho{b*;S~^YVnk+TW)9+gH)fqzf49IP!jb@v18!@$UxHrv^XCr6#urb`10rP<&=)W^8X< z{AgIn=+VG&{rWuQX$T=Uq(4O3(vZv$OYt`3UoN>t>Yi@lnDz=)kE^24f;?+Af32;@e}@~qu&JTn2IS4vXJA? zQ8LUs0lxu8*(phKNB1IqwFQPJPo5HchN6iAc%#^O5r6Nh1NFM0zbcBrVN+y$QOM0o z2rKpV^{5g0r}m$`R)2$rRI>zhQ(HIoQ5&?!gPniiCP8}BlBa`%`bxUAN;et9!GKKw z8oGOmJel}RCAZfbR_U#4TVr+XQ3XE2+3Z$feWR7+6BfV2D;nzRyDb6%Q3(n33=G#e zl0}hfT3TcE-s_rTxGNk$YqiwWAWYfaG5TBcTaqlkwFAmP)AsK$2#cmD2k(hzC!%9w z+QOMUi&EWq(UMOV7P3%p`iPfWo%<5~_X%hSSo8Q#pFV*Uq}I>?(E{8EXxL$=K+|Yb zU=z-fr1OB_)c^~EOVucVrazt?J3-QffXM?_5uV?hY>xp`fM7Wa=kIethEUrJO!a4t z>kPzJma{5Zxu9W?^g_Z05{t^mn!)mcZd`~W4K~)WTUgQvmV<`-&9p~h5@5Ak%i~Qj zo9O81_(7@)hVhi}8xKA|U0GQH{US^i$l8||C(?bFBnZX94zMFX-rbzXbE?OK_{arH z3g~B$G>Tc_N@_%BM!U&O6c4e_O5jN9-cxbD{0qx z5g9aL$!z4+*}F42ISFiZcXyXf!e#RFvt!^7RbxK(pg_SAhB^hpRBzw@0{Wc8jf*a> zu3$34pk5N9-3!JVd=p}0zqPg&Jd)>d0qzZP6yy&H=7{DXDo{2hZ{95XrB!6O02Ba7 zNH{5tmNhj6LNdK~?;iYp$nFC5zms=dDNdgzKg&GJC}wwO{}#{cKD#NkE-j~shHbGJ`hxi^ne0V@aH?_93u!ujID6U(YAIR-d zppy9@TLCUmWLow5)vJ8Z@qk^ti2d-!Y~Q2)4|hOV1>s5(tfy)`fMgv&D?sWKHVu)q z^CfP~QD0WhdhkEhj ziQy_`Wb)aAo61;r;a$<2v0>d;B_%Nqq6-9Kv3cF_@Gwkqj^Gp40txfp{rkm^=Pz8a zzHw3U8-%UYZb(g3EFfIQ$H#9j;Y>@=yE{8AZEZ8t)1t&f96}fv3kV9p>OiIebvrYY zgZkR_>vyw|fK{5Bnn+=I#6gsxYjl%RjtU9;$h6YMZVLKclB7mqM4z&vq8lDVfFs}C z#PfiPDC1L6JM!U9%R!O^k11D#5~#wxy@X38Xx28Nwh)HrF}8FiAWZUL7YM~04Cl`2SXfw?nqo`OQMhNGgNEl+$6(V`Vq(Ea*)F7+~!>72lKyuQw(Z$-dr?J z?i$|MdI-7{&QSo+c4Q_^Dx)uo2M+DrWKb z-2r;EE#u>Il9G~FuTB$dF?F6!%_T1?P(&gT#-*jDg$@7f#0ijk!DCS)?&@!yfAwbs zwsT&&!VJoNPnrz*3wB=KAC)HZ6kx{IR#y7@`tQ1?V`F1;j&VV;1N;Z}(6CSh)O87o zoxyy)IuHC^T25){deDnBcLx`syV5Nm;9J|%B18N8_tPXbm@ZztNKX&dAX(Vt7hfJ! znhcdvR8V-z?XoPWQ9geBxX`dD>E@%?K4Kgk9HOF|-$Kr3DTm)R1za`*Im~79dvI`Y zX=y2_?&ZIjx0otOjzmE}?^X+uD}qff0I)MhCU*xU#&qxL#O-abtUhteuP==({D&0k zf`6pR?1CZ%ne;K#3*e>(gEUVOvxL&A@hf#{Ve9u}VE4?S+;@(KhK8Pg1`HxJG=f(rZ)0#^A}wM z6Gz*Wn{Qdv@B?tyQdQNFqx?p>Hd20^(tG==bMsd5BPG*{>;-W#6Z=6_GbcuQu+SgM zF~>nd)Ys4JL*?X514;n+4kj-xEzQn;8(h-fvq;+;6lO5J*w{fg0oe6V_jtkH0QkDJ z^a5!B^*rL@P5Bb^@>qiu97jdP;IAin>AZQz%G}-EL7~0I%lomUq{^fSV1p=QI2<%T zzZU)qH}~w?R3~!X#9XY^nO&Am2ZEuxni@D4K#%^hO0uNif8=&&tLvGOQa+hTRhG)4 zf&!O)HP@=oR^@n2bS`|arPPuGxI`|$cy8-3IM?^@sv^Q+$p$x|9GJu10pcaWXCHtz zoK;$M^zV68Y3U6qsXFLe_Gf0Gm#tGBh2#li{{Hm)|-OLM7 z;H5RiBj?Yb&pJ@kqkpGy=MEHIeHvtCWe<8Y6ks*Q1qF7fhAE3@!WYi~RjjG00Z{EG z&I}%TjNGi|p;EKK4KQs}Gc#sLZujnqyG*JQ!un60It40XNnxR$7>|H}oX6rlC~Xe9 z2TIcQFwi4>fdCU8IstKnKhGTm_P#vJa&h8C{duIGo*vWwVSk1kVzw_!#m}#PVD4i< zfh3f70F41>!|~l1`TB}W2FyqjMv|A82elQ@M)PV$PT_-jH%TSkL3Km{)E%Lym4ycp zT|r(xDF9!4?3d?-ryhN`18sK%dk)jrpJ$19A?2TM%IX=?a^ARc1FQi&NLF?XcQl62 z%&Wf~REQT}bf8)g6Z5Eigi&_T?SckDy%$Wuu-xG?lpLXyd|6m@Gcu=`s2#oA%jpk2pnA$0YBZq0n@kuovmDYnNt3l&SE4RvX=`Ytju z&YP(A!(^8*OhwuwZYr?do-!Y_vMDJj?1iT>i`U=5CU^b#FutE(J-q(fK@kd-ZZcCKyInMztgz0K1L4kY#YRV%{1wn zu1#^Tm5D?l+k=S{ax3`-7!6aiPZ^J_M*)b}`hK?(6iL>>RhshB5w80!je1~_#aMC( zNjHSUKLGL5Ovn|vcm`O1ku`9y&2ETNRF#>}sjYj#~9)w4x@U4U@2d3?;{iua#0G8=d2h>wMZyTpZ(lE;<~o+tWMDR_=JrqIjzA&^k41}X^|RV=v+lAzyWS(~WC z&j}y5Kds>weyguq9`2B800Zd<8zk5cOs|PJU#QHsUjnTTunU%!mXHcT#R08JS8mrI z43N!xGD^9|kU%PQ!2NV#Q#jA@hM6>9sLojmCbIg>W>i;;yFcE8g6xywkH(z|0#3wH zI>T&+Z~=?4*1JqkL>%`MJa`JbaA1PKQJiWYq9K+^jlM;eJ6Q~PGOSpGdSp{>tQ*TJ z<1>gx7wY{~S62rEEJ82r@9hCDc6D_HrcviXm1<;UL{CRYlIak_kQAZD|MlxvIC*sO zP>VLeqRtKzvt!UQ|4+XcphH?e@9ah`T`L{6yXE5R^(03AH+VNm8D`b;I>a5$TQdN9 zM#7oIitm+iK)|_lX#&W^J~YIrsi~PUNfQS3=1bN{T?de7mWYY})I|{tNDvTRv02Ss zMaUeaRud9t>5^?3TF;7lT`*~=bM|)xz!ShKAu^| z^BhkL>`g9WanFSLs$a#CrKjh=}?*QwCr%%b;AI~QxF;W9m>+0#*GV3v*Z#SfG1&m`)i-gV; zIK>pLTzg9gs^eAPMEKB@6)8?OBg#ITi{3M-p0cao&IA7Ah)z#$f)G$B3&04#qSw!f z|9b6jDoKkfJp#pVWyW?pQ;CcE!UcC=aCmGL7F{88z5-(-2GvQx2tOOP#uk#ydk2B8 zu>y|)T-pRR#Pk4Se!JCOT5CL}GA=G|b#?UxIpsX4L(q6-5^%|=sNm09-_1aG`R6B! zYfkgCaGIEptI^@Zj87n#cxT*jDOzyYQZdod@(K#(;Yr3arN$|In1N^UWb6F@QLPa_ ztNb-upt}-z3Vo7)-Px2Xgl?AG#l;1{#gH9xS^nt)`f*diHmKvTUcP+8CfC?N(H9KA zvcdd&^?jAh^Qm$7tGz00Ss5&=9K;2I+Kmy!qmQXE;$uKM>ZiPiLdxe*xf(y zC*lU_U71ULN6GvwY%f;73Ntz==yR!XXa7_C7IB13w)ni3`cp5bkT+V?Nb|F2#l@Q? z6)-C%jcJDm2qJ=KewM zafSQi@;6wTF=7TM3?^Bd^GM-?spcAy>u0JArncgKE3*6U62A<(3OQD=LMhU`e9lmEz}l;_U_@80q`pYew5tA{v+1J=)QI8& z4%#+)my-5bI#!TD!#*{J!6?2y@;}vlfl_xW$ewm9@AI{<6p>fhTOTL6#jWRJ; z|2-!O&*rLP6>L36MQqT?NrG4e!dIqVDq`W6Ch77-|KbWXU@p9nrkbzpmr|-|U`NL~ zo60^>hjo5t>1oo&I!kz0m@Vudhmu&t0&5#`dl+`dx%`F@nee3LHl1v7WzbLv>i)FE zAJN^Qt8fxe7bZ^Mu`(M++niSlMisRvw7QRcvQ}?ars0#6;1@hPK@@(Y`OR#+kAFQa z1XWb5+lu>S-3iE+$?+CxR8zk#d#ggz*qXR&MvhYBPR2dsTSE$tREk(smd)tvKuwfp z9^bWV5+K62AKEUDWhK?p9Q;~-p>u{^^E27wH|K7#XPGIP+))4a`;mQ7=4Blg%-4#_ zhfxe2pG^2NdsK(|=rVZCk7t~YJe}Il=Jmzd@OWjBb!$dAo&L)6TQx5()Lc%e4@{}D z6=Xm4>ulSy?T(5|x9sksKTQ`pHMN{g&hUC1bk)(Hegz^HXeR@P2W@PDv8q=9z1m^1 z7!2*{mQ1Cv*6IeRM3ObXM0C1nYHEUr5UqM;b91w`wKX+06=FORiS&~V%uI&g_(67~ z;~a8CBVQjPj3;y+LjT7G9iV;{6&2ztXlf)FH#+L@;K3!@)A+?j^0QMOo}LNu@u-T5 zi%d*mEx(PBR%ImtG?HVTqxIec zKYw}wrS0zS2C?YT=zaL?Q|j9l*5zqwtn$HSWvidfSy)*3`1n8)OcX_80AW3{w>JgG zB}z!+f8^xk^x(k_f1;bc{erWd7-{6vOPEiIQBlIzvgBDER*yPl!Lk-oe3)q&X#&l{s5ju*F!{)z+RlbLQQL&e%CT9>2Vt zn=b3UX7!N?dPT@?&;+9#lywK8vkoL7HfgV3=s6u9A0HbFfN0hh$(H=?o%HTvIb_#` zg#}-z6aq6*XLf$x1Y)tdx#l=} z7%Gv2gR$oXq2~n9&;EM);RkLtZdwc$OC{|Ga&~rhHYFt`oV$>im=hAovIWiy?Y|U# z@%!6;jbUM(pYd?S>(gCK)wt&77v9k8s|$X|BLK_{sVa^i<6O+{`Geq z`#<&C2?V4lKmW0Q!F66<2L$3`Tmk73tw;ayhS+UkLhWfW5q-AztTKE?j;*pvSCN@V)17HQlwXJHF-pgJn|p1b4c&uaMc&AEOYP6lRs z`SN8S`k>~y<>lqMxjvM?yvbSkz>O=xs73V9kdmCv^*9_32iyMg+@nW-8XIM=mV3Cn zGk^@l!0;F=%gzU#3S<{)6iqh^^YiCsXW@SMp;bEd*HQW4kdSuh1onmffKnsKf6`tn zx319W(q<#2*e4Th)8PJhvty(gB3?;dDNVn}3&P-IC#M;g8gL+T^25VJTWGF@dQ$_b zdJIo}CGYF&i^CQb6#;|>ll$@G2izcbGZk7+$a-O!Q)z(*-txiVk)O?B){N&1Q23+I zCZHqfB7u%%8gJ+{R7oR}#or=*edqt;>y4CI@=|6cUCB*D<$~qP2%`vVSJDK2!Z*bp zspl)|lcsZ#D;O1X^0fnLJ<3PV)3m1C%^#HEBmHlhmi|ib=5_4|bJKfAvrsX||Gq0t zR3WtBdnNH!1q;lnd>WLb zuYl>%yBvKZa+T{}JL=0{dFWt)2+N8I3h4PKyBOUUNorgn!#p^7MmemN{l@>RWBczm zlXr`K!)Uaaq@;;^m?DP+==!BR^#S{};6A}v5n+(~FIIFFSVQ}YAhfM`R?EH;VQjqv zdzzD1XjB4J?(67iO6QcMloaH!s;a8<@_zpQ*FrP7L)-p%`}#t`dSHr^rX6Is#Aa}o zYoWD%JD*G{6^P$i+uIt_rbHfYaUEDiqAq{XzwYbf1GFB>7P5zX>&^UGJ-?cHq|Xvy z+ciW%W?Y3X0(W;lZf*nu0nOct3JT4@CTAOpoO;?)%JfKD#wBIq622 zH>mvqU9Dme&55f(-nlMc&KibZq3@tH&eGrO=`b}hfn+IcKg>%(5e9k^Bv(p@84!X% zHg08ZgmeOBP;m(fzI&zb^YT=SG~jy@uq+UvKiqu`f`#iR?GVXqg{npCc&e|&>B`t#yD4LK-khkICkWAD4H%FkP z+_l&NT?6gy@cj^|5m25v1Mr5#4|~$#2zus@LiauCix3VDS6)K-_)c~|k5O@NB z*T{Dr)Wwm;dV_gv9uzOuBhN|V+dsl*02J%l6)4$2)}~J+Z{D=26sl0*38lMgr@h|M zd3{`X%uiznm4yEmP)v~qP$A(+&@1H?6kPNtKD$T(unWsK5ql`{U5hYUVon$R(c0kD z)GZSf6uccBJvKImQ@{?E5YCBN2cFhG?HRNdAcZkO`O9-&EZqqd5HJzQfd>UD&^^;r z{^lQY=>FmL3=Gu0Ha*rim~dTUWjZfk+uHj2%NP!&Yy*=ux(Uqs82Wd!X>ilNC@Z^{ zm^d*t6w-?~D<_)iycmUPJ?RY*74UH6?EjRY!q)mJI00kLh!@4%R1gr4Cz`)>O z*<-9^A|5pO-^n# z$Zu$A$%~8o0OkmihEEPVJP+I3+3nYCK#`dCn&)$Ec_KIFyVLox%^gS!@W7&uBM1^~ zx7YN;^z;LIYg!L%2~|Y{$jr>#JLT!&k(Ze%GB%ICJwg}QWKV$*x}+5QBU^5af7umY zu|7c2Mnx@AtFihW?)Y``C+zH0>aNw!=JHNIKO(YB*)Au}ccS~_M|n*hDBMsx#2La~ znWJOIeb43Z?B>SH%`IHu<>iILIN!PO&DY1rhh9nO*rQMN8nTI2n|hAr6&1~4WP(vA~Y$8KL_S6^6OicDHRBNf=Tl7Je-rWs3NF&M? znr-xCw6w^K!oBo_+sfG3VH%Q(i)+iDKZiQc#m%h~au%Qu0(^Wmjyk9$Ha2~donG~| zwVHcE`OY^ob2qHWvCu-ya+Nt@fL!0!o$ORVQy;Ea4Xra4NjWlmX-`O zG{S{j>EyAlfZnr5<*>I0!vl6y36f`~?C9(9$qybp2nwPGV}KcG!-jA;-9o3}{4NlvI9EQ8dj*FkuiPY3^pLZfn~mD;v9YTc|2XtSXj{wzhqm4Pb5>Qw<;? z0QBh`tDAH6)-63t%g+zjfhZnwnP?)prfNO26T2^*Ibe2Wt+9(2Bh*vT%9kp)j>}1E$Vq+_I z8#csJzBRnRuP^HMZB&5$8_=htyuW#K0>Ttbv(PKe9`S*{2HL~gU<=U}Fq4oFeEjq& z+xY2ONHlUpL6%_d!bxXluGH4432VhFO(CXUQEnp4GSXo&a zt|_+3JXGkctSnGGSUyWjOB*L){R8fW^(V8iaJP`qe!C1st~`ei^61pzcY)Ps5>}M{ z9ku_s8f})U!o~f|YBcLc%ooPArXJZSLEQdtZtv9A^8+m$s%may!^F-W8xv!1VX=MS zl-;{rO%56w`NL_thd>M7HG@bJ^@0Dg6Xx}mD_>Pq)N8)2sd<=@p%Hg5n@q+6ibZ8@ z!Zk1~IFE*gm)lc96x?kTg(a}0|=tZ|vZ@)rw3vdjqN?Y2Aragk@#3eHHwXZvq2Z0Cz z?pS(~^2zm2PI=?WX?=z%Iw125KKFt@rR2mSyy--epWo;E26}qT^z_-dW*|7g1Nf#N zt0o-{jRSl;_wL=pHJ@=TOF2cSFIln6V>7MV>C?ODd;w_$1_nj~Si>l>K9jSx&-i~- zzb?P{xK2WuoA$=do7C?*T3h#0LZTJNmkLfC3r2oFKR^Gg>gwU4q0bIG7#JAF9UcYk z6_05K4_;9L9aJi2JS^&vKX7v^>P-_+P6X{+b_<+e7nG4_&*agZojNr((cg@MRFId~ zy92_iPhG*XKB#QxuSM=oe*4p>CeXe)<>_w?higPgkF4${4d4ij z=3{7ABqcS})Ly-Q9nZH{WiwOtK23C6hgDQA;`0;~6kNHo4^pj{-zbTr30j<_r{AbZXN0~E@4UJ!a9Ch6n2_O5smglL9(h_Aumyh^ z9E^^Q)i`N{iu5F>ydgI)4scNA0Xg@YG`;^)^$x&l8HKF4%(oj(iOJiSI3Aq zRAj6@n9iCQi7^=j7JJnLGnNOe~X0FmmG5Q1&h z&AwFn;br$IbXAak=|P}!^r*FdQ$O@%IA><5t+>X4!=pK15IlNNN9V4ta@u*Da+`tc zL8n-yoK?5np!$s>^C$~5^ZkVzn)g-8Eo$GwhCn(qVzr}o&BkSaRpQ=* zNC4(Q5D;RPZ|=n6wj$PK_z2Js1NFfFT3A@f&QEutEyUnsXJwU?P>HUl(`zhHj$;}g zXC^kbd8pk)3zm}|Y7QLVRq>-h0_z-T0Ve9>g?HpMU_2zX^-54Nz6$AT68~-+W_I>% zv;hF#pi-!>uZP#Efr^mkwYF-}cMlD*!EPNME@>V8Z`$Dc)1}XzMdY z=gy%Gn?i@*?d0v{1(0ez)%hX1p9^cUZ^p$2{$CsJt9xG>hg-ZQx>3?bgD}ZfHd&wB zvw>w4%n~PZedauI*(oWVFY_z=xe$H=Mzcplcd_aT2@3Wk0iVTFf$ENHXC8f^8{zS~ z+ewKl)X#6pSawd%p{anM3M+Lh*~IyERTYe$bMU&Nk%y2G)LUt?|7zD`7us>=-KjK5 z35s3JCq|XqYHAL4pA=`fvosO9%(5b=g>ibY?4&~Hn4CTTrpAGZLja`7EZr9R6*Q$!fNUr*1P1#b5pKd zS*4_j5futBQ`Z2+c&x91Dm!6z^Y8%ujJIuUZpMm_F{$U$Gc!fKRW8nZ6Mk+iP0+m; z(As^8<|d3aBss~Zdvq&STm)443jLox8v_IRM2o0p^G~JC6%7vV7&M<)1km=v0n2pK zO}HsL=b%cGc;CRlyJGJGTo6DWaVH->%%G%MnkyRiiAeS)^(e2I4I~@pBztMgZdp%3 zQ<#CfX8(cS?P;M@^VMeEYI8R8OJ%qg&gCoy8bv#V2T z!z@EMsPpsT54RS)vxr|@(D?!j4DQ33TI=?j)d?wz!A*U9!VNJ&O*bNw1qf{Wjtzbn zyn?`u*Kh#GK*XM&9@Mh+=K|D-juB4J>aw!W5Q0R@`pRVO9>5^Vu+8v_g*v*EgD^VhzKK+13Cba+!1RfY@yuH1fGmMN-#tt5=0jPBIW?9!rk0`Vxn3@6V zjE{~|tzCQM{_ej)3jQIOc0k#mm&eui>dTmdfN4w=JvZ|9eJmqUHpt?y0WqoBZm+2FPwGazZIfi*)A%Y z@4Mgwm57Gy9R2$BiB@jJMWAf$q|^r4KIUj3DbX~e5Q)H5pS(4LiGe}FtZa4uTZjpR z*rc~GTmiCjJ39J>sfYm&7uU1O%D~bO$e2iZ`0(IVFWYYS5a1@)uXEE=?PRHfA{~&y z!t{t4>qLLR@hzMX(!FeIx*5;s<~9`)5`uPiuD>PMF+q-l!yluLP0dg;W1R=Mif^;C z^i)c=wgRzu0pIzrOhyQ-ICv1h^Q3D;kxLUOJ$?WM`^y4?77( zilzf52TpF_Iu9NUV1amJ$YXRfJRDq$_0?NgK<~0gL`C7a5j~`}x`)S3B~45iS_FKM zpPT!2<~uaV_{?e(Z+|JP%5(kesLqcsrM@U;?bfimw-7JW+uIA_%enwXU>!%&^%)Jj z0HOaCPpCBGUhFqFHn^+&sFn?`6O)r{0Q``&g4dIe3t`)_+jE>x`;1yC7CDp}l(SOn zGk#Bf^U-eq82(@Tj)8Q9vBBoP(Zo@C%HVR0Hu3CYz5CNrel5DpZ%0B8+R~bB{IZ6U zGS|5mO-enM)8+@q5_Gn>=)?~e{wT<5Pkt}Rpfa(@Xop$LKf`-4F)>k5QKc{NK*X?X z*EfvWHk(0jg$wCT4iyZ8PT6wfHCm=QvvgH%Q=e1H&110o)?9?u&(gx8H<|c=mo8o; zJVPrvvGm~5XVPf?d%LQT&!f;+rCOy2Uw>?DCo;=EH~_x_@#cI49}uItp`jseB+P0+ z^&l|92-fN(jL-R`CrUB03x@-jHL6PSCrLC^=qPb6maek0w3LCiALrCdMwXk~pW0;h zEh;+vBT&*&P*6~EqF*u1Bp5{ut`!wm^1A%WW*dXrVN$_3jSFLJOs~*Av#cJg%Rp<+ zzOCUE-J|I90U@mEdfn3*Z4&!9E9(?6Kh!5wI5gc@An28PlNH-M_%DNz>+9)xn3DrY z!p+eUPI=}R^Tb-#BNzC3sw9;DSj_9G!Z0Z&T&_rLy55Nkf1q7$@N z`l`Rm$^<>mu4+qPwuGpOyHXokqO*gH6k`% zN==|%91o1C;K$p9vC=*Sc|&wnJhZ0$eDaH&RYXIG_r%4;<1PG@ z#!zL|kKg-rzF`-LJ3N;}w|1SY&f;zk2>tK=yD{Z2{7Bo$_WT^D?!Dk_O-;GNUg4H2V{w8~biKggh+DTnup(Fo zks6beuKB6>dmXvFvQh})NB%b+F8^`(YB1p>Bqb$1dZe{A95yFeAetp53!pXNB}J2m zo#PYyFbLquL2-G~y z_U)^H*~YRm%EH7X6H?%N_ju%0e;(K?^^GAy^ZWgId1_}&H#og2Mb@wR5 z+?fS3bd*1?)CdIEpztBDMu_1GD+>!y{$ga20Qb5lhXo$l8O$dO<6JqEG+X-$Pkn(U z_YKT|SZ@iT)@y-`nl?-t5D~1WQnIkv99zA1&6>^r+3yEPs#$0_nfyiGuy;z z4zn z_LGyN^cbs@#7e)_sCf6?(xl&hfBzP!`~W^+WrMyBEvU*#_%?hMAXhkB205ZcHM z>(~DQ8%<=q`*l+B4;dYGx*We-S~`(f)?FMOKa9;Nq~4_Aq7BetUpw)Yf60%dZk?;Y zRodphV+NsA&}o1T4=t}1qNxHDA%0w$Bf2+HOJ(lY`6MwXXSE}Wk7aWDNcjM}{`ii(N=U@I`~i`nv{;wVE2IfTajARj#z)ROtxerWML zJw5SZ(OppkQUIzQ5fOoo48sPDnZ;&PEQJQ-o1Zc05*x7&yX(T6(`5XF$BYqJv}=c^z=rA@sH}W z$->lh6wNHr+2Zo+=#Y_=l;q_tfBMvq<`Hzy2x9`I2o(3R*cBicAlw2=oPueP+b#PReG!O;<*r$X8bbkMkx?>7}ffkU_%k-0tGlw)esH<+&Q;0g^xhJrnvbrkeGXC-pnimkh)&`TsbX4KuT|T9^;%gUiPz zC#$NflOAt7`q21&ovFgjwEe(Z-Q{KDI&IL4ErT2Le_R!dvgPMkma`rmN8a$t-l60B*aO4^q0}g%0k@_P1^Y6`}fAs_?(x2 z+UNe~G@CMLO{)Xa->Y9sV$!!#~;m2~%^t`+r>I8J+AnXul2pdNZ z#V-u+8eJ>!MEJ41JVkIhU4SB7W%vQ10_%V;h^LuW9&q1o{J{%hX2d-YH;+S}KA>>m zADAX|)8gVxjErLC?Dw<530mjCoU)l8qLcJXe2UW3)8pgiyGT|C4g>`U2c!A~ z2JXiM3_a5wUKpT0I^_}gvo;7<7{fecNSum-4EGrvKwvvA)({H0QT$U zRsV4&>)XSevX`4SMTV{KL)Y5H`W>UZ2;W-^%B|RI`7tF57xbMwcL3*rK)?g0F_8&j zMrV!y#k!7;D*yLb6~I2m9aNQVWOy{O?pMqnOPDsj3s%O_PRwK0fKr$0p@1!xboHux zBBz)=PoD;k4hnbY07DQoo{ou=;VTq~_E4K%+P?2EG--qZS7>r}woaGkKMpcd@egBw z7r~$j031eabP0qW@i{bZAR&>Tcfih0i1RL}TLFQ6W~-!k??y%3N7>ugw-=VVw4E?} zLRo>LfaH}A4m*H~ZaUF-R3V#{m#Jhl`Rd&sS-M7I`<{(#|5JoZ=N}6DCIlc}I4WqE z>%fVUH#%x+f9_7xv;U%&?|S8{piCJzt}kGFd-LwS8w+b5es3A5Hq*&cR+zIi$u4sg zD9Z^aB^YxXl|I$BcJgt5Dwpb;Gm^T0CsZx~Yf+41dM>P%pRl`d%QrB<#8*{pQ*Ok4 zd_$73&Lwh!TD9W7g~x~7Ow9H1qcd^x*{sVH_GT}QCGr@+7mGVAA-{qsD`Gs>Nw}wh z3s2h~5we2GL|y`ONUf{2vPf;;4#n!L`)E!PlY!3r&qkiLMY<~$QcSs%>Py(($y}vz zLY;vh7b82|b|{sIAaJyQf`%ohz2>w(q6+ij@`3RLwBx`4u-^8Ljsuh<6BCJ@A^(me z{bWQ>u)WzFt$m^min|!>4- z3>{w6)+2G8g`?F*n2~nyp@zzecS%;tx?umem3*gVWSoJQEHWYj^a)_>(2mBsx<^>M z;jc$iMyMo??R=P*Hv=XKt$vc(F$pT@TGf8Z-N+`6mAd z2oreuvIolu?s!>5YU=3FYis-k$wNNRjv^6Z;e%YE5S{?tmYwbcGsi5^;b z8u$_-cHQ4US%T&k5g|35xBl(g1r`V`<_^#CFRpIjshOa9H|iiwe%j_TeQ;A)0^Acf}?{n9NC73hHP2rTTY-Y^{4SPDP82=u$;_4 zhOGq*)8YOjf6PLyQf$BQN6NjIDM%0Xot#E(Gm1W=D|r9@&g{3};zgH#=%)v(<9Ib6{Pb>Jo(Zh2%M7Z!)?STWH9lCxkyEaQD%3^{=4+hUrMp~K> zFh0;I(28TerdRUt^b~!usG)K}KoBHvM+Fb3#igcRuISc1dbCCZf_|)rXr2UxgjR9_ zyX>g?;D9&As0`o}(lirGOXZWXVpi1Jhu}rh*VkWM&Y{;sTV>&z65|ZhK1KitDYgEkhvCUaW(k#%5+E0~l9& zVroT!b(|UP4mb2Xo;=5tmt@-@QMcQvFQ~T9EV(OJkoh%8s=&*aqtFXh%P#zi-?qMe ziyGGo&6ljfNb+BgCKI zATL`^-9jsmTFFiO>Phc{`gu_BY&nP81#awx#=By7k=rmE=X2m6dMeOGf5C(&CDR2Y z1Shg*$$4~;7&UQfL{3MFT*4*i*To_J`I|WG9G-;=DrP;Q)PK>|^*A#86EtrAxl4W1 z&)T|JNGyA-zl20_|2}iqj_N43sg9}61`nAgxb&yLl3OTNpSTK_#uTzE(O?6QM^SS@ z-Ws|ZpttyM2z5@wP1i#Ybs#LmN|bSrOJJ=;x4Ad*5o#Nfw*E=l@cfBfeBBE(9=;Rj^ zz*;eb{B+oody>TfHf`TNaqDC;boP7#0&Nhsfn!h^)!-#PxlYH#lsZWF@bTj*V)9Weq@i z;4_AKPKjjx6-cVchcns4Bo1gAngFD-K;qGR@~Lyf%-X>!E;&?GXE<7L4H1*k4i*SNq%+?3#Pe9)-RFLHW}?3Q&as;kJ9o**ycMr@ z??a%&Ei5$1KDxQhNT${Z`Y1rG@7uR;AuyA_ zq^k``tP2YS#M?+6KYHvKq9ZR+-%Cw1#mxk|0^B#+GL&|f-R=%37{DwB8%oqLGC??v zQx>z!%^u9l{rmk9CGjPi-nTM&Te)hfmx>PkhQS13^#$JF$U%{7HEyU)%&Z8b>)_U2 zXPA@ZuiMIIm3lIZ-}mBg+^wM-`_k4w=yGIKQE7A)>tjs+TB%JAc$tF^I>8d!8}8QH zM5{6jhEb(5R?b(&Ds=6{CZ7yZdp9Y+sebmg;$f!P-EOa5*{*uwGmf93CtP@V?N7;l zn~KGLSJq$K>iyfEJxG&=8gn9M3;-Lwl0mW8v9#7qdkNC+ZhUqg8;P?~&{4-e({tOu zeAYc>CJ@s&Gb0(9TAk&JKe@36kIq*YCRVL^ObVSzS0V%Bu0{NWsFepQq-qF$FNmf~5>33TGk~&Y@ z-}E-(55FG_zq^7I!OhdIulL>3SG4rHzPr?40FYfp_62`MKYCvXfn|oR?cl+K9JB%U z9ffM!q}f?mPC(&skS|x?-rU^W+PVi!o{lX{bx@r%<@%RDDY0*DO(+30g_vh$4w~;o z(ObKA0m1td156l_B#$ZEwG_<@eKTg+5VIVY;J8iMpGdIHGD!Ls)qkc9q|r*;p_$f|eMy%1m>NTjXgiLx5|lLfJBJ_1Yu8sMz@Kh$Xq7oJ@or zJ)vM~#t9HFlSADa8dy3&)d*4eqv9m{hN2Gg-DP*!aT{Xkjt)cb{N-Pr zrMzde5mbf2W2)1)v!Ma;rpwSvXMQudr-^^4$L5Oy+ zp2WDp*{rfZ-LBm=a9?Tv(b#B{|En0W_9{k9Ocg{nctQdiFhW3!W$F;K7+V@n<9Up2 z5PxHPjGXmwhr@k-gpVFj8t7MX@#`%&es)vHSkItW!2<#w6y`>4?3huEa5Nw{d3ig9 zgaTuVtAU&S!f^EL(1c{|L?aMoPY7ngyV@7dODF8sOn zrdC|RC-Z&TX3lP}G9$WRt_&kiG~hBsSHZ~ny=ZK@RLE)13WmauzpB9Bq{9V=z>2E+ z`mpLR5Ea#^iTtef7AfUU{r9>_Yh`Se0iW%6s8m*+e+GoR8p@_mYC0;-q!@{DV_vb9 z&??^Fln?cb=B~RWi*ER0lNPz_dViKzJ@#tEr3IBy}4P9@*@dflA zE$})C*Qp;cbGhiB;*)R=Y#1<1jGE9Et8rh$HHR42X-oka8M*zzs&x_3^^kO8$uL9l zBig*-7bCD5KxtAkH>oERy8sJ3#`zJzml01UlQq3>INB~ds8sSXY^=L!GB~#{IGsqX z2$q?(Hf9tP%YxoEClF^C%Ri`vDUWWa8MF!$C)aXvgTogTRCmistvoz8b46!MlXumGFabCHGt{!)AZ_8H%x!?f~9X$^3minH^(Q$E4nOF_+{Wi@8hFw!a zOi9D{A7y3jL%aa8!mO>6AuPbc4h_+RZ;GB+1yX}uzSA0OF?MUV@k`0ww;UMSnj%rY z8Ig-{C>l?KAtX$;<8L35cWz}$s)E7;ne*r>$RF7+H_2RiFG40Vp|Y|o}yM}7U+93na)a201=kr9Gc%sj0p1SeYx3ckTeocO?Fl_((A{rcCsud96SmktUO>yk zU#NDEi=og46Cj`fqUPYpz|joyt;4fF4Ul*JY3ww^h5$cpZ3ssoa>W}6corlin7O)2 z%uPe(;~xSSwsZxi4H#_~zLhK_uy4~N4**$*{}+ndZCkd)2U|cSw`<$BVCt1B!EEqO z3=9u9JH|sRjS1z}&hI(R*g!gV9_BfWZbm*c7LZ(Im$$Y;k28(g4|zs#IK*p+>`W=H zR2H|X2oh=aD;pfT_Jd4h!m7U%I>b>50U+r#PE!Z3Teb-b9Lx8+zZXz0YLh5pOXolkls^!&$iA zH6ExRwz#-<02s-Cfqa6+dN74lrGy)yqn8{i}Q9J-!^xPihAy>?Go2Lq%MA*>Wu=wYw%mV8KO#kpDaj8f2cALd zl%z1fn35etBe$`k=N+d>GGn;(`g{3|#|pT72qDP#*(q>ok-NmYZngv96cQPi)Hxl(G+G#GXdq z8t9a&7oKpul(FL(6TseGkZR8Y_v=3f9|8tpCPv1<mKD+CVHUh}|C#cS6vS}3q4u*M#KYA&ptkt-t*^Rsou&@-WRO%jo- z`X?z^Cn=1u8<5Zd8R4G|3ASL>TcOT&2)-5QezMpGz63)sqx!jD5*+8d@LU}2gCdV&AT44_#5 zy8lL1-n!AV+wHu(2uK!448=-V8k<7@iTqQcJO)zC&ksWg(CDzv`UQgsHPeu59h05GZd334^ zN0tOIltm7$uZCI}UMM2n4RuXZa~%Ui+4oxsX38OoT*z9mlGj_r^D;4Z#8UTm#{2a* ztks_}&{N4yqs*wDg#z32P8m7HkWV@zDJW-Pi88e9==ZRmA!_?Lw6Fa9xO!%weB#=) zi3q1g(~DjO9#C3&_^4nF!-I$ofgilv2?|Rh61}L%r6EINLciMMi}_LQ>WRplj6vsd z?$h^Tu&Qr6_UQSmSI3{8CE7#h zVYw^#&6wh}?X1d#IrY|DZ5tsjYK4zn3;P>9uzJ(zeTV$}aUtJadi6YD6qu>eh+KJL z3L+C7GB_vzme=@^?yP_4&_o&Y$z;~#uKK_jPa@|Os3=N&2~zcdT!Vc_jtbynjeYwz zl~nFJ`KN$7g1K?6AR`M4vRpC_68P7Qmk;LUCt^fVfKUKtEiakQ=H|zM8lfU4BBN20 zAjfjPePI93WX<%!HnFb`Q9)U@yNQk7p!R`U2kL8Z_T$+;-sz=Z)$^?@E-h@2nMo+% z79EOsR%vZQRa^8i@7%dkIPHNE=x<%SY86gAW0vjvHA#&0kZ@T5J$Q=-2;^{Xu605C z(}TzL7O$W7Cf%voQK_CC2ld)?wq2iZ)-GR@w?tV9F`KH~qClR5gMrsRMo7v(aVd1_ zy(f(uitB3k$EJMotmYtC+1Xb|D0TqhJ?IE_J!>{eJP<=%xSeSfudm zp-3-4ZY`C}q`oF9vo(@ZXHrzV+V31%P?}$y33?LzR;0E&NFl)AWf*n3nxQF&PMd{=P(*lkc)|MJDyk+` zqg@TLJqr>xKYYkU@-87Ux&a^tYTN{?o3Nw_8szJk9eUGn%5s(T#O>-Y_ZjM?ZH*S{ zMYNN4upEFc>Ey|bxDUR|WZMU8U2}u7*6vp9%Jz}Y!08OMu8=EZwN=dq_1xlr;X>d1 zv#6jmt&`wHl$DeQ-{p;=bQoeiSWKeuZ>35Aj9boYj9oYIz)O31eMghd2KSgl#|**O zz+@a6KVLFABtw2ZYX5%Pd*kzmWCcU2^;GmO*I#}kt®zHpw=@yaDW&WID{tA(XX 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 l;JPP1uLXNu%Tdm+5Id_7rK&i76QTi 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png b/arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png new file mode 100644 index 0000000000000000000000000000000000000000..4150dbefeb191e3ea5e01859fcef8ea8e3f7f9c4 GIT binary patch literal 38566 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia new file mode 100644 index 0000000000000000000000000000000000000000..d12eec07dde88316538645ac5605977de5e1222f GIT binary patch literal 2985 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_design.png b/arm-trusted-firmware/docs/resources/diagrams/romlib_design.png new file mode 100644 index 0000000000000000000000000000000000000000..bfffcde7bacedf077f78339ec488b51ec16b1c23 GIT binary patch literal 17244 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia new file mode 100644 index 0000000000000000000000000000000000000000..30cfbd801033ef4fdf501d26dfb54be746793f22 GIT binary patch literal 2543 zcmVDKATLo8(2hDWUn<>qpB*B*?kpHvS<}wO=r>k&t;L{XNzfF ztEo57)4Z5GMCsM^%dPuNFPdg9UbM5P?RB(_XGI+S+1)fYAFYpRdL0+L&92sYnV2fo z)B07Fj&|(7TXmXRrKyxHufP12eW`D$x$xXp+l_XDRI8|1CfREoGd5{G5Ckbgh#3s7 zmBx}u*o?{h;by0WOHT_|oE9!AZ`OHH6;V>XhMeVj8b?`;S{3*4@i^r?N)5&Kb*o1& zZj-9Y-?;zVC@l}^Kz;f9+xFf!cUdHh{V(o|8Xc`XCX4Fs=9{PCs#|~Z)cQkGCbKkd zyZa=o25bIlnC5q%j#KaFAMeSAy0uR8uuw6N`TNbo@;+I_2a!fkanUsY+q0RTG!M8@oJlmVl7~%cYfSRlAMw0uI{U9G$`( zA5peU<7XsjkN}HI!VxfA7Kp>K$Z;C4ZsvKBz4jS~?xcfq67#yF8+l=f620{S(gW)* zPL_97HyA|>Z+{3J2UgzYk2ft2<=fV>{ms63rtty1{yqLyZ4nz9V#5H$){b7pJbT~7 z-XH;!mxLm!q_RcLq&g0`vZL~br0>+}db-XBeo=47UH)UWu4XApI-KS`mZr;X$+M~r z&|aV1Myn)!GWQi_<#bY3PgW9*oYg=2_c(ost7IN+EBE{F;MJ?s^7>$;@XHVD2l|qa z@8aY!a4&7}od`vfLe8BRQaU!AbmW9)(UA%L1SRl zzQB@$M_Lm^h~x|u0WN@2V4o=bZ@Ea(oV@7{c^|<~9n|ocguAL^ME{TEh!kv2##}O6}Y5_U++ec2^Ol zsd4i(F=qE@)jiPeQYkQF0&5{SBT{}MyDNtvHRfO+Inhk{_9rb8Lqcn1?Jk8HnK3qo zNuB#@9;~i^tJ_J*V0Fi5byZ)1Qb;Po>`X8y<#W#20MQ1BDsgF-c^xoAgetGgy+d^I z5VI?h(P1Gxh zEvus)ic`irvq?SE7$P3u5l<&6KSRU=NpjulbtZGFRjJdKRBT>ZrstkH~3O#J4WYELW z=%EQXK1LAfAc9y2976jSL@R(MYQ~Kqa_!2BjYbf|&c@RSVjCrcAdW^5^#|!;|1D=m zjj(ostRl?o!Z$$@hzpSk(e#qq4O-HbwLBL2w0dX{r$qK#H0HE%z-PV#NDGys|i(syfB6O;yDw_QC zSVZe}Tm+>$#c8ZoY6hhmqf+SsPOb=TCyNCVN;1DES2jpk6Xs5?kh-ksvB;-Bx$-p# z)Cmr*v@k>ovh;&+<6khN0Tin2-Hags*R9ApGG+K zO!}vscSy!_l9$GnX98S8H*Egnd-}PnpY0iynCA7)Ll9y9`BTq7 zv-iwDQ_s`S?dP@#>3?oZ06#aO3oz;R)D{=~oFgrmyaZ*wa=XUKso;K(Z1wHk510SU z9vqUO7^Vs^!%BXl{AYyrUrgbIvU7=;*2?Qz3X?Ss)5;Q>N#Uj^rMc{r(F1fa#nPB|^M^8<{X^5wWNXC$ zv{uYz|6~e-Us_urjg;bG4K9~8uAs-_o_Niu3>Nnk7Pp;`!RU_A=nk+|P*CP(Dj6fx zzdG3oSxu-lx*Vu*OWHzFzecxz7ekWKlNw#spVm@hRwsV&>q^!*)QG9JHdiX#r0`=Q z!DukKd)XK)?ihDz=>FQIuyi@Ei4@YSIMqN52?cHnj?o&J5h24avY<|T`55GBgz`l3 z0PrDyG&N&iZfA!~g7%Z$VVPLkP@OVxz23_*4 zOYKw)x->>z>YrScB0+$k+ut@Le1>z+K)}F+bIhjHGbN?O2!c6;P!J~XSw%az7^G>8 z(!_?4CQaOLU8V{=OOpix#2E!AP1^Bg6c^WLb;0~y7SZbZ?Ej0npo|!s F005p7;Vu9G literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png b/arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png new file mode 100644 index 0000000000000000000000000000000000000000..ec3a44118b71f2f31e13a4c9b81fc0b793e2ab83 GIT binary patch literal 12085 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 L+p>8wCeQvKK0#5L literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png b/arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png new file mode 100644 index 0000000000000000000000000000000000000000..1a9fa5b0dccfb6f1041dfbfe8dd3321403883973 GIT binary patch literal 77894 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ℑ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 N%ak9xO$(XAUiJ0_b=+KBM#s3dPO5D-j`pw zTvYi#{&H2-NVk3vbjJbH7jZCwg&|1IiFw>cvowP{mD1?2-VgonH|K7kEKBSvawcCO zJcA6pVY$lFB!6A-J8;iUaU`le&%L}66+H8JbmnMG8lq^p*EN{!w134&LxLW3@XJNo zJ7!FPLJyWI$V-GLVO=Oh&KnlyZSbdJzw3rql)*6U1){>QT>N6U4&nKrIyi~!`<$EY zr5ja)Fz}?)1mR=c;qA7#fp8nu7l1d0YkWW2%#w-#r-Dt9y>Qqe^6OGueLv#Jk>y8w z_`m3IbTAarJrk2XCke_K7+ z&&D;`I@j^OlU5;R!vId>QadvVJ684f9S5%{g+0;?XcW!Gt&BAA|HMjM+M2vN1~iT1 zA%Dfpl!`8`2XZynb{G5Hj<>f2%de0~ApG_@Du}mwC>@uQsY`R>1 zmf{e5KQ~^6%{+gKzE=mgl%Q{;=ytH1Ah{Q_nS}(>Pl6F^f%a zue;Z!pRc5Y@I=JT#4Qz3fqq_6i0|9^4Ua~#?AeXNzq{E}FtU^Pz-mRm@bbY$2heU! zm#k=oUyh)*4wkc?PRmL+I8dS>;kp*Rd_7Z_>q!q4aCwWSrW7+KjRpSJbI$;z>W|vz zbCq@F=T7^vF_lY$&mHDZ=ZZL95>GX3H`Zaz7L~t$I4wl>^hUlYBvr`7YvONE{fsRV z(N$8T=D{DuW4B}JV0PBD84^>ZEk!fc?kYcZbAKupVt&}@Q#=}K`NfiEWuCGF{7(!L zv?R~QuCXEp%F?i(;JsWjxIo;f=&N40xOz zW&jY(A>lVAyK_qK)mN^*MVnSzlqrR#3w_$>Y5#kZ1CCmIZ#XBu+IXD12S9sw%_f#~ zN*33&#>4n)?uVgfCasQw;V;ih?>}0-SK}rKjyz3Hu%BUnj|b{tu)$X0b^8JqXyW`h z_j~q-JY3{be7w5JAlmeE-uVD}(p69q6VK7hVk#Q4yqg9et12^ClGJ)DJ=kBIrPJsQ z8~tK!GnnY8a>^y`vI?EY*<+YKrh+5)NoSSrp4#l$KB8IYg920GGJ4&sDlhkb zQE9c7JUo@undwMG=_@nvu1I;{)V04#4Y-j@wVvmtOP)LTw;6vm?zoROPROPi?7-Vi z_xqb8kPHFYY&^Pr;J12DtONfZ7x+LpB2uke+BCrJ{-yhLc}j2RzLd9f7~Z@Mmv?e) zAq`7iL34`x=+XPHRvi+OTbw2aG|v5K)1PXkMt@xoM3j10k;h=9Q|peeyWYR_=J)KF z!w@rYAo#QA<8X{I4uFpyF-RZ10ACy}P!GiH+gMl5{?CB+|BMhf6*>m&t4*EY!v?OE z&jE*DdQF_k)n1|H#Wx37?H|7JBLSRw8kCvVY_#MGJF_w=M+kthEH_whM s@7~|vU*EZ&g@t9?l^MnmxdNXD`z=d1|K!kb;$Z*+Pgg&ebxsLQ0A2pPH2?qr literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png b/arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png new file mode 100644 index 0000000000000000000000000000000000000000..fa5c340af879bd57b2c7df13fdce82adeb1f9deb GIT binary patch literal 173315 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

?ZOdSf4fs_4e6H&={d-9T!3DVhNm|qL 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 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png b/arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png new file mode 100644 index 0000000000000000000000000000000000000000..1f2d55506a5b4677d89b37159b1a6a00ed759d26 GIT binary patch literal 34202 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 A1^@s6 literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png b/arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png new file mode 100644 index 0000000000000000000000000000000000000000..58898c531e968c2c5ea29596b561d077e49729f8 GIT binary patch literal 66389 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

pU_eBZFxpmCYsCd}Ws9@2~aRP6b&uqjI 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 Q^Y?H52f4i?pUM0H0P3K06#xJL literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/docs/resources/diagrams/xlat_align.png b/arm-trusted-firmware/docs/resources/diagrams/xlat_align.png new file mode 100644 index 0000000000000000000000000000000000000000..cffd3c19181ca820083f3833b256772ee99fec98 GIT binary patch literal 46712 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 + block_size > + image_desc->image_info.image_size) { + block_size = image_desc->image_info.image_size - + image_desc->copied_size; + WARN("BL1-FWU: Copy argument block_size > remaining image size." + " Clipping block_size\n"); + } + + /* Make sure the image src/size is mapped. */ + if (bl1_plat_mem_check(image_src, block_size, flags)) { + WARN("BL1-FWU: Copy arguments source/size not mapped\n"); + return -ENOMEM; + } + + INFO("BL1-FWU: Continuing image copy in blocks\n"); + + /* Copy image for given block size. */ + base_addr += image_desc->copied_size; + image_desc->copied_size += block_size; + memcpy((void *)base_addr, (const void *)image_src, block_size); + ... + + This code fragment is executed when the image copy operation is performed in + blocks over multiple SMCs. ``block_size`` is an SMC argument and therefore + potentially controllable by an attacker. A very large value may result in an + integer overflow in the 1st ``if`` statement, which would bypass the check, + allowing an unclipped ``block_size`` to be passed into + ``bl1_plat_mem_check()``. If ``bl1_plat_mem_check()`` also passes, this may + result in an unexpectedly large copy of data into secure memory. + +- Line 206: + + .. code:: c + + /* Make sure the image src/size is mapped. */ + if (bl1_plat_mem_check(image_src, block_size, flags)) { + WARN("BL1-FWU: Copy arguments source/size not mapped\n"); + return -ENOMEM; + } + + /* Find out how much free trusted ram remains after BL1 load */ + mem_layout = bl1_plat_sec_mem_layout(); + if ((image_desc->image_info.image_base < mem_layout->free_base) || + (image_desc->image_info.image_base + image_size > + mem_layout->free_base + mem_layout->free_size)) { + WARN("BL1-FWU: Memory not available to copy\n"); + return -ENOMEM; + } + + /* Update the image size. */ + image_desc->image_info.image_size = image_size; + + /* Copy image for given size. */ + memcpy((void *)base_addr, (const void *)image_src, block_size); + ... + + This code fragment is executed during the 1st invocation of the image copy + operation. Both ``block_size`` and ``image_size`` are SMC arguments. A very + large value of ``image_size`` may result in an integer overflow in the 2nd + ``if`` statement, which would bypass the check, allowing execution to proceed. + If ``bl1_plat_mem_check()`` also passes, this may result in an unexpectedly + large copy of data into secure memory. + +If the platform's implementation of ``bl1_plat_mem_check()`` is correct then it +may help prevent the above 2 vulnerabilities from being exploited. However, the +ARM platform version of this function contains a similar vulnerability: + +- Line 88 of ``plat/arm/common/arm_bl1_fwu.c`` in function of + ``bl1_plat_mem_check()``: + + .. code:: c + + 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++; + } + ... + + This function checks that the passed memory region is within one of the + regions mapped in by ARM platforms. Here, ``mem_size`` may be the + ``block_size`` passed from ``bl1_fwu_image_copy()``. A very large value of + ``mem_size`` may result in an integer overflow and the function to incorrectly + return success. Platforms that copy this insecure pattern will have the same + vulnerability. + +.. _CVE-2016-10319: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-10319 +.. _48bfb88: https://github.com/ARM-software/arm-trusted-firmware/commit/48bfb88 +.. _Pull Request #783: https://github.com/ARM-software/arm-trusted-firmware/pull/783 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst new file mode 100644 index 0000000..0ed2a7f --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst @@ -0,0 +1,61 @@ +Advisory TFV-2 (CVE-2017-7564) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Enabled secure self-hosted invasive debug interface can | +| | allow normal world to panic secure world | ++================+=============================================================+ +| CVE ID | `CVE-2017-7564`_ | ++----------------+-------------------------------------------------------------+ +| Date | 02 Feb 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | All versions up to v1.3 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Denial of Service (secure world panic) | ++----------------+-------------------------------------------------------------+ +| Fix Version | 15 Feb 2017 `Pull Request #841`_ | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The ``MDCR_EL3.SDD`` bit controls AArch64 secure self-hosted invasive debug +enablement. By default, the BL1 and BL31 images of the current version of ARM +Trusted Firmware (TF) unconditionally assign this bit to ``0`` in the early +entrypoint code, which enables debug exceptions from the secure world. This can +be seen in the implementation of the ``el3_arch_init_common`` `AArch64 macro`_ . +Given that TF does not currently contain support for this feature (for example, +by saving and restoring the appropriate debug registers), this may allow a +normal world attacker to induce a panic in the secure world. + +The ``MDCR_EL3.SDD`` bit should be assigned to ``1`` to disable debug exceptions +from the secure world. + +Earlier versions of TF (prior to `commit 495f3d3`_) did not assign this bit. +Since the bit has an architecturally ``UNKNOWN`` reset value, earlier versions +may or may not have the same problem, depending on the platform. + +A similar issue applies to the ``MDCR_EL3.SPD32`` bits, which control AArch32 +secure self-hosted invasive debug enablement. TF assigns these bits to ``00`` +meaning that debug exceptions from Secure EL1 are enabled by the authentication +interface. Therefore this issue only exists for AArch32 Secure EL1 code when +secure privileged invasive debug is enabled by the authentication interface, at +which point the device is vulnerable to other, more serious attacks anyway. + +However, given that TF contains no support for handling debug exceptions, the +``MDCR_EL3.SPD32`` bits should be assigned to ``10`` to disable debug exceptions +from AArch32 Secure EL1. + +Finally, this also issue applies to AArch32 platforms that use the TF SP_MIN +image or integrate the `AArch32 equivalent`_ of the ``el3_arch_init_common`` +macro. Here the affected bits are ``SDCR.SPD``, which should also be assigned to +``10`` instead of ``00`` + +.. _CVE-2017-7564: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7564 +.. _commit 495f3d3: https://github.com/ARM-software/arm-trusted-firmware/commit/495f3d3 +.. _AArch64 macro: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch64/el3_common_macros.S#L85 +.. _AArch32 equivalent: https://github.com/ARM-software/arm-trusted-firmware/blob/bcc2bf0/include/common/aarch32/el3_common_macros.S#L41 +.. _Pull Request #841: https://github.com/ARM-software/arm-trusted-firmware/pull/841 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst new file mode 100644 index 0000000..b395f13 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst @@ -0,0 +1,86 @@ +Advisory TFV-3 (CVE-2017-7563) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | RO memory is always executable at AArch64 Secure EL1 | ++================+=============================================================+ +| CVE ID | `CVE-2017-7563`_ | ++----------------+-------------------------------------------------------------+ +| Date | 06 Apr 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | v1.3 (since `Pull Request #662`_) | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | AArch64 BL2, TSP or other users of xlat_tables library | +| Affected | executing at AArch64 Secure EL1 | ++----------------+-------------------------------------------------------------+ +| Impact | Unexpected Privilege Escalation | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #924`_ | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The translation table library in ARM Trusted Firmware (TF) (under +``lib/xlat_tables`` and ``lib/xlat_tables_v2``) provides APIs to help program +translation tables in the MMU. The xlat\_tables client specifies its required +memory mappings in the form of ``mmap_region`` structures. Each ``mmap_region`` +has memory attributes represented by the ``mmap_attr_t`` enumeration type. This +contains flags to control data access permissions (``MT_RO``/``MT_RW``) and +instruction execution permissions (``MT_EXECUTE``/``MT_EXECUTE_NEVER``). Thus a +mapping specifying both ``MT_RO`` and ``MT_EXECUTE_NEVER`` should result in a +Read-Only (RO), non-executable memory region. + +This feature does not work correctly for AArch64 images executing at Secure EL1. +Any memory region mapped as RO will always be executable, regardless of whether +the client specified ``MT_EXECUTE`` or ``MT_EXECUTE_NEVER``. + +The vulnerability is known to affect the BL2 and Test Secure Payload (TSP) +images on platforms that enable the ``SEPARATE_CODE_AND_RODATA`` build option, +which includes all ARM standard platforms, and the upstream Xilinx and NVidia +platforms. The RO data section for these images on these platforms is +unexpectedly executable instead of non-executable. Other platforms or +``xlat_tables`` clients may also be affected. + +The vulnerability primarily manifests itself after `Pull Request #662`_. Before +that, ``xlat_tables`` clients could not specify instruction execution +permissions separately to data access permissions. All RO normal memory regions +were implicitly executable. Before `Pull Request #662`_. the vulnerability +would only manifest itself for device memory mapped as RO; use of this mapping +is considered rare, although the upstream QEMU platform uses this mapping when +the ``DEVICE2_BASE`` build option is used. + +Note that one or more separate vulnerabilities are also required to exploit this +vulnerability. + +The vulnerability is due to incorrect handling of the execute-never bits in the +translation tables. The EL3 translation regime uses a single ``XN`` bit to +determine whether a region is executable. The Secure EL1&0 translation regime +handles 2 Virtual Address (VA) ranges and so uses 2 bits, ``UXN`` and ``PXN``. +The ``xlat_tables`` library only handles the ``XN`` bit, which maps to ``UXN`` +in the Secure EL1&0 regime. As a result, this programs the Secure EL0 execution +permissions but always leaves the memory as executable at Secure EL1. + +The vulnerability is mitigated by the following factors: + +- The xlat\_tables library ensures that all Read-Write (RW) memory regions are + non-executable by setting the ``SCTLR_ELx.WXN`` bit. This overrides any value + of the ``XN``, ``UXN`` or ``PXN`` bits in the translation tables. See the + ``enable_mmu()`` function: + + :: + + sctlr = read_sctlr_el##_el(); \ + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; \ + +- AArch32 configurations are unaffected. Here the ``XN`` bit controls execution + privileges of the currently executing translation regime, which is the desired + behaviour. + +- ARM TF EL3 code (for example BL1 and BL31) ensures that all non-secure memory + mapped into the secure world is non-executable by setting the ``SCR_EL3.SIF`` + bit. See the ``el3_arch_init_common`` macro in ``el3_common_macros.S``. + +.. _CVE-2017-7563: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-7563 +.. _Pull Request #662: https://github.com/ARM-software/arm-trusted-firmware/pull/662 +.. _Pull Request #924: https://github.com/ARM-software/arm-trusted-firmware/pull/924 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst new file mode 100644 index 0000000..66dd542 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst @@ -0,0 +1,124 @@ +Advisory TFV-4 (CVE-2017-9607) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Malformed Firmware Update SMC can result in copy or | +| | authentication of unexpected data in secure memory in | +| | AArch32 state | ++================+=============================================================+ +| CVE ID | `CVE-2017-9607`_ | ++----------------+-------------------------------------------------------------+ +| Date | 20 Jun 2017 | ++----------------+-------------------------------------------------------------+ +| Versions | None (only between 22 May 2017 and 14 June 2017) | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | Platforms that use AArch32 BL1 plus untrusted normal world | +| Affected | firmware update code executing before BL31 | ++----------------+-------------------------------------------------------------+ +| Impact | Copy or authentication of unexpected data in the secure | +| | memory | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #979`_ (merged on 14 June 2017) | ++----------------+-------------------------------------------------------------+ +| Credit | ARM | ++----------------+-------------------------------------------------------------+ + +The ``include/lib/utils_def.h`` header file provides the +``check_uptr_overflow()`` macro, which aims at detecting arithmetic overflows +that may occur when computing the sum of a base pointer and an offset. This +macro evaluates to 1 if the sum of the given base pointer and offset would +result in a value large enough to wrap around, which may lead to unpredictable +behaviour. + +The macro code is at line 52, referring to the version of the code as of `commit +c396b73`_: + +.. code:: c + + /* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ + #define check_uptr_overflow(ptr, inc) \ + (((ptr) > UINTPTR_MAX - (inc)) ? 1 : 0) + +This macro does not work correctly for AArch32 images. It fails to detect +overflows when the sum of its two parameters fall into the ``[2^32, 2^64 - 1]`` +range. Therefore, any AArch32 code relying on this macro to detect such integer +overflows is actually not protected. + +The buggy code has been present in ARM Trusted Firmware (TF) since `Pull Request +#678`_ was merged (on 18 August 2016). However, the upstream code was not +vulnerable until `Pull Request #939`_ was merged (on 22 May 2017), which +introduced AArch32 support for the Trusted Board Boot (TBB) feature. Before +then, the ``check_uptr_overflow()`` macro was not used in AArch32 code. + +The vulnerability resides in the BL1 FWU SMC handling code and it may be +exploited when *all* the following conditions apply: + +- Platform code uses TF BL1 with the ``TRUSTED_BOARD_BOOT`` build option. + +- Platform code uses the Firmware Update (FWU) code provided in + ``bl1/bl1_fwu.c``, which is part of the TBB support. + +- TF BL1 is compiled with the ``ARCH=aarch32`` build option. + +In this context, the AArch32 BL1 image might fail to detect potential integer +overflows in the input validation checks while handling the +``FWU_SMC_IMAGE_COPY`` and ``FWU_SMC_IMAGE_AUTH`` SMCs. + +The ``FWU_SMC_IMAGE_COPY`` SMC handler is designed to copy an image into secure +memory for subsequent authentication. This is implemented by the +``bl1_fwu_image_copy()`` function, which has the following function prototype: + +.. code:: c + + static int bl1_fwu_image_copy(unsigned int image_id, + uintptr_t image_src, + unsigned int block_size, + unsigned int image_size, + unsigned int flags) + +``image_src`` is an SMC argument and therefore potentially controllable by an +attacker. A very large 32-bit value, for example ``2^32 -1``, may result in the +sum of ``image_src`` and ``block_size`` overflowing a 32-bit type, which +``check_uptr_overflow()`` will fail to detect. Depending on its implementation, +the platform-specific function ``bl1_plat_mem_check()`` might get defeated by +these unsanitized values and allow the following memory copy operation, that +would wrap around. This may allow an attacker to copy unexpected data into +secure memory if the memory is mapped in BL1's address space, or cause a fatal +exception if it's not. + +The ``FWU_SMC_IMAGE_AUTH`` SMC handler is designed to authenticate an image +resident in secure memory. This is implemented by the ``bl1_fwu_image_auth()`` +function, which has the following function prototype: + +.. code:: c + + static int bl1_fwu_image_auth(unsigned int image_id, + uintptr_t image_src, + unsigned int image_size, + unsigned int flags) + +Similarly, if an attacker has control over the ``image_src`` or ``image_size`` +arguments through the SMC interface and injects high values whose sum overflows, +they might defeat the ``bl1_plat_mem_check()`` function and make the +authentication module read data outside of what's normally allowed by the +platform code or crash the platform. + +Note that in both cases, a separate vulnerability is required to leverage this +vulnerability; for example a way to get the system to change its behaviour based +on the unexpected secure memory accesses. Moreover, the normal world FWU code +would need to be compromised in order to send a malformed FWU SMC that triggers +an integer overflow. + +The vulnerability is known to affect all ARM standard platforms when enabling +the ``TRUSTED_BOARD_BOOT`` and ``ARCH=aarch32`` build options. Other platforms +may also be affected if they fulfil the above conditions. + +.. _CVE-2017-9607: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-9607 +.. _commit c396b73: https://github.com/ARM-software/arm-trusted-firmware/commit/c396b73 +.. _Pull Request #678: https://github.com/ARM-software/arm-trusted-firmware/pull/678 +.. _Pull Request #939: https://github.com/ARM-software/arm-trusted-firmware/pull/939 +.. _Pull Request #979: https://github.com/ARM-software/arm-trusted-firmware/pull/979 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst new file mode 100644 index 0000000..97f7cd9 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst @@ -0,0 +1,57 @@ +Advisory TFV-5 (CVE-2017-15031) +=============================== + ++----------------+-------------------------------------------------------------+ +| Title | Not initializing or saving/restoring ``PMCR_EL0`` can leak | +| | secure world timing information | ++================+=============================================================+ +| CVE ID | `CVE-2017-15031`_ | ++----------------+-------------------------------------------------------------+ +| Date | 02 Oct 2017, updated on 04 Nov 2019 | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v2.1 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of sensitive secure world timing information | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1127`_ (merged on 18 October 2017) | +| | | +| | `Commit e290a8fcbc`_ (merged on 23 August 2019) | +| | | +| | `Commit c3e8b0be9b`_ (merged on 27 September 2019) | ++----------------+-------------------------------------------------------------+ +| Credit | Arm, Marek Bykowski | ++----------------+-------------------------------------------------------------+ + +The ``PMCR_EL0`` (Performance Monitors Control Register) provides details of the +Performance Monitors implementation, including the number of counters +implemented, and configures and controls the counters. If the ``PMCR_EL0.DP`` +bit is set to zero, the cycle counter (when enabled) counts during secure world +execution, even when prohibited by the debug signals. + +Since TF-A does not save and restore ``PMCR_EL0`` when switching between the +normal and secure worlds, normal world code can set ``PMCR_EL0.DP`` to zero to +cause leakage of secure world timing information. This register should be added +to the list of saved/restored registers both when entering EL3 and also +transitioning to S-EL1. + +Furthermore, ``PMCR_EL0.DP`` has an architecturally ``UNKNOWN`` reset value. +Since Arm TF does not initialize this register, it's possible that on at least +some implementations, ``PMCR_EL0.DP`` is set to zero by default. This and other +bits with an architecturally UNKNOWN reset value should be initialized to +sensible default values in the secure context. + +The same issue exists for the equivalent AArch32 register, ``PMCR``, except that +here ``PMCR_EL0.DP`` architecturally resets to zero. + +NOTE: The original pull request referenced above only fixed the issue for S-EL1 +whereas the EL3 was fixed in the later commits. + +.. _CVE-2017-15031: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-15031 +.. _Pull Request #1127: https://github.com/ARM-software/arm-trusted-firmware/pull/1127 +.. _Commit e290a8fcbc: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=e290a8fcbc +.. _Commit c3e8b0be9b: https://git.trustedfirmware.org/TF-A/trusted-firmware-a.git/commit/?id=c3e8b0be9b + diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst new file mode 100644 index 0000000..9eeaeec --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst @@ -0,0 +1,148 @@ +Advisory TFV-6 (CVE-2017-5753, CVE-2017-5715, CVE-2017-5754) +============================================================ + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities using cache timing side-channels | ++================+=============================================================+ +| CVE ID | `CVE-2017-5753`_ / `CVE-2017-5715`_ / `CVE-2017-5754`_ | ++----------------+-------------------------------------------------------------+ +| Date | 03 Jan 2018 (Updated 11 Jan, 18 Jan, 26 Jan, 30 Jan and 07 | +| | June 2018) | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v1.4 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of secure world data to normal world | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1214`_, `Pull Request #1228`_, | +| | `Pull Request #1240`_ and `Pull Request #1405`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Google / Arm | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A exposure to the speculative processor vulnerabilities identified by +`Google Project Zero`_. To understand the background and wider impact of these +vulnerabilities on Arm systems, please refer to the `Arm Processor Security +Update`_. + +Variant 1 (`CVE-2017-5753`_) +---------------------------- + +At the time of writing, no vulnerable patterns have been observed in upstream TF +code, therefore no workarounds have been applied or are planned. + +Variant 2 (`CVE-2017-5715`_) +---------------------------- + +Where possible on vulnerable CPUs, Arm recommends invalidating the branch +predictor as early as possible on entry into the secure world, before any branch +instruction is executed. There are a number of implementation defined ways to +achieve this. + +For Cortex-A57 and Cortex-A72 CPUs, the Pull Requests (PRs) in this advisory +invalidate the branch predictor when entering EL3 by disabling and re-enabling +the MMU. + +For Cortex-A73 and Cortex-A75 CPUs, the PRs in this advisory invalidate the +branch predictor when entering EL3 by temporarily dropping into AArch32 +Secure-EL1 and executing the ``BPIALL`` instruction. This workaround is +significantly more complex than the "MMU disable/enable" workaround. The latter +is not effective at invalidating the branch predictor on Cortex-A73/Cortex-A75. + +Note that if other privileged software, for example a Rich OS kernel, implements +its own branch predictor invalidation during context switch by issuing an SMC +(to execute firmware branch predictor invalidation), then there is a dependency +on the PRs in this advisory being deployed in order for those workarounds to +work. If that other privileged software is able to workaround the vulnerability +locally (for example by implementing "MMU disable/enable" itself), there is no +such dependency. + +`Pull Request #1240`_ and `Pull Request #1405`_ optimise the earlier fixes by +implementing a specified `CVE-2017-5715`_ workaround SMC +(``SMCCC_ARCH_WORKAROUND_1``) for use by normal world privileged software. This +is more efficient than calling an arbitrary SMC (for example ``PSCI_VERSION``). +Details of ``SMCCC_ARCH_WORKAROUND_1`` can be found in the `CVE-2017-5715 +mitigation specification`_. The specification and implementation also enable +the normal world to discover the presence of this firmware service. + +On Juno R1 we measured the round trip latency for both the ``PSCI_VERSION`` and +``SMCCC_ARCH_WORKAROUND_1`` SMCs on Cortex-A57, using both the "MMU +disable/enable" and "BPIALL at AArch32 Secure-EL1" workarounds described above. +This includes the time spent in test code conforming to the SMC Calling +Convention (SMCCC) from AArch64. For the ``SMCCC_ARCH_WORKAROUND_1`` cases, the +test code uses SMCCC v1.1, which reduces the number of general purpose registers +it needs to save/restore. Although the ``BPIALL`` instruction is not effective +at invalidating the branch predictor on Cortex-A57, the drop into Secure-EL1 +with MMU disabled that this workaround entails effectively does invalidate the +branch predictor. Hence this is a reasonable comparison. + +The results were as follows: + ++------------------------------------------------------------------+-----------+ +| Test | Time (ns) | ++==================================================================+===========+ +| ``PSCI_VERSION`` baseline (without PRs in this advisory) | 515 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` baseline (with PRs in this advisory) | 527 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` with "MMU disable/enable" | 930 | ++------------------------------------------------------------------+-----------+ +| ``SMCCC_ARCH_WORKAROUND_1`` with "MMU disable/enable" | 386 | ++------------------------------------------------------------------+-----------+ +| ``PSCI_VERSION`` with "BPIALL at AArch32 Secure-EL1" | 1276 | ++------------------------------------------------------------------+-----------+ +| ``SMCCC_ARCH_WORKAROUND_1`` with "BPIALL at AArch32 Secure-EL1" | 770 | ++------------------------------------------------------------------+-----------+ + +Due to the high severity and wide applicability of this issue, the above +workarounds are enabled by default (on vulnerable CPUs only), despite some +performance and code size overhead. Platforms can choose to disable them at +compile time if they do not require them. `Pull Request #1240`_ disables the +workarounds for unaffected upstream platforms. + +For vulnerable AArch32-only CPUs (for example Cortex-A8, Cortex-A9 and +Cortex-A17), the ``BPIALL`` instruction should be used as early as possible on +entry into the secure world. For Cortex-A8, also set ``ACTLR[6]`` to 1 during +early processor initialization. Note that the ``BPIALL`` instruction is not +effective at invalidating the branch predictor on Cortex-A15. For that CPU, set +``ACTLR[0]`` to 1 during early processor initialization, and invalidate the +branch predictor by performing an ``ICIALLU`` instruction. + +On AArch32 EL3 systems, the monitor and secure-SVC code is typically tightly +integrated, for example as part of a Trusted OS. Therefore any Variant 2 +workaround should be provided by vendors of that software and is outside the +scope of TF. However, an example implementation in the minimal AArch32 Secure +Payload, ``SP_MIN`` is provided in `Pull Request #1228`_. + +Other Arm CPUs are not vulnerable to this or other variants. This includes +Cortex-A76, Cortex-A53, Cortex-A55, Cortex-A32, Cortex-A7 and Cortex-A5. + +For more information about non-Arm CPUs, please contact the CPU vendor. + +Variant 3 (`CVE-2017-5754`_) +---------------------------- + +This variant is only exploitable between Exception Levels within the same +translation regime, for example between EL0 and EL1, therefore this variant +cannot be used to access secure memory from the non-secure world, and is not +applicable for TF. However, Secure Payloads (for example, Trusted OS) should +provide mitigations on vulnerable CPUs to protect themselves from exploited +Secure-EL0 applications. + +The only Arm CPU vulnerable to this variant is Cortex-A75. + +.. _Google Project Zero: https://googleprojectzero.blogspot.co.uk/2018/01/reading-privileged-memory-with-side.html +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2017-5753: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5753 +.. _CVE-2017-5715: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5715 +.. _CVE-2017-5754: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2017-5754 +.. _Pull Request #1214: https://github.com/ARM-software/arm-trusted-firmware/pull/1214 +.. _Pull Request #1228: https://github.com/ARM-software/arm-trusted-firmware/pull/1228 +.. _Pull Request #1240: https://github.com/ARM-software/arm-trusted-firmware/pull/1240 +.. _Pull Request #1405: https://github.com/ARM-software/arm-trusted-firmware/pull/1405 +.. _CVE-2017-5715 mitigation specification: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst new file mode 100644 index 0000000..8e06762 --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst @@ -0,0 +1,107 @@ +Advisory TFV-7 (CVE-2018-3639) +============================== + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to cache speculation | +| | vulnerability Variant 4 | ++================+=============================================================+ +| CVE ID | `CVE-2018-3639`_ | ++----------------+-------------------------------------------------------------+ +| Date | 21 May 2018 (Updated 7 June 2018) | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v1.5 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of secure world data to normal world | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1392`_, `Pull Request #1397`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Google | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A (TF-A) exposure to Variant 4 of the cache speculation vulnerabilities +identified by `Google Project Zero`_. To understand the background and wider +impact of these vulnerabilities on Arm systems, please refer to the `Arm +Processor Security Update`_. + +At the time of writing, the TF-A project is not aware of a Variant 4 exploit +that could be used against TF-A. It is likely to be very difficult to achieve an +exploit against current standard configurations of TF-A, due to the limited +interfaces into the secure world with attacker-controlled inputs. However, this +is becoming increasingly difficult to guarantee with the introduction of complex +new firmware interfaces, for example the `Software Delegated Exception Interface +(SDEI)`_. Also, the TF-A project does not have visibility of all +vendor-supplied interfaces. Therefore, the TF-A project takes a conservative +approach by mitigating Variant 4 in hardware wherever possible during secure +world execution. The mitigation is enabled by setting an implementation defined +control bit to prevent the re-ordering of stores and loads. + +For each affected CPU type, TF-A implements one of the two following mitigation +approaches in `Pull Request #1392`_ and `Pull Request #1397`_. Both approaches +have a system performance impact, which varies for each CPU type and use-case. +The mitigation code is enabled by default, but can be disabled at compile time +for platforms that are unaffected or where the risk is deemed low enough. + +Arm CPUs not mentioned below are unaffected. + +Static mitigation +----------------- + +For affected CPUs, this approach enables the mitigation during EL3 +initialization, following every PE reset. No mechanism is provided to disable +the mitigation at runtime. + +This approach permanently mitigates the entire software stack and no additional +mitigation code is required in other software components. + +TF-A implements this approach for the following affected CPUs: + +- Cortex-A57 and Cortex-A72, by setting bit 55 (Disable load pass store) of + ``CPUACTLR_EL1`` (``S3_1_C15_C2_0``). + +- Cortex-A73, by setting bit 3 of ``S3_0_C15_C0_0`` (not documented in the + Technical Reference Manual (TRM)). + +- Cortex-A75, by setting bit 35 (reserved in TRM) of ``CPUACTLR_EL1`` + (``S3_0_C15_C1_0``). + +Dynamic mitigation +------------------ + +For affected CPUs, this approach also enables the mitigation during EL3 +initialization, following every PE reset. In addition, this approach implements +``SMCCC_ARCH_WORKAROUND_2`` in the Arm architectural range to allow callers at +lower exception levels to temporarily disable the mitigation in their execution +context, where the risk is deemed low enough. This approach enables mitigation +on entry to EL3, and restores the mitigation state of the lower exception level +on exit from EL3. For more information on this approach, see `Firmware +interfaces for mitigating cache speculation vulnerabilities`_. + +This approach may be complemented by additional mitigation code in other +software components, for example code that calls ``SMCCC_ARCH_WORKAROUND_2``. +However, even without any mitigation code in other software components, this +approach will effectively permanently mitigate the entire software stack, since +the default mitigation state for firmware-managed execution contexts is enabled. + +Since the expectation in this approach is that more software executes with the +mitigation disabled, this may result in better system performance than the +static approach for some systems or use-cases. However, for other systems or +use-cases, this performance saving may be outweighed by the additional overhead +of ``SMCCC_ARCH_WORKAROUND_2`` calls and TF-A exception handling. + +TF-A implements this approach for the following affected CPU: + +- Cortex-A76, by setting and clearing bit 16 (reserved in TRM) of + ``CPUACTLR2_EL1`` (``S3_0_C15_C1_1``). + +.. _Google Project Zero: https://bugs.chromium.org/p/project-zero/issues/detail?id=1528 +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2018-3639: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-3639 +.. _Software Delegated Exception Interface (SDEI): http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Firmware interfaces for mitigating cache speculation vulnerabilities: https://developer.arm.com/cache-speculation-vulnerability-firmware-specification +.. _Pull Request #1392: https://github.com/ARM-software/arm-trusted-firmware/pull/1392 +.. _Pull Request #1397: https://github.com/ARM-software/arm-trusted-firmware/pull/1397 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst new file mode 100644 index 0000000..ebe324e --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst @@ -0,0 +1,103 @@ +Advisory TFV-8 (CVE-2018-19440) +=============================== + ++----------------+-------------------------------------------------------------+ +| Title | Not saving x0 to x3 registers can leak information from one | +| | Normal World SMC client to another | ++================+=============================================================+ +| CVE ID | `CVE-2018-19440`_ | ++----------------+-------------------------------------------------------------+ +| Date | 27 Nov 2018 | ++----------------+-------------------------------------------------------------+ +| Versions | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | Multiple normal world SMC clients calling into AArch64 BL31 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Leakage of SMC return values from one normal world SMC | +| | client to another | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Pull Request #1710`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Secmation | ++----------------+-------------------------------------------------------------+ + +When taking an exception to EL3, BL31 saves the CPU context. The aim is to +restore it before returning into the lower exception level software that called +into the firmware. However, for an SMC exception, the general purpose registers +``x0`` to ``x3`` are not part of the CPU context saved on the stack. + +As per the `SMC Calling Convention`_, up to 4 values may be returned to the +caller in registers ``x0`` to ``x3``. In TF-A, these return values are written +into the CPU context, typically using one of the ``SMC_RETx()`` macros provided +in the ``include/lib/aarch64/smccc_helpers.h`` header file. + +Before returning to the caller, the ``restore_gp_registers()`` function is +called. It restores the values of all general purpose registers taken from the +CPU context stored on the stack. This includes registers ``x0`` to ``x3``, as +can be seen in the ``lib/el3_runtime/aarch64/context.S`` file at line 339 +(referring to the version of the code as of `commit c385955`_): + +:: + + /* + * This function restores all general purpose registers except x30 from the + * CPU context. x30 register must be explicitly restored by the caller. + */ + func restore_gp_registers + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + +In the case of an SMC handler that does not use all 4 return values, the +remaining ones are left unchanged in the CPU context. As a result, +``restore_gp_registers()`` restores the stale values saved by a previous SMC +request (or asynchronous exception to EL3) that used these return values. + +In the presence of multiple normal world SMC clients, this behaviour might leak +some of the return values from one client to another. For example, if a victim +client first sends an SMC that returns 4 values, a malicious client may then +send a second SMC expecting no return values (for example, a +``SDEI_EVENT_COMPLETE`` SMC) to get the 4 return values of the victim client. + +In general, the responsibility for mitigating threats due to the presence of +multiple normal world SMC clients lies with EL2 software. When present, EL2 +software must trap SMC calls from EL1 software to ensure secure behaviour. + +For this reason, TF-A does not save ``x0`` to ``x3`` in the CPU context on an +SMC synchronous exception. It has behaved this way since the first version. + +We can confirm that at least upstream KVM-based systems mitigate this threat, +and are therefore unaffected by this issue. Other EL2 software should be audited +to assess the impact of this threat. + +EL2 software might find mitigating this threat somewhat onerous, because for all +SMCs it would need to be aware of which return registers contain valid data, so +it can sanitise any unused return registers. On the other hand, mitigating this +in EL3 is relatively easy and cheap. Therefore, TF-A will now ensure that no +information is leaked through registers ``x0`` to ``x3``, by preserving the +register state over the call. + +Note that AArch32 TF-A is not affected by this issue. The SMC handling code in +``SP_MIN`` already saves all general purpose registers - including ``r0`` to +``r3``, as can be seen in the ``include/lib/aarch32/smccc_macros.S`` file at +line 19 (referring to the version of the code as of `commit c385955`_): + +.. code:: c + + /* + * Macro to save the General purpose registers (r0 - r12), the banked + * spsr, lr, sp registers and the `scr` register to the SMC context on entry + * due a SMC call. The `lr` of the current mode (monitor) is expected to be + * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. + */ + .macro smccc_save_gp_mode_regs + /* Save r0 - r12 in the SMC context */ + stm sp, {r0-r12} + +.. _CVE-2018-19440: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2018-19440 +.. _commit c385955: https://github.com/ARM-software/arm-trusted-firmware/commit/c385955 +.. _SMC Calling Convention: https://developer.arm.com/docs/den0028/latest +.. _Pull Request #1710: https://github.com/ARM-software/arm-trusted-firmware/pull/1710 diff --git a/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst new file mode 100644 index 0000000..74b85dc --- /dev/null +++ b/arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst @@ -0,0 +1,104 @@ +Advisory TFV-9 (CVE-2022-23960) +============================================================ + ++----------------+-------------------------------------------------------------+ +| Title | Trusted Firmware-A exposure to speculative processor | +| | vulnerabilities with branch prediction target reuse | ++================+=============================================================+ +| CVE ID | `CVE-2022-23960`_ | ++----------------+-------------------------------------------------------------+ +| Date | 08 Mar 2022 | ++----------------+-------------------------------------------------------------+ +| Versions | All, up to and including v2.6 | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Configurations | All | +| Affected | | ++----------------+-------------------------------------------------------------+ +| Impact | Potential leakage of secure world data to normal world | +| | if an attacker is able to find a TF-A exfiltration primitive| +| | that can be predicted as a valid branch target, and somehow | +| | induce misprediction onto that primitive. There are | +| | currently no known exploits. | ++----------------+-------------------------------------------------------------+ +| Fix Version | `Gerrit topic #spectre_bhb`_ | ++----------------+-------------------------------------------------------------+ +| Credit | Systems and Network Security Group at Vrije Universiteit | +| | Amsterdam for CVE-2022-23960, Arm for patches | ++----------------+-------------------------------------------------------------+ + +This security advisory describes the current understanding of the Trusted +Firmware-A exposure to the new speculative processor vulnerability. +To understand the background and wider impact of these vulnerabilities on Arm +systems, please refer to the `Arm Processor Security Update`_. The whitepaper +referred to below describes the Spectre attack and mitigation in more detail +including implementation specific mitigation details for all impacted Arm CPUs. + + +`CVE-2022-23960`_ +----------------- + +Where possible on vulnerable CPUs that implement FEAT_CSV2, Arm recommends +inserting a loop workaround with implementation specific number of iterations +that will discard the branch history on exception entry to a higher exception +level for the given CPU. This is done as early as possible on entry into EL3, +before any branch instruction is executed. This is sufficient to mitigate +Spectre-BHB on behalf of all secure world code, assuming that no secure world +code is under attacker control. + +The below table lists the CPUs that mitigate against this vulnerability in +TF-A using the loop workaround(all cores that implement FEAT_CSV2 except the +revisions of Cortex-A73 and Cortex-A75 that implements FEAT_CSV2). + ++----------------------+ +| Core | ++----------------------+ +| Cortex-A72(from r1p0)| ++----------------------+ +| Cortex-A76 | ++----------------------+ +| Cortex-A77 | ++----------------------+ +| Cortex-A78 | ++----------------------+ +| Cortex-X2 | ++----------------------+ +| Cortex-A710 | ++----------------------+ +| Neoverse-N1 | ++----------------------+ +| Neoverse-N2 | ++----------------------+ +| Neoverse-V1 | ++----------------------+ + +For all other cores impacted by Spectre-BHB, some of which that do not implement +FEAT_CSV2 and some that do e.g. Cortex-A73, the recommended mitigation is to +flush all branch predictions via an implementation specific route. + +In case local workaround is not feasible, the Rich OS can invoke the SMC +(``SMCCC_ARCH_WORKAROUND_3``) to apply the workaround. Refer to `SMCCC Calling +Convention specification`_ for more details. + +`Gerrit topic #spectre_bhb`_ This patchset implements the Spectre-BHB loop +workaround for CPUs mentioned in the above table. It also mitigates against +this vulnerability for Cortex-A72 CPU versions that support the CSV2 feature +(from r1p0). The patch stack also includes an implementation for a specified +`CVE-2022-23960`_ workaround SMC(``SMCCC_ARCH_WORKAROUND_3``) for use by normal +world privileged software. Details of ``SMCCC_ARCH_WORKAROUND_3`` can be found +in the `SMCCC Calling Convention specification`_. The specification and +implementation also enables the normal world to discover the presence of this +firmware service. This patch also implements ``SMCCC_ARCH_WORKAROUND_3`` for +Cortex-A57, Coxtex-A72, Cortex-A73 and Cortex-A75 using the existing workaround. +for CVE-2017-5715. + +The above workaround is enabled by default (on vulnerable CPUs only). Platforms +can choose to disable them at compile time if they do not require them. + +For more information about non-Arm CPUs, please contact the CPU vendor. + +.. _Arm Processor Security Update: http://www.arm.com/security-update +.. _CVE-2022-23960: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2022-23960 +.. _Gerrit topic #spectre_bhb: https://review.trustedfirmware.org/q/topic:"spectre_bhb"+(status:open%20OR%20status:merged) +.. _CVE-2022-23960 mitigation specification: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _SMCCC Calling Convention specification: https://developer.arm.com/documentation/den0028/latest diff --git a/arm-trusted-firmware/docs/threat_model/index.rst b/arm-trusted-firmware/docs/threat_model/index.rst new file mode 100644 index 0000000..335937e --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/index.rst @@ -0,0 +1,22 @@ +Threat Model +============ + +Threat modeling is an important part of Secure Development Lifecycle (SDL) +that helps us identify potential threats and mitigations affecting a system. + +In the next sections, we first give a description of the target of evaluation +using a data flow diagram. Then we provide a list of threats we have identified +based on the data flow diagram and potential threat mitigations. + +.. toctree:: + :maxdepth: 1 + :caption: Contents + :numbered: + + threat_model + threat_model_spm + threat_model_fvp_r + +-------------- + +*Copyright (c) 2021, Arm Limited and Contributors. All rights reserved.* diff --git a/arm-trusted-firmware/docs/threat_model/threat_model.rst b/arm-trusted-firmware/docs/threat_model/threat_model.rst new file mode 100644 index 0000000..072babc --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model.rst @@ -0,0 +1,788 @@ +Generic Threat Model +******************** + +************************ +Introduction +************************ +This document provides a generic threat model for TF-A firmware. + +.. note:: + + This threat model doesn't consider Root and Realm worlds introduced by + :ref:`Realm Management Extension (RME)`. + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the Trusted +Firmware for A-class Processors (TF-A). This includes the boot ROM (BL1), +the trusted boot firmware (BL2) and the runtime EL3 firmware (BL31) as +shown on Figure 1. Everything else on Figure 1 is outside of the scope of +the evaluation. + +TF-A can be configured in various ways. In this threat model we consider +only the most basic configuration. To that end we make the following +assumptions: + +- All TF-A images are run from either ROM or on-chip trusted SRAM. This means + TF-A is not vulnerable to an attacker that can probe or tamper with off-chip + memory. + +- Trusted boot is enabled. This means an attacker can't boot arbitrary images + that are not approved by platform providers. + +- There is no Secure-EL2. We don't consider threats that may come with + Secure-EL2 software. + +Data Flow Diagram +====================== +Figure 1 shows a high-level data flow diagram for TF-A. The diagram +shows a model of the different components of a TF-A-based system and +their interactions with TF-A. A description of each diagram element +is given on Table 1. On the diagram, the red broken lines indicate +trust boundaries. Components outside of the broken lines +are considered untrusted by TF-A. + +.. uml:: ../resources/diagrams/plantuml/tfa_dfd.puml + :caption: Figure 1: TF-A Data Flow Diagram + +.. table:: Table 1: TF-A Data Flow Diagram Description + + +-----------------+--------------------------------------------------------+ + | Diagram Element | Description | + +=================+========================================================+ + | ``DF1`` | | At boot time, images are loaded from non-volatile | + | | memory and verified by TF-A boot firmware. These | + | | images include TF-A BL2 and BL31 images, as well as | + | | other secure and non-secure images. | + +-----------------+--------------------------------------------------------+ + | ``DF2`` | | TF-A log system framework outputs debug messages | + | | over a UART interface. | + +-----------------+--------------------------------------------------------+ + | ``DF3`` | | Debug and trace IP on a platform can allow access | + | | to registers and memory of TF-A. | + +-----------------+--------------------------------------------------------+ + | ``DF4`` | | Secure world software (e.g. trusted OS) interact | + | | with TF-A through SMC call interface and/or shared | + | | memory. | + +-----------------+--------------------------------------------------------+ + | ``DF5`` | | Non-secure world software (e.g. rich OS) interact | + | | with TF-A through SMC call interface and/or shared | + | | memory. | + +-----------------+--------------------------------------------------------+ + | ``DF6`` | | This path represents the interaction between TF-A and| + | | various hardware IPs such as TrustZone controller | + | | and GIC. At boot time TF-A configures/initializes the| + | | IPs and interacts with them at runtime through | + | | interrupts and registers. | + +-----------------+--------------------------------------------------------+ + + +********************* +Threat Analysis +********************* +In this section we identify and provide assessment of potential threats to TF-A +firmware. The threats are identified for each diagram element on the +data flow diagram above. + +For each threat, we identify the *asset* that is under threat, the +*threat agent* and the *threat type*. Each threat is given a *risk rating* +that represents the impact and likelihood of that threat. We also discuss +potential mitigations. + +Assets +================== +We have identified the following assets for TF-A: + +.. table:: Table 2: TF-A Assets + + +--------------------+---------------------------------------------------+ + | Asset | Description | + +====================+===================================================+ + | ``Sensitive Data`` | | These include sensitive data that an attacker | + | | must not be able to tamper with (e.g. the Root | + | | of Trust Public Key) or see (e.g. secure logs, | + | | debugging information such as crash reports). | + +--------------------+---------------------------------------------------+ + | ``Code Execution`` | | This represents the requirement that the | + | | platform should run only TF-A code approved by | + | | the platform provider. | + +--------------------+---------------------------------------------------+ + | ``Availability`` | | This represents the requirement that TF-A | + | | services should always be available for use. | + +--------------------+---------------------------------------------------+ + +Threat Agents +===================== +To understand the attack surface, it is important to identify potential +attackers, i.e. attack entry points. The following threat agents are +in scope of this threat model. + +.. table:: Table 3: Threat Agents + + +-------------------+-------------------------------------------------------+ + | Threat Agent | Description | + +===================+=======================================================+ + | ``NSCode`` | | Malicious or faulty code running in the Non-secure | + | | world, including NS-EL0 NS-EL1 and NS-EL2 levels | + +-------------------+-------------------------------------------------------+ + | ``SecCode`` | | Malicious or faulty code running in the secure | + | | world, including S-EL0 and S-EL1 levels | + +-------------------+-------------------------------------------------------+ + | ``AppDebug`` | | Physical attacker using debug signals to access | + | | TF-A resources | + +-------------------+-------------------------------------------------------+ + | ``PhysicalAccess``| | Physical attacker having access to external device | + | | communication bus and to external flash | + | | communication bus using common hardware | + +-------------------+-------------------------------------------------------+ + +.. note:: + + In this threat model an advanced physical attacker that has the capability + to tamper with a hardware (e.g. "rewiring" a chip using a focused + ion beam (FIB) workstation or decapsulate the chip using chemicals) is + considered out-of-scope. + +Threat Types +======================== +In this threat model we categorize threats using the `STRIDE threat +analysis technique`_. In this technique a threat is categorized as one +or more of these types: ``Spoofing``, ``Tampering``, ``Repudiation``, +``Information disclosure``, ``Denial of service`` or +``Elevation of privilege``. + +Threat Risk Ratings +======================== +For each threat identified, a risk rating that ranges +from *informational* to *critical* is given based on the likelihood of the +threat occuring if a mitigation is not in place, and the impact of the +threat (i.e. how severe the consequences could be). Table 4 explains each +rating in terms of score, impact and likelihood. + +.. table:: Table 4: Rating and score as applied to impact and likelihood + + +-----------------------+-------------------------+---------------------------+ + | **Rating (Score)** | **Impact** | **Likelihood** | + +=======================+=========================+===========================+ + | ``Critical (5)`` | | Extreme impact to | | Threat is almost | + | | entire organization | certain to be exploited.| + | | if exploited. | | + | | | | Knowledge of the threat | + | | | and how to exploit it | + | | | are in the public | + | | | domain. | + +-----------------------+-------------------------+---------------------------+ + | ``High (4)`` | | Major impact to entire| | Threat is relatively | + | | organization or single| easy to detect and | + | | line of business if | exploit by an attacker | + | | exploited | with little skill. | + +-----------------------+-------------------------+---------------------------+ + | ``Medium (3)`` | | Noticeable impact to | | A knowledgeable insider | + | | line of business if | or expert attacker could| + | | exploited. | exploit the threat | + | | | without much difficulty.| + +-----------------------+-------------------------+---------------------------+ + | ``Low (2)`` | | Minor damage if | | Exploiting the threat | + | | exploited or could | would require | + | | be used in conjunction| considerable expertise | + | | with other | and resources | + | | vulnerabilities to | | + | | perform a more serious| | + | | attack | | + +-----------------------+-------------------------+---------------------------+ + | ``Informational (1)`` | | Poor programming | | Threat is not likely | + | | practice or poor | to be exploited on its | + | | design decision that | own, but may be used to | + | | may not represent an | gain information for | + | | immediate risk on its | launching another | + | | own, but may have | attack | + | | security implications | | + | | if multiplied and/or | | + | | combined with other | | + | | threats. | | + +-----------------------+-------------------------+---------------------------+ + +Aggregate risk scores are assigned to identified threats; +specifically, the impact score multiplied by the likelihood score. +For example, a threat with high likelihood and low impact would have an +aggregate risk score of eight (8); that is, four (4) for high likelihood +multiplied by two (2) for low impact. The aggregate risk score determines +the finding's overall risk level, as shown in the following table. + +.. table:: Table 5: Overall risk levels and corresponding aggregate scores + + +---------------------+-----------------------------------+ + | Overall Risk Level | Aggregate Risk Score | + | | (Impact multiplied by Likelihood) | + +=====================+===================================+ + | Critical | 20–25 | + +---------------------+-----------------------------------+ + | High | 12–19 | + +---------------------+-----------------------------------+ + | Medium | 6–11 | + +---------------------+-----------------------------------+ + | Low | 2–5 | + +---------------------+-----------------------------------+ + | Informational | 1 | + +---------------------+-----------------------------------+ + +The likelihood and impact of a threat depends on the +target environment in which TF-A is running. For example, attacks +that require physical access are unlikely in server environments while +they are more common in Internet of Things(IoT) environments. +In this threat model we consider three target environments: +``Internet of Things(IoT)``, ``Mobile`` and ``Server``. + +Threat Assessment +============================ +The following threats were identified by applying STRIDE analysis on +each diagram element of the data flow diagram. + ++------------------------+----------------------------------------------------+ +| ID | 01 | ++========================+====================================================+ +| ``Threat`` | | **An attacker can mangle firmware images to | +| | execute arbitrary code** | +| | | +| | | Some TF-A images are loaded from external | +| | storage. It is possible for an attacker to access| +| | the external flash memory and change its contents| +| | physically, through the Rich OS, or using the | +| | updating mechanism to modify the non-volatile | +| | images to execute arbitrary code. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF4, DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess, NSCode, SecCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of Privilege | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Critical (25) | Critical (25) | Critical (25) | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A implements the `Trusted Board Boot (TBB)`_ | +| | feature which prevents malicious firmware from | +| | running on the platform by authenticating all | +| | firmware images. In addition to this, the TF-A | +| | boot firmware performs extra checks on | +| | unauthenticated data, such as FIP metadata, prior| +| | to use. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 02 | ++========================+====================================================+ +| ``Threat`` | | **An attacker may attempt to boot outdated, | +| | potentially vulnerable firmware image** | +| | | +| | | When updating firmware, an attacker may attempt | +| | to rollback to an older version that has unfixed | +| | vulnerabilities. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF4, DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess, NSCode, SecCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Critical (25) | Critical (25) | Critical (25) | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A supports anti-rollback protection using | +| | non-volatile counters (NV counters) as required | +| | by `TBBR-Client specification`_. After a firmware| +| | image is validated, the image revision number | +| | taken from a certificate extension field is | +| | compared with the corresponding NV counter stored| +| | in hardware to make sure the new counter value is| +| | larger or equal to the current counter value. | +| | Platforms must implement this protection using | +| | platform specific hardware NV counters. | ++------------------------+----------------------------------------------------+ + ++------------------------+-------------------------------------------------------+ +| ID | 03 | ++========================+=======================================================+ +| ``Threat`` | | **An attacker can use Time-of-Check-Time-of-Use | +| | (TOCTOU) attack to bypass image authentication | +| | during the boot process** | +| | | +| | | Time-of-Check-Time-of-Use (TOCTOU) threats occur | +| | when the security check is produced before the time | +| | the resource is accessed. If an attacker is sitting | +| | in the middle of the off-chip images, they could | +| | change the binary containing executable code right | +| | after the integrity and authentication check has | +| | been performed. | ++------------------------+-------------------------------------------------------+ +| ``Diagram Elements`` | DF1 | ++------------------------+-------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2 | +| Components`` | | ++------------------------+-------------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+-------------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess | ++------------------------+-------------------------------------------------------+ +| ``Threat Type`` | Elevation of Privilege | ++------------------------+---------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+---------------------+-----------------+---------------+ +| ``Impact`` | N/A | Critical (5) | Critical (5) | ++------------------------+---------------------+-----------------+---------------+ +| ``Likelihood`` | N/A | Medium (3) | Medium (3) | ++------------------------+---------------------+-----------------+---------------+ +| ``Total Risk Rating`` | N/A | High (15) | High (15) | ++------------------------+---------------------+-----------------+---------------+ +| ``Mitigations`` | | TF-A boot firmware copies image to on-chip | +| | memory before authenticating an image. | ++------------------------+-------------------------------------------------------+ + ++------------------------+-------------------------------------------------------+ +| ID | 04 | ++========================+=======================================================+ +| ``Threat`` | | **An attacker with physical access can execute | +| | arbitrary image by bypassing the signature | +| | verification stage using glitching techniques** | +| | | +| | | Glitching (Fault injection) attacks attempt to put | +| | a hardware into a undefined state by manipulating an| +| | environmental variable such as power supply. | +| | | +| | | TF-A relies on a chain of trust that starts with the| +| | ROTPK, which is the key stored inside the chip and | +| | the root of all validation processes. If an attacker| +| | can break this chain of trust, they could execute | +| | arbitrary code on the device. This could be | +| | achieved with physical access to the device by | +| | attacking the normal execution flow of the | +| | process using glitching techniques that target | +| | points where the image is validated against the | +| | signature. | ++------------------------+-------------------------------------------------------+ +| ``Diagram Elements`` | DF1 | ++------------------------+-------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2 | +| Components`` | | ++------------------------+-------------------------------------------------------+ +| ``Assets`` | Code Execution | ++------------------------+-------------------------------------------------------+ +| ``Threat Agent`` | PhysicalAccess | ++------------------------+-------------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of Privilege | ++------------------------+---------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+---------------------+-----------------+---------------+ +| ``Impact`` | N/A | Critical (5) | Critical (5) | ++------------------------+---------------------+-----------------+---------------+ +| ``Likelihood`` | N/A | Medium (3) | Medium (3) | ++------------------------+---------------------+-----------------+---------------+ +| ``Total Risk Rating`` | N/A | High (15) | High (15) | ++------------------------+---------------------+-----------------+---------------+ +| ``Mitigations`` | | The most effective mitigation is adding glitching | +| | detection and mitigation circuit at the hardware | +| | level. However, software techniques, | +| | such as adding redundant checks when performing | +| | conditional branches that are security sensitive, | +| | can be used to harden TF-A against such attacks. | +| | **At the moment TF-A doesn't implement such | +| | mitigations.** | ++------------------------+-------------------------------------------------------+ + ++------------------------+---------------------------------------------------+ +| ID | 05 | ++========================+===================================================+ +| ``Threat`` | | **Information leak via UART logs such as | +| | crashes** | +| | | +| | | During the development stages of software it is | +| | common to include crash reports with detailed | +| | information of the CPU state including current | +| | values of the registers, privilege level and | +| | stack dumps. This information is useful when | +| | debugging problems before releasing the | +| | production version, but it could be used by an | +| | attacker to develop a working exploit if left | +| | in the production version. | ++------------------------+---------------------------------------------------+ +| ``Diagram Elements`` | DF2 | ++------------------------+---------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+---------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+---------------------------------------------------+ +| ``Threat Agent`` | AppDebug | ++------------------------+---------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+------------------+----------------+---------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+----------------+---------------+ +| ``Impact`` | N/A | Low (2) | Low (2) | ++------------------------+------------------+----------------+---------------+ +| ``Likelihood`` | N/A | High (4) | High (4) | ++------------------------+------------------+----------------+---------------+ +| ``Total Risk Rating`` | N/A | Medium (8) | Medium (8) | ++------------------------+------------------+----------------+---------------+ +| ``Mitigations`` | | In TF-A, crash reporting is only enabled for | +| | debug builds by default. Alternatively, the log | +| | level can be tuned at build time (from verbose | +| | to no output at all), independently of the | +| | build type. | ++------------------------+---------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 06 | ++========================+====================================================+ +| ``Threat`` | | **An attacker can read sensitive data and | +| | execute arbitrary code through the external | +| | debug and trace interface** | +| | | +| | | Arm processors include hardware-assisted debug | +| | and trace features that can be controlled without| +| | the need for software operating on the platform. | +| | If left enabled without authentication, this | +| | feature can be used by an attacker to inspect and| +| | modify TF-A registers and memory allowing the | +| | attacker to read sensitive data and execute | +| | arbitrary code. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | AppDebug | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Information Disclosure, | +| | Elevation of privilege | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | N/A | High (4) | High (4) | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | N/A | Critical (5) | Critical (5) | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | N/A | Critical (20) | Critical (20) | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | | Configuration of debug and trace capabilities is | +| | platform specific. Therefore, platforms must | +| | disable the debug and trace capability for | +| | production releases or enable proper debug | +| | authentication as recommended by [`DEN0034`_]. | ++------------------------+----------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 07 | ++========================+======================================================+ +| ``Threat`` | | **An attacker can perform a denial-of-service | +| | attack by using a broken SMC call that causes the | +| | system to reboot or enter into unknown state.** | +| | | +| | | Secure and non-secure clients access TF-A services | +| | through SMC calls. Malicious code can attempt to | +| | place the TF-A runtime into an inconsistent state | +| | by calling unimplemented SMC call or by passing | +| | invalid arguments. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Availability | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode, SecCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Denial of Service | ++------------------------+-------------------+----------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-------------------+----------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | High (12) | ++------------------------+-------------------+----------------+-----------------+ +| ``Mitigations`` | | The generic TF-A code validates SMC function ids | +| | and arguments before using them. | +| | Platforms that implement SiP services must also | +| | validate SMC call arguments. | ++------------------------+------------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 08 | ++========================+======================================================+ +| ``Threat`` | | **Memory corruption due to memory overflows and | +| | lack of boundary checking when accessing resources | +| | could allow an attacker to execute arbitrary code, | +| | modify some state variable to change the normal | +| | flow of the program, or leak sensitive | +| | information** | +| | | +| | | Like in other software, the Trusted Firmware has | +| | multiple points where memory corruption security | +| | errors can arise. Memory corruption is a dangerous | +| | security issue since it could allow an attacker | +| | to execute arbitrary code, modify some state | +| | variable to change the normal flow of the program, | +| | or leak sensitive information. | +| | | +| | | Some of the errors include integer overflow, | +| | buffer overflow, incorrect array boundary checks, | +| | and incorrect error management. | +| | Improper use of asserts instead of proper input | +| | validations might also result in these kinds of | +| | errors in release builds. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Code Execution, Sensitive Data | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode, SecCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Tampering, Information Disclosure, | +| | Elevation of Privilege | ++------------------------+-------------------+-----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+-----------------+----------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+-------------------+-----------------+----------------+ +| ``Likelihood`` | Medium (3 | Medium (3) | Medium (3) | ++------------------------+-------------------+-----------------+----------------+ +| ``Total Risk Rating`` | High (15) | High (15) | High (15) | ++------------------------+-------------------+-----------------+----------------+ +| ``Mitigations`` | | TF-A uses a combination of manual code reviews and | +| | automated program analysis and testing to detect | +| | and fix memory corruption bugs. All TF-A code | +| | including platform code go through manual code | +| | reviews. Additionally, static code analysis is | +| | performed using Coverity Scan on all TF-A code. | +| | The code is also tested with | +| | `Trusted Firmware-A Tests`_ on Juno and FVP | +| | platforms. | +| | | +| | | Data received from normal world, such as addresses | +| | and sizes identifying memory regions, are | +| | sanitized before being used. These security checks | +| | make sure that the normal world software does not | +| | access memory beyond its limit. | +| | | +| | | By default *asserts* are only used to check for | +| | programming errors in debug builds. Other types of | +| | errors are handled through condition checks that | +| | remain enabled in release builds. See | +| | `TF-A error handling policy`_. TF-A provides an | +| | option to use *asserts* in release builds, however | +| | we recommend using proper runtime checks instead | +| | of relying on asserts in release builds. | ++------------------------+------------------------------------------------------+ + ++------------------------+------------------------------------------------------+ +| ID | 09 | ++========================+======================================================+ +| ``Threat`` | | **Improperly handled SMC calls can leak register | +| | contents** | +| | | +| | | When switching between secure and non-secure | +| | states, register contents of Secure world or | +| | register contents of other normal world clients | +| | can be leaked. | ++------------------------+------------------------------------------------------+ +| ``Diagram Elements`` | DF5 | ++------------------------+------------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+------------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+------------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+------------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+-----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-------------------+----------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | High (12) | ++------------------------+-------------------+----------------+-----------------+ +| ``Mitigations`` | | TF-A saves and restores registers | +| | by default when switching contexts. Build options | +| | are also provided to save/restore additional | +| | registers such as floating-point registers. | ++------------------------+------------------------------------------------------+ + ++------------------------+-----------------------------------------------------+ +| ID | 10 | ++========================+=====================================================+ +| ``Threat`` | | **SMC calls can leak sensitive information from | +| | TF-A memory via microarchitectural side channels**| +| | | +| | | Microarchitectural side-channel attacks such as | +| | `Spectre`_ can be used to leak data across | +| | security boundaries. An attacker might attempt to | +| | use this kind of attack to leak sensitive | +| | data from TF-A memory. | ++------------------------+-----------------------------------------------------+ +| ``Diagram Elements`` | DF4, DF5 | ++------------------------+-----------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+-----------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+-----------------------------------------------------+ +| ``Threat Agent`` | SecCode, NSCode | ++------------------------+-----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-------------------+----------------+----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Total Risk Rating`` | Medium (9) | Medium (9) | Medium (9) | ++------------------------+-------------------+----------------+----------------+ +| ``Mitigations`` | | TF-A implements software mitigations for Spectre | +| | type attacks as recommended by `Cache Speculation | +| | Side-channels`_ for the generic code. SiPs should | +| | implement similar mitigations for code that is | +| | deemed to be vulnerable to such attacks. | ++------------------------+-----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 11 | ++========================+====================================================+ +| ``Threat`` | | **Misconfiguration of the Memory Management Unit | +| | (MMU) may allow a normal world software to | +| | access sensitive data or execute arbitrary | +| | code** | +| | | +| | | A misconfiguration of the MMU could | +| | lead to an open door for software running in the | +| | normal world to access sensitive data or even | +| | execute code if the proper security mechanisms | +| | are not in place. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF5, DF6 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | BL1, BL2, BL31 | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Sensitive Data, Code execution | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure, Elevation of Privilege | ++------------------------+-----------------+-----------------+----------------+ +| ``Application`` | ``Server`` | ``IoT`` | ``Mobile`` | ++------------------------+-----------------+-----------------+----------------+ +| ``Impact`` | Critical (5) | Critical (5) | Critical (5) | ++------------------------+-----------------+-----------------+----------------+ +| ``Likelihood`` | High (4) | High (4) | High (4) | ++------------------------+-----------------+-----------------+----------------+ +| ``Total Risk Rating`` | Critical (20) | Critical (20) | Critical (20) | ++------------------------+-----------------+-----------------+----------------+ +| ``Mitigations`` | | In TF-A, configuration of the MMU is done | +| | through a translation tables library. The | +| | library provides APIs to define memory regions | +| | and assign attributes including memory types and | +| | access permissions. Memory configurations are | +| | platform specific, therefore platforms need make | +| | sure the correct attributes are assigned to | +| | memory regions. When assigning access | +| | permissions, principle of least privilege ought | +| | to be enforced, i.e. we should not grant more | +| | privileges than strictly needed, e.g. code | +| | should be read-only executable, RO data should | +| | be read-only XN, and so on. | ++------------------------+----------------------------------------------------+ + ++------------------------+-----------------------------------------------------+ +| ID | 12 | ++========================+=====================================================+ +| ``Threat`` | | **Incorrect configuration of Performance Monitor | +| | Unit (PMU) counters can allow an attacker to | +| | mount side-channel attacks using information | +| | exposed by the counters** | +| | | +| | | Non-secure software can configure PMU registers | +| | to count events at any exception level and in | +| | both Secure and Non-secure states. This allows | +| | a Non-secure software (or a lower-level Secure | +| | software) to potentially carry out | +| | side-channel timing attacks against TF-A. | ++------------------------+-----------------------------------------------------+ +| ``Diagram Elements`` | DF5, DF6 | ++------------------------+-----------------------------------------------------+ +| ``Affected TF-A | BL31 | +| Components`` | | ++------------------------+-----------------------------------------------------+ +| ``Assets`` | Sensitive Data | ++------------------------+-----------------------------------------------------+ +| ``Threat Agent`` | NSCode | ++------------------------+-----------------------------------------------------+ +| ``Threat Type`` | Information Disclosure | ++------------------------+-------------------+----------------+----------------+ +| ``Impact`` | Medium (3) | Medium (3) | Medium (3) | ++------------------------+-------------------+----------------+----------------+ +| ``Likelihood`` | Low (2) | Low (2) | Low (2) | ++------------------------+-------------------+----------------+----------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | Medium (6) | ++------------------------+-------------------+----------------+----------------+ +| ``Mitigations`` | | TF-A follows mitigation strategies as described | +| | in `Secure Development Guidelines`_. General | +| | events and cycle counting in the Secure world is | +| | prohibited by default when applicable. However, | +| | on some implementations (e.g. PMUv3) Secure world | +| | event counting depends on external debug interface| +| | signals, i.e. Secure world event counting is | +| | enabled if external debug is enabled. | +| | Configuration of debug signals is platform | +| | specific, therefore platforms need to make sure | +| | that external debug is disabled in production or | +| | proper debug authentication is in place. | ++------------------------+-----------------------------------------------------+ + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + + +.. _STRIDE threat analysis technique: https://docs.microsoft.com/en-us/azure/security/develop/threat-modeling-tool-threats#stride-model +.. _DEN0034: https://developer.arm.com/documentation/den0034/latest +.. _Cache Speculation Side-channels: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _Spectre: https://developer.arm.com/support/arm-security-updates/speculative-processor-vulnerability +.. _TBBR-Client specification: https://developer.arm.com/documentation/den0006/d/ +.. _Trusted Board Boot (TBB): https://trustedfirmware-a.readthedocs.io/en/latest/design/trusted-board-boot.html +.. _TF-A error handling policy: https://trustedfirmware-a.readthedocs.io/en/latest/process/coding-guidelines.html#error-handling-and-robustness +.. _Secure Development Guidelines: https://trustedfirmware-a.readthedocs.io/en/latest/process/security-hardening.html#secure-development-guidelines +.. _Trusted Firmware-A Tests: https://git.trustedfirmware.org/TF-A/tf-a-tests.git/about/ diff --git a/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst b/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst new file mode 100644 index 0000000..c1462bb --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst @@ -0,0 +1,97 @@ +fvp_r-Platform Threat Model +*************************** + +************************ +Introduction +************************ +This document provides a threat model for TF-A fvp_r platform. + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the fvp_r platform of Trusted +Firmware for A-class Processors (TF-A). The fvp_r platform provides limited +support of AArch64 R-class Processors (v8-R64). + +This is a delta document, only pointing out differences from the general TF-A +threat-model document, :ref:`Generic Threat Model` + +BL1 Only +======== +The most fundamental difference between the threat model for the current fvp_r +implementation compared to the general TF-A threat model, is that fvp_r is +currently limited to BL1 only. Any threats from the general TF-A threat model +unrelated to BL1 are therefore not relevant to the fvp_r implementation. + +The fvp_r BL1 implementation directly loads a customer/partner-defined runtime +system. The threat model for that runtime system, being partner-defined, is +out-of-scope for this threat-model. + +Relatedly, all exceptions, synchronous and asynchronous, are disabled during BL1 +execution. So, any references to exceptions are not relevant. + +EL3 is Unsupported and All Secure +================================= +v8-R64 cores do not support EL3, and (essentially) all operation is defined as +Secure-mode. Therefore: + + - Any threats regarding NS operation are not relevant. + + - Any mentions of SMCs are also not relevant. + + - Anything otherwise-relevant code running in EL3 is instead run in EL2. + +MPU instead of MMU +================== +v8-R64 cores, running in EL2, use an MPU for memory management, rather than an +MMU. The MPU in the fvp_r implementation is configured to function effectively +identically with the MMU for the usual BL1 implementation. There are +memory-map differences, but the MPU configuration is functionally equivalent. + +No AArch32 Support +================== +Another substantial difference between v8-A and v8-R64 cores is that v8-R64 does +not support AArch32. However, this is not believed to have any threat-modeling +ramifications. + + +Threat Assessment +================= +For this section, please reference the Threat Assessment under the general TF-A +threat-model document, :ref:`Generic Threat Model` + +The following threats from that document are still relevant to the fvp_r +implementation: + + - ID 01: An attacker can mangle firmware images to execute arbitrary code. + + - ID 03: An attacker can use Time-of-Check-Time-of-Use (TOCTOU) attack to + bypass image authentication during the boot process. + + - ID 04: An attacker with physical access can execute arbitrary image by + bypassing the signature verification stage using clock- or power-glitching + techniques. + + - ID 05: Information leak via UART logs such as crashes + + - ID 06: An attacker can read sensitive data and execute arbitrary code + through the external debug and trace interface. + + - ID 08: Memory corruption due to memory overflows and lack of boundary + checking when accessing resources could allow an attacker to execute + arbitrary code, modify some state variable to change the normal flow of + the program, or leak sensitive. + + - ID 11: Misconfiguration of the Memory Protection Unit (MPU) may allow + normal world software to access sensitive data or execute arbitrary code. + Arguably, MPUs having fewer memory regions, there may be a temptation to + share memory regions, making this a greater threat. However, since the + fvp_r implementation is limited to BL1, since BL1's regions are fixed, + and since the MPU configuration is equivalent with that for the fvp + platform and others, this is not expected to be a concern. + + + +-------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* diff --git a/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst b/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst new file mode 100644 index 0000000..a7bc2a9 --- /dev/null +++ b/arm-trusted-firmware/docs/threat_model/threat_model_spm.rst @@ -0,0 +1,892 @@ +SPMC Threat Model +***************** + +************************ +Introduction +************************ +This document provides a threat model for the TF-A `Secure Partition Manager`_ +(SPM) implementation or more generally the S-EL2 reference firmware running on +systems implementing the FEAT_SEL2 (formerly Armv8.4 Secure EL2) architecture +extension. The SPM implementation is based on the `Arm Firmware Framework for +Arm A-profile`_ specification. + +In brief, the broad FF-A specification and S-EL2 firmware implementation +provide: + +- Isolation of mutually mistrusting SW components, or endpoints in the FF-A + terminology. +- Distinct sandboxes in the secure world called secure partitions. This permits + isolation of services from multiple vendors. +- A standard protocol for communication and memory sharing between FF-A + endpoints. +- Mutual isolation of the normal world and the secure world (e.g. a Trusted OS + is prevented to map an arbitrary NS physical memory region such as the kernel + or the Hypervisor). + +************************ +Target of Evaluation +************************ +In this threat model, the target of evaluation is the S-EL2 firmware or the +``Secure Partition Manager Core`` component (SPMC). +The monitor and SPMD at EL3 are covered by the `Generic TF-A threat model`_. + +The scope for this threat model is: + +- The TF-A implementation for the S-EL2 SPMC based on the Hafnium hypervisor + running in the secure world of TrustZone (at S-EL2 exception level). + The threat model is not related to the normal world Hypervisor or VMs. + The S-EL1 SPMC solution is not covered. +- The implementation complies with the FF-A v1.0 specification, and a few + features of FF-A v1.1 specification. +- Secure partitions are statically provisioned at boot time. +- Focus on the run-time part of the life-cycle (no specific emphasis on boot + time, factory firmware provisioning, firmware udpate etc.) +- Not covering advanced or invasive physical attacks such as decapsulation, + FIB etc. +- Assumes secure boot or in particular TF-A trusted boot (TBBR or dual CoT) is + enabled. An attacker cannot boot arbitrary images that are not approved by the + SiP or platform providers. + +Data Flow Diagram +====================== +Figure 1 shows a high-level data flow diagram for the SPM split into an SPMD +component at EL3 and an SPMC component at S-EL2. The SPMD mostly acts as a +relayer/pass-through between the normal world and the secure world. It is +assumed to expose small attack surface. + +A description of each diagram element is given in Table 1. In the diagram, the +red broken lines indicate trust boundaries. + +Components outside of the broken lines are considered untrusted. + +.. uml:: ../resources/diagrams/plantuml/spm_dfd.puml + :caption: Figure 1: SPMC Data Flow Diagram + +.. table:: Table 1: SPMC Data Flow Diagram Description + + +---------------------+--------------------------------------------------------+ + | Diagram Element | Description | + +=====================+========================================================+ + | ``DF1`` | SP to SPMC communication. FF-A function invocation or | + | | implementation-defined Hypervisor call. | + +---------------------+--------------------------------------------------------+ + | ``DF2`` | SPMC to SPMD FF-A call. | + +---------------------+--------------------------------------------------------+ + | ``DF3`` | SPMD to NS forwarding. | + +---------------------+--------------------------------------------------------+ + | ``DF4`` | SP to SP FF-A direct message request/response. | + | | Note as a matter of simplifying the diagram | + | | the SP to SP communication happens through the SPMC | + | | (SP1 performs a direct message request to the | + | | SPMC targeting SP2 as destination. And similarly for | + | | the direct message response from SP2 to SP1). | + +---------------------+--------------------------------------------------------+ + | ``DF5`` | HW control. | + +---------------------+--------------------------------------------------------+ + | ``DF6`` | Bootloader image loading. | + +---------------------+--------------------------------------------------------+ + | ``DF7`` | External memory access. | + +---------------------+--------------------------------------------------------+ + +********************* +Threat Analysis +********************* + +This threat model follows a similar methodology to the `Generic TF-A threat model`_. +The following sections define: + +- Trust boundaries +- Assets +- Theat agents +- Threat types + +Trust boundaries +============================ + +- Normal world is untrusted. +- Secure world and normal world are separate trust boundaries. +- EL3 monitor, SPMD and SPMC are trusted. +- Bootloaders (in particular BL1/BL2 if using TF-A) and run-time BL31 are + implicitely trusted by the usage of secure boot. +- EL3 monitor, SPMD, SPMC do not trust SPs. + +.. figure:: ../resources/diagrams/spm-threat-model-trust-boundaries.png + + Figure 2: Trust boundaries + +Assets +============================ + +The following assets are identified: + +- SPMC state. +- SP state. +- Information exchange between endpoints (partition messages). +- SPMC secrets (e.g. pointer authentication key when enabled) +- SP secrets (e.g. application keys). +- Scheduling cycles. +- Shared memory. + +Threat Agents +============================ + +The following threat agents are identified: + +- NS-Endpoint identifies a non-secure endpoint: normal world client at NS-EL2 + (Hypervisor) or NS-EL1 (VM or OS kernel). +- S-Endpoint identifies a secure endpoint typically a secure partition. +- Hardware attacks (non-invasive) requiring a physical access to the device, + such as bus probing or DRAM stress. + +Threat types +============================ + +The following threat categories as exposed in the `Generic TF-A threat model`_ +are re-used: + +- Spoofing +- Tampering +- Repudiation +- Information disclosure +- Denial of service +- Elevation of privileges + +Similarly this threat model re-uses the same threat risk ratings. The risk +analysis is evaluated based on the environment being ``Server`` or ``Mobile``. + +Threat Assessment +============================ + +The following threats are identified by applying STRIDE analysis on each diagram +element of the data flow diagram. + ++------------------------+----------------------------------------------------+ +| ID | 01 | ++========================+====================================================+ +| ``Threat`` | **An endpoint impersonates the sender or receiver | +| | FF-A ID in a direct request/response invocation.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------++----------------+---------------+ +| ``Impact`` | Critical(5) | Critical(5) | | ++------------------------+------------------++----------------+---------------+ +| ``Likelihood`` | Critical(5) | Critical(5) | | ++------------------------+------------------++----------------+---------------+ +| ``Total Risk Rating`` | Critical(25) | Critical(25) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | The guidance below is left for a system integrator | +| | to implemented as necessary. | +| | The SPMC must enforce checks in the direct message | +| | request/response interfaces such an endpoint cannot| +| | spoof the origin and destination worlds (e.g. a NWd| +| | originated message directed to the SWd cannot use a| +| | SWd ID as the sender ID). | +| | Additionally a software component residing in the | +| | SPMC can be added for the purpose of direct | +| | request/response filtering. | +| | It can be configured with the list of known IDs | +| | and about which interaction can occur between one | +| | and another endpoint (e.g. which NWd endpoint ID | +| | sends a direct request to which SWd endpoint ID). | +| | This component checks the sender/receiver fields | +| | for a legitimate communication between endpoints. | +| | A similar component can exist in the OS kernel | +| | driver, or Hypervisor although it remains untrusted| +| | by the SPMD/SPMC. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 02 | ++========================+====================================================+ +| ``Threat`` | **Tampering with memory shared between an endpoint | +| | and the SPMC.** | +| | A malicious endpoint may attempt tampering with its| +| | RX/TX buffer contents while the SPMC is processing | +| | it (TOCTOU). | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF3, DF4, DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Shared memory, Information exchange | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | High (16) | High (16) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | In context of FF-A v1.0 this is the case of sharing| +| | the RX/TX buffer pair and usage in the | +| | PARTITION_INFO_GET or mem sharing primitives. | +| | The SPMC must copy the contents of the TX buffer | +| | to an internal temporary buffer before processing | +| | its contents. The SPMC must implement hardened | +| | input validation on data transmitted through the TX| +| | buffer by an untrusted endpoint. | +| | The TF-A SPMC mitigates this threat by enforcing | +| | checks on data transmitted through RX/TX buffers. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 03 | ++========================+====================================================+ +| ``Threat`` | **An endpoint may tamper with its own state or the | +| | state of another endpoint.** | +| | A malicious endpoint may attempt violating: | +| | - its own or another SP state by using an unusual | +| | combination (or out-of-order) FF-A function | +| | invocations. | +| | This can also be an endpoint emitting | +| | FF-A function invocations to another endpoint while| +| | the latter in not in a state to receive it (e.g. a | +| | SP sends a direct request to the normal world early| +| | while the normal world is not booted yet). | +| | - the SPMC state itself by employing unexpected | +| | transitions in FF-A memory sharing, direct requests| +| | and responses, or handling of interrupts. | +| | This can be led by random stimuli injection or | +| | fuzzing. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP state, SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The SPMC may be vulnerable to invalid state | +| | transitions for itself or while handling an SP | +| | state. The FF-A v1.1 specification provides a | +| | guidance on those state transitions (run-time | +| | model). The TF-A SPMC will be hardened in future | +| | releases to follow this guidance. | +| | Additionally The TF-A SPMC mitigates the threat by | +| | runs of the Arm `FF-A ACS`_ compliance test suite. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 04 | ++========================+====================================================+ +| ``Threat`` | *An attacker may attempt injecting errors by the | +| | use of external DRAM stress techniques.** | +| | A malicious agent may attempt toggling an SP | +| | Stage-2 MMU descriptor bit within the page tables | +| | that the SPMC manages. This can happen in Rowhammer| +| | types of attack. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP or SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | Hardware attack | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Low (2) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | Medium (8) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | The TF-A SPMC does not provide mitigations to this | +| | type of attack. It can be addressed by the use of | +| | dedicated HW circuity or hardening at the chipset | +| | or platform level left to the integrator. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 05 | ++========================+====================================================+ +| ``Threat`` | **Protection of the SPMC from a DMA capable device | +| | upstream to an SMMU.** | +| | A device may attempt to tamper with the internal | +| | SPMC code/data sections. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF5 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC or SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Elevation of privileges | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | A platform may prefer assigning boot time, | +| | statically alocated memory regions through the SMMU| +| | configuration and page tables. The FF-A v1.1 | +| | specification provisions this capability through | +| | static DMA isolation. | +| | The TF-A SPMC does not mitigate this threat. | +| | It will adopt the static DMA isolation approach in | +| | a future release. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 06 | ++========================+====================================================+ +| ``Threat`` | **Replay fragments of past communication between | +| | endpoints.** | +| | A malicious endpoint may replay a message exchange | +| | that occured between two legitimate endpoint as | +| | a matter of triggering a malfunction or extracting | +| | secrets from the receiving endpoint. In particular | +| | the memory sharing operation with fragmented | +| | messages between an endpoint and the SPMC may be | +| | replayed by a malicious agent as a matter of | +| | getting access or gaining permissions to a memory | +| | region which does not belong to this agent. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | Information exchange | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Repdudiation | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 07 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to extract data | +| | or state information by the use of invalid or | +| | incorrect input arguments.** | +| | Lack of input parameter validation or side effects | +| | of maliciously forged input parameters might affect| +| | the SPMC. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMD, SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP secrets, SPMC secrets, SP state, SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information discolure | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | High (4) | High (4) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | High (12) | High (12) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | Secure Partitions must follow security standards | +| | and best practises as a way to mitigate the risk | +| | of common vulnerabilities to be exploited. | +| | The use of software (canaries) or hardware | +| | hardening techniques (XN, WXN, BTI, pointer | +| | authentication, MTE) helps detecting and stopping | +| | an exploitation early. | +| | The TF-A SPMC mitigates this threat by implementing| +| | stack protector, pointer authentication, BTI, XN, | +| | WXN, security hardening techniques. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 08 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may forge a direct message | +| | request such that it reveals the internal state of | +| | another endpoint through the direct message | +| | response.** | +| | The secure partition or SPMC replies to a partition| +| | message by a direct message response with | +| | information which may reveal its internal state | +| | (.e.g. partition message response outside of | +| | allowed bounds). | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC or SP state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information discolure | ++------------------------+------------------+---------------+-----------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+---------------+-----------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+---------------+-----------------+ +| ``Likelihood`` | Low (2) | Low (2) | | ++------------------------+------------------+---------------+-----------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | | ++------------------------+------------------+---------------+-----------------+ +| ``Mitigations`` | For the specific case of direct requests targeting | +| | the SPMC, the latter is hardened to prevent | +| | its internal state or the state of an SP to be | +| | revealed through a direct message response. | +| | Further FF-A v1.1 guidance about run time models | +| | and partition states will be implemented in future | +| | TF-A SPMC releases. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 09 | ++========================+====================================================+ +| ``Threat`` | **Probing the FF-A communication between | +| | endpoints.** | +| | SPMC and SPs are typically loaded to external | +| | memory (protected by a TrustZone memory | +| | controller). A malicious agent may use non invasive| +| | methods to probe the external memory bus and | +| | extract the traffic between an SP and the SPMC or | +| | among SPs when shared buffers are held in external | +| | memory. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP/SPMC state, SP/SPMC secrets | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | Hardware attack | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low (2) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | It is expected the platform or chipset provides | +| | guarantees in protecting the DRAM contents. | +| | The TF-A SPMC does not mitigate this class of | +| | attack and this is left to the integrator. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 10 | ++========================+====================================================+ +| ``Threat`` | **A malicious agent may attempt revealing the SPMC | +| | state or secrets by the use of software-based cache| +| | side-channel attack techniques.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF7 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SP or SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low (2) | Low (2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (6) | Medium (6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | From an integration perspective it is assumed | +| | platforms consuming the SPMC component at S-EL2 | +| | (hence implementing the Armv8.4 FEAT_SEL2 | +| | architecture extension) implement mitigations to | +| | Spectre, Meltdown or other cache timing | +| | side-channel type of attacks. | +| | The TF-A SPMC implements one mitigation (barrier | +| | preventing speculation past exeception returns). | +| | The SPMC may be hardened further with SW | +| | mitigations (e.g. speculation barriers) for the | +| | cases not covered in HW. Usage of hardened | +| | compilers and appropriate options, code inspection | +| | are recommended ways to mitigate Spectre types of | +| | attacks. For non-hardened cores, the usage of | +| | techniques such a kernel page table isolation can | +| | help mitigating Meltdown type of attacks. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 11 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt flooding the | +| | SPMC with requests targeting a service within an | +| | endpoint such that it denies another endpoint to | +| | access this service.** | +| | Similarly, the malicious endpoint may target a | +| | a service within an endpoint such that the latter | +| | is unable to request services from another | +| | endpoint. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Denial of service | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium (3) | Medium (3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium (9) | Medium (9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | Bounding the time for operations to complete can | +| | be achieved by the usage of a trusted watchdog. | +| | Other quality of service monitoring can be achieved| +| | in the SPMC such as counting a number of operations| +| | in a limited timeframe. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 12 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to allocate | +| | notifications bitmaps in the SPMC, through the | +| | FFA_NOTIFICATION_BITMAP_CREATE.** | +| | This might be an attempt to exhaust SPMC's memory, | +| | or to allocate a bitmap for a VM that was not | +| | intended to receive notifications from SPs. Thus | +| | creating the possibility for a channel that was not| +| | meant to exist. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Denial of service, Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(9) | Medium(9) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this threat by defining a | +| | a fixed size pool for bitmap allocation. | +| | It also limits the designated FF-A calls to be used| +| | from NWd endpoints. | +| | In the NWd the hypervisor is supposed to limit the | +| | access to the designated FF-A call. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 13 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint may attempt to destroy the | +| | notifications bitmaps in the SPMC, through the | +| | FFA_NOTIFICATION_BITMAP_DESTROY.** | +| | This might be an attempt to tamper with the SPMC | +| | state such that a partition isn't able to receive | +| | notifications. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(4) | Low(4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this issue by limiting the | +| | designated FF-A call to be issued by the NWd. | +| | Also, the notifications bitmap can't be destroyed | +| | if there are pending notifications. | +| | In the NWd, the hypervisor must restrict the | +| | NS-endpoints that can issue the designated call. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 14 | ++========================+====================================================+ +| ``Threat`` | **A malicious endpoint might attempt to give | +| | permissions to an unintended sender to set | +| | notifications targeting another receiver using the | +| | FF-A call FFA_NOTIFICATION_BIND.** | +| | This might be an attempt to tamper with the SPMC | +| | state such that an unintended, and possibly | +| | malicious, communication channel is established. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Tampering, Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by restricting | +| | designated FFA_NOTIFICATION_BIND call to be issued | +| | by the receiver only. The receiver is responsible | +| | for allocating the notifications IDs to one | +| | specific partition. | +| | Also, receivers that are not meant to receive | +| | notifications, must have notifications receipt | +| | disabled in the respective partition's manifest. | +| | As for calls coming from NWd, if the NWd VM has had| +| | its bitmap allocated at initialization, the TF-A | +| | SPMC can't guarantee this threat won't happen. | +| | The Hypervisor must mitigate in the NWd, similarly | +| | to SPMC for calls in SWd. Though, if the Hypervisor| +| | has been compromised, the SPMC won't be able to | +| | mitigate it for calls forwarded from NWd. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 15 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | set notifications that are not bound to it.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(4) | Low(4) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by checking the | +| | sender's ID provided in the input to the call | +| | FFA_NOTIFICATION_SET. The SPMC keeps track of which| +| | notifications are bound to which sender, for a | +| | given receiver. If the sender is an SP, the | +| | provided sender ID must match the ID of the | +| | currently running partition. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 16 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | get notifications that are not targeted to it.** | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Spoofing | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Informational(1) | Informational(1)| | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by checking the | +| | receiver's ID provided in the input to the call | +| | FFA_NOTIFICATION_GET. The SPMC keeps track of which| +| | notifications are pending for each receiver. | +| | The provided receiver ID must match the ID of the | +| | currently running partition, if it is an SP. | +| | For calls forwarded from NWd, the SPMC will return | +| | the pending notifications if the receiver had its | +| | bitmap created, and has pending notifications. | +| | If Hypervisor or OS kernel are compromised, the | +| | SPMC won't be able to mitigate calls from rogue NWd| +| | endpoints. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 17 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | get the information about pending notifications, | +| | through the FFA_NOTIFICATION_INFO_GET call.** | +| | This call is meant to be used by the NWd FF-A | +| | driver. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | Information disclosure | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC mitigates this by returning error to | +| | calls made by SPs to FFA_NOTIFICATION_INFO_GET. | +| | If Hypervisor or OS kernel are compromised, the | +| | SPMC won't be able mitigate calls from rogue NWd | +| | endpoints. | ++------------------------+----------------------------------------------------+ + ++------------------------+----------------------------------------------------+ +| ID | 18 | ++========================+====================================================+ +| ``Threat`` | **A malicious partition endpoint might attempt to | +| | flood another partition endpoint with notifications| +| | hindering its operation.** | +| | The intent of the malicious endpoint could be to | +| | interfere with both the receiver's and/or primary | +| | endpoint execution, as they can both be preempted | +| | by the NPI and SRI, respectively. | ++------------------------+----------------------------------------------------+ +| ``Diagram Elements`` | DF1, DF2, DF3, DF4 | ++------------------------+----------------------------------------------------+ +| ``Affected TF-A | SPMC | +| Components`` | | ++------------------------+----------------------------------------------------+ +| ``Assets`` | SPMC state, SP state, CPU cycles | ++------------------------+----------------------------------------------------+ +| ``Threat Agent`` | NS-Endpoint, S-Endpoint | ++------------------------+----------------------------------------------------+ +| ``Threat Type`` | DoS | ++------------------------+------------------+-----------------+---------------+ +| ``Application`` | ``Server`` | ``Mobile`` | | ++------------------------+------------------+-----------------+---------------+ +| ``Impact`` | Low(2) | Low(2) | | ++------------------------+------------------+-----------------+---------------+ +| ``Likelihood`` | Medium(3) | Medium(3) | | ++------------------------+------------------+-----------------+---------------+ +| ``Total Risk Rating`` | Medium(6) | Medium(6) | | ++------------------------+------------------+-----------------+---------------+ +| ``Mitigations`` | The TF-A SPMC does not mitigate this threat. | +| | However, the impact is limited due to the | +| | architecture: | +| | - Notifications are not queued, one that has been | +| | signaled needs to be retrieved by the receiver, | +| | until it can be sent again. | +| | - Both SRI and NPI can't be pended until handled | +| | which limits the amount of spurious interrupts. | +| | - A given receiver could only bind a maximum number| +| | of notifications to a given sender, within a given | +| | execution context. | ++------------------------+----------------------------------------------------+ + +--------------- + +*Copyright (c) 2021, Arm Limited. All rights reserved.* + +.. _Arm Firmware Framework for Arm A-profile: https://developer.arm.com/docs/den0077/latest +.. _Secure Partition Manager: ../components/secure-partition-manager.html +.. _Generic TF-A threat model: ./threat_model.html#threat-analysis +.. _FF-A ACS: https://github.com/ARM-software/ff-a-acs/releases diff --git a/arm-trusted-firmware/drivers/allwinner/axp/axp803.c b/arm-trusted-firmware/drivers/allwinner/axp/axp803.c new file mode 100644 index 0000000..19a9549 --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/axp803.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const uint8_t axp_chip_id = AXP803_CHIP_ID; +const char *const axp_compatible = "x-powers,axp803"; + +#if SUNXI_SETUP_REGULATORS == 1 +const struct axp_regulator axp_regulators[] = { + {"aldo1", 700, 3300, 100, NA, 0x28, 0x13, 5}, + {"dcdc1", 1600, 3400, 100, NA, 0x20, 0x10, 0}, + {"dcdc5", 800, 1840, 10, 32, 0x24, 0x10, 4}, + {"dcdc6", 600, 1520, 10, 50, 0x25, 0x10, 5}, + {"dldo1", 700, 3300, 100, NA, 0x15, 0x12, 3}, + {"dldo2", 700, 4200, 100, 27, 0x16, 0x12, 4}, + {"dldo3", 700, 3300, 100, NA, 0x17, 0x12, 5}, + {"dldo4", 700, 3300, 100, NA, 0x18, 0x12, 6}, + {"fldo1", 700, 1450, 50, NA, 0x1c, 0x13, 2}, + {} +}; +#endif diff --git a/arm-trusted-firmware/drivers/allwinner/axp/axp805.c b/arm-trusted-firmware/drivers/allwinner/axp/axp805.c new file mode 100644 index 0000000..3a03fec --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/axp805.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +const uint8_t axp_chip_id = AXP805_CHIP_ID; +const char *const axp_compatible = "x-powers,axp805"; + +#if SUNXI_SETUP_REGULATORS == 1 +/* + * The "dcdcd" split changes the step size by a factor of 5, not 2; + * disallow values above the split to maintain accuracy. + */ +const struct axp_regulator axp_regulators[] = { + {"dcdca", 600, 1520, 10, 50, 0x12, 0x10, 0}, + {"dcdcb", 1000, 2550, 50, NA, 0x13, 0x10, 1}, + {"dcdcc", 600, 1520, 10, 50, 0x14, 0x10, 2}, + {"dcdcd", 600, 1500, 20, NA, 0x15, 0x10, 3}, + {"dcdce", 1100, 3400, 100, NA, 0x16, 0x10, 4}, + {"aldo1", 700, 3300, 100, NA, 0x17, 0x10, 5}, + {"aldo2", 700, 3300, 100, NA, 0x18, 0x10, 6}, + {"aldo3", 700, 3300, 100, NA, 0x19, 0x10, 7}, + {"bldo1", 700, 1900, 100, NA, 0x20, 0x11, 0}, + {"bldo2", 700, 1900, 100, NA, 0x21, 0x11, 1}, + {"bldo3", 700, 1900, 100, NA, 0x22, 0x11, 2}, + {"bldo4", 700, 1900, 100, NA, 0x23, 0x11, 3}, + {"cldo1", 700, 3300, 100, NA, 0x24, 0x11, 4}, + {"cldo2", 700, 4200, 100, 27, 0x25, 0x11, 5}, + {"cldo3", 700, 3300, 100, NA, 0x26, 0x11, 6}, + {} +}; +#endif diff --git a/arm-trusted-firmware/drivers/allwinner/axp/common.c b/arm-trusted-firmware/drivers/allwinner/axp/common.c new file mode 100644 index 0000000..f1250b0 --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/axp/common.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +int axp_check_id(void) +{ + int ret; + + ret = axp_read(0x03); + if (ret < 0) + return ret; + + ret &= 0xcf; + if (ret != axp_chip_id) { + ERROR("PMIC: Found unknown PMIC %02x\n", ret); + return ret; + } + + return 0; +} + +int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask) +{ + uint8_t val; + int ret; + + ret = axp_read(reg); + if (ret < 0) + return ret; + + val = (ret & ~clr_mask) | set_mask; + + return axp_write(reg, val); +} + +void axp_power_off(void) +{ + /* Set "power disable control" bit */ + axp_setbits(0x32, BIT(7)); +} + +#if SUNXI_SETUP_REGULATORS == 1 +/* + * Retrieve the voltage from a given regulator DTB node. + * Both the regulator-{min,max}-microvolt properties must be present and + * have the same value. Return that value in millivolts. + */ +static int fdt_get_regulator_millivolt(const void *fdt, int node) +{ + const fdt32_t *prop; + uint32_t min_volt; + + prop = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + min_volt = fdt32_to_cpu(*prop); + + prop = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (prop == NULL) + return -EINVAL; + + if (fdt32_to_cpu(*prop) != min_volt) + return -EINVAL; + + return min_volt / 1000; +} + +static int setup_regulator(const void *fdt, int node, + const struct axp_regulator *reg) +{ + uint8_t val; + int mvolt; + + mvolt = fdt_get_regulator_millivolt(fdt, node); + if (mvolt < reg->min_volt || mvolt > reg->max_volt) + return -EINVAL; + + val = (mvolt / reg->step) - (reg->min_volt / reg->step); + if (val > reg->split) + val = ((val - reg->split) / 2) + reg->split; + + axp_write(reg->volt_reg, val); + axp_setbits(reg->switch_reg, BIT(reg->switch_bit)); + + INFO("PMIC: %s voltage: %d.%03dV\n", reg->dt_name, + mvolt / 1000, mvolt % 1000); + + return 0; +} + +static bool is_node_disabled(const void *fdt, int node) +{ + const char *cell; + cell = fdt_getprop(fdt, node, "status", NULL); + if (cell == NULL) { + return false; + } + return strcmp(cell, "okay") != 0; +} + +static bool should_enable_regulator(const void *fdt, int node) +{ + if (is_node_disabled(fdt, node)) { + return false; + } + if (fdt_getprop(fdt, node, "phandle", NULL) != NULL) { + return true; + } + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { + return true; + } + return false; +} + +static bool board_uses_usb0_host_mode(const void *fdt) +{ + int node, length; + const char *prop; + + node = fdt_node_offset_by_compatible(fdt, -1, + "allwinner,sun8i-a33-musb"); + if (node < 0) { + return false; + } + + prop = fdt_getprop(fdt, node, "dr_mode", &length); + if (!prop) { + return false; + } + + return !strncmp(prop, "host", length); +} + +void axp_setup_regulators(const void *fdt) +{ + int node; + bool sw = false; + + if (fdt == NULL) + return; + + /* locate the PMIC DT node, bail out if not found */ + node = fdt_node_offset_by_compatible(fdt, -1, axp_compatible); + if (node < 0) { + WARN("PMIC: No PMIC DT node, skipping setup\n"); + return; + } + + /* This applies to AXP803 only. */ + if (fdt_getprop(fdt, node, "x-powers,drive-vbus-en", NULL) && + board_uses_usb0_host_mode(fdt)) { + axp_clrbits(0x8f, BIT(4)); + axp_setbits(0x30, BIT(2)); + INFO("PMIC: Enabling DRIVEVBUS\n"); + } + + /* descend into the "regulators" subnode */ + node = fdt_subnode_offset(fdt, node, "regulators"); + if (node < 0) { + WARN("PMIC: No regulators DT node, skipping setup\n"); + return; + } + + /* iterate over all regulators to find used ones */ + fdt_for_each_subnode(node, fdt, node) { + const struct axp_regulator *reg; + const char *name; + int length; + + /* We only care if it's always on or referenced. */ + if (!should_enable_regulator(fdt, node)) + continue; + + name = fdt_get_name(fdt, node, &length); + + /* Enable the switch last to avoid overheating. */ + if (!strncmp(name, "dc1sw", length) || + !strncmp(name, "sw", length)) { + sw = true; + continue; + } + + for (reg = axp_regulators; reg->dt_name; reg++) { + if (!strncmp(name, reg->dt_name, length)) { + setup_regulator(fdt, node, reg); + break; + } + } + } + + /* + * On the AXP803, if DLDO2 is enabled after DC1SW, the PMIC overheats + * and shuts down. So always enable DC1SW as the very last regulator. + */ + if (sw) { + INFO("PMIC: Enabling DC SW\n"); + if (axp_chip_id == AXP803_CHIP_ID) + axp_setbits(0x12, BIT(7)); + if (axp_chip_id == AXP805_CHIP_ID) + axp_setbits(0x11, BIT(7)); + } +} +#endif /* SUNXI_SETUP_REGULATORS */ diff --git a/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c b/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c new file mode 100644 index 0000000..cc4a6ff --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +#define REMOTE_IRQ_EN_REG 0x0040 +#define REMOTE_IRQ_STAT_REG 0x0050 +#define LOCAL_IRQ_EN_REG 0x0060 +#define LOCAL_IRQ_STAT_REG 0x0070 + +#define RX_IRQ(n) BIT(0 + 2 * (n)) +#define TX_IRQ(n) BIT(1 + 2 * (n)) + +#define FIFO_STAT_REG(n) (0x0100 + 0x4 * (n)) +#define FIFO_STAT_MASK GENMASK(0, 0) + +#define MSG_STAT_REG(n) (0x0140 + 0x4 * (n)) +#define MSG_STAT_MASK GENMASK(2, 0) + +#define MSG_DATA_REG(n) (0x0180 + 0x4 * (n)) + +#define RX_CHAN 1 +#define TX_CHAN 0 + +#define MHU_MAX_SLOT_ID 31 + +#define MHU_TIMEOUT_DELAY 10 +#define MHU_TIMEOUT_ITERS 10000 + +static DEFINE_BAKERY_LOCK(mhu_secure_message_lock); + +static bool sunxi_msgbox_last_tx_done(unsigned int chan) +{ + uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + REMOTE_IRQ_STAT_REG); + + return (stat & RX_IRQ(chan)) == 0U; +} + +static bool sunxi_msgbox_peek_data(unsigned int chan) +{ + uint32_t stat = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_STAT_REG(chan)); + + return (stat & MSG_STAT_MASK) != 0U; +} + +void mhu_secure_message_start(unsigned int slot_id __unused) +{ + uint32_t timeout = MHU_TIMEOUT_ITERS; + + bakery_lock_get(&mhu_secure_message_lock); + + /* Wait for all previous messages to be acknowledged. */ + while (!sunxi_msgbox_last_tx_done(TX_CHAN) && --timeout) + udelay(MHU_TIMEOUT_DELAY); +} + +void mhu_secure_message_send(unsigned int slot_id) +{ + mmio_write_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(TX_CHAN), BIT(slot_id)); +} + +uint32_t mhu_secure_message_wait(void) +{ + uint32_t timeout = MHU_TIMEOUT_ITERS; + uint32_t msg = 0; + + /* Wait for a message from the SCP. */ + while (!sunxi_msgbox_peek_data(RX_CHAN) && --timeout) + udelay(MHU_TIMEOUT_DELAY); + + /* Return the most recent message in the FIFO. */ + while (sunxi_msgbox_peek_data(RX_CHAN)) + msg = mmio_read_32(SUNXI_MSGBOX_BASE + MSG_DATA_REG(RX_CHAN)); + + return msg; +} + +void mhu_secure_message_end(unsigned int slot_id) +{ + /* Acknowledge a response by clearing the IRQ status. */ + mmio_write_32(SUNXI_MSGBOX_BASE + LOCAL_IRQ_STAT_REG, RX_IRQ(RX_CHAN)); + + bakery_lock_release(&mhu_secure_message_lock); +} diff --git a/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c b/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c new file mode 100644 index 0000000..67f5b7e --- /dev/null +++ b/arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +#define RSB_CTRL 0x00 +#define RSB_CCR 0x04 +#define RSB_INTE 0x08 +#define RSB_STAT 0x0c +#define RSB_DADDR0 0x10 +#define RSB_DLEN 0x18 +#define RSB_DATA0 0x1c +#define RSB_LCR 0x24 +#define RSB_PMCR 0x28 +#define RSB_CMD 0x2c +#define RSB_SADDR 0x30 + +#define RSBCMD_SRTA 0xE8 +#define RSBCMD_RD8 0x8B +#define RSBCMD_RD16 0x9C +#define RSBCMD_RD32 0xA6 +#define RSBCMD_WR8 0x4E +#define RSBCMD_WR16 0x59 +#define RSBCMD_WR32 0x63 + +#define MAX_TRIES 100000 + +static int rsb_wait_bit(const char *desc, unsigned int offset, uint32_t mask) +{ + uint32_t reg, tries = MAX_TRIES; + + do + reg = mmio_read_32(SUNXI_R_RSB_BASE + offset); + while ((reg & mask) && --tries); /* transaction in progress */ + if (reg & mask) { + ERROR("%s: timed out\n", desc); + return -ETIMEDOUT; + } + + return 0; +} + +static int rsb_wait_stat(const char *desc) +{ + uint32_t reg; + int ret = rsb_wait_bit(desc, RSB_CTRL, BIT(7)); + + if (ret) + return ret; + + reg = mmio_read_32(SUNXI_R_RSB_BASE + RSB_STAT); + if (reg == 0x01) + return 0; + + ERROR("%s: 0x%x\n", desc, reg); + return -reg; +} + +/* Initialize the RSB controller. */ +int rsb_init_controller(void) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x01); /* soft reset */ + + return rsb_wait_bit("RSB: reset controller", RSB_CTRL, BIT(0)); +} + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr) +{ + int ret; + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_RD8); /* read a byte */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + ret = rsb_wait_stat("RSB: read command"); + if (ret) + return ret; + + return mmio_read_32(SUNXI_R_RSB_BASE + RSB_DATA0) & 0xff; /* result */ +} + +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_WR8); /* byte write */ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, rt_addr << 16); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DADDR0, reg_addr); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_DATA0, value); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80);/* start transaction */ + + return rsb_wait_stat("RSB: write command"); +} + +int rsb_set_device_mode(uint32_t device_mode) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_PMCR, + (device_mode & 0x00ffffff) | BIT(31)); + + return rsb_wait_bit("RSB: set device to RSB", RSB_PMCR, BIT(31)); +} + +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq) +{ + uint32_t reg; + + if (bus_freq == 0) + return -EINVAL; + + reg = source_freq / bus_freq; + if (reg < 2) + return -EINVAL; + + reg = reg / 2 - 1; + reg |= (1U << 8); /* one cycle of CD output delay */ + + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CCR, reg); + + return 0; +} + +/* Initialize the RSB PMIC connection. */ +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr) +{ + mmio_write_32(SUNXI_R_RSB_BASE + RSB_SADDR, hw_addr | (rt_addr << 16)); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CMD, RSBCMD_SRTA); + mmio_write_32(SUNXI_R_RSB_BASE + RSB_CTRL, 0x80); + + return rsb_wait_stat("RSB: set run-time address"); +} diff --git a/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S b/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S new file mode 100644 index 0000000..6d0a2d6 --- /dev/null +++ b/arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S @@ -0,0 +1,262 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl console_meson_register + .globl console_meson_init + .globl console_meson_putc + .globl console_meson_getc + .globl console_meson_flush + .globl console_meson_core_putc + .globl console_meson_core_getc + .globl console_meson_core_flush + + /* ----------------------------------------------- + * Hardware definitions + * ----------------------------------------------- + */ +#define MESON_WFIFO_OFFSET 0x0 +#define MESON_RFIFO_OFFSET 0x4 +#define MESON_CONTROL_OFFSET 0x8 +#define MESON_STATUS_OFFSET 0xC +#define MESON_MISC_OFFSET 0x10 +#define MESON_REG5_OFFSET 0x14 + +#define MESON_CONTROL_CLR_ERROR_BIT 24 +#define MESON_CONTROL_RX_RESET_BIT 23 +#define MESON_CONTROL_TX_RESET_BIT 22 +#define MESON_CONTROL_RX_ENABLE_BIT 13 +#define MESON_CONTROL_TX_ENABLE_BIT 12 + +#define MESON_STATUS_RX_EMPTY_BIT 20 +#define MESON_STATUS_TX_FULL_BIT 21 +#define MESON_STATUS_TX_EMPTY_BIT 22 + +#define MESON_REG5_USE_XTAL_CLK_BIT 24 +#define MESON_REG5_USE_NEW_RATE_BIT 23 +#define MESON_REG5_NEW_BAUD_RATE_MASK 0x7FFFFF + + /* ----------------------------------------------- + * int console_meson_register(uintptr_t base, + * uint32_t clk, uint32_t baud, + * console_t *console); + * Function to initialize and register a new MESON + * 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_meson_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_meson_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register meson putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_meson_register + + /* ----------------------------------------------- + * int console_meson_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x0-x3 + * ----------------------------------------------- + */ +func console_meson_init + cmp w0, #0 + beq init_fail + mov_imm w3, 24000000 /* TODO: This only works with a 24 MHz clock. */ + cmp w1, w3 + bne init_fail + cmp w2, #0 + beq init_fail + /* Set baud rate: value = ((clock / 3) / baudrate) - 1 */ + mov w3, #3 + udiv w3, w1, w3 + udiv w3, w3, w2 + sub w3, w3, #1 + orr w3, w3, #((1 << MESON_REG5_USE_XTAL_CLK_BIT) | \ + (1 << MESON_REG5_USE_NEW_RATE_BIT)) + str w3, [x0, #MESON_REG5_OFFSET] + /* Reset UART and clear error flag */ + ldr w3, [x0, #MESON_CONTROL_OFFSET] + orr w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + bic w3, w3, #((1 << MESON_CONTROL_CLR_ERROR_BIT) | \ + (1 << MESON_CONTROL_RX_RESET_BIT) | \ + (1 << MESON_CONTROL_TX_RESET_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Enable transfer and receive FIFO */ + orr w3, w3, #((1 << MESON_CONTROL_RX_ENABLE_BIT) | \ + (1 << MESON_CONTROL_TX_ENABLE_BIT)) + str w3, [x0, #MESON_CONTROL_OFFSET] + /* Success */ + mov w0, #1 + ret +init_fail: + mov w0, wzr + ret +endfunc console_meson_init + + /* -------------------------------------------------------- + * int console_meson_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_meson_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_meson_core_putc +endfunc console_meson_putc + + /* -------------------------------------------------------- + * int console_meson_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_meson_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Wait until the transmit FIFO isn't full */ +1: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 1b + /* Write '\r' if needed */ + mov w2, #0xD + str w2, [x1, #MESON_WFIFO_OFFSET] + /* Wait until the transmit FIFO isn't full */ +2: ldr w2, [x1, #MESON_STATUS_OFFSET] + tbnz w2, #MESON_STATUS_TX_FULL_BIT, 2b + /* Write input character */ + str w0, [x1, #MESON_WFIFO_OFFSET] + ret +endfunc console_meson_core_putc + + /* --------------------------------------------- + * int console_meson_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_meson_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_meson_core_getc +endfunc console_meson_getc + + /* --------------------------------------------- + * int console_meson_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_meson_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Is the receive FIFO empty? */ + ldr w1, [x0, #MESON_STATUS_OFFSET] + tbnz w1, #MESON_STATUS_RX_EMPTY_BIT, 1f + /* Read one character from the RX FIFO */ + ldr w0, [x0, #MESON_RFIFO_OFFSET] + ret +1: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_meson_core_getc + + /* --------------------------------------------- + * void console_meson_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_meson_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_meson_core_flush +endfunc console_meson_flush + + /* --------------------------------------------- + * void console_meson_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_meson_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + /* Wait until the transmit FIFO is empty */ +1: ldr w1, [x0, #MESON_STATUS_OFFSET] + tbz w1, #MESON_STATUS_TX_EMPTY_BIT, 1b + ret +endfunc console_meson_core_flush diff --git a/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c b/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c new file mode 100644 index 0000000..fceb1c0 --- /dev/null +++ b/arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "aml_private.h" + +#define ASD_MODE_SHA224 0x7 +#define ASD_MODE_SHA256 0x6 + +/* SHA DMA descriptor */ +struct asd_desc { + uint32_t cfg; + uint32_t src; + uint32_t dst; +}; +#define ASD_DESC_GET(x, msk, off) (((x) >> (off)) & (msk)) +#define ASD_DESC_SET(x, v, msk, off) \ + ((x) = ((x) & ~((msk) << (off))) | (((v) & (msk)) << (off))) + +#define ASD_DESC_LEN_OFF 0 +#define ASD_DESC_LEN_MASK 0x1ffff +#define ASD_DESC_LEN(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) +#define ASD_DESC_LEN_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LEN_MASK, ASD_DESC_LEN_OFF)) + +#define ASD_DESC_IRQ_OFF 17 +#define ASD_DESC_IRQ_MASK 0x1 +#define ASD_DESC_IRQ(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) +#define ASD_DESC_IRQ_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_IRQ_MASK, ASD_DESC_IRQ_OFF)) + +#define ASD_DESC_EOD_OFF 18 +#define ASD_DESC_EOD_MASK 0x1 +#define ASD_DESC_EOD(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) +#define ASD_DESC_EOD_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_EOD_MASK, ASD_DESC_EOD_OFF)) + +#define ASD_DESC_LOOP_OFF 19 +#define ASD_DESC_LOOP_MASK 0x1 +#define ASD_DESC_LOOP(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) +#define ASD_DESC_LOOP_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_LOOP_MASK, ASD_DESC_LOOP_OFF)) + +#define ASD_DESC_MODE_OFF 20 +#define ASD_DESC_MODE_MASK 0xf +#define ASD_DESC_MODE(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) +#define ASD_DESC_MODE_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_MODE_MASK, ASD_DESC_MODE_OFF)) + +#define ASD_DESC_BEGIN_OFF 24 +#define ASD_DESC_BEGIN_MASK 0x1 +#define ASD_DESC_BEGIN(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) +#define ASD_DESC_BEGIN_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BEGIN_MASK, ASD_DESC_BEGIN_OFF)) + +#define ASD_DESC_END_OFF 25 +#define ASD_DESC_END_MASK 0x1 +#define ASD_DESC_END(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) +#define ASD_DESC_END_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_END_MASK, ASD_DESC_END_OFF)) + +#define ASD_DESC_OP_OFF 26 +#define ASD_DESC_OP_MASK 0x2 +#define ASD_DESC_OP(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) +#define ASD_DESC_OP_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OP_MASK, ASD_DESC_OP_OFF)) + +#define ASD_DESC_ENCONLY_OFF 28 +#define ASD_DESC_ENCONLY_MASK 0x1 +#define ASD_DESC_ENCONLY(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) +#define ASD_DESC_ENCONLY_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ENCONLY_MASK, ASD_DESC_ENCONLY_OFF)) + +#define ASD_DESC_BLOCK_OFF 29 +#define ASD_DESC_BLOCK_MASK 0x1 +#define ASD_DESC_BLOCK(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) +#define ASD_DESC_BLOCK_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_BLOCK_MASK, ASD_DESC_BLOCK_OFF)) + +#define ASD_DESC_ERR_OFF 30 +#define ASD_DESC_ERR_MASK 0x1 +#define ASD_DESC_ERR(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) +#define ASD_DESC_ERR_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_ERR_MASK, ASD_DESC_ERR_OFF)) + +#define ASD_DESC_OWNER_OFF 31u +#define ASD_DESC_OWNER_MASK 0x1u +#define ASD_DESC_OWNER(d) \ + (ASD_DESC_GET((d)->cfg, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) +#define ASD_DESC_OWNER_SET(d, v) \ + (ASD_DESC_SET((d)->cfg, v, ASD_DESC_OWNER_MASK, ASD_DESC_OWNER_OFF)) + +static void asd_compute_sha(struct asd_ctx *ctx, void *data, size_t len, + int finalize) +{ + /* Make it cache line size aligned ? */ + struct asd_desc desc = { + .src = (uint32_t)(uintptr_t)data, + .dst = (uint32_t)(uintptr_t)ctx->digest, + }; + + /* Check data address is 32bit compatible */ + assert((uintptr_t)data == (uintptr_t)desc.src); + assert((uintptr_t)ctx->digest == (uintptr_t)desc.dst); + assert((uintptr_t)&desc == (uintptr_t)&desc); + + ASD_DESC_LEN_SET(&desc, len); + ASD_DESC_OWNER_SET(&desc, 1u); + ASD_DESC_ENCONLY_SET(&desc, 1); + ASD_DESC_EOD_SET(&desc, 1); + if (ctx->started == 0) { + ASD_DESC_BEGIN_SET(&desc, 1); + ctx->started = 1; + } + if (finalize) { + ASD_DESC_END_SET(&desc, 1); + ctx->started = 0; + } + if (ctx->mode == ASM_SHA224) + ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA224); + else + ASD_DESC_MODE_SET(&desc, ASD_MODE_SHA256); + + flush_dcache_range((uintptr_t)&desc, sizeof(desc)); + flush_dcache_range((uintptr_t)data, len); + + mmio_write_32(AML_SHA_DMA_STATUS, 0xf); + mmio_write_32(AML_SHA_DMA_DESC, ((uintptr_t)&desc) | 2); + while (mmio_read_32(AML_SHA_DMA_STATUS) == 0) + continue; + flush_dcache_range((uintptr_t)ctx->digest, SHA256_HASHSZ); +} + +void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len) +{ + size_t nr; + + if (ctx->blocksz) { + nr = MIN(len, SHA256_BLOCKSZ - ctx->blocksz); + memcpy(ctx->block + ctx->blocksz, data, nr); + ctx->blocksz += nr; + len -= nr; + data += nr; + } + + if (ctx->blocksz == SHA256_BLOCKSZ) { + asd_compute_sha(ctx, ctx->block, SHA256_BLOCKSZ, 0); + ctx->blocksz = 0; + } + + asd_compute_sha(ctx, data, len & ~(SHA256_BLOCKSZ - 1), 0); + data += len & ~(SHA256_BLOCKSZ - 1); + + if (len & (SHA256_BLOCKSZ - 1)) { + nr = len & (SHA256_BLOCKSZ - 1); + memcpy(ctx->block + ctx->blocksz, data, nr); + ctx->blocksz += nr; + } +} + +void asd_sha_finalize(struct asd_ctx *ctx) +{ + asd_compute_sha(ctx, ctx->block, ctx->blocksz, 1); +} diff --git a/arm-trusted-firmware/drivers/arm/cci/cci.c b/arm-trusted-firmware/drivers/arm/cci/cci.c new file mode 100644 index 0000000..2adfe17 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/cci/cci.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAKE_CCI_PART_NUMBER(hi, lo) (((hi) << 8) | (lo)) +#define CCI_PART_LO_MASK U(0xff) +#define CCI_PART_HI_MASK U(0xf) + +/* CCI part number codes read from Peripheral ID registers 0 and 1 */ +#define CCI400_PART_NUM 0x420 +#define CCI500_PART_NUM 0x422 +#define CCI550_PART_NUM 0x423 + +#define CCI400_SLAVE_PORTS 5 +#define CCI500_SLAVE_PORTS 7 +#define CCI550_SLAVE_PORTS 7 + +static uintptr_t cci_base; +static const int *cci_slave_if_map; + +#if ENABLE_ASSERTIONS +static unsigned int max_master_id; +static int cci_num_slave_ports; + +static bool validate_cci_map(const int *map) +{ + unsigned int valid_cci_map = 0U; + int slave_if_id; + unsigned int i; + + /* Validate the map */ + for (i = 0U; i <= max_master_id; i++) { + slave_if_id = map[i]; + + if (slave_if_id < 0) + continue; + + if (slave_if_id >= cci_num_slave_ports) { + ERROR("Slave interface ID is invalid\n"); + return false; + } + + if ((valid_cci_map & (1UL << slave_if_id)) != 0U) { + ERROR("Multiple masters are assigned same slave interface ID\n"); + return false; + } + valid_cci_map |= 1UL << slave_if_id; + } + + if (valid_cci_map == 0U) { + ERROR("No master is assigned a valid slave interface\n"); + return false; + } + + return true; +} + +/* + * Read CCI part number from Peripheral ID registers + */ +static unsigned int read_cci_part_number(uintptr_t base) +{ + unsigned int part_lo, part_hi; + + part_lo = mmio_read_32(base + PERIPHERAL_ID0) & CCI_PART_LO_MASK; + part_hi = mmio_read_32(base + PERIPHERAL_ID1) & CCI_PART_HI_MASK; + + return MAKE_CCI_PART_NUMBER(part_hi, part_lo); +} + +/* + * Identify a CCI device, and return the number of slaves. Return -1 for an + * unidentified device. + */ +static int get_slave_ports(unsigned int part_num) +{ + int num_slave_ports = -1; + + switch (part_num) { + + case CCI400_PART_NUM: + num_slave_ports = CCI400_SLAVE_PORTS; + break; + case CCI500_PART_NUM: + num_slave_ports = CCI500_SLAVE_PORTS; + break; + case CCI550_PART_NUM: + num_slave_ports = CCI550_SLAVE_PORTS; + break; + default: + /* Do nothing in default case */ + break; + } + + return num_slave_ports; +} +#endif /* ENABLE_ASSERTIONS */ + +void __init cci_init(uintptr_t base, const int *map, + unsigned int num_cci_masters) +{ + assert(map != NULL); + assert(base != 0U); + + cci_base = base; + cci_slave_if_map = map; + +#if ENABLE_ASSERTIONS + /* + * Master Id's are assigned from zero, So in an array of size n + * the max master id is (n - 1). + */ + max_master_id = num_cci_masters - 1U; + cci_num_slave_ports = get_slave_ports(read_cci_part_number(base)); +#endif + assert(cci_num_slave_ports >= 0); + + assert(validate_cci_map(map)); +} + +void cci_enable_snoop_dvm_reqs(unsigned int master_id) +{ + int slave_if_id = cci_slave_if_map[master_id]; + + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base != 0U); + + /* + * Enable Snoops and DVM messages, no need for Read/Modify/Write as + * rest of bits are write ignore + */ + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + DVM_EN_BIT | SNOOP_EN_BIT); + + /* + * Wait for the completion of the write to the Snoop Control Register + * before testing the change_pending bit + */ + dsbish(); + + /* Wait for the dust to settle down */ + while ((mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) != 0U) + ; +} + +void cci_disable_snoop_dvm_reqs(unsigned int master_id) +{ + int slave_if_id = cci_slave_if_map[master_id]; + + assert(master_id <= max_master_id); + assert((slave_if_id < cci_num_slave_ports) && (slave_if_id >= 0)); + assert(cci_base != 0U); + + /* + * Disable Snoops and DVM messages, no need for Read/Modify/Write as + * rest of bits are write ignore. + */ + mmio_write_32(cci_base + + SLAVE_IFACE_OFFSET(slave_if_id) + SNOOP_CTRL_REG, + ~(DVM_EN_BIT | SNOOP_EN_BIT)); + + /* + * Wait for the completion of the write to the Snoop Control Register + * before testing the change_pending bit + */ + dsbish(); + + /* Wait for the dust to settle down */ + while ((mmio_read_32(cci_base + STATUS_REG) & CHANGE_PENDING_BIT) != 0U) + ; +} + diff --git a/arm-trusted-firmware/drivers/arm/ccn/ccn.c b/arm-trusted-firmware/drivers/arm/ccn/ccn.c new file mode 100644 index 0000000..5b13250 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ccn/ccn.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include "ccn_private.h" + +static const ccn_desc_t *ccn_plat_desc; +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) +DEFINE_BAKERY_LOCK(ccn_lock); +#endif + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV), a + * region ID of one of the 256 regions (0-255) and a register offset within the + * region. It converts the first two parameters into a base address and uses it + * to read the register at the offset. + ******************************************************************************/ +static inline unsigned long long ccn_reg_read(uintptr_t periphbase, + unsigned int region_id, + unsigned int register_offset) +{ + uintptr_t region_base; + + assert(periphbase); + assert(region_id < REGION_ID_LIMIT); + + region_base = periphbase + region_id_to_base(region_id); + return mmio_read_64(region_base + register_offset); +} + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV), a + * region ID of one of the 256 regions (0-255), a register offset within the + * region and a value. It converts the first two parameters into a base address + * and uses it to write the value in the register at the offset. + ******************************************************************************/ +static inline void ccn_reg_write(uintptr_t periphbase, + unsigned int region_id, + unsigned int register_offset, + unsigned long long value) +{ + uintptr_t region_base; + + assert(periphbase); + assert(region_id < REGION_ID_LIMIT); + + region_base = periphbase + region_id_to_base(region_id); + mmio_write_64(region_base + register_offset, value); +} + +#if ENABLE_ASSERTIONS + +typedef struct rn_info { + unsigned char node_desc[MAX_RN_NODES]; + } rn_info_t; + +/******************************************************************************* + * This function takes the base address of the CCN's programmer's view (PV) and + * the node ID of a Request Node (RN-D or RN-I). It returns the maximum number + * of master interfaces resident on that node. This number is equal to the least + * significant two bits of the node type ID + 1. + ******************************************************************************/ +static unsigned int ccn_get_rni_mcount(uintptr_t periphbase, + unsigned int rn_id) +{ + unsigned int rn_type_id; + + /* Use the node id to find the type of RN-I/D node */ + rn_type_id = get_node_type(ccn_reg_read(periphbase, + rn_id + RNI_REGION_ID_START, + REGION_ID_OFFSET)); + + /* Return the number master interfaces based on node type */ + return rn_type_id_to_master_cnt(rn_type_id); +} + +/******************************************************************************* + * This function reads the CCN registers to find the following information about + * the ACE/ACELite/ACELite+DVM/CHI interfaces resident on the various types of + * Request Nodes (RN-Fs, RN-Is and RN-Ds) in the system: + * + * 1. The total number of such interfaces that this CCN IP supports. This is the + * cumulative number of interfaces across all Request node types. It is + * passed back as the return value of this function. + * + * 2. The maximum number of interfaces of a type resident on a Request node of + * one of the three types. This information is populated in the 'info' + * array provided by the caller as described next. + * + * The array has 64 entries. Each entry corresponds to a Request node. The + * Miscellaneous node's programmer's view has RN-F, RN-I and RN-D ID + * registers. For each RN-I and RN-D ID indicated as being present in these + * registers, its identification register (offset 0xFF00) is read. This + * register specifies the maximum number of master interfaces the node + * supports. For RN-Fs it is assumed that there can be only a single fully + * coherent master resident on each node. The counts for each type of node + * are use to populate the array entry at the index corresponding to the node + * ID i.e. rn_info[node ID] = + ******************************************************************************/ +static unsigned int ccn_get_rn_master_info(uintptr_t periphbase, + rn_info_t *info) +{ + unsigned int num_masters = 0; + rn_types_t rn_type; + + assert (info); + + for (rn_type = RN_TYPE_RNF; rn_type < NUM_RN_TYPES; rn_type++) { + unsigned int mn_reg_off, node_id; + unsigned long long rn_bitmap; + + /* + * RN-F, RN-I, RN-D node registers in the MN region occupy + * contiguous 16 byte apart offsets. + */ + mn_reg_off = MN_RNF_NODEID_OFFSET + (rn_type << 4); + rn_bitmap = ccn_reg_read(periphbase, MN_REGION_ID, mn_reg_off); + + FOR_EACH_PRESENT_NODE_ID(node_id, rn_bitmap) { + unsigned int node_mcount; + + /* + * A RN-F does not have a node type since it does not + * export a programmer's interface. It can only have a + * single fully coherent master residing on it. If the + * offset of the MN(Miscellaneous Node) register points + * to a RN-I/D node then the master count is set to the + * maximum number of master interfaces that can possibly + * reside on the node. + */ + node_mcount = (mn_reg_off == MN_RNF_NODEID_OFFSET ? 1 : + ccn_get_rni_mcount(periphbase, node_id)); + + /* + * Use this value to increment the maximum possible + * master interfaces in the system. + */ + num_masters += node_mcount; + + /* + * Update the entry in 'info' for this node ID with + * the maximum number of masters than can sit on + * it. This information will be used to validate the + * node information passed by the platform later. + */ + info->node_desc[node_id] = node_mcount; + } + } + + return num_masters; +} + +/******************************************************************************* + * This function validates parameters passed by the platform (in a debug build). + * It collects information about the maximum number of master interfaces that: + * a) the CCN IP can accommodate and + * b) can exist on each Request node. + * It compares this with the information provided by the platform to determine + * the validity of the latter. + ******************************************************************************/ +static void __init ccn_validate_plat_params(const ccn_desc_t *plat_desc) +{ + unsigned int master_id, num_rn_masters; + rn_info_t info = { {0} }; + + assert(plat_desc); + assert(plat_desc->periphbase); + assert(plat_desc->master_to_rn_id_map); + assert(plat_desc->num_masters); + assert(plat_desc->num_masters < CCN_MAX_RN_MASTERS); + + /* + * Find the number and properties of fully coherent, IO coherent and IO + * coherent + DVM master interfaces + */ + num_rn_masters = ccn_get_rn_master_info(plat_desc->periphbase, &info); + assert(plat_desc->num_masters < num_rn_masters); + + /* + * Iterate through the Request nodes specified by the platform. + * Decrement the count of the masters in the 'info' array for each + * Request node encountered. If the count would drop below 0 then the + * platform's view of this aspect of CCN configuration is incorrect. + */ + for (master_id = 0; master_id < plat_desc->num_masters; master_id++) { + unsigned int node_id; + + node_id = plat_desc->master_to_rn_id_map[master_id]; + assert(node_id < MAX_RN_NODES); + assert(info.node_desc[node_id]); + info.node_desc[node_id]--; + } +} +#endif /* ENABLE_ASSERTIONS */ + +/******************************************************************************* + * This function validates parameters passed by the platform (in a debug build) + * and initialises its internal data structures. A lock is required to prevent + * simultaneous CCN operations at runtime (only BL31) to add and remove Request + * nodes from coherency. + ******************************************************************************/ +void __init ccn_init(const ccn_desc_t *plat_desc) +{ +#if ENABLE_ASSERTIONS + ccn_validate_plat_params(plat_desc); +#endif + + ccn_plat_desc = plat_desc; +} + +/******************************************************************************* + * This function converts a bit map of master interface IDs to a bit map of the + * Request node IDs that they reside on. + ******************************************************************************/ +static unsigned long long ccn_master_to_rn_id_map(unsigned long long master_map) +{ + unsigned long long rn_id_map = 0; + unsigned int node_id, iface_id; + + assert(master_map); + assert(ccn_plat_desc); + + FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, master_map) { + assert(iface_id < ccn_plat_desc->num_masters); + + /* Convert the master ID into the node ID */ + node_id = ccn_plat_desc->master_to_rn_id_map[iface_id]; + + /* Set the bit corresponding to this node ID */ + rn_id_map |= (1ULL << node_id); + } + + return rn_id_map; +} + +/******************************************************************************* + * This function executes the necessary operations to add or remove Request node + * IDs specified in the 'rn_id_map' bitmap from the snoop/DVM domains specified + * in the 'hn_id_map'. The 'region_id' specifies the ID of the first HN-F/MN + * on which the operation should be performed. 'op_reg_offset' specifies the + * type of operation (add/remove). 'stat_reg_offset' specifies the register + * which should be polled to determine if the operation has completed or not. + ******************************************************************************/ +static void ccn_snoop_dvm_do_op(unsigned long long rn_id_map, + unsigned long long hn_id_map, + unsigned int region_id, + unsigned int op_reg_offset, + unsigned int stat_reg_offset) +{ + unsigned int start_region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) + bakery_lock_get(&ccn_lock); +#endif + start_region_id = region_id; + FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) { + ccn_reg_write(ccn_plat_desc->periphbase, + start_region_id, + op_reg_offset, + rn_id_map); + } + + start_region_id = region_id; + + FOR_EACH_PRESENT_REGION_ID(start_region_id, hn_id_map) { + WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(start_region_id, + stat_reg_offset, + op_reg_offset, + rn_id_map); + } + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) + bakery_lock_release(&ccn_lock); +#endif +} + +/******************************************************************************* + * The following functions provide the boot and runtime API to the platform for + * adding and removing master interfaces from the snoop/DVM domains. A bitmap of + * master interfaces IDs is passed as a parameter. It is converted into a bitmap + * of Request node IDs using the mapping provided by the platform while + * initialising the driver. + * For example, consider a dual cluster system where the clusters have values 0 + * & 1 in the affinity level 1 field of their respective MPIDRs. While + * initialising this driver, the platform provides the mapping between each + * cluster and the corresponding Request node. To add or remove a cluster from + * the snoop and dvm domain, the bit position corresponding to the cluster ID + * should be set in the 'master_iface_map' i.e. to remove both clusters the + * bitmap would equal 0x11. + ******************************************************************************/ +void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase, + MN_HNF_NODEID_OFFSET), + HNF_REGION_ID_START, + HNF_SDC_SET_OFFSET, + HNF_SDC_STAT_OFFSET); + + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_SET_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_HN_NODEID_MAP(ccn_plat_desc->periphbase, + MN_HNF_NODEID_OFFSET), + HNF_REGION_ID_START, + HNF_SDC_CLR_OFFSET, + HNF_SDC_STAT_OFFSET); + + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_CLR_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_enter_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_SET_OFFSET, + MN_DDC_STAT_OFFSET); +} + +void ccn_exit_dvm_domain(unsigned long long master_iface_map) +{ + unsigned long long rn_id_map; + + rn_id_map = ccn_master_to_rn_id_map(master_iface_map); + ccn_snoop_dvm_do_op(rn_id_map, + CCN_GET_MN_NODEID_MAP(ccn_plat_desc->periphbase), + MN_REGION_ID, + MN_DDC_CLR_OFFSET, + MN_DDC_STAT_OFFSET); +} + +/******************************************************************************* + * This function returns the run mode of all the L3 cache partitions in the + * system. The state is expected to be one of NO_L3, SF_ONLY, L3_HAM or + * L3_FAM. Instead of comparing the states reported by all HN-Fs, the state of + * the first present HN-F node is reported. Since the driver does not export an + * interface to program them separately, there is no reason to perform this + * check. An HN-F could report that the L3 cache is transitioning from one mode + * to another e.g. HNF_PM_NOL3_2_SFONLY. In this case, the function waits for + * the transition to complete and reports the final state. + ******************************************************************************/ +unsigned int ccn_get_l3_run_mode(void) +{ + unsigned long long hnf_pstate_stat; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + + /* + * Wait for a L3 cache partition to enter any run mode. The pstate + * parameter is read from an HN-F P-state status register. A non-zero + * value in bits[1:0] means that the cache is transitioning to a run + * mode. + */ + do { + hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase, + HNF_REGION_ID_START, + HNF_PSTATE_STAT_OFFSET); + } while (hnf_pstate_stat & 0x3); + + return PSTATE_TO_RUN_MODE(hnf_pstate_stat); +} + +/******************************************************************************* + * This function sets the run mode of all the L3 cache partitions in the + * system to one of NO_L3, SF_ONLY, L3_HAM or L3_FAM depending upon the state + * specified by the 'mode' argument. + ******************************************************************************/ +void ccn_set_l3_run_mode(unsigned int mode) +{ + unsigned long long mn_hnf_id_map, hnf_pstate_stat; + unsigned int region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + assert(mode <= CCN_L3_RUN_MODE_FAM); + + mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, + MN_HNF_NODEID_OFFSET); + region_id = HNF_REGION_ID_START; + + /* Program the desired run mode */ + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + ccn_reg_write(ccn_plat_desc->periphbase, + region_id, + HNF_PSTATE_REQ_OFFSET, + mode); + } + + /* Wait for the caches to transition to the run mode */ + region_id = HNF_REGION_ID_START; + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + /* + * Wait for a L3 cache partition to enter a target run + * mode. The pstate parameter is read from an HN-F P-state + * status register. + */ + do { + hnf_pstate_stat = ccn_reg_read(ccn_plat_desc->periphbase, + region_id, + HNF_PSTATE_STAT_OFFSET); + } while (((hnf_pstate_stat & HNF_PSTATE_MASK) >> 2) != mode); + } +} + +/******************************************************************************* + * This function configures system address map and provides option to enable the + * 3SN striping mode of Slave node operation. The Slave node IDs and the Top + * Address bit1 and bit0 are provided as parameters to this function. This + * configuration is needed only if network contains a single SN-F or 3 SN-F and + * must be completed before the first request by the system to normal memory. + ******************************************************************************/ +void ccn_program_sys_addrmap(unsigned int sn0_id, + unsigned int sn1_id, + unsigned int sn2_id, + unsigned int top_addr_bit0, + unsigned int top_addr_bit1, + unsigned char three_sn_en) +{ + unsigned long long mn_hnf_id_map, hnf_sam_ctrl_value; + unsigned int region_id; + + assert(ccn_plat_desc); + assert(ccn_plat_desc->periphbase); + + mn_hnf_id_map = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, + MN_HNF_NODEID_OFFSET); + region_id = HNF_REGION_ID_START; + hnf_sam_ctrl_value = MAKE_HNF_SAM_CTRL_VALUE(sn0_id, + sn1_id, + sn2_id, + top_addr_bit0, + top_addr_bit1, + three_sn_en); + + FOR_EACH_PRESENT_REGION_ID(region_id, mn_hnf_id_map) { + + /* Program the SAM control register */ + ccn_reg_write(ccn_plat_desc->periphbase, + region_id, + HNF_SAM_CTRL_OFFSET, + hnf_sam_ctrl_value); + } + +} + +/******************************************************************************* + * This function returns the part0 id from the peripheralID 0 register + * in CCN. This id can be used to distinguish the CCN variant present in the + * system. + ******************************************************************************/ +int ccn_get_part0_id(uintptr_t periphbase) +{ + assert(periphbase); + return (int)(mmio_read_64(periphbase + + MN_PERIPH_ID_0_1_OFFSET) & 0xFF); +} + +/******************************************************************************* + * This function returns the region id corresponding to a node_id of node_type. + ******************************************************************************/ +static unsigned int get_region_id_for_node(node_types_t node_type, + unsigned int node_id) +{ + unsigned int mn_reg_off, region_id; + unsigned long long node_bitmap; + unsigned int loc_node_id, node_pos_in_map = 0; + + assert(node_type < NUM_NODE_TYPES); + assert(node_id < MAX_RN_NODES); + + switch (node_type) { + case NODE_TYPE_RNI: + region_id = RNI_REGION_ID_START; + break; + case NODE_TYPE_HNF: + region_id = HNF_REGION_ID_START; + break; + case NODE_TYPE_HNI: + region_id = HNI_REGION_ID_START; + break; + case NODE_TYPE_SN: + region_id = SBSX_REGION_ID_START; + break; + default: + ERROR("Un-supported Node Type = %d.\n", node_type); + assert(false); + return REGION_ID_LIMIT; + } + /* + * RN-I, HN-F, HN-I, SN node registers in the MN region + * occupy contiguous 16 byte apart offsets. + * + * RN-F and RN-D node are not supported as + * none of them exposes any memory map to + * configure any of their offset registers. + */ + + mn_reg_off = MN_RNF_NODEID_OFFSET + (node_type << 4); + node_bitmap = ccn_reg_read(ccn_plat_desc->periphbase, + MN_REGION_ID, mn_reg_off); + + assert((node_bitmap & (1ULL << (node_id))) != 0U); + + + FOR_EACH_PRESENT_NODE_ID(loc_node_id, node_bitmap) { + INFO("Index = %u with loc_nod=%u and input nod=%u\n", + node_pos_in_map, loc_node_id, node_id); + if (loc_node_id == node_id) + break; + node_pos_in_map++; + } + + if (node_pos_in_map == CCN_MAX_RN_MASTERS) { + ERROR("Node Id = %d, is not found.\n", node_id); + assert(false); + return REGION_ID_LIMIT; + } + + /* + * According to section 3.1.1 in CCN specification, region offset for + * the RN-I components is calculated as (128 + NodeID of RN-I). + */ + if (node_type == NODE_TYPE_RNI) + region_id += node_id; + else + region_id += node_pos_in_map; + + return region_id; +} + +/******************************************************************************* + * This function sets the value 'val' to the register at register_offset from + * the base address pointed to by the region_id. + * where, region id is mapped to a node_id of node_type. + ******************************************************************************/ +void ccn_write_node_reg(node_types_t node_type, unsigned int node_id, + unsigned int reg_offset, unsigned long long val) +{ + unsigned int region_id = get_region_id_for_node(node_type, node_id); + + if (reg_offset > REGION_ID_OFFSET) { + ERROR("Invalid Register offset 0x%x is provided.\n", + reg_offset); + assert(false); + return; + } + + /* Setting the value of Auxiliary Control Register of the Node */ + ccn_reg_write(ccn_plat_desc->periphbase, region_id, reg_offset, val); + VERBOSE("Value is successfully written at address 0x%lx.\n", + (ccn_plat_desc->periphbase + + region_id_to_base(region_id)) + + reg_offset); +} + +/******************************************************************************* + * This function read the value 'val' stored in the register at register_offset + * from the base address pointed to by the region_id. + * where, region id is mapped to a node_id of node_type. + ******************************************************************************/ +unsigned long long ccn_read_node_reg(node_types_t node_type, + unsigned int node_id, + unsigned int reg_offset) +{ + unsigned long long val; + unsigned int region_id = get_region_id_for_node(node_type, node_id); + + if (reg_offset > REGION_ID_OFFSET) { + ERROR("Invalid Register offset 0x%x is provided.\n", + reg_offset); + assert(false); + return ULL(0); + } + + /* Setting the value of Auxiliary Control Register of the Node */ + val = ccn_reg_read(ccn_plat_desc->periphbase, region_id, reg_offset); + VERBOSE("Value is successfully read from address 0x%lx.\n", + (ccn_plat_desc->periphbase + + region_id_to_base(region_id)) + + reg_offset); + + return val; +} diff --git a/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h b/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h new file mode 100644 index 0000000..8a936d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ccn/ccn_private.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2015-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCN_PRIVATE_H +#define CCN_PRIVATE_H + +/* + * A CCN implementation can have a maximum of 64 Request nodes with node IDs + * from 0-63. These IDs are split across the three types of Request nodes + * i.e. RN-F, RN-D and RN-I. + */ +#define MAX_RN_NODES 64 + +/* Enum used to loop through the 3 types of Request nodes */ +typedef enum rn_types { + RN_TYPE_RNF = 0, + RN_TYPE_RNI, + RN_TYPE_RND, + NUM_RN_TYPES +} rn_types_t; + +/* Macro to convert a region id to its base address */ +#define region_id_to_base(id) ((id) << 16) + +/* + * Macro to calculate the number of master interfaces resident on a RN-I/RN-D. + * Value of first two bits of the RN-I/D node type + 1 == Maximum number of + * ACE-Lite or ACE-Lite+DVM interfaces supported on this node. E.g. + * + * 0x14 : RN-I with 1 ACE-Lite interface + * 0x15 : RN-I with 2 ACE-Lite interfaces + * 0x16 : RN-I with 3 ACE-Lite interfaces + */ +#define rn_type_id_to_master_cnt(id) (((id) & 0x3) + 1) + +/* + * Constants used to identify a region in the programmer's view. These are + * common for all regions. + */ +#define REGION_ID_LIMIT 256 +#define REGION_ID_OFFSET 0xFF00 + +#define REGION_NODE_ID_SHIFT 8 +#define REGION_NODE_ID_MASK 0x7f +#define get_node_id(id_reg) (((id_reg) >> REGION_NODE_ID_SHIFT) \ + & REGION_NODE_ID_MASK) + +#define REGION_NODE_TYPE_SHIFT 0 +#define REGION_NODE_TYPE_MASK 0x1f +#define get_node_type(id_reg) (((id_reg) >> REGION_NODE_TYPE_SHIFT) \ + & REGION_NODE_TYPE_MASK) + +/* Common offsets of registers to enter or exit a snoop/dvm domain */ +#define DOMAIN_CTRL_STAT_OFFSET 0x0200 +#define DOMAIN_CTRL_SET_OFFSET 0x0210 +#define DOMAIN_CTRL_CLR_OFFSET 0x0220 + +/* + * Thess macros are used to determine if an operation to add or remove a Request + * node from the snoop/dvm domain has completed. 'rn_id_map' is a bit map of + * nodes. It was used to program the SET or CLEAR control register. The type of + * register is specified by 'op_reg_offset'. 'status_reg' is the bit map of + * nodes currently present in the snoop/dvm domain. 'rn_id_map' and 'status_reg' + * are logically ANDed and the result it stored back in the 'status_reg'. There + * are two outcomes of this operation: + * + * 1. If the DOMAIN_CTRL_SET_OFFSET register was programmed, then the set bits in + * 'rn_id_map' should appear in 'status_reg' when the operation completes. So + * after the AND operation, at some point of time 'status_reg' should equal + * 'rn_id_map'. + * + * 2. If the DOMAIN_CTRL_CLR_OFFSET register was programmed, then the set bits in + * 'rn_id_map' should disappear in 'status_reg' when the operation + * completes. So after the AND operation, at some point of time 'status_reg' + * should equal 0. + */ +#define WAIT_FOR_DOMAIN_CTRL_OP_COMPLETION(region_id, stat_reg_offset, \ + op_reg_offset, rn_id_map) \ + { \ + unsigned long long status_reg; \ + do { \ + status_reg = ccn_reg_read((ccn_plat_desc->periphbase), \ + (region_id), \ + (stat_reg_offset)); \ + status_reg &= (rn_id_map); \ + } while ((op_reg_offset) == DOMAIN_CTRL_SET_OFFSET ? \ + (rn_id_map) != status_reg : status_reg); \ + } + +/* + * Region ID of the Miscellaneous Node is always 0 as its located at the base of + * the programmer's view. + */ +#define MN_REGION_ID 0 + +#define MN_REGION_ID_START 0 +#define DEBUG_REGION_ID_START 1 +#define HNI_REGION_ID_START 8 +#define SBSX_REGION_ID_START 16 +#define HNF_REGION_ID_START 32 +#define XP_REGION_ID_START 64 +#define RNI_REGION_ID_START 128 + +/* Selected register offsets from the base of a HNF region */ +#define HNF_CFG_CTRL_OFFSET 0x0000 +#define HNF_SAM_CTRL_OFFSET 0x0008 +#define HNF_PSTATE_REQ_OFFSET 0x0010 +#define HNF_PSTATE_STAT_OFFSET 0x0018 +#define HNF_SDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET +#define HNF_SDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET +#define HNF_SDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET +#define HNF_AUX_CTRL_OFFSET 0x0500 + +/* Selected register offsets from the base of a MN region */ +#define MN_SAR_OFFSET 0x0000 +#define MN_RNF_NODEID_OFFSET 0x0180 +#define MN_RNI_NODEID_OFFSET 0x0190 +#define MN_RND_NODEID_OFFSET 0x01A0 +#define MN_HNF_NODEID_OFFSET 0x01B0 +#define MN_HNI_NODEID_OFFSET 0x01C0 +#define MN_SN_NODEID_OFFSET 0x01D0 +#define MN_DDC_STAT_OFFSET DOMAIN_CTRL_STAT_OFFSET +#define MN_DDC_SET_OFFSET DOMAIN_CTRL_SET_OFFSET +#define MN_DDC_CLR_OFFSET DOMAIN_CTRL_CLR_OFFSET +#define MN_PERIPH_ID_0_1_OFFSET 0xFE0 +#define MN_ID_OFFSET REGION_ID_OFFSET + +/* HNF System Address Map register bit masks and shifts */ +#define HNF_SAM_CTRL_SN_ID_MASK 0x7f +#define HNF_SAM_CTRL_SN0_ID_SHIFT 0 +#define HNF_SAM_CTRL_SN1_ID_SHIFT 8 +#define HNF_SAM_CTRL_SN2_ID_SHIFT 16 + +#define HNF_SAM_CTRL_TAB0_MASK ULL(0x3f) +#define HNF_SAM_CTRL_TAB0_SHIFT 48 +#define HNF_SAM_CTRL_TAB1_MASK ULL(0x3f) +#define HNF_SAM_CTRL_TAB1_SHIFT 56 + +#define HNF_SAM_CTRL_3SN_ENB_SHIFT 32 +#define HNF_SAM_CTRL_3SN_ENB_MASK ULL(0x01) + +/* + * Macro to create a value suitable for programming into a HNF SAM Control + * register for enabling 3SN striping. + */ +#define MAKE_HNF_SAM_CTRL_VALUE(sn0, sn1, sn2, tab0, tab1, three_sn_en) \ + ((((sn0) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN0_ID_SHIFT) | \ + (((sn1) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN1_ID_SHIFT) | \ + (((sn2) & HNF_SAM_CTRL_SN_ID_MASK) << HNF_SAM_CTRL_SN2_ID_SHIFT) | \ + (((tab0) & HNF_SAM_CTRL_TAB0_MASK) << HNF_SAM_CTRL_TAB0_SHIFT) | \ + (((tab1) & HNF_SAM_CTRL_TAB1_MASK) << HNF_SAM_CTRL_TAB1_SHIFT) | \ + (((three_sn_en) & HNF_SAM_CTRL_3SN_ENB_MASK) << HNF_SAM_CTRL_3SN_ENB_SHIFT)) + +/* Mask to read the power state value from an HN-F P-state register */ +#define HNF_PSTATE_MASK 0xf + +/* Macro to extract the run mode from a p-state value */ +#define PSTATE_TO_RUN_MODE(pstate) (((pstate) & HNF_PSTATE_MASK) >> 2) + +/* + * Helper macro that iterates through a given bit map. In each iteration, + * it returns the position of the set bit. + * It can be used by other utility macros to iterates through all nodes + * or masters given a bit map of them. + */ +#define FOR_EACH_BIT(bit_pos, bit_map) \ + for (bit_pos = __builtin_ctzll(bit_map); \ + bit_map; \ + bit_map &= ~(1ULL << (bit_pos)), \ + bit_pos = __builtin_ctzll(bit_map)) + +/* + * Utility macro that iterates through a bit map of node IDs. In each + * iteration, it returns the ID of the next present node in the bit map. Node + * ID of a present node == Position of set bit == Number of zeroes trailing the + * bit. + */ +#define FOR_EACH_PRESENT_NODE_ID(node_id, bit_map) \ + FOR_EACH_BIT(node_id, bit_map) + +/* + * Helper function to return number of set bits in bitmap + */ +static inline unsigned int count_set_bits(unsigned long long bitmap) +{ + unsigned int count = 0; + + for (; bitmap; bitmap &= bitmap - 1) + ++count; + + return count; +} + +/* + * Utility macro that iterates through a bit map of node IDs. In each iteration, + * it returns the ID of the next present region corresponding to a node present + * in the bit map. Region ID of a present node is in between passed region id + * and region id + number of set bits in the bitmap i.e. the number of present + * nodes. + */ +#define FOR_EACH_PRESENT_REGION_ID(region_id, bit_map) \ + for (unsigned long long region_id_limit = count_set_bits(bit_map) \ + + region_id; \ + region_id < region_id_limit; \ + region_id++) + +/* + * Same macro as FOR_EACH_PRESENT_NODE, but renamed to indicate it traverses + * through a bit map of master interfaces. + */ +#define FOR_EACH_PRESENT_MASTER_INTERFACE(iface_id, bit_map) \ + FOR_EACH_BIT(iface_id, bit_map) + +/* + * Macro that returns the node id bit map for the Miscellaneous Node + */ +#define CCN_GET_MN_NODEID_MAP(periphbase) \ + (1 << get_node_id(ccn_reg_read(periphbase, MN_REGION_ID, \ + REGION_ID_OFFSET))) + +/* + * This macro returns the bitmap of Home nodes on the basis of the + * 'mn_hn_id_reg_offset' parameter from the Miscellaneous node's (MN) + * programmer's view. The MN has a register which carries the bitmap of present + * Home nodes of each type i.e. HN-Fs, HN-Is & HN-Ds. + */ +#define CCN_GET_HN_NODEID_MAP(periphbase, mn_hn_id_reg_offset) \ + ccn_reg_read(periphbase, MN_REGION_ID, mn_hn_id_reg_offset) + +#endif /* CCN_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c new file mode 100644 index 0000000..b7faf7e --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +/* 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 + +ARM_INSTANTIATE_LOCK; + +/* Weak definition may be overridden in specific CSS based platform */ +#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(unsigned int slot_id) +{ + assert(slot_id <= MHU_MAX_SLOT_ID); + + arm_lock_get(); + + /* Make sure any previous command has finished */ + while (mmio_read_32(PLAT_CSS_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_CSS_MHU_BASE + CPU_INTR_S_STAT) & + (1 << slot_id))); + + /* Send command to SCP */ + mmio_write_32(PLAT_CSS_MHU_BASE + CPU_INTR_S_SET, 1 << slot_id); +} + +uint32_t mhu_secure_message_wait(void) +{ + /* Wait for response from SCP */ + uint32_t response; + while (!(response = mmio_read_32(PLAT_CSS_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_CSS_MHU_BASE + SCP_INTR_S_CLEAR, 1 << slot_id); + + 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_CSS_MHU_BASE + CPU_INTR_S_STAT) == 0); +} + +void __init plat_arm_pwrc_setup(void) +{ + mhu_secure_init(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c new file mode 100644 index 0000000..c51f3b1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info) +{ + MHU_RING_DOORBELL(plat_info->db_reg_addr, + plat_info->db_modify_mask, + plat_info->db_preserve_mask); + return; +} + +void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info) +{ + uintptr_t mhuv2_base = plat_info->db_reg_addr & MHU_V2_FRAME_BASE_MASK; + + /* wake receiver */ + MHU_V2_ACCESS_REQUEST(mhuv2_base); + + /* wait for receiver to acknowledge its ready */ + while (MHU_V2_IS_ACCESS_READY(mhuv2_base) == 0) + ; + + MHU_RING_DOORBELL(plat_info->db_reg_addr, + plat_info->db_modify_mask, + plat_info->db_preserve_mask); + + /* clear the access request for the receiver */ + MHU_V2_CLEAR_REQUEST(mhuv2_base); + + return; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c new file mode 100644 index 0000000..5941b87 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI AP core reset address and attributes + */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_SET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG3(mbx_mem->payload, reset_addr & 0xffffffff, + reset_addr >> 32, attr); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI AP core reset address and attributes + */ +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + uint32_t lo_addr, hi_addr; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_AP_CORE_PROTO_ID, + SCMI_AP_CORE_RESET_ADDR_GET_MSG, token); + mbx_mem->len = SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL4(mbx_mem->payload, ret, lo_addr, hi_addr, *attr); + *reset_addr = lo_addr | (uint64_t)hi_addr << 32; + assert(mbx_mem->len == SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c new file mode 100644 index 0000000..ec749fb --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +#if HW_ASSISTED_COHERENCY +#define scmi_lock_init(lock) +#define scmi_lock_get(lock) spin_lock(lock) +#define scmi_lock_release(lock) spin_unlock(lock) +#else +#define scmi_lock_init(lock) bakery_lock_init(lock) +#define scmi_lock_get(lock) bakery_lock_get(lock) +#define scmi_lock_release(lock) bakery_lock_release(lock) +#endif + + +/* + * Private helper function to get exclusive access to SCMI channel. + */ +void scmi_get_channel(scmi_channel_t *ch) +{ + assert(ch->lock); + scmi_lock_get(ch->lock); + + /* Make sure any previous command has finished */ + assert(SCMI_IS_CHANNEL_FREE( + ((mailbox_mem_t *)(ch->info->scmi_mbx_mem))->status)); +} + +/* + * Private helper function to transfer ownership of channel from AP to SCP. + */ +void scmi_send_sync_command(scmi_channel_t *ch) +{ + mailbox_mem_t *mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + + SCMI_MARK_CHANNEL_BUSY(mbx_mem->status); + + /* + * Ensure that any write to the SCMI payload area is seen by SCP before + * we write to the doorbell register. If these 2 writes were reordered + * by the CPU then SCP would read stale payload data + */ + dmbst(); + + ch->info->ring_doorbell(ch->info); + /* + * Ensure that the write to the doorbell register is ordered prior to + * checking whether the channel is free. + */ + dmbsy(); + + /* Wait for channel to be free */ + while (!SCMI_IS_CHANNEL_FREE(mbx_mem->status)) + ; + + /* + * Ensure that any read to the SCMI payload area is done after reading + * mailbox status. If these 2 reads were reordered then the CPU would + * read invalid payload data + */ + dmbld(); +} + +/* + * Private helper function to release exclusive access to SCMI channel. + */ +void scmi_put_channel(scmi_channel_t *ch) +{ + /* Make sure any previous command has finished */ + assert(SCMI_IS_CHANNEL_FREE( + ((mailbox_mem_t *)(ch->info->scmi_mbx_mem))->status)); + + assert(ch->lock); + scmi_lock_release(ch->lock); +} + +/* + * API to query the SCMI protocol version. + */ +int scmi_proto_version(void *p, uint32_t proto_id, uint32_t *version) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(proto_id, SCMI_PROTO_VERSION_MSG, + token); + mbx_mem->len = SCMI_PROTO_VERSION_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *version); + assert(mbx_mem->len == SCMI_PROTO_VERSION_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to query the protocol message attributes for a SCMI protocol. + */ +int scmi_proto_msg_attr(void *p, uint32_t proto_id, + uint32_t command_id, uint32_t *attr) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(proto_id, + SCMI_PROTO_MSG_ATTR_MSG, token); + mbx_mem->len = SCMI_PROTO_MSG_ATTR_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG1(mbx_mem->payload, command_id); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *attr); + assert(mbx_mem->len == SCMI_PROTO_MSG_ATTR_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * SCMI Driver initialization API. Returns initialized channel on success + * or NULL on error. The return type is an opaque void pointer. + */ +void *scmi_init(scmi_channel_t *ch) +{ + uint32_t version; + int ret; + + assert(ch && ch->info); + assert(ch->info->db_reg_addr); + assert(ch->info->db_modify_mask); + assert(ch->info->db_preserve_mask); + assert(ch->info->ring_doorbell != NULL); + + assert(ch->lock); + + scmi_lock_init(ch->lock); + + ch->is_initialized = 1; + + ret = scmi_proto_version(ch, SCMI_PWR_DMN_PROTO_ID, &version); + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI power domain protocol version message failed\n"); + goto error; + } + + if (!is_scmi_version_compatible(SCMI_PWR_DMN_PROTO_VER, version)) { + WARN("SCMI power domain protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_PWR_DMN_PROTO_VER); + goto error; + } + + VERBOSE("SCMI power domain protocol version 0x%x detected\n", version); + + ret = scmi_proto_version(ch, SCMI_SYS_PWR_PROTO_ID, &version); + if ((ret != SCMI_E_SUCCESS)) { + WARN("SCMI system power protocol version message failed\n"); + goto error; + } + + if (!is_scmi_version_compatible(SCMI_SYS_PWR_PROTO_VER, version)) { + WARN("SCMI system power management protocol version 0x%x incompatible with driver version 0x%x\n", + version, SCMI_SYS_PWR_PROTO_VER); + goto error; + } + + VERBOSE("SCMI system power management protocol version 0x%x detected\n", + version); + + INFO("SCMI driver initialized\n"); + + return (void *)ch; + +error: + ch->is_initialized = 0; + return NULL; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h new file mode 100644 index 0000000..a684ca5 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_PRIVATE_H +#define SCMI_PRIVATE_H + +#include + +/* + * SCMI power domain management protocol message and response lengths. It is + * calculated as sum of length in bytes of the message header (4) and payload + * area (the number of bytes of parameters or return values in the payload). + */ +#define SCMI_PROTO_VERSION_MSG_LEN 4 +#define SCMI_PROTO_VERSION_RESP_LEN 12 + +#define SCMI_PROTO_MSG_ATTR_MSG_LEN 8 +#define SCMI_PROTO_MSG_ATTR_RESP_LEN 12 + +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG_LEN 16 +#define SCMI_AP_CORE_RESET_ADDR_SET_RESP_LEN 8 + +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG_LEN 4 +#define SCMI_AP_CORE_RESET_ADDR_GET_RESP_LEN 20 + +#define SCMI_PWR_STATE_SET_MSG_LEN 16 +#define SCMI_PWR_STATE_SET_RESP_LEN 8 + +#define SCMI_PWR_STATE_GET_MSG_LEN 8 +#define SCMI_PWR_STATE_GET_RESP_LEN 12 + +#define SCMI_SYS_PWR_STATE_SET_MSG_LEN 12 +#define SCMI_SYS_PWR_STATE_SET_RESP_LEN 8 + +#define SCMI_SYS_PWR_STATE_GET_MSG_LEN 4 +#define SCMI_SYS_PWR_STATE_GET_RESP_LEN 12 + +/* SCMI message header format bit field */ +#define SCMI_MSG_ID_SHIFT 0 +#define SCMI_MSG_ID_WIDTH 8 +#define SCMI_MSG_ID_MASK ((1 << SCMI_MSG_ID_WIDTH) - 1) + +#define SCMI_MSG_TYPE_SHIFT 8 +#define SCMI_MSG_TYPE_WIDTH 2 +#define SCMI_MSG_TYPE_MASK ((1 << SCMI_MSG_TYPE_WIDTH) - 1) + +#define SCMI_MSG_PROTO_ID_SHIFT 10 +#define SCMI_MSG_PROTO_ID_WIDTH 8 +#define SCMI_MSG_PROTO_ID_MASK ((1 << SCMI_MSG_PROTO_ID_WIDTH) - 1) + +#define SCMI_MSG_TOKEN_SHIFT 18 +#define SCMI_MSG_TOKEN_WIDTH 10 +#define SCMI_MSG_TOKEN_MASK ((1 << SCMI_MSG_TOKEN_WIDTH) - 1) + + +/* SCMI mailbox flags */ +#define SCMI_FLAG_RESP_POLL 0 +#define SCMI_FLAG_RESP_INT 1 + +/* SCMI power domain protocol `POWER_STATE_SET` message flags */ +#define SCMI_PWR_STATE_SET_FLAG_SYNC 0 +#define SCMI_PWR_STATE_SET_FLAG_ASYNC 1 + +/* + * Helper macro to create an SCMI message header given protocol, message id + * and token. + */ +#define SCMI_MSG_CREATE(_protocol, _msg_id, _token) \ + ((((_protocol) & SCMI_MSG_PROTO_ID_MASK) << SCMI_MSG_PROTO_ID_SHIFT) | \ + (((_msg_id) & SCMI_MSG_ID_MASK) << SCMI_MSG_ID_SHIFT) | \ + (((_token) & SCMI_MSG_TOKEN_MASK) << SCMI_MSG_TOKEN_SHIFT)) + +/* Helper macro to get the token from a SCMI message header */ +#define SCMI_MSG_GET_TOKEN(_msg) \ + (((_msg) >> SCMI_MSG_TOKEN_SHIFT) & SCMI_MSG_TOKEN_MASK) + +/* SCMI Channel Status bit fields */ +#define SCMI_CH_STATUS_RES0_MASK 0xFFFFFFFE +#define SCMI_CH_STATUS_FREE_SHIFT 0 +#define SCMI_CH_STATUS_FREE_WIDTH 1 +#define SCMI_CH_STATUS_FREE_MASK ((1 << SCMI_CH_STATUS_FREE_WIDTH) - 1) + +/* Helper macros to check and write the channel status */ +#define SCMI_IS_CHANNEL_FREE(status) \ + (!!(((status) >> SCMI_CH_STATUS_FREE_SHIFT) & SCMI_CH_STATUS_FREE_MASK)) + +#define SCMI_MARK_CHANNEL_BUSY(status) do { \ + assert(SCMI_IS_CHANNEL_FREE(status)); \ + (status) &= ~(SCMI_CH_STATUS_FREE_MASK << \ + SCMI_CH_STATUS_FREE_SHIFT); \ + } while (0) + +/* Helper macros to copy arguments to the mailbox payload */ +#define SCMI_PAYLOAD_ARG1(payld_arr, arg1) \ + mmio_write_32((uintptr_t)&payld_arr[0], arg1) + +#define SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2) do { \ + SCMI_PAYLOAD_ARG1(payld_arr, arg1); \ + mmio_write_32((uintptr_t)&payld_arr[1], arg2); \ + } while (0) + +#define SCMI_PAYLOAD_ARG3(payld_arr, arg1, arg2, arg3) do { \ + SCMI_PAYLOAD_ARG2(payld_arr, arg1, arg2); \ + mmio_write_32((uintptr_t)&payld_arr[2], arg3); \ + } while (0) + +/* Helper macros to read return values from the mailbox payload */ +#define SCMI_PAYLOAD_RET_VAL1(payld_arr, val1) \ + (val1) = mmio_read_32((uintptr_t)&payld_arr[0]) + +#define SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2) do { \ + SCMI_PAYLOAD_RET_VAL1(payld_arr, val1); \ + (val2) = mmio_read_32((uintptr_t)&payld_arr[1]); \ + } while (0) + +#define SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3) do { \ + SCMI_PAYLOAD_RET_VAL2(payld_arr, val1, val2); \ + (val3) = mmio_read_32((uintptr_t)&payld_arr[2]); \ + } while (0) + +#define SCMI_PAYLOAD_RET_VAL4(payld_arr, val1, val2, val3, val4) do { \ + SCMI_PAYLOAD_RET_VAL3(payld_arr, val1, val2, val3); \ + (val4) = mmio_read_32((uintptr_t)&payld_arr[3]); \ + } while (0) + +/* + * Private data structure for representing the mailbox memory layout. Refer + * the SCMI specification for more details. + */ +typedef struct mailbox_mem { + uint32_t res_a; /* Reserved */ + volatile uint32_t status; + uint64_t res_b; /* Reserved */ + uint32_t flags; + volatile uint32_t len; + volatile uint32_t msg_header; + uint32_t payload[]; +} mailbox_mem_t; + + +/* Private APIs for use within SCMI driver */ +void scmi_get_channel(scmi_channel_t *ch); +void scmi_send_sync_command(scmi_channel_t *ch); +void scmi_put_channel(scmi_channel_t *ch); + +static inline void validate_scmi_channel(scmi_channel_t *ch) +{ + assert(ch && ch->is_initialized); + assert(ch->info && ch->info->scmi_mbx_mem); +} + +/* + * SCMI vendor specific protocol + */ +#define SCMI_SYS_VENDOR_EXT_PROTO_ID 0x80 + +#endif /* SCMI_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c new file mode 100644 index 0000000..a342aa8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI power domain power state. + */ +int scmi_pwr_state_set(void *p, uint32_t domain_id, + uint32_t scmi_pwr_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + + /* + * Only asynchronous mode of `set power state` command is allowed on + * application processors. + */ + uint32_t pwr_state_set_msg_flag = SCMI_PWR_STATE_SET_FLAG_ASYNC; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_SET_MSG, token); + mbx_mem->len = SCMI_PWR_STATE_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG3(mbx_mem->payload, pwr_state_set_msg_flag, + domain_id, scmi_pwr_state); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_PWR_STATE_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI power domain power state. + */ +int scmi_pwr_state_get(void *p, uint32_t domain_id, + uint32_t *scmi_pwr_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_GET_MSG, token); + mbx_mem->len = SCMI_PWR_STATE_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG1(mbx_mem->payload, domain_id); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *scmi_pwr_state); + assert(mbx_mem->len == SCMI_PWR_STATE_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c new file mode 100644 index 0000000..c8e62d1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" + +/* + * API to set the SCMI system power state + */ +int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_SET_MSG, token); + mbx_mem->len = SCMI_SYS_PWR_STATE_SET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + SCMI_PAYLOAD_ARG2(mbx_mem->payload, flags, system_state); + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + assert(mbx_mem->len == SCMI_SYS_PWR_STATE_SET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} + +/* + * API to get the SCMI system power state + */ +int scmi_sys_pwr_state_get(void *p, uint32_t *system_state) +{ + mailbox_mem_t *mbx_mem; + unsigned int token = 0; + int ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_GET_MSG, token); + mbx_mem->len = SCMI_SYS_PWR_STATE_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL2(mbx_mem->payload, ret, *system_state); + assert(mbx_mem->len == SCMI_SYS_PWR_STATE_GET_RESP_LEN); + assert(token == SCMI_MSG_GET_TOKEN(mbx_mem->msg_header)); + + scmi_put_channel(ch); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c new file mode 100644 index 0000000..f185424 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "scmi_private.h" +#include "scmi_sq.h" + +#include + +/* SCMI messge ID to get the available DRAM region */ +#define SCMI_VENDOR_EXT_MEMINFO_GET_MSG 0x3 + +#define SCMI_VENDOR_EXT_MEMINFO_GET_MSG_LEN 4 + +/* + * API to get the available DRAM region + */ +int scmi_get_draminfo(void *p, struct draminfo *info) +{ + mailbox_mem_t *mbx_mem; + int token = 0, ret; + scmi_channel_t *ch = (scmi_channel_t *)p; + struct dram_info_resp response; + + validate_scmi_channel(ch); + + scmi_get_channel(ch); + + mbx_mem = (mailbox_mem_t *)(ch->info->scmi_mbx_mem); + mbx_mem->msg_header = SCMI_MSG_CREATE(SCMI_SYS_VENDOR_EXT_PROTO_ID, + SCMI_VENDOR_EXT_MEMINFO_GET_MSG, token); + mbx_mem->len = SCMI_VENDOR_EXT_MEMINFO_GET_MSG_LEN; + mbx_mem->flags = SCMI_FLAG_RESP_POLL; + + scmi_send_sync_command(ch); + + /* + * 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(); + + /* Get the return values */ + SCMI_PAYLOAD_RET_VAL1(mbx_mem->payload, ret); + + memcpy(&response, (void *)mbx_mem->payload, sizeof(response)); + + scmi_put_channel(ch); + + *info = response.info; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h new file mode 100644 index 0000000..aee1a3a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_SQ_H +#define SCMI_SQ_H + +#include +#include + +#include + +/* Structure to represent available DRAM region */ +struct dram_info_resp { + int status; + int reserved; + struct draminfo info; +}; + +/* API to get the available DRAM region */ +int scmi_get_draminfo(void *p, struct draminfo *info); + +#endif /* SCMI_SQ_H */ diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c b/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c new file mode 100644 index 0000000..74121b4 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* ID of the MHU slot used for the BOM protocol */ +#define BOM_MHU_SLOT_ID 0 + +/* Boot commands sent from AP -> SCP */ +#define BOOT_CMD_INFO 0x00 +#define BOOT_CMD_DATA 0x01 + +/* BOM command header */ +typedef struct { + uint32_t id : 8; + uint32_t reserved : 24; +} bom_cmd_t; + +typedef struct { + uint32_t image_size; + uint32_t checksum; +} cmd_info_payload_t; + +/* + * Unlike the SCPI protocol, the boot protocol uses the same memory region + * for both AP -> SCP and SCP -> AP transfers; define the address of this... + */ +#define BOM_SHARED_MEM PLAT_CSS_SCP_COM_SHARED_MEM_BASE +#define BOM_CMD_HEADER ((bom_cmd_t *) BOM_SHARED_MEM) +#define BOM_CMD_PAYLOAD ((void *) (BOM_SHARED_MEM + sizeof(bom_cmd_t))) + +typedef struct { + /* Offset from the base address of the Trusted RAM */ + uint32_t offset; + uint32_t block_size; +} cmd_data_payload_t; + +/* + * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31 + * usually resides except when ARM_BL31_IN_DRAM is + * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into shared RAM and + * the fw_config. + */ +CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2); +CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2); + +CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow); +CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow); + +static void scp_boot_message_start(void) +{ + mhu_secure_message_start(BOM_MHU_SLOT_ID); +} + +static void scp_boot_message_send(size_t payload_size) +{ + /* Ensure that any write to the BOM 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(); + + /* Send command to SCP */ + mhu_secure_message_send(BOM_MHU_SLOT_ID); +} + +static uint32_t scp_boot_message_wait(size_t size) +{ + uint32_t mhu_status; + + mhu_status = mhu_secure_message_wait(); + + /* Expect an SCP Boot Protocol message, reject any other protocol */ + if (mhu_status != (1 << BOM_MHU_SLOT_ID)) { + ERROR("MHU: Unexpected protocol (MHU status: 0x%x)\n", + mhu_status); + panic(); + } + + /* Ensure that any read to the BOM payload area is done after reading + * the MHU register. If these 2 reads were reordered then the CPU would + * read invalid payload data */ + dmbld(); + + return *(uint32_t *) BOM_SHARED_MEM; +} + +static void scp_boot_message_end(void) +{ + mhu_secure_message_end(BOM_MHU_SLOT_ID); +} + +int css_scp_boot_image_xfer(void *image, unsigned int image_size) +{ + uint32_t response; + uint32_t checksum; + cmd_info_payload_t *cmd_info_payload; + cmd_data_payload_t *cmd_data_payload; + + assert((uintptr_t) image == SCP_BL2_BASE); + + if ((image_size == 0) || (image_size % 4 != 0)) { + ERROR("Invalid size for the SCP_BL2 image. Must be a multiple of " + "4 bytes and not zero (current size = 0x%x)\n", + image_size); + return -1; + } + + /* Extract the checksum from the image */ + checksum = *(uint32_t *) image; + image = (char *) image + sizeof(checksum); + image_size -= sizeof(checksum); + + mhu_secure_init(); + + VERBOSE("Send info about the SCP_BL2 image to be transferred to SCP\n"); + + /* + * Send information about the SCP firmware image about to be transferred + * to SCP + */ + scp_boot_message_start(); + + BOM_CMD_HEADER->id = BOOT_CMD_INFO; + cmd_info_payload = BOM_CMD_PAYLOAD; + cmd_info_payload->image_size = image_size; + cmd_info_payload->checksum = checksum; + + scp_boot_message_send(sizeof(*cmd_info_payload)); +#if CSS_DETECT_PRE_1_7_0_SCP + { + const uint32_t deprecated_scp_nack_cmd = 0x404; + uint32_t mhu_status; + + VERBOSE("Detecting SCP version incompatibility\n"); + + mhu_status = mhu_secure_message_wait(); + if (mhu_status == deprecated_scp_nack_cmd) { + ERROR("Detected an incompatible version of the SCP firmware.\n"); + ERROR("Only versions from v1.7.0 onwards are supported.\n"); + ERROR("Please update the SCP firmware.\n"); + return -1; + } + + VERBOSE("SCP version looks OK\n"); + } +#endif /* CSS_DETECT_PRE_1_7_0_SCP */ + response = scp_boot_message_wait(sizeof(response)); + scp_boot_message_end(); + + if (response != 0) { + ERROR("SCP BOOT_CMD_INFO returned error %u\n", response); + return -1; + } + + VERBOSE("Transferring SCP_BL2 image to SCP\n"); + + /* Transfer SCP_BL2 image to SCP */ + scp_boot_message_start(); + + BOM_CMD_HEADER->id = BOOT_CMD_DATA; + cmd_data_payload = BOM_CMD_PAYLOAD; + cmd_data_payload->offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE; + cmd_data_payload->block_size = image_size; + + scp_boot_message_send(sizeof(*cmd_data_payload)); + response = scp_boot_message_wait(sizeof(response)); + scp_boot_message_end(); + + if (response != 0) { + ERROR("SCP BOOT_CMD_DATA returned error %u\n", response); + return -1; + } + + return 0; +} + +int css_scp_boot_ready(void) +{ + VERBOSE("Waiting for SCP to signal it is ready to go on\n"); + + /* Wait for SCP to signal it's ready */ + return scpi_wait_ready(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c new file mode 100644 index 0000000..5de2604 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * This file implements the SCP helper functions using SCMI protocol. + */ + +/* + * SCMI power state parameter bit field encoding for ARM CSS platforms. + * + * 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 handles for invoking the SCMI driver APIs after the driver + * has been initialized. + */ +static void *scmi_handles[PLAT_ARM_SCMI_CHANNEL_COUNT]; + +/* The global SCMI channels array */ +static scmi_channel_t scmi_channels[PLAT_ARM_SCMI_CHANNEL_COUNT]; + +/* + * Channel ID for the default SCMI channel. + * The default channel is used to issue SYSTEM level SCMI requests and is + * initialized to the channel which has the boot cpu as its resource. + */ +static uint32_t default_scmi_channel_id; + +/* + * TODO: Allow use of channel specific lock instead of using a single lock for + * all the channels. + */ +ARM_SCMI_INSTANTIATE_LOCK; + +/* + * Function to obtain the SCMI Domain ID and SCMI Channel number from the linear + * core position. The SCMI Channel number is encoded in the upper 16 bits and + * the Domain ID is encoded in the lower 16 bits in each entry of the mapping + * array exported by the platform. + */ +static void css_scp_core_pos_to_scmi_channel(unsigned int core_pos, + unsigned int *scmi_domain_id, unsigned int *scmi_channel_id) +{ + unsigned int composite_id; + + composite_id = plat_css_core_pos_to_scmi_dmn_id_map[core_pos]; + + *scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id); + *scmi_domain_id = GET_SCMI_DOMAIN_ID(composite_id); +} + +/* + * Helper function to suspend a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_suspend(const struct psci_power_state *target_state) +{ + int ret; + + /* At least power domain level 0 should be specified to be suspended */ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* Check if power down at system power domain level is requested */ + if (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) { + /* Issue SCMI command for SYSTEM_SUSPEND on all SCMI channels */ + ret = scmi_sys_pwr_state_set( + scmi_handles[default_scmi_channel_id], + SCMI_SYS_PWR_FORCEFUL_REQ, SCMI_SYS_PWR_SUSPEND); + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI system power domain suspend return 0x%x unexpected\n", + ret); + panic(); + } + return; + } +#if !HW_ASSISTED_COHERENCY + unsigned int lvl, channel_id, domain_id; + uint32_t scmi_pwr_state = 0; + /* + * If we reach here, then assert that power down at system power domain + * level is running. + */ + assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN); + + /* For level 0, specify `scmi_power_state_sleep` as the power state */ + SCMI_SET_PWR_STATE_LVL(scmi_pwr_state, ARM_PWR_LVL0, + scmi_power_state_sleep); + + for (lvl = ARM_PWR_LVL1; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + if (target_state->pwr_domain_state[lvl] == ARM_LOCAL_STATE_RUN) + break; + + assert(target_state->pwr_domain_state[lvl] == + ARM_LOCAL_STATE_OFF); + /* + * Specify `scmi_power_state_off` as power state for higher + * levels. + */ + 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); + + css_scp_core_pos_to_scmi_channel(plat_my_core_pos(), + &domain_id, &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, scmi_pwr_state); + + if (ret != SCMI_E_SUCCESS) { + ERROR("SCMI set power state command return 0x%x unexpected\n", + ret); + panic(); + } +#endif +} + +/* + * Helper function to turn off a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_off(const struct psci_power_state *target_state) +{ + unsigned int lvl = 0, channel_id, domain_id; + int ret; + uint32_t scmi_pwr_state = 0; + + /* At-least the CPU level should be specified to be OFF */ + assert(target_state->pwr_domain_state[ARM_PWR_LVL0] == + ARM_LOCAL_STATE_OFF); + + /* PSCI CPU OFF cannot be used to turn OFF system power domain */ + assert(css_system_pwr_state(target_state) == ARM_LOCAL_STATE_RUN); + + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) { + if (target_state->pwr_domain_state[lvl] == ARM_LOCAL_STATE_RUN) + break; + + assert(target_state->pwr_domain_state[lvl] == + ARM_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); + + css_scp_core_pos_to_scmi_channel(plat_my_core_pos(), + &domain_id, &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, 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 css_scp_on(u_register_t mpidr) +{ + unsigned int lvl = 0, channel_id, core_pos, domain_id; + int ret; + 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 = (unsigned int)plat_core_pos_by_mpidr(mpidr); + assert(core_pos < PLATFORM_CORE_COUNT); + + css_scp_core_pos_to_scmi_channel(core_pos, &domain_id, + &channel_id); + ret = scmi_pwr_state_set(scmi_handles[channel_id], + domain_id, 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 get the power state of a power domain node as reported + * by the SCP. + */ +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) +{ + int ret; + uint32_t scmi_pwr_state = 0, lvl_state; + unsigned int channel_id, cpu_idx, domain_id; + + /* We don't support get power state at the system power domain level */ + if ((power_level > PLAT_MAX_PWR_LVL) || + (power_level == CSS_SYSTEM_PWR_DMN_LVL)) { + WARN("Invalid power level %u specified for SCMI get power state\n", + power_level); + return PSCI_E_INVALID_PARAMS; + } + + cpu_idx = (unsigned int)plat_core_pos_by_mpidr(mpidr); + assert(cpu_idx < PLATFORM_CORE_COUNT); + + css_scp_core_pos_to_scmi_channel(cpu_idx, &domain_id, &channel_id); + ret = scmi_pwr_state_get(scmi_handles[channel_id], + domain_id, &scmi_pwr_state); + + if (ret != SCMI_E_SUCCESS) { + WARN("SCMI get power state command return 0x%x unexpected\n", + ret); + return PSCI_E_INVALID_PARAMS; + } + + /* + * Find the maximum power level described in the get power state + * command. If it is less than the requested power level, then assume + * the requested power level is ON. + */ + if (SCMI_GET_PWR_STATE_MAX_PWR_LVL(scmi_pwr_state) < power_level) + return HW_ON; + + lvl_state = SCMI_GET_PWR_STATE_LVL(scmi_pwr_state, power_level); + if (lvl_state == scmi_power_state_on) + return HW_ON; + + assert((lvl_state == scmi_power_state_off) || + (lvl_state == scmi_power_state_sleep)); + return HW_OFF; +} + +void __dead2 css_scp_system_off(int state) +{ + int ret; + + /* + * Disable GIC CPU interface to prevent pending interrupt from waking + * up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* + * Issue SCMI command. First issue a graceful + * request and if that fails force the request. + */ + ret = scmi_sys_pwr_state_set(scmi_handles[default_scmi_channel_id], + 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("CSS set power state: operation not handled.\n"); + panic(); +} + +/* + * Helper function to shutdown the system via SCMI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + css_scp_system_off(SCMI_SYS_PWR_SHUTDOWN); +} + +/* + * Helper function to reset the system via SCMI. + */ +void __dead2 css_scp_sys_reboot(void) +{ + css_scp_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_arm_pwrc_setup(void) +{ + unsigned int composite_id, idx; + + for (idx = 0; idx < PLAT_ARM_SCMI_CHANNEL_COUNT; idx++) { + INFO("Initializing SCMI driver on channel %d\n", idx); + + scmi_channels[idx].info = plat_css_get_scmi_info(idx); + scmi_channels[idx].lock = ARM_SCMI_LOCK_GET_INSTANCE; + scmi_handles[idx] = scmi_init(&scmi_channels[idx]); + + if (scmi_handles[idx] == NULL) { + ERROR("SCMI Initialization failed on channel %d\n", idx); + panic(); + } + + if (scmi_ap_core_init(&scmi_channels[idx]) < 0) { + ERROR("SCMI AP core protocol initialization failed\n"); + panic(); + } + } + + composite_id = plat_css_core_pos_to_scmi_dmn_id_map[plat_my_core_pos()]; + default_scmi_channel_id = GET_SCMI_CHANNEL_ID(composite_id); +} + +/****************************************************************************** + * This function overrides the default definition for ARM platforms. Initialize + * the SCMI driver, query capability via SCMI and modify the PSCI capability + * based on that. + *****************************************************************************/ +const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops) +{ + uint32_t msg_attr; + int ret; + void *scmi_handle = scmi_handles[default_scmi_channel_id]; + + assert(scmi_handle); + + /* Check that power domain POWER_STATE_SET message is supported */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_SET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) { + ERROR("Set power state command is not supported by SCMI\n"); + panic(); + } + + /* + * Don't support PSCI NODE_HW_STATE call if SCMI doesn't support + * POWER_STATE_GET message. + */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_PWR_DMN_PROTO_ID, + SCMI_PWR_STATE_GET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) + ops->get_node_hw_state = NULL; + + /* Check if the SCMI SYSTEM_POWER_STATE_SET message is supported */ + ret = scmi_proto_msg_attr(scmi_handle, SCMI_SYS_PWR_PROTO_ID, + SCMI_SYS_PWR_STATE_SET_MSG, &msg_attr); + if (ret != SCMI_E_SUCCESS) { + /* System power management operations are not supported */ + ops->system_off = NULL; + ops->system_reset = NULL; + ops->get_sys_suspend_power_state = NULL; + } else { + if (!(msg_attr & SCMI_SYS_PWR_SUSPEND_SUPPORTED)) { + /* + * System power management protocol is available, but + * it does not support SYSTEM SUSPEND. + */ + ops->get_sys_suspend_power_state = NULL; + } + if (!(msg_attr & SCMI_SYS_PWR_WARM_RESET_SUPPORTED)) { + /* + * WARM reset is not available. + */ + ops->system_reset2 = NULL; + } + } + + return ops; +} + +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie) +{ + if (is_vendor || (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET)) + return PSCI_E_INVALID_PARAMS; + + css_scp_system_off(SCMI_SYS_PWR_WARM_RESET); + /* + * css_scp_system_off cannot return (it is a __dead function), + * but css_system_reset2 has to return some value, even in + * this case. + */ + return 0; +} + +#if PROGRAMMABLE_RESET_ADDRESS +void plat_arm_program_trusted_mailbox(uintptr_t address) +{ + int ret, i; + + for (i = 0; i < PLAT_ARM_SCMI_CHANNEL_COUNT; i++) { + assert(scmi_handles[i]); + + ret = scmi_ap_core_set_reset_addr(scmi_handles[i], address, + SCMI_AP_CORE_LOCK_ATTR); + if (ret != SCMI_E_SUCCESS) { + ERROR("CSS: Failed to program reset address: %d\n", ret); + panic(); + } + } +} +#endif diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c new file mode 100644 index 0000000..b4019ce --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * This file implements the SCP power management functions using SCPI protocol. + */ + +/* + * Helper function to inform power down state to SCP. + */ +void css_scp_suspend(const struct psci_power_state *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 (css_system_pwr_state(target_state) == ARM_LOCAL_STATE_OFF) + system_state = scpi_power_retention; + + /* Cluster is to be turned off, so disable coherency */ + if (CSS_CLUSTER_PWR_STATE(target_state) == ARM_LOCAL_STATE_OFF) + cluster_state = scpi_power_off; + + /* + * Ask the SCP to power down the appropriate components depending upon + * their state. + */ + scpi_set_css_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. + */ +void css_scp_off(const struct psci_power_state *target_state) +{ + css_scp_suspend(target_state); +} + +/* + * Helper function to turn ON a CPU power domain and its parent power domains + * if applicable. + */ +void css_scp_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_css_power_state(mpidr, scpi_power_on, scpi_power_on, + scpi_power_on); +} + +/* + * Helper function to get the power state of a power domain node as reported + * by the SCP. + */ +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level) +{ + int rc, element; + unsigned int cpu_state, cluster_state; + + /* + * 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; + + /* Query SCP */ + rc = scpi_get_css_power_state(mpidr, &cpu_state, &cluster_state); + if (rc != 0) + return PSCI_E_INVALID_PARAMS; + + /* Map power states of CPU and cluster to expected PSCI return codes */ + if (power_level == ARM_PWR_LVL0) { + /* + * The CPU state returned by SCP is an 8-bit bit mask + * corresponding to each CPU in the cluster + */ +#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. + */ + element = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; +#else + element = mpidr & MPIDR_AFFLVL_MASK; +#endif /* ARM_PLAT_MT */ + return CSS_CPU_PWR_STATE(cpu_state, element) == + CSS_CPU_PWR_STATE_ON ? HW_ON : HW_OFF; + } else { + assert(cluster_state == CSS_CLUSTER_PWR_STATE_ON || + cluster_state == CSS_CLUSTER_PWR_STATE_OFF); + return cluster_state == CSS_CLUSTER_PWR_STATE_ON ? HW_ON : + HW_OFF; + } +} + +/* + * Helper function to shutdown the system via SCPI. + */ +void __dead2 css_scp_sys_shutdown(void) +{ + uint32_t response; + + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* Send the power down request to the SCP */ + response = scpi_sys_power_state(scpi_system_shutdown); + + if (response != SCP_OK) { + ERROR("CSS System Off: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Off: operation not handled.\n"); + panic(); +} + +/* + * Helper function to reset the system via SCPI. + */ +void __dead2 css_scp_sys_reboot(void) +{ + uint32_t response; + + /* + * Disable GIC CPU interface to prevent pending interrupt + * from waking up the AP from WFI. + */ + plat_arm_gic_cpuif_disable(); + + /* Send the system reset request to the SCP */ + response = scpi_sys_power_state(scpi_system_reboot); + + if (response != SCP_OK) { + ERROR("CSS System Reset: SCP error %u.\n", response); + panic(); + } + wfi(); + ERROR("CSS System Reset: operation not handled.\n"); + panic(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c b/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c new file mode 100644 index 0000000..e42ee10 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scp/css_sds.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +int css_scp_boot_image_xfer(void *image, unsigned int image_size) +{ + int ret; + unsigned int image_offset, image_flags; + + ret = sds_init(); + if (ret != SDS_OK) { + ERROR("SCP SDS initialization failed\n"); + panic(); + } + + VERBOSE("Writing SCP image metadata\n"); + image_offset = (uintptr_t) image - ARM_TRUSTED_SRAM_BASE; + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_ADDR_OFFSET, + &image_offset, SDS_SCP_IMG_ADDR_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_SIZE_OFFSET, + &image_size, SDS_SCP_IMG_SIZE_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + VERBOSE("Marking SCP image metadata as valid\n"); + image_flags = SDS_SCP_IMG_VALID_FLAG_BIT; + ret = sds_struct_write(SDS_SCP_IMG_STRUCT_ID, SDS_SCP_IMG_FLAG_OFFSET, + &image_flags, SDS_SCP_IMG_FLAG_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) + goto sds_fail; + + return 0; +sds_fail: + ERROR("SCP SDS write to SCP IMG struct failed\n"); + panic(); +} + +/* + * API to wait for SCP to signal till it's ready after booting the transferred + * image. + */ +int css_scp_boot_ready(void) +{ + uint32_t scp_feature_availability_flags; + int ret, retry = CSS_SCP_READY_10US_RETRIES; + + + VERBOSE("Waiting for SCP RAM to complete its initialization process\n"); + + /* Wait for the SCP RAM Firmware to complete its initialization process */ + while (retry > 0) { + ret = sds_struct_read(SDS_FEATURE_AVAIL_STRUCT_ID, 0, + &scp_feature_availability_flags, + SDS_FEATURE_AVAIL_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret == SDS_ERR_STRUCT_NOT_FINALIZED) + continue; + + if (ret != SDS_OK) { + ERROR(" sds_struct_read failed\n"); + panic(); + } + + if (scp_feature_availability_flags & + SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT) + return 0; + + udelay(10); + retry--; + } + + ERROR("Timeout of %d ms expired waiting for SCP RAM Ready flag\n", + CSS_SCP_READY_10US_RETRIES/100); + + plat_panic_handler(); +} diff --git a/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c b/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c new file mode 100644 index 0000000..416356b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#define SCPI_SHARED_MEM_SCP_TO_AP PLAT_CSS_SCP_COM_SHARED_MEM_BASE +#define SCPI_SHARED_MEM_AP_TO_SCP (PLAT_CSS_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 int 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); + return -1; + } + + /* + * 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)); + + return 0; +} + +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; + int rc; + + VERBOSE("Waiting for SCP_READY command...\n"); + + /* Get a message from the SCP */ + scpi_secure_message_start(); + rc = scpi_secure_message_receive(&scpi_cmd); + scpi_secure_message_end(); + + /* If no message was received, don't send a response */ + if (rc != 0) + return rc; + + /* 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 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_css_power_state(unsigned int mpidr, + scpi_power_state_t cpu_state, scpi_power_state_t cluster_state, + scpi_power_state_t css_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 |= css_state << 16; + + scpi_secure_message_start(); + + /* Populate the command header */ + cmd = SCPI_CMD_HEADER_AP_TO_SCP; + cmd->id = SCPI_CMD_SET_CSS_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 CSS 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_css_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 + */ +#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. + */ + cpu = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; +#else + cpu = mpidr & MPIDR_AFFLVL_MASK; + cluster = (mpidr >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK; +#endif /* ARM_PLAT_MT */ + 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_CSS_POWER_STATE; + + /* + * Send message and wait for SCP's response + */ + scpi_secure_message_send(0); + if (scpi_secure_message_receive(&response) != 0) + goto exit; + + 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_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)); + + /* If no response is received, fill in an error status */ + if (scpi_secure_message_receive(&response) != 0) + response.status = SCP_E_TIMEOUT; + + scpi_secure_message_end(); + + return response.status; +} diff --git a/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S b/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S new file mode 100644 index 0000000..13ff0e1 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "../sds_private.h" + + .globl sds_get_primary_cpu_id + + /* + * int sds_get_primary_cpu_id(void); + * Return the primary CPU ID from SDS Structure + * Returns CPUID on success or -1 on failure + */ +func sds_get_primary_cpu_id + ldr r0, =PLAT_ARM_SDS_MEM_BASE + ldr r2, =SDS_REGION_SIGNATURE + ldr r1, [r0] + ubfx r3, r1, #0, #16 + + /* Check if the SDS region signature found */ + cmp r2, r3 + bne 2f + + /* Get the structure count from region descriptor in r1 */ + ubfx r1, r1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH + cmp r1, #0 + beq 2f + add r0, r0, #SDS_REGION_DESC_SIZE + + /* Initialize the loop iterator count in r3 */ + mov r3, #0 +loop_begin: + ldrh r2, [r0] + cmp r2, #SDS_AP_CPU_INFO_STRUCT_ID + bne continue_loop + + /* We have found the required structure */ + ldr r0, [r0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)] + bx lr +continue_loop: + /* Increment the loop counter and exit loop if counter == structure count */ + add r3, r3, #0x1 + cmp r1, r3 + beq 2f + + /* Read the 2nd word in header */ + ldr r2, [r0,#4] + /* Get the structure size from header */ + ubfx r2, r2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH + /* Add the structure size and SDS HEADER SIZE to point to next header */ + add r2, r2, #SDS_HEADER_SIZE + add r0, r0, r2 + b loop_begin +2: + mov r0, #0xffffffff + bx lr +endfunc sds_get_primary_cpu_id diff --git a/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S b/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S new file mode 100644 index 0000000..3256c2b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "../sds_private.h" + + .globl sds_get_primary_cpu_id + + /* + * int sds_get_primary_cpu_id(void); + * Return the primary CPI ID from SDS Structure + * Returns CPUID on success or -1 on failure + */ +func sds_get_primary_cpu_id + mov_imm x0, PLAT_ARM_SDS_MEM_BASE + mov w2, #SDS_REGION_SIGNATURE + ldr w1, [x0] + + /* Check if the SDS region signature found */ + cmp w2, w1, uxth + b.ne 2f + + /* Get the structure count from region descriptor in `w1 */ + ubfx w1, w1, #SDS_REGION_STRUCT_COUNT_SHIFT, #SDS_REGION_STRUCT_COUNT_WIDTH + cbz w1, 2f + add x0, x0, #SDS_REGION_DESC_SIZE + + /* Initialize the loop iterator count in w3 */ + mov w3, #0 +loop_begin: + ldrh w2, [x0] + cmp w2, #SDS_AP_CPU_INFO_STRUCT_ID + b.ne continue_loop + + /* We have found the required structure */ + ldr w0, [x0,#(SDS_HEADER_SIZE + SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET)] + ret +continue_loop: + /* Increment the loop counter and exit loop if counter == structure count */ + add w3, w3, #0x1 + cmp w1, w3 + b.eq 2f + + /* Read the 2nd word in header */ + ldr w2, [x0,#4] + /* Get the structure size from header */ + ubfx x2, x2, #SDS_HEADER_STRUCT_SIZE_SHIFT, #SDS_HEADER_STRUCT_SIZE_WIDTH + /* Add the structure size and SDS HEADER SIZE to point to next header */ + add x2, x2, #SDS_HEADER_SIZE + add x0, x0, x2 + b loop_begin +2: + mov w0, #0xffffffff + ret +endfunc sds_get_primary_cpu_id diff --git a/arm-trusted-firmware/drivers/arm/css/sds/sds.c b/arm-trusted-firmware/drivers/arm/css/sds/sds.c new file mode 100644 index 0000000..1fb196c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/sds.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "sds_private.h" + +/* + * Variables used to track and maintain the state of the memory region reserved + * for usage by the SDS framework. + */ + +/* Pointer to the base of the SDS memory region */ +static uintptr_t sds_mem_base; + +/* Size of the SDS memory region in bytes */ +static size_t sds_mem_size; + +/* + * Perform some non-exhaustive tests to determine whether any of the fields + * within a Structure Header contain obviously invalid data. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +static int sds_struct_is_valid(uintptr_t header) +{ + size_t struct_size = GET_SDS_HEADER_STRUCT_SIZE(header); + + /* Zero is not a valid identifier */ + if (GET_SDS_HEADER_ID(header) == 0) + return SDS_ERR_FAIL; + + /* Check SDS Schema version */ + if (GET_SDS_HEADER_VERSION(header) == SDS_REGION_SCH_VERSION) + return SDS_ERR_FAIL; + + /* The SDS Structure sizes have to be multiple of 8 */ + if ((struct_size == 0) || ((struct_size % 8) != 0)) + return SDS_ERR_FAIL; + + if (struct_size > sds_mem_size) + return SDS_ERR_FAIL; + + return SDS_OK; +} + +/* + * Validate the SDS structure headers. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +static int validate_sds_struct_headers(void) +{ + unsigned int i, structure_count; + uintptr_t header; + + structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base); + + if (structure_count == 0) + return SDS_ERR_FAIL; + + header = sds_mem_base + SDS_REGION_DESC_SIZE; + + /* Iterate over structure headers and validate each one */ + for (i = 0; i < structure_count; i++) { + if (sds_struct_is_valid(header) != SDS_OK) { + WARN("SDS: Invalid structure header detected\n"); + return SDS_ERR_FAIL; + } + header += GET_SDS_HEADER_STRUCT_SIZE(header) + SDS_HEADER_SIZE; + } + return SDS_OK; +} + +/* + * Get the structure header pointer corresponding to the structure ID. + * Returns SDS_OK on success, SDS_ERR_STRUCT_NOT_FOUND on error. + */ +static int get_struct_header(uint32_t structure_id, struct_header_t **header) +{ + unsigned int i, structure_count; + uintptr_t current_header; + + assert(header); + + structure_count = GET_SDS_REGION_STRUCTURE_COUNT(sds_mem_base); + if (structure_count == 0) + return SDS_ERR_STRUCT_NOT_FOUND; + + current_header = ((uintptr_t)sds_mem_base) + SDS_REGION_DESC_SIZE; + + /* Iterate over structure headers to find one with a matching ID */ + for (i = 0; i < structure_count; i++) { + if (GET_SDS_HEADER_ID(current_header) == structure_id) { + *header = (struct_header_t *)current_header; + return SDS_OK; + } + current_header += GET_SDS_HEADER_STRUCT_SIZE(current_header) + + SDS_HEADER_SIZE; + } + + *header = NULL; + return SDS_ERR_STRUCT_NOT_FOUND; +} + +/* + * Check if a structure header corresponding to the structure ID exists. + * Returns SDS_OK if structure header exists else SDS_ERR_STRUCT_NOT_FOUND + * if not found. + */ +int sds_struct_exists(unsigned int structure_id) +{ + struct_header_t *header = NULL; + int ret; + + ret = get_struct_header(structure_id, &header); + if (ret == SDS_OK) { + assert(header); + } + + return ret; +} + +/* + * Read from field in the structure corresponding to `structure_id`. + * `fld_off` is the offset to the field in the structure and `mode` + * indicates whether cache maintenance need to performed prior to the read. + * The `data` is the pointer to store the read data of size specified by `size`. + * Returns SDS_OK on success or corresponding error codes on failure. + */ +int sds_struct_read(uint32_t structure_id, unsigned int fld_off, + void *data, size_t size, sds_access_mode_t mode) +{ + int status; + uintptr_t field_base; + struct_header_t *header = NULL; + + if (!data) + return SDS_ERR_INVALID_PARAMS; + + /* Check if a structure with this ID exists */ + status = get_struct_header(structure_id, &header); + if (status != SDS_OK) + return status; + + assert(header); + + if (mode == SDS_ACCESS_MODE_CACHED) + inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size); + + if (!IS_SDS_HEADER_VALID(header)) { + WARN("SDS: Reading from un-finalized structure 0x%x\n", + structure_id); + return SDS_ERR_STRUCT_NOT_FINALIZED; + } + + if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header)) + return SDS_ERR_FAIL; + + field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off; + if (check_uptr_overflow(field_base, size - 1)) + return SDS_ERR_FAIL; + + /* Copy the required field in the struct */ + memcpy(data, (void *)field_base, size); + + return SDS_OK; +} + +/* + * Write to the field in the structure corresponding to `structure_id`. + * `fld_off` is the offset to the field in the structure and `mode` + * indicates whether cache maintenance need to performed for the write. + * The `data` is the pointer to data of size specified by `size`. + * Returns SDS_OK on success or corresponding error codes on failure. + */ +int sds_struct_write(uint32_t structure_id, unsigned int fld_off, + void *data, size_t size, sds_access_mode_t mode) +{ + int status; + uintptr_t field_base; + struct_header_t *header = NULL; + + if (!data) + return SDS_ERR_INVALID_PARAMS; + + /* Check if a structure with this ID exists */ + status = get_struct_header(structure_id, &header); + if (status != SDS_OK) + return status; + + assert(header); + + if (mode == SDS_ACCESS_MODE_CACHED) + inv_dcache_range((uintptr_t)header, SDS_HEADER_SIZE + size); + + if (!IS_SDS_HEADER_VALID(header)) { + WARN("SDS: Writing to un-finalized structure 0x%x\n", + structure_id); + return SDS_ERR_STRUCT_NOT_FINALIZED; + } + + if ((fld_off + size) > GET_SDS_HEADER_STRUCT_SIZE(header)) + return SDS_ERR_FAIL; + + field_base = (uintptr_t)header + SDS_HEADER_SIZE + fld_off; + if (check_uptr_overflow(field_base, size - 1)) + return SDS_ERR_FAIL; + + /* Copy the required field in the struct */ + memcpy((void *)field_base, data, size); + + if (mode == SDS_ACCESS_MODE_CACHED) + flush_dcache_range((uintptr_t)field_base, size); + + return SDS_OK; +} + +/* + * Initialize the SDS driver. Also verifies the SDS version and sanity of + * the SDS structure headers. + * Returns SDS_OK on success, SDS_ERR_FAIL on error. + */ +int sds_init(void) +{ + sds_mem_base = (uintptr_t)PLAT_ARM_SDS_MEM_BASE; + + if (!IS_SDS_REGION_VALID(sds_mem_base)) { + WARN("SDS: No valid SDS Memory Region found\n"); + return SDS_ERR_FAIL; + } + + if (GET_SDS_REGION_SCHEMA_VERSION(sds_mem_base) + != SDS_REGION_SCH_VERSION) { + WARN("SDS: Unsupported SDS schema version\n"); + return SDS_ERR_FAIL; + } + + sds_mem_size = GET_SDS_REGION_SIZE(sds_mem_base); + if (sds_mem_size > PLAT_ARM_SDS_MEM_SIZE_MAX) { + WARN("SDS: SDS Memory Region exceeds size limit\n"); + return SDS_ERR_FAIL; + } + + INFO("SDS: Detected SDS Memory Region (%zu bytes)\n", sds_mem_size); + + if (validate_sds_struct_headers() != SDS_OK) + return SDS_ERR_FAIL; + + return SDS_OK; +} diff --git a/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h b/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h new file mode 100644 index 0000000..d801a04 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/css/sds/sds_private.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDS_PRIVATE_H +#define SDS_PRIVATE_H + +/* SDS Header defines */ +#define SDS_HEADER_ID_SHIFT 0 +#define SDS_HEADER_ID_WIDTH 16 +#define SDS_HEADER_ID_MASK ((1 << SDS_HEADER_ID_WIDTH) - 1) + +#define SDS_HEADER_MINOR_VERSION_WIDTH 8 +#define SDS_HEADER_MINOR_VERSION_SHIFT 16 +#define SDS_HEADER_MAJOR_VERSION_WIDTH 8 + +#define MAKE_SDS_HEADER_VERSION(major, minor) \ + (((((major) & 0xff) << SDS_HEADER_MINOR_VERSION_WIDTH) | ((minor) & 0xff))) +#define SDS_HEADER_VERSION_MASK \ + ((1 << (SDS_HEADER_MINOR_VERSION_WIDTH + SDS_HEADER_MAJOR_VERSION_WIDTH)) - 1) + +#define SDS_HEADER_VERSION MAKE_SDS_HEADER_VERSION(1, 0) +#define SDS_HEADER_STRUCT_SIZE_WIDTH 23 +#define SDS_HEADER_STRUCT_SIZE_SHIFT 1 +#define SDS_HEADER_STRUCT_SIZE_MASK ((1 << SDS_HEADER_STRUCT_SIZE_WIDTH) - 1) +#define SDS_HEADER_VALID_MASK 0x1 +#define SDS_HEADER_VALID_SHIFT 0 +#define SDS_HEADER_SIZE 0x8 + +/* Arbitrary, 16 bit value that indicates a valid SDS Memory Region */ +#define SDS_REGION_SIGNATURE 0xAA7A +#define SDS_REGION_SIGNATURE_WIDTH 16 +#define SDS_REGION_SIGNATURE_SHIFT 0 +#define SDS_REGION_SIGNATURE_MASK ((1 << SDS_REGION_SIGNATURE_WIDTH) - 1) + +#define SDS_REGION_STRUCT_COUNT_SHIFT 16 +#define SDS_REGION_STRUCT_COUNT_WIDTH 8 +#define SDS_REGION_STRUCT_COUNT_MASK ((1 << SDS_REGION_STRUCT_COUNT_WIDTH) - 1) + +#define SDS_REGION_SCH_MINOR_SHIFT 24 +#define SDS_REGION_SCH_MINOR_WIDTH 4 +#define SDS_REGION_SCH_MINOR_MASK ((1 << SDS_REGION_SCH_MINOR_WIDTH) - 1) + +#define SDS_REGION_SCH_MAJOR_SHIFT 28 +#define SDS_REGION_SCH_MAJOR_WIDTH 4 +#define SDS_REGION_SCH_MAJOR_MASK ((1 << SDS_REGION_SCH_MAJOR_WIDTH) - 1) + +#define SDS_REGION_SCH_VERSION_MASK \ + ((1 << (SDS_REGION_SCH_MINOR_WIDTH + SDS_REGION_SCH_MAJOR_WIDTH)) - 1) + +#define MAKE_SDS_REGION_SCH_VERSION(maj, min) \ + ((((maj) & SDS_REGION_SCH_MAJOR_MASK) << SDS_REGION_SCH_MINOR_WIDTH) | \ + ((min) & SDS_REGION_SCH_MINOR_MASK)) + +#define SDS_REGION_SCH_VERSION MAKE_SDS_REGION_SCH_VERSION(1, 0) +#define SDS_REGION_REGIONSIZE_OFFSET 0x4 +#define SDS_REGION_DESC_SIZE 0x8 + +#ifndef __ASSEMBLER__ +#include +#include + +/* Header containing Shared Data Structure metadata */ +typedef struct structure_header { + uint32_t reg[2]; +} struct_header_t; + +#define GET_SDS_HEADER_ID(_header) \ + ((((struct_header_t *)(_header))->reg[0]) & SDS_HEADER_ID_MASK) +#define GET_SDS_HEADER_VERSION(_header) \ + (((((struct_header_t *)(_header))->reg[0]) >> SDS_HEADER_MINOR_VERSION_SHIFT)\ + & SDS_HEADER_VERSION_MASK) +#define GET_SDS_HEADER_STRUCT_SIZE(_header) \ + (((((struct_header_t *)(_header))->reg[1]) >> SDS_HEADER_STRUCT_SIZE_SHIFT)\ + & SDS_HEADER_STRUCT_SIZE_MASK) +#define IS_SDS_HEADER_VALID(_header) \ + ((((struct_header_t *)(_header))->reg[1]) & SDS_HEADER_VALID_MASK) +#define GET_SDS_STRUCT_FIELD(_header, _field_offset) \ + ((((uint8_t *)(_header)) + sizeof(struct_header_t)) + (_field_offset)) + +/* Region Descriptor describing the SDS Memory Region */ +typedef struct region_descriptor { + uint32_t reg[2]; +} region_desc_t; + +#define IS_SDS_REGION_VALID(region) \ + (((((region_desc_t *)(region))->reg[0]) & SDS_REGION_SIGNATURE_MASK) == SDS_REGION_SIGNATURE) +#define GET_SDS_REGION_STRUCTURE_COUNT(region) \ + (((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_STRUCT_COUNT_SHIFT)\ + & SDS_REGION_STRUCT_COUNT_MASK) +#define GET_SDS_REGION_SCHEMA_VERSION(region) \ + (((((region_desc_t *)(region))->reg[0]) >> SDS_REGION_SCH_MINOR_SHIFT)\ + & SDS_REGION_SCH_VERSION_MASK) +#define GET_SDS_REGION_SIZE(region) ((((region_desc_t *)(region))->reg[1])) + +#endif /* __ASSEMBLER__ */ + +#endif /* SDS_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c b/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c new file mode 100644 index 0000000..0b7e541 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/dcc/dcc_console.c @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2015-2021, Xilinx Inc. + * Written by Michal Simek. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * Neither the name of ARM nor the names of its contributors may be used + * to endorse or promote products derived from this software without specific + * prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include + +/* DCC Status Bits */ +#define DCC_STATUS_RX BIT(30) +#define DCC_STATUS_TX BIT(29) +#define TIMEOUT_COUNT_US U(0x10624) + +struct dcc_console { + struct console console; +}; + +static inline uint32_t __dcc_getstatus(void) +{ + return read_mdccsr_el0(); +} + +static inline char __dcc_getchar(void) +{ + char c; + + c = read_dbgdtrrx_el0(); + + return c; +} + +static inline void __dcc_putchar(char c) +{ + /* + * The typecast is to make absolutely certain that 'c' is + * zero-extended. + */ + write_dbgdtrtx_el0((unsigned char)c); +} + +static int32_t dcc_status_timeout(uint32_t mask) +{ + const unsigned int timeout_count = TIMEOUT_COUNT_US; + uint64_t timeout; + unsigned int status; + + timeout = timeout_init_us(timeout_count); + + do { + status = (__dcc_getstatus() & mask); + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } while ((status != 0U)); + + return 0; +} + +static int32_t dcc_console_putc(int32_t ch, struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_TX); + if (status != 0U) { + return status; + } + __dcc_putchar(ch); + + return ch; +} + +static int32_t dcc_console_getc(struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_RX); + if (status != 0U) { + return status; + } + + return __dcc_getchar(); +} + +int32_t dcc_console_init(unsigned long base_addr, uint32_t uart_clk, + uint32_t baud_rate) +{ + return 0; /* No init needed */ +} + +/** + * dcc_console_flush() - Function to force a write of all buffered data + * that hasn't been output. + * @console Console struct + * + */ +static void dcc_console_flush(struct console *console) +{ + unsigned int status; + + status = dcc_status_timeout(DCC_STATUS_TX); + if (status != 0U) { + return; + } +} + +static struct dcc_console dcc_console = { + .console = { + .flags = CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME, + .putc = dcc_console_putc, + .getc = dcc_console_getc, + .flush = dcc_console_flush, + }, +}; + +int console_dcc_register(void) +{ + return console_register(&dcc_console.console); +} diff --git a/arm-trusted-firmware/drivers/arm/dsu/ppu.c b/arm-trusted-firmware/drivers/arm/dsu/ppu.c new file mode 100644 index 0000000..cc00902 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/dsu/ppu.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +/* Global variables */ +static uint64_t ub_base; +static uint64_t ub_per_socket_mmio_size; +static uint32_t ub_num_cpus_per_socket; + +/* + * Follow the sequence from DSU-110 TRM section 6.6.1 to power on the + * core. Expect PPU_PWPR settings for the cluster and the core, from + * the platform. + */ +int dsu_ppu_core_power_on(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr) +{ + uint32_t val; + uint64_t ub_base_socket; + + assert(ub_num_cpus_per_socket > 0U); + + /* Sanity check core number */ + if (core > (ub_num_cpus_per_socket - 1U)) { + ERROR("%s: invalid core %" PRIx32 "\n", __func__, core); + return -EINVAL; + } + + /* Sanity check base address */ + if (ub_base == U(0)) { + ERROR("%s: invalid base %" PRIx64 "\n", __func__, ub_base); + return -ENXIO; + } + + /* Calculate utility bus offset for the socket */ + ub_base_socket = ub_base + (ub_per_socket_mmio_size * socket); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_cluster_write_32(core, ub_base_socket, PPU_PWPR, cluster_ppu_pwpr); + isb(); + + /* + * Poll the cluster PPU_PWSR register until the value + * read matches the value written to the PPU_PWPR + * register + */ + do { + val = dsu_ppu_cluster_read_32(core, ub_base_socket, PPU_PWSR); + } while (val != cluster_ppu_pwpr); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_core_write_32(core, ub_base_socket, PPU_PWPR, core_ppu_pwpr); + isb(); + + /* + * Poll the core PPU_PWSR register until the value + * read matches the value written to the PPU_PWPR + * register + */ + do { + val = dsu_ppu_core_read_32(core, ub_base_socket, PPU_PWSR); + } while (val != core_ppu_pwpr); + + return 0; +} + +/* + * Follow the sequence from DSU-110 TRM section 6.6.2 to power off the + * core. Expect PPU_PWPR settings for the cluster and the core, from + * the platform. + */ +int dsu_ppu_core_power_off(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr) +{ + uint64_t ub_base_socket; + + assert(ub_num_cpus_per_socket > 0U); + + /* Sanity check core number */ + if (core > (ub_num_cpus_per_socket - 1U)) { + return -EINVAL; + } + + /* Sanity check base address */ + if (ub_base == U(0)) { + ERROR("%s: invalid base %" PRIx64 "\n", __func__, ub_base); + return -ENXIO; + } + + /* Calculate utility bus offset for the socket */ + ub_base_socket = ub_base + (ub_per_socket_mmio_size * socket); + + /* + * Set the static power mode policy to platform provided + * value + */ + dsu_ppu_core_write_32(core, ub_base_socket, PPU_PWPR, core_ppu_pwpr); + isb(); + + /* + * This sets the static power mode policy to platform provided + * value + */ + dsu_ppu_cluster_write_32(core, ub_base_socket, PPU_PWPR, cluster_ppu_pwpr); + isb(); + + return 0; +} + +/* + * Setup PPU driver. Pass the utility bus base address. + */ +int dsu_ppu_setup(uint64_t base, uint64_t per_socket_mmio_size, + unsigned int num_cpus_per_socket) +{ + uint32_t num_sockets = PLATFORM_CORE_COUNT / num_cpus_per_socket; + int ret; + + if (base == U(0)) { + return -EINVAL; + } + + /* Ensure that we dont exceed UINT64 boundary */ + if ((UINT64_MAX / per_socket_mmio_size) < num_sockets) { + ERROR("%s: invalid number of sockets %" PRIx8 "\n", __func__, num_sockets); + return -ENOMEM; + } + + /* Ensure that we dont exceed UINT64 boundary */ + if ((UINT64_MAX - (per_socket_mmio_size * num_sockets)) < base) { + ERROR("%s: invalid number of sockets %" PRIx8 "\n", __func__, num_sockets); + return -ENOMEM; + } + + /* save global variables */ + ub_base = base; + ub_per_socket_mmio_size = per_socket_mmio_size; + ub_num_cpus_per_socket = num_cpus_per_socket; + + /* map memory for per-socket DSU region */ + for (unsigned int i = 0; i < num_sockets; i++) { + uint64_t socket_base = base + (i * per_socket_mmio_size); + + ret = mmap_add_dynamic_region(socket_base, socket_base, + PPU_REGION_SIZE * num_cpus_per_socket, + MT_DEVICE | MT_RW | MT_SECURE); + if (ret < 0) { + ERROR("%s: failed to map PPU region 0x%lx for socket %d - error code %d\n", + __func__, socket_base, i, ret); + return ret; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c b/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c new file mode 100644 index 0000000..60364cd --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * Number of Arm Ethos-N NPU (NPU) cores available for a + * particular parent device + */ +#define ETHOSN_NUM_CORES \ + FCONF_GET_PROPERTY(hw_config, ethosn_config, num_cores) + +/* Address to an NPU core */ +#define ETHOSN_CORE_ADDR(core_idx) \ + FCONF_GET_PROPERTY(hw_config, ethosn_core_addr, core_idx) + +/* NPU core sec registry address */ +#define ETHOSN_CORE_SEC_REG(core_addr, reg_offset) \ + (core_addr + reg_offset) + +/* Reset timeout in us */ +#define ETHOSN_RESET_TIMEOUT_US U(10 * 1000 * 1000) +#define ETHOSN_RESET_WAIT_US U(1) + +#define SEC_DEL_REG U(0x0004) +#define SEC_DEL_VAL U(0x81C) +#define SEC_DEL_EXCC_MASK U(0x20) + +#define SEC_SECCTLR_REG U(0x0010) +#define SEC_SECCTLR_VAL U(0x3) + +#define SEC_DEL_MMUSID_REG U(0x2008) +#define SEC_DEL_MMUSID_VAL U(0x3FFFF) + +#define SEC_DEL_ADDR_EXT_REG U(0x201C) +#define SEC_DEL_ADDR_EXT_VAL U(0x15) + +#define SEC_SYSCTRL0_REG U(0x0018) +#define SEC_SYSCTRL0_SOFT_RESET U(3U << 29) +#define SEC_SYSCTRL0_HARD_RESET U(1U << 31) + +static bool ethosn_is_core_addr_valid(uintptr_t core_addr) +{ + for (uint32_t core_idx = 0U; core_idx < ETHOSN_NUM_CORES; core_idx++) { + if (ETHOSN_CORE_ADDR(core_idx) == core_addr) { + return true; + } + } + + return false; +} + +static void ethosn_delegate_to_ns(uintptr_t core_addr) +{ + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_SECCTLR_REG), + SEC_SECCTLR_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG), + SEC_DEL_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_MMUSID_REG), + SEC_DEL_MMUSID_VAL); + + mmio_setbits_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_ADDR_EXT_REG), + SEC_DEL_ADDR_EXT_VAL); +} + +static int ethosn_is_sec(uintptr_t core_addr) +{ + if ((mmio_read_32(ETHOSN_CORE_SEC_REG(core_addr, SEC_DEL_REG)) + & SEC_DEL_EXCC_MASK) != 0U) { + return 0; + } + + return 1; +} + +static bool ethosn_reset(uintptr_t core_addr, int hard_reset) +{ + unsigned int timeout; + const uintptr_t sysctrl0_reg = + ETHOSN_CORE_SEC_REG(core_addr, SEC_SYSCTRL0_REG); + const uint32_t reset_val = (hard_reset != 0) ? SEC_SYSCTRL0_HARD_RESET + : SEC_SYSCTRL0_SOFT_RESET; + + mmio_write_32(sysctrl0_reg, reset_val); + + /* Wait for reset to complete */ + for (timeout = 0U; timeout < ETHOSN_RESET_TIMEOUT_US; + timeout += ETHOSN_RESET_WAIT_US) { + + if ((mmio_read_32(sysctrl0_reg) & reset_val) == 0U) { + break; + } + + udelay(ETHOSN_RESET_WAIT_US); + } + + return timeout < ETHOSN_RESET_TIMEOUT_US; +} + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_addr, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags) +{ + int hard_reset = 0; + const uint32_t fid = smc_fid & FUNCID_NUM_MASK; + + /* Only SiP fast calls are expected */ + if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || + (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Truncate parameters to 32-bits for SMC32 */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + core_addr &= 0xFFFFFFFF; + x2 &= 0xFFFFFFFF; + x3 &= 0xFFFFFFFF; + x4 &= 0xFFFFFFFF; + } + + if (!is_ethosn_fid(smc_fid)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Commands that do not require a valid core address */ + switch (fid) { + case ETHOSN_FNUM_VERSION: + SMC_RET2(handle, ETHOSN_VERSION_MAJOR, ETHOSN_VERSION_MINOR); + } + + if (!ethosn_is_core_addr_valid(core_addr)) { + WARN("ETHOSN: Unknown core address given to SMC call.\n"); + SMC_RET1(handle, ETHOSN_UNKNOWN_CORE_ADDRESS); + } + + /* Commands that require a valid addr */ + switch (fid) { + case ETHOSN_FNUM_IS_SEC: + SMC_RET1(handle, ethosn_is_sec(core_addr)); + case ETHOSN_FNUM_HARD_RESET: + hard_reset = 1; + /* Fallthrough */ + case ETHOSN_FNUM_SOFT_RESET: + if (!ethosn_reset(core_addr, hard_reset)) { + SMC_RET1(handle, ETHOSN_FAILURE); + } + ethosn_delegate_to_ns(core_addr); + SMC_RET1(handle, ETHOSN_SUCCESS); + default: + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c b/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c new file mode 100644 index 0000000..75a2b66 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * TODO: Someday there will be a generic power controller api. At the moment + * each platform has its own pwrc so just exporting functions is fine. + */ +ARM_INSTANTIATE_LOCK; + +unsigned int fvp_pwrc_get_cpu_wkr(u_register_t mpidr) +{ + return PSYSR_WK(fvp_pwrc_read_psysr(mpidr)); +} + +unsigned int fvp_pwrc_read_psysr(u_register_t mpidr) +{ + unsigned int rc; + arm_lock_get(); + mmio_write_32(PWRC_BASE + PSYSR_OFF, (unsigned int) mpidr); + rc = mmio_read_32(PWRC_BASE + PSYSR_OFF); + arm_lock_release(); + return rc; +} + +void fvp_pwrc_write_pponr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PPONR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_write_ppoffr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PPOFFR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_set_wen(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) (PWKUPR_WEN | mpidr)); + arm_lock_release(); +} + +void fvp_pwrc_clr_wen(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PWKUPR_OFF, + (unsigned int) mpidr); + arm_lock_release(); +} + +void fvp_pwrc_write_pcoffr(u_register_t mpidr) +{ + arm_lock_get(); + mmio_write_32(PWRC_BASE + PCOFFR_OFF, (unsigned int) mpidr); + arm_lock_release(); +} + +/* Nothing else to do here apart from initializing the lock */ +void __init plat_arm_pwrc_setup(void) +{ + arm_lock_init(); +} + + + diff --git a/arm-trusted-firmware/drivers/arm/gic/common/gic_common.c b/arm-trusted-firmware/drivers/arm/gic/common/gic_common.c new file mode 100644 index 0000000..bf6405f --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/common/gic_common.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#pragma message __FILE__ " is deprecated, use gicv2.mk instead" + +#include + +#include +#include + +#include "gic_common_private.h" + +/******************************************************************************* + * GIC Distributor interface accessors for reading entire registers + ******************************************************************************/ +/* + * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt + * `id`, 32 interrupt ids at a time. + */ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + return mmio_read_32(base + GICD_IGROUPR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt ids at a time. + */ +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)); +} + +/* + * Accessor to read the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + return mmio_read_32(base + GICD_ICENABLER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + return mmio_read_32(base + GICD_ISPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + return mmio_read_32(base + GICD_ICPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICGFR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICFGR_SHIFT; + + return mmio_read_32(base + GICD_ICFGR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> NSACR_SHIFT; + + return mmio_read_32(base + GICD_NSACR + (n << 2)); +} + +/******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +/* + * Accessor to write the GIC Distributor IGROUPR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + mmio_write_32(base + GICD_IGROUPR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISENABLER_SHIFT; + + mmio_write_32(base + GICD_ISENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + mmio_write_32(base + GICD_ICENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + mmio_write_32(base + GICD_ISPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + mmio_write_32(base + GICD_ICPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICFGR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICFGR_SHIFT; + + mmio_write_32(base + GICD_ICFGR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> NSACR_SHIFT; + + mmio_write_32(base + GICD_NSACR + (n << 2), val); +} + +/******************************************************************************* + * GIC Distributor functions for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val | (1U << bit_num)); +} + +void gicd_clr_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num)); +} + +void gicd_set_isenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); + + gicd_write_isenabler(base, id, (1U << bit_num)); +} + +void gicd_set_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); + + gicd_write_icenabler(base, id, (1U << bit_num)); +} + +void gicd_set_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); + + gicd_write_ispendr(base, id, (1U << bit_num)); +} + +void gicd_set_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); + + gicd_write_icpendr(base, id, (1U << bit_num)); +} + +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + unsigned int reg_val = gicd_read_isactiver(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + + gicd_write_isactiver(base, id, (1U << bit_num)); +} + +void gicd_set_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U); + + gicd_write_icactiver(base, id, (1U << bit_num)); +} + +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + uint8_t val = pri & GIC_PRI_MASK; + + mmio_write_8(base + GICD_IPRIORITYR + id, val); +} + +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); + unsigned int bit_shift = bit_num << 1; + + uint32_t reg_val = gicd_read_icfgr(base, id); + + /* Clear the field, and insert required configuration */ + reg_val &= ~(GIC_CFG_MASK << bit_shift); + reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); + + gicd_write_icfgr(base, id, reg_val); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h b/arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h new file mode 100644 index 0000000..1ab1bdb --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC_COMMON_PRIVATE_H +#define GIC_COMMON_PRIVATE_H + +#include + +#include +#include + +/******************************************************************************* + * GIC Distributor interface register accessors that are common to GICv3 & GICv2 + ******************************************************************************/ +static inline unsigned int gicd_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICD_CTLR); +} + +static inline unsigned int gicd_read_typer(uintptr_t base) +{ + return mmio_read_32(base + GICD_TYPER); +} + +static inline unsigned int gicd_read_iidr(uintptr_t base) +{ + return mmio_read_32(base + GICD_IIDR); +} + +static inline void gicd_write_ctlr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICD_CTLR, val); +} + +/******************************************************************************* + * GIC Distributor function prototypes for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id); +unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id); +unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id); +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id); +unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id); +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id); +unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id); +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id); +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id); +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id); +unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id); +unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id); +unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id); +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val); +void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val); + +/******************************************************************************* + * GIC Distributor function prototypes for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id); +void gicd_set_igroupr(uintptr_t base, unsigned int id); +void gicd_clr_igroupr(uintptr_t base, unsigned int id); +void gicd_set_isenabler(uintptr_t base, unsigned int id); +void gicd_set_icenabler(uintptr_t base, unsigned int id); +void gicd_set_ispendr(uintptr_t base, unsigned int id); +void gicd_set_icpendr(uintptr_t base, unsigned int id); +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id); +void gicd_set_isactiver(uintptr_t base, unsigned int id); +void gicd_set_icactiver(uintptr_t base, unsigned int id); +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri); +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg); + +#endif /* GIC_COMMON_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c new file mode 100644 index 0000000..db9ba87 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c @@ -0,0 +1,340 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../common/gic_common_private.h" + +/******************************************************************************* + * GIC Distributor interface accessors for reading entire registers + ******************************************************************************/ +/* + * Accessor to read the GIC Distributor IGROUPR corresponding to the interrupt + * `id`, 32 interrupt ids at a time. + */ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + return mmio_read_32(base + GICD_IGROUPR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt ids at a time. + */ +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)); +} + +/* + * Accessor to read the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + return mmio_read_32(base + GICD_ICENABLER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + return mmio_read_32(base + GICD_ISPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + return mmio_read_32(base + GICD_ICPENDR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ISACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + return mmio_read_32(base + GICD_ICACTIVER + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + return mmio_read_32(base + GICD_IPRIORITYR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor ICGFR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> ICFGR_SHIFT; + + return mmio_read_32(base + GICD_ICFGR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) +{ + unsigned int n = id >> NSACR_SHIFT; + + return mmio_read_32(base + GICD_NSACR + (n << 2)); +} + +/******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +/* + * Accessor to write the GIC Distributor IGROUPR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IGROUPR_SHIFT; + + mmio_write_32(base + GICD_IGROUPR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISENABLER_SHIFT; + + mmio_write_32(base + GICD_ISENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICENABLER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICENABLER_SHIFT; + + mmio_write_32(base + GICD_ICENABLER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISPENDR_SHIFT; + + mmio_write_32(base + GICD_ISPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICPENDR corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icpendr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICPENDR_SHIFT; + + mmio_write_32(base + GICD_ICPENDR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ISACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ISACTIVER_SHIFT; + + mmio_write_32(base + GICD_ISACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICACTIVER corresponding to the + * interrupt `id`, 32 interrupt IDs at a time. + */ +void gicd_write_icactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICACTIVER_SHIFT; + + mmio_write_32(base + GICD_ICACTIVER + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor IPRIORITYR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> IPRIORITYR_SHIFT; + + mmio_write_32(base + GICD_IPRIORITYR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor ICFGR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> ICFGR_SHIFT; + + mmio_write_32(base + GICD_ICFGR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor NSACR corresponding to the + * interrupt `id`, 16 interrupt IDs at a time. + */ +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned int n = id >> NSACR_SHIFT; + + mmio_write_32(base + GICD_NSACR + (n << 2), val); +} + +/******************************************************************************* + * GIC Distributor functions for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val | (1U << bit_num)); +} + +void gicd_clr_igroupr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << IGROUPR_SHIFT) - 1U); + unsigned int reg_val = gicd_read_igroupr(base, id); + + gicd_write_igroupr(base, id, reg_val & ~(1U << bit_num)); +} + +void gicd_set_isenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISENABLER_SHIFT) - 1U); + + gicd_write_isenabler(base, id, (1U << bit_num)); +} + +void gicd_set_icenabler(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICENABLER_SHIFT) - 1U); + + gicd_write_icenabler(base, id, (1U << bit_num)); +} + +void gicd_set_ispendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISPENDR_SHIFT) - 1U); + + gicd_write_ispendr(base, id, (1U << bit_num)); +} + +void gicd_set_icpendr(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICPENDR_SHIFT) - 1U); + + gicd_write_icpendr(base, id, (1U << bit_num)); +} + +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + unsigned int reg_val = gicd_read_isactiver(base, id); + + return (reg_val >> bit_num) & 0x1U; +} + +void gicd_set_isactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ISACTIVER_SHIFT) - 1U); + + gicd_write_isactiver(base, id, (1U << bit_num)); +} + +void gicd_set_icactiver(uintptr_t base, unsigned int id) +{ + unsigned int bit_num = id & ((1U << ICACTIVER_SHIFT) - 1U); + + gicd_write_icactiver(base, id, (1U << bit_num)); +} + +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + uint8_t val = pri & GIC_PRI_MASK; + + mmio_write_8(base + GICD_IPRIORITYR + id, val); +} + +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_num = id & ((1U << ICFGR_SHIFT) - 1U); + unsigned int bit_shift = bit_num << 1; + + uint32_t reg_val = gicd_read_icfgr(base, id); + + /* Clear the field, and insert required configuration */ + reg_val &= ~(GIC_CFG_MASK << bit_shift); + reg_val |= ((cfg & GIC_CFG_MASK) << bit_shift); + + gicd_write_icfgr(base, id, reg_val); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk new file mode 100644 index 0000000..49996bb --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2.mk @@ -0,0 +1,15 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# No support for extended PPI and SPI range +GIC_EXT_INTID := 0 + +GICV2_SOURCES += drivers/arm/gic/v2/gicv2_main.c \ + drivers/arm/gic/v2/gicv2_helpers.c \ + drivers/arm/gic/v2/gicdv2_helpers.c + +# Set GICv2 build option +$(eval $(call add_define,GIC_EXT_INTID)) \ No newline at end of file diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c new file mode 100644 index 0000000..751316c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gicv2_private.h" + +/* + * Accessor to read the GIC Distributor ITARGETSR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_itargetsr(uintptr_t base, unsigned int id) +{ + unsigned n = id >> ITARGETSR_SHIFT; + return mmio_read_32(base + GICD_ITARGETSR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor CPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_cpendsgir(uintptr_t base, unsigned int id) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_CPENDSGIR + (n << 2)); +} + +/* + * Accessor to read the GIC Distributor SPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_spendsgir(uintptr_t base, unsigned int id) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + return mmio_read_32(base + GICD_SPENDSGIR + (n << 2)); +} + +/* + * Accessor to write the GIC Distributor ITARGETSR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_itargetsr(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> ITARGETSR_SHIFT; + mmio_write_32(base + GICD_ITARGETSR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor CPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_cpendsgir(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> CPENDSGIR_SHIFT; + mmio_write_32(base + GICD_CPENDSGIR + (n << 2), val); +} + +/* + * Accessor to write the GIC Distributor SPENDSGIR corresponding to the + * interrupt `id`, 4 interrupt IDs at a time. + */ +void gicd_write_spendsgir(uintptr_t base, unsigned int id, unsigned int val) +{ + unsigned n = id >> SPENDSGIR_SHIFT; + mmio_write_32(base + GICD_SPENDSGIR + (n << 2), val); +} + +/******************************************************************************* + * Get the current CPU bit mask from GICD_ITARGETSR0 + ******************************************************************************/ +unsigned int gicv2_get_cpuif_id(uintptr_t base) +{ + unsigned int val; + + val = gicd_read_itargetsr(base, 0); + return val & GIC_TARGET_CPU_MASK; +} + +/******************************************************************************* + * Helper function to configure the default attributes of SPIs. + ******************************************************************************/ +void gicv2_spis_configure_defaults(uintptr_t gicd_base) +{ + unsigned int index, num_ints; + + num_ints = gicd_read_typer(gicd_base); + num_ints &= TYPER_IT_LINES_NO_MASK; + num_ints = (num_ints + 1U) << 5; + + /* + * Treat all SPIs as G1NS by default. The number of interrupts is + * calculated as 32 * (IT_LINES + 1). We do 32 at a time. + */ + for (index = MIN_SPI_ID; index < num_ints; index += 32U) + gicd_write_igroupr(gicd_base, index, ~0U); + + /* Setup the default SPI priorities doing four at a time */ + for (index = MIN_SPI_ID; index < num_ints; index += 4U) + gicd_write_ipriorityr(gicd_base, + index, + GICD_IPRIORITYR_DEF_VAL); + + /* Treat all SPIs as level triggered by default, 16 at a time */ + for (index = MIN_SPI_ID; index < num_ints; index += 16U) + gicd_write_icfgr(gicd_base, index, 0U); +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 SPIs. + ******************************************************************************/ +void gicv2_secure_spis_configure_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *prop_desc; + + /* Make sure there's a valid property array */ + if (interrupt_props_num != 0U) + assert(interrupt_props != NULL); + + for (i = 0; i < interrupt_props_num; i++) { + prop_desc = &interrupt_props[i]; + + if (prop_desc->intr_num < MIN_SPI_ID) + continue; + + /* Configure this interrupt as a secure interrupt */ + assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); + gicd_clr_igroupr(gicd_base, prop_desc->intr_num); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, + prop_desc->intr_pri); + + /* Target the secure interrupts to primary CPU */ + gicd_set_itargetsr(gicd_base, prop_desc->intr_num, + gicv2_get_cpuif_id(gicd_base)); + + /* Set interrupt configuration */ + gicd_set_icfgr(gicd_base, prop_desc->intr_num, + prop_desc->intr_cfg); + + /* Enable this interrupt */ + gicd_set_isenabler(gicd_base, prop_desc->intr_num); + } +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 SGIs and PPIs. + ******************************************************************************/ +void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + uint32_t sec_ppi_sgi_mask = 0; + const interrupt_prop_t *prop_desc; + + /* Make sure there's a valid property array */ + if (interrupt_props_num != 0U) + assert(interrupt_props != NULL); + + /* + * Disable all SGIs (imp. def.)/PPIs before configuring them. This is a + * more scalable approach as it avoids clearing the enable bits in the + * GICD_CTLR. + */ + gicd_write_icenabler(gicd_base, 0U, ~0U); + + /* Setup the default PPI/SGI priorities doing four at a time */ + for (i = 0U; i < MIN_SPI_ID; i += 4U) + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + + for (i = 0U; i < interrupt_props_num; i++) { + prop_desc = &interrupt_props[i]; + + if (prop_desc->intr_num >= MIN_SPI_ID) + continue; + + /* Configure this interrupt as a secure interrupt */ + assert(prop_desc->intr_grp == GICV2_INTR_GROUP0); + + /* + * Set interrupt configuration for PPIs. Configuration for SGIs + * are ignored. + */ + if ((prop_desc->intr_num >= MIN_PPI_ID) && + (prop_desc->intr_num < MIN_SPI_ID)) { + gicd_set_icfgr(gicd_base, prop_desc->intr_num, + prop_desc->intr_cfg); + } + + /* We have an SGI or a PPI. They are Group0 at reset */ + sec_ppi_sgi_mask |= (1u << prop_desc->intr_num); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, prop_desc->intr_num, + prop_desc->intr_pri); + } + + /* + * Invert the bitmask to create a mask for non-secure PPIs and SGIs. + * Program the GICD_IGROUPR0 with this bit mask. + */ + gicd_write_igroupr(gicd_base, 0, ~sec_ppi_sgi_mask); + + /* Enable the Group 0 SGIs and PPIs */ + gicd_write_isenabler(gicd_base, 0, sec_ppi_sgi_mask); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c new file mode 100644 index 0000000..939d097 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c @@ -0,0 +1,555 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gicv2_private.h" + +static const gicv2_driver_data_t *driver_data; + +/* + * Spinlock to guard registers needing read-modify-write. APIs protected by this + * spinlock are used either at boot time (when only a single CPU is active), or + * when the system is fully coherent. + */ +static spinlock_t gic_lock; + +/******************************************************************************* + * Enable secure interrupts and use FIQs to route them. Disable legacy bypass + * and set the priority mask register to allow all interrupts to trickle in. + ******************************************************************************/ +void gicv2_cpuif_enable(void) +{ + unsigned int val; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* + * Enable the Group 0 interrupts, FIQEn and disable Group 0/1 + * bypass. + */ + val = CTLR_ENABLE_G0_BIT | FIQ_EN_BIT | FIQ_BYP_DIS_GRP0; + val |= IRQ_BYP_DIS_GRP0 | FIQ_BYP_DIS_GRP1 | IRQ_BYP_DIS_GRP1; + + /* Program the idle priority in the PMR */ + gicc_write_pmr(driver_data->gicc_base, GIC_PRI_MASK); + gicc_write_ctlr(driver_data->gicc_base, val); +} + +/******************************************************************************* + * Place the cpu interface in a state where it can never make a cpu exit wfi as + * as result of an asserted interrupt. This is critical for powering down a cpu + ******************************************************************************/ +void gicv2_cpuif_disable(void) +{ + unsigned int val; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* Disable secure, non-secure interrupts and disable their bypass */ + val = gicc_read_ctlr(driver_data->gicc_base); + val &= ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT); + val |= FIQ_BYP_DIS_GRP1 | FIQ_BYP_DIS_GRP0; + val |= IRQ_BYP_DIS_GRP0 | IRQ_BYP_DIS_GRP1; + gicc_write_ctlr(driver_data->gicc_base, val); +} + +/******************************************************************************* + * Per cpu gic distributor setup which will be done by all cpus after a cold + * boot/hotplug. This marks out the secure SPIs and PPIs & enables them. + ******************************************************************************/ +void gicv2_pcpu_distif_init(void) +{ + unsigned int ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + gicv2_secure_ppi_sgi_setup_props(driver_data->gicd_base, + driver_data->interrupt_props, + driver_data->interrupt_props_num); + + /* Enable G0 interrupts if not already */ + ctlr = gicd_read_ctlr(driver_data->gicd_base); + if ((ctlr & CTLR_ENABLE_G0_BIT) == 0U) { + gicd_write_ctlr(driver_data->gicd_base, + ctlr | CTLR_ENABLE_G0_BIT); + } +} + +/******************************************************************************* + * Global gic distributor init which will be done by the primary cpu after a + * cold boot. It marks out the secure SPIs, PPIs & SGIs and enables them. It + * then enables the secure GIC distributor interface. + ******************************************************************************/ +void gicv2_distif_init(void) +{ + unsigned int ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* Disable the distributor before going further */ + ctlr = gicd_read_ctlr(driver_data->gicd_base); + gicd_write_ctlr(driver_data->gicd_base, + ctlr & ~(CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1_BIT)); + + /* Set the default attribute of all SPIs */ + gicv2_spis_configure_defaults(driver_data->gicd_base); + + gicv2_secure_spis_configure_props(driver_data->gicd_base, + driver_data->interrupt_props, + driver_data->interrupt_props_num); + + + /* Re-enable the secure SPIs now that they have been configured */ + gicd_write_ctlr(driver_data->gicd_base, ctlr | CTLR_ENABLE_G0_BIT); +} + +/******************************************************************************* + * Initialize the ARM GICv2 driver with the provided platform inputs + ******************************************************************************/ +void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data) +{ + unsigned int gic_version; + + assert(plat_driver_data != NULL); + assert(plat_driver_data->gicd_base != 0U); + assert(plat_driver_data->gicc_base != 0U); + + assert(plat_driver_data->interrupt_props_num > 0 ? + plat_driver_data->interrupt_props != NULL : 1); + + /* Ensure that this is a GICv2 system */ + gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); + gic_version = (gic_version >> PIDR2_ARCH_REV_SHIFT) + & PIDR2_ARCH_REV_MASK; + + /* + * GICv1 with security extension complies with trusted firmware + * GICv2 driver as far as virtualization and few tricky power + * features are not used. GICv2 features that are not supported + * by GICv1 with Security Extensions are: + * - virtual interrupt support. + * - wake up events. + * - writeable GIC state register (for power sequences) + * - interrupt priority drop. + * - interrupt signal bypass. + */ + assert((gic_version == ARCH_REV_GICV2) || + (gic_version == ARCH_REV_GICV1)); + + driver_data = plat_driver_data; + + /* + * The GIC driver data is initialized by the primary CPU with caches + * enabled. When the secondary CPU boots up, it initializes the + * GICC/GICR interface with the caches disabled. Hence flush the + * driver_data to ensure coherency. This is not required if the + * platform has HW_ASSISTED_COHERENCY or WARMBOOT_ENABLE_DCACHE_EARLY + * enabled. + */ +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range((uintptr_t) &driver_data, sizeof(driver_data)); + flush_dcache_range((uintptr_t) driver_data, sizeof(*driver_data)); +#endif + INFO("ARM GICv2 driver initialized\n"); +} + +/****************************************************************************** + * This function returns whether FIQ is enabled in the GIC CPU interface. + *****************************************************************************/ +unsigned int gicv2_is_fiq_enabled(void) +{ + unsigned int gicc_ctlr; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + gicc_ctlr = gicc_read_ctlr(driver_data->gicc_base); + return (gicc_ctlr >> FIQ_EN_SHIFT) & 0x1U; +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. The return values can be one of the following : + * PENDING_G1_INTID : The interrupt type is non secure Group 1. + * 0 - 1019 : The interrupt type is secure Group 0. + * GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with + * sufficient priority to be signaled + ******************************************************************************/ +unsigned int gicv2_get_pending_interrupt_type(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK; +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. GIC_SPURIOUS_INTERRUPT is returned when there is no + * interrupt pending. + ******************************************************************************/ +unsigned int gicv2_get_pending_interrupt_id(void) +{ + unsigned int id; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + id = gicc_read_hppir(driver_data->gicc_base) & INT_ID_MASK; + + /* + * Find out which non-secure interrupt it is under the assumption that + * the GICC_CTLR.AckCtl bit is 0. + */ + if (id == PENDING_G1_INTID) + id = gicc_read_ahppir(driver_data->gicc_base) & INT_ID_MASK; + + return id; +} + +/******************************************************************************* + * This functions reads the GIC cpu interface Interrupt Acknowledge register + * to start handling the pending secure 0 interrupt. It returns the + * contents of the IAR. + ******************************************************************************/ +unsigned int gicv2_acknowledge_interrupt(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_IAR(driver_data->gicc_base); +} + +/******************************************************************************* + * This functions writes the GIC cpu interface End Of Interrupt register with + * the passed value to finish handling the active secure group 0 interrupt. + ******************************************************************************/ +void gicv2_end_of_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + /* + * Ensure the write to peripheral registers are *complete* before the write + * to GIC_EOIR. + * + * Note: The completion gurantee depends on various factors of system design + * and the barrier is the best core can do by which execution of further + * instructions waits till the barrier is alive. + */ + dsbishst(); + gicc_write_EOIR(driver_data->gicc_base, id); +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 secure or group1 non secure. It returns zero for Group 0 secure and + * one for Group 1 non secure interrupt. + ******************************************************************************/ +unsigned int gicv2_get_interrupt_group(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + return gicd_get_igroupr(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function returns the priority of the interrupt the processor is + * currently servicing. + ******************************************************************************/ +unsigned int gicv2_get_running_priority(void) +{ + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + return gicc_read_rpr(driver_data->gicc_base); +} + +/******************************************************************************* + * This function sets the GICv2 target mask pattern for the current PE. The PE + * target mask is used to translate linear PE index (returned by platform core + * position) to a bit mask used when targeting interrupts to a PE (for example + * when raising SGIs and routing SPIs). + ******************************************************************************/ +void gicv2_set_pe_target_mask(unsigned int proc_num) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(driver_data->target_masks != NULL); + assert(proc_num < GICV2_MAX_TARGET_PE); + assert(proc_num < driver_data->target_masks_num); + + /* Return if the target mask is already populated */ + if (driver_data->target_masks[proc_num] != 0U) + return; + + /* + * Update target register corresponding to this CPU and flush for it to + * be visible to other CPUs. + */ + if (driver_data->target_masks[proc_num] == 0U) { + driver_data->target_masks[proc_num] = + gicv2_get_cpuif_id(driver_data->gicd_base); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* + * PEs only update their own masks. Primary updates it with + * caches on. But because secondaries does it with caches off, + * all updates go to memory directly, and there's no danger of + * secondaries overwriting each others' mask, despite + * target_masks[] not being cache line aligned. + */ + flush_dcache_range((uintptr_t) + &driver_data->target_masks[proc_num], + sizeof(driver_data->target_masks[proc_num])); +#endif + } +} + +/******************************************************************************* + * This function returns the active status of the interrupt (either because the + * state is active, or active and pending). + ******************************************************************************/ +unsigned int gicv2_get_interrupt_active(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + return gicd_get_isactiver(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function enables the interrupt identified by id. + ******************************************************************************/ +void gicv2_enable_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before enabling interrupt. + */ + dsbishst(); + gicd_set_isenabler(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function disables the interrupt identified by id. + ******************************************************************************/ +void gicv2_disable_interrupt(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* + * Disable interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + gicd_set_icenabler(driver_data->gicd_base, id); + dsbishst(); +} + +/******************************************************************************* + * This function sets the interrupt priority as supplied for the given interrupt + * id. + ******************************************************************************/ +void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + gicd_set_ipriorityr(driver_data->gicd_base, id, priority); +} + +/******************************************************************************* + * This function assigns group for the interrupt identified by id. The group can + * be any of GICV2_INTR_GROUP* + ******************************************************************************/ +void gicv2_set_interrupt_type(unsigned int id, unsigned int type) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + assert(id <= MAX_SPI_ID); + + /* Serialize read-modify-write to Distributor registers */ + spin_lock(&gic_lock); + switch (type) { + case GICV2_INTR_GROUP1: + gicd_set_igroupr(driver_data->gicd_base, id); + break; + case GICV2_INTR_GROUP0: + gicd_clr_igroupr(driver_data->gicd_base, id); + break; + default: + assert(false); + break; + } + spin_unlock(&gic_lock); +} + +/******************************************************************************* + * This function raises the specified SGI to requested targets. + * + * The proc_num parameter must be the linear index of the target PE in the + * system. + ******************************************************************************/ +void gicv2_raise_sgi(int sgi_num, int proc_num) +{ + unsigned int sgir_val, target; + + assert(driver_data != NULL); + assert(proc_num >= 0); + assert(proc_num < (int)GICV2_MAX_TARGET_PE); + assert(driver_data->gicd_base != 0U); + + /* + * Target masks array must have been supplied, and the core position + * should be valid. + */ + assert(driver_data->target_masks != NULL); + assert(proc_num < (int)driver_data->target_masks_num); + + /* Don't raise SGI if the mask hasn't been populated */ + target = driver_data->target_masks[proc_num]; + assert(target != 0U); + + sgir_val = GICV2_SGIR_VALUE(SGIR_TGT_SPECIFIC, target, sgi_num); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + gicd_write_sgir(driver_data->gicd_base, sgir_val); +} + +/******************************************************************************* + * This function sets the interrupt routing for the given SPI interrupt id. + * The interrupt routing is specified in routing mode. The proc_num parameter is + * linear index of the PE to target SPI. When proc_num < 0, the SPI may target + * all PEs. + ******************************************************************************/ +void gicv2_set_spi_routing(unsigned int id, int proc_num) +{ + unsigned int target; + + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + assert((id >= MIN_SPI_ID) && (id <= MAX_SPI_ID)); + + /* + * Target masks array must have been supplied, and the core position + * should be valid. + */ + assert(driver_data->target_masks != NULL); + assert(proc_num < (int)GICV2_MAX_TARGET_PE); + assert(driver_data->target_masks_num < INT_MAX); + assert(proc_num < (int)driver_data->target_masks_num); + + if (proc_num < 0) { + /* Target all PEs */ + target = GIC_TARGET_CPU_MASK; + } else { + /* Don't route interrupt if the mask hasn't been populated */ + target = driver_data->target_masks[proc_num]; + assert(target != 0U); + } + + gicd_set_itargetsr(driver_data->gicd_base, id, target); +} + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_clear_interrupt_pending(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + gicd_set_icpendr(driver_data->gicd_base, id); + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + ******************************************************************************/ +void gicv2_set_interrupt_pending(unsigned int id) +{ + assert(driver_data != NULL); + assert(driver_data->gicd_base != 0U); + + /* SGIs can't be cleared pending */ + assert(id >= MIN_PPI_ID); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + gicd_set_ispendr(driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function sets the PMR register with the supplied value. Returns the + * original PMR. + ******************************************************************************/ +unsigned int gicv2_set_pmr(unsigned int mask) +{ + unsigned int old_mask; + + assert(driver_data != NULL); + assert(driver_data->gicc_base != 0U); + + old_mask = gicc_read_pmr(driver_data->gicc_base); + + /* + * Order memory updates w.r.t. PMR write, and ensure they're visible + * before potential out of band interrupt trigger because of PMR update. + */ + dmbishst(); + gicc_write_pmr(driver_data->gicc_base, mask); + dsbishst(); + + return old_mask; +} + +/******************************************************************************* + * This function updates single interrupt configuration to be level/edge + * triggered + ******************************************************************************/ +void gicv2_interrupt_set_cfg(unsigned int id, unsigned int cfg) +{ + gicd_set_icfgr(driver_data->gicd_base, id, cfg); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h new file mode 100644 index 0000000..0fbdab0 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV2_PRIVATE_H +#define GICV2_PRIVATE_H + +#include + +#include +#include + +/******************************************************************************* + * Private function prototypes + ******************************************************************************/ +void gicv2_spis_configure_defaults(uintptr_t gicd_base); +void gicv2_secure_spis_configure_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +void gicv2_secure_ppi_sgi_setup_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +unsigned int gicv2_get_cpuif_id(uintptr_t base); + +/******************************************************************************* + * GIC Distributor interface accessors for reading entire registers + ******************************************************************************/ +static inline unsigned int gicd_read_pidr2(uintptr_t base) +{ + return mmio_read_32(base + GICD_PIDR2_GICV2); +} + +/******************************************************************************* + * GIC Distributor interface accessors for writing entire registers + ******************************************************************************/ +static inline unsigned int gicd_get_itargetsr(uintptr_t base, unsigned int id) +{ + return mmio_read_8(base + GICD_ITARGETSR + id); +} + +static inline void gicd_set_itargetsr(uintptr_t base, unsigned int id, + unsigned int target) +{ + uint8_t val = target & GIC_TARGET_CPU_MASK; + + mmio_write_8(base + GICD_ITARGETSR + id, val); +} + +static inline void gicd_write_sgir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICD_SGIR, val); +} + +/******************************************************************************* + * GIC CPU interface accessors for reading entire registers + ******************************************************************************/ + +static inline unsigned int gicc_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICC_CTLR); +} + +static inline unsigned int gicc_read_pmr(uintptr_t base) +{ + return mmio_read_32(base + GICC_PMR); +} + +static inline unsigned int gicc_read_BPR(uintptr_t base) +{ + return mmio_read_32(base + GICC_BPR); +} + +static inline unsigned int gicc_read_IAR(uintptr_t base) +{ + return mmio_read_32(base + GICC_IAR); +} + +static inline unsigned int gicc_read_EOIR(uintptr_t base) +{ + return mmio_read_32(base + GICC_EOIR); +} + +static inline unsigned int gicc_read_hppir(uintptr_t base) +{ + return mmio_read_32(base + GICC_HPPIR); +} + +static inline unsigned int gicc_read_ahppir(uintptr_t base) +{ + return mmio_read_32(base + GICC_AHPPIR); +} + +static inline unsigned int gicc_read_dir(uintptr_t base) +{ + return mmio_read_32(base + GICC_DIR); +} + +static inline unsigned int gicc_read_iidr(uintptr_t base) +{ + return mmio_read_32(base + GICC_IIDR); +} + +static inline unsigned int gicc_read_rpr(uintptr_t base) +{ + return mmio_read_32(base + GICC_RPR); +} + +/******************************************************************************* + * GIC CPU interface accessors for writing entire registers + ******************************************************************************/ + +static inline void gicc_write_ctlr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_CTLR, val); +} + +static inline void gicc_write_pmr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_PMR, val); +} + +static inline void gicc_write_BPR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_BPR, val); +} + + +static inline void gicc_write_IAR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_IAR, val); +} + +static inline void gicc_write_EOIR(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_EOIR, val); +} + +static inline void gicc_write_hppir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_HPPIR, val); +} + +static inline void gicc_write_dir(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICC_DIR, val); +} + +#endif /* GICV2_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c b/arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c new file mode 100644 index 0000000..4489892 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for implementation defined features that are identical in ARM GICv3 +* implementations (GIC-500 and GIC-600 for now). This driver only overrides +* APIs that are different to those generic ones in GICv3 driver. + */ + +#include + +#include +#include +#include + +#include "gicv3_private.h" + +/* + * Flush the internal GIC cache of the LPIs pending tables to memory before + * saving the state of the Redistributor. This is required before powering off + * the GIC when the pending status must be preserved. + * `rdist_proc_num` is the processor number corresponding to the Redistributor of the + * current CPU. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base = 0; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * The GICR_WAKER.Sleep bit should be set only when both + * GICR_WAKER.ChildrenAsleep and GICR_WAKER.ProcessorSleep are set on + * all the Redistributors. + */ + for (unsigned int i = 0; i < gicv3_driver_data->rdistif_num; i++) { + gicr_base = gicv3_driver_data->rdistif_base_addrs[i]; + assert(gicr_base); + assert(gicr_read_waker(gicr_base) & WAKER_CA_BIT); + assert(gicr_read_waker(gicr_base) & WAKER_PS_BIT); + } + + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + + /* + * Set GICR_WAKER.Sleep + * After this point, the system must be configured so that the + * wake_request signals for the right cores are asserted when a wakeup + * interrupt is detected. The GIC will not be able to do that anymore + * when the GICR_WAKER.Sleep bit is set to 1. + */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_SL_BIT); + + /* Wait until the GICR_WAKER.Quiescent bit is set */ + while (!(gicr_read_waker(gicr_base) & WAKER_QSC_BIT)) + ; +} + +/* + * Allow the LPIs pending state to be read back from the tables in memory after + * having restored the state of the GIC Redistributor. + */ +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data); + assert(gicv3_driver_data->rdistif_base_addrs); + + /* + * According to the TRM, there is only one instance of the + * GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits that can be accessed + * through any of the Redistributor. + */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[rdist_proc_num]; + assert(gicr_base); + + /* + * If the GIC had power removed, the GICR_WAKER state will be reset. + * Since the GICR_WAKER.Sleep and GICR_WAKER.Quiescent bits are cleared, + * we can exit early. This also prevents the following assert from + * erroneously triggering. + */ + if (!(gicr_read_waker(gicr_base) & WAKER_SL_BIT)) + return; + + /* + * Writes to GICR_WAKER.Sleep bit are ignored if GICR_WAKER.Quiescent + * bit is not set. We should be alright on power on path, therefore + * coming out of sleep and Quiescent should be set, but we assert in + * case. + */ + assert(gicr_read_waker(gicr_base) & WAKER_QSC_BIT); + + /* Clear GICR_WAKER.Sleep */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_SL_BIT); + + /* + * We don't know if the effects of setting GICR_WAKER.Sleep bit is + * instantaneous, so we wait until the interface is not Quiescent + * anymore. + */ + while (gicr_read_waker(gicr_base) & WAKER_QSC_BIT) + ; +} + diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c new file mode 100644 index 0000000..aaef485 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c @@ -0,0 +1,172 @@ +/* + * 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 + */ + +/* + * Driver for GIC-500 and GIC-600 specific features. This driver only + * overrides APIs that are different to those generic ones in GICv3 + * driver. + * + * GIC-600 supports independently power-gating redistributor interface. + */ + +#include + +#include +#include +#include + +#include "gicv3_private.h" + +/* GIC-600 specific register offsets */ +#define GICR_PWRR 0x24U + +/* GICR_PWRR fields */ +#define PWRR_RDPD_SHIFT 0 +#define PWRR_RDAG_SHIFT 1 +#define PWRR_RDGPD_SHIFT 2 +#define PWRR_RDGPO_SHIFT 3 + +#define PWRR_RDPD (1U << PWRR_RDPD_SHIFT) +#define PWRR_RDAG (1U << PWRR_RDAG_SHIFT) +#define PWRR_RDGPD (1U << PWRR_RDGPD_SHIFT) +#define PWRR_RDGPO (1U << PWRR_RDGPO_SHIFT) + +/* + * Values to write to GICR_PWRR register to power redistributor + * for operating through the core (GICR_PWRR.RDAG = 0) + */ +#define PWRR_ON (0U << PWRR_RDPD_SHIFT) +#define PWRR_OFF (1U << PWRR_RDPD_SHIFT) + +#if GICV3_SUPPORT_GIC600 + +/* GIC-600/700 specific accessor functions */ +static void gicr_write_pwrr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_PWRR, val); +} + +static uint32_t gicr_read_pwrr(uintptr_t base) +{ + return mmio_read_32(base + GICR_PWRR); +} + +static void gicr_wait_group_not_in_transit(uintptr_t base) +{ + uint32_t pwrr; + + do { + pwrr = gicr_read_pwrr(base); + + /* Check group not transitioning: RDGPD == RDGPO */ + } while (((pwrr & PWRR_RDGPD) >> PWRR_RDGPD_SHIFT) != + ((pwrr & PWRR_RDGPO) >> PWRR_RDGPO_SHIFT)); +} + +static void gic600_pwr_on(uintptr_t base) +{ + do { /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + + /* Power on redistributor */ + gicr_write_pwrr(base, PWRR_ON); + + /* + * Wait until the power on state is reflected. + * If RDPD == 0 then powered on. + */ + } while ((gicr_read_pwrr(base) & PWRR_RDPD) != PWRR_ON); +} + +static void gic600_pwr_off(uintptr_t base) +{ + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + + /* Power off redistributor */ + gicr_write_pwrr(base, PWRR_OFF); + + /* + * If this is the last man, turning this redistributor frame off will + * result in the group itself being powered off and RDGPD = 1. + * In that case, wait as long as it's in transition, or has aborted + * the transition altogether for any reason. + */ + if ((gicr_read_pwrr(base) & PWRR_RDGPD) != 0U) { + /* Wait until group not transitioning */ + gicr_wait_group_not_in_transit(base); + } +} + +static uintptr_t get_gicr_base(unsigned int proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0UL); + + return gicr_base; +} + +static bool gicv3_redists_need_power_mgmt(uintptr_t gicr_base) +{ + uint32_t reg = mmio_read_32(gicr_base + GICR_IIDR); + + /* + * The Arm GIC-600 and GIC-700 models have their redistributors + * powered down at reset. + */ + return (((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600) || + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_600AE) || + ((reg & IIDR_MODEL_MASK) == IIDR_MODEL_ARM_GIC_700)); +} + +#endif /* GICV3_SUPPORT_GIC600 */ + +void gicv3_distif_pre_save(unsigned int proc_num) +{ + arm_gicv3_distif_pre_save(proc_num); +} + +void gicv3_distif_post_restore(unsigned int proc_num) +{ + arm_gicv3_distif_post_restore(proc_num); +} + +/* + * Power off GIC-600 redistributor (if configured and detected) + */ +void gicv3_rdistif_off(unsigned int proc_num) +{ +#if GICV3_SUPPORT_GIC600 + uintptr_t gicr_base = get_gicr_base(proc_num); + + /* Attempt to power redistributor off */ + if (gicv3_redists_need_power_mgmt(gicr_base)) { + gic600_pwr_off(gicr_base); + } +#endif +} + +/* + * Power on GIC-600 redistributor (if configured and detected) + */ +void gicv3_rdistif_on(unsigned int proc_num) +{ +#if GICV3_SUPPORT_GIC600 + uintptr_t gicr_base = get_gicr_base(proc_num); + + /* Power redistributor on */ + if (gicv3_redists_need_power_mgmt(gicr_base)) { + gic600_pwr_on(gicr_base); + } +#endif +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c new file mode 100644 index 0000000..5f42ad9 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * GIC-600 driver extension for multichip setup + */ + +#include + +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gic600_multichip_private.h" + +/******************************************************************************* + * GIC-600 multichip operation related helper functions + ******************************************************************************/ +static void gicd_dchipr_wait_for_power_update_progress(uintptr_t base) +{ + unsigned int retry = GICD_PUP_UPDATE_RETRIES; + + while ((read_gicd_dchipr(base) & GICD_DCHIPR_PUP_BIT) != 0U) { + if (retry-- == 0) { + ERROR("GIC-600 connection to Routing Table Owner timed " + "out\n"); + panic(); + } + } +} + +/******************************************************************************* + * Sets up the routing table owner. + ******************************************************************************/ +static void set_gicd_dchipr_rt_owner(uintptr_t base, unsigned int rt_owner) +{ + /* + * Ensure that Group enables in GICD_CTLR are disabled and no pending + * register writes to GICD_CTLR. + */ + if ((gicd_read_ctlr(base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes. Cannot set RT owner.\n"); + panic(); + } + + /* Poll till PUP is zero before intiating write */ + gicd_dchipr_wait_for_power_update_progress(base); + + write_gicd_dchipr(base, read_gicd_dchipr(base) | + (rt_owner << GICD_DCHIPR_RT_OWNER_SHIFT)); + + /* Poll till PUP is zero to ensure write is complete */ + gicd_dchipr_wait_for_power_update_progress(base); +} + +/******************************************************************************* + * Configures the Chip Register to make connections to GICDs on + * a multichip platform. + ******************************************************************************/ +static void set_gicd_chipr_n(uintptr_t base, + unsigned int chip_id, + uint64_t chip_addr, + unsigned int spi_id_min, + unsigned int spi_id_max) +{ + unsigned int spi_block_min, spi_blocks; + unsigned int gicd_iidr_val = gicd_read_iidr(base); + uint64_t chipr_n_val; + + /* + * Ensure that group enables in GICD_CTLR are disabled and no pending + * register writes to GICD_CTLR. + */ + if ((gicd_read_ctlr(base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes. Cannot set CHIPR register.\n"); + panic(); + } + + /* + * spi_id_min and spi_id_max of value 0 is used to intidicate that the + * chip doesn't own any SPI block. Re-assign min and max values as SPI + * id starts from 32. + */ + if (spi_id_min == 0 && spi_id_max == 0) { + spi_id_min = GIC600_SPI_ID_MIN; + spi_id_max = GIC600_SPI_ID_MIN; + } + + spi_block_min = SPI_BLOCK_MIN_VALUE(spi_id_min); + spi_blocks = SPI_BLOCKS_VALUE(spi_id_min, spi_id_max); + + switch ((gicd_iidr_val & IIDR_MODEL_MASK)) { + case IIDR_MODEL_ARM_GIC_600: + chipr_n_val = GICD_CHIPR_VALUE_GIC_600(chip_addr, + spi_block_min, + spi_blocks); + break; + case IIDR_MODEL_ARM_GIC_700: + chipr_n_val = GICD_CHIPR_VALUE_GIC_700(chip_addr, + spi_block_min, + spi_blocks); + break; + default: + ERROR("Unsupported GIC model 0x%x for multichip setup.\n", + gicd_iidr_val); + panic(); + break; + } + chipr_n_val |= GICD_CHIPRx_SOCKET_STATE; + + /* + * Wait for DCHIPR.PUP to be zero before commencing writes to + * GICD_CHIPRx. + */ + gicd_dchipr_wait_for_power_update_progress(base); + + /* + * Assign chip addr, spi min block, number of spi blocks and bring chip + * online by setting SocketState. + */ + write_gicd_chipr_n(base, chip_id, chipr_n_val); + + /* + * Poll until DCHIP.PUP is zero to verify connection to rt_owner chip + * is complete. + */ + gicd_dchipr_wait_for_power_update_progress(base); + + /* + * Ensure that write to GICD_CHIPRx is successful and the chip_n came + * online. + */ + if (read_gicd_chipr_n(base, chip_id) != chipr_n_val) { + ERROR("GICD_CHIPR%u write failed\n", chip_id); + panic(); + } + + /* Ensure that chip is in consistent state */ + if (((read_gicd_chipsr(base) & GICD_CHIPSR_RTS_MASK) >> + GICD_CHIPSR_RTS_SHIFT) != + GICD_CHIPSR_RTS_STATE_CONSISTENT) { + ERROR("Chip %u routing table is not in consistent state\n", + chip_id); + panic(); + } +} + +/******************************************************************************* + * Validates the GIC-600 Multichip data structure passed by the platform. + ******************************************************************************/ +static void gic600_multichip_validate_data( + struct gic600_multichip_data *multichip_data) +{ + unsigned int i, spi_id_min, spi_id_max, blocks_of_32; + unsigned int multichip_spi_blocks = 0; + + assert(multichip_data != NULL); + + if (multichip_data->chip_count > GIC600_MAX_MULTICHIP) { + ERROR("GIC-600 Multichip count should not exceed %d\n", + GIC600_MAX_MULTICHIP); + panic(); + } + + for (i = 0; i < multichip_data->chip_count; i++) { + spi_id_min = multichip_data->spi_ids[i][SPI_MIN_INDEX]; + spi_id_max = multichip_data->spi_ids[i][SPI_MAX_INDEX]; + + if ((spi_id_min != 0) || (spi_id_max != 0)) { + + /* SPI IDs range check */ + if (!(spi_id_min >= GIC600_SPI_ID_MIN) || + !(spi_id_max < GIC600_SPI_ID_MAX) || + !(spi_id_min <= spi_id_max) || + !((spi_id_max - spi_id_min + 1) % 32 == 0)) { + ERROR("Invalid SPI IDs {%u, %u} passed for " + "Chip %u\n", spi_id_min, + spi_id_max, i); + panic(); + } + + /* SPI IDs overlap check */ + blocks_of_32 = BLOCKS_OF_32(spi_id_min, spi_id_max); + if ((multichip_spi_blocks & blocks_of_32) != 0) { + ERROR("SPI IDs of Chip %u overlapping\n", i); + panic(); + } + multichip_spi_blocks |= blocks_of_32; + } + } +} + +/******************************************************************************* + * Intialize GIC-600 Multichip operation. + ******************************************************************************/ +void gic600_multichip_init(struct gic600_multichip_data *multichip_data) +{ + unsigned int i; + + gic600_multichip_validate_data(multichip_data); + + /* + * Ensure that G0/G1S/G1NS interrupts are disabled. This also ensures + * that GIC-600 Multichip configuration is done first. + */ + if ((gicd_read_ctlr(multichip_data->rt_owner_base) & + (CTLR_ENABLE_G0_BIT | CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT | GICD_CTLR_RWP_BIT)) != 0) { + ERROR("GICD_CTLR group interrupts are either enabled or have " + "pending writes.\n"); + panic(); + } + + /* Ensure that the routing table owner is in disconnected state */ + if (((read_gicd_chipsr(multichip_data->rt_owner_base) & + GICD_CHIPSR_RTS_MASK) >> GICD_CHIPSR_RTS_SHIFT) != + GICD_CHIPSR_RTS_STATE_DISCONNECTED) { + ERROR("GIC-600 routing table owner is not in disconnected " + "state to begin multichip configuration\n"); + panic(); + } + + /* Initialize the GICD which is marked as routing table owner first */ + set_gicd_dchipr_rt_owner(multichip_data->rt_owner_base, + multichip_data->rt_owner); + + set_gicd_chipr_n(multichip_data->rt_owner_base, multichip_data->rt_owner, + multichip_data->chip_addrs[multichip_data->rt_owner], + multichip_data-> + spi_ids[multichip_data->rt_owner][SPI_MIN_INDEX], + multichip_data-> + spi_ids[multichip_data->rt_owner][SPI_MAX_INDEX]); + + for (i = 0; i < multichip_data->chip_count; i++) { + if (i == multichip_data->rt_owner) + continue; + + set_gicd_chipr_n(multichip_data->rt_owner_base, i, + multichip_data->chip_addrs[i], + multichip_data->spi_ids[i][SPI_MIN_INDEX], + multichip_data->spi_ids[i][SPI_MAX_INDEX]); + } +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h new file mode 100644 index 0000000..5d1ff6a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600_MULTICHIP_PRIVATE_H +#define GIC600_MULTICHIP_PRIVATE_H + +#include + +#include "gicv3_private.h" + +/* GIC600 GICD multichip related offsets */ +#define GICD_CHIPSR U(0xC000) +#define GICD_DCHIPR U(0xC004) +#define GICD_CHIPR U(0xC008) + +/* GIC600 GICD multichip related masks */ +#define GICD_CHIPRx_PUP_BIT BIT_64(1) +#define GICD_CHIPRx_SOCKET_STATE BIT_64(0) +#define GICD_DCHIPR_PUP_BIT BIT_32(0) +#define GICD_CHIPSR_RTS_MASK (BIT_32(4) | BIT_32(5)) + +/* GIC600 GICD multichip related shifts */ +#define GICD_CHIPRx_ADDR_SHIFT 16 +#define GICD_CHIPSR_RTS_SHIFT 4 +#define GICD_DCHIPR_RT_OWNER_SHIFT 4 + +/* Other shifts and masks remain the same between GIC-600 and GIC-700. */ +#define GIC_700_SPI_BLOCK_MIN_SHIFT 9 +#define GIC_700_SPI_BLOCKS_SHIFT 3 +#define GIC_600_SPI_BLOCK_MIN_SHIFT 10 +#define GIC_600_SPI_BLOCKS_SHIFT 5 + +#define GICD_CHIPSR_RTS_STATE_DISCONNECTED U(0) +#define GICD_CHIPSR_RTS_STATE_UPDATING U(1) +#define GICD_CHIPSR_RTS_STATE_CONSISTENT U(2) + +/* SPI interrupt id minimum and maximum range */ +#define GIC600_SPI_ID_MIN 32 +#define GIC600_SPI_ID_MAX 960 + +/* Number of retries for PUP update */ +#define GICD_PUP_UPDATE_RETRIES 10000 + +#define SPI_MIN_INDEX 0 +#define SPI_MAX_INDEX 1 + +#define SPI_BLOCK_MIN_VALUE(spi_id_min) \ + (((spi_id_min) - GIC600_SPI_ID_MIN) / \ + GIC600_SPI_ID_MIN) +#define SPI_BLOCKS_VALUE(spi_id_min, spi_id_max) \ + (((spi_id_max) - (spi_id_min) + 1) / \ + GIC600_SPI_ID_MIN) +#define GICD_CHIPR_VALUE_GIC_700(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_700_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_700_SPI_BLOCKS_SHIFT)) +#define GICD_CHIPR_VALUE_GIC_600(chip_addr, spi_block_min, spi_blocks) \ + (((chip_addr) << GICD_CHIPRx_ADDR_SHIFT) | \ + ((spi_block_min) << GIC_600_SPI_BLOCK_MIN_SHIFT) | \ + ((spi_blocks) << GIC_600_SPI_BLOCKS_SHIFT)) + +/* + * Multichip data assertion macros + */ +/* Set bits from 0 to ((spi_id_max + 1) / 32) */ +#define SPI_BLOCKS_TILL_MAX(spi_id_max) ((1 << (((spi_id_max) + 1) >> 5)) - 1) +/* Set bits from 0 to (spi_id_min / 32) */ +#define SPI_BLOCKS_TILL_MIN(spi_id_min) ((1 << ((spi_id_min) >> 5)) - 1) +/* Set bits from (spi_id_min / 32) to ((spi_id_max + 1) / 32) */ +#define BLOCKS_OF_32(spi_id_min, spi_id_max) \ + SPI_BLOCKS_TILL_MAX(spi_id_max) ^ \ + SPI_BLOCKS_TILL_MIN(spi_id_min) + +/******************************************************************************* + * GIC-600 multichip operation related helper functions + ******************************************************************************/ +static inline uint32_t read_gicd_dchipr(uintptr_t base) +{ + return mmio_read_32(base + GICD_DCHIPR); +} + +static inline uint64_t read_gicd_chipr_n(uintptr_t base, uint8_t n) +{ + return mmio_read_64(base + (GICD_CHIPR + (8U * n))); +} + +static inline uint32_t read_gicd_chipsr(uintptr_t base) +{ + return mmio_read_32(base + GICD_CHIPSR); +} + +static inline void write_gicd_dchipr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICD_DCHIPR, val); +} + +static inline void write_gicd_chipr_n(uintptr_t base, uint8_t n, uint64_t val) +{ + mmio_write_64(base + (GICD_CHIPR + (8U * n)), val); +} + +#endif /* GIC600_MULTICHIP_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c new file mode 100644 index 0000000..7a033bd --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c @@ -0,0 +1,392 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Driver for GIC-600AE Fault Management Unit + */ + +#include +#include + +#include +#include +#include +#include + +/* GIC-600 AE FMU specific register offsets */ + +/* GIC-600 AE FMU specific macros */ +#define FMU_ERRIDR_NUM U(44) +#define FMU_ERRIDR_NUM_MASK U(0xFFFF) + +/* Safety mechanisms for GICD block */ +static char *gicd_sm_info[] = { + "Reserved", + "GICD dual lockstep error", + "GICD AXI4 slave interface error", + "GICD-PPI AXI4-Stream interface error", + "GICD-ITS AXI4-Stream interface error", + "GICD-SPI-Collator AXI4-Stream interface error", + "GICD AXI4 master interface error", + "SPI RAM DED error", + "SGI RAM DED error", + "Reserved", + "LPI RAM DED error", + "GICD-remote-GICD AXI4-Stream interface error", + "GICD Q-Channel interface error", + "GICD P-Channel interface error", + "SPI RAM address decode error", + "SGI RAM address decode error", + "Reserved", + "LPI RAM address decode error", + "FMU dual lockstep error", + "FMU ping ACK error", + "FMU APB parity error", + "GICD-Wake AXI4-Stream interface error", + "GICD PageOffset or Chip ID error", + "MBIST REQ error", + "SPI RAM SEC error", + "SGI RAM SEC error", + "Reserved", + "LPI RAM SEC error", + "User custom SM0 error", + "User custom SM1 error", + "GICD-ITS Monolithic switch error", + "GICD-ITS Q-Channel interface error", + "GICD-ITS Monolithic interface error", + "GICD FMU ClkGate override" +}; + +/* Safety mechanisms for PPI block */ +static char *ppi_sm_info[] = { + "Reserved", + "PPI dual lockstep error", + "PPI-GICD AXI4-Stream interface error", + "PPI-CPU-IF AXI4-Stream interface error", + "PPI Q-Channel interface error", + "PPI RAM DED error", + "PPI RAM address decode error", + "PPI RAM SEC error", + "PPI User0 SM", + "PPI User1 SM", + "MBIST REQ error", + "PPI interrupt parity protection error", + "PPI FMU ClkGate override" +}; + +/* Safety mechanisms for ITS block */ +static char *its_sm_info[] = { + "Reserved", + "ITS dual lockstep error", + "ITS-GICD AXI4-Stream interface error", + "ITS AXI4 slave interface error", + "ITS AXI4 master interface error", + "ITS Q-Channel interface error", + "ITS RAM DED error", + "ITS RAM address decode error", + "Bypass ACE switch error", + "ITS RAM SEC error", + "ITS User0 SM", + "ITS User1 SM", + "ITS-GICD Monolithic interface error", + "MBIST REQ error", + "ITS FMU ClkGate override" +}; + +/* Safety mechanisms for SPI Collator block */ +static char *spicol_sm_info[] = { + "Reserved", + "SPI Collator dual lockstep error", + "SPI-Collator-GICD AXI4-Stream interface error", + "SPI Collator Q-Channel interface error", + "SPI Collator Q-Channel clock error", + "SPI interrupt parity error" +}; + +/* Safety mechanisms for Wake Request block */ +static char *wkrqst_sm_info[] = { + "Reserved", + "Wake dual lockstep error", + "Wake-GICD AXI4-Stream interface error" +}; + +/* Helper function to find detailed information for a specific IERR */ +static char *ras_ierr_to_str(unsigned int blkid, unsigned int ierr) +{ + char *str = NULL; + + /* Find the correct record */ + switch (blkid) { + case FMU_BLK_GICD: + assert(ierr < ARRAY_SIZE(gicd_sm_info)); + str = gicd_sm_info[ierr]; + break; + + case FMU_BLK_SPICOL: + assert(ierr < ARRAY_SIZE(spicol_sm_info)); + str = spicol_sm_info[ierr]; + break; + + case FMU_BLK_WAKERQ: + assert(ierr < ARRAY_SIZE(wkrqst_sm_info)); + str = wkrqst_sm_info[ierr]; + break; + + case FMU_BLK_ITS0...FMU_BLK_ITS7: + assert(ierr < ARRAY_SIZE(its_sm_info)); + str = its_sm_info[ierr]; + break; + + case FMU_BLK_PPI0...FMU_BLK_PPI31: + assert(ierr < ARRAY_SIZE(ppi_sm_info)); + str = ppi_sm_info[ierr]; + break; + + default: + assert(1); + break; + } + + return str; +} + +/* + * Probe for error in memory-mapped registers containing error records. + * Upon detecting an error, set probe data to the index of the record + * in error, and return 1; otherwise, return 0. + */ +int gic600_fmu_probe(uint64_t base, int *probe_data) +{ + uint64_t gsr; + + assert(base != 0UL); + + /* + * Read ERR_GSR to find the error record 'M' + */ + gsr = gic_fmu_read_errgsr(base); + if (gsr == U(0)) { + return 0; + } + + /* Return the index of the record in error */ + if (probe_data != NULL) { + *probe_data = (int)__builtin_ctzll(gsr); + } + + return 1; +} + +/* + * The handler function to read RAS records and find the safety + * mechanism with the error. + */ +int gic600_fmu_ras_handler(uint64_t base, int probe_data) +{ + uint64_t errstatus; + unsigned int blkid, ierr, serr; + + assert(base != 0UL); + assert((unsigned int)probe_data <= FMU_BLK_PPI31); + + /* + * Find more information by reading FMU_ERRSTATUS + * register + */ + errstatus = gic_fmu_read_errstatus(base, probe_data); + + /* + * If FMU_ERRSTATUS.V is set to 0, no RAS records + * need to be scanned. + */ + if ((errstatus & FMU_ERRSTATUS_V_BIT) == U(0)) { + return 0; + } + + /* + * FMU_ERRGSR indicates the ID of the GIC + * block that faulted. + */ + blkid = (unsigned int)probe_data; + assert(blkid <= FMU_BLK_PPI31); + + /* + * FMU_ERRSTATUS.IERR indicates which Safety Mechanism + * reported the error. + */ + ierr = (errstatus >> FMU_ERRSTATUS_IERR_SHIFT) & + FMU_ERRSTATUS_IERR_MASK; + + /* + * FMU_ERRSTATUS.SERR indicates architecturally + * defined primary error code. + */ + serr = errstatus & FMU_ERRSTATUS_SERR_MASK; + + ERROR("**************************************\n"); + ERROR("RAS %s Error detected by GIC600 AE FMU\n", + ((errstatus & FMU_ERRSTATUS_UE_BIT) != 0U) ? + "Uncorrectable" : "Corrected"); + ERROR("\tStatus = 0x%" PRIx64 "\n", errstatus); + ERROR("\tBlock ID = 0x%x\n", blkid); + ERROR("\tSafety Mechanism ID = 0x%x (%s)\n", ierr, + ras_ierr_to_str(blkid, ierr)); + ERROR("\tArchitecturally defined primary error code = 0x%x\n", + serr); + ERROR("**************************************\n"); + + /* Clear FMU_ERRSTATUS */ + gic_fmu_write_errstatus(base, probe_data, errstatus); + + return 0; +} + +/* + * Initialization sequence for the FMU + * + * 1. enable error detection for error records that are passed in the blk_present_mask + * 2. enable MBIST REQ and FMU Clk Gate override safety mechanisms for error records + * that are present on the platform + * + * The platforms are expected to pass `errctlr_ce_en` and `errctlr_ue_en`. + */ +void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, + bool errctlr_ce_en, bool errctlr_ue_en) +{ + unsigned int num_blk = gic_fmu_read_erridr(base) & FMU_ERRIDR_NUM_MASK; + uint64_t errctlr; + uint32_t smen; + + INFO("GIC600-AE FMU supports %d error records\n", num_blk); + + assert(num_blk == FMU_ERRIDR_NUM); + + /* sanitize block present mask */ + blk_present_mask &= FMU_BLK_PRESENT_MASK; + + /* Enable error detection for all error records */ + for (unsigned int i = 0U; i < num_blk; i++) { + + /* Skip next steps if the block is not present */ + if ((blk_present_mask & BIT(i)) == 0U) { + continue; + } + + /* Read the error record control register */ + errctlr = gic_fmu_read_errctlr(base, i); + + /* Enable error reporting and logging, if it is disabled */ + if ((errctlr & FMU_ERRCTLR_ED_BIT) == 0U) { + errctlr |= FMU_ERRCTLR_ED_BIT; + } + + /* Enable client provided ERRCTLR settings */ + errctlr |= (errctlr_ce_en ? (FMU_ERRCTLR_CI_BIT | FMU_ERRCTLR_CE_EN_BIT) : 0); + errctlr |= (errctlr_ue_en ? FMU_ERRCTLR_UI_BIT : 0U); + + gic_fmu_write_errctlr(base, i, errctlr); + } + + /* + * Disable all safety mechanisms for blocks that are not + * present + */ + for (unsigned int i = FMU_BLK_GICD; i <= FMU_BLK_PPI31; i++) { + if ((blk_present_mask & BIT(i)) == 0U) { + gic_fmu_disable_all_sm_blkid(base, i); + } + } + + /* + * Enable MBIST REQ error and FMU CLK gate override safety mechanisms for + * all blocks + * + * GICD, SMID 23 and SMID 33 + * PPI, SMID 10 and SMID 12 + * ITS, SMID 13 and SMID 14 + */ + if ((blk_present_mask & BIT(FMU_BLK_GICD)) != 0U) { + smen = (GICD_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (GICD_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (FMU_BLK_GICD << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + + for (unsigned int i = FMU_BLK_PPI0; i < FMU_BLK_PPI31; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (PPI_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (PPI_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + } + + for (unsigned int i = FMU_BLK_ITS0; i < FMU_BLK_ITS7; i++) { + if ((blk_present_mask & BIT(i)) != 0U) { + smen = (ITS_MBIST_REQ_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + + smen = (ITS_FMU_CLKGATE_ERROR << FMU_SMEN_SMID_SHIFT) | + (i << FMU_SMEN_BLK_SHIFT) | + FMU_SMEN_EN_BIT; + gic_fmu_write_smen(base, smen); + } + } +} + +/* + * This function enable the GICD background ping engine. The GICD sends ping + * messages to each remote GIC block, and expects a PING_ACK back within the + * specified timeout. Pings need to be enabled after programming the timeout + * value. + */ +void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, + unsigned int timeout_val, unsigned int interval_diff) +{ + /* + * Populate the PING Mask to skip a specific block while generating + * background ping messages and enable the ping mechanism. + */ + gic_fmu_write_pingmask(base, ~blk_present_mask); + gic_fmu_write_pingctlr(base, (interval_diff << FMU_PINGCTLR_INTDIFF_SHIFT) | + (timeout_val << FMU_PINGCTLR_TIMEOUTVAL_SHIFT) | FMU_PINGCTLR_EN_BIT); +} + +/* Print the safety mechanism description for a given block */ +void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid) +{ + if (blk == FMU_BLK_GICD && smid <= FMU_SMID_GICD_MAX) { + INFO("GICD, SMID %d: %s\n", smid, gicd_sm_info[smid]); + } + + if (blk == FMU_BLK_SPICOL && smid <= FMU_SMID_SPICOL_MAX) { + INFO("SPI Collator, SMID %d: %s\n", smid, spicol_sm_info[smid]); + } + + if (blk == FMU_BLK_WAKERQ && (smid <= FMU_SMID_WAKERQ_MAX)) { + INFO("Wake Request, SMID %d: %s\n", smid, wkrqst_sm_info[smid]); + } + + if (((blk >= FMU_BLK_ITS0) && (blk <= FMU_BLK_ITS7)) && (smid <= FMU_SMID_ITS_MAX)) { + INFO("ITS, SMID %d: %s\n", smid, its_sm_info[smid]); + } + + if (((blk >= FMU_BLK_PPI0) && (blk <= FMU_BLK_PPI31)) && (smid <= FMU_SMID_PPI_MAX)) { + INFO("PPI, SMID %d: %s\n", smid, ppi_sm_info[smid]); + } +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c new file mode 100644 index 0000000..b1abd0a --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define GICFMU_IDLE_TIMEOUT_US U(2000000) + +/* Macro to write 32-bit FMU registers */ +#define GIC_FMU_WRITE_32(base, reg, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* Perform the actual write */ \ + mmio_write_32((base) + (reg), (val)); \ + } while (false) + +/* Macro to write 64-bit FMU registers */ +#define GIC_FMU_WRITE_64(base, reg, n, val) \ + do { \ + /* \ + * This register receives the unlock key that is required for \ + * writes to FMU registers to be successful. \ + */ \ + mmio_write_32(base + GICFMU_KEY, 0xBE); \ + /* \ + * APB bus is 32-bit wide; so split the 64-bit write into \ + * two 32-bit writes \ + */ \ + mmio_write_32((base) + reg##_LO + (n * 64), (val)); \ + mmio_write_32((base) + reg##_HI + (n * 64), (val)); \ + } while (false) + +/* Helper function to wait until FMU is ready to accept the next command */ +static void wait_until_fmu_is_idle(uintptr_t base) +{ + uint32_t timeout_count = GICFMU_IDLE_TIMEOUT_US; + uint64_t status; + + /* wait until status is 'busy' */ + do { + status = (gic_fmu_read_status(base) & BIT(0)); + + if (timeout_count-- == 0U) { + ERROR("GIC600 AE FMU is not responding\n"); + panic(); + } + + udelay(1U); + + } while (status == U(0)); +} + +#define GIC_FMU_WRITE_ON_IDLE_32(base, reg, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_32(base, reg, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +#define GIC_FMU_WRITE_ON_IDLE_64(base, reg, n, val) \ + do { \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + /* Actual register write */ \ + GIC_FMU_WRITE_64(base, reg, n, val); \ + /* Wait until FMU is ready */ \ + wait_until_fmu_is_idle(base); \ + } while (false) + +/******************************************************************************* + * GIC FMU functions for accessing the Fault Management Unit registers + ******************************************************************************/ + +/* + * Accessors to read the Error Record Feature Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRFR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRFR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Control Register bits corresponding + * to an error record 'n' + */ +uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRCTLR_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Record Primary Status Register bits + * corresponding to an error record 'n' + */ +uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_LO + n * 64U); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRSTATUS_HI + n * 64U) << 32); + return reg_val; +} + +/* + * Accessors to read the Error Group Status Register + */ +uint64_t gic_fmu_read_errgsr(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_ERRGSR_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_ERRGSR_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the Ping Control Register + */ +uint32_t gic_fmu_read_pingctlr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGCTLR); +} + +/* + * Accessors to read the Ping Now Register + */ +uint32_t gic_fmu_read_pingnow(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_PINGNOW); +} + +/* + * Accessors to read the Ping Mask Register + */ +uint64_t gic_fmu_read_pingmask(uintptr_t base) +{ + /* + * APB bus is 32-bit wide; so split the 64-bit read into + * two 32-bit reads + */ + uint64_t reg_val = (uint64_t)mmio_read_32(base + GICFMU_PINGMASK_LO); + + reg_val |= ((uint64_t)mmio_read_32(base + GICFMU_PINGMASK_HI) << 32); + return reg_val; +} + +/* + * Accessors to read the FMU Status Register + */ +uint32_t gic_fmu_read_status(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_STATUS); +} + +/* + * Accessors to read the Error Record ID Register + */ +uint32_t gic_fmu_read_erridr(uintptr_t base) +{ + return mmio_read_32(base + GICFMU_ERRIDR); +} + +/* + * Accessors to write a 64 bit value to the Error Record Control Register + */ +void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_ERRCTLR, n, val); +} + +/* + * Accessors to write a 64 bit value to the Error Record Primary Status + * Register + */ +void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_64(base, GICFMU_ERRSTATUS, n, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Control Register + */ +void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val) +{ + GIC_FMU_WRITE_32(base, GICFMU_PINGCTLR, val); +} + +/* + * Accessors to write a 32 bit value to the Ping Now Register + */ +void gic_fmu_write_pingnow(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_PINGNOW, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Enable Register + */ +void gic_fmu_write_smen(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMEN, val); +} + +/* + * Accessors to write a 32 bit value to the Safety Mechanism Inject Error + * Register + */ +void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val) +{ + /* Wait until FMU is ready before writing */ + GIC_FMU_WRITE_ON_IDLE_32(base, GICFMU_SMINJERR, val); +} + +/* + * Accessors to write a 64 bit value to the Ping Mask Register + */ +void gic_fmu_write_pingmask(uintptr_t base, uint64_t val) +{ + GIC_FMU_WRITE_64(base, GICFMU_PINGMASK, 0, val); +} + +/* + * Helper function to disable all safety mechanisms for a given block + */ +void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid) +{ + uint32_t smen, max_smid = U(0); + + /* Sanity check block ID */ + assert((blkid >= FMU_BLK_GICD) && (blkid <= FMU_BLK_PPI31)); + + /* Find the max safety mechanism ID for the block */ + switch (blkid) { + case FMU_BLK_GICD: + max_smid = FMU_SMID_GICD_MAX; + break; + + case FMU_BLK_SPICOL: + max_smid = FMU_SMID_SPICOL_MAX; + break; + + case FMU_BLK_WAKERQ: + max_smid = FMU_SMID_WAKERQ_MAX; + break; + + case FMU_BLK_ITS0...FMU_BLK_ITS7: + max_smid = FMU_SMID_ITS_MAX; + break; + + case FMU_BLK_PPI0...FMU_BLK_PPI31: + max_smid = FMU_SMID_PPI_MAX; + break; + + default: + assert(1); + break; + } + + /* Disable all Safety Mechanisms for a given block id */ + for (unsigned int i = 0; i < max_smid; i++) { + smen = (blkid << FMU_SMEN_BLK_SHIFT) | (i << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(base, smen); + } +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c new file mode 100644 index 0000000..987be69 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "gicv3_private.h" + +/******************************************************************************* + * GIC Distributor functions for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ + +/* + * Accessors to set the bits corresponding to interrupt ID + * in GIC Distributor ICFGR and ICFGRE. + */ +void gicd_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U; + + /* Clear the field, and insert required configuration */ + mmio_clrsetbits_32(base + GICD_OFFSET(ICFG, id), + (uint32_t)GIC_CFG_MASK << bit_shift, + (cfg & GIC_CFG_MASK) << bit_shift); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt ID + * in GIC Distributor IGROUPR and IGROUPRE. + */ +unsigned int gicd_get_igroupr(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(IGROUP, base, id); +} + +void gicd_set_igroupr(uintptr_t base, unsigned int id) +{ + GICD_SET_BIT(IGROUP, base, id); +} + +void gicd_clr_igroupr(uintptr_t base, unsigned int id) +{ + GICD_CLR_BIT(IGROUP, base, id); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt ID + * in GIC Distributor IGRPMODR and IGRPMODRE. + */ +unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(IGRPMOD, base, id); +} + +void gicd_set_igrpmodr(uintptr_t base, unsigned int id) +{ + GICD_SET_BIT(IGRPMOD, base, id); +} + +void gicd_clr_igrpmodr(uintptr_t base, unsigned int id) +{ + GICD_CLR_BIT(IGRPMOD, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ICENABLER and ICENABLERE. + */ +void gicd_set_icenabler(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ICENABLE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ICPENDR and ICPENDRE. + */ +void gicd_set_icpendr(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ICPEND, base, id); +} + +/* + * Accessors to get/set the bit corresponding to interrupt ID + * in GIC Distributor ISACTIVER and ISACTIVERE. + */ +unsigned int gicd_get_isactiver(uintptr_t base, unsigned int id) +{ + return GICD_GET_BIT(ISACTIVE, base, id); +} + +void gicd_set_isactiver(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISACTIVE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ISENABLER and ISENABLERE. + */ +void gicd_set_isenabler(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISENABLE, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor ISPENDR and ISPENDRE. + */ +void gicd_set_ispendr(uintptr_t base, unsigned int id) +{ + GICD_WRITE_BIT(ISPEND, base, id); +} + +/* + * Accessors to set the bit corresponding to interrupt ID + * in GIC Distributor IPRIORITYR and IPRIORITYRE. + */ +void gicd_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + GICD_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK)); +} + +/******************************************************************************* + * GIC Distributor interface accessors for reading/writing entire registers + ******************************************************************************/ + +/* + * Accessors to read/write the GIC Distributor ICGFR and ICGFRE + * corresponding to the interrupt ID, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_icfgr(uintptr_t base, unsigned int id) +{ + return GICD_READ(ICFG, base, id); +} + +void gicd_write_icfgr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ICFG, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IGROUPR and IGROUPRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_igroupr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IGROUP, base, id); +} + +void gicd_write_igroupr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IGROUP, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IGRPMODR and IGRPMODRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IGRPMOD, base, id); +} + +void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IGRPMOD, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor IPRIORITYR and IPRIORITYRE + * corresponding to the interrupt ID, 4 interrupt IDs at a time. + */ +unsigned int gicd_read_ipriorityr(uintptr_t base, unsigned int id) +{ + return GICD_READ(IPRIORITY, base, id); +} + +void gicd_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(IPRIORITY, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISACTIVER and ISACTIVERE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isactiver(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISACTIVE, base, id); +} + +void gicd_write_isactiver(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISACTIVE, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISENABLER and ISENABLERE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_isenabler(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISENABLE, base, id); +} + +void gicd_write_isenabler(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISENABLE, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor ISPENDR and ISPENDRE + * corresponding to the interrupt ID, 32 interrupt IDs at a time. + */ +unsigned int gicd_read_ispendr(uintptr_t base, unsigned int id) +{ + return GICD_READ(ISPEND, base, id); +} + +void gicd_write_ispendr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(ISPEND, base, id, val); +} + +/* + * Accessors to read/write the GIC Distributor NSACR and NSACRE + * corresponding to the interrupt ID, 16 interrupt IDs at a time. + */ +unsigned int gicd_read_nsacr(uintptr_t base, unsigned int id) +{ + return GICD_READ(NSAC, base, id); +} + +void gicd_write_nsacr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICD_WRITE(NSAC, base, id, val); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c new file mode 100644 index 0000000..3004054 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "gicv3_private.h" + +/******************************************************************************* + * GIC Redistributor functions + * Note: The raw register values correspond to multiple interrupt `id`s and + * the number of interrupt `id`s involved depends on the register accessed. + ******************************************************************************/ + +/* + * Accessors to read/write the GIC Redistributor IPRIORITYR and IPRIORITYRE + * register corresponding to the interrupt `id`, 4 interrupts IDs at a time. + */ +unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id) +{ + return GICR_READ(IPRIORITY, base, id); +} + +void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val) +{ + GICR_WRITE(IPRIORITY, base, id, val); +} + +/* + * Accessor to set the byte corresponding to interrupt `id` + * in GIC Redistributor IPRIORITYR and IPRIORITYRE. + */ +void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri) +{ + GICR_WRITE_8(IPRIORITY, base, id, (uint8_t)(pri & GIC_PRI_MASK)); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt `id` + * from GIC Redistributor IGROUPR0 and IGROUPRE + */ +unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(IGROUP, base, id); +} + +void gicr_set_igroupr(uintptr_t base, unsigned int id) +{ + GICR_SET_BIT(IGROUP, base, id); +} + +void gicr_clr_igroupr(uintptr_t base, unsigned int id) +{ + GICR_CLR_BIT(IGROUP, base, id); +} + +/* + * Accessors to get/set/clear the bit corresponding to interrupt `id` + * from GIC Redistributor IGRPMODR0 and IGRPMODRE + */ +unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(IGRPMOD, base, id); +} + +void gicr_set_igrpmodr(uintptr_t base, unsigned int id) +{ + GICR_SET_BIT(IGRPMOD, base, id); +} + +void gicr_clr_igrpmodr(uintptr_t base, unsigned int id) +{ + GICR_CLR_BIT(IGRPMOD, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ISENABLER0 and ISENABLERE + */ +void gicr_set_isenabler(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ISENABLE, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ICENABLER0 and ICENABLERE + */ +void gicr_set_icenabler(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ICENABLE, base, id); +} + +/* + * Accessor to get the bit corresponding to interrupt `id` + * in GIC Redistributor ISACTIVER0 and ISACTIVERE + */ +unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id) +{ + return GICR_GET_BIT(ISACTIVE, base, id); +} + +/* + * Accessor to clear the bit corresponding to interrupt `id` + * in GIC Redistributor ICPENDR0 and ICPENDRE + */ +void gicr_set_icpendr(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ICPEND, base, id); +} + +/* + * Accessor to write the bit corresponding to interrupt `id` + * in GIC Redistributor ISPENDR0 and ISPENDRE + */ +void gicr_set_ispendr(uintptr_t base, unsigned int id) +{ + GICR_WRITE_BIT(ISPEND, base, id); +} + +/* + * Accessor to set the bit fields corresponding to interrupt `id` + * in GIC Redistributor ICFGR0, ICFGR1 and ICFGRE + */ +void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg) +{ + /* Interrupt configuration is a 2-bit field */ + unsigned int bit_shift = BIT_NUM(ICFG, id) << 1U; + + /* Clear the field, and insert required configuration */ + mmio_clrsetbits_32(base + GICR_OFFSET(ICFG, id), + (uint32_t)GIC_CFG_MASK << bit_shift, + (cfg & GIC_CFG_MASK) << bit_shift); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk new file mode 100644 index 0000000..8891ff5 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3.mk @@ -0,0 +1,50 @@ +# +# Copyright (c) 2013-2020, Arm Limited and Contributors. All rights reserved. +# Copyright (c) 2021, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default configuration values +GICV3_SUPPORT_GIC600 ?= 0 +GICV3_SUPPORT_GIC600AE_FMU ?= 0 +GICV3_IMPL_GIC600_MULTICHIP ?= 0 +GICV3_OVERRIDE_DISTIF_PWR_OPS ?= 0 +GIC_ENABLE_V4_EXTN ?= 0 +GIC_EXT_INTID ?= 0 +GICV3_RESTRICT_GICT_GICP_ACCESS ?= 0 + +GICV3_SOURCES += drivers/arm/gic/v3/gicv3_main.c \ + drivers/arm/gic/v3/gicv3_helpers.c \ + drivers/arm/gic/v3/gicdv3_helpers.c \ + drivers/arm/gic/v3/gicrv3_helpers.c + +ifeq (${GICV3_SUPPORT_GIC600AE_FMU}, 1) +GICV3_SOURCES += drivers/arm/gic/v3/gic600ae_fmu.c \ + drivers/arm/gic/v3/gic600ae_fmu_helpers.c +endif + +ifeq (${GICV3_OVERRIDE_DISTIF_PWR_OPS}, 0) +GICV3_SOURCES += drivers/arm/gic/v3/arm_gicv3_common.c +endif + +GICV3_SOURCES += drivers/arm/gic/v3/gic-x00.c +ifeq (${GICV3_IMPL_GIC600_MULTICHIP}, 1) +GICV3_SOURCES += drivers/arm/gic/v3/gic600_multichip.c +endif + +# Set GIC-600 support +$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600)) +$(eval $(call add_define,GICV3_SUPPORT_GIC600)) + +# Set GIC-600AE FMU support +$(eval $(call assert_boolean,GICV3_SUPPORT_GIC600AE_FMU)) +$(eval $(call add_define,GICV3_SUPPORT_GIC600AE_FMU)) + +# Set GICv4 extension +$(eval $(call assert_boolean,GIC_ENABLE_V4_EXTN)) +$(eval $(call add_define,GIC_ENABLE_V4_EXTN)) + +# Set support for extended PPI and SPI range +$(eval $(call assert_boolean,GIC_EXT_INTID)) +$(eval $(call add_define,GIC_EXT_INTID)) diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c new file mode 100644 index 0000000..753d995 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c @@ -0,0 +1,410 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "../common/gic_common_private.h" +#include "gicv3_private.h" + +/****************************************************************************** + * This function marks the core as awake in the re-distributor and + * ensures that the interface is active. + *****************************************************************************/ +void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base) +{ + /* + * The WAKER_PS_BIT should be changed to 0 + * only when WAKER_CA_BIT is 1. + */ + assert((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U); + + /* Mark the connected core as awake */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) & ~WAKER_PS_BIT); + + /* Wait till the WAKER_CA_BIT changes to 0 */ + while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) != 0U) { + } +} + +/****************************************************************************** + * This function marks the core as asleep in the re-distributor and ensures + * that the interface is quiescent. + *****************************************************************************/ +void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base) +{ + /* Mark the connected core as asleep */ + gicr_write_waker(gicr_base, gicr_read_waker(gicr_base) | WAKER_PS_BIT); + + /* Wait till the WAKER_CA_BIT changes to 1 */ + while ((gicr_read_waker(gicr_base) & WAKER_CA_BIT) == 0U) { + } +} + +/******************************************************************************* + * This function probes the Redistributor frames when the driver is initialised + * and saves their base addresses. These base addresses are used later to + * initialise each Redistributor interface. + ******************************************************************************/ +void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, + unsigned int rdistif_num, + uintptr_t gicr_base, + mpidr_hash_fn mpidr_to_core_pos) +{ + u_register_t mpidr; + unsigned int proc_num; + uint64_t typer_val; + uintptr_t rdistif_base = gicr_base; + + assert(rdistif_base_addrs != NULL); + + /* + * Iterate over the Redistributor frames. Store the base address of each + * frame in the platform provided array. Use the "Processor Number" + * field to index into the array if the platform has not provided a hash + * function to convert an MPIDR (obtained from the "Affinity Value" + * field into a linear index. + */ + do { + typer_val = gicr_read_typer(rdistif_base); + if (mpidr_to_core_pos != NULL) { + mpidr = mpidr_from_gicr_typer(typer_val); + proc_num = mpidr_to_core_pos(mpidr); + } else { + proc_num = (typer_val >> TYPER_PROC_NUM_SHIFT) & + TYPER_PROC_NUM_MASK; + } + + if (proc_num < rdistif_num) { + rdistif_base_addrs[proc_num] = rdistif_base; + } + rdistif_base += gicv3_redist_size(typer_val); + } while ((typer_val & TYPER_LAST_BIT) == 0U); +} + +/******************************************************************************* + * Helper function to get the maximum SPI INTID + 1. + ******************************************************************************/ +unsigned int gicv3_get_spi_limit(uintptr_t gicd_base) +{ + unsigned int spi_limit; + unsigned int typer_reg = gicd_read_typer(gicd_base); + + /* (maximum SPI INTID + 1) is equal to 32 * (GICD_TYPER.ITLinesNumber+1) */ + spi_limit = ((typer_reg & TYPER_IT_LINES_NO_MASK) + 1U) << 5; + + /* Filter out special INTIDs 1020-1023 */ + if (spi_limit > (MAX_SPI_ID + 1U)) { + return MAX_SPI_ID + 1U; + } + + return spi_limit; +} + +#if GIC_EXT_INTID +/******************************************************************************* + * Helper function to get the maximum ESPI INTID + 1. + ******************************************************************************/ +unsigned int gicv3_get_espi_limit(uintptr_t gicd_base) +{ + unsigned int typer_reg = gicd_read_typer(gicd_base); + + /* Check if extended SPI range is implemented */ + if ((typer_reg & TYPER_ESPI) != 0U) { + /* + * (maximum ESPI INTID + 1) is equal to + * 32 * (GICD_TYPER.ESPI_range + 1) + 4096 + */ + return ((((typer_reg >> TYPER_ESPI_RANGE_SHIFT) & + TYPER_ESPI_RANGE_MASK) + 1U) << 5) + MIN_ESPI_ID; + } + + return 0U; +} +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * Helper function to configure the default attributes of (E)SPIs. + ******************************************************************************/ +void gicv3_spis_config_defaults(uintptr_t gicd_base) +{ + unsigned int i, num_ints; +#if GIC_EXT_INTID + unsigned int num_eints; +#endif + + num_ints = gicv3_get_spi_limit(gicd_base); + INFO("Maximum SPI INTID supported: %u\n", num_ints - 1); + + /* Treat all (E)SPIs as G1NS by default. We do 32 at a time. */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << IGROUPR_SHIFT)) { + gicd_write_igroupr(gicd_base, i, ~0U); + } + +#if GIC_EXT_INTID + num_eints = gicv3_get_espi_limit(gicd_base); + if (num_eints != 0U) { + INFO("Maximum ESPI INTID supported: %u\n", num_eints - 1); + + for (i = MIN_ESPI_ID; i < num_eints; + i += (1U << IGROUPR_SHIFT)) { + gicd_write_igroupr(gicd_base, i, ~0U); + } + } else { + INFO("ESPI range is not implemented.\n"); + } +#endif + + /* Setup the default (E)SPI priorities doing four at a time */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << IPRIORITYR_SHIFT)) { + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + } + +#if GIC_EXT_INTID + for (i = MIN_ESPI_ID; i < num_eints; + i += (1U << IPRIORITYR_SHIFT)) { + gicd_write_ipriorityr(gicd_base, i, GICD_IPRIORITYR_DEF_VAL); + } +#endif + /* + * Treat all (E)SPIs as level triggered by default, write 16 at a time + */ + for (i = MIN_SPI_ID; i < num_ints; i += (1U << ICFGR_SHIFT)) { + gicd_write_icfgr(gicd_base, i, 0U); + } + +#if GIC_EXT_INTID + for (i = MIN_ESPI_ID; i < num_eints; i += (1U << ICFGR_SHIFT)) { + gicd_write_icfgr(gicd_base, i, 0U); + } +#endif +} + +/******************************************************************************* + * Helper function to configure properties of secure (E)SPIs + ******************************************************************************/ +unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *current_prop; + unsigned long long gic_affinity_val; + unsigned int ctlr_enable = 0U; + + /* Make sure there's a valid property array */ + if (interrupt_props_num > 0U) { + assert(interrupt_props != NULL); + } + + for (i = 0U; i < interrupt_props_num; i++) { + current_prop = &interrupt_props[i]; + + unsigned int intr_num = current_prop->intr_num; + + /* Skip SGI, (E)PPI and LPI interrupts */ + if (!IS_SPI(intr_num)) { + continue; + } + + /* Configure this interrupt as a secure interrupt */ + gicd_clr_igroupr(gicd_base, intr_num); + + /* Configure this interrupt as G0 or a G1S interrupt */ + assert((current_prop->intr_grp == INTR_GROUP0) || + (current_prop->intr_grp == INTR_GROUP1S)); + + if (current_prop->intr_grp == INTR_GROUP1S) { + gicd_set_igrpmodr(gicd_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G1S_BIT; + } else { + gicd_clr_igrpmodr(gicd_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G0_BIT; + } + + /* Set interrupt configuration */ + gicd_set_icfgr(gicd_base, intr_num, current_prop->intr_cfg); + + /* Set the priority of this interrupt */ + gicd_set_ipriorityr(gicd_base, intr_num, + current_prop->intr_pri); + + /* Target (E)SPIs to the primary CPU */ + gic_affinity_val = + gicd_irouter_val_from_mpidr(read_mpidr(), 0U); + gicd_write_irouter(gicd_base, intr_num, + gic_affinity_val); + + /* Enable this interrupt */ + gicd_set_isenabler(gicd_base, intr_num); + } + + return ctlr_enable; +} + +/******************************************************************************* + * Helper function to configure the default attributes of (E)SPIs + ******************************************************************************/ +void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base) +{ + unsigned int i, ppi_regs_num, regs_num; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* + * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. + * This is a more scalable approach as it avoids clearing + * the enable bits in the GICD_CTLR. + */ + for (i = 0U; i < ppi_regs_num; ++i) { + gicr_write_icenabler(gicr_base, i, ~0U); + } + + /* Wait for pending writes to GICR_ICENABLER */ + gicr_wait_for_pending_write(gicr_base); + + /* 32 interrupt IDs per GICR_IGROUPR register */ + for (i = 0U; i < ppi_regs_num; ++i) { + /* Treat all SGIs/(E)PPIs as G1NS by default */ + gicr_write_igroupr(gicr_base, i, ~0U); + } + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + /* Setup the default (E)PPI/SGI priorities doing 4 at a time */ + gicr_write_ipriorityr(gicr_base, i, GICD_IPRIORITYR_DEF_VAL); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = (MIN_PPI_ID >> ICFGR_SHIFT); i < regs_num; ++i) { + /* Configure all (E)PPIs as level triggered by default */ + gicr_write_icfgr(gicr_base, i, 0U); + } +} + +/******************************************************************************* + * Helper function to configure properties of secure G0 and G1S (E)PPIs and SGIs + ******************************************************************************/ +unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num) +{ + unsigned int i; + const interrupt_prop_t *current_prop; + unsigned int ctlr_enable = 0U; + + /* Make sure there's a valid property array */ + if (interrupt_props_num > 0U) { + assert(interrupt_props != NULL); + } + + for (i = 0U; i < interrupt_props_num; i++) { + current_prop = &interrupt_props[i]; + + unsigned int intr_num = current_prop->intr_num; + + /* Skip (E)SPI interrupt */ + if (!IS_SGI_PPI(intr_num)) { + continue; + } + + /* Configure this interrupt as a secure interrupt */ + gicr_clr_igroupr(gicr_base, intr_num); + + /* Configure this interrupt as G0 or a G1S interrupt */ + assert((current_prop->intr_grp == INTR_GROUP0) || + (current_prop->intr_grp == INTR_GROUP1S)); + + if (current_prop->intr_grp == INTR_GROUP1S) { + gicr_set_igrpmodr(gicr_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G1S_BIT; + } else { + gicr_clr_igrpmodr(gicr_base, intr_num); + ctlr_enable |= CTLR_ENABLE_G0_BIT; + } + + /* Set the priority of this interrupt */ + gicr_set_ipriorityr(gicr_base, intr_num, + current_prop->intr_pri); + + /* + * Set interrupt configuration for (E)PPIs. + * Configurations for SGIs 0-15 are ignored. + */ + if (intr_num >= MIN_PPI_ID) { + gicr_set_icfgr(gicr_base, intr_num, + current_prop->intr_cfg); + } + + /* Enable this interrupt */ + gicr_set_isenabler(gicr_base, intr_num); + } + + return ctlr_enable; +} + +/** + * gicv3_rdistif_get_number_frames() - determine size of GICv3 GICR region + * @gicr_frame: base address of the GICR region to check + * + * This iterates over the GICR_TYPER registers of multiple GICR frames in + * a GICR region, to find the instance which has the LAST bit set. For most + * systems this corresponds to the number of cores handled by a redistributor, + * but there could be disabled cores among them. + * It assumes that each GICR region is fully accessible (till the LAST bit + * marks the end of the region). + * If a platform has multiple GICR regions, this function would need to be + * called multiple times, providing the respective GICR base address each time. + * + * Return: number of valid GICR frames (at least 1, up to PLATFORM_CORE_COUNT) + ******************************************************************************/ +unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame) +{ + uintptr_t rdistif_base = gicr_frame; + unsigned int count; + + for (count = 1U; count < PLATFORM_CORE_COUNT; count++) { + uint64_t typer_val = gicr_read_typer(rdistif_base); + + if ((typer_val & TYPER_LAST_BIT) != 0U) { + break; + } + rdistif_base += gicv3_redist_size(typer_val); + } + + return count; +} + +unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame) +{ + unsigned int part_id; + + /* + * The lower 8 bits of PIDR0, complemented by the lower 4 bits of + * PIDR1 contain a part number identifying the GIC component at a + * particular base address. + */ + part_id = mmio_read_32(gic_frame + GICD_PIDR0_GICV3) & 0xff; + part_id |= (mmio_read_32(gic_frame + GICD_PIDR1_GICV3) << 8) & 0xf00; + + return part_id; +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c new file mode 100644 index 0000000..6c2dc4b --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c @@ -0,0 +1,1350 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "gicv3_private.h" + +const gicv3_driver_data_t *gicv3_driver_data; + +/* + * Spinlock to guard registers needing read-modify-write. APIs protected by this + * spinlock are used either at boot time (when only a single CPU is active), or + * when the system is fully coherent. + */ +static spinlock_t gic_lock; + +/* + * Redistributor power operations are weakly bound so that they can be + * overridden + */ +#pragma weak gicv3_rdistif_off +#pragma weak gicv3_rdistif_on + +/* Check interrupt ID for SGI/(E)PPI and (E)SPIs */ +static bool is_sgi_ppi(unsigned int id); + +/* + * Helper macros to save and restore GICR and GICD registers + * corresponding to their numbers to and from the context + */ +#define RESTORE_GICR_REG(base, ctx, name, i) \ + gicr_write_##name((base), (i), (ctx)->gicr_##name[(i)]) + +#define SAVE_GICR_REG(base, ctx, name, i) \ + (ctx)->gicr_##name[(i)] = gicr_read_##name((base), (i)) + +/* Helper macros to save and restore GICD registers to and from the context */ +#define RESTORE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + gicd_write_##reg((base), int_id, \ + (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ + REG##R_SHIFT]); \ + } \ + } while (false) + +#define SAVE_GICD_REGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_SPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + (ctx)->gicd_##reg[(int_id - MIN_SPI_ID) >> \ + REG##R_SHIFT] = gicd_read_##reg((base), int_id); \ + } \ + } while (false) + +#if GIC_EXT_INTID +#define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + gicd_write_##reg((base), int_id, \ + (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ + round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ + >> REG##R_SHIFT]); \ + } \ + } while (false) + +#define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) \ + do { \ + for (unsigned int int_id = MIN_ESPI_ID; int_id < (intr_num);\ + int_id += (1U << REG##R_SHIFT)) { \ + (ctx)->gicd_##reg[(int_id - (MIN_ESPI_ID - \ + round_up(TOTAL_SPI_INTR_NUM, 1U << REG##R_SHIFT)))\ + >> REG##R_SHIFT] = gicd_read_##reg((base), int_id);\ + } \ + } while (false) +#else +#define SAVE_GICD_EREGS(base, ctx, intr_num, reg, REG) +#define RESTORE_GICD_EREGS(base, ctx, intr_num, reg, REG) +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * This function initialises the ARM GICv3 driver in EL3 with provided platform + * inputs. + ******************************************************************************/ +void __init gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data) +{ + unsigned int gic_version; + unsigned int gicv2_compat; + + assert(plat_driver_data != NULL); + assert(plat_driver_data->gicd_base != 0U); + assert(plat_driver_data->rdistif_num != 0U); + assert(plat_driver_data->rdistif_base_addrs != NULL); + + assert(IS_IN_EL3()); + + assert((plat_driver_data->interrupt_props_num != 0U) ? + (plat_driver_data->interrupt_props != NULL) : 1); + + /* Check for system register support */ +#ifndef __aarch64__ + assert((read_id_pfr1() & + (ID_PFR1_GIC_MASK << ID_PFR1_GIC_SHIFT)) != 0U); +#else + assert((read_id_aa64pfr0_el1() & + (ID_AA64PFR0_GIC_MASK << ID_AA64PFR0_GIC_SHIFT)) != 0U); +#endif /* !__aarch64__ */ + + gic_version = gicd_read_pidr2(plat_driver_data->gicd_base); + gic_version >>= PIDR2_ARCH_REV_SHIFT; + gic_version &= PIDR2_ARCH_REV_MASK; + + /* Check GIC version */ +#if !GIC_ENABLE_V4_EXTN + assert(gic_version == ARCH_REV_GICV3); +#endif + /* + * Find out whether the GIC supports the GICv2 compatibility mode. + * The ARE_S bit resets to 0 if supported + */ + gicv2_compat = gicd_read_ctlr(plat_driver_data->gicd_base); + gicv2_compat >>= CTLR_ARE_S_SHIFT; + gicv2_compat = gicv2_compat & CTLR_ARE_S_MASK; + + if (plat_driver_data->gicr_base != 0U) { + /* + * Find the base address of each implemented Redistributor interface. + * The number of interfaces should be equal to the number of CPUs in the + * system. The memory for saving these addresses has to be allocated by + * the platform port + */ + gicv3_rdistif_base_addrs_probe(plat_driver_data->rdistif_base_addrs, + plat_driver_data->rdistif_num, + plat_driver_data->gicr_base, + plat_driver_data->mpidr_to_core_pos); +#if !HW_ASSISTED_COHERENCY + /* + * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. + */ + flush_dcache_range((uintptr_t)(plat_driver_data->rdistif_base_addrs), + plat_driver_data->rdistif_num * + sizeof(*(plat_driver_data->rdistif_base_addrs))); +#endif + } + gicv3_driver_data = plat_driver_data; + + /* + * The GIC driver data is initialized by the primary CPU with caches + * enabled. When the secondary CPU boots up, it initializes the + * GICC/GICR interface with the caches disabled. Hence flush the + * driver data to ensure coherency. This is not required if the + * platform has HW_ASSISTED_COHERENCY enabled. + */ +#if !HW_ASSISTED_COHERENCY + flush_dcache_range((uintptr_t)&gicv3_driver_data, + sizeof(gicv3_driver_data)); + flush_dcache_range((uintptr_t)gicv3_driver_data, + sizeof(*gicv3_driver_data)); +#endif + INFO("GICv%u with%s legacy support detected.\n", gic_version, + (gicv2_compat == 0U) ? "" : "out"); + INFO("ARM GICv%u driver initialized in EL3\n", gic_version); +} + +/******************************************************************************* + * This function initialises the GIC distributor interface based upon the data + * provided by the platform while initialising the driver. + ******************************************************************************/ +void __init gicv3_distif_init(void) +{ + unsigned int bitmap; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + assert(IS_IN_EL3()); + + /* + * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring + * the ARE_S bit. The Distributor might generate a system error + * otherwise. + */ + gicd_clr_ctlr(gicv3_driver_data->gicd_base, + CTLR_ENABLE_G0_BIT | + CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT, + RWP_TRUE); + + /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ + gicd_set_ctlr(gicv3_driver_data->gicd_base, + CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); + + /* Set the default attribute of all (E)SPIs */ + gicv3_spis_config_defaults(gicv3_driver_data->gicd_base); + +#if GICV3_RESTRICT_GICT_GICP_ACCESS + /* + * Restrict access to GIC Trace and PMU to secure only by + * Set TNS and PNS bit in GICD_SAC register + */ + bitmap = gicd_read_sac(gicv3_driver_data->gicd_base); + bitmap &= ~(SAC_GICTNS | SAC_GICPNS); + gicd_write_sac(gicv3_driver_data->gicd_base, bitmap); +#endif + + bitmap = gicv3_secure_spis_config_props( + gicv3_driver_data->gicd_base, + gicv3_driver_data->interrupt_props, + gicv3_driver_data->interrupt_props_num); + + /* Enable the secure (E)SPIs now that they have been configured */ + gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); +} + +/******************************************************************************* + * This function initialises the GIC Redistributor interface of the calling CPU + * (identified by the 'proc_num' parameter) based upon the data provided by the + * platform while initialising the driver. + ******************************************************************************/ +void gicv3_rdistif_init(unsigned int proc_num) +{ + uintptr_t gicr_base; + unsigned int bitmap; + uint32_t ctlr; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + ctlr = gicd_read_ctlr(gicv3_driver_data->gicd_base); + assert((ctlr & CTLR_ARE_S_BIT) != 0U); + + assert(IS_IN_EL3()); + + /* Power on redistributor */ + gicv3_rdistif_on(proc_num); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0U); + + /* Set the default attribute of all SGIs and (E)PPIs */ + gicv3_ppi_sgi_config_defaults(gicr_base); + + bitmap = gicv3_secure_ppi_sgi_config_props(gicr_base, + gicv3_driver_data->interrupt_props, + gicv3_driver_data->interrupt_props_num); + + /* Enable interrupt groups as required, if not already */ + if ((ctlr & bitmap) != bitmap) { + gicd_set_ctlr(gicv3_driver_data->gicd_base, bitmap, RWP_TRUE); + } +} + +/******************************************************************************* + * Functions to perform power operations on GIC Redistributor + ******************************************************************************/ +void gicv3_rdistif_off(unsigned int proc_num) +{ +} + +void gicv3_rdistif_on(unsigned int proc_num) +{ +} + +/******************************************************************************* + * This function enables the GIC CPU interface of the calling CPU using only + * system register accesses. + ******************************************************************************/ +void gicv3_cpuif_enable(unsigned int proc_num) +{ + uintptr_t gicr_base; + u_register_t scr_el3; + unsigned int icc_sre_el3; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + + /* Mark the connected core as awake */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + gicv3_rdistif_mark_core_awake(gicr_base); + + /* Disable the legacy interrupt bypass */ + icc_sre_el3 = ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT; + + /* + * Enable system register access for EL3 and allow lower exception + * levels to configure the same for themselves. If the legacy mode is + * not supported, the SRE bit is RAO/WI + */ + icc_sre_el3 |= (ICC_SRE_EN_BIT | ICC_SRE_SRE_BIT); + write_icc_sre_el3(read_icc_sre_el3() | icc_sre_el3); + + scr_el3 = read_scr_el3(); + + /* + * Switch to NS state to write Non secure ICC_SRE_EL1 and + * ICC_SRE_EL2 registers. + */ + write_scr_el3(scr_el3 | SCR_NS_BIT); + isb(); + + write_icc_sre_el2(read_icc_sre_el2() | icc_sre_el3); + write_icc_sre_el1(ICC_SRE_SRE_BIT); + isb(); + + /* Switch to secure state. */ + write_scr_el3(scr_el3 & (~SCR_NS_BIT)); + isb(); + + /* Write the secure ICC_SRE_EL1 register */ + write_icc_sre_el1(ICC_SRE_SRE_BIT); + isb(); + + /* Program the idle priority in the PMR */ + write_icc_pmr_el1(GIC_PRI_MASK); + + /* Enable Group0 interrupts */ + write_icc_igrpen0_el1(IGRPEN1_EL1_ENABLE_G0_BIT); + + /* Enable Group1 Secure interrupts */ + write_icc_igrpen1_el3(read_icc_igrpen1_el3() | + IGRPEN1_EL3_ENABLE_G1S_BIT); + isb(); + /* Add DSB to ensure visibility of System register writes */ + dsb(); +} + +/******************************************************************************* + * This function disables the GIC CPU interface of the calling CPU using + * only system register accesses. + ******************************************************************************/ +void gicv3_cpuif_disable(unsigned int proc_num) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + assert(IS_IN_EL3()); + + /* Disable legacy interrupt bypass */ + write_icc_sre_el3(read_icc_sre_el3() | + (ICC_SRE_DIB_BIT | ICC_SRE_DFB_BIT)); + + /* Disable Group0 interrupts */ + write_icc_igrpen0_el1(read_icc_igrpen0_el1() & + ~IGRPEN1_EL1_ENABLE_G0_BIT); + + /* Disable Group1 Secure and Non-Secure interrupts */ + write_icc_igrpen1_el3(read_icc_igrpen1_el3() & + ~(IGRPEN1_EL3_ENABLE_G1NS_BIT | + IGRPEN1_EL3_ENABLE_G1S_BIT)); + + /* Synchronise accesses to group enable registers */ + isb(); + /* Add DSB to ensure visibility of System register writes */ + dsb(); + + /* Mark the connected core as asleep */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + assert(gicr_base != 0U); + gicv3_rdistif_mark_core_asleep(gicr_base); +} + +/******************************************************************************* + * This function returns the id of the highest priority pending interrupt at + * the GIC cpu interface. + ******************************************************************************/ +unsigned int gicv3_get_pending_interrupt_id(void) +{ + unsigned int id; + + assert(IS_IN_EL3()); + id = (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; + + /* + * If the ID is special identifier corresponding to G1S or G1NS + * interrupt, then read the highest pending group 1 interrupt. + */ + if ((id == PENDING_G1S_INTID) || (id == PENDING_G1NS_INTID)) { + return (uint32_t)read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK; + } + + return id; +} + +/******************************************************************************* + * This function returns the type of the highest priority pending interrupt at + * the GIC cpu interface. The return values can be one of the following : + * PENDING_G1S_INTID : The interrupt type is secure Group 1. + * PENDING_G1NS_INTID : The interrupt type is non secure Group 1. + * 0 - 1019 : The interrupt type is secure Group 0. + * GIC_SPURIOUS_INTERRUPT : there is no pending interrupt with + * sufficient priority to be signaled + ******************************************************************************/ +unsigned int gicv3_get_pending_interrupt_type(void) +{ + assert(IS_IN_EL3()); + return (uint32_t)read_icc_hppir0_el1() & HPPIR0_EL1_INTID_MASK; +} + +/******************************************************************************* + * This function returns the type of the interrupt id depending upon the group + * this interrupt has been configured under by the interrupt controller i.e. + * group0 or group1 Secure / Non Secure. The return value can be one of the + * following : + * INTR_GROUP0 : The interrupt type is a Secure Group 0 interrupt + * INTR_GROUP1S : The interrupt type is a Secure Group 1 secure interrupt + * INTR_GROUP1NS: The interrupt type is a Secure Group 1 non secure + * interrupt. + ******************************************************************************/ +unsigned int gicv3_get_interrupt_type(unsigned int id, unsigned int proc_num) +{ + unsigned int igroup, grpmodr; + uintptr_t gicr_base; + + assert(IS_IN_EL3()); + assert(gicv3_driver_data != NULL); + + /* Ensure the parameters are valid */ + assert((id < PENDING_G1S_INTID) || (id >= MIN_LPI_ID)); + assert(proc_num < gicv3_driver_data->rdistif_num); + + /* All LPI interrupts are Group 1 non secure */ + if (id >= MIN_LPI_ID) { + return INTR_GROUP1NS; + } + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + igroup = gicr_get_igroupr(gicr_base, id); + grpmodr = gicr_get_igrpmodr(gicr_base, id); + } else { + /* SPIs: 32-1019, ESPIs: 4096-5119 */ + assert(gicv3_driver_data->gicd_base != 0U); + igroup = gicd_get_igroupr(gicv3_driver_data->gicd_base, id); + grpmodr = gicd_get_igrpmodr(gicv3_driver_data->gicd_base, id); + } + + /* + * If the IGROUP bit is set, then it is a Group 1 Non secure + * interrupt + */ + if (igroup != 0U) { + return INTR_GROUP1NS; + } + + /* If the GRPMOD bit is set, then it is a Group 1 Secure interrupt */ + if (grpmodr != 0U) { + return INTR_GROUP1S; + } + + /* Else it is a Group 0 Secure interrupt */ + return INTR_GROUP0; +} + +/***************************************************************************** + * Function to save and disable the GIC ITS register context. The power + * management of GIC ITS is implementation-defined and this function doesn't + * save any memory structures required to support ITS. As the sequence to save + * this state is implementation defined, it should be executed in platform + * specific code. Calling this function alone and then powering down the GIC and + * ITS without implementing the aforementioned platform specific code will + * corrupt the ITS state. + * + * This function must be invoked after the GIC CPU interface is disabled. + *****************************************************************************/ +void gicv3_its_save_disable(uintptr_t gits_base, + gicv3_its_ctx_t * const its_ctx) +{ + unsigned int i; + + assert(gicv3_driver_data != NULL); + assert(IS_IN_EL3()); + assert(its_ctx != NULL); + assert(gits_base != 0U); + + its_ctx->gits_ctlr = gits_read_ctlr(gits_base); + + /* Disable the ITS */ + gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); + + /* Wait for quiescent state */ + gits_wait_for_quiescent_bit(gits_base); + + its_ctx->gits_cbaser = gits_read_cbaser(gits_base); + its_ctx->gits_cwriter = gits_read_cwriter(gits_base); + + for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { + its_ctx->gits_baser[i] = gits_read_baser(gits_base, i); + } +} + +/***************************************************************************** + * Function to restore the GIC ITS register context. The power + * management of GIC ITS is implementation defined and this function doesn't + * restore any memory structures required to support ITS. The assumption is + * that these structures are in memory and are retained during system suspend. + * + * This must be invoked before the GIC CPU interface is enabled. + *****************************************************************************/ +void gicv3_its_restore(uintptr_t gits_base, + const gicv3_its_ctx_t * const its_ctx) +{ + unsigned int i; + + assert(gicv3_driver_data != NULL); + assert(IS_IN_EL3()); + assert(its_ctx != NULL); + assert(gits_base != 0U); + + /* Assert that the GITS is disabled and quiescent */ + assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U); + assert((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) != 0U); + + gits_write_cbaser(gits_base, its_ctx->gits_cbaser); + gits_write_cwriter(gits_base, its_ctx->gits_cwriter); + + for (i = 0U; i < ARRAY_SIZE(its_ctx->gits_baser); i++) { + gits_write_baser(gits_base, i, its_ctx->gits_baser[i]); + } + + /* Restore the ITS CTLR but leave the ITS disabled */ + gits_write_ctlr(gits_base, its_ctx->gits_ctlr & ~GITS_CTLR_ENABLED_BIT); +} + +/***************************************************************************** + * Function to save the GIC Redistributor register context. This function + * must be invoked after CPU interface disable and prior to Distributor save. + *****************************************************************************/ +void gicv3_rdistif_save(unsigned int proc_num, + gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int i, ppi_regs_num, regs_num; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + assert(rdist_ctx != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* + * Wait for any write to GICR_CTLR to complete before trying to save any + * state. + */ + gicr_wait_for_pending_write(gicr_base); + + rdist_ctx->gicr_ctlr = gicr_read_ctlr(gicr_base); + + rdist_ctx->gicr_propbaser = gicr_read_propbaser(gicr_base); + rdist_ctx->gicr_pendbaser = gicr_read_pendbaser(gicr_base); + + /* 32 interrupt IDs per register */ + for (i = 0U; i < ppi_regs_num; ++i) { + SAVE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); + SAVE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = 0U; i < regs_num; ++i) { + SAVE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); + } + + rdist_ctx->gicr_nsacr = gicr_read_nsacr(gicr_base); + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + rdist_ctx->gicr_ipriorityr[i] = + gicr_ipriorityr_read(gicr_base, i); + } + + flush_dcache_range((uint64_t)rdist_ctx, sizeof(gicv3_redist_ctx_t)); + + /* + * Call the pre-save hook that implements the IMP DEF sequence that may + * be required on some GIC implementations. As this may need to access + * the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_pre_save(proc_num); +} + +/***************************************************************************** + * Function to restore the GIC Redistributor register context. We disable + * LPI and per-cpu interrupts before we start restore of the Redistributor. + * This function must be invoked after Distributor restore but prior to + * CPU interface enable. The pending and active interrupts are restored + * after the interrupts are fully configured and enabled. + *****************************************************************************/ +void gicv3_rdistif_init_restore(unsigned int proc_num, + const gicv3_redist_ctx_t * const rdist_ctx) +{ + uintptr_t gicr_base; + unsigned int i, ppi_regs_num, regs_num; + + assert(gicv3_driver_data != NULL); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + assert(IS_IN_EL3()); + assert(rdist_ctx != NULL); + + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + +#if GIC_EXT_INTID + /* Calculate number of PPI registers */ + ppi_regs_num = (unsigned int)((gicr_read_typer(gicr_base) >> + TYPER_PPI_NUM_SHIFT) & TYPER_PPI_NUM_MASK) + 1; + /* All other values except PPInum [0-2] are reserved */ + if (ppi_regs_num > 3U) { + ppi_regs_num = 1U; + } +#else + ppi_regs_num = 1U; +#endif + /* Power on redistributor */ + gicv3_rdistif_on(proc_num); + + /* + * Call the post-restore hook that implements the IMP DEF sequence that + * may be required on some GIC implementations. As this may need to + * access the Redistributor registers, we pass it proc_num. + */ + gicv3_distif_post_restore(proc_num); + + /* + * Disable all SGIs (imp. def.)/(E)PPIs before configuring them. + * This is a more scalable approach as it avoids clearing the enable + * bits in the GICD_CTLR. + */ + for (i = 0U; i < ppi_regs_num; ++i) { + gicr_write_icenabler(gicr_base, i, ~0U); + } + + /* Wait for pending writes to GICR_ICENABLER */ + gicr_wait_for_pending_write(gicr_base); + + /* + * Disable the LPIs to avoid unpredictable behavior when writing to + * GICR_PROPBASER and GICR_PENDBASER. + */ + gicr_write_ctlr(gicr_base, + rdist_ctx->gicr_ctlr & ~(GICR_CTLR_EN_LPIS_BIT)); + + /* Restore registers' content */ + gicr_write_propbaser(gicr_base, rdist_ctx->gicr_propbaser); + gicr_write_pendbaser(gicr_base, rdist_ctx->gicr_pendbaser); + + /* 32 interrupt IDs per register */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, igroupr, i); + RESTORE_GICR_REG(gicr_base, rdist_ctx, igrpmodr, i); + } + + /* 4 interrupt IDs per GICR_IPRIORITYR register */ + regs_num = ppi_regs_num << 3; + for (i = 0U; i < regs_num; ++i) { + gicr_ipriorityr_write(gicr_base, i, + rdist_ctx->gicr_ipriorityr[i]); + } + + /* 16 interrupt IDs per GICR_ICFGR register */ + regs_num = ppi_regs_num << 1; + for (i = 0U; i < regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, icfgr, i); + } + + gicr_write_nsacr(gicr_base, rdist_ctx->gicr_nsacr); + + /* Restore after group and priorities are set. + * 32 interrupt IDs per register + */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, ispendr, i); + RESTORE_GICR_REG(gicr_base, rdist_ctx, isactiver, i); + } + + /* + * Wait for all writes to the Distributor to complete before enabling + * the SGI and (E)PPIs. + */ + gicr_wait_for_upstream_pending_write(gicr_base); + + /* 32 interrupt IDs per GICR_ISENABLER register */ + for (i = 0U; i < ppi_regs_num; ++i) { + RESTORE_GICR_REG(gicr_base, rdist_ctx, isenabler, i); + } + + /* + * Restore GICR_CTLR.Enable_LPIs bit and wait for pending writes in case + * the first write to GICR_CTLR was still in flight (this write only + * restores GICR_CTLR.Enable_LPIs and no waiting is required for this + * bit). + */ + gicr_write_ctlr(gicr_base, rdist_ctx->gicr_ctlr); + gicr_wait_for_pending_write(gicr_base); +} + +/***************************************************************************** + * Function to save the GIC Distributor register context. This function + * must be invoked after CPU interface disable and Redistributor save. + *****************************************************************************/ +void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(IS_IN_EL3()); + assert(dist_ctx != NULL); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + unsigned int num_ints = gicv3_get_spi_limit(gicd_base); +#if GIC_EXT_INTID + unsigned int num_eints = gicv3_get_espi_limit(gicd_base); +#endif + + /* Wait for pending write to complete */ + gicd_wait_for_pending_write(gicd_base); + + /* Save the GICD_CTLR */ + dist_ctx->gicd_ctlr = gicd_read_ctlr(gicd_base); + + /* Save GICD_IGROUPR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); + + /* Save GICD_IGROUPRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); + + /* Save GICD_ISENABLER for INT_IDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); + + /* Save GICD_ISENABLERE for INT_IDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); + + /* Save GICD_ISPENDR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); + + /* Save GICD_ISPENDRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); + + /* Save GICD_ISACTIVER for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); + + /* Save GICD_ISACTIVERE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); + + /* Save GICD_IPRIORITYR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); + + /* Save GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); + + /* Save GICD_ICFGR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); + + /* Save GICD_ICFGRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); + + /* Save GICD_IGRPMODR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); + + /* Save GICD_IGRPMODRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); + + /* Save GICD_NSACR for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); + + /* Save GICD_NSACRE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); + + /* Save GICD_IROUTER for INTIDs 32 - 1019 */ + SAVE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); + + /* Save GICD_IROUTERE for INTIDs 4096 - 5119 */ + SAVE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); + + flush_dcache_range((uint64_t)dist_ctx, sizeof(gicv3_dist_ctx_t)); + + /* + * GICD_ITARGETSR and GICD_SPENDSGIR are RAZ/WI when + * GICD_CTLR.ARE_(S|NS) bits are set which is the case for our GICv3 + * driver. + */ +} + +/***************************************************************************** + * Function to restore the GIC Distributor register context. We disable G0, G1S + * and G1NS interrupt groups before we start restore of the Distributor. This + * function must be invoked prior to Redistributor restore and CPU interface + * enable. The pending and active interrupts are restored after the interrupts + * are fully configured and enabled. + *****************************************************************************/ +void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(IS_IN_EL3()); + assert(dist_ctx != NULL); + + uintptr_t gicd_base = gicv3_driver_data->gicd_base; + + /* + * Clear the "enable" bits for G0/G1S/G1NS interrupts before configuring + * the ARE_S bit. The Distributor might generate a system error + * otherwise. + */ + gicd_clr_ctlr(gicd_base, + CTLR_ENABLE_G0_BIT | + CTLR_ENABLE_G1S_BIT | + CTLR_ENABLE_G1NS_BIT, + RWP_TRUE); + + /* Set the ARE_S and ARE_NS bit now that interrupts have been disabled */ + gicd_set_ctlr(gicd_base, CTLR_ARE_S_BIT | CTLR_ARE_NS_BIT, RWP_TRUE); + + unsigned int num_ints = gicv3_get_spi_limit(gicd_base); +#if GIC_EXT_INTID + unsigned int num_eints = gicv3_get_espi_limit(gicd_base); +#endif + /* Restore GICD_IGROUPR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igroupr, IGROUP); + + /* Restore GICD_IGROUPRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igroupr, IGROUP); + + /* Restore GICD_IPRIORITYR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ipriorityr, IPRIORITY); + + /* Restore GICD_IPRIORITYRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ipriorityr, IPRIORITY); + + /* Restore GICD_ICFGR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, icfgr, ICFG); + + /* Restore GICD_ICFGRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, icfgr, ICFG); + + /* Restore GICD_IGRPMODR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, igrpmodr, IGRPMOD); + + /* Restore GICD_IGRPMODRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, igrpmodr, IGRPMOD); + + /* Restore GICD_NSACR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, nsacr, NSAC); + + /* Restore GICD_NSACRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, nsacr, NSAC); + + /* Restore GICD_IROUTER for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, irouter, IROUTE); + + /* Restore GICD_IROUTERE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, irouter, IROUTE); + + /* + * Restore ISENABLER(E), ISPENDR(E) and ISACTIVER(E) after + * the interrupts are configured. + */ + + /* Restore GICD_ISENABLER for INT_IDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isenabler, ISENABLE); + + /* Restore GICD_ISENABLERE for INT_IDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isenabler, ISENABLE); + + /* Restore GICD_ISPENDR for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, ispendr, ISPEND); + + /* Restore GICD_ISPENDRE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, ispendr, ISPEND); + + /* Restore GICD_ISACTIVER for INTIDs 32 - 1019 */ + RESTORE_GICD_REGS(gicd_base, dist_ctx, num_ints, isactiver, ISACTIVE); + + /* Restore GICD_ISACTIVERE for INTIDs 4096 - 5119 */ + RESTORE_GICD_EREGS(gicd_base, dist_ctx, num_eints, isactiver, ISACTIVE); + + /* Restore the GICD_CTLR */ + gicd_write_ctlr(gicd_base, dist_ctx->gicd_ctlr); + gicd_wait_for_pending_write(gicd_base); +} + +/******************************************************************************* + * This function gets the priority of the interrupt the processor is currently + * servicing. + ******************************************************************************/ +unsigned int gicv3_get_running_priority(void) +{ + return (unsigned int)read_icc_rpr_el1(); +} + +/******************************************************************************* + * This function checks if the interrupt identified by id is active (whether the + * state is either active, or active and pending). The proc_num is used if the + * interrupt is SGI or (E)PPI and programs the corresponding Redistributor + * interface. + ******************************************************************************/ +unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + return gicr_get_isactiver( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } + + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + return gicd_get_isactiver(gicv3_driver_data->gicd_base, id); +} + +/******************************************************************************* + * This function enables the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or PPI, and programs the corresponding + * Redistributor interface. + ******************************************************************************/ +void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before enabling interrupt. + */ + dsbishst(); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_isenabler( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_isenabler(gicv3_driver_data->gicd_base, id); + } +} + +/******************************************************************************* + * This function disables the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or PPI, and programs the corresponding + * Redistributor interface. + ******************************************************************************/ +void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Disable interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_icenabler( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + + /* Write to clear enable requires waiting for pending writes */ + gicr_wait_for_pending_write( + gicv3_driver_data->rdistif_base_addrs[proc_num]); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_icenabler(gicv3_driver_data->gicd_base, id); + + /* Write to clear enable requires waiting for pending writes */ + gicd_wait_for_pending_write(gicv3_driver_data->gicd_base); + } + + dsbishst(); +} + +/******************************************************************************* + * This function sets the interrupt priority as supplied for the given interrupt + * id. + ******************************************************************************/ +void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, + unsigned int priority) +{ + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + gicr_set_ipriorityr(gicr_base, id, priority); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_ipriorityr(gicv3_driver_data->gicd_base, id, priority); + } +} + +/******************************************************************************* + * This function assigns group for the interrupt identified by id. The proc_num + * is used if the interrupt is SGI or (E)PPI, and programs the corresponding + * Redistributor interface. The group can be any of GICV3_INTR_GROUP* + ******************************************************************************/ +void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, + unsigned int type) +{ + bool igroup = false, grpmod = false; + uintptr_t gicr_base; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + switch (type) { + case INTR_GROUP1S: + igroup = false; + grpmod = true; + break; + case INTR_GROUP0: + igroup = false; + grpmod = false; + break; + case INTR_GROUP1NS: + igroup = true; + grpmod = false; + break; + default: + assert(false); + break; + } + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_base = gicv3_driver_data->rdistif_base_addrs[proc_num]; + + igroup ? gicr_set_igroupr(gicr_base, id) : + gicr_clr_igroupr(gicr_base, id); + grpmod ? gicr_set_igrpmodr(gicr_base, id) : + gicr_clr_igrpmodr(gicr_base, id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + + /* Serialize read-modify-write to Distributor registers */ + spin_lock(&gic_lock); + + igroup ? gicd_set_igroupr(gicv3_driver_data->gicd_base, id) : + gicd_clr_igroupr(gicv3_driver_data->gicd_base, id); + grpmod ? gicd_set_igrpmodr(gicv3_driver_data->gicd_base, id) : + gicd_clr_igrpmodr(gicv3_driver_data->gicd_base, id); + + spin_unlock(&gic_lock); + } +} + +/******************************************************************************* + * This function raises the specified Secure Group 0 SGI. + * + * The target parameter must be a valid MPIDR in the system. + ******************************************************************************/ +void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target) +{ + unsigned int tgt, aff3, aff2, aff1, aff0; + uint64_t sgi_val; + + /* Verify interrupt number is in the SGI range */ + assert((sgi_num >= MIN_SGI_ID) && (sgi_num < MIN_PPI_ID)); + + /* Extract affinity fields from target */ + aff0 = MPIDR_AFFLVL0_VAL(target); + aff1 = MPIDR_AFFLVL1_VAL(target); + aff2 = MPIDR_AFFLVL2_VAL(target); + aff3 = MPIDR_AFFLVL3_VAL(target); + + /* + * Make target list from affinity 0, and ensure GICv3 SGI can target + * this PE. + */ + assert(aff0 < GICV3_MAX_SGI_TARGETS); + tgt = BIT_32(aff0); + + /* Raise SGI to PE specified by its affinity */ + sgi_val = GICV3_SGIR_VALUE(aff3, aff2, aff1, sgi_num, SGIR_IRM_TO_AFF, + tgt); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before raising SGI. + */ + dsbishst(); + write_icc_sgi0r_el1(sgi_val); + isb(); +} + +/******************************************************************************* + * This function sets the interrupt routing for the given (E)SPI interrupt id. + * The interrupt routing is specified in routing mode and mpidr. + * + * The routing mode can be either of: + * - GICV3_IRM_ANY + * - GICV3_IRM_PE + * + * The mpidr is the affinity of the PE to which the interrupt will be routed, + * and is ignored for routing mode GICV3_IRM_ANY. + ******************************************************************************/ +void gicv3_set_spi_routing(unsigned int id, unsigned int irm, u_register_t mpidr) +{ + unsigned long long aff; + uint64_t router; + + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + + assert((irm == GICV3_IRM_ANY) || (irm == GICV3_IRM_PE)); + + assert(IS_SPI(id)); + + aff = gicd_irouter_val_from_mpidr(mpidr, irm); + gicd_write_irouter(gicv3_driver_data->gicd_base, id, aff); + + /* + * In implementations that do not require 1 of N distribution of SPIs, + * IRM might be RAZ/WI. Read back and verify IRM bit. + */ + if (irm == GICV3_IRM_ANY) { + router = gicd_read_irouter(gicv3_driver_data->gicd_base, id); + if (((router >> IROUTER_IRM_SHIFT) & IROUTER_IRM_MASK) == 0U) { + ERROR("GICv3 implementation doesn't support routing ANY\n"); + panic(); + } + } +} + +/******************************************************************************* + * This function clears the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or (E)PPI, and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Clear pending interrupt, and ensure that any shared variable updates + * depending on out of band interrupt trigger are observed afterwards. + */ + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_icpendr( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_icpendr(gicv3_driver_data->gicd_base, id); + } + + dsbishst(); +} + +/******************************************************************************* + * This function sets the pending status of an interrupt identified by id. + * The proc_num is used if the interrupt is SGI or PPI and programs the + * corresponding Redistributor interface. + ******************************************************************************/ +void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num) +{ + assert(gicv3_driver_data != NULL); + assert(gicv3_driver_data->gicd_base != 0U); + assert(proc_num < gicv3_driver_data->rdistif_num); + assert(gicv3_driver_data->rdistif_base_addrs != NULL); + + /* + * Ensure that any shared variable updates depending on out of band + * interrupt trigger are observed before setting interrupt pending. + */ + dsbishst(); + + /* Check interrupt ID */ + if (is_sgi_ppi(id)) { + /* For SGIs: 0-15, PPIs: 16-31 and EPPIs: 1056-1119 */ + gicr_set_ispendr( + gicv3_driver_data->rdistif_base_addrs[proc_num], id); + } else { + /* For SPIs: 32-1019 and ESPIs: 4096-5119 */ + gicd_set_ispendr(gicv3_driver_data->gicd_base, id); + } +} + +/******************************************************************************* + * This function sets the PMR register with the supplied value. Returns the + * original PMR. + ******************************************************************************/ +unsigned int gicv3_set_pmr(unsigned int mask) +{ + unsigned int old_mask; + + old_mask = (unsigned int)read_icc_pmr_el1(); + + /* + * Order memory updates w.r.t. PMR write, and ensure they're visible + * before potential out of band interrupt trigger because of PMR update. + * PMR system register writes are self-synchronizing, so no ISB required + * thereafter. + */ + dsbishst(); + write_icc_pmr_el1(mask); + + return old_mask; +} + +/******************************************************************************* + * This function delegates the responsibility of discovering the corresponding + * Redistributor frames to each CPU itself. It is a modified version of + * gicv3_rdistif_base_addrs_probe() and is executed by each CPU in the platform + * unlike the previous way in which only the Primary CPU did the discovery of + * all the Redistributor frames for every CPU. It also handles the scenario in + * which the frames of various CPUs are not contiguous in physical memory. + ******************************************************************************/ +int gicv3_rdistif_probe(const uintptr_t gicr_frame) +{ + u_register_t mpidr, mpidr_self; + unsigned int proc_num; + uint64_t typer_val; + uintptr_t rdistif_base; + bool gicr_frame_found = false; + + assert(gicv3_driver_data->gicr_base == 0U); + + /* Ensure this function is called with Data Cache enabled */ +#ifndef __aarch64__ + assert((read_sctlr() & SCTLR_C_BIT) != 0U); +#else + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); +#endif /* !__aarch64__ */ + + mpidr_self = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + rdistif_base = gicr_frame; + do { + typer_val = gicr_read_typer(rdistif_base); + mpidr = mpidr_from_gicr_typer(typer_val); + if (gicv3_driver_data->mpidr_to_core_pos != NULL) { + proc_num = gicv3_driver_data->mpidr_to_core_pos(mpidr); + } else { + proc_num = (unsigned int)(typer_val >> + TYPER_PROC_NUM_SHIFT) & TYPER_PROC_NUM_MASK; + } + if (mpidr == mpidr_self) { + /* The base address doesn't need to be initialized on + * every warm boot. + */ + if (gicv3_driver_data->rdistif_base_addrs[proc_num] + != 0U) { + return 0; + } + gicv3_driver_data->rdistif_base_addrs[proc_num] = + rdistif_base; + gicr_frame_found = true; + break; + } + rdistif_base += gicv3_redist_size(typer_val); + } while ((typer_val & TYPER_LAST_BIT) == 0U); + + if (!gicr_frame_found) { + return -1; + } + + /* + * Flush the driver data to ensure coherency. This is + * not required if platform has HW_ASSISTED_COHERENCY + * enabled. + */ +#if !HW_ASSISTED_COHERENCY + /* + * Flush the rdistif_base_addrs[] contents linked to the GICv3 driver. + */ + flush_dcache_range((uintptr_t)&(gicv3_driver_data->rdistif_base_addrs[proc_num]), + sizeof(*(gicv3_driver_data->rdistif_base_addrs))); +#endif + return 0; /* Found matching GICR frame */ +} + +/****************************************************************************** + * This function checks the interrupt ID and returns true for SGIs and (E)PPIs + * and false for (E)SPIs IDs. + *****************************************************************************/ +static bool is_sgi_ppi(unsigned int id) +{ + /* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ + if (IS_SGI_PPI(id)) { + return true; + } + + /* SPIs: 32-1019, ESPIs: 4096-5119 */ + if (IS_SPI(id)) { + return false; + } + + assert(false); + panic(); +} diff --git a/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h new file mode 100644 index 0000000..f56a5be --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h @@ -0,0 +1,718 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV3_PRIVATE_H +#define GICV3_PRIVATE_H + +#include +#include + +#include +#include +#include + +#include "../common/gic_common_private.h" + +/******************************************************************************* + * GICv3 private macro definitions + ******************************************************************************/ + +/* Constants to indicate the status of the RWP bit */ +#define RWP_TRUE U(1) +#define RWP_FALSE U(0) + +/* Calculate GIC register bit number corresponding to its interrupt ID */ +#define BIT_NUM(REG, id) \ + ((id) & ((1U << REG##R_SHIFT) - 1U)) + +/* + * Calculate 8, 32 and 64-bit GICD register offset + * corresponding to its interrupt ID + */ +#if GIC_EXT_INTID + /* GICv3.1 */ +#define GICD_OFFSET_8(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (uintptr_t)(id) : \ + GICD_##REG##RE + (uintptr_t)(id) - MIN_ESPI_ID) + +#define GICD_OFFSET(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \ + GICD_##REG##RE + ((((uintptr_t)(id) - MIN_ESPI_ID) >> \ + REG##R_SHIFT) << 2)) + +#define GICD_OFFSET_64(REG, id) \ + (((id) <= MAX_SPI_ID) ? \ + GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3) : \ + GICD_##REG##RE + ((((uintptr_t)(id) - MIN_ESPI_ID) >> \ + REG##R_SHIFT) << 3)) + +#else /* GICv3 */ +#define GICD_OFFSET_8(REG, id) \ + (GICD_##REG##R + (uintptr_t)(id)) + +#define GICD_OFFSET(REG, id) \ + (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2)) + +#define GICD_OFFSET_64(REG, id) \ + (GICD_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 3)) +#endif /* GIC_EXT_INTID */ + +/* + * Read/Write 8, 32 and 64-bit GIC Distributor register + * corresponding to its interrupt ID + */ +#define GICD_READ(REG, base, id) \ + mmio_read_32((base) + GICD_OFFSET(REG, (id))) + +#define GICD_READ_64(REG, base, id) \ + mmio_read_64((base) + GICD_OFFSET_64(REG, (id))) + +#define GICD_WRITE_8(REG, base, id, val) \ + mmio_write_8((base) + GICD_OFFSET_8(REG, (id)), (val)) + +#define GICD_WRITE(REG, base, id, val) \ + mmio_write_32((base) + GICD_OFFSET(REG, (id)), (val)) + +#define GICD_WRITE_64(REG, base, id, val) \ + mmio_write_64((base) + GICD_OFFSET_64(REG, (id)), (val)) + +/* + * Bit operations on GIC Distributor register corresponding + * to its interrupt ID + */ +/* Get bit in GIC Distributor register */ +#define GICD_GET_BIT(REG, base, id) \ + ((mmio_read_32((base) + GICD_OFFSET(REG, (id))) >> \ + BIT_NUM(REG, (id))) & 1U) + +/* Set bit in GIC Distributor register */ +#define GICD_SET_BIT(REG, base, id) \ + mmio_setbits_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Clear bit in GIC Distributor register */ +#define GICD_CLR_BIT(REG, base, id) \ + mmio_clrbits_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Write bit in GIC Distributor register */ +#define GICD_WRITE_BIT(REG, base, id) \ + mmio_write_32((base) + GICD_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* + * Calculate 8 and 32-bit GICR register offset + * corresponding to its interrupt ID + */ +#if GIC_EXT_INTID + /* GICv3.1 */ +#define GICR_OFFSET_8(REG, id) \ + (((id) <= MAX_PPI_ID) ? \ + GICR_##REG##R + (uintptr_t)(id) : \ + GICR_##REG##R + (uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID)) + +#define GICR_OFFSET(REG, id) \ + (((id) <= MAX_PPI_ID) ? \ + GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2) : \ + GICR_##REG##R + ((((uintptr_t)(id) - (MIN_EPPI_ID - MIN_SPI_ID))\ + >> REG##R_SHIFT) << 2)) +#else /* GICv3 */ +#define GICR_OFFSET_8(REG, id) \ + (GICR_##REG##R + (uintptr_t)(id)) + +#define GICR_OFFSET(REG, id) \ + (GICR_##REG##R + (((uintptr_t)(id) >> REG##R_SHIFT) << 2)) +#endif /* GIC_EXT_INTID */ + +/* Read/Write GIC Redistributor register corresponding to its interrupt ID */ +#define GICR_READ(REG, base, id) \ + mmio_read_32((base) + GICR_OFFSET(REG, (id))) + +#define GICR_WRITE_8(REG, base, id, val) \ + mmio_write_8((base) + GICR_OFFSET_8(REG, (id)), (val)) + +#define GICR_WRITE(REG, base, id, val) \ + mmio_write_32((base) + GICR_OFFSET(REG, (id)), (val)) + +/* + * Bit operations on GIC Redistributor register + * corresponding to its interrupt ID + */ +/* Get bit in GIC Redistributor register */ +#define GICR_GET_BIT(REG, base, id) \ + ((mmio_read_32((base) + GICR_OFFSET(REG, (id))) >> \ + BIT_NUM(REG, (id))) & 1U) + +/* Write bit in GIC Redistributor register */ +#define GICR_WRITE_BIT(REG, base, id) \ + mmio_write_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Set bit in GIC Redistributor register */ +#define GICR_SET_BIT(REG, base, id) \ + mmio_setbits_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* Clear bit in GIC Redistributor register */ +#define GICR_CLR_BIT(REG, base, id) \ + mmio_clrbits_32((base) + GICR_OFFSET(REG, (id)), \ + ((uint32_t)1 << BIT_NUM(REG, (id)))) + +/* + * Macro to convert an mpidr to a value suitable for programming into a + * GICD_IROUTER. Bits[31:24] in the MPIDR are cleared as they are not relevant + * to GICv3. + */ +static inline u_register_t gicd_irouter_val_from_mpidr(u_register_t mpidr, + unsigned int irm) +{ + return (mpidr & MPIDR_AFFINITY_MASK) | + ((irm & IROUTER_IRM_MASK) << IROUTER_IRM_SHIFT); +} + +/* + * Macro to convert a GICR_TYPER affinity value into a MPIDR value. Bits[31:24] + * are zeroes. + */ +#ifdef __aarch64__ +static inline u_register_t mpidr_from_gicr_typer(uint64_t typer_val) +{ + return (((typer_val >> 56) & MPIDR_AFFLVL_MASK) << MPIDR_AFF3_SHIFT) | + ((typer_val >> 32) & U(0xffffff)); +} +#else +static inline u_register_t mpidr_from_gicr_typer(uint64_t typer_val) +{ + return (((typer_val) >> 32) & U(0xffffff)); +} +#endif + +/******************************************************************************* + * GICv3 private global variables declarations + ******************************************************************************/ +extern const gicv3_driver_data_t *gicv3_driver_data; + +/******************************************************************************* + * Private GICv3 function prototypes for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ +unsigned int gicd_read_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_read_ipriorityr(uintptr_t base, unsigned int id); +void gicd_write_igrpmodr(uintptr_t base, unsigned int id, unsigned int val); +void gicr_write_ipriorityr(uintptr_t base, unsigned int id, unsigned int val); + +/******************************************************************************* + * Private GICv3 function prototypes for accessing the GIC registers + * corresponding to a single interrupt ID. These functions use bitwise + * operations or appropriate register accesses to modify or return + * the bit-field corresponding the single interrupt ID. + ******************************************************************************/ +unsigned int gicd_get_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_get_igrpmodr(uintptr_t base, unsigned int id); +unsigned int gicr_get_igroupr(uintptr_t base, unsigned int id); +unsigned int gicr_get_isactiver(uintptr_t base, unsigned int id); +void gicd_set_igrpmodr(uintptr_t base, unsigned int id); +void gicr_set_igrpmodr(uintptr_t base, unsigned int id); +void gicr_set_isenabler(uintptr_t base, unsigned int id); +void gicr_set_icenabler(uintptr_t base, unsigned int id); +void gicr_set_ispendr(uintptr_t base, unsigned int id); +void gicr_set_icpendr(uintptr_t base, unsigned int id); +void gicr_set_igroupr(uintptr_t base, unsigned int id); +void gicd_clr_igrpmodr(uintptr_t base, unsigned int id); +void gicr_clr_igrpmodr(uintptr_t base, unsigned int id); +void gicr_clr_igroupr(uintptr_t base, unsigned int id); +void gicr_set_ipriorityr(uintptr_t base, unsigned int id, unsigned int pri); +void gicr_set_icfgr(uintptr_t base, unsigned int id, unsigned int cfg); + +/******************************************************************************* + * Private GICv3 helper function prototypes + ******************************************************************************/ +unsigned int gicv3_get_spi_limit(uintptr_t gicd_base); +unsigned int gicv3_get_espi_limit(uintptr_t gicd_base); +void gicv3_spis_config_defaults(uintptr_t gicd_base); +void gicv3_ppi_sgi_config_defaults(uintptr_t gicr_base); +unsigned int gicv3_secure_ppi_sgi_config_props(uintptr_t gicr_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +unsigned int gicv3_secure_spis_config_props(uintptr_t gicd_base, + const interrupt_prop_t *interrupt_props, + unsigned int interrupt_props_num); +void gicv3_rdistif_base_addrs_probe(uintptr_t *rdistif_base_addrs, + unsigned int rdistif_num, + uintptr_t gicr_base, + mpidr_hash_fn mpidr_to_core_pos); +void gicv3_rdistif_mark_core_awake(uintptr_t gicr_base); +void gicv3_rdistif_mark_core_asleep(uintptr_t gicr_base); + +/******************************************************************************* + * GIC Distributor interface accessors + ******************************************************************************/ +/* + * Wait for updates to: + * GICD_CTLR[2:0] - the Group Enables + * GICD_CTLR[7:4] - the ARE bits, E1NWF bit and DS bit + * GICD_ICENABLER - the clearing of enable state for SPIs + */ +static inline void gicd_wait_for_pending_write(uintptr_t gicd_base) +{ + while ((gicd_read_ctlr(gicd_base) & GICD_CTLR_RWP_BIT) != 0U) { + } +} + +static inline uint32_t gicd_read_pidr2(uintptr_t base) +{ + return mmio_read_32(base + GICD_PIDR2_GICV3); +} + +static inline uint64_t gicd_read_irouter(uintptr_t base, unsigned int id) +{ + assert(id >= MIN_SPI_ID); + return GICD_READ_64(IROUTE, base, id); +} + +static inline void gicd_write_irouter(uintptr_t base, + unsigned int id, + uint64_t affinity) +{ + assert(id >= MIN_SPI_ID); + GICD_WRITE_64(IROUTE, base, id, affinity); +} + +static inline void gicd_clr_ctlr(uintptr_t base, + unsigned int bitmap, + unsigned int rwp) +{ + gicd_write_ctlr(base, gicd_read_ctlr(base) & ~bitmap); + if (rwp != 0U) { + gicd_wait_for_pending_write(base); + } +} + +static inline void gicd_set_ctlr(uintptr_t base, + unsigned int bitmap, + unsigned int rwp) +{ + gicd_write_ctlr(base, gicd_read_ctlr(base) | bitmap); + if (rwp != 0U) { + gicd_wait_for_pending_write(base); + } +} + +static inline uint32_t gicd_read_sac(uintptr_t base) +{ + return mmio_read_32(base + GICD_SAC); +} + +static inline void gicd_write_sac(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICD_SAC, val); +} + +/******************************************************************************* + * GIC Redistributor interface accessors + ******************************************************************************/ +static inline uint32_t gicr_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GICR_CTLR); +} + +static inline void gicr_write_ctlr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICR_CTLR, val); +} + +static inline uint64_t gicr_read_typer(uintptr_t base) +{ + return mmio_read_64(base + GICR_TYPER); +} + +static inline uint32_t gicr_read_waker(uintptr_t base) +{ + return mmio_read_32(base + GICR_WAKER); +} + +static inline void gicr_write_waker(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GICR_WAKER, val); +} + +/* + * Wait for updates to: + * GICR_ICENABLER0 + * GICR_CTLR.DPG1S + * GICR_CTLR.DPG1NS + * GICR_CTLR.DPG0 + * GICR_CTLR, which clears EnableLPIs from 1 to 0 + */ +static inline void gicr_wait_for_pending_write(uintptr_t gicr_base) +{ + while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_RWP_BIT) != 0U) { + } +} + +static inline void gicr_wait_for_upstream_pending_write(uintptr_t gicr_base) +{ + while ((gicr_read_ctlr(gicr_base) & GICR_CTLR_UWP_BIT) != 0U) { + } +} + +/* Private implementation of Distributor power control hooks */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num); +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num); + +/******************************************************************************* + * GIC Redistributor functions for accessing entire registers. + * Note: The raw register values correspond to multiple interrupt IDs and + * the number of interrupt IDs involved depends on the register accessed. + ******************************************************************************/ + +/* + * Accessors to read/write GIC Redistributor ICENABLER0 register + */ +static inline unsigned int gicr_read_icenabler0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICENABLER0); +} + +static inline void gicr_write_icenabler0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICENABLER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ICENABLER0 and ICENABLERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_icenabler(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ICENABLER + (reg_num << 2)); +} + +static inline void gicr_write_icenabler(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICENABLER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ICFGR0, ICFGR1 registers + */ +static inline unsigned int gicr_read_icfgr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICFGR0); +} + +static inline unsigned int gicr_read_icfgr1(uintptr_t base) +{ + return mmio_read_32(base + GICR_ICFGR1); +} + +static inline void gicr_write_icfgr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR0, val); +} + +static inline void gicr_write_icfgr1(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR1, val); +} + +/* + * Accessors to read/write GIC Redistributor ICFGR0, ICFGR1 and ICFGRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_icfgr(uintptr_t base, unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ICFGR + (reg_num << 2)); +} + +static inline void gicr_write_icfgr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICFGR + (reg_num << 2), val); +} + +/* + * Accessor to write GIC Redistributor ICPENDR0 register + */ +static inline void gicr_write_icpendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ICPENDR0, val); +} + +/* + * Accessor to write GIC Redistributor ICPENDR0 and ICPENDRE + * register corresponding to its number + */ +static inline void gicr_write_icpendr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ICPENDR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor IGROUPR0 register + */ +static inline unsigned int gicr_read_igroupr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_IGROUPR0); +} + +static inline void gicr_write_igroupr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_IGROUPR0, val); +} + +/* + * Accessors to read/write GIC Redistributor IGROUPR0 and IGROUPRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_igroupr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IGROUPR + (reg_num << 2)); +} + +static inline void gicr_write_igroupr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IGROUPR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor IGRPMODR0 register + */ +static inline unsigned int gicr_read_igrpmodr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_IGRPMODR0); +} + +static inline void gicr_write_igrpmodr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_IGRPMODR0, val); +} + +/* + * Accessors to read/write GIC Redistributor IGRPMODR0 and IGRPMODRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_igrpmodr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IGRPMODR + (reg_num << 2)); +} + +static inline void gicr_write_igrpmodr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IGRPMODR + (reg_num << 2), val); +} + +/* + * Accessors to read/write the GIC Redistributor IPRIORITYR(E) register + * corresponding to its number, 4 interrupts IDs at a time. + */ +static inline unsigned int gicr_ipriorityr_read(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_IPRIORITYR + (reg_num << 2)); +} + +static inline void gicr_ipriorityr_write(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_IPRIORITYR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISACTIVER0 register + */ +static inline unsigned int gicr_read_isactiver0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISACTIVER0); +} + +static inline void gicr_write_isactiver0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISACTIVER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISACTIVER0 and ISACTIVERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_isactiver(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISACTIVER + (reg_num << 2)); +} + +static inline void gicr_write_isactiver(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISACTIVER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISENABLER0 register + */ +static inline unsigned int gicr_read_isenabler0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISENABLER0); +} + +static inline void gicr_write_isenabler0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISENABLER0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISENABLER0 and ISENABLERE + * register corresponding to its number + */ +static inline unsigned int gicr_read_isenabler(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISENABLER + (reg_num << 2)); +} + +static inline void gicr_write_isenabler(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISENABLER + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor ISPENDR0 register + */ +static inline unsigned int gicr_read_ispendr0(uintptr_t base) +{ + return mmio_read_32(base + GICR_ISPENDR0); +} + +static inline void gicr_write_ispendr0(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_ISPENDR0, val); +} + +/* + * Accessors to read/write GIC Redistributor ISPENDR0 and ISPENDRE + * register corresponding to its number + */ +static inline unsigned int gicr_read_ispendr(uintptr_t base, + unsigned int reg_num) +{ + return mmio_read_32(base + GICR_ISPENDR + (reg_num << 2)); +} + +static inline void gicr_write_ispendr(uintptr_t base, unsigned int reg_num, + unsigned int val) +{ + mmio_write_32(base + GICR_ISPENDR + (reg_num << 2), val); +} + +/* + * Accessors to read/write GIC Redistributor NSACR register + */ +static inline unsigned int gicr_read_nsacr(uintptr_t base) +{ + return mmio_read_32(base + GICR_NSACR); +} + +static inline void gicr_write_nsacr(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GICR_NSACR, val); +} + +/* + * Accessors to read/write GIC Redistributor PROPBASER register + */ +static inline uint64_t gicr_read_propbaser(uintptr_t base) +{ + return mmio_read_64(base + GICR_PROPBASER); +} + +static inline void gicr_write_propbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GICR_PROPBASER, val); +} + +/* + * Accessors to read/write GIC Redistributor PENDBASER register + */ +static inline uint64_t gicr_read_pendbaser(uintptr_t base) +{ + return mmio_read_64(base + GICR_PENDBASER); +} + +static inline void gicr_write_pendbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GICR_PENDBASER, val); +} + +/******************************************************************************* + * GIC ITS functions to read and write entire ITS registers. + ******************************************************************************/ +static inline uint32_t gits_read_ctlr(uintptr_t base) +{ + return mmio_read_32(base + GITS_CTLR); +} + +static inline void gits_write_ctlr(uintptr_t base, uint32_t val) +{ + mmio_write_32(base + GITS_CTLR, val); +} + +static inline uint64_t gits_read_cbaser(uintptr_t base) +{ + return mmio_read_64(base + GITS_CBASER); +} + +static inline void gits_write_cbaser(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GITS_CBASER, val); +} + +static inline uint64_t gits_read_cwriter(uintptr_t base) +{ + return mmio_read_64(base + GITS_CWRITER); +} + +static inline void gits_write_cwriter(uintptr_t base, uint64_t val) +{ + mmio_write_64(base + GITS_CWRITER, val); +} + +static inline uint64_t gits_read_baser(uintptr_t base, + unsigned int its_table_id) +{ + assert(its_table_id < 8U); + return mmio_read_64(base + GITS_BASER + (8U * its_table_id)); +} + +static inline void gits_write_baser(uintptr_t base, unsigned int its_table_id, + uint64_t val) +{ + assert(its_table_id < 8U); + mmio_write_64(base + GITS_BASER + (8U * its_table_id), val); +} + +/* + * Wait for Quiescent bit when GIC ITS is disabled + */ +static inline void gits_wait_for_quiescent_bit(uintptr_t gits_base) +{ + assert((gits_read_ctlr(gits_base) & GITS_CTLR_ENABLED_BIT) == 0U); + while ((gits_read_ctlr(gits_base) & GITS_CTLR_QUIESCENT_BIT) == 0U) { + } +} + +#endif /* GICV3_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S b/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S new file mode 100644 index 0000000..9caeb0c --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writeable memory and are thus safe to call in BL1 crash context. + */ + .globl console_pl011_core_init + .globl console_pl011_core_putc + .globl console_pl011_core_getc + .globl console_pl011_core_flush + + .globl console_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush + + + /* ----------------------------------------------- + * int console_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------- + */ +func console_pl011_core_init + /* Check the input base address */ + cmp r0, #0 + beq core_init_fail +#if !PL011_GENERIC_UART + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq core_init_fail + cmp r2, #0 + beq core_init_fail + /* Disable the UART before initialization */ + ldr r3, [r0, #UARTCR] + bic r3, r3, #PL011_UARTCR_UARTEN + str r3, [r0, #UARTCR] + /* Program the baudrate */ + /* Divisor = (Uart clock * 4) / baudrate */ + lsl r1, r1, #2 +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + push {r0,r3} + softudiv r0,r1,r2,r3 + mov r2, r0 + pop {r0,r3} +#else + udiv r2, r1, r2 +#endif + /* IBRD = Divisor >> 6 */ + lsr r1, r2, #6 + /* Write the IBRD */ + str r1, [r0, #UARTIBRD] + /* FBRD = Divisor & 0x3F */ + and r1, r2, #0x3f + /* Write the FBRD */ + str r1, [r0, #UARTFBRD] + mov r1, #PL011_LINE_CONTROL + str r1, [r0, #UARTLCR_H] + /* Clear any pending errors */ + mov r1, #0 + str r1, [r0, #UARTECR] + /* Enable tx, rx, and uart overall */ + ldr r1, =(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) + str r1, [r0, #UARTCR] +#endif + mov r0, #1 + bx lr +core_init_fail: + mov r0, #0 + bx lr +endfunc console_pl011_core_init + + .globl console_pl011_register + + /* ------------------------------------------------------- + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new PL011 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_pl011_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + bl console_pl011_core_init + cmp r0, #0 + beq register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register pl011 putc=1, getc=1, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_pl011_register + + /* -------------------------------------------------------- + * int console_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 : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_pl011_core_putc + /* Check the input parameter */ + cmp r1, #0 + beq putc_error + /* Prepend '\r' to '\n' */ + cmp r0, #0xA + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldr r2, [r1, #UARTFR] + tst r2, #PL011_UARTFR_TXFF + bne 1b + mov r2, #0xD + str r2, [r1, #UARTDR] +2: + /* Check if the transmit FIFO is full */ + ldr r2, [r1, #UARTFR] + tst r2, #PL011_UARTFR_TXFF + bne 2b + str r0, [r1, #UARTDR] + bx lr +putc_error: + mov r0, #-1 + bx lr +endfunc console_pl011_core_putc + + /* -------------------------------------------------------- + * int console_pl011_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: r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list: r2 + * ------------------------------------------------------- + */ +func console_pl011_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc + + /* --------------------------------------------- + * int console_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_pl011_core_getc + cmp r0, #0 + beq getc_error +1: + /* Check if the receive FIFO is empty */ + ldr r1, [r0, #UARTFR] + tst r1, #PL011_UARTFR_RXFE + bne 1b + ldr r1, [r0, #UARTDR] + mov r0, r1 + bx lr +getc_error: + mov r0, #-1 + bx lr +endfunc console_pl011_core_getc + + /* ------------------------------------------------ + * int console_pl011_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 : r0 - pointer to console_t structure + * Out: r0 - character if available, else -1 + * Clobber list: r0, r1 + * ------------------------------------------------ + */ +func console_pl011_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc + + /* --------------------------------------------- + * void console_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_pl011_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + +1: + /* Loop while the transmit FIFO is busy */ + ldr r1, [r0, #UARTFR] + tst r1, #PL011_UARTFR_BUSY + bne 1b + + bx lr +endfunc console_pl011_core_flush + + /* --------------------------------------------- + * void console_pl011_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void + * Clobber list: r0, r1 + * --------------------------------------------- + */ +func console_pl011_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S b/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S new file mode 100644 index 0000000..861d2ed --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S @@ -0,0 +1,247 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_pl011_core_init + .globl console_pl011_core_putc + .globl console_pl011_core_getc + .globl console_pl011_core_flush + + .globl console_pl011_putc + .globl console_pl011_getc + .globl console_pl011_flush + + /* ----------------------------------------------- + * int console_pl011_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : x1, x2, x3, x4 + * ----------------------------------------------- + */ +func console_pl011_core_init + /* Check the input base address */ + cbz x0, core_init_fail +#if !PL011_GENERIC_UART + /* Check baud rate and uart clock for sanity */ + cbz w1, core_init_fail + cbz w2, core_init_fail + /* Disable uart before programming */ + ldr w3, [x0, #UARTCR] + mov w4, #PL011_UARTCR_UARTEN + bic w3, w3, w4 + str w3, [x0, #UARTCR] + /* Program the baudrate */ + /* Divisor = (Uart clock * 4) / baudrate */ + lsl w1, w1, #2 + udiv w2, w1, w2 + /* IBRD = Divisor >> 6 */ + lsr w1, w2, #6 + /* Write the IBRD */ + str w1, [x0, #UARTIBRD] + /* FBRD = Divisor & 0x3F */ + and w1, w2, #0x3f + /* Write the FBRD */ + str w1, [x0, #UARTFBRD] + mov w1, #PL011_LINE_CONTROL + str w1, [x0, #UARTLCR_H] + /* Clear any pending errors */ + str wzr, [x0, #UARTECR] + /* Enable tx, rx, and uart overall */ + mov w1, #(PL011_UARTCR_RXE | PL011_UARTCR_TXE | PL011_UARTCR_UARTEN) + str w1, [x0, #UARTCR] +#endif + mov w0, #1 + ret +core_init_fail: + mov w0, wzr + ret +endfunc console_pl011_core_init + + .globl console_pl011_register + + /* ----------------------------------------------- + * int console_pl011_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new PL011 + * 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_pl011_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_pl011_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register pl011 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_pl011_register + + /* -------------------------------------------------------- + * int console_pl011_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_pl011_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 1b + mov w2, #0xD + str w2, [x1, #UARTDR] +2: + /* Check if the transmit FIFO is full */ + ldr w2, [x1, #UARTFR] + tbnz w2, #PL011_UARTFR_TXFF_BIT, 2b + str w0, [x1, #UARTDR] + ret +endfunc console_pl011_core_putc + + /* -------------------------------------------------------- + * int console_pl011_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_pl011_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_pl011_core_putc +endfunc console_pl011_putc + + /* --------------------------------------------- + * int console_pl011_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_pl011_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ + ldr w1, [x0, #UARTFR] + tbnz w1, #PL011_UARTFR_RXFE_BIT, no_char + ldr w1, [x0, #UARTDR] + mov w0, w1 + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_pl011_core_getc + + /* --------------------------------------------- + * int console_pl011_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_pl011_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_pl011_core_getc +endfunc console_pl011_getc + + /* --------------------------------------------- + * void console_pl011_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_pl011_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ +1: + /* Loop until the transmit FIFO is empty */ + ldr w1, [x0, #UARTFR] + tbnz w1, #PL011_UARTFR_BUSY_BIT, 1b + ret +endfunc console_pl011_core_flush + + /* --------------------------------------------- + * void console_pl011_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_pl011_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_pl011_core_flush +endfunc console_pl011_flush diff --git a/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c b/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c new file mode 100644 index 0000000..97013e8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * ARM PL061 GPIO Driver. + * Reference to ARM DDI 0190B document. + * + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#if !PLAT_PL061_MAX_GPIOS +# define PLAT_PL061_MAX_GPIOS 32 +#endif /* PLAT_PL061_MAX_GPIOS */ + +CASSERT(PLAT_PL061_MAX_GPIOS > 0, assert_plat_pl061_max_gpios); + +#define MAX_GPIO_DEVICES ((PLAT_PL061_MAX_GPIOS + \ + (GPIOS_PER_PL061 - 1)) / GPIOS_PER_PL061) + +#define PL061_GPIO_DIR 0x400 + +#define GPIOS_PER_PL061 8 + +static int pl061_get_direction(int gpio); +static void pl061_set_direction(int gpio, int direction); +static int pl061_get_value(int gpio); +static void pl061_set_value(int gpio, int value); + +static uintptr_t pl061_reg_base[MAX_GPIO_DEVICES]; + +static const gpio_ops_t pl061_gpio_ops = { + .get_direction = pl061_get_direction, + .set_direction = pl061_set_direction, + .get_value = pl061_get_value, + .set_value = pl061_set_value, +}; + +static int pl061_get_direction(int gpio) +{ + uintptr_t base_addr; + unsigned int data, offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + data = mmio_read_8(base_addr + PL061_GPIO_DIR); + if (data & BIT(offset)) + return GPIO_DIR_OUT; + return GPIO_DIR_IN; +} + +static void pl061_set_direction(int gpio, int direction) +{ + uintptr_t base_addr; + unsigned int data, offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (direction == GPIO_DIR_OUT) { + data = mmio_read_8(base_addr + PL061_GPIO_DIR) | BIT(offset); + mmio_write_8(base_addr + PL061_GPIO_DIR, data); + } else { + data = mmio_read_8(base_addr + PL061_GPIO_DIR) & ~BIT(offset); + mmio_write_8(base_addr + PL061_GPIO_DIR, data); + } +} + +/* + * The offset of GPIODATA register is 0. + * The values read from GPIODATA are determined for each bit, by the mask bit + * derived from the address used to access the data register, PADDR[9:2]. + * Bits that are 1 in the address mask cause the corresponding bits in GPIODATA + * to be read, and bits that are 0 in the address mask cause the corresponding + * bits in GPIODATA to be read as 0, regardless of their value. + */ +static int pl061_get_value(int gpio) +{ + uintptr_t base_addr; + unsigned int offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (mmio_read_8(base_addr + BIT(offset + 2))) + return GPIO_LEVEL_HIGH; + return GPIO_LEVEL_LOW; +} + +/* + * In order to write GPIODATA, the corresponding bits in the mask, resulting + * from the address bus, PADDR[9:2], must be HIGH. Otherwise the bit values + * remain unchanged by the write. + */ +static void pl061_set_value(int gpio, int value) +{ + uintptr_t base_addr; + int offset; + + assert((gpio >= 0) && (gpio < PLAT_PL061_MAX_GPIOS)); + + base_addr = pl061_reg_base[gpio / GPIOS_PER_PL061]; + offset = gpio % GPIOS_PER_PL061; + if (value == GPIO_LEVEL_HIGH) + mmio_write_8(base_addr + BIT(offset + 2), BIT(offset)); + else + mmio_write_8(base_addr + BIT(offset + 2), 0); +} + + +/* + * Register the PL061 GPIO controller with a base address and the offset + * of start pin in this GPIO controller. + * This function is called after pl061_gpio_ops_init(). + */ +void pl061_gpio_register(uintptr_t base_addr, int gpio_dev) +{ + assert((gpio_dev >= 0) && (gpio_dev < MAX_GPIO_DEVICES)); + + pl061_reg_base[gpio_dev] = base_addr; +} + +/* + * Initialize PL061 GPIO controller with the total GPIO numbers in SoC. + */ +void pl061_gpio_init(void) +{ + gpio_init(&pl061_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c b/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c new file mode 100644 index 0000000..79c6f26 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sbsa/sbsa.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +void sbsa_watchdog_offset_reg_write(uintptr_t base, uint64_t value) +{ + assert((value >> SBSA_WDOG_WOR_WIDTH) == 0); + mmio_write_32(base + SBSA_WDOG_WOR_LOW_OFFSET, + ((uint32_t)value & UINT32_MAX)); + mmio_write_32(base + SBSA_WDOG_WOR_HIGH_OFFSET, (uint32_t)(value >> 32)); +} + +/* + * Start the watchdog timer at base address "base" for a + * period of "ms" milliseconds.The watchdog has to be + * refreshed within this time period. + */ +void sbsa_wdog_start(uintptr_t base, uint64_t ms) +{ + uint64_t counter_freq; + uint64_t offset_reg_value; + + counter_freq = (uint64_t)plat_get_syscnt_freq2(); + offset_reg_value = ms * counter_freq / 1000; + + sbsa_watchdog_offset_reg_write(base, offset_reg_value); + mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, SBSA_WDOG_WCS_EN); +} + +/* Stop the watchdog */ +void sbsa_wdog_stop(uintptr_t base) +{ + mmio_write_32(base + SBSA_WDOG_WCS_OFFSET, (0x0)); +} diff --git a/arm-trusted-firmware/drivers/arm/scu/scu.c b/arm-trusted-firmware/drivers/arm/scu/scu.c new file mode 100644 index 0000000..aceac92 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/scu/scu.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Turn ON snoop control unit. This is needed to synchronize the data between + * CPU's. + ******************************************************************************/ +void enable_snoop_ctrl_unit(uintptr_t base) +{ + uint32_t scu_ctrl; + + INFO("[SCU]: enabling snoop control unit ... \n"); + + assert(base != 0U); + scu_ctrl = mmio_read_32(base + SCU_CTRL_REG); + + /* already enabled? */ + if ((scu_ctrl & SCU_ENABLE_BIT) != 0) { + return; + } + + scu_ctrl |= SCU_ENABLE_BIT; + mmio_write_32(base + SCU_CTRL_REG, scu_ctrl); +} + +/******************************************************************************* + * Snoop Control Unit configuration register. This is read-only register and + * contains information such as + * - number of CPUs present + * - is a particular CPU operating in SMP mode or AMP mode + * - data cache size of a particular CPU + * - does SCU has ACP port + * - is L2CPRESENT + * NOTE: user of this API should interpert the bits in this register according + * to the TRM + ******************************************************************************/ +uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base) +{ + assert(base != 0U); + + return mmio_read_32(base + SCU_CFG_REG); +} diff --git a/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c b/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c new file mode 100644 index 0000000..a082a81 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* SMMU poll number of retries */ +#define SMMU_POLL_TIMEOUT_US U(1000) + +static int __init smmuv3_poll(uintptr_t smmu_reg, uint32_t mask, + uint32_t value) +{ + uint32_t reg_val; + uint64_t timeout; + + /* Set 1ms timeout value */ + timeout = timeout_init_us(SMMU_POLL_TIMEOUT_US); + do { + reg_val = mmio_read_32(smmu_reg); + if ((reg_val & mask) == value) + return 0; + } while (!timeout_elapsed(timeout)); + + ERROR("Timeout polling SMMUv3 register @%p\n", (void *)smmu_reg); + ERROR("Read value 0x%x, expected 0x%x\n", reg_val, + value == 0U ? reg_val & ~mask : reg_val | mask); + return -1; +} + +/* + * Abort all incoming transactions in order to implement a default + * deny policy on reset. + */ +int __init smmuv3_security_init(uintptr_t smmu_base) +{ + /* Attribute update has completed when SMMU_(S)_GBPA.Update bit is 0 */ + if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U) + return -1; + + /* + * SMMU_(S)_CR0 resets to zero with all streams bypassing the SMMU, + * so just abort all incoming transactions. + */ + mmio_setbits_32(smmu_base + SMMU_GBPA, + SMMU_GBPA_UPDATE | SMMU_GBPA_ABORT); + + if (smmuv3_poll(smmu_base + SMMU_GBPA, SMMU_GBPA_UPDATE, 0U) != 0U) + return -1; + + /* Check if the SMMU supports secure state */ + if ((mmio_read_32(smmu_base + SMMU_S_IDR1) & + SMMU_S_IDR1_SECURE_IMPL) == 0U) + return 0; + + /* Abort all incoming secure transactions */ + if (smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U) != 0U) + return -1; + + mmio_setbits_32(smmu_base + SMMU_S_GBPA, + SMMU_S_GBPA_UPDATE | SMMU_S_GBPA_ABORT); + + return smmuv3_poll(smmu_base + SMMU_S_GBPA, SMMU_S_GBPA_UPDATE, 0U); +} + +/* + * Initialize the SMMU by invalidating all secure caches and TLBs. + * Abort all incoming transactions in order to implement a default + * deny policy on reset + */ +int __init smmuv3_init(uintptr_t smmu_base) +{ + /* Abort all incoming transactions */ + if (smmuv3_security_init(smmu_base) != 0) + return -1; + + /* Check if the SMMU supports secure state */ + if ((mmio_read_32(smmu_base + SMMU_S_IDR1) & + SMMU_S_IDR1_SECURE_IMPL) == 0U) + return 0; + /* + * Initiate invalidation of secure caches and TLBs if the SMMU + * supports secure state. If not, it's implementation defined + * as to how SMMU_S_INIT register is accessed. + */ + mmio_write_32(smmu_base + SMMU_S_INIT, SMMU_S_INIT_INV_ALL); + + /* Wait for global invalidation operation to finish */ + return smmuv3_poll(smmu_base + SMMU_S_INIT, + SMMU_S_INIT_INV_ALL, 0U); +} diff --git a/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c b/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c new file mode 100644 index 0000000..9c5e762 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +uintptr_t sp804_base_addr; + +#define SP804_TIMER1_LOAD (sp804_base_addr + 0x000) +#define SP804_TIMER1_VALUE (sp804_base_addr + 0x004) +#define SP804_TIMER1_CONTROL (sp804_base_addr + 0x008) +#define SP804_TIMER1_BGLOAD (sp804_base_addr + 0x018) + +#define TIMER_CTRL_ONESHOT (1 << 0) +#define TIMER_CTRL_32BIT (1 << 1) +#define TIMER_CTRL_DIV1 (0 << 2) +#define TIMER_CTRL_DIV16 (1 << 2) +#define TIMER_CTRL_DIV256 (2 << 2) +#define TIMER_CTRL_IE (1 << 5) +#define TIMER_CTRL_PERIODIC (1 << 6) +#define TIMER_CTRL_ENABLE (1 << 7) + +/******************************************************************** + * The SP804 timer delay function + ********************************************************************/ +uint32_t sp804_get_timer_value(void) +{ + return mmio_read_32(SP804_TIMER1_VALUE); +} + +/******************************************************************** + * Initialize the 1st timer in the SP804 dual timer with a base + * address and a timer ops + ********************************************************************/ +void sp804_timer_ops_init(uintptr_t base_addr, const timer_ops_t *ops) +{ + assert(base_addr != 0); + assert(ops != 0 && ops->get_timer_value == sp804_get_timer_value); + + sp804_base_addr = base_addr; + timer_init(ops); + + /* disable timer1 */ + mmio_write_32(SP804_TIMER1_CONTROL, 0); + mmio_write_32(SP804_TIMER1_LOAD, UINT32_MAX); + mmio_write_32(SP804_TIMER1_VALUE, UINT32_MAX); + + /* enable as a free running 32-bit counter */ + mmio_write_32(SP804_TIMER1_CONTROL, + TIMER_CTRL_32BIT | TIMER_CTRL_ENABLE); +} diff --git a/arm-trusted-firmware/drivers/arm/sp805/sp805.c b/arm-trusted-firmware/drivers/arm/sp805/sp805.c new file mode 100644 index 0000000..ffca1ce --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/sp805/sp805.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* Inline register access functions */ + +static inline void sp805_write_wdog_load(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_LOAD_OFF, value); +} + +static inline void sp805_write_wdog_ctrl(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_CTR_OFF, value); +} + +static inline void sp805_write_wdog_lock(uintptr_t base, uint32_t value) +{ + mmio_write_32(base + SP805_WDOG_LOCK_OFF, value); +} + + +/* Public API implementation */ + +void sp805_start(uintptr_t base, unsigned int ticks) +{ + sp805_write_wdog_load(base, ticks); + sp805_write_wdog_ctrl(base, SP805_CTR_RESEN | SP805_CTR_INTEN); + /* Lock registers access */ + sp805_write_wdog_lock(base, 0U); +} + +void sp805_stop(uintptr_t base) +{ + sp805_write_wdog_lock(base, WDOG_UNLOCK_KEY); + sp805_write_wdog_ctrl(base, 0U); +} + +void sp805_refresh(uintptr_t base, unsigned int ticks) +{ + sp805_write_wdog_lock(base, WDOG_UNLOCK_KEY); + sp805_write_wdog_load(base, ticks); + sp805_write_wdog_lock(base, 0U); +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc380.c b/arm-trusted-firmware/drivers/arm/tzc/tzc380.c new file mode 100644 index 0000000..9518748 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc380.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +struct tzc380_instance { + uintptr_t base; + uint8_t addr_width; + uint8_t num_regions; +}; + +struct tzc380_instance tzc380; + +static unsigned int tzc380_read_build_config(uintptr_t base) +{ + return mmio_read_32(base + TZC380_CONFIGURATION_OFF); +} + +static void tzc380_write_action(uintptr_t base, unsigned int action) +{ + mmio_write_32(base + ACTION_OFF, action); +} + +static void tzc380_write_region_base_low(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_SETUP_LOW_OFF(region), val); +} + +static void tzc380_write_region_base_high(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_SETUP_HIGH_OFF(region), val); +} + +static void tzc380_write_region_attributes(uintptr_t base, unsigned int region, + unsigned int val) +{ + mmio_write_32(base + REGION_ATTRIBUTES_OFF(region), val); +} + +void tzc380_init(uintptr_t base) +{ + unsigned int tzc_build; + + assert(base != 0U); + tzc380.base = base; + + /* Save values we will use later. */ + tzc_build = tzc380_read_build_config(tzc380.base); + tzc380.addr_width = ((tzc_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1; + tzc380.num_regions = ((tzc_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1; +} + +static uint32_t addr_low(uintptr_t addr) +{ + return (uint32_t)addr; +} + +static uint32_t addr_high(uintptr_t addr __unused) +{ +#if (UINTPTR_MAX == UINT64_MAX) + return addr >> 32; +#else + return 0; +#endif +} + +/* + * `tzc380_configure_region` is used to program regions into the TrustZone + * controller. + */ +void tzc380_configure_region(uint8_t region, uintptr_t region_base, unsigned int attr) +{ + assert(tzc380.base != 0U); + + assert(region < tzc380.num_regions); + + tzc380_write_region_base_low(tzc380.base, region, addr_low(region_base)); + tzc380_write_region_base_high(tzc380.base, region, addr_high(region_base)); + tzc380_write_region_attributes(tzc380.base, region, attr); +} + +void tzc380_set_action(unsigned int action) +{ + assert(tzc380.base != 0U); + + /* + * - Currently no handler is provided to trap an error via interrupt + * or exception. + * - The interrupt action has not been tested. + */ + tzc380_write_action(tzc380.base, action); +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc400.c b/arm-trusted-firmware/drivers/arm/tzc/tzc400.c new file mode 100644 index 0000000..759824d --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc400.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "tzc_common_private.h" + +/* + * Macros which will be used by common core functions. + */ +#define TZC_400_REGION_BASE_LOW_0_OFFSET U(0x100) +#define TZC_400_REGION_BASE_HIGH_0_OFFSET U(0x104) +#define TZC_400_REGION_TOP_LOW_0_OFFSET U(0x108) +#define TZC_400_REGION_TOP_HIGH_0_OFFSET U(0x10c) +#define TZC_400_REGION_ATTR_0_OFFSET U(0x110) +#define TZC_400_REGION_ID_ACCESS_0_OFFSET U(0x114) + +/* + * Implementation defined values used to validate inputs later. + * Filters : max of 4 ; 0 to 3 + * Regions : max of 9 ; 0 to 8 + * Address width : Values between 32 to 64 + */ +typedef struct tzc400_instance { + uintptr_t base; + uint8_t addr_width; + uint8_t num_filters; + uint8_t num_regions; +} tzc400_instance_t; + +static tzc400_instance_t tzc400; + +static inline unsigned int _tzc400_read_build_config(uintptr_t base) +{ + return mmio_read_32(base + BUILD_CONFIG_OFF); +} + +static inline unsigned int _tzc400_read_gate_keeper(uintptr_t base) +{ + return mmio_read_32(base + GATE_KEEPER_OFF); +} + +static inline void _tzc400_write_gate_keeper(uintptr_t base, unsigned int val) +{ + mmio_write_32(base + GATE_KEEPER_OFF, val); +} + +/* + * Get the open status information for all filter units. + */ +#define get_gate_keeper_os(_base) ((_tzc400_read_gate_keeper(_base) >> \ + GATE_KEEPER_OS_SHIFT) & \ + GATE_KEEPER_OS_MASK) + + +/* Define common core functions used across different TZC peripherals. */ +DEFINE_TZC_COMMON_WRITE_ACTION(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_BASE(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_TOP(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(400, 400) +DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(400, 400) +DEFINE_TZC_COMMON_UPDATE_FILTERS(400, 400) +DEFINE_TZC_COMMON_CONFIGURE_REGION0(400) +DEFINE_TZC_COMMON_CONFIGURE_REGION(400) + +static void _tzc400_clear_it(uintptr_t base, uint32_t filter) +{ + mmio_write_32(base + INT_CLEAR, BIT_32(filter)); +} + +static uint32_t _tzc400_get_int_by_filter(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + INT_STATUS) & BIT_32(filter); +} + +#if DEBUG +static unsigned long _tzc400_get_fail_address(uintptr_t base, uint32_t filter) +{ + unsigned long fail_address; + + fail_address = mmio_read_32(base + FAIL_ADDRESS_LOW_OFF + + (filter * FILTER_OFFSET)); +#ifdef __aarch64__ + fail_address += (unsigned long)mmio_read_32(base + FAIL_ADDRESS_HIGH_OFF + + (filter * FILTER_OFFSET)) << 32; +#endif + + return fail_address; +} + +static uint32_t _tzc400_get_fail_id(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + FAIL_ID + (filter * FILTER_OFFSET)); +} + +static uint32_t _tzc400_get_fail_control(uintptr_t base, uint32_t filter) +{ + return mmio_read_32(base + FAIL_CONTROL_OFF + (filter * FILTER_OFFSET)); +} + +static void _tzc400_dump_fail_filter(uintptr_t base, uint32_t filter) +{ + uint32_t control_fail; + uint32_t fail_id; + unsigned long address_fail; + + address_fail = _tzc400_get_fail_address(base, filter); + ERROR("Illegal access to 0x%lx:\n", address_fail); + + fail_id = _tzc400_get_fail_id(base, filter); + ERROR("\tFAIL_ID = 0x%x\n", fail_id); + + control_fail = _tzc400_get_fail_control(base, filter); + if (((control_fail & BIT_32(FAIL_CONTROL_NS_SHIFT)) >> FAIL_CONTROL_NS_SHIFT) == + FAIL_CONTROL_NS_NONSECURE) { + ERROR("\tNon-Secure\n"); + } else { + ERROR("\tSecure\n"); + } + + if (((control_fail & BIT_32(FAIL_CONTROL_PRIV_SHIFT)) >> FAIL_CONTROL_PRIV_SHIFT) == + FAIL_CONTROL_PRIV_PRIV) { + ERROR("\tPrivilege\n"); + } else { + ERROR("\tUnprivilege\n"); + } + + if (((control_fail & BIT_32(FAIL_CONTROL_DIR_SHIFT)) >> FAIL_CONTROL_DIR_SHIFT) == + FAIL_CONTROL_DIR_WRITE) { + ERROR("\tWrite\n"); + } else { + ERROR("\tRead\n"); + } +} +#endif /* DEBUG */ + +static unsigned int _tzc400_get_gate_keeper(uintptr_t base, + unsigned int filter) +{ + unsigned int open_status; + + open_status = get_gate_keeper_os(base); + + return (open_status >> filter) & GATE_KEEPER_FILTER_MASK; +} + +/* This function is not MP safe. */ +static void _tzc400_set_gate_keeper(uintptr_t base, + unsigned int filter, + int val) +{ + unsigned int open_status; + + /* Upper half is current state. Lower half is requested state. */ + open_status = get_gate_keeper_os(base); + + if (val != 0) + open_status |= (1UL << filter); + else + open_status &= ~(1UL << filter); + + _tzc400_write_gate_keeper(base, (open_status & GATE_KEEPER_OR_MASK) << + GATE_KEEPER_OR_SHIFT); + + /* Wait here until we see the change reflected in the TZC status. */ + while ((get_gate_keeper_os(base)) != open_status) + ; +} + +void tzc400_set_action(unsigned int action) +{ + assert(tzc400.base != 0U); + assert(action <= TZC_ACTION_ERR_INT); + + _tzc400_write_action(tzc400.base, action); +} + +void tzc400_init(uintptr_t base) +{ +#if DEBUG + unsigned int tzc400_id; +#endif + unsigned int tzc400_build; + + assert(base != 0U); + tzc400.base = base; + +#if DEBUG + tzc400_id = _tzc_read_peripheral_id(base); + if (tzc400_id != TZC_400_PERIPHERAL_ID) { + ERROR("TZC-400 : Wrong device ID (0x%x).\n", tzc400_id); + panic(); + } +#endif + + /* Save values we will use later. */ + tzc400_build = _tzc400_read_build_config(tzc400.base); + tzc400.num_filters = (uint8_t)((tzc400_build >> BUILD_CONFIG_NF_SHIFT) & + BUILD_CONFIG_NF_MASK) + 1U; + tzc400.addr_width = (uint8_t)((tzc400_build >> BUILD_CONFIG_AW_SHIFT) & + BUILD_CONFIG_AW_MASK) + 1U; + tzc400.num_regions = (uint8_t)((tzc400_build >> BUILD_CONFIG_NR_SHIFT) & + BUILD_CONFIG_NR_MASK) + 1U; +} + +/* + * `tzc400_configure_region0` is used to program region 0 into the TrustZone + * controller. Region 0 covers the whole address space that is not mapped + * to any other region, and is enabled on all filters; this cannot be + * changed. This function only changes the access permissions. + */ +void tzc400_configure_region0(unsigned int sec_attr, + unsigned int ns_device_access) +{ + assert(tzc400.base != 0U); + assert(sec_attr <= TZC_REGION_S_RDWR); + + _tzc400_configure_region0(tzc400.base, sec_attr, ns_device_access); +} + +/* + * `tzc400_configure_region` is used to program regions into the TrustZone + * controller. A region can be associated with more than one filter. The + * associated filters are passed in as a bitmap (bit0 = filter0), except that + * the value TZC_400_REGION_ATTR_FILTER_BIT_ALL selects all filters, based on + * the value of tzc400.num_filters. + * NOTE: + * Region 0 is special; it is preferable to use tzc400_configure_region0 + * for this region (see comment for that function). + */ +void tzc400_configure_region(unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + assert(tzc400.base != 0U); + + /* Adjust filter mask by real filter number */ + if (filters == TZC_400_REGION_ATTR_FILTER_BIT_ALL) { + filters = (1U << tzc400.num_filters) - 1U; + } + + /* Do range checks on filters and regions. */ + assert(((filters >> tzc400.num_filters) == 0U) && + (region < tzc400.num_regions)); + + /* + * Do address range check based on TZC configuration. A 64bit address is + * the max and expected case. + */ + assert((region_top <= (UINT64_MAX >> (64U - tzc400.addr_width))) && + (region_base < region_top)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + assert(sec_attr <= TZC_REGION_S_RDWR); + + _tzc400_configure_region(tzc400.base, filters, region, region_base, + region_top, + sec_attr, nsaid_permissions); +} + +void tzc400_update_filters(unsigned int region, unsigned int filters) +{ + /* Do range checks on filters and regions. */ + assert(((filters >> tzc400.num_filters) == 0U) && + (region < tzc400.num_regions)); + + _tzc400_update_filters(tzc400.base, region, tzc400.num_filters, filters); +} + +void tzc400_enable_filters(void) +{ + unsigned int state; + unsigned int filter; + + assert(tzc400.base != 0U); + + for (filter = 0U; filter < tzc400.num_filters; filter++) { + state = _tzc400_get_gate_keeper(tzc400.base, filter); + if (state != 0U) { + /* Filter 0 is special and cannot be disabled. + * So here we allow it being already enabled. */ + if (filter == 0U) { + continue; + } + /* + * The TZC filter is already configured. Changing the + * programmer's view in an active system can cause + * unpredictable behavior therefore panic for now rather + * than try to determine whether this is safe in this + * instance. + * + * See the 'ARM (R) CoreLink TM TZC-400 TrustZone (R) + * Address Space Controller' Technical Reference Manual. + */ + ERROR("TZC-400 : Filter %u Gatekeeper already enabled.\n", + filter); + panic(); + } + _tzc400_set_gate_keeper(tzc400.base, filter, 1); + } +} + +void tzc400_disable_filters(void) +{ + unsigned int filter; + unsigned int state; + unsigned int start = 0U; + + assert(tzc400.base != 0U); + + /* Filter 0 is special and cannot be disabled. */ + state = _tzc400_get_gate_keeper(tzc400.base, 0); + if (state != 0U) { + start++; + } + for (filter = start; filter < tzc400.num_filters; filter++) + _tzc400_set_gate_keeper(tzc400.base, filter, 0); +} + +int tzc400_it_handler(void) +{ + uint32_t filter; + uint32_t filter_it_pending = tzc400.num_filters; + + assert(tzc400.base != 0U); + + for (filter = 0U; filter < tzc400.num_filters; filter++) { + if (_tzc400_get_int_by_filter(tzc400.base, filter) != 0U) { + filter_it_pending = filter; + break; + } + } + + if (filter_it_pending == tzc400.num_filters) { + ERROR("TZC-400: No interrupt pending!\n"); + return -1; + } + +#if DEBUG + _tzc400_dump_fail_filter(tzc400.base, filter_it_pending); +#endif + + _tzc400_clear_it(tzc400.base, filter_it_pending); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h b/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h new file mode 100644 index 0000000..2090944 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_COMMON_PRIVATE_H +#define TZC_COMMON_PRIVATE_H + +#include +#include +#include +#include + +#define DEFINE_TZC_COMMON_WRITE_ACTION(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_action( \ + uintptr_t base, \ + unsigned int action) \ + { \ + mmio_write_32(base + TZC_##macro_name##_ACTION_OFF, \ + action); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_BASE(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_base( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned long long region_base) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_BASE_LOW_0_OFFSET, \ + (uint32_t)region_base); \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_BASE_HIGH_0_OFFSET, \ + (uint32_t)(region_base >> 32)); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_TOP(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_top( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned long long region_top) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_TOP_LOW_0_OFFSET, \ + (uint32_t)region_top); \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_TOP_HIGH_0_OFFSET, \ + (uint32_t)(region_top >> 32)); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_attributes( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int attr) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ + attr); \ + } + +#define DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(fn_name, macro_name) \ + static inline void _tzc##fn_name##_write_region_id_access( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int val) \ + { \ + mmio_write_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + (u_register_t)region_no) + \ + TZC_##macro_name##_REGION_ID_ACCESS_0_OFFSET, \ + val); \ + } + +/* + * It is used to modify the filters status for a defined region. + */ +#define DEFINE_TZC_COMMON_UPDATE_FILTERS(fn_name, macro_name) \ + static inline void _tzc##fn_name##_update_filters( \ + uintptr_t base, \ + unsigned int region_no, \ + unsigned int nbfilters, \ + unsigned int filters) \ + { \ + uint32_t filters_mask = GENMASK(nbfilters - 1U, 0); \ + \ + mmio_clrsetbits_32(base + \ + TZC_REGION_OFFSET( \ + TZC_##macro_name##_REGION_SIZE, \ + region_no) + \ + TZC_##macro_name##_REGION_ATTR_0_OFFSET, \ + filters_mask << TZC_REGION_ATTR_F_EN_SHIFT, \ + filters << TZC_REGION_ATTR_F_EN_SHIFT); \ + } + +/* + * It is used to program region 0 ATTRIBUTES and ACCESS register. + */ +#define DEFINE_TZC_COMMON_CONFIGURE_REGION0(fn_name) \ + static void _tzc##fn_name##_configure_region0(uintptr_t base, \ + unsigned int sec_attr, \ + unsigned int ns_device_access) \ + { \ + assert(base != 0U); \ + VERBOSE("TrustZone : Configuring region 0 " \ + "(TZC Interface Base=0x%lx sec_attr=0x%x," \ + " ns_devs=0x%x)\n", base, \ + sec_attr, ns_device_access); \ + \ + /* Set secure attributes on region 0 */ \ + _tzc##fn_name##_write_region_attributes(base, 0, \ + sec_attr << TZC_REGION_ATTR_SEC_SHIFT); \ + \ + /***************************************************/ \ + /* Specify which non-secure devices have permission*/ \ + /* to access region 0. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_id_access(base, \ + 0, \ + ns_device_access); \ + } + +/* + * It is used to program a region from 1 to 8 in the TrustZone controller. + * NOTE: + * Region 0 is special; it is preferable to use + * ##fn_name##_configure_region0 for this region (see comment for + * that function). + */ +#define DEFINE_TZC_COMMON_CONFIGURE_REGION(fn_name) \ + static void _tzc##fn_name##_configure_region(uintptr_t base, \ + unsigned int filters, \ + unsigned int region_no, \ + unsigned long long region_base, \ + unsigned long long region_top, \ + unsigned int sec_attr, \ + unsigned int nsaid_permissions) \ + { \ + assert(base != 0U); \ + VERBOSE("TrustZone : Configuring region " \ + "(TZC Interface Base: 0x%lx, region_no = %u)" \ + "...\n", base, region_no); \ + VERBOSE("TrustZone : ... base = %llx, top = %llx," \ + "\n", region_base, region_top); \ + VERBOSE("TrustZone : ... sec_attr = 0x%x," \ + " ns_devs = 0x%x)\n", \ + sec_attr, nsaid_permissions); \ + \ + /***************************************************/ \ + /* Inputs look ok, start programming registers. */ \ + /* All the address registers are 32 bits wide and */ \ + /* have a LOW and HIGH */ \ + /* component used to construct an address up to a */ \ + /* 64bit. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_base(base, \ + region_no, region_base); \ + _tzc##fn_name##_write_region_top(base, \ + region_no, region_top); \ + \ + /* Enable filter to the region and set secure attributes */\ + _tzc##fn_name##_write_region_attributes(base, \ + region_no, \ + (sec_attr << TZC_REGION_ATTR_SEC_SHIFT) |\ + (filters << TZC_REGION_ATTR_F_EN_SHIFT));\ + \ + /***************************************************/ \ + /* Specify which non-secure devices have permission*/ \ + /* to access this region. */ \ + /***************************************************/ \ + _tzc##fn_name##_write_region_id_access(base, \ + region_no, \ + nsaid_permissions); \ + } + +static inline unsigned int _tzc_read_peripheral_id(uintptr_t base) +{ + unsigned int id; + + id = mmio_read_32(base + PID0_OFF); + /* Masks DESC part in PID1 */ + id |= ((mmio_read_32(base + PID1_OFF) & 0xFU) << 8U); + + return id; +} + +#endif /* TZC_COMMON_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c new file mode 100644 index 0000000..e45fbf8 --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "tzc_common_private.h" + +/* + * Macros which will be used by common core functions. + */ +#define TZC_DMC500_REGION_BASE_LOW_0_OFFSET 0x054 +#define TZC_DMC500_REGION_BASE_HIGH_0_OFFSET 0x058 +#define TZC_DMC500_REGION_TOP_LOW_0_OFFSET 0x05C +#define TZC_DMC500_REGION_TOP_HIGH_0_OFFSET 0x060 +#define TZC_DMC500_REGION_ATTR_0_OFFSET 0x064 +#define TZC_DMC500_REGION_ID_ACCESS_0_OFFSET 0x068 + +#define TZC_DMC500_ACTION_OFF 0x50 + +/* Pointer to the tzc_dmc500_driver_data structure populated by the platform */ +static const tzc_dmc500_driver_data_t *g_driver_data; +static unsigned int g_sys_if_count; + +#define verify_region_attr(region, attr) \ + ((g_conf_regions[(region)].sec_attr == \ + ((attr) >> TZC_REGION_ATTR_SEC_SHIFT)) \ + && ((attr) & (0x1 << TZC_REGION_ATTR_F_EN_SHIFT))) + +/* + * Structure for configured regions attributes in DMC500. + */ +typedef struct tzc_dmc500_regions { + unsigned int sec_attr; + int is_enabled; +} tzc_dmc500_regions_t; + +/* + * Array storing the attributes of the configured regions. This array + * will be used by the `tzc_dmc500_verify_complete` to verify the flush + * completion. + */ +static tzc_dmc500_regions_t g_conf_regions[MAX_REGION_VAL + 1]; + +/* Helper Macros for making the code readable */ +#define DMC_INST_BASE_ADDR(instance) (g_driver_data->dmc_base[instance]) +#define DMC_INST_SI_BASE(instance, interface) \ + (DMC_INST_BASE_ADDR(instance) + IFACE_OFFSET(interface)) + +DEFINE_TZC_COMMON_WRITE_ACTION(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_BASE(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_TOP(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_ATTRIBUTES(_dmc500, DMC500) +DEFINE_TZC_COMMON_WRITE_REGION_ID_ACCESS(_dmc500, DMC500) + +DEFINE_TZC_COMMON_CONFIGURE_REGION0(_dmc500) +DEFINE_TZC_COMMON_CONFIGURE_REGION(_dmc500) + +static inline unsigned int _tzc_dmc500_read_region_attr_0( + uintptr_t dmc_si_base, + unsigned int region_no) +{ + return mmio_read_32(dmc_si_base + + TZC_REGION_OFFSET(TZC_DMC500_REGION_SIZE, region_no) + + TZC_DMC500_REGION_ATTR_0_OFFSET); +} + +static inline void _tzc_dmc500_write_flush_control(uintptr_t dmc_si_base) +{ + mmio_write_32(dmc_si_base + SI_FLUSH_CTRL_OFFSET, 1); +} + +/* + * Sets the Flush controls for all the DMC Instances and System Interfaces. + * This initiates the flush of configuration settings from the shadow + * registers to the actual configuration register. The caller should poll + * changed register to confirm update. + */ +void tzc_dmc500_config_complete(void) +{ + int dmc_inst, sys_if; + + assert(g_driver_data); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_write_flush_control( + DMC_INST_SI_BASE(dmc_inst, sys_if)); + } +} + +/* + * This function reads back the secure attributes from the configuration + * register for each DMC Instance and System Interface and compares it with + * the configured value. The successful verification of the region attributes + * confirms that the flush operation has completed. + * If the verification fails, the caller is expected to invoke this API again + * till it succeeds. + * Returns 0 on success and 1 on failure. + */ +int tzc_dmc500_verify_complete(void) +{ + int dmc_inst, sys_if, region_no; + unsigned int attr; + + assert(g_driver_data); + /* Region 0 must be configured */ + assert(g_conf_regions[0].is_enabled); + + /* Iterate over all configured regions */ + for (region_no = 0; region_no <= MAX_REGION_VAL; region_no++) { + if (!g_conf_regions[region_no].is_enabled) + continue; + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; + dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; + sys_if++) { + attr = _tzc_dmc500_read_region_attr_0( + DMC_INST_SI_BASE(dmc_inst, sys_if), + region_no); + VERBOSE("Verifying DMC500 region:%d" + " dmc_inst:%d sys_if:%d attr:%x\n", + region_no, dmc_inst, sys_if, attr); + if (!verify_region_attr(region_no, attr)) + return 1; + } + } + } + + return 0; +} + +/* + * `tzc_dmc500_configure_region0` is used to program region 0 in both the + * system interfaces of all the DMC-500 instances. Region 0 covers the whole + * address space that is not mapped to any other region for a system interface, + * and is always enabled; this cannot be changed. This function only changes + * the access permissions. + */ +void tzc_dmc500_configure_region0(unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + int dmc_inst, sys_if; + + /* Assert if DMC-500 is not initialized */ + assert(g_driver_data); + + /* Configure region_0 in all DMC instances */ + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_configure_region0( + DMC_INST_SI_BASE(dmc_inst, sys_if), + sec_attr, nsaid_permissions); + } + + g_conf_regions[0].sec_attr = sec_attr; + g_conf_regions[0].is_enabled = 1; +} + +/* + * `tzc_dmc500_configure_region` is used to program a region into all system + * interfaces of all the DMC instances. + * NOTE: + * Region 0 is special; it is preferable to use tzc_dmc500_configure_region0 + * for this region (see comment for that function). + */ +void tzc_dmc500_configure_region(unsigned int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions) +{ + int dmc_inst, sys_if; + + assert(g_driver_data); + /* Do range checks on regions. */ + assert((region_no >= 0U) && (region_no <= MAX_REGION_VAL)); + + /* + * Do address range check based on DMC-TZ configuration. A 43bit address + * is the max and expected case. + */ + assert(((region_top <= (UINT64_MAX >> (64U - 43U))) && + (region_base < region_top))); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + for (sys_if = 0; sys_if < g_sys_if_count; sys_if++) + _tzc_dmc500_configure_region( + DMC_INST_SI_BASE(dmc_inst, sys_if), + TZC_DMC500_REGION_ATTR_F_EN_MASK, + region_no, region_base, region_top, + sec_attr, nsaid_permissions); + } + + g_conf_regions[region_no].sec_attr = sec_attr; + g_conf_regions[region_no].is_enabled = 1; +} + +/* Sets the action value for all the DMC instances */ +void tzc_dmc500_set_action(unsigned int action) +{ + int dmc_inst; + + assert(g_driver_data); + + for (dmc_inst = 0; dmc_inst < g_driver_data->dmc_count; dmc_inst++) { + assert(DMC_INST_BASE_ADDR(dmc_inst)); + /* + * - Currently no handler is provided to trap an error via + * interrupt or exception. + * - The interrupt action has not been tested. + */ + _tzc_dmc500_write_action(DMC_INST_BASE_ADDR(dmc_inst), action); + } +} + +/* + * A DMC-500 instance must be present at each base address provided by the + * platform. It also expects platform to pass at least one instance of + * DMC-500. + */ +static void validate_plat_driver_data( + const tzc_dmc500_driver_data_t *plat_driver_data) +{ +#if ENABLE_ASSERTIONS + int i; + unsigned int dmc_id; + uintptr_t dmc_base; + + assert(plat_driver_data); + assert(plat_driver_data->dmc_count > 0 && + (plat_driver_data->dmc_count <= MAX_DMC_COUNT)); + + for (i = 0; i < plat_driver_data->dmc_count; i++) { + dmc_base = plat_driver_data->dmc_base[i]; + assert(dmc_base); + + dmc_id = _tzc_read_peripheral_id(dmc_base); + assert(dmc_id == DMC500_PERIPHERAL_ID); + } +#endif /* ENABLE_ASSERTIONS */ +} + + +/* + * Initializes the base address and count of DMC instances. + * + * Note : Only pointer to plat_driver_data is saved, so it is caller's + * responsibility to keep it valid until the driver is used. + */ +void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data) +{ + /* Check valid pointer is passed */ + assert(plat_driver_data); + + /* + * NOTE: This driver expects the DMC-500 controller is already in + * READY state. Hence, it uses the reconfiguration method for + * programming TrustZone regions + */ + /* Validates the information passed by platform */ + validate_plat_driver_data(plat_driver_data); + g_driver_data = plat_driver_data; + + /* Check valid system interface count */ + assert(g_driver_data->sys_if_count <= MAX_SYS_IF_COUNT); + + g_sys_if_count = g_driver_data->sys_if_count; + + /* If interface count is not present then assume max */ + if (g_sys_if_count == 0U) + g_sys_if_count = MAX_SYS_IF_COUNT; +} diff --git a/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c new file mode 100644 index 0000000..7e307ee --- /dev/null +++ b/arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* Mask to extract bit 31 to 16 */ +#define MASK_31_16 UINT64_C(0x0000ffff0000) +/* Mask to extract bit 47 to 32 */ +#define MASK_47_32 UINT64_C(0xffff00000000) + +/* Helper macro for getting dmc_base addr of a dmc_inst */ +#define DMC_BASE(plat_data, dmc_inst) \ + ((uintptr_t)((plat_data)->dmc_base[(dmc_inst)])) + +/* Pointer to the tzc_dmc620_config_data structure populated by the platform */ +static const tzc_dmc620_config_data_t *g_plat_config_data; + +#if ENABLE_ASSERTIONS +/* + * Helper function to check if the DMC-620 instance is present at the + * base address provided by the platform and also check if at least + * one dmc instance is present. + */ +static void tzc_dmc620_validate_plat_driver_data( + const tzc_dmc620_driver_data_t *plat_driver_data) +{ + unsigned int dmc_inst, dmc_count, dmc_id; + uintptr_t base; + + assert(plat_driver_data != NULL); + + dmc_count = plat_driver_data->dmc_count; + assert(dmc_count > 0U); + + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + base = DMC_BASE(plat_driver_data, dmc_inst); + dmc_id = mmio_read_32(base + DMC620_PERIPHERAL_ID_0); + assert(dmc_id == DMC620_PERIPHERAL_ID_0_VALUE); + } +} +#endif + +/* + * Program a region with region base and region top addresses of all + * DMC-620 instances. + */ +static void tzc_dmc620_configure_region(int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr) +{ + uint32_t min_31_00, min_47_32; + uint32_t max_31_00, max_47_32; + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + assert(plat_driver_data != NULL); + + /* Do range checks on regions. */ + assert((region_no >= 0) && (region_no <= DMC620_ACC_ADDR_COUNT)); + + /* region_base and (region_top + 1) must be 4KB aligned */ + assert(((region_base | (region_top + 1U)) & (4096U - 1U)) == 0U); + + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + min_31_00 = (uint32_t)((region_base & MASK_31_16) | sec_attr); + min_47_32 = (uint32_t)((region_base & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); + max_31_00 = (uint32_t)(region_top & MASK_31_16); + max_47_32 = (uint32_t)((region_top & MASK_47_32) + >> DMC620_ACC_ADDR_WIDTH); + + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Configure access address region registers */ + mmio_write_32(base + DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no), + min_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no), + min_47_32); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no), + max_31_00); + mmio_write_32(base + DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no), + max_47_32); + } +} + +/* + * Set the action value for all the DMC-620 instances. + */ +static void tzc_dmc620_set_action(void) +{ + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + /* Switch to READY */ + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_GO); + mmio_write_32(base + DMC620_MEMC_CMD, DMC620_MEMC_CMD_EXECUTE); + } +} + +/* + * Verify whether the DMC-620 configuration is complete by reading back + * configuration registers and comparing it with the configured value. If + * configuration is incomplete, loop till the configured value is reflected in + * the register. + */ +static void tzc_dmc620_verify_complete(void) +{ + unsigned int dmc_inst, dmc_count; + uintptr_t base; + const tzc_dmc620_driver_data_t *plat_driver_data; + + plat_driver_data = g_plat_config_data->plat_drv_data; + dmc_count = plat_driver_data->dmc_count; + for (dmc_inst = 0U; dmc_inst < dmc_count; dmc_inst++) { + /* Extract the base address of the DMC-620 instance */ + base = DMC_BASE(plat_driver_data, dmc_inst); + while ((mmio_read_32(base + DMC620_MEMC_STATUS) & + DMC620_MEMC_CMD_MASK) != DMC620_MEMC_CMD_GO) { + continue; + } + } +} + +/* + * Initialize the DMC-620 TrustZone Controller using the region configuration + * supplied by the platform. The DMC620 controller should be enabled elsewhere + * before invoking this function. + */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data) +{ + uint8_t i; + + /* Check if valid pointer is passed */ + assert(plat_config_data != NULL); + + /* + * Check if access address count passed by the platform is less than or + * equal to DMC620's access address count + */ + assert(plat_config_data->acc_addr_count <= DMC620_ACC_ADDR_COUNT); + +#if ENABLE_ASSERTIONS + /* Validates the information passed by platform */ + tzc_dmc620_validate_plat_driver_data(plat_config_data->plat_drv_data); +#endif + + g_plat_config_data = plat_config_data; + + INFO("Configuring DMC-620 TZC settings\n"); + for (i = 0U; i < g_plat_config_data->acc_addr_count; i++) { + tzc_dmc620_configure_region(i, + g_plat_config_data->plat_acc_addr_data[i].region_base, + g_plat_config_data->plat_acc_addr_data[i].region_top, + g_plat_config_data->plat_acc_addr_data[i].sec_attr); + } + + tzc_dmc620_set_action(); + tzc_dmc620_verify_complete(); + INFO("DMC-620 TZC setup completed\n"); +} diff --git a/arm-trusted-firmware/drivers/auth/auth_mod.c b/arm-trusted-firmware/drivers/auth/auth_mod.c new file mode 100644 index 0000000..a99a2c7 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/auth_mod.c @@ -0,0 +1,444 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ASN.1 tags */ +#define ASN1_INTEGER 0x02 + +#define return_if_error(rc) \ + do { \ + if (rc != 0) { \ + return rc; \ + } \ + } while (0) + +#pragma weak plat_set_nv_ctr2 + + +static int cmp_auth_param_type_desc(const auth_param_type_desc_t *a, + const auth_param_type_desc_t *b) +{ + if ((a->type == b->type) && (a->cookie == b->cookie)) { + return 0; + } + return 1; +} + +/* + * This function obtains the requested authentication parameter data from the + * information extracted from the parent image after its authentication. + */ +static int auth_get_param(const auth_param_type_desc_t *param_type_desc, + const auth_img_desc_t *img_desc, + void **param, unsigned int *len) +{ + int i; + + if (img_desc->authenticated_data == NULL) + return 1; + + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (0 == cmp_auth_param_type_desc(param_type_desc, + img_desc->authenticated_data[i].type_desc)) { + *param = img_desc->authenticated_data[i].data.ptr; + *len = img_desc->authenticated_data[i].data.len; + return 0; + } + } + + return 1; +} + +/* + * Authenticate an image by matching the data hash + * + * This function implements 'AUTH_METHOD_HASH'. To authenticate an image using + * this method, the image must contain: + * + * - The data to calculate the hash from + * + * The parent image must contain: + * + * - The hash to be matched with (including hash algorithm) + * + * For a successful authentication, both hashes must match. The function calls + * the crypto-module to check this matching. + * + * Parameters: + * param: parameters to perform the hash authentication + * img_desc: pointer to image descriptor so we can know the image type + * and parent image + * img: pointer to image in memory + * img_len: length of image (in bytes) + * + * Return: + * 0 = success, Otherwise = error + */ +static int auth_hash(const auth_method_param_hash_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *hash_der_ptr; + unsigned int data_len, hash_der_len; + int rc = 0; + + /* Get the hash from the parent image. This hash will be DER encoded + * and contain the hash algorithm */ + rc = auth_get_param(param->hash, img_desc->parent, + &hash_der_ptr, &hash_der_len); + return_if_error(rc); + + /* Get the data to be hashed from the current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->data, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Ask the crypto module to verify this hash */ + rc = crypto_mod_verify_hash(data_ptr, data_len, + hash_der_ptr, hash_der_len); + + return rc; +} + +/* + * Authenticate by digital signature + * + * This function implements 'AUTH_METHOD_SIG'. To authenticate an image using + * this method, the image must contain: + * + * - Data to be signed + * - Signature + * - Signature algorithm + * + * We rely on the image parser module to extract this data from the image. + * The parent image must contain: + * + * - Public key (or a hash of it) + * + * If the parent image contains only a hash of the key, we will try to obtain + * the public key from the image itself (i.e. self-signed certificates). In that + * case, the signature verification is considered just an integrity check and + * the authentication is established by calculating the hash of the key and + * comparing it with the hash obtained from the parent. + * + * If the image has no parent (NULL), it means it has to be authenticated using + * the ROTPK stored in the platform. Again, this ROTPK could be the key itself + * or a hash of it. + * + * Return: 0 = success, Otherwise = error + */ +static int auth_signature(const auth_method_param_sig_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len) +{ + void *data_ptr, *pk_ptr, *pk_hash_ptr, *sig_ptr, *sig_alg_ptr; + unsigned int data_len, pk_len, pk_hash_len, sig_len, sig_alg_len; + unsigned int flags = 0; + int rc = 0; + + /* Get the data to be signed from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->data, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Get the signature from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->sig, + img, img_len, &sig_ptr, &sig_len); + return_if_error(rc); + + /* Get the signature algorithm from current image */ + rc = img_parser_get_auth_param(img_desc->img_type, param->alg, + img, img_len, &sig_alg_ptr, &sig_alg_len); + return_if_error(rc); + + /* Get the public key from the parent. If there is no parent (NULL), + * the certificate has been signed with the ROTPK, so we have to get + * the PK from the platform */ + if (img_desc->parent) { + rc = auth_get_param(param->pk, img_desc->parent, + &pk_ptr, &pk_len); + } else { + rc = plat_get_rotpk_info(param->pk->cookie, &pk_ptr, &pk_len, + &flags); + } + return_if_error(rc); + + if (flags & (ROTPK_IS_HASH | ROTPK_NOT_DEPLOYED)) { + /* If the PK is a hash of the key or if the ROTPK is not + deployed on the platform, retrieve the key from the image */ + pk_hash_ptr = pk_ptr; + pk_hash_len = pk_len; + rc = img_parser_get_auth_param(img_desc->img_type, + param->pk, img, img_len, + &pk_ptr, &pk_len); + return_if_error(rc); + + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + return_if_error(rc); + + if (flags & ROTPK_NOT_DEPLOYED) { + NOTICE("ROTPK is not deployed on platform. " + "Skipping ROTPK verification.\n"); + } else { + /* Ask the crypto-module to verify the key hash */ + rc = crypto_mod_verify_hash(pk_ptr, pk_len, + pk_hash_ptr, pk_hash_len); + } + } else { + /* Ask the crypto module to verify the signature */ + rc = crypto_mod_verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); + } + + return rc; +} + +/* + * Authenticate by Non-Volatile counter + * + * To protect the system against rollback, the platform includes a non-volatile + * counter whose value can only be increased. All certificates include a counter + * value that should not be lower than the value stored in the platform. If the + * value is larger, the counter in the platform must be updated to the new value + * (provided it has been authenticated). + * + * Return: 0 = success, Otherwise = error + * Returns additionally, + * cert_nv_ctr -> NV counter value present in the certificate + * need_nv_ctr_upgrade = 0 -> platform NV counter upgrade is not needed + * need_nv_ctr_upgrade = 1 -> platform NV counter upgrade is needed + */ +static int auth_nvctr(const auth_method_param_nv_ctr_t *param, + const auth_img_desc_t *img_desc, + void *img, unsigned int img_len, + unsigned int *cert_nv_ctr, + bool *need_nv_ctr_upgrade) +{ + char *p; + void *data_ptr = NULL; + unsigned int data_len, len, i; + unsigned int plat_nv_ctr; + int rc = 0; + bool is_trial_run = false; + + /* Get the counter value from current image. The AM expects the IPM + * to return the counter value as a DER encoded integer */ + rc = img_parser_get_auth_param(img_desc->img_type, param->cert_nv_ctr, + img, img_len, &data_ptr, &data_len); + return_if_error(rc); + + /* Parse the DER encoded integer */ + assert(data_ptr); + p = (char *)data_ptr; + if (*p != ASN1_INTEGER) { + /* Invalid ASN.1 integer */ + return 1; + } + p++; + + /* NV-counters are unsigned integers up to 32-bit */ + len = (unsigned int)(*p & 0x7f); + if ((*p & 0x80) || (len > 4)) { + return 1; + } + p++; + + /* Check the number is not negative */ + if (*p & 0x80) { + return 1; + } + + /* Convert to unsigned int. This code is for a little-endian CPU */ + *cert_nv_ctr = 0; + for (i = 0; i < len; i++) { + *cert_nv_ctr = (*cert_nv_ctr << 8) | *p++; + } + + /* Get the counter from the platform */ + rc = plat_get_nv_ctr(param->plat_nv_ctr->cookie, &plat_nv_ctr); + return_if_error(rc); + + if (*cert_nv_ctr < plat_nv_ctr) { + /* Invalid NV-counter */ + return 1; + } else if (*cert_nv_ctr > plat_nv_ctr) { +#if PSA_FWU_SUPPORT && IMAGE_BL2 + is_trial_run = fwu_is_trial_run_state(); +#endif /* PSA_FWU_SUPPORT && IMAGE_BL2 */ + *need_nv_ctr_upgrade = !is_trial_run; + } + + return 0; +} + +int plat_set_nv_ctr2(void *cookie, const auth_img_desc_t *img_desc __unused, + unsigned int nv_ctr) +{ + return plat_set_nv_ctr(cookie, nv_ctr); +} + +/* + * Return the parent id in the output parameter '*parent_id' + * + * Return value: + * 0 = Image has parent, 1 = Image has no parent or parent is authenticated + */ +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + const auth_img_desc_t *img_desc = NULL; + + assert(parent_id != NULL); + /* Get the image descriptor */ + img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id); + + /* Check if the image has no parent (ROT) */ + if (img_desc->parent == NULL) { + *parent_id = 0; + return 1; + } + + /* Check if the parent has already been authenticated */ + if (auth_img_flags[img_desc->parent->img_id] & IMG_FLAG_AUTHENTICATED) { + *parent_id = 0; + return 1; + } + + *parent_id = img_desc->parent->img_id; + return 0; +} + +/* + * Initialize the different modules in the authentication framework + */ +void auth_mod_init(void) +{ + /* Check we have a valid CoT registered */ + assert(cot_desc_ptr != NULL); + + /* Image parser module */ + img_parser_init(); +} + +/* + * Authenticate a certificate/image + * + * Return: 0 = success, Otherwise = error + */ +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len) +{ + const auth_img_desc_t *img_desc = NULL; + const auth_method_desc_t *auth_method = NULL; + void *param_ptr; + unsigned int param_len; + int rc, i; + unsigned int cert_nv_ctr = 0; + bool need_nv_ctr_upgrade = false; + bool sig_auth_done = false; + const auth_method_param_nv_ctr_t *nv_ctr_param = NULL; + + /* Get the image descriptor from the chain of trust */ + img_desc = FCONF_GET_PROPERTY(tbbr, cot, img_id); + + /* Ask the parser to check the image integrity */ + rc = img_parser_check_integrity(img_desc->img_type, img_ptr, img_len); + return_if_error(rc); + + /* Authenticate the image using the methods indicated in the image + * descriptor. */ + if (img_desc->img_auth_methods == NULL) + return 1; + for (i = 0 ; i < AUTH_METHOD_NUM ; i++) { + auth_method = &img_desc->img_auth_methods[i]; + switch (auth_method->type) { + case AUTH_METHOD_NONE: + rc = 0; + break; + case AUTH_METHOD_HASH: + rc = auth_hash(&auth_method->param.hash, + img_desc, img_ptr, img_len); + break; + case AUTH_METHOD_SIG: + rc = auth_signature(&auth_method->param.sig, + img_desc, img_ptr, img_len); + sig_auth_done = true; + break; + case AUTH_METHOD_NV_CTR: + nv_ctr_param = &auth_method->param.nv_ctr; + rc = auth_nvctr(nv_ctr_param, + img_desc, img_ptr, img_len, + &cert_nv_ctr, &need_nv_ctr_upgrade); + break; + default: + /* Unknown authentication method */ + rc = 1; + break; + } + return_if_error(rc); + } + + /* + * Do platform NV counter upgrade only if the certificate gets + * authenticated, and platform NV-counter upgrade is needed. + */ + if (need_nv_ctr_upgrade && sig_auth_done) { + rc = plat_set_nv_ctr2(nv_ctr_param->plat_nv_ctr->cookie, + img_desc, cert_nv_ctr); + return_if_error(rc); + } + + /* Extract the parameters indicated in the image descriptor to + * authenticate the children images. */ + if (img_desc->authenticated_data != NULL) { + for (i = 0 ; i < COT_MAX_VERIFIED_PARAMS ; i++) { + if (img_desc->authenticated_data[i].type_desc == NULL) { + continue; + } + + /* Get the parameter from the image parser module */ + rc = img_parser_get_auth_param(img_desc->img_type, + img_desc->authenticated_data[i].type_desc, + img_ptr, img_len, ¶m_ptr, ¶m_len); + return_if_error(rc); + + /* Check parameter size */ + if (param_len > img_desc->authenticated_data[i].data.len) { + return 1; + } + + /* Copy the parameter for later use */ + memcpy((void *)img_desc->authenticated_data[i].data.ptr, + (void *)param_ptr, param_len); + } + } + + /* Mark image as authenticated */ + auth_img_flags[img_desc->img_id] |= IMG_FLAG_AUTHENTICATED; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/auth/crypto_mod.c b/arm-trusted-firmware/drivers/auth/crypto_mod.c new file mode 100644 index 0000000..eada357 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/crypto_mod.c @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2015-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* Variable exported by the crypto library through REGISTER_CRYPTO_LIB() */ + +/* + * The crypto module is responsible for verifying digital signatures and hashes. + * It relies on a crypto library to perform the cryptographic operations. + * + * The crypto module itself does not impose any specific format on signatures, + * signature algorithm, keys or hashes, but most cryptographic libraries will + * take the parameters as the following DER encoded ASN.1 structures: + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * SignatureAlgorithm ::= AlgorithmIdentifier + * + * SignatureValue ::= BIT STRING + */ + +/* + * Perform some static checking and call the library initialization function + */ +void crypto_mod_init(void) +{ + assert(crypto_lib_desc.name != NULL); + assert(crypto_lib_desc.init != NULL); +#if TRUSTED_BOARD_BOOT + assert(crypto_lib_desc.verify_signature != NULL); + assert(crypto_lib_desc.verify_hash != NULL); +#endif /* TRUSTED_BOARD_BOOT */ +#if MEASURED_BOOT + assert(crypto_lib_desc.calc_hash != NULL); +#endif /* MEASURED_BOOT */ + + /* Initialize the cryptographic library */ + crypto_lib_desc.init(); + INFO("Using crypto library '%s'\n", crypto_lib_desc.name); +} + +/* + * Function to verify a digital signature + * + * Parameters: + * + * data_ptr, data_len: signed data + * sig_ptr, sig_len: the digital signature + * sig_alg_ptr, sig_alg_len: the digital signature algorithm + * pk_ptr, pk_len: the public key + */ +int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg_ptr, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(sig_ptr != NULL); + assert(sig_len != 0); + assert(sig_alg_ptr != NULL); + assert(sig_alg_len != 0); + assert(pk_ptr != NULL); + assert(pk_len != 0); + + return crypto_lib_desc.verify_signature(data_ptr, data_len, + sig_ptr, sig_len, + sig_alg_ptr, sig_alg_len, + pk_ptr, pk_len); +} + +/* + * Verify a hash by comparison + * + * Parameters: + * + * data_ptr, data_len: data to be hashed + * digest_info_ptr, digest_info_len: hash to be compared + */ +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(digest_info_ptr != NULL); + assert(digest_info_len != 0); + + return crypto_lib_desc.verify_hash(data_ptr, data_len, + digest_info_ptr, digest_info_len); +} + +#if MEASURED_BOOT +/* + * Calculate a hash + * + * Parameters: + * + * alg: message digest algorithm + * data_ptr, data_len: data to be hashed + * output: resulting hash + */ +int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]) +{ + assert(data_ptr != NULL); + assert(data_len != 0); + assert(output != NULL); + + return crypto_lib_desc.calc_hash(alg, data_ptr, data_len, output); +} +#endif /* MEASURED_BOOT */ + +/* + * Authenticated decryption of data + * + * Parameters: + * + * dec_algo: authenticated decryption algorithm + * data_ptr, len: data to be decrypted (inout param) + * key, key_len, key_flags: symmetric decryption key + * iv, iv_len: initialization vector + * tag, tag_len: authentication tag + */ +int crypto_mod_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) +{ + assert(crypto_lib_desc.auth_decrypt != NULL); + assert(data_ptr != NULL); + assert(len != 0U); + assert(key != NULL); + assert(key_len != 0U); + assert(iv != NULL); + assert((iv_len != 0U) && (iv_len <= CRYPTO_MAX_IV_SIZE)); + assert(tag != NULL); + assert((tag_len != 0U) && (tag_len <= CRYPTO_MAX_TAG_SIZE)); + + return crypto_lib_desc.auth_decrypt(dec_algo, data_ptr, len, key, + key_len, key_flags, iv, iv_len, tag, + tag_len); +} diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c new file mode 100644 index 0000000..c7ee36f --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#define LIB_NAME "CryptoCell 712 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvSbromInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvSbromInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvLcsGetAndInit((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvLcsGetAndInit() error %x\n", ret); + panic(); + } + + /* If the lifecyclestate is `SD`, then stop further execution */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) { + ERROR("CryptoCell LCS is security-disabled\n"); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + CCError_t error; + CCSbNParams_t pk; + CCSbSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + /* Temp buf to store the public key modulo (N) in LE format */ + uint32_t RevN[SB_RSA_MOD_SIZE_IN_WORDS]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The CCSbVerifySignature() API expects N and Np in BE format and + * the signature in LE format. Copy N from certificate. + */ + memcpy(pk.N, p, RSA_MOD_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* + * Calculate the Np (Barrett n' value). The RSA_CalcNp() API expects + * N in LE format. Hence reverse N into a temporary buffer `RevN`. + */ + UTIL_ReverseMemCopy((uint8_t *)RevN, (uint8_t *)pk.N, sizeof(RevN)); + + RSA_CalcNp((uintptr_t)PLAT_CRYPTOCELL_BASE, RevN, pk.Np); + + /* Np is in LE format. Reverse it to BE */ + UTIL_ReverseBuff((uint8_t *)pk.Np, sizeof(pk.Np)); + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != RSA_MOD_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * The signature is BE format. Convert it to LE before calling + * CCSbVerifySignature(). + */ + UTIL_ReverseMemCopy((uint8_t *)signature.sig, p, RSA_MOD_SIZE_IN_BYTES); + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + /* Verify the signature */ + error = CCSbVerifySignature((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uint32_t *)data_ptr, &pk, &signature, + data_len, RSA_PSS); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + /* + * CryptoCell utilises DMA internally to transfer data. Flush the data + * from caches. + */ + flush_dcache_range((uintptr_t)data_ptr, data_len); + + hash = p; + error = SBROM_CryptoHash((uintptr_t)PLAT_CRYPTOCELL_BASE, + (uintptr_t)data_ptr, data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c new file mode 100644 index 0000000..53d77db --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include + +/* + * Return the ROTPK hash + * + * dst: buffer into which the ROTPK hash will be copied into + * len: length of the provided buffer, which must be at least enough for a + * SHA256 hash + * flags: a pointer to integer that will be set to indicate the ROTPK status + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = NVM_GetLCS(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + /* If the lifecycle state is `SD`, return failure */ + if (lcs == CC_BSV_SECURITY_DISABLED_LCS) + return 1; + + /* + * If the lifecycle state is `CM` or `DM`, ROTPK shouldn't be verified. + * Return success after setting ROTPK_NOT_DEPLOYED flag + */ + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || + (lcs == CC_BSV_DEVICE_MANUFACTURE_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + /* Copy the DER header */ + error = NVM_ReadHASHPubKey(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + (uint32_t *)dst, HASH_RESULT_SIZE_IN_WORDS); + if (error != CC_OK) + return 1; + + *flags = ROTPK_IS_HASH; + return 0; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_GetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER1, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = NVM_SetSwVersion(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_COUNTER2, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c new file mode 100644 index 0000000..077317e --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define LIB_NAME "CryptoCell 713 SBROM" +#define RSA_SALT_LEN 32 +#define RSA_EXPONENT 65537 + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm, + * maskGenAlgorithm [1] MaskGenAlgorithm, + * saltLength [2] INTEGER, + * trailerField [3] TrailerField DEFAULT trailerFieldBC + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + CCError_t ret; + uint32_t lcs; + + /* Initialize CC SBROM */ + ret = CC_BsvInit((uintptr_t)PLAT_CRYPTOCELL_BASE); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvInit() error %x\n", ret); + panic(); + } + + /* Initialize lifecycle state */ + ret = CC_BsvGetAndInitLcs((uintptr_t)PLAT_CRYPTOCELL_BASE, &lcs); + if (ret != CC_OK) { + ERROR("CryptoCell CC_BsvGetAndInitLcs() error %x\n", ret); + panic(); + } +} + +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + CCError_t error; + CCBsvNBuff_t NBuff; + CCBsvSignature_t signature; + int rc, exp; + mbedtls_asn1_buf sig_oid, alg_oid, params; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_rsassa_pss_options pss_opts; + size_t len; + uint8_t *p, *end; + CCHashResult_t digest; + CCBool_t is_verified; + /* This is a rather large array, we don't want it on stack */ + static uint32_t workspace[BSV_RSA_WORKSPACE_MIN_SIZE]; + + /* Verify the signature algorithm */ + /* Get pointers to signature OID and parameters */ + p = sig_alg; + end = p + sig_alg_len; + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_oid_get_sig_alg(&sig_oid, &md_alg, &pk_alg); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports RSASSA-PSS signature */ + if (pk_alg != MBEDTLS_PK_RSASSA_PSS || md_alg != MBEDTLS_MD_NONE) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the RSASSA-PSS params */ + /* The trailer field is verified to be 0xBC internally by this API */ + rc = mbedtls_x509_get_rsassa_pss_params(¶ms, &md_alg, + &pss_opts.mgf1_hash_id, + &pss_opts.expected_salt_len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + /* The CryptoCell only supports SHA256 as hash algorithm */ + if (md_alg != MBEDTLS_MD_SHA256 || + pss_opts.mgf1_hash_id != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_SIGNATURE; + + if (pss_opts.expected_salt_len != RSA_SALT_LEN) + return CRYPTO_ERR_SIGNATURE; + + /* Parse the public key */ + p = pk_ptr; + end = p + pk_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + end = p + len; + rc = mbedtls_asn1_get_alg_null(&p, end, &alg_oid); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (mbedtls_oid_get_pk_alg(&alg_oid, &pk_alg) != 0) + return CRYPTO_ERR_SIGNATURE; + + if (pk_alg != MBEDTLS_PK_RSA) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (*p == 0) { + p++; len--; + } + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy N from certificate. + */ + memcpy(NBuff, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + /* Verify the RSA exponent */ + p += len; + rc = mbedtls_asn1_get_int(&p, end, &exp); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (exp != RSA_EXPONENT) + return CRYPTO_ERR_SIGNATURE; + + /* Get the signature (bitstring) */ + p = sig_ptr; + end = p + sig_len; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &len); + if (rc != 0) + return CRYPTO_ERR_SIGNATURE; + + if (len != BSV_CERT_RSA_KEY_SIZE_IN_BYTES || ((p + len) > end)) + return CRYPTO_ERR_SIGNATURE; + + /* + * Copy the signature (in BE format) + */ + memcpy((uint8_t *)signature, p, BSV_CERT_RSA_KEY_SIZE_IN_BYTES); + + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, + data_ptr, data_len, digest); + if (error != CC_OK) + return CRYPTO_ERR_SIGNATURE; + + /* Verify the signature */ + error = CC_BsvRsaPssVerify((uintptr_t)PLAT_CRYPTOCELL_BASE, NBuff, + NULL, signature, digest, workspace, + BSV_RSA_WORKSPACE_MIN_SIZE, &is_verified); + if ((error != CC_OK) || (is_verified != CC_TRUE)) + return CRYPTO_ERR_SIGNATURE; + + /* Signature verification success */ + return CRYPTO_SUCCESS; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + uint8_t *p, *end, *hash; + CCHashResult_t pubKeyHash; + size_t len; + int rc; + CCError_t error; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) + return CRYPTO_ERR_HASH; + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) + return CRYPTO_ERR_HASH; + /* Verify that hash algorithm is SHA256 */ + if (md_alg != MBEDTLS_MD_SHA256) + return CRYPTO_ERR_HASH; + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) + return CRYPTO_ERR_HASH; + + /* Length of hash must match the algorithm's size */ + if (len != HASH_RESULT_SIZE_IN_BYTES) + return CRYPTO_ERR_HASH; + + hash = p; + error = CC_BsvSha256((uintptr_t)PLAT_CRYPTOCELL_BASE, data_ptr, + data_len, pubKeyHash); + if (error != CC_OK) + return CRYPTO_ERR_HASH; + + rc = memcmp(pubKeyHash, hash, HASH_RESULT_SIZE_IN_BYTES); + if (rc != 0) + return CRYPTO_ERR_HASH; + + return CRYPTO_SUCCESS; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c new file mode 100644 index 0000000..17e1280 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * Return the ROTPK hash + * + * Return: 0 = success, Otherwise = error + */ +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, unsigned int *flags) +{ + CCError_t error; + uint32_t lcs; + int i; + uint32_t *key = (uint32_t *)dst; + + assert(dst != NULL); + assert(len >= HASH_RESULT_SIZE_IN_WORDS); + assert(flags != NULL); + + error = CC_BsvLcsGet(PLAT_CRYPTOCELL_BASE, &lcs); + if (error != CC_OK) + return 1; + + if ((lcs == CC_BSV_CHIP_MANUFACTURE_LCS) || (lcs == CC_BSV_RMA_LCS)) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + error = CC_BsvPubKeyHashGet(PLAT_CRYPTOCELL_BASE, + CC_SB_HASH_BOOT_KEY_256B, + key, HASH_RESULT_SIZE_IN_WORDS); + + if (error == CC_BSV_HASH_NOT_PROGRAMMED_ERR) { + *flags = ROTPK_NOT_DEPLOYED; + return 0; + } + + if (error == CC_OK) { + + /* Keys are stored in OTP in little-endian format */ + for (i = 0; i < HASH_RESULT_SIZE_IN_WORDS; i++) + key[i] = le32toh(key[i]); + + *flags = ROTPK_IS_HASH; + return 0; + } + + return 1; +} + +/* + * Return the non-volatile counter value stored in the platform. The cookie + * specifies the OID of the counter in the certificate. + * + * Return: 0 = success, Otherwise = error + */ +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionGet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + +/* + * Store a new non-volatile counter value in the counter specified by the OID + * in the cookie. This function is not expected to be called if the Lifecycle + * state is RMA as the values in the certificate are expected to always match + * the nvcounter values. But if called when the LCS is RMA, the underlying + * helper functions will return success but without updating the counter. + * + * Return: 0 = success, Otherwise = error + */ +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr) +{ + CCError_t error = CC_FAIL; + + if (strcmp(cookie, TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_TRUSTED, nv_ctr); + } else if (strcmp(cookie, NON_TRUSTED_FW_NVCOUNTER_OID) == 0) { + error = CC_BsvSwVersionSet(PLAT_CRYPTOCELL_BASE, + CC_SW_VERSION_NON_TRUSTED, nv_ctr); + } + + return (error != CC_OK); +} + diff --git a/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk b/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk new file mode 100644 index 0000000..db39047 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/cryptocell/cryptocell_crypto.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +# The algorithm is RSA when using Cryptocell crypto driver +TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA + +# Needs to be set to drive mbed TLS configuration correctly +$(eval $(call add_define,TF_MBEDTLS_KEY_ALG_ID)) + +$(eval $(call add_define,KEY_SIZE)) + +# CCSBROM_LIB_PATH must be set to the Cryptocell SBROM library path +ifeq (${CCSBROM_LIB_PATH},) + $(error Error: CCSBROM_LIB_PATH not set) +endif + +CRYPTOCELL_VERSION ?= 712 +ifeq (${CRYPTOCELL_VERSION},712) + CCSBROM_LIB_FILENAME := cc_712sbromx509 +else ifeq (${CRYPTOCELL_VERSION},713) + CCSBROM_LIB_FILENAME := cc_713bsv +else + $(error Error: CRYPTOCELL_VERSION set to invalid version) +endif + +CRYPTOCELL_SRC_DIR := drivers/auth/cryptocell/${CRYPTOCELL_VERSION}/ + +CRYPTOCELL_SOURCES := ${CRYPTOCELL_SRC_DIR}/cryptocell_crypto.c \ + ${CRYPTOCELL_SRC_DIR}/cryptocell_plat_helpers.c + +TF_LDFLAGS += -L$(CCSBROM_LIB_PATH) +LDLIBS += -l$(CCSBROM_LIB_FILENAME) + +BL1_SOURCES += ${CRYPTOCELL_SOURCES} +BL2_SOURCES += ${CRYPTOCELL_SOURCES} diff --git a/arm-trusted-firmware/drivers/auth/dualroot/cot.c b/arm-trusted-firmware/drivers/auth/dualroot/cot.c new file mode 100644 index 0000000..8368503 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/dualroot/cot.c @@ -0,0 +1,959 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include MBEDTLS_CONFIG_FILE +#include +#include + +/* + * Allocate static buffers to store the authentication parameters extracted from + * the certificates. + */ +static unsigned char fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char hw_config_hash_buf[HASH_DER_LEN]; +static unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +#ifdef IMAGE_BL2 +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; +#if defined(SPD_spmd) +static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN]; +#endif /* SPD_spmd */ + +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +#endif + +/* + * Parameter type descriptors. + */ +static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +static auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID); +static auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, HW_CONFIG_HASH_OID); +static auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FW_CONFIG_HASH_OID); +#ifdef IMAGE_BL1 +static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FWU_HASH_OID); +#endif /* IMAGE_BL1 */ + +#ifdef IMAGE_BL2 +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); + +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t prot_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, PROT_PK_OID); + +static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +#if defined(SPD_spmd) +static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG1_HASH_OID); +static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG2_HASH_OID); +static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG3_HASH_OID); +static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG4_HASH_OID); +static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG5_HASH_OID); +static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG6_HASH_OID); +static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG7_HASH_OID); +static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG8_HASH_OID); +#endif /* SPD_spmd */ +#endif /* IMAGE_BL2 */ + + +/* BL2 */ +static const auth_img_desc_t trusted_boot_fw_cert = { + .img_id = TRUSTED_BOOT_FW_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tb_fw_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tb_fw_config_hash, + .data = { + .ptr = (void *)tb_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &hw_config_hash, + .data = { + .ptr = (void *)hw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &fw_config_hash, + .data = { + .ptr = (void *)fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +#ifdef IMAGE_BL1 +static const auth_img_desc_t bl2_image = { + .img_id = BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_hash + } + } + } +}; +#endif /* IMAGE_BL1 */ + +/* HW Config */ +static const auth_img_desc_t hw_config = { + .img_id = HW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &hw_config_hash + } + } + } +}; + +/* TB FW Config */ +#ifdef IMAGE_BL1 +static const auth_img_desc_t tb_fw_config = { + .img_id = TB_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_config_hash + } + } + } +}; + +static const auth_img_desc_t fw_config = { + .img_id = FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &fw_config_hash + } + } + } +}; + +#endif /* IMAGE_BL1 */ + +#ifdef IMAGE_BL2 +/* Trusted key certificate */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + } +}; + +/* SCP Firmware */ +static const auth_img_desc_t scp_fw_key_cert = { + .img_id = SCP_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t scp_fw_content_cert = { + .img_id = SCP_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &scp_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &scp_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &scp_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_fw_hash + } + } + } +}; + +/* SoC Firmware */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; + +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; + +/* Trusted OS Firmware */ +static const auth_img_desc_t trusted_os_fw_key_cert = { + .img_id = TRUSTED_OS_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; + +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; + +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; + +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; + +/* Non-Trusted Firmware */ +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, /* Root certificate. */ + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &prot_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; + +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; + +/* + * Secure Partitions + */ +#if defined(SPD_spmd) +static const auth_img_desc_t sip_sp_content_cert = { + .img_id = SIP_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg1_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[0], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg2_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[1], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg3_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[2], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg4_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[3], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_SIP_SP_PKG(1); +DEFINE_SIP_SP_PKG(2); +DEFINE_SIP_SP_PKG(3); +DEFINE_SIP_SP_PKG(4); + +static const auth_img_desc_t plat_sp_content_cert = { + .img_id = PLAT_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &prot_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg5_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[4], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg6_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[5], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg7_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[6], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg8_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[7], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_PLAT_SP_PKG(5); +DEFINE_PLAT_SP_PKG(6); +DEFINE_PLAT_SP_PKG(7); +DEFINE_PLAT_SP_PKG(8); +#endif /* SPD_spmd */ + +#else /* IMAGE_BL2 */ + +/* FWU auth descriptor */ +static const auth_img_desc_t fwu_cert = { + .img_id = FWU_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_bl2u_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &bl2u_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ns_bl2u_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +/* SCP_BL2U */ +static const auth_img_desc_t scp_bl2u_image = { + .img_id = SCP_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_bl2u_hash + } + } + } +}; + +/* BL2U */ +static const auth_img_desc_t bl2u_image = { + .img_id = BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl2u_hash + } + } + } +}; + +/* NS_BL2U */ +static const auth_img_desc_t ns_bl2u_image = { + .img_id = NS_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ns_bl2u_hash + } + } + } +}; +#endif /* IMAGE_BL2 */ + +/* + * Chain of trust definition + */ +#ifdef IMAGE_BL1 +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [BL2_IMAGE_ID] = &bl2_image, + [HW_CONFIG_ID] = &hw_config, + [TB_FW_CONFIG_ID] = &tb_fw_config, + [FW_CONFIG_ID] = &fw_config, + [FWU_CERT_ID] = &fwu_cert, + [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image, + [BL2U_IMAGE_ID] = &bl2u_image, + [NS_BL2U_IMAGE_ID] = &ns_bl2u_image +}; +#else /* IMAGE_BL2 */ +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [HW_CONFIG_ID] = &hw_config, + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert, + [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert, + [BL32_IMAGE_ID] = &bl32_image, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, + [PLAT_SP_CONTENT_CERT_ID] = &plat_sp_content_cert, + [SP_PKG1_ID] = &sp_pkg1, + [SP_PKG2_ID] = &sp_pkg2, + [SP_PKG3_ID] = &sp_pkg3, + [SP_PKG4_ID] = &sp_pkg4, + [SP_PKG5_ID] = &sp_pkg5, + [SP_PKG6_ID] = &sp_pkg6, + [SP_PKG7_ID] = &sp_pkg7, + [SP_PKG8_ID] = &sp_pkg8, +#endif +}; +#endif + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/img_parser_mod.c b/arm-trusted-firmware/drivers/auth/img_parser_mod.c new file mode 100644 index 0000000..535695d --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/img_parser_mod.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_START__, PARSER_LIB_DESCS_START); +IMPORT_SYM(uintptr_t, __PARSER_LIB_DESCS_END__, PARSER_LIB_DESCS_END); +static unsigned int parser_lib_indices[IMG_MAX_TYPES]; +static img_parser_lib_desc_t *parser_lib_descs; + +#define INVALID_IDX UINT_MAX + +static void validate_desc(img_parser_lib_desc_t *desc) +{ + assert(desc != NULL); + assert(desc->init != NULL); + assert(desc->name != NULL); + assert(desc->check_integrity != NULL); + assert(desc->get_auth_param != NULL); +} + +void img_parser_init(void) +{ + unsigned int index, mod_num; + + /* Initialise internal variables to invalid state */ + for (index = 0; index < IMG_MAX_TYPES; index++) { + parser_lib_indices[index] = INVALID_IDX; + } + + /* Calculate how many image parsers are registered. At least one parser + * must be present */ + mod_num = PARSER_LIB_DESCS_END - PARSER_LIB_DESCS_START; + mod_num /= sizeof(img_parser_lib_desc_t); + assert(mod_num > 0); + + parser_lib_descs = (img_parser_lib_desc_t *) PARSER_LIB_DESCS_START; + for (index = 0; index < mod_num; index++) { + + /* Check that the image parser library descriptor is valid */ + validate_desc(&parser_lib_descs[index]); + + /* Initialize image parser */ + parser_lib_descs[index].init(); + + /* Ensure only one parser is registered for each image type */ + assert(parser_lib_indices[parser_lib_descs[index].img_type] == + INVALID_IDX); + + /* Keep the index of this hash calculator */ + parser_lib_indices[parser_lib_descs[index].img_type] = index; + } +} + +int img_parser_check_integrity(img_type_t img_type, + void *img_ptr, unsigned int img_len) +{ + unsigned int idx; + + assert(img_ptr != NULL); + assert(img_len != 0); + + /* No integrity checks on raw images */ + if (img_type == IMG_RAW) { + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to check the image integrity */ + return parser_lib_descs[idx].check_integrity(img_ptr, img_len); +} + +/* + * Extract an authentication parameter from an image + * + * Parameters: + * img_type: image type (certificate, raw image, etc) + * type_desc: provides info to obtain the parameter + * img_ptr: pointer to image data + * img_len: image length + * param_ptr: [out] stores a pointer to the parameter + * param_len: [out] stores the length of the parameter + */ +int img_parser_get_auth_param(img_type_t img_type, + const auth_param_type_desc_t *type_desc, + void *img_ptr, unsigned int img_len, + void **param_ptr, unsigned int *param_len) +{ + unsigned int idx; + + assert(type_desc != NULL); + assert(img_ptr != NULL); + assert(img_len != 0); + assert(param_ptr != NULL); + assert(param_len != NULL); + + /* In a raw image we can only get the data itself */ + if (img_type == IMG_RAW) { + assert(type_desc->type == AUTH_PARAM_RAW_DATA); + *param_ptr = img_ptr; + *param_len = img_len; + return IMG_PARSER_OK; + } + + /* Find the index of the required image parser library */ + idx = parser_lib_indices[img_type]; + assert(idx != INVALID_IDX); + + /* Call the function to obtain the parameter */ + return parser_lib_descs[idx].get_auth_param(type_desc, img_ptr, img_len, + param_ptr, param_len); +} diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c new file mode 100644 index 0000000..a12e49c --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* mbed TLS headers */ +#include +#include + +#include +#include +#include MBEDTLS_CONFIG_FILE +#include + +static void cleanup(void) +{ + ERROR("EXIT from BL2\n"); + panic(); +} + +/* + * mbed TLS initialization function + */ +void mbedtls_init(void) +{ + static int ready; + void *heap_addr; + size_t heap_size = 0; + int err; + + if (!ready) { + if (atexit(cleanup)) + panic(); + + err = plat_get_mbedtls_heap(&heap_addr, &heap_size); + + /* Ensure heap setup is proper */ + if (err < 0) { + ERROR("Mbed TLS failed to get a heap\n"); + panic(); + } + assert(heap_size >= TF_MBEDTLS_HEAP_SIZE); + + /* Initialize the mbed TLS heap */ + mbedtls_memory_buffer_alloc_init(heap_addr, heap_size); + +#ifdef MBEDTLS_PLATFORM_SNPRINTF_ALT + mbedtls_platform_set_snprintf(snprintf); +#endif + ready = 1; + } +} + +/* + * The following helper function simply returns the default allocated heap. + * It can be used by platforms for their plat_get_mbedtls_heap() implementation. + */ +int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size) +{ + static unsigned char heap[TF_MBEDTLS_HEAP_SIZE]; + + assert(heap_addr != NULL); + assert(heap_size != NULL); + + *heap_addr = heap; + *heap_size = sizeof(heap); + return 0; +} diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk new file mode 100644 index 0000000..0a4775d --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.mk @@ -0,0 +1,126 @@ +# +# Copyright (c) 2015-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${MBEDTLS_COMMON_MK},1) +MBEDTLS_COMMON_MK := 1 + +# MBEDTLS_DIR must be set to the mbed TLS main directory (it must contain +# the 'include' and 'library' subdirectories). +ifeq (${MBEDTLS_DIR},) + $(error Error: MBEDTLS_DIR not set) +endif + +MBEDTLS_INC = -I${MBEDTLS_DIR}/include + +# Specify mbed TLS configuration file +MBEDTLS_CONFIG_FILE ?= "" +$(eval $(call add_define,MBEDTLS_CONFIG_FILE)) + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_common.c + + +LIBMBEDTLS_SRCS := $(addprefix ${MBEDTLS_DIR}/library/, \ + aes.c \ + asn1parse.c \ + asn1write.c \ + cipher.c \ + cipher_wrap.c \ + memory_buffer_alloc.c \ + oid.c \ + platform.c \ + platform_util.c \ + bignum.c \ + gcm.c \ + md.c \ + pk.c \ + pk_wrap.c \ + pkparse.c \ + pkwrite.c \ + sha256.c \ + sha512.c \ + ecdsa.c \ + ecp_curves.c \ + ecp.c \ + rsa.c \ + rsa_internal.c \ + x509.c \ + x509_crt.c \ + ) + +# The platform may define the variable 'TF_MBEDTLS_KEY_ALG' to select the key +# algorithm to use. If the variable is not defined, select it based on +# algorithm used for key generation `KEY_ALG`. If `KEY_ALG` is not defined, +# then it is set to `rsa`. +ifeq (${TF_MBEDTLS_KEY_ALG},) + ifeq (${KEY_ALG}, ecdsa) + TF_MBEDTLS_KEY_ALG := ecdsa + else + TF_MBEDTLS_KEY_ALG := rsa + endif +endif + +ifeq (${TF_MBEDTLS_KEY_SIZE},) + ifneq ($(findstring rsa,${TF_MBEDTLS_KEY_ALG}),) + ifeq (${KEY_SIZE},) + TF_MBEDTLS_KEY_SIZE := 2048 + else + TF_MBEDTLS_KEY_SIZE := ${KEY_SIZE} + endif + endif +endif + +ifeq (${HASH_ALG}, sha384) + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA384 +else ifeq (${HASH_ALG}, sha512) + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA512 +else + TF_MBEDTLS_HASH_ALG_ID := TF_MBEDTLS_SHA256 +endif + +ifeq (${TF_MBEDTLS_KEY_ALG},ecdsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_ECDSA +else ifeq (${TF_MBEDTLS_KEY_ALG},rsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA +else ifeq (${TF_MBEDTLS_KEY_ALG},rsa+ecdsa) + TF_MBEDTLS_KEY_ALG_ID := TF_MBEDTLS_RSA_AND_ECDSA +else + $(error "TF_MBEDTLS_KEY_ALG=${TF_MBEDTLS_KEY_ALG} not supported on mbed TLS") +endif + +ifeq (${DECRYPTION_SUPPORT}, aes_gcm) + TF_MBEDTLS_USE_AES_GCM := 1 +else + TF_MBEDTLS_USE_AES_GCM := 0 +endif + +ifeq ($(MEASURED_BOOT),1) + ifeq (${TPM_HASH_ALG}, sha256) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA256 + else ifeq (${TPM_HASH_ALG}, sha384) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA384 + else ifeq (${TPM_HASH_ALG}, sha512) + TF_MBEDTLS_TPM_HASH_ALG_ID := TF_MBEDTLS_SHA512 + else + $(error "TPM_HASH_ALG not defined.") + endif +endif + +# Needs to be set to drive mbed TLS configuration correctly +$(eval $(call add_defines,\ + $(sort \ + TF_MBEDTLS_KEY_ALG_ID \ + TF_MBEDTLS_KEY_SIZE \ + TF_MBEDTLS_HASH_ALG_ID \ + TF_MBEDTLS_USE_AES_GCM \ +))) + +ifeq ($(MEASURED_BOOT),1) + $(eval $(call add_define,TF_MBEDTLS_TPM_HASH_ALG_ID)) +endif + +$(eval $(call MAKE_LIB,mbedtls)) + +endif diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c new file mode 100644 index 0000000..0901d04 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c @@ -0,0 +1,388 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* mbed TLS headers */ +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define LIB_NAME "mbed TLS" + +#if MEASURED_BOOT +/* + * CRYPTO_MD_MAX_SIZE value is as per current stronger algorithm available + * so make sure that mbed TLS MD maximum size must be lesser than this. + */ +CASSERT(CRYPTO_MD_MAX_SIZE >= MBEDTLS_MD_MAX_SIZE, + assert_mbedtls_md_size_overflow); + +#endif /* MEASURED_BOOT */ + +/* + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING + * } + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + */ + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + /* Initialize mbed TLS */ + mbedtls_init(); +} + +#if TRUSTED_BOARD_BOOT +/* + * Verify a signature. + * + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + mbedtls_asn1_buf sig_oid, sig_params; + mbedtls_asn1_buf signature; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; + mbedtls_pk_context pk = {0}; + int rc; + void *sig_opts = NULL; + const mbedtls_md_info_t *md_info; + unsigned char *p, *end; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + /* Get pointers to signature OID and parameters */ + p = (unsigned char *)sig_alg; + end = (unsigned char *)(p + sig_alg_len); + rc = mbedtls_asn1_get_alg(&p, end, &sig_oid, &sig_params); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Get the actual signature algorithm (MD + PK) */ + rc = mbedtls_x509_get_sig_alg(&sig_oid, &sig_params, &md_alg, &pk_alg, &sig_opts); + if (rc != 0) { + return CRYPTO_ERR_SIGNATURE; + } + + /* Parse the public key */ + mbedtls_pk_init(&pk); + p = (unsigned char *)pk_ptr; + end = (unsigned char *)(p + pk_len); + rc = mbedtls_pk_parse_subpubkey(&p, end, &pk); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end2; + } + + /* Get the signature (bitstring) */ + p = (unsigned char *)sig_ptr; + end = (unsigned char *)(p + sig_len); + signature.tag = *p; + rc = mbedtls_asn1_get_bitstring_null(&p, end, &signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + signature.p = p; + + /* Calculate the hash of the data */ + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + p = (unsigned char *)data_ptr; + rc = mbedtls_md(md_info, p, data_len, hash); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + + /* Verify the signature */ + rc = mbedtls_pk_verify_ext(pk_alg, sig_opts, &pk, md_alg, hash, + mbedtls_md_get_size(md_info), + signature.p, signature.len); + if (rc != 0) { + rc = CRYPTO_ERR_SIGNATURE; + goto end1; + } + + /* Signature verification success */ + rc = CRYPTO_SUCCESS; + +end1: + mbedtls_pk_free(&pk); +end2: + mbedtls_free(sig_opts); + return rc; +} + +/* + * Match a hash + * + * Digest info is passed in DER format following the ASN.1 structure detailed + * above. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + mbedtls_asn1_buf hash_oid, params; + mbedtls_md_type_t md_alg; + const mbedtls_md_info_t *md_info; + unsigned char *p, *end, *hash; + unsigned char data_hash[MBEDTLS_MD_MAX_SIZE]; + size_t len; + int rc; + + /* Digest info should be an MBEDTLS_ASN1_SEQUENCE */ + p = (unsigned char *)digest_info_ptr; + end = p + digest_info_len; + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Get the hash algorithm */ + rc = mbedtls_asn1_get_alg(&p, end, &hash_oid, ¶ms); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + rc = mbedtls_oid_get_md_alg(&hash_oid, &md_alg); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + md_info = mbedtls_md_info_from_type(md_alg); + if (md_info == NULL) { + return CRYPTO_ERR_HASH; + } + + /* Hash should be octet string type */ + rc = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OCTET_STRING); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Length of hash must match the algorithm's size */ + if (len != mbedtls_md_get_size(md_info)) { + return CRYPTO_ERR_HASH; + } + hash = p; + + /* Calculate the hash of the data */ + p = (unsigned char *)data_ptr; + rc = mbedtls_md(md_info, p, data_len, data_hash); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + /* Compare values */ + rc = memcmp(data_hash, hash, mbedtls_md_get_size(md_info)); + if (rc != 0) { + return CRYPTO_ERR_HASH; + } + + return CRYPTO_SUCCESS; +} +#endif /* TRUSTED_BOARD_BOOT */ + +#if MEASURED_BOOT +/* + * Map a generic crypto message digest algorithm to the corresponding macro used + * by Mbed TLS. + */ +static inline mbedtls_md_type_t md_type(enum crypto_md_algo algo) +{ + switch (algo) { + case CRYPTO_MD_SHA512: + return MBEDTLS_MD_SHA512; + case CRYPTO_MD_SHA384: + return MBEDTLS_MD_SHA384; + case CRYPTO_MD_SHA256: + return MBEDTLS_MD_SHA256; + default: + /* Invalid hash algorithm. */ + return MBEDTLS_MD_NONE; + } +} + +/* + * Calculate a hash + * + * output points to the computed hash + */ +static int calc_hash(enum crypto_md_algo md_algo, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]) +{ + const mbedtls_md_info_t *md_info; + + md_info = mbedtls_md_info_from_type(md_type(md_algo)); + if (md_info == NULL) { + return CRYPTO_ERR_HASH; + } + + /* + * Calculate the hash of the data, it is safe to pass the + * 'output' hash buffer pointer considering its size is always + * bigger than or equal to MBEDTLS_MD_MAX_SIZE. + */ + return mbedtls_md(md_info, data_ptr, data_len, output); +} +#endif /* MEASURED_BOOT */ + +#if TF_MBEDTLS_USE_AES_GCM +/* + * Stack based buffer allocation for decryption operation. It could + * be configured to balance stack usage vs execution speed. + */ +#define DEC_OP_BUF_SIZE 128 + +static int aes_gcm_decrypt(void *data_ptr, size_t len, const void *key, + unsigned int key_len, const void *iv, + unsigned int iv_len, const void *tag, + unsigned int tag_len) +{ + mbedtls_gcm_context ctx; + mbedtls_cipher_id_t cipher = MBEDTLS_CIPHER_ID_AES; + unsigned char buf[DEC_OP_BUF_SIZE]; + unsigned char tag_buf[CRYPTO_MAX_TAG_SIZE]; + unsigned char *pt = data_ptr; + size_t dec_len; + int diff, i, rc; + + mbedtls_gcm_init(&ctx); + + rc = mbedtls_gcm_setkey(&ctx, cipher, key, key_len * 8); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + rc = mbedtls_gcm_starts(&ctx, MBEDTLS_GCM_DECRYPT, iv, iv_len, NULL, 0); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + while (len > 0) { + dec_len = MIN(sizeof(buf), len); + + rc = mbedtls_gcm_update(&ctx, dec_len, pt, buf); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + memcpy(pt, buf, dec_len); + pt += dec_len; + len -= dec_len; + } + + rc = mbedtls_gcm_finish(&ctx, tag_buf, sizeof(tag_buf)); + if (rc != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) + diff |= ((const unsigned char *)tag)[i] ^ tag_buf[i]; + + if (diff != 0) { + rc = CRYPTO_ERR_DECRYPTION; + goto exit_gcm; + } + + /* GCM decryption success */ + rc = CRYPTO_SUCCESS; + +exit_gcm: + mbedtls_gcm_free(&ctx); + return rc; +} + +/* + * Authenticated decryption of an image + */ +static int 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; + + assert((key_flags & ENC_KEY_IS_IDENTIFIER) == 0); + + switch (dec_algo) { + case CRYPTO_GCM_DECRYPT: + rc = aes_gcm_decrypt(data_ptr, len, key, key_len, iv, iv_len, + tag, tag_len); + if (rc != 0) + return rc; + break; + default: + return CRYPTO_ERR_DECRYPTION; + } + + return CRYPTO_SUCCESS; +} +#endif /* TF_MBEDTLS_USE_AES_GCM */ + +/* + * Register crypto library descriptor + */ +#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + auth_decrypt); +#else +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, calc_hash, + NULL); +#endif +#elif TRUSTED_BOARD_BOOT +#if TF_MBEDTLS_USE_AES_GCM +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, + auth_decrypt); +#else +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); +#endif +#elif MEASURED_BOOT +REGISTER_CRYPTO_LIB(LIB_NAME, init, calc_hash); +#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk new file mode 100644 index 0000000..2a9fbbf --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_crypto.c + + diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk new file mode 100644 index 0000000..a0557e2 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509.mk @@ -0,0 +1,9 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include drivers/auth/mbedtls/mbedtls_common.mk + +MBEDTLS_SOURCES += drivers/auth/mbedtls/mbedtls_x509_parser.c diff --git a/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c new file mode 100644 index 0000000..129566b --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c @@ -0,0 +1,478 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * X509 parser based on mbed TLS + * + * This module implements functions to check the integrity of a X509v3 + * certificate ASN.1 structure and extract authentication parameters from the + * extensions field, such as an image hash or a public key. + */ + +#include +#include +#include +#include + +/* mbed TLS headers */ +#include +#include +#include + +#include +#include +#include +#include + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "mbed TLS X509v3" + +/* Temporary variables to speed up the authentication parameters search. These + * variables are assigned once during the integrity check and used any time an + * authentication parameter is requested, so we do not have to parse the image + * again */ +static mbedtls_asn1_buf tbs; +static mbedtls_asn1_buf v3_ext; +static mbedtls_asn1_buf pk; +static mbedtls_asn1_buf sig_alg; +static mbedtls_asn1_buf signature; + +/* + * Clear all static temporary variables. + */ +static void clear_temp_vars(void) +{ +#define ZERO_AND_CLEAN(x) \ + do { \ + zeromem(&x, sizeof(x)); \ + clean_dcache_range((uintptr_t)&x, sizeof(x)); \ + } while (0); + + ZERO_AND_CLEAN(tbs) + ZERO_AND_CLEAN(v3_ext); + ZERO_AND_CLEAN(pk); + ZERO_AND_CLEAN(sig_alg); + ZERO_AND_CLEAN(signature); + +#undef ZERO_AND_CLEAN +} + +/* + * Get X509v3 extension + * + * Global variable 'v3_ext' must point to the extensions region + * in the certificate. No need to check for errors since the image has passed + * the integrity check. + */ +static int get_ext(const char *oid, void **ext, unsigned int *ext_len) +{ + int oid_len; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + unsigned char *p; + const unsigned char *end; + char oid_str[MAX_OID_STR_LEN]; + mbedtls_asn1_buf extn_oid; + int is_critical; + + assert(oid != NULL); + + p = v3_ext.p; + end = v3_ext.p + v3_ext.len; + + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + + while (p < end) { + zeromem(&extn_oid, sizeof(extn_oid)); + is_critical = 0; /* DEFAULT FALSE */ + + mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + end_ext_data = p + len; + + /* Get extension ID */ + extn_oid.tag = *p; + mbedtls_asn1_get_tag(&p, end, &extn_oid.len, MBEDTLS_ASN1_OID); + extn_oid.p = p; + p += extn_oid.len; + + /* Get optional critical */ + mbedtls_asn1_get_bool(&p, end_ext_data, &is_critical); + + /* Extension data */ + mbedtls_asn1_get_tag(&p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING); + end_ext_octet = p + len; + + /* Detect requested extension */ + oid_len = mbedtls_oid_get_numeric_string(oid_str, + MAX_OID_STR_LEN, + &extn_oid); + if (oid_len == MBEDTLS_ERR_OID_BUF_TOO_SMALL) { + return IMG_PARSER_ERR; + } + if ((oid_len == strlen(oid_str)) && !strcmp(oid, oid_str)) { + *ext = (void *)p; + *ext_len = (unsigned int)len; + return IMG_PARSER_OK; + } + + /* Next */ + p = end_ext_octet; + } + + return IMG_PARSER_ERR_NOT_FOUND; +} + + +/* + * Check the integrity of the certificate ASN.1 structure. + * + * Extract the relevant data that will be used later during authentication. + * + * This function doesn't clear the static variables located on the top of this + * file in case of an error. It is only called from check_integrity(), which + * performs the cleanup if necessary. + */ +static int cert_parse(void *img, unsigned int img_len) +{ + int ret, is_critical; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_asn1_buf sig_alg1, sig_alg2; + + p = (unsigned char *)img; + len = img_len; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + if (len > (size_t)(end - p)) { + return IMG_PARSER_ERR_FORMAT; + } + crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + tbs.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + end = p + len; + tbs.len = end - tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 0); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * CertificateSerialNumber ::= INTEGER + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_INTEGER); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * signature AlgorithmIdentifier + */ + sig_alg1.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg1.len = (p + len) - sig_alg1.p; + p += len; + + /* + * issuer Name + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * subject Name + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* + * SubjectPublicKeyInfo + */ + pk.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + pk.len = (p + len) - pk.p; + p += len; + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 1); + if (ret != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 2); + if (ret != 0) { + if (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) { + return IMG_PARSER_ERR_FORMAT; + } + } else { + p += len; + } + + /* + * extensions [3] EXPLICIT Extensions OPTIONAL + */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | + MBEDTLS_ASN1_CONSTRUCTED | 3); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + */ + v3_ext.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + v3_ext.len = (p + len) - v3_ext.p; + + /* + * Check extensions integrity + */ + while (p < end) { + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Get extension ID */ + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_OID); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + + /* Get optional critical */ + ret = mbedtls_asn1_get_bool(&p, end, &is_critical); + if ((ret != 0) && (ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG)) { + return IMG_PARSER_ERR_FORMAT; + } + + /* Data should be octet string type */ + ret = mbedtls_asn1_get_tag(&p, end, &len, + MBEDTLS_ASN1_OCTET_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + p += len; + } + + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier + */ + sig_alg2.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + if ((end - p) < 1) { + return IMG_PARSER_ERR_FORMAT; + } + sig_alg2.len = (p + len) - sig_alg2.p; + p += len; + + /* Compare both signature algorithms */ + if (sig_alg1.len != sig_alg2.len) { + return IMG_PARSER_ERR_FORMAT; + } + if (0 != memcmp(sig_alg1.p, sig_alg2.p, sig_alg1.len)) { + return IMG_PARSER_ERR_FORMAT; + } + memcpy(&sig_alg, &sig_alg1, sizeof(sig_alg)); + + /* + * signatureValue BIT STRING + */ + signature.p = p; + ret = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_BIT_STRING); + if (ret != 0) { + return IMG_PARSER_ERR_FORMAT; + } + signature.len = (p + len) - signature.p; + p += len; + + /* Check certificate length */ + if (p != end) { + return IMG_PARSER_ERR_FORMAT; + } + + return IMG_PARSER_OK; +} + + +/* Exported functions */ + +static void init(void) +{ + mbedtls_init(); +} + +/* + * Wrapper for cert_parse() that clears the static variables used by it in case + * of an error. + */ +static int check_integrity(void *img, unsigned int img_len) +{ + int rc = cert_parse(img, img_len); + + if (rc != IMG_PARSER_OK) + clear_temp_vars(); + + return rc; +} + +/* + * Extract an authentication parameter from an X509v3 certificate + * + * This function returns a pointer to the extracted data and its length. + * Depending on the type of parameter, a pointer to the data stored in the + * certificate may be returned (i.e. an octet string containing a hash). Other + * data may need to be copied and formatted (i.e. integers). In the later case, + * a buffer of the correct type needs to be statically allocated, filled and + * returned. + */ +static int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len) +{ + int rc = IMG_PARSER_OK; + + /* We do not use img because the check_integrity function has already + * extracted the relevant data (v3_ext, pk, sig_alg, etc) */ + + switch (type_desc->type) { + case AUTH_PARAM_RAW_DATA: + /* Data to be signed */ + *param = (void *)tbs.p; + *param_len = (unsigned int)tbs.len; + break; + case AUTH_PARAM_HASH: + case AUTH_PARAM_NV_CTR: + /* All these parameters are included as X509v3 extensions */ + rc = get_ext(type_desc->cookie, param, param_len); + break; + case AUTH_PARAM_PUB_KEY: + if (type_desc->cookie != 0) { + /* Get public key from extension */ + rc = get_ext(type_desc->cookie, param, param_len); + } else { + /* Get the subject public key */ + *param = (void *)pk.p; + *param_len = (unsigned int)pk.len; + } + break; + case AUTH_PARAM_SIG_ALG: + /* Get the certificate signature algorithm */ + *param = (void *)sig_alg.p; + *param_len = (unsigned int)sig_alg.len; + break; + case AUTH_PARAM_SIG: + /* Get the certificate signature */ + *param = (void *)signature.p; + *param_len = (unsigned int)signature.len; + break; + default: + rc = IMG_PARSER_ERR_NOT_FOUND; + break; + } + + return rc; +} + +REGISTER_IMG_PARSER_LIB(IMG_CERT, LIB_NAME, init, \ + check_integrity, get_auth_param); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c new file mode 100644 index 0000000..44f8638 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +static auth_param_type_desc_t scp_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, AP_FWU_CFG_HASH_OID); +static auth_param_type_desc_t ns_bl2u_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FWU_HASH_OID); + +static const auth_img_desc_t bl2_image = { + .img_id = BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_hash + } + } + } +}; + +/* + * FWU auth descriptor. + */ +static const auth_img_desc_t fwu_cert = { + .img_id = FWU_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_bl2u_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &bl2u_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ns_bl2u_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +/* + * SCP_BL2U + */ +static const auth_img_desc_t scp_bl2u_image = { + .img_id = SCP_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_bl2u_hash + } + } + } +}; +/* + * BL2U + */ +static const auth_img_desc_t bl2u_image = { + .img_id = BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &bl2u_hash + } + } + } +}; +/* + * NS_BL2U + */ +static const auth_img_desc_t ns_bl2u_image = { + .img_id = NS_BL2U_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &fwu_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ns_bl2u_hash + } + } + } +}; +/* + * TB_FW_CONFIG + */ +static const auth_img_desc_t tb_fw_config = { + .img_id = TB_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tb_fw_config_hash + } + } + } +}; + +static const auth_img_desc_t fw_config = { + .img_id = FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &fw_config_hash + } + } + } +}; + +/* + * TBBR Chain of trust definition + */ +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [BL2_IMAGE_ID] = &bl2_image, + [HW_CONFIG_ID] = &hw_config, + [TB_FW_CONFIG_ID] = &tb_fw_config, + [FW_CONFIG_ID] = &fw_config, + [FWU_CERT_ID] = &fwu_cert, + [SCP_BL2U_IMAGE_ID] = &scp_bl2u_image, + [BL2U_IMAGE_ID] = &bl2u_image, + [NS_BL2U_IMAGE_ID] = &ns_bl2u_image +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c new file mode 100644 index 0000000..78e38f6 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif +#include + + +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +/* + * Non-Trusted Firmware + */ +static const auth_img_desc_t non_trusted_fw_key_cert = { + .img_id = NON_TRUSTED_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c new file mode 100644 index 0000000..11e2f46 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c @@ -0,0 +1,688 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; +#if defined(SPD_spmd) +static unsigned char sp_pkg_hash_buf[MAX_SP_IDS][HASH_DER_LEN]; +#endif /* SPD_spmd */ + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t scp_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SCP_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t scp_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SCP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); +#if defined(SPD_spmd) +static auth_param_type_desc_t sp_pkg1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG1_HASH_OID); +static auth_param_type_desc_t sp_pkg2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG2_HASH_OID); +static auth_param_type_desc_t sp_pkg3_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG3_HASH_OID); +static auth_param_type_desc_t sp_pkg4_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG4_HASH_OID); +static auth_param_type_desc_t sp_pkg5_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG5_HASH_OID); +static auth_param_type_desc_t sp_pkg6_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG6_HASH_OID); +static auth_param_type_desc_t sp_pkg7_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG7_HASH_OID); +static auth_param_type_desc_t sp_pkg8_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SP_PKG8_HASH_OID); +#endif /* SPD_spmd */ + +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +/* + * SCP Firmware + */ +static const auth_img_desc_t scp_fw_key_cert = { + .img_id = SCP_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t scp_fw_content_cert = { + .img_id = SCP_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &scp_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &scp_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &scp_fw_hash, + .data = { + .ptr = (void *)scp_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &scp_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &scp_fw_hash + } + } + } +}; +/* + * SoC Firmware + */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; +/* + * Trusted OS Firmware + */ +static const auth_img_desc_t trusted_os_fw_key_cert = { + .img_id = TRUSTED_OS_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; +/* + * Non-Trusted Firmware + */ +static const auth_img_desc_t non_trusted_fw_key_cert = { + .img_id = NON_TRUSTED_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; +/* Secure Partitions */ +#if defined(SPD_spmd) +static const auth_img_desc_t sip_sp_content_cert = { + .img_id = SIP_SP_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &sp_pkg1_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[0], + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &sp_pkg2_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[1], + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &sp_pkg3_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[2], + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &sp_pkg4_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[3], + .len = (unsigned int)HASH_DER_LEN + } + }, + [4] = { + .type_desc = &sp_pkg5_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[4], + .len = (unsigned int)HASH_DER_LEN + } + }, + [5] = { + .type_desc = &sp_pkg6_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[5], + .len = (unsigned int)HASH_DER_LEN + } + }, + [6] = { + .type_desc = &sp_pkg7_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[6], + .len = (unsigned int)HASH_DER_LEN + } + }, + [7] = { + .type_desc = &sp_pkg8_hash, + .data = { + .ptr = (void *)sp_pkg_hash_buf[7], + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +DEFINE_SIP_SP_PKG(1); +DEFINE_SIP_SP_PKG(2); +DEFINE_SIP_SP_PKG(3); +DEFINE_SIP_SP_PKG(4); +DEFINE_SIP_SP_PKG(5); +DEFINE_SIP_SP_PKG(6); +DEFINE_SIP_SP_PKG(7); +DEFINE_SIP_SP_PKG(8); +#endif /* SPD_spmd */ + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_BOOT_FW_CERT_ID] = &trusted_boot_fw_cert, + [HW_CONFIG_ID] = &hw_config, + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SCP_FW_KEY_CERT_ID] = &scp_fw_key_cert, + [SCP_FW_CONTENT_CERT_ID] = &scp_fw_content_cert, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert, + [BL32_IMAGE_ID] = &bl32_image, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#if defined(SPD_spmd) + [SIP_SP_CONTENT_CERT_ID] = &sip_sp_content_cert, + [SP_PKG1_ID] = &sp_pkg1, + [SP_PKG2_ID] = &sp_pkg2, + [SP_PKG3_ID] = &sp_pkg3, + [SP_PKG4_ID] = &sp_pkg4, + [SP_PKG5_ID] = &sp_pkg5, + [SP_PKG6_ID] = &sp_pkg6, + [SP_PKG7_ID] = &sp_pkg7, + [SP_PKG8_ID] = &sp_pkg8, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c new file mode 100644 index 0000000..0983d42 --- /dev/null +++ b/arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include MBEDTLS_CONFIG_FILE + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +/* + * The platform must allocate buffers to store the authentication parameters + * extracted from the certificates. In this case, because of the way the CoT is + * established, we can reuse some of the buffers on different stages + */ + +static unsigned char fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tb_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char hw_config_hash_buf[HASH_DER_LEN]; +unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +/* + * common Parameter type descriptors across BL1 and BL2 + */ +auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); +auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +/* common hash used across BL1 and BL2 */ +auth_param_type_desc_t tb_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_HASH_OID); +auth_param_type_desc_t tb_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_BOOT_FW_CONFIG_HASH_OID); +auth_param_type_desc_t fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, FW_CONFIG_HASH_OID); +static auth_param_type_desc_t hw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, HW_CONFIG_HASH_OID); + +/* trusted_boot_fw_cert */ +const auth_img_desc_t trusted_boot_fw_cert = { + .img_id = TRUSTED_BOOT_FW_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tb_fw_hash, + .data = { + .ptr = (void *)tb_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tb_fw_config_hash, + .data = { + .ptr = (void *)tb_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &hw_config_hash, + .data = { + .ptr = (void *)hw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &fw_config_hash, + .data = { + .ptr = (void *)fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; + +/* HW Config */ +const auth_img_desc_t hw_config = { + .img_id = HW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_boot_fw_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &hw_config_hash + } + } + } +}; diff --git a/arm-trusted-firmware/drivers/brcm/chimp.c b/arm-trusted-firmware/drivers/brcm/chimp.c new file mode 100644 index 0000000..81767bb --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/chimp.c @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#define CHIMP_DEFAULT_STARTUP_ADDR 0xb4300000 + +/* ChiMP's view of APE scratchpad memory for fastboot */ +#define CHIMP_FASTBOOT_ADDR 0x61000000 + +#define CHIMP_PREPARE_ACCESS_WINDOW(addr) \ + (\ + mmio_write_32(\ + NIC400_NITRO_CHIMP_S_IDM_IO_CONTROL_DIRECT, \ + addr & 0xffc00000)\ + ) +#define CHIMP_INDIRECT_TGT_ADDR(addr) \ + (CHIMP_INDIRECT_BASE + (addr & CHIMP_INDIRECT_ADDR_MASK)) + +#define CHIMP_CTRL_ADDR(x) (CHIMP_REG_CTRL_BASE + x) + +/* For non-PAXC builds */ +#ifndef CHIMP_FB1_ENTRY +#define CHIMP_FB1_ENTRY 0 +#endif + +#define CHIMP_DBG VERBOSE + +void bcm_chimp_write(uintptr_t addr, uint32_t value) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_write_32(CHIMP_INDIRECT_TGT_ADDR(addr), value); +} + +uint32_t bcm_chimp_read(uintptr_t addr) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + return mmio_read_32(CHIMP_INDIRECT_TGT_ADDR(addr)); +} + +void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_clrbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits); +} + +void bcm_chimp_setbits(uintptr_t addr, uint32_t bits) +{ + CHIMP_PREPARE_ACCESS_WINDOW(addr); + mmio_setbits_32(CHIMP_INDIRECT_TGT_ADDR(addr), bits); +} + +int bcm_chimp_is_nic_mode(void) +{ + uint32_t val; + + /* Check if ChiMP straps are set */ + val = mmio_read_32(CDRU_CHIP_STRAP_DATA_LSW); + val &= CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK; + + return val == CDRU_CHIP_STRAP_DATA_LSW__NIC_MODE_MASK; +} + +void bcm_chimp_fru_prog_done(bool is_done) +{ + uint32_t val; + + val = is_done ? (1 << CHIMP_FRU_PROG_DONE_BIT) : 0; + bcm_chimp_setbits(CHIMP_REG_ECO_RESERVED, val); +} + +int bcm_chimp_handshake_done(void) +{ + uint32_t value; + + value = bcm_chimp_read(CHIMP_REG_ECO_RESERVED); + value &= (1 << CHIMP_FLASH_ACCESS_DONE_BIT); + + return value != 0; +} + +int bcm_chimp_wait_handshake(void) +{ + uint32_t timeout = CHIMP_HANDSHAKE_TIMEOUT_MS; + uint32_t status; + + INFO("Waiting for ChiMP handshake...\n"); + do { + if (bcm_chimp_handshake_done()) + break; + /* No need to wait if ChiMP reported an error */ + status = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_STAT_REG); + if (status & CHIMP_ERROR_MASK) { + ERROR("ChiMP error 0x%x. Wait aborted\n", status); + break; + } + mdelay(1); + } while (--timeout); + + if (!bcm_chimp_handshake_done()) { + if (timeout == 0) { + WARN("Timeout waiting for ChiMP handshake\n"); + } + } else { + INFO("Got handshake from ChiMP!\n"); + } + + return bcm_chimp_handshake_done(); +} + +uint32_t bcm_chimp_read_ctrl(uint32_t offset) +{ + return bcm_chimp_read(CHIMP_CTRL_ADDR(offset)); +} + +static int bcm_chimp_nitro_reset(void) +{ + uint32_t timeout; + + /* Perform tasks done by M0 in NIC mode */ + CHIMP_DBG("Taking Nitro out of reset\n"); + mmio_setbits_32(CDRU_MISC_RESET_CONTROL, + /* MHB_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_MHB_RESET_N_R) | + /* PCI_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_PCIE_RESET_N_R) | + /* PM_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_PM_RESET_N_R) | + /* NIC_RESET_N */ + (1 << CDRU_MISC_RESET_CONTROL__CDRU_NITRO_RESET_N_R) + ); + + /* Wait until Nitro is out of reset */ + timeout = NIC_RESET_RELEASE_TIMEOUT_US; + do { + uint32_t value; + + value = bcm_chimp_read_ctrl(CHIMP_REG_CTRL_BPE_MODE_REG); + if ((value & CHIMP_BPE_MODE_ID_MASK) == + CHIMP_BPE_MODE_ID_PATTERN) + break; + udelay(1); + } while (--timeout); + + if (timeout == 0) { + ERROR("NIC reset release timed out\n"); + return -1; + } + + return 0; +} + +static void bcm_nitro_secure_mode_enable(void) +{ + mmio_setbits_32(CDRU_NITRO_CONTROL, + (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_MODE_R) | + (1 << CDRU_NITRO_CONTROL__CDRU_NITRO_SEC_OVERRIDE_R)); + mmio_write_32(NITRO_TZPC_TZPCDECPROT0clr, + /* NITRO_TZPC */ + 1 << NITRO_TZPC_TZPCDECPROT0clr__DECPROT0_chimp_m_clr_R); +} + +static int bcm_chimp_reset_and_initial_setup(void) +{ + + int err; + uint32_t handshake_reg; + + err = bcm_chimp_nitro_reset(); + if (err) + return err; + + /* Enable Nitro secure mode */ + bcm_nitro_secure_mode_enable(); + + /* Force ChiMP back into reset */ + bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R); + + handshake_reg = (1 << SR_IN_SMARTNIC_MODE_BIT); + + /* Get OTP secure Chimp boot status */ + if (mmio_read_32(CRMU_OTP_STATUS) & (1 << CRMU_OTP_STATUS_BIT)) + handshake_reg |= (1 << SR_CHIMP_SECURE_BOOT_BIT); + + bcm_chimp_write(CHIMP_REG_ECO_RESERVED, handshake_reg); + + CHIMP_DBG("ChiMP reset and initial handshake parameters set\n"); + + return 0; +} + +static void bcm_nitro_chimp_release_reset(void) +{ + bcm_chimp_clrbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + 1 << CHIMP_REG_CHIMP_REG_CTRL_BPE_MODE_REG__cm3_rst_R); + + CHIMP_DBG("Nitro Reset Released\n"); +} + +static void bcm_chimp_set_fastboot(int mode) +{ + uint32_t fb_entry; + + /* 1. Enable fastboot */ + bcm_chimp_setbits(CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_BPE_MODE_REG), + (1 << CHIMP_FAST_BOOT_MODE_BIT)); + fb_entry = CHIMP_FASTBOOT_ADDR | mode; + if (mode == CHIMP_FASTBOOT_JUMP_IN_PLACE) + fb_entry = CHIMP_FB1_ENTRY; + /* 2. Write startup address and mode */ + INFO("Setting fastboot type %d entry to 0x%x\n", mode, fb_entry); + bcm_chimp_write( + CHIMP_CTRL_ADDR(CHIMP_REG_CTRL_FSTBOOT_PTR_REG), + fb_entry); +} + +#ifndef CHIMPFW_USE_SIDELOAD +static void bcm_chimp_load_fw_from_spi(uintptr_t spi_addr, size_t size) +{ + uintptr_t ape_scpad; + uintptr_t dest; + size_t bytes_left; + + ape_scpad = CHIMP_REG_CHIMP_APE_SCPAD; + dest = CHIMP_INDIRECT_TGT_ADDR(CHIMP_REG_CHIMP_APE_SCPAD); + bytes_left = size; + + while (bytes_left) { + uint32_t delta; + + delta = bytes_left > CHIMP_WINDOW_SIZE ? + bytes_left - CHIMP_WINDOW_SIZE : bytes_left; + CHIMP_PREPARE_ACCESS_WINDOW(ape_scpad); + INFO("Transferring %d byte(s) from 0x%lx to 0x%lx\n", + delta, spi_addr, dest); + /* + * This single memcpy call takes significant amount of time + * on Palladium. Be patient + */ + memcpy((void *)dest, (void *)spi_addr, delta); + bytes_left -= delta; + INFO("Transferred %d byte(s) from 0x%lx to 0x%lx (%lu%%)\n", + delta, spi_addr, dest, + ((size - bytes_left) * 100)/size); + spi_addr += delta; + dest += delta; + ape_scpad += delta; + } +} + +static int bcm_chimp_find_fw_in_spi(uintptr_t *addr, size_t *size) +{ + int i; + bnxnvm_master_block_header_t *master_block_hdr; + bnxnvm_directory_block_header_t *dir_block_hdr; + bnxnvm_directory_entry_t *dir_entry; + int found; + + found = 0; + + /* Read the master block */ + master_block_hdr = + (bnxnvm_master_block_header_t *)(uintptr_t)QSPI_BASE_ADDR; + if (master_block_hdr->sig != BNXNVM_MASTER_BLOCK_SIG) { + WARN("Invalid masterblock 0x%x (expected 0x%x)\n", + master_block_hdr->sig, + BNXNVM_MASTER_BLOCK_SIG); + return -NV_NOT_NVRAM; + } + if ((master_block_hdr->block_size > NV_MAX_BLOCK_SIZE) || + (master_block_hdr->directory_offset >= + master_block_hdr->nvram_size)) { + WARN("Invalid masterblock block size 0x%x or directory offset 0x%x\n", + master_block_hdr->block_size, + master_block_hdr->directory_offset); + return -NV_BAD_MB; + } + + /* Skip to the Directory block start */ + dir_block_hdr = + (bnxnvm_directory_block_header_t *) + ((uintptr_t)QSPI_BASE_ADDR + + master_block_hdr->directory_offset); + if (dir_block_hdr->sig != BNXNVM_DIRECTORY_BLOCK_SIG) { + WARN("Invalid directory header 0x%x (expected 0x%x)\n", + dir_block_hdr->sig, + BNXNVM_DIRECTORY_BLOCK_SIG); + return -NV_BAD_DIR_HEADER; + } + + /* Locate the firmware */ + for (i = 0; i < dir_block_hdr->entries; i++) { + *addr = ((uintptr_t)dir_block_hdr + dir_block_hdr->length + + i * dir_block_hdr->entry_length); + dir_entry = (bnxnvm_directory_entry_t *)(*addr); + if ((dir_entry->type == BNX_DIR_TYPE_BOOTCODE) || + (dir_entry->type == BNX_DIR_TYPE_BOOTCODE_2)) { + found = 1; + break; + } + } + + if (!found) + return -NV_FW_NOT_FOUND; + + *addr = QSPI_BASE_ADDR + dir_entry->item_location; + *size = dir_entry->data_length; + + INFO("Found chimp firmware at 0x%lx, size %lu byte(s)\n", + *addr, *size); + + return NV_OK; +} +#endif + +int bcm_chimp_initiate_fastboot(int fastboot_type) +{ + int err; + + if ((fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) && + (fastboot_type <= CHIMP_FASTBOOT_JUMP_DECOMPRESS)) { + CHIMP_DBG("Initiating ChiMP fastboot type %d\n", fastboot_type); + } + + /* + * If we are here, M0 did not setup Nitro because NIC mode + * strap was not present + */ + err = bcm_chimp_reset_and_initial_setup(); + if (err) + return err; + + if (fastboot_type > CHIMP_FASTBOOT_JUMP_DECOMPRESS) { + WARN("ChiMP setup deferred\n"); + return -1; + } + + if (fastboot_type != CHIMP_FASTBOOT_NITRO_RESET) { + + if ((fastboot_type == CHIMP_FASTBOOT_JUMP_IN_PLACE) && + (CHIMP_FB1_ENTRY == 0)) { + ERROR("Missing ESAL entry point for fastboot type 1.\n" + "Fastboot failed\n"); + return -1; + } + + /* + * TODO: We need to think of the way to load the ChiMP fw. + * This could be SPI, NAND, etc. + * For now we temporarily stick to the SPI load unless + * CHIMPFW_USE_SIDELOAD is defined. Note that for the SPI NVRAM + * image we need to parse directory and get the image. + * When we load image from other media there is no need to + * parse because fw image can be directly placed into the APE's + * scratchpad. + * For sideload method we simply reset the ChiMP, set bpe_reg + * to do fastboot with the type we define, and release from + * reset so that ROM loader would initiate fastboot immediately + */ +#ifndef CHIMPFW_USE_SIDELOAD + { + uintptr_t spi_addr; + size_t size; + + err = bcm_chimp_find_fw_in_spi(&spi_addr, &size); + if (!err) { + INFO("Loading ChiMP firmware, addr 0x%lx, size %lu byte(s)\n", + spi_addr, size); + bcm_chimp_load_fw_from_spi(spi_addr, size); + } else { + ERROR("Error %d ChiMP firmware not in NVRAM directory!\n", + err); + } + } +#else + INFO("Skip ChiMP QSPI fastboot type %d due to sideload requested\n", + fastboot_type); +#endif + if (!err) { + INFO("Instruct ChiMP to fastboot\n"); + bcm_chimp_set_fastboot(fastboot_type); + INFO("Fastboot mode set\n"); + } + } + + bcm_nitro_chimp_release_reset(); + + return err; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c new file mode 100644 index 0000000..34d761c --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c @@ -0,0 +1,1017 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +extern void emmc_soft_reset(void); + +#define SD_VDD_WINDOW_1_6_TO_1_7 0x00000010 // 1.6 V to 1.7 Volts +#define SD_VDD_WINDOW_1_7_TO_1_8 0x00000020 // 1.7 V to 1.8 Volts +#define SD_VDD_WINDOW_1_8_TO_1_9 0x00000040 // 1.8 V to 1.9 Volts +#define SD_VDD_WINDOW_1_9_TO_2_0 0x00000080 // 1.9 V to 2.0 Volts +#define SD_VDD_WINDOW_2_0_TO_2_1 0x00000100 // 2.0 V to 2.1 Volts +#define SD_VDD_WINDOW_2_1_TO_2_2 0x00000200 // 2.1 V to 2.2 Volts +#define SD_VDD_WINDOW_2_2_TO_2_3 0x00000400 // 2.2 V to 2.3 Volts +#define SD_VDD_WINDOW_2_3_TO_2_4 0x00000800 // 2.3 V to 2.4 Volts +#define SD_VDD_WINDOW_2_4_TO_2_5 0x00001000 // 2.4 V to 2.5 Volts +#define SD_VDD_WINDOW_2_5_TO_2_6 0x00002000 // 2.5 V to 2.6 Volts +#define SD_VDD_WINDOW_2_6_TO_2_7 0x00004000 // 2.6 V to 2.7 Volts +#define SD_VDD_WINDOW_2_7_TO_2_8 0x00008000 // 2.7 V to 2.8 Volts +#define SD_VDD_WINDOW_2_8_TO_2_9 0x00010000 // 2.8 V to 2.9 Volts +#define SD_VDD_WINDOW_2_9_TO_3_0 0x00020000 // 2.9 V to 3.0 Volts +#define SD_VDD_WINDOW_3_0_TO_3_1 0x00040000 // 3.0 V to 3.1 Volts +#define SD_VDD_WINDOW_3_1_TO_3_2 0x00080000 // 3.1 V to 3.2 Volts +#define SD_VDD_WINDOW_3_2_TO_3_3 0x00100000 // 3.2 V to 3.3 Volts +#define SD_VDD_WINDOW_3_3_TO_3_4 0x00200000 // 3.3 V to 3.4 Volts +#define SD_VDD_WINDOW_3_4_TO_3_5 0x00400000 // 3.4 V to 3.5 Volts +#define SD_VDD_WINDOW_3_5_TO_3_6 0x00800000 // 3.5 V to 3.6 Volts + +#define SD_VDD_WINDOW_1_6_TO_2_6 (SD_VDD_WINDOW_1_6_TO_1_7 | \ + SD_VDD_WINDOW_1_7_TO_1_8 | \ + SD_VDD_WINDOW_1_8_TO_1_9 | \ + SD_VDD_WINDOW_1_9_TO_2_0 | \ + SD_VDD_WINDOW_2_0_TO_2_1 | \ + SD_VDD_WINDOW_2_1_TO_2_2 | \ + SD_VDD_WINDOW_2_2_TO_2_3 | \ + SD_VDD_WINDOW_2_3_TO_2_4 | \ + SD_VDD_WINDOW_2_4_TO_2_5 | \ + SD_VDD_WINDOW_2_5_TO_2_6) + +#define SD_VDD_WINDOW_2_6_TO_3_2 (SD_VDD_WINDOW_2_6_TO_2_7 | \ + SD_VDD_WINDOW_2_7_TO_2_8 | \ + SD_VDD_WINDOW_2_8_TO_2_9 | \ + SD_VDD_WINDOW_2_9_TO_3_0 | \ + SD_VDD_WINDOW_3_0_TO_3_1 | \ + SD_VDD_WINDOW_3_1_TO_3_2) + +#define SD_VDD_WINDOW_3_2_TO_3_6 (SD_VDD_WINDOW_3_2_TO_3_3 | \ + SD_VDD_WINDOW_3_3_TO_3_4 | \ + SD_VDD_WINDOW_3_4_TO_3_5 | \ + SD_VDD_WINDOW_3_5_TO_3_6) + + +static int32_t chal_sd_set_power(struct sd_dev *handle, + uint32_t voltage, uint32_t state); + +static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary); + +static int32_t chal_sd_setup_handler(struct sd_dev *handle, + uint32_t sdBbase, uint32_t hostBase); + +/* + * Configure host controller pwr settings, + * to match voltage requirements by SD Card + */ +static int32_t chal_sd_set_power(struct sd_dev *handle, + uint32_t voltage, uint32_t state) +{ + int32_t rc, rval = SD_FAIL; + uint32_t time = 0; + + if (handle == NULL) + return SD_INVALID_HANDLE; + + mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + (SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK | + SD4_EMMC_TOP_CTRL_SDPWR_MASK), + (voltage << 9)); + + /* + * Long delay is required here in emulation. Without this, the initial + * commands sent to the eMMC card timeout. We don't know if this + * delay is necessary with silicon, leaving in for safety. + * It is observed that 403ms on emulation system and as per the clock + * calculations it is expected to complete with in 1ms on chip + */ + do { + rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET); + + if ((rc & SD4_EMMC_TOP_INTR_CRDINS_MASK) == + SD4_EMMC_TOP_INTR_CRDINS_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CARD_DETECT_TIMEOUT_MS); + + if (time >= EMMC_CARD_DETECT_TIMEOUT_MS) { + ERROR("EMMC: Card insert event detection timeout\n"); + return rval; + } + + VERBOSE("EMMC: Card detection delay: %dms\n", time); + + if (state) + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_SDPWR_MASK); + + /* dummy write & ack to verify if the sdio is ready to send commads */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, 0); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, 0); + + /* + * 63ms observed on emulation system, As per clock calculations + * it will complete < 1ms on chip. + */ + time = 0; + do { + rc = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET); + + if (rc & SD4_EMMC_TOP_INTR_ERRIRQ_MASK) + break; + + if ((rc & SD4_EMMC_TOP_INTR_CMDDONE_MASK) == + SD4_EMMC_TOP_INTR_CMDDONE_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CMD_TIMEOUT_MS); + + if (time >= EMMC_CMD_TIMEOUT_MS) { + WARN("%s %d Initial dummy command timeout is happened\n", + __func__, __LINE__); + return rval; + } + + VERBOSE("EMMC: Dummy Command delay: %dms\n", time); + + return SD_OK; +} + +/* + * Configure DMA Boundaries + */ +static void chal_sd_set_dma_boundary(struct sd_dev *handle, uint32_t boundary) +{ + if (handle == NULL) + return; + + mmio_clrsetbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BLOCK_OFFSET, + SD4_EMMC_TOP_BLOCK_HSBS_MASK, boundary); +} + +static int32_t chal_sd_setup_handler(struct sd_dev *handle, uint32_t sdBase, + uint32_t hostBase) +{ + if (handle == NULL) + return SD_INVALID_HANDLE; + + handle->ctrl.sdRegBaseAddr = sdBase; + handle->ctrl.hostRegBaseAddr = hostBase; + handle->ctrl.present = 0; + handle->ctrl.rca = 0; + handle->ctrl.blkGapEnable = 0; + handle->ctrl.cmdStatus = 0; + + return SD_OK; +} + +/* + * Initialize SD Host controller + */ +int32_t chal_sd_init(CHAL_HANDLE *sd_handle) +{ + uint32_t cap_val_l = 0; + uint32_t ctl_val, voltage; + uint32_t timeout_val; + struct sd_dev *handle; + uint32_t reg_val; + int32_t rval = SD_FAIL; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + /* + * Set SDIO Host Controller capabilities register + */ + EMMC_TRACE("Set Host Controller Capabilities register\n"); + + reg_val = 0; + reg_val |= (1 << ICFG_SDIO0_CAP0__SLOT_TYPE_R); + reg_val |= (0 << ICFG_SDIO0_CAP0__INT_MODE_R); + reg_val |= (0 << ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__SUSPEND_RESUME_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__SDMA_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__HIGH_SPEED_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__ADMA2_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R); + reg_val |= (2 << ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R); + reg_val |= (0xd0 << ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R); + reg_val |= (1 << ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R); + reg_val |= (0x30 << ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R); + + mmio_write_32(ICFG_SDIO0_CAP0, reg_val); + + reg_val = 0; + reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SPI_MODE_R); + reg_val |= (0 << ICFG_SDIO0_CAP1__CLK_MULT_R); + reg_val |= (0 << ICFG_SDIO0_CAP1__RETUNING_MODE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__TUNE_SDR50_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__TIME_RETUNE_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_D_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_C_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DRIVER_A_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__DDR50_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SDR104_R); + reg_val |= (1 << ICFG_SDIO0_CAP1__SDR50_R); + + mmio_write_32(ICFG_SDIO0_CAP1, reg_val); + + /* Reset the SDIO controller */ + chal_sd_stop(); + + /* Turn on SD clock */ + chal_sd_set_clock(sd_handle, + chal_sd_freq_2_div_ctrl_setting(INIT_CLK_FREQ), 1); + + /* program data time out value to the max */ + timeout_val = SD_HOST_CORE_TIMEOUT; + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + ctl_val |= ((timeout_val & 0xf) << SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + ctl_val); + + /* enable all interrupt status */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, + 0); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, + 0); + + SD_US_DELAY(100); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN1_OFFSET, + SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_INTREN2_OFFSET, + SD_NOR_INTERRUPTS | SD_ERR_INTERRUPTS); + + /* Select SD bus voltage */ + cap_val_l = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CAPABILITIES1_OFFSET); + handle->cfg.voltage = 0; + voltage = 0x7; + + if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V33_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_3_3_TO_3_4; + voltage = 0x7; + } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V3_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_3_0_TO_3_1; + voltage = 0x6; + } else if (cap_val_l & SD4_EMMC_TOP_CAPABILITIES1_V18_MASK) { + handle->cfg.voltage |= SD_VDD_WINDOW_1_8_TO_1_9; + voltage = 0x5; + } + + rval = chal_sd_set_power(handle, voltage, SD4_EMMC_TOP_CTRL_SDPWR_MASK); + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_HCVERSIRQ_OFFSET); + handle->ctrl.version = ((ctl_val >> 16) & 0xFF); + + return rval; +} + +void chal_sd_set_speed(CHAL_HANDLE *sd_handle, uint32_t speed) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *) sd_handle; + + if (speed) { + EMMC_TRACE("enable HighSpeed\n"); + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_HSEN_MASK); + } else { + EMMC_TRACE("disable HighSpeed\n"); + mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, + SD4_EMMC_TOP_CTRL_HSEN_MASK); + } +} + +int32_t chal_sd_stop(void) +{ + uintptr_t idm_rst_ctrl_addr = EMMC_IDM_RESET_CTRL_ADDR; + + /* Configure IO pins */ + emmc_soft_reset(); + + /* Reset the SDIO controller */ + mmio_write_32(idm_rst_ctrl_addr, 1); + SD_US_DELAY(100); + mmio_write_32(idm_rst_ctrl_addr, 0); + SD_US_DELAY(100); + + return SD_OK; +} + +/* + * Check if host supports specified capability + * returns -ve val on error, 0 if capability not supported else 1. + */ +int32_t chal_sd_check_cap(CHAL_HANDLE *sd_handle, uint32_t caps) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (caps & mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CAPABILITIES1_OFFSET)) + return 1; + else + return 0; +} + +int32_t chal_sd_start(CHAL_HANDLE *sd_handle, + uint32_t mode, uint32_t sd_base, uint32_t host_base) +{ + + struct sd_dev *handle; + int32_t rval = SD_FAIL; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + handle->cfg.mode = SD_PIO_MODE; /* set to PIO mode first for init */ + handle->cfg.dma = SD_DMA_OFF; + + chal_sd_setup_handler(handle, sd_base, host_base); + + /* init and start hw */ + rval = chal_sd_init(sd_handle); + if (rval != SD_OK) + return rval; + + chal_sd_clear_pending_irq(sd_handle); + + handle->ctrl.eventList = 0; + handle->cfg.mode = mode; + + return SD_OK; +} + +/* + * Function to check 8bits of err generated from auto CMD12 + */ +int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_ERRSTAT_OFFSET) & 0xFF); +} + +/* + * Read present state register + */ +uint32_t chal_sd_get_present_status(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_OFFSET); +} + +/* + * Set SD bus width + */ +int32_t chal_sd_config_bus_width(CHAL_HANDLE *sd_handle, int32_t width) +{ + uint32_t ctl_val; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + ctl_val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET); + + switch (width) { +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + case SD_BUS_DATA_WIDTH_8BIT: + ctl_val &= ~SD_BUS_DATA_WIDTH_4BIT; + ctl_val |= SD_BUS_DATA_WIDTH_8BIT; + break; +#endif + case SD_BUS_DATA_WIDTH_4BIT: + ctl_val &= ~SD_BUS_DATA_WIDTH_8BIT; + ctl_val |= SD_BUS_DATA_WIDTH_4BIT; + break; + case SD_BUS_DATA_WIDTH_1BIT: + ctl_val &= ~(SD_BUS_DATA_WIDTH_4BIT | SD_BUS_DATA_WIDTH_8BIT); + break; + default: + return SD_INV_DATA_WIDTH; + }; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL_OFFSET, + ctl_val); + + return SD_OK; +} + +/* + * Function to enable or disable DMA control. + */ +int32_t chal_sd_set_dma(CHAL_HANDLE *sd_handle, uint32_t mode) +{ + uint32_t val; + struct sd_dev *handle; + int32_t rc; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + if (mode) { + rc = chal_sd_check_cap(sd_handle, + SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK | + SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK); + if (rc < 0) + return rc; + + if (rc) { + + handle->cfg.dma = mode; + val = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET); + val &= ~(SD4_EMMC_TOP_CTRL_DMASEL_MASK); + val |= handle->cfg.dma - 1; + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL_OFFSET, val); + return SD_OK; + } + } + handle->cfg.dma = 0; + + return SD_FAIL; +} + +/* + * Get current DMA address. + * Called only when there is no data transaction activity. + */ +uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (handle->cfg.dma == SD_DMA_OFF) + return 0; + + return (uintptr_t)mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_SYSADDR_OFFSET); +} + +int32_t chal_sd_send_cmd(CHAL_HANDLE *sd_handle, uint32_t cmd_idx, + uint32_t argument, uint32_t options) +{ + uint32_t cmd_mode_reg = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + EMMC_TRACE("%s %d cmd:%d argReg:%x options:%x\n", + __func__, __LINE__, cmd_idx, argument, options); + + /* Configure the value for command and mode registers */ + cmd_mode_reg = (cmd_idx << 24) | options; + + /* + * 1. Write block size reg & block count reg, + * this is done in the tx or rx setup + */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_BLOCK_OFFSET, + handle->ctrl.blkReg); + + /* 2. Write argument reg */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_ARG_OFFSET, + argument); + handle->ctrl.argReg = argument; + + /* + * 3. Write transfer mode reg & command reg, check the DMA bit which is + * set before this function call if it is selected. + */ + if (cmd_idx == 24 || cmd_idx == 25 || cmd_idx == 18 || cmd_idx == 17 || + cmd_idx == 42 || cmd_idx == 51 || cmd_idx == 53) + cmd_mode_reg |= ((handle->cfg.dma) ? 1 : 0); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CMD_OFFSET, + cmd_mode_reg); + + handle->ctrl.cmdIndex = cmd_idx; + + return SD_OK; +} + +int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sd_handle, uintptr_t address) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (handle->cfg.dma == SD_DMA_OFF) + return SD_FAIL; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, + address); + return SD_OK; +} + +uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq) +{ + /* + * Divider control setting represents 1/2 of the actual divider value. + * + * DesiredFreq = BaseClockFreq / (2 * div_ctrl_setting) + * + * ==> div_ctrl_setting = BaseClockFreq / (2 * DesiredFreq) + */ + uint32_t div_ctrl_setting; + uint32_t actual_freq; + + assert(desired_freq != 0); + + /* Special case, 0 = divider of 1. */ + if (desired_freq >= BASE_CLK_FREQ) + return 0; + + /* Normal case, desired_freq < BASE_CLK_FREQ */ + div_ctrl_setting = BASE_CLK_FREQ / (2 * desired_freq); + + actual_freq = BASE_CLK_FREQ / (2 * div_ctrl_setting); + + if (actual_freq > desired_freq) { + /* + * Division does not result in exact freqency match. + * Make sure resulting frequency does not exceed requested freq. + */ + div_ctrl_setting++; + } + + return div_ctrl_setting; +} + +int32_t chal_sd_set_clock(CHAL_HANDLE *sd_handle, uint32_t div_ctrl_setting, + uint32_t on) +{ + uint32_t value; + struct sd_dev *handle; + uint32_t time; + uint32_t clk_sel_high_byte = 0xFF & (div_ctrl_setting >> 8); + uint32_t clk_sel_low_byte = 0xFF & div_ctrl_setting; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + EMMC_TRACE("set_clock(div_ctrl_setting=%d,on=%d)\n", + div_ctrl_setting, on); + + handle = (struct sd_dev *) sd_handle; + + /* Read control register content. */ + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + /* Disable Clock */ + value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK); + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + /* Clear bits of interest. */ + value &= ~(SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK | + SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK); + + /* Set bits of interest to new value. */ + value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK & + (clk_sel_low_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT)); + value |= (SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK & + (clk_sel_high_byte << SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT)); + value |= SD4_EMMC_TOP_CTRL1_ICLKEN_MASK; + + /* Write updated value back to control register. */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + time = 0; + do { + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + if ((value & SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) == + SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK) + break; + + mdelay(1); + } while (time++ < EMMC_CLOCK_SETTING_TIMEOUT_MS); + + if (time >= EMMC_CLOCK_SETTING_TIMEOUT_MS) + WARN("%s %d clock settings timeout happenedi (%dms)\n", + __func__, __LINE__, time); + + VERBOSE("EMMC: clock settings delay: %dms\n", time); + + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + + if (on) + value |= SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK; + + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + value); + + return SD_OK; +} + +/* + * function to setup DMA buffer and data length, calculates block + * size and the number of blocks to be transferred and return + * the DMA buffer address. + */ +int32_t chal_sd_setup_xfer(CHAL_HANDLE *sd_handle, + uint8_t *data, uint32_t length, int32_t dir) +{ + uint32_t blocks = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + if (length <= handle->cfg.blockSize) { + handle->ctrl.blkReg = length | handle->cfg.dmaBoundary; + } else { + blocks = length / handle->cfg.blockSize; + handle->ctrl.blkReg = (blocks << 16) | handle->cfg.blockSize | + handle->cfg.dmaBoundary; + } + + if (handle->cfg.dma != SD_DMA_OFF) { + /* For DMA target address setting, physical address should be used */ + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_SYSADDR_OFFSET, + (uintptr_t)data); + } + + return SD_OK; +} + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +/* + * function to write one block data directly to the + * host controller's FIFO which is 1K uint8_t or + * 2K uint8_t in size. + * It is used in Non-DMA mode for data transmission. + */ +int32_t chal_sd_write_buffer(CHAL_HANDLE *sd_handle, uint32_t length, + uint8_t *data) +{ + uint32_t i, leftOver = 0, blockSize, size, value = 0; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + blockSize = handle->cfg.blockSize; + + if (length == 0) + return SD_OK; + + /* PIO mode, push into fifo word by word */ + if (length >= blockSize) { + size = blockSize; + } else { + size = ((length >> 2) << 2); + leftOver = length % 4; + } + + for (i = 0; i < size; i += 4) { + value = *(uint32_t *)(data + i); + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET, value); + } +/* + * BUG ALERT: + * This implementation has TWO issues that must be addressed before you + * can safely INCLUDE_EMMC_DRIVER_WRITE_CODE. + * + * (1) For the last leftOver bytes, driver writes full word, which means + * some of the eMMC content (i.e. "4 - leftOver" will be erroneously + * overwritten). + * (2) eMMC is a block device. What happens when less than a full block of + * data is submitted??? + */ + if (leftOver > 0) { + value = ((*(uint32_t *)(data + i)) << (4 - leftOver)); + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET, value); + } + + return SD_OK; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + +/* + * Function to read maximal one block data directly + * from the data port of the host controller (FIFO). It is used + * in Non-DMA mode for data transmission. + */ +int32_t chal_sd_read_buffer(CHAL_HANDLE *sd_handle, uint32_t length, + uint8_t *data) +{ + uint32_t i, size, leftOver, blockSize, value; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + value = 0; + + blockSize = handle->cfg.blockSize; + + /* PIO mode, extract fifo word by word */ + if (length >= blockSize) { + size = blockSize; + leftOver = 0; + } else { + leftOver = length % 4; + size = ((length >> 2) << 2); + } + + for (i = 0; i < size; i += 4) { + value = + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + memcpy((void *)(data + i), &value, sizeof(uint32_t)); + } + + if (leftOver > 0) { + value = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + + /* + * Copy remaining non-full word bytes. + * (We run ARM as Little Endian) + */ + uint8_t j = 0; + + for (j = 0; j < leftOver; j++) { + data[i + j] = (value >> (j * 8)) & 0xFF; + } + } + + return SD_OK; +} + +/* + * Resets both DAT or CMD line. + */ +int32_t chal_sd_reset_line(CHAL_HANDLE *sd_handle, uint32_t line) +{ + uint32_t control, flag; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + flag = SD4_EMMC_TOP_CTRL1_CMDRST_MASK | SD4_EMMC_TOP_CTRL1_DATRST_MASK; + + if (flag != (line | flag)) + return SD_FAIL; + + control = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + control |= line; + mmio_write_32(handle->ctrl.sdRegBaseAddr + SD4_EMMC_TOP_CTRL1_OFFSET, + control); + + /* reset CMD and DATA line should always work, no need to timed out */ + do { + control = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_CTRL1_OFFSET); + } while (control & line); + + return SD_OK; +} + +/* + * Function to be called once a SD command is done to read + * back it's response data. + */ +int32_t chal_sd_get_response(CHAL_HANDLE *sd_handle, uint32_t *resp) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + resp[0] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP0_OFFSET); + resp[1] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP2_OFFSET); + resp[2] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP4_OFFSET); + resp[3] = mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_RESP6_OFFSET); + + return SD_OK; +} + +/* + * The function is called to clean all the pending interrupts. + */ +int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sd_handle) +{ + uint32_t status = SD_OK; + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *)sd_handle; + + /* Make sure clean all interrupts */ + do { + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET, 0xFFFFFFFF); + SD_US_DELAY(10); + } while (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); + + return status; +} + +/* + * The function returns interrupt status register value. + */ +int32_t chal_sd_get_irq_status(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + return (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); +} + +/* + * The function clears interrupt(s) specified in the mask. + */ +int32_t chal_sd_clear_irq(CHAL_HANDLE *sd_handle, uint32_t mask) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + /* Make sure clean masked interrupts */ + do { + mmio_write_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET, mask); + SD_US_DELAY(10); + } while (mask & + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTR_OFFSET)); + + return SD_OK; +} + +/* + * Description: The function configures the SD host controller. + */ +int32_t chal_sd_config(CHAL_HANDLE *sd_handle, uint32_t speed, uint32_t retry, + uint32_t boundary, uint32_t blkSize, uint32_t dma) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return SD_INVALID_HANDLE; + + handle = (struct sd_dev *) sd_handle; + + handle->cfg.speedMode = speed; + handle->cfg.retryLimit = retry; + handle->cfg.dmaBoundary = boundary; + handle->cfg.blockSize = blkSize; + + chal_sd_set_dma(sd_handle, dma); + SD_US_DELAY(100); + chal_sd_set_dma_boundary(handle, boundary); + SD_US_DELAY(100); + + chal_sd_set_speed(sd_handle, speed); + + SD_US_DELAY(100); + return SD_OK; +} + +/* + * Cleans up HC FIFO. + */ +void chal_sd_dump_fifo(CHAL_HANDLE *sd_handle) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *)sd_handle; + + /* in case there still data in the host buffer */ + while (mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_OFFSET) & 0x800) { + mmio_read_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_BUFDAT_OFFSET); + }; +} + +/* + * Enable or disable a SD interrupt signal. + */ +void chal_sd_set_irq_signal(CHAL_HANDLE *sd_handle, uint32_t mask, + uint32_t state) +{ + struct sd_dev *handle; + + if (sd_handle == NULL) + return; + + handle = (struct sd_dev *)sd_handle; + + if (state) + mmio_setbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTREN2_OFFSET, mask); + else + mmio_clrbits_32(handle->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_INTREN2_OFFSET, mask); +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c new file mode 100644 index 0000000..9e2c618 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c @@ -0,0 +1,1089 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_csl_sdprot.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +#define SD_CARD_BUSY 0x80000000 +#define SD_CARD_RETRY_LIMIT 1000 +#define SD_CARD_HIGH_SPEED_PS 13 +#define SD_CHK_HIGH_SPEED_MODE 0x00FFFFF1 +#define SD_SET_HIGH_SPEED_MODE 0x80FFFFF1 +#define SD_MMC_ENABLE_HIGH_SPEED 0x03b90100 //0x03b90103 +#define SD_MMC_8BIT_MODE 0x03b70200 +#define SD_MMC_4BIT_MODE 0x03b70100 +#define SD_MMC_1BIT_MODE 0x03b70000 + +#define SD_MMC_BOOT_8BIT_MODE 0x03b10200 +#define SD_MMC_BOOT_4BIT_MODE 0x03b10100 +#define SD_MMC_BOOT_1BIT_MODE 0x03b10000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_CNF 0X03B30000 + +#ifdef USE_EMMC_FIP_TOC_CACHE +/* + * Cache size mirrors the size of the global eMMC temp buffer + * which is used for non-image body reads such as headers, ToC etc. + */ +#define CACHE_SIZE ((EMMC_BLOCK_SIZE) * 2) +#define PARTITION_BLOCK_ADDR ((PLAT_FIP_ATTEMPT_OFFSET)/(EMMC_BLOCK_SIZE)) + +static uint32_t cached_partition_block; +static uint8_t cached_block[CACHE_SIZE]; +#endif + +static int set_card_data_width(struct sd_handle *handle, int width); +static int abort_err(struct sd_handle *handle); +static int err_recovery(struct sd_handle *handle, uint32_t errors); +static int xfer_data(struct sd_handle *handle, uint32_t mode, uint32_t addr, + uint32_t length, uint8_t *base); + +int set_boot_config(struct sd_handle *handle, uint32_t config) +{ + return mmc_cmd6(handle, SDIO_HW_EMMC_EXT_CSD_BOOT_CNF | config); +} + +void process_csd_mmc_speed(struct sd_handle *handle, uint32_t csd_mmc_speed) +{ + uint32_t div_ctrl_setting; + + /* CSD field TRAN_SPEED: + * Bits [2:0] 0 = 100 KHz + * 1 = 1 MHz + * 2 = 10 MHz + * 3 = 100 MHz + * 4...7 Reserved. + * Bits [6:3] 0 = Reserved + * 1 = 1.0 + * 2 = 1.2 + * 3 = 1.3 + * 4 = 1.5 + * 5 = 2.0 + * 6 = 2.6 + * 7 = 3.0 + * 8 = 3.5 + * 9 = 4.0 + * A = 4.5 + * B = 5.2 + * C = 5.5 + * D = 6.0 + * E = 7.0 + * F = 8.0 + * For cards supporting version 4.0, 4.1, and 4.2 of the standard, + * the value shall be 20 MHz (0x2A). + * For cards supporting version 4.3 , the value shall be 26 MHz (0x32) + */ + + switch (csd_mmc_speed & 0x7F) { + case 0x2A: + EMMC_TRACE("Speeding up eMMC clock to 20MHz\n"); + div_ctrl_setting = + chal_sd_freq_2_div_ctrl_setting(20 * 1000 * 1000); + break; + case 0x32: + EMMC_TRACE("Speeding up eMMC clock to 26MHz\n"); + div_ctrl_setting = + chal_sd_freq_2_div_ctrl_setting(26 * 1000 * 1000); + break; + default: + /* Unknown */ + return; + } + + chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 0); + + chal_sd_set_clock((CHAL_HANDLE *) handle->device, div_ctrl_setting, 1); + + SD_US_DELAY(1000); +} + + +/* + * The function changes SD/SDIO/MMC card data width if + * the card support configurable data width. The host controller + * and the card has to be in the same bus data width. + */ +int set_card_data_width(struct sd_handle *handle, int width) +{ + uint32_t data_width = 0; + int is_valid_arg = 1; + int rc = SD_FAIL; + char *bitwidth_str = " "; + char *result_str = "failed"; + + switch (width) { +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + case SD_BUS_DATA_WIDTH_8BIT: + data_width = SD_MMC_8BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "8_BIT"; +#endif + break; +#endif + case SD_BUS_DATA_WIDTH_4BIT: + data_width = SD_MMC_4BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "4_BIT"; +#endif + break; + + case SD_BUS_DATA_WIDTH_1BIT: + data_width = SD_MMC_1BIT_MODE; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "1_BIT"; +#endif + break; + + default: + is_valid_arg = 0; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + bitwidth_str = "unknown"; +#endif + break; + } + + if (is_valid_arg) { + rc = mmc_cmd6(handle, data_width); + if (rc == SD_OK) { +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "succeeded"; +#endif + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + width); + } else { +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "failed"; +#endif + } + } else { + rc = SD_FAIL; +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + result_str = "ignored"; +#endif + } + + VERBOSE("SDIO Data Width(%s) %s.\n", bitwidth_str, result_str); + + return rc; +} + + +/* + * Error handling routine. Does abort data + * transmission if error is found. + */ +static int abort_err(struct sd_handle *handle) +{ + uint32_t present, options, event, rel = 0; + struct sd_resp cmdRsp; + + handle->device->ctrl.argReg = 0; + handle->device->ctrl.cmdIndex = SD_CMD_STOP_TRANSMISSION; + + options = (SD_CMD_STOP_TRANSMISSION << 24) | + (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + chal_sd_send_cmd((CHAL_HANDLE *) handle->device, + handle->device->ctrl.cmdIndex, + handle->device->ctrl.argReg, options); + + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_CMDDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (event & SD_CMD_ERROR_INT) { + rel = SD_ERROR_NON_RECOVERABLE; + } else { + if (event & SD_DAT_TIMEOUT) { + return SD_ERROR_NON_RECOVERABLE; + } + + chal_sd_get_response((CHAL_HANDLE *) handle->device, + (uint32_t *)&cmdRsp); + + process_cmd_response(handle, handle->device->ctrl.cmdIndex, + cmdRsp.data.r2.rsp1, cmdRsp.data.r2.rsp2, + cmdRsp.data.r2.rsp3, cmdRsp.data.r2.rsp4, + &cmdRsp); + + SD_US_DELAY(2000); + + present = + chal_sd_get_present_status((CHAL_HANDLE *) handle->device); + + if ((present & 0x00F00000) == 0x00F00000) + rel = SD_ERROR_RECOVERABLE; + else + rel = SD_ERROR_NON_RECOVERABLE; + } + + return rel; +} + + +/* + * The function handles real data transmission on both DMA and + * none DMA mode, In None DMA mode the data transfer starts + * when the command is sent to the card, data has to be written + * into the host contollers buffer at this time one block + * at a time. + * In DMA mode, the real data transfer is done by the DMA engine + * and this functions just waits for the data transfer to complete. + * + */ +int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, uint32_t addr, + uint32_t length, int dir) +{ + if (dir == SD_XFER_HOST_TO_CARD) { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + if (handle->device->cfg.dma == SD_DMA_OFF) { + /* + * In NON DMA mode, the real data xfer starts from here + */ + if (write_buffer(handle, length, buffer)) + return SD_WRITE_ERROR; + } else { + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_OK) + return SD_OK; + + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } +#else + return SD_WRITE_ERROR; +#endif + } else { /* SD_XFER_CARD_TO_HOST */ + + if (handle->device->cfg.dma == SD_DMA_OFF) { + /* In NON DMA mode, the real data + * transfer starts from here + */ + if (read_buffer(handle, length, buffer)) + return SD_READ_ERROR; + + } else { /* for DMA mode */ + + /* + * once the data transmission is done + * copy data to the host buffer. + */ + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_OK) + return SD_OK; + + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + } + return SD_OK; +} + + +/* + * The function sets block size for the next SD/SDIO/MMC + * card read/write command. + */ +int select_blk_sz(struct sd_handle *handle, uint16_t size) +{ + return sd_cmd16(handle, size); +} + + +/* + * The function initalizes the SD/SDIO/MMC/CEATA and detects + * the card according to the flag of detection. + * Once this function is called, the card is put into ready state + * so application can do data transfer to and from the card. + */ +int init_card(struct sd_handle *handle, int detection) +{ + /* + * After Reset, eMMC comes up in 1 Bit Data Width by default. + * Set host side to match. + */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + +#ifdef USE_EMMC_FIP_TOC_CACHE + cached_partition_block = 0; +#endif + handle->device->ctrl.present = 0; /* init card present to be no card */ + + init_mmc_card(handle); + + handle->device->ctrl.present = 1; /* card is detected */ + + /* switch the data width back */ + if (handle->card->type != SD_CARD_MMC) + return SD_FAIL; + + /* + * Dynamically set Data Width to highest supported value. + * Try different data width settings (highest to lowest). + * Verify each setting by reading EXT_CSD and comparing + * against the EXT_CSD contents previously read in call to + * init_mmc_card() earlier. Stop at first verified data width + * setting. + */ + { +#define EXT_CSD_PROPERTIES_SECTION_START_INDEX 192 +#define EXT_CSD_PROPERTIES_SECTION_END_INDEX 511 + uint8_t buffer[EXT_CSD_SIZE]; +#ifdef DRIVER_EMMC_ENABLE_DATA_WIDTH_8BIT + /* Try 8 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_8BIT); + if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_8BIT)) && + (!mmc_cmd8(handle, buffer)) && + (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX], + &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]), + EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1))) + + return SD_OK; +#endif + /* Fall back to 4 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_4BIT); + if ((!set_card_data_width(handle, SD_BUS_DATA_WIDTH_4BIT)) && + (!mmc_cmd8(handle, buffer)) && + (!memcmp(&buffer[EXT_CSD_PROPERTIES_SECTION_START_INDEX], + &(emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_PROPERTIES_SECTION_START_INDEX]), + EXT_CSD_PROPERTIES_SECTION_END_INDEX - EXT_CSD_PROPERTIES_SECTION_START_INDEX + 1))) + + return SD_OK; + + /* Fall back to 1 Bit Data Width */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + /* Just use 1 Bit Data Width then. */ + if (!set_card_data_width(handle, SD_BUS_DATA_WIDTH_1BIT)) + return SD_OK; + + } + return SD_CARD_INIT_ERROR; +} + + +/* + * The function handles MMC/CEATA card initalization. + */ +int init_mmc_card(struct sd_handle *handle) +{ + uint32_t ocr = 0, newOcr, rc, limit = 0; + uint32_t cmd1_option = 0x40300000; + uint32_t sec_count; + + handle->card->type = SD_CARD_MMC; + + do { + SD_US_DELAY(1000); + newOcr = 0; + ocr = 0; + rc = sd_cmd1(handle, cmd1_option, &newOcr); + limit++; + + if (rc == SD_OK) + ocr = newOcr; + + } while (((ocr & SD_CARD_BUSY) == 0) && (limit < SD_CARD_RETRY_LIMIT)); + + if (limit >= SD_CARD_RETRY_LIMIT) { + handle->card->type = SD_CARD_UNKNOWN; + EMMC_TRACE("CMD1 Timeout: Device is not ready\n"); + return SD_CARD_UNKNOWN; + } + + /* Save the ocr register */ + handle->device->ctrl.ocr = ocr; + + /* Ready State */ + rc = sd_cmd2(handle); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + rc = sd_cmd3(handle); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + /* read CSD */ + rc = sd_cmd9(handle, &emmc_global_vars_ptr->cardData); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + /* Increase clock frequency according to what the card advertises */ + EMMC_TRACE("From CSD... cardData.csd.mmc.speed = 0x%X\n", + emmc_global_vars_ptr->cardData.csd.mmc.speed); + process_csd_mmc_speed(handle, + emmc_global_vars_ptr->cardData.csd.mmc.speed); + + /* goto transfer mode */ + rc = sd_cmd7(handle, handle->device->ctrl.rca); + if (rc != SD_OK) { + handle->card->type = SD_CARD_UNKNOWN; + return SD_CARD_UNKNOWN; + } + + rc = mmc_cmd8(handle, emmc_global_buf_ptr->u.Ext_CSD_storage); + if (rc == SD_OK) { + /* calcul real capacity */ + sec_count = emmc_global_buf_ptr->u.Ext_CSD_storage[212] | + emmc_global_buf_ptr->u.Ext_CSD_storage[213] << 8 | + emmc_global_buf_ptr->u.Ext_CSD_storage[214] << 16 | + emmc_global_buf_ptr->u.Ext_CSD_storage[215] << 24; + + EMMC_TRACE("Device density = %ldMBytes\n", + handle->card->size / (1024 * 1024)); + + if (sec_count > 0) { + handle->card->size = (uint64_t)sec_count * 512; + + EMMC_TRACE("Updated Device density = %ldMBytes\n", + handle->card->size / (1024 * 1024)); + } + + if (sec_count > (2u * 1024 * 1024 * 1024) / 512) { + handle->device->ctrl.ocr |= SD_CARD_HIGH_CAPACITY; + handle->device->cfg.blockSize = 512; + } + + if (handle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + EMMC_TRACE("Sector addressing\n"); + else + EMMC_TRACE("Byte addressing\n"); + + EMMC_TRACE("Ext_CSD_storage[162]: 0x%02X Ext_CSD_storage[179]: 0x%02X\n", + emmc_global_buf_ptr->u.Ext_CSD_storage[162], + emmc_global_buf_ptr->u.Ext_CSD_storage[179]); + } + + return handle->card->type; +} + + +/* + * The function send reset command to the card. + * The card will be in ready status after the reset. + */ +int reset_card(struct sd_handle *handle) +{ + int res = SD_OK; + + /* on reset, card's RCA should return to 0 */ + handle->device->ctrl.rca = 0; + + res = sd_cmd0(handle); + + if (res != SD_OK) + return SD_RESET_ERROR; + + return res; +} + + +/* + * The function sends command to the card and starts + * data transmission. + */ +static int xfer_data(struct sd_handle *handle, + uint32_t mode, + uint32_t addr, uint32_t length, uint8_t *base) +{ + int rc = SD_OK; + + VERBOSE("XFER: dest: 0x%" PRIx64 ", addr: 0x%x, size: 0x%x bytes\n", + (uint64_t)base, addr, length); + + if ((length / handle->device->cfg.blockSize) > 1) { + if (mode == SD_OP_READ) { + inv_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd18(handle, addr, length, base); + } else { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + flush_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd25(handle, addr, length, base); +#else + rc = SD_DATA_XFER_ERROR; +#endif + } + } else { + if (mode == SD_OP_READ) { + inv_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd17(handle, addr, + handle->device->cfg.blockSize, base); + } else { +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + flush_dcache_range((uintptr_t)base, (uint64_t)length); + rc = sd_cmd24(handle, addr, + handle->device->cfg.blockSize, base); +#else + rc = SD_DATA_XFER_ERROR; +#endif + } + } + + if (rc != SD_OK) + return SD_DATA_XFER_ERROR; + + return SD_OK; +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks) +{ + uint32_t end_addr; + + INFO("ERASE: addr: 0x%x, num of sectors: 0x%x\n", addr, blocks); + + if (sd_cmd35(handle, addr) != SD_OK) + return SD_FAIL; + + end_addr = addr + blocks - 1; + if (sd_cmd36(handle, end_addr) != SD_OK) + return SD_FAIL; + + if (sd_cmd38(handle) != SD_OK) + return SD_FAIL; + + return SD_OK; +} +#endif + +/* + * The function reads block data from a card. + */ +#ifdef USE_EMMC_FIP_TOC_CACHE +int read_block(struct sd_handle *handle, + uint8_t *dst, uint32_t addr, uint32_t len) +{ + int rel = SD_OK; + + /* + * Avoid doing repeated reads of the partition block + * by caching. + */ + if (cached_partition_block && + addr == PARTITION_BLOCK_ADDR && + len == CACHE_SIZE) { + memcpy(dst, cached_block, len); + } else { + rel = xfer_data(handle, SD_OP_READ, addr, len, dst); + + if (len == CACHE_SIZE && addr == PARTITION_BLOCK_ADDR) { + cached_partition_block = 1; + memcpy(cached_block, dst, len); + } + } + + return rel; +} +#else +int read_block(struct sd_handle *handle, + uint8_t *dst, uint32_t addr, uint32_t len) +{ + return xfer_data(handle, SD_OP_READ, addr, len, dst); +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + +/* + * The function writes block data to a card. + */ +int write_block(struct sd_handle *handle, + uint8_t *src, uint32_t addr, uint32_t len) +{ + int rel = SD_OK; + + /* + * Current HC has problem to get response of cmd16 after cmd12, + * the delay is necessary to sure the next cmd16 will not be timed out. + * The delay has to be at least 4 ms. + * The code removed cmd16 and use cmd13 to get card status before + * sending cmd18 or cmd25 to make sure the card is ready and thus + * no need to have delay here. + */ + + rel = xfer_data(handle, SD_OP_WRITE, addr, len, src); + + EMMC_TRACE("wr_blk addr:0x%08X src:0x%08X len:0x%08X result:%d\n", + addr, src, len, rel); + + return rel; +} + + +/* + * The function is called to write one block data directly to + * a card's data buffer. + * it is used in Non-DMA mode for card data transmission. + */ +int write_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data) +{ + uint32_t rem, blockSize, event; + uint8_t *pData = data; + + blockSize = handle->device->cfg.blockSize; + rem = length; + + if (rem == 0) + return SD_OK; + + while (rem > 0) { + + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_BWRDY_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } + + if (rem >= blockSize) + chal_sd_write_buffer((CHAL_HANDLE *) handle->device, + blockSize, pData); + else + chal_sd_write_buffer((CHAL_HANDLE *) handle->device, + rem, pData); + + if (rem > blockSize) { + rem -= blockSize; + pData += blockSize; + } else { + pData += rem; + rem = 0; + } + } + + if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) != + SD4_EMMC_TOP_INTR_TXDONE_MASK) { + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus != SD_OK) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_WRITE_ERROR; + } + } else { + handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK; + } + + return SD_OK; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + + +/* + * The function is called to read maximal one block data + * directly from a card + * It is used in Non-DMA mode for card data transmission. + */ +int read_buffer(struct sd_handle *handle, uint32_t length, uint8_t *data) +{ + uint32_t rem, blockSize, event = 0; + uint8_t *pData = data; + + blockSize = handle->device->cfg.blockSize; + rem = length; + + if (rem == 0) + return SD_OK; + + while (rem > 0) { + event = wait_for_event(handle, + SD4_EMMC_TOP_INTR_BRRDY_MASK | + SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + + if (rem >= blockSize) + chal_sd_read_buffer((CHAL_HANDLE *) handle->device, + blockSize, pData); + else + chal_sd_read_buffer((CHAL_HANDLE *) handle->device, rem, + pData); + + if (rem > blockSize) { + rem -= blockSize; + pData += blockSize; + } else { + pData += rem; + rem = 0; + } + } + + /* In case, there are extra data in the SD FIFO, just dump them. */ + chal_sd_dump_fifo((CHAL_HANDLE *) handle->device); + + if ((event & SD4_EMMC_TOP_INTR_TXDONE_MASK) != + SD4_EMMC_TOP_INTR_TXDONE_MASK) { + event = wait_for_event(handle, SD4_EMMC_TOP_INTR_TXDONE_MASK, + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus) { + check_error(handle, handle->device->ctrl.cmdStatus); + return SD_READ_ERROR; + } + } else { + handle->device->ctrl.eventList &= ~SD4_EMMC_TOP_INTR_TXDONE_MASK; + } + + return SD_OK; +} + + +/* + * Error handling routine. + * The function just reset the DAT + * and CMD line if an error occures during data transmission. + */ +int check_error(struct sd_handle *handle, uint32_t ints) +{ + uint32_t rel; + + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 0); + + if (ints & SD4_EMMC_TOP_INTR_CMDERROR_MASK) { + + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_CMDRST_MASK); + rel = abort_err(handle); + + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_DATRST_MASK); + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 1); + + return (rel == SD_ERROR_NON_RECOVERABLE) ? + SD_ERROR_NON_RECOVERABLE : SD_ERROR_RECOVERABLE; + } else { + rel = err_recovery(handle, ints); + } + + chal_sd_set_irq_signal((CHAL_HANDLE *) handle->device, + SD_ERR_INTERRUPTS, 1); + + return rel; +} + + +/* + * Error recovery routine. + * Try to recover from the error. + */ +static int err_recovery(struct sd_handle *handle, uint32_t errors) +{ + uint32_t rel = 0; + + /* + * In case of timeout error, the cmd line and data line maybe + * still active or stuck at atcitve so it is needed to reset + * either data line or cmd line to make sure a new cmd can be sent. + */ + + if (errors & SD_CMD_ERROR_INT) + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_CMDRST_MASK); + + if (errors & SD_DAT_ERROR_INT) + chal_sd_reset_line((CHAL_HANDLE *) handle->device, + SD4_EMMC_TOP_CTRL1_DATRST_MASK); + + /* Abort transaction by sending out stop command */ + if ((handle->device->ctrl.cmdIndex == 18) || + (handle->device->ctrl.cmdIndex == 25)) + rel = abort_err(handle); + + return rel; +} + + +/* + * The function is called to read one block data directly from a card. + * It is used in Non-DMA mode for card data transmission. + */ +int process_cmd_response(struct sd_handle *handle, + uint32_t cmdIndex, + uint32_t rsp0, + uint32_t rsp1, + uint32_t rsp2, uint32_t rsp3, struct sd_resp *resp) +{ + int result = SD_OK; + + /* R6 */ + uint32_t rca = (rsp0 >> 16) & 0xffff; + uint32_t cardStatus = rsp0; + + /* R4 */ + uint32_t cBit = (rsp0 >> 31) & 0x1; + uint32_t funcs = (rsp0 >> 28) & 0x7; + uint32_t memPresent = (rsp0 >> 27) & 0x1; + + resp->r1 = 0x3f; + resp->cardStatus = cardStatus; + + if (cmdIndex == SD_CMD_IO_SEND_OP_COND) { + resp->data.r4.cardReady = cBit; + resp->data.r4.funcs = funcs; + resp->data.r4.memPresent = memPresent; + resp->data.r4.ocr = cardStatus; + } + + if (cmdIndex == SD_CMD_MMC_SET_RCA) { + resp->data.r6.rca = rca; + resp->data.r6.cardStatus = cardStatus & 0xFFFF; + } + + if (cmdIndex == SD_CMD_SELECT_DESELECT_CARD) { + resp->data.r7.rca = rca; + } + + if (cmdIndex == SD_CMD_IO_RW_DIRECT) { + if (((rsp0 >> 16) & 0xffff) != 0) + result = SD_CMD_ERR_INVALID_RESPONSE; + + resp->data.r5.data = rsp0 & 0xff; + } + + if (cmdIndex == SD_CMD_IO_RW_EXTENDED) { + if (((rsp0 >> 16) & 0xffff) != 0) + result = SD_CMD_ERR_INVALID_RESPONSE; + + resp->data.r5.data = rsp0 & 0xff; + } + + if (cmdIndex == SD_ACMD_SD_SEND_OP_COND || + cmdIndex == SD_CMD_SEND_OPCOND) + resp->data.r3.ocr = cardStatus; + + if (cmdIndex == SD_CMD_SEND_CSD || + cmdIndex == SD_CMD_SEND_CID || + cmdIndex == SD_CMD_ALL_SEND_CID) { + resp->data.r2.rsp4 = rsp3; + resp->data.r2.rsp3 = rsp2; + resp->data.r2.rsp2 = rsp1; + resp->data.r2.rsp1 = rsp0; + } + + if ((cmdIndex == SD_CMD_READ_EXT_CSD) && + (handle->card->type == SD_CARD_SD)) { + if ((resp->cardStatus & 0xAA) != 0xAA) { + result = SD_CMD_ERR_INVALID_RESPONSE; + } + } + + return result; +} + + +/* + * The function sets DMA buffer and data length, process + * block size and the number of blocks to be transferred. + * It returns the DMA buffer address. + * It copies dma data from user buffer to the DMA buffer + * if the operation is to write data to the SD card. + */ +void data_xfer_setup(struct sd_handle *handle, uint8_t *data, uint32_t length, + int dir) +{ + chal_sd_setup_xfer((CHAL_HANDLE *)handle->device, data, length, dir); +} + + +/* + * The function does soft reset the host SD controller. After + * the function call all host controller's register are reset + * to default vallue; + * + * Note This function only resets the host controller it does not + * reset the controller's handler. + */ +int reset_host_ctrl(struct sd_handle *handle) +{ + chal_sd_stop(); + + return SD_OK; +} + +static void pstate_log(struct sd_handle *handle) +{ + ERROR("PSTATE: 0x%x\n", mmio_read_32 + (handle->device->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_PSTATE_SD4_OFFSET)); + ERROR("ERRSTAT: 0x%x\n", mmio_read_32 + (handle->device->ctrl.sdRegBaseAddr + + SD4_EMMC_TOP_ERRSTAT_OFFSET)); +} + +/* + * The function waits for one or a group of interrupts specified + * by mask. The function returns if any one the interrupt status + * is set. If interrupt mode is not enabled then it will poll + * the interrupt status register until a interrupt status is set + * an error interrupt happens. If interrupt mode is enabled then + * this function should be called after the interrupt + * is received by ISR routine. + */ +uint32_t wait_for_event(struct sd_handle *handle, + uint32_t mask, uint32_t retry) +{ + uint32_t regval, cmd12, time = 0; + + handle->device->ctrl.cmdStatus = 0; /* no error */ + EMMC_TRACE("%s %d mask:0x%x timeout:%d irq_status:0x%x\n", + __func__, __LINE__, mask, retry, + chal_sd_get_irq_status((CHAL_HANDLE *)handle->device)); + + /* Polling mode */ + do { + regval = chal_sd_get_irq_status((CHAL_HANDLE *)handle->device); + + if (regval & SD4_EMMC_TOP_INTR_DMAIRQ_MASK) { + chal_sd_set_dma_addr((CHAL_HANDLE *)handle->device, + (uintptr_t) + chal_sd_get_dma_addr((CHAL_HANDLE *) + handle->device)); + chal_sd_clear_irq((CHAL_HANDLE *)handle->device, + SD4_EMMC_TOP_INTR_DMAIRQ_MASK); + } + + if (time++ > retry) { + ERROR("EMMC: No response (cmd%d) after %dus.\n", + handle->device->ctrl.cmdIndex, + time * EMMC_WFE_RETRY_DELAY_US); + handle->device->ctrl.cmdStatus = SD_CMD_MISSING; + pstate_log(handle); + ERROR("EMMC: INT[0x%x]\n", regval); + break; + } + + if (regval & SD4_EMMC_TOP_INTR_CTOERR_MASK) { + ERROR("EMMC: Cmd%d timeout INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = + SD4_EMMC_TOP_INTR_CTOERR_MASK; + pstate_log(handle); + break; + } + if (regval & SD_CMD_ERROR_FLAGS) { + ERROR("EMMC: Cmd%d error INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = SD_CMD_ERROR_FLAGS; + pstate_log(handle); + break; + } + + cmd12 = chal_sd_get_atuo12_error((CHAL_HANDLE *)handle->device); + if (cmd12) { + ERROR("EMMC: Cmd%d auto cmd12 err:0x%x\n", + handle->device->ctrl.cmdIndex, cmd12); + handle->device->ctrl.cmdStatus = cmd12; + pstate_log(handle); + break; + } + + if (SD_DATA_ERROR_FLAGS & regval) { + ERROR("EMMC: Data for cmd%d error, INT[0x%x]\n", + handle->device->ctrl.cmdIndex, regval); + handle->device->ctrl.cmdStatus = + (SD_DATA_ERROR_FLAGS & regval); + pstate_log(handle); + break; + } + + if ((regval & mask) == 0) + udelay(EMMC_WFE_RETRY_DELAY_US); + + } while ((regval & mask) == 0); + + /* clear the interrupt since it is processed */ + chal_sd_clear_irq((CHAL_HANDLE *)handle->device, (regval & mask)); + + return (regval & mask); +} + +int32_t set_config(struct sd_handle *handle, uint32_t speed, uint32_t retry, + uint32_t dma, uint32_t dmaBound, uint32_t blkSize, + uint32_t wfe_retry) +{ + int32_t rel = 0; + + if (handle == NULL) + return SD_FAIL; + + handle->device->cfg.wfe_retry = wfe_retry; + + rel = chal_sd_config((CHAL_HANDLE *)handle->device, speed, retry, + dmaBound, blkSize, dma); + return rel; + +} + +int mmc_cmd1(struct sd_handle *handle) +{ + uint32_t newOcr, res; + uint32_t cmd1_option = MMC_OCR_OP_VOLT | MMC_OCR_SECTOR_ACCESS_MODE; + + /* + * After Reset, eMMC comes up in 1 Bit Data Width by default. + * Set host side to match. + */ + chal_sd_config_bus_width((CHAL_HANDLE *) handle->device, + SD_BUS_DATA_WIDTH_1BIT); + +#ifdef USE_EMMC_FIP_TOC_CACHE + cached_partition_block = 0; +#endif + handle->device->ctrl.present = 0; /* init card present to be no card */ + + handle->card->type = SD_CARD_MMC; + + res = sd_cmd1(handle, cmd1_option, &newOcr); + + if (res != SD_OK) { + EMMC_TRACE("CMD1 Timeout: Device is not ready\n"); + res = SD_CARD_UNKNOWN; + } + return res; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c new file mode 100644 index 0000000..c62886c --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c @@ -0,0 +1,842 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "bcm_emmc.h" +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_chal_sd.h" +#include "emmc_pboot_hal_memory_drv.h" + +int sd_cmd0(struct sd_handle *handle) +{ + int res; + uint32_t argument = 0x0; /* Go to IDLE state. */ + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_GO_IDLE_STATE, argument, 0, NULL); + + if (res == SD_OK) { + /* Clear all other interrupts */ + chal_sd_clear_irq((void *)handle->device, 0xffffffff); + } + + return res; +} + +int sd_cmd1(struct sd_handle *handle, uint32_t ocr, uint32_t *ocr_output) +{ + int res; + uint32_t options; + struct sd_resp resp; + + options = SD_CMDR_RSP_TYPE_R3_4 << SD_CMDR_RSP_TYPE_S; + + if (ocr_output == NULL) { + EMMC_TRACE("Invalid args\n"); + return SD_FAIL; + } + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_OPCOND, ocr, options, &resp); + + if (res == SD_OK) + *ocr_output = resp.data.r3.ocr; + + return res; +} + +int sd_cmd2(struct sd_handle *handle) +{ + uint32_t options; + struct sd_resp resp; + + /* send cmd and parse result */ + options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S; + + return send_cmd(handle, SD_CMD_ALL_SEND_CID, 0, options, &resp); +} + +int sd_cmd3(struct sd_handle *handle) +{ + int res; + uint32_t options = 0; + uint32_t argument; + struct sd_resp resp; + + /* use non zero and non 0x1 value for rca */ + handle->device->ctrl.rca = 0x5; + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_MMC_SET_RCA, argument, options, &resp); + + if (res != SD_OK) + handle->device->ctrl.rca = 0; + + return res; +} + +int sd_cmd7(struct sd_handle *handle, uint32_t rca) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + argument = (rca << SD_CMD7_ARG_RCA_SHIFT); + + /* + * Response to CMD7 is: + * R1 while selectiing from Stand-By State to Transfer State + * R1b while selecting from Disconnected State to Programming State. + * + * In this driver, we only issue a CMD7 once, to go to transfer mode + * during init_mmc_card(). + */ + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SELECT_DESELECT_CARD, argument, options, + &resp); + + if (res == SD_OK) + /* Clear all other interrupts */ + chal_sd_clear_irq((void *)handle->device, 0xffffffff); + + return res; +} + + +/* + * CMD8 Get CSD_EXT + */ +int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg) +{ + uint32_t res, options; + struct sd_resp resp; + + data_xfer_setup(handle, extCsdReg, CEATA_EXT_CSDBLOCK_SIZE, + SD_XFER_CARD_TO_HOST); + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_READ_EXT_CSD, 0, options, &resp); + + if (res == SD_OK) + res = process_data_xfer(handle, extCsdReg, 0, + CEATA_EXT_CSDBLOCK_SIZE, + SD_XFER_CARD_TO_HOST); + + return res; +} + +int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card) +{ + int res; + uint32_t argument, options, iBlkNum, multiFactor = 1; + uint32_t maxReadBlockLen = 1, maxWriteBlockLen = 1; + struct sd_resp resp; + + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R2 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_CSD, argument, options, &resp); + + if (res != SD_OK) + return res; + + if (handle->card->type == SD_CARD_MMC) { + card->csd.mmc.structure = (resp.data.r2.rsp4 >> 22) & 0x3; + card->csd.mmc.csdSpecVer = (resp.data.r2.rsp4 >> 18) & 0x0f; + card->csd.mmc.taac = (resp.data.r2.rsp4 >> 8) & 0xff; + card->csd.mmc.nsac = resp.data.r2.rsp4 & 0xff; + card->csd.mmc.speed = resp.data.r2.rsp3 >> 24; + card->csd.mmc.classes = (resp.data.r2.rsp3 >> 12) & 0xfff; + card->csd.mmc.rdBlkLen = (resp.data.r2.rsp3 >> 8) & 0xf; + card->csd.mmc.rdBlkPartial = (resp.data.r2.rsp3 >> 7) & 0x01; + card->csd.mmc.wrBlkMisalign = (resp.data.r2.rsp3 >> 6) & 0x1; + card->csd.mmc.rdBlkMisalign = (resp.data.r2.rsp3 >> 5) & 0x1; + card->csd.mmc.dsr = (resp.data.r2.rsp2 >> 4) & 0x01; + card->csd.mmc.size = + ((resp.data.r2.rsp3 & 0x3) << 10) + + ((resp.data.r2.rsp2 >> 22) & 0x3ff); + card->csd.mmc.vddRdCurrMin = (resp.data.r2.rsp2 >> 19) & 0x7; + card->csd.mmc.vddRdCurrMax = (resp.data.r2.rsp2 >> 16) & 0x7; + card->csd.mmc.vddWrCurrMin = (resp.data.r2.rsp2 >> 13) & 0x7; + card->csd.mmc.vddWrCurrMax = (resp.data.r2.rsp2 >> 10) & 0x7; + card->csd.mmc.devSizeMulti = (resp.data.r2.rsp2 >> 7) & 0x7; + card->csd.mmc.eraseGrpSize = (resp.data.r2.rsp2 >> 2) & 0x1f; + card->csd.mmc.eraseGrpSizeMulti = + ((resp.data.r2.rsp2 & 0x3) << 3) + + ((resp.data.r2.rsp1 >> 29) & 0x7); + card->csd.mmc.wrProtGroupSize = + ((resp.data.r2.rsp1 >> 24) & 0x1f); + card->csd.mmc.wrProtGroupEnable = + (resp.data.r2.rsp1 >> 23) & 0x1; + card->csd.mmc.manuDefEcc = (resp.data.r2.rsp1 >> 21) & 0x3; + card->csd.mmc.wrSpeedFactor = (resp.data.r2.rsp1 >> 18) & 0x7; + card->csd.mmc.wrBlkLen = (resp.data.r2.rsp1 >> 14) & 0xf; + card->csd.mmc.wrBlkPartial = (resp.data.r2.rsp1 >> 13) & 0x1; + card->csd.mmc.protAppl = (resp.data.r2.rsp1 >> 8) & 0x1; + card->csd.mmc.copyFlag = (resp.data.r2.rsp1 >> 7) & 0x1; + card->csd.mmc.permWrProt = (resp.data.r2.rsp1 >> 6) & 0x1; + card->csd.mmc.tmpWrProt = (resp.data.r2.rsp1 >> 5) & 0x1; + card->csd.mmc.fileFormat = (resp.data.r2.rsp1 >> 4) & 0x03; + card->csd.mmc.eccCode = resp.data.r2.rsp1 & 0x03; + maxReadBlockLen <<= card->csd.mmc.rdBlkLen; + maxWriteBlockLen <<= card->csd.mmc.wrBlkLen; + + iBlkNum = card->csd.mmc.size + 1; + multiFactor = (1 << (card->csd.mmc.devSizeMulti + 2)); + + handle->card->size = + iBlkNum * multiFactor * (1 << card->csd.mmc.rdBlkLen); + } + + handle->card->maxRdBlkLen = maxReadBlockLen; + handle->card->maxWtBlkLen = maxWriteBlockLen; + + if (handle->card->size < 0xA00000) { + /* + * 10MB Too small size mean, cmd9 response is wrong, + * Use default value 1G + */ + handle->card->size = 0x40000000; + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } + + if ((handle->card->maxRdBlkLen > 512) || + (handle->card->maxWtBlkLen > 512)) { + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } else if ((handle->card->maxRdBlkLen == 0) || + (handle->card->maxWtBlkLen == 0)) { + handle->card->maxRdBlkLen = 512; + handle->card->maxWtBlkLen = 512; + } + + handle->device->cfg.blockSize = handle->card->maxRdBlkLen; + + return res; +} + +int sd_cmd13(struct sd_handle *handle, uint32_t *status) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + argument = handle->device->ctrl.rca << SD_CMD7_ARG_RCA_SHIFT; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SEND_STATUS, argument, options, &resp); + + if (res == SD_OK) { + *status = resp.cardStatus; + } + + return res; +} + +int sd_cmd16(struct sd_handle *handle, uint32_t length) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + argument = length; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd13 failed before cmd16: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd16\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_SET_BLOCKLEN, argument, options, &resp); + + return res; +} + +int sd_cmd17(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd17: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd17\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); + + /* send cmd and parse result */ + argument = addr; + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + res = send_cmd(handle, SD_CMD_READ_SINGLE_BLOCK, argument, options, + &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); + + return res; +} + +int sd_cmd18(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd18: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd18\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_CARD_TO_HOST); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_DTDS_MASK | + SD4_EMMC_TOP_CMD_MSBS_MASK | SD4_EMMC_TOP_CMD_CCHK_EN_MASK | + SD4_EMMC_TOP_CMD_BCEN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | + BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_READ_MULTIPLE_BLOCK, argument, options, + &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_CARD_TO_HOST); + + return res; +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +static int card_sts_resp(struct sd_handle *handle, uint32_t *status) +{ + int res; + uint32_t ntry = 0; + + do { + res = sd_cmd13(handle, status); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd35: rca 0x%0x, return %d\n", + handle->device->ctrl.rca, res); + return res; + } + + if (*status & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd35\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + return SD_OK; +} + +int sd_cmd35(struct sd_handle *handle, uint32_t start) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = start; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE_GROUP_START, + argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} + +int sd_cmd36(struct sd_handle *handle, uint32_t end) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = end; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE_GROUP_END, + argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} + +int sd_cmd38(struct sd_handle *handle) +{ + int res; + uint32_t argument, options; + struct sd_resp resp; + + res = card_sts_resp(handle, &resp.cardStatus); + if (res != SD_OK) + return res; + + argument = 0; + + options = (SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S) | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_ERASE, argument, options, &resp); + + if (res != SD_OK) + return res; + + return res; +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE + +int sd_cmd24(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd24: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, &resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd24\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK; + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_WRITE_BLOCK, argument, options, &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); + + return res; +} + +int sd_cmd25(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer) +{ + int res = SD_OK; + uint32_t argument, options, ntry; + struct sd_resp resp; + + ntry = 0; + do { + res = sd_cmd13(handle, &resp.cardStatus); + if (res != SD_OK) { + EMMC_TRACE( + "cmd 13 failed before cmd25: rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, &resp.cardStatus); + return res; + } + + if (resp.cardStatus & 0x100) + break; + + EMMC_TRACE("cmd13 rsp:0x%08x before cmd25\n", resp.cardStatus); + + if (ntry > handle->device->cfg.retryLimit) { + EMMC_TRACE("cmd13 retry reach limit %d\n", + handle->device->cfg.retryLimit); + return SD_CMD_TIMEOUT; + } + + ntry++; + EMMC_TRACE("cmd13 retry %d\n", ntry); + + SD_US_DELAY(1000); + } while (1); + + data_xfer_setup(handle, buffer, len, SD_XFER_HOST_TO_CARD); + + argument = addr; + + options = SD_CMDR_RSP_TYPE_R1_5_6 << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_DPS_MASK | SD4_EMMC_TOP_CMD_MSBS_MASK | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_BCEN_MASK | + SD4_EMMC_TOP_CMD_CRC_EN_MASK | + BIT(SD4_EMMC_TOP_CMD_ACMDEN_SHIFT); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_CMD_WRITE_MULTIPLE_BLOCK, + argument, options, &resp); + + if (res != SD_OK) + return res; + + res = process_data_xfer(handle, buffer, addr, len, SD_XFER_HOST_TO_CARD); + + return res; +} +#endif /* INCLUDE_EMMC_DRIVER_WRITE_CODE */ + +int mmc_cmd6(struct sd_handle *handle, uint32_t argument) +{ + int res; + uint32_t options; + struct sd_resp resp; + + options = SD_CMDR_RSP_TYPE_R1b_5b << SD_CMDR_RSP_TYPE_S | + SD4_EMMC_TOP_CMD_CCHK_EN_MASK | SD4_EMMC_TOP_CMD_CRC_EN_MASK; + + EMMC_TRACE("Sending CMD6 with argument 0x%X\n", argument); + + /* send cmd and parse result */ + res = send_cmd(handle, SD_ACMD_SET_BUS_WIDTH, argument, options, &resp); + + /* + * For R1b type response: + * controller issues a COMMAND COMPLETE interrupt when the R1 + * response is received, + * then controller monitors DAT0 for busy status, + * controller issues a TRANSFER COMPLETE interrupt when busy signal + * clears. + */ + wait_for_event(handle, + SD4_EMMC_TOP_INTR_TXDONE_MASK | SD_ERR_INTERRUPTS, + handle->device->cfg.wfe_retry); + + if (res == SD_OK) { + /* Check result of Cmd6 using Cmd13 to check card status */ + + /* Check status using Cmd13 */ + res = sd_cmd13(handle, &resp.cardStatus); + + if (res == SD_OK) { + /* Check bit 7 (SWITCH_ERROR) in card status */ + if ((resp.cardStatus & 0x80) != 0) { + EMMC_TRACE("cmd6 failed: SWITCH_ERROR\n"); + res = SD_FAIL; + } + } else { + EMMC_TRACE("cmd13 failed after cmd6: "); + EMMC_TRACE("rca 0x%0x, return %d, response 0x%0x\n", + handle->device->ctrl.rca, res, resp.cardStatus); + } + } + + return res; +} + + +#define SD_BUSY_CHECK 0x00203000 +#define DAT0_LEVEL_MASK 0x100000 /* bit20 in PSTATE */ +#define DEV_BUSY_TIMEOUT 600000 /* 60 Sec : 600000 * 100us */ + +int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, uint32_t argument, + uint32_t options, struct sd_resp *resp) +{ + int status = SD_OK; + uint32_t event = 0, present, timeout = 0, retry = 0, mask = 3; + uint32_t temp_resp[4]; + + if (handle == NULL) { + EMMC_TRACE("Invalid handle for cmd%d\n", cmdIndex); + return SD_INVALID_HANDLE; + } + + mask = (SD_BUSY_CHECK & options) ? 3 : 1; + +RETRY_WRITE_CMD: + do { + /* Make sure it is ok to send command */ + present = + chal_sd_get_present_status((CHAL_HANDLE *) handle->device); + timeout++; + + if (present & mask) + SD_US_DELAY(1000); + else + break; + + } while (timeout < EMMC_BUSY_CMD_TIMEOUT_MS); + + if (timeout >= EMMC_BUSY_CMD_TIMEOUT_MS) { + status = SD_CMD_MISSING; + EMMC_TRACE("cmd%d timedout %dms\n", cmdIndex, timeout); + } + + /* Reset both DAT and CMD line if only of them are stuck */ + if (present & mask) + check_error(handle, SD4_EMMC_TOP_INTR_CMDERROR_MASK); + + handle->device->ctrl.argReg = argument; + chal_sd_send_cmd((CHAL_HANDLE *) handle->device, cmdIndex, + handle->device->ctrl.argReg, options); + + handle->device->ctrl.cmdIndex = cmdIndex; + + event = wait_for_event(handle, + (SD4_EMMC_TOP_INTR_CMDDONE_MASK | + SD_ERR_INTERRUPTS), + handle->device->cfg.wfe_retry); + + if (handle->device->ctrl.cmdStatus == SD_CMD_MISSING) { + retry++; + + if (retry >= handle->device->cfg.retryLimit) { + status = SD_CMD_MISSING; + EMMC_TRACE("cmd%d retry reaches the limit %d\n", + cmdIndex, retry); + } else { + /* reset both DAT & CMD line if one of them is stuck */ + present = chal_sd_get_present_status((CHAL_HANDLE *) + handle->device); + + if (present & mask) + check_error(handle, + SD4_EMMC_TOP_INTR_CMDERROR_MASK); + + EMMC_TRACE("cmd%d retry %d PSTATE[0x%08x]\n", + cmdIndex, retry, + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device)); + goto RETRY_WRITE_CMD; + } + } + + if (handle->device->ctrl.cmdStatus == SD_OK) { + if (resp != NULL) { + status = + chal_sd_get_response((CHAL_HANDLE *) handle->device, + temp_resp); + process_cmd_response(handle, + handle->device->ctrl.cmdIndex, + temp_resp[0], temp_resp[1], + temp_resp[2], temp_resp[3], resp); + } + + /* Check Device busy after CMD */ + if ((cmdIndex == 5) || (cmdIndex == 6) || (cmdIndex == 7) || + (cmdIndex == 28) || (cmdIndex == 29) || (cmdIndex == 38)) { + + timeout = 0; + do { + present = + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device); + + timeout++; + + /* Dat[0]:bit20 low means device busy */ + if ((present & DAT0_LEVEL_MASK) == 0) { + EMMC_TRACE("Device busy: "); + EMMC_TRACE( + "cmd%d arg:0x%08x: PSTATE[0x%08x]\n", + cmdIndex, argument, present); + SD_US_DELAY(100); + } else { + break; + } + } while (timeout < DEV_BUSY_TIMEOUT); + } + } else if (handle->device->ctrl.cmdStatus && + handle->device->ctrl.cmdStatus != SD_CMD_MISSING) { + retry++; + status = check_error(handle, handle->device->ctrl.cmdStatus); + + EMMC_TRACE( + "cmd%d error: cmdStatus:0x%08x error_status:0x%08x\n", + cmdIndex, handle->device->ctrl.cmdStatus, status); + + if ((handle->device->ctrl.cmdIndex == 1) || + (handle->device->ctrl.cmdIndex == 5)) { + status = event; + } else if ((handle->device->ctrl.cmdIndex == 7) || + (handle->device->ctrl.cmdIndex == 41)) { + status = event; + } else if ((status == SD_ERROR_RECOVERABLE) && + (retry < handle->device->cfg.retryLimit)) { + EMMC_TRACE("cmd%d recoverable error ", cmdIndex); + EMMC_TRACE("retry %d PSTATE[0x%08x].\n", retry, + chal_sd_get_present_status((CHAL_HANDLE *) + handle->device)); + goto RETRY_WRITE_CMD; + } else { + EMMC_TRACE("cmd%d retry reaches the limit %d\n", + cmdIndex, retry); + status = event; + } + } + + handle->device->ctrl.blkReg = 0; + /* clear error status for next command */ + handle->device->ctrl.cmdStatus = 0; + + return status; +} diff --git a/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c b/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c new file mode 100644 index 0000000..68f93e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c @@ -0,0 +1,621 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#define MAX_CMD_RETRY 10 + +#if EMMC_USE_DMA +#define USE_DMA 1 +#else +#define USE_DMA 0 +#endif + +struct emmc_global_buffer emmc_global_buf; +struct emmc_global_buffer *emmc_global_buf_ptr = &emmc_global_buf; + +struct emmc_global_vars emmc_global_vars; +struct emmc_global_vars *emmc_global_vars_ptr = &emmc_global_vars; + +static struct sd_handle *sdio_gethandle(void); +static uint32_t sdio_idle(struct sd_handle *p_sdhandle); + +static uint32_t sdio_read(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t storage_addr, + size_t storage_size, + size_t bytes_to_read); + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +static uint32_t sdio_write(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t data_addr, + size_t bytes_to_write); +#endif + +static struct sd_handle *sdio_init(void); +static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle); + +static void init_globals(void) +{ + memset((void *)emmc_global_buf_ptr, 0, sizeof(*emmc_global_buf_ptr)); + memset((void *)emmc_global_vars_ptr, 0, sizeof(*emmc_global_vars_ptr)); +} + +/* + * This function is used to change partition + */ +uint32_t emmc_partition_select(uint32_t partition) +{ + int rc; + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + switch (partition) { + case EMMC_BOOT_PARTITION1: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1); + EMMC_TRACE( + "Change to Boot Partition 1 result:%d (0 means SD_OK)\n", + rc); + break; + + case EMMC_BOOT_PARTITION2: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2); + EMMC_TRACE( + "Change to Boot Partition 2 result:%d (0 means SD_OK)\n", + rc); + break; + + case EMMC_USE_CURRENT_PARTITION: + rc = SD_OK; + EMMC_TRACE("Stay on current partition"); + break; + + case EMMC_USER_AREA: + default: + rc = set_boot_config(sd_handle, + SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER); + EMMC_TRACE("Change to User area result:%d (0 means SD_OK)\n", + rc); + break; + + } + return (rc == SD_OK); +} + +/* + * Initialize emmc controller for eMMC + * Returns 0 on fail condition + */ +uint32_t bcm_emmc_init(bool card_rdy_only) +{ + struct sd_handle *p_sdhandle; + uint32_t result = 0; + + EMMC_TRACE("Enter emmc_controller_init()\n"); + + /* If eMMC is already initialized, skip init */ + if (emmc_global_vars_ptr->init_done) + return 1; + + init_globals(); + + p_sdhandle = sdio_init(); + + if (p_sdhandle == NULL) { + ERROR("eMMC init failed"); + return result; + } + + if (card_rdy_only) { + /* Put the card in Ready state, Not complete init */ + result = bcm_emmc_card_ready_state(p_sdhandle); + return !result; + } + + if (sdio_idle(p_sdhandle) == EMMC_BOOT_OK) { + set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, USE_DMA, + SD_DMA_BOUNDARY_256K, EMMC_BLOCK_SIZE, + EMMC_WFE_RETRY); + + if (!select_blk_sz(p_sdhandle, + p_sdhandle->device->cfg.blockSize)) { + emmc_global_vars_ptr->init_done = 1; + result = 1; + } else { + ERROR("Select Block Size failed\n"); + } + } else { + ERROR("eMMC init failed"); + } + + /* Initialization is failed, so deinit HW setting */ + if (result == 0) + emmc_deinit(); + + return result; +} + +/* + * Function to de-init SDIO controller for eMMC + */ +void emmc_deinit(void) +{ + emmc_global_vars_ptr->init_done = 0; + emmc_global_vars_ptr->sdHandle.card = 0; + emmc_global_vars_ptr->sdHandle.device = 0; +} + +/* + * Read eMMC memory + * Returns read_size + */ +uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + return sdio_read(sdio_gethandle(), mem_addr, storage_addr, + storage_size, bytes_to_read); +} + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +#define EXT_CSD_ERASE_GRP_SIZE 224 + +static int emmc_block_erase(uintptr_t mem_addr, size_t blocks) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + ERROR("eMMC init is not done"); + return -1; + } + + return erase_card(sdio_gethandle(), mem_addr, blocks); +} + +int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition) +{ + int err = 0; + size_t block_count = 0, blocks = 0; + size_t erase_group = 0; + + erase_group = + emmc_global_buf_ptr->u.Ext_CSD_storage[EXT_CSD_ERASE_GRP_SIZE]*1024; + + INFO("eMMC Erase Group Size=0x%lx\n", erase_group); + + emmc_partition_select(partition); + + while (block_count < num_of_blocks) { + blocks = ((num_of_blocks - block_count) > erase_group) ? + erase_group : (num_of_blocks - block_count); + err = emmc_block_erase(mem_addr + block_count, blocks); + if (err) + break; + + block_count += blocks; + } + + if (err == 0) + INFO("eMMC Erase of partition %d successful\n", partition); + else + ERROR("eMMC Erase of partition %d Failed(%i)\n", partition, err); + + return err; +} +#endif + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +/* + * Write to eMMC memory + * Returns written_size + */ +uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr, + size_t bytes_to_write) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 0; + } + + return sdio_write(sd_handle, mem_addr, data_addr, bytes_to_write); +} +#endif + +/* + * Send SDIO Cmd + * Return 0 for pass condition + */ +uint32_t send_sdio_cmd(uint32_t cmdIndex, uint32_t argument, + uint32_t options, struct sd_resp *resp) +{ + struct sd_handle *sd_handle = sdio_gethandle(); + + if (sd_handle->device == 0) { + EMMC_TRACE("eMMC init is not done"); + return 1; + } + + return send_cmd(sd_handle, cmdIndex, argument, options, resp); +} + + +/* + * This function return SDIO handle + */ +struct sd_handle *sdio_gethandle(void) +{ + return &emmc_global_vars_ptr->sdHandle; +} + +/* + * Initialize SDIO controller + */ +struct sd_handle *sdio_init(void) +{ + uint32_t SDIO_base; + struct sd_handle *p_sdhandle = &emmc_global_vars_ptr->sdHandle; + + SDIO_base = EMMC_CTRL_REGS_BASE_ADDR; + + if (SDIO_base == SDIO0_EMMCSDXC_SYSADDR) + EMMC_TRACE(" ---> for SDIO 0 Controller\n\n"); + + memset(p_sdhandle, 0, sizeof(struct sd_handle)); + + p_sdhandle->device = &emmc_global_vars_ptr->sdDevice; + p_sdhandle->card = &emmc_global_vars_ptr->sdCard; + + memset(p_sdhandle->device, 0, sizeof(struct sd_dev)); + memset(p_sdhandle->card, 0, sizeof(struct sd_card_info)); + + if (chal_sd_start((CHAL_HANDLE *) p_sdhandle->device, + SD_PIO_MODE, SDIO_base, SDIO_base) != SD_OK) + return NULL; + + set_config(p_sdhandle, SD_NORMAL_SPEED, MAX_CMD_RETRY, SD_DMA_OFF, + SD_DMA_BOUNDARY_4K, EMMC_BLOCK_SIZE, EMMC_WFE_RETRY); + + return &emmc_global_vars_ptr->sdHandle; +} + +uint32_t sdio_idle(struct sd_handle *p_sdhandle) +{ + reset_card(p_sdhandle); + + SD_US_DELAY(1000); + + if (init_card(p_sdhandle, SD_CARD_DETECT_MMC) != SD_OK) { + reset_card(p_sdhandle); + reset_host_ctrl(p_sdhandle); + return EMMC_BOOT_NO_CARD; + } + + return EMMC_BOOT_OK; +} + +/* + * This function read eMMC + */ +uint32_t sdio_read(struct sd_handle *p_sdhandle, + uintptr_t mem_addr, + uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read) +{ + uint32_t offset = 0, blockAddr, readLen = 0, rdCount; + uint32_t remSize, manual_copy_size; + uint8_t *outputBuf = (uint8_t *) storage_addr; + const size_t blockSize = p_sdhandle->device->cfg.blockSize; + + VERBOSE("EMMC READ: dst=0x%lx, src=0x%lx, size=0x%lx\n", + storage_addr, mem_addr, bytes_to_read); + + if (storage_size < bytes_to_read) + /* Don't have sufficient storage to complete the operation */ + return 0; + + /* Range check non high capacity memory */ + if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) { + if (mem_addr > 0x80000000) + return 0; + } + + /* High capacity card use block address mode */ + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) { + blockAddr = (uint32_t) (mem_addr / blockSize); + offset = (uint32_t) (mem_addr - (blockAddr * blockSize)); + } else { + blockAddr = (uint32_t) (mem_addr / blockSize) * blockSize; + offset = (uint32_t) (mem_addr - blockAddr); + } + + remSize = bytes_to_read; + + rdCount = 0; + + /* Process first unaligned block of MAX_READ_LENGTH */ + if (offset > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, SD_MAX_READ_LENGTH)) { + + if (remSize < (blockSize - offset)) { + rdCount += remSize; + manual_copy_size = remSize; + remSize = 0; /* read is done */ + } else { + remSize -= (blockSize - offset); + rdCount += (blockSize - offset); + manual_copy_size = blockSize - offset; + } + + /* Check for overflow */ + if (manual_copy_size > storage_size || + (((uintptr_t)outputBuf + manual_copy_size) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow 1\n"); + return 0; + } + + memcpy(outputBuf, + (void *)((uintptr_t) + (emmc_global_buf_ptr->u.tempbuf + offset)), + manual_copy_size); + + /* Update Physical address */ + outputBuf += manual_copy_size; + + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr++; + else + blockAddr += blockSize; + } else { + return 0; + } + } + + while (remSize >= blockSize) { + + if (remSize >= SD_MAX_BLK_TRANSFER_LENGTH) + readLen = SD_MAX_BLK_TRANSFER_LENGTH; + else + readLen = (remSize / blockSize) * blockSize; + + /* Check for overflow */ + if ((rdCount + readLen) > storage_size || + (((uintptr_t) outputBuf + readLen) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow\n"); + return 0; + } + + if (!read_block(p_sdhandle, outputBuf, blockAddr, readLen)) { + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr += (readLen / blockSize); + else + blockAddr += readLen; + + remSize -= readLen; + rdCount += readLen; + + /* Update Physical address */ + outputBuf += readLen; + } else { + return 0; + } + } + + /* process the last unaligned block reading */ + if (remSize > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, SD_MAX_READ_LENGTH)) { + + rdCount += remSize; + /* Check for overflow */ + if (rdCount > storage_size || + (((uintptr_t) outputBuf + remSize) > + (storage_addr + storage_size))) { + ERROR("EMMC READ: Overflow\n"); + return 0; + } + + memcpy(outputBuf, + emmc_global_buf_ptr->u.tempbuf, remSize); + + /* Update Physical address */ + outputBuf += remSize; + } else { + rdCount = 0; + } + } + + return rdCount; +} + +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +static uint32_t sdio_write(struct sd_handle *p_sdhandle, uintptr_t mem_addr, + uintptr_t data_addr, size_t bytes_to_write) +{ + + uint32_t offset, blockAddr, writeLen, wtCount = 0; + uint32_t remSize, manual_copy_size = 0; + + uint8_t *inputBuf = (uint8_t *)data_addr; + + /* range check non high capacity memory */ + if ((p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) == 0) { + if (mem_addr > 0x80000000) + return 0; + } + + /* the high capacity card use block address mode */ + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) { + blockAddr = + (uint32_t)(mem_addr / p_sdhandle->device->cfg.blockSize); + offset = + (uint32_t)(mem_addr - + blockAddr * p_sdhandle->device->cfg.blockSize); + } else { + blockAddr = + ((uint32_t)mem_addr / p_sdhandle->device->cfg.blockSize) * + p_sdhandle->device->cfg.blockSize; + offset = (uint32_t) mem_addr - blockAddr; + } + + remSize = bytes_to_write; + + wtCount = 0; + + /* process first unaligned block */ + if (offset > 0) { + if (!read_block(p_sdhandle, emmc_global_buf_ptr->u.tempbuf, + blockAddr, p_sdhandle->device->cfg.blockSize)) { + + if (remSize < + (p_sdhandle->device->cfg.blockSize - offset)) + manual_copy_size = remSize; + else + manual_copy_size = + p_sdhandle->device->cfg.blockSize - offset; + + memcpy((void *)((uintptr_t) + (emmc_global_buf_ptr->u.tempbuf + offset)), + inputBuf, + manual_copy_size); + + /* Update Physical address */ + + if (!write_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, + p_sdhandle->device->cfg.blockSize)) { + + if (remSize < + (p_sdhandle->device->cfg.blockSize - + offset)) { + wtCount += remSize; + manual_copy_size = remSize; + remSize = 0; /* read is done */ + } else { + remSize -= + (p_sdhandle->device->cfg.blockSize - + offset); + wtCount += + (p_sdhandle->device->cfg.blockSize - + offset); + manual_copy_size = + p_sdhandle->device->cfg.blockSize - + offset; + } + + inputBuf += manual_copy_size; + + if (p_sdhandle->device->ctrl.ocr & + SD_CARD_HIGH_CAPACITY) + blockAddr++; + else + blockAddr += + p_sdhandle->device->cfg.blockSize; + } else + return 0; + } else { + return 0; + } + } + + /* process block writing */ + while (remSize >= p_sdhandle->device->cfg.blockSize) { + if (remSize >= SD_MAX_READ_LENGTH) { + writeLen = SD_MAX_READ_LENGTH; + } else { + writeLen = + (remSize / p_sdhandle->device->cfg.blockSize) * + p_sdhandle->device->cfg.blockSize; + } + + if (!write_block(p_sdhandle, inputBuf, blockAddr, writeLen)) { + if (p_sdhandle->device->ctrl.ocr & SD_CARD_HIGH_CAPACITY) + blockAddr += + (writeLen / + p_sdhandle->device->cfg.blockSize); + else + blockAddr += writeLen; + + remSize -= writeLen; + wtCount += writeLen; + inputBuf += writeLen; + } else { + return 0; + } + } + + /* process the last unaligned block reading */ + if (remSize > 0) { + if (!read_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, p_sdhandle->device->cfg.blockSize)) { + + memcpy(emmc_global_buf_ptr->u.tempbuf, + inputBuf, remSize); + + /* Update Physical address */ + + if (!write_block(p_sdhandle, + emmc_global_buf_ptr->u.tempbuf, + blockAddr, + p_sdhandle->device->cfg.blockSize)) { + wtCount += remSize; + inputBuf += remSize; + } else { + return 0; + } + } else { + wtCount = 0; + } + } + + return wtCount; +} +#endif + +/* + * Function to put the card in Ready state by sending CMD0 and CMD1 + */ +static int32_t bcm_emmc_card_ready_state(struct sd_handle *p_sdhandle) +{ + int32_t result = 0; + uint32_t argument = MMC_CMD_IDLE_RESET_ARG; /* Exit from Boot mode */ + + if (p_sdhandle) { + send_sdio_cmd(SD_CMD_GO_IDLE_STATE, argument, 0, NULL); + + result = reset_card(p_sdhandle); + if (result != SD_OK) { + EMMC_TRACE("eMMC Reset error\n"); + return SD_RESET_ERROR; + } + SD_US_DELAY(2000); + result = mmc_cmd1(p_sdhandle); + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/brcm/i2c/i2c.c b/arm-trusted-firmware/drivers/brcm/i2c/i2c.c new file mode 100644 index 0000000..2096a82 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/i2c/i2c.c @@ -0,0 +1,886 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +/* Max instances */ +#define MAX_I2C 2U + +/* Transaction error codes defined in Master command register (0x30) */ +#define MSTR_STS_XACT_SUCCESS 0U +#define MSTR_STS_LOST_ARB 1U +#define MSTR_STS_NACK_FIRST_BYTE 2U + /* NACK on a byte other than the first byte */ +#define MSTR_STS_NACK_NON_FIRST_BYTE 3U + +#define MSTR_STS_TTIMEOUT_EXCEEDED 4U +#define MSTR_STS_TX_TLOW_MEXT_EXCEEDED 5U +#define MSTR_STS_RX_TLOW_MEXT_EXCEEDED 6U + +/* SMBUS protocol values defined in register 0x30 */ +#define SMBUS_PROT_QUICK_CMD 0U +#define SMBUS_PROT_SEND_BYTE 1U +#define SMBUS_PROT_RECV_BYTE 2U +#define SMBUS_PROT_WR_BYTE 3U +#define SMBUS_PROT_RD_BYTE 4U +#define SMBUS_PROT_WR_WORD 5U +#define SMBUS_PROT_RD_WORD 6U +#define SMBUS_PROT_BLK_WR 7U +#define SMBUS_PROT_BLK_RD 8U +#define SMBUS_PROT_PROC_CALL 9U +#define SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL 10U + +/* Number can be changed later */ +#define BUS_BUSY_COUNT 100000U + +#define IPROC_I2C_INVALID_ADDR 0xFFU + +#define I2C_SMBUS_BLOCK_MAX 32U + +/* + * Enum to specify clock speed. The user will provide it during initialization. + * If needed, it can be changed dynamically + */ +typedef enum iproc_smb_clk_freq { + IPROC_SMB_SPEED_100KHz = 0, + IPROC_SMB_SPEED_400KHz = 1, + IPROC_SMB_SPEED_INVALID = 255 +} smb_clk_freq_t; + +/* Structure used to pass information to read/write functions. */ +struct iproc_xact_info { + /* Bus Identifier */ + uint32_t bus_id; + /* Device Address */ + uint8_t devaddr; + /* Passed by caller to send SMBus command cod e*/ + uint8_t command; + /* actual data passed by the caller */ + uint8_t *data; + /* Size of data buffer passed */ + uint32_t size; + /* Sent by caller specifying PEC, 10-bit addresses */ + uint16_t flags; + /* SMBus protocol to use to perform transaction */ + uint8_t smb_proto; + /* true if command field below is valid. Otherwise, false */ + uint32_t cmd_valid; +}; + +static const uintptr_t smbus_base_reg_addr[MAX_I2C] = { + SMBUS0_REGS_BASE, + SMBUS1_REGS_BASE +}; + +/* Function to read a value from specified register. */ +static uint32_t iproc_i2c_reg_read(uint32_t bus_id, unsigned long reg_addr) +{ + uint32_t val; + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + val = mmio_read_32(smbus + reg_addr); + VERBOSE("i2c %u: reg %p read 0x%x\n", bus_id, + (void *)(smbus + reg_addr), val); + return val; +} + +/* Function to write a value ('val') in to a specified register. */ +static void iproc_i2c_reg_write(uint32_t bus_id, + unsigned long reg_addr, + uint32_t val) +{ + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + mmio_write_32((smbus + reg_addr), val); + VERBOSE("i2c %u: reg %p wrote 0x%x\n", bus_id, + (void *)(smbus + reg_addr), val); +} + +/* Function to clear and set bits in a specified register. */ +static void iproc_i2c_reg_clearset(uint32_t bus_id, + unsigned long reg_addr, + uint32_t clear, + uint32_t set) +{ + uintptr_t smbus; + + smbus = smbus_base_reg_addr[bus_id]; + + mmio_clrsetbits_32((smbus + reg_addr), clear, set); + VERBOSE("i2c %u: reg %p clear 0x%x, set 0x%x\n", bus_id, + (void *)(smbus + reg_addr), clear, set); +} + +/* Function to dump all SMBUS register */ +#ifdef BCM_I2C_DEBUG +static int iproc_dump_i2c_regs(uint32_t bus_id) +{ + uint32_t regval; + + if (bus_id > MAX_I2C) { + return -1; + } + + INFO("----------------------------------------------\n"); + INFO("%s: Dumping SMBus %u registers...\n", __func__, bus_id); + + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + INFO("SMB_CFG_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG); + INFO("SMB_TIMGCFG_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_ADDR_REG); + INFO("SMB_ADDR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRFIFOCTL_REG); + INFO("SMB_MSTRFIFOCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVFIFOCTL_REG); + INFO("SMB_SLVFIFOCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_BITBANGCTL_REG); + INFO("SMB_BITBANGCTL_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + INFO("SMB_MSTRCMD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVCMD_REG); + INFO("SMB_SLVCMD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_EVTEN_REG); + INFO("SMB_EVTEN_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG); + INFO("SMB_EVTSTS_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATAWR_REG); + INFO("SMB_MSTRDATAWR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRDATARD_REG); + INFO("SMB_MSTRDATARD_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATAWR_REG); + INFO("SMB_SLVDATAWR_REG=0x%x\n", regval); + + regval = iproc_i2c_reg_read(bus_id, SMB_SLVDATARD_REG); + INFO("SMB_SLVDATARD_REG=0x%x\n", regval); + + INFO("----------------------------------------------\n"); + return 0; +} +#endif + +/* + * Function to ensure that the previous transaction was completed before + * initiating a new transaction. It can also be used in polling mode to + * check status of completion of a command + */ +static int iproc_i2c_startbusy_wait(uint32_t bus_id) +{ + uint32_t regval; + uint32_t retry = 0U; + + /* + * Check if an operation is in progress. During probe it won't be. + * Want to make sure that the transaction in progress is completed. + */ + do { + udelay(1U); + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + regval &= SMB_MSTRSTARTBUSYCMD_MASK; + if (retry++ > BUS_BUSY_COUNT) { + ERROR("%s: START_BUSY bit didn't clear, exiting\n", + __func__); + return -1; + } + + } while (regval != 0U); + + return 0; +} + +/* + * This function copies data to SMBus's Tx FIFO. Valid for write transactions + * info: Data to copy in to Tx FIFO. For read commands, the size should be + * set to zero by the caller + */ +static void iproc_i2c_write_trans_data(struct iproc_xact_info *info) +{ + uint32_t regval; + uint8_t devaddr; + uint32_t i; + uint32_t num_data_bytes = 0U; + +#ifdef BCM_I2C_DEBUG + INFO("%s:dev_addr=0x%x,cmd_valid=%d, cmd=0x%x, size=%u proto=%d\n", + __func__, info->devaddr, info->cmd_valid, info->command, + info->size, info->smb_proto); +#endif + /* Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n */ + devaddr = (info->devaddr << 1); + + /* + * Depending on the SMBus protocol, we need to write additional + * transaction data in to Tx FIFO. Refer to section 5.5 of SMBus spec + * for sequence for a transaction + */ + switch (info->smb_proto) { + case SMBUS_PROT_RECV_BYTE: + /* No additional data to be written */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U | SMB_MSTRWRSTS_MASK); + break; + case SMBUS_PROT_SEND_BYTE: + num_data_bytes = info->size; + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + break; + case SMBUS_PROT_RD_BYTE: + case SMBUS_PROT_RD_WORD: + case SMBUS_PROT_BLK_RD: + /* Write slave address with R/W~ set (bit #0) */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U); + break; + case SMBUS_PROT_BLK_WR_BLK_RD_PROC_CALL: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr | 0x1U | SMB_MSTRWRSTS_MASK); + break; + case SMBUS_PROT_WR_BYTE: + case SMBUS_PROT_WR_WORD: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + /* + * No additional bytes to be written. Data portion is written + * in the 'for' loop below + */ + num_data_bytes = info->size; + break; + case SMBUS_PROT_BLK_WR: + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + devaddr); + /* 3rd byte is byte count */ + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + info->size); + num_data_bytes = info->size; + break; + default: + return; + } + + /* If the protocol needs command code, copy it */ + if (info->cmd_valid) { + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + info->command); + } + + /* + * Copy actual data from caller. In general, for reads, + * no data is copied. + */ + for (i = 0U; num_data_bytes; --num_data_bytes, i++) { + /* For the last byte, set MASTER_WR_STATUS bit */ + regval = (num_data_bytes == 1U) ? + info->data[i] | SMB_MSTRWRSTS_MASK : info->data[i]; + iproc_i2c_reg_write(info->bus_id, SMB_MSTRDATAWR_REG, + regval); + } +} + +/* + * This function writes to the master command register and + * then polls for completion + */ +static int iproc_i2c_write_master_command(uint32_t mastercmd, + struct iproc_xact_info *info) +{ + uint32_t retry = 0U; + uint32_t regval; + + iproc_i2c_reg_write(info->bus_id, SMB_MSTRCMD_REG, mastercmd); + + /* Check for Master Busy status */ + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG); + while ((regval & SMB_MSTRSTARTBUSYCMD_MASK) != 0U) { + udelay(1U); + if (retry++ > BUS_BUSY_COUNT) { + ERROR("%s: START_BUSY bit didn't clear, exiting\n", + __func__); + return -1; + } + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRCMD_REG); + } + + /* If start_busy bit cleared, check if there are any errors */ + if (!(regval & SMB_MSTRSTARTBUSYCMD_MASK)) { + /* start_busy bit cleared, check master_status field now */ + regval &= SMB_MSTRSTS_MASK; + regval >>= SMB_MSTRSTS_SHIFT; + if (regval != MSTR_STS_XACT_SUCCESS) { + /* Error We can flush Tx FIFO here */ + ERROR("%s: ERROR: %u exiting\n", __func__, regval); + return -1; + } + } + return 0; + +} +/* Function to initiate data send and verify completion status */ +static int iproc_i2c_data_send(struct iproc_xact_info *info) +{ + int rc; + uint32_t mastercmd; + + /* Make sure the previous transaction completed */ + rc = iproc_i2c_startbusy_wait(info->bus_id); + + if (rc < 0) { + WARN("%s: Send: bus is busy, exiting\n", __func__); + return rc; + } + /* Write transaction bytes to Tx FIFO */ + iproc_i2c_write_trans_data(info); + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK; + + if (iproc_i2c_write_master_command(mastercmd, info)) { + return -1; + } + + return 0; +} + +/* + * Function to initiate data receive, verify completion status, + * and read from SMBUS Read FIFO + */ +static int iproc_i2c_data_recv(struct iproc_xact_info *info, + uint32_t *num_bytes_read) +{ + int rc; + uint32_t mastercmd; + uint32_t regval; + + /* Make sure the previous transaction completed */ + rc = iproc_i2c_startbusy_wait(info->bus_id); + + if (rc < 0) { + WARN("%s: Receive: Bus is busy, exiting\n", __func__); + return rc; + } + + /* Program all transaction bytes into master Tx FIFO */ + iproc_i2c_write_trans_data(info); + + /* + * Program master command register (0x30) with protocol type and set + * start_busy_command bit to initiate the write transaction + */ + mastercmd = (info->smb_proto << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK | info->size; + + if (iproc_i2c_write_master_command(mastercmd, info)) { + return -1; + } + + /* Read received byte(s), after TX out address etc */ + regval = iproc_i2c_reg_read(info->bus_id, SMB_MSTRDATARD_REG); + + /* For block read, protocol (hw) returns byte count,as the first byte */ + if (info->smb_proto == SMBUS_PROT_BLK_RD) { + uint32_t i; + + *num_bytes_read = regval & SMB_MSTRRDDATA_MASK; + /* + * Limit to reading a max of 32 bytes only; just a safeguard. + * If # bytes read is a number > 32, check transaction set up, + * and contact hw engg. + * Assumption: PEC is disabled + */ + for (i = 0U; (i < *num_bytes_read) && + (i < I2C_SMBUS_BLOCK_MAX); i++) { + /* Read Rx FIFO for data bytes */ + regval = iproc_i2c_reg_read(info->bus_id, + SMB_MSTRDATARD_REG); + info->data[i] = regval & SMB_MSTRRDDATA_MASK; + } + } else { + /* 1 Byte data */ + *info->data = regval & SMB_MSTRRDDATA_MASK; + *num_bytes_read = 1U; + } + + return 0; +} + +/* + * This function set clock frequency for SMBus block. As per hardware + * engineering, the clock frequency can be changed dynamically. + */ +static int iproc_i2c_set_clk_freq(uint32_t bus_id, smb_clk_freq_t freq) +{ + uint32_t val; + + switch (freq) { + case IPROC_SMB_SPEED_100KHz: + val = 0U; + break; + case IPROC_SMB_SPEED_400KHz: + val = 1U; + break; + default: + return -1; + } + + iproc_i2c_reg_clearset(bus_id, SMB_TIMGCFG_REG, + SMB_TIMGCFG_MODE400_MASK, + val << SMB_TIMGCFG_MODE400_SHIFT); + + return 0; +} + +/* Helper function to fill the iproc_xact_info structure */ +static void iproc_i2c_fill_info(struct iproc_xact_info *info, uint32_t bus_id, + uint8_t devaddr, uint8_t cmd, uint8_t *value, + uint8_t smb_proto, uint32_t cmd_valid) +{ + info->bus_id = bus_id; + info->devaddr = devaddr; + info->command = (uint8_t)cmd; + info->smb_proto = smb_proto; + info->data = value; + info->size = 1U; + info->flags = 0U; + info->cmd_valid = cmd_valid; +} + +/* This function initializes the SMBUS */ +static void iproc_i2c_init(uint32_t bus_id, int speed) +{ + uint32_t regval; + +#ifdef BCM_I2C_DEBUG + INFO("%s: Enter Init\n", __func__); +#endif + + /* Put controller in reset */ + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + regval |= BIT(SMB_CFG_RST_SHIFT); + regval &= ~(BIT(SMB_CFG_SMBEN_SHIFT)); + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + + /* Wait 100 usec per spec */ + udelay(100U); + + /* Bring controller out of reset */ + regval &= ~(BIT(SMB_CFG_RST_SHIFT)); + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + + /* + * Flush Tx, Rx FIFOs. Note we are setting the Rx FIFO threshold to 0. + * May be OK since we are setting RX_EVENT and RX_FIFO_FULL interrupts + */ + regval = SMB_MSTRRXFIFOFLSH_MASK | SMB_MSTRTXFIFOFLSH_MASK; + iproc_i2c_reg_write(bus_id, SMB_MSTRFIFOCTL_REG, regval); + + /* + * Enable SMbus block. Note, we are setting MASTER_RETRY_COUNT to zero + * since there will be only one master + */ + + regval = iproc_i2c_reg_read(bus_id, SMB_CFG_REG); + regval |= SMB_CFG_SMBEN_MASK; + iproc_i2c_reg_write(bus_id, SMB_CFG_REG, regval); + /* Wait a minimum of 50 Usec, as per SMB hw doc. But we wait longer */ + mdelay(10U); + + /* If error then set default speed */ + if (i2c_set_bus_speed(bus_id, speed)) { + i2c_set_bus_speed(bus_id, I2C_SPEED_DEFAULT); + } + + /* Disable intrs */ + regval = 0x0U; + iproc_i2c_reg_write(bus_id, SMB_EVTEN_REG, regval); + + /* Clear intrs (W1TC) */ + regval = iproc_i2c_reg_read(bus_id, SMB_EVTSTS_REG); + iproc_i2c_reg_write(bus_id, SMB_EVTSTS_REG, regval); + +#ifdef BCM_I2C_DEBUG + iproc_dump_i2c_regs(bus_id); + + INFO("%s: Exit Init Successfully\n", __func__); +#endif +} + +/* + * Function Name: i2c_init + * + * Description: + * This function initializes the SMBUS. + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_init(uint32_t bus_id, int speed) +{ + if (bus_id > MAX_I2C) { + WARN("%s: Invalid Bus %u\n", __func__, bus_id); + return -1; + } + + iproc_i2c_init(bus_id, speed); + return 0U; +} + +/* + * Function Name: i2c_probe + * + * Description: + * This function probes the I2C bus for the existence of the specified + * device. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_probe(uint32_t bus_id, uint8_t devaddr) +{ + uint32_t regval; + int rc; + + /* + * i2c_init() Initializes internal regs, disable intrs (and then clear intrs), + * set fifo thresholds, etc. + * Shift devaddr by 1 bit since SMBus uses the low bit[0] for R/W_n + */ + regval = (devaddr << 1U); + iproc_i2c_reg_write(bus_id, SMB_MSTRDATAWR_REG, regval); + + regval = ((SMBUS_PROT_QUICK_CMD << SMB_MSTRSMBUSPROTO_SHIFT) | + SMB_MSTRSTARTBUSYCMD_MASK); + iproc_i2c_reg_write(bus_id, SMB_MSTRCMD_REG, regval); + + rc = iproc_i2c_startbusy_wait(bus_id); + + if (rc < 0) { + WARN("%s: Probe: bus is busy, exiting\n", __func__); + return rc; + } + + regval = iproc_i2c_reg_read(bus_id, SMB_MSTRCMD_REG); + if (((regval & SMB_MSTRSTS_MASK) >> SMB_MSTRSTS_SHIFT) == 0) + VERBOSE("i2c device address: 0x%x\n", devaddr); + else + return -1; + +#ifdef BCM_I2C_DEBUG + iproc_dump_i2c_regs(bus_id); +#endif + return 0; +} + +/* + * Function Name: i2c_recv_byte + * + * Description: + * This function reads I2C data from a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Read + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value) +{ + int rc; + struct iproc_xact_info info; + uint32_t num_bytes_read = 0; + + iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, value, + SMBUS_PROT_RECV_BYTE, 0U); + + /* Refer to i2c_smbus_read_byte for params passed. */ + rc = iproc_i2c_data_recv(&info, &num_bytes_read); + + if (rc < 0) { + printf("%s: %s error accessing device 0x%x\n", + __func__, "Read", devaddr); + } + + return rc; +} + +/* + * Function Name: i2c_send_byte + * + * Description: + * This function send I2C data to a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Send + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value) +{ + int rc; + struct iproc_xact_info info; + + iproc_i2c_fill_info(&info, bus_id, devaddr, 0U, &value, + SMBUS_PROT_SEND_BYTE, 0U); + + /* Refer to i2c_smbus_write_byte params passed. */ + rc = iproc_i2c_data_send(&info); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Write", devaddr); + } + + return rc; +} + +/* Helper function to read a single byte */ +static int i2c_read_byte(uint32_t bus_id, + uint8_t devaddr, + uint8_t regoffset, + uint8_t *value) +{ + int rc; + struct iproc_xact_info info; + uint32_t num_bytes_read = 0U; + + iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, value, + SMBUS_PROT_RD_BYTE, 1U); + + /* Refer to i2c_smbus_read_byte for params passed. */ + rc = iproc_i2c_data_recv(&info, &num_bytes_read); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Read", devaddr); + } + return rc; +} + +/* + * Function Name: i2c_read + * + * Description: + * This function reads I2C data from a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_read(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len) +{ + uint32_t i; + + if (alen > 1) { + WARN("I2C read: addr len %d not supported\n", alen); + return -1; + } + + if (addr + len > 256) { + WARN("I2C read: address out of range\n"); + return -1; + } + + for (i = 0U; i < len; i++) { + if (i2c_read_byte(bus_id, devaddr, addr + i, &buffer[i])) { + ERROR("I2C read: I/O error\n"); + iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id)); + return -1; + } + } + + return 0; +} + +/* Helper function to write a single byte */ +static int i2c_write_byte(uint32_t bus_id, + uint8_t devaddr, + uint8_t regoffset, + uint8_t value) +{ + int rc; + struct iproc_xact_info info; + + iproc_i2c_fill_info(&info, bus_id, devaddr, regoffset, &value, + SMBUS_PROT_WR_BYTE, 1U); + + /* Refer to i2c_smbus_write_byte params passed. */ + rc = iproc_i2c_data_send(&info); + + if (rc < 0) { + ERROR("%s: %s error accessing device 0x%x\n", + __func__, "Write", devaddr); + return -1; + } + + return 0; +} + +/* + * Function Name: i2c_write + * + * Description: + * This function write I2C data to a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_write(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len) +{ + uint32_t i; + + if (alen > 1) { + WARN("I2C write: addr len %d not supported\n", alen); + return -1; + } + + if (addr + len > 256U) { + WARN("I2C write: address out of range\n"); + return -1; + } + + for (i = 0U; i < len; i++) { + if (i2c_write_byte(bus_id, devaddr, addr + i, buffer[i])) { + ERROR("I2C write: I/O error\n"); + iproc_i2c_init(bus_id, i2c_get_bus_speed(bus_id)); + return -1; + } + } + return 0; +} + +/* + * Function Name: i2c_set_bus_speed + * + * Description: + * This function configures the SMBUS speed + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed) +{ + switch (speed) { + case I2C_SPEED_100KHz: + iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_100KHz); + break; + + case I2C_SPEED_400KHz: + iproc_i2c_set_clk_freq(bus_id, IPROC_SMB_SPEED_400KHz); + break; + + default: + return -1; + } + return 0; +} + +/* + * Function Name: i2c_get_bus_speed + * + * Description: + * This function returns the SMBUS speed. + * + * Parameters: + * bus_id - I2C bus ID + * + * Return: + * Bus speed in Hz, 0 on failure + */ +uint32_t i2c_get_bus_speed(uint32_t bus_id) +{ + uint32_t regval; + uint32_t retval = 0U; + + regval = iproc_i2c_reg_read(bus_id, SMB_TIMGCFG_REG); + regval &= SMB_TIMGCFG_MODE400_MASK; + regval >>= SMB_TIMGCFG_MODE400_SHIFT; + + switch (regval) { + case IPROC_SMB_SPEED_100KHz: + retval = I2C_SPEED_100KHz; + break; + + case IPROC_SMB_SPEED_400KHz: + retval = I2C_SPEED_400KHz; + break; + + default: + break; + } + return retval; +} + diff --git a/arm-trusted-firmware/drivers/brcm/iproc_gpio.c b/arm-trusted-firmware/drivers/brcm/iproc_gpio.c new file mode 100644 index 0000000..f61a3bc --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/iproc_gpio.c @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define IPROC_GPIO_DATA_IN_OFFSET 0x00 +#define IPROC_GPIO_DATA_OUT_OFFSET 0x04 +#define IPROC_GPIO_OUT_EN_OFFSET 0x08 +#define IPROC_GPIO_PAD_RES_OFFSET 0x34 +#define IPROC_GPIO_RES_EN_OFFSET 0x38 + +#define PINMUX_OFFSET(gpio) ((gpio) * 4) +#define PINCONF_OFFSET(gpio) ((gpio) * 4) +#define PINCONF_PULL_UP BIT(4) +#define PINCONF_PULL_DOWN BIT(5) + +/* + * iProc GPIO bank is always 0x200 per bank, + * with each bank supporting 32 GPIOs. + */ +#define GPIO_BANK_SIZE 0x200 +#define NGPIOS_PER_BANK 32 +#define GPIO_BANK(pin) ((pin) / NGPIOS_PER_BANK) + +#define IPROC_GPIO_REG(pin, reg) (GPIO_BANK(pin) * GPIO_BANK_SIZE + (reg)) +#define IPROC_GPIO_SHIFT(pin) ((pin) % NGPIOS_PER_BANK) + +#define MUX_GPIO_MODE 0x3 + +/* + * @base: base address of the gpio controller + * @pinconf_base: base address of the pinconf + * @pinmux_base: base address of the mux controller + * @nr_gpios: maxinum number of GPIOs + */ +struct iproc_gpio { + uintptr_t base; + uintptr_t pinconf_base; + uintptr_t pinmux_base; + int nr_gpios; +}; + +static struct iproc_gpio iproc_gpio; + +static void gpio_set_bit(uintptr_t base, unsigned int reg, int gpio, bool set) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + uint32_t val; + + val = mmio_read_32(base + offset); + if (set) + val |= BIT(shift); + else + val &= ~BIT(shift); + + mmio_write_32(base + offset, val); +} + +static bool gpio_get_bit(uintptr_t base, unsigned int reg, int gpio) +{ + unsigned int offset = IPROC_GPIO_REG(gpio, reg); + unsigned int shift = IPROC_GPIO_SHIFT(gpio); + + return !!(mmio_read_32(base + offset) & BIT(shift)); +} + +static void mux_to_gpio(struct iproc_gpio *g, int gpio) +{ + /* mux pad to GPIO if IOPAD configuration is mandatory */ + if (g->pinmux_base) + mmio_write_32(g->pinmux_base + PINMUX_OFFSET(gpio), + MUX_GPIO_MODE); +} + +static void set_direction(int gpio, int direction) +{ + struct iproc_gpio *g = &iproc_gpio; + bool dir = (direction == GPIO_DIR_OUT) ? true : false; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, dir); +} + +static int get_direction(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + int dir; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + dir = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ? + GPIO_DIR_OUT : GPIO_DIR_IN; + + return dir; +} + +static int get_value(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + unsigned int offset; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + + /* + * If GPIO is configured as output, read from the GPIO_OUT register; + * otherwise, read from the GPIO_IN register + */ + offset = gpio_get_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio) ? + IPROC_GPIO_DATA_OUT_OFFSET : IPROC_GPIO_DATA_IN_OFFSET; + + return gpio_get_bit(g->base, offset, gpio); +} + +static void set_value(int gpio, int val) +{ + struct iproc_gpio *g = &iproc_gpio; + + assert(gpio < g->nr_gpios); + + mux_to_gpio(g, gpio); + + /* make sure GPIO is configured to output, and then set the value */ + gpio_set_bit(g->base, IPROC_GPIO_OUT_EN_OFFSET, gpio, true); + gpio_set_bit(g->base, IPROC_GPIO_DATA_OUT_OFFSET, gpio, !!(val)); +} + +static int get_pull(int gpio) +{ + struct iproc_gpio *g = &iproc_gpio; + uint32_t val; + + assert(gpio < g->nr_gpios); + mux_to_gpio(g, gpio); + + /* when there's a valid pinconf_base, use it */ + if (g->pinconf_base) { + val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio)); + + if (val & PINCONF_PULL_UP) + return GPIO_PULL_UP; + else if (val & PINCONF_PULL_DOWN) + return GPIO_PULL_DOWN; + else + return GPIO_PULL_NONE; + } + + /* no pinconf_base. fall back to GPIO internal pull control */ + if (!gpio_get_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio)) + return GPIO_PULL_NONE; + + return gpio_get_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio) ? + GPIO_PULL_UP : GPIO_PULL_DOWN; +} + +static void set_pull(int gpio, int pull) +{ + struct iproc_gpio *g = &iproc_gpio; + uint32_t val; + + assert(gpio < g->nr_gpios); + mux_to_gpio(g, gpio); + + /* when there's a valid pinconf_base, use it */ + if (g->pinconf_base) { + val = mmio_read_32(g->pinconf_base + PINCONF_OFFSET(gpio)); + + if (pull == GPIO_PULL_NONE) { + val &= ~(PINCONF_PULL_UP | PINCONF_PULL_DOWN); + } else if (pull == GPIO_PULL_UP) { + val |= PINCONF_PULL_UP; + val &= ~PINCONF_PULL_DOWN; + } else if (pull == GPIO_PULL_DOWN) { + val |= PINCONF_PULL_DOWN; + val &= ~PINCONF_PULL_UP; + } else { + return; + } + mmio_write_32(g->pinconf_base + PINCONF_OFFSET(gpio), val); + } + + /* no pinconf_base. fall back to GPIO internal pull control */ + if (pull == GPIO_PULL_NONE) { + gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, false); + return; + } + + /* enable pad register and pull up or down */ + gpio_set_bit(g->base, IPROC_GPIO_RES_EN_OFFSET, gpio, true); + gpio_set_bit(g->base, IPROC_GPIO_PAD_RES_OFFSET, gpio, + !!(pull == GPIO_PULL_UP)); +} + +const gpio_ops_t iproc_gpio_ops = { + .get_direction = get_direction, + .set_direction = set_direction, + .get_value = get_value, + .set_value = set_value, + .get_pull = get_pull, + .set_pull = set_pull, +}; + +void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base) +{ + iproc_gpio.base = base; + iproc_gpio.nr_gpios = nr_gpios; + + /* pinmux/pinconf base is optional for some SoCs */ + if (pinmux_base) + iproc_gpio.pinmux_base = pinmux_base; + + if (pinconf_base) + iproc_gpio.pinconf_base = pinconf_base; + + gpio_init(&iproc_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/brcm/mdio/mdio.c b/arm-trusted-firmware/drivers/brcm/mdio/mdio.c new file mode 100644 index 0000000..1cf9d66 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/mdio/mdio.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include + +#include +#include +#include +#include + +static int mdio_op_status(uint32_t result) +{ + uint32_t timeout = 1000000U; /* loop for 1s */ + uint32_t val; + + do { + val = mmio_read_32(CMIC_MIIM_STAT); + if ((val & MDIO_STAT_DONE) == result) { + return 0; + } + + udelay(1U); + } while (timeout-- != 0U); + return -1; +} + +static int mdio_op(uint16_t busid, uint16_t phyid, uint32_t reg, + uint16_t val, uint8_t op) +{ + uint32_t param; + int ret; + + mmio_write_32(CMIC_MIIM_CTRL, 0U); + ret = mdio_op_status(0U); + if (ret != 0) { + goto err; + } + + param = 0U; + param |= 1U << MDIO_PARAM_INTERNAL_SEL; + param |= (busid & MDIO_PARAM_BUSID_MASK) << MDIO_PARAM_BUSID; + param |= (phyid & MDIO_PARAM_PHYID_MASK) << MDIO_PARAM_PHYID; + param |= (val & MDIO_PARAM_DATA_MASK) << MDIO_PARAM_DATA; + + mmio_write_32(CMIC_MIIM_PARAM, param); + + mmio_write_32(CMIC_MIIM_ADDRESS, reg); + + mmio_write_32(CMIC_MIIM_CTRL, op); + + ret = mdio_op_status(1U); + if (ret != 0) { + goto err; + } + + if (op == MDIO_CTRL_READ_OP) { + ret = mmio_read_32(CMIC_MIIM_READ_DATA) & MDIO_READ_DATA_MASK; + } +err: + return ret; +} + +int mdio_write(uint16_t busid, uint16_t phyid, uint32_t reg, uint16_t val) +{ + int ret; + + ret = mdio_op(busid, phyid, reg, val, MDIO_CTRL_WRITE_OP); + if (ret == -1) { + INFO("MDIO write fail\n"); + } + return ret; +} + +int mdio_read(uint16_t busid, uint16_t phyid, uint32_t reg) +{ + int ret; + + ret = mdio_op(busid, phyid, reg, 0U, MDIO_CTRL_READ_OP); + if (ret == -1) { + INFO("MDIO read fail\n"); + } + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/ocotp.c b/arm-trusted-firmware/drivers/brcm/ocotp.c new file mode 100644 index 0000000..6ff8554 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/ocotp.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#define OTP_MAP 2 +#define OTP_NUM_WORDS 2048 +/* + * # of tries for OTP Status. The time to execute a command varies. The slowest + * commands are writes which also vary based on the # of bits turned on. Writing + * 0xffffffff takes ~3800 us. + */ +#define OTPC_RETRIES_US 5000 + +/* Sequence to enable OTP program */ +#define OTPC_PROG_EN_SEQ { 0xf, 0x4, 0x8, 0xd } + +/* OTPC Commands */ +#define OTPC_CMD_READ 0x0 +#define OTPC_CMD_OTP_PROG_ENABLE 0x2 +#define OTPC_CMD_OTP_PROG_DISABLE 0x3 +#define OTPC_CMD_PROGRAM 0x8 +#define OTPC_CMD_ECC 0x10 +#define OTPC_ECC_ADDR 0x1A +#define OTPC_ECC_VAL 0x00EC0000 + +/* OTPC Status Bits */ +#define OTPC_STAT_CMD_DONE BIT(1) +#define OTPC_STAT_PROG_OK BIT(2) + +/* OTPC register definition */ +#define OTPC_MODE_REG_OFFSET 0x0 +#define OTPC_MODE_REG_OTPC_MODE 0 +#define OTPC_COMMAND_OFFSET 0x4 +#define OTPC_COMMAND_COMMAND_WIDTH 6 +#define OTPC_CMD_START_OFFSET 0x8 +#define OTPC_CMD_START_START 0 +#define OTPC_CPU_STATUS_OFFSET 0xc +#define OTPC_CPUADDR_REG_OFFSET 0x28 +#define OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH 16 +#define OTPC_CPU_WRITE_REG_OFFSET 0x2c + +#define OTPC_CMD_MASK (BIT(OTPC_COMMAND_COMMAND_WIDTH) - 1) +#define OTPC_ADDR_MASK (BIT(OTPC_CPUADDR_REG_OTPC_CPU_ADDRESS_WIDTH) - 1) + +#define OTPC_MODE_REG OCOTP_REGS_BASE + +struct chip_otp_cfg { + uint32_t base; + uint32_t num_words; +}; + +struct chip_otp_cfg ocotp_cfg = { + .base = OTPC_MODE_REG, + .num_words = 2048, +}; + +struct otpc_priv { + uint32_t base; + struct otpc_map *map; + int size; + int state; +}; + +struct otpc_priv otpc_info; + +static inline void set_command(uint32_t base, uint32_t command) +{ + mmio_write_32(base + OTPC_COMMAND_OFFSET, command & OTPC_CMD_MASK); +} + +static inline void set_cpu_address(uint32_t base, uint32_t addr) +{ + mmio_write_32(base + OTPC_CPUADDR_REG_OFFSET, addr & OTPC_ADDR_MASK); +} + +static inline void set_start_bit(uint32_t base) +{ + mmio_write_32(base + OTPC_CMD_START_OFFSET, 1 << OTPC_CMD_START_START); +} + +static inline void reset_start_bit(uint32_t base) +{ + mmio_write_32(base + OTPC_CMD_START_OFFSET, 0); +} + +static inline void write_cpu_data(uint32_t base, uint32_t value) +{ + mmio_write_32(base + OTPC_CPU_WRITE_REG_OFFSET, value); +} + +static int poll_cpu_status(uint32_t base, uint32_t value) +{ + uint32_t status; + uint32_t retries; + + for (retries = 0; retries < OTPC_RETRIES_US; retries++) { + status = mmio_read_32(base + OTPC_CPU_STATUS_OFFSET); + if (status & value) + break; + udelay(1); + } + if (retries == OTPC_RETRIES_US) + return -1; + + return 0; +} + +static int bcm_otpc_ecc(uint32_t enable) +{ + struct otpc_priv *priv = &otpc_info; + int ret; + + set_command(priv->base, OTPC_CMD_ECC); + set_cpu_address(priv->base, OTPC_ECC_ADDR); + + if (!enable) + write_cpu_data(priv->base, OTPC_ECC_VAL); + else + write_cpu_data(priv->base, ~OTPC_ECC_VAL); + + set_start_bit(priv->base); + ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); + if (ret) { + ERROR("otp ecc op error: 0x%x", ret); + return -1; + } + reset_start_bit(priv->base); + + return 0; +} + +/* + * bcm_otpc_read read otp data in the size of 8 byte rows. + * bytes has to be the multiple of 8. + * return -1 in error case, return read bytes in success. + */ +int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes, + uint32_t ecc_flag) +{ + struct otpc_priv *priv = &otpc_info; + uint32_t *buf = val; + uint32_t bytes_read; + uint32_t address = offset / priv->map->word_size; + int i, ret; + + if (!priv->state) { + ERROR("OCOTP read failed\n"); + return -1; + } + + bcm_otpc_ecc(ecc_flag); + + for (bytes_read = 0; (bytes_read + priv->map->word_size) <= bytes;) { + set_command(priv->base, OTPC_CMD_READ); + set_cpu_address(priv->base, address++); + set_start_bit(priv->base); + ret = poll_cpu_status(priv->base, OTPC_STAT_CMD_DONE); + if (ret) { + ERROR("otp read error: 0x%x", ret); + return -1; + } + + for (i = 0; i < priv->map->otpc_row_size; i++) { + *buf++ = mmio_read_32(priv->base + + priv->map->data_r_offset[i]); + bytes_read += sizeof(*buf); + } + + reset_start_bit(priv->base); + } + + return bytes_read; +} + +int bcm_otpc_init(struct otpc_map *map) +{ + struct otpc_priv *priv; + + priv = &otpc_info; + priv->base = ocotp_cfg.base; + priv->map = map; + + priv->size = 4 * ocotp_cfg.num_words; + + /* Enable CPU access to OTPC. */ + mmio_setbits_32(priv->base + OTPC_MODE_REG_OFFSET, + BIT(OTPC_MODE_REG_OTPC_MODE)); + reset_start_bit(priv->base); + priv->state = 1; + VERBOSE("OTPC Initialization done\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/rng.c b/arm-trusted-firmware/drivers/brcm/rng.c new file mode 100644 index 0000000..ee2e656 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/rng.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define RNG_CTRL_REG (RNG_BASE_ADDR + 0x00) +#define RNG_CTRL_MASK 0x00001FFF +#define RNG_CTRL_ENABLE 0x00000001 +#define RNG_CTRL_DISABLE 0x00000000 + +#define RNG_SOFT_RESET_REG (RNG_BASE_ADDR + 0x04) +#define RNG_SOFT_RESET_MASK 0x00000001 + +#define RNG_FIFO_DATA_REG (RNG_BASE_ADDR + 0x20) + +#define RNG_FIFO_COUNT_REG (RNG_BASE_ADDR + 0x24) +#define RNG_FIFO_COUNT_MASK 0x000000FF + +#define RNG_FIFO_WORDS_MAX 16 +#define MAX_WAIT_COUNT_50US 20000 + + +static void rng_reset(void) +{ + /* Disable RBG */ + mmio_clrbits_32(RNG_CTRL_REG, RNG_CTRL_MASK); + + /* Reset RNG and RBG */ + mmio_setbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); + + /* Take all out of reset */ + mmio_clrbits_32(RNG_SOFT_RESET_REG, RNG_SOFT_RESET_MASK); +} + +static void rng_enable(void) +{ + /* Setup RNG. */ + mmio_clrsetbits_32(RNG_CTRL_REG, RNG_CTRL_MASK, RNG_CTRL_ENABLE); +} + +int rng_init(void) +{ + rng_reset(); + + rng_enable(); + + return 0; +} + +int rng_read(uint32_t *p_out, uint32_t *words_read) +{ + uint32_t available_words; + uint32_t i; + uint32_t word_processed = 0; + uint32_t wait_count = MAX_WAIT_COUNT_50US; + + if (*words_read == 0) { + ERROR("RNG Parameter: No word requested\n"); + return -1; + } + + do { + available_words = mmio_read_32(RNG_FIFO_COUNT_REG); + available_words &= RNG_FIFO_COUNT_MASK; + + if (available_words != 0) { + available_words = MIN(available_words, + *words_read - word_processed); + + for (i = 0; i < available_words; i++) + p_out[word_processed + i] = + mmio_read_32(RNG_FIFO_DATA_REG); + word_processed += available_words; + } else { + udelay(50); + } + + if (word_processed == *words_read) + break; + + } while (--wait_count); + + if (word_processed != *words_read) { + ERROR("RNG Timeout: requested %d word(s) got %d\n", + *words_read, word_processed); + *words_read = word_processed; + return -1; + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/scp.c b/arm-trusted-firmware/drivers/brcm/scp.c new file mode 100644 index 0000000..6196073 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/scp.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* MCU binary image structure:

+ * + * Header structure: + * + * + * { }* + * + * + * MCU data () consists of several sections of code/data, to be + * installed (copied) into MCU memories. + * Header (
) gives information about sections contained in . + * + * The installer code iterates over sections in MCU binary. + * For each section, it copies the section into MCU memory. + * + * The header contains: + * - - 32-bit magic number to mark header start + * - - number of sections in + * - tuples. Each tuple describes a section. + * A tuple contains three 32-bit words. + * - - 32-bit magic number to mark header end + * + * Each section is describes by a tuple, consisting of three 32-bit words: + * - offset of section within MCU binary (relative to beginning of ) + * - section size (in bytes) in MCU binary + * - target address (in MCU memory). Section is copied to this location. + * + * All fields are 32-bit unsigned integers in little endian format. + * All sizes are assumed to be 32-bit aligned. + */ + +#define SCP_BIN_HEADER_MAGIC_START 0xfa587D01 +#define SCP_BIN_HEADER_MAGIC_END 0xf3e06a85 + +int download_scp_patch(void *image, unsigned int image_size) +{ + unsigned int *pheader = (unsigned int *)(image); + unsigned int header_size; + unsigned char *pdata; + void *dest; + unsigned int num_sections; + unsigned int section_src_offset; + unsigned int section_size; + + if (pheader && (pheader[0] != SCP_BIN_HEADER_MAGIC_START)) { + ERROR("SCP: Could not find SCP header.\n"); + return -1; + } + + num_sections = pheader[1]; + INFO("...Number of sections: %d\n", num_sections); + header_size = 4 * (1 + 1 + 3 * num_sections + 1); + + if (image_size < header_size) { + ERROR("SCP: Wrong size.\n"); + return -1; + } + + if (*(pheader + header_size/4 - 1) != SCP_BIN_HEADER_MAGIC_END) { + ERROR("SCP: Could not find SCP footer.\n"); + return -1; + } + + VERBOSE("SCP image header validated successfully\n"); + pdata = (unsigned char *)pheader + header_size; + + for (pheader += 2; num_sections > 0; num_sections--) { + + section_src_offset = pheader[0]; + section_size = pheader[1]; + dest = (void *)(unsigned long)pheader[2]; + + INFO("section: src:0x%x, size:%d, dst:0x%x\n", + section_src_offset, section_size, pheader[2]); + + if ((section_src_offset + section_size) > image_size) { + ERROR("SCP: Section points to outside of patch.\n"); + return -1; + } + + /* copy from source to target section */ + memcpy(dest, pdata + section_src_offset, section_size); + flush_dcache_range((uintptr_t)dest, section_size); + + /* next section */ + pheader += 3; + } + return 0; +} diff --git a/arm-trusted-firmware/drivers/brcm/sotp.c b/arm-trusted-firmware/drivers/brcm/sotp.c new file mode 100644 index 0000000..63c4820 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/sotp.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#ifdef USE_SOFT_SOTP +extern uint64_t soft_sotp[]; +#endif + +#define SOTP_PROG_CONTROL (SOTP_REGS_OTP_BASE + 0x0000) +#define SOTP_PROG_CONTROL__OTP_CPU_MODE_EN 15 +#define SOTP_PROG_CONTROL__OTP_DISABLE_ECC 9 +#define SOTP_PROG_CONTROL__OTP_ECC_WREN 8 + +#define SOTP_WRDATA_0 (SOTP_REGS_OTP_BASE + 0x0004) +#define SOTP_WRDATA_1 (SOTP_REGS_OTP_BASE + 0x0008) + +#define SOTP_ADDR (SOTP_REGS_OTP_BASE + 0x000c) +#define SOTP_ADDR__OTP_ROW_ADDR_R 6 +#define SOTP_ADDR_MASK 0x3FF + +#define SOTP_CTRL_0 (SOTP_REGS_OTP_BASE + 0x0010) +#define SOTP_CTRL_0__START 0 +#define SOTP_CTRL_0__OTP_CMD 1 + +#define SOTP_STATUS_0 (SOTP_REGS_OTP_BASE + 0x0018) +#define SOTP_STATUS__FDONE 3 + +#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c) +#define SOTP_STATUS_1__CMD_DONE 1 +#define SOTP_STATUS_1__ECC_DET 17 + +#define SOTP_RDDATA_0 (SOTP_REGS_OTP_BASE + 0x0020) +#define SOTP_RDDATA_1 (SOTP_REGS_OTP_BASE + 0x0024) + +#define SOTP_READ 0 + +#define SOTP_PROG_WORD 10 +#define SOTP_STATUS__PROGOK 2 +#define SOTP_PROG_ENABLE 2 + +#define SOTP_ROW_DATA_MASK 0xffffffff +#define SOTP_ECC_ERR_BITS_MASK 0x1ff00000000 + +#define SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES 4 +#define SOTP_CHIP_CTRL_SW_MANU_PROG 5 +#define SOTP_CHIP_CTRL_SW_CID_PROG 6 +#define SOTP_CHIP_CTRL_SW_AB_DEVICE 8 +#define SOTP_CHIP_CTRL_SW_AB_DEV_MODE 9 +#define CHIP_STATE_UNPROGRAMMED 0x1 +#define CHIP_STATE_UNASSIGNED 0x2 + +uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc) +{ +#ifdef USE_SOFT_SOTP + (void)sotp_add_ecc; + + return soft_sotp[offset]; +#else + uint64_t read_data = 0; + uint64_t read_data1 = 0; + uint64_t read_data2 = 0; + + /* Check for FDONE status */ + while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) != + BIT(SOTP_STATUS__FDONE)) + ; + + /* Enable OTP access by CPU */ + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + if (sotp_add_ecc == 1) { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC)); + } + + if (sotp_add_ecc == 0) { + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_DISABLE_ECC)); + } + + mmio_write_32(SOTP_ADDR, + ((offset & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R)); + mmio_write_32(SOTP_CTRL_0, (SOTP_READ << SOTP_CTRL_0__OTP_CMD)); + + /* Start bit to tell SOTP to send command to the OTP controller */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to be set */ + while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + if ((offset > SOTP_DEVICE_SECURE_CFG3_ROW) && + (mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__ECC_DET))) { + ERROR("SOTP ECC ERROR Detected row offset %d\n", offset); + read_data = SOTP_ECC_ERR_DETECT; + } else { + read_data1 = (uint64_t)mmio_read_32(SOTP_RDDATA_0); + read_data1 = read_data1 & 0xFFFFFFFF; + read_data2 = (uint64_t)mmio_read_32(SOTP_RDDATA_1); + read_data2 = (read_data2 & 0x1ff) << 32; + read_data = read_data1 | read_data2; + } + + /* Command done is cleared */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* disable OTP access by CPU */ + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + return read_data; +#endif +} + +void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata) +{ +#ifdef USE_SOFT_SOTP + (void)sotp_add_ecc; + + soft_sotp[addr] = wdata; +#else + uint32_t loop; + uint8_t prog_array[4] = { 0x0F, 0x04, 0x08, 0x0D }; + + uint32_t chip_state_default = + (CHIP_STATE_UNASSIGNED|CHIP_STATE_UNPROGRAMMED); + uint32_t chip_state = mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES); + uint32_t chip_ctrl_default = 0; + + /* + * The override settings is required to allow the customer to program + * the application specific keys into SOTP, before the conversion to + * one of the AB modes. + * At the end of write operation, the chip ctrl settings will restored + * to the state prior to write call + */ + if (chip_state & chip_state_default) { + uint32_t chip_ctrl; + + chip_ctrl_default = mmio_read_32(SOTP_CHIP_CTRL); + INFO("SOTP: enable special prog mode\n"); + + chip_ctrl = BIT(SOTP_CHIP_CTRL_SW_OVERRIDE_CHIP_STATES) | + BIT(SOTP_CHIP_CTRL_SW_MANU_PROG) | + BIT(SOTP_CHIP_CTRL_SW_CID_PROG) | + BIT(SOTP_CHIP_CTRL_SW_AB_DEVICE); + mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl); + } + + /* Check for FDONE status */ + while ((mmio_read_32(SOTP_STATUS_0) & BIT(SOTP_STATUS__FDONE)) != + BIT(SOTP_STATUS__FDONE)) + ; + + /* Enable OTP acces by CPU */ + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + if (addr > SOTP_DEVICE_SECURE_CFG3_ROW) { + if (sotp_add_ecc == 0) { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + if (sotp_add_ecc == 1) { + mmio_setbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + } else { + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_ECC_WREN)); + } + + mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_ENABLE << 1)); + + /* + * In order to avoid unintentional writes / programming of the OTP + * array, the OTP Controller must be put into programming mode before + * it will accept program commands. This is done by writing 0xF, 0x4, + * 0x8, 0xD with program commands prior to starting the actual + * programming sequence + */ + for (loop = 0; loop < 4; loop++) { + mmio_write_32(SOTP_WRDATA_0, prog_array[loop]); + + /* + * Start bit to tell SOTP to send command to the OTP controller + */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to <-- be set */ + while ((mmio_read_32(SOTP_STATUS_1) & + BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Command done is cleared w1c */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + } + + /* Check for PROGOK */ + while ((mmio_read_32(SOTP_STATUS_0) & 0x4) != BIT(SOTP_STATUS__PROGOK)) + ; + + /* Set 10 bit row address */ + mmio_write_32(SOTP_ADDR, + ((addr & SOTP_ADDR_MASK) << SOTP_ADDR__OTP_ROW_ADDR_R)); + + /* Set SOTP Row data */ + mmio_write_32(SOTP_WRDATA_0, (wdata & SOTP_ROW_DATA_MASK)); + + /* Set SOTP ECC and error bits */ + mmio_write_32(SOTP_WRDATA_1, ((wdata & SOTP_ECC_ERR_BITS_MASK) >> 32)); + + /* Set prog_word command */ + mmio_write_32(SOTP_CTRL_0, (SOTP_PROG_WORD << 1)); + + /* Start bit to tell SOTP to send command to the OTP controller */ + mmio_setbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + /* Wait for SOTP command done to be set */ + while ((mmio_read_32(SOTP_STATUS_1) & BIT(SOTP_STATUS_1__CMD_DONE)) != + BIT(SOTP_STATUS_1__CMD_DONE)) + ; + + /* Command done is cleared w1c */ + mmio_setbits_32(SOTP_STATUS_1, BIT(SOTP_STATUS_1__CMD_DONE)); + + /* disable OTP acces by CPU */ + mmio_clrbits_32(SOTP_PROG_CONTROL, + BIT(SOTP_PROG_CONTROL__OTP_CPU_MODE_EN)); + + /* Clr Start bit after command done */ + mmio_clrbits_32(SOTP_CTRL_0, BIT(SOTP_CTRL_0__START)); + + if (chip_state & chip_state_default) + mmio_write_32(SOTP_CHIP_CTRL, chip_ctrl_default); + +#endif +} + +int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row) +{ + int row; + uint32_t status = 0; + uint32_t status2 = 0xFFFFFFFF; + uint64_t row_data; + uint32_t data; + uint32_t *temp_key = (uint32_t *)key; + + row = start_row; + while ((keysize > 0) && (row <= end_row)) { + row_data = sotp_mem_read(row, SOTP_ROW_ECC); + if (!(row_data & (SOTP_ECC_ERR_DETECT | SOTP_FAIL_BITS))) { + memcpy(temp_key++, &row_data, sizeof(uint32_t)); + keysize -= sizeof(uint32_t); + data = (uint32_t)(row_data & SOTP_ROW_DATA_MASK); + status |= data; + status2 &= data; + } + row++; + } + + if ((status2 == 0xFFFFFFFF) || (status == 0) || (row > end_row)) + return -1; + + return 0; +} + +int sotp_key_erased(void) +{ + uint64_t row_data; + int status = 0; + + row_data = sotp_mem_read(SOTP_DEVICE_SECURE_CFG0_ROW, 0); + if (row_data & SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK) + status = 1; + + else if (mmio_read_32(SOTP_REGS_SOTP_CHIP_STATES) & + SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK) + status = 1; + + return status; +} + +/* + * This function optimise the SOTP redundancy + * by considering the 00- zero and 01,10,11 - one + */ +uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data) +{ + uint32_t opt_data; + uint32_t opt_loop; + uint32_t temp_data; + + opt_data = 0; + + for (opt_loop = 0; opt_loop < 16; opt_loop = opt_loop + 1) { + temp_data = ((sotp_row_data >> (opt_loop * 2)) & 0x3); + + if (temp_data != 0x0) + opt_data = (opt_data | (1 << opt_loop)); + } + return opt_data; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c new file mode 100644 index 0000000..4c533d5 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#include "iproc_qspi.h" + +struct bcmspi_priv spi_cfg; + +/* Redefined by platform to force appropriate information */ +#pragma weak plat_spi_init +int plat_spi_init(uint32_t *max_hz) +{ + return 0; +} + +/* Initialize & setup iproc qspi controller */ +int iproc_qspi_setup(uint32_t bus, uint32_t cs, uint32_t max_hz, uint32_t mode) +{ + struct bcmspi_priv *priv = NULL; + uint32_t spbr; + + priv = &spi_cfg; + priv->spi_mode = mode; + priv->state = QSPI_STATE_DISABLED; + priv->bspi_hw = QSPI_BSPI_MODE_REG_BASE; + priv->mspi_hw = QSPI_MSPI_MODE_REG_BASE; + + /* Initialize clock and platform specific */ + if (plat_spi_init(&max_hz) != 0) + return -1; + + priv->max_hz = max_hz; + + /* MSPI: Basic hardware initialization */ + mmio_write_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, 0); + + /* MSPI: SCK configuration */ + spbr = (QSPI_AXI_CLK - 1) / (2 * priv->max_hz) + 1; + spbr = MIN(spbr, SPBR_DIV_MAX); + spbr = MAX(spbr, SPBR_DIV_MIN); + mmio_write_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG, spbr); + + /* MSPI: Mode configuration (8 bits by default) */ + priv->mspi_16bit = 0; + mmio_write_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG, + BIT(MSPI_SPCR0_MSB_REG_MSTR_SHIFT) | /* Master */ + MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT | /* 16 bits per word */ + (priv->spi_mode & MSPI_SPCR0_MSB_REG_MODE_MASK)); /* mode: CPOL / CPHA */ + + /* Display bus info */ + VERBOSE("SPI: SPCR0_LSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR0_LSB_REG)); + VERBOSE("SPI: SPCR0_MSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR0_MSB_REG)); + VERBOSE("SPI: SPCR1_LSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR1_LSB_REG)); + VERBOSE("SPI: SPCR1_MSB: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR1_MSB_REG)); + VERBOSE("SPI: SPCR2: 0x%x\n", + mmio_read_32(priv->mspi_hw + MSPI_SPCR2_REG)); + VERBOSE("SPI: CLK: %d\n", priv->max_hz); + + return 0; +} + +void bcmspi_enable_bspi(struct bcmspi_priv *priv) +{ + if (priv->state != QSPI_STATE_BSPI) { + /* Switch to BSPI */ + mmio_write_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG, 0); + + priv->state = QSPI_STATE_BSPI; + } +} + +static int bcmspi_disable_bspi(struct bcmspi_priv *priv) +{ + uint32_t retry; + + if (priv->state == QSPI_STATE_MSPI) + return 0; + + /* Switch to MSPI if not yet */ + if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) & + MSPI_CTRL_MASK) == 0) { + retry = QSPI_RETRY_COUNT_US_MAX; + do { + if ((mmio_read_32( + priv->bspi_hw + BSPI_BUSY_STATUS_REG) & + BSPI_BUSY_MASK) == 0) { + mmio_write_32(priv->bspi_hw + + BSPI_MAST_N_BOOT_CTRL_REG, + MSPI_CTRL_MASK); + udelay(1); + break; + } + udelay(1); + } while (retry--); + + if ((mmio_read_32(priv->bspi_hw + BSPI_MAST_N_BOOT_CTRL_REG) & + MSPI_CTRL_MASK) != MSPI_CTRL_MASK) { + ERROR("QSPI: Switching to QSPI error.\n"); + return -1; + } + } + + /* Update state */ + priv->state = QSPI_STATE_MSPI; + + return 0; +} + +int iproc_qspi_claim_bus(void) +{ + struct bcmspi_priv *priv = &spi_cfg; + + /* Switch to MSPI by default */ + if (bcmspi_disable_bspi(priv) != 0) + return -1; + + return 0; +} + +void iproc_qspi_release_bus(void) +{ + struct bcmspi_priv *priv = &spi_cfg; + + /* Switch to BSPI by default */ + bcmspi_enable_bspi(priv); +} + +static int mspi_xfer(struct bcmspi_priv *priv, uint32_t bytes, + const uint8_t *tx, uint8_t *rx, uint32_t flag) +{ + uint32_t retry; + uint32_t mode = CDRAM_PCS0; + + if (flag & SPI_XFER_QUAD) { + mode |= CDRAM_QUAD_MODE; + VERBOSE("SPI: QUAD mode\n"); + + if (!tx) { + VERBOSE("SPI: 4 lane input\n"); + mode |= CDRAM_RBIT_INPUT; + } + } + + /* Use 8-bit queue for odd-bytes transfer */ + if (bytes & 1) + priv->mspi_16bit = 0; + else { + priv->mspi_16bit = 1; + mode |= CDRAM_BITS_EN; + } + + while (bytes) { + uint32_t chunk; + uint32_t queues; + uint32_t i; + + /* Separate code for 16bit and 8bit transfers for performance */ + if (priv->mspi_16bit) { + VERBOSE("SPI: 16 bits xfer\n"); + /* Determine how many bytes to process this time */ + chunk = MIN(bytes, NUM_CDRAM_BYTES * 2); + queues = (chunk - 1) / 2 + 1; + bytes -= chunk; + + /* Fill CDRAMs */ + for (i = 0; i < queues; i++) + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + (i << 2), mode | CDRAM_CONT); + + /* Fill TXRAMs */ + for (i = 0; i < chunk; i++) + if (tx) + mmio_write_32(priv->mspi_hw + + MSPI_TXRAM_REG + + (i << 2), tx[i]); + } else { + VERBOSE("SPI: 8 bits xfer\n"); + /* Determine how many bytes to process this time */ + chunk = MIN(bytes, NUM_CDRAM_BYTES); + queues = chunk; + bytes -= chunk; + + /* Fill CDRAMs and TXRAMS */ + for (i = 0; i < chunk; i++) { + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + (i << 2), mode | CDRAM_CONT); + if (tx) + mmio_write_32(priv->mspi_hw + + MSPI_TXRAM_REG + + (i << 3), tx[i]); + } + } + + /* Advance pointers */ + if (tx) + tx += chunk; + + /* Setup queue pointers */ + mmio_write_32(priv->mspi_hw + MSPI_NEWQP_REG, 0); + mmio_write_32(priv->mspi_hw + MSPI_ENDQP_REG, queues - 1); + + /* Remove CONT on the last byte command */ + if (bytes == 0 && (flag & SPI_XFER_END)) + mmio_write_32(priv->mspi_hw + MSPI_CDRAM_REG + + ((queues - 1) << 2), mode); + + /* Kick off */ + mmio_write_32(priv->mspi_hw + MSPI_STATUS_REG, 0); + if (bytes == 0 && (flag & SPI_XFER_END)) + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, MSPI_SPE); + else + mmio_write_32(priv->mspi_hw + MSPI_SPCR2_REG, + MSPI_SPE | MSPI_CONT_AFTER_CMD); + + /* Wait for completion */ + retry = QSPI_RETRY_COUNT_US_MAX; + do { + if (mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) & + MSPI_CMD_COMPLETE_MASK) + break; + udelay(1); + } while (retry--); + + if ((mmio_read_32(priv->mspi_hw + MSPI_STATUS_REG) & + MSPI_CMD_COMPLETE_MASK) == 0) { + ERROR("SPI: Completion timeout.\n"); + return -1; + } + + /* Read data out */ + if (rx) { + if (priv->mspi_16bit) { + for (i = 0; i < chunk; i++) { + rx[i] = mmio_read_32(priv->mspi_hw + + MSPI_RXRAM_REG + + (i << 2)) + & 0xff; + } + } else { + for (i = 0; i < chunk; i++) { + rx[i] = mmio_read_32(priv->mspi_hw + + MSPI_RXRAM_REG + + (((i << 1) + 1) << 2)) + & 0xff; + } + } + rx += chunk; + } + } + + return 0; +} + +int iproc_qspi_xfer(uint32_t bitlen, + const void *dout, void *din, unsigned long flags) +{ + struct bcmspi_priv *priv; + const uint8_t *tx = dout; + uint8_t *rx = din; + uint32_t bytes = bitlen / 8; + int ret = 0; + + priv = &spi_cfg; + + if (priv->state == QSPI_STATE_DISABLED) { + ERROR("QSPI: state disabled\n"); + return -1; + } + + /* we can only do 8 bit transfers */ + if (bitlen % 8) { + ERROR("QSPI: Only support 8 bit transfers (requested %d)\n", + bitlen); + return -1; + } + + /* MSPI: Enable write lock at the beginning */ + if (flags & SPI_XFER_BEGIN) { + /* Switch to MSPI if not yet */ + if (bcmspi_disable_bspi(priv) != 0) { + ERROR("QSPI: Switch to MSPI failed\n"); + return -1; + } + + mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 1); + } + + /* MSPI: Transfer it */ + if (bytes) + ret = mspi_xfer(priv, bytes, tx, rx, flags); + + /* MSPI: Disable write lock if it's done */ + if (flags & SPI_XFER_END) + mmio_write_32(priv->mspi_hw + MSPI_WRITE_LOCK_REG, 0); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h new file mode 100644 index 0000000..7a8bd91 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IPROC_QSPI_H +#define IPROC_QSPI_H + +#include + +/*SPI configuration enable*/ +#define IPROC_QSPI_CLK_SPEED 62500000 +#define SPI_CPHA (1 << 0) +#define SPI_CPOL (1 << 1) +#define IPROC_QSPI_MODE0 0 +#define IPROC_QSPI_MODE3 (SPI_CPOL|SPI_CPHA) + +#define IPROC_QSPI_BUS 0 +#define IPROC_QSPI_CS 0 +#define IPROC_QSPI_BASE_REG QSPI_CTRL_BASE_ADDR +#define IPROC_QSPI_CRU_CONTROL_REG QSPI_CLK_CTRL + +#define QSPI_AXI_CLK 200000000 + +#define QSPI_RETRY_COUNT_US_MAX 200000 + +/* Chip attributes */ +#define QSPI_REG_BASE IPROC_QSPI_BASE_REG +#define CRU_CONTROL_REG IPROC_QSPI_CRU_CONTROL_REG +#define SPBR_DIV_MIN 8U +#define SPBR_DIV_MAX 255U +#define NUM_CDRAM_BYTES 16U + +/* Register fields */ +#define MSPI_SPCR0_MSB_BITS_8 0x00000020 + +/* Flash opcode and parameters */ +#define CDRAM_PCS0 2 +#define CDRAM_CONT (1 << 7) +#define CDRAM_BITS_EN (1 << 6) +#define CDRAM_QUAD_MODE (1 << 8) +#define CDRAM_RBIT_INPUT (1 << 10) + +/* MSPI registers */ +#define QSPI_MSPI_MODE_REG_BASE (QSPI_REG_BASE + 0x200) +#define MSPI_SPCR0_LSB_REG 0x000 +#define MSPI_SPCR0_MSB_REG 0x004 +#define MSPI_SPCR1_LSB_REG 0x008 +#define MSPI_SPCR1_MSB_REG 0x00c +#define MSPI_NEWQP_REG 0x010 +#define MSPI_ENDQP_REG 0x014 +#define MSPI_SPCR2_REG 0x018 +#define MSPI_STATUS_REG 0x020 +#define MSPI_CPTQP_REG 0x024 +#define MSPI_TXRAM_REG 0x040 +#define MSPI_RXRAM_REG 0x0c0 +#define MSPI_CDRAM_REG 0x140 +#define MSPI_WRITE_LOCK_REG 0x180 +#define MSPI_DISABLE_FLUSH_GEN_REG 0x184 + +#define MSPI_SPCR0_MSB_REG_MSTR_SHIFT 7 +#define MSPI_SPCR0_MSB_REG_16_BITS_PER_WD_SHIFT (0 << 2) +#define MSPI_SPCR0_MSB_REG_MODE_MASK 0x3 + +/* BSPI registers */ +#define QSPI_BSPI_MODE_REG_BASE QSPI_REG_BASE +#define BSPI_MAST_N_BOOT_CTRL_REG 0x008 +#define BSPI_BUSY_STATUS_REG 0x00c + +#define MSPI_CMD_COMPLETE_MASK 1 +#define BSPI_BUSY_MASK 1 +#define MSPI_CTRL_MASK 1 + +#define MSPI_SPE (1 << 6) +#define MSPI_CONT_AFTER_CMD (1 << 7) + +/* State */ +enum bcm_qspi_state { + QSPI_STATE_DISABLED, + QSPI_STATE_MSPI, + QSPI_STATE_BSPI +}; + +/* QSPI private data */ +struct bcmspi_priv { + /* Specified SPI parameters */ + uint32_t max_hz; + uint32_t spi_mode; + + /* State */ + enum bcm_qspi_state state; + int mspi_16bit; + + /* Registers */ + uintptr_t mspi_hw; + uintptr_t bspi_hw; +}; + +int iproc_qspi_setup(uint32_t bus, uint32_t cs, + uint32_t max_hz, uint32_t mode); +int iproc_qspi_claim_bus(void); +void iproc_qspi_release_bus(void); +int iproc_qspi_xfer(uint32_t bitlen, const void *dout, + void *din, unsigned long flags); + +#endif /* _IPROC_QSPI_H_ */ diff --git a/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c b/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c new file mode 100644 index 0000000..551e587 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "iproc_qspi.h" + +int spi_init(void) +{ + return iproc_qspi_setup(IPROC_QSPI_BUS, IPROC_QSPI_CS, + IPROC_QSPI_CLK_SPEED, IPROC_QSPI_MODE0); +} + +int spi_claim_bus(void) +{ + return iproc_qspi_claim_bus(); +} + +void spi_release_bus(void) +{ + iproc_qspi_release_bus(); +} + +int spi_xfer(uint32_t bitlen, const void *dout, + void *din, uint32_t flags) +{ + return iproc_qspi_xfer(bitlen, dout, din, flags); +} diff --git a/arm-trusted-firmware/drivers/brcm/spi_flash.c b/arm-trusted-firmware/drivers/brcm/spi_flash.c new file mode 100644 index 0000000..336d230 --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi_flash.c @@ -0,0 +1,308 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#define SPI_FLASH_CMD_LEN 4 +#define QSPI_WAIT_TIMEOUT_US 200000U /* usec */ + +#define FINFO(jedec_id, ext_id, _sector_size, _n_sectors, _page_size, _flags) \ + .id = { \ + ((jedec_id) >> 16) & 0xff, \ + ((jedec_id) >> 8) & 0xff, \ + (jedec_id) & 0xff, \ + ((ext_id) >> 8) & 0xff, \ + (ext_id) & 0xff, \ + }, \ + .id_len = (!(jedec_id) ? 0 : (3 + ((ext_id) ? 2 : 0))), \ + .sector_size = (_sector_size), \ + .n_sectors = (_n_sectors), \ + .page_size = _page_size, \ + .flags = (_flags), + +/* SPI/QSPI flash device params structure */ +const struct spi_flash_info spi_flash_ids[] = { + {"W25Q64CV", FINFO(0xef4017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)}, + {"W25Q64DW", FINFO(0xef6017, 0x0, 64 * 1024, 128, 256, WR_QPP | SECT_4K)}, + {"W25Q32", FINFO(0xef4016, 0x0, 64 * 1024, 64, 256, SECT_4K)}, + {"MX25l3205D", FINFO(0xc22016, 0x0, 64 * 1024, 64, 256, SECT_4K)}, +}; + +static void spi_flash_addr(uint32_t addr, uint8_t *cmd) +{ + /* + * cmd[0] holds a SPI Flash command, stored earlier + * cmd[1/2/3] holds 24bit flash address + */ + cmd[1] = addr >> 16; + cmd[2] = addr >> 8; + cmd[3] = addr >> 0; +} + +static const struct spi_flash_info *spi_flash_read_id(void) +{ + const struct spi_flash_info *info; + uint8_t id[SPI_FLASH_MAX_ID_LEN]; + int ret; + + ret = spi_flash_cmd(CMD_READ_ID, id, SPI_FLASH_MAX_ID_LEN); + if (ret < 0) { + ERROR("SF: Error %d reading JEDEC ID\n", ret); + return NULL; + } + + for (info = spi_flash_ids; info->name != NULL; info++) { + if (info->id_len) { + if (!memcmp(info->id, id, info->id_len)) + return info; + } + } + + printf("SF: unrecognized JEDEC id bytes: %02x, %02x, %02x\n", + id[0], id[1], id[2]); + return NULL; +} + +/* Enable writing on the SPI flash */ +static inline int spi_flash_cmd_write_enable(struct spi_flash *flash) +{ + return spi_flash_cmd(CMD_WRITE_ENABLE, NULL, 0); +} + +static int spi_flash_cmd_wait(struct spi_flash *flash) +{ + uint8_t cmd; + uint32_t i; + uint8_t status; + int ret; + + i = 0; + while (1) { + cmd = CMD_RDSR; + ret = spi_flash_cmd_read(&cmd, 1, &status, 1); + if (ret < 0) { + ERROR("SF: cmd wait failed\n"); + break; + } + if (!(status & STATUS_WIP)) + break; + + i++; + if (i >= QSPI_WAIT_TIMEOUT_US) { + ERROR("SF: cmd wait timeout\n"); + ret = -1; + break; + } + udelay(1); + } + + return ret; +} + +static int spi_flash_write_common(struct spi_flash *flash, const uint8_t *cmd, + size_t cmd_len, const void *buf, + size_t buf_len) +{ + int ret; + + ret = spi_flash_cmd_write_enable(flash); + if (ret < 0) { + ERROR("SF: enabling write failed\n"); + return ret; + } + + ret = spi_flash_cmd_write(cmd, cmd_len, buf, buf_len); + if (ret < 0) { + ERROR("SF: write cmd failed\n"); + return ret; + } + + ret = spi_flash_cmd_wait(flash); + if (ret < 0) { + ERROR("SF: write timed out\n"); + return ret; + } + + return ret; +} + +static int spi_flash_read_common(const uint8_t *cmd, size_t cmd_len, + void *data, size_t data_len) +{ + int ret; + + ret = spi_flash_cmd_read(cmd, cmd_len, data, data_len); + if (ret < 0) { + ERROR("SF: read cmd failed\n"); + return ret; + } + + return ret; +} + +int spi_flash_read(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *data) +{ + uint32_t read_len = 0, read_addr; + uint8_t cmd[SPI_FLASH_CMD_LEN]; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + cmd[0] = CMD_READ_NORMAL; + while (len) { + read_addr = offset; + read_len = MIN(flash->page_size, (len - read_len)); + spi_flash_addr(read_addr, cmd); + + ret = spi_flash_read_common(cmd, sizeof(cmd), data, read_len); + if (ret < 0) { + ERROR("SF: read failed\n"); + break; + } + + offset += read_len; + len -= read_len; + data += read_len; + } + SPI_DEBUG("SF read done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_write(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *buf) +{ + unsigned long byte_addr, page_size; + uint8_t cmd[SPI_FLASH_CMD_LEN]; + uint32_t chunk_len, actual; + uint32_t write_addr; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + page_size = flash->page_size; + + cmd[0] = flash->write_cmd; + for (actual = 0; actual < len; actual += chunk_len) { + write_addr = offset; + byte_addr = offset % page_size; + chunk_len = MIN(len - actual, + (uint32_t)(page_size - byte_addr)); + spi_flash_addr(write_addr, cmd); + + SPI_DEBUG("SF:0x%p=>cmd:{0x%02x 0x%02x%02x%02x} chunk_len:%d\n", + buf + actual, cmd[0], cmd[1], + cmd[2], cmd[3], chunk_len); + + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), + buf + actual, chunk_len); + if (ret < 0) { + ERROR("SF: write cmd failed\n"); + break; + } + + offset += chunk_len; + } + SPI_DEBUG("SF write done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len) +{ + uint8_t cmd[SPI_FLASH_CMD_LEN]; + uint32_t erase_size, erase_addr; + int ret; + + erase_size = flash->erase_size; + + if (offset % erase_size || len % erase_size) { + ERROR("SF: Erase offset/length not multiple of erase size\n"); + return -1; + } + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: unable to claim SPI bus\n"); + return ret; + } + + cmd[0] = flash->erase_cmd; + while (len) { + erase_addr = offset; + spi_flash_addr(erase_addr, cmd); + + SPI_DEBUG("SF: erase %2x %2x %2x %2x (%x)\n", cmd[0], cmd[1], + cmd[2], cmd[3], erase_addr); + + ret = spi_flash_write_common(flash, cmd, sizeof(cmd), NULL, 0); + if (ret < 0) { + ERROR("SF: erase failed\n"); + break; + } + + offset += erase_size; + len -= erase_size; + } + SPI_DEBUG("sf erase done\n"); + + spi_release_bus(); + return ret; +} + +int spi_flash_probe(struct spi_flash *flash) +{ + const struct spi_flash_info *info = NULL; + int ret; + + ret = spi_claim_bus(); + if (ret) { + ERROR("SF: Unable to claim SPI bus\n"); + ERROR("SF: probe failed\n"); + return ret; + } + + info = spi_flash_read_id(); + if (!info) + goto probe_fail; + + INFO("Flash Name: %s sectors %x, sec size %x\n", + info->name, info->n_sectors, + info->sector_size); + flash->size = info->n_sectors * info->sector_size; + flash->sector_size = info->sector_size; + flash->page_size = info->page_size; + flash->flags = info->flags; + + flash->read_cmd = CMD_READ_NORMAL; + flash->write_cmd = CMD_PAGE_PROGRAM; + flash->erase_cmd = CMD_ERASE_64K; + flash->erase_size = ERASE_SIZE_64K; + +probe_fail: + spi_release_bus(); + return ret; +} diff --git a/arm-trusted-firmware/drivers/brcm/spi_sf.c b/arm-trusted-firmware/drivers/brcm/spi_sf.c new file mode 100644 index 0000000..8bbb09f --- /dev/null +++ b/arm-trusted-firmware/drivers/brcm/spi_sf.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#define BITS_PER_BYTE 8 +#define CMD_LEN1 1 + +static int spi_flash_read_write(const uint8_t *cmd, + size_t cmd_len, + const uint8_t *data_out, + uint8_t *data_in, + size_t data_len) +{ + unsigned long flags = SPI_XFER_BEGIN; + int ret; + + if (data_len == 0) + flags |= SPI_XFER_END; + + ret = spi_xfer(cmd_len * BITS_PER_BYTE, cmd, NULL, flags); + if (ret) { + ERROR("SF: Failed to send command (%zu bytes): %d\n", + cmd_len, ret); + } else if (data_len != 0) { + ret = spi_xfer(data_len * BITS_PER_BYTE, data_out, + data_in, SPI_XFER_END); + if (ret) + ERROR("SF: Failed to transfer %zu bytes of data: %d\n", + data_len, ret); + } + + return ret; +} + +int spi_flash_cmd_read(const uint8_t *cmd, + size_t cmd_len, + void *data, + size_t data_len) +{ + return spi_flash_read_write(cmd, cmd_len, NULL, data, data_len); +} + +int spi_flash_cmd(uint8_t cmd, void *response, size_t len) +{ + return spi_flash_cmd_read(&cmd, CMD_LEN1, response, len); +} + +int spi_flash_cmd_write(const uint8_t *cmd, + size_t cmd_len, + const void *data, + size_t data_len) +{ + return spi_flash_read_write(cmd, cmd_len, data, NULL, data_len); +} diff --git a/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S b/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S new file mode 100644 index 0000000..4c1a80e --- /dev/null +++ b/arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_cdns_core_init + .globl console_cdns_core_putc + .globl console_cdns_core_getc + .globl console_cdns_core_flush + + .globl console_cdns_putc + .globl console_cdns_getc + .globl console_cdns_flush + + /* ----------------------------------------------- + * int console_cdns_core_init(uintptr_t base_addr) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * We assume that the bootloader already set up + * the HW (baud, ...) and only enable the trans- + * mitter and receiver here. + * In: x0 - console base address + * Out: return 1 on success else 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func console_cdns_core_init + /* Check the input base address */ + cbz x0, core_init_fail + + /* RX/TX enabled & reset */ + mov w3, #(R_UART_CR_TX_EN | R_UART_CR_RX_EN | R_UART_CR_TXRST | R_UART_CR_RXRST) + str w3, [x0, #R_UART_CR] + + mov w0, #1 + ret +core_init_fail: + mov w0, wzr + ret +endfunc console_cdns_core_init + + .globl console_cdns_register + + /* ----------------------------------------------- + * int console_cdns_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new CDNS + * 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_cdns_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_cdns_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register cdns putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_cdns_register + + /* -------------------------------------------------------- + * int console_cdns_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_cdns_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f +1: + /* Check if the transmit FIFO is empty */ + ldr w2, [x1, #R_UART_SR] + tbz w2, #UART_SR_INTR_TEMPTY_BIT, 1b + mov w2, #0xD + str w2, [x1, #R_UART_TX] +2: + /* Check if the transmit FIFO is empty */ + ldr w2, [x1, #R_UART_SR] + tbz w2, #UART_SR_INTR_TEMPTY_BIT, 2b + str w0, [x1, #R_UART_TX] + ret +endfunc console_cdns_core_putc + + /* -------------------------------------------------------- + * int console_cdns_putc(int c, console_t *cdns) + * 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_cdns_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_cdns_core_putc +endfunc console_cdns_putc + + /* --------------------------------------------- + * int console_cdns_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : x0 - console base address + * Out: w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_cdns_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ + ldr w1, [x0, #R_UART_SR] + tbnz w1, #UART_SR_INTR_REMPTY_BIT, no_char + ldr w1, [x0, #R_UART_RX] + mov w0, w1 + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_cdns_core_getc + + /* --------------------------------------------- + * int console_cdns_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_cdns_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_cdns_core_getc +endfunc console_cdns_getc + + /* --------------------------------------------- + * void console_cdns_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_cdns_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Placeholder */ + ret +endfunc console_cdns_core_flush + + /* --------------------------------------------- + * void console_cdns_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_cdns_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_cdns_core_flush +endfunc console_cdns_flush diff --git a/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c b/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c new file mode 100644 index 0000000..6690189 --- /dev/null +++ b/arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * This file supplies a low level interface to the vexpress NOR flash + * memory of juno and fvp. This memory is organized as an interleaved + * memory of two chips with a 16 bit word. It means that every 32 bit + * access is going to access to two different chips. This is very + * important when we send commands or read status of the chips. + */ + +/* + * DWS ready poll retries. The number of retries in this driver have been + * obtained empirically from Juno. FVP implements a zero wait state NOR flash + * model + */ +#define DWS_WORD_PROGRAM_RETRIES 1000 +#define DWS_WORD_ERASE_RETRIES 3000000 +#define DWS_WORD_LOCK_RETRIES 1000 + +/* Helper macro to detect end of command */ +#define NOR_CMD_END (NOR_DWS | (NOR_DWS << 16l)) + +/* Helper macros to access two flash banks in parallel */ +#define NOR_2X16(d) ((d << 16) | (d & 0xffff)) + +static unsigned int nor_status(uintptr_t base_addr) +{ + unsigned long status; + + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + status |= status >> 16; /* merge status from both flash banks */ + + return status & 0xFFFF; +} + +/* + * Poll Write State Machine. + * Return values: + * 0 = WSM ready + * -EBUSY = WSM busy after the number of retries + */ +static int nor_poll_dws(uintptr_t base_addr, unsigned long int retries) +{ + unsigned long status; + + do { + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + if ((status & NOR_CMD_END) == NOR_CMD_END) + return 0; + } while (retries-- > 0); + + return -EBUSY; +} + +/* + * Return values: + * 0 = success + * -EPERM = Device protected or Block locked + * -EIO = General I/O error + */ +static int nor_full_status_check(uintptr_t base_addr) +{ + unsigned long status; + + /* Full status check */ + status = nor_status(base_addr); + + if (status & (NOR_PS | NOR_BLS | NOR_ESS | NOR_PSS)) + return -EPERM; + if (status & (NOR_VPPS | NOR_ES)) + return -EIO; + return 0; +} + +void nor_send_cmd(uintptr_t base_addr, unsigned long cmd) +{ + mmio_write_32(base_addr, NOR_2X16(cmd)); +} + +/* + * This function programs a word in the flash. Be aware that it only + * can reset bits that were previously set. It cannot set bits that + * were previously reset. The resulting bits = old_bits & new bits. + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_word_program(uintptr_t base_addr, unsigned long data) +{ + uint32_t status; + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + /* Set the device in write word mode */ + nor_send_cmd(base_addr, NOR_CMD_WORD_PROGRAM); + mmio_write_32(base_addr, data); + + ret = nor_poll_dws(base_addr, DWS_WORD_PROGRAM_RETRIES); + if (ret == 0) { + /* Full status check */ + nor_send_cmd(base_addr, NOR_CMD_READ_STATUS_REG); + status = mmio_read_32(base_addr); + + if (status & (NOR_PS | NOR_BLS)) { + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + ret = -EPERM; + } + } + + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Erase a full 256K block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_erase(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE); + nor_send_cmd(base_addr, NOR_CMD_BLOCK_ERASE_ACK); + + ret = nor_poll_dws(base_addr, DWS_WORD_ERASE_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * Lock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_lock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_LOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} + +/* + * unlock a full 256 block + * Return values: + * 0 = success + * otherwise it returns a negative value + */ +int nor_unlock(uintptr_t base_addr) +{ + int ret; + + nor_send_cmd(base_addr, NOR_CMD_CLEAR_STATUS_REG); + + nor_send_cmd(base_addr, NOR_CMD_LOCK_UNLOCK); + nor_send_cmd(base_addr, NOR_UNLOCK_BLOCK); + + ret = nor_poll_dws(base_addr, DWS_WORD_LOCK_RETRIES); + if (ret == 0) + ret = nor_full_status_check(base_addr); + nor_send_cmd(base_addr, NOR_CMD_READ_ARRAY); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/clk/clk.c b/arm-trusted-firmware/drivers/clk/clk.c new file mode 100644 index 0000000..4cbc0f7 --- /dev/null +++ b/arm-trusted-firmware/drivers/clk/clk.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * Author(s): Ludovic Barre, for STMicroelectronics. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +static const struct clk_ops *ops; + +int clk_enable(unsigned long id) +{ + assert((ops != NULL) && (ops->enable != NULL)); + + return ops->enable(id); +} + +void clk_disable(unsigned long id) +{ + assert((ops != NULL) && (ops->disable != NULL)); + + ops->disable(id); +} + +unsigned long clk_get_rate(unsigned long id) +{ + assert((ops != NULL) && (ops->get_rate != NULL)); + + return ops->get_rate(id); +} + +int clk_get_parent(unsigned long id) +{ + assert((ops != NULL) && (ops->get_parent != NULL)); + + return ops->get_parent(id); +} + +bool clk_is_enabled(unsigned long id) +{ + assert((ops != NULL) && (ops->is_enabled != NULL)); + + return ops->is_enabled(id); +} + +/* + * Initialize the clk. The fields in the provided clk + * ops pointer must be valid. + */ +void clk_register(const struct clk_ops *ops_ptr) +{ + assert((ops_ptr != NULL) && + (ops_ptr->enable != NULL) && + (ops_ptr->disable != NULL) && + (ops_ptr->get_rate != NULL) && + (ops_ptr->get_parent != NULL) && + (ops_ptr->is_enabled != NULL)); + + ops = ops_ptr; +} diff --git a/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S b/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S new file mode 100644 index 0000000..a9e13ec --- /dev/null +++ b/arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + /* + * This file contains a skeleton console driver that can be used as a + * basis for a real console driver. Console drivers in Trusted Firmware + * can be instantiated multiple times. Each instance is described by a + * separate console_t structure which must be registered with the common + * console framework via console_register(). Console drivers should + * define a console_xxx_register() function that initializes a new + * console_t structure passed in from the caller and registers it after + * initializing the console hardware. Drivers may define their own + * structures extending console_t to store private driver information. + * Console drivers *MUST* ensure that the console callbacks they + * implement only change registers allowed in the clobber lists defined + * in this file. (Note that in addition to the explicit clobber lists, + * any function may always clobber the intra-procedure-call register + * r12, but may never depend on it retaining its value across any + * function call.) + */ + + .globl console_xxx_register + .globl console_xxx_putc + .globl console_xxx_getc + .globl console_xxx_flush + + /* ----------------------------------------------- + * int console_xxx_register(console_xxx_t *console, + * ...additional parameters as desired...) + * Function to initialize and register the console. + * The caller needs to pass an empty console_xxx_t + * structure in which *MUST* be allocated in + * persistent memory (e.g. a global or static local + * variable, *NOT* on the stack). + * In : r0 - pointer to empty console_t structure + * r1 through r7: additional parameters as desired + * Out: r0 - 1 on success, 0 on error + * Clobber list : r0 - r7 + * ----------------------------------------------- + */ +func console_xxx_register + /* + * Store parameters (e.g. hardware base address) in driver-specific + * console_xxx_t structure field if they will need to be retrieved + * by later console callback (e.g. putc). + * Example: + */ + str r1, [r0, #CONSOLE_T_BASE] + str r2, [r0, #CONSOLE_T_XXX_SOME_OTHER_VALUE] + + /* + * Initialize console hardware, using r1 - r7 parameters as needed. + * Keep console_t pointer in r0 for later. + */ + + /* + * Macro to finish up registration and return (needs valid r0 + lr). + * If any of the argument is unspecified, then the corresponding + * entry in console_t is set to 0. + */ + finish_console_register xxx putc=1, getc=1, flush=1 + + /* Jump here if hardware init fails or parameters are invalid. */ +register_fail: + mov r0, #0 + bx lr +endfunc console_xxx_register + + /* -------------------------------------------------------- + * int console_xxx_putc(int c, console_xxx_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - pointer to console_t struct + * Out: r0 - printed character on success, < 0 on error. + * Clobber list : r0, r1, r2 + * -------------------------------------------------------- + */ +func console_xxx_putc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r1. + * Example: + */ + ldr r1, [r1, #CONSOLE_T_BASE] + + /* + * Write r0 to hardware. + */ + + bx lr + + /* Jump here if output fails for any reason. */ +putc_error: + mov r0, #-1 + bx lr +endfunc console_xxx_putc + + /* --------------------------------------------- + * int console_xxx_getc(console_xxx_t *console) + * Function to get a character from the console. + * Even though console_getc() is blocking, this + * callback has to be non-blocking and always + * return immediately to allow polling multiple + * drivers concurrently. + * Returns the character grabbed on success, + * ERROR_NO_PENDING_CHAR if no character was + * available at this time, or any value + * between -2 and -127 if there was an error. + * In : r0 - pointer to console_t struct + * Out: r0 - character on success, + * ERROR_NO_PENDING_CHAR if no char, + * < -1 on error + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_xxx_getc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r0. + * Example: + */ + ldr r1, [r0, #CONSOLE_T_BASE] + + /* + * Try to read character into r0 from hardware. + */ + + bx lr + + /* Jump here if there is no character available at this time. */ +getc_no_char: + mov r0, #ERROR_NO_PENDING_CHAR + bx lr + + /* Jump here if there was any hardware error. */ +getc_error: + mov r0, #-2 /* may pick error codes between -2 and -127 */ + bx lr +endfunc console_xxx_getc + + /* --------------------------------------------- + * int console_xxx_flush(console_xxx_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_xxx_t struct + * Out: void + * Clobber list : r0, r1, r2, r3, r4, r5 + * --------------------------------------------- + */ +func console_xxx_flush + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by r0. + * Example: + */ + ldr r1, [r0, #CONSOLE_T_BASE] + + /* + * Flush all remaining output from hardware FIFOs. Do not return until + * all data has been flushed or there was an unrecoverable error. + */ + + bx lr +endfunc console_xxx_flush diff --git a/arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S b/arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S new file mode 100644 index 0000000..7ea2eec --- /dev/null +++ b/arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + /* + * This file contains a skeleton console driver that can be used as a + * basis for a real console driver. Console drivers in Trusted Firmware + * can be instantiated multiple times. Each instance is described by a + * separate console_t structure which must be registered with the common + * console framework via console_register(). Console drivers should + * define a console_xxx_register() function that initializes a new + * console_t structure passed in from the caller and registers it after + * initializing the console hardware. Drivers may define their own + * structures extending console_t to store private driver information. + * Console drivers *MUST* ensure that the console callbacks they + * implement only change registers allowed in the clobber lists defined + * in this file. (Note that in addition to the explicit clobber lists, + * any function may always clobber the intra-procedure-call registers + * X16 and X17, but may never depend on them retaining their values + * across any function call.) + */ + + .globl console_xxx_register + .globl console_xxx_putc + .globl console_xxx_getc + .globl console_xxx_flush + + /* ----------------------------------------------- + * int console_xxx_register(console_xxx_t *console, + * ...additional parameters as desired...) + * Function to initialize and register the console. + * The caller needs to pass an empty console_xxx_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 through x7: additional parameters as desired + * Out: x0 - 1 on success, 0 on error + * Clobber list : x0 - x7 + * ----------------------------------------------- + */ +func console_xxx_register + /* + * Store parameters (e.g. hardware base address) in driver-specific + * console_xxx_t structure field if they will need to be retrieved + * by later console callback (e.g. putc). + * Example: + */ + str x1, [x0, #CONSOLE_T_BASE] + str x2, [x0, #CONSOLE_T_XXX_SOME_OTHER_VALUE] + + /* + * Initialize console hardware, using x1 - x7 parameters as needed. + * Keep console_t pointer in x0 for later. + */ + + /* + * Macro to finish up registration and return (needs valid x0 + x30). + * If any of the argument is unspecified, then the corresponding + * entry in console_t is set to 0. + */ + finish_console_register xxx putc=1, getc=1, flush=1 + + /* Jump here if hardware init fails or parameters are invalid. */ +register_fail: + mov w0, #0 + ret +endfunc console_xxx_register + + /* -------------------------------------------------------- + * int console_xxx_putc(int c, console_xxx_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 struct + * Out: w0 - printed character on success, < 0 on error. + * Clobber list : x0, x1, x2 + * -------------------------------------------------------- + */ +func console_xxx_putc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x1. + * Example: + */ + ldr x1, [x1, #CONSOLE_T_BASE] + + /* + * Write w0 to hardware. + */ + + ret + + /* Jump here if output fails for any reason. */ +putc_error: + mov w0, #-1 + ret +endfunc console_xxx_putc + + /* --------------------------------------------- + * int console_xxx_getc(console_xxx_t *console) + * Function to get a character from the console. + * Even though console_getc() is blocking, this + * callback has to be non-blocking and always + * return immediately to allow polling multiple + * drivers concurrently. + * Returns the character grabbed on success, + * ERROR_NO_PENDING_CHAR if no character was + * available at this time, or any value + * between -2 and -127 if there was an error. + * In : x0 - pointer to console_t struct + * Out: w0 - character on success, + * ERROR_NO_PENDING_CHAR if no char, + * < -1 on error + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_xxx_getc + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x0. + * Example: + */ + ldr x1, [x0, #CONSOLE_T_BASE] + + /* + * Try to read character into w0 from hardware. + */ + + ret + + /* Jump here if there is no character available at this time. */ +getc_no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret + + /* Jump here if there was any hardware error. */ +getc_error: + mov w0, #-2 /* may pick error codes between -2 and -127 */ + ret +endfunc console_xxx_getc + + /* --------------------------------------------- + * void console_xxx_flush(console_xxx_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_xxx_t struct + * Out: void + * Clobber list : x0, x1, x2, x3, x4, x5 + * --------------------------------------------- + */ +func console_xxx_flush + /* + * Retrieve values we need (e.g. hardware base address) from + * console_xxx_t structure pointed to by x0. + * Example: + */ + ldr x1, [x0, #CONSOLE_T_BASE] + + /* + * Flush all remaining output from hardware FIFOs. Do not return until + * all data has been flushed or there was an unrecoverable error. + */ + + ret +endfunc console_xxx_flush diff --git a/arm-trusted-firmware/drivers/console/multi_console.c b/arm-trusted-firmware/drivers/console/multi_console.c new file mode 100644 index 0000000..08b8e9f --- /dev/null +++ b/arm-trusted-firmware/drivers/console/multi_console.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +console_t *console_list; +uint8_t console_state = CONSOLE_FLAG_BOOT; + +IMPORT_SYM(console_t *, __STACKS_START__, stacks_start) +IMPORT_SYM(console_t *, __STACKS_END__, stacks_end) + +int console_register(console_t *console) +{ + /* Assert that the struct is not on the stack (common mistake). */ + assert((console < stacks_start) || (console >= stacks_end)); + + /* Check that we won't make a circle in the list. */ + if (console_is_registered(console) == 1) + return 1; + + console->next = console_list; + console_list = console; + + /* Return 1 for convenient tail-calling from console_xxx_register(). */ + return 1; +} + +console_t *console_unregister(console_t *to_be_deleted) +{ + console_t **ptr; + + assert(to_be_deleted != NULL); + + for (ptr = &console_list; *ptr != NULL; ptr = &(*ptr)->next) + if (*ptr == to_be_deleted) { + *ptr = (*ptr)->next; + return to_be_deleted; + } + + return NULL; +} + +int console_is_registered(console_t *to_find) +{ + console_t *console; + + assert(to_find != NULL); + + for (console = console_list; console != NULL; console = console->next) + if (console == to_find) + return 1; + + return 0; +} + +void console_switch_state(unsigned int new_state) +{ + console_state = new_state; +} + +void console_set_scope(console_t *console, unsigned int scope) +{ + assert(console != NULL); + + console->flags = (console->flags & ~CONSOLE_FLAG_SCOPE_MASK) | scope; +} + +static int do_putc(int c, console_t *console) +{ + int ret; + + if ((c == '\n') && + ((console->flags & CONSOLE_FLAG_TRANSLATE_CRLF) != 0)) { + ret = console->putc('\r', console); + if (ret < 0) + return ret; + } + + return console->putc(c, console); +} + +int console_putc(int c) +{ + int err = ERROR_NO_VALID_CONSOLE; + console_t *console; + + for (console = console_list; console != NULL; console = console->next) + if ((console->flags & console_state) && (console->putc != NULL)) { + int ret = do_putc(c, console); + if ((err == ERROR_NO_VALID_CONSOLE) || (ret < err)) + err = ret; + } + + return err; +} + +int console_getc(void) +{ + int err = ERROR_NO_VALID_CONSOLE; + console_t *console; + + do { /* Keep polling while at least one console works correctly. */ + for (console = console_list; console != NULL; + console = console->next) + if ((console->flags & console_state) && (console->getc != NULL)) { + int ret = console->getc(console); + if (ret >= 0) + return ret; + if (err != ERROR_NO_PENDING_CHAR) + err = ret; + } + } while (err == ERROR_NO_PENDING_CHAR); + + return err; +} + +void console_flush(void) +{ + console_t *console; + + for (console = console_list; console != NULL; console = console->next) + if ((console->flags & console_state) && (console->flush != NULL)) { + console->flush(console); + } +} diff --git a/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S b/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S new file mode 100644 index 0000000..db07e6c --- /dev/null +++ b/arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* + * This driver implements access to coreboot's in-memory console + * (CBMEM console). For the original implementation, see + * /src/lib/cbmem_console.c. + */ + + .globl console_cbmc_register + .globl console_cbmc_putc + .globl console_cbmc_flush + + /* ----------------------------------------------- + * int console_cbmc_register(uintptr_t base, + * console_cbmc_t *console); + * Registers a new CBMEM console instance. Reads + * the size field from the buffer header structure + * and stores it in our console_cbmc_t struct, so + * that we keep the size in secure memory where we + * can trust it. A malicious EL1 could manipulate + * the console buffer (including the header), so we + * must not trust its contents after boot. + * In: x0 - CBMEM console base address + * x1 - pointer to empty console_cbmc_t struct + * Out: x0 - 1 to indicate success + * Clobber list: x0, x1, x2, x7 + * ----------------------------------------------- + */ +func console_cbmc_register + str x0, [x1, #CONSOLE_T_BASE] + ldr w2, [x0] + str w2, [x1, #CONSOLE_T_CBMC_SIZE] + mov x0, x1 + finish_console_register cbmc putc=1, flush=1 +endfunc console_cbmc_register + + /* ----------------------------------------------- + * int console_cbmc_puts(int c, console_cbmc_t *console) + * Writes a character to the CBMEM console buffer, + * including overflow handling of the cursor field. + * The character must be preserved in x0. + * In: x0 - character to be stored + * x1 - pointer to console_cbmc_t struct + * Clobber list: x1, x2, x16, x17 + * ----------------------------------------------- + */ +func console_cbmc_putc + ldr w2, [x1, #CONSOLE_T_CBMC_SIZE] + ldr x1, [x1, #CONSOLE_T_BASE] + add x1, x1, #8 /* keep address of body in x1 */ + + ldr w16, [x1, #-4] /* load cursor (one u32 before body) */ + and w17, w16, #0xf0000000 /* keep flags part in w17 */ + and w16, w16, #0x0fffffff /* keep actual cursor part in w16 */ + + cmp w16, w2 /* sanity check that cursor < size */ + b.lo putc_within_bounds + mov w0, #-1 /* cursor >= size must be malicious */ + ret /* so return error, don't write char */ + +putc_within_bounds: + strb w0, [x1, w16, uxtw] /* body[cursor] = character */ + add w16, w16, #1 /* cursor++ */ + cmp w16, w2 /* if cursor < size... */ + b.lo putc_write_back /* ...skip overflow handling */ + + mov w16, #0 /* on overflow, set cursor back to 0 */ + orr w17, w17, #(1 << 31) /* and set overflow flag */ + +putc_write_back: + orr w16, w16, w17 /* merge cursor and flags back */ + str w16, [x1, #-4] /* write back cursor to memory */ + ret +endfunc console_cbmc_putc + + /* ----------------------------------------------- + * void console_cbmc_flush(console_cbmc_t *console) + * Flushes the CBMEM console by flushing the + * console buffer from the CPU's data cache. + * In: x0 - pointer to console_cbmc_t struct + * Out: void + * Clobber list: x0, x1, x2, x3 + * ----------------------------------------------- + */ +func console_cbmc_flush + ldr x1, [x0, #CONSOLE_T_CBMC_SIZE] + ldr x0, [x0, #CONSOLE_T_BASE] + add x1, x1, #8 /* add size of console header */ + b clean_dcache_range /* (clobbers x2 and x3) */ +endfunc console_cbmc_flush diff --git a/arm-trusted-firmware/drivers/delay_timer/delay_timer.c b/arm-trusted-firmware/drivers/delay_timer/delay_timer.c new file mode 100644 index 0000000..a3fd7bf --- /dev/null +++ b/arm-trusted-firmware/drivers/delay_timer/delay_timer.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +/*********************************************************** + * The delay timer implementation + ***********************************************************/ +static const timer_ops_t *timer_ops; + +/*********************************************************** + * Delay for the given number of microseconds. The driver must + * be initialized before calling this function. + ***********************************************************/ +void udelay(uint32_t usec) +{ + assert((timer_ops != NULL) && + (timer_ops->clk_mult != 0U) && + (timer_ops->clk_div != 0U) && + (timer_ops->get_timer_value != NULL)); + + uint32_t start, delta; + uint64_t total_delta; + + assert(usec < (UINT64_MAX / timer_ops->clk_div)); + + start = timer_ops->get_timer_value(); + + /* Add an extra tick to avoid delaying less than requested. */ + total_delta = + div_round_up((uint64_t)usec * timer_ops->clk_div, + timer_ops->clk_mult) + 1U; + /* + * Precaution for the total_delta ~ UINT32_MAX and the fact that we + * cannot catch every tick of the timer. + * For example 100MHz timer over 25MHz APB will miss at least 4 ticks. + * 1000U is an arbitrary big number which is believed to be sufficient. + */ + assert(total_delta < (UINT32_MAX - 1000U)); + + do { + /* + * If the timer value wraps around, the subtraction will + * overflow and it will still give the correct result. + * delta is decreasing counter + */ + delta = start - timer_ops->get_timer_value(); + + } while (delta < total_delta); +} + +/*********************************************************** + * Delay for the given number of milliseconds. The driver must + * be initialized before calling this function. + ***********************************************************/ +void mdelay(uint32_t msec) +{ + assert((msec * 1000UL) < UINT32_MAX); + udelay(msec * 1000U); +} + +/*********************************************************** + * Initialize the timer. The fields in the provided timer + * ops pointer must be valid. + ***********************************************************/ +void timer_init(const timer_ops_t *ops_ptr) +{ + assert((ops_ptr != NULL) && + (ops_ptr->clk_mult != 0U) && + (ops_ptr->clk_div != 0U) && + (ops_ptr->get_timer_value != NULL)); + + timer_ops = ops_ptr; +} diff --git a/arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c b/arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c new file mode 100644 index 0000000..ca522e0 --- /dev/null +++ b/arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c @@ -0,0 +1,62 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +static timer_ops_t ops; + +static uint32_t 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 generic_delay_timer_init_args(uint32_t mult, uint32_t div) +{ + ops.get_timer_value = get_timer_value; + ops.clk_mult = mult; + ops.clk_div = div; + + timer_init(&ops); + + VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", + mult, div); +} + +void generic_delay_timer_init(void) +{ + assert(is_armv7_gentimer_present()); + + /* Value in ticks */ + unsigned int mult = MHZ_TICKS_PER_SEC; + + /* Value in ticks per second (Hz) */ + unsigned int div = plat_get_syscnt_freq2(); + + /* Reduce multiplier and divider by dividing them repeatedly by 10 */ + while (((mult % 10U) == 0U) && ((div % 10U) == 0U)) { + mult /= 10U; + div /= 10U; + } + + generic_delay_timer_init_args(mult, div); +} + diff --git a/arm-trusted-firmware/drivers/fwu/fwu.c b/arm-trusted-firmware/drivers/fwu/fwu.c new file mode 100644 index 0000000..ff432be --- /dev/null +++ b/arm-trusted-firmware/drivers/fwu/fwu.c @@ -0,0 +1,194 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* + * Assert that crc_32 is the first member of fwu_metadata structure. + * It avoids accessing data outside of the metadata structure during + * CRC32 computation if the crc_32 field gets moved due the structure + * member(s) addition in the future. + */ +CASSERT((offsetof(struct fwu_metadata, crc_32) == 0), + crc_32_must_be_first_member_of_structure); + +static struct fwu_metadata metadata; +static bool is_metadata_initialized __unused; + +/******************************************************************************* + * Compute CRC32 of the FWU metadata, and check it against the CRC32 value + * present in the FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_crc_check(void) +{ + unsigned char *data = (unsigned char *)&metadata; + + uint32_t calc_crc = tf_crc32(0U, data + sizeof(metadata.crc_32), + (sizeof(metadata) - + sizeof(metadata.crc_32))); + + if (metadata.crc_32 != calc_crc) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Check the sanity of FWU metadata. + * + * return -1 on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_sanity_check(void) +{ + /* ToDo: add more conditions for sanity check */ + if ((metadata.active_index >= NR_OF_FW_BANKS) || + (metadata.previous_active_index >= NR_OF_FW_BANKS)) { + return -1; + } + + return 0; +} + +/******************************************************************************* + * Verify and load specified FWU metadata image to local FWU metadata structure. + * + * @image_id: FWU metadata image id (either FWU_METADATA_IMAGE_ID or + * BKUP_FWU_METADATA_IMAGE_ID) + * + * return a negative value on error, otherwise 0 + ******************************************************************************/ +static int fwu_metadata_load(unsigned int image_id) +{ + int result; + uintptr_t dev_handle, image_handle, image_spec; + size_t bytes_read; + + assert((image_id == FWU_METADATA_IMAGE_ID) || + (image_id == BKUP_FWU_METADATA_IMAGE_ID)); + + result = plat_fwu_set_metadata_image_source(image_id, + &dev_handle, + &image_spec); + if (result != 0) { + WARN("Failed to set reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + WARN("Failed to load image id id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_read(image_handle, (uintptr_t)&metadata, + sizeof(struct fwu_metadata), &bytes_read); + + if (result != 0) { + WARN("Failed to read image id=%u (%i)\n", image_id, result); + goto exit; + } + + if (sizeof(struct fwu_metadata) != bytes_read) { + /* return -1 in case of partial/no read */ + result = -1; + WARN("Read bytes (%zu) instead of expected (%zu) bytes\n", + bytes_read, sizeof(struct fwu_metadata)); + goto exit; + } + + /* sanity check on loaded parameters */ + result = fwu_metadata_sanity_check(); + if (result != 0) { + WARN("Sanity %s\n", "check failed on FWU metadata"); + goto exit; + } + + /* CRC check on loaded parameters */ + result = fwu_metadata_crc_check(); + if (result != 0) { + WARN("CRC %s\n", "check failed on FWU metadata"); + } + +exit: + (void)io_close(image_handle); + + return result; +} + +/******************************************************************************* + * The system runs in the trial run state if any of the images in the active + * firmware bank has not been accepted yet. + * + * Returns true if the system is running in the trial state. + ******************************************************************************/ +bool fwu_is_trial_run_state(void) +{ + bool trial_run = false; + + assert(is_metadata_initialized); + + for (unsigned int i = 0U; i < NR_OF_IMAGES_IN_FW_BANK; i++) { + struct fwu_image_entry *entry = &metadata.img_entry[i]; + struct fwu_image_properties *img_props = + &entry->img_props[metadata.active_index]; + if (img_props->accepted == 0) { + trial_run = true; + break; + } + } + + return trial_run; +} + +const struct fwu_metadata *fwu_get_metadata(void) +{ + assert(is_metadata_initialized); + + return &metadata; +} + +/******************************************************************************* + * Load verified copy of FWU metadata image kept in the platform NV storage + * into local FWU metadata structure. + * Also, update platform I/O policies with the offset address and length of + * firmware-updated images kept in the platform NV storage. + ******************************************************************************/ +void fwu_init(void) +{ + /* Load FWU metadata which will be used to load the images in the + * active bank as per PSA FWU specification + */ + int result = fwu_metadata_load(FWU_METADATA_IMAGE_ID); + + if (result != 0) { + WARN("loading of FWU-Metadata failed, " + "using Bkup-FWU-Metadata\n"); + + result = fwu_metadata_load(BKUP_FWU_METADATA_IMAGE_ID); + if (result != 0) { + ERROR("loading of Bkup-FWU-Metadata failed\n"); + panic(); + } + } + + is_metadata_initialized = true; + + plat_fwu_set_images_source(&metadata); +} diff --git a/arm-trusted-firmware/drivers/fwu/fwu.mk b/arm-trusted-firmware/drivers/fwu/fwu.mk new file mode 100644 index 0000000..f4452e0 --- /dev/null +++ b/arm-trusted-firmware/drivers/fwu/fwu.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +FWU_SRC_DIR := drivers/fwu/ + +FWU_SRCS := ${FWU_SRC_DIR}fwu.c + +BL2_SOURCES += ${FWU_SRCS} diff --git a/arm-trusted-firmware/drivers/gpio/gpio.c b/arm-trusted-firmware/drivers/gpio/gpio.c new file mode 100644 index 0000000..76612b2 --- /dev/null +++ b/arm-trusted-firmware/drivers/gpio/gpio.c @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * GPIO -- General Purpose Input/Output + * + * Defines a simple and generic interface to access GPIO device. + * + */ + +#include +#include + +#include + +/* + * The gpio implementation + */ +static const gpio_ops_t *ops; + +int gpio_get_direction(int gpio) +{ + assert(ops); + assert(ops->get_direction != 0); + assert(gpio >= 0); + + return ops->get_direction(gpio); +} + +void gpio_set_direction(int gpio, int direction) +{ + assert(ops); + assert(ops->set_direction != 0); + assert((direction == GPIO_DIR_OUT) || (direction == GPIO_DIR_IN)); + assert(gpio >= 0); + + ops->set_direction(gpio, direction); +} + +int gpio_get_value(int gpio) +{ + assert(ops); + assert(ops->get_value != 0); + assert(gpio >= 0); + + return ops->get_value(gpio); +} + +void gpio_set_value(int gpio, int value) +{ + assert(ops); + assert(ops->set_value != 0); + assert((value == GPIO_LEVEL_LOW) || (value == GPIO_LEVEL_HIGH)); + assert(gpio >= 0); + + ops->set_value(gpio, value); +} + +void gpio_set_pull(int gpio, int pull) +{ + assert(ops); + assert(ops->set_pull != 0); + assert((pull == GPIO_PULL_NONE) || (pull == GPIO_PULL_UP) || + (pull == GPIO_PULL_DOWN)); + assert(gpio >= 0); + + ops->set_pull(gpio, pull); +} + +int gpio_get_pull(int gpio) +{ + assert(ops); + assert(ops->get_pull != 0); + assert(gpio >= 0); + + return ops->get_pull(gpio); +} + +/* + * Initialize the gpio. The fields in the provided gpio + * ops pointer must be valid. + */ +void gpio_init(const gpio_ops_t *ops_ptr) +{ + assert(ops_ptr != 0 && + (ops_ptr->get_direction != 0) && + (ops_ptr->set_direction != 0) && + (ops_ptr->get_value != 0) && + (ops_ptr->set_value != 0)); + + ops = ops_ptr; +} diff --git a/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c new file mode 100644 index 0000000..464efe9 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.c @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#define GPTCR_SWR BIT(15) /* Software reset */ +#define GPTCR_24MEN BIT(10) /* Enable 24MHz clock input */ +#define GPTCR_CLKSOURCE_OSC (5 << 6) /* Clock source OSC */ +#define GPTCR_CLKSOURCE_MASK (0x7 << 6) +#define GPTCR_TEN 1 /* Timer enable */ + +#define GPTPR_PRESCL_24M_SHIFT 12 + +#define SYS_COUNTER_FREQ_IN_MHZ 3 + +#define GPTPR_TIMER_CTRL (imx_base_addr + 0x000) +#define GPTPR_TIMER_PRESCL (imx_base_addr + 0x004) +#define GPTPR_TIMER_CNTR (imx_base_addr + 0x024) + +static uintptr_t imx_base_addr; + +uint32_t imx_get_timer_value(void) +{ + return ~mmio_read_32(GPTPR_TIMER_CNTR); +} + +static const timer_ops_t imx_gpt_ops = { + .get_timer_value = imx_get_timer_value, + .clk_mult = 1, + .clk_div = SYS_COUNTER_FREQ_IN_MHZ, +}; + +void imx_gpt_ops_init(uintptr_t base_addr) +{ + int val; + + assert(base_addr != 0); + + imx_base_addr = base_addr; + + /* setup GP Timer */ + mmio_write_32(GPTPR_TIMER_CTRL, GPTCR_SWR); + mmio_write_32(GPTPR_TIMER_CTRL, 0); + + /* get 3MHz from 24MHz */ + mmio_write_32(GPTPR_TIMER_PRESCL, (7 << GPTPR_PRESCL_24M_SHIFT)); + + val = mmio_read_32(GPTPR_TIMER_CTRL); + val &= ~GPTCR_CLKSOURCE_MASK; + val |= GPTCR_24MEN | GPTCR_CLKSOURCE_OSC | GPTCR_TEN; + mmio_write_32(GPTPR_TIMER_CTRL, val); + + timer_init(&imx_gpt_ops); +} diff --git a/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h new file mode 100644 index 0000000..2432633 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/timer/imx_gpt.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_GPT_H +#define IMX_GPT_H + +#include + +void imx_gpt_ops_init(uintptr_t reg_base); + +#endif /* IMX_GPT_H */ diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S b/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S new file mode 100644 index 0000000..aa987b3 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S @@ -0,0 +1,131 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + + .globl imx_crash_uart_init + .globl imx_crash_uart_putc + + /* ----------------------------------------------- + * int imx_crash_uart_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3, r4 + * ----------------------------------------------- + */ +func imx_crash_uart_init + /* Free up r1 as a scratch reg */ + mov r4, r0 + mov r0, r1 + + /* Reset UART via CR2 */ + add r1, r4, #IMX_UART_CR2_OFFSET + movs r3, #0 + str r3, [r4, #IMX_UART_CR2_OFFSET] + + /* Wait for reset complete */ +__wait_cr2_reset: + ldr r3, [r1, #0] + ands r3, #IMX_UART_CR2_SRST + beq __wait_cr2_reset + + /* Enable UART */ + movs r3, #IMX_UART_CR1_UARTEN + mov r1, r2 + str r3, [r4, #IMX_UART_CR1_OFFSET] + + /* + * Ignore RTC/CTS - disable reset + * Magic value #16423 => + * IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST + */ + movw r3, #16423 + str r3, [r4, #IMX_UART_CR2_OFFSET] + + /* + * No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) + * Magic value => #132 + * IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL + */ + movs r3, #132 + str r3, [r4, #IMX_UART_CR3_OFFSET] + + /* + * Set CTS FIFO trigger to 32 bytes bits 15:10 + * Magic value => #32768 + * FIFO trigger bitmask 100000 + * */ + mov r3, #32768 + str r3, [r4, #IMX_UART_CR4_OFFSET] + + /* + * TX/RX-thresh = 2 bytes, DCE (bit6 = 0), refclk @24MHz / 4 + * Magic value #2562 + * IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | IMX_UART_FCR_RFDIV2 + */ + #ifdef IMX_UART_DTE + movw r3, #2626 + #else + movw r3, #2562 + #endif + str r3, [r4, #IMX_UART_FCR_OFFSET] + + /* This BIR should be set to 0x0F prior to writing the BMR */ + movs r3, #15 + str r3, [r4, #IMX_UART_BIR_OFFSET] + + /* Hard-code to 115200 @ 24 MHz */ + movs r0, #104 + str r0, [r4, #IMX_UART_BMR_OFFSET] + + /* Indicate success */ + movs r0, #1 + bx lr +endfunc imx_crash_uart_init + + /* -------------------------------------------------------- + * int imx_crash_uart_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 : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func imx_crash_uart_putc + /* Output specified character to UART shift-register */ + str r0, [r1, #IMX_UART_TXD_OFFSET] + + /* Wait for transmit IMX_UART_STAT2_OFFSET.IMX_UART_STAT2_TXDC == 1 */ +__putc_spin_ready: + ldr r2, [r1, #IMX_UART_STAT2_OFFSET] + ands r2, #IMX_UART_STAT2_TXDC + beq __putc_spin_ready + + /* Transmit complete do we need to fixup \n to \n\r */ + cmp r0, #10 + beq __putc_fixup_lf + + /* No fixup necessary - exit here */ + movs r0, #0 + bx lr + + /* Fixup \n to \n\r */ +__putc_fixup_lf: + movs r0, #13 + b imx_crash_uart_putc +endfunc imx_crash_uart_putc diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_uart.c b/arm-trusted-firmware/drivers/imx/uart/imx_uart.c new file mode 100644 index 0000000..dfe2e92 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_uart.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include + +/* TX/RX FIFO threshold */ +#define TX_RX_THRESH 2 + +struct clk_div_factors { + uint32_t fcr_div; + uint32_t bmr_div; +}; + +static struct clk_div_factors clk_div[] = { + { + .fcr_div = IMX_UART_FCR_RFDIV1, + .bmr_div = 1, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV2, + .bmr_div = 2, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV3, + .bmr_div = 3, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV4, + .bmr_div = 4, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV5, + .bmr_div = 5, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV6, + .bmr_div = 6, + }, + { + .fcr_div = IMX_UART_FCR_RFDIV7, + .bmr_div = 7, + }, +}; + +static void write_reg(uintptr_t base, uint32_t offset, uint32_t val) +{ + mmio_write_32(base + offset, val); +} + +static uint32_t read_reg(uintptr_t base, uint32_t offset) +{ + return mmio_read_32(base + offset); +} + +int console_imx_uart_core_init(uintptr_t base_addr, unsigned int uart_clk, + unsigned int baud_rate) +{ + uint32_t val; + uint8_t clk_idx = 1; + + /* Reset UART */ + write_reg(base_addr, IMX_UART_CR2_OFFSET, 0); + do { + val = read_reg(base_addr, IMX_UART_CR2_OFFSET); + } while (!(val & IMX_UART_CR2_SRST)); + + /* Enable UART */ + write_reg(base_addr, IMX_UART_CR1_OFFSET, IMX_UART_CR1_UARTEN); + + /* Ignore RTS, 8N1, enable tx/rx, disable reset */ + val = (IMX_UART_CR2_IRTS | IMX_UART_CR2_WS | IMX_UART_CR2_TXEN | + IMX_UART_CR2_RXEN | IMX_UART_CR2_SRST); + write_reg(base_addr, IMX_UART_CR2_OFFSET, val); + + /* No parity, autobaud detect-old, rxdmuxsel=1 (fixed i.mx7) */ + val = IMX_UART_CR3_ADNIMP | IMX_UART_CR3_RXDMUXSEL; + write_reg(base_addr, IMX_UART_CR3_OFFSET, val); + + /* Set CTS FIFO trigger to 32 bytes bits 15:10 */ + write_reg(base_addr, IMX_UART_CR4_OFFSET, 0x8000); + + /* TX/RX-thresh = 2 bytes, DTE (bit6 = 0), refclk @24MHz / 4 */ + val = IMX_UART_FCR_TXTL(TX_RX_THRESH) | IMX_UART_FCR_RXTL(TX_RX_THRESH) | + clk_div[clk_idx].fcr_div; + #ifdef IMX_UART_DTE + /* Set DTE (bit6 = 1) */ + val |= IMX_UART_FCR_DCEDTE; + #endif + write_reg(base_addr, IMX_UART_FCR_OFFSET, val); + + /* + * The equation for BAUD rate calculation is + * RefClk = Supplied clock / FCR_DIVx + * + * BAUD = Refclk + * ------------ + * 16 x (UBMR + 1/ UBIR + 1) + * + * We write 0x0f into UBIR to remove the 16 mult + * BAUD = 6000000 + * ------------ + * 16 x (UBMR + 1/ 15 + 1) + */ + + write_reg(base_addr, IMX_UART_BIR_OFFSET, 0x0f); + val = ((uart_clk / clk_div[clk_idx].bmr_div) / baud_rate) - 1; + write_reg(base_addr, IMX_UART_BMR_OFFSET, val); + + return 0; +} + +/* -------------------------------------------------------- + * int console_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 : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +int console_imx_uart_core_putc(int c, uintptr_t base_addr) +{ + uint32_t val; + + if (c == '\n') + console_imx_uart_core_putc('\r', base_addr); + + /* Write data */ + write_reg(base_addr, IMX_UART_TXD_OFFSET, c); + + /* Wait for transmit */ + do { + val = read_reg(base_addr, IMX_UART_STAT2_OFFSET); + } while (!(val & IMX_UART_STAT2_TXDC)); + + return 0; +} + +/* + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on error. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +int console_imx_uart_core_getc(uintptr_t base_addr) +{ + uint32_t val; + + val = read_reg(base_addr, IMX_UART_TS_OFFSET); + if (val & IMX_UART_TS_RXEMPTY) + return -1; + + val = read_reg(base_addr, IMX_UART_RXD_OFFSET); + return (int)(val & 0x000000FF); +} + +/* + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +void console_imx_uart_core_flush(uintptr_t base_addr) +{ +} + diff --git a/arm-trusted-firmware/drivers/imx/uart/imx_uart.h b/arm-trusted-firmware/drivers/imx/uart/imx_uart.h new file mode 100644 index 0000000..a133024 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/uart/imx_uart.h @@ -0,0 +1,163 @@ +/* + * Copyright (c) Linaro 2018 Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef IMX_UART_H +#define IMX_UART_H + +#include + +#define IMX_UART_RXD_OFFSET 0x00 +#define IMX_UART_RXD_CHARRDY BIT(15) +#define IMX_UART_RXD_ERR BIT(14) +#define IMX_UART_RXD_OVERRUN BIT(13) +#define IMX_UART_RXD_FRMERR BIT(12) +#define IMX_UART_RXD_BRK BIT(11) +#define IMX_UART_RXD_PRERR BIT(10) + +#define IMX_UART_TXD_OFFSET 0x40 + +#define IMX_UART_CR1_OFFSET 0x80 +#define IMX_UART_CR1_ADEN BIT(15) +#define IMX_UART_CR1_ADBR BIT(14) +#define IMX_UART_CR1_TRDYEN BIT(13) +#define IMX_UART_CR1_IDEN BIT(12) +#define IMX_UART_CR1_RRDYEN BIT(9) +#define IMX_UART_CR1_RXDMAEN BIT(8) +#define IMX_UART_CR1_IREN BIT(7) +#define IMX_UART_CR1_TXMPTYEN BIT(6) +#define IMX_UART_CR1_RTSDEN BIT(5) +#define IMX_UART_CR1_SNDBRK BIT(4) +#define IMX_UART_CR1_TXDMAEN BIT(3) +#define IMX_UART_CR1_ATDMAEN BIT(2) +#define IMX_UART_CR1_DOZE BIT(1) +#define IMX_UART_CR1_UARTEN BIT(0) + +#define IMX_UART_CR2_OFFSET 0x84 +#define IMX_UART_CR2_ESCI BIT(15) +#define IMX_UART_CR2_IRTS BIT(14) +#define IMX_UART_CR2_CTSC BIT(13) +#define IMX_UART_CR2_CTS BIT(12) +#define IMX_UART_CR2_ESCEN BIT(11) +#define IMX_UART_CR2_PREN BIT(8) +#define IMX_UART_CR2_PROE BIT(7) +#define IMX_UART_CR2_STPB BIT(6) +#define IMX_UART_CR2_WS BIT(5) +#define IMX_UART_CR2_RTSEN BIT(4) +#define IMX_UART_CR2_ATEN BIT(3) +#define IMX_UART_CR2_TXEN BIT(2) +#define IMX_UART_CR2_RXEN BIT(1) +#define IMX_UART_CR2_SRST BIT(0) + +#define IMX_UART_CR3_OFFSET 0x88 +#define IMX_UART_CR3_DTREN BIT(13) +#define IMX_UART_CR3_PARERREN BIT(12) +#define IMX_UART_CR3_FARERREN BIT(11) +#define IMX_UART_CR3_DSD BIT(10) +#define IMX_UART_CR3_DCD BIT(9) +#define IMX_UART_CR3_RI BIT(8) +#define IMX_UART_CR3_ADNIMP BIT(7) +#define IMX_UART_CR3_RXDSEN BIT(6) +#define IMX_UART_CR3_AIRINTEN BIT(5) +#define IMX_UART_CR3_AWAKEN BIT(4) +#define IMX_UART_CR3_DTRDEN BIT(3) +#define IMX_UART_CR3_RXDMUXSEL BIT(2) +#define IMX_UART_CR3_INVT BIT(1) +#define IMX_UART_CR3_ACIEN BIT(0) + +#define IMX_UART_CR4_OFFSET 0x8c +#define IMX_UART_CR4_INVR BIT(9) +#define IMX_UART_CR4_ENIRI BIT(8) +#define IMX_UART_CR4_WKEN BIT(7) +#define IMX_UART_CR4_IDDMAEN BIT(6) +#define IMX_UART_CR4_IRSC BIT(5) +#define IMX_UART_CR4_LPBYP BIT(4) +#define IMX_UART_CR4_TCEN BIT(3) +#define IMX_UART_CR4_BKEN BIT(2) +#define IMX_UART_CR4_OREN BIT(1) +#define IMX_UART_CR4_DREN BIT(0) + +#define IMX_UART_FCR_OFFSET 0x90 +#define IMX_UART_FCR_TXTL_MASK (BIT(15) | BIT(14) | BIT(13) | BIT(12) |\ + BIT(11) | BIT(10)) +#define IMX_UART_FCR_TXTL(x) ((x) << 10) +#define IMX_UART_FCR_RFDIV_MASK (BIT(9) | BIT(8) | BIT(7)) +#define IMX_UART_FCR_RFDIV7 (BIT(9) | BIT(8)) +#define IMX_UART_FCR_RFDIV1 (BIT(9) | BIT(7)) +#define IMX_UART_FCR_RFDIV2 BIT(9) +#define IMX_UART_FCR_RFDIV3 (BIT(8) | BIT(7)) +#define IMX_UART_FCR_RFDIV4 BIT(8) +#define IMX_UART_FCR_RFDIV5 BIT(7) +#define IMX_UART_FCR_RFDIV6 0 +#define IMX_UART_FCR_DCEDTE BIT(6) +#define IMX_UART_FCR_RXTL_MASK (BIT(5) | BIT(4) | BIT(3) | BIT(2) |\ + BIT(1) | BIT(0)) +#define IMX_UART_FCR_RXTL(x) x + +#define IMX_UART_STAT1_OFFSET 0x94 +#define IMX_UART_STAT1_PARITYERR BIT(15) +#define IMX_UART_STAT1_RTSS BIT(14) +#define IMX_UART_STAT1_TRDY BIT(13) +#define IMX_UART_STAT1_RTSD BIT(12) +#define IMX_UART_STAT1_ESCF BIT(11) +#define IMX_UART_STAT1_FRAMEERR BIT(10) +#define IMX_UART_STAT1_RRDY BIT(9) +#define IMX_UART_STAT1_AGTIM BIT(8) +#define IMX_UART_STAT1_DTRD BIT(7) +#define IMX_UART_STAT1_RXDS BIT(6) +#define IMX_UART_STAT1_AIRINT BIT(5) +#define IMX_UART_STAT1_AWAKE BIT(4) +#define IMX_UART_STAT1_SAD BIT(3) + +#define IMX_UART_STAT2_OFFSET 0x98 +#define IMX_UART_STAT2_ADET BIT(15) +#define IMX_UART_STAT2_TXFE BIT(14) +#define IMX_UART_STAT2_DTRF BIT(13) +#define IMX_UART_STAT2_IDLE BIT(12) +#define IMX_UART_STAT2_ACST BIT(11) +#define IMX_UART_STAT2_RIDELT BIT(10) +#define IMX_UART_STAT2_RIIN BIT(9) +#define IMX_UART_STAT2_IRINT BIT(8) +#define IMX_UART_STAT2_WAKE BIT(7) +#define IMX_UART_STAT2_DCDDELT BIT(6) +#define IMX_UART_STAT2_DCDIN BIT(5) +#define IMX_UART_STAT2_RTSF BIT(4) +#define IMX_UART_STAT2_TXDC BIT(3) +#define IMX_UART_STAT2_BRCD BIT(2) +#define IMX_UART_STAT2_ORE BIT(1) +#define IMX_UART_STAT2_RCR BIT(0) + +#define IMX_UART_ESC_OFFSET 0x9c + +#define IMX_UART_TIM_OFFSET 0xa0 + +#define IMX_UART_BIR_OFFSET 0xa4 + +#define IMX_UART_BMR_OFFSET 0xa8 + +#define IMX_UART_BRC_OFFSET 0xac + +#define IMX_UART_ONEMS_OFFSET 0xb0 + +#define IMX_UART_TS_OFFSET 0xb4 +#define IMX_UART_TS_FRCPERR BIT(13) +#define IMX_UART_TS_LOOP BIT(12) +#define IMX_UART_TS_DBGEN BIT(11) +#define IMX_UART_TS_LOOPIR BIT(10) +#define IMX_UART_TS_RXDBG BIT(9) +#define IMX_UART_TS_TXEMPTY BIT(6) +#define IMX_UART_TS_RXEMPTY BIT(5) +#define IMX_UART_TS_TXFULL BIT(4) +#define IMX_UART_TS_RXFULL BIT(3) +#define IMX_UART_TS_SOFTRST BIT(0) + +#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/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c new file mode 100644 index 0000000..07f55b7 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c @@ -0,0 +1,302 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +static void imx_usdhc_initialize(void); +static int imx_usdhc_send_cmd(struct mmc_cmd *cmd); +static int imx_usdhc_set_ios(unsigned int clk, unsigned int width); +static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size); +static int imx_usdhc_read(int lba, uintptr_t buf, size_t size); +static int imx_usdhc_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops imx_usdhc_ops = { + .init = imx_usdhc_initialize, + .send_cmd = imx_usdhc_send_cmd, + .set_ios = imx_usdhc_set_ios, + .prepare = imx_usdhc_prepare, + .read = imx_usdhc_read, + .write = imx_usdhc_write, +}; + +static imx_usdhc_params_t imx_usdhc_params; + +#define IMX7_MMC_SRC_CLK_RATE (200 * 1000 * 1000) +static void imx_usdhc_set_clk(int clk) +{ + int div = 1; + int pre_div = 1; + unsigned int sdhc_clk = IMX7_MMC_SRC_CLK_RATE; + uintptr_t reg_base = imx_usdhc_params.reg_base; + + assert(clk > 0); + + while (sdhc_clk / (16 * pre_div) > clk && pre_div < 256) + pre_div *= 2; + + while (sdhc_clk / div > clk && div < 16) + div++; + + pre_div >>= 1; + div -= 1; + clk = (pre_div << 8) | (div << 4); + + mmio_clrbits32(reg_base + VENDSPEC, VENDSPEC_CARD_CLKEN); + mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_CLOCK_MASK, clk); + udelay(10000); + + mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_PER_CLKEN | VENDSPEC_CARD_CLKEN); +} + +static void imx_usdhc_initialize(void) +{ + unsigned int timeout = 10000; + uintptr_t reg_base = imx_usdhc_params.reg_base; + + assert((imx_usdhc_params.reg_base & MMC_BLOCK_MASK) == 0); + + /* reset the controller */ + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTA); + + /* wait for reset done */ + while ((mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTA)) { + if (!timeout) + ERROR("IMX MMC reset timeout.\n"); + timeout--; + } + + mmio_write_32(reg_base + MMCBOOT, 0); + mmio_write_32(reg_base + MIXCTRL, 0); + mmio_write_32(reg_base + CLKTUNECTRLSTS, 0); + + mmio_write_32(reg_base + VENDSPEC, VENDSPEC_INIT); + mmio_write_32(reg_base + DLLCTRL, 0); + mmio_setbits32(reg_base + VENDSPEC, VENDSPEC_IPG_CLKEN | VENDSPEC_PER_CLKEN); + + /* Set the initial boot clock rate */ + imx_usdhc_set_clk(MMC_BOOT_CLK_RATE); + udelay(100); + + /* Clear read/write ready status */ + mmio_clrbits32(reg_base + INTSTATEN, INTSTATEN_BRR | INTSTATEN_BWR); + + /* configure as little endian */ + mmio_write_32(reg_base + PROTCTRL, PROTCTRL_LE); + + /* Set timeout to the maximum value */ + mmio_clrsetbits32(reg_base + SYSCTRL, SYSCTRL_TIMEOUT_MASK, + SYSCTRL_TIMEOUT(15)); + + /* set wartermark level as 16 for safe for MMC */ + mmio_clrsetbits32(reg_base + WATERMARKLEV, WMKLV_MASK, 16 | (16 << 16)); +} + +#define FSL_CMD_RETRIES 1000 + +static int imx_usdhc_send_cmd(struct mmc_cmd *cmd) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + unsigned int xfertype = 0, mixctl = 0, multiple = 0, data = 0, err = 0; + unsigned int state, flags = INTSTATEN_CC | INTSTATEN_CTOE; + unsigned int cmd_retries = 0; + + assert(cmd); + + /* clear all irq status */ + mmio_write_32(reg_base + INTSTAT, 0xffffffff); + + /* Wait for the bus to be idle */ + do { + state = mmio_read_32(reg_base + PSTATE); + } while (state & (PSTATE_CDIHB | PSTATE_CIHB)); + + while (mmio_read_32(reg_base + PSTATE) & PSTATE_DLA) + ; + + mmio_write_32(reg_base + INTSIGEN, 0); + udelay(1000); + + switch (cmd->cmd_idx) { + case MMC_CMD(12): + xfertype |= XFERTYPE_CMDTYP_ABORT; + break; + case MMC_CMD(18): + multiple = 1; + /* fall thru for read op */ + case MMC_CMD(17): + case MMC_CMD(8): + mixctl |= MIXCTRL_DTDSEL; + data = 1; + break; + case MMC_CMD(25): + multiple = 1; + /* fall thru for data op flag */ + case MMC_CMD(24): + data = 1; + break; + default: + break; + } + + if (multiple) { + mixctl |= MIXCTRL_MSBSEL; + mixctl |= MIXCTRL_BCEN; + } + + if (data) { + xfertype |= XFERTYPE_DPSEL; + mixctl |= MIXCTRL_DMAEN; + } + + if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) + xfertype |= XFERTYPE_RSPTYP_48; + else if (cmd->resp_type & MMC_RSP_136) + xfertype |= XFERTYPE_RSPTYP_136; + else if (cmd->resp_type & MMC_RSP_BUSY) + xfertype |= XFERTYPE_RSPTYP_48_BUSY; + + if (cmd->resp_type & MMC_RSP_CMD_IDX) + xfertype |= XFERTYPE_CICEN; + + if (cmd->resp_type & MMC_RSP_CRC) + xfertype |= XFERTYPE_CCCEN; + + xfertype |= XFERTYPE_CMD(cmd->cmd_idx); + + /* Send the command */ + mmio_write_32(reg_base + CMDARG, cmd->cmd_arg); + mmio_clrsetbits32(reg_base + MIXCTRL, MIXCTRL_DATMASK, mixctl); + mmio_write_32(reg_base + XFERTYPE, xfertype); + + /* Wait for the command done */ + do { + state = mmio_read_32(reg_base + INTSTAT); + if (cmd_retries) + udelay(1); + } while ((!(state & flags)) && ++cmd_retries < FSL_CMD_RETRIES); + + if ((state & (INTSTATEN_CTOE | CMD_ERR)) || cmd_retries == FSL_CMD_RETRIES) { + if (cmd_retries == FSL_CMD_RETRIES) + err = -ETIMEDOUT; + else + err = -EIO; + ERROR("imx_usdhc mmc cmd %d state 0x%x errno=%d\n", + cmd->cmd_idx, state, err); + goto out; + } + + /* Copy the response to the response buffer */ + if (cmd->resp_type & MMC_RSP_136) { + unsigned int cmdrsp3, cmdrsp2, cmdrsp1, cmdrsp0; + + cmdrsp3 = mmio_read_32(reg_base + CMDRSP3); + cmdrsp2 = mmio_read_32(reg_base + CMDRSP2); + cmdrsp1 = mmio_read_32(reg_base + CMDRSP1); + cmdrsp0 = mmio_read_32(reg_base + CMDRSP0); + cmd->resp_data[3] = (cmdrsp3 << 8) | (cmdrsp2 >> 24); + cmd->resp_data[2] = (cmdrsp2 << 8) | (cmdrsp1 >> 24); + cmd->resp_data[1] = (cmdrsp1 << 8) | (cmdrsp0 >> 24); + cmd->resp_data[0] = (cmdrsp0 << 8); + } else { + cmd->resp_data[0] = mmio_read_32(reg_base + CMDRSP0); + } + + /* Wait until all of the blocks are transferred */ + if (data) { + flags = DATA_COMPLETE; + do { + state = mmio_read_32(reg_base + INTSTAT); + + if (state & (INTSTATEN_DTOE | DATA_ERR)) { + err = -EIO; + ERROR("imx_usdhc mmc data state 0x%x\n", state); + goto out; + } + } while ((state & flags) != flags); + } + +out: + /* Reset CMD and DATA on error */ + if (err) { + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTC); + while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTC) + ; + + if (data) { + mmio_setbits32(reg_base + SYSCTRL, SYSCTRL_RSTD); + while (mmio_read_32(reg_base + SYSCTRL) & SYSCTRL_RSTD) + ; + } + } + + /* clear all irq status */ + mmio_write_32(reg_base + INTSTAT, 0xffffffff); + + return err; +} + +static int imx_usdhc_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + + imx_usdhc_set_clk(clk); + + if (width == MMC_BUS_WIDTH_4) + mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, + PROTCTRL_WIDTH_4); + else if (width == MMC_BUS_WIDTH_8) + mmio_clrsetbits32(reg_base + PROTCTRL, PROTCTRL_WIDTH_MASK, + PROTCTRL_WIDTH_8); + + return 0; +} + +static int imx_usdhc_prepare(int lba, uintptr_t buf, size_t size) +{ + uintptr_t reg_base = imx_usdhc_params.reg_base; + + mmio_write_32(reg_base + DSADDR, buf); + mmio_write_32(reg_base + BLKATT, + (size / MMC_BLOCK_SIZE) << 16 | MMC_BLOCK_SIZE); + + return 0; +} + +static int imx_usdhc_read(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +static int imx_usdhc_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +void imx_usdhc_init(imx_usdhc_params_t *params, + struct mmc_device_info *mmc_dev_info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0) && + (params->clk_rate > 0) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&imx_usdhc_params, params, sizeof(imx_usdhc_params_t)); + mmc_init(&imx_usdhc_ops, params->clk_rate, params->bus_width, + params->flags, mmc_dev_info); +} diff --git a/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h new file mode 100644 index 0000000..e063316 --- /dev/null +++ b/arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_USDHC_H +#define IMX_USDHC_H + +#include + +typedef struct imx_usdhc_params { + uintptr_t reg_base; + int clk_rate; + int bus_width; + unsigned int flags; +} imx_usdhc_params_t; + +void imx_usdhc_init(imx_usdhc_params_t *params, + struct mmc_device_info *mmc_dev_info); + +/* iMX MMC registers definition */ +#define DSADDR 0x000 +#define BLKATT 0x004 +#define CMDARG 0x008 +#define CMDRSP0 0x010 +#define CMDRSP1 0x014 +#define CMDRSP2 0x018 +#define CMDRSP3 0x01c + +#define XFERTYPE 0x00c +#define XFERTYPE_CMD(x) (((x) & 0x3f) << 24) +#define XFERTYPE_CMDTYP_ABORT (3 << 22) +#define XFERTYPE_DPSEL BIT(21) +#define XFERTYPE_CICEN BIT(20) +#define XFERTYPE_CCCEN BIT(19) +#define XFERTYPE_RSPTYP_136 BIT(16) +#define XFERTYPE_RSPTYP_48 BIT(17) +#define XFERTYPE_RSPTYP_48_BUSY (BIT(16) | BIT(17)) + +#define PSTATE 0x024 +#define PSTATE_DAT0 BIT(24) +#define PSTATE_DLA BIT(2) +#define PSTATE_CDIHB BIT(1) +#define PSTATE_CIHB BIT(0) + +#define PROTCTRL 0x028 +#define PROTCTRL_LE BIT(5) +#define PROTCTRL_WIDTH_4 BIT(1) +#define PROTCTRL_WIDTH_8 BIT(2) +#define PROTCTRL_WIDTH_MASK 0x6 + +#define SYSCTRL 0x02c +#define SYSCTRL_RSTD BIT(26) +#define SYSCTRL_RSTC BIT(25) +#define SYSCTRL_RSTA BIT(24) +#define SYSCTRL_CLOCK_MASK 0x0000fff0 +#define SYSCTRL_TIMEOUT_MASK 0x000f0000 +#define SYSCTRL_TIMEOUT(x) ((0xf & (x)) << 16) + +#define INTSTAT 0x030 +#define INTSTAT_DMAE BIT(28) +#define INTSTAT_DEBE BIT(22) +#define INTSTAT_DCE BIT(21) +#define INTSTAT_DTOE BIT(20) +#define INTSTAT_CIE BIT(19) +#define INTSTAT_CEBE BIT(18) +#define INTSTAT_CCE BIT(17) +#define INTSTAT_DINT BIT(3) +#define INTSTAT_BGE BIT(2) +#define INTSTAT_TC BIT(1) +#define INTSTAT_CC BIT(0) +#define CMD_ERR (INTSTAT_CIE | INTSTAT_CEBE | INTSTAT_CCE) +#define DATA_ERR (INTSTAT_DMAE | INTSTAT_DEBE | INTSTAT_DCE | \ + INTSTAT_DTOE) +#define DATA_COMPLETE (INTSTAT_DINT | INTSTAT_TC) + +#define INTSTATEN 0x034 +#define INTSTATEN_DEBE BIT(22) +#define INTSTATEN_DCE BIT(21) +#define INTSTATEN_DTOE BIT(20) +#define INTSTATEN_CIE BIT(19) +#define INTSTATEN_CEBE BIT(18) +#define INTSTATEN_CCE BIT(17) +#define INTSTATEN_CTOE BIT(16) +#define INTSTATEN_CINT BIT(8) +#define INTSTATEN_BRR BIT(5) +#define INTSTATEN_BWR BIT(4) +#define INTSTATEN_DINT BIT(3) +#define INTSTATEN_TC BIT(1) +#define INTSTATEN_CC BIT(0) +#define EMMC_INTSTATEN_BITS (INTSTATEN_CC | INTSTATEN_TC | INTSTATEN_DINT | \ + INTSTATEN_BWR | INTSTATEN_BRR | INTSTATEN_CINT | \ + INTSTATEN_CTOE | INTSTATEN_CCE | INTSTATEN_CEBE | \ + INTSTATEN_CIE | INTSTATEN_DTOE | INTSTATEN_DCE | \ + INTSTATEN_DEBE) + +#define INTSIGEN 0x038 + +#define WATERMARKLEV 0x044 +#define WMKLV_RD_MASK 0xff +#define WMKLV_WR_MASK 0x00ff0000 +#define WMKLV_MASK (WMKLV_RD_MASK | WMKLV_WR_MASK) + +#define MIXCTRL 0x048 +#define MIXCTRL_MSBSEL BIT(5) +#define MIXCTRL_DTDSEL BIT(4) +#define MIXCTRL_DDREN BIT(3) +#define MIXCTRL_AC12EN BIT(2) +#define MIXCTRL_BCEN BIT(1) +#define MIXCTRL_DMAEN BIT(0) +#define MIXCTRL_DATMASK 0x7f + +#define DLLCTRL 0x060 + +#define CLKTUNECTRLSTS 0x068 + +#define VENDSPEC 0x0c0 +#define VENDSPEC_RSRV1 BIT(29) +#define VENDSPEC_CARD_CLKEN BIT(14) +#define VENDSPEC_PER_CLKEN BIT(13) +#define VENDSPEC_AHB_CLKEN BIT(12) +#define VENDSPEC_IPG_CLKEN BIT(11) +#define VENDSPEC_AC12_CHKBUSY BIT(3) +#define VENDSPEC_EXTDMA BIT(0) +#define VENDSPEC_INIT (VENDSPEC_RSRV1 | VENDSPEC_CARD_CLKEN | \ + VENDSPEC_PER_CLKEN | VENDSPEC_AHB_CLKEN | \ + VENDSPEC_IPG_CLKEN | VENDSPEC_AC12_CHKBUSY | \ + VENDSPEC_EXTDMA) + +#define MMCBOOT 0x0c4 + +#define mmio_clrsetbits32(addr, clear, set) mmio_write_32(addr, (mmio_read_32(addr) & ~(clear)) | (set)) +#define mmio_clrbits32(addr, clear) mmio_write_32(addr, mmio_read_32(addr) & ~(clear)) +#define mmio_setbits32(addr, set) mmio_write_32(addr, mmio_read_32(addr) | (set)) + +#endif /* IMX_USDHC_H */ diff --git a/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c b/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c new file mode 100644 index 0000000..dcd1991 --- /dev/null +++ b/arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c @@ -0,0 +1,253 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "qspi/cadence_qspi.h" + +/* As we need to be able to keep state for seek, only one file can be open + * at a time. Make this a structure and point to the entity->info. When we + * can malloc memory we can change this to support more open files. + */ +typedef struct { + /* Use the 'in_use' flag as any value for base and file_pos could be + * valid. + */ + int in_use; + uintptr_t base; + unsigned long long file_pos; + unsigned long long size; +} file_state_t; + +static file_state_t current_file = {0}; + +/* Identify the device type as memmap */ +static io_type_t device_type_memmap(void) +{ + return IO_TYPE_MEMMAP; +} + +/* Memmap device functions */ +static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset); +static int memmap_block_len(io_entity_t *entity, size_t *length); +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int memmap_block_close(io_entity_t *entity); +static int memmap_dev_close(io_dev_info_t *dev_info); + + +static const io_dev_connector_t memmap_dev_connector = { + .dev_open = memmap_dev_open +}; + + +static const io_dev_funcs_t memmap_dev_funcs = { + .type = device_type_memmap, + .open = memmap_block_open, + .seek = memmap_block_seek, + .size = memmap_block_len, + .read = memmap_block_read, + .write = memmap_block_write, + .close = memmap_block_close, + .dev_init = NULL, + .dev_close = memmap_dev_close, +}; + + +/* No state associated with this device so structure can be const */ +static const io_dev_info_t memmap_dev_info = { + .funcs = &memmap_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the memmap device */ +static int memmap_dev_open(const uintptr_t dev_spec __unused, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&memmap_dev_info; /* cast away const */ + + return 0; +} + + + +/* Close a connection to the memmap device */ +static int memmap_dev_close(io_dev_info_t *dev_info) +{ + /* NOP */ + /* TODO: Consider tracking open files and cleaning them up here */ + return 0; +} + + +/* Open a file on the memmap device */ +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result = -ENOMEM; + const io_block_spec_t *block_spec = (io_block_spec_t *)spec; + + /* Since we need to track open state for seek() we only allow one open + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ + if (current_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_file.in_use = 1; + current_file.base = block_spec->offset; + /* File cursor offset for seek and incremental reads etc. */ + current_file.file_pos = 0; + current_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_file; + result = 0; + } else { + WARN("A Memmap device is already active. Close first.\n"); + } + + return result; +} + + +/* Seek to a particular file offset on the memmap device */ +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset) +{ + int result = -ENOENT; + file_state_t *fp; + + /* We only support IO_SEEK_SET for the moment. */ + if (mode == IO_SEEK_SET) { + assert(entity != NULL); + + fp = (file_state_t *) entity->info; + + /* Assert that new file position is valid */ + assert((offset >= 0) && + ((unsigned long long)offset < fp->size)); + + /* Reset file position */ + fp->file_pos = offset; + result = 0; + } + + return result; +} + + +/* Return the size of a file on the memmap device */ +static int memmap_block_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = ((file_state_t *)entity->info)->size; + + return 0; +} + + +/* Read data from a file on the memmap device */ +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); + + fp = (file_state_t *) entity->info; + + /* Assert that file position is valid for this read operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + //memcpy((void *)buffer, (void *)(fp->base + fp->file_pos), length); + cad_qspi_read((void *)buffer, fp->base + fp->file_pos, length); + *length_read = length; + + /* Set file position after read */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Write data to a file on the memmap device */ +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); + + fp = (file_state_t *) entity->info; + + /* Assert that file position is valid for this write operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + memcpy((void *)(fp->base + fp->file_pos), (void *)buffer, length); + + *length_written = length; + + /* Set file position after write */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Close a file on the memmap device */ +static int memmap_block_close(io_entity_t *entity) +{ + assert(entity != NULL); + + entity->info = 0; + + /* This would be a mem free() if we had malloc.*/ + zeromem((void *)¤t_file, sizeof(current_file)); + + return 0; +} + + +/* Exported functions */ + +/* Register the memmap driver with the IO abstraction */ +int register_io_dev_memmap(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&memmap_dev_info); + if (result == 0) + *dev_con = &memmap_dev_connector; + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_block.c b/arm-trusted-firmware/drivers/io/io_block.c new file mode 100644 index 0000000..5d45c2f --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_block.c @@ -0,0 +1,551 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +typedef struct { + io_block_dev_spec_t *dev_spec; + uintptr_t base; + unsigned long long file_pos; + unsigned long long size; +} block_dev_state_t; + +#define is_power_of_2(x) (((x) != 0U) && (((x) & ((x) - 1U)) == 0U)) + +io_type_t device_type_block(void); + +static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int block_seek(io_entity_t *entity, int mode, signed long long offset); +static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int block_close(io_entity_t *entity); +static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int block_dev_close(io_dev_info_t *dev_info); + +static const io_dev_connector_t block_dev_connector = { + .dev_open = block_dev_open +}; + +static const io_dev_funcs_t block_dev_funcs = { + .type = device_type_block, + .open = block_open, + .seek = block_seek, + .size = NULL, + .read = block_read, + .write = block_write, + .close = block_close, + .dev_init = NULL, + .dev_close = block_dev_close, +}; + +static block_dev_state_t state_pool[MAX_IO_BLOCK_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_IO_BLOCK_DEVICES]; + +/* Track number of allocated block state */ +static unsigned int block_dev_count; + +io_type_t device_type_block(void) +{ + return IO_TYPE_BLOCK; +} + +/* Locate a block state in the pool, specified by address */ +static int find_first_block_state(const io_block_dev_spec_t *dev_spec, + unsigned int *index_out) +{ + unsigned int index; + int result = -ENOENT; + + for (index = 0U; index < MAX_IO_BLOCK_DEVICES; ++index) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + +/* Allocate a device info from the pool and return a pointer to it */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + int result = -ENOMEM; + assert(dev_info != NULL); + + if (block_dev_count < MAX_IO_BLOCK_DEVICES) { + unsigned int index = 0; + result = find_first_block_state(NULL, &index); + assert(result == 0); + /* initialize dev_info */ + dev_info_pool[index].funcs = &block_dev_funcs; + dev_info_pool[index].info = (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + ++block_dev_count; + } + + return result; +} + + +/* Release a device info to the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0; + block_dev_state_t *state; + assert(dev_info != NULL); + + state = (block_dev_state_t *)dev_info->info; + result = find_first_block_state(state->dev_spec, &index); + if (result == 0) { + /* free if device info is valid */ + zeromem(state, sizeof(block_dev_state_t)); + zeromem(dev_info, sizeof(io_dev_info_t)); + --block_dev_count; + } + + return result; +} + +static int block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + block_dev_state_t *cur; + io_block_spec_t *region; + + assert((dev_info->info != (uintptr_t)NULL) && + (spec != (uintptr_t)NULL) && + (entity->info == (uintptr_t)NULL)); + + region = (io_block_spec_t *)spec; + cur = (block_dev_state_t *)dev_info->info; + assert(((region->offset % cur->dev_spec->block_size) == 0) && + ((region->length % cur->dev_spec->block_size) == 0)); + + cur->base = region->offset; + cur->size = region->length; + cur->file_pos = 0; + + entity->info = (uintptr_t)cur; + return 0; +} + +/* parameter offset is relative address at here */ +static int block_seek(io_entity_t *entity, int mode, signed long long offset) +{ + block_dev_state_t *cur; + + assert(entity->info != (uintptr_t)NULL); + + cur = (block_dev_state_t *)entity->info; + assert((offset >= 0) && ((unsigned long long)offset < cur->size)); + + switch (mode) { + case IO_SEEK_SET: + cur->file_pos = (unsigned long long)offset; + break; + case IO_SEEK_CUR: + cur->file_pos += (unsigned long long)offset; + break; + default: + return -EINVAL; + } + assert(cur->file_pos < cur->size); + return 0; +} + +/* + * This function allows the caller to read any number of bytes + * from any position. It hides from the caller that the low level + * driver only can read aligned blocks of data. For this reason + * we need to handle the use case where the first byte to be read is not + * aligned to start of the block, the last byte to be read is also not + * aligned to the end of a block, and there are zero or more blocks-worth + * of data in between. + * + * In such a case we need to read more bytes than requested (i.e. full + * blocks) and strip-out the leading bytes (aka skip) and the trailing + * bytes (aka padding). See diagram below + * + * cur->file_pos ------------ + * | + * cur->base | + * | | + * v v<---- length ----> + * -------------------------------------------------------------- + * | | block#1 | | block#n | + * | block#0 | + | ... | + | + * | | <- skip -> + | | + <- padding ->| + * ------------------------+----------------------+-------------- + * ^ ^ + * | | + * v iteration#1 iteration#n v + * -------------------------------------------------- + * | | | | + * |<---- request ---->| ... |<----- request ---->| + * | | | | + * -------------------------------------------------- + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * / / | | + * <---- request ------> <------ request -----> + * --------------------- ----------------------- + * | | | | | | + * |<-skip->|<-nbytes->| -------->|<-nbytes->|<-padding->| + * | | | | | | | + * --------------------- | ----------------------- + * ^ \ \ | | | + * | \ \ | | | + * | \ \ | | | + * buf->offset \ \ buf->offset | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * \ \ | | + * -------------------------------- + * | | | | + * buffer-------------->| | ... | | + * | | | | + * -------------------------------- + * <-count#1->| | + * <---------- count#n --------> + * <---------- length ----------> + * + * Additionally, the IO driver has an underlying buffer that is at least + * one block-size and may be big enough to allow. + */ +static int block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + block_dev_state_t *cur; + io_block_spec_t *buf; + io_block_ops_t *ops; + int lba; + size_t block_size, left; + size_t nbytes; /* number of bytes read in one iteration */ + size_t request; /* number of requested bytes in one iteration */ + size_t count; /* number of bytes already read */ + /* + * number of leading bytes from start of the block + * to the first byte to be read + */ + size_t skip; + + /* + * number of trailing bytes between the last byte + * to be read and the end of the block + */ + size_t padding; + + assert(entity->info != (uintptr_t)NULL); + cur = (block_dev_state_t *)entity->info; + ops = &(cur->dev_spec->ops); + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && + (length > 0U) && + (ops->read != 0)); + + /* + * We don't know the number of bytes that we are going + * to read in every iteration, because it will depend + * on the low level driver. + */ + count = 0; + for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, + * we have to request the operation to start at the + * previous block boundary and skip the leading bytes. And + * similarly, the number of bytes requested must be a + * block size multiple + */ + skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos + * - e.g. block 3. + */ + lba = (cur->file_pos + cur->base) / block_size; + + if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just + * fill the buffer, and then read again. + */ + request = buf->length; + } else { + /* + * The underlying read buffer is big enough to + * read all the required data. Calculate the + * number of bytes to read to align with the + * block size. + */ + request = skip + left; + request = (request + (block_size - 1U)) & + ~(block_size - 1U); + } + request = ops->read(lba, buf->offset, request); + + if (request <= skip) { + /* + * We couldn't read enough bytes to jump over + * the skip bytes, so we should have to read + * again the same block, thus generating + * the same error. + */ + return -EIO; + } + + /* + * Need to remove skip and padding bytes,if any, from + * the read data when copying to the user buffer. + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + memcpy((void *)(buffer + count), + (void *)(buf->offset + skip), + nbytes); + + cur->file_pos += nbytes; + count += nbytes; + } + assert(count == length); + *length_read = count; + + return 0; +} + +/* + * This function allows the caller to write any number of bytes + * from any position. It hides from the caller that the low level + * driver only can write aligned blocks of data. + * See comments for block_read for more details. + */ +static int block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + block_dev_state_t *cur; + io_block_spec_t *buf; + io_block_ops_t *ops; + int lba; + size_t block_size, left; + size_t nbytes; /* number of bytes read in one iteration */ + size_t request; /* number of requested bytes in one iteration */ + size_t count; /* number of bytes already read */ + /* + * number of leading bytes from start of the block + * to the first byte to be read + */ + size_t skip; + + /* + * number of trailing bytes between the last byte + * to be read and the end of the block + */ + size_t padding; + + assert(entity->info != (uintptr_t)NULL); + cur = (block_dev_state_t *)entity->info; + ops = &(cur->dev_spec->ops); + buf = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((length <= cur->size) && + (length > 0U) && + (ops->read != 0) && + (ops->write != 0)); + + /* + * We don't know the number of bytes that we are going + * to write in every iteration, because it will depend + * on the low level driver. + */ + count = 0; + for (left = length; left > 0U; left -= nbytes) { + /* + * We must only request operations aligned to the block + * size. Therefore if file_pos is not block-aligned, + * we have to request the operation to start at the + * previous block boundary and skip the leading bytes. And + * similarly, the number of bytes requested must be a + * block size multiple + */ + skip = cur->file_pos & (block_size - 1U); + + /* + * Calculate the block number containing file_pos + * - e.g. block 3. + */ + lba = (cur->file_pos + cur->base) / block_size; + + if ((skip + left) > buf->length) { + /* + * The underlying read buffer is too small to + * read all the required data - limit to just + * fill the buffer, and then read again. + */ + request = buf->length; + } else { + /* + * The underlying read buffer is big enough to + * read all the required data. Calculate the + * number of bytes to read to align with the + * block size. + */ + request = skip + left; + request = (request + (block_size - 1U)) & + ~(block_size - 1U); + } + + /* + * The number of bytes that we are going to write + * from the user buffer will depend of the size + * of the current request. + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + /* + * If we have skip or padding bytes then we have to preserve + * some content and it means that we have to read before + * writing + */ + if ((skip > 0U) || (padding > 0U)) { + request = ops->read(lba, buf->offset, request); + /* + * The read may return size less than + * requested. Round down to the nearest block + * boundary + */ + request &= ~(block_size - 1U); + if (request <= skip) { + /* + * We couldn't read enough bytes to jump over + * the skip bytes, so we should have to read + * again the same block, thus generating + * the same error. + */ + return -EIO; + } + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + } + + memcpy((void *)(buf->offset + skip), + (void *)(buffer + count), + nbytes); + + request = ops->write(lba, buf->offset, request); + if (request <= skip) + return -EIO; + + /* + * And the previous write operation may modify the size + * of the request, so again, we have to calculate the + * number of bytes that we consumed from the user + * buffer + */ + nbytes = request - skip; + padding = (nbytes > left) ? nbytes - left : 0U; + nbytes -= padding; + + cur->file_pos += nbytes; + count += nbytes; + } + assert(count == length); + *length_written = count; + + return 0; +} + +static int block_close(io_entity_t *entity) +{ + entity->info = (uintptr_t)NULL; + return 0; +} + +static int block_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + block_dev_state_t *cur; + io_block_spec_t *buffer; + io_dev_info_t *info; + size_t block_size; + int result; + + assert(dev_info != NULL); + result = allocate_dev_info(&info); + if (result != 0) + return -ENOENT; + + cur = (block_dev_state_t *)info->info; + /* dev_spec is type of io_block_dev_spec_t. */ + cur->dev_spec = (io_block_dev_spec_t *)dev_spec; + buffer = &(cur->dev_spec->buffer); + block_size = cur->dev_spec->block_size; + assert((block_size > 0U) && + (is_power_of_2(block_size) != 0U) && + ((buffer->offset % block_size) == 0U) && + ((buffer->length % block_size) == 0U)); + + *dev_info = info; /* cast away const */ + (void)block_size; + (void)buffer; + return 0; +} + +static int block_dev_close(io_dev_info_t *dev_info) +{ + return free_dev_info(dev_info); +} + +/* Exported functions */ + +/* Register the Block driver with the IO abstraction */ +int register_io_dev_block(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + /* + * Since dev_info isn't really used in io_register_device, always + * use the same device info at here instead. + */ + result = io_register_device(&dev_info_pool[0]); + if (result == 0) + *dev_con = &block_dev_connector; + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_dummy.c b/arm-trusted-firmware/drivers/io/io_dummy.c new file mode 100644 index 0000000..4f0cda6 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_dummy.c @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +struct file_state { + int in_use; + size_t size; +}; + +static struct file_state current_file = {0}; + +/* Identify the device type as dummy */ +static io_type_t device_type_dummy(void) +{ + return IO_TYPE_DUMMY; +} + +/* Dummy device functions */ +static int dummy_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int dummy_block_len(io_entity_t *entity, size_t *length); +static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int dummy_block_close(io_entity_t *entity); +static int dummy_dev_close(io_dev_info_t *dev_info); + + +static const io_dev_connector_t dummy_dev_connector = { + .dev_open = dummy_dev_open +}; + + +static const io_dev_funcs_t dummy_dev_funcs = { + .type = device_type_dummy, + .open = dummy_block_open, + .seek = NULL, + .size = dummy_block_len, + .read = dummy_block_read, + .write = NULL, + .close = dummy_block_close, + .dev_init = NULL, + .dev_close = dummy_dev_close, +}; + + +static const io_dev_info_t dummy_dev_info = { + .funcs = &dummy_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the dummy device */ +static int dummy_dev_open(const uintptr_t dev_spec __attribute__((unused)), + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&dummy_dev_info; + + return 0; +} + + +/* Close a connection to the dummy device */ +static int dummy_dev_close(io_dev_info_t *dev_info) +{ + return 0; +} + + +/* Open a file on the dummy device */ +static int dummy_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + const io_block_spec_t *block_spec = (io_block_spec_t *)spec; + + if (current_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_file.in_use = 1; + current_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_file; + result = 0; + } else { + WARN("A Dummy device is already active. Close first.\n"); + result = -ENOMEM; + } + + return result; +} + + +/* Return the size of a file on the dummy device */ +static int dummy_block_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = ((struct file_state *)entity->info)->size; + + return 0; +} + + +/* Read data from a file on the dummy device */ +static int dummy_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + assert(length_read != NULL); + + *length_read = length; + + return 0; +} + + +/* Close a file on the dummy device */ +static int dummy_block_close(io_entity_t *entity) +{ + assert(entity != NULL); + + entity->info = 0; + current_file.in_use = 0; + + return 0; +} + + +/* Exported functions */ + +/* Register the dummy driver with the IO abstraction */ +int register_io_dev_dummy(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&dummy_dev_info); + if (result == 0) + *dev_con = &dummy_dev_connector; + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_encrypted.c b/arm-trusted-firmware/drivers/io/io_encrypted.c new file mode 100644 index 0000000..744ca83 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_encrypted.c @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t backend_dev_handle; +static uintptr_t backend_dev_spec; +static uintptr_t backend_handle; +static uintptr_t backend_image_spec; + +static io_dev_info_t enc_dev_info; + +/* Encrypted firmware driver functions */ +static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int enc_file_len(io_entity_t *entity, size_t *length); +static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int enc_file_close(io_entity_t *entity); +static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int enc_dev_close(io_dev_info_t *dev_info); + +static inline int is_valid_header(struct fw_enc_hdr *header) +{ + if (header->magic == ENC_HEADER_MAGIC) + return 1; + else + return 0; +} + +static io_type_t device_type_enc(void) +{ + return IO_TYPE_ENCRYPTED; +} + +static const io_dev_connector_t enc_dev_connector = { + .dev_open = enc_dev_open +}; + +static const io_dev_funcs_t enc_dev_funcs = { + .type = device_type_enc, + .open = enc_file_open, + .seek = NULL, + .size = enc_file_len, + .read = enc_file_read, + .write = NULL, + .close = enc_file_close, + .dev_init = enc_dev_init, + .dev_close = enc_dev_close, +}; + +static int enc_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + + enc_dev_info.funcs = &enc_dev_funcs; + *dev_info = &enc_dev_info; + + return 0; +} + +static int enc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + int result; + unsigned int image_id = (unsigned int)init_params; + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(image_id, &backend_dev_handle, + &backend_dev_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + return -ENOENT; + } + + return result; +} + +static int enc_dev_close(io_dev_info_t *dev_info) +{ + backend_dev_handle = (uintptr_t)NULL; + backend_dev_spec = (uintptr_t)NULL; + + return 0; +} + +static int enc_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + + assert(spec != 0); + assert(entity != NULL); + + backend_image_spec = spec; + + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open backend device (%i)\n", result); + result = -ENOENT; + } + + return result; +} + +static int enc_file_len(io_entity_t *entity, size_t *length) +{ + int result; + + assert(entity != NULL); + assert(length != NULL); + + result = io_size(backend_handle, length); + if (result != 0) { + WARN("Failed to read blob length (%i)\n", result); + return -ENOENT; + } + + /* + * Encryption header is attached at the beginning of the encrypted file + * and is not considered a part of the payload. + */ + if (*length < sizeof(struct fw_enc_hdr)) + return -EIO; + + *length -= sizeof(struct fw_enc_hdr); + + return result; +} + +static int enc_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result; + struct fw_enc_hdr header; + enum fw_enc_status_t fw_enc_status; + size_t bytes_read; + uint8_t key[ENC_MAX_KEY_SIZE]; + size_t key_len = sizeof(key); + unsigned int key_flags = 0; + const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)backend_image_spec; + + assert(entity != NULL); + assert(length_read != NULL); + + result = io_read(backend_handle, (uintptr_t)&header, sizeof(header), + &bytes_read); + if (result != 0) { + WARN("Failed to read encryption header (%i)\n", result); + return -ENOENT; + } + + if (!is_valid_header(&header)) { + WARN("Encryption header check failed.\n"); + return -ENOENT; + } + + VERBOSE("Encryption header looks OK.\n"); + fw_enc_status = header.flags & FW_ENC_STATUS_FLAG_MASK; + + if ((header.iv_len > ENC_MAX_IV_SIZE) || + (header.tag_len > ENC_MAX_TAG_SIZE)) { + WARN("Incorrect IV or tag length\n"); + return -ENOENT; + } + + result = io_read(backend_handle, buffer, length, &bytes_read); + if (result != 0) { + WARN("Failed to read encrypted payload (%i)\n", result); + return -ENOENT; + } + + *length_read = bytes_read; + + result = plat_get_enc_key_info(fw_enc_status, key, &key_len, &key_flags, + (uint8_t *)&uuid_spec->uuid, + sizeof(uuid_t)); + if (result != 0) { + WARN("Failed to obtain encryption key (%i)\n", result); + return -ENOENT; + } + + result = crypto_mod_auth_decrypt(header.dec_algo, + (void *)buffer, *length_read, key, + key_len, key_flags, header.iv, + header.iv_len, header.tag, + header.tag_len); + memset(key, 0, key_len); + + if (result != 0) { + ERROR("File decryption failed (%i)\n", result); + return -ENOENT; + } + + return result; +} + +static int enc_file_close(io_entity_t *entity) +{ + io_close(backend_handle); + + backend_image_spec = (uintptr_t)NULL; + entity->info = 0; + + return 0; +} + +/* Exported functions */ + +/* Register the Encrypted Firmware driver with the IO abstraction */ +int register_io_dev_enc(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&enc_dev_info); + if (result == 0) + *dev_con = &enc_dev_connector; + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_fip.c b/arm-trusted-firmware/drivers/io/io_fip.c new file mode 100644 index 0000000..6e15295 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_fip.c @@ -0,0 +1,481 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef MAX_FIP_DEVICES +#define MAX_FIP_DEVICES 1 +#endif + +/* Useful for printing UUIDs when debugging.*/ +#define PRINT_UUID2(x) \ + "%08x-%04hx-%04hx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx", \ + x.time_low, x.time_mid, x.time_hi_and_version, \ + x.clock_seq_hi_and_reserved, x.clock_seq_low, \ + x.node[0], x.node[1], x.node[2], x.node[3], \ + x.node[4], x.node[5] + +typedef struct { + unsigned int file_pos; + fip_toc_entry_t entry; +} fip_file_state_t; + +/* + * Maintain dev_spec per FIP Device + * TODO - Add backend handles and file state + * per FIP device here once backends like io_memmap + * can support multiple open files + */ +typedef struct { + uintptr_t dev_spec; + uint16_t plat_toc_flag; +} fip_dev_state_t; + +/* + * Only one file can be open across all FIP device + * as backends like io_memmap don't support + * multiple open files. The file state and + * backend handle should be maintained per FIP device + * if the same support is available in the backend + */ +static fip_file_state_t current_fip_file = {0}; +static uintptr_t backend_dev_handle; +static uintptr_t backend_image_spec; + +static fip_dev_state_t state_pool[MAX_FIP_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_FIP_DEVICES]; + +/* Track number of allocated fip devices */ +static unsigned int fip_dev_count; + +/* Firmware Image Package driver functions */ +static int fip_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int fip_file_len(io_entity_t *entity, size_t *length); +static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int fip_file_close(io_entity_t *entity); +static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int fip_dev_close(io_dev_info_t *dev_info); + + +/* Return 0 for equal uuids. */ +static inline int compare_uuids(const uuid_t *uuid1, const uuid_t *uuid2) +{ + return memcmp(uuid1, uuid2, sizeof(uuid_t)); +} + + +static inline int is_valid_header(fip_toc_header_t *header) +{ + if ((header->name == TOC_HEADER_NAME) && (header->serial_number != 0)) { + return 1; + } else { + return 0; + } +} + + +/* Identify the device type as a virtual driver */ +static io_type_t device_type_fip(void) +{ + return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; +} + + +static const io_dev_connector_t fip_dev_connector = { + .dev_open = fip_dev_open +}; + + +static const io_dev_funcs_t fip_dev_funcs = { + .type = device_type_fip, + .open = fip_file_open, + .seek = NULL, + .size = fip_file_len, + .read = fip_file_read, + .write = NULL, + .close = fip_file_close, + .dev_init = fip_dev_init, + .dev_close = fip_dev_close, +}; + +/* Locate a file state in the pool, specified by address */ +static int find_first_fip_state(const uintptr_t dev_spec, + unsigned int *index_out) +{ + int result = -ENOENT; + unsigned int index; + + for (index = 0; index < (unsigned int)MAX_FIP_DEVICES; ++index) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + + +/* Allocate a device info from the pool and return a pointer to it */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + int result = -ENOMEM; + + assert(dev_info != NULL); + + if (fip_dev_count < (unsigned int)MAX_FIP_DEVICES) { + unsigned int index = 0; + + result = find_first_fip_state(0, &index); + assert(result == 0); + /* initialize dev_info */ + dev_info_pool[index].funcs = &fip_dev_funcs; + dev_info_pool[index].info = + (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + ++fip_dev_count; + } + + return result; +} + +/* Release a device info to the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0; + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + result = find_first_fip_state(state->dev_spec, &index); + if (result == 0) { + /* free if device info is valid */ + zeromem(state, sizeof(fip_dev_state_t)); + --fip_dev_count; + } + + return result; +} + +/* + * Multiple FIP devices can be opened depending on the value of + * MAX_FIP_DEVICES. Given that there is only one backend, only a + * single file can be open at a time by any FIP device. + */ +static int fip_dev_open(const uintptr_t dev_spec, + io_dev_info_t **dev_info) +{ + int result; + io_dev_info_t *info; + fip_dev_state_t *state; + + assert(dev_info != NULL); +#if MAX_FIP_DEVICES > 1 + assert(dev_spec != (uintptr_t)NULL); +#endif + + result = allocate_dev_info(&info); + if (result != 0) + return -ENOMEM; + + state = (fip_dev_state_t *)info->info; + + state->dev_spec = dev_spec; + + *dev_info = info; + + return 0; +} + + +/* Do some basic package checks. */ +static int fip_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + int result; + unsigned int image_id = (unsigned int)init_params; + uintptr_t backend_handle; + fip_toc_header_t header; + size_t bytes_read; + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(image_id, &backend_dev_handle, + &backend_image_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + result = -ENOENT; + goto fip_dev_init_exit; + } + + /* Attempt to access the FIP image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + result = -ENOENT; + goto fip_dev_init_exit; + } + + result = io_read(backend_handle, (uintptr_t)&header, sizeof(header), + &bytes_read); + if (result == 0) { + if (!is_valid_header(&header)) { + WARN("Firmware Image Package header check failed.\n"); + result = -ENOENT; + } else { + VERBOSE("FIP header looks OK.\n"); + /* + * Store 16-bit Platform ToC flags field which occupies + * bits [32-47] in fip header. + */ + state->plat_toc_flag = (header.flags >> 32) & 0xffff; + } + } + + io_close(backend_handle); + + fip_dev_init_exit: + return result; +} + +/* Close a connection to the FIP device */ +static int fip_dev_close(io_dev_info_t *dev_info) +{ + /* TODO: Consider tracking open files and cleaning them up here */ + + /* Clear the backend. */ + backend_dev_handle = (uintptr_t)NULL; + backend_image_spec = (uintptr_t)NULL; + + return free_dev_info(dev_info); +} + + +/* Open a file for access from package. */ +static int fip_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result; + uintptr_t backend_handle; + const io_uuid_spec_t *uuid_spec = (io_uuid_spec_t *)spec; + static const uuid_t uuid_null = { {0} }; /* Double braces for clang */ + size_t bytes_read; + int found_file = 0; + + assert(uuid_spec != NULL); + assert(entity != NULL); + + /* Can only have one file open at a time for the moment. We need to + * track state like file cursor position. We know the header lives at + * offset zero, so this entry should never be zero for an active file. + * When the system supports dynamic memory allocation we can allow more + * than one open file at a time if needed. + */ + if (current_fip_file.entry.offset_address != 0U) { + WARN("fip_file_open : Only one open file at a time.\n"); + return -ENFILE; + } + + /* Attempt to access the FIP image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open Firmware Image Package (%i)\n", result); + result = -ENOENT; + goto fip_file_open_exit; + } + + /* Seek past the FIP header into the Table of Contents */ + result = io_seek(backend_handle, IO_SEEK_SET, + (signed long long)sizeof(fip_toc_header_t)); + if (result != 0) { + WARN("fip_file_open: failed to seek\n"); + result = -ENOENT; + goto fip_file_open_close; + } + + found_file = 0; + do { + result = io_read(backend_handle, + (uintptr_t)¤t_fip_file.entry, + sizeof(current_fip_file.entry), + &bytes_read); + if (result == 0) { + if (compare_uuids(¤t_fip_file.entry.uuid, + &uuid_spec->uuid) == 0) { + found_file = 1; + } + } else { + WARN("Failed to read FIP (%i)\n", result); + goto fip_file_open_close; + } + } while ((found_file == 0) && + (compare_uuids(¤t_fip_file.entry.uuid, + &uuid_null) != 0)); + + if (found_file == 1) { + /* All fine. Update entity info with file state and return. Set + * the file position to 0. The 'current_fip_file.entry' holds + * the base and size of the file. + */ + current_fip_file.file_pos = 0; + entity->info = (uintptr_t)¤t_fip_file; + } else { + /* Did not find the file in the FIP. */ + current_fip_file.entry.offset_address = 0; + result = -ENOENT; + } + + fip_file_open_close: + io_close(backend_handle); + + fip_file_open_exit: + return result; +} + + +/* Return the size of a file in package */ +static int fip_file_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = ((fip_file_state_t *)entity->info)->entry.size; + + return 0; +} + + +/* Read data from a file in package */ +static int fip_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result; + fip_file_state_t *fp; + size_t file_offset; + size_t bytes_read; + uintptr_t backend_handle; + + assert(entity != NULL); + assert(length_read != NULL); + assert(entity->info != (uintptr_t)NULL); + + /* Open the backend, attempt to access the blob image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + if (result != 0) { + WARN("Failed to open FIP (%i)\n", result); + result = -ENOENT; + goto fip_file_read_exit; + } + + fp = (fip_file_state_t *)entity->info; + + /* Seek to the position in the FIP where the payload lives */ + file_offset = fp->entry.offset_address + fp->file_pos; + result = io_seek(backend_handle, IO_SEEK_SET, + (signed long long)file_offset); + if (result != 0) { + WARN("fip_file_read: failed to seek\n"); + result = -ENOENT; + goto fip_file_read_close; + } + + result = io_read(backend_handle, buffer, length, &bytes_read); + if (result != 0) { + /* We cannot read our data. Fail. */ + WARN("Failed to read payload (%i)\n", result); + result = -ENOENT; + goto fip_file_read_close; + } else { + /* Set caller length and new file position. */ + *length_read = bytes_read; + fp->file_pos += bytes_read; + } + +/* Close the backend. */ + fip_file_read_close: + io_close(backend_handle); + + fip_file_read_exit: + return result; +} + + +/* Close a file in package */ +static int fip_file_close(io_entity_t *entity) +{ + /* Clear our current file pointer. + * If we had malloc() we would free() here. + */ + if (current_fip_file.entry.offset_address != 0U) { + zeromem(¤t_fip_file, sizeof(current_fip_file)); + } + + /* Clear the Entity info. */ + entity->info = 0; + + return 0; +} + +/* Exported functions */ + +/* Register the Firmware Image Package driver with the IO abstraction */ +int register_io_dev_fip(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + /* + * Since dev_info isn't really used in io_register_device, always + * use the same device info at here instead. + */ + result = io_register_device(&dev_info_pool[0]); + if (result == 0) + *dev_con = &fip_dev_connector; + + return result; +} + +/* Function to retrieve plat_toc_flags, previously saved in FIP dev */ +int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag) +{ + fip_dev_state_t *state; + + assert(dev_info != NULL); + + state = (fip_dev_state_t *)dev_info->info; + + *plat_toc_flag = state->plat_toc_flag; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/io/io_memmap.c b/arm-trusted-firmware/drivers/io/io_memmap.c new file mode 100644 index 0000000..eb69163 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_memmap.c @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include + +/* As we need to be able to keep state for seek, only one file can be open + * at a time. Make this a structure and point to the entity->info. When we + * can malloc memory we can change this to support more open files. + */ +typedef struct { + /* Use the 'in_use' flag as any value for base and file_pos could be + * valid. + */ + int in_use; + uintptr_t base; + unsigned long long file_pos; + unsigned long long size; +} memmap_file_state_t; + +static memmap_file_state_t current_memmap_file = {0}; + +/* Identify the device type as memmap */ +static io_type_t device_type_memmap(void) +{ + return IO_TYPE_MEMMAP; +} + +/* Memmap device functions */ +static int memmap_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset); +static int memmap_block_len(io_entity_t *entity, size_t *length); +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int memmap_block_close(io_entity_t *entity); +static int memmap_dev_close(io_dev_info_t *dev_info); + + +static const io_dev_connector_t memmap_dev_connector = { + .dev_open = memmap_dev_open +}; + + +static const io_dev_funcs_t memmap_dev_funcs = { + .type = device_type_memmap, + .open = memmap_block_open, + .seek = memmap_block_seek, + .size = memmap_block_len, + .read = memmap_block_read, + .write = memmap_block_write, + .close = memmap_block_close, + .dev_init = NULL, + .dev_close = memmap_dev_close, +}; + + +/* No state associated with this device so structure can be const */ +static io_dev_info_t memmap_dev_info = { + .funcs = &memmap_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the memmap device */ +static int memmap_dev_open(const uintptr_t dev_spec __unused, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = &memmap_dev_info; + return 0; +} + + + +/* Close a connection to the memmap device */ +static int memmap_dev_close(io_dev_info_t *dev_info) +{ + /* NOP */ + /* TODO: Consider tracking open files and cleaning them up here */ + return 0; +} + + +/* Open a file on the memmap device */ +static int memmap_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + int result = -ENOMEM; + const io_block_spec_t *block_spec = (io_block_spec_t *)spec; + + /* Since we need to track open state for seek() we only allow one open + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ + if (current_memmap_file.in_use == 0) { + assert(block_spec != NULL); + assert(entity != NULL); + + current_memmap_file.in_use = 1; + current_memmap_file.base = block_spec->offset; + /* File cursor offset for seek and incremental reads etc. */ + current_memmap_file.file_pos = 0; + current_memmap_file.size = block_spec->length; + entity->info = (uintptr_t)¤t_memmap_file; + result = 0; + } else { + WARN("A Memmap device is already active. Close first.\n"); + } + + return result; +} + + +/* Seek to a particular file offset on the memmap device */ +static int memmap_block_seek(io_entity_t *entity, int mode, + signed long long offset) +{ + int result = -ENOENT; + memmap_file_state_t *fp; + + /* We only support IO_SEEK_SET for the moment. */ + if (mode == IO_SEEK_SET) { + assert(entity != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that new file position is valid */ + assert((offset >= 0) && + ((unsigned long long)offset < fp->size)); + + /* Reset file position */ + fp->file_pos = (unsigned long long)offset; + result = 0; + } + + return result; +} + + +/* Return the size of a file on the memmap device */ +static int memmap_block_len(io_entity_t *entity, size_t *length) +{ + assert(entity != NULL); + assert(length != NULL); + + *length = (size_t)((memmap_file_state_t *)entity->info)->size; + + return 0; +} + + +/* Read data from a file on the memmap device */ +static int memmap_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + memmap_file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_read != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that file position is valid for this read operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + memcpy((void *)buffer, + (void *)((uintptr_t)(fp->base + fp->file_pos)), length); + + *length_read = length; + + /* Set file position after read */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Write data to a file on the memmap device */ +static int memmap_block_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + memmap_file_state_t *fp; + unsigned long long pos_after; + + assert(entity != NULL); + assert(length_written != NULL); + + fp = (memmap_file_state_t *) entity->info; + + /* Assert that file position is valid for this write operation */ + pos_after = fp->file_pos + length; + assert((pos_after >= fp->file_pos) && (pos_after <= fp->size)); + + memcpy((void *)((uintptr_t)(fp->base + fp->file_pos)), + (void *)buffer, length); + + *length_written = length; + + /* Set file position after write */ + fp->file_pos = pos_after; + + return 0; +} + + +/* Close a file on the memmap device */ +static int memmap_block_close(io_entity_t *entity) +{ + assert(entity != NULL); + + entity->info = 0; + + /* This would be a mem free() if we had malloc.*/ + zeromem((void *)¤t_memmap_file, sizeof(current_memmap_file)); + + return 0; +} + + +/* Exported functions */ + +/* Register the memmap driver with the IO abstraction */ +int register_io_dev_memmap(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + result = io_register_device(&memmap_dev_info); + if (result == 0) + *dev_con = &memmap_dev_connector; + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_mtd.c b/arm-trusted-firmware/drivers/io/io_mtd.c new file mode 100644 index 0000000..5d86592 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_mtd.c @@ -0,0 +1,290 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +typedef struct { + io_mtd_dev_spec_t *dev_spec; + uintptr_t base; + unsigned long long pos; /* Offset in bytes */ + unsigned long long size; /* Size of device in bytes */ + unsigned long long extra_offset; /* Extra offset in bytes */ +} mtd_dev_state_t; + +io_type_t device_type_mtd(void); + +static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int mtd_seek(io_entity_t *entity, int mode, signed long long offset); +static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int mtd_close(io_entity_t *entity); +static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int mtd_dev_close(io_dev_info_t *dev_info); + +static const io_dev_connector_t mtd_dev_connector = { + .dev_open = mtd_dev_open +}; + +static const io_dev_funcs_t mtd_dev_funcs = { + .type = device_type_mtd, + .open = mtd_open, + .seek = mtd_seek, + .read = mtd_read, + .close = mtd_close, + .dev_close = mtd_dev_close, +}; + +static mtd_dev_state_t state_pool[MAX_IO_MTD_DEVICES]; +static io_dev_info_t dev_info_pool[MAX_IO_MTD_DEVICES]; + +io_type_t device_type_mtd(void) +{ + return IO_TYPE_MTD; +} + +/* Locate a MTD state in the pool, specified by address */ +static int find_first_mtd_state(const io_mtd_dev_spec_t *dev_spec, + unsigned int *index_out) +{ + unsigned int index; + int result = -ENOENT; + + for (index = 0U; index < MAX_IO_MTD_DEVICES; index++) { + /* dev_spec is used as identifier since it's unique */ + if (state_pool[index].dev_spec == dev_spec) { + result = 0; + *index_out = index; + break; + } + } + + return result; +} + +/* Allocate a device info from the pool */ +static int allocate_dev_info(io_dev_info_t **dev_info) +{ + unsigned int index = 0U; + int result; + + result = find_first_mtd_state(NULL, &index); + if (result != 0) { + return -ENOMEM; + } + + dev_info_pool[index].funcs = &mtd_dev_funcs; + dev_info_pool[index].info = (uintptr_t)&state_pool[index]; + *dev_info = &dev_info_pool[index]; + + return 0; +} + +/* Release a device info from the pool */ +static int free_dev_info(io_dev_info_t *dev_info) +{ + int result; + unsigned int index = 0U; + mtd_dev_state_t *state; + + state = (mtd_dev_state_t *)dev_info->info; + result = find_first_mtd_state(state->dev_spec, &index); + if (result != 0) { + return result; + } + + zeromem(state, sizeof(mtd_dev_state_t)); + zeromem(dev_info, sizeof(io_dev_info_t)); + + return 0; +} + +static int mtd_add_extra_offset(mtd_dev_state_t *cur, size_t *extra_offset) +{ + io_mtd_ops_t *ops = &cur->dev_spec->ops; + int ret; + + if (ops->seek == NULL) { + return 0; + } + + ret = ops->seek(cur->base, cur->pos, extra_offset); + if (ret != 0) { + ERROR("%s: Seek error %d\n", __func__, ret); + return ret; + } + + return 0; +} + +static int mtd_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + mtd_dev_state_t *cur; + io_block_spec_t *region; + size_t extra_offset = 0U; + int ret; + + assert((dev_info->info != 0UL) && (entity->info == 0UL)); + + region = (io_block_spec_t *)spec; + cur = (mtd_dev_state_t *)dev_info->info; + entity->info = (uintptr_t)cur; + cur->base = region->offset; + cur->pos = 0U; + cur->extra_offset = 0U; + + ret = mtd_add_extra_offset(cur, &extra_offset); + if (ret != 0) { + return ret; + } + + cur->base += extra_offset; + + return 0; +} + +/* Seek to a specific position using offset */ +static int mtd_seek(io_entity_t *entity, int mode, signed long long offset) +{ + mtd_dev_state_t *cur; + size_t extra_offset = 0U; + int ret; + + assert((entity->info != (uintptr_t)NULL) && (offset >= 0)); + + cur = (mtd_dev_state_t *)entity->info; + + switch (mode) { + case IO_SEEK_SET: + if ((offset >= 0) && + ((unsigned long long)offset >= cur->size)) { + return -EINVAL; + } + + cur->pos = offset; + break; + case IO_SEEK_CUR: + if (((cur->base + cur->pos + (unsigned long long)offset) >= + cur->size) || + ((cur->base + cur->pos + (unsigned long long)offset) < + cur->base + cur->pos)) { + return -EINVAL; + } + + cur->pos += (unsigned long long)offset; + break; + default: + return -EINVAL; + } + + ret = mtd_add_extra_offset(cur, &extra_offset); + if (ret != 0) { + return ret; + } + + cur->extra_offset = extra_offset; + + return 0; +} + +static int mtd_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *out_length) +{ + mtd_dev_state_t *cur; + io_mtd_ops_t *ops; + int ret; + + assert(entity->info != (uintptr_t)NULL); + assert((length > 0U) && (buffer != (uintptr_t)NULL)); + + cur = (mtd_dev_state_t *)entity->info; + ops = &cur->dev_spec->ops; + assert(ops->read != NULL); + + VERBOSE("Read at %llx into %lx, length %zu\n", + cur->base + cur->pos, buffer, length); + if ((cur->base + cur->pos + length) > cur->dev_spec->device_size) { + return -EINVAL; + } + + ret = ops->read(cur->base + cur->pos + cur->extra_offset, buffer, + length, out_length); + if (ret < 0) { + return ret; + } + + assert(*out_length == length); + cur->pos += *out_length; + + return 0; +} + +static int mtd_close(io_entity_t *entity) +{ + entity->info = (uintptr_t)NULL; + + return 0; +} + +static int mtd_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info) +{ + mtd_dev_state_t *cur; + io_dev_info_t *info; + io_mtd_ops_t *ops; + int result; + + result = allocate_dev_info(&info); + if (result != 0) { + return -ENOENT; + } + + cur = (mtd_dev_state_t *)info->info; + cur->dev_spec = (io_mtd_dev_spec_t *)dev_spec; + *dev_info = info; + ops = &(cur->dev_spec->ops); + if (ops->init != NULL) { + result = ops->init(&cur->dev_spec->device_size, + &cur->dev_spec->erase_size); + } + + if (result == 0) { + cur->size = cur->dev_spec->device_size; + } else { + cur->size = 0ULL; + } + + return result; +} + +static int mtd_dev_close(io_dev_info_t *dev_info) +{ + return free_dev_info(dev_info); +} + +/* Exported functions */ + +/* Register the MTD driver in the IO abstraction */ +int register_io_dev_mtd(const io_dev_connector_t **dev_con) +{ + int result; + + result = io_register_device(&dev_info_pool[0]); + if (result == 0) { + *dev_con = &mtd_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_semihosting.c b/arm-trusted-firmware/drivers/io/io_semihosting.c new file mode 100644 index 0000000..1c2f84d --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_semihosting.c @@ -0,0 +1,201 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +/* Identify the device type as semihosting */ +static io_type_t device_type_sh(void) +{ + return IO_TYPE_SEMIHOSTING; +} + + +/* Semi-hosting functions, device info and handle */ + +static int sh_dev_open(const uintptr_t dev_spec, io_dev_info_t **dev_info); +static int sh_file_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset); +static int sh_file_len(io_entity_t *entity, size_t *length); +static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int sh_file_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); +static int sh_file_close(io_entity_t *entity); + +static const io_dev_connector_t sh_dev_connector = { + .dev_open = sh_dev_open +}; + + +static const io_dev_funcs_t sh_dev_funcs = { + .type = device_type_sh, + .open = sh_file_open, + .seek = sh_file_seek, + .size = sh_file_len, + .read = sh_file_read, + .write = sh_file_write, + .close = sh_file_close, + .dev_init = NULL, /* NOP */ + .dev_close = NULL, /* NOP */ +}; + + +static io_dev_info_t sh_dev_info = { + .funcs = &sh_dev_funcs, + .info = (uintptr_t)NULL +}; + + +/* Open a connection to the semi-hosting device */ +static int sh_dev_open(const uintptr_t dev_spec __unused, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + *dev_info = &sh_dev_info; + return 0; +} + + +/* Open a file on the semi-hosting device */ +static int sh_file_open(io_dev_info_t *dev_info __unused, + const uintptr_t spec, io_entity_t *entity) +{ + int result = -ENOENT; + long sh_result; + const io_file_spec_t *file_spec = (const io_file_spec_t *)spec; + + assert(file_spec != NULL); + assert(entity != NULL); + + sh_result = semihosting_file_open(file_spec->path, file_spec->mode); + + if (sh_result > 0) { + entity->info = (uintptr_t)sh_result; + result = 0; + } + return result; +} + + +/* Seek to a particular file offset on the semi-hosting device */ +static int sh_file_seek(io_entity_t *entity, int mode, signed long long offset) +{ + long file_handle, sh_result; + + assert(entity != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_seek(file_handle, (ssize_t)offset); + + return (sh_result == 0) ? 0 : -ENOENT; +} + + +/* Return the size of a file on the semi-hosting device */ +static int sh_file_len(io_entity_t *entity, size_t *length) +{ + int result = -ENOENT; + + assert(entity != NULL); + assert(length != NULL); + + long sh_handle = (long)entity->info; + long sh_result = semihosting_file_length(sh_handle); + + if (sh_result >= 0) { + result = 0; + *length = (size_t)sh_result; + } + + return result; +} + + +/* Read data from a file on the semi-hosting device */ +static int sh_file_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read) +{ + int result = -ENOENT; + long sh_result; + size_t bytes = length; + long file_handle; + + assert(entity != NULL); + assert(length_read != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_read(file_handle, &bytes, buffer); + + if (sh_result >= 0) { + *length_read = (bytes != length) ? bytes : length; + result = 0; + } + + return result; +} + + +/* Write data to a file on the semi-hosting device */ +static int sh_file_write(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written) +{ + long sh_result; + long file_handle; + size_t bytes = length; + + assert(entity != NULL); + assert(length_written != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_write(file_handle, &bytes, buffer); + + *length_written = length - bytes; + + return (sh_result == 0) ? 0 : -ENOENT; +} + + +/* Close a file on the semi-hosting device */ +static int sh_file_close(io_entity_t *entity) +{ + long sh_result; + long file_handle; + + assert(entity != NULL); + + file_handle = (long)entity->info; + + sh_result = semihosting_file_close(file_handle); + + return (sh_result >= 0) ? 0 : -ENOENT; +} + + +/* Exported functions */ + +/* Register the semi-hosting driver with the IO abstraction */ +int register_io_dev_sh(const io_dev_connector_t **dev_con) +{ + int result; + assert(dev_con != NULL); + + result = io_register_device(&sh_dev_info); + if (result == 0) + *dev_con = &sh_dev_connector; + + return result; +} diff --git a/arm-trusted-firmware/drivers/io/io_storage.c b/arm-trusted-firmware/drivers/io/io_storage.c new file mode 100644 index 0000000..0534268 --- /dev/null +++ b/arm-trusted-firmware/drivers/io/io_storage.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* Storage for a fixed maximum number of IO entities, definable by platform */ +static io_entity_t entity_pool[MAX_IO_HANDLES]; + +/* Simple way of tracking used storage - each entry is NULL or a pointer to an + * entity */ +static io_entity_t *entity_map[MAX_IO_HANDLES]; + +/* Track number of allocated entities */ +static unsigned int entity_count; + +/* Array of fixed maximum of registered devices, definable by platform */ +static const io_dev_info_t *devices[MAX_IO_DEVICES]; + +/* Number of currently registered devices */ +static unsigned int dev_count; + +/* Extra validation functions only used when asserts are enabled */ +#if ENABLE_ASSERTIONS + +/* Return a boolean value indicating whether a device connector is valid */ +static bool is_valid_dev_connector(const io_dev_connector_t *dev_con) +{ + return (dev_con != NULL) && (dev_con->dev_open != NULL); +} + +/* Return a boolean value indicating whether a device handle is valid */ +static bool is_valid_dev(const uintptr_t dev_handle) +{ + const io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + return (dev != NULL) && (dev->funcs != NULL) && + (dev->funcs->type != NULL) && + (dev->funcs->type() < IO_TYPE_MAX); +} + + +/* Return a boolean value indicating whether an IO entity is valid */ +static bool is_valid_entity(const uintptr_t handle) +{ + const io_entity_t *entity = (io_entity_t *)handle; + + return (entity != NULL) && + (is_valid_dev((uintptr_t)entity->dev_handle)); +} + + +/* Return a boolean value indicating whether a seek mode is valid */ +static bool is_valid_seek_mode(io_seek_mode_t mode) +{ + return ((mode != IO_SEEK_INVALID) && (mode < IO_SEEK_MAX)); +} + +#endif /* ENABLE_ASSERTIONS */ +/* End of extra validation functions only used when asserts are enabled */ + + +/* Open a connection to a specific device */ +static int io_storage_dev_open(const io_dev_connector_t *dev_con, + const uintptr_t dev_spec, + io_dev_info_t **dev_info) +{ + assert(dev_info != NULL); + assert(is_valid_dev_connector(dev_con)); + + return dev_con->dev_open(dev_spec, dev_info); +} + + +/* Set a handle to track an entity */ +static void set_handle(uintptr_t *handle, io_entity_t *entity) +{ + assert(handle != NULL); + *handle = (uintptr_t)entity; +} + + +/* Locate an entity in the pool, specified by address */ +static int find_first_entity(const io_entity_t *entity, unsigned int *index_out) +{ + int result = -ENOENT; + for (unsigned int index = 0; index < MAX_IO_HANDLES; ++index) { + if (entity_map[index] == entity) { + result = 0; + *index_out = index; + break; + } + } + return result; +} + + +/* Allocate an entity from the pool and return a pointer to it */ +static int allocate_entity(io_entity_t **entity) +{ + int result = -ENOMEM; + assert(entity != NULL); + + if (entity_count < MAX_IO_HANDLES) { + unsigned int index = 0; + result = find_first_entity(NULL, &index); + assert(result == 0); + *entity = &entity_pool[index]; + entity_map[index] = &entity_pool[index]; + ++entity_count; + } + + return result; +} + + +/* Release an entity back to the pool */ +static int free_entity(const io_entity_t *entity) +{ + int result; + unsigned int index = 0; + assert(entity != NULL); + + result = find_first_entity(entity, &index); + if (result == 0) { + entity_map[index] = NULL; + --entity_count; + } + + return result; +} + + +/* Exported API */ + +/* Register a device driver */ +int io_register_device(const io_dev_info_t *dev_info) +{ + int result = -ENOMEM; + assert(dev_info != NULL); + + if (dev_count < MAX_IO_DEVICES) { + devices[dev_count] = dev_info; + dev_count++; + result = 0; + } + + return result; +} + + +/* Open a connection to an IO device */ +int io_dev_open(const io_dev_connector_t *dev_con, const uintptr_t dev_spec, + uintptr_t *handle) +{ + assert(handle != NULL); + return io_storage_dev_open(dev_con, dev_spec, (io_dev_info_t **)handle); +} + + +/* Initialise an IO device explicitly - to permit lazy initialisation or + * re-initialisation */ +int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params) +{ + int result = 0; + assert(dev_handle != (uintptr_t)NULL); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->dev_init != NULL) { + result = dev->funcs->dev_init(dev, init_params); + } + + return result; +} + +/* Close a connection to a device */ +int io_dev_close(uintptr_t dev_handle) +{ + int result = 0; + assert(dev_handle != (uintptr_t)NULL); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->dev_close != NULL) { + result = dev->funcs->dev_close(dev); + } + + return result; +} + + +/* Synchronous operations */ + + +/* Open an IO entity */ +int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle) +{ + int result; + assert((spec != (uintptr_t)NULL) && (handle != NULL)); + assert(is_valid_dev(dev_handle)); + + io_dev_info_t *dev = (io_dev_info_t *)dev_handle; + io_entity_t *entity; + + result = allocate_entity(&entity); + + if (result == 0) { + assert(dev->funcs->open != NULL); + result = dev->funcs->open(dev, spec, entity); + + if (result == 0) { + entity->dev_handle = dev; + set_handle(handle, entity); + } else + free_entity(entity); + } + return result; +} + + +/* Seek to a specific position in an IO entity */ +int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset) +{ + int result = -ENODEV; + assert(is_valid_entity(handle) && is_valid_seek_mode(mode)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->seek != NULL) + result = dev->funcs->seek(entity, mode, offset); + + return result; +} + + +/* Determine the length of an IO entity */ +int io_size(uintptr_t handle, size_t *length) +{ + int result = -ENODEV; + assert(is_valid_entity(handle) && (length != NULL)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->size != NULL) + result = dev->funcs->size(entity, length); + + return result; +} + + +/* Read data from an IO entity */ +int io_read(uintptr_t handle, + uintptr_t buffer, + size_t length, + size_t *length_read) +{ + int result = -ENODEV; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->read != NULL) + result = dev->funcs->read(entity, buffer, length, length_read); + + return result; +} + + +/* Write data to an IO entity */ +int io_write(uintptr_t handle, + const uintptr_t buffer, + size_t length, + size_t *length_written) +{ + int result = -ENODEV; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + if (dev->funcs->write != NULL) { + result = dev->funcs->write(entity, buffer, length, + length_written); + } + + return result; +} + + +/* Close an IO entity */ +int io_close(uintptr_t handle) +{ + int result = 0; + assert(is_valid_entity(handle)); + + io_entity_t *entity = (io_entity_t *)handle; + + io_dev_info_t *dev = entity->dev_handle; + + /* Absence of registered function implies NOP here */ + if (dev->funcs->close != NULL) + result = dev->funcs->close(entity); + + /* Ignore improbable free_entity failure */ + (void)free_entity(entity); + + return result; +} diff --git a/arm-trusted-firmware/drivers/marvell/amb_adec.c b/arm-trusted-firmware/drivers/marvell/amb_adec.c new file mode 100644 index 0000000..d78fa25 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/amb_adec.c @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AXI to M-Bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs */ + +#include +#include + +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) + +#define MVEBU_AMB_ADEC_OFFSET (0x70ff00) + +#define AMB_WIN_CR_OFFSET(win) (amb_base + 0x0 + (0x8 * win)) +#define AMB_ATTR_OFFSET 8 +#define AMB_ATTR_MASK 0xFF +#define AMB_SIZE_OFFSET 16 +#define AMB_SIZE_MASK 0xFF + +#define AMB_WIN_BASE_OFFSET(win) (amb_base + 0x4 + (0x8 * win)) +#define AMB_BASE_OFFSET 16 +#define AMB_BASE_ADDR_MASK ((1 << (32 - AMB_BASE_OFFSET)) - 1) + +#define AMB_WIN_ALIGNMENT_64K (0x10000) +#define AMB_WIN_ALIGNMENT_1M (0x100000) + +uintptr_t amb_base; + +static void amb_check_win(struct addr_map_win *win, uint32_t win_num) +{ + uint32_t base_addr; + + /* make sure the base address is in 16-bit range */ + if (win->base_addr > AMB_BASE_ADDR_MASK) { + WARN("Window %d: base address is too big 0x%" PRIx64 "\n", + win_num, win->base_addr); + win->base_addr = AMB_BASE_ADDR_MASK; + WARN("Set the base address to 0x%" PRIx64 "\n", win->base_addr); + } + + base_addr = win->base_addr << AMB_BASE_OFFSET; + /* for AMB The base is always 1M aligned */ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(base_addr, AMB_WIN_ALIGNMENT_1M)) { + win->base_addr = ALIGN_UP(base_addr, AMB_WIN_ALIGNMENT_1M); + WARN("Window %d: base address unaligned to 0x%x\n", + win_num, AMB_WIN_ALIGNMENT_1M); + WARN("Align up the base address to 0x%" PRIx64 "\n", win->base_addr); + } + + /* size parameter validity check */ + if (!IS_POWER_OF_2(win->win_size)) { + WARN("Window %d: window size is not power of 2 (0x%" PRIx64 ")\n", + win_num, win->win_size); + win->win_size = ROUND_UP_TO_POW_OF_2(win->win_size); + WARN("Rounding size to 0x%" PRIx64 "\n", win->win_size); + } +} + +static void amb_enable_win(struct addr_map_win *win, uint32_t win_num) +{ + uint32_t ctrl, base, size; + + /* + * size is 64KB granularity. + * The number of ones specifies the size of the + * window in 64 KB granularity. 0 is 64KB + */ + size = (win->win_size / AMB_WIN_ALIGNMENT_64K) - 1; + ctrl = (size << AMB_SIZE_OFFSET) | (win->target_id << AMB_ATTR_OFFSET); + base = win->base_addr << AMB_BASE_OFFSET; + + mmio_write_32(AMB_WIN_BASE_OFFSET(win_num), base); + mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl); + + /* enable window after configuring window size (and attributes) */ + ctrl |= WIN_ENABLE_BIT; + mmio_write_32(AMB_WIN_CR_OFFSET(win_num), ctrl); +} + +#ifdef DEBUG_ADDR_MAP +static void dump_amb_adec(void) +{ + uint32_t ctrl, base, win_id, attr; + uint32_t size, size_count; + + /* Dump all AMB windows */ + printf("bank attribute base size\n"); + printf("--------------------------------------------\n"); + for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) { + ctrl = mmio_read_32(AMB_WIN_CR_OFFSET(win_id)); + if (ctrl & WIN_ENABLE_BIT) { + base = mmio_read_32(AMB_WIN_BASE_OFFSET(win_id)); + attr = (ctrl >> AMB_ATTR_OFFSET) & AMB_ATTR_MASK; + size_count = (ctrl >> AMB_SIZE_OFFSET) & AMB_SIZE_MASK; + size = (size_count + 1) * AMB_WIN_ALIGNMENT_64K; + printf("amb 0x%04x 0x%08x 0x%08x\n", + attr, base, size); + } + } +} +#endif + +int init_amb_adec(uintptr_t base) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing AXI to MBus Bridge Address decoding\n"); + + /* Get the base address of the AMB address decoding */ + amb_base = base + MVEBU_AMB_ADEC_OFFSET; + + /* Get the array of the windows and its size */ + marvell_get_amb_memory_map(&win, &win_count, base); + if (win_count <= 0) + INFO("no windows configurations found\n"); + + if (win_count > AMB_MAX_WIN_ID) { + INFO("number of windows is bigger than %d\n", AMB_MAX_WIN_ID); + return 0; + } + + /* disable all AMB windows */ + for (win_id = 0; win_id < AMB_MAX_WIN_ID; win_id++) { + win_reg = mmio_read_32(AMB_WIN_CR_OFFSET(win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(AMB_WIN_CR_OFFSET(win_id), win_reg); + } + + /* enable relevant windows */ + for (win_id = 0; win_id < win_count; win_id++, win++) { + amb_check_win(win, win_id); + amb_enable_win(win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_amb_adec(); +#endif + + INFO("Done AXI to MBus Bridge Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c b/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c new file mode 100644 index 0000000..c1f8619 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c @@ -0,0 +1,109 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include + +#include + +/* Notify bootloader on DRAM setup */ +#define AP807_CPU_ARO_CTRL(cluster) \ + (MVEBU_RFU_BASE + 0x82A8 + (0xA58 * (cluster))) + +/* 0 - ARO clock is enabled, 1 - ARO clock is disabled */ +#define AP807_CPU_ARO_CLK_EN_OFFSET 0 +#define AP807_CPU_ARO_CLK_EN_MASK (0x1 << AP807_CPU_ARO_CLK_EN_OFFSET) + +/* 0 - ARO is the clock source, 1 - PLL is the clock source */ +#define AP807_CPU_ARO_SEL_PLL_OFFSET 5 +#define AP807_CPU_ARO_SEL_PLL_MASK (0x1 << AP807_CPU_ARO_SEL_PLL_OFFSET) + +/* AP807 clusters count */ +#define AP807_CLUSTER_NUM 2 + +/* PLL frequency values */ +#define PLL_FREQ_1200 0x2AE5F002 /* 1200 */ +#define PLL_FREQ_2000 0x2FC9F002 /* 2000 */ +#define PLL_FREQ_2200 0x2AC57001 /* 2200 */ +#define PLL_FREQ_2400 0x2AE5F001 /* 2400 */ + +/* CPU PLL control registers */ +#define AP807_CPU_PLL_CTRL(cluster) \ + (MVEBU_RFU_BASE + 0x82E0 + (0x8 * (cluster))) + +#define AP807_CPU_PLL_PARAM(cluster) AP807_CPU_PLL_CTRL(cluster) +#define AP807_CPU_PLL_CFG(cluster) (AP807_CPU_PLL_CTRL(cluster) + 0x4) +#define AP807_CPU_PLL_CFG_BYPASS_MODE (0x1) +#define AP807_CPU_PLL_FRC_DSCHG (0x2) +#define AP807_CPU_PLL_CFG_USE_REG_FILE (0x1 << 9) + +static void pll_set_freq(unsigned int freq_val) +{ + int i; + + if (freq_val != PLL_FREQ_2200) + return; + + for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) { + /* Set parameter of cluster i PLL to 2.2GHz */ + mmio_write_32(AP807_CPU_PLL_PARAM(i), freq_val); + /* Set apll_lpf_frc_dschg - Control + * voltage of internal VCO is discharged + */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_FRC_DSCHG); + /* Set use_rf_conf load PLL parameter from register */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_FRC_DSCHG | + AP807_CPU_PLL_CFG_USE_REG_FILE); + /* Un-set apll_lpf_frc_dschg */ + mmio_write_32(AP807_CPU_PLL_CFG(i), + AP807_CPU_PLL_CFG_USE_REG_FILE); + } +} + +/* Switch to ARO from PLL in ap807 */ +static void aro_to_pll(void) +{ + unsigned int reg; + int i; + + for (i = 0 ; i < AP807_CLUSTER_NUM ; i++) { + /* switch from ARO to PLL */ + reg = mmio_read_32(AP807_CPU_ARO_CTRL(i)); + reg |= AP807_CPU_ARO_SEL_PLL_MASK; + mmio_write_32(AP807_CPU_ARO_CTRL(i), reg); + + mdelay(100); + + /* disable ARO clk driver */ + reg = mmio_read_32(AP807_CPU_ARO_CTRL(i)); + reg |= (AP807_CPU_ARO_CLK_EN_MASK); + mmio_write_32(AP807_CPU_ARO_CTRL(i), reg); + } +} + +/* switch from ARO to PLL + * in case of default frequency option, configure PLL registers + * to be aligned with new default frequency. + */ +void ap807_clocks_init(unsigned int freq_option) +{ + /* Modifications in frequency table: + * 0x0: 764x: change to 2000 MHz. + * 0x2: 744x change to 1800 MHz, 764x change to 2200/2400. + * 0x3: 3900/744x/764x change to 1200 MHz. + */ + + if (freq_option == CPU_2200_DDR_1200_RCLK_1200) + pll_set_freq(PLL_FREQ_2200); + + /* Switch from ARO to PLL */ + aro_to_pll(); + +} diff --git a/arm-trusted-firmware/drivers/marvell/cache_llc.c b/arm-trusted-firmware/drivers/marvell/cache_llc.c new file mode 100644 index 0000000..4b06b47 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/cache_llc.c @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* LLC driver is the Last Level Cache (L3C) driver + * for Marvell SoCs in AP806, AP807, and AP810 + */ + +#include + +#include +#include +#include +#include + +#include + +#define CCU_HTC_CR(ap_index) (MVEBU_CCU_BASE(ap_index) + 0x200) +#define CCU_SET_POC_OFFSET 5 + +extern void ca72_l2_enable_unique_clean(void); + +void llc_cache_sync(int ap_index) +{ + mmio_write_32(LLC_SYNC(ap_index), 0); + /* Atomic write, no need to wait */ +} + +void llc_flush_all(int ap_index) +{ + mmio_write_32(LLC_CLEAN_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_clean_all(int ap_index) +{ + mmio_write_32(LLC_CLEAN_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_inv_all(int ap_index) +{ + mmio_write_32(LLC_INV_WAY(ap_index), LLC_ALL_WAYS_MASK); + llc_cache_sync(ap_index); +} + +void llc_disable(int ap_index) +{ + llc_flush_all(ap_index); + mmio_write_32(LLC_CTRL(ap_index), 0); + dsbishst(); +} + +void llc_enable(int ap_index, int excl_mode) +{ + uint32_t val; + + dsbsy(); + llc_inv_all(ap_index); + dsbsy(); + + val = LLC_CTRL_EN; + if (excl_mode) + val |= LLC_EXCLUSIVE_EN; + + mmio_write_32(LLC_CTRL(ap_index), val); + dsbsy(); +} + +int llc_is_exclusive(int ap_index) +{ + uint32_t reg; + + reg = mmio_read_32(LLC_CTRL(ap_index)); + + if ((reg & (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) == + (LLC_CTRL_EN | LLC_EXCLUSIVE_EN)) + return 1; + + return 0; +} + +void llc_runtime_enable(int ap_index) +{ + uint32_t reg; + + reg = mmio_read_32(LLC_CTRL(ap_index)); + if (reg & LLC_CTRL_EN) + return; + + INFO("Enabling LLC\n"); + + /* + * Enable L2 UniqueClean evictions with data + * Note: this configuration assumes that LLC is configured + * in exclusive mode. + * Later on in the code this assumption will be validated + */ + ca72_l2_enable_unique_clean(); + llc_enable(ap_index, 1); + + /* Set point of coherency to DDR. + * This is required by units which have SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR(ap_index)); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR(ap_index), reg); +} + +#if LLC_SRAM +int llc_sram_enable(int ap_index, int size) +{ + uint32_t tc, way, ways_to_allocate; + uint32_t way_addr; + + if ((size <= 0) || (size > LLC_SIZE) || (size % LLC_WAY_SIZE)) + return -1; + + llc_enable(ap_index, 1); + llc_inv_all(ap_index); + + ways_to_allocate = size / LLC_WAY_SIZE; + + /* Lockdown all available ways for all traffic classes */ + for (tc = 0; tc < LLC_TC_NUM; tc++) + mmio_write_32(LLC_TCN_LOCK(ap_index, tc), LLC_ALL_WAYS_MASK); + + /* Clear the high bits of SRAM address */ + mmio_write_32(LLC_BANKED_MNT_AHR(ap_index), 0); + + way_addr = PLAT_MARVELL_TRUSTED_RAM_BASE; + for (way = 0; way < ways_to_allocate; way++) { + /* Trigger allocation block command */ + mmio_write_32(LLC_BLK_ALOC(ap_index), + LLC_BLK_ALOC_BASE_ADDR(way_addr) | + LLC_BLK_ALOC_WAY_DATA_SET | + LLC_BLK_ALOC_WAY_ID(way)); + way_addr += LLC_WAY_SIZE; + } + return 0; +} + +void llc_sram_disable(int ap_index) +{ + uint32_t tc; + + /* Disable the line lockings */ + for (tc = 0; tc < LLC_TC_NUM; tc++) + mmio_write_32(LLC_TCN_LOCK(ap_index, tc), 0); + + /* Invalidate all ways */ + llc_inv_all(ap_index); +} + +int llc_sram_test(int ap_index, int size, char *msg) +{ + uintptr_t addr, end_addr; + uint32_t data = 0; + + if ((size <= 0) || (size > LLC_SIZE)) + return -1; + + INFO("=== LLC SRAM WRITE test %s\n", msg); + for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, + end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; + addr < end_addr; addr += 4) { + mmio_write_32(addr, addr); + } + INFO("=== LLC SRAM WRITE test %s PASSED\n", msg); + INFO("=== LLC SRAM READ test %s\n", msg); + for (addr = PLAT_MARVELL_TRUSTED_RAM_BASE, + end_addr = PLAT_MARVELL_TRUSTED_RAM_BASE + size; + addr < end_addr; addr += 4) { + data = mmio_read_32(addr); + if (data != addr) { + INFO("=== LLC SRAM READ test %s FAILED @ 0x%08lx)\n", + msg, addr); + return -1; + } + } + INFO("=== LLC SRAM READ test %s PASSED (last read = 0x%08x)\n", + msg, data); + return 0; +} + +#endif /* LLC_SRAM */ diff --git a/arm-trusted-firmware/drivers/marvell/ccu.c b/arm-trusted-firmware/drivers/marvell/ccu.c new file mode 100644 index 0000000..c206f11 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ccu.c @@ -0,0 +1,417 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {AddrLow[19:0],20'h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define CCU_WIN_ALIGNMENT (0x100000) + +/* + * Physical address of the highest address of window bits[31:19] = 0x6FF + * Physical address of the lowest address of window bits[18:6] = 0x6E0 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0x37f9b809 - 11011111111 0011011100000 0010 0 1 + */ +#define ERRATA_WA_CCU_WIN4 0x37f9b809U + +/* + * Physical address of the highest address of window bits[31:19] = 0xFFF + * Physical address of the lowest address of window bits[18:6] = 0x800 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0x7ffa0009 - 111111111111 0100000000000 0010 0 1 + */ +#define ERRATA_WA_CCU_WIN5 0x7ffa0009U + +/* + * Physical address of the highest address of window bits[31:19] = 0x1FFF + * Physical address of the lowest address of window bits[18:6] = 0x1000 + * Unit Id bits [5:2] = 2 + * RGF Window Enable bit[0] = 1 + * 0xfffc000d - 1111111111111 1000000000000 0011 0 1 + */ +#define ERRATA_WA_CCU_WIN6 0xfffc000dU + +#define IS_DRAM_TARGET(tgt) ((((tgt) == DRAM_0_TID) || \ + ((tgt) == DRAM_1_TID) || \ + ((tgt) == RAR_TID)) ? 1 : 0) + +#define CCU_RGF(win) (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x90 + 4 * (win)) + +/* For storage of CR, SCR, ALR, AHR abd GCR */ +static uint32_t ccu_regs_save[MVEBU_CCU_MAX_WINS * 4 + 1]; + +#ifdef DEBUG_ADDR_MAP +static void dump_ccu(int ap_index) +{ + uint32_t win_id, win_cr, alr, ahr; + uint8_t target_id; + uint64_t start, end; + + /* Dump all AP windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_CCU_MAX_WINS; win_id++) { + win_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + if (win_cr & WIN_ENABLE_BIT) { + target_id = (win_cr >> CCU_TARGET_ID_OFFSET) & + CCU_TARGET_ID_MASK; + alr = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, + win_id)); + ahr = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_index, + win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + printf("\tccu%d %02x 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + win_id, target_id, start, end); + } + } + win_cr = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_index)); + target_id = (win_cr >> CCU_GCR_TARGET_OFFSET) & CCU_GCR_TARGET_MASK; + printf("\tccu GCR %d - all other transactions\n", target_id); +} +#endif + +void ccu_win_check(struct addr_map_win *win) +{ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(win->base_addr, CCU_WIN_ALIGNMENT)) { + win->base_addr = ALIGN_UP(win->base_addr, CCU_WIN_ALIGNMENT); + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, CCU_WIN_ALIGNMENT)) { + win->win_size = ALIGN_UP(win->win_size, CCU_WIN_ALIGNMENT); + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +int ccu_is_win_enabled(int ap_index, uint32_t win_id) +{ + return mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)) & + WIN_ENABLE_BIT; +} + +void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id) +{ + uint32_t ccu_win_reg; + uint32_t alr, ahr; + uint64_t end_addr; + + if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { + ERROR("Enabling wrong CCU window %d!\n", win_id); + return; + } + + end_addr = (win->base_addr + win->win_size - 1); + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + mmio_write_32(CCU_WIN_ALR_OFFSET(ap_index, win_id), alr); + mmio_write_32(CCU_WIN_AHR_OFFSET(ap_index, win_id), ahr); + + ccu_win_reg = WIN_ENABLE_BIT; + ccu_win_reg |= (win->target_id & CCU_TARGET_ID_MASK) + << CCU_TARGET_ID_OFFSET; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), ccu_win_reg); +} + +static void ccu_disable_win(int ap_index, uint32_t win_id) +{ + uint32_t win_reg; + + if ((win_id == 0) || (win_id > MVEBU_CCU_MAX_WINS)) { + ERROR("Disabling wrong CCU window %d!\n", win_id); + return; + } + + win_reg = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_CCU_MAX_WINS - 1 - i; + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_CCU_MAX_WINS - 1 - i; + + target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + target >>= CCU_TARGET_ID_OFFSET; + target &= CCU_TARGET_ID_MASK; + + base = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_index, win_id)); + base <<= ADDRESS_SHIFT; + + if ((win->target_id != target) || (win->base_addr != base)) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + ccu_disable_win(ap_index, win_id); + win++; + } +} + +/* Returns current DRAM window target (DRAM_0_TID, DRAM_1_TID, RAR_TID) + * NOTE: Call only once for each AP. + * The AP0 DRAM window is located at index 2 only at the BL31 execution start. + * Then it relocated to index 1 for matching the rest of APs DRAM settings. + * Calling this function after relocation will produce wrong results on AP0 + */ +static uint32_t ccu_dram_target_get(int ap_index) +{ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * All the rest of detected APs will use window at index 1. + * The AP0 DRAM window is moved from index 2 to 1 during + * init_ccu() execution. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; + uint32_t target; + + target = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + target >>= CCU_TARGET_ID_OFFSET; + target &= CCU_TARGET_ID_MASK; + + return target; +} + +void ccu_dram_target_set(int ap_index, uint32_t target) +{ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * All the rest of detected APs will use window at index 1. + * The AP0 DRAM window is moved from index 2 to 1 + * during init_ccu() execution. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; + uint32_t dram_cr; + + dram_cr = mmio_read_32(CCU_WIN_CR_OFFSET(ap_index, win_id)); + dram_cr &= ~(CCU_TARGET_ID_MASK << CCU_TARGET_ID_OFFSET); + dram_cr |= (target & CCU_TARGET_ID_MASK) << CCU_TARGET_ID_OFFSET; + mmio_write_32(CCU_WIN_CR_OFFSET(ap_index, win_id), dram_cr); +} + +/* Setup CCU DRAM window and enable it */ +void ccu_dram_win_config(int ap_index, struct addr_map_win *win) +{ +#if IMAGE_BLE /* BLE */ + /* On BLE stage the AP0 DRAM window is opened by the BootROM at index 2. + * Since the BootROM is not accessing DRAM at BLE stage, + * the DRAM window can be temporarely disabled. + */ + const uint32_t win_id = (ap_index == 0) ? 2 : 1; +#else /* end of BLE */ + /* At the ccu_init() execution stage, DRAM windows of all APs + * are arranged at index 1. + * The AP0 still has the old window BootROM DRAM at index 2, so + * the window-1 can be safely disabled without breaking the DRAM access. + */ + const uint32_t win_id = 1; +#endif + + ccu_disable_win(ap_index, win_id); + /* enable write secure (and clear read secure) */ + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), + CCU_WIN_ENA_WRITE_SECURE); + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); +} + +/* Save content of CCU window + GCR */ +static void ccu_save_win_range(int ap_id, int win_first, + int win_last, uint32_t *buffer) +{ + int win_id, idx; + /* Save CCU */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + buffer[idx++] = mmio_read_32(CCU_WIN_CR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_SCR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_ALR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(CCU_WIN_AHR_OFFSET(ap_id, win_id)); + } + buffer[idx] = mmio_read_32(CCU_WIN_GCR_OFFSET(ap_id)); +} + +/* Restore content of CCU window + GCR */ +static void ccu_restore_win_range(int ap_id, int win_first, + int win_last, uint32_t *buffer) +{ + int win_id, idx; + /* Restore CCU */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + mmio_write_32(CCU_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(CCU_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]); + } + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_id), buffer[idx]); +} + +void ccu_save_win_all(int ap_id) +{ + ccu_save_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); +} + +void ccu_restore_win_all(int ap_id) +{ + ccu_restore_win_range(ap_id, 0, MVEBU_CCU_MAX_WINS - 1, ccu_regs_save); +} + +int init_ccu(int ap_index) +{ + struct addr_map_win *win, *dram_win; + uint32_t win_id, win_reg; + uint32_t win_count, array_id; + uint32_t dram_target; +#if IMAGE_BLE + /* In BootROM context CCU Window-1 + * has SRAM_TID target and should not be disabled + */ + const uint32_t win_start = 2; +#else + const uint32_t win_start = 1; +#endif + + INFO("Initializing CCU Address decoding\n"); + + /* Get the array of the windows and fill the map data */ + marvell_get_ccu_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) { + INFO("No windows configurations found\n"); + } else if (win_count > (MVEBU_CCU_MAX_WINS - 1)) { + ERROR("CCU mem map array > than max available windows (%d)\n", + MVEBU_CCU_MAX_WINS); + win_count = MVEBU_CCU_MAX_WINS; + } + + /* Need to set GCR to DRAM before all CCU windows are disabled for + * securing the normal access to DRAM location, which the ATF is running + * from. Once all CCU windows are set, which have to include the + * dedicated DRAM window as well, the GCR can be switched to the target + * defined by the platform configuration. + */ + dram_target = ccu_dram_target_get(ap_index); + win_reg = (dram_target & CCU_GCR_TARGET_MASK) << CCU_GCR_TARGET_OFFSET; + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); + + /* If the DRAM window was already configured at the BLE stage, + * only the window target considered valid, the address range should be + * updated according to the platform configuration. + */ + for (dram_win = win, array_id = 0; array_id < win_count; + array_id++, dram_win++) { + if (IS_DRAM_TARGET(dram_win->target_id)) { + dram_win->target_id = dram_target; + break; + } + } + + /* Disable all AP CCU windows + * Window-0 is always bypassed since it already contains + * data allowing the internal configuration space access + */ + for (win_id = win_start; win_id < MVEBU_CCU_MAX_WINS; win_id++) { + ccu_disable_win(ap_index, win_id); + /* enable write secure (and clear read secure) */ + mmio_write_32(CCU_WIN_SCR_OFFSET(ap_index, win_id), + CCU_WIN_ENA_WRITE_SECURE); + } + + /* win_id is the index of the current ccu window + * array_id is the index of the current memory map window entry + */ + for (win_id = win_start, array_id = 0; + ((win_id < MVEBU_CCU_MAX_WINS) && (array_id < win_count)); + win_id++) { + ccu_win_check(win); + ccu_enable_win(ap_index, win, win_id); + win++; + array_id++; + } + + /* Get & set the default target according to board topology */ + win_reg = (marvell_get_ccu_gcr_target(ap_index) & CCU_GCR_TARGET_MASK) + << CCU_GCR_TARGET_OFFSET; + mmio_write_32(CCU_WIN_GCR_OFFSET(ap_index), win_reg); + +#ifdef DEBUG_ADDR_MAP + dump_ccu(ap_index); +#endif + + INFO("Done CCU Address decoding Initializing\n"); + + return 0; +} + +void errata_wa_init(void) +{ + /* + * EERATA ID: RES-3033912 - Internal Address Space Init state causes + * a hang upon accesses to [0xf070_0000, 0xf07f_ffff] + * Workaround: Boot Firmware (ATF) should configure CCU_RGF_WIN(4) to + * split [0x6e_0000, 0x1ff_ffff] to values [0x6e_0000, 0x6f_ffff] and + * [0x80_0000, 0xff_ffff] and [0x100_0000, 0x1ff_ffff],that cause + * accesses to the segment of [0xf070_0000, 0xf1ff_ffff] + * to act as RAZWI. + */ + mmio_write_32(CCU_RGF(4), ERRATA_WA_CCU_WIN4); + mmio_write_32(CCU_RGF(5), ERRATA_WA_CCU_WIN5); + mmio_write_32(CCU_RGF(6), ERRATA_WA_CCU_WIN6); +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy.h b/arm-trusted-firmware/drivers/marvell/comphy.h new file mode 100644 index 0000000..fab564e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy.h @@ -0,0 +1,472 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for COMPHY unit that is part or Marvell A8K SoCs */ + +#ifndef COMPHY_H +#define COMPHY_H + +/* COMPHY registers */ +#define COMMON_PHY_CFG1_REG 0x0 +#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1 +#define COMMON_PHY_CFG1_PWR_UP_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET) +#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2 +#define COMMON_PHY_CFG1_PIPE_SELECT_MASK \ + (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET) +#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 13 +#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET) +#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 14 +#define COMMON_PHY_CFG1_CORE_RSTN_MASK \ + (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET) +#define COMMON_PHY_PHY_MODE_OFFSET 15 +#define COMMON_PHY_PHY_MODE_MASK \ + (0x1 << COMMON_PHY_PHY_MODE_OFFSET) + +#define COMMON_SELECTOR_PHY_OFFSET 0x140 +#define COMMON_SELECTOR_PIPE_OFFSET 0x144 + +#define COMMON_PHY_SD_CTRL1 0x148 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_OFFSET 0 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_4_PORT_MASK 0xFFFF +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24 +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25 +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET) + +#define DFX_DEV_GEN_CTRL12 0x80 +#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7 +#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \ + (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET) + +/* HPIPE register */ +#define HPIPE_PWR_PLL_REG 0x4 +#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0 +#define HPIPE_PWR_PLL_REF_FREQ_MASK \ + (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET) +#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5 +#define HPIPE_PWR_PLL_PHY_MODE_MASK \ + (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET) + +#define HPIPE_DFE_REG0 0x01C +#define HPIPE_DFE_RES_FORCE_OFFSET 15 +#define HPIPE_DFE_RES_FORCE_MASK \ + (0x1 << HPIPE_DFE_RES_FORCE_OFFSET) + +#define HPIPE_G2_SET_1_REG 0x040 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET 0 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET 3 +#define HPIPE_G2_SET_1_G2_RX_SELMUPP_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPP_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET 6 +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET) + +#define HPIPE_G3_SETTINGS_1_REG 0x048 +#define HPIPE_G3_RX_SELMUPI_OFFSET 0 +#define HPIPE_G3_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G3_RX_SELMUPI_OFFSET) +#define HPIPE_G3_RX_SELMUPF_OFFSET 3 +#define HPIPE_G3_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G3_RX_SELMUPF_OFFSET) +#define HPIPE_G3_SETTING_BIT_OFFSET 13 +#define HPIPE_G3_SETTING_BIT_MASK \ + (0x1 << HPIPE_G3_SETTING_BIT_OFFSET) + +#define HPIPE_INTERFACE_REG 0x94 +#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10 +#define HPIPE_INTERFACE_GEN_MAX_MASK \ + (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET) +#define HPIPE_INTERFACE_DET_BYPASS_OFFSET 12 +#define HPIPE_INTERFACE_DET_BYPASS_MASK \ + (0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET) +#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14 +#define HPIPE_INTERFACE_LINK_TRAIN_MASK \ + (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET) + +#define HPIPE_VDD_CAL_CTRL_REG 0x114 +#define HPIPE_EXT_SELLV_RXSAMPL_OFFSET 5 +#define HPIPE_EXT_SELLV_RXSAMPL_MASK \ + (0x1f << HPIPE_EXT_SELLV_RXSAMPL_OFFSET) + +#define HPIPE_PCIE_REG0 0x120 +#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12 +#define HPIPE_PCIE_IDLE_SYNC_MASK \ + (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET) +#define HPIPE_PCIE_SEL_BITS_OFFSET 13 +#define HPIPE_PCIE_SEL_BITS_MASK \ + (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET) + +#define HPIPE_LANE_ALIGN_REG 0x124 +#define HPIPE_LANE_ALIGN_OFF_OFFSET 12 +#define HPIPE_LANE_ALIGN_OFF_MASK \ + (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET) + +#define HPIPE_MISC_REG 0x13C +#define HPIPE_MISC_CLK100M_125M_OFFSET 4 +#define HPIPE_MISC_CLK100M_125M_MASK \ + (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET) +#define HPIPE_MISC_ICP_FORCE_OFFSET 5 +#define HPIPE_MISC_ICP_FORCE_MASK \ + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET) +#define HPIPE_MISC_TXDCLK_2X_OFFSET 6 +#define HPIPE_MISC_TXDCLK_2X_MASK \ + (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET) +#define HPIPE_MISC_CLK500_EN_OFFSET 7 +#define HPIPE_MISC_CLK500_EN_MASK \ + (0x1 << HPIPE_MISC_CLK500_EN_OFFSET) +#define HPIPE_MISC_REFCLK_SEL_OFFSET 10 +#define HPIPE_MISC_REFCLK_SEL_MASK \ + (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET) + +#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C +#define HPIPE_SMAPLER_OFFSET 12 +#define HPIPE_SMAPLER_MASK (0x1 << HPIPE_SMAPLER_OFFSET) + +#define HPIPE_PWR_CTR_DTL_REG 0x184 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET) + +#define HPIPE_FRAME_DET_CONTROL_REG 0x220 +#define HPIPE_FRAME_DET_LOCK_LOST_TO_OFFSET 12 +#define HPIPE_FRAME_DET_LOCK_LOST_TO_MASK \ + (0x1 << HPIPE_FRAME_DET_LOCK_LOST_TO_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268 +#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15 +#define HPIPE_TX_TRAIN_P2P_HOLD_MASK \ + (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_REG 0x26C +#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0 +#define HPIPE_TX_TRAIN_CTRL_G1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1 +#define HPIPE_TX_TRAIN_CTRL_GN1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2 +#define HPIPE_TX_TRAIN_CTRL_G0_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278 +#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_TRX_TRAIN_TIMER_MASK \ + (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4 +#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11 +#define HPIPE_TX_TRAIN_START_SQ_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12 +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13 +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET) +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14 +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET) + +#define HPIPE_TX_TRAIN_REG 0x31C +#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4 +#define HPIPE_TX_TRAIN_CHK_INIT_MASK \ + (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET) +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7 +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK \ + (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET) + +#define HPIPE_CDR_CONTROL_REG 0x418 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9 +#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET 6 +#define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438 +#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6 +#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK \ + (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET) +#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10 +#define HPIPE_TX_NUM_OF_PRESET_MASK \ + (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET) +#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15 +#define HPIPE_TX_SWEEP_PRESET_EN_MASK \ + (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET) +#define HPIPE_G2_SETTINGS_4_REG 0x44C +#define HPIPE_G2_DFE_RES_OFFSET 8 +#define HPIPE_G2_DFE_RES_MASK (0x3 << HPIPE_G2_DFE_RES_OFFSET) + +#define HPIPE_G3_SETTING_3_REG 0x450 +#define HPIPE_G3_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G3_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET) +#define HPIPE_G3_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G3_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G3_FFE_RES_SEL_OFFSET) +#define HPIPE_G3_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G3_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G3_SETTING_4_REG 0x454 +#define HPIPE_G3_DFE_RES_OFFSET 8 +#define HPIPE_G3_DFE_RES_MASK (0x3 << HPIPE_G3_DFE_RES_OFFSET) + +#define HPIPE_DFE_CONTROL_REG 0x470 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET 14 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK \ + (0x3 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET) + +#define HPIPE_DFE_CTRL_28_REG 0x49C +#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7 +#define HPIPE_DFE_CTRL_28_PIPE4_MASK \ + (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET) + +#define HPIPE_G3_SETTING_5_REG 0x548 +#define HPIPE_G3_SETTING_5_G3_ICP_OFFSET 0 +#define HPIPE_G3_SETTING_5_G3_ICP_MASK \ + (0xf << HPIPE_G3_SETTING_5_G3_ICP_OFFSET) + +#define HPIPE_LANE_STATUS1_REG 0x60C +#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0 +#define HPIPE_LANE_STATUS1_PCLK_EN_MASK \ + (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET) + +#define HPIPE_LANE_CFG4_REG 0x620 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET 3 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET) + +#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C +#define HPIPE_CFG_EQ_FS_OFFSET 0 +#define HPIPE_CFG_EQ_FS_MASK (0x3f << HPIPE_CFG_EQ_FS_OFFSET) +#define HPIPE_CFG_EQ_LF_OFFSET 6 +#define HPIPE_CFG_EQ_LF_MASK (0x3f << HPIPE_CFG_EQ_LF_OFFSET) +#define HPIPE_CFG_PHY_RC_EP_OFFSET 12 +#define HPIPE_CFG_PHY_RC_EP_MASK \ + (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET) + +#define HPIPE_LANE_EQ_CFG1_REG 0x6a0 +#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12 +#define HPIPE_CFG_UPDATE_POLARITY_MASK \ + (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET) + +#define HPIPE_LANE_EQ_CFG2_REG 0x6a4 +#define HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET 14 +#define HPIPE_CFG_EQ_BUNDLE_DIS_MASK \ + (0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET) + +#define HPIPE_LANE_PRESET_CFG0_REG 0x6a8 +#define HPIPE_CFG_CURSOR_PRESET0_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET0_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET1_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET1_OFFSET) + +#define HPIPE_LANE_PRESET_CFG1_REG 0x6ac +#define HPIPE_CFG_CURSOR_PRESET2_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET2_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET3_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET3_OFFSET) + +#define HPIPE_LANE_PRESET_CFG2_REG 0x6b0 +#define HPIPE_CFG_CURSOR_PRESET4_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET4_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET5_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET5_OFFSET) + +#define HPIPE_LANE_PRESET_CFG3_REG 0x6b4 +#define HPIPE_CFG_CURSOR_PRESET6_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET6_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET7_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET7_OFFSET) + +#define HPIPE_LANE_PRESET_CFG4_REG 0x6b8 +#define HPIPE_CFG_CURSOR_PRESET8_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET8_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET9_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET9_OFFSET) + +#define HPIPE_LANE_PRESET_CFG5_REG 0x6bc +#define HPIPE_CFG_CURSOR_PRESET10_OFFSET 0 +#define HPIPE_CFG_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET10_OFFSET) +#define HPIPE_CFG_CURSOR_PRESET11_OFFSET 6 +#define HPIPE_CFG_CURSOR_PRESET11_MASK \ + (0x3f << HPIPE_CFG_CURSOR_PRESET11_OFFSET) + +#define HPIPE_LANE_PRESET_CFG6_REG 0x6c0 +#define HPIPE_CFG_PRE_CURSOR_PRESET0_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET0_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET0_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET0_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET0_OFFSET) + +#define HPIPE_LANE_PRESET_CFG7_REG 0x6c4 +#define HPIPE_CFG_PRE_CURSOR_PRESET1_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET1_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET1_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET1_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET1_OFFSET) + +#define HPIPE_LANE_PRESET_CFG8_REG 0x6c8 +#define HPIPE_CFG_PRE_CURSOR_PRESET2_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET2_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET2_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET2_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET2_OFFSET) + +#define HPIPE_LANE_PRESET_CFG9_REG 0x6cc +#define HPIPE_CFG_PRE_CURSOR_PRESET3_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET3_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET3_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET3_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET3_OFFSET) + +#define HPIPE_LANE_PRESET_CFG10_REG 0x6d0 +#define HPIPE_CFG_PRE_CURSOR_PRESET4_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET4_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET4_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET4_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET4_OFFSET) + +#define HPIPE_LANE_PRESET_CFG11_REG 0x6d4 +#define HPIPE_CFG_PRE_CURSOR_PRESET5_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET5_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET5_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET5_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET5_OFFSET) + +#define HPIPE_LANE_PRESET_CFG12_REG 0x6d8 +#define HPIPE_CFG_PRE_CURSOR_PRESET6_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET6_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET6_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET6_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET6_OFFSET) + +#define HPIPE_LANE_PRESET_CFG13_REG 0x6dc +#define HPIPE_CFG_PRE_CURSOR_PRESET7_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET7_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET7_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET7_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET7_OFFSET) + +#define HPIPE_LANE_PRESET_CFG14_REG 0x6e0 +#define HPIPE_CFG_PRE_CURSOR_PRESET8_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET8_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET8_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET8_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET8_OFFSET) + +#define HPIPE_LANE_PRESET_CFG15_REG 0x6e4 +#define HPIPE_CFG_PRE_CURSOR_PRESET9_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET9_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET9_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET9_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET9_OFFSET) + +#define HPIPE_LANE_PRESET_CFG16_REG 0x6e8 +#define HPIPE_CFG_PRE_CURSOR_PRESET10_OFFSET 0 +#define HPIPE_CFG_PRE_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_PRE_CURSOR_PRESET10_OFFSET) +#define HPIPE_CFG_POST_CURSOR_PRESET10_OFFSET 6 +#define HPIPE_CFG_POST_CURSOR_PRESET10_MASK \ + (0x3f << HPIPE_CFG_POST_CURSOR_PRESET10_OFFSET) + +#define HPIPE_LANE_EQ_REMOTE_SETTING_REG 0x6f8 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET 0 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET) +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET 1 +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET) +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET 2 +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK \ + (0xf << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET) + +#define HPIPE_RST_CLK_CTRL_REG 0x704 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET) +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2 +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET) +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3 +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET) +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9 +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET) + +#define HPIPE_CLK_SRC_LO_REG 0x70c +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK \ + (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET) +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \ + (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET) +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5 +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK \ + (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET) + +#define HPIPE_CLK_SRC_HI_REG 0x710 +#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0 +#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1 +#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2 +#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET) +#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7 +#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET) + +#define HPIPE_GLOBAL_PM_CTRL 0x740 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK \ + (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET) + +#endif /* COMPHY_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h b/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h new file mode 100644 index 0000000..af5c715 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 SoC COMPHY unit driver */ + +#ifndef COMPHY_CP110_H +#define COMPHY_CP110_H + +#define SD_ADDR(base, lane) (base + 0x1000 * lane) +#define HPIPE_ADDR(base, lane) (SD_ADDR(base, lane) + 0x800) +#define COMPHY_ADDR(base, lane) (base + 0x28 * lane) + +#define MAX_NUM_OF_FFE 8 +#define RX_TRAINING_TIMEOUT 500 + +/* Comphy registers */ +#define COMMON_PHY_CFG1_REG 0x0 +#define COMMON_PHY_CFG1_PWR_UP_OFFSET 1 +#define COMMON_PHY_CFG1_PWR_UP_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET) +#define COMMON_PHY_CFG1_PIPE_SELECT_OFFSET 2 +#define COMMON_PHY_CFG1_PIPE_SELECT_MASK \ + (0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET) +#define COMMON_PHY_CFG1_CORE_RSTN_OFFSET 13 +#define COMMON_PHY_CFG1_CORE_RSTN_MASK \ + (0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET) +#define COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET 14 +#define COMMON_PHY_CFG1_PWR_ON_RESET_MASK \ + (0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET) +#define COMMON_PHY_PHY_MODE_OFFSET 15 +#define COMMON_PHY_PHY_MODE_MASK \ + (0x1 << COMMON_PHY_PHY_MODE_OFFSET) + +#define COMMON_PHY_CFG6_REG 0x14 +#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18 +#define COMMON_PHY_CFG6_IF_40_SEL_MASK \ + (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET) + +#define COMMON_PHY_CFG6_REG 0x14 +#define COMMON_PHY_CFG6_IF_40_SEL_OFFSET 18 +#define COMMON_PHY_CFG6_IF_40_SEL_MASK \ + (0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET) + +#define COMMON_SELECTOR_PHY_REG_OFFSET 0x140 +#define COMMON_SELECTOR_PIPE_REG_OFFSET 0x144 +#define COMMON_SELECTOR_COMPHY_MASK 0xf +#define COMMON_SELECTOR_COMPHYN_FIELD_WIDTH 4 +#define COMMON_SELECTOR_COMPHYN_SATA 0x4 +#define COMMON_SELECTOR_PIPE_COMPHY_PCIE 0x4 +#define COMMON_SELECTOR_PIPE_COMPHY_USBH 0x1 +#define COMMON_SELECTOR_PIPE_COMPHY_USBD 0x2 + +/* SGMII/Base-X/SFI/RXAUI */ +#define COMMON_SELECTOR_COMPHY0_1_2_NETWORK 0x1 +#define COMMON_SELECTOR_COMPHY3_RXAUI 0x1 +#define COMMON_SELECTOR_COMPHY3_SGMII 0x2 +#define COMMON_SELECTOR_COMPHY4_PORT1 0x1 +#define COMMON_SELECTOR_COMPHY4_ALL_OTHERS 0x2 +#define COMMON_SELECTOR_COMPHY5_RXAUI 0x2 +#define COMMON_SELECTOR_COMPHY5_SGMII 0x1 + +#define COMMON_PHY_SD_CTRL1 0x148 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET 0 +#define COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET 4 +#define COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET 8 +#define COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET 12 +#define COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK 0xFFFF +#define COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK 0xFF +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET 24 +#define COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET 25 +#define COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET) +#define COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET 26 +#define COMMON_PHY_SD_CTRL1_RXAUI1_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET) +#define COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET 27 +#define COMMON_PHY_SD_CTRL1_RXAUI0_MASK \ + (0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET) + +/* DFX register */ +#define DFX_BASE (0x400000) +#define DFX_DEV_GEN_CTRL12_REG (0x280) +#define DFX_DEV_GEN_PCIE_CLK_SRC_MUX (0x3) +#define DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET 7 +#define DFX_DEV_GEN_PCIE_CLK_SRC_MASK \ + (0x3 << DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET) + +/* SerDes IP registers */ +#define SD_EXTERNAL_CONFIG0_REG 0 +#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET 1 +#define SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET 3 +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK \ + (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET 7 +#define SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK \ + (0xf << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET 11 +#define SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET) +#define SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET 12 +#define SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK \ + (1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET) +#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET 14 +#define SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK \ + (1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET) +#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET 15 +#define SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET) + +#define SD_EXTERNAL_CONFIG1_REG 0x4 +#define SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET 2 +#define SD_EXTERNAL_CONFIG1_TX_IDLE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET) +#define SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET 3 +#define SD_EXTERNAL_CONFIG1_RESET_IN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET) +#define SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET 4 +#define SD_EXTERNAL_CONFIG1_RX_INIT_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET) +#define SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET 5 +#define SD_EXTERNAL_CONFIG1_RESET_CORE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET) +#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET 6 +#define SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET) + +#define SD_EXTERNAL_CONFIG2_REG 0x8 +#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET 4 +#define SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK \ + (0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET) +#define SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET 7 +#define SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK \ + (0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET) + +#define SD_EXTERNAL_STATUS_REG 0xc +#define SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET 7 +#define SD_EXTERNAL_STATUS_START_RX_TRAINING_MASK \ + (1 << SD_EXTERNAL_STATUS_START_RX_TRAINING_OFFSET) + +#define SD_EXTERNAL_STATUS0_REG 0x18 +#define SD_EXTERNAL_STATUS0_PLL_TX_OFFSET 2 +#define SD_EXTERNAL_STATUS0_PLL_TX_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_PLL_TX_OFFSET) +#define SD_EXTERNAL_STATUS0_PLL_RX_OFFSET 3 +#define SD_EXTERNAL_STATUS0_PLL_RX_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_PLL_RX_OFFSET) +#define SD_EXTERNAL_STATUS0_RX_INIT_OFFSET 4 +#define SD_EXTERNAL_STATUS0_RX_INIT_MASK \ + (0x1 << SD_EXTERNAL_STATUS0_RX_INIT_OFFSET) + +#define SD_EXTERNAL_STATAUS1_REG 0x1c +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_OFFSET 0 +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_MASK \ + (1 << SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_COMP_OFFSET) +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_OFFSET 1 +#define SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_MASK \ + (1 << SD_EXTERNAL_STATAUS1_REG_RX_TRAIN_FAILED_OFFSET) + +/* HPIPE registers */ +#define HPIPE_PWR_PLL_REG 0x4 +#define HPIPE_PWR_PLL_REF_FREQ_OFFSET 0 +#define HPIPE_PWR_PLL_REF_FREQ_MASK \ + (0x1f << HPIPE_PWR_PLL_REF_FREQ_OFFSET) +#define HPIPE_PWR_PLL_PHY_MODE_OFFSET 5 +#define HPIPE_PWR_PLL_PHY_MODE_MASK \ + (0x7 << HPIPE_PWR_PLL_PHY_MODE_OFFSET) + +#define HPIPE_CAL_REG1_REG 0xc +#define HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET 10 +#define HPIPE_CAL_REG_1_EXT_TXIMP_MASK \ + (0x1f << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET) +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET 15 +#define HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK \ + (0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET) + +#define HPIPE_SQUELCH_FFE_SETTING_REG 0x18 +#define HPIPE_SQUELCH_THRESH_IN_OFFSET 8 +#define HPIPE_SQUELCH_THRESH_IN_MASK \ + (0xf << HPIPE_SQUELCH_THRESH_IN_OFFSET) +#define HPIPE_SQUELCH_DETECTED_OFFSET 14 +#define HPIPE_SQUELCH_DETECTED_MASK \ + (0x1 << HPIPE_SQUELCH_DETECTED_OFFSET) + +#define HPIPE_DFE_REG0 0x1c +#define HPIPE_DFE_RES_FORCE_OFFSET 15 +#define HPIPE_DFE_RES_FORCE_MASK \ + (0x1 << HPIPE_DFE_RES_FORCE_OFFSET) + +#define HPIPE_DFE_F3_F5_REG 0x28 +#define HPIPE_DFE_F3_F5_DFE_EN_OFFSET 14 +#define HPIPE_DFE_F3_F5_DFE_EN_MASK \ + (0x1 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET) +#define HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET 15 +#define HPIPE_DFE_F3_F5_DFE_CTRL_MASK \ + (0x1 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET) + +#define HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG 0x30 +#define HPIPE_ADAPTED_DFE_RES_OFFSET 13 +#define HPIPE_ADAPTED_DFE_RES_MASK \ + (0x3 << HPIPE_ADAPTED_DFE_RES_OFFSET) + +#define HPIPE_G1_SET_0_REG 0x34 +#define HPIPE_G1_SET_0_G1_TX_AMP_OFFSET 1 +#define HPIPE_G1_SET_0_G1_TX_AMP_MASK \ + (0x1f << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET 7 +#define HPIPE_G1_SET_0_G1_TX_EMPH1_MASK \ + (0xf << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET) +#define HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET) + +#define HPIPE_G1_SET_1_REG 0x38 +#define HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET 0 +#define HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET 3 +#define HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET 6 +#define HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET 8 +#define HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET 10 +#define HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET) +#define HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET) + +#define HPIPE_G2_SET_0_REG 0x3c +#define HPIPE_G2_SET_0_G2_TX_AMP_OFFSET 1 +#define HPIPE_G2_SET_0_G2_TX_AMP_MASK \ + (0x1f << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET 7 +#define HPIPE_G2_SET_0_G2_TX_EMPH1_MASK \ + (0xf << HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET) +#define HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET) + +#define HPIPE_G2_SET_1_REG 0x40 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET 0 +#define HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET 3 +#define HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET 6 +#define HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET 8 +#define HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_DFE_EN_OFFSET 10 +#define HPIPE_G2_SET_1_G2_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G2_SET_1_G2_RX_DFE_EN_OFFSET) +#define HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET) + +#define HPIPE_G3_SET_0_REG 0x44 +#define HPIPE_G3_SET_0_G3_TX_AMP_OFFSET 1 +#define HPIPE_G3_SET_0_G3_TX_AMP_MASK \ + (0x1f << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET 6 +#define HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET 7 +#define HPIPE_G3_SET_0_G3_TX_EMPH1_MASK \ + (0xf << HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET 11 +#define HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET 12 +#define HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK \ + (0x7 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET) +#define HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET 15 +#define HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK \ + (0x1 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET) + +#define HPIPE_G3_SET_1_REG 0x48 +#define HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET 0 +#define HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK \ + (0x7 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET 3 +#define HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK \ + (0x7 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET 6 +#define HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET 8 +#define HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET 10 +#define HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK \ + (0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET) +#define HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET 11 +#define HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK \ + (0x3 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET) +#define HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET 13 +#define HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK \ + (0x1 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET) + +#define HPIPE_PHY_TEST_CONTROL_REG 0x54 +#define HPIPE_PHY_TEST_PATTERN_SEL_OFFSET 4 +#define HPIPE_PHY_TEST_PATTERN_SEL_MASK \ + (0xf << HPIPE_PHY_TEST_PATTERN_SEL_OFFSET) +#define HPIPE_PHY_TEST_RESET_OFFSET 14 +#define HPIPE_PHY_TEST_RESET_MASK \ + (0x1 << HPIPE_PHY_TEST_RESET_OFFSET) +#define HPIPE_PHY_TEST_EN_OFFSET 15 +#define HPIPE_PHY_TEST_EN_MASK \ + (0x1 << HPIPE_PHY_TEST_EN_OFFSET) + +#define HPIPE_PHY_TEST_DATA_REG 0x6c +#define HPIPE_PHY_TEST_DATA_OFFSET 0 +#define HPIPE_PHY_TEST_DATA_MASK \ + (0xffff << HPIPE_PHY_TEST_DATA_OFFSET) + +#define HPIPE_PHY_TEST_PRBS_ERROR_COUNTER_1_REG 0x80 + +#define HPIPE_PHY_TEST_OOB_0_REGISTER 0x84 +#define HPIPE_PHY_PT_OOB_EN_OFFSET 14 +#define HPIPE_PHY_PT_OOB_EN_MASK \ + (0x1 << HPIPE_PHY_PT_OOB_EN_OFFSET) +#define HPIPE_PHY_TEST_PT_TESTMODE_OFFSET 12 +#define HPIPE_PHY_TEST_PT_TESTMODE_MASK \ + (0x3 << HPIPE_PHY_TEST_PT_TESTMODE_OFFSET) + +#define HPIPE_LOOPBACK_REG 0x8c +#define HPIPE_LOOPBACK_SEL_OFFSET 1 +#define HPIPE_LOOPBACK_SEL_MASK \ + (0x7 << HPIPE_LOOPBACK_SEL_OFFSET) +#define HPIPE_CDR_LOCK_OFFSET 7 +#define HPIPE_CDR_LOCK_MASK \ + (0x1 << HPIPE_CDR_LOCK_OFFSET) +#define HPIPE_CDR_LOCK_DET_EN_OFFSET 8 +#define HPIPE_CDR_LOCK_DET_EN_MASK \ + (0x1 << HPIPE_CDR_LOCK_DET_EN_OFFSET) + +#define HPIPE_SYNC_PATTERN_REG 0x090 +#define HPIPE_SYNC_PATTERN_TXD_INV_OFFSET 10 +#define HPIPE_SYNC_PATTERN_TXD_INV_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET) +#define HPIPE_SYNC_PATTERN_RXD_INV_OFFSET 11 +#define HPIPE_SYNC_PATTERN_RXD_INV_MASK \ + (0x1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET) + +#define HPIPE_INTERFACE_REG 0x94 +#define HPIPE_INTERFACE_GEN_MAX_OFFSET 10 +#define HPIPE_INTERFACE_GEN_MAX_MASK \ + (0x3 << HPIPE_INTERFACE_GEN_MAX_OFFSET) +#define HPIPE_INTERFACE_DET_BYPASS_OFFSET 12 +#define HPIPE_INTERFACE_DET_BYPASS_MASK \ + (0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET) +#define HPIPE_INTERFACE_LINK_TRAIN_OFFSET 14 +#define HPIPE_INTERFACE_LINK_TRAIN_MASK \ + (0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET) + +#define HPIPE_G1_SET_2_REG 0xf4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET 0 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_MASK \ + (0xf << HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET) +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET) + +#define HPIPE_G2_SET_2_REG 0xf8 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET 0 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_MASK \ + (0xf << HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET) +#define HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET) +#define HPIPE_G2_TX_SSC_AMP_OFFSET 9 +#define HPIPE_G2_TX_SSC_AMP_MASK \ + (0x7f << HPIPE_G2_TX_SSC_AMP_OFFSET) + +#define HPIPE_G3_SET_2_REG 0xfc +#define HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET 0 +#define HPIPE_G3_SET_2_G3_TX_EMPH0_MASK \ + (0xf << HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET) +#define HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET 4 +#define HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK \ + (0x1 << HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET) +#define HPIPE_G3_TX_SSC_AMP_OFFSET 9 +#define HPIPE_G3_TX_SSC_AMP_MASK \ + (0x7f << HPIPE_G3_TX_SSC_AMP_OFFSET) + +#define HPIPE_VDD_CAL_0_REG 0x108 +#define HPIPE_CAL_VDD_CONT_MODE_OFFSET 15 +#define HPIPE_CAL_VDD_CONT_MODE_MASK \ + (0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET) + +#define HPIPE_VDD_CAL_CTRL_REG 0x114 +#define HPIPE_EXT_SELLV_RXSAMPL_OFFSET 5 +#define HPIPE_EXT_SELLV_RXSAMPL_MASK \ + (0x1f << HPIPE_EXT_SELLV_RXSAMPL_OFFSET) + +#define HPIPE_PCIE_REG0 0x120 +#define HPIPE_PCIE_IDLE_SYNC_OFFSET 12 +#define HPIPE_PCIE_IDLE_SYNC_MASK \ + (0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET) +#define HPIPE_PCIE_SEL_BITS_OFFSET 13 +#define HPIPE_PCIE_SEL_BITS_MASK \ + (0x3 << HPIPE_PCIE_SEL_BITS_OFFSET) + +#define HPIPE_LANE_ALIGN_REG 0x124 +#define HPIPE_LANE_ALIGN_OFF_OFFSET 12 +#define HPIPE_LANE_ALIGN_OFF_MASK \ + (0x1 << HPIPE_LANE_ALIGN_OFF_OFFSET) + +#define HPIPE_MISC_REG 0x13C +#define HPIPE_MISC_CLK100M_125M_OFFSET 4 +#define HPIPE_MISC_CLK100M_125M_MASK \ + (0x1 << HPIPE_MISC_CLK100M_125M_OFFSET) +#define HPIPE_MISC_ICP_FORCE_OFFSET 5 +#define HPIPE_MISC_ICP_FORCE_MASK \ + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET) +#define HPIPE_MISC_TXDCLK_2X_OFFSET 6 +#define HPIPE_MISC_TXDCLK_2X_MASK \ + (0x1 << HPIPE_MISC_TXDCLK_2X_OFFSET) +#define HPIPE_MISC_CLK500_EN_OFFSET 7 +#define HPIPE_MISC_CLK500_EN_MASK \ + (0x1 << HPIPE_MISC_CLK500_EN_OFFSET) +#define HPIPE_MISC_REFCLK_SEL_OFFSET 10 +#define HPIPE_MISC_REFCLK_SEL_MASK \ + (0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET) + +#define HPIPE_RX_CONTROL_1_REG 0x140 +#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET 11 +#define HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK \ + (0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET) +#define HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET 12 +#define HPIPE_RX_CONTROL_1_CLK8T_EN_MASK \ + (0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET) + +#define HPIPE_PWR_CTR_REG 0x148 +#define HPIPE_PWR_CTR_RST_DFE_OFFSET 0 +#define HPIPE_PWR_CTR_RST_DFE_MASK \ + (0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET) +#define HPIPE_PWR_CTR_SFT_RST_OFFSET 10 +#define HPIPE_PWR_CTR_SFT_RST_MASK \ + (0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET) + +#define HPIPE_SPD_DIV_FORCE_REG 0x154 +#define HPIPE_TXDIGCK_DIV_FORCE_OFFSET 7 +#define HPIPE_TXDIGCK_DIV_FORCE_MASK \ + (0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET) +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET 8 +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK \ + (0x3 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET) +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET 10 +#define HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK \ + (0x1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET) +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET 13 +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK \ + (0x3 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET) +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET 15 +#define HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK \ + (0x1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET) + +/* HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIBRATION_CTRL_REG */ +#define HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG 0x168 +#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET 15 +#define HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK \ + (0x1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET) +#define HPIPE_CAL_OS_PH_EXT_OFFSET 8 +#define HPIPE_CAL_OS_PH_EXT_MASK \ + (0x7f << HPIPE_CAL_OS_PH_EXT_OFFSET) + +#define HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG 0x16C +#define HPIPE_RX_SAMPLER_OS_GAIN_OFFSET 6 +#define HPIPE_RX_SAMPLER_OS_GAIN_MASK \ + (0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET) +#define HPIPE_SMAPLER_OFFSET 12 +#define HPIPE_SMAPLER_MASK \ + (0x1 << HPIPE_SMAPLER_OFFSET) + +#define HPIPE_TX_REG1_REG 0x174 +#define HPIPE_TX_REG1_TX_EMPH_RES_OFFSET 5 +#define HPIPE_TX_REG1_TX_EMPH_RES_MASK \ + (0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET) +#define HPIPE_TX_REG1_SLC_EN_OFFSET 10 +#define HPIPE_TX_REG1_SLC_EN_MASK \ + (0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET) + +#define HPIPE_PWR_CTR_DTL_REG 0x184 +#define HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET 0 +#define HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET 1 +#define HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET 2 +#define HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET 4 +#define HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK \ + (0x7 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET) +#define HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET 10 +#define HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK \ + (0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET 12 +#define HPIPE_PWR_CTR_DTL_CLK_MODE_MASK \ + (0x3 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET) +#define HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET 14 +#define HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK \ + (1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET) + +#define HPIPE_PHASE_CONTROL_REG 0x188 +#define HPIPE_OS_PH_OFFSET_OFFSET 0 +#define HPIPE_OS_PH_OFFSET_MASK \ + (0x7f << HPIPE_OS_PH_OFFSET_OFFSET) +#define HPIPE_OS_PH_OFFSET_FORCE_OFFSET 7 +#define HPIPE_OS_PH_OFFSET_FORCE_MASK \ + (0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET) +#define HPIPE_OS_PH_VALID_OFFSET 8 +#define HPIPE_OS_PH_VALID_MASK \ + (0x1 << HPIPE_OS_PH_VALID_OFFSET) + +#define HPIPE_DATA_PHASE_OFF_CTRL_REG 0x1A0 +#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET 9 +#define HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK \ + (0x7f << HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET) + +#define HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG 0x1A4 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET 12 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK \ + (0x3 << HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET) +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET 8 +#define HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK \ + (0xf << HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET) + +#define HPIPE_SQ_GLITCH_FILTER_CTRL 0x1c8 +#define HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET 0 +#define HPIPE_SQ_DEGLITCH_WIDTH_P_MASK \ + (0xf << HPIPE_SQ_DEGLITCH_WIDTH_P_OFFSET) +#define HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET 4 +#define HPIPE_SQ_DEGLITCH_WIDTH_N_MASK \ + (0xf << HPIPE_SQ_DEGLITCH_WIDTH_N_OFFSET) +#define HPIPE_SQ_DEGLITCH_EN_OFFSET 8 +#define HPIPE_SQ_DEGLITCH_EN_MASK \ + (0x1 << HPIPE_SQ_DEGLITCH_EN_OFFSET) + +#define HPIPE_FRAME_DETECT_CTRL_0_REG 0x214 +#define HPIPE_TRAIN_PAT_NUM_OFFSET 0x7 +#define HPIPE_TRAIN_PAT_NUM_MASK \ + (0x1FF << HPIPE_TRAIN_PAT_NUM_OFFSET) + +#define HPIPE_FRAME_DETECT_CTRL_3_REG 0x220 +#define HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET 12 +#define HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK \ + (0x1 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET) + +#define HPIPE_DME_REG 0x228 +#define HPIPE_DME_ETHERNET_MODE_OFFSET 7 +#define HPIPE_DME_ETHERNET_MODE_MASK \ + (0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET) + +#define HPIPE_TRX_TRAIN_CTRL_0_REG 0x22c +#define HPIPE_TRX_TX_F0T_EO_BASED_OFFSET 14 +#define HPIPE_TRX_TX_F0T_EO_BASED_MASK \ + (1 << HPIPE_TRX_TX_F0T_EO_BASED_OFFSET) +#define HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET 6 +#define HPIPE_TRX_UPDATE_THEN_HOLD_MASK \ + (1 << HPIPE_TRX_UPDATE_THEN_HOLD_OFFSET) +#define HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET 5 +#define HPIPE_TRX_TX_CTRL_CLK_EN_MASK \ + (1 << HPIPE_TRX_TX_CTRL_CLK_EN_OFFSET) +#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET 4 +#define HPIPE_TRX_RX_ANA_IF_CLK_ENE_MASK \ + (1 << HPIPE_TRX_RX_ANA_IF_CLK_ENE_OFFSET) +#define HPIPE_TRX_TX_TRAIN_EN_OFFSET 1 +#define HPIPE_TRX_TX_TRAIN_EN_MASK \ + (1 << HPIPE_TRX_TX_TRAIN_EN_OFFSET) +#define HPIPE_TRX_RX_TRAIN_EN_OFFSET 0 +#define HPIPE_TRX_RX_TRAIN_EN_MASK \ + (1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_0_REG 0x268 +#define HPIPE_TX_TRAIN_P2P_HOLD_OFFSET 15 +#define HPIPE_TX_TRAIN_P2P_HOLD_MASK \ + (0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_REG 0x26C +#define HPIPE_TX_TRAIN_CTRL_G1_OFFSET 0 +#define HPIPE_TX_TRAIN_CTRL_G1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_GN1_OFFSET 1 +#define HPIPE_TX_TRAIN_CTRL_GN1_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET) +#define HPIPE_TX_TRAIN_CTRL_G0_OFFSET 2 +#define HPIPE_TX_TRAIN_CTRL_G0_MASK \ + (0x1 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_4_REG 0x278 +#define HPIPE_TRX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_TRX_TRAIN_TIMER_MASK \ + (0x3FF << HPIPE_TRX_TRAIN_TIMER_OFFSET) + +#define HPIPE_TX_TRAIN_CTRL_5_REG 0x2A4 +#define HPIPE_RX_TRAIN_TIMER_OFFSET 0 +#define HPIPE_RX_TRAIN_TIMER_MASK \ + (0x3ff << HPIPE_RX_TRAIN_TIMER_OFFSET) +#define HPIPE_TX_TRAIN_START_SQ_EN_OFFSET 11 +#define HPIPE_TX_TRAIN_START_SQ_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET 12 +#define HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET) +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET 13 +#define HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET) +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET 14 +#define HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET) + +#define HPIPE_INTERRUPT_1_REGISTER 0x2AC +#define HPIPE_TRX_TRAIN_FAILED_OFFSET 6 +#define HPIPE_TRX_TRAIN_FAILED_MASK \ + (1 << HPIPE_TRX_TRAIN_FAILED_OFFSET) +#define HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET 5 +#define HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK \ + (1 << HPIPE_TRX_TRAIN_TIME_OUT_INT_OFFSET) +#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET 4 +#define HPIPE_INTERRUPT_TRX_TRAIN_DONE_MASK \ + (1 << HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET) +#define HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET 3 +#define HPIPE_INTERRUPT_DFE_DONE_INT_MASK \ + (1 << HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET) +#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET 1 +#define HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK \ + (1 << HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_OFFSET) + +#define HPIPE_TX_TRAIN_REG 0x31C +#define HPIPE_TX_TRAIN_CHK_INIT_OFFSET 4 +#define HPIPE_TX_TRAIN_CHK_INIT_MASK \ + (0x1 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET) +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET 7 +#define HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK \ + (0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET) +#define HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET 8 +#define HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK \ + (0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET) +#define HPIPE_TX_TRAIN_PAT_SEL_OFFSET 9 +#define HPIPE_TX_TRAIN_PAT_SEL_MASK \ + (0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET) + +#define HPIPE_SAVED_DFE_VALUES_REG 0x328 +#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET 10 +#define HPIPE_SAVED_DFE_VALUES_SAV_F0D_MASK \ + (0x3f << HPIPE_SAVED_DFE_VALUES_SAV_F0D_OFFSET) + +#define HPIPE_CDR_CONTROL_REG 0x418 +#define HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET 0 +#define HPIPE_CRD_MIDPOINT_PHASE_OS_MASK \ + (0x3f << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET 6 +#define HPIPE_CDR_MAX_DFE_ADAPT_1_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET 9 +#define HPIPE_CDR_MAX_DFE_ADAPT_0_MASK \ + (0x7 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET 12 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET) +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET 14 +#define HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK \ + (0x3 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET) + + +#define HPIPE_CDR_CONTROL1_REG 0x41c +#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF 12 +#define HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK \ + (0xf << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF) + +#define HPIPE_CDR_CONTROL2_REG 0x420 +#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF 12 +#define HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK \ + (0xf << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF) + +#define HPIPE_TX_TRAIN_CTRL_11_REG 0x438 +#define HPIPE_TX_STATUS_CHECK_MODE_OFFSET 6 +#define HPIPE_TX_TX_STATUS_CHECK_MODE_MASK \ + (0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET) +#define HPIPE_TX_NUM_OF_PRESET_OFFSET 10 +#define HPIPE_TX_NUM_OF_PRESET_MASK \ + (0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET) +#define HPIPE_TX_SWEEP_PRESET_EN_OFFSET 15 +#define HPIPE_TX_SWEEP_PRESET_EN_MASK \ + (0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET) + +#define HPIPE_G1_SETTINGS_3_REG 0x440 +#define HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET 9 +#define HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK \ + (0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G1_SETTINGS_4_REG 0x444 +#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET 8 +#define HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK \ + (0x3 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET) + +#define HPIPE_G2_SETTINGS_4_REG 0x44c +#define HPIPE_G2_DFE_RES_OFFSET 8 +#define HPIPE_G2_DFE_RES_MASK \ + (0x3 << HPIPE_G2_DFE_RES_OFFSET) + +#define HPIPE_G3_SETTING_3_REG 0x450 +#define HPIPE_G3_FFE_CAP_SEL_OFFSET 0 +#define HPIPE_G3_FFE_CAP_SEL_MASK \ + (0xf << HPIPE_G3_FFE_CAP_SEL_OFFSET) +#define HPIPE_G3_FFE_RES_SEL_OFFSET 4 +#define HPIPE_G3_FFE_RES_SEL_MASK \ + (0x7 << HPIPE_G3_FFE_RES_SEL_OFFSET) +#define HPIPE_G3_FFE_SETTING_FORCE_OFFSET 7 +#define HPIPE_G3_FFE_SETTING_FORCE_MASK \ + (0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET) +#define HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET 12 +#define HPIPE_G3_FFE_DEG_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET) +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET 14 +#define HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK \ + (0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET) + +#define HPIPE_G3_SETTING_4_REG 0x454 +#define HPIPE_G3_DFE_RES_OFFSET 8 +#define HPIPE_G3_DFE_RES_MASK (0x3 << HPIPE_G3_DFE_RES_OFFSET) + +#define HPIPE_TX_PRESET_INDEX_REG 0x468 +#define HPIPE_TX_PRESET_INDEX_OFFSET 0 +#define HPIPE_TX_PRESET_INDEX_MASK \ + (0xf << HPIPE_TX_PRESET_INDEX_OFFSET) + +#define HPIPE_DFE_CONTROL_REG 0x470 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET 14 +#define HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK \ + (0x3 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET) + +#define HPIPE_DFE_CTRL_28_REG 0x49C +#define HPIPE_DFE_CTRL_28_PIPE4_OFFSET 7 +#define HPIPE_DFE_CTRL_28_PIPE4_MASK \ + (0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET) + +#define HPIPE_TRX0_REG 0x4cc /*in doc 0x133*4*/ +#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF 2 +#define HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK \ + (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF) +#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF 0 +#define HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK \ + (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF) + +#define HPIPE_TRX_REG1 0x4d0 /*in doc 0x134*4*/ +#define HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF 3 +#define HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK \ + (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF) +#define HPIPE_TRX_REG1_SUMFTAP_EN_OFF 10 +#define HPIPE_TRX_REG1_SUMFTAP_EN_MASK \ + (0x3f << HPIPE_TRX_REG1_SUMFTAP_EN_OFF) + +#define HPIPE_TRX_REG2 0x4d8 /*in doc 0x136*4*/ +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF 11 +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK \ + (0x1f << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF) +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF 7 +#define HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK \ + (0xf << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF) + +#define HPIPE_G1_SETTING_5_REG 0x538 +#define HPIPE_G1_SETTING_5_G1_ICP_OFFSET 0 +#define HPIPE_G1_SETTING_5_G1_ICP_MASK \ + (0xf << HPIPE_G1_SETTING_5_G1_ICP_OFFSET) + +#define HPIPE_G3_SETTING_5_REG 0x548 +#define HPIPE_G3_SETTING_5_G3_ICP_OFFSET 0 +#define HPIPE_G3_SETTING_5_G3_ICP_MASK \ + (0xf << HPIPE_G3_SETTING_5_G3_ICP_OFFSET) + +#define HPIPE_LANE_CONFIG0_REG 0x600 +#define HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET 0 +#define HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK \ + (0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET) + +#define HPIPE_LANE_STATUS1_REG 0x60C +#define HPIPE_LANE_STATUS1_PCLK_EN_OFFSET 0 +#define HPIPE_LANE_STATUS1_PCLK_EN_MASK \ + (0x1 << HPIPE_LANE_STATUS1_PCLK_EN_OFFSET) + +#define HPIPE_LANE_CFG4_REG 0x620 +#define HPIPE_LANE_CFG4_DFE_CTRL_OFFSET 0 +#define HPIPE_LANE_CFG4_DFE_CTRL_MASK \ + (0x7 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET) +#define HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET 3 +#define HPIPE_LANE_CFG4_DFE_EN_SEL_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET) +#define HPIPE_LANE_CFG4_DFE_OVER_OFFSET 6 +#define HPIPE_LANE_CFG4_DFE_OVER_MASK \ + (0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET) +#define HPIPE_LANE_CFG4_SSC_CTRL_OFFSET 7 +#define HPIPE_LANE_CFG4_SSC_CTRL_MASK \ + (0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET) + +#define HPIPE_LANE_EQ_REMOTE_SETTING_REG 0x6f8 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET 0 +#define HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET) +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET 1 +#define HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK \ + (0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET) +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET 2 +#define HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK \ + (0xf << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET) + +#define HPIPE_LANE_EQU_CONFIG_0_REG 0x69C +#define HPIPE_CFG_PHY_RC_EP_OFFSET 12 +#define HPIPE_CFG_PHY_RC_EP_MASK \ + (0x1 << HPIPE_CFG_PHY_RC_EP_OFFSET) + +#define HPIPE_LANE_EQ_CFG1_REG 0x6a0 +#define HPIPE_CFG_UPDATE_POLARITY_OFFSET 12 +#define HPIPE_CFG_UPDATE_POLARITY_MASK \ + (0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET) + +#define HPIPE_LANE_EQ_CFG2_REG 0x6a4 +#define HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET 14 +#define HPIPE_CFG_EQ_BUNDLE_DIS_MASK \ + (0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET) + +#define HPIPE_RST_CLK_CTRL_REG 0x704 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET 0 +#define HPIPE_RST_CLK_CTRL_PIPE_RST_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET) +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET 2 +#define HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET) +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET 3 +#define HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET) +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET 9 +#define HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK \ + (0x1 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET) + +#define HPIPE_TST_MODE_CTRL_REG 0x708 +#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET 2 +#define HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK \ + (0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET) + +#define HPIPE_CLK_SRC_LO_REG 0x70c +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET 1 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK \ + (0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET) +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET 2 +#define HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK \ + (0x3 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET) +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET 5 +#define HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK \ + (0x7 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET) + +#define HPIPE_CLK_SRC_HI_REG 0x710 +#define HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET 0 +#define HPIPE_CLK_SRC_HI_LANE_STRT_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET 1 +#define HPIPE_CLK_SRC_HI_LANE_BREAK_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET) +#define HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET 2 +#define HPIPE_CLK_SRC_HI_LANE_MASTER_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET) +#define HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET 7 +#define HPIPE_CLK_SRC_HI_MODE_PIPE_MASK \ + (0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET) + +#define HPIPE_GLOBAL_MISC_CTRL 0x718 +#define HPIPE_GLOBAL_PM_CTRL 0x740 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET 0 +#define HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK \ + (0xFF << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET) + +/* General defines */ +#define PLL_LOCK_TIMEOUT 15000 + +#endif /* COMPHY_CP110_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c new file mode 100644 index 0000000..1a97753 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c @@ -0,0 +1,1065 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include + +#include "phy-comphy-3700.h" +#include "phy-comphy-common.h" + +/* + * COMPHY_INDIRECT_REG points to ahci address space but the ahci region used in + * Linux is up to 0x178 so none will access it from Linux in runtime + * concurrently. + */ +#define COMPHY_INDIRECT_REG (MVEBU_REGS_BASE + 0xE0178) + +/* The USB3_GBE1_PHY range is above USB3 registers used in dts */ +#define USB3_GBE1_PHY (MVEBU_REGS_BASE + 0x5C000) +#define COMPHY_SD_ADDR (MVEBU_REGS_BASE + 0x1F000) + +struct sgmii_phy_init_data_fix { + uint16_t addr; + uint16_t value; +}; + +/* Changes to 40M1G25 mode data required for running 40M3G125 init mode */ +static struct sgmii_phy_init_data_fix sgmii_phy_init_fix[] = { + {0x005, 0x07CC}, {0x015, 0x0000}, {0x01B, 0x0000}, {0x01D, 0x0000}, + {0x01E, 0x0000}, {0x01F, 0x0000}, {0x020, 0x0000}, {0x021, 0x0030}, + {0x026, 0x0888}, {0x04D, 0x0152}, {0x04F, 0xA020}, {0x050, 0x07CC}, + {0x053, 0xE9CA}, {0x055, 0xBD97}, {0x071, 0x3015}, {0x076, 0x03AA}, + {0x07C, 0x0FDF}, {0x0C2, 0x3030}, {0x0C3, 0x8000}, {0x0E2, 0x5550}, + {0x0E3, 0x12A4}, {0x0E4, 0x7D00}, {0x0E6, 0x0C83}, {0x101, 0xFCC0}, + {0x104, 0x0C10} +}; + +/* 40M1G25 mode init data */ +static uint16_t sgmii_phy_init[512] = { + /* 0 1 2 3 4 5 6 7 */ + /*-----------------------------------------------------------*/ + /* 8 9 A B C D E F */ + 0x3110, 0xFD83, 0x6430, 0x412F, 0x82C0, 0x06FA, 0x4500, 0x6D26, /* 00 */ + 0xAFC0, 0x8000, 0xC000, 0x0000, 0x2000, 0x49CC, 0x0BC9, 0x2A52, /* 08 */ + 0x0BD2, 0x0CDE, 0x13D2, 0x0CE8, 0x1149, 0x10E0, 0x0000, 0x0000, /* 10 */ + 0x0000, 0x0000, 0x0000, 0x0001, 0x0000, 0x4134, 0x0D2D, 0xFFFF, /* 18 */ + 0xFFE0, 0x4030, 0x1016, 0x0030, 0x0000, 0x0800, 0x0866, 0x0000, /* 20 */ + 0x0000, 0x0000, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF, /* 28 */ + 0xFFFF, 0xFFFF, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* 30 */ + 0x0000, 0x0000, 0x000F, 0x6A62, 0x1988, 0x3100, 0x3100, 0x3100, /* 38 */ + 0x3100, 0xA708, 0x2430, 0x0830, 0x1030, 0x4610, 0xFF00, 0xFF00, /* 40 */ + 0x0060, 0x1000, 0x0400, 0x0040, 0x00F0, 0x0155, 0x1100, 0xA02A, /* 48 */ + 0x06FA, 0x0080, 0xB008, 0xE3ED, 0x5002, 0xB592, 0x7A80, 0x0001, /* 50 */ + 0x020A, 0x8820, 0x6014, 0x8054, 0xACAA, 0xFC88, 0x2A02, 0x45CF, /* 58 */ + 0x000F, 0x1817, 0x2860, 0x064F, 0x0000, 0x0204, 0x1800, 0x6000, /* 60 */ + 0x810F, 0x4F23, 0x4000, 0x4498, 0x0850, 0x0000, 0x000E, 0x1002, /* 68 */ + 0x9D3A, 0x3009, 0xD066, 0x0491, 0x0001, 0x6AB0, 0x0399, 0x3780, /* 70 */ + 0x0040, 0x5AC0, 0x4A80, 0x0000, 0x01DF, 0x0000, 0x0007, 0x0000, /* 78 */ + 0x2D54, 0x00A1, 0x4000, 0x0100, 0xA20A, 0x0000, 0x0000, 0x0000, /* 80 */ + 0x0000, 0x0000, 0x0000, 0x7400, 0x0E81, 0x1000, 0x1242, 0x0210, /* 88 */ + 0x80DF, 0x0F1F, 0x2F3F, 0x4F5F, 0x6F7F, 0x0F1F, 0x2F3F, 0x4F5F, /* 90 */ + 0x6F7F, 0x4BAD, 0x0000, 0x0000, 0x0800, 0x0000, 0x2400, 0xB651, /* 98 */ + 0xC9E0, 0x4247, 0x0A24, 0x0000, 0xAF19, 0x1004, 0x0000, 0x0000, /* A0 */ + 0x0000, 0x0013, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* A8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /* B0 */ + 0x0000, 0x0000, 0x0000, 0x0060, 0x0000, 0x0000, 0x0000, 0x0000, /* B8 */ + 0x0000, 0x0000, 0x3010, 0xFA00, 0x0000, 0x0000, 0x0000, 0x0003, /* C0 */ + 0x1618, 0x8200, 0x8000, 0x0400, 0x050F, 0x0000, 0x0000, 0x0000, /* C8 */ + 0x4C93, 0x0000, 0x1000, 0x1120, 0x0010, 0x1242, 0x1242, 0x1E00, /* D0 */ + 0x0000, 0x0000, 0x0000, 0x00F8, 0x0000, 0x0041, 0x0800, 0x0000, /* D8 */ + 0x82A0, 0x572E, 0x2490, 0x14A9, 0x4E00, 0x0000, 0x0803, 0x0541, /* E0 */ + 0x0C15, 0x0000, 0x0000, 0x0400, 0x2626, 0x0000, 0x0000, 0x4200, /* E8 */ + 0x0000, 0xAA55, 0x1020, 0x0000, 0x0000, 0x5010, 0x0000, 0x0000, /* F0 */ + 0x0000, 0x0000, 0x5000, 0x0000, 0x0000, 0x0000, 0x02F2, 0x0000, /* F8 */ + 0x101F, 0xFDC0, 0x4000, 0x8010, 0x0110, 0x0006, 0x0000, 0x0000, /*100 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*108 */ + 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04CF, 0x0000, 0x04C6, 0x0000, /*110 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*118 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*120 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*128 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*130 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*138 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*140 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*148 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*150 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*158 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*160 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*168 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*170 */ + 0x0000, 0x0000, 0x0000, 0x00F0, 0x08A2, 0x3112, 0x0A14, 0x0000, /*178 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*180 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*188 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*190 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*198 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1A8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1B8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1C8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1D8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1E8 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, /*1F0 */ + 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 /*1F8 */ +}; + +/* PHY selector configures with corresponding modes */ +static int mvebu_a3700_comphy_set_phy_selector(uint8_t comphy_index, + uint32_t comphy_mode) +{ + uint32_t reg; + int mode = COMPHY_GET_MODE(comphy_mode); + + reg = mmio_read_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG); + switch (mode) { + case (COMPHY_SATA_MODE): + /* SATA must be in Lane2 */ + if (comphy_index == COMPHY_LANE2) + reg &= ~COMPHY_SELECTOR_USB3_PHY_SEL_BIT; + else + goto error; + break; + + case (COMPHY_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): + if (comphy_index == COMPHY_LANE0) + reg &= ~COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; + else if (comphy_index == COMPHY_LANE1) + reg &= ~COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; + else + goto error; + break; + + case (COMPHY_USB3H_MODE): + case (COMPHY_USB3D_MODE): + case (COMPHY_USB3_MODE): + if (comphy_index == COMPHY_LANE2) + reg |= COMPHY_SELECTOR_USB3_PHY_SEL_BIT; + else if (comphy_index == COMPHY_LANE0) + reg |= COMPHY_SELECTOR_USB3_GBE1_SEL_BIT; + else + goto error; + break; + + case (COMPHY_PCIE_MODE): + /* PCIE must be in Lane1 */ + if (comphy_index == COMPHY_LANE1) + reg |= COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT; + else + goto error; + break; + + default: + goto error; + } + + mmio_write_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG, reg); + return 0; +error: + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); + return -EINVAL; +} + +/* + * This is something like the inverse of the previous function: for given + * lane it returns COMPHY_*_MODE. + * + * It is useful when powering the phy off. + * + * This function returns COMPHY_USB3_MODE even if the phy was configured + * with COMPHY_USB3D_MODE or COMPHY_USB3H_MODE. (The usb3 phy initialization + * code does not differentiate between these modes.) + * Also it returns COMPHY_SGMII_MODE even if the phy was configures with + * COMPHY_2500BASEX_MODE. (The sgmii phy initialization code does differentiate + * between these modes, but it is irrelevant when powering the phy off.) + */ +static int mvebu_a3700_comphy_get_mode(uint8_t comphy_index) +{ + uint32_t reg; + + reg = mmio_read_32(MVEBU_COMPHY_REG_BASE + COMPHY_SELECTOR_PHY_REG); + switch (comphy_index) { + case COMPHY_LANE0: + if ((reg & COMPHY_SELECTOR_USB3_GBE1_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE1: + if ((reg & COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT) != 0) + return COMPHY_PCIE_MODE; + else + return COMPHY_SGMII_MODE; + case COMPHY_LANE2: + if ((reg & COMPHY_SELECTOR_USB3_PHY_SEL_BIT) != 0) + return COMPHY_USB3_MODE; + else + return COMPHY_SATA_MODE; + } + + return COMPHY_UNUSED; +} + +/* It is only used for SATA and USB3 on comphy lane2. */ +static void comphy_set_indirect(uintptr_t addr, uint32_t offset, uint16_t data, + uint16_t mask, bool is_sata) +{ + /* + * When Lane 2 PHY is for USB3, access the PHY registers + * through indirect Address and Data registers: + * INDIR_ACC_PHY_ADDR (RD00E0178h [31:0]), + * INDIR_ACC_PHY_DATA (RD00E017Ch [31:0]), + * within the SATA Host Controller registers, Lane 2 base register + * offset is 0x200 + */ + if (is_sata) { + mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, offset); + } else { + mmio_write_32(addr + COMPHY_LANE2_INDIR_ADDR_OFFSET, + offset + USB3PHY_LANE2_REG_BASE_OFFSET); + } + + reg_set(addr + COMPHY_LANE2_INDIR_DATA_OFFSET, data, mask); +} + +/* It is only used for SATA on comphy lane2. */ +static void comphy_sata_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, true); +} + +/* It is only used for USB3 indirect access on comphy lane2. */ +static void comphy_usb3_set_indirect(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + comphy_set_indirect(addr, reg_offset, data, mask, false); +} + +/* It is only used for USB3 direct access not on comphy lane2. */ +static void comphy_usb3_set_direct(uintptr_t addr, uint32_t reg_offset, + uint16_t data, uint16_t mask) +{ + reg_set16((reg_offset * PHY_SHFT(USB3) + addr), data, mask); +} + +static void comphy_sgmii_phy_init(uintptr_t sd_ip_addr, bool is_1gbps) +{ + const int fix_arr_sz = ARRAY_SIZE(sgmii_phy_init_fix); + int addr, fix_idx; + uint16_t val; + + fix_idx = 0; + for (addr = 0; addr < 512; addr++) { + /* + * All PHY register values are defined in full for 3.125Gbps + * SERDES speed. The values required for 1.25 Gbps are almost + * the same and only few registers should be "fixed" in + * comparison to 3.125 Gbps values. These register values are + * stored in "sgmii_phy_init_fix" array. + */ + if (!is_1gbps && sgmii_phy_init_fix[fix_idx].addr == addr) { + /* Use new value */ + val = sgmii_phy_init_fix[fix_idx].value; + if (fix_idx < fix_arr_sz) + fix_idx++; + } else { + val = sgmii_phy_init[addr]; + } + + reg_set16(SGMIIPHY_ADDR(addr, sd_ip_addr), val, 0xFFFF); + } +} + +static int mvebu_a3700_comphy_sata_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t offset, data = 0, ref_clk; + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Configure phy selector for SATA */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Clear phy isolation mode to make it work in normal mode */ + offset = COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, PHY_ISOLATE_MODE); + + /* 0. Check the Polarity invert bits */ + if (invert & COMPHY_POLARITY_TXD_INVERT) + data |= TXD_INVERT_BIT; + if (invert & COMPHY_POLARITY_RXD_INVERT) + data |= RXD_INVERT_BIT; + + offset = COMPHY_SYNC_PATTERN + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, data, TXD_INVERT_BIT | + RXD_INVERT_BIT); + + /* 1. Select 40-bit data width width */ + offset = COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, DATA_WIDTH_40BIT, + SEL_DATA_WIDTH_MASK); + + /* 2. Select reference clock(25M) and PHY mode (SATA) */ + offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + if (get_ref_clk() == 40) + ref_clk = REF_FREF_SEL_SERDES_40MHZ; + else + ref_clk = REF_FREF_SEL_SERDES_25MHZ; + + comphy_sata_set_indirect(comphy_indir_regs, offset, ref_clk | PHY_MODE_SATA, + REF_FREF_SEL_MASK | PHY_MODE_MASK); + + /* 3. Use maximum PLL rate (no power save) */ + offset = COMPHY_KVCO_CAL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, USE_MAX_PLL_RATE_BIT, + USE_MAX_PLL_RATE_BIT); + + /* 4. Reset reserved bit */ + comphy_sata_set_indirect(comphy_indir_regs, COMPHY_RESERVED_REG, 0, + PHYCTRL_FRM_PIN_BIT); + + /* 5. Set vendor-specific configuration (It is done in sata driver) */ + /* XXX: in U-Boot below sequence was executed in this place, in Linux + * not. Now it is done only in U-Boot before this comphy + * initialization - tests shows that it works ok, but in case of any + * future problem it is left for reference. + * reg_set(MVEBU_REGS_BASE + 0xe00a0, 0, 0xffffffff); + * reg_set(MVEBU_REGS_BASE + 0xe00a4, BIT(6), BIT(6)); + */ + + /* Wait for > 55 us to allow PLL be enabled */ + udelay(PLL_SET_DELAY_US); + + /* Polling status */ + mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET, + COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET); + + ret = polling_with_timeout(comphy_indir_regs + + COMPHY_LANE2_INDIR_DATA_OFFSET, + PLL_READY_TX_BIT, PLL_READY_TX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sgmii_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t mask, data; + uintptr_t offset; + uintptr_t sd_ip_addr; + int mode = COMPHY_GET_MODE(comphy_mode); + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Set selector */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Serdes IP Base address + * COMPHY Lane0 -- USB3/GBE1 + * COMPHY Lane1 -- PCIe/GBE0 + */ + if (comphy_index == COMPHY_LANE0) { + /* Get usb3 and gbe */ + sd_ip_addr = USB3_GBE1_PHY; + } else + sd_ip_addr = COMPHY_SD_ADDR; + + /* + * 1. Reset PHY by setting PHY input port PIN_RESET=1. + * 2. Set PHY input port PIN_TX_IDLE=1, PIN_PU_IVREF=1 to keep + * PHY TXP/TXN output to idle state during PHY initialization + * 3. Set PHY input port PIN_PU_PLL=0, PIN_PU_RX=0, PIN_PU_TX=0. + */ + data = PIN_PU_IVREF_BIT | PIN_TX_IDLE_BIT | PIN_RESET_COMPHY_BIT; + mask = data | PIN_RESET_CORE_BIT | PIN_PU_PLL_BIT | PIN_PU_RX_BIT | + PIN_PU_TX_BIT; + offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index); + reg_set(offset, data, mask); + + /* 4. Release reset to the PHY by setting PIN_RESET=0. */ + data = 0; + mask = PIN_RESET_COMPHY_BIT; + reg_set(offset, data, mask); + + /* + * 5. Set PIN_PHY_GEN_TX[3:0] and PIN_PHY_GEN_RX[3:0] to decide COMPHY + * bit rate + */ + if (mode == COMPHY_SGMII_MODE) { + /* SGMII 1G, SerDes speed 1.25G */ + data |= SD_SPEED_1_25_G << GEN_RX_SEL_OFFSET; + data |= SD_SPEED_1_25_G << GEN_TX_SEL_OFFSET; + } else if (mode == COMPHY_2500BASEX_MODE) { + /* 2500Base-X, SerDes speed 3.125G */ + data |= SD_SPEED_3_125_G << GEN_RX_SEL_OFFSET; + data |= SD_SPEED_3_125_G << GEN_TX_SEL_OFFSET; + } else { + /* Other rates are not supported */ + ERROR("unsupported SGMII speed on comphy lane%d\n", + comphy_index); + return -EINVAL; + } + mask = GEN_RX_SEL_MASK | GEN_TX_SEL_MASK; + reg_set(offset, data, mask); + + /* + * 6. Wait 10mS for bandgap and reference clocks to stabilize; then + * start SW programming. + */ + mdelay(10); + + /* 7. Program COMPHY register PHY_MODE */ + data = PHY_MODE_SGMII; + mask = PHY_MODE_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_POWER_PLL_CTRL, sd_ip_addr), data, mask); + + /* + * 8. Set COMPHY register REFCLK_SEL to select the correct REFCLK + * source + */ + data = 0; + mask = PHY_REF_CLK_SEL; + reg_set16(SGMIIPHY_ADDR(COMPHY_MISC_CTRL0, sd_ip_addr), data, mask); + + /* + * 9. Set correct reference clock frequency in COMPHY register + * REF_FREF_SEL. + */ + if (get_ref_clk() == 40) + data = REF_FREF_SEL_SERDES_50MHZ; + else + data = REF_FREF_SEL_SERDES_25MHZ; + + mask = REF_FREF_SEL_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_POWER_PLL_CTRL, sd_ip_addr), data, mask); + + /* 10. Program COMPHY register PHY_GEN_MAX[1:0] + * This step is mentioned in the flow received from verification team. + * However the PHY_GEN_MAX value is only meaningful for other interfaces + * (not SGMII). For instance, it selects SATA speed 1.5/3/6 Gbps or PCIe + * speed 2.5/5 Gbps + */ + + /* + * 11. Program COMPHY register SEL_BITS to set correct parallel data + * bus width + */ + data = DATA_WIDTH_10BIT; + mask = SEL_DATA_WIDTH_MASK; + reg_set16(SGMIIPHY_ADDR(COMPHY_DIG_LOOPBACK_EN, sd_ip_addr), + data, mask); + + /* + * 12. As long as DFE function needs to be enabled in any mode, + * COMPHY register DFE_UPDATE_EN[5:0] shall be programmed to 0x3F + * for real chip during COMPHY power on. + * The step 14 exists (and empty) in the original initialization flow + * obtained from the verification team. According to the functional + * specification DFE_UPDATE_EN already has the default value 0x3F + */ + + /* + * 13. Program COMPHY GEN registers. + * These registers should be programmed based on the lab testing result + * to achieve optimal performance. Please contact the CEA group to get + * the related GEN table during real chip bring-up. We only required to + * run though the entire registers programming flow defined by + * "comphy_sgmii_phy_init" when the REF clock is 40 MHz. For REF clock + * 25 MHz the default values stored in PHY registers are OK. + */ + debug("Running C-DPI phy init %s mode\n", + mode == COMPHY_2500BASEX_MODE ? "2G5" : "1G"); + if (get_ref_clk() == 40) + comphy_sgmii_phy_init(sd_ip_addr, mode != COMPHY_2500BASEX_MODE); + + /* + * 14. [Simulation Only] should not be used for real chip. + * By pass power up calibration by programming EXT_FORCE_CAL_DONE + * (R02h[9]) to 1 to shorten COMPHY simulation time. + */ + + /* + * 15. [Simulation Only: should not be used for real chip] + * Program COMPHY register FAST_DFE_TIMER_EN=1 to shorten RX training + * simulation time. + */ + + /* + * 16. Check the PHY Polarity invert bit + */ + data = 0x0; + if (invert & COMPHY_POLARITY_TXD_INVERT) + data |= TXD_INVERT_BIT; + if (invert & COMPHY_POLARITY_RXD_INVERT) + data |= RXD_INVERT_BIT; + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + reg_set16(SGMIIPHY_ADDR(COMPHY_SYNC_PATTERN, sd_ip_addr), data, mask); + + /* + * 17. Set PHY input ports PIN_PU_PLL, PIN_PU_TX and PIN_PU_RX to 1 to + * start PHY power up sequence. All the PHY register programming should + * be done before PIN_PU_PLL=1. There should be no register programming + * for normal PHY operation from this point. + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT, + PIN_PU_PLL_BIT | PIN_PU_RX_BIT | PIN_PU_TX_BIT); + + /* + * 18. Wait for PHY power up sequence to finish by checking output ports + * PIN_PLL_READY_TX=1 and PIN_PLL_READY_RX=1. + */ + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + /* + * 19. Set COMPHY input port PIN_TX_IDLE=0 + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + 0x0, PIN_TX_IDLE_BIT); + + /* + * 20. After valid data appear on PIN_RXDATA bus, set PIN_RX_INIT=1. To + * start RX initialization. PIN_RX_INIT_DONE will be cleared to 0 by the + * PHY After RX initialization is done, PIN_RX_INIT_DONE will be set to + * 1 by COMPHY Set PIN_RX_INIT=0 after PIN_RX_INIT_DONE= 1. Please + * refer to RX initialization part for details. + */ + reg_set(MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index), + PHY_RX_INIT_BIT, PHY_RX_INIT_BIT); + + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + PHY_PLL_READY_TX_BIT | PHY_PLL_READY_RX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to lock PLL for SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + ret = polling_with_timeout(MVEBU_COMPHY_REG_BASE + + COMPHY_PHY_STATUS_OFFSET(comphy_index), + PHY_RX_INIT_DONE_BIT, PHY_RX_INIT_DONE_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + if (ret) { + ERROR("Failed to init RX of SGMII PHY %d\n", comphy_index); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sgmii_power_off(uint8_t comphy_index) +{ + uintptr_t offset; + uint32_t mask, data; + + debug_enter(); + + data = PIN_RESET_CORE_BIT | PIN_RESET_COMPHY_BIT; + mask = data; + offset = MVEBU_COMPHY_REG_BASE + COMPHY_PHY_CFG1_OFFSET(comphy_index); + reg_set(offset, data, mask); + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_usb3_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uintptr_t reg_base = 0; + uintptr_t addr; + uint32_t mask, data, cfg, ref_clk; + void (*usb3_reg_set)(uintptr_t addr, uint32_t reg_offset, uint16_t data, + uint16_t mask); + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Set phy seclector */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* Set usb3 reg access func, Lane2 is indirect access */ + if (comphy_index == COMPHY_LANE2) { + usb3_reg_set = &comphy_usb3_set_indirect; + reg_base = COMPHY_INDIRECT_REG; + } else { + /* Get the direct access register resource and map */ + usb3_reg_set = &comphy_usb3_set_direct; + reg_base = USB3_GBE1_PHY; + } + + /* + * 0. Set PHY OTG Control(0x5d034), bit 4, Power up OTG module The + * register belong to UTMI module, so it is set in UTMI phy driver. + */ + + /* + * 1. Set PRD_TXDEEMPH (3.5db de-emph) + */ + mask = PRD_TXDEEMPH0_MASK | PRD_TXMARGIN_MASK | PRD_TXSWING_MASK | + CFG_TX_ALIGN_POS_MASK; + usb3_reg_set(reg_base, COMPHY_LANE_CFG0, PRD_TXDEEMPH0_MASK, mask); + + /* + * 2. Set BIT0: enable transmitter in high impedance mode + * Set BIT[3:4]: delay 2 clock cycles for HiZ off latency + * Set BIT6: Tx detect Rx at HiZ mode + * Unset BIT15: set to 0 to set USB3 De-emphasize level to -3.5db + * together with bit 0 of COMPHY_LANE_CFG0 register + */ + mask = PRD_TXDEEMPH1_MASK | TX_DET_RX_MODE | GEN2_TX_DATA_DLY_MASK | + TX_ELEC_IDLE_MODE_EN; + data = TX_DET_RX_MODE | GEN2_TX_DATA_DLY_DEFT | TX_ELEC_IDLE_MODE_EN; + usb3_reg_set(reg_base, COMPHY_LANE_CFG1, data, mask); + + /* + * 3. Set Spread Spectrum Clock Enabled + */ + usb3_reg_set(reg_base, COMPHY_LANE_CFG4, + SPREAD_SPECTRUM_CLK_EN, SPREAD_SPECTRUM_CLK_EN); + + /* + * 4. Set Override Margining Controls From the MAC: + * Use margining signals from lane configuration + */ + usb3_reg_set(reg_base, COMPHY_TEST_MODE_CTRL, + MODE_MARGIN_OVERRIDE, REG_16_BIT_MASK); + + /* + * 5. Set Lane-to-Lane Bundle Clock Sampling Period = per PCLK cycles + * set Mode Clock Source = PCLK is generated from REFCLK + */ + usb3_reg_set(reg_base, COMPHY_CLK_SRC_LO, 0x0, + (MODE_CLK_SRC | BUNDLE_PERIOD_SEL | + BUNDLE_PERIOD_SCALE_MASK | BUNDLE_SAMPLE_CTRL | + PLL_READY_DLY_MASK)); + + /* + * 6. Set G2 Spread Spectrum Clock Amplitude at 4K + */ + usb3_reg_set(reg_base, COMPHY_GEN2_SET2, + GS2_TX_SSC_AMP_VALUE_20, GS2_TX_SSC_AMP_MASK); + + /* + * 7. Unset G3 Spread Spectrum Clock Amplitude + * set G3 TX and RX Register Master Current Select + */ + mask = GS2_TX_SSC_AMP_MASK | GS2_VREG_RXTX_MAS_ISET_MASK | + GS2_RSVD_6_0_MASK; + usb3_reg_set(reg_base, COMPHY_GEN3_SET2, + GS2_VREG_RXTX_MAS_ISET_60U, mask); + + /* + * 8. Check crystal jumper setting and program the Power and PLL Control + * accordingly Change RX wait + */ + if (get_ref_clk() == 40) { + ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; + cfg = CFG_PM_RXDLOZ_WAIT_12_UNIT; + + } else { + /* 25 MHz */ + ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; + cfg = CFG_PM_RXDLOZ_WAIT_7_UNIT; + } + + mask = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | PLL_LOCK_BIT | PHY_MODE_MASK | + REF_FREF_SEL_MASK; + data = PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | PHY_MODE_USB3 | ref_clk; + usb3_reg_set(reg_base, COMPHY_POWER_PLL_CTRL, data, mask); + + mask = CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | + CFG_PM_RXDLOZ_WAIT_MASK; + data = CFG_PM_RXDEN_WAIT_1_UNIT | cfg; + usb3_reg_set(reg_base, COMPHY_PWR_MGM_TIM1, data, mask); + + /* + * 9. Enable idle sync + */ + data = IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN; + usb3_reg_set(reg_base, COMPHY_IDLE_SYNC_EN, data, REG_16_BIT_MASK); + + /* + * 10. Enable the output of 500M clock + */ + data = MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN; + usb3_reg_set(reg_base, COMPHY_MISC_CTRL0, data, REG_16_BIT_MASK); + + /* + * 11. Set 20-bit data width + */ + usb3_reg_set(reg_base, COMPHY_DIG_LOOPBACK_EN, DATA_WIDTH_20BIT, + REG_16_BIT_MASK); + + /* + * 12. Override Speed_PLL value and use MAC PLL + */ + usb3_reg_set(reg_base, COMPHY_KVCO_CAL_CTRL, + (SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT), + REG_16_BIT_MASK); + + /* + * 13. Check the Polarity invert bit + */ + data = 0U; + if (invert & COMPHY_POLARITY_TXD_INVERT) { + data |= TXD_INVERT_BIT; + } + if (invert & COMPHY_POLARITY_RXD_INVERT) { + data |= RXD_INVERT_BIT; + } + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + usb3_reg_set(reg_base, COMPHY_SYNC_PATTERN, data, mask); + + /* + * 14. Set max speed generation to USB3.0 5Gbps + */ + usb3_reg_set(reg_base, COMPHY_SYNC_MASK_GEN, PHY_GEN_MAX_USB3_5G, + PHY_GEN_MAX_MASK); + + /* + * 15. Set capacitor value for FFE gain peaking to 0xF + */ + usb3_reg_set(reg_base, COMPHY_GEN2_SET3, + GS3_FFE_CAP_SEL_VALUE, GS3_FFE_CAP_SEL_MASK); + + /* + * 16. Release SW reset + */ + data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32 | MODE_REFDIV_BY_4; + usb3_reg_set(reg_base, COMPHY_RST_CLK_CTRL, data, REG_16_BIT_MASK); + + /* Wait for > 55 us to allow PCLK be enabled */ + udelay(PLL_SET_DELAY_US); + + if (comphy_index == COMPHY_LANE2) { + data = COMPHY_LANE_STAT1 + USB3PHY_LANE2_REG_BASE_OFFSET; + mmio_write_32(reg_base + COMPHY_LANE2_INDIR_ADDR_OFFSET, + data); + + addr = reg_base + COMPHY_LANE2_INDIR_DATA_OFFSET; + ret = polling_with_timeout(addr, TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_32BIT); + } else { + ret = polling_with_timeout(LANE_STAT1_ADDR(USB3) + reg_base, + TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_16BIT); + } + if (ret) { + ERROR("Failed to lock USB3 PLL\n"); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_pcie_power_on(uint8_t comphy_index, + uint32_t comphy_mode) +{ + int ret; + uint32_t ref_clk; + uint32_t mask, data; + int invert = COMPHY_GET_POLARITY_INVERT(comphy_mode); + + debug_enter(); + + /* Configure phy selector for PCIe */ + ret = mvebu_a3700_comphy_set_phy_selector(comphy_index, comphy_mode); + if (ret) { + return ret; + } + + /* 1. Enable max PLL. */ + reg_set16(LANE_CFG1_ADDR(PCIE) + COMPHY_SD_ADDR, + USE_MAX_PLL_RATE_EN, USE_MAX_PLL_RATE_EN); + + /* 2. Select 20 bit SERDES interface. */ + reg_set16(CLK_SRC_LO_ADDR(PCIE) + COMPHY_SD_ADDR, + CFG_SEL_20B, CFG_SEL_20B); + + /* 3. Force to use reg setting for PCIe mode */ + reg_set16(MISC_CTRL1_ADDR(PCIE) + COMPHY_SD_ADDR, + SEL_BITS_PCIE_FORCE, SEL_BITS_PCIE_FORCE); + + /* 4. Change RX wait */ + reg_set16(PWR_MGM_TIM1_ADDR(PCIE) + COMPHY_SD_ADDR, + CFG_PM_RXDEN_WAIT_1_UNIT | CFG_PM_RXDLOZ_WAIT_12_UNIT, + (CFG_PM_OSCCLK_WAIT_MASK | CFG_PM_RXDEN_WAIT_MASK | + CFG_PM_RXDLOZ_WAIT_MASK)); + + /* 5. Enable idle sync */ + reg_set16(IDLE_SYNC_EN_ADDR(PCIE) + COMPHY_SD_ADDR, + IDLE_SYNC_EN_DEFAULT_VALUE | IDLE_SYNC_EN, REG_16_BIT_MASK); + + /* 6. Enable the output of 100M/125M/500M clock */ + reg_set16(MISC_CTRL0_ADDR(PCIE) + COMPHY_SD_ADDR, + MISC_CTRL0_DEFAULT_VALUE | CLK500M_EN | TXDCLK_2X_SEL | CLK100M_125M_EN, + REG_16_BIT_MASK); + + /* + * 7. Enable TX, PCIE global register, 0xd0074814, it is done in + * PCI-E driver + */ + + /* + * 8. Check crystal jumper setting and program the Power and PLL + * Control accordingly + */ + + if (get_ref_clk() == 40) + ref_clk = REF_FREF_SEL_PCIE_USB3_40MHZ; + else + ref_clk = REF_FREF_SEL_PCIE_USB3_25MHZ; + + reg_set16(PWR_PLL_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, + (PU_IVREF_BIT | PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT | + PU_TX_INTP_BIT | PU_DFE_BIT | ref_clk | PHY_MODE_PCIE), + REG_16_BIT_MASK); + + /* 9. Override Speed_PLL value and use MAC PLL */ + reg_set16(KVCO_CAL_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, + SPEED_PLL_VALUE_16 | USE_MAX_PLL_RATE_BIT, REG_16_BIT_MASK); + + /* 10. Check the Polarity invert bit */ + data = 0U; + if (invert & COMPHY_POLARITY_TXD_INVERT) { + data |= TXD_INVERT_BIT; + } + if (invert & COMPHY_POLARITY_RXD_INVERT) { + data |= RXD_INVERT_BIT; + } + mask = TXD_INVERT_BIT | RXD_INVERT_BIT; + reg_set16(SYNC_PATTERN_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask); + + /* 11. Release SW reset */ + data = MODE_CORE_CLK_FREQ_SEL | MODE_PIPE_WIDTH_32; + mask = data | SOFT_RESET | MODE_REFDIV_MASK; + reg_set16(RST_CLK_CTRL_ADDR(PCIE) + COMPHY_SD_ADDR, data, mask); + + /* Wait for > 55 us to allow PCLK be enabled */ + udelay(PLL_SET_DELAY_US); + + ret = polling_with_timeout(LANE_STAT1_ADDR(PCIE) + COMPHY_SD_ADDR, + TXDCLK_PCLK_EN, TXDCLK_PCLK_EN, + COMPHY_PLL_TIMEOUT, REG_16BIT); + if (ret) { + ERROR("Failed to lock PCIE PLL\n"); + return -ETIMEDOUT; + } + + debug_exit(); + + return 0; +} + +int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int ret = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + ret = mvebu_a3700_comphy_sata_power_on(comphy_index, + comphy_mode); + break; + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + ret = mvebu_a3700_comphy_sgmii_power_on(comphy_index, + comphy_mode); + break; + case (COMPHY_USB3_MODE): + case (COMPHY_USB3H_MODE): + ret = mvebu_a3700_comphy_usb3_power_on(comphy_index, + comphy_mode); + break; + case (COMPHY_PCIE_MODE): + ret = mvebu_a3700_comphy_pcie_power_on(comphy_index, + comphy_mode); + break; + default: + ERROR("comphy%d: unsupported comphy mode\n", comphy_index); + ret = -EINVAL; + break; + } + + debug_exit(); + + return ret; +} + +static int mvebu_a3700_comphy_usb3_power_off(void) +{ + /* + * Currently the USB3 MAC will control the USB3 PHY to set it to low + * state, thus do not need to power off USB3 PHY again. + */ + debug_enter(); + debug_exit(); + + return 0; +} + +static int mvebu_a3700_comphy_sata_power_off(void) +{ + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + uint32_t offset; + + debug_enter(); + + /* Set phy isolation mode */ + offset = COMPHY_ISOLATION_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, PHY_ISOLATE_MODE, + PHY_ISOLATE_MODE); + + /* Power off PLL, Tx, Rx */ + offset = COMPHY_POWER_PLL_CTRL + SATAPHY_LANE2_REG_BASE_OFFSET; + comphy_sata_set_indirect(comphy_indir_regs, offset, 0, + PU_PLL_BIT | PU_RX_BIT | PU_TX_BIT); + + debug_exit(); + + return 0; +} + +int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int err = 0; + + debug_enter(); + + if (!mode) { + /* + * The user did not specify which mode should be powered off. + * In this case we can identify this by reading the phy selector + * register. + */ + mode = mvebu_a3700_comphy_get_mode(comphy_index); + } + + switch (mode) { + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + err = mvebu_a3700_comphy_sgmii_power_off(comphy_index); + break; + case (COMPHY_USB3_MODE): + case (COMPHY_USB3H_MODE): + err = mvebu_a3700_comphy_usb3_power_off(); + break; + case (COMPHY_SATA_MODE): + err = mvebu_a3700_comphy_sata_power_off(); + break; + + default: + debug("comphy%d: power off is not implemented for mode %d\n", + comphy_index, mode); + break; + } + + debug_exit(); + + return err; +} + +static int mvebu_a3700_comphy_sata_is_pll_locked(void) +{ + uint32_t data, addr; + uintptr_t comphy_indir_regs = COMPHY_INDIRECT_REG; + int ret = 0; + + debug_enter(); + + /* Polling status */ + mmio_write_32(comphy_indir_regs + COMPHY_LANE2_INDIR_ADDR_OFFSET, + COMPHY_DIG_LOOPBACK_EN + SATAPHY_LANE2_REG_BASE_OFFSET); + addr = comphy_indir_regs + COMPHY_LANE2_INDIR_DATA_OFFSET; + data = polling_with_timeout(addr, PLL_READY_TX_BIT, PLL_READY_TX_BIT, + COMPHY_PLL_TIMEOUT, REG_32BIT); + + if (data != 0) { + ERROR("TX PLL is not locked\n"); + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +int mvebu_3700_comphy_is_pll_locked(uint8_t comphy_index, uint32_t comphy_mode) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int ret = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + ret = mvebu_a3700_comphy_sata_is_pll_locked(); + break; + + default: + ERROR("comphy[%d] mode[%d] doesn't support PLL lock check\n", + comphy_index, mode); + ret = -EINVAL; + break; + } + + debug_exit(); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h new file mode 100644 index 0000000..ed07624 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h @@ -0,0 +1,249 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PHY_COMPHY_3700_H +#define PHY_COMPHY_3700_H + +#define PLL_SET_DELAY_US 600 +#define COMPHY_PLL_TIMEOUT 1000 +#define REG_16_BIT_MASK 0xFFFF + +#define COMPHY_SELECTOR_PHY_REG 0xFC +/* bit0: 0: Lane1 is GbE0; 1: Lane1 is PCIE */ +#define COMPHY_SELECTOR_PCIE_GBE0_SEL_BIT BIT(0) +/* bit4: 0: Lane0 is GbE1; 1: Lane0 is USB3 */ +#define COMPHY_SELECTOR_USB3_GBE1_SEL_BIT BIT(4) +/* bit8: 0: Lane0 is USB3 instead of GbE1, Lane2 is SATA; 1: Lane2 is USB3 */ +#define COMPHY_SELECTOR_USB3_PHY_SEL_BIT BIT(8) + +/* SATA PHY register offset */ +#define SATAPHY_LANE2_REG_BASE_OFFSET 0x200 + +/* USB3 PHY offset compared to SATA PHY */ +#define USB3PHY_LANE2_REG_BASE_OFFSET 0x200 + +/* Comphy lane2 indirect access register offset */ +#define COMPHY_LANE2_INDIR_ADDR_OFFSET 0x0 +#define COMPHY_LANE2_INDIR_DATA_OFFSET 0x4 + +/* PHY shift to get related register address */ +enum { + PCIE = 1, + USB3, +}; + +#define PCIEPHY_SHFT 2 +#define USB3PHY_SHFT 2 +#define PHY_SHFT(unit) ((unit == PCIE) ? PCIEPHY_SHFT : USB3PHY_SHFT) + +/* PHY register */ +#define COMPHY_POWER_PLL_CTRL 0x01 +#define PWR_PLL_CTRL_ADDR(unit) (COMPHY_POWER_PLL_CTRL * PHY_SHFT(unit)) +#define PU_IVREF_BIT BIT(15) +#define PU_PLL_BIT BIT(14) +#define PU_RX_BIT BIT(13) +#define PU_TX_BIT BIT(12) +#define PU_TX_INTP_BIT BIT(11) +#define PU_DFE_BIT BIT(10) +#define RESET_DTL_RX_BIT BIT(9) +#define PLL_LOCK_BIT BIT(8) +#define REF_FREF_SEL_OFFSET 0 +#define REF_FREF_SEL_MASK (0x1F << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_25MHZ (0x1 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_40MHZ (0x3 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_SERDES_50MHZ (0x4 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_PCIE_USB3_25MHZ (0x2 << REF_FREF_SEL_OFFSET) +#define REF_FREF_SEL_PCIE_USB3_40MHZ (0x3 << REF_FREF_SEL_OFFSET) +#define PHY_MODE_OFFSET 5 +#define PHY_MODE_MASK (7 << PHY_MODE_OFFSET) +#define PHY_MODE_SATA (0x0 << PHY_MODE_OFFSET) +#define PHY_MODE_PCIE (0x3 << PHY_MODE_OFFSET) +#define PHY_MODE_SGMII (0x4 << PHY_MODE_OFFSET) +#define PHY_MODE_USB3 (0x5 << PHY_MODE_OFFSET) + +#define COMPHY_KVCO_CAL_CTRL 0x02 +#define KVCO_CAL_CTRL_ADDR(unit) (COMPHY_KVCO_CAL_CTRL * PHY_SHFT(unit)) +#define USE_MAX_PLL_RATE_BIT BIT(12) +#define SPEED_PLL_OFFSET 2 +#define SPEED_PLL_MASK (0x3F << SPEED_PLL_OFFSET) +#define SPEED_PLL_VALUE_16 (0x10 << SPEED_PLL_OFFSET) + +#define COMPHY_DIG_LOOPBACK_EN 0x23 +#define DIG_LOOPBACK_EN_ADDR(unit) (COMPHY_DIG_LOOPBACK_EN * \ + PHY_SHFT(unit)) +#define SEL_DATA_WIDTH_OFFSET 10 +#define SEL_DATA_WIDTH_MASK (0x3 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_10BIT (0x0 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_20BIT (0x1 << SEL_DATA_WIDTH_OFFSET) +#define DATA_WIDTH_40BIT (0x2 << SEL_DATA_WIDTH_OFFSET) +#define PLL_READY_TX_BIT BIT(4) + +#define COMPHY_SYNC_PATTERN 0x24 +#define SYNC_PATTERN_ADDR(unit) (COMPHY_SYNC_PATTERN * PHY_SHFT(unit)) +#define TXD_INVERT_BIT BIT(10) +#define RXD_INVERT_BIT BIT(11) + +#define COMPHY_SYNC_MASK_GEN 0x25 +#define PHY_GEN_MAX_OFFSET 10 +#define PHY_GEN_MAX_MASK (3 << PHY_GEN_MAX_OFFSET) +#define PHY_GEN_MAX_USB3_5G (1 << PHY_GEN_MAX_OFFSET) + +#define COMPHY_ISOLATION_CTRL 0x26 +#define ISOLATION_CTRL_ADDR(unit) (COMPHY_ISOLATION_REG * PHY_SHFT(unit)) +#define PHY_ISOLATE_MODE BIT(15) + +#define COMPHY_GEN2_SET2 0x3e +#define GEN2_SET2_ADDR(unit) (COMPHY_GEN2_SET2 * PHY_SHFT(unit)) +#define GS2_TX_SSC_AMP_VALUE_20 BIT(14) +#define GS2_TX_SSC_AMP_OFF 9 +#define GS2_TX_SSC_AMP_LEN 7 +#define GS2_TX_SSC_AMP_MASK (((1 << GS2_TX_SSC_AMP_LEN) - 1) << \ + GS2_TX_SSC_AMP_OFF) +#define GS2_VREG_RXTX_MAS_ISET_OFF 7 +#define GS2_VREG_RXTX_MAS_ISET_60U (0 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_80U (1 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_100U (2 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_120U (3 << GS2_VREG_RXTX_MAS_ISET_OFF) +#define GS2_VREG_RXTX_MAS_ISET_MASK (BIT(7) | BIT(8)) +#define GS2_RSVD_6_0_OFF 0 +#define GS2_RSVD_6_0_LEN 7 +#define GS2_RSVD_6_0_MASK (((1 << GS2_RSVD_6_0_LEN) - 1) << \ + GS2_RSVD_6_0_OFF) + +#define COMPHY_GEN3_SET2 0x3f +#define GEN3_SET2_ADDR(unit) (COMPHY_GEN3_SET2 * PHY_SHFT(unit)) + +#define COMPHY_IDLE_SYNC_EN 0x48 +#define IDLE_SYNC_EN_ADDR(unit) (COMPHY_IDLE_SYNC_EN * PHY_SHFT(unit)) +#define IDLE_SYNC_EN BIT(12) +#define IDLE_SYNC_EN_DEFAULT_VALUE 0x60 + +#define COMPHY_MISC_CTRL0 0x4F +#define MISC_CTRL0_ADDR(unit) (COMPHY_MISC_CTRL0 * PHY_SHFT(unit)) +#define CLK100M_125M_EN BIT(4) +#define TXDCLK_2X_SEL BIT(6) +#define CLK500M_EN BIT(7) +#define PHY_REF_CLK_SEL BIT(10) +#define MISC_CTRL0_DEFAULT_VALUE 0xA00D + +#define COMPHY_MISC_CTRL1 0x73 +#define MISC_CTRL1_ADDR(unit) (COMPHY_MISC_CTRL1 * PHY_SHFT(unit)) +#define SEL_BITS_PCIE_FORCE BIT(15) + +#define COMPHY_GEN2_SET3 0x112 +#define GS3_FFE_CAP_SEL_MASK 0xF +#define GS3_FFE_CAP_SEL_VALUE 0xF + +#define COMPHY_LANE_CFG0 0x180 +#define LANE_CFG0_ADDR(unit) (COMPHY_LANE_CFG0 * PHY_SHFT(unit)) +#define PRD_TXDEEMPH0_MASK BIT(0) +#define PRD_TXMARGIN_MASK (BIT(1) | BIT(2) | BIT(3)) +#define PRD_TXSWING_MASK BIT(4) +#define CFG_TX_ALIGN_POS_MASK (BIT(5) | BIT(6) | BIT(7) | BIT(8)) + +#define COMPHY_LANE_CFG1 0x181 +#define LANE_CFG1_ADDR(unit) (COMPHY_LANE_CFG1 * PHY_SHFT(unit)) +#define PRD_TXDEEMPH1_MASK BIT(15) +#define USE_MAX_PLL_RATE_EN BIT(9) +#define TX_DET_RX_MODE BIT(6) +#define GEN2_TX_DATA_DLY_MASK (BIT(3) | BIT(4)) +#define GEN2_TX_DATA_DLY_DEFT (2 << 3) +#define TX_ELEC_IDLE_MODE_EN BIT(0) + +#define COMPHY_LANE_STAT1 0x183 +#define LANE_STAT1_ADDR(unit) (COMPHY_LANE_STAT1 * PHY_SHFT(unit)) +#define TXDCLK_PCLK_EN BIT(0) + +#define COMPHY_LANE_CFG4 0x188 +#define LANE_CFG4_ADDR(unit) (COMPHY_LANE_CFG4 * PHY_SHFT(unit)) +#define SPREAD_SPECTRUM_CLK_EN BIT(7) + +#define COMPHY_RST_CLK_CTRL 0x1C1 +#define RST_CLK_CTRL_ADDR(unit) (COMPHY_RST_CLK_CTRL * PHY_SHFT(unit)) +#define SOFT_RESET BIT(0) +#define MODE_CORE_CLK_FREQ_SEL BIT(9) +#define MODE_PIPE_WIDTH_32 BIT(3) +#define MODE_REFDIV_OFFSET 4 +#define MODE_REFDIV_LEN 2 +#define MODE_REFDIV_MASK (0x3 << MODE_REFDIV_OFFSET) +#define MODE_REFDIV_BY_4 (0x2 << MODE_REFDIV_OFFSET) + +#define COMPHY_TEST_MODE_CTRL 0x1C2 +#define TEST_MODE_CTRL_ADDR(unit) (COMPHY_TEST_MODE_CTRL * PHY_SHFT(unit)) +#define MODE_MARGIN_OVERRIDE BIT(2) + +#define COMPHY_CLK_SRC_LO 0x1C3 +#define CLK_SRC_LO_ADDR(unit) (COMPHY_CLK_SRC_LO * PHY_SHFT(unit)) +#define MODE_CLK_SRC BIT(0) +#define BUNDLE_PERIOD_SEL BIT(1) +#define BUNDLE_PERIOD_SCALE_MASK (BIT(2) | BIT(3)) +#define BUNDLE_SAMPLE_CTRL BIT(4) +#define PLL_READY_DLY_MASK (BIT(5) | BIT(6) | BIT(7)) +#define CFG_SEL_20B BIT(15) + +#define COMPHY_PWR_MGM_TIM1 0x1D0 +#define PWR_MGM_TIM1_ADDR(unit) (COMPHY_PWR_MGM_TIM1 * PHY_SHFT(unit)) +#define CFG_PM_OSCCLK_WAIT_OFF 12 +#define CFG_PM_OSCCLK_WAIT_LEN 4 +#define CFG_PM_OSCCLK_WAIT_MASK (((1 << CFG_PM_OSCCLK_WAIT_LEN) - 1) \ + << CFG_PM_OSCCLK_WAIT_OFF) +#define CFG_PM_RXDEN_WAIT_OFF 8 +#define CFG_PM_RXDEN_WAIT_LEN 4 +#define CFG_PM_RXDEN_WAIT_MASK (((1 << CFG_PM_RXDEN_WAIT_LEN) - 1) \ + << CFG_PM_RXDEN_WAIT_OFF) +#define CFG_PM_RXDEN_WAIT_1_UNIT (1 << CFG_PM_RXDEN_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_OFF 0 +#define CFG_PM_RXDLOZ_WAIT_LEN 8 +#define CFG_PM_RXDLOZ_WAIT_MASK (((1 << CFG_PM_RXDLOZ_WAIT_LEN) - 1) \ + << CFG_PM_RXDLOZ_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_7_UNIT (7 << CFG_PM_RXDLOZ_WAIT_OFF) +#define CFG_PM_RXDLOZ_WAIT_12_UNIT (0xC << CFG_PM_RXDLOZ_WAIT_OFF) + +/* + * This register is not from PHY lane register space. It only exists in the + * indirect register space, before the actual PHY lane 2 registers. So the + * offset is absolute, not relative to SATAPHY_LANE2_REG_BASE_OFFSET. + * It is used only for SATA PHY initialization. + */ +#define COMPHY_RESERVED_REG 0x0E +#define PHYCTRL_FRM_PIN_BIT BIT(13) + +/* SGMII */ +#define COMPHY_PHY_CFG1_OFFSET(lane) ((1 - (lane)) * 0x28) +#define PIN_PU_IVREF_BIT BIT(1) +#define PIN_RESET_CORE_BIT BIT(11) +#define PIN_RESET_COMPHY_BIT BIT(12) +#define PIN_PU_PLL_BIT BIT(16) +#define PIN_PU_RX_BIT BIT(17) +#define PIN_PU_TX_BIT BIT(18) +#define PIN_TX_IDLE_BIT BIT(19) +#define GEN_RX_SEL_OFFSET 22 +#define GEN_RX_SEL_MASK (0xF << GEN_RX_SEL_OFFSET) +#define GEN_TX_SEL_OFFSET 26 +#define GEN_TX_SEL_MASK (0xF << GEN_TX_SEL_OFFSET) +#define PHY_RX_INIT_BIT BIT(30) +#define SD_SPEED_1_25_G 0x6 +#define SD_SPEED_3_125_G 0x8 + +/* COMPHY status reg: + * lane0: USB3/GbE1 PHY Status 1 + * lane1: PCIe/GbE0 PHY Status 1 + */ +#define COMPHY_PHY_STATUS_OFFSET(lane) (0x18 + (1 - (lane)) * 0x28) +#define PHY_RX_INIT_DONE_BIT BIT(0) +#define PHY_PLL_READY_RX_BIT BIT(2) +#define PHY_PLL_READY_TX_BIT BIT(3) + +#define SGMIIPHY_ADDR(off, base) ((((off) & 0x00007FF) * 2) + (base)) + +#define MAX_LANE_NR 3 + +/* comphy API */ +int mvebu_3700_comphy_is_pll_locked(uint8_t comphy_index, uint32_t comphy_mode); +int mvebu_3700_comphy_power_off(uint8_t comphy_index, uint32_t comphy_mode); +int mvebu_3700_comphy_power_on(uint8_t comphy_index, uint32_t comphy_mode); +#endif /* PHY_COMPHY_3700_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h new file mode 100644 index 0000000..ba5d255 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h @@ -0,0 +1,167 @@ +/* + * Copyright (C) 2018-2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 ana A3700 common */ + +#ifndef PHY_COMPHY_COMMON_H +#define PHY_COMPHY_COMMON_H + +/* #define DEBUG_COMPHY */ +#ifdef DEBUG_COMPHY +#define debug(format...) printf(format) +#else +#define debug(format, arg...) +#endif + +/* A lane is described by 4 fields: + * - bit 1~0 represent comphy polarity invert + * - bit 7~2 represent comphy speed + * - bit 11~8 represent unit index + * - bit 16~12 represent mode + * - bit 17 represent comphy indication of clock source + * - bit 20~18 represents pcie width (in case of pcie comphy config.) + * - bit 21 represents the source of the request (Linux/Bootloader), + * (reguired only for PCIe!) + * - bit 31~22 reserved + */ + +#define COMPHY_INVERT_OFFSET 0 +#define COMPHY_INVERT_LEN 2 +#define COMPHY_INVERT_MASK COMPHY_MASK(COMPHY_INVERT_OFFSET, \ + COMPHY_INVERT_LEN) +#define COMPHY_SPEED_OFFSET (COMPHY_INVERT_OFFSET + COMPHY_INVERT_LEN) +#define COMPHY_SPEED_LEN 6 +#define COMPHY_SPEED_MASK COMPHY_MASK(COMPHY_SPEED_OFFSET, \ + COMPHY_SPEED_LEN) +#define COMPHY_UNIT_ID_OFFSET (COMPHY_SPEED_OFFSET + COMPHY_SPEED_LEN) +#define COMPHY_UNIT_ID_LEN 4 +#define COMPHY_UNIT_ID_MASK COMPHY_MASK(COMPHY_UNIT_ID_OFFSET, \ + COMPHY_UNIT_ID_LEN) +#define COMPHY_MODE_OFFSET (COMPHY_UNIT_ID_OFFSET + COMPHY_UNIT_ID_LEN) +#define COMPHY_MODE_LEN 5 +#define COMPHY_MODE_MASK COMPHY_MASK(COMPHY_MODE_OFFSET, COMPHY_MODE_LEN) +#define COMPHY_CLK_SRC_OFFSET (COMPHY_MODE_OFFSET + COMPHY_MODE_LEN) +#define COMPHY_CLK_SRC_LEN 1 +#define COMPHY_CLK_SRC_MASK COMPHY_MASK(COMPHY_CLK_SRC_OFFSET, \ + COMPHY_CLK_SRC_LEN) +#define COMPHY_PCI_WIDTH_OFFSET (COMPHY_CLK_SRC_OFFSET + COMPHY_CLK_SRC_LEN) +#define COMPHY_PCI_WIDTH_LEN 3 +#define COMPHY_PCI_WIDTH_MASK COMPHY_MASK(COMPHY_PCI_WIDTH_OFFSET, \ + COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_OFFSET \ + (COMPHY_PCI_WIDTH_OFFSET + COMPHY_PCI_WIDTH_LEN) +#define COMPHY_PCI_CALLER_LEN 1 +#define COMPHY_PCI_CALLER_MASK COMPHY_MASK(COMPHY_PCI_CALLER_OFFSET, \ + COMPHY_PCI_CALLER_LEN) + +#define COMPHY_MASK(offset, len) (((1 << (len)) - 1) << (offset)) + +/* Macro which extracts mode from lane description */ +#define COMPHY_GET_MODE(x) (((x) & COMPHY_MODE_MASK) >> \ + COMPHY_MODE_OFFSET) +/* Macro which extracts unit index from lane description */ +#define COMPHY_GET_ID(x) (((x) & COMPHY_UNIT_ID_MASK) >> \ + COMPHY_UNIT_ID_OFFSET) +/* Macro which extracts speed from lane description */ +#define COMPHY_GET_SPEED(x) (((x) & COMPHY_SPEED_MASK) >> \ + COMPHY_SPEED_OFFSET) +/* Macro which extracts clock source indication from lane description */ +#define COMPHY_GET_CLK_SRC(x) (((x) & COMPHY_CLK_SRC_MASK) >> \ + COMPHY_CLK_SRC_OFFSET) +/* Macro which extracts pcie width indication from lane description */ +#define COMPHY_GET_PCIE_WIDTH(x) (((x) & COMPHY_PCI_WIDTH_MASK) >> \ + COMPHY_PCI_WIDTH_OFFSET) + +/* Macro which extracts the caller for pcie power on from lane description */ +#define COMPHY_GET_CALLER(x) (((x) & COMPHY_PCI_CALLER_MASK) >> \ + COMPHY_PCI_CALLER_OFFSET) + +/* Macro which extracts the polarity invert from lane description */ +#define COMPHY_GET_POLARITY_INVERT(x) (((x) & COMPHY_INVERT_MASK) >> \ + COMPHY_INVERT_OFFSET) + + +#define COMPHY_SATA_MODE 0x1 +#define COMPHY_SGMII_MODE 0x2 /* SGMII 1G */ +#define COMPHY_2500BASEX_MODE 0x3 /* 2500Base-X */ +#define COMPHY_USB3H_MODE 0x4 +#define COMPHY_USB3D_MODE 0x5 +#define COMPHY_PCIE_MODE 0x6 +#define COMPHY_RXAUI_MODE 0x7 +#define COMPHY_XFI_MODE 0x8 +#define COMPHY_SFI_MODE 0x9 +#define COMPHY_USB3_MODE 0xa +#define COMPHY_AP_MODE 0xb + +#define COMPHY_UNUSED 0xFFFFFFFF + +/* Polarity invert macro */ +#define COMPHY_POLARITY_NO_INVERT 0 +#define COMPHY_POLARITY_TXD_INVERT 1 +#define COMPHY_POLARITY_RXD_INVERT 2 +#define COMPHY_POLARITY_ALL_INVERT (COMPHY_POLARITY_TXD_INVERT | \ + COMPHY_POLARITY_RXD_INVERT) + +enum reg_width_type { + REG_16BIT = 0, + REG_32BIT, +}; + +enum { + COMPHY_LANE0 = 0, + COMPHY_LANE1, + COMPHY_LANE2, + COMPHY_LANE3, + COMPHY_LANE4, + COMPHY_LANE5, + COMPHY_LANE_MAX, +}; + +static inline uint32_t polling_with_timeout(uintptr_t addr, uint32_t val, + uint32_t mask, + uint32_t usec_timeout, + enum reg_width_type type) +{ + uint32_t data; + + do { + udelay(1); + if (type == REG_16BIT) + data = mmio_read_16(addr) & mask; + else + data = mmio_read_32(addr) & mask; + } while (data != val && --usec_timeout > 0); + + if (usec_timeout == 0) + return data; + + return 0; +} + +static inline void reg_set(uintptr_t addr, uint32_t data, uint32_t mask) +{ + debug(": WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ", + addr, data, mask); + debug("old value = 0x%x ==> ", mmio_read_32(addr)); + mmio_clrsetbits_32(addr, mask, data & mask); + + debug("new val 0x%x\n", mmio_read_32(addr)); +} + +static inline void __unused reg_set16(uintptr_t addr, uint16_t data, + uint16_t mask) +{ + + debug(": WR to addr = 0x%lx, data = 0x%x (mask = 0x%x) - ", + addr, data, mask); + debug("old value = 0x%x ==> ", mmio_read_16(addr)); + mmio_clrsetbits_16(addr, mask, data & mask); + + debug("new val 0x%x\n", mmio_read_16(addr)); +} + +#endif /* PHY_COMPHY_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c new file mode 100644 index 0000000..fa9fe41 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c @@ -0,0 +1,2528 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Marvell CP110 SoC COMPHY unit driver */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include "mvebu.h" +#include "comphy-cp110.h" +#include "phy-comphy-cp110.h" +#include "phy-comphy-common.h" + +#if __has_include("phy-porting-layer.h") +#include "phy-porting-layer.h" +#else +#include "phy-default-porting-layer.h" +#endif + +/* COMPHY speed macro */ +#define COMPHY_SPEED_1_25G 0 /* SGMII 1G */ +#define COMPHY_SPEED_2_5G 1 +#define COMPHY_SPEED_3_125G 2 /* 2500Base-X */ +#define COMPHY_SPEED_5G 3 +#define COMPHY_SPEED_5_15625G 4 /* XFI 5G */ +#define COMPHY_SPEED_6G 5 +#define COMPHY_SPEED_10_3125G 6 /* XFI 10G */ +#define COMPHY_SPEED_MAX 0x3F +/* The default speed for IO with fixed known speed */ +#define COMPHY_SPEED_DEFAULT COMPHY_SPEED_MAX + +/* Commands for comphy driver */ +#define COMPHY_COMMAND_DIGITAL_PWR_OFF 0x00000001 +#define COMPHY_COMMAND_DIGITAL_PWR_ON 0x00000002 + +#define COMPHY_PIPE_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x120000) + +/* System controller registers */ +#define PCIE_MAC_RESET_MASK_PORT0 BIT(13) +#define PCIE_MAC_RESET_MASK_PORT1 BIT(11) +#define PCIE_MAC_RESET_MASK_PORT2 BIT(12) +#define SYS_CTRL_UINIT_SOFT_RESET_REG 0x268 +#define SYS_CTRL_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + 0x440000) + +/* DFX register spaces */ +#define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET (30) +#define SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK (0x1UL << \ + SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET) +#define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET (31) +#define SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK (0x1UL << \ + SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET) +#define SAR_STATUS_0_REG 0x40600 +#define DFX_FROM_COMPHY_ADDR(x) ((x & ~0xffffff) + DFX_BASE) +/* Common Phy training */ +#define COMPHY_TRX_TRAIN_COMPHY_OFFS 0x1000 +#define COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE 0x1 +#define COMPHY_TRX_RELATIVE_ADDR(comphy_index) (comphy_train_base + \ + (comphy_index) * COMPHY_TRX_TRAIN_COMPHY_OFFS) + +/* The same Units Soft Reset Config register are accessed in all PCIe ports + * initialization, so a spin lock is defined in case when more than 1 CPUs + * resets PCIe MAC and need to access the register in the same time. The spin + * lock is shared by all CP110 units. + */ +spinlock_t cp110_mac_reset_lock; + +/* These values come from the PCI Express Spec */ +enum pcie_link_width { + PCIE_LNK_WIDTH_RESRV = 0x00, + PCIE_LNK_X1 = 0x01, + PCIE_LNK_X2 = 0x02, + PCIE_LNK_X4 = 0x04, + PCIE_LNK_X8 = 0x08, + PCIE_LNK_X12 = 0x0C, + PCIE_LNK_X16 = 0x10, + PCIE_LNK_X32 = 0x20, + PCIE_LNK_WIDTH_UNKNOWN = 0xFF, +}; + +_Bool rx_trainng_done[AP_NUM][CP_NUM][MAX_LANE_NR] = {0}; + +static void mvebu_cp110_get_ap_and_cp_nr(uint8_t *ap_nr, uint8_t *cp_nr, + uint64_t comphy_base) +{ +#if (AP_NUM == 1) + *ap_nr = 0; +#else + *ap_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(0)) / + AP_IO_OFFSET); +#endif + + *cp_nr = (((comphy_base & ~0xffffff) - MVEBU_AP_IO_BASE(*ap_nr)) / + MVEBU_CP_OFFSET); + + debug("cp_base 0x%" PRIx64 ", ap_io_base 0x%lx, cp_offset 0x%lx\n", + comphy_base, (unsigned long)MVEBU_AP_IO_BASE(*ap_nr), + (unsigned long)MVEBU_CP_OFFSET); +} + +/* Clear PIPE selector - avoid collision with previous configuration */ +static void mvebu_cp110_comphy_clr_pipe_selector(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t reg, mask, field; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET); + field = reg & mask; + + if (field) { + reg &= ~mask; + mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, + reg); + } +} + +/* Clear PHY selector - avoid collision with previous configuration */ +static void mvebu_cp110_comphy_clr_phy_selector(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t reg, mask, field; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET); + field = reg & mask; + + /* Clear comphy selector - if it was already configured. + * (might be that this comphy was configured as PCIe/USB, + * in such case, no need to clear comphy selector because PCIe/USB + * are controlled by hpipe selector). + */ + if (field) { + reg &= ~mask; + mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, + reg); + } +} + +/* PHY selector configures SATA and Network modes */ +static void mvebu_cp110_comphy_set_phy_selector(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uint32_t reg, mask; + uint32_t comphy_offset = + COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + int mode; + + /* If phy selector is used the pipe selector should be marked as + * unconnected. + */ + mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index); + + /* Comphy mode (compound of the IO mode and id). Here, only the IO mode + * is required to distinguish between SATA and network modes. + */ + mode = COMPHY_GET_MODE(comphy_mode); + + mask = COMMON_SELECTOR_COMPHY_MASK << comphy_offset; + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET); + reg &= ~mask; + + /* SATA port 0/1 require the same configuration */ + if (mode == COMPHY_SATA_MODE) { + /* SATA selector values is always 4 */ + reg |= COMMON_SELECTOR_COMPHYN_SATA << comphy_offset; + } else { + switch (comphy_index) { + case(0): + case(1): + case(2): + /* For comphy 0,1, and 2: + * Network selector value is always 1. + */ + reg |= COMMON_SELECTOR_COMPHY0_1_2_NETWORK << + comphy_offset; + break; + case(3): + /* For comphy 3: + * 0x1 = RXAUI_Lane1 + * 0x2 = SGMII/Base-X Port1 + */ + if (mode == COMPHY_RXAUI_MODE) + reg |= COMMON_SELECTOR_COMPHY3_RXAUI << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY3_SGMII << + comphy_offset; + break; + case(4): + /* For comphy 4: + * 0x1 = SGMII/Base-X Port1, XFI1/SFI1 + * 0x2 = SGMII/Base-X Port0: XFI0/SFI0, RXAUI_Lane0 + * + * We want to check if SGMII1 is the + * requested mode in order to determine which value + * should be set (all other modes use the same value) + * so we need to strip the mode, and check the ID + * because we might handle SGMII0 too. + */ + /* TODO: need to distinguish between CP110 and CP115 + * as SFI1/XFI1 available only for CP115. + */ + if ((mode == COMPHY_SGMII_MODE || + mode == COMPHY_2500BASEX_MODE || + mode == COMPHY_SFI_MODE || + mode == COMPHY_XFI_MODE || + mode == COMPHY_AP_MODE) + && COMPHY_GET_ID(comphy_mode) == 1) + reg |= COMMON_SELECTOR_COMPHY4_PORT1 << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY4_ALL_OTHERS << + comphy_offset; + break; + case(5): + /* For comphy 5: + * 0x1 = SGMII/Base-X Port2 + * 0x2 = RXAUI Lane1 + */ + if (mode == COMPHY_RXAUI_MODE) + reg |= COMMON_SELECTOR_COMPHY5_RXAUI << + comphy_offset; + else + reg |= COMMON_SELECTOR_COMPHY5_SGMII << + comphy_offset; + break; + } + } + + mmio_write_32(comphy_base + COMMON_SELECTOR_PHY_REG_OFFSET, reg); +} + +/* PIPE selector configures for PCIe, USB 3.0 Host, and USB 3.0 Device mode */ +static void mvebu_cp110_comphy_set_pipe_selector(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uint32_t reg; + uint32_t shift = COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index; + int mode = COMPHY_GET_MODE(comphy_mode); + uint32_t mask = COMMON_SELECTOR_COMPHY_MASK << shift; + uint32_t pipe_sel = 0x0; + + /* If pipe selector is used the phy selector should be marked as + * unconnected. + */ + mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index); + + reg = mmio_read_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET); + reg &= ~mask; + + switch (mode) { + case (COMPHY_PCIE_MODE): + /* For lanes support PCIE, selector value are all same */ + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_PCIE; + break; + + case (COMPHY_USB3H_MODE): + /* Only lane 1-4 support USB host, selector value is same */ + if (comphy_index == COMPHY_LANE0 || + comphy_index == COMPHY_LANE5) + ERROR("COMPHY[%d] mode[%d] is invalid\n", + comphy_index, mode); + else + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBH; + break; + + case (COMPHY_USB3D_MODE): + /* Lane 1 and 4 support USB device, selector value is same */ + if (comphy_index == COMPHY_LANE1 || + comphy_index == COMPHY_LANE4) + pipe_sel = COMMON_SELECTOR_PIPE_COMPHY_USBD; + else + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, + mode); + break; + + default: + ERROR("COMPHY[%d] mode[%d] is invalid\n", comphy_index, mode); + break; + } + + mmio_write_32(comphy_base + COMMON_SELECTOR_PIPE_REG_OFFSET, reg | + (pipe_sel << shift)); +} + +int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, uint8_t comphy_index) +{ + uintptr_t sd_ip_addr, addr; + uint32_t mask, data; + int ret = 0; + + debug_enter(); + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_TX_MASK & + SD_EXTERNAL_STATUS0_PLL_RX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, REG_32BIT); + if (data != 0) { + if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK) + ERROR("RX PLL is not locked\n"); + if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK) + ERROR("TX PLL is not locked\n"); + + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +static void mvebu_cp110_polarity_invert(uintptr_t addr, uint8_t phy_polarity_invert) +{ + uint32_t mask, data; + + /* Set RX / TX polarity */ + data = mask = 0x0U; + if ((phy_polarity_invert & COMPHY_POLARITY_TXD_INVERT) != 0) { + data |= (1 << HPIPE_SYNC_PATTERN_TXD_INV_OFFSET); + mask |= HPIPE_SYNC_PATTERN_TXD_INV_MASK; + debug("%s: inverting TX polarity\n", __func__); + } + + if ((phy_polarity_invert & COMPHY_POLARITY_RXD_INVERT) != 0) { + data |= (1 << HPIPE_SYNC_PATTERN_RXD_INV_OFFSET); + mask |= HPIPE_SYNC_PATTERN_RXD_INV_MASK; + debug("%s: inverting RX polarity\n", __func__); + } + + reg_set(addr, data, mask); +} + +static int mvebu_cp110_comphy_sata_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr, phy_polarity_invert; + int ret = 0; + + debug_enter(); + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + const struct sata_params *sata_static_values = + &sata_static_values_tab[ap_nr][cp_nr][comphy_index]; + + phy_polarity_invert = sata_static_values->polarity_invert; + + /* configure phy selector for SATA */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, + comphy_index, comphy_mode); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + debug(" add hpipe 0x%lx, sd 0x%lx, comphy 0x%lx\n", + hpipe_addr, sd_ip_addr, comphy_addr); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Set select data width 40Bit - SATA mode only */ + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, + 0x1 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET, + COMMON_PHY_CFG6_IF_40_SEL_MASK); + + /* release from hard reset in SD external */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + debug("stage: Comphy configuration\n"); + /* Start comphy Configuration */ + /* Set reference clock to comes from group 1 - choose 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Reference frequency select set 1 (for SATA = 25Mhz) */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* PHY mode select (set SATA = 0x0 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x0 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set max PHY generation setting - 6Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 40Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x2 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + + debug("stage: Analog parameters from ETP(HW)\n"); + /* G1 settings */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = sata_static_values->g1_rx_selmupi << + HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= sata_static_values->g1_rx_selmupf << + HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; + data |= sata_static_values->g1_rx_selmufi << + HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; + data |= sata_static_values->g1_rx_selmuff << + HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + + mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data = 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= 0x2 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* G2 settings */ + mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; + data = sata_static_values->g2_rx_selmupi << + HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK; + data |= sata_static_values->g2_rx_selmupf << + HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; + data |= sata_static_values->g2_rx_selmufi << + HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFF_MASK; + data |= sata_static_values->g2_rx_selmuff << + HPIPE_G2_SET_1_G2_RX_SELMUFF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_MASK; + data |= 0x1 << HPIPE_G2_SET_1_G2_RX_DIGCK_DIV_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); + + /* G3 settings */ + mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; + data = sata_static_values->g3_rx_selmupi << + HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; + data |= sata_static_values->g3_rx_selmupf << + HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUFI_MASK; + data |= sata_static_values->g3_rx_selmufi << + HPIPE_G3_SET_1_G3_RX_SELMUFI_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_SELMUFF_MASK; + data |= sata_static_values->g3_rx_selmuff << + HPIPE_G3_SET_1_G3_RX_SELMUFF_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G3_SET_1_G3_RX_DFE_EN_OFFSET; + mask |= HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_MASK; + data |= 0x2 << HPIPE_G3_SET_1_G3_RX_DIGCK_DIV_OFFSET; + mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); + + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_SQ_DET_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_SQ_DET_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_SQ_PLOOP_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLAMPING_SEL_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLAMPING_SEL_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_INTPCLK_DIV_FORCE_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_OFFSET; + mask |= HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_MASK; + data |= 0x1 << HPIPE_PWR_CTR_DTL_CLK_MODE_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Trigger sampler enable pulse */ + mask = HPIPE_SMAPLER_MASK; + data = 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + mask = HPIPE_SMAPLER_MASK; + data = 0x0 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + + /* VDD Calibration Control 3 */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x10 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + /* DFE Resolution Control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* DFE F3-F5 Coefficient Control */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* G3 Setting 3 */ + mask = HPIPE_G3_FFE_CAP_SEL_MASK; + data = sata_static_values->g3_ffe_cap_sel << + HPIPE_G3_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G3_FFE_RES_SEL_MASK; + data |= sata_static_values->g3_ffe_res_sel << + HPIPE_G3_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G3_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G3_FFE_SETTING_FORCE_OFFSET; + mask |= HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; + data |= 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); + + /* G3 Setting 4 */ + mask = HPIPE_G3_DFE_RES_MASK; + data = sata_static_values->g3_dfe_res << HPIPE_G3_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); + + /* Offset Phase Control */ + mask = HPIPE_OS_PH_OFFSET_MASK; + data = sata_static_values->align90 << HPIPE_OS_PH_OFFSET_OFFSET; + mask |= HPIPE_OS_PH_OFFSET_FORCE_MASK; + data |= 0x1 << HPIPE_OS_PH_OFFSET_FORCE_OFFSET; + mask |= HPIPE_OS_PH_VALID_MASK; + data |= 0x0 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + mask = HPIPE_OS_PH_VALID_MASK; + data = 0x1 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + mask = HPIPE_OS_PH_VALID_MASK; + data = 0x0 << HPIPE_OS_PH_VALID_OFFSET; + reg_set(hpipe_addr + HPIPE_PHASE_CONTROL_REG, data, mask); + + /* Set G1 TX amplitude and TX post emphasis value */ + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = sata_static_values->g1_amp << HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; + data |= sata_static_values->g1_tx_amp_adj << + HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= sata_static_values->g1_emph << + HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; + data |= sata_static_values->g1_emph_en << + HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + + /* Set G1 emph */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data = sata_static_values->g1_tx_emph_en << + HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data |= sata_static_values->g1_tx_emph << + HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + + /* Set G2 TX amplitude and TX post emphasis value */ + mask = HPIPE_G2_SET_0_G2_TX_AMP_MASK; + data = sata_static_values->g2_amp << HPIPE_G2_SET_0_G2_TX_AMP_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_AMP_ADJ_MASK; + data |= sata_static_values->g2_tx_amp_adj << + HPIPE_G2_SET_0_G2_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_MASK; + data |= sata_static_values->g2_emph << + HPIPE_G2_SET_0_G2_TX_EMPH1_OFFSET; + mask |= HPIPE_G2_SET_0_G2_TX_EMPH1_EN_MASK; + data |= sata_static_values->g2_emph_en << + HPIPE_G2_SET_0_G2_TX_EMPH1_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_0_REG, data, mask); + + /* Set G2 emph */ + mask = HPIPE_G2_SET_2_G2_TX_EMPH0_EN_MASK; + data = sata_static_values->g2_tx_emph_en << + HPIPE_G2_SET_2_G2_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G2_SET_2_G2_TX_EMPH0_MASK; + data |= sata_static_values->g2_tx_emph << + HPIPE_G2_SET_2_G2_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask); + + /* Set G3 TX amplitude and TX post emphasis value */ + mask = HPIPE_G3_SET_0_G3_TX_AMP_MASK; + data = sata_static_values->g3_amp << HPIPE_G3_SET_0_G3_TX_AMP_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_AMP_ADJ_MASK; + data |= sata_static_values->g3_tx_amp_adj << + HPIPE_G3_SET_0_G3_TX_AMP_ADJ_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_MASK; + data |= sata_static_values->g3_emph << + HPIPE_G3_SET_0_G3_TX_EMPH1_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_EMPH1_EN_MASK; + data |= sata_static_values->g3_emph_en << + HPIPE_G3_SET_0_G3_TX_EMPH1_EN_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_MASK; + data |= 0x4 << HPIPE_G3_SET_0_G3_TX_SLEW_RATE_SEL_OFFSET; + mask |= HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_0_G3_TX_SLEW_CTRL_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_0_REG, data, mask); + + /* Set G3 emph */ + mask = HPIPE_G3_SET_2_G3_TX_EMPH0_EN_MASK; + data = sata_static_values->g3_tx_emph_en << + HPIPE_G3_SET_2_G3_TX_EMPH0_EN_OFFSET; + mask |= HPIPE_G3_SET_2_G3_TX_EMPH0_MASK; + data |= sata_static_values->g3_tx_emph << + HPIPE_G3_SET_2_G3_TX_EMPH0_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_2_REG, data, mask); + + /* SERDES External Configuration 2 register */ + mask = SD_EXTERNAL_CONFIG2_SSC_ENABLE_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_SSC_ENABLE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + + /* DFE reset sequence */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_RST_DFE_OFFSET, + HPIPE_PWR_CTR_RST_DFE_MASK); + + if (phy_polarity_invert != 0) + mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG, + phy_polarity_invert); + + /* SW reset for interrupt logic */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x1 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + reg_set(hpipe_addr + HPIPE_PWR_CTR_REG, + 0x0 << HPIPE_PWR_CTR_SFT_RST_OFFSET, + HPIPE_PWR_CTR_SFT_RST_MASK); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_sgmii_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data, sgmii_speed = COMPHY_GET_SPEED(comphy_mode); + int ret = 0; + + debug_enter(); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for SGMII */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + /* Confiugre the lane */ + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + + if (sgmii_speed == COMPHY_SPEED_1_25G) { + /* SGMII 1G, SerDes speed 1.25G */ + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x6 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else if (sgmii_speed == COMPHY_SPEED_3_125G) { + /* 2500Base-X, SerDes speed 3.125G */ + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + data |= 0x8 << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + } else { + /* Other rates are not supported */ + ERROR("unsupported SGMII speed on comphy%d\n", comphy_index); + return -EINVAL; + } + + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 1 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* Set hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Release hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Make sure that 40 data bits is disabled + * This bit is not cleared by reset + */ + mask = COMMON_PHY_CFG6_IF_40_SEL_MASK; + data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_REFCLK_SEL_MASK; + data = 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x0 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Set analog parameters from ETP(HW) - for now use the default data */ + debug("stage: Analog parameters from ETP(HW)\n"); + + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0x1 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + ret = mvebu_cp110_comphy_is_pll_locked(comphy_base, comphy_index); + if (ret) + return ret; + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + ERROR("RX init failed\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_xfi_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode, + uint64_t comphy_train_base) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data, speed = COMPHY_GET_SPEED(comphy_mode); + int ret = 0; + uint8_t ap_nr, cp_nr; + + debug_enter(); + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) { + debug("Skip %s for comphy[%d][%d][%d], due to rx training\n", + __func__, ap_nr, cp_nr, comphy_index); + return 0; + } + + const struct xfi_params *xfi_static_values = + &xfi_static_values_tab[ap_nr][cp_nr][comphy_index]; + + debug("%s: the ap_nr = %d, cp_nr = %d, comphy_index %d\n", + __func__, ap_nr, cp_nr, comphy_index); + + debug("g1_ffe_cap_sel= 0x%x, g1_ffe_res_sel= 0x%x, g1_dfe_res= 0x%x\n", + xfi_static_values->g1_ffe_cap_sel, + xfi_static_values->g1_ffe_res_sel, + xfi_static_values->g1_dfe_res); + + if (!xfi_static_values->valid) { + ERROR("[ap%d][cp[%d][comphy:%d]: Has no valid static params\n", + ap_nr, cp_nr, comphy_index); + ERROR("[ap%d][cp[%d][comphy:%d]: porting layer needs update\n", + ap_nr, cp_nr, comphy_index); + return -EINVAL; + } + + if ((speed != COMPHY_SPEED_5_15625G) && + (speed != COMPHY_SPEED_10_3125G) && + (speed != COMPHY_SPEED_DEFAULT)) { + ERROR("comphy:%d: unsupported sfi/xfi speed\n", comphy_index); + return -EINVAL; + } + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for XFI/SFI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Make sure that 40 data bits is disabled + * This bit is not cleared by reset + */ + mask = COMMON_PHY_CFG6_IF_40_SEL_MASK; + data = 0 << COMMON_PHY_CFG6_IF_40_SEL_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG6_REG, data, mask); + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xE << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_TX_IDLE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_TX_IDLE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* + * Erratum IPCE_COMPHY-1353: toggle TX_IDLE bit in + * addition to the PHY reset + */ + mask = SD_EXTERNAL_CONFIG1_TX_IDLE_MASK; + data = 0x0U; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + mask = HPIPE_MISC_ICP_FORCE_MASK; + data = (speed == COMPHY_SPEED_5_15625G) ? + (0x0 << HPIPE_MISC_ICP_FORCE_OFFSET) : + (0x1 << HPIPE_MISC_ICP_FORCE_OFFSET); + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + mask = HPIPE_LOOPBACK_SEL_MASK; + data = 0x1 << HPIPE_LOOPBACK_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, data, mask); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x1 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Transmitter/Receiver Speed Divider Force */ + if (speed == COMPHY_SPEED_5_15625G) { + mask = HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_MASK; + data = 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_RX_SPD_DIV_FORCE_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_OFFSET; + mask |= HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_MASK; + data |= 1 << HPIPE_SPD_DIV_FORCE_TX_SPD_DIV_FORCE_OFFSET; + } else { + mask = HPIPE_TXDIGCK_DIV_FORCE_MASK; + data = 0x1 << HPIPE_TXDIGCK_DIV_FORCE_OFFSET; + } + reg_set(hpipe_addr + HPIPE_SPD_DIV_FORCE_REG, data, mask); + + /* Set analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + mask = SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, data, mask); + /* 0x7-DFE Resolution control */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + /* 0xd-G1_Setting_0 */ + if (speed == COMPHY_SPEED_5_15625G) { + mask = HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data = 0x6 << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + } else { + mask = HPIPE_G1_SET_0_G1_TX_AMP_MASK; + data = xfi_static_values->g1_amp << + HPIPE_G1_SET_0_G1_TX_AMP_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_MASK; + data |= xfi_static_values->g1_emph << + HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET; + + mask |= HPIPE_G1_SET_0_G1_TX_EMPH1_EN_MASK; + data |= xfi_static_values->g1_emph_en << + HPIPE_G1_SET_0_G1_TX_EMPH1_EN_OFFSET; + mask |= HPIPE_G1_SET_0_G1_TX_AMP_ADJ_MASK; + data |= xfi_static_values->g1_tx_amp_adj << + HPIPE_G1_SET_0_G1_TX_AMP_ADJ_OFFSET; + } + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, data, mask); + /* Genration 1 setting 2 (G1_Setting_2) */ + mask = HPIPE_G1_SET_2_G1_TX_EMPH0_MASK; + data = xfi_static_values->g1_tx_emph << + HPIPE_G1_SET_2_G1_TX_EMPH0_OFFSET; + mask |= HPIPE_G1_SET_2_G1_TX_EMPH0_EN_MASK; + data |= xfi_static_values->g1_tx_emph_en << + HPIPE_G1_SET_2_G1_TX_EMPH0_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_2_REG, data, mask); + /* Transmitter Slew Rate Control register (tx_reg1) */ + mask = HPIPE_TX_REG1_TX_EMPH_RES_MASK; + data = 0x3 << HPIPE_TX_REG1_TX_EMPH_RES_OFFSET; + mask |= HPIPE_TX_REG1_SLC_EN_MASK; + data |= 0x3f << HPIPE_TX_REG1_SLC_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_REG1_REG, data, mask); + /* Impedance Calibration Control register (cal_reg1) */ + mask = HPIPE_CAL_REG_1_EXT_TXIMP_MASK; + data = 0xe << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + mask |= HPIPE_CAL_REG_1_EXT_TXIMP_EN_MASK; + data |= 0x1 << HPIPE_CAL_REG_1_EXT_TXIMP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_CAL_REG1_REG, data, mask); + /* Generation 1 Setting 5 (g1_setting_5) */ + mask = HPIPE_G1_SETTING_5_G1_ICP_MASK; + data = 0 << HPIPE_CAL_REG_1_EXT_TXIMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTING_5_REG, data, mask); + + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + if (speed == COMPHY_SPEED_5_15625G) { + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + } else { + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data |= xfi_static_values->g1_rx_selmupi << + HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= xfi_static_values->g1_rx_selmupf << + HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFI_MASK; + data |= xfi_static_values->g1_rx_selmufi << + HPIPE_G1_SET_1_G1_RX_SELMUFI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUFF_MASK; + data |= xfi_static_values->g1_rx_selmuff << + HPIPE_G1_SET_1_G1_RX_SELMUFF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_MASK; + data |= 0x3 << HPIPE_G1_SET_1_G1_RX_DIGCK_DIV_OFFSET; + } + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + /* Genration 1 setting 3 (G1_Setting_3) */ + mask = HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_3_G1_FBCK_SEL_OFFSET; + if (speed == COMPHY_SPEED_5_15625G) { + /* Force FFE (Feed Forward Equalization) to 5G */ + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data |= 0xf << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= 0x4 << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + } else { + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data |= xfi_static_values->g1_ffe_cap_sel << + HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data |= xfi_static_values->g1_ffe_res_sel << + HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + mask |= HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data |= 0x1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Use the value from CAL_OS_PH_EXT */ + mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK; + data = 1 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET; + reg_set(hpipe_addr + + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Update align90 */ + mask = HPIPE_CAL_OS_PH_EXT_MASK; + data = xfi_static_values->align90 << HPIPE_CAL_OS_PH_EXT_OFFSET; + reg_set(hpipe_addr + + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Force DFE resolution (use gen table value) */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* 0x111-G1 DFE_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = xfi_static_values->g1_dfe_res << + HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + } + + /* Connfigure RX training timer */ + mask = HPIPE_RX_TRAIN_TIMER_MASK; + data = 0x13 << HPIPE_RX_TRAIN_TIMER_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); + + /* Enable TX train peak to peak hold */ + mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; + data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); + + /* Configure TX preset index */ + mask = HPIPE_TX_PRESET_INDEX_MASK; + data = 0x2 << HPIPE_TX_PRESET_INDEX_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_PRESET_INDEX_REG, data, mask); + + /* Disable pattern lock lost timeout */ + mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; + data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); + + /* Configure TX training pattern and TX training 16bit auto */ + mask = HPIPE_TX_TRAIN_16BIT_AUTO_EN_MASK; + data = 0x1 << HPIPE_TX_TRAIN_16BIT_AUTO_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_PAT_SEL_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_PAT_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); + + /* Configure Training patten number */ + mask = HPIPE_TRAIN_PAT_NUM_MASK; + data = 0x88 << HPIPE_TRAIN_PAT_NUM_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_0_REG, data, mask); + + /* Configure differencial manchester encoter to ethernet mode */ + mask = HPIPE_DME_ETHERNET_MODE_MASK; + data = 0x1 << HPIPE_DME_ETHERNET_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_DME_REG, data, mask); + + /* Configure VDD Continuous Calibration */ + mask = HPIPE_CAL_VDD_CONT_MODE_MASK; + data = 0x1 << HPIPE_CAL_VDD_CONT_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_0_REG, data, mask); + + /* Trigger sampler enable pulse (by toggleing the bit) */ + mask = HPIPE_RX_SAMPLER_OS_GAIN_MASK; + data = 0x3 << HPIPE_RX_SAMPLER_OS_GAIN_OFFSET; + mask |= HPIPE_SMAPLER_MASK; + data |= 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + mask = HPIPE_SMAPLER_MASK; + data = 0x0 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + + /* Set External RX Regulator Control */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x1A << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, REG_32BIT); + if (data != 0) { + if (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK) + ERROR("RX PLL is not locked\n"); + if (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK) + ERROR("TX PLL is not locked\n"); + + ret = -ETIMEDOUT; + } + + /* RX init */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + ERROR("RX init failed\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Force rx training on 10G port */ + data = mmio_read_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index)); + data |= COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE; + mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data); + mdelay(200); + data &= ~COMPHY_TRX_TRAIN_RX_TRAIN_ENABLE; + mmio_write_32(COMPHY_TRX_RELATIVE_ADDR(comphy_index), data); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_pcie_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + int ret = 0; + uint32_t reg, mask, data, pcie_width; + uint32_t clk_dir; + uintptr_t hpipe_addr, comphy_addr, addr; + _Bool clk_src = COMPHY_GET_CLK_SRC(comphy_mode); + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); + + /* In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later). + * This means that power on can be executed only once, so let's + * mark if the caller is bootloader or Linux. + * If bootloader -> run power on. + * If Linux -> exit. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-on by Linux. + */ + if (!called_from_uboot) + return ret; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + pcie_width = COMPHY_GET_PCIE_WIDTH(comphy_mode); + + debug_enter(); + + spin_lock(&cp110_mac_reset_lock); + + reg = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG); + switch (comphy_index) { + case COMPHY_LANE0: + reg |= PCIE_MAC_RESET_MASK_PORT0; + break; + case COMPHY_LANE4: + reg |= PCIE_MAC_RESET_MASK_PORT1; + break; + case COMPHY_LANE5: + reg |= PCIE_MAC_RESET_MASK_PORT2; + break; + } + + mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG, reg); + spin_unlock(&cp110_mac_reset_lock); + + /* Configure PIPE selector for PCIE */ + mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index, + comphy_mode); + + /* + * Read SAR (Sample-At-Reset) configuration for the PCIe clock + * direction. + * + * SerDes Lane 4/5 got the PCIe ref-clock #1, + * and SerDes Lane 0 got PCIe ref-clock #0 + */ + reg = mmio_read_32(DFX_FROM_COMPHY_ADDR(comphy_base) + + SAR_STATUS_0_REG); + if (comphy_index == COMPHY_LANE4 || comphy_index == COMPHY_LANE5) + clk_dir = (reg & SAR_RST_PCIE1_CLOCK_CONFIG_CP0_MASK) >> + SAR_RST_PCIE1_CLOCK_CONFIG_CP0_OFFSET; + else + clk_dir = (reg & SAR_RST_PCIE0_CLOCK_CONFIG_CP0_MASK) >> + SAR_RST_PCIE0_CLOCK_CONFIG_CP0_OFFSET; + + debug("On lane %d\n", comphy_index); + debug("PCIe clock direction = %x\n", clk_dir); + debug("PCIe Width = %d\n", pcie_width); + + /* enable PCIe X4 and X2 */ + if (comphy_index == COMPHY_LANE0) { + if (pcie_width == PCIE_LNK_X4) { + data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X4_EN_OFFSET; + mask = COMMON_PHY_SD_CTRL1_PCIE_X4_EN_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + data, mask); + } else if (pcie_width == PCIE_LNK_X2) { + data = 0x1 << COMMON_PHY_SD_CTRL1_PCIE_X2_EN_OFFSET; + mask = COMMON_PHY_SD_CTRL1_PCIE_X2_EN_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask); + } + } + + /* If PCIe clock is output and clock source from SerDes lane 5, + * need to configure the clock-source MUX. + * By default, the clock source is from lane 4 + */ + if (clk_dir && clk_src && (comphy_index == COMPHY_LANE5)) { + data = DFX_DEV_GEN_PCIE_CLK_SRC_MUX << + DFX_DEV_GEN_PCIE_CLK_SRC_OFFSET; + mask = DFX_DEV_GEN_PCIE_CLK_SRC_MASK; + reg_set(DFX_FROM_COMPHY_ADDR(comphy_base) + + DFX_DEV_GEN_CTRL12_REG, data, mask); + } + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x0 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x1 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + data = 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET; + mask = HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK; + if (pcie_width != PCIE_LNK_X1) { + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SEL_MASK; + data |= 0x1 << HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_OFFSET; + mask |= HPIPE_CLK_SRC_LO_BUNDLE_PERIOD_SCALE_MASK; + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, data, mask); + + /* Set PIPE mode interface to PCIe3 - 0x1 & set lane order */ + data = 0x1 << HPIPE_CLK_SRC_HI_MODE_PIPE_OFFSET; + mask = HPIPE_CLK_SRC_HI_MODE_PIPE_MASK; + if (pcie_width != PCIE_LNK_X1) { + mask |= HPIPE_CLK_SRC_HI_LANE_STRT_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_MASTER_MASK; + mask |= HPIPE_CLK_SRC_HI_LANE_BREAK_MASK; + if (comphy_index == 0) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_STRT_OFFSET; + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_MASTER_OFFSET; + } else if (comphy_index == (pcie_width - 1)) { + data |= 0x1 << HPIPE_CLK_SRC_HI_LANE_BREAK_OFFSET; + } + } + reg_set(hpipe_addr + HPIPE_CLK_SRC_HI_REG, data, mask); + /* Config update polarity equalization */ + data = 0x1 << HPIPE_CFG_UPDATE_POLARITY_OFFSET; + mask = HPIPE_CFG_UPDATE_POLARITY_MASK; + reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG1_REG, data, mask); + /* Set PIPE version 4 to mode enable */ + data = 0x1 << HPIPE_DFE_CTRL_28_PIPE4_OFFSET; + mask = HPIPE_DFE_CTRL_28_PIPE4_MASK; + reg_set(hpipe_addr + HPIPE_DFE_CTRL_28_REG, data, mask); + /* TODO: check if pcie clock is output/input - for bringup use input*/ + /* Enable PIN clock 100M_125M */ + mask = 0; + data = 0; + /* Only if clock is output, configure the clock-source mux */ + if (clk_dir) { + mask |= HPIPE_MISC_CLK100M_125M_MASK; + data |= 0x1 << HPIPE_MISC_CLK100M_125M_OFFSET; + } + /* Set PIN_TXDCLK_2X Clock Freq. Selection for outputs 500MHz clock */ + mask |= HPIPE_MISC_TXDCLK_2X_MASK; + data |= 0x0 << HPIPE_MISC_TXDCLK_2X_OFFSET; + /* Enable 500MHz Clock */ + mask |= HPIPE_MISC_CLK500_EN_MASK; + data |= 0x1 << HPIPE_MISC_CLK500_EN_OFFSET; + if (clk_dir) { /* output */ + /* Set reference clock comes from group 1 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } else { + /* Set reference clock comes from group 2 */ + mask |= HPIPE_MISC_REFCLK_SEL_MASK; + data |= 0x1 << HPIPE_MISC_REFCLK_SEL_OFFSET; + } + mask |= HPIPE_MISC_ICP_FORCE_MASK; + data |= 0x1 << HPIPE_MISC_ICP_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_MISC_REG, data, mask); + if (clk_dir) { /* output */ + /* Set reference frequcency select - 0x2 for 25MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } else { + /* Set reference frequcency select - 0x0 for 100MHz*/ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x0 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + } + /* Set PHY mode to PCIe */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x3 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + + /* ref clock alignment */ + if (pcie_width != PCIE_LNK_X1) { + mask = HPIPE_LANE_ALIGN_OFF_MASK; + data = 0x0 << HPIPE_LANE_ALIGN_OFF_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_ALIGN_REG, data, mask); + } + + /* Set the amount of time spent in the LoZ state - set for 0x7 only if + * the PCIe clock is output + */ + if (clk_dir) + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + + /* Set Maximal PHY Generation Setting(8Gbps) */ + mask = HPIPE_INTERFACE_GEN_MAX_MASK; + data = 0x2 << HPIPE_INTERFACE_GEN_MAX_OFFSET; + /* Bypass frame detection and sync detection for RX DATA */ + mask |= HPIPE_INTERFACE_DET_BYPASS_MASK; + data |= 0x1 << HPIPE_INTERFACE_DET_BYPASS_OFFSET; + /* Set Link Train Mode (Tx training control pins are used) */ + mask |= HPIPE_INTERFACE_LINK_TRAIN_MASK; + data |= 0x1 << HPIPE_INTERFACE_LINK_TRAIN_OFFSET; + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, data, mask); + + /* Set Idle_sync enable */ + mask = HPIPE_PCIE_IDLE_SYNC_MASK; + data = 0x1 << HPIPE_PCIE_IDLE_SYNC_OFFSET; + /* Select bits for PCIE Gen3(32bit) */ + mask |= HPIPE_PCIE_SEL_BITS_MASK; + data |= 0x2 << HPIPE_PCIE_SEL_BITS_OFFSET; + reg_set(hpipe_addr + HPIPE_PCIE_REG0, data, mask); + + /* Enable Tx_adapt_g1 */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK; + data = 0x1 << HPIPE_TX_TRAIN_CTRL_G1_OFFSET; + /* Enable Tx_adapt_gn1 */ + mask |= HPIPE_TX_TRAIN_CTRL_GN1_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_CTRL_GN1_OFFSET; + /* Disable Tx_adapt_g0 */ + mask |= HPIPE_TX_TRAIN_CTRL_G0_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Set reg_tx_train_chk_init */ + mask = HPIPE_TX_TRAIN_CHK_INIT_MASK; + data = 0x0 << HPIPE_TX_TRAIN_CHK_INIT_OFFSET; + /* Enable TX_COE_FM_PIN_PCIE3_EN */ + mask |= HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_COE_FM_PIN_PCIE3_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_REG, data, mask); + + debug("stage: TRx training parameters\n"); + /* Set Preset sweep configurations */ + mask = HPIPE_TX_TX_STATUS_CHECK_MODE_MASK; + data = 0x1 << HPIPE_TX_STATUS_CHECK_MODE_OFFSET; + mask |= HPIPE_TX_NUM_OF_PRESET_MASK; + data |= 0x7 << HPIPE_TX_NUM_OF_PRESET_OFFSET; + mask |= HPIPE_TX_SWEEP_PRESET_EN_MASK; + data |= 0x1 << HPIPE_TX_SWEEP_PRESET_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_11_REG, data, mask); + + /* Tx train start configuration */ + mask = HPIPE_TX_TRAIN_START_SQ_EN_MASK; + data = 0x1 << HPIPE_TX_TRAIN_START_SQ_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_START_FRM_DET_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_DET_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_START_FRM_LOCK_EN_MASK; + data |= 0x0 << HPIPE_TX_TRAIN_START_FRM_LOCK_EN_OFFSET; + mask |= HPIPE_TX_TRAIN_WAIT_TIME_EN_MASK; + data |= 0x1 << HPIPE_TX_TRAIN_WAIT_TIME_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_5_REG, data, mask); + + /* Enable Tx train P2P */ + mask = HPIPE_TX_TRAIN_P2P_HOLD_MASK; + data = 0x1 << HPIPE_TX_TRAIN_P2P_HOLD_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_0_REG, data, mask); + + /* Configure Tx train timeout */ + mask = HPIPE_TRX_TRAIN_TIMER_MASK; + data = 0x17 << HPIPE_TRX_TRAIN_TIMER_OFFSET; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_4_REG, data, mask); + + /* Disable G0/G1/GN1 adaptation */ + mask = HPIPE_TX_TRAIN_CTRL_G1_MASK | HPIPE_TX_TRAIN_CTRL_GN1_MASK + | HPIPE_TX_TRAIN_CTRL_G0_OFFSET; + data = 0; + reg_set(hpipe_addr + HPIPE_TX_TRAIN_CTRL_REG, data, mask); + + /* Disable DTL frequency loop */ + mask = HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK; + data = 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, data, mask); + + /* Configure G3 DFE */ + mask = HPIPE_G3_DFE_RES_MASK; + data = 0x3 << HPIPE_G3_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_4_REG, data, mask); + + /* Use TX/RX training result for DFE */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* Configure initial and final coefficient value for receiver */ + mask = HPIPE_G3_SET_1_G3_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPI_OFFSET; + + mask |= HPIPE_G3_SET_1_G3_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G3_SET_1_G3_RX_SELMUPF_OFFSET; + + mask |= HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_MASK; + data |= 0x0 << HPIPE_G3_SET_1_G3_SAMPLER_INPAIRX2_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SET_1_REG, data, mask); + + /* Trigger sampler enable pulse */ + mask = HPIPE_SMAPLER_MASK; + data = 0x1 << HPIPE_SMAPLER_OFFSET; + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, data, mask); + udelay(5); + reg_set(hpipe_addr + HPIPE_SAMPLER_N_PROC_CALIB_CTRL_REG, 0, mask); + + /* FFE resistor tuning for different bandwidth */ + mask = HPIPE_G3_FFE_DEG_RES_LEVEL_MASK; + data = 0x1 << HPIPE_G3_FFE_DEG_RES_LEVEL_OFFSET; + mask |= HPIPE_G3_FFE_LOAD_RES_LEVEL_MASK; + data |= 0x3 << HPIPE_G3_FFE_LOAD_RES_LEVEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_3_REG, data, mask); + + /* Pattern lock lost timeout disable */ + mask = HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_MASK; + data = 0x0 << HPIPE_PATTERN_LOCK_LOST_TIMEOUT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_FRAME_DETECT_CTRL_3_REG, data, mask); + + /* Configure DFE adaptations */ + mask = HPIPE_CDR_RX_MAX_DFE_ADAPT_0_MASK; + data = 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_0_OFFSET; + mask |= HPIPE_CDR_RX_MAX_DFE_ADAPT_1_MASK; + data |= 0x0 << HPIPE_CDR_RX_MAX_DFE_ADAPT_1_OFFSET; + mask |= HPIPE_CDR_MAX_DFE_ADAPT_0_MASK; + data |= 0x0 << HPIPE_CDR_MAX_DFE_ADAPT_0_OFFSET; + mask |= HPIPE_CDR_MAX_DFE_ADAPT_1_MASK; + data |= 0x1 << HPIPE_CDR_MAX_DFE_ADAPT_1_OFFSET; + reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); + + mask = HPIPE_DFE_TX_MAX_DFE_ADAPT_MASK; + data = 0x0 << HPIPE_DFE_TX_MAX_DFE_ADAPT_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_CONTROL_REG, data, mask); + + /* Genration 2 setting 1*/ + mask = HPIPE_G2_SET_1_G2_RX_SELMUPI_MASK; + data = 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUPI_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G2_SET_1_G2_RX_SELMUPF_OFFSET; + mask |= HPIPE_G2_SET_1_G2_RX_SELMUFI_MASK; + data |= 0x0 << HPIPE_G2_SET_1_G2_RX_SELMUFI_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_1_REG, data, mask); + + /* DFE enable */ + mask = HPIPE_G2_DFE_RES_MASK; + data = 0x3 << HPIPE_G2_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SETTINGS_4_REG, data, mask); + + /* Configure DFE Resolution */ + mask = HPIPE_LANE_CFG4_DFE_EN_SEL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_EN_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + + /* VDD calibration control */ + mask = HPIPE_EXT_SELLV_RXSAMPL_MASK; + data = 0x16 << HPIPE_EXT_SELLV_RXSAMPL_OFFSET; + reg_set(hpipe_addr + HPIPE_VDD_CAL_CTRL_REG, data, mask); + + /* Set PLL Charge-pump Current Control */ + mask = HPIPE_G3_SETTING_5_G3_ICP_MASK; + data = 0x4 << HPIPE_G3_SETTING_5_G3_ICP_OFFSET; + reg_set(hpipe_addr + HPIPE_G3_SETTING_5_REG, data, mask); + + /* Set lane rqualization remote setting */ + mask = HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_MASK; + data = 0x1 << HPIPE_LANE_CFG_FOM_DIRN_OVERRIDE_OFFSET; + mask |= HPIPE_LANE_CFG_FOM_ONLY_MODE_MASK; + data |= 0x1 << HPIPE_LANE_CFG_FOM_ONLY_MODE_OFFFSET; + mask |= HPIPE_LANE_CFG_FOM_PRESET_VECTOR_MASK; + data |= 0x6 << HPIPE_LANE_CFG_FOM_PRESET_VECTOR_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_EQ_REMOTE_SETTING_REG, data, mask); + + mask = HPIPE_CFG_EQ_BUNDLE_DIS_MASK; + data = 0x1 << HPIPE_CFG_EQ_BUNDLE_DIS_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_EQ_CFG2_REG, data, mask); + + debug("stage: Comphy power up\n"); + + /* For PCIe X4 or X2: + * release from reset only after finish to configure all lanes + */ + if ((pcie_width == PCIE_LNK_X1) || (comphy_index == (pcie_width - 1))) { + uint32_t i, start_lane, end_lane; + + if (pcie_width != PCIE_LNK_X1) { + /* allows writing to all lanes in one write */ + data = 0x0; + if (pcie_width == PCIE_LNK_X2) + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK; + else if (pcie_width == PCIE_LNK_X4) + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK; + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, data, mask); + start_lane = 0; + end_lane = pcie_width; + + /* Release from PIPE soft reset + * For PCIe by4 or by2: + * release from soft reset all lanes - can't use + * read modify write + */ + reg_set(HPIPE_ADDR( + COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), 0) + + HPIPE_RST_CLK_CTRL_REG, 0x24, 0xffffffff); + } else { + start_lane = comphy_index; + end_lane = comphy_index + 1; + + /* Release from PIPE soft reset + * for PCIe by4 or by2: + * release from soft reset all lanes + */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + } + + if (pcie_width != PCIE_LNK_X1) { + /* disable writing to all lanes with one write */ + if (pcie_width == PCIE_LNK_X2) { + data = (COMPHY_LANE0 << + COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) | + (COMPHY_LANE1 << + COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET); + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_1_PORT_MASK; + } else if (pcie_width == PCIE_LNK_X4) { + data = (COMPHY_LANE0 << + COMMON_PHY_SD_CTRL1_COMPHY_0_PORT_OFFSET) | + (COMPHY_LANE1 << + COMMON_PHY_SD_CTRL1_COMPHY_1_PORT_OFFSET) | + (COMPHY_LANE2 << + COMMON_PHY_SD_CTRL1_COMPHY_2_PORT_OFFSET) | + (COMPHY_LANE3 << + COMMON_PHY_SD_CTRL1_COMPHY_3_PORT_OFFSET); + mask = COMMON_PHY_SD_CTRL1_COMPHY_0_3_PORT_MASK; + } + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + data, mask); + } + + debug("stage: Check PLL\n"); + /* Read lane status */ + for (i = start_lane; i < end_lane; i++) { + addr = HPIPE_ADDR( + COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), i) + + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, + PLL_LOCK_TIMEOUT, + REG_32BIT); + if (data) { + ERROR("Failed to lock PCIE PLL\n"); + ret = -ETIMEDOUT; + } + } + } + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_rxaui_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, sd_ip_addr, comphy_addr, addr; + uint32_t mask, data; + int ret = 0; + + debug_enter(); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + /* configure phy selector for RXAUI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + if (comphy_index == 2) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI0_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI0_MASK); + } + if (comphy_index == 4) { + reg_set(comphy_base + COMMON_PHY_SD_CTRL1, + 0x1 << COMMON_PHY_SD_CTRL1_RXAUI1_OFFSET, + COMMON_PHY_SD_CTRL1_RXAUI1_MASK); + } + + /* Select Baud Rate of Comphy And PD_PLL/Tx/Rx */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_MASK; + data |= 0xB << SD_EXTERNAL_CONFIG0_SD_PHY_GEN_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG0_HALF_BUS_MODE_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_MEDIA_MODE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_MEDIA_MODE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + /* release from hard reset */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* set reference clock */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Power and PLL Control */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x1 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x4 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Loopback register */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, HPIPE_LOOPBACK_SEL_MASK); + /* rx control 1 */ + mask = HPIPE_RX_CONTROL_1_RXCLK2X_SEL_MASK; + data = 0x1 << HPIPE_RX_CONTROL_1_RXCLK2X_SEL_OFFSET; + mask |= HPIPE_RX_CONTROL_1_CLK8T_EN_MASK; + data |= 0x1 << HPIPE_RX_CONTROL_1_CLK8T_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CONTROL_1_REG, data, mask); + /* DTL Control */ + reg_set(hpipe_addr + HPIPE_PWR_CTR_DTL_REG, + 0x0 << HPIPE_PWR_CTR_DTL_FLOOP_EN_OFFSET, + HPIPE_PWR_CTR_DTL_FLOOP_EN_MASK); + + /* Set analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* SERDES External Configuration 2 */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG2_REG, + 0x1 << SD_EXTERNAL_CONFIG2_PIN_DFE_EN_OFFSET, + SD_EXTERNAL_CONFIG2_PIN_DFE_EN_MASK); + /* 0x7-DFE Resolution control */ + reg_set(hpipe_addr + HPIPE_DFE_REG0, 0x1 << HPIPE_DFE_RES_FORCE_OFFSET, + HPIPE_DFE_RES_FORCE_MASK); + /* 0xd-G1_Setting_0 */ + reg_set(hpipe_addr + HPIPE_G1_SET_0_REG, + 0xd << HPIPE_G1_SET_0_G1_TX_EMPH1_OFFSET, + HPIPE_G1_SET_0_G1_TX_EMPH1_MASK); + /* 0xE-G1_Setting_1 */ + mask = HPIPE_G1_SET_1_G1_RX_SELMUPI_MASK; + data = 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPI_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_SELMUPF_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_SELMUPF_OFFSET; + mask |= HPIPE_G1_SET_1_G1_RX_DFE_EN_MASK; + data |= 0x1 << HPIPE_G1_SET_1_G1_RX_DFE_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SET_1_REG, data, mask); + /* 0xA-DFE_Reg3 */ + mask = HPIPE_DFE_F3_F5_DFE_EN_MASK; + data = 0x0 << HPIPE_DFE_F3_F5_DFE_EN_OFFSET; + mask |= HPIPE_DFE_F3_F5_DFE_CTRL_MASK; + data |= 0x0 << HPIPE_DFE_F3_F5_DFE_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_F3_F5_REG, data, mask); + + /* 0x111-G1_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = 0x1 << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + debug("stage: RFU configurations- Power Up PLL,Tx,Rx\n"); + /* SERDES External Configuration */ + mask = SD_EXTERNAL_CONFIG0_SD_PU_PLL_MASK; + data = 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_PLL_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_RX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_RX_OFFSET; + mask |= SD_EXTERNAL_CONFIG0_SD_PU_TX_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG0_SD_PU_TX_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG0_REG, data, mask); + + + /* check PLL rx & tx ready */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_PLL_RX_MASK | + SD_EXTERNAL_STATUS0_PLL_TX_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + ERROR("SD_EXTERNAL_STATUS0_PLL_RX is %d, -\"-_PLL_TX is %d\n", + (data & SD_EXTERNAL_STATUS0_PLL_RX_MASK), + (data & SD_EXTERNAL_STATUS0_PLL_TX_MASK)); + ret = -ETIMEDOUT; + } + + /* RX init */ + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, + 0x1 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET, + SD_EXTERNAL_CONFIG1_RX_INIT_MASK); + + /* check that RX init done */ + addr = sd_ip_addr + SD_EXTERNAL_STATUS0_REG; + data = SD_EXTERNAL_STATUS0_RX_INIT_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 100, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + sd_ip_addr + SD_EXTERNAL_STATUS0_REG, data); + ERROR("SD_EXTERNAL_STATUS0_RX_INIT is 0\n"); + ret = -ETIMEDOUT; + } + + debug("stage: RF Reset\n"); + /* RF Reset */ + mask = SD_EXTERNAL_CONFIG1_RX_INIT_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RX_INIT_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x1 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + debug_exit(); + + return ret; +} + +static int mvebu_cp110_comphy_usb3_power_on(uint64_t comphy_base, + uint8_t comphy_index, uint32_t comphy_mode) +{ + uintptr_t hpipe_addr, comphy_addr, addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr, phy_polarity_invert; + int ret = 0; + + debug_enter(); + + /* Configure PIPE selector for USB3 */ + mvebu_cp110_comphy_set_pipe_selector(comphy_base, comphy_index, + comphy_mode); + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + const struct usb_params *usb_static_values = + &usb_static_values_tab[ap_nr][cp_nr][comphy_index]; + + phy_polarity_invert = usb_static_values->polarity_invert; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_addr = COMPHY_ADDR(comphy_base, comphy_index); + + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x1 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + mask |= COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + mask |= COMMON_PHY_PHY_MODE_MASK; + data |= 0x1 << COMMON_PHY_PHY_MODE_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* release from hard reset */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x1 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Wait 1ms - until band gap and ref clock ready */ + mdelay(1); + + /* Start comphy Configuration */ + debug("stage: Comphy configuration\n"); + /* Set PIPE soft reset */ + mask = HPIPE_RST_CLK_CTRL_PIPE_RST_MASK; + data = 0x1 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET; + /* Set PHY datapath width mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_FIXED_PCLK_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_FIXED_PCLK_OFFSET; + /* Set Data bus width USB mode for V0 */ + mask |= HPIPE_RST_CLK_CTRL_PIPE_WIDTH_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_PIPE_WIDTH_OFFSET; + /* Set CORE_CLK output frequency for 250Mhz */ + mask |= HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_MASK; + data |= 0x0 << HPIPE_RST_CLK_CTRL_CORE_FREQ_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, data, mask); + /* Set PLL ready delay for 0x2 */ + reg_set(hpipe_addr + HPIPE_CLK_SRC_LO_REG, + 0x2 << HPIPE_CLK_SRC_LO_PLL_RDY_DL_OFFSET, + HPIPE_CLK_SRC_LO_PLL_RDY_DL_MASK); + /* Set reference clock to come from group 1 - 25Mhz */ + reg_set(hpipe_addr + HPIPE_MISC_REG, + 0x0 << HPIPE_MISC_REFCLK_SEL_OFFSET, + HPIPE_MISC_REFCLK_SEL_MASK); + /* Set reference frequcency select - 0x2 */ + mask = HPIPE_PWR_PLL_REF_FREQ_MASK; + data = 0x2 << HPIPE_PWR_PLL_REF_FREQ_OFFSET; + /* Set PHY mode to USB - 0x5 */ + mask |= HPIPE_PWR_PLL_PHY_MODE_MASK; + data |= 0x5 << HPIPE_PWR_PLL_PHY_MODE_OFFSET; + reg_set(hpipe_addr + HPIPE_PWR_PLL_REG, data, mask); + /* Set the amount of time spent in the LoZ state - set for 0x7 */ + reg_set(hpipe_addr + HPIPE_GLOBAL_PM_CTRL, + 0x7 << HPIPE_GLOBAL_PM_RXDLOZ_WAIT_OFFSET, + HPIPE_GLOBAL_PM_RXDLOZ_WAIT_MASK); + /* Set max PHY generation setting - 5Gbps */ + reg_set(hpipe_addr + HPIPE_INTERFACE_REG, + 0x1 << HPIPE_INTERFACE_GEN_MAX_OFFSET, + HPIPE_INTERFACE_GEN_MAX_MASK); + /* Set select data width 20Bit (SEL_BITS[2:0]) */ + reg_set(hpipe_addr + HPIPE_LOOPBACK_REG, + 0x1 << HPIPE_LOOPBACK_SEL_OFFSET, + HPIPE_LOOPBACK_SEL_MASK); + /* select de-emphasize 3.5db */ + reg_set(hpipe_addr + HPIPE_LANE_CONFIG0_REG, + 0x1 << HPIPE_LANE_CONFIG0_TXDEEMPH0_OFFSET, + HPIPE_LANE_CONFIG0_TXDEEMPH0_MASK); + /* override tx margining from the MAC */ + reg_set(hpipe_addr + HPIPE_TST_MODE_CTRL_REG, + 0x1 << HPIPE_TST_MODE_CTRL_MODE_MARGIN_OFFSET, + HPIPE_TST_MODE_CTRL_MODE_MARGIN_MASK); + + /* The polarity inversion for USB was not tested due to lack of hw + * design which requires it. Support is added for customer needs. + */ + if (phy_polarity_invert) + mvebu_cp110_polarity_invert(hpipe_addr + HPIPE_SYNC_PATTERN_REG, + phy_polarity_invert); + + /* Start analog parameters from ETP(HW) */ + debug("stage: Analog parameters from ETP(HW)\n"); + /* Set Pin DFE_PAT_DIS -> Bit[1]: PIN_DFE_PAT_DIS = 0x0 */ + mask = HPIPE_LANE_CFG4_DFE_CTRL_MASK; + data = 0x1 << HPIPE_LANE_CFG4_DFE_CTRL_OFFSET; + /* Set Override PHY DFE control pins for 0x1 */ + mask |= HPIPE_LANE_CFG4_DFE_OVER_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_DFE_OVER_OFFSET; + /* Set Spread Spectrum Clock Enable fot 0x1 */ + mask |= HPIPE_LANE_CFG4_SSC_CTRL_MASK; + data |= 0x1 << HPIPE_LANE_CFG4_SSC_CTRL_OFFSET; + reg_set(hpipe_addr + HPIPE_LANE_CFG4_REG, data, mask); + /* Confifure SSC amplitude */ + mask = HPIPE_G2_TX_SSC_AMP_MASK; + data = 0x1f << HPIPE_G2_TX_SSC_AMP_OFFSET; + reg_set(hpipe_addr + HPIPE_G2_SET_2_REG, data, mask); + /* End of analog parameters */ + + debug("stage: Comphy power up\n"); + /* Release from PIPE soft reset */ + reg_set(hpipe_addr + HPIPE_RST_CLK_CTRL_REG, + 0x0 << HPIPE_RST_CLK_CTRL_PIPE_RST_OFFSET, + HPIPE_RST_CLK_CTRL_PIPE_RST_MASK); + + /* wait 15ms - for comphy calibration done */ + debug("stage: Check PLL\n"); + /* Read lane status */ + addr = hpipe_addr + HPIPE_LANE_STATUS1_REG; + data = HPIPE_LANE_STATUS1_PCLK_EN_MASK; + mask = data; + data = polling_with_timeout(addr, data, mask, 15000, REG_32BIT); + if (data != 0) { + debug("Read from reg = %lx - value = 0x%x\n", + hpipe_addr + HPIPE_LANE_STATUS1_REG, data); + ERROR("HPIPE_LANE_STATUS1_PCLK_EN_MASK is 0\n"); + ret = -ETIMEDOUT; + } + + debug_exit(); + + return ret; +} + +static void rx_pre_train(uint64_t comphy_base, uint8_t comphy_index) +{ + uintptr_t hpipe_addr; + uint32_t mask, data; + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + debug("rx_training preparation\n\n"); + + mask = HPIPE_TRX0_GAIN_TRAIN_WITH_C_MASK; + data = (0x1 << HPIPE_TRX0_GAIN_TRAIN_WITH_C_OFF); + mask |= HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_MASK; + data |= (0x0 << HPIPE_TRX0_GAIN_TRAIN_WITH_SAMPLER_OFF); + reg_set(hpipe_addr + HPIPE_TRX0_REG, data, mask); + + + mask = HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK; + data = (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF); + mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_MASK; + data |= (0x0 << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_K_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG2, data, mask); + + mask = HPIPE_TRX_REG1_MIN_BOOST_MODE_MASK; + data = (0x1 << HPIPE_TRX_REG1_MIN_BOOST_MODE_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask); + + mask = HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_MASK; + data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_SMALL_THRES_K_OFF); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL1_REG, data, mask); + + mask = HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_MASK; + data = (0x8 << HPIPE_CRD2_CRD_MIDPOINT_LARGE_THRES_K_OFF); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL2_REG, data, mask); + + mask = HPIPE_CRD_MIDPOINT_PHASE_OS_MASK; + data = (0x0 << HPIPE_CRD_MIDPOINT_PHASE_OS_OFFSET); + reg_set(hpipe_addr + HPIPE_CDR_CONTROL_REG, data, mask); + + mask = HPIPE_TRX_REG1_SUMFTAP_EN_MASK; + data = (0x38 << HPIPE_TRX_REG1_SUMFTAP_EN_OFF); + mask |= HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_MASK; + data |= (0x1e << HPIPE_TRX_REG2_SUMF_BOOST_TARGET_C_OFF); + reg_set(hpipe_addr + HPIPE_TRX_REG1, data, mask); +} + +int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base, + uint8_t comphy_index) +{ + uint32_t mask, data, timeout; + uint32_t g1_ffe_cap_sel, g1_ffe_res_sel, align90, g1_dfe_res; + uintptr_t hpipe_addr; + + uint8_t ap_nr, cp_nr; + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + hpipe_addr = HPIPE_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + debug_enter(); + + rx_pre_train(comphy_base, comphy_index); + + debug("Preparation for rx_training\n\n"); + + /* Use the FFE table */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data = 0 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Use auto-calibration value */ + mask = HPIPE_CAL_RXCLKALIGN_90_EXT_EN_MASK; + data = 0 << HPIPE_CAL_RXCLKALIGN_90_EXT_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_RX_CLK_ALIGN90_AND_TX_IDLE_CALIB_CTRL_REG, + data, mask); + + /* Use Tx/Rx training results */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + debug("Enable RX training\n\n"); + + mask = HPIPE_TRX_RX_TRAIN_EN_MASK; + data = 0x1 << HPIPE_TRX_RX_TRAIN_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask); + + /* Check the result of RX training */ + timeout = RX_TRAINING_TIMEOUT; + mask = HPIPE_INTERRUPT_TRX_TRAIN_DONE_OFFSET | + HPIPE_INTERRUPT_DFE_DONE_INT_OFFSET | + HPIPE_INTERRUPT_RX_TRAIN_COMPLETE_INT_MASK; + while (timeout) { + data = mmio_read_32(hpipe_addr + HPIPE_INTERRUPT_1_REGISTER); + if (data & mask) + break; + mdelay(1); + timeout--; + } + + debug("RX training result: interrupt reg 0x%lx = 0x%x\n\n", + hpipe_addr + HPIPE_INTERRUPT_1_REGISTER, data); + + if (timeout == 0 || data & HPIPE_TRX_TRAIN_TIME_OUT_INT_MASK) { + ERROR("Rx training timeout...\n"); + return -ETIMEDOUT; + } + + if (data & HPIPE_TRX_TRAIN_FAILED_MASK) { + ERROR("Rx training failed...\n"); + return -EINVAL; + } + + mask = HPIPE_TRX_RX_TRAIN_EN_MASK; + data = 0x0 << HPIPE_TRX_RX_TRAIN_EN_OFFSET; + reg_set(hpipe_addr + HPIPE_TRX_TRAIN_CTRL_0_REG, data, mask); + + debug("Training done, reading results...\n\n"); + + mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_MASK; + g1_ffe_res_sel = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG) + & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_RES_OFFSET); + + mask = HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_MASK; + g1_ffe_cap_sel = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG) + & mask) >> HPIPE_ADAPTED_FFE_ADAPTED_FFE_CAP_OFFSET); + + mask = HPIPE_DATA_PHASE_ADAPTED_OS_PH_MASK; + align90 = ((mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG) + & mask) >> HPIPE_DATA_PHASE_ADAPTED_OS_PH_OFFSET); + + mask = HPIPE_ADAPTED_DFE_RES_MASK; + g1_dfe_res = ((mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG) + & mask) >> HPIPE_ADAPTED_DFE_RES_OFFSET); + + debug("================================================\n"); + debug("Switching to static configuration:\n"); + debug("FFE_RES = 0x%x FFE_CAP = 0x%x align90 = 0x%x g1_dfe_res 0x%x\n", + g1_ffe_res_sel, g1_ffe_cap_sel, align90, g1_dfe_res); + debug("Result after training: 0x%lx= 0x%x, 0x%lx= 0x%x, 0x%lx = 0x%x\n", + (hpipe_addr + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG), + mmio_read_32(hpipe_addr + + HPIPE_ADAPTED_FFE_CAPACITOR_COUNTER_CTRL_REG), + (hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG), + mmio_read_32(hpipe_addr + HPIPE_DATA_PHASE_OFF_CTRL_REG), + (hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG), + mmio_read_32(hpipe_addr + HPIPE_ADAPTED_DFE_COEFFICIENT_1_REG)); + debug("================================================\n"); + + /* Update FFE_RES */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_MASK; + data = g1_ffe_res_sel << HPIPE_G1_SETTINGS_3_G1_FFE_RES_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Update FFE_CAP */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_MASK; + data = g1_ffe_cap_sel << HPIPE_G1_SETTINGS_3_G1_FFE_CAP_SEL_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Bypass the FFE table settings and use the FFE settings directly from + * registers FFE_RES_SEL and FFE_CAP_SEL + */ + mask = HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_MASK; + data = 1 << HPIPE_G1_SETTINGS_3_G1_FFE_SETTING_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_3_REG, data, mask); + + /* Force DFE resolution (use gen table value) */ + mask = HPIPE_DFE_RES_FORCE_MASK; + data = 0x1 << HPIPE_DFE_RES_FORCE_OFFSET; + reg_set(hpipe_addr + HPIPE_DFE_REG0, data, mask); + + /* 0x111-G1 DFE_Setting_4 */ + mask = HPIPE_G1_SETTINGS_4_G1_DFE_RES_MASK; + data = g1_dfe_res << HPIPE_G1_SETTINGS_4_G1_DFE_RES_OFFSET; + reg_set(hpipe_addr + HPIPE_G1_SETTINGS_4_REG, data, mask); + + printf("########################################################\n"); + printf("# To use trained values update the ATF sources:\n"); + printf("# plat/marvell/armada/a8k//board/phy-porting-layer.h "); + printf("file\n# with new values as below (for appropriate AP nr %d", + ap_nr); + printf("and CP nr: %d comphy_index %d\n\n", + cp_nr, comphy_index); + printf("static struct xfi_params xfi_static_values_tab[AP_NUM]"); + printf("[CP_NUM][MAX_LANE_NR] = {\n"); + printf("\t...\n"); + printf("\t.g1_ffe_res_sel = 0x%x,\n", g1_ffe_res_sel); + printf("\t.g1_ffe_cap_sel = 0x%x,\n", g1_ffe_cap_sel); + printf("\t.align90 = 0x%x,\n", align90); + printf("\t.g1_dfe_res = 0x%x\n", g1_dfe_res); + printf("\t...\n"); + printf("};\n\n"); + printf("########################################################\n"); + + rx_trainng_done[ap_nr][cp_nr][comphy_index] = 1; + + return 0; +} + +/* During AP the proper mode is auto-negotiated and the mac, pcs and serdes + * configuration are done by the firmware loaded to the MG's CM3 for appropriate + * negotiated mode. Therefore there is no need to configure the mac, pcs and + * serdes from u-boot. The only thing that need to be setup is powering up + * the comphy, which is done through Common PHY Configuration 1 Register + * (CP0: 0xF2441000, CP1: 0xF4441000). This step can't be done by MG's CM3, + * since it doesn't have an access to this register-set (but it has access to + * the network registers like: MG, AP, MAC, PCS, Serdes etc.) + */ +static int mvebu_cp110_comphy_ap_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode) +{ + uint32_t mask, data; + uintptr_t comphy_addr = comphy_addr = + COMPHY_ADDR(comphy_base, comphy_index); + + /* configure phy selector for XFI/SFI */ + mvebu_cp110_comphy_set_phy_selector(comphy_base, comphy_index, + comphy_mode); + debug_enter(); + debug("stage: RFU configurations - hard reset comphy\n"); + /* RFU configurations - hard reset comphy */ + mask = COMMON_PHY_CFG1_PWR_UP_MASK; + data = 0x1 << COMMON_PHY_CFG1_PWR_UP_OFFSET; + mask |= COMMON_PHY_CFG1_PIPE_SELECT_MASK; + data |= 0x0 << COMMON_PHY_CFG1_PIPE_SELECT_OFFSET; + reg_set(comphy_addr + COMMON_PHY_CFG1_REG, data, mask); + debug_exit(); + +#if MSS_SUPPORT + do { + uint8_t ap_nr, cp_nr; + + /* start ap fw */ + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + mg_start_ap_fw(cp_nr, comphy_index); + + } while (0); +#endif + return 0; +} + +/* + * This function allows to reset the digital synchronizers between + * the MAC and the PHY, it is required when the MAC changes its state. + */ +int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, + uint8_t comphy_index, + uint32_t comphy_mode, uint32_t command) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + uintptr_t sd_ip_addr; + uint32_t mask, data; + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + + switch (mode) { + case (COMPHY_SGMII_MODE): + case (COMPHY_2500BASEX_MODE): + case (COMPHY_XFI_MODE): + case (COMPHY_SFI_MODE): + case (COMPHY_RXAUI_MODE): + mask = SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data = ((command == COMPHY_COMMAND_DIGITAL_PWR_OFF) ? + 0x0 : 0x1) << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + break; + default: + ERROR("comphy%d: Digital PWR ON/OFF is not supported\n", + comphy_index); + return -EINVAL; + } + + return 0; +} + +int mvebu_cp110_comphy_power_on(uint64_t comphy_base, + uint8_t comphy_index, + uint64_t comphy_mode, + uint64_t comphy_train_base) +{ + int mode = COMPHY_GET_MODE(comphy_mode); + int err = 0; + + debug_enter(); + + switch (mode) { + case(COMPHY_SATA_MODE): + err = mvebu_cp110_comphy_sata_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case(COMPHY_SGMII_MODE): + case(COMPHY_2500BASEX_MODE): + err = mvebu_cp110_comphy_sgmii_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + /* From comphy perspective, XFI and SFI are the same */ + case (COMPHY_XFI_MODE): + case (COMPHY_SFI_MODE): + err = mvebu_cp110_comphy_xfi_power_on(comphy_base, + comphy_index, + comphy_mode, + comphy_train_base); + break; + case (COMPHY_PCIE_MODE): + err = mvebu_cp110_comphy_pcie_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_RXAUI_MODE): + err = mvebu_cp110_comphy_rxaui_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_USB3H_MODE): + case (COMPHY_USB3D_MODE): + err = mvebu_cp110_comphy_usb3_power_on(comphy_base, + comphy_index, + comphy_mode); + break; + case (COMPHY_AP_MODE): + err = mvebu_cp110_comphy_ap_power_on(comphy_base, comphy_index, + comphy_mode); + break; + default: + ERROR("comphy%d: unsupported comphy mode\n", comphy_index); + err = -EINVAL; + break; + } + + debug_exit(); + + return err; +} + +int mvebu_cp110_comphy_power_off(uint64_t comphy_base, uint8_t comphy_index, + uint64_t comphy_mode) +{ + uintptr_t sd_ip_addr, comphy_ip_addr; + uint32_t mask, data; + uint8_t ap_nr, cp_nr; + _Bool called_from_uboot = COMPHY_GET_CALLER(comphy_mode); + + debug_enter(); + + /* Power-off might happen because of 2 things: + * 1. Bootloader turns off unconnected lanes + * 2. Linux turns off all lanes during boot + * (and then reconfigure it). + * + * For PCIe, there's a problem: + * In Armada 8K DB boards, PCIe initialization can be executed + * only once (PCIe reset performed during chip power on and + * it cannot be executed via GPIO later) so a lane configured to + * PCIe should not be powered off by Linux. + * + * So, check 2 things: + * 1. Is Linux called for power-off? + * 2. Is the comphy configured to PCIe? + * If the answer is YES for both 1 and 2, skip the power-off. + * + * TODO: In MacciatoBIN, PCIe reset is connected via GPIO, + * so after GPIO reset is added to Linux Kernel, it can be + * powered-off. + */ + if (!called_from_uboot) { + data = mmio_read_32(comphy_base + + COMMON_SELECTOR_PIPE_REG_OFFSET); + data >>= (COMMON_SELECTOR_COMPHYN_FIELD_WIDTH * comphy_index); + data &= COMMON_SELECTOR_COMPHY_MASK; + if (data == COMMON_SELECTOR_PIPE_COMPHY_PCIE) + return 0; + } + + mvebu_cp110_get_ap_and_cp_nr(&ap_nr, &cp_nr, comphy_base); + + if (rx_trainng_done[ap_nr][cp_nr][comphy_index]) { + debug("Skip %s for comphy[%d][%d][%d], due to rx training\n", + __func__, ap_nr, cp_nr, comphy_index); + return 0; + } + + sd_ip_addr = SD_ADDR(COMPHY_PIPE_FROM_COMPHY_ADDR(comphy_base), + comphy_index); + comphy_ip_addr = COMPHY_ADDR(comphy_base, comphy_index); + + /* Hard reset the comphy, for Ethernet modes and Sata */ + mask = SD_EXTERNAL_CONFIG1_RESET_IN_MASK; + data = 0x0 << SD_EXTERNAL_CONFIG1_RESET_IN_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RESET_CORE_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RESET_CORE_OFFSET; + mask |= SD_EXTERNAL_CONFIG1_RF_RESET_IN_MASK; + data |= 0x0 << SD_EXTERNAL_CONFIG1_RF_RESET_IN_OFFSET; + reg_set(sd_ip_addr + SD_EXTERNAL_CONFIG1_REG, data, mask); + + /* PCIe reset */ + spin_lock(&cp110_mac_reset_lock); + + /* The mvebu_cp110_comphy_power_off will be called only from Linux (to + * override settings done by bootloader) and it will be relevant only + * to PCIe (called before check if to skip pcie power off or not). + */ + data = mmio_read_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG); + switch (comphy_index) { + case COMPHY_LANE0: + data &= ~PCIE_MAC_RESET_MASK_PORT0; + break; + case COMPHY_LANE4: + data &= ~PCIE_MAC_RESET_MASK_PORT1; + break; + case COMPHY_LANE5: + data &= ~PCIE_MAC_RESET_MASK_PORT2; + break; + } + + mmio_write_32(SYS_CTRL_FROM_COMPHY_ADDR(comphy_base) + + SYS_CTRL_UINIT_SOFT_RESET_REG, data); + spin_unlock(&cp110_mac_reset_lock); + + /* Hard reset the comphy, for PCIe and usb3 */ + mask = COMMON_PHY_CFG1_PWR_ON_RESET_MASK; + data = 0x0 << COMMON_PHY_CFG1_PWR_ON_RESET_OFFSET; + mask |= COMMON_PHY_CFG1_CORE_RSTN_MASK; + data |= 0x0 << COMMON_PHY_CFG1_CORE_RSTN_OFFSET; + reg_set(comphy_ip_addr + COMMON_PHY_CFG1_REG, data, mask); + + /* Clear comphy PHY and PIPE selector, can't rely on previous config. */ + mvebu_cp110_comphy_clr_phy_selector(comphy_base, comphy_index); + mvebu_cp110_comphy_clr_pipe_selector(comphy_base, comphy_index); + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h new file mode 100644 index 0000000..0be6c26 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h @@ -0,0 +1,102 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Those are parameters for xfi mode, which need to be tune for each board type. + * For known DB boards the parameters was already calibrated and placed under + * the plat/marvell/armada/a8k//board/phy-porting-layer.h + */ +struct xfi_params { + uint8_t g1_ffe_res_sel; + uint8_t g1_ffe_cap_sel; + uint8_t align90; + uint8_t g1_dfe_res; + uint8_t g1_amp; + uint8_t g1_emph; + uint8_t g1_emph_en; + uint8_t g1_tx_amp_adj; + uint8_t g1_tx_emph_en; + uint8_t g1_tx_emph; + uint8_t g1_rx_selmuff; + uint8_t g1_rx_selmufi; + uint8_t g1_rx_selmupf; + uint8_t g1_rx_selmupi; + _Bool valid; +}; + +struct sata_params { + uint8_t g1_amp; + uint8_t g2_amp; + uint8_t g3_amp; + + uint8_t g1_emph; + uint8_t g2_emph; + uint8_t g3_emph; + + uint8_t g1_emph_en; + uint8_t g2_emph_en; + uint8_t g3_emph_en; + + uint8_t g1_tx_amp_adj; + uint8_t g2_tx_amp_adj; + uint8_t g3_tx_amp_adj; + + uint8_t g1_tx_emph_en; + uint8_t g2_tx_emph_en; + uint8_t g3_tx_emph_en; + + uint8_t g1_tx_emph; + uint8_t g2_tx_emph; + uint8_t g3_tx_emph; + + uint8_t g3_dfe_res; + + uint8_t g3_ffe_res_sel; + + uint8_t g3_ffe_cap_sel; + + uint8_t align90; + + uint8_t g1_rx_selmuff; + uint8_t g2_rx_selmuff; + uint8_t g3_rx_selmuff; + + uint8_t g1_rx_selmufi; + uint8_t g2_rx_selmufi; + uint8_t g3_rx_selmufi; + + uint8_t g1_rx_selmupf; + uint8_t g2_rx_selmupf; + uint8_t g3_rx_selmupf; + + uint8_t g1_rx_selmupi; + uint8_t g2_rx_selmupi; + uint8_t g3_rx_selmupi; + + uint8_t polarity_invert; + + _Bool valid; +}; + +struct usb_params { + uint8_t polarity_invert; +}; + +int mvebu_cp110_comphy_is_pll_locked(uint64_t comphy_base, + uint8_t comphy_index); +int mvebu_cp110_comphy_power_off(uint64_t comphy_base, + uint8_t comphy_index, uint64_t comphy_mode); +int mvebu_cp110_comphy_power_on(uint64_t comphy_base, uint8_t comphy_index, + uint64_t comphy_mode, + uint64_t comphy_train_base); +int mvebu_cp110_comphy_xfi_rx_training(uint64_t comphy_base, + uint8_t comphy_index); +int mvebu_cp110_comphy_digital_reset(uint64_t comphy_base, uint8_t comphy_index, + uint32_t comphy_mode, uint32_t command); + +#define COMPHY_POLARITY_NO_INVERT 0 +#define COMPHY_POLARITY_TXD_INVERT 1 +#define COMPHY_POLARITY_RXD_INVERT 2 diff --git a/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h b/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h new file mode 100644 index 0000000..3c63c64 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PHY_DEFAULT_PORTING_LAYER_H +#define PHY_DEFAULT_PORTING_LAYER_H + + +#define MAX_LANE_NR 6 + +#warning "Using default comphy params - you may need to suit them to your board" + +static const struct xfi_params + xfi_static_values_tab[AP_NUM][CP_NUM][MAX_LANE_NR] = { + [0 ... AP_NUM-1][0 ... CP_NUM-1][0 ... MAX_LANE_NR-1] = { + .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 + } +}; + +static const struct 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_DEFAULT_PORTING_LAYER_H */ diff --git a/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c new file mode 100644 index 0000000..352d1ef --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.c @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include "ddr_phy_access.h" +#include +#include +#include + +#define DDR_PHY_END_ADDRESS 0x100000 + +#ifdef DDR_PHY_DEBUG +#define debug_printf(...) printf(__VA_ARGS__) +#else +#define debug_printf(...) +#endif + + +/* + * This routine writes 'data' to specified 'address' offset, + * with optional debug print support + */ +int snps_fw_write(uintptr_t offset, uint16_t data) +{ + debug_printf("In %s\n", __func__); + + if (offset < DDR_PHY_END_ADDRESS) { + mmio_write_16(DDR_PHY_BASE_ADDR + (2 * offset), data); + return 0; + } + debug_printf("%s: illegal offset value: 0x%x\n", __func__, offset); + return -EINVAL; +} + +int snps_fw_read(uintptr_t offset, uint16_t *read) +{ + debug_printf("In %s\n", __func__); + + if (offset < DDR_PHY_END_ADDRESS) { + *read = mmio_read_16(DDR_PHY_BASE_ADDR + (2 * offset)); + return 0; + } + debug_printf("%s: illegal offset value: 0x%x\n", __func__, offset); + return -EINVAL; +} + +int mvebu_ddr_phy_write(uintptr_t offset, uint16_t data) +{ + return snps_fw_write(offset, data); +} + +int mvebu_ddr_phy_read(uintptr_t offset, uint16_t *read) +{ + return snps_fw_read(offset, read); +} diff --git a/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h new file mode 100644 index 0000000..5f9a668 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/ddr_phy_access.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include + +#define DEVICE_BASE 0xF0000000 +#define DDR_PHY_OFFSET 0x1000000 +#define DDR_PHY_BASE_ADDR (DEVICE_BASE + DDR_PHY_OFFSET) + +int mvebu_ddr_phy_write(uintptr_t offset, uint16_t data); +int mvebu_ddr_phy_read(uintptr_t offset, uint16_t *read); diff --git a/arm-trusted-firmware/drivers/marvell/gwin.c b/arm-trusted-firmware/drivers/marvell/gwin.c new file mode 100644 index 0000000..fa59cb0 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/gwin.c @@ -0,0 +1,231 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* GWIN unit device driver for Marvell AP810 SoC */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +#define WIN_TARGET_MASK (0xF) +#define WIN_TARGET_SHIFT (0x8) +#define WIN_TARGET(tgt) (((tgt) & WIN_TARGET_MASK) \ + << WIN_TARGET_SHIFT) + +/* Bits[43:26] of the physical address are the window base, + * which is aligned to 64MB + */ +#define ADDRESS_RSHIFT (26) +#define ADDRESS_LSHIFT (10) +#define GWIN_ALIGNMENT_64M (0x4000000) + +/* AP registers */ +#define GWIN_CR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0x0 + \ + (0x10 * (win))) +#define GWIN_ALR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0x8 + \ + (0x10 * (win))) +#define GWIN_AHR_OFFSET(ap, win) (MVEBU_GWIN_BASE(ap) + 0xc + \ + (0x10 * (win))) + +#define CCU_GRU_CR_OFFSET(ap) (MVEBU_CCU_GRU_BASE(ap)) +#define CCR_GRU_CR_GWIN_MBYPASS (1 << 1) + +static void gwin_check(struct addr_map_win *win) +{ + /* The base is always 64M aligned */ + if (IS_NOT_ALIGN(win->base_addr, GWIN_ALIGNMENT_64M)) { + win->base_addr &= ~(GWIN_ALIGNMENT_64M - 1); + NOTICE("%s: Align the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, GWIN_ALIGNMENT_64M)) { + win->win_size = ALIGN_UP(win->win_size, GWIN_ALIGNMENT_64M); + NOTICE("%s: Aligning window size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +static void gwin_enable_window(int ap_index, struct addr_map_win *win, + uint32_t win_num) +{ + uint32_t alr, ahr; + uint64_t end_addr; + + if ((win->target_id & WIN_TARGET_MASK) != win->target_id) { + ERROR("target ID = %d, is invalid\n", win->target_id); + return; + } + + /* calculate 64bit end-address */ + end_addr = (win->base_addr + win->win_size - 1); + + alr = (uint32_t)((win->base_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT); + ahr = (uint32_t)((end_addr >> ADDRESS_RSHIFT) << ADDRESS_LSHIFT); + + /* write start address and end address for GWIN */ + mmio_write_32(GWIN_ALR_OFFSET(ap_index, win_num), alr); + mmio_write_32(GWIN_AHR_OFFSET(ap_index, win_num), ahr); + + /* write the target ID and enable the window */ + mmio_write_32(GWIN_CR_OFFSET(ap_index, win_num), + WIN_TARGET(win->target_id) | WIN_ENABLE_BIT); +} + +static void gwin_disable_window(int ap_index, uint32_t win_num) +{ + uint32_t win_reg; + + win_reg = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(GWIN_CR_OFFSET(ap_index, win_num), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void gwin_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_GWIN_MAX_WINS - i - 1; + gwin_check(win); + gwin_enable_window(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void gwin_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_GWIN_MAX_WINS - i - 1; + + target = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_id)); + target >>= WIN_TARGET_SHIFT; + target &= WIN_TARGET_MASK; + + base = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_id)); + base >>= ADDRESS_LSHIFT; + base <<= ADDRESS_RSHIFT; + + if (win->target_id != target) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + gwin_disable_window(ap_index, win_id); + win++; + } +} + +#ifdef DEBUG_ADDR_MAP +static void dump_gwin(int ap_index) +{ + uint32_t win_num; + + /* Dump all GWIN windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_num = 0; win_num < MVEBU_GWIN_MAX_WINS; win_num++) { + uint32_t cr; + uint64_t alr, ahr; + + cr = mmio_read_32(GWIN_CR_OFFSET(ap_index, win_num)); + /* Window enabled */ + if (cr & WIN_ENABLE_BIT) { + alr = mmio_read_32(GWIN_ALR_OFFSET(ap_index, win_num)); + alr = (alr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; + ahr = mmio_read_32(GWIN_AHR_OFFSET(ap_index, win_num)); + ahr = (ahr >> ADDRESS_LSHIFT) << ADDRESS_RSHIFT; + printf("\tgwin %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + (cr >> 8) & 0xF, alr, ahr); + } + } +} +#endif + +int init_gwin(int ap_index) +{ + struct addr_map_win *win; + uint32_t win_id; + uint32_t win_count; + uint32_t win_reg; + + INFO("Initializing GWIN Address decoding\n"); + + /* Get the array of the windows and its size */ + marvell_get_gwin_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) { + INFO("no windows configurations found\n"); + return 0; + } + + if (win_count > MVEBU_GWIN_MAX_WINS) { + ERROR("number of windows is bigger than %d\n", + MVEBU_GWIN_MAX_WINS); + return 0; + } + + /* disable all windows */ + for (win_id = 0; win_id < MVEBU_GWIN_MAX_WINS; win_id++) + gwin_disable_window(ap_index, win_id); + + /* enable relevant windows */ + for (win_id = 0; win_id < win_count; win_id++, win++) { + gwin_check(win); + gwin_enable_window(ap_index, win, win_id); + } + + /* GWIN Miss feature has not verified, therefore any access towards + * remote AP should be accompanied with proper configuration to + * GWIN registers group and therefore the GWIN Miss feature + * should be set into Bypass mode, need to make sure all GWIN regions + * are defined correctly that will assure no GWIN miss occurrance + * JIRA-AURORA2-1630 + */ + INFO("Update GWIN miss bypass\n"); + win_reg = mmio_read_32(CCU_GRU_CR_OFFSET(ap_index)); + win_reg |= CCR_GRU_CR_GWIN_MBYPASS; + mmio_write_32(CCU_GRU_CR_OFFSET(ap_index), win_reg); + +#ifdef DEBUG_ADDR_MAP + dump_gwin(ap_index); +#endif + + INFO("Done GWIN Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/io_win.c b/arm-trusted-firmware/drivers/marvell/io_win.c new file mode 100644 index 0000000..124382a --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/io_win.c @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IO Window unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {Addr[19:0],20`h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define IO_WIN_ALIGNMENT_1M (0x100000) +#define IO_WIN_ALIGNMENT_64K (0x10000) + +/* AP registers */ +#define IO_WIN_ALR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0x0 + \ + (0x10 * win)) +#define IO_WIN_AHR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0x8 + \ + (0x10 * win)) +#define IO_WIN_CR_OFFSET(ap, win) (MVEBU_IO_WIN_BASE(ap) + 0xC + \ + (0x10 * win)) + +/* For storage of CR, ALR, AHR abd GCR */ +static uint32_t io_win_regs_save[MVEBU_IO_WIN_MAX_WINS * 3 + 1]; + +static void io_win_check(struct addr_map_win *win) +{ + /* for IO The base is always 1M aligned */ + /* check if address is aligned to 1M */ + if (IS_NOT_ALIGN(win->base_addr, IO_WIN_ALIGNMENT_1M)) { + win->base_addr = ALIGN_UP(win->base_addr, IO_WIN_ALIGNMENT_1M); + NOTICE("%s: Align up the base address to 0x%" PRIx64 "\n", + __func__, win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, IO_WIN_ALIGNMENT_1M)) { + win->win_size = ALIGN_UP(win->win_size, IO_WIN_ALIGNMENT_1M); + NOTICE("%s: Aligning size to 0x%" PRIx64 "\n", + __func__, win->win_size); + } +} + +static void io_win_enable_window(int ap_index, struct addr_map_win *win, + uint32_t win_num) +{ + uint32_t alr, ahr; + uint64_t end_addr; + + if (win->target_id < 0 || win->target_id >= MVEBU_IO_WIN_MAX_WINS) { + ERROR("target ID = %d, is invalid\n", win->target_id); + return; + } + + if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) { + ERROR("Enabling wrong IOW window %d!\n", win_num); + return; + } + + /* calculate the end-address */ + end_addr = (win->base_addr + win->win_size - 1); + + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + alr |= WIN_ENABLE_BIT; + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + /* write start address and end address for IO window */ + mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), alr); + mmio_write_32(IO_WIN_AHR_OFFSET(ap_index, win_num), ahr); + + /* write window target */ + mmio_write_32(IO_WIN_CR_OFFSET(ap_index, win_num), win->target_id); +} + +static void io_win_disable_window(int ap_index, uint32_t win_num) +{ + uint32_t win_reg; + + if ((win_num == 0) || (win_num > MVEBU_IO_WIN_MAX_WINS)) { + ERROR("Disabling wrong IOW window %d!\n", win_num); + return; + } + + win_reg = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_num)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(IO_WIN_ALR_OFFSET(ap_index, win_num), win_reg); +} + +/* Insert/Remove temporary window for using the out-of reset default + * CPx base address to access the CP configuration space prior to + * the further base address update in accordance with address mapping + * design. + * + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void iow_temp_win_insert(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + for (int i = 0; i < size; i++) { + win_id = MVEBU_IO_WIN_MAX_WINS - i - 1; + io_win_check(win); + io_win_enable_window(ap_index, win, win_id); + win++; + } +} + +/* + * NOTE: Use the same window array for insertion and removal of + * temporary windows. + */ +void iow_temp_win_remove(int ap_index, struct addr_map_win *win, int size) +{ + uint32_t win_id; + + /* Start from the last window and do not touch Win0 */ + for (int i = 0; i < size; i++) { + uint64_t base; + uint32_t target; + + win_id = MVEBU_IO_WIN_MAX_WINS - i - 1; + + target = mmio_read_32(IO_WIN_CR_OFFSET(ap_index, win_id)); + base = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id)); + base &= ~WIN_ENABLE_BIT; + base <<= ADDRESS_SHIFT; + + if ((win->target_id != target) || (win->base_addr != base)) { + ERROR("%s: Trying to remove bad window-%d!\n", + __func__, win_id); + continue; + } + io_win_disable_window(ap_index, win_id); + win++; + } +} + +#ifdef DEBUG_ADDR_MAP +static void dump_io_win(int ap_index) +{ + uint32_t trgt_id, win_id; + uint32_t alr, ahr; + uint64_t start, end; + + /* Dump all IO windows */ + printf("\tbank target start end\n"); + printf("\t----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++) { + alr = mmio_read_32(IO_WIN_ALR_OFFSET(ap_index, win_id)); + if (alr & WIN_ENABLE_BIT) { + alr &= ~WIN_ENABLE_BIT; + ahr = mmio_read_32(IO_WIN_AHR_OFFSET(ap_index, win_id)); + trgt_id = mmio_read_32(IO_WIN_CR_OFFSET(ap_index, + win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + printf("\tio-win %d 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + trgt_id, start, end); + } + } + printf("\tio-win gcr is %x\n", + mmio_read_32(MVEBU_IO_WIN_BASE(ap_index) + + MVEBU_IO_WIN_GCR_OFFSET)); +} +#endif + +static void iow_save_win_range(int ap_id, int win_first, int win_last, + uint32_t *buffer) +{ + int win_id, idx; + + /* Save IOW */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + buffer[idx++] = mmio_read_32(IO_WIN_CR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(IO_WIN_ALR_OFFSET(ap_id, win_id)); + buffer[idx++] = mmio_read_32(IO_WIN_AHR_OFFSET(ap_id, win_id)); + } + buffer[idx] = mmio_read_32(MVEBU_IO_WIN_BASE(ap_id) + + MVEBU_IO_WIN_GCR_OFFSET); +} + +static void iow_restore_win_range(int ap_id, int win_first, int win_last, + uint32_t *buffer) +{ + int win_id, idx; + + /* Restore IOW */ + for (idx = 0, win_id = win_first; win_id <= win_last; win_id++) { + mmio_write_32(IO_WIN_CR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(IO_WIN_ALR_OFFSET(ap_id, win_id), buffer[idx++]); + mmio_write_32(IO_WIN_AHR_OFFSET(ap_id, win_id), buffer[idx++]); + } + mmio_write_32(MVEBU_IO_WIN_BASE(ap_id) + MVEBU_IO_WIN_GCR_OFFSET, + buffer[idx++]); +} + +void iow_save_win_all(int ap_id) +{ + iow_save_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1, + io_win_regs_save); +} + +void iow_restore_win_all(int ap_id) +{ + iow_restore_win_range(ap_id, 0, MVEBU_IO_WIN_MAX_WINS - 1, + io_win_regs_save); +} + +int init_io_win(int ap_index) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing IO WIN Address decoding\n"); + + /* Get the array of the windows and its size */ + marvell_get_io_win_memory_map(ap_index, &win, &win_count); + if (win_count <= 0) + INFO("no windows configurations found\n"); + + if (win_count > MVEBU_IO_WIN_MAX_WINS) { + INFO("number of windows is bigger than %d\n", + MVEBU_IO_WIN_MAX_WINS); + return 0; + } + + /* Get the default target id to set the GCR */ + win_reg = marvell_get_io_win_gcr_target(ap_index); + mmio_write_32(MVEBU_IO_WIN_BASE(ap_index) + MVEBU_IO_WIN_GCR_OFFSET, + win_reg); + + /* disable all IO windows */ + for (win_id = 1; win_id < MVEBU_IO_WIN_MAX_WINS; win_id++) + io_win_disable_window(ap_index, win_id); + + /* enable relevant windows, starting from win_id = 1 because + * index 0 dedicated for BootROM + */ + for (win_id = 1; win_id <= win_count; win_id++, win++) { + io_win_check(win); + io_win_enable_window(ap_index, win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_io_win(ap_index); +#endif + + INFO("Done IO WIN Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/iob.c b/arm-trusted-firmware/drivers/marvell/iob.c new file mode 100644 index 0000000..1f39395 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/iob.c @@ -0,0 +1,214 @@ +/* + * Copyright (C) 2016 - 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IOW unit device driver for Marvell CP110 and CP115 SoCs */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +#if LOG_LEVEL >= LOG_LEVEL_INFO +#define DEBUG_ADDR_MAP +#endif + +#define MVEBU_IOB_OFFSET (0x190000) +#define MVEBU_IOB_MAX_WINS 16 + +/* common defines */ +#define WIN_ENABLE_BIT (0x1) +/* Physical address of the base of the window = {AddrLow[19:0],20`h0} */ +#define ADDRESS_SHIFT (20 - 4) +#define ADDRESS_MASK (0xFFFFFFF0) +#define IOB_WIN_ALIGNMENT (0x100000) + +/* IOB registers */ +#define IOB_WIN_CR_OFFSET(win) (iob_base + 0x0 + (0x20 * win)) +#define IOB_TARGET_ID_OFFSET (8) +#define IOB_TARGET_ID_MASK (0xF) + +#define IOB_WIN_SCR_OFFSET(win) (iob_base + 0x4 + (0x20 * win)) +#define IOB_WIN_ENA_CTRL_WRITE_SECURE (0x1) +#define IOB_WIN_ENA_CTRL_READ_SECURE (0x2) +#define IOB_WIN_ENA_WRITE_SECURE (0x4) +#define IOB_WIN_ENA_READ_SECURE (0x8) + +#define IOB_WIN_ALR_OFFSET(win) (iob_base + 0x8 + (0x20 * win)) +#define IOB_WIN_AHR_OFFSET(win) (iob_base + 0xC + (0x20 * win)) + +#define IOB_WIN_DIOB_CR_OFFSET(win) (iob_base + 0x10 + (0x20 * win)) +#define IOB_WIN_XOR0_DIOB_EN BIT(0) +#define IOB_WIN_XOR1_DIOB_EN BIT(1) + +uintptr_t iob_base; + +static void iob_win_check(struct addr_map_win *win, uint32_t win_num) +{ + /* check if address is aligned to the size */ + if (IS_NOT_ALIGN(win->base_addr, IOB_WIN_ALIGNMENT)) { + win->base_addr = ALIGN_UP(win->base_addr, IOB_WIN_ALIGNMENT); + ERROR("Window %d: base address unaligned to 0x%x\n", + win_num, IOB_WIN_ALIGNMENT); + printf("Align up the base address to 0x%" PRIx64 "\n", + win->base_addr); + } + + /* size parameter validity check */ + if (IS_NOT_ALIGN(win->win_size, IOB_WIN_ALIGNMENT)) { + win->win_size = ALIGN_UP(win->win_size, IOB_WIN_ALIGNMENT); + ERROR("Window %d: window size unaligned to 0x%x\n", win_num, + IOB_WIN_ALIGNMENT); + printf("Aligning size to 0x%" PRIx64 "\n", win->win_size); + } +} + +static void iob_enable_win(struct addr_map_win *win, uint32_t win_id) +{ + uint32_t iob_win_reg; + uint32_t alr, ahr; + uint64_t end_addr; + uint32_t reg_en; + + /* move XOR (DMA) to use WIN1 which is used for PCI-EP address space */ + reg_en = IOB_WIN_XOR0_DIOB_EN | IOB_WIN_XOR1_DIOB_EN; + iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(0)); + iob_win_reg &= ~reg_en; + mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(0), iob_win_reg); + + iob_win_reg = mmio_read_32(IOB_WIN_DIOB_CR_OFFSET(1)); + iob_win_reg |= reg_en; + mmio_write_32(IOB_WIN_DIOB_CR_OFFSET(1), iob_win_reg); + + end_addr = (win->base_addr + win->win_size - 1); + alr = (uint32_t)((win->base_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + ahr = (uint32_t)((end_addr >> ADDRESS_SHIFT) & ADDRESS_MASK); + + mmio_write_32(IOB_WIN_ALR_OFFSET(win_id), alr); + mmio_write_32(IOB_WIN_AHR_OFFSET(win_id), ahr); + + iob_win_reg = WIN_ENABLE_BIT; + iob_win_reg |= (win->target_id & IOB_TARGET_ID_MASK) + << IOB_TARGET_ID_OFFSET; + mmio_write_32(IOB_WIN_CR_OFFSET(win_id), iob_win_reg); + +} + +#ifdef DEBUG_ADDR_MAP +static void dump_iob(void) +{ + uint32_t win_id, win_cr, alr, ahr; + uint8_t target_id; + uint64_t start, end; + char *iob_target_name[IOB_MAX_TID] = { + "CFG ", "MCI0 ", "PEX1 ", "PEX2 ", + "PEX0 ", "NAND ", "RUNIT", "MCI1 " }; + + /* Dump all IOB windows */ + printf("bank id target start end\n"); + printf("----------------------------------------------------\n"); + for (win_id = 0; win_id < MVEBU_IOB_MAX_WINS; win_id++) { + win_cr = mmio_read_32(IOB_WIN_CR_OFFSET(win_id)); + if (win_cr & WIN_ENABLE_BIT) { + target_id = (win_cr >> IOB_TARGET_ID_OFFSET) & + IOB_TARGET_ID_MASK; + alr = mmio_read_32(IOB_WIN_ALR_OFFSET(win_id)); + start = ((uint64_t)alr << ADDRESS_SHIFT); + if (win_id != 0) { + ahr = mmio_read_32(IOB_WIN_AHR_OFFSET(win_id)); + end = (((uint64_t)ahr + 0x10) << ADDRESS_SHIFT); + } else { + /* Window #0 size is hardcoded to 16MB, as it's + * reserved for CP configuration space. + */ + end = start + (16 << 20); + } + printf("iob %02d %s 0x%016" PRIx64 " 0x%016" PRIx64 "\n", + win_id, iob_target_name[target_id], + start, end); + } + } +} +#endif + +void iob_cfg_space_update(int ap_idx, int cp_idx, uintptr_t base, + uintptr_t new_base) +{ + debug_enter(); + + iob_base = base + MVEBU_IOB_OFFSET; + + NOTICE("Change the base address of AP%d-CP%d to %lx\n", + ap_idx, cp_idx, new_base); + mmio_write_32(IOB_WIN_ALR_OFFSET(0), new_base >> ADDRESS_SHIFT); + + iob_base = new_base + MVEBU_IOB_OFFSET; + + /* Make sure the address was configured by the CPU before + * any possible access to the CP. + */ + dsb(); + + debug_exit(); +} + +int init_iob(uintptr_t base) +{ + struct addr_map_win *win; + uint32_t win_id, win_reg; + uint32_t win_count; + + INFO("Initializing IOB Address decoding\n"); + + /* Get the base address of the address decoding MBUS */ + iob_base = base + MVEBU_IOB_OFFSET; + + /* Get the array of the windows and fill the map data */ + marvell_get_iob_memory_map(&win, &win_count, base); + if (win_count <= 0) { + INFO("no windows configurations found\n"); + return 0; + } else if (win_count > (MVEBU_IOB_MAX_WINS - 1)) { + ERROR("IOB mem map array > than max available windows (%d)\n", + MVEBU_IOB_MAX_WINS); + win_count = MVEBU_IOB_MAX_WINS; + } + + /* disable all IOB windows, start from win_id = 1 + * because can't disable internal register window + */ + for (win_id = 1; win_id < MVEBU_IOB_MAX_WINS; win_id++) { + win_reg = mmio_read_32(IOB_WIN_CR_OFFSET(win_id)); + win_reg &= ~WIN_ENABLE_BIT; + mmio_write_32(IOB_WIN_CR_OFFSET(win_id), win_reg); + + win_reg = ~IOB_WIN_ENA_CTRL_WRITE_SECURE; + win_reg &= ~IOB_WIN_ENA_CTRL_READ_SECURE; + win_reg &= ~IOB_WIN_ENA_WRITE_SECURE; + win_reg &= ~IOB_WIN_ENA_READ_SECURE; + mmio_write_32(IOB_WIN_SCR_OFFSET(win_id), win_reg); + } + + for (win_id = 1; win_id < win_count + 1; win_id++, win++) { + iob_win_check(win, win_id); + iob_enable_win(win, win_id); + } + +#ifdef DEBUG_ADDR_MAP + dump_iob(); +#endif + + INFO("Done IOB Address decoding Initializing\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c new file mode 100644 index 0000000..648bd0e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c @@ -0,0 +1,76 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include +#include + +#include + +#include "mc_trustzone.h" + +#define TZ_SIZE(x) ((x) >> 13) + +static int fls(int x) +{ + if (!x) + return 0; + + return 32 - __builtin_clz(x); +} + +/* To not duplicate types, the addr_map_win is used, but the "target" + * filed is referring to attributes instead of "target". + */ +void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id) +{ + int tz_size; + uint32_t val, base = win->base_addr; + + if ((win_id < 0) || (win_id > MVEBU_TZ_MAX_WINS)) { + ERROR("Enabling wrong MC TrustZone window %d!\n", win_id); + return; + } + + /* map the window size to trustzone register convention */ + tz_size = fls(TZ_SIZE(win->win_size)); + + VERBOSE("%s: window size = 0x%" PRIx64 " maps to tz_size %d\n", + __func__, win->win_size, tz_size); + if (tz_size < 0 || tz_size > 31) { + ERROR("Using not allowed size for MC TrustZone window %d!\n", + win_id); + return; + } + + if (base & 0xfff) { + base = base & ~0xfff; + WARN("Attempt to open MC TZ win. at 0x%" PRIx64 ", truncate to 0x%x\n", + win->base_addr, base); + } + + val = base | (tz_size << 7) | win->target_id | TZ_VALID; + + VERBOSE("%s: base 0x%x, tz_size moved 0x%x, attr 0x%x, val 0x%x\n", + __func__, base, (tz_size << 7), win->target_id, val); + + mmio_write_32(MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id), val); + + VERBOSE("%s: Win%d[0x%x] configured to 0x%x\n", __func__, win_id, + MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id), + mmio_read_32(MVEBU_AP_MC_TRUSTZONE_REG_LOW(ap_index, win_id))); + + mmio_write_32(MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id), + (win->base_addr >> 32)); + + VERBOSE("%s: Win%d[0x%x] configured to 0x%x\n", __func__, win_id, + MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id), + mmio_read_32(MVEBU_AP_MC_TRUSTZONE_REG_HIGH(ap_index, win_id))); +} diff --git a/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h new file mode 100644 index 0000000..296dce8 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h @@ -0,0 +1,27 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MC_TRUSTZONE_H +#define MC_TRUSTZONE_H + +#include + +#define MVEBU_TZ_MAX_WINS 16 + +#define TZ_VALID (1 << 0) +#define TZ_PERM(x) ((x) << 1) +#define TZ_RZ_ENABLE (1 << 3) + +/* tz attr definitions */ +#define TZ_PERM_RW (TZ_PERM(0)) +#define TZ_PERM_RO (TZ_PERM(1)) +#define TZ_PERM_WO (TZ_PERM(2)) +#define TZ_PERM_ABORT (TZ_PERM(3)) + +void tz_enable_win(int ap_index, const struct addr_map_win *win, int win_id); + +#endif /* MC_TRUSTZONE_H */ diff --git a/arm-trusted-firmware/drivers/marvell/mci.c b/arm-trusted-firmware/drivers/marvell/mci.c new file mode 100644 index 0000000..2b54700 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mci.c @@ -0,0 +1,834 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */ + +#include +#include +#include +#include + +#include +#include +#include + +/* /HB /Units /Direct_regs /Direct regs + * /Configuration Register Write/Read Data Register + */ +#define MCI_WRITE_READ_DATA_REG(mci_index) \ + MVEBU_MCI_REG_BASE_REMAP(mci_index) +/* /HB /Units /Direct_regs /Direct regs + * /Configuration Register Access Command Register + */ +#define MCI_ACCESS_CMD_REG(mci_index) \ + (MVEBU_MCI_REG_BASE_REMAP(mci_index) + 0x4) + +/* Access Command fields : + * bit[3:0] - Sub command: 1 => Peripheral Config Register Read, + * 0 => Peripheral Config Register Write, + * 2 => Peripheral Assign ID request, + * 3 => Circular Config Write + * bit[5] - 1 => Local (same chip access) 0 => Remote + * bit[15:8] - Destination hop ID. Put Global ID (GID) here (see scheme below). + * bit[23:22] - 0x3 IHB PHY REG address space, 0x0 IHB Controller space + * bit[21:16] - Low 6 bits of offset. Hight 2 bits are taken from bit[28:27] + * of IHB_PHY_CTRL + * (must be set before any PHY register access occurs): + * /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Version Control Register + * + * ixi_ihb_top IHB PHY + * AXI ----------------------------- ------------- + * <--| axi_hb_top | ihb_pipe_top |-->| | + * -->| GID=1 | GID=0 |<--| | + * ----------------------------- ------------- + */ +#define MCI_INDIRECT_CTRL_READ_CMD 0x1 +#define MCI_INDIRECT_CTRL_ASSIGN_CMD 0x2 +#define MCI_INDIRECT_CTRL_CIRCULAR_CMD 0x3 +#define MCI_INDIRECT_CTRL_LOCAL_PKT (1 << 5) +#define MCI_INDIRECT_CTRL_CMD_DONE_OFFSET 6 +#define MCI_INDIRECT_CTRL_CMD_DONE \ + (1 << MCI_INDIRECT_CTRL_CMD_DONE_OFFSET) +#define MCI_INDIRECT_CTRL_DATA_READY_OFFSET 7 +#define MCI_INDIRECT_CTRL_DATA_READY \ + (1 << MCI_INDIRECT_CTRL_DATA_READY_OFFSET) +#define MCI_INDIRECT_CTRL_HOPID_OFFSET 8 +#define MCI_INDIRECT_CTRL_HOPID(id) \ + (((id) & 0xFF) << MCI_INDIRECT_CTRL_HOPID_OFFSET) +#define MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET 16 +#define MCI_INDIRECT_REG_CTRL_ADDR(reg_num) \ + (reg_num << MCI_INDIRECT_CTRL_REG_CHIPID_OFFSET) + +/* Hop ID values */ +#define GID_IHB_PIPE 0 +#define GID_AXI_HB 1 +#define GID_IHB_EXT 2 + +#define MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG 0x2 +/* Target MCi Local ID (LID, which is = self DID) */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(val) (((val) & 0xFF) << 16) +/* Bits [15:8]: Number of MCis on chip of target MCi */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(val) (((val) & 0xFF) << 8) +/* Bits [7:0]: Number of hops on chip of target MCi */ +#define MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(val) (((val) & 0xFF) << 0) + +/* IHB_REG domain registers */ +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * Rx Memory Configuration Register (RX_MEM_CFG) + */ +#define MCI_CTRL_RX_MEM_CFG_REG_NUM 0x0 +#define MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(val) (((val) & 0xFF) << 24) +#define MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(val) (((val) & 0xFF) << 16) +#define MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(val) (((val) & 0xFF) << 8) +#define MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(val) (((val) & 0xF) << 4) +#define MCI_CTRL_RX_TX_MEM_CFG_RTC(val) (((val) & 0x3) << 2) +#define MCI_CTRL_RX_TX_MEM_CFG_WTC(val) (((val) & 0x3) << 0) +#define MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x07) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + +#define MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x03) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x3f) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(0xf) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * Tx Memory Configuration Register (TX_MEM_CFG) + */ +#define MCI_CTRL_TX_MEM_CFG_REG_NUM 0x1 +/* field mapping for TX mem config register + * are the same as for RX register - see register above + */ +#define MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL \ + (MCI_CTRL_RX_TX_MEM_CFG_RQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_PQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_NQ_THRESH(0x20) | \ + MCI_CTRL_RX_TX_MEM_CFG_DELTA_THRESH(2) | \ + MCI_CTRL_RX_TX_MEM_CFG_RTC(1) | \ + MCI_CTRL_RX_TX_MEM_CFG_WTC(1)) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Link CRC Control + */ +/* MCi Link CRC Control Register (MCi_CRC_CTRL) */ +#define MCI_LINK_CRC_CTRL_REG_NUM 0x4 + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Status Register + */ +/* MCi Status Register (MCi_STS) */ +#define MCI_CTRL_STATUS_REG_NUM 0x5 +#define MCI_CTRL_STATUS_REG_PHY_READY (1 << 12) +#define MCI_CTRL_STATUS_REG_LINK_PRESENT (1 << 15) +#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET 24 +#define MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK \ + (0xF << MCI_CTRL_STATUS_REG_PHY_CID_VIO_OFFSET) +/* Expected successful Link result, including reserved bit */ +#define MCI_CTRL_PHY_READY (MCI_CTRL_STATUS_REG_PHY_READY | \ + MCI_CTRL_STATUS_REG_LINK_PRESENT | \ + MCI_CTRL_STATUS_REG_PHY_CID_VIO_MASK) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers/ + * MCi PHY Speed Settings Register (MCi_PHY_SETTING) + */ +#define MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM 0x8 +#define MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(val) (((val) & 0xF) << 28) +#define MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(val) (((val) & 0xF) << 12) +#define MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(val) (((val) & 0xF) << 8) +#define MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(val) (((val) & 0xF) << 4) +#define MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(val) (((val) & 0x1) << 1) +#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL \ + (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x2) | \ + MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) +#define MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 \ + (MCI_CTRL_MCI_PHY_SET_DLO_FIFO_FULL_TRESH(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHY_MAX_SPEED(0x3) | \ + MCI_CTRL_MCI_PHY_SET_PHYCLK_SEL(0x5) | \ + MCI_CTRL_MCI_PHY_SET_REFCLK_FREQ_SEL(0x1)) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Mode Config + */ +#define MCI_CTRL_IHB_MODE_CFG_REG_NUM 0x25 +#define MCI_CTRL_IHB_MODE_HBCLK_DIV(val) ((val) & 0xFF) +#define MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET 8 +#define MCI_CTRL_IHB_MODE_CHUNK_MOD \ + (1 << MCI_CTRL_IHB_MODE_CHUNK_MOD_OFFSET) +#define MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET 9 +#define MCI_CTRL_IHB_MODE_FWD_MOD \ + (1 << MCI_CTRL_IHB_MODE_FWD_MOD_OFFSET) +#define MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(val) (((val) & 0xF) << 12) +#define MCI_CTRL_IHB_MODE_RX_COMB_THRESH(val) (((val) & 0xFF) << 16) +#define MCI_CTRL_IHB_MODE_TX_COMB_THRESH(val) (((val) & 0xFF) << 24) + +#define MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL \ + (MCI_CTRL_IHB_MODE_HBCLK_DIV(6) | \ + MCI_CTRL_IHB_MODE_FWD_MOD | \ + MCI_CTRL_IHB_MODE_SEQFF_FINE_MOD(0xF) | \ + MCI_CTRL_IHB_MODE_RX_COMB_THRESH(0x3f) | \ + MCI_CTRL_IHB_MODE_TX_COMB_THRESH(0x40)) +/* AXI_HB registers */ +#define MCI_AXI_ACCESS_DATA_REG_NUM 0x0 +#define MCI_AXI_ACCESS_PCIE_MODE 1 +#define MCI_AXI_ACCESS_CACHE_CHECK_OFFSET 5 +#define MCI_AXI_ACCESS_CACHE_CHECK \ + (1 << MCI_AXI_ACCESS_CACHE_CHECK_OFFSET) +#define MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET 6 +#define MCI_AXI_ACCESS_FORCE_POST_WR \ + (1 << MCI_AXI_ACCESS_FORCE_POST_WR_OFFSET) +#define MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET 9 +#define MCI_AXI_ACCESS_DISABLE_CLK_GATING \ + (1 << MCI_AXI_ACCESS_DISABLE_CLK_GATING_OFFSET) + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers + * /Window 0 Address Mask Register + */ +#define MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM 0x2 + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers + * /Window 0 Destination Register + */ +#define MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM 0x3 +#define MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(val) (((val) & 0x1) << 16) +#define MCI_HB_CTRL_WIN0_DEST_ID(val) (((val) & 0xFF) << 0) + +/* /HB /Units /HB_REG /HB_REGHopping Bus Registers /Tx Control Register */ +#define MCI_HB_CTRL_TX_CTRL_REG_NUM 0xD +#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET 24 +#define MCI_HB_CTRL_TX_CTRL_PCIE_MODE \ + (1 << MCI_HB_CTRL_TX_CTRL_PCIE_MODE_OFFSET) +#define MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(val) (((val) & 0xF) << 12) +#define MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(val) (((val) & 0x1F) << 6) +#define MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(val) (((val) & 0x1F) << 0) + +/* /HB /Units /IHB_REG /IHB_REGInterchip Hopping Bus Registers + * /IHB Version Control Register + */ +#define MCI_PHY_CTRL_REG_NUM 0x7 +#define MCI_PHY_CTRL_MCI_MINOR 0x8 /* BITS [3:0] */ +#define MCI_PHY_CTRL_MCI_MAJOR_OFFSET 4 +#define MCI_PHY_CTRL_MCI_MAJOR \ + (1 << MCI_PHY_CTRL_MCI_MAJOR_OFFSET) +#define MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET 11 +#define MCI_PHY_CTRL_MCI_SLEEP_REQ \ + (1 << MCI_PHY_CTRL_MCI_SLEEP_REQ_OFFSET) +/* Host=1 / Device=0 PHY mode */ +#define MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET 24 +#define MCI_PHY_CTRL_MCI_PHY_MODE_HOST \ + (1 << MCI_PHY_CTRL_MCI_PHY_MODE_OFFSET) +/* Register=1 / PWM=0 interface */ +#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET 25 +#define MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE \ + (1 << MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE_OFFSET) + /* PHY code InReset=1 */ +#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET 26 +#define MCI_PHY_CTRL_MCI_PHY_RESET_CORE \ + (1 << MCI_PHY_CTRL_MCI_PHY_RESET_CORE_OFFSET) +#define MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET 27 +#define MCI_PHY_CTRL_PHY_ADDR_MSB(addr) \ + (((addr) & 0x3) << \ + MCI_PHY_CTRL_PHY_ADDR_MSB_OFFSET) +#define MCI_PHY_CTRL_PIDI_MODE_OFFSET 31 +#define MCI_PHY_CTRL_PIDI_MODE \ + (1U << MCI_PHY_CTRL_PIDI_MODE_OFFSET) + +/* Number of times to wait for the MCI link ready after MCI configurations + * Normally takes 34-35 successive reads + */ +#define LINK_READY_TIMEOUT 100 + +enum mci_register_type { + MCI_REG_TYPE_PHY = 0, + MCI_REG_TYPE_CTRL, +}; + +enum { + MCI_CMD_WRITE, + MCI_CMD_READ +}; + +/* Write wrapper callback for debug: + * will print written data in case LOG_LEVEL >= 40 + */ +static void mci_mmio_write_32(uintptr_t addr, uint32_t value) +{ + VERBOSE("Write:\t0x%x = 0x%x\n", (uint32_t)addr, value); + mmio_write_32(addr, value); +} +/* Read wrapper callback for debug: + * will print read data in case LOG_LEVEL >= 40 + */ +static uint32_t mci_mmio_read_32(uintptr_t addr) +{ + uint32_t value; + + value = mmio_read_32(addr); + VERBOSE("Read:\t0x%x = 0x%x\n", (uint32_t)addr, value); + return value; +} + +/* MCI indirect access command completion polling: + * Each write/read command done via MCI indirect registers must be polled + * for command completions status. + * + * Returns 1 in case of error + * Returns 0 in case of command completed successfully. + */ +static int mci_poll_command_completion(int mci_index, int command_type) +{ + uint32_t mci_cmd_value = 0, retry_count = 100, ret = 0; + uint32_t completion_flags = MCI_INDIRECT_CTRL_CMD_DONE; + + debug_enter(); + /* Read commands require validating that requested data is ready */ + if (command_type == MCI_CMD_READ) + completion_flags |= MCI_INDIRECT_CTRL_DATA_READY; + + do { + /* wait 1 ms before each polling */ + mdelay(1); + mci_cmd_value = mci_mmio_read_32(MCI_ACCESS_CMD_REG(mci_index)); + } while (((mci_cmd_value & completion_flags) != completion_flags) && + (retry_count-- > 0)); + + if (retry_count == 0) { + ERROR("%s: MCI command timeout (command status = 0x%x)\n", + __func__, mci_cmd_value); + ret = 1; + } + + debug_exit(); + return ret; +} + +int mci_read(int mci_idx, uint32_t cmd, uint32_t *value) +{ + int rval; + + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); + + rval = mci_poll_command_completion(mci_idx, MCI_CMD_READ); + + *value = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_idx)); + + return rval; +} + +int mci_write(int mci_idx, uint32_t cmd, uint32_t data) +{ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_idx), data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_idx), cmd); + + return mci_poll_command_completion(mci_idx, MCI_CMD_WRITE); +} + +/* Perform 3 configurations in one command: PCI mode, + * queues separation and cache bit + */ +static int mci_axi_set_pcie_mode(int mci_index) +{ + uint32_t reg_data, ret = 1; + + debug_enter(); + /* This configuration makes MCI IP behave consistently with AXI protocol + * It should be configured at one side only (for example locally at AP). + * The IP takes care of performing the same configurations at MCI on + * another side (for example remotely at CP). + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_AXI_ACCESS_PCIE_MODE | + MCI_AXI_ACCESS_CACHE_CHECK | + MCI_AXI_ACCESS_FORCE_POST_WR | + MCI_AXI_ACCESS_DISABLE_CLK_GATING); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_AXI_ACCESS_DATA_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_CIRCULAR_CMD); + + /* if Write command was successful, verify PCIe mode */ + if (mci_poll_command_completion(mci_index, MCI_CMD_WRITE) == 0) { + /* Verify the PCIe mode selected */ + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_READ_CMD); + /* if read was completed, verify PCIe mode */ + if (mci_poll_command_completion(mci_index, MCI_CMD_READ) == 0) { + reg_data = mci_mmio_read_32( + MCI_WRITE_READ_DATA_REG(mci_index)); + if (reg_data & MCI_HB_CTRL_TX_CTRL_PCIE_MODE) + ret = 0; + } + } + + debug_exit(); + return ret; +} + +/* Reduce sequence FIFO timer expiration threshold */ +static int mci_axi_set_fifo_thresh(int mci_index) +{ + uint32_t reg_data, ret = 0; + + debug_enter(); + /* This configuration reduces sequence FIFO timer expiration threshold + * (to 0x7 instead of 0xA). + * In MCI 1.6 version this configuration prevents possible functional + * issues. + * In version 1.82 the configuration prevents performance degradation + */ + + /* Configure local AP side */ + reg_data = MCI_PHY_CTRL_PIDI_MODE | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Reduce the threshold */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); + + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_IHB_MODE_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Exit PIDI mode */ + reg_data = MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Configure remote CP side */ + reg_data = MCI_PHY_CTRL_PIDI_MODE | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_CTRL_IHB_MODE_FWD_MOD); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Reduce the threshold */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_IHB_MODE_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_IHB_MODE_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Exit PIDI mode */ + reg_data = MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_PHY_REG_IF_MODE; + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), reg_data); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_CTRL_IHB_MODE_FWD_MOD); + + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* Configure: + * 1. AP & CP TX thresholds and delta configurations + * 2. DLO & DLI FIFO full threshold + * 3. RX thresholds and delta configurations + * 4. CP AR and AW outstanding + * 5. AP AR and AW outstanding + */ +static int mci_axi_set_fifo_rx_tx_thresh(int mci_index) +{ + uint32_t ret = 0; + + debug_enter(); + /* AP TX thresholds and delta configurations (IHB_reg 0x1) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_TX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP TX thresholds and delta configurations (IHB_reg 0x1) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_TX_MEM_CFG_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_TX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP DLO & DLI FIFO full threshold & Auto-Link enable (IHB_reg 0x8) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP DLO & DLI FIFO full threshold (IHB_reg 0x8) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP RX thresholds and delta configurations (IHB_reg 0x0) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_RX_MEM_CFG_REG_DEF_AP_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_RX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP RX thresholds and delta configurations (IHB_reg 0x0) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_CTRL_RX_MEM_CFG_REG_DEF_CP_VAL); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_CTRL_RX_MEM_CFG_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* AP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | + MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(3) | + MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(3)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* CP AR & AW maximum AXI outstanding request cfg (HB_reg 0xd) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_TX_CTRL_PRI_TH_QOS(8) | + MCI_HB_CTRL_TX_CTRL_MAX_RD_CNT(0xB) | + MCI_HB_CTRL_TX_CTRL_MAX_WR_CNT(0x11)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_TX_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* configure MCI to allow read & write transactions to arrive at the same time. + * Without the below configuration, MCI won't sent response to CPU for + * transactions which arrived simultaneously and will lead to CPU hang. + * The below will configure MCI to be able to pass transactions from/to CP/AP. + */ +static int mci_enable_simultaneous_transactions(int mci_index) +{ + uint32_t ret = 0; + + debug_enter(); + /* ID assignment (assigning global ID offset to CP) */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_DID_GLOBAL_ASSIGN_REQ_MCI_LOCAL_ID(2) | + MCI_DID_GLOBAL_ASSIGN_REQ_MCI_COUNT(2) | + MCI_DID_GLOBAL_ASSIGN_REQ_HOPS_NUM(2)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_DID_GLOBAL_ASSIGNMENT_REQUEST_REG) | + MCI_INDIRECT_CTRL_ASSIGN_CMD); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Assigning dest. ID=3 to all transactions entering from AXI at AP */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | + MCI_HB_CTRL_WIN0_DEST_ID(3)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* Assigning dest. ID=1 to all transactions entering from AXI at CP */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), + MCI_HB_CTRL_WIN0_DEST_VALID_FLAG(1) | + MCI_HB_CTRL_WIN0_DEST_ID(1)); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* End address to all transactions entering from AXI at AP. + * This will lead to get match for any AXI address + * and receive destination ID=3 + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + /* End address to all transactions entering from AXI at CP. + * This will lead to get match for any AXI address + * and receive destination ID=1 + */ + mci_mmio_write_32(MCI_WRITE_READ_DATA_REG(mci_index), 0xffffffff); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_ADDRESS_MASK_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_IHB_EXT) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB)); + ret |= mci_poll_command_completion(mci_index, MCI_CMD_WRITE); + + debug_exit(); + return ret; +} + +/* Check if MCI simultaneous transaction was already enabled. + * Currently bootrom does this mci configuration only when the boot source is + * SAR_MCIX4, in other cases it should be done at this stage. + * It is worth noticing that in case of booting from uart, the bootrom + * flow is different and this mci initialization is skipped even if boot + * source is SAR_MCIX4. Therefore new verification bases on appropriate mci's + * register content: if the appropriate reg contains 0x0 it means that the + * bootrom didn't perform required mci configuration. + * + * Returns: + * 0 - configuration already done + * 1 - configuration missing + */ +static _Bool mci_simulatenous_trans_missing(int mci_index) +{ + uint32_t reg, ret; + + /* read 'Window 0 Destination ID assignment' from HB register 0x3 + * (TX_CFG_W0_DST_ID) to check whether ID assignment was already + * performed by BootROM. + */ + debug_enter(); + mci_mmio_write_32(MCI_ACCESS_CMD_REG(mci_index), + MCI_INDIRECT_REG_CTRL_ADDR( + MCI_HB_CTRL_WIN0_DESTINATION_REG_NUM) | + MCI_INDIRECT_CTRL_HOPID(GID_AXI_HB) | + MCI_INDIRECT_CTRL_LOCAL_PKT | + MCI_INDIRECT_CTRL_READ_CMD); + ret = mci_poll_command_completion(mci_index, MCI_CMD_READ); + + reg = mci_mmio_read_32(MCI_WRITE_READ_DATA_REG(mci_index)); + + if (ret) + ERROR("Failed to verify MCI simultaneous read/write status\n"); + + debug_exit(); + /* default ID assignment is 0, so if register doesn't contain zeros + * it means that bootrom already performed required configuration. + */ + if (reg != 0) + return 0; + + return 1; +} + +/* For A1 revision, configure the MCI link for performance improvement: + * - set MCI to support read/write transactions to arrive at the same time + * - Switch AXI to PCIe mode + * - Reduce sequence FIFO threshold + * - Configure RX/TX FIFO thresholds + * + * Note: + * We don't exit on error code from any sub routine, to try (best effort) to + * complete the MCI configuration. + * (If we exit - Bootloader will surely fail to boot) + */ +int mci_configure(int mci_index) +{ + int rval; + + debug_enter(); + /* According to design guidelines the MCI simultaneous transaction + * shouldn't be enabled more then once - therefore make sure that it + * wasn't already enabled in bootrom. + */ + if (mci_simulatenous_trans_missing(mci_index)) { + VERBOSE("Enabling MCI simultaneous transaction for mci%d\n", + mci_index); + /* set MCI to support read/write transactions + * to arrive at the same time + */ + rval = mci_enable_simultaneous_transactions(mci_index); + if (rval) + ERROR("Failed to set MCI simultaneous read/write\n"); + } else + VERBOSE("Skip MCI ID assignment - already done by bootrom\n"); + + /* Configure MCI for more consistent behavior with AXI protocol */ + rval = mci_axi_set_pcie_mode(mci_index); + if (rval) + ERROR("Failed to set MCI to AXI PCIe mode\n"); + + /* reduce FIFO global threshold */ + rval = mci_axi_set_fifo_thresh(mci_index); + if (rval) + ERROR("Failed to set MCI FIFO global threshold\n"); + + /* configure RX/TX FIFO thresholds */ + rval = mci_axi_set_fifo_rx_tx_thresh(mci_index); + if (rval) + ERROR("Failed to set MCI RX/TX FIFO threshold\n"); + + debug_exit(); + return 1; +} + +int mci_get_link_status(void) +{ + uint32_t cmd, data; + + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT | MCI_INDIRECT_CTRL_READ_CMD); + if (mci_read(0, cmd, &data)) { + ERROR("Failed to read status register\n"); + return -1; + } + + /* Check if the link is ready */ + if (data != MCI_CTRL_PHY_READY) { + ERROR("Bad link status %x\n", data); + return -1; + } + + return 0; +} + +void mci_turn_link_down(void) +{ + uint32_t cmd, data; + int rval = 0; + + debug_enter(); + + /* Turn off auto-link */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(0)); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to turn off auto-link\n"); + + /* Reset AP PHY */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_PHY_CTRL_MCI_MINOR | + MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST | + MCI_PHY_CTRL_MCI_PHY_RESET_CORE); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to reset AP PHY\n"); + + /* Clear all status & CRC values */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_LINK_CRC_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = 0x0; + mci_write(0, cmd, data); + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_STATUS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = 0x0; + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to reset AP PHY\n"); + + /* Wait 5ms before un-reset the PHY */ + mdelay(5); + + /* Un-reset AP PHY */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_PHY_CTRL_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_PHY_CTRL_MCI_MINOR | MCI_PHY_CTRL_MCI_MAJOR | + MCI_PHY_CTRL_MCI_PHY_MODE_HOST); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to un-reset AP PHY\n"); + + debug_exit(); +} + +void mci_turn_link_on(void) +{ + uint32_t cmd, data; + int rval = 0; + + debug_enter(); + /* Turn on auto-link */ + cmd = (MCI_INDIRECT_REG_CTRL_ADDR(MCI_CTRL_MCI_PHY_SETTINGS_REG_NUM) | + MCI_INDIRECT_CTRL_LOCAL_PKT); + data = (MCI_CTRL_MCI_PHY_SET_REG_DEF_VAL2 | + MCI_CTRL_MCI_PHY_SET_AUTO_LINK_EN(1)); + rval = mci_write(0, cmd, data); + if (rval) + ERROR("Failed to turn on auto-link\n"); + + debug_exit(); +} + +/* Initialize MCI for performance improvements */ +int mci_link_tune(int mci_index) +{ + int ret; + + debug_enter(); + INFO("MCI%d initialization:\n", mci_index); + + ret = mci_configure(mci_index); + + debug_exit(); + return ret; +} diff --git a/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c new file mode 100644 index 0000000..98e1896 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include + +/* CONFI REGISTERS */ +#define MG_CM3_CONFI_BASE(CP) (MVEBU_CP_REGS_BASE(CP) + 0x100000) +#define MG_CM3_SRAM_BASE(CP) MG_CM3_CONFI_BASE(CP) +#define MG_CM3_CONFI_GLOB_CFG_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B500) +#define CM3_CPU_EN_BIT BIT(28) +#define MG_CM3_MG_INT_MFX_REG(CP) (MG_CM3_CONFI_BASE(CP) + 0x2B054) +#define CM3_SYS_RESET_BIT BIT(0) + +#define MG_CM3_SHARED_MEM_BASE(CP) (MG_CM3_SRAM_BASE(CP) + 0x1FC00ULL) + +#define MG_SRAM_SIZE 0x20000 /* 128KB */ + +#define MG_ACK_TIMEOUT 10 + +/** + * struct ap_sharedmem_ctrl - used to pass information between the HOST and CM3 + * @init_done: Set by CM3 when ap_proces initialzied. Host check if CM3 set + * this flag to confirm that the process is running + * @lane_nr: Set by Host to mark which comphy lane should be configure. E.g.: + * - A8K development board uses comphy lane 2 for eth0 + * - CN913x development board uses comphy lane 4 for eth0 + */ +struct ap_sharedmem_ctrl { + uint32_t init_done; + uint32_t lane_nr; +}; + +int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index) +{ + uintptr_t mg_regs = MG_CM3_SRAM_BASE(cp_index); + + if (size > MG_SRAM_SIZE) { + ERROR("image is too big to fit into MG CM3 memory\n"); + return 1; + } + + NOTICE("Loading MG image from address 0x%lx Size 0x%x to MG at 0x%lx\n", + src_addr, size, mg_regs); + + /* Copy image to MG CM3 SRAM */ + memcpy((void *)mg_regs, (void *)src_addr, size); + + /* Don't release MG CM3 from reset - it will be done by next step + * bootloader (e.g. U-Boot), when appriopriate device-tree setup (which + * has enabeld 802.3. auto-neg) will be choosen. + */ + + return 0; +} + +void mg_start_ap_fw(int cp_nr, uint8_t comphy_index) +{ + volatile struct ap_sharedmem_ctrl *ap_shared_ctrl = + (void *)MG_CM3_SHARED_MEM_BASE(cp_nr); + int timeout = MG_ACK_TIMEOUT; + + if (mmio_read_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr)) & CM3_CPU_EN_BIT) { + VERBOSE("cm3 already running\n"); + return; /* cm3 already running */ + } + + /* + * Mark which comphy lane should be used - it will be read via shared + * mem by ap process + */ + ap_shared_ctrl->lane_nr = comphy_index; + /* Make sure it took place before enabling cm3 */ + dmbst(); + + mmio_setbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), CM3_CPU_EN_BIT); + mmio_setbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), CM3_SYS_RESET_BIT); + + /* Check for ap process initialization by fw */ + while (ap_shared_ctrl->init_done != 1 && timeout--) + VERBOSE("Waiting for ap process ack, timeout %d\n", timeout); + + if (timeout == 0) { + ERROR("AP process failed, disabling cm3\n"); + mmio_clrbits_32(MG_CM3_MG_INT_MFX_REG(cp_nr), + CM3_SYS_RESET_BIT); + mmio_clrbits_32(MG_CM3_CONFI_GLOB_CFG_REG(cp_nr), + CM3_CPU_EN_BIT); + } +} diff --git a/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h new file mode 100644 index 0000000..e2756de --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +void mg_start_ap_fw(int cp_nr, uint8_t comphy_index); +int mg_image_load(uintptr_t src_addr, uint32_t size, int cp_index); diff --git a/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c new file mode 100644 index 0000000..75e9654 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c @@ -0,0 +1,339 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP807 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10) +#define SMMU_sACR_PG_64K (1 << 16) + +#define CCU_GSPMU_CR (MVEBU_CCU_BASE(MVEBU_AP0) \ + + 0x3F0) +#define GSPMU_CPU_CONTROL (0x1 << 0) + +#define CCU_HTC_CR (MVEBU_CCU_BASE(MVEBU_AP0) \ + + 0x200) +#define CCU_SET_POC_OFFSET 5 + +#define DSS_CR0 (MVEBU_RFU_BASE + 0x100) +#define DVM_48BIT_VA_ENABLE (1 << 21) + + +/* SoC RFU / IHBx4 Control */ +#define MCIX4_807_REG_START_ADDR_REG(unit_id) (MVEBU_RFU_BASE + \ + 0x4258 + (unit_id * 0x4)) + +/* Secure MoChi incoming access */ +#define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738) +#define SEC_MOCHI_IN_ACC_IHB0_EN (1) +#define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3) +#define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6) +#define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9) +#define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \ + SEC_MOCHI_IN_ACC_IHB1_EN | \ + SEC_MOCHI_IN_ACC_IHB2_EN | \ + SEC_MOCHI_IN_ACC_PIDI_EN) +#define MOCHI_IN_ACC_LEVEL_FORCE_NONSEC (0) +#define MOCHI_IN_ACC_LEVEL_FORCE_SEC (1) +#define MOCHI_IN_ACC_LEVEL_LEAVE_ORIG (2) +#define MOCHI_IN_ACC_LEVEL_MASK_ALL (3) +#define SEC_MOCHI_IN_ACC_IHB0_LEVEL(l) ((l) << 1) +#define SEC_MOCHI_IN_ACC_IHB1_LEVEL(l) ((l) << 4) +#define SEC_MOCHI_IN_ACC_PIDI_LEVEL(l) ((l) << 10) + + +/* SYSRST_OUTn Config definitions */ +#define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4) +#define WD_MASK_SYS_RST_OUT (1 << 2) + +/* DSS PHY for DRAM */ +#define DSS_SCR_REG (MVEBU_RFU_BASE + 0x208) +#define DSS_PPROT_OFFS 4 +#define DSS_PPROT_MASK 0x7 +#define DSS_PPROT_PRIV_SECURE_DATA 0x1 + +/* Used for Units of AP-807 (e.g. SDIO and etc) */ +#define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \ + 0x4 * index) + +#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000) +#define XOR_STREAM_ID_MASK 0xFFFF +#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600) +#define SDIO_STREAM_ID_MASK 0xFF + +/* Do not use the default Stream ID 0 */ +#define A807_STREAM_ID_BASE (0x1) + +static uintptr_t stream_id_reg[] = { + XOR_STREAM_ID_REG(0), + XOR_STREAM_ID_REG(1), + XOR_STREAM_ID_REG(2), + XOR_STREAM_ID_REG(3), + SDIO_STREAM_ID_REG, + 0 +}; + +enum axi_attr { + AXI_SDIO_ATTR = 0, + AXI_DFX_ATTR, + AXI_MAX_ATTR, +}; + +static void ap_sec_masters_access_en(uint32_t enable) +{ + /* Open/Close incoming access for all masters. + * The access is disabled in trusted boot mode + * Could only be done in EL3 + */ + if (enable != 0) { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, 0x0U, /* no clear */ + SEC_IN_ACCESS_ENA_ALL_MASTERS); +#if LLC_SRAM + /* Do not change access security level + * for PIDI masters + */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_LEAVE_ORIG)); +#endif + } else { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_IN_ACCESS_ENA_ALL_MASTERS, + 0x0U /* no set */); +#if LLC_SRAM + /* Return PIDI access level to the default */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_FORCE_NONSEC)); +#endif + } +} + +static void setup_smmu(void) +{ + uint32_t reg; + + /* Set the SMMU page size to 64 KB */ + reg = mmio_read_32(SMMU_sACR); + reg |= SMMU_sACR_PG_64K; + mmio_write_32(SMMU_sACR, reg); +} + +static void init_aurora2(void) +{ + uint32_t reg; + + /* Enable GSPMU control by CPU */ + reg = mmio_read_32(CCU_GSPMU_CR); + reg |= GSPMU_CPU_CONTROL; + mmio_write_32(CCU_GSPMU_CR, reg); + +#if LLC_ENABLE + /* Enable LLC for AP807 in exclusive mode */ + llc_enable(0, 1); + + /* Set point of coherency to DDR. + * This is required by units which have + * SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR, reg); +#endif /* LLC_ENABLE */ + + errata_wa_init(); +} + + +/* MCIx indirect access register are based by default at 0xf4000000/0xf6000000 + * to avoid conflict of internal registers of units connected via MCIx, which + * can be based on the same address (i.e CP1 base is also 0xf4000000), + * the following routines remaps the MCIx indirect bases to another domain + */ +static void mci_remap_indirect_access_base(void) +{ + uint32_t mci; + + for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++) + mmio_write_32(MCIX4_807_REG_START_ADDR_REG(mci), + MVEBU_MCI_REG_BASE_REMAP(mci) >> + MCI_REMAP_OFF_SHIFT); +} + +/* Set a unique stream id for all DMA capable devices */ +static void ap807_stream_id_init(void) +{ + uint32_t i; + + for (i = 0; + stream_id_reg[i] != 0 && i < ARRAY_SIZE(stream_id_reg); i++) { + uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ? + SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK; + + mmio_clrsetbits_32(stream_id_reg[i], mask, + i + A807_STREAM_ID_BASE); + } +} + +static void ap807_axi_attr_init(void) +{ + uint32_t index, data; + + /* Initialize AXI attributes for AP807 */ + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable. + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(MVEBU_AXI_ATTR_REG(index), data); + } + } +} + +static void misc_soc_configurations(void) +{ + uint32_t reg; + + /* Enable 48-bit VA */ + mmio_setbits_32(DSS_CR0, DVM_48BIT_VA_ENABLE); + + /* Un-mask Watchdog reset from influencing the SYSRST_OUTn. + * Otherwise, upon WD timeout, the WD reset signal won't trigger reset + */ + reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG); + reg &= ~(WD_MASK_SYS_RST_OUT); + mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg); +} + +/* + * By default all external CPs start with configuration address space set to + * 0xf200_0000. To overcome this issue, go in the loop and initialize the + * CP one by one, using temporary window configuration which allows to access + * each CP and update its configuration space according to decoding + * windows scheme defined for each platform. + */ +void update_cp110_default_win(int cp_id) +{ + int mci_id = cp_id - 1; + uintptr_t cp110_base, cp110_temp_base; + + /* CP110 default configuration address space */ + cp110_temp_base = MVEBU_AP_IO_BASE(MVEBU_AP0); + + struct addr_map_win iowin_temp_win = { + .base_addr = cp110_temp_base, + .win_size = MVEBU_CP_OFFSET, + }; + + iowin_temp_win.target_id = mci_id; + iow_temp_win_insert(0, &iowin_temp_win, 1); + + /* Calculate the new CP110 - base address */ + cp110_base = MVEBU_CP_REGS_BASE(cp_id); + /* Go and update the CP110 configuration address space */ + iob_cfg_space_update(0, cp_id, cp110_temp_base, cp110_base); + + /* Remove the temporary IO-WIN window */ + iow_temp_win_remove(0, &iowin_temp_win, 1); +} + +void ap_init(void) +{ + /* Setup Aurora2. */ + init_aurora2(); + + /* configure MCI mapping */ + mci_remap_indirect_access_base(); + + /* configure IO_WIN windows */ + init_io_win(MVEBU_AP0); + + /* configure CCU windows */ + init_ccu(MVEBU_AP0); + + /* Set the stream IDs for DMA masters */ + ap807_stream_id_init(); + + /* configure the SMMU */ + setup_smmu(); + + /* Open AP incoming access for all masters */ + ap_sec_masters_access_en(1); + + /* configure axi for AP */ + ap807_axi_attr_init(); + + /* misc configuration of the SoC */ + misc_soc_configurations(); +} + +static void ap807_dram_phy_access_config(void) +{ + uint32_t reg_val; + /* Update DSS port access permission to DSS_PHY */ + reg_val = mmio_read_32(DSS_SCR_REG); + reg_val &= ~(DSS_PPROT_MASK << DSS_PPROT_OFFS); + reg_val |= ((DSS_PPROT_PRIV_SECURE_DATA & DSS_PPROT_MASK) << + DSS_PPROT_OFFS); + mmio_write_32(DSS_SCR_REG, reg_val); +} + +void ap_ble_init(void) +{ + /* Enable DSS port */ + ap807_dram_phy_access_config(); +} + +int ap_get_count(void) +{ + return 1; +} + + diff --git a/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c new file mode 100644 index 0000000..5c71fed --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP806 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define SMMU_sACR (MVEBU_SMMU_BASE + 0x10) +#define SMMU_sACR_PG_64K (1 << 16) + +#define CCU_GSPMU_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x3F0) +#define GSPMU_CPU_CONTROL (0x1 << 0) + +#define CCU_HTC_CR (MVEBU_CCU_BASE(MVEBU_AP0) + \ + 0x200) +#define CCU_SET_POC_OFFSET 5 + +#define DSS_CR0 (MVEBU_RFU_BASE + 0x100) +#define DVM_48BIT_VA_ENABLE (1 << 21) + +/* Secure MoChi incoming access */ +#define SEC_MOCHI_IN_ACC_REG (MVEBU_RFU_BASE + 0x4738) +#define SEC_MOCHI_IN_ACC_IHB0_EN (1) +#define SEC_MOCHI_IN_ACC_IHB1_EN (1 << 3) +#define SEC_MOCHI_IN_ACC_IHB2_EN (1 << 6) +#define SEC_MOCHI_IN_ACC_PIDI_EN (1 << 9) +#define SEC_IN_ACCESS_ENA_ALL_MASTERS (SEC_MOCHI_IN_ACC_IHB0_EN | \ + SEC_MOCHI_IN_ACC_IHB1_EN | \ + SEC_MOCHI_IN_ACC_IHB2_EN | \ + SEC_MOCHI_IN_ACC_PIDI_EN) +#define MOCHI_IN_ACC_LEVEL_FORCE_NONSEC (0) +#define MOCHI_IN_ACC_LEVEL_FORCE_SEC (1) +#define MOCHI_IN_ACC_LEVEL_LEAVE_ORIG (2) +#define MOCHI_IN_ACC_LEVEL_MASK_ALL (3) +#define SEC_MOCHI_IN_ACC_IHB0_LEVEL(l) ((l) << 1) +#define SEC_MOCHI_IN_ACC_IHB1_LEVEL(l) ((l) << 4) +#define SEC_MOCHI_IN_ACC_PIDI_LEVEL(l) ((l) << 10) + + +/* SYSRST_OUTn Config definitions */ +#define MVEBU_SYSRST_OUT_CONFIG_REG (MVEBU_MISC_SOC_BASE + 0x4) +#define WD_MASK_SYS_RST_OUT (1 << 2) + +/* Generic Timer System Controller */ +#define MVEBU_MSS_GTCR_REG (MVEBU_REGS_BASE + 0x581000) +#define MVEBU_MSS_GTCR_ENABLE_BIT 0x1 + +/* + * AXI Configuration. + */ + +/* Used for Units of AP-806 (e.g. SDIO and etc) */ +#define MVEBU_AXI_ATTR_BASE (MVEBU_REGS_BASE + 0x6F4580) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_BASE + \ + 0x4 * index) + +#define XOR_STREAM_ID_REG(ch) (MVEBU_REGS_BASE + 0x410010 + (ch) * 0x20000) +#define XOR_STREAM_ID_MASK 0xFFFF +#define SDIO_STREAM_ID_REG (MVEBU_RFU_BASE + 0x4600) +#define SDIO_STREAM_ID_MASK 0xFF + +/* Do not use the default Stream ID 0 */ +#define A806_STREAM_ID_BASE (0x1) + +static uintptr_t stream_id_reg[] = { + XOR_STREAM_ID_REG(0), + XOR_STREAM_ID_REG(1), + XOR_STREAM_ID_REG(2), + XOR_STREAM_ID_REG(3), + SDIO_STREAM_ID_REG, + 0 +}; + +enum axi_attr { + AXI_SDIO_ATTR = 0, + AXI_DFX_ATTR, + AXI_MAX_ATTR, +}; + +static void apn_sec_masters_access_en(uint32_t enable) +{ + /* Open/Close incoming access for all masters. + * The access is disabled in trusted boot mode + * Could only be done in EL3 + */ + if (enable != 0) { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, 0x0U, /* no clear */ + SEC_IN_ACCESS_ENA_ALL_MASTERS); +#if LLC_SRAM + /* Do not change access security level + * for PIDI masters + */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_LEAVE_ORIG)); +#endif + } else { + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_IN_ACCESS_ENA_ALL_MASTERS, + 0x0U /* no set */); +#if LLC_SRAM + /* Return PIDI access level to the default */ + mmio_clrsetbits_32(SEC_MOCHI_IN_ACC_REG, + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_MASK_ALL), + SEC_MOCHI_IN_ACC_PIDI_LEVEL( + MOCHI_IN_ACC_LEVEL_FORCE_NONSEC)); +#endif + } +} + +static void setup_smmu(void) +{ + uint32_t reg; + + /* Set the SMMU page size to 64 KB */ + reg = mmio_read_32(SMMU_sACR); + reg |= SMMU_sACR_PG_64K; + mmio_write_32(SMMU_sACR, reg); +} + +static void init_aurora2(void) +{ + uint32_t reg; + + /* Enable GSPMU control by CPU */ + reg = mmio_read_32(CCU_GSPMU_CR); + reg |= GSPMU_CPU_CONTROL; + mmio_write_32(CCU_GSPMU_CR, reg); + +#if LLC_ENABLE + /* Enable LLC for AP806 in exclusive mode */ + llc_enable(0, 1); + + /* Set point of coherency to DDR. + * This is required by units which have + * SW cache coherency + */ + reg = mmio_read_32(CCU_HTC_CR); + reg |= (0x1 << CCU_SET_POC_OFFSET); + mmio_write_32(CCU_HTC_CR, reg); +#endif /* LLC_ENABLE */ + + errata_wa_init(); +} + + +/* MCIx indirect access register are based by default at 0xf4000000/0xf6000000 + * to avoid conflict of internal registers of units connected via MCIx, which + * can be based on the same address (i.e CP1 base is also 0xf4000000), + * the following routines remaps the MCIx indirect bases to another domain + */ +static void mci_remap_indirect_access_base(void) +{ + uint32_t mci; + + for (mci = 0; mci < MCI_MAX_UNIT_ID; mci++) + mmio_write_32(MCIX4_REG_START_ADDRESS_REG(mci), + MVEBU_MCI_REG_BASE_REMAP(mci) >> + MCI_REMAP_OFF_SHIFT); +} + +/* Set a unique stream id for all DMA capable devices */ +static void ap806_stream_id_init(void) +{ + int i; + + for (i = 0; stream_id_reg[i] != 0; i++) { + uint32_t mask = stream_id_reg[i] == SDIO_STREAM_ID_REG ? + SDIO_STREAM_ID_MASK : XOR_STREAM_ID_MASK; + + mmio_clrsetbits_32(stream_id_reg[i], mask, + i + A806_STREAM_ID_BASE); + } +} + +static void apn806_axi_attr_init(void) +{ + uint32_t index, data; + + /* Initialize AXI attributes for APN806 */ + + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(MVEBU_AXI_ATTR_REG(index), data); + } + } +} + +static void dss_setup(void) +{ + /* Enable 48-bit VA */ + mmio_setbits_32(DSS_CR0, DVM_48BIT_VA_ENABLE); +} + +void misc_soc_configurations(void) +{ + uint32_t reg; + + /* Un-mask Watchdog reset from influencing the SYSRST_OUTn. + * Otherwise, upon WD timeout, the WD reset signal won't trigger reset + */ + reg = mmio_read_32(MVEBU_SYSRST_OUT_CONFIG_REG); + reg &= ~(WD_MASK_SYS_RST_OUT); + mmio_write_32(MVEBU_SYSRST_OUT_CONFIG_REG, reg); +} + +void ap_init(void) +{ + /* Setup Aurora2. */ + init_aurora2(); + + /* configure MCI mapping */ + mci_remap_indirect_access_base(); + + /* configure IO_WIN windows */ + init_io_win(MVEBU_AP0); + + /* configure CCU windows */ + init_ccu(MVEBU_AP0); + + /* configure DSS */ + dss_setup(); + + /* Set the stream IDs for DMA masters */ + ap806_stream_id_init(); + + /* configure the SMMU */ + setup_smmu(); + + /* Open APN incoming access for all masters */ + apn_sec_masters_access_en(1); + + /* configure axi for APN*/ + apn806_axi_attr_init(); + + /* misc configuration of the SoC */ + misc_soc_configurations(); +} + +void ap_ble_init(void) +{ +} + +int ap_get_count(void) +{ + return 1; +} + +void update_cp110_default_win(int cp_id) +{ +} diff --git a/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c b/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c new file mode 100644 index 0000000..f12da0e --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c @@ -0,0 +1,467 @@ +/* + * Copyright (C) 2018-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CP110 Marvell SoC driver */ + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * AXI Configuration. + */ + + /* Used for Units of CP-110 (e.g. USB device, USB Host, and etc) */ +#define MVEBU_AXI_ATTR_OFFSET (0x441300) +#define MVEBU_AXI_ATTR_REG(index) (MVEBU_AXI_ATTR_OFFSET + \ + 0x4 * index) + +/* AXI Protection bits */ +#define MVEBU_AXI_PROT_OFFSET (0x441200) + +/* AXI Protection regs */ +#define MVEBU_AXI_PROT_REG(index) ((index <= 4) ? \ + (MVEBU_AXI_PROT_OFFSET + \ + 0x4 * index) : \ + (MVEBU_AXI_PROT_OFFSET + 0x18)) +#define MVEBU_AXI_PROT_REGS_NUM (6) + +#define MVEBU_SOC_CFGS_OFFSET (0x441900) +#define MVEBU_SOC_CFG_REG(index) (MVEBU_SOC_CFGS_OFFSET + \ + 0x4 * index) +#define MVEBU_SOC_CFG_REG_NUM (0) +#define MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK (0xE) + +/* SATA3 MBUS to AXI regs */ +#define MVEBU_BRIDGE_WIN_DIS_REG (MVEBU_SOC_CFGS_OFFSET + 0x10) +#define MVEBU_BRIDGE_WIN_DIS_OFF (0x0) + +/* SATA3 MBUS to AXI regs */ +#define MVEBU_SATA_M2A_AXI_PORT_CTRL_REG (0x54ff04) + +/* AXI to MBUS bridge registers */ +#define MVEBU_AMB_IP_OFFSET (0x13ff00) +#define MVEBU_AMB_IP_BRIDGE_WIN_REG(win) (MVEBU_AMB_IP_OFFSET + \ + (win * 0x8)) +#define MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET 0 +#define MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK \ + (0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET) +#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET 16 +#define MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK \ + (0xffffu << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET) + +#define MVEBU_SAMPLE_AT_RESET_REG (0x440600) +#define SAR_PCIE1_CLK_CFG_OFFSET 31 +#define SAR_PCIE1_CLK_CFG_MASK (0x1u << SAR_PCIE1_CLK_CFG_OFFSET) +#define SAR_PCIE0_CLK_CFG_OFFSET 30 +#define SAR_PCIE0_CLK_CFG_MASK (0x1 << SAR_PCIE0_CLK_CFG_OFFSET) +#define SAR_I2C_INIT_EN_OFFSET 24 +#define SAR_I2C_INIT_EN_MASK (1 << SAR_I2C_INIT_EN_OFFSET) + +/******************************************************************************* + * PCIE clock buffer control + ******************************************************************************/ +#define MVEBU_PCIE_REF_CLK_BUF_CTRL (0x4404F0) +#define PCIE1_REFCLK_BUFF_SOURCE 0x800 +#define PCIE0_REFCLK_BUFF_SOURCE 0x400 + +/******************************************************************************* + * MSS Device Push Set Register + ******************************************************************************/ +#define MVEBU_CP_MSS_DPSHSR_REG (0x280040) +#define MSS_DPSHSR_REG_PCIE_CLK_SEL 0x8 + +/******************************************************************************* + * RTC Configuration + ******************************************************************************/ +#define MVEBU_RTC_BASE (0x284000) +#define MVEBU_RTC_STATUS_REG (MVEBU_RTC_BASE + 0x0) +#define MVEBU_RTC_STATUS_ALARM1_MASK 0x1 +#define MVEBU_RTC_STATUS_ALARM2_MASK 0x2 +#define MVEBU_RTC_IRQ_1_CONFIG_REG (MVEBU_RTC_BASE + 0x4) +#define MVEBU_RTC_IRQ_2_CONFIG_REG (MVEBU_RTC_BASE + 0x8) +#define MVEBU_RTC_TIME_REG (MVEBU_RTC_BASE + 0xC) +#define MVEBU_RTC_ALARM_1_REG (MVEBU_RTC_BASE + 0x10) +#define MVEBU_RTC_ALARM_2_REG (MVEBU_RTC_BASE + 0x14) +#define MVEBU_RTC_CCR_REG (MVEBU_RTC_BASE + 0x18) +#define MVEBU_RTC_NOMINAL_TIMING 0x2000 +#define MVEBU_RTC_NOMINAL_TIMING_MASK 0x7FFF +#define MVEBU_RTC_TEST_CONFIG_REG (MVEBU_RTC_BASE + 0x1C) +#define MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG (MVEBU_RTC_BASE + 0x80) +#define MVEBU_RTC_WRCLK_PERIOD_MASK 0xFFFF +#define MVEBU_RTC_WRCLK_PERIOD_DEFAULT 0x3FF +#define MVEBU_RTC_WRCLK_SETUP_OFFS 16 +#define MVEBU_RTC_WRCLK_SETUP_MASK 0xFFFF0000 +#define MVEBU_RTC_WRCLK_SETUP_DEFAULT 0x29 +#define MVEBU_RTC_BRIDGE_TIMING_CTRL1_REG (MVEBU_RTC_BASE + 0x84) +#define MVEBU_RTC_READ_OUTPUT_DELAY_MASK 0xFFFF +#define MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT 0x1F + +/******************************************************************************* + * TRNG Configuration + ******************************************************************************/ +#define MVEBU_TRNG_BASE (0x760000) +#define MVEBU_EFUSE_TRNG_ENABLE_EFUSE_WORD MVEBU_AP_LDX_220_189_EFUSE_OFFS +#define MVEBU_EFUSE_TRNG_ENABLE_BIT_OFFSET 13 /* LD0[202] */ + +enum axi_attr { + AXI_ADUNIT_ATTR = 0, + AXI_COMUNIT_ATTR, + AXI_EIP197_ATTR, + AXI_USB3D_ATTR, + AXI_USB3H0_ATTR, + AXI_USB3H1_ATTR, + AXI_SATA0_ATTR, + AXI_SATA1_ATTR, + AXI_DAP_ATTR, + AXI_DFX_ATTR, + AXI_DBG_TRC_ATTR = 12, + AXI_SDIO_ATTR, + AXI_MSS_ATTR, + AXI_MAX_ATTR, +}; + +/* Most stream IDS are configured centrally in the CP-110 RFU + * but some are configured inside the unit registers + */ +#define RFU_STREAM_ID_BASE (0x450000) +#define USB3H_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0xC) +#define USB3H_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x10) +#define SATA_0_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x14) +#define SATA_1_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x18) +#define SDIO_STREAM_ID_REG (RFU_STREAM_ID_BASE + 0x28) + +#define CP_DMA_0_STREAM_ID_REG (0x6B0010) +#define CP_DMA_1_STREAM_ID_REG (0x6D0010) + +/* We allocate IDs 128-255 for PCIe */ +#define MAX_STREAM_ID (0x80) + +static uintptr_t stream_id_reg[] = { + USB3H_0_STREAM_ID_REG, + USB3H_1_STREAM_ID_REG, + CP_DMA_0_STREAM_ID_REG, + CP_DMA_1_STREAM_ID_REG, + SATA_0_STREAM_ID_REG, + SATA_1_STREAM_ID_REG, + SDIO_STREAM_ID_REG, + 0 +}; + +static void cp110_errata_wa_init(uintptr_t base) +{ + uint32_t data; + + /* ERRATA GL-4076863: + * Reset value for global_secure_enable inputs must be changed + * from '1' to '0'. + * When asserted, only "secured" transactions can enter IHB + * configuration space. + * However, blocking AXI transactions is performed by IOB. + * Performing it also at IHB/HB complicates programming model. + * + * Enable non-secure access in SOC configuration register + */ + data = mmio_read_32(base + MVEBU_SOC_CFG_REG(MVEBU_SOC_CFG_REG_NUM)); + data &= ~MVEBU_SOC_CFG_GLOG_SECURE_EN_MASK; + mmio_write_32(base + MVEBU_SOC_CFG_REG(MVEBU_SOC_CFG_REG_NUM), data); +} + +static void cp110_pcie_clk_cfg(uintptr_t base) +{ + uint32_t pcie0_clk, pcie1_clk, reg; + + /* + * Determine the pcie0/1 clock direction (input/output) from the + * sample at reset. + */ + reg = mmio_read_32(base + MVEBU_SAMPLE_AT_RESET_REG); + pcie0_clk = (reg & SAR_PCIE0_CLK_CFG_MASK) >> SAR_PCIE0_CLK_CFG_OFFSET; + pcie1_clk = (reg & SAR_PCIE1_CLK_CFG_MASK) >> SAR_PCIE1_CLK_CFG_OFFSET; + + /* CP110 revision A2 or CN913x */ + if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A2 || + cp110_device_id_get(base) == MVEBU_CN9130_DEV_ID) { + /* + * PCIe Reference Clock Buffer Control register must be + * set according to the clock direction (input/output) + */ + reg = mmio_read_32(base + MVEBU_PCIE_REF_CLK_BUF_CTRL); + reg &= ~(PCIE0_REFCLK_BUFF_SOURCE | PCIE1_REFCLK_BUFF_SOURCE); + if (!pcie0_clk) + reg |= PCIE0_REFCLK_BUFF_SOURCE; + if (!pcie1_clk) + reg |= PCIE1_REFCLK_BUFF_SOURCE; + + mmio_write_32(base + MVEBU_PCIE_REF_CLK_BUF_CTRL, reg); + } + + /* CP110 revision A1 */ + if (cp110_rev_id_get(base) == MVEBU_CP110_REF_ID_A1) { + if (!pcie0_clk || !pcie1_clk) { + /* + * if one of the pcie clocks is set to input, + * we need to set mss_push[131] field, otherwise, + * the pcie clock might not work. + */ + reg = mmio_read_32(base + MVEBU_CP_MSS_DPSHSR_REG); + reg |= MSS_DPSHSR_REG_PCIE_CLK_SEL; + mmio_write_32(base + MVEBU_CP_MSS_DPSHSR_REG, reg); + } + } +} + +/* Set a unique stream id for all DMA capable devices */ +static void cp110_stream_id_init(uintptr_t base, uint32_t stream_id) +{ + int i = 0; + + while (stream_id_reg[i]) { + if (i > MAX_STREAM_ID_PER_CP) { + NOTICE("Only first %d (maximum) Stream IDs allocated\n", + MAX_STREAM_ID_PER_CP); + return; + } + + if ((stream_id_reg[i] == CP_DMA_0_STREAM_ID_REG) || + (stream_id_reg[i] == CP_DMA_1_STREAM_ID_REG)) + mmio_write_32(base + stream_id_reg[i], + stream_id << 16 | stream_id); + else + mmio_write_32(base + stream_id_reg[i], stream_id); + + /* SATA port 0/1 are in the same SATA unit, and they should use + * the same STREAM ID number + */ + if (stream_id_reg[i] != SATA_0_STREAM_ID_REG) + stream_id++; + + i++; + } +} + +static void cp110_axi_attr_init(uintptr_t base) +{ + uint32_t index, data; + + /* Initialize AXI attributes for Armada-7K/8K SoC */ + + /* Go over the AXI attributes and set Ax-Cache and Ax-Domain */ + for (index = 0; index < AXI_MAX_ATTR; index++) { + switch (index) { + /* DFX and MSS unit works with no coherent only - + * there's no option to configure the Ax-Cache and Ax-Domain + */ + case AXI_DFX_ATTR: + case AXI_MSS_ATTR: + continue; + default: + /* Set Ax-Cache as cacheable, no allocate, modifiable, + * bufferable + * The values are different because Read & Write + * definition is different in Ax-Cache + */ + data = mmio_read_32(base + MVEBU_AXI_ATTR_REG(index)); + data &= ~MVEBU_AXI_ATTR_ARCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_ARCACHE_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_AXI_ATTR_AWCACHE_OFFSET; + /* Set Ax-Domain as Outer domain */ + data &= ~MVEBU_AXI_ATTR_ARDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_ARDOMAIN_OFFSET; + data &= ~MVEBU_AXI_ATTR_AWDOMAIN_MASK; + data |= DOMAIN_OUTER_SHAREABLE << + MVEBU_AXI_ATTR_AWDOMAIN_OFFSET; + mmio_write_32(base + MVEBU_AXI_ATTR_REG(index), data); + } + } + + /* SATA IOCC supported, cache attributes + * for SATA MBUS to AXI configuration. + */ + data = mmio_read_32(base + MVEBU_SATA_M2A_AXI_PORT_CTRL_REG); + data &= ~MVEBU_SATA_M2A_AXI_AWCACHE_MASK; + data |= (CACHE_ATTR_WRITE_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_SATA_M2A_AXI_AWCACHE_OFFSET; + data &= ~MVEBU_SATA_M2A_AXI_ARCACHE_MASK; + data |= (CACHE_ATTR_READ_ALLOC | + CACHE_ATTR_CACHEABLE | + CACHE_ATTR_BUFFERABLE) << + MVEBU_SATA_M2A_AXI_ARCACHE_OFFSET; + mmio_write_32(base + MVEBU_SATA_M2A_AXI_PORT_CTRL_REG, data); + + /* Set all IO's AXI attribute to non-secure access. */ + for (index = 0; index < MVEBU_AXI_PROT_REGS_NUM; index++) + mmio_write_32(base + MVEBU_AXI_PROT_REG(index), + DOMAIN_SYSTEM_SHAREABLE); +} + +void cp110_amb_init(uintptr_t base) +{ + uint32_t reg; + + /* Open AMB bridge Window to Access COMPHY/MDIO registers */ + reg = mmio_read_32(base + MVEBU_AMB_IP_BRIDGE_WIN_REG(0)); + reg &= ~(MVEBU_AMB_IP_BRIDGE_WIN_SIZE_MASK | + MVEBU_AMB_IP_BRIDGE_WIN_EN_MASK); + reg |= (0x7ff << MVEBU_AMB_IP_BRIDGE_WIN_SIZE_OFFSET) | + (0x1 << MVEBU_AMB_IP_BRIDGE_WIN_EN_OFFSET); + mmio_write_32(base + MVEBU_AMB_IP_BRIDGE_WIN_REG(0), reg); +} + +static void cp110_rtc_init(uintptr_t base) +{ + /* Update MBus timing parameters before accessing RTC registers */ + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG, + MVEBU_RTC_WRCLK_PERIOD_MASK, + MVEBU_RTC_WRCLK_PERIOD_DEFAULT); + + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL0_REG, + MVEBU_RTC_WRCLK_SETUP_MASK, + MVEBU_RTC_WRCLK_SETUP_DEFAULT << + MVEBU_RTC_WRCLK_SETUP_OFFS); + + mmio_clrsetbits_32(base + MVEBU_RTC_BRIDGE_TIMING_CTRL1_REG, + MVEBU_RTC_READ_OUTPUT_DELAY_MASK, + MVEBU_RTC_READ_OUTPUT_DELAY_DEFAULT); + + /* + * Issue reset to the RTC if Clock Correction register + * contents did not sustain the reboot/power-on. + */ + if ((mmio_read_32(base + MVEBU_RTC_CCR_REG) & + MVEBU_RTC_NOMINAL_TIMING_MASK) != MVEBU_RTC_NOMINAL_TIMING) { + /* Reset Test register */ + mmio_write_32(base + MVEBU_RTC_TEST_CONFIG_REG, 0); + mdelay(500); + + /* Reset Status register */ + mmio_write_32(base + MVEBU_RTC_STATUS_REG, + (MVEBU_RTC_STATUS_ALARM1_MASK | + MVEBU_RTC_STATUS_ALARM2_MASK)); + udelay(62); + + /* Turn off Int1 and Int2 sources & clear the Alarm count */ + mmio_write_32(base + MVEBU_RTC_IRQ_1_CONFIG_REG, 0); + mmio_write_32(base + MVEBU_RTC_IRQ_2_CONFIG_REG, 0); + mmio_write_32(base + MVEBU_RTC_ALARM_1_REG, 0); + mmio_write_32(base + MVEBU_RTC_ALARM_2_REG, 0); + + /* Setup nominal register access timing */ + mmio_write_32(base + MVEBU_RTC_CCR_REG, + MVEBU_RTC_NOMINAL_TIMING); + + /* Reset Status register */ + mmio_write_32(base + MVEBU_RTC_STATUS_REG, + (MVEBU_RTC_STATUS_ALARM1_MASK | + MVEBU_RTC_STATUS_ALARM2_MASK)); + udelay(50); + } +} + +static void cp110_amb_adec_init(uintptr_t base) +{ + /* enable AXI-MBUS by clearing "Bridge Windows Disable" */ + mmio_clrbits_32(base + MVEBU_BRIDGE_WIN_DIS_REG, + (1 << MVEBU_BRIDGE_WIN_DIS_OFF)); + + /* configure AXI-MBUS windows for CP */ + init_amb_adec(base); +} + +static void cp110_trng_init(uintptr_t base) +{ + static bool done; + int ret; + uint32_t reg_val, efuse; + + /* 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 AP LD0 bit defining TRNG presence */ + efuse = mmio_read_32(MVEBU_EFUSE_TRNG_ENABLE_EFUSE_WORD); + efuse >>= MVEBU_EFUSE_TRNG_ENABLE_BIT_OFFSET; + efuse &= 1; + + if (efuse == 0) { + VERBOSE("TRNG is not present, skipping"); + return; + } + + if (!done) { + ret = eip76_rng_probe(base + MVEBU_TRNG_BASE); + if (ret != 0) { + ERROR("Failed to init TRNG @ 0x%lx\n", base); + return; + } + done = true; + } +} +void cp110_init(uintptr_t cp110_base, uint32_t stream_id) +{ + INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base); + + /* configure IOB windows for CP0*/ + init_iob(cp110_base); + + /* configure AXI-MBUS windows for CP0*/ + cp110_amb_adec_init(cp110_base); + + /* configure axi for CP0*/ + cp110_axi_attr_init(cp110_base); + + /* Execute SW WA for erratas */ + cp110_errata_wa_init(cp110_base); + + /* Confiure pcie clock according to clock direction */ + cp110_pcie_clk_cfg(cp110_base); + + /* configure stream id for CP0 */ + cp110_stream_id_init(cp110_base, stream_id); + + /* Open AMB bridge for comphy for CP0 & CP1*/ + cp110_amb_init(cp110_base); + + /* Reset RTC if needed */ + cp110_rtc_init(cp110_base); + + /* TRNG init - for CP0 only */ + cp110_trng_init(cp110_base); +} + +/* Do the minimal setup required to configure the CP in BLE */ +void cp110_ble_init(uintptr_t cp110_base) +{ +#if PCI_EP_SUPPORT + INFO("%s: Initialize CPx - base = %lx\n", __func__, cp110_base); + + cp110_amb_init(cp110_base); + + /* Configure PCIe clock */ + cp110_pcie_clk_cfg(cp110_base); + + /* Configure PCIe endpoint */ + ble_plat_pcie_ep_setup(); +#endif +} diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c new file mode 100644 index 0000000..4f7191b --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c @@ -0,0 +1,253 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +#include +#include +#include +#include +#include +#include +#include "dfx.h" + +/* #define DEBUG_DFX */ +#ifdef DEBUG_DFX +#define debug(format...) NOTICE(format) +#else +#define debug(format, arg...) +#endif + +#define TSEN_CTRL0 0xf06f8084 + #define TSEN_CTRL0_START BIT(0) + #define TSEN_CTRL0_RESET BIT(1) + #define TSEN_CTRL0_ENABLE BIT(2) + #define TSEN_CTRL0_AVG_BYPASS BIT(6) + #define TSEN_CTRL0_CHAN_SHIFT 13 + #define TSEN_CTRL0_CHAN_MASK 0xF + #define TSEN_CTRL0_OSR_SHIFT 24 + #define TSEN_CTRL0_OSR_MAX 0x3 + #define TSEN_CTRL0_MODE_SHIFT 30 + #define TSEN_CTRL0_MODE_EXTERNAL 0x2U + #define TSEN_CTRL0_MODE_MASK 0x3U + +#define TSEN_CTRL1 0xf06f8088 + #define TSEN_CTRL1_INT_EN BIT(25) + #define TSEN_CTRL1_HYST_SHIFT 19 + #define TSEN_CTRL1_HYST_MASK (0x3 << TSEN_CTRL1_HYST_SHIFT) + #define TSEN_CTRL1_THRESH_SHIFT 3 + #define TSEN_CTRL1_THRESH_MASK (0x3ff << TSEN_CTRL1_THRESH_SHIFT) + +#define TSEN_STATUS 0xf06f808c + #define TSEN_STATUS_VALID_OFFSET 16 + #define TSEN_STATUS_VALID_MASK (0x1 << TSEN_STATUS_VALID_OFFSET) + #define TSEN_STATUS_TEMP_OUT_OFFSET 0 + #define TSEN_STATUS_TEMP_OUT_MASK (0x3FF << TSEN_STATUS_TEMP_OUT_OFFSET) + +#define DFX_SERVER_IRQ_SUM_MASK_REG 0xf06f8104 + #define DFX_SERVER_IRQ_EN BIT(1) + +#define DFX_IRQ_CAUSE_REG 0xf06f8108 + +#define DFX_IRQ_MASK_REG 0xf06f810c + #define DFX_IRQ_TSEN_OVERHEAT_OFFSET BIT(22) + +#define THERMAL_SEN_OUTPUT_MSB 512 +#define THERMAL_SEN_OUTPUT_COMP 1024 + +#define COEF_M 423 +#define COEF_B -150000LL + +static void armada_ap806_thermal_read(u_register_t *temp) +{ + uint32_t reg; + + reg = mmio_read_32(TSEN_STATUS); + + reg = ((reg & TSEN_STATUS_TEMP_OUT_MASK) >> + TSEN_STATUS_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; + + *temp = ((COEF_M * ((signed int)reg)) - COEF_B); +} + +static void armada_ap806_thermal_irq(void) +{ + /* Dummy read, register ROC */ + mmio_read_32(DFX_IRQ_CAUSE_REG); +} + +static void armada_ap806_thermal_overheat_irq_init(void) +{ + uint32_t reg; + + /* Clear DFX temperature IRQ cause */ + reg = mmio_read_32(DFX_IRQ_CAUSE_REG); + + /* Enable DFX Temperature IRQ */ + reg = mmio_read_32(DFX_IRQ_MASK_REG); + reg |= DFX_IRQ_TSEN_OVERHEAT_OFFSET; + mmio_write_32(DFX_IRQ_MASK_REG, reg); + + /* Enable DFX server IRQ */ + reg = mmio_read_32(DFX_SERVER_IRQ_SUM_MASK_REG); + reg |= DFX_SERVER_IRQ_EN; + mmio_write_32(DFX_SERVER_IRQ_SUM_MASK_REG, reg); + + /* Enable overheat interrupt */ + reg = mmio_read_32(TSEN_CTRL1); + reg |= TSEN_CTRL1_INT_EN; + mmio_write_32(TSEN_CTRL1, reg); +} + +static unsigned int armada_mc_to_reg_temp(unsigned int temp_mc) +{ + unsigned int sample; + + sample = (temp_mc + COEF_B) / COEF_M; + + return sample & 0x3ff; +} + +/* + * The documentation states: + * high/low watermark = threshold +/- 0.4761 * 2^(hysteresis + 2) + * which is the mathematical derivation for: + * 0x0 <=> 1.9°C, 0x1 <=> 3.8°C, 0x2 <=> 7.6°C, 0x3 <=> 15.2°C + */ +static unsigned int hyst_levels_mc[] = {1900, 3800, 7600, 15200}; + +static unsigned int armada_mc_to_reg_hyst(int hyst_mc) +{ + int i; + + /* + * We will always take the smallest possible hysteresis to avoid risking + * the hardware integrity by enlarging the threshold by +8°C in the + * worst case. + */ + for (i = ARRAY_SIZE(hyst_levels_mc) - 1; i > 0; i--) + if (hyst_mc >= hyst_levels_mc[i]) + break; + + return i; +} + +static void armada_ap806_thermal_threshold(int thresh_mc, int hyst_mc) +{ + uint32_t ctrl1; + unsigned int threshold = armada_mc_to_reg_temp(thresh_mc); + unsigned int hysteresis = armada_mc_to_reg_hyst(hyst_mc); + + ctrl1 = mmio_read_32(TSEN_CTRL1); + /* Set Threshold */ + if (thresh_mc >= 0) { + ctrl1 &= ~(TSEN_CTRL1_THRESH_MASK); + ctrl1 |= threshold << TSEN_CTRL1_THRESH_SHIFT; + } + + /* Set Hysteresis */ + if (hyst_mc >= 0) { + ctrl1 &= ~(TSEN_CTRL1_HYST_MASK); + ctrl1 |= hysteresis << TSEN_CTRL1_HYST_SHIFT; + } + + mmio_write_32(TSEN_CTRL1, ctrl1); +} + +static void armada_select_channel(int channel) +{ + uint32_t ctrl0; + + /* Stop the measurements */ + ctrl0 = mmio_read_32(TSEN_CTRL0); + ctrl0 &= ~TSEN_CTRL0_START; + mmio_write_32(TSEN_CTRL0, ctrl0); + + /* Reset the mode, internal sensor will be automatically selected */ + ctrl0 &= ~(TSEN_CTRL0_MODE_MASK << TSEN_CTRL0_MODE_SHIFT); + + /* Other channels are external and should be selected accordingly */ + if (channel) { + /* Change the mode to external */ + ctrl0 |= TSEN_CTRL0_MODE_EXTERNAL << + TSEN_CTRL0_MODE_SHIFT; + /* Select the sensor */ + ctrl0 &= ~(TSEN_CTRL0_CHAN_MASK << TSEN_CTRL0_CHAN_SHIFT); + ctrl0 |= (channel - 1) << TSEN_CTRL0_CHAN_SHIFT; + } + + /* Actually set the mode/channel */ + mmio_write_32(TSEN_CTRL0, ctrl0); + + /* Re-start the measurements */ + ctrl0 |= TSEN_CTRL0_START; + mmio_write_32(TSEN_CTRL0, ctrl0); +} + +static void armada_ap806_thermal_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(TSEN_CTRL0); + reg &= ~TSEN_CTRL0_RESET; + reg |= TSEN_CTRL0_START | TSEN_CTRL0_ENABLE; + + /* Sample every ~2ms */ + reg |= TSEN_CTRL0_OSR_MAX << TSEN_CTRL0_OSR_SHIFT; + + /* Enable average (2 samples by default) */ + reg &= ~TSEN_CTRL0_AVG_BYPASS; + + mmio_write_32(TSEN_CTRL0, reg); + + debug("thermal: Initialization done\n"); +} + +static void armada_is_valid(u_register_t *read) +{ + *read = (mmio_read_32(TSEN_STATUS) & TSEN_STATUS_VALID_MASK); +} + +int mvebu_dfx_thermal_handle(u_register_t func, u_register_t *read, + u_register_t x2, u_register_t x3) +{ + debug_enter(); + + switch (func) { + case MV_SIP_DFX_THERMAL_INIT: + armada_ap806_thermal_init(); + break; + case MV_SIP_DFX_THERMAL_READ: + armada_ap806_thermal_read(read); + break; + case MV_SIP_DFX_THERMAL_IRQ: + armada_ap806_thermal_irq(); + break; + case MV_SIP_DFX_THERMAL_THRESH: + armada_ap806_thermal_threshold(x2, x3); + armada_ap806_thermal_overheat_irq_init(); + break; + case MV_SIP_DFX_THERMAL_IS_VALID: + armada_is_valid(read); + break; + case MV_SIP_DFX_THERMAL_SEL_CHANNEL: + armada_select_channel(x2); + break; + default: + ERROR("unsupported dfx func\n"); + return -EINVAL; + } + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h new file mode 100644 index 0000000..88c4de8 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h @@ -0,0 +1,22 @@ +/* + * Copyright (C) 2019 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* DFX sub-FID */ +#define MV_SIP_DFX_THERMAL_INIT 1 +#define MV_SIP_DFX_THERMAL_READ 2 +#define MV_SIP_DFX_THERMAL_IS_VALID 3 +#define MV_SIP_DFX_THERMAL_IRQ 4 +#define MV_SIP_DFX_THERMAL_THRESH 5 +#define MV_SIP_DFX_THERMAL_SEL_CHANNEL 6 + +#define MV_SIP_DFX_SREAD 20 +#define MV_SIP_DFX_SWRITE 21 + +int mvebu_dfx_thermal_handle(u_register_t func, u_register_t *read, + u_register_t x2, u_register_t x3); +int mvebu_dfx_misc_handle(u_register_t func, u_register_t *read, + u_register_t addr, u_register_t val); diff --git a/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c new file mode 100644 index 0000000..189105f --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include "dfx.h" +#include +#include +#include + +/* #define DEBUG_DFX */ +#ifdef DEBUG_DFX +#define debug(format...) NOTICE(format) +#else +#define debug(format, arg...) +#endif + +#define SAR_BASE (MVEBU_REGS_BASE + 0x6F8200) +#define SAR_SIZE 0x4 +#define AP_DEV_ID_STATUS_REG (MVEBU_REGS_BASE + 0x6F8240) +#define JTAG_DEV_ID_STATUS_REG (MVEBU_REGS_BASE + 0x6F8244) +#define EFUSE_CTRL (MVEBU_REGS_BASE + 0x6F8008) +#define EFUSE_LD_BASE (MVEBU_REGS_BASE + 0x6F8F00) +#define EFUSE_LD_SIZE 0x1C +#define EFUSE_HD_BASE (MVEBU_REGS_BASE + 0x6F9000) +#define EFUSE_HD_SIZE 0x3F8 + +/* AP806 CPU DFS register mapping*/ +#define AP806_CA72MP2_0_PLL_CR_0_BASE (MVEBU_REGS_BASE + 0x6F8278) +#define AP806_CA72MP2_0_PLL_CR_1_BASE (MVEBU_REGS_BASE + 0x6F8280) +#define AP806_CA72MP2_0_PLL_CR_2_BASE (MVEBU_REGS_BASE + 0x6F8284) +#define AP806_CA72MP2_0_PLL_SR_BASE (MVEBU_REGS_BASE + 0x6F8C94) + +/* AP807 CPU DFS register mapping */ +#define AP807_DEVICE_GENERAL_CR_10_BASE (MVEBU_REGS_BASE + 0x6F8278) +#define AP807_DEVICE_GENERAL_CR_11_BASE (MVEBU_REGS_BASE + 0x6F827C) +#define AP807_DEVICE_GENERAL_STATUS_6_BASE (MVEBU_REGS_BASE + 0x6F8C98) + +#ifdef MVEBU_SOC_AP807 + #define CLUSTER_OFFSET 0x8 + #define CLK_DIVIDER_REG AP807_DEVICE_GENERAL_CR_10_BASE + #define CLK_FORCE_REG AP807_DEVICE_GENERAL_CR_11_BASE + #define CLK_RATIO_REG AP807_DEVICE_GENERAL_CR_11_BASE + #define CLK_RATIO_STATE_REG AP807_DEVICE_GENERAL_STATUS_6_BASE +#else + #define CLUSTER_OFFSET 0x14 + #define CLK_DIVIDER_REG AP806_CA72MP2_0_PLL_CR_0_BASE + #define CLK_FORCE_REG AP806_CA72MP2_0_PLL_CR_1_BASE + #define CLK_RATIO_REG AP806_CA72MP2_0_PLL_CR_2_BASE + #define CLK_RATIO_STATE_REG AP806_CA72MP2_0_PLL_SR_BASE +#endif /* MVEBU_SOC_AP807 */ + +static _Bool is_valid(u_register_t addr) +{ + switch (addr) { + case AP_DEV_ID_STATUS_REG: + case JTAG_DEV_ID_STATUS_REG: + case SAR_BASE ... (SAR_BASE + SAR_SIZE): + case EFUSE_LD_BASE ... (EFUSE_LD_BASE + EFUSE_LD_SIZE): + case EFUSE_HD_BASE ... (EFUSE_HD_BASE + EFUSE_HD_SIZE): + case EFUSE_CTRL: + /* cpu-clk related registers */ + case CLK_DIVIDER_REG: + case CLK_DIVIDER_REG + CLUSTER_OFFSET: + case CLK_FORCE_REG: + case CLK_FORCE_REG + CLUSTER_OFFSET: +#ifndef MVEBU_SOC_AP807 + case CLK_RATIO_REG: + case CLK_RATIO_REG + CLUSTER_OFFSET: +#endif + case CLK_RATIO_STATE_REG: + case CLK_RATIO_STATE_REG + CLUSTER_OFFSET: + return true; + default: + return false; + } +} + +static int armada_dfx_sread(u_register_t *read, u_register_t addr) +{ + if (!is_valid(addr)) + return -EINVAL; + + *read = mmio_read_32(addr); + + return 0; +} + +static int armada_dfx_swrite(u_register_t addr, u_register_t val) +{ + if (!is_valid(addr)) + return -EINVAL; + + mmio_write_32(addr, val); + + return 0; +} + +int mvebu_dfx_misc_handle(u_register_t func, u_register_t *read, + u_register_t addr, u_register_t val) +{ + debug_enter(); + + debug("func %ld, addr 0x%lx, val 0x%lx\n", func, addr, val); + + switch (func) { + case MV_SIP_DFX_SREAD: + return armada_dfx_sread(read, addr); + case MV_SIP_DFX_SWRITE: + return armada_dfx_swrite(addr, val); + default: + ERROR("unsupported dfx misc sub-func\n"); + return -EINVAL; + } + + debug_exit(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/thermal.c b/arm-trusted-firmware/drivers/marvell/thermal.c new file mode 100644 index 0000000..a501ab4 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/thermal.c @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for thermal unit located in Marvell ARMADA 8K and compatible SoCs */ + +#include +#include + +int marvell_thermal_init(struct tsen_config *tsen_cfg) +{ + if (tsen_cfg->tsen_ready == 1) { + INFO("thermal sensor is already initialized\n"); + return 0; + } + + if (tsen_cfg->ptr_tsen_probe == NULL) { + ERROR("initial thermal sensor configuration is missing\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_probe(tsen_cfg)) { + ERROR("thermal sensor initialization failed\n"); + return -1; + } + + VERBOSE("thermal sensor was initialized\n"); + + return 0; +} + +int marvell_thermal_read(struct tsen_config *tsen_cfg, int *temp) +{ + if (temp == NULL) { + ERROR("NULL pointer for temperature read\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_read == NULL || + tsen_cfg->tsen_ready == 0) { + ERROR("thermal sensor was not initialized\n"); + return -1; + } + + if (tsen_cfg->ptr_tsen_read(tsen_cfg, temp)) { + ERROR("temperature read failed\n"); + return -1; + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S b/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S new file mode 100644 index 0000000..c7eb165 --- /dev/null +++ b/arm-trusted-firmware/drivers/marvell/uart/a3700_console.S @@ -0,0 +1,271 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_a3700_core_putc + .globl console_a3700_core_init + .globl console_a3700_core_getc + .globl console_a3700_core_flush + + .globl console_a3700_putc + .globl console_a3700_getc + .globl console_a3700_flush + + /* ----------------------------------------------- + * int console_a3700_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 + * Clobber list : x1, x2, x3, x4 + * ----------------------------------------------- + */ +func console_a3700_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* + * Wait for the TX (THR and TSR) to be empty. If wait for 3ms, the TX FIFO is + * still not empty, TX FIFO will reset by all means. + */ + mov w4, #30 /* max time out 30 * 100 us */ +2: + /* Check whether TX (THR and TSR) is empty */ + ldr w3, [x0, #UART_STATUS_REG] + and w3, w3, #UARTLSR_TXEMPTY + cmp w3, #0 + b.ne 4f + + /* Delay */ + mov w3, #60000 /* 60000 cycles of below 3 instructions on 1200 MHz CPU ~~ 100 us */ +3: + sub w3, w3, #1 + cmp w3, #0 + b.ne 3b + + /* Check whether wait timeout expired */ + sub w4, w4, #1 + cmp w4, #0 + b.ne 2b + +4: + /* Reset UART via North Bridge Peripheral */ + mov_imm x4, MVEBU_NB_RESET_REG + ldr w3, [x4] + bic w3, w3, #MVEBU_NB_RESET_UART_N + str w3, [x4] + orr w3, w3, #MVEBU_NB_RESET_UART_N + str w3, [x4] + + /* Reset FIFO */ + mov w3, #UART_CTRL_RXFIFO_RESET + orr w3, w3, #UART_CTRL_TXFIFO_RESET + str w3, [x0, #UART_CTRL_REG] + + /* Delay */ + mov w3, #2000 +1: + sub w3, w3, #1 + cmp w3, #0 + b.ne 1b + + /* Program the baudrate */ + /* Divisor = Round(Uartclock / (16 * baudrate)) */ + lsl w2, w2, #4 + add w1, w1, w2, lsr #1 + udiv w2, w1, w2 + and w2, w2, #0x3ff /* clear all other bits to use default clock */ + + str w2, [x0, #UART_BAUD_REG]/* set baud rate divisor */ + + /* Set UART to default 16X scheme */ + mov w3, #0 + str w3, [x0, #UART_POSSR_REG] + + /* No Parity, 1 Stop */ + mov w3, #0 + str w3, [x0, #UART_CTRL_REG] + + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc console_a3700_core_init + + .globl console_a3700_register + + /* ----------------------------------------------- + * int console_a3700_register(console_t *console, + uintptr_t base, uint32_t clk, uint32_t baud) + * Function to initialize and register a new a3700 + * 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, x3, x4, x6, x7, x14 + * ----------------------------------------------- + */ +func console_a3700_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_a3700_core_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register a3700, putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_a3700_register + + /* -------------------------------------------------------- + * int console_a3700_core_putc(int c, unsigned int 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_a3700_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_STATUS_REG] + and w2, w2, #UARTLSR_TXFIFOFULL + cmp w2, #UARTLSR_TXFIFOFULL + b.eq 1b + mov w2, #0xD /* '\r' */ + str w2, [x1, #UART_TX_REG] + + /* Check if the transmit FIFO is full */ +2: ldr w2, [x1, #UART_STATUS_REG] + and w2, w2, #UARTLSR_TXFIFOFULL + cmp w2, #UARTLSR_TXFIFOFULL + b.eq 2b + str w0, [x1, #UART_TX_REG] + ret +putc_error: + mov w0, #-1 + ret +endfunc console_a3700_core_putc + + /* -------------------------------------------------------- + * int console_a3700_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_a3700_putc + ldr x1, [x1, #CONSOLE_T_BASE] + b console_a3700_core_putc +endfunc console_a3700_putc + + /* --------------------------------------------- + * int console_a3700_core_getc(void) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 if no character is available. + * In : w0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_core_getc + /* Check if there is a pending character */ + ldr w1, [x0, #UART_STATUS_REG] + and w1, w1, #UARTLSR_RXRDY + cmp w1, #UARTLSR_RXRDY + b.ne getc_no_char + ldr w0, [x0, #UART_RX_REG] + and w0, w0, #0xff + ret +getc_no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_a3700_core_getc + + /* --------------------------------------------- + * int console_a3700_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t structure + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_a3700_getc + ldr x0, [x0, #CONSOLE_T_BASE] + b console_a3700_core_getc +endfunc console_a3700_getc + + /* --------------------------------------------- + * void console_a3700_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_a3700_core_flush + /* Wait for the TX (THR and TSR) to be empty */ +1: ldr w1, [x0, #UART_STATUS_REG] + and w1, w1, #UARTLSR_TXEMPTY + cmp w1, #UARTLSR_TXEMPTY + b.ne 1b + ret +endfunc console_a3700_core_flush + + /* --------------------------------------------- + * void console_a3700_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_a3700_flush + ldr x0, [x0, #CONSOLE_T_BASE] + b console_a3700_core_flush +endfunc console_a3700_flush + diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c new file mode 100644 index 0000000..792f235 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c @@ -0,0 +1,293 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include + +#if TPM_ALG_ID == TPM_ALG_SHA512 +#define CRYPTO_MD_ID CRYPTO_MD_SHA512 +#elif TPM_ALG_ID == TPM_ALG_SHA384 +#define CRYPTO_MD_ID CRYPTO_MD_SHA384 +#elif TPM_ALG_ID == TPM_ALG_SHA256 +#define CRYPTO_MD_ID CRYPTO_MD_SHA256 +#else +# error Invalid TPM algorithm. +#endif /* TPM_ALG_ID */ + +/* Running Event Log Pointer */ +static uint8_t *log_ptr; + +/* Pointer to the first byte past end of the Event Log buffer */ +static uintptr_t log_end; + +/* Pointer to event_log_metadata_t */ +static const event_log_metadata_t *plat_metadata_ptr; + +/* TCG_EfiSpecIdEvent */ +static const id_event_headers_t id_event_header = { + .header = { + .pcr_index = PCR_0, + .event_type = EV_NO_ACTION, + .digest = {0}, + .event_size = (uint32_t)(sizeof(id_event_struct_t) + + (sizeof(id_event_algorithm_size_t) * + HASH_ALG_COUNT)) + }, + + .struct_header = { + .signature = TCG_ID_EVENT_SIGNATURE_03, + .platform_class = PLATFORM_CLASS_CLIENT, + .spec_version_minor = TCG_SPEC_VERSION_MINOR_TPM2, + .spec_version_major = TCG_SPEC_VERSION_MAJOR_TPM2, + .spec_errata = TCG_SPEC_ERRATA_TPM2, + .uintn_size = (uint8_t)(sizeof(unsigned int) / + sizeof(uint32_t)), + .number_of_algorithms = HASH_ALG_COUNT + } +}; + +static const event2_header_t locality_event_header = { + /* + * All EV_NO_ACTION events SHALL set + * TCG_PCR_EVENT2.pcrIndex = 0, unless otherwise specified + */ + .pcr_index = PCR_0, + + /* + * All EV_NO_ACTION events SHALL set + * TCG_PCR_EVENT2.eventType = 03h + */ + .event_type = EV_NO_ACTION, + + /* + * All EV_NO_ACTION events SHALL set TCG_PCR_EVENT2.digests to all + * 0x00's for each allocated Hash algorithm + */ + .digests = { + .count = HASH_ALG_COUNT + } +}; + +/* + * Record a measurement as a TCG_PCR_EVENT2 event + * + * @param[in] hash Pointer to hash data of TCG_DIGEST_SIZE bytes + * @param[in] metadata_ptr Pointer to event_log_metadata_t structure + * + * There must be room for storing this new event into the event log buffer. + */ +static void event_log_record(const uint8_t *hash, + const event_log_metadata_t *metadata_ptr) +{ + void *ptr = log_ptr; + uint32_t name_len; + + assert(hash != NULL); + assert(metadata_ptr != NULL); + assert(metadata_ptr->name != NULL); + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); + + name_len = (uint32_t)strlen(metadata_ptr->name) + 1U; + + /* Check for space in Event Log buffer */ + assert(((uintptr_t)ptr + (uint32_t)EVENT2_HDR_SIZE + name_len) < + log_end); + + /* + * As per TCG specifications, firmware components that are measured + * into PCR[0] must be logged in the event log using the event type + * EV_POST_CODE. + */ + /* TCG_PCR_EVENT2.PCRIndex */ + ((event2_header_t *)ptr)->pcr_index = metadata_ptr->pcr; + + /* TCG_PCR_EVENT2.EventType */ + ((event2_header_t *)ptr)->event_type = EV_POST_CODE; + + /* TCG_PCR_EVENT2.Digests.Count */ + ptr = (uint8_t *)ptr + offsetof(event2_header_t, digests); + ((tpml_digest_values *)ptr)->count = HASH_ALG_COUNT; + + /* TCG_PCR_EVENT2.Digests[] */ + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(tpml_digest_values, digests)); + + /* TCG_PCR_EVENT2.Digests[].AlgorithmId */ + ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID; + + /* TCG_PCR_EVENT2.Digests[].Digest[] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest)); + + /* Copy digest */ + (void)memcpy(ptr, (const void *)hash, TCG_DIGEST_SIZE); + + /* TCG_PCR_EVENT2.EventSize */ + ptr = (uint8_t *)((uintptr_t)ptr + TCG_DIGEST_SIZE); + ((event2_data_t *)ptr)->event_size = name_len; + + /* Copy event data to TCG_PCR_EVENT2.Event */ + (void)memcpy((void *)(((event2_data_t *)ptr)->event), + (const void *)metadata_ptr->name, name_len); + + /* End of event data */ + log_ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(event2_data_t, event) + name_len); +} + +/* + * Initialise Event Log global variables, used during the recording + * of various payload measurements into the Event Log buffer + * + * @param[in] event_log_start Base address of Event Log buffer + * @param[in] event_log_finish End address of Event Log buffer, + * it is a first byte past end of the + * buffer + */ +void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish) +{ + assert(event_log_start != NULL); + assert(event_log_finish > event_log_start); + + log_ptr = event_log_start; + log_end = (uintptr_t)event_log_finish; + + /* Get pointer to platform's event_log_metadata_t structure */ + plat_metadata_ptr = plat_event_log_get_metadata(); + assert(plat_metadata_ptr != NULL); +} + +/* + * Initialises Event Log by writing Specification ID and + * Startup Locality events + */ +void event_log_write_header(void) +{ + const char locality_signature[] = TCG_STARTUP_LOCALITY_SIGNATURE; + void *ptr = log_ptr; + + /* event_log_init() must have been called prior to this. */ + assert(log_ptr != NULL); + + /* + * Add Specification ID Event first + * + * Copy TCG_EfiSpecIDEventStruct structure header + */ + (void)memcpy(ptr, (const void *)&id_event_header, + sizeof(id_event_header)); + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_header)); + + /* TCG_EfiSpecIdEventAlgorithmSize structure */ + ((id_event_algorithm_size_t *)ptr)->algorithm_id = TPM_ALG_ID; + ((id_event_algorithm_size_t *)ptr)->digest_size = TCG_DIGEST_SIZE; + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(id_event_algorithm_size_t)); + + /* + * TCG_EfiSpecIDEventStruct.vendorInfoSize + * No vendor data + */ + ((id_event_struct_data_t *)ptr)->vendor_info_size = 0; + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(id_event_struct_data_t, vendor_info)); + + /* + * The Startup Locality event should be placed in the log before + * any event which extends PCR[0]. + * + * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3 + */ + + /* Copy Startup Locality Event Header */ + (void)memcpy(ptr, (const void *)&locality_event_header, + sizeof(locality_event_header)); + ptr = (uint8_t *)((uintptr_t)ptr + sizeof(locality_event_header)); + + /* TCG_PCR_EVENT2.Digests[].AlgorithmId */ + ((tpmt_ha *)ptr)->algorithm_id = TPM_ALG_ID; + + /* TCG_PCR_EVENT2.Digests[].Digest[] */ + (void)memset(&((tpmt_ha *)ptr)->digest, 0, TPM_ALG_ID); + ptr = (uint8_t *)((uintptr_t)ptr + + offsetof(tpmt_ha, digest) + TCG_DIGEST_SIZE); + + /* TCG_PCR_EVENT2.EventSize */ + ((event2_data_t *)ptr)->event_size = + (uint32_t)sizeof(startup_locality_event_t); + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event)); + + /* TCG_EfiStartupLocalityEvent.Signature */ + (void)memcpy(ptr, (const void *)locality_signature, + sizeof(TCG_STARTUP_LOCALITY_SIGNATURE)); + + /* + * TCG_EfiStartupLocalityEvent.StartupLocality = 0: + * the platform's boot firmware + */ + ((startup_locality_event_t *)ptr)->startup_locality = 0U; + log_ptr = (uint8_t *)((uintptr_t)ptr + sizeof(startup_locality_event_t)); +} + +/* + * Calculate and write hash of image, configuration data, etc. + * to Event Log. + * + * @param[in] data_base Address of data + * @param[in] data_size Size of data + * @param[in] data_id Data ID + * @return: + * 0 = success + * < 0 = error + */ +int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, + uint32_t data_id) +{ + unsigned char hash_data[CRYPTO_MD_MAX_SIZE]; + int rc; + const event_log_metadata_t *metadata_ptr = plat_metadata_ptr; + + /* Get the metadata associated with this image. */ + while ((metadata_ptr->id != EVLOG_INVALID_ID) && + (metadata_ptr->id != data_id)) { + metadata_ptr++; + } + assert(metadata_ptr->id != EVLOG_INVALID_ID); + + /* Calculate hash */ + rc = crypto_mod_calc_hash(CRYPTO_MD_ID, + (void *)data_base, data_size, hash_data); + if (rc != 0) { + return rc; + } + + event_log_record(hash_data, metadata_ptr); + + return 0; +} + +/* + * Get current Event Log buffer size i.e. used space of Event Log buffer + * + * @param[in] event_log_start Base Pointer to Event Log buffer + * + * @return: current Size of Event Log buffer + */ +size_t event_log_get_cur_size(uint8_t *event_log_start) +{ + assert(event_log_start != NULL); + assert(log_ptr >= event_log_start); + + return (size_t)((uintptr_t)log_ptr - (uintptr_t)event_log_start); +} diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk new file mode 100644 index 0000000..1ff4aa8 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_log.mk @@ -0,0 +1,36 @@ +# +# Copyright (c) 2020-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default log level to dump the event log (LOG_LEVEL_INFO) +EVENT_LOG_LEVEL ?= 40 + +# TPM hash algorithm. +# SHA-256 (or stronger) is required for all devices that are TPM 2.0 compliant. +TPM_HASH_ALG := sha256 + +ifeq (${TPM_HASH_ALG}, sha512) + TPM_ALG_ID := TPM_ALG_SHA512 + TCG_DIGEST_SIZE := 64U +else ifeq (${TPM_HASH_ALG}, sha384) + TPM_ALG_ID := TPM_ALG_SHA384 + TCG_DIGEST_SIZE := 48U +else + TPM_ALG_ID := TPM_ALG_SHA256 + TCG_DIGEST_SIZE := 32U +endif #TPM_HASH_ALG + +# Set definitions for Measured Boot driver. +$(eval $(call add_defines,\ + $(sort \ + TPM_ALG_ID \ + TCG_DIGEST_SIZE \ + EVENT_LOG_LEVEL \ +))) + +EVENT_LOG_SRC_DIR := drivers/measured_boot/event_log/ + +EVENT_LOG_SOURCES := ${EVENT_LOG_SRC_DIR}event_log.c \ + ${EVENT_LOG_SRC_DIR}event_print.c diff --git a/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c b/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c new file mode 100644 index 0000000..e2ba174 --- /dev/null +++ b/arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#if LOG_LEVEL >= EVENT_LOG_LEVEL + +/* + * Print TCG_EfiSpecIDEventStruct + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void id_event_print(uint8_t **log_addr, size_t *log_size) +{ + unsigned int i; + uint8_t info_size, *info_size_ptr; + void *ptr = *log_addr; + id_event_headers_t *event = (id_event_headers_t *)ptr; + id_event_algorithm_size_t *alg_ptr; + uint32_t event_size, number_of_algorithms; + size_t digest_len; +#if ENABLE_ASSERTIONS + const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size); + bool valid = true; +#endif + + assert(*log_size >= sizeof(id_event_headers_t)); + + /* The fields of the event log header are defined to be PCRIndex of 0, + * EventType of EV_NO_ACTION, Digest of 20 bytes of 0, and + * Event content defined as TCG_EfiSpecIDEventStruct. + */ + LOG_EVENT("TCG_EfiSpecIDEvent:\n"); + LOG_EVENT(" PCRIndex : %u\n", event->header.pcr_index); + assert(event->header.pcr_index == (uint32_t)PCR_0); + + LOG_EVENT(" EventType : %u\n", event->header.event_type); + assert(event->header.event_type == EV_NO_ACTION); + + LOG_EVENT(" Digest :"); + for (i = 0U; i < sizeof(event->header.digest); ++i) { + uint8_t val = event->header.digest[i]; + + (void)printf(" %02x", val); + if ((i & U(0xF)) == 0U) { + (void)printf("\n"); + LOG_EVENT("\t\t :"); + } +#if ENABLE_ASSERTIONS + if (val != 0U) { + valid = false; + } +#endif + } + if ((i & U(0xF)) != 0U) { + (void)printf("\n"); + } + + assert(valid); + + /* EventSize */ + event_size = event->header.event_size; + LOG_EVENT(" EventSize : %u\n", event_size); + + LOG_EVENT(" Signature : %s\n", + event->struct_header.signature); + LOG_EVENT(" PlatformClass : %u\n", + event->struct_header.platform_class); + LOG_EVENT(" SpecVersion : %u.%u.%u\n", + event->struct_header.spec_version_major, + event->struct_header.spec_version_minor, + event->struct_header.spec_errata); + LOG_EVENT(" UintnSize : %u\n", + event->struct_header.uintn_size); + + /* NumberOfAlgorithms */ + number_of_algorithms = event->struct_header.number_of_algorithms; + LOG_EVENT(" NumberOfAlgorithms : %u\n", number_of_algorithms); + + /* Address of DigestSizes[] */ + alg_ptr = event->struct_header.digest_size; + + /* Size of DigestSizes[] */ + digest_len = number_of_algorithms * sizeof(id_event_algorithm_size_t); + assert(((uintptr_t)alg_ptr + digest_len) <= (uintptr_t)end_ptr); + + LOG_EVENT(" DigestSizes :\n"); + for (i = 0U; i < number_of_algorithms; ++i) { + LOG_EVENT(" #%u AlgorithmId : SHA", i); + uint16_t algorithm_id = alg_ptr[i].algorithm_id; + + switch (algorithm_id) { + case TPM_ALG_SHA256: + (void)printf("256\n"); + break; + case TPM_ALG_SHA384: + (void)printf("384\n"); + break; + case TPM_ALG_SHA512: + (void)printf("512\n"); + break; + default: + (void)printf("?\n"); + ERROR("Algorithm 0x%x not found\n", algorithm_id); + assert(false); + } + + LOG_EVENT(" DigestSize : %u\n", + alg_ptr[i].digest_size); + } + + /* Address of VendorInfoSize */ + info_size_ptr = (uint8_t *)((uintptr_t)alg_ptr + digest_len); + assert((uintptr_t)info_size_ptr <= (uintptr_t)end_ptr); + + info_size = *info_size_ptr++; + LOG_EVENT(" VendorInfoSize : %u\n", info_size); + + /* Check VendorInfo end address */ + assert(((uintptr_t)info_size_ptr + info_size) <= (uintptr_t)end_ptr); + + /* Check EventSize */ + assert(event_size == (sizeof(id_event_struct_t) + + digest_len + info_size)); + if (info_size != 0U) { + LOG_EVENT(" VendorInfo :"); + for (i = 0U; i < info_size; ++i) { + (void)printf(" %02x", *info_size_ptr++); + } + (void)printf("\n"); + } + + *log_size -= (uintptr_t)info_size_ptr - (uintptr_t)*log_addr; + *log_addr = info_size_ptr; +} + +/* + * Print TCG_PCR_EVENT2 + * + * @param[in/out] log_addr Pointer to Event Log + * @param[in/out] log_size Pointer to Event Log size + */ +static void event2_print(uint8_t **log_addr, size_t *log_size) +{ + uint32_t event_size, count; + size_t sha_size, digests_size = 0U; + void *ptr = *log_addr; +#if ENABLE_ASSERTIONS + const uint8_t *end_ptr = (uint8_t *)((uintptr_t)*log_addr + *log_size); +#endif + + assert(*log_size >= sizeof(event2_header_t)); + + LOG_EVENT("PCR_Event2:\n"); + LOG_EVENT(" PCRIndex : %u\n", + ((event2_header_t *)ptr)->pcr_index); + LOG_EVENT(" EventType : %u\n", + ((event2_header_t *)ptr)->event_type); + + count = ((event2_header_t *)ptr)->digests.count; + LOG_EVENT(" Digests Count : %u\n", count); + + /* Address of TCG_PCR_EVENT2.Digests[] */ + ptr = (uint8_t *)ptr + sizeof(event2_header_t); + assert(((uintptr_t)ptr <= (uintptr_t)end_ptr) && (count != 0U)); + + for (unsigned int i = 0U; i < count; ++i) { + /* Check AlgorithmId address */ + assert(((uintptr_t)ptr + + offsetof(tpmt_ha, digest)) <= (uintptr_t)end_ptr); + + LOG_EVENT(" #%u AlgorithmId : SHA", i); + switch (((tpmt_ha *)ptr)->algorithm_id) { + case TPM_ALG_SHA256: + sha_size = SHA256_DIGEST_SIZE; + (void)printf("256\n"); + break; + case TPM_ALG_SHA384: + sha_size = SHA384_DIGEST_SIZE; + (void)printf("384\n"); + break; + case TPM_ALG_SHA512: + sha_size = SHA512_DIGEST_SIZE; + (void)printf("512\n"); + break; + default: + (void)printf("?\n"); + ERROR("Algorithm 0x%x not found\n", + ((tpmt_ha *)ptr)->algorithm_id); + panic(); + } + + /* End of Digest[] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(tpmt_ha, digest)); + assert(((uintptr_t)ptr + sha_size) <= (uintptr_t)end_ptr); + + /* Total size of all digests */ + digests_size += sha_size; + + LOG_EVENT(" Digest :"); + for (unsigned int j = 0U; j < sha_size; ++j) { + (void)printf(" %02x", *(uint8_t *)ptr++); + if ((j & U(0xF)) == U(0xF)) { + (void)printf("\n"); + if (j < (sha_size - 1U)) { + LOG_EVENT("\t\t :"); + } + } + } + } + + /* TCG_PCR_EVENT2.EventSize */ + assert(((uintptr_t)ptr + offsetof(event2_data_t, event)) <= (uintptr_t)end_ptr); + + event_size = ((event2_data_t *)ptr)->event_size; + LOG_EVENT(" EventSize : %u\n", event_size); + + /* Address of TCG_PCR_EVENT2.Event[EventSize] */ + ptr = (uint8_t *)((uintptr_t)ptr + offsetof(event2_data_t, event)); + + /* End of TCG_PCR_EVENT2.Event[EventSize] */ + assert(((uintptr_t)ptr + event_size) <= (uintptr_t)end_ptr); + + if ((event_size == sizeof(startup_locality_event_t)) && + (strcmp((const char *)ptr, TCG_STARTUP_LOCALITY_SIGNATURE) == 0)) { + LOG_EVENT(" Signature : %s\n", + ((startup_locality_event_t *)ptr)->signature); + LOG_EVENT(" StartupLocality : %u\n", + ((startup_locality_event_t *)ptr)->startup_locality); + } else { + LOG_EVENT(" Event : %s\n", (uint8_t *)ptr); + } + + *log_size -= (uintptr_t)ptr + event_size - (uintptr_t)*log_addr; + *log_addr = (uint8_t *)ptr + event_size; +} +#endif /* LOG_LEVEL >= EVENT_LOG_LEVEL */ + +/* + * Print Event Log + * + * @param[in] log_addr Pointer to Event Log + * @param[in] log_size Event Log size + */ +void dump_event_log(uint8_t *log_addr, size_t log_size) +{ +#if LOG_LEVEL >= EVENT_LOG_LEVEL + assert(log_addr != NULL); + + /* Print TCG_EfiSpecIDEvent */ + id_event_print(&log_addr, &log_size); + + while (log_size != 0U) { + event2_print(&log_addr, &log_size); + } +#endif +} diff --git a/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c b/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c new file mode 100644 index 0000000..b0270c9 --- /dev/null +++ b/arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c @@ -0,0 +1,614 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018 Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* + * This driver is for Mentor Graphics Inventra MI2CV IP core, which is used + * for Marvell and Allwinner SoCs in ATF. + */ + +#include + +#include +#include +#include +#include + +#include + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +#define DEBUG_I2C +#endif + +#define I2C_TIMEOUT_VALUE 0x500 +#define I2C_MAX_RETRY_CNT 1000 +#define I2C_CMD_WRITE 0x0 +#define I2C_CMD_READ 0x1 + +#define I2C_DATA_ADDR_7BIT_OFFS 0x1 +#define I2C_DATA_ADDR_7BIT_MASK (0xFF << I2C_DATA_ADDR_7BIT_OFFS) + +#define I2C_CONTROL_ACK 0x00000004 +#define I2C_CONTROL_IFLG 0x00000008 +#define I2C_CONTROL_STOP 0x00000010 +#define I2C_CONTROL_START 0x00000020 +#define I2C_CONTROL_TWSIEN 0x00000040 +#define I2C_CONTROL_INTEN 0x00000080 + +#define I2C_STATUS_START 0x08 +#define I2C_STATUS_REPEATED_START 0x10 +#define I2C_STATUS_ADDR_W_ACK 0x18 +#define I2C_STATUS_DATA_W_ACK 0x28 +#define I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER 0x38 +#define I2C_STATUS_ADDR_R_ACK 0x40 +#define I2C_STATUS_DATA_R_ACK 0x50 +#define I2C_STATUS_DATA_R_NAK 0x58 +#define I2C_STATUS_LOST_ARB_GENERAL_CALL 0x78 +#define I2C_STATUS_IDLE 0xF8 + +#define I2C_UNSTUCK_TRIGGER 0x1 +#define I2C_UNSTUCK_ONGOING 0x2 +#define I2C_UNSTUCK_ERROR 0x4 + +static struct mentor_i2c_regs *base; + +static int mentor_i2c_lost_arbitration(uint32_t *status) +{ + *status = mmio_read_32((uintptr_t)&base->status); + if ((*status == I2C_STATUS_LOST_ARB_DATA_ADDR_TRANSFER) || + (*status == I2C_STATUS_LOST_ARB_GENERAL_CALL)) + return -EAGAIN; + + return 0; +} + +static void mentor_i2c_interrupt_clear(void) +{ + uint32_t reg; + + reg = mmio_read_32((uintptr_t)&base->control); +#ifndef I2C_INTERRUPT_CLEAR_INVERTED + reg &= ~(I2C_CONTROL_IFLG); +#else + reg |= I2C_CONTROL_IFLG; +#endif + mmio_write_32((uintptr_t)&base->control, reg); + /* Wait for 1 us for the clear to take effect */ + udelay(1); +} + +static bool mentor_i2c_interrupt_get(void) +{ + uint32_t reg; + + /* get the interrupt flag bit */ + reg = mmio_read_32((uintptr_t)&base->control); + reg &= I2C_CONTROL_IFLG; + return (reg != 0U); +} + +static int mentor_i2c_wait_interrupt(void) +{ + uint32_t timeout = 0; + + while (!mentor_i2c_interrupt_get() && (timeout++ < I2C_TIMEOUT_VALUE)) + ; + if (timeout >= I2C_TIMEOUT_VALUE) + return -ETIMEDOUT; + + return 0; +} + +static int mentor_i2c_start_bit_set(void) +{ + int is_int_flag = 0; + uint32_t status; + + if (mentor_i2c_interrupt_get()) + is_int_flag = 1; + + /* set start bit */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_START); + + /* in case that the int flag was set before i.e. repeated start bit */ + if (is_int_flag) { + VERBOSE("%s: repeated start Bit\n", __func__); + mentor_i2c_interrupt_clear(); + } + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check that start bit went down */ + if ((mmio_read_32((uintptr_t)&base->control) & + I2C_CONTROL_START) != 0) { + ERROR("Start bit didn't went down\n"); + return -EPERM; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if ((status != I2C_STATUS_START) && + (status != I2C_STATUS_REPEATED_START)) { + ERROR("Got status %x after enable start bit.\n", status); + return -EPERM; + } + + return 0; +} + +static int mentor_i2c_stop_bit_set(void) +{ + int timeout; + uint32_t status; + + /* Generate stop bit */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_STOP); + mentor_i2c_interrupt_clear(); + + timeout = 0; + /* Read control register, check the control stop bit */ + while ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) && + (timeout++ < I2C_TIMEOUT_VALUE)) + ; + if (timeout >= I2C_TIMEOUT_VALUE) { + ERROR("Stop bit didn't went down\n"); + return -ETIMEDOUT; + } + + /* check that stop bit went down */ + if ((mmio_read_32((uintptr_t)&base->control) & I2C_CONTROL_STOP) != 0) { + ERROR("Stop bit didn't went down\n"); + return -EPERM; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (status != I2C_STATUS_IDLE) { + ERROR("Got status %x after enable stop bit.\n", status); + return -EPERM; + } + + return 0; +} + +static int mentor_i2c_address_set(uint8_t chain, int command) +{ + uint32_t reg, status; + + reg = (chain << I2C_DATA_ADDR_7BIT_OFFS) & I2C_DATA_ADDR_7BIT_MASK; + reg |= command; + mmio_write_32((uintptr_t)&base->data, reg); + udelay(1); + + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (((status != I2C_STATUS_ADDR_R_ACK) && (command == I2C_CMD_READ)) || + ((status != I2C_STATUS_ADDR_W_ACK) && (command == I2C_CMD_WRITE))) { + /* only in debug, since in boot we try to read the SPD + * of both DRAM, and we don't want error messages in cas + * DIMM doesn't exist. + */ + INFO("%s: ERROR - status %x addr in %s mode.\n", __func__, + status, (command == I2C_CMD_WRITE) ? "Write" : "Read"); + return -EPERM; + } + + return 0; +} + +/* + * The I2C module contains a clock divider to generate the SCL clock. + * This function calculates and sets the and fields in the I2C Baud + * Rate Register (t=01) to obtain given 'requested_speed'. + * The requested_speed will be equal to: + * CONFIG_SYS_TCLK / (10 * (M + 1) * (2 << N)) + * Where M is the value represented by bits[6:3] and N is the value represented + * by bits[2:0] of "I2C Baud Rate Register". + * Therefore max M which can be set is 16 (2^4) and max N is 8 (2^3). So the + * lowest possible baudrate is: + * CONFIG_SYS_TCLK/(10 * (16 +1) * (2 << 8), which equals to: + * CONFIG_SYS_TCLK/87040. Assuming that CONFIG_SYS_TCLK=250MHz, the lowest + * possible frequency is ~2,872KHz. + */ +static unsigned int mentor_i2c_bus_speed_set(unsigned int requested_speed) +{ + unsigned int n, m, freq, margin, min_margin = 0xffffffff; + unsigned int actual_n = 0, actual_m = 0; + int val; + + /* Calculate N and M for the TWSI clock baud rate */ + for (n = 0; n < 8; n++) { + for (m = 0; m < 16; m++) { + freq = CONFIG_SYS_TCLK / (10 * (m + 1) * (2 << n)); + val = requested_speed - freq; + margin = (val > 0) ? val : -val; + + if ((freq <= requested_speed) && + (margin < min_margin)) { + min_margin = margin; + actual_n = n; + actual_m = m; + } + } + } + VERBOSE("%s: actual_n = %u, actual_m = %u\n", + __func__, actual_n, actual_m); + /* Set the baud rate */ + mmio_write_32((uintptr_t)&base->baudrate, (actual_m << 3) | actual_n); + + return 0; +} + +#ifdef DEBUG_I2C +static int mentor_i2c_probe(uint8_t chip) +{ + int ret = 0; + + ret = mentor_i2c_start_bit_set(); + if (ret != 0) { + mentor_i2c_stop_bit_set(); + ERROR("%s - %d: %s", __func__, __LINE__, + "mentor_i2c_start_bit_set failed\n"); + return -EPERM; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret != 0) { + mentor_i2c_stop_bit_set(); + ERROR("%s - %d: %s", __func__, __LINE__, + "mentor_i2c_address_set failed\n"); + return -EPERM; + } + + mentor_i2c_stop_bit_set(); + + VERBOSE("%s: successful I2C probe\n", __func__); + + return ret; +} +#endif + +/* regular i2c transaction */ +static int mentor_i2c_data_receive(uint8_t *p_block, uint32_t block_size) +{ + uint32_t reg, status, block_size_read = block_size; + + /* Wait for cause interrupt */ + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + while (block_size_read) { + if (block_size_read == 1) { + reg = mmio_read_32((uintptr_t)&base->control); + reg &= ~(I2C_CONTROL_ACK); + mmio_write_32((uintptr_t)&base->control, reg); + } + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if ((status != I2C_STATUS_DATA_R_ACK) && + (block_size_read != 1)) { + ERROR("Status %x in read transaction\n", status); + return -EPERM; + } + if ((status != I2C_STATUS_DATA_R_NAK) && + (block_size_read == 1)) { + ERROR("Status %x in Rd Terminate\n", status); + return -EPERM; + } + + /* read the data */ + *p_block = (uint8_t) mmio_read_32((uintptr_t)&base->data); + VERBOSE("%s: place %d read %x\n", __func__, + block_size - block_size_read, *p_block); + p_block++; + block_size_read--; + } + + return 0; +} + +static int mentor_i2c_data_transmit(uint8_t *p_block, uint32_t block_size) +{ + uint32_t status, block_size_write = block_size; + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + while (block_size_write) { + /* write the data */ + mmio_write_32((uintptr_t)&base->data, (uint32_t) *p_block); + VERBOSE("%s: index = %d, data = %x\n", __func__, + block_size - block_size_write, *p_block); + p_block++; + block_size_write--; + + mentor_i2c_interrupt_clear(); + + if (mentor_i2c_wait_interrupt()) { + ERROR("Start clear bit timeout\n"); + return -ETIMEDOUT; + } + + /* check the status */ + if (mentor_i2c_lost_arbitration(&status)) { + ERROR("%s - %d: Lost arbitration, got status %x\n", + __func__, __LINE__, status); + return -EAGAIN; + } + if (status != I2C_STATUS_DATA_W_ACK) { + ERROR("Status %x in write transaction\n", status); + return -EPERM; + } + } + + return 0; +} + +static int mentor_i2c_target_offset_set(uint8_t chip, uint32_t addr, int alen) +{ + uint8_t off_block[2]; + uint32_t off_size; + + if (alen == 2) { /* 2-byte addresses support */ + off_block[0] = (addr >> 8) & 0xff; + off_block[1] = addr & 0xff; + off_size = 2; + } else { /* 1-byte addresses support */ + off_block[0] = addr & 0xff; + off_size = 1; + } + VERBOSE("%s: off_size = %x addr1 = %x addr2 = %x\n", __func__, + off_size, off_block[0], off_block[1]); + return mentor_i2c_data_transmit(off_block, off_size); +} + +#ifdef I2C_CAN_UNSTUCK +static int mentor_i2c_unstuck(int ret) +{ + uint32_t v; + + if (ret != -ETIMEDOUT) + return ret; + VERBOSE("Trying to \"unstuck i2c\"... "); + i2c_init(base); + mmio_write_32((uintptr_t)&base->unstuck, I2C_UNSTUCK_TRIGGER); + do { + v = mmio_read_32((uintptr_t)&base->unstuck); + } while (v & I2C_UNSTUCK_ONGOING); + + if (v & I2C_UNSTUCK_ERROR) { + VERBOSE("failed - soft reset i2c\n"); + ret = -EPERM; + } else { + VERBOSE("ok\n"); + i2c_init(base); + ret = -EAGAIN; + } + return ret; +} +#else +static int mentor_i2c_unstuck(int ret) +{ + VERBOSE("Cannot \"unstuck i2c\" - soft reset i2c\n"); + return -EPERM; +} +#endif + +/* + * API Functions + */ +void i2c_init(void *i2c_base) +{ + /* For I2C speed and slave address, now we do not set them since + * we just provide the working speed and slave address otherwhere + * for i2c_init + */ + base = (struct mentor_i2c_regs *)i2c_base; + + /* Reset the I2C logic */ + mmio_write_32((uintptr_t)&base->soft_reset, 0); + + udelay(200); + + mentor_i2c_bus_speed_set(CONFIG_SYS_I2C_SPEED); + + /* Enable the I2C and slave */ + mmio_write_32((uintptr_t)&base->control, + I2C_CONTROL_TWSIEN | I2C_CONTROL_ACK); + + /* set the I2C slave address */ + mmio_write_32((uintptr_t)&base->xtnd_slave_addr, 0); + mmio_write_32((uintptr_t)&base->slave_address, CONFIG_SYS_I2C_SLAVE); + + /* unmask I2C interrupt */ + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_INTEN); + + udelay(10); +} + +/* + * i2c_read: - Read multiple bytes from an i2c device + * + * The higher level routines take into account that this function is only + * called with len < page length of the device (see configuration file) + * + * @chip: address of the chip which is to be read + * @addr: i2c data address within the chip + * @alen: length of the i2c data address (1..2 bytes) + * @buffer: where to write the data + * @len: how much byte do we want to read + * @return: 0 in case of success + */ +int i2c_read(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) +{ + int ret = 0; + uint32_t counter = 0; + +#ifdef DEBUG_I2C + mentor_i2c_probe(chip); +#endif + + do { + if (ret != -EAGAIN && ret) { + ERROR("i2c transaction failed, after %d retries\n", + counter); + mentor_i2c_stop_bit_set(); + return ret; + } + + /* wait for 1 us for the interrupt clear to take effect */ + if (counter > 0) + udelay(1); + counter++; + + ret = mentor_i2c_start_bit_set(); + if (ret) { + ret = mentor_i2c_unstuck(ret); + continue; + } + + /* if EEPROM device */ + if (alen != 0) { + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret) + continue; + + ret = mentor_i2c_target_offset_set(chip, addr, alen); + if (ret) + continue; + ret = mentor_i2c_start_bit_set(); + if (ret) + continue; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_READ); + if (ret) + continue; + + ret = mentor_i2c_data_receive(buffer, len); + if (ret) + continue; + + ret = mentor_i2c_stop_bit_set(); + } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); + + if (counter == I2C_MAX_RETRY_CNT) { + ERROR("I2C transactions failed, got EAGAIN %d times\n", + I2C_MAX_RETRY_CNT); + ret = -EPERM; + } + mmio_write_32((uintptr_t)&base->control, + mmio_read_32((uintptr_t)&base->control) | + I2C_CONTROL_ACK); + + udelay(1); + return ret; +} + +/* + * i2c_write: - Write multiple bytes to an i2c device + * + * The higher level routines take into account that this function is only + * called with len < page length of the device (see configuration file) + * + * @chip: address of the chip which is to be written + * @addr: i2c data address within the chip + * @alen: length of the i2c data address (1..2 bytes) + * @buffer: where to find the data to be written + * @len: how much byte do we want to read + * @return: 0 in case of success + */ +int i2c_write(uint8_t chip, uint32_t addr, int alen, uint8_t *buffer, int len) +{ + int ret = 0; + uint32_t counter = 0; + + do { + if (ret != -EAGAIN && ret) { + ERROR("i2c transaction failed\n"); + mentor_i2c_stop_bit_set(); + return ret; + } + /* wait for 1 us for the interrupt clear to take effect */ + if (counter > 0) + udelay(1); + counter++; + + ret = mentor_i2c_start_bit_set(); + if (ret) { + ret = mentor_i2c_unstuck(ret); + continue; + } + + ret = mentor_i2c_address_set(chip, I2C_CMD_WRITE); + if (ret) + continue; + + /* if EEPROM device */ + if (alen != 0) { + ret = mentor_i2c_target_offset_set(chip, addr, alen); + if (ret) + continue; + } + + ret = mentor_i2c_data_transmit(buffer, len); + if (ret) + continue; + + ret = mentor_i2c_stop_bit_set(); + } while ((ret == -EAGAIN) && (counter < I2C_MAX_RETRY_CNT)); + + if (counter == I2C_MAX_RETRY_CNT) { + ERROR("I2C transactions failed, got EAGAIN %d times\n", + I2C_MAX_RETRY_CNT); + ret = -EPERM; + } + + udelay(1); + return ret; +} diff --git a/arm-trusted-firmware/drivers/mmc/mmc.c b/arm-trusted-firmware/drivers/mmc/mmc.c new file mode 100644 index 0000000..c327e71 --- /dev/null +++ b/arm-trusted-firmware/drivers/mmc/mmc.c @@ -0,0 +1,811 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Define a simple and generic interface to access eMMC and SD-card devices. */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MMC_DEFAULT_MAX_RETRIES 5 +#define SEND_OP_COND_MAX_RETRIES 100 + +#define MULT_BY_512K_SHIFT 19 + +static const struct mmc_ops *ops; +static unsigned int mmc_ocr_value; +static struct mmc_csd_emmc mmc_csd; +static unsigned char mmc_ext_csd[512] __aligned(16); +static unsigned int mmc_flags; +static struct mmc_device_info *mmc_dev_info; +static unsigned int rca; +static unsigned int scr[2]__aligned(16) = { 0 }; + +static const unsigned char tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 26, 30, 35, 40, 45, 52, 55, 60, 70, 80 +}; + +static const unsigned char sd_tran_speed_base[16] = { + 0, 10, 12, 13, 15, 20, 25, 30, 35, 40, 45, 50, 55, 60, 70, 80 +}; + +static bool is_cmd23_enabled(void) +{ + return ((mmc_flags & MMC_FLAG_CMD23) != 0U); +} + +static int mmc_send_cmd(unsigned int idx, unsigned int arg, + unsigned int r_type, unsigned int *r_data) +{ + struct mmc_cmd cmd; + int ret; + + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = idx; + cmd.cmd_arg = arg; + cmd.resp_type = r_type; + + ret = ops->send_cmd(&cmd); + + if ((ret == 0) && (r_data != NULL)) { + int i; + + for (i = 0; i < 4; i++) { + *r_data = cmd.resp_data[i]; + r_data++; + } + } + + if (ret != 0) { + VERBOSE("Send command %u error: %d\n", idx, ret); + } + + return ret; +} + +static int mmc_device_state(void) +{ + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int resp_data[4]; + + do { + int ret; + + if (retries == 0) { + ERROR("CMD13 failed after %d retries\n", + MMC_DEFAULT_MAX_RETRIES); + return -EIO; + } + + ret = mmc_send_cmd(MMC_CMD(13), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, &resp_data[0]); + if (ret != 0) { + retries--; + continue; + } + + if ((resp_data[0] & STATUS_SWITCH_ERROR) != 0U) { + return -EIO; + } + + retries--; + } while ((resp_data[0] & STATUS_READY_FOR_DATA) == 0U); + + return MMC_GET_STATE(resp_data[0]); +} + +static int mmc_send_part_switch_cmd(unsigned int part_config) +{ + int ret; + unsigned int part_time = 0; + + ret = mmc_send_cmd(MMC_CMD(6), + EXTCSD_WRITE_BYTES | + EXTCSD_CMD(CMD_EXTCSD_PARTITION_CONFIG) | + EXTCSD_VALUE(part_config) | + EXTCSD_CMD_SET_NORMAL, + MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return ret; + } + + /* Partition switch timing is in 10ms units */ + part_time = mmc_ext_csd[CMD_EXTCSD_PART_SWITCH_TIME] * 10; + + mdelay(part_time); + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_set_ext_csd(unsigned int ext_cmd, unsigned int value) +{ + int ret; + + ret = mmc_send_cmd(MMC_CMD(6), + EXTCSD_WRITE_BYTES | EXTCSD_CMD(ext_cmd) | + EXTCSD_VALUE(value) | EXTCSD_CMD_SET_NORMAL, + MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_sd_switch(unsigned int bus_width) +{ + int ret; + int retries = MMC_DEFAULT_MAX_RETRIES; + unsigned int bus_width_arg = 0; + + ret = ops->prepare(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R5, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD51: SEND_SCR */ + do { + ret = mmc_send_cmd(MMC_ACMD(51), 0, MMC_RESPONSE_R1, NULL); + if ((ret != 0) && (retries == 0)) { + ERROR("ACMD51 failed after %d retries (ret=%d)\n", + MMC_DEFAULT_MAX_RETRIES, ret); + return ret; + } + + retries--; + } while (ret != 0); + + ret = ops->read(0, (uintptr_t)&scr, sizeof(scr)); + if (ret != 0) { + return ret; + } + + if (((scr[0] & SD_SCR_BUS_WIDTH_4) != 0U) && + (bus_width == MMC_BUS_WIDTH_4)) { + bus_width_arg = 2; + } + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R5, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD6: SET_BUS_WIDTH */ + ret = mmc_send_cmd(MMC_ACMD(6), bus_width_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret == MMC_STATE_PRG); + + return 0; +} + +static int mmc_set_ios(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int width = bus_width; + + if (mmc_dev_info->mmc_dev_type != MMC_IS_EMMC) { + if (width == MMC_BUS_WIDTH_8) { + WARN("Wrong bus config for SD-card, force to 4\n"); + width = MMC_BUS_WIDTH_4; + } + ret = mmc_sd_switch(width); + if (ret != 0) { + return ret; + } + } else if (mmc_csd.spec_vers == 4U) { + ret = mmc_set_ext_csd(CMD_EXTCSD_BUS_WIDTH, + (unsigned int)width); + if (ret != 0) { + return ret; + } + } else { + VERBOSE("Wrong MMC type or spec version\n"); + } + + return ops->set_ios(clk, width); +} + +static int mmc_fill_device_info(void) +{ + unsigned long long c_size; + unsigned int speed_idx; + unsigned int nb_blocks; + unsigned int freq_unit; + int ret = 0; + struct mmc_csd_sd_v2 *csd_sd_v2; + + switch (mmc_dev_info->mmc_dev_type) { + case MMC_IS_EMMC: + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + ret = ops->prepare(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + /* MMC CMD8: SEND_EXT_CSD */ + ret = mmc_send_cmd(MMC_CMD(8), 0, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + ret = ops->read(0, (uintptr_t)&mmc_ext_csd, + sizeof(mmc_ext_csd)); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret != MMC_STATE_TRAN); + + nb_blocks = (mmc_ext_csd[CMD_EXTCSD_SEC_CNT] << 0) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 1] << 8) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 2] << 16) | + (mmc_ext_csd[CMD_EXTCSD_SEC_CNT + 3] << 24); + + mmc_dev_info->device_size = (unsigned long long)nb_blocks * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD: + /* + * Use the same mmc_csd struct, as required fields here + * (READ_BL_LEN, C_SIZE, CSIZE_MULT) are common with eMMC. + */ + mmc_dev_info->block_size = BIT_32(mmc_csd.read_bl_len); + + c_size = ((unsigned long long)mmc_csd.c_size_high << 2U) | + (unsigned long long)mmc_csd.c_size_low; + assert(c_size != 0xFFFU); + + mmc_dev_info->device_size = (c_size + 1U) * + BIT_64(mmc_csd.c_size_mult + 2U) * + mmc_dev_info->block_size; + + break; + + case MMC_IS_SD_HC: + assert(mmc_csd.csd_structure == 1U); + + mmc_dev_info->block_size = MMC_BLOCK_SIZE; + + /* Need to use mmc_csd_sd_v2 struct */ + csd_sd_v2 = (struct mmc_csd_sd_v2 *)&mmc_csd; + c_size = ((unsigned long long)csd_sd_v2->c_size_high << 16) | + (unsigned long long)csd_sd_v2->c_size_low; + + mmc_dev_info->device_size = (c_size + 1U) << MULT_BY_512K_SHIFT; + + break; + + default: + ret = -EINVAL; + break; + } + + if (ret < 0) { + return ret; + } + + speed_idx = (mmc_csd.tran_speed & CSD_TRAN_SPEED_MULT_MASK) >> + CSD_TRAN_SPEED_MULT_SHIFT; + + assert(speed_idx > 0U); + + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + mmc_dev_info->max_bus_freq = tran_speed_base[speed_idx]; + } else { + mmc_dev_info->max_bus_freq = sd_tran_speed_base[speed_idx]; + } + + freq_unit = mmc_csd.tran_speed & CSD_TRAN_SPEED_UNIT_MASK; + while (freq_unit != 0U) { + mmc_dev_info->max_bus_freq *= 10U; + --freq_unit; + } + + mmc_dev_info->max_bus_freq *= 10000U; + + return 0; +} + +static int sd_send_op_cond(void) +{ + int n; + unsigned int resp_data[4]; + + for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) { + int ret; + + /* CMD55: Application Specific Command */ + ret = mmc_send_cmd(MMC_CMD(55), 0, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + /* ACMD41: SD_SEND_OP_COND */ + ret = mmc_send_cmd(MMC_ACMD(41), OCR_HCS | + mmc_dev_info->ocr_voltage, MMC_RESPONSE_R3, + &resp_data[0]); + if (ret != 0) { + return ret; + } + + if ((resp_data[0] & OCR_POWERUP) != 0U) { + mmc_ocr_value = resp_data[0]; + + if ((mmc_ocr_value & OCR_HCS) != 0U) { + mmc_dev_info->mmc_dev_type = MMC_IS_SD_HC; + } else { + mmc_dev_info->mmc_dev_type = MMC_IS_SD; + } + + return 0; + } + + mdelay(10); + } + + ERROR("ACMD41 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); + + return -EIO; +} + +static int mmc_reset_to_idle(void) +{ + int ret; + + /* CMD0: reset to IDLE */ + ret = mmc_send_cmd(MMC_CMD(0), 0, 0, NULL); + if (ret != 0) { + return ret; + } + + mdelay(2); + + return 0; +} + +static int mmc_send_op_cond(void) +{ + int ret, n; + unsigned int resp_data[4]; + + ret = mmc_reset_to_idle(); + if (ret != 0) { + return ret; + } + + for (n = 0; n < SEND_OP_COND_MAX_RETRIES; n++) { + ret = mmc_send_cmd(MMC_CMD(1), OCR_SECTOR_MODE | + OCR_VDD_MIN_2V7 | OCR_VDD_MIN_1V7, + MMC_RESPONSE_R3, &resp_data[0]); + if (ret != 0) { + return ret; + } + + if ((resp_data[0] & OCR_POWERUP) != 0U) { + mmc_ocr_value = resp_data[0]; + return 0; + } + + mdelay(10); + } + + ERROR("CMD1 failed after %d retries\n", SEND_OP_COND_MAX_RETRIES); + + return -EIO; +} + +static int mmc_enumerate(unsigned int clk, unsigned int bus_width) +{ + int ret; + unsigned int resp_data[4]; + + ops->init(); + + ret = mmc_reset_to_idle(); + if (ret != 0) { + return ret; + } + + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + ret = mmc_send_op_cond(); + } else { + /* CMD8: Send Interface Condition Command */ + ret = mmc_send_cmd(MMC_CMD(8), VHS_2_7_3_6_V | CMD8_CHECK_PATTERN, + MMC_RESPONSE_R5, &resp_data[0]); + + if ((ret == 0) && ((resp_data[0] & 0xffU) == CMD8_CHECK_PATTERN)) { + ret = sd_send_op_cond(); + } + } + if (ret != 0) { + return ret; + } + + /* CMD2: Card Identification */ + ret = mmc_send_cmd(MMC_CMD(2), 0, MMC_RESPONSE_R2, NULL); + if (ret != 0) { + return ret; + } + + /* CMD3: Set Relative Address */ + if (mmc_dev_info->mmc_dev_type == MMC_IS_EMMC) { + rca = MMC_FIX_RCA; + ret = mmc_send_cmd(MMC_CMD(3), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + } else { + ret = mmc_send_cmd(MMC_CMD(3), 0, + MMC_RESPONSE_R6, &resp_data[0]); + if (ret != 0) { + return ret; + } + + rca = (resp_data[0] & 0xFFFF0000U) >> 16; + } + + /* CMD9: CSD Register */ + ret = mmc_send_cmd(MMC_CMD(9), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R2, &resp_data[0]); + if (ret != 0) { + return ret; + } + + memcpy(&mmc_csd, &resp_data, sizeof(resp_data)); + + /* CMD7: Select Card */ + ret = mmc_send_cmd(MMC_CMD(7), rca << RCA_SHIFT_OFFSET, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return ret; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return ret; + } + } while (ret != MMC_STATE_TRAN); + + ret = mmc_set_ios(clk, bus_width); + if (ret != 0) { + return ret; + } + + return mmc_fill_device_info(); +} + +size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->read != NULL) && + (size != 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(18); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(18); + } else { + cmd_idx = MMC_CMD(17); + } + } + + if (((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) && + (mmc_dev_info->mmc_dev_type != MMC_IS_SD_HC)) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = ops->read(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_DATA)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size) +{ + int ret; + unsigned int cmd_idx, cmd_arg; + + assert((ops != NULL) && + (ops->write != NULL) && + (size != 0U) && + ((buf & MMC_BLOCK_MASK) == 0U) && + ((size & MMC_BLOCK_MASK) == 0U)); + + ret = ops->prepare(lba, buf, size); + if (ret != 0) { + return 0; + } + + if (is_cmd23_enabled()) { + /* Set block count */ + ret = mmc_send_cmd(MMC_CMD(23), size / MMC_BLOCK_SIZE, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + cmd_idx = MMC_CMD(25); + } else { + if (size > MMC_BLOCK_SIZE) { + cmd_idx = MMC_CMD(25); + } else { + cmd_idx = MMC_CMD(24); + } + } + + if ((mmc_ocr_value & OCR_ACCESS_MODE_MASK) == OCR_BYTE_MODE) { + cmd_arg = lba * MMC_BLOCK_SIZE; + } else { + cmd_arg = lba; + } + + ret = mmc_send_cmd(cmd_idx, cmd_arg, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = ops->write(lba, buf, size); + if (ret != 0) { + return 0; + } + + /* Wait buffer empty */ + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while ((ret != MMC_STATE_TRAN) && (ret != MMC_STATE_RCV)); + + if (!is_cmd23_enabled() && (size > MMC_BLOCK_SIZE)) { + ret = mmc_send_cmd(MMC_CMD(12), 0, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + } + + return size; +} + +size_t mmc_erase_blocks(int lba, size_t size) +{ + int ret; + + assert(ops != NULL); + assert((size != 0U) && ((size & MMC_BLOCK_MASK) == 0U)); + + ret = mmc_send_cmd(MMC_CMD(35), lba, MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(36), lba + (size / MMC_BLOCK_SIZE) - 1U, + MMC_RESPONSE_R1, NULL); + if (ret != 0) { + return 0; + } + + ret = mmc_send_cmd(MMC_CMD(38), lba, MMC_RESPONSE_R1B, NULL); + if (ret != 0) { + return 0; + } + + do { + ret = mmc_device_state(); + if (ret < 0) { + return 0; + } + } while (ret != MMC_STATE_TRAN); + + return size; +} + +static inline void mmc_rpmb_enable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE | + PART_CFG_BOOT_PARTITION1_ACCESS); +} + +static inline void mmc_rpmb_disable(void) +{ + mmc_set_ext_csd(CMD_EXTCSD_PARTITION_CONFIG, + PART_CFG_BOOT_PARTITION1_ENABLE); +} + +size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size) +{ + size_t size_read; + + mmc_rpmb_enable(); + size_read = mmc_read_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_read; +} + +size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size) +{ + size_t size_written; + + mmc_rpmb_enable(); + size_written = mmc_write_blocks(lba, buf, size); + mmc_rpmb_disable(); + + return size_written; +} + +size_t mmc_rpmb_erase_blocks(int lba, size_t size) +{ + size_t size_erased; + + mmc_rpmb_enable(); + size_erased = mmc_erase_blocks(lba, size); + mmc_rpmb_disable(); + + return size_erased; +} + +static int mmc_part_switch(unsigned int part_type) +{ + uint8_t part_config = mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]; + + part_config &= ~EXT_CSD_PART_CONFIG_ACC_MASK; + part_config |= part_type; + + return mmc_send_part_switch_cmd(part_config); +} + +static unsigned char mmc_current_boot_part(void) +{ + return PART_CFG_CURRENT_BOOT_PARTITION(mmc_ext_csd[CMD_EXTCSD_PARTITION_CONFIG]); +} + +size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size) +{ + size_t size_read; + int ret; + unsigned char current_boot_part = mmc_current_boot_part(); + + if (current_boot_part != 1U && + current_boot_part != 2U) { + ERROR("Got unexpected value for active boot partition, %u\n", current_boot_part); + return 0; + } + + ret = mmc_part_switch(current_boot_part); + if (ret < 0) { + ERROR("Failed to switch to boot partition, %d\n", ret); + return 0; + } + + size_read = mmc_read_blocks(lba, buf, size); + + ret = mmc_part_switch(0); + if (ret < 0) { + ERROR("Failed to switch back to user partition, %d\n", ret); + return 0; + } + + return size_read; +} + +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info) +{ + assert((ops_ptr != NULL) && + (ops_ptr->init != NULL) && + (ops_ptr->send_cmd != NULL) && + (ops_ptr->set_ios != NULL) && + (ops_ptr->prepare != NULL) && + (ops_ptr->read != NULL) && + (ops_ptr->write != NULL) && + (device_info != NULL) && + (clk != 0) && + ((width == MMC_BUS_WIDTH_1) || + (width == MMC_BUS_WIDTH_4) || + (width == MMC_BUS_WIDTH_8) || + (width == MMC_BUS_WIDTH_DDR_4) || + (width == MMC_BUS_WIDTH_DDR_8))); + + ops = ops_ptr; + mmc_flags = flags; + mmc_dev_info = device_info; + + return mmc_enumerate(clk, width); +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/core.c b/arm-trusted-firmware/drivers/mtd/nand/core.c new file mode 100644 index 0000000..9f0331a --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/core.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include + +/* + * Define a single nand_device used by specific NAND frameworks. + */ +static struct nand_device nand_dev; +static uint8_t scratch_buff[PLATFORM_MTD_MAX_PAGE_SIZE]; + +int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read) +{ + unsigned int block = offset / nand_dev.block_size; + unsigned int end_block = (offset + length - 1U) / nand_dev.block_size; + unsigned int page_start = + (offset % nand_dev.block_size) / nand_dev.page_size; + unsigned int nb_pages = nand_dev.block_size / nand_dev.page_size; + unsigned int start_offset = offset % nand_dev.page_size; + unsigned int page; + unsigned int bytes_read; + int is_bad; + int ret; + + VERBOSE("Block %u - %u, page_start %u, nb %u, length %zu, offset %u\n", + block, end_block, page_start, nb_pages, length, offset); + + *length_read = 0UL; + + if (((start_offset != 0U) || (length % nand_dev.page_size) != 0U) && + (sizeof(scratch_buff) < nand_dev.page_size)) { + return -EINVAL; + } + + while (block <= end_block) { + is_bad = nand_dev.mtd_block_is_bad(block); + if (is_bad < 0) { + return is_bad; + } + + if (is_bad == 1) { + /* Skip the block */ + uint32_t max_block = + nand_dev.size / nand_dev.block_size; + + block++; + end_block++; + if ((block < max_block) && (end_block < max_block)) { + continue; + } + + return -EIO; + } + + for (page = page_start; page < nb_pages; page++) { + if ((start_offset != 0U) || + (length < nand_dev.page_size)) { + ret = nand_dev.mtd_read_page( + &nand_dev, + (block * nb_pages) + page, + (uintptr_t)scratch_buff); + if (ret != 0) { + return ret; + } + + bytes_read = MIN((size_t)(nand_dev.page_size - + start_offset), + length); + + memcpy((uint8_t *)buffer, + scratch_buff + start_offset, + bytes_read); + + start_offset = 0U; + } else { + ret = nand_dev.mtd_read_page(&nand_dev, + (block * nb_pages) + page, + buffer); + if (ret != 0) { + return ret; + } + + bytes_read = nand_dev.page_size; + } + + length -= bytes_read; + buffer += bytes_read; + *length_read += bytes_read; + + if (length == 0U) { + break; + } + } + + page_start = 0U; + block++; + } + + return 0; +} + +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset) +{ + unsigned int block; + unsigned int offset_block; + unsigned int max_block; + int is_bad; + size_t count_bb = 0U; + + block = base / nand_dev.block_size; + + if (offset != 0U) { + offset_block = (base + offset - 1U) / nand_dev.block_size; + } else { + offset_block = block; + } + + max_block = nand_dev.size / nand_dev.block_size; + + while (block <= offset_block) { + if (offset_block >= max_block) { + return -EIO; + } + + is_bad = nand_dev.mtd_block_is_bad(block); + if (is_bad < 0) { + return is_bad; + } + + if (is_bad == 1) { + count_bb++; + offset_block++; + } + + block++; + } + + *extra_offset = count_bb * nand_dev.block_size; + + return 0; +} + +struct nand_device *get_nand_device(void) +{ + return &nand_dev; +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c b/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c new file mode 100644 index 0000000..021e30b --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/raw_nand.c @@ -0,0 +1,443 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define ONFI_SIGNATURE_ADDR 0x20U + +/* CRC calculation */ +#define CRC_POLYNOM 0x8005U +#define CRC_INIT_VALUE 0x4F4EU + +/* Status register */ +#define NAND_STATUS_READY BIT(6) + +static struct rawnand_device rawnand_dev; + +#pragma weak plat_get_raw_nand_data +int plat_get_raw_nand_data(struct rawnand_device *device) +{ + return 0; +} + +static int nand_send_cmd(uint8_t cmd, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_CMD | cmd; + req.inst_delay = tim; + + return rawnand_dev.ops->exec(&req); +} + +static int nand_send_addr(uint8_t addr, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_ADDR; + req.addr = &addr; + req.inst_delay = tim; + + return rawnand_dev.ops->exec(&req); +} + +static int nand_send_wait(unsigned int delay, unsigned int tim) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_WAIT; + req.inst_delay = tim; + req.delay_ms = delay; + + return rawnand_dev.ops->exec(&req); +} + + +static int nand_read_data(uint8_t *data, unsigned int length, bool use_8bit) +{ + struct nand_req req; + + zeromem(&req, sizeof(struct nand_req)); + req.nand = rawnand_dev.nand_dev; + req.type = NAND_REQ_DATAIN | (use_8bit ? NAND_REQ_BUS_WIDTH_8 : 0U); + req.addr = data; + req.length = length; + + return rawnand_dev.ops->exec(&req); +} + +int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, + unsigned int len) +{ + int ret; + uint8_t addr[2]; + unsigned int i; + + ret = nand_send_cmd(NAND_CMD_CHANGE_1ST, 0U); + if (ret != 0) { + return ret; + } + + if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { + offset /= 2U; + } + + addr[0] = offset; + addr[1] = offset >> 8; + + for (i = 0; i < 2U; i++) { + ret = nand_send_addr(addr[i], 0U); + if (ret != 0) { + return ret; + } + } + + ret = nand_send_cmd(NAND_CMD_CHANGE_2ND, NAND_TCCS_MIN); + if (ret != 0) { + return ret; + } + + return nand_read_data((uint8_t *)buffer, len, false); +} + +int nand_read_page_cmd(unsigned int page, unsigned int offset, + uintptr_t buffer, unsigned int len) +{ + uint8_t addr[5]; + uint8_t i = 0U; + uint8_t j; + int ret; + + VERBOSE(">%s page %u offset %u buffer 0x%lx\n", __func__, page, offset, + buffer); + + if (rawnand_dev.nand_dev->buswidth == NAND_BUS_WIDTH_16) { + offset /= 2U; + } + + addr[i++] = offset; + addr[i++] = offset >> 8; + + addr[i++] = page; + addr[i++] = page >> 8; + if (rawnand_dev.nand_dev->size > SZ_128M) { + addr[i++] = page >> 16; + } + + ret = nand_send_cmd(NAND_CMD_READ_1ST, 0U); + if (ret != 0) { + return ret; + } + + for (j = 0U; j < i; j++) { + ret = nand_send_addr(addr[j], 0U); + if (ret != 0) { + return ret; + } + } + + ret = nand_send_cmd(NAND_CMD_READ_2ND, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); + if (ret != 0) { + return ret; + } + + if (buffer != 0U) { + ret = nand_read_data((uint8_t *)buffer, len, false); + } + + return ret; +} + +static int nand_status(uint8_t *status) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_STATUS, NAND_TWHR_MIN); + if (ret != 0) { + return ret; + } + + if (status != NULL) { + ret = nand_read_data(status, 1U, true); + } + + return ret; +} + +int nand_wait_ready(unsigned int delay_ms) +{ + uint8_t status; + int ret; + uint64_t timeout; + + /* Wait before reading status */ + udelay(1); + + ret = nand_status(NULL); + if (ret != 0) { + return ret; + } + + timeout = timeout_init_us(delay_ms * 1000U); + while (!timeout_elapsed(timeout)) { + ret = nand_read_data(&status, 1U, true); + if (ret != 0) { + return ret; + } + + if ((status & NAND_STATUS_READY) != 0U) { + return nand_send_cmd(NAND_CMD_READ_1ST, 0U); + } + + udelay(10); + } + + return -ETIMEDOUT; +} + +#if NAND_ONFI_DETECT +static uint16_t nand_check_crc(uint16_t crc, uint8_t *data_in, + unsigned int data_len) +{ + uint32_t i; + uint32_t j; + uint32_t bit; + + for (i = 0U; i < data_len; i++) { + uint8_t cur_param = *data_in++; + + for (j = BIT(7); j != 0U; j >>= 1) { + bit = crc & BIT(15); + crc <<= 1; + + if ((cur_param & j) != 0U) { + bit ^= BIT(15); + } + + if (bit != 0U) { + crc ^= CRC_POLYNOM; + } + } + + crc &= GENMASK(15, 0); + } + + return crc; +} + +static int nand_read_id(uint8_t addr, uint8_t *id, unsigned int size) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_READID, 0U); + if (ret != 0) { + return ret; + } + + ret = nand_send_addr(addr, NAND_TWHR_MIN); + if (ret != 0) { + return ret; + } + + return nand_read_data(id, size, true); +} + +static int nand_reset(void) +{ + int ret; + + ret = nand_send_cmd(NAND_CMD_RESET, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + return nand_send_wait(PSEC_TO_MSEC(NAND_TRST_MAX), 0U); +} + +static int nand_read_param_page(void) +{ + struct nand_param_page page; + uint8_t addr = 0U; + int ret; + + ret = nand_send_cmd(NAND_CMD_READ_PARAM_PAGE, 0U); + if (ret != 0) { + return ret; + } + + ret = nand_send_addr(addr, NAND_TWB_MAX); + if (ret != 0) { + return ret; + } + + ret = nand_send_wait(PSEC_TO_MSEC(NAND_TR_MAX), NAND_TRR_MIN); + if (ret != 0) { + return ret; + } + + ret = nand_read_data((uint8_t *)&page, sizeof(page), true); + if (ret != 0) { + return ret; + } + + if (strncmp((char *)&page.page_sig, "ONFI", 4) != 0) { + WARN("Error ONFI detection\n"); + return -EINVAL; + } + + if (nand_check_crc(CRC_INIT_VALUE, (uint8_t *)&page, 254U) != + page.crc16) { + WARN("Error reading param\n"); + return -EINVAL; + } + + if ((page.features & ONFI_FEAT_BUS_WIDTH_16) != 0U) { + rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_16; + } else { + rawnand_dev.nand_dev->buswidth = NAND_BUS_WIDTH_8; + } + + rawnand_dev.nand_dev->block_size = page.num_pages_per_blk * + page.bytes_per_page; + rawnand_dev.nand_dev->page_size = page.bytes_per_page; + rawnand_dev.nand_dev->size = page.num_pages_per_blk * + page.bytes_per_page * + page.num_blk_in_lun * page.num_lun; + + if (page.nb_ecc_bits != GENMASK_32(7, 0)) { + rawnand_dev.nand_dev->ecc.max_bit_corr = page.nb_ecc_bits; + rawnand_dev.nand_dev->ecc.size = SZ_512; + } + + VERBOSE("Page size %u, block_size %u, Size %llu, ecc %u, buswidth %u\n", + rawnand_dev.nand_dev->page_size, + rawnand_dev.nand_dev->block_size, rawnand_dev.nand_dev->size, + rawnand_dev.nand_dev->ecc.max_bit_corr, + rawnand_dev.nand_dev->buswidth); + + return 0; +} + +static int detect_onfi(void) +{ + int ret; + char id[4]; + + ret = nand_reset(); + if (ret != 0) { + return ret; + } + + ret = nand_read_id(ONFI_SIGNATURE_ADDR, (uint8_t *)id, sizeof(id)); + if (ret != 0) { + return ret; + } + + if (strncmp(id, "ONFI", sizeof(id)) != 0) { + WARN("NAND Non ONFI detected\n"); + return -ENODEV; + } + + return nand_read_param_page(); +} +#endif + +static int nand_mtd_block_is_bad(unsigned int block) +{ + unsigned int nbpages_per_block = rawnand_dev.nand_dev->block_size / + rawnand_dev.nand_dev->page_size; + uint8_t bbm_marker[2]; + uint8_t page; + int ret; + + for (page = 0U; page < 2U; page++) { + ret = nand_read_page_cmd(block * nbpages_per_block, + rawnand_dev.nand_dev->page_size, + (uintptr_t)bbm_marker, + sizeof(bbm_marker)); + if (ret != 0) { + return ret; + } + + if ((bbm_marker[0] != GENMASK_32(7, 0)) || + (bbm_marker[1] != GENMASK_32(7, 0))) { + WARN("Block %u is bad\n", block); + return 1; + } + } + + return 0; +} + +static int nand_mtd_read_page_raw(struct nand_device *nand, unsigned int page, + uintptr_t buffer) +{ + return nand_read_page_cmd(page, 0U, buffer, + rawnand_dev.nand_dev->page_size); +} + +void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops) +{ + rawnand_dev.ops = ops; +} + +int nand_raw_init(unsigned long long *size, unsigned int *erase_size) +{ + rawnand_dev.nand_dev = get_nand_device(); + if (rawnand_dev.nand_dev == NULL) { + return -EINVAL; + } + + rawnand_dev.nand_dev->mtd_block_is_bad = nand_mtd_block_is_bad; + rawnand_dev.nand_dev->mtd_read_page = nand_mtd_read_page_raw; + rawnand_dev.nand_dev->ecc.mode = NAND_ECC_NONE; + + if ((rawnand_dev.ops->setup == NULL) || + (rawnand_dev.ops->exec == NULL)) { + return -ENODEV; + } + +#if NAND_ONFI_DETECT + if (detect_onfi() != 0) { + WARN("Detect ONFI failed\n"); + } +#endif + + if (plat_get_raw_nand_data(&rawnand_dev) != 0) { + return -EINVAL; + } + + assert((rawnand_dev.nand_dev->page_size != 0U) && + (rawnand_dev.nand_dev->block_size != 0U) && + (rawnand_dev.nand_dev->size != 0U)); + + *size = rawnand_dev.nand_dev->size; + *erase_size = rawnand_dev.nand_dev->block_size; + + rawnand_dev.ops->setup(rawnand_dev.nand_dev); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c b/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c new file mode 100644 index 0000000..542b614 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nand/spi_nand.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#define SPI_NAND_MAX_ID_LEN 4U +#define DELAY_US_400MS 400000U +#define MACRONIX_ID 0xC2U + +static struct spinand_device spinand_dev; + +#pragma weak plat_get_spi_nand_data +int plat_get_spi_nand_data(struct spinand_device *device) +{ + return 0; +} + +static int spi_nand_reg(bool read_reg, uint8_t reg, uint8_t *val, + enum spi_mem_data_dir dir) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + if (read_reg) { + op.cmd.opcode = SPI_NAND_OP_GET_FEATURE; + } else { + op.cmd.opcode = SPI_NAND_OP_SET_FEATURE; + } + + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.addr.val = reg; + op.addr.nbytes = 1U; + op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = dir; + op.data.nbytes = 1U; + op.data.buf = val; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_read_reg(uint8_t reg, uint8_t *val) +{ + return spi_nand_reg(true, reg, val, SPI_MEM_DATA_IN); +} + +static int spi_nand_write_reg(uint8_t reg, uint8_t val) +{ + return spi_nand_reg(false, reg, &val, SPI_MEM_DATA_OUT); +} + +static int spi_nand_update_cfg(uint8_t mask, uint8_t val) +{ + int ret; + uint8_t cfg = spinand_dev.cfg_cache; + + cfg &= ~mask; + cfg |= val; + + if (cfg == spinand_dev.cfg_cache) { + return 0; + } + + ret = spi_nand_write_reg(SPI_NAND_REG_CFG, cfg); + if (ret == 0) { + spinand_dev.cfg_cache = cfg; + } + + return ret; +} + +static int spi_nand_ecc_enable(bool enable) +{ + return spi_nand_update_cfg(SPI_NAND_CFG_ECC_EN, + enable ? SPI_NAND_CFG_ECC_EN : 0U); +} + +static int spi_nand_quad_enable(uint8_t manufacturer_id) +{ + bool enable = false; + + if (manufacturer_id != MACRONIX_ID) { + return 0; + } + + if (spinand_dev.spi_read_cache_op.data.buswidth == + SPI_MEM_BUSWIDTH_4_LINE) { + enable = true; + } + + return spi_nand_update_cfg(SPI_NAND_CFG_QE, + enable ? SPI_NAND_CFG_QE : 0U); +} + +static int spi_nand_wait_ready(uint8_t *status) +{ + int ret; + uint64_t timeout = timeout_init_us(DELAY_US_400MS); + + while (!timeout_elapsed(timeout)) { + ret = spi_nand_read_reg(SPI_NAND_REG_STATUS, status); + if (ret != 0) { + return ret; + } + + VERBOSE("%s Status %x\n", __func__, *status); + if ((*status & SPI_NAND_STATUS_BUSY) == 0U) { + return 0; + } + } + + return -ETIMEDOUT; +} + +static int spi_nand_reset(void) +{ + struct spi_mem_op op; + uint8_t status; + int ret; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_RESET; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + ret = spi_mem_exec_op(&op); + if (ret != 0) { + return ret; + } + + return spi_nand_wait_ready(&status); +} + +static int spi_nand_read_id(uint8_t *id) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_READ_ID; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = SPI_MEM_DATA_IN; + op.data.nbytes = SPI_NAND_MAX_ID_LEN; + op.data.buf = id; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_load_page(unsigned int page) +{ + struct spi_mem_op op; + uint32_t block_nb = page / spinand_dev.nand_dev->block_size; + uint32_t page_nb = page - (block_nb * spinand_dev.nand_dev->page_size); + uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint32_t block_sh = __builtin_ctz(nbpages_per_block) + 1U; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = SPI_NAND_OP_LOAD_PAGE; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.addr.val = (block_nb << block_sh) | page_nb; + op.addr.nbytes = 3U; + op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + return spi_mem_exec_op(&op); +} + +static int spi_nand_read_from_cache(unsigned int page, unsigned int offset, + uint8_t *buffer, unsigned int len) +{ + uint32_t nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint32_t block_nb = page / nbpages_per_block; + uint32_t page_sh = __builtin_ctz(spinand_dev.nand_dev->page_size) + 1U; + + spinand_dev.spi_read_cache_op.addr.val = offset; + + if ((spinand_dev.nand_dev->nb_planes > 1U) && ((block_nb % 2U) == 1U)) { + spinand_dev.spi_read_cache_op.addr.val |= 1U << page_sh; + } + + spinand_dev.spi_read_cache_op.data.buf = buffer; + spinand_dev.spi_read_cache_op.data.nbytes = len; + + return spi_mem_exec_op(&spinand_dev.spi_read_cache_op); +} + +static int spi_nand_read_page(unsigned int page, unsigned int offset, + uint8_t *buffer, unsigned int len, + bool ecc_enabled) +{ + uint8_t status; + int ret; + + ret = spi_nand_ecc_enable(ecc_enabled); + if (ret != 0) { + return ret; + } + + ret = spi_nand_load_page(page); + if (ret != 0) { + return ret; + } + + ret = spi_nand_wait_ready(&status); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_from_cache(page, offset, buffer, len); + if (ret != 0) { + return ret; + } + + if (ecc_enabled && ((status & SPI_NAND_STATUS_ECC_UNCOR) != 0U)) { + return -EBADMSG; + } + + return 0; +} + +static int spi_nand_mtd_block_is_bad(unsigned int block) +{ + unsigned int nbpages_per_block = spinand_dev.nand_dev->block_size / + spinand_dev.nand_dev->page_size; + uint8_t bbm_marker[2]; + int ret; + + ret = spi_nand_read_page(block * nbpages_per_block, + spinand_dev.nand_dev->page_size, + bbm_marker, sizeof(bbm_marker), false); + if (ret != 0) { + return ret; + } + + if ((bbm_marker[0] != GENMASK_32(7, 0)) || + (bbm_marker[1] != GENMASK_32(7, 0))) { + WARN("Block %u is bad\n", block); + return 1; + } + + return 0; +} + +static int spi_nand_mtd_read_page(struct nand_device *nand, unsigned int page, + uintptr_t buffer) +{ + return spi_nand_read_page(page, 0, (uint8_t *)buffer, + spinand_dev.nand_dev->page_size, true); +} + +int spi_nand_init(unsigned long long *size, unsigned int *erase_size) +{ + uint8_t id[SPI_NAND_MAX_ID_LEN]; + int ret; + + spinand_dev.nand_dev = get_nand_device(); + if (spinand_dev.nand_dev == NULL) { + return -EINVAL; + } + + spinand_dev.nand_dev->mtd_block_is_bad = spi_nand_mtd_block_is_bad; + spinand_dev.nand_dev->mtd_read_page = spi_nand_mtd_read_page; + spinand_dev.nand_dev->nb_planes = 1; + + spinand_dev.spi_read_cache_op.cmd.opcode = SPI_NAND_OP_READ_FROM_CACHE; + spinand_dev.spi_read_cache_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.addr.nbytes = 2U; + spinand_dev.spi_read_cache_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.dummy.nbytes = 1U; + spinand_dev.spi_read_cache_op.dummy.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + spinand_dev.spi_read_cache_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + + if (plat_get_spi_nand_data(&spinand_dev) != 0) { + return -EINVAL; + } + + assert((spinand_dev.nand_dev->page_size != 0U) && + (spinand_dev.nand_dev->block_size != 0U) && + (spinand_dev.nand_dev->size != 0U)); + + ret = spi_nand_reset(); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_id(id); + if (ret != 0) { + return ret; + } + + ret = spi_nand_read_reg(SPI_NAND_REG_CFG, &spinand_dev.cfg_cache); + if (ret != 0) { + return ret; + } + + ret = spi_nand_quad_enable(id[1]); + if (ret != 0) { + return ret; + } + + VERBOSE("SPI_NAND Detected ID 0x%x\n", id[1]); + + VERBOSE("Page size %u, Block size %u, size %llu\n", + spinand_dev.nand_dev->page_size, + spinand_dev.nand_dev->block_size, + spinand_dev.nand_dev->size); + + *size = spinand_dev.nand_dev->size; + *erase_size = spinand_dev.nand_dev->block_size; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c b/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c new file mode 100644 index 0000000..2e34344 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/nor/spi_nor.c @@ -0,0 +1,387 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#define SR_WIP BIT(0) /* Write in progress */ +#define CR_QUAD_EN_SPAN BIT(1) /* Spansion Quad I/O */ +#define SR_QUAD_EN_MX BIT(6) /* Macronix Quad I/O */ +#define FSR_READY BIT(7) /* Device status, 0 = Busy, 1 = Ready */ + +/* Defined IDs for supported memories */ +#define SPANSION_ID 0x01U +#define MACRONIX_ID 0xC2U +#define MICRON_ID 0x2CU + +#define BANK_SIZE 0x1000000U + +#define SPI_READY_TIMEOUT_US 40000U + +static struct nor_device nor_dev; + +#pragma weak plat_get_nor_data +int plat_get_nor_data(struct nor_device *device) +{ + return 0; +} + +static int spi_nor_reg(uint8_t reg, uint8_t *buf, size_t len, + enum spi_mem_data_dir dir) +{ + struct spi_mem_op op; + + zeromem(&op, sizeof(struct spi_mem_op)); + op.cmd.opcode = reg; + op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + op.data.dir = dir; + op.data.nbytes = len; + op.data.buf = buf; + + return spi_mem_exec_op(&op); +} + +static inline int spi_nor_read_id(uint8_t *id) +{ + return spi_nor_reg(SPI_NOR_OP_READ_ID, id, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_cr(uint8_t *cr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_CR, cr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_sr(uint8_t *sr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_SR, sr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_read_fsr(uint8_t *fsr) +{ + return spi_nor_reg(SPI_NOR_OP_READ_FSR, fsr, 1U, SPI_MEM_DATA_IN); +} + +static inline int spi_nor_write_en(void) +{ + return spi_nor_reg(SPI_NOR_OP_WREN, NULL, 0U, SPI_MEM_DATA_OUT); +} + +/* + * Check if device is ready. + * + * Return 0 if ready, 1 if busy or a negative error code otherwise + */ +static int spi_nor_ready(void) +{ + uint8_t sr; + int ret; + + ret = spi_nor_read_sr(&sr); + if (ret != 0) { + return ret; + } + + if ((nor_dev.flags & SPI_NOR_USE_FSR) != 0U) { + uint8_t fsr; + + ret = spi_nor_read_fsr(&fsr); + if (ret != 0) { + return ret; + } + + return (((fsr & FSR_READY) != 0U) && ((sr & SR_WIP) == 0U)) ? + 0 : 1; + } + + return (((sr & SR_WIP) == 0U) ? 0 : 1); +} + +static int spi_nor_wait_ready(void) +{ + int ret; + uint64_t timeout = timeout_init_us(SPI_READY_TIMEOUT_US); + + while (!timeout_elapsed(timeout)) { + ret = spi_nor_ready(); + if (ret <= 0) { + return ret; + } + } + + return -ETIMEDOUT; +} + +static int spi_nor_macronix_quad_enable(void) +{ + uint8_t sr; + int ret; + + ret = spi_nor_read_sr(&sr); + if (ret != 0) { + return ret; + } + + if ((sr & SR_QUAD_EN_MX) != 0U) { + return 0; + } + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + sr |= SR_QUAD_EN_MX; + ret = spi_nor_reg(SPI_NOR_OP_WRSR, &sr, 1U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return ret; + } + + ret = spi_nor_wait_ready(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_read_sr(&sr); + if ((ret != 0) || ((sr & SR_QUAD_EN_MX) == 0U)) { + return -EINVAL; + } + + return 0; +} + +static int spi_nor_write_sr_cr(uint8_t *sr_cr) +{ + int ret; + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_reg(SPI_NOR_OP_WRSR, sr_cr, 2U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return -EINVAL; + } + + ret = spi_nor_wait_ready(); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int spi_nor_quad_enable(void) +{ + uint8_t sr_cr[2]; + int ret; + + ret = spi_nor_read_cr(&sr_cr[1]); + if (ret != 0) { + return ret; + } + + if ((sr_cr[1] & CR_QUAD_EN_SPAN) != 0U) { + return 0; + } + + sr_cr[1] |= CR_QUAD_EN_SPAN; + ret = spi_nor_read_sr(&sr_cr[0]); + if (ret != 0) { + return ret; + } + + ret = spi_nor_write_sr_cr(sr_cr); + if (ret != 0) { + return ret; + } + + ret = spi_nor_read_cr(&sr_cr[1]); + if ((ret != 0) || ((sr_cr[1] & CR_QUAD_EN_SPAN) == 0U)) { + return -EINVAL; + } + + return 0; +} + +static int spi_nor_clean_bar(void) +{ + int ret; + + if (nor_dev.selected_bank == 0U) { + return 0; + } + + nor_dev.selected_bank = 0U; + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + return spi_nor_reg(nor_dev.bank_write_cmd, &nor_dev.selected_bank, + 1U, SPI_MEM_DATA_OUT); +} + +static int spi_nor_write_bar(uint32_t offset) +{ + uint8_t selected_bank = offset / BANK_SIZE; + int ret; + + if (selected_bank == nor_dev.selected_bank) { + return 0; + } + + ret = spi_nor_write_en(); + if (ret != 0) { + return ret; + } + + ret = spi_nor_reg(nor_dev.bank_write_cmd, &selected_bank, + 1U, SPI_MEM_DATA_OUT); + if (ret != 0) { + return ret; + } + + nor_dev.selected_bank = selected_bank; + + return 0; +} + +static int spi_nor_read_bar(void) +{ + uint8_t selected_bank = 0U; + int ret; + + ret = spi_nor_reg(nor_dev.bank_read_cmd, &selected_bank, + 1U, SPI_MEM_DATA_IN); + if (ret != 0) { + return ret; + } + + nor_dev.selected_bank = selected_bank; + + return 0; +} + +int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read) +{ + size_t remain_len; + int ret; + + *length_read = 0U; + nor_dev.read_op.addr.val = offset; + nor_dev.read_op.data.buf = (void *)buffer; + + VERBOSE("%s offset %u length %zu\n", __func__, offset, length); + + while (length != 0U) { + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + ret = spi_nor_write_bar(nor_dev.read_op.addr.val); + if (ret != 0) { + return ret; + } + + remain_len = (BANK_SIZE * (nor_dev.selected_bank + 1)) - + nor_dev.read_op.addr.val; + nor_dev.read_op.data.nbytes = MIN(length, remain_len); + } else { + nor_dev.read_op.data.nbytes = length; + } + + ret = spi_mem_exec_op(&nor_dev.read_op); + if (ret != 0) { + spi_nor_clean_bar(); + return ret; + } + + length -= nor_dev.read_op.data.nbytes; + nor_dev.read_op.addr.val += nor_dev.read_op.data.nbytes; + nor_dev.read_op.data.buf += nor_dev.read_op.data.nbytes; + *length_read += nor_dev.read_op.data.nbytes; + } + + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + ret = spi_nor_clean_bar(); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +int spi_nor_init(unsigned long long *size, unsigned int *erase_size) +{ + int ret; + uint8_t id; + + /* Default read command used */ + nor_dev.read_op.cmd.opcode = SPI_NOR_OP_READ; + nor_dev.read_op.cmd.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.addr.nbytes = 3U; + nor_dev.read_op.addr.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.data.buswidth = SPI_MEM_BUSWIDTH_1_LINE; + nor_dev.read_op.data.dir = SPI_MEM_DATA_IN; + + if (plat_get_nor_data(&nor_dev) != 0) { + return -EINVAL; + } + + assert(nor_dev.size != 0U); + + if (nor_dev.size > BANK_SIZE) { + nor_dev.flags |= SPI_NOR_USE_BANK; + } + + *size = nor_dev.size; + + ret = spi_nor_read_id(&id); + if (ret != 0) { + return ret; + } + + if ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U) { + switch (id) { + case SPANSION_ID: + nor_dev.bank_read_cmd = SPINOR_OP_BRRD; + nor_dev.bank_write_cmd = SPINOR_OP_BRWR; + break; + default: + nor_dev.bank_read_cmd = SPINOR_OP_RDEAR; + nor_dev.bank_write_cmd = SPINOR_OP_WREAR; + break; + } + } + + if (nor_dev.read_op.data.buswidth == 4U) { + switch (id) { + case MACRONIX_ID: + INFO("Enable Macronix quad support\n"); + ret = spi_nor_macronix_quad_enable(); + break; + case MICRON_ID: + break; + default: + ret = spi_nor_quad_enable(); + break; + } + } + + if ((ret == 0) && ((nor_dev.flags & SPI_NOR_USE_BANK) != 0U)) { + ret = spi_nor_read_bar(); + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c b/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c new file mode 100644 index 0000000..c43d519 --- /dev/null +++ b/arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#define SPI_MEM_DEFAULT_SPEED_HZ 100000U + +/* + * struct spi_slave - Representation of a SPI slave. + * + * @max_hz: Maximum speed for this slave in Hertz. + * @cs: ID of the chip select connected to the slave. + * @mode: SPI mode to use for this slave (see SPI mode flags). + * @ops: Ops defined by the bus. + */ +struct spi_slave { + unsigned int max_hz; + unsigned int cs; + unsigned int mode; + const struct spi_bus_ops *ops; +}; + +static struct spi_slave spi_slave; + +static bool spi_mem_check_buswidth_req(uint8_t buswidth, bool tx) +{ + switch (buswidth) { + case 1U: + return true; + + case 2U: + if ((tx && (spi_slave.mode & (SPI_TX_DUAL | SPI_TX_QUAD)) != + 0U) || + (!tx && (spi_slave.mode & (SPI_RX_DUAL | SPI_RX_QUAD)) != + 0U)) { + return true; + } + break; + + case 4U: + if ((tx && (spi_slave.mode & SPI_TX_QUAD) != 0U) || + (!tx && (spi_slave.mode & SPI_RX_QUAD) != 0U)) { + return true; + } + break; + + default: + break; + } + + return false; +} + +static bool spi_mem_supports_op(const struct spi_mem_op *op) +{ + if (!spi_mem_check_buswidth_req(op->cmd.buswidth, true)) { + return false; + } + + if ((op->addr.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->addr.buswidth, true)) { + return false; + } + + if ((op->dummy.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->dummy.buswidth, true)) { + return false; + } + + if ((op->data.nbytes != 0U) && + !spi_mem_check_buswidth_req(op->data.buswidth, + op->data.dir == SPI_MEM_DATA_OUT)) { + return false; + } + + return true; +} + +static int spi_mem_set_speed_mode(void) +{ + const struct spi_bus_ops *ops = spi_slave.ops; + int ret; + + ret = ops->set_speed(spi_slave.max_hz); + if (ret != 0) { + VERBOSE("Cannot set speed (err=%d)\n", ret); + return ret; + } + + ret = ops->set_mode(spi_slave.mode); + if (ret != 0) { + VERBOSE("Cannot set mode (err=%d)\n", ret); + return ret; + } + + return 0; +} + +static int spi_mem_check_bus_ops(const struct spi_bus_ops *ops) +{ + bool error = false; + + if (ops->claim_bus == NULL) { + VERBOSE("Ops claim bus is not defined\n"); + error = true; + } + + if (ops->release_bus == NULL) { + VERBOSE("Ops release bus is not defined\n"); + error = true; + } + + if (ops->exec_op == NULL) { + VERBOSE("Ops exec op is not defined\n"); + error = true; + } + + if (ops->set_speed == NULL) { + VERBOSE("Ops set speed is not defined\n"); + error = true; + } + + if (ops->set_mode == NULL) { + VERBOSE("Ops set mode is not defined\n"); + error = true; + } + + return error ? -EINVAL : 0; +} + +/* + * spi_mem_exec_op() - Execute a memory operation. + * @op: The memory operation to execute. + * + * This function first checks that @op is supported and then tries to execute + * it. + * + * Return: 0 in case of success, a negative error code otherwise. + */ +int spi_mem_exec_op(const struct spi_mem_op *op) +{ + const struct spi_bus_ops *ops = spi_slave.ops; + int ret; + + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addqr:%" PRIx64 " len:%x\n", + __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + + if (!spi_mem_supports_op(op)) { + WARN("Error in spi_mem_support\n"); + return -ENOTSUP; + } + + ret = ops->claim_bus(spi_slave.cs); + if (ret != 0) { + WARN("Error claim_bus\n"); + return ret; + } + + ret = ops->exec_op(op); + + ops->release_bus(); + + return ret; +} + +/* + * spi_mem_init_slave() - SPI slave device initialization. + * @fdt: Pointer to the device tree blob. + * @bus_node: Offset of the bus node. + * @ops: The SPI bus ops defined. + * + * This function first checks that @ops are supported and then tries to find + * a SPI slave device. + * + * Return: 0 in case of success, a negative error code otherwise. + */ +int spi_mem_init_slave(void *fdt, int bus_node, const struct spi_bus_ops *ops) +{ + int ret; + int mode = 0; + int nchips = 0; + int bus_subnode = 0; + const fdt32_t *cuint = NULL; + + ret = spi_mem_check_bus_ops(ops); + if (ret != 0) { + return ret; + } + + fdt_for_each_subnode(bus_subnode, fdt, bus_node) { + nchips++; + } + + if (nchips != 1) { + ERROR("Only one SPI device is currently supported\n"); + return -EINVAL; + } + + fdt_for_each_subnode(bus_subnode, fdt, bus_node) { + /* Get chip select */ + cuint = fdt_getprop(fdt, bus_subnode, "reg", NULL); + if (cuint == NULL) { + ERROR("Chip select not well defined\n"); + return -EINVAL; + } + spi_slave.cs = fdt32_to_cpu(*cuint); + + /* Get max slave frequency */ + spi_slave.max_hz = SPI_MEM_DEFAULT_SPEED_HZ; + cuint = fdt_getprop(fdt, bus_subnode, + "spi-max-frequency", NULL); + if (cuint != NULL) { + spi_slave.max_hz = fdt32_to_cpu(*cuint); + } + + /* Get mode */ + if ((fdt_getprop(fdt, bus_subnode, "spi-cpol", NULL)) != NULL) { + mode |= SPI_CPOL; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-cpha", NULL)) != NULL) { + mode |= SPI_CPHA; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-cs-high", NULL)) != + NULL) { + mode |= SPI_CS_HIGH; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-3wire", NULL)) != + NULL) { + mode |= SPI_3WIRE; + } + if ((fdt_getprop(fdt, bus_subnode, "spi-half-duplex", NULL)) != + NULL) { + mode |= SPI_PREAMBLE; + } + + /* Get dual/quad mode */ + cuint = fdt_getprop(fdt, bus_subnode, "spi-tx-bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 1U: + break; + case 2U: + mode |= SPI_TX_DUAL; + break; + case 4U: + mode |= SPI_TX_QUAD; + break; + default: + WARN("spi-tx-bus-width %u not supported\n", + fdt32_to_cpu(*cuint)); + return -EINVAL; + } + } + + cuint = fdt_getprop(fdt, bus_subnode, "spi-rx-bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 1U: + break; + case 2U: + mode |= SPI_RX_DUAL; + break; + case 4U: + mode |= SPI_RX_QUAD; + break; + default: + WARN("spi-rx-bus-width %u not supported\n", + fdt32_to_cpu(*cuint)); + return -EINVAL; + } + } + + spi_slave.mode = mode; + spi_slave.ops = ops; + } + + return spi_mem_set_speed_mode(); +} diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c new file mode 100644 index 0000000..4502ed6 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c @@ -0,0 +1,284 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + + +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t sig_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, 0); + +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); + +/* + * TBBR Chain of trust definition + */ +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t scp_bl2_image = { + .img_id = SCP_BL2_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#ifdef POLICY_FUSE_PROVISION +static const auth_img_desc_t fuse_prov_img = { + .img_id = FUSE_PROV_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t fuse_upgrade_img = { + .img_id = FUSE_UP_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#endif +#ifdef CONFIG_DDR_FIP_IMAGE +static const auth_img_desc_t ddr_imem_udimm_1d_img = { + .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_udimm_2d_img = { + .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_1d_img = { + .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_2d_img = { + .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_1d_img = { + .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_2d_img = { + .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_1d_img = { + .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_2d_img = { + .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_PLAT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &sig_hash + } + } + } +}; +#endif + +static const auth_img_desc_t * const cot_desc[] = { + [BL31_IMAGE_ID] = &bl31_image, + [SCP_BL2_IMAGE_ID] = &scp_bl2_image, + [BL32_IMAGE_ID] = &bl32_image, + [BL33_IMAGE_ID] = &bl33_image, +#ifdef POLICY_FUSE_PROVISION + [FUSE_PROV_IMAGE_ID] = &fuse_prov_img, + [FUSE_UP_IMAGE_ID] = &fuse_upgrade_img, +#endif +#ifdef CONFIG_DDR_FIP_IMAGE + [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img, + [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img, + [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img, + [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img, + [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img, + [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img, + [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img, + [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk new file mode 100644 index 0000000..1af51f8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr.mk @@ -0,0 +1,64 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CSF_HDR_SOURCES := $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/csf_hdr_parser.c + +CSF_HDR_SOURCES += $(PLAT_DRIVERS_PATH)/auth/csf_hdr_parser/plat_img_parser.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/auth/csf_hdr_parser/ + +$(eval $(call add_define, CSF_HEADER_PREPENDED)) + + +# Path to CST directory is required to generate the CSF header +# and prepend it to image before fip image gets generated +ifeq (${CST_DIR},) + $(error Error: CST_DIR not set) +endif + +# Rules are created for generating and appending CSF header to images before +# FIT image generation + +# CST_BL31 +define CST_BL31_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL31_INPUT_FILE} +endef + +CST_BL31_SUFFIX := .cst + +# CST_BL32 +define CST_BL32_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL32_INPUT_FILE} +endef + +CST_BL32_SUFFIX := .cst + +# CST_BL33 +define CST_BL33_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${BL33_INPUT_FILE} +endef + +CST_BL33_SUFFIX := .cst + +# CST_SCP_BL2 +define CST_SCP_BL2_RULE +$(1): $(2) + @echo " Generating CSF Header for $$@ $$<" + $(Q)$(CST_DIR)/create_hdr_esbc --in $(2) --out $(1) --app_off ${CSF_HDR_SZ} \ + --app $(2) ${FUSE_INPUT_FILE} +endef + +CST_SCP_BL2_SUFFIX := .cst diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c new file mode 100644 index 0000000..b878082 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c @@ -0,0 +1,365 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "NXP CSFv2" + +#ifdef CSF_HDR_CH3 +/* Barker Code for LS Ch3 ESBC Header */ +static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x12, 0x19, 0x20, 0x01 }; +#else +static const uint8_t barker_code[CSF_BARKER_LEN] = { 0x68, 0x39, 0x27, 0x81 }; +#endif + +#define CHECK_KEY_LEN(key_len) (((key_len) == 2 * RSA_1K_KEY_SZ_BYTES) || \ + ((key_len) == 2 * RSA_2K_KEY_SZ_BYTES) || \ + ((key_len) == 2 * RSA_4K_KEY_SZ_BYTES)) + +/* Flag to indicate if values are there in rotpk_hash_table */ +bool rotpk_not_dpld = true; +uint8_t rotpk_hash_table[MAX_KEY_ENTRIES][SHA256_BYTES]; +uint32_t num_rotpk_hash_entries; + +/* + * This function deploys the hashes of the various platform keys in + * rotpk_hash_table. This is done in case of secure boot after comparison + * of table's hash with the hash in SFP fuses. This installation is done + * only in the first header parsing. + */ +static int deploy_rotpk_hash_table(void *srk_buffer, uint16_t num_srk) +{ + void *ctx; + int ret = 0; + int i, j = 0; + unsigned int digest_size = SHA256_BYTES; + enum hash_algo algo = SHA256; + uint8_t hash[SHA256_BYTES]; + uint32_t srk_hash[SHA256_BYTES/4] __aligned(CACHE_WRITEBACK_GRANULE); + struct srk_table *srktbl = (void *)srk_buffer; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr() + + SFP_FUSE_REGS_OFFSET); + + + if (num_srk > MAX_KEY_ENTRIES) { + return -1; + } + + ret = hash_init(algo, &ctx); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, (uint8_t *)((uint8_t *)srk_buffer), + num_srk * sizeof(struct srk_table)); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, hash, digest_size); + if (ret != 0) { + return -1; + } + + /* Add comparison of hash with SFP hash here */ + for (i = 0; i < SHA256_BYTES/4; i++) { + srk_hash[i] = + mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); + } + + VERBOSE("SRK table HASH\n"); + for (i = 0; i < 8; i++) { + VERBOSE("%x\n", *((uint32_t *)hash + i)); + } + + if (memcmp(hash, srk_hash, SHA256_BYTES) != 0) { + ERROR("Error in installing ROTPK table\n"); + ERROR("SRK hash doesn't match the fuse hash\n"); + return -1; + } + + /* Hash table already deployed */ + if (rotpk_not_dpld == false) { + return 0; + } + + for (i = 0; i < num_srk; i++) { + ret = hash_init(algo, &ctx); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, srktbl[i].pkey, srktbl[i].key_len); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, rotpk_hash_table[i], digest_size); + if (ret != 0) { + return -1; + } + VERBOSE("Table key %d HASH\n", i); + for (j = 0; j < 8; j++) { + VERBOSE("%x\n", *((uint32_t *)rotpk_hash_table[i] + j)); + } + } + rotpk_not_dpld = false; + num_rotpk_hash_entries = num_srk; + + return 0; +} + +/* + * Calculate hash of ESBC hdr and ESBC. This function calculates the + * single hash of ESBC header and ESBC image + */ +int calc_img_hash(struct csf_hdr *hdr, + void *img_addr, uint32_t img_size, + uint8_t *img_hash, uint32_t *hash_len) +{ + void *ctx; + int ret = 0; + unsigned int digest_size = SHA256_BYTES; + enum hash_algo algo = SHA256; + + ret = hash_init(algo, &ctx); + /* Copy hash at destination buffer */ + if (ret != 0) { + return -1; + } + + /* Update hash for CSF Header */ + ret = hash_update(algo, ctx, (uint8_t *)hdr, sizeof(struct csf_hdr)); + if (ret != 0) { + return -1; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, + (uint8_t *)((uint8_t *)hdr + hdr->srk_tbl_off), + hdr->len_kr.num_srk * sizeof(struct srk_table)); + if (ret != 0) { + return -1; + } + + /* Update hash for actual Image */ + ret = hash_update(algo, ctx, (uint8_t *)(img_addr), img_size); + if (ret != 0) { + return -1; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, img_hash, digest_size); + if (ret != 0) { + return -1; + } + + *hash_len = digest_size; + + VERBOSE("IMG encoded HASH\n"); + for (int i = 0; i < 8; i++) { + VERBOSE("%x\n", *((uint32_t *)img_hash + i)); + } + + return 0; +} + +/* This function checks if selected key is revoked or not.*/ +static uint32_t is_key_revoked(uint32_t keynum, uint32_t rev_flag) +{ + if (keynum == UNREVOCABLE_KEY) { + return 0; + } + + if (((uint32_t)(1 << (REVOC_KEY_ALIGN - keynum)) & rev_flag) != 0) { + return 1; + } + + return 0; +} + +/* Parse the header to extract the type of key, + * Check if key is not revoked + * and return the key , key length and key_type + */ +static int32_t get_key(struct csf_hdr *hdr, uint8_t **key, uint32_t *len, + enum sig_alg *key_type) +{ + int i = 0; + uint32_t ret = 0U; + uint32_t key_num, key_revoc_flag; + void *esbc = hdr; + struct srk_table *srktbl = (void *)((uint8_t *)esbc + hdr->srk_tbl_off); + bool sb; + uint32_t mode; + + /* We currently support only RSA keys and signature */ + *key_type = RSA; + + /* Check for number of SRK entries */ + if ((hdr->len_kr.num_srk == 0) || + (hdr->len_kr.num_srk > MAX_KEY_ENTRIES)) { + ERROR("Error in NUM entries in SRK Table\n"); + return -1; + } + + /* + * Check the key number field. It should be not greater than + * number of entries in SRK table. + */ + key_num = hdr->len_kr.srk_sel; + if ((key_num == 0) || (key_num > hdr->len_kr.num_srk)) { + ERROR("Invalid Key number\n"); + return -1; + } + + /* Get revoc key from sfp */ + key_revoc_flag = get_key_revoc(); + + /* Check if selected key has been revoked */ + ret = is_key_revoked(key_num, key_revoc_flag); + if (ret != 0) { + ERROR("Selected key has been revoked\n"); + return -1; + } + + /* Check for valid key length - allowed key sized 1k, 2k and 4K */ + for (i = 0; i < hdr->len_kr.num_srk; i++) { + if (CHECK_KEY_LEN(srktbl[i].key_len) == 0) { + ERROR("Invalid key length\n"); + return -1; + } + } + + /* We don't return error from here. While parsing we just try to + * install the srk table. Failure needs to be taken care of in + * case of secure boot. This failure will be handled at the time + * of rotpk comparison in plat_get_rotpk_info function + */ + sb = check_boot_mode_secure(&mode); + if (sb) { + ret = deploy_rotpk_hash_table(srktbl, hdr->len_kr.num_srk); + if (ret != 0) { + ERROR("ROTPK FAILURE\n"); + /* For ITS =1 , return failure */ + if (mode != 0) { + return -1; + } + ERROR("SECURE BOOT DEV-ENV MODE:\n"); + ERROR("\tCHECK ROTPK !\n"); + ERROR("\tCONTINUING ON FAILURE...\n"); + } + } + + /* Return the length of the selected key */ + *len = srktbl[key_num - 1].key_len; + + /* Point key to the selected key */ + *key = (uint8_t *)&(srktbl[key_num - 1].pkey); + + return 0; +} + +/* + * This function would parse the CSF header and do the following: + * 1. Basic integrity checks + * 2. Key checks and extract the key from SRK/IE Table + * 3. Key hash comparison with SRKH in fuses in case of SRK Table + * 4. OEM/UID checks - To be added + * 5. Hash calculation for various components used in signature + * 6. Signature integrity checks + * return -> 0 on success, -1 on failure + */ +int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len, + void **img_sign, uint32_t *sign_len, + enum sig_alg *algo) +{ + struct csf_hdr *hdr = img_hdr; + uint8_t *s; + int32_t ret = 0; + void *esbc = (uint8_t *)img_hdr; + uint8_t *key; + uint32_t klen; + + /* check barker code */ + if (memcmp(hdr->barker, barker_code, CSF_BARKER_LEN) != 0) { + ERROR("Wrong barker code in header\n"); + return -1; + } + + ret = get_key(hdr, &key, &klen, algo); + if (ret != 0) { + return -1; + } + + /* check signaure */ + if (klen == (2 * hdr->sign_len)) { + /* check signature length */ + if (((hdr->sign_len == RSA_1K_KEY_SZ_BYTES) || + (hdr->sign_len == RSA_2K_KEY_SZ_BYTES) || + (hdr->sign_len == RSA_4K_KEY_SZ_BYTES)) == 0) { + ERROR("Wrong Signature length in header\n"); + return -1; + } + } else { + ERROR("RSA key length not twice the signature length\n"); + return -1; + } + + /* modulus most significant bit should be set */ + + if ((key[0] & 0x80) == 0U) { + ERROR("RSA Public key MSB not set\n"); + return -1; + } + + /* modulus value should be odd */ + if ((key[klen / 2 - 1] & 0x1) == 0U) { + ERROR("Public key Modulus in header not odd\n"); + return -1; + } + + /* Check signature value < modulus value */ + s = (uint8_t *)(esbc + hdr->psign); + + if (!(memcmp(s, key, hdr->sign_len) < 0)) { + ERROR("Signature not less than modulus"); + return -1; + } + + /* Populate the return addresses */ + *img_sign = (void *)(s); + + /* Save the length of signature */ + *sign_len = hdr->sign_len; + + *img_key = (uint8_t *)key; + + *key_len = klen; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 new file mode 100644 index 0000000..bf8934b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1 +PLATFORM=LS1043 +# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0) +ESBC=0 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +ENTRY_POINT=10000000 +--------------------------------------------------- +# Specify the file name of the keys separated by comma. +# The number of files and key select should lie between 1 and 4 for 1040 and C290. +# For rest of the platforms only one key is required and key select should not be provided. + +# USAGE (for 4080/5020/5040/3041/2041/1010/913x): PRI_KEY = +# USAGE (for 1040/C290/9164/4240/LS1): PRI_KEY = , , , + +# PRI_KEY (Default private key :srk.pri) - [Optional] +PRI_KEY=srk.pri +# PUB_KEY (Default public key :srk.pub) - [Optional] +PUB_KEY=srk.pub +# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240/LS1 only) - [Optional] +KEY_SELECT= +--------------------------------------------------- +# Specify SG table address, only for (2041/3041/4080/5020/5040) with ESBC=0 - [Optional] +SG_TABLE_ADDR= +--------------------------------------------------- +# Specify the target where image will be loaded. (Default is NOR_16B) - [Optional] +# Only required for Non-PBL Devices (1010/1040/9131/9132i/C290) +# Select from - NOR_8B/NOR_16B/NAND_8B_512/NAND_8B_2K/NAND_8B_4K/NAND_16B_512/NAND_16B_2K/NAND_16B_4K/SD/MMC/SPI +IMAGE_TARGET= +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +IMAGE_1={bl2.bin,10000000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +--------------------------------------------------- +# Specify the file names of csf header and sg table. (Default :hdr.out) [Optional] +OUTPUT_HDR_FILENAME=hdr_bl2.out + +# Specify the file names of hash file and sign file. +HASH_FILENAME=img_hash.out +INPUT_SIGN_FILENAME=sign.out + +# Specify the signature size.It is mandatory when neither public key nor private key is specified. +# Signature size would be [0x80 for 1k key, 0x100 for 2k key, and 0x200 for 4k key]. +SIGN_SIZE= +--------------------------------------------------- +# Specify the output file name of sg table. (Default :sg_table.out). [Optional] +# Please note that OUTPUT SG BIN is only required for 2041/3041/4080/5020/5040 when ESBC flag is not set. +OUTPUT_SG_BIN= +--------------------------------------------------- +# Following fields are Required for 4240/9164/1040/C290 only + +# Specify House keeping Area +# Required for 4240/9164/1040/C290 only when ESBC flag is not set. [Mandatory] +HK_AREA_POINTER= +HK_AREA_SIZE= +--------------------------------------------------- +# Following field Required for 4240/9164/1040/C290 only +# Specify Secondary Image Flag. (0 or 1) - [Optional] +# (Default is 0) +SEC_IMAGE=0 +# Specify Manufacturing Protection Flag. (0 or 1) - [Optional] +# Required only for LS1(Default is 0) +MP_FLAG=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 new file mode 100644 index 0000000..5fdad9c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 @@ -0,0 +1,65 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.2: LX2160 +PLATFORM=LS2088 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +# Address can be 64 bit +ENTRY_POINT=1800A000 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. +# DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +# Address can be 64 bit +IMAGE_1={bl2.bin,1800A000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify the output file names [Optional]. +# Default Values chosen in Tool +OUTPUT_HDR_FILENAME=hdr_bl2.out +IMAGE_HASH_FILENAME= +RSA_SIGN_FILENAME= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 new file mode 100644 index 0000000..cc7c07c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 @@ -0,0 +1,65 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.2: LX2160 +PLATFORM=LX2160 +--------------------------------------------------- +# Entry Point/Image start address field in the header.[Mandatory] +# (default=ADDRESS of first file specified in images) +# Address can be 64 bit +ENTRY_POINT=1800D000 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify IMAGE, Max 8 images are possible. +# DST_ADDR is required only for Non-PBL Platform. [Mandatory] +# USAGE : IMAGE_NO = {IMAGE_NAME, SRC_ADDR, DST_ADDR} +# Address can be 64 bit +IMAGE_1={bl2.bin,1800D000,ffffffff} +IMAGE_2={,,} +IMAGE_3={,,} +IMAGE_4={,,} +IMAGE_5={,,} +IMAGE_6={,,} +IMAGE_7={,,} +IMAGE_8={,,} +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify the output file names [Optional]. +# Default Values chosen in Tool +OUTPUT_HDR_FILENAME=hdr_bl2.out +IMAGE_HASH_FILENAME= +RSA_SIGN_FILENAME= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 new file mode 100644 index 0000000..93b020b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 @@ -0,0 +1,30 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - 1010/1040/2041/3041/4080/5020/5040/9131/9132/9164/4240/C290/LS1 +PLATFORM=LS1043 +# ESBC Flag. Specify ESBC=0 to sign u-boot and ESBC=1 to sign ESBC images.(default is 0) +ESBC=1 +--------------------------------------------------- +# Specify the file name of the keys separated by comma. + +# PRI_KEY (Default private key :srk.pri) - [Optional] +PRI_KEY=srk.pri +# PUB_KEY (Default public key :srk.pub) - [Optional] +PUB_KEY=srk.pub +# Please provide KEY_SELECT(between 1 to 4) (Required for 1040/C290/9164/4240 only) - [Optional] +KEY_SELECT=1 +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 new file mode 100644 index 0000000..18e8e3b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 @@ -0,0 +1,37 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +ESBC=1 +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LS2088 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri + +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 new file mode 100644 index 0000000..9111a2a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 @@ -0,0 +1,43 @@ +/* + * Copyright 2016-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LS2088 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 new file mode 100644 index 0000000..c2d7ce4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 @@ -0,0 +1,43 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +--------------------------------------------------- +# Specify the platform. [Mandatory] +# Choose Platform - +# TRUST 3.0: LS2085 +# TRUST 3.1: LS2088, LS1088 +PLATFORM=LX2160 +--------------------------------------------------- +# Specify the Key Information. +# PUB_KEY [Mandatory] Comma Separated List +# Usage: ..... +PUB_KEY=srk.pub +# KEY_SELECT [Mandatory] +# USAGE (for TRUST 3.x): (between 1 to 8) +KEY_SELECT=1 +# PRI_KEY [Mandatory] Single Key Used for Signing +# USAGE: +PRI_KEY=srk.pri +--------------------------------------------------- +# Specify OEM AND FSL ID to be populated in header. [Optional] +# e.g FSL_UID_0=11111111 +FSL_UID_0= +FSL_UID_1= +OEM_UID_0= +OEM_UID_1= +OEM_UID_2= +OEM_UID_3= +OEM_UID_4= +--------------------------------------------------- +# Specify The Flags. (0 or 1) - [Optional] +MP_FLAG=0 +ISS_FLAG=1 +LW_FLAG=0 +--------------------------------------------------- +# Specify VERBOSE as 1, if you want to Display Header Information [Optional] +VERBOSE=1 +--------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c new file mode 100644 index 0000000..43b78e5 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2014-2016, Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* Temporary variables to speed up the authentication parameters search. These + * variables are assigned once during the integrity check and used any time an + * authentication parameter is requested, so we do not have to parse the image + * again. + */ + +/* Hash of Image + CSF Header + SRK table */ +uint8_t img_hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); +uint32_t hash_len; + +/* Key being used for authentication + * Points to the key in CSF header copied in DDR + * ESBC client key + */ +void *img_key; +uint32_t key_len; + +/* ESBC client signature */ +void *img_sign; +uint32_t sign_len; +enum sig_alg alg; + +/* Maximum OID string length ("a.b.c.d.e.f ...") */ +#define MAX_OID_STR_LEN 64 + +#define LIB_NAME "NXP CSFv2" + +/* + * Clear all static temporary variables. + */ +static void clear_temp_vars(void) +{ +#define ZERO_AND_CLEAN(x) \ + do { \ + zeromem(&x, sizeof(x)); \ + clean_dcache_range((uintptr_t)&x, sizeof(x)); \ + } while (0) + + ZERO_AND_CLEAN(img_key); + ZERO_AND_CLEAN(img_sign); + ZERO_AND_CLEAN(img_hash); + ZERO_AND_CLEAN(key_len); + ZERO_AND_CLEAN(hash_len); + ZERO_AND_CLEAN(sign_len); + +#undef ZERO_AND_CLEAN +} + +/* Exported functions */ + +static void init(void) +{ + clear_temp_vars(); +} + +/* + * This function would check the integrity of the CSF header + */ +static int check_integrity(void *img, unsigned int img_len) +{ + int ret; + + /* + * The image file has been successfully loaded till here. + * + * Flush the image to main memory so that it can be authenticated + * by CAAM, a HW accelerator regardless of cache and MMU state. + */ + flush_dcache_range((uintptr_t) img, img_len); + + /* + * Image is appended at an offset of 16K (IMG_OFFSET) to the header. + * So the size in header should be equal to img_len - IMG_OFFSET + */ + VERBOSE("Barker code is %x\n", *(unsigned int *)img); + ret = validate_esbc_header(img, &img_key, &key_len, &img_sign, + &sign_len, &alg); + if (ret < 0) { + ERROR("Header authentication failed\n"); + clear_temp_vars(); + return IMG_PARSER_ERR; + } + /* Calculate the hash of various components from the image */ + ret = calc_img_hash(img, (uint8_t *)img + CSF_HDR_SZ, + img_len - CSF_HDR_SZ, img_hash, &hash_len); + if (ret != 0) { + ERROR("Issue in hash calculation %d\n", ret); + clear_temp_vars(); + return IMG_PARSER_ERR; + } + + return IMG_PARSER_OK; +} + +/* + * Extract an authentication parameter from CSF header + * + * CSF header has already been parsed and the required information like + * hash of data, signature, length stored in global variables has been + * extracted in chek_integrity function. This data + * is returned back to the caller. + */ +static int get_auth_param(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len) +{ + int rc = IMG_PARSER_OK; + + /* We do not use img because the check_integrity function has already + * extracted the relevant data ( pk, sig_alg, etc) + */ + + switch (type_desc->type) { + + /* Hash will be returned for comparison with signature */ + case AUTH_PARAM_HASH: + *param = (void *)img_hash; + *param_len = (unsigned int)SHA256_BYTES; + break; + + /* Return the public key used for signature extracted from the SRK table + * after checks with key revocation + */ + case AUTH_PARAM_PUB_KEY: + /* Get the subject public key */ + /* For a 1K key - the length would be 2k/8 = 0x100 bytes + * 2K RSA key - 0x200 , 4K RSA - 0x400 + */ + *param = img_key; + *param_len = (unsigned int)key_len; + break; + + /* Call a function to tell if signature is RSA or ECDSA. ECDSA to be + * supported in later platforms like LX2 etc + */ + case AUTH_PARAM_SIG_ALG: + /* Algo will be signature - RSA or ECDSA on hash */ + *param = (void *)&alg; + *param_len = 4U; + break; + + /* Return the signature */ + case AUTH_PARAM_SIG: + *param = img_sign; + *param_len = (unsigned int)sign_len; + break; + + case AUTH_PARAM_NV_CTR: + + default: + rc = IMG_PARSER_ERR_NOT_FOUND; + break; + } + + return rc; +} + +REGISTER_IMG_PARSER_LIB(IMG_PLAT, LIB_NAME, init, + check_integrity, get_auth_param); diff --git a/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c b/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c new file mode 100644 index 0000000..bb21fa0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c @@ -0,0 +1,820 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + + +#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256 +#define HASH_DER_LEN 51 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384 +#define HASH_DER_LEN 67 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512 +#define HASH_DER_LEN 83 +#else +#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID" +#endif + +/* + * The platform must allocate buffers to store the authentication parameters + * extracted from the certificates. In this case, because of the way the CoT is + * established, we can reuse some of the buffers on different stages + */ + +static unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +static unsigned char soc_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra1_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_extra2_hash_buf[HASH_DER_LEN]; +static unsigned char trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char non_trusted_world_pk_buf[PK_DER_LEN]; +static unsigned char content_pk_buf[PK_DER_LEN]; +static unsigned char soc_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char tos_fw_config_hash_buf[HASH_DER_LEN]; +static unsigned char nt_fw_config_hash_buf[HASH_DER_LEN]; + +#ifdef CONFIG_DDR_FIP_IMAGE +static unsigned char ddr_fw_content_pk_buf[PK_DER_LEN]; +static unsigned char ddr_imem_udimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_imem_udimm_2d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_udimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_udimm_2d_hash_buf[HASH_DER_LEN]; + +static unsigned char ddr_imem_rdimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_imem_rdimm_2d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_rdimm_1d_hash_buf[HASH_DER_LEN]; +static unsigned char ddr_dmem_rdimm_2d_hash_buf[HASH_DER_LEN]; +#endif + +/* + * Parameter type descriptors + */ +static auth_param_type_desc_t trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, TRUSTED_FW_NVCOUNTER_OID); + +static auth_param_type_desc_t subject_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, 0); +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + + +static auth_param_type_desc_t non_trusted_nv_ctr = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_NV_CTR, NON_TRUSTED_FW_NVCOUNTER_OID); +static auth_param_type_desc_t trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t non_trusted_world_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_WORLD_PK_OID); +static auth_param_type_desc_t soc_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, SOC_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t tos_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, TRUSTED_OS_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t nt_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, NON_TRUSTED_FW_CONTENT_CERT_PK_OID); +static auth_param_type_desc_t soc_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_AP_FW_HASH_OID); +static auth_param_type_desc_t soc_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, SOC_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_HASH_OID); +static auth_param_type_desc_t tos_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_CONFIG_HASH_OID); +static auth_param_type_desc_t tos_fw_extra1_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA1_HASH_OID); +static auth_param_type_desc_t tos_fw_extra2_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, TRUSTED_OS_FW_EXTRA2_HASH_OID); +static auth_param_type_desc_t nt_world_bl_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID); +static auth_param_type_desc_t nt_fw_config_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, NON_TRUSTED_FW_CONFIG_HASH_OID); + +#ifdef CONFIG_DDR_FIP_IMAGE +static auth_param_type_desc_t ddr_fw_content_pk = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_PUB_KEY, DDR_FW_CONTENT_CERT_PK_OID); + +static auth_param_type_desc_t ddr_imem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_UDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_imem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_UDIMM_2D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_udimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_UDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_udimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_UDIMM_2D_HASH_OID); + +static auth_param_type_desc_t ddr_imem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_RDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_imem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_IMEM_RDIMM_2D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_rdimm_1d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_RDIMM_1D_HASH_OID); +static auth_param_type_desc_t ddr_dmem_rdimm_2d_fw_hash = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_HASH, DDR_DMEM_RDIMM_2D_HASH_OID); +#endif + + +/* + * Trusted key certificate + */ +static const auth_img_desc_t trusted_key_cert = { + .img_id = TRUSTED_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = NULL, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &subject_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &trusted_world_pk, + .data = { + .ptr = (void *)trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + }, + [1] = { + .type_desc = &non_trusted_world_pk, + .data = { + .ptr = (void *)non_trusted_world_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; + +/* + * SoC Firmware + */ +static const auth_img_desc_t soc_fw_key_cert = { + .img_id = SOC_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t soc_fw_content_cert = { + .img_id = SOC_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &soc_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &soc_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &soc_fw_hash, + .data = { + .ptr = (void *)soc_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &soc_fw_config_hash, + .data = { + .ptr = (void *)soc_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl31_image = { + .img_id = BL31_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_hash + } + } + } +}; +/* SOC FW Config */ +static const auth_img_desc_t soc_fw_config = { + .img_id = SOC_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &soc_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &soc_fw_config_hash + } + } + } +}; +/* + * Trusted OS Firmware + */ +static const auth_img_desc_t trusted_os_fw_key_cert = { + .img_id = TRUSTED_OS_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t trusted_os_fw_content_cert = { + .img_id = TRUSTED_OS_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_os_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &tos_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &tos_fw_hash, + .data = { + .ptr = (void *)tos_fw_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &tos_fw_extra1_hash, + .data = { + .ptr = (void *)tos_fw_extra1_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &tos_fw_extra2_hash, + .data = { + .ptr = (void *)tos_fw_extra2_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &tos_fw_config_hash, + .data = { + .ptr = (void *)tos_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl32_image = { + .img_id = BL32_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra1_image = { + .img_id = BL32_EXTRA1_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra1_hash + } + } + } +}; +static const auth_img_desc_t bl32_extra2_image = { + .img_id = BL32_EXTRA2_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_extra2_hash + } + } + } +}; +/* TOS FW Config */ +static const auth_img_desc_t tos_fw_config = { + .img_id = TOS_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &trusted_os_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &tos_fw_config_hash + } + } + } +}; +/* + * Non-Trusted Firmware + */ +static const auth_img_desc_t non_trusted_fw_key_cert = { + .img_id = NON_TRUSTED_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &non_trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_fw_content_pk, + .data = { + .ptr = (void *)content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t non_trusted_fw_content_cert = { + .img_id = NON_TRUSTED_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &non_trusted_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &nt_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &non_trusted_nv_ctr, + .plat_nv_ctr = &non_trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &nt_world_bl_hash, + .data = { + .ptr = (void *)nt_world_bl_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &nt_fw_config_hash, + .data = { + .ptr = (void *)nt_fw_config_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + } + } +}; +static const auth_img_desc_t bl33_image = { + .img_id = BL33_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_world_bl_hash + } + } + } +}; +/* NT FW Config */ +static const auth_img_desc_t nt_fw_config = { + .img_id = NT_FW_CONFIG_ID, + .img_type = IMG_RAW, + .parent = &non_trusted_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &nt_fw_config_hash + } + } + } +}; +#ifdef CONFIG_DDR_FIP_IMAGE +/* + * DDR Firmware + */ +static const auth_img_desc_t ddr_fw_key_cert = { + .img_id = DDR_FW_KEY_CERT_ID, + .img_type = IMG_CERT, + .parent = &trusted_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &trusted_world_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_fw_content_pk, + .data = { + .ptr = (void *)ddr_fw_content_pk_buf, + .len = (unsigned int)PK_DER_LEN + } + } + } +}; +static const auth_img_desc_t ddr_udimm_fw_content_cert = { + .img_id = DDR_UDIMM_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &ddr_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &ddr_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_imem_udimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_udimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &ddr_imem_udimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_udimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ddr_dmem_udimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_udimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &ddr_dmem_udimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_udimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + } +}; + +static const auth_img_desc_t ddr_imem_udimm_1d_img = { + .img_id = DDR_IMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_udimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_udimm_2d_img = { + .img_id = DDR_IMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_udimm_2d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_1d_img = { + .img_id = DDR_DMEM_UDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_udimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_udimm_2d_img = { + .img_id = DDR_DMEM_UDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_udimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_udimm_2d_fw_hash + } + } + } +}; + +static const auth_img_desc_t ddr_rdimm_fw_content_cert = { + .img_id = DDR_RDIMM_FW_CONTENT_CERT_ID, + .img_type = IMG_CERT, + .parent = &ddr_fw_key_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_SIG, + .param.sig = { + .pk = &ddr_fw_content_pk, + .sig = &sig, + .alg = &sig_alg, + .data = &raw_data + } + }, + [1] = { + .type = AUTH_METHOD_NV_CTR, + .param.nv_ctr = { + .cert_nv_ctr = &trusted_nv_ctr, + .plat_nv_ctr = &trusted_nv_ctr + } + } + }, + .authenticated_data = (const auth_param_desc_t[COT_MAX_VERIFIED_PARAMS]) { + [0] = { + .type_desc = &ddr_imem_rdimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_rdimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [1] = { + .type_desc = &ddr_imem_rdimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_imem_rdimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [2] = { + .type_desc = &ddr_dmem_rdimm_1d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_rdimm_1d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + [3] = { + .type_desc = &ddr_dmem_rdimm_2d_fw_hash, + .data = { + .ptr = (void *)ddr_dmem_rdimm_2d_hash_buf, + .len = (unsigned int)HASH_DER_LEN + } + }, + } +}; + +static const auth_img_desc_t ddr_imem_rdimm_1d_img = { + .img_id = DDR_IMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_rdimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_imem_rdimm_2d_img = { + .img_id = DDR_IMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_imem_rdimm_2d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_1d_img = { + .img_id = DDR_DMEM_RDIMM_1D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_rdimm_1d_fw_hash + } + } + } +}; +static const auth_img_desc_t ddr_dmem_rdimm_2d_img = { + .img_id = DDR_DMEM_RDIMM_2D_IMAGE_ID, + .img_type = IMG_RAW, + .parent = &ddr_rdimm_fw_content_cert, + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { + [0] = { + .type = AUTH_METHOD_HASH, + .param.hash = { + .data = &raw_data, + .hash = &ddr_dmem_rdimm_2d_fw_hash + } + } + } +}; +#endif + +/* + * TBBR Chain of trust definition + */ + +static const auth_img_desc_t * const cot_desc[] = { + [TRUSTED_KEY_CERT_ID] = &trusted_key_cert, + [SOC_FW_KEY_CERT_ID] = &soc_fw_key_cert, + [SOC_FW_CONTENT_CERT_ID] = &soc_fw_content_cert, + [BL31_IMAGE_ID] = &bl31_image, + [SOC_FW_CONFIG_ID] = &soc_fw_config, + [TRUSTED_OS_FW_KEY_CERT_ID] = &trusted_os_fw_key_cert, + [TRUSTED_OS_FW_CONTENT_CERT_ID] = &trusted_os_fw_content_cert, + [BL32_IMAGE_ID] = &bl32_image, + [BL32_EXTRA1_IMAGE_ID] = &bl32_extra1_image, + [BL32_EXTRA2_IMAGE_ID] = &bl32_extra2_image, + [TOS_FW_CONFIG_ID] = &tos_fw_config, + [NON_TRUSTED_FW_KEY_CERT_ID] = &non_trusted_fw_key_cert, + [NON_TRUSTED_FW_CONTENT_CERT_ID] = &non_trusted_fw_content_cert, + [BL33_IMAGE_ID] = &bl33_image, + [NT_FW_CONFIG_ID] = &nt_fw_config, +#ifdef CONFIG_DDR_FIP_IMAGE + [DDR_FW_KEY_CERT_ID] = &ddr_fw_key_cert, + [DDR_UDIMM_FW_CONTENT_CERT_ID] = &ddr_udimm_fw_content_cert, + [DDR_RDIMM_FW_CONTENT_CERT_ID] = &ddr_rdimm_fw_content_cert, + [DDR_IMEM_UDIMM_1D_IMAGE_ID] = &ddr_imem_udimm_1d_img, + [DDR_IMEM_UDIMM_2D_IMAGE_ID] = &ddr_imem_udimm_2d_img, + [DDR_DMEM_UDIMM_1D_IMAGE_ID] = &ddr_dmem_udimm_1d_img, + [DDR_DMEM_UDIMM_2D_IMAGE_ID] = &ddr_dmem_udimm_2d_img, + [DDR_IMEM_RDIMM_1D_IMAGE_ID] = &ddr_imem_rdimm_1d_img, + [DDR_IMEM_RDIMM_2D_IMAGE_ID] = &ddr_imem_rdimm_2d_img, + [DDR_DMEM_RDIMM_1D_IMAGE_ID] = &ddr_dmem_rdimm_1d_img, + [DDR_DMEM_RDIMM_2D_IMAGE_ID] = &ddr_dmem_rdimm_2d_img, +#endif +}; + +/* Register the CoT in the authentication module */ +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/drivers/nxp/console/16550_console.S b/arm-trusted-firmware/drivers/nxp/console/16550_console.S new file mode 100644 index 0000000..044d3d0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/16550_console.S @@ -0,0 +1,319 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* UART16550 Registers */ +#define UARTTX 0x0 +#define UARTRX 0x0 +#define UARTDLL 0x0 +#define UARTIER 0x1 +#define UARTDLLM 0x1 +#define UARTFCR 0x2 +#define UARTLCR 0x3 +#define UARTLSR 0x5 +#define UARTMCR 0x4 + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ +#define UARTFCR_64FIFO (1 << 5) + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */ +#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */ +#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */ +#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */ +#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */ +#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */ +#define UARTLSR_FERR (1 << 3) /* Framing Error */ +#define UARTLSR_PERR (1 << 3) /* Parity Error */ +#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */ +#define UARTLSR_RDR (1 << 2) /* Rx Data Ready */ + +#define CONSOLE_T_16550_BASE CONSOLE_T_BASE + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl nxp_console_16550_core_init + .globl nxp_console_16550_core_putc + .globl nxp_console_16550_core_getc + .globl nxp_console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int nxp_console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func nxp_console_16550_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl w2, w2, #4 + udiv w2, w1, w2 + and w1, w2, #0xff /* w1 = DLL */ + lsr w2, w2, #8 + and w2, w2, #0xff /* w2 = DLLM */ + ldrb w3, [x0, #UARTLCR] + orr w3, w3, #UARTLCR_DLAB + strb w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */ + strb w1, [x0, #UARTDLL] /* program DLL */ + strb w2, [x0, #UARTDLLM] /* program DLLM */ + mov w2, #~UARTLCR_DLAB + and w3, w3, w2 + strb w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov w3, #3 + strb w3, [x0, #UARTLCR] + /* no interrupt */ + mov w3, #0 + strb w3, [x0, #UARTIER] + /* enable fifo, DMA */ + mov w3, #(UARTFCR_FIFOEN |UARTFCR_TXCLR | UARTFCR_RXCLR) + strb w3, [x0, #UARTFCR] + /* DTR + RTS */ + mov w3, #3 + str w3, [x0, #UARTMCR] + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc nxp_console_16550_core_init + + .globl nxp_console_16550_register + + /* ----------------------------------------------- + * int nxp_console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If w1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. w2 is ignored then as well. + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate (ignored if w1 is 0) + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func nxp_console_16550_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_16550_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cbz w1, register_16550 + + bl nxp_console_16550_core_init + cbz x0, register_fail + +register_16550: + mov x0, x6 + mov x30, x7 + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc nxp_console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func nxp_console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #'\n' + b.ne 2f + /* Check if the transmit FIFO is full */ +1: ldrb w2, [x1, #UARTLSR] + and w2, w2, #UARTLSR_THRE /* #(UARTLSR_TEMT | UARTLSR_THRE)*/ + cmp w2, #(UARTLSR_THRE) + b.ne 1b + mov w2, #'\r' + strb w2, [x1, #UARTTX] + ldrb w2, [x1, #UARTFCR] + orr w2, w2, #UARTFCR_TXCLR + + /* Check if the transmit FIFO is full */ +2: ldrb w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_THRE) + cmp w2, #(UARTLSR_THRE) + b.ne 2b + strb w0, [x1, #UARTTX] + ret +endfunc nxp_console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func nxp_console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldrb w1, [x0, #UARTLSR] + tbz w1, #UARTLSR_RDR, 1b + ldrb w0, [x0, #UARTRX] + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc nxp_console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t structure + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * int console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func nxp_console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldrb w1, [x0, #UARTLSR] + and w1, w1, #(UARTLSR_THRE) + cmp w1, #(UARTLSR_THRE) + b.ne 1b + + mov w0, #0 + ret +endfunc nxp_console_16550_core_flush + + /* --------------------------------------------- + * int console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : return -1 on error else return 0. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_16550_BASE] + b nxp_console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/nxp/console/console.mk b/arm-trusted-firmware/drivers/nxp/console/console.mk new file mode 100644 index 0000000..6174650 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console.mk @@ -0,0 +1,46 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the CORE files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_CONSOLE},) + +ADD_CONSOLE := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/console + +ifeq ($(CONSOLE), NS16550) +NXP_CONSOLE := NS16550 + +$(eval $(call add_define_val,NXP_CONSOLE,${NXP_CONSOLE})) + +CONSOLE_SOURCES := $(PLAT_DRIVERS_PATH)/console/16550_console.S \ + $(PLAT_DRIVERS_PATH)/console/console_16550.c +else +ifeq ($(CONSOLE), PL011) +CONSOLE_SOURCES := drivers/arm/pl011/aarch64/pl011_console.S \ + ${PLAT_DRIVERS_PATH}/console/console_pl011.c +else + $(error -> CONSOLE not set!) +endif +endif + +ifeq (${BL_COMM_CONSOLE_NEEDED},yes) +BL_COMMON_SOURCES += ${CONSOLE_SOURCES} +else +ifeq (${BL2_CONSOLE_NEEDED},yes) +BL2_SOURCES += ${CONSOLE_SOURCES} +endif +ifeq (${BL31_CONSOLE_NEEDED},yes) +BL31_SOURCES += ${CONSOLE_SOURCES} +endif +endif +endif +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/console/console_16550.c b/arm-trusted-firmware/drivers/nxp/console/console_16550.c new file mode 100644 index 0000000..fa5c5bb --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console_16550.c @@ -0,0 +1,33 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include + +/* + * Perform Arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud) +{ + struct sysinfo sys; + static console_t nxp_console; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + panic(); + } + nxp_console_16550_register(nxp_console_addr, + (sys.freq_platform/uart_clk_div), + baud, &nxp_console); +} diff --git a/arm-trusted-firmware/drivers/nxp/console/console_pl011.c b/arm-trusted-firmware/drivers/nxp/console/console_pl011.c new file mode 100644 index 0000000..93f2fc2 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/console/console_pl011.c @@ -0,0 +1,35 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include + +/* + * Perform Arm specific early platform setup. At this moment we only initialize + * the console and the memory layout. + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud) +{ + struct sysinfo sys; + static console_t nxp_console; + + zeromem(&sys, sizeof(sys)); + if (get_clocks(&sys)) { + ERROR("System clocks are not set\n"); + panic(); + } + + console_pl011_register(nxp_console_addr, + (sys.freq_platform/uart_clk_div), + baud, &nxp_console); +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk b/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk new file mode 100644 index 0000000..f929f53 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/caam.mk @@ -0,0 +1,27 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +ifeq (${ADD_CAAM},) + +ADD_CAAM := 1 + +CAAM_DRIVER_SOURCES += $(wildcard $(PLAT_DRIVERS_PATH)/crypto/caam/src/*.c) + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/crypto/caam + +ifeq (${BL_COMM_CRYPTO_NEEDED},yes) +BL_COMMON_SOURCES += ${CAAM_DRIVER_SOURCES} +else +ifeq (${BL2_CRYPTO_NEEDED},yes) +BL2_SOURCES += ${CAAM_DRIVER_SOURCES} +endif +ifeq (${BL31_CRYPTO_NEEDED},yes) +BL31_SOURCES += ${CAAM_DRIVER_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk new file mode 100644 index 0000000..d1f8c75 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/auth.mk @@ -0,0 +1,12 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +SEC_DRIVERS_PATH := drivers/nxp/crypto/caam + +ifeq (${TRUSTED_BOARD_BOOT},1) +AUTH_SOURCES += $(wildcard $(SEC_DRIVERS_PATH)/src/auth/*.c) +endif diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c new file mode 100644 index 0000000..1665df1 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c @@ -0,0 +1,155 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include + +#include "hash.h" +#include "jobdesc.h" +#include "sec_hw_specific.h" + +/* Since no Allocator is available . Taking a global static ctx. + * This would mean that only one active ctx can be there at a time. + */ + +static struct hash_ctx glbl_ctx; + +static void hash_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("Hash Desc SUCCESS with status %x\n", status); +} + +/*************************************************************************** + * Function : hash_init + * Arguments : ctx - SHA context + * Return : init, + * Description : This function initializes the context for SHA calculation + ***************************************************************************/ +int hash_init(enum hash_algo algo, void **ctx) +{ + if (glbl_ctx.active == false) { + memset(&glbl_ctx, 0, sizeof(struct hash_ctx)); + glbl_ctx.active = true; + glbl_ctx.algo = algo; + *ctx = &glbl_ctx; + return 0; + } else { + return -1; + } +} + +/*************************************************************************** + * Function : hash_update + * Arguments : ctx - SHA context + * buffer - Data + * length - Length + * Return : -1 on error + * 0 on SUCCESS + * Description : This function creates SG entry of the data provided + ***************************************************************************/ +int hash_update(enum hash_algo algo, void *context, void *data_ptr, + unsigned int data_len) +{ + struct hash_ctx *ctx = context; + /* MAX_SG would be MAX_SG_ENTRIES + key + hdr + sg table */ + if (ctx->sg_num >= MAX_SG) { + ERROR("Reached limit for calling %s\n", __func__); + ctx->active = false; + return -EINVAL; + + } + + if (ctx->algo != algo) { + ERROR("ctx for algo not correct\n"); + ctx->active = false; + return -EINVAL; + } + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)data_ptr, data_len); + dmbsy(); +#endif + +#ifdef CONFIG_PHYS_64BIT + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, + (uint32_t) ((uintptr_t) data_ptr >> 32)); +#else + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_hi, 0x0); +#endif + sec_out32(&ctx->sg_tbl[ctx->sg_num].addr_lo, (uintptr_t) data_ptr); + + sec_out32(&ctx->sg_tbl[ctx->sg_num].len_flag, + (data_len & SG_ENTRY_LENGTH_MASK)); + + ctx->sg_num++; + + ctx->len += data_len; + + return 0; +} + +/*************************************************************************** + * Function : hash_final + * Arguments : ctx - SHA context + * Return : SUCCESS or FAILURE + * Description : This function sets the final bit and enqueues the decriptor + ***************************************************************************/ +int hash_final(enum hash_algo algo, void *context, void *hash_ptr, + unsigned int hash_len) +{ + int ret = 0; + struct hash_ctx *ctx = context; + uint32_t final = 0U; + + struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); + + jobdesc.arg = NULL; + jobdesc.callback = hash_done; + + if (ctx->algo != algo) { + ERROR("ctx for algo not correct\n"); + ctx->active = false; + return -EINVAL; + } + + final = sec_in32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag) | + SG_ENTRY_FINAL_BIT; + sec_out32(&ctx->sg_tbl[ctx->sg_num - 1].len_flag, final); + + dsb(); + + /* create the hw_rng descriptor */ + cnstr_hash_jobdesc(jobdesc.desc, (uint8_t *) ctx->sg_tbl, + ctx->len, hash_ptr); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)ctx->sg_tbl, + (sizeof(struct sg_entry) * MAX_SG)); + inv_dcache_range((uintptr_t)hash_ptr, hash_len); + + dmbsy(); +#endif + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(&jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + ctx->active = false; + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c new file mode 100644 index 0000000..646e981 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c @@ -0,0 +1,123 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include "caam.h" +#include +#include + +#include "hash.h" +#include "rsa.h" + +#define LIB_NAME "NXP crypto" + +/* + * Initialize the library and export the descriptor + */ +static void init(void) +{ + /* Initialize NXP crypto library`:*/ + NOTICE("Initializing & configuring SEC block.\n"); + + if (config_sec_block() < 0) { + ERROR("Init & config failure for caam.\n"); + } +} + +/* + * Verify a signature. + * + * For IMG_PLAT - data points to a PKCS#1.5 encoded HASH + * sig_alg will be RSA or ECC + * Parameters are passed using the DER encoding format following the ASN.1 + * structures detailed above. + */ +static int verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sign_alg, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len) +{ + int ret = CRYPTO_SUCCESS; + + enum sig_alg alg = *(enum sig_alg *)sign_alg; + + switch (alg) { + case RSA: + NOTICE("Verifying RSA\n"); + ret = rsa_verify_signature(data_ptr, data_len, sig_ptr, sig_len, + pk_ptr, pk_len); + break; + case ECC: + default: + ret = CRYPTO_ERR_SIGNATURE; + break; + } + + if (ret != 0) { + ERROR("RSA verification Failed\n"); + } + return ret; + +} + +/* + * Match a hash + * + * Digest info is passed as a table of SHA-26 hashes and digest_info_len + * is number of entries in the table + * This implementation is very specific to the CSF header parser ROTPK + * comparison. + */ +static int verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len) +{ + void *ctx = NULL; + int i = 0, ret = 0; + enum hash_algo algo = SHA256; + uint8_t hash[SHA256_BYTES] __aligned(CACHE_WRITEBACK_GRANULE) = {0}; + uint32_t digest_size = SHA256_BYTES; + uint8_t *hash_tbl = digest_info_ptr; + + NOTICE("Verifying hash\n"); + ret = hash_init(algo, &ctx); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + /* Update hash with that of SRK table */ + ret = hash_update(algo, ctx, data_ptr, data_len); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + /* Copy hash at destination buffer */ + ret = hash_final(algo, ctx, hash, digest_size); + if (ret != 0) { + return CRYPTO_ERR_HASH; + } + + VERBOSE("%s Calculated hash\n", __func__); + for (i = 0; i < SHA256_BYTES/4; i++) { + VERBOSE("%x\n", *((uint32_t *)hash + i)); + } + + for (i = 0; i < digest_info_len; i++) { + if (memcmp(hash, (hash_tbl + (i * digest_size)), + digest_size) == 0) { + return CRYPTO_SUCCESS; + } + } + + return CRYPTO_ERR_HASH; +} + +/* + * Register crypto library descriptor + */ +REGISTER_CRYPTO_LIB(LIB_NAME, init, verify_signature, verify_hash, NULL); diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c new file mode 100644 index 0000000..0c44462 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c @@ -0,0 +1,179 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include + +#include "jobdesc.h" +#include "rsa.h" +#include "sec_hw_specific.h" + +/* This array contains DER value for SHA-256 */ +static const uint8_t hash_identifier[] = { + 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, + 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, 0x00, + 0x04, 0x20 +}; + +static void rsa_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("RSA Desc SUCCESS with status %x\n", status); +} + +static int rsa_public_verif_sec(uint8_t *sign, uint8_t *to, + uint8_t *rsa_pub_key, uint32_t klen) +{ + int ret = 0; + struct rsa_context ctx __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor jobdesc __aligned(CACHE_WRITEBACK_GRANULE); + + jobdesc.arg = NULL; + jobdesc.callback = rsa_done; + + memset(&ctx, 0, sizeof(struct rsa_context)); + + ctx.pkin.a = sign; + ctx.pkin.a_siz = klen; + ctx.pkin.n = rsa_pub_key; + ctx.pkin.n_siz = klen; + ctx.pkin.e = rsa_pub_key + klen; + ctx.pkin.e_siz = klen; + + cnstr_jobdesc_pkha_rsaexp(jobdesc.desc, &ctx.pkin, to, klen); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)sign, klen); + flush_dcache_range((uintptr_t)rsa_pub_key, 2 * klen); + flush_dcache_range((uintptr_t)&ctx.pkin, sizeof(ctx.pkin)); + inv_dcache_range((uintptr_t)to, klen); + + dmbsy(); + dsbsy(); + isb(); +#endif + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(&jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)to, klen); + dmbsy(); + dsbsy(); + isb(); +#endif + return ret; +} + +/* + * Construct encoded hash EM' wrt PKCSv1.5. This function calculates the + * pointers for padding, DER value and hash. And finally, constructs EM' + * which includes hash of complete CSF header and ESBC image. If SG flag + * is on, hash of SG table and entries is also included. + */ +static int construct_img_encoded_hash_second(uint8_t *hash, uint8_t hash_len, + uint8_t *encoded_hash_second, + unsigned int key_len) +{ + /* + * RSA PKCSv1.5 encoding format for encoded message is below + * EM = 0x0 || 0x1 || PS || 0x0 || DER || Hash + * PS is Padding String + * DER is DER value for SHA-256 + * Hash is SHA-256 hash + * ********************************************************* + * representative points to first byte of EM initially and is + * filled with 0x0 + * representative is incremented by 1 and second byte is filled + * with 0x1 + * padding points to third byte of EM + * digest points to full length of EM - 32 bytes + * hash_id (DER value) points to 19 bytes before pDigest + * separator is one byte which separates padding and DER + */ + + unsigned int len; + uint8_t *representative; + uint8_t *padding, *digest; + uint8_t *hash_id, *separator; + int i; + int ret = 0; + + if (hash_len != SHA256_BYTES) { + return -1; + } + + /* Key length = Modulus length */ + len = (key_len / 2U) - 1U; + representative = encoded_hash_second; + representative[0] = 0U; + representative[1] = 1U; /* block type 1 */ + + padding = &representative[2]; + digest = &representative[1] + len - 32; + hash_id = digest - sizeof(hash_identifier); + separator = hash_id - 1; + + /* fill padding area pointed by padding with 0xff */ + memset(padding, 0xff, separator - padding); + + /* fill byte pointed by separator */ + *separator = 0U; + + /* fill SHA-256 DER value pointed by HashId */ + memcpy(hash_id, hash_identifier, sizeof(hash_identifier)); + + /* fill hash pointed by Digest */ + for (i = 0; i < SHA256_BYTES; i++) { + digest[i] = hash[i]; + } + + return ret; +} + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len) +{ + uint8_t img_encoded_hash_second[RSA_4K_KEY_SZ_BYTES]; + uint8_t encoded_hash[RSA_4K_KEY_SZ_BYTES] __aligned(CACHE_WRITEBACK_GRANULE); + int ret = 0; + + ret = construct_img_encoded_hash_second(hash_ptr, hash_len, + img_encoded_hash_second, + pk_len); + if (ret != 0) { + ERROR("Encoded Hash Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = rsa_public_verif_sec(sig_ptr, encoded_hash, pk_ptr, pk_len / 2); + if (ret != 0) { + ERROR("RSA signature Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + ret = memcmp(img_encoded_hash_second, encoded_hash, sig_len); + if (ret != 0) { + ERROR("Comparison Failure\n"); + return CRYPTO_ERR_SIGNATURE; + } + + return CRYPTO_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c new file mode 100644 index 0000000..e594f7b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c @@ -0,0 +1,339 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + +static uintptr_t g_nxp_caam_addr; +static void *job_ring; + +uintptr_t get_caam_addr(void) +{ + if (g_nxp_caam_addr == 0) { + ERROR("Sec Init is not done.\n"); + panic(); + } + return g_nxp_caam_addr; +} + +/* This function sets the TZ bit for the Job ring number passed as @num */ +static void config_tz(int num) +{ + uint32_t jricid; + + /* Setting TZ bit of job ring */ + switch (num) { + case 0: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR0ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 1: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR1ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 2: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR2ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + case 3: + jricid = sec_in32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET); + sec_out32(g_nxp_caam_addr + SEC_REG_JR3ICIDR_MS_OFFSET, + jricid | JRICID_MS_TZ); + break; + default: + break; + } +} + +/* This function checks if Virtualization is enabled for JR and + * accordingly sets the bot for starting JR in JRSTARTR register + */ +static inline void start_jr(int num) +{ + uint32_t ctpr = sec_in32((g_nxp_caam_addr + SEC_REG_CTPR_MS_OFFSET)); + uint32_t tmp = sec_in32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET)); + uint32_t scfgr = sec_in32((g_nxp_caam_addr + SEC_REG_SCFGR_OFFSET)); + bool start = false; + + if ((ctpr & CTPR_VIRT_EN_INC) != 0U) { + if (((ctpr & CTPR_VIRT_EN_POR) != 0U) || + ((scfgr & SCFGR_VIRT_EN) != 0U)) { + start = true; + } + } else { + if ((ctpr & CTPR_VIRT_EN_POR) != 0U) { + start = true; + } + } + + if (start == true) { + switch (num) { + case 0: + tmp |= JRSTARTR_STARTJR0; + break; + case 1: + tmp |= JRSTARTR_STARTJR1; + break; + case 2: + tmp |= JRSTARTR_STARTJR2; + break; + case 3: + tmp |= JRSTARTR_STARTJR3; + break; + default: + break; + } + } + sec_out32((g_nxp_caam_addr + SEC_REG_JRSTARTR_OFFSET), tmp); +} + +/* This functions configures the Job Ring + * JR3 is reserved for use by Secure world + */ +static int configure_jr(int num) +{ + int ret; + void *reg_base_addr; + + switch (num) { + case 0: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR0_OFFSET); + break; + case 1: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR1_OFFSET); + break; + case 2: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR2_OFFSET); + break; + case 3: + reg_base_addr = (void *)(g_nxp_caam_addr + CAAM_JR3_OFFSET); + break; + default: + break; + } + + /* Initialize the JR library */ + ret = sec_jr_lib_init(); + if (ret != 0) { + ERROR("Error in sec_jr_lib_init"); + return -1; + } + + start_jr(num); + + /* Do HW configuration of the JR */ + job_ring = init_job_ring(SEC_NOTIFICATION_TYPE_POLL, 0, 0, + reg_base_addr, 0); + + if (job_ring == NULL) { + ERROR("Error in init_job_ring"); + return -1; + } + + return ret; +} + +/* TBD - Configures and locks the ICID values for various JR */ +static inline void configure_icid(void) +{ +} + +/* TBD configures the TZ settings of RTIC */ +static inline void configure_rtic(void) +{ +} + +int sec_init(uintptr_t nxp_caam_addr) +{ + g_nxp_caam_addr = nxp_caam_addr; + return config_sec_block(); +} + +/* This function configure SEC block: + * - It does basic parameter setting + * - Configures the default Job ring assigned to TZ /secure world + * - Instantiates the RNG + */ +int config_sec_block(void) +{ + int ret = 0; + uint32_t mcfgr; + + if (g_nxp_caam_addr == 0) { + ERROR("Sec Init is not done.\n"); + return -1; + } else if (job_ring != NULL) { + NOTICE("Sec is already initialized and configured.\n"); + return ret; + } + + mcfgr = sec_in32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET); + + /* Modify CAAM Read/Write attributes + * AXI Write - Cacheable, WB and WA + * AXI Read - Cacheable, RA + */ +#if defined(CONFIG_ARCH_LS2080A) || defined(CONFIG_ARCH_LS2088A) + mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0xb << MCFGR_AWCACHE_SHIFT); + mcfgr = (mcfgr & ~MCFGR_ARCACHE_MASK) | (0x6 << MCFGR_ARCACHE_SHIFT); +#else + mcfgr = (mcfgr & ~MCFGR_AWCACHE_MASK) | (0x2 << MCFGR_AWCACHE_SHIFT); +#endif + + /* Set PS bit to 1 */ +#ifdef CONFIG_PHYS_64BIT + mcfgr |= (1 << MCFGR_PS_SHIFT); +#endif + sec_out32(g_nxp_caam_addr + SEC_REG_MCFGR_OFFSET, mcfgr); + + /* Asssign ICID to all Job rings and lock them for usage */ + configure_icid(); + + /* Configure the RTIC */ + configure_rtic(); + + /* Configure the default JR for usage */ + ret = configure_jr(DEFAULT_JR); + if (ret != 0) { + ERROR("\nFSL_JR: configuration failure\n"); + return -1; + } + /* Do TZ configuration of default JR for sec firmware */ + config_tz(DEFAULT_JR); + +#ifdef CONFIG_RNG_INIT + /* Instantiate the RNG */ + ret = hw_rng_instantiate(); + if (ret != 0) { + ERROR("\nRNG Instantiation failure\n"); + return -1; + } +#endif + + return ret; +} + +/* This function is used for sumbitting job to the Job Ring + * [param] [in] - jobdesc to be submitted + * Return - -1 in case of error and 0 in case of SUCCESS + */ +int run_descriptor_jr(struct job_descriptor *jobdesc) +{ + int i = 0, ret = 0; + uint32_t *desc_addr = jobdesc->desc; + uint32_t desc_len = desc_length(jobdesc->desc); + uint32_t desc_word; + + for (i = 0; i < desc_len; i++) { + desc_word = desc_addr[i]; + VERBOSE("%x\n", desc_word); + sec_out32((uint32_t *)&desc_addr[i], desc_word); + } + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)desc_addr, desc_len * 4); + dmbsy(); + dsbsy(); + isb(); +#endif + + ret = enq_jr_desc(job_ring, jobdesc); + if (ret == 0) { + VERBOSE("JR enqueue done...\n"); + } else { + ERROR("Error in Enqueue\n"); + return ret; + } + + VERBOSE("Dequeue in progress"); + + ret = dequeue_jr(job_ring, -1); + if (ret >= 0) { + VERBOSE("Dequeue of %x desc success\n", ret); + ret = 0; + } else { + ERROR("deq_ret %x\n", ret); + ret = -1; + } + + return ret; +} + +/* this function returns a random number using HW RNG Algo + * In case of failure, random number returned is 0 + * prngWidth = 0 - 32 bit random number + * prngWidth > 0 means 64 bit random number + */ +unsigned long long get_random(int rngWidth) +{ + unsigned long long result = 0; + uint8_t rand_byte[64] __aligned(CACHE_WRITEBACK_GRANULE); + uint8_t rand_byte_swp[8]; + int bytes = 0; + int i = 0; + int ret = 0; + +#ifdef CAAM_TEST + rand_byte[0] = U(0x12); + rand_byte[1] = U(0x34); + rand_byte[2] = U(0x56); + rand_byte[3] = U(0x78); + rand_byte[4] = U(0x9a); + rand_byte[5] = U(0xbc); + rand_byte[6] = U(0xde); + rand_byte[7] = U(0xf1); +#endif + + if (rngWidth == 0U) { + bytes = 4; + } else { + bytes = 8; + } + + memset(rand_byte, 0, 64); + + ret = get_rand_bytes_hw(rand_byte, bytes); + + for (i = 0; i < bytes; i++) { + if (ret != 0) { + /* Return 0 in case of failure */ + rand_byte_swp[i] = 0; + } else { + rand_byte_swp[i] = rand_byte[bytes - i - 1]; + result = (result << 8) | rand_byte_swp[i]; + } + } + + INFO("result %llx\n", result); + + return result; + +} /* _get_RNG() */ + +unsigned int _get_hw_unq_key(uint64_t hw_key_phy_addr, unsigned int size) +{ + int ret = 0; + uint8_t *hw_key = (uint8_t *) ptov((phys_addr_t *) hw_key_phy_addr); + + ret = get_hw_unq_key_blob_hw(hw_key, size); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c new file mode 100644 index 0000000..0720695 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c @@ -0,0 +1,81 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Callback function after Instantiation decsriptor is submitted to SEC + */ +static void blob_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("Blob Desc SUCCESS with status %x\n", status); +} + +/* @brief Submit descriptor to create blob + * @retval 0 on success + * @retval -1 on error + */ +int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size) +{ + int ret = 0; + int i = 0; + + uint32_t key_sz = KEY_IDNFR_SZ_BYTES; + uint8_t key_data[KEY_IDNFR_SZ_BYTES]; + uint8_t in_data[16]; + uint8_t out_data[16 + KEY_BLOB_SIZE + MAC_SIZE]; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + uint32_t in_sz = 16U; + + /* Output blob will have 32 bytes key blob in beginning and + * 16 byte HMAC identifier at end of data blob + */ + uint32_t out_sz = in_sz + KEY_BLOB_SIZE + MAC_SIZE; + + uint32_t operation = CMD_OPERATION | OP_TYPE_ENCAP_PROTOCOL | + OP_PCLID_BLOB | BLOB_PROTO_INFO; + + memset(key_data, 0xff, KEY_IDNFR_SZ_BYTES); + memset(in_data, 0x00, in_sz); + memset(out_data, 0x00, in_sz); + + jobdesc->arg = NULL; + jobdesc->callback = blob_done; + + INFO("\nGenerating Master Key Verification Blob.\n"); + + /* Create the hw_rng descriptor */ + ret = cnstr_hw_encap_blob_jobdesc(jobdesc->desc, key_data, key_sz, + CLASS_2, in_data, in_sz, out_data, + out_sz, operation); + + /* Finally, generate the blob. */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running hw unq key blob descriptor\n"); + return -1; + } + /* Copying alternate bytes of the Master Key Verification Blob. + */ + for (i = 0; i < size; i++) { + hw_key[i] = out_data[2 * i]; + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c new file mode 100644 index 0000000..f559c4b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c @@ -0,0 +1,236 @@ +/* + * Copyright 2017-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include "caam.h" +#include +#include "jobdesc.h" +#include "rsa.h" +#include "sec_hw_specific.h" + + +/* Return Length of desctiptr from first word */ +uint32_t desc_length(uint32_t *desc) +{ + return desc[0] & DESC_LEN_MASK; +} + +/*Update start index in first word of descriptor */ +void desc_update_start_index(uint32_t *desc, uint32_t index) +{ + desc[0] |= (index << DESC_START_SHIFT); +} + +/* Initialize the descriptor */ +void desc_init(uint32_t *desc) +{ + *desc = 0; +} + +/* Add word in the descriptor and increment the length */ +void desc_add_word(uint32_t *desc, uint32_t word) +{ + uint32_t len = desc_length(desc); + + /* Add Word at Last */ + uint32_t *last = desc + len; + *last = word; + + /* Increase the length */ + desc[0] += 1; +} + +/* Add Pointer to the descriptor */ +void desc_add_ptr(uint32_t *desc, phys_addr_t *ptr) +{ + uint32_t len = desc_length(desc); + + /* Add Word at Last */ + phys_addr_t *last = (phys_addr_t *) (desc + len); + +#ifdef CONFIG_PHYS_64BIT + ptr_addr_t *ptr_addr = (ptr_addr_t *) last; + + ptr_addr->high = PHYS_ADDR_HI(ptr); + ptr_addr->low = PHYS_ADDR_LO(ptr); +#else + *last = ptr; +#endif + + /* Increase the length */ + desc[0] += (uint32_t) (sizeof(phys_addr_t) / sizeof(uint32_t)); +} + +/* Descriptor to generate Random words */ +int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle, + uint32_t *add_inp, uint32_t add_ip_len, + uint8_t *out_data, uint32_t len) +{ + phys_addr_t *phys_addr_out = vtop(out_data); + + /* Current descriptor support only 64K length */ + if (len > U(0xffff)) + return -1; + /* Additional Input not supported by current descriptor */ + if (add_ip_len > 0U) + return -1; + + VERBOSE("Constructing descriptor\n"); + desc_init(desc); + /* Class1 Alg Operation,RNG Optype, Generate */ + desc_add_word(desc, U(0xb0800000)); + desc_add_word(desc, U(0x82500000) | (state_handle << ALG_AAI_SH_SHIFT)); + desc_add_word(desc, U(0x60340000) | len); + desc_add_ptr(desc, phys_addr_out); + + return 0; + +} + +/* Construct descriptor to instantiate RNG */ +int cnstr_rng_instantiate_jobdesc(uint32_t *desc) +{ + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + /* Class1 Alg Operation,RNG Optype, Instantiate */ + desc_add_word(desc, U(0x82500004)); + /* Wait for done */ + desc_add_word(desc, U(0xa2000001)); + /*Load to clear written */ + desc_add_word(desc, U(0x10880004)); + /*Pri Mode Reg clear */ + desc_add_word(desc, U(0x00000001)); + /* Generate secure keys */ + desc_add_word(desc, U(0x82501000)); + + return 0; +} + +/* Construct descriptor to generate hw key blob */ +int cnstr_hw_encap_blob_jobdesc(uint32_t *desc, + uint8_t *key_idnfr, uint32_t key_sz, + uint32_t key_class, uint8_t *plain_txt, + uint32_t in_sz, uint8_t *enc_blob, + uint32_t out_sz, uint32_t operation) +{ + phys_addr_t *phys_key_idnfr, *phys_addr_in, *phys_addr_out; + int i = 0; + + phys_key_idnfr = vtop((void *)key_idnfr); + phys_addr_in = vtop((void *)plain_txt); + phys_addr_out = vtop((void *)enc_blob); + + desc_init(desc); + + desc_add_word(desc, U(0xb0800000)); + + /* Key Identifier */ + desc_add_word(desc, (key_class | key_sz)); + desc_add_ptr(desc, phys_key_idnfr); + + /* Source Address */ + desc_add_word(desc, U(0xf0400000)); + desc_add_ptr(desc, phys_addr_in); + + /* In Size = 0x10 */ + desc_add_word(desc, in_sz); + + /* Out Address */ + desc_add_word(desc, U(0xf8400000)); + desc_add_ptr(desc, phys_addr_out); + + /* Out Size = 0x10 */ + desc_add_word(desc, out_sz); + + /* Operation */ + desc_add_word(desc, operation); + + for (i = 0; i < 15; i++) + VERBOSE("desc word %x\n", desc[i]); + + return 0; +} + +/*************************************************************************** + * Function : inline_cnstr_jobdesc_pkha_rsaexp + * Arguments : desc - Pointer to Descriptor + * pkin - Pointer to Input Params + * out - Pointer to Output + * out_siz - Output Size + * Return : Void + * Description : Creates the descriptor for PKHA RSA + ***************************************************************************/ +void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz) +{ + phys_addr_t *ptr_addr_e, *ptr_addr_a, *ptr_addr_n, *ptr_addr_out; + + ptr_addr_e = vtop((void *)(pkin->e)); + ptr_addr_a = vtop((void *)(pkin->a)); + ptr_addr_n = vtop((void *)(pkin->n)); + ptr_addr_out = vtop((void *)(out)); + + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + desc_add_word(desc, U(0x02010000) | pkin->e_siz); + desc_add_ptr(desc, ptr_addr_e); + desc_add_word(desc, U(0x220c0000) | pkin->a_siz); + desc_add_ptr(desc, ptr_addr_a); + desc_add_word(desc, U(0x22080000) | pkin->n_siz); + desc_add_ptr(desc, ptr_addr_n); + desc_add_word(desc, U(0x81800006)); + desc_add_word(desc, U(0x620d0000) | out_siz); + desc_add_ptr(desc, ptr_addr_out); +} + +/*************************************************************************** + * Function : inline_cnstr_jobdesc_sha256 + * Arguments : desc - Pointer to Descriptor + * msg - Pointer to SG Table + * msgsz - Size of SG Table + * digest - Pointer to Output Digest + * Return : Void + * Description : Creates the descriptor for SHA256 HASH calculation + ***************************************************************************/ +void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz, + uint8_t *digest) +{ + /* SHA 256 , output is of length 32 words */ + phys_addr_t *ptr_addr_in, *ptr_addr_out; + + ptr_addr_in = (void *)vtop(msg); + ptr_addr_out = (void *)vtop(digest); + + desc_init(desc); + desc_add_word(desc, U(0xb0800000)); + + /* Operation Command + * OP_TYPE_CLASS2_ALG | OP_ALG_ALGSEL_SHA256 | OP_ALG_AAI_HASH | + * OP_ALG_AS_INITFINAL | OP_ALG_ENCRYPT | OP_ALG_ICV_OFF) + */ + desc_add_word(desc, U(0x8443000d)); + + if (msgsz > U(0xffff)) { + desc_add_word(desc, U(0x25540000)); /* FIFO Load */ + desc_add_ptr(desc, ptr_addr_in); /* Pointer to msg */ + desc_add_word(desc, msgsz); /* Size */ + desc_add_word(desc, U(0x54200020)); /* FIFO Store */ + desc_add_ptr(desc, ptr_addr_out); /* Pointer to Result */ + } else { + desc_add_word(desc, U(0x25140000) | msgsz); + desc_add_ptr(desc, ptr_addr_in); + desc_add_word(desc, U(0x54200020)); + desc_add_ptr(desc, ptr_addr_out); + } + +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c new file mode 100644 index 0000000..0b9d87d --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c @@ -0,0 +1,251 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Callback function after Instantiation decsriptor is submitted to SEC */ +static void rng_done(uint32_t *desc, uint32_t status, void *arg, + void *job_ring) +{ + INFO("RNG Desc SUCCESS with status %x\n", status); +} + +/* Is the HW RNG instantiated? + * Return code: + * 0 - Not in the instantiated state + * 1 - In the instantiated state + * state_handle - 0 for SH0, 1 for SH1 + */ +static int is_hw_rng_instantiated(uint32_t *state_handle) +{ + int ret_code = 0; + uint32_t rdsta; + + rdsta = sec_in32(get_caam_addr() + RNG_REG_RDSTA_OFFSET); + + /*Check if either of the two state handles has been instantiated */ + if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) { + *state_handle = 0; + ret_code = 1; + } else if (rdsta & RNG_STATE0_HANDLE_INSTANTIATED) { + *state_handle = 1; + ret_code = 1; + } + + return ret_code; +} + +/* @brief Kick the TRNG block of the RNG HW Engine + * @param [in] ent_delay Entropy delay to be used + * By default, the TRNG runs for 200 clocks per sample; + * 1200 clocks per sample generates better entropy. + * @retval 0 on success + * @retval -1 on error + */ +static void kick_trng(int ent_delay) +{ + uint32_t val; + + /* put RNG4 into program mode */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val | RTMCTL_PRGM; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); + + /* rtsdctl bits 0-15 contain "Entropy Delay, which defines the + * length (in system clocks) of each Entropy sample taken + */ + val = sec_in32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET); + val = (val & ~RTSDCTL_ENT_DLY_MASK) | + (ent_delay << RTSDCTL_ENT_DLY_SHIFT); + sec_out32(get_caam_addr() + RNG_REG_RTSDCTL_OFFSET, val); + /* min. freq. count, equal to 1/4 of the entropy sample length */ + sec_out32(get_caam_addr() + RNG_REG_RTFRQMIN_OFFSET, ent_delay >> 2); + /* disable maximum frequency count */ + sec_out32(get_caam_addr() + RNG_REG_RTFRQMAX_OFFSET, RTFRQMAX_DISABLE); + + /* select raw sampling in both entropy shifter + * and statistical checker + */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val | RTMCTL_SAMP_MODE_RAW_ES_SC; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); + + /* put RNG4 into run mode */ + val = sec_in32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET); + val = val & ~RTMCTL_PRGM; + sec_out32(get_caam_addr() + RNG_REG_RTMCTL_OFFSET, val); +} + +/* @brief Submit descriptor to instantiate the RNG + * @retval 0 on success + * @retval -1 on error + */ +static int instantiate_rng(void) +{ + int ret = 0; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + + jobdesc->arg = NULL; + jobdesc->callback = rng_done; + + /* create the hw_rng descriptor */ + cnstr_rng_instantiate_jobdesc(jobdesc->desc); + + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + return ret; +} + +/* Generate Random Data using HW RNG + * Parameters: + * uint8_t* add_input - user specified optional input byte array + * uint32_t add_input_len - number of bytes of additional input + * uint8_t* out - user specified output byte array + * uint32_t out_len - number of bytes to store in output byte array + * Return code: + * 0 - SUCCESS + * -1 - ERROR + */ +static int +hw_rng_generate(uint32_t *add_input, uint32_t add_input_len, + uint8_t *out, uint32_t out_len, uint32_t state_handle) +{ + int ret = 0; + struct job_descriptor desc __aligned(CACHE_WRITEBACK_GRANULE); + struct job_descriptor *jobdesc = &desc; + + jobdesc->arg = NULL; + jobdesc->callback = rng_done; + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)out, out_len); + dmbsy(); +#endif + + /* create the hw_rng descriptor */ + ret = cnstr_rng_jobdesc(jobdesc->desc, state_handle, + add_input, add_input_len, out, out_len); + if (ret != 0) { + ERROR("Descriptor construction failed\n"); + ret = -1; + goto out; + } + /* Finally, generate the requested random data bytes */ + ret = run_descriptor_jr(jobdesc); + if (ret != 0) { + ERROR("Error in running descriptor\n"); + ret = -1; + } + +out: + return ret; +} + +/* this function instantiates the rng + * + * Return code: + * 0 - All is well + * <0 - Error occurred somewhere + */ +int hw_rng_instantiate(void) +{ + int ret = 0; + int ent_delay = RTSDCTL_ENT_DLY_MIN; + uint32_t state_handle; + + ret = is_hw_rng_instantiated(&state_handle); + if (ret != 0) { + NOTICE("RNG already instantiated\n"); + return 0; + } + do { + kick_trng(ent_delay); + ent_delay += 400; + /*if instantiate_rng(...) fails, the loop will rerun + *and the kick_trng(...) function will modify the + *upper and lower limits of the entropy sampling + *interval, leading to a sucessful initialization of + */ + ret = instantiate_rng(); + } while ((ret == -1) && (ent_delay < RTSDCTL_ENT_DLY_MAX)); + if (ret != 0) { + ERROR("RNG: Failed to instantiate RNG\n"); + return ret; + } + + NOTICE("RNG: INSTANTIATED\n"); + + /* Enable RDB bit so that RNG works faster */ + // sec_setbits32(&sec->scfgr, SEC_SCFGR_RDBENABLE); + + return ret; +} + +/* Generate random bytes, and stuff them into the bytes buffer + * + * If the HW RNG has not already been instantiated, + * it will be instantiated before data is generated. + * + * Parameters: + * uint8_t* bytes - byte buffer large enough to hold the requested random date + * int byte_len - number of random bytes to generate + * + * Return code: + * 0 - All is well + * ~0 - Error occurred somewhere + */ +int get_rand_bytes_hw(uint8_t *bytes, int byte_len) +{ + int ret_code = 0; + uint32_t state_handle; + + /* If this is the first time this routine is called, + * then the hash_drbg will not already be instantiated. + * Therefore, before generating data, instantiate the hash_drbg + */ + ret_code = is_hw_rng_instantiated(&state_handle); + if (ret_code == 0) { + INFO("Instantiating the HW RNG\n"); + + /* Instantiate the hw RNG */ + ret_code = hw_rng_instantiate(); + if (ret_code != 0) { + ERROR("HW RNG Instantiate failed\n"); + return ret_code; + } + } + /* If HW RNG is still not instantiated, something must have gone wrong, + * it must be in the error state, we will not generate any random data + */ + if (is_hw_rng_instantiated(&state_handle) == 0) { + ERROR("HW RNG is in an Error state, and cannot be used\n"); + return -1; + } + /* Generate a random 256-bit value, as 32 bytes */ + ret_code = hw_rng_generate(0, 0, bytes, byte_len, state_handle); + if (ret_code != 0) { + ERROR("HW RNG Generate failed\n"); + return ret_code; + } + + return ret_code; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c new file mode 100644 index 0000000..92b7762 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c @@ -0,0 +1,635 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "sec_hw_specific.h" + + +/* Job rings used for communication with SEC HW */ +extern struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS]; + +/* The current state of SEC user space driver */ +extern volatile sec_driver_state_t g_driver_state; + +/* The number of job rings used by SEC user space driver */ +extern int g_job_rings_no; + +/* LOCAL FUNCTIONS */ +static inline void hw_set_input_ring_start_addr(struct jobring_regs *regs, + phys_addr_t *start_addr) +{ +#if defined(CONFIG_PHYS_64BIT) + sec_out32(®s->irba_h, PHYS_ADDR_HI(start_addr)); +#else + sec_out32(®s->irba_h, 0); +#endif + sec_out32(®s->irba_l, PHYS_ADDR_LO(start_addr)); +} + +static inline void hw_set_output_ring_start_addr(struct jobring_regs *regs, + phys_addr_t *start_addr) +{ +#if defined(CONFIG_PHYS_64BIT) + sec_out32(®s->orba_h, PHYS_ADDR_HI(start_addr)); +#else + sec_out32(®s->orba_h, 0); +#endif + sec_out32(®s->orba_l, PHYS_ADDR_LO(start_addr)); +} + +/* ORJR - Output Ring Jobs Removed Register shows how many jobs were + * removed from the Output Ring for processing by software. This is done after + * the software has processed the entries. + */ +static inline void hw_remove_entries(sec_job_ring_t *jr, int num) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + sec_out32(®s->orjr, num); +} + +/* IRSA - Input Ring Slots Available register holds the number of entries in + * the Job Ring's input ring. Once a job is enqueued, the value returned is + * decremented by the hardware by the number of jobs enqueued. + */ +static inline int hw_get_available_slots(sec_job_ring_t *jr) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + return sec_in32(®s->irsa); +} + +/* ORSFR - Output Ring Slots Full register holds the number of jobs which were + * processed by the SEC and can be retrieved by the software. Once a job has + * been processed by software, the user will call hw_remove_one_entry in order + * to notify the SEC that the entry was processed + */ +static inline int hw_get_no_finished_jobs(sec_job_ring_t *jr) +{ + struct jobring_regs *regs = + (struct jobring_regs *)jr->register_base_addr; + + return sec_in32(®s->orsf); +} + +/* @brief Process Jump Halt Condition related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jmp_halt_cond_err(union hw_error_code error_code) +{ + ERROR("JMP %x\n", error_code.error_desc.jmp_halt_cond_src.jmp); + ERROR("Descriptor Index: %d\n", + error_code.error_desc.jmp_halt_cond_src.desc_idx); + ERROR(" Condition %x\n", error_code.error_desc.jmp_halt_cond_src.cond); +} + +/* @brief Process DECO related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_deco_err(union hw_error_code error_code) +{ + ERROR("JMP %x\n", error_code.error_desc.deco_src.jmp); + ERROR("Descriptor Index: 0x%x", + error_code.error_desc.deco_src.desc_idx); + + switch (error_code.error_desc.deco_src.desc_err) { + case SEC_HW_ERR_DECO_HFN_THRESHOLD: + WARN(" Descriptor completed but exceeds the Threshold"); + break; + default: + ERROR("Error 0x%04x not implemented", + error_code.error_desc.deco_src.desc_err); + break; + } +} + +/* @brief Process Jump Halt User Status related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jmp_halt_user_err(union hw_error_code error_code) +{ + WARN(" Not implemented"); +} + +/* @brief Process CCB related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_ccb_err(union hw_error_code hw_error_code) +{ + WARN(" Not implemented"); +} + +/* @brief Process Job Ring related errors + * @param [in] error_code The error code in the descriptor status word + */ +static inline void hw_handle_jr_err(union hw_error_code hw_error_code) +{ + WARN(" Not implemented"); +} + +/* GLOBAL FUNCTIONS */ + +int hw_reset_job_ring(sec_job_ring_t *job_ring) +{ + int ret = 0; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* First reset the job ring in hw */ + ret = hw_shutdown_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed resetting job ring in hardware"); + return ret; + } + /* In order to have the HW JR in a workable state + *after a reset, I need to re-write the input + * queue size, input start address, output queue + * size and output start address + * Write the JR input queue size to the HW register + */ + sec_out32(®s->irs, SEC_JOB_RING_SIZE); + + /* Write the JR output queue size to the HW register */ + sec_out32(®s->ors, SEC_JOB_RING_SIZE); + + /* Write the JR input queue start address */ + hw_set_input_ring_start_addr(regs, vtop(job_ring->input_ring)); + + /* Write the JR output queue start address */ + hw_set_output_ring_start_addr(regs, vtop(job_ring->output_ring)); + + return 0; +} + +int hw_shutdown_job_ring(sec_job_ring_t *job_ring) +{ + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + unsigned int timeout = SEC_TIMEOUT; + uint32_t tmp = 0U; + + VERBOSE("Resetting Job ring\n"); + + /* + * Mask interrupts since we are going to poll + * for reset completion status + * Also, at POR, interrupts are ENABLED on a JR, thus + * this is the point where I can disable them without + * changing the code logic too much + */ + + jr_disable_irqs(job_ring); + + /* initiate flush (required prior to reset) */ + sec_out32(®s->jrcr, JR_REG_JRCR_VAL_RESET); + + /* dummy read */ + tmp = sec_in32(®s->jrcr); + + do { + tmp = sec_in32(®s->jrint); + } while (((tmp & JRINT_ERR_HALT_MASK) == + JRINT_ERR_HALT_INPROGRESS) && ((--timeout) != 0U)); + + if ((tmp & JRINT_ERR_HALT_MASK) != JRINT_ERR_HALT_COMPLETE || + timeout == 0U) { + ERROR("Failed to flush hw job ring %x\n %u", tmp, timeout); + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return -1; + } + /* Initiate reset */ + timeout = SEC_TIMEOUT; + sec_out32(®s->jrcr, JR_REG_JRCR_VAL_RESET); + + do { + tmp = sec_in32(®s->jrcr); + } while (((tmp & JR_REG_JRCR_VAL_RESET) != 0U) && + ((--timeout) != 0U)); + + if (timeout == 0U) { + ERROR("Failed to reset hw job ring\n"); + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return -1; + } + /* unmask interrupts */ + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + jr_enable_irqs(job_ring); + } + return 0; + +} + +void hw_handle_job_ring_error(sec_job_ring_t *job_ring, uint32_t error_code) +{ + union hw_error_code hw_err_code; + + hw_err_code.error = error_code; + + switch (hw_err_code.error_desc.value.ssrc) { + case SEC_HW_ERR_SSRC_NO_SRC: + INFO("No Status Source "); + break; + case SEC_HW_ERR_SSRC_CCB_ERR: + INFO("CCB Status Source"); + hw_handle_ccb_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JMP_HALT_U: + INFO("Jump Halt User Status Source"); + hw_handle_jmp_halt_user_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_DECO: + INFO("DECO Status Source"); + hw_handle_deco_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JR: + INFO("Job Ring Status Source"); + hw_handle_jr_err(hw_err_code); + break; + case SEC_HW_ERR_SSRC_JMP_HALT_COND: + INFO("Jump Halt Condition Codes"); + hw_handle_jmp_halt_cond_err(hw_err_code); + break; + default: + INFO("Unknown SSRC"); + break; + } +} + +int hw_job_ring_error(sec_job_ring_t *job_ring) +{ + uint32_t jrint_error_code; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + if (JR_REG_JRINT_JRE_EXTRACT(sec_in32(®s->jrint)) == 0) { + return 0; + } + + jrint_error_code = + JR_REG_JRINT_ERR_TYPE_EXTRACT(sec_in32(®s->jrint)); + switch (jrint_error_code) { + case JRINT_ERR_WRITE_STATUS: + ERROR("Error writing status to Output Ring "); + break; + case JRINT_ERR_BAD_INPUT_BASE: + ERROR("Bad Input Ring Base (not on a 4-byte boundary)\n"); + break; + case JRINT_ERR_BAD_OUTPUT_BASE: + ERROR("Bad Output Ring Base (not on a 4-byte boundary)\n"); + break; + case JRINT_ERR_WRITE_2_IRBA: + ERROR("Invalid write to Input Ring Base Address Register\n"); + break; + case JRINT_ERR_WRITE_2_ORBA: + ERROR("Invalid write to Output Ring Base Address Register\n"); + break; + case JRINT_ERR_RES_B4_HALT: + ERROR("Job Ring released before Job Ring is halted\n"); + break; + case JRINT_ERR_REM_TOO_MANY: + ERROR("Removed too many jobs from job ring\n"); + break; + case JRINT_ERR_ADD_TOO_MANY: + ERROR("Added too many jobs on job ring\n"); + break; + default: + ERROR("Unknown SEC JR Error :%d\n", jrint_error_code); + break; + } + return jrint_error_code; +} + +int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Set descriptor count coalescing */ + reg_val |= (irq_coalescing_count << JR_REG_JRCFG_LO_ICDCT_SHIFT); + + /* Set coalescing timer value */ + reg_val |= (irq_coalescing_timer << JR_REG_JRCFG_LO_ICTT_SHIFT); + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Set coalescing params on jr\n"); + + return 0; +} + +int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Enable coalescing */ + reg_val |= JR_REG_JRCFG_LO_ICEN_EN; + + /* Write in hw */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Enabled coalescing on jr\n"); + + return 0; +} + +int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Disable coalescing */ + reg_val &= ~JR_REG_JRCFG_LO_ICEN_EN; + + /* Write in hw */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Disabled coalescing on jr"); + + return 0; + +} + +void hw_flush_job_ring(struct sec_job_ring_t *job_ring, + uint32_t do_notify, + uint32_t error_code, uint32_t *notified_descs) +{ + int32_t jobs_no_to_discard = 0; + int32_t discarded_descs_no = 0; + int32_t number_of_jobs_available = 0; + + VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx); + VERBOSE("error code %x\n", error_code); + VERBOSE("Notify_desc = %d\n", do_notify); + + number_of_jobs_available = hw_get_no_finished_jobs(job_ring); + + /* Discard all jobs */ + jobs_no_to_discard = number_of_jobs_available; + + VERBOSE("JR pi[%d]i ci[%d]\n", job_ring->pidx, job_ring->cidx); + VERBOSE("Discarding desc = %d\n", jobs_no_to_discard); + + while (jobs_no_to_discard > discarded_descs_no) { + discarded_descs_no++; + /* Now increment the consumer index for the current job ring, + * AFTER saving job in temporary location! + * Increment the consumer index for the current job ring + */ + + job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx, + SEC_JOB_RING_SIZE); + + hw_remove_entries(job_ring, 1); + } + + if (do_notify == true) { + if (notified_descs == NULL) { + return; + } + *notified_descs = discarded_descs_no; + } +} + +/* return >0 in case of success + * -1 in case of error from SEC block + * 0 in case job not yet processed by SEC + * or Descriptor returned is NULL after dequeue + */ +int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit) +{ + int32_t jobs_no_to_notify = 0; + int32_t number_of_jobs_available = 0; + int32_t notified_descs_no = 0; + uint32_t error_descs_no = 0U; + uint32_t sec_error_code = 0U; + uint32_t do_driver_shutdown = false; + phys_addr_t *fnptr, *arg_addr; + user_callback usercall = NULL; + uint8_t *current_desc; + void *arg; + uintptr_t current_desc_addr; + phys_addr_t current_desc_loc; + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range((uintptr_t)job_ring->register_base_addr, sizeof(struct jobring_regs)); + dmbsy(); +#endif + + /* check here if any JR error that cannot be written + * in the output status word has occurred + */ + sec_error_code = hw_job_ring_error(job_ring); + if (unlikely(sec_error_code) != 0) { + ERROR("Error here itself %x\n", sec_error_code); + return -1; + } + /* Compute the number of notifications that need to be raised to UA + * If limit < 0 -> notify all done jobs + * If limit > total number of done jobs -> notify all done jobs + * If limit = 0 -> error + * If limit > 0 && limit < total number of done jobs -> notify a number + * of done jobs equal with limit + */ + + /*compute the number of jobs available in the job ring based on the + * producer and consumer index values. + */ + + number_of_jobs_available = hw_get_no_finished_jobs(job_ring); + jobs_no_to_notify = (limit < 0 || limit > number_of_jobs_available) ? + number_of_jobs_available : limit; + VERBOSE("JR - pi %d, ci %d, ", job_ring->pidx, job_ring->cidx); + VERBOSE("Jobs submitted %d", number_of_jobs_available); + VERBOSE("Jobs to notify %d\n", jobs_no_to_notify); + + while (jobs_no_to_notify > notified_descs_no) { + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + inv_dcache_range( + (uintptr_t)(&job_ring->output_ring[job_ring->cidx]), + sizeof(struct sec_outring_entry)); + dmbsy(); +#endif + + /* Get job status here */ + sec_error_code = + sec_in32(&(job_ring->output_ring[job_ring->cidx].status)); + + /* Get completed descriptor + */ + current_desc_loc = (uintptr_t) + &job_ring->output_ring[job_ring->cidx].desc; + current_desc_addr = sec_read_addr(current_desc_loc); + + current_desc = ptov((phys_addr_t *) current_desc_addr); + if (current_desc == 0) { + ERROR("No descriptor returned from SEC"); + assert(current_desc); + return 0; + } + /* now increment the consumer index for the current job ring, + * AFTER saving job in temporary location! + */ + job_ring->cidx = SEC_CIRCULAR_COUNTER(job_ring->cidx, + SEC_JOB_RING_SIZE); + + if (sec_error_code != 0) { + ERROR("desc at cidx %d\n ", job_ring->cidx); + ERROR("generated error %x\n", sec_error_code); + + sec_handle_desc_error(job_ring, + sec_error_code, + &error_descs_no, + &do_driver_shutdown); + hw_remove_entries(job_ring, 1); + + return -1; + } + /* Signal that the job has been processed & the slot is free */ + hw_remove_entries(job_ring, 1); + notified_descs_no++; + + arg_addr = (phys_addr_t *) (current_desc + + (MAX_DESC_SIZE_WORDS * sizeof(uint32_t))); + + fnptr = (phys_addr_t *) (current_desc + + (MAX_DESC_SIZE_WORDS * sizeof(uint32_t) + + sizeof(void *))); + + arg = (void *)*(arg_addr); + if (*fnptr != 0) { + VERBOSE("Callback Function called\n"); + usercall = (user_callback) *(fnptr); + (*usercall) ((uint32_t *) current_desc, + sec_error_code, arg, job_ring); + } + } + + return notified_descs_no; +} + +void sec_handle_desc_error(sec_job_ring_t *job_ring, + uint32_t sec_error_code, + uint32_t *notified_descs, + uint32_t *do_driver_shutdown) +{ + /* Analyze the SEC error on this job ring */ + hw_handle_job_ring_error(job_ring, sec_error_code); +} + +void flush_job_rings(void) +{ + struct sec_job_ring_t *job_ring = NULL; + int i = 0; + + for (i = 0; i < g_job_rings_no; i++) { + job_ring = &g_job_rings[i]; + /* Producer index is frozen. If consumer index is not equal + * with producer index, then we have descs to flush. + */ + while (job_ring->pidx != job_ring->cidx) { + hw_flush_job_ring(job_ring, false, 0, /* no error */ + NULL); + } + } +} + +int shutdown_job_ring(struct sec_job_ring_t *job_ring) +{ + int ret = 0; + + ret = hw_shutdown_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed to shutdown hardware job ring\n"); + return ret; + } + + if (job_ring->coalescing_en != 0) { + hw_job_ring_disable_coalescing(job_ring); + } + + if (job_ring->jr_mode != SEC_NOTIFICATION_TYPE_POLL) { + ret = jr_disable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to disable irqs for job ring"); + return ret; + } + } + + return 0; +} + +int jr_enable_irqs(struct sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Enable interrupts by disabling interrupt masking*/ + reg_val &= ~JR_REG_JRCFG_LO_IMSK_EN; + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Enable interrupts on JR\n"); + + return 0; +} + +int jr_disable_irqs(struct sec_job_ring_t *job_ring) +{ + uint32_t reg_val = 0U; + struct jobring_regs *regs = + (struct jobring_regs *)job_ring->register_base_addr; + + /* Get the current value of the register */ + reg_val = sec_in32(®s->jrcfg1); + + /* Disable interrupts by enabling interrupt masking*/ + reg_val |= JR_REG_JRCFG_LO_IMSK_EN; + + /* Update parameters in HW */ + sec_out32(®s->jrcfg1, reg_val); + + VERBOSE("Disable interrupts on JR\n"); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c new file mode 100644 index 0000000..1fe7007 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c @@ -0,0 +1,241 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +#include +#include "caam.h" +#include +#include "jobdesc.h" +#include "nxp_timer.h" +#include "sec_hw_specific.h" +#include "sec_jr_driver.h" + + +/* Job rings used for communication with SEC HW */ +struct sec_job_ring_t g_job_rings[MAX_SEC_JOB_RINGS]; + +/* The current state of SEC user space driver */ +volatile sec_driver_state_t g_driver_state = SEC_DRIVER_STATE_IDLE; + +int g_job_rings_no; + +uint8_t ip_ring[SEC_DMA_MEM_INPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE); +uint8_t op_ring[SEC_DMA_MEM_OUTPUT_RING_SIZE] __aligned(CACHE_WRITEBACK_GRANULE); + +void *init_job_ring(uint8_t jr_mode, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count, + void *reg_base_addr, uint32_t irq_id) +{ + struct sec_job_ring_t *job_ring = &g_job_rings[g_job_rings_no++]; + int ret = 0; + + job_ring->register_base_addr = reg_base_addr; + job_ring->jr_mode = jr_mode; + job_ring->irq_fd = irq_id; + + job_ring->input_ring = vtop(ip_ring); + memset(job_ring->input_ring, 0, SEC_DMA_MEM_INPUT_RING_SIZE); + + job_ring->output_ring = (struct sec_outring_entry *)vtop(op_ring); + memset(job_ring->output_ring, 0, SEC_DMA_MEM_OUTPUT_RING_SIZE); + + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)(job_ring->input_ring), + SEC_DMA_MEM_INPUT_RING_SIZE), + flush_dcache_range((uintptr_t)(job_ring->output_ring), + SEC_DMA_MEM_OUTPUT_RING_SIZE), + + dmbsy(); +#endif + /* Reset job ring in SEC hw and configure job ring registers */ + ret = hw_reset_job_ring(job_ring); + if (ret != 0) { + ERROR("Failed to reset hardware job ring\n"); + return NULL; + } + + if (jr_mode == SEC_NOTIFICATION_TYPE_IRQ) { + /* Enable IRQ if driver work sin interrupt mode */ + ERROR("Enabling DONE IRQ generation on job ring\n"); + ret = jr_enable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to enable irqs for job ring\n"); + return NULL; + } + } + if ((irq_coalescing_timer != 0) || (irq_coalescing_count != 0)) { + hw_job_ring_set_coalescing_param(job_ring, + irq_coalescing_timer, + irq_coalescing_count); + + hw_job_ring_enable_coalescing(job_ring); + job_ring->coalescing_en = 1; + } + + job_ring->jr_state = SEC_JOB_RING_STATE_STARTED; + + return job_ring; +} + +int sec_release(void) +{ + int i; + + /* Validate driver state */ + if (g_driver_state == SEC_DRIVER_STATE_RELEASE) { + ERROR("Driver release is already in progress"); + return SEC_DRIVER_RELEASE_IN_PROGRESS; + } + /* Update driver state */ + g_driver_state = SEC_DRIVER_STATE_RELEASE; + + /* If any descriptors in flight , poll and wait + * until all descriptors are received and silently discarded. + */ + + flush_job_rings(); + + for (i = 0; i < g_job_rings_no; i++) { + shutdown_job_ring(&g_job_rings[i]); + } + g_job_rings_no = 0; + g_driver_state = SEC_DRIVER_STATE_IDLE; + + return SEC_SUCCESS; +} + +int sec_jr_lib_init(void) +{ + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_IDLE) { + ERROR("Driver already initialized\n"); + return 0; + } + + memset(g_job_rings, 0, sizeof(g_job_rings)); + g_job_rings_no = 0; + + /* Update driver state */ + g_driver_state = SEC_DRIVER_STATE_STARTED; + return 0; +} + +int dequeue_jr(void *job_ring_handle, int32_t limit) +{ + int ret = 0; + int notified_descs_no = 0; + struct sec_job_ring_t *job_ring = (sec_job_ring_t *) job_ring_handle; + uint64_t start_time; + + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_STARTED) { + ERROR("Driver release in progress or driver not initialized\n"); + return -1; + } + + /* Validate input arguments */ + if (job_ring == NULL) { + ERROR("job_ring_handle is NULL\n"); + return -1; + } + if (((limit == 0) || (limit > SEC_JOB_RING_SIZE))) { + ERROR("Invalid limit parameter configuration\n"); + return -1; + } + + VERBOSE("JR Polling limit[%d]\n", limit); + + /* Poll job ring + * If limit < 0 -> poll JR until no more notifications are available. + * If limit > 0 -> poll JR until limit is reached. + */ + + start_time = get_timer_val(0); + + while (notified_descs_no == 0) { + /* Run hw poll job ring */ + notified_descs_no = hw_poll_job_ring(job_ring, limit); + if (notified_descs_no < 0) { + ERROR("Error polling SEC engine job ring "); + return notified_descs_no; + } + VERBOSE("Jobs notified[%d]. ", notified_descs_no); + + if (get_timer_val(start_time) >= CAAM_TIMEOUT) { + break; + } + } + + if (job_ring->jr_mode == SEC_NOTIFICATION_TYPE_IRQ) { + + /* Always enable IRQ generation when in pure IRQ mode */ + ret = jr_enable_irqs(job_ring); + if (ret != 0) { + ERROR("Failed to enable irqs for job ring"); + return ret; + } + } + return notified_descs_no; +} + +int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr) +{ + struct sec_job_ring_t *job_ring; + + job_ring = (struct sec_job_ring_t *)job_ring_handle; + + /* Validate driver state */ + if (g_driver_state != SEC_DRIVER_STATE_STARTED) { + ERROR("Driver release in progress or driver not initialized\n"); + return -1; + } + + /* Check job ring state */ + if (job_ring->jr_state != SEC_JOB_RING_STATE_STARTED) { + ERROR("Job ring is currently resetting\n"); + return -1; + } + + if (SEC_JOB_RING_IS_FULL(job_ring->pidx, job_ring->cidx, + SEC_JOB_RING_SIZE, SEC_JOB_RING_SIZE)) { + ERROR("Job ring is full\n"); + return -1; + } + + /* Set ptr in input ring to current descriptor */ + sec_write_addr(&job_ring->input_ring[job_ring->pidx], + (phys_addr_t) vtop(jobdescr->desc)); + + dsb(); + +#if defined(SEC_MEM_NON_COHERENT) && defined(IMAGE_BL2) + flush_dcache_range((uintptr_t)(&job_ring->input_ring[job_ring->pidx]), + sizeof(phys_addr_t)); + + inv_dcache_range((uintptr_t)(&job_ring->output_ring[job_ring->cidx]), + sizeof(struct sec_outring_entry)); + dmbsy(); +#endif + /* Notify HW that a new job is enqueued */ + hw_enqueue_desc_on_job_ring( + (struct jobring_regs *)job_ring->register_base_addr, 1); + + /* increment the producer index for the current job ring */ + job_ring->pidx = SEC_CIRCULAR_COUNTER(job_ring->pidx, + SEC_JOB_RING_SIZE); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/csu/csu.c b/arm-trusted-firmware/drivers/nxp/csu/csu.c new file mode 100644 index 0000000..9f90fe0 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/csu/csu.c @@ -0,0 +1,34 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev, + uint32_t num, uintptr_t nxp_csu_addr) +{ + uint32_t *base = (uint32_t *)nxp_csu_addr; + uint32_t *reg; + uint32_t val; + int i; + + for (i = 0; i < num; i++) { + reg = base + csu_ns_dev[i].ind / 2U; + val = be32toh(mmio_read_32((uintptr_t)reg)); + if (csu_ns_dev[i].ind % 2U == 0U) { + val &= 0x0000ffffU; + val |= csu_ns_dev[i].val << 16U; + } else { + val &= 0xffff0000U; + val |= csu_ns_dev[i].val; + } + mmio_write_32((uintptr_t)reg, htobe32(val)); + } +} diff --git a/arm-trusted-firmware/drivers/nxp/csu/csu.mk b/arm-trusted-firmware/drivers/nxp/csu/csu.mk new file mode 100644 index 0000000..bc16035 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/csu/csu.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${CSU_ADDED},) + +CSU_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/csu + +CSU_SOURCES += $(PLAT_DRIVERS_PATH)/csu/csu.c + +ifeq (${BL_COMM_CSU_NEEDED},yes) +BL_COMMON_SOURCES += ${CSU_SOURCES} +else +ifeq (${BL2_CSU_NEEDED},yes) +BL2_SOURCES += ${CSU_SOURCES} +endif +ifeq (${BL31_CSU_NEEDED},yes) +BL31_SOURCES += ${CSU_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c new file mode 100644 index 0000000..e5c4db4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c @@ -0,0 +1,156 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include "dcfg.h" +#include +#ifdef NXP_SFP_ENABLED +#include +#endif + +static soc_info_t soc_info = {0}; +static devdisr5_info_t devdisr5_info = {0}; +static dcfg_init_info_t *dcfg_init_info; + +/* Read the PORSR1 register */ +uint32_t read_reg_porsr1(void) +{ + unsigned int *porsr1_addr = NULL; + + if (dcfg_init_info->porsr1 != 0U) { + return dcfg_init_info->porsr1; + } + + porsr1_addr = (void *) + (dcfg_init_info->g_nxp_dcfg_addr + DCFG_PORSR1_OFFSET); + dcfg_init_info->porsr1 = gur_in32(porsr1_addr); + + return dcfg_init_info->porsr1; +} + + +const soc_info_t *get_soc_info(void) +{ + uint32_t reg; + + if (soc_info.is_populated == true) { + return (const soc_info_t *) &soc_info; + } + + reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_SVR_OFFSET); + + soc_info.svr_reg.val = reg; + + /* zero means SEC enabled. */ + soc_info.sec_enabled = + (((reg & SVR_SEC_MASK) >> SVR_SEC_SHIFT) == 0) ? true : false; + + soc_info.is_populated = true; + return (const soc_info_t *) &soc_info; +} + +void dcfg_init(dcfg_init_info_t *dcfg_init_data) +{ + dcfg_init_info = dcfg_init_data; + read_reg_porsr1(); + get_soc_info(); +} + +bool is_sec_enabled(void) +{ + return soc_info.sec_enabled; +} + +const devdisr5_info_t *get_devdisr5_info(void) +{ + uint32_t reg; + + if (devdisr5_info.is_populated == true) + return (const devdisr5_info_t *) &devdisr5_info; + + reg = gur_in32(dcfg_init_info->g_nxp_dcfg_addr + DCFG_DEVDISR5_OFFSET); + + devdisr5_info.ddrc1_present = (reg & DISR5_DDRC1_MASK) ? 0 : 1; +#if defined(CONFIG_CHASSIS_3_2) + devdisr5_info.ddrc2_present = (reg & DISR5_DDRC2_MASK) ? 0 : 1; +#endif + devdisr5_info.ocram_present = (reg & DISR5_OCRAM_MASK) ? 0 : 1; + devdisr5_info.is_populated = true; + + return (const devdisr5_info_t *) &devdisr5_info; +} + +int get_clocks(struct sysinfo *sys) +{ + unsigned int *rcwsr0 = NULL; + const unsigned long sysclk = dcfg_init_info->nxp_sysclk_freq; + const unsigned long ddrclk = dcfg_init_info->nxp_ddrclk_freq; + + rcwsr0 = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR0_OFFSET); + sys->freq_platform = sysclk; + sys->freq_ddr_pll0 = ddrclk; + sys->freq_ddr_pll1 = ddrclk; + + sys->freq_platform *= (gur_in32(rcwsr0) >> + RCWSR0_SYS_PLL_RAT_SHIFT) & + RCWSR0_SYS_PLL_RAT_MASK; + + sys->freq_platform /= dcfg_init_info->nxp_plat_clk_divider; + + sys->freq_ddr_pll0 *= (gur_in32(rcwsr0) >> + RCWSR0_MEM_PLL_RAT_SHIFT) & + RCWSR0_MEM_PLL_RAT_MASK; + sys->freq_ddr_pll1 *= (gur_in32(rcwsr0) >> + RCWSR0_MEM2_PLL_RAT_SHIFT) & + RCWSR0_MEM2_PLL_RAT_MASK; + if (sys->freq_platform == 0) { + return 1; + } else { + return 0; + } +} + +#ifdef NXP_SFP_ENABLED +/******************************************************************************* + * Returns true if secur eboot is enabled on board + * mode = 0 (development mode - sb_en = 1) + * mode = 1 (production mode - ITS = 1) + ******************************************************************************/ +bool check_boot_mode_secure(uint32_t *mode) +{ + uint32_t val = 0U; + uint32_t *rcwsr = NULL; + *mode = 0U; + + if (sfp_check_its() == 1) { + /* ITS =1 , Production mode */ + *mode = 1U; + return true; + } + + rcwsr = (void *)(dcfg_init_info->g_nxp_dcfg_addr + RCWSR_SB_EN_OFFSET); + + val = (gur_in32(rcwsr) >> RCWSR_SBEN_SHIFT) & + RCWSR_SBEN_MASK; + + if (val == RCWSR_SBEN_MASK) { + *mode = 0U; + return true; + } + + return false; +} +#endif + +void error_handler(int error_code) +{ + /* Dump error code in SCRATCH4 register */ + INFO("Error in Fuse Provisioning: %x\n", error_code); + gur_out32((void *) + (dcfg_init_info->g_nxp_dcfg_addr + DCFG_SCRATCH4_OFFSET), + error_code); +} diff --git a/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk new file mode 100644 index 0000000..206595f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/dcfg/dcfg.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_DCFG},) + +ADD_DCFG := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/dcfg + +DCFG_SOURCES += $(PLAT_DRIVERS_PATH)/dcfg/dcfg.c + +ifeq (${BL_COMM_DCFG_NEEDED},yes) +BL_COMMON_SOURCES += ${DCFG_SOURCES} +else +ifeq (${BL2_DCFG_NEEDED},yes) +BL2_SOURCES += ${DCFG_SOURCES} +endif +ifeq (${BL31_DCFG_NEEDED},yes) +BL31_SOURCES += ${DCFG_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk new file mode 100644 index 0000000..afccb62 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/ddr.mk @@ -0,0 +1,19 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- + +# MMDC ddr cntlr driver files + +DDR_DRIVERS_PATH := drivers/nxp/ddr + +DDR_CNTLR_SOURCES := ${PLAT_DRIVERS_PATH}/ddr/fsl-mmdc/fsl_mmdc.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/utility.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddr.c \ + ${PLAT_DRIVERS_PATH}/ddr/nxp-ddr/ddrc.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr \ + -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr/fsl-mmdc +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c new file mode 100644 index 0000000..7e6504e --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c @@ -0,0 +1,176 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* + * Generic driver for Freescale MMDC(Multi Mode DDR Controller). + */ + +#include +#include +#include +#include +#include + +#include +#include "ddr_io.h" +#include +#include + +static void set_wait_for_bits_clear(void *ptr, unsigned int value, + unsigned int bits) +{ + int timeout = 1000; + + ddr_out32(ptr, value); + + while ((ddr_in32(ptr) & bits) != 0) { + udelay(100); + timeout--; + } + if (timeout <= 0) { + INFO("Error: %llx", (unsigned long long)ptr); + INFO(" wait for clear timeout.\n"); + } +} + +void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr) +{ + struct mmdc_regs *mmdc = (struct mmdc_regs *)nxp_ddr_addr; + unsigned int tmp; + + /* 1. set configuration request */ + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); + + /* 2. configure the desired timing parameters */ + ddr_out32(&mmdc->mdotc, priv->mdotc); + ddr_out32(&mmdc->mdcfg0, priv->mdcfg0); + ddr_out32(&mmdc->mdcfg1, priv->mdcfg1); + ddr_out32(&mmdc->mdcfg2, priv->mdcfg2); + + /* 3. configure DDR type and other miscellaneous parameters */ + ddr_out32(&mmdc->mdmisc, priv->mdmisc); + ddr_out32(&mmdc->mpmur0, MMDC_MPMUR0_FRC_MSR); + ddr_out32(&mmdc->mdrwd, priv->mdrwd); + ddr_out32(&mmdc->mpodtctrl, priv->mpodtctrl); + + /* 4. configure the required delay while leaving reset */ + ddr_out32(&mmdc->mdor, priv->mdor); + + /* 5. configure DDR physical parameters */ + /* set row/column address width, burst length, data bus width */ + tmp = priv->mdctl & ~(MDCTL_SDE0 | MDCTL_SDE1); + ddr_out32(&mmdc->mdctl, tmp); + /* configure address space partition */ + ddr_out32(&mmdc->mdasp, priv->mdasp); + + /* 6. perform a ZQ calibration - not needed here, doing in #8b */ + + /* 7. enable MMDC with the desired chip select */ +#if (DDRC_NUM_CS == 1) + ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0); +#elif (DDRC_NUM_CS == 2) + ddr_out32(&mmdc->mdctl, tmp | MDCTL_SDE0 | MDCTL_SDE1); +#else +#error "Unsupported DDRC_NUM_CS" +#endif + + /* 8a. dram init sequence: update MRs for ZQ, ODT, PRE, etc */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(8) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_2); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_1); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x19) | + CMD_ADDR_LSB_MR_ADDR(0x30) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_0); + + /* 8b. ZQ calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(0x4) | + MDSCR_ENABLE_CON_REQ | + CMD_ZQ_CALIBRATION | CMD_BANK_ADDR_0); + + set_wait_for_bits_clear(&mmdc->mpzqhwctrl, priv->mpzqhwctrl, + MPZQHWCTRL_ZQ_HW_FORCE); + + /* 9a. calibrations now, wr lvl */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(0x84) | MDSCR_WL_EN | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); + + set_wait_for_bits_clear(&mmdc->mpwlgcr, MPWLGCR_HW_WL_EN, + MPWLGCR_HW_WL_EN); + + mdelay(1); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | + MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_1); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ); + + mdelay(1); + + /* 9b. read DQS gating calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | + CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); + + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); + + ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); + + /* set absolute read delay offset */ + if (priv->mprddlctl != 0) { + ddr_out32(&mmdc->mprddlctl, priv->mprddlctl); + } else { + ddr_out32(&mmdc->mprddlctl, MMDC_MPRDDLCTL_DEFAULT_DELAY); + } + + set_wait_for_bits_clear(&mmdc->mpdgctrl0, + AUTO_RD_DQS_GATING_CALIBRATION_EN, + AUTO_RD_DQS_GATING_CALIBRATION_EN); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + /* 9c. read calibration */ + ddr_out32(&mmdc->mdscr, CMD_ADDR_MSB_MR_OP(4) | MDSCR_ENABLE_CON_REQ | + CMD_PRECHARGE_BANK_OPEN | CMD_BANK_ADDR_0); + ddr_out32(&mmdc->mdscr, CMD_ADDR_LSB_MR_ADDR(4) | MDSCR_ENABLE_CON_REQ | + CMD_LOAD_MODE_REG | CMD_BANK_ADDR_3); + ddr_out32(&mmdc->mppdcmpr2, MPPDCMPR2_MPR_COMPARE_EN); + set_wait_for_bits_clear(&mmdc->mprddlhwctl, + MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN, + MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN); + + ddr_out32(&mmdc->mdscr, MDSCR_ENABLE_CON_REQ | CMD_LOAD_MODE_REG | + CMD_BANK_ADDR_3); + + /* 10. configure power-down, self-refresh entry, exit parameters */ + ddr_out32(&mmdc->mdpdc, priv->mdpdc); + ddr_out32(&mmdc->mapsr, MMDC_MAPSR_PWR_SAV_CTRL_STAT); + + /* 11. ZQ config again? do nothing here */ + + /* 12. refresh scheme */ + set_wait_for_bits_clear(&mmdc->mdref, priv->mdref, + MDREF_START_REFRESH); + + /* 13. disable CON_REQ */ + ddr_out32(&mmdc->mdscr, MDSCR_DISABLE_CFG_REQ); +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt new file mode 100644 index 0000000..8796302 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt @@ -0,0 +1,31 @@ +Table for dynamic ODT for DDR4 with PHY generation 2 +==================================================== +Two-slot system +Only symmetric configurations are supported for interleaving. Non-symmetric +configurations are possible but not covered here. First slot empty is possbile +but prohibited for simplicity. ++-----------------------+-------------+---------------+-----------------------------+-----------------------------+ +| Configuration | |DRAM controller| Slot 1 | Slot 2 | ++-----------+-----------+-------------+-------+-------+--------------+--------------+--------------+--------------+ +| | | | | | Rank 1 | Rank 2 | Rank 1 | Rank 2 | +| Slot 1 | Slot 2 | Write/Read | Write | Read |-------+------+-------+------+-------+------+-------+------+ +| | | | | | Write | Read | Write | Read | Write | Read | Write | Read | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 60 | 240 | off | 60 | 240 | 60 | 60 | 60 | 60 | +| | |Slot 1|------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 2| off | 60 | 60 | 240 | 240 | off | 60 | 60 | 60 | 60 | +| Dual Rank | Dual Rank |------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 60 | 60 | 60 | 60 | 60 | 240 | off | 60 | 240 | +| | |Slot 2|------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | |Rank 2| off | 60 | 60 | 60 | 60 | 60 | 60 | 240 | 240 | off | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | Slot 1 | off | 60 | 80 | off | | | | | | | +|Single Rank|Single Rank|-------------+-------+-------+-------+------+-------+------+-------+------+-------+------+ +| | | Slot 2 | off | 60 | | | | | 80 | off | ++-----------+-----------+------+------+-------+-------+-------+------+-------+------+-------+------+ +| | | |Rank 1| off | 80 | 80 | off | off | off | +| Dual Rank | |Slot 1|------+-------+-------+-------+------+-------+------+ +| | | |Rank 2| off | 80 | 80 | off | off | off | ++-----------+-----------+-------------+-------+-------+-------+------+-------+------+ +|Single Rank| | Slot 1 | off | 80 | 80 | off | ++-----------+-----------+-------------+-------+-------+-------+------+ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c new file mode 100644 index 0000000..c051b3b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c @@ -0,0 +1,931 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#ifndef CONFIG_DDR_NODIMM +#include +#endif +#include + +struct dynamic_odt { + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; +}; + +#ifndef CONFIG_STATIC_DDR +#if defined(PHY_GEN2_FW_IMAGE_BUFFER) && !defined(NXP_DDR_PHY_GEN2) +#error Missing NXP_DDR_PHY_GEN2 +#endif +#ifdef NXP_DDR_PHY_GEN2 +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs1 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs2 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + }, + { /* cs3 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_60_OHM, + DDR4_RTT_WR_240_OHM + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + { /* cs2 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_CS, + DDR4_RTT_80_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {} +}; +#else +static const struct dynamic_odt single_D[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt single_S[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_ALL, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {}, +}; + +static const struct dynamic_odt dual_DD[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_120_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_OTHER_DIMM, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs2 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_120_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs3 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_OTHER_DIMM, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_OFF + } +}; + +static const struct dynamic_odt dual_SS[4] = { + { /* cs0 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_120_OHM + }, + {}, + { /* cs2 */ + DDR_ODT_OTHER_DIMM, + DDR_ODT_ALL, + DDR4_RTT_34_OHM, + DDR4_RTT_WR_120_OHM + }, + {} +}; + +static const struct dynamic_odt dual_D0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_SAME_DIMM, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + { /* cs1 */ + DDR_ODT_NEVER, + DDR_ODT_NEVER, + DDR4_RTT_OFF, + DDR4_RTT_WR_OFF + }, + {}, + {} +}; + +static const struct dynamic_odt dual_S0[4] = { + { /* cs0 */ + DDR_ODT_NEVER, + DDR_ODT_CS, + DDR4_RTT_40_OHM, + DDR4_RTT_WR_OFF + }, + {}, + {}, + {} +}; +#endif /* NXP_DDR_PHY_GEN2 */ + +/* + * Automatically select bank interleaving mode based on DIMMs + * in this order: cs0_cs1_cs2_cs3, cs0_cs1, null. + * This function only deal with one or two slots per controller. + */ +static inline unsigned int auto_bank_intlv(const int cs_in_use, + const struct dimm_params *pdimm) +{ + switch (cs_in_use) { + case 0xf: + return DDR_BA_INTLV_CS0123; + case 0x3: + return DDR_BA_INTLV_CS01; + case 0x1: + return DDR_BA_NONE; + case 0x5: + return DDR_BA_NONE; + default: + break; + } + + return 0U; +} + +static int cal_odt(const unsigned int clk, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm, + const int dimm_slot_per_ctrl) + +{ + unsigned int i; + const struct dynamic_odt *pdodt = NULL; + + const static struct dynamic_odt *table[2][5] = { + {single_S, single_D, NULL, NULL}, + {dual_SS, dual_DD, NULL, NULL}, + }; + + if (dimm_slot_per_ctrl != 1 && dimm_slot_per_ctrl != 2) { + ERROR("Unsupported number of DIMMs\n"); + return -EINVAL; + } + + pdodt = table[dimm_slot_per_ctrl - 1][pdimm->n_ranks - 1]; + if (pdodt == dual_SS) { + pdodt = (conf->cs_in_use == 0x5) ? dual_SS : + ((conf->cs_in_use == 0x1) ? dual_S0 : NULL); + } else if (pdodt == dual_DD) { + pdodt = (conf->cs_in_use == 0xf) ? dual_DD : + ((conf->cs_in_use == 0x3) ? dual_D0 : NULL); + } + if (pdodt == dual_DD && pdimm->package_3ds) { + ERROR("Too many 3DS DIMMs.\n"); + return -EINVAL; + } + + if (pdodt == NULL) { + ERROR("Error determing ODT.\n"); + return -EINVAL; + } + + /* Pick chip-select local options. */ + for (i = 0U; i < DDRC_NUM_CS; i++) { + debug("cs %d\n", i); + popts->cs_odt[i].odt_rd_cfg = pdodt[i].odt_rd_cfg; + debug(" odt_rd_cfg 0x%x\n", + popts->cs_odt[i].odt_rd_cfg); + popts->cs_odt[i].odt_wr_cfg = pdodt[i].odt_wr_cfg; + debug(" odt_wr_cfg 0x%x\n", + popts->cs_odt[i].odt_wr_cfg); + popts->cs_odt[i].odt_rtt_norm = pdodt[i].odt_rtt_norm; + debug(" odt_rtt_norm 0x%x\n", + popts->cs_odt[i].odt_rtt_norm); + popts->cs_odt[i].odt_rtt_wr = pdodt[i].odt_rtt_wr; + debug(" odt_rtt_wr 0x%x\n", + popts->cs_odt[i].odt_rtt_wr); + popts->cs_odt[i].auto_precharge = 0; + debug(" auto_precharge %d\n", + popts->cs_odt[i].auto_precharge); + } + + return 0; +} + +static int cal_opts(const unsigned int clk, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm, + const int dimm_slot_per_ctrl, + const unsigned int ip_rev) +{ + popts->rdimm = pdimm->rdimm; + popts->mirrored_dimm = pdimm->mirrored_dimm; +#ifdef CONFIG_DDR_ECC_EN + popts->ecc_mode = pdimm->edc_config == 0x02 ? 1 : 0; +#endif + popts->ctlr_init_ecc = popts->ecc_mode; + debug("ctlr_init_ecc %d\n", popts->ctlr_init_ecc); + popts->self_refresh_in_sleep = 1; + popts->dynamic_power = 0; + + /* + * check sdram width, allow platform override + * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit + */ + if (pdimm->primary_sdram_width == 64) { + popts->data_bus_dimm = DDR_DBUS_64; + popts->otf_burst_chop_en = 1; + } else if (pdimm->primary_sdram_width == 32) { + popts->data_bus_dimm = DDR_DBUS_32; + popts->otf_burst_chop_en = 0; + } else if (pdimm->primary_sdram_width == 16) { + popts->data_bus_dimm = DDR_DBUS_16; + popts->otf_burst_chop_en = 0; + } else { + ERROR("primary sdram width invalid!\n"); + return -EINVAL; + } + popts->data_bus_used = popts->data_bus_dimm; + popts->x4_en = (pdimm->device_width == 4) ? 1 : 0; + debug("x4_en %d\n", popts->x4_en); + + /* for RDIMM and DDR4 UDIMM/discrete memory, address parity enable */ + if (popts->rdimm != 0) { + popts->ap_en = 1; /* 0 = disable, 1 = enable */ + } else { + popts->ap_en = 0; /* disabled for DDR4 UDIMM/discrete default */ + } + + if (ip_rev == 0x50500) { + popts->ap_en = 0; + } + + debug("ap_en %d\n", popts->ap_en); + + /* BSTTOPRE precharge interval uses 1/4 of refint value. */ + popts->bstopre = picos_to_mclk(clk, pdimm->refresh_rate_ps) >> 2; + popts->tfaw_ps = pdimm->tfaw_ps; + + return 0; +} + +static void cal_intlv(const int num_ctlrs, + struct memctl_opt *popts, + struct ddr_conf *conf, + struct dimm_params *pdimm) +{ +#ifdef NXP_DDR_INTLV_256B + if (num_ctlrs == 2) { + popts->ctlr_intlv = 1; + popts->ctlr_intlv_mode = DDR_256B_INTLV; + } +#endif + debug("ctlr_intlv %d\n", popts->ctlr_intlv); + debug("ctlr_intlv_mode %d\n", popts->ctlr_intlv_mode); + + popts->ba_intlv = auto_bank_intlv(conf->cs_in_use, pdimm); + debug("ba_intlv 0x%x\n", popts->ba_intlv); +} + +static int update_burst_length(struct memctl_opt *popts) +{ + /* Choose burst length. */ + if ((popts->data_bus_used == DDR_DBUS_32) || + (popts->data_bus_used == DDR_DBUS_16)) { + /* 32-bit or 16-bit bus */ + popts->otf_burst_chop_en = 0; + popts->burst_length = DDR_BL8; + } else if (popts->otf_burst_chop_en != 0) { /* on-the-fly burst chop */ + popts->burst_length = DDR_OTF; /* on-the-fly BC4 and BL8 */ + } else { + popts->burst_length = DDR_BL8; + } + debug("data_bus_used %d\n", popts->data_bus_used); + debug("otf_burst_chop_en %d\n", popts->otf_burst_chop_en); + debug("burst_length 0x%x\n", popts->burst_length); + /* + * If a reduced data width is requested, but the SPD + * specifies a physically wider device, adjust the + * computed dimm capacities accordingly before + * assigning addresses. + * 0 = 64-bit, 1 = 32-bit, 2 = 16-bit + */ + if (popts->data_bus_dimm > popts->data_bus_used) { + ERROR("Data bus configuration error\n"); + return -EINVAL; + } + popts->dbw_cap_shift = popts->data_bus_used - popts->data_bus_dimm; + debug("dbw_cap_shift %d\n", popts->dbw_cap_shift); + + return 0; +} + +int cal_board_params(struct ddr_info *priv, + const struct board_timing *dimm, + int len) +{ + const unsigned long speed = priv->clk / 1000000; + const struct dimm_params *pdimm = &priv->dimm; + struct memctl_opt *popts = &priv->opt; + struct rc_timing const *prt = NULL; + struct rc_timing const *chosen = NULL; + int i; + + for (i = 0; i < len; i++) { + if (pdimm->rc == dimm[i].rc) { + prt = dimm[i].p; + break; + } + } + if (prt == NULL) { + ERROR("Board parameters no match.\n"); + return -EINVAL; + } + while (prt->speed_bin != 0) { + if (speed <= prt->speed_bin) { + chosen = prt; + break; + } + prt++; + } + if (chosen == NULL) { + ERROR("timing no match for speed %lu\n", speed); + return -EINVAL; + } + popts->clk_adj = prt->clk_adj; + popts->wrlvl_start = prt->wrlvl; + popts->wrlvl_ctl_2 = (prt->wrlvl * 0x01010101 + dimm[i].add1) & + 0xFFFFFFFF; + popts->wrlvl_ctl_3 = (prt->wrlvl * 0x01010101 + dimm[i].add2) & + 0xFFFFFFFF; + + return 0; +} + +static int synthesize_ctlr(struct ddr_info *priv) +{ + int ret; + + ret = cal_odt(priv->clk, + &priv->opt, + &priv->conf, + &priv->dimm, + priv->dimm_on_ctlr); + if (ret != 0) { + return ret; + } + + ret = cal_opts(priv->clk, + &priv->opt, + &priv->conf, + &priv->dimm, + priv->dimm_on_ctlr, + priv->ip_rev); + + if (ret != 0) { + return ret; + } + + cal_intlv(priv->num_ctlrs, &priv->opt, &priv->conf, &priv->dimm); + ret = ddr_board_options(priv); + if (ret != 0) { + ERROR("Failed matching board timing.\n"); + } + + ret = update_burst_length(&priv->opt); + + return ret; +} + +/* Return the bit mask of valid DIMMs found */ +static int parse_spd(struct ddr_info *priv) +{ + struct ddr_conf *conf = &priv->conf; + struct dimm_params *dimm = &priv->dimm; + int j, valid_mask = 0; + +#ifdef CONFIG_DDR_NODIMM + valid_mask = ddr_get_ddr_params(dimm, conf); + if (valid_mask < 0) { + ERROR("DDR params error\n"); + return valid_mask; + } +#else + const int *spd_addr = priv->spd_addr; + const int num_ctlrs = priv->num_ctlrs; + const int num_dimm = priv->dimm_on_ctlr; + struct ddr4_spd spd[2]; + unsigned int spd_checksum[2]; + int addr_idx = 0; + int spd_idx = 0; + int ret, addr, i; + + /* Scan all DIMMs */ + for (i = 0; i < num_ctlrs; i++) { + debug("Controller %d\n", i); + for (j = 0; j < num_dimm; j++, addr_idx++) { + debug("DIMM %d\n", j); + addr = spd_addr[addr_idx]; + if (addr == 0) { + if (j == 0) { + ERROR("First SPD addr wrong.\n"); + return -EINVAL; + } + continue; + } + debug("addr 0x%x\n", addr); + ret = read_spd(addr, &spd[spd_idx], + sizeof(struct ddr4_spd)); + if (ret != 0) { /* invalid */ + debug("Invalid SPD at address 0x%x\n", addr); + continue; + } + + spd_checksum[spd_idx] = + (spd[spd_idx].crc[1] << 24) | + (spd[spd_idx].crc[0] << 16) | + (spd[spd_idx].mod_section.uc[127] << 8) | + (spd[spd_idx].mod_section.uc[126] << 0); + debug("checksum 0x%x\n", spd_checksum[spd_idx]); + if (spd_checksum[spd_idx] == 0) { + debug("Bad checksum, ignored.\n"); + continue; + } + if (spd_idx == 0) { + /* first valid SPD */ + ret = cal_dimm_params(&spd[0], dimm); + if (ret != 0) { + ERROR("SPD calculation error\n"); + return -EINVAL; + } + } + + if (spd_idx != 0 && spd_checksum[0] != + spd_checksum[spd_idx]) { + ERROR("Not identical DIMMs.\n"); + return -EINVAL; + } + conf->dimm_in_use[j] = 1; + valid_mask |= 1 << addr_idx; + spd_idx = 1; + } + debug("done with controller %d\n", i); + } + switch (num_ctlrs) { + case 1: + if ((valid_mask & 0x1) == 0) { + ERROR("First slot cannot be empty.\n"); + return -EINVAL; + } + break; + case 2: + switch (num_dimm) { + case 1: + if (valid_mask == 0) { + ERROR("Both slot empty\n"); + return -EINVAL; + } + break; + case 2: + if (valid_mask != 0x5 && + valid_mask != 0xf && + (valid_mask & 0x7) != 0x4 && + (valid_mask & 0xd) != 0x1) { + ERROR("Invalid DIMM combination.\n"); + return -EINVAL; + } + break; + default: + ERROR("Invalid number of DIMMs.\n"); + return -EINVAL; + } + break; + default: + ERROR("Invalid number of controllers.\n"); + return -EINVAL; + } + /* now we have valid and identical DIMMs on controllers */ +#endif /* CONFIG_DDR_NODIMM */ + + debug("cal cs\n"); + conf->cs_in_use = 0; + for (j = 0; j < DDRC_NUM_DIMM; j++) { + if (conf->dimm_in_use[j] == 0) { + continue; + } + switch (dimm->n_ranks) { + case 4: + ERROR("Quad-rank DIMM not supported\n"); + return -EINVAL; + case 2: + conf->cs_on_dimm[j] = 0x3 << (j * CONFIG_CS_PER_SLOT); + conf->cs_in_use |= conf->cs_on_dimm[j]; + break; + case 1: + conf->cs_on_dimm[j] = 0x1 << (j * CONFIG_CS_PER_SLOT); + conf->cs_in_use |= conf->cs_on_dimm[j]; + break; + default: + ERROR("SPD error with n_ranks\n"); + return -EINVAL; + } + debug("cs_in_use = %x\n", conf->cs_in_use); + debug("cs_on_dimm[%d] = %x\n", j, conf->cs_on_dimm[j]); + } +#ifndef CONFIG_DDR_NODIMM + if (priv->dimm.rdimm != 0) { + NOTICE("RDIMM %s\n", priv->dimm.mpart); + } else { + NOTICE("UDIMM %s\n", priv->dimm.mpart); + } +#else + NOTICE("%s\n", priv->dimm.mpart); +#endif + + return valid_mask; +} + +static unsigned long long assign_intlv_addr( + const struct dimm_params *pdimm, + const struct memctl_opt *opt, + struct ddr_conf *conf, + const unsigned long long current_mem_base) +{ + int i; + int ctlr_density_mul = 0; + const unsigned long long rank_density = pdimm->rank_density >> + opt->dbw_cap_shift; + unsigned long long total_ctlr_mem; + + debug("rank density 0x%llx\n", rank_density); + switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { + case DDR_BA_INTLV_CS0123: + ctlr_density_mul = 4; + break; + case DDR_BA_INTLV_CS01: + ctlr_density_mul = 2; + break; + default: + ctlr_density_mul = 1; + break; + } + debug("ctlr density mul %d\n", ctlr_density_mul); + switch (opt->ctlr_intlv_mode) { + case DDR_256B_INTLV: + total_ctlr_mem = 2 * ctlr_density_mul * rank_density; + break; + default: + ERROR("Unknown interleaving mode"); + return 0; + } + conf->base_addr = current_mem_base; + conf->total_mem = total_ctlr_mem; + + /* overwrite cs_in_use bitmask with controller interleaving */ + conf->cs_in_use = (1 << ctlr_density_mul) - 1; + debug("Overwrite cs_in_use as %x\n", conf->cs_in_use); + + /* Fill addr with each cs in use */ + for (i = 0; i < ctlr_density_mul; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = total_ctlr_mem; + debug("CS %d\n", i); + debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); + debug(" size 0x%llx\n", conf->cs_size[i]); + } + + return total_ctlr_mem; +} + +static unsigned long long assign_non_intlv_addr( + const struct dimm_params *pdimm, + const struct memctl_opt *opt, + struct ddr_conf *conf, + unsigned long long current_mem_base) +{ + int i; + const unsigned long long rank_density = pdimm->rank_density >> + opt->dbw_cap_shift; + unsigned long long total_ctlr_mem = 0ULL; + + debug("rank density 0x%llx\n", rank_density); + conf->base_addr = current_mem_base; + + /* assign each cs */ + switch (opt->ba_intlv & DDR_BA_INTLV_CS0123) { + case DDR_BA_INTLV_CS0123: + for (i = 0; i < DDRC_NUM_CS; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density << 2; + total_ctlr_mem += rank_density; + } + break; + case DDR_BA_INTLV_CS01: + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && i < 2; i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density << 1; + total_ctlr_mem += rank_density; + } + current_mem_base += total_ctlr_mem; + for (; ((conf->cs_in_use & (1 << i)) != 0) && i < DDRC_NUM_CS; + i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density; + total_ctlr_mem += rank_density; + current_mem_base += rank_density; + } + break; + case DDR_BA_NONE: + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && + (i < DDRC_NUM_CS); i++) { + conf->cs_base_addr[i] = current_mem_base; + conf->cs_size[i] = rank_density; + current_mem_base += rank_density; + total_ctlr_mem += rank_density; + } + break; + default: + ERROR("Unsupported bank interleaving\n"); + return 0; + } + for (i = 0; ((conf->cs_in_use & (1 << i)) != 0) && + (i < DDRC_NUM_CS); i++) { + debug("CS %d\n", i); + debug(" base_addr 0x%llx\n", conf->cs_base_addr[i]); + debug(" size 0x%llx\n", conf->cs_size[i]); + } + + return total_ctlr_mem; +} + +unsigned long long assign_addresses(struct ddr_info *priv) + __attribute__ ((weak)); + +unsigned long long assign_addresses(struct ddr_info *priv) +{ + struct memctl_opt *opt = &priv->opt; + const struct dimm_params *dimm = &priv->dimm; + struct ddr_conf *conf = &priv->conf; + unsigned long long current_mem_base = priv->mem_base; + unsigned long long total_mem; + + total_mem = 0ULL; + debug("ctlr_intlv %d\n", opt->ctlr_intlv); + if (opt->ctlr_intlv != 0) { + total_mem = assign_intlv_addr(dimm, opt, conf, + current_mem_base); + } else { + /* + * Simple linear assignment if memory controllers are not + * interleaved. This is only valid for SoCs with single DDRC. + */ + total_mem = assign_non_intlv_addr(dimm, opt, conf, + current_mem_base); + } + conf->total_mem = total_mem; + debug("base 0x%llx\n", current_mem_base); + debug("Total mem by assignment is 0x%llx\n", total_mem); + + return total_mem; +} + +static int cal_ddrc_regs(struct ddr_info *priv) +{ + int ret; + + ret = compute_ddrc(priv->clk, + &priv->opt, + &priv->conf, + &priv->ddr_reg, + &priv->dimm, + priv->ip_rev); + if (ret != 0) { + ERROR("Calculating DDR registers failed\n"); + } + + return ret; +} + +#endif /* CONFIG_STATIC_DDR */ + +static int write_ddrc_regs(struct ddr_info *priv) +{ + int i; + int ret; + + for (i = 0; i < priv->num_ctlrs; i++) { + ret = ddrc_set_regs(priv->clk, &priv->ddr_reg, priv->ddr[i], 0); + if (ret != 0) { + ERROR("Writing DDR register(s) failed\n"); + return ret; + } + } + + return 0; +} + +long long dram_init(struct ddr_info *priv +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , uintptr_t nxp_ccn_hn_f0_addr +#endif + ) +{ + uint64_t time __unused; + long long dram_size; + int ret; + const uint64_t time_base = get_timer_val(0); + unsigned int ip_rev = get_ddrc_version(priv->ddr[0]); + + int valid_spd_mask __unused; + int scratch = 0x0; + + priv->ip_rev = ip_rev; + +#ifndef CONFIG_STATIC_DDR + INFO("time base %" PRIu64 " ms\n", time_base); + debug("Parse DIMM SPD(s)\n"); + valid_spd_mask = parse_spd(priv); + + if (valid_spd_mask < 0) { + ERROR("Parsing DIMM Error\n"); + return valid_spd_mask; + } + +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + if (priv->num_ctlrs == 2 || priv->num_ctlrs == 1) { + ret = disable_unused_ddrc(priv, valid_spd_mask, + nxp_ccn_hn_f0_addr); + if (ret != 0) { + return ret; + } + } +#endif + + time = get_timer_val(time_base); + INFO("Time after parsing SPD %" PRIu64 " ms\n", time); + debug("Synthesize configurations\n"); + ret = synthesize_ctlr(priv); + if (ret != 0) { + ERROR("Synthesize config error\n"); + return ret; + } + + debug("Assign binding addresses\n"); + dram_size = assign_addresses(priv); + if (dram_size == 0) { + ERROR("Assigning address error\n"); + return -EINVAL; + } + + debug("Calculate controller registers\n"); + ret = cal_ddrc_regs(priv); + if (ret != 0) { + ERROR("Calculate register error\n"); + return ret; + } + + ret = compute_ddr_phy(priv); + if (ret != 0) + ERROR("Calculating DDR PHY registers failed.\n"); + +#else + dram_size = board_static_ddr(priv); + if (dram_size == 0) { + ERROR("Error getting static DDR settings.\n"); + return -EINVAL; + } +#endif + + if (priv->warm_boot_flag == DDR_WARM_BOOT) { + scratch = (priv->ddr_reg).sdram_cfg[1]; + scratch = scratch & ~(SDRAM_CFG2_D_INIT); + priv->ddr_reg.sdram_cfg[1] = scratch; + } + + time = get_timer_val(time_base); + INFO("Time before programming controller %" PRIu64 " ms\n", time); + debug("Program controller registers\n"); + ret = write_ddrc_regs(priv); + if (ret != 0) { + ERROR("Programing DDRC error\n"); + return ret; + } + + puts(""); + NOTICE("%lld GB ", dram_size >> 30); + print_ddr_info(priv->ddr[0]); + + time = get_timer_val(time_base); + INFO("Time used by DDR driver %" PRIu64 " ms\n", time); + + return dram_size; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk new file mode 100644 index 0000000..f827a1b --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.mk @@ -0,0 +1,80 @@ +# +# Copyright 2021-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(PLAT_DDR_PHY), PHY_GEN2) +$(eval $(call add_define, PHY_GEN2)) +PLAT_DDR_PHY_DIR := phy-gen2 +ifeq (${APPLY_MAX_CDD},yes) +$(eval $(call add_define,NXP_APPLY_MAX_CDD)) +endif + +ifeq (${ERRATA_DDR_A011396}, 1) +$(eval $(call add_define,ERRATA_DDR_A011396)) +endif + +ifeq (${ERRATA_DDR_A050450}, 1) +$(eval $(call add_define,ERRATA_DDR_A050450)) +endif + +ifeq (${ERRATA_DDR_A050958}, 1) +$(eval $(call add_define,ERRATA_DDR_A050958)) +endif + +endif + +ifeq ($(PLAT_DDR_PHY), PHY_GEN1) +PLAT_DDR_PHY_DIR := phy-gen1 + +ifeq (${ERRATA_DDR_A008511},1) +$(eval $(call add_define,ERRATA_DDR_A008511)) +endif + +ifeq (${ERRATA_DDR_A009803},1) +$(eval $(call add_define,ERRATA_DDR_A009803)) +endif + +ifeq (${ERRATA_DDR_A009942},1) +$(eval $(call add_define,ERRATA_DDR_A009942)) +endif + +ifeq (${ERRATA_DDR_A010165},1) +$(eval $(call add_define,ERRATA_DDR_A010165)) +endif + +endif + +ifeq ($(DDR_BIST), yes) +$(eval $(call add_define, BIST_EN)) +endif + +ifeq ($(DDR_DEBUG), yes) +$(eval $(call add_define, DDR_DEBUG)) +endif + +ifeq ($(DDR_PHY_DEBUG), yes) +$(eval $(call add_define, DDR_PHY_DEBUG)) +endif + +ifeq ($(DEBUG_PHY_IO), yes) +$(eval $(call add_define, DEBUG_PHY_IO)) +endif + +ifeq ($(DEBUG_WARM_RESET), yes) +$(eval $(call add_define, DEBUG_WARM_RESET)) +endif + +ifeq ($(DEBUG_DDR_INPUT_CONFIG), yes) +$(eval $(call add_define, DEBUG_DDR_INPUT_CONFIG)) +endif + +DDR_CNTLR_SOURCES := $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddrc.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/dimm.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/regs.c \ + $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/utility.c \ + $(PLAT_DRIVERS_PATH)/ddr/$(PLAT_DDR_PHY_DIR)/phy.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ddr diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c new file mode 100644 index 0000000..17a2b6a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c @@ -0,0 +1,594 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define BIST_CR 0x80060000 +#define BIST_CR_EN 0x80000000 +#define BIST_CR_STAT 0x00000001 +#define CTLR_INTLV_MASK 0x20000000 + +#pragma weak run_bist + +bool run_bist(void) +{ +#ifdef BIST_EN + return true; +#else + return false; +#endif +} + +/* + * Perform build-in test on memory + * timeout value in 10ms + */ +int bist(const struct ccsr_ddr *ddr, int timeout) +{ + const unsigned int test_pattern[10] = { + 0xffffffff, + 0x00000000, + 0xaaaaaaaa, + 0x55555555, + 0xcccccccc, + 0x33333333, + 0x12345678, + 0xabcdef01, + 0xaa55aa55, + 0x55aa55aa + }; + unsigned int mtcr, err_detect, err_sbe; + unsigned int cs0_config; + unsigned int csn_bnds[4]; + int ret = 0; + uint32_t i; +#ifdef CONFIG_DDR_ADDR_DEC + uint32_t dec_9 = ddr_in32(&ddr->dec[9]); + uint32_t pos = 0U; + uint32_t map_save = 0U; + uint32_t temp32 = 0U; + uint32_t map, shift, highest; +#endif + + cs0_config = ddr_in32(&ddr->csn_cfg[0]); + if ((cs0_config & CTLR_INTLV_MASK) != 0U) { + /* set bnds to non-interleaving */ + for (i = 0U; i < 4U; i++) { + csn_bnds[i] = ddr_in32(&ddr->bnds[i].a); + ddr_out32(&ddr->bnds[i].a, + (csn_bnds[i] & U(0xfffefffe)) >> 1U); + } + ddr_out32(&ddr->csn_cfg[0], cs0_config & ~CTLR_INTLV_MASK); +#ifdef CONFIG_DDR_ADDR_DEC + if ((dec_9 & 0x1U) != 0U) { + highest = (dec_9 >> 26U) == U(0x3F) ? 0U : dec_9 >> 26U; + pos = 37U; + for (i = 0U; i < 36U; i++) { /* Go through all 37 */ + if ((i % 4U) == 0U) { + temp32 = ddr_in32(&ddr->dec[i >> 2U]); + } + shift = (3U - i % 4U) * 8U + 2U; + map = (temp32 >> shift) & U(0x3F); + if (map > highest && map != U(0x3F)) { + highest = map; + pos = i; + } + } + debug("\nFound highest position %d, mapping to %d, ", + pos, highest); + map_save = ddr_in32(&ddr->dec[pos >> 2]); + shift = (3U - pos % 4U) * 8U + 2U; + debug("in dec[%d], bit %d (0x%x)\n", + pos >> 2U, shift, map_save); + temp32 = map_save & ~(U(0x3F) << shift); + temp32 |= 8U << shift; + ddr_out32(&ddr->dec[pos >> 2U], temp32); + timeout <<= 2U; + debug("Increase wait time to %d ms\n", timeout * 10); + } +#endif + } + for (i = 0U; i < 10U; i++) { + ddr_out32(&ddr->mtp[i], test_pattern[i]); + } + mtcr = BIST_CR; + ddr_out32(&ddr->mtcr, mtcr); + do { + mdelay(10); + mtcr = ddr_in32(&ddr->mtcr); + } while (timeout-- > 0 && ((mtcr & BIST_CR_EN) != 0)); + if (timeout <= 0) { + ERROR("Timeout\n"); + } else { + debug("Timer remains %d\n", timeout); + } + + err_detect = ddr_in32(&ddr->err_detect); + err_sbe = ddr_in32(&ddr->err_sbe); + if (err_detect != 0U || ((err_sbe & U(0xffff)) != 0U)) { + ERROR("ECC error detected\n"); + ret = -EIO; + } + + if ((cs0_config & CTLR_INTLV_MASK) != 0) { + for (i = 0U; i < 4U; i++) { + ddr_out32(&ddr->bnds[i].a, csn_bnds[i]); + } + ddr_out32(&ddr->csn_cfg[0], cs0_config); +#ifdef CONFIG_DDR_ADDR_DEC + if ((dec_9 & U(0x1)) != 0U) { + ddr_out32(&ddr->dec[pos >> 2], map_save); + } +#endif + } + if ((mtcr & BIST_CR_STAT) != 0) { + ERROR("Built-in self test failed\n"); + ret = -EIO; + } else { + NOTICE("Build-in self test passed\n"); + } + + return ret; +} + +void dump_ddrc(unsigned int *ddr) +{ +#ifdef DDR_DEBUG + uint32_t i; + unsigned long val; + + for (i = 0U; i < U(0x400); i++, ddr++) { + val = ddr_in32(ddr); + if (val != 0U) { /* skip zeros */ + debug("*0x%lx = 0x%lx\n", (unsigned long)ddr, val); + } + } +#endif +} + +#ifdef ERRATA_DDR_A009803 +static void set_wait_for_bits_clear(const void *ptr, + unsigned int value, + unsigned int bits) +{ + int timeout = 1000; + + ddr_out32(ptr, value); + do { + udelay(100); + } while (timeout-- > 0 && ((ddr_in32(ptr) & bits) != 0)); + + if (timeout <= 0) { + ERROR("wait for clear timeout.\n"); + } +} +#endif + +#if (DDRC_NUM_CS > 4) +#error Invalid setting for DDRC_NUM_CS +#endif + +/* + * If supported by the platform, writing to DDR controller takes two + * passes to deassert DDR reset to comply with JEDEC specs for RDIMMs. + */ +int ddrc_set_regs(const unsigned long clk, + const struct ddr_cfg_regs *regs, + const struct ccsr_ddr *ddr, + int twopass) +{ + unsigned int i, bus_width; + unsigned int temp_sdram_cfg; + unsigned int total_mem_per_ctrl, total_mem_per_ctrl_adj; + const int mod_bnds = regs->cs[0].config & CTLR_INTLV_MASK; + int timeout; + int ret = 0; +#if defined(ERRATA_DDR_A009942) || defined(ERRATA_DDR_A010165) + unsigned long ddr_freq; + unsigned int tmp; +#ifdef ERRATA_DDR_A009942 + unsigned int check; + unsigned int cpo_min = U(0xff); + unsigned int cpo_max = 0U; +#endif +#endif + + if (twopass == 2U) { + goto after_reset; + } + + /* Set cdr1 first in case 0.9v VDD is enabled for some SoCs*/ + ddr_out32(&ddr->ddr_cdr1, regs->cdr[0]); + + ddr_out32(&ddr->sdram_clk_cntl, regs->clk_cntl); + + for (i = 0U; i < DDRC_NUM_CS; i++) { + if (mod_bnds != 0U) { + ddr_out32(&ddr->bnds[i].a, + (regs->cs[i].bnds & U(0xfffefffe)) >> 1U); + } else { + ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds); + } + ddr_out32(&ddr->csn_cfg_2[i], regs->cs[i].config_2); + } + + ddr_out32(&ddr->timing_cfg_0, regs->timing_cfg[0]); + ddr_out32(&ddr->timing_cfg_1, regs->timing_cfg[1]); + ddr_out32(&ddr->timing_cfg_2, regs->timing_cfg[2]); + ddr_out32(&ddr->timing_cfg_3, regs->timing_cfg[3]); + ddr_out32(&ddr->timing_cfg_4, regs->timing_cfg[4]); + ddr_out32(&ddr->timing_cfg_5, regs->timing_cfg[5]); + ddr_out32(&ddr->timing_cfg_6, regs->timing_cfg[6]); + ddr_out32(&ddr->timing_cfg_7, regs->timing_cfg[7]); + ddr_out32(&ddr->timing_cfg_8, regs->timing_cfg[8]); + ddr_out32(&ddr->timing_cfg_9, regs->timing_cfg[9]); + ddr_out32(&ddr->zq_cntl, regs->zq_cntl); + for (i = 0U; i < 4U; i++) { + ddr_out32(&ddr->dq_map[i], regs->dq_map[i]); + } + ddr_out32(&ddr->sdram_cfg_3, regs->sdram_cfg[2]); + ddr_out32(&ddr->sdram_mode, regs->sdram_mode[0]); + ddr_out32(&ddr->sdram_mode_2, regs->sdram_mode[1]); + ddr_out32(&ddr->sdram_mode_3, regs->sdram_mode[2]); + ddr_out32(&ddr->sdram_mode_4, regs->sdram_mode[3]); + ddr_out32(&ddr->sdram_mode_5, regs->sdram_mode[4]); + ddr_out32(&ddr->sdram_mode_6, regs->sdram_mode[5]); + ddr_out32(&ddr->sdram_mode_7, regs->sdram_mode[6]); + ddr_out32(&ddr->sdram_mode_8, regs->sdram_mode[7]); + ddr_out32(&ddr->sdram_mode_9, regs->sdram_mode[8]); + ddr_out32(&ddr->sdram_mode_10, regs->sdram_mode[9]); + ddr_out32(&ddr->sdram_mode_11, regs->sdram_mode[10]); + ddr_out32(&ddr->sdram_mode_12, regs->sdram_mode[11]); + ddr_out32(&ddr->sdram_mode_13, regs->sdram_mode[12]); + ddr_out32(&ddr->sdram_mode_14, regs->sdram_mode[13]); + ddr_out32(&ddr->sdram_mode_15, regs->sdram_mode[14]); + ddr_out32(&ddr->sdram_mode_16, regs->sdram_mode[15]); + ddr_out32(&ddr->sdram_md_cntl, regs->md_cntl); +#ifdef ERRATA_DDR_A009663 + ddr_out32(&ddr->sdram_interval, + regs->interval & ~SDRAM_INTERVAL_BSTOPRE); +#else + ddr_out32(&ddr->sdram_interval, regs->interval); +#endif + ddr_out32(&ddr->sdram_data_init, regs->data_init); + if (regs->eor != 0) { + ddr_out32(&ddr->eor, regs->eor); + } + + ddr_out32(&ddr->wrlvl_cntl, regs->wrlvl_cntl[0]); +#ifndef NXP_DDR_EMU + /* + * Skip these two registers if running on emulator + * because emulator doesn't have skew between bytes. + */ + + if (regs->wrlvl_cntl[1] != 0) { + ddr_out32(&ddr->ddr_wrlvl_cntl_2, regs->wrlvl_cntl[1]); + } + if (regs->wrlvl_cntl[2] != 0) { + ddr_out32(&ddr->ddr_wrlvl_cntl_3, regs->wrlvl_cntl[2]); + } +#endif + + ddr_out32(&ddr->ddr_sr_cntr, regs->ddr_sr_cntr); + ddr_out32(&ddr->ddr_sdram_rcw_1, regs->sdram_rcw[0]); + ddr_out32(&ddr->ddr_sdram_rcw_2, regs->sdram_rcw[1]); + ddr_out32(&ddr->ddr_sdram_rcw_3, regs->sdram_rcw[2]); + ddr_out32(&ddr->ddr_sdram_rcw_4, regs->sdram_rcw[3]); + ddr_out32(&ddr->ddr_sdram_rcw_5, regs->sdram_rcw[4]); + ddr_out32(&ddr->ddr_sdram_rcw_6, regs->sdram_rcw[5]); + ddr_out32(&ddr->ddr_cdr2, regs->cdr[1]); + ddr_out32(&ddr->sdram_cfg_2, regs->sdram_cfg[1]); + ddr_out32(&ddr->init_addr, regs->init_addr); + ddr_out32(&ddr->init_ext_addr, regs->init_ext_addr); + +#ifdef ERRATA_DDR_A009803 + /* part 1 of 2 */ + if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) { + if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) { + ddr_out32(&ddr->ddr_sdram_rcw_2, + regs->sdram_rcw[1] & ~0xf0); + } + + ddr_out32(&ddr->err_disable, + regs->err_disable | DDR_ERR_DISABLE_APED); + } +#else + ddr_out32(&ddr->err_disable, regs->err_disable); +#endif + ddr_out32(&ddr->err_int_en, regs->err_int_en); + + /* For DDRC 5.05 only */ + if (get_ddrc_version(ddr) == 0x50500) { + ddr_out32(&ddr->tx_cfg[1], 0x1f1f1f1f); + ddr_out32(&ddr->debug[3], 0x124a02c0); + } + + for (i = 0U; i < 4U; i++) { + if (regs->tx_cfg[i] != 0) { + ddr_out32(&ddr->tx_cfg[i], regs->tx_cfg[i]); + } + } + for (i = 0U; i < 64U; i++) { + if (regs->debug[i] != 0) { +#ifdef ERRATA_DDR_A009942 + if (i == 28U) { + continue; + } +#endif + ddr_out32(&ddr->debug[i], regs->debug[i]); + } + } +#ifdef CONFIG_DDR_ADDR_DEC + if ((regs->dec[9] & 1) != 0U) { + for (i = 0U; i < 10U; i++) { + ddr_out32(&ddr->dec[i], regs->dec[i]); + } + if (mod_bnds != 0) { + debug("Disable address decoding\n"); + ddr_out32(&ddr->dec[9], 0); + } + } +#endif + +#ifdef ERRATA_DDR_A008511 + /* Part 1 of 2 */ + /* This erraum only applies to verion 5.2.1 */ + if (get_ddrc_version(ddr) == 0x50200) { + ERROR("Unsupported SoC.\n"); + } else if (get_ddrc_version(ddr) == 0x50201) { + ddr_out32(&ddr->debug[37], (U(1) << 31)); + ddr_out32(&ddr->ddr_cdr2, + regs->cdr[1] | DDR_CDR2_VREF_TRAIN_EN); + } else { + debug("Erratum A008511 doesn't apply.\n"); + } +#endif + +#ifdef ERRATA_DDR_A009942 + ddr_freq = clk / 1000000U; + tmp = ddr_in32(&ddr->debug[28]); + tmp &= U(0xff0fff00); + tmp |= ddr_freq <= 1333U ? U(0x0080006a) : + (ddr_freq <= 1600U ? U(0x0070006f) : + (ddr_freq <= 1867U ? U(0x00700076) : U(0x0060007b))); + if (regs->debug[28] != 0) { + tmp &= ~0xff; + tmp |= regs->debug[28] & 0xff; + } else { + WARN("Warning: Optimal CPO value not set.\n"); + } + ddr_out32(&ddr->debug[28], tmp); +#endif + +#ifdef ERRATA_DDR_A010165 + ddr_freq = clk / 1000000U; + if ((ddr_freq > 1900) && (ddr_freq < 2300)) { + tmp = ddr_in32(&ddr->debug[28]); + ddr_out32(&ddr->debug[28], tmp | 0x000a0000); + } +#endif + /* + * For RDIMMs, JEDEC spec requires clocks to be stable before reset is + * deasserted. Clocks start when any chip select is enabled and clock + * control register is set. Because all DDR components are connected to + * one reset signal, this needs to be done in two steps. Step 1 is to + * get the clocks started. Step 2 resumes after reset signal is + * deasserted. + */ + if (twopass == 1) { + udelay(200); + return 0; + } + + /* As per new sequence flow shall be write CSn_CONFIG registers needs to + * be set after all the other DDR controller registers are set, then poll + * for PHY_INIT_CMPLT = 1 , then wait at least 100us (micro seconds), + * then set the MEM_EN = 1 + */ + for (i = 0U; i < DDRC_NUM_CS; i++) { + if (mod_bnds != 0U && i == 0U) { + ddr_out32(&ddr->csn_cfg[i], + (regs->cs[i].config & ~CTLR_INTLV_MASK)); + } else { + ddr_out32(&ddr->csn_cfg[i], regs->cs[i].config); + } + } + +after_reset: + /* Set, but do not enable the memory */ + temp_sdram_cfg = regs->sdram_cfg[0]; + temp_sdram_cfg &= ~(SDRAM_CFG_MEM_EN); + ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg); + + if (get_ddrc_version(ddr) < U(0x50500)) { + /* + * 500 painful micro-seconds must elapse between + * the DDR clock setup and the DDR config enable. + * DDR2 need 200 us, and DDR3 need 500 us from spec, + * we choose the max, that is 500 us for all of case. + */ + udelay(500); + /* applied memory barrier */ + mb(); + isb(); + } else { + /* wait for PHY complete */ + timeout = 40; + while (((ddr_in32(&ddr->ddr_dsr2) & 0x4) != 0) && + (timeout > 0)) { + udelay(500); + timeout--; + } + if (timeout <= 0) { + printf("PHY handshake timeout, ddr_dsr2 = %x\n", + ddr_in32(&ddr->ddr_dsr2)); + } else { + debug("PHY handshake completed, timer remains %d\n", + timeout); + } + } + + temp_sdram_cfg = ddr_in32(&ddr->sdram_cfg); + /* Let the controller go */ + udelay(100); + ddr_out32(&ddr->sdram_cfg, temp_sdram_cfg | SDRAM_CFG_MEM_EN); + + /* applied memory barrier */ + mb(); + isb(); + + total_mem_per_ctrl = 0; + for (i = 0; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & 0x80000000) == 0) { + continue; + } + total_mem_per_ctrl += 1 << ( + ((regs->cs[i].config >> 14) & 0x3) + 2 + + ((regs->cs[i].config >> 8) & 0x7) + 12 + + ((regs->cs[i].config >> 4) & 0x3) + 0 + + ((regs->cs[i].config >> 0) & 0x7) + 8 + + ((regs->sdram_cfg[2] >> 4) & 0x3) + + 3 - ((regs->sdram_cfg[0] >> 19) & 0x3) - + 26); /* minus 26 (count of 64M) */ + } + total_mem_per_ctrl_adj = total_mem_per_ctrl; + /* + * total memory / bus width = transactions needed + * transactions needed / data rate = seconds + * to add plenty of buffer, double the time + * For example, 2GB on 666MT/s 64-bit bus takes about 402ms + * Let's wait for 800ms + */ + bus_width = 3 - ((ddr_in32(&ddr->sdram_cfg) & SDRAM_CFG_DBW_MASK) + >> SDRAM_CFG_DBW_SHIFT); + timeout = ((total_mem_per_ctrl_adj << (6 - bus_width)) * 100 / + (clk >> 20)) << 2; + total_mem_per_ctrl_adj >>= 4; /* shift down to gb size */ + if ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT) != 0) { + debug("total size %d GB\n", total_mem_per_ctrl_adj); + debug("Need to wait up to %d ms\n", timeout * 10); + + do { + mdelay(10); + } while (timeout-- > 0 && + ((ddr_in32(&ddr->sdram_cfg_2) & SDRAM_CFG2_D_INIT)) != 0); + + if (timeout <= 0) { + if (ddr_in32(&ddr->debug[1]) & 0x3d00) { + ERROR("Found training error(s): 0x%x\n", + ddr_in32(&ddr->debug[1])); + } + ERROR("Error: Waiting for D_INIT timeout.\n"); + return -EIO; + } + } + + if (mod_bnds != 0U) { + debug("Restore original bnds\n"); + for (i = 0U; i < DDRC_NUM_CS; i++) { + ddr_out32(&ddr->bnds[i].a, regs->cs[i].bnds); + } + ddr_out32(&ddr->csn_cfg[0], regs->cs[0].config); +#ifdef CONFIG_DDR_ADDR_DEC + if ((regs->dec[9] & U(0x1)) != 0U) { + debug("Restore address decoding\n"); + ddr_out32(&ddr->dec[9], regs->dec[9]); + } +#endif + } + +#ifdef ERRATA_DDR_A009803 + /* Part 2 of 2 */ + if ((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) { + timeout = 400; + do { + mdelay(1); + } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0)); + + if ((regs->sdram_cfg[0] & SDRAM_CFG_RD_EN) != 0) { + for (i = 0U; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0) { + continue; + } + set_wait_for_bits_clear(&ddr->sdram_md_cntl, + MD_CNTL_MD_EN | + MD_CNTL_CS_SEL(i) | + 0x070000ed, + MD_CNTL_MD_EN); + udelay(1); + } + } + + ddr_out32(&ddr->err_disable, + regs->err_disable & ~DDR_ERR_DISABLE_APED); + } +#endif + +#ifdef ERRATA_DDR_A009663 + ddr_out32(&ddr->sdram_interval, regs->interval); +#endif + +#ifdef ERRATA_DDR_A009942 + timeout = 400; + do { + mdelay(1); + } while (timeout-- > 0 && ((ddr_in32(&ddr->debug[1]) & 0x2) == 0)); + tmp = (regs->sdram_cfg[0] >> 19) & 0x3; + check = (tmp == DDR_DBUS_64) ? 4 : ((tmp == DDR_DBUS_32) ? 2 : 1); + for (i = 0; i < check; i++) { + tmp = ddr_in32(&ddr->debug[9 + i]); + debug("Reading debug[%d] as 0x%x\n", i + 9, tmp); + cpo_min = min(cpo_min, + min((tmp >> 24) & 0xff, (tmp >> 8) & 0xff)); + cpo_max = max(cpo_max, + max((tmp >> 24) & 0xff, (tmp >> 8) & 0xff)); + } + if ((regs->sdram_cfg[0] & SDRAM_CFG_ECC_EN) != 0) { + tmp = ddr_in32(&ddr->debug[13]); + cpo_min = min(cpo_min, (tmp >> 24) & 0xff); + cpo_max = max(cpo_max, (tmp >> 24) & 0xff); + } + debug("cpo_min 0x%x\n", cpo_min); + debug("cpo_max 0x%x\n", cpo_max); + tmp = ddr_in32(&ddr->debug[28]); + debug("debug[28] 0x%x\n", tmp); + if ((cpo_min + 0x3B) < (tmp & 0xff)) { + WARN("Warning: A009942 requires setting cpo_sample to 0x%x\n", + (cpo_min + cpo_max) / 2 + 0x27); + } else { + debug("Optimal cpo_sample 0x%x\n", + (cpo_min + cpo_max) / 2 + 0x27); + } +#endif + if (run_bist() != 0) { + if ((ddr_in32(&ddr->debug[1]) & + ((get_ddrc_version(ddr) == 0x50500) ? 0x3c00 : 0x3d00)) != 0) { + ERROR("Found training error(s): 0x%x\n", + ddr_in32(&ddr->debug[1])); + return -EIO; + } + INFO("Running built-in self test ...\n"); + /* give it 10x time to cover whole memory */ + timeout = ((total_mem_per_ctrl << (6 - bus_width)) * + 100 / (clk >> 20)) * 10; + INFO("\tWait up to %d ms\n", timeout * 10); + ret = bist(ddr, timeout); + } + dump_ddrc((void *)ddr); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c new file mode 100644 index 0000000..a82db6c --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c @@ -0,0 +1,399 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include +#include + +int read_spd(unsigned char chip, void *buf, int len) +{ + unsigned char dummy = 0U; + int ret; + + if (len < 256) { + ERROR("Invalid SPD length\n"); + return -EINVAL; + } + + i2c_write(SPD_SPA0_ADDRESS, 0, 1, &dummy, 1); + ret = i2c_read(chip, 0, 1, buf, 256); + if (ret == 0) { + i2c_write(SPD_SPA1_ADDRESS, 0, 1, &dummy, 1); + ret = i2c_read(chip, 0, 1, buf + 256, min(256, len - 256)); + } + if (ret != 0) { + zeromem(buf, len); + } + + return ret; +} + +int crc16(unsigned char *ptr, int count) +{ + int i; + int crc = 0; + + while (--count >= 0) { + crc = crc ^ (int)*ptr++ << 8; + for (i = 0; i < 8; ++i) { + if ((crc & 0x8000) != 0) { + crc = crc << 1 ^ 0x1021; + } else { + crc = crc << 1; + } + } + } + return crc & 0xffff; +} + +static int ddr4_spd_check(const struct ddr4_spd *spd) +{ + void *p = (void *)spd; + int csum16; + int len; + char crc_lsb; /* byte 126 */ + char crc_msb; /* byte 127 */ + + len = 126; + csum16 = crc16(p, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->crc[0] != crc_lsb || spd->crc[1] != crc_msb) { + ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n", + spd->crc[1], spd->crc[0], crc_msb, crc_lsb); + return -EINVAL; + } + + p = (void *)spd + 128; + len = 126; + csum16 = crc16(p, len); + + crc_lsb = (char) (csum16 & 0xff); + crc_msb = (char) (csum16 >> 8); + + if (spd->mod_section.uc[126] != crc_lsb || + spd->mod_section.uc[127] != crc_msb) { + ERROR("SPD CRC = 0x%x%x, computed CRC = 0x%x%x\n", + spd->mod_section.uc[127], spd->mod_section.uc[126], + crc_msb, crc_lsb); + return -EINVAL; + } + + return 0; +} + +static unsigned long long +compute_ranksize(const struct ddr4_spd *spd) +{ + unsigned long long bsize; + + int nbit_sdram_cap_bsize = 0; + int nbit_primary_bus_width = 0; + int nbit_sdram_width = 0; + int die_count = 0; + bool package_3ds; + + if ((spd->density_banks & 0xf) <= 7) { + nbit_sdram_cap_bsize = (spd->density_banks & 0xf) + 28; + } + if ((spd->bus_width & 0x7) < 4) { + nbit_primary_bus_width = (spd->bus_width & 0x7) + 3; + } + if ((spd->organization & 0x7) < 4) { + nbit_sdram_width = (spd->organization & 0x7) + 2; + } + package_3ds = (spd->package_type & 0x3) == 0x2; + if (package_3ds) { + die_count = (spd->package_type >> 4) & 0x7; + } + + bsize = 1ULL << (nbit_sdram_cap_bsize - 3 + + nbit_primary_bus_width - nbit_sdram_width + + die_count); + + return bsize; +} + +int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm) +{ + int ret; + int i; + static const unsigned char udimm_rc_e_dq[18] = { + 0x0c, 0x2c, 0x15, 0x35, 0x15, 0x35, 0x0b, 0x2c, 0x15, + 0x35, 0x0b, 0x35, 0x0b, 0x2c, 0x0b, 0x35, 0x15, 0x36 + }; + int spd_error = 0; + unsigned char *ptr; + unsigned char val; + + if (spd->mem_type != SPD_MEMTYPE_DDR4) { + ERROR("Not a DDR4 DIMM.\n"); + return -EINVAL; + } + + ret = ddr4_spd_check(spd); + if (ret != 0) { + ERROR("DIMM SPD checksum mismatch\n"); + return -EINVAL; + } + + /* + * The part name in ASCII in the SPD EEPROM is not null terminated. + * Guarantee null termination here by presetting all bytes to 0 + * and copying the part name in ASCII from the SPD onto it + */ + if ((spd->info_size_crc & 0xF) > 2) { + memcpy(pdimm->mpart, spd->mpart, sizeof(pdimm->mpart) - 1); + } + + /* DIMM organization parameters */ + pdimm->n_ranks = ((spd->organization >> 3) & 0x7) + 1; + debug("n_ranks %d\n", pdimm->n_ranks); + pdimm->rank_density = compute_ranksize(spd); + if (pdimm->rank_density == 0) { + return -EINVAL; + } + + debug("rank_density 0x%llx\n", pdimm->rank_density); + pdimm->capacity = pdimm->n_ranks * pdimm->rank_density; + debug("capacity 0x%llx\n", pdimm->capacity); + pdimm->die_density = spd->density_banks & 0xf; + debug("die density 0x%x\n", pdimm->die_density); + pdimm->primary_sdram_width = 1 << (3 + (spd->bus_width & 0x7)); + debug("primary_sdram_width %d\n", pdimm->primary_sdram_width); + if (((spd->bus_width >> 3) & 0x3) != 0) { + pdimm->ec_sdram_width = 8; + } else { + pdimm->ec_sdram_width = 0; + } + debug("ec_sdram_width %d\n", pdimm->ec_sdram_width); + pdimm->device_width = 1 << ((spd->organization & 0x7) + 2); + debug("device_width %d\n", pdimm->device_width); + pdimm->package_3ds = (spd->package_type & 0x3) == 0x2 ? + (spd->package_type >> 4) & 0x7 : 0; + debug("package_3ds %d\n", pdimm->package_3ds); + + switch (spd->module_type & DDR4_SPD_MODULETYPE_MASK) { + case DDR4_SPD_RDIMM: + case DDR4_SPD_MINI_RDIMM: + case DDR4_SPD_72B_SO_RDIMM: + pdimm->rdimm = 1; + pdimm->rc = spd->mod_section.registered.ref_raw_card & 0x9f; + if ((spd->mod_section.registered.reg_map & 0x1) != 0) { + pdimm->mirrored_dimm = 1; + } + val = spd->mod_section.registered.ca_stren; + pdimm->rcw[3] = val >> 4; + pdimm->rcw[4] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); + val = spd->mod_section.registered.clk_stren; + pdimm->rcw[5] = ((val & 0x3) << 2) | ((val & 0xc) >> 2); + pdimm->rcw[6] = 0xf; + /* A17 used for 16Gb+, C[2:0] used for 3DS */ + pdimm->rcw[8] = pdimm->die_density >= 0x6 ? 0x0 : 0x8 | + (pdimm->package_3ds > 0x3 ? 0x0 : + (pdimm->package_3ds > 0x1 ? 0x1 : + (pdimm->package_3ds > 0 ? 0x2 : 0x3))); + if (pdimm->package_3ds != 0 || pdimm->n_ranks != 4) { + pdimm->rcw[13] = 0x4; + } else { + pdimm->rcw[13] = 0x5; + } + pdimm->rcw[13] |= pdimm->mirrored_dimm ? 0x8 : 0; + break; + + case DDR4_SPD_UDIMM: + case DDR4_SPD_SO_DIMM: + case DDR4_SPD_MINI_UDIMM: + case DDR4_SPD_72B_SO_UDIMM: + case DDR4_SPD_16B_SO_DIMM: + case DDR4_SPD_32B_SO_DIMM: + pdimm->rc = spd->mod_section.unbuffered.ref_raw_card & 0x9f; + if ((spd->mod_section.unbuffered.addr_mapping & 0x1) != 0) { + pdimm->mirrored_dimm = 1; + } + if ((spd->mod_section.unbuffered.mod_height & 0xe0) == 0 && + (spd->mod_section.unbuffered.ref_raw_card == 0x04)) { + /* Fix SPD error found on DIMMs with raw card E0 */ + for (i = 0; i < 18; i++) { + if (spd->mapping[i] == udimm_rc_e_dq[i]) { + continue; + } + spd_error = 1; + ptr = (unsigned char *)&spd->mapping[i]; + *ptr = udimm_rc_e_dq[i]; + } + if (spd_error != 0) { + INFO("SPD DQ mapping error fixed\n"); + } + } + break; + + default: + ERROR("Unknown module_type 0x%x\n", spd->module_type); + return -EINVAL; + } + debug("rdimm %d\n", pdimm->rdimm); + debug("mirrored_dimm %d\n", pdimm->mirrored_dimm); + debug("rc 0x%x\n", pdimm->rc); + + /* SDRAM device parameters */ + pdimm->n_row_addr = ((spd->addressing >> 3) & 0x7) + 12; + debug("n_row_addr %d\n", pdimm->n_row_addr); + pdimm->n_col_addr = (spd->addressing & 0x7) + 9; + debug("n_col_addr %d\n", pdimm->n_col_addr); + pdimm->bank_addr_bits = (spd->density_banks >> 4) & 0x3; + debug("bank_addr_bits %d\n", pdimm->bank_addr_bits); + pdimm->bank_group_bits = (spd->density_banks >> 6) & 0x3; + debug("bank_group_bits %d\n", pdimm->bank_group_bits); + + if (pdimm->ec_sdram_width != 0) { + pdimm->edc_config = 0x02; + } else { + pdimm->edc_config = 0x00; + } + debug("edc_config %d\n", pdimm->edc_config); + + /* DDR4 spec has BL8 -bit3, BC4 -bit2 */ + pdimm->burst_lengths_bitmask = 0x0c; + debug("burst_lengths_bitmask 0x%x\n", pdimm->burst_lengths_bitmask); + + /* MTB - medium timebase + * The MTB in the SPD spec is 125ps, + * + * FTB - fine timebase + * use 1/10th of ps as our unit to avoid floating point + * eg, 10 for 1ps, 25 for 2.5ps, 50 for 5ps + */ + if ((spd->timebases & 0xf) == 0x0) { + pdimm->mtb_ps = 125; + pdimm->ftb_10th_ps = 10; + + } else { + ERROR("Unknown Timebases\n"); + return -EINVAL; + } + + /* sdram minimum cycle time */ + pdimm->tckmin_x_ps = spd_to_ps(spd->tck_min, spd->fine_tck_min); + debug("tckmin_x_ps %d\n", pdimm->tckmin_x_ps); + + /* sdram max cycle time */ + pdimm->tckmax_ps = spd_to_ps(spd->tck_max, spd->fine_tck_max); + debug("tckmax_ps %d\n", pdimm->tckmax_ps); + + /* + * CAS latency supported + * bit0 - CL7 + * bit4 - CL11 + * bit8 - CL15 + * bit12- CL19 + * bit16- CL23 + */ + pdimm->caslat_x = (spd->caslat_b1 << 7) | + (spd->caslat_b2 << 15) | + (spd->caslat_b3 << 23); + debug("caslat_x 0x%x\n", pdimm->caslat_x); + + if (spd->caslat_b4 != 0) { + WARN("Unhandled caslat_b4 value\n"); + } + + /* + * min CAS latency time + */ + pdimm->taa_ps = spd_to_ps(spd->taa_min, spd->fine_taa_min); + debug("taa_ps %d\n", pdimm->taa_ps); + + /* + * min RAS to CAS delay time + */ + pdimm->trcd_ps = spd_to_ps(spd->trcd_min, spd->fine_trcd_min); + debug("trcd_ps %d\n", pdimm->trcd_ps); + + /* + * Min Row Precharge Delay Time + */ + pdimm->trp_ps = spd_to_ps(spd->trp_min, spd->fine_trp_min); + debug("trp_ps %d\n", pdimm->trp_ps); + + /* min active to precharge delay time */ + pdimm->tras_ps = (((spd->tras_trc_ext & 0xf) << 8) + + spd->tras_min_lsb) * pdimm->mtb_ps; + debug("tras_ps %d\n", pdimm->tras_ps); + + /* min active to actice/refresh delay time */ + pdimm->trc_ps = spd_to_ps((((spd->tras_trc_ext & 0xf0) << 4) + + spd->trc_min_lsb), spd->fine_trc_min); + debug("trc_ps %d\n", pdimm->trc_ps); + /* Min Refresh Recovery Delay Time */ + pdimm->trfc1_ps = ((spd->trfc1_min_msb << 8) | (spd->trfc1_min_lsb)) * + pdimm->mtb_ps; + debug("trfc1_ps %d\n", pdimm->trfc1_ps); + pdimm->trfc2_ps = ((spd->trfc2_min_msb << 8) | (spd->trfc2_min_lsb)) * + pdimm->mtb_ps; + debug("trfc2_ps %d\n", pdimm->trfc2_ps); + pdimm->trfc4_ps = ((spd->trfc4_min_msb << 8) | (spd->trfc4_min_lsb)) * + pdimm->mtb_ps; + debug("trfc4_ps %d\n", pdimm->trfc4_ps); + /* min four active window delay time */ + pdimm->tfaw_ps = (((spd->tfaw_msb & 0xf) << 8) | spd->tfaw_min) * + pdimm->mtb_ps; + debug("tfaw_ps %d\n", pdimm->tfaw_ps); + + /* min row active to row active delay time, different bank group */ + pdimm->trrds_ps = spd_to_ps(spd->trrds_min, spd->fine_trrds_min); + debug("trrds_ps %d\n", pdimm->trrds_ps); + /* min row active to row active delay time, same bank group */ + pdimm->trrdl_ps = spd_to_ps(spd->trrdl_min, spd->fine_trrdl_min); + debug("trrdl_ps %d\n", pdimm->trrdl_ps); + /* min CAS to CAS Delay Time (tCCD_Lmin), same bank group */ + pdimm->tccdl_ps = spd_to_ps(spd->tccdl_min, spd->fine_tccdl_min); + debug("tccdl_ps %d\n", pdimm->tccdl_ps); + if (pdimm->package_3ds != 0) { + if (pdimm->die_density > 5) { + debug("Unsupported logical rank density 0x%x\n", + pdimm->die_density); + return -EINVAL; + } + pdimm->trfc_slr_ps = (pdimm->die_density <= 4) ? + 260000 : 350000; + } + debug("trfc_slr_ps %d\n", pdimm->trfc_slr_ps); + + /* 15ns for all speed bins */ + pdimm->twr_ps = 15000; + debug("twr_ps %d\n", pdimm->twr_ps); + + /* + * Average periodic refresh interval + * tREFI = 7.8 us at normal temperature range + */ + pdimm->refresh_rate_ps = 7800000; + debug("refresh_rate_ps %d\n", pdimm->refresh_rate_ps); + + for (i = 0; i < 18; i++) { + pdimm->dq_mapping[i] = spd->mapping[i]; + debug("dq_mapping 0x%x\n", pdimm->dq_mapping[i]); + } + + pdimm->dq_mapping_ors = ((spd->mapping[0] >> 6) & 0x3) == 0 ? 1 : 0; + debug("dq_mapping_ors %d\n", pdimm->dq_mapping_ors); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c new file mode 100644 index 0000000..cedd7ca --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c @@ -0,0 +1,1394 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +static inline unsigned int cal_cwl(const unsigned long clk) +{ + const unsigned int mclk_ps = get_memory_clk_ps(clk); + + return mclk_ps >= 1250U ? 9U : + (mclk_ps >= 1070U ? 10U : + (mclk_ps >= 935U ? 11U : + (mclk_ps >= 833U ? 12U : + (mclk_ps >= 750U ? 14U : + (mclk_ps >= 625U ? 16U : 18U))))); +} + +static void cal_csn_config(int i, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + unsigned int intlv_en = 0U; + unsigned int intlv_ctl = 0U; + const unsigned int cs_n_en = 1U; + const unsigned int ap_n_en = popts->cs_odt[i].auto_precharge; + const unsigned int odt_rd_cfg = popts->cs_odt[i].odt_rd_cfg; + const unsigned int odt_wr_cfg = popts->cs_odt[i].odt_wr_cfg; + const unsigned int ba_bits_cs_n = pdimm->bank_addr_bits; + const unsigned int row_bits_cs_n = pdimm->n_row_addr - 12U; + const unsigned int col_bits_cs_n = pdimm->n_col_addr - 8U; + const unsigned int bg_bits_cs_n = pdimm->bank_group_bits; + + if (i == 0) { + /* These fields only available in CS0_CONFIG */ + if (popts->ctlr_intlv != 0) { + switch (popts->ctlr_intlv_mode) { + case DDR_256B_INTLV: + intlv_en = popts->ctlr_intlv; + intlv_ctl = popts->ctlr_intlv_mode; + break; + default: + break; + } + } + } + regs->cs[i].config = ((cs_n_en & 0x1) << 31) | + ((intlv_en & 0x3) << 29) | + ((intlv_ctl & 0xf) << 24) | + ((ap_n_en & 0x1) << 23) | + ((odt_rd_cfg & 0x7) << 20) | + ((odt_wr_cfg & 0x7) << 16) | + ((ba_bits_cs_n & 0x3) << 14) | + ((row_bits_cs_n & 0x7) << 8) | + ((bg_bits_cs_n & 0x3) << 4) | + ((col_bits_cs_n & 0x7) << 0); + debug("cs%d\n", i); + debug(" _config = 0x%x\n", regs->cs[i].config); +} + +static inline int avoid_odt_overlap(const struct ddr_conf *conf, + const struct dimm_params *pdimm) +{ + if ((conf->cs_in_use == 0xf) != 0) { + return 2; + } + +#if DDRC_NUM_DIMM >= 2 + if (conf->dimm_in_use[0] != 0 && conf->dimm_in_use[1] != 0) { + return 1; + } +#endif + return 0; +} + +/* Requires rcw2 set first */ +static void cal_timing_cfg(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm, + const struct ddr_conf *conf, + unsigned int cas_latency, + unsigned int additive_latency) +{ + const unsigned int mclk_ps = get_memory_clk_ps(clk); + /* tXP=max(4nCK, 6ns) */ + const int txp = max((int)mclk_ps * 4, 6000); + /* DDR4 supports 10, 12, 14, 16, 18, 20, 24 */ + static const int wrrec_table[] = { + 10, 10, 10, 10, 10, + 10, 10, 10, 10, 10, + 12, 12, 14, 14, 16, + 16, 18, 18, 20, 20, + 24, 24, 24, 24, + }; + int trwt_mclk = (clk / 1000000 > 1900) ? 3 : 2; + int twrt_mclk; + int trrt_mclk; + int twwt_mclk; + const int act_pd_exit_mclk = picos_to_mclk(clk, txp); + const int pre_pd_exit_mclk = act_pd_exit_mclk; + const int taxpd_mclk = 0; + /* + * MRS_CYC = max(tMRD, tMOD) + * tMRD = 8nCK, tMOD = max(24nCK, 15ns) + */ + const int tmrd_mclk = max(24U, picos_to_mclk(clk, 15000)); + const int pretoact_mclk = picos_to_mclk(clk, pdimm->trp_ps); + const int acttopre_mclk = picos_to_mclk(clk, pdimm->tras_ps); + const int acttorw_mclk = picos_to_mclk(clk, pdimm->trcd_ps); + const int caslat_ctrl = (cas_latency - 1) << 1; + const int trfc1_min = pdimm->die_density >= 0x3 ? 16000 : + (pdimm->die_density == 0x4 ? 26000 : + (pdimm->die_density == 0x5 ? 35000 : + 55000)); + const int refrec_ctrl = picos_to_mclk(clk, + pdimm->trfc1_ps) - 8; + int wrrec_mclk = picos_to_mclk(clk, pdimm->twr_ps); + const int acttoact_mclk = max(picos_to_mclk(clk, + pdimm->trrds_ps), + 4U); + int wrtord_mclk = max(2U, picos_to_mclk(clk, 2500)); + const unsigned int cpo = 0U; + const int wr_lat = cal_cwl(clk); + int rd_to_pre = picos_to_mclk(clk, 7500); + const int wr_data_delay = popts->wr_data_delay; + const int cke_pls = max(3U, picos_to_mclk(clk, 5000)); +#ifdef ERRATA_DDR_A050450 + const unsigned short four_act = ((popts->twot_en == 0) && + (popts->threet_en == 0) && + (popts->tfaw_ps % 2 == 0)) ? + (picos_to_mclk(clk, popts->tfaw_ps) + 1) : + picos_to_mclk(clk, popts->tfaw_ps); +#else + const unsigned short four_act = picos_to_mclk(clk, + popts->tfaw_ps); +#endif + const unsigned int cntl_adj = 0U; + const unsigned int ext_pretoact = picos_to_mclk(clk, + pdimm->trp_ps) >> 4U; + const unsigned int ext_acttopre = picos_to_mclk(clk, + pdimm->tras_ps) >> 4U; + const unsigned int ext_acttorw = picos_to_mclk(clk, + pdimm->trcd_ps) >> 4U; + const unsigned int ext_caslat = (2U * cas_latency - 1U) >> 4U; + const unsigned int ext_add_lat = additive_latency >> 4U; + const unsigned int ext_refrec = (picos_to_mclk(clk, + pdimm->trfc1_ps) - 8U) >> 4U; + const unsigned int ext_wrrec = (picos_to_mclk(clk, pdimm->twr_ps) + + (popts->otf_burst_chop_en ? 2U : 0U)) >> 4U; + const unsigned int rwt_same_cs = 0U; + const unsigned int wrt_same_cs = 0U; + const unsigned int rrt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; + const unsigned int wwt_same_cs = popts->burst_length == DDR_BL8 ? 0U : 2U; + const unsigned int dll_lock = 2U; + unsigned int rodt_on = 0U; + const unsigned int rodt_off = 4U; + const unsigned int wodt_on = 1U; + const unsigned int wodt_off = 4U; + const unsigned int hs_caslat = 0U; + const unsigned int hs_wrlat = 0U; + const unsigned int hs_wrrec = 0U; + const unsigned int hs_clkadj = 0U; + const unsigned int hs_wrlvl_start = 0U; + const unsigned int txpr = max(5U, + picos_to_mclk(clk, + pdimm->trfc1_ps + 10000U)); + const unsigned int tcksre = max(5U, picos_to_mclk(clk, 10000U)); + const unsigned int tcksrx = max(5U, picos_to_mclk(clk, 10000U)); + const unsigned int cs_to_cmd = 0U; + const unsigned int cke_rst = txpr <= 200U ? 0U : + (txpr <= 256U ? 1U : + (txpr <= 512U ? 2U : 3U)); + const unsigned int cksre = tcksre <= 19U ? tcksre - 5U : 15U; + const unsigned int cksrx = tcksrx <= 19U ? tcksrx - 5U : 15U; + unsigned int par_lat = 0U; + const int tccdl = max(5U, picos_to_mclk(clk, pdimm->tccdl_ps)); + int rwt_bg = cas_latency + 2 + 4 - wr_lat; + int wrt_bg = wr_lat + 4 + 1 - cas_latency; + const int rrt_bg = popts->burst_length == DDR_BL8 ? + tccdl - 4 : tccdl - 2; + const int wwt_bg = popts->burst_length == DDR_BL8 ? + tccdl - 4 : tccdl - 2; + const unsigned int acttoact_bg = picos_to_mclk(clk, pdimm->trrdl_ps); + const unsigned int wrtord_bg = max(4U, picos_to_mclk(clk, 7500)) + + (popts->otf_burst_chop_en ? 2 : 0); + const unsigned int pre_all_rec = 0; + const unsigned int refrec_cid_mclk = pdimm->package_3ds ? + picos_to_mclk(clk, pdimm->trfc_slr_ps) : 0; + const unsigned int acttoact_cid_mclk = pdimm->package_3ds ? 4U : 0; + + + /* for two dual-rank DIMMs to avoid ODT overlap */ + if (avoid_odt_overlap(conf, pdimm) == 2) { + twrt_mclk = 2; + twwt_mclk = 2; + trrt_mclk = 2; + } else { + twrt_mclk = 1; + twwt_mclk = 1; + trrt_mclk = 0; + } + + if (popts->trwt_override != 0) { + trwt_mclk = popts->trwt; + if (popts->twrt != 0) { + twrt_mclk = popts->twrt; + } + if (popts->trrt != 0) { + trrt_mclk = popts->trrt; + } + if (popts->twwt != 0) { + twwt_mclk = popts->twwt; + } + } + regs->timing_cfg[0] = (((trwt_mclk & 0x3) << 30) | + ((twrt_mclk & 0x3) << 28) | + ((trrt_mclk & 0x3) << 26) | + ((twwt_mclk & 0x3) << 24) | + ((act_pd_exit_mclk & 0xf) << 20) | + ((pre_pd_exit_mclk & 0xF) << 16) | + ((taxpd_mclk & 0xf) << 8) | + ((tmrd_mclk & 0x1f) << 0)); + debug("timing_cfg[0] = 0x%x\n", regs->timing_cfg[0]); + + if ((wrrec_mclk < 1) || (wrrec_mclk > 24)) { + ERROR("WRREC doesn't support clock %d\n", wrrec_mclk); + } else { + wrrec_mclk = wrrec_table[wrrec_mclk - 1]; + } + + if (popts->otf_burst_chop_en != 0) { + wrrec_mclk += 2; + wrtord_mclk += 2; + } + + if (pdimm->trfc1_ps < trfc1_min) { + ERROR("trfc1_ps (%d) < %d\n", pdimm->trfc1_ps, trfc1_min); + } + + regs->timing_cfg[1] = (((pretoact_mclk & 0x0F) << 28) | + ((acttopre_mclk & 0x0F) << 24) | + ((acttorw_mclk & 0xF) << 20) | + ((caslat_ctrl & 0xF) << 16) | + ((refrec_ctrl & 0xF) << 12) | + ((wrrec_mclk & 0x0F) << 8) | + ((acttoact_mclk & 0x0F) << 4) | + ((wrtord_mclk & 0x0F) << 0)); + debug("timing_cfg[1] = 0x%x\n", regs->timing_cfg[1]); + + if (rd_to_pre < 4) { + rd_to_pre = 4; + } + if (popts->otf_burst_chop_en) { + rd_to_pre += 2; + } + + regs->timing_cfg[2] = (((additive_latency & 0xf) << 28) | + ((cpo & 0x1f) << 23) | + ((wr_lat & 0xf) << 19) | + (((wr_lat & 0x10) >> 4) << 18) | + ((rd_to_pre & 0xf) << 13) | + ((wr_data_delay & 0xf) << 9) | + ((cke_pls & 0x7) << 6) | + ((four_act & 0x3f) << 0)); + debug("timing_cfg[2] = 0x%x\n", regs->timing_cfg[2]); + + regs->timing_cfg[3] = (((ext_pretoact & 0x1) << 28) | + ((ext_acttopre & 0x3) << 24) | + ((ext_acttorw & 0x1) << 22) | + ((ext_refrec & 0x3F) << 16) | + ((ext_caslat & 0x3) << 12) | + ((ext_add_lat & 0x1) << 10) | + ((ext_wrrec & 0x1) << 8) | + ((cntl_adj & 0x7) << 0)); + debug("timing_cfg[3] = 0x%x\n", regs->timing_cfg[3]); + + regs->timing_cfg[4] = (((rwt_same_cs & 0xf) << 28) | + ((wrt_same_cs & 0xf) << 24) | + ((rrt_same_cs & 0xf) << 20) | + ((wwt_same_cs & 0xf) << 16) | + ((trwt_mclk & 0xc) << 12) | + ((twrt_mclk & 0x4) << 10) | + ((trrt_mclk & 0x4) << 8) | + ((twwt_mclk & 0x4) << 6) | + (dll_lock & 0x3)); + debug("timing_cfg[4] = 0x%x\n", regs->timing_cfg[4]); + + /* rodt_on = timing_cfg_1[caslat] - timing_cfg_2[wrlat] + 1 */ + if (cas_latency >= wr_lat) { + rodt_on = cas_latency - wr_lat + 1; + } + + regs->timing_cfg[5] = (((rodt_on & 0x1f) << 24) | + ((rodt_off & 0x7) << 20) | + ((wodt_on & 0x1f) << 12) | + (wodt_off & 0x7) << 8); + debug("timing_cfg[5] = 0x%x\n", regs->timing_cfg[5]); + + regs->timing_cfg[6] = (((hs_caslat & 0x1f) << 24) | + ((hs_wrlat & 0x1f) << 19) | + ((hs_wrrec & 0x1f) << 12) | + ((hs_clkadj & 0x1f) << 6) | + ((hs_wrlvl_start & 0x1f) << 0)); + debug("timing_cfg[6] = 0x%x\n", regs->timing_cfg[6]); + + if (popts->ap_en != 0) { + par_lat = (regs->sdram_rcw[1] & 0xf) + 1; + debug("PAR_LAT = 0x%x\n", par_lat); + } + + regs->timing_cfg[7] = (((cke_rst & 0x3) << 28) | + ((cksre & 0xf) << 24) | + ((cksrx & 0xf) << 20) | + ((par_lat & 0xf) << 16) | + ((cs_to_cmd & 0xf) << 4)); + debug("timing_cfg[7] = 0x%x\n", regs->timing_cfg[7]); + + if (rwt_bg < tccdl) { + rwt_bg = tccdl - rwt_bg; + } else { + rwt_bg = 0; + } + if (wrt_bg < tccdl) { + wrt_bg = tccdl - wrt_bg; + } else { + wrt_bg = 0; + } + regs->timing_cfg[8] = (((rwt_bg & 0xf) << 28) | + ((wrt_bg & 0xf) << 24) | + ((rrt_bg & 0xf) << 20) | + ((wwt_bg & 0xf) << 16) | + ((acttoact_bg & 0xf) << 12) | + ((wrtord_bg & 0xf) << 8) | + ((pre_all_rec & 0x1f) << 0)); + debug("timing_cfg[8] = 0x%x\n", regs->timing_cfg[8]); + + regs->timing_cfg[9] = (refrec_cid_mclk & 0x3ff) << 16 | + (acttoact_cid_mclk & 0xf) << 8; + debug("timing_cfg[9] = 0x%x\n", regs->timing_cfg[9]); +} + +static void cal_ddr_sdram_rcw(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + const unsigned int freq = clk / 1000000U; + unsigned int rc0a, rc0f; + + if (pdimm->rdimm == 0) { + return; + } + + rc0a = freq > 3200U ? 7U : + (freq > 2933U ? 6U : + (freq > 2666U ? 5U : + (freq > 2400U ? 4U : + (freq > 2133U ? 3U : + (freq > 1866U ? 2U : + (freq > 1600U ? 1U : 0U)))))); + rc0f = freq > 3200U ? 3U : + (freq > 2400U ? 2U : + (freq > 2133U ? 1U : 0U)); + rc0f = (regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) ? rc0f : 4; + regs->sdram_rcw[0] = + pdimm->rcw[0] << 28 | + pdimm->rcw[1] << 24 | + pdimm->rcw[2] << 20 | + pdimm->rcw[3] << 16 | + pdimm->rcw[4] << 12 | + pdimm->rcw[5] << 8 | + pdimm->rcw[6] << 4 | + pdimm->rcw[7]; + regs->sdram_rcw[1] = + pdimm->rcw[8] << 28 | + pdimm->rcw[9] << 24 | + rc0a << 20 | + pdimm->rcw[11] << 16 | + pdimm->rcw[12] << 12 | + pdimm->rcw[13] << 8 | + pdimm->rcw[14] << 4 | + rc0f; + regs->sdram_rcw[2] = + ((freq - 1260 + 19) / 20) << 8; + + debug("sdram_rcw[0] = 0x%x\n", regs->sdram_rcw[0]); + debug("sdram_rcw[1] = 0x%x\n", regs->sdram_rcw[1]); + debug("sdram_rcw[2] = 0x%x\n", regs->sdram_rcw[2]); +} + +static void cal_ddr_sdram_cfg(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm, + const unsigned int ip_rev) +{ + const unsigned int mem_en = 1U; + const unsigned int sren = popts->self_refresh_in_sleep; + const unsigned int ecc_en = popts->ecc_mode; + const unsigned int rd_en = (pdimm->rdimm != 0U) ? 1U : 0U; + const unsigned int dyn_pwr = popts->dynamic_power; + const unsigned int dbw = popts->data_bus_used; + const unsigned int eight_be = (dbw == 1U || + popts->burst_length == DDR_BL8) ? 1U : 0U; + const unsigned int ncap = 0U; + const unsigned int threet_en = popts->threet_en; + const unsigned int twot_en = pdimm->rdimm ? + 0U : popts->twot_en; + const unsigned int ba_intlv = popts->ba_intlv; + const unsigned int x32_en = 0U; + const unsigned int pchb8 = 0U; + const unsigned int hse = popts->half_strength_drive_en; + const unsigned int acc_ecc_en = (dbw != 0U && ecc_en == 1U) ? 1U : 0U; + const unsigned int mem_halt = 0U; +#ifdef PHY_GEN2 + const unsigned int bi = 1U; +#else + const unsigned int bi = 0U; +#endif + const unsigned int sdram_type = SDRAM_TYPE_DDR4; + unsigned int odt_cfg = 0U; + const unsigned int frc_sr = 0U; + const unsigned int sr_ie = popts->self_refresh_irq_en; + const unsigned int num_pr = pdimm->package_3ds + 1U; + const unsigned int slow = (clk < 1249000000U) ? 1U : 0U; + const unsigned int x4_en = popts->x4_en; + const unsigned int obc_cfg = popts->otf_burst_chop_en; + const unsigned int ap_en = ip_rev == 0x50500U ? 0U : popts->ap_en; + const unsigned int d_init = popts->ctlr_init_ecc; + const unsigned int rcw_en = popts->rdimm; + const unsigned int md_en = popts->mirrored_dimm; + const unsigned int qd_en = popts->quad_rank_present; + const unsigned int unq_mrs_en = ip_rev < 0x50500U ? 1U : 0U; + const unsigned int rd_pre = popts->quad_rank_present; + int i; + + regs->sdram_cfg[0] = ((mem_en & 0x1) << 31) | + ((sren & 0x1) << 30) | + ((ecc_en & 0x1) << 29) | + ((rd_en & 0x1) << 28) | + ((sdram_type & 0x7) << 24) | + ((dyn_pwr & 0x1) << 21) | + ((dbw & 0x3) << 19) | + ((eight_be & 0x1) << 18) | + ((ncap & 0x1) << 17) | + ((threet_en & 0x1) << 16) | + ((twot_en & 0x1) << 15) | + ((ba_intlv & 0x7F) << 8) | + ((x32_en & 0x1) << 5) | + ((pchb8 & 0x1) << 4) | + ((hse & 0x1) << 3) | + ((acc_ecc_en & 0x1) << 2) | + ((mem_halt & 0x1) << 1) | + ((bi & 0x1) << 0); + debug("sdram_cfg[0] = 0x%x\n", regs->sdram_cfg[0]); + + for (i = 0; i < DDRC_NUM_CS; i++) { + if (popts->cs_odt[i].odt_rd_cfg != 0 || + popts->cs_odt[i].odt_wr_cfg != 0) { + odt_cfg = SDRAM_CFG2_ODT_ONLY_READ; + break; + } + } + + regs->sdram_cfg[1] = (0 + | ((frc_sr & 0x1) << 31) + | ((sr_ie & 0x1) << 30) + | ((odt_cfg & 0x3) << 21) + | ((num_pr & 0xf) << 12) + | ((slow & 1) << 11) + | (x4_en << 10) + | (qd_en << 9) + | (unq_mrs_en << 8) + | ((obc_cfg & 0x1) << 6) + | ((ap_en & 0x1) << 5) + | ((d_init & 0x1) << 4) + | ((rcw_en & 0x1) << 2) + | ((md_en & 0x1) << 0) + ); + debug("sdram_cfg[1] = 0x%x\n", regs->sdram_cfg[1]); + + regs->sdram_cfg[2] = (rd_pre & 0x1) << 16 | + (popts->rdimm ? 1 : 0); + if (pdimm->package_3ds != 0) { + if (((pdimm->package_3ds + 1) & 0x1) != 0) { + WARN("Unsupported 3DS DIMM\n"); + } else { + regs->sdram_cfg[2] |= ((pdimm->package_3ds + 1) >> 1) + << 4; + } + } + debug("sdram_cfg[2] = 0x%x\n", regs->sdram_cfg[2]); +} + + +static void cal_ddr_sdram_interval(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct dimm_params *pdimm) +{ + const unsigned int refint = picos_to_mclk(clk, pdimm->refresh_rate_ps); + const unsigned int bstopre = popts->bstopre; + + regs->interval = ((refint & 0xFFFF) << 16) | + ((bstopre & 0x3FFF) << 0); + debug("interval = 0x%x\n", regs->interval); +} + +/* Require cs and cfg first */ +static void cal_ddr_sdram_mode(const unsigned long clk, + struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + const struct dimm_params *pdimm, + unsigned int cas_latency, + unsigned int additive_latency, + const unsigned int ip_rev) +{ + int i; + unsigned short esdmode; /* Extended SDRAM mode */ + unsigned short sdmode; /* SDRAM mode */ + + /* Mode Register - MR1 */ + const unsigned int qoff = 0; + const unsigned int tdqs_en = 0; + unsigned int rtt; + const unsigned int wrlvl_en = 0; + unsigned int al = 0; + unsigned int dic = 0; + const unsigned int dll_en = 1; + + /* Mode Register - MR0 */ + unsigned int wr = 0; + const unsigned int dll_rst = 0; + const unsigned int mode = 0; + unsigned int caslat = 4;/* CAS# latency, default set as 6 cycles */ + /* BT: Burst Type (0=Nibble Sequential, 1=Interleaved) */ + const unsigned int bt = 0; + const unsigned int bl = popts->burst_length == DDR_BL8 ? 0 : + (popts->burst_length == DDR_BC4 ? 2 : 1); + + const unsigned int wr_mclk = picos_to_mclk(clk, pdimm->twr_ps); + /* DDR4 support WR 10, 12, 14, 16, 18, 20, 24 */ + static const int wr_table[] = { + 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 6 + }; + /* DDR4 support CAS 9, 10, 11, 12, 13, 14, 15, 16, 18, 20, 22, 24 */ + static const int cas_latency_table[] = { + 0, 1, 2, 3, 4, 5, 6, 7, 13, 8, + 14, 9, 15, 10, 12, 11, 16, 17, + 18, 19, 20, 21, 22, 23 + }; + const unsigned int unq_mrs_en = ip_rev < U(0x50500) ? 1U : 0U; + unsigned short esdmode2 = 0U; + unsigned short esdmode3 = 0U; + const unsigned int wr_crc = 0U; + unsigned int rtt_wr = 0U; + const unsigned int srt = 0U; + unsigned int cwl = cal_cwl(clk); + const unsigned int mpr = 0U; + const unsigned int mclk_ps = get_memory_clk_ps(clk); + const unsigned int wc_lat = 0U; + unsigned short esdmode4 = 0U; + unsigned short esdmode5; + int rtt_park_all = 0; + unsigned int rtt_park; + const bool four_cs = conf->cs_in_use == 0xf ? true : false; + unsigned short esdmode6 = 0U; /* Extended SDRAM mode 6 */ + unsigned short esdmode7 = 0U; /* Extended SDRAM mode 7 */ + const unsigned int tccdl_min = max(5U, + picos_to_mclk(clk, pdimm->tccdl_ps)); + + if (popts->rtt_override != 0U) { + rtt = popts->rtt_override_value; + } else { + rtt = popts->cs_odt[0].odt_rtt_norm; + } + + if (additive_latency == (cas_latency - 1)) { + al = 1; + } + if (additive_latency == (cas_latency - 2)) { + al = 2; + } + + if (popts->quad_rank_present != 0 || popts->output_driver_impedance != 0) { + dic = 1; /* output driver impedance 240/7 ohm */ + } + + esdmode = (((qoff & 0x1) << 12) | + ((tdqs_en & 0x1) << 11) | + ((rtt & 0x7) << 8) | + ((wrlvl_en & 0x1) << 7) | + ((al & 0x3) << 3) | + ((dic & 0x3) << 1) | + ((dll_en & 0x1) << 0)); + + if (wr_mclk >= 10 && wr_mclk <= 24) { + wr = wr_table[wr_mclk - 10]; + } else { + ERROR("unsupported wc_mclk = %d for mode register\n", wr_mclk); + } + + /* look up table to get the cas latency bits */ + if (cas_latency >= 9 && cas_latency <= 32) { + caslat = cas_latency_table[cas_latency - 9]; + } else { + WARN("Error: unsupported cas latency for mode register\n"); + } + + sdmode = (((caslat & 0x10) << 8) | + ((wr & 0x7) << 9) | + ((dll_rst & 0x1) << 8) | + ((mode & 0x1) << 7) | + (((caslat >> 1) & 0x7) << 4) | + ((bt & 0x1) << 3) | + ((caslat & 1) << 2) | + ((bl & 0x3) << 0)); + + regs->sdram_mode[0] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + debug("sdram_mode[0] = 0x%x\n", regs->sdram_mode[0]); + + switch (cwl) { + case 9: + case 10: + case 11: + case 12: + cwl -= 9; + break; + case 14: + cwl -= 10; + break; + case 16: + cwl -= 11; + break; + case 18: + cwl -= 12; + break; + case 20: + cwl -= 13; + break; + default: + printf("Error CWL\n"); + break; + } + + if (popts->rtt_override != 0) { + rtt_wr = popts->rtt_wr_override_value; + } else { + rtt_wr = popts->cs_odt[0].odt_rtt_wr; + } + + esdmode2 = ((wr_crc & 0x1) << 12) | + ((rtt_wr & 0x7) << 9) | + ((srt & 0x3) << 6) | + ((cwl & 0x7) << 3); + esdmode3 = ((mpr & 0x3) << 11) | ((wc_lat & 0x3) << 9); + + regs->sdram_mode[1] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + debug("sdram_mode[1] = 0x%x\n", regs->sdram_mode[1]); + + esdmode6 = ((tccdl_min - 4) & 0x7) << 10; + if (popts->vref_dimm != 0) { + esdmode6 |= popts->vref_dimm & 0x7f; + } else if ((popts->ddr_cdr2 & DDR_CDR2_VREF_RANGE_2) != 0) { + esdmode6 |= 1 << 6; /* Range 2 */ + } + + regs->sdram_mode[9] = ((esdmode6 & 0xffff) << 16) | + ((esdmode7 & 0xffff) << 0); + debug("sdram_mode[9] = 0x%x\n", regs->sdram_mode[9]); + + rtt_park = (popts->rtt_park != 0) ? popts->rtt_park : 240; + switch (rtt_park) { + case 240: + rtt_park = 0x4; + break; + case 120: + rtt_park = 0x2; + break; + case 80: + rtt_park = 0x6; + break; + case 60: + rtt_park = 0x1; + break; + case 48: + rtt_park = 0x5; + break; + case 40: + rtt_park = 0x3; + break; + case 34: + rtt_park = 0x7; + break; + default: + rtt_park = 0; + break; + } + + for (i = 0; i < DDRC_NUM_CS; i++) { + if (i != 0 && unq_mrs_en == 0) { + break; + } + + if (popts->rtt_override != 0) { + rtt = popts->rtt_override_value; + rtt_wr = popts->rtt_wr_override_value; + } else { + rtt = popts->cs_odt[i].odt_rtt_norm; + rtt_wr = popts->cs_odt[i].odt_rtt_wr; + } + + esdmode &= 0xF8FF; /* clear bit 10,9,8 for rtt */ + esdmode |= (rtt & 0x7) << 8; + esdmode2 &= 0xF9FF; /* clear bit 10, 9 */ + esdmode2 |= (rtt_wr & 0x3) << 9; + esdmode5 = (popts->x4_en) ? 0 : 0x400; /* data mask */ + + if (rtt_park_all == 0 && + ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) != 0)) { + esdmode5 |= rtt_park << 6; + rtt_park_all = four_cs ? 0 : 1; + } + + if (((regs->sdram_cfg[1] & SDRAM_CFG2_AP_EN) != 0) && + (popts->rdimm == 0)) { + if (mclk_ps >= 935) { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_4_CLK; + } else if (mclk_ps >= 833) { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + } else { + esdmode5 |= DDR_MR5_CA_PARITY_LAT_5_CLK; + WARN("mclk_ps not supported %d", mclk_ps); + + } + } + + switch (i) { + case 0: + regs->sdram_mode[8] = ((esdmode4 & 0xffff) << 16) | + ((esdmode5 & 0xffff) << 0); + debug("sdram_mode[8] = 0x%x\n", regs->sdram_mode[8]); + break; + case 1: + regs->sdram_mode[2] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[3] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[10] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[11] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[2] = 0x%x\n", regs->sdram_mode[2]); + debug("sdram_mode[3] = 0x%x\n", regs->sdram_mode[3]); + debug("sdram_mode[10] = 0x%x\n", regs->sdram_mode[10]); + debug("sdram_mode[11] = 0x%x\n", regs->sdram_mode[11]); + break; + case 2: + regs->sdram_mode[4] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[5] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[12] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[13] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[4] = 0x%x\n", regs->sdram_mode[4]); + debug("sdram_mode[5] = 0x%x\n", regs->sdram_mode[5]); + debug("sdram_mode[12] = 0x%x\n", regs->sdram_mode[12]); + debug("sdram_mode[13] = 0x%x\n", regs->sdram_mode[13]); + break; + case 3: + regs->sdram_mode[6] = (((esdmode & 0xFFFF) << 16) | + ((sdmode & 0xFFFF) << 0)); + regs->sdram_mode[7] = ((esdmode2 & 0xFFFF) << 16) | + ((esdmode3 & 0xFFFF) << 0); + regs->sdram_mode[14] = ((esdmode4 & 0xFFFF) << 16) | + ((esdmode5 & 0xFFFF) << 0); + regs->sdram_mode[15] = ((esdmode6 & 0xFFFF) << 16) | + ((esdmode7 & 0xFFFF) << 0); + debug("sdram_mode[6] = 0x%x\n", regs->sdram_mode[6]); + debug("sdram_mode[7] = 0x%x\n", regs->sdram_mode[7]); + debug("sdram_mode[14] = 0x%x\n", regs->sdram_mode[14]); + debug("sdram_mode[15] = 0x%x\n", regs->sdram_mode[15]); + break; + default: + break; + } + } +} + +#ifndef CONFIG_MEM_INIT_VALUE +#define CONFIG_MEM_INIT_VALUE 0xDEADBEEF +#endif +static void cal_ddr_data_init(struct ddr_cfg_regs *regs) +{ + regs->data_init = CONFIG_MEM_INIT_VALUE; +} + +static void cal_ddr_dq_mapping(struct ddr_cfg_regs *regs, + const struct dimm_params *pdimm) +{ + const unsigned int acc_ecc_en = (regs->sdram_cfg[0] >> 2) & 0x1; +/* FIXME: revert the dq mapping from DIMM */ + regs->dq_map[0] = ((pdimm->dq_mapping[0] & 0x3F) << 26) | + ((pdimm->dq_mapping[1] & 0x3F) << 20) | + ((pdimm->dq_mapping[2] & 0x3F) << 14) | + ((pdimm->dq_mapping[3] & 0x3F) << 8) | + ((pdimm->dq_mapping[4] & 0x3F) << 2); + + regs->dq_map[1] = ((pdimm->dq_mapping[5] & 0x3F) << 26) | + ((pdimm->dq_mapping[6] & 0x3F) << 20) | + ((pdimm->dq_mapping[7] & 0x3F) << 14) | + ((pdimm->dq_mapping[10] & 0x3F) << 8) | + ((pdimm->dq_mapping[11] & 0x3F) << 2); + + regs->dq_map[2] = ((pdimm->dq_mapping[12] & 0x3F) << 26) | + ((pdimm->dq_mapping[13] & 0x3F) << 20) | + ((pdimm->dq_mapping[14] & 0x3F) << 14) | + ((pdimm->dq_mapping[15] & 0x3F) << 8) | + ((pdimm->dq_mapping[16] & 0x3F) << 2); + + /* dq_map for ECC[4:7] is set to 0 if accumulated ECC is enabled */ + regs->dq_map[3] = ((pdimm->dq_mapping[17] & 0x3F) << 26) | + ((pdimm->dq_mapping[8] & 0x3F) << 20) | + ((acc_ecc_en != 0) ? 0 : + (pdimm->dq_mapping[9] & 0x3F) << 14) | + pdimm->dq_mapping_ors; + debug("dq_map[0] = 0x%x\n", regs->dq_map[0]); + debug("dq_map[1] = 0x%x\n", regs->dq_map[1]); + debug("dq_map[2] = 0x%x\n", regs->dq_map[2]); + debug("dq_map[3] = 0x%x\n", regs->dq_map[3]); +} +static void cal_ddr_zq_cntl(struct ddr_cfg_regs *regs) +{ + const unsigned int zqinit = 10U; /* 1024 clocks */ + const unsigned int zqoper = 9U; /* 512 clocks */ + const unsigned int zqcs = 7U; /* 128 clocks */ + const unsigned int zqcs_init = 5U; /* 1024 refresh seqences */ + const unsigned int zq_en = 1U; /* enabled */ + + regs->zq_cntl = ((zq_en & 0x1) << 31) | + ((zqinit & 0xF) << 24) | + ((zqoper & 0xF) << 16) | + ((zqcs & 0xF) << 8) | + ((zqcs_init & 0xF) << 0); + debug("zq_cntl = 0x%x\n", regs->zq_cntl); +} + +static void cal_ddr_sr_cntr(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int sr_it = (popts->auto_self_refresh_en) ? + popts->sr_it : 0; + + regs->ddr_sr_cntr = (sr_it & 0xF) << 16; + debug("ddr_sr_cntr = 0x%x\n", regs->ddr_sr_cntr); +} + +static void cal_ddr_eor(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + if (popts->addr_hash != 0) { + regs->eor = 0x40000000; /* address hash enable */ + debug("eor = 0x%x\n", regs->eor); + } +} + +static void cal_ddr_csn_bnds(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + const struct dimm_params *pdimm) +{ + int i; + unsigned long long ea, sa; + + /* Chip Select Memory Bounds (CSn_BNDS) */ + for (i = 0; + i < DDRC_NUM_CS && conf->cs_size[i]; + i++) { + debug("cs_in_use = 0x%x\n", conf->cs_in_use); + if (conf->cs_in_use != 0) { + sa = conf->cs_base_addr[i]; + ea = sa + conf->cs_size[i] - 1; + sa >>= 24; + ea >>= 24; + regs->cs[i].bnds = ((sa & 0xffff) << 16) | + ((ea & 0xffff) << 0); + cal_csn_config(i, regs, popts, pdimm); + } else { + /* setting bnds to 0xffffffff for inactive CS */ + regs->cs[i].bnds = 0xffffffff; + } + + debug("cs[%d].bnds = 0x%x\n", i, regs->cs[i].bnds); + } +} + +static void cal_ddr_addr_dec(struct ddr_cfg_regs *regs) +{ +#ifdef CONFIG_DDR_ADDR_DEC + unsigned int ba_bits __unused; + char p __unused; + const unsigned int cs0_config = regs->cs[0].config; + const int cacheline = PLATFORM_CACHE_LINE_SHIFT; + unsigned int bg_bits; + unsigned int row_bits; + unsigned int col_bits; + unsigned int cs; + unsigned int map_row[18]; + unsigned int map_col[11]; + unsigned int map_ba[2]; + unsigned int map_cid[2] = {0x3F, 0x3F}; + unsigned int map_bg[2] = {0x3F, 0x3F}; + unsigned int map_cs[2] = {0x3F, 0x3F}; + unsigned int dbw; + unsigned int ba_intlv; + int placement; + int intlv; + int abort = 0; + int i; + int j; + + col_bits = (cs0_config >> 0) & 0x7; + if (col_bits < 4) { + col_bits += 8; + } else if (col_bits < 7 || col_bits > 10) { + ERROR("Error %s col_bits = %d\n", __func__, col_bits); + } + row_bits = ((cs0_config >> 8) & 0x7) + 12; + ba_bits = ((cs0_config >> 14) & 0x3) + 2; + bg_bits = ((cs0_config >> 4) & 0x3) + 0; + intlv = (cs0_config >> 24) & 0xf; + ba_intlv = (regs->sdram_cfg[0] >> 8) & 0x7f; + switch (ba_intlv) { + case DDR_BA_INTLV_CS01: + cs = 1; + break; + case DDR_BA_INTLV_CS0123: + cs = 2; + break; + case DDR_BA_NONE: + cs = 0; + break; + default: + ERROR("%s ba_intlv 0x%x\n", __func__, ba_intlv); + return; + } + debug("col %d, row %d, ba %d, bg %d, intlv %d\n", + col_bits, row_bits, ba_bits, bg_bits, intlv); + /* + * Example mapping of 15x2x2x10 + * ---- --rr rrrr rrrr rrrr rCBB Gccc cccI cGcc cbbb + */ + dbw = (regs->sdram_cfg[0] >> 19) & 0x3; + switch (dbw) { + case 0: /* 64-bit */ + placement = 3; + break; + case 1: /* 32-bit */ + placement = 2; + break; + default: + ERROR("%s dbw = %d\n", __func__, dbw); + return; + } + debug("cacheline size %d\n", cacheline); + for (i = 0; placement < cacheline; i++) { + map_col[i] = placement++; + } + map_bg[0] = placement++; + for ( ; i < col_bits; i++) { + map_col[i] = placement++; + if (placement == intlv) { + placement++; + } + } + for ( ; i < 11; i++) { + map_col[i] = 0x3F; /* unused col bits */ + } + + if (bg_bits >= 2) { + map_bg[1] = placement++; + } + map_ba[0] = placement++; + map_ba[1] = placement++; + if (cs != 0U) { + map_cs[0] = placement++; + if (cs == 2U) { + map_cs[1] = placement++; + } + } else { + map_cs[0] = U(0x3F); + } + + for (i = 0; i < row_bits; i++) { + map_row[i] = placement++; + } + + for ( ; i < 18; i++) { + map_row[i] = 0x3F; /* unused row bits */ + } + + for (i = 39; i >= 0 ; i--) { + if (i == intlv) { + placement = 8; + p = 'I'; + } else if (i < 3) { + p = 'b'; + placement = 0; + } else { + placement = 0; + p = '-'; + } + for (j = 0; j < 18; j++) { + if (map_row[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'r'; + } + for (j = 0; j < 11; j++) { + if (map_col[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'c'; + } + for (j = 0; j < 2; j++) { + if (map_ba[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'B'; + } + for (j = 0; j < 2; j++) { + if (map_bg[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'G'; + } + for (j = 0; j < 2; j++) { + if (map_cs[j] != i) { + continue; + } + if (placement != 0) { + abort = 1; + ERROR("%s wrong address bit %d\n", __func__, i); + } + placement = i; + p = 'C'; + } +#ifdef DDR_DEBUG + printf("%c", p); + if ((i % 4) == 0) { + printf(" "); + } +#endif + } +#ifdef DDR_DEBUG + puts("\n"); +#endif + + if (abort != 0) { + return; + } + + regs->dec[0] = map_row[17] << 26 | + map_row[16] << 18 | + map_row[15] << 10 | + map_row[14] << 2; + regs->dec[1] = map_row[13] << 26 | + map_row[12] << 18 | + map_row[11] << 10 | + map_row[10] << 2; + regs->dec[2] = map_row[9] << 26 | + map_row[8] << 18 | + map_row[7] << 10 | + map_row[6] << 2; + regs->dec[3] = map_row[5] << 26 | + map_row[4] << 18 | + map_row[3] << 10 | + map_row[2] << 2; + regs->dec[4] = map_row[1] << 26 | + map_row[0] << 18 | + map_col[10] << 10 | + map_col[9] << 2; + regs->dec[5] = map_col[8] << 26 | + map_col[7] << 18 | + map_col[6] << 10 | + map_col[5] << 2; + regs->dec[6] = map_col[4] << 26 | + map_col[3] << 18 | + map_col[2] << 10 | + map_col[1] << 2; + regs->dec[7] = map_col[0] << 26 | + map_ba[1] << 18 | + map_ba[0] << 10 | + map_cid[1] << 2; + regs->dec[8] = map_cid[1] << 26 | + map_cs[1] << 18 | + map_cs[0] << 10 | + map_bg[1] << 2; + regs->dec[9] = map_bg[0] << 26 | + 1; + for (i = 0; i < 10; i++) { + debug("dec[%d] = 0x%x\n", i, regs->dec[i]); + } +#endif +} +static unsigned int skip_caslat(unsigned int tckmin_ps, + unsigned int taamin_ps, + unsigned int mclk_ps, + unsigned int package_3ds) +{ + int i, j, k; + struct cas { + const unsigned int tckmin_ps; + const unsigned int caslat[4]; + }; + struct speed { + const struct cas *cl; + const unsigned int taamin_ps[4]; + }; + const struct cas cl_3200[] = { + {625, {0xa00000, 0xb00000, 0xf000000,} }, + {750, { 0x20000, 0x60000, 0xe00000,} }, + {833, { 0x8000, 0x18000, 0x38000,} }, + {937, { 0x4000, 0x4000, 0xc000,} }, + {1071, { 0x1000, 0x1000, 0x3000,} }, + {1250, { 0x400, 0x400, 0xc00,} }, + {1500, { 0, 0x600, 0x200,} }, + }; + const struct cas cl_2933[] = { + {682, { 0, 0x80000, 0x180000, 0x380000} }, + {750, { 0x20000, 0x60000, 0x60000, 0xe0000} }, + {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, + {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0x400, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0x200, 0x200, 0x200} }, + }; + const struct cas cl_2666[] = { + {750, { 0, 0x20000, 0x60000, 0xe0000} }, + {833, { 0x8000, 0x18000, 0x18000, 0x38000} }, + {937, { 0x4000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x1000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0x400, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0, 0x200, 0x200} }, + }; + const struct cas cl_2400[] = { + {833, { 0, 0x8000, 0x18000, 0x38000} }, + {937, { 0xc000, 0x4000, 0x4000, 0xc000} }, + {1071, { 0x3000, 0x1000, 0x1000, 0x3000} }, + {1250, { 0xc00, 0x400, 0x400, 0xc00} }, + {1500, { 0, 0x400, 0x200, 0x200} }, + }; + const struct cas cl_2133[] = { + {937, { 0, 0x4000, 0xc000,} }, + {1071, { 0x2000, 0, 0x2000,} }, + {1250, { 0x800, 0, 0x800,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct cas cl_1866[] = { + {1071, { 0, 0x1000, 0x3000,} }, + {1250, { 0xc00, 0x400, 0xc00,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct cas cl_1600[] = { + {1250, { 0, 0x400, 0xc00,} }, + {1500, { 0, 0x400, 0x200,} }, + }; + const struct speed bin_0[] = { + {cl_3200, {12500, 13750, 15000,} }, + {cl_2933, {12960, 13640, 13750, 15000,} }, + {cl_2666, {12750, 13500, 13750, 15000,} }, + {cl_2400, {12500, 13320, 13750, 15000,} }, + {cl_2133, {13130, 13500, 15000,} }, + {cl_1866, {12850, 13500, 15000,} }, + {cl_1600, {12500, 13500, 15000,} } + }; + const struct cas cl_3200_3ds[] = { + {625, { 0xa000000, 0xb000000, 0xf000000,} }, + {750, { 0xaa00000, 0xab00000, 0xef00000,} }, + {833, { 0xaac0000, 0xaac0000, 0xebc0000,} }, + {937, { 0xaab0000, 0xaab0000, 0xeaf0000,} }, + {1071, { 0xaaa4000, 0xaaac000, 0xeaec000,} }, + {1250, { 0xaaa0000, 0xaaa2000, 0xeaeb000,} }, + }; + const struct cas cl_2666_3ds[] = { + {750, { 0xa00000, 0xb00000, 0xf00000,} }, + {833, { 0xac0000, 0xac0000, 0xbc0000,} }, + {937, { 0xab0000, 0xab0000, 0xaf0000,} }, + {1071, { 0xaa4000, 0xaac000, 0xaac000,} }, + {1250, { 0xaa0000, 0xaaa000, 0xaaa000,} }, + }; + const struct cas cl_2400_3ds[] = { + {833, { 0xe00000, 0xe40000, 0xec0000, 0xb00000} }, + {937, { 0xe00000, 0xe00000, 0xea0000, 0xae0000} }, + {1071, { 0xe00000, 0xe04000, 0xeac000, 0xaec000} }, + {1250, { 0xe00000, 0xe00000, 0xeaa000, 0xae2000} }, + }; + const struct cas cl_2133_3ds[] = { + {937, { 0x90000, 0xb0000, 0xf0000,} }, + {1071, { 0x84000, 0xac000, 0xec000,} }, + {1250, { 0x80000, 0xa2000, 0xe2000,} }, + }; + const struct cas cl_1866_3ds[] = { + {1071, { 0, 0x4000, 0xc000,} }, + {1250, { 0, 0x1000, 0x3000,} }, + }; + const struct cas cl_1600_3ds[] = { + {1250, { 0, 0x1000, 0x3000,} }, + }; + const struct speed bin_3ds[] = { + {cl_3200_3ds, {15000, 16250, 17140,} }, + {cl_2666_3ds, {15000, 16500, 17140,} }, + {cl_2400_3ds, {15000, 15830, 16670, 17140} }, + {cl_2133_3ds, {15950, 16880, 17140,} }, + {cl_1866_3ds, {15000, 16070, 17140,} }, + {cl_1600_3ds, {15000, 16250, 17500,} }, + }; + const struct speed *bin; + int size; + unsigned int taamin_max, tck_max; + + if (taamin_ps > ((package_3ds != 0) ? 21500 : 18000)) { + ERROR("taamin_ps %u invalid\n", taamin_ps); + return 0; + } + if (package_3ds != 0) { + bin = bin_3ds; + size = ARRAY_SIZE(bin_3ds); + taamin_max = 1250; + tck_max = 1500; + } else { + bin = bin_0; + size = ARRAY_SIZE(bin_0); + taamin_max = 1500; + tck_max = 1600; + } + if (mclk_ps < 625 || mclk_ps > tck_max) { + ERROR("mclk %u invalid\n", mclk_ps); + return 0; + } + + for (i = 0; i < size; i++) { + if (bin[i].cl[0].tckmin_ps >= tckmin_ps) { + break; + } + } + if (i >= size) { + ERROR("speed bin not found\n"); + return 0; + } + if (bin[i].cl[0].tckmin_ps > tckmin_ps && i > 0) { + i--; + } + + for (j = 0; j < 4; j++) { + if ((bin[i].taamin_ps[j] == 0) || + bin[i].taamin_ps[j] >= taamin_ps) { + break; + } + } + + if (j >= 4) { + ERROR("taamin_ps out of range.\n"); + return 0; + } + + if ((bin[i].taamin_ps[j] == 0) || + (bin[i].taamin_ps[j] > taamin_ps && j > 0)) { + j--; + } + + for (k = 0; bin[i].cl[k].tckmin_ps < mclk_ps && + bin[i].cl[k].tckmin_ps < taamin_max; k++) + ; + if (bin[i].cl[k].tckmin_ps > mclk_ps && k > 0) { + k--; + } + + debug("Skip CL mask for this speed 0x%x\n", bin[i].cl[k].caslat[j]); + + return bin[i].cl[k].caslat[j]; +} + +int compute_ddrc(const unsigned long clk, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + struct ddr_cfg_regs *regs, + const struct dimm_params *pdimm, + unsigned int ip_rev) +{ + unsigned int cas_latency; + unsigned int caslat_skip; + unsigned int additive_latency; + const unsigned int mclk_ps = get_memory_clk_ps(clk); + int i; + + zeromem(regs, sizeof(struct ddr_cfg_regs)); + + if (mclk_ps < pdimm->tckmin_x_ps) { + ERROR("DDR Clk: MCLK cycle is %u ps.\n", mclk_ps); + ERROR("DDR Clk is faster than DIMM can support.\n"); + } + + /* calculate cas latency, override first */ + cas_latency = (popts->caslat_override != 0) ? + popts->caslat_override_value : + (pdimm->taa_ps + mclk_ps - 1) / mclk_ps; + + /* skip unsupported caslat based on speed bin */ + caslat_skip = skip_caslat(pdimm->tckmin_x_ps, + pdimm->taa_ps, + mclk_ps, + pdimm->package_3ds); + debug("Skip caslat 0x%x\n", caslat_skip); + + /* Check if DIMM supports the cas latency */ + i = 24; + while (((pdimm->caslat_x & ~caslat_skip & (1 << cas_latency)) == 0) && + (i-- > 0)) { + cas_latency++; + } + + if (i <= 0) { + ERROR("Failed to find a proper cas latency\n"); + return -EINVAL; + } + /* Verify cas latency does not exceed 18ns for DDR4 */ + if (cas_latency * mclk_ps > 18000) { + ERROR("cas latency is too large %d\n", cas_latency); + return -EINVAL; + } + + additive_latency = (popts->addt_lat_override != 0) ? + popts->addt_lat_override_value : 0; + + cal_ddr_csn_bnds(regs, popts, conf, pdimm); + cal_ddr_sdram_cfg(clk, regs, popts, pdimm, ip_rev); + cal_ddr_sdram_rcw(clk, regs, popts, pdimm); + cal_timing_cfg(clk, regs, popts, pdimm, conf, cas_latency, + additive_latency); + cal_ddr_dq_mapping(regs, pdimm); + + if (ip_rev >= 0x50500) { + cal_ddr_addr_dec(regs); + } + + cal_ddr_sdram_mode(clk, regs, popts, conf, pdimm, cas_latency, + additive_latency, ip_rev); + cal_ddr_eor(regs, popts); + cal_ddr_data_init(regs); + cal_ddr_sdram_interval(clk, regs, popts, pdimm); + cal_ddr_zq_cntl(regs); + cal_ddr_sr_cntr(regs, popts); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c new file mode 100644 index 0000000..b6dffc8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c @@ -0,0 +1,288 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#define UL_5POW12 244140625UL +#define ULL_2E12 2000000000000ULL +#define UL_2POW13 (1UL << 13) +#define ULL_8FS 0xFFFFFFFFULL + +#define do_div(n, base) ({ \ + unsigned int __base = (base); \ + unsigned int __rem; \ + __rem = ((unsigned long long)(n)) % __base; \ + (n) = ((unsigned long long)(n)) / __base; \ + __rem; \ +}) + +#define CCN_HN_F_SAM_NODEID_MASK 0x7f +#ifdef NXP_HAS_CCN504 +#define CCN_HN_F_SAM_NODEID_DDR0 0x4 +#define CCN_HN_F_SAM_NODEID_DDR1 0xe +#elif defined(NXP_HAS_CCN508) +#define CCN_HN_F_SAM_NODEID_DDR0_0 0x3 +#define CCN_HN_F_SAM_NODEID_DDR0_1 0x8 +#define CCN_HN_F_SAM_NODEID_DDR1_0 0x13 +#define CCN_HN_F_SAM_NODEID_DDR1_1 0x18 +#endif + +unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num) +{ + if (sys->freq_ddr_pll0 == 0) { + get_clocks(sys); + } + + switch (ctrl_num) { + case 0: + return sys->freq_ddr_pll0; + case 1: + return sys->freq_ddr_pll0; + case 2: + return sys->freq_ddr_pll1; + } + + return 0; +} + +unsigned int get_memory_clk_ps(const unsigned long data_rate) +{ + unsigned int result; + /* Round to nearest 10ps, being careful about 64-bit multiply/divide */ + unsigned long long rem, mclk_ps = ULL_2E12; + + /* Now perform the big divide, the result fits in 32-bits */ + rem = do_div(mclk_ps, data_rate); + result = (rem >= (data_rate >> 1)) ? mclk_ps + 1 : mclk_ps; + + return result; +} + +unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos) +{ + unsigned long long clks, clks_rem; + + /* Short circuit for zero picos */ + if ((picos == 0U) || (data_rate == 0UL)) { + return 0U; + } + + /* First multiply the time by the data rate (32x32 => 64) */ + clks = picos * (unsigned long long)data_rate; + /* + * Now divide by 5^12 and track the 32-bit remainder, then divide + * by 2*(2^12) using shifts (and updating the remainder). + */ + clks_rem = do_div(clks, UL_5POW12); + clks_rem += (clks & (UL_2POW13-1)) * UL_5POW12; + clks >>= 13U; + + /* If we had a remainder greater than the 1ps error, then round up */ + if (clks_rem > data_rate) { + clks++; + } + + /* Clamp to the maximum representable value */ + if (clks > ULL_8FS) { + clks = ULL_8FS; + } + return (unsigned int) clks; +} + +/* valid_spd_mask has been checked by parse_spd */ +int disable_unused_ddrc(struct ddr_info *priv, + int valid_spd_mask, uintptr_t nxp_ccn_hn_f0_addr) +{ +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + void *hnf_sam_ctrl = (void *)(nxp_ccn_hn_f0_addr + CCN_HN_F_SAM_CTL); + uint32_t val, nodeid; +#ifdef NXP_HAS_CCN504 + uint32_t num_hnf_nodes = 4U; +#else + uint32_t num_hnf_nodes = 8U; +#endif + int disable_ddrc = 0; + int i; + + if (priv->num_ctlrs < 2) { + debug("%s: nothing to do.\n", __func__); + } + + switch (priv->dimm_on_ctlr) { + case 1: + disable_ddrc = ((valid_spd_mask &0x2) == 0) ? 2 : 0; + disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc; + break; + case 2: + disable_ddrc = ((valid_spd_mask &0x4) == 0) ? 2 : 0; + disable_ddrc = ((valid_spd_mask &0x1) == 0) ? 1 : disable_ddrc; + break; + default: + ERROR("Invalid number of DIMMs %d\n", priv->dimm_on_ctlr); + return -EINVAL; + } + + if (disable_ddrc != 0) { + debug("valid_spd_mask = 0x%x\n", valid_spd_mask); + } + + switch (disable_ddrc) { + case 1: + priv->num_ctlrs = 1; + priv->spd_addr = &priv->spd_addr[priv->dimm_on_ctlr]; + priv->ddr[0] = priv->ddr[1]; + priv->ddr[1] = NULL; + priv->phy[0] = priv->phy[0]; + priv->phy[1] = NULL; + debug("Disable first DDR controller\n"); + break; + case 2: + priv->num_ctlrs = 1; + priv->ddr[1] = NULL; + priv->phy[1] = NULL; + debug("Disable second DDR controller\n"); + /* fallthrough */ + case 0: + break; + default: + ERROR("Program error.\n"); + return -EINVAL; + } + + if (disable_ddrc == 0) { + debug("Both controllers in use.\n"); + return 0; + } + + for (i = 0; i < num_hnf_nodes; i++) { + val = mmio_read_64((uintptr_t)hnf_sam_ctrl); +#ifdef NXP_HAS_CCN504 + nodeid = disable_ddrc == 1 ? CCN_HN_F_SAM_NODEID_DDR1 : + (disable_ddrc == 2 ? CCN_HN_F_SAM_NODEID_DDR0 : + 0x0); /*Failure condition. never hit */ +#elif defined(NXP_HAS_CCN508) + if (disable_ddrc == 1) { + nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR1_1 : + CCN_HN_F_SAM_NODEID_DDR1_0; + } else if (disable_ddrc == 2) { + nodeid = (i < 2 || i >= 6) ? CCN_HN_F_SAM_NODEID_DDR0_0 : + CCN_HN_F_SAM_NODEID_DDR0_1; + } else { + nodeid = 0; /* Failure condition. never hit */ + } +#endif + if (nodeid != (val & CCN_HN_F_SAM_NODEID_MASK)) { + debug("Setting HN-F node %d\n", i); + debug("nodeid = 0x%x\n", nodeid); + val &= ~CCN_HN_F_SAM_NODEID_MASK; + val |= nodeid; + mmio_write_64((uintptr_t)hnf_sam_ctrl, val); + } + hnf_sam_ctrl += CCN_HN_F_REGION_SIZE; + } +#endif + return 0; +} + +unsigned int get_ddrc_version(const struct ccsr_ddr *ddr) +{ + unsigned int ver; + + ver = (ddr_in32(&ddr->ip_rev1) & 0xFFFF) << 8U; + ver |= (ddr_in32(&ddr->ip_rev2) & 0xFF00) >> 8U; + + return ver; +} + +void print_ddr_info(struct ccsr_ddr *ddr) +{ + unsigned int cs0_config = ddr_in32(&ddr->csn_cfg[0]); + unsigned int sdram_cfg = ddr_in32(&ddr->sdram_cfg); + int cas_lat; + + if ((sdram_cfg & SDRAM_CFG_MEM_EN) == 0U) { + printf(" (DDR not enabled)\n"); + return; + } + + printf("DDR"); + switch ((sdram_cfg & SDRAM_CFG_SDRAM_TYPE_MASK) >> + SDRAM_CFG_SDRAM_TYPE_SHIFT) { + case SDRAM_TYPE_DDR4: + printf("4"); + break; + default: + printf("?"); + break; + } + + switch (sdram_cfg & SDRAM_CFG_DBW_MASK) { + case SDRAM_CFG_32_BW: + printf(", 32-bit"); + break; + case SDRAM_CFG_16_BW: + printf(", 16-bit"); + break; + case SDRAM_CFG_8_BW: + printf(", 8-bit"); + break; + default: + printf(", 64-bit"); + break; + } + + /* Calculate CAS latency based on timing cfg values */ + cas_lat = ((ddr_in32(&ddr->timing_cfg_1) >> 16) & 0xf); + cas_lat += 2; /* for DDRC newer than 4.4 */ + cas_lat += ((ddr_in32(&ddr->timing_cfg_3) >> 12) & 3) << 4; + printf(", CL=%d", cas_lat >> 1); + if ((cas_lat & 0x1) != 0) { + printf(".5"); + } + + if ((sdram_cfg & SDRAM_CFG_ECC_EN) != 0) { + printf(", ECC on"); + } else { + printf(", ECC off"); + } + + if ((cs0_config & 0x20000000) != 0) { + printf(", "); + switch ((cs0_config >> 24) & 0xf) { + case DDR_256B_INTLV: + printf("256B"); + break; + default: + printf("invalid"); + break; + } + } + + if (((sdram_cfg >> 8) & 0x7f) != 0) { + printf(", "); + switch (sdram_cfg >> 8 & 0x7f) { + case DDR_BA_INTLV_CS0123: + printf("CS0+CS1+CS2+CS3"); + break; + case DDR_BA_INTLV_CS01: + printf("CS0+CS1"); + break; + default: + printf("invalid"); + break; + } + } + printf("\n"); +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c new file mode 100644 index 0000000..4b66d38 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c @@ -0,0 +1,97 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +static void cal_ddr_sdram_clk_cntl(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int clk_adj = popts->clk_adj; + const unsigned int ss_en = 0U; + + regs->clk_cntl = ((ss_en & U(0x1)) << 31U) | + ((clk_adj & U(0x1F)) << 22U); + debug("clk_cntl = 0x%x\n", regs->clk_cntl); +} + +static void cal_ddr_cdr(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + regs->cdr[0] = popts->ddr_cdr1; + regs->cdr[1] = popts->ddr_cdr2; + debug("cdr[0] = 0x%x\n", regs->cdr[0]); + debug("cdr[1] = 0x%x\n", regs->cdr[1]); +} + +static void cal_ddr_wrlvl_cntl(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + const unsigned int wrlvl_en = 1U; /* enabled */ + const unsigned int wrlvl_mrd = U(0x6); /* > 40nCK */ + const unsigned int wrlvl_odten = U(0x7); /* 128 */ + const unsigned int wrlvl_dqsen = U(0x5); /* > 25nCK */ + const unsigned int wrlvl_wlr = U(0x6); /* > tWLO + 6 */ + const unsigned int wrlvl_smpl = popts->wrlvl_override ? + popts->wrlvl_sample : U(0xf); + const unsigned int wrlvl_start = popts->wrlvl_start; + + regs->wrlvl_cntl[0] = ((wrlvl_en & U(0x1)) << 31U) | + ((wrlvl_mrd & U(0x7)) << 24U) | + ((wrlvl_odten & U(0x7)) << 20U) | + ((wrlvl_dqsen & U(0x7)) << 16U) | + ((wrlvl_smpl & U(0xf)) << 12U) | + ((wrlvl_wlr & U(0x7)) << 8U) | + ((wrlvl_start & U(0x1F)) << 0U); + regs->wrlvl_cntl[1] = popts->wrlvl_ctl_2; + regs->wrlvl_cntl[2] = popts->wrlvl_ctl_3; + debug("wrlvl_cntl[0] = 0x%x\n", regs->wrlvl_cntl[0]); + debug("wrlvl_cntl[1] = 0x%x\n", regs->wrlvl_cntl[1]); + debug("wrlvl_cntl[2] = 0x%x\n", regs->wrlvl_cntl[2]); + +} + +static void cal_ddr_dbg(struct ddr_cfg_regs *regs, + const struct memctl_opt *popts) +{ + if (popts->cswl_override != 0) { + regs->debug[18] = popts->cswl_override; + } + +#ifdef CONFIG_SYS_FSL_DDR_EMU + /* disable DDR training for emulator */ + regs->debug[2] = U(0x00000400); + regs->debug[4] = U(0xff800800); + regs->debug[5] = U(0x08000800); + regs->debug[6] = U(0x08000800); + regs->debug[7] = U(0x08000800); + regs->debug[8] = U(0x08000800); +#endif + if (popts->cpo_sample != 0U) { + regs->debug[28] = popts->cpo_sample; + debug("debug[28] = 0x%x\n", regs->debug[28]); + } +} + +int compute_ddr_phy(struct ddr_info *priv) +{ + const struct memctl_opt *popts = &priv->opt; + struct ddr_cfg_regs *regs = &priv->ddr_reg; + + cal_ddr_sdram_clk_cntl(regs, popts); + cal_ddr_cdr(regs, popts); + cal_ddr_wrlvl_cntl(regs, popts); + cal_ddr_dbg(regs, popts); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h new file mode 100644 index 0000000..ee7b4d8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h @@ -0,0 +1,151 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSR_H +#define CSR_H + +#define t_anib 0 +#define t_dbyte 0x10000 +#define t_master 0x20000 +#define t_acsm 0x40000 +#define t_initeng 0x90000 +#define t_drtub 0xc0000 +#define t_apbonly 0xd0000 +#define csr_dbyte_misc_mode_addr 0x00 +#define csr_micro_cont_mux_sel_addr 0x00 +#define csr_uct_shadow_regs 0x04 +#define csr_cal_uclk_info_addr 0x08 +#define csr_seq0bdly0_addr 0x0b +#define csr_seq0bdly1_addr 0x0c +#define csr_seq0bdly2_addr 0x0d +#define csr_seq0bdly3_addr 0x0e +#define csr_seq0bdisable_flag0_addr 0x0c +#define csr_seq0bdisable_flag1_addr 0x0d +#define csr_seq0bdisable_flag2_addr 0x0e +#define csr_seq0bdisable_flag3_addr 0x0f +#define csr_seq0bdisable_flag4_addr 0x10 +#define csr_seq0bdisable_flag5_addr 0x11 +#define csr_seq0bdisable_flag6_addr 0x12 +#define csr_seq0bdisable_flag7_addr 0x13 +#define csr_dfi_mode_addr 0x18 +#define csr_tristate_mode_ca_addr 0x19 +#define csr_dfiphyupd_addr 0x21 +#define csr_dqs_preamble_control_addr 0x24 +#define csr_master_x4config_addr 0x25 +#define csr_enable_cs_multicast_addr 0x27 +#define csr_acx4_anib_dis_addr 0x2c +#define csr_dmipin_present_addr 0x2d +#define csr_ard_ptr_init_val_addr 0x2e +#define csr_dct_write_prot 0x31 +#define csr_uct_write_only_shadow 0x32 +#define csr_uct_write_prot 0x33 +#define csr_uct_dat_write_only_shadow 0x34 +#define csr_dbyte_dll_mode_cntrl_addr 0x3a +#define csr_atx_impedance_addr 0x43 +#define csr_dq_dqs_rcv_cntrl_addr 0x43 +#define csr_cal_offsets_addr 0x45 +#define csr_tx_impedance_ctrl1_addr 0x49 +#define csr_dq_dqs_rcv_cntrl1_addr 0x4a +#define csr_tx_odt_drv_stren_addr 0x4d +#define csr_cal_drv_str0_addr 0x50 +#define csr_atx_slew_rate_addr 0x55 +#define csr_proc_odt_time_ctl_addr 0x56 +#define csr_mem_alert_control_addr 0x5b +#define csr_mem_alert_control2_addr 0x5c +#define csr_tx_slew_rate_addr 0x5f +#define csr_mem_reset_l_addr 0x60 +#define csr_dfi_camode_addr 0x75 +#define csr_dll_gain_ctl_addr 0x7c +#define csr_dll_lockparam_addr 0x7d +#define csr_ucclk_hclk_enables_addr 0x80 +#define csr_acsm_playback0x0_addr 0x80 +#define csr_acsm_playback1x0_addr 0x81 +#define csr_cal_rate_addr 0x88 +#define csr_cal_zap_addr 0x89 +#define csr_cal_misc2_addr 0x98 +#define csr_micro_reset_addr 0x99 +#define csr_dfi_rd_data_cs_dest_map_addr 0xb0 +#define csr_vref_in_global_addr 0xb2 +#define csr_dfi_wr_data_cs_dest_map_addr 0xb4 +#define csr_pll_pwr_dn_addr 0xc3 +#define csr_pll_ctrl2_addr 0xc5 +#define csr_pll_ctrl1_addr 0xc7 +#define csr_pll_test_mode_addr 0xca +#define csr_pll_ctrl4_addr 0xcc +#define csr_dfi_freq_xlat0_addr 0xf0 +#define csr_acsm_ctrl0_addr 0xf0 +#define csr_dfi_freq_ratio_addr 0xfa +#define csr_acsm_ctrl13_addr 0xfd +#define csr_tx_pre_drv_mode_lsb 8 +#define csr_tx_pre_n_lsb 4 +#define csr_tx_pre_p_lsb 0 +#define csr_atx_pre_drv_mode_lsb 8 +#define csr_atx_pre_n_lsb 4 +#define csr_atx_pre_p_lsb 0 +#define csr_wdqsextension_lsb 8 +#define csr_lp4sttc_pre_bridge_rx_en_lsb 7 +#define csr_lp4postamble_ext_lsb 6 +#define csr_lp4tgl_two_tck_tx_dqs_pre_lsb 5 +#define csr_position_dfe_init_lsb 2 +#define csr_two_tck_tx_dqs_pre_lsb 1 +#define csr_two_tck_rx_dqs_pre_lsb 0 +#define csr_dll_rx_preamble_mode_lsb 1 +#define csr_odtstren_n_lsb 6 +#define csr_drv_stren_fsdq_n_lsb 6 +#define csr_drv_stren_fsdq_p_lsb 0 +#define csr_adrv_stren_n_lsb 5 +#define csr_adrv_stren_p_lsb 0 +#define csr_cal_drv_str_pu50_lsb 4 +#define csr_cal_once_lsb 5 +#define csr_cal_interval_lsb 0 +#define csr_cal_run_lsb 4 +#define csr_global_vref_in_dac_lsb 3 +#define csr_gain_curr_adj_lsb 7 +#define csr_major_mode_dbyte_lsb 4 +#define csr_dfe_ctrl_lsb 2 +#define csr_ext_vref_range_lsb 1 +#define csr_sel_analog_vref_lsb 0 +#define csr_malertsync_bypass_lsb 0 +#define csr_ck_dis_val_lsb 2 +#define csr_ddr2tmode_lsb 1 +#define csr_dis_dyn_adr_tri_lsb 0 +#define csr_dbyte_disable_lsb 2 +#define csr_power_down_rcvr_lsb 0 +#define csr_power_down_rcvr_dqs_lsb 9 +#define csr_rx_pad_standby_en_lsb 10 +#define csr_rx_pad_standby_en_mask 0x400 +#define csr_x4tg_lsb 0 +#define csr_reset_to_micro_mask 0x8 +#define csr_protect_mem_reset_mask 0x2 +#define csr_stall_to_micro_mask 0x1 +#define uct_write_prot_shadow_mask 0x1 +#define csr_acsm_par_mode_mask 0x4000 +#define csr_acsm_cke_enb_lsb 0 +#define csr_dfiphyupd_threshold_lsb 8 +#define csr_dfiphyupd_threshold_msb 11 +#define csr_dfiphyupd_threshold_mask 0xf00 +#define csr_dfi_rd_destm0_lsb 0 +#define csr_dfi_rd_destm1_lsb 2 +#define csr_dfi_rd_destm2_lsb 4 +#define csr_dfi_rd_destm3_lsb 6 +#define csr_dfi_wr_destm0_lsb 0 +#define csr_dfi_wr_destm1_lsb 2 +#define csr_dfi_wr_destm2_lsb 4 +#define csr_dfi_wr_destm3_lsb 6 +#define csr_acsm_2t_mode_mask 0x40 +#define csr_cal_misc2_err_dis 13 +#define csr_cal_offset_pdc_lsb 6 +#define csr_cal_offset_pdc_msb 9 +#define csr_cal_offset_pdc_mask 0xe0 +#define csr_cal_drv_pdth_mask 0x3c0 + + +struct impedance_mapping { + int ohm; + int code; +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h new file mode 100644 index 0000000..f17f2e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h @@ -0,0 +1,2897 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR4FW +#define DDR4FW + +#define PHY_GEN2_MAX_IMAGE_SIZE 32768 +#define PHY_GEN2_IMEM_ADDR 0x50000 +#define PHY_GEN2_DMEM_ADDR 0x54000 + +struct ddr4u1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x1B - 0x19]; + uint8_t share2dvref_result; + uint8_t reserved1c[0x22 - 0x1c]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t reserved_d6[0x3f6 - 0xd6]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4u2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22 - 0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33 - 0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41 - 0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t reserved_d6[0x3f6 - 0xd6]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4r1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x22 - 0x19]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t reserved142[0x3f6 - 0x142]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4r2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22-0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33-0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41-0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t reserved142[0x3f6 - 0x142]; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4lr1d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t reserved19[0x22 - 0x19]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + int8_t cdd_rr_3_2; + int8_t cdd_rr_3_1; + int8_t cdd_rr_3_0; + int8_t cdd_rr_2_3; + int8_t cdd_rr_2_1; + int8_t cdd_rr_2_0; + int8_t cdd_rr_1_3; + int8_t cdd_rr_1_2; + int8_t cdd_rr_1_0; + int8_t cdd_rr_0_3; + int8_t cdd_rr_0_2; + int8_t cdd_rr_0_1; + int8_t cdd_ww_3_2; + int8_t cdd_ww_3_1; + int8_t cdd_ww_3_0; + int8_t cdd_ww_2_3; + int8_t cdd_ww_2_1; + int8_t cdd_ww_2_0; + int8_t cdd_ww_1_3; + int8_t cdd_ww_1_2; + int8_t cdd_ww_1_0; + int8_t cdd_ww_0_3; + int8_t cdd_ww_0_2; + int8_t cdd_ww_0_1; + int8_t cdd_rw_3_3; + int8_t cdd_rw_3_2; + int8_t cdd_rw_3_1; + int8_t cdd_rw_3_0; + int8_t cdd_rw_2_3; + int8_t cdd_rw_2_2; + int8_t cdd_rw_2_1; + int8_t cdd_rw_2_0; + int8_t cdd_rw_1_3; + int8_t cdd_rw_1_2; + int8_t cdd_rw_1_1; + int8_t cdd_rw_1_0; + int8_t cdd_rw_0_3; + int8_t cdd_rw_0_2; + int8_t cdd_rw_0_1; + int8_t cdd_rw_0_0; + int8_t cdd_wr_3_3; + int8_t cdd_wr_3_2; + int8_t cdd_wr_3_1; + int8_t cdd_wr_3_0; + int8_t cdd_wr_2_3; + int8_t cdd_wr_2_2; + int8_t cdd_wr_2_1; + int8_t cdd_wr_2_0; + int8_t cdd_wr_1_3; + int8_t cdd_wr_1_2; + int8_t cdd_wr_1_1; + int8_t cdd_wr_1_0; + int8_t cdd_wr_0_3; + int8_t cdd_wr_0_2; + int8_t cdd_wr_0_1; + int8_t cdd_wr_0_0; + uint8_t reserved5d; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t bc00_d0; + uint8_t bc01_d0; + uint8_t bc02_d0; + uint8_t bc03_d0; + uint8_t bc04_d0; + uint8_t bc05_d0; + uint8_t bc06_d0; + uint8_t bc07_d0; + uint8_t bc08_d0; + uint8_t bc09_d0; + uint8_t bc0a_d0; + uint8_t bc0b_d0; + uint8_t bc0c_d0; + uint8_t bc0d_d0; + uint8_t bc0e_d0; + uint8_t f0bc6x_d0; + uint8_t f0bccx_d0; + uint8_t f0bcdx_d0; + uint8_t f0bcex_d0; + uint8_t f0bcfx_d0; + uint8_t f1bccx_d0; + uint8_t f1bcdx_d0; + uint8_t f1bcex_d0; + uint8_t f1bcfx_d0; + uint8_t f0bc2x_b0_d0; + uint8_t f0bc3x_b0_d0; + uint8_t f0bc4x_b0_d0; + uint8_t f0bc5x_b0_d0; + uint8_t f0bc8x_b0_d0; + uint8_t f0bc9x_b0_d0; + uint8_t f0bcax_b0_d0; + uint8_t f0bcbx_b0_d0; + uint8_t f1bc2x_b0_d0; + uint8_t f1bc3x_b0_d0; + uint8_t f1bc4x_b0_d0; + uint8_t f1bc5x_b0_d0; + uint8_t f1bc8x_b0_d0; + uint8_t f1bc9x_b0_d0; + uint8_t f1bcax_b0_d0; + uint8_t f1bcbx_b0_d0; + uint8_t f2bc2x_b0_d0; + uint8_t f2bc3x_b0_d0; + uint8_t f2bc4x_b0_d0; + uint8_t f2bc5x_b0_d0; + uint8_t f2bc8x_b0_d0; + uint8_t f2bc9x_b0_d0; + uint8_t f2bcax_b0_d0; + uint8_t f2bcbx_b0_d0; + uint8_t f3bc2x_b0_d0; + uint8_t f3bc3x_b0_d0; + uint8_t f3bc4x_b0_d0; + uint8_t f3bc5x_b0_d0; + uint8_t f3bc8x_b0_d0; + uint8_t f3bc9x_b0_d0; + uint8_t f3bcax_b0_d0; + uint8_t f3bcbx_b0_d0; + uint8_t f0bc2x_b1_d0; + uint8_t f0bc3x_b1_d0; + uint8_t f0bc4x_b1_d0; + uint8_t f0bc5x_b1_d0; + uint8_t f0bc8x_b1_d0; + uint8_t f0bc9x_b1_d0; + uint8_t f0bcax_b1_d0; + uint8_t f0bcbx_b1_d0; + uint8_t f1bc2x_b1_d0; + uint8_t f1bc3x_b1_d0; + uint8_t f1bc4x_b1_d0; + uint8_t f1bc5x_b1_d0; + uint8_t f1bc8x_b1_d0; + uint8_t f1bc9x_b1_d0; + uint8_t f1bcax_b1_d0; + uint8_t f1bcbx_b1_d0; + uint8_t f2bc2x_b1_d0; + uint8_t f2bc3x_b1_d0; + uint8_t f2bc4x_b1_d0; + uint8_t f2bc5x_b1_d0; + uint8_t f2bc8x_b1_d0; + uint8_t f2bc9x_b1_d0; + uint8_t f2bcax_b1_d0; + uint8_t f2bcbx_b1_d0; + uint8_t f3bc2x_b1_d0; + uint8_t f3bc3x_b1_d0; + uint8_t f3bc4x_b1_d0; + uint8_t f3bc5x_b1_d0; + uint8_t f3bc8x_b1_d0; + uint8_t f3bc9x_b1_d0; + uint8_t f3bcax_b1_d0; + uint8_t f3bcbx_b1_d0; + uint8_t f0bc2x_b2_d0; + uint8_t f0bc3x_b2_d0; + uint8_t f0bc4x_b2_d0; + uint8_t f0bc5x_b2_d0; + uint8_t f0bc8x_b2_d0; + uint8_t f0bc9x_b2_d0; + uint8_t f0bcax_b2_d0; + uint8_t f0bcbx_b2_d0; + uint8_t f1bc2x_b2_d0; + uint8_t f1bc3x_b2_d0; + uint8_t f1bc4x_b2_d0; + uint8_t f1bc5x_b2_d0; + uint8_t f1bc8x_b2_d0; + uint8_t f1bc9x_b2_d0; + uint8_t f1bcax_b2_d0; + uint8_t f1bcbx_b2_d0; + uint8_t f2bc2x_b2_d0; + uint8_t f2bc3x_b2_d0; + uint8_t f2bc4x_b2_d0; + uint8_t f2bc5x_b2_d0; + uint8_t f2bc8x_b2_d0; + uint8_t f2bc9x_b2_d0; + uint8_t f2bcax_b2_d0; + uint8_t f2bcbx_b2_d0; + uint8_t f3bc2x_b2_d0; + uint8_t f3bc3x_b2_d0; + uint8_t f3bc4x_b2_d0; + uint8_t f3bc5x_b2_d0; + uint8_t f3bc8x_b2_d0; + uint8_t f3bc9x_b2_d0; + uint8_t f3bcax_b2_d0; + uint8_t f3bcbx_b2_d0; + uint8_t f0bc2x_b3_d0; + uint8_t f0bc3x_b3_d0; + uint8_t f0bc4x_b3_d0; + uint8_t f0bc5x_b3_d0; + uint8_t f0bc8x_b3_d0; + uint8_t f0bc9x_b3_d0; + uint8_t f0bcax_b3_d0; + uint8_t f0bcbx_b3_d0; + uint8_t f1bc2x_b3_d0; + uint8_t f1bc3x_b3_d0; + uint8_t f1bc4x_b3_d0; + uint8_t f1bc5x_b3_d0; + uint8_t f1bc8x_b3_d0; + uint8_t f1bc9x_b3_d0; + uint8_t f1bcax_b3_d0; + uint8_t f1bcbx_b3_d0; + uint8_t f2bc2x_b3_d0; + uint8_t f2bc3x_b3_d0; + uint8_t f2bc4x_b3_d0; + uint8_t f2bc5x_b3_d0; + uint8_t f2bc8x_b3_d0; + uint8_t f2bc9x_b3_d0; + uint8_t f2bcax_b3_d0; + uint8_t f2bcbx_b3_d0; + uint8_t f3bc2x_b3_d0; + uint8_t f3bc3x_b3_d0; + uint8_t f3bc4x_b3_d0; + uint8_t f3bc5x_b3_d0; + uint8_t f3bc8x_b3_d0; + uint8_t f3bc9x_b3_d0; + uint8_t f3bcax_b3_d0; + uint8_t f3bcbx_b3_d0; + uint8_t f0bc2x_b4_d0; + uint8_t f0bc3x_b4_d0; + uint8_t f0bc4x_b4_d0; + uint8_t f0bc5x_b4_d0; + uint8_t f0bc8x_b4_d0; + uint8_t f0bc9x_b4_d0; + uint8_t f0bcax_b4_d0; + uint8_t f0bcbx_b4_d0; + uint8_t f1bc2x_b4_d0; + uint8_t f1bc3x_b4_d0; + uint8_t f1bc4x_b4_d0; + uint8_t f1bc5x_b4_d0; + uint8_t f1bc8x_b4_d0; + uint8_t f1bc9x_b4_d0; + uint8_t f1bcax_b4_d0; + uint8_t f1bcbx_b4_d0; + uint8_t f2bc2x_b4_d0; + uint8_t f2bc3x_b4_d0; + uint8_t f2bc4x_b4_d0; + uint8_t f2bc5x_b4_d0; + uint8_t f2bc8x_b4_d0; + uint8_t f2bc9x_b4_d0; + uint8_t f2bcax_b4_d0; + uint8_t f2bcbx_b4_d0; + uint8_t f3bc2x_b4_d0; + uint8_t f3bc3x_b4_d0; + uint8_t f3bc4x_b4_d0; + uint8_t f3bc5x_b4_d0; + uint8_t f3bc8x_b4_d0; + uint8_t f3bc9x_b4_d0; + uint8_t f3bcax_b4_d0; + uint8_t f3bcbx_b4_d0; + uint8_t f0bc2x_b5_d0; + uint8_t f0bc3x_b5_d0; + uint8_t f0bc4x_b5_d0; + uint8_t f0bc5x_b5_d0; + uint8_t f0bc8x_b5_d0; + uint8_t f0bc9x_b5_d0; + uint8_t f0bcax_b5_d0; + uint8_t f0bcbx_b5_d0; + uint8_t f1bc2x_b5_d0; + uint8_t f1bc3x_b5_d0; + uint8_t f1bc4x_b5_d0; + uint8_t f1bc5x_b5_d0; + uint8_t f1bc8x_b5_d0; + uint8_t f1bc9x_b5_d0; + uint8_t f1bcax_b5_d0; + uint8_t f1bcbx_b5_d0; + uint8_t f2bc2x_b5_d0; + uint8_t f2bc3x_b5_d0; + uint8_t f2bc4x_b5_d0; + uint8_t f2bc5x_b5_d0; + uint8_t f2bc8x_b5_d0; + uint8_t f2bc9x_b5_d0; + uint8_t f2bcax_b5_d0; + uint8_t f2bcbx_b5_d0; + uint8_t f3bc2x_b5_d0; + uint8_t f3bc3x_b5_d0; + uint8_t f3bc4x_b5_d0; + uint8_t f3bc5x_b5_d0; + uint8_t f3bc8x_b5_d0; + uint8_t f3bc9x_b5_d0; + uint8_t f3bcax_b5_d0; + uint8_t f3bcbx_b5_d0; + uint8_t f0bc2x_b6_d0; + uint8_t f0bc3x_b6_d0; + uint8_t f0bc4x_b6_d0; + uint8_t f0bc5x_b6_d0; + uint8_t f0bc8x_b6_d0; + uint8_t f0bc9x_b6_d0; + uint8_t f0bcax_b6_d0; + uint8_t f0bcbx_b6_d0; + uint8_t f1bc2x_b6_d0; + uint8_t f1bc3x_b6_d0; + uint8_t f1bc4x_b6_d0; + uint8_t f1bc5x_b6_d0; + uint8_t f1bc8x_b6_d0; + uint8_t f1bc9x_b6_d0; + uint8_t f1bcax_b6_d0; + uint8_t f1bcbx_b6_d0; + uint8_t f2bc2x_b6_d0; + uint8_t f2bc3x_b6_d0; + uint8_t f2bc4x_b6_d0; + uint8_t f2bc5x_b6_d0; + uint8_t f2bc8x_b6_d0; + uint8_t f2bc9x_b6_d0; + uint8_t f2bcax_b6_d0; + uint8_t f2bcbx_b6_d0; + uint8_t f3bc2x_b6_d0; + uint8_t f3bc3x_b6_d0; + uint8_t f3bc4x_b6_d0; + uint8_t f3bc5x_b6_d0; + uint8_t f3bc8x_b6_d0; + uint8_t f3bc9x_b6_d0; + uint8_t f3bcax_b6_d0; + uint8_t f3bcbx_b6_d0; + uint8_t f0bc2x_b7_d0; + uint8_t f0bc3x_b7_d0; + uint8_t f0bc4x_b7_d0; + uint8_t f0bc5x_b7_d0; + uint8_t f0bc8x_b7_d0; + uint8_t f0bc9x_b7_d0; + uint8_t f0bcax_b7_d0; + uint8_t f0bcbx_b7_d0; + uint8_t f1bc2x_b7_d0; + uint8_t f1bc3x_b7_d0; + uint8_t f1bc4x_b7_d0; + uint8_t f1bc5x_b7_d0; + uint8_t f1bc8x_b7_d0; + uint8_t f1bc9x_b7_d0; + uint8_t f1bcax_b7_d0; + uint8_t f1bcbx_b7_d0; + uint8_t f2bc2x_b7_d0; + uint8_t f2bc3x_b7_d0; + uint8_t f2bc4x_b7_d0; + uint8_t f2bc5x_b7_d0; + uint8_t f2bc8x_b7_d0; + uint8_t f2bc9x_b7_d0; + uint8_t f2bcax_b7_d0; + uint8_t f2bcbx_b7_d0; + uint8_t f3bc2x_b7_d0; + uint8_t f3bc3x_b7_d0; + uint8_t f3bc4x_b7_d0; + uint8_t f3bc5x_b7_d0; + uint8_t f3bc8x_b7_d0; + uint8_t f3bc9x_b7_d0; + uint8_t f3bcax_b7_d0; + uint8_t f3bcbx_b7_d0; + uint8_t f0bc2x_b8_d0; + uint8_t f0bc3x_b8_d0; + uint8_t f0bc4x_b8_d0; + uint8_t f0bc5x_b8_d0; + uint8_t f0bc8x_b8_d0; + uint8_t f0bc9x_b8_d0; + uint8_t f0bcax_b8_d0; + uint8_t f0bcbx_b8_d0; + uint8_t f1bc2x_b8_d0; + uint8_t f1bc3x_b8_d0; + uint8_t f1bc4x_b8_d0; + uint8_t f1bc5x_b8_d0; + uint8_t f1bc8x_b8_d0; + uint8_t f1bc9x_b8_d0; + uint8_t f1bcax_b8_d0; + uint8_t f1bcbx_b8_d0; + uint8_t f2bc2x_b8_d0; + uint8_t f2bc3x_b8_d0; + uint8_t f2bc4x_b8_d0; + uint8_t f2bc5x_b8_d0; + uint8_t f2bc8x_b8_d0; + uint8_t f2bc9x_b8_d0; + uint8_t f2bcax_b8_d0; + uint8_t f2bcbx_b8_d0; + uint8_t f3bc2x_b8_d0; + uint8_t f3bc3x_b8_d0; + uint8_t f3bc4x_b8_d0; + uint8_t f3bc5x_b8_d0; + uint8_t f3bc8x_b8_d0; + uint8_t f3bc9x_b8_d0; + uint8_t f3bcax_b8_d0; + uint8_t f3bcbx_b8_d0; + uint8_t f5bc5x_d0; + uint8_t f5bc6x_d0; + uint8_t f4bc8x_d0; + uint8_t f4bc9x_d0; + uint8_t f4bcax_d0; + uint8_t f4bcbx_d0; + uint8_t f4bccx_d0; + uint8_t f4bcdx_d0; + uint8_t f4bcex_d0; + uint8_t f4bcfx_d0; + uint8_t f5bc8x_d0; + uint8_t f5bc9x_d0; + uint8_t f5bcax_d0; + uint8_t f5bcbx_d0; + uint8_t f5bccx_d0; + uint8_t f5bcdx_d0; + uint8_t f5bcex_d0; + uint8_t f5bcfx_d0; + uint8_t f6bc8x_d0; + uint8_t f6bc9x_d0; + uint8_t f6bcax_d0; + uint8_t f6bcbx_d0; + uint8_t f6bccx_d0; + uint8_t f6bcdx_d0; + uint8_t f6bcex_d0; + uint8_t f6bcfx_d0; + uint8_t f7bc8x_d0; + uint8_t f7bc9x_d0; + uint8_t f7bcax_d0; + uint8_t f7bcbx_d0; + uint8_t f7bccx_d0; + uint8_t f7bcdx_d0; + uint8_t f7bcex_d0; + uint8_t f7bcfx_d0; + uint8_t bc00_d1; + uint8_t bc01_d1; + uint8_t bc02_d1; + uint8_t bc03_d1; + uint8_t bc04_d1; + uint8_t bc05_d1; + uint8_t bc06_d1; + uint8_t bc07_d1; + uint8_t bc08_d1; + uint8_t bc09_d1; + uint8_t bc0a_d1; + uint8_t bc0b_d1; + uint8_t bc0c_d1; + uint8_t bc0d_d1; + uint8_t bc0e_d1; + uint8_t f0bc6x_d1; + uint8_t f0bccx_d1; + uint8_t f0bcdx_d1; + uint8_t f0bcex_d1; + uint8_t f0bcfx_d1; + uint8_t f1bccx_d1; + uint8_t f1bcdx_d1; + uint8_t f1bcex_d1; + uint8_t f1bcfx_d1; + uint8_t f0bc2x_b0_d1; + uint8_t f0bc3x_b0_d1; + uint8_t f0bc4x_b0_d1; + uint8_t f0bc5x_b0_d1; + uint8_t f0bc8x_b0_d1; + uint8_t f0bc9x_b0_d1; + uint8_t f0bcax_b0_d1; + uint8_t f0bcbx_b0_d1; + uint8_t f1bc2x_b0_d1; + uint8_t f1bc3x_b0_d1; + uint8_t f1bc4x_b0_d1; + uint8_t f1bc5x_b0_d1; + uint8_t f1bc8x_b0_d1; + uint8_t f1bc9x_b0_d1; + uint8_t f1bcax_b0_d1; + uint8_t f1bcbx_b0_d1; + uint8_t f2bc2x_b0_d1; + uint8_t f2bc3x_b0_d1; + uint8_t f2bc4x_b0_d1; + uint8_t f2bc5x_b0_d1; + uint8_t f2bc8x_b0_d1; + uint8_t f2bc9x_b0_d1; + uint8_t f2bcax_b0_d1; + uint8_t f2bcbx_b0_d1; + uint8_t f3bc2x_b0_d1; + uint8_t f3bc3x_b0_d1; + uint8_t f3bc4x_b0_d1; + uint8_t f3bc5x_b0_d1; + uint8_t f3bc8x_b0_d1; + uint8_t f3bc9x_b0_d1; + uint8_t f3bcax_b0_d1; + uint8_t f3bcbx_b0_d1; + uint8_t f0bc2x_b1_d1; + uint8_t f0bc3x_b1_d1; + uint8_t f0bc4x_b1_d1; + uint8_t f0bc5x_b1_d1; + uint8_t f0bc8x_b1_d1; + uint8_t f0bc9x_b1_d1; + uint8_t f0bcax_b1_d1; + uint8_t f0bcbx_b1_d1; + uint8_t f1bc2x_b1_d1; + uint8_t f1bc3x_b1_d1; + uint8_t f1bc4x_b1_d1; + uint8_t f1bc5x_b1_d1; + uint8_t f1bc8x_b1_d1; + uint8_t f1bc9x_b1_d1; + uint8_t f1bcax_b1_d1; + uint8_t f1bcbx_b1_d1; + uint8_t f2bc2x_b1_d1; + uint8_t f2bc3x_b1_d1; + uint8_t f2bc4x_b1_d1; + uint8_t f2bc5x_b1_d1; + uint8_t f2bc8x_b1_d1; + uint8_t f2bc9x_b1_d1; + uint8_t f2bcax_b1_d1; + uint8_t f2bcbx_b1_d1; + uint8_t f3bc2x_b1_d1; + uint8_t f3bc3x_b1_d1; + uint8_t f3bc4x_b1_d1; + uint8_t f3bc5x_b1_d1; + uint8_t f3bc8x_b1_d1; + uint8_t f3bc9x_b1_d1; + uint8_t f3bcax_b1_d1; + uint8_t f3bcbx_b1_d1; + uint8_t f0bc2x_b2_d1; + uint8_t f0bc3x_b2_d1; + uint8_t f0bc4x_b2_d1; + uint8_t f0bc5x_b2_d1; + uint8_t f0bc8x_b2_d1; + uint8_t f0bc9x_b2_d1; + uint8_t f0bcax_b2_d1; + uint8_t f0bcbx_b2_d1; + uint8_t f1bc2x_b2_d1; + uint8_t f1bc3x_b2_d1; + uint8_t f1bc4x_b2_d1; + uint8_t f1bc5x_b2_d1; + uint8_t f1bc8x_b2_d1; + uint8_t f1bc9x_b2_d1; + uint8_t f1bcax_b2_d1; + uint8_t f1bcbx_b2_d1; + uint8_t f2bc2x_b2_d1; + uint8_t f2bc3x_b2_d1; + uint8_t f2bc4x_b2_d1; + uint8_t f2bc5x_b2_d1; + uint8_t f2bc8x_b2_d1; + uint8_t f2bc9x_b2_d1; + uint8_t f2bcax_b2_d1; + uint8_t f2bcbx_b2_d1; + uint8_t f3bc2x_b2_d1; + uint8_t f3bc3x_b2_d1; + uint8_t f3bc4x_b2_d1; + uint8_t f3bc5x_b2_d1; + uint8_t f3bc8x_b2_d1; + uint8_t f3bc9x_b2_d1; + uint8_t f3bcax_b2_d1; + uint8_t f3bcbx_b2_d1; + uint8_t f0bc2x_b3_d1; + uint8_t f0bc3x_b3_d1; + uint8_t f0bc4x_b3_d1; + uint8_t f0bc5x_b3_d1; + uint8_t f0bc8x_b3_d1; + uint8_t f0bc9x_b3_d1; + uint8_t f0bcax_b3_d1; + uint8_t f0bcbx_b3_d1; + uint8_t f1bc2x_b3_d1; + uint8_t f1bc3x_b3_d1; + uint8_t f1bc4x_b3_d1; + uint8_t f1bc5x_b3_d1; + uint8_t f1bc8x_b3_d1; + uint8_t f1bc9x_b3_d1; + uint8_t f1bcax_b3_d1; + uint8_t f1bcbx_b3_d1; + uint8_t f2bc2x_b3_d1; + uint8_t f2bc3x_b3_d1; + uint8_t f2bc4x_b3_d1; + uint8_t f2bc5x_b3_d1; + uint8_t f2bc8x_b3_d1; + uint8_t f2bc9x_b3_d1; + uint8_t f2bcax_b3_d1; + uint8_t f2bcbx_b3_d1; + uint8_t f3bc2x_b3_d1; + uint8_t f3bc3x_b3_d1; + uint8_t f3bc4x_b3_d1; + uint8_t f3bc5x_b3_d1; + uint8_t f3bc8x_b3_d1; + uint8_t f3bc9x_b3_d1; + uint8_t f3bcax_b3_d1; + uint8_t f3bcbx_b3_d1; + uint8_t f0bc2x_b4_d1; + uint8_t f0bc3x_b4_d1; + uint8_t f0bc4x_b4_d1; + uint8_t f0bc5x_b4_d1; + uint8_t f0bc8x_b4_d1; + uint8_t f0bc9x_b4_d1; + uint8_t f0bcax_b4_d1; + uint8_t f0bcbx_b4_d1; + uint8_t f1bc2x_b4_d1; + uint8_t f1bc3x_b4_d1; + uint8_t f1bc4x_b4_d1; + uint8_t f1bc5x_b4_d1; + uint8_t f1bc8x_b4_d1; + uint8_t f1bc9x_b4_d1; + uint8_t f1bcax_b4_d1; + uint8_t f1bcbx_b4_d1; + uint8_t f2bc2x_b4_d1; + uint8_t f2bc3x_b4_d1; + uint8_t f2bc4x_b4_d1; + uint8_t f2bc5x_b4_d1; + uint8_t f2bc8x_b4_d1; + uint8_t f2bc9x_b4_d1; + uint8_t f2bcax_b4_d1; + uint8_t f2bcbx_b4_d1; + uint8_t f3bc2x_b4_d1; + uint8_t f3bc3x_b4_d1; + uint8_t f3bc4x_b4_d1; + uint8_t f3bc5x_b4_d1; + uint8_t f3bc8x_b4_d1; + uint8_t f3bc9x_b4_d1; + uint8_t f3bcax_b4_d1; + uint8_t f3bcbx_b4_d1; + uint8_t f0bc2x_b5_d1; + uint8_t f0bc3x_b5_d1; + uint8_t f0bc4x_b5_d1; + uint8_t f0bc5x_b5_d1; + uint8_t f0bc8x_b5_d1; + uint8_t f0bc9x_b5_d1; + uint8_t f0bcax_b5_d1; + uint8_t f0bcbx_b5_d1; + uint8_t f1bc2x_b5_d1; + uint8_t f1bc3x_b5_d1; + uint8_t f1bc4x_b5_d1; + uint8_t f1bc5x_b5_d1; + uint8_t f1bc8x_b5_d1; + uint8_t f1bc9x_b5_d1; + uint8_t f1bcax_b5_d1; + uint8_t f1bcbx_b5_d1; + uint8_t f2bc2x_b5_d1; + uint8_t f2bc3x_b5_d1; + uint8_t f2bc4x_b5_d1; + uint8_t f2bc5x_b5_d1; + uint8_t f2bc8x_b5_d1; + uint8_t f2bc9x_b5_d1; + uint8_t f2bcax_b5_d1; + uint8_t f2bcbx_b5_d1; + uint8_t f3bc2x_b5_d1; + uint8_t f3bc3x_b5_d1; + uint8_t f3bc4x_b5_d1; + uint8_t f3bc5x_b5_d1; + uint8_t f3bc8x_b5_d1; + uint8_t f3bc9x_b5_d1; + uint8_t f3bcax_b5_d1; + uint8_t f3bcbx_b5_d1; + uint8_t f0bc2x_b6_d1; + uint8_t f0bc3x_b6_d1; + uint8_t f0bc4x_b6_d1; + uint8_t f0bc5x_b6_d1; + uint8_t f0bc8x_b6_d1; + uint8_t f0bc9x_b6_d1; + uint8_t f0bcax_b6_d1; + uint8_t f0bcbx_b6_d1; + uint8_t f1bc2x_b6_d1; + uint8_t f1bc3x_b6_d1; + uint8_t f1bc4x_b6_d1; + uint8_t f1bc5x_b6_d1; + uint8_t f1bc8x_b6_d1; + uint8_t f1bc9x_b6_d1; + uint8_t f1bcax_b6_d1; + uint8_t f1bcbx_b6_d1; + uint8_t f2bc2x_b6_d1; + uint8_t f2bc3x_b6_d1; + uint8_t f2bc4x_b6_d1; + uint8_t f2bc5x_b6_d1; + uint8_t f2bc8x_b6_d1; + uint8_t f2bc9x_b6_d1; + uint8_t f2bcax_b6_d1; + uint8_t f2bcbx_b6_d1; + uint8_t f3bc2x_b6_d1; + uint8_t f3bc3x_b6_d1; + uint8_t f3bc4x_b6_d1; + uint8_t f3bc5x_b6_d1; + uint8_t f3bc8x_b6_d1; + uint8_t f3bc9x_b6_d1; + uint8_t f3bcax_b6_d1; + uint8_t f3bcbx_b6_d1; + uint8_t f0bc2x_b7_d1; + uint8_t f0bc3x_b7_d1; + uint8_t f0bc4x_b7_d1; + uint8_t f0bc5x_b7_d1; + uint8_t f0bc8x_b7_d1; + uint8_t f0bc9x_b7_d1; + uint8_t f0bcax_b7_d1; + uint8_t f0bcbx_b7_d1; + uint8_t f1bc2x_b7_d1; + uint8_t f1bc3x_b7_d1; + uint8_t f1bc4x_b7_d1; + uint8_t f1bc5x_b7_d1; + uint8_t f1bc8x_b7_d1; + uint8_t f1bc9x_b7_d1; + uint8_t f1bcax_b7_d1; + uint8_t f1bcbx_b7_d1; + uint8_t f2bc2x_b7_d1; + uint8_t f2bc3x_b7_d1; + uint8_t f2bc4x_b7_d1; + uint8_t f2bc5x_b7_d1; + uint8_t f2bc8x_b7_d1; + uint8_t f2bc9x_b7_d1; + uint8_t f2bcax_b7_d1; + uint8_t f2bcbx_b7_d1; + uint8_t f3bc2x_b7_d1; + uint8_t f3bc3x_b7_d1; + uint8_t f3bc4x_b7_d1; + uint8_t f3bc5x_b7_d1; + uint8_t f3bc8x_b7_d1; + uint8_t f3bc9x_b7_d1; + uint8_t f3bcax_b7_d1; + uint8_t f3bcbx_b7_d1; + uint8_t f0bc2x_b8_d1; + uint8_t f0bc3x_b8_d1; + uint8_t f0bc4x_b8_d1; + uint8_t f0bc5x_b8_d1; + uint8_t f0bc8x_b8_d1; + uint8_t f0bc9x_b8_d1; + uint8_t f0bcax_b8_d1; + uint8_t f0bcbx_b8_d1; + uint8_t f1bc2x_b8_d1; + uint8_t f1bc3x_b8_d1; + uint8_t f1bc4x_b8_d1; + uint8_t f1bc5x_b8_d1; + uint8_t f1bc8x_b8_d1; + uint8_t f1bc9x_b8_d1; + uint8_t f1bcax_b8_d1; + uint8_t f1bcbx_b8_d1; + uint8_t f2bc2x_b8_d1; + uint8_t f2bc3x_b8_d1; + uint8_t f2bc4x_b8_d1; + uint8_t f2bc5x_b8_d1; + uint8_t f2bc8x_b8_d1; + uint8_t f2bc9x_b8_d1; + uint8_t f2bcax_b8_d1; + uint8_t f2bcbx_b8_d1; + uint8_t f3bc2x_b8_d1; + uint8_t f3bc3x_b8_d1; + uint8_t f3bc4x_b8_d1; + uint8_t f3bc5x_b8_d1; + uint8_t f3bc8x_b8_d1; + uint8_t f3bc9x_b8_d1; + uint8_t f3bcax_b8_d1; + uint8_t f3bcbx_b8_d1; + uint8_t f5bc5x_d1; + uint8_t f5bc6x_d1; + uint8_t f4bc8x_d1; + uint8_t f4bc9x_d1; + uint8_t f4bcax_d1; + uint8_t f4bcbx_d1; + uint8_t f4bccx_d1; + uint8_t f4bcdx_d1; + uint8_t f4bcex_d1; + uint8_t f4bcfx_d1; + uint8_t f5bc8x_d1; + uint8_t f5bc9x_d1; + uint8_t f5bcax_d1; + uint8_t f5bcbx_d1; + uint8_t f5bccx_d1; + uint8_t f5bcdx_d1; + uint8_t f5bcex_d1; + uint8_t f5bcfx_d1; + uint8_t f6bc8x_d1; + uint8_t f6bc9x_d1; + uint8_t f6bcax_d1; + uint8_t f6bcbx_d1; + uint8_t f6bccx_d1; + uint8_t f6bcdx_d1; + uint8_t f6bcex_d1; + uint8_t f6bcfx_d1; + uint8_t f7bc8x_d1; + uint8_t f7bc9x_d1; + uint8_t f7bcax_d1; + uint8_t f7bcbx_d1; + uint8_t f7bccx_d1; + uint8_t f7bcdx_d1; + uint8_t f7bcex_d1; + uint8_t f7bcfx_d1; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; + +struct ddr4lr2d { + uint8_t reserved00; + uint8_t msg_misc; + uint16_t pmu_revision; + uint8_t pstate; + uint8_t pll_bypass_en; + uint16_t dramfreq; + uint8_t dfi_freq_ratio; + uint8_t bpznres_val; + uint8_t phy_odt_impedance; + uint8_t phy_drv_impedance; + uint8_t phy_vref; + uint8_t dram_type; + uint8_t disabled_dbyte; + uint8_t enabled_dqs; + uint8_t cs_present; + uint8_t cs_present_d0; + uint8_t cs_present_d1; + uint8_t addr_mirror; + uint8_t cs_test_fail; + uint8_t phy_cfg; + uint16_t sequence_ctrl; + uint8_t hdt_ctrl; + uint8_t rx2d_train_opt; + uint8_t tx2d_train_opt; + uint8_t share2dvref_result; + uint8_t delay_weight2d; + uint8_t voltage_weight2d; + uint8_t reserved1e[0x22 - 0x1e]; + uint16_t phy_config_override; + uint8_t dfimrlmargin; + uint8_t r0_rx_clk_dly_margin; + uint8_t r0_vref_dac_margin; + uint8_t r0_tx_dq_dly_margin; + uint8_t r0_device_vref_margin; + uint8_t reserved29[0x33 - 0x29]; + uint8_t r1_rx_clk_dly_margin; + uint8_t r1_vref_dac_margin; + uint8_t r1_tx_dq_dly_margin; + uint8_t r1_device_vref_margin; + uint8_t reserved37[0x41 - 0x37]; + uint8_t r2_rx_clk_dly_margin; + uint8_t r2_vref_dac_margin; + uint8_t r2_tx_dq_dly_margin; + uint8_t r2_device_vref_margin; + uint8_t reserved45[0x4f - 0x45]; + uint8_t r3_rx_clk_dly_margin; + uint8_t r3_vref_dac_margin; + uint8_t r3_tx_dq_dly_margin; + uint8_t r3_device_vref_margin; + uint8_t reserved53[0x5e - 0x53]; + uint16_t mr0; + uint16_t mr1; + uint16_t mr2; + uint16_t mr3; + uint16_t mr4; + uint16_t mr5; + uint16_t mr6; + uint8_t x16present; + uint8_t cs_setup_gddec; + uint16_t rtt_nom_wr_park0; + uint16_t rtt_nom_wr_park1; + uint16_t rtt_nom_wr_park2; + uint16_t rtt_nom_wr_park3; + uint16_t rtt_nom_wr_park4; + uint16_t rtt_nom_wr_park5; + uint16_t rtt_nom_wr_park6; + uint16_t rtt_nom_wr_park7; + uint8_t acsm_odt_ctrl0; + uint8_t acsm_odt_ctrl1; + uint8_t acsm_odt_ctrl2; + uint8_t acsm_odt_ctrl3; + uint8_t acsm_odt_ctrl4; + uint8_t acsm_odt_ctrl5; + uint8_t acsm_odt_ctrl6; + uint8_t acsm_odt_ctrl7; + uint8_t vref_dq_r0nib0; + uint8_t vref_dq_r0nib1; + uint8_t vref_dq_r0nib2; + uint8_t vref_dq_r0nib3; + uint8_t vref_dq_r0nib4; + uint8_t vref_dq_r0nib5; + uint8_t vref_dq_r0nib6; + uint8_t vref_dq_r0nib7; + uint8_t vref_dq_r0nib8; + uint8_t vref_dq_r0nib9; + uint8_t vref_dq_r0nib10; + uint8_t vref_dq_r0nib11; + uint8_t vref_dq_r0nib12; + uint8_t vref_dq_r0nib13; + uint8_t vref_dq_r0nib14; + uint8_t vref_dq_r0nib15; + uint8_t vref_dq_r0nib16; + uint8_t vref_dq_r0nib17; + uint8_t vref_dq_r0nib18; + uint8_t vref_dq_r0nib19; + uint8_t vref_dq_r1nib0; + uint8_t vref_dq_r1nib1; + uint8_t vref_dq_r1nib2; + uint8_t vref_dq_r1nib3; + uint8_t vref_dq_r1nib4; + uint8_t vref_dq_r1nib5; + uint8_t vref_dq_r1nib6; + uint8_t vref_dq_r1nib7; + uint8_t vref_dq_r1nib8; + uint8_t vref_dq_r1nib9; + uint8_t vref_dq_r1nib10; + uint8_t vref_dq_r1nib11; + uint8_t vref_dq_r1nib12; + uint8_t vref_dq_r1nib13; + uint8_t vref_dq_r1nib14; + uint8_t vref_dq_r1nib15; + uint8_t vref_dq_r1nib16; + uint8_t vref_dq_r1nib17; + uint8_t vref_dq_r1nib18; + uint8_t vref_dq_r1nib19; + uint8_t vref_dq_r2nib0; + uint8_t vref_dq_r2nib1; + uint8_t vref_dq_r2nib2; + uint8_t vref_dq_r2nib3; + uint8_t vref_dq_r2nib4; + uint8_t vref_dq_r2nib5; + uint8_t vref_dq_r2nib6; + uint8_t vref_dq_r2nib7; + uint8_t vref_dq_r2nib8; + uint8_t vref_dq_r2nib9; + uint8_t vref_dq_r2nib10; + uint8_t vref_dq_r2nib11; + uint8_t vref_dq_r2nib12; + uint8_t vref_dq_r2nib13; + uint8_t vref_dq_r2nib14; + uint8_t vref_dq_r2nib15; + uint8_t vref_dq_r2nib16; + uint8_t vref_dq_r2nib17; + uint8_t vref_dq_r2nib18; + uint8_t vref_dq_r2nib19; + uint8_t vref_dq_r3nib0; + uint8_t vref_dq_r3nib1; + uint8_t vref_dq_r3nib2; + uint8_t vref_dq_r3nib3; + uint8_t vref_dq_r3nib4; + uint8_t vref_dq_r3nib5; + uint8_t vref_dq_r3nib6; + uint8_t vref_dq_r3nib7; + uint8_t vref_dq_r3nib8; + uint8_t vref_dq_r3nib9; + uint8_t vref_dq_r3nib10; + uint8_t vref_dq_r3nib11; + uint8_t vref_dq_r3nib12; + uint8_t vref_dq_r3nib13; + uint8_t vref_dq_r3nib14; + uint8_t vref_dq_r3nib15; + uint8_t vref_dq_r3nib16; + uint8_t vref_dq_r3nib17; + uint8_t vref_dq_r3nib18; + uint8_t vref_dq_r3nib19; + uint8_t f0rc00_d0; + uint8_t f0rc01_d0; + uint8_t f0rc02_d0; + uint8_t f0rc03_d0; + uint8_t f0rc04_d0; + uint8_t f0rc05_d0; + uint8_t f0rc06_d0; + uint8_t f0rc07_d0; + uint8_t f0rc08_d0; + uint8_t f0rc09_d0; + uint8_t f0rc0a_d0; + uint8_t f0rc0b_d0; + uint8_t f0rc0c_d0; + uint8_t f0rc0d_d0; + uint8_t f0rc0e_d0; + uint8_t f0rc0f_d0; + uint8_t f0rc1x_d0; + uint8_t f0rc2x_d0; + uint8_t f0rc3x_d0; + uint8_t f0rc4x_d0; + uint8_t f0rc5x_d0; + uint8_t f0rc6x_d0; + uint8_t f0rc7x_d0; + uint8_t f0rc8x_d0; + uint8_t f0rc9x_d0; + uint8_t f0rcax_d0; + uint8_t f0rcbx_d0; + uint8_t f1rc00_d0; + uint8_t f1rc01_d0; + uint8_t f1rc02_d0; + uint8_t f1rc03_d0; + uint8_t f1rc04_d0; + uint8_t f1rc05_d0; + uint8_t f1rc06_d0; + uint8_t f1rc07_d0; + uint8_t f1rc08_d0; + uint8_t f1rc09_d0; + uint8_t f1rc0a_d0; + uint8_t f1rc0b_d0; + uint8_t f1rc0c_d0; + uint8_t f1rc0d_d0; + uint8_t f1rc0e_d0; + uint8_t f1rc0f_d0; + uint8_t f1rc1x_d0; + uint8_t f1rc2x_d0; + uint8_t f1rc3x_d0; + uint8_t f1rc4x_d0; + uint8_t f1rc5x_d0; + uint8_t f1rc6x_d0; + uint8_t f1rc7x_d0; + uint8_t f1rc8x_d0; + uint8_t f1rc9x_d0; + uint8_t f1rcax_d0; + uint8_t f1rcbx_d0; + uint8_t f0rc00_d1; + uint8_t f0rc01_d1; + uint8_t f0rc02_d1; + uint8_t f0rc03_d1; + uint8_t f0rc04_d1; + uint8_t f0rc05_d1; + uint8_t f0rc06_d1; + uint8_t f0rc07_d1; + uint8_t f0rc08_d1; + uint8_t f0rc09_d1; + uint8_t f0rc0a_d1; + uint8_t f0rc0b_d1; + uint8_t f0rc0c_d1; + uint8_t f0rc0d_d1; + uint8_t f0rc0e_d1; + uint8_t f0rc0f_d1; + uint8_t f0rc1x_d1; + uint8_t f0rc2x_d1; + uint8_t f0rc3x_d1; + uint8_t f0rc4x_d1; + uint8_t f0rc5x_d1; + uint8_t f0rc6x_d1; + uint8_t f0rc7x_d1; + uint8_t f0rc8x_d1; + uint8_t f0rc9x_d1; + uint8_t f0rcax_d1; + uint8_t f0rcbx_d1; + uint8_t f1rc00_d1; + uint8_t f1rc01_d1; + uint8_t f1rc02_d1; + uint8_t f1rc03_d1; + uint8_t f1rc04_d1; + uint8_t f1rc05_d1; + uint8_t f1rc06_d1; + uint8_t f1rc07_d1; + uint8_t f1rc08_d1; + uint8_t f1rc09_d1; + uint8_t f1rc0a_d1; + uint8_t f1rc0b_d1; + uint8_t f1rc0c_d1; + uint8_t f1rc0d_d1; + uint8_t f1rc0e_d1; + uint8_t f1rc0f_d1; + uint8_t f1rc1x_d1; + uint8_t f1rc2x_d1; + uint8_t f1rc3x_d1; + uint8_t f1rc4x_d1; + uint8_t f1rc5x_d1; + uint8_t f1rc6x_d1; + uint8_t f1rc7x_d1; + uint8_t f1rc8x_d1; + uint8_t f1rc9x_d1; + uint8_t f1rcax_d1; + uint8_t f1rcbx_d1; + uint8_t bc00_d0; + uint8_t bc01_d0; + uint8_t bc02_d0; + uint8_t bc03_d0; + uint8_t bc04_d0; + uint8_t bc05_d0; + uint8_t bc06_d0; + uint8_t bc07_d0; + uint8_t bc08_d0; + uint8_t bc09_d0; + uint8_t bc0a_d0; + uint8_t bc0b_d0; + uint8_t bc0c_d0; + uint8_t bc0d_d0; + uint8_t bc0e_d0; + uint8_t f0bc6x_d0; + uint8_t f0bccx_d0; + uint8_t f0bcdx_d0; + uint8_t f0bcex_d0; + uint8_t f0bcfx_d0; + uint8_t f1bccx_d0; + uint8_t f1bcdx_d0; + uint8_t f1bcex_d0; + uint8_t f1bcfx_d0; + uint8_t f0bc2x_b0_d0; + uint8_t f0bc3x_b0_d0; + uint8_t f0bc4x_b0_d0; + uint8_t f0bc5x_b0_d0; + uint8_t f0bc8x_b0_d0; + uint8_t f0bc9x_b0_d0; + uint8_t f0bcax_b0_d0; + uint8_t f0bcbx_b0_d0; + uint8_t f1bc2x_b0_d0; + uint8_t f1bc3x_b0_d0; + uint8_t f1bc4x_b0_d0; + uint8_t f1bc5x_b0_d0; + uint8_t f1bc8x_b0_d0; + uint8_t f1bc9x_b0_d0; + uint8_t f1bcax_b0_d0; + uint8_t f1bcbx_b0_d0; + uint8_t f2bc2x_b0_d0; + uint8_t f2bc3x_b0_d0; + uint8_t f2bc4x_b0_d0; + uint8_t f2bc5x_b0_d0; + uint8_t f2bc8x_b0_d0; + uint8_t f2bc9x_b0_d0; + uint8_t f2bcax_b0_d0; + uint8_t f2bcbx_b0_d0; + uint8_t f3bc2x_b0_d0; + uint8_t f3bc3x_b0_d0; + uint8_t f3bc4x_b0_d0; + uint8_t f3bc5x_b0_d0; + uint8_t f3bc8x_b0_d0; + uint8_t f3bc9x_b0_d0; + uint8_t f3bcax_b0_d0; + uint8_t f3bcbx_b0_d0; + uint8_t f0bc2x_b1_d0; + uint8_t f0bc3x_b1_d0; + uint8_t f0bc4x_b1_d0; + uint8_t f0bc5x_b1_d0; + uint8_t f0bc8x_b1_d0; + uint8_t f0bc9x_b1_d0; + uint8_t f0bcax_b1_d0; + uint8_t f0bcbx_b1_d0; + uint8_t f1bc2x_b1_d0; + uint8_t f1bc3x_b1_d0; + uint8_t f1bc4x_b1_d0; + uint8_t f1bc5x_b1_d0; + uint8_t f1bc8x_b1_d0; + uint8_t f1bc9x_b1_d0; + uint8_t f1bcax_b1_d0; + uint8_t f1bcbx_b1_d0; + uint8_t f2bc2x_b1_d0; + uint8_t f2bc3x_b1_d0; + uint8_t f2bc4x_b1_d0; + uint8_t f2bc5x_b1_d0; + uint8_t f2bc8x_b1_d0; + uint8_t f2bc9x_b1_d0; + uint8_t f2bcax_b1_d0; + uint8_t f2bcbx_b1_d0; + uint8_t f3bc2x_b1_d0; + uint8_t f3bc3x_b1_d0; + uint8_t f3bc4x_b1_d0; + uint8_t f3bc5x_b1_d0; + uint8_t f3bc8x_b1_d0; + uint8_t f3bc9x_b1_d0; + uint8_t f3bcax_b1_d0; + uint8_t f3bcbx_b1_d0; + uint8_t f0bc2x_b2_d0; + uint8_t f0bc3x_b2_d0; + uint8_t f0bc4x_b2_d0; + uint8_t f0bc5x_b2_d0; + uint8_t f0bc8x_b2_d0; + uint8_t f0bc9x_b2_d0; + uint8_t f0bcax_b2_d0; + uint8_t f0bcbx_b2_d0; + uint8_t f1bc2x_b2_d0; + uint8_t f1bc3x_b2_d0; + uint8_t f1bc4x_b2_d0; + uint8_t f1bc5x_b2_d0; + uint8_t f1bc8x_b2_d0; + uint8_t f1bc9x_b2_d0; + uint8_t f1bcax_b2_d0; + uint8_t f1bcbx_b2_d0; + uint8_t f2bc2x_b2_d0; + uint8_t f2bc3x_b2_d0; + uint8_t f2bc4x_b2_d0; + uint8_t f2bc5x_b2_d0; + uint8_t f2bc8x_b2_d0; + uint8_t f2bc9x_b2_d0; + uint8_t f2bcax_b2_d0; + uint8_t f2bcbx_b2_d0; + uint8_t f3bc2x_b2_d0; + uint8_t f3bc3x_b2_d0; + uint8_t f3bc4x_b2_d0; + uint8_t f3bc5x_b2_d0; + uint8_t f3bc8x_b2_d0; + uint8_t f3bc9x_b2_d0; + uint8_t f3bcax_b2_d0; + uint8_t f3bcbx_b2_d0; + uint8_t f0bc2x_b3_d0; + uint8_t f0bc3x_b3_d0; + uint8_t f0bc4x_b3_d0; + uint8_t f0bc5x_b3_d0; + uint8_t f0bc8x_b3_d0; + uint8_t f0bc9x_b3_d0; + uint8_t f0bcax_b3_d0; + uint8_t f0bcbx_b3_d0; + uint8_t f1bc2x_b3_d0; + uint8_t f1bc3x_b3_d0; + uint8_t f1bc4x_b3_d0; + uint8_t f1bc5x_b3_d0; + uint8_t f1bc8x_b3_d0; + uint8_t f1bc9x_b3_d0; + uint8_t f1bcax_b3_d0; + uint8_t f1bcbx_b3_d0; + uint8_t f2bc2x_b3_d0; + uint8_t f2bc3x_b3_d0; + uint8_t f2bc4x_b3_d0; + uint8_t f2bc5x_b3_d0; + uint8_t f2bc8x_b3_d0; + uint8_t f2bc9x_b3_d0; + uint8_t f2bcax_b3_d0; + uint8_t f2bcbx_b3_d0; + uint8_t f3bc2x_b3_d0; + uint8_t f3bc3x_b3_d0; + uint8_t f3bc4x_b3_d0; + uint8_t f3bc5x_b3_d0; + uint8_t f3bc8x_b3_d0; + uint8_t f3bc9x_b3_d0; + uint8_t f3bcax_b3_d0; + uint8_t f3bcbx_b3_d0; + uint8_t f0bc2x_b4_d0; + uint8_t f0bc3x_b4_d0; + uint8_t f0bc4x_b4_d0; + uint8_t f0bc5x_b4_d0; + uint8_t f0bc8x_b4_d0; + uint8_t f0bc9x_b4_d0; + uint8_t f0bcax_b4_d0; + uint8_t f0bcbx_b4_d0; + uint8_t f1bc2x_b4_d0; + uint8_t f1bc3x_b4_d0; + uint8_t f1bc4x_b4_d0; + uint8_t f1bc5x_b4_d0; + uint8_t f1bc8x_b4_d0; + uint8_t f1bc9x_b4_d0; + uint8_t f1bcax_b4_d0; + uint8_t f1bcbx_b4_d0; + uint8_t f2bc2x_b4_d0; + uint8_t f2bc3x_b4_d0; + uint8_t f2bc4x_b4_d0; + uint8_t f2bc5x_b4_d0; + uint8_t f2bc8x_b4_d0; + uint8_t f2bc9x_b4_d0; + uint8_t f2bcax_b4_d0; + uint8_t f2bcbx_b4_d0; + uint8_t f3bc2x_b4_d0; + uint8_t f3bc3x_b4_d0; + uint8_t f3bc4x_b4_d0; + uint8_t f3bc5x_b4_d0; + uint8_t f3bc8x_b4_d0; + uint8_t f3bc9x_b4_d0; + uint8_t f3bcax_b4_d0; + uint8_t f3bcbx_b4_d0; + uint8_t f0bc2x_b5_d0; + uint8_t f0bc3x_b5_d0; + uint8_t f0bc4x_b5_d0; + uint8_t f0bc5x_b5_d0; + uint8_t f0bc8x_b5_d0; + uint8_t f0bc9x_b5_d0; + uint8_t f0bcax_b5_d0; + uint8_t f0bcbx_b5_d0; + uint8_t f1bc2x_b5_d0; + uint8_t f1bc3x_b5_d0; + uint8_t f1bc4x_b5_d0; + uint8_t f1bc5x_b5_d0; + uint8_t f1bc8x_b5_d0; + uint8_t f1bc9x_b5_d0; + uint8_t f1bcax_b5_d0; + uint8_t f1bcbx_b5_d0; + uint8_t f2bc2x_b5_d0; + uint8_t f2bc3x_b5_d0; + uint8_t f2bc4x_b5_d0; + uint8_t f2bc5x_b5_d0; + uint8_t f2bc8x_b5_d0; + uint8_t f2bc9x_b5_d0; + uint8_t f2bcax_b5_d0; + uint8_t f2bcbx_b5_d0; + uint8_t f3bc2x_b5_d0; + uint8_t f3bc3x_b5_d0; + uint8_t f3bc4x_b5_d0; + uint8_t f3bc5x_b5_d0; + uint8_t f3bc8x_b5_d0; + uint8_t f3bc9x_b5_d0; + uint8_t f3bcax_b5_d0; + uint8_t f3bcbx_b5_d0; + uint8_t f0bc2x_b6_d0; + uint8_t f0bc3x_b6_d0; + uint8_t f0bc4x_b6_d0; + uint8_t f0bc5x_b6_d0; + uint8_t f0bc8x_b6_d0; + uint8_t f0bc9x_b6_d0; + uint8_t f0bcax_b6_d0; + uint8_t f0bcbx_b6_d0; + uint8_t f1bc2x_b6_d0; + uint8_t f1bc3x_b6_d0; + uint8_t f1bc4x_b6_d0; + uint8_t f1bc5x_b6_d0; + uint8_t f1bc8x_b6_d0; + uint8_t f1bc9x_b6_d0; + uint8_t f1bcax_b6_d0; + uint8_t f1bcbx_b6_d0; + uint8_t f2bc2x_b6_d0; + uint8_t f2bc3x_b6_d0; + uint8_t f2bc4x_b6_d0; + uint8_t f2bc5x_b6_d0; + uint8_t f2bc8x_b6_d0; + uint8_t f2bc9x_b6_d0; + uint8_t f2bcax_b6_d0; + uint8_t f2bcbx_b6_d0; + uint8_t f3bc2x_b6_d0; + uint8_t f3bc3x_b6_d0; + uint8_t f3bc4x_b6_d0; + uint8_t f3bc5x_b6_d0; + uint8_t f3bc8x_b6_d0; + uint8_t f3bc9x_b6_d0; + uint8_t f3bcax_b6_d0; + uint8_t f3bcbx_b6_d0; + uint8_t f0bc2x_b7_d0; + uint8_t f0bc3x_b7_d0; + uint8_t f0bc4x_b7_d0; + uint8_t f0bc5x_b7_d0; + uint8_t f0bc8x_b7_d0; + uint8_t f0bc9x_b7_d0; + uint8_t f0bcax_b7_d0; + uint8_t f0bcbx_b7_d0; + uint8_t f1bc2x_b7_d0; + uint8_t f1bc3x_b7_d0; + uint8_t f1bc4x_b7_d0; + uint8_t f1bc5x_b7_d0; + uint8_t f1bc8x_b7_d0; + uint8_t f1bc9x_b7_d0; + uint8_t f1bcax_b7_d0; + uint8_t f1bcbx_b7_d0; + uint8_t f2bc2x_b7_d0; + uint8_t f2bc3x_b7_d0; + uint8_t f2bc4x_b7_d0; + uint8_t f2bc5x_b7_d0; + uint8_t f2bc8x_b7_d0; + uint8_t f2bc9x_b7_d0; + uint8_t f2bcax_b7_d0; + uint8_t f2bcbx_b7_d0; + uint8_t f3bc2x_b7_d0; + uint8_t f3bc3x_b7_d0; + uint8_t f3bc4x_b7_d0; + uint8_t f3bc5x_b7_d0; + uint8_t f3bc8x_b7_d0; + uint8_t f3bc9x_b7_d0; + uint8_t f3bcax_b7_d0; + uint8_t f3bcbx_b7_d0; + uint8_t f0bc2x_b8_d0; + uint8_t f0bc3x_b8_d0; + uint8_t f0bc4x_b8_d0; + uint8_t f0bc5x_b8_d0; + uint8_t f0bc8x_b8_d0; + uint8_t f0bc9x_b8_d0; + uint8_t f0bcax_b8_d0; + uint8_t f0bcbx_b8_d0; + uint8_t f1bc2x_b8_d0; + uint8_t f1bc3x_b8_d0; + uint8_t f1bc4x_b8_d0; + uint8_t f1bc5x_b8_d0; + uint8_t f1bc8x_b8_d0; + uint8_t f1bc9x_b8_d0; + uint8_t f1bcax_b8_d0; + uint8_t f1bcbx_b8_d0; + uint8_t f2bc2x_b8_d0; + uint8_t f2bc3x_b8_d0; + uint8_t f2bc4x_b8_d0; + uint8_t f2bc5x_b8_d0; + uint8_t f2bc8x_b8_d0; + uint8_t f2bc9x_b8_d0; + uint8_t f2bcax_b8_d0; + uint8_t f2bcbx_b8_d0; + uint8_t f3bc2x_b8_d0; + uint8_t f3bc3x_b8_d0; + uint8_t f3bc4x_b8_d0; + uint8_t f3bc5x_b8_d0; + uint8_t f3bc8x_b8_d0; + uint8_t f3bc9x_b8_d0; + uint8_t f3bcax_b8_d0; + uint8_t f3bcbx_b8_d0; + uint8_t f5bc5x_d0; + uint8_t f5bc6x_d0; + uint8_t f4bc8x_d0; + uint8_t f4bc9x_d0; + uint8_t f4bcax_d0; + uint8_t f4bcbx_d0; + uint8_t f4bccx_d0; + uint8_t f4bcdx_d0; + uint8_t f4bcex_d0; + uint8_t f4bcfx_d0; + uint8_t f5bc8x_d0; + uint8_t f5bc9x_d0; + uint8_t f5bcax_d0; + uint8_t f5bcbx_d0; + uint8_t f5bccx_d0; + uint8_t f5bcdx_d0; + uint8_t f5bcex_d0; + uint8_t f5bcfx_d0; + uint8_t f6bc8x_d0; + uint8_t f6bc9x_d0; + uint8_t f6bcax_d0; + uint8_t f6bcbx_d0; + uint8_t f6bccx_d0; + uint8_t f6bcdx_d0; + uint8_t f6bcex_d0; + uint8_t f6bcfx_d0; + uint8_t f7bc8x_d0; + uint8_t f7bc9x_d0; + uint8_t f7bcax_d0; + uint8_t f7bcbx_d0; + uint8_t f7bccx_d0; + uint8_t f7bcdx_d0; + uint8_t f7bcex_d0; + uint8_t f7bcfx_d0; + uint8_t bc00_d1; + uint8_t bc01_d1; + uint8_t bc02_d1; + uint8_t bc03_d1; + uint8_t bc04_d1; + uint8_t bc05_d1; + uint8_t bc06_d1; + uint8_t bc07_d1; + uint8_t bc08_d1; + uint8_t bc09_d1; + uint8_t bc0a_d1; + uint8_t bc0b_d1; + uint8_t bc0c_d1; + uint8_t bc0d_d1; + uint8_t bc0e_d1; + uint8_t f0bc6x_d1; + uint8_t f0bccx_d1; + uint8_t f0bcdx_d1; + uint8_t f0bcex_d1; + uint8_t f0bcfx_d1; + uint8_t f1bccx_d1; + uint8_t f1bcdx_d1; + uint8_t f1bcex_d1; + uint8_t f1bcfx_d1; + uint8_t f0bc2x_b0_d1; + uint8_t f0bc3x_b0_d1; + uint8_t f0bc4x_b0_d1; + uint8_t f0bc5x_b0_d1; + uint8_t f0bc8x_b0_d1; + uint8_t f0bc9x_b0_d1; + uint8_t f0bcax_b0_d1; + uint8_t f0bcbx_b0_d1; + uint8_t f1bc2x_b0_d1; + uint8_t f1bc3x_b0_d1; + uint8_t f1bc4x_b0_d1; + uint8_t f1bc5x_b0_d1; + uint8_t f1bc8x_b0_d1; + uint8_t f1bc9x_b0_d1; + uint8_t f1bcax_b0_d1; + uint8_t f1bcbx_b0_d1; + uint8_t f2bc2x_b0_d1; + uint8_t f2bc3x_b0_d1; + uint8_t f2bc4x_b0_d1; + uint8_t f2bc5x_b0_d1; + uint8_t f2bc8x_b0_d1; + uint8_t f2bc9x_b0_d1; + uint8_t f2bcax_b0_d1; + uint8_t f2bcbx_b0_d1; + uint8_t f3bc2x_b0_d1; + uint8_t f3bc3x_b0_d1; + uint8_t f3bc4x_b0_d1; + uint8_t f3bc5x_b0_d1; + uint8_t f3bc8x_b0_d1; + uint8_t f3bc9x_b0_d1; + uint8_t f3bcax_b0_d1; + uint8_t f3bcbx_b0_d1; + uint8_t f0bc2x_b1_d1; + uint8_t f0bc3x_b1_d1; + uint8_t f0bc4x_b1_d1; + uint8_t f0bc5x_b1_d1; + uint8_t f0bc8x_b1_d1; + uint8_t f0bc9x_b1_d1; + uint8_t f0bcax_b1_d1; + uint8_t f0bcbx_b1_d1; + uint8_t f1bc2x_b1_d1; + uint8_t f1bc3x_b1_d1; + uint8_t f1bc4x_b1_d1; + uint8_t f1bc5x_b1_d1; + uint8_t f1bc8x_b1_d1; + uint8_t f1bc9x_b1_d1; + uint8_t f1bcax_b1_d1; + uint8_t f1bcbx_b1_d1; + uint8_t f2bc2x_b1_d1; + uint8_t f2bc3x_b1_d1; + uint8_t f2bc4x_b1_d1; + uint8_t f2bc5x_b1_d1; + uint8_t f2bc8x_b1_d1; + uint8_t f2bc9x_b1_d1; + uint8_t f2bcax_b1_d1; + uint8_t f2bcbx_b1_d1; + uint8_t f3bc2x_b1_d1; + uint8_t f3bc3x_b1_d1; + uint8_t f3bc4x_b1_d1; + uint8_t f3bc5x_b1_d1; + uint8_t f3bc8x_b1_d1; + uint8_t f3bc9x_b1_d1; + uint8_t f3bcax_b1_d1; + uint8_t f3bcbx_b1_d1; + uint8_t f0bc2x_b2_d1; + uint8_t f0bc3x_b2_d1; + uint8_t f0bc4x_b2_d1; + uint8_t f0bc5x_b2_d1; + uint8_t f0bc8x_b2_d1; + uint8_t f0bc9x_b2_d1; + uint8_t f0bcax_b2_d1; + uint8_t f0bcbx_b2_d1; + uint8_t f1bc2x_b2_d1; + uint8_t f1bc3x_b2_d1; + uint8_t f1bc4x_b2_d1; + uint8_t f1bc5x_b2_d1; + uint8_t f1bc8x_b2_d1; + uint8_t f1bc9x_b2_d1; + uint8_t f1bcax_b2_d1; + uint8_t f1bcbx_b2_d1; + uint8_t f2bc2x_b2_d1; + uint8_t f2bc3x_b2_d1; + uint8_t f2bc4x_b2_d1; + uint8_t f2bc5x_b2_d1; + uint8_t f2bc8x_b2_d1; + uint8_t f2bc9x_b2_d1; + uint8_t f2bcax_b2_d1; + uint8_t f2bcbx_b2_d1; + uint8_t f3bc2x_b2_d1; + uint8_t f3bc3x_b2_d1; + uint8_t f3bc4x_b2_d1; + uint8_t f3bc5x_b2_d1; + uint8_t f3bc8x_b2_d1; + uint8_t f3bc9x_b2_d1; + uint8_t f3bcax_b2_d1; + uint8_t f3bcbx_b2_d1; + uint8_t f0bc2x_b3_d1; + uint8_t f0bc3x_b3_d1; + uint8_t f0bc4x_b3_d1; + uint8_t f0bc5x_b3_d1; + uint8_t f0bc8x_b3_d1; + uint8_t f0bc9x_b3_d1; + uint8_t f0bcax_b3_d1; + uint8_t f0bcbx_b3_d1; + uint8_t f1bc2x_b3_d1; + uint8_t f1bc3x_b3_d1; + uint8_t f1bc4x_b3_d1; + uint8_t f1bc5x_b3_d1; + uint8_t f1bc8x_b3_d1; + uint8_t f1bc9x_b3_d1; + uint8_t f1bcax_b3_d1; + uint8_t f1bcbx_b3_d1; + uint8_t f2bc2x_b3_d1; + uint8_t f2bc3x_b3_d1; + uint8_t f2bc4x_b3_d1; + uint8_t f2bc5x_b3_d1; + uint8_t f2bc8x_b3_d1; + uint8_t f2bc9x_b3_d1; + uint8_t f2bcax_b3_d1; + uint8_t f2bcbx_b3_d1; + uint8_t f3bc2x_b3_d1; + uint8_t f3bc3x_b3_d1; + uint8_t f3bc4x_b3_d1; + uint8_t f3bc5x_b3_d1; + uint8_t f3bc8x_b3_d1; + uint8_t f3bc9x_b3_d1; + uint8_t f3bcax_b3_d1; + uint8_t f3bcbx_b3_d1; + uint8_t f0bc2x_b4_d1; + uint8_t f0bc3x_b4_d1; + uint8_t f0bc4x_b4_d1; + uint8_t f0bc5x_b4_d1; + uint8_t f0bc8x_b4_d1; + uint8_t f0bc9x_b4_d1; + uint8_t f0bcax_b4_d1; + uint8_t f0bcbx_b4_d1; + uint8_t f1bc2x_b4_d1; + uint8_t f1bc3x_b4_d1; + uint8_t f1bc4x_b4_d1; + uint8_t f1bc5x_b4_d1; + uint8_t f1bc8x_b4_d1; + uint8_t f1bc9x_b4_d1; + uint8_t f1bcax_b4_d1; + uint8_t f1bcbx_b4_d1; + uint8_t f2bc2x_b4_d1; + uint8_t f2bc3x_b4_d1; + uint8_t f2bc4x_b4_d1; + uint8_t f2bc5x_b4_d1; + uint8_t f2bc8x_b4_d1; + uint8_t f2bc9x_b4_d1; + uint8_t f2bcax_b4_d1; + uint8_t f2bcbx_b4_d1; + uint8_t f3bc2x_b4_d1; + uint8_t f3bc3x_b4_d1; + uint8_t f3bc4x_b4_d1; + uint8_t f3bc5x_b4_d1; + uint8_t f3bc8x_b4_d1; + uint8_t f3bc9x_b4_d1; + uint8_t f3bcax_b4_d1; + uint8_t f3bcbx_b4_d1; + uint8_t f0bc2x_b5_d1; + uint8_t f0bc3x_b5_d1; + uint8_t f0bc4x_b5_d1; + uint8_t f0bc5x_b5_d1; + uint8_t f0bc8x_b5_d1; + uint8_t f0bc9x_b5_d1; + uint8_t f0bcax_b5_d1; + uint8_t f0bcbx_b5_d1; + uint8_t f1bc2x_b5_d1; + uint8_t f1bc3x_b5_d1; + uint8_t f1bc4x_b5_d1; + uint8_t f1bc5x_b5_d1; + uint8_t f1bc8x_b5_d1; + uint8_t f1bc9x_b5_d1; + uint8_t f1bcax_b5_d1; + uint8_t f1bcbx_b5_d1; + uint8_t f2bc2x_b5_d1; + uint8_t f2bc3x_b5_d1; + uint8_t f2bc4x_b5_d1; + uint8_t f2bc5x_b5_d1; + uint8_t f2bc8x_b5_d1; + uint8_t f2bc9x_b5_d1; + uint8_t f2bcax_b5_d1; + uint8_t f2bcbx_b5_d1; + uint8_t f3bc2x_b5_d1; + uint8_t f3bc3x_b5_d1; + uint8_t f3bc4x_b5_d1; + uint8_t f3bc5x_b5_d1; + uint8_t f3bc8x_b5_d1; + uint8_t f3bc9x_b5_d1; + uint8_t f3bcax_b5_d1; + uint8_t f3bcbx_b5_d1; + uint8_t f0bc2x_b6_d1; + uint8_t f0bc3x_b6_d1; + uint8_t f0bc4x_b6_d1; + uint8_t f0bc5x_b6_d1; + uint8_t f0bc8x_b6_d1; + uint8_t f0bc9x_b6_d1; + uint8_t f0bcax_b6_d1; + uint8_t f0bcbx_b6_d1; + uint8_t f1bc2x_b6_d1; + uint8_t f1bc3x_b6_d1; + uint8_t f1bc4x_b6_d1; + uint8_t f1bc5x_b6_d1; + uint8_t f1bc8x_b6_d1; + uint8_t f1bc9x_b6_d1; + uint8_t f1bcax_b6_d1; + uint8_t f1bcbx_b6_d1; + uint8_t f2bc2x_b6_d1; + uint8_t f2bc3x_b6_d1; + uint8_t f2bc4x_b6_d1; + uint8_t f2bc5x_b6_d1; + uint8_t f2bc8x_b6_d1; + uint8_t f2bc9x_b6_d1; + uint8_t f2bcax_b6_d1; + uint8_t f2bcbx_b6_d1; + uint8_t f3bc2x_b6_d1; + uint8_t f3bc3x_b6_d1; + uint8_t f3bc4x_b6_d1; + uint8_t f3bc5x_b6_d1; + uint8_t f3bc8x_b6_d1; + uint8_t f3bc9x_b6_d1; + uint8_t f3bcax_b6_d1; + uint8_t f3bcbx_b6_d1; + uint8_t f0bc2x_b7_d1; + uint8_t f0bc3x_b7_d1; + uint8_t f0bc4x_b7_d1; + uint8_t f0bc5x_b7_d1; + uint8_t f0bc8x_b7_d1; + uint8_t f0bc9x_b7_d1; + uint8_t f0bcax_b7_d1; + uint8_t f0bcbx_b7_d1; + uint8_t f1bc2x_b7_d1; + uint8_t f1bc3x_b7_d1; + uint8_t f1bc4x_b7_d1; + uint8_t f1bc5x_b7_d1; + uint8_t f1bc8x_b7_d1; + uint8_t f1bc9x_b7_d1; + uint8_t f1bcax_b7_d1; + uint8_t f1bcbx_b7_d1; + uint8_t f2bc2x_b7_d1; + uint8_t f2bc3x_b7_d1; + uint8_t f2bc4x_b7_d1; + uint8_t f2bc5x_b7_d1; + uint8_t f2bc8x_b7_d1; + uint8_t f2bc9x_b7_d1; + uint8_t f2bcax_b7_d1; + uint8_t f2bcbx_b7_d1; + uint8_t f3bc2x_b7_d1; + uint8_t f3bc3x_b7_d1; + uint8_t f3bc4x_b7_d1; + uint8_t f3bc5x_b7_d1; + uint8_t f3bc8x_b7_d1; + uint8_t f3bc9x_b7_d1; + uint8_t f3bcax_b7_d1; + uint8_t f3bcbx_b7_d1; + uint8_t f0bc2x_b8_d1; + uint8_t f0bc3x_b8_d1; + uint8_t f0bc4x_b8_d1; + uint8_t f0bc5x_b8_d1; + uint8_t f0bc8x_b8_d1; + uint8_t f0bc9x_b8_d1; + uint8_t f0bcax_b8_d1; + uint8_t f0bcbx_b8_d1; + uint8_t f1bc2x_b8_d1; + uint8_t f1bc3x_b8_d1; + uint8_t f1bc4x_b8_d1; + uint8_t f1bc5x_b8_d1; + uint8_t f1bc8x_b8_d1; + uint8_t f1bc9x_b8_d1; + uint8_t f1bcax_b8_d1; + uint8_t f1bcbx_b8_d1; + uint8_t f2bc2x_b8_d1; + uint8_t f2bc3x_b8_d1; + uint8_t f2bc4x_b8_d1; + uint8_t f2bc5x_b8_d1; + uint8_t f2bc8x_b8_d1; + uint8_t f2bc9x_b8_d1; + uint8_t f2bcax_b8_d1; + uint8_t f2bcbx_b8_d1; + uint8_t f3bc2x_b8_d1; + uint8_t f3bc3x_b8_d1; + uint8_t f3bc4x_b8_d1; + uint8_t f3bc5x_b8_d1; + uint8_t f3bc8x_b8_d1; + uint8_t f3bc9x_b8_d1; + uint8_t f3bcax_b8_d1; + uint8_t f3bcbx_b8_d1; + uint8_t f5bc5x_d1; + uint8_t f5bc6x_d1; + uint8_t f4bc8x_d1; + uint8_t f4bc9x_d1; + uint8_t f4bcax_d1; + uint8_t f4bcbx_d1; + uint8_t f4bccx_d1; + uint8_t f4bcdx_d1; + uint8_t f4bcex_d1; + uint8_t f4bcfx_d1; + uint8_t f5bc8x_d1; + uint8_t f5bc9x_d1; + uint8_t f5bcax_d1; + uint8_t f5bcbx_d1; + uint8_t f5bccx_d1; + uint8_t f5bcdx_d1; + uint8_t f5bcex_d1; + uint8_t f5bcfx_d1; + uint8_t f6bc8x_d1; + uint8_t f6bc9x_d1; + uint8_t f6bcax_d1; + uint8_t f6bcbx_d1; + uint8_t f6bccx_d1; + uint8_t f6bcdx_d1; + uint8_t f6bcex_d1; + uint8_t f6bcfx_d1; + uint8_t f7bc8x_d1; + uint8_t f7bc9x_d1; + uint8_t f7bcax_d1; + uint8_t f7bcbx_d1; + uint8_t f7bccx_d1; + uint8_t f7bcdx_d1; + uint8_t f7bcex_d1; + uint8_t f7bcfx_d1; + uint16_t alt_cas_l; + uint8_t alt_wcas_l; + uint8_t d4misc; +} __packed; +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk new file mode 100644 index 0000000..ba5c774 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddrphy.mk @@ -0,0 +1,20 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#----------------------------------------------------------------------------- + +# SNPS ddr phy driver files + +DDR_PHY_C = +DDR_PHY_H = + +$(DDR_PHY_C): $(DDR_PHY_H) $(COMMON_HDRS) src + @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@" + +$(DDR_PHY_H): src + @cp -r "$(DDR_PHY_PATH)/$@" "$(SRC_DIR)/$@" + +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h new file mode 100644 index 0000000..dbcd1ae --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h @@ -0,0 +1,106 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _INPUT_H_ +#define _INPUT_H_ + +enum dram_types { + DDR4, + DDR3, + LPDDR4, + LPDDR3, + LPDDR2, + DDR5, +}; + +enum dimm_types { + UDIMM, + SODIMM, + RDIMM, + LRDIMM, + NODIMM, +}; + +struct input_basic { + enum dram_types dram_type; + enum dimm_types dimm_type; + int lp4x_mode; /* 0x1 = lpddr4x mode, when dram_type is lpddr4 + */ + /* not used for protocols other than lpddr4 */ + int num_dbyte; /* number of dbytes physically instantiated */ + int num_active_dbyte_dfi0; /* number of active dbytes to be + * controlled by dfi0 + */ + int num_active_dbyte_dfi1; /* number of active dbytes to be + * controlled by dfi1. Not used for + * protocols other than lpddr3 and + * lpddr4 + */ + int num_anib; /* number of anibs physically instantiated */ + int num_rank_dfi0; /* number of ranks in dfi0 channel */ + int num_rank_dfi1; /* number of ranks in dfi1 channel */ + int dram_data_width; /* 4,8,16 or 32 depending on protocol and dram + * type + */ + int num_pstates; + int frequency; /* memclk frequency in mhz -- round up */ + int pll_bypass; /* pll bypass enable */ + int dfi_freq_ratio; /* selected dfi frequency ratio */ + int dfi1exists; /* whether they phy config has dfi1 channel */ + int train2d; + int hard_macro_ver; + int read_dbienable; + int dfi_mode; /* no longer used */ +}; + +struct input_advanced { + int d4rx_preamble_length; + int d4tx_preamble_length; + int ext_cal_res_val; /* external pull-down resistor */ + int is2ttiming; + int odtimpedance; + int tx_impedance; + int atx_impedance; + int mem_alert_en; + int mem_alert_puimp; + int mem_alert_vref_level; + int mem_alert_sync_bypass; + int dis_dyn_adr_tri; + int phy_mstr_train_interval; + int phy_mstr_max_req_to_ack; + int wdqsext; + int cal_interval; + int cal_once; + int dram_byte_swap; + int rx_en_back_off; + int train_sequence_ctrl; + int phy_gen2_umctl_opt; + int phy_gen2_umctl_f0rc5x; + int tx_slew_rise_dq; + int tx_slew_fall_dq; + int tx_slew_rise_ac; + int tx_slew_fall_ac; + int enable_high_clk_skew_fix; + int disable_unused_addr_lns; + int phy_init_sequence_num; + int cs_mode; /* rdimm */ + int cast_cs_to_cid; /* rdimm */ +}; + +struct input { + struct input_basic basic; + struct input_advanced adv; + unsigned int mr[7]; + unsigned int cs_d0; + unsigned int cs_d1; + unsigned int mirror; + unsigned int odt[4]; + unsigned int rcw[16]; + unsigned int rcw3x; + unsigned int vref; +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h new file mode 100644 index 0000000..7dec7df --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h @@ -0,0 +1,2909 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef MESSAGE_H +#define MESSAGE_H + +#ifdef DEBUG +struct phy_msg { + uint32_t index; + const char *msg; +}; + +const static struct phy_msg messages_1d[] = { + {0x00000001, + "PMU1:prbsGenCtl:%x\n" + }, + {0x00010000, + "PMU1: loading 2D acsm sequence\n" + }, + {0x00020000, + "PMU1: loading 1D acsm sequence\n" + }, + {0x00030002, + "PMU3: %d memclocks @ %d to get half of 300ns\n" + }, + {0x00040000, + "PMU: Error: User requested MPR read pattern for read DQS training in DDR3 Mode\n" + }, + {0x00050000, + "PMU3: Running 1D search for left eye edge\n" + }, + {0x00060001, + "PMU1: In Phase Left Edge Search cs %d\n" + }, + {0x00070001, + "PMU1: Out of Phase Left Edge Search cs %d\n" + }, + {0x00080000, + "PMU3: Running 1D search for right eye edge\n" + }, + {0x00090001, + "PMU1: In Phase Right Edge Search cs %d\n" + }, + {0x000a0001, + "PMU1: Out of Phase Right Edge Search cs %d\n" + }, + {0x000b0001, + "PMU1: mxRdLat training pstate %d\n" + }, + {0x000c0001, + "PMU1: mxRdLat search for cs %d\n" + }, + {0x000d0001, + "PMU0: MaxRdLat non consistent DtsmLoThldXingInd 0x%03x\n" + }, + {0x000e0003, + "PMU4: CS %d Dbyte %d worked with DFIMRL = %d DFICLKs\n" + }, + {0x000f0004, + "PMU3: MaxRdLat Read Lane err mask for csn %d, DFIMRL %2d DFIClks, dbyte %d = 0x%03x\n" + }, + {0x00100003, + "PMU3: MaxRdLat Read Lane err mask for csn %d DFIMRL %2d, All dbytes = 0x%03x\n" + }, + {0x00110001, + "PMU: Error: CS%d failed to find a DFIMRL setting that worked for all bytes during MaxRdLat training\n" + }, + {0x00120002, + "PMU3: Smallest passing DFIMRL for all dbytes in CS%d = %d DFIClks\n" + }, + {0x00130000, + "PMU: Error: No passing DFIMRL value found for any chip select during MaxRdLat training\n" + }, + {0x00140003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00150006, + "PMU10: Adjusting rxclkdly db %d nib %d from %d+%d=%d->%d\n" + }, + {0x00160000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00170005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00180002, + "PMU2: TXDQ delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00190004, + "PMU2: TXDQ delayLeft[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x001a0002, + "PMU2: TXDQ delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x001b0004, + "PMU2: TXDQ delayRight[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x001c0003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x001d0000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x001e0002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x001f0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00200002, + "PMU3: Running 1D search csn %d for DM Right/NotLeft(%d) eye edge\n" + }, + {0x00210002, + "PMU3: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00220002, + "PMU3: WrDq DM byte%2d avgDly 0x%04x\n" + }, + {0x00230002, + "PMU1: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00240001, + "PMU: Error: Dbyte %d txDqDly DM training did not start inside the eye\n" + }, + {0x00250000, + "PMU4: DM TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00260002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00270005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00280003, + "PMU: Error: Dbyte %d lane %d txDqDly DM passing region is too small (width = %d)\n" + }, + {0x00290004, + "PMU3: Errcnt for MRD/MWD search nib %2d delay = (%d, 0x%02x) = %d\n" + }, + {0x002a0000, + "PMU3: Precharge all open banks\n" + }, + {0x002b0002, + "PMU: Error: Dbyte %d nibble %d found mutliple working coarse delay setting for MRD/MWD\n" + }, + {0x002c0000, + "PMU4: MRD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x002d0000, + "PMU4: MWD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x002e0004, + "PMU10: Warning: DB %d nibble %d has multiple working coarse delays, %d and %d, choosing the smaller delay\n" + }, + {0x002f0003, + "PMU: Error: Dbyte %d nibble %d MRD/MWD passing region is too small (width = %d)\n" + }, + {0x00300006, + "PMU4: DB %d nibble %d: %3d, %3d %3d -> %3d\n" + }, + {0x00310002, + "PMU1: Start MRD/nMWD %d for csn %d\n" + }, + {0x00320002, + "PMU2: RXDQS delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00330006, + "PMU2: RXDQS delayLeft[%2d] = %3d delayOop[%2d] = %3d OopScaled %4d, selectOop %d\n" + }, + {0x00340002, + "PMU2: RXDQS delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00350006, + "PMU2: RXDQS delayRight[%2d] = %3d delayOop[%2d] = %4d OopScaled %4d, selectOop %d\n" + }, + {0x00360000, + "PMU4: RxClkDly Passing Regions (EyeLeft EyeRight -> EyeCenter)\n" + }, + {0x00370002, + "PMU4: DB %d nibble %d: (DISCONNECTED)\n" + }, + {0x00380005, + "PMU4: DB %d nibble %d: %3d %3d -> %3d\n" + }, + {0x00390003, + "PMU: Error: Dbyte %d nibble %d rxClkDly passing region is too small (width = %d)\n" + }, + {0x003a0002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x003b0001, + "PMU3: RxClkDly = %d\n" + }, + {0x003c0005, + "PMU0: db %d l %d absLane %d -> bottom %d top %d\n" + }, + {0x003d0009, + "PMU3: BYTE %d - %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x003e0002, + "PMU: Error: dbyte %d lane %d's per-lane vrefDAC's had no passing region\n" + }, + {0x003f0004, + "PMU0: db%d l%d - %d %d\n" + }, + {0x00400002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00410004, + "PMU3: db%d l%d saw %d issues at rxClkDly %d\n" + }, + {0x00420003, + "PMU3: db%d l%d first saw a pass->fail edge at rxClkDly %d\n" + }, + {0x00430002, + "PMU3: lane %d PBD = %d\n" + }, + {0x00440003, + "PMU3: db%d l%d first saw a DBI pass->fail edge at rxClkDly %d\n" + }, + {0x00450003, + "PMU2: db%d l%d already passed rxPBD = %d\n" + }, + {0x00460003, + "PMU0: db%d l%d, PBD = %d\n" + }, + {0x00470002, + "PMU: Error: dbyte %d lane %d failed read deskew\n" + }, + {0x00480003, + "PMU0: db%d l%d, inc PBD = %d\n" + }, + {0x00490003, + "PMU1: Running lane deskew on pstate %d csn %d rdDBIEn %d\n" + }, + {0x004a0000, + "PMU: Error: Read deskew training has been requested, but csrMajorModeDbyte[2] is set\n" + }, + {0x004b0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x004c0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x004d0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3U Type\n" + }, + {0x004e0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3R Type\n" + }, + {0x004f0001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4U Type\n" + }, + {0x00500001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4R Type\n" + }, + {0x00510001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4LR Type\n" + }, + {0x00520000, + "PMU: Error: Both 2t timing mode and ddr4 geardown mode specified in the messageblock's PhyCfg and MR3 fields. Only one can be enabled\n" + }, + {0x00530003, + "PMU10: PHY TOTALS - NUM_DBYTES %d NUM_NIBBLES %d NUM_ANIBS %d\n" + }, + {0x00540006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR3\n" + }, + {0x00550006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR4\n" + }, + {0x00560008, + "PMU10: CS=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, 2T=%d, MMISC=%d AddrMirror=%d DRAMFreq=%dMT DramType=%d\n" + }, + {0x00570004, + "PMU10: Pstate%d MR0=0x%04x MR1=0x%04x MR2=0x%04x\n" + }, + {0x00580008, + "PMU10: Pstate%d MRS MR0=0x%04x MR1=0x%04x MR2=0x%04x MR3=0x%04x MR4=0x%04x MR5=0x%04x MR6=0x%04x\n" + }, + {0x00590005, + "PMU10: Pstate%d MRS MR1_A0=0x%04x MR2_A0=0x%04x MR3_A0=0x%04x MR11_A0=0x%04x\n" + }, + {0x005a0000, + "PMU10: UseBroadcastMR set. All ranks and channels use MRXX_A0 for MR settings.\n" + }, + {0x005b0005, + "PMU10: Pstate%d MRS MR01_A0=0x%02x MR02_A0=0x%02x MR03_A0=0x%02x MR11_A0=0x%02x\n" + }, + {0x005c0005, + "PMU10: Pstate%d MRS MR12_A0=0x%02x MR13_A0=0x%02x MR14_A0=0x%02x MR22_A0=0x%02x\n" + }, + {0x005d0005, + "PMU10: Pstate%d MRS MR01_A1=0x%02x MR02_A1=0x%02x MR03_A1=0x%02x MR11_A1=0x%02x\n" + }, + {0x005e0005, + "PMU10: Pstate%d MRS MR12_A1=0x%02x MR13_A1=0x%02x MR14_A1=0x%02x MR22_A1=0x%02x\n" + }, + {0x005f0005, + "PMU10: Pstate%d MRS MR01_B0=0x%02x MR02_B0=0x%02x MR03_B0=0x%02x MR11_B0=0x%02x\n" + }, + {0x00600005, + "PMU10: Pstate%d MRS MR12_B0=0x%02x MR13_B0=0x%02x MR14_B0=0x%02x MR22_B0=0x%02x\n" + }, + {0x00610005, + "PMU10: Pstate%d MRS MR01_B1=0x%02x MR02_B1=0x%02x MR03_B1=0x%02x MR11_B1=0x%02x\n" + }, + {0x00620005, + "PMU10: Pstate%d MRS MR12_B1=0x%02x MR13_B1=0x%02x MR14_B1=0x%02x MR22_B1=0x%02x\n" + }, + {0x00630002, + "PMU1: AcsmOdtCtrl%02d 0x%02x\n" + }, + {0x00640002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00650002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00660000, + "PMU1: HwtCAMode set\n" + }, + {0x00670001, + "PMU3: DDR4 infinite preamble enter/exit mode %d\n" + }, + {0x00680002, + "PMU1: In rxenb_train() csn=%d pstate=%d\n" + }, + {0x00690000, + "PMU3: Finding DQS falling edge\n" + }, + {0x006a0000, + "PMU3: Searching for DDR3/LPDDR3/LPDDR4 read preamble\n" + }, + {0x006b0009, + "PMU3: dtsm fails Even Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x006c0009, + "PMU3: dtsm fails Odd Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x006d0002, + "PMU3: Preamble search pass=%d anyfail=%d\n" + }, + {0x006e0000, + "PMU: Error: RxEn training preamble not found\n" + }, + {0x006f0000, + "PMU3: Found DQS pre-amble\n" + }, + {0x00700001, + "PMU: Error: Dbyte %d couldn't find the rising edge of DQS during RxEn Training\n" + }, + {0x00710000, + "PMU3: RxEn aligning to first rising edge of burst\n" + }, + {0x00720001, + "PMU3: Decreasing RxEn delay by %d fine step to allow full capture of reads\n" + }, + {0x00730001, + "PMU3: MREP Delay = %d\n" + }, + {0x00740003, + "PMU3: Errcnt for MREP nib %2d delay = %2d is %d\n" + }, + {0x00750002, + "PMU3: MREP nibble %d sampled a 1 at data buffer delay %d\n" + }, + {0x00760002, + "PMU3: MREP nibble %d saw a 0 to 1 transition at data buffer delay %d\n" + }, + {0x00770000, + "PMU2: MREP did not find a 0 to 1 transition for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x00780002, + "PMU2: Rising edge found in alias window, setting rxDly for nibble %d = %d\n" + }, + {0x00790002, + "PMU: Error: Failed MREP for nib %d with %d one\n" + }, + {0x007a0003, + "PMU2: Rising edge not found in alias window with %d one, leaving rxDly for nibble %d = %d\n" + }, + {0x007b0002, + "PMU3: Training DIMM %d CSn %d\n" + }, + {0x007c0001, + "PMU3: exitCAtrain_lp3 cs 0x%x\n" + }, + {0x007d0001, + "PMU3: enterCAtrain_lp3 cs 0x%x\n" + }, + {0x007e0001, + "PMU3: CAtrain_switchmsb_lp3 cs 0x%x\n" + }, + {0x007f0001, + "PMU3: CATrain_rdwr_lp3 looking for pattern %x\n" + }, + {0x00800000, + "PMU3: exitCAtrain_lp4\n" + }, + {0x00810001, + "PMU3: DEBUG enterCAtrain_lp4 1: cs 0x%x\n" + }, + {0x00820001, + "PMU3: DEBUG enterCAtrain_lp4 3: Put dbyte %d in async mode\n" + }, + {0x00830000, + "PMU3: DEBUG enterCAtrain_lp4 5: Send MR13 to turn on CA training\n" + }, + {0x00840003, + "PMU3: DEBUG enterCAtrain_lp4 7: idx = %d vref = %x mr12 = %x\n" + }, + {0x00850001, + "PMU3: CATrain_rdwr_lp4 looking for pattern %x\n" + }, + {0x00860004, + "PMU3: Phase %d CAreadbackA db:%d %x xo:%x\n" + }, + {0x00870005, + "PMU3: DEBUG lp4SetCatrVref 1: cs=%d chan=%d mr12=%x vref=%d.%d%%\n" + }, + {0x00880003, + "PMU3: DEBUG lp4SetCatrVref 3: mr12 = %x send vref= %x to db=%d\n" + }, + {0x00890000, + "PMU10:Optimizing vref\n" + }, + {0x008a0004, + "PMU4:mr12:%2x cs:%d chan %d r:%4x\n" + }, + {0x008b0005, + "PMU3: i:%2d bstr:%2d bsto:%2d st:%d r:%d\n" + }, + {0x008c0002, + "Failed to find sufficient CA Vref Passing Region for CS %d ch. %d\n" + }, + {0x008d0005, + "PMU3:Found %d.%d%% MR12:%x for cs:%d chan %d\n" + }, + {0x008e0002, + "PMU3:Calculated %d for AtxImpedence from acx %d.\n" + }, + {0x008f0000, + "PMU3:CA Odt impedence ==0. Use default vref.\n" + }, + {0x00900003, + "PMU3:Calculated %d.%d%% for Vref MR12=0x%x.\n" + }, + {0x00910000, + "PMU3: CAtrain_lp\n" + }, + {0x00920000, + "PMU3: CAtrain Begins.\n" + }, + {0x00930001, + "PMU3: CAtrain_lp testing dly %d\n" + }, + {0x00940001, + "PMU5: CA bitmap dump for cs %x\n" + }, + {0x00950001, + "PMU5: CAA%d " + }, + {0x00960001, "%02x" + }, + {0x00970000, "\n" + }, + {0x00980001, + "PMU5: CAB%d " + }, + {0x00990001, "%02x" + }, + {0x009a0000, "\n" + }, + {0x009b0003, + "PMU3: anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x009c0001, "%02x" + }, + {0x009d0001, "\nPMU3:Raw CA setting :%x" + }, + {0x009e0002, "\nPMU3:ATxDly setting:%x margin:%d\n" + }, + {0x009f0002, "\nPMU3:InvClk ATxDly setting:%x margin:%d\n" + }, + {0x00a00000, "\nPMU3:No Range found!\n" + }, + {0x00a10003, + "PMU3: 2 anibi=%d, anibichan[anibi]=%d ,chan=%d" + }, + {0x00a20002, "\nPMU3: no neg clock => CA setting anib=%d, :%d\n" + }, + {0x00a30001, + "PMU3:Normal margin:%d\n" + }, + {0x00a40001, + "PMU3:Inverted margin:%d\n" + }, + {0x00a50000, + "PMU3:Using Inverted clock\n" + }, + {0x00a60000, + "PMU3:Using normal clk\n" + }, + {0x00a70003, + "PMU3: 3 anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x00a80002, + "PMU3: Setting ATxDly for anib %x to %x\n" + }, + {0x00a90000, + "PMU: Error: CA Training Failed.\n" + }, + {0x00aa0000, + "PMU1: Writing MRs\n" + }, + {0x00ab0000, + "PMU4:Using MR12 values from 1D CA VREF training.\n" + }, + {0x00ac0000, + "PMU3:Writing all MRs to fsp 1\n" + }, + {0x00ad0000, + "PMU10:Lp4Quickboot mode.\n" + }, + {0x00ae0000, + "PMU3: Writing MRs\n" + }, + {0x00af0001, + "PMU10: Setting boot clock divider to %d\n" + }, + {0x00b00000, + "PMU3: Resetting DRAM\n" + }, + {0x00b10000, + "PMU3: setup for RCD initalization\n" + }, + {0x00b20000, + "PMU3: pmu_exit_SR from dev_init()\n" + }, + {0x00b30000, + "PMU3: initializing RCD\n" + }, + {0x00b40000, + "PMU10: **** Executing 2D Image ****\n" + }, + {0x00b50001, + "PMU10: **** Start DDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b60001, + "PMU10: **** Start DDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b70001, + "PMU10: **** Start LPDDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b80001, + "PMU10: **** Start LPDDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x00b90000, + "PMU: Error: Mismatched internal revision between DCCM and ICCM images\n" + }, + {0x00ba0001, + "PMU10: **** Testchip %d Specific Firmware ****\n" + }, + {0x00bb0000, + "PMU1: LRDIMM with EncodedCS mode, one DIMM\n" + }, + {0x00bc0000, + "PMU1: LRDIMM with EncodedCS mode, two DIMMs\n" + }, + {0x00bd0000, + "PMU1: RDIMM with EncodedCS mode, one DIMM\n" + }, + {0x00be0000, + "PMU2: Starting LRDIMM MREP training for all ranks\n" + }, + {0x00bf0000, + "PMU199: LRDIMM MREP training for all ranks completed\n" + }, + {0x00c00000, + "PMU2: Starting LRDIMM DWL training for all ranks\n" + }, + {0x00c10000, + "PMU199: LRDIMM DWL training for all ranks completed\n" + }, + {0x00c20000, + "PMU2: Starting LRDIMM MRD training for all ranks\n" + }, + {0x00c30000, + "PMU199: LRDIMM MRD training for all ranks completed\n" + }, + {0x00c40000, + "PMU2: Starting RXEN training for all ranks\n" + }, + {0x00c50000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x00c60000, + "PMU2: Starting LRDIMM MWD training for all ranks\n" + }, + {0x00c70000, + "PMU199: LRDIMM MWD training for all ranks completed\n" + }, + {0x00c80000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x00c90000, + "PMU2: Starting read deskew training\n" + }, + {0x00ca0000, + "PMU2: Starting SI friendly 1d RdDqs training for all ranks\n" + }, + {0x00cb0000, + "PMU2: Starting write leveling coarse delay training for all ranks\n" + }, + {0x00cc0000, + "PMU2: Starting 1d WrDq training for all ranks\n" + }, + {0x00cd0000, + "PMU2: Running DQS2DQ Oscillator for all ranks\n" + }, + {0x00ce0000, + "PMU2: Starting again read deskew training but with PRBS\n" + }, + {0x00cf0000, + "PMU2: Starting 1d RdDqs training for all ranks\n" + }, + {0x00d00000, + "PMU2: Starting again 1d WrDq training for all ranks\n" + }, + {0x00d10000, + "PMU2: Starting MaxRdLat training\n" + }, + {0x00d20000, + "PMU2: Starting 2d WrDq training for all ranks\n" + }, + {0x00d30000, + "PMU2: Starting 2d RdDqs training for all ranks\n" + }, + {0x00d40002, + "PMU3:read_fifo %x %x\n" + }, + {0x00d50001, + "PMU: Error: Invalid PhyDrvImpedance of 0x%x specified in message block.\n" + }, + {0x00d60001, + "PMU: Error: Invalid PhyOdtImpedance of 0x%x specified in message block.\n" + }, + {0x00d70001, + "PMU: Error: Invalid BPZNResVal of 0x%x specified in message block.\n" + }, + {0x00d80005, + "PMU3: fixRxEnBackOff csn:%d db:%d dn:%d bo:%d dly:%x\n" + }, + {0x00d90001, + "PMU3: fixRxEnBackOff dly:%x\n" + }, + {0x00da0000, + "PMU3: Entering setupPpt\n" + }, + {0x00db0000, + "PMU3: Start lp4PopulateHighLowBytes\n" + }, + {0x00dc0002, + "PMU3:Dbyte Detect: db%d received %x\n" + }, + {0x00dd0002, + "PMU3:getDqs2Dq read %x from dbyte %d\n" + }, + {0x00de0002, + "PMU3:getDqs2Dq(2) read %x from dbyte %d\n" + }, + {0x00df0001, + "PMU: Error: Dbyte %d read 0 from the DQS oscillator it is connected to\n" + }, + {0x00e00002, + "PMU4: Dbyte %d dqs2dq = %d/32 UI\n" + }, + {0x00e10003, + "PMU3:getDqs2Dq set dqs2dq:%d/32 ui (%d ps) from dbyte %d\n" + }, + {0x00e20003, + "PMU3: Setting coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x00e30003, + "PMU3: Clearing coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x00e40000, + "PMU3: Performing DDR4 geardown sync sequence\n" + }, + {0x00e50000, + "PMU1: Enter self refresh\n" + }, + {0x00e60000, + "PMU1: Exit self refresh\n" + }, + {0x00e70000, + "PMU: Error: No dbiEnable with lp4\n" + }, + {0x00e80000, + "PMU: Error: No dbiDisable with lp4\n" + }, + {0x00e90001, + "PMU1: DDR4 update Rx DBI Setting disable %d\n" + }, + {0x00ea0001, + "PMU1: DDR4 update 2nCk WPre Setting disable %d\n" + }, + {0x00eb0005, + "PMU1: read_delay: db%d lane%d delays[%2d] = 0x%02x (max 0x%02x)\n" + }, + {0x00ec0004, + "PMU1: write_delay: db%d lane%d delays[%2d] = 0x%04x\n" + }, + {0x00ed0001, + "PMU5: ID=%d -- db0 db1 db2 db3 db4 db5 db6 db7 db8 db9 --\n" + }, + {0x00ee000b, + "PMU5: [%d]:0x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n" + }, + {0x00ef0003, + "PMU2: dump delays - pstate=%d dimm=%d csn=%d\n" + }, + {0x00f00000, + "PMU3: Printing Mid-Training Delay Information\n" + }, + {0x00f10001, + "PMU5: CS%d <> 0 TrainingCntr <> coarse(15:10) fine(9:0)\n" + }, + {0x00f20001, + "PMU5: CS%d <> 0 RxEnDly, 1 RxClkDly <> coarse(10:6) fine(5:0)\n" + }, + {0x00f30001, + "PMU5: CS%d <> 0 TxDqsDly, 1 TxDqDly <> coarse(9:6) fine(5:0)\n" + }, + {0x00f40001, + "PMU5: CS%d <> 0 RxPBDly <> 1 Delay Unit ~= 7ps\n" + }, + {0x00f50000, + "PMU5: all CS <> 0 DFIMRL <> Units = DFI clocks\n" + }, + {0x00f60000, + "PMU5: all CS <> VrefDACs <> DAC(6:0)\n" + }, + {0x00f70000, + "PMU1: Set DMD in MR13 and wrDBI in MR3 for training\n" + }, + {0x00f80000, + "PMU: Error: getMaxRxen() failed to find largest rxen nibble delay\n" + }, + {0x00f90003, + "PMU2: getMaxRxen(): maxDly %d maxTg %d maxNib %d\n" + }, + {0x00fa0003, + "PMU2: getRankMaxRxen(): maxDly %d Tg %d maxNib %d\n" + }, + {0x00fb0000, + "PMU1: skipping CDD calculation in 2D image\n" + }, + {0x00fc0001, + "PMU3: Calculating CDDs for pstate %d\n" + }, + {0x00fd0003, + "PMU3: rxFromDly[%d][%d] = %d\n" + }, + {0x00fe0003, + "PMU3: rxToDly [%d][%d] = %d\n" + }, + {0x00ff0003, + "PMU3: rxDly [%d][%d] = %d\n" + }, + {0x01000003, + "PMU3: txDly [%d][%d] = %d\n" + }, + {0x01010003, + "PMU3: allFine CDD_RR_%d_%d = %d\n" + }, + {0x01020003, + "PMU3: allFine CDD_WW_%d_%d = %d\n" + }, + {0x01030003, + "PMU3: CDD_RR_%d_%d = %d\n" + }, + {0x01040003, + "PMU3: CDD_WW_%d_%d = %d\n" + }, + {0x01050003, + "PMU3: allFine CDD_RW_%d_%d = %d\n" + }, + {0x01060003, + "PMU3: allFine CDD_WR_%d_%d = %d\n" + }, + {0x01070003, + "PMU3: CDD_RW_%d_%d = %d\n" + }, + {0x01080003, + "PMU3: CDD_WR_%d_%d = %d\n" + }, + {0x01090004, + "PMU3: F%dBC2x_B%d_D%d = 0x%02x\n" + }, + {0x010a0004, + "PMU3: F%dBC3x_B%d_D%d = 0x%02x\n" + }, + {0x010b0004, + "PMU3: F%dBC4x_B%d_D%d = 0x%02x\n" + }, + {0x010c0004, + "PMU3: F%dBC5x_B%d_D%d = 0x%02x\n" + }, + {0x010d0004, + "PMU3: F%dBC8x_B%d_D%d = 0x%02x\n" + }, + {0x010e0004, + "PMU3: F%dBC9x_B%d_D%d = 0x%02x\n" + }, + {0x010f0004, + "PMU3: F%dBCAx_B%d_D%d = 0x%02x\n" + }, + {0x01100004, + "PMU3: F%dBCBx_B%d_D%d = 0x%02x\n" + }, + {0x01110000, + "PMU10: Entering context_switch_postamble\n" + }, + {0x01120003, + "PMU10: context_switch_postamble is enabled for DIMM %d, RC0A=0x%x, RC3x=0x%x\n" + }, + {0x01130000, + "PMU10: Setting bcw fspace 0\n" + }, + {0x01140001, + "PMU10: Sending BC0A = 0x%x\n" + }, + {0x01150001, + "PMU10: Sending BC6x = 0x%x\n" + }, + {0x01160001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01170001, + "PMU10: Sending RC3x = 0x%x\n" + }, + {0x01180001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01190001, + "PMU1: enter_lp3: DEBUG: pstate = %d\n" + }, + {0x011a0001, + "PMU1: enter_lp3: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x011b0001, + "PMU1: enter_lp3: DEBUG: pllbypass = %d\n" + }, + {0x011c0001, + "PMU1: enter_lp3: DEBUG: forcecal = %d\n" + }, + {0x011d0001, + "PMU1: enter_lp3: DEBUG: pllmaxrange = 0x%x\n" + }, + {0x011e0001, + "PMU1: enter_lp3: DEBUG: dacval_out = 0x%x\n" + }, + {0x011f0001, + "PMU1: enter_lp3: DEBUG: pllctrl3 = 0x%x\n" + }, + {0x01200000, + "PMU3: Loading DRAM with BIOS supplied MR values and entering self refresh prior to exiting PMU code.\n" + }, + {0x01210002, + "PMU3: Setting DataBuffer function space of dimmcs 0x%02x to %d\n" + }, + {0x01220002, + "PMU4: Setting RCW FxRC%Xx = 0x%02x\n" + }, + {0x01230002, + "PMU4: Setting RCW FxRC%02x = 0x%02x\n" + }, + {0x01240001, + "PMU1: DDR4 update Rd Pre Setting disable %d\n" + }, + {0x01250002, + "PMU2: Setting BCW FxBC%Xx = 0x%02x\n" + }, + {0x01260002, + "PMU2: Setting BCW BC%02x = 0x%02x\n" + }, + {0x01270002, + "PMU2: Setting BCW PBA mode FxBC%Xx = 0x%02x\n" + }, + {0x01280002, + "PMU2: Setting BCW PBA mode BC%02x = 0x%02x\n" + }, + {0x01290003, + "PMU4: BCW value for dimm %d, fspace %d, addr 0x%04x\n" + }, + {0x012a0002, + "PMU4: DB %d, value 0x%02x\n" + }, + {0x012b0000, + "PMU6: WARNING MREP underflow, set to min value -2 coarse, 0 fine\n" + }, + {0x012c0004, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d, new MREP fine %2d\n" + }, + {0x012d0003, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d\n" + }, + {0x012e0003, + "PMU6: LRDIMM Writing data buffer fine delay type %d nib %2d, code %2d\n" + }, + {0x012f0002, + "PMU6: Writing final data buffer coarse delay value dbyte %2d, coarse = 0x%02x\n" + }, + {0x01300003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01310003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01320003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01330003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01340001, + "PMU3: Update BC00, BC01, BC02 for rank-dimm 0x%02x\n" + }, + {0x01350000, + "PMU3: Writing D4 RDIMM RCD Control words F0RC00 -> F0RC0F\n" + }, + {0x01360000, + "PMU3: Disable parity in F0RC0E\n" + }, + {0x01370000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC00 -> F1RC05\n" + }, + {0x01380000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC1x -> F1RC9x\n" + }, + {0x01390000, + "PMU3: Writing D4 Data buffer Control words BC00 -> BC0E\n" + }, + {0x013a0002, + "PMU1: setAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013b0002, + "PMU1: restoreFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013c0002, + "PMU1: restoreAcsmFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x013d0002, + "PMU2: Setting D3R RC%d = 0x%01x\n" + }, + {0x013e0000, + "PMU3: Writing D3 RDIMM RCD Control words RC0 -> RC11\n" + }, + {0x013f0002, + "PMU0: VrefDAC0/1 vddqStart %d dacToVddq %d\n" + }, + {0x01400001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated LPDDR4 receivers. Please see the pub databook\n" + }, + {0x01410001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated DDR4 receivers. Please see the pub databook\n" + }, + {0x01420001, + "PMU0: PHY VREF @ (%d/1000) VDDQ\n" + }, + {0x01430002, + "PMU0: initalizing phy vrefDacs to %d ExtVrefRange %x\n" + }, + {0x01440002, + "PMU0: initalizing global vref to %d range %d\n" + }, + {0x01450002, + "PMU4: Setting initial device vrefDQ for CS%d to MR6 = 0x%04x\n" + }, + {0x01460003, + "PMU1: In write_level_fine() csn=%d dimm=%d pstate=%d\n" + }, + {0x01470000, + "PMU3: Fine write leveling hardware search increasing TxDqsDly until full bursts are seen\n" + }, + {0x01480000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01490007, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x\n" + }, + {0x014a0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x014b0000, + "PMU3: Exiting write leveling mode\n" + }, + {0x014c0001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x014d0003, + "PMU1: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x014e0003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x014f0003, + "PMU3: right eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01500004, + "PMU3: eye center db:%d ln:%d dly:0x%x (maxdq:%x)\n" + }, + {0x01510003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01520003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01530002, + "PMU3: Coarse write leveling dbyte%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01540002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01550000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01560001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01570003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01580003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01590003, + "PMU3: right eye edge search db: %d ln: %d dly: 0x%x\n" + }, + {0x015a0004, + "PMU3: eye center db: %d ln: %d dly: 0x%x (maxdq: 0x%x)\n" + }, + {0x015b0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x015c0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x015d0002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x015e0002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x015f0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01600000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01610009, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x%08x%08x\n" + }, + {0x01620000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01630001, + "PMU8: Adjust margin after WL coarse to be larger than %d\n" + }, + {0x01640001, + "PMU: Error: All margin after write leveling coarse are smaller than minMargin %d\n" + }, + {0x01650002, + "PMU8: Decrement nib %d TxDqsDly by %d fine step\n" + }, + {0x01660003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01670005, + "PMU2: Write level: dbyte %d nib%d dq/dmbi %2d dqsfine 0x%04x dqDly 0x%04x\n" + }, + {0x01680002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01690002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x016a0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x016b0001, + "PMU3: DWL delay = %d\n" + }, + {0x016c0003, + "PMU3: Errcnt for DWL nib %2d delay = %2d is %d\n" + }, + {0x016d0002, + "PMU3: DWL nibble %d sampled a 1 at delay %d\n" + }, + {0x016e0003, + "PMU3: DWL nibble %d passed at delay %d. Rising edge was at %d\n" + }, + {0x016f0000, + "PMU2: DWL did nto find a rising edge of memclk for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x01700002, + "PMU2: Rising edge found in alias window, setting wrlvlDly for nibble %d = %d\n" + }, + {0x01710002, + "PMU: Error: Failed DWL for nib %d with %d one\n" + }, + {0x01720003, + "PMU2: Rising edge not found in alias window with %d one, leaving wrlvlDly for nibble %d = %d\n" + }, + {0x04000000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04010000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04020000, + "PMU: ***** Assertion Error - terminating *****\n" + }, + {0x04030002, + "PMU1: swapByte db %d by %d\n" + }, + {0x04040003, + "PMU3: get_cmd_dly max(%d ps, %d memclk) = %d\n" + }, + {0x04050002, + "PMU0: Write CSR 0x%06x 0x%04x\n" + }, + {0x04060002, + "PMU0: hwt_init_ppgc_prbs(): Polynomial: %x, Deg: %d\n" + }, + {0x04070001, + "PMU: Error: acsm_set_cmd to non existent instruction address %d\n" + }, + {0x04080001, + "PMU: Error: acsm_set_cmd with unknown ddr cmd 0x%x\n" + }, + {0x0409000c, + "PMU1: acsm_addr %02x, acsm_flgs %04x, ddr_cmd %02x, cmd_dly %02x, ddr_addr %04x, ddr_bnk %02x, ddr_cs %02x, cmd_rcnt %02x, AcsmSeq0/1/2/3 %04x %04x %04x %04x\n" + }, + {0x040a0000, + "PMU: Error: Polling on ACSM done failed to complete in acsm_poll_done()...\n" + }, + {0x040b0000, + "PMU1: acsm RUN\n" + }, + {0x040c0000, + "PMU1: acsm STOPPED\n" + }, + {0x040d0002, + "PMU1: acsm_init: acsm_mode %04x mxrdlat %04x\n" + }, + {0x040e0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 2 and 5, resp. CL=%d CWL=%d\n" + }, + {0x040f0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 5. CL=%d CWL=%d\n" + }, + {0x04100002, + "PMU1: setAcsmCLCWL: CASL %04d WCASL %04d\n" + }, + {0x04110001, + "PMU: Error: Reserved value of register F0RC0F found in message block: 0x%04x\n" + }, + {0x04120001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04130001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04140000, + "PMU3: Entering Boot Freq Mode.\n" + }, + {0x04150001, + "PMU: Error: Boot clock divider setting of %d is too small\n" + }, + {0x04160000, + "PMU3: Exiting Boot Freq Mode.\n" + }, + {0x04170002, + "PMU3: Writing MR%d OP=%x\n" + }, + {0x04180000, + "PMU: Error: Delay too large in slomo\n" + }, + {0x04190001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x041a0000, + "PMU3: Enable Channel A\n" + }, + {0x041b0000, + "PMU3: Enable Channel B\n" + }, + {0x041c0000, + "PMU3: Enable All Channels\n" + }, + {0x041d0002, + "PMU2: Use PDA mode to set MR%d with value 0x%02x\n" + }, + {0x041e0001, + "PMU3: Written Vref with PDA to CS=0x%02x\n" + }, + {0x041f0000, + "PMU1: start_cal: DEBUG: setting CalRun to 1\n" + }, + {0x04200000, + "PMU1: start_cal: DEBUG: setting CalRun to 0\n" + }, + {0x04210001, + "PMU1: lock_pll_dll: DEBUG: pstate = %d\n" + }, + {0x04220001, + "PMU1: lock_pll_dll: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x04230001, + "PMU1: lock_pll_dll: DEBUG: pllbypass = %d\n" + }, + {0x04240001, + "PMU3: SaveLcdlSeed: Saving seed %d\n" + }, + {0x04250000, + "PMU1: in phy_defaults()\n" + }, + {0x04260003, + "PMU3: ACXConf:%d MaxNumDbytes:%d NumDfi:%d\n" + }, + {0x04270005, + "PMU1: setAltAcsmCLCWL setting cl=%d cwl=%d\n" + }, +}; + +const static struct phy_msg messages_2d[] = { + {0x00000001, + "PMU0: Converting %d into an MR\n" + }, + {0x00010003, + "PMU DEBUG: vref_idx %d -= %d, range_idx = %d\n" + }, + {0x00020002, + "PMU0: vrefIdx. Passing range %d, remaining vrefidx = %d\n" + }, + {0x00030002, + "PMU0: VrefIdx %d -> MR[6:0] 0x%02x\n" + }, + {0x00040001, + "PMU0: Converting MR 0x%04x to vrefIdx\n" + }, + {0x00050002, + "PMU0: DAC %d Range %d\n" + }, + {0x00060003, + "PMU0: Range %d, Range_idx %d, vref_idx offset %d\n" + }, + {0x00070002, + "PMU0: MR 0x%04x -> VrefIdx %d\n" + }, + {0x00080001, + "PMU: Error: Illegal timing group number ,%d, in getPtrVrefDq\n" + }, + {0x00090003, + "PMU1: VrefDqR%dNib%d = %d\n" + }, + {0x000a0003, + "PMU0: VrefDqR%dNib%d = %d\n" + }, + {0x000b0000, + "PMU0: ----------------MARGINS-------\n" + }, + {0x000c0002, + "PMU0: R%d_RxClkDly_Margin = %d\n" + }, + {0x000d0002, + "PMU0: R%d_VrefDac_Margin = %d\n" + }, + {0x000e0002, + "PMU0: R%d_TxDqDly_Margin = %d\n" + }, + {0x000f0002, + "PMU0: R%d_DeviceVref_Margin = %d\n" + }, + {0x00100000, + "PMU0: -----------------------\n" + }, + {0x00110003, + "PMU0: eye %d's for all TG's is [%d ... %d]\n" + }, + {0x00120000, + "PMU0: ------- settingWeight -----\n" + }, + {0x00130002, + "PMU0: Weight %d @ Setting %d\n" + }, + {0x0014001f, + "PMU4: %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d >%3d< %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x00150002, + "PMU3: Voltage Range = [%d, %d]\n" + }, + {0x00160004, + "PMU4: -- DB%d L%d -- centers: delay = %d, voltage = %d\n" + }, + {0x00170001, + "PMU5: <> 0 TxDqDlyTg%d <> coarse(6:6) fine(5:0)\n" + }, + {0x00180001, + "PMU5: <> 0 messageBlock VrefDqR%d <> MR6(6:0)\n" + }, + {0x00190001, + "PMU5: <> 0 RxClkDlyTg%d <> fine(5:0)\n" + }, + {0x001a0003, + "PMU0: tgToCsn: tg %d + 0x%04x -> csn %d\n" + }, + {0x001b0002, + "PMU: Error: LP4 rank %d cannot be mapped on tg %d\n" + }, + {0x001c0002, + "PMU3: Sending vref %d, Mr = 0X%05x, to all devices\n" + }, + {0x001d0004, + "PMU4: -------- %dD Write Scanning TG %d (CS 0x%x) Lanes 0x%03x --------\n" + }, + {0x001e0002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x001f0003, + "PMU4: ------- 2D-DFE Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00200004, + "PMU4: ------- %dD Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00210003, + "PMU4: TG%d MR1[13,6,5]=0x%x MR6[13,9,8]=0x%x\n" + }, + {0x00220002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x00230003, + "PMU4: ------- 2D-DFE Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00240004, + "PMU4: ------- %dD Read Scanning TG %d (CS 0x%x) Lanes 0x%03x -------\n" + }, + {0x00250002, + "PMU0: training lanes 0x%03x using lanes 0x%03x\n" + }, + {0x00260002, + "PMU3: Sending vref %d, Mr = 0X%05x, to all devices\n" + }, + {0x00270004, + "PMU4: -------- %dD Write Scanning TG %d (CS 0x%x) Lanes 0x%03x --------\n" + }, + {0x00280001, + "PMU0: input %d\n" + }, + {0x00290002, + "PMU4: Programmed Voltage Search Range [%d, %d]\n" + }, + {0x002a0002, + "PMU3: Delay Stepsize = %d Fine, Voltage Stepsize = %d DAC\n" + }, + {0x002b0002, + "PMU4: Delay Weight = %d, Voltage Weight = %d\n" + }, + {0x002c0003, + "PMU0: raw 0x%x allFine %d incDec %d" + }, + {0x002d0008, + "PMU0: db%d l%d, voltage 0x%x (u_r %d) delay 0x%x (u_r %d) - lcdl %d mask 0x%x\n" + }, + {0x002e0005, + "PMU0: DB%d L%d, Eye %d, Seed = (0x%x, 0x%x)\n" + }, + {0x002f0002, + "PMU3: 2D Enables : %d, 1, %d\n" + }, + {0x00300006, + "PMU3: 2D Delay Ranges: OOPL[0x%04x,0x%04x], IP[0x%04x,0x%04x], OOPR[0x%04x,0x%04x]\n" + }, + {0x00310002, + "PMU3: 2D Voltage Search Range : [%d, %d]\n" + }, + {0x00320002, + "PMU4: Found Voltage Search Range [%d, %d]\n" + }, + {0x00330002, + "PMU0: User Weight = %d, Voltage Weight = %d\n" + }, + {0x00340005, + "PMU0: D(%d,%d) V(%d,%d | %d)\n" + }, + {0x00350002, + "PMU0: Norm Weight = %d, Voltage Weight = %d\n" + }, + {0x00360002, + "PMU0: seed 0 = (%d,%d) (center)\n" + }, + {0x00370003, + "PMU0: seed 1 = (%d,%d).min edge at idx %d\n" + }, + {0x00380003, + "PMU0: seed 2 = (%d,%d) max edge at idx %d\n" + }, + {0x00390003, + "PMU0: Search point %d = (%d,%d)\n" + }, + {0x003a0005, + "PMU0: YMARGIN: ^ %d, - %d, v %d. rate %d = %d\n" + }, + {0x003b0003, + "PMU0: XMARGIN: center %d, edge %d. = %d\n" + }, + {0x003c0002, + "PMU0: ----------- weighting (%d,%d) ----------------\n" + }, + {0x003d0003, + "PMU0: X margin - L %d R %d - Min %d\n" + }, + {0x003e0003, + "PMU0: Y margin - L %d R %d - Min %d\n" + }, + {0x003f0003, + "PMU0: center (%d,%d) weight = %d\n" + }, + {0x00400003, + "PMU4: Eye argest blob area %d from %d to %d\n" + }, + {0x00410002, + "PMU0: Compute centroid min_x %d max_x %d\n" + }, + {0x00420003, + "PMU0: Compute centroid sumLnDlyWidth %d sumLnVrefWidth %d sumLnWidht %d\n" + }, + {0x00430000, + "PMU: Error: No passing region found for 1 or more lanes. Set hdtCtrl=4 to see passing regions\n" + }, + {0x00440003, + "PMU0: Centroid ( %d, %d ) found with sumLnWidht %d\n" + }, + {0x00450003, + "PMU0: Optimal allFine Center ( %d + %d ,%d )\n" + }, + {0x00460003, + "PMU3: point %d starting at (%d,%d)\n" + }, + {0x00470002, + "PMU0: picking left (%d > %d)\n" + }, + {0x00480002, + "PMU0: picking right (%d > %d)\n" + }, + {0x00490002, + "PMU0: picking down (%d > %d)\n" + }, + {0x004a0002, + "PMU0: picking up (%d > %d)\n" + }, + {0x004b0009, + "PMU3: new center @ (%3d, %3d). Moved (%2i, %2i) -- L %d, R %d, C %d, U %d, D %d\n" + }, + {0x004c0003, + "PMU3: cordNum %d imporved %d to %d\n" + }, + {0x004d0000, + "PMU: Error: No passing region found for 1 or more lanes. Set hdtCtrl=4 to see passing regions\n" + }, + {0x004e0004, + "PMU0: Optimal allFine Center ( %d + %d ,%d ), found with weight %d.\n" + }, + {0x004f0003, + "PMU0: merging lanes=%d..%d, centerMerge_t %d\n" + }, + {0x00500001, + "PMU0: laneVal %d is disable\n" + }, + {0x00510002, + "PMU0: checking common center %d against current center %d\n" + }, + {0x00520001, + "PMU: Error: getCompoundEye Called on lane%d eye with non-compatible centers\n" + }, + {0x00530001, + "PMU0: laneItr %d is disable\n" + }, + {0x00540005, + "PMU0: lane %d, data_idx %d, offset_idx %d, = [%d..%d]\n" + }, + {0x00550003, + "PMU0: lane %d, data_idx %d, offset_idx %d, offset_idx out of range!\n" + }, + {0x00560003, + "PMU0: mergeData[%d] = max_v_low %d, min_v_high %d\n" + }, + {0x00570005, + "PMU1: writing merged center (%d,%d) back to dataBlock[%d]. doDelay %d, doVoltage %d\n" + }, + {0x00580005, + "PMU0: applying relative (%i,%i) back to dataBlock[%d]. doDelay %d, doVoltage %d\n" + }, + {0x00590002, + "PMU0: drvstren %x is idx %d in the table\n" + }, + {0x005a0000, + "PMU4: truncating FFE drive strength search range. Out of drive strengths to check.\n" + }, + {0x005b0002, + "PMU5: Weak 1 changed to pull-up %5d ohms, pull-down %5d ohms\n" + }, + {0x005c0002, + "PMU5: Weak 0 changed to pull-up %5d ohms, pull-down %5d ohms\n" + }, + {0x005d0003, + "PMU0: dlyMargin L %02d R %02d, min %02d\n" + }, + {0x005e0003, + "PMU0: vrefMargin T %02d B %02d, min %02d\n" + }, + {0x005f0002, + "PMU3: new minimum VrefMargin (%d < %d) recorded\n" + }, + {0x00600002, + "PMU3: new minimum DlyMargin (%d < %d) recorded\n" + }, + {0x00610000, + "PMU0: RX finding the per-nibble, per-tg rxClkDly values\n" + }, + {0x00620003, + "PMU0: Merging collected eyes [%d..%d) and analyzing for nibble %d's optimal rxClkDly\n" + }, + {0x00630002, + "PMU0: -- centers: delay = %d, voltage = %d\n" + }, + {0x00640003, + "PMU0: dumping optimized eye -- centers: delay = %d (%d), voltage = %d\n" + }, + {0x00650000, + "PMU0: TX optimizing txDqDelays\n" + }, + {0x00660001, + "PMU3: Analyzing collected eye %d for a lane's optimal TxDqDly\n" + }, + {0x00670001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00680000, + "PMU0: TX optimizing device voltages\n" + }, + {0x00690002, + "PMU0: Merging collected eyes [%d..%d) and analyzing for optimal device txVref\n" + }, + {0x006a0002, + "PMU0: -- centers: delay = %d, voltage = %d\n" + }, + {0x006b0003, + "PMU0: dumping optimized eye -- centers: delay = %d (%d), voltage = %d\n" + }, + {0x006c0000, + "PMU4: VrefDac (compound all TG) Bottom Top -> Center\n" + }, + {0x006d0005, + "PMU4: DB%d L%d %3d %3d -> %3d (DISCONNECTED)\n" + }, + {0x006e0005, + "PMU4: DB%d L%d %3d %3d -> %3d\n" + }, + {0x006f0005, + "PMU0: writing rxClkDelay for tg%d db%1d nib%1d to 0x%02x from eye[%02d] (DISCONNECTED)\n" + }, + {0x00700003, + "PMU: Error: Dbyte %d nibble %d's optimal rxClkDly of 0x%x is out of bounds\n" + }, + {0x00710005, + "PMU0: writing rxClkDelay for tg%d db%1d nib%1d to 0x%02x from eye[%02d]\n" + }, + {0x00720005, + "PMU0: tx voltage for tg%2d nib%2d to %3d (%d) from eye[%02d]\n" + }, + {0x00730001, + "PMU0: vref Sum = %d\n" + }, + {0x00740004, + "PMU0: tx voltage total is %d/%d -> %d -> %d\n" + }, + {0x00750007, + "PMU0: writing txDqDelay for tg%1d db%1d ln%1d to 0x%02x (%d coarse, %d fine) from eye[%02d] (DISCONNECTED)\n" + }, + {0x00760003, + "PMU: Error: Dbyte %d lane %d's optimal txDqDly of 0x%x is out of bounds\n" + }, + {0x00770007, + "PMU0: writing txDqDelay for tg%1d db%1d l%1d to 0x%02x (%d coarse, %d fine) from eye[%02d]\n" + }, + {0x00780002, + "PMU0: %d (0=tx, 1=rx) TgMask for this simulation: %x\n" + }, + {0x00790001, + "PMU0: eye-byte %d is disable\n" + }, + {0x007a0001, + "PMU0: eye-lane %d is disable\n" + }, + {0x007b0003, + "PMU10: Start d4_2d_lrdimm_rx_dfe dimm %d nbTap %d biasStepMode %d\n" + }, + {0x007c0001, + "PMU10: DB DFE feature not fully supported, F2BCEx value is 0x%02x\n" + }, + {0x007d0001, + "PMU10: DB DFE feature fully supported, F2BCEx value is 0x%02x\n" + }, + {0x007e0002, + "PMU8: Start d4_2d_lrdimm_rx_dfe for tap %d biasStepInc %d\n" + }, + {0x007f0001, + "PMU7: Start d4_2d_lrdimm_rx_dfe tapCoff 0x%0x\n" + }, + {0x00800003, + "PMU6: d4_2d_lrdimm_rx_dfe db %d lane %d area %d\n" + }, + {0x00810004, + "PMU7: d4_2d_lrdimm_rx_dfe db %d lane %d max area %d best bias 0x%0x\n" + }, + {0x00820001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00830003, + "PMU5: Setting 0x%x improved rank weight (%4d < %4d)\n" + }, + {0x00840001, + "PMU4: Setting 0x%x still optimal\n" + }, + {0x00850002, + "PMU5: ---- Training CS%d MR%d DRAM Equalization ----\n" + }, + {0x00860001, + "PMU0: eye-lane %d is disable\n" + }, + {0x00870003, + "PMU0: eye %d weight %d allTgWeight %d\n" + }, + {0x00880002, + "PMU5: FFE figure of merit improved from %d to %d\n" + }, + {0x00890002, + "PMU: Error: LP4 rank %d cannot be mapped on tg %d\n" + }, + {0x008a0000, + "PMU4: Adjusting vrefDac0 for just 1->x transitions\n" + }, + {0x008b0000, + "PMU4: Adjusting vrefDac1 for just 0->x transitions\n" + }, + {0x008c0001, + "PMU5: Strong 1, pull-up %d ohms\n" + }, + {0x008d0001, + "PMU5: Strong 0, pull-down %d ohms\n" + }, + {0x008e0000, + "PMU4: Enabling weak drive strengths (FFE)\n" + }, + {0x008f0000, + "PMU5: Changing all weak driver strengths\n" + }, + {0x00900000, + "PMU5: Finalizing weak drive strengths\n" + }, + {0x00910000, + "PMU4: retraining with optimal drive strength settings\n" + }, + {0x00920002, + "PMU0: targeting CsX = %d and CsY = %d\n" + }, + {0x00930001, + "PMU1:prbsGenCtl:%x\n" + }, + {0x00940000, + "PMU1: loading 2D acsm sequence\n" + }, + {0x00950000, + "PMU1: loading 1D acsm sequence\n" + }, + {0x00960002, + "PMU3: %d memclocks @ %d to get half of 300ns\n" + }, + {0x00970000, + "PMU: Error: User requested MPR read pattern for read DQS training in DDR3 Mode\n" + }, + {0x00980000, + "PMU3: Running 1D search for left eye edge\n" + }, + {0x00990001, + "PMU1: In Phase Left Edge Search cs %d\n" + }, + {0x009a0001, + "PMU1: Out of Phase Left Edge Search cs %d\n" + }, + {0x009b0000, + "PMU3: Running 1D search for right eye edge\n" + }, + {0x009c0001, + "PMU1: In Phase Right Edge Search cs %d\n" + }, + {0x009d0001, + "PMU1: Out of Phase Right Edge Search cs %d\n" + }, + {0x009e0001, + "PMU1: mxRdLat training pstate %d\n" + }, + {0x009f0001, + "PMU1: mxRdLat search for cs %d\n" + }, + {0x00a00001, + "PMU0: MaxRdLat non consistent DtsmLoThldXingInd 0x%03x\n" + }, + {0x00a10003, + "PMU4: CS %d Dbyte %d worked with DFIMRL = %d DFICLKs\n" + }, + {0x00a20004, + "PMU3: MaxRdLat Read Lane err mask for csn %d, DFIMRL %2d DFIClks, dbyte %d = 0x%03x\n" + }, + {0x00a30003, + "PMU3: MaxRdLat Read Lane err mask for csn %d DFIMRL %2d, All dbytes = 0x%03x\n" + }, + {0x00a40001, + "PMU: Error: CS%d failed to find a DFIMRL setting that worked for all bytes during MaxRdLat training\n" + }, + {0x00a50002, + "PMU3: Smallest passing DFIMRL for all dbytes in CS%d = %d DFIClks\n" + }, + {0x00a60000, + "PMU: Error: No passing DFIMRL value found for any chip select during MaxRdLat training\n" + }, + {0x00a70003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00a80006, + "PMU10: Adjusting rxclkdly db %d nib %d from %d+%d=%d->%d\n" + }, + {0x00a90000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00aa0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00ab0002, + "PMU2: TXDQ delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00ac0004, + "PMU2: TXDQ delayLeft[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x00ad0002, + "PMU2: TXDQ delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00ae0004, + "PMU2: TXDQ delayRight[%2d] = %3d oopScaled = %3d selectOop %d\n" + }, + {0x00af0003, + "PMU: Error: Dbyte %d lane %d txDqDly passing region is too small (width = %d)\n" + }, + {0x00b00000, + "PMU4: TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00b10002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00b20005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00b30002, + "PMU3: Running 1D search csn %d for DM Right/NotLeft(%d) eye edge\n" + }, + {0x00b40002, + "PMU3: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00b50002, + "PMU3: WrDq DM byte%2d avgDly 0x%04x\n" + }, + {0x00b60002, + "PMU1: WrDq DM byte%2d with Errcnt %d\n" + }, + {0x00b70001, + "PMU: Error: Dbyte %d txDqDly DM training did not start inside the eye\n" + }, + {0x00b80000, + "PMU4: DM TxDqDly Passing Regions (EyeLeft EyeRight -> EyeCenter) Units=1/32 UI\n" + }, + {0x00b90002, + "PMU4: DB %d Lane %d: (DISCONNECTED)\n" + }, + {0x00ba0005, + "PMU4: DB %d Lane %d: %3d %3d -> %3d\n" + }, + {0x00bb0003, + "PMU: Error: Dbyte %d lane %d txDqDly DM passing region is too small (width = %d)\n" + }, + {0x00bc0004, + "PMU3: Errcnt for MRD/MWD search nib %2d delay = (%d, 0x%02x) = %d\n" + }, + {0x00bd0000, + "PMU3: Precharge all open banks\n" + }, + {0x00be0002, + "PMU: Error: Dbyte %d nibble %d found mutliple working coarse delay setting for MRD/MWD\n" + }, + {0x00bf0000, + "PMU4: MRD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x00c00000, + "PMU4: MWD Passing Regions (coarseVal, fineLeft fineRight -> fineCenter)\n" + }, + {0x00c10004, + "PMU10: Warning: DB %d nibble %d has multiple working coarse delays, %d and %d, choosing the smaller delay\n" + }, + {0x00c20003, + "PMU: Error: Dbyte %d nibble %d MRD/MWD passing region is too small (width = %d)\n" + }, + {0x00c30006, + "PMU4: DB %d nibble %d: %3d, %3d %3d -> %3d\n" + }, + {0x00c40002, + "PMU1: Start MRD/nMWD %d for csn %d\n" + }, + {0x00c50002, + "PMU2: RXDQS delayLeft[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00c60006, + "PMU2: RXDQS delayLeft[%2d] = %3d delayOop[%2d] = %3d OopScaled %4d, selectOop %d\n" + }, + {0x00c70002, + "PMU2: RXDQS delayRight[%2d] = %3d (DISCONNECTED)\n" + }, + {0x00c80006, + "PMU2: RXDQS delayRight[%2d] = %3d delayOop[%2d] = %4d OopScaled %4d, selectOop %d\n" + }, + {0x00c90000, + "PMU4: RxClkDly Passing Regions (EyeLeft EyeRight -> EyeCenter)\n" + }, + {0x00ca0002, + "PMU4: DB %d nibble %d: (DISCONNECTED)\n" + }, + {0x00cb0005, + "PMU4: DB %d nibble %d: %3d %3d -> %3d\n" + }, + {0x00cc0003, + "PMU: Error: Dbyte %d nibble %d rxClkDly passing region is too small (width = %d)\n" + }, + {0x00cd0002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00ce0001, + "PMU3: RxClkDly = %d\n" + }, + {0x00cf0005, + "PMU0: db %d l %d absLane %d -> bottom %d top %d\n" + }, + {0x00d00009, + "PMU3: BYTE %d - %3d %3d %3d %3d %3d %3d %3d %3d\n" + }, + {0x00d10002, + "PMU: Error: dbyte %d lane %d's per-lane vrefDAC's had no passing region\n" + }, + {0x00d20004, + "PMU0: db%d l%d - %d %d\n" + }, + {0x00d30002, + "PMU0: goodbar = %d for RDWR_BLEN %d\n" + }, + {0x00d40004, + "PMU3: db%d l%d saw %d issues at rxClkDly %d\n" + }, + {0x00d50003, + "PMU3: db%d l%d first saw a pass->fail edge at rxClkDly %d\n" + }, + {0x00d60002, + "PMU3: lane %d PBD = %d\n" + }, + {0x00d70003, + "PMU3: db%d l%d first saw a DBI pass->fail edge at rxClkDly %d\n" + }, + {0x00d80003, + "PMU2: db%d l%d already passed rxPBD = %d\n" + }, + {0x00d90003, + "PMU0: db%d l%d, PBD = %d\n" + }, + {0x00da0002, + "PMU: Error: dbyte %d lane %d failed read deskew\n" + }, + {0x00db0003, + "PMU0: db%d l%d, inc PBD = %d\n" + }, + {0x00dc0003, + "PMU1: Running lane deskew on pstate %d csn %d rdDBIEn %d\n" + }, + {0x00dd0000, + "PMU: Error: Read deskew training has been requested, but csrMajorModeDbyte[2] is set\n" + }, + {0x00de0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00df0002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00e00001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3U Type\n" + }, + {0x00e10001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D3R Type\n" + }, + {0x00e20001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4U Type\n" + }, + {0x00e30001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4R Type\n" + }, + {0x00e40001, + "PMU: Error: Wrong PMU image loaded. message Block DramType = 0x%02x, but image built for D4LR Type\n" + }, + {0x00e50000, + "PMU: Error: Both 2t timing mode and ddr4 geardown mode specified in the messageblock's PhyCfg and MR3 fields. Only one can be enabled\n" + }, + {0x00e60003, + "PMU10: PHY TOTALS - NUM_DBYTES %d NUM_NIBBLES %d NUM_ANIBS %d\n" + }, + {0x00e70006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR3\n" + }, + {0x00e80006, + "PMU10: CSA=0x%02x, CSB=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, MMISC=%d DRAMFreq=%dMT DramType=LPDDR4\n" + }, + {0x00e90008, + "PMU10: CS=0x%02x, TSTAGES=0x%04x, HDTOUT=%d, 2T=%d, MMISC=%d AddrMirror=%d DRAMFreq=%dMT DramType=%d\n" + }, + {0x00ea0004, + "PMU10: Pstate%d MR0=0x%04x MR1=0x%04x MR2=0x%04x\n" + }, + {0x00eb0008, + "PMU10: Pstate%d MRS MR0=0x%04x MR1=0x%04x MR2=0x%04x MR3=0x%04x MR4=0x%04x MR5=0x%04x MR6=0x%04x\n" + }, + {0x00ec0005, + "PMU10: Pstate%d MRS MR1_A0=0x%04x MR2_A0=0x%04x MR3_A0=0x%04x MR11_A0=0x%04x\n" + }, + {0x00ed0000, + "PMU10: UseBroadcastMR set. All ranks and channels use MRXX_A0 for MR settings.\n" + }, + {0x00ee0005, + "PMU10: Pstate%d MRS MR01_A0=0x%02x MR02_A0=0x%02x MR03_A0=0x%02x MR11_A0=0x%02x\n" + }, + {0x00ef0005, + "PMU10: Pstate%d MRS MR12_A0=0x%02x MR13_A0=0x%02x MR14_A0=0x%02x MR22_A0=0x%02x\n" + }, + {0x00f00005, + "PMU10: Pstate%d MRS MR01_A1=0x%02x MR02_A1=0x%02x MR03_A1=0x%02x MR11_A1=0x%02x\n" + }, + {0x00f10005, + "PMU10: Pstate%d MRS MR12_A1=0x%02x MR13_A1=0x%02x MR14_A1=0x%02x MR22_A1=0x%02x\n" + }, + {0x00f20005, + "PMU10: Pstate%d MRS MR01_B0=0x%02x MR02_B0=0x%02x MR03_B0=0x%02x MR11_B0=0x%02x\n" + }, + {0x00f30005, + "PMU10: Pstate%d MRS MR12_B0=0x%02x MR13_B0=0x%02x MR14_B0=0x%02x MR22_B0=0x%02x\n" + }, + {0x00f40005, + "PMU10: Pstate%d MRS MR01_B1=0x%02x MR02_B1=0x%02x MR03_B1=0x%02x MR11_B1=0x%02x\n" + }, + {0x00f50005, + "PMU10: Pstate%d MRS MR12_B1=0x%02x MR13_B1=0x%02x MR14_B1=0x%02x MR22_B1=0x%02x\n" + }, + {0x00f60002, + "PMU1: AcsmOdtCtrl%02d 0x%02x\n" + }, + {0x00f70002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00f80002, + "PMU1: AcsmCsMapCtrl%02d 0x%04x\n" + }, + {0x00f90000, + "PMU1: HwtCAMode set\n" + }, + {0x00fa0001, + "PMU3: DDR4 infinite preamble enter/exit mode %d\n" + }, + {0x00fb0002, + "PMU1: In rxenb_train() csn=%d pstate=%d\n" + }, + {0x00fc0000, + "PMU3: Finding DQS falling edge\n" + }, + {0x00fd0000, + "PMU3: Searching for DDR3/LPDDR3/LPDDR4 read preamble\n" + }, + {0x00fe0009, + "PMU3: dtsm fails Even Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x00ff0009, + "PMU3: dtsm fails Odd Nibbles : %2x %2x %2x %2x %2x %2x %2x %2x %2x\n" + }, + {0x01000002, + "PMU3: Preamble search pass=%d anyfail=%d\n" + }, + {0x01010000, + "PMU: Error: RxEn training preamble not found\n" + }, + {0x01020000, + "PMU3: Found DQS pre-amble\n" + }, + {0x01030001, + "PMU: Error: Dbyte %d couldn't find the rising edge of DQS during RxEn Training\n" + }, + {0x01040000, + "PMU3: RxEn aligning to first rising edge of burst\n" + }, + {0x01050001, + "PMU3: Decreasing RxEn delay by %d fine step to allow full capture of reads\n" + }, + {0x01060001, + "PMU3: MREP Delay = %d\n" + }, + {0x01070003, + "PMU3: Errcnt for MREP nib %2d delay = %2d is %d\n" + }, + {0x01080002, + "PMU3: MREP nibble %d sampled a 1 at data buffer delay %d\n" + }, + {0x01090002, + "PMU3: MREP nibble %d saw a 0 to 1 transition at data buffer delay %d\n" + }, + {0x010a0000, + "PMU2: MREP did not find a 0 to 1 transition for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x010b0002, + "PMU2: Rising edge found in alias window, setting rxDly for nibble %d = %d\n" + }, + {0x010c0002, + "PMU: Error: Failed MREP for nib %d with %d one\n" + }, + {0x010d0003, + "PMU2: Rising edge not found in alias window with %d one, leaving rxDly for nibble %d = %d\n" + }, + {0x010e0002, + "PMU3: Training DIMM %d CSn %d\n" + }, + {0x010f0001, + "PMU3: exitCAtrain_lp3 cs 0x%x\n" + }, + {0x01100001, + "PMU3: enterCAtrain_lp3 cs 0x%x\n" + }, + {0x01110001, + "PMU3: CAtrain_switchmsb_lp3 cs 0x%x\n" + }, + {0x01120001, + "PMU3: CATrain_rdwr_lp3 looking for pattern %x\n" + }, + {0x01130000, + "PMU3: exitCAtrain_lp4\n" + }, + {0x01140001, + "PMU3: DEBUG enterCAtrain_lp4 1: cs 0x%x\n" + }, + {0x01150001, + "PMU3: DEBUG enterCAtrain_lp4 3: Put dbyte %d in async mode\n" + }, + {0x01160000, + "PMU3: DEBUG enterCAtrain_lp4 5: Send MR13 to turn on CA training\n" + }, + {0x01170003, + "PMU3: DEBUG enterCAtrain_lp4 7: idx = %d vref = %x mr12 = %x\n" + }, + {0x01180001, + "PMU3: CATrain_rdwr_lp4 looking for pattern %x\n" + }, + {0x01190004, + "PMU3: Phase %d CAreadbackA db:%d %x xo:%x\n" + }, + {0x011a0005, + "PMU3: DEBUG lp4SetCatrVref 1: cs=%d chan=%d mr12=%x vref=%d.%d%%\n" + }, + {0x011b0003, + "PMU3: DEBUG lp4SetCatrVref 3: mr12 = %x send vref= %x to db=%d\n" + }, + {0x011c0000, + "PMU10:Optimizing vref\n" + }, + {0x011d0004, + "PMU4:mr12:%2x cs:%d chan %d r:%4x\n" + }, + {0x011e0005, + "PMU3: i:%2d bstr:%2d bsto:%2d st:%d r:%d\n" + }, + {0x011f0002, + "Failed to find sufficient CA Vref Passing Region for CS %d ch. %d\n" + }, + {0x01200005, + "PMU3:Found %d.%d%% MR12:%x for cs:%d chan %d\n" + }, + {0x01210002, + "PMU3:Calculated %d for AtxImpedence from acx %d.\n" + }, + {0x01220000, + "PMU3:CA Odt impedence ==0. Use default vref.\n" + }, + {0x01230003, + "PMU3:Calculated %d.%d%% for Vref MR12=0x%x.\n" + }, + {0x01240000, + "PMU3: CAtrain_lp\n" + }, + {0x01250000, + "PMU3: CAtrain Begins.\n" + }, + {0x01260001, + "PMU3: CAtrain_lp testing dly %d\n" + }, + {0x01270001, + "PMU5: CA bitmap dump for cs %x\n" + }, + {0x01280001, + "PMU5: CAA%d " + }, + {0x01290001, "%02x" + }, + {0x012a0000, "\n" + }, + {0x012b0001, + "PMU5: CAB%d " + }, + {0x012c0001, "%02x" + }, + {0x012d0000, "\n" + }, + {0x012e0003, + "PMU3: anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x012f0001, "%02x" + }, + {0x01300001, "\nPMU3:Raw CA setting :%x" + }, + {0x01310002, "\nPMU3:ATxDly setting:%x margin:%d\n" + }, + {0x01320002, "\nPMU3:InvClk ATxDly setting:%x margin:%d\n" + }, + {0x01330000, "\nPMU3:No Range found!\n" + }, + {0x01340003, + "PMU3: 2 anibi=%d, anibichan[anibi]=%d ,chan=%d" + }, + {0x01350002, "\nPMU3: no neg clock => CA setting anib=%d, :%d\n" + }, + {0x01360001, + "PMU3:Normal margin:%d\n" + }, + {0x01370001, + "PMU3:Inverted margin:%d\n" + }, + {0x01380000, + "PMU3:Using Inverted clock\n" + }, + {0x01390000, + "PMU3:Using normal clk\n" + }, + {0x013a0003, + "PMU3: 3 anibi=%d, anibichan[anibi]=%d ,chan=%d\n" + }, + {0x013b0002, + "PMU3: Setting ATxDly for anib %x to %x\n" + }, + {0x013c0000, + "PMU: Error: CA Training Failed.\n" + }, + {0x013d0000, + "PMU1: Writing MRs\n" + }, + {0x013e0000, + "PMU4:Using MR12 values from 1D CA VREF training.\n" + }, + {0x013f0000, + "PMU3:Writing all MRs to fsp 1\n" + }, + {0x01400000, + "PMU10:Lp4Quickboot mode.\n" + }, + {0x01410000, + "PMU3: Writing MRs\n" + }, + {0x01420001, + "PMU10: Setting boot clock divider to %d\n" + }, + {0x01430000, + "PMU3: Resetting DRAM\n" + }, + {0x01440000, + "PMU3: setup for RCD initalization\n" + }, + {0x01450000, + "PMU3: pmu_exit_SR from dev_init()\n" + }, + {0x01460000, + "PMU3: initializing RCD\n" + }, + {0x01470000, + "PMU10: **** Executing 2D Image ****\n" + }, + {0x01480001, + "PMU10: **** Start DDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x01490001, + "PMU10: **** Start DDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014a0001, + "PMU10: **** Start LPDDR3 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014b0001, + "PMU10: **** Start LPDDR4 Training. PMU Firmware Revision 0x%04x ****\n" + }, + {0x014c0000, + "PMU: Error: Mismatched internal revision between DCCM and ICCM images\n" + }, + {0x014d0001, + "PMU10: **** Testchip %d Specific Firmware ****\n" + }, + {0x014e0000, + "PMU1: LRDIMM with EncodedCS mode, one DIMM\n" + }, + {0x014f0000, + "PMU1: LRDIMM with EncodedCS mode, two DIMMs\n" + }, + {0x01500000, + "PMU1: RDIMM with EncodedCS mode, one DIMM\n" + }, + {0x01510000, + "PMU2: Starting LRDIMM MREP training for all ranks\n" + }, + {0x01520000, + "PMU199: LRDIMM MREP training for all ranks completed\n" + }, + {0x01530000, + "PMU2: Starting LRDIMM DWL training for all ranks\n" + }, + {0x01540000, + "PMU199: LRDIMM DWL training for all ranks completed\n" + }, + {0x01550000, + "PMU2: Starting LRDIMM MRD training for all ranks\n" + }, + {0x01560000, + "PMU199: LRDIMM MRD training for all ranks completed\n" + }, + {0x01570000, + "PMU2: Starting RXEN training for all ranks\n" + }, + {0x01580000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x01590000, + "PMU2: Starting LRDIMM MWD training for all ranks\n" + }, + {0x015a0000, + "PMU199: LRDIMM MWD training for all ranks completed\n" + }, + {0x015b0000, + "PMU2: Starting write leveling fine delay training for all ranks\n" + }, + {0x015c0000, + "PMU2: Starting read deskew training\n" + }, + {0x015d0000, + "PMU2: Starting SI friendly 1d RdDqs training for all ranks\n" + }, + {0x015e0000, + "PMU2: Starting write leveling coarse delay training for all ranks\n" + }, + {0x015f0000, + "PMU2: Starting 1d WrDq training for all ranks\n" + }, + {0x01600000, + "PMU2: Running DQS2DQ Oscillator for all ranks\n" + }, + {0x01610000, + "PMU2: Starting again read deskew training but with PRBS\n" + }, + {0x01620000, + "PMU2: Starting 1d RdDqs training for all ranks\n" + }, + {0x01630000, + "PMU2: Starting again 1d WrDq training for all ranks\n" + }, + {0x01640000, + "PMU2: Starting MaxRdLat training\n" + }, + {0x01650000, + "PMU2: Starting 2d WrDq training for all ranks\n" + }, + {0x01660000, + "PMU2: Starting 2d RdDqs training for all ranks\n" + }, + {0x01670002, + "PMU3:read_fifo %x %x\n" + }, + {0x01680001, + "PMU: Error: Invalid PhyDrvImpedance of 0x%x specified in message block.\n" + }, + {0x01690001, + "PMU: Error: Invalid PhyOdtImpedance of 0x%x specified in message block.\n" + }, + {0x016a0001, + "PMU: Error: Invalid BPZNResVal of 0x%x specified in message block.\n" + }, + {0x016b0005, + "PMU3: fixRxEnBackOff csn:%d db:%d dn:%d bo:%d dly:%x\n" + }, + {0x016c0001, + "PMU3: fixRxEnBackOff dly:%x\n" + }, + {0x016d0000, + "PMU3: Entering setupPpt\n" + }, + {0x016e0000, + "PMU3: Start lp4PopulateHighLowBytes\n" + }, + {0x016f0002, + "PMU3:Dbyte Detect: db%d received %x\n" + }, + {0x01700002, + "PMU3:getDqs2Dq read %x from dbyte %d\n" + }, + {0x01710002, + "PMU3:getDqs2Dq(2) read %x from dbyte %d\n" + }, + {0x01720001, + "PMU: Error: Dbyte %d read 0 from the DQS oscillator it is connected to\n" + }, + {0x01730002, + "PMU4: Dbyte %d dqs2dq = %d/32 UI\n" + }, + {0x01740003, + "PMU3:getDqs2Dq set dqs2dq:%d/32 ui (%d ps) from dbyte %d\n" + }, + {0x01750003, + "PMU3: Setting coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x01760003, + "PMU3: Clearing coarse delay in AtxDly chiplet %d from 0x%02x to 0x%02x\n" + }, + {0x01770000, + "PMU3: Performing DDR4 geardown sync sequence\n" + }, + {0x01780000, + "PMU1: Enter self refresh\n" + }, + {0x01790000, + "PMU1: Exit self refresh\n" + }, + {0x017a0000, + "PMU: Error: No dbiEnable with lp4\n" + }, + {0x017b0000, + "PMU: Error: No dbiDisable with lp4\n" + }, + {0x017c0001, + "PMU1: DDR4 update Rx DBI Setting disable %d\n" + }, + {0x017d0001, + "PMU1: DDR4 update 2nCk WPre Setting disable %d\n" + }, + {0x017e0005, + "PMU1: read_delay: db%d lane%d delays[%2d] = 0x%02x (max 0x%02x)\n" + }, + {0x017f0004, + "PMU1: write_delay: db%d lane%d delays[%2d] = 0x%04x\n" + }, + {0x01800001, + "PMU5: ID=%d -- db0 db1 db2 db3 db4 db5 db6 db7 db8 db9 --\n" + }, + {0x0181000b, + "PMU5: [%d]:0x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x\n" + }, + {0x01820003, + "PMU2: dump delays - pstate=%d dimm=%d csn=%d\n" + }, + {0x01830000, + "PMU3: Printing Mid-Training Delay Information\n" + }, + {0x01840001, + "PMU5: CS%d <> 0 TrainingCntr <> coarse(15:10) fine(9:0)\n" + }, + {0x01850001, + "PMU5: CS%d <> 0 RxEnDly, 1 RxClkDly <> coarse(10:6) fine(5:0)\n" + }, + {0x01860001, + "PMU5: CS%d <> 0 TxDqsDly, 1 TxDqDly <> coarse(9:6) fine(5:0)\n" + }, + {0x01870001, + "PMU5: CS%d <> 0 RxPBDly <> 1 Delay Unit ~= 7ps\n" + }, + {0x01880000, + "PMU5: all CS <> 0 DFIMRL <> Units = DFI clocks\n" + }, + {0x01890000, + "PMU5: all CS <> VrefDACs <> DAC(6:0)\n" + }, + {0x018a0000, + "PMU1: Set DMD in MR13 and wrDBI in MR3 for training\n" + }, + {0x018b0000, + "PMU: Error: getMaxRxen() failed to find largest rxen nibble delay\n" + }, + {0x018c0003, + "PMU2: getMaxRxen(): maxDly %d maxTg %d maxNib %d\n" + }, + {0x018d0003, + "PMU2: getRankMaxRxen(): maxDly %d Tg %d maxNib %d\n" + }, + {0x018e0000, + "PMU1: skipping CDD calculation in 2D image\n" + }, + {0x018f0001, + "PMU3: Calculating CDDs for pstate %d\n" + }, + {0x01900003, + "PMU3: rxFromDly[%d][%d] = %d\n" + }, + {0x01910003, + "PMU3: rxToDly [%d][%d] = %d\n" + }, + {0x01920003, + "PMU3: rxDly [%d][%d] = %d\n" + }, + {0x01930003, + "PMU3: txDly [%d][%d] = %d\n" + }, + {0x01940003, + "PMU3: allFine CDD_RR_%d_%d = %d\n" + }, + {0x01950003, + "PMU3: allFine CDD_WW_%d_%d = %d\n" + }, + {0x01960003, + "PMU3: CDD_RR_%d_%d = %d\n" + }, + {0x01970003, + "PMU3: CDD_WW_%d_%d = %d\n" + }, + {0x01980003, + "PMU3: allFine CDD_RW_%d_%d = %d\n" + }, + {0x01990003, + "PMU3: allFine CDD_WR_%d_%d = %d\n" + }, + {0x019a0003, + "PMU3: CDD_RW_%d_%d = %d\n" + }, + {0x019b0003, + "PMU3: CDD_WR_%d_%d = %d\n" + }, + {0x019c0004, + "PMU3: F%dBC2x_B%d_D%d = 0x%02x\n" + }, + {0x019d0004, + "PMU3: F%dBC3x_B%d_D%d = 0x%02x\n" + }, + {0x019e0004, + "PMU3: F%dBC4x_B%d_D%d = 0x%02x\n" + }, + {0x019f0004, + "PMU3: F%dBC5x_B%d_D%d = 0x%02x\n" + }, + {0x01a00004, + "PMU3: F%dBC8x_B%d_D%d = 0x%02x\n" + }, + {0x01a10004, + "PMU3: F%dBC9x_B%d_D%d = 0x%02x\n" + }, + {0x01a20004, + "PMU3: F%dBCAx_B%d_D%d = 0x%02x\n" + }, + {0x01a30004, + "PMU3: F%dBCBx_B%d_D%d = 0x%02x\n" + }, + {0x01a40000, + "PMU10: Entering context_switch_postamble\n" + }, + {0x01a50003, + "PMU10: context_switch_postamble is enabled for DIMM %d, RC0A=0x%x, RC3x=0x%x\n" + }, + {0x01a60000, + "PMU10: Setting bcw fspace 0\n" + }, + {0x01a70001, + "PMU10: Sending BC0A = 0x%x\n" + }, + {0x01a80001, + "PMU10: Sending BC6x = 0x%x\n" + }, + {0x01a90001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01aa0001, + "PMU10: Sending RC3x = 0x%x\n" + }, + {0x01ab0001, + "PMU10: Sending RC0A = 0x%x\n" + }, + {0x01ac0001, + "PMU1: enter_lp3: DEBUG: pstate = %d\n" + }, + {0x01ad0001, + "PMU1: enter_lp3: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x01ae0001, + "PMU1: enter_lp3: DEBUG: pllbypass = %d\n" + }, + {0x01af0001, + "PMU1: enter_lp3: DEBUG: forcecal = %d\n" + }, + {0x01b00001, + "PMU1: enter_lp3: DEBUG: pllmaxrange = 0x%x\n" + }, + {0x01b10001, + "PMU1: enter_lp3: DEBUG: dacval_out = 0x%x\n" + }, + {0x01b20001, + "PMU1: enter_lp3: DEBUG: pllctrl3 = 0x%x\n" + }, + {0x01b30000, + "PMU3: Loading DRAM with BIOS supplied MR values and entering self refresh prior to exiting PMU code.\n" + }, + {0x01b40002, + "PMU3: Setting DataBuffer function space of dimmcs 0x%02x to %d\n" + }, + {0x01b50002, + "PMU4: Setting RCW FxRC%Xx = 0x%02x\n" + }, + {0x01b60002, + "PMU4: Setting RCW FxRC%02x = 0x%02x\n" + }, + {0x01b70001, + "PMU1: DDR4 update Rd Pre Setting disable %d\n" + }, + {0x01b80002, + "PMU2: Setting BCW FxBC%Xx = 0x%02x\n" + }, + {0x01b90002, + "PMU2: Setting BCW BC%02x = 0x%02x\n" + }, + {0x01ba0002, + "PMU2: Setting BCW PBA mode FxBC%Xx = 0x%02x\n" + }, + {0x01bb0002, + "PMU2: Setting BCW PBA mode BC%02x = 0x%02x\n" + }, + {0x01bc0003, + "PMU4: BCW value for dimm %d, fspace %d, addr 0x%04x\n" + }, + {0x01bd0002, + "PMU4: DB %d, value 0x%02x\n" + }, + {0x01be0000, + "PMU6: WARNING MREP underflow, set to min value -2 coarse, 0 fine\n" + }, + {0x01bf0004, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d, new MREP fine %2d\n" + }, + {0x01c00003, + "PMU6: LRDIMM Writing final data buffer fine delay value nib %2d, trainDly %3d, fineDly code %2d\n" + }, + {0x01c10003, + "PMU6: LRDIMM Writing data buffer fine delay type %d nib %2d, code %2d\n" + }, + {0x01c20002, + "PMU6: Writing final data buffer coarse delay value dbyte %2d, coarse = 0x%02x\n" + }, + {0x01c30003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01c40003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01c50003, + "PMU4: data 0x%04x at MB addr 0x%08x saved at CSR addr 0x%08x\n" + }, + {0x01c60003, + "PMU4: data 0x%04x at MB addr 0x%08x restored from CSR addr 0x%08x\n" + }, + {0x01c70001, + "PMU3: Update BC00, BC01, BC02 for rank-dimm 0x%02x\n" + }, + {0x01c80000, + "PMU3: Writing D4 RDIMM RCD Control words F0RC00 -> F0RC0F\n" + }, + {0x01c90000, + "PMU3: Disable parity in F0RC0E\n" + }, + {0x01ca0000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC00 -> F1RC05\n" + }, + {0x01cb0000, + "PMU3: Writing D4 RDIMM RCD Control words F1RC1x -> F1RC9x\n" + }, + {0x01cc0000, + "PMU3: Writing D4 Data buffer Control words BC00 -> BC0E\n" + }, + {0x01cd0002, + "PMU1: setAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01ce0002, + "PMU1: restoreFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01cf0002, + "PMU1: restoreAcsmFromAltCL Sending MR0 0x%x cl=%d\n" + }, + {0x01d00002, + "PMU2: Setting D3R RC%d = 0x%01x\n" + }, + {0x01d10000, + "PMU3: Writing D3 RDIMM RCD Control words RC0 -> RC11\n" + }, + {0x01d20002, + "PMU0: VrefDAC0/1 vddqStart %d dacToVddq %d\n" + }, + {0x01d30001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated LPDDR4 receivers. Please see the pub databook\n" + }, + {0x01d40001, + "PMU: Error: Messageblock phyVref=0x%x is above the limit for TSMC28's attenuated DDR4 receivers. Please see the pub databook\n" + }, + {0x01d50001, + "PMU0: PHY VREF @ (%d/1000) VDDQ\n" + }, + {0x01d60002, + "PMU0: initalizing phy vrefDacs to %d ExtVrefRange %x\n" + }, + {0x01d70002, + "PMU0: initalizing global vref to %d range %d\n" + }, + {0x01d80002, + "PMU4: Setting initial device vrefDQ for CS%d to MR6 = 0x%04x\n" + }, + {0x01d90003, + "PMU1: In write_level_fine() csn=%d dimm=%d pstate=%d\n" + }, + {0x01da0000, + "PMU3: Fine write leveling hardware search increasing TxDqsDly until full bursts are seen\n" + }, + {0x01db0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01dc0007, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x\n" + }, + {0x01dd0000, + "PMU4: WL normalized pos : ........................|........................\n" + }, + {0x01de0000, + "PMU3: Exiting write leveling mode\n" + }, + {0x01df0001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01e00003, + "PMU1: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01e10003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01e20003, + "PMU3: right eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01e30004, + "PMU3: eye center db:%d ln:%d dly:0x%x (maxdq:%x)\n" + }, + {0x01e40003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01e50003, + "PMU3: Wrote to TxDqDly db:%d ln:%d dly:0x%x\n" + }, + {0x01e60002, + "PMU3: Coarse write leveling dbyte%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01e70002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01e80000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01e90001, + "PMU3: got %d for cl in load_wrlvl_acsm\n" + }, + {0x01ea0003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01eb0003, + "PMU3: left eye edge search db:%d ln:%d dly:0x%x\n" + }, + {0x01ec0003, + "PMU3: right eye edge search db: %d ln: %d dly: 0x%x\n" + }, + {0x01ed0004, + "PMU3: eye center db: %d ln: %d dly: 0x%x (maxdq: 0x%x)\n" + }, + {0x01ee0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x01ef0003, + "PMU3: Wrote to TxDqDly db: %d ln: %d dly: 0x%x\n" + }, + {0x01f00002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01f10002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01f20000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01f30000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01f40009, + "PMU4: WL margin for nib %2d: %08x%08x%08x%08x%08x%08x%08x%08x\n" + }, + {0x01f50000, + "PMU4: WL normalized pos : ................................|................................\n" + }, + {0x01f60001, + "PMU8: Adjust margin after WL coarse to be larger than %d\n" + }, + {0x01f70001, + "PMU: Error: All margin after write leveling coarse are smaller than minMargin %d\n" + }, + {0x01f80002, + "PMU8: Decrement nib %d TxDqsDly by %d fine step\n" + }, + {0x01f90003, + "PMU3: In write_level_coarse() csn=%d dimm=%d pstate=%d\n" + }, + {0x01fa0005, + "PMU2: Write level: dbyte %d nib%d dq/dmbi %2d dqsfine 0x%04x dqDly 0x%04x\n" + }, + {0x01fb0002, + "PMU3: Coarse write leveling nibble%2d is still failing for TxDqsDly=0x%04x\n" + }, + {0x01fc0002, + "PMU4: Coarse write leveling iteration %d saw %d data miscompares across the entire phy\n" + }, + {0x01fd0000, + "PMU: Error: Failed write leveling coarse\n" + }, + {0x01fe0001, + "PMU3: DWL delay = %d\n" + }, + {0x01ff0003, + "PMU3: Errcnt for DWL nib %2d delay = %2d is %d\n" + }, + {0x02000002, + "PMU3: DWL nibble %d sampled a 1 at delay %d\n" + }, + {0x02010003, + "PMU3: DWL nibble %d passed at delay %d. Rising edge was at %d\n" + }, + {0x02020000, + "PMU2: DWL did nto find a rising edge of memclk for all nibbles. Failing nibbles assumed to have rising edge close to fine delay 63\n" + }, + {0x02030002, + "PMU2: Rising edge found in alias window, setting wrlvlDly for nibble %d = %d\n" + }, + {0x02040002, + "PMU: Error: Failed DWL for nib %d with %d one\n" + }, + {0x02050003, + "PMU2: Rising edge not found in alias window with %d one, leaving wrlvlDly for nibble %d = %d\n" + }, + {0x04000000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04010000, + "PMU: Error:Mailbox Buffer Overflowed.\n" + }, + {0x04020000, + "PMU: ***** Assertion Error - terminating *****\n" + }, + {0x04030002, + "PMU1: swapByte db %d by %d\n" + }, + {0x04040003, + "PMU3: get_cmd_dly max(%d ps, %d memclk) = %d\n" + }, + {0x04050002, + "PMU0: Write CSR 0x%06x 0x%04x\n" + }, + {0x04060002, + "PMU0: hwt_init_ppgc_prbs(): Polynomial: %x, Deg: %d\n" + }, + {0x04070001, + "PMU: Error: acsm_set_cmd to non existent instruction address %d\n" + }, + {0x04080001, + "PMU: Error: acsm_set_cmd with unknown ddr cmd 0x%x\n" + }, + {0x0409000c, + "PMU1: acsm_addr %02x, acsm_flgs %04x, ddr_cmd %02x, cmd_dly %02x, ddr_addr %04x, ddr_bnk %02x, ddr_cs %02x, cmd_rcnt %02x, AcsmSeq0/1/2/3 %04x %04x %04x %04x\n" + }, + {0x040a0000, + "PMU: Error: Polling on ACSM done failed to complete in acsm_poll_done()...\n" + }, + {0x040b0000, + "PMU1: acsm RUN\n" + }, + {0x040c0000, + "PMU1: acsm STOPPED\n" + }, + {0x040d0002, + "PMU1: acsm_init: acsm_mode %04x mxrdlat %04x\n" + }, + {0x040e0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 2 and 5, resp. CL=%d CWL=%d\n" + }, + {0x040f0002, + "PMU: Error: setAcsmCLCWL: cl and cwl must be each >= 5. CL=%d CWL=%d\n" + }, + {0x04100002, + "PMU1: setAcsmCLCWL: CASL %04d WCASL %04d\n" + }, + {0x04110001, + "PMU: Error: Reserved value of register F0RC0F found in message block: 0x%04x\n" + }, + {0x04120001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04130001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x04140000, + "PMU3: Entering Boot Freq Mode.\n" + }, + {0x04150001, + "PMU: Error: Boot clock divider setting of %d is too small\n" + }, + {0x04160000, + "PMU3: Exiting Boot Freq Mode.\n" + }, + {0x04170002, + "PMU3: Writing MR%d OP=%x\n" + }, + {0x04180000, + "PMU: Error: Delay too large in slomo\n" + }, + {0x04190001, + "PMU3: Written MRS to CS=0x%02x\n" + }, + {0x041a0000, + "PMU3: Enable Channel A\n" + }, + {0x041b0000, + "PMU3: Enable Channel B\n" + }, + {0x041c0000, + "PMU3: Enable All Channels\n" + }, + {0x041d0002, + "PMU2: Use PDA mode to set MR%d with value 0x%02x\n" + }, + {0x041e0001, + "PMU3: Written Vref with PDA to CS=0x%02x\n" + }, + {0x041f0000, + "PMU1: start_cal: DEBUG: setting CalRun to 1\n" + }, + {0x04200000, + "PMU1: start_cal: DEBUG: setting CalRun to 0\n" + }, + {0x04210001, + "PMU1: lock_pll_dll: DEBUG: pstate = %d\n" + }, + {0x04220001, + "PMU1: lock_pll_dll: DEBUG: dfifreqxlat_pstate = %d\n" + }, + {0x04230001, + "PMU1: lock_pll_dll: DEBUG: pllbypass = %d\n" + }, + {0x04240001, + "PMU3: SaveLcdlSeed: Saving seed %d\n" + }, + {0x04250000, + "PMU1: in phy_defaults()\n" + }, + {0x04260003, + "PMU3: ACXConf:%d MaxNumDbytes:%d NumDfi:%d\n" + }, + {0x04270005, + "PMU1: setAltAcsmCLCWL setting cl=%d cwl=%d\n" + }, +}; +#endif /* DEBUG */ +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c new file mode 100644 index 0000000..7dbe3a3 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c @@ -0,0 +1,2673 @@ +/* + * Copyright 2021-2022 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include "csr.h" +#include +#include "ddr4fw.h" +#include +#ifdef NXP_WARM_BOOT +#include +#endif +#include "input.h" +#include +#include +#include +#ifdef DDR_PHY_DEBUG +#include "messages.h" +#endif +#ifdef NXP_WARM_BOOT +#include "phy.h" +#endif +#include "pie.h" + +#define TIMEOUTDEFAULT 500 +#define MAP_PHY_ADDR(pstate, n, instance, offset, c) \ + ((((pstate * n) + instance + c) << 12) + offset) + +static uint32_t map_phy_addr_space(uint32_t addr) +{ + /* 23 bit addressing */ + uint32_t pstate = (addr & U(0x700000)) >> 20U; /* bit 22:20 */ + uint32_t block_type = (addr & U(0x0f0000)) >> 16U; /* bit 19:16 */ + uint32_t instance = (addr & U(0x00f000)) >> 12U; /* bit 15:12 */ + uint32_t offset = (addr & U(0x000fff)); /* bit 11:0 */ + + switch (block_type) { + case 0x0: /* 0x0 : ANIB */ + return MAP_PHY_ADDR(pstate, 12, instance, offset, 0); + case 0x1: /* 0x1 : DBYTE */ + return MAP_PHY_ADDR(pstate, 10, instance, offset, 0x30); + case 0x2: /* 0x2 : MASTER */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x58); + case 0x4: /* 0x4 : ACSM */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x5c); + case 0x5: /* 0x5 : μCTL Memory */ + return MAP_PHY_ADDR(pstate, 0, instance, offset, 0x60); + case 0x7: /* 0x7 : PPGC */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x68); + case 0x9: /* 0x9 : INITENG */ + return MAP_PHY_ADDR(pstate, 1, 0, offset, 0x69); + case 0xc: /* 0xC : DRTUB */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6d); + case 0xd: /* 0xD : APB Only */ + return MAP_PHY_ADDR(pstate, 0, 0, offset, 0x6e); + default: + printf("ERR: Invalid block_type = 0x%x\n", block_type); + return 0; + } +} + +static inline uint16_t *phy_io_addr(void *phy, uint32_t addr) +{ + return phy + (map_phy_addr_space(addr) << 2); +} + +static inline void phy_io_write16(uint16_t *phy, uint32_t addr, uint16_t data) +{ + mmio_write_16((uintptr_t)phy_io_addr(phy, addr), data); +#ifdef DEBUG_PHY_IO + printf("0x%06x,0x%x\n", addr, data); +#endif +} + +static inline uint16_t phy_io_read16(uint16_t *phy, uint32_t addr) +{ + uint16_t reg = mmio_read_16((uintptr_t) phy_io_addr(phy, addr)); + +#ifdef DEBUG_PHY_IO + printf("R: 0x%06x,0x%x\n", addr, reg); +#endif + + return reg; +} + +#ifdef NXP_APPLY_MAX_CDD + +#define CDD_VAL_READ_ADDR (0x054012) +#define CDD_DATA_LEN (60) + +static void read_phy_reg(uint16_t *phy, uint32_t addr, + uint16_t *buf, uint32_t len) +{ + uint32_t i = 0U; + + for (i = 0U; i < len/2; i++) { + buf[i] = phy_io_read16(phy, (addr + i)); + } +} + +static uint32_t findrank(uint32_t cs_in_use) +{ + uint32_t val = 0U; + + switch (cs_in_use) { + case U(0xf): + val = 4U; + break; + case U(0x3): + val = 2U; + break; + case U(0x1): + val = 1U; + break; + default: + printf("Error - Invalid cs_in_use value\n"); + } + return val; +} + +static uint8_t findmax(uint8_t *buf, uint32_t len) +{ + uint8_t max = 0U; + uint32_t i = 0U; + + for (i = 0U; i < len; i++) { + if (buf[i] > max) { + max = buf[i]; + } + } + + return max; +} + +static void get_cdd_val(uint16_t **phy_ptr, uint32_t rank, uint32_t freq, + uint32_t *tcfg0, uint32_t *tcfg4) +{ + uint8_t cdd[CDD_DATA_LEN+4] = {0U}; + uint32_t i, val = 0U; + uint16_t *phy; + uint8_t buf[16] = {U(0x0)}; + uint8_t trr = 0U, tww = 0U, trw = 0U, twr = 0U; + uint8_t rrmax = 0U, wwmax = 0U, rwmax = 0U, wrmax = 0U; + uint8_t tmp = U(0x0); + uint8_t *c = NULL; + + for (i = 0U; i < NUM_OF_DDRC; i++) { + + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, U(0x0)); + + read_phy_reg(phy, CDD_VAL_READ_ADDR, + (uint16_t *)&cdd, CDD_DATA_LEN); + + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, U(0x1)); + + /* CDD values and address + * + * 0x054012 0x24 cdd[0] CDD[X][X] + * 0x054012 0x25 cdd[1] RR[3][2] + * 0x054013 0x26 cdd[2] RR[3][1] + * 0x054013 0x27 cdd[3] RR[3][0] + * 0x054014 0x28 cdd[4] RR[2][3] + * 0x054014 0x29 cdd[5] RR[2][1] + * 0x054015 0x2a cdd[6] RR[2][0] + * 0x054015 0x2b cdd[7] RR[1][3] + * 0x054016 0x2c cdd[8] RR[1][2] + * 0x054016 0x2d cdd[9] RR[1][0] + * 0x054017 0x2e cdd[10] RR[0][3] + * 0x054017 0x2f cdd[11] RR[0][2] + * 0x054018 0x30 cdd[12] RR[0][1] + + * 0x054018 0x31 cdd[13] WW[3][2] + * 0x054019 0x32 cdd[14] WW[3][1] + * 0x054019 0x33 cdd[15] WW[3][0] + * 0x05401a 0x34 cdd[16] WW[2][3] + * 0x05401a 0x35 cdd[17] WW[2][1] + * 0x05401b 0x36 cdd[18] WW[2][0] + * 0x05401b 0x37 cdd[19] WW[1][3] + * 0x05401c 0x38 cdd[20] WW[1][2] + * 0x05401c 0x39 cdd[21] WW[1][0] + * 0x05401d 0x3a cdd[22] WW[0][3] + * 0x05401d 0x3b cdd[23] WW[0][2] + * 0x05401e 0x3c cdd[24] WW[0][1] + + * 0x05401e 0x3d cdd[25] RW[3][3] + * 0x05401f 0x3e cdd[26] RW[3][2] + * 0x05401f 0x3f cdd[27] RW[3][1] + * 0x054020 0x40 cdd[28] RW[3][0] + * 0x054020 0x41 cdd[29] RW[2][3] + * 0x054021 0x42 cdd[30] RW[2][2] + * 0x054021 0x43 cdd[31] RW[2][1] + * 0x054022 0x44 cdd[32] RW[2][0] + * 0x054022 0x45 cdd[33] RW[1][3] + * 0x054023 0x46 cdd[34] RW[1][2] + * 0x054023 0x47 cdd[35] RW[1][1] + * 0x054024 0x48 cdd[36] RW[1][0] + * 0x054024 0x49 cdd[37] RW[0][3] + * 0x054025 0x4a cdd[38] RW[0][2] + * 0x054025 0x4b cdd[39] RW[0][1] + * 0x054026 0x4c cdd[40] RW[0][0] + + * 0x054026 0x4d cdd[41] WR[3][3] + * 0x054027 0x4e cdd[42] WR[3][2] + * 0x054027 0x4f cdd[43] WR[3][1] + * 0x054028 0x50 cdd[44] WR[3][0] + * 0x054028 0x51 cdd[45] WR[2][3] + * 0x054029 0x52 cdd[46] WR[2][2] + * 0x054029 0x53 cdd[47] WR[2][1] + * 0x05402a 0x54 cdd[48] WR[2][0] + * 0x05402a 0x55 cdd[49] WR[1][3] + * 0x05402b 0x56 cdd[50] WR[1][2] + * 0x05402b 0x57 cdd[51] WR[1][1] + * 0x05402c 0x58 cdd[52] WR[1][0] + * 0x05402c 0x59 cdd[53] WR[0][3] + * 0x05402d 0x5a cdd[54] WR[0][2] + * 0x05402d 0x5b cdd[55] WR[0][1] + * 0x05402e 0x5c cdd[56] WR[0][0] + * 0x05402e 0x5d cdd[57] CDD[Y][Y] + */ + + switch (rank) { + case 1U: + tmp = rwmax; + rwmax = cdd[40]; + if (tmp > rwmax) { + rwmax = tmp; + } + + tmp = wrmax; + wrmax = cdd[56]; + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + case 2U: + buf[0] = cdd[12]; + buf[1] = cdd[9]; + tmp = rrmax; + rrmax = findmax(buf, 2U); + if (tmp > rrmax) { + rrmax = tmp; + } + + buf[0] = cdd[24]; + buf[1] = cdd[21]; + tmp = wwmax; + wwmax = findmax(buf, 2U); + if (tmp > wwmax) { + wwmax = tmp; + } + + buf[0] = cdd[40]; + buf[1] = cdd[39]; + buf[2] = cdd[36]; + buf[3] = cdd[35]; + tmp = rwmax; + rwmax = findmax(buf, 4U); + if (tmp > rwmax) { + rwmax = tmp; + } + + buf[0] = cdd[56]; + buf[1] = cdd[55]; + buf[2] = cdd[52]; + buf[3] = cdd[51]; + tmp = wrmax; + wrmax = findmax(buf, 4U); + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + case 4U: + tmp = rrmax; + c = &cdd[1]; + rrmax = findmax(c, 12U); + if (tmp > rrmax) { + rrmax = tmp; + } + + tmp = wwmax; + c = &cdd[13]; + wwmax = findmax(c, 12U); + if (tmp > wwmax) { + wwmax = tmp; + } + + tmp = rwmax; + c = &cdd[25]; + rwmax = findmax(c, 16U); + if (tmp > rwmax) { + rwmax = tmp; + } + + tmp = wrmax; + c = &cdd[41]; + wrmax = findmax(c, 16U); + if (tmp > wrmax) { + wrmax = tmp; + } + + break; + + } + } + + rrmax += 3U; + wwmax += 4U; + + if (wwmax > 7U) { + wwmax = 7U; + } + + if (rrmax > 7U) { + rrmax = 7U; + } + + if (wrmax > U(0xf)) { + wrmax = 0U; + } + + if (rwmax > U(0x7)) { + rwmax = U(0x7); + } + + val = *tcfg0; + tww = (val >> 24U) & U(0x3); + trr = (val >> 26U) & U(0x3); + twr = (val >> 28U) & U(0x3); + trw = (val >> 30U) & U(0x3); + + val = *tcfg4; + tww = tww | (((val >> 8U) & U(0x1)) << 2U); + trr = trr | (((val >> 10U) & U(0x1)) << 2U); + twr = twr | (((val >> 12U) & U(0x1)) << 2U); + trw = trw | (((val >> 14U) & U(0x3)) << 2U); + + if (trr > rrmax) { + rrmax = trr; + } + + if (tww > wwmax) { + wwmax = tww; + } + + if (trw > rwmax) { + rwmax = trw; + } + + if (twr > wrmax) { + wrmax = twr; + } + + debug("CDD rrmax %x wwmax %x rwmax %x wrmax %x\n", + rrmax, wwmax, rwmax, wrmax); + + val = ((wwmax & U(0x3)) << 24U) + | ((rrmax & U(0x3)) << 26U) + | ((wrmax & U(0x3)) << 28U) + | ((rwmax & U(0x3)) << 30U); + + *tcfg0 = (*tcfg0 & U(0x00FFFFFF)) | (val); + + val = (((wwmax >> 2U) & U(0x1)) << 8U) + | (((rrmax >> 2U) & U(0x1)) << 10U) + | (((wrmax >> 2U) & U(0x1)) << 12U) + | (((rwmax >> 2U) & U(0x3)) << 14U); + + *tcfg4 = (*tcfg4 & U(0xffff00ff)) | val; +} +#endif + +#ifdef NXP_WARM_BOOT +int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store, + uint32_t num_of_phy, int train2d) +{ + uint16_t *phy = NULL, value = 0x0; + uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; + int i = 0, j = 0, ret = -EINVAL; + + ret = xspi_sector_erase(address_to_store, PHY_ERASE_SIZE); + if (ret != 0) { + return -EINVAL; + } + + for (j = 0; j < num_of_phy; j++) { + /* Save training values of all PHYs */ + phy = phy_ptr[j]; + size = sizeof(training_1D_values); + num_of_regs = ARRAY_SIZE(training_1D_values); + + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x0); + /* Enable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x3); + if (train2d != 0) { + /* Address to store training values is + * to be appended for next PHY + */ + phy_store = address_to_store + (j * + (sizeof(training_1D_values) + + sizeof(training_2D_values))); + } else { + phy_store = address_to_store + (j * + (sizeof(training_1D_values))); + } + debug("Saving 1D Training reg val at: %d\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + value = phy_io_read16(phy, training_1D_values[i].addr); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_1D_values[i].addr, value, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + training_1D_values[i].data = value; + } + /* Storing 1D training values on flash */ + ret = xspi_write(phy_store, (void *)training_1D_values, size); + if (train2d != 0) { + phy_store = phy_store+size; + size = sizeof(training_2D_values); + num_of_regs = ARRAY_SIZE(training_2D_values); + debug("Saving 2D Training reg val at:%d\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + value = phy_io_read16(phy, + training_2D_values[i].addr); + training_2D_values[i].data = value; +#ifdef DEBUG_WARM_RESET + debug("%d.2D addr:0x%x,val:0x%x,PHY:0x%p\n", + i, training_2D_values[i].addr, + value, phy_io_addr(phy, + training_2D_values[i].addr)); +#endif + } + /* Storing 2D training values on flash */ + ret = xspi_write(phy_store, training_2D_values, + size); + } + /* Disable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x0); + /* Disable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x1); + } + if (ret != 0) { + return -EINVAL; + } + + return 0; +} + +int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore, + uint32_t num_of_phy, int train2d) +{ + uint16_t *phy = NULL; + uint32_t size = 1U, num_of_regs = 1U, phy_store = 0U; + int i = 0, j = 0, ret = -EINVAL; + + debug("Restoring Training register values\n"); + for (j = 0; j < num_of_phy; j++) { + phy = phy_ptr[j]; + size = sizeof(training_1D_values); + num_of_regs = ARRAY_SIZE(training_1D_values); + if (train2d != 0) { + /* The address to restore training values is + * to be appended for next PHY + */ + phy_store = address_to_restore + (j * + (sizeof(training_1D_values) + + sizeof(training_2D_values))); + } else { + phy_store = address_to_restore + (j * + (sizeof(training_1D_values))); + } + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x0); + /* Enable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x3); + + /* Reading 1D training values from flash*/ + ret = xspi_read(phy_store, (uint32_t *)training_1D_values, + size); + debug("Restoring 1D Training reg val at:%08x\n", phy_store); + for (i = 0; i < num_of_regs; i++) { + phy_io_write16(phy, training_1D_values[i].addr, + training_1D_values[i].data); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_1D_values[i].addr, + training_1D_values[i].data, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + } + if (train2d != 0) { + phy_store = phy_store + size; + size = sizeof(training_2D_values); + num_of_regs = ARRAY_SIZE(training_2D_values); + /* Reading 2D training values from flash */ + ret = xspi_read(phy_store, + (uint32_t *)training_2D_values, size); + debug("Restoring 2D Training reg val at:%08x\n", + phy_store); + for (i = 0; i < num_of_regs; i++) { + phy_io_write16(phy, training_2D_values[i].addr, + training_2D_values[i].data); +#ifdef DEBUG_WARM_RESET + debug("%d. Reg: %x, value: %x PHY: %p\n", i, + training_2D_values[i].addr, + training_2D_values[i].data, + phy_io_addr(phy, + training_1D_values[i].addr)); +#endif + } + } + /* Disable clocks in case they were disabled. */ + phy_io_write16(phy, t_drtub | + csr_ucclk_hclk_enables_addr, 0x0); + /* Disable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | + csr_micro_cont_mux_sel_addr, 0x1); + } + if (ret != 0) { + return -EINVAL; + } + return 0; +} +#endif + +static void load_pieimage(uint16_t *phy, + enum dimm_types dimm_type) +{ + int i; + int size; + const struct pie *image = NULL; + + switch (dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + image = pie_udimm; + size = ARRAY_SIZE(pie_udimm); + break; + case RDIMM: + image = pie_rdimm; + size = ARRAY_SIZE(pie_rdimm); + break; + case LRDIMM: + image = pie_lrdimm; + size = ARRAY_SIZE(pie_lrdimm); + break; + default: + printf("Unsupported DIMM type\n"); + break; + } + + if (image != NULL) { + for (i = 0; i < size; i++) + phy_io_write16(phy, image[i].addr, image[i].data); + } +} + +static void prog_acsm_playback(uint16_t *phy, + const struct input *input, const void *msg) +{ + int vec; + const struct ddr4r1d *msg_blk; + uint16_t acsmplayback[2][3]; + uint32_t f0rc0a; + uint32_t f0rc3x; + uint32_t f0rc5x; + + if (input->basic.dimm_type != RDIMM) { + return; + } + + msg_blk = msg; + f0rc0a = (msg_blk->f0rc0a_d0 & U(0xf)) | U(0xa0); + f0rc3x = (msg_blk->f0rc3x_d0 & U(0xff)) | U(0x300); + f0rc5x = (input->adv.phy_gen2_umctl_f0rc5x & U(0xff)) | U(0x500); + + acsmplayback[0][0] = U(0x3ff) & f0rc0a; + acsmplayback[1][0] = (U(0x1c00) & f0rc0a) >> 10U; + acsmplayback[0][1] = U(0x3ff) & f0rc3x; + acsmplayback[1][1] = (U(0x1c00) & f0rc3x) >> 10U; + acsmplayback[0][2] = U(0x3ff) & f0rc5x; + acsmplayback[1][2] = (U(0x1c00) & f0rc5x) >> 10U; + for (vec = 0; vec < 3; vec++) { + phy_io_write16(phy, t_acsm | (csr_acsm_playback0x0_addr + + (vec << 1)), acsmplayback[0][vec]); + phy_io_write16(phy, t_acsm | (csr_acsm_playback1x0_addr + + (vec << 1)), acsmplayback[1][vec]); + } +} + +static void prog_acsm_ctr(uint16_t *phy, + const struct input *input) +{ + if (input->basic.dimm_type != RDIMM) { + return; + } + + phy_io_write16(phy, t_acsm | csr_acsm_ctrl13_addr, + 0xf << csr_acsm_cke_enb_lsb); + + phy_io_write16(phy, t_acsm | csr_acsm_ctrl0_addr, + csr_acsm_par_mode_mask | csr_acsm_2t_mode_mask); +} + +static void prog_cal_rate_run(uint16_t *phy, + const struct input *input) +{ + int cal_rate; + int cal_interval; + int cal_once; + uint32_t addr; + + cal_interval = input->adv.cal_interval; + cal_once = input->adv.cal_once; + cal_rate = 0x1 << csr_cal_run_lsb | + cal_once << csr_cal_once_lsb | + cal_interval << csr_cal_interval_lsb; + addr = t_master | csr_cal_rate_addr; + phy_io_write16(phy, addr, cal_rate); +} + +static void prog_seq0bdly0(uint16_t *phy, + const struct input *input) +{ + int ps_count[4]; + int frq; + uint32_t addr; + int lower_freq_opt = 0; + + __unused const soc_info_t *soc_info; + + frq = input->basic.frequency >> 1; + ps_count[0] = frq >> 3; /* 0.5 * frq / 4*/ + if (input->basic.frequency < 400) { + lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 7 : 3; + } else if (input->basic.frequency < 533) { + lower_freq_opt = (input->basic.dimm_type == RDIMM) ? 14 : 11; + } + + /* 1.0 * frq / 4 - lower_freq */ + ps_count[1] = (frq >> 2) - lower_freq_opt; + ps_count[2] = (frq << 1) + (frq >> 1); /* 10.0 * frq / 4 */ + +#ifdef DDR_PLL_FIX + soc_info = get_soc_info(); + if (soc_info->svr_reg.bf.maj_ver == 1) { + ps_count[0] = 0x520; /* seq0bdly0 */ + ps_count[1] = 0xa41; /* seq0bdly1 */ + ps_count[2] = 0x668a; /* seq0bdly2 */ + } +#endif + if (frq > 266) { + ps_count[3] = 44; + } else if (frq > 200) { + ps_count[3] = 33; + } else { + ps_count[3] = 16; + } + + addr = t_master | csr_seq0bdly0_addr; + phy_io_write16(phy, addr, ps_count[0]); + + debug("seq0bdly0 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly1_addr; + phy_io_write16(phy, addr, ps_count[1]); + + debug("seq0bdly1 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly2_addr; + phy_io_write16(phy, addr, ps_count[2]); + + debug("seq0bdly2 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_seq0bdly3_addr; + phy_io_write16(phy, addr, ps_count[3]); + + debug("seq0bdly3 = 0x%x\n", phy_io_read16(phy, addr)); +} + +/* Only RDIMM requires msg_blk */ +static void i_load_pie(uint16_t **phy_ptr, + const struct input *input, + const void *msg) +{ + int i; + uint16_t *phy; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + phy_io_write16(phy, + t_apbonly | csr_micro_cont_mux_sel_addr, + 0U); + + load_pieimage(phy, input->basic.dimm_type); + + prog_seq0bdly0(phy, input); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag0_addr, + U(0x0000)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag1_addr, + U(0x0173)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag2_addr, + U(0x0060)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag3_addr, + U(0x6110)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag4_addr, + U(0x2152)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag5_addr, + U(0xdfbd)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag6_addr, + input->basic.dimm_type == RDIMM && + input->adv.phy_gen2_umctl_opt == 1U ? + U(0x6000) : U(0xffff)); + phy_io_write16(phy, t_initeng | csr_seq0bdisable_flag7_addr, + U(0x6152)); + prog_acsm_playback(phy, input, msg); /* rdimm */ + prog_acsm_ctr(phy, input); /* rdimm */ + + phy_io_write16(phy, t_master | csr_cal_zap_addr, U(0x1)); + prog_cal_rate_run(phy, input); + + phy_io_write16(phy, t_drtub | csr_ucclk_hclk_enables_addr, + input->basic.dimm_type == RDIMM ? U(0x2) : 0U); + + phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 1U); + } +} + +static void phy_gen2_init_input(struct input *input) +{ + int i; + + input->adv.dram_byte_swap = 0; + input->adv.ext_cal_res_val = 0; + input->adv.tx_slew_rise_dq = 0xf; + input->adv.tx_slew_fall_dq = 0xf; + input->adv.tx_slew_rise_ac = 0xf; + input->adv.tx_slew_fall_ac = 0xf; + input->adv.mem_alert_en = 0; + input->adv.mem_alert_puimp = 5; + input->adv.mem_alert_vref_level = 0x29; + input->adv.mem_alert_sync_bypass = 0; + input->adv.cal_interval = 0x9; + input->adv.cal_once = 0; + input->adv.dis_dyn_adr_tri = 0; + input->adv.is2ttiming = 0; + input->adv.d4rx_preamble_length = 0; + input->adv.d4tx_preamble_length = 0; + + for (i = 0; i < 7; i++) { + debug("mr[%d] = 0x%x\n", i, input->mr[i]); + } + + debug("input->cs_d0 = 0x%x\n", input->cs_d0); + debug("input->cs_d1 = 0x%x\n", input->cs_d1); + debug("input->mirror = 0x%x\n", input->mirror); + debug("PHY ODT impedance = %d ohm\n", input->adv.odtimpedance); + debug("PHY DQ driver impedance = %d ohm\n", input->adv.tx_impedance); + debug("PHY Addr driver impedance = %d ohm\n", input->adv.atx_impedance); + + for (i = 0; i < 4; i++) { + debug("odt[%d] = 0x%x\n", i, input->odt[i]); + } + + if (input->basic.dimm_type == RDIMM) { + for (i = 0; i < 16; i++) { + debug("input->rcw[%d] = 0x%x\n", i, input->rcw[i]); + } + debug("input->rcw3x = 0x%x\n", input->rcw3x); + } +} + +/* + * All protocols share the same base structure of message block. + * RDIMM and LRDIMM have more entries defined than UDIMM. + * Create message blocks for 1D and 2D training. + * Update len with message block size. + */ +static int phy_gen2_msg_init(void *msg_1d, + void *msg_2d, + const struct input *input) +{ + struct ddr4u1d *msg_blk = msg_1d; + struct ddr4u2d *msg_blk_2d = msg_2d; + struct ddr4r1d *msg_blk_r; + struct ddr4lr1d *msg_blk_lr; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + msg_blk->dram_type = U(0x2); + break; + case RDIMM: + msg_blk->dram_type = U(0x4); + break; + case LRDIMM: + msg_blk->dram_type = U(0x5); + break; + default: + ERROR("Unsupported DIMM type\n"); + return -EINVAL; + } + msg_blk->pstate = 0U; + + /*Enable quickRd2D, a substage of read deskew, to 1D training.*/ + msg_blk->reserved00 = U(0x20); + + /*Enable High-Effort WrDQ1D.*/ + msg_blk->reserved00 |= U(0x40); + + /* Enable 1D extra effort training.*/ + msg_blk->reserved1c[3] = U(0x3); + + if (input->basic.dimm_type == LRDIMM) { + msg_blk->sequence_ctrl = U(0x3f1f); + } else { + msg_blk->sequence_ctrl = U(0x031f); + } + msg_blk->phy_config_override = 0U; +#ifdef DDR_PHY_DEBUG + msg_blk->hdt_ctrl = U(0x5); +#else + msg_blk->hdt_ctrl = U(0xc9); +#endif + msg_blk->msg_misc = U(0x0); + msg_blk->dfimrlmargin = U(0x1); + msg_blk->phy_vref = input->vref ? input->vref : U(0x61); + msg_blk->cs_present = input->cs_d0 | input->cs_d1; + msg_blk->cs_present_d0 = input->cs_d0; + msg_blk->cs_present_d1 = input->cs_d1; + if (input->mirror != 0) { + msg_blk->addr_mirror = U(0x0a); /* odd CS are mirrored */ + } + msg_blk->share2dvref_result = 1U; + + msg_blk->acsm_odt_ctrl0 = input->odt[0]; + msg_blk->acsm_odt_ctrl1 = input->odt[1]; + msg_blk->acsm_odt_ctrl2 = input->odt[2]; + msg_blk->acsm_odt_ctrl3 = input->odt[3]; + msg_blk->enabled_dqs = (input->basic.num_active_dbyte_dfi0 + + input->basic.num_active_dbyte_dfi1) * 8; + msg_blk->x16present = input->basic.dram_data_width == 0x10 ? + msg_blk->cs_present : 0; + msg_blk->d4misc = U(0x1); + msg_blk->cs_setup_gddec = U(0x1); + msg_blk->rtt_nom_wr_park0 = 0U; + msg_blk->rtt_nom_wr_park1 = 0U; + msg_blk->rtt_nom_wr_park2 = 0U; + msg_blk->rtt_nom_wr_park3 = 0U; + msg_blk->rtt_nom_wr_park4 = 0U; + msg_blk->rtt_nom_wr_park5 = 0U; + msg_blk->rtt_nom_wr_park6 = 0U; + msg_blk->rtt_nom_wr_park7 = 0U; + msg_blk->mr0 = input->mr[0]; + msg_blk->mr1 = input->mr[1]; + msg_blk->mr2 = input->mr[2]; + msg_blk->mr3 = input->mr[3]; + msg_blk->mr4 = input->mr[4]; + msg_blk->mr5 = input->mr[5]; + msg_blk->mr6 = input->mr[6]; + if ((msg_blk->mr4 & U(0x1c0)) != 0U) { + ERROR("Setting DRAM CAL mode is not supported\n"); + } + + msg_blk->alt_cas_l = 0U; + msg_blk->alt_wcas_l = 0U; + + msg_blk->dramfreq = input->basic.frequency * 2U; + msg_blk->pll_bypass_en = input->basic.pll_bypass; + msg_blk->dfi_freq_ratio = input->basic.dfi_freq_ratio == 0U ? 1U : + input->basic.dfi_freq_ratio == 1U ? 2U : + 4U; + msg_blk->bpznres_val = input->adv.ext_cal_res_val; + msg_blk->disabled_dbyte = 0U; + + debug("msg_blk->dram_type = 0x%x\n", msg_blk->dram_type); + debug("msg_blk->sequence_ctrl = 0x%x\n", msg_blk->sequence_ctrl); + debug("msg_blk->phy_cfg = 0x%x\n", msg_blk->phy_cfg); + debug("msg_blk->x16present = 0x%x\n", msg_blk->x16present); + debug("msg_blk->dramfreq = 0x%x\n", msg_blk->dramfreq); + debug("msg_blk->pll_bypass_en = 0x%x\n", msg_blk->pll_bypass_en); + debug("msg_blk->dfi_freq_ratio = 0x%x\n", msg_blk->dfi_freq_ratio); + debug("msg_blk->phy_odt_impedance = 0x%x\n", + msg_blk->phy_odt_impedance); + debug("msg_blk->phy_drv_impedance = 0x%x\n", + msg_blk->phy_drv_impedance); + debug("msg_blk->bpznres_val = 0x%x\n", msg_blk->bpznres_val); + debug("msg_blk->enabled_dqs = 0x%x\n", msg_blk->enabled_dqs); + debug("msg_blk->acsm_odt_ctrl0 = 0x%x\n", msg_blk->acsm_odt_ctrl0); + debug("msg_blk->acsm_odt_ctrl1 = 0x%x\n", msg_blk->acsm_odt_ctrl1); + debug("msg_blk->acsm_odt_ctrl2 = 0x%x\n", msg_blk->acsm_odt_ctrl2); + debug("msg_blk->acsm_odt_ctrl3 = 0x%x\n", msg_blk->acsm_odt_ctrl3); + + /* RDIMM only */ + if (input->basic.dimm_type == RDIMM || + input->basic.dimm_type == LRDIMM) { + msg_blk_r = (struct ddr4r1d *)msg_blk; + if (msg_blk_r->cs_present_d0 != 0U) { + msg_blk_r->f0rc00_d0 = input->rcw[0]; + msg_blk_r->f0rc01_d0 = input->rcw[1]; + msg_blk_r->f0rc02_d0 = input->rcw[2]; + msg_blk_r->f0rc03_d0 = input->rcw[3]; + msg_blk_r->f0rc04_d0 = input->rcw[4]; + msg_blk_r->f0rc05_d0 = input->rcw[5]; + msg_blk_r->f0rc06_d0 = input->rcw[6]; + msg_blk_r->f0rc07_d0 = input->rcw[7]; + msg_blk_r->f0rc08_d0 = input->rcw[8]; + msg_blk_r->f0rc09_d0 = input->rcw[9]; + msg_blk_r->f0rc0a_d0 = input->rcw[10]; + msg_blk_r->f0rc0b_d0 = input->rcw[11]; + msg_blk_r->f0rc0c_d0 = input->rcw[12]; + msg_blk_r->f0rc0d_d0 = input->rcw[13]; + msg_blk_r->f0rc0e_d0 = input->rcw[14]; + msg_blk_r->f0rc0f_d0 = input->rcw[15]; + msg_blk_r->f0rc3x_d0 = input->rcw3x; + } + if (msg_blk_r->cs_present_d1 != 0) { + msg_blk_r->f0rc00_d1 = input->rcw[0]; + msg_blk_r->f0rc01_d1 = input->rcw[1]; + msg_blk_r->f0rc02_d1 = input->rcw[2]; + msg_blk_r->f0rc03_d1 = input->rcw[3]; + msg_blk_r->f0rc04_d1 = input->rcw[4]; + msg_blk_r->f0rc05_d1 = input->rcw[5]; + msg_blk_r->f0rc06_d1 = input->rcw[6]; + msg_blk_r->f0rc07_d1 = input->rcw[7]; + msg_blk_r->f0rc08_d1 = input->rcw[8]; + msg_blk_r->f0rc09_d1 = input->rcw[9]; + msg_blk_r->f0rc0a_d1 = input->rcw[10]; + msg_blk_r->f0rc0b_d1 = input->rcw[11]; + msg_blk_r->f0rc0c_d1 = input->rcw[12]; + msg_blk_r->f0rc0d_d1 = input->rcw[13]; + msg_blk_r->f0rc0e_d1 = input->rcw[14]; + msg_blk_r->f0rc0f_d1 = input->rcw[15]; + msg_blk_r->f0rc3x_d1 = input->rcw3x; + } + if (input->basic.dimm_type == LRDIMM) { + msg_blk_lr = (struct ddr4lr1d *)msg_blk; + msg_blk_lr->bc0a_d0 = msg_blk_lr->f0rc0a_d0; + msg_blk_lr->bc0a_d1 = msg_blk_lr->f0rc0a_d1; + msg_blk_lr->f0bc6x_d0 = msg_blk_lr->f0rc3x_d0; + msg_blk_lr->f0bc6x_d1 = msg_blk_lr->f0rc3x_d1; + } + } + + /* below is different for 1D and 2D message block */ + if (input->basic.train2d != 0) { + memcpy(msg_blk_2d, msg_blk, sizeof(struct ddr4u1d)); + /*High-Effort WrDQ1D is applicable to 2D traning also*/ + msg_blk_2d->reserved00 |= U(0x40); + msg_blk_2d->sequence_ctrl = U(0x0061); + msg_blk_2d->rx2d_train_opt = 0U; + msg_blk_2d->tx2d_train_opt = 0U; + msg_blk_2d->share2dvref_result = 1U; + msg_blk_2d->delay_weight2d = U(0x20); + msg_blk_2d->voltage_weight2d = U(0x80); + debug("rx2d_train_opt %d, tx2d_train_opt %d\n", + msg_blk_2d->rx2d_train_opt, + msg_blk_2d->tx2d_train_opt); + } + + msg_blk->phy_cfg = (((msg_blk->mr3 & U(0x8)) != 0U) || + ((msg_blk_2d->mr3 & 0x8) != 0U)) ? 0U + : input->adv.is2ttiming; + + return 0; +} + +static void prog_tx_pre_drv_mode(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr, p_addr; + int tx_slew_rate, tx_pre_p, tx_pre_n; + int tx_pre_drv_mode = 0x2; + uint32_t addr; + + /* Program TxPreDrvMode with 0x2 */ + /* FIXME: TxPreDrvMode depends on DramType? */ + tx_pre_p = input->adv.tx_slew_rise_dq; + tx_pre_n = input->adv.tx_slew_fall_dq; + tx_slew_rate = tx_pre_drv_mode << csr_tx_pre_drv_mode_lsb | + tx_pre_p << csr_tx_pre_p_lsb | + tx_pre_n << csr_tx_pre_n_lsb; + p_addr = 0; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = p_addr | t_dbyte | c_addr | b_addr | + csr_tx_slew_rate_addr; + phy_io_write16(phy, addr, tx_slew_rate); + } + } +} + +static void prog_atx_pre_drv_mode(uint16_t *phy, + const struct input *input) +{ + int anib, c_addr; + int atx_slew_rate, atx_pre_p, atx_pre_n, atx_pre_drv_mode, + ck_anib_inst[2]; + uint32_t addr; + + atx_pre_n = input->adv.tx_slew_fall_ac; + atx_pre_p = input->adv.tx_slew_rise_ac; + + if (input->basic.num_anib == 8) { + ck_anib_inst[0] = 1; + ck_anib_inst[1] = 1; + } else if (input->basic.num_anib == 10 || input->basic.num_anib == 12 || + input->basic.num_anib == 13) { + ck_anib_inst[0] = 4; + ck_anib_inst[1] = 5; + } else { + ERROR("Invalid number of aNIBs: %d\n", input->basic.num_anib); + return; + } + + for (anib = 0; anib < input->basic.num_anib; anib++) { + c_addr = anib << 12; + if (anib == ck_anib_inst[0] || anib == ck_anib_inst[1]) { + atx_pre_drv_mode = 0; + } else { + atx_pre_drv_mode = 3; + } + atx_slew_rate = atx_pre_drv_mode << csr_atx_pre_drv_mode_lsb | + atx_pre_n << csr_atx_pre_n_lsb | + atx_pre_p << csr_atx_pre_p_lsb; + addr = t_anib | c_addr | csr_atx_slew_rate_addr; + phy_io_write16(phy, addr, atx_slew_rate); + } +} + +static void prog_enable_cs_multicast(uint16_t *phy, + const struct input *input) +{ + uint32_t addr = t_master | csr_enable_cs_multicast_addr; + + if (input->basic.dimm_type != RDIMM && + input->basic.dimm_type != LRDIMM) { + return; + } + + phy_io_write16(phy, addr, input->adv.cast_cs_to_cid); +} + +static void prog_dfi_rd_data_cs_dest_map(uint16_t *phy, + unsigned int ip_rev, + const struct input *input, + const struct ddr4lr1d *msg) +{ + const struct ddr4lr1d *msg_blk; + uint16_t dfi_xxdestm0 = 0U; + uint16_t dfi_xxdestm1 = 0U; + uint16_t dfi_xxdestm2 = 0U; + uint16_t dfi_xxdestm3 = 0U; + uint16_t dfi_rd_data_cs_dest_map; + uint16_t dfi_wr_data_cs_dest_map; + __unused const soc_info_t *soc_info; + +#ifdef ERRATA_DDR_A011396 + /* Only apply to DDRC 5.05.00 */ + soc_info = get_soc_info(); + if ((soc_info->svr_reg.bf.maj_ver == 1U) && (ip_rev == U(0x50500))) { + phy_io_write16(phy, + t_master | csr_dfi_rd_data_cs_dest_map_addr, + 0U); + return; + } +#endif + + msg_blk = msg; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + if ((msg_blk->msg_misc & U(0x40)) != 0U) { + dfi_rd_data_cs_dest_map = U(0xa0); + dfi_wr_data_cs_dest_map = U(0xa0); + + phy_io_write16(phy, + t_master | csr_dfi_rd_data_cs_dest_map_addr, + dfi_rd_data_cs_dest_map); + phy_io_write16(phy, + t_master | csr_dfi_wr_data_cs_dest_map_addr, + dfi_wr_data_cs_dest_map); + } + break; + case LRDIMM: + if (msg->cs_present_d1 != 0U) { + dfi_xxdestm2 = 1U; + dfi_xxdestm3 = 1U; + } + + dfi_rd_data_cs_dest_map = + dfi_xxdestm0 << csr_dfi_rd_destm0_lsb | + dfi_xxdestm1 << csr_dfi_rd_destm1_lsb | + dfi_xxdestm2 << csr_dfi_rd_destm2_lsb | + dfi_xxdestm3 << csr_dfi_rd_destm3_lsb; + dfi_wr_data_cs_dest_map = + dfi_xxdestm0 << csr_dfi_wr_destm0_lsb | + dfi_xxdestm1 << csr_dfi_wr_destm1_lsb | + dfi_xxdestm2 << csr_dfi_wr_destm2_lsb | + dfi_xxdestm3 << csr_dfi_wr_destm3_lsb; + phy_io_write16(phy, t_master | csr_dfi_rd_data_cs_dest_map_addr, + dfi_rd_data_cs_dest_map); + phy_io_write16(phy, t_master | csr_dfi_wr_data_cs_dest_map_addr, + dfi_wr_data_cs_dest_map); + + break; + default: + break; + } +} + +static void prog_pll_ctrl(uint16_t *phy, + const struct input *input) +{ + uint32_t addr; + int pll_ctrl1 = 0x21; /* 000100001b */ + int pll_ctrl4 = 0x17f; /* 101111111b */ + int pll_test_mode = 0x24; /* 00100100b */ + + addr = t_master | csr_pll_ctrl1_addr; + phy_io_write16(phy, addr, pll_ctrl1); + + debug("pll_ctrl1 = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_pll_test_mode_addr; + phy_io_write16(phy, addr, pll_test_mode); + + debug("pll_test_mode = 0x%x\n", phy_io_read16(phy, addr)); + + addr = t_master | csr_pll_ctrl4_addr; + phy_io_write16(phy, addr, pll_ctrl4); + + debug("pll_ctrl4 = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_pll_ctrl2(uint16_t *phy, + const struct input *input) +{ + int pll_ctrl2; + uint32_t addr = t_master | csr_pll_ctrl2_addr; + + if (input->basic.frequency / 2 < 235) { + pll_ctrl2 = 0x7; + } else if (input->basic.frequency / 2 < 313) { + pll_ctrl2 = 0x6; + } else if (input->basic.frequency / 2 < 469) { + pll_ctrl2 = 0xb; + } else if (input->basic.frequency / 2 < 625) { + pll_ctrl2 = 0xa; + } else if (input->basic.frequency / 2 < 938) { + pll_ctrl2 = 0x19; + } else if (input->basic.frequency / 2 < 1067) { + pll_ctrl2 = 0x18; + } else { + pll_ctrl2 = 0x19; + } + + phy_io_write16(phy, addr, pll_ctrl2); + + debug("pll_ctrl2 = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_dll_lck_param(uint16_t *phy, const struct input *input) +{ + uint32_t addr = t_master | csr_dll_lockparam_addr; + + phy_io_write16(phy, addr, U(0x212)); + debug("dll_lck_param = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_dll_gain_ctl(uint16_t *phy, const struct input *input) +{ + uint32_t addr = t_master | csr_dll_gain_ctl_addr; + + phy_io_write16(phy, addr, U(0x61)); + debug("dll_gain_ctl = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_pll_pwr_dn(uint16_t *phy, + const struct input *input) +{ + uint32_t addr; + + addr = t_master | csr_pll_pwr_dn_addr; + phy_io_write16(phy, addr, 0U); + + debug("pll_pwrdn = 0x%x\n", phy_io_read16(phy, addr)); +} + +static void prog_ard_ptr_init_val(uint16_t *phy, + const struct input *input) +{ + int ard_ptr_init_val; + uint32_t addr = t_master | csr_ard_ptr_init_val_addr; + + if (input->basic.frequency >= 933) { + ard_ptr_init_val = 0x2; + } else { + ard_ptr_init_val = 0x1; + } + + phy_io_write16(phy, addr, ard_ptr_init_val); +} + +static void prog_dqs_preamble_control(uint16_t *phy, + const struct input *input) +{ + int data; + uint32_t addr = t_master | csr_dqs_preamble_control_addr; + const int wdqsextension = 0; + const int lp4sttc_pre_bridge_rx_en = 0; + const int lp4postamble_ext = 0; + const int lp4tgl_two_tck_tx_dqs_pre = 0; + const int position_dfe_init = 2; + const int dll_rx_preamble_mode = 1; + int two_tck_tx_dqs_pre = input->adv.d4tx_preamble_length; + int two_tck_rx_dqs_pre = input->adv.d4rx_preamble_length; + + data = wdqsextension << csr_wdqsextension_lsb | + lp4sttc_pre_bridge_rx_en << csr_lp4sttc_pre_bridge_rx_en_lsb | + lp4postamble_ext << csr_lp4postamble_ext_lsb | + lp4tgl_two_tck_tx_dqs_pre << csr_lp4tgl_two_tck_tx_dqs_pre_lsb | + position_dfe_init << csr_position_dfe_init_lsb | + two_tck_tx_dqs_pre << csr_two_tck_tx_dqs_pre_lsb | + two_tck_rx_dqs_pre << csr_two_tck_rx_dqs_pre_lsb; + phy_io_write16(phy, addr, data); + + data = dll_rx_preamble_mode << csr_dll_rx_preamble_mode_lsb; + addr = t_master | csr_dbyte_dll_mode_cntrl_addr; + phy_io_write16(phy, addr, data); +} + +static void prog_proc_odt_time_ctl(uint16_t *phy, + const struct input *input) +{ + int proc_odt_time_ctl; + uint32_t addr = t_master | csr_proc_odt_time_ctl_addr; + + if (input->adv.wdqsext != 0) { + proc_odt_time_ctl = 0x3; + } else if (input->basic.frequency <= 933) { + proc_odt_time_ctl = 0xa; + } else if (input->basic.frequency <= 1200) { + if (input->adv.d4rx_preamble_length == 1) { + proc_odt_time_ctl = 0x2; + } else { + proc_odt_time_ctl = 0x6; + } + } else { + if (input->adv.d4rx_preamble_length == 1) { + proc_odt_time_ctl = 0x3; + } else { + proc_odt_time_ctl = 0x7; + } + } + phy_io_write16(phy, addr, proc_odt_time_ctl); +} + +static const struct impedance_mapping map[] = { + { 29, 0x3f }, + { 31, 0x3e }, + { 33, 0x3b }, + { 36, 0x3a }, + { 39, 0x39 }, + { 42, 0x38 }, + { 46, 0x1b }, + { 51, 0x1a }, + { 57, 0x19 }, + { 64, 0x18 }, + { 74, 0x0b }, + { 88, 0x0a }, + { 108, 0x09 }, + { 140, 0x08 }, + { 200, 0x03 }, + { 360, 0x02 }, + { 481, 0x01 }, + {} +}; + +static int map_impedance(int strength) +{ + const struct impedance_mapping *tbl = map; + int val = 0; + + if (strength == 0) { + return 0; + } + + while (tbl->ohm != 0U) { + if (strength < tbl->ohm) { + val = tbl->code; + break; + } + tbl++; + } + + return val; +} + +static int map_odtstren_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0; + } else if (strength == 120) { + val = 0x8; + } else if (strength == 60) { + val = 0x18; + } else if (strength == 40) { + val = 0x38; + } else { + printf("error: unsupported ODTStrenP %d\n", strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static void prog_tx_odt_drv_stren(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int tx_odt_drv_stren; + int odtstren_p, odtstren_n; + uint32_t addr; + + odtstren_p = map_odtstren_p(input->adv.odtimpedance, + input->basic.hard_macro_ver); + if (odtstren_p < 0) { + return; + } + + odtstren_n = 0; /* always high-z */ + tx_odt_drv_stren = odtstren_n << csr_odtstren_n_lsb | odtstren_p; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_tx_odt_drv_stren_addr; + phy_io_write16(phy, addr, tx_odt_drv_stren); + } + } +} + +static int map_drvstren_fsdq_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0x07; + } else if (strength == 120) { + val = 0x0F; + } else if (strength == 60) { + val = 0x1F; + } else if (strength == 40) { + val = 0x3F; + } else { + printf("error: unsupported drv_stren_fSDq_p %d\n", + strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static int map_drvstren_fsdq_n(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 0) { + val = 0x00; + } else if (strength == 120) { + val = 0x08; + } else if (strength == 60) { + val = 0x18; + } else if (strength == 40) { + val = 0x38; + } else { + printf("error: unsupported drvStrenFSDqN %d\n", + strength); + } + } else { + val = map_impedance(strength); + } + + return val; +} + +static void prog_tx_impedance_ctrl1(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int tx_impedance_ctrl1; + int drv_stren_fsdq_p, drv_stren_fsdq_n; + uint32_t addr; + + drv_stren_fsdq_p = map_drvstren_fsdq_p(input->adv.tx_impedance, + input->basic.hard_macro_ver); + drv_stren_fsdq_n = map_drvstren_fsdq_n(input->adv.tx_impedance, + input->basic.hard_macro_ver); + tx_impedance_ctrl1 = drv_stren_fsdq_n << csr_drv_stren_fsdq_n_lsb | + drv_stren_fsdq_p << csr_drv_stren_fsdq_p_lsb; + + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_tx_impedance_ctrl1_addr; + phy_io_write16(phy, addr, tx_impedance_ctrl1); + } + } +} + +static int map_adrv_stren_p(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 120) { + val = 0x1c; + } else if (strength == 60) { + val = 0x1d; + } else if (strength == 40) { + val = 0x1f; + } else { + printf("error: unsupported aDrv_stren_p %d\n", + strength); + } + } else { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else if (strength == 30) { + val = 0x07; + } else if (strength == 24) { + val = 0x0f; + } else if (strength == 20) { + val = 0x1f; + } else { + printf("error: unsupported aDrv_stren_p %d\n", + strength); + } + } + + return val; +} + +static int map_adrv_stren_n(int strength, int hard_macro_ver) +{ + int val = -1; + + if (hard_macro_ver == 4) { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else { + printf("Error: unsupported ADrvStrenP %d\n", strength); + } + } else { + if (strength == 120) { + val = 0x00; + } else if (strength == 60) { + val = 0x01; + } else if (strength == 40) { + val = 0x03; + } else if (strength == 30) { + val = 0x07; + } else if (strength == 24) { + val = 0x0f; + } else if (strength == 20) { + val = 0x1f; + } else { + printf("Error: unsupported ADrvStrenP %d\n", strength); + } + } + + return val; +} + +static void prog_atx_impedance(uint16_t *phy, + const struct input *input) +{ + int anib, c_addr; + int atx_impedance; + int adrv_stren_p; + int adrv_stren_n; + uint32_t addr; + + if (input->basic.hard_macro_ver == 4 && + input->adv.atx_impedance == 20) { + printf("Error:ATxImpedance has to be 40 for HardMacroVer 4\n"); + return; + } + + adrv_stren_p = map_adrv_stren_p(input->adv.atx_impedance, + input->basic.hard_macro_ver); + adrv_stren_n = map_adrv_stren_n(input->adv.atx_impedance, + input->basic.hard_macro_ver); + atx_impedance = adrv_stren_n << csr_adrv_stren_n_lsb | + adrv_stren_p << csr_adrv_stren_p_lsb; + for (anib = 0; anib < input->basic.num_anib; anib++) { + c_addr = anib << 12; + addr = t_anib | c_addr | csr_atx_impedance_addr; + phy_io_write16(phy, addr, atx_impedance); + } +} + +static void prog_dfi_mode(uint16_t *phy, + const struct input *input) +{ + int dfi_mode; + uint32_t addr; + + if (input->basic.dfi1exists == 1) { + dfi_mode = 0x5; /* DFI1 exists but disabled */ + } else { + dfi_mode = 0x1; /* DFI1 does not physically exists */ + } + addr = t_master | csr_dfi_mode_addr; + phy_io_write16(phy, addr, dfi_mode); +} + +static void prog_acx4_anib_dis(uint16_t *phy, const struct input *input) +{ + uint32_t addr; + + addr = t_master | csr_acx4_anib_dis_addr; + phy_io_write16(phy, addr, 0x0); + debug("%s 0x%x\n", __func__, phy_io_read16(phy, addr)); +} + +static void prog_dfi_camode(uint16_t *phy, + const struct input *input) +{ + int dfi_camode = 2; + uint32_t addr = t_master | csr_dfi_camode_addr; + + phy_io_write16(phy, addr, dfi_camode); +} + +static void prog_cal_drv_str0(uint16_t *phy, + const struct input *input) +{ + int cal_drv_str0; + int cal_drv_str_pd50; + int cal_drv_str_pu50; + uint32_t addr; + + cal_drv_str_pu50 = input->adv.ext_cal_res_val; + cal_drv_str_pd50 = cal_drv_str_pu50; + cal_drv_str0 = cal_drv_str_pu50 << csr_cal_drv_str_pu50_lsb | + cal_drv_str_pd50; + addr = t_master | csr_cal_drv_str0_addr; + phy_io_write16(phy, addr, cal_drv_str0); +} + +static void prog_cal_uclk_info(uint16_t *phy, + const struct input *input) +{ + int cal_uclk_ticks_per1u_s; + uint32_t addr; + + cal_uclk_ticks_per1u_s = input->basic.frequency >> 1; + if (cal_uclk_ticks_per1u_s < 24) { + cal_uclk_ticks_per1u_s = 24; + } + + addr = t_master | csr_cal_uclk_info_addr; + phy_io_write16(phy, addr, cal_uclk_ticks_per1u_s); +} + +static void prog_cal_rate(uint16_t *phy, + const struct input *input) +{ + int cal_rate; + int cal_interval; + int cal_once; + uint32_t addr; + + cal_interval = input->adv.cal_interval; + cal_once = input->adv.cal_once; + cal_rate = cal_once << csr_cal_once_lsb | + cal_interval << csr_cal_interval_lsb; + addr = t_master | csr_cal_rate_addr; + phy_io_write16(phy, addr, cal_rate); +} + +static void prog_vref_in_global(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int vref_in_global; + int global_vref_in_dac = 0; + int global_vref_in_sel = 0; + uint32_t addr; + + /* + * phy_vref_prcnt = msg->phy_vref / 128.0 + * global_vref_in_dac = (phy_vref_prcnt - 0.345) / 0.005; + */ + global_vref_in_dac = (msg->phy_vref * 1000 - 345 * 128 + 320) / + (5 * 128); + + vref_in_global = global_vref_in_dac << csr_global_vref_in_dac_lsb | + global_vref_in_sel; + addr = t_master | csr_vref_in_global_addr; + phy_io_write16(phy, addr, vref_in_global); +} + +static void prog_dq_dqs_rcv_cntrl(uint16_t *phy, + const struct input *input) +{ + int lane, byte, b_addr, c_addr; + int dq_dqs_rcv_cntrl; + int gain_curr_adj_defval = 0xb; + int major_mode_dbyte = 3; + int dfe_ctrl_defval = 0; + int ext_vref_range_defval = 0; + int sel_analog_vref = 1; + uint32_t addr; + +#ifdef ERRATA_DDR_A050958 + gain_curr_adj_defval = 0x1f; +#endif + + dq_dqs_rcv_cntrl = gain_curr_adj_defval << csr_gain_curr_adj_lsb | + major_mode_dbyte << csr_major_mode_dbyte_lsb | + dfe_ctrl_defval << csr_dfe_ctrl_lsb | + ext_vref_range_defval << csr_ext_vref_range_lsb | + sel_analog_vref << csr_sel_analog_vref_lsb; + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + for (lane = 0; lane <= 1; lane++) { + b_addr = lane << 8; + addr = t_dbyte | c_addr | b_addr | + csr_dq_dqs_rcv_cntrl_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl); + } + } +} + +static void prog_mem_alert_control(uint16_t *phy, + const struct input *input) +{ + int mem_alert_control; + int mem_alert_control2; + int malertpu_en; + int malertrx_en; + int malertvref_level; + int malertpu_stren; + int malertsync_bypass; + int malertdisable_val_defval = 1; + uint32_t addr; + + if (input->basic.dram_type == DDR4 && input->adv.mem_alert_en == 1) { + malertpu_en = 1; + malertrx_en = 1; + malertpu_stren = input->adv.mem_alert_puimp; + malertvref_level = input->adv.mem_alert_vref_level; + malertsync_bypass = input->adv.mem_alert_sync_bypass; + mem_alert_control = malertdisable_val_defval << 14 | + malertrx_en << 13 | + malertpu_en << 12 | + malertpu_stren << 8 | + malertvref_level; + mem_alert_control2 = malertsync_bypass << + csr_malertsync_bypass_lsb; + addr = t_master | csr_mem_alert_control_addr; + phy_io_write16(phy, addr, mem_alert_control); + addr = t_master | csr_mem_alert_control2_addr; + phy_io_write16(phy, addr, mem_alert_control2); + } +} + +static void prog_dfi_freq_ratio(uint16_t *phy, + const struct input *input) +{ + int dfi_freq_ratio; + uint32_t addr = t_master | csr_dfi_freq_ratio_addr; + + dfi_freq_ratio = input->basic.dfi_freq_ratio; + phy_io_write16(phy, addr, dfi_freq_ratio); +} + +static void prog_tristate_mode_ca(uint16_t *phy, + const struct input *input) +{ + int tristate_mode_ca; + int dis_dyn_adr_tri; + int ddr2tmode; + int ck_dis_val_def = 1; + uint32_t addr = t_master | csr_tristate_mode_ca_addr; + + dis_dyn_adr_tri = input->adv.dis_dyn_adr_tri; + ddr2tmode = input->adv.is2ttiming; + tristate_mode_ca = ck_dis_val_def << csr_ck_dis_val_lsb | + ddr2tmode << csr_ddr2tmode_lsb | + dis_dyn_adr_tri << csr_dis_dyn_adr_tri_lsb; + phy_io_write16(phy, addr, tristate_mode_ca); +} + +static void prog_dfi_xlat(uint16_t *phy, + const struct input *input) +{ + uint16_t loop_vector; + int dfifreqxlat_dat; + int pllbypass_dat; + uint32_t addr; + + /* fIXME: Shall unused P1, P2, P3 be bypassed? */ + pllbypass_dat = input->basic.pll_bypass; /* only [0] is used */ + for (loop_vector = 0; loop_vector < 8; loop_vector++) { + if (loop_vector == 0) { + dfifreqxlat_dat = pllbypass_dat + 0x5555; + } else if (loop_vector == 7) { + dfifreqxlat_dat = 0xf000; + } else { + dfifreqxlat_dat = 0x5555; + } + addr = t_master | (csr_dfi_freq_xlat0_addr + loop_vector); + phy_io_write16(phy, addr, dfifreqxlat_dat); + } +} + +static void prog_dbyte_misc_mode(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int dbyte_misc_mode; + int dq_dqs_rcv_cntrl1; + int dq_dqs_rcv_cntrl1_1; + int byte, c_addr; + uint32_t addr; + + dbyte_misc_mode = 0x1 << csr_dbyte_disable_lsb; + dq_dqs_rcv_cntrl1 = 0x1ff << csr_power_down_rcvr_lsb | + 0x1 << csr_power_down_rcvr_dqs_lsb | + 0x1 << csr_rx_pad_standby_en_lsb; + dq_dqs_rcv_cntrl1_1 = (0x100 << csr_power_down_rcvr_lsb | + csr_rx_pad_standby_en_mask); + for (byte = 0; byte < input->basic.num_dbyte; byte++) { + c_addr = byte << 12; + if (byte <= input->basic.num_active_dbyte_dfi0 - 1) { + /* disable RDBI lane if not used. */ + if ((input->basic.dram_data_width != 4) && + (((msg->mr5 >> 12) & 0x1) == 0)) { + addr = t_dbyte + | c_addr + | csr_dq_dqs_rcv_cntrl1_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1_1); + } + } else { + addr = t_dbyte | c_addr | csr_dbyte_misc_mode_addr; + phy_io_write16(phy, addr, dbyte_misc_mode); + addr = t_dbyte | c_addr | csr_dq_dqs_rcv_cntrl1_addr; + phy_io_write16(phy, addr, dq_dqs_rcv_cntrl1); + } + } +} + +static void prog_master_x4config(uint16_t *phy, + const struct input *input) +{ + int master_x4config; + int x4tg; + uint32_t addr = t_master | csr_master_x4config_addr; + + x4tg = input->basic.dram_data_width == 4 ? 0xf : 0; + master_x4config = x4tg << csr_x4tg_lsb; + phy_io_write16(phy, addr, master_x4config); +} + +static void prog_dmipin_present(uint16_t *phy, + const struct input *input, + const struct ddr4u1d *msg) +{ + int dmipin_present; + uint32_t addr = t_master | csr_dmipin_present_addr; + + dmipin_present = (msg->mr5 >> 12) & 0x1; + phy_io_write16(phy, addr, dmipin_present); +} + +static void prog_dfi_phyupd(uint16_t *phy, + const struct input *input) +{ + int dfiphyupd_dat; + uint32_t addr; + + addr = t_master | (csr_dfiphyupd_addr); + dfiphyupd_dat = phy_io_read16(phy, addr) & + ~csr_dfiphyupd_threshold_mask; + + phy_io_write16(phy, addr, dfiphyupd_dat); +} + +static void prog_cal_misc2(uint16_t *phy, + const struct input *input) +{ + int cal_misc2_dat, cal_drv_pdth_data, cal_offsets_dat; + uint32_t addr; + + addr = t_master | (csr_cal_misc2_addr); + cal_misc2_dat = phy_io_read16(phy, addr) | + (1 << csr_cal_misc2_err_dis); + + phy_io_write16(phy, addr, cal_misc2_dat); + + addr = t_master | (csr_cal_offsets_addr); + + cal_drv_pdth_data = 0x9 << 6; + cal_offsets_dat = (phy_io_read16(phy, addr) & ~csr_cal_drv_pdth_mask) + | cal_drv_pdth_data; + + phy_io_write16(phy, addr, cal_offsets_dat); +} + +static int c_init_phy_config(uint16_t **phy_ptr, + unsigned int ip_rev, + const struct input *input, + const void *msg) +{ + int i; + uint16_t *phy; + __unused const soc_info_t *soc_info; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + debug("Initialize PHY %d config\n", i); + prog_dfi_phyupd(phy, input); + prog_cal_misc2(phy, input); + prog_tx_pre_drv_mode(phy, input); + prog_atx_pre_drv_mode(phy, input); + prog_enable_cs_multicast(phy, input); /* rdimm and lrdimm */ + prog_dfi_rd_data_cs_dest_map(phy, ip_rev, input, msg); + prog_pll_ctrl2(phy, input); +#ifdef DDR_PLL_FIX + soc_info = get_soc_info(); + debug("SOC_SI_REV = %x\n", soc_info->svr_reg.bf.maj_ver); + if (soc_info->svr_reg.bf.maj_ver == 1) { + prog_pll_pwr_dn(phy, input); + + /*Enable FFE aka TxEqualizationMode for rev1 SI*/ + phy_io_write16(phy, 0x010048, 0x1); + } +#endif + prog_ard_ptr_init_val(phy, input); + prog_dqs_preamble_control(phy, input); + prog_dll_lck_param(phy, input); + prog_dll_gain_ctl(phy, input); + prog_proc_odt_time_ctl(phy, input); + prog_tx_odt_drv_stren(phy, input); + prog_tx_impedance_ctrl1(phy, input); + prog_atx_impedance(phy, input); + prog_dfi_mode(phy, input); + prog_dfi_camode(phy, input); + prog_cal_drv_str0(phy, input); + prog_cal_uclk_info(phy, input); + prog_cal_rate(phy, input); + prog_vref_in_global(phy, input, msg); + prog_dq_dqs_rcv_cntrl(phy, input); + prog_mem_alert_control(phy, input); + prog_dfi_freq_ratio(phy, input); + prog_tristate_mode_ca(phy, input); + prog_dfi_xlat(phy, input); + prog_dbyte_misc_mode(phy, input, msg); + prog_master_x4config(phy, input); + prog_dmipin_present(phy, input, msg); + prog_acx4_anib_dis(phy, input); + } + + return 0; +} + +static uint32_t get_mail(uint16_t *phy, int stream) +{ + int timeout; + uint32_t mail = 0U; + + timeout = TIMEOUTDEFAULT; + while (((--timeout) != 0) && + ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) + & uct_write_prot_shadow_mask) != 0)) { + mdelay(10); + } + if (timeout == 0) { + ERROR("Timeout getting mail from PHY\n"); + return 0xFFFF; + } + + mail = phy_io_read16(phy, t_apbonly | + csr_uct_write_only_shadow); + if (stream != 0) { + mail |= phy_io_read16(phy, t_apbonly | + csr_uct_dat_write_only_shadow) << 16; + } + + /* Ack */ + phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 0); + + timeout = TIMEOUTDEFAULT; + while (((--timeout) != 0) && + ((phy_io_read16(phy, t_apbonly | csr_uct_shadow_regs) + & uct_write_prot_shadow_mask) == 0)) { + mdelay(1); + } + if (timeout == 0) { + ERROR("Timeout ack PHY mail\n"); + } + + /* completed */ + phy_io_write16(phy, t_apbonly | csr_dct_write_prot, 1U); + + return mail; +} + +#ifdef DDR_PHY_DEBUG +static const char *lookup_msg(uint32_t index, int train2d) +{ + int i; + int size; + const struct phy_msg *messages; + const char *ptr = NULL; + + if (train2d != 0) { + messages = messages_2d; + size = ARRAY_SIZE(messages_2d); + } else { + messages = messages_1d; + size = ARRAY_SIZE(messages_1d); + } + for (i = 0; i < size; i++) { + if (messages[i].index == index) { + ptr = messages[i].msg; + break; + } + } + + return ptr; +} +#endif + +#define MAX_ARGS 32 +static void decode_stream_message(uint16_t *phy, int train2d) +{ + uint32_t index __unused; + + __unused const char *format; + __unused uint32_t args[MAX_ARGS]; + __unused int i; + +#ifdef DDR_PHY_DEBUG + index = get_mail(phy, 1); + if ((index & 0xffff) > MAX_ARGS) { /* up to MAX_ARGS args so far */ + printf("Program error in %s\n", __func__); + } + for (i = 0; i < (index & 0xffff) && i < MAX_ARGS; i++) { + args[i] = get_mail(phy, 1); + } + + format = lookup_msg(index, train2d); + if (format != NULL) { + printf("0x%08x: ", index); + printf(format, args[0], args[1], args[2], args[3], args[4], + args[5], args[6], args[7], args[8], args[9], args[10], + args[11], args[12], args[13], args[14], args[15], + args[16], args[17], args[18], args[19], args[20], + args[21], args[22], args[23], args[24], args[25], + args[26], args[27], args[28], args[29], args[30], + args[31]); + } +#endif +} + +static int wait_fw_done(uint16_t *phy, int train2d) +{ + uint32_t mail = 0U; + + while (mail == U(0x0)) { + mail = get_mail(phy, 0); + switch (mail) { + case U(0x7): + debug("%s Training completed\n", train2d ? "2D" : "1D"); + break; + case U(0xff): + debug("%s Training failure\n", train2d ? "2D" : "1D"); + break; + case U(0x0): + debug("End of initialization\n"); + mail = 0U; + break; + case U(0x1): + debug("End of fine write leveling\n"); + mail = 0U; + break; + case U(0x2): + debug("End of read enable training\n"); + mail = 0U; + break; + case U(0x3): + debug("End of read delay center optimization\n"); + mail = 0U; + break; + case U(0x4): + debug("End of write delay center optimization\n"); + mail = 0U; + break; + case U(0x5): + debug("End of 2D read delay/voltage center optimztn\n"); + mail = 0U; + break; + case U(0x6): + debug("End of 2D write delay/voltage center optmztn\n"); + mail = 0U; + break; + case U(0x8): + decode_stream_message(phy, train2d); + mail = 0U; + break; + case U(0x9): + debug("End of max read latency training\n"); + mail = 0U; + break; + case U(0xa): + debug("End of read dq deskew training\n"); + mail = 0U; + break; + case U(0xc): + debug("End of LRDIMM Specific training, including:\n"); + debug("/tDWL, MREP, MRD and MWD\n"); + mail = 0U; + break; + case U(0xd): + debug("End of CA training\n"); + mail = 0U; + break; + case U(0xfd): + debug("End of MPR read delay center optimization\n"); + mail = 0U; + break; + case U(0xfe): + debug("End of Write leveling coarse delay\n"); + mail = 0U; + break; + case U(0xffff): + debug("Timed out\n"); + break; + default: + mail = 0U; + break; + } + } + + if (mail == U(0x7)) { + return 0; + } else if (mail == U(0xff)) { + return -EIO; + } else if (mail == U(0xffff)) { + return -ETIMEDOUT; + } + + debug("PHY_GEN2 FW: Unxpected mail = 0x%x\n", mail); + + return -EINVAL; +} + +static int g_exec_fw(uint16_t **phy_ptr, int train2d, struct input *input) +{ + int ret = -EINVAL; + int i; + uint16_t *phy; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + debug("Applying PLL optimal settings\n"); + prog_pll_ctrl2(phy, input); + prog_pll_ctrl(phy, input); + phy_io_write16(phy, + t_apbonly | csr_micro_cont_mux_sel_addr, + 0x1); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + csr_reset_to_micro_mask | + csr_stall_to_micro_mask); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + csr_stall_to_micro_mask); + phy_io_write16(phy, + t_apbonly | csr_micro_reset_addr, + 0); + + ret = wait_fw_done(phy, train2d); + if (ret == -ETIMEDOUT) { + ERROR("Wait timed out: Firmware execution on PHY %d\n", + i); + } + } + return ret; +} + +static inline int send_fw(uint16_t *phy, + uint32_t dst, + uint16_t *img, + uint32_t size) +{ + uint32_t i; + + if ((size % 2U) != 0U) { + ERROR("Wrong image size 0x%x\n", size); + return -EINVAL; + } + + for (i = 0U; i < size / 2; i++) { + phy_io_write16(phy, dst + i, *(img + i)); + } + + return 0; +} + +static int load_fw(uint16_t **phy_ptr, + struct input *input, + int train2d, + void *msg, + size_t len, + uintptr_t phy_gen2_fw_img_buf, + int (*img_loadr)(unsigned int, uintptr_t *, uint32_t *), + uint32_t warm_boot_flag) +{ + uint32_t imem_id, dmem_id; + uintptr_t image_buf; + uint32_t size; + int ret; + int i; + uint16_t *phy; + + switch (input->basic.dimm_type) { + case UDIMM: + case SODIMM: + case NODIMM: + imem_id = train2d ? DDR_IMEM_UDIMM_2D_IMAGE_ID : + DDR_IMEM_UDIMM_1D_IMAGE_ID; + dmem_id = train2d ? DDR_DMEM_UDIMM_2D_IMAGE_ID : + DDR_DMEM_UDIMM_1D_IMAGE_ID; + break; + case RDIMM: + imem_id = train2d ? DDR_IMEM_RDIMM_2D_IMAGE_ID : + DDR_IMEM_RDIMM_1D_IMAGE_ID; + dmem_id = train2d ? DDR_DMEM_RDIMM_2D_IMAGE_ID : + DDR_DMEM_RDIMM_1D_IMAGE_ID; + break; + default: + ERROR("Unsupported DIMM type\n"); + return -EINVAL; + } + + size = PHY_GEN2_MAX_IMAGE_SIZE; + image_buf = (uintptr_t)phy_gen2_fw_img_buf; + mmap_add_dynamic_region(phy_gen2_fw_img_buf, + phy_gen2_fw_img_buf, + PHY_GEN2_MAX_IMAGE_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); + ret = img_loadr(imem_id, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load %d firmware.\n", imem_id); + return ret; + } + debug("Loaded Imaged id %d of size %x at address %lx\n", + imem_id, size, image_buf); + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + if (warm_boot_flag != DDR_WARM_BOOT) { + if (train2d == 0) { + phy_io_write16(phy, t_master | + csr_mem_reset_l_addr, + csr_protect_mem_reset_mask); + } + } + /* Enable access to the internal CSRs */ + phy_io_write16(phy, t_apbonly | csr_micro_cont_mux_sel_addr, 0); + + ret = send_fw(phy, PHY_GEN2_IMEM_ADDR, + (uint16_t *)image_buf, size); + if (ret != 0) { + return ret; + } + } + + size = PHY_GEN2_MAX_IMAGE_SIZE; + image_buf = (uintptr_t)phy_gen2_fw_img_buf; + ret = img_loadr(dmem_id, &image_buf, &size); + if (ret != 0) { + ERROR("Failed to load %d firmware.\n", dmem_id); + return ret; + } + debug("Loaded Imaged id %d of size %x at address %lx\n", + dmem_id, size, image_buf); + image_buf += len; + size -= len; + + for (i = 0; i < NUM_OF_DDRC; i++) { + phy = phy_ptr[i]; + if (phy == NULL) { + continue; + } + + ret = send_fw(phy, PHY_GEN2_DMEM_ADDR, msg, len); + if (ret != 0) { + return ret; + } + + ret = send_fw(phy, PHY_GEN2_DMEM_ADDR + len / 2, + (uint16_t *)image_buf, size); + if (ret != 0) { + return ret; + } + } + + return ret; +} + +static void parse_odt(const unsigned int val, + const int read, + const int i, + const unsigned int cs_d0, + const unsigned int cs_d1, + unsigned int *odt) +{ + int shift = read ? 4 : 0; + int j; + + if (i < 0 || i > 3) { + printf("Error: invalid chip-select value\n"); + } + switch (val) { + case DDR_ODT_CS: + odt[i] |= (1 << i) << shift; + break; + case DDR_ODT_ALL_OTHER_CS: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (i == j) { + continue; + } + if (((cs_d0 | cs_d1) & (1 << j)) == 0) { + continue; + } + odt[j] |= (1 << i) << shift; + } + break; + case DDR_ODT_CS_AND_OTHER_DIMM: + odt[i] |= (1 << i) << 4; + /* fallthrough */ + case DDR_ODT_OTHER_DIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_ALL: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (((cs_d0 | cs_d1) & (1 << j)) == 0) { + continue; + } + odt[j] |= (1 << i) << shift; + } + break; + case DDR_ODT_SAME_DIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_OTHER_CS_ONSAMEDIMM: + for (j = 0; j < DDRC_NUM_CS; j++) { + if (i == j) { + continue; + } + if ((((cs_d0 & (1 << i)) != 0) && + ((cs_d0 & (1 << j)) != 0)) || + (((cs_d1 & (1 << i)) != 0) && + ((cs_d1 & (1 << j)) != 0))) { + odt[j] |= (1 << i) << shift; + } + } + break; + case DDR_ODT_NEVER: + break; + default: + break; + } +} + +#ifdef DEBUG_DDR_INPUT_CONFIG +char *dram_types_str[] = { + "DDR4", + "DDR3", + "LDDDR4", + "LPDDR3", + "LPDDR2", + "DDR5" +}; + +char *dimm_types_str[] = { + "UDIMM", + "SODIMM", + "RDIMM", + "LRDIMM", + "NODIMM", +}; + + +static void print_jason_format(struct input *input, + struct ddr4u1d *msg_1d, + struct ddr4u2d *msg_2d) +{ + + printf("\n{"); + printf("\n \"dram_type\": \"%s\",", dram_types_str[input->basic.dram_type]); + printf("\n \"dimm_type\": \"%s\",", dimm_types_str[input->basic.dimm_type]); + printf("\n \"hard_macro_ver\": \"%d\",", input->basic.hard_macro_ver); + printf("\n \"num_dbyte\": \"0x%04x\",", (unsigned int)input->basic.num_dbyte); + printf("\n \"num_active_dbyte_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_active_dbyte_dfi0); + printf("\n \"num_anib\": \"0x%04x\",", (unsigned int)input->basic.num_anib); + printf("\n \"num_rank_dfi0\": \"0x%04x\",", (unsigned int)input->basic.num_rank_dfi0); + printf("\n \"num_pstates\": \"0x%04x\",", (unsigned int)input->basic.num_pstates); + printf("\n \"frequency\": \"%d\",", input->basic.frequency); + printf("\n \"pll_bypass\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); + printf("\n \"dfi_freq_ratio\": \"0x%04x\",", (unsigned int)input->basic.dfi_freq_ratio); + printf("\n \"dfi1_exists\": \"0x%04x\",", (unsigned int)input->basic.dfi1exists); + printf("\n \"dram_data_width\": \"0x%04x\",", (unsigned int)input->basic.dram_data_width); + printf("\n \"dram_byte_swap\": \"0x%04x\",", (unsigned int)input->adv.dram_byte_swap); + printf("\n \"ext_cal_res_val\": \"0x%04x\",", (unsigned int)input->adv.ext_cal_res_val); + printf("\n \"tx_slew_rise_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_dq); + printf("\n \"tx_slew_fall_dq\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_dq); + printf("\n \"tx_slew_rise_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_rise_ac); + printf("\n \"tx_slew_fall_ac\": \"0x%04x\",", (unsigned int)input->adv.tx_slew_fall_ac); + printf("\n \"odt_impedance\": \"%d\",", input->adv.odtimpedance); + printf("\n \"tx_impedance\": \"%d\",", input->adv.tx_impedance); + printf("\n \"atx_impedance\": \"%d\",", input->adv.atx_impedance); + printf("\n \"mem_alert_en\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_en); + printf("\n \"mem_alert_pu_imp\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_puimp); + printf("\n \"mem_alert_vref_level\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_vref_level); + printf("\n \"mem_alert_sync_bypass\": \"0x%04x\",", (unsigned int)input->adv.mem_alert_sync_bypass); + printf("\n \"cal_interval\": \"0x%04x\",", (unsigned int)input->adv.cal_interval); + printf("\n \"cal_once\": \"0x%04x\",", (unsigned int)input->adv.cal_once); + printf("\n \"dis_dyn_adr_tri\": \"0x%04x\",", (unsigned int)input->adv.dis_dyn_adr_tri); + printf("\n \"is2t_timing\": \"0x%04x\",", (unsigned int)input->adv.is2ttiming); + printf("\n \"d4rx_preabmle_length\": \"0x%04x\",", (unsigned int)input->adv.d4rx_preamble_length); + printf("\n \"d4tx_preamble_length\": \"0x%04x\",", (unsigned int)input->adv.d4tx_preamble_length); + printf("\n \"msg_misc\": \"0x%02x\",", (unsigned int)msg_1d->msg_misc); + printf("\n \"reserved00\": \"0x%01x\",", (unsigned int)msg_1d->reserved00); + printf("\n \"hdt_ctrl\": \"0x%02x\",", (unsigned int)msg_1d->hdt_ctrl); + printf("\n \"cs_present\": \"0x%02x\",", (unsigned int)msg_1d->cs_present); + printf("\n \"phy_vref\": \"0x%02x\",", (unsigned int)msg_1d->phy_vref); + printf("\n \"dfi_mrl_margin\": \"0x%02x\",", (unsigned int)msg_1d->dfimrlmargin); + printf("\n \"addr_mirror\": \"0x%02x\",", (unsigned int)msg_1d->addr_mirror); + printf("\n \"wr_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0x0f)); + printf("\n \"wr_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0x0f)); + printf("\n \"wr_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0x0f)); + printf("\n \"wr_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0x0f)); + printf("\n \"rd_odt_pat_rank0\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl0 & 0xf0)); + printf("\n \"rd_odt_pat_rank1\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl1 & 0xf0)); + printf("\n \"rd_odt_pat_rank2\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl2 & 0xf0)); + printf("\n \"rd_odt_pat_rank3\": \"0x%02x\",", (unsigned int)(msg_1d->acsm_odt_ctrl3 & 0xf0)); + printf("\n \"d4_misc\": \"0x%01x\",", (unsigned int)msg_1d->d4misc); + printf("\n \"share_2d_vref_results\": \"0x%01x\",", (unsigned int)msg_1d->share2dvref_result); + printf("\n \"sequence_ctrl\": \"0x%04x\",", (unsigned int)msg_1d->sequence_ctrl); + printf("\n \"mr0\": \"0x%04x\",", (unsigned int)msg_1d->mr0); + printf("\n \"mr1\": \"0x%04x\",", (unsigned int)msg_1d->mr1); + printf("\n \"mr2\": \"0x%04x\",", (unsigned int)msg_1d->mr2); + printf("\n \"mr3\": \"0x%04x\",", (unsigned int)msg_1d->mr3); + printf("\n \"mr4\": \"0x%04x\",", (unsigned int)msg_1d->mr4); + printf("\n \"mr5\": \"0x%04x\",", (unsigned int)msg_1d->mr5); + printf("\n \"mr6\": \"0x%04x\",", (unsigned int)msg_1d->mr6); + printf("\n \"alt_cal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_cas_l); + printf("\n \"alt_wcal_l\": \"0x%04x\",", (unsigned int)msg_1d->alt_wcas_l); + printf("\n \"sequence_ctrl_2d\": \"0x%04x\",", (unsigned int)msg_2d->sequence_ctrl); + printf("\n \"rtt_nom_wr_park0\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park0); + printf("\n \"rtt_nom_wr_park1\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park1); + printf("\n \"rtt_nom_wr_park2\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park2); + printf("\n \"rtt_nom_wr_park3\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park3); + printf("\n \"rtt_nom_wr_park4\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park4); + printf("\n \"rtt_nom_wr_park5\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park5); + printf("\n \"rtt_nom_wr_park6\": \"0x%01x\",", (unsigned int)msg_1d->rtt_nom_wr_park6); + printf("\n \"rtt_nom_wr_park7\": \"0x%01x\"", (unsigned int)msg_1d->rtt_nom_wr_park7); + printf("\n}"); + printf("\n"); +} +#endif + +int compute_ddr_phy(struct ddr_info *priv) +{ + const unsigned long clk = priv->clk; + const struct memctl_opt *popts = &priv->opt; + const struct ddr_conf *conf = &priv->conf; + const struct dimm_params *dimm_param = &priv->dimm; + struct ddr_cfg_regs *regs = &priv->ddr_reg; + int ret; + static struct input input; + static struct ddr4u1d msg_1d; + static struct ddr4u2d msg_2d; + unsigned int i; + unsigned int odt_rd, odt_wr; + __unused const soc_info_t *soc_info; +#ifdef NXP_APPLY_MAX_CDD + unsigned int tcfg0, tcfg4, rank; +#endif + + if (dimm_param == NULL) { + ERROR("Empty DIMM parameters.\n"); + return -EINVAL; + } + + zeromem(&input, sizeof(input)); + zeromem(&msg_1d, sizeof(msg_1d)); + zeromem(&msg_2d, sizeof(msg_2d)); + + input.basic.dram_type = DDR4; + /* FIXME: Add condition for LRDIMM */ + input.basic.dimm_type = (dimm_param->rdimm != 0) ? RDIMM : UDIMM; + input.basic.num_dbyte = dimm_param->primary_sdram_width / 8 + + dimm_param->ec_sdram_width / 8; + input.basic.num_active_dbyte_dfi0 = input.basic.num_dbyte; + input.basic.num_rank_dfi0 = dimm_param->n_ranks; + input.basic.dram_data_width = dimm_param->device_width; + input.basic.hard_macro_ver = 0xa; + input.basic.num_pstates = 1; + input.basic.dfi_freq_ratio = 1; + input.basic.num_anib = 0xc; + input.basic.train2d = popts->skip2d ? 0 : 1; + input.basic.frequency = (int) (clk / 2000000ul); + debug("frequency = %dMHz\n", input.basic.frequency); + input.cs_d0 = conf->cs_on_dimm[0]; +#if DDRC_NUM_DIMM > 1 + input.cs_d1 = conf->cs_on_dimm[1]; +#endif + input.mirror = dimm_param->mirrored_dimm; + input.mr[0] = regs->sdram_mode[0] & U(0xffff); + input.mr[1] = regs->sdram_mode[0] >> 16U; + input.mr[2] = regs->sdram_mode[1] >> 16U; + input.mr[3] = regs->sdram_mode[1] & U(0xffff); + input.mr[4] = regs->sdram_mode[8] >> 16U; + input.mr[5] = regs->sdram_mode[8] & U(0xffff); + input.mr[6] = regs->sdram_mode[9] >> 16U; + input.vref = popts->vref_phy; + debug("Vref_phy = %d percent\n", (input.vref * 100U) >> 7U); + for (i = 0U; i < DDRC_NUM_CS; i++) { + if ((regs->cs[i].config & SDRAM_CS_CONFIG_EN) == 0U) { + continue; + } + odt_rd = (regs->cs[i].config >> 20U) & U(0x7); + odt_wr = (regs->cs[i].config >> 16U) & U(0x7); + parse_odt(odt_rd, true, i, input.cs_d0, input.cs_d1, + input.odt); + parse_odt(odt_wr, false, i, input.cs_d0, input.cs_d1, + input.odt); + } + + /* Do not set sdram_cfg[RD_EN] or sdram_cfg2[RCW_EN] for RDIMM */ + if (dimm_param->rdimm != 0U) { + regs->sdram_cfg[0] &= ~(1 << 28U); + regs->sdram_cfg[1] &= ~(1 << 2U); + input.rcw[0] = (regs->sdram_rcw[0] >> 28U) & U(0xf); + input.rcw[1] = (regs->sdram_rcw[0] >> 24U) & U(0xf); + input.rcw[2] = (regs->sdram_rcw[0] >> 20U) & U(0xf); + input.rcw[3] = (regs->sdram_rcw[0] >> 16U) & U(0xf); + input.rcw[4] = (regs->sdram_rcw[0] >> 12U) & U(0xf); + input.rcw[5] = (regs->sdram_rcw[0] >> 8U) & U(0xf); + input.rcw[6] = (regs->sdram_rcw[0] >> 4U) & U(0xf); + input.rcw[7] = (regs->sdram_rcw[0] >> 0U) & U(0xf); + input.rcw[8] = (regs->sdram_rcw[1] >> 28U) & U(0xf); + input.rcw[9] = (regs->sdram_rcw[1] >> 24U) & U(0xf); + input.rcw[10] = (regs->sdram_rcw[1] >> 20U) & U(0xf); + input.rcw[11] = (regs->sdram_rcw[1] >> 16U) & U(0xf); + input.rcw[12] = (regs->sdram_rcw[1] >> 12U) & U(0xf); + input.rcw[13] = (regs->sdram_rcw[1] >> 8U) & U(0xf); + input.rcw[14] = (regs->sdram_rcw[1] >> 4U) & U(0xf); + input.rcw[15] = (regs->sdram_rcw[1] >> 0U) & U(0xf); + input.rcw3x = (regs->sdram_rcw[2] >> 8U) & U(0xff); + } + + input.adv.odtimpedance = popts->odt ? popts->odt : 60; + input.adv.tx_impedance = popts->phy_tx_impedance ? + popts->phy_tx_impedance : 28; + input.adv.atx_impedance = popts->phy_atx_impedance ? + popts->phy_atx_impedance : 30; + + debug("Initializing input adv data structure\n"); + phy_gen2_init_input(&input); + + debug("Initializing message block\n"); + ret = phy_gen2_msg_init(&msg_1d, &msg_2d, &input); + if (ret != 0) { + ERROR("Init msg failed (error code %d)\n", ret); + return ret; + } + + ret = c_init_phy_config(priv->phy, priv->ip_rev, &input, &msg_1d); + if (ret != 0) { + ERROR("Init PHY failed (error code %d)\n", ret); + return ret; + } +#ifdef NXP_WARM_BOOT + debug("Warm boot flag value %0x\n", priv->warm_boot_flag); + if (priv->warm_boot_flag == DDR_WARM_BOOT) { + debug("Restoring the Phy training data\n"); + // Restore the training data + ret = restore_phy_training_values(priv->phy, + PHY_TRAINING_REGS_ON_FLASH, + priv->num_ctlrs, + input.basic.train2d); + if (ret != 0) { + ERROR("Restoring of training data failed %d\n", ret); + return ret; + } + } else { +#endif + + debug("Load 1D firmware\n"); + ret = load_fw(priv->phy, &input, 0, &msg_1d, + sizeof(struct ddr4u1d), priv->phy_gen2_fw_img_buf, + priv->img_loadr, priv->warm_boot_flag); + if (ret != 0) { + ERROR("Loading firmware failed (error code %d)\n", ret); + return ret; + } + + debug("Execute firmware\n"); + ret = g_exec_fw(priv->phy, 0, &input); + if (ret != 0) { + ERROR("Execution FW failed (error code %d)\n", ret); + } + +#ifdef NXP_APPLY_MAX_CDD + soc_info = get_soc_info(); + if (soc_info->svr_reg.bf.maj_ver == 2) { + tcfg0 = regs->timing_cfg[0]; + tcfg4 = regs->timing_cfg[4]; + rank = findrank(conf->cs_in_use); + get_cdd_val(priv->phy, rank, input.basic.frequency, + &tcfg0, &tcfg4); + regs->timing_cfg[0] = tcfg0; + regs->timing_cfg[4] = tcfg4; + } +#endif + + if ((ret == 0) && (input.basic.train2d != 0)) { + /* 2D training starts here */ + debug("Load 2D firmware\n"); + ret = load_fw(priv->phy, &input, 1, &msg_2d, + sizeof(struct ddr4u2d), + priv->phy_gen2_fw_img_buf, + priv->img_loadr, + priv->warm_boot_flag); + if (ret != 0) { + ERROR("Loading fw failed (err code %d)\n", ret); + } else { + debug("Execute 2D firmware\n"); + ret = g_exec_fw(priv->phy, 1, &input); + if (ret != 0) { + ERROR("Execution FW failed (err %d)\n", + ret); + } + } + } +#ifdef NXP_WARM_BOOT + if (priv->warm_boot_flag != DDR_WRM_BOOT_NT_SUPPORTED && + ret == 0) { + debug("save the phy training data\n"); + //Save training data TBD + ret = save_phy_training_values(priv->phy, + PHY_TRAINING_REGS_ON_FLASH, + priv->num_ctlrs, + input.basic.train2d); + if (ret != 0) { + ERROR("Saving training data failed."); + ERROR("Warm boot will fail. Error=%d.\n", ret); + } + } + } /* else */ +#endif + + if (ret == 0) { + debug("Load PIE\n"); + i_load_pie(priv->phy, &input, &msg_1d); + + NOTICE("DDR4 %s with %d-rank %d-bit bus (x%d)\n", + input.basic.dimm_type == RDIMM ? "RDIMM" : + input.basic.dimm_type == LRDIMM ? "LRDIMM" : + "UDIMM", + dimm_param->n_ranks, + dimm_param->primary_sdram_width, + dimm_param->device_width); + } +#ifdef DEBUG_DDR_INPUT_CONFIG + print_jason_format(&input, &msg_1d, &msg_2d); +#endif + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h new file mode 100644 index 0000000..15e80d1 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h @@ -0,0 +1,334 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if !defined(PHY_H) && defined(NXP_WARM_BOOT) +#define PHY_H + +#include + +/* To store sector size to be erase on flash*/ +#define PHY_ERASE_SIZE F_SECTOR_ERASE_SZ + +/*Structure to implement address-data map tuples to store PHY training values*/ +struct phy_training_values { + uint32_t addr; + uint16_t data; +}; +/* Saves PHY Training Register values after cold reset + *@param[in] phy_ptr array to store addresses of PHYs + *@param[in] address_to_store address to save PHY training register values + *on flash + *@param[in] num_of_phy the number of PHY for which training values are + *to be saved + *@param[in] train2d flag to store whether 2D training registers are to + *be saved or not + * + *PHY training values will be stored on flash at contigous memory in the order: + *1D training registers, 2D training registers + *for each PHY + * + *if train2d is false saving 2D training registers will be skipped + */ +int save_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_store, + uint32_t num_of_phy, int train2d); + +/*Restores PHY Training Register values after warm reset + *@param[in] phy_ptr array to store addresses of PHYs + *@param[in] address_to_store address to retrieve PHY training register + *values from flash + *@param[in] num_of_phy the number of PHY for which training values are + *to be restored + *@param[in] train2d flag to store whether 2D training registers are + *to be restored or not + * + *if train2d is false saving 2D training registers will be skipped + */ + +int restore_phy_training_values(uint16_t **phy_ptr, uint32_t address_to_restore, + uint32_t num_of_phy, int train2d); + +/* + * Address data tuples to store the PHY 1D + */ + +struct phy_training_values training_1D_values[] = { + {0x200B2, 0}, {0x200CB, 0}, {0x10043, 0}, {0x11043, 0}, + {0x12043, 0}, {0x13043, 0}, {0x14043, 0}, {0x15043, 0}, + {0x16043, 0}, {0x17043, 0}, {0x18043, 0}, {0x10143, 0}, + {0x11143, 0}, {0x12143, 0}, {0x13143, 0}, {0x14143, 0}, + {0x15143, 0}, {0x16143, 0}, {0x17143, 0}, {0x18143, 0}, + {0x10080, 0}, {0x11080, 0}, {0x12080, 0}, {0x13080, 0}, + {0x14080, 0}, {0x15080, 0}, {0x16080, 0}, {0x17080, 0}, + {0x18080, 0}, {0x10180, 0}, {0x11180, 0}, {0x12180, 0}, + {0x13180, 0}, {0x14180, 0}, {0x15180, 0}, {0x16180, 0}, + {0x17180, 0}, {0x18180, 0}, {0x10081, 0}, {0x11081, 0}, + {0x12081, 0}, {0x13081, 0}, {0x14081, 0}, {0x15081, 0}, + {0x16081, 0}, {0x17081, 0}, {0x18081, 0}, {0x10181, 0}, + {0x11181, 0}, {0x12181, 0}, {0x13181, 0}, {0x14181, 0}, + {0x15181, 0}, {0x16181, 0}, {0x17181, 0}, {0x18181, 0}, + {0x10082, 0}, {0x11082, 0}, {0x12082, 0}, {0x13082, 0}, + {0x14082, 0}, {0x15082, 0}, {0x16082, 0}, {0x17082, 0}, + {0x18082, 0}, {0x10182, 0}, {0x11182, 0}, {0x12182, 0}, + {0x13182, 0}, {0x14182, 0}, {0x15182, 0}, {0x16182, 0}, + {0x17182, 0}, {0x18182, 0}, {0x10083, 0}, {0x11083, 0}, + {0x12083, 0}, {0x13083, 0}, {0x14083, 0}, {0x15083, 0}, + {0x16083, 0}, {0x17083, 0}, {0x18083, 0}, {0x10183, 0}, + {0x11183, 0}, {0x12183, 0}, {0x13183, 0}, {0x14183, 0}, + {0x15183, 0}, {0x16183, 0}, {0x17183, 0}, {0x18183, 0}, + {0x100D0, 0}, {0x110D0, 0}, {0x120D0, 0}, {0x130D0, 0}, + {0x140D0, 0}, {0x150D0, 0}, {0x160D0, 0}, {0x170D0, 0}, + {0x180D0, 0}, {0x101D0, 0}, {0x111D0, 0}, {0x121D0, 0}, + {0x131D0, 0}, {0x141D0, 0}, {0x151D0, 0}, {0x161D0, 0}, + {0x171D0, 0}, {0x181D0, 0}, {0x100D1, 0}, {0x110D1, 0}, + {0x120D1, 0}, {0x130D1, 0}, {0x140D1, 0}, {0x150D1, 0}, + {0x160D1, 0}, {0x170D1, 0}, {0x180D1, 0}, {0x101D1, 0}, + {0x111D1, 0}, {0x121D1, 0}, {0x131D1, 0}, {0x141D1, 0}, + {0x151D1, 0}, {0x161D1, 0}, {0x171D1, 0}, {0x181D1, 0}, + {0x100D2, 0}, {0x110D2, 0}, {0x120D2, 0}, {0x130D2, 0}, + {0x140D2, 0}, {0x150D2, 0}, {0x160D2, 0}, {0x170D2, 0}, + {0x180D2, 0}, {0x101D2, 0}, {0x111D2, 0}, {0x121D2, 0}, + {0x131D2, 0}, {0x141D2, 0}, {0x151D2, 0}, {0x161D2, 0}, + {0x171D2, 0}, {0x181D2, 0}, {0x100D3, 0}, {0x110D3, 0}, + {0x120D3, 0}, {0x130D3, 0}, {0x140D3, 0}, {0x150D3, 0}, + {0x160D3, 0}, {0x170D3, 0}, {0x180D3, 0}, {0x101D3, 0}, + {0x111D3, 0}, {0x121D3, 0}, {0x131D3, 0}, {0x141D3, 0}, + {0x151D3, 0}, {0x161D3, 0}, {0x171D3, 0}, {0x181D3, 0}, + {0x10068, 0}, {0x11068, 0}, {0x12068, 0}, {0x13068, 0}, + {0x14068, 0}, {0x15068, 0}, {0x16068, 0}, {0x17068, 0}, + {0x18068, 0}, {0x10168, 0}, {0x11168, 0}, {0x12168, 0}, + {0x13168, 0}, {0x14168, 0}, {0x15168, 0}, {0x16168, 0}, + {0x17168, 0}, {0x18168, 0}, {0x10268, 0}, {0x11268, 0}, + {0x12268, 0}, {0x13268, 0}, {0x14268, 0}, {0x15268, 0}, + {0x16268, 0}, {0x17268, 0}, {0x18268, 0}, {0x10368, 0}, + {0x11368, 0}, {0x12368, 0}, {0x13368, 0}, {0x14368, 0}, + {0x15368, 0}, {0x16368, 0}, {0x17368, 0}, {0x18368, 0}, + {0x10468, 0}, {0x11468, 0}, {0x12468, 0}, {0x13468, 0}, + {0x14468, 0}, {0x15468, 0}, {0x16468, 0}, {0x17468, 0}, + {0x18468, 0}, {0x10568, 0}, {0x11568, 0}, {0x12568, 0}, + {0x13568, 0}, {0x14568, 0}, {0x15568, 0}, {0x16568, 0}, + {0x17568, 0}, {0x18568, 0}, {0x10668, 0}, {0x11668, 0}, + {0x12668, 0}, {0x13668, 0}, {0x14668, 0}, {0x15668, 0}, + {0x16668, 0}, {0x17668, 0}, {0x18668, 0}, {0x10768, 0}, + {0x11768, 0}, {0x12768, 0}, {0x13768, 0}, {0x14768, 0}, + {0x15768, 0}, {0x16768, 0}, {0x17768, 0}, {0x18768, 0}, + {0x10868, 0}, {0x11868, 0}, {0x12868, 0}, {0x13868, 0}, + {0x14868, 0}, {0x15868, 0}, {0x16868, 0}, {0x17868, 0}, + {0x18868, 0}, {0x10069, 0}, {0x11069, 0}, {0x12069, 0}, + {0x13069, 0}, {0x14069, 0}, {0x15069, 0}, {0x16069, 0}, + {0x17069, 0}, {0x18069, 0}, {0x10169, 0}, {0x11169, 0}, + {0x12169, 0}, {0x13169, 0}, {0x14169, 0}, {0x15169, 0}, + {0x16169, 0}, {0x17169, 0}, {0x18169, 0}, {0x10269, 0}, + {0x11269, 0}, {0x12269, 0}, {0x13269, 0}, {0x14269, 0}, + {0x15269, 0}, {0x16269, 0}, {0x17269, 0}, {0x18269, 0}, + {0x10369, 0}, {0x11369, 0}, {0x12369, 0}, {0x13369, 0}, + {0x14369, 0}, {0x15369, 0}, {0x16369, 0}, {0x17369, 0}, + {0x18369, 0}, {0x10469, 0}, {0x11469, 0}, {0x12469, 0}, + {0x13469, 0}, {0x14469, 0}, {0x15469, 0}, {0x16469, 0}, + {0x17469, 0}, {0x18469, 0}, {0x10569, 0}, {0x11569, 0}, + {0x12569, 0}, {0x13569, 0}, {0x14569, 0}, {0x15569, 0}, + {0x16569, 0}, {0x17569, 0}, {0x18569, 0}, {0x10669, 0}, + {0x11669, 0}, {0x12669, 0}, {0x13669, 0}, {0x14669, 0}, + {0x15669, 0}, {0x16669, 0}, {0x17669, 0}, {0x18669, 0}, + {0x10769, 0}, {0x11769, 0}, {0x12769, 0}, {0x13769, 0}, + {0x14769, 0}, {0x15769, 0}, {0x16769, 0}, {0x17769, 0}, + {0x18769, 0}, {0x10869, 0}, {0x11869, 0}, {0x12869, 0}, + {0x13869, 0}, {0x14869, 0}, {0x15869, 0}, {0x16869, 0}, + {0x17869, 0}, {0x18869, 0}, {0x1006A, 0}, {0x1106A, 0}, + {0x1206A, 0}, {0x1306A, 0}, {0x1406A, 0}, {0x1506A, 0}, + {0x1606A, 0}, {0x1706A, 0}, {0x1806A, 0}, {0x1016A, 0}, + {0x1116A, 0}, {0x1216A, 0}, {0x1316A, 0}, {0x1416A, 0}, + {0x1516A, 0}, {0x1616A, 0}, {0x1716A, 0}, {0x1816A, 0}, + {0x1026A, 0}, {0x1126A, 0}, {0x1226A, 0}, {0x1326A, 0}, + {0x1426A, 0}, {0x1526A, 0}, {0x1626A, 0}, {0x1726A, 0}, + {0x1826A, 0}, {0x1036A, 0}, {0x1136A, 0}, {0x1236A, 0}, + {0x1336A, 0}, {0x1436A, 0}, {0x1536A, 0}, {0x1636A, 0}, + {0x1736A, 0}, {0x1836A, 0}, {0x1046A, 0}, {0x1146A, 0}, + {0x1246A, 0}, {0x1346A, 0}, {0x1446A, 0}, {0x1546A, 0}, + {0x1646A, 0}, {0x1746A, 0}, {0x1846A, 0}, {0x1056A, 0}, + {0x1156A, 0}, {0x1256A, 0}, {0x1356A, 0}, {0x1456A, 0}, + {0x1556A, 0}, {0x1656A, 0}, {0x1756A, 0}, {0x1856A, 0}, + {0x1066A, 0}, {0x1166A, 0}, {0x1266A, 0}, {0x1366A, 0}, + {0x1466A, 0}, {0x1566A, 0}, {0x1666A, 0}, {0x1766A, 0}, + {0x1866A, 0}, {0x1076A, 0}, {0x1176A, 0}, {0x1276A, 0}, + {0x1376A, 0}, {0x1476A, 0}, {0x1576A, 0}, {0x1676A, 0}, + {0x1776A, 0}, {0x1876A, 0}, {0x1086A, 0}, {0x1186A, 0}, + {0x1286A, 0}, {0x1386A, 0}, {0x1486A, 0}, {0x1586A, 0}, + {0x1686A, 0}, {0x1786A, 0}, {0x1886A, 0}, {0x1006B, 0}, + {0x1106B, 0}, {0x1206B, 0}, {0x1306B, 0}, {0x1406B, 0}, + {0x1506B, 0}, {0x1606B, 0}, {0x1706B, 0}, {0x1806B, 0}, + {0x1016B, 0}, {0x1116B, 0}, {0x1216B, 0}, {0x1316B, 0}, + {0x1416B, 0}, {0x1516B, 0}, {0x1616B, 0}, {0x1716B, 0}, + {0x1816B, 0}, {0x1026B, 0}, {0x1126B, 0}, {0x1226B, 0}, + {0x1326B, 0}, {0x1426B, 0}, {0x1526B, 0}, {0x1626B, 0}, + {0x1726B, 0}, {0x1826B, 0}, {0x1036B, 0}, {0x1136B, 0}, + {0x1236B, 0}, {0x1336B, 0}, {0x1436B, 0}, {0x1536B, 0}, + {0x1636B, 0}, {0x1736B, 0}, {0x1836B, 0}, {0x1046B, 0}, + {0x1146B, 0}, {0x1246B, 0}, {0x1346B, 0}, {0x1446B, 0}, + {0x1546B, 0}, {0x1646B, 0}, {0x1746B, 0}, {0x1846B, 0}, + {0x1056B, 0}, {0x1156B, 0}, {0x1256B, 0}, {0x1356B, 0}, + {0x1456B, 0}, {0x1556B, 0}, {0x1656B, 0}, {0x1756B, 0}, + {0x1856B, 0}, {0x1066B, 0}, {0x1166B, 0}, {0x1266B, 0}, + {0x1366B, 0}, {0x1466B, 0}, {0x1566B, 0}, {0x1666B, 0}, + {0x1766B, 0}, {0x1866B, 0}, {0x1076B, 0}, {0x1176B, 0}, + {0x1276B, 0}, {0x1376B, 0}, {0x1476B, 0}, {0x1576B, 0}, + {0x1676B, 0}, {0x1776B, 0}, {0x1876B, 0}, {0x1086B, 0}, + {0x1186B, 0}, {0x1286B, 0}, {0x1386B, 0}, {0x1486B, 0}, + {0x1586B, 0}, {0x1686B, 0}, {0x1786B, 0}, {0x1886B, 0}, + {0x1008C, 0}, {0x1108C, 0}, {0x1208C, 0}, {0x1308C, 0}, + {0x1408C, 0}, {0x1508C, 0}, {0x1608C, 0}, {0x1708C, 0}, + {0x1808C, 0}, {0x1018C, 0}, {0x1118C, 0}, {0x1218C, 0}, + {0x1318C, 0}, {0x1418C, 0}, {0x1518C, 0}, {0x1618C, 0}, + {0x1718C, 0}, {0x1818C, 0}, {0x1008D, 0}, {0x1108D, 0}, + {0x1208D, 0}, {0x1308D, 0}, {0x1408D, 0}, {0x1508D, 0}, + {0x1608D, 0}, {0x1708D, 0}, {0x1808D, 0}, {0x1018D, 0}, + {0x1118D, 0}, {0x1218D, 0}, {0x1318D, 0}, {0x1418D, 0}, + {0x1518D, 0}, {0x1618D, 0}, {0x1718D, 0}, {0x1818D, 0}, + {0x1008E, 0}, {0x1108E, 0}, {0x1208E, 0}, {0x1308E, 0}, + {0x1408E, 0}, {0x1508E, 0}, {0x1608E, 0}, {0x1708E, 0}, + {0x1808E, 0}, {0x1018E, 0}, {0x1118E, 0}, {0x1218E, 0}, + {0x1318E, 0}, {0x1418E, 0}, {0x1518E, 0}, {0x1618E, 0}, + {0x1718E, 0}, {0x1818E, 0}, {0x1008F, 0}, {0x1108F, 0}, + {0x1208F, 0}, {0x1308F, 0}, {0x1408F, 0}, {0x1508F, 0}, + {0x1608F, 0}, {0x1708F, 0}, {0x1808F, 0}, {0x1018F, 0}, + {0x1118F, 0}, {0x1218F, 0}, {0x1318F, 0}, {0x1418F, 0}, + {0x1518F, 0}, {0x1618F, 0}, {0x1718F, 0}, {0x1818F, 0}, + {0x100C0, 0}, {0x110C0, 0}, {0x120C0, 0}, {0x130C0, 0}, + {0x140C0, 0}, {0x150C0, 0}, {0x160C0, 0}, {0x170C0, 0}, + {0x180C0, 0}, {0x101C0, 0}, {0x111C0, 0}, {0x121C0, 0}, + {0x131C0, 0}, {0x141C0, 0}, {0x151C0, 0}, {0x161C0, 0}, + {0x171C0, 0}, {0x181C0, 0}, {0x102C0, 0}, {0x112C0, 0}, + {0x122C0, 0}, {0x132C0, 0}, {0x142C0, 0}, {0x152C0, 0}, + {0x162C0, 0}, {0x172C0, 0}, {0x182C0, 0}, {0x103C0, 0}, + {0x113C0, 0}, {0x123C0, 0}, {0x133C0, 0}, {0x143C0, 0}, + {0x153C0, 0}, {0x163C0, 0}, {0x173C0, 0}, {0x183C0, 0}, + {0x104C0, 0}, {0x114C0, 0}, {0x124C0, 0}, {0x134C0, 0}, + {0x144C0, 0}, {0x154C0, 0}, {0x164C0, 0}, {0x174C0, 0}, + {0x184C0, 0}, {0x105C0, 0}, {0x115C0, 0}, {0x125C0, 0}, + {0x135C0, 0}, {0x145C0, 0}, {0x155C0, 0}, {0x165C0, 0}, + {0x175C0, 0}, {0x185C0, 0}, {0x106C0, 0}, {0x116C0, 0}, + {0x126C0, 0}, {0x136C0, 0}, {0x146C0, 0}, {0x156C0, 0}, + {0x166C0, 0}, {0x176C0, 0}, {0x186C0, 0}, {0x107C0, 0}, + {0x117C0, 0}, {0x127C0, 0}, {0x137C0, 0}, {0x147C0, 0}, + {0x157C0, 0}, {0x167C0, 0}, {0x177C0, 0}, {0x187C0, 0}, + {0x108C0, 0}, {0x118C0, 0}, {0x128C0, 0}, {0x138C0, 0}, + {0x148C0, 0}, {0x158C0, 0}, {0x168C0, 0}, {0x178C0, 0}, + {0x188C0, 0}, {0x100C1, 0}, {0x110C1, 0}, {0x120C1, 0}, + {0x130C1, 0}, {0x140C1, 0}, {0x150C1, 0}, {0x160C1, 0}, + {0x170C1, 0}, {0x180C1, 0}, {0x101C1, 0}, {0x111C1, 0}, + {0x121C1, 0}, {0x131C1, 0}, {0x141C1, 0}, {0x151C1, 0}, + {0x161C1, 0}, {0x171C1, 0}, {0x181C1, 0}, {0x102C1, 0}, + {0x112C1, 0}, {0x122C1, 0}, {0x132C1, 0}, {0x142C1, 0}, + {0x152C1, 0}, {0x162C1, 0}, {0x172C1, 0}, {0x182C1, 0}, + {0x103C1, 0}, {0x113C1, 0}, {0x123C1, 0}, {0x133C1, 0}, + {0x143C1, 0}, {0x153C1, 0}, {0x163C1, 0}, {0x173C1, 0}, + {0x183C1, 0}, {0x104C1, 0}, {0x114C1, 0}, {0x124C1, 0}, + {0x134C1, 0}, {0x144C1, 0}, {0x154C1, 0}, {0x164C1, 0}, + {0x174C1, 0}, {0x184C1, 0}, {0x105C1, 0}, {0x115C1, 0}, + {0x125C1, 0}, {0x135C1, 0}, {0x145C1, 0}, {0x155C1, 0}, + {0x165C1, 0}, {0x175C1, 0}, {0x185C1, 0}, {0x106C1, 0}, + {0x116C1, 0}, {0x126C1, 0}, {0x136C1, 0}, {0x146C1, 0}, + {0x156C1, 0}, {0x166C1, 0}, {0x176C1, 0}, {0x186C1, 0}, + {0x107C1, 0}, {0x117C1, 0}, {0x127C1, 0}, {0x137C1, 0}, + {0x147C1, 0}, {0x157C1, 0}, {0x167C1, 0}, {0x177C1, 0}, + {0x187C1, 0}, {0x108C1, 0}, {0x118C1, 0}, {0x128C1, 0}, + {0x138C1, 0}, {0x148C1, 0}, {0x158C1, 0}, {0x168C1, 0}, + {0x178C1, 0}, {0x188C1, 0}, {0x100C2, 0}, {0x110C2, 0}, + {0x120C2, 0}, {0x130C2, 0}, {0x140C2, 0}, {0x150C2, 0}, + {0x160C2, 0}, {0x170C2, 0}, {0x180C2, 0}, {0x101C2, 0}, + {0x111C2, 0}, {0x121C2, 0}, {0x131C2, 0}, {0x141C2, 0}, + {0x151C2, 0}, {0x161C2, 0}, {0x171C2, 0}, {0x181C2, 0}, + {0x102C2, 0}, {0x112C2, 0}, {0x122C2, 0}, {0x132C2, 0}, + {0x142C2, 0}, {0x152C2, 0}, {0x162C2, 0}, {0x172C2, 0}, + {0x182C2, 0}, {0x103C2, 0}, {0x113C2, 0}, {0x123C2, 0}, + {0x133C2, 0}, {0x143C2, 0}, {0x153C2, 0}, {0x163C2, 0}, + {0x173C2, 0}, {0x183C2, 0}, {0x104C2, 0}, {0x114C2, 0}, + {0x124C2, 0}, {0x134C2, 0}, {0x144C2, 0}, {0x154C2, 0}, + {0x164C2, 0}, {0x174C2, 0}, {0x184C2, 0}, {0x105C2, 0}, + {0x115C2, 0}, {0x125C2, 0}, {0x135C2, 0}, {0x145C2, 0}, + {0x155C2, 0}, {0x165C2, 0}, {0x175C2, 0}, {0x185C2, 0}, + {0x106C2, 0}, {0x116C2, 0}, {0x126C2, 0}, {0x136C2, 0}, + {0x146C2, 0}, {0x156C2, 0}, {0x166C2, 0}, {0x176C2, 0}, + {0x186C2, 0}, {0x107C2, 0}, {0x117C2, 0}, {0x127C2, 0}, + {0x137C2, 0}, {0x147C2, 0}, {0x157C2, 0}, {0x167C2, 0}, + {0x177C2, 0}, {0x187C2, 0}, {0x108C2, 0}, {0x118C2, 0}, + {0x128C2, 0}, {0x138C2, 0}, {0x148C2, 0}, {0x158C2, 0}, + {0x168C2, 0}, {0x178C2, 0}, {0x188C2, 0}, {0x100C3, 0}, + {0x110C3, 0}, {0x120C3, 0}, {0x130C3, 0}, {0x140C3, 0}, + {0x150C3, 0}, {0x160C3, 0}, {0x170C3, 0}, {0x180C3, 0}, + {0x101C3, 0}, {0x111C3, 0}, {0x121C3, 0}, {0x131C3, 0}, + {0x141C3, 0}, {0x151C3, 0}, {0x161C3, 0}, {0x171C3, 0}, + {0x181C3, 0}, {0x102C3, 0}, {0x112C3, 0}, {0x122C3, 0}, + {0x132C3, 0}, {0x142C3, 0}, {0x152C3, 0}, {0x162C3, 0}, + {0x172C3, 0}, {0x182C3, 0}, {0x103C3, 0}, {0x113C3, 0}, + {0x123C3, 0}, {0x133C3, 0}, {0x143C3, 0}, {0x153C3, 0}, + {0x163C3, 0}, {0x173C3, 0}, {0x183C3, 0}, {0x104C3, 0}, + {0x114C3, 0}, {0x124C3, 0}, {0x134C3, 0}, {0x144C3, 0}, + {0x154C3, 0}, {0x164C3, 0}, {0x174C3, 0}, {0x184C3, 0}, + {0x105C3, 0}, {0x115C3, 0}, {0x125C3, 0}, {0x135C3, 0}, + {0x145C3, 0}, {0x155C3, 0}, {0x165C3, 0}, {0x175C3, 0}, + {0x185C3, 0}, {0x106C3, 0}, {0x116C3, 0}, {0x126C3, 0}, + {0x136C3, 0}, {0x146C3, 0}, {0x156C3, 0}, {0x166C3, 0}, + {0x176C3, 0}, {0x186C3, 0}, {0x107C3, 0}, {0x117C3, 0}, + {0x127C3, 0}, {0x137C3, 0}, {0x147C3, 0}, {0x157C3, 0}, + {0x167C3, 0}, {0x177C3, 0}, {0x187C3, 0}, {0x108C3, 0}, + {0x118C3, 0}, {0x128C3, 0}, {0x138C3, 0}, {0x148C3, 0}, + {0x158C3, 0}, {0x168C3, 0}, {0x178C3, 0}, {0x188C3, 0}, + {0x10020, 0}, {0x11020, 0}, {0x12020, 0}, {0x13020, 0}, + {0x14020, 0}, {0x15020, 0}, {0x16020, 0}, {0x17020, 0}, + {0x18020, 0}, {0x2007D, 0}, {0x20077, 0} +}; + +/* + *Array to store the PHY 2D Training register addresses + */ +struct phy_training_values training_2D_values[] = { + {0x1008C, 0}, {0x1108C, 0}, {0x1208C, 0}, {0x1308C, 0}, + {0x1408C, 0}, {0x1508C, 0}, {0x1608C, 0}, {0x1708C, 0}, + {0x1808C, 0}, {0x1018C, 0}, {0x1118C, 0}, {0x1218C, 0}, + {0x1318C, 0}, {0x1418C, 0}, {0x1518C, 0}, {0x1618C, 0}, + {0x1718C, 0}, {0x1818C, 0}, {0x10040, 0}, {0x11040, 0}, + {0x12040, 0}, {0x13040, 0}, {0x14040, 0}, {0x15040, 0}, + {0x16040, 0}, {0x17040, 0}, {0x18040, 0}, {0x10140, 0}, + {0x11140, 0}, {0x12140, 0}, {0x13140, 0}, {0x14140, 0}, + {0x15140, 0}, {0x16140, 0}, {0x17140, 0}, {0x18140, 0}, + {0x10240, 0}, {0x11240, 0}, {0x12240, 0}, {0x13240, 0}, + {0x14240, 0}, {0x15240, 0}, {0x16240, 0}, {0x17240, 0}, + {0x18240, 0}, {0x10340, 0}, {0x11340, 0}, {0x12340, 0}, + {0x13340, 0}, {0x14340, 0}, {0x15340, 0}, {0x16340, 0}, + {0x17340, 0}, {0x18340, 0}, {0x10440, 0}, {0x11440, 0}, + {0x12440, 0}, {0x13440, 0}, {0x14440, 0}, {0x15440, 0}, + {0x16440, 0}, {0x17440, 0}, {0x18440, 0}, {0x10540, 0}, + {0x11540, 0}, {0x12540, 0}, {0x13540, 0}, {0x14540, 0}, + {0x15540, 0}, {0x16540, 0}, {0x17540, 0}, {0x18540, 0}, + {0x10640, 0}, {0x11640, 0}, {0x12640, 0}, {0x13640, 0}, + {0x14640, 0}, {0x15640, 0}, {0x16640, 0}, {0x17640, 0}, + {0x18640, 0}, {0x10740, 0}, {0x11740, 0}, {0x12740, 0}, + {0x13740, 0}, {0x14740, 0}, {0x15740, 0}, {0x16740, 0}, + {0x17740, 0}, {0x18740, 0}, {0x10840, 0}, {0x11840, 0}, + {0x12840, 0}, {0x13840, 0}, {0x14840, 0}, {0x15840, 0}, + {0x16840, 0}, {0x17840, 0}, {0x18840, 0}, {0x10030, 0}, + {0x11030, 0}, {0x12030, 0}, {0x13030, 0}, {0x14030, 0}, + {0x15030, 0}, {0x16030, 0}, {0x17030, 0}, {0x18030, 0}, + {0x10130, 0}, {0x11130, 0}, {0x12130, 0}, {0x13130, 0}, + {0x14130, 0}, {0x15130, 0}, {0x16130, 0}, {0x17130, 0}, + {0x18130, 0}, {0x10230, 0}, {0x11230, 0}, {0x12230, 0}, + {0x13230, 0}, {0x14230, 0}, {0x15230, 0}, {0x16230, 0}, + {0x17230, 0}, {0x18230, 0}, {0x10330, 0}, {0x11330, 0}, + {0x12330, 0}, {0x13330, 0}, {0x14330, 0}, {0x15330, 0}, + {0x16330, 0}, {0x17330, 0}, {0x18330, 0}, {0x10430, 0}, + {0x11430, 0}, {0x12430, 0}, {0x13430, 0}, {0x14430, 0}, + {0x15430, 0}, {0x16430, 0}, {0x17430, 0}, {0x18430, 0}, + {0x10530, 0}, {0x11530, 0}, {0x12530, 0}, {0x13530, 0}, + {0x14530, 0}, {0x15530, 0}, {0x16530, 0}, {0x17530, 0}, + {0x18530, 0}, {0x10630, 0}, {0x11630, 0}, {0x12630, 0}, + {0x13630, 0}, {0x14630, 0}, {0x15630, 0}, {0x16630, 0}, + {0x17630, 0}, {0x18630, 0}, {0x10730, 0}, {0x11730, 0}, + {0x12730, 0}, {0x13730, 0}, {0x14730, 0}, {0x15730, 0}, + {0x16730, 0}, {0x17730, 0}, {0x18730, 0}, {0x10830, 0}, + {0x11830, 0}, {0x12830, 0}, {0x13830, 0}, {0x14830, 0}, + {0x15830, 0}, {0x16830, 0}, {0x17830, 0}, {0x18830, 0} +}; + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h new file mode 100644 index 0000000..b89066a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h @@ -0,0 +1,632 @@ +/* + * Copyright 2021 NXP + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PIE_H +#define PIE_H + +struct pie { + uint32_t addr; + uint16_t data; +}; + +static const struct pie pie_udimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x90029, 0xb}, + {0x9002a, 0x480}, + {0x9002b, 0x109}, + {0x9002c, 0x8}, + {0x9002d, 0x448}, + {0x9002e, 0x139}, + {0x9002f, 0x8}, + {0x90030, 0x478}, + {0x90031, 0x109}, + {0x90032, 0x2}, + {0x90033, 0x10}, + {0x90034, 0x139}, + {0x90035, 0xb}, + {0x90036, 0x7c0}, + {0x90037, 0x139}, + {0x90038, 0x44}, + {0x90039, 0x633}, + {0x9003a, 0x159}, + {0x9003b, 0x14f}, + {0x9003c, 0x630}, + {0x9003d, 0x159}, + {0x9003e, 0x47}, + {0x9003f, 0x633}, + {0x90040, 0x149}, + {0x90041, 0x4f}, + {0x90042, 0x633}, + {0x90043, 0x179}, + {0x90044, 0x8}, + {0x90045, 0xe0}, + {0x90046, 0x109}, + {0x90047, 0x0}, + {0x90048, 0x7c8}, + {0x90049, 0x109}, + {0x9004a, 0x0}, + {0x9004b, 0x1}, + {0x9004c, 0x8}, + {0x9004d, 0x0}, + {0x9004e, 0x45a}, + {0x9004f, 0x9}, + {0x90050, 0x0}, + {0x90051, 0x448}, + {0x90052, 0x109}, + {0x90053, 0x40}, + {0x90054, 0x633}, + {0x90055, 0x179}, + {0x90056, 0x1}, + {0x90057, 0x618}, + {0x90058, 0x109}, + {0x90059, 0x40c0}, + {0x9005a, 0x633}, + {0x9005b, 0x149}, + {0x9005c, 0x8}, + {0x9005d, 0x4}, + {0x9005e, 0x48}, + {0x9005f, 0x4040}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x0}, + {0x90063, 0x4}, + {0x90064, 0x48}, + {0x90065, 0x40}, + {0x90066, 0x633}, + {0x90067, 0x149}, + {0x90068, 0x10}, + {0x90069, 0x4}, + {0x9006a, 0x18}, + {0x9006b, 0x0}, + {0x9006c, 0x4}, + {0x9006d, 0x78}, + {0x9006e, 0x549}, + {0x9006f, 0x633}, + {0x90070, 0x159}, + {0x90071, 0xd49}, + {0x90072, 0x633}, + {0x90073, 0x159}, + {0x90074, 0x94a}, + {0x90075, 0x633}, + {0x90076, 0x159}, + {0x90077, 0x441}, + {0x90078, 0x633}, + {0x90079, 0x149}, + {0x9007a, 0x42}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x1}, + {0x9007e, 0x633}, + {0x9007f, 0x149}, + {0x90080, 0x0}, + {0x90081, 0xe0}, + {0x90082, 0x109}, + {0x90083, 0xa}, + {0x90084, 0x10}, + {0x90085, 0x109}, + {0x90086, 0x9}, + {0x90087, 0x3c0}, + {0x90088, 0x149}, + {0x90089, 0x9}, + {0x9008a, 0x3c0}, + {0x9008b, 0x159}, + {0x9008c, 0x18}, + {0x9008d, 0x10}, + {0x9008e, 0x109}, + {0x9008f, 0x0}, + {0x90090, 0x3c0}, + {0x90091, 0x109}, + {0x90092, 0x18}, + {0x90093, 0x4}, + {0x90094, 0x48}, + {0x90095, 0x18}, + {0x90096, 0x4}, + {0x90097, 0x58}, + {0x90098, 0xb}, + {0x90099, 0x10}, + {0x9009a, 0x109}, + {0x9009b, 0x1}, + {0x9009c, 0x10}, + {0x9009d, 0x109}, + {0x9009e, 0x5}, + {0x9009f, 0x7c0}, + {0x900a0, 0x109}, + {0x900a1, 0x0}, + {0x900a2, 0x8140}, + {0x900a3, 0x10c}, + {0x900a4, 0x10}, + {0x900a5, 0x8138}, + {0x900a6, 0x10c}, + {0x900a7, 0x8}, + {0x900a8, 0x7c8}, + {0x900a9, 0x101}, + {0x900aa, 0x8}, + {0x900ab, 0x448}, + {0x900ac, 0x109}, + {0x900ad, 0xf}, + {0x900ae, 0x7c0}, + {0x900af, 0x109}, + {0x900b0, 0x47}, + {0x900b1, 0x630}, + {0x900b2, 0x109}, + {0x900b3, 0x8}, + {0x900b4, 0x618}, + {0x900b5, 0x109}, + {0x900b6, 0x8}, + {0x900b7, 0xe0}, + {0x900b8, 0x109}, + {0x900b9, 0x0}, + {0x900ba, 0x7c8}, + {0x900bb, 0x109}, + {0x900bc, 0x8}, + {0x900bd, 0x8140}, + {0x900be, 0x10c}, + {0x900bf, 0x0}, + {0x900c0, 0x478}, + {0x900c1, 0x109}, + {0x900c2, 0x0}, + {0x900c3, 0x1}, + {0x900c4, 0x8}, + {0x900c5, 0x8}, + {0x900c6, 0x4}, + {0x900c7, 0x8}, + {0x900c8, 0x8}, + {0x900c9, 0x7c8}, + {0x900ca, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x2b}, +}; + +static const struct pie pie_rdimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x40000, 0x10}, + {0x40020, 0x0}, + {0x40040, 0x0}, + {0x40060, 0x0}, + {0x40001, 0x70a}, + {0x40021, 0x7005}, + {0x40041, 0x0}, + {0x40061, 0x2001}, + {0x40002, 0x4010}, + {0x40022, 0x0}, + {0x40042, 0x0}, + {0x40062, 0x0}, + {0x90029, 0x10}, + {0x9002a, 0x400}, + {0x9002b, 0x16e}, + {0x9002c, 0x8}, + {0x9002d, 0x370}, + {0x9002e, 0x169}, + {0x9002f, 0x8}, + {0x90030, 0x7aa}, + {0x90031, 0x6a}, + {0x90032, 0x10}, + {0x90033, 0x7b2}, + {0x90034, 0x6a}, + {0x90035, 0x0}, + {0x90036, 0x48a}, + {0x90037, 0x6a}, + {0x90038, 0x9}, + {0x90039, 0x480}, + {0x9003a, 0x16a}, + {0x9003b, 0x4}, + {0x9003c, 0x790}, + {0x9003d, 0x16a}, + {0x9003e, 0xc}, + {0x9003f, 0x408}, + {0x90040, 0x169}, + {0x90041, 0xa}, + {0x90042, 0x0}, + {0x90043, 0x68}, + {0x90044, 0x0}, + {0x90045, 0x408}, + {0x90046, 0x169}, + {0x90047, 0x1}, + {0x90048, 0x480}, + {0x90049, 0x16a}, + {0x9004a, 0xb}, + {0x9004b, 0x480}, + {0x9004c, 0x109}, + {0x9004d, 0x8}, + {0x9004e, 0x448}, + {0x9004f, 0x139}, + {0x90050, 0x78}, + {0x90051, 0x8}, + {0x90052, 0x139}, + {0x90053, 0x2}, + {0x90054, 0x10}, + {0x90055, 0x139}, + {0x90056, 0xb}, + {0x90057, 0x7c0}, + {0x90058, 0x139}, + {0x90059, 0x44}, + {0x9005a, 0x633}, + {0x9005b, 0x159}, + {0x9005c, 0x14f}, + {0x9005d, 0x630}, + {0x9005e, 0x159}, + {0x9005f, 0x47}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x4f}, + {0x90063, 0x633}, + {0x90064, 0x179}, + {0x90065, 0x8}, + {0x90066, 0xe0}, + {0x90067, 0x109}, + {0x90068, 0x0}, + {0x90069, 0x7c8}, + {0x9006a, 0x109}, + {0x9006b, 0x0}, + {0x9006c, 0x1}, + {0x9006d, 0x8}, + {0x9006e, 0x0}, + {0x9006f, 0x45a}, + {0x90070, 0x9}, + {0x90071, 0x0}, + {0x90072, 0x448}, + {0x90073, 0x109}, + {0x90074, 0x40}, + {0x90075, 0x633}, + {0x90076, 0x179}, + {0x90077, 0x1}, + {0x90078, 0x618}, + {0x90079, 0x109}, + {0x9007a, 0x40c0}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x8}, + {0x9007e, 0x4}, + {0x9007f, 0x48}, + {0x90080, 0x4040}, + {0x90081, 0x633}, + {0x90082, 0x149}, + {0x90083, 0x0}, + {0x90084, 0x4}, + {0x90085, 0x48}, + {0x90086, 0x40}, + {0x90087, 0x633}, + {0x90088, 0x149}, + {0x90089, 0x10}, + {0x9008a, 0x4}, + {0x9008b, 0x18}, + {0x9008c, 0x0}, + {0x9008d, 0x4}, + {0x9008e, 0x78}, + {0x9008f, 0x549}, + {0x90090, 0x633}, + {0x90091, 0x159}, + {0x90092, 0xd49}, + {0x90093, 0x633}, + {0x90094, 0x159}, + {0x90095, 0x94a}, + {0x90096, 0x633}, + {0x90097, 0x159}, + {0x90098, 0x441}, + {0x90099, 0x633}, + {0x9009a, 0x149}, + {0x9009b, 0x42}, + {0x9009c, 0x633}, + {0x9009d, 0x149}, + {0x9009e, 0x1}, + {0x9009f, 0x633}, + {0x900a0, 0x149}, + {0x900a1, 0x0}, + {0x900a2, 0xe0}, + {0x900a3, 0x109}, + {0x900a4, 0xa}, + {0x900a5, 0x10}, + {0x900a6, 0x109}, + {0x900a7, 0x9}, + {0x900a8, 0x3c0}, + {0x900a9, 0x149}, + {0x900aa, 0x9}, + {0x900ab, 0x3c0}, + {0x900ac, 0x159}, + {0x900ad, 0x18}, + {0x900ae, 0x10}, + {0x900af, 0x109}, + {0x900b0, 0x0}, + {0x900b1, 0x3c0}, + {0x900b2, 0x109}, + {0x900b3, 0x18}, + {0x900b4, 0x4}, + {0x900b5, 0x48}, + {0x900b6, 0x18}, + {0x900b7, 0x4}, + {0x900b8, 0x58}, + {0x900b9, 0xb}, + {0x900ba, 0x10}, + {0x900bb, 0x109}, + {0x900bc, 0x1}, + {0x900bd, 0x10}, + {0x900be, 0x109}, + {0x900bf, 0x5}, + {0x900c0, 0x7c0}, + {0x900c1, 0x109}, + {0x900c2, 0x3}, + {0x900c3, 0x370}, + {0x900c4, 0x169}, + {0x900c5, 0x3}, + {0x900c6, 0x8}, + {0x900c7, 0x139}, + {0x900c8, 0x0}, + {0x900c9, 0x400}, + {0x900ca, 0x16e}, + {0x900cb, 0x8}, + {0x900cc, 0x478}, + {0x900cd, 0x109}, + {0x900ce, 0x0}, + {0x900cf, 0x8140}, + {0x900d0, 0x10c}, + {0x900d1, 0x10}, + {0x900d2, 0x8138}, + {0x900d3, 0x10c}, + {0x900d4, 0x8}, + {0x900d5, 0x7c8}, + {0x900d6, 0x101}, + {0x900d7, 0x7a}, + {0x900d8, 0x8}, + {0x900d9, 0x109}, + {0x900da, 0x8}, + {0x900db, 0x448}, + {0x900dc, 0x109}, + {0x900dd, 0xf}, + {0x900de, 0x7c0}, + {0x900df, 0x109}, + {0x900e0, 0x47}, + {0x900e1, 0x630}, + {0x900e2, 0x109}, + {0x900e3, 0x8}, + {0x900e4, 0x618}, + {0x900e5, 0x109}, + {0x900e6, 0x8}, + {0x900e7, 0xe0}, + {0x900e8, 0x109}, + {0x900e9, 0x0}, + {0x900ea, 0x8}, + {0x900eb, 0x109}, + {0x900ec, 0x0}, + {0x900ed, 0x7c8}, + {0x900ee, 0x109}, + {0x900ef, 0x8}, + {0x900f0, 0x8140}, + {0x900f1, 0x10c}, + {0x900f2, 0x0}, + {0x900f3, 0x478}, + {0x900f4, 0x109}, + {0x900f5, 0x0}, + {0x900f6, 0x1}, + {0x900f7, 0x8}, + {0x900f8, 0x8}, + {0x900f9, 0x4}, + {0x900fa, 0x8}, + {0x900fb, 0x8}, + {0x900fc, 0x7c8}, + {0x900fd, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x3a}, +}; + +static const struct pie pie_lrdimm[] = { + {0x90000, 0x10}, + {0x90001, 0x400}, + {0x90002, 0x10e}, + {0x90003, 0x0}, + {0x90004, 0x0}, + {0x90005, 0x8}, + {0x90029, 0xb}, + {0x9002a, 0x480}, + {0x9002b, 0x109}, + {0x9002c, 0x8}, + {0x9002d, 0x448}, + {0x9002e, 0x139}, + {0x9002f, 0x78}, + {0x90030, 0x8}, + {0x90031, 0x139}, + {0x90032, 0x2}, + {0x90033, 0x10}, + {0x90034, 0x139}, + {0x90035, 0xb}, + {0x90036, 0x7c0}, + {0x90037, 0x139}, + {0x90038, 0x44}, + {0x90039, 0x633}, + {0x9003a, 0x159}, + {0x9003b, 0x14f}, + {0x9003c, 0x630}, + {0x9003d, 0x159}, + {0x9003e, 0x47}, + {0x9003f, 0x633}, + {0x90040, 0x149}, + {0x90041, 0x4f}, + {0x90042, 0x633}, + {0x90043, 0x179}, + {0x90044, 0x8}, + {0x90045, 0xe0}, + {0x90046, 0x109}, + {0x90047, 0x0}, + {0x90048, 0x7c8}, + {0x90049, 0x109}, + {0x9004a, 0x0}, + {0x9004b, 0x1}, + {0x9004c, 0x8}, + {0x9004d, 0x0}, + {0x9004e, 0x45a}, + {0x9004f, 0x9}, + {0x90050, 0x0}, + {0x90051, 0x448}, + {0x90052, 0x109}, + {0x90053, 0x40}, + {0x90054, 0x633}, + {0x90055, 0x179}, + {0x90056, 0x1}, + {0x90057, 0x618}, + {0x90058, 0x109}, + {0x90059, 0x40c0}, + {0x9005a, 0x633}, + {0x9005b, 0x149}, + {0x9005c, 0x8}, + {0x9005d, 0x4}, + {0x9005e, 0x48}, + {0x9005f, 0x4040}, + {0x90060, 0x633}, + {0x90061, 0x149}, + {0x90062, 0x0}, + {0x90063, 0x4}, + {0x90064, 0x48}, + {0x90065, 0x40}, + {0x90066, 0x633}, + {0x90067, 0x149}, + {0x90068, 0x10}, + {0x90069, 0x4}, + {0x9006a, 0x18}, + {0x9006b, 0x0}, + {0x9006c, 0x4}, + {0x9006d, 0x78}, + {0x9006e, 0x549}, + {0x9006f, 0x633}, + {0x90070, 0x159}, + {0x90071, 0xd49}, + {0x90072, 0x633}, + {0x90073, 0x159}, + {0x90074, 0x94a}, + {0x90075, 0x633}, + {0x90076, 0x159}, + {0x90077, 0x441}, + {0x90078, 0x633}, + {0x90079, 0x149}, + {0x9007a, 0x42}, + {0x9007b, 0x633}, + {0x9007c, 0x149}, + {0x9007d, 0x1}, + {0x9007e, 0x633}, + {0x9007f, 0x149}, + {0x90080, 0x0}, + {0x90081, 0xe0}, + {0x90082, 0x109}, + {0x90083, 0xa}, + {0x90084, 0x10}, + {0x90085, 0x109}, + {0x90086, 0x9}, + {0x90087, 0x3c0}, + {0x90088, 0x149}, + {0x90089, 0x9}, + {0x9008a, 0x3c0}, + {0x9008b, 0x159}, + {0x9008c, 0x18}, + {0x9008d, 0x10}, + {0x9008e, 0x109}, + {0x9008f, 0x0}, + {0x90090, 0x3c0}, + {0x90091, 0x109}, + {0x90092, 0x18}, + {0x90093, 0x4}, + {0x90094, 0x48}, + {0x90095, 0x18}, + {0x90096, 0x4}, + {0x90097, 0x58}, + {0x90098, 0xb}, + {0x90099, 0x10}, + {0x9009a, 0x109}, + {0x9009b, 0x1}, + {0x9009c, 0x10}, + {0x9009d, 0x109}, + {0x9009e, 0x5}, + {0x9009f, 0x7c0}, + {0x900a0, 0x109}, + {0x900a1, 0x3}, + {0x900a2, 0x8}, + {0x900a3, 0x139}, + {0x900a4, 0x0}, + {0x900a5, 0x400}, + {0x900a6, 0x16e}, + {0x900a7, 0x8}, + {0x900a8, 0x478}, + {0x900a9, 0x109}, + {0x900aa, 0x0}, + {0x900ab, 0x8140}, + {0x900ac, 0x10c}, + {0x900ad, 0x10}, + {0x900ae, 0x8138}, + {0x900af, 0x10c}, + {0x900b0, 0x8}, + {0x900b1, 0x7c8}, + {0x900b2, 0x101}, + {0x900b3, 0x7a}, + {0x900b4, 0x8}, + {0x900b5, 0x109}, + {0x900b6, 0x8}, + {0x900b7, 0x448}, + {0x900b8, 0x109}, + {0x900b9, 0xf}, + {0x900ba, 0x7c0}, + {0x900bb, 0x109}, + {0x900bc, 0x47}, + {0x900bd, 0x630}, + {0x900be, 0x109}, + {0x900bf, 0x8}, + {0x900c0, 0x618}, + {0x900c1, 0x109}, + {0x900c2, 0x8}, + {0x900c3, 0xe0}, + {0x900c4, 0x109}, + {0x900c5, 0x0}, + {0x900c6, 0x8}, + {0x900c7, 0x109}, + {0x900c8, 0x0}, + {0x900c9, 0x7c8}, + {0x900ca, 0x109}, + {0x900cb, 0x8}, + {0x900cc, 0x8140}, + {0x900cd, 0x10c}, + {0x900ce, 0x0}, + {0x900cf, 0x478}, + {0x900d0, 0x109}, + {0x900d1, 0x0}, + {0x900d2, 0x1}, + {0x900d3, 0x8}, + {0x900d4, 0x8}, + {0x900d5, 0x4}, + {0x900d6, 0x8}, + {0x900d7, 0x8}, + {0x900d8, 0x7c8}, + {0x900d9, 0x101}, + {0x90006, 0x0}, + {0x90007, 0x0}, + {0x90008, 0x8}, + {0x90009, 0x0}, + {0x9000a, 0x0}, + {0x9000b, 0x0}, + {0xd00e7, 0x400}, + {0x90017, 0x0}, + {0x90026, 0x2e}, +}; +#endif diff --git a/arm-trusted-firmware/drivers/nxp/drivers.mk b/arm-trusted-firmware/drivers/nxp/drivers.mk new file mode 100644 index 0000000..d77e985 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/drivers.mk @@ -0,0 +1,99 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +############################################################################### + + +PLAT_DRIVERS_PATH := drivers/nxp +PLAT_DRIVERS_INCLUDE_PATH := include/drivers/nxp + +ifeq (${SMMU_NEEDED},yes) +PLAT_INCLUDES += -Iinclude/drivers/nxp/smmu/ +endif + +ifeq (${DCFG_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/dcfg/dcfg.mk +endif + +ifeq (${CSU_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/csu/csu.mk +endif + +ifeq (${TIMER_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/timer/timer.mk +endif + +ifeq (${INTERCONNECT_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/interconnect/interconnect.mk +endif + +ifeq (${GIC_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/gic/gic.mk +endif + +ifeq (${SD_MMC_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sd/sd_mmc.mk +endif + +ifeq (${CONSOLE_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/console/console.mk +endif + +ifeq (${SFP_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sfp/sfp.mk +endif + +ifeq (${XSPI_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/flexspi/nor/flexspi_nor.mk +endif + +ifeq (${QSPI_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/qspi/qspi.mk +endif + +ifeq (${SNVS_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/sec_mon/sec_mon.mk +endif + +ifeq ($(I2C_NEEDED),yes) +$(eval $(call add_define, I2C_INIT)) +include $(PLAT_DRIVERS_PATH)/i2c/i2c.mk +endif + +ifeq ($(DDR_DRIVER_NEEDED),yes) +$(eval $(call add_define, DDR_INIT)) +# define DDR_CNTRL_SOURCES +ifeq ($(DDRCNTLR),MMDC) +include $(PLAT_DRIVERS_PATH)/ddr/fsl-mmdc/ddr.mk +else +include $(PLAT_DRIVERS_PATH)/ddr/nxp-ddr/ddr.mk +endif # DDR_CNTRL_SOURCES +endif + +ifeq (${PMU_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/pmu/pmu.mk +endif + +ifeq (${CRYPTO_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/crypto/caam/caam.mk +endif + +ifeq (${TZASC_NEEDED},yes) +include $(PLAT_DRIVERS_PATH)/tzc/tzc.mk +endif + +ifeq (${GPIO_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/gpio/gpio.mk +endif + +ifeq (${IFC_NOR_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/ifc/nor/ifc_nor.mk +endif + +ifeq (${IFC_NAND_NEEDED},yes) +include ${PLAT_DRIVERS_PATH}/ifc/nand/ifc_nand.mk +endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c new file mode 100644 index 0000000..748228d --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c @@ -0,0 +1,25 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +int flexspi_nor_io_setup(uintptr_t nxp_flexspi_flash_addr, + size_t nxp_flexspi_flash_size, uint32_t fspi_base_reg_addr) +{ + int ret = 0; + + ret = fspi_init(fspi_base_reg_addr, nxp_flexspi_flash_addr); + /* Adding NOR Memory Map in XLAT Table */ + mmap_add_region(nxp_flexspi_flash_addr, nxp_flexspi_flash_addr, + nxp_flexspi_flash_size, MT_MEMORY | MT_RW); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h new file mode 100644 index 0000000..61fc236 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h @@ -0,0 +1,15 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FLEXSPI_NOR_H +#define FLEXSPI_NOR_H + +int flexspi_nor_io_setup(uintptr_t nxp_flexspi_flash_addr, + size_t nxp_flexspi_flash_size, + uint32_t fspi_base_reg_addr); + +#endif /* FLEXSPI_NOR_H */ diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk new file mode 100644 index 0000000..6d9eebb --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.mk @@ -0,0 +1,35 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${XSPI_NOR},) +XSPI_NOR := 1 + +FLEXSPI_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/flexspi/nor + +PLAT_XSPI_INCLUDES += -I$(FLEXSPI_DRIVERS_PATH) + +XSPI_BOOT_SOURCES += $(FLEXSPI_DRIVERS_PATH)/flexspi_nor.c \ + ${FLEXSPI_DRIVERS_PATH}/fspi.c +ifeq ($(DEBUG),1) +XSPI_BOOT_SOURCES += ${FLEXSPI_DRIVERS_PATH}/test_fspi.c +endif + +PLAT_XSPI_INCLUDES += -Iinclude/drivers/nxp/flexspi + +PLAT_INCLUDES += ${PLAT_XSPI_INCLUDES} + +ifeq (${BL_COMM_XSPI_NEEDED},yes) +BL_COMMON_SOURCES += ${XSPI_BOOT_SOURCES} +else +ifeq (${BL2_XSPI_NEEDED},yes) +BL2_SOURCES += ${XSPI_BOOT_SOURCES} +endif +ifeq (${BL31_XSPI_NEEDED},yes) +BL31_SOURCES += ${XSPI_BOOT_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c new file mode 100644 index 0000000..7c919b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c @@ -0,0 +1,853 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * NXP FlexSpi Controller Driver. + * Copyright 2021 NXP + * + */ +#include +#include +#include +#include + +#include +#include +#include "fspi.h" +#include +#include + +#ifdef DEBUG_FLEXSPI +#define PR printf("In [%s][%d]\n", __func__, __LINE__) +#define PRA(a, b) printf("In [%s][%d] %s="a"\n", __func__, __LINE__, #b, b) +#else +#define PR +#define PRA(a, b) +#endif + +/* + * This errata is valid for all NXP SoC. + */ +#define ERRATA_FLASH_A050272 1 + +static uintptr_t fspi_base_reg_addr; +static uintptr_t fspi_flash_base_addr; + +static void fspi_RDSR(uint32_t *, const void *, uint32_t); + +static void fspi_writel(uint32_t x_addr, uint32_t x_val) +{ + fspi_out32((uint32_t *)(fspi_base_reg_addr + x_addr), + (uint32_t) x_val); +} + +static uint32_t fspi_readl(uint32_t x_addr) +{ + return fspi_in32((uint32_t *)(fspi_base_reg_addr + x_addr)); +} + +static void fspi_MDIS(uint8_t x_disable) +{ + uint32_t ui_reg; + + ui_reg = fspi_readl(FSPI_MCR0); + if (x_disable != 0U) { + ui_reg |= FSPI_MCR0_MDIS; + } else { + ui_reg &= (uint32_t) (~FSPI_MCR0_MDIS); + } + + fspi_writel(FSPI_MCR0, ui_reg); +} + +static void fspi_lock_LUT(void) +{ + fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); + fspi_writel(FSPI_LCKCR, FSPI_LCKER_LOCK); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); +} + +static void fspi_unlock_LUT(void) +{ + fspi_writel(FSPI_LUTKEY, FSPI_LUTKEY_VALUE); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); + fspi_writel(FSPI_LCKCR, FSPI_LCKER_UNLOCK); + VERBOSE("%s 0x%x\n", __func__, fspi_readl(FSPI_LCKCR)); +} + +static void fspi_op_setup(uint32_t fspi_op_seq_id, bool ignore_flash_sz) +{ + uint32_t x_addr, x_instr0 = 0, x_instr1 = 0, x_instr2 = 0; + uint32_t cmd_id1, cmd_id2; + + VERBOSE("In func %s\n", __func__); + + switch (fspi_op_seq_id) { + case FSPI_READ_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_READ; + cmd_id2 = FSPI_NOR_CMD_READ_4B; + x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_READ); + break; + case FSPI_FASTREAD_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_FASTREAD; + cmd_id2 = FSPI_NOR_CMD_FASTREAD_4B; + x_instr2 = FSPI_INSTR_OPRND0(8) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_DUMMY_SDR) + | FSPI_INSTR_OPRND1(0) + | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); + break; + case FSPI_WRITE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_PP; + cmd_id2 = FSPI_NOR_CMD_PP_4B; + x_instr2 = FSPI_INSTR_OPRND0(0) | FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_WRITE); + break; + case FSPI_WREN_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_WREN; + cmd_id2 = FSPI_NOR_CMD_WREN; + break; + case FSPI_SE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_SE_64K; + cmd_id2 = FSPI_NOR_CMD_SE_64K_4B; + break; + case FSPI_4K_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_SE_4K; + cmd_id2 = FSPI_NOR_CMD_SE_4K_4B; + break; + case FSPI_BE_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_BE; + cmd_id2 = FSPI_NOR_CMD_BE; + break; + case FSPI_RDSR_SEQ_ID: + cmd_id1 = FSPI_NOR_CMD_RDSR; + cmd_id2 = FSPI_NOR_CMD_RDSR; + break; + } + + x_addr = FSPI_LUTREG_OFFSET + (uint32_t)(0x10 * fspi_op_seq_id); + if ((F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) || (ignore_flash_sz)) { + x_instr0 = FSPI_INSTR_OPRND0(cmd_id1); + x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR24BIT); + VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id1, x_addr); + } else { + x_instr0 = FSPI_INSTR_OPRND0(cmd_id2); + x_instr1 = FSPI_INSTR_OPRND1(FSPI_LUT_ADDR32BIT); + VERBOSE("CMD_ID = %x offset = 0x%x\n", cmd_id2, x_addr); + } + x_instr0 |= FSPI_INSTR_PAD0(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE0(FSPI_LUT_CMD); + + x_instr1 |= FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_ADDR); + + if (fspi_op_seq_id == FSPI_RDSR_SEQ_ID) { + x_instr0 |= FSPI_INSTR_OPRND1(1) | FSPI_INSTR_PAD1(FSPI_LUT_PAD1) + | FSPI_INSTR_OPCODE1(FSPI_LUT_READ); + } else if ((fspi_op_seq_id != FSPI_BE_SEQ_ID) + && (fspi_op_seq_id != FSPI_WREN_SEQ_ID)) { + x_instr0 |= x_instr1; + } + + fspi_writel((x_addr), x_instr0); + fspi_writel((x_addr + U(0x4)), x_instr2); + fspi_writel((x_addr + U(0x8)), (uint32_t) 0x0); /* STOP command */ + fspi_writel((x_addr + U(0xc)), (uint32_t) 0x0); /* STOP command */ +} + +static void fspi_setup_LUT(void) +{ + VERBOSE("In func %s\n", __func__); + fspi_unlock_LUT(); + + /* LUT Setup for READ Command 3-Byte low Frequency */ + fspi_op_setup(FSPI_READ_SEQ_ID, false); + + /* LUT Setup for FAST READ Command 3-Byte/4-Byte high Frequency */ + fspi_op_setup(FSPI_FASTREAD_SEQ_ID, false); + + /* LUT Setup for Page Program */ + fspi_op_setup(FSPI_WRITE_SEQ_ID, false); + + /* LUT Setup for WREN */ + fspi_op_setup(FSPI_WREN_SEQ_ID, true); + + /* LUT Setup for Sector_Erase */ + fspi_op_setup(FSPI_SE_SEQ_ID, false); + + /* LUT Setup for Sub Sector 4K Erase */ + fspi_op_setup(FSPI_4K_SEQ_ID, false); + + /* LUT Setup for Bulk_Erase */ + fspi_op_setup(FSPI_BE_SEQ_ID, true); + + /* Read Status */ + fspi_op_setup(FSPI_RDSR_SEQ_ID, true); + + fspi_lock_LUT(); +} + +static inline void fspi_ahb_invalidate(void) +{ + uint32_t reg; + + VERBOSE("In func %s %d\n", __func__, __LINE__); + reg = fspi_readl(FSPI_MCR0); + reg |= FSPI_MCR0_SWRST; + fspi_writel(FSPI_MCR0, reg); + while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST) != 0) + ; /* FSPI_MCR0_SWRESET_MASK */ + VERBOSE("In func %s %d\n", __func__, __LINE__); +} + +#if defined(CONFIG_FSPI_AHB) +static void fspi_init_ahb(void) +{ + uint32_t i, x_flash_cr2, seq_id; + + x_flash_cr2 = 0; + /* Reset AHB RX buffer CR configuration */ + for (i = 0; i < 8; i++) { + fspi_writel((FSPI_AHBRX_BUF0CR0 + 4 * i), 0U); + } + + /* Set ADATSZ with the maximum AHB buffer size */ + fspi_writel(FSPI_AHBRX_BUF7CR0, + ((uint32_t) ((FSPI_RX_MAX_AHBBUF_SIZE / 8U) | + FSPI_AHBRXBUF0CR7_PREF))); + + /* Known limitation handling: prefetch and + * no start address alignment.*/ + fspi_writel(FSPI_AHBCR, FSPI_AHBCR_PREF_EN); + INFO("xAhbcr=0x%x\n", fspi_readl(FSPI_AHBCR)); + + // Setup AHB READ sequenceID for all flashes. + x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); + + seq_id = CONFIG_FSPI_FASTREAD ? + FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; + x_flash_cr2 |= ((seq_id << FSPI_FLSHXCR2_ARDSEQI_SHIFT) & 0x1f); + + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); + + fspi_writel(FSPI_FLSHA1CR2, x_flash_cr2); + x_flash_cr2 = fspi_readl(FSPI_FLSHA1CR2); + INFO("x_flash_cr2=0x%x\n", x_flash_cr2); +} +#endif + +int xspi_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) +{ + if (x_size_bytes == 0) { + ERROR("Zero length reads are not allowed\n"); + return XSPI_READ_FAIL; + } + +#if defined(CONFIG_FSPI_AHB) + return xspi_ahb_read(pc_rx_addr, pc_rx_buf, x_size_bytes); +#else + return xspi_ip_read(pc_rx_addr, pc_rx_buf, x_size_bytes); +#endif +} +#if defined(CONFIG_FSPI_AHB) +int xspi_ahb_read(uint32_t pc_rx_addr, uint32_t *pc_rx_buf, uint32_t x_size_bytes) +{ + VERBOSE("In func %s 0x%x\n", __func__, (pc_rx_addr)); + + if (F_FLASH_SIZE_BYTES <= SZ_16M_BYTES) { + pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_24BIT_ADDRESS)); + } else { + pc_rx_addr = ((uint32_t)(pcRxAddr & MASK_32BIT_ADDRESS)); + } + + pc_rx_addr = ((uint32_t)(pcRxAddr + fspi_flash_base_addr)); + + if (((pc_rx_addr % 4) != 0) || (((uintptr_t)pc_rx_buf % 4) != 0)) { + WARN("%s: unaligned Start Address src=%ld dst=0x%p\n", + __func__, (pc_rx_addr - fspi_flash_base_addr), pc_rx_buf); + } + + /* Directly copy from AHB Buffer */ + memcpy(pc_rx_buf, (void *)(uintptr_t)pc_rx_addr, x_size_bytes); + + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} +#endif + +int xspi_ip_read(uint32_t pc_rx_addr, uint32_t *pv_rx_buf, uint32_t ui_len) +{ + + uint32_t i = 0U, j = 0U, x_rem = 0U; + uint32_t x_iteration = 0U, x_size_rx = 0U, x_size_wm, temp_size; + uint32_t data = 0U; + uint32_t x_len_bytes; + uint32_t x_addr, sts0, intr, seq_id; + + x_addr = (uint32_t) pc_rx_addr; + x_len_bytes = ui_len; + + /* Watermark level : 8 bytes. (BY DEFAULT) */ + x_size_wm = 8U; + + /* Clear RX Watermark interrupt in INT register, if any existing. */ + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); + PRA("0x%x", fspi_readl(FSPI_INTR)); + /* Invalid the RXFIFO, to run next IP Command */ + /* Clears data entries in IP Rx FIFOs, Also reset R/W pointers */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTEN_IPCMDDONE); + + while (x_len_bytes) { + + /* FlexSPI can store no more than FSPI_RX_IPBUF_SIZE */ + x_size_rx = (x_len_bytes > FSPI_RX_IPBUF_SIZE) ? + FSPI_RX_IPBUF_SIZE : x_len_bytes; + + /* IP Control Register0 - SF Address to be read */ + fspi_writel(FSPI_IPCR0, x_addr); + PRA("0x%x", fspi_readl(FSPI_IPCR0)); + /* IP Control Register1 - SEQID_READ operation, Size */ + + seq_id = CONFIG_FSPI_FASTREAD ? + FSPI_FASTREAD_SEQ_ID : FSPI_READ_SEQ_ID; + + fspi_writel(FSPI_IPCR1, + (uint32_t)(seq_id << FSPI_IPCR1_ISEQID_SHIFT) | + (uint16_t) x_size_rx); + + PRA("0x%x", fspi_readl(FSPI_IPCR1)); + + do { + sts0 = fspi_readl(FSPI_STS0); + } while (((sts0 & FSPI_STS0_ARB_IDLE) == 0) && + ((sts0 & FSPI_STS0_SEQ_IDLE) == 0)); + + /* Trigger IP Read Command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + PRA("0x%x", fspi_readl(FSPI_IPCMD)); + + intr = fspi_readl(FSPI_INTR); + if (((intr & FSPI_INTR_IPCMDGE) != 0) || + ((intr & FSPI_INTR_IPCMDERR) != 0)) { + ERROR("Error in IP READ INTR=0x%x\n", intr); + return -XSPI_IP_READ_FAIL; + } + /* Will read in n iterations of each 8 FIFO's(WM level) */ + x_iteration = x_size_rx / x_size_wm; + for (i = 0U; i < x_iteration; i++) { + if ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK) == 0) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + /* Wait for IP Rx Watermark Fill event */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPRXWA_MASK)) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + + /* Read RX FIFO's(upto WM level) & copy to rxbuffer */ + for (j = 0U; j < x_size_wm; j += 4U) { + /* Read FIFO Data Register */ + data = fspi_readl(FSPI_RFDR + j); +#if FSPI_IPDATA_SWAP /* Just In case you want swap */ + data = bswap32(data); +#endif + memcpy(pv_rx_buf++, &data, 4); + } + + /* Clear IP_RX_WATERMARK Event in INTR register */ + /* Reset FIFO Read pointer for next iteration.*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA); + } + + x_rem = x_size_rx % x_size_wm; + + if (x_rem != 0U) { + /* Wait for data filled */ + while (!(fspi_readl(FSPI_IPRXFSTS) & FSPI_IPRXFSTS_FILL_MASK)) { + PRA("0x%x", fspi_readl(FSPI_IPRXFSTS)); + } + + temp_size = 0; + j = 0U; + while (x_rem > 0U) { + data = 0U; + data = fspi_readl(FSPI_RFDR + j); +#if FSPI_IPDATA_SWAP /* Just In case you want swap */ + data = bswap32(data); +#endif + temp_size = (x_rem < 4) ? x_rem : 4; + memcpy(pv_rx_buf++, &data, temp_size); + x_rem -= temp_size; + } + } + + + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + + /* Invalid the RX FIFO, to run next IP Command */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + /* Clear IP Command Done flag in interrupt register*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + /* Update remaining len, Increment x_addr read pointer. */ + x_len_bytes -= x_size_rx; + x_addr += x_size_rx; + } + PR; + return XSPI_SUCCESS; +} + +void xspi_ip_write(uint32_t pc_wr_addr, uint32_t *pv_wr_buf, uint32_t ui_len) +{ + + uint32_t x_iteration = 0U, x_rem = 0U; + uint32_t x_size_tx = 0U, x_size_wm, temp_size; + uint32_t i = 0U, j = 0U; + uint32_t ui_data = 0U; + uint32_t x_addr, x_len_bytes; + + + x_size_wm = 8U; /* Default TX WaterMark level: 8 Bytes. */ + x_addr = (uint32_t)pc_wr_addr; + x_len_bytes = ui_len; + VERBOSE("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", + __func__, __LINE__, x_addr, x_len_bytes); + + while (x_len_bytes != 0U) { + + x_size_tx = (x_len_bytes > FSPI_TX_IPBUF_SIZE) ? + FSPI_TX_IPBUF_SIZE : x_len_bytes; + + /* IP Control Register0 - SF Address to be read */ + fspi_writel(FSPI_IPCR0, x_addr); + INFO("In func %s[%d] x_addr =0x%x xLen_bytes=%d\n", + __func__, __LINE__, x_addr, x_len_bytes); + + /* + * Fill TX FIFO's.. + * + */ + + x_iteration = x_size_tx / x_size_wm; + for (i = 0U; i < x_iteration; i++) { + + /* Ensure TX FIFO Watermark Available */ + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE_MASK) == 0) + ; + + + /* Fill TxFIFO's ( upto watermark level) */ + for (j = 0U; j < x_size_wm; j += 4U) { + memcpy(&ui_data, pv_wr_buf++, 4); + /* Write TX FIFO Data Register */ + fspi_writel((FSPI_TFDR + j), ui_data); + + } + + /* Clear IP_TX_WATERMARK Event in INTR register */ + /* Reset the FIFO Write pointer for next iteration */ + fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); + } + + x_rem = x_size_tx % x_size_wm; + + if (x_rem != 0U) { + /* Wait for TXFIFO empty */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPTXWE)) + ; + + temp_size = 0U; + j = 0U; + while (x_rem > 0U) { + ui_data = 0U; + temp_size = (x_rem < 4U) ? x_rem : 4U; + memcpy(&ui_data, pv_wr_buf++, temp_size); + INFO("%d ---> pv_wr_buf=0x%p\n", __LINE__, pv_wr_buf); + fspi_writel((FSPI_TFDR + j), ui_data); + x_rem -= temp_size; + j += 4U ; /* TODO: May not be needed*/ + } + /* Clear IP_TX_WATERMARK Event in INTR register */ + /* Reset FIFO's Write pointer for next iteration.*/ + fspi_writel(FSPI_INTR, FSPI_INTR_IPTXWE); + } + + /* IP Control Register1 - SEQID_WRITE operation, Size */ + fspi_writel(FSPI_IPCR1, (uint32_t)(FSPI_WRITE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | (uint16_t) x_size_tx); + /* Trigger IP Write Command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + /* Wait for IP Write command done */ + while (!(fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK)) + ; + + /* Invalidate TX FIFOs & acknowledge IP_CMD_DONE event */ + fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + /* for next iteration */ + x_len_bytes -= x_size_tx; + x_addr += x_size_tx; + } + +} + +int xspi_write(uint32_t pc_wr_addr, void *pv_wr_buf, uint32_t ui_len) +{ + + uint32_t x_addr; + uint32_t x_page1_len = 0U, x_page_l_len = 0U; + uint32_t i, j = 0U; + void *buf = pv_wr_buf; + + VERBOSE("\nIn func %s\n", __func__); + + x_addr = (uint32_t)(pc_wr_addr); + if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { + x_page1_len = ui_len; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len <= F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { + x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); + if (ui_len > x_page1_len) { + x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; + } else { + x_page1_len = ui_len; + x_page_l_len = 0; + } + j = 0U; + INFO("%d 0x%x 0x%x\n", x_addr % F_PAGE_256, x_addr % F_PAGE_256, F_PAGE_256); + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) == 0)) { + j = ui_len / F_PAGE_256; + x_page_l_len = ui_len % F_PAGE_256; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } else if ((ui_len > F_PAGE_256) && ((x_addr % F_PAGE_256) != 0)) { + x_page1_len = (F_PAGE_256 - (x_addr % F_PAGE_256)); + j = (ui_len - x_page1_len) / F_PAGE_256; + x_page_l_len = (ui_len - x_page1_len) % F_PAGE_256; + INFO("%d ---> x_page1_len=0x%x x_page_l_len =0x%x j=0x%x\n", __LINE__, x_page1_len, x_page_l_len, j); + } + + if (x_page1_len != 0U) { + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, x_page1_len); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); + x_addr += x_page1_len; + /* TODO What is buf start is not 4 aligned */ + buf = buf + x_page1_len; + } + + for (i = 0U; i < j; i++) { + INFO("In for loop Buf pv_wr_buf=%p, final Buf=%p x_addr=0x%x offset_buf %d.\n", + pv_wr_buf, buf, x_addr, x_page1_len/4); + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, F_PAGE_256); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + x_addr += F_PAGE_256; + /* TODO What is buf start is not 4 aligned */ + buf = buf + F_PAGE_256; + INFO("Initial Buf pv_wr_buf=%p, final Buf=%p\n", pv_wr_buf, buf); + } + + if (x_page_l_len != 0U) { + INFO("%d Initial Buf pv_wr_buf=%p, final Buf=%p x_page_l_len=0x%x\n", __LINE__, pv_wr_buf, buf, x_page_l_len); + xspi_wren(x_addr); + xspi_ip_write(x_addr, (uint32_t *)buf, x_page_l_len); + while (is_flash_busy()) + ; + INFO("%d Initial pc_wr_addr=0x%x, Final x_addr=0x%x, Initial ui_len=0x%x Final ui_len=0x%x\n", + __LINE__, pc_wr_addr, x_addr, ui_len, (x_addr-pc_wr_addr)); + } + + VERBOSE("Now calling func call Invalidate%s\n", __func__); + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + +int xspi_wren(uint32_t pc_wr_addr) +{ + VERBOSE("In func %s Addr=0x%x\n", __func__, pc_wr_addr); + + fspi_writel(FSPI_IPTXFCR, FSPI_IPTXFCR_CLR); + + fspi_writel(FSPI_IPCR0, (uint32_t)pc_wr_addr); + fspi_writel(FSPI_IPCR1, ((FSPI_WREN_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + return XSPI_SUCCESS; +} + +static void fspi_bbluk_er(void) +{ + VERBOSE("In func %s\n", __func__); + fspi_writel(FSPI_IPCR0, 0x0); + fspi_writel(FSPI_IPCR1, ((FSPI_BE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 20)); + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + +} + +static void fspi_RDSR(uint32_t *rxbuf, const void *p_addr, uint32_t size) +{ + uint32_t iprxfcr = 0U; + uint32_t data = 0U; + + iprxfcr = fspi_readl(FSPI_IPRXFCR); + /* IP RX FIFO would be read by processor */ + iprxfcr = iprxfcr & (uint32_t)~FSPI_IPRXFCR_CLR; + /* Invalid data entries in IP RX FIFO */ + iprxfcr = iprxfcr | FSPI_IPRXFCR_CLR; + fspi_writel(FSPI_IPRXFCR, iprxfcr); + + fspi_writel(FSPI_IPCR0, (uintptr_t) p_addr); + fspi_writel(FSPI_IPCR1, + (uint32_t) ((FSPI_RDSR_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) + | (uint16_t) size)); + /* Trigger the command */ + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + /* Wait for command done */ + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) + ; + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + + data = fspi_readl(FSPI_RFDR); + memcpy(rxbuf, &data, size); + + /* Rx FIFO invalidation needs to be done prior w1c of INTR.IPRXWA bit */ + fspi_writel(FSPI_IPRXFCR, FSPI_IPRXFCR_CLR); + fspi_writel(FSPI_INTR, FSPI_INTR_IPRXWA_MASK); + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); + +} + +bool is_flash_busy(void) +{ +#define FSPI_ONE_BYTE 1 + uint8_t data[4]; + + VERBOSE("In func %s\n\n", __func__); + fspi_RDSR((uint32_t *) data, 0, FSPI_ONE_BYTE); + + return !!((uint32_t) data[0] & FSPI_NOR_SR_WIP_MASK); +} + +int xspi_bulk_erase(void) +{ + VERBOSE("In func %s\n", __func__); + xspi_wren((uint32_t) 0x0); + fspi_bbluk_er(); + while (is_flash_busy()) + ; + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + +static void fspi_sec_er(uint32_t pc_wr_addr) +{ + uint32_t x_addr; + + VERBOSE("In func %s\n", __func__); + x_addr = (uint32_t)(pc_wr_addr); + + fspi_writel(FSPI_IPCR0, x_addr); + INFO("In [%s][%d] Erase address 0x%x\n", __func__, __LINE__, (x_addr)); +#if CONFIG_FSPI_ERASE_4K + fspi_writel(FSPI_IPCR1, ((FSPI_4K_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); +#else + fspi_writel(FSPI_IPCR1, ((FSPI_SE_SEQ_ID << FSPI_IPCR1_ISEQID_SHIFT) | 0)); +#endif + fspi_writel(FSPI_IPCMD, FSPI_IPCMD_TRG_MASK); + + while ((fspi_readl(FSPI_INTR) & FSPI_INTR_IPCMDDONE_MASK) == 0) { + PRA("0x%x", fspi_readl(FSPI_INTR)); + } + fspi_writel(FSPI_INTR, FSPI_INTR_IPCMDDONE_MASK); +} + +int xspi_sector_erase(uint32_t pc_wr_addr, uint32_t ui_len) +{ + uint32_t x_addr, x_len_bytes, i, num_sector = 0U; + + VERBOSE("In func %s\n", __func__); + x_addr = (uint32_t)(pc_wr_addr); + if ((x_addr % F_SECTOR_ERASE_SZ) != 0) { + ERROR("!!! In func %s, unalinged start address can only be in multiples of 0x%x\n", + __func__, F_SECTOR_ERASE_SZ); + return -XSPI_ERASE_FAIL; + } + + x_len_bytes = ui_len * 1; + if (x_len_bytes < F_SECTOR_ERASE_SZ) { + ERROR("!!! In func %s, Less than 1 sector can only be in multiples of 0x%x\n", + __func__, F_SECTOR_ERASE_SZ); + return -XSPI_ERASE_FAIL; + } + + num_sector = x_len_bytes/F_SECTOR_ERASE_SZ; + num_sector += x_len_bytes % F_SECTOR_ERASE_SZ ? 1U : 0U; + INFO("F_SECTOR_ERASE_SZ: 0x%08x, num_sector: %d\n", F_SECTOR_ERASE_SZ, num_sector); + + for (i = 0U; i < num_sector ; i++) { + xspi_wren(x_addr + (F_SECTOR_ERASE_SZ * i)); + fspi_sec_er(x_addr + (F_SECTOR_ERASE_SZ * i)); + while (is_flash_busy()) + ; + } + fspi_ahb_invalidate(); + return XSPI_SUCCESS; +} + + +__attribute__((unused)) static void fspi_delay_ms(uint32_t x) +{ + volatile unsigned long ul_count; + + for (ul_count = 0U; ul_count < (30U * x); ul_count++) + ; + +} + + +#if defined(DEBUG_FLEXSPI) +static void fspi_dump_regs(void) +{ + uint32_t i; + + VERBOSE("\nRegisters Dump:\n"); + VERBOSE("Flexspi: Register FSPI_MCR0(0x%x) = 0x%08x\n", FSPI_MCR0, fspi_readl(FSPI_MCR0)); + VERBOSE("Flexspi: Register FSPI_MCR2(0x%x) = 0x%08x\n", FSPI_MCR2, fspi_readl(FSPI_MCR2)); + VERBOSE("Flexspi: Register FSPI_DLL_A_CR(0x%x) = 0x%08x\n", FSPI_DLLACR, fspi_readl(FSPI_DLLACR)); + VERBOSE("\n"); + + for (i = 0U; i < 8U; i++) { + VERBOSE("Flexspi: Register FSPI_AHBRX_BUF0CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF0CR0 + i * 4, fspi_readl((FSPI_AHBRX_BUF0CR0 + i * 4))); + } + VERBOSE("\n"); + + VERBOSE("Flexspi: Register FSPI_AHBRX_BUF7CR0(0x%x) = 0x%08x\n", FSPI_AHBRX_BUF7CR0, fspi_readl(FSPI_AHBRX_BUF7CR0)); + VERBOSE("Flexspi: Register FSPI_AHB_CR(0x%x) \t = 0x%08x\n", FSPI_AHBCR, fspi_readl(FSPI_AHBCR)); + VERBOSE("\n"); + + for (i = 0U; i < 4U; i++) { + VERBOSE("Flexspi: Register FSPI_FLSH_A1_CR2,(0x%x) = 0x%08x\n", FSPI_FLSHA1CR2 + i * 4, fspi_readl(FSPI_FLSHA1CR2 + i * 4)); + } +} +#endif + +int fspi_init(uint32_t base_reg_addr, uint32_t flash_start_addr) +{ + uint32_t mcrx; + uint32_t flash_size; + + if (fspi_base_reg_addr != 0U) { + INFO("FSPI is already initialized.\n"); + return XSPI_SUCCESS; + } + + fspi_base_reg_addr = base_reg_addr; + fspi_flash_base_addr = flash_start_addr; + + INFO("Flexspi driver: Version v1.0\n"); + INFO("Flexspi: Default MCR0 = 0x%08x, before reset\n", fspi_readl(FSPI_MCR0)); + VERBOSE("Flexspi: Resetting controller...\n"); + + /* Reset FlexSpi Controller */ + fspi_writel(FSPI_MCR0, FSPI_MCR0_SWRST); + while ((fspi_readl(FSPI_MCR0) & FSPI_MCR0_SWRST)) + ; /* FSPI_MCR0_SWRESET_MASK */ + + + /* Disable Controller Module before programming its registersi, especially MCR0 (Master Control Register0) */ + fspi_MDIS(1); + /* + * Program MCR0 with default values, AHB Timeout(0xff), IP Timeout(0xff). {FSPI_MCR0- 0xFFFF0000} + */ + + /* Timeout wait cycle for AHB command grant */ + mcrx = fspi_readl(FSPI_MCR0); + mcrx |= (uint32_t)((FSPI_MAX_TIMEOUT_AHBCMD << FSPI_MCR0_AHBGRANTWAIT_SHIFT) & (FSPI_MCR0_AHBGRANTWAIT_MASK)); + + /* Time out wait cycle for IP command grant*/ + mcrx |= (uint32_t) (FSPI_MAX_TIMEOUT_IPCMD << FSPI_MCR0_IPGRANTWAIT_SHIFT) & (FSPI_MCR0_IPGRANTWAIT_MASK); + + /* TODO why BE64 set BE32*/ + mcrx |= (uint32_t) (FSPI_ENDCFG_LE64 << FSPI_MCR0_ENDCFG_SHIFT) & FSPI_MCR0_ENDCFG_MASK; + + fspi_writel(FSPI_MCR0, mcrx); + + /* Reset the DLL register to default value */ + fspi_writel(FSPI_DLLACR, FSPI_DLLACR_OVRDEN); + fspi_writel(FSPI_DLLBCR, FSPI_DLLBCR_OVRDEN); + +#if ERRATA_FLASH_A050272 /* ERRATA DLL */ + for (uint8_t delay = 100U; delay > 0U; delay--) { + __asm__ volatile ("nop"); + } +#endif + + /* Configure flash control registers for different chip select */ + flash_size = (F_FLASH_SIZE_BYTES * FLASH_NUM) / FSPI_BYTES_PER_KBYTES; + fspi_writel(FSPI_FLSHA1CR0, flash_size); + fspi_writel(FSPI_FLSHA2CR0, 0U); + fspi_writel(FSPI_FLSHB1CR0, 0U); + fspi_writel(FSPI_FLSHB2CR0, 0U); + +#if defined(CONFIG_FSPI_AHB) + fspi_init_ahb(); +#endif + /* RE-Enable Controller Module */ + fspi_MDIS(0); + INFO("Flexspi: After MCR0 = 0x%08x,\n", fspi_readl(FSPI_MCR0)); + fspi_setup_LUT(); + + /* Dump of all registers, ensure controller not disabled anymore*/ +#if defined(DEBUG_FLEXSPI) + fspi_dump_regs(); +#endif + + INFO("Flexspi: Init done!!\n"); + +#if DEBUG_FLEXSPI + + uint32_t xspi_addr = SZ_57M; + + /* + * Second argument of fspi_test is the size of buffer(s) passed + * to the function. + * SIZE_BUFFER defined in test_fspi.c is kept large enough to + * accommodate variety of sizes for regressive tests. + */ + fspi_test(xspi_addr, 0x40, 0); + fspi_test(xspi_addr, 0x15, 2); + fspi_test(xspi_addr, 0x80, 0); + fspi_test(xspi_addr, 0x81, 0); + fspi_test(xspi_addr, 0x79, 3); + + fspi_test(xspi_addr + 0x11, 0x15, 0); + fspi_test(xspi_addr + 0x11, 0x40, 0); + fspi_test(xspi_addr + 0xff, 0x40, 1); + fspi_test(xspi_addr + 0x25, 0x81, 2); + fspi_test(xspi_addr + 0xef, 0x6f, 3); + + fspi_test((xspi_addr - F_SECTOR_ERASE_SZ), 0x229, 0); +#endif + + return XSPI_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h new file mode 100644 index 0000000..da2e269 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h @@ -0,0 +1,385 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * FlexSpi Registers & Bits definition. + * + */ + +#ifndef FSPI_H +#define FSPI_H + +#ifndef __ASSEMBLER__ +#include + +#ifdef NXP_FSPI_BE +#define fspi_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define fspi_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_FSPI_LE) +#define fspi_in32(a) mmio_read_32((uintptr_t)(a)) +#define fspi_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define FSPI register endianness +#endif + +#endif + +/* All LE so not swap needed */ +#define FSPI_IPDATA_SWAP 0U +#define FSPI_AHBDATA_SWAP 0U + +#define CONFIG_FSPI_FASTREAD 1U + +#define FSPI_BYTES_PER_KBYTES 0x400U +#define FLASH_NUM 1U + +#define FSPI_READ_SEQ_ID 0U +#define FSPI_WREN_SEQ_ID 1U +#define FSPI_WRITE_SEQ_ID 2U +#define FSPI_SE_SEQ_ID 3U +#define FSPI_RDSR_SEQ_ID 4U +#define FSPI_BE_SEQ_ID 5U +#define FSPI_FASTREAD_SEQ_ID 6U +#define FSPI_4K_SEQ_ID 7U + +/* + * LUT register layout: + * + * --------------------------------------------------- + * | INSTR1 | PAD1 | OPRND1 | INSTR0 | PAD0 | OPRND0 | + * --------------------------------------------------- + * + * INSTR_SHIFT- 10, PAD_SHIFT - 8, OPRND_SHIFT -0 + */ +#define FSPI_INSTR_OPRND0_SHIFT 0 +#define FSPI_INSTR_OPRND0(x) (x << FSPI_INSTR_OPRND0_SHIFT) +#define FSPI_INSTR_PAD0_SHIFT 8 +#define FSPI_INSTR_PAD0(x) ((x) << FSPI_INSTR_PAD0_SHIFT) +#define FSPI_INSTR_OPCODE0_SHIFT 10 +#define FSPI_INSTR_OPCODE0(x) ((x) << FSPI_INSTR_OPCODE0_SHIFT) +#define FSPI_INSTR_OPRND1_SHIFT 16 +#define FSPI_INSTR_OPRND1(x) ((x) << FSPI_INSTR_OPRND1_SHIFT) +#define FSPI_INSTR_PAD1_SHIFT 24 +#define FSPI_INSTR_PAD1(x) ((x) << FSPI_INSTR_PAD1_SHIFT) +#define FSPI_INSTR_OPCODE1_SHIFT 26 +#define FSPI_INSTR_OPCODE1(x) ((x) << FSPI_INSTR_OPCODE1_SHIFT) + +/* Instruction set for the LUT register. */ +#define LUT_STOP 0x00 +#define LUT_CMD 0x01 +#define LUT_ADDR 0x02 +#define LUT_CADDR_SDR 0x03 +#define LUT_MODE 0x04 +#define LUT_MODE2 0x05 +#define LUT_MODE4 0x06 +#define LUT_MODE8 0x07 +#define LUT_NXP_WRITE 0x08 +#define LUT_NXP_READ 0x09 + +#define LUT_LEARN_SDR 0x0A +#define LUT_DATSZ_SDR 0x0B +#define LUT_DUMMY 0x0C +#define LUT_DUMMY_RWDS_SDR 0x0D +#define LUT_JMP_ON_CS 0x1F +#define LUT_CMD_DDR 0x21 +#define LUT_ADDR_DDR 0x22 +#define LUT_CADDR_DDR 0x23 +#define LUT_MODE_DDR 0x24 +#define LUT_MODE2_DDR 0x25 +#define LUT_MODE4_DDR 0x26 +#define LUT_MODE8_DDR 0x27 +#define LUT_WRITE_DDR 0x28 +#define LUT_READ_DDR 0x29 +#define LUT_LEARN_DDR 0x2A +#define LUT_DATSZ_DDR 0x2B +#define LUT_DUMMY_DDR 0x2C +#define LUT_DUMMY_RWDS_DDR 0x2D + +#define FSPI_NOR_CMD_READ 0x03 +#define FSPI_NOR_CMD_READ_4B 0x13 +#define FSPI_NOR_CMD_FASTREAD 0x0b +#define FSPI_NOR_CMD_FASTREAD_4B 0x0c +#define FSPI_NOR_CMD_PP 0x02 +#define FSPI_NOR_CMD_PP_4B 0x12 +#define FSPI_NOR_CMD_WREN 0x06 +#define FSPI_NOR_CMD_SE_64K 0xd8 +#define FSPI_NOR_CMD_SE_64K_4B 0xdc +#define FSPI_NOR_CMD_SE_4K 0x20 +#define FSPI_NOR_CMD_SE_4K_4B 0x21 +#define FSPI_NOR_CMD_BE 0x60 +#define FSPI_NOR_CMD_RDSR 0x05 +#define FSPI_NOR_CMD_WREN_STOP 0x04 + +#define FSPI_LUT_STOP 0x00 +#define FSPI_LUT_CMD 0x01 +#define FSPI_LUT_ADDR 0x02 + +#define FSPI_LUT_PAD1 0 +#define FSPI_LUT_PAD2 1 +#define FSPI_LUT_PAD4 2 +#define FSPI_LUT_PAD8 3 + +#define FSPI_LUT_ADDR24BIT 0x18 +#define FSPI_LUT_ADDR32BIT 0x20 + +#define FSPI_LUT_WRITE 0x08 +#define FSPI_LUT_READ 0x09 +#define FSPI_DUMMY_SDR 0x0c + +/* TODO Check size if functional*/ +#define FSPI_RX_IPBUF_SIZE 0x200 /* 64*64 bits */ +#define FSPI_TX_IPBUF_SIZE 0x400 /* 128*64 bits */ + +#define FSPI_RX_MAX_AHBBUF_SIZE 0x800 /* 256 * 64bits */ +#define FSPI_TX_MAX_AHBBUF_SIZE 0x40 /* 8 * 64bits */ + +#define FSPI_LUTREG_OFFSET 0x200ul + +#define FSPI_MAX_TIMEOUT_AHBCMD 0xFFU +#define FSPI_MAX_TIMEOUT_IPCMD 0xFF +#define FSPI_SER_CLK_DIV 0x04 +#define FSPI_HSEN 0 +#define FSPI_ENDCFG_BE64 0x01 +#define FSPI_ENDCFG_BE32 0x03 +#define FSPI_ENDCFG_LE32 0x02 +#define FSPI_ENDCFG_LE64 0x0 + +#define MASK_24BIT_ADDRESS 0x00ffffff +#define MASK_32BIT_ADDRESS 0xffffffff + +/* Registers used by the driver */ +#define FSPI_MCR0 0x0ul +#define FSPI_MCR0_AHB_TIMEOUT(x) ((x) << 24) +#define FSPI_MCR0_IP_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR0_LEARN_EN BIT(15) +#define FSPI_MCR0_SCRFRUN_EN BIT(14) +#define FSPI_MCR0_OCTCOMB_EN BIT(13) +#define FSPI_MCR0_DOZE_EN BIT(12) +#define FSPI_MCR0_HSEN BIT(11) +#define FSPI_MCR0_SERCLKDIV BIT(8) +#define FSPI_MCR0_ATDF_EN BIT(7) +#define FSPI_MCR0_ARDF_EN BIT(6) +#define FSPI_MCR0_RXCLKSRC(x) ((x) << 4) +#define FSPI_MCR0_END_CFG(x) ((x) << 2) +#define FSPI_MCR0_MDIS BIT(1) +#define FSPI_MCR0_SWRST BIT(0) + +#define FSPI_MCR0_AHBGRANTWAIT_SHIFT 24 +#define FSPI_MCR0_AHBGRANTWAIT_MASK (0xFFU << FSPI_MCR0_AHBGRANTWAIT_SHIFT) +#define FSPI_MCR0_IPGRANTWAIT_SHIFT 16 +#define FSPI_MCR0_IPGRANTWAIT_MASK (0xFF << FSPI_MCR0_IPGRANTWAIT_SHIFT) +#define FSPI_MCR0_HSEN_SHIFT 11 +#define FSPI_MCR0_HSEN_MASK (1 << FSPI_MCR0_HSEN_SHIFT) +#define FSPI_MCR0_SERCLKDIV_SHIFT 8 +#define FSPI_MCR0_SERCLKDIV_MASK (7 << FSPI_MCR0_SERCLKDIV_SHIFT) +#define FSPI_MCR0_ENDCFG_SHIFT 2 +#define FSPI_MCR0_ENDCFG_MASK (3 << FSPI_MCR0_ENDCFG_SHIFT) +#define FSPI_MCR0_RXCLKSRC_SHIFT 4 +#define FSPI_MCR0_RXCLKSRC_MASK (3 << FSPI_MCR0_RXCLKSRC_SHIFT) + +#define FSPI_MCR1 0x04 +#define FSPI_MCR1_SEQ_TIMEOUT(x) ((x) << 16) +#define FSPI_MCR1_AHB_TIMEOUT(x) (x) + +#define FSPI_MCR2 0x08 +#define FSPI_MCR2_IDLE_WAIT(x) ((x) << 24) +#define FSPI_MCR2_SAMEDEVICEEN BIT(15) +#define FSPI_MCR2_CLRLRPHS BIT(14) +#define FSPI_MCR2_ABRDATSZ BIT(8) +#define FSPI_MCR2_ABRLEARN BIT(7) +#define FSPI_MCR2_ABR_READ BIT(6) +#define FSPI_MCR2_ABRWRITE BIT(5) +#define FSPI_MCR2_ABRDUMMY BIT(4) +#define FSPI_MCR2_ABR_MODE BIT(3) +#define FSPI_MCR2_ABRCADDR BIT(2) +#define FSPI_MCR2_ABRRADDR BIT(1) +#define FSPI_MCR2_ABR_CMD BIT(0) + +#define FSPI_AHBCR 0x0c +#define FSPI_AHBCR_RDADDROPT BIT(6) +#define FSPI_AHBCR_PREF_EN BIT(5) +#define FSPI_AHBCR_BUFF_EN BIT(4) +#define FSPI_AHBCR_CACH_EN BIT(3) +#define FSPI_AHBCR_CLRTXBUF BIT(2) +#define FSPI_AHBCR_CLRRXBUF BIT(1) +#define FSPI_AHBCR_PAR_EN BIT(0) + +#define FSPI_INTEN 0x10 +#define FSPI_INTEN_SCLKSBWR BIT(9) +#define FSPI_INTEN_SCLKSBRD BIT(8) +#define FSPI_INTEN_DATALRNFL BIT(7) +#define FSPI_INTEN_IPTXWE BIT(6) +#define FSPI_INTEN_IPRXWA BIT(5) +#define FSPI_INTEN_AHBCMDERR BIT(4) +#define FSPI_INTEN_IPCMDERR BIT(3) +#define FSPI_INTEN_AHBCMDGE BIT(2) +#define FSPI_INTEN_IPCMDGE BIT(1) +#define FSPI_INTEN_IPCMDDONE BIT(0) + +#define FSPI_INTR 0x14 +#define FSPI_INTR_SCLKSBWR BIT(9) +#define FSPI_INTR_SCLKSBRD BIT(8) +#define FSPI_INTR_DATALRNFL BIT(7) +#define FSPI_INTR_IPTXWE BIT(6) +#define FSPI_INTR_IPRXWA BIT(5) +#define FSPI_INTR_AHBCMDERR BIT(4) +#define FSPI_INTR_IPCMDERR BIT(3) +#define FSPI_INTR_AHBCMDGE BIT(2) +#define FSPI_INTR_IPCMDGE BIT(1) +#define FSPI_INTR_IPCMDDONE BIT(0) + +#define FSPI_LUTKEY 0x18 +#define FSPI_LUTKEY_VALUE 0x5AF05AF0 + +#define FSPI_LCKCR 0x1C + +#define FSPI_LCKER_LOCK 0x1 +#define FSPI_LCKER_UNLOCK 0x2 + +#define FSPI_BUFXCR_INVALID_MSTRID 0xE +#define FSPI_AHBRX_BUF0CR0 0x20 +#define FSPI_AHBRX_BUF1CR0 0x24 +#define FSPI_AHBRX_BUF2CR0 0x28 +#define FSPI_AHBRX_BUF3CR0 0x2C +#define FSPI_AHBRX_BUF4CR0 0x30 +#define FSPI_AHBRX_BUF5CR0 0x34 +#define FSPI_AHBRX_BUF6CR0 0x38 +#define FSPI_AHBRX_BUF7CR0 0x3C + +#define FSPI_AHBRXBUF0CR7_PREF BIT(31) + +#define FSPI_AHBRX_BUF0CR1 0x40 +#define FSPI_AHBRX_BUF1CR1 0x44 +#define FSPI_AHBRX_BUF2CR1 0x48 +#define FSPI_AHBRX_BUF3CR1 0x4C +#define FSPI_AHBRX_BUF4CR1 0x50 +#define FSPI_AHBRX_BUF5CR1 0x54 +#define FSPI_AHBRX_BUF6CR1 0x58 +#define FSPI_AHBRX_BUF7CR1 0x5C + +#define FSPI_FLSHA1CR0 0x60 +#define FSPI_FLSHA2CR0 0x64 +#define FSPI_FLSHB1CR0 0x68 +#define FSPI_FLSHB2CR0 0x6C +#define FSPI_FLSHXCR0_SZ_KB 10 +#define FSPI_FLSHXCR0_SZ(x) ((x) >> FSPI_FLSHXCR0_SZ_KB) + +#define FSPI_FLSHA1CR1 0x70 +#define FSPI_FLSHA2CR1 0x74 +#define FSPI_FLSHB1CR1 0x78 +#define FSPI_FLSHB2CR1 0x7C +#define FSPI_FLSHXCR1_CSINTR(x) ((x) << 16) +#define FSPI_FLSHXCR1_CAS(x) ((x) << 11) +#define FSPI_FLSHXCR1_WA BIT(10) +#define FSPI_FLSHXCR1_TCSH(x) ((x) << 5) +#define FSPI_FLSHXCR1_TCSS(x) (x) + +#define FSPI_FLSHXCR1_TCSH_SHIFT 5 +#define FSPI_FLSHXCR1_TCSH_MASK (0x1F << FSPI_FLSHXCR1_TCSH_SHIFT) +#define FSPI_FLSHXCR1_TCSS_SHIFT 0 +#define FSPI_FLSHXCR1_TCSS_MASK (0x1F << FSPI_FLSHXCR1_TCSS_SHIFT) + +#define FSPI_FLSHA1CR2 0x80 +#define FSPI_FLSHA2CR2 0x84 +#define FSPI_FLSHB1CR2 0x88 +#define FSPI_FLSHB2CR2 0x8C +#define FSPI_FLSHXCR2_CLRINSP BIT(24) +#define FSPI_FLSHXCR2_AWRWAIT BIT(16) +#define FSPI_FLSHXCR2_AWRSEQN_SHIFT 13 +#define FSPI_FLSHXCR2_AWRSEQI_SHIFT 8 +#define FSPI_FLSHXCR2_ARDSEQN_SHIFT 5 +#define FSPI_FLSHXCR2_ARDSEQI_SHIFT 0 + +#define FSPI_IPCR0 0xA0 + +#define FSPI_IPCR1 0xA4 +#define FSPI_IPCR1_IPAREN BIT(31) +#define FSPI_IPCR1_SEQNUM_SHIFT 24 +#define FSPI_IPCR1_SEQID_SHIFT 16 +#define FSPI_IPCR1_IDATSZ(x) (x) + +#define FSPI_IPCMD 0xB0 +#define FSPI_IPCMD_TRG BIT(0) + + +/* IP Command Register */ +#define FSPI_IPCMD_TRG_SHIFT 0 +#define FSPI_IPCMD_TRG_MASK (1 << FSPI_IPCMD_TRG_SHIFT) + +#define FSPI_INTR_IPRXWA_SHIFT 5 +#define FSPI_INTR_IPRXWA_MASK (1 << FSPI_INTR_IPRXWA_SHIFT) + +#define FSPI_INTR_IPCMDDONE_SHIFT 0 +#define FSPI_INTR_IPCMDDONE_MASK (1 << FSPI_INTR_IPCMDDONE_SHIFT) + +#define FSPI_INTR_IPTXWE_SHIFT 6 +#define FSPI_INTR_IPTXWE_MASK (1 << FSPI_INTR_IPTXWE_SHIFT) + +#define FSPI_IPTXFSTS_FILL_SHIFT 0 +#define FSPI_IPTXFSTS_FILL_MASK (0xFF << FSPI_IPTXFSTS_FILL_SHIFT) + +#define FSPI_IPCR1_ISEQID_SHIFT 16 +#define FSPI_IPCR1_ISEQID_MASK (0x1F << FSPI_IPCR1_ISEQID_SHIFT) + +#define FSPI_IPRXFSTS_FILL_SHIFT 0 +#define FSPI_IPRXFSTS_FILL_MASK (0xFF << FSPI_IPRXFSTS_FILL_SHIFT) + +#define FSPI_DLPR 0xB4 + +#define FSPI_IPRXFCR 0xB8 +#define FSPI_IPRXFCR_CLR BIT(0) +#define FSPI_IPRXFCR_DMA_EN BIT(1) +#define FSPI_IPRXFCR_WMRK(x) ((x) << 2) + +#define FSPI_IPTXFCR 0xBC +#define FSPI_IPTXFCR_CLR BIT(0) +#define FSPI_IPTXFCR_DMA_EN BIT(1) +#define FSPI_IPTXFCR_WMRK(x) ((x) << 2) + +#define FSPI_DLLACR 0xC0 +#define FSPI_DLLACR_OVRDEN BIT(8) + +#define FSPI_DLLBCR 0xC4 +#define FSPI_DLLBCR_OVRDEN BIT(8) + +#define FSPI_STS0 0xE0 +#define FSPI_STS0_DLPHB(x) ((x) << 8) +#define FSPI_STS0_DLPHA(x) ((x) << 4) +#define FSPI_STS0_CMD_SRC(x) ((x) << 2) +#define FSPI_STS0_ARB_IDLE BIT(1) +#define FSPI_STS0_SEQ_IDLE BIT(0) + +#define FSPI_STS1 0xE4 +#define FSPI_STS1_IP_ERRCD(x) ((x) << 24) +#define FSPI_STS1_IP_ERRID(x) ((x) << 16) +#define FSPI_STS1_AHB_ERRCD(x) ((x) << 8) +#define FSPI_STS1_AHB_ERRID(x) (x) + +#define FSPI_AHBSPNST 0xEC +#define FSPI_AHBSPNST_DATLFT(x) ((x) << 16) +#define FSPI_AHBSPNST_BUFID(x) ((x) << 1) +#define FSPI_AHBSPNST_ACTIVE BIT(0) + +#define FSPI_IPRXFSTS 0xF0 +#define FSPI_IPRXFSTS_RDCNTR(x) ((x) << 16) +#define FSPI_IPRXFSTS_FILL(x) (x) + +#define FSPI_IPTXFSTS 0xF4 +#define FSPI_IPTXFSTS_WRCNTR(x) ((x) << 16) +#define FSPI_IPTXFSTS_FILL(x) (x) + +#define FSPI_NOR_SR_WIP_SHIFT (0) +#define FSPI_NOR_SR_WIP_MASK (1 << FSPI_NOR_SR_WIP_SHIFT) + +#define FSPI_RFDR 0x100 +#define FSPI_TFDR 0x180 + +#define FSPI_LUT_BASE 0x200 +#define FSPI_LUT_OFFSET (SEQID_LUT * 4 * 4) +#define FSPI_LUT_REG(idx) \ + (FSPI_LUT_BASE + FSPI_LUT_OFFSET + (idx) * 4) + +/* register map end */ + +#endif diff --git a/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c b/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c new file mode 100644 index 0000000..c36c5b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c @@ -0,0 +1,91 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include "fspi.h" +#include + +/* + * The macros are defined to be used as test vector for testing fspi. + */ +#define SIZE_BUFFER 0x250 + +/* + * You may choose fspi_swap based on core endianness and flexspi IP/AHB + * buffer endianness set in MCR. + */ +#define fspi_swap32(A) (A) + +void fspi_test(uint32_t fspi_test_addr, uint32_t size, int extra) +{ + uint32_t buffer[SIZE_BUFFER]; + uint32_t count = 1; + uint32_t failed, i; + + NOTICE("-------------------------- %d----------------------------------\n", count++); + INFO("Sector Erase size: 0x%08x, size: %d\n", F_SECTOR_ERASE_SZ, size); + /* Test Sector Erase */ + xspi_sector_erase(fspi_test_addr - fspi_test_addr % F_SECTOR_ERASE_SZ, + F_SECTOR_ERASE_SZ); + + /* Test Erased data using IP read */ + xspi_ip_read((fspi_test_addr), buffer, size * 4); + + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0xffffffff) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success Erase: data in buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Erase: Failed -->xxx with buffer[%d]=0x%08x\n", i, buffer[i]); + } + + for (i = 0; i < SIZE_BUFFER; i++) + buffer[i] = 0x12345678; + + /* Write data from buffer to flash */ + xspi_write(fspi_test_addr, (void *)buffer, (size * 4 + extra)); + /* Check written data using IP read */ + xspi_ip_read(fspi_test_addr, buffer, (size * 4 + extra)); + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0x12345678) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success IpWrite with IP READ in buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Write: Failed -->xxxx with IP READ in buffer[%d]=0x%08x\n", i, buffer[i]); + return; + } + + /* xspi_read may use AHB read */ + xspi_read((fspi_test_addr), buffer, (size * 4 + extra)); + failed = 0; + for (i = 0; i < size; i++) + if (fspi_swap32(0x12345678) != buffer[i]) { + failed = 1; + break; + } + + if (failed == 0) { + NOTICE("[%d]: Success IpWrite with AHB OR IP READ on buffer[%d] 0x%08x\n", __LINE__, i-3, buffer[i-3]); + } else { + ERROR("Write: Failed -->xxxx with AHB READ on buffer[%d]=0x%08x\n", i, buffer[i]); + return; + } +} diff --git a/arm-trusted-firmware/drivers/nxp/gic/gic.mk b/arm-trusted-firmware/drivers/nxp/gic/gic.mk new file mode 100644 index 0000000..d75e071 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/gic.mk @@ -0,0 +1,46 @@ +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the GIC files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_GIC},) +ADD_GIC := 1 +ifeq ($(GIC), GIC400) +include drivers/arm/gic/v2/gicv2.mk +GIC_SOURCES += ${GICV2_SOURCES} +GIC_SOURCES += ${PLAT_DRIVERS_PATH}/gic/ls_gicv2.c \ + plat/common/plat_gicv2.c + +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv2 +else +ifeq ($(GIC), GIC500) +include drivers/arm/gic/v3/gicv3.mk +GIC_SOURCES += ${GICV3_SOURCES} +GIC_SOURCES += ${PLAT_DRIVERS_PATH}/gic/ls_gicv3.c \ + plat/common/plat_gicv3.c + +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/gic/gicv3 +else + $(error -> GIC type not set!) +endif +endif + +ifeq (${BL_COMM_GIC_NEEDED},yes) +BL_COMMON_SOURCES += ${GIC_SOURCES} +else +ifeq (${BL2_GIC_NEEDED},yes) +BL2_SOURCES += ${GIC_SOURCES} +endif +ifeq (${BL31_GIC_NEEDED},yes) +BL31_SOURCES += ${GIC_SOURCES} +endif +endif +endif + +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c new file mode 100644 index 0000000..62bc8db --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c @@ -0,0 +1,76 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + + +/* + * NXP common helper to initialize the GICv3 only driver. + */ +void plat_ls_gic_driver_init(uintptr_t nxp_gicd_addr, + uintptr_t nxp_gicc_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uint32_t *target_mask_array) +{ + static struct gicv2_driver_data ls_gic_data; + + ls_gic_data.gicd_base = nxp_gicd_addr; + ls_gic_data.gicc_base = nxp_gicc_addr; + ls_gic_data.target_masks = target_mask_array; + ls_gic_data.target_masks_num = plat_core_count; + ls_gic_data.interrupt_props = ls_interrupt_props; + ls_gic_data.interrupt_props_num = ls_interrupt_prop_count; + + gicv2_driver_init(&ls_gic_data); +} + +void plat_ls_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to enable the GICv2 CPU interface + *****************************************************************************/ +void plat_ls_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * ARM common helper to disable the GICv2 CPU interface + *****************************************************************************/ +void plat_ls_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +/****************************************************************************** + * NXP common helper to initialize GICv2 per cpu + *****************************************************************************/ +void plat_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +/****************************************************************************** + * Stubs for Redistributor power management. Although GICv2 doesn't have + * Redistributor interface, these are provided for the sake of uniform GIC API + *****************************************************************************/ +void plat_ls_gic_redistif_on(void) +{ +} + +void plat_ls_gic_redistif_off(void) +{ +} diff --git a/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c new file mode 100644 index 0000000..9c02bd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c @@ -0,0 +1,78 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +/* + * NXP common helper to initialize the GICv3 only driver. + */ +void plat_ls_gic_driver_init(uintptr_t nxp_gicd_addr, + uintptr_t nxp_gicr_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uintptr_t *target_mask_array, + mpidr_hash_fn mpidr_to_core_pos) +{ + static struct gicv3_driver_data ls_gic_data; + + ls_gic_data.gicd_base = nxp_gicd_addr; + ls_gic_data.gicr_base = nxp_gicr_addr; + ls_gic_data.interrupt_props = ls_interrupt_props; + ls_gic_data.interrupt_props_num = ls_interrupt_prop_count; + ls_gic_data.rdistif_num = plat_core_count; + ls_gic_data.rdistif_base_addrs = target_mask_array; + ls_gic_data.mpidr_to_core_pos = mpidr_to_core_pos; + + gicv3_driver_init(&ls_gic_data); +} + +void plat_ls_gic_init(void) +{ + gicv3_distif_init(); + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * NXP common helper to enable the GICv3 CPU interface + */ +void plat_ls_gic_cpuif_enable(void) +{ + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * NXP common helper to disable the GICv3 CPU interface + */ +void plat_ls_gic_cpuif_disable(void) +{ + gicv3_cpuif_disable(plat_my_core_pos()); +} + +/* + * NXP common helper to initialize the per cpu distributor interface in GICv3 + */ +void plat_gic_pcpu_init(void) +{ + gicv3_rdistif_init(plat_my_core_pos()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/* + * Stubs for Redistributor power management. Although GICv3 doesn't have + * Redistributor interface, these are provided for the sake of uniform GIC API + */ +void plat_ls_gic_redistif_on(void) +{ +} + +void plat_ls_gic_redistif_off(void) +{ +} diff --git a/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk b/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk new file mode 100644 index 0000000..74f0dc4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gpio/gpio.mk @@ -0,0 +1,28 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- + +ifeq (${GPIO_ADDED},) + +GPIO_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/gpio + +GPIO_SOURCES := $(PLAT_DRIVERS_PATH)/gpio/nxp_gpio.c + +ifeq (${BL_COMM_GPIO_NEEDED},yes) +BL_COMMON_SOURCES += ${GPIO_SOURCES} +else +ifeq (${BL2_GPIO_NEEDED},yes) +BL2_SOURCES += ${GPIO_SOURCES} +endif +ifeq (${BL31_GPIO_NEEDED},yes) +BL31_SOURCES += ${GPIO_SOURCES} +endif +endif + +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c b/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c new file mode 100644 index 0000000..28c9db9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c @@ -0,0 +1,144 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +static gpio_init_info_t *gpio_init_info; + +void gpio_init(gpio_init_info_t *gpio_init_data) +{ + gpio_init_info = gpio_init_data; +} + +/* This function set GPIO pin for raising POVDD. */ +int set_gpio_bit(uint32_t *gpio_base_addr, + uint32_t bit_num) +{ + uint32_t val = 0U; + uint32_t *gpdir = NULL; + uint32_t *gpdat = NULL; + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + return GPIO_FAILURE; + } + + gpdir = gpio_base_addr + GPDIR_REG_OFFSET; + gpdat = gpio_base_addr + (GPDAT_REG_OFFSET >> 2); + + /* + * Set the corresponding bit in direction register + * to configure the GPIO as output. + */ + val = gpio_read32(gpdir); + val = val | bit_num; + gpio_write32(gpdir, val); + + /* Set the corresponding bit in GPIO data register */ + val = gpio_read32(gpdat); + val = val | bit_num; + gpio_write32(gpdat, val); + + val = gpio_read32(gpdat); + + if ((val & bit_num) == 0U) { + return GPIO_FAILURE; + } + + return GPIO_SUCCESS; +} + +/* This function reset GPIO pin set for raising POVDD. */ +int clr_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num) +{ + uint32_t val = 0U; + uint32_t *gpdir = NULL; + uint32_t *gpdat = NULL; + + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + return GPIO_FAILURE; + } + + gpdir = gpio_base_addr + GPDIR_REG_OFFSET; + gpdat = gpio_base_addr + GPDAT_REG_OFFSET; + + /* + * Reset the corresponding bit in direction and data register + * to configure the GPIO as input. + */ + val = gpio_read32(gpdat); + val = val & ~(bit_num); + gpio_write32(gpdat, val); + + val = gpio_read32(gpdat); + + val = gpio_read32(gpdir); + val = val & ~(bit_num); + gpio_write32(gpdir, val); + + val = gpio_read32(gpdat); + + if ((val & bit_num) != 0U) { + return GPIO_FAILURE; + } + + return GPIO_SUCCESS; +} + +uint32_t *select_gpio_n_bitnum(uint32_t povdd_gpio, uint32_t *bit_num) +{ + uint32_t *ret_gpio; + uint32_t povdd_gpio_val = 0U; + uint32_t gpio_num = 0U; + + if (gpio_init_info == NULL) { + ERROR("GPIO is not initialized.\n"); + } + /* + * Subtract 1 from fuse_hdr povdd_gpio value as + * for 0x1 value, bit 0 is to be set + * for 0x20 value i.e 32, bit 31 i.e. 0x1f is to be set. + * 0x1f - 0x00 : GPIO_1 + * 0x3f - 0x20 : GPIO_2 + * 0x5f - 0x40 : GPIO_3 + * 0x7f - 0x60 : GPIO_4 + */ + povdd_gpio_val = (povdd_gpio - 1U) & GPIO_SEL_MASK; + + /* Right shift by 5 to divide by 32 */ + gpio_num = povdd_gpio_val >> GPIO_ID_BASE_ADDR_SHIFT; + *bit_num = 1U << (GPIO_BITS_PER_BASE_REG + - (povdd_gpio_val & GPIO_BIT_MASK) + - 1U); + + switch (gpio_num) { + case GPIO_0: + ret_gpio = (uint32_t *) gpio_init_info->gpio1_base_addr; + break; + case GPIO_1: + ret_gpio = (uint32_t *) gpio_init_info->gpio2_base_addr; + break; + case GPIO_2: + ret_gpio = (uint32_t *) gpio_init_info->gpio3_base_addr; + break; + case GPIO_3: + ret_gpio = (uint32_t *) gpio_init_info->gpio4_base_addr; + break; + default: + ret_gpio = NULL; + } + + if (ret_gpio == NULL) { + INFO("GPIO_NUM = %d doesn't exist.\n", gpio_num); + } + + return ret_gpio; +} diff --git a/arm-trusted-firmware/drivers/nxp/i2c/i2c.c b/arm-trusted-firmware/drivers/nxp/i2c/i2c.c new file mode 100644 index 0000000..9281409 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/i2c/i2c.c @@ -0,0 +1,257 @@ +/* + * Copyright 2016-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include "i2c.h" +#include + +static uintptr_t g_nxp_i2c_addr; + +void i2c_init(uintptr_t nxp_i2c_addr) +{ + struct ls_i2c *ccsr_i2c = (void *)nxp_i2c_addr; + + g_nxp_i2c_addr = nxp_i2c_addr; + /* Presume workaround for erratum a009203 applied */ + i2c_out(&ccsr_i2c->cr, I2C_CR_DIS); + i2c_out(&ccsr_i2c->fd, I2C_FD_CONSERV); + i2c_out(&ccsr_i2c->sr, I2C_SR_RST); + i2c_out(&ccsr_i2c->cr, I2C_CR_EN); +} + +static int wait_for_state(struct ls_i2c *ccsr_i2c, + unsigned char state, unsigned char mask) +{ + unsigned char sr; + uint64_t start_time = get_timer_val(0); + uint64_t timer; + + do { + sr = i2c_in(&ccsr_i2c->sr); + if (sr & I2C_SR_AL) { + i2c_out(&ccsr_i2c->sr, sr); + WARN("I2C arbitration lost\n"); + return -EIO; + } + if ((sr & mask) == state) { + return (int)sr; + } + + timer = get_timer_val(start_time); + if (timer > I2C_TIMEOUT) + break; + mdelay(1); + } while (1); + WARN("I2C: Timeout waiting for state 0x%x, sr = 0x%x\n", state, sr); + + return -ETIMEDOUT; +} + +static int tx_byte(struct ls_i2c *ccsr_i2c, unsigned char c) +{ + int ret; + + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + i2c_out(&ccsr_i2c->dr, c); + ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); + if (ret < 0) { + WARN("%s: state error\n", __func__); + return ret; + } + if (ret & I2C_SR_RX_NAK) { + WARN("%s: nodev\n", __func__); + return -ENODEV; + } + + return 0; +} + +static int gen_stop(struct ls_i2c *ccsr_i2c) +{ + unsigned char cr; + int ret; + + cr = i2c_in(&ccsr_i2c->cr); + cr &= ~(I2C_CR_MA | I2C_CR_TX); + i2c_out(&ccsr_i2c->cr, cr); + ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); + if (ret < 0) { + WARN("I2C: Generating stop failed.\n"); + } + return ret; +} + +static int i2c_write_addr(struct ls_i2c *ccsr_i2c, unsigned char chip, + int addr, int alen) +{ + int ret; + unsigned char cr; + + if (alen != 1) { + WARN("I2C: Unsupported address len [%d]\n", alen); + return -EIO; + } + + if (i2c_in(&ccsr_i2c->ad) == (chip << 1)) { + WARN("I2C: slave address same as self\n"); + return -ENODEV; + } + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + ret = wait_for_state(ccsr_i2c, I2C_SR_IDLE, I2C_SR_BB); + if (ret < 0) { + return ret; + } + + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_MA; + i2c_out(&ccsr_i2c->cr, cr); + ret = wait_for_state(ccsr_i2c, I2C_SR_BB, I2C_SR_BB); + if (ret < 0) { + return ret; + } + + VERBOSE("Before writing chip %d\n", chip); + cr |= I2C_CR_TX | I2C_CR_TX_NAK; + i2c_out(&ccsr_i2c->cr, cr); + ret = tx_byte(ccsr_i2c, chip << 1); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + VERBOSE("Before writing addr\n"); + while (alen--) { + ret = tx_byte(ccsr_i2c, (addr >> (alen << 3)) & 0xff); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + } + + return 0; +} + +static int read_data(struct ls_i2c *ccsr_i2c, unsigned char chip, + unsigned char *buf, int len) +{ + int i; + int ret; + unsigned char cr; + + cr = i2c_in(&ccsr_i2c->cr); + cr &= ~(I2C_CR_TX | I2C_CR_TX_NAK); + if (len == 1) { + cr |= I2C_CR_TX_NAK; + } + i2c_out(&ccsr_i2c->cr, cr); + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + i2c_in(&ccsr_i2c->dr); /* dummy read */ + for (i = 0; i < len; i++) { + ret = wait_for_state(ccsr_i2c, I2C_SR_IF, I2C_SR_IF); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + if (i == (len - 1)) { + gen_stop(ccsr_i2c); + } else if (i == (len - 2)) { + /* Updating the command to send + * No ACK. + */ + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_TX_NAK; + i2c_out(&ccsr_i2c->cr, cr); + } + i2c_out(&ccsr_i2c->sr, I2C_SR_IF); + buf[i] = i2c_in(&ccsr_i2c->dr); + } + + return 0; +} + +static int write_data(struct ls_i2c *ccsr_i2c, unsigned char chip, + const unsigned char *buf, int len) +{ + int i; + int ret; + + for (i = 0; i < len; i++) { + ret = tx_byte(ccsr_i2c, buf[i]); + if (ret < 0) { + break; + } + } + ret = gen_stop(ccsr_i2c); + + return ret; +} + + +int i2c_read(unsigned char chip, int addr, int alen, + unsigned char *buf, int len) +{ + int ret; + unsigned char cr; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + cr = i2c_in(&ccsr_i2c->cr); + cr |= I2C_CR_RSTA; + i2c_out(&ccsr_i2c->cr, cr); + + ret = tx_byte(ccsr_i2c, (chip << 1) | 1); + if (ret < 0) { + gen_stop(ccsr_i2c); + return ret; + } + + return read_data(ccsr_i2c, chip, buf, len); +} + +int i2c_write(unsigned char chip, int addr, int alen, + const unsigned char *buf, int len) +{ + int ret; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, addr, alen); + if (ret < 0) { + return ret; + } + + return write_data(ccsr_i2c, chip, buf, len); +} + +int i2c_probe_chip(unsigned char chip) +{ + int ret; + struct ls_i2c *ccsr_i2c = (void *)g_nxp_i2c_addr; + + ret = i2c_write_addr(ccsr_i2c, chip, 0, 0); + if (ret < 0) { + WARN("write addr failed\n"); + return ret; + } + + ret = gen_stop(ccsr_i2c); + if (ret < 0) { + WARN("I2C: Probe not complete.\n"); + } + + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk b/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk new file mode 100644 index 0000000..716e14a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/i2c/i2c.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_I2C},) + +ADD_I2C := 1 + +I2C_SOURCES += $(PLAT_DRIVERS_PATH)/i2c/i2c.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/i2c + +ifeq (${BL_COMM_I2C_NEEDED},yes) +BL_COMMON_SOURCES += ${I2C_SOURCES} +else +ifeq (${BL2_I2C_NEEDED},yes) +BL2_SOURCES += ${I2C_SOURCES} +endif +ifeq (${BL31_I2C_NEEDED},yes) +BL31_SOURCES += ${I2C_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h new file mode 100644 index 0000000..56c5f92 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h @@ -0,0 +1,329 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IFC_H +#define IFC_H + +#include + +#include + +#define NXP_IFC_RUN_TIME_ADDR U(0x1000) + +/* CPSR - Chip Select Property Register Offset */ +#define EXT_CSPR(n) (U(0x000C) + (n * 0xC)) +#define CSPR(n) (U(0x0010) + (n * 0xC)) +#define CSOR(n) (U(0x0130) + (n * 0xC)) +#define EXT_CSOR(n) (U(0x0134) + (n * 0xC)) +#define IFC_AMASK_CS0 U(0x00A0) + +/* NAND specific Registers Offset */ +#define NCFGR (NXP_IFC_RUN_TIME_ADDR + U(0x0000)) +#define NAND_FCR0 (NXP_IFC_RUN_TIME_ADDR + U(0x0014)) + +#define ROW0 (NXP_IFC_RUN_TIME_ADDR + U(0x003C)) +#define ROW1 (NXP_IFC_RUN_TIME_ADDR + U(0x004C)) +#define COL0 (NXP_IFC_RUN_TIME_ADDR + U(0x0044)) +#define COL1 (NXP_IFC_RUN_TIME_ADDR + U(0x0054)) + +#define NAND_BC (NXP_IFC_RUN_TIME_ADDR + U(0x0108)) +#define NAND_FIR0 (NXP_IFC_RUN_TIME_ADDR + U(0x0110)) +#define NAND_FIR1 (NXP_IFC_RUN_TIME_ADDR + U(0x0114)) +#define NAND_FIR2 (NXP_IFC_RUN_TIME_ADDR + U(0x0118)) +#define NAND_CSEL (NXP_IFC_RUN_TIME_ADDR + U(0x015C)) +#define NANDSEQ_STRT (NXP_IFC_RUN_TIME_ADDR + U(0x0164)) +#define NAND_EVTER_STAT (NXP_IFC_RUN_TIME_ADDR + U(0x016C)) +#define NAND_AUTOBOOT_TRGR (NXP_IFC_RUN_TIME_ADDR + U(0x0284)) + +/* Size of SRAM Buffer */ +#define CSPR_PS U(0x00000180) +#define CSPR_PS_SHIFT 7 +#define CSPR_PS_8 0x1 // Port Size 8 bit +#define CSPR_PS_16 0x2 // Port Size 16 bit +#define CSPR_PS_32 0x3 // Port Size 32 bit + +/* Chip Select Option Register NAND Machine */ +#define CSOR_NAND_PGS U(0x00380000) +#define CSOR_NAND_PGS_SHIFT 19 +#define CSOR_NAND_PGS_512 U(0x00000000) +#define CSOR_NAND_PGS_2K U(0x00080000) +#define CSOR_NAND_PGS_4K U(0x00100000) +#define CSOR_NAND_PGS_8K U(0x00180000) +#define CSOR_NAND_PGS_16K U(0x00200000) + + +#define CSOR_NAND_PB U(0x00000700) +#define CSOR_NAND_PB_32 U(0x00000000) +#define CSOR_NAND_PB_64 U(0x00000100) +#define CSOR_NAND_PB_128 U(0x00000200) +#define CSOR_NAND_PB_256 U(0x00000300) +#define CSOR_NAND_PB_512 U(0x00000400) +#define CSOR_NAND_PB_1024 U(0x00000500) +#define CSOR_NAND_PB_2048 U(0x00000600) +#define CSOR_NAND_PPB_32 32 +#define CSOR_NAND_PPB_64 64 +#define CSOR_NAND_PPB_128 128 +#define CSOR_NAND_PPB_256 256 +#define CSOR_NAND_PPB_512 512 +#define CSOR_NAND_PPB_1024 1024 +#define CSOR_NAND_PPB_2048 2048 + +/* NAND Chip select register */ +#define NAND_CSEL_SHIFT 26 +#define NAND_COL_MS_SHIFT 31 + +/* FCR - Flash Command Register */ +#define FCR_CMD0 U(0xFF000000) +#define FCR_CMD0_SHIFT 24 +#define FCR_CMD1 U(0x00FF0000) +#define FCR_CMD1_SHIFT 16 +#define FCR_CMD2 U(0x0000FF00) +#define FCR_CMD2_SHIFT 8 +#define FCR_CMD3 U(0x000000FF) +#define FCR_CMD3_SHIFT 0 + +/* FIR - Flash Instruction Register Opcode */ +#define FIR_OP0 U(0xFC000000) +#define FIR_OP0_SHIFT 26 +#define FIR_OP1 U(0x03F00000) +#define FIR_OP1_SHIFT 20 +#define FIR_OP2 U(0x000FC000) +#define FIR_OP2_SHIFT 14 +#define FIR_OP3 U(0x00003F00) +#define FIR_OP3_SHIFT 8 +#define FIR_OP4 U(0x000000FC) +#define FIR_OP4_SHIFT 2 +#define FIR_OP5 U(0xFC000000) +#define FIR_OP5_SHIFT 26 +#define FIR_OP6 U(0x03F00000) +#define FIR_OP6_SHIFT 20 + +/* Instruction Opcode - 6 bits */ +#define FIR_OP_NOP 0x00 +#define FIR_OP_CA0 0x01 /* Issue current column address */ +#define FIR_OP_CA1 0x02 /* Issue current column address */ +#define FIR_OP_RA0 0x05 /* Issue current column address */ +#define FIR_OP_RA1 0x06 /* Issue current column address */ +#define FIR_OP_CMD0 0x09 /* Issue command from FCR[CMD0] */ +#define FIR_OP_CMD1 0x0a /* Issue command from FCR[CMD1] */ +#define FIR_OP_CMD2 0x0b /* Issue command from FCR[CMD2] */ +#define FIR_OP_CMD3 0x0c /* Issue command from FCR[CMD3] */ +#define FIR_OP_CW0 0x11 /* Wait then issue FCR[CMD0] */ +#define FIR_OP_CW1 0x12 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_CW2 0x13 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_CW3 0x14 /* Wait then issue FCR[CMD1] */ +#define FIR_OP_WBCD 0x19 /* Wait then read FBCR bytes */ +#define FIR_OP_RBCD 0x1a /* Wait then read 1 or 2 bytes */ +#define FIR_OP_BTRD 0x1b /* Wait then read 1 or 2 bytes */ +#define FIR_OP_RDSTAT 0x1c /* Wait then read 1 or 2 bytes */ +#define FIR_OP_NWAIT 0x1d /* Wait then read 1 or 2 bytes */ +#define FIR_OP_WFR 0x1e /* Wait then read 1 or 2 bytes */ + +#define NAND_SEQ_STRT_FIR_STRT U(0x80000000) +#define NAND_SEQ_STRT_FIR_STRT_SHIFT 31 + +#define NAND_EVTER_STAT_FTOER U(0x08000000) +#define NAND_EVTER_STAT_WPER U(0x04000000) +#define NAND_EVTER_STAT_ECCER U(0x02000000) +#define NAND_EVTER_STAT_DQSER U(0x01000000) +#define NAND_EVTER_STAT_RCW_DN U(0x00008000) +#define NAND_EVTER_STAT_BOOT_DN U(0x00004000) +#define NAND_EVTER_STAT_RCW_DN U(0x00008000) +#define NAND_EVTER_STAT_OPC_DN U(0x80000000) +#define NAND_EVTER_STAT_BBI_SRCH_SEL U(0x00000800) +#define NCFGR_BOOT U(0x80000000) +#define NAND_AUTOBOOT_TRGR_RCW_LD U(0x80000000) +#define NAND_AUTOBOOT_TRGR_BOOT_LD U(0x20000000) + +/* ECC ERROR STATUS Registers */ +#define NAND_RCW_LD U(0x80000000) +#define NAND_BOOT_LD U(0x20000000) + +/*Other Temp Defines */ +/*256 bad Blocks supported */ +#define BBT_SIZE 256 + +/*Standard NAND flash commands */ +#define NAND_CMD_READ0 0 +#define NAND_CMD_READ1 1 +#define NAND_CMD_READOOB 0x50 + +/*Extended commands for large page devices */ +#define NAND_CMD_READSTART 0x30 + +#define NAND_TIMEOUT_MS 40 + +#define EMPTY_VAL_CHECK U(0xFFFFFFFF) +#define EMPTY_VAL 0xFF + + +#define MAIN 0 +#define SPARE 1 + +#define GOOD_BLK 1 +#define BAD_BLK 0 +#define DIV_2 2 + +#define ATTRIBUTE_PGSZ 0xa +#define ATTRIBUTE_PPB 0xb + +#define CSPR_PORT_SIZE_8 (0x1 << 7) +#define CSPR_PORT_SIZE_16 (0x2 << 7) +#define CSPR_PORT_SIZE_32 (0x3 << 7) + +/* NAND specific */ +#define RCW_SRC_NAND_PORT_MASK U(0x00000080) + +#define NAND_DEFAULT_CSPR U(0x00000053) +#define NAND_DEFAULT_CSOR U(0x0180C00C) +#define NAND_DEFAULT_EXT_CSPR U(0x00000000) +#define NAND_DEFAULT_EXT_CSOR U(0x00000000) +#define NAND_DEFAULT_FTIM0 U(0x181c0c10) +#define NAND_DEFAULT_FTIM1 U(0x5454141e) +#define NAND_DEFAULT_FTIM2 U(0x03808034) +#define NAND_DEFAULT_FTIM3 U(0x2c000000) + +#define NAND_CSOR_ECC_MODE_DISABLE U(0x00000000) +#define NAND_CSOR_ECC_MODE0 U(0x84000000) +#define NAND_CSOR_ECC_MODE1 U(0x94000000) +#define NAND_CSOR_ECC_MODE2 U(0xa4000000) +#define NAND_CSOR_ECC_MODE3 U(0xb4000000) +#define NAND_CSOR_PAGE_SIZE_2K (0x1 << 19) +#define NAND_CSOR_PAGE_SIZE_4K (0x2 << 19) +#define NAND_CSOR_PAGE_SIZE_8K (0x3 << 19) +#define NAND_CSOR_PAGE_SIZE_16K (0x4 << 19) +#define NAND_CSOR_PPB_64 (0x1 << 8) +#define NAND_CSOR_PPB_128 (0x2 << 8) +#define NAND_CSOR_PPB_256 (0x3 << 8) +#define NAND_CSOR_PPB_512 (0x4 << 8) + +/* BBI INDICATOR for NAND_2K(CFG_RCW_SRC[1]) for + * devices greater than 2K page size(CFG_RCW_SRC[3]) + */ +#define RCW_SRC_NAND_BBI_MASK U(0x00000008) +#define RCW_SRC_NAND_BBI_MASK_NAND_2K U(0x00000002) +#define NAND_BBI_ONFI_2K (0x1 << 1) +#define NAND_BBI_ONFI (0x1 << 3) + +#define RCW_SRC_NAND_PAGE_MASK U(0x00000070) +#define RCW_SRC_NAND_PAGE_MASK_NAND_2K U(0x0000000C) +#define NAND_2K_XXX 0x00 +#define NAND_2K_64 0x04 +#define NAND_2K_128 0x08 +#define NAND_4K_128 0x10 +#define NAND_4K_256 0x20 +#define NAND_4K_512 0x30 +#define NAND_8K_128 0x40 +#define NAND_8K_256 0x50 +#define NAND_8K_512 0x60 +#define NAND_16K_512 0x70 +#define BLOCK_LEN_2K 2048 + +#define RCW_SRC_NAND_ECC_MASK U(0x00000007) +#define RCW_SRC_NAND_ECC_MASK_NAND_2K U(0x00000001) +#define NAND_ECC_DISABLE 0x0 +#define NAND_ECC_4_520 0x1 +#define NAND_ECC_8_528 0x5 +#define NAND_ECC_24_1K 0x6 +#define NAND_ECC_40_1K 0x7 + +#define NAND_SPARE_2K U(0x00000040) +#define NAND_SPARE_4K_ECC_M0 U(0x00000080) +#define NAND_SPARE_4K_ECC_M1 U(0x000000D2) +#define NAND_SPARE_4K_ECC_M2 U(0x000000B0) +#define NAND_SPARE_4K_ECC_M3 U(0x00000120) +#define NAND_SPARE_8K_ECC_M0 U(0x00000088) +#define NAND_SPARE_8K_ECC_M1 U(0x00000108) +#define NAND_SPARE_8K_ECC_M2 U(0x00000158) +#define NAND_SPARE_8K_ECC_M3 U(0x00000238) +#define NAND_SPARE_16K_ECC_M0 U(0x00000108) +#define NAND_SPARE_16K_ECC_M1 U(0x00000208) +#define NAND_SPARE_16K_ECC_M2 U(0x000002A8) +#define NAND_SPARE_16K_ECC_M3 U(0x00000468) + +struct nand_info { + uintptr_t ifc_register_addr; + uintptr_t ifc_region_addr; + uint32_t page_size; + uint32_t port_size; + uint32_t blk_size; + uint32_t ppb; + uint32_t pi_width; /* Bits Required to index a page in block */ + uint32_t ral; + uint32_t ibr_flow; + uint32_t bbt[BBT_SIZE]; + uint32_t lgb; /* Last Good Block */ + uint32_t bbt_max; /* Total entries in bbt */ + uint32_t bzero_good; + uint8_t bbs; + uint8_t bad_marker_loc; + uint8_t onfi_dev_flag; + uint8_t init_time_boot_flag; + uint8_t *buf; +}; + +struct ifc_regs { + uint32_t ext_cspr; + uint32_t cspr; + uint32_t csor; + uint32_t ext_csor; +}; + +struct sec_nand_info { + uint32_t cspr_port_size; + uint32_t csor_ecc_mode; + uint32_t csor_page_size; + uint32_t csor_ppb; + uint32_t ext_csor_spare_size; + uint32_t onfi_flag; +}; + +struct sec_nor_info { + uint32_t cspr_port_size; + uint32_t csor_nor_mode; + uint32_t csor_adm_shift; + uint32_t port_size; + uint32_t addr_bits; +}; + +enum ifc_chip_sel { + IFC_CS0, + IFC_CS1, + IFC_CS2, + IFC_CS3, + IFC_CS4, + IFC_CS5, + IFC_CS6, + IFC_CS7, +}; + +enum ifc_ftims { + IFC_FTIM0, + IFC_FTIM1, + IFC_FTIM2, + IFC_FTIM3, +}; + +#ifdef NXP_IFC_BE +#define nand_in32(a) bswap32(mmio_read_32((uintptr_t)a)) +#define nand_out32(a, v) mmio_write_32((uintptr_t)a, bswap32(v)) +#else +#define nand_in32(a) mmio_read_32((uintptr_t)a) +#define nand_out32(a, v) mmio_write_32((uintptr_t)a, v) +#endif + +/* Read Write on IFC registers */ +static inline void write_reg(struct nand_info *nand, uint32_t reg, uint32_t val) +{ + nand_out32(nand->ifc_register_addr + reg, val); +} + +static inline uint32_t read_reg(struct nand_info *nand, uint32_t reg) +{ + return nand_in32(nand->ifc_register_addr + reg); +} + +#endif /* IFC_H */ diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c new file mode 100644 index 0000000..1f7092a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c @@ -0,0 +1,658 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include "ifc.h" +#include +#include + +/* Private structure for NAND driver data */ +static struct nand_info nand_drv_data; + +static int update_bbt(uint32_t idx, uint32_t blk, uint32_t *updated, + struct nand_info *nand); + +static int nand_wait(struct nand_info *nand) +{ + int timeout = 1; + uint32_t neesr; + unsigned long start_time; + + start_time = get_timer_val(0); + + while (get_timer_val(start_time) < NAND_TIMEOUT_MS) { + /* clear the OPC event */ + neesr = read_reg(nand, NAND_EVTER_STAT); + if (neesr & NAND_EVTER_STAT_OPC_DN) { + write_reg(nand, NAND_EVTER_STAT, neesr); + timeout = 0; + + /* check for other errors */ + if (neesr & NAND_EVTER_STAT_FTOER) { + ERROR("%s NAND_EVTER_STAT_FTOER occurs\n", + __func__); + return -1; + } else if (neesr & NAND_EVTER_STAT_ECCER) { + ERROR("%s NAND_EVTER_STAT_ECCER occurs\n", + __func__); + return -1; + } else if (neesr & NAND_EVTER_STAT_DQSER) { + ERROR("%s NAND_EVTER_STAT_DQSER occurs\n", + __func__); + return -1; + } + + break; + } + } + + if (timeout) { + ERROR("%s ERROR_NAND_TIMEOUT occurs\n", __func__); + return -1; + } + + return 0; +} + +static uint32_t nand_get_port_size(struct nand_info *nand) +{ + uint32_t port_size = U(0); + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = U(0); + cs_reg = CSPR(cur_cs); + port_size = (read_reg(nand, cs_reg) & CSPR_PS) >> CSPR_PS_SHIFT; + switch (port_size) { + case CSPR_PS_8: + port_size = U(8); + break; + case CSPR_PS_16: + port_size = U(16); + break; + case CSPR_PS_32: + port_size = U(32); + break; + default: + port_size = U(8); + } + + return port_size; +} + +static uint32_t nand_get_page_size(struct nand_info *nand) +{ + uint32_t pg_size; + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = 0; + cs_reg = CSOR(cur_cs); + pg_size = read_reg(nand, cs_reg) & CSOR_NAND_PGS; + switch (pg_size) { + case CSOR_NAND_PGS_2K: + pg_size = U(2048); + break; + case CSOR_NAND_PGS_4K: + pg_size = U(4096); + break; + case CSOR_NAND_PGS_8K: + pg_size = U(8192); + break; + case CSOR_NAND_PGS_16K: + pg_size = U(16384); + break; + default: + pg_size = U(512); + } + + return pg_size; +} + +static uint32_t nand_get_pages_per_blk(struct nand_info *nand) +{ + uint32_t pages_per_blk; + uint32_t cs_reg; + uint32_t cur_cs; + + cur_cs = 0; + cs_reg = CSOR(cur_cs); + pages_per_blk = (read_reg(nand, cs_reg) & CSOR_NAND_PB); + switch (pages_per_blk) { + case CSOR_NAND_PB_32: + pages_per_blk = U(32); + break; + case CSOR_NAND_PB_64: + pages_per_blk = U(64); + break; + case CSOR_NAND_PB_128: + pages_per_blk = U(128); + break; + case CSOR_NAND_PB_256: + pages_per_blk = U(256); + break; + case CSOR_NAND_PB_512: + pages_per_blk = U(512); + break; + case CSOR_NAND_PB_1024: + pages_per_blk = U(1024); + break; + case CSOR_NAND_PB_2048: + pages_per_blk = U(2048); + break; + default: + pages_per_blk = U(0); + } + + return pages_per_blk; +} + +static uint32_t get_page_index_width(uint32_t ppb) +{ + switch (ppb) { + case CSOR_NAND_PPB_32: + return U(5); + case CSOR_NAND_PPB_64: + return U(6); + case CSOR_NAND_PPB_128: + return U(7); + case CSOR_NAND_PPB_256: + return U(8); + case CSOR_NAND_PPB_512: + return U(9); + case CSOR_NAND_PPB_1024: + return U(10); + case CSOR_NAND_PPB_2048: + return U(11); + default: + return U(5); + } +} + +static void nand_get_params(struct nand_info *nand) +{ + nand->port_size = nand_get_port_size(nand); + + nand->page_size = nand_get_page_size(nand); + + /* + * Set Bad marker Location for LP / SP + * Small Page : 8 Bit : 0x5 + * Small Page : 16 Bit : 0xa + * Large Page : 8 /16 Bit : 0x0 + */ + nand->bad_marker_loc = (nand->page_size == 512) ? + ((nand->port_size == 8) ? 0x5 : 0xa) : 0; + + /* check for the device is ONFI compliant or not */ + nand->onfi_dev_flag = + (read_reg(nand, NAND_EVTER_STAT) & NAND_EVTER_STAT_BBI_SRCH_SEL) + ? 1 : 0; + + /* NAND Blk serached count for incremental Bad block search cnt */ + nand->bbs = 0; + + /* pages per Block */ + nand->ppb = nand_get_pages_per_blk(nand); + + /* Blk size */ + nand->blk_size = nand->page_size * nand->ppb; + + /* get_page_index_width */ + nand->pi_width = get_page_index_width(nand->ppb); + + /* bad block table init */ + nand->lgb = 0; + nand->bbt_max = 0; + nand->bzero_good = 0; + memset(nand->bbt, EMPTY_VAL, BBT_SIZE * sizeof(nand->bbt[0])); +} + +static int nand_init(struct nand_info *nand) +{ + uint32_t ncfgr = 0; + + /* Get nand Parameters from IFC */ + nand_get_params(nand); + + /* Clear all errors */ + write_reg(nand, NAND_EVTER_STAT, U(0xffffffff)); + + /* + * Disable autoboot in NCFGR. Mapping will change from + * physical to logical for SRAM buffer + */ + ncfgr = read_reg(nand, NCFGR); + write_reg(nand, NCFGR, (ncfgr & ~NCFGR_BOOT)); + + return 0; +} + +static int nand_read_data( + uintptr_t ifc_region_addr, + uint32_t row_add, + uint32_t col_add, + uint32_t byte_cnt, + uint8_t *data, + uint32_t main_spare, + struct nand_info *nand) +{ + uint32_t page_size_add_bits = U(0); + uint32_t page_add_in_actual, page_add; + uintptr_t sram_addr_calc; + int ret; + uint32_t col_val; + + /* Programming MS bit to read from spare area.*/ + col_val = (main_spare << NAND_COL_MS_SHIFT) | col_add; + + write_reg(nand, NAND_BC, byte_cnt); + + write_reg(nand, ROW0, row_add); + write_reg(nand, COL0, col_val); + + /* Program FCR for small Page */ + if (nand->page_size == U(512)) { + if (byte_cnt == 0 || + (byte_cnt != 0 && main_spare == 0 && col_add <= 255)) { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READ0 << FCR_CMD0_SHIFT)); + } else if (main_spare == 0) { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READ1 << FCR_CMD0_SHIFT)); + } else { + write_reg(nand, NAND_FCR0, + (NAND_CMD_READOOB << FCR_CMD0_SHIFT)); + } + + } else { + /* Program FCR for Large Page */ + write_reg(nand, NAND_FCR0, (NAND_CMD_READ0 << FCR_CMD0_SHIFT) | + (NAND_CMD_READSTART << FCR_CMD1_SHIFT)); + } + if (nand->page_size == U(512)) { + write_reg(nand, NAND_FIR0, ((FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA0 << FIR_OP1_SHIFT) | + (FIR_OP_RA0 << FIR_OP2_SHIFT) | + (FIR_OP_BTRD << FIR_OP3_SHIFT) | + (FIR_OP_NOP << FIR_OP4_SHIFT))); + write_reg(nand, NAND_FIR1, U(0x00000000)); + } else { + write_reg(nand, NAND_FIR0, ((FIR_OP_CW0 << FIR_OP0_SHIFT) | + (FIR_OP_CA0 << FIR_OP1_SHIFT) | + (FIR_OP_RA0 << FIR_OP2_SHIFT) | + (FIR_OP_CMD1 << FIR_OP3_SHIFT) | + (FIR_OP_BTRD << FIR_OP4_SHIFT))); + + write_reg(nand, NAND_FIR1, (FIR_OP_NOP << FIR_OP5_SHIFT)); + } + write_reg(nand, NANDSEQ_STRT, NAND_SEQ_STRT_FIR_STRT); + + ret = nand_wait(nand); + if (ret != 0) + return ret; + + /* calculate page_size_add_bits i.e bits + * in sram address corresponding to area + * within a page for sram + */ + if (nand->page_size == U(512)) + page_size_add_bits = U(10); + else if (nand->page_size == U(2048)) + page_size_add_bits = U(12); + else if (nand->page_size == U(4096)) + page_size_add_bits = U(13); + else if (nand->page_size == U(8192)) + page_size_add_bits = U(14); + else if (nand->page_size == U(16384)) + page_size_add_bits = U(15); + + page_add = row_add; + + page_add_in_actual = (page_add << page_size_add_bits) & U(0x0000FFFF); + + if (byte_cnt == 0) + col_add = U(0); + + /* Calculate SRAM address for main and spare area */ + if (main_spare == 0) + sram_addr_calc = ifc_region_addr | page_add_in_actual | col_add; + else + sram_addr_calc = ifc_region_addr | page_add_in_actual | + (col_add + nand->page_size); + + /* Depending Byte_count copy full page or partial page from SRAM */ + if (byte_cnt == 0) + memcpy(data, (void *)sram_addr_calc, + nand->page_size); + else + memcpy(data, (void *)sram_addr_calc, byte_cnt); + + return 0; +} + +static int nand_read(struct nand_info *nand, int32_t src_addr, + uintptr_t dst, uint32_t size) +{ + uint32_t log_blk = U(0); + uint32_t pg_no = U(0); + uint32_t col_off = U(0); + uint32_t row_off = U(0); + uint32_t byte_cnt = U(0); + uint32_t read_cnt = U(0); + uint32_t i = U(0); + uint32_t updated = U(0); + + int ret = 0; + uint8_t *out = (uint8_t *)dst; + + uint32_t pblk; + + /* loop till size */ + while (size) { + log_blk = (src_addr / nand->blk_size); + pg_no = ((src_addr - (log_blk * nand->blk_size)) / + nand->page_size); + pblk = log_blk; + + // iterate the bbt to find the block + for (i = 0; i <= nand->bbt_max; i++) { + if (nand->bbt[i] == EMPTY_VAL_CHECK) { + ret = update_bbt(i, pblk, &updated, nand); + + if (ret != 0) + return ret; + /* + * if table not updated and we reached + * end of table + */ + if (!updated) + break; + } + + if (pblk < nand->bbt[i]) + break; + else if (pblk >= nand->bbt[i]) + pblk++; + } + + col_off = (src_addr % nand->page_size); + if (col_off) { + if ((col_off + size) < nand->page_size) + byte_cnt = size; + else + byte_cnt = nand->page_size - col_off; + + row_off = (pblk << nand->pi_width) | pg_no; + + ret = nand_read_data( + nand->ifc_region_addr, + row_off, + col_off, + byte_cnt, out, MAIN, nand); + + if (ret != 0) + return ret; + } else { + /* + * fullpage/Partial Page + * if byte_cnt = 0 full page + * else partial page + */ + if (size < nand->page_size) { + byte_cnt = size; + read_cnt = size; + } else { + byte_cnt = nand->page_size; + read_cnt = 0; + } + row_off = (pblk << nand->pi_width) | pg_no; + + ret = nand_read_data( + nand->ifc_region_addr, + row_off, + 0, + read_cnt, out, MAIN, nand); + + if (ret != 0) { + ERROR("Error from nand-read_data %d\n", ret); + return ret; + } + } + src_addr += byte_cnt; + out += byte_cnt; + size -= byte_cnt; + } + return 0; +} + +static int isgoodblock(uint32_t blk, uint32_t *gb, struct nand_info *nand) +{ + uint8_t buf[2]; + int ret; + uint32_t row_add; + + *gb = 0; + + /* read Page 0 of blk */ + ret = nand_read_data( + nand->ifc_region_addr, + blk << nand->pi_width, + nand->bad_marker_loc, + 0x2, buf, 1, nand); + + if (ret != 0) + return ret; + + /* For ONFI devices check Page 0 and Last page of block for + * Bad Marker and for NON-ONFI Page 0 and 1 for Bad Marker + */ + row_add = (blk << nand->pi_width); + if (nand->port_size == 8) { + /* port size is 8 Bit */ + /* check if page 0 has 0xff */ + if (buf[0] == 0xff) { + /* check page 1 */ + if (nand->onfi_dev_flag) + ret = nand_read_data( + nand->ifc_region_addr, + row_add | (nand->ppb - 1), + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + else + ret = nand_read_data( + nand->ifc_region_addr, + row_add | 1, + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + + if (ret != 0) + return ret; + + if (buf[0] == 0xff) + *gb = GOOD_BLK; + else + *gb = BAD_BLK; + } else { + /* no, so it is bad blk */ + *gb = BAD_BLK; + } + } else { + /* Port size 16-Bit */ + /* check if page 0 has 0xffff */ + if ((buf[0] == 0xff) && + (buf[1] == 0xff)) { + /* check page 1 for 0xffff */ + if (nand->onfi_dev_flag) { + ret = nand_read_data( + nand->ifc_region_addr, + row_add | (nand->ppb - 1), + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + } else { + ret = nand_read_data( + nand->ifc_region_addr, + row_add | 1, + nand->bad_marker_loc, + 0x2, buf, SPARE, nand); + } + + if (ret != 0) + return ret; + + if ((buf[0] == 0xff) && + (buf[1] == 0xff)) { + *gb = GOOD_BLK; + } else { + *gb = BAD_BLK; + } + } else { + /* no, so it is bad blk */ + *gb = BAD_BLK; + } + } + return 0; +} + +static int update_bbt(uint32_t idx, uint32_t blk, + uint32_t *updated, struct nand_info *nand) +{ + uint32_t sblk; + uint32_t lgb; + int ret; + + if (nand->bzero_good && blk == 0) + return 0; + + /* special case for lgb == 0 */ + /* if blk <= lgb retrun */ + if (nand->lgb != 0 && blk <= nand->lgb) + return 0; + + *updated = 0; + + /* if blk is more than lgb, iterate from lgb till a good block + * is found for blk + */ + + if (nand->lgb < blk) + sblk = nand->lgb; + else + /* this is when lgb = 0 */ + sblk = blk; + + + lgb = nand->lgb; + + /* loop from blk to find a good block */ + while (1) { + while (lgb <= sblk) { + uint32_t gb = 0; + + ret = isgoodblock(lgb, &gb, nand); + if (ret != 0) + return ret; + + /* special case block 0 is good then set this flag */ + if (lgb == 0 && gb == GOOD_BLK) + nand->bzero_good = 1; + + if (gb == BAD_BLK) { + if (idx >= BBT_SIZE) { + ERROR("NAND BBT Table full\n"); + return -1; + } + *updated = 1; + nand->bbt[idx] = lgb; + idx++; + blk++; + sblk++; + if (idx > nand->bbt_max) + nand->bbt_max = idx; + } + lgb++; + } + /* the access block found */ + if (sblk == blk) { + /* when good block found update lgb */ + nand->lgb = blk; + break; + } + sblk++; + } + + return 0; +} + +static size_t ifc_nand_read(int lba, uintptr_t buf, size_t size) +{ + int ret; + uint32_t page_size; + uint32_t src_addr; + struct nand_info *nand = &nand_drv_data; + + page_size = nand_get_page_size(nand); + src_addr = lba * page_size; + ret = nand_read(nand, src_addr, buf, size); + return ret ? 0 : size; +} + +static struct io_block_dev_spec ifc_nand_spec = { + .buffer = { + .offset = 0, + .length = 0, + }, + .ops = { + .read = ifc_nand_read, + }, + /* + * Default block size assumed as 2K + * Would be updated based on actual size + */ + .block_size = UL(2048), +}; + +int ifc_nand_init(uintptr_t *block_dev_spec, + uintptr_t ifc_region_addr, + uintptr_t ifc_register_addr, + size_t ifc_sram_size, + uintptr_t ifc_nand_blk_offset, + size_t ifc_nand_blk_size) +{ + struct nand_info *nand = NULL; + int ret; + + nand = &nand_drv_data; + memset(nand, 0, sizeof(struct nand_info)); + + nand->ifc_region_addr = ifc_region_addr; + nand->ifc_register_addr = ifc_register_addr; + + VERBOSE("nand_init\n"); + ret = nand_init(nand); + if (ret) { + ERROR("nand init failed\n"); + return ret; + } + + ifc_nand_spec.buffer.offset = ifc_nand_blk_offset; + ifc_nand_spec.buffer.length = ifc_nand_blk_size; + + ifc_nand_spec.block_size = nand_get_page_size(nand); + + VERBOSE("Page size is %ld\n", ifc_nand_spec.block_size); + + *block_dev_spec = (uintptr_t)&ifc_nand_spec; + + /* Adding NAND SRAM< Buffer in XLAT Table */ + mmap_add_region(ifc_region_addr, ifc_region_addr, + ifc_sram_size, MT_DEVICE | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk new file mode 100644 index 0000000..890fd23 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.mk @@ -0,0 +1,29 @@ +# +# Copyright 2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${NAND_ADDED},) + +NAND_ADDED := 1 + +NAND_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/ifc/nand + +NAND_SOURCES := $(NAND_DRIVERS_PATH)/ifc_nand.c \ + drivers/io/io_block.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ifc + +ifeq (${BL_COMM_IFC_NAND_NEEDED},yes) +BL_COMMON_SOURCES += ${NAND_SOURCES} +else +ifeq (${BL2_IFC_NAND_NEEDED},yes) +BL2_SOURCES += ${NAND_SOURCES} +endif +ifeq (${BL31_IFC_NAND_NEEDED},yes) +BL31_SOURCES += ${NAND_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c new file mode 100644 index 0000000..24fc308 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c @@ -0,0 +1,18 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include + +#include + +int ifc_nor_init(uintptr_t flash_addr, size_t flash_size) +{ + /* Adding NOR Memory Map in XLAT Table */ + mmap_add_region(flash_addr, flash_addr, flash_size, MT_MEMORY | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk new file mode 100644 index 0000000..0022a81 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.mk @@ -0,0 +1,28 @@ +# +# Copyright 2020-2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${NOR_ADDED},) + +NOR_ADDED := 1 + +NOR_DRIVERS_PATH := ${PLAT_DRIVERS_PATH}/ifc/nor + +NOR_SOURCES := $(NOR_DRIVERS_PATH)/ifc_nor.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/ifc + +ifeq (${BL_COMM_IFC_NOR_NEEDED},yes) +BL_COMMON_SOURCES += ${NOR_SOURCES} +else +ifeq (${BL2_IFC_NOR_NEEDED},yes) +BL2_SOURCES += ${NOR_SOURCES} +endif +ifeq (${BL31_IFC_NOR_NEEDED},yes) +BL31_SOURCES += ${NOR_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk b/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk new file mode 100644 index 0000000..aa51be4 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/interconnect.mk @@ -0,0 +1,44 @@ +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +#------------------------------------------------------------------------------ +# +# Select the Interconnect files +# +# ----------------------------------------------------------------------------- + +ifeq (${ADD_INTERCONNECT},) + +ADD_INTERCONNECT := 1 +PLAT_INCLUDES += -I${PLAT_DRIVERS_INCLUDE_PATH}/interconnect + +ifeq (, $(filter $(INTERCONNECT), CCI400 CCN502 CCN504 CCN508)) + $(error -> Interconnect type not set!) +else +$(eval $(call add_define_val,INTERCONNECT,${INTERCONNECT})) +ifeq ($(INTERCONNECT), $(filter $(INTERCONNECT), CCN502 CCN504 CCN508)) +INTERCONNECT_SOURCES := drivers/arm/ccn/ccn.c \ + ${PLAT_DRIVERS_PATH}/interconnect/ls_ccn.c +else +ifeq ($(INTERCONNECT), CCI400) +INTERCONNECT_SOURCES := drivers/arm/cci/cci.c \ + ${PLAT_DRIVERS_PATH}/interconnect/ls_cci.c +endif +endif +endif + +ifeq (${BL_COMM_INTERCONNECT_NEEDED},yes) +BL_COMMON_SOURCES += ${INTERCONNECT_SOURCES} +else +ifeq (${BL2_INTERCONNECT_NEEDED},yes) +BL2_SOURCES += ${INTERCONNECT_SOURCES} +endif +ifeq (${BL31_INTERCONNECT_NEEDED},yes) +BL31_SOURCES += ${INTERCONNECT_SOURCES} +endif +endif +endif + +# ----------------------------------------------------------------------------- diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c b/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c new file mode 100644 index 0000000..72a898a --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c @@ -0,0 +1,38 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +/****************************************************************************** + * 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_enter_coherency +#pragma weak plat_arm_interconnect_exit_coherency + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters) +{ + cci_enable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + for (uint32_t index = 1U; index < num_clusters; index++) { + cci_enable_snoop_dvm_reqs(index); + } +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_ls_interconnect_exit_coherency(void) +{ + cci_disable_snoop_dvm_reqs(MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c b/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c new file mode 100644 index 0000000..8f90325 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c @@ -0,0 +1,31 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +/****************************************************************************** + * Helper function to place current master into coherency + *****************************************************************************/ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters) +{ + ccn_enter_snoop_dvm_domain(1ULL << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + for (uint32_t index = 1U; index < num_clusters; index++) { + ccn_enter_snoop_dvm_domain(1ULL << index); + } +} + +/****************************************************************************** + * Helper function to remove current master from coherency + *****************************************************************************/ +void plat_ls_interconnect_exit_coherency(void) +{ + ccn_exit_snoop_dvm_domain(1ULL << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); +} diff --git a/arm-trusted-firmware/drivers/nxp/pmu/pmu.c b/arm-trusted-firmware/drivers/nxp/pmu/pmu.c new file mode 100644 index 0000000..2a907c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/pmu/pmu.c @@ -0,0 +1,45 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include + +void enable_timer_base_to_cluster(uintptr_t nxp_pmu_addr) +{ + uint32_t *cltbenr = NULL; + uint32_t cltbenr_val = 0U; + + cltbenr = (uint32_t *)(nxp_pmu_addr + + CLUST_TIMER_BASE_ENBL_OFFSET); + + cltbenr_val = mmio_read_32((uintptr_t)cltbenr); + + cltbenr_val = cltbenr_val + | (1 << MPIDR_AFFLVL1_VAL(read_mpidr_el1())); + + mmio_write_32((uintptr_t)cltbenr, cltbenr_val); + + VERBOSE("Enable cluster time base\n"); +} + +/* + * Enable core timebase. In certain Layerscape SoCs, the clock for each core's + * has an enable bit in the PMU Physical Core Time Base Enable + * Register (PCTBENR), which allows the watchdog to operate. + */ + +void enable_core_tb(uintptr_t nxp_pmu_addr) +{ + uint32_t *pctbenr = (uint32_t *) (nxp_pmu_addr + + CORE_TIMEBASE_ENBL_OFFSET); + + mmio_write_32((uintptr_t)pctbenr, 0xff); +} diff --git a/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk b/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk new file mode 100644 index 0000000..8d2ef07 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/pmu/pmu.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${PMU_ADDED},) + +PMU_ADDED := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/pmu + +PMU_SOURCES += $(PLAT_DRIVERS_PATH)/pmu/pmu.c + +ifeq (${BL_COMM_PMU_NEEDED},yes) +BL_COMMON_SOURCES += ${PMU_SOURCES} +else +ifeq (${BL2_PMU_NEEDED},yes) +BL2_SOURCES += ${PMU_SOURCES} +endif +ifeq (${BL31_PMU_NEEDED},yes) +BL31_SOURCES += ${PMU_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/qspi/qspi.c b/arm-trusted-firmware/drivers/nxp/qspi/qspi.c new file mode 100644 index 0000000..97b2a19 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/qspi/qspi.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include + +int qspi_io_setup(uintptr_t nxp_qspi_flash_addr, + size_t nxp_qspi_flash_size, + uintptr_t fip_offset) +{ + uint32_t qspi_mcr_val = qspi_in32(CHS_QSPI_MCR); + + /* Enable and change endianness of QSPI IP */ + qspi_out32(CHS_QSPI_MCR, (qspi_mcr_val | CHS_QSPI_64LE)); + + /* Adding QSPI Memory Map in XLAT Table */ + mmap_add_region(nxp_qspi_flash_addr, nxp_qspi_flash_addr, + nxp_qspi_flash_size, MT_MEMORY | MT_RW); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk b/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk new file mode 100644 index 0000000..450aeca --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/qspi/qspi.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${QSPI_ADDED},) + +QSPI_ADDED := 1 + +QSPI_SOURCES := $(PLAT_DRIVERS_PATH)/qspi/qspi.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/qspi + +ifeq (${BL_COMM_QSPI_NEEDED},yes) +BL_COMMON_SOURCES += ${QSPI_SOURCES} +else +ifeq (${BL2_QSPI_NEEDED},yes) +BL2_SOURCES += ${QSPI_SOURCES} +endif +ifeq (${BL31_QSPI_NEEDED},yes) +BL31_SOURCES += ${QSPI_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c new file mode 100644 index 0000000..f7f48e7 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c @@ -0,0 +1,1496 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include "nxp_timer.h" +#include "sd_mmc.h" +#include +#include + + +/* Private structure for MMC driver data */ +static struct mmc mmc_drv_data; + +#ifndef NXP_POLICY_OTA +/* + * For NXP_POLICY_OTA, SD needs to do R/W on OCRAM. OCRAM is secure memory at + * default. SD can only do non-secure DMA. Configuring SD to work in PIO mode + * instead of DMA mode will make SD R/W on OCRAM available. + */ +/* To debug without dma comment this MACRO */ +#define NXP_SD_DMA_CAPABILITY +#endif +#define SD_TIMEOUT 1000 /* ms */ +#define SD_TIMEOUT_HIGH 20000 /* ms */ +#define SD_BLOCK_TIMEOUT 8 /* ms */ + +#define ERROR_ESDHC_CARD_DETECT_FAIL -1 +#define ERROR_ESDHC_UNUSABLE_CARD -2 +#define ERROR_ESDHC_COMMUNICATION_ERROR -3 +#define ERROR_ESDHC_BLOCK_LENGTH -4 +#define ERROR_ESDHC_DMA_ERROR -5 +#define ERROR_ESDHC_BUSY -6 + +/*************************************************************** + * Function : set_speed + * Arguments : mmc - Pointer to mmc struct + * clock - Clock Value to be set + * Return : void + * Description : Calculates the value of SDCLKFS and DVS to be set + * for getting the required clock assuming the base_clk + * as a fixed value (MAX_PLATFORM_CLOCK) + *****************************************************************/ +static void set_speed(struct mmc *mmc, uint32_t clock) +{ + /* sdhc_clk = (base clock) / [(SDCLKFS × 2) × (DVS +1)] */ + + uint32_t dvs = 1U; + uint32_t sdclkfs = 2U; + /* TBD - Change this to actual platform clock by reading via RCW */ + uint32_t base_clk = MAX_PLATFORM_CLOCK; + + if (base_clk / 16 > clock) { + for (sdclkfs = 2U; sdclkfs < 256U; sdclkfs *= 2U) { + if ((base_clk / sdclkfs) <= (clock * 16)) { + break; + } + } + } + + for (dvs = 1U; dvs <= 16U; dvs++) { + if ((base_clk / (dvs * sdclkfs)) <= clock) { + break; + } + } + + sdclkfs >>= 1U; + dvs -= 1U; + + esdhc_out32(&mmc->esdhc_regs->sysctl, + (ESDHC_SYSCTL_DTOCV(TIMEOUT_COUNTER_SDCLK_2_27) | + ESDHC_SYSCTL_SDCLKFS(sdclkfs) | ESDHC_SYSCTL_DVS(dvs) | + ESDHC_SYSCTL_SDCLKEN)); +} + +/*************************************************************************** + * Function : esdhc_init + * Arguments : mmc - Pointer to mmc struct + * card_detect - flag to indicate if card insert needs + * to be detected or not. For SDHC2 controller, Card detect + * is not present, so this field will be false + * Return : SUCCESS or Error Code + * Description : 1. Set Initial Clock Speed + * 2. Card Detect if not eMMC + * 3. Enable Controller Clock + * 4. Send 80 ticks for card to power up + * 5. Set LE mode and Bus Width as 1 bit. + ***************************************************************************/ +static int esdhc_init(struct mmc *mmc, bool card_detect) +{ + uint32_t val; + uint64_t start_time; + + /* Reset the entire host controller */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_RSTA; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + /* Wait until the controller is available */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_RSTA; + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & + (ESDHC_SYSCTL_RSTA); + if (val != 0U) { + ERROR("SD Reset failed\n"); + return ERROR_ESDHC_BUSY; + } + + /* Set initial clock speed */ + set_speed(mmc, CARD_IDENTIFICATION_FREQ); + + if (card_detect) { + /* Check CINS in prsstat register */ + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_CINS; + if (val == 0) { + ERROR("CINS not set in prsstat\n"); + return ERROR_ESDHC_CARD_DETECT_FAIL; + } + } + + /* Enable controller clock */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_SDCLKEN; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + /* Send 80 clock ticks for the card to power up */ + val = esdhc_in32(&mmc->esdhc_regs->sysctl) | ESDHC_SYSCTL_INITA; + esdhc_out32(&mmc->esdhc_regs->sysctl, val); + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT) { + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->sysctl) & ESDHC_SYSCTL_INITA; + if (val == 0U) { + ERROR("Failed to power up the card\n"); + return ERROR_ESDHC_CARD_DETECT_FAIL; + } + + INFO("Card detected successfully\n"); + + val = esdhc_in32(&mmc->esdhc_regs->proctl); + val = val | (ESDHC_PROCTL_EMODE_LE | ESDHC_PROCTL_DTW_1BIT); + + /* Set little endian mode, set bus width as 1-bit */ + esdhc_out32(&mmc->esdhc_regs->proctl, val); + + /* Enable cache snooping for DMA transactions */ + val = esdhc_in32(&mmc->esdhc_regs->ctl) | ESDHC_DCR_SNOOP; + esdhc_out32(&mmc->esdhc_regs->ctl, val); + + return 0; +} + +/*************************************************************************** + * Function : esdhc_send_cmd + * Arguments : mmc - Pointer to mmc struct + * cmd - Command Number + * args - Command Args + * Return : SUCCESS is 0, or Error Code ( < 0) + * Description : Updates the eSDHC registers cmdargs and xfertype + ***************************************************************************/ +static int esdhc_send_cmd(struct mmc *mmc, uint32_t cmd, uint32_t args) +{ + uint32_t val; + uint64_t start_time; + uint32_t xfertyp = 0; + + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + /* Wait for the command line & data line to be free */ + /* (poll the CIHB,CDIHB bit of the present state register) */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + (ESDHC_PRSSTAT_CIHB | ESDHC_PRSSTAT_CDIHB); + if (val != 0U) { + ERROR("SD send cmd: Command Line or Data Line Busy cmd = %x\n", + cmd); + return ERROR_ESDHC_BUSY; + } + + if (cmd == CMD2 || cmd == CMD9) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_136; + } else if (cmd == CMD7 || (cmd == CMD6 && mmc->card.type == MMC_CARD)) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_48_BUSY; + } else if (cmd != CMD0) { + xfertyp |= ESDHC_XFERTYP_RSPTYP_48; + } + + if (cmd == CMD2 || cmd == CMD9) { + xfertyp |= ESDHC_XFERTYP_CCCEN; /* Command index check enable */ + } else if ((cmd != CMD0) && (cmd != ACMD41) && (cmd != CMD1)) { + xfertyp = xfertyp | ESDHC_XFERTYP_CCCEN | ESDHC_XFERTYP_CICEN; + } + + if ((cmd == CMD8 || cmd == CMD14 || cmd == CMD19) && + mmc->card.type == MMC_CARD) { + xfertyp |= ESDHC_XFERTYP_DPSEL; + if (cmd != CMD19) { + xfertyp |= ESDHC_XFERTYP_DTDSEL; + } + } + + if (cmd == CMD6 || cmd == CMD17 || cmd == CMD18 || cmd == CMD24 || + cmd == ACMD51) { + if (!(mmc->card.type == MMC_CARD && cmd == CMD6)) { + if (cmd == CMD24) { + xfertyp |= ESDHC_XFERTYP_DPSEL; + } else { + xfertyp |= (ESDHC_XFERTYP_DPSEL | + ESDHC_XFERTYP_DTDSEL); + } + } + + if (cmd == CMD18) { + xfertyp |= ESDHC_XFERTYP_BCEN; + if (mmc->dma_support != 0) { + /* Set BCEN of XFERTYP */ + xfertyp |= ESDHC_XFERTYP_DMAEN; + } + } + + if ((cmd == CMD17 || cmd == CMD24) && (mmc->dma_support != 0)) { + xfertyp |= ESDHC_XFERTYP_DMAEN; + } + } + + xfertyp |= ((cmd & 0x3F) << 24); + esdhc_out32(&mmc->esdhc_regs->cmdarg, args); + esdhc_out32(&mmc->esdhc_regs->xfertyp, xfertyp); + +#ifdef NXP_SD_DEBUG + INFO("cmd = %d\n", cmd); + INFO("args = %x\n", args); + INFO("xfertyp: = %x\n", xfertyp); +#endif + return 0; +} + +/*************************************************************************** + * Function : esdhc_wait_response + * Arguments : mmc - Pointer to mmc struct + * response - Value updated + * Return : SUCCESS - Response Received + * COMMUNICATION_ERROR - Command not Complete + * COMMAND_ERROR - CIE, CCE or CEBE error + * RESP_TIMEOUT - CTOE error + * Description : Checks for successful command completion. + * Clears the CC bit at the end. + ***************************************************************************/ +static int esdhc_wait_response(struct mmc *mmc, uint32_t *response) +{ + uint32_t val; + uint64_t start_time; + uint32_t status = 0U; + + /* Wait for the command to complete */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_CC; + if (val == 0U) { + ERROR("%s:IRQSTAT Cmd not complete(CC not set)\n", __func__); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + /* Check whether the interrupt is a CRC, CTOE or CIE error */ + if ((status & (ESDHC_IRQSTAT_CIE | ESDHC_IRQSTAT_CEBE | + ESDHC_IRQSTAT_CCE)) != 0) { + ERROR("%s: IRQSTAT CRC, CEBE or CIE error = %x\n", + __func__, status); + return COMMAND_ERROR; + } + + if ((status & ESDHC_IRQSTAT_CTOE) != 0) { + INFO("%s: IRQSTAT CTOE set = %x\n", __func__, status); + return RESP_TIMEOUT; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("%s: IRQSTAT DMAE set = %x\n", __func__, status); + return ERROR_ESDHC_DMA_ERROR; + } + + if (response != NULL) { + /* Get response values from eSDHC CMDRSPx registers. */ + response[0] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[0]); + response[1] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[1]); + response[2] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[2]); + response[3] = esdhc_in32(&mmc->esdhc_regs->cmdrsp[3]); +#ifdef NXP_SD_DEBUG + INFO("Resp R1 R2 R3 R4\n"); + INFO("Resp R1 = %x\n", response[0]); + INFO("R2 = %x\n", response[1]); + INFO("R3 = %x\n", response[2]); + INFO("R4 = %x\n", response[3]); + INFO("\n"); +#endif + } + + /* Clear the CC bit - w1c */ + val = esdhc_in32(&mmc->esdhc_regs->irqstat) | ESDHC_IRQSTAT_CC; + esdhc_out32(&mmc->esdhc_regs->irqstat, val); + + return 0; +} + +/*************************************************************************** + * Function : mmc_switch_to_high_frquency + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : mmc card bellow ver 4.0 does not support high speed + * freq = 20 MHz + * Send CMD6 (CMD_SWITCH_FUNC) With args 0x03B90100 + * Send CMD13 (CMD_SEND_STATUS) + * if SWITCH Error, freq = 26 MHz + * if no error, freq = 52 MHz + ***************************************************************************/ +static int mmc_switch_to_high_frquency(struct mmc *mmc) +{ + int error; + uint32_t response[4]; + uint64_t start_time; + + mmc->card.bus_freq = MMC_SS_20MHZ; + /* mmc card bellow ver 4.0 does not support high speed */ + if (mmc->card.version < MMC_CARD_VERSION_4_X) { + return 0; + } + + /* send switch cmd to change the card to High speed */ + error = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SET_EXT_CSD_HS_TIMING); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + + start_time = get_timer_val(0); + do { + /* check the status for which error */ + error = esdhc_send_cmd(mmc, + CMD_SEND_STATUS, mmc->card.rca << 16); + if (error != 0) { + return error; + } + + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + } while (((response[0] & SWITCH_ERROR) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT)); + + /* Check for the present state of card */ + if ((response[0] & SWITCH_ERROR) != 0) { + mmc->card.bus_freq = MMC_HS_26MHZ; + } else { + mmc->card.bus_freq = MMC_HS_52MHZ; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_set_data_attributes + * Arguments : mmc - Pointer to mmc struct + * blkcnt + * blklen + * Return : SUCCESS or Error Code + * Description : Set block attributes and watermark level register + ***************************************************************************/ +static int esdhc_set_data_attributes(struct mmc *mmc, uint32_t *dest_ptr, + uint32_t blkcnt, uint32_t blklen) +{ + uint32_t val; + uint64_t start_time; + uint32_t wml; + uint32_t wl; + uint32_t dst = (uint32_t)((uint64_t)(dest_ptr)); + + /* set blkattr when no transactions are executing */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; + if (val == 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA; + if (val != 0U) { + ERROR("%s: Data line active.Can't set attribute\n", __func__); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + wml = esdhc_in32(&mmc->esdhc_regs->wml); + wml &= ~(ESDHC_WML_WR_BRST_MASK | ESDHC_WML_RD_BRST_MASK | + ESDHC_WML_RD_WML_MASK | ESDHC_WML_WR_WML_MASK); + + if ((mmc->dma_support != 0) && (dest_ptr != NULL)) { + /* Set burst length to 128 bytes */ + esdhc_out32(&mmc->esdhc_regs->wml, + wml | ESDHC_WML_WR_BRST(BURST_128_BYTES)); + esdhc_out32(&mmc->esdhc_regs->wml, + wml | ESDHC_WML_RD_BRST(BURST_128_BYTES)); + + /* Set DMA System Destination Address */ + esdhc_out32(&mmc->esdhc_regs->dsaddr, dst); + } else { + wl = (blklen >= BLOCK_LEN_512) ? + WML_512_BYTES : ((blklen + 3) / 4); + /* Set 'Read Water Mark Level' register */ + esdhc_out32(&mmc->esdhc_regs->wml, wml | ESDHC_WML_RD_WML(wl)); + } + + /* Configure block Attributes register */ + esdhc_out32(&mmc->esdhc_regs->blkattr, + ESDHC_BLKATTR_BLKCNT(blkcnt) | ESDHC_BLKATTR_BLKSZE(blklen)); + + mmc->block_len = blklen; + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data_nodma + * Arguments : mmc - Pointer to mmc struct + * dest_ptr - Bufffer where read data is to be copied + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Read data from the sdhc buffer without using DMA + * and using polling mode + ***************************************************************************/ +static int esdhc_read_data_nodma(struct mmc *mmc, void *dest_ptr, uint32_t len) +{ + uint32_t i = 0U; + uint32_t status; + uint32_t num_blocks; + uint32_t *dst = (uint32_t *)dest_ptr; + uint32_t val; + uint64_t start_time; + + num_blocks = len / mmc->block_len; + + while ((num_blocks--) != 0U) { + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BREN; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) + & ESDHC_PRSSTAT_BREN; + if (val == 0U) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); + i < mmc->block_len / 4; i++, dst++) { + /* get data from data port */ + val = mmio_read_32( + (uintptr_t)&mmc->esdhc_regs->datport); + esdhc_out32(dst, val); + /* Increment destination pointer */ + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + } + /* Check whether the interrupt is an DTOE/DCE/DEBE */ + if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | + ESDHC_IRQSTAT_DEBE)) != 0) { + ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + } + + /* Wait for TC */ + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val == 0U) { + ERROR("SD read timeout: Transfer bit not set in IRQSTAT\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_write_data_nodma + * Arguments : mmc - Pointer to mmc struct + * src_ptr - Buffer where data is copied from + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Write data to the sdhc buffer without using DMA + * and using polling mode + ***************************************************************************/ +static int esdhc_write_data_nodma(struct mmc *mmc, void *src_ptr, uint32_t len) +{ + uint32_t i = 0U; + uint32_t status; + uint32_t num_blocks; + uint32_t *src = (uint32_t *)src_ptr; + uint32_t val; + uint64_t start_time; + + num_blocks = len / mmc->block_len; + + while ((num_blocks--) != 0U) { + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BWEN; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->prsstat) & + ESDHC_PRSSTAT_BWEN; + if (val == 0U) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + for (i = 0U, status = esdhc_in32(&mmc->esdhc_regs->irqstat); + i < mmc->block_len / 4; i++, src++) { + val = esdhc_in32(src); + /* put data to data port */ + mmio_write_32((uintptr_t)&mmc->esdhc_regs->datport, + val); + /* Increment source pointer */ + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + } + /* Check whether the interrupt is an DTOE/DCE/DEBE */ + if ((status & (ESDHC_IRQSTAT_DTOE | ESDHC_IRQSTAT_DCE | + ESDHC_IRQSTAT_DEBE)) != 0) { + ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + } + + /* Wait for TC */ + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val != 0U) { + break; + } + } + + val = esdhc_in32(&mmc->esdhc_regs->irqstat) & ESDHC_IRQSTAT_TC; + if (val == 0U) { + ERROR("SD write timeout: Transfer bit not set in IRQSTAT\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data_dma + * Arguments : mmc - Pointer to mmc struct + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Read data from the sd card using DMA. + ***************************************************************************/ +static int esdhc_read_data_dma(struct mmc *mmc, uint32_t len) +{ + uint32_t status; + uint32_t tblk; + uint64_t start_time; + + tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); + + start_time = get_timer_val(0); + + /* poll till TC is set */ + do { + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE + | ESDHC_IRQSTAT_DTOE)) != 0) { + ERROR("SD read error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("SD read error - DMA error = %x\n", status); + return ERROR_ESDHC_DMA_ERROR; + } + + } while (((status & ESDHC_IRQSTAT_TC) == 0) && + ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { + ERROR("SD read DMA timeout\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_write_data_dma + * Arguments : mmc - Pointer to mmc struct + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Write data to the sd card using DMA. + ***************************************************************************/ +static int esdhc_write_data_dma(struct mmc *mmc, uint32_t len) +{ + uint32_t status; + uint32_t tblk; + uint64_t start_time; + + tblk = SD_BLOCK_TIMEOUT * (len / mmc->block_len); + + start_time = get_timer_val(0); + + /* poll till TC is set */ + do { + status = esdhc_in32(&mmc->esdhc_regs->irqstat); + + if ((status & (ESDHC_IRQSTAT_DEBE | ESDHC_IRQSTAT_DCE + | ESDHC_IRQSTAT_DTOE)) != 0) { + ERROR("SD write error - DTOE, DCE, DEBE bit set = %x\n", + status); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status & ESDHC_IRQSTAT_DMAE) != 0) { + ERROR("SD write error - DMA error = %x\n", status); + return ERROR_ESDHC_DMA_ERROR; + } + } while (((status & ESDHC_IRQSTAT_TC) == 0) && + ((esdhc_in32(&mmc->esdhc_regs->prsstat) & ESDHC_PRSSTAT_DLA) != 0) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH + tblk)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH + tblk) { + ERROR("SD write DMA timeout\n"); + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + return 0; +} + +/*************************************************************************** + * Function : esdhc_read_data + * Arguments : mmc - Pointer to mmc struct + * dest_ptr - Bufffer where read data is to be copied + * len - Length of Data to be read + * Return : SUCCESS or Error Code + * Description : Calls esdhc_read_data_nodma and clear interrupt status + ***************************************************************************/ +int esdhc_read_data(struct mmc *mmc, void *dest_ptr, uint32_t len) +{ + int ret; + + if (mmc->dma_support && len > 64) { + ret = esdhc_read_data_dma(mmc, len); + } else { + ret = esdhc_read_data_nodma(mmc, dest_ptr, len); + } + + /* clear interrupt status */ + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + return ret; +} + +/*************************************************************************** + * Function : esdhc_write_data + * Arguments : mmc - Pointer to mmc struct + * src_ptr - Buffer where data is copied from + * len - Length of Data to be written + * Return : SUCCESS or Error Code + * Description : Calls esdhc_write_data_nodma and clear interrupt status + ***************************************************************************/ +int esdhc_write_data(struct mmc *mmc, void *src_ptr, uint32_t len) +{ + int ret; + + if (mmc->dma_support && len > 64) { + ret = esdhc_write_data_dma(mmc, len); + } else { + ret = esdhc_write_data_nodma(mmc, src_ptr, len); + } + + /* clear interrupt status */ + esdhc_out32(&mmc->esdhc_regs->irqstat, ESDHC_IRQSTAT_CLEAR_ALL); + + return ret; +} + +/*************************************************************************** + * Function : sd_switch_to_high_freq + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send ACMD51 (CMD_SEND_SCR) + * 2. Read the SCR to check if card supports higher freq + * 3. check version from SCR + * 4. If SD 1.0, return (no Switch) freq = 25 MHz. + * 5. Send CMD6 (CMD_SWITCH_FUNC) with args 0x00FFFFF1 to + * check the status of switch func + * 6. Send CMD6 (CMD_SWITCH_FUNC) With args 0x80FFFFF1 to + * switch to high frequency = 50 Mhz + ***************************************************************************/ +static int sd_switch_to_high_freq(struct mmc *mmc) +{ + int err; + uint8_t scr[8]; + uint8_t status[64]; + uint32_t response[4]; + uint32_t version; + uint32_t count; + uint32_t sd_versions[] = {SD_CARD_VERSION_1_0, SD_CARD_VERSION_1_10, + SD_CARD_VERSION_2_0}; + + mmc->card.bus_freq = SD_SS_25MHZ; + /* Send Application command */ + err = esdhc_send_cmd(mmc, CMD_APP_CMD, mmc->card.rca << 16); + if (err != 0) { + return err; + } + + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + esdhc_set_data_attributes(mmc, NULL, 1, 8); + /* Read the SCR to find out if this card supports higher speeds */ + err = esdhc_send_cmd(mmc, CMD_SEND_SCR, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* read 8 bytes of scr data */ + err = esdhc_read_data(mmc, scr, 8U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* check version from SCR */ + version = scr[0] & U(0xF); + if (version <= 2U) { + mmc->card.version = sd_versions[version]; + } else { + mmc->card.version = SD_CARD_VERSION_2_0; + } + + /* does not support switch func */ + if (mmc->card.version == SD_CARD_VERSION_1_0) { + return 0; + } + + /* read 64 bytes of status */ + esdhc_set_data_attributes(mmc, NULL, 1U, 64U); + + /* check the status of switch func */ + for (count = 0U; count < 4U; count++) { + err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, + SD_SWITCH_FUNC_CHECK_MODE); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + /* read 64 bytes of scr data */ + err = esdhc_read_data(mmc, status, 64U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status[29] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { + break; + } + } + + if ((status[13] & SD_SWITCH_FUNC_HIGH_SPEED) == 0) { + return 0; + } + + /* SWITCH */ + esdhc_set_data_attributes(mmc, NULL, 1, 64); + err = esdhc_send_cmd(mmc, CMD_SWITCH_FUNC, SD_SWITCH_FUNC_SWITCH_MODE); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + err = esdhc_read_data(mmc, status, 64U); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if ((status[16]) == U(0x01)) { + mmc->card.bus_freq = SD_HS_50MHZ; + } + + return 0; +} + +/*************************************************************************** + * Function : change_state_to_transfer_state + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send CMD7 (CMD_SELECT_CARD) to toggles the card + * between stand-by and transfer state + * 2. Send CMD13 (CMD_SEND_STATUS) to check state as + * Transfer State + ***************************************************************************/ +static int change_state_to_transfer_state(struct mmc *mmc) +{ + int error = 0; + uint32_t response[4]; + uint64_t start_time; + + /* Command CMD_SELECT_CARD/CMD7 toggles the card between stand-by + * and transfer states + */ + error = esdhc_send_cmd(mmc, CMD_SELECT_CARD, mmc->card.rca << 16); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if (error != 0) { + return error; + } + + start_time = get_timer_val(0); + while (get_timer_val(start_time) < SD_TIMEOUT_HIGH) { + /* send CMD13 to check card status */ + error = esdhc_send_cmd(mmc, + CMD_SEND_STATUS, mmc->card.rca << 16); + if (error != 0) { + return error; + } + error = esdhc_wait_response(mmc, response); + if ((error != 0) || ((response[0] & R1_ERROR) != 0)) { + return error; + } + + /* Check for the present state of card */ + if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { + break; + } + } + if (((response[0] >> 9U) & U(0xF)) == STATE_TRAN) { + return 0; + } else { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } +} + +/*************************************************************************** + * Function : get_cid_rca_csd + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send CMD2 (CMD_ALL_SEND_CID) + * 2. get RCA for SD cards, set rca for mmc cards + * Send CMD3 (CMD_SEND_RELATIVE_ADDR) + * 3. Send CMD9 (CMD_SEND_CSD) + * 4. Get MMC Version from CSD + ***************************************************************************/ +static int get_cid_rca_csd(struct mmc *mmc) +{ + int err; + uint32_t version; + uint32_t response[4]; + uint32_t mmc_version[] = {MMC_CARD_VERSION_1_2, MMC_CARD_VERSION_1_4, + MMC_CARD_VERSION_2_X, MMC_CARD_VERSION_3_X, + MMC_CARD_VERSION_4_X}; + + err = esdhc_send_cmd(mmc, CMD_ALL_SEND_CID, 0); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* get RCA for SD cards, set rca for mmc cards */ + mmc->card.rca = SD_MMC_CARD_RCA; + + /* send RCA cmd */ + err = esdhc_send_cmd(mmc, CMD_SEND_RELATIVE_ADDR, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + /* for SD, get the the RCA */ + if (mmc->card.type == SD_CARD) { + mmc->card.rca = (response[0] >> 16) & 0xFFFF; + } + + /* Get the CSD (card specific data) from card. */ + err = esdhc_send_cmd(mmc, CMD_SEND_CSD, mmc->card.rca << 16); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, response); + if (err != 0) { + return err; + } + + version = (response[3] >> 18U) & U(0xF); + if (mmc->card.type == MMC_CARD) { + if (version <= MMC_CARD_VERSION_4_X) { + mmc->card.version = mmc_version[version]; + } else { + mmc->card.version = MMC_CARD_VERSION_4_X; + } + } + + mmc->card.block_len = 1 << ((response[2] >> 8) & 0xF); + + if (mmc->card.block_len > BLOCK_LEN_512) { + mmc->card.block_len = BLOCK_LEN_512; + } + + return 0; +} + +/*************************************************************************** + * Function : identify_mmc_card + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send Reset Command + * 2. Send CMD1 with args to set voltage range and Sector + * Mode. (Voltage Args = 0xFF8) + * 3. Check the OCR Response + ***************************************************************************/ +static int identify_mmc_card(struct mmc *mmc) +{ + uint64_t start_time; + uint32_t resp[4]; + int ret; + uint32_t args; + + /* card reset */ + ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ret; + } + + /* Send CMD1 to get the ocr value repeatedly till the card */ + /* busy is clear. timeout = 20sec */ + + start_time = get_timer_val(0); + do { + /* set the bits for the voltage ranges supported by host */ + args = mmc->voltages_caps | MMC_OCR_SECTOR_MODE; + ret = esdhc_send_cmd(mmc, CMD_MMC_SEND_OP_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + } while (((resp[0] & MMC_OCR_BUSY) == 0U) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + + if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { + mmc->card.is_high_capacity = 1; + } + + return MMC_CARD; +} + +/*************************************************************************** + * Function : check_for_sd_card + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : 1. Send Reset Command + * 2. Send CMD8 with pattern 0xAA (to check for SD 2.0) + * 3. Send ACMD41 with args to set voltage range and HCS + * HCS is set only for SD Card > 2.0 + * Voltage Caps = 0xFF8 + * 4. Check the OCR Response + ***************************************************************************/ +static int check_for_sd_card(struct mmc *mmc) +{ + uint64_t start_time; + uint32_t args; + int ret; + uint32_t resp[4]; + + /* Send reset command */ + ret = esdhc_send_cmd(mmc, CMD_GO_IDLE_STATE, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret != 0) { + return ret; + } + + /* send CMD8 with pattern 0xAA */ + args = MMC_VDD_HIGH_VOLTAGE | 0xAA; + ret = esdhc_send_cmd(mmc, CMD_SEND_IF_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == RESP_TIMEOUT) { /* sd ver 1.x or not sd */ + mmc->card.is_high_capacity = 0; + } else if ((resp[0] & U(0xFF)) == U(0xAA)) { /* ver 2.0 or later */ + mmc->card.version = SD_CARD_VERSION_2_0; + } else { + return NOT_SD_CARD; + } + /* Send Application command-55 to get the ocr value repeatedly till + * the card busy is clear. timeout = 20sec + */ + + start_time = get_timer_val(0); + do { + ret = esdhc_send_cmd(mmc, CMD_APP_CMD, 0U); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == COMMAND_ERROR) { + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* set the bits for the voltage ranges supported by host */ + args = mmc->voltages_caps; + if (mmc->card.version == SD_CARD_VERSION_2_0) { + args |= SD_OCR_HCS; + } + + /* Send ACMD41 to set voltage range */ + ret = esdhc_send_cmd(mmc, CMD_SD_SEND_OP_COND, args); + if (ret != 0) { + return ret; + } + ret = esdhc_wait_response(mmc, resp); + if (ret == COMMAND_ERROR) { + return ERROR_ESDHC_UNUSABLE_CARD; + } else if (ret == RESP_TIMEOUT) { + return NOT_SD_CARD; + } + } while (((resp[0] & MMC_OCR_BUSY) == 0U) && + (get_timer_val(start_time) < SD_TIMEOUT_HIGH)); + + if (get_timer_val(start_time) > SD_TIMEOUT_HIGH) { + INFO("SD_TIMEOUT_HIGH\n"); + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* bit set in card capacity status */ + if ((resp[0] & MMC_OCR_CCS) == MMC_OCR_CCS) { + mmc->card.is_high_capacity = 1; + } + + return SD_CARD; +} + +/*************************************************************************** + * Function : esdhc_emmc_init + * Arguments : mmc - Pointer to mmc struct + * src_emmc - Flag to Indicate SRC as emmc + * Return : SUCCESS or Error Code (< 0) + * Description : Base Function called from sd_mmc_init or emmc_init + ***************************************************************************/ +int esdhc_emmc_init(struct mmc *mmc, bool card_detect) +{ + int error = 0; + int ret = 0; + + error = esdhc_init(mmc, card_detect); + if (error != 0) { + return error; + } + + mmc->card.bus_freq = CARD_IDENTIFICATION_FREQ; + mmc->card.rca = 0; + mmc->card.is_high_capacity = 0; + mmc->card.type = ERROR_ESDHC_UNUSABLE_CARD; + + /* Set Voltage caps as FF8 i.e all supported */ + /* high voltage bits 2.7 - 3.6 */ + mmc->voltages_caps = MMC_OCR_VDD_FF8; + +#ifdef NXP_SD_DMA_CAPABILITY + /* Getting host DMA capabilities. */ + mmc->dma_support = esdhc_in32(&mmc->esdhc_regs->hostcapblt) & + ESDHC_HOSTCAPBLT_DMAS; +#else + mmc->dma_support = 0; +#endif + + ret = NOT_SD_CARD; + /* If SRC is not EMMC, check for SD or MMC */ + ret = check_for_sd_card(mmc); + switch (ret) { + case SD_CARD: + mmc->card.type = SD_CARD; + break; + + case NOT_SD_CARD: + /* try for MMC card */ + if (identify_mmc_card(mmc) == MMC_CARD) { + mmc->card.type = MMC_CARD; + } else { + return ERROR_ESDHC_UNUSABLE_CARD; + } + break; + + default: + return ERROR_ESDHC_UNUSABLE_CARD; + } + + /* get CID, RCA and CSD. For MMC, set the rca */ + error = get_cid_rca_csd(mmc); + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* change state to Transfer mode */ + error = change_state_to_transfer_state(mmc); + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* change to high frequency if supported */ + if (mmc->card.type == SD_CARD) { + error = sd_switch_to_high_freq(mmc); + } else { + error = mmc_switch_to_high_frquency(mmc); + } + if (error != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + /* mmc: 20000000, 26000000, 52000000 */ + /* sd: 25000000, 50000000 */ + set_speed(mmc, mmc->card.bus_freq); + + INFO("init done:\n"); + return 0; +} + +/*************************************************************************** + * Function : sd_mmc_init + * Arguments : mmc - Pointer to mmc struct + * Return : SUCCESS or Error Code + * Description : Base Function called via hal_init for SD/MMC + * initialization + ***************************************************************************/ +int sd_mmc_init(uintptr_t nxp_esdhc_addr, bool card_detect) +{ + struct mmc *mmc = NULL; + int ret; + + mmc = &mmc_drv_data; + memset(mmc, 0, sizeof(struct mmc)); + mmc->esdhc_regs = (struct esdhc_regs *)nxp_esdhc_addr; + + INFO("esdhc_emmc_init\n"); + ret = esdhc_emmc_init(mmc, card_detect); + return ret; +} + +/*************************************************************************** + * Function : esdhc_read_block + * Arguments : mmc - Pointer to mmc struct + * dst - Destination Pointer + * block - Block Number + * Return : SUCCESS or Error Code + * Description : Read a Single block to Destination Pointer + * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen + * 2. Send CMD17 (CMD_READ_SINGLE_BLOCK) with args offset + ***************************************************************************/ +static int esdhc_read_block(struct mmc *mmc, void *dst, uint32_t block) +{ + uint32_t offset; + int err; + + /* send cmd16 to set the block size. */ + err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if (mmc->card.is_high_capacity != 0) { + offset = block; + } else { + offset = block * mmc->card.block_len; + } + + esdhc_set_data_attributes(mmc, dst, 1, mmc->card.block_len); + err = esdhc_send_cmd(mmc, CMD_READ_SINGLE_BLOCK, offset); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return err; + } + + err = esdhc_read_data(mmc, dst, mmc->card.block_len); + + return err; +} + +/*************************************************************************** + * Function : esdhc_write_block + * Arguments : mmc - Pointer to mmc struct + * src - Source Pointer + * block - Block Number + * Return : SUCCESS or Error Code + * Description : Write a Single block from Source Pointer + * 1. Send CMD16 (CMD_SET_BLOCKLEN) with args as blocklen + * 2. Send CMD24 (CMD_WRITE_SINGLE_BLOCK) with args offset + ***************************************************************************/ +static int esdhc_write_block(struct mmc *mmc, void *src, uint32_t block) +{ + uint32_t offset; + int err; + + /* send cmd16 to set the block size. */ + err = esdhc_send_cmd(mmc, CMD_SET_BLOCKLEN, mmc->card.block_len); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return ERROR_ESDHC_COMMUNICATION_ERROR; + } + + if (mmc->card.is_high_capacity != 0) { + offset = block; + } else { + offset = block * mmc->card.block_len; + } + + esdhc_set_data_attributes(mmc, src, 1, mmc->card.block_len); + err = esdhc_send_cmd(mmc, CMD_WRITE_SINGLE_BLOCK, offset); + if (err != 0) { + return err; + } + err = esdhc_wait_response(mmc, NULL); + if (err != 0) { + return err; + } + + err = esdhc_write_data(mmc, src, mmc->card.block_len); + + return err; +} + +/*************************************************************************** + * Function : esdhc_read + * Arguments : src_offset - offset on sd/mmc to read from. Should be block + * size aligned + * dst - Destination Pointer + * size - Length of Data ( Multiple of block size) + * Return : SUCCESS or Error Code + * Description : Calls esdhc_read_block repeatedly for reading the + * data. + ***************************************************************************/ +int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, size_t size) +{ + int error = 0; + uint32_t blk, num_blocks; + uint8_t *buff = (uint8_t *)dst; + +#ifdef NXP_SD_DEBUG + INFO("sd mmc read\n"); + INFO("src = %x, dst = %lxsize = %lu\n", src_offset, dst, size); +#endif + + /* check for size */ + if (size == 0) { + return 0; + } + + if ((size % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + if ((src_offset % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + /* start block */ + blk = src_offset / mmc->card.block_len; +#ifdef NXP_SD_DEBUG + INFO("blk = %x\n", blk); +#endif + + /* Number of blocks to be read */ + num_blocks = size / mmc->card.block_len; + + while (num_blocks) { + error = esdhc_read_block(mmc, buff, blk); + if (error != 0) { + ERROR("Read error = %x\n", error); + return error; + } + + buff = buff + mmc->card.block_len; + blk++; + num_blocks--; + } + + INFO("sd-mmc read done.\n"); + return error; +} + +/*************************************************************************** + * Function : esdhc_write + * Arguments : src - Source Pointer + * dst_offset - offset on sd/mmc to write to. Should be block + * size aligned + * size - Length of Data (Multiple of block size) + * Return : SUCCESS or Error Code + * Description : Calls esdhc_write_block repeatedly for writing the + * data. + ***************************************************************************/ +int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset, + size_t size) +{ + int error = 0; + uint32_t blk, num_blocks; + uint8_t *buff = (uint8_t *)src; + +#ifdef NXP_SD_DEBUG + INFO("sd mmc write\n"); + INFO("src = %x, dst = %lxsize = %lu\n", src, dst_offset, size); +#endif + + /* check for size */ + if (size == 0) { + return 0; + } + + if ((size % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + if ((dst_offset % mmc->card.block_len) != 0) { + ERROR("Size is not block aligned\n"); + return -1; + } + + /* start block */ + blk = dst_offset / mmc->card.block_len; +#ifdef NXP_SD_DEBUG + INFO("blk = %x\n", blk); +#endif + + /* Number of blocks to be written */ + num_blocks = size / mmc->card.block_len; + + while (num_blocks != 0U) { + error = esdhc_write_block(mmc, buff, blk); + if (error != 0U) { + ERROR("Write error = %x\n", error); + return error; + } + + buff = buff + mmc->card.block_len; + blk++; + num_blocks--; + } + + INFO("sd-mmc write done.\n"); + return error; +} + +static size_t ls_sd_emmc_read(int lba, uintptr_t buf, size_t size) +{ + struct mmc *mmc = NULL; + int ret; + + mmc = &mmc_drv_data; + lba *= BLOCK_LEN_512; + ret = esdhc_read(mmc, lba, buf, size); + return ret ? 0 : size; +} + +static struct io_block_dev_spec ls_emmc_dev_spec = { + .buffer = { + .offset = 0, + .length = 0, + }, + .ops = { + .read = ls_sd_emmc_read, + }, + .block_size = BLOCK_LEN_512, +}; + +int sd_emmc_init(uintptr_t *block_dev_spec, + uintptr_t nxp_esdhc_addr, + size_t nxp_sd_block_offset, + size_t nxp_sd_block_size, + bool card_detect) +{ + int ret; + + ret = sd_mmc_init(nxp_esdhc_addr, card_detect); + if (ret != 0) { + return ret; + } + + ls_emmc_dev_spec.buffer.offset = nxp_sd_block_offset; + ls_emmc_dev_spec.buffer.length = nxp_sd_block_size; + *block_dev_spec = (uintptr_t)&ls_emmc_dev_spec; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk new file mode 100644 index 0000000..c83b1bd --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sd/sd_mmc.mk @@ -0,0 +1,26 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_SD_MMC},) + +ADD_SD_MMC := 1 + +SD_MMC_BOOT_SOURCES += ${PLAT_DRIVERS_PATH}/sd/sd_mmc.c \ + drivers/io/io_block.c + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sd + +ifeq (${BL_COMM_SD_MMC_NEEDED},yes) +BL_COMMON_SOURCES += ${SD_MMC_BOOT_SOURCES} +else +ifeq (${BL2_SD_MMC_NEEDED},yes) +BL2_SOURCES += ${SD_MMC_BOOT_SOURCES} +endif +ifeq (${BL3_SD_MMC_NEEDED},yes) +BL31_SOURCES += ${SD_MMC_BOOT_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk b/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk new file mode 100644 index 0000000..aaac53f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sec_mon/sec_mon.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_SNVS},) + +ADD_SNVS := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sec_mon + +SNVS_SOURCES += $(PLAT_DRIVERS_PATH)/sec_mon/snvs.c + +ifeq (${BL_COMM_SNVS_NEEDED},yes) +BL_COMMON_SOURCES += ${SNVS_SOURCES} +else +ifeq (${BL2_SNVS_NEEDED},yes) +BL2_SOURCES += ${SNVS_SOURCES} +endif +ifeq (${BL31_SNVS_NEEDED},yes) +BL31_SOURCES += ${SNVS_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c b/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c new file mode 100644 index 0000000..6208b67 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c @@ -0,0 +1,186 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include + +static uintptr_t g_nxp_snvs_addr; + +void snvs_init(uintptr_t nxp_snvs_addr) +{ + g_nxp_snvs_addr = nxp_snvs_addr; +} + +uint32_t get_snvs_state(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + + return (snvs_read32(&snvs->hp_stat) & HPSTS_MASK_SSM_ST); +} + +static uint32_t do_snvs_state_transition(uint32_t state_transtion_bit, + uint32_t target_state) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + uint32_t fetch_cnt = 16U; + uint32_t val = snvs_read32(&snvs->hp_com) | state_transtion_bit; + + snvs_write32(&snvs->hp_com, val); + + /* polling loop till SNVS is in target state */ + do { + sts = get_snvs_state(); + } while ((sts != target_state) && ((--fetch_cnt) != 0)); + + return sts; +} +void transition_snvs_non_secure(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check or Non-Secure, then + * set the Software Security Violation Bit and + * transition to Non-Secure State. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + break; + + /* If initial state is Trusted, Secure or Soft-Fail, then + * first set the Software Security Violation Bit and + * transition to Soft-Fail State. + */ + case HPSTS_TRUST_SSM_ST: + case HPSTS_SECURE_SSM_ST: + case HPSTS_SOFT_FAIL_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SW_SV, HPSTS_NON_SECURE_SSM_ST); + + /* If SSM Soft Fail to Non-Secure State Transition + * Disable is not set, then set SSM_ST bit and + * transition to Non-Secure State. + */ + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_SFNS_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_NON_SECURE_SSM_ST); + } + break; + default: + break; + } +} + +void transition_snvs_soft_fail(void) +{ + do_snvs_state_transition(HPCOM_SW_FSV, HPSTS_SOFT_FAIL_SSM_ST); +} + +uint32_t transition_snvs_trusted(void) +{ + struct snvs_regs *snvs = (struct snvs_regs *) (g_nxp_snvs_addr); + uint32_t sts = get_snvs_state(); + + switch (sts) { + /* If initial state is check, set the SSM_ST bit to + * change the state to trusted. + */ + case HPSTS_CHECK_SSM_ST: + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + break; + /* If SSM Secure to Trusted State Transition Disable + * is not set, then set SSM_ST bit and + * transition to Trusted State. + */ + case HPSTS_SECURE_SSM_ST: + if ((snvs_read32(&snvs->hp_com) & HPCOM_SSM_ST_DIS) == 0) { + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + } + break; + /* If initial state is Soft-Fail or Non-Secure, then + * transition to Trusted is not Possible. + */ + default: + break; + } + + return sts; +} + +uint32_t transition_snvs_secure(void) +{ + uint32_t sts = get_snvs_state(); + + if (sts == HPSTS_SECURE_SSM_ST) { + return sts; + } + + if (sts != HPSTS_TRUST_SSM_ST) { + sts = transition_snvs_trusted(); + if (sts != HPSTS_TRUST_SSM_ST) { + return sts; + } + } + + sts = do_snvs_state_transition(HPCOM_SSM_ST, HPSTS_TRUST_SSM_ST); + + return sts; +} + +void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val) +{ + if (flag_val) { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + | (1 << bit_pos)); + } else { + snvs_write32(g_nxp_snvs_addr + offset, + (snvs_read32(g_nxp_snvs_addr + offset)) + & ~(1 << bit_pos)); + } +} + +uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos) +{ + return (snvs_read32(g_nxp_snvs_addr + offset) & (1 << bit_pos)); +} + +void snvs_disable_zeroize_lp_gpr(void) +{ + snvs_write_lp_gpr_bit(NXP_LPCR_OFFSET, + NXP_GPR_Z_DIS_BIT, + true); +} + +#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB) +void snvs_write_app_data_bit(uint32_t bit_pos) +{ + snvs_write_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, + bit_pos, + true); +} + +uint32_t snvs_read_app_data(void) +{ + return snvs_read32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET); +} + +uint32_t snvs_read_app_data_bit(uint32_t bit_pos) +{ + uint8_t ret = snvs_read_lp_gpr_bit(NXP_APP_DATA_LP_GPR_OFFSET, bit_pos); + + return ((ret != 0U) ? 1U : 0U); +} + +void snvs_clear_app_data(void) +{ + snvs_write32(g_nxp_snvs_addr + NXP_APP_DATA_LP_GPR_OFFSET, 0x0); +} +#endif diff --git a/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c b/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c new file mode 100644 index 0000000..165474f --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c @@ -0,0 +1,462 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + + +static int write_a_fuse(uint32_t *fuse_addr, uint32_t *fuse_hdr_val, + uint32_t mask) +{ + uint32_t last_stored_val = sfp_read32(fuse_addr); + + /* Check if fuse already blown or not */ + if ((last_stored_val & mask) == mask) { + return ERROR_ALREADY_BLOWN; + } + + /* Write fuse in mirror registers */ + sfp_write32(fuse_addr, last_stored_val | (*fuse_hdr_val & mask)); + + /* Read back to check if write success */ + if (sfp_read32(fuse_addr) != (last_stored_val | (*fuse_hdr_val & mask))) { + return ERROR_WRITE; + } + + return 0; +} + +static int write_fuses(uint32_t *fuse_addr, uint32_t *fuse_hdr_val, uint8_t len) +{ + int i; + + /* Check if fuse already blown or not */ + for (i = 0; i < len; i++) { + if (sfp_read32(&fuse_addr[i]) != 0) { + return ERROR_ALREADY_BLOWN; + } + } + + /* Write fuse in mirror registers */ + for (i = 0; i < len; i++) { + sfp_write32(&fuse_addr[i], fuse_hdr_val[i]); + } + + /* Read back to check if write success */ + for (i = 0; i < len; i++) { + if (sfp_read32(&fuse_addr[i]) != fuse_hdr_val[i]) { + return ERROR_WRITE; + } + } + + return 0; +} + +/* + * This function program Super Root Key Hash (SRKH) in fuse + * registers. + */ +static int prog_srkh(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret = 0; + + ret = write_fuses(sfp_ccsr_regs->srk_hash, fuse_hdr->srkh, 8); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_SRKH_ALREADY_BLOWN : ERROR_SRKH_WRITE; + } + + return ret; +} + +/* This function program OEMUID[0-4] in fuse registers. */ +static int prog_oemuid(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int i, ret = 0; + + for (i = 0; i < 5; i++) { + /* Check OEMUIDx to be blown or not */ + if (((fuse_hdr->flags >> (FLAG_OUID0_SHIFT + i)) & 0x1) != 0) { + /* Check if OEMUID[i] already blown or not */ + ret = write_fuses(&sfp_ccsr_regs->oem_uid[i], + &fuse_hdr->oem_uid[i], 1); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OEMUID_ALREADY_BLOWN + : ERROR_OEMUID_WRITE; + } + } + } + return ret; +} + +/* This function program DCV[0-1], DRV[0-1] in fuse registers. */ +static int prog_debug(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + + /* Check DCV to be blown or not */ + if (((fuse_hdr->flags >> (FLAG_DCV0_SHIFT)) & 0x3) != 0) { + /* Check if DCV[i] already blown or not */ + ret = write_fuses(sfp_ccsr_regs->dcv, fuse_hdr->dcv, 2); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_DCV_ALREADY_BLOWN + : ERROR_DCV_WRITE; + } + } + + /* Check DRV to be blown or not */ + if ((((fuse_hdr->flags >> (FLAG_DRV0_SHIFT)) & 0x3)) != 0) { + /* Check if DRV[i] already blown or not */ + ret = write_fuses(sfp_ccsr_regs->drv, fuse_hdr->drv, 2); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_DRV_ALREADY_BLOWN + : ERROR_DRV_WRITE; + } else { + /* Check for DRV hamming error */ + if (sfp_read32((void *)(get_sfp_addr() + + SFP_SVHESR_OFFSET)) + & SFP_SVHESR_DRV_MASK) { + return ERROR_DRV_HAMMING_ERROR; + } + } + } + + return 0; +} + + /* + * Turn a 256-bit random value (32 bytes) into an OTPMK code word + * modifying the input data array in place + */ +static void otpmk_make_code_word_256(uint8_t *otpmk, bool minimal_flag) +{ + int i; + uint8_t parity_bit; + uint8_t code_bit; + + if (minimal_flag == true) { + /* + * Force bits 252, 253, 254 and 255 to 1 + * This is because these fuses may have already been blown + * and the OTPMK cannot force them back to 0 + */ + otpmk[252/8] |= (1 << (252%8)); + otpmk[253/8] |= (1 << (253%8)); + otpmk[254/8] |= (1 << (254%8)); + otpmk[255/8] |= (1 << (255%8)); + } + + /* Generate the hamming code for the code word */ + parity_bit = 0; + code_bit = 0; + for (i = 0; i < 256; i += 1) { + if ((otpmk[i/8] & (1 << (i%8))) != 0) { + parity_bit ^= 1; + code_bit ^= i; + } + } + + /* Inverting otpmk[code_bit] will cause the otpmk + * to become a valid code word (except for overall parity) + */ + if (code_bit < 252) { + otpmk[code_bit/8] ^= (1 << (code_bit % 8)); + parity_bit ^= 1; // account for flipping a bit changing parity + } else { + /* Invert two bits: (code_bit - 4) and 4 + * Because we invert two bits, no need to touch the parity bit + */ + otpmk[(code_bit - 4)/8] ^= (1 << ((code_bit - 4) % 8)); + otpmk[4/8] ^= (1 << (4 % 8)); + } + + /* Finally, adjust the overall parity of the otpmk + * otpmk bit 0 + */ + otpmk[0] ^= parity_bit; +} + +/* This function program One Time Programmable Master Key (OTPMK) + * in fuse registers. + */ +static int prog_otpmk(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret = 0; + uint32_t otpmk_flags; + uint32_t otpmk_random[8] __aligned(CACHE_WRITEBACK_GRANULE); + + otpmk_flags = (fuse_hdr->flags >> (FLAG_OTPMK_SHIFT)) & FLAG_OTPMK_MASK; + + switch (otpmk_flags) { + case PROG_OTPMK_MIN: + memset(fuse_hdr->otpmk, 0, sizeof(fuse_hdr->otpmk)); + + /* Minimal OTPMK value (252-255 bits set to 1) */ + fuse_hdr->otpmk[0] |= OTPMK_MIM_BITS_MASK; + break; + + case PROG_OTPMK_RANDOM: + if (is_sec_enabled() == false) { + ret = ERROR_OTPMK_SEC_DISABLED; + goto out; + } + + /* Generate Random number using CAAM for OTPMK */ + memset(otpmk_random, 0, sizeof(otpmk_random)); + if (get_rand_bytes_hw((uint8_t *)otpmk_random, + sizeof(otpmk_random)) != 0) { + ret = ERROR_OTPMK_SEC_ERROR; + goto out; + } + + /* Run hamming over random no. to make OTPMK */ + otpmk_make_code_word_256((uint8_t *)otpmk_random, false); + + /* Swap OTPMK */ + fuse_hdr->otpmk[0] = otpmk_random[7]; + fuse_hdr->otpmk[1] = otpmk_random[6]; + fuse_hdr->otpmk[2] = otpmk_random[5]; + fuse_hdr->otpmk[3] = otpmk_random[4]; + fuse_hdr->otpmk[4] = otpmk_random[3]; + fuse_hdr->otpmk[5] = otpmk_random[2]; + fuse_hdr->otpmk[6] = otpmk_random[1]; + fuse_hdr->otpmk[7] = otpmk_random[0]; + break; + + case PROG_OTPMK_USER: + break; + + case PROG_OTPMK_RANDOM_MIN: + /* Here assumption is that user is aware of minimal OTPMK + * already blown. + */ + + /* Generate Random number using CAAM for OTPMK */ + if (is_sec_enabled() == false) { + ret = ERROR_OTPMK_SEC_DISABLED; + goto out; + } + + memset(otpmk_random, 0, sizeof(otpmk_random)); + if (get_rand_bytes_hw((uint8_t *)otpmk_random, + sizeof(otpmk_random)) != 0) { + ret = ERROR_OTPMK_SEC_ERROR; + goto out; + } + + /* Run hamming over random no. to make OTPMK */ + otpmk_make_code_word_256((uint8_t *)otpmk_random, true); + + /* Swap OTPMK */ + fuse_hdr->otpmk[0] = otpmk_random[7]; + fuse_hdr->otpmk[1] = otpmk_random[6]; + fuse_hdr->otpmk[2] = otpmk_random[5]; + fuse_hdr->otpmk[3] = otpmk_random[4]; + fuse_hdr->otpmk[4] = otpmk_random[3]; + fuse_hdr->otpmk[5] = otpmk_random[2]; + fuse_hdr->otpmk[6] = otpmk_random[1]; + fuse_hdr->otpmk[7] = otpmk_random[0]; + break; + + case PROG_OTPMK_USER_MIN: + /* + * Here assumption is that user is aware of minimal OTPMK + * already blown. Check if minimal bits are set in user + * supplied OTPMK. + */ + if ((fuse_hdr->otpmk[0] & OTPMK_MIM_BITS_MASK) != + OTPMK_MIM_BITS_MASK) { + ret = ERROR_OTPMK_USER_MIN; + goto out; + } + break; + + default: + ret = 0; + goto out; + } + + ret = write_fuses(sfp_ccsr_regs->otpmk, fuse_hdr->otpmk, 8); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OTPMK_ALREADY_BLOWN + : ERROR_OTPMK_WRITE; + } else { + /* Check for DRV hamming error */ + if ((sfp_read32((void *)(get_sfp_addr() + SFP_SVHESR_OFFSET)) + & SFP_SVHESR_OTPMK_MASK) != 0) { + ret = ERROR_OTPMK_HAMMING_ERROR; + } + } + +out: + return ret; +} + +/* This function program OSPR1 in fuse registers. + */ +static int prog_ospr1(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + uint32_t mask = 0; + +#ifdef NXP_SFP_VER_3_4 + if (((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) { + mask = OSPR1_MC_MASK; + } +#endif + if (((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0) { + mask = mask | OSPR1_DBG_LVL_MASK; + } + + ret = write_a_fuse(&sfp_ccsr_regs->ospr1, &fuse_hdr->ospr1, mask); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_OSPR1_ALREADY_BLOWN + : ERROR_OSPR1_WRITE; + } + + return ret; +} + +/* This function program SYSCFG in fuse registers. + */ +static int prog_syscfg(struct fuse_hdr_t *fuse_hdr, + struct sfp_ccsr_regs_t *sfp_ccsr_regs) +{ + int ret; + + /* Check if SYSCFG already blown or not */ + ret = write_a_fuse(&sfp_ccsr_regs->ospr, &fuse_hdr->sc, OSPR0_SC_MASK); + + if (ret != 0) { + ret = (ret == ERROR_ALREADY_BLOWN) ? + ERROR_SC_ALREADY_BLOWN + : ERROR_SC_WRITE; + } + + return ret; +} + +/* This function does fuse provisioning. + */ +int provision_fuses(unsigned long long fuse_scr_addr, + bool en_povdd_status) +{ + struct fuse_hdr_t *fuse_hdr = NULL; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(get_sfp_addr() + + SFP_FUSE_REGS_OFFSET); + int ret = 0; + + fuse_hdr = (struct fuse_hdr_t *)fuse_scr_addr; + + /* + * Check for Write Protect (WP) fuse. If blown then do + * no fuse provisioning. + */ + if ((sfp_read32(&sfp_ccsr_regs->ospr) & 0x1) != 0) { + goto out; + } + + /* Check if SRKH to be blown or not */ + if (((fuse_hdr->flags >> FLAG_SRKH_SHIFT) & 0x1) != 0) { + INFO("Fuse: Program SRKH\n"); + ret = prog_srkh(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if OEMUID to be blown or not */ + if (((fuse_hdr->flags >> FLAG_OUID0_SHIFT) & FLAG_OUID_MASK) != 0) { + INFO("Fuse: Program OEMUIDs\n"); + ret = prog_oemuid(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if Debug values to be blown or not */ + if (((fuse_hdr->flags >> FLAG_DCV0_SHIFT) & FLAG_DEBUG_MASK) != 0) { + INFO("Fuse: Program Debug values\n"); + ret = prog_debug(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if OTPMK values to be blown or not */ + if (((fuse_hdr->flags >> FLAG_OTPMK_SHIFT) & PROG_NO_OTPMK) != + PROG_NO_OTPMK) { + INFO("Fuse: Program OTPMK\n"); + ret = prog_otpmk(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + + /* Check if MC or DBG LVL to be blown or not */ + if ((((fuse_hdr->flags >> FLAG_MC_SHIFT) & 0x1) != 0) || + (((fuse_hdr->flags >> FLAG_DBG_LVL_SHIFT) & 0x1) != 0)) { + INFO("Fuse: Program OSPR1\n"); + ret = prog_ospr1(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + /* Check if SYSCFG to be blown or not */ + if (((fuse_hdr->flags >> FLAG_SYSCFG_SHIFT) & 0x1) != 0) { + INFO("Fuse: Program SYSCFG\n"); + ret = prog_syscfg(fuse_hdr, sfp_ccsr_regs); + if (ret != 0) { + error_handler(ret); + goto out; + } + } + + if (en_povdd_status) { + ret = sfp_program_fuses(); + if (ret != 0) { + error_handler(ret); + goto out; + } + } +out: + return ret; +} diff --git a/arm-trusted-firmware/drivers/nxp/sfp/sfp.c b/arm-trusted-firmware/drivers/nxp/sfp/sfp.c new file mode 100644 index 0000000..e06c6b9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/sfp.c @@ -0,0 +1,167 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static uintptr_t g_nxp_sfp_addr; +static uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)] + __aligned(CACHE_WRITEBACK_GRANULE); + +void sfp_init(uintptr_t nxp_sfp_addr) +{ + g_nxp_sfp_addr = nxp_sfp_addr; +} + +uintptr_t get_sfp_addr(void) +{ + return g_nxp_sfp_addr; +} + +uint32_t *get_sfp_srk_hash(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = + (void *) (g_nxp_sfp_addr + SFP_FUSE_REGS_OFFSET); + int i = 0; + + /* Add comparison of hash with SFP hash here */ + for (i = 0; i < SRK_HASH_SIZE/sizeof(uint32_t); i++) + srk_hash[i] = + mmio_read_32((uintptr_t)&sfp_ccsr_regs->srk_hash[i]); + + return srk_hash; +} + +void set_sfp_wr_disable(void) +{ + /* + * Mark SFP Write Disable and Write Disable Lock + * Bit to prevent write to SFP fuses like + * OUID's, Key Revocation fuse etc + */ + void *sfpcr = (void *)(g_nxp_sfp_addr + SFP_SFPCR_OFFSET); + uint32_t sfpcr_val; + + sfpcr_val = sfp_read32(sfpcr); + sfpcr_val |= (SFP_SFPCR_WD | SFP_SFPCR_WDL); + sfp_write32(sfpcr, sfpcr_val); +} + +int sfp_program_fuses(void) +{ + uint32_t ingr; + uint32_t sfp_cmd_status = 0U; + int ret = 0; + + /* Program SFP fuses from mirror registers */ + sfp_write32((void *)(g_nxp_sfp_addr + SFP_INGR_OFFSET), + SFP_INGR_PROGFB_CMD); + + /* Wait until fuse programming is successful */ + do { + ingr = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET); + } while (ingr & SFP_INGR_PROGFB_CMD); + + /* Check for SFP fuse programming error */ + sfp_cmd_status = sfp_read32(g_nxp_sfp_addr + SFP_INGR_OFFSET) + & SFP_INGR_ERROR_MASK; + + if (sfp_cmd_status != 0U) { + return ERROR_PROGFB_CMD; + } + + return ret; +} + +uint32_t sfp_read_oem_uid(uint8_t oem_uid) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if (oem_uid > MAX_OEM_UID) { + ERROR("Invalid OEM UID received.\n"); + return ERROR_OEMUID_WRITE; + } + + val = sfp_read32(&sfp_ccsr_regs->oem_uid[oem_uid]); + + return val; +} + +/* + * return val: 0 - No update required. + * 1 - successful update done. + * ERROR_OEMUID_WRITE - Invalid OEM UID + */ +uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val) +{ + uint32_t val = 0U; + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + val = sfp_read_oem_uid(oem_uid); + + if (val == ERROR_OEMUID_WRITE) { + return ERROR_OEMUID_WRITE; + } + + /* Counter already set. No need to do anything */ + if ((val & sfp_val) != 0U) { + return 0U; + } + + val |= sfp_val; + + INFO("SFP Value is %x for setting sfp_val = %d\n", val, sfp_val); + + sfp_write32(&sfp_ccsr_regs->oem_uid[oem_uid], val); + + return 1U; +} + +int sfp_check_its(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_ITS_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +int sfp_check_oem_wp(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + if ((sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_WP_MASK) != 0) { + return 1; + } else { + return 0; + } +} + +/* This function returns ospr's key_revoc values.*/ +uint32_t get_key_revoc(void) +{ + struct sfp_ccsr_regs_t *sfp_ccsr_regs = (void *)(g_nxp_sfp_addr + + SFP_FUSE_REGS_OFFSET); + + return (sfp_read32(&sfp_ccsr_regs->ospr) & OSPR_KEY_REVOC_MASK) >> + OSPR_KEY_REVOC_SHIFT; +} diff --git a/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk b/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk new file mode 100644 index 0000000..de708c5 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/sfp/sfp.mk @@ -0,0 +1,33 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +#----------------------------------------------------------------------------- +ifeq (${SFP_ADDED},) + +SFP_ADDED := 1 +$(eval $(call add_define, NXP_SFP_ENABLED)) + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/sfp + +SFP_SOURCES += $(PLAT_DRIVERS_PATH)/sfp/sfp.c + +ifeq (${FUSE_PROG}, 1) +SFP_BL2_SOURCES += $(PLAT_DRIVERS_PATH)/sfp/fuse_prov.c +endif + +ifeq (${BL_COMM_SFP_NEEDED},yes) +BL_COMMON_SOURCES += ${SFP_SOURCES} +BL2_SOURCES += ${SFP_BL2_SOURCES} +else +ifeq (${BL2_SFP_NEEDED},yes) +BL2_SOURCES += ${SFP_SOURCES}\ + ${SFP_BL2_SOURCES} +endif +ifeq (${BL31_SFP_NEEDED},yes) +BL31_SOURCES += ${SFP_SOURCES} +endif +endif +endif +#------------------------------------------------ diff --git a/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c b/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c new file mode 100644 index 0000000..8eecd2e --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c @@ -0,0 +1,143 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +static uintptr_t g_nxp_timer_addr; +static timer_ops_t ops; + +uint64_t get_timer_val(uint64_t start) +{ + uint64_t cntpct; + + isb(); + cntpct = read_cntpct_el0(); + return (cntpct * 1000ULL / read_cntfrq_el0() - start); +} + +static uint32_t timer_get_value(void) +{ + uint64_t cntpct; + + isb(); + cntpct = read_cntpct_el0(); +#ifdef ERRATA_SOC_A008585 + uint8_t max_fetch_count = 10U; + /* This erratum number needs to be confirmed to match ARM document */ + uint64_t temp; + + isb(); + temp = read_cntpct_el0(); + + while (temp != cntpct && max_fetch_count) { + isb(); + cntpct = read_cntpct_el0(); + isb(); + temp = read_cntpct_el0(); + max_fetch_count--; + } +#endif + + /* + * 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)(~cntpct); +} + +static void delay_timer_init_args(uint32_t mult, uint32_t div) +{ + ops.get_timer_value = timer_get_value, + ops.clk_mult = mult; + ops.clk_div = div; + + timer_init(&ops); + + VERBOSE("Generic delay timer configured with mult=%u and div=%u\n", + mult, div); +} + +/* + * Initialise the nxp on-chip free rolling usec counter as the delay + * timer. + */ +void delay_timer_init(uintptr_t nxp_timer_addr) +{ + /* Value in ticks */ + unsigned int mult = MHZ_TICKS_PER_SEC; + + unsigned int div; + + unsigned int counter_base_frequency = plat_get_syscnt_freq2(); + + g_nxp_timer_addr = nxp_timer_addr; + /* Rounding off the Counter Frequency to MHZ_TICKS_PER_SEC */ + if (counter_base_frequency > MHZ_TICKS_PER_SEC) { + counter_base_frequency = (counter_base_frequency + / MHZ_TICKS_PER_SEC) + * MHZ_TICKS_PER_SEC; + } else { + counter_base_frequency = (counter_base_frequency + / KHZ_TICKS_PER_SEC) + * KHZ_TICKS_PER_SEC; + } + + /* Value in ticks per second (Hz) */ + div = counter_base_frequency; + + /* Reduce multiplier and divider by dividing them repeatedly by 10 */ + while ((mult % 10U == 0U) && (div % 10U == 0U)) { + mult /= 10U; + div /= 10U; + } + + /* Enable and initialize the System level generic timer */ + mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_EN); + + delay_timer_init_args(mult, div); +} + + +#ifdef IMAGE_BL31 +/******************************************************************************* + * TBD: Configures access to the system counter timer module. + ******************************************************************************/ +void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, + uint8_t ls_config_cntacr, + uint8_t plat_ls_ns_timer_frame_id) +{ + unsigned int reg_val; + + if (ls_config_cntacr == 1U) { + 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(ls_sys_timctl_base + + CNTACR_BASE(plat_ls_ns_timer_frame_id), reg_val); + mmio_write_32(ls_sys_timctl_base, plat_get_syscnt_freq2()); + } + + reg_val = (1U << CNTNSAR_NS_SHIFT(plat_ls_ns_timer_frame_id)); + mmio_write_32(ls_sys_timctl_base + CNTNSAR, reg_val); +} + +void enable_init_timer(void) +{ + /* Enable and initialize the System level generic timer */ + mmio_write_32(g_nxp_timer_addr + CNTCR_OFF, + CNTCR_FCREQ(0) | CNTCR_EN); +} +#endif diff --git a/arm-trusted-firmware/drivers/nxp/timer/timer.mk b/arm-trusted-firmware/drivers/nxp/timer/timer.mk new file mode 100644 index 0000000..d658d19 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/timer/timer.mk @@ -0,0 +1,25 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_TIMER},) + +ADD_TIMER := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/timer +TIMER_SOURCES += drivers/delay_timer/delay_timer.c \ + $(PLAT_DRIVERS_PATH)/timer/nxp_timer.c + +ifeq (${BL_COMM_TIMER_NEEDED},yes) +BL_COMMON_SOURCES += ${TIMER_SOURCES} +else +ifeq (${BL2_TIMER_NEEDED},yes) +BL2_SOURCES += ${TIMER_SOURCES} +endif +ifeq (${BL31_TIMER_NEEDED},yes) +BL31_SOURCES += ${TIMER_SOURCES} +endif +endif +endif diff --git a/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c new file mode 100644 index 0000000..13cf3b9 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#pragma weak populate_tzc380_reg_list + +#ifdef DEFAULT_TZASC_CONFIG +/* + * Typical Memory map of DRAM0 + * |-----------NXP_NS_DRAM_ADDR ( = NXP_DRAM0_ADDR)----------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * | | + * |------- (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE - 1) -------| + * |-----------------NXP_SECURE_DRAM_ADDR--------------------| + * | | + * | | + * | | + * | SECURE REGION (= 64MB) | + * | | + * | | + * | | + * |--- (NXP_SECURE_DRAM_ADDR + NXP_SECURE_DRAM_SIZE - 1)----| + * |-----------------NXP_SP_SHRD_DRAM_ADDR-------------------| + * | | + * | Secure EL1 Payload SHARED REGION (= 2MB) | + * | | + * |-----------(NXP_DRAM0_ADDR + NXP_DRAM0_SIZE - 1)---------| + * + * + * + * Typical Memory map of DRAM1 + * |---------------------NXP_DRAM1_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM1_ADDR + Dynamically calculated Size - 1) ---| + * + * + * Typical Memory map of DRAM2 + * |---------------------NXP_DRAM2_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM2_ADDR + Dynamically calculated Size - 1) ---| + */ + +/***************************************************************************** + * This function sets up access permissions on memory regions + * + * Input: + * tzc380_reg_list : TZC380 Region List + * dram_idx : DRAM index + * list_idx : TZC380 Region List Index + * dram_start_addr : Start address of DRAM at dram_idx. + * dram_size : Size of DRAM at dram_idx. + * secure_dram_sz : Secure DRAM Size + * shrd_dram_sz : Shared DRAM Size + * + * Out: + * list_idx : last populated index + 1 + * + ****************************************************************************/ +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + /* Region 0: Default region marked as Non-Secure */ + if (list_idx == 0) { + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_NS_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_DISABLE; + tzc380_reg_list[list_idx].addr = UL(0x0); + tzc380_reg_list[list_idx].size = 0x0; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + } + /* Continue with list entries for index > 0 */ + if (dram_idx == 0) { + /* TZC Region 1 on DRAM0 for Secure Memory*/ + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_S_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_ENABLE; + tzc380_reg_list[list_idx].addr = dram_start_addr + dram_size; + tzc380_reg_list[list_idx].size = secure_dram_sz; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + + /* TZC Region 2 on DRAM0 for Shared Memory*/ + tzc380_reg_list[list_idx].secure = TZC_ATTR_SP_S_RW; + tzc380_reg_list[list_idx].enabled = TZC_ATTR_REGION_ENABLE; + tzc380_reg_list[list_idx].addr = dram_start_addr + dram_size + secure_dram_sz; + tzc380_reg_list[list_idx].size = shrd_dram_sz; + tzc380_reg_list[list_idx].sub_mask = 0x0; /* all enabled */ + list_idx++; + + } + + return list_idx; +} +#else +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + ERROR("tzc380_reg_list used is not a default list\n"); + ERROR("%s needs to be over-written.\n", __func__); + return 0; +} +#endif /* DEFAULT_TZASC_CONFIG */ + + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc380_reg *tzc380_reg_list) +{ + uint32_t indx = 0; + unsigned int attr_value; + + VERBOSE("Configuring TrustZone Controller tzc380\n"); + + tzc380_init(base); + + tzc380_set_action(TZC_ACTION_NONE); + + for (indx = 0; indx < total_regions; indx++) { + attr_value = tzc380_reg_list[indx].secure | + TZC_ATTR_SUBREG_DIS(tzc380_reg_list[indx].sub_mask) | + TZC_ATTR_REGION_SIZE(tzc380_reg_list[indx].size) | + tzc380_reg_list[indx].enabled; + + tzc380_configure_region(indx, tzc380_reg_list[indx].addr, + attr_value); + } + + tzc380_set_action(TZC_ACTION_ERR); +} diff --git a/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c new file mode 100644 index 0000000..4fe5221 --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c @@ -0,0 +1,187 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +#pragma weak populate_tzc400_reg_list + +#ifdef DEFAULT_TZASC_CONFIG +/* + * Typical Memory map of DRAM0 + * |-----------NXP_NS_DRAM_ADDR ( = NXP_DRAM0_ADDR)----------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * | | + * |------- (NXP_NS_DRAM_ADDR + NXP_NS_DRAM_SIZE - 1) -------| + * |-----------------NXP_SECURE_DRAM_ADDR--------------------| + * | | + * | | + * | | + * | SECURE REGION (= 64MB) | + * | | + * | | + * | | + * |--- (NXP_SECURE_DRAM_ADDR + NXP_SECURE_DRAM_SIZE - 1)----| + * |-----------------NXP_SP_SHRD_DRAM_ADDR-------------------| + * | | + * | Secure EL1 Payload SHARED REGION (= 2MB) | + * | | + * |-----------(NXP_DRAM0_ADDR + NXP_DRAM0_SIZE - 1)---------| + * + * + * + * Typical Memory map of DRAM1 + * |---------------------NXP_DRAM1_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM1_ADDR + Dynamically calculated Size - 1) ---| + * + * + * Typical Memory map of DRAM2 + * |---------------------NXP_DRAM2_ADDR----------------------| + * | | + * | | + * | Non-SECURE REGION | + * | | + * | | + * |---(NXP_DRAM2_ADDR + Dynamically calculated Size - 1) ---| + */ + +/***************************************************************************** + * This function sets up access permissions on memory regions + * + * Input: + * tzc400_reg_list : TZC400 Region List + * dram_idx : DRAM index + * list_idx : TZC400 Region List Index + * dram_start_addr : Start address of DRAM at dram_idx. + * dram_size : Size of DRAM at dram_idx. + * secure_dram_sz : Secure DRAM Size + * shrd_dram_sz : Shared DRAM Size + * + * Out: + * list_idx : last populated index + 1 + * + ****************************************************************************/ +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + if (list_idx == 0) { + /* No need to configure TZC Region 0 in this list. + */ + list_idx++; + } + /* Continue with list entries for index > 0 */ + if (dram_idx == 0) { + /* TZC Region 1 on DRAM0 for Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + + secure_dram_sz - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_REGION_NS_NONE; + list_idx++; + + /* TZC Region 2 on DRAM0 for Shared Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr + dram_size + + secure_dram_sz; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + + secure_dram_sz + + shrd_dram_sz + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + + /* TZC Region 3 on DRAM0 for Non-Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + } else { + /* TZC Region 3+i on DRAM(> 0) for Non-Secure Memory*/ + tzc400_reg_list[list_idx].reg_filter_en = 1; + tzc400_reg_list[list_idx].start_addr = dram_start_addr; + tzc400_reg_list[list_idx].end_addr = dram_start_addr + dram_size + - 1; + tzc400_reg_list[list_idx].sec_attr = TZC_REGION_S_RDWR; + tzc400_reg_list[list_idx].nsaid_permissions = TZC_NS_ACCESS_ID; + list_idx++; + } + + return list_idx; +} +#else +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz) +{ + ERROR("tzc400_reg_list used is not a default list\n"); + ERROR("%s needs to be over-written.\n", __func__); + return 0; +} +#endif /* DEFAULT_TZASC_CONFIG */ + +/******************************************************************************* + * Configure memory access permissions + * - Region 0 with no access; + * - Region 1 to 4 as per the tzc400_reg_list populated by + * function populate_tzc400_reg_list() with default for all the SoC. + ******************************************************************************/ +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc400_reg *tzc400_reg_list) +{ + uint32_t list_indx = 0U; + + INFO("Configuring TrustZone Controller\n"); + + tzc400_init(base); + + /* Disable filters. */ + tzc400_disable_filters(); + + /* Region 0 set to no access by default */ + tzc400_configure_region0(TZC_REGION_S_NONE, 0U); + + for (list_indx = 1U; list_indx < total_regions; list_indx++) { + tzc400_configure_region( + tzc400_reg_list[list_indx].reg_filter_en, + list_indx, + tzc400_reg_list[list_indx].start_addr, + tzc400_reg_list[list_indx].end_addr, + tzc400_reg_list[list_indx].sec_attr, + tzc400_reg_list[list_indx].nsaid_permissions); + } + + /* + * 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(); +} diff --git a/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk b/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk new file mode 100644 index 0000000..4418bfc --- /dev/null +++ b/arm-trusted-firmware/drivers/nxp/tzc/tzc.mk @@ -0,0 +1,40 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ADD_TZASC},) + +ADD_TZASC := 1 + +PLAT_INCLUDES += -I$(PLAT_DRIVERS_INCLUDE_PATH)/tzc + +ifeq ($(TZC_ID), TZC400) +TZASC_SOURCES += drivers/arm/tzc/tzc400.c\ + $(PLAT_DRIVERS_PATH)/tzc/plat_tzc400.c +else +ifeq ($(TZC_ID), TZC380) +TZASC_SOURCES += drivers/arm/tzc/tzc380.c\ + $(PLAT_DRIVERS_PATH)/tzc/plat_tzc380.c +else +ifeq ($(TZC_ID), NONE) + $(info -> No TZC present on platform) +else + $(error -> TZC type not set!) +endif +endif +endif + +ifeq (${BL_COMM_TZASC_NEEDED},yes) +BL_COMMON_SOURCES += ${TZASC_SOURCES} +else +ifeq (${BL2_TZASC_NEEDED},yes) +BL2_SOURCES += ${TZASC_SOURCES} +endif +ifeq (${BL31_TZASC_NEEDED},yes) +BL31_SOURCES += ${TZASC_SOURCES} +endif +endif + +endif diff --git a/arm-trusted-firmware/drivers/partition/gpt.c b/arm-trusted-firmware/drivers/partition/gpt.c new file mode 100644 index 0000000..ee0bddf --- /dev/null +++ b/arm-trusted-firmware/drivers/partition/gpt.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +static int unicode_to_ascii(unsigned short *str_in, unsigned char *str_out) +{ + uint8_t *name; + int i; + + assert((str_in != NULL) && (str_out != NULL)); + + name = (uint8_t *)str_in; + + assert(name[0] != '\0'); + + /* check whether the unicode string is valid */ + for (i = 1; i < (EFI_NAMELEN << 1); i += 2) { + if (name[i] != '\0') + return -EINVAL; + } + /* convert the unicode string to ascii string */ + for (i = 0; i < (EFI_NAMELEN << 1); i += 2) { + str_out[i >> 1] = name[i]; + if (name[i] == '\0') + break; + } + return 0; +} + +int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry) +{ + int result; + + assert((gpt_entry != NULL) && (entry != NULL)); + + if ((gpt_entry->first_lba == 0) && (gpt_entry->last_lba == 0)) { + return -EINVAL; + } + + zeromem(entry, sizeof(partition_entry_t)); + result = unicode_to_ascii(gpt_entry->name, (uint8_t *)entry->name); + if (result != 0) { + return result; + } + entry->start = (uint64_t)gpt_entry->first_lba * + PLAT_PARTITION_BLOCK_SIZE; + entry->length = (uint64_t)(gpt_entry->last_lba - + gpt_entry->first_lba + 1) * + PLAT_PARTITION_BLOCK_SIZE; + guidcpy(&entry->part_guid, &gpt_entry->unique_uuid); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/partition/partition.c b/arm-trusted-firmware/drivers/partition/partition.c new file mode 100644 index 0000000..7706f88 --- /dev/null +++ b/arm-trusted-firmware/drivers/partition/partition.c @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static uint8_t mbr_sector[PLAT_PARTITION_BLOCK_SIZE]; +static partition_entry_list_t list; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +static void dump_entries(int num) +{ + char name[EFI_NAMELEN]; + int i, j, len; + + VERBOSE("Partition table with %d entries:\n", num); + for (i = 0; i < num; i++) { + len = snprintf(name, EFI_NAMELEN, "%s", list.list[i].name); + for (j = 0; j < EFI_NAMELEN - len - 1; j++) { + name[len + j] = ' '; + } + name[EFI_NAMELEN - 1] = '\0'; + VERBOSE("%d: %s %" PRIx64 "-%" PRIx64 "\n", i + 1, name, list.list[i].start, + list.list[i].start + list.list[i].length - 4); + } +} +#else +#define dump_entries(num) ((void)num) +#endif + +/* + * Load the first sector that carries MBR header. + * The MBR boot signature should be always valid whether it's MBR or GPT. + */ +static int load_mbr_header(uintptr_t image_handle, mbr_entry_t *mbr_entry) +{ + size_t bytes_read; + uintptr_t offset; + int result; + + assert(mbr_entry != NULL); + /* MBR partition table is in LBA0. */ + result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); + if (result != 0) { + WARN("Failed to seek (%i)\n", result); + return result; + } + result = io_read(image_handle, (uintptr_t)&mbr_sector, + PLAT_PARTITION_BLOCK_SIZE, &bytes_read); + if (result != 0) { + WARN("Failed to read data (%i)\n", result); + return result; + } + + /* Check MBR boot signature. */ + if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || + (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + return -ENOENT; + } + offset = (uintptr_t)&mbr_sector + MBR_PRIMARY_ENTRY_OFFSET; + memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); + return 0; +} + +/* + * Load GPT header and check the GPT signature. + * If partition numbers could be found, check & update it. + */ +static int load_gpt_header(uintptr_t image_handle) +{ + gpt_header_t header; + size_t bytes_read; + int result; + + result = io_seek(image_handle, IO_SEEK_SET, GPT_HEADER_OFFSET); + if (result != 0) { + return result; + } + result = io_read(image_handle, (uintptr_t)&header, + sizeof(gpt_header_t), &bytes_read); + if ((result != 0) || (sizeof(gpt_header_t) != bytes_read)) { + return result; + } + if (memcmp(header.signature, GPT_SIGNATURE, + sizeof(header.signature)) != 0) { + return -EINVAL; + } + + /* partition numbers can't exceed PLAT_PARTITION_MAX_ENTRIES */ + list.entry_count = header.list_num; + if (list.entry_count > PLAT_PARTITION_MAX_ENTRIES) { + list.entry_count = PLAT_PARTITION_MAX_ENTRIES; + } + return 0; +} + +static int load_mbr_entry(uintptr_t image_handle, mbr_entry_t *mbr_entry, + int part_number) +{ + size_t bytes_read; + uintptr_t offset; + int result; + + assert(mbr_entry != NULL); + /* MBR partition table is in LBA0. */ + result = io_seek(image_handle, IO_SEEK_SET, MBR_OFFSET); + if (result != 0) { + WARN("Failed to seek (%i)\n", result); + return result; + } + result = io_read(image_handle, (uintptr_t)&mbr_sector, + PLAT_PARTITION_BLOCK_SIZE, &bytes_read); + if (result != 0) { + WARN("Failed to read data (%i)\n", result); + return result; + } + + /* Check MBR boot signature. */ + if ((mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 2] != MBR_SIGNATURE_FIRST) || + (mbr_sector[LEGACY_PARTITION_BLOCK_SIZE - 1] != MBR_SIGNATURE_SECOND)) { + return -ENOENT; + } + offset = (uintptr_t)&mbr_sector + + MBR_PRIMARY_ENTRY_OFFSET + + MBR_PRIMARY_ENTRY_SIZE * part_number; + memcpy(mbr_entry, (void *)offset, sizeof(mbr_entry_t)); + + return 0; +} + +static int load_mbr_entries(uintptr_t image_handle) +{ + mbr_entry_t mbr_entry; + int i; + + list.entry_count = MBR_PRIMARY_ENTRY_NUMBER; + + for (i = 0; i < list.entry_count; i++) { + load_mbr_entry(image_handle, &mbr_entry, i); + list.list[i].start = mbr_entry.first_lba * 512; + list.list[i].length = mbr_entry.sector_nums * 512; + list.list[i].name[0] = mbr_entry.type; + } + + return 0; +} + +static int load_gpt_entry(uintptr_t image_handle, gpt_entry_t *entry) +{ + size_t bytes_read; + int result; + + assert(entry != NULL); + result = io_read(image_handle, (uintptr_t)entry, sizeof(gpt_entry_t), + &bytes_read); + if (sizeof(gpt_entry_t) != bytes_read) + return -EINVAL; + return result; +} + +static int verify_partition_gpt(uintptr_t image_handle) +{ + gpt_entry_t entry; + int result, i; + + for (i = 0; i < list.entry_count; i++) { + result = load_gpt_entry(image_handle, &entry); + assert(result == 0); + result = parse_gpt_entry(&entry, &list.list[i]); + if (result != 0) { + break; + } + } + if (i == 0) { + return -EINVAL; + } + /* + * Only records the valid partition number that is loaded from + * partition table. + */ + list.entry_count = i; + dump_entries(list.entry_count); + + return 0; +} + +int load_partition_table(unsigned int image_id) +{ + uintptr_t dev_handle, image_handle, image_spec = 0; + mbr_entry_t mbr_entry; + int result; + + result = plat_get_image_source(image_id, &dev_handle, &image_spec); + if (result != 0) { + WARN("Failed to obtain reference to image id=%u (%i)\n", + image_id, result); + return result; + } + + result = io_open(dev_handle, image_spec, &image_handle); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + return result; + } + + result = load_mbr_header(image_handle, &mbr_entry); + if (result != 0) { + WARN("Failed to access image id=%u (%i)\n", image_id, result); + return result; + } + if (mbr_entry.type == PARTITION_TYPE_GPT) { + result = load_gpt_header(image_handle); + assert(result == 0); + result = io_seek(image_handle, IO_SEEK_SET, GPT_ENTRY_OFFSET); + assert(result == 0); + result = verify_partition_gpt(image_handle); + } else { + result = load_mbr_entries(image_handle); + } + + io_close(image_handle); + return result; +} + +const partition_entry_t *get_partition_entry(const char *name) +{ + int i; + + for (i = 0; i < list.entry_count; i++) { + if (strcmp(name, list.list[i].name) == 0) { + return &list.list[i]; + } + } + return NULL; +} + +const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid) +{ + int i; + + for (i = 0; i < list.entry_count; i++) { + if (guidcmp(part_uuid, &list.list[i].part_guid) == 0) { + return &list.list[i]; + } + } + + return NULL; +} + +const partition_entry_list_t *get_partition_entry_list(void) +{ + return &list; +} + +void partition_init(unsigned int image_id) +{ + load_partition_table(image_id); +} diff --git a/arm-trusted-firmware/drivers/rambus/trng_ip_76.c b/arm-trusted-firmware/drivers/rambus/trng_ip_76.c new file mode 100644 index 0000000..8de12e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/rambus/trng_ip_76.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved. + * + * Based on Linux kernel omap-rng.c - RNG driver for TI OMAP CPU family + * + * Author: Deepak Saxena + * + * Copyright 2005 (c) MontaVista Software, Inc. + * + * Mostly based on original driver: + * + * Copyright (C) 2005 Nokia Corporation + * Author: Juha Yrjölä + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#define RNG_REG_STATUS_RDY (1 << 0) + +#define RNG_REG_INTACK_RDY_MASK (1 << 0) + +#define RNG_CONTROL_ENABLE_TRNG_MASK (1 << 10) + +#define RNG_CONFIG_NOISE_BLOCKS(val) ((0xff & (val)) << 0) +#define RNG_CONFIG_NOISE_BLK_VAL 0x5 + +#define RNG_CONFIG_SAMPLE_CYCLES(val) ((0xff & (val)) << 16) +#define RNG_CONFIG_SAMPLE_CYCLES_VAL 0x22 + +#define RNG_REG_FRO_ENABLE_MASK 0xffffff +#define RNG_REG_FRO_DETUNE_MASK 0x0 + +#define EIP76_RNG_OUTPUT_SIZE 0x10 +#define EIP76_RNG_WAIT_ROUNDS 10 + +#define RNG_HW_IS_EIP76(ver) ((ver) & (0xff == 0x4C)) +#define RNG_HW_VER_MAJOR(ver) (((ver) & (0xf << 24)) >> 24) +#define RNG_HW_VER_MINOR(ver) (((ver) & (0xf << 20)) >> 20) +#define RNG_HW_VER_PATCH(ver) (((ver) & (0xf << 16)) >> 16) + + +enum { + RNG_OUTPUT_0_REG = 0, + RNG_OUTPUT_1_REG, + RNG_OUTPUT_2_REG, + RNG_OUTPUT_3_REG, + RNG_STATUS_REG, + RNG_INTMASK_REG, + RNG_INTACK_REG, + RNG_CONTROL_REG, + RNG_CONFIG_REG, + RNG_ALARMCNT_REG, + RNG_FROENABLE_REG, + RNG_FRODETUNE_REG, + RNG_ALARMMASK_REG, + RNG_ALARMSTOP_REG, + RNG_REV_REG +}; + +static uint16_t reg_map_eip76[] = { + [RNG_OUTPUT_0_REG] = 0x0, + [RNG_OUTPUT_1_REG] = 0x4, + [RNG_OUTPUT_2_REG] = 0x8, + [RNG_OUTPUT_3_REG] = 0xc, + [RNG_STATUS_REG] = 0x10, + [RNG_INTACK_REG] = 0x10, + [RNG_CONTROL_REG] = 0x14, + [RNG_CONFIG_REG] = 0x18, + [RNG_ALARMCNT_REG] = 0x1c, + [RNG_FROENABLE_REG] = 0x20, + [RNG_FRODETUNE_REG] = 0x24, + [RNG_ALARMMASK_REG] = 0x28, + [RNG_ALARMSTOP_REG] = 0x2c, + [RNG_REV_REG] = 0x7c, +}; + +struct eip76_rng_dev { + uintptr_t base; + uint16_t *regs; +}; + +/* Locals */ +static struct eip76_rng_dev eip76_dev; +static spinlock_t rng_lock; + +static inline uint32_t eip76_rng_read(struct eip76_rng_dev *dev, uint16_t reg) +{ + return mmio_read_32(dev->base + dev->regs[reg]); +} + +static inline void eip76_rng_write(struct eip76_rng_dev *dev, + uint16_t reg, uint32_t val) +{ + mmio_write_32(dev->base + dev->regs[reg], val); +} + +static void eip76_rng_init(struct eip76_rng_dev *dev) +{ + uint32_t val; + + /* Return if RNG is already running. */ + if (eip76_rng_read(dev, RNG_CONTROL_REG) & + RNG_CONTROL_ENABLE_TRNG_MASK) { + return; + } + + /* This field sets the number of 512-bit blocks of raw Noise Source + * output data that must be processed by either the Conditioning + * Function or the SP 800-90 DRBG ‘BC_DF’ functionality to yield + * a ‘full entropy’ output value. As according to [SP 800-90B draft] + * the amount of entropy input to this functionality must be twice + * the amount that is output and the 8-bit samples output by the Noise + * Source are supposed to have one bit of entropy each, the settings + * for this field are as follows: + * - SHA-1 Conditioning Function: + * generates 160 bits output, requiring 2560 sample bits, + * equivalent to 5 blocks of raw Noise Source input. + * - SHA-256 Conditioning Function: + * generates 256 bits output, requiring 4096 sample bits, equivalent + * to 8 blocks of raw Noise Source input. Note that two blocks of 256 + * bits are needed to start or re-seed the SP 800-90 DRBG + * (in the EIP-76d-*-SHA2 configurations) + * - SP 800-90 DRBG ‘BC_DF’ functionality: + * generates 384 bits output, requiring 6144 sample bits, equivalent + * to 12 blocks of raw Noise Source input. + * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL + * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’ + * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 256 blocks + * of 512 bits to be processed. + */ + val = RNG_CONFIG_NOISE_BLOCKS(RNG_CONFIG_NOISE_BLK_VAL); + + /* This field sets the number of FRO samples that are XOR-ed together + * into one bit to be shifted into the main shift register. + * This value must be such that there is at least one bit of entropy + * (in total) in each 8 bits that are shifted. + * This field can only be modified when ‘enable_trng’ in TRNG_CONTROL + * is ‘0’ or when either of the ‘test_known_noise’ or ‘test_cond_func’ + * bits in TRNG_TEST is ‘1’. Value 0 in this field selects 65536 FRO + * samples to be XOR-ed together + */ + val |= RNG_CONFIG_SAMPLE_CYCLES(RNG_CONFIG_SAMPLE_CYCLES_VAL); + eip76_rng_write(dev, RNG_CONFIG_REG, val); + + /* Enable all available FROs */ + eip76_rng_write(dev, RNG_FRODETUNE_REG, RNG_REG_FRO_DETUNE_MASK); + eip76_rng_write(dev, RNG_FROENABLE_REG, RNG_REG_FRO_ENABLE_MASK); + + /* Enable TRNG */ + eip76_rng_write(dev, RNG_CONTROL_REG, RNG_CONTROL_ENABLE_TRNG_MASK); +} + +int32_t eip76_rng_read_rand_buf(void *data, bool wait) +{ + uint32_t i, present; + + if (!eip76_dev.base) /* not initialized */ + return -1; + + for (i = 0; i < EIP76_RNG_WAIT_ROUNDS; i++) { + present = eip76_rng_read(&eip76_dev, RNG_STATUS_REG) & + RNG_REG_STATUS_RDY; + if (present || !wait) { + break; + } + + udelay(10); + } + + if (present != 0U) { + return 0; + } + + memcpy(data, + (void *)(eip76_dev.base + eip76_dev.regs[RNG_OUTPUT_0_REG]), + EIP76_RNG_OUTPUT_SIZE); + + eip76_rng_write(&eip76_dev, RNG_INTACK_REG, RNG_REG_INTACK_RDY_MASK); + + return EIP76_RNG_OUTPUT_SIZE; +} + +int32_t eip76_rng_probe(uintptr_t base_addr) +{ + uint32_t ver; + + eip76_dev.base = base_addr; + eip76_dev.regs = reg_map_eip76; + + eip76_rng_init(&eip76_dev); + + ver = eip76_rng_read(&eip76_dev, RNG_REV_REG); + + INFO("%s Random Number Generator HW ver. %01x.%01x.%01x\n", + RNG_HW_IS_EIP76(ver) ? "TRNG-IP-76" : "Unknown", + RNG_HW_VER_MAJOR(ver), RNG_HW_VER_MINOR(ver), + RNG_HW_VER_PATCH(ver)); + + return 0; +} + +int32_t eip76_rng_get_random(uint8_t *data, uint32_t len) +{ + static uint8_t rand[EIP76_RNG_OUTPUT_SIZE]; + static uint8_t pos; + uint32_t i; + int32_t ret = 0; + + if (!data) + return -1; + + spin_lock(&rng_lock); + + for (i = 0; i < len; i++) { + if (pos >= EIP76_RNG_OUTPUT_SIZE) { + pos = 0; + } + + if (pos != 0U) { + ret = eip76_rng_read_rand_buf(rand, true); + } + + /* Only advance FIFO index if it is non zero or + * the update from TRNG HW was successful + */ + if (pos || ret > 0) { + data[i] = rand[pos++]; + ret = 0; + } else { + ret = -1; + break; + } + } + + spin_unlock(&rng_lock); + + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c b/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c new file mode 100644 index 0000000..4aa86e2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c @@ -0,0 +1,172 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include "rom_api.h" + +typedef int32_t(*secure_boot_api_f) (uint32_t a, uint32_t b, void *c); +extern int32_t rcar_get_certificate(const int32_t name, uint32_t *cert_addr); + +#define RCAR_IMAGE_ID_MAX (10) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) +#define RCAR_BOOT_KEY_CERT (0xE6300C00U) +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define MFISOFTMDR (0xE6260600U) +#define MODEMR_MD5_MASK (0x00000020U) +#define MODEMR_MD5_SHIFT (5U) +#define SOFTMD_BOOTMODE_MASK (0x00000001U) +#define SOFTMD_NORMALBOOT (0x1U) + +static secure_boot_api_f secure_boot_api; + +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id) +{ + return 1; +} + +int auth_mod_verify_img(unsigned int img_id, void *ptr, unsigned int len) +{ + int32_t ret = 0, index = 0; + uint32_t cert_addr = 0U; + static const struct img_to_cert_t { + uint32_t id; + int32_t cert; + const char *name; + } image[RCAR_IMAGE_ID_MAX] = { + { BL31_IMAGE_ID, SOC_FW_CONTENT_CERT_ID, "BL31" }, + { BL32_IMAGE_ID, TRUSTED_OS_FW_CONTENT_CERT_ID, "BL32" }, + { BL33_IMAGE_ID, NON_TRUSTED_FW_CONTENT_CERT_ID, "BL33" }, + { BL332_IMAGE_ID, BL332_CERT_ID, "BL332" }, + { BL333_IMAGE_ID, BL333_CERT_ID, "BL333" }, + { BL334_IMAGE_ID, BL334_CERT_ID, "BL334" }, + { BL335_IMAGE_ID, BL335_CERT_ID, "BL335" }, + { BL336_IMAGE_ID, BL336_CERT_ID, "BL336" }, + { BL337_IMAGE_ID, BL337_CERT_ID, "BL337" }, + { BL338_IMAGE_ID, BL338_CERT_ID, "BL338" }, + }; + +#if IMAGE_BL2 + switch (img_id) { + case TRUSTED_KEY_CERT_ID: + case SOC_FW_KEY_CERT_ID: + case TRUSTED_OS_FW_KEY_CERT_ID: + case NON_TRUSTED_FW_KEY_CERT_ID: + case BL332_KEY_CERT_ID: + case BL333_KEY_CERT_ID: + case BL334_KEY_CERT_ID: + case BL335_KEY_CERT_ID: + case BL336_KEY_CERT_ID: + case BL337_KEY_CERT_ID: + case BL338_KEY_CERT_ID: + case SOC_FW_CONTENT_CERT_ID: + case TRUSTED_OS_FW_CONTENT_CERT_ID: + case NON_TRUSTED_FW_CONTENT_CERT_ID: + case BL332_CERT_ID: + case BL333_CERT_ID: + case BL334_CERT_ID: + case BL335_CERT_ID: + case BL336_CERT_ID: + case BL337_CERT_ID: + case BL338_CERT_ID: + return ret; + case BL31_IMAGE_ID: + case BL32_IMAGE_ID: + case BL33_IMAGE_ID: + case BL332_IMAGE_ID: + case BL333_IMAGE_ID: + case BL334_IMAGE_ID: + case BL335_IMAGE_ID: + case BL336_IMAGE_ID: + case BL337_IMAGE_ID: + case BL338_IMAGE_ID: + goto verify_image; + default: + return -1; + } + +verify_image: + for (index = 0; index < RCAR_IMAGE_ID_MAX; index++) { + if (img_id != image[index].id) + continue; + + ret = rcar_get_certificate(image[index].cert, &cert_addr); + break; + } + + if (ret || (index == RCAR_IMAGE_ID_MAX)) { + ERROR("Verification Failed for image id = %d\n", img_id); + return ret; + } +#if RCAR_BL2_DCACHE == 1 + /* clean and disable */ + write_sctlr_el3(read_sctlr_el3() & ~SCTLR_C_BIT); + dcsw_op_all(DCCISW); +#endif + ret = (mmio_read_32(RCAR_BOOT_KEY_CERT_NEW) == RCAR_CERT_MAGIC_NUM) ? + secure_boot_api(RCAR_BOOT_KEY_CERT_NEW, cert_addr, NULL) : + secure_boot_api(RCAR_BOOT_KEY_CERT, cert_addr, NULL); + if (ret) + ERROR("Verification Failed 0x%x, %s\n", ret, image[index].name); + +#if RCAR_BL2_DCACHE == 1 + /* enable */ + write_sctlr_el3(read_sctlr_el3() | SCTLR_C_BIT); +#endif /* RCAR_BL2_DCACHE */ + +#endif /* IMAGE_BL2 */ + return ret; +} + +static int32_t normal_boot_verify(uint32_t a, uint32_t b, void *c) +{ + return 0; +} + +void auth_mod_init(void) +{ +#if RCAR_SECURE_BOOT + uint32_t soft_md = mmio_read_32(MFISOFTMDR) & SOFTMD_BOOTMODE_MASK; + uint32_t md = mmio_read_32(RST_MODEMR) & MODEMR_MD5_MASK; + uint32_t lcs, ret; + + secure_boot_api = (secure_boot_api_f) &rcar_rom_secure_boot_api; + + ret = rcar_rom_get_lcs(&lcs); + if (ret) { + ERROR("BL2: Failed to get the LCS. (%d)\n", ret); + panic(); + } + + switch (lcs) { + case LCS_SE: + if (soft_md == SOFTMD_NORMALBOOT) + secure_boot_api = &normal_boot_verify; + break; + case LCS_SD: + secure_boot_api = &normal_boot_verify; + break; + default: + if (md >> MODEMR_MD5_SHIFT) + secure_boot_api = &normal_boot_verify; + } + + NOTICE("BL2: %s boot\n", + secure_boot_api == &normal_boot_verify ? "Normal" : "Secure"); +#else + NOTICE("BL2: Normal boot\n"); + secure_boot_api = &normal_boot_verify; +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c new file mode 100644 index 0000000..2c939cd --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c @@ -0,0 +1,630 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "avs_driver.h" +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 +/* Read PMIC register for debug. 1:enable / 0:disable */ +#define AVS_READ_PMIC_REG_ENABLE 0 +/* The re-try number of times of the AVS setting. */ +#define AVS_RETRY_NUM (1U) +#endif /* PMIC_ROHM_BD9571 */ + +/* Base address of Adaptive Voltage Scaling module registers*/ +#define AVS_BASE (0xE60A0000U) +/* Adaptive Dynamic Voltage ADJust Parameter2 registers */ +#define ADVADJP2 (AVS_BASE + 0x013CU) + +/* Mask VOLCOND bit in ADVADJP2 registers */ +#define ADVADJP2_VOLCOND_MASK (0x000001FFU) /* VOLCOND[8:0] */ + +#if PMIC_ROHM_BD9571 +/* I2C for DVFS bit in CPG registers for module standby and software reset*/ +#define CPG_SYS_DVFS_BIT (0x04000000U) +#endif /* PMIC_ROHM_BD9571 */ +/* ADVFS Module bit in CPG registers for module standby and software reset*/ +#define CPG_SYS_ADVFS_BIT (0x02000000U) + +#if PMIC_ROHM_BD9571 +/* Base address of IICDVFS registers*/ +#define IIC_DVFS_BASE (0xE60B0000U) +/* IIC bus data register */ +#define IIC_ICDR (IIC_DVFS_BASE + 0x0000U) +/* IIC bus control register */ +#define IIC_ICCR (IIC_DVFS_BASE + 0x0004U) +/* IIC bus status register */ +#define IIC_ICSR (IIC_DVFS_BASE + 0x0008U) +/* IIC interrupt control register */ +#define IIC_ICIC (IIC_DVFS_BASE + 0x000CU) +/* IIC clock control register low */ +#define IIC_ICCL (IIC_DVFS_BASE + 0x0010U) +/* IIC clock control register high */ +#define IIC_ICCH (IIC_DVFS_BASE + 0x0014U) + +/* Bit in ICSR register */ +#define ICSR_BUSY (0x10U) +#define ICSR_AL (0x08U) +#define ICSR_TACK (0x04U) +#define ICSR_WAIT (0x02U) +#define ICSR_DTE (0x01U) + +/* Bit in ICIC register */ +#define ICIC_TACKE (0x04U) +#define ICIC_WAITE (0x02U) +#define ICIC_DTEE (0x01U) + +/* I2C bus interface enable */ +#define ICCR_ENABLE (0x80U) +/* Start condition */ +#define ICCR_START (0x94U) +/* Stop condition */ +#define ICCR_STOP (0x90U) +/* Restart condition with change to receive mode change */ +#define ICCR_START_RECV (0x81U) +/* Stop condition for receive mode */ +#define ICCR_STOP_RECV (0xC0U) + +/* Low-level period of SCL */ +#define ICCL_FREQ_8p33M (0x07U) /* for CP Phy 8.3333MHz */ +#define ICCL_FREQ_10M (0x09U) /* for CP Phy 10MHz */ +#define ICCL_FREQ_12p5M (0x0BU) /* for CP Phy 12.5MHz */ +#define ICCL_FREQ_16p66M (0x0EU) /* for CP Phy 16.6666MHz */ +/* High-level period of SCL */ +#define ICCH_FREQ_8p33M (0x01U) /* for CP Phy 8.3333MHz */ +#define ICCH_FREQ_10M (0x02U) /* for CP Phy 10MHz */ +#define ICCH_FREQ_12p5M (0x03U) /* for CP Phy 12.5MHz */ +#define ICCH_FREQ_16p66M (0x05U) /* for CP Phy 16.6666MHz */ + +/* PMIC */ +/* ROHM BD9571 slave address + (W) */ +#define PMIC_W_SLAVE_ADDRESS (0x60U) +/* ROHM BD9571 slave address + (R) */ +#define PMIC_R_SLAVE_ADDRESS (0x61U) +/* ROHM BD9571 DVFS SetVID register */ +#define PMIC_DVFS_SETVID (0x54U) +#endif /* PMIC_ROHM_BD9571 */ + +/* Individual information */ +#define EFUSE_AVS0 (0U) +#define EFUSE_AVS_NUM ARRAY_SIZE(init_vol_tbl) + +typedef struct { + uint32_t avs; /* AVS code */ + uint8_t vol; /* Voltage */ +} initial_voltage_t; + +static const initial_voltage_t init_vol_tbl[] = { + /* AVS code, ROHM BD9571 DVFS SetVID register */ + {0x00U, 0x53U}, /* AVS0, 0.83V */ + {0x01U, 0x52U}, /* AVS1, 0.82V */ + {0x02U, 0x51U}, /* AVS2, 0.81V */ + {0x04U, 0x50U}, /* AVS3, 0.80V */ + {0x08U, 0x4FU}, /* AVS4, 0.79V */ + {0x10U, 0x4EU}, /* AVS5, 0.78V */ + {0x20U, 0x4DU}, /* AVS6, 0.77V */ + {0x40U, 0x4CU} /* AVS7, 0.76V */ +}; + +#if PMIC_ROHM_BD9571 +/* Kind of AVS settings status */ +typedef enum { + avs_status_none = 0, + avs_status_init, + avs_status_start_condition, + avs_status_set_slave_addr, + avs_status_write_reg_addr, + avs_status_write_reg_data, + avs_status_stop_condition, + avs_status_end, + avs_status_complete, + avs_status_al_start, + avs_status_al_transfer, + avs_status_nack, + avs_status_error_stop, + ave_status_error_end +} avs_status_t; + +/* Kind of AVS error */ +typedef enum { + avs_error_none = 0, + avs_error_al, + avs_error_nack +} avs_error_t; + +static avs_status_t avs_status; +static uint32_t avs_retry; +#endif /* PMIC_ROHM_BD9571 */ +static uint32_t efuse_avs = EFUSE_AVS0; + +#if PMIC_ROHM_BD9571 +/* prototype */ +static avs_error_t avs_check_error(void); +static void avs_set_iic_clock(void); +#if AVS_READ_PMIC_REG_ENABLE == 1 +static uint8_t avs_read_pmic_reg(uint8_t addr); +static void avs_poll(uint8_t bit_pos, uint8_t val); +#endif +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ + +/* + * Initialize to enable the AVS setting. + */ +void rcar_avs_init(void) +{ +#if (AVS_SETTING_ENABLE == 1) + uint32_t val; + +#if PMIC_ROHM_BD9571 + /* Initialize AVS status */ + avs_status = avs_status_init; +#endif /* PMIC_ROHM_BD9571 */ + + /* Enable clock supply to ADVFS. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_ADVFS_BIT); + + /* Read AVS code (Initial values are derived from eFuse) */ + val = mmio_read_32(ADVADJP2) & ADVADJP2_VOLCOND_MASK; + + for (efuse_avs = 0U; efuse_avs < EFUSE_AVS_NUM; efuse_avs++) { + if (val == init_vol_tbl[efuse_avs].avs) + break; + } + + if (efuse_avs >= EFUSE_AVS_NUM) + efuse_avs = EFUSE_AVS0; /* Not applicable */ +#if PMIC_ROHM_BD9571 + /* Enable clock supply to DVFS. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, CPG_SYS_DVFS_BIT); + + /* Disable I2C module and All internal registers initialized. */ + mmio_write_8(IIC_ICCR, 0x00U); + while ((mmio_read_8(IIC_ICCR) & ICCR_ENABLE) != 0U) { + /* Disable I2C module and all internal registers initialized. */ + mmio_write_8(IIC_ICCR, 0x00U); + } + + /* Set next status */ + avs_status = avs_status_start_condition; + +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +/* + * Set the value of register corresponding to the voltage + * by transfer of I2C to PIMC. + */ +void rcar_avs_setting(void) +{ +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 + avs_error_t err; + + switch (avs_status) { + case avs_status_start_condition: + /* Set ICCR.ICE=1 to activate the I2C module. */ + mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE); + /* Set frequency of 400kHz */ + avs_set_iic_clock(); + /* Set ICIC.TACKE=1, ICIC.WAITE=1, ICIC.DTEE=1 to */ + /* enable interrupt control. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + | ICIC_TACKE | ICIC_WAITE | ICIC_DTEE); + /* Write H'94 in ICCR to issue start condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + /* Set next status */ + avs_status = avs_status_set_slave_addr; + break; + case avs_status_set_slave_addr: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of just after start. */ + avs_status = avs_status_al_start; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* Was data transmission enabled ? */ + if ((mmio_read_8(IIC_ICSR) & ICSR_DTE) == ICSR_DTE) { + /* Clear ICIC.DTEE to disable a DTE interrupt */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + & (uint8_t) (~ICIC_DTEE)); + /* Send PMIC slave address + (W) */ + mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS); + /* Set next status */ + avs_status = avs_status_write_reg_addr; + } + } + break; + case avs_status_write_reg_addr: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write PMIC DVFS_SetVID address */ + mmio_write_8(IIC_ICDR, PMIC_DVFS_SETVID); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_write_reg_data; + } + } + break; + case avs_status_write_reg_data: + /* Check error. */ + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Dose efuse_avs exceed the number of */ + /* the tables? */ + if (efuse_avs >= EFUSE_AVS_NUM) { + ERROR("%s%s=%u\n", "AVS number of ", + "eFuse is out of range. number", + efuse_avs); + /* Infinite loop */ + panic(); + } + /* Write PMIC DVFS_SetVID value */ + mmio_write_8(IIC_ICDR, + init_vol_tbl[efuse_avs].vol); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_stop_condition; + } + } + break; + case avs_status_stop_condition: + err = avs_check_error(); + if (err == avs_error_al) { + /* Recovery sequence of during data transfer. */ + avs_status = avs_status_al_transfer; + } else if (err == avs_error_nack) { + /* Recovery sequence of detected NACK */ + avs_status = avs_status_nack; + } else { + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = avs_status_end; + } + } + break; + case avs_status_end: + /* Is this module not busy?. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) { + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + /* Set next status */ + avs_status = avs_status_complete; + } + break; + case avs_status_al_start: + /* Clear ICSR.AL bit */ + mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_AL))); + /* Transmit a clock pulse */ + mmio_write_8(IIC_ICDR, init_vol_tbl[EFUSE_AVS0].vol); + /* Set next status */ + avs_status = avs_status_error_stop; + break; + case avs_status_al_transfer: + /* Clear ICSR.AL bit */ + mmio_write_8(IIC_ICSR, (mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_AL))); + /* Set next status */ + avs_status = avs_status_error_stop; + break; + case avs_status_nack: + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Disable a WAIT and DTEE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) + & (uint8_t) (~(ICIC_WAITE | ICIC_DTEE))); + /* Clear ICSR.TACK bit */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_TACK)); + /* Set next status */ + avs_status = ave_status_error_end; + break; + case avs_status_error_stop: + /* If wait state after data transmission. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_WAIT) == ICSR_WAIT) { + /* Write H'90 in ICCR to issue stop condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP); + /* Clear ICSR.WAIT to exit from wait state. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) + & (uint8_t) (~ICSR_WAIT)); + /* Set next status */ + avs_status = ave_status_error_end; + } + break; + case ave_status_error_end: + /* Is this module not busy?. */ + if ((mmio_read_8(IIC_ICSR) & ICSR_BUSY) == 0U) { + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + /* Increment the re-try number of times. */ + avs_retry++; + /* Set start a re-try to status. */ + avs_status = avs_status_start_condition; + } + break; + case avs_status_complete: + /* After "avs_status" became the "avs_status_complete", */ + /* "avs_setting()" function may be called. */ + break; + default: + /* This case is not possible. */ + ERROR("AVS setting is in invalid status. status=%u\n", + avs_status); + /* Infinite loop */ + panic(); + break; + } +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +/* + * Finish the AVS setting. + */ +void rcar_avs_end(void) +{ +#if (AVS_SETTING_ENABLE == 1) + uint32_t mstp; + +#if PMIC_ROHM_BD9571 + /* While status is not completion, be repeated. */ + while (avs_status != avs_status_complete) + rcar_avs_setting(); + + NOTICE("AVS setting succeeded. DVFS_SetVID=0x%x\n", + init_vol_tbl[efuse_avs].vol); + +#if AVS_READ_PMIC_REG_ENABLE == 1 + { + uint8_t addr = PMIC_DVFS_SETVID; + uint8_t value = avs_read_pmic_reg(addr); + + NOTICE("Read PMIC register. address=0x%x value=0x%x\n", + addr, value); + } +#endif + + /* Bit of the module which wants to disable clock supply. */ + mstp = CPG_SYS_DVFS_BIT; + /* Disables the supply of clock signal to a module. */ + cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp); +#endif /* PMIC_ROHM_BD9571 */ + + /* Bit of the module which wants to disable clock supply. */ + mstp = CPG_SYS_ADVFS_BIT; + /* Disables the supply of clock signal to a module. */ + cpg_write(CPG_SMSTPCR9, mmio_read_32(CPG_SMSTPCR9) | mstp); + +#endif /* (AVS_SETTING_ENABLE==1) */ +} + +#if (AVS_SETTING_ENABLE == 1) +#if PMIC_ROHM_BD9571 +/* + * Check error and judge re-try. + */ +static avs_error_t avs_check_error(void) +{ + avs_error_t ret; + + if ((mmio_read_8(IIC_ICSR) & ICSR_AL) == ICSR_AL) { + NOTICE("%s AVS status=%d Retry=%u\n", + "Loss of arbitration is detected.", avs_status, avs_retry); + /* Check of retry number of times */ + if (avs_retry >= AVS_RETRY_NUM) { + ERROR("AVS setting failed in retry. max=%u\n", + AVS_RETRY_NUM); + /* Infinite loop */ + panic(); + } + /* Set the error detected to error status. */ + ret = avs_error_al; + } else if ((mmio_read_8(IIC_ICSR) & ICSR_TACK) == ICSR_TACK) { + NOTICE("%s AVS status=%d Retry=%u\n", + "Non-acknowledge is detected.", avs_status, avs_retry); + /* Check of retry number of times */ + if (avs_retry >= AVS_RETRY_NUM) { + ERROR("AVS setting failed in retry. max=%u\n", + AVS_RETRY_NUM); + /* Infinite loop */ + panic(); + } + /* Set the error detected to error status. */ + ret = avs_error_nack; + } else { + /* Not error. */ + ret = avs_error_none; + } + return ret; +} + +/* + * Set I2C for DVFS clock. + */ +static void avs_set_iic_clock(void) +{ + uint32_t md_pin; + + /* Read Mode pin register. */ + md_pin = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14; + /* Set the module clock (CP phy) for the IIC-DVFS. */ + /* CP phy is EXTAL / 2. */ + switch (md_pin) { + case MD14_MD13_TYPE_0: /* EXTAL = 16.6666MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_8p33M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_8p33M); + break; + case MD14_MD13_TYPE_1: /* EXTAL = 20MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_10M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_10M); + break; + case MD14_MD13_TYPE_2: /* EXTAL = 25MHz (H3/M3) */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_12p5M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_12p5M); + break; + case MD14_MD13_TYPE_3: /* EXTAL = 33.3333MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M); + break; + default: /* This case is not possible. */ + /* CP Phy frequency is to be set for the 16.66MHz */ + mmio_write_8(IIC_ICCL, ICCL_FREQ_16p66M); + mmio_write_8(IIC_ICCH, ICCH_FREQ_16p66M); + break; + } +} + +#if AVS_READ_PMIC_REG_ENABLE == 1 +/* + * Read the value of the register of PMIC. + */ +static uint8_t avs_read_pmic_reg(uint8_t addr) +{ + uint8_t reg; + + /* Set ICCR.ICE=1 to activate the I2C module. */ + mmio_write_8(IIC_ICCR, mmio_read_8(IIC_ICCR) | ICCR_ENABLE); + + /* Set frequency of 400kHz */ + avs_set_iic_clock(); + + /* + * Set ICIC.WAITE=1, ICIC.DTEE=1 to enable data transmission + * interrupt and wait interrupt. + */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_WAITE | ICIC_DTEE); + + /* Write H'94 in ICCR to issue start condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Send slave address of PMIC */ + mmio_write_8(IIC_ICDR, PMIC_W_SLAVE_ADDRESS); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* write PMIC address */ + mmio_write_8(IIC_ICDR, addr); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Write H'94 in ICCR to issue restart condition */ + mmio_write_8(IIC_ICCR, ICCR_START); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + /* Set ICIC.DTEE=1 to enable data transmission interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Send slave address of PMIC */ + mmio_write_8(IIC_ICDR, PMIC_R_SLAVE_ADDRESS); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Write H'81 to ICCR to issue the repeated START condition */ + /* for changing the transmission mode to the receive mode. */ + mmio_write_8(IIC_ICCR, ICCR_START_RECV); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + + /* Wait for a until ICSR.WAIT becomes 1. */ + avs_poll(ICSR_WAIT, 1U); + + /* Set ICCR to H'C0 for the STOP condition */ + mmio_write_8(IIC_ICCR, ICCR_STOP_RECV); + /* Clear ICSR.WAIT to exit from WAIT status. */ + mmio_write_8(IIC_ICSR, mmio_read_8(IIC_ICSR) & (uint8_t) (~ICSR_WAIT)); + /* Set ICIC.DTEE=1 to enable data transmission interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) | ICIC_DTEE); + + /* Wait for a until ICSR.DTE becomes 1. */ + avs_poll(ICSR_DTE, 1U); + + /* Receive DVFS SetVID register */ + /* Clear ICIC.DTEE to disable a DTE interrupt. */ + mmio_write_8(IIC_ICIC, mmio_read_8(IIC_ICIC) & (uint8_t) (~ICIC_DTEE)); + /* Receive DVFS SetVID register */ + reg = mmio_read_8(IIC_ICDR); + + /* Wait until ICSR.BUSY is cleared. */ + avs_poll(ICSR_BUSY, 0U); + + /* Set ICCR=H'00 to disable the I2C module. */ + mmio_write_8(IIC_ICCR, 0x00U); + + return reg; +} + +/* + * Wait processing by the polling. + */ +static void avs_poll(uint8_t bit_pos, uint8_t val) +{ + uint8_t bit_val = 0U; + + if (val != 0U) + bit_val = bit_pos; + + while (1) { + if ((mmio_read_8(IIC_ICSR) & bit_pos) == bit_val) + break; + } +} +#endif /* AVS_READ_PMIC_REG_ENABLE */ +#endif /* PMIC_ROHM_BD9571 */ +#endif /* (AVS_SETTING_ENABLE==1) */ diff --git a/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h new file mode 100644 index 0000000..aa773b6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AVS_DRIVER_H +#define AVS_DRIVER_H + +/* AVS Setting. 1:enable / 0:disable */ +#ifndef AVS_SETTING_ENABLE +#define AVS_SETTING_ENABLE 1 +#endif /* AVS_SETTING_ENABLE */ + +void rcar_avs_init(void); +void rcar_avs_setting(void); +void rcar_avs_end(void); + +#endif /* AVS_DRIVER_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/common.c b/arm-trusted-firmware/drivers/renesas/common/common.c new file mode 100644 index 0000000..a0aa480 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/common.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "cpg_registers.h" +#include "rcar_private.h" + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) cpg_write(uintptr_t regadr, uint32_t regval) +#else +void cpg_write(uintptr_t regadr, uint32_t regval) +#endif +{ + uint32_t value = regval; + + mmio_write_32(CPG_CPGWPR, ~value); + mmio_write_32(regadr, value); +} + +#if IMAGE_BL31 +void __attribute__ ((section(".system_ram"))) mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, + uint32_t target_bit) +#else +void mstpcr_write(uint32_t mstpcr, uint32_t mstpsr, uint32_t target_bit) +#endif +{ + uint32_t reg; + + reg = mmio_read_32(mstpcr); + reg &= ~target_bit; + cpg_write(mstpcr, reg); + while ((mmio_read_32(mstpsr) & target_bit) != 0U) { + } +} diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S b/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S new file mode 100644 index 0000000..b683d7b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S @@ -0,0 +1,93 @@ +/* + * Copyright (c) 2018-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + .extern rcar_log_init + .extern rcar_set_log_data + + /* ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * 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_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl rcar_log_init + cbz x0, register_fail + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* --------------------------------------------- + * int console_rcar_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 crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + * --------------------------------------------- + */ +func console_rcar_init + mov w0, #1 + ret +endfunc console_rcar_init + + /* -------------------------------------------------------- + * int console_rcar_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_rcar_putc + b rcar_set_log_data +endfunc console_rcar_putc + + /* --------------------------------------------- + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_rcar_flush + ret +endfunc console_rcar_flush diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c new file mode 100644 index 0000000..ad074fe --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include "rcar_def.h" +#include "rcar_private.h" +#include "rcar_printf.h" + +#define INDEX_TIMER_COUNT (4U) + +#define RCAR_LOG_HEAD (('T' << 0) | ('L' << 8) | ('O' << 16) | ('G' << 24)) + +/* + * The log is initialized and used before BL31 xlat tables are initialized, + * therefore the log memory is a device memory at that point. Make sure the + * memory is correclty aligned and accessed only with up-to 32bit, aligned, + * writes. + */ +CASSERT((RCAR_BL31_LOG_BASE & 0x7) == 0, assert_bl31_log_base_unaligned); +CASSERT((RCAR_BL31_LOG_MAX & 0x7) == 0, assert_bl31_log_max_unaligned); + +extern RCAR_INSTANTIATE_LOCK typedef struct log_head { + uint32_t head; + uint32_t index; + uint32_t size; + uint32_t res; +} loghead_t; + +typedef struct log_map { + loghead_t header; + uint8_t log_data[RCAR_BL31_LOG_MAX]; + uint8_t res_data[RCAR_LOG_RES_SIZE]; +} logmap_t; + +int32_t rcar_set_log_data(int32_t c) +{ + logmap_t *t_log; + + t_log = (logmap_t *) RCAR_BL31_LOG_BASE; + + rcar_lock_get(); + + /* + * If index is broken, then index and size initialize + */ + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + t_log->header.size = 0U; + } + /* + * data store to log area then index and size renewal + */ + t_log->log_data[t_log->header.index] = (uint8_t) c; + t_log->header.index++; + if (t_log->header.size < t_log->header.index) { + t_log->header.size = t_log->header.index; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + t_log->header.index = 0U; + } + + rcar_lock_release(); + + return 1; +} + +int32_t rcar_log_init(void) +{ + logmap_t *t_log = (logmap_t *)RCAR_BL31_LOG_BASE; + uint32_t *log_data = (uint32_t *)t_log->log_data; + int16_t init_flag = 0; + int i; + + if (t_log->header.head != RCAR_LOG_HEAD) { + /* + * Log header is not "TLOG", then log area initialize + */ + init_flag = 1; + } + if (t_log->header.index >= (uint32_t) RCAR_BL31_LOG_MAX) { + /* + * index is broken, then log area initialize + */ + init_flag = 1; + } + if (init_flag == 1) { + for (i = 0; i < RCAR_BL31_LOG_MAX; i += 4) + *log_data++ = 0; + + t_log->header.head = RCAR_LOG_HEAD; + t_log->header.index = 0U; + t_log->header.size = 0U; + } + rcar_lock_init(); + + return 1; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h new file mode 100644 index 0000000..5da70e6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRINTF_H +#define RCAR_PRINTF_H + +#include + +int32_t rcar_set_log_data(int32_t c); +int32_t rcar_log_init(void); + +#endif /* RCAR_PRINTF_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h b/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h new file mode 100644 index 0000000..ac237b2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_INIT_DRAM_H +#define BOOT_INIT_DRAM_H + +extern int32_t rcar_dram_init(void); + +#define INITDRAM_OK 0 +#define INITDRAM_NG 0xffffffff +#define INITDRAM_ERR_I 0xffffffff +#define INITDRAM_ERR_O 0xfffffffe +#define INITDRAM_ERR_T 0xfffffff0 + +#endif /* BOOT_INIT_DRAM_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk new file mode 100644 index 0000000..9483686 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr.mk @@ -0,0 +1,17 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(RCAR_LSI),$(filter $(RCAR_LSI),${RCAR_E3} ${RZ_G2E})) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk + BL2_SOURCES += drivers/renesas/common/ddr/dram_sub_func.c +else ifeq (${RCAR_LSI},${RCAR_D3}) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk +else ifeq (${RCAR_LSI},${RCAR_V3M}) + include drivers/renesas/common/ddr/ddr_a/ddr_a.mk +else + include drivers/renesas/common/ddr/ddr_b/ddr_b.mk + BL2_SOURCES += drivers/renesas/common/ddr/dram_sub_func.c +endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h new file mode 100644 index 0000000..0f89b43 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../ddr_regs.h" diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk new file mode 100644 index 0000000..cd6433d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_a.mk @@ -0,0 +1,13 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq ($(RCAR_LSI),$(filter $(RCAR_LSI),${RCAR_E3} ${RZ_G2E})) +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c +else ifeq (${RCAR_LSI},${RCAR_D3}) +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c +else +BL2_SOURCES += drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c +endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c new file mode 100644 index 0000000..f0113f1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c @@ -0,0 +1,735 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "rcar_def.h" +#include "../ddr_regs.h" + +#define RCAR_DDR_VERSION "rev.0.02" + +/* Average periodic refresh interval[ns]. Support 3900,7800 */ +#define REFRESH_RATE 3900 + + +#if RCAR_LSI != RCAR_D3 +#error "Don't have DDR initialize routine." +#endif + +static void init_ddr_d3_1866(void) +{ + uint32_t i, r2, r3, r5, r6, r7, r12; + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000D); + mmio_write_32(DBSC_DBTR1, 0x00000009); + mmio_write_32(DBSC_DBTR2, 0x00000000); + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A04); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 928 / 125) - 400 + + 0x0A300000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000020); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x000000A0); + } + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000E); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x0000FF00) >> 0x9; + r3 = (r2 << 16) + (r2 << 8) + r2; + r6 = (r2 << 24) + (r2 << 16) + (r2 << 8) + r2; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000011); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000012); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000016); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000017); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000019); + mmio_write_32(DBSC_DBPDRGD_0, r6); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 116 / 125) + 0x00080000); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting // only for non qos_init + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS91, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + mmio_write_32(0xE67F0018, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif +} + +static void init_ddr_d3_1600(void) +{ + uint32_t i, r2, r3, r5, r6, r7, r12; + + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a01); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + mmio_write_32(DBSC_DBTR2, 0x00000000); + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, + (uint32_t) (REFRESH_RATE * 792 / 125) - 400 + 0x08B00000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + if (REFRESH_RATE > 3900) { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000018); + } else { + mmio_write_32(DBSC_DBPDRGD_0, 0x00000098); + } + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000E); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x0000FF00) >> 0x9; + r3 = (r2 << 16) + (r2 << 8) + r2; + r6 = (r2 << 24) + (r2 << 16) + (r2 << 8) + r2; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000011); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000012); + mmio_write_32(DBSC_DBPDRGD_0, r3); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000016); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000017); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGD_0, r6); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000019); + mmio_write_32(DBSC_DBPDRGD_0, r6); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000AF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + r2 = mmio_read_32(DBSC_DBPDRGD_0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000CF); + mmio_write_32(DBSC_DBPDRGD_0, ((r2 + 0x1) & 0xFF) | (r2 & 0xFFFFFF00)); + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 2; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, + (uint32_t) (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBRFCNF1, + (uint32_t) (REFRESH_RATE * 99 / 125) + 0x00080000); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting // only for non qos_init + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS91, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + mmio_write_32(0xE67F0018, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif +} + +#define PRR 0xFFF00044U +#define PRR_PRODUCT_MASK 0x00007F00U +#define PRR_PRODUCT_D3 0x00005800U + +#define MODEMR_MD19 BIT(19) + +int32_t rcar_dram_init(void) +{ + uint32_t reg; + uint32_t ddr_mbps; + + reg = mmio_read_32(PRR); + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_D3) { + ERROR("LSI Product ID (PRR=0x%x) DDR initialize not supported.\n", + reg); + panic(); + } + + reg = mmio_read_32(RST_MODEMR); + if (reg & MODEMR_MD19) { + init_ddr_d3_1866(); + ddr_mbps = 1866; + } else { + init_ddr_d3_1600(); + ddr_mbps = 1600; + } + + NOTICE("BL2: DDR%d(%s)\n", ddr_mbps, RCAR_DDR_VERSION); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c new file mode 100644 index 0000000..fc278ef --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c @@ -0,0 +1,1712 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "boot_init_dram.h" +#include "rcar_def.h" +#include "../ddr_regs.h" + +#include "../dram_sub_func.h" + +#define RCAR_E3_DDR_VERSION "rev.0.12" + +/* Average periodic refresh interval[ns]. Support 3900,7800 */ +#ifdef ddr_qos_init_setting +#define REFRESH_RATE 3900U +#else +#if RCAR_REF_INT == 1 +#define REFRESH_RATE 7800U +#else +#define REFRESH_RATE 3900U +#endif +#endif + +/* + * Initialize ddr + */ +uint32_t init_ddr(void) +{ + uint32_t i, r2, r5, r6, r7, r12; + uint32_t ddr_md; + uint32_t regval, j; + uint32_t dqsgd_0c, bdlcount_0c, bdlcount_0c_div2, bdlcount_0c_div4; + uint32_t bdlcount_0c_div8, bdlcount_0c_div16; + uint32_t gatesl_0c, rdqsd_0c, rdqsnd_0c, rbd_0c[4]; + uint32_t pdqsr_ctl, lcdl_ctl, lcdl_judge1, lcdl_judge2; + uint32_t pdr_ctl; + uint32_t byp_ctl; + + if ((mmio_read_32(0xFFF00044) & 0x000000FF) == 0x00000000) { + pdqsr_ctl = 1; + lcdl_ctl = 1; + pdr_ctl = 1; + byp_ctl = 1; + } else { + pdqsr_ctl = 0; + lcdl_ctl = 0; + pdr_ctl = 0; + byp_ctl = 0; + } + + /* Judge the DDR bit rate (ddr_md : 0 = 1584Mbps, 1 = 1856Mbps) */ + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & BIT(0); + + /* 1584Mbps setting */ + if (ddr_md == 0) { + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); /* Change to 1584Mbps */ + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + } + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); /* 1GB */ +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); /* 2GB(default) */ +#endif + +#if RCAR_DRAM_DDR3L_MEMDUAL == 1 + r2 = mmio_read_32(0xE6790614); + mmio_write_32(0xE6790614, r2 | 0x3); /* MCS1_N/MODT1 are activated. */ +#endif + + mmio_write_32(DBSC_DBPHYCONF0, 0x1); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR0, 0xB); + mmio_write_32(DBSC_DBTR1, 0x8); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR0, 0xD); + mmio_write_32(DBSC_DBTR1, 0x9); + } + + mmio_write_32(DBSC_DBTR2, 0x00000000); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + } + + mmio_write_32(DBSC_DBTR7, 0x00060006); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + } + + mmio_write_32(DBSC_DBTR18, 0x00000200); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + } + + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + } + + /* + * Initial_Step0( INITBYP ) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01840001); + mmio_write_32(DBSC_DBCMD, 0x08840000); + NOTICE("BL2: [COLD_BOOT]\n"); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step1( ZCAL,PLLINIT,DCAL,PHYRST training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A04); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step2( DRAMRST/DRAMINT training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 792 / 125) - + 400 + 0x08B00000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 928 / 125) - + 400 + 0x0A300000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + if (REFRESH_RATE > 3900) /* [7]SRT=0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x18); + else /* [7]SRT=1 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x98); + } else { /* 1856Mbps */ + if (REFRESH_RATE > 3900) /* [7]SRT=0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x20); + else /* [7]SRT=1 */ + mmio_write_32(DBSC_DBPDRGD_0, 0xA0); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08840001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step3( WL/QSG training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + ((r5) << 1)) & + 0xFF)); + } + } + + /* + * Initial_Step4( WLADJ training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step5(Read Data Bit Deskew) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00011001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step6(Write Data Bit Deskew) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00012001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step7(Read Data Eye Training) + */ + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00014001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step8(Write Data Eye Training) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00018001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* + * Initial_Step3_2( DQS Gate Training ) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = (r5 >> 0x2); + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + /* + * Initial_Step5-2_7-2( Rd bit Rd eye ) + */ + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (lcdl_ctl == 1) { + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + dqsgd_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + bdlcount_0c = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> + 8; + bdlcount_0c_div2 = bdlcount_0c >> 1; + bdlcount_0c_div4 = bdlcount_0c >> 2; + bdlcount_0c_div8 = bdlcount_0c >> 3; + bdlcount_0c_div16 = bdlcount_0c >> 4; + + if (ddr_md == 0) { /* 1584Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4 + + bdlcount_0c_div8; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4 + + bdlcount_0c_div16; + } else { /* 1856Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4; + } + + if (dqsgd_0c <= lcdl_judge1) + continue; + + if (dqsgd_0c <= lcdl_judge2) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, + (dqsgd_0c - bdlcount_0c_div8) | + regval); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + gatesl_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGD_0, regval | + (gatesl_0c + 1)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rdqsd_0c = (regval & 0xFF00) >> 8; + rdqsnd_0c = (regval & 0xFF0000) >> 16; + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + (regval & 0xFF0000FF) | + ((rdqsd_0c + + bdlcount_0c_div4) << 8) | + ((rdqsnd_0c + + bdlcount_0c_div4) << 16)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + } + } + mmio_write_32(DBSC_DBPDRGA_0, 0x2); + mmio_write_32(DBSC_DBPDRGD_0, 0x7D81E37); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + mmio_write_32(DBSC_DBCALCNF, (64000000 / REFRESH_RATE) + 0x01000000); + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 99 / 125) + 0x00080000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 116 / 125) + 0x00080000); + } + + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + + if (pdqsr_ctl == 1) { + mmio_write_32(0xE67F0018, 0x00000001); + regval = mmio_read_32(0x40000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + /* + * Initial_Step9( Initial End ) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting /* only for non qos_init */ + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + + if (pdqsr_ctl == 0) + mmio_write_32(0xE67F0018, 0x00000001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif + + return 1; +} + +static uint32_t recovery_from_backup_mode(uint32_t ddr_backup) +{ + /* + * recovery_Step0(DBSC Setting 1) / same "init_ddr" + */ + uint32_t r2, r5, r6, r7, r12, i; + uint32_t ddr_md; + uint32_t err; + uint32_t regval, j; + uint32_t dqsgd_0c, bdlcount_0c, bdlcount_0c_div2, bdlcount_0c_div4; + uint32_t bdlcount_0c_div8, bdlcount_0c_div16; + uint32_t gatesl_0c, rdqsd_0c, rdqsnd_0c, rbd_0c[4]; + uint32_t pdqsr_ctl, lcdl_ctl, lcdl_judge1, lcdl_judge2; + uint32_t pdr_ctl; + uint32_t byp_ctl; + + if ((mmio_read_32(0xFFF00044) & 0x000000FF) == 0x00000000) { + pdqsr_ctl = 1; + lcdl_ctl = 1; + pdr_ctl = 1; + byp_ctl = 1; + } else { + pdqsr_ctl = 0; + lcdl_ctl = 0; + pdr_ctl = 0; + byp_ctl = 0; + } + + /* Judge the DDR bit rate (ddr_md : 0 = 1584Mbps, 1 = 1856Mbps) */ + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & BIT(0); + + /* 1584Mbps setting */ + if (ddr_md == 0) { + mmio_write_32(CPG_CPGWPR, 0x5A5AFFFF); + mmio_write_32(CPG_CPGWPCR, 0xA5A50000); + + mmio_write_32(CPG_SRCR4, 0x20000000); + + mmio_write_32(0xE61500DC, 0xe2200000); /* Change to 1584Mbps */ + while (!(mmio_read_32(CPG_PLLECR) & BIT(11))) + ; + + mmio_write_32(CPG_SRSTCLR4, 0x20000000); + + mmio_write_32(CPG_CPGWPCR, 0xA5A50001); + } + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); + +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); +#endif + +#if RCAR_DRAM_DDR3L_MEMDUAL == 1 + r2 = mmio_read_32(0xE6790614); + mmio_write_32(0xE6790614, r2 | 0x3); /* MCS1_N/MODT1 are activated. */ +#endif + + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR0, 0x0000000D); + mmio_write_32(DBSC_DBTR1, 0x00000009); + } + + mmio_write_32(DBSC_DBTR2, 0x00000000); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR3, 0x0000000D); + mmio_write_32(DBSC_DBTR4, 0x000D000D); + mmio_write_32(DBSC_DBTR5, 0x0000002D); + mmio_write_32(DBSC_DBTR6, 0x00000020); + } + + mmio_write_32(DBSC_DBTR7, 0x00060006); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000A); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x000000CE); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071F0305); + mmio_write_32(DBSC_DBTR17, 0x040C0000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR8, 0x00000021); + mmio_write_32(DBSC_DBTR9, 0x00000007); + mmio_write_32(DBSC_DBTR10, 0x0000000E); + mmio_write_32(DBSC_DBTR11, 0x0000000C); + mmio_write_32(DBSC_DBTR12, 0x00140014); + mmio_write_32(DBSC_DBTR13, 0x000000F2); + mmio_write_32(DBSC_DBTR14, 0x00170006); + mmio_write_32(DBSC_DBTR15, 0x00060005); + mmio_write_32(DBSC_DBTR16, 0x09210507); + mmio_write_32(DBSC_DBTR17, 0x040E0000); + } + + mmio_write_32(DBSC_DBTR18, 0x00000200); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x020000D6); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBTR19, 0x0129004B); + mmio_write_32(DBSC_DBTR20, 0x020000FB); + } + + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + mmio_write_32(DBSC_DBSCHRW1, 0x00000046); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0D050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0306030C); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_SCFCTST0, 0x0C050B03); + mmio_write_32(DBSC_SCFCTST1, 0x0305030C); + } + + /* + * recovery_Step1(PHY setting 1) + */ + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01840001); + mmio_write_32(DBSC_DBCMD, 0x0A840000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); /* DDR_PLLCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); /* DDR_PGCR1 */ + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); /* DDR_DXCCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); /* DDR_ACIOCR0 */ + mmio_write_32(DBSC_DBPDRGD_0, 0x33C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 792 / 125) - + 400 + 0x08B00000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, (REFRESH_RATE * 928 / 125) - + 400 + 0x0A300000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x35A00D77); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88B400); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x2A8A2C28); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x30005E00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0014CB49); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000F14); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000046); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + if (REFRESH_RATE > 3900) + mmio_write_32(DBSC_DBPDRGD_0, 0x18); /* [7]SRT=0 */ + else + mmio_write_32(DBSC_DBPDRGD_0, 0x98); /* [7]SRT=1 */ + } else { /* 1856Mbps */ + if (REFRESH_RATE > 3900) + mmio_write_32(DBSC_DBPDRGD_0, 0x20); /* [7]SRT=0 */ + else + mmio_write_32(DBSC_DBPDRGD_0, 0xA0); /* [7]SRT=1 */ + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BBAD); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); /* DDR_DSGCR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x40010000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000092); /* DDR_ZQ0DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC2C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000096); /* DDR_ZQ1DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC4285FBF); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000009A); /* DDR_ZQ2DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0xC2C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00050001); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + /* ddr backupmode end */ + if (ddr_backup) + NOTICE("BL2: [WARM_BOOT]\n"); + else + NOTICE("BL2: [COLD_BOOT]\n"); + + err = rcar_dram_update_boot_status(ddr_backup); + if (err) { + NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n"); + return INITDRAM_ERR_I; + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000092); /* DDR_ZQ0DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x02C59AB5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000096); /* DDR_ZQ1DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04285FBF); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000009A); /* DDR_ZQ2DR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x02C59AB5); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x08000000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00000003); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); /* DDR_ZQCR */ + + /* Select setting value in bps */ + if (ddr_md == 0) /* 1584Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + else /* 1856Mbps */ + mmio_write_32(DBSC_DBPDRGD_0, 0x04058A00); + + mmio_write_32(DBSC_DBPDRGA_0, 0x0000000C); + mmio_write_32(DBSC_DBPDRGD_0, 0x18000040); + + /* + * recovery_Step2(PHY setting 2) + */ + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + + mmio_write_32(DBSC_DBCALCNF, (64000000 / REFRESH_RATE) + 0x01000000); + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + + /* Select setting value in bps */ + if (ddr_md == 0) { /* 1584Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 99 / 125) + 0x00080000); + } else { /* 1856Mbps */ + mmio_write_32(DBSC_DBRFCNF1, + (REFRESH_RATE * 116 / 125) + 0x00080000); + } + + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBCMD, 0x0A840001); + while (mmio_read_32(DBSC_DBWAIT) & BIT(0)) + ; + + mmio_write_32(DBSC_DBCMD, 0x00000000); + + mmio_write_32(DBSC_DBCMD, 0x04840010); + while (mmio_read_32(DBSC_DBWAIT) & BIT(0)) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); /* DDR_PIR */ + mmio_write_32(DBSC_DBPDRGD_0, 0x00010701); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); /* DDR_PGSR0 */ + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + r2 | ((r6 + (r5 << 1)) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00C0); + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00D8); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00011001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00012001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00014001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (pdqsr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00018001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = ((mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 0x8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + r12 = r5 >> 0x2; + + if (r12 < r6) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r7 + 0x1) & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | ((r6 - r12) & 0xFF)); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | (r7 & 0x7)); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + r2 | + ((r6 + r5 + (r5 >> 1) + r12) & 0xFF)); + } + } + + if (pdqsr_ctl == 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR always off */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000008); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + if (lcdl_ctl == 1) { + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000B0 + i * 0x20); + dqsgd_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x000000FF; + mmio_write_32(DBSC_DBPDRGA_0, 0x000000B1 + i * 0x20); + bdlcount_0c = (mmio_read_32(DBSC_DBPDRGD_0) & + 0x0000FF00) >> 8; + bdlcount_0c_div2 = (bdlcount_0c >> 1); + bdlcount_0c_div4 = (bdlcount_0c >> 2); + bdlcount_0c_div8 = (bdlcount_0c >> 3); + bdlcount_0c_div16 = (bdlcount_0c >> 4); + + if (ddr_md == 0) { /* 1584Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4 + + bdlcount_0c_div8; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4 + + bdlcount_0c_div16; + } else { /* 1856Mbps */ + lcdl_judge1 = bdlcount_0c_div2 + + bdlcount_0c_div4; + lcdl_judge2 = bdlcount_0c + + bdlcount_0c_div4; + } + + if (dqsgd_0c <= lcdl_judge1) + continue; + + if (dqsgd_0c <= lcdl_judge2) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, + (dqsgd_0c - bdlcount_0c_div8) | + regval); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFF00; + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + gatesl_0c = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xFFFFFFF8; + mmio_write_32(DBSC_DBPDRGD_0, + regval | (gatesl_0c + 1)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0); + rdqsd_0c = (regval & 0xFF00) >> 8; + rdqsnd_0c = (regval & 0xFF0000) >> 16; + mmio_write_32(DBSC_DBPDRGA_0, 0xAF + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, + (regval & 0xFF0000FF) | + ((rdqsd_0c + + bdlcount_0c_div4) << 8) | + ((rdqsnd_0c + + bdlcount_0c_div4) << 16)); + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = (regval) & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAA + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = (mmio_read_32(DBSC_DBPDRGD_0)); + rbd_0c[0] = regval & 0x1f; + rbd_0c[1] = (regval >> 8) & 0x1f; + rbd_0c[2] = (regval >> 16) & 0x1f; + rbd_0c[3] = (regval >> 24) & 0x1f; + mmio_write_32(DBSC_DBPDRGA_0, 0xAB + i * 0x20); + regval = mmio_read_32(DBSC_DBPDRGD_0) & + 0xE0E0E0E0; + for (j = 0; j < 4; j++) { + rbd_0c[j] = rbd_0c[j] + + bdlcount_0c_div4; + if (rbd_0c[j] > 0x1F) + rbd_0c[j] = 0x1F; + regval = regval | (rbd_0c[j] << 8 * j); + } + mmio_write_32(DBSC_DBPDRGD_0, regval); + } + } + mmio_write_32(DBSC_DBPDRGA_0, 0x00000002); + mmio_write_32(DBSC_DBPDRGD_0, 0x07D81E37); + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + if (byp_ctl == 1) + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C720); + else + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + /* + * recovery_Step3(DBSC Setting 2) + */ + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + + if (pdqsr_ctl == 1) { + mmio_write_32(0xE67F0018, 0x00000001); + regval = mmio_read_32(0x40000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGD_0, regval); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + } + + /* PDR dynamic */ + if (pdr_ctl == 1) { + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E3); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000103); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000000); + } + + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + +#ifdef ddr_qos_init_setting /* only for non qos_init */ + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + mmio_write_32(DBSC_DBSCHCNT0, 0x000f0037); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010); + + if (pdqsr_ctl == 0) + mmio_write_32(0xE67F0018, 0x00000001); + + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); +#endif + + return 1; + +} /* recovery_from_backup_mode */ + +/* + * init_ddr : MD19=0,DDR3L,1584Mbps / MD19=1,DDR3L,1856Mbps + */ + +/* + * DDR Initialize entry for IPL + */ +int32_t rcar_dram_init(void) +{ + uint32_t dataL; + uint32_t failcount; + uint32_t md = 0; + uint32_t ddr = 0; + uint32_t ddr_backup; + + md = *((volatile uint32_t*)RST_MODEMR); + ddr = (md & 0x00080000) >> 19; + if (ddr == 0x0) + NOTICE("BL2: DDR1584(%s)\n", RCAR_E3_DDR_VERSION); + else if (ddr == 0x1) + NOTICE("BL2: DDR1856(%s)\n", RCAR_E3_DDR_VERSION); + + rcar_dram_get_boot_status(&ddr_backup); + + if (ddr_backup == DRAM_BOOT_STATUS_WARM) + dataL = recovery_from_backup_mode(ddr_backup); /* WARM boot */ + else + dataL = init_ddr(); /* COLD boot */ + + if (dataL == 1) + failcount = 0; + else + failcount = 1; + + if (failcount == 0) + return INITDRAM_OK; + else + return INITDRAM_NG; + +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c new file mode 100644 index 0000000..5410771 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c @@ -0,0 +1,339 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "boot_init_dram.h" +#include "rcar_def.h" +#include "../ddr_regs.h" + +static uint32_t init_ddr_v3m_1600(void) +{ + uint32_t i, r2, r5, r6, r7, r12; + + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + mmio_write_32(DBSC_DBKIND, 0x00000007); +#if RCAR_DRAM_DDR3L_MEMCONF == 0 + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x0f030a02); // 1GB: Eagle +#else + mmio_write_32(DBSC_DBMEMCONF_0_0, 0x10030a02); // 2GB: V3MSK +#endif + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + mmio_write_32(DBSC_DBTR0, 0x0000000B); + mmio_write_32(DBSC_DBTR1, 0x00000008); + mmio_write_32(DBSC_DBTR3, 0x0000000B); + mmio_write_32(DBSC_DBTR4, 0x000B000B); + mmio_write_32(DBSC_DBTR5, 0x00000027); + mmio_write_32(DBSC_DBTR6, 0x0000001C); + mmio_write_32(DBSC_DBTR7, 0x00060006); + mmio_write_32(DBSC_DBTR8, 0x00000020); + mmio_write_32(DBSC_DBTR9, 0x00000006); + mmio_write_32(DBSC_DBTR10, 0x0000000C); + mmio_write_32(DBSC_DBTR11, 0x0000000B); + mmio_write_32(DBSC_DBTR12, 0x00120012); + mmio_write_32(DBSC_DBTR13, 0x01180118); + mmio_write_32(DBSC_DBTR14, 0x00140005); + mmio_write_32(DBSC_DBTR15, 0x00050004); + mmio_write_32(DBSC_DBTR16, 0x071D0305); + mmio_write_32(DBSC_DBTR17, 0x040C0010); + mmio_write_32(DBSC_DBTR18, 0x00000200); + mmio_write_32(DBSC_DBTR19, 0x01000040); + mmio_write_32(DBSC_DBTR20, 0x02000120); + mmio_write_32(DBSC_DBTR21, 0x00040004); + mmio_write_32(DBSC_DBBL, 0x00000000); + mmio_write_32(DBSC_DBODT0, 0x00000001); + mmio_write_32(DBSC_DBADJ0, 0x00000001); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00082010); + mmio_write_32(DBSC_DBCAM0CNF2, 0x00002000); + mmio_write_32(DBSC_DBSCHCNT0, 0x080f003f); + mmio_write_32(DBSC_DBSCHCNT1, 0x00001010); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHRW0, 0x00000200); + mmio_write_32(DBSC_DBSCHRW1, 0x00000040); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000600); + mmio_write_32(DBSC_DBSCHQOS41, 0x00000480); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000400); + mmio_write_32(DBSC_DBSCHQOS91, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS92, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000300); + mmio_write_32(DBSC_DBSCHQOS131, 0x00000240); + mmio_write_32(DBSC_DBSCHQOS132, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS133, 0x000000c0); + mmio_write_32(DBSC_DBSCHQOS140, 0x00000200); + mmio_write_32(DBSC_DBSCHQOS141, 0x00000180); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000100); + mmio_write_32(DBSC_DBSCHQOS151, 0x000000c0); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000080); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000040); + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + mmio_write_32(DBSC_DBCAM0CNF1, 0x00040C04); + mmio_write_32(DBSC_DBCAM0CNF2, 0x000001c4); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000003); + mmio_write_32(DBSC_DBSCHRW1, 0x001a0080); + mmio_write_32(DBSC_DBDFICNT_0, 0x00000010); + + mmio_write_32(DBSC_DBPDLK_0, 0x0000A55A); + mmio_write_32(DBSC_DBCMD, 0x01000001); + mmio_write_32(DBSC_DBCMD, 0x08000000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x80010000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000008); + mmio_write_32(DBSC_DBPDRGD_0, 0x000B8000); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058904); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000091); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000095); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000099); + mmio_write_32(DBSC_DBPDRGD_0, 0x0007BB6D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024641E); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010073); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x0C058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000090); + mmio_write_32(DBSC_DBPDRGD_0, 0x04058900); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0780C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(30))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGD_0, 0x08C0C170); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000022); + mmio_write_32(DBSC_DBPDRGD_0, 0x1000040B); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000023); + mmio_write_32(DBSC_DBPDRGD_0, 0x2D9C0B66); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000024); + mmio_write_32(DBSC_DBPDRGD_0, 0x2A88C400); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000025); + mmio_write_32(DBSC_DBPDRGD_0, 0x30005200); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000026); + mmio_write_32(DBSC_DBPDRGD_0, 0x0014A9C9); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000027); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000D70); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000028); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000004); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000029); + mmio_write_32(DBSC_DBPDRGD_0, 0x00000018); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003047); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000020); + mmio_write_32(DBSC_DBPDRGD_0, 0x00181884); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000001A); + mmio_write_32(DBSC_DBPDRGD_0, 0x13C03C10); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E7); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E8); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E9); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000107); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000108); + mmio_write_32(DBSC_DBPDRGD_0, 0x0D0D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000109); + mmio_write_32(DBSC_DBPDRGD_0, 0x000D0D0D); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010181); + mmio_write_32(DBSC_DBCMD, 0x08000001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010601); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = mmio_read_32(DBSC_DBPDRGD_0) & 0xFF; + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = mmio_read_32(DBSC_DBPDRGD_0) & 0x7; + + if (r6 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r7 + 1) & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r6); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | r7); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + (((r5 << 1) + r6) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00A0); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010801); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000005); + mmio_write_32(DBSC_DBPDRGD_0, 0xC1AA00B8); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x0001F001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C000285); + mmio_write_32(DBSC_DBPDRGA_0, 0x0000002C); + mmio_write_32(DBSC_DBPDRGD_0, 0x81003087); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00010401); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + for (i = 0; i < 4; i++) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB1 + i * 0x20); + r5 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF00) >> 8; + mmio_write_32(DBSC_DBPDRGA_0, 0xB4 + i * 0x20); + r6 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFF); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB3 + i * 0x20); + r7 = (mmio_read_32(DBSC_DBPDRGD_0) & 0x7); + r12 = (r5 >> 2); + if (r6 - r12 > 0) { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r7 + 1) & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, ((r6 - r12) & 0xFF) | r2); + } else { + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFFF8); + mmio_write_32(DBSC_DBPDRGA_0, 0xB2 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, (r7 & 0x7) | r2); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + r2 = (mmio_read_32(DBSC_DBPDRGD_0) & 0xFFFFFF00); + mmio_write_32(DBSC_DBPDRGA_0, 0xB0 + i * 0x20); + mmio_write_32(DBSC_DBPDRGD_0, r2 | + ((r6 + r5 + + (r5 >> 1) + r12) & 0xFF)); + } + } + + mmio_write_32(DBSC_DBPDRGA_0, 0x000000A0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000C0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x000000E0); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000100); + mmio_write_32(DBSC_DBPDRGD_0, 0x7C0002C5); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000001); + mmio_write_32(DBSC_DBPDRGD_0, 0x00015001); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000006); + while (!(mmio_read_32(DBSC_DBPDRGD_0) & BIT(0))) + ; + + mmio_write_32(DBSC_DBPDRGA_0, 0x00000003); + mmio_write_32(DBSC_DBPDRGD_0, 0x0380C700); + mmio_write_32(DBSC_DBPDRGA_0, 0x00000007); + while (mmio_read_32(DBSC_DBPDRGD_0) & BIT(30)) + ; + mmio_write_32(DBSC_DBPDRGA_0, 0x00000021); + mmio_write_32(DBSC_DBPDRGD_0, 0x0024643E); + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000000); + mmio_write_32(DBSC_DBBUS0CNF0, 0x00010001); + mmio_write_32(DBSC_DBCALCNF, 0x0100200E); + mmio_write_32(DBSC_DBRFCNF1, 0x00081860); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000); + mmio_write_32(DBSC_DBDFICUPDCNF, 0x40100001); + mmio_write_32(DBSC_DBRFEN, 0x00000001); + mmio_write_32(DBSC_DBACEN, 0x00000001); + mmio_write_32(DBSC_DBPDLK_0, 0x00000000); + mmio_write_32(0xE67F0024, 0x00000001); + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + + return INITDRAM_OK; +} + +int32_t rcar_dram_init(void) +{ + return init_ddr_v3m_1600(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c new file mode 100644 index 0000000..8d002de --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c @@ -0,0 +1,4484 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#include "ddr_regdef.h" +#include "init_dram_tbl_h3.h" +#include "init_dram_tbl_m3.h" +#include "init_dram_tbl_h3ver2.h" +#include "init_dram_tbl_m3n.h" +#include "boot_init_dram_regdef.h" +#include "boot_init_dram.h" +#include "dram_sub_func.h" +#include "micro_delay.h" +#include "rcar_def.h" + +#define DDR_BACKUPMODE +#define FATAL_MSG(x) NOTICE(x) + +/* variables */ +#ifdef RCAR_DDR_FIXED_LSI_TYPE +#ifndef RCAR_AUTO +#define RCAR_AUTO 99 +#define RCAR_H3 0 +#define RCAR_M3 1 +#define RCAR_M3N 2 +#define RCAR_E3 3 /* NON */ +#define RCAR_H3N 4 + +#define RZ_G2M 100U +#define RZ_G2H 101U +#define RZ_G2N 102U + +#define RCAR_CUT_10 0 +#define RCAR_CUT_11 1 +#define RCAR_CUT_20 10 +#define RCAR_CUT_30 20 +#endif +#ifndef RCAR_LSI +#define RCAR_LSI RCAR_AUTO +#endif + +#if (RCAR_LSI == RCAR_AUTO) +static uint32_t prr_product; +static uint32_t prr_cut; +#else +#if (RCAR_LSI == RCAR_H3) +static const uint32_t prr_product = PRR_PRODUCT_H3; +#elif(RCAR_LSI == RCAR_M3 || RCAR_LSI == RZ_G2M) +static const uint32_t prr_product = PRR_PRODUCT_M3; +#elif(RCAR_LSI == RCAR_M3N || RCAR_LSI == RZ_G2N) +static const uint32_t prr_product = PRR_PRODUCT_M3N; +#elif(RCAR_LSI == RCAR_H3N || RCAR_LSI == RZ_G2H) +static const uint32_t prr_product = PRR_PRODUCT_H3; +#endif /* RCAR_LSI */ + +#ifndef RCAR_LSI_CUT +static uint32_t prr_cut; +#else /* RCAR_LSI_CUT */ +#if (RCAR_LSI_CUT == RCAR_CUT_10) +static const uint32_t prr_cut = PRR_PRODUCT_10; +#elif(RCAR_LSI_CUT == RCAR_CUT_11) +static const uint32_t prr_cut = PRR_PRODUCT_11; +#elif(RCAR_LSI_CUT == RCAR_CUT_20) +static const uint32_t prr_cut = PRR_PRODUCT_20; +#elif(RCAR_LSI_CUT == RCAR_CUT_30) +static const uint32_t prr_cut = PRR_PRODUCT_30; +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_AUTO_NON */ +#else /* RCAR_DDR_FIXED_LSI_TYPE */ +static uint32_t prr_product; +static uint32_t prr_cut; +#endif /* RCAR_DDR_FIXED_LSI_TYPE */ + +static const uint32_t *p_ddr_regdef_tbl; +static uint32_t brd_clk; +static uint32_t brd_clkdiv; +static uint32_t brd_clkdiva; +static uint32_t ddr_mbps; +static uint32_t ddr_mbpsdiv; +static uint32_t ddr_tccd; +static uint32_t ddr_phycaslice; +static const struct _boardcnf *board_cnf; +static uint32_t ddr_phyvalid; +static uint32_t ddr_density[DRAM_CH_CNT][CS_CNT]; +static uint32_t ch_have_this_cs[CS_CNT] __aligned(64); +static uint32_t rdqdm_dly[DRAM_CH_CNT][CSAB_CNT][SLICE_CNT * 2][9]; +static uint32_t max_density; +static uint32_t ddr0800_mul; +static uint32_t ddr_mul; +static uint32_t DDR_PHY_SLICE_REGSET_OFS; +static uint32_t DDR_PHY_ADR_V_REGSET_OFS; +static uint32_t DDR_PHY_ADR_I_REGSET_OFS; +static uint32_t DDR_PHY_ADR_G_REGSET_OFS; +static uint32_t DDR_PI_REGSET_OFS; +static uint32_t DDR_PHY_SLICE_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_V_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_I_REGSET_SIZE; +static uint32_t DDR_PHY_ADR_G_REGSET_SIZE; +static uint32_t DDR_PI_REGSET_SIZE; +static uint32_t DDR_PHY_SLICE_REGSET_NUM; +static uint32_t DDR_PHY_ADR_V_REGSET_NUM; +static uint32_t DDR_PHY_ADR_I_REGSET_NUM; +static uint32_t DDR_PHY_ADR_G_REGSET_NUM; +static uint32_t DDR_PI_REGSET_NUM; +static uint32_t DDR_PHY_ADR_I_NUM; +#define DDR_PHY_REGSET_MAX 128 +#define DDR_PI_REGSET_MAX 320 +static uint32_t _cnf_DDR_PHY_SLICE_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_V_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_I_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PHY_ADR_G_REGSET[DDR_PHY_REGSET_MAX]; +static uint32_t _cnf_DDR_PI_REGSET[DDR_PI_REGSET_MAX]; +static uint32_t pll3_mode; +static uint32_t loop_max; +#ifdef DDR_BACKUPMODE +uint32_t ddr_backup; +/* #define DDR_BACKUPMODE_HALF //for Half channel(ch0,1 only) */ +#endif + +#ifdef ddr_qos_init_setting /* only for non qos_init */ +#define OPERATING_FREQ (400U) /* Mhz */ +#define BASE_SUB_SLOT_NUM (0x6U) +#define SUB_SLOT_CYCLE (0x7EU) /* 126 */ +#define QOSWT_WTSET0_CYCLE \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / \ + OPERATING_FREQ) /* unit:ns */ + +uint32_t get_refperiod(void) +{ + return QOSWT_WTSET0_CYCLE; +} +#else /* ddr_qos_init_setting // only for non qos_init */ +extern uint32_t get_refperiod(void); +#endif /* ddr_qos_init_setting // only for non qos_init */ + +#define _reg_PHY_RX_CAL_X_NUM 11 +static const uint32_t _reg_PHY_RX_CAL_X[_reg_PHY_RX_CAL_X_NUM] = { + _reg_PHY_RX_CAL_DQ0, + _reg_PHY_RX_CAL_DQ1, + _reg_PHY_RX_CAL_DQ2, + _reg_PHY_RX_CAL_DQ3, + _reg_PHY_RX_CAL_DQ4, + _reg_PHY_RX_CAL_DQ5, + _reg_PHY_RX_CAL_DQ6, + _reg_PHY_RX_CAL_DQ7, + _reg_PHY_RX_CAL_DM, + _reg_PHY_RX_CAL_DQS, + _reg_PHY_RX_CAL_FDBK +}; + +#define _reg_PHY_CLK_WRX_SLAVE_DELAY_NUM 10 +static const uint32_t _reg_PHY_CLK_WRX_SLAVE_DELAY + [_reg_PHY_CLK_WRX_SLAVE_DELAY_NUM] = { + _reg_PHY_CLK_WRDQ0_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ1_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ2_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ3_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ4_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ5_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ6_SLAVE_DELAY, + _reg_PHY_CLK_WRDQ7_SLAVE_DELAY, + _reg_PHY_CLK_WRDM_SLAVE_DELAY, + _reg_PHY_CLK_WRDQS_SLAVE_DELAY +}; + +#define _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM 9 +static const uint32_t _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY + [_reg_PHY_RDDQS_X_FALL_SLAVE_DELAY_NUM] = { + _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY, + _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY +}; + +#define _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM 9 +static const uint32_t _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [_reg_PHY_RDDQS_X_RISE_SLAVE_DELAY_NUM] = { + _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY, + _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY +}; + +#define _reg_PHY_PAD_TERM_X_NUM 8 +static const uint32_t _reg_PHY_PAD_TERM_X[_reg_PHY_PAD_TERM_X_NUM] = { + _reg_PHY_PAD_FDBK_TERM, + _reg_PHY_PAD_DATA_TERM, + _reg_PHY_PAD_DQS_TERM, + _reg_PHY_PAD_ADDR_TERM, + _reg_PHY_PAD_CLK_TERM, + _reg_PHY_PAD_CKE_TERM, + _reg_PHY_PAD_RST_TERM, + _reg_PHY_PAD_CS_TERM +}; + +#define _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM 10 +static const uint32_t _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM] = { + _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY, + _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY, + + _reg_PHY_GRP_SLAVE_DELAY_0, + _reg_PHY_GRP_SLAVE_DELAY_1, + _reg_PHY_GRP_SLAVE_DELAY_2, + _reg_PHY_GRP_SLAVE_DELAY_3 +}; + +/* Prototypes */ +static inline uint32_t vch_nxt(uint32_t pos); +static void cpg_write_32(uint32_t a, uint32_t v); +static void pll3_control(uint32_t high); +static inline void dsb_sev(void); +static void wait_dbcmd(void); +static void send_dbcmd(uint32_t cmd); +static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd); +static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata); +static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata); +static inline uint32_t ddr_regdef(uint32_t _regdef); +static inline uint32_t ddr_regdef_adr(uint32_t _regdef); +static inline uint32_t ddr_regdef_lsb(uint32_t _regdef); +static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef, + uint32_t val); +static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef); +static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val); +static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val); +static void ddr_setval_ach(uint32_t regdef, uint32_t val); +static void ddr_setval_ach_as(uint32_t regdef, uint32_t val); +static uint32_t ddr_getval(uint32_t ch, uint32_t regdef); +static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p); +static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p); +static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size); +static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val); +static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef); +static uint32_t ddrphy_regif_chk(void); +static inline void ddrphy_regif_idle(void); +static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps, + uint16_t cyc); +static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, + uint16_t *_js2); +static int16_t _f_scale_adj(int16_t ps); +static void ddrtbl_load(void); +static void ddr_config_sub(void); +static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz); +static void ddr_config_sub_h3v1x(void); +static void ddr_config(void); +static void dbsc_regset(void); +static void dbsc_regset_post(void); +static uint32_t dfi_init_start(void); +static void change_lpddr4_en(uint32_t mode); +static uint32_t set_term_code(void); +static void ddr_register_set(void); +static inline uint32_t wait_freqchgreq(uint32_t assert); +static inline void set_freqchgack(uint32_t assert); +static inline void set_dfifrequency(uint32_t freq); +static uint32_t pll3_freq(uint32_t on); +static void update_dly(void); +static uint32_t pi_training_go(void); +static uint32_t init_ddr(void); +static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick); +static uint32_t wdqdm_man1(void); +static uint32_t wdqdm_man(void); +static uint32_t rdqdm_man1(void); +static uint32_t rdqdm_man(void); + +static int32_t _find_change(uint64_t val, uint32_t dir); +static uint32_t _rx_offset_cal_updn(uint32_t code); +static uint32_t rx_offset_cal(void); +static uint32_t rx_offset_cal_hw(void); +static void adjust_rddqs_latency(void); +static void adjust_wpath_latency(void); + +struct ddrt_data { + int32_t init_temp; /* Initial Temperature (do) */ + uint32_t init_cal[4]; /* Initial io-code (4 is for H3) */ + uint32_t tcomp_cal[4]; /* Temp. compensated io-code (4 is for H3) */ +}; + +static struct ddrt_data tcal; + +static void pvtcode_update(void); +static void pvtcode_update2(void); +static void ddr_padcal_tcompensate_getinit(uint32_t override); + +/* load board configuration */ +#include "boot_init_dram_config.c" + +#ifndef DDR_FAST_INIT +static uint32_t rdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_nw[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2][9]; +static uint32_t rdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static uint32_t rdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT * 2]; +static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn); +static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn); + +static uint32_t wdqdm_le[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_te[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_dly[DRAM_CH_CNT][CS_CNT][SLICE_CNT][9]; +static uint32_t wdqdm_st[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static uint32_t wdqdm_win[DRAM_CH_CNT][CS_CNT][SLICE_CNT]; +static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn); +static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn); +#endif/* DDR_FAST_INIT */ + +/* macro for channel selection loop */ +static inline uint32_t vch_nxt(uint32_t pos) +{ + uint32_t posn; + + for (posn = pos; posn < DRAM_CH_CNT; posn++) { + if (ddr_phyvalid & (1U << posn)) + break; + } + return posn; +} + +#define foreach_vch(ch) \ +for (ch = vch_nxt(0); ch < DRAM_CH_CNT; ch = vch_nxt(ch + 1)) + +#define foreach_ech(ch) \ +for (ch = 0; ch < DRAM_CH_CNT; ch++) + +/* Printing functions */ +#define MSG_LF(...) + +/* clock settings, reset control */ +static void cpg_write_32(uint32_t a, uint32_t v) +{ + mmio_write_32(CPG_CPGWPR, ~v); + mmio_write_32(a, v); +} + +static void pll3_control(uint32_t high) +{ + uint32_t data_l, data_div, data_mul, tmp_div; + + if (high) { + tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) / + (brd_clk * ddr_mul) / 2; + data_mul = ((ddr_mul * tmp_div) - 1) << 24; + pll3_mode = 1; + loop_max = 2; + } else { + tmp_div = 3999 * brd_clkdiv * (brd_clkdiva + 1) / + (brd_clk * ddr0800_mul) / 2; + data_mul = ((ddr0800_mul * tmp_div) - 1) << 24; + pll3_mode = 0; + loop_max = 8; + } + + switch (tmp_div) { + case 1: + data_div = 0; + break; + case 2: + case 3: + case 4: + data_div = tmp_div; + break; + default: + data_div = 6; + data_mul = (data_mul * tmp_div) / 3; + break; + } + data_mul = data_mul | (brd_clkdiva << 7); + + /* PLL3 disable */ + data_l = mmio_read_32(CPG_PLLECR) & ~CPG_PLLECR_PLL3E_BIT; + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + if ((prr_product == PRR_PRODUCT_M3) || + ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_20))) { + /* PLL3 DIV resetting(Lowest value:3) */ + data_l = 0x00030003 | (0xFF80FF80 & mmio_read_32(CPG_FRQCRD)); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* zb3 clk stop */ + data_l = CPG_ZB3CKCR_ZB3ST_BIT | mmio_read_32(CPG_ZB3CKCR); + cpg_write_32(CPG_ZB3CKCR, data_l); + dsb_sev(); + + /* PLL3 enable */ + data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR); + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* PLL3 DIV resetting (Highest value:0) */ + data_l = (0xFF80FF80 & mmio_read_32(CPG_FRQCRD)); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + /* PLL3 multiplie set */ + cpg_write_32(CPG_PLL3CR, data_mul); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* PLL3 DIV resetting(Target value) */ + data_l = (data_div << 16) | data_div | + (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80); + cpg_write_32(CPG_FRQCRD, data_l); + dsb_sev(); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + + /* zb3 clk start */ + data_l = (~CPG_ZB3CKCR_ZB3ST_BIT) & mmio_read_32(CPG_ZB3CKCR); + cpg_write_32(CPG_ZB3CKCR, data_l); + dsb_sev(); + + } else { /* H3Ver.3.0/M3N/V3H */ + + /* PLL3 multiplie set */ + cpg_write_32(CPG_PLL3CR, data_mul); + dsb_sev(); + + /* PLL3 DIV set(Target value) */ + data_l = (data_div << 16) | data_div | + (mmio_read_32(CPG_FRQCRD) & 0xFF80FF80); + cpg_write_32(CPG_FRQCRD, data_l); + + /* DIV SET KICK */ + data_l = CPG_FRQCRB_KICK_BIT | mmio_read_32(CPG_FRQCRB); + cpg_write_32(CPG_FRQCRB, data_l); + dsb_sev(); + + /* PLL3 enable */ + data_l = CPG_PLLECR_PLL3E_BIT | mmio_read_32(CPG_PLLECR); + cpg_write_32(CPG_PLLECR, data_l); + dsb_sev(); + + do { + data_l = mmio_read_32(CPG_PLLECR); + } while ((data_l & CPG_PLLECR_PLL3ST_BIT) == 0); + dsb_sev(); + } +} + +/* barrier */ +static inline void dsb_sev(void) +{ + __asm__ __volatile__("dsb sy"); +} + +/* DDR memory register access */ +static void wait_dbcmd(void) +{ + uint32_t data_l; + /* dummy read */ + data_l = mmio_read_32(DBSC_DBCMD); + dsb_sev(); + while (1) { + /* wait DBCMD 1=busy, 0=ready */ + data_l = mmio_read_32(DBSC_DBWAIT); + dsb_sev(); + if ((data_l & 0x00000001) == 0x00) + break; + } +} + +static void send_dbcmd(uint32_t cmd) +{ + /* dummy read */ + wait_dbcmd(); + mmio_write_32(DBSC_DBCMD, cmd); + dsb_sev(); +} + +static void dbwait_loop(uint32_t wait_loop) +{ + uint32_t i; + + for (i = 0; i < wait_loop; i++) + wait_dbcmd(); +} + +/* DDRPHY register access (raw) */ +static uint32_t reg_ddrphy_read(uint32_t phyno, uint32_t regadd) +{ + uint32_t val; + uint32_t loop; + + val = 0; + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + } + dsb_sev(); + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + } + (void)val; + } else { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00004000); + dsb_sev(); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != + (regadd | 0x0000C000)) { + dsb_sev(); + }; + val = mmio_read_32(DBSC_DBPDRGA(phyno)); + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + + dsb_sev(); + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + (void)val; + } + return val; +} + +static void reg_ddrphy_write(uint32_t phyno, uint32_t regadd, uint32_t regdata) +{ + uint32_t val; + uint32_t loop; + + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGA(phyno)); + dsb_sev(); + } + mmio_write_32(DBSC_DBPDRGD(phyno), regdata); + dsb_sev(); + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(phyno)); + dsb_sev(); + } + } else { + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGD(phyno), regdata); + dsb_sev(); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != + (regadd | 0x00008000)) { + dsb_sev(); + }; + mmio_write_32(DBSC_DBPDRGA(phyno), regadd | 0x00008000); + + while (mmio_read_32(DBSC_DBPDRGA(phyno)) != regadd) { + dsb_sev(); + }; + dsb_sev(); + + mmio_write_32(DBSC_DBPDRGA(phyno), regadd); + } + (void)val; +} + +static void reg_ddrphy_write_a(uint32_t regadd, uint32_t regdata) +{ + uint32_t ch; + uint32_t val; + uint32_t loop; + + if ((prr_product != PRR_PRODUCT_M3N) && + (prr_product != PRR_PRODUCT_V3H)) { + foreach_vch(ch) { + mmio_write_32(DBSC_DBPDRGA(ch), regadd); + dsb_sev(); + } + + foreach_vch(ch) { + mmio_write_32(DBSC_DBPDRGD(ch), regdata); + dsb_sev(); + } + + for (loop = 0; loop < loop_max; loop++) { + val = mmio_read_32(DBSC_DBPDRGD(0)); + dsb_sev(); + } + (void)val; + } else { + foreach_vch(ch) { + reg_ddrphy_write(ch, regadd, regdata); + dsb_sev(); + } + } +} + +static inline void ddrphy_regif_idle(void) +{ + uint32_t val; + + val = reg_ddrphy_read(0, ddr_regdef_adr(_reg_PI_INT_STATUS)); + dsb_sev(); + (void)val; +} + +/* DDRPHY register access (field modify) */ +static inline uint32_t ddr_regdef(uint32_t _regdef) +{ + return p_ddr_regdef_tbl[_regdef]; +} + +static inline uint32_t ddr_regdef_adr(uint32_t _regdef) +{ + return DDR_REGDEF_ADR(p_ddr_regdef_tbl[_regdef]); +} + +static inline uint32_t ddr_regdef_lsb(uint32_t _regdef) +{ + return DDR_REGDEF_LSB(p_ddr_regdef_tbl[_regdef]); +} + +static void ddr_setval_s(uint32_t ch, uint32_t slice, uint32_t _regdef, + uint32_t val) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice; + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1) << lsb; + + tmp = reg_ddrphy_read(ch, adr); + tmp = (tmp & (~msk)) | ((val << lsb) & msk); + reg_ddrphy_write(ch, adr, tmp); +} + +static uint32_t ddr_getval_s(uint32_t ch, uint32_t slice, uint32_t _regdef) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef) + 0x80 * slice; + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1); + + tmp = reg_ddrphy_read(ch, adr); + tmp = (tmp >> lsb) & msk; + + return tmp; +} + +static void ddr_setval(uint32_t ch, uint32_t regdef, uint32_t val) +{ + ddr_setval_s(ch, 0, regdef, val); +} + +static void ddr_setval_ach_s(uint32_t slice, uint32_t regdef, uint32_t val) +{ + uint32_t ch; + + foreach_vch(ch) + ddr_setval_s(ch, slice, regdef, val); +} + +static void ddr_setval_ach(uint32_t regdef, uint32_t val) +{ + ddr_setval_ach_s(0, regdef, val); +} + +static void ddr_setval_ach_as(uint32_t regdef, uint32_t val) +{ + uint32_t slice; + + for (slice = 0; slice < SLICE_CNT; slice++) + ddr_setval_ach_s(slice, regdef, val); +} + +static uint32_t ddr_getval(uint32_t ch, uint32_t regdef) +{ + return ddr_getval_s(ch, 0, regdef); +} + +static uint32_t ddr_getval_ach(uint32_t regdef, uint32_t *p) +{ + uint32_t ch; + + foreach_vch(ch) + p[ch] = ddr_getval_s(ch, 0, regdef); + return p[0]; +} + +static uint32_t ddr_getval_ach_as(uint32_t regdef, uint32_t *p) +{ + uint32_t ch, slice; + uint32_t *pp; + + pp = p; + foreach_vch(ch) + for (slice = 0; slice < SLICE_CNT; slice++) + *pp++ = ddr_getval_s(ch, slice, regdef); + return p[0]; +} + +/* handling functions for setteing ddrphy value table */ +static void _tblcopy(uint32_t *to, const uint32_t *from, uint32_t size) +{ + uint32_t i; + + for (i = 0; i < size; i++) { + to[i] = from[i]; + } +} + +static void ddrtbl_setval(uint32_t *tbl, uint32_t _regdef, uint32_t val) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t adrmsk; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef); + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1) << lsb; + + if (adr < 0x400) { + adrmsk = 0xff; + } else { + adrmsk = 0x7f; + } + + tmp = tbl[adr & adrmsk]; + tmp = (tmp & (~msk)) | ((val << lsb) & msk); + tbl[adr & adrmsk] = tmp; +} + +static uint32_t ddrtbl_getval(uint32_t *tbl, uint32_t _regdef) +{ + uint32_t adr; + uint32_t lsb; + uint32_t len; + uint32_t msk; + uint32_t tmp; + uint32_t adrmsk; + uint32_t regdef; + + regdef = ddr_regdef(_regdef); + adr = DDR_REGDEF_ADR(regdef); + len = DDR_REGDEF_LEN(regdef); + lsb = DDR_REGDEF_LSB(regdef); + if (len == 0x20) + msk = 0xffffffff; + else + msk = ((1U << len) - 1); + + if (adr < 0x400) { + adrmsk = 0xff; + } else { + adrmsk = 0x7f; + } + + tmp = tbl[adr & adrmsk]; + tmp = (tmp >> lsb) & msk; + + return tmp; +} + +/* DDRPHY register access handling */ +static uint32_t ddrphy_regif_chk(void) +{ + uint32_t tmp_ach[DRAM_CH_CNT]; + uint32_t ch; + uint32_t err; + uint32_t PI_VERSION_CODE; + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3)) { + PI_VERSION_CODE = 0x2041; /* H3 Ver.1.x/M3-W */ + } else { + PI_VERSION_CODE = 0x2040; /* H3 Ver.2.0 or later/M3-N/V3H */ + } + + ddr_getval_ach(_reg_PI_VERSION, (uint32_t *)tmp_ach); + err = 0; + foreach_vch(ch) { + if (tmp_ach[ch] != PI_VERSION_CODE) + err = 1; + } + return err; +} + +/* functions and parameters for timing setting */ +struct _jedec_spec1 { + uint16_t fx3; + uint8_t rlwodbi; + uint8_t rlwdbi; + uint8_t WL; + uint8_t nwr; + uint8_t nrtp; + uint8_t odtlon; + uint8_t MR1; + uint8_t MR2; +}; + +#define JS1_USABLEC_SPEC_LO 2 +#define JS1_USABLEC_SPEC_HI 5 +#define JS1_FREQ_TBL_NUM 8 +#define JS1_MR1(f) (0x04 | ((f) << 4)) +#define JS1_MR2(f) (0x00 | ((f) << 3) | (f)) +const struct _jedec_spec1 js1[JS1_FREQ_TBL_NUM] = { + /* 533.333Mbps */ + { 800, 6, 6, 4, 6, 8, 0, JS1_MR1(0), JS1_MR2(0) | 0x40 }, + /* 1066.666Mbps */ + { 1600, 10, 12, 8, 10, 8, 0, JS1_MR1(1), JS1_MR2(1) | 0x40 }, + /* 1600.000Mbps */ + { 2400, 14, 16, 12, 16, 8, 6, JS1_MR1(2), JS1_MR2(2) | 0x40 }, + /* 2133.333Mbps */ + { 3200, 20, 22, 10, 20, 8, 4, JS1_MR1(3), JS1_MR2(3) }, + /* 2666.666Mbps */ + { 4000, 24, 28, 12, 24, 10, 4, JS1_MR1(4), JS1_MR2(4) }, + /* 3200.000Mbps */ + { 4800, 28, 32, 14, 30, 12, 6, JS1_MR1(5), JS1_MR2(5) }, + /* 3733.333Mbps */ + { 5600, 32, 36, 16, 34, 14, 6, JS1_MR1(6), JS1_MR2(6) }, + /* 4266.666Mbps */ + { 6400, 36, 40, 18, 40, 16, 8, JS1_MR1(7), JS1_MR2(7) } +}; + +struct _jedec_spec2 { + uint16_t ps; + uint16_t cyc; +}; + +#define js2_tsr 0 +#define js2_txp 1 +#define js2_trtp 2 +#define js2_trcd 3 +#define js2_trppb 4 +#define js2_trpab 5 +#define js2_tras 6 +#define js2_twr 7 +#define js2_twtr 8 +#define js2_trrd 9 +#define js2_tppd 10 +#define js2_tfaw 11 +#define js2_tdqsck 12 +#define js2_tckehcmd 13 +#define js2_tckelcmd 14 +#define js2_tckelpd 15 +#define js2_tmrr 16 +#define js2_tmrw 17 +#define js2_tmrd 18 +#define js2_tzqcalns 19 +#define js2_tzqlat 20 +#define js2_tiedly 21 +#define js2_tODTon_min 22 +#define JS2_TBLCNT 23 + +#define js2_trcpb (JS2_TBLCNT) +#define js2_trcab (JS2_TBLCNT + 1) +#define js2_trfcab (JS2_TBLCNT + 2) +#define JS2_CNT (JS2_TBLCNT + 3) + +#ifndef JS2_DERATE +#define JS2_DERATE 0 +#endif +const struct _jedec_spec2 jedec_spec2[2][JS2_TBLCNT] = { + { +/*tSR */ {15000, 3}, +/*tXP */ {7500, 3}, +/*tRTP */ {7500, 8}, +/*tRCD */ {18000, 4}, +/*tRPpb */ {18000, 3}, +/*tRPab */ {21000, 3}, +/*tRAS */ {42000, 3}, +/*tWR */ {18000, 4}, +/*tWTR */ {10000, 8}, +/*tRRD */ {10000, 4}, +/*tPPD */ {0, 0}, +/*tFAW */ {40000, 0}, +/*tDQSCK*/ {3500, 0}, +/*tCKEHCMD*/ {7500, 3}, +/*tCKELCMD*/ {7500, 3}, +/*tCKELPD*/ {7500, 3}, +/*tMRR*/ {0, 8}, +/*tMRW*/ {10000, 10}, +/*tMRD*/ {14000, 10}, +/*tZQCALns*/ {1000 * 10, 0}, +/*tZQLAT*/ {30000, 10}, +/*tIEdly*/ {12500, 0}, +/*tODTon_min*/ {1500, 0} + }, { +/*tSR */ {15000, 3}, +/*tXP */ {7500, 3}, +/*tRTP */ {7500, 8}, +/*tRCD */ {19875, 4}, +/*tRPpb */ {19875, 3}, +/*tRPab */ {22875, 3}, +/*tRAS */ {43875, 3}, +/*tWR */ {18000, 4}, +/*tWTR */ {10000, 8}, +/*tRRD */ {11875, 4}, +/*tPPD */ {0, 0}, +/*tFAW */ {40000, 0}, +/*tDQSCK*/ {3600, 0}, +/*tCKEHCMD*/ {7500, 3}, +/*tCKELCMD*/ {7500, 3}, +/*tCKELPD*/ {7500, 3}, +/*tMRR*/ {0, 8}, +/*tMRW*/ {10000, 10}, +/*tMRD*/ {14000, 10}, +/*tZQCALns*/ {1000 * 10, 0}, +/*tZQLAT*/ {30000, 10}, +/*tIEdly*/ {12500, 0}, +/*tODTon_min*/ {1500, 0} + } +}; + +const uint16_t jedec_spec2_trfc_ab[7] = { +/* 4Gb, 6Gb, 8Gb,12Gb, 16Gb, 24Gb(non), 32Gb(non) */ + 130, 180, 180, 280, 280, 560, 560 +}; + +static uint32_t js1_ind; +static uint16_t js2[JS2_CNT]; +static uint8_t RL; +static uint8_t WL; + +static uint16_t _f_scale(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, uint32_t ps, + uint16_t cyc) +{ + uint32_t tmp; + uint32_t div; + + tmp = (((uint32_t)(ps) + 9) / 10) * _ddr_mbps; + div = tmp / (200000 * _ddr_mbpsdiv); + if (tmp != (div * 200000 * _ddr_mbpsdiv)) + div = div + 1; + + if (div > cyc) + return (uint16_t)div; + return cyc; +} + +static void _f_scale_js2(uint32_t _ddr_mbps, uint32_t _ddr_mbpsdiv, + uint16_t *_js2) +{ + int i; + + for (i = 0; i < JS2_TBLCNT; i++) { + _js2[i] = _f_scale(_ddr_mbps, _ddr_mbpsdiv, + 1UL * jedec_spec2[JS2_DERATE][i].ps, + jedec_spec2[JS2_DERATE][i].cyc); + } + + _js2[js2_trcpb] = _js2[js2_tras] + _js2[js2_trppb]; + _js2[js2_trcab] = _js2[js2_tras] + _js2[js2_trpab]; +} + +/* scaler for DELAY value */ +static int16_t _f_scale_adj(int16_t ps) +{ + int32_t tmp; + /* + * tmp = (int32_t)512 * ps * ddr_mbps /2 / ddr_mbpsdiv / 1000 / 1000; + * = ps * ddr_mbps /2 / ddr_mbpsdiv *512 / 8 / 8 / 125 / 125 + * = ps * ddr_mbps / ddr_mbpsdiv *4 / 125 / 125 + */ + tmp = + (int32_t)4 * (int32_t)ps * (int32_t)ddr_mbps / + (int32_t)ddr_mbpsdiv; + tmp = (int32_t)tmp / (int32_t)15625; + + return (int16_t)tmp; +} + +static const uint32_t reg_pi_mr1_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR1_DATA_F0_0, + _reg_PI_MR1_DATA_F0_1, + _reg_PI_MR1_DATA_F0_2, + _reg_PI_MR1_DATA_F0_3}, + { + _reg_PI_MR1_DATA_F1_0, + _reg_PI_MR1_DATA_F1_1, + _reg_PI_MR1_DATA_F1_2, + _reg_PI_MR1_DATA_F1_3} +}; + +static const uint32_t reg_pi_mr2_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR2_DATA_F0_0, + _reg_PI_MR2_DATA_F0_1, + _reg_PI_MR2_DATA_F0_2, + _reg_PI_MR2_DATA_F0_3}, + { + _reg_PI_MR2_DATA_F1_0, + _reg_PI_MR2_DATA_F1_1, + _reg_PI_MR2_DATA_F1_2, + _reg_PI_MR2_DATA_F1_3} +}; + +static const uint32_t reg_pi_mr3_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR3_DATA_F0_0, + _reg_PI_MR3_DATA_F0_1, + _reg_PI_MR3_DATA_F0_2, + _reg_PI_MR3_DATA_F0_3}, + { + _reg_PI_MR3_DATA_F1_0, + _reg_PI_MR3_DATA_F1_1, + _reg_PI_MR3_DATA_F1_2, + _reg_PI_MR3_DATA_F1_3} +}; + +const uint32_t reg_pi_mr11_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR11_DATA_F0_0, + _reg_PI_MR11_DATA_F0_1, + _reg_PI_MR11_DATA_F0_2, + _reg_PI_MR11_DATA_F0_3}, + { + _reg_PI_MR11_DATA_F1_0, + _reg_PI_MR11_DATA_F1_1, + _reg_PI_MR11_DATA_F1_2, + _reg_PI_MR11_DATA_F1_3} +}; + +const uint32_t reg_pi_mr12_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR12_DATA_F0_0, + _reg_PI_MR12_DATA_F0_1, + _reg_PI_MR12_DATA_F0_2, + _reg_PI_MR12_DATA_F0_3}, + { + _reg_PI_MR12_DATA_F1_0, + _reg_PI_MR12_DATA_F1_1, + _reg_PI_MR12_DATA_F1_2, + _reg_PI_MR12_DATA_F1_3} +}; + +const uint32_t reg_pi_mr14_data_fx_csx[2][CSAB_CNT] = { + { + _reg_PI_MR14_DATA_F0_0, + _reg_PI_MR14_DATA_F0_1, + _reg_PI_MR14_DATA_F0_2, + _reg_PI_MR14_DATA_F0_3}, + { + _reg_PI_MR14_DATA_F1_0, + _reg_PI_MR14_DATA_F1_1, + _reg_PI_MR14_DATA_F1_2, + _reg_PI_MR14_DATA_F1_3} +}; + +/* + * regif pll w/a ( REGIF H3 Ver.2.0 or later/M3-N/V3H WA ) + */ +static void regif_pll_wa(void) +{ + uint32_t ch; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + // PLL setting for PHY : H3 Ver.1.x + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT), + (0x0064U << + ddr_regdef_lsb(_reg_PHY_PLL_WAIT))); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL)); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL)); + + } else { + /* PLL setting for PHY : M3-W/M3-N/V3H/H3 Ver.2.0 or later */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_WAIT), + (0x5064U << + ddr_regdef_lsb(_reg_PHY_PLL_WAIT))); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL), + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL_TOP) << 16) | + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL)); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_PLL_CTRL_CA), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PLL_CTRL_CA)); + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LP4_BOOT_PLL_CTRL), + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL_CA) << 16) | + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL)); + reg_ddrphy_write_a(ddr_regdef_adr + (_reg_PHY_LP4_BOOT_TOP_PLL_CTRL), + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_TOP_PLL_CTRL + )); + } + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_LPDDR3_CS), + _cnf_DDR_PHY_ADR_G_REGSET + [ddr_regdef_adr(_reg_PHY_LPDDR3_CS) - + DDR_PHY_ADR_G_REGSET_OFS]); + + /* protect register interface */ + ddrphy_regif_idle(); + pll3_control(0); + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_DLL_RST_EN), + (0x01U << + ddr_regdef_lsb(_reg_PHY_DLL_RST_EN))); + ddrphy_regif_idle(); + } + + /* init start */ + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10); + dsb_sev(); + + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =1 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11); + dsb_sev(); + + foreach_ech(ch) + if ((board_cnf->phyvalid) & BIT(ch)) + while ((mmio_read_32(DBSC_PLL_LOCK(ch)) & 0x1f) != 0x1f) + ; + dsb_sev(); +} + +/* load table data into DDR registers */ +static void ddrtbl_load(void) +{ + uint32_t i; + uint32_t slice; + uint32_t csab; + uint32_t adr; + uint32_t data_l; + uint32_t tmp[3]; + uint16_t dataS; + + /* TIMING REGISTERS */ + /* search jedec_spec1 index */ + for (i = JS1_USABLEC_SPEC_LO; i < JS1_FREQ_TBL_NUM - 1; i++) { + if (js1[i].fx3 * 2U * ddr_mbpsdiv >= ddr_mbps * 3U) + break; + } + if (i > JS1_USABLEC_SPEC_HI) + js1_ind = JS1_USABLEC_SPEC_HI; + else + js1_ind = i; + + if (board_cnf->dbi_en) + RL = js1[js1_ind].rlwdbi; + else + RL = js1[js1_ind].rlwodbi; + + WL = js1[js1_ind].WL; + + /* calculate jedec_spec2 */ + _f_scale_js2(ddr_mbps, ddr_mbpsdiv, js2); + + /* PREPARE TBL */ + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* H3 Ver.1.x */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_H3, + DDR_PHY_SLICE_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_H3, + DDR_PHY_ADR_V_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, + DDR_PHY_ADR_I_REGSET_H3, + DDR_PHY_ADR_I_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_H3, + DDR_PHY_ADR_G_REGSET_NUM_H3); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3, + DDR_PI_REGSET_NUM_H3); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_H3; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_H3; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_H3; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_H3; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3; + DDR_PHY_SLICE_REGSET_SIZE = + DDR_PHY_SLICE_REGSET_SIZE_H3; + DDR_PHY_ADR_V_REGSET_SIZE = + DDR_PHY_ADR_V_REGSET_SIZE_H3; + DDR_PHY_ADR_I_REGSET_SIZE = + DDR_PHY_ADR_I_REGSET_SIZE_H3; + DDR_PHY_ADR_G_REGSET_SIZE = + DDR_PHY_ADR_G_REGSET_SIZE_H3; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_H3; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_H3; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_H3; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_H3; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3; + + DDR_PHY_ADR_I_NUM = 1; + } else { + /* H3 Ver.2.0 or later */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_H3VER2, + DDR_PHY_SLICE_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_H3VER2, + DDR_PHY_ADR_V_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_H3VER2, + DDR_PHY_ADR_G_REGSET_NUM_H3VER2); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_H3VER2, + DDR_PI_REGSET_NUM_H3VER2); + + DDR_PHY_SLICE_REGSET_OFS = + DDR_PHY_SLICE_REGSET_OFS_H3VER2; + DDR_PHY_ADR_V_REGSET_OFS = + DDR_PHY_ADR_V_REGSET_OFS_H3VER2; + DDR_PHY_ADR_G_REGSET_OFS = + DDR_PHY_ADR_G_REGSET_OFS_H3VER2; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_H3VER2; + DDR_PHY_SLICE_REGSET_SIZE = + DDR_PHY_SLICE_REGSET_SIZE_H3VER2; + DDR_PHY_ADR_V_REGSET_SIZE = + DDR_PHY_ADR_V_REGSET_SIZE_H3VER2; + DDR_PHY_ADR_G_REGSET_SIZE = + DDR_PHY_ADR_G_REGSET_SIZE_H3VER2; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_H3VER2; + DDR_PHY_SLICE_REGSET_NUM = + DDR_PHY_SLICE_REGSET_NUM_H3VER2; + DDR_PHY_ADR_V_REGSET_NUM = + DDR_PHY_ADR_V_REGSET_NUM_H3VER2; + DDR_PHY_ADR_G_REGSET_NUM = + DDR_PHY_ADR_G_REGSET_NUM_H3VER2; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_H3VER2; + + DDR_PHY_ADR_I_NUM = 0; + } + } else if (prr_product == PRR_PRODUCT_M3) { + /* M3-W */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_M3, DDR_PHY_SLICE_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, + DDR_PHY_ADR_V_REGSET_M3, DDR_PHY_ADR_V_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, + DDR_PHY_ADR_I_REGSET_M3, DDR_PHY_ADR_I_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, + DDR_PHY_ADR_G_REGSET_M3, DDR_PHY_ADR_G_REGSET_NUM_M3); + _tblcopy(_cnf_DDR_PI_REGSET, + DDR_PI_REGSET_M3, DDR_PI_REGSET_NUM_M3); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3; + DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3; + DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3; + DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3; + DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3; + + DDR_PHY_ADR_I_NUM = 2; + } else { + /* M3-N/V3H */ + _tblcopy(_cnf_DDR_PHY_SLICE_REGSET, + DDR_PHY_SLICE_REGSET_M3N, + DDR_PHY_SLICE_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_V_REGSET, DDR_PHY_ADR_V_REGSET_M3N, + DDR_PHY_ADR_V_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_I_REGSET, DDR_PHY_ADR_I_REGSET_M3N, + DDR_PHY_ADR_I_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PHY_ADR_G_REGSET, DDR_PHY_ADR_G_REGSET_M3N, + DDR_PHY_ADR_G_REGSET_NUM_M3N); + _tblcopy(_cnf_DDR_PI_REGSET, DDR_PI_REGSET_M3N, + DDR_PI_REGSET_NUM_M3N); + + DDR_PHY_SLICE_REGSET_OFS = DDR_PHY_SLICE_REGSET_OFS_M3N; + DDR_PHY_ADR_V_REGSET_OFS = DDR_PHY_ADR_V_REGSET_OFS_M3N; + DDR_PHY_ADR_I_REGSET_OFS = DDR_PHY_ADR_I_REGSET_OFS_M3N; + DDR_PHY_ADR_G_REGSET_OFS = DDR_PHY_ADR_G_REGSET_OFS_M3N; + DDR_PI_REGSET_OFS = DDR_PI_REGSET_OFS_M3N; + DDR_PHY_SLICE_REGSET_SIZE = DDR_PHY_SLICE_REGSET_SIZE_M3N; + DDR_PHY_ADR_V_REGSET_SIZE = DDR_PHY_ADR_V_REGSET_SIZE_M3N; + DDR_PHY_ADR_I_REGSET_SIZE = DDR_PHY_ADR_I_REGSET_SIZE_M3N; + DDR_PHY_ADR_G_REGSET_SIZE = DDR_PHY_ADR_G_REGSET_SIZE_M3N; + DDR_PI_REGSET_SIZE = DDR_PI_REGSET_SIZE_M3N; + DDR_PHY_SLICE_REGSET_NUM = DDR_PHY_SLICE_REGSET_NUM_M3N; + DDR_PHY_ADR_V_REGSET_NUM = DDR_PHY_ADR_V_REGSET_NUM_M3N; + DDR_PHY_ADR_I_REGSET_NUM = DDR_PHY_ADR_I_REGSET_NUM_M3N; + DDR_PHY_ADR_G_REGSET_NUM = DDR_PHY_ADR_G_REGSET_NUM_M3N; + DDR_PI_REGSET_NUM = DDR_PI_REGSET_NUM_M3N; + + DDR_PHY_ADR_I_NUM = 2; + } + + /* PLL CODE CHANGE */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) { + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, _reg_PHY_PLL_CTRL, + 0x1142); + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_LP4_BOOT_PLL_CTRL, 0x1142); + } + + /* on fly gate adjust */ + if ((prr_product == PRR_PRODUCT_M3) && (prr_cut == PRR_PRODUCT_10)) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_ON_FLY_GATE_ADJUST_EN, 0x00); + } + + /* Adjust PI parameters */ +#ifdef _def_LPDDR4_ODT + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[i][csab], + _def_LPDDR4_ODT); + } + } +#endif /* _def_LPDDR4_ODT */ + +#ifdef _def_LPDDR4_VREFCA + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr12_data_fx_csx[i][csab], + _def_LPDDR4_VREFCA); + } + } +#endif /* _def_LPDDR4_VREFCA */ + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 7000, 0) + 7U; + if (js2[js2_tiedly] > (RL)) + js2[js2_tiedly] = RL; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 9000, 0) + 4U; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + js2[js2_tiedly] = _f_scale(ddr_mbps, ddr_mbpsdiv, 10000, 0); + } + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + if ((js2[js2_tiedly]) >= 0x1e) + dataS = 0x1e; + else + dataS = js2[js2_tiedly]; + } else { + if ((js2[js2_tiedly]) >= 0x0e) + dataS = 0x0e; + else + dataS = js2[js2_tiedly]; + } + + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_DLY, dataS); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_RDDATA_EN_TSEL_DLY, + (dataS - 2)); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_RDDATA_EN_OE_DLY, dataS - 2); + } + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1, RL - dataS); + + if (ddrtbl_getval + (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) { + data_l = WL - 1; + } else { + data_l = WL; + } + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1, data_l - 2); + ddrtbl_setval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1, data_l); + + if (board_cnf->dbi_en) { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE, + 0x01); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_WDQLVL_DATADM_MASK, 0x000); + } else { + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_DBI_MODE, + 0x00); + ddrtbl_setval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_WDQLVL_DATADM_MASK, 0x100); + } + + tmp[0] = js1[js1_ind].MR1; + tmp[1] = js1[js1_ind].MR2; + data_l = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_MR3_DATA_F1_0); + if (board_cnf->dbi_en) + tmp[2] = data_l | 0xc0; + else + tmp[2] = data_l & (~0xc0); + + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr1_data_fx_csx[i][csab], tmp[0]); + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr2_data_fx_csx[i][csab], tmp[1]); + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr3_data_fx_csx[i][csab], tmp[2]); + } + } + + /* DDRPHY INT START */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + regif_pll_wa(); + dbwait_loop(5); + } + + /* FREQ_SEL_MULTICAST & PER_CS_TRAINING_MULTICAST SET (for safety) */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x01); + + /* SET DATA SLICE TABLE */ + for (slice = 0; slice < SLICE_CNT; slice++) { + adr = + DDR_PHY_SLICE_REGSET_OFS + + DDR_PHY_SLICE_REGSET_SIZE * slice; + for (i = 0; i < DDR_PHY_SLICE_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_SLICE_REGSET[i]); + } + } + + /* SET ADR SLICE TABLE */ + adr = DDR_PHY_ADR_V_REGSET_OFS; + for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_V_REGSET[i]); + } + + if (((prr_product == PRR_PRODUCT_M3) || + (prr_product == PRR_PRODUCT_M3N)) && + ((0x00ffffff & (uint32_t)((board_cnf->ch[0].ca_swap) >> 40)) + != 0x00)) { + adr = DDR_PHY_ADR_I_REGSET_OFS + DDR_PHY_ADR_I_REGSET_SIZE; + for (i = 0; i < DDR_PHY_ADR_V_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_ADR_V_REGSET[i]); + } + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_ADR_DISABLE, 0x02); + DDR_PHY_ADR_I_NUM -= 1; + ddr_phycaslice = 1; + +#ifndef _def_LPDDR4_ODT + for (i = 0; i < 2; i++) { + for (csab = 0; csab < CSAB_CNT; csab++) { + ddrtbl_setval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[i][csab], + 0x66); + } + } +#endif/* _def_LPDDR4_ODT */ + } else { + ddr_phycaslice = 0; + } + + if (DDR_PHY_ADR_I_NUM > 0) { + for (slice = 0; slice < DDR_PHY_ADR_I_NUM; slice++) { + adr = + DDR_PHY_ADR_I_REGSET_OFS + + DDR_PHY_ADR_I_REGSET_SIZE * slice; + for (i = 0; i < DDR_PHY_ADR_I_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, + _cnf_DDR_PHY_ADR_I_REGSET + [i]); + } + } + } + + /* SET ADRCTRL SLICE TABLE */ + adr = DDR_PHY_ADR_G_REGSET_OFS; + for (i = 0; i < DDR_PHY_ADR_G_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PHY_ADR_G_REGSET[i]); + } + + /* SET PI REGISTERS */ + adr = DDR_PI_REGSET_OFS; + for (i = 0; i < DDR_PI_REGSET_NUM; i++) { + reg_ddrphy_write_a(adr + i, _cnf_DDR_PI_REGSET[i]); + } +} + +/* CONFIGURE DDR REGISTERS */ +static void ddr_config_sub(void) +{ + uint32_t i; + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + uint8_t high_byte[SLICE_CNT]; + const uint32_t _par_CALVL_DEVICE_MAP = 1; + + foreach_vch(ch) { + /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */ + for (slice = 0; slice < SLICE_CNT; slice++) { + high_byte[slice] = + (board_cnf->ch[ch].dqs_swap >> (4 * slice)) % 2; + ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE0, + board_cnf->ch[ch].dq_swap[slice]); + ddr_setval_s(ch, slice, _reg_PHY_DQ_DM_SWIZZLE1, + board_cnf->ch[ch].dm_swap[slice]); + if (high_byte[slice]) { + /* HIGHER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x00); + } else { + /* LOWER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x01); + } + } + + /* BOARD SETTINGS (CA,ADDR_SEL) */ + data_l = (0x00ffffff & (uint32_t)(board_cnf->ch[ch].ca_swap)) | + 0x00888888; + + /* --- ADR_CALVL_SWIZZLE --- */ + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, + 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, + 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } else { + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0, data_l); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1, 0x00000000); + ddr_setval(ch, _reg_PHY_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } + + /* --- ADR_ADDR_SEL --- */ + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) { + data_l = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + } else { + data_l = 0; + tmp = board_cnf->ch[ch].ca_swap; + for (i = 0; i < 6; i++) { + data_l |= ((tmp & 0x0f) << (i * 5)); + tmp = tmp >> 4; + } + } + ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, data_l); + if (ddr_phycaslice == 1) { + /* ----------- adr slice2 swap ----------- */ + tmp = (uint32_t)((board_cnf->ch[ch].ca_swap) >> 40); + data_l = (tmp & 0x00ffffff) | 0x00888888; + + /* --- ADR_CALVL_SWIZZLE --- */ + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0_0, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1_0, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0_1, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1_1, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } else { + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE0, + data_l); + ddr_setval_s(ch, 2, + _reg_PHY_ADR_CALVL_SWIZZLE1, + 0x00000000); + ddr_setval_s(ch, 2, + _reg_PHY_CALVL_DEVICE_MAP, + _par_CALVL_DEVICE_MAP); + } + + /* --- ADR_ADDR_SEL --- */ + data_l = 0; + for (i = 0; i < 6; i++) { + data_l |= ((tmp & 0x0f) << (i * 5)); + tmp = tmp >> 4; + } + + ddr_setval_s(ch, 2, _reg_PHY_ADR_ADDR_SEL, data_l); + } + + /* BOARD SETTINGS (BYTE_ORDER_SEL) */ + if (prr_product == PRR_PRODUCT_M3) { + /* --- DATA_BYTE_SWAP --- */ + data_l = 0; + tmp = board_cnf->ch[ch].dqs_swap; + for (i = 0; i < 4; i++) { + data_l |= ((tmp & 0x03) << (i * 2)); + tmp = tmp >> 4; + } + } else { + /* --- DATA_BYTE_SWAP --- */ + data_l = board_cnf->ch[ch].dqs_swap; + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_EN, 0x01); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE0, + (data_l) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE1, + (data_l >> 4 * 1) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE2, + (data_l >> 4 * 2) & 0x0f); + ddr_setval(ch, _reg_PI_DATA_BYTE_SWAP_SLICE3, + (data_l >> 4 * 3) & 0x0f); + + ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH, 0x00); + } + ddr_setval(ch, _reg_PHY_DATA_BYTE_ORDER_SEL, data_l); + } +} + +static void get_ca_swizzle(uint32_t ch, uint32_t ddr_csn, uint32_t *p_swz) +{ + uint32_t slice; + uint32_t tmp; + uint32_t tgt; + + if (ddr_csn / 2) { + tgt = 3; + } else { + tgt = 1; + } + + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (tgt == tmp) + break; + } + tmp = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + if (slice % 2) + tmp |= 0x00888888; + *p_swz = tmp; +} + +static void ddr_config_sub_h3v1x(void) +{ + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + uint8_t high_byte[SLICE_CNT]; + uint32_t ca_swizzle; + uint32_t ca; + uint32_t csmap; + uint32_t o_inv; + uint32_t inv; + uint32_t bit_soc; + uint32_t bit_mem; + uint32_t j; + + const uint8_t o_mr15 = 0x55; + const uint8_t o_mr20 = 0x55; + const uint16_t o_mr32_mr40 = 0x5a3c; + + foreach_vch(ch) { + /* BOARD SETTINGS (DQ,DM,VREF_DRIVING) */ + csmap = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & + 0x0f; + high_byte[slice] = tmp % 2; + if (tmp == 1 && (slice >= 2)) + csmap |= 0x05; + if (tmp == 3 && (slice >= 2)) + csmap |= 0x50; + ddr_setval_s(ch, slice, _reg_PHY_DQ_SWIZZLING, + board_cnf->ch[ch].dq_swap[slice]); + if (high_byte[slice]) { + /* HIGHER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x00); + } else { + /* LOWER 16 BYTE */ + ddr_setval_s(ch, slice, + _reg_PHY_CALVL_VREF_DRIVING_SLICE, + 0x01); + } + } + /* BOARD SETTINGS (CA,ADDR_SEL) */ + ca = 0x00FFFFFF & board_cnf->ch[ch].ca_swap; + ddr_setval(ch, _reg_PHY_ADR_ADDR_SEL, ca); + ddr_setval(ch, _reg_PHY_CALVL_CS_MAP, csmap); + + get_ca_swizzle(ch, 0, &ca_swizzle); + + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_0, ca_swizzle); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_0, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE0_1, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_SWIZZLE1_1, 0x00000000); + ddr_setval(ch, _reg_PHY_ADR_CALVL_DEVICE_MAP, 0x01); + + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_NUM, + 0x01); + ddr_setval_s(ch, slice, _reg_PI_RDLVL_PATTERN_START, + 0x08); + + if (high_byte[slice]) + o_inv = o_mr20; + else + o_inv = o_mr15; + + tmp = board_cnf->ch[ch].dq_swap[slice]; + inv = 0; + j = 0; + for (bit_soc = 0; bit_soc < 8; bit_soc++) { + bit_mem = (tmp >> (4 * bit_soc)) & 0x0f; + j |= (1U << bit_mem); + if (o_inv & (1U << bit_mem)) + inv |= (1U << bit_soc); + } + data_l = o_mr32_mr40; + if (!high_byte[slice]) + data_l |= (inv << 24); + if (high_byte[slice]) + data_l |= (inv << 16); + ddr_setval_s(ch, slice, _reg_PHY_LP4_RDLVL_PATT8, + data_l); + } + } +} + +static void ddr_config(void) +{ + int32_t i; + uint32_t ch, slice; + uint32_t data_l; + uint32_t tmp; + int8_t _adj; + int16_t adj; + uint32_t dq; + union { + uint32_t ui32[4]; + uint8_t ui8[16]; + } patt; + uint16_t patm; + + /* configure ddrphy registers */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_config_sub_h3v1x(); + } else { /* H3 Ver.2.0 or later/M3-N/V3H is same as M3-W */ + ddr_config_sub(); + } + + /* WDQ_USER_PATT */ + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + patm = 0; + for (i = 0; i < 16; i++) { + tmp = board_cnf->ch[ch].wdqlvl_patt[i]; + patt.ui8[i] = tmp & 0xff; + if (tmp & 0x100) + patm |= (1U << i); + } + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT0, + patt.ui32[0]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT1, + patt.ui32[1]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT2, + patt.ui32[2]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT3, + patt.ui32[3]); + ddr_setval_s(ch, slice, _reg_PHY_USER_PATT4, patm); + } + } + + /* CACS DLY */ + data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj); + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + 0x00U); + foreach_vch(ch) { + for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]), + _cnf_DDR_PHY_ADR_V_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_V_REGSET_OFS]); + } + + for (i = (_reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM - 4); + i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]), + _cnf_DDR_PHY_ADR_G_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_G_REGSET_OFS]); + } + + if (ddr_phycaslice == 1) { + for (i = 0; i < 6; i++) { + adj = _f_scale_adj + (board_cnf->ch[ch].cacs_adj + [i + + _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]); + ddrtbl_setval(_cnf_DDR_PHY_ADR_V_REGSET, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [i], + data_l + adj); + reg_ddrphy_write(ch, + ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) + + 0x0100, + _cnf_DDR_PHY_ADR_V_REGSET + [ddr_regdef_adr + (_reg_PHY_CLK_CACS_SLAVE_DELAY_X[i]) - + DDR_PHY_ADR_V_REGSET_OFS]); + } + } + } + + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + + /* WDQDM DLY */ + data_l = board_cnf->dqdm_dly_w; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_w[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_w[dq]; + adj = _f_scale_adj(_adj); + ddr_setval_s(ch, slice, + _reg_PHY_CLK_WRX_SLAVE_DELAY[i], + data_l + adj); + } + } + } + + /* RDQDM DLY */ + data_l = board_cnf->dqdm_dly_r; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_r[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_r[dq]; + adj = _f_scale_adj(_adj); + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY + [i], data_l + adj); + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [i], data_l + adj); + } + } + } +} + +/* DBSC register setting functions */ +static void dbsc_regset_pre(void) +{ + uint32_t ch, csab; + uint32_t data_l; + + /* PRIMARY SETTINGS */ + /* LPDDR4, BL=16, DFI interface */ + mmio_write_32(DBSC_DBKIND, 0x0000000a); + mmio_write_32(DBSC_DBBL, 0x00000002); + mmio_write_32(DBSC_DBPHYCONF0, 0x00000001); + + /* FREQRATIO=2 */ + mmio_write_32(DBSC_DBSYSCONF1, 0x00000002); + + /* Chanel map (H3 Ver.1.x) */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) + mmio_write_32(DBSC_DBSCHCNT1, 0x00001010); + + /* DRAM SIZE REGISTER: + * set all ranks as density=0(4Gb) for PHY initialization + */ + foreach_vch(ch) { + for (csab = 0; csab < 4; csab++) { + mmio_write_32(DBSC_DBMEMCONF(ch, csab), + DBMEMCONF_REGD(0)); + } + } + + if (prr_product == PRR_PRODUCT_M3) { + data_l = 0xe4e4e4e4; + foreach_ech(ch) { + if ((ddr_phyvalid & (1U << ch))) + data_l = (data_l & (~(0x000000FF << (ch * 8)))) + | (((board_cnf->ch[ch].dqs_swap & 0x0003) + | ((board_cnf->ch[ch].dqs_swap & 0x0030) + >> 2) + | ((board_cnf->ch[ch].dqs_swap & 0x0300) + >> 4) + | ((board_cnf->ch[ch].dqs_swap & 0x3000) + >> 6)) << (ch * 8)); + } + mmio_write_32(DBSC_DBBSWAP, data_l); + } +} + +static void dbsc_regset(void) +{ + int32_t i; + uint32_t ch; + uint32_t data_l; + uint32_t data_l2; + uint32_t tmp[4]; + + /* RFC */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_20) && + (max_density == 0)) { + js2[js2_trfcab] = + _f_scale(ddr_mbps, ddr_mbpsdiv, + 1UL * jedec_spec2_trfc_ab[1] * 1000, 0); + } else { + js2[js2_trfcab] = + _f_scale(ddr_mbps, ddr_mbpsdiv, + 1UL * jedec_spec2_trfc_ab[max_density] * + 1000, 0); + } + + /* DBTR0.CL : RL */ + mmio_write_32(DBSC_DBTR(0), RL); + + /* DBTR1.CWL : WL */ + mmio_write_32(DBSC_DBTR(1), WL); + + /* DBTR2.AL : 0 */ + mmio_write_32(DBSC_DBTR(2), 0); + + /* DBTR3.TRCD: tRCD */ + mmio_write_32(DBSC_DBTR(3), js2[js2_trcd]); + + /* DBTR4.TRPA,TRP: tRPab,tRPpb */ + mmio_write_32(DBSC_DBTR(4), (js2[js2_trpab] << 16) | js2[js2_trppb]); + + /* DBTR5.TRC : use tRCpb */ + mmio_write_32(DBSC_DBTR(5), js2[js2_trcpb]); + + /* DBTR6.TRAS : tRAS */ + mmio_write_32(DBSC_DBTR(6), js2[js2_tras]); + + /* DBTR7.TRRD : tRRD */ + mmio_write_32(DBSC_DBTR(7), (js2[js2_trrd] << 16) | js2[js2_trrd]); + + /* DBTR8.TFAW : tFAW */ + mmio_write_32(DBSC_DBTR(8), js2[js2_tfaw]); + + /* DBTR9.TRDPR : tRTP */ + mmio_write_32(DBSC_DBTR(9), js2[js2_trtp]); + + /* DBTR10.TWR : nWR */ + mmio_write_32(DBSC_DBTR(10), js1[js1_ind].nwr); + + /* + * DBTR11.TRDWR : RL + BL / 2 + Rounddown(tRPST) + PHY_ODTLoff - + * odtlon + tDQSCK - tODTon,min + + * PCB delay (out+in) + tPHY_ODToff + */ + mmio_write_32(DBSC_DBTR(11), + RL + (16 / 2) + 1 + 2 - js1[js1_ind].odtlon + + js2[js2_tdqsck] - js2[js2_tODTon_min] + + _f_scale(ddr_mbps, ddr_mbpsdiv, 1300, 0)); + + /* DBTR12.TWRRD : WL + 1 + BL/2 + tWTR */ + data_l = WL + 1 + (16 / 2) + js2[js2_twtr]; + mmio_write_32(DBSC_DBTR(12), (data_l << 16) | data_l); + + /* DBTR13.TRFCAB : tRFCab */ + mmio_write_32(DBSC_DBTR(13), (js2[js2_trfcab])); + + /* DBTR14.TCKEHDLL,tCKEH : tCKEHCMD,tCKEHCMD */ + mmio_write_32(DBSC_DBTR(14), + (js2[js2_tckehcmd] << 16) | (js2[js2_tckehcmd])); + + /* DBTR15.TCKESR,TCKEL : tSR,tCKELPD */ + mmio_write_32(DBSC_DBTR(15), (js2[js2_tsr] << 16) | (js2[js2_tckelpd])); + + /* DBTR16 */ + /* WDQL : tphy_wrlat + tphy_wrdata */ + tmp[0] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_F1); + /* DQENLTNCY : tphy_wrlat = WL-2 : PHY_WRITE_PATH_LAT_ADD == 0 + * tphy_wrlat = WL-3 : PHY_WRITE_PATH_LAT_ADD != 0 + */ + tmp[1] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_WRLAT_ADJ_F1); + /* DQL : tphy_rdlat + trdata_en */ + /* it is not important for dbsc */ + tmp[2] = RL + 16; + /* DQIENLTNCY : trdata_en */ + tmp[3] = ddrtbl_getval(_cnf_DDR_PI_REGSET, _reg_PI_RDLAT_ADJ_F1) - 1; + mmio_write_32(DBSC_DBTR(16), + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBTR24 */ + /* WRCSLAT = WRLAT -5 */ + tmp[0] -= 5; + /* WRCSGAP = 5 */ + tmp[1] = 5; + /* RDCSLAT = RDLAT_ADJ +2 */ + if (prr_product == PRR_PRODUCT_M3) { + tmp[2] = tmp[3]; + } else { + tmp[2] = tmp[3] + 2; + } + /* RDCSGAP = 6 */ + if (prr_product == PRR_PRODUCT_M3) { + tmp[3] = 4; + } else { + tmp[3] = 6; + } + mmio_write_32(DBSC_DBTR(24), + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBTR17.TMODRD,TMOD,TRDMR: tMRR,tMRD,(0) */ + mmio_write_32(DBSC_DBTR(17), + (js2[js2_tmrr] << 24) | (js2[js2_tmrd] << 16)); + + /* DBTR18.RODTL, RODTA, WODTL, WODTA : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(18), 0); + + /* DBTR19.TZQCL, TZQCS : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(19), 0); + + /* DBTR20.TXSDLL, TXS : tRFCab+tCKEHCMD */ + data_l = js2[js2_trfcab] + js2[js2_tckehcmd]; + mmio_write_32(DBSC_DBTR(20), (data_l << 16) | data_l); + + /* DBTR21.TCCD */ + /* DBTR23.TCCD */ + /* H3 Ver.1.0 cannot use TBTR23 feature */ + if (ddr_tccd == 8 && + !((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_10)) + ) { + data_l = 8; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000002); + } else if (ddr_tccd <= 11) { + data_l = 11; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000000); + } else { + data_l = ddr_tccd; + mmio_write_32(DBSC_DBTR(21), (data_l << 16) | data_l); + mmio_write_32(DBSC_DBTR(23), 0x00000000); + } + + /* DBTR22.ZQLAT : */ + data_l = js2[js2_tzqcalns] * 100; /* 1000 * 1000 ps */ + data_l = (data_l << 16) | (js2[js2_tzqlat] + 24 + 20); + mmio_write_32(DBSC_DBTR(22), data_l); + + /* DBTR25 : do not use in LPDDR4 */ + mmio_write_32(DBSC_DBTR(25), 0); + + /* DBRNK : */ + /* + * DBSC_DBRNK2 rkrr + * DBSC_DBRNK3 rkrw + * DBSC_DBRNK4 rkwr + * DBSC_DBRNK5 rkww + */ +#define _par_DBRNK_VAL (0x7007) + + for (i = 0; i < 4; i++) { + data_l = (_par_DBRNK_VAL >> (i * 4)) & 0x0f; + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11) && (i == 0)) { + data_l += 1; + } + data_l2 = 0; + foreach_vch(ch) { + data_l2 = data_l2 | (data_l << (4 * ch)); + } + mmio_write_32(DBSC_DBRNK(2 + i), data_l2); + } + mmio_write_32(DBSC_DBADJ0, 0x00000000); + + /* timing registers for Scheduler */ + /* SCFCTST0 */ + /* SCFCTST0 ACT-ACT */ + tmp[3] = 1UL * js2[js2_trcpb] * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 RDA-ACT */ + tmp[2] = + 1UL * ((16 / 2) + js2[js2_trtp] - 8 + + js2[js2_trppb]) * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 WRA-ACT */ + tmp[1] = + 1UL * (WL + 1 + (16 / 2) + + js1[js1_ind].nwr) * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST0 PRE-ACT */ + tmp[0] = 1UL * js2[js2_trppb]; + mmio_write_32(DBSC_SCFCTST0, + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* SCFCTST1 */ + /* SCFCTST1 RD-WR */ + tmp[3] = + 1UL * (mmio_read_32(DBSC_DBTR(11)) & 0xff) * 800 * ddr_mbpsdiv / + ddr_mbps; + /* SCFCTST1 WR-RD */ + tmp[2] = + 1UL * (mmio_read_32(DBSC_DBTR(12)) & 0xff) * 800 * ddr_mbpsdiv / + ddr_mbps; + /* SCFCTST1 ACT-RD/WR */ + tmp[1] = 1UL * js2[js2_trcd] * 800 * ddr_mbpsdiv / ddr_mbps; + /* SCFCTST1 ASYNCOFS */ + tmp[0] = 12; + mmio_write_32(DBSC_SCFCTST1, + (tmp[3] << 24) | (tmp[2] << 16) | (tmp[1] << 8) | tmp[0]); + + /* DBSCHRW1 */ + /* DBSCHRW1 SCTRFCAB */ + tmp[0] = 1UL * js2[js2_trfcab] * 800 * ddr_mbpsdiv / ddr_mbps; + data_l = (((mmio_read_32(DBSC_DBTR(16)) & 0x00FF0000) >> 16) + + (mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + + (0x28 * 2)) * 400 * 2 * ddr_mbpsdiv / ddr_mbps + 7; + if (tmp[0] < data_l) + tmp[0] = data_l; + + if ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30)) { + mmio_write_32(DBSC_DBSCHRW1, tmp[0] + + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) / + ddr_mbps - 3); + } else { + mmio_write_32(DBSC_DBSCHRW1, tmp[0] + + ((mmio_read_32(DBSC_DBTR(22)) & 0x0000FFFF) + * 400 * 2 * ddr_mbpsdiv + (ddr_mbps - 1)) / + ddr_mbps); + } + + /* QOS and CAM */ +#ifdef ddr_qos_init_setting /* only for non qos_init */ + /*wbkwait(0004), wbkmdhi(4,2),wbkmdlo(1,8) */ + mmio_write_32(DBSC_DBCAM0CNF1, 0x00043218); + /*0(fillunit),8(dirtymax),4(dirtymin) */ + mmio_write_32(DBSC_DBCAM0CNF2, 0x000000F4); + /*stop_tolerance */ + mmio_write_32(DBSC_DBSCHRW0, 0x22421111); + /*rd-wr/wr-rd toggle priority */ + mmio_write_32(DBSC_SCFCTST2, 0x012F1123); + mmio_write_32(DBSC_DBSCHSZ0, 0x00000001); + mmio_write_32(DBSC_DBSCHCNT0, 0x000F0037); + + /* QoS Settings */ + mmio_write_32(DBSC_DBSCHQOS00, 0x00000F00U); + mmio_write_32(DBSC_DBSCHQOS01, 0x00000B00U); + mmio_write_32(DBSC_DBSCHQOS02, 0x00000000U); + mmio_write_32(DBSC_DBSCHQOS03, 0x00000000U); + mmio_write_32(DBSC_DBSCHQOS40, 0x00000300U); + mmio_write_32(DBSC_DBSCHQOS41, 0x000002F0U); + mmio_write_32(DBSC_DBSCHQOS42, 0x00000200U); + mmio_write_32(DBSC_DBSCHQOS43, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS90, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS91, 0x000000F0U); + mmio_write_32(DBSC_DBSCHQOS92, 0x000000A0U); + mmio_write_32(DBSC_DBSCHQOS93, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS120, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS121, 0x00000030U); + mmio_write_32(DBSC_DBSCHQOS122, 0x00000020U); + mmio_write_32(DBSC_DBSCHQOS123, 0x00000010U); + mmio_write_32(DBSC_DBSCHQOS130, 0x00000100U); + mmio_write_32(DBSC_DBSCHQOS131, 0x000000F0U); + mmio_write_32(DBSC_DBSCHQOS132, 0x000000A0U); + mmio_write_32(DBSC_DBSCHQOS133, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS140, 0x000000C0U); + mmio_write_32(DBSC_DBSCHQOS141, 0x000000B0U); + mmio_write_32(DBSC_DBSCHQOS142, 0x00000080U); + mmio_write_32(DBSC_DBSCHQOS143, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS150, 0x00000040U); + mmio_write_32(DBSC_DBSCHQOS151, 0x00000030U); + mmio_write_32(DBSC_DBSCHQOS152, 0x00000020U); + mmio_write_32(DBSC_DBSCHQOS153, 0x00000010U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* ddr_qos_init_setting */ + /* H3 Ver.1.1 need to set monitor function */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_11)) { + mmio_write_32(DBSC_DBMONCONF4, 0x00700000); + } + + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut == PRR_PRODUCT_10) { + /* resrdis, simple mode, sc off */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000007); + } else if (prr_cut == PRR_PRODUCT_11) { + /* resrdis, simple mode */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000005); + } else if (prr_cut < PRR_PRODUCT_30) { + /* H3 Ver.2.0 */ + /* resrdis */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + } else { /* H3 Ver.3.0(include H3N) */ + /* exprespque */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000010); + } + } else { /* M3-W/M3-N/V3H */ + /* resrdis */ + mmio_write_32(DBSC_DBBCAMDIS, 0x00000001); + } +} + +static void dbsc_regset_post(void) +{ + uint32_t ch, cs; + uint32_t data_l; + uint32_t slice, rdlat_max, rdlat_min; + + rdlat_max = 0; + rdlat_min = 0xffff; + foreach_vch(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + if ((ch_have_this_cs[cs] & (1U << ch)) != 0) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + cs); + data_l = ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_LATENCY_ADJUST); + if (data_l > rdlat_max) + rdlat_max = data_l; + if (data_l < rdlat_min) + rdlat_min = data_l; + } + } + } + } + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) { +#if RCAR_DRAM_SPLIT == 2 + if (board_cnf->phyvalid == 0x05) { + mmio_write_32(DBSC_DBTR(24), + (rdlat_max << 24) + (rdlat_min << 16) + + mmio_read_32(DBSC_DBTR(24))); + } else { + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max * 2 - rdlat_min + 4) << 24) + + ((rdlat_min + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); + } +#else /*RCAR_DRAM_SPLIT == 2 */ + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max * 2 - rdlat_min + 4) << 24) + + ((rdlat_min + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); +#endif /*RCAR_DRAM_SPLIT == 2 */ + } else { + mmio_write_32(DBSC_DBTR(24), + ((rdlat_max + 2) << 24) + + ((rdlat_max + 2) << 16) + + mmio_read_32(DBSC_DBTR(24))); + } + + /* set ddr density information */ + foreach_ech(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + if (ddr_density[ch][cs] == 0xff) { + mmio_write_32(DBSC_DBMEMCONF(ch, cs), 0x00); + } else { + mmio_write_32(DBSC_DBMEMCONF(ch, cs), + DBMEMCONF_REGD(ddr_density[ch] + [cs])); + } + } + mmio_write_32(DBSC_DBMEMCONF(ch, 2), 0x00000000); + mmio_write_32(DBSC_DBMEMCONF(ch, 3), 0x00000000); + } + + mmio_write_32(DBSC_DBBUS0CNF1, 0x00000010); + + /*set DBI */ + if (board_cnf->dbi_en) + mmio_write_32(DBSC_DBDBICNT, 0x00000003); + + /* H3 Ver.2.0 or later/M3-N/V3H DBI wa */ + if ((((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) && + board_cnf->dbi_en) + reg_ddrphy_write_a(0x00001010, 0x01000000); + + /*set REFCYCLE */ + data_l = (get_refperiod()) * ddr_mbps / 2000 / ddr_mbpsdiv; + mmio_write_32(DBSC_DBRFCNF1, 0x00080000 | (data_l & 0x0000ffff)); + mmio_write_32(DBSC_DBRFCNF2, 0x00010000 | DBSC_REFINTS); + +#if RCAR_REWT_TRAINING != 0 + /* Periodic-WriteDQ Training seeting */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */ + } else { + /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000000); + + ddr_setval_ach_as(_reg_PHY_WDQLVL_PATT, 0x04); + ddr_setval_ach_as(_reg_PHY_WDQLVL_QTR_DLY_STEP, 0x0F); + ddr_setval_ach_as(_reg_PHY_WDQLVL_DLY_STEP, 0x50); + ddr_setval_ach_as(_reg_PHY_WDQLVL_DQDM_SLV_DLY_START, 0x0300); + + ddr_setval_ach(_reg_PI_WDQLVL_CS_MAP, + ddrtbl_getval(_cnf_DDR_PI_REGSET, + _reg_PI_WDQLVL_CS_MAP)); + ddr_setval_ach(_reg_PI_LONG_COUNT_MASK, 0x1f); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00); + ddr_setval_ach(_reg_PI_WDQLVL_ROTATE, 0x01); + ddr_setval_ach(_reg_PI_TREF_F0, 0x0000); + ddr_setval_ach(_reg_PI_TREF_F1, 0x0000); + ddr_setval_ach(_reg_PI_TREF_F2, 0x0000); + + if (prr_product == PRR_PRODUCT_M3) { + ddr_setval_ach(_reg_PI_WDQLVL_EN, 0x02); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_EN_F1, 0x02); + } + ddr_setval_ach(_reg_PI_WDQLVL_PERIODIC, 0x01); + + /* DFI_PHYMSTR_ACK , WTmode setting */ + /* DFI_PHYMSTR_ACK: WTmode =b'01 */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000011); + } +#endif /* RCAR_REWT_TRAINING */ + /* periodic dram zqcal enable */ + mmio_write_32(DBSC_DBCALCNF, 0x01000010); + + /* periodic phy ctrl update enable */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { +#if RCAR_DRAM_SPLIT == 2 + if ((prr_product == PRR_PRODUCT_H3) && + (board_cnf->phyvalid == 0x05)) + mmio_write_32(DBSC_DBDFICUPDCNF, 0x2a240001); + else + mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001); +#else /* RCAR_DRAM_SPLIT == 2 */ + mmio_write_32(DBSC_DBDFICUPDCNF, 0x28240001); +#endif /* RCAR_DRAM_SPLIT == 2 */ + } + +#ifdef DDR_BACKUPMODE + /* SRX */ + if (ddr_backup == DRAM_BOOT_STATUS_WARM) { +#ifdef DDR_BACKUPMODE_HALF /* for Half channel(ch0, 1 only) */ + NOTICE("BL2: [DEBUG_MESS] DDR_BACKUPMODE_HALF\n"); + send_dbcmd(0x0A040001); + if (Prr_Product == PRR_PRODUCT_H3) + send_dbcmd(0x0A140001); +#else /* DDR_BACKUPMODE_HALF */ /* for All channels */ + send_dbcmd(0x0A840001); +#endif /* DDR_BACKUPMODE_HALF */ + } +#endif /* DDR_BACKUPMODE */ + + /* set Auto Refresh */ + mmio_write_32(DBSC_DBRFEN, 0x00000001); + +#if RCAR_REWT_TRAINING != 0 + /* Periodic WriteDQ Traning */ + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + /* non : H3 Ver.1.x/M3-W Ver.1.0 not support */ + } else { + /* H3 Ver.2.0 or later/M3-W Ver.1.1 or later/M3-N/V3H */ + ddr_setval_ach(_reg_PI_WDQLVL_INTERVAL, 0x0100); + } +#endif /* RCAR_REWT_TRAINING */ + + /* dram access enable */ + mmio_write_32(DBSC_DBACEN, 0x00000001); + + MSG_LF(__func__ "(done)"); +} + +/* DFI_INIT_START */ +static uint32_t dfi_init_start(void) +{ + uint32_t ch; + uint32_t phytrainingok; + uint32_t retry; + uint32_t data_l; + const uint32_t RETRY_MAX = 0x10000; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* PLL3 Disable */ + /* protect register interface */ + ddrphy_regif_idle(); + + pll3_control(0); + + /* init start */ + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F10); + dsb_sev(); + + /* dbdficnt0: + * dfi_dram_clk_disable=1 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =1 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000F11); + dsb_sev(); + + } else { + ddr_setval_ach_as(_reg_PHY_DLL_RST_EN, 0x02); + dsb_sev(); + ddrphy_regif_idle(); + } + + /* dll_rst negate */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT3(ch), 0x0000CF01); + dsb_sev(); + + /* wait init_complete */ + phytrainingok = 0; + retry = 0; + while (retry++ < RETRY_MAX) { + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFISTAT(ch)); + if (data_l & 0x00000001) + phytrainingok |= (1U << ch); + } + dsb_sev(); + if (phytrainingok == ddr_phyvalid) + break; + if (retry % 256 == 0) + ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01); + } + + /* all ch ok? */ + if ((phytrainingok & ddr_phyvalid) != ddr_phyvalid) + return 0xff; + + /* dbdficnt0: + * dfi_dram_clk_disable=0 + * dfi_frequency = 0 + * freq_ratio = 01 (2:1) + * init_start =0 + */ + foreach_vch(ch) + mmio_write_32(DBSC_DBDFICNT(ch), 0x00000010); + dsb_sev(); + + return 0; +} + +/* drivablity setting : CMOS MODE ON/OFF */ +static void change_lpddr4_en(uint32_t mode) +{ + uint32_t ch; + uint32_t i; + uint32_t data_l; + const uint32_t _reg_PHY_PAD_DRIVE_X[3] = { + _reg_PHY_PAD_ADDR_DRIVE, + _reg_PHY_PAD_CLK_DRIVE, + _reg_PHY_PAD_CS_DRIVE + }; + + foreach_vch(ch) { + for (i = 0; i < 3; i++) { + data_l = ddr_getval(ch, _reg_PHY_PAD_DRIVE_X[i]); + if (mode) { + data_l |= (1U << 14); + } else { + data_l &= ~(1U << 14); + } + ddr_setval(ch, _reg_PHY_PAD_DRIVE_X[i], data_l); + } + } +} + +/* drivablity setting */ +static uint32_t set_term_code(void) +{ + int32_t i; + uint32_t ch, index; + uint32_t data_l; + uint32_t chip_id[2]; + uint32_t term_code; + uint32_t override; + uint32_t pvtr; + uint32_t pvtp; + uint32_t pvtn; + + term_code = ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_DATA_TERM); + override = 0; + for (i = 0; i < 2; i++) + chip_id[i] = mmio_read_32(LIFEC_CHIPID(i)); + + index = 0; + while (1) { + if (termcode_by_sample[index][0] == 0xffffffff) { + break; + } + if ((termcode_by_sample[index][0] == chip_id[0]) && + (termcode_by_sample[index][1] == chip_id[1])) { + term_code = termcode_by_sample[index][2]; + override = 1; + break; + } + index++; + } + + if (override) { + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; index++) { + data_l = + ddrtbl_getval(_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[index]); + data_l = (data_l & 0xfffe0000) | term_code; + ddr_setval_ach(_reg_PHY_PAD_TERM_X[index], data_l); + } + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10)) { + /* non */ + } else { + ddr_setval_ach(_reg_PHY_PAD_TERM_X[0], + (ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[0]) & 0xFFFE0000)); + ddr_setval_ach(_reg_PHY_CAL_CLEAR_0, 0x01); + ddr_setval_ach(_reg_PHY_CAL_START_0, 0x01); + foreach_vch(ch) { + do { + data_l = + ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0); + } while (!(data_l & 0x00800000)); + } + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + data_l = ddr_getval(ch, _reg_PHY_PAD_TERM_X[0]); + pvtr = (data_l >> 12) & 0x1f; + pvtr += 8; + if (pvtr > 0x1f) + pvtr = 0x1f; + data_l = + ddr_getval(ch, _reg_PHY_CAL_RESULT2_OBS_0); + pvtn = (data_l >> 6) & 0x03f; + pvtp = (data_l >> 0) & 0x03f; + + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; + index++) { + data_l = + ddrtbl_getval + (_cnf_DDR_PHY_ADR_G_REGSET, + _reg_PHY_PAD_TERM_X[index]); + data_l = (data_l & 0xfffe0000) + | (pvtr << 12) + | (pvtn << 6) + | (pvtp); + ddr_setval(ch, + _reg_PHY_PAD_TERM_X[index], + data_l); + } + } + } else { + /* M3-W Ver.1.1 or later/H3 Ver.2.0 or later/M3-N/V3H */ + foreach_vch(ch) { + for (index = 0; index < _reg_PHY_PAD_TERM_X_NUM; + index++) { + data_l = + ddr_getval(ch, + _reg_PHY_PAD_TERM_X + [index]); + ddr_setval(ch, + _reg_PHY_PAD_TERM_X[index], + (data_l & 0xFFFE0FFF) | + 0x00015000); + } + } + } + } + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + /* non */ + } else { + ddr_padcal_tcompensate_getinit(override); + } + + return 0; +} + +/* DDR mode register setting */ +static void ddr_register_set(void) +{ + int32_t fspwp; + uint32_t tmp; + + for (fspwp = 1; fspwp >= 0; fspwp--) { + /*MR13, fspwp */ + send_dbcmd(0x0e840d08 | ((2 - fspwp) << 6)); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr1_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840100 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr2_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840200 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr3_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840300 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr11_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840b00 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr12_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840c00 | tmp); + + tmp = + ddrtbl_getval(_cnf_DDR_PI_REGSET, + reg_pi_mr14_data_fx_csx[fspwp][0]); + send_dbcmd(0x0e840e00 | tmp); + /* MR22 */ + send_dbcmd(0x0e841616); + + /* ZQCAL start */ + send_dbcmd(0x0d84004F); + + /* ZQLAT */ + send_dbcmd(0x0d840051); + } + + /* MR13, fspwp */ + send_dbcmd(0x0e840d08); +} + +/* Training handshake functions */ +static inline uint32_t wait_freqchgreq(uint32_t assert) +{ + uint32_t data_l; + uint32_t count; + uint32_t ch; + + count = 100000; + + /* H3 Ver.1.x cannot see frqchg_req */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + return 0; + } + + if (assert) { + do { + data_l = 1; + foreach_vch(ch) { + data_l &= mmio_read_32(DBSC_DBPDSTAT(ch)); + } + count = count - 1; + } while (((data_l & 0x01) != 0x01) & (count != 0)); + } else { + do { + data_l = 0; + foreach_vch(ch) { + data_l |= mmio_read_32(DBSC_DBPDSTAT(ch)); + } + count = count - 1; + } while (((data_l & 0x01) != 0x00) & (count != 0)); + } + + return (count == 0); +} + +static inline void set_freqchgack(uint32_t assert) +{ + uint32_t ch; + uint32_t data_l; + + if (assert) + data_l = 0x0CF20000; + else + data_l = 0x00000000; + + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT2(ch), data_l); +} + +static inline void set_dfifrequency(uint32_t freq) +{ + uint32_t ch; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) + mmio_clrsetbits_32(DBSC_DBPDCNT1(ch), 0x1fU, freq); + } else { + foreach_vch(ch) { + mmio_clrsetbits_32(DBSC_DBDFICNT(ch), 0x1fU << 24, + (freq << 24)); + } + } + dsb_sev(); +} + +static uint32_t pll3_freq(uint32_t on) +{ + uint32_t timeout; + + timeout = wait_freqchgreq(1); + + if (timeout) { + return 1; + } + + pll3_control(on); + set_dfifrequency(on); + + set_freqchgack(1); + timeout = wait_freqchgreq(0); + set_freqchgack(0); + + if (timeout) { + FATAL_MSG("BL2: Time out[2]\n"); + return 1; + } + return 0; +} + +/* update dly */ +static void update_dly(void) +{ + ddr_setval_ach(_reg_SC_PHY_MANUAL_UPDATE, 0x01); + ddr_setval_ach(_reg_PHY_ADRCTL_MANUAL_UPDATE, 0x01); +} + +/* training by pi */ +static uint32_t pi_training_go(void) +{ + uint32_t flag; + uint32_t data_l; + uint32_t retry; + const uint32_t RETRY_MAX = 4096 * 16; + uint32_t ch; + + uint32_t mst_ch; + uint32_t cur_frq; + uint32_t complete; + uint32_t frqchg_req; + + /* pi_start */ + ddr_setval_ach(_reg_PI_START, 0x01); + foreach_vch(ch) + ddr_getval(ch, _reg_PI_INT_STATUS); + + /* set dfi_phymstr_ack = 1 */ + mmio_write_32(DBSC_DBDFIPMSTRCNF, 0x00000001); + dsb_sev(); + + /* wait pi_int_status[0] */ + mst_ch = 0; + flag = 0; + complete = 0; + cur_frq = 0; + retry = RETRY_MAX; + do { + frqchg_req = mmio_read_32(DBSC_DBPDSTAT(mst_ch)) & 0x01; + + /* H3 Ver.1.x cannot see frqchg_req */ + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + if ((retry % 4096) == 1) { + frqchg_req = 1; + } else { + frqchg_req = 0; + } + } + + if (frqchg_req) { + if (cur_frq) { + /* Low frequency */ + flag = pll3_freq(0); + cur_frq = 0; + } else { + /* High frequency */ + flag = pll3_freq(1); + cur_frq = 1; + } + if (flag) + break; + } else { + if (cur_frq) { + foreach_vch(ch) { + if (complete & (1U << ch)) + continue; + data_l = + ddr_getval(ch, _reg_PI_INT_STATUS); + if (data_l & 0x01) { + complete |= (1U << ch); + } + } + if (complete == ddr_phyvalid) + break; + } + } + } while (--retry); + foreach_vch(ch) { + /* dummy read */ + data_l = ddr_getval_s(ch, 0, _reg_PHY_CAL_RESULT2_OBS_0); + data_l = ddr_getval(ch, _reg_PI_INT_STATUS); + ddr_setval(ch, _reg_PI_INT_ACK, data_l); + } + if (ddrphy_regif_chk()) { + return 0xfd; + } + return complete; +} + +/* Initialize DDR */ +static uint32_t init_ddr(void) +{ + int32_t i; + uint32_t data_l; + uint32_t phytrainingok; + uint32_t ch, slice; + uint32_t err; + int16_t adj; + + MSG_LF(__func__ ":0\n"); + +#ifdef DDR_BACKUPMODE + rcar_dram_get_boot_status(&ddr_backup); +#endif + + /* unlock phy */ + /* Unlock DDRPHY register(AGAIN) */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDLK(ch), 0x0000A55A); + dsb_sev(); + + if ((((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) && board_cnf->dbi_en) + reg_ddrphy_write_a(0x00001010, 0x01000001); + else + reg_ddrphy_write_a(0x00001010, 0x00000001); + /* DBSC register pre-setting */ + dbsc_regset_pre(); + + /* load ddrphy registers */ + + ddrtbl_load(); + + /* configure ddrphy registers */ + ddr_config(); + + /* dfi_reset assert */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT0(ch), 0x01); + dsb_sev(); + + /* dbsc register set */ + dbsc_regset(); + MSG_LF(__func__ ":1\n"); + + /* dfi_reset negate */ + foreach_vch(ch) + mmio_write_32(DBSC_DBPDCNT0(ch), 0x00); + dsb_sev(); + + /* dfi_init_start (start ddrphy) */ + err = dfi_init_start(); + if (err) { + return INITDRAM_ERR_I; + } + MSG_LF(__func__ ":2\n"); + + /* ddr backupmode end */ +#ifdef DDR_BACKUPMODE + if (ddr_backup) { + NOTICE("BL2: [WARM_BOOT]\n"); + } else { + NOTICE("BL2: [COLD_BOOT]\n"); + } + err = rcar_dram_update_boot_status(ddr_backup); + if (err) { + NOTICE("BL2: [BOOT_STATUS_UPDATE_ERROR]\n"); + return INITDRAM_ERR_I; + } +#endif + MSG_LF(__func__ ":3\n"); + + /* override term code after dfi_init_complete */ + err = set_term_code(); + if (err) { + return INITDRAM_ERR_I; + } + MSG_LF(__func__ ":4\n"); + + /* rx offset calibration */ + if ((prr_cut > PRR_PRODUCT_11) || (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + err = rx_offset_cal_hw(); + } else { + err = rx_offset_cal(); + } + if (err) + return INITDRAM_ERR_O; + MSG_LF(__func__ ":5\n"); + + /* Dummy PDE */ + send_dbcmd(0x08840000); + + /* PDX */ + send_dbcmd(0x08840001); + + /* check register i/f is alive */ + err = ddrphy_regif_chk(); + if (err) { + return INITDRAM_ERR_O; + } + MSG_LF(__func__ ":6\n"); + + /* phy initialize end */ + + /* setup DDR mode registers */ + /* CMOS MODE */ + change_lpddr4_en(0); + + /* MRS */ + ddr_register_set(); + + /* Thermal sensor setting */ + /* THCTR Bit6: PONM=0 , Bit0: THSST=1 */ + data_l = (mmio_read_32(THS1_THCTR) & 0xFFFFFFBF) | 0x00000001; + mmio_write_32(THS1_THCTR, data_l); + + /* LPDDR4 MODE */ + change_lpddr4_en(1); + + MSG_LF(__func__ ":7\n"); + + /* mask CS_MAP if RANKx is not found */ + foreach_vch(ch) { + data_l = ddr_getval(ch, _reg_PI_CS_MAP); + if (!(ch_have_this_cs[1] & (1U << ch))) + data_l = data_l & 0x05; + ddr_setval(ch, _reg_PI_CS_MAP, data_l); + } + + /* exec pi_training */ + reg_ddrphy_write_a(ddr_regdef_adr(_reg_PHY_FREQ_SEL_MULTICAST_EN), + BIT(ddr_regdef_lsb(_reg_PHY_FREQ_SEL_MULTICAST_EN))); + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_MULTICAST_EN, 0x00); + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_EN, 0x01); + } else { + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_EN, + ((ch_have_this_cs[1]) >> ch) + & 0x01); + } + } + } + + phytrainingok = pi_training_go(); + + if (ddr_phyvalid != (phytrainingok & ddr_phyvalid)) { + return INITDRAM_ERR_T | phytrainingok; + } + + MSG_LF(__func__ ":8\n"); + + /* CACS DLY ADJUST */ + data_l = board_cnf->cacs_dly + _f_scale_adj(board_cnf->cacs_dly_adj); + foreach_vch(ch) { + for (i = 0; i < _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj[i]); + ddr_setval(ch, _reg_PHY_CLK_CACS_SLAVE_DELAY_X[i], + data_l + adj); + } + + if (ddr_phycaslice == 1) { + for (i = 0; i < 6; i++) { + adj = _f_scale_adj(board_cnf->ch[ch].cacs_adj + [i + + _reg_PHY_CLK_CACS_SLAVE_DELAY_X_NUM]); + ddr_setval_s(ch, 2, + _reg_PHY_CLK_CACS_SLAVE_DELAY_X + [i], + data_l + adj + ); + } + } + } + + update_dly(); + MSG_LF(__func__ ":9\n"); + + /* H3 fix rd latency to avoid bug in elasitic buffer */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) + adjust_rddqs_latency(); + + /* Adjust Write path latency */ + if (ddrtbl_getval + (_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_WRITE_PATH_LAT_ADD)) + adjust_wpath_latency(); + + /* RDQLVL Training */ + if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE)) + ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x01); + + err = rdqdm_man(); + + if (!ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, _reg_PHY_IE_MODE)) + ddr_setval_ach_as(_reg_PHY_IE_MODE, 0x00); + + if (err) { + return INITDRAM_ERR_T; + } + update_dly(); + MSG_LF(__func__ ":10\n"); + + /* WDQLVL Training */ + err = wdqdm_man(); + if (err) { + return INITDRAM_ERR_T; + } + update_dly(); + MSG_LF(__func__ ":11\n"); + + /* training complete, setup DBSC */ + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach_as(_reg_PHY_DFI40_POLARITY, 0x00); + ddr_setval_ach(_reg_PI_DFI40_POLARITY, 0x00); + } + + dbsc_regset_post(); + MSG_LF(__func__ ":12\n"); + + return phytrainingok; +} + +/* SW LEVELING COMMON */ +static uint32_t swlvl1(uint32_t ddr_csn, uint32_t reg_cs, uint32_t reg_kick) +{ + uint32_t ch; + uint32_t data_l; + uint32_t retry; + uint32_t waiting; + uint32_t err; + + const uint32_t RETRY_MAX = 0x1000; + + err = 0; + /* set EXIT -> OP_DONE is cleared */ + ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01); + + /* kick */ + foreach_vch(ch) { + if (ch_have_this_cs[ddr_csn % 2] & (1U << ch)) { + ddr_setval(ch, reg_cs, ddr_csn); + ddr_setval(ch, reg_kick, 0x01); + } + } + foreach_vch(ch) { + /*PREPARE ADDR REGISTER (for SWLVL_OP_DONE) */ + ddr_getval(ch, _reg_PI_SWLVL_OP_DONE); + } + waiting = ch_have_this_cs[ddr_csn % 2]; + dsb_sev(); + retry = RETRY_MAX; + do { + foreach_vch(ch) { + if (!(waiting & (1U << ch))) + continue; + data_l = ddr_getval(ch, _reg_PI_SWLVL_OP_DONE); + if (data_l & 0x01) + waiting &= ~(1U << ch); + } + retry--; + } while (waiting && (retry > 0)); + if (retry == 0) { + err = 1; + } + + dsb_sev(); + /* set EXIT -> OP_DONE is cleared */ + ddr_setval_ach(_reg_PI_SWLVL_EXIT, 0x01); + dsb_sev(); + + return err; +} + +/* WDQ TRAINING */ +#ifndef DDR_FAST_INIT +static void wdqdm_clr1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + + /* clr of training results buffer */ + cs = ddr_csn % 2; + data_l = board_cnf->dqdm_dly_w; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + for (i = 0; i <= 8; i++) { + if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) + wdqdm_dly[ch][cs][slice][i] = + wdqdm_dly[ch][CS_CNT - 1 - cs][slice][i]; + else + wdqdm_dly[ch][cs][slice][i] = data_l; + wdqdm_le[ch][cs][slice][i] = 0; + wdqdm_te[ch][cs][slice][i] = 0; + } + wdqdm_st[ch][cs][slice] = 0; + wdqdm_win[ch][cs][slice] = 0; + } +} + +static uint32_t wdqdm_ana1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + uint32_t err; + const uint32_t _par_WDQLVL_RETRY_THRES = 0x7c0; + + int32_t min_win; + int32_t win; + int8_t _adj; + int16_t adj; + uint32_t dq; + + /* analysis of training results */ + err = 0; + for (slice = 0; slice < SLICE_CNT; slice += 1) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + cs = ddr_csn % 2; + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs); + for (i = 0; i < 9; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_w[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_w[dq]; + adj = _f_scale_adj(_adj); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_CLK_WRX_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_CLK_WRX_SLAVE_DELAY[i], + data_l); + wdqdm_dly[ch][cs][slice][i] = data_l; + } + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, 0x00); + data_l = ddr_getval_s(ch, slice, _reg_PHY_WDQLVL_STATUS_OBS); + wdqdm_st[ch][cs][slice] = data_l; + min_win = INT_LEAST32_MAX; + for (i = 0; i <= 8; i++) { + ddr_setval_s(ch, slice, _reg_PHY_WDQLVL_DQDM_OBS_SELECT, + i); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS); + wdqdm_te[ch][cs][slice][i] = data_l; + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS); + wdqdm_le[ch][cs][slice][i] = data_l; + win = + (int32_t)wdqdm_te[ch][cs][slice][i] - + wdqdm_le[ch][cs][slice][i]; + if (min_win > win) + min_win = win; + if (data_l >= _par_WDQLVL_RETRY_THRES) + err = 2; + } + wdqdm_win[ch][cs][slice] = min_win; + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, + 0x01); + } else { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_EN, + ((ch_have_this_cs[1]) >> ch) & 0x01); + } + } + return err; +} +#endif/* DDR_FAST_INIT */ + +static void wdqdm_cp(uint32_t ddr_csn, uint32_t restore) +{ + uint32_t i; + uint32_t ch, slice; + uint32_t tgt_cs, src_cs; + uint32_t tmp_r; + + /* copy of training results */ + foreach_vch(ch) { + for (tgt_cs = 0; tgt_cs < CS_CNT; tgt_cs++) { + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + tgt_cs); + src_cs = ddr_csn % 2; + if (!(ch_have_this_cs[1] & (1U << ch))) + src_cs = 0; + for (i = 0; i <= 4; i += 4) { + if (restore) + tmp_r = + rdqdm_dly[ch][tgt_cs][slice] + [i]; + else + tmp_r = + rdqdm_dly[ch][src_cs][slice] + [i]; + + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY + [i], tmp_r); + } + } + } + } +} + +static uint32_t wdqdm_man1(void) +{ + int32_t k; + uint32_t ch, cs, slice; + uint32_t ddr_csn; + uint32_t data_l; + uint32_t err; + uint32_t high_dq[DRAM_CH_CNT]; + uint32_t mr14_csab0_bak[DRAM_CH_CNT]; +#ifndef DDR_FAST_INIT + uint32_t err_flg; +#endif/* DDR_FAST_INIT */ + + /* manual execution of training */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + high_dq[ch] = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> + (4 * slice)) & 0x0f; + if (k >= 2) + high_dq[ch] |= (1U << slice); + } + ddr_setval(ch, _reg_PI_16BIT_DRAM_CONNECT, 0x00); + } + } + err = 0; + /* CLEAR PREV RESULT */ + for (cs = 0; cs < CS_CNT; cs++) { + ddr_setval_ach_as(_reg_PHY_PER_CS_TRAINING_INDEX, cs); + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach_as(_reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS, + 0x01); + } else { + ddr_setval_ach_as(_reg_PHY_WDQLVL_CLR_PREV_RESULTS, + 0x01); + } + } + ddrphy_regif_idle(); + +#ifndef DDR_FAST_INIT + err_flg = 0; +#endif/* DDR_FAST_INIT */ + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFICNT(ch)); + data_l &= ~(0x00ffU << 16); + + if (ddr_csn >= 2) + k = (high_dq[ch] ^ 0x0f); + else + k = high_dq[ch]; + data_l |= (k << 16); + mmio_write_32(DBSC_DBDFICNT(ch), data_l); + ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, k); + } + } + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut == PRR_PRODUCT_10))) { + wdqdm_cp(ddr_csn, 0); + } + + foreach_vch(ch) { + data_l = + ddr_getval(ch, + reg_pi_mr14_data_fx_csx[1][ddr_csn]); + ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], data_l); + } + + /* KICK WDQLVL */ + err = swlvl1(ddr_csn, _reg_PI_WDQLVL_CS, _reg_PI_WDQLVL_REQ); + if (err) + goto err_exit; + + if (ddr_csn == 0) + foreach_vch(ch) { + mr14_csab0_bak[ch] = + ddr_getval(ch, reg_pi_mr14_data_fx_csx[1][0]); + } else + foreach_vch(ch) { + ddr_setval(ch, reg_pi_mr14_data_fx_csx[1][0], + mr14_csab0_bak[ch]); + } +#ifndef DDR_FAST_INIT + foreach_vch(ch) { + if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) { + wdqdm_clr1(ch, ddr_csn); + continue; + } + err = wdqdm_ana1(ch, ddr_csn); + if (err) + err_flg |= (1U << (ddr_csn * 4 + ch)); + ddrphy_regif_idle(); + } +#endif/* DDR_FAST_INIT */ + } +err_exit: +#ifndef DDR_FAST_INIT + err |= err_flg; +#endif/* DDR_FAST_INIT */ + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + ddr_setval_ach(_reg_PI_16BIT_DRAM_CONNECT, 0x01); + foreach_vch(ch) { + data_l = mmio_read_32(DBSC_DBDFICNT(ch)); + data_l &= ~(0x00ffU << 16); + mmio_write_32(DBSC_DBDFICNT(ch), data_l); + ddr_setval(ch, _reg_PI_WDQLVL_RESP_MASK, 0x00); + } + } + return err; +} + +static uint32_t wdqdm_man(void) +{ + uint32_t err, retry_cnt; + const uint32_t retry_max = 0x10; + uint32_t datal, ch, ddr_csn, mr14_bkup[4][4]; + + datal = RL + js2[js2_tdqsck] + (16 / 2) + 1 - WL + 2 + 2 + 19; + if ((mmio_read_32(DBSC_DBTR(11)) & 0xFF) > datal) + datal = mmio_read_32(DBSC_DBTR(11)) & 0xFF; + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_RW, datal); + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F0, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR_F1, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + } else { + ddr_setval_ach(_reg_PI_TDFI_WDQLVL_WR, + (mmio_read_32(DBSC_DBTR(12)) & 0xFF) + 10); + } + ddr_setval_ach(_reg_PI_TRFC_F0, mmio_read_32(DBSC_DBTR(13)) & 0x1FF); + ddr_setval_ach(_reg_PI_TRFC_F1, mmio_read_32(DBSC_DBTR(13)) & 0x1FF); + + retry_cnt = 0; + err = 0; + do { + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + err = wdqdm_man1(); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x01); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE, + 0x01); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x0C); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x0C); + } + dsb_sev(); + err = wdqdm_man1(); + foreach_vch(ch) { + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + mr14_bkup[ch][ddr_csn] = + ddr_getval(ch, + reg_pi_mr14_data_fx_csx + [1][ddr_csn]); + dsb_sev(); + } + } + + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x04); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x04); + } + pvtcode_update(); + err = wdqdm_man1(); + foreach_vch(ch) { + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + mr14_bkup[ch][ddr_csn] = + (mr14_bkup[ch][ddr_csn] + + ddr_getval(ch, + reg_pi_mr14_data_fx_csx + [1][ddr_csn])) / 2; + ddr_setval(ch, + reg_pi_mr14_data_fx_csx[1] + [ddr_csn], + mr14_bkup[ch][ddr_csn]); + } + } + + ddr_setval_ach(_reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE, + 0x00); + if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA_F1, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1, + 0x00); + } else { + ddr_setval_ach(_reg_PI_WDQLVL_VREF_DELTA, 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_START_POINT, + 0x00); + ddr_setval_ach + (_reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT, + 0x00); + } + ddr_setval_ach(_reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE, + 0x00); + + pvtcode_update2(); + err = wdqdm_man1(); + ddr_setval_ach(_reg_PI_WDQLVL_VREF_EN, 0x00); + } + } while (err && (++retry_cnt < retry_max)); + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut <= PRR_PRODUCT_10))) { + wdqdm_cp(0, 1); + } + + return (retry_cnt >= retry_max); +} + +/* RDQ TRAINING */ +#ifndef DDR_FAST_INIT +static void rdqdm_clr1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + + /* clr of training results buffer */ + cs = ddr_csn % 2; + data_l = board_cnf->dqdm_dly_r; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + for (i = 0; i <= 8; i++) { + if (ch_have_this_cs[CS_CNT - 1 - cs] & (1U << ch)) { + rdqdm_dly[ch][cs][slice][i] = + rdqdm_dly[ch][CS_CNT - 1 - cs][slice][i]; + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = + rdqdm_dly[ch][CS_CNT - 1 - cs][slice + + SLICE_CNT] + [i]; + } else { + rdqdm_dly[ch][cs][slice][i] = data_l; + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = + data_l; + } + rdqdm_le[ch][cs][slice][i] = 0; + rdqdm_le[ch][cs][slice + SLICE_CNT][i] = 0; + rdqdm_te[ch][cs][slice][i] = 0; + rdqdm_te[ch][cs][slice + SLICE_CNT][i] = 0; + rdqdm_nw[ch][cs][slice][i] = 0; + rdqdm_nw[ch][cs][slice + SLICE_CNT][i] = 0; + } + rdqdm_st[ch][cs][slice] = 0; + rdqdm_win[ch][cs][slice] = 0; + } +} + +static uint32_t rdqdm_ana1(uint32_t ch, uint32_t ddr_csn) +{ + int32_t i, k; + uint32_t cs, slice; + uint32_t data_l; + uint32_t err; + int8_t _adj; + int16_t adj; + uint32_t dq; + int32_t min_win; + int32_t win; + uint32_t rdq_status_obs_select; + + /* analysis of training results */ + err = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + k = (board_cnf->ch[ch].dqs_swap >> (4 * slice)) & 0x0f; + if (((k >= 2) && (ddr_csn < 2)) || ((k < 2) && (ddr_csn >= 2))) + continue; + + cs = ddr_csn % 2; + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, cs); + ddrphy_regif_idle(); + + ddr_getval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX); + ddrphy_regif_idle(); + + for (i = 0; i <= 8; i++) { + dq = slice * 8 + i; + if (i == 8) + _adj = board_cnf->ch[ch].dm_adj_r[slice]; + else + _adj = board_cnf->ch[ch].dq_adj_r[dq]; + + adj = _f_scale_adj(_adj); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + + adj; + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], + data_l); + rdqdm_dly[ch][cs][slice][i] = data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + + adj; + ddr_setval_s(ch, slice, + _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], + data_l); + rdqdm_dly[ch][cs][slice + SLICE_CNT][i] = data_l; + } + min_win = INT_LEAST32_MAX; + for (i = 0; i <= 8; i++) { + data_l = + ddr_getval_s(ch, slice, _reg_PHY_RDLVL_STATUS_OBS); + rdqdm_st[ch][cs][slice] = data_l; + rdqdm_st[ch][cs][slice + SLICE_CNT] = data_l; + /* k : rise/fall */ + for (k = 0; k < 2; k++) { + if (i == 8) { + rdq_status_obs_select = 16 + 8 * k; + } else { + rdq_status_obs_select = i + k * 8; + } + ddr_setval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT, + rdq_status_obs_select); + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS); + rdqdm_le[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS); + rdqdm_te[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + data_l = + ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS); + rdqdm_nw[ch][cs][slice + SLICE_CNT * k][i] = + data_l; + + win = + (int32_t)rdqdm_te[ch][cs][slice + + SLICE_CNT * + k][i] - + rdqdm_le[ch][cs][slice + SLICE_CNT * k][i]; + if (i != 8) { + if (min_win > win) + min_win = win; + } + } + } + rdqdm_win[ch][cs][slice] = min_win; + if (min_win <= 0) { + err = 2; + } + } + return err; +} +#endif/* DDR_FAST_INIT */ + +static uint32_t rdqdm_man1(void) +{ + uint32_t ch; + uint32_t ddr_csn; +#ifdef DDR_FAST_INIT + uint32_t slice; + uint32_t i, adj, data_l; +#endif/* DDR_FAST_INIT */ + uint32_t err; + + /* manual execution of training */ + err = 0; + + for (ddr_csn = 0; ddr_csn < CSAB_CNT; ddr_csn++) { + /* KICK RDQLVL */ + err = swlvl1(ddr_csn, _reg_PI_RDLVL_CS, _reg_PI_RDLVL_REQ); + if (err) + goto err_exit; +#ifndef DDR_FAST_INIT + foreach_vch(ch) { + if (!(ch_have_this_cs[ddr_csn % 2] & (1U << ch))) { + rdqdm_clr1(ch, ddr_csn); + ddrphy_regif_idle(); + continue; + } + err = rdqdm_ana1(ch, ddr_csn); + ddrphy_regif_idle(); + if (err) + goto err_exit; + } +#else/* DDR_FAST_INIT */ + foreach_vch(ch) { + if (ch_have_this_cs[ddr_csn] & (1U << ch)) { + for (slice = 0; slice < SLICE_CNT; slice++) { + if (ddr_getval_s(ch, slice, + _reg_PHY_RDLVL_STATUS_OBS) != + 0x0D00FFFF) { + err = (1U << ch) | + (0x10U << slice); + goto err_exit; + } + } + } + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && + (prr_cut <= PRR_PRODUCT_10))) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (i = 0; i <= 8; i++) { + if (i == 8) + adj = _f_scale_adj(board_cnf->ch[ch].dm_adj_r[slice]); + else + adj = _f_scale_adj(board_cnf->ch[ch].dq_adj_r[slice * 8 + i]); + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, ddr_csn); + data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_RISE_SLAVE_DELAY[i], data_l); + rdqdm_dly[ch][ddr_csn][slice][i] = data_l; + rdqdm_dly[ch][ddr_csn | 1][slice][i] = data_l; + + data_l = ddr_getval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i]) + adj; + ddr_setval_s(ch, slice, _reg_PHY_RDDQS_X_FALL_SLAVE_DELAY[i], data_l); + rdqdm_dly[ch][ddr_csn][slice + SLICE_CNT][i] = data_l; + rdqdm_dly[ch][ddr_csn | 1][slice + SLICE_CNT][i] = data_l; + } + } + } + } + ddrphy_regif_idle(); + +#endif/* DDR_FAST_INIT */ + } + +err_exit: + return err; +} + +static uint32_t rdqdm_man(void) +{ + uint32_t err, retry_cnt; + const uint32_t retry_max = 0x01; + + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE, + 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE, + 0x00000004 | ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT, + 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_SELECT)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT, + 0xFF0FFFFF & ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_SELECT)); + + retry_cnt = 0; + do { + err = rdqdm_man1(); + ddrphy_regif_idle(); + } while (err && (++retry_cnt < retry_max)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_ENABLE, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_ENABLE, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_ENABLE)); + ddr_setval_ach_as(_reg_PHY_DQ_TSEL_SELECT, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQ_TSEL_SELECT)); + ddr_setval_ach_as(_reg_PHY_DQS_TSEL_SELECT, + ddrtbl_getval(_cnf_DDR_PHY_SLICE_REGSET, + _reg_PHY_DQS_TSEL_SELECT)); + + return (retry_cnt >= retry_max); +} + +/* rx offset calibration */ +static int32_t _find_change(uint64_t val, uint32_t dir) +{ + int32_t i; + uint32_t startval; + uint32_t curval; + const int32_t VAL_END = 0x3f; + + if (dir == 0) { + startval = (val & 0x01); + for (i = 1; i <= VAL_END; i++) { + curval = (val >> i) & 0x01; + if (curval != startval) + return i; + } + return VAL_END; + } + + startval = (val >> dir) & 0x01; + for (i = dir - 1; i >= 0; i--) { + curval = (val >> i) & 0x01; + if (curval != startval) + return i; + } + return 0; +} + +static uint32_t _rx_offset_cal_updn(uint32_t code) +{ + const uint32_t CODE_MAX = 0x40; + uint32_t tmp; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) { + if (code == 0) + tmp = (1U << 6) | (CODE_MAX - 1); + else if (code <= 0x20) + tmp = + ((CODE_MAX - 1 - + (0x20 - code) * 2) << 6) | (CODE_MAX - 1); + else + tmp = + ((CODE_MAX - 1) << 6) | (CODE_MAX - 1 - + (code - 0x20) * 2); + } else { + if (code == 0) + tmp = (1U << 6) | (CODE_MAX - 1); + else + tmp = (code << 6) | (CODE_MAX - code); + } + return tmp; +} + +static uint32_t rx_offset_cal(void) +{ + uint32_t index; + uint32_t code; + const uint32_t CODE_MAX = 0x40; + const uint32_t CODE_STEP = 2; + uint32_t ch, slice; + uint32_t tmp; + uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT]; + uint64_t val[DRAM_CH_CNT][SLICE_CNT][_reg_PHY_RX_CAL_X_NUM]; + uint64_t tmpval; + int32_t lsb, msb; + + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x01); + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) + val[ch][slice][index] = 0; + } + } + + for (code = 0; code < CODE_MAX / CODE_STEP; code++) { + tmp = _rx_offset_cal_updn(code * CODE_STEP); + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; index++) { + ddr_setval_ach_as(_reg_PHY_RX_CAL_X[index], tmp); + } + dsb_sev(); + ddr_getval_ach_as(_reg_PHY_RX_CAL_OBS, (uint32_t *)tmp_ach_as); + + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = tmp_ach_as[ch][slice]; + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; + index++) { + if (tmp & (1U << index)) { + val[ch][slice][index] |= + (1ULL << code); + } else { + val[ch][slice][index] &= + ~(1ULL << code); + } + } + } + } + } + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + for (index = 0; index < _reg_PHY_RX_CAL_X_NUM; + index++) { + tmpval = val[ch][slice][index]; + lsb = _find_change(tmpval, 0); + msb = + _find_change(tmpval, + (CODE_MAX / CODE_STEP) - 1); + tmp = (lsb + msb) >> 1; + + tmp = _rx_offset_cal_updn(tmp * CODE_STEP); + ddr_setval_s(ch, slice, + _reg_PHY_RX_CAL_X[index], tmp); + } + } + } + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00); + + return 0; +} + +static uint32_t rx_offset_cal_hw(void) +{ + uint32_t ch, slice; + uint32_t retry; + uint32_t complete; + uint32_t tmp; + uint32_t tmp_ach_as[DRAM_CH_CNT][SLICE_CNT]; + + ddr_setval_ach_as(_reg_PHY_RX_CAL_X[9], 0x00); + ddr_setval_ach_as(_reg_PHY_RX_CAL_OVERRIDE, 0x00); + ddr_setval_ach_as(_reg_PHY_RX_CAL_SAMPLE_WAIT, 0x0f); + + retry = 0; + while (retry < 4096) { + if ((retry & 0xff) == 0) { + ddr_setval_ach_as(_reg_SC_PHY_RX_CAL_START, 0x01); + } + foreach_vch(ch) + for (slice = 0; slice < SLICE_CNT; slice++) + tmp_ach_as[ch][slice] = + ddr_getval_s(ch, slice, _reg_PHY_RX_CAL_X[9]); + + complete = 1; + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = tmp_ach_as[ch][slice]; + tmp = (tmp & 0x3f) + ((tmp >> 6) & 0x3f); + if (((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_11)) || + (prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + if (tmp != 0x3E) + complete = 0; + } else { + if (tmp != 0x40) + complete = 0; + } + } + } + if (complete) + break; + + retry++; + } + + return (complete == 0); +} + +/* adjust rddqs latency */ +static void adjust_rddqs_latency(void) +{ + uint32_t ch, slice; + uint32_t dly; + uint32_t maxlatx2; + uint32_t tmp; + uint32_t rdlat_adjx2[SLICE_CNT]; + + foreach_vch(ch) { + maxlatx2 = 0; + for (slice = 0; slice < SLICE_CNT; slice++) { + ddr_setval_s(ch, slice, _reg_PHY_PER_CS_TRAINING_INDEX, + 0x00); + + dly = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_GATE_SLAVE_DELAY); + tmp = + ddr_getval_s(ch, slice, + _reg_PHY_RDDQS_LATENCY_ADJUST); + /* note gate_slave_delay[9] is always 0 */ + tmp = (tmp << 1) + (dly >> 8); + rdlat_adjx2[slice] = tmp; + if (maxlatx2 < tmp) + maxlatx2 = tmp; + } + maxlatx2 = ((maxlatx2 + 1) >> 1) << 1; + for (slice = 0; slice < SLICE_CNT; slice++) { + tmp = maxlatx2 - rdlat_adjx2[slice]; + tmp = (tmp >> 1); + if (tmp) { + ddr_setval_s(ch, slice, _reg_PHY_RPTR_UPDATE, + ddr_getval_s(ch, slice, + _reg_PHY_RPTR_UPDATE) + + 1); + } + } + } +} + +/* adjust wpath latency */ +static void adjust_wpath_latency(void) +{ + uint32_t ch, cs, slice; + uint32_t dly; + uint32_t wpath_add; + const uint32_t _par_EARLY_THRESHOLD_VAL = 0x180; + + foreach_vch(ch) { + for (slice = 0; slice < SLICE_CNT; slice += 1) { + for (cs = 0; cs < CS_CNT; cs++) { + ddr_setval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX, + cs); + ddr_getval_s(ch, slice, + _reg_PHY_PER_CS_TRAINING_INDEX); + dly = + ddr_getval_s(ch, slice, + _reg_PHY_CLK_WRDQS_SLAVE_DELAY); + if (dly <= _par_EARLY_THRESHOLD_VAL) + continue; + + wpath_add = + ddr_getval_s(ch, slice, + _reg_PHY_WRITE_PATH_LAT_ADD); + ddr_setval_s(ch, slice, + _reg_PHY_WRITE_PATH_LAT_ADD, + wpath_add - 1); + } + } + } +} + +/* DDR Initialize entry */ +int32_t rcar_dram_init(void) +{ + uint32_t ch, cs; + uint32_t data_l; + uint32_t bus_mbps, bus_mbpsdiv; + uint32_t tmp_tccd; + uint32_t failcount; + uint32_t cnf_boardtype; + + /* Thermal sensor setting */ + data_l = mmio_read_32(CPG_MSTPSR5); + if (data_l & BIT(22)) { /* case THS/TSC Standby */ + data_l &= ~BIT(22); + cpg_write_32(CPG_SMSTPCR5, data_l); + while (mmio_read_32(CPG_MSTPSR5) & BIT(22)) + ; /* wait bit=0 */ + } + + /* THCTR Bit6: PONM=0 , Bit0: THSST=0 */ + data_l = mmio_read_32(THS1_THCTR); + if (data_l & 0x00000040U) { + data_l = data_l & 0xFFFFFFBEU; + } else { + data_l = data_l | BIT(1); + } + + mmio_write_32(THS1_THCTR, data_l); + + /* Judge product and cut */ +#ifdef RCAR_DDR_FIXED_LSI_TYPE +#if (RCAR_LSI == RCAR_AUTO) + prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#else /* RCAR_LSI */ +#ifndef RCAR_LSI_CUT + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#endif /* RCAR_LSI_CUT */ +#endif /* RCAR_LSI */ +#else /* RCAR_DDR_FIXED_LSI_TYPE */ + prr_product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + prr_cut = mmio_read_32(PRR) & PRR_CUT_MASK; +#endif /* RCAR_DDR_FIXED_LSI_TYPE */ + + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[0][0]; + } else { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[2][0]; + } + } else if (prr_product == PRR_PRODUCT_M3) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[1][0]; + } else if ((prr_product == PRR_PRODUCT_M3N) || + (prr_product == PRR_PRODUCT_V3H)) { + p_ddr_regdef_tbl = + (const uint32_t *)&DDR_REGDEF_TBL[3][0]; + } else { + FATAL_MSG("BL2: DDR:Unknown Product\n"); + return 0xff; + } + + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234); + } + + /* Judge board type */ + cnf_boardtype = boardcnf_get_brd_type(); + if (cnf_boardtype >= BOARDNUM) { + FATAL_MSG("BL2: DDR:Unknown Board\n"); + return 0xff; + } + board_cnf = (const struct _boardcnf *)&boardcnfs[cnf_boardtype]; + +/* RCAR_DRAM_SPLIT_2CH (2U) */ +#if RCAR_DRAM_SPLIT == 2 + /* H3(Test for future H3-N): Swap ch2 and ch1 for 2ch-split */ + if ((prr_product == PRR_PRODUCT_H3) && (board_cnf->phyvalid == 0x05)) { + mmio_write_32(DBSC_DBMEMSWAPCONF0, 0x00000006); + ddr_phyvalid = 0x03; + } else { + ddr_phyvalid = board_cnf->phyvalid; + } +#else /* RCAR_DRAM_SPLIT_2CH */ + ddr_phyvalid = board_cnf->phyvalid; +#endif /* RCAR_DRAM_SPLIT_2CH */ + + max_density = 0; + + for (cs = 0; cs < CS_CNT; cs++) { + ch_have_this_cs[cs] = 0; + } + + foreach_ech(ch) + for (cs = 0; cs < CS_CNT; cs++) + ddr_density[ch][cs] = 0xff; + + foreach_vch(ch) { + for (cs = 0; cs < CS_CNT; cs++) { + data_l = board_cnf->ch[ch].ddr_density[cs]; + ddr_density[ch][cs] = data_l; + + if (data_l == 0xff) + continue; + if (data_l > max_density) + max_density = data_l; + if ((cs == 1) && (prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) + continue; + ch_have_this_cs[cs] |= (1U << ch); + } + } + + /* Judge board clock frequency (in MHz) */ + boardcnf_get_brd_clk(cnf_boardtype, &brd_clk, &brd_clkdiv); + if ((brd_clk / brd_clkdiv) > 25) { + brd_clkdiva = 1; + } else { + brd_clkdiva = 0; + } + + /* Judge ddr operating frequency clock(in Mbps) */ + boardcnf_get_ddr_mbps(cnf_boardtype, &ddr_mbps, &ddr_mbpsdiv); + + ddr0800_mul = CLK_DIV(800, 2, brd_clk, brd_clkdiv * (brd_clkdiva + 1)); + + ddr_mul = CLK_DIV(ddr_mbps, ddr_mbpsdiv * 2, brd_clk, + brd_clkdiv * (brd_clkdiva + 1)); + + /* Adjust tccd */ + data_l = (0x00006000 & mmio_read_32(RST_MODEMR)) >> 13; + bus_mbps = 0; + bus_mbpsdiv = 0; + switch (data_l) { + case 0: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 1: + bus_mbps = brd_clk * 0x50 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 2: + bus_mbps = brd_clk * 0x40 * 2; + bus_mbpsdiv = brd_clkdiv * 1; + break; + case 3: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 2; + break; + default: + bus_mbps = brd_clk * 0x60 * 2; + bus_mbpsdiv = brd_clkdiv * 2; + break; + } + tmp_tccd = CLK_DIV(ddr_mbps * 8, ddr_mbpsdiv, bus_mbps, bus_mbpsdiv); + if (8 * ddr_mbps * bus_mbpsdiv != tmp_tccd * bus_mbps * ddr_mbpsdiv) + tmp_tccd = tmp_tccd + 1; + + if (tmp_tccd < 8) + ddr_tccd = 8; + else + ddr_tccd = tmp_tccd; + + NOTICE("BL2: DDR%d(%s)\n", ddr_mbps / ddr_mbpsdiv, RCAR_DDR_VERSION); + + MSG_LF("Start\n"); + + /* PLL Setting */ + pll3_control(1); + + /* initialize DDR */ + data_l = init_ddr(); + if (data_l == ddr_phyvalid) { + failcount = 0; + } else { + failcount = 1; + } + + foreach_vch(ch) + mmio_write_32(DBSC_DBPDLK(ch), 0x00000000); + if (((prr_product == PRR_PRODUCT_H3) && (prr_cut <= PRR_PRODUCT_11)) || + ((prr_product == PRR_PRODUCT_M3) && (prr_cut < PRR_PRODUCT_30))) { + /* non : H3 Ver.1.x/M3-W Ver.1.x not support */ + } else { + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000); + } + + if (failcount == 0) { + return INITDRAM_OK; + } else { + return INITDRAM_NG; + } +} + +void pvtcode_update(void) +{ + uint32_t ch; + uint32_t data_l; + uint32_t pvtp[4], pvtn[4], pvtp_init, pvtn_init; + int32_t pvtp_tmp, pvtn_tmp; + + foreach_vch(ch) { + pvtn_init = (tcal.tcomp_cal[ch] & 0xFC0) >> 6; + pvtp_init = (tcal.tcomp_cal[ch] & 0x03F) >> 0; + + if (8912 * pvtp_init > 44230) { + pvtp_tmp = (5000 + 8912 * pvtp_init - 44230) / 10000; + } else { + pvtp_tmp = + -((-(5000 + 8912 * pvtp_init - 44230)) / 10000); + } + pvtn_tmp = (5000 + 5776 * pvtn_init + 30280) / 10000; + + pvtn[ch] = pvtn_tmp + pvtn_init; + pvtp[ch] = pvtp_tmp + pvtp_init; + + if (pvtn[ch] > 63) { + pvtn[ch] = 63; + pvtp[ch] = + (pvtp_tmp) * (63 - 6 * pvtn_tmp - + pvtn_init) / (pvtn_tmp) + + 6 * pvtp_tmp + pvtp_init; + } + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + data_l = pvtp[ch] | (pvtn[ch] << 6) | + (tcal.tcomp_cal[ch] & 0xfffff000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + data_l | 0x00020000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + data_l); + } else { + data_l = pvtp[ch] | (pvtn[ch] << 6) | 0x00015000; + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + data_l | 0x00020000); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + data_l); + reg_ddrphy_write(ch, + ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + data_l); + } + } +} + +void pvtcode_update2(void) +{ + uint32_t ch; + + foreach_vch(ch) { + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_FDBK_TERM), + tcal.init_cal[ch] | 0x00020000); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DATA_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_DQS_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_ADDR_TERM), + tcal.init_cal[ch]); + reg_ddrphy_write(ch, ddr_regdef_adr(_reg_PHY_PAD_CS_TERM), + tcal.init_cal[ch]); + } +} + +void ddr_padcal_tcompensate_getinit(uint32_t override) +{ + uint32_t ch; + uint32_t data_l; + uint32_t pvtp, pvtn; + + tcal.init_temp = 0; + for (ch = 0; ch < 4; ch++) { + tcal.init_cal[ch] = 0; + tcal.tcomp_cal[ch] = 0; + } + + foreach_vch(ch) { + tcal.init_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]); + tcal.tcomp_cal[ch] = ddr_getval(ch, _reg_PHY_PAD_TERM_X[1]); + } + + if (!override) { + data_l = mmio_read_32(THS1_TEMP); + if (data_l < 2800) { + tcal.init_temp = + (143 * (int32_t)data_l - 359000) / 1000; + } else { + tcal.init_temp = + (121 * (int32_t)data_l - 296300) / 1000; + } + + foreach_vch(ch) { + pvtp = (tcal.init_cal[ch] >> 0) & 0x000003F; + pvtn = (tcal.init_cal[ch] >> 6) & 0x000003F; + if ((int32_t)pvtp > + ((tcal.init_temp * 29 - 3625) / 1000)) + pvtp = + (int32_t)pvtp + + ((3625 - tcal.init_temp * 29) / 1000); + else + pvtp = 0; + + if ((int32_t)pvtn > + ((tcal.init_temp * 54 - 6750) / 1000)) + pvtn = + (int32_t)pvtn + + ((6750 - tcal.init_temp * 54) / 1000); + else + pvtn = 0; + + if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + tcal.init_cal[ch] = + (tcal.init_cal[ch] & 0xfffff000) | + (pvtn << 6) | + pvtp; + } else { + tcal.init_cal[ch] = + 0x00015000 | (pvtn << 6) | pvtp; + } + } + tcal.init_temp = 125; + } +} + +#ifndef ddr_qos_init_setting +/* For QoS init */ +uint8_t get_boardcnf_phyvalid(void) +{ + return ddr_phyvalid; +} +#endif /* ddr_qos_init_setting */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c new file mode 100644 index 0000000..bbb0200 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c @@ -0,0 +1,2108 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZG_SOC +#define RZG_SOC 0 +#endif + +#if (RZG_SOC == 1) +#define BOARDNUM 4 +#else + +#include + +#define BOARDNUM 22 +#endif /* RZG_SOC == 1 */ +#define BOARD_JUDGE_AUTO + +#ifdef BOARD_JUDGE_AUTO +static uint32_t _board_judge(void); + +static uint32_t boardcnf_get_brd_type(void) +{ + return _board_judge(); +} +#else +static uint32_t boardcnf_get_brd_type(void) +{ + return 1; +} +#endif + +#define DDR_FAST_INIT + +struct _boardcnf_ch { + uint8_t ddr_density[CS_CNT]; + uint64_t ca_swap; + uint16_t dqs_swap; + uint32_t dq_swap[SLICE_CNT]; + uint8_t dm_swap[SLICE_CNT]; + uint16_t wdqlvl_patt[16]; + int8_t cacs_adj[16]; + int8_t dm_adj_w[SLICE_CNT]; + int8_t dq_adj_w[SLICE_CNT * 8]; + int8_t dm_adj_r[SLICE_CNT]; + int8_t dq_adj_r[SLICE_CNT * 8]; +}; + +struct _boardcnf { + uint8_t phyvalid; + uint8_t dbi_en; + uint16_t cacs_dly; + int16_t cacs_dly_adj; + uint16_t dqdm_dly_w; + uint16_t dqdm_dly_r; + struct _boardcnf_ch ch[DRAM_CH_CNT]; +}; + +#define WDQLVL_PAT {\ + 0x00AA,\ + 0x0055,\ + 0x00AA,\ + 0x0155,\ + 0x01CC,\ + 0x0133,\ + 0x00CC,\ + 0x0033,\ + 0x00F0,\ + 0x010F,\ + 0x01F0,\ + 0x010F,\ + 0x00F0,\ + 0x00F0,\ + 0x000F,\ + 0x010F} + +#if (RZG_SOC == 1) +static const struct _boardcnf boardcnfs[BOARDNUM] = { + { +/* boardcnf[0] HopeRun HiHope RZ/G2M 16Gbit/1rank/2ch board with G2M SoC */ + .phyvalid = 0x03U, + .dbi_en = 0x01U, + .cacs_dly = 0x02c0U, + .cacs_dly_adj = 0x0U, + .dqdm_dly_w = 0x0300U, + .dqdm_dly_r = 0x00a0U, + .ch = { + { + { 0x04U, 0xffU }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[1] HopeRun HiHope RZ/G2M 8Gbit/2rank/2ch board with G2M SoC */ + { + 0x03U, + 0x01U, + 0x02c0U, + 0x0U, + 0x0300U, + 0x00a0U, + { + { + { 0x02U, 0x02U }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x02U, 0x02U }, + 0x00302154UL, + 0x2310, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[2] HopeRun HiHope RZ/G2H board 16Gbit/1rank/2ch */ + { + 0x05U, + 0x01U, + 0x0300U, + 0, + 0x0300U, + 0x00a0U, + { + { + { 0x04U, 0xffU }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45367012U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0x04U, 0xffU }, + 0x00302154UL, + 0x2310U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + }, + { + { 0xffU, 0xffU }, + 0UL, + 0U, + { 0U, 0U, 0U, 0U }, + { 0U, 0U, 0U, 0U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +/* boardcnf[3] HopeRun HiHope RZ/G2N board 16Gbit/2rank/1ch */ + { + 0x01U, + 0x01U, + 0x0300U, + 0, + 0x0300U, + 0x00a0U, + { + { + { 0x04U, 0x04U }, + 0x00345201UL, + 0x3201U, + { 0x01672543U, 0x45361207U, 0x45632107U, 0x60715234U }, + { 0x08U, 0x08U, 0x08U, 0x08U }, + WDQLVL_PAT, + { 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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 } + } + } + }, +}; +#else +static const struct _boardcnf boardcnfs[BOARDNUM] = { + { +/* boardcnf[0] RENESAS SALVATOR-X board with M3-W/SIP */ + .phyvalid = 0x03, + .dbi_en = 0x01, + .cacs_dly = 0x02c0, + .cacs_dly_adj = 0, + .dqdm_dly_w = 0x0300, + .dqdm_dly_r = 0x00a0, + .ch = { + { + {0x02, 0x02}, + 0x00543210U, + 0x3201U, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + + { + {0x02, 0x02}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[1] RENESAS KRIEK board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x2c0, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[2] RENESAS SALVATOR-X board with H3 Ver.1.x/SIP(8Gbit 1rank) */ + { + 0x0f, + 0x00, + 0x300, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x3210, + {0x20741365, 0x34256107, 0x57460321, 0x70614532}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x3102, + {0x23547610, 0x34526107, 0x67452310, 0x32106754}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x0213, + {0x30216754, 0x67453210, 0x70165243, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x0213, + {0x01327654, 0x70615432, 0x54760123, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[3] RENESAS Starter Kit board with M3-W/SIP(8Gbit 1rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x02, 0xFF}, + 0x00543210U, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xFF}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[4] RENESAS SALVATOR-M(1rank) board with H3 Ver.1.x/SoC */ + { + 0x0f, + 0x00, + 0x2c0, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00315024, + 0x3120, + {0x30671254, 0x26541037, 0x17054623, 0x12307645}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00025143, + 0x3210, + {0x70613542, 0x16245307, 0x30712645, 0x21706354}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00523104, + 0x2301, + {0x70613542, 0x16245307, 0x30712645, 0x21706354}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00153402, + 0x2031, + {0x30671254, 0x26541037, 0x17054623, 0x12307645}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[5] RENESAS KRIEK-1rank board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x2c0, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[6] RENESAS SALVATOR-X board with H3 Ver.1.x/SIP(8Gbit 2rank) */ + { + 0x0f, + 0x00, + 0x300, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00543210, + 0x3210, + {0x20741365, 0x34256107, 0x57460321, 0x70614532}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x3102, + {0x23547610, 0x34526107, 0x67452310, 0x32106754}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x0213, + {0x30216754, 0x67453210, 0x70165243, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x0213, + {0x01327654, 0x70615432, 0x54760123, 0x07162345}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* + * boardcnf[7] RENESAS SALVATOR-X board with + * H3 Ver.2.0 or later/SIP(8Gbit 1rank) + */ + { + 0x0f, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* + * boardcnf[8] RENESAS SALVATOR-X board with + * H3 Ver.2.0 or later/SIP(8Gbit 2rank) + */ + { +#if RCAR_DRAM_CHANNEL == 5 + 0x05, +#else + 0x0f, +#endif + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#if ((RCAR_DRAM_CHANNEL == 5) && (RCAR_DRAM_SPLIT == 2)) + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#else + { + {0x02, 0x02}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#endif + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[9] RENESAS SALVATOR-MS(1rank) board with H3 Ver.2.0 or later/SoC */ + { + 0x0f, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0xff}, + 0x00543210, + 0x3210, + {0x27645310, 0x75346210, 0x53467210, 0x23674510}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00543210, + 0x2301, + {0x23764510, 0x43257610, 0x43752610, 0x37652401}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {-128, -128, -128, -128, -128, -128, 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, + 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, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00452103, + 0x3210, + {0x32764510, 0x43257610, 0x43752610, 0x26573401}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0xff}, + 0x00520413, + 0x2301, + {0x47652301, 0x75346210, 0x53467210, 0x32674501}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {30, 30, 30, 30, 30, 30, 30, 30, + 30, 30}, + {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, 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, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[10] RENESAS Kriek(2rank) board with M3-N/SoC */ + { + 0x01, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[11] RENESAS SALVATOR-X board with M3-N/SIP(8Gbit 2rank) */ + { + 0x01, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { +#if (RCAR_DRAM_LPDDR4_MEMCONF == 2) + {0x04, 0x04}, +#else + {0x02, 0x02}, +#endif + 0x00342501, + 0x3201, + {0x10672534, 0x43257106, 0x34527601, 0x71605243}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[12] RENESAS CONDOR board with V3H/SoC */ + { + 0x01, + 0x1, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00501342, + 0x3201, + {0x70562134, 0x34526071, 0x23147506, 0x12430567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[13] RENESAS KRIEK board with PM3/SoC */ + { + 0x05, + 0x00, + 0x2c0, + -320, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0xff, 0xff}, + 0, + 0, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[14] SALVATOR-X board with H3 Ver.2.0 or later/SIP(16Gbit 1rank) */ + { +#if RCAR_DRAM_CHANNEL == 5 + 0x05, +#else + 0x0f, +#endif + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x04, 0xff}, + 0x00543210, + 0x2310, + {0x70631425, 0x34527016, 0x43527610, 0x32104567}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#if ((RCAR_DRAM_CHANNEL == 5) && (RCAR_DRAM_SPLIT == 2)) + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#else + { + {0x04, 0xff}, + 0x00105432, + 0x3210, + {0x43256107, 0x07162354, 0x10234567, 0x01235467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, +#endif + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x01327654, 0x02316457, 0x10234567, 0x01325467}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00543210, + 0x2301, + {0x12034765, 0x23105467, 0x23017645, 0x32106745}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[15] RENESAS KRIEK board with H3N */ + { + 0x05, + 0x01, + 0x300, + 0, + 0x300, + 0x0a0, + { + { + {0x02, 0x02}, + 0x00345201, + 0x3201, + {0x01672543, 0x45367012, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x02, 0x02}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0xff, 0xff}, + 0, + 0, + {0, 0, 0, 0}, + {0, 0, 0, 0}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[16] RENESAS KRIEK-P2P board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x0320, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x520314FFFF523041, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x314250FFFF312405, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[17] RENESAS KRIEK-P2P board with M3-N/SoC */ + { + 0x01, + 0x01, + 0x0300, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x520314FFFF523041, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[18] RENESAS SALVATOR-X board with M3-W/SIP(16Gbit 2rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x00543210, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[19] RENESAS SALVATOR-X board with M3-W/SIP(16Gbit 1rank) */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0xff}, + 0x00543210, + 0x3201, + {0x70612543, 0x43251670, 0x45326170, 0x10672534}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00543210, + 0x2310, + {0x01327654, 0x34526107, 0x35421670, 0x70615324}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[20] RENESAS KRIEK 16Gbit/2rank/2ch board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0x04}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0x04}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + }, +/* boardcnf[21] RENESAS KRIEK 16Gbit/1rank/2ch board with M3-W/SoC */ + { + 0x03, + 0x01, + 0x02c0, + 0, + 0x0300, + 0x00a0, + { + { + {0x04, 0xff}, + 0x00345201, + 0x3201, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + }, + { + {0x04, 0xff}, + 0x00302154, + 0x2310, + {0x01672543, 0x45361207, 0x45632107, 0x60715234}, + {0x08, 0x08, 0x08, 0x08}, + WDQLVL_PAT, + {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, 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, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0} + } + } + } +}; +#endif /* RZG_SOC == 1 */ + +void boardcnf_get_brd_clk(uint32_t brd, uint32_t *clk, uint32_t *div) +{ + uint32_t md; + + if ((prr_product == PRR_PRODUCT_H3) && (prr_cut == PRR_PRODUCT_10)) { + *clk = 50; + *div = 3; + } else { + md = (mmio_read_32(RST_MODEMR) >> 13) & 0x3; + switch (md) { + case 0x0: + *clk = 50; + *div = 3; + break; + case 0x1: + *clk = 60; + *div = 3; + break; + case 0x2: + *clk = 75; + *div = 3; + break; + case 0x3: + *clk = 100; + *div = 3; + break; + } + } + (void)brd; +} + +void boardcnf_get_ddr_mbps(uint32_t brd, uint32_t *mbps, uint32_t *div) +{ + uint32_t md; + + if (prr_product == PRR_PRODUCT_V3H) { + md = (mmio_read_32(RST_MODEMR) >> 19) & 0x1; + md = (md | (md << 1)) & 0x3; /* 0 or 3 */ + } else { + md = (mmio_read_32(RST_MODEMR) >> 17) & 0x5; + md = (md | (md >> 1)) & 0x3; + } + switch (md) { + case 0x0: + *mbps = 3200; + *div = 1; + break; + case 0x1: + *mbps = 2800; + *div = 1; + break; + case 0x2: + *mbps = 2400; + *div = 1; + break; + case 0x3: + *mbps = 1600; + *div = 1; + break; + } + (void)brd; +} + +#define _def_REFPERIOD 1890 + +#define M3_SAMPLE_TT_A84 0xB866CC10, 0x3B250421 +#define M3_SAMPLE_TT_A85 0xB866CC10, 0x3AA50421 +#define M3_SAMPLE_TT_A86 0xB866CC10, 0x3AA48421 +#define M3_SAMPLE_FF_B45 0xB866CC10, 0x3AB00C21 +#define M3_SAMPLE_FF_B49 0xB866CC10, 0x39B10C21 +#define M3_SAMPLE_FF_B56 0xB866CC10, 0x3AAF8C21 +#define M3_SAMPLE_SS_E24 0xB866CC10, 0x3BA39421 +#define M3_SAMPLE_SS_E28 0xB866CC10, 0x3C231421 +#define M3_SAMPLE_SS_E32 0xB866CC10, 0x3C241421 + +static const uint32_t termcode_by_sample[20][3] = { + {M3_SAMPLE_TT_A84, 0x000158D5}, + {M3_SAMPLE_TT_A85, 0x00015955}, + {M3_SAMPLE_TT_A86, 0x00015955}, + {M3_SAMPLE_FF_B45, 0x00015690}, + {M3_SAMPLE_FF_B49, 0x00015753}, + {M3_SAMPLE_FF_B56, 0x00015793}, + {M3_SAMPLE_SS_E24, 0x00015996}, + {M3_SAMPLE_SS_E28, 0x000159D7}, + {M3_SAMPLE_SS_E32, 0x00015997}, + {0xFFFFFFFF, 0xFFFFFFFF, 0x0001554F} +}; + +#ifdef BOARD_JUDGE_AUTO +/* + * SAMPLE board detect function + */ +#define PFC_PMMR 0xE6060000U +#define PFC_PUEN5 0xE6060414U +#define PFC_PUEN6 0xE6060418U +#define PFC_PUD5 0xE6060454U +#define PFC_PUD6 0xE6060458U +#define GPIO_INDT5 0xE605500CU +#define GPIO_GPSR6 0xE6060118U + +#if (RCAR_GEN3_ULCB == 0) && (RZG_SOC == 0) +static void pfc_write_and_poll(uint32_t a, uint32_t v) +{ + mmio_write_32(PFC_PMMR, ~v); + v = ~mmio_read_32(PFC_PMMR); + mmio_write_32(a, v); + while (v != mmio_read_32(a)) + ; + dsb_sev(); +} +#endif + +#ifndef RCAR_GEN3_ULCB +#define RCAR_GEN3_ULCB 0 +#endif + +#if (RCAR_GEN3_ULCB == 0) && (RZG_SOC == 0) /* non Starter Kit */ + +static uint32_t opencheck_SSI_WS6(void) +{ + uint32_t dataL, down, up; + uint32_t gpsr6_bak; + uint32_t puen5_bak; + uint32_t pud5_bak; + + gpsr6_bak = mmio_read_32(GPIO_GPSR6); + puen5_bak = mmio_read_32(PFC_PUEN5); + pud5_bak = mmio_read_32(PFC_PUD5); + dsb_sev(); + + dataL = (gpsr6_bak & ~BIT(15)); + pfc_write_and_poll(GPIO_GPSR6, dataL); + + /* Pull-Up/Down Enable (PUEN5[22]=1) */ + dataL = puen5_bak; + dataL |= (BIT(22)); + pfc_write_and_poll(PFC_PUEN5, dataL); + + /* Pull-Down-Enable (PUD5[22]=0, PUEN5[22]=1) */ + dataL = pud5_bak; + dataL &= ~(BIT(22)); + pfc_write_and_poll(PFC_PUD5, dataL); + /* GPSR6[15]=SSI_WS6 */ + rcar_micro_delay(10); + down = (mmio_read_32(GPIO_INDT6) >> 15) & 0x1; + dsb_sev(); + + /* Pull-Up-Enable (PUD5[22]=1, PUEN5[22]=1) */ + dataL = pud5_bak; + dataL |= (BIT(22)); + pfc_write_and_poll(PFC_PUD5, dataL); + + /* GPSR6[15]=SSI_WS6 */ + rcar_micro_delay(10); + up = (mmio_read_32(GPIO_INDT6) >> 15) & 0x1; + + dsb_sev(); + + pfc_write_and_poll(GPIO_GPSR6, gpsr6_bak); + pfc_write_and_poll(PFC_PUEN5, puen5_bak); + pfc_write_and_poll(PFC_PUD5, pud5_bak); + + if (down == up) { + /* Same = Connect */ + return 0; + } + + /* Diff = Open */ + return 1; +} + +#endif + +#if (RZG_SOC == 1) +#define LPDDR4_2RANK (0x01U << 25U) + +static uint32_t rzg2_board_judge(void) +{ + uint32_t brd; + + switch (prr_product) { + case PRR_PRODUCT_M3: + brd = 1U; + if ((mmio_read_32(PRR) & PRR_CUT_MASK) != RCAR_M3_CUT_VER11) { + if ((mmio_read_32(GPIO_INDT5) & LPDDR4_2RANK) == 0U) { + brd = 0U; + } + } + break; + case PRR_PRODUCT_H3: + brd = 2U; + break; + case PRR_PRODUCT_M3N: + brd = 3U; + break; + default: + brd = 99U; + } + + return brd; +} +#endif /* RZG_SOC == 1 */ + +#if (RZG_SOC == 0) && (RCAR_DRAM_LPDDR4_MEMCONF != 0) +static uint32_t ddr_rank_judge(void) +{ + uint32_t brd; + +#if (RCAR_DRAM_MEMRANK == 0) + int32_t ret; + uint32_t type = 0U; + uint32_t rev = 0U; + + brd = 99U; + ret = rcar_get_board_type(&type, &rev); + if ((ret == 0) && (rev != 0xFFU)) { + if (type == (uint32_t)BOARD_SALVATOR_XS) { + if (rev == 0x11U) { + brd = 14U; + } else { + brd = 8U; + } + } else if (type == (uint32_t)BOARD_STARTER_KIT_PRE) { + if (rev == 0x21U) { + brd = 14U; + } else { + brd = 8U; + } + } + } +#elif (RCAR_DRAM_MEMRANK == 1) + brd = 14U; +#elif (RCAR_DRAM_MEMRANK == 2) + brd = 8U; +#else +#error Invalid value was set to RCAR_DRAM_MEMRANK +#endif /* (RCAR_DRAM_MEMRANK == 0) */ + return brd; +} +#endif /* (RCAR_DRAM_LPDDR4_MEMCONF != 0) */ + +static uint32_t _board_judge(void) +{ + uint32_t brd; + +#if (RZG_SOC == 1) + brd = rzg2_board_judge(); +#else +#if (RCAR_GEN3_ULCB == 1) + /* Starter Kit */ + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* RENESAS Starter Kit(H3 Ver.1.x/SIP) board */ + brd = 2; + } else { + /* RENESAS Starter Kit(H3 Ver.2.0 or later/SIP) board */ +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + brd = 7; +#else + brd = ddr_rank_judge(); +#endif + } + } else if (prr_product == PRR_PRODUCT_M3) { + if (prr_cut >= PRR_PRODUCT_30) { + /* RENESAS Starter Kit (M3-W Ver.3.0/SIP) */ + brd = 18; + } else { + /* RENESAS Starter Kit(M3-W/SIP 8Gbit 1rank) board */ + brd = 3; + } + } else { + /* RENESAS Starter Kit(M3-N/SIP) board */ + brd = 11; + } +#else + uint32_t usb2_ovc_open; + + usb2_ovc_open = opencheck_SSI_WS6(); + + /* RENESAS Eva-board */ + brd = 99; + if (prr_product == PRR_PRODUCT_V3H) { + /* RENESAS Condor board */ + brd = 12; + } else if (usb2_ovc_open) { + if (prr_product == PRR_PRODUCT_M3N) { + /* RENESAS Kriek board with M3-N */ + brd = 10; + } else if (prr_product == PRR_PRODUCT_M3) { + /* RENESAS Kriek board with M3-W */ + brd = 1; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut <= PRR_PRODUCT_11)) { + /* RENESAS Kriek board with PM3 */ + brd = 13; + } else if ((prr_product == PRR_PRODUCT_H3) && + (prr_cut > PRR_PRODUCT_20)) { + /* RENESAS Kriek board with H3N */ + brd = 15; + } + } else { + if (prr_product == PRR_PRODUCT_H3) { + if (prr_cut <= PRR_PRODUCT_11) { + /* RENESAS SALVATOR-X (H3 Ver.1.x/SIP) */ + brd = 2; + } else if (prr_cut < PRR_PRODUCT_30) { + /* RENESAS SALVATOR-X (H3 Ver.2.0/SIP) */ + brd = 7; // 8Gbit/1rank + } else { + /* RENESAS SALVATOR-X (H3 Ver.3.0/SIP) */ +#if (RCAR_DRAM_LPDDR4_MEMCONF == 0) + brd = 7; +#else + brd = ddr_rank_judge(); +#endif + } + } else if (prr_product == PRR_PRODUCT_M3N) { + /* RENESAS SALVATOR-X (M3-N/SIP) */ + brd = 11; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut <= PRR_PRODUCT_20)) { + /* RENESAS SALVATOR-X (M3-W/SIP) */ + brd = 0; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut < PRR_PRODUCT_30)) { + /* RENESAS SALVATOR-X (M3-W Ver.1.x/SIP) */ + brd = 19; + } else if ((prr_product == PRR_PRODUCT_M3) && + (prr_cut >= PRR_PRODUCT_30)) { + /* RENESAS SALVATOR-X (M3-W ver.3.0/SIP) */ + brd = 18; + } + } +#endif +#endif /* RZG_SOC == 1 */ + + return brd; +} +#endif diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h new file mode 100644 index 0000000..3cb1975 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_DDR_VERSION "rev.0.41" +#define DRAM_CH_CNT 0x04 +#define SLICE_CNT 0x04 +#define CS_CNT 0x02 + +/* order : CS0A, CS0B, CS1A, CS1B */ +#define CSAB_CNT (CS_CNT * 2) + +/* order : CH0A, CH0B, CH1A, CH1B, CH2A, CH2B, CH3A, CH3B */ +#define CHAB_CNT (DRAM_CH_CNT * 2) + +/* pll setting */ +#define CLK_DIV(a, diva, b, divb) (((a) * (divb)) / ((b) * (diva))) +#define CLK_MUL(a, diva, b, divb) (((a) * (b)) / ((diva) * (divb))) + +/* for ddr deisity setting */ +#define DBMEMCONF_REG(d3, row, bank, col, dw) \ + (((d3) << 30) | ((row) << 24) | ((bank) << 16) | ((col) << 8) | (dw)) + +#define DBMEMCONF_REGD(density) \ + (DBMEMCONF_REG((density) % 2, ((density) + 1) / \ + 2 + (29 - 3 - 10 - 2), 3, 10, 2)) + +#define DBMEMCONF_VAL(ch, cs) (DBMEMCONF_REGD(DBMEMCONF_DENS(ch, cs))) + +/* refresh mode */ +#define DBSC_REFINTS (0x0) + +/* system registers */ +#define CPG_FRQCRB (CPG_BASE + 0x0004U) + +#define CPG_PLLECR (CPG_BASE + 0x00D0U) +#define CPG_MSTPSR5 (CPG_BASE + 0x003CU) +#define CPG_SRCR4 (CPG_BASE + 0x00BCU) +#define CPG_PLL3CR (CPG_BASE + 0x00DCU) +#define CPG_ZB3CKCR (CPG_BASE + 0x0380U) +#define CPG_FRQCRD (CPG_BASE + 0x00E4U) +#define CPG_SMSTPCR5 (CPG_BASE + 0x0144U) +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +#define CPG_SRSTCLR4 (CPG_BASE + 0x0950U) + +#define CPG_FRQCRB_KICK_BIT BIT(31) +#define CPG_PLLECR_PLL3E_BIT BIT(3) +#define CPG_PLLECR_PLL3ST_BIT BIT(11) +#define CPG_ZB3CKCR_ZB3ST_BIT BIT(11) + +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) + +#define LIFEC_CHIPID(x) (0xE6110040U + 0x04U * (x)) + +/* DBSC registers */ +#include "../ddr_regs.h" + +#define DBSC_DBMONCONF4 0xE6793010U + +#define DBSC_PLL_LOCK(ch) (0xE6794054U + 0x100U * (ch)) +#define DBSC_PLL_LOCK_0 0xE6794054U +#define DBSC_PLL_LOCK_1 0xE6794154U +#define DBSC_PLL_LOCK_2 0xE6794254U +#define DBSC_PLL_LOCK_3 0xE6794354U + +/* STAT registers */ +#define MSTAT_SL_INIT 0xE67E8000U +#define MSTAT_REF_ARS 0xE67E8004U +#define MSTATQ_STATQC 0xE67E8008U +#define MSTATQ_WTENABLE 0xE67E8030U +#define MSTATQ_WTREFRESH 0xE67E8034U +#define MSTATQ_WTSETTING0 0xE67E8038U +#define MSTATQ_WTSETTING1 0xE67E803CU + +#define QOS_BASE1 (0xE67F0000U) +#define QOSCTRL_RAS (QOS_BASE1 + 0x0000U) +#define QOSCTRL_FIXTH (QOS_BASE1 + 0x0004U) +#define QOSCTRL_RAEN (QOS_BASE1 + 0x0018U) +#define QOSCTRL_REGGD (QOS_BASE1 + 0x0020U) +#define QOSCTRL_DANN (QOS_BASE1 + 0x0030U) +#define QOSCTRL_DANT (QOS_BASE1 + 0x0038U) +#define QOSCTRL_EC (QOS_BASE1 + 0x003CU) +#define QOSCTRL_EMS (QOS_BASE1 + 0x0040U) +#define QOSCTRL_INSFC (QOS_BASE1 + 0x0050U) +#define QOSCTRL_BERR (QOS_BASE1 + 0x0054U) +#define QOSCTRL_RACNT0 (QOS_BASE1 + 0x0080U) +#define QOSCTRL_STATGEN0 (QOS_BASE1 + 0x0088U) + +/* other module */ +#define THS1_THCTR 0xE6198020U +#define THS1_TEMP 0xE6198028U diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk new file mode 100644 index 0000000..0334780 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_b.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL2_SOURCES += drivers/renesas/common/ddr/ddr_b/boot_init_dram.c diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h new file mode 100644 index 0000000..adf8dab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h @@ -0,0 +1,5887 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define _reg_PHY_DQ_DM_SWIZZLE0 0x00000000U +#define _reg_PHY_DQ_DM_SWIZZLE1 0x00000001U +#define _reg_PHY_CLK_WR_BYPASS_SLAVE_DELAY 0x00000002U +#define _reg_PHY_RDDQS_GATE_BYPASS_SLAVE_DELAY 0x00000003U +#define _reg_PHY_BYPASS_TWO_CYC_PREAMBLE 0x00000004U +#define _reg_PHY_CLK_BYPASS_OVERRIDE 0x00000005U +#define _reg_PHY_SW_WRDQ0_SHIFT 0x00000006U +#define _reg_PHY_SW_WRDQ1_SHIFT 0x00000007U +#define _reg_PHY_SW_WRDQ2_SHIFT 0x00000008U +#define _reg_PHY_SW_WRDQ3_SHIFT 0x00000009U +#define _reg_PHY_SW_WRDQ4_SHIFT 0x0000000aU +#define _reg_PHY_SW_WRDQ5_SHIFT 0x0000000bU +#define _reg_PHY_SW_WRDQ6_SHIFT 0x0000000cU +#define _reg_PHY_SW_WRDQ7_SHIFT 0x0000000dU +#define _reg_PHY_SW_WRDM_SHIFT 0x0000000eU +#define _reg_PHY_SW_WRDQS_SHIFT 0x0000000fU +#define _reg_PHY_DQ_TSEL_ENABLE 0x00000010U +#define _reg_PHY_DQ_TSEL_SELECT 0x00000011U +#define _reg_PHY_DQS_TSEL_ENABLE 0x00000012U +#define _reg_PHY_DQS_TSEL_SELECT 0x00000013U +#define _reg_PHY_TWO_CYC_PREAMBLE 0x00000014U +#define _reg_PHY_DBI_MODE 0x00000015U +#define _reg_PHY_PER_RANK_CS_MAP 0x00000016U +#define _reg_PHY_PER_CS_TRAINING_MULTICAST_EN 0x00000017U +#define _reg_PHY_PER_CS_TRAINING_INDEX 0x00000018U +#define _reg_PHY_LP4_BOOT_RDDATA_EN_IE_DLY 0x00000019U +#define _reg_PHY_LP4_BOOT_RDDATA_EN_DLY 0x0000001aU +#define _reg_PHY_LP4_BOOT_RDDATA_EN_TSEL_DLY 0x0000001bU +#define _reg_PHY_LP4_BOOT_RPTR_UPDATE 0x0000001cU +#define _reg_PHY_LP4_BOOT_RDDQS_GATE_SLAVE_DELAY 0x0000001dU +#define _reg_PHY_LP4_BOOT_RDDQS_LATENCY_ADJUST 0x0000001eU +#define _reg_PHY_LP4_BOOT_WRPATH_GATE_DISABLE 0x0000001fU +#define _reg_PHY_LP4_BOOT_RDDATA_EN_OE_DLY 0x00000020U +#define _reg_PHY_LPBK_CONTROL 0x00000021U +#define _reg_PHY_LPBK_DFX_TIMEOUT_EN 0x00000022U +#define _reg_PHY_AUTO_TIMING_MARGIN_CONTROL 0x00000023U +#define _reg_PHY_AUTO_TIMING_MARGIN_OBS 0x00000024U +#define _reg_PHY_SLICE_PWR_RDC_DISABLE 0x00000025U +#define _reg_PHY_PRBS_PATTERN_START 0x00000026U +#define _reg_PHY_PRBS_PATTERN_MASK 0x00000027U +#define _reg_PHY_RDDQS_DQ_BYPASS_SLAVE_DELAY 0x00000028U +#define _reg_PHY_GATE_ERROR_DELAY_SELECT 0x00000029U +#define _reg_SC_PHY_SNAP_OBS_REGS 0x0000002aU +#define _reg_PHY_LPDDR 0x0000002bU +#define _reg_PHY_LPDDR_TYPE 0x0000002cU +#define _reg_PHY_GATE_SMPL1_SLAVE_DELAY 0x0000002dU +#define _reg_PHY_GATE_SMPL2_SLAVE_DELAY 0x0000002eU +#define _reg_ON_FLY_GATE_ADJUST_EN 0x0000002fU +#define _reg_PHY_GATE_TRACKING_OBS 0x00000030U +#define _reg_PHY_DFI40_POLARITY 0x00000031U +#define _reg_PHY_LP4_PST_AMBLE 0x00000032U +#define _reg_PHY_RDLVL_PATT8 0x00000033U +#define _reg_PHY_RDLVL_PATT9 0x00000034U +#define _reg_PHY_RDLVL_PATT10 0x00000035U +#define _reg_PHY_RDLVL_PATT11 0x00000036U +#define _reg_PHY_LP4_RDLVL_PATT8 0x00000037U +#define _reg_PHY_LP4_RDLVL_PATT9 0x00000038U +#define _reg_PHY_LP4_RDLVL_PATT10 0x00000039U +#define _reg_PHY_LP4_RDLVL_PATT11 0x0000003aU +#define _reg_PHY_SLAVE_LOOP_CNT_UPDATE 0x0000003bU +#define _reg_PHY_SW_FIFO_PTR_RST_DISABLE 0x0000003cU +#define _reg_PHY_MASTER_DLY_LOCK_OBS_SELECT 0x0000003dU +#define _reg_PHY_RDDQ_ENC_OBS_SELECT 0x0000003eU +#define _reg_PHY_RDDQS_DQ_ENC_OBS_SELECT 0x0000003fU +#define _reg_PHY_WR_ENC_OBS_SELECT 0x00000040U +#define _reg_PHY_WR_SHIFT_OBS_SELECT 0x00000041U +#define _reg_PHY_FIFO_PTR_OBS_SELECT 0x00000042U +#define _reg_PHY_LVL_DEBUG_MODE 0x00000043U +#define _reg_SC_PHY_LVL_DEBUG_CONT 0x00000044U +#define _reg_PHY_WRLVL_CAPTURE_CNT 0x00000045U +#define _reg_PHY_WRLVL_UPDT_WAIT_CNT 0x00000046U +#define _reg_PHY_WRLVL_DQ_MASK 0x00000047U +#define _reg_PHY_GTLVL_CAPTURE_CNT 0x00000048U +#define _reg_PHY_GTLVL_UPDT_WAIT_CNT 0x00000049U +#define _reg_PHY_RDLVL_CAPTURE_CNT 0x0000004aU +#define _reg_PHY_RDLVL_UPDT_WAIT_CNT 0x0000004bU +#define _reg_PHY_RDLVL_OP_MODE 0x0000004cU +#define _reg_PHY_RDLVL_RDDQS_DQ_OBS_SELECT 0x0000004dU +#define _reg_PHY_RDLVL_DATA_MASK 0x0000004eU +#define _reg_PHY_RDLVL_DATA_SWIZZLE 0x0000004fU +#define _reg_PHY_WDQLVL_BURST_CNT 0x00000050U +#define _reg_PHY_WDQLVL_PATT 0x00000051U +#define _reg_PHY_WDQLVL_DQDM_SLV_DLY_JUMP_OFFSET 0x00000052U +#define _reg_PHY_WDQLVL_UPDT_WAIT_CNT 0x00000053U +#define _reg_PHY_WDQLVL_DQDM_OBS_SELECT 0x00000054U +#define _reg_PHY_WDQLVL_QTR_DLY_STEP 0x00000055U +#define _reg_SC_PHY_WDQLVL_CLR_PREV_RESULTS 0x00000056U +#define _reg_PHY_WDQLVL_CLR_PREV_RESULTS 0x00000057U +#define _reg_PHY_WDQLVL_DATADM_MASK 0x00000058U +#define _reg_PHY_USER_PATT0 0x00000059U +#define _reg_PHY_USER_PATT1 0x0000005aU +#define _reg_PHY_USER_PATT2 0x0000005bU +#define _reg_PHY_USER_PATT3 0x0000005cU +#define _reg_PHY_USER_PATT4 0x0000005dU +#define _reg_PHY_DQ_SWIZZLING 0x0000005eU +#define _reg_PHY_CALVL_VREF_DRIVING_SLICE 0x0000005fU +#define _reg_SC_PHY_MANUAL_CLEAR 0x00000060U +#define _reg_PHY_FIFO_PTR_OBS 0x00000061U +#define _reg_PHY_LPBK_RESULT_OBS 0x00000062U +#define _reg_PHY_LPBK_ERROR_COUNT_OBS 0x00000063U +#define _reg_PHY_MASTER_DLY_LOCK_OBS 0x00000064U +#define _reg_PHY_RDDQ_SLV_DLY_ENC_OBS 0x00000065U +#define _reg_PHY_RDDQS_BASE_SLV_DLY_ENC_OBS 0x00000066U +#define _reg_PHY_RDDQS_DQ_RISE_ADDER_SLV_DLY_ENC_OBS 0x00000067U +#define _reg_PHY_RDDQS_DQ_FALL_ADDER_SLV_DLY_ENC_OBS 0x00000068U +#define _reg_PHY_RDDQS_GATE_SLV_DLY_ENC_OBS 0x00000069U +#define _reg_PHY_WRDQS_BASE_SLV_DLY_ENC_OBS 0x0000006aU +#define _reg_PHY_WRDQ_BASE_SLV_DLY_ENC_OBS 0x0000006bU +#define _reg_PHY_WR_ADDER_SLV_DLY_ENC_OBS 0x0000006cU +#define _reg_PHY_WR_SHIFT_OBS 0x0000006dU +#define _reg_PHY_WRLVL_HARD0_DELAY_OBS 0x0000006eU +#define _reg_PHY_WRLVL_HARD1_DELAY_OBS 0x0000006fU +#define _reg_PHY_WRLVL_STATUS_OBS 0x00000070U +#define _reg_PHY_GATE_SMPL1_SLV_DLY_ENC_OBS 0x00000071U +#define _reg_PHY_GATE_SMPL2_SLV_DLY_ENC_OBS 0x00000072U +#define _reg_PHY_WRLVL_ERROR_OBS 0x00000073U +#define _reg_PHY_GTLVL_HARD0_DELAY_OBS 0x00000074U +#define _reg_PHY_GTLVL_HARD1_DELAY_OBS 0x00000075U +#define _reg_PHY_GTLVL_STATUS_OBS 0x00000076U +#define _reg_PHY_RDLVL_RDDQS_DQ_LE_DLY_OBS 0x00000077U +#define _reg_PHY_RDLVL_RDDQS_DQ_TE_DLY_OBS 0x00000078U +#define _reg_PHY_RDLVL_RDDQS_DQ_NUM_WINDOWS_OBS 0x00000079U +#define _reg_PHY_RDLVL_STATUS_OBS 0x0000007aU +#define _reg_PHY_WDQLVL_DQDM_LE_DLY_OBS 0x0000007bU +#define _reg_PHY_WDQLVL_DQDM_TE_DLY_OBS 0x0000007cU +#define _reg_PHY_WDQLVL_STATUS_OBS 0x0000007dU +#define _reg_PHY_DDL_MODE 0x0000007eU +#define _reg_PHY_DDL_TEST_OBS 0x0000007fU +#define _reg_PHY_DDL_TEST_MSTR_DLY_OBS 0x00000080U +#define _reg_PHY_DDL_TRACK_UPD_THRESHOLD 0x00000081U +#define _reg_PHY_LP4_WDQS_OE_EXTEND 0x00000082U +#define _reg_SC_PHY_RX_CAL_START 0x00000083U +#define _reg_PHY_RX_CAL_OVERRIDE 0x00000084U +#define _reg_PHY_RX_CAL_SAMPLE_WAIT 0x00000085U +#define _reg_PHY_RX_CAL_DQ0 0x00000086U +#define _reg_PHY_RX_CAL_DQ1 0x00000087U +#define _reg_PHY_RX_CAL_DQ2 0x00000088U +#define _reg_PHY_RX_CAL_DQ3 0x00000089U +#define _reg_PHY_RX_CAL_DQ4 0x0000008aU +#define _reg_PHY_RX_CAL_DQ5 0x0000008bU +#define _reg_PHY_RX_CAL_DQ6 0x0000008cU +#define _reg_PHY_RX_CAL_DQ7 0x0000008dU +#define _reg_PHY_RX_CAL_DM 0x0000008eU +#define _reg_PHY_RX_CAL_DQS 0x0000008fU +#define _reg_PHY_RX_CAL_FDBK 0x00000090U +#define _reg_PHY_RX_CAL_OBS 0x00000091U +#define _reg_PHY_RX_CAL_LOCK_OBS 0x00000092U +#define _reg_PHY_RX_CAL_DISABLE 0x00000093U +#define _reg_PHY_CLK_WRDQ0_SLAVE_DELAY 0x00000094U +#define _reg_PHY_CLK_WRDQ1_SLAVE_DELAY 0x00000095U +#define _reg_PHY_CLK_WRDQ2_SLAVE_DELAY 0x00000096U +#define _reg_PHY_CLK_WRDQ3_SLAVE_DELAY 0x00000097U +#define _reg_PHY_CLK_WRDQ4_SLAVE_DELAY 0x00000098U +#define _reg_PHY_CLK_WRDQ5_SLAVE_DELAY 0x00000099U +#define _reg_PHY_CLK_WRDQ6_SLAVE_DELAY 0x0000009aU +#define _reg_PHY_CLK_WRDQ7_SLAVE_DELAY 0x0000009bU +#define _reg_PHY_CLK_WRDM_SLAVE_DELAY 0x0000009cU +#define _reg_PHY_CLK_WRDQS_SLAVE_DELAY 0x0000009dU +#define _reg_PHY_WRLVL_THRESHOLD_ADJUST 0x0000009eU +#define _reg_PHY_RDDQ0_SLAVE_DELAY 0x0000009fU +#define _reg_PHY_RDDQ1_SLAVE_DELAY 0x000000a0U +#define _reg_PHY_RDDQ2_SLAVE_DELAY 0x000000a1U +#define _reg_PHY_RDDQ3_SLAVE_DELAY 0x000000a2U +#define _reg_PHY_RDDQ4_SLAVE_DELAY 0x000000a3U +#define _reg_PHY_RDDQ5_SLAVE_DELAY 0x000000a4U +#define _reg_PHY_RDDQ6_SLAVE_DELAY 0x000000a5U +#define _reg_PHY_RDDQ7_SLAVE_DELAY 0x000000a6U +#define _reg_PHY_RDDM_SLAVE_DELAY 0x000000a7U +#define _reg_PHY_RDDQS_DQ0_RISE_SLAVE_DELAY 0x000000a8U +#define _reg_PHY_RDDQS_DQ0_FALL_SLAVE_DELAY 0x000000a9U +#define _reg_PHY_RDDQS_DQ1_RISE_SLAVE_DELAY 0x000000aaU +#define _reg_PHY_RDDQS_DQ1_FALL_SLAVE_DELAY 0x000000abU +#define _reg_PHY_RDDQS_DQ2_RISE_SLAVE_DELAY 0x000000acU +#define _reg_PHY_RDDQS_DQ2_FALL_SLAVE_DELAY 0x000000adU +#define _reg_PHY_RDDQS_DQ3_RISE_SLAVE_DELAY 0x000000aeU +#define _reg_PHY_RDDQS_DQ3_FALL_SLAVE_DELAY 0x000000afU +#define _reg_PHY_RDDQS_DQ4_RISE_SLAVE_DELAY 0x000000b0U +#define _reg_PHY_RDDQS_DQ4_FALL_SLAVE_DELAY 0x000000b1U +#define _reg_PHY_RDDQS_DQ5_RISE_SLAVE_DELAY 0x000000b2U +#define _reg_PHY_RDDQS_DQ5_FALL_SLAVE_DELAY 0x000000b3U +#define _reg_PHY_RDDQS_DQ6_RISE_SLAVE_DELAY 0x000000b4U +#define _reg_PHY_RDDQS_DQ6_FALL_SLAVE_DELAY 0x000000b5U +#define _reg_PHY_RDDQS_DQ7_RISE_SLAVE_DELAY 0x000000b6U +#define _reg_PHY_RDDQS_DQ7_FALL_SLAVE_DELAY 0x000000b7U +#define _reg_PHY_RDDQS_DM_RISE_SLAVE_DELAY 0x000000b8U +#define _reg_PHY_RDDQS_DM_FALL_SLAVE_DELAY 0x000000b9U +#define _reg_PHY_RDDQS_GATE_SLAVE_DELAY 0x000000baU +#define _reg_PHY_RDDQS_LATENCY_ADJUST 0x000000bbU +#define _reg_PHY_WRITE_PATH_LAT_ADD 0x000000bcU +#define _reg_PHY_WRLVL_DELAY_EARLY_THRESHOLD 0x000000bdU +#define _reg_PHY_WRLVL_DELAY_PERIOD_THRESHOLD 0x000000beU +#define _reg_PHY_WRLVL_EARLY_FORCE_ZERO 0x000000bfU +#define _reg_PHY_GTLVL_RDDQS_SLV_DLY_START 0x000000c0U +#define _reg_PHY_GTLVL_LAT_ADJ_START 0x000000c1U +#define _reg_PHY_WDQLVL_DQDM_SLV_DLY_START 0x000000c2U +#define _reg_PHY_RDLVL_RDDQS_DQ_SLV_DLY_START 0x000000c3U +#define _reg_PHY_FDBK_PWR_CTRL 0x000000c4U +#define _reg_PHY_DQ_OE_TIMING 0x000000c5U +#define _reg_PHY_DQ_TSEL_RD_TIMING 0x000000c6U +#define _reg_PHY_DQ_TSEL_WR_TIMING 0x000000c7U +#define _reg_PHY_DQS_OE_TIMING 0x000000c8U +#define _reg_PHY_DQS_TSEL_RD_TIMING 0x000000c9U +#define _reg_PHY_DQS_OE_RD_TIMING 0x000000caU +#define _reg_PHY_DQS_TSEL_WR_TIMING 0x000000cbU +#define _reg_PHY_PER_CS_TRAINING_EN 0x000000ccU +#define _reg_PHY_DQ_IE_TIMING 0x000000cdU +#define _reg_PHY_DQS_IE_TIMING 0x000000ceU +#define _reg_PHY_RDDATA_EN_IE_DLY 0x000000cfU +#define _reg_PHY_IE_MODE 0x000000d0U +#define _reg_PHY_RDDATA_EN_DLY 0x000000d1U +#define _reg_PHY_RDDATA_EN_TSEL_DLY 0x000000d2U +#define _reg_PHY_RDDATA_EN_OE_DLY 0x000000d3U +#define _reg_PHY_SW_MASTER_MODE 0x000000d4U +#define _reg_PHY_MASTER_DELAY_START 0x000000d5U +#define _reg_PHY_MASTER_DELAY_STEP 0x000000d6U +#define _reg_PHY_MASTER_DELAY_WAIT 0x000000d7U +#define _reg_PHY_MASTER_DELAY_HALF_MEASURE 0x000000d8U +#define _reg_PHY_RPTR_UPDATE 0x000000d9U +#define _reg_PHY_WRLVL_DLY_STEP 0x000000daU +#define _reg_PHY_WRLVL_RESP_WAIT_CNT 0x000000dbU +#define _reg_PHY_GTLVL_DLY_STEP 0x000000dcU +#define _reg_PHY_GTLVL_RESP_WAIT_CNT 0x000000ddU +#define _reg_PHY_GTLVL_BACK_STEP 0x000000deU +#define _reg_PHY_GTLVL_FINAL_STEP 0x000000dfU +#define _reg_PHY_WDQLVL_DLY_STEP 0x000000e0U +#define _reg_PHY_TOGGLE_PRE_SUPPORT 0x000000e1U +#define _reg_PHY_RDLVL_DLY_STEP 0x000000e2U +#define _reg_PHY_WRPATH_GATE_DISABLE 0x000000e3U +#define _reg_PHY_WRPATH_GATE_TIMING 0x000000e4U +#define _reg_PHY_ADR0_SW_WRADDR_SHIFT 0x000000e5U +#define _reg_PHY_ADR1_SW_WRADDR_SHIFT 0x000000e6U +#define _reg_PHY_ADR2_SW_WRADDR_SHIFT 0x000000e7U +#define _reg_PHY_ADR3_SW_WRADDR_SHIFT 0x000000e8U +#define _reg_PHY_ADR4_SW_WRADDR_SHIFT 0x000000e9U +#define _reg_PHY_ADR5_SW_WRADDR_SHIFT 0x000000eaU +#define _reg_PHY_ADR_CLK_WR_BYPASS_SLAVE_DELAY 0x000000ebU +#define _reg_PHY_ADR_CLK_BYPASS_OVERRIDE 0x000000ecU +#define _reg_SC_PHY_ADR_MANUAL_CLEAR 0x000000edU +#define _reg_PHY_ADR_LPBK_RESULT_OBS 0x000000eeU +#define _reg_PHY_ADR_LPBK_ERROR_COUNT_OBS 0x000000efU +#define _reg_PHY_ADR_MASTER_DLY_LOCK_OBS_SELECT 0x000000f0U +#define _reg_PHY_ADR_MASTER_DLY_LOCK_OBS 0x000000f1U +#define _reg_PHY_ADR_BASE_SLV_DLY_ENC_OBS 0x000000f2U +#define _reg_PHY_ADR_ADDER_SLV_DLY_ENC_OBS 0x000000f3U +#define _reg_PHY_ADR_SLAVE_LOOP_CNT_UPDATE 0x000000f4U +#define _reg_PHY_ADR_SLV_DLY_ENC_OBS_SELECT 0x000000f5U +#define _reg_SC_PHY_ADR_SNAP_OBS_REGS 0x000000f6U +#define _reg_PHY_ADR_TSEL_ENABLE 0x000000f7U +#define _reg_PHY_ADR_LPBK_CONTROL 0x000000f8U +#define _reg_PHY_ADR_PRBS_PATTERN_START 0x000000f9U +#define _reg_PHY_ADR_PRBS_PATTERN_MASK 0x000000faU +#define _reg_PHY_ADR_PWR_RDC_DISABLE 0x000000fbU +#define _reg_PHY_ADR_TYPE 0x000000fcU +#define _reg_PHY_ADR_WRADDR_SHIFT_OBS 0x000000fdU +#define _reg_PHY_ADR_IE_MODE 0x000000feU +#define _reg_PHY_ADR_DDL_MODE 0x000000ffU +#define _reg_PHY_ADR_DDL_TEST_OBS 0x00000100U +#define _reg_PHY_ADR_DDL_TEST_MSTR_DLY_OBS 0x00000101U +#define _reg_PHY_ADR_CALVL_START 0x00000102U +#define _reg_PHY_ADR_CALVL_COARSE_DLY 0x00000103U +#define _reg_PHY_ADR_CALVL_QTR 0x00000104U +#define _reg_PHY_ADR_CALVL_SWIZZLE0 0x00000105U +#define _reg_PHY_ADR_CALVL_SWIZZLE1 0x00000106U +#define _reg_PHY_ADR_CALVL_SWIZZLE0_0 0x00000107U +#define _reg_PHY_ADR_CALVL_SWIZZLE1_0 0x00000108U +#define _reg_PHY_ADR_CALVL_SWIZZLE0_1 0x00000109U +#define _reg_PHY_ADR_CALVL_SWIZZLE1_1 0x0000010aU +#define _reg_PHY_ADR_CALVL_DEVICE_MAP 0x0000010bU +#define _reg_PHY_ADR_CALVL_RANK_CTRL 0x0000010cU +#define _reg_PHY_ADR_CALVL_NUM_PATTERNS 0x0000010dU +#define _reg_PHY_ADR_CALVL_CAPTURE_CNT 0x0000010eU +#define _reg_PHY_ADR_CALVL_RESP_WAIT_CNT 0x0000010fU +#define _reg_PHY_ADR_CALVL_DEBUG_MODE 0x00000110U +#define _reg_SC_PHY_ADR_CALVL_DEBUG_CONT 0x00000111U +#define _reg_SC_PHY_ADR_CALVL_ERROR_CLR 0x00000112U +#define _reg_PHY_ADR_CALVL_OBS_SELECT 0x00000113U +#define _reg_PHY_ADR_CALVL_OBS0 0x00000114U +#define _reg_PHY_ADR_CALVL_OBS1 0x00000115U +#define _reg_PHY_ADR_CALVL_RESULT 0x00000116U +#define _reg_PHY_ADR_CALVL_FG_0 0x00000117U +#define _reg_PHY_ADR_CALVL_BG_0 0x00000118U +#define _reg_PHY_ADR_CALVL_FG_1 0x00000119U +#define _reg_PHY_ADR_CALVL_BG_1 0x0000011aU +#define _reg_PHY_ADR_CALVL_FG_2 0x0000011bU +#define _reg_PHY_ADR_CALVL_BG_2 0x0000011cU +#define _reg_PHY_ADR_CALVL_FG_3 0x0000011dU +#define _reg_PHY_ADR_CALVL_BG_3 0x0000011eU +#define _reg_PHY_ADR_ADDR_SEL 0x0000011fU +#define _reg_PHY_ADR_LP4_BOOT_SLV_DELAY 0x00000120U +#define _reg_PHY_ADR_BIT_MASK 0x00000121U +#define _reg_PHY_ADR_SEG_MASK 0x00000122U +#define _reg_PHY_ADR_CALVL_TRAIN_MASK 0x00000123U +#define _reg_PHY_ADR_CSLVL_TRAIN_MASK 0x00000124U +#define _reg_PHY_ADR_SW_TXIO_CTRL 0x00000125U +#define _reg_PHY_ADR_TSEL_SELECT 0x00000126U +#define _reg_PHY_ADR0_CLK_WR_SLAVE_DELAY 0x00000127U +#define _reg_PHY_ADR1_CLK_WR_SLAVE_DELAY 0x00000128U +#define _reg_PHY_ADR2_CLK_WR_SLAVE_DELAY 0x00000129U +#define _reg_PHY_ADR3_CLK_WR_SLAVE_DELAY 0x0000012aU +#define _reg_PHY_ADR4_CLK_WR_SLAVE_DELAY 0x0000012bU +#define _reg_PHY_ADR5_CLK_WR_SLAVE_DELAY 0x0000012cU +#define _reg_PHY_ADR_SW_MASTER_MODE 0x0000012dU +#define _reg_PHY_ADR_MASTER_DELAY_START 0x0000012eU +#define _reg_PHY_ADR_MASTER_DELAY_STEP 0x0000012fU +#define _reg_PHY_ADR_MASTER_DELAY_WAIT 0x00000130U +#define _reg_PHY_ADR_MASTER_DELAY_HALF_MEASURE 0x00000131U +#define _reg_PHY_ADR_CALVL_DLY_STEP 0x00000132U +#define _reg_PHY_FREQ_SEL 0x00000133U +#define _reg_PHY_FREQ_SEL_FROM_REGIF 0x00000134U +#define _reg_PHY_FREQ_SEL_MULTICAST_EN 0x00000135U +#define _reg_PHY_FREQ_SEL_INDEX 0x00000136U +#define _reg_PHY_SW_GRP_SHIFT_0 0x00000137U +#define _reg_PHY_SW_GRP_SHIFT_1 0x00000138U +#define _reg_PHY_SW_GRP_SHIFT_2 0x00000139U +#define _reg_PHY_SW_GRP_SHIFT_3 0x0000013aU +#define _reg_PHY_GRP_BYPASS_SLAVE_DELAY 0x0000013bU +#define _reg_PHY_SW_GRP_BYPASS_SHIFT 0x0000013cU +#define _reg_PHY_GRP_BYPASS_OVERRIDE 0x0000013dU +#define _reg_SC_PHY_MANUAL_UPDATE 0x0000013eU +#define _reg_SC_PHY_MANUAL_UPDATE_PHYUPD_ENABLE 0x0000013fU +#define _reg_PHY_LP4_BOOT_DISABLE 0x00000140U +#define _reg_PHY_CSLVL_ENABLE 0x00000141U +#define _reg_PHY_CSLVL_CS_MAP 0x00000142U +#define _reg_PHY_CSLVL_START 0x00000143U +#define _reg_PHY_CSLVL_QTR 0x00000144U +#define _reg_PHY_CSLVL_COARSE_CHK 0x00000145U +#define _reg_PHY_CSLVL_CAPTURE_CNT 0x00000146U +#define _reg_PHY_CSLVL_COARSE_DLY 0x00000147U +#define _reg_PHY_CSLVL_COARSE_CAPTURE_CNT 0x00000148U +#define _reg_PHY_CSLVL_DEBUG_MODE 0x00000149U +#define _reg_SC_PHY_CSLVL_DEBUG_CONT 0x0000014aU +#define _reg_SC_PHY_CSLVL_ERROR_CLR 0x0000014bU +#define _reg_PHY_CSLVL_OBS0 0x0000014cU +#define _reg_PHY_CSLVL_OBS1 0x0000014dU +#define _reg_PHY_CALVL_CS_MAP 0x0000014eU +#define _reg_PHY_GRP_SLV_DLY_ENC_OBS_SELECT 0x0000014fU +#define _reg_PHY_GRP_SHIFT_OBS_SELECT 0x00000150U +#define _reg_PHY_GRP_SLV_DLY_ENC_OBS 0x00000151U +#define _reg_PHY_GRP_SHIFT_OBS 0x00000152U +#define _reg_PHY_ADRCTL_SLAVE_LOOP_CNT_UPDATE 0x00000153U +#define _reg_PHY_ADRCTL_SNAP_OBS_REGS 0x00000154U +#define _reg_PHY_DFI_PHYUPD_TYPE 0x00000155U +#define _reg_PHY_ADRCTL_LPDDR 0x00000156U +#define _reg_PHY_LP4_ACTIVE 0x00000157U +#define _reg_PHY_LPDDR3_CS 0x00000158U +#define _reg_PHY_CALVL_RESULT_MASK 0x00000159U +#define _reg_SC_PHY_UPDATE_CLK_CAL_VALUES 0x0000015aU +#define _reg_PHY_SW_TXIO_CTRL_0 0x0000015bU +#define _reg_PHY_SW_TXIO_CTRL_1 0x0000015cU +#define _reg_PHY_SW_TXIO_CTRL_2 0x0000015dU +#define _reg_PHY_SW_TXIO_CTRL_3 0x0000015eU +#define _reg_PHY_MEMCLK_SW_TXIO_CTRL 0x0000015fU +#define _reg_PHY_CA_SW_TXPWR_CTRL 0x00000160U +#define _reg_PHY_MEMCLK_SW_TXPWR_CTRL 0x00000161U +#define _reg_PHY_USER_DEF_REG_AC_0 0x00000162U +#define _reg_PHY_USER_DEF_REG_AC_1 0x00000163U +#define _reg_PHY_USER_DEF_REG_AC_2 0x00000164U +#define _reg_PHY_USER_DEF_REG_AC_3 0x00000165U +#define _reg_PHY_UPDATE_CLK_CAL_VALUES 0x00000166U +#define _reg_PHY_CONTINUOUS_CLK_CAL_UPDATE 0x00000167U +#define _reg_PHY_PLL_CTRL 0x00000168U +#define _reg_PHY_PLL_CTRL_TOP 0x00000169U +#define _reg_PHY_PLL_CTRL_CA 0x0000016aU +#define _reg_PHY_PLL_BYPASS 0x0000016bU +#define _reg_PHY_LOW_FREQ_SEL 0x0000016cU +#define _reg_PHY_PAD_VREF_CTRL_DQ_0 0x0000016dU +#define _reg_PHY_PAD_VREF_CTRL_DQ_1 0x0000016eU +#define _reg_PHY_PAD_VREF_CTRL_DQ_2 0x0000016fU +#define _reg_PHY_PAD_VREF_CTRL_DQ_3 0x00000170U +#define _reg_PHY_PAD_VREF_CTRL_AC 0x00000171U +#define _reg_PHY_CSLVL_DLY_STEP 0x00000172U +#define _reg_PHY_SET_DFI_INPUT_0 0x00000173U +#define _reg_PHY_SET_DFI_INPUT_1 0x00000174U +#define _reg_PHY_SET_DFI_INPUT_2 0x00000175U +#define _reg_PHY_SET_DFI_INPUT_3 0x00000176U +#define _reg_PHY_GRP_SLAVE_DELAY_0 0x00000177U +#define _reg_PHY_GRP_SLAVE_DELAY_1 0x00000178U +#define _reg_PHY_GRP_SLAVE_DELAY_2 0x00000179U +#define _reg_PHY_GRP_SLAVE_DELAY_3 0x0000017aU +#define _reg_PHY_CS_ACS_ALLOCATION_0 0x0000017bU +#define _reg_PHY_CS_ACS_ALLOCATION_1 0x0000017cU +#define _reg_PHY_CS_ACS_ALLOCATION_2 0x0000017dU +#define _reg_PHY_CS_ACS_ALLOCATION_3 0x0000017eU +#define _reg_PHY_LP4_BOOT_PLL_CTRL 0x0000017fU +#define _reg_PHY_LP4_BOOT_PLL_CTRL_CA 0x00000180U +#define _reg_PHY_LP4_BOOT_TOP_PLL_CTRL 0x00000181U +#define _reg_PHY_PLL_CTRL_OVERRIDE 0x00000182U +#define _reg_PHY_PLL_WAIT 0x00000183U +#define _reg_PHY_PLL_WAIT_TOP 0x00000184U +#define _reg_PHY_PLL_OBS_0 0x00000185U +#define _reg_PHY_PLL_OBS_1 0x00000186U +#define _reg_PHY_PLL_OBS_2 0x00000187U +#define _reg_PHY_PLL_OBS_3 0x00000188U +#define _reg_PHY_PLL_OBS_4 0x00000189U +#define _reg_PHY_PLL_TESTOUT_SEL 0x0000018aU +#define _reg_PHY_TCKSRE_WAIT 0x0000018bU +#define _reg_PHY_LP4_BOOT_LOW_FREQ_SEL 0x0000018cU +#define _reg_PHY_LP_WAKEUP 0x0000018dU +#define _reg_PHY_LS_IDLE_EN 0x0000018eU +#define _reg_PHY_LP_CTRLUPD_CNTR_CFG 0x0000018fU +#define _reg_PHY_TDFI_PHY_WRDELAY 0x00000190U +#define _reg_PHY_PAD_FDBK_DRIVE 0x00000191U +#define _reg_PHY_PAD_DATA_DRIVE 0x00000192U +#define _reg_PHY_PAD_DQS_DRIVE 0x00000193U +#define _reg_PHY_PAD_ADDR_DRIVE 0x00000194U +#define _reg_PHY_PAD_CLK_DRIVE 0x00000195U +#define _reg_PHY_PAD_FDBK_TERM 0x00000196U +#define _reg_PHY_PAD_DATA_TERM 0x00000197U +#define _reg_PHY_PAD_DQS_TERM 0x00000198U +#define _reg_PHY_PAD_ADDR_TERM 0x00000199U +#define _reg_PHY_PAD_CLK_TERM 0x0000019aU +#define _reg_PHY_PAD_CKE_DRIVE 0x0000019bU +#define _reg_PHY_PAD_CKE_TERM 0x0000019cU +#define _reg_PHY_PAD_RST_DRIVE 0x0000019dU +#define _reg_PHY_PAD_RST_TERM 0x0000019eU +#define _reg_PHY_PAD_CS_DRIVE 0x0000019fU +#define _reg_PHY_PAD_CS_TERM 0x000001a0U +#define _reg_PHY_PAD_ODT_DRIVE 0x000001a1U +#define _reg_PHY_PAD_ODT_TERM 0x000001a2U +#define _reg_PHY_ADRCTL_RX_CAL 0x000001a3U +#define _reg_PHY_ADRCTL_LP3_RX_CAL 0x000001a4U +#define _reg_PHY_TST_CLK_PAD_CTRL 0x000001a5U +#define _reg_PHY_TST_CLK_PAD_CTRL2 0x000001a6U +#define _reg_PHY_CAL_MODE_0 0x000001a7U +#define _reg_PHY_CAL_CLEAR_0 0x000001a8U +#define _reg_PHY_CAL_START_0 0x000001a9U +#define _reg_PHY_CAL_INTERVAL_COUNT_0 0x000001aaU +#define _reg_PHY_CAL_SAMPLE_WAIT_0 0x000001abU +#define _reg_PHY_LP4_BOOT_CAL_CLK_SELECT_0 0x000001acU +#define _reg_PHY_CAL_CLK_SELECT_0 0x000001adU +#define _reg_PHY_CAL_RESULT_OBS_0 0x000001aeU +#define _reg_PHY_CAL_RESULT2_OBS_0 0x000001afU +#define _reg_PHY_CAL_CPTR_CNT_0 0x000001b0U +#define _reg_PHY_CAL_SETTLING_PRD_0 0x000001b1U +#define _reg_PHY_CAL_PU_FINE_ADJ_0 0x000001b2U +#define _reg_PHY_CAL_PD_FINE_ADJ_0 0x000001b3U +#define _reg_PHY_CAL_RCV_FINE_ADJ_0 0x000001b4U +#define _reg_PHY_CAL_DBG_CFG_0 0x000001b5U +#define _reg_SC_PHY_PAD_DBG_CONT_0 0x000001b6U +#define _reg_PHY_CAL_RESULT3_OBS_0 0x000001b7U +#define _reg_PHY_ADRCTL_PVT_MAP_0 0x000001b8U +#define _reg_PHY_CAL_SLOPE_ADJ_0 0x000001b9U +#define _reg_PHY_CAL_SLOPE_ADJ_PASS2_0 0x000001baU +#define _reg_PHY_CAL_TWO_PASS_CFG_0 0x000001bbU +#define _reg_PHY_CAL_SW_CAL_CFG_0 0x000001bcU +#define _reg_PHY_CAL_RANGE_MIN_0 0x000001bdU +#define _reg_PHY_CAL_RANGE_MAX_0 0x000001beU +#define _reg_PHY_PAD_ATB_CTRL 0x000001bfU +#define _reg_PHY_ADRCTL_MANUAL_UPDATE 0x000001c0U +#define _reg_PHY_AC_LPBK_ERR_CLEAR 0x000001c1U +#define _reg_PHY_AC_LPBK_OBS_SELECT 0x000001c2U +#define _reg_PHY_AC_LPBK_ENABLE 0x000001c3U +#define _reg_PHY_AC_LPBK_CONTROL 0x000001c4U +#define _reg_PHY_AC_PRBS_PATTERN_START 0x000001c5U +#define _reg_PHY_AC_PRBS_PATTERN_MASK 0x000001c6U +#define _reg_PHY_AC_LPBK_RESULT_OBS 0x000001c7U +#define _reg_PHY_AC_CLK_LPBK_OBS_SELECT 0x000001c8U +#define _reg_PHY_AC_CLK_LPBK_ENABLE 0x000001c9U +#define _reg_PHY_AC_CLK_LPBK_CONTROL 0x000001caU +#define _reg_PHY_AC_CLK_LPBK_RESULT_OBS 0x000001cbU +#define _reg_PHY_AC_PWR_RDC_DISABLE 0x000001ccU +#define _reg_PHY_DATA_BYTE_ORDER_SEL 0x000001cdU +#define _reg_PHY_DATA_BYTE_ORDER_SEL_HIGH 0x000001ceU +#define _reg_PHY_LPDDR4_CONNECT 0x000001cfU +#define _reg_PHY_CALVL_DEVICE_MAP 0x000001d0U +#define _reg_PHY_ADR_DISABLE 0x000001d1U +#define _reg_PHY_ADRCTL_MSTR_DLY_ENC_SEL 0x000001d2U +#define _reg_PHY_CS_DLY_UPT_PER_AC_SLICE 0x000001d3U +#define _reg_PHY_DDL_AC_ENABLE 0x000001d4U +#define _reg_PHY_DDL_AC_MODE 0x000001d5U +#define _reg_PHY_PAD_BACKGROUND_CAL 0x000001d6U +#define _reg_PHY_INIT_UPDATE_CONFIG 0x000001d7U +#define _reg_PHY_DDL_TRACK_UPD_THRESHOLD_AC 0x000001d8U +#define _reg_PHY_DLL_RST_EN 0x000001d9U +#define _reg_PHY_AC_INIT_COMPLETE_OBS 0x000001daU +#define _reg_PHY_DS_INIT_COMPLETE_OBS 0x000001dbU +#define _reg_PHY_UPDATE_MASK 0x000001dcU +#define _reg_PHY_PLL_SWITCH_CNT 0x000001ddU +#define _reg_PI_START 0x000001deU +#define _reg_PI_DRAM_CLASS 0x000001dfU +#define _reg_PI_VERSION 0x000001e0U +#define _reg_PI_NORMAL_LVL_SEQ 0x000001e1U +#define _reg_PI_INIT_LVL_EN 0x000001e2U +#define _reg_PI_NOTCARE_PHYUPD 0x000001e3U +#define _reg_PI_ONBUS_MBIST 0x000001e4U +#define _reg_PI_TCMD_GAP 0x000001e5U +#define _reg_PI_MASTER_ACK_DURATION_MIN 0x000001e6U +#define _reg_PI_DFI_VERSION 0x000001e7U +#define _reg_PI_TDFI_PHYMSTR_TYPE0 0x000001e8U +#define _reg_PI_TDFI_PHYMSTR_TYPE1 0x000001e9U +#define _reg_PI_TDFI_PHYMSTR_TYPE2 0x000001eaU +#define _reg_PI_TDFI_PHYMSTR_TYPE3 0x000001ebU +#define _reg_PI_DFI_PHYMSTR_TYPE 0x000001ecU +#define _reg_PI_DFI_PHYMSTR_CS_STATE_R 0x000001edU +#define _reg_PI_DFI_PHYMSTR_STATE_SEL_R 0x000001eeU +#define _reg_PI_TDFI_PHYMSTR_MAX_F0 0x000001efU +#define _reg_PI_TDFI_PHYMSTR_RESP_F0 0x000001f0U +#define _reg_PI_TDFI_PHYMSTR_MAX_F1 0x000001f1U +#define _reg_PI_TDFI_PHYMSTR_RESP_F1 0x000001f2U +#define _reg_PI_TDFI_PHYMSTR_MAX_F2 0x000001f3U +#define _reg_PI_TDFI_PHYMSTR_RESP_F2 0x000001f4U +#define _reg_PI_TDFI_PHYUPD_RESP_F0 0x000001f5U +#define _reg_PI_TDFI_PHYUPD_TYPE0_F0 0x000001f6U +#define _reg_PI_TDFI_PHYUPD_TYPE1_F0 0x000001f7U +#define _reg_PI_TDFI_PHYUPD_TYPE2_F0 0x000001f8U +#define _reg_PI_TDFI_PHYUPD_TYPE3_F0 0x000001f9U +#define _reg_PI_TDFI_PHYUPD_RESP_F1 0x000001faU +#define _reg_PI_TDFI_PHYUPD_TYPE0_F1 0x000001fbU +#define _reg_PI_TDFI_PHYUPD_TYPE1_F1 0x000001fcU +#define _reg_PI_TDFI_PHYUPD_TYPE2_F1 0x000001fdU +#define _reg_PI_TDFI_PHYUPD_TYPE3_F1 0x000001feU +#define _reg_PI_TDFI_PHYUPD_RESP_F2 0x000001ffU +#define _reg_PI_TDFI_PHYUPD_TYPE0_F2 0x00000200U +#define _reg_PI_TDFI_PHYUPD_TYPE1_F2 0x00000201U +#define _reg_PI_TDFI_PHYUPD_TYPE2_F2 0x00000202U +#define _reg_PI_TDFI_PHYUPD_TYPE3_F2 0x00000203U +#define _reg_PI_CONTROL_ERROR_STATUS 0x00000204U +#define _reg_PI_EXIT_AFTER_INIT_CALVL 0x00000205U +#define _reg_PI_FREQ_MAP 0x00000206U +#define _reg_PI_INIT_WORK_FREQ 0x00000207U +#define _reg_PI_INIT_DFS_CALVL_ONLY 0x00000208U +#define _reg_PI_POWER_ON_SEQ_BYPASS_ARRAY 0x00000209U +#define _reg_PI_POWER_ON_SEQ_END_ARRAY 0x0000020aU +#define _reg_PI_SEQ1_PAT 0x0000020bU +#define _reg_PI_SEQ1_PAT_MASK 0x0000020cU +#define _reg_PI_SEQ2_PAT 0x0000020dU +#define _reg_PI_SEQ2_PAT_MASK 0x0000020eU +#define _reg_PI_SEQ3_PAT 0x0000020fU +#define _reg_PI_SEQ3_PAT_MASK 0x00000210U +#define _reg_PI_SEQ4_PAT 0x00000211U +#define _reg_PI_SEQ4_PAT_MASK 0x00000212U +#define _reg_PI_SEQ5_PAT 0x00000213U +#define _reg_PI_SEQ5_PAT_MASK 0x00000214U +#define _reg_PI_SEQ6_PAT 0x00000215U +#define _reg_PI_SEQ6_PAT_MASK 0x00000216U +#define _reg_PI_SEQ7_PAT 0x00000217U +#define _reg_PI_SEQ7_PAT_MASK 0x00000218U +#define _reg_PI_SEQ8_PAT 0x00000219U +#define _reg_PI_SEQ8_PAT_MASK 0x0000021aU +#define _reg_PI_WDT_DISABLE 0x0000021bU +#define _reg_PI_SW_RST_N 0x0000021cU +#define _reg_RESERVED_R0 0x0000021dU +#define _reg_PI_CS_MAP 0x0000021eU +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F0 0x0000021fU +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F1 0x00000220U +#define _reg_PI_TDELAY_RDWR_2_BUS_IDLE_F2 0x00000221U +#define _reg_PI_TMRR 0x00000222U +#define _reg_PI_WRLAT_F0 0x00000223U +#define _reg_PI_ADDITIVE_LAT_F0 0x00000224U +#define _reg_PI_CASLAT_LIN_F0 0x00000225U +#define _reg_PI_WRLAT_F1 0x00000226U +#define _reg_PI_ADDITIVE_LAT_F1 0x00000227U +#define _reg_PI_CASLAT_LIN_F1 0x00000228U +#define _reg_PI_WRLAT_F2 0x00000229U +#define _reg_PI_ADDITIVE_LAT_F2 0x0000022aU +#define _reg_PI_CASLAT_LIN_F2 0x0000022bU +#define _reg_PI_PREAMBLE_SUPPORT 0x0000022cU +#define _reg_PI_AREFRESH 0x0000022dU +#define _reg_PI_MCAREF_FORWARD_ONLY 0x0000022eU +#define _reg_PI_TRFC_F0 0x0000022fU +#define _reg_PI_TREF_F0 0x00000230U +#define _reg_PI_TRFC_F1 0x00000231U +#define _reg_PI_TREF_F1 0x00000232U +#define _reg_PI_TRFC_F2 0x00000233U +#define _reg_PI_TREF_F2 0x00000234U +#define _reg_RESERVED_H3VER2 0x00000235U +#define _reg_PI_TREF_INTERVAL 0x00000236U +#define _reg_PI_FREQ_CHANGE_REG_COPY 0x00000237U +#define _reg_PI_FREQ_SEL_FROM_REGIF 0x00000238U +#define _reg_PI_SWLVL_LOAD 0x00000239U +#define _reg_PI_SWLVL_OP_DONE 0x0000023aU +#define _reg_PI_SW_WRLVL_RESP_0 0x0000023bU +#define _reg_PI_SW_WRLVL_RESP_1 0x0000023cU +#define _reg_PI_SW_WRLVL_RESP_2 0x0000023dU +#define _reg_PI_SW_WRLVL_RESP_3 0x0000023eU +#define _reg_PI_SW_RDLVL_RESP_0 0x0000023fU +#define _reg_PI_SW_RDLVL_RESP_1 0x00000240U +#define _reg_PI_SW_RDLVL_RESP_2 0x00000241U +#define _reg_PI_SW_RDLVL_RESP_3 0x00000242U +#define _reg_PI_SW_CALVL_RESP_0 0x00000243U +#define _reg_PI_SW_LEVELING_MODE 0x00000244U +#define _reg_PI_SWLVL_START 0x00000245U +#define _reg_PI_SWLVL_EXIT 0x00000246U +#define _reg_PI_SWLVL_WR_SLICE_0 0x00000247U +#define _reg_PI_SWLVL_RD_SLICE_0 0x00000248U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_0 0x00000249U +#define _reg_PI_SW_WDQLVL_RESP_0 0x0000024aU +#define _reg_PI_SWLVL_WR_SLICE_1 0x0000024bU +#define _reg_PI_SWLVL_RD_SLICE_1 0x0000024cU +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_1 0x0000024dU +#define _reg_PI_SW_WDQLVL_RESP_1 0x0000024eU +#define _reg_PI_SWLVL_WR_SLICE_2 0x0000024fU +#define _reg_PI_SWLVL_RD_SLICE_2 0x00000250U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_2 0x00000251U +#define _reg_PI_SW_WDQLVL_RESP_2 0x00000252U +#define _reg_PI_SWLVL_WR_SLICE_3 0x00000253U +#define _reg_PI_SWLVL_RD_SLICE_3 0x00000254U +#define _reg_PI_SWLVL_VREF_UPDATE_SLICE_3 0x00000255U +#define _reg_PI_SW_WDQLVL_RESP_3 0x00000256U +#define _reg_PI_SW_WDQLVL_VREF 0x00000257U +#define _reg_PI_SWLVL_SM2_START 0x00000258U +#define _reg_PI_SWLVL_SM2_WR 0x00000259U +#define _reg_PI_SWLVL_SM2_RD 0x0000025aU +#define _reg_PI_SEQUENTIAL_LVL_REQ 0x0000025bU +#define _reg_PI_DFS_PERIOD_EN 0x0000025cU +#define _reg_PI_SRE_PERIOD_EN 0x0000025dU +#define _reg_PI_DFI40_POLARITY 0x0000025eU +#define _reg_PI_16BIT_DRAM_CONNECT 0x0000025fU +#define _reg_PI_TDFI_CTRL_DELAY_F0 0x00000260U +#define _reg_PI_TDFI_CTRL_DELAY_F1 0x00000261U +#define _reg_PI_TDFI_CTRL_DELAY_F2 0x00000262U +#define _reg_PI_WRLVL_REQ 0x00000263U +#define _reg_PI_WRLVL_CS 0x00000264U +#define _reg_PI_WLDQSEN 0x00000265U +#define _reg_PI_WLMRD 0x00000266U +#define _reg_PI_WRLVL_EN_F0 0x00000267U +#define _reg_PI_WRLVL_EN_F1 0x00000268U +#define _reg_PI_WRLVL_EN_F2 0x00000269U +#define _reg_PI_WRLVL_EN 0x0000026aU +#define _reg_PI_WRLVL_INTERVAL 0x0000026bU +#define _reg_PI_WRLVL_PERIODIC 0x0000026cU +#define _reg_PI_WRLVL_ON_SREF_EXIT 0x0000026dU +#define _reg_PI_WRLVL_DISABLE_DFS 0x0000026eU +#define _reg_PI_WRLVL_RESP_MASK 0x0000026fU +#define _reg_PI_WRLVL_ROTATE 0x00000270U +#define _reg_PI_WRLVL_CS_MAP 0x00000271U +#define _reg_PI_WRLVL_ERROR_STATUS 0x00000272U +#define _reg_PI_TDFI_WRLVL_EN 0x00000273U +#define _reg_PI_TDFI_WRLVL_WW_F0 0x00000274U +#define _reg_PI_TDFI_WRLVL_WW_F1 0x00000275U +#define _reg_PI_TDFI_WRLVL_WW_F2 0x00000276U +#define _reg_PI_TDFI_WRLVL_WW 0x00000277U +#define _reg_PI_TDFI_WRLVL_RESP 0x00000278U +#define _reg_PI_TDFI_WRLVL_MAX 0x00000279U +#define _reg_PI_WRLVL_STROBE_NUM 0x0000027aU +#define _reg_PI_WRLVL_MRR_DQ_RETURN_HIZ 0x0000027bU +#define _reg_PI_WRLVL_EN_DEASSERT_2_MRR 0x0000027cU +#define _reg_PI_TODTL_2CMD_F0 0x0000027dU +#define _reg_PI_ODT_EN_F0 0x0000027eU +#define _reg_PI_TODTL_2CMD_F1 0x0000027fU +#define _reg_PI_ODT_EN_F1 0x00000280U +#define _reg_PI_TODTL_2CMD_F2 0x00000281U +#define _reg_PI_ODT_EN_F2 0x00000282U +#define _reg_PI_TODTH_WR 0x00000283U +#define _reg_PI_TODTH_RD 0x00000284U +#define _reg_PI_ODT_RD_MAP_CS0 0x00000285U +#define _reg_PI_ODT_WR_MAP_CS0 0x00000286U +#define _reg_PI_ODT_RD_MAP_CS1 0x00000287U +#define _reg_PI_ODT_WR_MAP_CS1 0x00000288U +#define _reg_PI_ODT_RD_MAP_CS2 0x00000289U +#define _reg_PI_ODT_WR_MAP_CS2 0x0000028aU +#define _reg_PI_ODT_RD_MAP_CS3 0x0000028bU +#define _reg_PI_ODT_WR_MAP_CS3 0x0000028cU +#define _reg_PI_EN_ODT_ASSERT_EXCEPT_RD 0x0000028dU +#define _reg_PI_ODTLON_F0 0x0000028eU +#define _reg_PI_TODTON_MIN_F0 0x0000028fU +#define _reg_PI_ODTLON_F1 0x00000290U +#define _reg_PI_TODTON_MIN_F1 0x00000291U +#define _reg_PI_ODTLON_F2 0x00000292U +#define _reg_PI_TODTON_MIN_F2 0x00000293U +#define _reg_PI_WR_TO_ODTH_F0 0x00000294U +#define _reg_PI_WR_TO_ODTH_F1 0x00000295U +#define _reg_PI_WR_TO_ODTH_F2 0x00000296U +#define _reg_PI_RD_TO_ODTH_F0 0x00000297U +#define _reg_PI_RD_TO_ODTH_F1 0x00000298U +#define _reg_PI_RD_TO_ODTH_F2 0x00000299U +#define _reg_PI_ADDRESS_MIRRORING 0x0000029aU +#define _reg_PI_RDLVL_REQ 0x0000029bU +#define _reg_PI_RDLVL_GATE_REQ 0x0000029cU +#define _reg_PI_RDLVL_CS 0x0000029dU +#define _reg_PI_RDLVL_PAT_0 0x0000029eU +#define _reg_PI_RDLVL_PAT_1 0x0000029fU +#define _reg_PI_RDLVL_PAT_2 0x000002a0U +#define _reg_PI_RDLVL_PAT_3 0x000002a1U +#define _reg_PI_RDLVL_PAT_4 0x000002a2U +#define _reg_PI_RDLVL_PAT_5 0x000002a3U +#define _reg_PI_RDLVL_PAT_6 0x000002a4U +#define _reg_PI_RDLVL_PAT_7 0x000002a5U +#define _reg_PI_RDLVL_SEQ_EN 0x000002a6U +#define _reg_PI_RDLVL_GATE_SEQ_EN 0x000002a7U +#define _reg_PI_RDLVL_PERIODIC 0x000002a8U +#define _reg_PI_RDLVL_ON_SREF_EXIT 0x000002a9U +#define _reg_PI_RDLVL_DISABLE_DFS 0x000002aaU +#define _reg_PI_RDLVL_GATE_PERIODIC 0x000002abU +#define _reg_PI_RDLVL_GATE_ON_SREF_EXIT 0x000002acU +#define _reg_PI_RDLVL_GATE_DISABLE_DFS 0x000002adU +#define _reg_RESERVED_R1 0x000002aeU +#define _reg_PI_RDLVL_ROTATE 0x000002afU +#define _reg_PI_RDLVL_GATE_ROTATE 0x000002b0U +#define _reg_PI_RDLVL_CS_MAP 0x000002b1U +#define _reg_PI_RDLVL_GATE_CS_MAP 0x000002b2U +#define _reg_PI_TDFI_RDLVL_RR 0x000002b3U +#define _reg_PI_TDFI_RDLVL_RESP 0x000002b4U +#define _reg_PI_RDLVL_RESP_MASK 0x000002b5U +#define _reg_PI_TDFI_RDLVL_EN 0x000002b6U +#define _reg_PI_RDLVL_EN_F0 0x000002b7U +#define _reg_PI_RDLVL_GATE_EN_F0 0x000002b8U +#define _reg_PI_RDLVL_EN_F1 0x000002b9U +#define _reg_PI_RDLVL_GATE_EN_F1 0x000002baU +#define _reg_PI_RDLVL_EN_F2 0x000002bbU +#define _reg_PI_RDLVL_GATE_EN_F2 0x000002bcU +#define _reg_PI_RDLVL_EN 0x000002bdU +#define _reg_PI_RDLVL_GATE_EN 0x000002beU +#define _reg_PI_TDFI_RDLVL_MAX 0x000002bfU +#define _reg_PI_RDLVL_ERROR_STATUS 0x000002c0U +#define _reg_PI_RDLVL_INTERVAL 0x000002c1U +#define _reg_PI_RDLVL_GATE_INTERVAL 0x000002c2U +#define _reg_PI_RDLVL_PATTERN_START 0x000002c3U +#define _reg_PI_RDLVL_PATTERN_NUM 0x000002c4U +#define _reg_PI_RDLVL_STROBE_NUM 0x000002c5U +#define _reg_PI_RDLVL_GATE_STROBE_NUM 0x000002c6U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_8 0x000002c7U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_9 0x000002c8U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_10 0x000002c9U +#define _reg_PI_LPDDR4_RDLVL_PATTERN_11 0x000002caU +#define _reg_PI_RD_PREAMBLE_TRAINING_EN 0x000002cbU +#define _reg_PI_REG_DIMM_ENABLE 0x000002ccU +#define _reg_PI_RDLAT_ADJ_F0 0x000002cdU +#define _reg_PI_RDLAT_ADJ_F1 0x000002ceU +#define _reg_PI_RDLAT_ADJ_F2 0x000002cfU +#define _reg_PI_TDFI_RDDATA_EN 0x000002d0U +#define _reg_PI_WRLAT_ADJ_F0 0x000002d1U +#define _reg_PI_WRLAT_ADJ_F1 0x000002d2U +#define _reg_PI_WRLAT_ADJ_F2 0x000002d3U +#define _reg_PI_TDFI_PHY_WRLAT 0x000002d4U +#define _reg_PI_TDFI_WRCSLAT_F0 0x000002d5U +#define _reg_PI_TDFI_WRCSLAT_F1 0x000002d6U +#define _reg_PI_TDFI_WRCSLAT_F2 0x000002d7U +#define _reg_PI_TDFI_RDCSLAT_F0 0x000002d8U +#define _reg_PI_TDFI_RDCSLAT_F1 0x000002d9U +#define _reg_PI_TDFI_RDCSLAT_F2 0x000002daU +#define _reg_PI_TDFI_PHY_WRDATA_F0 0x000002dbU +#define _reg_PI_TDFI_PHY_WRDATA_F1 0x000002dcU +#define _reg_PI_TDFI_PHY_WRDATA_F2 0x000002ddU +#define _reg_PI_TDFI_PHY_WRDATA 0x000002deU +#define _reg_PI_CALVL_REQ 0x000002dfU +#define _reg_PI_CALVL_CS 0x000002e0U +#define _reg_RESERVED_R2 0x000002e1U +#define _reg_RESERVED_R3 0x000002e2U +#define _reg_PI_CALVL_SEQ_EN 0x000002e3U +#define _reg_PI_CALVL_PERIODIC 0x000002e4U +#define _reg_PI_CALVL_ON_SREF_EXIT 0x000002e5U +#define _reg_PI_CALVL_DISABLE_DFS 0x000002e6U +#define _reg_PI_CALVL_ROTATE 0x000002e7U +#define _reg_PI_CALVL_CS_MAP 0x000002e8U +#define _reg_PI_TDFI_CALVL_EN 0x000002e9U +#define _reg_PI_TDFI_CALVL_CC_F0 0x000002eaU +#define _reg_PI_TDFI_CALVL_CAPTURE_F0 0x000002ebU +#define _reg_PI_TDFI_CALVL_CC_F1 0x000002ecU +#define _reg_PI_TDFI_CALVL_CAPTURE_F1 0x000002edU +#define _reg_PI_TDFI_CALVL_CC_F2 0x000002eeU +#define _reg_PI_TDFI_CALVL_CAPTURE_F2 0x000002efU +#define _reg_PI_TDFI_CALVL_RESP 0x000002f0U +#define _reg_PI_TDFI_CALVL_MAX 0x000002f1U +#define _reg_PI_CALVL_RESP_MASK 0x000002f2U +#define _reg_PI_CALVL_EN_F0 0x000002f3U +#define _reg_PI_CALVL_EN_F1 0x000002f4U +#define _reg_PI_CALVL_EN_F2 0x000002f5U +#define _reg_PI_CALVL_EN 0x000002f6U +#define _reg_PI_CALVL_ERROR_STATUS 0x000002f7U +#define _reg_PI_CALVL_INTERVAL 0x000002f8U +#define _reg_PI_TCACKEL 0x000002f9U +#define _reg_PI_TCAMRD 0x000002faU +#define _reg_PI_TCACKEH 0x000002fbU +#define _reg_PI_TMRZ_F0 0x000002fcU +#define _reg_PI_TCAENT_F0 0x000002fdU +#define _reg_PI_TMRZ_F1 0x000002feU +#define _reg_PI_TCAENT_F1 0x000002ffU +#define _reg_PI_TMRZ_F2 0x00000300U +#define _reg_PI_TCAENT_F2 0x00000301U +#define _reg_PI_TCAEXT 0x00000302U +#define _reg_PI_CA_TRAIN_VREF_EN 0x00000303U +#define _reg_PI_TDFI_CACSCA_F0 0x00000304U +#define _reg_PI_TDFI_CASEL_F0 0x00000305U +#define _reg_PI_TVREF_SHORT_F0 0x00000306U +#define _reg_PI_TVREF_LONG_F0 0x00000307U +#define _reg_PI_TDFI_CACSCA_F1 0x00000308U +#define _reg_PI_TDFI_CASEL_F1 0x00000309U +#define _reg_PI_TVREF_SHORT_F1 0x0000030aU +#define _reg_PI_TVREF_LONG_F1 0x0000030bU +#define _reg_PI_TDFI_CACSCA_F2 0x0000030cU +#define _reg_PI_TDFI_CASEL_F2 0x0000030dU +#define _reg_PI_TVREF_SHORT_F2 0x0000030eU +#define _reg_PI_TVREF_LONG_F2 0x0000030fU +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F0 0x00000310U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F0 0x00000311U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F1 0x00000312U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F1 0x00000313U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT_F2 0x00000314U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT_F2 0x00000315U +#define _reg_PI_CALVL_VREF_INITIAL_START_POINT 0x00000316U +#define _reg_PI_CALVL_VREF_INITIAL_STOP_POINT 0x00000317U +#define _reg_PI_CALVL_VREF_INITIAL_STEPSIZE 0x00000318U +#define _reg_PI_CALVL_VREF_NORMAL_STEPSIZE 0x00000319U +#define _reg_PI_CALVL_VREF_DELTA_F0 0x0000031aU +#define _reg_PI_CALVL_VREF_DELTA_F1 0x0000031bU +#define _reg_PI_CALVL_VREF_DELTA_F2 0x0000031cU +#define _reg_PI_CALVL_VREF_DELTA 0x0000031dU +#define _reg_PI_TDFI_INIT_START_MIN 0x0000031eU +#define _reg_PI_TDFI_INIT_COMPLETE_MIN 0x0000031fU +#define _reg_PI_TDFI_CALVL_STROBE_F0 0x00000320U +#define _reg_PI_TXP_F0 0x00000321U +#define _reg_PI_TMRWCKEL_F0 0x00000322U +#define _reg_PI_TCKELCK_F0 0x00000323U +#define _reg_PI_TDFI_CALVL_STROBE_F1 0x00000324U +#define _reg_PI_TXP_F1 0x00000325U +#define _reg_PI_TMRWCKEL_F1 0x00000326U +#define _reg_PI_TCKELCK_F1 0x00000327U +#define _reg_PI_TDFI_CALVL_STROBE_F2 0x00000328U +#define _reg_PI_TXP_F2 0x00000329U +#define _reg_PI_TMRWCKEL_F2 0x0000032aU +#define _reg_PI_TCKELCK_F2 0x0000032bU +#define _reg_PI_TCKCKEH 0x0000032cU +#define _reg_PI_CALVL_STROBE_NUM 0x0000032dU +#define _reg_PI_SW_CA_TRAIN_VREF 0x0000032eU +#define _reg_PI_TDFI_INIT_START_F0 0x0000032fU +#define _reg_PI_TDFI_INIT_COMPLETE_F0 0x00000330U +#define _reg_PI_TDFI_INIT_START_F1 0x00000331U +#define _reg_PI_TDFI_INIT_COMPLETE_F1 0x00000332U +#define _reg_PI_TDFI_INIT_START_F2 0x00000333U +#define _reg_PI_TDFI_INIT_COMPLETE_F2 0x00000334U +#define _reg_PI_CLKDISABLE_2_INIT_START 0x00000335U +#define _reg_PI_INIT_STARTORCOMPLETE_2_CLKDISABLE 0x00000336U +#define _reg_PI_DRAM_CLK_DISABLE_DEASSERT_SEL 0x00000337U +#define _reg_PI_REFRESH_BETWEEN_SEGMENT_DISABLE 0x00000338U +#define _reg_PI_TCKEHDQS_F0 0x00000339U +#define _reg_PI_TCKEHDQS_F1 0x0000033aU +#define _reg_PI_TCKEHDQS_F2 0x0000033bU +#define _reg_PI_MC_DFS_PI_SET_VREF_ENABLE 0x0000033cU +#define _reg_PI_WDQLVL_VREF_EN 0x0000033dU +#define _reg_PI_WDQLVL_BST_NUM 0x0000033eU +#define _reg_PI_TDFI_WDQLVL_WR_F0 0x0000033fU +#define _reg_PI_TDFI_WDQLVL_WR_F1 0x00000340U +#define _reg_PI_TDFI_WDQLVL_WR_F2 0x00000341U +#define _reg_PI_TDFI_WDQLVL_WR 0x00000342U +#define _reg_PI_TDFI_WDQLVL_RW 0x00000343U +#define _reg_PI_WDQLVL_RESP_MASK 0x00000344U +#define _reg_PI_WDQLVL_ROTATE 0x00000345U +#define _reg_PI_WDQLVL_CS_MAP 0x00000346U +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F0 0x00000347U +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F0 0x00000348U +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F1 0x00000349U +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F1 0x0000034aU +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT_F2 0x0000034bU +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT_F2 0x0000034cU +#define _reg_PI_WDQLVL_VREF_INITIAL_START_POINT 0x0000034dU +#define _reg_PI_WDQLVL_VREF_INITIAL_STOP_POINT 0x0000034eU +#define _reg_PI_WDQLVL_VREF_INITIAL_STEPSIZE 0x0000034fU +#define _reg_PI_WDQLVL_VREF_NORMAL_STEPSIZE 0x00000350U +#define _reg_PI_WDQLVL_VREF_DELTA_F0 0x00000351U +#define _reg_PI_WDQLVL_VREF_DELTA_F1 0x00000352U +#define _reg_PI_WDQLVL_VREF_DELTA_F2 0x00000353U +#define _reg_PI_WDQLVL_VREF_DELTA 0x00000354U +#define _reg_PI_WDQLVL_PERIODIC 0x00000355U +#define _reg_PI_WDQLVL_REQ 0x00000356U +#define _reg_PI_WDQLVL_CS 0x00000357U +#define _reg_PI_TDFI_WDQLVL_EN 0x00000358U +#define _reg_PI_TDFI_WDQLVL_RESP 0x00000359U +#define _reg_PI_TDFI_WDQLVL_MAX 0x0000035aU +#define _reg_PI_WDQLVL_INTERVAL 0x0000035bU +#define _reg_PI_WDQLVL_EN_F0 0x0000035cU +#define _reg_PI_WDQLVL_EN_F1 0x0000035dU +#define _reg_PI_WDQLVL_EN_F2 0x0000035eU +#define _reg_PI_WDQLVL_EN 0x0000035fU +#define _reg_PI_WDQLVL_ON_SREF_EXIT 0x00000360U +#define _reg_PI_WDQLVL_DISABLE_DFS 0x00000361U +#define _reg_PI_WDQLVL_ERROR_STATUS 0x00000362U +#define _reg_PI_MR1_DATA_F0_0 0x00000363U +#define _reg_PI_MR2_DATA_F0_0 0x00000364U +#define _reg_PI_MR3_DATA_F0_0 0x00000365U +#define _reg_PI_MR11_DATA_F0_0 0x00000366U +#define _reg_PI_MR12_DATA_F0_0 0x00000367U +#define _reg_PI_MR14_DATA_F0_0 0x00000368U +#define _reg_PI_MR22_DATA_F0_0 0x00000369U +#define _reg_PI_MR1_DATA_F1_0 0x0000036aU +#define _reg_PI_MR2_DATA_F1_0 0x0000036bU +#define _reg_PI_MR3_DATA_F1_0 0x0000036cU +#define _reg_PI_MR11_DATA_F1_0 0x0000036dU +#define _reg_PI_MR12_DATA_F1_0 0x0000036eU +#define _reg_PI_MR14_DATA_F1_0 0x0000036fU +#define _reg_PI_MR22_DATA_F1_0 0x00000370U +#define _reg_PI_MR1_DATA_F2_0 0x00000371U +#define _reg_PI_MR2_DATA_F2_0 0x00000372U +#define _reg_PI_MR3_DATA_F2_0 0x00000373U +#define _reg_PI_MR11_DATA_F2_0 0x00000374U +#define _reg_PI_MR12_DATA_F2_0 0x00000375U +#define _reg_PI_MR14_DATA_F2_0 0x00000376U +#define _reg_PI_MR22_DATA_F2_0 0x00000377U +#define _reg_PI_MR13_DATA_0 0x00000378U +#define _reg_PI_MR1_DATA_F0_1 0x00000379U +#define _reg_PI_MR2_DATA_F0_1 0x0000037aU +#define _reg_PI_MR3_DATA_F0_1 0x0000037bU +#define _reg_PI_MR11_DATA_F0_1 0x0000037cU +#define _reg_PI_MR12_DATA_F0_1 0x0000037dU +#define _reg_PI_MR14_DATA_F0_1 0x0000037eU +#define _reg_PI_MR22_DATA_F0_1 0x0000037fU +#define _reg_PI_MR1_DATA_F1_1 0x00000380U +#define _reg_PI_MR2_DATA_F1_1 0x00000381U +#define _reg_PI_MR3_DATA_F1_1 0x00000382U +#define _reg_PI_MR11_DATA_F1_1 0x00000383U +#define _reg_PI_MR12_DATA_F1_1 0x00000384U +#define _reg_PI_MR14_DATA_F1_1 0x00000385U +#define _reg_PI_MR22_DATA_F1_1 0x00000386U +#define _reg_PI_MR1_DATA_F2_1 0x00000387U +#define _reg_PI_MR2_DATA_F2_1 0x00000388U +#define _reg_PI_MR3_DATA_F2_1 0x00000389U +#define _reg_PI_MR11_DATA_F2_1 0x0000038aU +#define _reg_PI_MR12_DATA_F2_1 0x0000038bU +#define _reg_PI_MR14_DATA_F2_1 0x0000038cU +#define _reg_PI_MR22_DATA_F2_1 0x0000038dU +#define _reg_PI_MR13_DATA_1 0x0000038eU +#define _reg_PI_MR1_DATA_F0_2 0x0000038fU +#define _reg_PI_MR2_DATA_F0_2 0x00000390U +#define _reg_PI_MR3_DATA_F0_2 0x00000391U +#define _reg_PI_MR11_DATA_F0_2 0x00000392U +#define _reg_PI_MR12_DATA_F0_2 0x00000393U +#define _reg_PI_MR14_DATA_F0_2 0x00000394U +#define _reg_PI_MR22_DATA_F0_2 0x00000395U +#define _reg_PI_MR1_DATA_F1_2 0x00000396U +#define _reg_PI_MR2_DATA_F1_2 0x00000397U +#define _reg_PI_MR3_DATA_F1_2 0x00000398U +#define _reg_PI_MR11_DATA_F1_2 0x00000399U +#define _reg_PI_MR12_DATA_F1_2 0x0000039aU +#define _reg_PI_MR14_DATA_F1_2 0x0000039bU +#define _reg_PI_MR22_DATA_F1_2 0x0000039cU +#define _reg_PI_MR1_DATA_F2_2 0x0000039dU +#define _reg_PI_MR2_DATA_F2_2 0x0000039eU +#define _reg_PI_MR3_DATA_F2_2 0x0000039fU +#define _reg_PI_MR11_DATA_F2_2 0x000003a0U +#define _reg_PI_MR12_DATA_F2_2 0x000003a1U +#define _reg_PI_MR14_DATA_F2_2 0x000003a2U +#define _reg_PI_MR22_DATA_F2_2 0x000003a3U +#define _reg_PI_MR13_DATA_2 0x000003a4U +#define _reg_PI_MR1_DATA_F0_3 0x000003a5U +#define _reg_PI_MR2_DATA_F0_3 0x000003a6U +#define _reg_PI_MR3_DATA_F0_3 0x000003a7U +#define _reg_PI_MR11_DATA_F0_3 0x000003a8U +#define _reg_PI_MR12_DATA_F0_3 0x000003a9U +#define _reg_PI_MR14_DATA_F0_3 0x000003aaU +#define _reg_PI_MR22_DATA_F0_3 0x000003abU +#define _reg_PI_MR1_DATA_F1_3 0x000003acU +#define _reg_PI_MR2_DATA_F1_3 0x000003adU +#define _reg_PI_MR3_DATA_F1_3 0x000003aeU +#define _reg_PI_MR11_DATA_F1_3 0x000003afU +#define _reg_PI_MR12_DATA_F1_3 0x000003b0U +#define _reg_PI_MR14_DATA_F1_3 0x000003b1U +#define _reg_PI_MR22_DATA_F1_3 0x000003b2U +#define _reg_PI_MR1_DATA_F2_3 0x000003b3U +#define _reg_PI_MR2_DATA_F2_3 0x000003b4U +#define _reg_PI_MR3_DATA_F2_3 0x000003b5U +#define _reg_PI_MR11_DATA_F2_3 0x000003b6U +#define _reg_PI_MR12_DATA_F2_3 0x000003b7U +#define _reg_PI_MR14_DATA_F2_3 0x000003b8U +#define _reg_PI_MR22_DATA_F2_3 0x000003b9U +#define _reg_PI_MR13_DATA_3 0x000003baU +#define _reg_PI_BANK_DIFF 0x000003bbU +#define _reg_PI_ROW_DIFF 0x000003bcU +#define _reg_PI_TFC_F0 0x000003bdU +#define _reg_PI_TFC_F1 0x000003beU +#define _reg_PI_TFC_F2 0x000003bfU +#define _reg_PI_TCCD 0x000003c0U +#define _reg_PI_TRTP_F0 0x000003c1U +#define _reg_PI_TRP_F0 0x000003c2U +#define _reg_PI_TRCD_F0 0x000003c3U +#define _reg_PI_TWTR_F0 0x000003c4U +#define _reg_PI_TWR_F0 0x000003c5U +#define _reg_PI_TRAS_MAX_F0 0x000003c6U +#define _reg_PI_TRAS_MIN_F0 0x000003c7U +#define _reg_PI_TDQSCK_MAX_F0 0x000003c8U +#define _reg_PI_TCCDMW_F0 0x000003c9U +#define _reg_PI_TSR_F0 0x000003caU +#define _reg_PI_TMRD_F0 0x000003cbU +#define _reg_PI_TMRW_F0 0x000003ccU +#define _reg_PI_TMOD_F0 0x000003cdU +#define _reg_PI_TRTP_F1 0x000003ceU +#define _reg_PI_TRP_F1 0x000003cfU +#define _reg_PI_TRCD_F1 0x000003d0U +#define _reg_PI_TWTR_F1 0x000003d1U +#define _reg_PI_TWR_F1 0x000003d2U +#define _reg_PI_TRAS_MAX_F1 0x000003d3U +#define _reg_PI_TRAS_MIN_F1 0x000003d4U +#define _reg_PI_TDQSCK_MAX_F1 0x000003d5U +#define _reg_PI_TCCDMW_F1 0x000003d6U +#define _reg_PI_TSR_F1 0x000003d7U +#define _reg_PI_TMRD_F1 0x000003d8U +#define _reg_PI_TMRW_F1 0x000003d9U +#define _reg_PI_TMOD_F1 0x000003daU +#define _reg_PI_TRTP_F2 0x000003dbU +#define _reg_PI_TRP_F2 0x000003dcU +#define _reg_PI_TRCD_F2 0x000003ddU +#define _reg_PI_TWTR_F2 0x000003deU +#define _reg_PI_TWR_F2 0x000003dfU +#define _reg_PI_TRAS_MAX_F2 0x000003e0U +#define _reg_PI_TRAS_MIN_F2 0x000003e1U +#define _reg_PI_TDQSCK_MAX_F2 0x000003e2U +#define _reg_PI_TCCDMW_F2 0x000003e3U +#define _reg_PI_TSR_F2 0x000003e4U +#define _reg_PI_TMRD_F2 0x000003e5U +#define _reg_PI_TMRW_F2 0x000003e6U +#define _reg_PI_TMOD_F2 0x000003e7U +#define _reg_RESERVED_R4 0x000003e8U +#define _reg_RESERVED_R5 0x000003e9U +#define _reg_RESERVED_R6 0x000003eaU +#define _reg_RESERVED_R7 0x000003ebU +#define _reg_RESERVED_R8 0x000003ecU +#define _reg_RESERVED_R9 0x000003edU +#define _reg_RESERVED_R10 0x000003eeU +#define _reg_RESERVED_R11 0x000003efU +#define _reg_RESERVED_R12 0x000003f0U +#define _reg_RESERVED_R13 0x000003f1U +#define _reg_RESERVED_R14 0x000003f2U +#define _reg_RESERVED_R15 0x000003f3U +#define _reg_RESERVED_R16 0x000003f4U +#define _reg_RESERVED_R17 0x000003f5U +#define _reg_RESERVED_R18 0x000003f6U +#define _reg_RESERVED_R19 0x000003f7U +#define _reg_RESERVED_R20 0x000003f8U +#define _reg_RESERVED_R21 0x000003f9U +#define _reg_RESERVED_R22 0x000003faU +#define _reg_RESERVED_R23 0x000003fbU +#define _reg_PI_INT_STATUS 0x000003fcU +#define _reg_PI_INT_ACK 0x000003fdU +#define _reg_PI_INT_MASK 0x000003feU +#define _reg_PI_BIST_EXP_DATA_P0 0x000003ffU +#define _reg_PI_BIST_EXP_DATA_P1 0x00000400U +#define _reg_PI_BIST_EXP_DATA_P2 0x00000401U +#define _reg_PI_BIST_EXP_DATA_P3 0x00000402U +#define _reg_PI_BIST_FAIL_DATA_P0 0x00000403U +#define _reg_PI_BIST_FAIL_DATA_P1 0x00000404U +#define _reg_PI_BIST_FAIL_DATA_P2 0x00000405U +#define _reg_PI_BIST_FAIL_DATA_P3 0x00000406U +#define _reg_PI_BIST_FAIL_ADDR_P0 0x00000407U +#define _reg_PI_BIST_FAIL_ADDR_P1 0x00000408U +#define _reg_PI_BSTLEN 0x00000409U +#define _reg_PI_LONG_COUNT_MASK 0x0000040aU +#define _reg_PI_CMD_SWAP_EN 0x0000040bU +#define _reg_PI_CKE_MUX_0 0x0000040cU +#define _reg_PI_CKE_MUX_1 0x0000040dU +#define _reg_PI_CKE_MUX_2 0x0000040eU +#define _reg_PI_CKE_MUX_3 0x0000040fU +#define _reg_PI_CS_MUX_0 0x00000410U +#define _reg_PI_CS_MUX_1 0x00000411U +#define _reg_PI_CS_MUX_2 0x00000412U +#define _reg_PI_CS_MUX_3 0x00000413U +#define _reg_PI_RAS_N_MUX 0x00000414U +#define _reg_PI_CAS_N_MUX 0x00000415U +#define _reg_PI_WE_N_MUX 0x00000416U +#define _reg_PI_BANK_MUX_0 0x00000417U +#define _reg_PI_BANK_MUX_1 0x00000418U +#define _reg_PI_BANK_MUX_2 0x00000419U +#define _reg_PI_ODT_MUX_0 0x0000041aU +#define _reg_PI_ODT_MUX_1 0x0000041bU +#define _reg_PI_ODT_MUX_2 0x0000041cU +#define _reg_PI_ODT_MUX_3 0x0000041dU +#define _reg_PI_RESET_N_MUX_0 0x0000041eU +#define _reg_PI_RESET_N_MUX_1 0x0000041fU +#define _reg_PI_RESET_N_MUX_2 0x00000420U +#define _reg_PI_RESET_N_MUX_3 0x00000421U +#define _reg_PI_DATA_BYTE_SWAP_EN 0x00000422U +#define _reg_PI_DATA_BYTE_SWAP_SLICE0 0x00000423U +#define _reg_PI_DATA_BYTE_SWAP_SLICE1 0x00000424U +#define _reg_PI_DATA_BYTE_SWAP_SLICE2 0x00000425U +#define _reg_PI_DATA_BYTE_SWAP_SLICE3 0x00000426U +#define _reg_PI_CTRLUPD_REQ_PER_AREF_EN 0x00000427U +#define _reg_PI_TDFI_CTRLUPD_MIN 0x00000428U +#define _reg_PI_TDFI_CTRLUPD_MAX_F0 0x00000429U +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F0 0x0000042aU +#define _reg_PI_TDFI_CTRLUPD_MAX_F1 0x0000042bU +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F1 0x0000042cU +#define _reg_PI_TDFI_CTRLUPD_MAX_F2 0x0000042dU +#define _reg_PI_TDFI_CTRLUPD_INTERVAL_F2 0x0000042eU +#define _reg_PI_UPDATE_ERROR_STATUS 0x0000042fU +#define _reg_PI_BIST_GO 0x00000430U +#define _reg_PI_BIST_RESULT 0x00000431U +#define _reg_PI_ADDR_SPACE 0x00000432U +#define _reg_PI_BIST_DATA_CHECK 0x00000433U +#define _reg_PI_BIST_ADDR_CHECK 0x00000434U +#define _reg_PI_BIST_START_ADDRESS_P0 0x00000435U +#define _reg_PI_BIST_START_ADDRESS_P1 0x00000436U +#define _reg_PI_BIST_DATA_MASK_P0 0x00000437U +#define _reg_PI_BIST_DATA_MASK_P1 0x00000438U +#define _reg_PI_BIST_ERR_COUNT 0x00000439U +#define _reg_PI_BIST_ERR_STOP 0x0000043aU +#define _reg_PI_BIST_ADDR_MASK_0_P0 0x0000043bU +#define _reg_PI_BIST_ADDR_MASK_0_P1 0x0000043cU +#define _reg_PI_BIST_ADDR_MASK_1_P0 0x0000043dU +#define _reg_PI_BIST_ADDR_MASK_1_P1 0x0000043eU +#define _reg_PI_BIST_ADDR_MASK_2_P0 0x0000043fU +#define _reg_PI_BIST_ADDR_MASK_2_P1 0x00000440U +#define _reg_PI_BIST_ADDR_MASK_3_P0 0x00000441U +#define _reg_PI_BIST_ADDR_MASK_3_P1 0x00000442U +#define _reg_PI_BIST_ADDR_MASK_4_P0 0x00000443U +#define _reg_PI_BIST_ADDR_MASK_4_P1 0x00000444U +#define _reg_PI_BIST_ADDR_MASK_5_P0 0x00000445U +#define _reg_PI_BIST_ADDR_MASK_5_P1 0x00000446U +#define _reg_PI_BIST_ADDR_MASK_6_P0 0x00000447U +#define _reg_PI_BIST_ADDR_MASK_6_P1 0x00000448U +#define _reg_PI_BIST_ADDR_MASK_7_P0 0x00000449U +#define _reg_PI_BIST_ADDR_MASK_7_P1 0x0000044aU +#define _reg_PI_BIST_ADDR_MASK_8_P0 0x0000044bU +#define _reg_PI_BIST_ADDR_MASK_8_P1 0x0000044cU +#define _reg_PI_BIST_ADDR_MASK_9_P0 0x0000044dU +#define _reg_PI_BIST_ADDR_MASK_9_P1 0x0000044eU +#define _reg_PI_BIST_MODE 0x0000044fU +#define _reg_PI_BIST_ADDR_MODE 0x00000450U +#define _reg_PI_BIST_PAT_MODE 0x00000451U +#define _reg_PI_BIST_USER_PAT_P0 0x00000452U +#define _reg_PI_BIST_USER_PAT_P1 0x00000453U +#define _reg_PI_BIST_USER_PAT_P2 0x00000454U +#define _reg_PI_BIST_USER_PAT_P3 0x00000455U +#define _reg_PI_BIST_PAT_NUM 0x00000456U +#define _reg_PI_BIST_STAGE_0 0x00000457U +#define _reg_PI_BIST_STAGE_1 0x00000458U +#define _reg_PI_BIST_STAGE_2 0x00000459U +#define _reg_PI_BIST_STAGE_3 0x0000045aU +#define _reg_PI_BIST_STAGE_4 0x0000045bU +#define _reg_PI_BIST_STAGE_5 0x0000045cU +#define _reg_PI_BIST_STAGE_6 0x0000045dU +#define _reg_PI_BIST_STAGE_7 0x0000045eU +#define _reg_PI_COL_DIFF 0x0000045fU +#define _reg_PI_SELF_REFRESH_EN 0x00000460U +#define _reg_PI_TXSR_F0 0x00000461U +#define _reg_PI_TXSR_F1 0x00000462U +#define _reg_PI_TXSR_F2 0x00000463U +#define _reg_PI_MONITOR_SRC_SEL_0 0x00000464U +#define _reg_PI_MONITOR_CAP_SEL_0 0x00000465U +#define _reg_PI_MONITOR_0 0x00000466U +#define _reg_PI_MONITOR_SRC_SEL_1 0x00000467U +#define _reg_PI_MONITOR_CAP_SEL_1 0x00000468U +#define _reg_PI_MONITOR_1 0x00000469U +#define _reg_PI_MONITOR_SRC_SEL_2 0x0000046aU +#define _reg_PI_MONITOR_CAP_SEL_2 0x0000046bU +#define _reg_PI_MONITOR_2 0x0000046cU +#define _reg_PI_MONITOR_SRC_SEL_3 0x0000046dU +#define _reg_PI_MONITOR_CAP_SEL_3 0x0000046eU +#define _reg_PI_MONITOR_3 0x0000046fU +#define _reg_PI_MONITOR_SRC_SEL_4 0x00000470U +#define _reg_PI_MONITOR_CAP_SEL_4 0x00000471U +#define _reg_PI_MONITOR_4 0x00000472U +#define _reg_PI_MONITOR_SRC_SEL_5 0x00000473U +#define _reg_PI_MONITOR_CAP_SEL_5 0x00000474U +#define _reg_PI_MONITOR_5 0x00000475U +#define _reg_PI_MONITOR_SRC_SEL_6 0x00000476U +#define _reg_PI_MONITOR_CAP_SEL_6 0x00000477U +#define _reg_PI_MONITOR_6 0x00000478U +#define _reg_PI_MONITOR_SRC_SEL_7 0x00000479U +#define _reg_PI_MONITOR_CAP_SEL_7 0x0000047aU +#define _reg_PI_MONITOR_7 0x0000047bU +#define _reg_PI_MONITOR_STROBE 0x0000047cU +#define _reg_PI_DLL_LOCK 0x0000047dU +#define _reg_PI_FREQ_NUMBER_STATUS 0x0000047eU +#define _reg_RESERVED_R24 0x0000047fU +#define _reg_PI_PHYMSTR_TYPE 0x00000480U +#define _reg_PI_POWER_REDUC_EN 0x00000481U +#define _reg_RESERVED_R25 0x00000482U +#define _reg_RESERVED_R26 0x00000483U +#define _reg_RESERVED_R27 0x00000484U +#define _reg_RESERVED_R28 0x00000485U +#define _reg_RESERVED_R29 0x00000486U +#define _reg_RESERVED_R30 0x00000487U +#define _reg_RESERVED_R31 0x00000488U +#define _reg_RESERVED_R32 0x00000489U +#define _reg_RESERVED_R33 0x0000048aU +#define _reg_RESERVED_R34 0x0000048bU +#define _reg_RESERVED_R35 0x0000048cU +#define _reg_RESERVED_R36 0x0000048dU +#define _reg_RESERVED_R37 0x0000048eU +#define _reg_RESERVED_R38 0x0000048fU +#define _reg_RESERVED_R39 0x00000490U +#define _reg_PI_WRLVL_MAX_STROBE_PEND 0x00000491U +#define _reg_PI_TSDO_F0 0x00000492U +#define _reg_PI_TSDO_F1 0x00000493U +#define _reg_PI_TSDO_F2 0x00000494U + +#define DDR_REGDEF_ADR(regdef) ((regdef) & 0xffff) +#define DDR_REGDEF_LEN(regdef) (((regdef) >> 16) & 0xff) +#define DDR_REGDEF_LSB(regdef) (((regdef) >> 24) & 0xff) + +static const uint32_t DDR_REGDEF_TBL[4][1173] = { + { +/*0000*/ 0xffffffffU, +/*0001*/ 0xffffffffU, +/*0002*/ 0x000b0400U, +/*0003*/ 0xffffffffU, +/*0004*/ 0xffffffffU, +/*0005*/ 0x10010400U, +/*0006*/ 0x18050400U, +/*0007*/ 0x00050401U, +/*0008*/ 0x08050401U, +/*0009*/ 0x10050401U, +/*000a*/ 0x18050401U, +/*000b*/ 0x00050402U, +/*000c*/ 0x08050402U, +/*000d*/ 0x10050402U, +/*000e*/ 0x18050402U, +/*000f*/ 0x00040403U, +/*0010*/ 0x08030403U, +/*0011*/ 0x00180404U, +/*0012*/ 0x18030404U, +/*0013*/ 0x00180405U, +/*0014*/ 0x18020405U, +/*0015*/ 0x00010406U, +/*0016*/ 0x08020406U, +/*0017*/ 0x10010406U, +/*0018*/ 0x18010406U, +/*0019*/ 0x00020407U, +/*001a*/ 0x08040407U, +/*001b*/ 0x10040407U, +/*001c*/ 0x18040407U, +/*001d*/ 0x000a0408U, +/*001e*/ 0x10040408U, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x18070408U, +/*0022*/ 0xffffffffU, +/*0023*/ 0xffffffffU, +/*0024*/ 0xffffffffU, +/*0025*/ 0xffffffffU, +/*0026*/ 0xffffffffU, +/*0027*/ 0xffffffffU, +/*0028*/ 0x000a0409U, +/*0029*/ 0x10040409U, +/*002a*/ 0x18010409U, +/*002b*/ 0x0001040aU, +/*002c*/ 0x0802040aU, +/*002d*/ 0x1009040aU, +/*002e*/ 0x0009040bU, +/*002f*/ 0x1002040bU, +/*0030*/ 0x0020040cU, +/*0031*/ 0xffffffffU, +/*0032*/ 0x0001040dU, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x0020040eU, +/*0038*/ 0x0020040fU, +/*0039*/ 0x00200410U, +/*003a*/ 0x00200411U, +/*003b*/ 0x00030412U, +/*003c*/ 0x08010412U, +/*003d*/ 0x10030412U, +/*003e*/ 0x18030412U, +/*003f*/ 0x00040413U, +/*0040*/ 0x08040413U, +/*0041*/ 0x10040413U, +/*0042*/ 0x18040413U, +/*0043*/ 0x00010414U, +/*0044*/ 0x08010414U, +/*0045*/ 0x10060414U, +/*0046*/ 0x18040414U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x00060415U, +/*0049*/ 0x08040415U, +/*004a*/ 0x10060415U, +/*004b*/ 0x18040415U, +/*004c*/ 0x00020416U, +/*004d*/ 0x08050416U, +/*004e*/ 0x10080416U, +/*004f*/ 0x00200417U, +/*0050*/ 0x00060418U, +/*0051*/ 0x08030418U, +/*0052*/ 0x100b0418U, +/*0053*/ 0x00040419U, +/*0054*/ 0x08040419U, +/*0055*/ 0x10040419U, +/*0056*/ 0xffffffffU, +/*0057*/ 0x18010419U, +/*0058*/ 0x0009041aU, +/*0059*/ 0x0020041bU, +/*005a*/ 0x0020041cU, +/*005b*/ 0x0020041dU, +/*005c*/ 0x0020041eU, +/*005d*/ 0x0010041fU, +/*005e*/ 0x00200420U, +/*005f*/ 0x00010421U, +/*0060*/ 0x08060421U, +/*0061*/ 0x10080421U, +/*0062*/ 0x00200422U, +/*0063*/ 0xffffffffU, +/*0064*/ 0x000a0423U, +/*0065*/ 0x10060423U, +/*0066*/ 0x18070423U, +/*0067*/ 0x00080424U, +/*0068*/ 0x08080424U, +/*0069*/ 0x100a0424U, +/*006a*/ 0x00070425U, +/*006b*/ 0x08080425U, +/*006c*/ 0x10080425U, +/*006d*/ 0x18030425U, +/*006e*/ 0x000a0426U, +/*006f*/ 0x100a0426U, +/*0070*/ 0x00110427U, +/*0071*/ 0x00090428U, +/*0072*/ 0x10090428U, +/*0073*/ 0x00100429U, +/*0074*/ 0x100e0429U, +/*0075*/ 0x000e042aU, +/*0076*/ 0x100c042aU, +/*0077*/ 0x000a042bU, +/*0078*/ 0x100a042bU, +/*0079*/ 0x0002042cU, +/*007a*/ 0x0020042dU, +/*007b*/ 0x000b042eU, +/*007c*/ 0x100b042eU, +/*007d*/ 0x0020042fU, +/*007e*/ 0x00120430U, +/*007f*/ 0x00200431U, +/*0080*/ 0x00200432U, +/*0081*/ 0xffffffffU, +/*0082*/ 0xffffffffU, +/*0083*/ 0x00010433U, +/*0084*/ 0x08010433U, +/*0085*/ 0x10080433U, +/*0086*/ 0x000c0434U, +/*0087*/ 0x100c0434U, +/*0088*/ 0x000c0435U, +/*0089*/ 0x100c0435U, +/*008a*/ 0x000c0436U, +/*008b*/ 0x100c0436U, +/*008c*/ 0x000c0437U, +/*008d*/ 0x100c0437U, +/*008e*/ 0x000c0438U, +/*008f*/ 0x100c0438U, +/*0090*/ 0x000c0439U, +/*0091*/ 0x100b0439U, +/*0092*/ 0xffffffffU, +/*0093*/ 0xffffffffU, +/*0094*/ 0x000b043aU, +/*0095*/ 0x100b043aU, +/*0096*/ 0x000b043bU, +/*0097*/ 0x100b043bU, +/*0098*/ 0x000b043cU, +/*0099*/ 0x100b043cU, +/*009a*/ 0x000b043dU, +/*009b*/ 0x100b043dU, +/*009c*/ 0x000b043eU, +/*009d*/ 0x100a043eU, +/*009e*/ 0xffffffffU, +/*009f*/ 0x000a043fU, +/*00a0*/ 0x100a043fU, +/*00a1*/ 0x000a0440U, +/*00a2*/ 0x100a0440U, +/*00a3*/ 0x000a0441U, +/*00a4*/ 0x100a0441U, +/*00a5*/ 0x000a0442U, +/*00a6*/ 0x100a0442U, +/*00a7*/ 0xffffffffU, +/*00a8*/ 0x000a0443U, +/*00a9*/ 0x100a0443U, +/*00aa*/ 0x000a0444U, +/*00ab*/ 0x100a0444U, +/*00ac*/ 0x000a0445U, +/*00ad*/ 0x100a0445U, +/*00ae*/ 0x000a0446U, +/*00af*/ 0x100a0446U, +/*00b0*/ 0x000a0447U, +/*00b1*/ 0x100a0447U, +/*00b2*/ 0x000a0448U, +/*00b3*/ 0x100a0448U, +/*00b4*/ 0x000a0449U, +/*00b5*/ 0x100a0449U, +/*00b6*/ 0x000a044aU, +/*00b7*/ 0x100a044aU, +/*00b8*/ 0x000a044bU, +/*00b9*/ 0x100a044bU, +/*00ba*/ 0x000a044cU, +/*00bb*/ 0x1004044cU, +/*00bc*/ 0x1803044cU, +/*00bd*/ 0x000a044dU, +/*00be*/ 0x100a044dU, +/*00bf*/ 0x0001044eU, +/*00c0*/ 0x080a044eU, +/*00c1*/ 0x1804044eU, +/*00c2*/ 0x000b044fU, +/*00c3*/ 0x100a044fU, +/*00c4*/ 0xffffffffU, +/*00c5*/ 0x00080450U, +/*00c6*/ 0x08080450U, +/*00c7*/ 0x10080450U, +/*00c8*/ 0x18080450U, +/*00c9*/ 0x00080451U, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x08080451U, +/*00cc*/ 0x10010451U, +/*00cd*/ 0x18080451U, +/*00ce*/ 0x00080452U, +/*00cf*/ 0x08020452U, +/*00d0*/ 0x10020452U, +/*00d1*/ 0x18040452U, +/*00d2*/ 0x00040453U, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x08040453U, +/*00d5*/ 0x100a0453U, +/*00d6*/ 0x00060454U, +/*00d7*/ 0x08080454U, +/*00d8*/ 0xffffffffU, +/*00d9*/ 0x10040454U, +/*00da*/ 0x18040454U, +/*00db*/ 0x00050455U, +/*00dc*/ 0x08040455U, +/*00dd*/ 0x10050455U, +/*00de*/ 0x000a0456U, +/*00df*/ 0x100a0456U, +/*00e0*/ 0x00080457U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040457U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050600U, +/*00e6*/ 0x08050600U, +/*00e7*/ 0x10050600U, +/*00e8*/ 0x18050600U, +/*00e9*/ 0x00050601U, +/*00ea*/ 0x08050601U, +/*00eb*/ 0x100b0601U, +/*00ec*/ 0x00010602U, +/*00ed*/ 0x08030602U, +/*00ee*/ 0x00200603U, +/*00ef*/ 0xffffffffU, +/*00f0*/ 0x00030604U, +/*00f1*/ 0x080a0604U, +/*00f2*/ 0xffffffffU, +/*00f3*/ 0xffffffffU, +/*00f4*/ 0x18030604U, +/*00f5*/ 0x00030605U, +/*00f6*/ 0x08010605U, +/*00f7*/ 0x10010605U, +/*00f8*/ 0x18060605U, +/*00f9*/ 0xffffffffU, +/*00fa*/ 0xffffffffU, +/*00fb*/ 0xffffffffU, +/*00fc*/ 0x00020606U, +/*00fd*/ 0x08030606U, +/*00fe*/ 0x10010606U, +/*00ff*/ 0x000f0607U, +/*0100*/ 0x00200608U, +/*0101*/ 0x00200609U, +/*0102*/ 0x000b060aU, +/*0103*/ 0x100b060aU, +/*0104*/ 0x000b060bU, +/*0105*/ 0xffffffffU, +/*0106*/ 0xffffffffU, +/*0107*/ 0x0018060cU, +/*0108*/ 0x0018060dU, +/*0109*/ 0x0018060eU, +/*010a*/ 0x0018060fU, +/*010b*/ 0x1804060fU, +/*010c*/ 0x00050610U, +/*010d*/ 0x08020610U, +/*010e*/ 0x10040610U, +/*010f*/ 0x18040610U, +/*0110*/ 0x00010611U, +/*0111*/ 0x08010611U, +/*0112*/ 0x10010611U, +/*0113*/ 0x18030611U, +/*0114*/ 0x00200612U, +/*0115*/ 0x00200613U, +/*0116*/ 0x00010614U, +/*0117*/ 0x08140614U, +/*0118*/ 0x00140615U, +/*0119*/ 0x00140616U, +/*011a*/ 0x00140617U, +/*011b*/ 0x00140618U, +/*011c*/ 0x00140619U, +/*011d*/ 0x0014061aU, +/*011e*/ 0x0014061bU, +/*011f*/ 0x0018061cU, +/*0120*/ 0x000a061dU, +/*0121*/ 0x1006061dU, +/*0122*/ 0x1806061dU, +/*0123*/ 0x0006061eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0xffffffffU, +/*0126*/ 0x0008061fU, +/*0127*/ 0x080b061fU, +/*0128*/ 0x000b0620U, +/*0129*/ 0x100b0620U, +/*012a*/ 0x000b0621U, +/*012b*/ 0x100b0621U, +/*012c*/ 0x000b0622U, +/*012d*/ 0x10040622U, +/*012e*/ 0x000a0623U, +/*012f*/ 0x10060623U, +/*0130*/ 0x18080623U, +/*0131*/ 0xffffffffU, +/*0132*/ 0x00040624U, +/*0133*/ 0xffffffffU, +/*0134*/ 0xffffffffU, +/*0135*/ 0x00010700U, +/*0136*/ 0x08020700U, +/*0137*/ 0x10050700U, +/*0138*/ 0x18050700U, +/*0139*/ 0x00050701U, +/*013a*/ 0x08050701U, +/*013b*/ 0x100b0701U, +/*013c*/ 0x00050702U, +/*013d*/ 0x08010702U, +/*013e*/ 0x10010702U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x18010702U, +/*0141*/ 0x00010703U, +/*0142*/ 0x08040703U, +/*0143*/ 0x100b0703U, +/*0144*/ 0x000b0704U, +/*0145*/ 0xffffffffU, +/*0146*/ 0x10040704U, +/*0147*/ 0x000b0705U, +/*0148*/ 0x10040705U, +/*0149*/ 0x18010705U, +/*014a*/ 0x00010706U, +/*014b*/ 0x08010706U, +/*014c*/ 0x00200707U, +/*014d*/ 0x00200708U, +/*014e*/ 0x00080709U, +/*014f*/ 0x080a0709U, +/*0150*/ 0x18050709U, +/*0151*/ 0x000a070aU, +/*0152*/ 0x1003070aU, +/*0153*/ 0x1803070aU, +/*0154*/ 0x0001070bU, +/*0155*/ 0x0802070bU, +/*0156*/ 0x1001070bU, +/*0157*/ 0x1801070bU, +/*0158*/ 0x0001070cU, +/*0159*/ 0x0802070cU, +/*015a*/ 0xffffffffU, +/*015b*/ 0xffffffffU, +/*015c*/ 0xffffffffU, +/*015d*/ 0xffffffffU, +/*015e*/ 0xffffffffU, +/*015f*/ 0xffffffffU, +/*0160*/ 0xffffffffU, +/*0161*/ 0xffffffffU, +/*0162*/ 0xffffffffU, +/*0163*/ 0xffffffffU, +/*0164*/ 0xffffffffU, +/*0165*/ 0xffffffffU, +/*0166*/ 0x1001070cU, +/*0167*/ 0x1801070cU, +/*0168*/ 0x000d070dU, +/*0169*/ 0xffffffffU, +/*016a*/ 0xffffffffU, +/*016b*/ 0x0005070eU, +/*016c*/ 0x0001070fU, +/*016d*/ 0x080e070fU, +/*016e*/ 0x000e0710U, +/*016f*/ 0x100e0710U, +/*0170*/ 0x000e0711U, +/*0171*/ 0x100e0711U, +/*0172*/ 0x00040712U, +/*0173*/ 0xffffffffU, +/*0174*/ 0xffffffffU, +/*0175*/ 0xffffffffU, +/*0176*/ 0xffffffffU, +/*0177*/ 0x080b0712U, +/*0178*/ 0x000b0713U, +/*0179*/ 0x100b0713U, +/*017a*/ 0x000b0714U, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d0715U, +/*0180*/ 0xffffffffU, +/*0181*/ 0xffffffffU, +/*0182*/ 0x10100715U, +/*0183*/ 0x00080716U, +/*0184*/ 0xffffffffU, +/*0185*/ 0x08100716U, +/*0186*/ 0x00100717U, +/*0187*/ 0x10100717U, +/*0188*/ 0x00100718U, +/*0189*/ 0x10100718U, +/*018a*/ 0x00030719U, +/*018b*/ 0x08040719U, +/*018c*/ 0x10010719U, +/*018d*/ 0x18040719U, +/*018e*/ 0xffffffffU, +/*018f*/ 0xffffffffU, +/*0190*/ 0x0001071aU, +/*0191*/ 0x0812071aU, +/*0192*/ 0x000a071bU, +/*0193*/ 0x100c071bU, +/*0194*/ 0x0012071cU, +/*0195*/ 0x0014071dU, +/*0196*/ 0x0012071eU, +/*0197*/ 0x0011071fU, +/*0198*/ 0x00110720U, +/*0199*/ 0x00120721U, +/*019a*/ 0x00120722U, +/*019b*/ 0x00120723U, +/*019c*/ 0x00120724U, +/*019d*/ 0x00120725U, +/*019e*/ 0x00120726U, +/*019f*/ 0x00120727U, +/*01a0*/ 0x00120728U, +/*01a1*/ 0xffffffffU, +/*01a2*/ 0xffffffffU, +/*01a3*/ 0x00190729U, +/*01a4*/ 0x0019072aU, +/*01a5*/ 0x0020072bU, +/*01a6*/ 0x0017072cU, +/*01a7*/ 0x1808072cU, +/*01a8*/ 0x0001072dU, +/*01a9*/ 0x0801072dU, +/*01aa*/ 0x0020072eU, +/*01ab*/ 0x0008072fU, +/*01ac*/ 0xffffffffU, +/*01ad*/ 0x0803072fU, +/*01ae*/ 0x00180730U, +/*01af*/ 0x00180731U, +/*01b0*/ 0xffffffffU, +/*01b1*/ 0xffffffffU, +/*01b2*/ 0xffffffffU, +/*01b3*/ 0xffffffffU, +/*01b4*/ 0xffffffffU, +/*01b5*/ 0xffffffffU, +/*01b6*/ 0xffffffffU, +/*01b7*/ 0xffffffffU, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x00100732U, +/*01c0*/ 0x10010732U, +/*01c1*/ 0x18010732U, +/*01c2*/ 0x00050733U, +/*01c3*/ 0x00200734U, +/*01c4*/ 0x00090735U, +/*01c5*/ 0xffffffffU, +/*01c6*/ 0xffffffffU, +/*01c7*/ 0x00200736U, +/*01c8*/ 0x00040737U, +/*01c9*/ 0x08100737U, +/*01ca*/ 0x18060737U, +/*01cb*/ 0x00100738U, +/*01cc*/ 0xffffffffU, +/*01cd*/ 0xffffffffU, +/*01ce*/ 0xffffffffU, +/*01cf*/ 0xffffffffU, +/*01d0*/ 0xffffffffU, +/*01d1*/ 0xffffffffU, +/*01d2*/ 0xffffffffU, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200739U, +/*01d5*/ 0x000b073aU, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0xffffffffU, +/*01d8*/ 0xffffffffU, +/*01d9*/ 0xffffffffU, +/*01da*/ 0xffffffffU, +/*01db*/ 0xffffffffU, +/*01dc*/ 0xffffffffU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0xffffffffU, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x10100201U, +/*01e6*/ 0xffffffffU, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200202U, +/*01f0*/ 0x00100203U, +/*01f1*/ 0x00200204U, +/*01f2*/ 0x00100205U, +/*01f3*/ 0x00200206U, +/*01f4*/ 0x00100207U, +/*01f5*/ 0x10100207U, +/*01f6*/ 0x00200208U, +/*01f7*/ 0x00200209U, +/*01f8*/ 0x0020020aU, +/*01f9*/ 0x0020020bU, +/*01fa*/ 0x0010020cU, +/*01fb*/ 0x0020020dU, +/*01fc*/ 0x0020020eU, +/*01fd*/ 0x0020020fU, +/*01fe*/ 0x00200210U, +/*01ff*/ 0x00100211U, +/*0200*/ 0x00200212U, +/*0201*/ 0x00200213U, +/*0202*/ 0x00200214U, +/*0203*/ 0x00200215U, +/*0204*/ 0x00090216U, +/*0205*/ 0x10010216U, +/*0206*/ 0x00200217U, +/*0207*/ 0x00050218U, +/*0208*/ 0x08010218U, +/*0209*/ 0x10080218U, +/*020a*/ 0x18080218U, +/*020b*/ 0x001c0219U, +/*020c*/ 0x001c021aU, +/*020d*/ 0x001c021bU, +/*020e*/ 0x001c021cU, +/*020f*/ 0x001c021dU, +/*0210*/ 0x001c021eU, +/*0211*/ 0x001c021fU, +/*0212*/ 0x001c0220U, +/*0213*/ 0x001c0221U, +/*0214*/ 0x001c0222U, +/*0215*/ 0x001c0223U, +/*0216*/ 0x001c0224U, +/*0217*/ 0x001c0225U, +/*0218*/ 0x001c0226U, +/*0219*/ 0x001c0227U, +/*021a*/ 0x001c0228U, +/*021b*/ 0x00010229U, +/*021c*/ 0x08010229U, +/*021d*/ 0x10010229U, +/*021e*/ 0x18040229U, +/*021f*/ 0x0008022aU, +/*0220*/ 0x0808022aU, +/*0221*/ 0x1008022aU, +/*0222*/ 0x1804022aU, +/*0223*/ 0x0006022bU, +/*0224*/ 0xffffffffU, +/*0225*/ 0x0807022bU, +/*0226*/ 0x1006022bU, +/*0227*/ 0xffffffffU, +/*0228*/ 0x1807022bU, +/*0229*/ 0x0006022cU, +/*022a*/ 0xffffffffU, +/*022b*/ 0x0807022cU, +/*022c*/ 0x1002022cU, +/*022d*/ 0x1801022cU, +/*022e*/ 0xffffffffU, +/*022f*/ 0x000a022dU, +/*0230*/ 0x1010022dU, +/*0231*/ 0x000a022eU, +/*0232*/ 0x1010022eU, +/*0233*/ 0x000a022fU, +/*0234*/ 0x1010022fU, +/*0235*/ 0xffffffffU, +/*0236*/ 0x00100230U, +/*0237*/ 0xffffffffU, +/*0238*/ 0xffffffffU, +/*0239*/ 0x10010230U, +/*023a*/ 0x18010230U, +/*023b*/ 0x00010231U, +/*023c*/ 0x08010231U, +/*023d*/ 0x10010231U, +/*023e*/ 0x18010231U, +/*023f*/ 0x00020232U, +/*0240*/ 0x08020232U, +/*0241*/ 0x10020232U, +/*0242*/ 0x18020232U, +/*0243*/ 0x00020233U, +/*0244*/ 0x08030233U, +/*0245*/ 0x10010233U, +/*0246*/ 0x18010233U, +/*0247*/ 0x00010234U, +/*0248*/ 0x08010234U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x10020234U, +/*024b*/ 0x18010234U, +/*024c*/ 0x00010235U, +/*024d*/ 0xffffffffU, +/*024e*/ 0x08020235U, +/*024f*/ 0x10010235U, +/*0250*/ 0x18010235U, +/*0251*/ 0xffffffffU, +/*0252*/ 0x00020236U, +/*0253*/ 0x08010236U, +/*0254*/ 0x10010236U, +/*0255*/ 0xffffffffU, +/*0256*/ 0x18020236U, +/*0257*/ 0x00070237U, +/*0258*/ 0x08010237U, +/*0259*/ 0x10010237U, +/*025a*/ 0x18010237U, +/*025b*/ 0x00010238U, +/*025c*/ 0x08010238U, +/*025d*/ 0x10010238U, +/*025e*/ 0xffffffffU, +/*025f*/ 0x18010238U, +/*0260*/ 0x00040239U, +/*0261*/ 0x08040239U, +/*0262*/ 0x10040239U, +/*0263*/ 0x18010239U, +/*0264*/ 0x0002023aU, +/*0265*/ 0x0806023aU, +/*0266*/ 0x1006023aU, +/*0267*/ 0xffffffffU, +/*0268*/ 0xffffffffU, +/*0269*/ 0xffffffffU, +/*026a*/ 0x1802023aU, +/*026b*/ 0x0010023bU, +/*026c*/ 0x1001023bU, +/*026d*/ 0x1801023bU, +/*026e*/ 0xffffffffU, +/*026f*/ 0x0004023cU, +/*0270*/ 0x0801023cU, +/*0271*/ 0x1004023cU, +/*0272*/ 0x1802023cU, +/*0273*/ 0x0008023dU, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x080a023dU, +/*0278*/ 0x0020023eU, +/*0279*/ 0x0020023fU, +/*027a*/ 0x00050240U, +/*027b*/ 0x08010240U, +/*027c*/ 0x10050240U, +/*027d*/ 0x18080240U, +/*027e*/ 0x00010241U, +/*027f*/ 0x08080241U, +/*0280*/ 0x10010241U, +/*0281*/ 0x18080241U, +/*0282*/ 0x00010242U, +/*0283*/ 0x08040242U, +/*0284*/ 0x10040242U, +/*0285*/ 0x18040242U, +/*0286*/ 0x00040243U, +/*0287*/ 0x08040243U, +/*0288*/ 0x10040243U, +/*0289*/ 0x18040243U, +/*028a*/ 0x00040244U, +/*028b*/ 0x08040244U, +/*028c*/ 0x10040244U, +/*028d*/ 0x18010244U, +/*028e*/ 0x00040245U, +/*028f*/ 0x08040245U, +/*0290*/ 0x10040245U, +/*0291*/ 0x18040245U, +/*0292*/ 0x00040246U, +/*0293*/ 0x08040246U, +/*0294*/ 0x10060246U, +/*0295*/ 0x18060246U, +/*0296*/ 0x00060247U, +/*0297*/ 0x08060247U, +/*0298*/ 0x10060247U, +/*0299*/ 0x18060247U, +/*029a*/ 0xffffffffU, +/*029b*/ 0x00010248U, +/*029c*/ 0x08010248U, +/*029d*/ 0x10020248U, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x18040248U, +/*02a7*/ 0x00040249U, +/*02a8*/ 0x08010249U, +/*02a9*/ 0x10010249U, +/*02aa*/ 0xffffffffU, +/*02ab*/ 0x18010249U, +/*02ac*/ 0x0001024aU, +/*02ad*/ 0xffffffffU, +/*02ae*/ 0x0801024aU, +/*02af*/ 0x1001024aU, +/*02b0*/ 0x1801024aU, +/*02b1*/ 0x0004024bU, +/*02b2*/ 0x0804024bU, +/*02b3*/ 0x100a024bU, +/*02b4*/ 0x0020024cU, +/*02b5*/ 0x0004024dU, +/*02b6*/ 0x0808024dU, +/*02b7*/ 0xffffffffU, +/*02b8*/ 0xffffffffU, +/*02b9*/ 0xffffffffU, +/*02ba*/ 0xffffffffU, +/*02bb*/ 0xffffffffU, +/*02bc*/ 0xffffffffU, +/*02bd*/ 0x1002024dU, +/*02be*/ 0x1802024dU, +/*02bf*/ 0x0020024eU, +/*02c0*/ 0x0002024fU, +/*02c1*/ 0x0810024fU, +/*02c2*/ 0x00100250U, +/*02c3*/ 0x10040250U, +/*02c4*/ 0x18040250U, +/*02c5*/ 0x00050251U, +/*02c6*/ 0x08050251U, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x10010251U, +/*02cc*/ 0x18010251U, +/*02cd*/ 0x00070252U, +/*02ce*/ 0x08070252U, +/*02cf*/ 0x10070252U, +/*02d0*/ 0x18070252U, +/*02d1*/ 0x00070253U, +/*02d2*/ 0x08070253U, +/*02d3*/ 0x10070253U, +/*02d4*/ 0x18070253U, +/*02d5*/ 0x00070254U, +/*02d6*/ 0x08070254U, +/*02d7*/ 0x10070254U, +/*02d8*/ 0xffffffffU, +/*02d9*/ 0xffffffffU, +/*02da*/ 0xffffffffU, +/*02db*/ 0xffffffffU, +/*02dc*/ 0xffffffffU, +/*02dd*/ 0xffffffffU, +/*02de*/ 0x18030254U, +/*02df*/ 0x00010255U, +/*02e0*/ 0x08020255U, +/*02e1*/ 0x10010255U, +/*02e2*/ 0x18040255U, +/*02e3*/ 0x00020256U, +/*02e4*/ 0x08010256U, +/*02e5*/ 0x10010256U, +/*02e6*/ 0xffffffffU, +/*02e7*/ 0x18010256U, +/*02e8*/ 0x00040257U, +/*02e9*/ 0x08080257U, +/*02ea*/ 0x100a0257U, +/*02eb*/ 0x000a0258U, +/*02ec*/ 0x100a0258U, +/*02ed*/ 0x000a0259U, +/*02ee*/ 0x100a0259U, +/*02ef*/ 0x000a025aU, +/*02f0*/ 0x0020025bU, +/*02f1*/ 0x0020025cU, +/*02f2*/ 0x0001025dU, +/*02f3*/ 0xffffffffU, +/*02f4*/ 0xffffffffU, +/*02f5*/ 0xffffffffU, +/*02f6*/ 0x0802025dU, +/*02f7*/ 0x1002025dU, +/*02f8*/ 0x0010025eU, +/*02f9*/ 0x1005025eU, +/*02fa*/ 0x1806025eU, +/*02fb*/ 0x0005025fU, +/*02fc*/ 0x0805025fU, +/*02fd*/ 0x100e025fU, +/*02fe*/ 0x00050260U, +/*02ff*/ 0x080e0260U, +/*0300*/ 0x18050260U, +/*0301*/ 0x000e0261U, +/*0302*/ 0x10050261U, +/*0303*/ 0x18010261U, +/*0304*/ 0x00050262U, +/*0305*/ 0x08050262U, +/*0306*/ 0x100a0262U, +/*0307*/ 0x000a0263U, +/*0308*/ 0x10050263U, +/*0309*/ 0x18050263U, +/*030a*/ 0x000a0264U, +/*030b*/ 0x100a0264U, +/*030c*/ 0x00050265U, +/*030d*/ 0x08050265U, +/*030e*/ 0x100a0265U, +/*030f*/ 0x000a0266U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070266U, +/*0317*/ 0x18070266U, +/*0318*/ 0x00040267U, +/*0319*/ 0x08040267U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040267U, +/*031e*/ 0x18080267U, +/*031f*/ 0x00080268U, +/*0320*/ 0x08040268U, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x10040268U, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x18040268U, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x00040269U, +/*032d*/ 0x08050269U, +/*032e*/ 0x10070269U, +/*032f*/ 0x18080269U, +/*0330*/ 0x0010026aU, +/*0331*/ 0x1008026aU, +/*0332*/ 0x0010026bU, +/*0333*/ 0x1008026bU, +/*0334*/ 0x0010026cU, +/*0335*/ 0x1008026cU, +/*0336*/ 0x1808026cU, +/*0337*/ 0x0001026dU, +/*0338*/ 0x0801026dU, +/*0339*/ 0x1006026dU, +/*033a*/ 0x1806026dU, +/*033b*/ 0x0006026eU, +/*033c*/ 0xffffffffU, +/*033d*/ 0x0801026eU, +/*033e*/ 0x1003026eU, +/*033f*/ 0xffffffffU, +/*0340*/ 0xffffffffU, +/*0341*/ 0xffffffffU, +/*0342*/ 0x000a026fU, +/*0343*/ 0x100a026fU, +/*0344*/ 0x00040270U, +/*0345*/ 0x08010270U, +/*0346*/ 0x10040270U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070270U, +/*034e*/ 0x00070271U, +/*034f*/ 0x08050271U, +/*0350*/ 0x10050271U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040271U, +/*0355*/ 0x00010272U, +/*0356*/ 0x08010272U, +/*0357*/ 0x10020272U, +/*0358*/ 0x18080272U, +/*0359*/ 0x00200273U, +/*035a*/ 0x00200274U, +/*035b*/ 0x00100275U, +/*035c*/ 0xffffffffU, +/*035d*/ 0xffffffffU, +/*035e*/ 0xffffffffU, +/*035f*/ 0x10020275U, +/*0360*/ 0x18010275U, +/*0361*/ 0xffffffffU, +/*0362*/ 0x00020276U, +/*0363*/ 0x08080276U, +/*0364*/ 0x10080276U, +/*0365*/ 0x18080276U, +/*0366*/ 0x00080277U, +/*0367*/ 0x08080277U, +/*0368*/ 0x10080277U, +/*0369*/ 0xffffffffU, +/*036a*/ 0x18080277U, +/*036b*/ 0x00080278U, +/*036c*/ 0x08080278U, +/*036d*/ 0x10080278U, +/*036e*/ 0x18080278U, +/*036f*/ 0x00080279U, +/*0370*/ 0xffffffffU, +/*0371*/ 0x08080279U, +/*0372*/ 0x10080279U, +/*0373*/ 0x18080279U, +/*0374*/ 0x0008027aU, +/*0375*/ 0x0808027aU, +/*0376*/ 0x1008027aU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1808027aU, +/*0379*/ 0x0008027bU, +/*037a*/ 0x0808027bU, +/*037b*/ 0x1008027bU, +/*037c*/ 0x1808027bU, +/*037d*/ 0x0008027cU, +/*037e*/ 0x0808027cU, +/*037f*/ 0xffffffffU, +/*0380*/ 0x1008027cU, +/*0381*/ 0x1808027cU, +/*0382*/ 0x0008027dU, +/*0383*/ 0x0808027dU, +/*0384*/ 0x1008027dU, +/*0385*/ 0x1808027dU, +/*0386*/ 0xffffffffU, +/*0387*/ 0x0008027eU, +/*0388*/ 0x0808027eU, +/*0389*/ 0x1008027eU, +/*038a*/ 0x1808027eU, +/*038b*/ 0x0008027fU, +/*038c*/ 0x0808027fU, +/*038d*/ 0xffffffffU, +/*038e*/ 0x1008027fU, +/*038f*/ 0x1808027fU, +/*0390*/ 0x00080280U, +/*0391*/ 0x08080280U, +/*0392*/ 0x10080280U, +/*0393*/ 0x18080280U, +/*0394*/ 0x00080281U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x08080281U, +/*0397*/ 0x10080281U, +/*0398*/ 0x18080281U, +/*0399*/ 0x00080282U, +/*039a*/ 0x08080282U, +/*039b*/ 0x10080282U, +/*039c*/ 0xffffffffU, +/*039d*/ 0x18080282U, +/*039e*/ 0x00080283U, +/*039f*/ 0x08080283U, +/*03a0*/ 0x10080283U, +/*03a1*/ 0x18080283U, +/*03a2*/ 0x00080284U, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x08080284U, +/*03a5*/ 0x10080284U, +/*03a6*/ 0x18080284U, +/*03a7*/ 0x00080285U, +/*03a8*/ 0x08080285U, +/*03a9*/ 0x10080285U, +/*03aa*/ 0x18080285U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x00080286U, +/*03ad*/ 0x08080286U, +/*03ae*/ 0x10080286U, +/*03af*/ 0x18080286U, +/*03b0*/ 0x00080287U, +/*03b1*/ 0x08080287U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x10080287U, +/*03b4*/ 0x18080287U, +/*03b5*/ 0x00080288U, +/*03b6*/ 0x08080288U, +/*03b7*/ 0x10080288U, +/*03b8*/ 0x18080288U, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x00080289U, +/*03bb*/ 0x08020289U, +/*03bc*/ 0x10030289U, +/*03bd*/ 0x000a028aU, +/*03be*/ 0x100a028aU, +/*03bf*/ 0x000a028bU, +/*03c0*/ 0x1005028bU, +/*03c1*/ 0x1804028bU, +/*03c2*/ 0x0008028cU, +/*03c3*/ 0x0808028cU, +/*03c4*/ 0x1006028cU, +/*03c5*/ 0x1806028cU, +/*03c6*/ 0x0011028dU, +/*03c7*/ 0x1808028dU, +/*03c8*/ 0x0004028eU, +/*03c9*/ 0x0806028eU, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x1006028eU, +/*03cc*/ 0x1808028eU, +/*03cd*/ 0xffffffffU, +/*03ce*/ 0x0004028fU, +/*03cf*/ 0x0808028fU, +/*03d0*/ 0x1008028fU, +/*03d1*/ 0x1806028fU, +/*03d2*/ 0x00060290U, +/*03d3*/ 0x08110290U, +/*03d4*/ 0x00080291U, +/*03d5*/ 0x08040291U, +/*03d6*/ 0x10060291U, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x18060291U, +/*03d9*/ 0x00080292U, +/*03da*/ 0xffffffffU, +/*03db*/ 0x08040292U, +/*03dc*/ 0x10080292U, +/*03dd*/ 0x18080292U, +/*03de*/ 0x00060293U, +/*03df*/ 0x08060293U, +/*03e0*/ 0x00110294U, +/*03e1*/ 0x18080294U, +/*03e2*/ 0x00040295U, +/*03e3*/ 0x08060295U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x10060295U, +/*03e6*/ 0x18080295U, +/*03e7*/ 0xffffffffU, +/*03e8*/ 0x00040296U, +/*03e9*/ 0x08040296U, +/*03ea*/ 0x10040296U, +/*03eb*/ 0x18040296U, +/*03ec*/ 0x00040297U, +/*03ed*/ 0x08040297U, +/*03ee*/ 0x10040297U, +/*03ef*/ 0x18040297U, +/*03f0*/ 0x00040298U, +/*03f1*/ 0x08040298U, +/*03f2*/ 0x10040298U, +/*03f3*/ 0x18040298U, +/*03f4*/ 0x00040299U, +/*03f5*/ 0x08040299U, +/*03f6*/ 0x10040299U, +/*03f7*/ 0x18040299U, +/*03f8*/ 0x0004029aU, +/*03f9*/ 0x0804029aU, +/*03fa*/ 0x1004029aU, +/*03fb*/ 0x1804029aU, +/*03fc*/ 0x0011029bU, +/*03fd*/ 0x0010029cU, +/*03fe*/ 0x0011029dU, +/*03ff*/ 0x0020029eU, +/*0400*/ 0x0020029fU, +/*0401*/ 0x002002a0U, +/*0402*/ 0x002002a1U, +/*0403*/ 0x002002a2U, +/*0404*/ 0x002002a3U, +/*0405*/ 0x002002a4U, +/*0406*/ 0x002002a5U, +/*0407*/ 0x002002a6U, +/*0408*/ 0x000202a7U, +/*0409*/ 0x080502a7U, +/*040a*/ 0x100502a7U, +/*040b*/ 0xffffffffU, +/*040c*/ 0xffffffffU, +/*040d*/ 0xffffffffU, +/*040e*/ 0xffffffffU, +/*040f*/ 0xffffffffU, +/*0410*/ 0xffffffffU, +/*0411*/ 0xffffffffU, +/*0412*/ 0xffffffffU, +/*0413*/ 0xffffffffU, +/*0414*/ 0xffffffffU, +/*0415*/ 0xffffffffU, +/*0416*/ 0xffffffffU, +/*0417*/ 0xffffffffU, +/*0418*/ 0xffffffffU, +/*0419*/ 0xffffffffU, +/*041a*/ 0xffffffffU, +/*041b*/ 0xffffffffU, +/*041c*/ 0xffffffffU, +/*041d*/ 0xffffffffU, +/*041e*/ 0xffffffffU, +/*041f*/ 0xffffffffU, +/*0420*/ 0xffffffffU, +/*0421*/ 0xffffffffU, +/*0422*/ 0xffffffffU, +/*0423*/ 0xffffffffU, +/*0424*/ 0xffffffffU, +/*0425*/ 0xffffffffU, +/*0426*/ 0xffffffffU, +/*0427*/ 0x180102a7U, +/*0428*/ 0x000402a8U, +/*0429*/ 0x081002a8U, +/*042a*/ 0x002002a9U, +/*042b*/ 0x001002aaU, +/*042c*/ 0x002002abU, +/*042d*/ 0x001002acU, +/*042e*/ 0x002002adU, +/*042f*/ 0x000702aeU, +/*0430*/ 0x080102aeU, +/*0431*/ 0x100202aeU, +/*0432*/ 0x180602aeU, +/*0433*/ 0x000102afU, +/*0434*/ 0x080102afU, +/*0435*/ 0x002002b0U, +/*0436*/ 0x000202b1U, +/*0437*/ 0x002002b2U, +/*0438*/ 0x002002b3U, +/*0439*/ 0xffffffffU, +/*043a*/ 0xffffffffU, +/*043b*/ 0xffffffffU, +/*043c*/ 0xffffffffU, +/*043d*/ 0xffffffffU, +/*043e*/ 0xffffffffU, +/*043f*/ 0xffffffffU, +/*0440*/ 0xffffffffU, +/*0441*/ 0xffffffffU, +/*0442*/ 0xffffffffU, +/*0443*/ 0xffffffffU, +/*0444*/ 0xffffffffU, +/*0445*/ 0xffffffffU, +/*0446*/ 0xffffffffU, +/*0447*/ 0xffffffffU, +/*0448*/ 0xffffffffU, +/*0449*/ 0xffffffffU, +/*044a*/ 0xffffffffU, +/*044b*/ 0xffffffffU, +/*044c*/ 0xffffffffU, +/*044d*/ 0xffffffffU, +/*044e*/ 0xffffffffU, +/*044f*/ 0xffffffffU, +/*0450*/ 0xffffffffU, +/*0451*/ 0xffffffffU, +/*0452*/ 0xffffffffU, +/*0453*/ 0xffffffffU, +/*0454*/ 0xffffffffU, +/*0455*/ 0xffffffffU, +/*0456*/ 0xffffffffU, +/*0457*/ 0xffffffffU, +/*0458*/ 0xffffffffU, +/*0459*/ 0xffffffffU, +/*045a*/ 0xffffffffU, +/*045b*/ 0xffffffffU, +/*045c*/ 0xffffffffU, +/*045d*/ 0xffffffffU, +/*045e*/ 0xffffffffU, +/*045f*/ 0x000402b4U, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0xffffffffU, +/*0465*/ 0xffffffffU, +/*0466*/ 0xffffffffU, +/*0467*/ 0xffffffffU, +/*0468*/ 0xffffffffU, +/*0469*/ 0xffffffffU, +/*046a*/ 0xffffffffU, +/*046b*/ 0xffffffffU, +/*046c*/ 0xffffffffU, +/*046d*/ 0xffffffffU, +/*046e*/ 0xffffffffU, +/*046f*/ 0xffffffffU, +/*0470*/ 0xffffffffU, +/*0471*/ 0xffffffffU, +/*0472*/ 0xffffffffU, +/*0473*/ 0xffffffffU, +/*0474*/ 0xffffffffU, +/*0475*/ 0xffffffffU, +/*0476*/ 0xffffffffU, +/*0477*/ 0xffffffffU, +/*0478*/ 0xffffffffU, +/*0479*/ 0xffffffffU, +/*047a*/ 0xffffffffU, +/*047b*/ 0xffffffffU, +/*047c*/ 0xffffffffU, +/*047d*/ 0xffffffffU, +/*047e*/ 0xffffffffU, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200800U, +/*0001*/ 0x00040801U, +/*0002*/ 0x080b0801U, +/*0003*/ 0xffffffffU, +/*0004*/ 0xffffffffU, +/*0005*/ 0x18010801U, +/*0006*/ 0x00050802U, +/*0007*/ 0x08050802U, +/*0008*/ 0x10050802U, +/*0009*/ 0x18050802U, +/*000a*/ 0x00050803U, +/*000b*/ 0x08050803U, +/*000c*/ 0x10050803U, +/*000d*/ 0x18050803U, +/*000e*/ 0x00050804U, +/*000f*/ 0x08040804U, +/*0010*/ 0x10030804U, +/*0011*/ 0x00180805U, +/*0012*/ 0x18030805U, +/*0013*/ 0x00180806U, +/*0014*/ 0x18020806U, +/*0015*/ 0x00010807U, +/*0016*/ 0x08020807U, +/*0017*/ 0x10010807U, +/*0018*/ 0x18010807U, +/*0019*/ 0x00020808U, +/*001a*/ 0x08040808U, +/*001b*/ 0x10040808U, +/*001c*/ 0x18040808U, +/*001d*/ 0x000a0809U, +/*001e*/ 0x10040809U, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x18070809U, +/*0022*/ 0xffffffffU, +/*0023*/ 0xffffffffU, +/*0024*/ 0xffffffffU, +/*0025*/ 0xffffffffU, +/*0026*/ 0xffffffffU, +/*0027*/ 0xffffffffU, +/*0028*/ 0x000a080aU, +/*0029*/ 0x1005080aU, +/*002a*/ 0x1801080aU, +/*002b*/ 0x0001080bU, +/*002c*/ 0x0802080bU, +/*002d*/ 0x1009080bU, +/*002e*/ 0x0009080cU, +/*002f*/ 0x1002080cU, +/*0030*/ 0x0020080dU, +/*0031*/ 0xffffffffU, +/*0032*/ 0x0001080eU, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x0020080fU, +/*0038*/ 0x00200810U, +/*0039*/ 0x00200811U, +/*003a*/ 0x00200812U, +/*003b*/ 0x00030813U, +/*003c*/ 0x08010813U, +/*003d*/ 0x10030813U, +/*003e*/ 0x18030813U, +/*003f*/ 0x00040814U, +/*0040*/ 0x08040814U, +/*0041*/ 0x10040814U, +/*0042*/ 0x18040814U, +/*0043*/ 0x00010815U, +/*0044*/ 0x08010815U, +/*0045*/ 0x10060815U, +/*0046*/ 0x18040815U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x00060816U, +/*0049*/ 0x08040816U, +/*004a*/ 0x10060816U, +/*004b*/ 0x18040816U, +/*004c*/ 0x00020817U, +/*004d*/ 0x08050817U, +/*004e*/ 0x10080817U, +/*004f*/ 0x00200818U, +/*0050*/ 0x00060819U, +/*0051*/ 0x08030819U, +/*0052*/ 0x100b0819U, +/*0053*/ 0x0004081aU, +/*0054*/ 0x0804081aU, +/*0055*/ 0x1004081aU, +/*0056*/ 0xffffffffU, +/*0057*/ 0x1801081aU, +/*0058*/ 0x0009081bU, +/*0059*/ 0x0020081cU, +/*005a*/ 0x0020081dU, +/*005b*/ 0x0020081eU, +/*005c*/ 0x0020081fU, +/*005d*/ 0x00100820U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010820U, +/*0060*/ 0x18060820U, +/*0061*/ 0x00080821U, +/*0062*/ 0x00200822U, +/*0063*/ 0xffffffffU, +/*0064*/ 0x000a0823U, +/*0065*/ 0x10060823U, +/*0066*/ 0x18070823U, +/*0067*/ 0x00080824U, +/*0068*/ 0x08080824U, +/*0069*/ 0x100a0824U, +/*006a*/ 0x00070825U, +/*006b*/ 0x08080825U, +/*006c*/ 0x10080825U, +/*006d*/ 0x18030825U, +/*006e*/ 0x000a0826U, +/*006f*/ 0x100a0826U, +/*0070*/ 0x00110827U, +/*0071*/ 0x00090828U, +/*0072*/ 0x10090828U, +/*0073*/ 0x00100829U, +/*0074*/ 0x100e0829U, +/*0075*/ 0x000e082aU, +/*0076*/ 0x100c082aU, +/*0077*/ 0x000a082bU, +/*0078*/ 0x100a082bU, +/*0079*/ 0x0002082cU, +/*007a*/ 0x0020082dU, +/*007b*/ 0x000b082eU, +/*007c*/ 0x100b082eU, +/*007d*/ 0x0020082fU, +/*007e*/ 0x00120830U, +/*007f*/ 0x00200831U, +/*0080*/ 0x00200832U, +/*0081*/ 0xffffffffU, +/*0082*/ 0xffffffffU, +/*0083*/ 0x00010833U, +/*0084*/ 0x08010833U, +/*0085*/ 0x10080833U, +/*0086*/ 0x000c0834U, +/*0087*/ 0x100c0834U, +/*0088*/ 0x000c0835U, +/*0089*/ 0x100c0835U, +/*008a*/ 0x000c0836U, +/*008b*/ 0x100c0836U, +/*008c*/ 0x000c0837U, +/*008d*/ 0x100c0837U, +/*008e*/ 0x000c0838U, +/*008f*/ 0x100c0838U, +/*0090*/ 0x000c0839U, +/*0091*/ 0x100b0839U, +/*0092*/ 0xffffffffU, +/*0093*/ 0xffffffffU, +/*0094*/ 0x000b083aU, +/*0095*/ 0x100b083aU, +/*0096*/ 0x000b083bU, +/*0097*/ 0x100b083bU, +/*0098*/ 0x000b083cU, +/*0099*/ 0x100b083cU, +/*009a*/ 0x000b083dU, +/*009b*/ 0x100b083dU, +/*009c*/ 0x000b083eU, +/*009d*/ 0x100a083eU, +/*009e*/ 0xffffffffU, +/*009f*/ 0x000a083fU, +/*00a0*/ 0x100a083fU, +/*00a1*/ 0x000a0840U, +/*00a2*/ 0x100a0840U, +/*00a3*/ 0x000a0841U, +/*00a4*/ 0x100a0841U, +/*00a5*/ 0x000a0842U, +/*00a6*/ 0x100a0842U, +/*00a7*/ 0x000a0843U, +/*00a8*/ 0x100a0843U, +/*00a9*/ 0x000a0844U, +/*00aa*/ 0x100a0844U, +/*00ab*/ 0x000a0845U, +/*00ac*/ 0x100a0845U, +/*00ad*/ 0x000a0846U, +/*00ae*/ 0x100a0846U, +/*00af*/ 0x000a0847U, +/*00b0*/ 0x100a0847U, +/*00b1*/ 0x000a0848U, +/*00b2*/ 0x100a0848U, +/*00b3*/ 0x000a0849U, +/*00b4*/ 0x100a0849U, +/*00b5*/ 0x000a084aU, +/*00b6*/ 0x100a084aU, +/*00b7*/ 0x000a084bU, +/*00b8*/ 0x100a084bU, +/*00b9*/ 0x000a084cU, +/*00ba*/ 0x100a084cU, +/*00bb*/ 0x0004084dU, +/*00bc*/ 0x0803084dU, +/*00bd*/ 0x100a084dU, +/*00be*/ 0x000a084eU, +/*00bf*/ 0x1001084eU, +/*00c0*/ 0x000a084fU, +/*00c1*/ 0x1004084fU, +/*00c2*/ 0x000b0850U, +/*00c3*/ 0x100a0850U, +/*00c4*/ 0xffffffffU, +/*00c5*/ 0x00080851U, +/*00c6*/ 0x08080851U, +/*00c7*/ 0x10080851U, +/*00c8*/ 0x18080851U, +/*00c9*/ 0x00080852U, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x08080852U, +/*00cc*/ 0x10010852U, +/*00cd*/ 0x18080852U, +/*00ce*/ 0x00080853U, +/*00cf*/ 0x08020853U, +/*00d0*/ 0x10020853U, +/*00d1*/ 0x18040853U, +/*00d2*/ 0x00040854U, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x08040854U, +/*00d5*/ 0x100a0854U, +/*00d6*/ 0x00060855U, +/*00d7*/ 0x08080855U, +/*00d8*/ 0xffffffffU, +/*00d9*/ 0x10040855U, +/*00da*/ 0x18040855U, +/*00db*/ 0x00050856U, +/*00dc*/ 0x08040856U, +/*00dd*/ 0x10050856U, +/*00de*/ 0x000a0857U, +/*00df*/ 0x100a0857U, +/*00e0*/ 0x00080858U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040858U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050a00U, +/*00e6*/ 0x08050a00U, +/*00e7*/ 0x10050a00U, +/*00e8*/ 0x18050a00U, +/*00e9*/ 0x00050a01U, +/*00ea*/ 0x08050a01U, +/*00eb*/ 0x100b0a01U, +/*00ec*/ 0x00010a02U, +/*00ed*/ 0x08030a02U, +/*00ee*/ 0x00200a03U, +/*00ef*/ 0xffffffffU, +/*00f0*/ 0x00030a04U, +/*00f1*/ 0x080a0a04U, +/*00f2*/ 0xffffffffU, +/*00f3*/ 0xffffffffU, +/*00f4*/ 0x18030a04U, +/*00f5*/ 0x00030a05U, +/*00f6*/ 0x08010a05U, +/*00f7*/ 0x10010a05U, +/*00f8*/ 0x18060a05U, +/*00f9*/ 0xffffffffU, +/*00fa*/ 0xffffffffU, +/*00fb*/ 0xffffffffU, +/*00fc*/ 0x00020a06U, +/*00fd*/ 0x08030a06U, +/*00fe*/ 0x10010a06U, +/*00ff*/ 0x000f0a07U, +/*0100*/ 0x00200a08U, +/*0101*/ 0x00200a09U, +/*0102*/ 0x000b0a0aU, +/*0103*/ 0x100b0a0aU, +/*0104*/ 0x000b0a0bU, +/*0105*/ 0xffffffffU, +/*0106*/ 0xffffffffU, +/*0107*/ 0x00180a0cU, +/*0108*/ 0x00180a0dU, +/*0109*/ 0x00180a0eU, +/*010a*/ 0x00180a0fU, +/*010b*/ 0x18040a0fU, +/*010c*/ 0x00020a10U, +/*010d*/ 0x08020a10U, +/*010e*/ 0x10040a10U, +/*010f*/ 0x18040a10U, +/*0110*/ 0x00010a11U, +/*0111*/ 0x08010a11U, +/*0112*/ 0x10010a11U, +/*0113*/ 0x18030a11U, +/*0114*/ 0x00200a12U, +/*0115*/ 0x00200a13U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140a14U, +/*0118*/ 0x00140a15U, +/*0119*/ 0x00140a16U, +/*011a*/ 0x00140a17U, +/*011b*/ 0x00140a18U, +/*011c*/ 0x00140a19U, +/*011d*/ 0x00140a1aU, +/*011e*/ 0x00140a1bU, +/*011f*/ 0x001e0a1cU, +/*0120*/ 0x000a0a1dU, +/*0121*/ 0x10060a1dU, +/*0122*/ 0x18060a1dU, +/*0123*/ 0x00060a1eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0x08060a1eU, +/*0126*/ 0x00080a1fU, +/*0127*/ 0x080b0a1fU, +/*0128*/ 0x000b0a20U, +/*0129*/ 0x100b0a20U, +/*012a*/ 0x000b0a21U, +/*012b*/ 0x100b0a21U, +/*012c*/ 0x000b0a22U, +/*012d*/ 0x10040a22U, +/*012e*/ 0x000a0a23U, +/*012f*/ 0x10060a23U, +/*0130*/ 0x18080a23U, +/*0131*/ 0xffffffffU, +/*0132*/ 0x00040a24U, +/*0133*/ 0xffffffffU, +/*0134*/ 0xffffffffU, +/*0135*/ 0x00010b80U, +/*0136*/ 0x08020b80U, +/*0137*/ 0x10050b80U, +/*0138*/ 0x18050b80U, +/*0139*/ 0x00050b81U, +/*013a*/ 0x08050b81U, +/*013b*/ 0x100b0b81U, +/*013c*/ 0x00050b82U, +/*013d*/ 0x08010b82U, +/*013e*/ 0x10010b82U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x18010b82U, +/*0141*/ 0x00010b83U, +/*0142*/ 0x08040b83U, +/*0143*/ 0x100b0b83U, +/*0144*/ 0x000b0b84U, +/*0145*/ 0xffffffffU, +/*0146*/ 0x10040b84U, +/*0147*/ 0x000b0b85U, +/*0148*/ 0x10040b85U, +/*0149*/ 0x18010b85U, +/*014a*/ 0x00010b86U, +/*014b*/ 0x08010b86U, +/*014c*/ 0x00200b87U, +/*014d*/ 0x00200b88U, +/*014e*/ 0x00080b89U, +/*014f*/ 0x080a0b89U, +/*0150*/ 0x18050b89U, +/*0151*/ 0x000a0b8aU, +/*0152*/ 0x10030b8aU, +/*0153*/ 0x18030b8aU, +/*0154*/ 0x00010b8bU, +/*0155*/ 0x08020b8bU, +/*0156*/ 0x10010b8bU, +/*0157*/ 0x18010b8bU, +/*0158*/ 0x00010b8cU, +/*0159*/ 0x08030b8cU, +/*015a*/ 0xffffffffU, +/*015b*/ 0x10040b8cU, +/*015c*/ 0x18040b8cU, +/*015d*/ 0x00040b8dU, +/*015e*/ 0x08040b8dU, +/*015f*/ 0xffffffffU, +/*0160*/ 0xffffffffU, +/*0161*/ 0xffffffffU, +/*0162*/ 0xffffffffU, +/*0163*/ 0xffffffffU, +/*0164*/ 0xffffffffU, +/*0165*/ 0xffffffffU, +/*0166*/ 0xffffffffU, +/*0167*/ 0xffffffffU, +/*0168*/ 0x000d0b8eU, +/*0169*/ 0x100d0b8eU, +/*016a*/ 0x000d0b8fU, +/*016b*/ 0x00050b90U, +/*016c*/ 0x00010b91U, +/*016d*/ 0x080e0b91U, +/*016e*/ 0x000e0b92U, +/*016f*/ 0x100e0b92U, +/*0170*/ 0x000e0b93U, +/*0171*/ 0x100e0b93U, +/*0172*/ 0x00040b94U, +/*0173*/ 0x08040b94U, +/*0174*/ 0x10040b94U, +/*0175*/ 0x18040b94U, +/*0176*/ 0x00040b95U, +/*0177*/ 0x080b0b95U, +/*0178*/ 0x000b0b96U, +/*0179*/ 0x100b0b96U, +/*017a*/ 0x000b0b97U, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d0b98U, +/*0180*/ 0x100d0b98U, +/*0181*/ 0x000d0b99U, +/*0182*/ 0x10100b99U, +/*0183*/ 0x10080b8dU, +/*0184*/ 0x18080b8dU, +/*0185*/ 0x00100b9aU, +/*0186*/ 0x10100b9aU, +/*0187*/ 0x00100b9bU, +/*0188*/ 0x10100b9bU, +/*0189*/ 0x00100b9cU, +/*018a*/ 0x10030b9cU, +/*018b*/ 0x18040b9cU, +/*018c*/ 0x00010b9dU, +/*018d*/ 0x08040b9dU, +/*018e*/ 0xffffffffU, +/*018f*/ 0xffffffffU, +/*0190*/ 0x10010b9dU, +/*0191*/ 0x00140b9eU, +/*0192*/ 0x000a0b9fU, +/*0193*/ 0x100c0b9fU, +/*0194*/ 0x00120ba0U, +/*0195*/ 0x00140ba1U, +/*0196*/ 0x00120ba2U, +/*0197*/ 0x00110ba3U, +/*0198*/ 0x00110ba4U, +/*0199*/ 0x00120ba5U, +/*019a*/ 0x00120ba6U, +/*019b*/ 0x00120ba7U, +/*019c*/ 0x00120ba8U, +/*019d*/ 0x00120ba9U, +/*019e*/ 0x00120baaU, +/*019f*/ 0x00120babU, +/*01a0*/ 0x00120bacU, +/*01a1*/ 0xffffffffU, +/*01a2*/ 0xffffffffU, +/*01a3*/ 0x00190badU, +/*01a4*/ 0x00190baeU, +/*01a5*/ 0x00200bafU, +/*01a6*/ 0x00170bb0U, +/*01a7*/ 0x18080bb0U, +/*01a8*/ 0x00010bb1U, +/*01a9*/ 0x08010bb1U, +/*01aa*/ 0x00200bb2U, +/*01ab*/ 0x00080bb3U, +/*01ac*/ 0xffffffffU, +/*01ad*/ 0x08030bb3U, +/*01ae*/ 0x00180bb4U, +/*01af*/ 0x00180bb5U, +/*01b0*/ 0xffffffffU, +/*01b1*/ 0xffffffffU, +/*01b2*/ 0xffffffffU, +/*01b3*/ 0xffffffffU, +/*01b4*/ 0xffffffffU, +/*01b5*/ 0xffffffffU, +/*01b6*/ 0xffffffffU, +/*01b7*/ 0xffffffffU, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x00100bb6U, +/*01c0*/ 0x10010bb6U, +/*01c1*/ 0x18010bb6U, +/*01c2*/ 0x00050bb7U, +/*01c3*/ 0x00200bb8U, +/*01c4*/ 0x00090bb9U, +/*01c5*/ 0xffffffffU, +/*01c6*/ 0xffffffffU, +/*01c7*/ 0x00200bbaU, +/*01c8*/ 0x00040bbbU, +/*01c9*/ 0x08100bbbU, +/*01ca*/ 0x18060bbbU, +/*01cb*/ 0x00100bbcU, +/*01cc*/ 0xffffffffU, +/*01cd*/ 0x10080bbcU, +/*01ce*/ 0xffffffffU, +/*01cf*/ 0xffffffffU, +/*01d0*/ 0xffffffffU, +/*01d1*/ 0x18030bbcU, +/*01d2*/ 0x00020bbdU, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200bbeU, +/*01d5*/ 0x000b0bbfU, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0xffffffffU, +/*01d8*/ 0xffffffffU, +/*01d9*/ 0x10020bbfU, +/*01da*/ 0xffffffffU, +/*01db*/ 0xffffffffU, +/*01dc*/ 0xffffffffU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0xffffffffU, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x10100201U, +/*01e6*/ 0xffffffffU, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200202U, +/*01f0*/ 0x00100203U, +/*01f1*/ 0x00200204U, +/*01f2*/ 0x00100205U, +/*01f3*/ 0x00200206U, +/*01f4*/ 0x00100207U, +/*01f5*/ 0x10100207U, +/*01f6*/ 0x00200208U, +/*01f7*/ 0x00200209U, +/*01f8*/ 0x0020020aU, +/*01f9*/ 0x0020020bU, +/*01fa*/ 0x0010020cU, +/*01fb*/ 0x0020020dU, +/*01fc*/ 0x0020020eU, +/*01fd*/ 0x0020020fU, +/*01fe*/ 0x00200210U, +/*01ff*/ 0x00100211U, +/*0200*/ 0x00200212U, +/*0201*/ 0x00200213U, +/*0202*/ 0x00200214U, +/*0203*/ 0x00200215U, +/*0204*/ 0x00090216U, +/*0205*/ 0x10010216U, +/*0206*/ 0x00200217U, +/*0207*/ 0x00050218U, +/*0208*/ 0x08010218U, +/*0209*/ 0x10080218U, +/*020a*/ 0x18080218U, +/*020b*/ 0x001e0219U, +/*020c*/ 0x001e021aU, +/*020d*/ 0x001e021bU, +/*020e*/ 0x001e021cU, +/*020f*/ 0x001e021dU, +/*0210*/ 0x001e021eU, +/*0211*/ 0x001e021fU, +/*0212*/ 0x001e0220U, +/*0213*/ 0x001e0221U, +/*0214*/ 0x001e0222U, +/*0215*/ 0x001e0223U, +/*0216*/ 0x001e0224U, +/*0217*/ 0x001e0225U, +/*0218*/ 0x001e0226U, +/*0219*/ 0x001e0227U, +/*021a*/ 0x001e0228U, +/*021b*/ 0x00010229U, +/*021c*/ 0x08010229U, +/*021d*/ 0x10010229U, +/*021e*/ 0x18040229U, +/*021f*/ 0x0008022aU, +/*0220*/ 0x0808022aU, +/*0221*/ 0x1008022aU, +/*0222*/ 0x1804022aU, +/*0223*/ 0x0005022bU, +/*0224*/ 0x0806022bU, +/*0225*/ 0x1007022bU, +/*0226*/ 0x1805022bU, +/*0227*/ 0x0006022cU, +/*0228*/ 0x0807022cU, +/*0229*/ 0x1005022cU, +/*022a*/ 0x1806022cU, +/*022b*/ 0x0007022dU, +/*022c*/ 0x0802022dU, +/*022d*/ 0x1001022dU, +/*022e*/ 0xffffffffU, +/*022f*/ 0x000a022eU, +/*0230*/ 0x1010022eU, +/*0231*/ 0x000a022fU, +/*0232*/ 0x1010022fU, +/*0233*/ 0x000a0230U, +/*0234*/ 0x10100230U, +/*0235*/ 0xffffffffU, +/*0236*/ 0x00100231U, +/*0237*/ 0xffffffffU, +/*0238*/ 0xffffffffU, +/*0239*/ 0x10010231U, +/*023a*/ 0x18010231U, +/*023b*/ 0x00010232U, +/*023c*/ 0x08010232U, +/*023d*/ 0x10010232U, +/*023e*/ 0x18010232U, +/*023f*/ 0x00020233U, +/*0240*/ 0x08020233U, +/*0241*/ 0x10020233U, +/*0242*/ 0x18020233U, +/*0243*/ 0x00020234U, +/*0244*/ 0x08030234U, +/*0245*/ 0x10010234U, +/*0246*/ 0x18010234U, +/*0247*/ 0x00010235U, +/*0248*/ 0x08010235U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x10020235U, +/*024b*/ 0x18010235U, +/*024c*/ 0x00010236U, +/*024d*/ 0xffffffffU, +/*024e*/ 0x08020236U, +/*024f*/ 0x10010236U, +/*0250*/ 0x18010236U, +/*0251*/ 0xffffffffU, +/*0252*/ 0x00020237U, +/*0253*/ 0x08010237U, +/*0254*/ 0x10010237U, +/*0255*/ 0xffffffffU, +/*0256*/ 0x18020237U, +/*0257*/ 0x00070238U, +/*0258*/ 0x08010238U, +/*0259*/ 0x10010238U, +/*025a*/ 0x18010238U, +/*025b*/ 0x00010239U, +/*025c*/ 0x08010239U, +/*025d*/ 0x10010239U, +/*025e*/ 0xffffffffU, +/*025f*/ 0x18010239U, +/*0260*/ 0x0004023aU, +/*0261*/ 0x0804023aU, +/*0262*/ 0x1004023aU, +/*0263*/ 0x1801023aU, +/*0264*/ 0x0002023bU, +/*0265*/ 0x0806023bU, +/*0266*/ 0x1006023bU, +/*0267*/ 0xffffffffU, +/*0268*/ 0xffffffffU, +/*0269*/ 0xffffffffU, +/*026a*/ 0x1802023bU, +/*026b*/ 0x0010023cU, +/*026c*/ 0x1001023cU, +/*026d*/ 0x1801023cU, +/*026e*/ 0xffffffffU, +/*026f*/ 0x0004023dU, +/*0270*/ 0x0801023dU, +/*0271*/ 0x1004023dU, +/*0272*/ 0x1802023dU, +/*0273*/ 0x0008023eU, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x080a023eU, +/*0278*/ 0x0020023fU, +/*0279*/ 0x00200240U, +/*027a*/ 0x00050241U, +/*027b*/ 0x08010241U, +/*027c*/ 0x10050241U, +/*027d*/ 0x18080241U, +/*027e*/ 0x00010242U, +/*027f*/ 0x08080242U, +/*0280*/ 0x10010242U, +/*0281*/ 0x18080242U, +/*0282*/ 0x00010243U, +/*0283*/ 0x08040243U, +/*0284*/ 0x10040243U, +/*0285*/ 0x18040243U, +/*0286*/ 0x00040244U, +/*0287*/ 0x08040244U, +/*0288*/ 0x10040244U, +/*0289*/ 0x18040244U, +/*028a*/ 0x00040245U, +/*028b*/ 0x08040245U, +/*028c*/ 0x10040245U, +/*028d*/ 0x18010245U, +/*028e*/ 0x00040246U, +/*028f*/ 0x08040246U, +/*0290*/ 0x10040246U, +/*0291*/ 0x18040246U, +/*0292*/ 0x00040247U, +/*0293*/ 0x08040247U, +/*0294*/ 0x10060247U, +/*0295*/ 0x18060247U, +/*0296*/ 0x00060248U, +/*0297*/ 0x08060248U, +/*0298*/ 0x10060248U, +/*0299*/ 0x18060248U, +/*029a*/ 0x00040249U, +/*029b*/ 0x08010249U, +/*029c*/ 0x10010249U, +/*029d*/ 0x18020249U, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x0004024aU, +/*02a7*/ 0x0804024aU, +/*02a8*/ 0x1001024aU, +/*02a9*/ 0x1801024aU, +/*02aa*/ 0xffffffffU, +/*02ab*/ 0x0001024bU, +/*02ac*/ 0x0801024bU, +/*02ad*/ 0xffffffffU, +/*02ae*/ 0x1001024bU, +/*02af*/ 0x1801024bU, +/*02b0*/ 0x0001024cU, +/*02b1*/ 0x0804024cU, +/*02b2*/ 0x1004024cU, +/*02b3*/ 0x000a024dU, +/*02b4*/ 0x0020024eU, +/*02b5*/ 0x0004024fU, +/*02b6*/ 0x0808024fU, +/*02b7*/ 0xffffffffU, +/*02b8*/ 0xffffffffU, +/*02b9*/ 0xffffffffU, +/*02ba*/ 0xffffffffU, +/*02bb*/ 0xffffffffU, +/*02bc*/ 0xffffffffU, +/*02bd*/ 0x1002024fU, +/*02be*/ 0x1802024fU, +/*02bf*/ 0x00200250U, +/*02c0*/ 0x00020251U, +/*02c1*/ 0x08100251U, +/*02c2*/ 0x00100252U, +/*02c3*/ 0x10040252U, +/*02c4*/ 0x18040252U, +/*02c5*/ 0x00050253U, +/*02c6*/ 0x08050253U, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x10010253U, +/*02cc*/ 0x18010253U, +/*02cd*/ 0x00080254U, +/*02ce*/ 0x08080254U, +/*02cf*/ 0x10080254U, +/*02d0*/ 0x18080254U, +/*02d1*/ 0x00080255U, +/*02d2*/ 0x08080255U, +/*02d3*/ 0x10080255U, +/*02d4*/ 0x18080255U, +/*02d5*/ 0x00080256U, +/*02d6*/ 0x08080256U, +/*02d7*/ 0x10080256U, +/*02d8*/ 0xffffffffU, +/*02d9*/ 0xffffffffU, +/*02da*/ 0xffffffffU, +/*02db*/ 0xffffffffU, +/*02dc*/ 0xffffffffU, +/*02dd*/ 0xffffffffU, +/*02de*/ 0x18030256U, +/*02df*/ 0x00010257U, +/*02e0*/ 0x08020257U, +/*02e1*/ 0x10010257U, +/*02e2*/ 0x18040257U, +/*02e3*/ 0x00020258U, +/*02e4*/ 0x08010258U, +/*02e5*/ 0x10010258U, +/*02e6*/ 0xffffffffU, +/*02e7*/ 0x18010258U, +/*02e8*/ 0x00040259U, +/*02e9*/ 0x08080259U, +/*02ea*/ 0x100a0259U, +/*02eb*/ 0x000a025aU, +/*02ec*/ 0x100a025aU, +/*02ed*/ 0x000a025bU, +/*02ee*/ 0x100a025bU, +/*02ef*/ 0x000a025cU, +/*02f0*/ 0x0020025dU, +/*02f1*/ 0x0020025eU, +/*02f2*/ 0x0001025fU, +/*02f3*/ 0xffffffffU, +/*02f4*/ 0xffffffffU, +/*02f5*/ 0xffffffffU, +/*02f6*/ 0x0802025fU, +/*02f7*/ 0x1002025fU, +/*02f8*/ 0x00100260U, +/*02f9*/ 0x10050260U, +/*02fa*/ 0x18060260U, +/*02fb*/ 0x00050261U, +/*02fc*/ 0x08050261U, +/*02fd*/ 0x100e0261U, +/*02fe*/ 0x00050262U, +/*02ff*/ 0x080e0262U, +/*0300*/ 0x18050262U, +/*0301*/ 0x000e0263U, +/*0302*/ 0x10050263U, +/*0303*/ 0x18010263U, +/*0304*/ 0x00050264U, +/*0305*/ 0x08050264U, +/*0306*/ 0x100a0264U, +/*0307*/ 0x000a0265U, +/*0308*/ 0x10050265U, +/*0309*/ 0x18050265U, +/*030a*/ 0x000a0266U, +/*030b*/ 0x100a0266U, +/*030c*/ 0x00050267U, +/*030d*/ 0x08050267U, +/*030e*/ 0x100a0267U, +/*030f*/ 0x000a0268U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070268U, +/*0317*/ 0x18070268U, +/*0318*/ 0x00040269U, +/*0319*/ 0x08040269U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040269U, +/*031e*/ 0x18080269U, +/*031f*/ 0x0008026aU, +/*0320*/ 0x0804026aU, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x1004026aU, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x1804026aU, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x0004026bU, +/*032d*/ 0x0805026bU, +/*032e*/ 0x1007026bU, +/*032f*/ 0x1808026bU, +/*0330*/ 0x0010026cU, +/*0331*/ 0x1008026cU, +/*0332*/ 0x0010026dU, +/*0333*/ 0x1008026dU, +/*0334*/ 0x0010026eU, +/*0335*/ 0x1008026eU, +/*0336*/ 0x1808026eU, +/*0337*/ 0x0001026fU, +/*0338*/ 0x0801026fU, +/*0339*/ 0x1006026fU, +/*033a*/ 0x1806026fU, +/*033b*/ 0x00060270U, +/*033c*/ 0xffffffffU, +/*033d*/ 0x08010270U, +/*033e*/ 0x10030270U, +/*033f*/ 0xffffffffU, +/*0340*/ 0xffffffffU, +/*0341*/ 0xffffffffU, +/*0342*/ 0x000a0271U, +/*0343*/ 0x100a0271U, +/*0344*/ 0x00040272U, +/*0345*/ 0x08010272U, +/*0346*/ 0x10040272U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070272U, +/*034e*/ 0x00070273U, +/*034f*/ 0x08050273U, +/*0350*/ 0x10050273U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040273U, +/*0355*/ 0x00010274U, +/*0356*/ 0x08010274U, +/*0357*/ 0x10020274U, +/*0358*/ 0x18080274U, +/*0359*/ 0x00200275U, +/*035a*/ 0x00200276U, +/*035b*/ 0x00100277U, +/*035c*/ 0xffffffffU, +/*035d*/ 0xffffffffU, +/*035e*/ 0xffffffffU, +/*035f*/ 0x10020277U, +/*0360*/ 0x18010277U, +/*0361*/ 0xffffffffU, +/*0362*/ 0x00020278U, +/*0363*/ 0x08100278U, +/*0364*/ 0x00100279U, +/*0365*/ 0x10100279U, +/*0366*/ 0x0008027aU, +/*0367*/ 0x0808027aU, +/*0368*/ 0x1008027aU, +/*0369*/ 0xffffffffU, +/*036a*/ 0x0010027bU, +/*036b*/ 0x1010027bU, +/*036c*/ 0x0010027cU, +/*036d*/ 0x1008027cU, +/*036e*/ 0x1808027cU, +/*036f*/ 0x0008027dU, +/*0370*/ 0xffffffffU, +/*0371*/ 0x0810027dU, +/*0372*/ 0x0010027eU, +/*0373*/ 0x1010027eU, +/*0374*/ 0x0008027fU, +/*0375*/ 0x0808027fU, +/*0376*/ 0x1008027fU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1808027fU, +/*0379*/ 0x00100280U, +/*037a*/ 0x10100280U, +/*037b*/ 0x00100281U, +/*037c*/ 0x10080281U, +/*037d*/ 0x18080281U, +/*037e*/ 0x00080282U, +/*037f*/ 0xffffffffU, +/*0380*/ 0x08100282U, +/*0381*/ 0x00100283U, +/*0382*/ 0x10100283U, +/*0383*/ 0x00080284U, +/*0384*/ 0x08080284U, +/*0385*/ 0x10080284U, +/*0386*/ 0xffffffffU, +/*0387*/ 0x00100285U, +/*0388*/ 0x10100285U, +/*0389*/ 0x00100286U, +/*038a*/ 0x10080286U, +/*038b*/ 0x18080286U, +/*038c*/ 0x00080287U, +/*038d*/ 0xffffffffU, +/*038e*/ 0x08080287U, +/*038f*/ 0x10100287U, +/*0390*/ 0x00100288U, +/*0391*/ 0x10100288U, +/*0392*/ 0x00080289U, +/*0393*/ 0x08080289U, +/*0394*/ 0x10080289U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x0010028aU, +/*0397*/ 0x1010028aU, +/*0398*/ 0x0010028bU, +/*0399*/ 0x1008028bU, +/*039a*/ 0x1808028bU, +/*039b*/ 0x0008028cU, +/*039c*/ 0xffffffffU, +/*039d*/ 0x0810028cU, +/*039e*/ 0x0010028dU, +/*039f*/ 0x1010028dU, +/*03a0*/ 0x0008028eU, +/*03a1*/ 0x0808028eU, +/*03a2*/ 0x1008028eU, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x1808028eU, +/*03a5*/ 0x0010028fU, +/*03a6*/ 0x1010028fU, +/*03a7*/ 0x00100290U, +/*03a8*/ 0x10080290U, +/*03a9*/ 0x18080290U, +/*03aa*/ 0x00080291U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x08100291U, +/*03ad*/ 0x00100292U, +/*03ae*/ 0x10100292U, +/*03af*/ 0x00080293U, +/*03b0*/ 0x08080293U, +/*03b1*/ 0x10080293U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x00100294U, +/*03b4*/ 0x10100294U, +/*03b5*/ 0x00100295U, +/*03b6*/ 0x10080295U, +/*03b7*/ 0x18080295U, +/*03b8*/ 0x00080296U, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x08080296U, +/*03bb*/ 0x10020296U, +/*03bc*/ 0x18030296U, +/*03bd*/ 0x000a0297U, +/*03be*/ 0x100a0297U, +/*03bf*/ 0x000a0298U, +/*03c0*/ 0x10050298U, +/*03c1*/ 0x18040298U, +/*03c2*/ 0x00080299U, +/*03c3*/ 0x08080299U, +/*03c4*/ 0x10060299U, +/*03c5*/ 0x18060299U, +/*03c6*/ 0x0011029aU, +/*03c7*/ 0x1808029aU, +/*03c8*/ 0x0004029bU, +/*03c9*/ 0x0806029bU, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x1006029bU, +/*03cc*/ 0x1808029bU, +/*03cd*/ 0x0008029cU, +/*03ce*/ 0x0804029cU, +/*03cf*/ 0x1008029cU, +/*03d0*/ 0x1808029cU, +/*03d1*/ 0x0006029dU, +/*03d2*/ 0x0806029dU, +/*03d3*/ 0x0011029eU, +/*03d4*/ 0x1808029eU, +/*03d5*/ 0x0004029fU, +/*03d6*/ 0x0806029fU, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x1006029fU, +/*03d9*/ 0x1808029fU, +/*03da*/ 0x000802a0U, +/*03db*/ 0x080402a0U, +/*03dc*/ 0x100802a0U, +/*03dd*/ 0x180802a0U, +/*03de*/ 0x000602a1U, +/*03df*/ 0x080602a1U, +/*03e0*/ 0x001102a2U, +/*03e1*/ 0x180802a2U, +/*03e2*/ 0x000402a3U, +/*03e3*/ 0x080602a3U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x100602a3U, +/*03e6*/ 0x180802a3U, +/*03e7*/ 0x000802a4U, +/*03e8*/ 0x080402a4U, +/*03e9*/ 0x100402a4U, +/*03ea*/ 0x180402a4U, +/*03eb*/ 0x000402a5U, +/*03ec*/ 0x080402a5U, +/*03ed*/ 0x100402a5U, +/*03ee*/ 0x180402a5U, +/*03ef*/ 0x000402a6U, +/*03f0*/ 0x080402a6U, +/*03f1*/ 0x100402a6U, +/*03f2*/ 0x180402a6U, +/*03f3*/ 0x000402a7U, +/*03f4*/ 0x080402a7U, +/*03f5*/ 0x100402a7U, +/*03f6*/ 0x180402a7U, +/*03f7*/ 0x000402a8U, +/*03f8*/ 0x080402a8U, +/*03f9*/ 0x100402a8U, +/*03fa*/ 0x180402a8U, +/*03fb*/ 0x000402a9U, +/*03fc*/ 0x081202a9U, +/*03fd*/ 0x001102aaU, +/*03fe*/ 0x001202abU, +/*03ff*/ 0x002002acU, +/*0400*/ 0x002002adU, +/*0401*/ 0x002002aeU, +/*0402*/ 0x002002afU, +/*0403*/ 0x002002b0U, +/*0404*/ 0x002002b1U, +/*0405*/ 0x002002b2U, +/*0406*/ 0x002002b3U, +/*0407*/ 0x002002b4U, +/*0408*/ 0x000302b5U, +/*0409*/ 0x080502b5U, +/*040a*/ 0x100502b5U, +/*040b*/ 0x180102b5U, +/*040c*/ 0x000502b6U, +/*040d*/ 0x080502b6U, +/*040e*/ 0x100502b6U, +/*040f*/ 0x180502b6U, +/*0410*/ 0x000502b7U, +/*0411*/ 0x080502b7U, +/*0412*/ 0x100502b7U, +/*0413*/ 0x180502b7U, +/*0414*/ 0x000502b8U, +/*0415*/ 0x080502b8U, +/*0416*/ 0x100502b8U, +/*0417*/ 0x180502b8U, +/*0418*/ 0x000502b9U, +/*0419*/ 0x080502b9U, +/*041a*/ 0x100502b9U, +/*041b*/ 0x180502b9U, +/*041c*/ 0x000502baU, +/*041d*/ 0x080502baU, +/*041e*/ 0x100502baU, +/*041f*/ 0x180502baU, +/*0420*/ 0x000502bbU, +/*0421*/ 0x080502bbU, +/*0422*/ 0x100102bbU, +/*0423*/ 0x180202bbU, +/*0424*/ 0x000202bcU, +/*0425*/ 0x080202bcU, +/*0426*/ 0x100202bcU, +/*0427*/ 0x180102bcU, +/*0428*/ 0x000402bdU, +/*0429*/ 0x081002bdU, +/*042a*/ 0x002002beU, +/*042b*/ 0x001002bfU, +/*042c*/ 0x002002c0U, +/*042d*/ 0x001002c1U, +/*042e*/ 0x002002c2U, +/*042f*/ 0x000702c3U, +/*0430*/ 0x080102c3U, +/*0431*/ 0x100202c3U, +/*0432*/ 0x180602c3U, +/*0433*/ 0x000102c4U, +/*0434*/ 0x080102c4U, +/*0435*/ 0x002002c5U, +/*0436*/ 0x000302c6U, +/*0437*/ 0x002002c7U, +/*0438*/ 0x002002c8U, +/*0439*/ 0xffffffffU, +/*043a*/ 0xffffffffU, +/*043b*/ 0xffffffffU, +/*043c*/ 0xffffffffU, +/*043d*/ 0xffffffffU, +/*043e*/ 0xffffffffU, +/*043f*/ 0xffffffffU, +/*0440*/ 0xffffffffU, +/*0441*/ 0xffffffffU, +/*0442*/ 0xffffffffU, +/*0443*/ 0xffffffffU, +/*0444*/ 0xffffffffU, +/*0445*/ 0xffffffffU, +/*0446*/ 0xffffffffU, +/*0447*/ 0xffffffffU, +/*0448*/ 0xffffffffU, +/*0449*/ 0xffffffffU, +/*044a*/ 0xffffffffU, +/*044b*/ 0xffffffffU, +/*044c*/ 0xffffffffU, +/*044d*/ 0xffffffffU, +/*044e*/ 0xffffffffU, +/*044f*/ 0xffffffffU, +/*0450*/ 0xffffffffU, +/*0451*/ 0xffffffffU, +/*0452*/ 0xffffffffU, +/*0453*/ 0xffffffffU, +/*0454*/ 0xffffffffU, +/*0455*/ 0xffffffffU, +/*0456*/ 0xffffffffU, +/*0457*/ 0xffffffffU, +/*0458*/ 0xffffffffU, +/*0459*/ 0xffffffffU, +/*045a*/ 0xffffffffU, +/*045b*/ 0xffffffffU, +/*045c*/ 0xffffffffU, +/*045d*/ 0xffffffffU, +/*045e*/ 0xffffffffU, +/*045f*/ 0x000402c9U, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0xffffffffU, +/*0465*/ 0xffffffffU, +/*0466*/ 0xffffffffU, +/*0467*/ 0xffffffffU, +/*0468*/ 0xffffffffU, +/*0469*/ 0xffffffffU, +/*046a*/ 0xffffffffU, +/*046b*/ 0xffffffffU, +/*046c*/ 0xffffffffU, +/*046d*/ 0xffffffffU, +/*046e*/ 0xffffffffU, +/*046f*/ 0xffffffffU, +/*0470*/ 0xffffffffU, +/*0471*/ 0xffffffffU, +/*0472*/ 0xffffffffU, +/*0473*/ 0xffffffffU, +/*0474*/ 0xffffffffU, +/*0475*/ 0xffffffffU, +/*0476*/ 0xffffffffU, +/*0477*/ 0xffffffffU, +/*0478*/ 0xffffffffU, +/*0479*/ 0xffffffffU, +/*047a*/ 0xffffffffU, +/*047b*/ 0xffffffffU, +/*047c*/ 0xffffffffU, +/*047d*/ 0xffffffffU, +/*047e*/ 0xffffffffU, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200400U, +/*0001*/ 0x00040401U, +/*0002*/ 0x080b0401U, +/*0003*/ 0x000a0402U, +/*0004*/ 0x10020402U, +/*0005*/ 0x18010402U, +/*0006*/ 0x00050403U, +/*0007*/ 0x08050403U, +/*0008*/ 0x10050403U, +/*0009*/ 0x18050403U, +/*000a*/ 0x00050404U, +/*000b*/ 0x08050404U, +/*000c*/ 0x10050404U, +/*000d*/ 0x18050404U, +/*000e*/ 0x00050405U, +/*000f*/ 0x08040405U, +/*0010*/ 0x10030405U, +/*0011*/ 0x00180406U, +/*0012*/ 0x18030406U, +/*0013*/ 0x00180407U, +/*0014*/ 0x18020407U, +/*0015*/ 0x00010408U, +/*0016*/ 0x08020408U, +/*0017*/ 0x10010408U, +/*0018*/ 0x18010408U, +/*0019*/ 0x00020409U, +/*001a*/ 0x08040409U, +/*001b*/ 0x10040409U, +/*001c*/ 0x18040409U, +/*001d*/ 0xffffffffU, +/*001e*/ 0x0004040aU, +/*001f*/ 0xffffffffU, +/*0020*/ 0xffffffffU, +/*0021*/ 0x0809040aU, +/*0022*/ 0x1801040aU, +/*0023*/ 0x0020040bU, +/*0024*/ 0x001c040cU, +/*0025*/ 0x0001040dU, +/*0026*/ 0x0807040dU, +/*0027*/ 0x1009040dU, +/*0028*/ 0x000a040eU, +/*0029*/ 0x1005040eU, +/*002a*/ 0x1801040eU, +/*002b*/ 0x1001040fU, +/*002c*/ 0x1802040fU, +/*002d*/ 0x0009040fU, +/*002e*/ 0x00090410U, +/*002f*/ 0x10020410U, +/*0030*/ 0x00200411U, +/*0031*/ 0x00010412U, +/*0032*/ 0x08020412U, +/*0033*/ 0xffffffffU, +/*0034*/ 0xffffffffU, +/*0035*/ 0xffffffffU, +/*0036*/ 0xffffffffU, +/*0037*/ 0x00200413U, +/*0038*/ 0x00200414U, +/*0039*/ 0x00200415U, +/*003a*/ 0x00200416U, +/*003b*/ 0x00030417U, +/*003c*/ 0x08010417U, +/*003d*/ 0x10040417U, +/*003e*/ 0x18030417U, +/*003f*/ 0x00040418U, +/*0040*/ 0x08040418U, +/*0041*/ 0x10040418U, +/*0042*/ 0x18040418U, +/*0043*/ 0x00010419U, +/*0044*/ 0x08010419U, +/*0045*/ 0x10060419U, +/*0046*/ 0x18040419U, +/*0047*/ 0xffffffffU, +/*0048*/ 0x0006041aU, +/*0049*/ 0x0804041aU, +/*004a*/ 0x1006041aU, +/*004b*/ 0x1804041aU, +/*004c*/ 0x0002041bU, +/*004d*/ 0x0805041bU, +/*004e*/ 0x1008041bU, +/*004f*/ 0xffffffffU, +/*0050*/ 0x1806041bU, +/*0051*/ 0x0003041cU, +/*0052*/ 0x080b041cU, +/*0053*/ 0x1804041cU, +/*0054*/ 0x0004041dU, +/*0055*/ 0x0804041dU, +/*0056*/ 0x1001041dU, +/*0057*/ 0xffffffffU, +/*0058*/ 0x0009041eU, +/*0059*/ 0x0020041fU, +/*005a*/ 0x00200420U, +/*005b*/ 0x00200421U, +/*005c*/ 0x00200422U, +/*005d*/ 0x00100423U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010423U, +/*0060*/ 0x18060423U, +/*0061*/ 0x00080424U, +/*0062*/ 0x00200425U, +/*0063*/ 0x00100426U, +/*0064*/ 0x100a0426U, +/*0065*/ 0x00060427U, +/*0066*/ 0x08070427U, +/*0067*/ 0x10080427U, +/*0068*/ 0x18080427U, +/*0069*/ 0x000a0428U, +/*006a*/ 0x10070428U, +/*006b*/ 0x18080428U, +/*006c*/ 0x00080429U, +/*006d*/ 0x08030429U, +/*006e*/ 0x100a0429U, +/*006f*/ 0x000a042aU, +/*0070*/ 0x0011042bU, +/*0071*/ 0x0009042cU, +/*0072*/ 0x1009042cU, +/*0073*/ 0x0010042dU, +/*0074*/ 0x100e042dU, +/*0075*/ 0x000e042eU, +/*0076*/ 0x0012042fU, +/*0077*/ 0x000a0430U, +/*0078*/ 0x100a0430U, +/*0079*/ 0x00020431U, +/*007a*/ 0x00200432U, +/*007b*/ 0x000b0433U, +/*007c*/ 0x100b0433U, +/*007d*/ 0x00200434U, +/*007e*/ 0x00120435U, +/*007f*/ 0x00200436U, +/*0080*/ 0x00200437U, +/*0081*/ 0x00080438U, +/*0082*/ 0x08010438U, +/*0083*/ 0x10010438U, +/*0084*/ 0x18010438U, +/*0085*/ 0x00080439U, +/*0086*/ 0x080c0439U, +/*0087*/ 0x000c043aU, +/*0088*/ 0x100c043aU, +/*0089*/ 0x000c043bU, +/*008a*/ 0x100c043bU, +/*008b*/ 0x000c043cU, +/*008c*/ 0x100c043cU, +/*008d*/ 0x000c043dU, +/*008e*/ 0x100c043dU, +/*008f*/ 0x000c043eU, +/*0090*/ 0x100c043eU, +/*0091*/ 0x000b043fU, +/*0092*/ 0x1009043fU, +/*0093*/ 0x00010440U, +/*0094*/ 0x000b0441U, +/*0095*/ 0x100b0441U, +/*0096*/ 0x000b0442U, +/*0097*/ 0x100b0442U, +/*0098*/ 0x000b0443U, +/*0099*/ 0x100b0443U, +/*009a*/ 0x000b0444U, +/*009b*/ 0x100b0444U, +/*009c*/ 0x000b0445U, +/*009d*/ 0x100a0445U, +/*009e*/ 0x00020446U, +/*009f*/ 0x080a0446U, +/*00a0*/ 0x000a0447U, +/*00a1*/ 0x100a0447U, +/*00a2*/ 0x000a0448U, +/*00a3*/ 0x100a0448U, +/*00a4*/ 0x000a0449U, +/*00a5*/ 0x100a0449U, +/*00a6*/ 0x000a044aU, +/*00a7*/ 0x100a044aU, +/*00a8*/ 0x000a044bU, +/*00a9*/ 0x100a044bU, +/*00aa*/ 0x000a044cU, +/*00ab*/ 0x100a044cU, +/*00ac*/ 0x000a044dU, +/*00ad*/ 0x100a044dU, +/*00ae*/ 0x000a044eU, +/*00af*/ 0x100a044eU, +/*00b0*/ 0x000a044fU, +/*00b1*/ 0x100a044fU, +/*00b2*/ 0x000a0450U, +/*00b3*/ 0x100a0450U, +/*00b4*/ 0x000a0451U, +/*00b5*/ 0x100a0451U, +/*00b6*/ 0x000a0452U, +/*00b7*/ 0x100a0452U, +/*00b8*/ 0x000a0453U, +/*00b9*/ 0x100a0453U, +/*00ba*/ 0x000a0454U, +/*00bb*/ 0x10040454U, +/*00bc*/ 0x18030454U, +/*00bd*/ 0x000a0455U, +/*00be*/ 0x100a0455U, +/*00bf*/ 0x00010456U, +/*00c0*/ 0x080a0456U, +/*00c1*/ 0x18040456U, +/*00c2*/ 0x000b0457U, +/*00c3*/ 0x100a0457U, +/*00c4*/ 0x00030458U, +/*00c5*/ 0x00080459U, +/*00c6*/ 0x08080459U, +/*00c7*/ 0x10080459U, +/*00c8*/ 0x18080459U, +/*00c9*/ 0x0008045aU, +/*00ca*/ 0xffffffffU, +/*00cb*/ 0x0808045aU, +/*00cc*/ 0x1001045aU, +/*00cd*/ 0x1808045aU, +/*00ce*/ 0x0008045bU, +/*00cf*/ 0x0802045bU, +/*00d0*/ 0x1002045bU, +/*00d1*/ 0x1805045bU, +/*00d2*/ 0x0005045cU, +/*00d3*/ 0xffffffffU, +/*00d4*/ 0x0804045cU, +/*00d5*/ 0x100a045cU, +/*00d6*/ 0x0006045dU, +/*00d7*/ 0x0808045dU, +/*00d8*/ 0x1008045dU, +/*00d9*/ 0x1804045dU, +/*00da*/ 0x0004045eU, +/*00db*/ 0x0805045eU, +/*00dc*/ 0x1004045eU, +/*00dd*/ 0x1805045eU, +/*00de*/ 0x000a045fU, +/*00df*/ 0x100a045fU, +/*00e0*/ 0x00080460U, +/*00e1*/ 0xffffffffU, +/*00e2*/ 0x08040460U, +/*00e3*/ 0xffffffffU, +/*00e4*/ 0xffffffffU, +/*00e5*/ 0x00050600U, +/*00e6*/ 0x08050600U, +/*00e7*/ 0x10050600U, +/*00e8*/ 0x18050600U, +/*00e9*/ 0x00050601U, +/*00ea*/ 0x08050601U, +/*00eb*/ 0x100b0601U, +/*00ec*/ 0x00010602U, +/*00ed*/ 0x08030602U, +/*00ee*/ 0x00200603U, +/*00ef*/ 0x00100604U, +/*00f0*/ 0x10040604U, +/*00f1*/ 0x000a0605U, +/*00f2*/ 0x10090605U, +/*00f3*/ 0x00080606U, +/*00f4*/ 0x08030606U, +/*00f5*/ 0x10030606U, +/*00f6*/ 0x18010606U, +/*00f7*/ 0x00010607U, +/*00f8*/ 0x08070607U, +/*00f9*/ 0x10070607U, +/*00fa*/ 0x18050607U, +/*00fb*/ 0x00010608U, +/*00fc*/ 0x08020608U, +/*00fd*/ 0x10030608U, +/*00fe*/ 0x18010608U, +/*00ff*/ 0x000f0609U, +/*0100*/ 0x0020060aU, +/*0101*/ 0x0020060bU, +/*0102*/ 0x000b060cU, +/*0103*/ 0x100b060cU, +/*0104*/ 0x000b060dU, +/*0105*/ 0x0018060eU, +/*0106*/ 0x0018060fU, +/*0107*/ 0xffffffffU, +/*0108*/ 0xffffffffU, +/*0109*/ 0xffffffffU, +/*010a*/ 0xffffffffU, +/*010b*/ 0xffffffffU, +/*010c*/ 0x1802060fU, +/*010d*/ 0x00020610U, +/*010e*/ 0x08040610U, +/*010f*/ 0x10040610U, +/*0110*/ 0x18010610U, +/*0111*/ 0x00010611U, +/*0112*/ 0x08010611U, +/*0113*/ 0x10030611U, +/*0114*/ 0x00200612U, +/*0115*/ 0x00200613U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140614U, +/*0118*/ 0x00140615U, +/*0119*/ 0x00140616U, +/*011a*/ 0x00140617U, +/*011b*/ 0x00140618U, +/*011c*/ 0x00140619U, +/*011d*/ 0x0014061aU, +/*011e*/ 0x0014061bU, +/*011f*/ 0x0018061cU, +/*0120*/ 0x000a061dU, +/*0121*/ 0x1006061dU, +/*0122*/ 0x1806061dU, +/*0123*/ 0x0006061eU, +/*0124*/ 0xffffffffU, +/*0125*/ 0x0806061eU, +/*0126*/ 0x0008061fU, +/*0127*/ 0x080b061fU, +/*0128*/ 0x000b0620U, +/*0129*/ 0x100b0620U, +/*012a*/ 0x000b0621U, +/*012b*/ 0x100b0621U, +/*012c*/ 0x000b0622U, +/*012d*/ 0x10040622U, +/*012e*/ 0x000a0623U, +/*012f*/ 0x10060623U, +/*0130*/ 0x18080623U, +/*0131*/ 0x00080624U, +/*0132*/ 0x08040624U, +/*0133*/ 0x00020680U, +/*0134*/ 0x00010681U, +/*0135*/ 0x08010681U, +/*0136*/ 0x10020681U, +/*0137*/ 0x18050681U, +/*0138*/ 0x00050682U, +/*0139*/ 0x08050682U, +/*013a*/ 0x10050682U, +/*013b*/ 0x000b0683U, +/*013c*/ 0x10050683U, +/*013d*/ 0x18010683U, +/*013e*/ 0x00010684U, +/*013f*/ 0xffffffffU, +/*0140*/ 0x08010684U, +/*0141*/ 0x10010684U, +/*0142*/ 0x18040684U, +/*0143*/ 0x000b0685U, +/*0144*/ 0x100b0685U, +/*0145*/ 0x000b0686U, +/*0146*/ 0x10040686U, +/*0147*/ 0x000b0687U, +/*0148*/ 0x10040687U, +/*0149*/ 0x18010687U, +/*014a*/ 0x00010688U, +/*014b*/ 0x08010688U, +/*014c*/ 0x00200689U, +/*014d*/ 0x0020068aU, +/*014e*/ 0x0008068bU, +/*014f*/ 0x080a068bU, +/*0150*/ 0x1805068bU, +/*0151*/ 0x000a068cU, +/*0152*/ 0x1003068cU, +/*0153*/ 0x1803068cU, +/*0154*/ 0x0001068dU, +/*0155*/ 0x0802068dU, +/*0156*/ 0x1001068dU, +/*0157*/ 0x1801068dU, +/*0158*/ 0x0001068eU, +/*0159*/ 0x0802068eU, +/*015a*/ 0x1001068eU, +/*015b*/ 0x0004068fU, +/*015c*/ 0x0804068fU, +/*015d*/ 0x1004068fU, +/*015e*/ 0x1804068fU, +/*015f*/ 0x00010690U, +/*0160*/ 0x08010690U, +/*0161*/ 0x10010690U, +/*0162*/ 0x00200691U, +/*0163*/ 0x00200692U, +/*0164*/ 0x00200693U, +/*0165*/ 0x00200694U, +/*0166*/ 0xffffffffU, +/*0167*/ 0x1801068eU, +/*0168*/ 0x000d0696U, +/*0169*/ 0x100d0696U, +/*016a*/ 0x000d0697U, +/*016b*/ 0x00050698U, +/*016c*/ 0x00010699U, +/*016d*/ 0x080e0699U, +/*016e*/ 0x000e069aU, +/*016f*/ 0x100e069aU, +/*0170*/ 0x000e069bU, +/*0171*/ 0x100e069bU, +/*0172*/ 0x0004069cU, +/*0173*/ 0x0804069cU, +/*0174*/ 0x1004069cU, +/*0175*/ 0x1804069cU, +/*0176*/ 0x0004069dU, +/*0177*/ 0x080b069dU, +/*0178*/ 0x000b069eU, +/*0179*/ 0x100b069eU, +/*017a*/ 0x000b069fU, +/*017b*/ 0xffffffffU, +/*017c*/ 0xffffffffU, +/*017d*/ 0xffffffffU, +/*017e*/ 0xffffffffU, +/*017f*/ 0x000d06a0U, +/*0180*/ 0x100d06a0U, +/*0181*/ 0x000d06a1U, +/*0182*/ 0x101006a1U, +/*0183*/ 0x00080695U, +/*0184*/ 0x08080695U, +/*0185*/ 0x001006a2U, +/*0186*/ 0x101006a2U, +/*0187*/ 0x001006a3U, +/*0188*/ 0x101006a3U, +/*0189*/ 0x001006a4U, +/*018a*/ 0x100306a4U, +/*018b*/ 0x180406a4U, +/*018c*/ 0x000106a5U, +/*018d*/ 0x080806a5U, +/*018e*/ 0x100106a5U, +/*018f*/ 0x180506a5U, +/*0190*/ 0x000106a6U, +/*0191*/ 0x081406a6U, +/*0192*/ 0x000a06a7U, +/*0193*/ 0x100c06a7U, +/*0194*/ 0x001206a8U, +/*0195*/ 0x001406a9U, +/*0196*/ 0x001206aaU, +/*0197*/ 0x001106abU, +/*0198*/ 0x001106acU, +/*0199*/ 0x001206adU, +/*019a*/ 0x001206aeU, +/*019b*/ 0x001206afU, +/*019c*/ 0x001206b0U, +/*019d*/ 0x001206b1U, +/*019e*/ 0x001206b2U, +/*019f*/ 0x001206b3U, +/*01a0*/ 0x001206b4U, +/*01a1*/ 0x001206b5U, +/*01a2*/ 0x001206b6U, +/*01a3*/ 0x000e06b7U, +/*01a4*/ 0x100d06b7U, +/*01a5*/ 0x002006b8U, +/*01a6*/ 0x001706b9U, +/*01a7*/ 0x000906baU, +/*01a8*/ 0x100106baU, +/*01a9*/ 0x180106baU, +/*01aa*/ 0x002006bbU, +/*01ab*/ 0x000806bcU, +/*01ac*/ 0x080306bcU, +/*01ad*/ 0x100306bcU, +/*01ae*/ 0x001806bdU, +/*01af*/ 0x001806beU, +/*01b0*/ 0x180706beU, +/*01b1*/ 0x000506bfU, +/*01b2*/ 0x080806bfU, +/*01b3*/ 0x100806bfU, +/*01b4*/ 0x180806bfU, +/*01b5*/ 0x000106c0U, +/*01b6*/ 0x080106c0U, +/*01b7*/ 0x002006c1U, +/*01b8*/ 0xffffffffU, +/*01b9*/ 0xffffffffU, +/*01ba*/ 0xffffffffU, +/*01bb*/ 0xffffffffU, +/*01bc*/ 0xffffffffU, +/*01bd*/ 0xffffffffU, +/*01be*/ 0xffffffffU, +/*01bf*/ 0x001006c2U, +/*01c0*/ 0x100106c2U, +/*01c1*/ 0x180106c2U, +/*01c2*/ 0x000206c3U, +/*01c3*/ 0x080406c3U, +/*01c4*/ 0x100906c3U, +/*01c5*/ 0x000706c4U, +/*01c6*/ 0x080406c4U, +/*01c7*/ 0x002006c5U, +/*01c8*/ 0x000106c6U, +/*01c9*/ 0x080206c6U, +/*01ca*/ 0x100606c6U, +/*01cb*/ 0x001006c7U, +/*01cc*/ 0x100106c7U, +/*01cd*/ 0x002006c8U, +/*01ce*/ 0x000806c9U, +/*01cf*/ 0x080106c9U, +/*01d0*/ 0x100506c9U, +/*01d1*/ 0xffffffffU, +/*01d2*/ 0x180206c9U, +/*01d3*/ 0x000106caU, +/*01d4*/ 0x002006cbU, +/*01d5*/ 0x000b06ccU, +/*01d6*/ 0x100106ccU, +/*01d7*/ 0x180306ccU, +/*01d8*/ 0x000806cdU, +/*01d9*/ 0x080206cdU, +/*01da*/ 0x100c06cdU, +/*01db*/ 0x000406ceU, +/*01dc*/ 0x080106ceU, +/*01dd*/ 0xffffffffU, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0x10010201U, +/*01e4*/ 0xffffffffU, +/*01e5*/ 0x00100202U, +/*01e6*/ 0x10080202U, +/*01e7*/ 0xffffffffU, +/*01e8*/ 0xffffffffU, +/*01e9*/ 0xffffffffU, +/*01ea*/ 0xffffffffU, +/*01eb*/ 0xffffffffU, +/*01ec*/ 0xffffffffU, +/*01ed*/ 0xffffffffU, +/*01ee*/ 0xffffffffU, +/*01ef*/ 0x00200203U, +/*01f0*/ 0x00100204U, +/*01f1*/ 0x00200205U, +/*01f2*/ 0x00100206U, +/*01f3*/ 0x00200207U, +/*01f4*/ 0x00100208U, +/*01f5*/ 0x00140209U, +/*01f6*/ 0x0020020aU, +/*01f7*/ 0x0020020bU, +/*01f8*/ 0x0020020cU, +/*01f9*/ 0x0020020dU, +/*01fa*/ 0x0014020eU, +/*01fb*/ 0x0020020fU, +/*01fc*/ 0x00200210U, +/*01fd*/ 0x00200211U, +/*01fe*/ 0x00200212U, +/*01ff*/ 0x00140213U, +/*0200*/ 0x00200214U, +/*0201*/ 0x00200215U, +/*0202*/ 0x00200216U, +/*0203*/ 0x00200217U, +/*0204*/ 0x00090218U, +/*0205*/ 0x10010218U, +/*0206*/ 0x00200219U, +/*0207*/ 0x0005021aU, +/*0208*/ 0x0801021aU, +/*0209*/ 0x1008021aU, +/*020a*/ 0x1808021aU, +/*020b*/ 0x001c021bU, +/*020c*/ 0x001c021cU, +/*020d*/ 0x001c021dU, +/*020e*/ 0x001c021eU, +/*020f*/ 0x001c021fU, +/*0210*/ 0x001c0220U, +/*0211*/ 0x001c0221U, +/*0212*/ 0x001c0222U, +/*0213*/ 0x001c0223U, +/*0214*/ 0x001c0224U, +/*0215*/ 0x001c0225U, +/*0216*/ 0x001c0226U, +/*0217*/ 0x001c0227U, +/*0218*/ 0x001c0228U, +/*0219*/ 0x001c0229U, +/*021a*/ 0x001c022aU, +/*021b*/ 0x0001022bU, +/*021c*/ 0x0801022bU, +/*021d*/ 0x1001022bU, +/*021e*/ 0x1804022bU, +/*021f*/ 0x0008022cU, +/*0220*/ 0x0808022cU, +/*0221*/ 0x1008022cU, +/*0222*/ 0x1804022cU, +/*0223*/ 0x0007022dU, +/*0224*/ 0xffffffffU, +/*0225*/ 0x0807022dU, +/*0226*/ 0x1007022dU, +/*0227*/ 0xffffffffU, +/*0228*/ 0x1807022dU, +/*0229*/ 0x0007022eU, +/*022a*/ 0xffffffffU, +/*022b*/ 0x0807022eU, +/*022c*/ 0x1002022eU, +/*022d*/ 0x1801022eU, +/*022e*/ 0x0001022fU, +/*022f*/ 0x080a022fU, +/*0230*/ 0x00140230U, +/*0231*/ 0x000a0231U, +/*0232*/ 0x00140232U, +/*0233*/ 0x000a0233U, +/*0234*/ 0x00140234U, +/*0235*/ 0x18010234U, +/*0236*/ 0x00100235U, +/*0237*/ 0x10050235U, +/*0238*/ 0x18010235U, +/*0239*/ 0x00010236U, +/*023a*/ 0x08010236U, +/*023b*/ 0x10010236U, +/*023c*/ 0x18010236U, +/*023d*/ 0x00010237U, +/*023e*/ 0x08010237U, +/*023f*/ 0x10020237U, +/*0240*/ 0x18020237U, +/*0241*/ 0x00020238U, +/*0242*/ 0x08020238U, +/*0243*/ 0x10020238U, +/*0244*/ 0x18030238U, +/*0245*/ 0x00010239U, +/*0246*/ 0x08010239U, +/*0247*/ 0x10010239U, +/*0248*/ 0x18010239U, +/*0249*/ 0xffffffffU, +/*024a*/ 0x0002023aU, +/*024b*/ 0x0801023aU, +/*024c*/ 0x1001023aU, +/*024d*/ 0xffffffffU, +/*024e*/ 0x1802023aU, +/*024f*/ 0x0001023bU, +/*0250*/ 0x0801023bU, +/*0251*/ 0xffffffffU, +/*0252*/ 0x1002023bU, +/*0253*/ 0x1801023bU, +/*0254*/ 0x0001023cU, +/*0255*/ 0xffffffffU, +/*0256*/ 0x0802023cU, +/*0257*/ 0x1007023cU, +/*0258*/ 0x1801023cU, +/*0259*/ 0x0001023dU, +/*025a*/ 0x0801023dU, +/*025b*/ 0x1001023dU, +/*025c*/ 0x1801023dU, +/*025d*/ 0x0001023eU, +/*025e*/ 0x0801023eU, +/*025f*/ 0x1001023eU, +/*0260*/ 0x1804023eU, +/*0261*/ 0x0004023fU, +/*0262*/ 0x0804023fU, +/*0263*/ 0x1001023fU, +/*0264*/ 0x1802023fU, +/*0265*/ 0x00060240U, +/*0266*/ 0x08060240U, +/*0267*/ 0x10020240U, +/*0268*/ 0x18020240U, +/*0269*/ 0x00020241U, +/*026a*/ 0xffffffffU, +/*026b*/ 0x08100241U, +/*026c*/ 0x18010241U, +/*026d*/ 0x00010242U, +/*026e*/ 0x08010242U, +/*026f*/ 0x10040242U, +/*0270*/ 0x18010242U, +/*0271*/ 0x00040243U, +/*0272*/ 0x08020243U, +/*0273*/ 0x10080243U, +/*0274*/ 0xffffffffU, +/*0275*/ 0xffffffffU, +/*0276*/ 0xffffffffU, +/*0277*/ 0x000a0244U, +/*0278*/ 0x00200245U, +/*0279*/ 0x00200246U, +/*027a*/ 0x00050247U, +/*027b*/ 0x08010247U, +/*027c*/ 0x10050247U, +/*027d*/ 0x18080247U, +/*027e*/ 0x00010248U, +/*027f*/ 0x08080248U, +/*0280*/ 0x10010248U, +/*0281*/ 0x18080248U, +/*0282*/ 0x00010249U, +/*0283*/ 0x08040249U, +/*0284*/ 0x10040249U, +/*0285*/ 0x18040249U, +/*0286*/ 0x0004024aU, +/*0287*/ 0x0804024aU, +/*0288*/ 0x1004024aU, +/*0289*/ 0x1804024aU, +/*028a*/ 0x0004024bU, +/*028b*/ 0x0804024bU, +/*028c*/ 0x1004024bU, +/*028d*/ 0x1801024bU, +/*028e*/ 0x0004024cU, +/*028f*/ 0x0804024cU, +/*0290*/ 0x1004024cU, +/*0291*/ 0x1804024cU, +/*0292*/ 0x0004024dU, +/*0293*/ 0x0804024dU, +/*0294*/ 0x1006024dU, +/*0295*/ 0x1806024dU, +/*0296*/ 0x0006024eU, +/*0297*/ 0x0806024eU, +/*0298*/ 0x1006024eU, +/*0299*/ 0x1806024eU, +/*029a*/ 0xffffffffU, +/*029b*/ 0x0001024fU, +/*029c*/ 0x0801024fU, +/*029d*/ 0x1002024fU, +/*029e*/ 0xffffffffU, +/*029f*/ 0xffffffffU, +/*02a0*/ 0xffffffffU, +/*02a1*/ 0xffffffffU, +/*02a2*/ 0xffffffffU, +/*02a3*/ 0xffffffffU, +/*02a4*/ 0xffffffffU, +/*02a5*/ 0xffffffffU, +/*02a6*/ 0x1804024fU, +/*02a7*/ 0x00040250U, +/*02a8*/ 0x08010250U, +/*02a9*/ 0x10010250U, +/*02aa*/ 0x18010250U, +/*02ab*/ 0x00010251U, +/*02ac*/ 0x08010251U, +/*02ad*/ 0x10010251U, +/*02ae*/ 0x18010251U, +/*02af*/ 0x00010252U, +/*02b0*/ 0x08010252U, +/*02b1*/ 0x10040252U, +/*02b2*/ 0x18040252U, +/*02b3*/ 0x000a0253U, +/*02b4*/ 0x00200254U, +/*02b5*/ 0x00040255U, +/*02b6*/ 0x08080255U, +/*02b7*/ 0x10020255U, +/*02b8*/ 0x18020255U, +/*02b9*/ 0x00020256U, +/*02ba*/ 0x08020256U, +/*02bb*/ 0x10020256U, +/*02bc*/ 0x18020256U, +/*02bd*/ 0xffffffffU, +/*02be*/ 0xffffffffU, +/*02bf*/ 0x00200257U, +/*02c0*/ 0x00020258U, +/*02c1*/ 0x08100258U, +/*02c2*/ 0x00100259U, +/*02c3*/ 0x10040259U, +/*02c4*/ 0x18040259U, +/*02c5*/ 0x0005025aU, +/*02c6*/ 0x0805025aU, +/*02c7*/ 0x0020025bU, +/*02c8*/ 0x0020025cU, +/*02c9*/ 0x0020025dU, +/*02ca*/ 0x0020025eU, +/*02cb*/ 0x0001025fU, +/*02cc*/ 0x0801025fU, +/*02cd*/ 0x1007025fU, +/*02ce*/ 0x1807025fU, +/*02cf*/ 0x00070260U, +/*02d0*/ 0x08070260U, +/*02d1*/ 0x10070260U, +/*02d2*/ 0x18070260U, +/*02d3*/ 0x00070261U, +/*02d4*/ 0x08070261U, +/*02d5*/ 0x10070261U, +/*02d6*/ 0x18070261U, +/*02d7*/ 0x00070262U, +/*02d8*/ 0x08070262U, +/*02d9*/ 0x10070262U, +/*02da*/ 0x18070262U, +/*02db*/ 0x00030263U, +/*02dc*/ 0x08030263U, +/*02dd*/ 0x10030263U, +/*02de*/ 0xffffffffU, +/*02df*/ 0x18010263U, +/*02e0*/ 0x00020264U, +/*02e1*/ 0x08010264U, +/*02e2*/ 0x10040264U, +/*02e3*/ 0x18020264U, +/*02e4*/ 0x00010265U, +/*02e5*/ 0x08010265U, +/*02e6*/ 0x10010265U, +/*02e7*/ 0x18010265U, +/*02e8*/ 0x00040266U, +/*02e9*/ 0x08080266U, +/*02ea*/ 0x100a0266U, +/*02eb*/ 0x000a0267U, +/*02ec*/ 0x100a0267U, +/*02ed*/ 0x000a0268U, +/*02ee*/ 0x100a0268U, +/*02ef*/ 0x000a0269U, +/*02f0*/ 0x0020026aU, +/*02f1*/ 0x0020026bU, +/*02f2*/ 0x0001026cU, +/*02f3*/ 0x0802026cU, +/*02f4*/ 0x1002026cU, +/*02f5*/ 0x1802026cU, +/*02f6*/ 0xffffffffU, +/*02f7*/ 0x0002026dU, +/*02f8*/ 0x0810026dU, +/*02f9*/ 0x1805026dU, +/*02fa*/ 0x0006026eU, +/*02fb*/ 0x0805026eU, +/*02fc*/ 0x1005026eU, +/*02fd*/ 0x000e026fU, +/*02fe*/ 0x1005026fU, +/*02ff*/ 0x000e0270U, +/*0300*/ 0x10050270U, +/*0301*/ 0x000e0271U, +/*0302*/ 0x10050271U, +/*0303*/ 0x18010271U, +/*0304*/ 0x00050272U, +/*0305*/ 0x08050272U, +/*0306*/ 0x100a0272U, +/*0307*/ 0x000a0273U, +/*0308*/ 0x10050273U, +/*0309*/ 0x18050273U, +/*030a*/ 0x000a0274U, +/*030b*/ 0x100a0274U, +/*030c*/ 0x00050275U, +/*030d*/ 0x08050275U, +/*030e*/ 0x100a0275U, +/*030f*/ 0x000a0276U, +/*0310*/ 0xffffffffU, +/*0311*/ 0xffffffffU, +/*0312*/ 0xffffffffU, +/*0313*/ 0xffffffffU, +/*0314*/ 0xffffffffU, +/*0315*/ 0xffffffffU, +/*0316*/ 0x10070276U, +/*0317*/ 0x18070276U, +/*0318*/ 0x00040277U, +/*0319*/ 0x08040277U, +/*031a*/ 0xffffffffU, +/*031b*/ 0xffffffffU, +/*031c*/ 0xffffffffU, +/*031d*/ 0x10040277U, +/*031e*/ 0x18080277U, +/*031f*/ 0x00080278U, +/*0320*/ 0x08040278U, +/*0321*/ 0xffffffffU, +/*0322*/ 0xffffffffU, +/*0323*/ 0xffffffffU, +/*0324*/ 0x10040278U, +/*0325*/ 0xffffffffU, +/*0326*/ 0xffffffffU, +/*0327*/ 0xffffffffU, +/*0328*/ 0x18040278U, +/*0329*/ 0xffffffffU, +/*032a*/ 0xffffffffU, +/*032b*/ 0xffffffffU, +/*032c*/ 0x00040279U, +/*032d*/ 0x08050279U, +/*032e*/ 0x10070279U, +/*032f*/ 0x18080279U, +/*0330*/ 0x0010027aU, +/*0331*/ 0x1008027aU, +/*0332*/ 0x0010027bU, +/*0333*/ 0x1008027bU, +/*0334*/ 0x0010027cU, +/*0335*/ 0x1008027cU, +/*0336*/ 0x1808027cU, +/*0337*/ 0x0001027dU, +/*0338*/ 0x0801027dU, +/*0339*/ 0x1006027dU, +/*033a*/ 0x1806027dU, +/*033b*/ 0x0006027eU, +/*033c*/ 0x0801027eU, +/*033d*/ 0x1001027eU, +/*033e*/ 0x1803027eU, +/*033f*/ 0x000a027fU, +/*0340*/ 0x100a027fU, +/*0341*/ 0x000a0280U, +/*0342*/ 0xffffffffU, +/*0343*/ 0x100a0280U, +/*0344*/ 0x00040281U, +/*0345*/ 0x08010281U, +/*0346*/ 0x10040281U, +/*0347*/ 0xffffffffU, +/*0348*/ 0xffffffffU, +/*0349*/ 0xffffffffU, +/*034a*/ 0xffffffffU, +/*034b*/ 0xffffffffU, +/*034c*/ 0xffffffffU, +/*034d*/ 0x18070281U, +/*034e*/ 0x00070282U, +/*034f*/ 0x08050282U, +/*0350*/ 0x10050282U, +/*0351*/ 0xffffffffU, +/*0352*/ 0xffffffffU, +/*0353*/ 0xffffffffU, +/*0354*/ 0x18040282U, +/*0355*/ 0x00010283U, +/*0356*/ 0x08010283U, +/*0357*/ 0x10020283U, +/*0358*/ 0x18080283U, +/*0359*/ 0x00200284U, +/*035a*/ 0x00200285U, +/*035b*/ 0x00100286U, +/*035c*/ 0x10020286U, +/*035d*/ 0x18020286U, +/*035e*/ 0x00020287U, +/*035f*/ 0xffffffffU, +/*0360*/ 0x08010287U, +/*0361*/ 0x10010287U, +/*0362*/ 0x18020287U, +/*0363*/ 0x00080288U, +/*0364*/ 0x08080288U, +/*0365*/ 0x10080288U, +/*0366*/ 0x18080288U, +/*0367*/ 0x00080289U, +/*0368*/ 0x08080289U, +/*0369*/ 0xffffffffU, +/*036a*/ 0x10080289U, +/*036b*/ 0x18080289U, +/*036c*/ 0x0008028aU, +/*036d*/ 0x0808028aU, +/*036e*/ 0x1008028aU, +/*036f*/ 0x1808028aU, +/*0370*/ 0xffffffffU, +/*0371*/ 0x0008028bU, +/*0372*/ 0x0808028bU, +/*0373*/ 0x1008028bU, +/*0374*/ 0x1808028bU, +/*0375*/ 0x0008028cU, +/*0376*/ 0x0808028cU, +/*0377*/ 0xffffffffU, +/*0378*/ 0x1008028cU, +/*0379*/ 0x1808028cU, +/*037a*/ 0x0008028dU, +/*037b*/ 0x0808028dU, +/*037c*/ 0x1008028dU, +/*037d*/ 0x1808028dU, +/*037e*/ 0x0008028eU, +/*037f*/ 0xffffffffU, +/*0380*/ 0x0808028eU, +/*0381*/ 0x1008028eU, +/*0382*/ 0x1808028eU, +/*0383*/ 0x0008028fU, +/*0384*/ 0x0808028fU, +/*0385*/ 0x1008028fU, +/*0386*/ 0xffffffffU, +/*0387*/ 0x1808028fU, +/*0388*/ 0x00080290U, +/*0389*/ 0x08080290U, +/*038a*/ 0x10080290U, +/*038b*/ 0x18080290U, +/*038c*/ 0x00080291U, +/*038d*/ 0xffffffffU, +/*038e*/ 0x08080291U, +/*038f*/ 0x10080291U, +/*0390*/ 0x18080291U, +/*0391*/ 0x00080292U, +/*0392*/ 0x08080292U, +/*0393*/ 0x10080292U, +/*0394*/ 0x18080292U, +/*0395*/ 0xffffffffU, +/*0396*/ 0x00080293U, +/*0397*/ 0x08080293U, +/*0398*/ 0x10080293U, +/*0399*/ 0x18080293U, +/*039a*/ 0x00080294U, +/*039b*/ 0x08080294U, +/*039c*/ 0xffffffffU, +/*039d*/ 0x10080294U, +/*039e*/ 0x18080294U, +/*039f*/ 0x00080295U, +/*03a0*/ 0x08080295U, +/*03a1*/ 0x10080295U, +/*03a2*/ 0x18080295U, +/*03a3*/ 0xffffffffU, +/*03a4*/ 0x00080296U, +/*03a5*/ 0x08080296U, +/*03a6*/ 0x10080296U, +/*03a7*/ 0x18080296U, +/*03a8*/ 0x00080297U, +/*03a9*/ 0x08080297U, +/*03aa*/ 0x10080297U, +/*03ab*/ 0xffffffffU, +/*03ac*/ 0x18080297U, +/*03ad*/ 0x00080298U, +/*03ae*/ 0x08080298U, +/*03af*/ 0x10080298U, +/*03b0*/ 0x18080298U, +/*03b1*/ 0x00080299U, +/*03b2*/ 0xffffffffU, +/*03b3*/ 0x08080299U, +/*03b4*/ 0x10080299U, +/*03b5*/ 0x18080299U, +/*03b6*/ 0x0008029aU, +/*03b7*/ 0x0808029aU, +/*03b8*/ 0x1008029aU, +/*03b9*/ 0xffffffffU, +/*03ba*/ 0x1808029aU, +/*03bb*/ 0x0002029bU, +/*03bc*/ 0x0803029bU, +/*03bd*/ 0x100a029bU, +/*03be*/ 0x000a029cU, +/*03bf*/ 0x100a029cU, +/*03c0*/ 0x0005029dU, +/*03c1*/ 0x0808029dU, +/*03c2*/ 0x1008029dU, +/*03c3*/ 0x1808029dU, +/*03c4*/ 0x0006029eU, +/*03c5*/ 0x0806029eU, +/*03c6*/ 0x0011029fU, +/*03c7*/ 0x1808029fU, +/*03c8*/ 0x000402a0U, +/*03c9*/ 0x080602a0U, +/*03ca*/ 0xffffffffU, +/*03cb*/ 0x100602a0U, +/*03cc*/ 0x180802a0U, +/*03cd*/ 0xffffffffU, +/*03ce*/ 0x000802a1U, +/*03cf*/ 0x080802a1U, +/*03d0*/ 0x100802a1U, +/*03d1*/ 0x180602a1U, +/*03d2*/ 0x000602a2U, +/*03d3*/ 0x081102a2U, +/*03d4*/ 0x000802a3U, +/*03d5*/ 0x080402a3U, +/*03d6*/ 0x100602a3U, +/*03d7*/ 0xffffffffU, +/*03d8*/ 0x180602a3U, +/*03d9*/ 0x000802a4U, +/*03da*/ 0xffffffffU, +/*03db*/ 0x080802a4U, +/*03dc*/ 0x100802a4U, +/*03dd*/ 0x180802a4U, +/*03de*/ 0x000602a5U, +/*03df*/ 0x080602a5U, +/*03e0*/ 0x001102a6U, +/*03e1*/ 0x180802a6U, +/*03e2*/ 0x000402a7U, +/*03e3*/ 0x080602a7U, +/*03e4*/ 0xffffffffU, +/*03e5*/ 0x100602a7U, +/*03e6*/ 0x180802a7U, +/*03e7*/ 0xffffffffU, +/*03e8*/ 0x000402a8U, +/*03e9*/ 0x080402a8U, +/*03ea*/ 0x100402a8U, +/*03eb*/ 0x180402a8U, +/*03ec*/ 0x000402a9U, +/*03ed*/ 0x080402a9U, +/*03ee*/ 0x100402a9U, +/*03ef*/ 0x180402a9U, +/*03f0*/ 0x000402aaU, +/*03f1*/ 0x080402aaU, +/*03f2*/ 0x100402aaU, +/*03f3*/ 0x180402aaU, +/*03f4*/ 0x000402abU, +/*03f5*/ 0x080402abU, +/*03f6*/ 0x100402abU, +/*03f7*/ 0x180402abU, +/*03f8*/ 0x000402acU, +/*03f9*/ 0x080402acU, +/*03fa*/ 0x100402acU, +/*03fb*/ 0x180402acU, +/*03fc*/ 0x001202adU, +/*03fd*/ 0x001102aeU, +/*03fe*/ 0x001202afU, +/*03ff*/ 0x002002b0U, +/*0400*/ 0x002002b1U, +/*0401*/ 0x002002b2U, +/*0402*/ 0x002002b3U, +/*0403*/ 0x002002b4U, +/*0404*/ 0x002002b5U, +/*0405*/ 0x002002b6U, +/*0406*/ 0x002002b7U, +/*0407*/ 0x002002b8U, +/*0408*/ 0x000202b9U, +/*0409*/ 0x080502b9U, +/*040a*/ 0x100502b9U, +/*040b*/ 0x180102b9U, +/*040c*/ 0x000402baU, +/*040d*/ 0x080402baU, +/*040e*/ 0x100402baU, +/*040f*/ 0x180402baU, +/*0410*/ 0x000402bbU, +/*0411*/ 0x080402bbU, +/*0412*/ 0x100402bbU, +/*0413*/ 0x180402bbU, +/*0414*/ 0xffffffffU, +/*0415*/ 0xffffffffU, +/*0416*/ 0xffffffffU, +/*0417*/ 0xffffffffU, +/*0418*/ 0xffffffffU, +/*0419*/ 0xffffffffU, +/*041a*/ 0x000402bcU, +/*041b*/ 0x080402bcU, +/*041c*/ 0x100402bcU, +/*041d*/ 0x180402bcU, +/*041e*/ 0x000402bdU, +/*041f*/ 0x080402bdU, +/*0420*/ 0x100402bdU, +/*0421*/ 0x180402bdU, +/*0422*/ 0x000102beU, +/*0423*/ 0x080202beU, +/*0424*/ 0x100202beU, +/*0425*/ 0x180202beU, +/*0426*/ 0x000202bfU, +/*0427*/ 0x080102bfU, +/*0428*/ 0x100402bfU, +/*0429*/ 0x001002c0U, +/*042a*/ 0x002002c1U, +/*042b*/ 0x001002c2U, +/*042c*/ 0x002002c3U, +/*042d*/ 0x001002c4U, +/*042e*/ 0x002002c5U, +/*042f*/ 0x000702c6U, +/*0430*/ 0x080102c6U, +/*0431*/ 0x100202c6U, +/*0432*/ 0x180602c6U, +/*0433*/ 0x000102c7U, +/*0434*/ 0x080102c7U, +/*0435*/ 0x002002c8U, +/*0436*/ 0x000202c9U, +/*0437*/ 0x002002caU, +/*0438*/ 0x002002cbU, +/*0439*/ 0x000c02ccU, +/*043a*/ 0x100c02ccU, +/*043b*/ 0x002002cdU, +/*043c*/ 0x000302ceU, +/*043d*/ 0x002002cfU, +/*043e*/ 0x000302d0U, +/*043f*/ 0x002002d1U, +/*0440*/ 0x000302d2U, +/*0441*/ 0x002002d3U, +/*0442*/ 0x000302d4U, +/*0443*/ 0x002002d5U, +/*0444*/ 0x000302d6U, +/*0445*/ 0x002002d7U, +/*0446*/ 0x000302d8U, +/*0447*/ 0x002002d9U, +/*0448*/ 0x000302daU, +/*0449*/ 0x002002dbU, +/*044a*/ 0x000302dcU, +/*044b*/ 0x002002ddU, +/*044c*/ 0x000302deU, +/*044d*/ 0x002002dfU, +/*044e*/ 0x000302e0U, +/*044f*/ 0x080302e0U, +/*0450*/ 0x100202e0U, +/*0451*/ 0x180202e0U, +/*0452*/ 0x002002e1U, +/*0453*/ 0x002002e2U, +/*0454*/ 0x002002e3U, +/*0455*/ 0x002002e4U, +/*0456*/ 0x000402e5U, +/*0457*/ 0x001e02e6U, +/*0458*/ 0x001e02e7U, +/*0459*/ 0x001e02e8U, +/*045a*/ 0x001e02e9U, +/*045b*/ 0x001e02eaU, +/*045c*/ 0x001e02ebU, +/*045d*/ 0x001e02ecU, +/*045e*/ 0x001e02edU, +/*045f*/ 0x000402eeU, +/*0460*/ 0xffffffffU, +/*0461*/ 0xffffffffU, +/*0462*/ 0xffffffffU, +/*0463*/ 0xffffffffU, +/*0464*/ 0x080402eeU, +/*0465*/ 0x100102eeU, +/*0466*/ 0x180802eeU, +/*0467*/ 0x000402efU, +/*0468*/ 0x080102efU, +/*0469*/ 0x100802efU, +/*046a*/ 0x180402efU, +/*046b*/ 0x000102f0U, +/*046c*/ 0x080802f0U, +/*046d*/ 0x100402f0U, +/*046e*/ 0x180102f0U, +/*046f*/ 0x000802f1U, +/*0470*/ 0x080402f1U, +/*0471*/ 0x100102f1U, +/*0472*/ 0x180802f1U, +/*0473*/ 0x000402f2U, +/*0474*/ 0x080102f2U, +/*0475*/ 0x100802f2U, +/*0476*/ 0x180402f2U, +/*0477*/ 0x000102f3U, +/*0478*/ 0x080802f3U, +/*0479*/ 0x100402f3U, +/*047a*/ 0x180102f3U, +/*047b*/ 0x000802f4U, +/*047c*/ 0x080802f4U, +/*047d*/ 0x100102f4U, +/*047e*/ 0x180502f4U, +/*047f*/ 0xffffffffU, +/*0480*/ 0xffffffffU, +/*0481*/ 0xffffffffU, +/*0482*/ 0xffffffffU, +/*0483*/ 0xffffffffU, +/*0484*/ 0xffffffffU, +/*0485*/ 0xffffffffU, +/*0486*/ 0xffffffffU, +/*0487*/ 0xffffffffU, +/*0488*/ 0xffffffffU, +/*0489*/ 0xffffffffU, +/*048a*/ 0xffffffffU, +/*048b*/ 0xffffffffU, +/*048c*/ 0xffffffffU, +/*048d*/ 0xffffffffU, +/*048e*/ 0xffffffffU, +/*048f*/ 0xffffffffU, +/*0490*/ 0xffffffffU, +/*0491*/ 0xffffffffU, +/*0492*/ 0xffffffffU, +/*0493*/ 0xffffffffU, +/*0494*/ 0xffffffffU, + }, + { +/*0000*/ 0x00200800U, +/*0001*/ 0x00040801U, +/*0002*/ 0x080b0801U, +/*0003*/ 0x000a0802U, +/*0004*/ 0x10020802U, +/*0005*/ 0x18010802U, +/*0006*/ 0x00060803U, +/*0007*/ 0x08060803U, +/*0008*/ 0x10060803U, +/*0009*/ 0x18060803U, +/*000a*/ 0x00060804U, +/*000b*/ 0x08060804U, +/*000c*/ 0x10050804U, +/*000d*/ 0x18060804U, +/*000e*/ 0x00060805U, +/*000f*/ 0x08040805U, +/*0010*/ 0x10030805U, +/*0011*/ 0x00180806U, +/*0012*/ 0x18030806U, +/*0013*/ 0x00180807U, +/*0014*/ 0x18020807U, +/*0015*/ 0x0801085eU, +/*0016*/ 0x00020808U, +/*0017*/ 0x08010808U, +/*0018*/ 0x10010808U, +/*0019*/ 0x18020808U, +/*001a*/ 0x00050809U, +/*001b*/ 0x08050809U, +/*001c*/ 0x10040809U, +/*001d*/ 0xffffffffU, +/*001e*/ 0x18040809U, +/*001f*/ 0x0002080aU, +/*0020*/ 0x0805080aU, +/*0021*/ 0x1009080aU, +/*0022*/ 0x0001080bU, +/*0023*/ 0x0020080cU, +/*0024*/ 0x001c080dU, +/*0025*/ 0x0001080eU, +/*0026*/ 0x0807080eU, +/*0027*/ 0x1009080eU, +/*0028*/ 0x000a080fU, +/*0029*/ 0x1005080fU, +/*002a*/ 0x1801080fU, +/*002b*/ 0x10010810U, +/*002c*/ 0x18020810U, +/*002d*/ 0x00090810U, +/*002e*/ 0x00090811U, +/*002f*/ 0x10020811U, +/*0030*/ 0x00200812U, +/*0031*/ 0x00010813U, +/*0032*/ 0x08020813U, +/*0033*/ 0x00200814U, +/*0034*/ 0x00200815U, +/*0035*/ 0x00200816U, +/*0036*/ 0x00200817U, +/*0037*/ 0xffffffffU, +/*0038*/ 0xffffffffU, +/*0039*/ 0xffffffffU, +/*003a*/ 0xffffffffU, +/*003b*/ 0x00030818U, +/*003c*/ 0x08010818U, +/*003d*/ 0x10040818U, +/*003e*/ 0x18030818U, +/*003f*/ 0x00040819U, +/*0040*/ 0x08040819U, +/*0041*/ 0x10040819U, +/*0042*/ 0x18040819U, +/*0043*/ 0x0001081aU, +/*0044*/ 0x0801081aU, +/*0045*/ 0x1006081aU, +/*0046*/ 0x1804081aU, +/*0047*/ 0x0008081bU, +/*0048*/ 0x0806081bU, +/*0049*/ 0x1004081bU, +/*004a*/ 0x1806081bU, +/*004b*/ 0x0004081cU, +/*004c*/ 0x0802081cU, +/*004d*/ 0x1005081cU, +/*004e*/ 0x1808081cU, +/*004f*/ 0xffffffffU, +/*0050*/ 0x0006081dU, +/*0051*/ 0x0803081dU, +/*0052*/ 0x100b081dU, +/*0053*/ 0x0004081eU, +/*0054*/ 0x0804081eU, +/*0055*/ 0x1004081eU, +/*0056*/ 0x1801081eU, +/*0057*/ 0xffffffffU, +/*0058*/ 0x0009081fU, +/*0059*/ 0x00200820U, +/*005a*/ 0x00200821U, +/*005b*/ 0x00200822U, +/*005c*/ 0x00200823U, +/*005d*/ 0x00100824U, +/*005e*/ 0xffffffffU, +/*005f*/ 0x10010824U, +/*0060*/ 0x18060824U, +/*0061*/ 0x00080825U, +/*0062*/ 0x00200826U, +/*0063*/ 0x00100827U, +/*0064*/ 0x100b0827U, +/*0065*/ 0x00070828U, +/*0066*/ 0x08070828U, +/*0067*/ 0x10090828U, +/*0068*/ 0x00090829U, +/*0069*/ 0x100b0829U, +/*006a*/ 0x0007082aU, +/*006b*/ 0x0808082aU, +/*006c*/ 0x1009082aU, +/*006d*/ 0x0003082bU, +/*006e*/ 0x080a082bU, +/*006f*/ 0x000a082cU, +/*0070*/ 0x0011082dU, +/*0071*/ 0x000a082eU, +/*0072*/ 0x100a082eU, +/*0073*/ 0x0010082fU, +/*0074*/ 0x100e082fU, +/*0075*/ 0x000e0830U, +/*0076*/ 0x00120831U, +/*0077*/ 0x000a0832U, +/*0078*/ 0x100a0832U, +/*0079*/ 0x00020833U, +/*007a*/ 0x00200834U, +/*007b*/ 0x000b0835U, +/*007c*/ 0x100b0835U, +/*007d*/ 0x00200836U, +/*007e*/ 0x00130837U, +/*007f*/ 0x00200838U, +/*0080*/ 0x00200839U, +/*0081*/ 0x0008083aU, +/*0082*/ 0x0801083aU, +/*0083*/ 0x1001083aU, +/*0084*/ 0x1801083aU, +/*0085*/ 0x0008083bU, +/*0086*/ 0x080c083bU, +/*0087*/ 0x000c083cU, +/*0088*/ 0x100c083cU, +/*0089*/ 0x000c083dU, +/*008a*/ 0x100c083dU, +/*008b*/ 0x000c083eU, +/*008c*/ 0x100c083eU, +/*008d*/ 0x000c083fU, +/*008e*/ 0x100c083fU, +/*008f*/ 0x000c0840U, +/*0090*/ 0x100c0840U, +/*0091*/ 0x000b0841U, +/*0092*/ 0x10090841U, +/*0093*/ 0x00010842U, +/*0094*/ 0x000b0843U, +/*0095*/ 0x100b0843U, +/*0096*/ 0x000b0844U, +/*0097*/ 0x100b0844U, +/*0098*/ 0x000b0845U, +/*0099*/ 0x100b0845U, +/*009a*/ 0x000b0846U, +/*009b*/ 0x100b0846U, +/*009c*/ 0x000b0847U, +/*009d*/ 0x100a0847U, +/*009e*/ 0x00020848U, +/*009f*/ 0x080a0848U, +/*00a0*/ 0x000a0849U, +/*00a1*/ 0x100a0849U, +/*00a2*/ 0x000a084aU, +/*00a3*/ 0x100a084aU, +/*00a4*/ 0x000a084bU, +/*00a5*/ 0x100a084bU, +/*00a6*/ 0x000a084cU, +/*00a7*/ 0x100a084cU, +/*00a8*/ 0x000a084dU, +/*00a9*/ 0x100a084dU, +/*00aa*/ 0x000a084eU, +/*00ab*/ 0x100a084eU, +/*00ac*/ 0x000a084fU, +/*00ad*/ 0x100a084fU, +/*00ae*/ 0x000a0850U, +/*00af*/ 0x100a0850U, +/*00b0*/ 0x000a0851U, +/*00b1*/ 0x100a0851U, +/*00b2*/ 0x000a0852U, +/*00b3*/ 0x100a0852U, +/*00b4*/ 0x000a0853U, +/*00b5*/ 0x100a0853U, +/*00b6*/ 0x000a0854U, +/*00b7*/ 0x100a0854U, +/*00b8*/ 0x000a0855U, +/*00b9*/ 0x100a0855U, +/*00ba*/ 0x000a0856U, +/*00bb*/ 0x10040856U, +/*00bc*/ 0x18030856U, +/*00bd*/ 0x000a0857U, +/*00be*/ 0x100a0857U, +/*00bf*/ 0x00010858U, +/*00c0*/ 0x080a0858U, +/*00c1*/ 0x18040858U, +/*00c2*/ 0x000b0859U, +/*00c3*/ 0x100a0859U, +/*00c4*/ 0x0003085aU, +/*00c5*/ 0x0008085bU, +/*00c6*/ 0x0808085bU, +/*00c7*/ 0x1008085bU, +/*00c8*/ 0x1808085bU, +/*00c9*/ 0x0008085cU, +/*00ca*/ 0x0808085cU, +/*00cb*/ 0x1008085cU, +/*00cc*/ 0x1801085cU, +/*00cd*/ 0x0008085dU, +/*00ce*/ 0x0808085dU, +/*00cf*/ 0x1002085dU, +/*00d0*/ 0x1802085dU, +/*00d1*/ 0x0005085eU, +/*00d2*/ 0x1005085eU, +/*00d3*/ 0x1805085eU, +/*00d4*/ 0x0004085fU, +/*00d5*/ 0x080b085fU, +/*00d6*/ 0x1806085fU, +/*00d7*/ 0x00080860U, +/*00d8*/ 0x08080860U, +/*00d9*/ 0x10040860U, +/*00da*/ 0x18040860U, +/*00db*/ 0x00060861U, +/*00dc*/ 0x08040861U, +/*00dd*/ 0x10050861U, +/*00de*/ 0x000a0862U, +/*00df*/ 0x100a0862U, +/*00e0*/ 0x00080863U, +/*00e1*/ 0x08010863U, +/*00e2*/ 0x10040863U, +/*00e3*/ 0x00020864U, +/*00e4*/ 0x08030864U, +/*00e5*/ 0x00050a00U, +/*00e6*/ 0x08050a00U, +/*00e7*/ 0x10050a00U, +/*00e8*/ 0x18050a00U, +/*00e9*/ 0x00050a01U, +/*00ea*/ 0x08050a01U, +/*00eb*/ 0x100b0a01U, +/*00ec*/ 0x00010a02U, +/*00ed*/ 0x08030a02U, +/*00ee*/ 0x00200a03U, +/*00ef*/ 0x00100a04U, +/*00f0*/ 0x10040a04U, +/*00f1*/ 0x000b0a05U, +/*00f2*/ 0x10070a05U, +/*00f3*/ 0x00090a06U, +/*00f4*/ 0x10030a06U, +/*00f5*/ 0x18030a06U, +/*00f6*/ 0x00010a07U, +/*00f7*/ 0x08010a07U, +/*00f8*/ 0x10070a07U, +/*00f9*/ 0x18070a07U, +/*00fa*/ 0x00050a08U, +/*00fb*/ 0x08010a08U, +/*00fc*/ 0x10020a08U, +/*00fd*/ 0x18030a08U, +/*00fe*/ 0x00010a09U, +/*00ff*/ 0x080f0a09U, +/*0100*/ 0x00200a0aU, +/*0101*/ 0x00200a0bU, +/*0102*/ 0x000b0a0cU, +/*0103*/ 0x100b0a0cU, +/*0104*/ 0x000b0a0dU, +/*0105*/ 0x00180a0eU, +/*0106*/ 0x00180a0fU, +/*0107*/ 0xffffffffU, +/*0108*/ 0xffffffffU, +/*0109*/ 0xffffffffU, +/*010a*/ 0xffffffffU, +/*010b*/ 0xffffffffU, +/*010c*/ 0x18020a0fU, +/*010d*/ 0x00020a10U, +/*010e*/ 0x08040a10U, +/*010f*/ 0x10040a10U, +/*0110*/ 0x18010a10U, +/*0111*/ 0x00010a11U, +/*0112*/ 0x08010a11U, +/*0113*/ 0x10030a11U, +/*0114*/ 0x00200a12U, +/*0115*/ 0x00200a13U, +/*0116*/ 0xffffffffU, +/*0117*/ 0x00140a14U, +/*0118*/ 0x00140a15U, +/*0119*/ 0x00140a16U, +/*011a*/ 0x00140a17U, +/*011b*/ 0x00140a18U, +/*011c*/ 0x00140a19U, +/*011d*/ 0x00140a1aU, +/*011e*/ 0x00140a1bU, +/*011f*/ 0x001e0a1cU, +/*0120*/ 0x000a0a1dU, +/*0121*/ 0x10060a1dU, +/*0122*/ 0x18060a1dU, +/*0123*/ 0x00060a1eU, +/*0124*/ 0x08060a1eU, +/*0125*/ 0x10060a1eU, +/*0126*/ 0x00080a1fU, +/*0127*/ 0x080b0a1fU, +/*0128*/ 0x000b0a20U, +/*0129*/ 0x100b0a20U, +/*012a*/ 0x000b0a21U, +/*012b*/ 0x100b0a21U, +/*012c*/ 0x000b0a22U, +/*012d*/ 0x10040a22U, +/*012e*/ 0x000b0a23U, +/*012f*/ 0x10060a23U, +/*0130*/ 0x18080a23U, +/*0131*/ 0x00080a24U, +/*0132*/ 0x08040a24U, +/*0133*/ 0x00020b80U, +/*0134*/ 0x00010b81U, +/*0135*/ 0x08010b81U, +/*0136*/ 0x10020b81U, +/*0137*/ 0x18050b81U, +/*0138*/ 0x00050b82U, +/*0139*/ 0x08050b82U, +/*013a*/ 0x10050b82U, +/*013b*/ 0x000b0b83U, +/*013c*/ 0x10050b83U, +/*013d*/ 0x18010b83U, +/*013e*/ 0x00010b84U, +/*013f*/ 0x08010b84U, +/*0140*/ 0x10010b84U, +/*0141*/ 0x18010b84U, +/*0142*/ 0x00040b85U, +/*0143*/ 0x080b0b85U, +/*0144*/ 0x000b0b86U, +/*0145*/ 0x100b0b86U, +/*0146*/ 0x00040b87U, +/*0147*/ 0x080b0b87U, +/*0148*/ 0x18040b87U, +/*0149*/ 0x00010b88U, +/*014a*/ 0x08010b88U, +/*014b*/ 0x10010b88U, +/*014c*/ 0x00200b89U, +/*014d*/ 0x00200b8aU, +/*014e*/ 0x00080b8bU, +/*014f*/ 0x080a0b8bU, +/*0150*/ 0x18050b8bU, +/*0151*/ 0x000b0b8cU, +/*0152*/ 0x10030b8cU, +/*0153*/ 0x18030b8cU, +/*0154*/ 0x00010b8dU, +/*0155*/ 0x08020b8dU, +/*0156*/ 0x10010b8dU, +/*0157*/ 0x18010b8dU, +/*0158*/ 0x00010b8eU, +/*0159*/ 0xffffffffU, +/*015a*/ 0x08010b8eU, +/*015b*/ 0x18040b8eU, +/*015c*/ 0x00040b8fU, +/*015d*/ 0x08040b8fU, +/*015e*/ 0x10040b8fU, +/*015f*/ 0x18010b8fU, +/*0160*/ 0x00010b90U, +/*0161*/ 0x08010b90U, +/*0162*/ 0x00200b91U, +/*0163*/ 0x00200b92U, +/*0164*/ 0x00200b93U, +/*0165*/ 0x00200b94U, +/*0166*/ 0xffffffffU, +/*0167*/ 0x10010b8eU, +/*0168*/ 0x000d0b96U, +/*0169*/ 0x100d0b96U, +/*016a*/ 0x000d0b97U, +/*016b*/ 0x00050b98U, +/*016c*/ 0x00010b99U, +/*016d*/ 0x080e0b99U, +/*016e*/ 0x000e0b9aU, +/*016f*/ 0x100e0b9aU, +/*0170*/ 0x000e0b9bU, +/*0171*/ 0x100e0b9bU, +/*0172*/ 0x00040b9cU, +/*0173*/ 0x08040b9cU, +/*0174*/ 0x10040b9cU, +/*0175*/ 0x18040b9cU, +/*0176*/ 0x00040b9dU, +/*0177*/ 0x080b0b9dU, +/*0178*/ 0x000b0b9eU, +/*0179*/ 0x100b0b9eU, +/*017a*/ 0x000b0b9fU, +/*017b*/ 0x00040ba0U, +/*017c*/ 0x08040ba0U, +/*017d*/ 0x10040ba0U, +/*017e*/ 0x18040ba0U, +/*017f*/ 0x000d0ba1U, +/*0180*/ 0x100d0ba1U, +/*0181*/ 0x000d0ba2U, +/*0182*/ 0x10100ba2U, +/*0183*/ 0x00080b95U, +/*0184*/ 0x08080b95U, +/*0185*/ 0x00100ba3U, +/*0186*/ 0x10100ba3U, +/*0187*/ 0x00100ba4U, +/*0188*/ 0x10100ba4U, +/*0189*/ 0x00100ba5U, +/*018a*/ 0x10030ba5U, +/*018b*/ 0x18040ba5U, +/*018c*/ 0x00010ba6U, +/*018d*/ 0x08080ba6U, +/*018e*/ 0x10010ba6U, +/*018f*/ 0x000a0ba7U, +/*0190*/ 0x10010ba7U, +/*0191*/ 0x00140ba8U, +/*0192*/ 0x000b0ba9U, +/*0193*/ 0x100c0ba9U, +/*0194*/ 0x00120baaU, +/*0195*/ 0x00140babU, +/*0196*/ 0x00120bacU, +/*0197*/ 0x00110badU, +/*0198*/ 0x00110baeU, +/*0199*/ 0x00120bafU, +/*019a*/ 0x00120bb0U, +/*019b*/ 0x00120bb1U, +/*019c*/ 0x00120bb2U, +/*019d*/ 0x00120bb3U, +/*019e*/ 0x00120bb4U, +/*019f*/ 0x00120bb5U, +/*01a0*/ 0x00120bb6U, +/*01a1*/ 0x00120bb7U, +/*01a2*/ 0x00120bb8U, +/*01a3*/ 0x000e0bb9U, +/*01a4*/ 0x100d0bb9U, +/*01a5*/ 0x00200bbaU, +/*01a6*/ 0x00170bbbU, +/*01a7*/ 0x000d0bbcU, +/*01a8*/ 0x10010bbcU, +/*01a9*/ 0x18010bbcU, +/*01aa*/ 0x00200bbdU, +/*01ab*/ 0x00080bbeU, +/*01ac*/ 0x08030bbeU, +/*01ad*/ 0x10030bbeU, +/*01ae*/ 0x00180bbfU, +/*01af*/ 0x00180bc0U, +/*01b0*/ 0x18070bc0U, +/*01b1*/ 0x00070bc1U, +/*01b2*/ 0x08080bc1U, +/*01b3*/ 0x10080bc1U, +/*01b4*/ 0x18080bc1U, +/*01b5*/ 0x00010bc2U, +/*01b6*/ 0x08010bc2U, +/*01b7*/ 0x00200bc3U, +/*01b8*/ 0x00070bc4U, +/*01b9*/ 0x08140bc4U, +/*01ba*/ 0x00140bc5U, +/*01bb*/ 0x00190bc6U, +/*01bc*/ 0x00170bc7U, +/*01bd*/ 0x00110bc8U, +/*01be*/ 0x00110bc9U, +/*01bf*/ 0x00100bcaU, +/*01c0*/ 0x10010bcaU, +/*01c1*/ 0x18010bcaU, +/*01c2*/ 0x00020bcbU, +/*01c3*/ 0x08040bcbU, +/*01c4*/ 0x10090bcbU, +/*01c5*/ 0x00070bccU, +/*01c6*/ 0x08040bccU, +/*01c7*/ 0x00200bcdU, +/*01c8*/ 0x00010bceU, +/*01c9*/ 0x08020bceU, +/*01ca*/ 0x10060bceU, +/*01cb*/ 0x00100bcfU, +/*01cc*/ 0x10010bcfU, +/*01cd*/ 0x00200bd0U, +/*01ce*/ 0x00080bd1U, +/*01cf*/ 0x08010bd1U, +/*01d0*/ 0x10050bd1U, +/*01d1*/ 0x18030bd1U, +/*01d2*/ 0x00020bd2U, +/*01d3*/ 0xffffffffU, +/*01d4*/ 0x00200bd3U, +/*01d5*/ 0x000b0bd4U, +/*01d6*/ 0xffffffffU, +/*01d7*/ 0x10030bd4U, +/*01d8*/ 0x18080bd4U, +/*01d9*/ 0x00020bd5U, +/*01da*/ 0x080c0bd5U, +/*01db*/ 0x18040bd5U, +/*01dc*/ 0x00010bd6U, +/*01dd*/ 0x08050bd6U, +/*01de*/ 0x00010200U, +/*01df*/ 0x08040200U, +/*01e0*/ 0x10100200U, +/*01e1*/ 0x00010201U, +/*01e2*/ 0x08010201U, +/*01e3*/ 0x10010201U, +/*01e4*/ 0x18010201U, +/*01e5*/ 0x00100202U, +/*01e6*/ 0x10080202U, +/*01e7*/ 0x18010202U, +/*01e8*/ 0x00200203U, +/*01e9*/ 0x00200204U, +/*01ea*/ 0x00200205U, +/*01eb*/ 0x00200206U, +/*01ec*/ 0x00020207U, +/*01ed*/ 0x08010207U, +/*01ee*/ 0x10010207U, +/*01ef*/ 0x00200208U, +/*01f0*/ 0x00140209U, +/*01f1*/ 0x0020020aU, +/*01f2*/ 0x0014020bU, +/*01f3*/ 0x0020020cU, +/*01f4*/ 0x0014020dU, +/*01f5*/ 0x0014020eU, +/*01f6*/ 0x0020020fU, +/*01f7*/ 0x00200210U, +/*01f8*/ 0x00200211U, +/*01f9*/ 0x00200212U, +/*01fa*/ 0x00140213U, +/*01fb*/ 0x00200214U, +/*01fc*/ 0x00200215U, +/*01fd*/ 0x00200216U, +/*01fe*/ 0x00200217U, +/*01ff*/ 0x00140218U, +/*0200*/ 0x00200219U, +/*0201*/ 0x0020021aU, +/*0202*/ 0x0020021bU, +/*0203*/ 0x0020021cU, +/*0204*/ 0x0009021dU, +/*0205*/ 0x1001021dU, +/*0206*/ 0x0020021eU, +/*0207*/ 0x0005021fU, +/*0208*/ 0x0801021fU, +/*0209*/ 0x1008021fU, +/*020a*/ 0x1808021fU, +/*020b*/ 0x001e0220U, +/*020c*/ 0x001e0221U, +/*020d*/ 0x001e0222U, +/*020e*/ 0x001e0223U, +/*020f*/ 0x001e0224U, +/*0210*/ 0x001e0225U, +/*0211*/ 0x001e0226U, +/*0212*/ 0x001e0227U, +/*0213*/ 0x001e0228U, +/*0214*/ 0x001e0229U, +/*0215*/ 0x001e022aU, +/*0216*/ 0x001e022bU, +/*0217*/ 0x001e022cU, +/*0218*/ 0x001e022dU, +/*0219*/ 0x001e022eU, +/*021a*/ 0x001e022fU, +/*021b*/ 0x00010230U, +/*021c*/ 0x08010230U, +/*021d*/ 0x10010230U, +/*021e*/ 0x18040230U, +/*021f*/ 0x00080231U, +/*0220*/ 0x08080231U, +/*0221*/ 0x10080231U, +/*0222*/ 0x18040231U, +/*0223*/ 0x00070232U, +/*0224*/ 0x08060232U, +/*0225*/ 0x10070232U, +/*0226*/ 0x18070232U, +/*0227*/ 0x00060233U, +/*0228*/ 0x08070233U, +/*0229*/ 0x10070233U, +/*022a*/ 0x18060233U, +/*022b*/ 0x00070234U, +/*022c*/ 0x08020234U, +/*022d*/ 0x10010234U, +/*022e*/ 0x18010234U, +/*022f*/ 0x000a0235U, +/*0230*/ 0x00140236U, +/*0231*/ 0x000a0237U, +/*0232*/ 0x00140238U, +/*0233*/ 0x000a0239U, +/*0234*/ 0x0014023aU, +/*0235*/ 0xffffffffU, +/*0236*/ 0xffffffffU, +/*0237*/ 0x0005023bU, +/*0238*/ 0x0001023cU, +/*0239*/ 0x1001023cU, +/*023a*/ 0x1801023cU, +/*023b*/ 0x0001023dU, +/*023c*/ 0x0801023dU, +/*023d*/ 0x1001023dU, +/*023e*/ 0x1801023dU, +/*023f*/ 0x0002023eU, +/*0240*/ 0x0802023eU, +/*0241*/ 0x1002023eU, +/*0242*/ 0x1802023eU, +/*0243*/ 0x0002023fU, +/*0244*/ 0x0803023fU, +/*0245*/ 0x1001023fU, +/*0246*/ 0x1801023fU, +/*0247*/ 0x00010240U, +/*0248*/ 0x08010240U, +/*0249*/ 0x10010240U, +/*024a*/ 0x18020240U, +/*024b*/ 0x00010241U, +/*024c*/ 0x08010241U, +/*024d*/ 0x10010241U, +/*024e*/ 0x18020241U, +/*024f*/ 0x00010242U, +/*0250*/ 0x08010242U, +/*0251*/ 0x10010242U, +/*0252*/ 0x18020242U, +/*0253*/ 0x00010243U, +/*0254*/ 0x08010243U, +/*0255*/ 0x10010243U, +/*0256*/ 0x18020243U, +/*0257*/ 0xffffffffU, +/*0258*/ 0x00010244U, +/*0259*/ 0x08010244U, +/*025a*/ 0x10010244U, +/*025b*/ 0x18010244U, +/*025c*/ 0x00010245U, +/*025d*/ 0x08010245U, +/*025e*/ 0x10010245U, +/*025f*/ 0x18010245U, +/*0260*/ 0x00040246U, +/*0261*/ 0x08040246U, +/*0262*/ 0x10040246U, +/*0263*/ 0x18010246U, +/*0264*/ 0x00020247U, +/*0265*/ 0x08060247U, +/*0266*/ 0x10060247U, +/*0267*/ 0x18020247U, +/*0268*/ 0x00020248U, +/*0269*/ 0x08020248U, +/*026a*/ 0xffffffffU, +/*026b*/ 0x10100248U, +/*026c*/ 0x00010249U, +/*026d*/ 0x08010249U, +/*026e*/ 0x10010249U, +/*026f*/ 0x18040249U, +/*0270*/ 0x0001024aU, +/*0271*/ 0x0804024aU, +/*0272*/ 0x1003024aU, +/*0273*/ 0x1808024aU, +/*0274*/ 0x000a024bU, +/*0275*/ 0x100a024bU, +/*0276*/ 0x000a024cU, +/*0277*/ 0xffffffffU, +/*0278*/ 0x0020024dU, +/*0279*/ 0x0020024eU, +/*027a*/ 0x0005024fU, +/*027b*/ 0x1801023aU, +/*027c*/ 0x0805023cU, +/*027d*/ 0x0808024fU, +/*027e*/ 0x1001024fU, +/*027f*/ 0x1808024fU, +/*0280*/ 0x00010250U, +/*0281*/ 0x08080250U, +/*0282*/ 0x10010250U, +/*0283*/ 0x18040250U, +/*0284*/ 0x00040251U, +/*0285*/ 0x08040251U, +/*0286*/ 0x10040251U, +/*0287*/ 0x18040251U, +/*0288*/ 0x00040252U, +/*0289*/ 0x08040252U, +/*028a*/ 0x10040252U, +/*028b*/ 0x18040252U, +/*028c*/ 0x00040253U, +/*028d*/ 0x08010253U, +/*028e*/ 0x10040253U, +/*028f*/ 0x18040253U, +/*0290*/ 0x00040254U, +/*0291*/ 0x08040254U, +/*0292*/ 0x10040254U, +/*0293*/ 0x18040254U, +/*0294*/ 0x00060255U, +/*0295*/ 0x08060255U, +/*0296*/ 0x10060255U, +/*0297*/ 0x18060255U, +/*0298*/ 0x00060256U, +/*0299*/ 0x08060256U, +/*029a*/ 0x10040256U, +/*029b*/ 0x18010256U, +/*029c*/ 0x00010257U, +/*029d*/ 0x08020257U, +/*029e*/ 0x00200258U, +/*029f*/ 0x00200259U, +/*02a0*/ 0x0020025aU, +/*02a1*/ 0x0020025bU, +/*02a2*/ 0x0020025cU, +/*02a3*/ 0x0020025dU, +/*02a4*/ 0x0020025eU, +/*02a5*/ 0x0020025fU, +/*02a6*/ 0x00040260U, +/*02a7*/ 0x08040260U, +/*02a8*/ 0x10010260U, +/*02a9*/ 0x18010260U, +/*02aa*/ 0x00010261U, +/*02ab*/ 0x08010261U, +/*02ac*/ 0x10010261U, +/*02ad*/ 0x18010261U, +/*02ae*/ 0x00010262U, +/*02af*/ 0x08010262U, +/*02b0*/ 0x10010262U, +/*02b1*/ 0x18040262U, +/*02b2*/ 0x00040263U, +/*02b3*/ 0x080a0263U, +/*02b4*/ 0x00200264U, +/*02b5*/ 0x00040265U, +/*02b6*/ 0x08080265U, +/*02b7*/ 0x10020265U, +/*02b8*/ 0x18020265U, +/*02b9*/ 0x00020266U, +/*02ba*/ 0x08020266U, +/*02bb*/ 0x10020266U, +/*02bc*/ 0x18020266U, +/*02bd*/ 0xffffffffU, +/*02be*/ 0xffffffffU, +/*02bf*/ 0x00200267U, +/*02c0*/ 0x00030268U, +/*02c1*/ 0x08100268U, +/*02c2*/ 0x00100269U, +/*02c3*/ 0x10040269U, +/*02c4*/ 0x18040269U, +/*02c5*/ 0x0005026aU, +/*02c6*/ 0x0805026aU, +/*02c7*/ 0xffffffffU, +/*02c8*/ 0xffffffffU, +/*02c9*/ 0xffffffffU, +/*02ca*/ 0xffffffffU, +/*02cb*/ 0x1001026aU, +/*02cc*/ 0x1801026aU, +/*02cd*/ 0x0008026bU, +/*02ce*/ 0x0808026bU, +/*02cf*/ 0x1008026bU, +/*02d0*/ 0x1808026bU, +/*02d1*/ 0x0008026cU, +/*02d2*/ 0x0808026cU, +/*02d3*/ 0x1008026cU, +/*02d4*/ 0x1808026cU, +/*02d5*/ 0x0008026dU, +/*02d6*/ 0x0808026dU, +/*02d7*/ 0x1008026dU, +/*02d8*/ 0x1808026dU, +/*02d9*/ 0x0008026eU, +/*02da*/ 0x0808026eU, +/*02db*/ 0x1003026eU, +/*02dc*/ 0x1803026eU, +/*02dd*/ 0x0003026fU, +/*02de*/ 0xffffffffU, +/*02df*/ 0x0801026fU, +/*02e0*/ 0x1002026fU, +/*02e1*/ 0x1801026fU, +/*02e2*/ 0x00040270U, +/*02e3*/ 0x08020270U, +/*02e4*/ 0x10010270U, +/*02e5*/ 0x18010270U, +/*02e6*/ 0x00010271U, +/*02e7*/ 0x08010271U, +/*02e8*/ 0x10040271U, +/*02e9*/ 0x18080271U, +/*02ea*/ 0x000a0272U, +/*02eb*/ 0x100a0272U, +/*02ec*/ 0x000a0273U, +/*02ed*/ 0x100a0273U, +/*02ee*/ 0x000a0274U, +/*02ef*/ 0x100a0274U, +/*02f0*/ 0x00200275U, +/*02f1*/ 0x00200276U, +/*02f2*/ 0x00010277U, +/*02f3*/ 0x08020277U, +/*02f4*/ 0x10020277U, +/*02f5*/ 0x18020277U, +/*02f6*/ 0xffffffffU, +/*02f7*/ 0x00020278U, +/*02f8*/ 0x08100278U, +/*02f9*/ 0x18050278U, +/*02fa*/ 0x00060279U, +/*02fb*/ 0x08050279U, +/*02fc*/ 0x10050279U, +/*02fd*/ 0x000e027aU, +/*02fe*/ 0x1005027aU, +/*02ff*/ 0x000e027bU, +/*0300*/ 0x1005027bU, +/*0301*/ 0x000e027cU, +/*0302*/ 0x1005027cU, +/*0303*/ 0x1801027cU, +/*0304*/ 0x0005027dU, +/*0305*/ 0x0805027dU, +/*0306*/ 0x100a027dU, +/*0307*/ 0x000a027eU, +/*0308*/ 0x1005027eU, +/*0309*/ 0x1805027eU, +/*030a*/ 0x000a027fU, +/*030b*/ 0x100a027fU, +/*030c*/ 0x00050280U, +/*030d*/ 0x08050280U, +/*030e*/ 0x100a0280U, +/*030f*/ 0x000a0281U, +/*0310*/ 0x10070281U, +/*0311*/ 0x18070281U, +/*0312*/ 0x00070282U, +/*0313*/ 0x08070282U, +/*0314*/ 0x10070282U, +/*0315*/ 0x18070282U, +/*0316*/ 0xffffffffU, +/*0317*/ 0xffffffffU, +/*0318*/ 0x00040283U, +/*0319*/ 0x08040283U, +/*031a*/ 0x10040283U, +/*031b*/ 0x18040283U, +/*031c*/ 0x00040284U, +/*031d*/ 0xffffffffU, +/*031e*/ 0x08080284U, +/*031f*/ 0x10080284U, +/*0320*/ 0x18040284U, +/*0321*/ 0x00050285U, +/*0322*/ 0x08080285U, +/*0323*/ 0x10050285U, +/*0324*/ 0x18040285U, +/*0325*/ 0x00050286U, +/*0326*/ 0x08080286U, +/*0327*/ 0x10050286U, +/*0328*/ 0x18040286U, +/*0329*/ 0x00050287U, +/*032a*/ 0x08080287U, +/*032b*/ 0x10050287U, +/*032c*/ 0x18040287U, +/*032d*/ 0x00050288U, +/*032e*/ 0x08070288U, +/*032f*/ 0x10080288U, +/*0330*/ 0x00100289U, +/*0331*/ 0x10080289U, +/*0332*/ 0x0010028aU, +/*0333*/ 0x1008028aU, +/*0334*/ 0x0010028bU, +/*0335*/ 0x1008028bU, +/*0336*/ 0x1808028bU, +/*0337*/ 0x0001028cU, +/*0338*/ 0x0801028cU, +/*0339*/ 0x1006028cU, +/*033a*/ 0x1806028cU, +/*033b*/ 0x0006028dU, +/*033c*/ 0x0801028dU, +/*033d*/ 0x1001028dU, +/*033e*/ 0x1803028dU, +/*033f*/ 0x000a028eU, +/*0340*/ 0x100a028eU, +/*0341*/ 0x000a028fU, +/*0342*/ 0xffffffffU, +/*0343*/ 0x100a028fU, +/*0344*/ 0x00040290U, +/*0345*/ 0x08010290U, +/*0346*/ 0x10040290U, +/*0347*/ 0x18070290U, +/*0348*/ 0x00070291U, +/*0349*/ 0x08070291U, +/*034a*/ 0x10070291U, +/*034b*/ 0x18070291U, +/*034c*/ 0x00070292U, +/*034d*/ 0xffffffffU, +/*034e*/ 0xffffffffU, +/*034f*/ 0x08050292U, +/*0350*/ 0x10050292U, +/*0351*/ 0x18040292U, +/*0352*/ 0x00040293U, +/*0353*/ 0x08040293U, +/*0354*/ 0xffffffffU, +/*0355*/ 0x10010293U, +/*0356*/ 0x18010293U, +/*0357*/ 0x00020294U, +/*0358*/ 0x08080294U, +/*0359*/ 0x00200295U, +/*035a*/ 0x00200296U, +/*035b*/ 0x00100297U, +/*035c*/ 0x10020297U, +/*035d*/ 0x18020297U, +/*035e*/ 0x00020298U, +/*035f*/ 0xffffffffU, +/*0360*/ 0x08010298U, +/*0361*/ 0x10010298U, +/*0362*/ 0x18020298U, +/*0363*/ 0x00100299U, +/*0364*/ 0x10100299U, +/*0365*/ 0x0010029aU, +/*0366*/ 0x1008029aU, +/*0367*/ 0x1808029aU, +/*0368*/ 0x0008029bU, +/*0369*/ 0x0808029bU, +/*036a*/ 0x1010029bU, +/*036b*/ 0x0010029cU, +/*036c*/ 0x1010029cU, +/*036d*/ 0x0008029dU, +/*036e*/ 0x0808029dU, +/*036f*/ 0x1008029dU, +/*0370*/ 0x1808029dU, +/*0371*/ 0x0010029eU, +/*0372*/ 0x1010029eU, +/*0373*/ 0x0010029fU, +/*0374*/ 0x1008029fU, +/*0375*/ 0x1808029fU, +/*0376*/ 0x000802a0U, +/*0377*/ 0x080802a0U, +/*0378*/ 0x100802a0U, +/*0379*/ 0x001002a1U, +/*037a*/ 0x101002a1U, +/*037b*/ 0x001002a2U, +/*037c*/ 0x100802a2U, +/*037d*/ 0x180802a2U, +/*037e*/ 0x000802a3U, +/*037f*/ 0x080802a3U, +/*0380*/ 0x101002a3U, +/*0381*/ 0x001002a4U, +/*0382*/ 0x101002a4U, +/*0383*/ 0x000802a5U, +/*0384*/ 0x080802a5U, +/*0385*/ 0x100802a5U, +/*0386*/ 0x180802a5U, +/*0387*/ 0x001002a6U, +/*0388*/ 0x101002a6U, +/*0389*/ 0x001002a7U, +/*038a*/ 0x100802a7U, +/*038b*/ 0x180802a7U, +/*038c*/ 0x000802a8U, +/*038d*/ 0x080802a8U, +/*038e*/ 0x100802a8U, +/*038f*/ 0x001002a9U, +/*0390*/ 0x101002a9U, +/*0391*/ 0x001002aaU, +/*0392*/ 0x100802aaU, +/*0393*/ 0x180802aaU, +/*0394*/ 0x000802abU, +/*0395*/ 0x080802abU, +/*0396*/ 0x101002abU, +/*0397*/ 0x001002acU, +/*0398*/ 0x101002acU, +/*0399*/ 0x000802adU, +/*039a*/ 0x080802adU, +/*039b*/ 0x100802adU, +/*039c*/ 0x180802adU, +/*039d*/ 0x001002aeU, +/*039e*/ 0x101002aeU, +/*039f*/ 0x001002afU, +/*03a0*/ 0x100802afU, +/*03a1*/ 0x180802afU, +/*03a2*/ 0x000802b0U, +/*03a3*/ 0x080802b0U, +/*03a4*/ 0x100802b0U, +/*03a5*/ 0x001002b1U, +/*03a6*/ 0x101002b1U, +/*03a7*/ 0x001002b2U, +/*03a8*/ 0x100802b2U, +/*03a9*/ 0x180802b2U, +/*03aa*/ 0x000802b3U, +/*03ab*/ 0x080802b3U, +/*03ac*/ 0x101002b3U, +/*03ad*/ 0x001002b4U, +/*03ae*/ 0x101002b4U, +/*03af*/ 0x000802b5U, +/*03b0*/ 0x080802b5U, +/*03b1*/ 0x100802b5U, +/*03b2*/ 0x180802b5U, +/*03b3*/ 0x001002b6U, +/*03b4*/ 0x101002b6U, +/*03b5*/ 0x001002b7U, +/*03b6*/ 0x100802b7U, +/*03b7*/ 0x180802b7U, +/*03b8*/ 0x000802b8U, +/*03b9*/ 0x080802b8U, +/*03ba*/ 0x100802b8U, +/*03bb*/ 0x180202b8U, +/*03bc*/ 0x000302b9U, +/*03bd*/ 0x080a02b9U, +/*03be*/ 0x000a02baU, +/*03bf*/ 0x100a02baU, +/*03c0*/ 0x000502bbU, +/*03c1*/ 0x080802bbU, +/*03c2*/ 0x100802bbU, +/*03c3*/ 0x180802bbU, +/*03c4*/ 0x000602bcU, +/*03c5*/ 0x080602bcU, +/*03c6*/ 0x001102bdU, +/*03c7*/ 0x180802bdU, +/*03c8*/ 0x000402beU, +/*03c9*/ 0x080602beU, +/*03ca*/ 0x100802beU, +/*03cb*/ 0x180802beU, +/*03cc*/ 0x000802bfU, +/*03cd*/ 0x080802bfU, +/*03ce*/ 0x100802bfU, +/*03cf*/ 0x180802bfU, +/*03d0*/ 0x000802c0U, +/*03d1*/ 0x080602c0U, +/*03d2*/ 0x100602c0U, +/*03d3*/ 0x001102c1U, +/*03d4*/ 0x180802c1U, +/*03d5*/ 0x000402c2U, +/*03d6*/ 0x080602c2U, +/*03d7*/ 0x100802c2U, +/*03d8*/ 0x180802c2U, +/*03d9*/ 0x000802c3U, +/*03da*/ 0x080802c3U, +/*03db*/ 0x100802c3U, +/*03dc*/ 0x180802c3U, +/*03dd*/ 0x000802c4U, +/*03de*/ 0x080602c4U, +/*03df*/ 0x100602c4U, +/*03e0*/ 0x001102c5U, +/*03e1*/ 0x180802c5U, +/*03e2*/ 0x000402c6U, +/*03e3*/ 0x080602c6U, +/*03e4*/ 0x100802c6U, +/*03e5*/ 0x180802c6U, +/*03e6*/ 0x000802c7U, +/*03e7*/ 0x080802c7U, +/*03e8*/ 0x100402c7U, +/*03e9*/ 0x180402c7U, +/*03ea*/ 0x000402c8U, +/*03eb*/ 0x080402c8U, +/*03ec*/ 0x100402c8U, +/*03ed*/ 0x180402c8U, +/*03ee*/ 0x000402c9U, +/*03ef*/ 0x080402c9U, +/*03f0*/ 0x100402c9U, +/*03f1*/ 0x180402c9U, +/*03f2*/ 0x000402caU, +/*03f3*/ 0x080402caU, +/*03f4*/ 0x100402caU, +/*03f5*/ 0x180402caU, +/*03f6*/ 0x000402cbU, +/*03f7*/ 0x080402cbU, +/*03f8*/ 0x100402cbU, +/*03f9*/ 0x180402cbU, +/*03fa*/ 0x000402ccU, +/*03fb*/ 0x080402ccU, +/*03fc*/ 0x001702cdU, +/*03fd*/ 0x001602ceU, +/*03fe*/ 0x001702cfU, +/*03ff*/ 0x002002d0U, +/*0400*/ 0x002002d1U, +/*0401*/ 0x002002d2U, +/*0402*/ 0x002002d3U, +/*0403*/ 0x002002d4U, +/*0404*/ 0x002002d5U, +/*0405*/ 0x002002d6U, +/*0406*/ 0x002002d7U, +/*0407*/ 0x002002d8U, +/*0408*/ 0x000202d9U, +/*0409*/ 0x080502d9U, +/*040a*/ 0x100502d9U, +/*040b*/ 0x180102d9U, +/*040c*/ 0x000502daU, +/*040d*/ 0x080502daU, +/*040e*/ 0x100502daU, +/*040f*/ 0x180502daU, +/*0410*/ 0x000502dbU, +/*0411*/ 0x080502dbU, +/*0412*/ 0x100502dbU, +/*0413*/ 0x180502dbU, +/*0414*/ 0x000502dcU, +/*0415*/ 0x080502dcU, +/*0416*/ 0x100502dcU, +/*0417*/ 0x180502dcU, +/*0418*/ 0x000502ddU, +/*0419*/ 0x080502ddU, +/*041a*/ 0x100502ddU, +/*041b*/ 0x180502ddU, +/*041c*/ 0x000502deU, +/*041d*/ 0x080502deU, +/*041e*/ 0x100502deU, +/*041f*/ 0x180502deU, +/*0420*/ 0x000502dfU, +/*0421*/ 0x080502dfU, +/*0422*/ 0x100102dfU, +/*0423*/ 0x180202dfU, +/*0424*/ 0x000202e0U, +/*0425*/ 0x080202e0U, +/*0426*/ 0x100202e0U, +/*0427*/ 0x180102e0U, +/*0428*/ 0x000802e1U, +/*0429*/ 0x081502e1U, +/*042a*/ 0x002002e2U, +/*042b*/ 0x001502e3U, +/*042c*/ 0x002002e4U, +/*042d*/ 0x001502e5U, +/*042e*/ 0x002002e6U, +/*042f*/ 0x000702e7U, +/*0430*/ 0x080102e7U, +/*0431*/ 0x100202e7U, +/*0432*/ 0x180602e7U, +/*0433*/ 0x000102e8U, +/*0434*/ 0x080102e8U, +/*0435*/ 0x002002e9U, +/*0436*/ 0x000202eaU, +/*0437*/ 0x002002ebU, +/*0438*/ 0x002002ecU, +/*0439*/ 0x000c02edU, +/*043a*/ 0x100c02edU, +/*043b*/ 0x002002eeU, +/*043c*/ 0x000302efU, +/*043d*/ 0x002002f0U, +/*043e*/ 0x000302f1U, +/*043f*/ 0x002002f2U, +/*0440*/ 0x000302f3U, +/*0441*/ 0x002002f4U, +/*0442*/ 0x000302f5U, +/*0443*/ 0x002002f6U, +/*0444*/ 0x000302f7U, +/*0445*/ 0x002002f8U, +/*0446*/ 0x000302f9U, +/*0447*/ 0x002002faU, +/*0448*/ 0x000302fbU, +/*0449*/ 0x002002fcU, +/*044a*/ 0x000302fdU, +/*044b*/ 0x002002feU, +/*044c*/ 0x000302ffU, +/*044d*/ 0x00200300U, +/*044e*/ 0x00030301U, +/*044f*/ 0x08030301U, +/*0450*/ 0x10020301U, +/*0451*/ 0x18020301U, +/*0452*/ 0x00200302U, +/*0453*/ 0x00200303U, +/*0454*/ 0x00200304U, +/*0455*/ 0x00200305U, +/*0456*/ 0x00040306U, +/*0457*/ 0x001e0307U, +/*0458*/ 0x001e0308U, +/*0459*/ 0x001e0309U, +/*045a*/ 0x001e030aU, +/*045b*/ 0x001e030bU, +/*045c*/ 0x001e030cU, +/*045d*/ 0x001e030dU, +/*045e*/ 0x001e030eU, +/*045f*/ 0x0004030fU, +/*0460*/ 0x0801030fU, +/*0461*/ 0x1010030fU, +/*0462*/ 0x00100310U, +/*0463*/ 0x10100310U, +/*0464*/ 0x00040311U, +/*0465*/ 0x08010311U, +/*0466*/ 0x10080311U, +/*0467*/ 0x18040311U, +/*0468*/ 0x00010312U, +/*0469*/ 0x08080312U, +/*046a*/ 0x10040312U, +/*046b*/ 0x18010312U, +/*046c*/ 0x00080313U, +/*046d*/ 0x08040313U, +/*046e*/ 0x10010313U, +/*046f*/ 0x18080313U, +/*0470*/ 0x00040314U, +/*0471*/ 0x08010314U, +/*0472*/ 0x10080314U, +/*0473*/ 0x18040314U, +/*0474*/ 0x00010315U, +/*0475*/ 0x08080315U, +/*0476*/ 0x10040315U, +/*0477*/ 0x18010315U, +/*0478*/ 0x00080316U, +/*0479*/ 0x08040316U, +/*047a*/ 0x10010316U, +/*047b*/ 0x18080316U, +/*047c*/ 0x00080317U, +/*047d*/ 0x00010318U, +/*047e*/ 0x08050318U, +/*047f*/ 0x10010318U, +/*0480*/ 0x18020318U, +/*0481*/ 0x00010319U, +/*0482*/ 0x08010319U, +/*0483*/ 0x10010319U, +/*0484*/ 0x18010319U, +/*0485*/ 0x0001031aU, +/*0486*/ 0x0801031aU, +/*0487*/ 0x1001031aU, +/*0488*/ 0x1801031aU, +/*0489*/ 0x0001031bU, +/*048a*/ 0x0801031bU, +/*048b*/ 0x1001031bU, +/*048c*/ 0x1801031bU, +/*048d*/ 0x0001031cU, +/*048e*/ 0x0801031cU, +/*048f*/ 0x1001031cU, +/*0490*/ 0x1801031cU, +/*0491*/ 0x0008031dU, +/*0492*/ 0x0808031dU, +/*0493*/ 0x1008031dU, +/*0494*/ 0x1808031dU, + } +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h new file mode 100644 index 0000000..357f8ba --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h @@ -0,0 +1,441 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_H3 0x0400 +#define DDR_PHY_ADR_V_REGSET_OFS_H3 0x0600 +#define DDR_PHY_ADR_I_REGSET_OFS_H3 0x0680 +#define DDR_PHY_ADR_G_REGSET_OFS_H3 0x0700 +#define DDR_PI_REGSET_OFS_H3 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_H3 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_H3 0x80 +#define DDR_PI_REGSET_SIZE_H3 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_H3 88 +#define DDR_PHY_ADR_V_REGSET_NUM_H3 37 +#define DDR_PHY_ADR_I_REGSET_NUM_H3 37 +#define DDR_PHY_ADR_G_REGSET_NUM_H3 59 +#define DDR_PI_REGSET_NUM_H3 181 + +static const uint32_t DDR_PHY_SLICE_REGSET_H3[DDR_PHY_SLICE_REGSET_NUM_H3] = { + /*0400*/ 0x000004f0, + /*0401*/ 0x00000000, + /*0402*/ 0x00000000, + /*0403*/ 0x00000100, + /*0404*/ 0x01003c0c, + /*0405*/ 0x02003c0c, + /*0406*/ 0x00010300, + /*0407*/ 0x04000100, + /*0408*/ 0x00000300, + /*0409*/ 0x000700c0, + /*040a*/ 0x00b00201, + /*040b*/ 0x00000020, + /*040c*/ 0x00000000, + /*040d*/ 0x00000000, + /*040e*/ 0x00000000, + /*040f*/ 0x00000000, + /*0410*/ 0x00000000, + /*0411*/ 0x00000000, + /*0412*/ 0x00000000, + /*0413*/ 0x09000000, + /*0414*/ 0x04080000, + /*0415*/ 0x04080400, + /*0416*/ 0x00000000, + /*0417*/ 0x32103210, + /*0418*/ 0x00800708, + /*0419*/ 0x000f000c, + /*041a*/ 0x00000100, + /*041b*/ 0x55aa55aa, + /*041c*/ 0x33cc33cc, + /*041d*/ 0x0ff00ff0, + /*041e*/ 0x0f0ff0f0, + /*041f*/ 0x00008e38, + /*0420*/ 0x76543210, + /*0421*/ 0x00000001, + /*0422*/ 0x00000000, + /*0423*/ 0x00000000, + /*0424*/ 0x00000000, + /*0425*/ 0x00000000, + /*0426*/ 0x00000000, + /*0427*/ 0x00000000, + /*0428*/ 0x00000000, + /*0429*/ 0x00000000, + /*042a*/ 0x00000000, + /*042b*/ 0x00000000, + /*042c*/ 0x00000000, + /*042d*/ 0x00000000, + /*042e*/ 0x00000000, + /*042f*/ 0x00000000, + /*0430*/ 0x00000000, + /*0431*/ 0x00000000, + /*0432*/ 0x00000000, + /*0433*/ 0x00200000, + /*0434*/ 0x08200820, + /*0435*/ 0x08200820, + /*0436*/ 0x08200820, + /*0437*/ 0x08200820, + /*0438*/ 0x08200820, + /*0439*/ 0x00000820, + /*043a*/ 0x03000300, + /*043b*/ 0x03000300, + /*043c*/ 0x03000300, + /*043d*/ 0x03000300, + /*043e*/ 0x00000300, + /*043f*/ 0x00000000, + /*0440*/ 0x00000000, + /*0441*/ 0x00000000, + /*0442*/ 0x00000000, + /*0443*/ 0x00a000a0, + /*0444*/ 0x00a000a0, + /*0445*/ 0x00a000a0, + /*0446*/ 0x00a000a0, + /*0447*/ 0x00a000a0, + /*0448*/ 0x00a000a0, + /*0449*/ 0x00a000a0, + /*044a*/ 0x00a000a0, + /*044b*/ 0x00a000a0, + /*044c*/ 0x01040109, + /*044d*/ 0x00000200, + /*044e*/ 0x01000000, + /*044f*/ 0x00000200, + /*0450*/ 0x4041a151, + /*0451*/ 0xc00141a0, + /*0452*/ 0x0e0100c0, + /*0453*/ 0x0010000c, + /*0454*/ 0x0c064208, + /*0455*/ 0x000f0c18, + /*0456*/ 0x00e00140, + /*0457*/ 0x00000c20 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_H3[DDR_PHY_ADR_V_REGSET_NUM_H3] = { + /*0600*/ 0x00000000, + /*0601*/ 0x00000000, + /*0602*/ 0x00000000, + /*0603*/ 0x00000000, + /*0604*/ 0x00000000, + /*0605*/ 0x00000000, + /*0606*/ 0x00000002, + /*0607*/ 0x00000000, + /*0608*/ 0x00000000, + /*0609*/ 0x00000000, + /*060a*/ 0x00400320, + /*060b*/ 0x00000040, + /*060c*/ 0x00dcba98, + /*060d*/ 0x00000000, + /*060e*/ 0x00dcba98, + /*060f*/ 0x01000000, + /*0610*/ 0x00020003, + /*0611*/ 0x00000000, + /*0612*/ 0x00000000, + /*0613*/ 0x00000000, + /*0614*/ 0x00002a01, + /*0615*/ 0x00000015, + /*0616*/ 0x00000015, + /*0617*/ 0x0000002a, + /*0618*/ 0x00000033, + /*0619*/ 0x0000000c, + /*061a*/ 0x0000000c, + /*061b*/ 0x00000033, + /*061c*/ 0x00418820, + /*061d*/ 0x003f0000, + /*061e*/ 0x0000003f, + /*061f*/ 0x0002006e, + /*0620*/ 0x02000200, + /*0621*/ 0x02000200, + /*0622*/ 0x00000200, + /*0623*/ 0x42080010, + /*0624*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_H3[DDR_PHY_ADR_I_REGSET_NUM_H3] = { + /*0680*/ 0x04040404, + /*0681*/ 0x00000404, + /*0682*/ 0x00000000, + /*0683*/ 0x00000000, + /*0684*/ 0x00000000, + /*0685*/ 0x00000000, + /*0686*/ 0x00000002, + /*0687*/ 0x00000000, + /*0688*/ 0x00000000, + /*0689*/ 0x00000000, + /*068a*/ 0x00400320, + /*068b*/ 0x00000040, + /*068c*/ 0x00000000, + /*068d*/ 0x00000000, + /*068e*/ 0x00000000, + /*068f*/ 0x01000000, + /*0690*/ 0x00020003, + /*0691*/ 0x00000000, + /*0692*/ 0x00000000, + /*0693*/ 0x00000000, + /*0694*/ 0x00002a01, + /*0695*/ 0x00000015, + /*0696*/ 0x00000015, + /*0697*/ 0x0000002a, + /*0698*/ 0x00000033, + /*0699*/ 0x0000000c, + /*069a*/ 0x0000000c, + /*069b*/ 0x00000033, + /*069c*/ 0x00000000, + /*069d*/ 0x00000000, + /*069e*/ 0x00000000, + /*069f*/ 0x0002006e, + /*06a0*/ 0x02000200, + /*06a1*/ 0x02000200, + /*06a2*/ 0x00000200, + /*06a3*/ 0x42080010, + /*06a4*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_H3[DDR_PHY_ADR_G_REGSET_NUM_H3] = { + /*0700*/ 0x00000001, + /*0701*/ 0x00000000, + /*0702*/ 0x00000005, + /*0703*/ 0x04000f00, + /*0704*/ 0x00020080, + /*0705*/ 0x00020055, + /*0706*/ 0x00000000, + /*0707*/ 0x00000000, + /*0708*/ 0x00000000, + /*0709*/ 0x00000050, + /*070a*/ 0x00000000, + /*070b*/ 0x01010100, + /*070c*/ 0x00000200, + /*070d*/ 0x00001102, + /*070e*/ 0x00000000, + /*070f*/ 0x000f1f00, + /*0710*/ 0x0f1f0f1f, + /*0711*/ 0x0f1f0f1f, + /*0712*/ 0x00020003, + /*0713*/ 0x02000200, + /*0714*/ 0x00000200, + /*0715*/ 0x00001102, + /*0716*/ 0x00000064, + /*0717*/ 0x00000000, + /*0718*/ 0x00000000, + /*0719*/ 0x00000502, + /*071a*/ 0x027f6e00, + /*071b*/ 0x007f007f, + /*071c*/ 0x00007f3c, + /*071d*/ 0x00047f6e, + /*071e*/ 0x0003154f, + /*071f*/ 0x0001154f, + /*0720*/ 0x0001154f, + /*0721*/ 0x0001154f, + /*0722*/ 0x0001154f, + /*0723*/ 0x00003fee, + /*0724*/ 0x0001154f, + /*0725*/ 0x00003fee, + /*0726*/ 0x0001154f, + /*0727*/ 0x00007f3c, + /*0728*/ 0x0001154f, + /*0729*/ 0x00000000, + /*072a*/ 0x00000000, + /*072b*/ 0x00000000, + /*072c*/ 0x65000000, + /*072d*/ 0x00000000, + /*072e*/ 0x00000000, + /*072f*/ 0x00000201, + /*0730*/ 0x00000000, + /*0731*/ 0x00000000, + /*0732*/ 0x00000000, + /*0733*/ 0x00000000, + /*0734*/ 0x00000000, + /*0735*/ 0x00000000, + /*0736*/ 0x00000000, + /*0737*/ 0x00000000, + /*0738*/ 0x00000000, + /*0739*/ 0x00000000, + /*073a*/ 0x00000000 +}; + +static const uint32_t DDR_PI_REGSET_H3[DDR_PI_REGSET_NUM_H3] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00000000, + /*0203*/ 0x0000ffff, + /*0204*/ 0x00000000, + /*0205*/ 0x0000ffff, + /*0206*/ 0x00000000, + /*0207*/ 0x304cffff, + /*0208*/ 0x00000200, + /*0209*/ 0x00000200, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x0000304c, + /*020d*/ 0x00000200, + /*020e*/ 0x00000200, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x0000304c, + /*0212*/ 0x00000200, + /*0213*/ 0x00000200, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00010000, + /*0217*/ 0x00000003, + /*0218*/ 0x01000001, + /*0219*/ 0x00000000, + /*021a*/ 0x00000000, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x0f000101, + /*022a*/ 0x08492d25, + /*022b*/ 0x500e0c04, + /*022c*/ 0x0002500e, + /*022d*/ 0x00460003, + /*022e*/ 0x182600cf, + /*022f*/ 0x182600cf, + /*0230*/ 0x00000005, + /*0231*/ 0x00000000, + /*0232*/ 0x00000000, + /*0233*/ 0x00000000, + /*0234*/ 0x00000000, + /*0235*/ 0x00000000, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x01000000, + /*0239*/ 0x00040404, + /*023a*/ 0x01280a00, + /*023b*/ 0x00000000, + /*023c*/ 0x000f0000, + /*023d*/ 0x00001803, + /*023e*/ 0x00000000, + /*023f*/ 0x00000000, + /*0240*/ 0x00060002, + /*0241*/ 0x00010001, + /*0242*/ 0x01000101, + /*0243*/ 0x04020201, + /*0244*/ 0x00080804, + /*0245*/ 0x00000000, + /*0246*/ 0x08030000, + /*0247*/ 0x15150408, + /*0248*/ 0x00000000, + /*0249*/ 0x00000000, + /*024a*/ 0x00000000, + /*024b*/ 0x001e0f0f, + /*024c*/ 0x00000000, + /*024d*/ 0x01000300, + /*024e*/ 0x00000000, + /*024f*/ 0x00000000, + /*0250*/ 0x01000000, + /*0251*/ 0x00010101, + /*0252*/ 0x000e0e0e, + /*0253*/ 0x000c0c0c, + /*0254*/ 0x02060601, + /*0255*/ 0x00000000, + /*0256*/ 0x00000003, + /*0257*/ 0x00181703, + /*0258*/ 0x00280006, + /*0259*/ 0x00280016, + /*025a*/ 0x00000016, + /*025b*/ 0x00000000, + /*025c*/ 0x00000000, + /*025d*/ 0x00000000, + /*025e*/ 0x140a0000, + /*025f*/ 0x0005010a, + /*0260*/ 0x03018d03, + /*0261*/ 0x000a018d, + /*0262*/ 0x00060100, + /*0263*/ 0x01000006, + /*0264*/ 0x018e018e, + /*0265*/ 0x018e0100, + /*0266*/ 0x1111018e, + /*0267*/ 0x10010204, + /*0268*/ 0x09090650, + /*0269*/ 0x20110202, + /*026a*/ 0x00201000, + /*026b*/ 0x00201000, + /*026c*/ 0x04041000, + /*026d*/ 0x18020100, + /*026e*/ 0x00010118, + /*026f*/ 0x004b004a, + /*0270*/ 0x050f0000, + /*0271*/ 0x0c01021e, + /*0272*/ 0x34000000, + /*0273*/ 0x00000000, + /*0274*/ 0x00000000, + /*0275*/ 0x00000000, + /*0276*/ 0x312ed400, + /*0277*/ 0xd4111132, + /*0278*/ 0x1132312e, + /*0279*/ 0x312ed411, + /*027a*/ 0x00111132, + /*027b*/ 0x32312ed4, + /*027c*/ 0x2ed41111, + /*027d*/ 0x11113231, + /*027e*/ 0x32312ed4, + /*027f*/ 0xd4001111, + /*0280*/ 0x1132312e, + /*0281*/ 0x312ed411, + /*0282*/ 0xd4111132, + /*0283*/ 0x1132312e, + /*0284*/ 0x2ed40011, + /*0285*/ 0x11113231, + /*0286*/ 0x32312ed4, + /*0287*/ 0x2ed41111, + /*0288*/ 0x11113231, + /*0289*/ 0x00020000, + /*028a*/ 0x018d018d, + /*028b*/ 0x0c08018d, + /*028c*/ 0x1f121d22, + /*028d*/ 0x4301b344, + /*028e*/ 0x10172006, + /*028f*/ 0x121d220c, + /*0290*/ 0x01b3441f, + /*0291*/ 0x17200643, + /*0292*/ 0x1d220c10, + /*0293*/ 0x00001f12, + /*0294*/ 0x4301b344, + /*0295*/ 0x10172006, + /*0296*/ 0x00020002, + /*0297*/ 0x00020002, + /*0298*/ 0x00020002, + /*0299*/ 0x00020002, + /*029a*/ 0x00020002, + /*029b*/ 0x00000000, + /*029c*/ 0x00000000, + /*029d*/ 0x00000000, + /*029e*/ 0x00000000, + /*029f*/ 0x00000000, + /*02a0*/ 0x00000000, + /*02a1*/ 0x00000000, + /*02a2*/ 0x00000000, + /*02a3*/ 0x00000000, + /*02a4*/ 0x00000000, + /*02a5*/ 0x00000000, + /*02a6*/ 0x00000000, + /*02a7*/ 0x01000400, + /*02a8*/ 0x00304c00, + /*02a9*/ 0x0001e2f8, + /*02aa*/ 0x0000304c, + /*02ab*/ 0x0001e2f8, + /*02ac*/ 0x0000304c, + /*02ad*/ 0x0001e2f8, + /*02ae*/ 0x08000000, + /*02af*/ 0x00000100, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000002 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h new file mode 100644 index 0000000..e5258af --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_H3VER2 0x0400 +#define DDR_PHY_ADR_V_REGSET_OFS_H3VER2 0x0600 +#define DDR_PHY_ADR_I_REGSET_OFS_H3VER2 0x0640 +#define DDR_PHY_ADR_G_REGSET_OFS_H3VER2 0x0680 +#define DDR_PI_REGSET_OFS_H3VER2 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_H3VER2 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_H3VER2 0x40 +#define DDR_PHY_ADR_I_REGSET_SIZE_H3VER2 0x40 +#define DDR_PHY_ADR_G_REGSET_SIZE_H3VER2 0x80 +#define DDR_PI_REGSET_SIZE_H3VER2 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_H3VER2 97 +#define DDR_PHY_ADR_V_REGSET_NUM_H3VER2 37 +#define DDR_PHY_ADR_I_REGSET_NUM_H3VER2 37 +#define DDR_PHY_ADR_G_REGSET_NUM_H3VER2 79 +#define DDR_PI_REGSET_NUM_H3VER2 245 + +static const uint32_t DDR_PHY_SLICE_REGSET_H3VER2 + [DDR_PHY_SLICE_REGSET_NUM_H3VER2] = { + /*0400*/ 0x76543210, + /*0401*/ 0x0004f008, + /*0402*/ 0x00020133, + /*0403*/ 0x00000000, + /*0404*/ 0x00000000, + /*0405*/ 0x00010000, + /*0406*/ 0x016e6e0e, + /*0407*/ 0x026e6e0e, + /*0408*/ 0x00010300, + /*0409*/ 0x04000100, + /*040a*/ 0x01000000, + /*040b*/ 0x00000000, + /*040c*/ 0x00000000, + /*040d*/ 0x00000100, + /*040e*/ 0x001700c0, + /*040f*/ 0x020100b0, + /*0410*/ 0x00030020, + /*0411*/ 0x00000000, + /*0412*/ 0x00000000, + /*0413*/ 0x00000000, + /*0414*/ 0x00000000, + /*0415*/ 0x00000000, + /*0416*/ 0x00000000, + /*0417*/ 0x00000000, + /*0418*/ 0x09000000, + /*0419*/ 0x04080000, + /*041a*/ 0x04080400, + /*041b*/ 0x08000000, + /*041c*/ 0x0c008007, + /*041d*/ 0x00000f00, + /*041e*/ 0x00000100, + /*041f*/ 0x55aa55aa, + /*0420*/ 0x33cc33cc, + /*0421*/ 0x0ff00ff0, + /*0422*/ 0x0f0ff0f0, + /*0423*/ 0x00018e38, + /*0424*/ 0x00000000, + /*0425*/ 0x00000000, + /*0426*/ 0x00000000, + /*0427*/ 0x00000000, + /*0428*/ 0x00000000, + /*0429*/ 0x00000000, + /*042a*/ 0x00000000, + /*042b*/ 0x00000000, + /*042c*/ 0x00000000, + /*042d*/ 0x00000000, + /*042e*/ 0x00000000, + /*042f*/ 0x00000000, + /*0430*/ 0x00000000, + /*0431*/ 0x00000000, + /*0432*/ 0x00000000, + /*0433*/ 0x00000000, + /*0434*/ 0x00000000, + /*0435*/ 0x00000000, + /*0436*/ 0x00000000, + /*0437*/ 0x00000000, + /*0438*/ 0x00000104, + /*0439*/ 0x00082020, + /*043a*/ 0x08200820, + /*043b*/ 0x08200820, + /*043c*/ 0x08200820, + /*043d*/ 0x08200820, + /*043e*/ 0x08200820, + /*043f*/ 0x00000000, + /*0440*/ 0x00000000, + /*0441*/ 0x03000300, + /*0442*/ 0x03000300, + /*0443*/ 0x03000300, + /*0444*/ 0x03000300, + /*0445*/ 0x00000300, + /*0446*/ 0x00000000, + /*0447*/ 0x00000000, + /*0448*/ 0x00000000, + /*0449*/ 0x00000000, + /*044a*/ 0x00000000, + /*044b*/ 0x00a000a0, + /*044c*/ 0x00a000a0, + /*044d*/ 0x00a000a0, + /*044e*/ 0x00a000a0, + /*044f*/ 0x00a000a0, + /*0450*/ 0x00a000a0, + /*0451*/ 0x00a000a0, + /*0452*/ 0x00a000a0, + /*0453*/ 0x00a000a0, + /*0454*/ 0x01040109, + /*0455*/ 0x00000200, + /*0456*/ 0x01000000, + /*0457*/ 0x00000200, + /*0458*/ 0x00000004, + /*0459*/ 0x4041a151, + /*045a*/ 0xc00141a0, + /*045b*/ 0x0e0000c0, + /*045c*/ 0x0010000c, + /*045d*/ 0x063e4208, + /*045e*/ 0x0f0c180c, + /*045f*/ 0x00e00140, + /*0460*/ 0x00000c20 +}; + +static const uint32_t + DDR_PHY_ADR_V_REGSET_H3VER2[DDR_PHY_ADR_V_REGSET_NUM_H3VER2] = { + /*0600*/ 0x00000000, + /*0601*/ 0x00000000, + /*0602*/ 0x00000000, + /*0603*/ 0x00000000, + /*0604*/ 0x00000000, + /*0605*/ 0x00000000, + /*0606*/ 0x00000000, + /*0607*/ 0x00010000, + /*0608*/ 0x00000200, + /*0609*/ 0x00000000, + /*060a*/ 0x00000000, + /*060b*/ 0x00000000, + /*060c*/ 0x00400320, + /*060d*/ 0x00000040, + /*060e*/ 0x00dcba98, + /*060f*/ 0x03000000, + /*0610*/ 0x00000200, + /*0611*/ 0x00000000, + /*0612*/ 0x00000000, + /*0613*/ 0x00000000, + /*0614*/ 0x0000002a, + /*0615*/ 0x00000015, + /*0616*/ 0x00000015, + /*0617*/ 0x0000002a, + /*0618*/ 0x00000033, + /*0619*/ 0x0000000c, + /*061a*/ 0x0000000c, + /*061b*/ 0x00000033, + /*061c*/ 0x00418820, + /*061d*/ 0x003f0000, + /*061e*/ 0x0000003f, + /*061f*/ 0x0002c06e, + /*0620*/ 0x02c002c0, + /*0621*/ 0x02c002c0, + /*0622*/ 0x000002c0, + /*0623*/ 0x42080010, + /*0624*/ 0x0000033e +}; + +static const uint32_t + DDR_PHY_ADR_I_REGSET_H3VER2[DDR_PHY_ADR_I_REGSET_NUM_H3VER2] = { + /*0640*/ 0x00000000, + /*0641*/ 0x00000000, + /*0642*/ 0x00000000, + /*0643*/ 0x00000000, + /*0644*/ 0x00000000, + /*0645*/ 0x00000000, + /*0646*/ 0x00000000, + /*0647*/ 0x00000000, + /*0648*/ 0x00000000, + /*0649*/ 0x00000000, + /*064a*/ 0x00000000, + /*064b*/ 0x00000000, + /*064c*/ 0x00000000, + /*064d*/ 0x00000000, + /*064e*/ 0x00000000, + /*064f*/ 0x00000000, + /*0650*/ 0x00000000, + /*0651*/ 0x00000000, + /*0652*/ 0x00000000, + /*0653*/ 0x00000000, + /*0654*/ 0x00000000, + /*0655*/ 0x00000000, + /*0656*/ 0x00000000, + /*0657*/ 0x00000000, + /*0658*/ 0x00000000, + /*0659*/ 0x00000000, + /*065a*/ 0x00000000, + /*065b*/ 0x00000000, + /*065c*/ 0x00000000, + /*065d*/ 0x00000000, + /*065e*/ 0x00000000, + /*065f*/ 0x00000000, + /*0660*/ 0x00000000, + /*0661*/ 0x00000000, + /*0662*/ 0x00000000, + /*0663*/ 0x00000000, + /*0664*/ 0x00000000 +}; + +static const uint32_t + DDR_PHY_ADR_G_REGSET_H3VER2[DDR_PHY_ADR_G_REGSET_NUM_H3VER2] = { + /*0680*/ 0x00000000, + /*0681*/ 0x00000100, + /*0682*/ 0x00000000, + /*0683*/ 0x00050000, + /*0684*/ 0x0f000000, + /*0685*/ 0x00800400, + /*0686*/ 0x00020032, + /*0687*/ 0x00020055, + /*0688*/ 0x00000000, + /*0689*/ 0x00000000, + /*068a*/ 0x00000000, + /*068b*/ 0x00000050, + /*068c*/ 0x00000000, + /*068d*/ 0x01010100, + /*068e*/ 0x01000200, + /*068f*/ 0x00000000, + /*0690*/ 0x00010100, + /*0691*/ 0x00000000, + /*0692*/ 0x00000000, + /*0693*/ 0x00000000, + /*0694*/ 0x00000000, + /*0695*/ 0x00005064, + /*0696*/ 0x01421142, + /*0697*/ 0x00000142, + /*0698*/ 0x00000000, + /*0699*/ 0x000f1100, + /*069a*/ 0x0f110f11, + /*069b*/ 0x09000f11, + /*069c*/ 0x00000003, + /*069d*/ 0x0002c000, + /*069e*/ 0x02c002c0, + /*069f*/ 0x000002c0, + /*06a0*/ 0x03421342, + /*06a1*/ 0x00000342, + /*06a2*/ 0x00000000, + /*06a3*/ 0x00000000, + /*06a4*/ 0x05020000, + /*06a5*/ 0x14000000, + /*06a6*/ 0x027f6e00, + /*06a7*/ 0x047f027f, + /*06a8*/ 0x00027f6e, + /*06a9*/ 0x00047f6e, + /*06aa*/ 0x0003554f, + /*06ab*/ 0x0001554f, + /*06ac*/ 0x0001554f, + /*06ad*/ 0x0001554f, + /*06ae*/ 0x0001554f, + /*06af*/ 0x00003fee, + /*06b0*/ 0x0001554f, + /*06b1*/ 0x00003fee, + /*06b2*/ 0x0001554f, + /*06b3*/ 0x00027f6e, + /*06b4*/ 0x0001554f, + /*06b5*/ 0x00004011, + /*06b6*/ 0x00004410, + /*06b7*/ 0x00000000, + /*06b8*/ 0x00000000, + /*06b9*/ 0x00000000, + /*06ba*/ 0x00000065, + /*06bb*/ 0x00000000, + /*06bc*/ 0x00020201, + /*06bd*/ 0x00000000, + /*06be*/ 0x03000000, + /*06bf*/ 0x00000008, + /*06c0*/ 0x00000000, + /*06c1*/ 0x00000000, + /*06c2*/ 0x00000000, + /*06c3*/ 0x00000000, + /*06c4*/ 0x00000001, + /*06c5*/ 0x00000000, + /*06c6*/ 0x00000000, + /*06c7*/ 0x00000000, + /*06c8*/ 0x000000e4, + /*06c9*/ 0x00010198, + /*06ca*/ 0x00000000, + /*06cb*/ 0x00000000, + /*06cc*/ 0x07010000, + /*06cd*/ 0x00000104, + /*06ce*/ 0x00000000 +}; + +static const uint32_t DDR_PI_REGSET_H3VER2[DDR_PI_REGSET_NUM_H3VER2] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00640000, + /*0203*/ 0x00000000, + /*0204*/ 0x0000ffff, + /*0205*/ 0x00000000, + /*0206*/ 0x0000ffff, + /*0207*/ 0x00000000, + /*0208*/ 0x0000ffff, + /*0209*/ 0x0000304c, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x00000200, + /*020d*/ 0x00000200, + /*020e*/ 0x0000304c, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x00000200, + /*0212*/ 0x00000200, + /*0213*/ 0x0000304c, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00000200, + /*0217*/ 0x00000200, + /*0218*/ 0x00010000, + /*0219*/ 0x00000003, + /*021a*/ 0x01000001, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x00000000, + /*022a*/ 0x00000000, + /*022b*/ 0x0f000101, + /*022c*/ 0x08492d25, + /*022d*/ 0x500e0c04, + /*022e*/ 0x0002500e, + /*022f*/ 0x00000301, + /*0230*/ 0x00000046, + /*0231*/ 0x000000cf, + /*0232*/ 0x00001826, + /*0233*/ 0x000000cf, + /*0234*/ 0x00001826, + /*0235*/ 0x00000005, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x00000000, + /*0239*/ 0x00000000, + /*023a*/ 0x00000000, + /*023b*/ 0x00000000, + /*023c*/ 0x00000000, + /*023d*/ 0x00000000, + /*023e*/ 0x04010000, + /*023f*/ 0x00000404, + /*0240*/ 0x0101280a, + /*0241*/ 0x00000000, + /*0242*/ 0x00000000, + /*0243*/ 0x0003000f, + /*0244*/ 0x00000018, + /*0245*/ 0x00000000, + /*0246*/ 0x00000000, + /*0247*/ 0x00060002, + /*0248*/ 0x00010001, + /*0249*/ 0x01000101, + /*024a*/ 0x04020201, + /*024b*/ 0x00080804, + /*024c*/ 0x00000000, + /*024d*/ 0x08030000, + /*024e*/ 0x15150408, + /*024f*/ 0x00000000, + /*0250*/ 0x00000000, + /*0251*/ 0x00000000, + /*0252*/ 0x0f0f0000, + /*0253*/ 0x0000001e, + /*0254*/ 0x00000000, + /*0255*/ 0x01000300, + /*0256*/ 0x00000100, + /*0257*/ 0x00000000, + /*0258*/ 0x00000000, + /*0259*/ 0x01000000, + /*025a*/ 0x00000101, + /*025b*/ 0x55555a5a, + /*025c*/ 0x55555a5a, + /*025d*/ 0x55555a5a, + /*025e*/ 0x55555a5a, + /*025f*/ 0x0e0e0001, + /*0260*/ 0x0c0c000e, + /*0261*/ 0x0601000c, + /*0262*/ 0x17170106, + /*0263*/ 0x00020202, + /*0264*/ 0x03000000, + /*0265*/ 0x00000000, + /*0266*/ 0x00181703, + /*0267*/ 0x00280006, + /*0268*/ 0x00280016, + /*0269*/ 0x00000016, + /*026a*/ 0x00000000, + /*026b*/ 0x00000000, + /*026c*/ 0x00000000, + /*026d*/ 0x0a000000, + /*026e*/ 0x00010a14, + /*026f*/ 0x00030005, + /*0270*/ 0x0003018d, + /*0271*/ 0x000a018d, + /*0272*/ 0x00060100, + /*0273*/ 0x01000006, + /*0274*/ 0x018e018e, + /*0275*/ 0x018e0100, + /*0276*/ 0x1111018e, + /*0277*/ 0x10010204, + /*0278*/ 0x09090650, + /*0279*/ 0xff110202, + /*027a*/ 0x00ff1000, + /*027b*/ 0x00ff1000, + /*027c*/ 0x04041000, + /*027d*/ 0x18020100, + /*027e*/ 0x01010018, + /*027f*/ 0x004a004a, + /*0280*/ 0x004b004a, + /*0281*/ 0x050f0000, + /*0282*/ 0x0c01021e, + /*0283*/ 0x34000000, + /*0284*/ 0x00000000, + /*0285*/ 0x00000000, + /*0286*/ 0x00000000, + /*0287*/ 0x00000000, + /*0288*/ 0x36312ed4, + /*0289*/ 0x2ed41111, + /*028a*/ 0x11113631, + /*028b*/ 0x36312ed4, + /*028c*/ 0xd4001111, + /*028d*/ 0x1136312e, + /*028e*/ 0x312ed411, + /*028f*/ 0xd4111136, + /*0290*/ 0x1136312e, + /*0291*/ 0x2ed40011, + /*0292*/ 0x11113631, + /*0293*/ 0x36312ed4, + /*0294*/ 0x2ed41111, + /*0295*/ 0x11113631, + /*0296*/ 0x312ed400, + /*0297*/ 0xd4111136, + /*0298*/ 0x1136312e, + /*0299*/ 0x312ed411, + /*029a*/ 0x00111136, + /*029b*/ 0x018d0200, + /*029c*/ 0x018d018d, + /*029d*/ 0x1d220c08, + /*029e*/ 0x00001f12, + /*029f*/ 0x4301b344, + /*02a0*/ 0x10172006, + /*02a1*/ 0x121d220c, + /*02a2*/ 0x01b3441f, + /*02a3*/ 0x17200643, + /*02a4*/ 0x1d220c10, + /*02a5*/ 0x00001f12, + /*02a6*/ 0x4301b344, + /*02a7*/ 0x10172006, + /*02a8*/ 0x00020002, + /*02a9*/ 0x00020002, + /*02aa*/ 0x00020002, + /*02ab*/ 0x00020002, + /*02ac*/ 0x00020002, + /*02ad*/ 0x00000000, + /*02ae*/ 0x00000000, + /*02af*/ 0x00000000, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000000, + /*02b5*/ 0x00000000, + /*02b6*/ 0x00000000, + /*02b7*/ 0x00000000, + /*02b8*/ 0x00000000, + /*02b9*/ 0x00000400, + /*02ba*/ 0x05040302, + /*02bb*/ 0x01000f0e, + /*02bc*/ 0x07060504, + /*02bd*/ 0x03020100, + /*02be*/ 0x02010000, + /*02bf*/ 0x00000103, + /*02c0*/ 0x0000304c, + /*02c1*/ 0x0001e2f8, + /*02c2*/ 0x0000304c, + /*02c3*/ 0x0001e2f8, + /*02c4*/ 0x0000304c, + /*02c5*/ 0x0001e2f8, + /*02c6*/ 0x08000000, + /*02c7*/ 0x00000100, + /*02c8*/ 0x00000000, + /*02c9*/ 0x00000000, + /*02ca*/ 0x00000000, + /*02cb*/ 0x00000000, + /*02cc*/ 0x00010000, + /*02cd*/ 0x00000000, + /*02ce*/ 0x00000000, + /*02cf*/ 0x00000000, + /*02d0*/ 0x00000000, + /*02d1*/ 0x00000000, + /*02d2*/ 0x00000000, + /*02d3*/ 0x00000000, + /*02d4*/ 0x00000000, + /*02d5*/ 0x00000000, + /*02d6*/ 0x00000000, + /*02d7*/ 0x00000000, + /*02d8*/ 0x00000000, + /*02d9*/ 0x00000000, + /*02da*/ 0x00000000, + /*02db*/ 0x00000000, + /*02dc*/ 0x00000000, + /*02dd*/ 0x00000000, + /*02de*/ 0x00000000, + /*02df*/ 0x00000000, + /*02e0*/ 0x00000000, + /*02e1*/ 0x00000000, + /*02e2*/ 0x00000000, + /*02e3*/ 0x00000000, + /*02e4*/ 0x00000000, + /*02e5*/ 0x00000000, + /*02e6*/ 0x00000000, + /*02e7*/ 0x00000000, + /*02e8*/ 0x00000000, + /*02e9*/ 0x00000000, + /*02ea*/ 0x00000000, + /*02eb*/ 0x00000000, + /*02ec*/ 0x00000000, + /*02ed*/ 0x00000000, + /*02ee*/ 0x00000002, + /*02ef*/ 0x00000000, + /*02f0*/ 0x00000000, + /*02f1*/ 0x00000000, + /*02f2*/ 0x00000000, + /*02f3*/ 0x00000000, + /*02f4*/ 0x00000000 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h new file mode 100644 index 0000000..b491f0e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h @@ -0,0 +1,468 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_M3 0x0800 +#define DDR_PHY_ADR_V_REGSET_OFS_M3 0x0a00 +#define DDR_PHY_ADR_I_REGSET_OFS_M3 0x0a80 +#define DDR_PHY_ADR_G_REGSET_OFS_M3 0x0b80 +#define DDR_PI_REGSET_OFS_M3 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_M3 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_M3 0x80 +#define DDR_PI_REGSET_SIZE_M3 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_M3 89 +#define DDR_PHY_ADR_V_REGSET_NUM_M3 37 +#define DDR_PHY_ADR_I_REGSET_NUM_M3 37 +#define DDR_PHY_ADR_G_REGSET_NUM_M3 64 +#define DDR_PI_REGSET_NUM_M3 202 + +static const uint32_t DDR_PHY_SLICE_REGSET_M3[DDR_PHY_SLICE_REGSET_NUM_M3] = { + /*0800*/ 0x76543210, + /*0801*/ 0x0004f008, + /*0802*/ 0x00000000, + /*0803*/ 0x00000000, + /*0804*/ 0x00010000, + /*0805*/ 0x036e6e0e, + /*0806*/ 0x026e6e0e, + /*0807*/ 0x00010300, + /*0808*/ 0x04000100, + /*0809*/ 0x00000300, + /*080a*/ 0x001700c0, + /*080b*/ 0x00b00201, + /*080c*/ 0x00030020, + /*080d*/ 0x00000000, + /*080e*/ 0x00000000, + /*080f*/ 0x00000000, + /*0810*/ 0x00000000, + /*0811*/ 0x00000000, + /*0812*/ 0x00000000, + /*0813*/ 0x00000000, + /*0814*/ 0x09000000, + /*0815*/ 0x04080000, + /*0816*/ 0x04080400, + /*0817*/ 0x00000000, + /*0818*/ 0x32103210, + /*0819*/ 0x00800708, + /*081a*/ 0x000f000c, + /*081b*/ 0x00000100, + /*081c*/ 0x55aa55aa, + /*081d*/ 0x33cc33cc, + /*081e*/ 0x0ff00ff0, + /*081f*/ 0x0f0ff0f0, + /*0820*/ 0x00018e38, + /*0821*/ 0x00000000, + /*0822*/ 0x00000000, + /*0823*/ 0x00000000, + /*0824*/ 0x00000000, + /*0825*/ 0x00000000, + /*0826*/ 0x00000000, + /*0827*/ 0x00000000, + /*0828*/ 0x00000000, + /*0829*/ 0x00000000, + /*082a*/ 0x00000000, + /*082b*/ 0x00000000, + /*082c*/ 0x00000000, + /*082d*/ 0x00000000, + /*082e*/ 0x00000000, + /*082f*/ 0x00000000, + /*0830*/ 0x00000000, + /*0831*/ 0x00000000, + /*0832*/ 0x00000000, + /*0833*/ 0x00200000, + /*0834*/ 0x08200820, + /*0835*/ 0x08200820, + /*0836*/ 0x08200820, + /*0837*/ 0x08200820, + /*0838*/ 0x08200820, + /*0839*/ 0x00000820, + /*083a*/ 0x03000300, + /*083b*/ 0x03000300, + /*083c*/ 0x03000300, + /*083d*/ 0x03000300, + /*083e*/ 0x00000300, + /*083f*/ 0x00000000, + /*0840*/ 0x00000000, + /*0841*/ 0x00000000, + /*0842*/ 0x00000000, + /*0843*/ 0x00a00000, + /*0844*/ 0x00a000a0, + /*0845*/ 0x00a000a0, + /*0846*/ 0x00a000a0, + /*0847*/ 0x00a000a0, + /*0848*/ 0x00a000a0, + /*0849*/ 0x00a000a0, + /*084a*/ 0x00a000a0, + /*084b*/ 0x00a000a0, + /*084c*/ 0x010900a0, + /*084d*/ 0x02000104, + /*084e*/ 0x00000000, + /*084f*/ 0x00010000, + /*0850*/ 0x00000200, + /*0851*/ 0x4041a151, + /*0852*/ 0xc00141a0, + /*0853*/ 0x0e0100c0, + /*0854*/ 0x0010000c, + /*0855*/ 0x0c064208, + /*0856*/ 0x000f0c18, + /*0857*/ 0x00e00140, + /*0858*/ 0x00000c20 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_M3[DDR_PHY_ADR_V_REGSET_NUM_M3] = { + /*0a00*/ 0x00000000, + /*0a01*/ 0x00000000, + /*0a02*/ 0x00000000, + /*0a03*/ 0x00000000, + /*0a04*/ 0x00000000, + /*0a05*/ 0x00000000, + /*0a06*/ 0x00000002, + /*0a07*/ 0x00000000, + /*0a08*/ 0x00000000, + /*0a09*/ 0x00000000, + /*0a0a*/ 0x00400320, + /*0a0b*/ 0x00000040, + /*0a0c*/ 0x00dcba98, + /*0a0d*/ 0x00000000, + /*0a0e*/ 0x00dcba98, + /*0a0f*/ 0x01000000, + /*0a10*/ 0x00020003, + /*0a11*/ 0x00000000, + /*0a12*/ 0x00000000, + /*0a13*/ 0x00000000, + /*0a14*/ 0x0000002a, + /*0a15*/ 0x00000015, + /*0a16*/ 0x00000015, + /*0a17*/ 0x0000002a, + /*0a18*/ 0x00000033, + /*0a19*/ 0x0000000c, + /*0a1a*/ 0x0000000c, + /*0a1b*/ 0x00000033, + /*0a1c*/ 0x0a418820, + /*0a1d*/ 0x003f0000, + /*0a1e*/ 0x0000003f, + /*0a1f*/ 0x0002c06e, + /*0a20*/ 0x02c002c0, + /*0a21*/ 0x02c002c0, + /*0a22*/ 0x000002c0, + /*0a23*/ 0x42080010, + /*0a24*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_M3[DDR_PHY_ADR_I_REGSET_NUM_M3] = { + /*0a80*/ 0x04040404, + /*0a81*/ 0x00000404, + /*0a82*/ 0x00000000, + /*0a83*/ 0x00000000, + /*0a84*/ 0x00000000, + /*0a85*/ 0x00000000, + /*0a86*/ 0x00000002, + /*0a87*/ 0x00000000, + /*0a88*/ 0x00000000, + /*0a89*/ 0x00000000, + /*0a8a*/ 0x00400320, + /*0a8b*/ 0x00000040, + /*0a8c*/ 0x00000000, + /*0a8d*/ 0x00000000, + /*0a8e*/ 0x00000000, + /*0a8f*/ 0x01000000, + /*0a90*/ 0x00020003, + /*0a91*/ 0x00000000, + /*0a92*/ 0x00000000, + /*0a93*/ 0x00000000, + /*0a94*/ 0x0000002a, + /*0a95*/ 0x00000015, + /*0a96*/ 0x00000015, + /*0a97*/ 0x0000002a, + /*0a98*/ 0x00000033, + /*0a99*/ 0x0000000c, + /*0a9a*/ 0x0000000c, + /*0a9b*/ 0x00000033, + /*0a9c*/ 0x00000000, + /*0a9d*/ 0x00000000, + /*0a9e*/ 0x00000000, + /*0a9f*/ 0x0002c06e, + /*0aa0*/ 0x02c002c0, + /*0aa1*/ 0x02c002c0, + /*0aa2*/ 0x000002c0, + /*0aa3*/ 0x42080010, + /*0aa4*/ 0x00000003 +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_M3[DDR_PHY_ADR_G_REGSET_NUM_M3] = { + /*0b80*/ 0x00000001, + /*0b81*/ 0x00000000, + /*0b82*/ 0x00000005, + /*0b83*/ 0x04000f00, + /*0b84*/ 0x00020080, + /*0b85*/ 0x00020055, + /*0b86*/ 0x00000000, + /*0b87*/ 0x00000000, + /*0b88*/ 0x00000000, + /*0b89*/ 0x00000050, + /*0b8a*/ 0x00000000, + /*0b8b*/ 0x01010100, + /*0b8c*/ 0x00000600, + /*0b8d*/ 0x50640000, + /*0b8e*/ 0x01421142, + /*0b8f*/ 0x00000142, + /*0b90*/ 0x00000000, + /*0b91*/ 0x000f1600, + /*0b92*/ 0x0f160f16, + /*0b93*/ 0x0f160f16, + /*0b94*/ 0x00000003, + /*0b95*/ 0x0002c000, + /*0b96*/ 0x02c002c0, + /*0b97*/ 0x000002c0, + /*0b98*/ 0x03421342, + /*0b99*/ 0x00000342, + /*0b9a*/ 0x00000000, + /*0b9b*/ 0x00000000, + /*0b9c*/ 0x05020000, + /*0b9d*/ 0x00000000, + /*0b9e*/ 0x00027f6e, + /*0b9f*/ 0x047f027f, + /*0ba0*/ 0x00027f6e, + /*0ba1*/ 0x00047f6e, + /*0ba2*/ 0x0003554f, + /*0ba3*/ 0x0001554f, + /*0ba4*/ 0x0001554f, + /*0ba5*/ 0x0001554f, + /*0ba6*/ 0x0001554f, + /*0ba7*/ 0x00003fee, + /*0ba8*/ 0x0001554f, + /*0ba9*/ 0x00003fee, + /*0baa*/ 0x0001554f, + /*0bab*/ 0x00027f6e, + /*0bac*/ 0x0001554f, + /*0bad*/ 0x00000000, + /*0bae*/ 0x00000000, + /*0baf*/ 0x00000000, + /*0bb0*/ 0x65000000, + /*0bb1*/ 0x00000000, + /*0bb2*/ 0x00000000, + /*0bb3*/ 0x00000201, + /*0bb4*/ 0x00000000, + /*0bb5*/ 0x00000000, + /*0bb6*/ 0x00000000, + /*0bb7*/ 0x00000000, + /*0bb8*/ 0x00000000, + /*0bb9*/ 0x00000000, + /*0bba*/ 0x00000000, + /*0bbb*/ 0x00000000, + /*0bbc*/ 0x06e40000, + /*0bbd*/ 0x00000000, + /*0bbe*/ 0x00000000, + /*0bbf*/ 0x00010000 +}; + +static const uint32_t DDR_PI_REGSET_M3[DDR_PI_REGSET_NUM_M3] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000100, + /*0202*/ 0x00000000, + /*0203*/ 0x0000ffff, + /*0204*/ 0x00000000, + /*0205*/ 0x0000ffff, + /*0206*/ 0x00000000, + /*0207*/ 0x304cffff, + /*0208*/ 0x00000200, + /*0209*/ 0x00000200, + /*020a*/ 0x00000200, + /*020b*/ 0x00000200, + /*020c*/ 0x0000304c, + /*020d*/ 0x00000200, + /*020e*/ 0x00000200, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x0000304c, + /*0212*/ 0x00000200, + /*0213*/ 0x00000200, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00010000, + /*0217*/ 0x00000003, + /*0218*/ 0x01000001, + /*0219*/ 0x00000000, + /*021a*/ 0x00000000, + /*021b*/ 0x00000000, + /*021c*/ 0x00000000, + /*021d*/ 0x00000000, + /*021e*/ 0x00000000, + /*021f*/ 0x00000000, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x0f000101, + /*022a*/ 0x08492d25, + /*022b*/ 0x0e0c0004, + /*022c*/ 0x000e5000, + /*022d*/ 0x00000250, + /*022e*/ 0x00460003, + /*022f*/ 0x182600cf, + /*0230*/ 0x182600cf, + /*0231*/ 0x00000005, + /*0232*/ 0x00000000, + /*0233*/ 0x00000000, + /*0234*/ 0x00000000, + /*0235*/ 0x00000000, + /*0236*/ 0x00000000, + /*0237*/ 0x00000000, + /*0238*/ 0x00000000, + /*0239*/ 0x01000000, + /*023a*/ 0x00040404, + /*023b*/ 0x01280a00, + /*023c*/ 0x00000000, + /*023d*/ 0x000f0000, + /*023e*/ 0x00001803, + /*023f*/ 0x00000000, + /*0240*/ 0x00000000, + /*0241*/ 0x00060002, + /*0242*/ 0x00010001, + /*0243*/ 0x01000101, + /*0244*/ 0x04020201, + /*0245*/ 0x00080804, + /*0246*/ 0x00000000, + /*0247*/ 0x08030000, + /*0248*/ 0x15150408, + /*0249*/ 0x00000000, + /*024a*/ 0x00000000, + /*024b*/ 0x00000000, + /*024c*/ 0x000f0f00, + /*024d*/ 0x0000001e, + /*024e*/ 0x00000000, + /*024f*/ 0x01000300, + /*0250*/ 0x00000000, + /*0251*/ 0x00000000, + /*0252*/ 0x01000000, + /*0253*/ 0x00010101, + /*0254*/ 0x000e0e0e, + /*0255*/ 0x000c0c0c, + /*0256*/ 0x02060601, + /*0257*/ 0x00000000, + /*0258*/ 0x00000003, + /*0259*/ 0x00181703, + /*025a*/ 0x00280006, + /*025b*/ 0x00280016, + /*025c*/ 0x00000016, + /*025d*/ 0x00000000, + /*025e*/ 0x00000000, + /*025f*/ 0x00000000, + /*0260*/ 0x140a0000, + /*0261*/ 0x0005010a, + /*0262*/ 0x03018d03, + /*0263*/ 0x000a018d, + /*0264*/ 0x00060100, + /*0265*/ 0x01000006, + /*0266*/ 0x018e018e, + /*0267*/ 0x018e0100, + /*0268*/ 0x1111018e, + /*0269*/ 0x10010204, + /*026a*/ 0x09090650, + /*026b*/ 0x20110202, + /*026c*/ 0x00201000, + /*026d*/ 0x00201000, + /*026e*/ 0x04041000, + /*026f*/ 0x18020100, + /*0270*/ 0x00010118, + /*0271*/ 0x004b004a, + /*0272*/ 0x050f0000, + /*0273*/ 0x0c01021e, + /*0274*/ 0x34000000, + /*0275*/ 0x00000000, + /*0276*/ 0x00000000, + /*0277*/ 0x00000000, + /*0278*/ 0x0000d400, + /*0279*/ 0x0031002e, + /*027a*/ 0x00111136, + /*027b*/ 0x002e00d4, + /*027c*/ 0x11360031, + /*027d*/ 0x0000d411, + /*027e*/ 0x0031002e, + /*027f*/ 0x00111136, + /*0280*/ 0x002e00d4, + /*0281*/ 0x11360031, + /*0282*/ 0x0000d411, + /*0283*/ 0x0031002e, + /*0284*/ 0x00111136, + /*0285*/ 0x002e00d4, + /*0286*/ 0x11360031, + /*0287*/ 0x00d40011, + /*0288*/ 0x0031002e, + /*0289*/ 0x00111136, + /*028a*/ 0x002e00d4, + /*028b*/ 0x11360031, + /*028c*/ 0x0000d411, + /*028d*/ 0x0031002e, + /*028e*/ 0x00111136, + /*028f*/ 0x002e00d4, + /*0290*/ 0x11360031, + /*0291*/ 0x0000d411, + /*0292*/ 0x0031002e, + /*0293*/ 0x00111136, + /*0294*/ 0x002e00d4, + /*0295*/ 0x11360031, + /*0296*/ 0x02000011, + /*0297*/ 0x018d018d, + /*0298*/ 0x0c08018d, + /*0299*/ 0x1f121d22, + /*029a*/ 0x4301b344, + /*029b*/ 0x10172006, + /*029c*/ 0x1d220c10, + /*029d*/ 0x00001f12, + /*029e*/ 0x4301b344, + /*029f*/ 0x10172006, + /*02a0*/ 0x1d220c10, + /*02a1*/ 0x00001f12, + /*02a2*/ 0x4301b344, + /*02a3*/ 0x10172006, + /*02a4*/ 0x02000210, + /*02a5*/ 0x02000200, + /*02a6*/ 0x02000200, + /*02a7*/ 0x02000200, + /*02a8*/ 0x02000200, + /*02a9*/ 0x00000000, + /*02aa*/ 0x00000000, + /*02ab*/ 0x00000000, + /*02ac*/ 0x00000000, + /*02ad*/ 0x00000000, + /*02ae*/ 0x00000000, + /*02af*/ 0x00000000, + /*02b0*/ 0x00000000, + /*02b1*/ 0x00000000, + /*02b2*/ 0x00000000, + /*02b3*/ 0x00000000, + /*02b4*/ 0x00000000, + /*02b5*/ 0x00000400, + /*02b6*/ 0x15141312, + /*02b7*/ 0x11100f0e, + /*02b8*/ 0x080b0c0d, + /*02b9*/ 0x05040a09, + /*02ba*/ 0x01000706, + /*02bb*/ 0x00000302, + /*02bc*/ 0x01030201, + /*02bd*/ 0x00304c00, + /*02be*/ 0x0001e2f8, + /*02bf*/ 0x0000304c, + /*02c0*/ 0x0001e2f8, + /*02c1*/ 0x0000304c, + /*02c2*/ 0x0001e2f8, + /*02c3*/ 0x08000000, + /*02c4*/ 0x00000100, + /*02c5*/ 0x00000000, + /*02c6*/ 0x00000000, + /*02c7*/ 0x00000000, + /*02c8*/ 0x00000000, + /*02c9*/ 0x00000002 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h new file mode 100644 index 0000000..fb3032d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h @@ -0,0 +1,587 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define DDR_PHY_SLICE_REGSET_OFS_M3N 0x0800 +#define DDR_PHY_ADR_V_REGSET_OFS_M3N 0x0a00 +#define DDR_PHY_ADR_I_REGSET_OFS_M3N 0x0a80 +#define DDR_PHY_ADR_G_REGSET_OFS_M3N 0x0b80 +#define DDR_PI_REGSET_OFS_M3N 0x0200 + +#define DDR_PHY_SLICE_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_V_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_I_REGSET_SIZE_M3N 0x80 +#define DDR_PHY_ADR_G_REGSET_SIZE_M3N 0x80 +#define DDR_PI_REGSET_SIZE_M3N 0x100 + +#define DDR_PHY_SLICE_REGSET_NUM_M3N 101 +#define DDR_PHY_ADR_V_REGSET_NUM_M3N 37 +#define DDR_PHY_ADR_I_REGSET_NUM_M3N 37 +#define DDR_PHY_ADR_G_REGSET_NUM_M3N 87 +#define DDR_PI_REGSET_NUM_M3N 286 + +static const uint32_t DDR_PHY_SLICE_REGSET_M3N[DDR_PHY_SLICE_REGSET_NUM_M3N] = { + /*0800*/ 0x76543210, + /*0801*/ 0x0004f008, + /*0802*/ 0x00020200, + /*0803*/ 0x00000000, + /*0804*/ 0x00000000, + /*0805*/ 0x00010000, + /*0806*/ 0x036e6e0e, + /*0807*/ 0x026e6e0e, + /*0808*/ 0x00000103, + /*0809*/ 0x00040001, + /*080a*/ 0x00000103, + /*080b*/ 0x00000001, + /*080c*/ 0x00000000, + /*080d*/ 0x00000000, + /*080e*/ 0x00000100, + /*080f*/ 0x001800c0, + /*0810*/ 0x020100b0, + /*0811*/ 0x00030020, + /*0812*/ 0x00000000, + /*0813*/ 0x00000000, + /*0814*/ 0x0000aaaa, + /*0815*/ 0x00005555, + /*0816*/ 0x0000b5b5, + /*0817*/ 0x00004a4a, + /*0818*/ 0x00000000, + /*0819*/ 0x09000000, + /*081a*/ 0x04080000, + /*081b*/ 0x08040000, + /*081c*/ 0x00000004, + /*081d*/ 0x00800710, + /*081e*/ 0x000f000c, + /*081f*/ 0x00000100, + /*0820*/ 0x55aa55aa, + /*0821*/ 0x33cc33cc, + /*0822*/ 0x0ff00ff0, + /*0823*/ 0x0f0ff0f0, + /*0824*/ 0x00018e38, + /*0825*/ 0x00000000, + /*0826*/ 0x00000000, + /*0827*/ 0x00000000, + /*0828*/ 0x00000000, + /*0829*/ 0x00000000, + /*082a*/ 0x00000000, + /*082b*/ 0x00000000, + /*082c*/ 0x00000000, + /*082d*/ 0x00000000, + /*082e*/ 0x00000000, + /*082f*/ 0x00000000, + /*0830*/ 0x00000000, + /*0831*/ 0x00000000, + /*0832*/ 0x00000000, + /*0833*/ 0x00000000, + /*0834*/ 0x00000000, + /*0835*/ 0x00000000, + /*0836*/ 0x00000000, + /*0837*/ 0x00000000, + /*0838*/ 0x00000000, + /*0839*/ 0x00000000, + /*083a*/ 0x00000104, + /*083b*/ 0x00082020, + /*083c*/ 0x08200820, + /*083d*/ 0x08200820, + /*083e*/ 0x08200820, + /*083f*/ 0x08200820, + /*0840*/ 0x08200820, + /*0841*/ 0x00000000, + /*0842*/ 0x00000000, + /*0843*/ 0x03000300, + /*0844*/ 0x03000300, + /*0845*/ 0x03000300, + /*0846*/ 0x03000300, + /*0847*/ 0x00000300, + /*0848*/ 0x00000000, + /*0849*/ 0x00000000, + /*084a*/ 0x00000000, + /*084b*/ 0x00000000, + /*084c*/ 0x00000000, + /*084d*/ 0x00a000a0, + /*084e*/ 0x00a000a0, + /*084f*/ 0x00a000a0, + /*0850*/ 0x00a000a0, + /*0851*/ 0x00a000a0, + /*0852*/ 0x00a000a0, + /*0853*/ 0x00a000a0, + /*0854*/ 0x00a000a0, + /*0855*/ 0x00a000a0, + /*0856*/ 0x01040119, + /*0857*/ 0x00000200, + /*0858*/ 0x01000000, + /*0859*/ 0x00000200, + /*085a*/ 0x00000004, + /*085b*/ 0x4041a151, + /*085c*/ 0x0141a0a0, + /*085d*/ 0x0000c0c0, + /*085e*/ 0x0e0c000e, + /*085f*/ 0x10001000, + /*0860*/ 0x0c073e42, + /*0861*/ 0x000f0c28, + /*0862*/ 0x00e00140, + /*0863*/ 0x000c0020, + /*0864*/ 0x00000203 +}; + +static const uint32_t DDR_PHY_ADR_V_REGSET_M3N[DDR_PHY_ADR_V_REGSET_NUM_M3N] = { + /*0a00*/ 0x00000000, + /*0a01*/ 0x00000000, + /*0a02*/ 0x00000000, + /*0a03*/ 0x00000000, + /*0a04*/ 0x00000000, + /*0a05*/ 0x00000000, + /*0a06*/ 0x00000000, + /*0a07*/ 0x01000000, + /*0a08*/ 0x00020000, + /*0a09*/ 0x00000000, + /*0a0a*/ 0x00000000, + /*0a0b*/ 0x00000000, + /*0a0c*/ 0x00400000, + /*0a0d*/ 0x00000080, + /*0a0e*/ 0x00dcba98, + /*0a0f*/ 0x03000000, + /*0a10*/ 0x00000200, + /*0a11*/ 0x00000000, + /*0a12*/ 0x00000000, + /*0a13*/ 0x00000000, + /*0a14*/ 0x0000002a, + /*0a15*/ 0x00000015, + /*0a16*/ 0x00000015, + /*0a17*/ 0x0000002a, + /*0a18*/ 0x00000033, + /*0a19*/ 0x0000000c, + /*0a1a*/ 0x0000000c, + /*0a1b*/ 0x00000033, + /*0a1c*/ 0x0a418820, + /*0a1d*/ 0x003f0000, + /*0a1e*/ 0x0000013f, + /*0a1f*/ 0x0002c06e, + /*0a20*/ 0x02c002c0, + /*0a21*/ 0x02c002c0, + /*0a22*/ 0x000002c0, + /*0a23*/ 0x42080010, + /*0a24*/ 0x0000033e +}; + +static const uint32_t DDR_PHY_ADR_I_REGSET_M3N[DDR_PHY_ADR_I_REGSET_NUM_M3N] = { + /*0a80*/ 0x00000000, + /*0a81*/ 0x00000000, + /*0a82*/ 0x00000000, + /*0a83*/ 0x00000000, + /*0a84*/ 0x00000000, + /*0a85*/ 0x00000000, + /*0a86*/ 0x00000000, + /*0a87*/ 0x01000000, + /*0a88*/ 0x00020000, + /*0a89*/ 0x00000000, + /*0a8a*/ 0x00000000, + /*0a8b*/ 0x00000000, + /*0a8c*/ 0x00400000, + /*0a8d*/ 0x00000080, + /*0a8e*/ 0x00000000, + /*0a8f*/ 0x03000000, + /*0a90*/ 0x00000200, + /*0a91*/ 0x00000000, + /*0a92*/ 0x00000000, + /*0a93*/ 0x00000000, + /*0a94*/ 0x0000002a, + /*0a95*/ 0x00000015, + /*0a96*/ 0x00000015, + /*0a97*/ 0x0000002a, + /*0a98*/ 0x00000033, + /*0a99*/ 0x0000000c, + /*0a9a*/ 0x0000000c, + /*0a9b*/ 0x00000033, + /*0a9c*/ 0x00000000, + /*0a9d*/ 0x00000000, + /*0a9e*/ 0x00000000, + /*0a9f*/ 0x0002c06e, + /*0aa0*/ 0x02c002c0, + /*0aa1*/ 0x02c002c0, + /*0aa2*/ 0x000002c0, + /*0aa3*/ 0x42080010, + /*0aa4*/ 0x0000033e +}; + +static const uint32_t DDR_PHY_ADR_G_REGSET_M3N[DDR_PHY_ADR_G_REGSET_NUM_M3N] = { + /*0b80*/ 0x00000000, + /*0b81*/ 0x00000100, + /*0b82*/ 0x00000000, + /*0b83*/ 0x00050000, + /*0b84*/ 0x00000000, + /*0b85*/ 0x0004000f, + /*0b86*/ 0x00280080, + /*0b87*/ 0x02005502, + /*0b88*/ 0x00000000, + /*0b89*/ 0x00000000, + /*0b8a*/ 0x00000000, + /*0b8b*/ 0x00000050, + /*0b8c*/ 0x00000000, + /*0b8d*/ 0x01010100, + /*0b8e*/ 0x00010000, + /*0b8f*/ 0x00000000, + /*0b90*/ 0x00000101, + /*0b91*/ 0x00000000, + /*0b92*/ 0x00000000, + /*0b93*/ 0x00000000, + /*0b94*/ 0x00000000, + /*0b95*/ 0x00005064, + /*0b96*/ 0x01421142, + /*0b97*/ 0x00000142, + /*0b98*/ 0x00000000, + /*0b99*/ 0x000f1600, + /*0b9a*/ 0x0f160f16, + /*0b9b*/ 0x0f160f16, + /*0b9c*/ 0x00000003, + /*0b9d*/ 0x0002c000, + /*0b9e*/ 0x02c002c0, + /*0b9f*/ 0x000002c0, + /*0ba0*/ 0x08040201, + /*0ba1*/ 0x03421342, + /*0ba2*/ 0x00000342, + /*0ba3*/ 0x00000000, + /*0ba4*/ 0x00000000, + /*0ba5*/ 0x05030000, + /*0ba6*/ 0x00010700, + /*0ba7*/ 0x00000014, + /*0ba8*/ 0x00027f6e, + /*0ba9*/ 0x047f027f, + /*0baa*/ 0x00027f6e, + /*0bab*/ 0x00047f6e, + /*0bac*/ 0x0003554f, + /*0bad*/ 0x0001554f, + /*0bae*/ 0x0001554f, + /*0baf*/ 0x0001554f, + /*0bb0*/ 0x0001554f, + /*0bb1*/ 0x00003fee, + /*0bb2*/ 0x0001554f, + /*0bb3*/ 0x00003fee, + /*0bb4*/ 0x0001554f, + /*0bb5*/ 0x00027f6e, + /*0bb6*/ 0x0001554f, + /*0bb7*/ 0x00004011, + /*0bb8*/ 0x00004410, + /*0bb9*/ 0x00000000, + /*0bba*/ 0x00000000, + /*0bbb*/ 0x00000000, + /*0bbc*/ 0x00000265, + /*0bbd*/ 0x00000000, + /*0bbe*/ 0x00040401, + /*0bbf*/ 0x00000000, + /*0bc0*/ 0x03000000, + /*0bc1*/ 0x00000020, + /*0bc2*/ 0x00000000, + /*0bc3*/ 0x00000000, + /*0bc4*/ 0x04102006, + /*0bc5*/ 0x00041020, + /*0bc6*/ 0x01c98c98, + /*0bc7*/ 0x00400000, + /*0bc8*/ 0x00000000, + /*0bc9*/ 0x0001ffff, + /*0bca*/ 0x00000000, + /*0bcb*/ 0x00000000, + /*0bcc*/ 0x00000001, + /*0bcd*/ 0x00000000, + /*0bce*/ 0x00000000, + /*0bcf*/ 0x00000000, + /*0bd0*/ 0x76543210, + /*0bd1*/ 0x06010198, + /*0bd2*/ 0x00000000, + /*0bd3*/ 0x00000000, + /*0bd4*/ 0x04070000, + /*0bd5*/ 0x00000001, + /*0bd6*/ 0x00000f00 +}; + +static const uint32_t DDR_PI_REGSET_M3N[DDR_PI_REGSET_NUM_M3N] = { + /*0200*/ 0x00000b00, + /*0201*/ 0x00000101, + /*0202*/ 0x01640000, + /*0203*/ 0x00000014, + /*0204*/ 0x00000014, + /*0205*/ 0x00000014, + /*0206*/ 0x00000014, + /*0207*/ 0x00000000, + /*0208*/ 0x00000000, + /*0209*/ 0x0000ffff, + /*020a*/ 0x00000000, + /*020b*/ 0x0000ffff, + /*020c*/ 0x00000000, + /*020d*/ 0x0000ffff, + /*020e*/ 0x0000304c, + /*020f*/ 0x00000200, + /*0210*/ 0x00000200, + /*0211*/ 0x00000200, + /*0212*/ 0x00000200, + /*0213*/ 0x0000304c, + /*0214*/ 0x00000200, + /*0215*/ 0x00000200, + /*0216*/ 0x00000200, + /*0217*/ 0x00000200, + /*0218*/ 0x0000304c, + /*0219*/ 0x00000200, + /*021a*/ 0x00000200, + /*021b*/ 0x00000200, + /*021c*/ 0x00000200, + /*021d*/ 0x00010000, + /*021e*/ 0x00000003, + /*021f*/ 0x01000001, + /*0220*/ 0x00000000, + /*0221*/ 0x00000000, + /*0222*/ 0x00000000, + /*0223*/ 0x00000000, + /*0224*/ 0x00000000, + /*0225*/ 0x00000000, + /*0226*/ 0x00000000, + /*0227*/ 0x00000000, + /*0228*/ 0x00000000, + /*0229*/ 0x00000000, + /*022a*/ 0x00000000, + /*022b*/ 0x00000000, + /*022c*/ 0x00000000, + /*022d*/ 0x00000000, + /*022e*/ 0x00000000, + /*022f*/ 0x00000000, + /*0230*/ 0x0f000101, + /*0231*/ 0x084d3129, + /*0232*/ 0x0e0c0004, + /*0233*/ 0x000e5000, + /*0234*/ 0x01000250, + /*0235*/ 0x00000003, + /*0236*/ 0x00000046, + /*0237*/ 0x000000cf, + /*0238*/ 0x00001826, + /*0239*/ 0x000000cf, + /*023a*/ 0x00001826, + /*023b*/ 0x00000000, + /*023c*/ 0x00000000, + /*023d*/ 0x00000000, + /*023e*/ 0x00000000, + /*023f*/ 0x00000000, + /*0240*/ 0x00000000, + /*0241*/ 0x00000000, + /*0242*/ 0x00000000, + /*0243*/ 0x00000000, + /*0244*/ 0x00000000, + /*0245*/ 0x01000000, + /*0246*/ 0x00040404, + /*0247*/ 0x01280a00, + /*0248*/ 0x00000001, + /*0249*/ 0x00000000, + /*024a*/ 0x03000f00, + /*024b*/ 0x00200020, + /*024c*/ 0x00000020, + /*024d*/ 0x00000000, + /*024e*/ 0x00000000, + /*024f*/ 0x00010002, + /*0250*/ 0x01010001, + /*0251*/ 0x02010100, + /*0252*/ 0x08040402, + /*0253*/ 0x00000008, + /*0254*/ 0x00000000, + /*0255*/ 0x04080803, + /*0256*/ 0x00001515, + /*0257*/ 0x00000000, + /*0258*/ 0x000000aa, + /*0259*/ 0x00000055, + /*025a*/ 0x000000b5, + /*025b*/ 0x0000004a, + /*025c*/ 0x00000056, + /*025d*/ 0x000000a9, + /*025e*/ 0x000000a9, + /*025f*/ 0x000000b5, + /*0260*/ 0x00000000, + /*0261*/ 0x00000000, + /*0262*/ 0x0f000000, + /*0263*/ 0x00001e0f, + /*0264*/ 0x000007d0, + /*0265*/ 0x01000300, + /*0266*/ 0x00000100, + /*0267*/ 0x00000000, + /*0268*/ 0x00000000, + /*0269*/ 0x01000000, + /*026a*/ 0x00010101, + /*026b*/ 0x000e0e0e, + /*026c*/ 0x000c0c0c, + /*026d*/ 0x01060601, + /*026e*/ 0x04041717, + /*026f*/ 0x00000004, + /*0270*/ 0x00000300, + /*0271*/ 0x17030000, + /*0272*/ 0x00060018, + /*0273*/ 0x00160028, + /*0274*/ 0x00160028, + /*0275*/ 0x00000000, + /*0276*/ 0x00000000, + /*0277*/ 0x00000000, + /*0278*/ 0x0a000000, + /*0279*/ 0x00010a14, + /*027a*/ 0x00030005, + /*027b*/ 0x0003018d, + /*027c*/ 0x000a018d, + /*027d*/ 0x00060100, + /*027e*/ 0x01000006, + /*027f*/ 0x018e018e, + /*0280*/ 0x018e0100, + /*0281*/ 0x1e1a018e, + /*0282*/ 0x1e1a1e1a, + /*0283*/ 0x01010204, + /*0284*/ 0x06501001, + /*0285*/ 0x090d0a07, + /*0286*/ 0x090d0a07, + /*0287*/ 0x0811180f, + /*0288*/ 0x00ff1102, + /*0289*/ 0x00ff1000, + /*028a*/ 0x00ff1000, + /*028b*/ 0x04041000, + /*028c*/ 0x18020100, + /*028d*/ 0x01010018, + /*028e*/ 0x005f005f, + /*028f*/ 0x005f005f, + /*0290*/ 0x050f0000, + /*0291*/ 0x051e051e, + /*0292*/ 0x0c01021e, + /*0293*/ 0x00000c0c, + /*0294*/ 0x00003400, + /*0295*/ 0x00000000, + /*0296*/ 0x00000000, + /*0297*/ 0x00000000, + /*0298*/ 0x00000000, + /*0299*/ 0x002e00d4, + /*029a*/ 0x11360031, + /*029b*/ 0x00d41611, + /*029c*/ 0x0031002e, + /*029d*/ 0x16111136, + /*029e*/ 0x002e00d4, + /*029f*/ 0x11360031, + /*02a0*/ 0x00001611, + /*02a1*/ 0x002e00d4, + /*02a2*/ 0x11360031, + /*02a3*/ 0x00d41611, + /*02a4*/ 0x0031002e, + /*02a5*/ 0x16111136, + /*02a6*/ 0x002e00d4, + /*02a7*/ 0x11360031, + /*02a8*/ 0x00001611, + /*02a9*/ 0x002e00d4, + /*02aa*/ 0x11360031, + /*02ab*/ 0x00d41611, + /*02ac*/ 0x0031002e, + /*02ad*/ 0x16111136, + /*02ae*/ 0x002e00d4, + /*02af*/ 0x11360031, + /*02b0*/ 0x00001611, + /*02b1*/ 0x002e00d4, + /*02b2*/ 0x11360031, + /*02b3*/ 0x00d41611, + /*02b4*/ 0x0031002e, + /*02b5*/ 0x16111136, + /*02b6*/ 0x002e00d4, + /*02b7*/ 0x11360031, + /*02b8*/ 0x00001611, + /*02b9*/ 0x00018d00, + /*02ba*/ 0x018d018d, + /*02bb*/ 0x1d220c08, + /*02bc*/ 0x00001f12, + /*02bd*/ 0x4301b344, + /*02be*/ 0x17032006, + /*02bf*/ 0x220c1010, + /*02c0*/ 0x001f121d, + /*02c1*/ 0x4301b344, + /*02c2*/ 0x17062006, + /*02c3*/ 0x220c1010, + /*02c4*/ 0x001f121d, + /*02c5*/ 0x4301b344, + /*02c6*/ 0x17182006, + /*02c7*/ 0x00021010, + /*02c8*/ 0x00020002, + /*02c9*/ 0x00020002, + /*02ca*/ 0x00020002, + /*02cb*/ 0x00020002, + /*02cc*/ 0x00000002, + /*02cd*/ 0x00000000, + /*02ce*/ 0x00000000, + /*02cf*/ 0x00000000, + /*02d0*/ 0x00000000, + /*02d1*/ 0x00000000, + /*02d2*/ 0x00000000, + /*02d3*/ 0x00000000, + /*02d4*/ 0x00000000, + /*02d5*/ 0x00000000, + /*02d6*/ 0x00000000, + /*02d7*/ 0x00000000, + /*02d8*/ 0x00000000, + /*02d9*/ 0x00000400, + /*02da*/ 0x15141312, + /*02db*/ 0x11100f0e, + /*02dc*/ 0x080b0c0d, + /*02dd*/ 0x05040a09, + /*02de*/ 0x01000706, + /*02df*/ 0x00000302, + /*02e0*/ 0x01030201, + /*02e1*/ 0x00304c08, + /*02e2*/ 0x0001e2f8, + /*02e3*/ 0x0000304c, + /*02e4*/ 0x0001e2f8, + /*02e5*/ 0x0000304c, + /*02e6*/ 0x0001e2f8, + /*02e7*/ 0x08000000, + /*02e8*/ 0x00000100, + /*02e9*/ 0x00000000, + /*02ea*/ 0x00000000, + /*02eb*/ 0x00000000, + /*02ec*/ 0x00000000, + /*02ed*/ 0x00010000, + /*02ee*/ 0x00000000, + /*02ef*/ 0x00000000, + /*02f0*/ 0x00000000, + /*02f1*/ 0x00000000, + /*02f2*/ 0x00000000, + /*02f3*/ 0x00000000, + /*02f4*/ 0x00000000, + /*02f5*/ 0x00000000, + /*02f6*/ 0x00000000, + /*02f7*/ 0x00000000, + /*02f8*/ 0x00000000, + /*02f9*/ 0x00000000, + /*02fa*/ 0x00000000, + /*02fb*/ 0x00000000, + /*02fc*/ 0x00000000, + /*02fd*/ 0x00000000, + /*02fe*/ 0x00000000, + /*02ff*/ 0x00000000, + /*0300*/ 0x00000000, + /*0301*/ 0x00000000, + /*0302*/ 0x00000000, + /*0303*/ 0x00000000, + /*0304*/ 0x00000000, + /*0305*/ 0x00000000, + /*0306*/ 0x00000000, + /*0307*/ 0x00000000, + /*0308*/ 0x00000000, + /*0309*/ 0x00000000, + /*030a*/ 0x00000000, + /*030b*/ 0x00000000, + /*030c*/ 0x00000000, + /*030d*/ 0x00000000, + /*030e*/ 0x00000000, + /*030f*/ 0x00050002, + /*0310*/ 0x015c0057, + /*0311*/ 0x01000100, + /*0312*/ 0x01020001, + /*0313*/ 0x00010300, + /*0314*/ 0x05000104, + /*0315*/ 0x01060001, + /*0316*/ 0x00010700, + /*0317*/ 0x00000000, + /*0318*/ 0x00000000, + /*0319*/ 0x00000001, + /*031a*/ 0x00000000, + /*031b*/ 0x00000000, + /*031c*/ 0x00000000, + /*031d*/ 0x20080101 +}; diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c new file mode 100644 index 0000000..ab8eabb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "dram_sub_func.h" +#include "rcar_def.h" + +#if RCAR_SYSTEM_SUSPEND +/* Local defines */ +#define DRAM_BACKUP_GPIO_USE 0 +#include "iic_dvfs.h" +#if PMIC_ROHM_BD9571 +#define PMIC_SLAVE_ADDR 0x30U +#define PMIC_BKUP_MODE_CNT 0x20U +#define PMIC_QLLM_CNT 0x27U +#define BIT_BKUP_CTRL_OUT BIT(4) +#define BIT_QLLM_DDR0_EN BIT(0) +#define BIT_QLLM_DDR1_EN BIT(1) +#endif + +#define GPIO_BKUP_REQB_SHIFT_SALVATOR 9U /* GP1_9 (BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_SALVATOR 8U /* GP1_8 (BKUP_TRG) */ +#define GPIO_BKUP_REQB_SHIFT_EBISU 14U /* GP6_14(BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_EBISU 13U /* GP6_13(BKUP_TRG) */ +#define GPIO_BKUP_REQB_SHIFT_CONDOR 1U /* GP3_1 (BKUP_REQB) */ +#define GPIO_BKUP_TRG_SHIFT_CONDOR 0U /* GP3_0 (BKUP_TRG) */ + +#define DRAM_BKUP_TRG_LOOP_CNT 1000U +#endif + +void rcar_dram_get_boot_status(uint32_t *status) +{ +#if RCAR_SYSTEM_SUSPEND + uint32_t reg_data; + uint32_t product; + uint32_t shift; + uint32_t gpio; + + product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + if (product == PRR_PRODUCT_V3H) { + shift = GPIO_BKUP_TRG_SHIFT_CONDOR; + gpio = GPIO_INDT3; + } else if (product == PRR_PRODUCT_E3) { + shift = GPIO_BKUP_TRG_SHIFT_EBISU; + gpio = GPIO_INDT6; + } else { + shift = GPIO_BKUP_TRG_SHIFT_SALVATOR; + gpio = GPIO_INDT1; + } + + reg_data = mmio_read_32(gpio); + if (reg_data & BIT(shift)) + *status = DRAM_BOOT_STATUS_WARM; + else + *status = DRAM_BOOT_STATUS_COLD; +#else /* RCAR_SYSTEM_SUSPEND */ + *status = DRAM_BOOT_STATUS_COLD; +#endif /* RCAR_SYSTEM_SUSPEND */ +} + +int32_t rcar_dram_update_boot_status(uint32_t status) +{ + int32_t ret = 0; +#if RCAR_SYSTEM_SUSPEND + uint32_t reg_data; +#if PMIC_ROHM_BD9571 +#if DRAM_BACKUP_GPIO_USE == 0 + uint8_t bkup_mode_cnt = 0U; +#else + uint32_t reqb, outd; +#endif + uint8_t qllm_cnt = 0U; + int32_t i2c_dvfs_ret = -1; +#endif + uint32_t loop_count; + uint32_t product; + uint32_t trg; + uint32_t gpio; + + product = mmio_read_32(PRR) & PRR_PRODUCT_MASK; + if (product == PRR_PRODUCT_V3H) { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_CONDOR; + outd = GPIO_OUTDT3; +#endif + trg = GPIO_BKUP_TRG_SHIFT_CONDOR; + gpio = GPIO_INDT3; + } else if (product == PRR_PRODUCT_E3) { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_EBISU; + outd = GPIO_OUTDT6; +#endif + trg = GPIO_BKUP_TRG_SHIFT_EBISU; + gpio = GPIO_INDT6; + } else { +#if DRAM_BACKUP_GPIO_USE == 1 + reqb = GPIO_BKUP_REQB_SHIFT_SALVATOR; + outd = GPIO_OUTDT1; +#endif + trg = GPIO_BKUP_TRG_SHIFT_SALVATOR; + gpio = GPIO_INDT1; + } + + if (status == DRAM_BOOT_STATUS_WARM) { +#if DRAM_BACKUP_GPIO_USE == 1 + mmio_setbits_32(outd, BIT(reqb)); +#else +#if PMIC_ROHM_BD9571 + /* Set BKUP_CRTL_OUT=High (BKUP mode cnt register) */ + i2c_dvfs_ret = rcar_iic_dvfs_receive(PMIC_SLAVE_ADDR, + PMIC_BKUP_MODE_CNT, + &bkup_mode_cnt); + if (i2c_dvfs_ret) { + ERROR("BKUP mode cnt READ ERROR.\n"); + ret = DRAM_UPDATE_STATUS_ERR; + } else { + bkup_mode_cnt &= (uint8_t)~BIT_BKUP_CTRL_OUT; + i2c_dvfs_ret = rcar_iic_dvfs_send(PMIC_SLAVE_ADDR, + PMIC_BKUP_MODE_CNT, + bkup_mode_cnt); + if (i2c_dvfs_ret) { + ERROR("BKUP mode cnt WRITE ERROR. value = %d\n", + bkup_mode_cnt); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#endif /* PMIC_ROHM_BD9571 */ +#endif /* DRAM_BACKUP_GPIO_USE == 1 */ + /* Wait BKUP_TRG=Low */ + loop_count = DRAM_BKUP_TRG_LOOP_CNT; + while (loop_count > 0) { + reg_data = mmio_read_32(gpio); + if (!(reg_data & BIT(trg))) + break; + loop_count--; + } + + if (!loop_count) { + ERROR("\nWarm booting...\n" + " The potential of BKUP_TRG did not switch to Low.\n" + " If you expect the operation of cold boot,\n" + " check the board configuration (ex, Dip-SW) and/or the H/W failure.\n"); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#if PMIC_ROHM_BD9571 + if (!ret) { + qllm_cnt = BIT_QLLM_DDR0_EN | BIT_QLLM_DDR1_EN; + i2c_dvfs_ret = rcar_iic_dvfs_send(PMIC_SLAVE_ADDR, + PMIC_QLLM_CNT, + qllm_cnt); + if (i2c_dvfs_ret) { + ERROR("QLLM cnt WRITE ERROR. value = %d\n", qllm_cnt); + ret = DRAM_UPDATE_STATUS_ERR; + } + } +#endif +#endif + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h new file mode 100644 index 0000000..69c4d86 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRAM_SUB_FUNC_H +#define DRAM_SUB_FUNC_H + +#define DRAM_UPDATE_STATUS_ERR -1 +#define DRAM_BOOT_STATUS_COLD 0 +#define DRAM_BOOT_STATUS_WARM 1 + +int32_t rcar_dram_update_boot_status(uint32_t status); +void rcar_dram_get_boot_status(uint32_t *status); + +#endif /* DRAM_SUB_FUNC_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h b/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h new file mode 100644 index 0000000..ba26c69 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/ddr_regs.h @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_INIT_DRAM_REGDEF_H_ +#define BOOT_INIT_DRAM_REGDEF_H_ + +/* DBSC registers */ +#define DBSC_DBSYSCONF0 0xE6790000U +#define DBSC_DBSYSCONF1 0xE6790004U +#define DBSC_DBPHYCONF0 0xE6790010U +#define DBSC_DBKIND 0xE6790020U +#define DBSC_DBMEMCONF(ch, cs) (0xE6790030U + 0x10U * (ch) + 0x04U * (cs)) +#define DBSC_DBMEMCONF_0_0 0xE6790030U +#define DBSC_DBMEMCONF_0_1 0xE6790034U +#define DBSC_DBMEMCONF_0_2 0xE6790038U +#define DBSC_DBMEMCONF_0_3 0xE679003CU +#define DBSC_DBMEMCONF_1_2 0xE6790048U +#define DBSC_DBMEMCONF_1_3 0xE679004CU +#define DBSC_DBMEMCONF_1_0 0xE6790040U +#define DBSC_DBMEMCONF_1_1 0xE6790044U +#define DBSC_DBMEMCONF_2_0 0xE6790050U +#define DBSC_DBMEMCONF_2_1 0xE6790054U +#define DBSC_DBMEMCONF_2_2 0xE6790058U +#define DBSC_DBMEMCONF_2_3 0xE679005CU +#define DBSC_DBMEMCONF_3_0 0xE6790060U +#define DBSC_DBMEMCONF_3_1 0xE6790064U +#define DBSC_DBMEMCONF_3_2 0xE6790068U +#define DBSC_DBMEMCONF_3_3 0xE679006CU +#define DBSC_DBSYSCNT0 0xE6790100U +#define DBSC_DBSVCR1 0xE6790104U +#define DBSC_DBSTATE0 0xE6790108U +#define DBSC_DBSTATE1 0xE679010CU +#define DBSC_DBINTEN 0xE6790180U +#define DBSC_DBINTSTAT0 0xE6790184U +#define DBSC_DBACEN 0xE6790200U +#define DBSC_DBRFEN 0xE6790204U +#define DBSC_DBCMD 0xE6790208U +#define DBSC_DBWAIT 0xE6790210U +#define DBSC_DBSYSCTRL0 0xE6790280U +#define DBSC_DBTR(x) (0xE6790300U + 0x04U * (x)) +#define DBSC_DBTR0 0xE6790300U +#define DBSC_DBTR1 0xE6790304U +#define DBSC_DBTR2 0xE6790308U +#define DBSC_DBTR3 0xE679030CU +#define DBSC_DBTR4 0xE6790310U +#define DBSC_DBTR5 0xE6790314U +#define DBSC_DBTR6 0xE6790318U +#define DBSC_DBTR7 0xE679031CU +#define DBSC_DBTR8 0xE6790320U +#define DBSC_DBTR9 0xE6790324U +#define DBSC_DBTR10 0xE6790328U +#define DBSC_DBTR11 0xE679032CU +#define DBSC_DBTR12 0xE6790330U +#define DBSC_DBTR13 0xE6790334U +#define DBSC_DBTR14 0xE6790338U +#define DBSC_DBTR15 0xE679033CU +#define DBSC_DBTR16 0xE6790340U +#define DBSC_DBTR17 0xE6790344U +#define DBSC_DBTR18 0xE6790348U +#define DBSC_DBTR19 0xE679034CU +#define DBSC_DBTR20 0xE6790350U +#define DBSC_DBTR21 0xE6790354U +#define DBSC_DBTR22 0xE6790358U +#define DBSC_DBTR23 0xE679035CU +#define DBSC_DBTR24 0xE6790360U +#define DBSC_DBTR25 0xE6790364U +#define DBSC_DBTR26 0xE6790368U +#define DBSC_DBBL 0xE6790400U +#define DBSC_DBRFCNF1 0xE6790414U +#define DBSC_DBRFCNF2 0xE6790418U +#define DBSC_DBTSPCNF 0xE6790420U +#define DBSC_DBCALCNF 0xE6790424U +#define DBSC_DBRNK(x) (0xE6790430U + 0x04U * (x)) +#define DBSC_DBRNK2 0xE6790438U +#define DBSC_DBRNK3 0xE679043CU +#define DBSC_DBRNK4 0xE6790440U +#define DBSC_DBRNK5 0xE6790444U +#define DBSC_DBPDNCNF 0xE6790450U +#define DBSC_DBODT(x) (0xE6790460U + 0x04U * (x)) +#define DBSC_DBODT0 0xE6790460U +#define DBSC_DBODT1 0xE6790464U +#define DBSC_DBODT2 0xE6790468U +#define DBSC_DBODT3 0xE679046CU +#define DBSC_DBODT4 0xE6790470U +#define DBSC_DBODT5 0xE6790474U +#define DBSC_DBODT6 0xE6790478U +#define DBSC_DBODT7 0xE679047CU +#define DBSC_DBADJ0 0xE6790500U +#define DBSC_DBDBICNT 0xE6790518U +#define DBSC_DBDFIPMSTRCNF 0xE6790520U +#define DBSC_DBDFICUPDCNF 0xE679052CU +#define DBSC_DBDFISTAT(ch) (0xE6790600U + 0x40U * (ch)) +#define DBSC_DBDFISTAT_0 0xE6790600U +#define DBSC_DBDFISTAT_1 0xE6790640U +#define DBSC_DBDFISTAT_2 0xE6790680U +#define DBSC_DBDFISTAT_3 0xE67906C0U +#define DBSC_DBDFICNT(ch) (0xE6790604U + 0x40U * (ch)) +#define DBSC_DBDFICNT_0 0xE6790604U +#define DBSC_DBDFICNT_1 0xE6790644U +#define DBSC_DBDFICNT_2 0xE6790684U +#define DBSC_DBDFICNT_3 0xE67906C4U +#define DBSC_DBPDCNT0(ch) (0xE6790610U + 0x40U * (ch)) +#define DBSC_DBPDCNT0_0 0xE6790610U +#define DBSC_DBPDCNT0_1 0xE6790650U +#define DBSC_DBPDCNT0_2 0xE6790690U +#define DBSC_DBPDCNT0_3 0xE67906D0U +#define DBSC_DBPDCNT1(ch) (0xE6790614U + 0x40U * (ch)) +#define DBSC_DBPDCNT1_0 0xE6790614U +#define DBSC_DBPDCNT1_1 0xE6790654U +#define DBSC_DBPDCNT1_2 0xE6790694U +#define DBSC_DBPDCNT1_3 0xE67906D4U +#define DBSC_DBPDCNT2(ch) (0xE6790618U + 0x40U * (ch)) +#define DBSC_DBPDCNT2_0 0xE6790618U +#define DBSC_DBPDCNT2_1 0xE6790658U +#define DBSC_DBPDCNT2_2 0xE6790698U +#define DBSC_DBPDCNT2_3 0xE67906D8U +#define DBSC_DBPDCNT3(ch) (0xE679061CU + 0x40U * (ch)) +#define DBSC_DBPDCNT3_0 0xE679061CU +#define DBSC_DBPDCNT3_1 0xE679065CU +#define DBSC_DBPDCNT3_2 0xE679069CU +#define DBSC_DBPDCNT3_3 0xE67906DCU +#define DBSC_DBPDLK(ch) (0xE6790620U + 0x40U * (ch)) +#define DBSC_DBPDLK_0 0xE6790620U +#define DBSC_DBPDLK_1 0xE6790660U +#define DBSC_DBPDLK_2 0xE67906a0U +#define DBSC_DBPDLK_3 0xE67906e0U +#define DBSC_DBPDRGA(ch) (0xE6790624U + 0x40U * (ch)) +#define DBSC_DBPDRGD(ch) (0xE6790628U + 0x40U * (ch)) +#define DBSC_DBPDRGA_0 0xE6790624U +#define DBSC_DBPDRGD_0 0xE6790628U +#define DBSC_DBPDRGA_1 0xE6790664U +#define DBSC_DBPDRGD_1 0xE6790668U +#define DBSC_DBPDRGA_2 0xE67906A4U +#define DBSC_DBPDRGD_2 0xE67906A8U +#define DBSC_DBPDRGA_3 0xE67906E4U +#define DBSC_DBPDRGD_3 0xE67906E8U +#define DBSC_DBPDSTAT(ch) (0xE6790630U + 0x40U * (ch)) +#define DBSC_DBPDSTAT_0 0xE6790630U +#define DBSC_DBPDSTAT_1 0xE6790670U +#define DBSC_DBPDSTAT_2 0xE67906B0U +#define DBSC_DBPDSTAT_3 0xE67906F0U +#define DBSC_DBBUS0CNF0 0xE6790800U +#define DBSC_DBBUS0CNF1 0xE6790804U +#define DBSC_DBCAM0CNF1 0xE6790904U +#define DBSC_DBCAM0CNF2 0xE6790908U +#define DBSC_DBCAM0CNF3 0xE679090CU +#define DBSC_DBBSWAP 0xE67909F0U +#define DBSC_DBBCAMDIS 0xE67909FCU +#define DBSC_DBSCHCNT0 0xE6791000U +#define DBSC_DBSCHCNT1 0xE6791004U +#define DBSC_DBSCHSZ0 0xE6791010U +#define DBSC_DBSCHRW0 0xE6791020U +#define DBSC_DBSCHRW1 0xE6791024U +#define DBSC_DBSCHQOS_0(x) (0xE6791030U + 0x10U * (x)) +#define DBSC_DBSCHQOS_1(x) (0xE6791034U + 0x10U * (x)) +#define DBSC_DBSCHQOS_2(x) (0xE6791038U + 0x10U * (x)) +#define DBSC_DBSCHQOS_3(x) (0xE679103CU + 0x10U * (x)) +#define DBSC_DBSCHQOS00 0xE6791030U +#define DBSC_DBSCHQOS01 0xE6791034U +#define DBSC_DBSCHQOS02 0xE6791038U +#define DBSC_DBSCHQOS03 0xE679103CU +#define DBSC_DBSCHQOS10 0xE6791040U +#define DBSC_DBSCHQOS11 0xE6791044U +#define DBSC_DBSCHQOS12 0xE6791048U +#define DBSC_DBSCHQOS13 0xE679104CU +#define DBSC_DBSCHQOS20 0xE6791050U +#define DBSC_DBSCHQOS21 0xE6791054U +#define DBSC_DBSCHQOS22 0xE6791058U +#define DBSC_DBSCHQOS23 0xE679105CU +#define DBSC_DBSCHQOS30 0xE6791060U +#define DBSC_DBSCHQOS31 0xE6791064U +#define DBSC_DBSCHQOS32 0xE6791068U +#define DBSC_DBSCHQOS33 0xE679106CU +#define DBSC_DBSCHQOS40 0xE6791070U +#define DBSC_DBSCHQOS41 0xE6791074U +#define DBSC_DBSCHQOS42 0xE6791078U +#define DBSC_DBSCHQOS43 0xE679107CU +#define DBSC_DBSCHQOS50 0xE6791080U +#define DBSC_DBSCHQOS51 0xE6791084U +#define DBSC_DBSCHQOS52 0xE6791088U +#define DBSC_DBSCHQOS53 0xE679108CU +#define DBSC_DBSCHQOS60 0xE6791090U +#define DBSC_DBSCHQOS61 0xE6791094U +#define DBSC_DBSCHQOS62 0xE6791098U +#define DBSC_DBSCHQOS63 0xE679109CU +#define DBSC_DBSCHQOS70 0xE67910A0U +#define DBSC_DBSCHQOS71 0xE67910A4U +#define DBSC_DBSCHQOS72 0xE67910A8U +#define DBSC_DBSCHQOS73 0xE67910ACU +#define DBSC_DBSCHQOS80 0xE67910B0U +#define DBSC_DBSCHQOS81 0xE67910B4U +#define DBSC_DBSCHQOS82 0xE67910B8U +#define DBSC_DBSCHQOS83 0xE67910BCU +#define DBSC_DBSCHQOS90 0xE67910C0U +#define DBSC_DBSCHQOS91 0xE67910C4U +#define DBSC_DBSCHQOS92 0xE67910C8U +#define DBSC_DBSCHQOS93 0xE67910CCU +#define DBSC_DBSCHQOS100 0xE67910D0U +#define DBSC_DBSCHQOS101 0xE67910D4U +#define DBSC_DBSCHQOS102 0xE67910D8U +#define DBSC_DBSCHQOS103 0xE67910DCU +#define DBSC_DBSCHQOS110 0xE67910E0U +#define DBSC_DBSCHQOS111 0xE67910E4U +#define DBSC_DBSCHQOS112 0xE67910E8U +#define DBSC_DBSCHQOS113 0xE67910ECU +#define DBSC_DBSCHQOS120 0xE67910F0U +#define DBSC_DBSCHQOS121 0xE67910F4U +#define DBSC_DBSCHQOS122 0xE67910F8U +#define DBSC_DBSCHQOS123 0xE67910FCU +#define DBSC_DBSCHQOS130 0xE6791100U +#define DBSC_DBSCHQOS131 0xE6791104U +#define DBSC_DBSCHQOS132 0xE6791108U +#define DBSC_DBSCHQOS133 0xE679110CU +#define DBSC_DBSCHQOS140 0xE6791110U +#define DBSC_DBSCHQOS141 0xE6791114U +#define DBSC_DBSCHQOS142 0xE6791118U +#define DBSC_DBSCHQOS143 0xE679111CU +#define DBSC_DBSCHQOS150 0xE6791120U +#define DBSC_DBSCHQOS151 0xE6791124U +#define DBSC_DBSCHQOS152 0xE6791128U +#define DBSC_DBSCHQOS153 0xE679112CU +#define DBSC_DBSCTR0 0xE6791700U +#define DBSC_DBSCTR1 0xE6791708U +#define DBSC_DBSCHRW2 0xE679170CU +#define DBSC_SCFCTST01(x) (0xE6791700U + 0x08U * (x)) +#define DBSC_SCFCTST0 0xE6791700U +#define DBSC_SCFCTST1 0xE6791708U +#define DBSC_SCFCTST2 0xE679170CU +#define DBSC_DBMRRDR(chab) (0xE6791800U + 0x04U * (chab)) +#define DBSC_DBMRRDR_0 0xE6791800U +#define DBSC_DBMRRDR_1 0xE6791804U +#define DBSC_DBMRRDR_2 0xE6791808U +#define DBSC_DBMRRDR_3 0xE679180CU +#define DBSC_DBMRRDR_4 0xE6791810U +#define DBSC_DBMRRDR_5 0xE6791814U +#define DBSC_DBMRRDR_6 0xE6791818U +#define DBSC_DBMRRDR_7 0xE679181CU +#define DBSC_DBMEMSWAPCONF0 0xE6792000U + +/* CPG registers */ +#define CPG_BASE 0xE6150000U +#define CPG_FRQCRB (CPG_BASE + 0x0004U) +#define CPG_PLLECR (CPG_BASE + 0x00D0U) +#define CPG_MSTPSR5 (CPG_BASE + 0x003CU) +#define CPG_SRCR4 (CPG_BASE + 0x00BCU) +#define CPG_PLL3CR (CPG_BASE + 0x00DCU) +#define CPG_ZB3CKCR (CPG_BASE + 0x0380U) +#define CPG_FRQCRD (CPG_BASE + 0x00E4U) +#define CPG_SMSTPCR5 (CPG_BASE + 0x0144U) +#define CPG_CPGWPR (CPG_BASE + 0x0900U) +#define CPG_SRSTCLR4 (CPG_BASE + 0x0950U) + +#endif /* BOOT_INIT_DRAM_REGDEF_H_*/ diff --git a/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c new file mode 100644 index 0000000..a5e2a69 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "micro_delay.h" + +#define RCAR_CONV_MICROSEC 1000000U + +void +#if IMAGE_BL31 + __attribute__ ((section(".system_ram"))) +#endif + rcar_micro_delay(uint64_t micro_sec) +{ + uint64_t freq; + uint64_t base_count; + uint64_t get_count; + uint64_t wait_time = 0U; + + freq = read_cntfrq_el0(); + base_count = read_cntpct_el0(); + while (micro_sec > wait_time) { + get_count = read_cntpct_el0(); + wait_time = ((get_count - base_count) * RCAR_CONV_MICROSEC) / freq; + } +} diff --git a/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h new file mode 100644 index 0000000..37b71f8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MICRO_DELAY_H +#define MICRO_DELAY_H + +#ifndef __ASSEMBLER__ +#include +void rcar_micro_delay(uint64_t micro_sec); +#endif + +#endif /* MICRO_DELAY_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c b/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c new file mode 100644 index 0000000..44ee985 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" + +/* DMA CHANNEL setting (0/16/32) */ +#if RCAR_LSI == RCAR_V3M +#define DMA_CH 16 +#else +#define DMA_CH 0 +#endif + +#if (DMA_CH == 0) +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#elif (DMA_CH == 16) +#define SYS_DMAC_BIT ((uint32_t)1U << 18U) +#define DMA_BASE (0xE7300000U) +#elif (DMA_CH == 32) +#define SYS_DMAC_BIT ((uint32_t)1U << 17U) +#define DMA_BASE (0xE7320000U) +#else +#define SYS_DMAC_BIT ((uint32_t)1U << 19U) +#define DMA_BASE (0xE6700000U) +#endif + +/* DMA operation */ +#define DMA_DMAOR (DMA_BASE + 0x0060U) +/* DMA secure control */ +#define DMA_DMASEC (DMA_BASE + 0x0030U) +/* DMA channel clear */ +#define DMA_DMACHCLR (DMA_BASE + 0x0080U) +/* DMA source address */ +#define DMA_DMASAR (DMA_BASE + 0x8000U) +/* DMA destination address */ +#define DMA_DMADAR (DMA_BASE + 0x8004U) +/* DMA transfer count */ +#define DMA_DMATCR (DMA_BASE + 0x8008U) +/* DMA channel control */ +#define DMA_DMACHCR (DMA_BASE + 0x800CU) +/* DMA fixed destination address */ +#define DMA_DMAFIXDAR (DMA_BASE + 0x8014U) + +#define DMA_USE_CHANNEL (0x00000001U) +#define DMAOR_INITIAL (0x0301U) +#define DMACHCLR_CH_ALL (0x0000FFFFU) +#define DMAFIXDAR_32BIT_SHIFT (32U) +#define DMAFIXDAR_DAR_MASK (0x000000FFU) +#define DMADAR_BOUNDARY_ADDR (0x100000000ULL) +#define DMATCR_CNT_SHIFT (6U) +#define DMATCR_MAX (0x00FFFFFFU) +#define DMACHCR_TRN_MODE (0x00105409U) +#define DMACHCR_DE_BIT (0x00000001U) +#define DMACHCR_TE_BIT (0x00000002U) +#define DMACHCR_CHE_BIT (0x80000000U) + +#define DMA_SIZE_UNIT FLASH_TRANS_SIZE_UNIT +#define DMA_FRACTION_MASK (0xFFU) +#define DMA_DST_LIMIT (0x10000000000ULL) + +/* transfer length limit */ +#define DMA_LENGTH_LIMIT ((DMATCR_MAX * (1U << DMATCR_CNT_SHIFT)) \ + & ~DMA_FRACTION_MASK) + +static void dma_enable(void) +{ + mstpcr_write(CPG_SMSTPCR2, CPG_MSTPSR2, SYS_DMAC_BIT); +} + +static void dma_setup(void) +{ + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMACHCLR_CH_ALL); +} + +static void dma_start(uintptr_t dst, uint32_t src, uint32_t len) +{ + mmio_write_16(DMA_DMAOR, DMAOR_INITIAL); + mmio_write_32(DMA_DMAFIXDAR, (dst >> DMAFIXDAR_32BIT_SHIFT) & + DMAFIXDAR_DAR_MASK); + mmio_write_32(DMA_DMADAR, dst & UINT32_MAX); + mmio_write_32(DMA_DMASAR, src); + mmio_write_32(DMA_DMATCR, len >> DMATCR_CNT_SHIFT); + mmio_write_32(DMA_DMASEC, DMA_USE_CHANNEL); + mmio_write_32(DMA_DMACHCR, DMACHCR_TRN_MODE); +} + +static void dma_end(void) +{ + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_TE_BIT) == 0) { + if ((mmio_read_32(DMA_DMACHCR) & DMACHCR_CHE_BIT) != 0U) { + ERROR("BL2: DMA - Channel Address Error\n"); + panic(); + break; + } + } + /* DMA transfer Disable */ + mmio_clrbits_32(DMA_DMACHCR, DMACHCR_DE_BIT); + while ((mmio_read_32(DMA_DMACHCR) & DMACHCR_DE_BIT) != 0) + ; + + mmio_write_32(DMA_DMASEC, 0); + mmio_write_16(DMA_DMAOR, 0); + mmio_write_32(DMA_DMACHCLR, DMA_USE_CHANNEL); +} + +void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len) +{ + uint32_t dma_len = len; + + if (len & DMA_FRACTION_MASK) + dma_len = (len + DMA_SIZE_UNIT) & ~DMA_FRACTION_MASK; + + if (!dma_len || dma_len > DMA_LENGTH_LIMIT) { + ERROR("BL2: DMA - size invalid, length (0x%x)\n", dma_len); + panic(); + } + + if (src & DMA_FRACTION_MASK) { + ERROR("BL2: DMA - src address invalid (0x%x), len=(0x%x)\n", + src, dma_len); + panic(); + } + + if ((dst & UINT32_MAX) + dma_len > DMADAR_BOUNDARY_ADDR || + (dst + dma_len > DMA_DST_LIMIT) || + (dst & DMA_FRACTION_MASK)) { + ERROR("BL2: DMA - dest address invalid (0x%lx), len=(0x%x)\n", + dst, dma_len); + panic(); + } + + dma_start(dst, src, dma_len); + dma_end(); +} + +void rcar_dma_init(void) +{ + dma_enable(); + dma_setup(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c new file mode 100644 index 0000000..d255bff --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c @@ -0,0 +1,493 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "micro_delay.h" + +static void emmc_little_to_big(uint8_t *p, uint32_t value) +{ + if (p == NULL) + return; + + p[0] = (uint8_t) (value >> 24); + p[1] = (uint8_t) (value >> 16); + p[2] = (uint8_t) (value >> 8); + p[3] = (uint8_t) value; + +} + +static void emmc_softreset(void) +{ + int32_t loop = 10000; + int32_t retry = 1000; + + /* flag clear */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + + /* during operation ? */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + goto reset; + + /* wait CMDSEQ = 0 */ + while (loop > 0) { + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) == 0) + break; /* ready */ + + loop--; + if ((loop == 0) && (retry > 0)) { + rcar_micro_delay(1000U); /* wait 1ms */ + loop = 10000; + retry--; + } + } + +reset: + /* reset */ + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) & (~SOFT_RST_SDRST))); + SETR_32(SOFT_RST, (GETR_32(SOFT_RST) | SOFT_RST_SDRST)); + + /* initialize */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ +} + +static void emmc_read_response(uint32_t *response) +{ + uint8_t *p; + + if (response == NULL) + return; + + /* read response */ + if (mmc_drv_obj.response_length != EMMC_MAX_RESPONSE_LENGTH) { + *response = GETR_32(SD_RSP10); /* [39:8] */ + return; + } + + /* CSD or CID */ + p = (uint8_t *) (response); + emmc_little_to_big(p, ((GETR_32(SD_RSP76) << 8) + | (GETR_32(SD_RSP54) >> 24))); /* [127:96] */ + emmc_little_to_big(p + 4, ((GETR_32(SD_RSP54) << 8) + | (GETR_32(SD_RSP32) >> 24))); /* [95:64] */ + emmc_little_to_big(p + 8, ((GETR_32(SD_RSP32) << 8) + | (GETR_32(SD_RSP10) >> 24))); /* [63:32] */ + emmc_little_to_big(p + 12, (GETR_32(SD_RSP10) << 8)); +} + +static EMMC_ERROR_CODE emmc_response_check(uint32_t *response, + uint32_t error_mask) +{ + + HAL_MEMCARD_RESPONSE_TYPE response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK); + + if (response == NULL) + return EMMC_ERR_PARAM; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) + return EMMC_SUCCESS; + + + if (response_type <= HAL_MEMCARD_RESPONSE_R1b) { + /* R1 or R1b */ + mmc_drv_obj.current_state = + (EMMC_R1_STATE) ((*response & EMMC_R1_STATE_MASK) >> + EMMC_R1_STATE_SHIFT); + if ((*response & error_mask) != 0) { + if ((0x80 & *response) != 0) { + ERROR("BL2: emmc SWITCH_ERROR\n"); + } + return EMMC_ERR_CARD_STATUS_BIT; + } + return EMMC_SUCCESS; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R4) { + if ((*response & EMMC_R4_STATUS) != 0) + return EMMC_ERR_CARD_STATUS_BIT; + } + + return EMMC_SUCCESS; +} + +static void emmc_WaitCmd2Cmd_8Cycle(void) +{ + uint32_t dataL, wait = 0; + + dataL = GETR_32(SD_CLK_CTRL); + dataL &= 0x000000FF; + + switch (dataL) { + case 0xFF: + case 0x00: + case 0x01: + case 0x02: + case 0x04: + case 0x08: + case 0x10: + case 0x20: + wait = 10U; + break; + case 0x40: + wait = 20U; + break; + case 0x80: + wait = 30U; + break; + } + + rcar_micro_delay(wait); +} + +static void cmdErrSdInfo2Log(void) +{ + ERROR("BL2: emmc ERR SD_INFO2 = 0x%x\n", mmc_drv_obj.error_info.info2); +} + +static void emmc_data_transfer_dma(void) +{ + mmc_drv_obj.during_dma_transfer = TRUE; + mmc_drv_obj.dma_error_flag = FALSE; + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + /* DMAC setting */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH0_ENABLE)); + /* BUFF --> FIFO */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH0 | + DM_CM_DTRAN_MODE_BIT_WIDTH)); + } else { + /* transfer complete interrupt enable */ + SETR_32(DM_CM_INFO1_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + SETR_32(DM_CM_INFO2_MASK, + (DM_CM_INFO_MASK_CLEAR | DM_CM_INFO_CH1_ENABLE)); + /* FIFO --> BUFF */ + SETR_32(DM_CM_DTRAN_MODE, (DM_CM_DTRAN_MODE_CH1 + | DM_CM_DTRAN_MODE_BIT_WIDTH)); + } + SETR_32(DM_DTRAN_ADDR, (((uintptr_t) mmc_drv_obj.buff_address_virtual & + DM_DTRAN_ADDR_WRITE_MASK))); + + SETR_32(DM_CM_DTRAN_CTRL, DM_CM_DTRAN_CTRL_START); +} + +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response) +{ + EMMC_ERROR_CODE rtn_code = EMMC_SUCCESS; + HAL_MEMCARD_RESPONSE_TYPE response_type; + HAL_MEMCARD_COMMAND_TYPE cmd_type; + EMMC_INT_STATE state; + uint32_t err_not_care_flag = FALSE; + + /* parameter check */ + if (response == NULL) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.clock_enable != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + if (mmc_drv_obj.state_machine_blocking == TRUE) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, EMMC_ERR); + return EMMC_ERR; + } + + state = ESTATE_BEGIN; + response_type = + ((HAL_MEMCARD_RESPONSE_TYPE)mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_RESPONSE_TYPE_MASK); + cmd_type = + ((HAL_MEMCARD_COMMAND_TYPE) mmc_drv_obj.cmd_info.cmd & + HAL_MEMCARD_COMMAND_TYPE_MASK); + + /* state machine */ + while ((mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END)) { + /* The interrupt factor flag is observed. */ + emmc_interrupt(); + + /* wait interrupt */ + if (mmc_drv_obj.state_machine_blocking == TRUE) + continue; + + switch (state) { + case ESTATE_BEGIN: + /* Busy check */ + if ((mmc_drv_obj.error_info.info2 & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* clear register */ + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO0); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + state = ESTATE_ISSUE_CMD; + /* through */ + + case ESTATE_ISSUE_CMD: + /* ARG */ + SETR_32(SD_ARG, mmc_drv_obj.cmd_info.arg); + /* issue cmd */ + SETR_32(SD_CMD, mmc_drv_obj.cmd_info.hw); + /* Set driver flag */ + mmc_drv_obj.during_cmd_processing = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (response_type == HAL_MEMCARD_RESPONSE_NONE) { + state = ESTATE_NON_RESP_CMD; + } else { + state = ESTATE_RCV_RESP; + } + + break; + + case ESTATE_NON_RESP_CMD: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_RCV_RESP: + /* interrupt disable */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + if ((mmc_drv_obj.get_partition_access_flag == + TRUE) + && ((mmc_drv_obj.int_event2 & SD_INFO2_ERR6) + != 0U)) { + err_not_care_flag = TRUE; + rtn_code = EMMC_ERR_CMD_TIMEOUT; + } else { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + } + state = ESTATE_ERROR; + break; + } else if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO0) == + 0) { + /* not receive expected interrupt */ + rtn_code = EMMC_ERR_RESPONSE; + state = ESTATE_ERROR; + break; + } + + /* read response */ + emmc_read_response(response); + + /* check response */ + rtn_code = emmc_response_check(response, error_mask); + if (rtn_code != EMMC_SUCCESS) { + state = ESTATE_ERROR; + break; + } + + if (response_type == HAL_MEMCARD_RESPONSE_R1b) { + /* R1b */ + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + state = ESTATE_RCV_RESPONSE_BUSY; + } else { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + } + break; + + case ESTATE_RCV_RESPONSE_BUSY: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_ERROR; + break; + } + /* DAT0 not Busy */ + if ((SD_INFO2_DAT0 & mmc_drv_obj.error_info.info2) != 0) { + state = ESTATE_CHECK_RESPONSE_COMPLETE; + break; + } + break; + + case ESTATE_CHECK_RESPONSE_COMPLETE: + if (cmd_type >= HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE) { + state = ESTATE_DATA_TRANSFER; + } else { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } + break; + + case ESTATE_DATA_TRANSFER: + /* ADTC command */ + mmc_drv_obj.during_transfer = TRUE; + mmc_drv_obj.state_machine_blocking = TRUE; + + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* DMA */ + emmc_data_transfer_dma(); + } else { + /* PIO */ + /* interrupt enable (FIFO read/write enable) */ + if (mmc_drv_obj.cmd_info.dir == + HAL_MEMCARD_WRITE) { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BWE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } else { + SETR_32(SD_INFO2_MASK, + (SD_INFO2_BRE | SD_INFO2_ALL_ERR + | SD_INFO2_CLEAR)); + } + } + state = ESTATE_DATA_TRANSFER_COMPLETE; + break; + + case ESTATE_DATA_TRANSFER_COMPLETE: + /* check interrupt */ + if ((mmc_drv_obj.int_event2 & SD_INFO2_ALL_ERR) != 0) { + /* error interrupt */ + cmdErrSdInfo2Log(); + rtn_code = EMMC_ERR_INFO2; + state = ESTATE_TRANSFER_ERROR; + break; + } + + /* DMAC error ? */ + if (mmc_drv_obj.dma_error_flag == TRUE) { + /* Error occurred in DMAC driver. */ + rtn_code = EMMC_ERR_FROM_DMAC_TRANSFER; + state = ESTATE_TRANSFER_ERROR; + } else if (mmc_drv_obj.during_dma_transfer == TRUE) { + /* DMAC not finished. unknown error */ + rtn_code = EMMC_ERR; + state = ESTATE_TRANSFER_ERROR; + } else { + SETR_32(SD_INFO1_MASK, SD_INFO1_INFO2); + SETR_32(SD_INFO2_MASK, + (SD_INFO2_ALL_ERR | SD_INFO2_CLEAR)); + + mmc_drv_obj.state_machine_blocking = TRUE; + + state = ESTATE_ACCESS_END; + } + break; + + case ESTATE_ACCESS_END: + + /* clear flag */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + + if ((mmc_drv_obj.int_event1 & SD_INFO1_INFO2) != 0) { + emmc_WaitCmd2Cmd_8Cycle(); + state = ESTATE_END; + } else { + state = ESTATE_ERROR; + } + break; + + case ESTATE_TRANSFER_ERROR: + /* The error occurred in the Data transfer. */ + if (mmc_drv_obj.transfer_mode == HAL_MEMCARD_DMA) { + /* W (CC_EXT_MODE, H'0000_1010) SD_BUF DMA transfer disabled */ + SETR_32(CC_EXT_MODE, CC_EXT_MODE_CLEAR); + SETR_32(SD_STOP, 0x00000000U); + mmc_drv_obj.during_dma_transfer = FALSE; + } + /* through */ + + case ESTATE_ERROR: + if (err_not_care_flag == TRUE) { + mmc_drv_obj.during_cmd_processing = FALSE; + } else { + emmc_softreset(); + emmc_write_error_info(EMMC_FUNCNO_EXEC_CMD, + rtn_code); + } + return rtn_code; + + default: + state = ESTATE_END; + break; + } /* switch (state) */ + } /* while ( (mmc_drv_obj.force_terminate != TRUE) && (state != ESTATE_END) ) */ + + /* force terminate */ + if (mmc_drv_obj.force_terminate == TRUE) { + /* timeout timer is expired. Or, PIO data transfer error. */ + /* Timeout occurred in the DMA transfer. */ + if (mmc_drv_obj.during_dma_transfer == TRUE) { + mmc_drv_obj.during_dma_transfer = FALSE; + } + ERROR("BL2: emmc exec_cmd:EMMC_ERR_FORCE_TERMINATE\n"); + emmc_softreset(); + + return EMMC_ERR_FORCE_TERMINATE; /* error information has already been written. */ + } + + /* success */ + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_transfer = FALSE; + + return EMMC_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h new file mode 100644 index 0000000..16b6b8a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_CONFIG_H +#define EMMC_CONFIG_H + +/* RCA */ +#define EMMC_RCA 1UL +/* 314ms (freq = 400KHz, timeout Counter = 0x04(SDCLK * 2^17) */ +#define EMMC_RW_DATA_TIMEOUT 0x40UL +/* how many times to try after fail. Don't change. */ +#define EMMC_RETRY_COUNT 0 +#define EMMC_CMD_MAX 60UL /* Don't change. */ + +#define LOADIMAGE_FLAGS_DMA_ENABLE 0x00000001UL + +#endif /* EMMC_CONFIG_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h new file mode 100644 index 0000000..178c795 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/** + * @file emmc_def.h + * @brief eMMC boot is expecting this header file + * + */ + +#ifndef EMMC_DEF_H +#define EMMC_DEF_H + +#include "emmc_std.h" + +/* ************************ HEADER (INCLUDE) SECTION *********************** */ + +/* ***************** MACROS, CONSTANTS, COMPILATION FLAGS ****************** */ +#define EMMC_POWER_ON (1U) + +/* ********************** STRUCTURES, TYPE DEFINITIONS ********************* */ + +/* ********************** DECLARATION OF EXTERNAL DATA ********************* */ +extern st_mmc_base mmc_drv_obj; + +/* ************************** FUNCTION PROTOTYPES ************************** */ + +/** @brief for assembler program + */ +uint32_t _rom_emmc_finalize(void); + +/** @brief eMMC driver API + */ +EMMC_ERROR_CODE rcar_emmc_init(void); +EMMC_ERROR_CODE emmc_terminate(void); +EMMC_ERROR_CODE rcar_emmc_memcard_power(uint8_t mode); +EMMC_ERROR_CODE rcar_emmc_mount(void); +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq); +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg); +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id); +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_write_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + uint32_t feature_flags); +EMMC_ERROR_CODE emmc_erase_sector(uint32_t *start_address, + uint32_t *end_address); +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom); + +/** @brief interrupt service + */ +uint32_t emmc_interrupt(void); + +/** @brief DMA + */ + +/** @brief send command API + */ +EMMC_ERROR_CODE emmc_exec_cmd(uint32_t error_mask, uint32_t *response); +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg); +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode); +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg); + +/** @brief for error information + */ +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code); +void emmc_write_error_info_func_no(uint16_t func_no); + +/* ********************************* CODE ********************************** */ + +#endif /* EMMC_DEF_H */ +/* ******************************** END ************************************ */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h new file mode 100644 index 0000000..0a85517 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h @@ -0,0 +1,535 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_HAL_H +#define EMMC_HAL_H + +/* memory card error/status types */ +#define HAL_MEMCARD_OUT_OF_RANGE 0x80000000L +#define HAL_MEMCARD_ADDRESS_ERROR 0x40000000L +#define HAL_MEMCARD_BLOCK_LEN_ERROR 0x20000000L +#define HAL_MEMCARD_ERASE_SEQ_ERROR 0x10000000L +#define HAL_MEMCARD_ERASE_PARAM 0x08000000L +#define HAL_MEMCARD_WP_VIOLATION 0x04000000L +#define HAL_MEMCARD_CARD_IS_LOCKED 0x02000000L +#define HAL_MEMCARD_LOCK_UNLOCK_FAILED 0x01000000L +#define HAL_MEMCARD_COM_CRC_ERROR 0x00800000L +#define HAL_MEMCARD_ILEGAL_COMMAND 0x00400000L +#define HAL_MEMCARD_CARD_ECC_FAILED 0x00200000L +#define HAL_MEMCARD_CC_ERROR 0x00100000L +#define HAL_MEMCARD_ERROR 0x00080000L +#define HAL_MEMCARD_UNDERRUN 0x00040000L +#define HAL_MEMCARD_OVERRUN 0x00020000L +#define HAL_MEMCARD_CIDCSD_OVERWRITE 0x00010000L +#define HAL_MEMCARD_WP_ERASE_SKIP 0x00008000L +#define HAL_MEMCARD_CARD_ECC_DISABLED 0x00004000L +#define HAL_MEMCARD_ERASE_RESET 0x00002000L +#define HAL_MEMCARD_CARD_STATE 0x00001E00L +#define HAL_MEMCARD_CARD_READY_FOR_DATA 0x00000100L +#define HAL_MEMCARD_APP_CMD 0x00000020L +#define HAL_MEMCARD_SWITCH_ERROR 0x00000080L +#define HAL_MEMCARD_AKE_SEQ_ERROR 0x00000008L +#define HAL_MEMCARD_NO_ERRORS 0x00000000L + +/* Memory card response types */ +#define HAL_MEMCARD_COMMAND_INDEX_MASK 0x0003f + +/* Type of the return value. */ +typedef enum { + HAL_MEMCARD_FAIL = 0U, + HAL_MEMCARD_OK = 1U, + HAL_MEMCARD_DMA_ALLOC_FAIL = 2U, /* DMA channel allocation failed */ + HAL_MEMCARD_DMA_TRANSFER_FAIL = 3U, /* DMA transfer failed */ + HAL_MEMCARD_CARD_STATUS_ERROR = 4U, /* card status non-masked error */ + HAL_MEMCARD_CMD_TIMEOUT = 5U, /* Command timeout occurred */ + HAL_MEMCARD_DATA_TIMEOUT = 6U, /* Data timeout occurred */ + HAL_MEMCARD_CMD_CRC_ERROR = 7U, /* Command CRC error occurred */ + HAL_MEMCARD_DATA_CRC_ERROR = 8U /* Data CRC error occurred */ +} HAL_MEMCARD_RETURN; + +/* memory access operation */ +typedef enum { + HAL_MEMCARD_READ = 0U, /* read */ + HAL_MEMCARD_WRITE = 1U /* write */ +} HAL_MEMCARD_OPERATION; + +/* Type of data width on memorycard bus */ +typedef enum { + HAL_MEMCARD_DATA_WIDTH_1_BIT = 0U, + HAL_MEMCARD_DATA_WIDTH_4_BIT = 1U, + HAL_MEMCARD_DATA_WIDTH_8_BIT = 2U +} HAL_MEMCARD_DATA_WIDTH; /* data (bus) width types */ + +/* Presence of the memory card */ +typedef enum { + HAL_MEMCARD_CARD_IS_IN = 0U, + HAL_MEMCARD_CARD_IS_OUT = 1U +} HAL_MEMCARD_PRESENCE_STATUS; /* presence status of the memory card */ + +/* mode of data transfer */ +typedef enum { + HAL_MEMCARD_DMA = 0U, + HAL_MEMCARD_NOT_DMA = 1U +} HAL_MEMCARD_DATA_TRANSFER_MODE; + +/* Memory card response types. */ +typedef enum hal_memcard_response_type { + HAL_MEMCARD_RESPONSE_NONE = 0x00000U, + HAL_MEMCARD_RESPONSE_R1 = 0x00100U, + HAL_MEMCARD_RESPONSE_R1b = 0x00200U, + HAL_MEMCARD_RESPONSE_R2 = 0x00300U, + HAL_MEMCARD_RESPONSE_R3 = 0x00400U, + HAL_MEMCARD_RESPONSE_R4 = 0x00500U, + HAL_MEMCARD_RESPONSE_R5 = 0x00600U, + HAL_MEMCARD_RESPONSE_R6 = 0x00700U, + HAL_MEMCARD_RESPONSE_R7 = 0x00800U, + HAL_MEMCARD_RESPONSE_TYPE_MASK = 0x00f00U +} HAL_MEMCARD_RESPONSE_TYPE; + +/* Memory card command types. */ +typedef enum hal_memcard_command_type { + HAL_MEMCARD_COMMAND_TYPE_BC = 0x00000U, + HAL_MEMCARD_COMMAND_TYPE_BCR = 0x01000U, + HAL_MEMCARD_COMMAND_TYPE_AC = 0x02000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE = 0x03000U, + HAL_MEMCARD_COMMAND_TYPE_ADTC_READ = 0x04000U, + HAL_MEMCARD_COMMAND_TYPE_MASK = 0x07000U +} HAL_MEMCARD_COMMAND_TYPE; + +/* Type of memory card */ +typedef enum hal_memcard_command_card_type { + HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON = 0x00000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MMC = 0x08000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_SD = 0x10000U, + HAL_MEMCARD_COMMAND_CARD_TYPE_MASK = 0x18000U +} HAL_MEMCARD_COMMAND_CARD_TYPE; + +/* Memory card application command. */ +typedef enum hal_memcard_command_app_norm { + HAL_MEMCARD_COMMAND_NORMAL = 0x00000U, + HAL_MEMCARD_COMMAND_APP = 0x20000U, + HAL_MEMCARD_COMMAND_APP_NORM_MASK = 0x20000U +} HAL_MEMCARD_COMMAND_APP_NORM; + +/* Memory card command codes. */ +typedef enum { +/* class 0 and class 1 */ + /* CMD0 */ + CMD0_GO_IDLE_STATE = + 0U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t) HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD1 */ + CMD1_SEND_OP_COND = + 1U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD2 */ + CMD2_ALL_SEND_CID_MMC = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD2_ALL_SEND_CID_SD = + 2U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD3 */ + CMD3_SET_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD3_SEND_RELATIVE_ADDR = + 3U | (uint32_t)HAL_MEMCARD_RESPONSE_R6 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD4 */ + CMD4_SET_DSR = + 4U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD5 */ + CMD5_SLEEP_AWAKE = + 5U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD6 */ + CMD6_SWITCH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD6_SWITCH_FUNC = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD6_SET_BUS_WIDTH = + 6U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD7 */ + CMD7_SELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD7(from Disconnected State to Programming State) */ + CMD7_SELECT_CARD_PROG = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD7_DESELECT_CARD = + 7U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD8 */ + CMD8_SEND_EXT_CSD = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD8_SEND_IF_COND = + 8U | (uint32_t)HAL_MEMCARD_RESPONSE_R7 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD9 */ + CMD9_SEND_CSD = + 9U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD10 */ + CMD10_SEND_CID = + 10U | (uint32_t)HAL_MEMCARD_RESPONSE_R2 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD11 */ + CMD11_READ_DAT_UNTIL_STOP = + 11U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12 */ + CMD12_STOP_TRANSMISSION = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD12(R1b : write case) */ + CMD12_STOP_TRANSMISSION_WRITE = + 12U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD13 */ + CMD13_SEND_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD13_SD_STATUS = + 13U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD14 */ + CMD14_BUSTEST_R = + 14U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD15 */ + CMD15_GO_INACTIVE_STATE = + 15U | (uint32_t)HAL_MEMCARD_RESPONSE_NONE | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 2 */ + /* CMD16 */ + CMD16_SET_BLOCKLEN = + 16U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD17 */ + CMD17_READ_SINGLE_BLOCK = + 17U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD18 */ + CMD18_READ_MULTIPLE_BLOCK = + 18U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD19 */ + CMD19_BUS_TEST_W = + 19U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 3 */ + /* CMD20 */ + CMD20_WRITE_DAT_UNTIL_STOP = + 20U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD21 */ + CMD21 = 21U, + /* CMD22 */ + CMD22 = 22U, + ACMD22_SEND_NUM_WR_BLOCKS = + 22U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 4 */ + /* CMD23 */ + CMD23_SET_BLOCK_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD23_SET_WR_BLK_ERASE_COUNT = + 23U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + /* CMD24 */ + CMD24_WRITE_BLOCK = + 24U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD25 */ + CMD25_WRITE_MULTIPLE_BLOCK = + 25U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD26 */ + CMD26_PROGRAM_CID = + 26U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD27 */ + CMD27_PROGRAM_CSD = + 27U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 6 */ + /* CMD28 */ + CMD28_SET_WRITE_PROT = + 28U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD29 */ + CMD29_CLR_WRITE_PROT = + 29U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD30 */ + CMD30_SEND_WRITE_PROT = + 30U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD31 */ + CMD30_SEND_WRITE_PROT_TYPE = + 31U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 5 */ + /* CMD32 */ + CMD32_ERASE_WR_BLK_START = + 32U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD33 */ + CMD33_ERASE_WR_BLK_END = + 33U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD34 */ + CMD34 = 34U, + /* CMD35 */ + CMD35_ERASE_GROUP_START = + 35U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD36 */ + CMD36_ERASE_GROUP_END = + 36U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD37 */ + CMD37 = 37U, + /* CMD38 */ + CMD38_ERASE = + 38U | (uint32_t)HAL_MEMCARD_RESPONSE_R1b | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + +/* class 9 */ + /* CMD39 */ + CMD39_FASTIO = + 39U | (uint32_t)HAL_MEMCARD_RESPONSE_R4 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD40 */ + CMD40_GO_IRQSTATE = + 40U | (uint32_t)HAL_MEMCARD_RESPONSE_R5 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_MMC | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD41 */ + CMD41 = 41, + ACMD41_SD_SEND_OP_COND = + 41U | (uint32_t)HAL_MEMCARD_RESPONSE_R3 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_BCR | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + +/* class 7 */ + /* CMD42 */ + CMD42_LOCK_UNLOCK = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + ACMD42_SET_CLR_CARD_DETECT = + 42U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD43 = 43U, /* CMD43 */ + CMD44 = 44U, /* CMD44 */ + CMD45 = 45U, /* CMD45 */ + CMD46 = 46U, /* CMD46 */ + CMD47 = 47U, /* CMD47 */ + CMD48 = 48U, /* CMD48 */ + CMD49 = 49U, /* CMD49 */ + CMD50 = 50U, /* CMD50 */ + CMD51 = 51U, /* CMD51 */ + ACMD51_SEND_SCR = + 51U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_READ | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_SD | + (uint32_t)HAL_MEMCARD_COMMAND_APP, + CMD52 = 52U, /* CMD52 */ + CMD53 = 53U, /* CMD53 */ + CMD54 = 54U, /* CMD54 */ + +/* class 8 */ + /* CMD55 */ + CMD55_APP_CMD = + 55U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_AC | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + /* CMD56 */ + CMD56_GEN_CMD = + 56U | (uint32_t)HAL_MEMCARD_RESPONSE_R1 | + (uint32_t)HAL_MEMCARD_COMMAND_TYPE_ADTC_WRITE | + (uint32_t)HAL_MEMCARD_COMMAND_CARD_TYPE_COMMON | + (uint32_t)HAL_MEMCARD_COMMAND_NORMAL, + CMD57 = 57U, /* CMD57 */ + CMD58 = 58U, /* CMD58 */ + CMD59 = 59U, /* CMD59 */ + CMD60 = 60U, /* CMD60 */ + CMD61 = 61U, /* CMD61 */ + CMD62 = 62U, /* CMD62 */ + CMD63 = 63U /* CMD63 */ +} HAL_MEMCARD_COMMAND; + +/* + * Configuration structure from HAL layer. + * + * If some field is not available it should be filled with 0xFF. + * The API version is 32-bit unsigned integer telling the version of the API. + * The integer is divided to four sections which each can be treated as a 8-bit + * unsigned number: + * Bits 31-24 make the most significant part of the version number. This number + * starts from 1 i.e. the second version of the API will be 0x02xxxxxx. This + * number changes only, if the API itself changes so much that it is not + * compatible anymore with older releases. + * Bits 23-16 API minor version number. For example API version 2.1 would be + * 0x0201xxxx. + * Bits 15-8 are the number of the year when release is done. The 0 is year + * 2000, 1 is year 2001 and so on + * Bits 7- are the week number when release is done. First full week of the + * year is 1 + * + * Example: let's assume that release 2.1 is done on week 10 year 2008 + * the version will get the value 0x0201080A + */ +typedef struct { + /* + * Version of the chipset API implementation + * + * bits [31:24] API specification major version number.
+ * bits [23:16] API specification minor version number.
+ * bits [15:8] API implementation year. (2000 = 0, 2001 = 1, ...) + * bits [7:0] API implementation week. + * Example: API spec version 4.0, implementation w46 2008 => 0x0400082E + */ + uint32_t api_version; + + /* maximum block count which can be transferred at once */ + uint32_t max_block_count; + + /* maximum clock frequence in Hz supported by HW */ + uint32_t max_clock_freq; + + /* maximum data bus width supported by HW */ + uint16_t max_data_width; + + /* Is high-speed mode supported by HW (yes=1, no=0) */ + uint8_t hs_mode_supported; + + /* Is memory card removable (yes=1, no=0) */ + uint8_t card_removable; + +} HAL_MEMCARD_HW_CONF; + +/* Configuration structure to HAL layer. */ +typedef struct { + /* how many times to try after fail, for instance sending command */ + uint32_t retries_after_fail; +} HAL_MEMCARD_INIT_CONF; + +#endif /* EMMC_HAL_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c new file mode 100644 index 0000000..c0ec600 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "emmc_config.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "emmc_registers.h" +#include "emmc_def.h" +#include "rcar_private.h" +#include "cpg_registers.h" + +st_mmc_base mmc_drv_obj; + +EMMC_ERROR_CODE rcar_emmc_memcard_power(uint8_t mode) +{ + + if (mode == TRUE) { + /* power on (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = TRUE; + } else { + /* power off (Vcc&Vccq is always power on) */ + mmc_drv_obj.card_power_enable = FALSE; + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + } + + return EMMC_SUCCESS; +} +static inline void emmc_set_retry_count(uint32_t retry) +{ + mmc_drv_obj.retries_after_fail = retry; +} + +static inline void emmc_set_data_timeout(uint32_t data_timeout) +{ + mmc_drv_obj.data_timeout = data_timeout; +} + +static void emmc_memset(uint8_t *buff, uint8_t data, uint32_t cnt) +{ + if (buff == NULL) { + return; + } + + while (cnt > 0) { + *buff++ = data; + cnt--; + } +} + +static void emmc_driver_config(void) +{ + emmc_set_retry_count(EMMC_RETRY_COUNT); + emmc_set_data_timeout(EMMC_RW_DATA_TIMEOUT); +} + +static void emmc_drv_init(void) +{ + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + mmc_drv_obj.card_present = HAL_MEMCARD_CARD_IS_IN; + mmc_drv_obj.data_timeout = EMMC_RW_DATA_TIMEOUT; + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; +} + +static EMMC_ERROR_CODE emmc_dev_finalize(void) +{ + EMMC_ERROR_CODE result; + uint32_t dataL; + + /* + * MMC power off + * the power supply of eMMC device is always turning on. + * RST_n : Hi --> Low level. + */ + result = rcar_emmc_memcard_power(FALSE); + + /* host controller reset */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* MMC clock stop */ + + dataL = mmio_read_32(SMSTPCR3); + if ((dataL & CPG_MSTP_MMC) == 0U) { + dataL |= (CPG_MSTP_MMC); + mmio_write_32(CPG_CPGWPR, (~dataL)); + mmio_write_32(SMSTPCR3, dataL); + } + + return result; +} + +static EMMC_ERROR_CODE emmc_dev_init(void) +{ + /* Enable clock supply to eMMC. */ + mstpcr_write(SMSTPCR3, CPG_MSTPSR3, CPG_MSTP_MMC); + + /* Set SD clock */ + mmio_write_32(CPG_CPGWPR, ~((uint32_t) (BIT9 | BIT0))); /* SD phy 200MHz */ + + /* Stop SDnH clock & SDn=200MHz */ + mmio_write_32(CPG_SDxCKCR, (BIT9 | BIT0)); + + /* MMCIF initialize */ + SETR_32(SD_INFO1, 0x00000000U); /* all interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* all interrupt clear */ + SETR_32(SD_INFO1_MASK, 0x00000000U); /* all interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* all interrupt disable */ + + SETR_32(HOST_MODE, 0x00000000U); /* SD_BUF access width = 64-bit */ + SETR_32(SD_OPTION, 0x0000C0EEU); /* Bus width = 1bit, timeout=MAX */ + SETR_32(SD_CLK_CTRL, 0x00000000U); /* Disable Automatic Control & Clock Output */ + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_reset_controller(void) +{ + EMMC_ERROR_CODE result; + + /* initialize mmc driver */ + emmc_drv_init(); + + /* initialize H/W */ + result = emmc_dev_init(); + if (result == EMMC_SUCCESS) { + mmc_drv_obj.initialize = TRUE; + } + + return result; + +} + +EMMC_ERROR_CODE emmc_terminate(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_dev_finalize(); + + emmc_memset((uint8_t *) (&mmc_drv_obj), 0, sizeof(st_mmc_base)); + + return result; +} + +EMMC_ERROR_CODE rcar_emmc_init(void) +{ + EMMC_ERROR_CODE result; + + result = emmc_reset_controller(); + if (result == EMMC_SUCCESS) { + emmc_driver_config(); + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c new file mode 100644 index 0000000..092fdfb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "rcar_def.h" + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual); + +uint32_t emmc_interrupt(void) +{ + EMMC_ERROR_CODE result; + uint32_t prr_data; + uint32_t cut_ver; + uint32_t end_bit; + + prr_data = mmio_read_32((uintptr_t) RCAR_PRR); + cut_ver = prr_data & PRR_CUT_MASK; + if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_H3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else if (cut_ver == PRR_PRODUCT_11) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else if ((prr_data & PRR_PRODUCT_MASK) == PRR_PRODUCT_M3) { + if (cut_ver == PRR_PRODUCT_10) { + end_bit = BIT17; + } else { + end_bit = BIT20; + } + } else { + end_bit = BIT20; + } + + /* SD_INFO */ + mmc_drv_obj.error_info.info1 = GETR_32(SD_INFO1); + mmc_drv_obj.error_info.info2 = GETR_32(SD_INFO2); + + /* SD_INFO EVENT */ + mmc_drv_obj.int_event1 = + mmc_drv_obj.error_info.info1 & GETR_32(SD_INFO1_MASK); + mmc_drv_obj.int_event2 = + mmc_drv_obj.error_info.info2 & GETR_32(SD_INFO2_MASK); + + /* ERR_STS */ + mmc_drv_obj.error_info.status1 = GETR_32(SD_ERR_STS1); + mmc_drv_obj.error_info.status2 = GETR_32(SD_ERR_STS2); + + /* DM_CM_INFO */ + mmc_drv_obj.error_info.dm_info1 = GETR_32(DM_CM_INFO1); + mmc_drv_obj.error_info.dm_info2 = GETR_32(DM_CM_INFO2); + + /* DM_CM_INFO EVENT */ + mmc_drv_obj.dm_event1 = + mmc_drv_obj.error_info.dm_info1 & GETR_32(DM_CM_INFO1_MASK); + mmc_drv_obj.dm_event2 = + mmc_drv_obj.error_info.dm_info2 & GETR_32(DM_CM_INFO2_MASK); + + /* ERR SD_INFO2 */ + if ((SD_INFO2_ALL_ERR & mmc_drv_obj.int_event2) != 0) { + SETR_32(SD_INFO1_MASK, 0x00000000U); /* interrupt disable */ + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); /* interrupt disable */ + SETR_32(SD_INFO1, 0x00000000U); /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); /* interrupt clear */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* PIO Transfer */ + /* BWE/BRE */ + else if (((SD_INFO2_BWE | SD_INFO2_BRE) & mmc_drv_obj.int_event2)) { + /* BWE */ + if (SD_INFO2_BWE & mmc_drv_obj.int_event2) { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + } + /* BRE */ + else { + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + } + + result = emmc_trans_sector(mmc_drv_obj.buff_address_virtual); + mmc_drv_obj.buff_address_virtual += EMMC_BLOCK_LENGTH; + mmc_drv_obj.remain_size -= EMMC_BLOCK_LENGTH; + + if (result != EMMC_SUCCESS) { + /* data transfer error */ + emmc_write_error_info(EMMC_FUNCNO_NONE, result); + + /* Panic */ + SETR_32(SD_INFO1_MASK, 0x00000000U); + SETR_32(SD_INFO2_MASK, SD_INFO2_CLEAR); + SETR_32(SD_INFO1, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, SD_INFO2_CLEAR); + mmc_drv_obj.force_terminate = TRUE; + } else { + mmc_drv_obj.during_transfer = FALSE; + } + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* DMA_TRANSFER */ + /* DM_CM_INFO1: DMA-ch0 transfer complete or error occurred */ + else if ((BIT16 & mmc_drv_obj.dm_event1) != 0) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BWE)); + /* DM_CM_INFO2: DMA-ch0 error occurred */ + if ((BIT16 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* DM_CM_INFO1: DMA-ch1 transfer complete or error occurred */ + else if ((end_bit & mmc_drv_obj.dm_event1) != 0U) { + SETR_32(DM_CM_INFO1, 0x00000000U); + SETR_32(DM_CM_INFO2, 0x00000000U); + /* interrupt clear */ + SETR_32(SD_INFO2, (GETR_32(SD_INFO2) & ~SD_INFO2_BRE)); + /* DM_CM_INFO2: DMA-ch1 error occurred */ + if ((BIT17 & mmc_drv_obj.dm_event2) != 0) { + mmc_drv_obj.dma_error_flag = TRUE; + } else { + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.during_transfer = FALSE; + } + /* wait next interrupt */ + mmc_drv_obj.state_machine_blocking = FALSE; + } + + /* Response end */ + else if ((SD_INFO1_INFO0 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO0)); + mmc_drv_obj.state_machine_blocking = FALSE; + } + /* Access end */ + else if ((SD_INFO1_INFO2 & mmc_drv_obj.int_event1) != 0) { + /* interrupt clear */ + SETR_32(SD_INFO1, (GETR_32(SD_INFO1) & ~SD_INFO1_INFO2)); + mmc_drv_obj.state_machine_blocking = FALSE; + } else { + /* nothing to do. */ + } + + return (uint32_t) 0; +} + +static EMMC_ERROR_CODE emmc_trans_sector(uint32_t *buff_address_virtual) +{ + uint32_t length, i; + uint64_t *bufPtrLL; + + if (buff_address_virtual == NULL) { + return EMMC_ERR_PARAM; + } + + if ((mmc_drv_obj.during_transfer != TRUE) + || (mmc_drv_obj.remain_size == 0)) { + return EMMC_ERR_STATE; + } + + bufPtrLL = (uint64_t *) buff_address_virtual; + length = mmc_drv_obj.remain_size; + + /* data transefer */ + for (i = 0; i < (length >> 3); i++) { + /* Write */ + if (mmc_drv_obj.cmd_info.dir == HAL_MEMCARD_WRITE) { + SETR_64(SD_BUF0, *bufPtrLL); /* buffer --> FIFO */ + } + /* Read */ + else { + /* Checks when the read data reaches SD_SIZE. */ + /* The BRE bit is cleared at emmc_interrupt function. */ + if (((i % + (uint32_t) (EMMC_BLOCK_LENGTH >> + EMMC_BUF_SIZE_SHIFT)) == 0U) + && (i != 0U)) { + /* BRE check */ + while (((GETR_32(SD_INFO2)) & SD_INFO2_BRE) == + 0U) { + /* ERROR check */ + if (((GETR_32(SD_INFO2)) & + SD_INFO2_ALL_ERR) != 0U) { + return EMMC_ERR_TRANSFER; + } + } + /* BRE clear */ + SETR_32(SD_INFO2, + (uint32_t) (GETR_32(SD_INFO2) & + ~SD_INFO2_BRE)); + } + *bufPtrLL = GETR_64(SD_BUF0); /* FIFO --> buffer */ + } + bufPtrLL++; + } + + return EMMC_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c new file mode 100644 index 0000000..e04afd4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" +#include "micro_delay.h" +#include "rcar_def.h" + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode); +static EMMC_ERROR_CODE emmc_card_init(void); +static EMMC_ERROR_CODE emmc_high_speed(void); +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width); +static uint32_t emmc_set_timeout_register_value(uint32_t freq); +static void set_sd_clk(uint32_t clkDiv); +static uint32_t emmc_calc_tran_speed(uint32_t *freq); +static void emmc_get_partition_access(void); +static void emmc_set_bootpartition(void); + +static void emmc_set_bootpartition(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == PRR_PRODUCT_M3_CUT10) { + mmc_drv_obj.boot_partition_en = + (EMMC_PARTITION_ID) ((mmc_drv_obj.ext_csd_data[179] & + EMMC_BOOT_PARTITION_EN_MASK) >> + EMMC_BOOT_PARTITION_EN_SHIFT); + } else if ((reg == PRR_PRODUCT_H3_CUT20) + || (reg == PRR_PRODUCT_M3_CUT11)) { + mmc_drv_obj.boot_partition_en = mmc_drv_obj.partition_access; + } else { + if ((mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) != + 0U) { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_2; + } else { + mmc_drv_obj.boot_partition_en = PARTITION_ID_BOOT_1; + } + } +} + +static EMMC_ERROR_CODE emmc_card_init(void) +{ + int32_t retry; + uint32_t freq = MMC_400KHZ; /* 390KHz */ + EMMC_ERROR_CODE result; + uint32_t result_calc; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock on (force change) */ + mmc_drv_obj.current_freq = 0; + mmc_drv_obj.max_freq = MMC_20MHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + rcar_micro_delay(1000U); /* wait 1ms */ + + /* Get current access partition */ + emmc_get_partition_access(); + + /* CMD0, arg=0x00000000 */ + result = emmc_send_idle_cmd(0x00000000); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + rcar_micro_delay(200U); /* wait 74clock 390kHz(189.74us) */ + + /* CMD1 */ + emmc_make_nontrans_cmd(CMD1_SEND_OP_COND, EMMC_HOST_OCR_VALUE); + for (retry = 300; retry > 0; retry--) { + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + if ((mmc_drv_obj.r3_ocr & EMMC_OCR_STATUS_BIT) != 0) { + break; /* card is ready. exit loop */ + } + rcar_micro_delay(1000U); /* wait 1ms */ + } + + if (retry == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR_TIMEOUT); + return EMMC_ERR_TIMEOUT; + } + + switch (mmc_drv_obj.r3_ocr & EMMC_OCR_ACCESS_MODE_MASK) { + case EMMC_OCR_ACCESS_MODE_SECT: + mmc_drv_obj.access_mode = TRUE; /* sector mode */ + break; + default: + /* unknown value */ + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, EMMC_ERR); + return EMMC_ERR; + } + + /* CMD2 */ + emmc_make_nontrans_cmd(CMD2_ALL_SEND_CID_MMC, 0x00000000); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.cid_data[0]); /* use CID special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD3 */ + emmc_make_nontrans_cmd(CMD3_SET_RELATIVE_ADDR, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* CMD9 (CSD) */ + emmc_make_nontrans_cmd(CMD9_SEND_CSD, EMMC_RCA << 16); + mmc_drv_obj.response = (uint32_t *) (&mmc_drv_obj.csd_data[0]); /* use CSD special buffer */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* card version check */ + if (EMMC_CSD_SPEC_VARS() < 4) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + + /* CMD7 (select card) */ + emmc_make_nontrans_cmd(CMD7_SELECT_CARD, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + mmc_drv_obj.selected = TRUE; + + /* + * card speed check + * Card spec is calculated from TRAN_SPEED(CSD) + */ + result_calc = emmc_calc_tran_speed(&freq); + if (result_calc == 0) { + emmc_write_error_info(EMMC_FUNCNO_CARD_INIT, + EMMC_ERR_ILLEGAL_CARD); + return EMMC_ERR_ILLEGAL_CARD; + } + mmc_drv_obj.max_freq = freq; /* max frequency (card spec) */ + + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* SET_BLOCKLEN(512byte) */ + /* CMD16 */ + emmc_make_nontrans_cmd(CMD16_SET_BLOCKLEN, EMMC_BLOCK_LENGTH); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Transfer Data Length */ + SETR_32(SD_SIZE, EMMC_BLOCK_LENGTH); + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* + * CMD12 is not send. + * If BUS initialization is failed, user must be execute Bus initialization again. + * Bus initialization is start CMD0(soft reset command). + */ + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + return result; + } + + /* Set boot partition */ + emmc_set_bootpartition(); + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_high_speed(void) +{ + uint32_t freq; /* High speed mode clock frequency */ + EMMC_ERROR_CODE result; + uint8_t cardType; + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_HIGH_SPEED, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* max frequency */ + cardType = (uint8_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_CARD_TYPE]; + if ((cardType & EMMC_EXT_CSD_CARD_TYPE_52MHZ) != 0) + freq = MMC_52MHZ; + else if ((cardType & EMMC_EXT_CSD_CARD_TYPE_26MHZ) != 0) + freq = MMC_26MHZ; + else + freq = MMC_20MHZ; + + /* Hi-Speed-mode selection */ + if ((freq == MMC_52MHZ) || (freq == MMC_26MHZ)) { + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, EMMC_SWITCH_HS_TIMING); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + mmc_drv_obj.hs_timing = TIMING_HIGH_SPEED; /* High-Speed */ + } + + /* set mmc clock */ + mmc_drv_obj.max_freq = freq; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return EMMC_ERR; + } + + /* set read/write timeout */ + mmc_drv_obj.data_timeout = emmc_set_timeout_register_value(freq); + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(SD_OPTION_TIMEOUT_CNT_MASK)) | + mmc_drv_obj.data_timeout)); + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK_WITHOUT_CRC, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + return result; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_clock_ctrl(uint8_t mode) +{ + uint32_t value; + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + if (mode == TRUE) { + /* clock ON */ + value = + ((GETR_32(SD_CLK_CTRL) | MMC_SD_CLK_START) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* on */ + mmc_drv_obj.clock_enable = TRUE; + } else { + /* clock OFF */ + value = + ((GETR_32(SD_CLK_CTRL) & MMC_SD_CLK_STOP) & + SD_CLK_WRITE_MASK); + SETR_32(SD_CLK_CTRL, value); /* off */ + mmc_drv_obj.clock_enable = FALSE; + } + + return EMMC_SUCCESS; +} + +static EMMC_ERROR_CODE emmc_bus_width(uint32_t width) +{ + EMMC_ERROR_CODE result = EMMC_ERR; + + /* parameter check */ + if ((width != 8) && (width != 4) && (width != 1)) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.selected != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* 2 = 8bit, 1 = 4bit, 0 =1bit */ + mmc_drv_obj.bus_width = (HAL_MEMCARD_DATA_WIDTH) (width >> 2); + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, + (EMMC_SWITCH_BUS_WIDTH_1 | + (mmc_drv_obj.bus_width << 8))); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + /* occurred error */ + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + goto EXIT; + } + + switch (mmc_drv_obj.bus_width) { + case HAL_MEMCARD_DATA_WIDTH_1_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT15)); + break; + case HAL_MEMCARD_DATA_WIDTH_4_BIT: + SETR_32(SD_OPTION, (GETR_32(SD_OPTION) & ~(BIT15 | BIT13))); + break; + case HAL_MEMCARD_DATA_WIDTH_8_BIT: + SETR_32(SD_OPTION, + ((GETR_32(SD_OPTION) & ~(BIT15 | BIT13)) | BIT13)); + break; + default: + goto EXIT; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + goto EXIT; + } + + return EMMC_SUCCESS; + +EXIT: + emmc_write_error_info(EMMC_FUNCNO_BUS_WIDTH, result); + ERROR("BL2: emmc bus_width error end\n"); + return result; +} + +EMMC_ERROR_CODE emmc_select_partition(EMMC_PARTITION_ID id) +{ + EMMC_ERROR_CODE result; + uint32_t arg; + uint32_t partition_config; + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* id = PARTITION_ACCESS(Bit[2:0]) */ + if ((id & ~PARTITION_ID_MASK) != 0) { + emmc_write_error_info(EMMC_FUNCNO_NONE, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* EXT_CSD[179] value */ + partition_config = + (uint32_t) mmc_drv_obj.ext_csd_data[EMMC_EXT_CSD_PARTITION_CONFIG]; + if ((partition_config & PARTITION_ID_MASK) == id) { + result = EMMC_SUCCESS; + } else { + + partition_config = + (uint32_t) ((partition_config & ~PARTITION_ID_MASK) | id); + arg = EMMC_SWITCH_PARTITION_CONFIG | (partition_config << 8); + + result = emmc_set_ext_csd(arg); + } + + return result; +} + +static void set_sd_clk(uint32_t clkDiv) +{ + uint32_t dataL; + + dataL = (GETR_32(SD_CLK_CTRL) & (~SD_CLK_CTRL_CLKDIV_MASK)); + + switch (clkDiv) { + case 1: + dataL |= 0x000000FFU; + break; /* 1/1 */ + case 2: + dataL |= 0x00000000U; + break; /* 1/2 */ + case 4: + dataL |= 0x00000001U; + break; /* 1/4 */ + case 8: + dataL |= 0x00000002U; + break; /* 1/8 */ + case 16: + dataL |= 0x00000004U; + break; /* 1/16 */ + case 32: + dataL |= 0x00000008U; + break; /* 1/32 */ + case 64: + dataL |= 0x00000010U; + break; /* 1/64 */ + case 128: + dataL |= 0x00000020U; + break; /* 1/128 */ + case 256: + dataL |= 0x00000040U; + break; /* 1/256 */ + case 512: + dataL |= 0x00000080U; + break; /* 1/512 */ + } + + SETR_32(SD_CLK_CTRL, dataL); + mmc_drv_obj.current_freq = (uint32_t) clkDiv; +} + +static void emmc_get_partition_access(void) +{ + uint32_t reg; + EMMC_ERROR_CODE result; + + reg = mmio_read_32(RCAR_PRR) & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if ((reg == PRR_PRODUCT_H3_CUT20) || (reg == PRR_PRODUCT_M3_CUT11)) { + SETR_32(SD_OPTION, 0x000060EEU); /* 8 bits width */ + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000U, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, + HAL_MEMCARD_READ, HAL_MEMCARD_NOT_DMA); + mmc_drv_obj.get_partition_access_flag = TRUE; + result = + emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + mmc_drv_obj.get_partition_access_flag = FALSE; + if (result == EMMC_SUCCESS) { + mmc_drv_obj.partition_access = + (EMMC_PARTITION_ID) (mmc_drv_obj.ext_csd_data[179] + & PARTITION_ID_MASK); + } else if (result == EMMC_ERR_CMD_TIMEOUT) { + mmc_drv_obj.partition_access = PARTITION_ID_BOOT_1; + } else { + emmc_write_error_info(EMMC_FUNCNO_GET_PERTITION_ACCESS, + result); + panic(); + } + SETR_32(SD_OPTION, 0x0000C0EEU); /* Initialize */ + } +} + +static uint32_t emmc_calc_tran_speed(uint32_t *freq) +{ + const uint32_t unit[8] = { 10000U, 100000U, 1000000U, 10000000U, + 0U, 0U, 0U, 0U }; /* frequency unit (1/10) */ + const uint32_t mult[16] = { 0U, 10U, 12U, 13U, 15U, 20U, 26U, 30U, 35U, + 40U, 45U, 52U, 55U, 60U, 70U, 80U }; + uint32_t tran_speed = EMMC_CSD_TRAN_SPEED(); + uint32_t max_freq; + uint32_t result; + + /* + * tran_speed = 0x32 + * unit[tran_speed&0x7] = uint[0x2] = 1000000 + * mult[(tran_speed&0x78)>>3] = mult[0x30>>3] = mult[6] = 26 + * 1000000 * 26 = 26000000 (26MHz) + */ + + result = 1; + max_freq = + unit[tran_speed & EMMC_TRANSPEED_FREQ_UNIT_MASK] * + mult[(tran_speed & EMMC_TRANSPEED_MULT_MASK) >> + EMMC_TRANSPEED_MULT_SHIFT]; + + if (max_freq == 0) { + result = 0; + } else if (max_freq >= MMC_FREQ_52MHZ) { + *freq = MMC_52MHZ; + } else if (max_freq >= MMC_FREQ_26MHZ) { + *freq = MMC_26MHZ; + } else if (max_freq >= MMC_FREQ_20MHZ) { + *freq = MMC_20MHZ; + } else { + *freq = MMC_400KHZ; + } + + return result; +} + +static uint32_t emmc_set_timeout_register_value(uint32_t freq) +{ + uint32_t timeout_cnt; /* SD_OPTION - Timeout Counter */ + + switch (freq) { + case 1U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 2U: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + case 4U: + timeout_cnt = 0xD0U; + break; /* SDCLK * 2^26 */ + case 8U: + timeout_cnt = 0xC0U; + break; /* SDCLK * 2^25 */ + case 16U: + timeout_cnt = 0xB0U; + break; /* SDCLK * 2^24 */ + case 32U: + timeout_cnt = 0xA0U; + break; /* SDCLK * 2^23 */ + case 64U: + timeout_cnt = 0x90U; + break; /* SDCLK * 2^22 */ + case 128U: + timeout_cnt = 0x80U; + break; /* SDCLK * 2^21 */ + case 256U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + case 512U: + timeout_cnt = 0x70U; + break; /* SDCLK * 2^20 */ + default: + timeout_cnt = 0xE0U; + break; /* SDCLK * 2^27 */ + } + + return timeout_cnt; +} + +EMMC_ERROR_CODE emmc_set_ext_csd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + + /* CMD6 */ + emmc_make_nontrans_cmd(CMD6_SWITCH, arg); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* CMD8 (EXT_CSD) */ + emmc_make_trans_cmd(CMD8_SEND_EXT_CSD, 0x00000000, + (uint32_t *) (&mmc_drv_obj.ext_csd_data[0]), + EMMC_MAX_EXT_CSD_LENGTH, HAL_MEMCARD_READ, + HAL_MEMCARD_NOT_DMA); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_set_request_mmc_clock(uint32_t *freq) +{ + /* parameter check */ + if (freq == NULL) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE)) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* clock is already running in the desired frequency. */ + if ((mmc_drv_obj.clock_enable == TRUE) + && (mmc_drv_obj.current_freq == *freq)) { + return EMMC_SUCCESS; + } + + /* busy check */ + if ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) { + emmc_write_error_info(EMMC_FUNCNO_SET_CLOCK, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR; + } + + set_sd_clk(*freq); + mmc_drv_obj.clock_enable = FALSE; + + return emmc_clock_ctrl(TRUE); /* clock on */ +} + +EMMC_ERROR_CODE rcar_emmc_mount(void) +{ + EMMC_ERROR_CODE result; + + /* state check */ + if ((mmc_drv_obj.initialize != TRUE) + || (mmc_drv_obj.card_power_enable != TRUE) + || ((GETR_32(SD_INFO2) & SD_INFO2_CBSY) != 0) + ) { + emmc_write_error_info(EMMC_FUNCNO_MOUNT, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* initialize card (IDLE state --> Transfer state) */ + result = emmc_card_init(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_CARD_INIT); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Switching high speed mode */ + result = emmc_high_speed(); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_HIGH_SPEED); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* Changing the data bus width */ + result = emmc_bus_width(8); + if (result != EMMC_SUCCESS) { + emmc_write_error_info_func_no(EMMC_FUNCNO_BUS_WIDTH); + if (emmc_clock_ctrl(FALSE) != EMMC_SUCCESS) { + /* nothing to do. */ + } + return result; + } + + /* mount complete */ + mmc_drv_obj.mount = TRUE; + + return EMMC_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c new file mode 100644 index 0000000..96e73ca --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +#define MIN_EMMC(a, b) (((a) < (b)) ? (a) : (b)) +#define EMMC_RW_SECTOR_COUNT_MAX 0x0000ffffU + +static EMMC_ERROR_CODE emmc_multiple_block_read(uint32_t *buff_address_virtual, + uint32_t sector_number, uint32_t count, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + EMMC_ERROR_CODE result; + + /* parameter check */ + if ((count > EMMC_RW_SECTOR_COUNT_MAX) + || (count == 0) + || ((transfer_mode != HAL_MEMCARD_DMA) + && (transfer_mode != HAL_MEMCARD_NOT_DMA)) + ) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* CMD23 */ + emmc_make_nontrans_cmd(CMD23_SET_BLOCK_COUNT, count); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + SETR_32(SD_SECCNT, count); + SETR_32(SD_STOP, 0x00000100); + /* SD_BUF Read/Write DMA Transfer enable */ + SETR_32(CC_EXT_MODE, (CC_EXT_MODE_CLEAR | CC_EXT_MODE_DMASDRW_ENABLE)); + + /* CMD18 */ + emmc_make_trans_cmd(CMD18_READ_MULTIPLE_BLOCK, sector_number, + buff_address_virtual, + count << EMMC_SECTOR_SIZE_SHIFT, HAL_MEMCARD_READ, + transfer_mode); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; /* CMD18 error code */ + } + + /* CMD13 */ + emmc_make_nontrans_cmd(CMD13_SEND_STATUS, EMMC_RCA << 16); + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } +#if RCAR_BL2_DCACHE == 1 + if (transfer_mode == HAL_MEMCARD_NOT_DMA) { + flush_dcache_range((uint64_t) buff_address_virtual, + ((size_t) count << EMMC_SECTOR_SIZE_SHIFT)); + } +#endif /* RCAR_BL2_DCACHE == 1 */ + + /* ready status check */ + if ((mmc_drv_obj.r1_card_status & EMMC_R1_READY) == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_BUSY); + return EMMC_ERR_CARD_BUSY; + } + + /* state check */ + if (mmc_drv_obj.current_state != EMMC_R1_STATE_TRAN) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, + EMMC_ERR_CARD_STATE); + return EMMC_ERR_CARD_STATE; + } + + return EMMC_SUCCESS; +} + +EMMC_ERROR_CODE emmc_read_sector(uint32_t *buff_address_virtual, + uint32_t sector_number, + uint32_t count, uint32_t feature_flags) +{ + uint32_t trans_count; + uint32_t remain; + EMMC_ERROR_CODE result; + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* parameter check */ + if (count == 0) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_PARAM); + return EMMC_ERR_PARAM; + } + + /* state check */ + if (mmc_drv_obj.mount != TRUE) { + emmc_write_error_info(EMMC_FUNCNO_READ_SECTOR, EMMC_ERR_STATE); + return EMMC_ERR_STATE; + } + + /* DMA? */ + if ((feature_flags & LOADIMAGE_FLAGS_DMA_ENABLE) != 0) { + transfer_mode = HAL_MEMCARD_DMA; + } else { + transfer_mode = HAL_MEMCARD_NOT_DMA; + } + + remain = count; + while (remain != 0) { + trans_count = MIN_EMMC(remain, EMMC_RW_SECTOR_COUNT_MAX); + result = + emmc_multiple_block_read(buff_address_virtual, + sector_number, trans_count, + transfer_mode); + if (result != EMMC_SUCCESS) { + return result; + } + + buff_address_virtual += (EMMC_BLOCK_LENGTH_DW * trans_count); + sector_number += trans_count; + remain -= trans_count; + } + + return EMMC_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h new file mode 100644 index 0000000..67d285d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h @@ -0,0 +1,215 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_REGISTERS_H +#define EMMC_REGISTERS_H + +/* MMC channel select */ +#define MMC_CH0 (0U) /* SDHI2/MMC0 */ +#define MMC_CH1 (1U) /* SDHI3/MMC1 */ + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2M) || (RCAR_LSI == RZ_G2H) || (RCAR_LSI == RZ_G2N) +#define USE_MMC_CH (MMC_CH1) /* R-Car E3 or RZ/G2{H,M,N} */ +#else /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2{H,M,N} */ +#define USE_MMC_CH (MMC_CH0) /* R-Car H3/M3/M3N */ +#endif /* RCAR_LSI == RCAR_E3 || RCAR_LSI == RZ_G2{H,M,N} */ + +#define BIT0 (0x00000001U) +#define BIT1 (0x00000002U) +#define BIT2 (0x00000004U) +#define BIT3 (0x00000008U) +#define BIT4 (0x00000010U) +#define BIT5 (0x00000020U) +#define BIT6 (0x00000040U) +#define BIT7 (0x00000080U) +#define BIT8 (0x00000100U) +#define BIT9 (0x00000200U) +#define BIT10 (0x00000400U) +#define BIT11 (0x00000800U) +#define BIT12 (0x00001000U) +#define BIT13 (0x00002000U) +#define BIT14 (0x00004000U) +#define BIT15 (0x00008000U) +#define BIT16 (0x00010000U) +#define BIT17 (0x00020000U) +#define BIT18 (0x00040000U) +#define BIT19 (0x00080000U) +#define BIT20 (0x00100000U) +#define BIT21 (0x00200000U) +#define BIT22 (0x00400000U) +#define BIT23 (0x00800000U) +#define BIT24 (0x01000000U) +#define BIT25 (0x02000000U) +#define BIT26 (0x04000000U) +#define BIT27 (0x08000000U) +#define BIT28 (0x10000000U) +#define BIT29 (0x20000000U) +#define BIT30 (0x40000000U) +#define BIT31 (0x80000000U) + +#if USE_MMC_CH == MMC_CH0 +#define CPG_SDxCKCR (CPG_SD2CKCR) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_SDxCKCR (CPG_SD3CKCR) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +/* Boot Status register */ +#define MFISBTSTSR (0xE6260604U) + +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + +/* eMMC registers */ +#define MMC0_SD_BASE (0xEE140000U) +#define MMC1_SD_BASE (0xEE160000U) + +#if USE_MMC_CH == MMC_CH0 +#define MMC_SD_BASE (MMC0_SD_BASE) +#else /* USE_MMC_CH == MMC_CH0 */ +#define MMC_SD_BASE (MMC1_SD_BASE) +#endif /* USE_MMC_CH == MMC_CH0 */ + +#define SD_CMD (MMC_SD_BASE + 0x0000U) +#define SD_PORTSEL (MMC_SD_BASE + 0x0008U) +#define SD_ARG (MMC_SD_BASE + 0x0010U) +#define SD_ARG1 (MMC_SD_BASE + 0x0018U) +#define SD_STOP (MMC_SD_BASE + 0x0020U) +#define SD_SECCNT (MMC_SD_BASE + 0x0028U) +#define SD_RSP10 (MMC_SD_BASE + 0x0030U) +#define SD_RSP1 (MMC_SD_BASE + 0x0038U) +#define SD_RSP32 (MMC_SD_BASE + 0x0040U) +#define SD_RSP3 (MMC_SD_BASE + 0x0048U) +#define SD_RSP54 (MMC_SD_BASE + 0x0050U) +#define SD_RSP5 (MMC_SD_BASE + 0x0058U) +#define SD_RSP76 (MMC_SD_BASE + 0x0060U) +#define SD_RSP7 (MMC_SD_BASE + 0x0068U) +#define SD_INFO1 (MMC_SD_BASE + 0x0070U) +#define SD_INFO2 (MMC_SD_BASE + 0x0078U) +#define SD_INFO1_MASK (MMC_SD_BASE + 0x0080U) +#define SD_INFO2_MASK (MMC_SD_BASE + 0x0088U) +#define SD_CLK_CTRL (MMC_SD_BASE + 0x0090U) +#define SD_SIZE (MMC_SD_BASE + 0x0098U) +#define SD_OPTION (MMC_SD_BASE + 0x00A0U) +#define SD_ERR_STS1 (MMC_SD_BASE + 0x00B0U) +#define SD_ERR_STS2 (MMC_SD_BASE + 0x00B8U) +#define SD_BUF0 (MMC_SD_BASE + 0x00C0U) +#define SDIO_MODE (MMC_SD_BASE + 0x00D0U) +#define SDIO_INFO1 (MMC_SD_BASE + 0x00D8U) +#define SDIO_INFO1_MASK (MMC_SD_BASE + 0x00E0U) +#define CC_EXT_MODE (MMC_SD_BASE + 0x0360U) +#define SOFT_RST (MMC_SD_BASE + 0x0380U) +#define VERSION (MMC_SD_BASE + 0x0388U) +#define HOST_MODE (MMC_SD_BASE + 0x0390U) +#define DM_CM_DTRAN_MODE (MMC_SD_BASE + 0x0820U) +#define DM_CM_DTRAN_CTRL (MMC_SD_BASE + 0x0828U) +#define DM_CM_RST (MMC_SD_BASE + 0x0830U) +#define DM_CM_INFO1 (MMC_SD_BASE + 0x0840U) +#define DM_CM_INFO1_MASK (MMC_SD_BASE + 0x0848U) +#define DM_CM_INFO2 (MMC_SD_BASE + 0x0850U) +#define DM_CM_INFO2_MASK (MMC_SD_BASE + 0x0858U) +#define DM_DTRAN_ADDR (MMC_SD_BASE + 0x0880U) + +/* SD_INFO1 Registers */ +#define SD_INFO1_HPIRES 0x00010000UL /* Response Reception Completion */ +#define SD_INFO1_INFO10 0x00000400UL /* Indicates the SDDAT3 state */ +#define SD_INFO1_INFO9 0x00000200UL /* SDDAT3 Card Insertion */ +#define SD_INFO1_INFO8 0x00000100UL /* SDDAT3 Card Removal */ +#define SD_INFO1_INFO7 0x00000080UL /* Write Protect */ +#define SD_INFO1_INFO5 0x00000020UL /* Indicates the ISDCD state */ +#define SD_INFO1_INFO4 0x00000010UL /* ISDCD Card Insertion */ +#define SD_INFO1_INFO3 0x00000008UL /* ISDCD Card Removal */ +#define SD_INFO1_INFO2 0x00000004UL /* Access end */ +#define SD_INFO1_INFO0 0x00000001UL /* Response end */ + +/* SD_INFO2 Registers */ +#define SD_INFO2_ILA 0x00008000UL /* Illegal Access Error */ +#define SD_INFO2_CBSY 0x00004000UL /* Command Type Register Busy */ +#define SD_INFO2_SCLKDIVEN 0x00002000UL +#define SD_INFO2_BWE 0x00000200UL /* SD_BUF Write Enable */ +#define SD_INFO2_BRE 0x00000100UL /* SD_BUF Read Enable */ +#define SD_INFO2_DAT0 0x00000080UL /* SDDAT0 */ +#define SD_INFO2_ERR6 0x00000040UL /* Response Timeout */ +#define SD_INFO2_ERR5 0x00000020UL /* SD_BUF Illegal Read Access */ +#define SD_INFO2_ERR4 0x00000010UL /* SD_BUF Illegal Write Access */ +#define SD_INFO2_ERR3 0x00000008UL /* Data Timeout */ +#define SD_INFO2_ERR2 0x00000004UL /* END Error */ +#define SD_INFO2_ERR1 0x00000002UL /* CRC Error */ +#define SD_INFO2_ERR0 0x00000001UL /* CMD Error */ +#define SD_INFO2_ALL_ERR 0x0000807FUL +#define SD_INFO2_CLEAR 0x00000800UL /* BIT11 write value should always be 1. HWM_0003 */ + +/* SOFT_RST */ +#define SOFT_RST_SDRST 0x00000001UL + +/* SD_CLK_CTRL */ +#define SD_CLK_CTRL_SDCLKOFFEN 0x00000200UL +#define SD_CLK_CTRL_SCLKEN 0x00000100UL +#define SD_CLK_CTRL_CLKDIV_MASK 0x000000FFUL +#define SD_CLOCK_ENABLE 0x00000100UL +#define SD_CLOCK_DISABLE 0x00000000UL +#define SD_CLK_WRITE_MASK 0x000003FFUL +#define SD_CLK_CLKDIV_CLEAR_MASK 0xFFFFFF0FUL + +/* SD_OPTION */ +#define SD_OPTION_TIMEOUT_CNT_MASK 0x000000F0UL + +/* + * MMC Clock Frequency + * 200MHz * 1/x = output clock + */ +#define MMC_CLK_OFF 0UL /* Clock output is disabled */ +#define MMC_400KHZ 512UL /* 200MHz * 1/512 = 390 KHz */ +#define MMC_20MHZ 16UL /* 200MHz * 1/16 = 12.5 MHz Normal speed mode */ +#define MMC_26MHZ 8UL /* 200MHz * 1/8 = 25 MHz HS mode 26Mhz */ +#define MMC_52MHZ 4UL /* 200MHz * 1/4 = 50 MHz HS mode 52Mhz */ +#define MMC_100MHZ 2UL /* 200MHz * 1/2 = 100 MHz */ +#define MMC_200MHZ 1UL /* 200MHz * 1/1 = 200 MHz */ + +#define MMC_FREQ_52MHZ 52000000UL +#define MMC_FREQ_26MHZ 26000000UL +#define MMC_FREQ_20MHZ 20000000UL + +/* MMC Clock DIV */ +#define MMC_SD_CLK_START 0x00000100UL /* CLOCK On */ +#define MMC_SD_CLK_STOP (~0x00000100UL) /* CLOCK stop */ +#define MMC_SD_CLK_DIV1 0x000000FFUL /* 1/1 */ +#define MMC_SD_CLK_DIV2 0x00000000UL /* 1/2 */ +#define MMC_SD_CLK_DIV4 0x00000001UL /* 1/4 */ +#define MMC_SD_CLK_DIV8 0x00000002UL /* 1/8 */ +#define MMC_SD_CLK_DIV16 0x00000004UL /* 1/16 */ +#define MMC_SD_CLK_DIV32 0x00000008UL /* 1/32 */ +#define MMC_SD_CLK_DIV64 0x00000010UL /* 1/64 */ +#define MMC_SD_CLK_DIV128 0x00000020UL /* 1/128 */ +#define MMC_SD_CLK_DIV256 0x00000040UL /* 1/256 */ +#define MMC_SD_CLK_DIV512 0x00000080UL /* 1/512 */ + +/* DM_CM_DTRAN_MODE */ +#define DM_CM_DTRAN_MODE_CH0 0x00000000UL /* CH0(downstream) */ +#define DM_CM_DTRAN_MODE_CH1 0x00010000UL /* CH1(upstream) */ +#define DM_CM_DTRAN_MODE_BIT_WIDTH 0x00000030UL + +/* CC_EXT_MODE */ +#define CC_EXT_MODE_DMASDRW_ENABLE 0x00000002UL /* SD_BUF Read/Write DMA Transfer */ +#define CC_EXT_MODE_CLEAR 0x00001010UL /* BIT 12 & 4 always 1. */ + +/* DM_CM_INFO_MASK */ +#define DM_CM_INFO_MASK_CLEAR 0xFFFCFFFEUL +#define DM_CM_INFO_CH0_ENABLE 0x00010001UL +#define DM_CM_INFO_CH1_ENABLE 0x00020001UL + +/* DM_DTRAN_ADDR */ +#define DM_DTRAN_ADDR_WRITE_MASK 0xFFFFFFF8UL + +/* DM_CM_DTRAN_CTRL */ +#define DM_CM_DTRAN_CTRL_START 0x00000001UL + +/* SYSC Registers */ +#if USE_MMC_CH == MMC_CH0 +#define CPG_MSTP_MMC (BIT12) /* SDHI2/MMC0 */ +#else /* USE_MMC_CH == MMC_CH0 */ +#define CPG_MSTP_MMC (BIT11) /* SDHI3/MMC1 */ +#endif /* USE_MMC_CH == MMC_CH0 */ + +#endif /* EMMC_REGISTERS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h new file mode 100644 index 0000000..087c6e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h @@ -0,0 +1,475 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_STD_H +#define EMMC_STD_H + +#include "emmc_hal.h" + +#ifndef FALSE +#define FALSE 0U +#endif +#ifndef TRUE +#define TRUE 1U +#endif + +/* 64bit registers */ +#define SETR_64(r, v) (*(volatile uint64_t *)(r) = (v)) +#define GETR_64(r) (*(volatile uint64_t *)(r)) + +/* 32bit registers */ +#define SETR_32(r, v) (*(volatile uint32_t *)(r) = (v)) +#define GETR_32(r) (*(volatile uint32_t *)(r)) + +/* 16bit registers */ +#define SETR_16(r, v) (*(volatile uint16_t *)(r) = (v)) +#define GETR_16(r) (*(volatile uint16_t *)(r)) + +/* 8bit registers */ +#define SETR_8(r, v) (*(volatile uint8_t *)(r) = (v)) +#define GETR_8(r) (*(volatile uint8_t *)(r)) + +/* CSD register Macros */ +#define EMMC_GET_CID(x, y) (emmc_bit_field(mmc_drv_obj.cid_data, (x), (y))) + +#define EMMC_CID_MID() (EMMC_GET_CID(127, 120)) +#define EMMC_CID_CBX() (EMMC_GET_CID(113, 112)) +#define EMMC_CID_OID() (EMMC_GET_CID(111, 104)) +#define EMMC_CID_PNM1() (EMMC_GET_CID(103, 88)) +#define EMMC_CID_PNM2() (EMMC_GET_CID(87, 56)) +#define EMMC_CID_PRV() (EMMC_GET_CID(55, 48)) +#define EMMC_CID_PSN() (EMMC_GET_CID(47, 16)) +#define EMMC_CID_MDT() (EMMC_GET_CID(15, 8)) +#define EMMC_CID_CRC() (EMMC_GET_CID(7, 1)) + +/* CSD register Macros */ +#define EMMC_GET_CSD(x, y) (emmc_bit_field(mmc_drv_obj.csd_data, (x), (y))) + +#define EMMC_CSD_CSD_STRUCTURE() (EMMC_GET_CSD(127, 126)) +#define EMMC_CSD_SPEC_VARS() (EMMC_GET_CSD(125, 122)) +#define EMMC_CSD_TAAC() (EMMC_GET_CSD(119, 112)) +#define EMMC_CSD_NSAC() (EMMC_GET_CSD(111, 104)) +#define EMMC_CSD_TRAN_SPEED() (EMMC_GET_CSD(103, 96)) +#define EMMC_CSD_CCC() (EMMC_GET_CSD(95, 84)) +#define EMMC_CSD_READ_BL_LEN() (EMMC_GET_CSD(83, 80)) +#define EMMC_CSD_READ_BL_PARTIAL() (EMMC_GET_CSD(79, 79)) +#define EMMC_CSD_WRITE_BLK_MISALIGN() (EMMC_GET_CSD(78, 78)) +#define EMMC_CSD_READ_BLK_MISALIGN() (EMMC_GET_CSD(77, 77)) +#define EMMC_CSD_DSR_IMP() (EMMC_GET_CSD(76, 76)) +#define EMMC_CSD_C_SIZE() (EMMC_GET_CSD(73, 62)) +#define EMMC_CSD_VDD_R_CURR_MIN() (EMMC_GET_CSD(61, 59)) +#define EMMC_CSD_VDD_R_CURR_MAX() (EMMC_GET_CSD(58, 56)) +#define EMMC_CSD_VDD_W_CURR_MIN() (EMMC_GET_CSD(55, 53)) +#define EMMC_CSD_VDD_W_CURR_MAX() (EMMC_GET_CSD(52, 50)) +#define EMMC_CSD_C_SIZE_MULT() (EMMC_GET_CSD(49, 47)) +#define EMMC_CSD_ERASE_GRP_SIZE() (EMMC_GET_CSD(46, 42)) +#define EMMC_CSD_ERASE_GRP_MULT() (EMMC_GET_CSD(41, 37)) +#define EMMC_CSD_WP_GRP_SIZE() (EMMC_GET_CSD(36, 32)) +#define EMMC_CSD_WP_GRP_ENABLE() (EMMC_GET_CSD(31, 31)) +#define EMMC_CSD_DEFALT_ECC() (EMMC_GET_CSD(30, 29)) +#define EMMC_CSD_R2W_FACTOR() (EMMC_GET_CSD(28, 26)) +#define EMMC_CSD_WRITE_BL_LEN() (EMMC_GET_CSD(25, 22)) +#define EMMC_CSD_WRITE_BL_PARTIAL() (EMMC_GET_CSD(21, 21)) +#define EMMC_CSD_CONTENT_PROT_APP() (EMMC_GET_CSD(16, 16)) +#define EMMC_CSD_FILE_FORMAT_GRP() (EMMC_GET_CSD(15, 15)) +#define EMMC_CSD_COPY() (EMMC_GET_CSD(14, 14)) +#define EMMC_CSD_PERM_WRITE_PROTECT() (EMMC_GET_CSD(13, 13)) +#define EMMC_CSD_TMP_WRITE_PROTECT() (EMMC_GET_CSD(12, 12)) +#define EMMC_CSD_FILE_FORMAT() (EMMC_GET_CSD(11, 10)) +#define EMMC_CSD_ECC() (EMMC_GET_CSD(9, 8)) +#define EMMC_CSD_CRC() (EMMC_GET_CSD(7, 1)) + +/* sector access */ +#define EMMC_4B_BOUNDARY_CHECK_MASK 0x00000003 +#define EMMC_SECTOR_SIZE_SHIFT 9U /* 512 = 2^9 */ +#define EMMC_SECTOR_SIZE 512 +#define EMMC_BLOCK_LENGTH 512 +#define EMMC_BLOCK_LENGTH_DW 128 +#define EMMC_BUF_SIZE_SHIFT 3U /* 8byte = 2^3 */ + +/* eMMC specification clock */ +#define EMMC_CLOCK_SPEC_400K 400000UL /* initialize clock 400KHz */ +#define EMMC_CLOCK_SPEC_20M 20000000UL /* normal speed 20MHz */ +#define EMMC_CLOCK_SPEC_26M 26000000UL /* high speed 26MHz */ +#define EMMC_CLOCK_SPEC_52M 52000000UL /* high speed 52MHz */ +#define EMMC_CLOCK_SPEC_100M 100000000UL /* high speed 100MHz */ + +/* EMMC driver error code. (extended HAL_MEMCARD_RETURN) */ +typedef enum { + EMMC_ERR = 0, /* unknown error */ + EMMC_SUCCESS, /* OK */ + EMMC_ERR_FROM_DMAC, /* DMAC allocation error */ + EMMC_ERR_FROM_DMAC_TRANSFER, /* DMAC transfer error */ + EMMC_ERR_CARD_STATUS_BIT, /* card status error */ + EMMC_ERR_CMD_TIMEOUT, /* command timeout error */ + EMMC_ERR_DATA_TIMEOUT, /* data timeout error */ + EMMC_ERR_CMD_CRC, /* command CRC error */ + EMMC_ERR_DATA_CRC, /* data CRC error */ + EMMC_ERR_PARAM, /* parameter error */ + EMMC_ERR_RESPONSE, /* response error */ + EMMC_ERR_RESPONSE_BUSY, /* response busy error */ + EMMC_ERR_TRANSFER, /* data transfer error */ + EMMC_ERR_READ_SECTOR, /* read sector error */ + EMMC_ERR_WRITE_SECTOR, /* write sector error */ + EMMC_ERR_STATE, /* state error */ + EMMC_ERR_TIMEOUT, /* timeout error */ + EMMC_ERR_ILLEGAL_CARD, /* illegal card */ + EMMC_ERR_CARD_BUSY, /* Busy state */ + EMMC_ERR_CARD_STATE, /* card state error */ + EMMC_ERR_SET_TRACE, /* trace information error */ + EMMC_ERR_FROM_TIMER, /* Timer error */ + EMMC_ERR_FORCE_TERMINATE, /* Force terminate */ + EMMC_ERR_CARD_POWER, /* card power fail */ + EMMC_ERR_ERASE_SECTOR, /* erase sector error */ + EMMC_ERR_INFO2 /* exec cmd error info2 */ +} EMMC_ERROR_CODE; + +/* Function number */ +#define EMMC_FUNCNO_NONE 0U +#define EMMC_FUNCNO_DRIVER_INIT 1U +#define EMMC_FUNCNO_CARD_POWER_ON 2U +#define EMMC_FUNCNO_MOUNT 3U +#define EMMC_FUNCNO_CARD_INIT 4U +#define EMMC_FUNCNO_HIGH_SPEED 5U +#define EMMC_FUNCNO_BUS_WIDTH 6U +#define EMMC_FUNCNO_MULTI_BOOT_SELECT_PARTITION 7U +#define EMMC_FUNCNO_MULTI_BOOT_READ_SECTOR 8U +#define EMMC_FUNCNO_TRANS_DATA_READ_SECTOR 9U +#define EMMC_FUNCNO_UBOOT_IMAGE_SELECT_PARTITION 10U +#define EMMC_FUNCNO_UBOOT_IMAGE_READ_SECTOR 11U +#define EMMC_FUNCNO_SET_CLOCK 12U +#define EMMC_FUNCNO_EXEC_CMD 13U +#define EMMC_FUNCNO_READ_SECTOR 14U +#define EMMC_FUNCNO_WRITE_SECTOR 15U +#define EMMC_FUNCNO_ERASE_SECTOR 16U +#define EMMC_FUNCNO_GET_PERTITION_ACCESS 17U +/* + * Response + * R1 + * Type 'E' bit and bit14(must be 0). ignore bit22 + */ +#define EMMC_R1_ERROR_MASK 0xFDBFE080U +/* Ignore bit23 (Not check CRC error) */ +#define EMMC_R1_ERROR_MASK_WITHOUT_CRC (0xFD3FE080U) +#define EMMC_R1_STATE_MASK 0x00001E00U /* [12:9] */ +#define EMMC_R1_READY 0x00000100U /* bit8 */ +#define EMMC_R1_STATE_SHIFT 9 + +/* R4 */ +#define EMMC_R4_RCA_MASK 0xFFFF0000UL +#define EMMC_R4_STATUS 0x00008000UL + +/* CSD */ +#define EMMC_TRANSPEED_FREQ_UNIT_MASK 0x07 /* bit[2:0] */ +#define EMMC_TRANSPEED_FREQ_UNIT_SHIFT 0 +#define EMMC_TRANSPEED_MULT_MASK 0x78 /* bit[6:3] */ +#define EMMC_TRANSPEED_MULT_SHIFT 3 + +/* OCR */ +#define EMMC_HOST_OCR_VALUE 0x40FF8080 +#define EMMC_OCR_STATUS_BIT 0x80000000L /* Card power up status bit */ +#define EMMC_OCR_ACCESS_MODE_MASK 0x60000000L /* bit[30:29] */ +#define EMMC_OCR_ACCESS_MODE_SECT 0x40000000L +#define EMMC_OCR_ACCESS_MODE_BYTE 0x00000000L + +/* EXT_CSD */ +#define EMMC_EXT_CSD_S_CMD_SET 504 +#define EMMC_EXT_CSD_INI_TIMEOUT_AP 241 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_360 239 +#define EMMC_EXT_CSD_PWR_CL_DDR_52_195 238 +#define EMMC_EXT_CSD_MIN_PERF_DDR_W_8_52 235 +#define EMMC_EXT_CSD_MIN_PERF_DDR_R_8_52 234 +#define EMMC_EXT_CSD_TRIM_MULT 232 +#define EMMC_EXT_CSD_SEC_FEATURE_SUPPORT 231 +#define EMMC_EXT_CSD_SEC_ERASE_MULT 229 +#define EMMC_EXT_CSD_BOOT_INFO 228 +#define EMMC_EXT_CSD_BOOT_SIZE_MULTI 226 +#define EMMC_EXT_CSD_ACC_SIZE 225 +#define EMMC_EXT_CSD_HC_ERASE_GRP_SIZE 224 +#define EMMC_EXT_CSD_ERASE_TIMEOUT_MULT 223 +#define EMMC_EXT_CSD_PEL_WR_SEC_C 222 +#define EMMC_EXT_CSD_HC_WP_GRP_SIZE 221 +#define EMMC_EXT_CSD_S_C_VCC 220 +#define EMMC_EXT_CSD_S_C_VCCQ 219 +#define EMMC_EXT_CSD_S_A_TIMEOUT 217 +#define EMMC_EXT_CSD_SEC_COUNT 215 +#define EMMC_EXT_CSD_MIN_PERF_W_8_52 210 +#define EMMC_EXT_CSD_MIN_PERF_R_8_52 209 +#define EMMC_EXT_CSD_MIN_PERF_W_8_26_4_52 208 +#define EMMC_EXT_CSD_MIN_PERF_R_8_26_4_52 207 +#define EMMC_EXT_CSD_MIN_PERF_W_4_26 206 +#define EMMC_EXT_CSD_MIN_PERF_R_4_26 205 +#define EMMC_EXT_CSD_PWR_CL_26_360 203 +#define EMMC_EXT_CSD_PWR_CL_52_360 202 +#define EMMC_EXT_CSD_PWR_CL_26_195 201 +#define EMMC_EXT_CSD_PWR_CL_52_195 200 +#define EMMC_EXT_CSD_CARD_TYPE 196 +#define EMMC_EXT_CSD_CSD_STRUCTURE 194 +#define EMMC_EXT_CSD_EXT_CSD_REV 192 +#define EMMC_EXT_CSD_CMD_SET 191 +#define EMMC_EXT_CSD_CMD_SET_REV 189 +#define EMMC_EXT_CSD_POWER_CLASS 187 +#define EMMC_EXT_CSD_HS_TIMING 185 +#define EMMC_EXT_CSD_BUS_WIDTH 183 +#define EMMC_EXT_CSD_ERASED_MEM_CONT 181 +#define EMMC_EXT_CSD_PARTITION_CONFIG 179 +#define EMMC_EXT_CSD_BOOT_CONFIG_PROT 178 +#define EMMC_EXT_CSD_BOOT_BUS_WIDTH 177 +#define EMMC_EXT_CSD_ERASE_GROUP_DEF 175 +#define EMMC_EXT_CSD_BOOT_WP 173 +#define EMMC_EXT_CSD_USER_WP 171 +#define EMMC_EXT_CSD_FW_CONFIG 169 +#define EMMC_EXT_CSD_RPMB_SIZE_MULT 168 +#define EMMC_EXT_CSD_RST_n_FUNCTION 162 +#define EMMC_EXT_CSD_PARTITIONING_SUPPORT 160 +#define EMMC_EXT_CSD_MAX_ENH_SIZE_MULT 159 +#define EMMC_EXT_CSD_PARTITIONS_ATTRIBUTE 156 +#define EMMC_EXT_CSD_PARTITION_SETTING_COMPLETED 155 +#define EMMC_EXT_CSD_GP_SIZE_MULT 154 +#define EMMC_EXT_CSD_ENH_SIZE_MULT 142 +#define EMMC_EXT_CSD_ENH_START_ADDR 139 +#define EMMC_EXT_CSD_SEC_BAD_BLK_MGMNT 134 + +#define EMMC_EXT_CSD_CARD_TYPE_26MHZ 0x01 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ 0x02 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_12V 0x04 +#define EMMC_EXT_CSD_CARD_TYPE_DDR_52MHZ_18V 0x08 +#define EMMC_EXT_CSD_CARD_TYPE_52MHZ_MASK 0x0e + +/* SWITCH (CMD6) argument */ +#define EXTCSD_ACCESS_BYTE (BIT25 | BIT24) +#define EXTCSD_SET_BITS BIT24 + +#define HS_TIMING_ADD (185 << 16) /* H'b9 */ +#define HS_TIMING_1 (1 << 8) +#define HS_TIMING_HS200 (2 << 8) +#define HS_TIMING_HS400 (3 << 8) + +#define BUS_WIDTH_ADD (183 << 16) /* H'b7 */ +#define BUS_WIDTH_1 (0 << 8) +#define BUS_WIDTH_4 (1 << 8) +#define BUS_WIDTH_8 (2 << 8) +#define BUS_WIDTH_4DDR (5 << 8) +#define BUS_WIDTH_8DDR (6 << 8) + +#define EMMC_SWITCH_HS_TIMING (EXTCSD_ACCESS_BYTE | HS_TIMING_ADD |\ + HS_TIMING_1) /* H'03b90100 */ +#define EMMC_SWITCH_HS_TIMING_OFF (EXTCSD_ACCESS_BYTE |\ + HS_TIMING_ADD) /* H'03b90000 */ + +#define EMMC_SWITCH_BUS_WIDTH_1 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_1) /* H'03b70000 */ +#define EMMC_SWITCH_BUS_WIDTH_4 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4) /* H'03b70100 */ +#define EMMC_SWITCH_BUS_WIDTH_8 (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8) /* H'03b70200 */ +#define EMMC_SWITCH_BUS_WIDTH_4DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_4DDR) /* H'03b70500 */ +#define EMMC_SWITCH_BUS_WIDTH_8DDR (EXTCSD_ACCESS_BYTE | BUS_WIDTH_ADD |\ + BUS_WIDTH_8DDR) /* H'03b70600 */ +/* Partition config = 0x00 */ +#define EMMC_SWITCH_PARTITION_CONFIG 0x03B30000UL + +#define TIMING_HIGH_SPEED 1UL +#define EMMC_BOOT_PARTITION_EN_MASK 0x38U +#define EMMC_BOOT_PARTITION_EN_SHIFT 3U + +/* Bus width */ +#define EMMC_BUSWIDTH_1BIT CE_CMD_SET_DATW_1BIT +#define EMMC_BUSWIDTH_4BIT CE_CMD_SET_DATW_4BIT +#define EMMC_BUSWIDTH_8BIT CE_CMD_SET_DATW_8BIT + +/* for st_mmc_base */ +#define EMMC_MAX_RESPONSE_LENGTH 17 +#define EMMC_MAX_CID_LENGTH 16 +#define EMMC_MAX_CSD_LENGTH 16 +#define EMMC_MAX_EXT_CSD_LENGTH 512U +#define EMMC_RES_REG_ALIGNED 4U +#define EMMC_BUF_REG_ALIGNED 8U + +/* TAAC mask */ +#define TAAC_TIME_UNIT_MASK (0x07) +#define TAAC_MULTIPLIER_FACTOR_MASK (0x0F) + +/* Partition id */ +typedef enum { + PARTITION_ID_USER = 0x0, /* User Area */ + PARTITION_ID_BOOT_1 = 0x1, /* boot partition 1 */ + PARTITION_ID_BOOT_2 = 0x2, /* boot partition 2 */ + PARTITION_ID_RPMB = 0x3, /* Replay Protected Memory Block */ + PARTITION_ID_GP_1 = 0x4, /* General Purpose partition 1 */ + PARTITION_ID_GP_2 = 0x5, /* General Purpose partition 2 */ + PARTITION_ID_GP_3 = 0x6, /* General Purpose partition 3 */ + PARTITION_ID_GP_4 = 0x7, /* General Purpose partition 4 */ + PARTITION_ID_MASK = 0x7 /* [2:0] */ +} EMMC_PARTITION_ID; + +/* card state in R1 response [12:9] */ +typedef enum { + EMMC_R1_STATE_IDLE = 0, + EMMC_R1_STATE_READY, + EMMC_R1_STATE_IDENT, + EMMC_R1_STATE_STBY, + EMMC_R1_STATE_TRAN, + EMMC_R1_STATE_DATA, + EMMC_R1_STATE_RCV, + EMMC_R1_STATE_PRG, + EMMC_R1_STATE_DIS, + EMMC_R1_STATE_BTST, + EMMC_R1_STATE_SLEP +} EMMC_R1_STATE; + +typedef enum { + ESTATE_BEGIN = 0, + ESTATE_ISSUE_CMD, + ESTATE_NON_RESP_CMD, + ESTATE_RCV_RESP, + ESTATE_RCV_RESPONSE_BUSY, + ESTATE_CHECK_RESPONSE_COMPLETE, + ESTATE_DATA_TRANSFER, + ESTATE_DATA_TRANSFER_COMPLETE, + ESTATE_ACCESS_END, + ESTATE_TRANSFER_ERROR, + ESTATE_ERROR, + ESTATE_END +} EMMC_INT_STATE; + +/* eMMC boot driver error information */ +typedef struct { + uint16_t num; /* error no */ + uint16_t code; /* error code */ + + volatile uint32_t info1; /* SD_INFO1. (hw dependent) */ + volatile uint32_t info2; /* SD_INFO2. (hw dependent) */ + volatile uint32_t status1; /* SD_ERR_STS1. (hw dependent) */ + volatile uint32_t status2; /* SD_ERR_STS2. (hw dependent) */ + volatile uint32_t dm_info1; /* DM_CM_INFO1. (hw dependent) */ + volatile uint32_t dm_info2; /* DM_CM_INFO2. (hw dependent) */ +} st_error_info; + +/* Command information */ +typedef struct { + HAL_MEMCARD_COMMAND cmd; /* Command information */ + uint32_t arg; /* argument */ + HAL_MEMCARD_OPERATION dir; /* direction */ + uint32_t hw; /* SD_CMD register value. */ +} st_command_info; + +/* MMC driver base */ +typedef struct { + st_error_info error_info; /* error information */ + st_command_info cmd_info; /* command information */ + + /* for data transfer */ + uint32_t *buff_address_virtual; /* Dest or Src buff */ + uint32_t *buff_address_physical; /* Dest or Src buff */ + HAL_MEMCARD_DATA_WIDTH bus_width; /* bus width */ + + uint32_t trans_size; /* transfer size for this command */ + uint32_t remain_size; /* remain size for this command */ + uint32_t response_length; /* response length for this command */ + uint32_t sector_size; /* sector_size */ + + /* clock */ + uint32_t base_clock; /* MMC host controller clock */ + /* + * Max freq (Card Spec)[Hz]. It changes dynamically by CSD and + * EXT_CSD. + */ + uint32_t max_freq; + /* request freq [Hz] (400K, 26MHz, 52MHz, etc) */ + uint32_t request_freq; + /* current MMC clock[Hz] (the closest frequency supported by HW) */ + uint32_t current_freq; + + /* state flag */ + /* presence status of the memory card */ + HAL_MEMCARD_PRESENCE_STATUS card_present; + + uint32_t card_power_enable; + uint32_t clock_enable; + /* True : initialize complete. */ + uint32_t initialize; + /* True : sector access, FALSE : byte access */ + uint32_t access_mode; + /* True : mount complete. */ + uint32_t mount; + /* True : selected card. */ + uint32_t selected; + /* 0: DMA, 1:PIO */ + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode; + + /* loaded ISSW image No. ISSW have copy image. */ + uint32_t image_num; + /* card state */ + EMMC_R1_STATE current_state; + /* True : during command processing */ + volatile uint32_t during_cmd_processing; + /* True : during transfer */ + volatile uint32_t during_transfer; + /* True : during transfer (DMA) */ + volatile uint32_t during_dma_transfer; + /* True : occurred DMAC error */ + volatile uint32_t dma_error_flag; + /* force terminate flag */ + volatile uint32_t force_terminate; + /* state machine blocking flag : True or False */ + volatile uint32_t state_machine_blocking; + /* True : get partition access processing */ + volatile uint32_t get_partition_access_flag; + + EMMC_PARTITION_ID boot_partition_en; /* Boot partition */ + EMMC_PARTITION_ID partition_access; /* Current access partition */ + + /* timeout */ + uint32_t hs_timing; + + /* read and write data timeout */ + uint32_t data_timeout; + + /* retry */ + uint32_t retries_after_fail; + + /* interrupt */ + volatile uint32_t int_event1; /* interrupt SD_INFO1 Event */ + volatile uint32_t int_event2; /* interrupt SD_INFO2 Event */ + volatile uint32_t dm_event1; /* interrupt DM_CM_INFO1 Event */ + volatile uint32_t dm_event2; /* interrupt DM_CM_INFO2 Event */ + + /* response */ + uint32_t *response; /* buffer ptr for executing command. */ + uint32_t r1_card_status; /* R1 response data */ + uint32_t r3_ocr; /* R3 response data */ + uint32_t r4_resp; /* R4 response data */ + uint32_t r5_resp; /* R5 response data */ + + /* True : clock mode is low. (MMC clock = Max26MHz) */ + uint32_t low_clock_mode_enable; + + uint32_t reserved2; + uint32_t reserved3; + uint32_t reserved4; + + /* CSD registers (4byte align) */ + uint8_t csd_data[EMMC_MAX_CSD_LENGTH] /* CSD */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* CID registers (4byte align) */ + uint8_t cid_data[EMMC_MAX_CID_LENGTH] /* CID */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); + /* EXT CSD registers (8byte align) */ + uint8_t ext_csd_data[EMMC_MAX_EXT_CSD_LENGTH] /* EXT_CSD */ + __attribute__ ((aligned(EMMC_BUF_REG_ALIGNED))); + /* Response registers (4byte align) */ + uint8_t response_data[EMMC_MAX_RESPONSE_LENGTH] /* other response */ + __attribute__ ((aligned(EMMC_RES_REG_ALIGNED))); +} st_mmc_base; + +typedef int (*func) (void); + +uint32_t emmc_get_csd_time(void); + +#define MMC_DEBUG +#endif /* EMMC_STD_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c new file mode 100644 index 0000000..2e88abc --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c @@ -0,0 +1,226 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_registers.h" +#include "emmc_std.h" + +static const uint32_t cmd_reg_hw[EMMC_CMD_MAX + 1] = { + 0x00000000, /* CMD0 */ + 0x00000701, /* CMD1 */ + 0x00000002, /* CMD2 */ + 0x00000003, /* CMD3 */ + 0x00000004, /* CMD4 */ + 0x00000505, /* CMD5 */ + 0x00000406, /* CMD6 */ + 0x00000007, /* CMD7 */ + 0x00001C08, /* CMD8 */ + 0x00000009, /* CMD9 */ + 0x0000000A, /* CMD10 */ + 0x00000000, /* reserved */ + 0x0000000C, /* CMD12 */ + 0x0000000D, /* CMD13 */ + 0x00001C0E, /* CMD14 */ + 0x0000000F, /* CMD15 */ + 0x00000010, /* CMD16 */ + 0x00000011, /* CMD17 */ + 0x00007C12, /* CMD18 */ + 0x00000C13, /* CMD19 */ + 0x00000000, + 0x00001C15, /* CMD21 */ + 0x00000000, + 0x00000017, /* CMD23 */ + 0x00000018, /* CMD24 */ + 0x00006C19, /* CMD25 */ + 0x00000C1A, /* CMD26 */ + 0x0000001B, /* CMD27 */ + 0x0000001C, /* CMD28 */ + 0x0000001D, /* CMD29 */ + 0x0000001E, /* CMD30 */ + 0x00001C1F, /* CMD31 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000423, /* CMD35 */ + 0x00000424, /* CMD36 */ + 0x00000000, + 0x00000026, /* CMD38 */ + 0x00000427, /* CMD39 */ + 0x00000428, /* CMD40(send cmd) */ + 0x00000000, + 0x0000002A, /* CMD42 */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000C31, + 0x00000000, + 0x00000000, + 0x00000000, + 0x00007C35, + 0x00006C36, + 0x00000037, /* CMD55 */ + 0x00000038, /* CMD56(Read) */ + 0x00000000, + 0x00000000, + 0x00000000, + 0x00000000 +}; + +uint32_t emmc_bit_field(uint8_t *data, uint32_t top, uint32_t bottom) +{ + uint32_t value; + + uint32_t index_top = (uint32_t) (15 - (top >> 3)); + uint32_t index_bottom = (uint32_t) (15 - (bottom >> 3)); + + if (index_top == index_bottom) { + value = data[index_top]; + } else if ((index_top + 1) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 8) | data[index_bottom]); + } else if ((index_top + 2) == index_bottom) { + value = + (uint32_t) ((data[index_top] << 16) | + (data[index_top + 1] << 8) | data[index_top + + 2]); + } else { + value = + (uint32_t) ((data[index_top] << 24) | + (data[index_top + 1] << 16) | + (data[index_top + 2] << 8) | + data[index_top + 3]); + } + + value = ((value >> (bottom & 0x07)) & ((1 << (top - bottom + 1)) - 1)); + + return value; +} + +void emmc_write_error_info(uint16_t func_no, EMMC_ERROR_CODE error_code) +{ + + mmc_drv_obj.error_info.num = func_no; + mmc_drv_obj.error_info.code = (uint16_t) error_code; + + ERROR("BL2: emmc err:func_no=0x%x code=0x%x\n", func_no, error_code); +} + +void emmc_write_error_info_func_no(uint16_t func_no) +{ + + mmc_drv_obj.error_info.num = func_no; + + ERROR("BL2: emmc err:func_no=0x%x\n", func_no); +} + +void emmc_make_nontrans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg) +{ + /* command information */ + mmc_drv_obj.cmd_info.cmd = cmd; + mmc_drv_obj.cmd_info.arg = arg; + mmc_drv_obj.cmd_info.dir = HAL_MEMCARD_READ; + mmc_drv_obj.cmd_info.hw = + cmd_reg_hw[cmd & HAL_MEMCARD_COMMAND_INDEX_MASK]; + + /* clear data transfer information */ + mmc_drv_obj.trans_size = 0; + mmc_drv_obj.remain_size = 0; + mmc_drv_obj.buff_address_virtual = NULL; + mmc_drv_obj.buff_address_physical = NULL; + + /* response information */ + mmc_drv_obj.response_length = 6; + + switch (mmc_drv_obj.cmd_info.cmd & HAL_MEMCARD_RESPONSE_TYPE_MASK) { + case HAL_MEMCARD_RESPONSE_NONE: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 0; + break; + case HAL_MEMCARD_RESPONSE_R1: + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R1b: + mmc_drv_obj.cmd_info.hw |= BIT10; /* bit10 = R1 busy bit */ + mmc_drv_obj.response = &mmc_drv_obj.r1_card_status; + break; + case HAL_MEMCARD_RESPONSE_R2: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + mmc_drv_obj.response_length = 17; + break; + case HAL_MEMCARD_RESPONSE_R3: + mmc_drv_obj.response = &mmc_drv_obj.r3_ocr; + break; + case HAL_MEMCARD_RESPONSE_R4: + mmc_drv_obj.response = &mmc_drv_obj.r4_resp; + break; + case HAL_MEMCARD_RESPONSE_R5: + mmc_drv_obj.response = &mmc_drv_obj.r5_resp; + break; + default: + mmc_drv_obj.response = (uint32_t *) mmc_drv_obj.response_data; + break; + } +} + +void emmc_make_trans_cmd(HAL_MEMCARD_COMMAND cmd, uint32_t arg, + uint32_t *buff_address_virtual, + uint32_t len, + HAL_MEMCARD_OPERATION dir, + HAL_MEMCARD_DATA_TRANSFER_MODE transfer_mode) +{ + emmc_make_nontrans_cmd(cmd, arg); /* update common information */ + + /* for data transfer command */ + mmc_drv_obj.cmd_info.dir = dir; + mmc_drv_obj.buff_address_virtual = buff_address_virtual; + mmc_drv_obj.buff_address_physical = buff_address_virtual; + mmc_drv_obj.trans_size = len; + mmc_drv_obj.remain_size = len; + mmc_drv_obj.transfer_mode = transfer_mode; +} + +EMMC_ERROR_CODE emmc_send_idle_cmd(uint32_t arg) +{ + EMMC_ERROR_CODE result; + uint32_t freq; + + /* initialize state */ + mmc_drv_obj.mount = FALSE; + mmc_drv_obj.selected = FALSE; + mmc_drv_obj.during_transfer = FALSE; + mmc_drv_obj.during_cmd_processing = FALSE; + mmc_drv_obj.during_dma_transfer = FALSE; + mmc_drv_obj.dma_error_flag = FALSE; + mmc_drv_obj.force_terminate = FALSE; + mmc_drv_obj.state_machine_blocking = FALSE; + + mmc_drv_obj.bus_width = HAL_MEMCARD_DATA_WIDTH_1_BIT; + mmc_drv_obj.max_freq = MMC_20MHZ; /* 20MHz */ + mmc_drv_obj.current_state = EMMC_R1_STATE_IDLE; + + /* CMD0 (MMC clock is current frequency. if Data transfer mode, 20MHz or higher.) */ + emmc_make_nontrans_cmd(CMD0_GO_IDLE_STATE, arg); /* CMD0 */ + result = emmc_exec_cmd(EMMC_R1_ERROR_MASK, mmc_drv_obj.response); + if (result != EMMC_SUCCESS) { + return result; + } + + /* change MMC clock(400KHz) */ + freq = MMC_400KHZ; + result = emmc_set_request_mmc_clock(&freq); + if (result != EMMC_SUCCESS) { + return result; + } + + return EMMC_SUCCESS; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c new file mode 100644 index 0000000..bf80697 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c @@ -0,0 +1,600 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "cpg_registers.h" +#include "iic_dvfs.h" +#include "rcar_def.h" +#include "rcar_private.h" + +#define DVFS_RETRY_MAX (2U) + +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_0 (0x07U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_1 (0x09U) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_2 (0x0BU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_3 (0x0EU) +#define IIC_DVFS_SET_ICCL_EXTAL_TYPE_E (0x15U) + +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_0 (0x01U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_1 (0x02U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_2 (0x03U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_3 (0x05U) +#define IIC_DVFS_SET_ICCH_EXTAL_TYPE_E (0x07U) + +#define CPG_BIT_SMSTPCR9_DVFS (0x04000000U) + +#define IIC_DVFS_REG_BASE (0xE60B0000U) +#define IIC_DVFS_REG_ICDR (IIC_DVFS_REG_BASE + 0x0000U) +#define IIC_DVFS_REG_ICCR (IIC_DVFS_REG_BASE + 0x0004U) +#define IIC_DVFS_REG_ICSR (IIC_DVFS_REG_BASE + 0x0008U) +#define IIC_DVFS_REG_ICIC (IIC_DVFS_REG_BASE + 0x000CU) +#define IIC_DVFS_REG_ICCL (IIC_DVFS_REG_BASE + 0x0010U) +#define IIC_DVFS_REG_ICCH (IIC_DVFS_REG_BASE + 0x0014U) + +#define IIC_DVFS_BIT_ICSR_BUSY (0x10U) +#define IIC_DVFS_BIT_ICSR_AL (0x08U) +#define IIC_DVFS_BIT_ICSR_TACK (0x04U) +#define IIC_DVFS_BIT_ICSR_WAIT (0x02U) +#define IIC_DVFS_BIT_ICSR_DTE (0x01U) + +#define IIC_DVFS_BIT_ICCR_ENABLE (0x80U) +#define IIC_DVFS_SET_ICCR_START (0x94U) +#define IIC_DVFS_SET_ICCR_STOP (0x90U) +#define IIC_DVFS_SET_ICCR_RETRANSMISSION (0x94U) +#define IIC_DVFS_SET_ICCR_CHANGE (0x81U) +#define IIC_DVFS_SET_ICCR_STOP_READ (0xC0U) + +#define IIC_DVFS_BIT_ICIC_TACKE (0x04U) +#define IIC_DVFS_BIT_ICIC_WAITE (0x02U) +#define IIC_DVFS_BIT_ICIC_DTEE (0x01U) + +#define DVFS_READ_MODE (0x01U) +#define DVFS_WRITE_MODE (0x00U) + +#define IIC_DVFS_SET_DUMMY (0x52U) +#define IIC_DVFS_SET_BUSY_LOOP (500000000U) + +enum dvfs_state_t { + DVFS_START = 0, + DVFS_STOP, + DVFS_RETRANSMIT, + DVFS_READ, + DVFS_STOP_READ, + DVFS_SET_SLAVE_READ, + DVFS_SET_SLAVE, + DVFS_WRITE_ADDR, + DVFS_WRITE_DATA, + DVFS_CHANGE_SEND_TO_RECEIVE, + DVFS_DONE, +}; + +#define DVFS_PROCESS (1) +#define DVFS_COMPLETE (0) +#define DVFS_ERROR (-1) + +#if IMAGE_BL31 +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t __attribute__ ((section(".system_ram"))) \ +dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t __attribute__ ((section(".system_ram"))) \ +rcar_iic_dvfs_ ##__name(__VA_ARGS__) + +#else +#define IIC_DVFS_FUNC(__name, ...) \ +static int32_t dvfs_ ##__name(__VA_ARGS__) + +#define RCAR_DVFS_API(__name, ...) \ +int32_t rcar_iic_dvfs_ ##__name(__VA_ARGS__) +#endif + +IIC_DVFS_FUNC(check_error, enum dvfs_state_t *state, uint32_t *err, uint8_t mode) +{ + uint8_t icsr_al = 0U, icsr_tack = 0U; + uint8_t reg, stop; + uint32_t i = 0U; + + stop = mode == DVFS_READ_MODE ? IIC_DVFS_SET_ICCR_STOP_READ : + IIC_DVFS_SET_ICCR_STOP; + + reg = mmio_read_8(IIC_DVFS_REG_ICSR); + icsr_al = (reg & IIC_DVFS_BIT_ICSR_AL) == IIC_DVFS_BIT_ICSR_AL; + icsr_tack = (reg & IIC_DVFS_BIT_ICSR_TACK) == IIC_DVFS_BIT_ICSR_TACK; + + if (icsr_al == 0U && icsr_tack == 0U) { + return DVFS_PROCESS; + } + + if (icsr_al) { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_AL; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + if (*state == DVFS_SET_SLAVE) { + mmio_write_8(IIC_DVFS_REG_ICDR, IIC_DVFS_SET_DUMMY); + } + + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_WAIT; + } while (reg == 0U); + + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + do { + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & + IIC_DVFS_BIT_ICSR_BUSY; + if (reg == 0U) { + break; + } + + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + + } while (true); + + mmio_write_8(IIC_DVFS_REG_ICCR, 0x00U); + + (*err)++; + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; + + } + + /* icsr_tack */ + mmio_write_8(IIC_DVFS_REG_ICCR, stop); + + reg = mmio_read_8(IIC_DVFS_REG_ICIC); + reg &= ~(IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE); + mmio_write_8(IIC_DVFS_REG_ICIC, reg); + + reg = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_TACK; + mmio_write_8(IIC_DVFS_REG_ICSR, reg); + + i = 0U; + while ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + if (i++ > IIC_DVFS_SET_BUSY_LOOP) { + panic(); + } + } + + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + (*err)++; + + if (*err > DVFS_RETRY_MAX) { + return DVFS_ERROR; + } + + *state = DVFS_START; + + return DVFS_PROCESS; +} + +IIC_DVFS_FUNC(start, enum dvfs_state_t *state) +{ + uint8_t iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_E; + uint8_t icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_E; + int32_t result = DVFS_PROCESS; + uint32_t reg, lsi_product; + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICCR) | IIC_DVFS_BIT_ICCR_ENABLE; + mmio_write_8(IIC_DVFS_REG_ICCR, mode); + + lsi_product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + if (lsi_product == PRR_PRODUCT_E3) { + goto start; + } + + reg = mmio_read_32(RCAR_MODEMR) & CHECK_MD13_MD14; + switch (reg) { + case MD14_MD13_TYPE_0: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_0; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_0; + break; + case MD14_MD13_TYPE_1: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_1; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_1; + break; + case MD14_MD13_TYPE_2: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_2; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_2; + break; + default: + iccl = IIC_DVFS_SET_ICCL_EXTAL_TYPE_3; + icch = IIC_DVFS_SET_ICCH_EXTAL_TYPE_3; + break; + } +start: + mmio_write_8(IIC_DVFS_REG_ICCL, iccl); + mmio_write_8(IIC_DVFS_REG_ICCH, icch); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) + | IIC_DVFS_BIT_ICIC_TACKE + | IIC_DVFS_BIT_ICIC_WAITE | IIC_DVFS_BIT_ICIC_DTEE; + + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_START); + + *state = DVFS_SET_SLAVE; + + return result; +} + +IIC_DVFS_FUNC(set_slave, enum dvfs_state_t *state, uint32_t *err, uint8_t slave) +{ + uint8_t mode; + int32_t result; + uint8_t address; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = slave << 1; + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_WRITE_ADDR; + + return result; +} + +IIC_DVFS_FUNC(write_addr, enum dvfs_state_t *state, uint32_t *err, uint8_t reg_addr) +{ + uint8_t mode; + int32_t result; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_WRITE_DATA; + + return result; +} + +IIC_DVFS_FUNC(write_data, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_data) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_data); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP; + + return result; +} + +IIC_DVFS_FUNC(stop, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_DONE; + + return result; +} + +IIC_DVFS_FUNC(done, void) +{ + uint32_t i; + + for (i = 0U; i < IIC_DVFS_SET_BUSY_LOOP; i++) { + if ((mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_BUSY) != 0U) { + continue; + } + goto done; + } + + panic(); +done: + mmio_write_8(IIC_DVFS_REG_ICCR, 0U); + + return DVFS_COMPLETE; +} + +IIC_DVFS_FUNC(write_reg_addr_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t reg_addr) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICDR, reg_addr); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_RETRANSMIT; + + return result; +} + +IIC_DVFS_FUNC(retransmit, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_RETRANSMISSION); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_SET_SLAVE_READ; + + return result; +} + +IIC_DVFS_FUNC(set_slave_read, enum dvfs_state_t *state, uint32_t *err, + uint8_t slave) +{ + uint8_t address; + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + address = ((uint8_t) (slave << 1) + DVFS_READ_MODE); + mmio_write_8(IIC_DVFS_REG_ICDR, address); + + *state = DVFS_CHANGE_SEND_TO_RECEIVE; + + return result; +} + +IIC_DVFS_FUNC(change_send_to_receive, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_WRITE_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_CHANGE); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + *state = DVFS_STOP_READ; + + return result; +} + +IIC_DVFS_FUNC(stop_read, enum dvfs_state_t *state, uint32_t *err) +{ + int32_t result; + uint8_t mode; + + result = dvfs_check_error(state, err, DVFS_READ_MODE); + if (result == DVFS_ERROR) { + return result; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_WAIT; + if (mode != IIC_DVFS_BIT_ICSR_WAIT) { + return result; + } + + mmio_write_8(IIC_DVFS_REG_ICCR, IIC_DVFS_SET_ICCR_STOP_READ); + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & ~IIC_DVFS_BIT_ICSR_WAIT; + mmio_write_8(IIC_DVFS_REG_ICSR, mode); + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) | IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *state = DVFS_READ; + + return result; +} + +IIC_DVFS_FUNC(read, enum dvfs_state_t *state, uint8_t *reg_data) +{ + uint8_t mode; + + mode = mmio_read_8(IIC_DVFS_REG_ICSR) & IIC_DVFS_BIT_ICSR_DTE; + if (mode != IIC_DVFS_BIT_ICSR_DTE) { + return DVFS_PROCESS; + } + + mode = mmio_read_8(IIC_DVFS_REG_ICIC) & ~IIC_DVFS_BIT_ICIC_DTEE; + mmio_write_8(IIC_DVFS_REG_ICIC, mode); + + *reg_data = mmio_read_8(IIC_DVFS_REG_ICDR); + *state = DVFS_DONE; + + return DVFS_PROCESS; +} + +RCAR_DVFS_API(send, uint8_t slave, uint8_t reg_addr, uint8_t reg_data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 1U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_addr(&state, &err, reg_addr); + break; + case DVFS_WRITE_DATA: + result = dvfs_write_data(&state, &err, reg_data); + break; + case DVFS_STOP: + result = dvfs_stop(&state, &err); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} + +RCAR_DVFS_API(receive, uint8_t slave, uint8_t reg, uint8_t *data) +{ + enum dvfs_state_t state = DVFS_START; + int32_t result = DVFS_PROCESS; + uint32_t err = 0U; + + mstpcr_write(SCMSTPCR9, CPG_MSTPSR9, CPG_BIT_SMSTPCR9_DVFS); + mmio_write_8(IIC_DVFS_REG_ICCR, 1U); +again: + switch (state) { + case DVFS_START: + result = dvfs_start(&state); + break; + case DVFS_SET_SLAVE: + result = dvfs_set_slave(&state, &err, slave); + break; + case DVFS_WRITE_ADDR: + result = dvfs_write_reg_addr_read(&state, &err, reg); + break; + case DVFS_RETRANSMIT: + result = dvfs_retransmit(&state, &err); + break; + case DVFS_SET_SLAVE_READ: + result = dvfs_set_slave_read(&state, &err, slave); + break; + case DVFS_CHANGE_SEND_TO_RECEIVE: + result = dvfs_change_send_to_receive(&state, &err); + break; + case DVFS_STOP_READ: + result = dvfs_stop_read(&state, &err); + break; + case DVFS_READ: + result = dvfs_read(&state, data); + break; + case DVFS_DONE: + result = dvfs_done(); + break; + default: + panic(); + break; + } + + if (result == DVFS_PROCESS) { + goto again; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h new file mode 100644 index 0000000..244c06c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IIC_DVFS_H +#define IIC_DVFS_H + +/* PMIC slave */ +#define PMIC (0x30U) +#define BKUP_MODE_CNT (0x20U) +#define DVFS_SET_VID (0x54U) +#define REG_KEEP10 (0x79U) + +/* EEPROM slave */ +#define EEPROM (0x50U) +#define BOARD_ID (0x70U) + +int32_t rcar_iic_dvfs_receive(uint8_t slave, uint8_t reg, uint8_t *data); +int32_t rcar_iic_dvfs_send(uint8_t slave, uint8_t regr, uint8_t data); + +#endif /* IIC_DVFS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_common.h b/arm-trusted-firmware/drivers/renesas/common/io/io_common.h new file mode 100644 index 0000000..6eb7777 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_common.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_COMMON_H +#define IO_COMMON_H + +typedef struct io_drv_spec { + size_t offset; + size_t length; + uint32_t partition; +} io_drv_spec_t; + +#endif /* IO_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c new file mode 100644 index 0000000..c2b5f7c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "emmc_config.h" +#include "emmc_def.h" +#include "emmc_hal.h" +#include "emmc_std.h" +#include "io_common.h" +#include "io_emmcdrv.h" +#include "io_private.h" + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info); + +typedef struct { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; + EMMC_PARTITION_ID partition; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static EMMC_PARTITION_ID emmcdrv_bootpartition = PARTITION_ID_USER; + +static io_type_t device_type_emmcdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t emmcdrv_block_seek(io_entity_t *entity, int32_t mode, + signed long long offset) +{ + if (mode != IO_SEEK_SET) { + return IO_FAIL; + } + + ((file_state_t *) entity->info)->file_pos = offset; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + file_state_t *fp = (file_state_t *) entity->info; + uint32_t sector_add, sector_num, emmc_dma = 0; + int32_t result = IO_SUCCESS; + + sector_add = current_file.file_pos >> EMMC_SECTOR_SIZE_SHIFT; + sector_num = (length + EMMC_SECTOR_SIZE - 1U) >> EMMC_SECTOR_SIZE_SHIFT; + + NOTICE("BL2: Load dst=0x%lx src=(p:%d)0x%llx(%d) len=0x%lx(%d)\n", + buffer, + current_file.partition, current_file.file_pos, + sector_add, length, sector_num); + + if ((buffer + length - 1U) <= (uintptr_t)UINT32_MAX) { + emmc_dma = LOADIMAGE_FLAGS_DMA_ENABLE; + } + + if (emmc_read_sector((uint32_t *) buffer, sector_add, sector_num, + emmc_dma) != EMMC_SUCCESS) { + result = IO_FAIL; + } + + *length_read = length; + fp->file_pos += (signed long long)length; + + return result; +} + +static int32_t emmcdrv_block_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity) +{ + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + + if (current_file.in_use != 0U) { + WARN("mmc_block: Only one open spec at a time\n"); + return IO_RESOURCES_EXHAUSTED; + } + + current_file.file_pos = 0; + current_file.in_use = 1; + + if (emmcdrv_bootpartition == PARTITION_ID_USER) { + emmcdrv_bootpartition = mmc_drv_obj.boot_partition_en; + if ((emmcdrv_bootpartition == PARTITION_ID_BOOT_1) || + (emmcdrv_bootpartition == PARTITION_ID_BOOT_2)) { + current_file.partition = emmcdrv_bootpartition; + + NOTICE("BL2: eMMC boot from partition %d\n", + emmcdrv_bootpartition); + goto done; + } + return IO_FAIL; + } + + if ((block_spec->partition == PARTITION_ID_USER) || + (block_spec->partition == PARTITION_ID_BOOT_1) || + (block_spec->partition == PARTITION_ID_BOOT_2)) { + current_file.partition = block_spec->partition; + } else { + current_file.partition = emmcdrv_bootpartition; + } + +done: + if (emmc_select_partition(current_file.partition) != EMMC_SUCCESS) { + return IO_FAIL; + } + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_block_close(io_entity_t *entity) +{ + memset((void *)¤t_file, 0, sizeof(current_file)); + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t emmcdrv_dev_funcs = { + .type = &device_type_emmcdrv, + .open = &emmcdrv_block_open, + .seek = &emmcdrv_block_seek, + .size = NULL, + .read = &emmcdrv_block_read, + .write = NULL, + .close = &emmcdrv_block_close, + .dev_init = NULL, + .dev_close = &emmcdrv_dev_close +}; + +static const io_dev_info_t emmcdrv_dev_info = { + .funcs = &emmcdrv_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t emmcdrv_dev_connector = { + &emmcdrv_dev_open, +}; + +static int32_t emmcdrv_dev_open(const uintptr_t spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &emmcdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t emmcdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **dev_con) +{ + int32_t rc; + + rc = io_register_device(&emmcdrv_dev_info); + if (rc == IO_SUCCESS) { + *dev_con = &emmcdrv_dev_connector; + } + + return rc; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h new file mode 100644 index 0000000..95070f2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_EMMCDRV_H +#define IO_EMMCDRV_H + +struct io_dev_connector; +int32_t rcar_register_io_dev_emmcdrv(const io_dev_connector_t **connector); + +#endif /* IO_EMMCDRV_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c new file mode 100644 index 0000000..1f31c0f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "io_common.h" +#include "io_memdrv.h" +#include "io_private.h" +#include "rcar_def.h" + +extern void rcar_dma_exec(uintptr_t dst, uint32_t src, uint32_t len); + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t memdrv_dev_close(io_dev_info_t *dev_info); + +/* + * As we need to be able to keep state for seek, only one file can be open + * at a time. Make this a structure and point to the entity->info. When we + * can malloc memory we can change this to support more open files. + */ +typedef struct { + uint32_t in_use; + uintptr_t base; + signed long long file_pos; +} file_state_t; + +static file_state_t current_file = { 0 }; + +static io_type_t device_type_memdrv(void) +{ + return IO_TYPE_MEMMAP; +} + +static int32_t memdrv_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + const io_drv_spec_t *block_spec = (io_drv_spec_t *) spec; + + /* + * Since we need to track open state for seek() we only allow one open + * spec at a time. When we have dynamic memory we can malloc and set + * entity->info. + */ + if (current_file.in_use != 0U) { + return IO_RESOURCES_EXHAUSTED; + } + + /* File cursor offset for seek and incremental reads etc. */ + current_file.base = block_spec->offset; + current_file.file_pos = 0; + current_file.in_use = 1; + + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_seek(io_entity_t *entity, int32_t mode, + signed long long offset) +{ + if (mode != IO_SEEK_SET) { + return IO_FAIL; + } + + ((file_state_t *) entity->info)->file_pos = offset; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp; + + fp = (file_state_t *) entity->info; + + NOTICE("BL2: dst=0x%lx src=0x%llx len=%ld(0x%lx)\n", + buffer, (unsigned long long)fp->base + + (unsigned long long)fp->file_pos, length, length); + + if (FLASH_MEMORY_SIZE < (fp->file_pos + (signed long long)length)) { + ERROR("BL2: check load image (source address)\n"); + return IO_FAIL; + } + + rcar_dma_exec(buffer, fp->base + (uintptr_t)fp->file_pos, length); + fp->file_pos += (signed long long)length; + *cnt = length; + + return IO_SUCCESS; +} + +static int32_t memdrv_block_close(io_entity_t *entity) +{ + entity->info = 0U; + + memset((void *)¤t_file, 0, sizeof(current_file)); + + return IO_SUCCESS; +} + +static const io_dev_funcs_t memdrv_dev_funcs = { + .type = &device_type_memdrv, + .open = &memdrv_block_open, + .seek = &memdrv_block_seek, + .size = NULL, + .read = &memdrv_block_read, + .write = NULL, + .close = &memdrv_block_close, + .dev_init = NULL, + .dev_close = &memdrv_dev_close, +}; + +static const io_dev_info_t memdrv_dev_info = { + .funcs = &memdrv_dev_funcs, + .info = 0, +}; + +static const io_dev_connector_t memdrv_dev_connector = { + .dev_open = &memdrv_dev_open +}; + +static int32_t memdrv_dev_open(const uintptr_t dev __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &memdrv_dev_info; + + return IO_SUCCESS; +} + +static int32_t memdrv_dev_close(io_dev_info_t *dev_info) +{ + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&memdrv_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &memdrv_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h new file mode 100644 index 0000000..90e6812 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MEMDRV_H +#define IO_MEMDRV_H + +struct io_dev_connector; +int32_t rcar_register_io_dev_memdrv(const io_dev_connector_t **connector); + +#endif /* IO_MEMDRV_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_private.h b/arm-trusted-firmware/drivers/renesas/common/io/io_private.h new file mode 100644 index 0000000..207523a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_private.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_PRIVATE_H +#define IO_PRIVATE_H + +/* + * Return codes reported by 'io_*' APIs + * The value of fail should not overlap with define of the errno. + * The errno is in "include/lib/stdlib/sys/errno.h". + */ +#define IO_SUCCESS (0) +#define IO_FAIL (-0x81) +#define IO_NOT_SUPPORTED (-0x82) +#define IO_RESOURCES_EXHAUSTED (-0x83) + +#endif /* IO_PRIVATE_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c new file mode 100644 index 0000000..45ef386 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "io_rcar.h" +#include "io_common.h" +#include "io_private.h" +#include + +extern int32_t plat_get_drv_source(uint32_t id, uintptr_t *dev, + uintptr_t *image_spec); + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info); +static int32_t rcar_dev_close(io_dev_info_t *dev_info); + +typedef struct { + const int32_t name; + const uint32_t offset; + const uint32_t attr; +} plat_rcar_name_offset_t; + +typedef struct { + /* + * Put position above the struct to allow {0} on static init. + * It is a workaround for a known bug in GCC + * http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53119 + */ + uint32_t position; + uint32_t no_load; + uintptr_t offset; + uint32_t size; + uintptr_t dst; + uintptr_t partition; /* for eMMC */ + /* RCAR_EMMC_PARTITION_BOOT_0 */ + /* RCAR_EMMC_PARTITION_BOOT_1 */ + /* RCAR_EMMC_PARTITION_USER */ +} file_state_t; + +#define RCAR_GET_FLASH_ADR(a, b) ((uint32_t)((0x40000U * (a)) + (b))) +#define RCAR_ATTR_SET_CALCADDR(a) ((a) & 0xF) +#define RCAR_ATTR_SET_ISNOLOAD(a) (((a) & 0x1) << 16U) +#define RCAR_ATTR_SET_CERTOFF(a) (((a) & 0xF) << 8U) +#define RCAR_ATTR_SET_ALL(a, b, c) ((uint32_t)(RCAR_ATTR_SET_CALCADDR(a) |\ + RCAR_ATTR_SET_ISNOLOAD(b) |\ + RCAR_ATTR_SET_CERTOFF(c))) + +#define RCAR_ATTR_GET_CALCADDR(a) ((a) & 0xFU) +#define RCAR_ATTR_GET_ISNOLOAD(a) (((a) >> 16) & 0x1U) +#define RCAR_ATTR_GET_CERTOFF(a) ((uint32_t)(((a) >> 8) & 0xFU)) + +#define RCAR_MAX_BL3X_IMAGE (8U) +#define RCAR_SECTOR6_CERT_OFFSET (0x400U) +#define RCAR_SDRAM_certESS (0x43F00000U) +#define RCAR_CERT_SIZE (0x800U) +#define RCAR_CERT_INFO_SIZE_OFFSET (0x264U) +#define RCAR_CERT_INFO_DST_OFFSET (0x154U) +#define RCAR_CERT_INFO_SIZE_OFFSET1 (0x364U) +#define RCAR_CERT_INFO_DST_OFFSET1 (0x1D4U) +#define RCAR_CERT_INFO_SIZE_OFFSET2 (0x464U) +#define RCAR_CERT_INFO_DST_OFFSET2 (0x254U) +#define RCAR_CERT_LOAD (1U) + +#define RCAR_FLASH_CERT_HEADER RCAR_GET_FLASH_ADR(6U, 0U) +#define RCAR_EMMC_CERT_HEADER (0x00030000U) + +#define RCAR_COUNT_LOAD_BL33 (2U) +#define RCAR_COUNT_LOAD_BL33X (3U) + +static const plat_rcar_name_offset_t name_offset[] = { + {BL31_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(0, 0, 0)}, + + /* BL3-2 is optional in the platform */ + {BL32_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(1, 0, 1)}, + {BL33_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(2, 0, 2)}, + {BL332_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(3, 0, 3)}, + {BL333_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(4, 0, 4)}, + {BL334_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(5, 0, 5)}, + {BL335_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(6, 0, 6)}, + {BL336_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(7, 0, 7)}, + {BL337_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(8, 0, 8)}, + {BL338_IMAGE_ID, 0U, RCAR_ATTR_SET_ALL(9, 0, 9)}, +}; + +#if TRUSTED_BOARD_BOOT +static const plat_rcar_name_offset_t cert_offset[] = { + /* Certificates */ + {TRUSTED_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {NON_TRUSTED_FW_KEY_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {SOC_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 0)}, + {TRUSTED_OS_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 1)}, + {NON_TRUSTED_FW_CONTENT_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 2)}, + {BL332_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 3)}, + {BL333_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 4)}, + {BL334_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 5)}, + {BL335_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 6)}, + {BL336_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 7)}, + {BL337_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 8)}, + {BL338_CERT_ID, 0U, RCAR_ATTR_SET_ALL(0, 1, 9)}, +}; +#endif /* TRUSTED_BOARD_BOOT */ + +static file_state_t current_file = { 0 }; + +static uintptr_t rcar_handle, rcar_spec; +static uint64_t rcar_image_header[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_header_prttn[RCAR_MAX_BL3X_IMAGE + 2U] = { 0U }; +static uint64_t rcar_image_number = { 0U }; +static uint32_t rcar_cert_load = { 0U }; + +static io_type_t device_type_rcar(void) +{ + return IO_TYPE_FIRMWARE_IMAGE_PACKAGE; +} + +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert) +{ +#if TRUSTED_BOARD_BOOT + int32_t i; + + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(cert_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + return 0; + } +#endif + return -EINVAL; +} + +#define MFISBTSTSR (0xE6260604U) +#define MFISBTSTSR_BOOT_PARTITION (0x00000010U) + +static int32_t file_to_offset(const int32_t name, uintptr_t *offset, + uint32_t *cert, uint32_t *no_load, + uintptr_t *partition) +{ + uint32_t addr; + int32_t i; + + for (i = 0; i < ARRAY_SIZE(name_offset); i++) { + if (name != name_offset[i].name) { + continue; + } + + addr = RCAR_ATTR_GET_CALCADDR(name_offset[i].attr); + if (rcar_image_number + 2U < addr) { + continue; + } + + *offset = rcar_image_header[addr]; + + if (mmio_read_32(MFISBTSTSR) & MFISBTSTSR_BOOT_PARTITION) + *offset += 0x800000; + *cert = RCAR_CERT_SIZE; + *cert *= RCAR_ATTR_GET_CERTOFF(name_offset[i].attr); + *cert += RCAR_SDRAM_certESS; + *no_load = RCAR_ATTR_GET_ISNOLOAD(name_offset[i].attr); + *partition = rcar_image_header_prttn[addr]; + return IO_SUCCESS; + } + +#if TRUSTED_BOARD_BOOT + for (i = 0; i < ARRAY_SIZE(cert_offset); i++) { + if (name != cert_offset[i].name) { + continue; + } + + *no_load = RCAR_ATTR_GET_ISNOLOAD(cert_offset[i].attr); + *partition = 0U; + *offset = 0U; + *cert = 0U; + return IO_SUCCESS; + } +#endif + return -EINVAL; +} + +#define RCAR_BOOT_KEY_CERT_NEW (0xE6300F00U) +#define RCAR_CERT_MAGIC_NUM (0xE291F358U) + +void rcar_read_certificate(uint64_t cert, uint32_t *len, uintptr_t *dst) +{ + uint32_t seed, val, info_1, info_2; + uintptr_t size, dsth, dstl; + + cert &= 0xFFFFFFFFU; + + seed = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW); + val = mmio_read_32(RCAR_BOOT_KEY_CERT_NEW + 0xC); + info_1 = (val >> 18) & 0x3U; + val = mmio_read_32(cert + 0xC); + info_2 = (val >> 21) & 0x3; + + if (seed == RCAR_CERT_MAGIC_NUM) { + if (info_1 != 1) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + if (info_2 > 2) { + ERROR("BL2: Cert is invalid.\n"); + *dst = 0; + *len = 0; + return; + } + + switch (info_2) { + case 2: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET2; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET2; + break; + case 1: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET1; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET1; + break; + case 0: + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + break; + } + + *len = mmio_read_32(size) * 4U; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); + return; + } + + size = cert + RCAR_CERT_INFO_SIZE_OFFSET; + *len = mmio_read_32(size) * 4U; + dstl = cert + RCAR_CERT_INFO_DST_OFFSET; + dsth = dstl + 4U; + *dst = ((uintptr_t) mmio_read_32(dsth) << 32) + + ((uintptr_t) mmio_read_32(dstl)); +} + +static int32_t check_load_area(uintptr_t dst, uintptr_t len) +{ + uint32_t legacy = dst + len <= UINT32_MAX - 1 ? 1 : 0; + uintptr_t dram_start, dram_end; + uintptr_t prot_start, prot_end; + int32_t result = IO_SUCCESS; + + dram_start = legacy ? DRAM1_BASE : DRAM_40BIT_BASE; + + dram_end = legacy ? DRAM1_BASE + DRAM1_SIZE : + DRAM_40BIT_BASE + DRAM_40BIT_SIZE; + + prot_start = legacy ? DRAM_PROTECTED_BASE : DRAM_40BIT_PROTECTED_BASE; + + prot_end = prot_start + DRAM_PROTECTED_SIZE; + + if (dst < dram_start || dst > dram_end - len) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + goto done; + } + + /* load image is within SDRAM protected area */ + if (dst >= prot_start && dst < prot_end) { + ERROR("BL2: dst address is on the protected area.\n"); + result = IO_FAIL; + } + + if (dst < prot_start && dst > prot_start - len) { + ERROR("BL2: loaded data is on the protected area.\n"); + result = IO_FAIL; + } +done: + if (result == IO_FAIL) { + ERROR("BL2: Out of range : dst=0x%lx len=0x%lx\n", dst, len); + } + + return result; +} + +static int32_t load_bl33x(void) +{ + static int32_t loaded = IO_NOT_SUPPORTED; + uintptr_t dst, partition, handle; + uint32_t noload, cert, len, i; + uintptr_t offset; + int32_t rc; + size_t cnt; + const int32_t img[] = { + BL33_IMAGE_ID, + BL332_IMAGE_ID, + BL333_IMAGE_ID, + BL334_IMAGE_ID, + BL335_IMAGE_ID, + BL336_IMAGE_ID, + BL337_IMAGE_ID, + BL338_IMAGE_ID + }; + + if (loaded != IO_NOT_SUPPORTED) { + return loaded; + } + + for (i = 1; i < rcar_image_number; i++) { + rc = file_to_offset(img[i], &offset, &cert, &noload, + &partition); + if (rc != IO_SUCCESS) { + WARN("%s: failed to get offset\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + ((io_drv_spec_t *) rcar_spec)->partition = partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("%s: Failed to open FIP (%i)\n", __func__, rc); + loaded = IO_FAIL; + return loaded; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = check_load_area(dst, len); + if (rc != IO_SUCCESS) { + WARN("%s: check load area\n", __func__); + loaded = IO_FAIL; + return loaded; + } + + rc = io_read(handle, dst, len, &cnt); + if (rc != IO_SUCCESS) { + WARN("%s: failed to read\n", __func__); + loaded = IO_FAIL; + return loaded; + } +#if TRUSTED_BOARD_BOOT + rc = auth_mod_verify_img(img[i], (void *)dst, len); + if (rc != 0) { + memset((void *)dst, 0x00, len); + loaded = IO_FAIL; + return loaded; + } +#endif + io_close(handle); + } + + loaded = IO_SUCCESS; + + return loaded; +} + +static int32_t rcar_dev_init(io_dev_info_t *dev_info, const uintptr_t name) +{ + static uint64_t header[64] __aligned(FLASH_TRANS_SIZE_UNIT) = {0UL}; + uintptr_t handle; + ssize_t offset; + uint32_t i; + int32_t rc; + size_t cnt; + + /* Obtain a reference to the image by querying the platform layer */ + rc = plat_get_drv_source(name, &rcar_handle, &rcar_spec); + if (rc != IO_SUCCESS) { + WARN("Failed to obtain reference to img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + if (rcar_cert_load == RCAR_CERT_LOAD) { + return IO_SUCCESS; + } + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to access img %ld (%i)\n", name, rc); + return IO_FAIL; + } + + /* + * get start address list + * [0] address num + * [1] BL33-1 image address + * [2] BL33-2 image address + * [3] BL33-3 image address + * [4] BL33-4 image address + * [5] BL33-5 image address + * [6] BL33-6 image address + * [7] BL33-7 image address + * [8] BL33-8 image address + */ + offset = name == EMMC_DEV_ID ? RCAR_EMMC_CERT_HEADER : + RCAR_FLASH_CERT_HEADER; + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek\n"); + goto error; + } + + rc = io_read(handle, (uintptr_t) &header, sizeof(header), &cnt); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to read\n"); + goto error; + } + +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range((uint64_t) header, sizeof(header)); +#endif + + rcar_image_number = header[0]; + for (i = 0; i < rcar_image_number + 2; i++) { + rcar_image_header[i] = header[i * 2 + 1]; + rcar_image_header_prttn[i] = header[i * 2 + 2]; + } + + if (rcar_image_number == 0 || rcar_image_number > RCAR_MAX_BL3X_IMAGE) { + WARN("Firmware Image Package header check failed.\n"); + rc = IO_FAIL; + goto error; + } + + rc = io_seek(handle, IO_SEEK_SET, offset + RCAR_SECTOR6_CERT_OFFSET); + if (rc != IO_SUCCESS) { + WARN("Firmware Image Package header failed to seek cert\n"); + goto error; + } + + rc = io_read(handle, RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number), &cnt); + if (rc != IO_SUCCESS) { + WARN("cert file read error.\n"); + goto error; + } + +#if RCAR_BL2_DCACHE == 1 + inv_dcache_range(RCAR_SDRAM_certESS, + RCAR_CERT_SIZE * (2 + rcar_image_number)); +#endif + + rcar_cert_load = RCAR_CERT_LOAD; +error: + + if (rc != IO_SUCCESS) { + rc = IO_FAIL; + } + + io_close(handle); + + return rc; + +} + +static int32_t rcar_file_open(io_dev_info_t *info, const uintptr_t file_spec, + io_entity_t *entity) +{ + const io_drv_spec_t *spec = (io_drv_spec_t *) file_spec; + uintptr_t partition, offset, dst; + uint32_t noload, cert, len; + int32_t rc; + + /* + * Only one file open at a time. We need to track state (ie, file + * cursor position). Since the header lives at offset zero, this entry + * should never be zero in an active file. + * Once the system supports dynamic memory allocation we will allow more + * than one open file at a time. + */ + if (current_file.offset != 0U) { + WARN("%s: Only one open file at a time.\n", __func__); + return IO_RESOURCES_EXHAUSTED; + } + + rc = file_to_offset(spec->offset, &offset, &cert, &noload, &partition); + if (rc != IO_SUCCESS) { + WARN("Failed to open file name %ld (%i)\n", spec->offset, rc); + return IO_FAIL; + } + + if (noload != 0U) { + current_file.offset = 1; + current_file.dst = 0; + current_file.size = 1; + current_file.position = 0; + current_file.no_load = noload; + current_file.partition = 0; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; + } + + rcar_read_certificate((uint64_t) cert, &len, &dst); + + /* Baylibre: HACK */ + if (spec->offset == BL31_IMAGE_ID && len < RCAR_TRUSTED_SRAM_SIZE) { + WARN("%s,%s\n", "r-car ignoring the BL31 size from certificate", + "using RCAR_TRUSTED_SRAM_SIZE instead"); + len = RCAR_TRUSTED_SRAM_SIZE; + } + + current_file.partition = partition; + current_file.no_load = noload; + current_file.offset = offset; + current_file.position = 0; + current_file.size = len; + current_file.dst = dst; + entity->info = (uintptr_t) ¤t_file; + + return IO_SUCCESS; +} + +static int32_t rcar_file_len(io_entity_t *entity, size_t *length) +{ + *length = ((file_state_t *) entity->info)->size; + + NOTICE("%s: len: 0x%08lx\n", __func__, *length); + + return IO_SUCCESS; +} + +static int32_t rcar_file_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *cnt) +{ + file_state_t *fp = (file_state_t *) entity->info; + ssize_t offset = fp->offset + fp->position; + uintptr_t handle; + int32_t rc; + +#ifdef SPD_NONE + static uint32_t load_bl33x_counter = 1; +#else + static uint32_t load_bl33x_counter; +#endif + if (current_file.no_load != 0U) { + *cnt = length; + return IO_SUCCESS; + } + + ((io_drv_spec_t *) rcar_spec)->partition = fp->partition; + + rc = io_open(rcar_handle, rcar_spec, &handle); + if (rc != IO_SUCCESS) { + WARN("Failed to open FIP (%i)\n", rc); + return IO_FAIL; + } + + rc = io_seek(handle, IO_SEEK_SET, offset); + if (rc != IO_SUCCESS) { + WARN("%s: failed to seek\n", __func__); + goto error; + } + + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33) { + rc = check_load_area(buffer, length); + if (rc != IO_SUCCESS) { + WARN("%s: load area err\n", __func__); + goto error; + } + } + + rc = io_read(handle, buffer, length, cnt); + if (rc != IO_SUCCESS) { + WARN("Failed to read payload (%i)\n", rc); + goto error; + } + + fp->position += *cnt; + io_close(handle); + + load_bl33x_counter += 1; + if (load_bl33x_counter == RCAR_COUNT_LOAD_BL33X) { + return load_bl33x(); + } + + return IO_SUCCESS; +error: + io_close(handle); + return IO_FAIL; +} + +static int32_t rcar_file_close(io_entity_t *entity) +{ + if (current_file.offset != 0U) { + memset(¤t_file, 0, sizeof(current_file)); + } + + entity->info = 0U; + + return IO_SUCCESS; +} + +static const io_dev_funcs_t rcar_dev_funcs = { + .type = &device_type_rcar, + .open = &rcar_file_open, + .seek = NULL, + .size = &rcar_file_len, + .read = &rcar_file_read, + .write = NULL, + .close = &rcar_file_close, + .dev_init = &rcar_dev_init, + .dev_close = &rcar_dev_close, +}; + +static const io_dev_info_t rcar_dev_info = { + .funcs = &rcar_dev_funcs, + .info = (uintptr_t) 0 +}; + +static const io_dev_connector_t rcar_dev_connector = { + .dev_open = &rcar_dev_open +}; + +static int32_t rcar_dev_open(const uintptr_t dev_spec __attribute__ ((unused)), + io_dev_info_t **dev_info) +{ + *dev_info = (io_dev_info_t *) &rcar_dev_info; + + return IO_SUCCESS; +} + +static int32_t rcar_dev_close(io_dev_info_t *dev_info) +{ + rcar_handle = 0; + rcar_spec = 0; + + return IO_SUCCESS; +} + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con) +{ + int32_t result; + + result = io_register_device(&rcar_dev_info); + if (result == IO_SUCCESS) { + *dev_con = &rcar_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h new file mode 100644 index 0000000..c26a617 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_RCAR_H +#define IO_RCAR_H + +int32_t rcar_register_io_dev(const io_dev_connector_t **dev_con); +int32_t rcar_get_certificate(const int32_t name, uint32_t *cert); +void rcar_read_certificate(uint64_t cert, uint32_t *size, uintptr_t *dest); + +#endif /* IO_RCAR_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h b/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h new file mode 100644 index 0000000..4187733 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pfc_regs.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PFC_REGS_H +#define PFC_REGS_H + +/* GPIO base address */ +#define GPIO_BASE (0xE6050000U) + +/* GPIO registers */ +#define GPIO_IOINTSEL0 (GPIO_BASE + 0x0000U) +#define GPIO_INOUTSEL0 (GPIO_BASE + 0x0004U) +#define GPIO_OUTDT0 (GPIO_BASE + 0x0008U) +#define GPIO_INDT0 (GPIO_BASE + 0x000CU) +#define GPIO_INTDT0 (GPIO_BASE + 0x0010U) +#define GPIO_INTCLR0 (GPIO_BASE + 0x0014U) +#define GPIO_INTMSK0 (GPIO_BASE + 0x0018U) +#define GPIO_MSKCLR0 (GPIO_BASE + 0x001CU) +#define GPIO_POSNEG0 (GPIO_BASE + 0x0020U) +#define GPIO_EDGLEVEL0 (GPIO_BASE + 0x0024U) +#define GPIO_FILONOFF0 (GPIO_BASE + 0x0028U) +#define GPIO_INTMSKS0 (GPIO_BASE + 0x0038U) +#define GPIO_MSKCLRS0 (GPIO_BASE + 0x003CU) +#define GPIO_OUTDTSEL0 (GPIO_BASE + 0x0040U) +#define GPIO_OUTDTH0 (GPIO_BASE + 0x0044U) +#define GPIO_OUTDTL0 (GPIO_BASE + 0x0048U) +#define GPIO_BOTHEDGE0 (GPIO_BASE + 0x004CU) +#define GPIO_IOINTSEL1 (GPIO_BASE + 0x1000U) +#define GPIO_INOUTSEL1 (GPIO_BASE + 0x1004U) +#define GPIO_OUTDT1 (GPIO_BASE + 0x1008U) +#define GPIO_INDT1 (GPIO_BASE + 0x100CU) +#define GPIO_INTDT1 (GPIO_BASE + 0x1010U) +#define GPIO_INTCLR1 (GPIO_BASE + 0x1014U) +#define GPIO_INTMSK1 (GPIO_BASE + 0x1018U) +#define GPIO_MSKCLR1 (GPIO_BASE + 0x101CU) +#define GPIO_POSNEG1 (GPIO_BASE + 0x1020U) +#define GPIO_EDGLEVEL1 (GPIO_BASE + 0x1024U) +#define GPIO_FILONOFF1 (GPIO_BASE + 0x1028U) +#define GPIO_INTMSKS1 (GPIO_BASE + 0x1038U) +#define GPIO_MSKCLRS1 (GPIO_BASE + 0x103CU) +#define GPIO_OUTDTSEL1 (GPIO_BASE + 0x1040U) +#define GPIO_OUTDTH1 (GPIO_BASE + 0x1044U) +#define GPIO_OUTDTL1 (GPIO_BASE + 0x1048U) +#define GPIO_BOTHEDGE1 (GPIO_BASE + 0x104CU) +#define GPIO_IOINTSEL2 (GPIO_BASE + 0x2000U) +#define GPIO_INOUTSEL2 (GPIO_BASE + 0x2004U) +#define GPIO_OUTDT2 (GPIO_BASE + 0x2008U) +#define GPIO_INDT2 (GPIO_BASE + 0x200CU) +#define GPIO_INTDT2 (GPIO_BASE + 0x2010U) +#define GPIO_INTCLR2 (GPIO_BASE + 0x2014U) +#define GPIO_INTMSK2 (GPIO_BASE + 0x2018U) +#define GPIO_MSKCLR2 (GPIO_BASE + 0x201CU) +#define GPIO_POSNEG2 (GPIO_BASE + 0x2020U) +#define GPIO_EDGLEVEL2 (GPIO_BASE + 0x2024U) +#define GPIO_FILONOFF2 (GPIO_BASE + 0x2028U) +#define GPIO_INTMSKS2 (GPIO_BASE + 0x2038U) +#define GPIO_MSKCLRS2 (GPIO_BASE + 0x203CU) +#define GPIO_OUTDTSEL2 (GPIO_BASE + 0x2040U) +#define GPIO_OUTDTH2 (GPIO_BASE + 0x2044U) +#define GPIO_OUTDTL2 (GPIO_BASE + 0x2048U) +#define GPIO_BOTHEDGE2 (GPIO_BASE + 0x204CU) +#define GPIO_IOINTSEL3 (GPIO_BASE + 0x3000U) +#define GPIO_INOUTSEL3 (GPIO_BASE + 0x3004U) +#define GPIO_OUTDT3 (GPIO_BASE + 0x3008U) +#define GPIO_INDT3 (GPIO_BASE + 0x300CU) +#define GPIO_INTDT3 (GPIO_BASE + 0x3010U) +#define GPIO_INTCLR3 (GPIO_BASE + 0x3014U) +#define GPIO_INTMSK3 (GPIO_BASE + 0x3018U) +#define GPIO_MSKCLR3 (GPIO_BASE + 0x301CU) +#define GPIO_POSNEG3 (GPIO_BASE + 0x3020U) +#define GPIO_EDGLEVEL3 (GPIO_BASE + 0x3024U) +#define GPIO_FILONOFF3 (GPIO_BASE + 0x3028U) +#define GPIO_INTMSKS3 (GPIO_BASE + 0x3038U) +#define GPIO_MSKCLRS3 (GPIO_BASE + 0x303CU) +#define GPIO_OUTDTSEL3 (GPIO_BASE + 0x3040U) +#define GPIO_OUTDTH3 (GPIO_BASE + 0x3044U) +#define GPIO_OUTDTL3 (GPIO_BASE + 0x3048U) +#define GPIO_BOTHEDGE3 (GPIO_BASE + 0x304CU) +#define GPIO_IOINTSEL4 (GPIO_BASE + 0x4000U) +#define GPIO_INOUTSEL4 (GPIO_BASE + 0x4004U) +#define GPIO_OUTDT4 (GPIO_BASE + 0x4008U) +#define GPIO_INDT4 (GPIO_BASE + 0x400CU) +#define GPIO_INTDT4 (GPIO_BASE + 0x4010U) +#define GPIO_INTCLR4 (GPIO_BASE + 0x4014U) +#define GPIO_INTMSK4 (GPIO_BASE + 0x4018U) +#define GPIO_MSKCLR4 (GPIO_BASE + 0x401CU) +#define GPIO_POSNEG4 (GPIO_BASE + 0x4020U) +#define GPIO_EDGLEVEL4 (GPIO_BASE + 0x4024U) +#define GPIO_FILONOFF4 (GPIO_BASE + 0x4028U) +#define GPIO_INTMSKS4 (GPIO_BASE + 0x4038U) +#define GPIO_MSKCLRS4 (GPIO_BASE + 0x403CU) +#define GPIO_OUTDTSEL4 (GPIO_BASE + 0x4040U) +#define GPIO_OUTDTH4 (GPIO_BASE + 0x4044U) +#define GPIO_OUTDTL4 (GPIO_BASE + 0x4048U) +#define GPIO_BOTHEDGE4 (GPIO_BASE + 0x404CU) +#define GPIO_IOINTSEL5 (GPIO_BASE + 0x5000U) +#define GPIO_INOUTSEL5 (GPIO_BASE + 0x5004U) +#define GPIO_OUTDT5 (GPIO_BASE + 0x5008U) +#define GPIO_INDT5 (GPIO_BASE + 0x500CU) +#define GPIO_INTDT5 (GPIO_BASE + 0x5010U) +#define GPIO_INTCLR5 (GPIO_BASE + 0x5014U) +#define GPIO_INTMSK5 (GPIO_BASE + 0x5018U) +#define GPIO_MSKCLR5 (GPIO_BASE + 0x501CU) +#define GPIO_POSNEG5 (GPIO_BASE + 0x5020U) +#define GPIO_EDGLEVEL5 (GPIO_BASE + 0x5024U) +#define GPIO_FILONOFF5 (GPIO_BASE + 0x5028U) +#define GPIO_INTMSKS5 (GPIO_BASE + 0x5038U) +#define GPIO_MSKCLRS5 (GPIO_BASE + 0x503CU) +#define GPIO_OUTDTSEL5 (GPIO_BASE + 0x5040U) +#define GPIO_OUTDTH5 (GPIO_BASE + 0x5044U) +#define GPIO_OUTDTL5 (GPIO_BASE + 0x5048U) +#define GPIO_BOTHEDGE5 (GPIO_BASE + 0x504CU) +#define GPIO_IOINTSEL6 (GPIO_BASE + 0x5400U) +#define GPIO_INOUTSEL6 (GPIO_BASE + 0x5404U) +#define GPIO_OUTDT6 (GPIO_BASE + 0x5408U) +#define GPIO_INTDT6 (GPIO_BASE + 0x5410U) +#define GPIO_INTCLR6 (GPIO_BASE + 0x5414U) +#define GPIO_INTMSK6 (GPIO_BASE + 0x5418U) +#define GPIO_MSKCLR6 (GPIO_BASE + 0x541CU) +#define GPIO_POSNEG6 (GPIO_BASE + 0x5420U) +#define GPIO_EDGLEVEL6 (GPIO_BASE + 0x5424U) +#define GPIO_FILONOFF6 (GPIO_BASE + 0x5428U) +#define GPIO_INTMSKS6 (GPIO_BASE + 0x5438U) +#define GPIO_MSKCLRS6 (GPIO_BASE + 0x543CU) +#define GPIO_OUTDTSEL6 (GPIO_BASE + 0x5440U) +#define GPIO_OUTDTH6 (GPIO_BASE + 0x5444U) +#define GPIO_OUTDTL6 (GPIO_BASE + 0x5448U) +#define GPIO_BOTHEDGE6 (GPIO_BASE + 0x544CU) +#define GPIO_IOINTSEL7 (GPIO_BASE + 0x5800U) +#define GPIO_INOUTSEL7 (GPIO_BASE + 0x5804U) +#define GPIO_OUTDT7 (GPIO_BASE + 0x5808U) +#define GPIO_INDT7 (GPIO_BASE + 0x580CU) +#define GPIO_INTDT7 (GPIO_BASE + 0x5810U) +#define GPIO_INTCLR7 (GPIO_BASE + 0x5814U) +#define GPIO_INTMSK7 (GPIO_BASE + 0x5818U) +#define GPIO_MSKCLR7 (GPIO_BASE + 0x581CU) +#define GPIO_POSNEG7 (GPIO_BASE + 0x5820U) +#define GPIO_EDGLEVEL7 (GPIO_BASE + 0x5824U) +#define GPIO_FILONOFF7 (GPIO_BASE + 0x5828U) +#define GPIO_INTMSKS7 (GPIO_BASE + 0x5838U) +#define GPIO_MSKCLRS7 (GPIO_BASE + 0x583CU) +#define GPIO_OUTDTSEL7 (GPIO_BASE + 0x5840U) +#define GPIO_OUTDTH7 (GPIO_BASE + 0x5844U) +#define GPIO_OUTDTL7 (GPIO_BASE + 0x5848U) +#define GPIO_BOTHEDGE7 (GPIO_BASE + 0x584CU) + +/* Pin functon base address */ +#define PFC_BASE (0xE6060000U) + +/* Pin functon registers */ +#define PFC_PMMR (PFC_BASE + 0x0000U) +#define PFC_GPSR0 (PFC_BASE + 0x0100U) +#define PFC_GPSR1 (PFC_BASE + 0x0104U) +#define PFC_GPSR2 (PFC_BASE + 0x0108U) +#define PFC_GPSR3 (PFC_BASE + 0x010CU) +#define PFC_GPSR4 (PFC_BASE + 0x0110U) +#define PFC_GPSR5 (PFC_BASE + 0x0114U) +#define PFC_GPSR6 (PFC_BASE + 0x0118U) +#define PFC_GPSR7 (PFC_BASE + 0x011CU) +#define PFC_IPSR0 (PFC_BASE + 0x0200U) +#define PFC_IPSR1 (PFC_BASE + 0x0204U) +#define PFC_IPSR2 (PFC_BASE + 0x0208U) +#define PFC_IPSR3 (PFC_BASE + 0x020CU) +#define PFC_IPSR4 (PFC_BASE + 0x0210U) +#define PFC_IPSR5 (PFC_BASE + 0x0214U) +#define PFC_IPSR6 (PFC_BASE + 0x0218U) +#define PFC_IPSR7 (PFC_BASE + 0x021CU) +#define PFC_IPSR8 (PFC_BASE + 0x0220U) +#define PFC_IPSR9 (PFC_BASE + 0x0224U) +#define PFC_IPSR10 (PFC_BASE + 0x0228U) +#define PFC_IPSR11 (PFC_BASE + 0x022CU) +#define PFC_IPSR12 (PFC_BASE + 0x0230U) +#define PFC_IPSR13 (PFC_BASE + 0x0234U) +#define PFC_IPSR14 (PFC_BASE + 0x0238U) +#define PFC_IPSR15 (PFC_BASE + 0x023CU) +#define PFC_IPSR16 (PFC_BASE + 0x0240U) +#define PFC_IPSR17 (PFC_BASE + 0x0244U) +#define PFC_IPSR18 (PFC_BASE + 0x0248U) +#define PFC_DRVCTRL0 (PFC_BASE + 0x0300U) +#define PFC_DRVCTRL1 (PFC_BASE + 0x0304U) +#define PFC_DRVCTRL2 (PFC_BASE + 0x0308U) +#define PFC_DRVCTRL3 (PFC_BASE + 0x030CU) +#define PFC_DRVCTRL4 (PFC_BASE + 0x0310U) +#define PFC_DRVCTRL5 (PFC_BASE + 0x0314U) +#define PFC_DRVCTRL6 (PFC_BASE + 0x0318U) +#define PFC_DRVCTRL7 (PFC_BASE + 0x031CU) +#define PFC_DRVCTRL8 (PFC_BASE + 0x0320U) +#define PFC_DRVCTRL9 (PFC_BASE + 0x0324U) +#define PFC_DRVCTRL10 (PFC_BASE + 0x0328U) +#define PFC_DRVCTRL11 (PFC_BASE + 0x032CU) +#define PFC_DRVCTRL12 (PFC_BASE + 0x0330U) +#define PFC_DRVCTRL13 (PFC_BASE + 0x0334U) +#define PFC_DRVCTRL14 (PFC_BASE + 0x0338U) +#define PFC_DRVCTRL15 (PFC_BASE + 0x033CU) +#define PFC_DRVCTRL16 (PFC_BASE + 0x0340U) +#define PFC_DRVCTRL17 (PFC_BASE + 0x0344U) +#define PFC_DRVCTRL18 (PFC_BASE + 0x0348U) +#define PFC_DRVCTRL19 (PFC_BASE + 0x034CU) +#define PFC_DRVCTRL20 (PFC_BASE + 0x0350U) +#define PFC_DRVCTRL21 (PFC_BASE + 0x0354U) +#define PFC_DRVCTRL22 (PFC_BASE + 0x0358U) +#define PFC_DRVCTRL23 (PFC_BASE + 0x035CU) +#define PFC_DRVCTRL24 (PFC_BASE + 0x0360U) +#define PFC_POCCTRL0 (PFC_BASE + 0x0380U) +#define PFC_IOCTRL31 (PFC_BASE + 0x0384U) +#define PFC_POCCTRL2 (PFC_BASE + 0x0388U) +#define PFC_TDSELCTRL0 (PFC_BASE + 0x03C0U) +#define PFC_IOCTRL (PFC_BASE + 0x03E0U) +#define PFC_TSREG (PFC_BASE + 0x03E4U) +#define PFC_PUEN0 (PFC_BASE + 0x0400U) +#define PFC_PUEN1 (PFC_BASE + 0x0404U) +#define PFC_PUEN2 (PFC_BASE + 0x0408U) +#define PFC_PUEN3 (PFC_BASE + 0x040CU) +#define PFC_PUEN4 (PFC_BASE + 0x0410U) +#define PFC_PUEN5 (PFC_BASE + 0x0414U) +#define PFC_PUEN6 (PFC_BASE + 0x0418U) +#define PFC_PUD0 (PFC_BASE + 0x0440U) +#define PFC_PUD1 (PFC_BASE + 0x0444U) +#define PFC_PUD2 (PFC_BASE + 0x0448U) +#define PFC_PUD3 (PFC_BASE + 0x044CU) +#define PFC_PUD4 (PFC_BASE + 0x0450U) +#define PFC_PUD5 (PFC_BASE + 0x0454U) +#define PFC_PUD6 (PFC_BASE + 0x0458U) +#define PFC_MOD_SEL0 (PFC_BASE + 0x0500U) +#define PFC_MOD_SEL1 (PFC_BASE + 0x0504U) +#define PFC_MOD_SEL2 (PFC_BASE + 0x0508U) + +#endif /* PFC_REGS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S b/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S new file mode 100644 index 0000000..aa8644c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.global rcar_pwrc_switch_stack + +/* + * x0 : jump address, + * x1 : stack address, + * x2 : arg, + * x3 : stack address (temporary) + */ +func rcar_pwrc_switch_stack + + /* lr to stack */ + stp x29, x30, [sp,#-16] + + /* change stack pointer */ + mov x3, sp + mov sp, x1 + + /* save stack pointer */ + sub sp, sp, #16 + stp x0, x3, [sp] + + /* data synchronization barrier */ + dsb sy + + /* jump to code */ + mov x1, x0 + mov x0, x2 + blr x1 + + /* load stack pointer */ + ldp x0, x2, [sp,#0] + + /* change stack pointer */ + mov sp, x2 + + /* return */ + ldp x29, x30, [sp,#-16] + ret +endfunc rcar_pwrc_switch_stack diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c new file mode 100644 index 0000000..b60ccab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c @@ -0,0 +1,917 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "iic_dvfs.h" +#include "micro_delay.h" +#include "pwrc.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "cpg_registers.h" + +/* + * Someday there will be a generic power controller api. At the moment each + * platform has its own pwrc so just exporting functions should be acceptable. + */ +RCAR_INSTANTIATE_LOCK + +#define WUP_IRQ_SHIFT (0U) +#define WUP_FIQ_SHIFT (8U) +#define WUP_CSD_SHIFT (16U) +#define BIT_SOFTRESET (1U << 15) +#define BIT_CA53_SCU (1U << 21) +#define BIT_CA57_SCU (1U << 12) +#define REQ_RESUME (1U << 1) +#define REQ_OFF (1U << 0) +#define STATUS_PWRUP (1U << 4) +#define STATUS_PWRDOWN (1U << 0) +#define STATE_CA57_CPU (27U) +#define STATE_CA53_CPU (22U) +#define MODE_L2_DOWN (0x00000002U) +#define CPU_PWR_OFF (0x00000003U) +#define RCAR_PSTR_MASK (0x00000003U) +#define ST_ALL_STANDBY (0x00003333U) +#define SYSCEXTMASK_EXTMSK0 (0x00000001U) +/* Suspend to ram */ +#define DBSC4_REG_BASE (0xE6790000U) +#define DBSC4_REG_DBSYSCNT0 (DBSC4_REG_BASE + 0x0100U) +#define DBSC4_REG_DBACEN (DBSC4_REG_BASE + 0x0200U) +#define DBSC4_REG_DBCMD (DBSC4_REG_BASE + 0x0208U) +#define DBSC4_REG_DBRFEN (DBSC4_REG_BASE + 0x0204U) +#define DBSC4_REG_DBWAIT (DBSC4_REG_BASE + 0x0210U) +#define DBSC4_REG_DBCALCNF (DBSC4_REG_BASE + 0x0424U) +#define DBSC4_REG_DBDFIPMSTRCNF (DBSC4_REG_BASE + 0x0520U) +#define DBSC4_REG_DBPDLK0 (DBSC4_REG_BASE + 0x0620U) +#define DBSC4_REG_DBPDRGA0 (DBSC4_REG_BASE + 0x0624U) +#define DBSC4_REG_DBPDRGD0 (DBSC4_REG_BASE + 0x0628U) +#define DBSC4_REG_DBCAM0CTRL0 (DBSC4_REG_BASE + 0x0940U) +#define DBSC4_REG_DBCAM0STAT0 (DBSC4_REG_BASE + 0x0980U) +#define DBSC4_REG_DBCAM1STAT0 (DBSC4_REG_BASE + 0x0990U) +#define DBSC4_REG_DBCAM2STAT0 (DBSC4_REG_BASE + 0x09A0U) +#define DBSC4_REG_DBCAM3STAT0 (DBSC4_REG_BASE + 0x09B0U) +#define DBSC4_BIT_DBACEN_ACCEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBRFEN_ARFEN ((uint32_t)(1U << 0)) +#define DBSC4_BIT_DBCAMxSTAT0 (0x00000001U) +#define DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN (0x00000001U) +#define DBSC4_SET_DBCMD_OPC_PRE (0x04000000U) +#define DBSC4_SET_DBCMD_OPC_SR (0x0A000000U) +#define DBSC4_SET_DBCMD_OPC_PD (0x08000000U) +#define DBSC4_SET_DBCMD_OPC_MRW (0x0E000000U) +#define DBSC4_SET_DBCMD_CH_ALL (0x00800000U) +#define DBSC4_SET_DBCMD_RANK_ALL (0x00040000U) +#define DBSC4_SET_DBCMD_ARG_ALL (0x00000010U) +#define DBSC4_SET_DBCMD_ARG_ENTER (0x00000000U) +#define DBSC4_SET_DBCMD_ARG_MRW_ODTC (0x00000B00U) +#define DBSC4_SET_DBSYSCNT0_WRITE_ENABLE (0x00001234U) +#define DBSC4_SET_DBSYSCNT0_WRITE_DISABLE (0x00000000U) +#define DBSC4_SET_DBPDLK0_PHY_ACCESS (0x0000A55AU) +#define DBSC4_SET_DBPDRGA0_ACIOCR0 (0x0000001AU) +#define DBSC4_SET_DBPDRGD0_ACIOCR0 (0x33C03C11U) +#define DBSC4_SET_DBPDRGA0_DXCCR (0x00000020U) +#define DBSC4_SET_DBPDRGD0_DXCCR (0x00181006U) +#define DBSC4_SET_DBPDRGA0_PGCR1 (0x00000003U) +#define DBSC4_SET_DBPDRGD0_PGCR1 (0x0380C600U) +#define DBSC4_SET_DBPDRGA0_ACIOCR1 (0x0000001BU) +#define DBSC4_SET_DBPDRGD0_ACIOCR1 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR3 (0x0000001DU) +#define DBSC4_SET_DBPDRGD0_ACIOCR3 (0xAAAAAAAAU) +#define DBSC4_SET_DBPDRGA0_ACIOCR5 (0x0000001FU) +#define DBSC4_SET_DBPDRGD0_ACIOCR5 (0x000000AAU) +#define DBSC4_SET_DBPDRGA0_DX0GCR2 (0x000000A2U) +#define DBSC4_SET_DBPDRGD0_DX0GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR2 (0x000000C2U) +#define DBSC4_SET_DBPDRGD0_DX1GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR2 (0x000000E2U) +#define DBSC4_SET_DBPDRGD0_DX2GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR2 (0x00000102U) +#define DBSC4_SET_DBPDRGD0_DX3GCR2 (0xAAAA0000U) +#define DBSC4_SET_DBPDRGA0_ZQCR (0x00000090U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 (0x04058904U) +#define DBSC4_SET_DBPDRGD0_ZQCR_MD19_1 (0x04058A04U) +#define DBSC4_SET_DBPDRGA0_DX0GCR0 (0x000000A0U) +#define DBSC4_SET_DBPDRGD0_DX0GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX1GCR0 (0x000000C0U) +#define DBSC4_SET_DBPDRGD0_DX1GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX2GCR0 (0x000000E0U) +#define DBSC4_SET_DBPDRGD0_DX2GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX3GCR0 (0x00000100U) +#define DBSC4_SET_DBPDRGD0_DX3GCR0 (0x7C0002E5U) +#define DBSC4_SET_DBPDRGA0_DX0GCR1 (0x000000A1U) +#define DBSC4_SET_DBPDRGD0_DX0GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX1GCR1 (0x000000C1U) +#define DBSC4_SET_DBPDRGD0_DX1GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX2GCR1 (0x000000E1U) +#define DBSC4_SET_DBPDRGD0_DX2GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX3GCR1 (0x00000101U) +#define DBSC4_SET_DBPDRGD0_DX3GCR1 (0x55550000U) +#define DBSC4_SET_DBPDRGA0_DX0GCR3 (0x000000A3U) +#define DBSC4_SET_DBPDRGD0_DX0GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX1GCR3 (0x000000C3U) +#define DBSC4_SET_DBPDRGD0_DX1GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX2GCR3 (0x000000E3U) +#define DBSC4_SET_DBPDRGD0_DX2GCR3 (0x00008484U) +#define DBSC4_SET_DBPDRGA0_DX3GCR3 (0x00000103U) +#define DBSC4_SET_DBPDRGD0_DX3GCR3 (0x00008484U) +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) +#define RST_MODEMR_BIT0 (0x00000001U) + +#define RCAR_CNTCR_OFF (0x00U) +#define RCAR_CNTCVL_OFF (0x08U) +#define RCAR_CNTCVU_OFF (0x0CU) +#define RCAR_CNTFID_OFF (0x20U) + +#define RCAR_CNTCR_EN ((uint32_t)1U << 0U) +#define RCAR_CNTCR_FCREQ(x) ((uint32_t)(x) << 8U) + +#if PMIC_ROHM_BD9571 +#define BIT_BKUP_CTRL_OUT ((uint8_t)(1U << 4)) +#define PMIC_BKUP_MODE_CNT (0x20U) +#define PMIC_QLLM_CNT (0x27U) +#define PMIC_RETRY_MAX (100U) +#endif /* PMIC_ROHM_BD9571 */ +#define SCTLR_EL3_M_BIT ((uint32_t)1U << 0) +#define RCAR_CA53CPU_NUM_MAX (4U) +#define RCAR_CA57CPU_NUM_MAX (4U) +#define IS_A53A57(c) ((c) == RCAR_CLUSTER_A53A57) +#define IS_CA57(c) ((c) == RCAR_CLUSTER_CA57) +#define IS_CA53(c) ((c) == RCAR_CLUSTER_CA53) + +#ifndef __ASSEMBLER__ +IMPORT_SYM(unsigned long, __system_ram_start__, SYSTEM_RAM_START); +IMPORT_SYM(unsigned long, __system_ram_end__, SYSTEM_RAM_END); +IMPORT_SYM(unsigned long, __SRAM_COPY_START__, SRAM_COPY_START); +#endif + +uint32_t rcar_pwrc_status(u_register_t mpidr) +{ + uint32_t ret = 0; + uint64_t cm, cpu; + uint32_t reg; + uint32_t c; + + rcar_lock_get(); + + c = rcar_pwrc_get_cluster(); + cm = mpidr & MPIDR_CLUSTER_MASK; + + if (!IS_A53A57(c) && cm != 0) { + ret = RCAR_INVALID; + goto done; + } + + reg = mmio_read_32(RCAR_PRR); + cpu = mpidr & MPIDR_CPU_MASK; + + if (IS_CA53(c)) + if (reg & (1 << (STATE_CA53_CPU + cpu))) + ret = RCAR_INVALID; + if (IS_CA57(c)) + if (reg & (1 << (STATE_CA57_CPU + cpu))) + ret = RCAR_INVALID; +done: + rcar_lock_release(); + + return ret; +} + +static void scu_power_up(u_register_t mpidr) +{ + uintptr_t reg_pwrsr, reg_cpumcr, reg_pwron, reg_pwrer; + uint32_t c, sysc_reg_bit; + uint32_t lsi_product; + uint32_t lsi_cut; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg_cpumcr = IS_CA57(c) ? RCAR_CA57CPUCMCR : RCAR_CA53CPUCMCR; + sysc_reg_bit = IS_CA57(c) ? BIT_CA57_SCU : BIT_CA53_SCU; + reg_pwron = IS_CA57(c) ? RCAR_PWRONCR5 : RCAR_PWRONCR3; + reg_pwrer = IS_CA57(c) ? RCAR_PWRER5 : RCAR_PWRER3; + reg_pwrsr = IS_CA57(c) ? RCAR_PWRSR5 : RCAR_PWRSR3; + + if ((mmio_read_32(reg_pwrsr) & STATUS_PWRDOWN) == 0) + return; + + if (mmio_read_32(reg_cpumcr) != 0) + mmio_write_32(reg_cpumcr, 0); + + lsi_product = mmio_read_32((uintptr_t)RCAR_PRR); + lsi_cut = lsi_product & PRR_CUT_MASK; + lsi_product &= PRR_PRODUCT_MASK; + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_setbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + + mmio_setbits_32(RCAR_SYSCIER, sysc_reg_bit); + mmio_setbits_32(RCAR_SYSCIMR, sysc_reg_bit); + + do { + while ((mmio_read_32(RCAR_SYSCSR) & REQ_RESUME) == 0) + ; + mmio_write_32(reg_pwron, 1); + } while (mmio_read_32(reg_pwrer) & 1); + + while ((mmio_read_32(RCAR_SYSCISR) & sysc_reg_bit) == 0) + ; + mmio_write_32(RCAR_SYSCISCR, sysc_reg_bit); + + if ((lsi_product == PRR_PRODUCT_M3 && lsi_cut >= PRR_PRODUCT_30) || + lsi_product == PRR_PRODUCT_H3 || + lsi_product == PRR_PRODUCT_M3N || + lsi_product == PRR_PRODUCT_E3) { + mmio_clrbits_32(RCAR_SYSCEXTMASK, SYSCEXTMASK_EXTMSK0); + } + + while ((mmio_read_32(reg_pwrsr) & STATUS_PWRUP) == 0) + ; +} + +void rcar_pwrc_cpuon(u_register_t mpidr) +{ + uint32_t res_data, on_data; + uintptr_t res_reg, on_reg; + uint32_t limit, c; + uint64_t cpu; + + rcar_lock_get(); + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + res_reg = IS_CA53(c) ? RCAR_CA53RESCNT : RCAR_CA57RESCNT; + on_reg = IS_CA53(c) ? RCAR_CA53WUPCR : RCAR_CA57WUPCR; + limit = IS_CA53(c) ? 0x5A5A0000 : 0xA5A50000; + + res_data = mmio_read_32(res_reg) | limit; + scu_power_up(mpidr); + cpu = mpidr & MPIDR_CPU_MASK; + on_data = 1 << cpu; + mmio_write_32(CPG_CPGWPR, ~on_data); + mmio_write_32(on_reg, on_data); + mmio_write_32(res_reg, res_data & (~(1 << (3 - cpu)))); + + rcar_lock_release(); +} + +void rcar_pwrc_cpuoff(u_register_t mpidr) +{ + uint32_t c; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_CA53CPU0CR : RCAR_CA57CPU0CR; + + if (read_mpidr_el1() != mpidr) + panic(); + + mmio_write_32(CPG_CPGWPR, ~CPU_PWR_OFF); + mmio_write_32(reg + cpu * 0x0010, CPU_PWR_OFF); + + rcar_lock_release(); +} + +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_clrbits_32(reg, ((uint32_t) 1 << shift_irq) | + ((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr) +{ + uint32_t c, shift_irq, shift_fiq; + uintptr_t reg; + uint64_t cpu; + + rcar_lock_get(); + + cpu = mpidr & MPIDR_CPU_MASK; + c = rcar_pwrc_get_mpidr_cluster(mpidr); + reg = IS_CA53(c) ? RCAR_WUPMSKCA53 : RCAR_WUPMSKCA57; + + shift_irq = WUP_IRQ_SHIFT + cpu; + shift_fiq = WUP_FIQ_SHIFT + cpu; + + mmio_setbits_32(reg, ((uint32_t) 1 << shift_irq) | + ((uint32_t) 1 << shift_fiq)); + rcar_lock_release(); +} + +void rcar_pwrc_all_disable_interrupt_wakeup(void) +{ + uint32_t cpu_num; + u_register_t cl, cpu, mpidr; + + const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA57, + RCAR_CLUSTER_CA53 + }; + + for (cl = 0; cl < PLATFORM_CLUSTER_COUNT; cl++) { + cpu_num = rcar_pwrc_get_cpu_num(cluster[cl]); + for (cpu = 0; cpu < cpu_num; cpu++) { + mpidr = ((cl << MPIDR_AFFINITY_BITS) | cpu); + if (mpidr == rcar_boot_mpidr) { + rcar_pwrc_enable_interrupt_wakeup(mpidr); + } else { + rcar_pwrc_disable_interrupt_wakeup(mpidr); + } + } + } +} + +void rcar_pwrc_clusteroff(u_register_t mpidr) +{ + uint32_t c, product, cut, reg; + uintptr_t dst; + + rcar_lock_get(); + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + c = rcar_pwrc_get_mpidr_cluster(mpidr); + dst = IS_CA53(c) ? RCAR_CA53CPUCMCR : RCAR_CA57CPUCMCR; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto done; + } + + if (product == PRR_PRODUCT_H3 && cut <= PRR_PRODUCT_20) { + goto done; + } + + /* all of the CPUs in the cluster is in the CoreStandby mode */ + mmio_write_32(dst, MODE_L2_DOWN); +done: + rcar_lock_release(); +} + +static uint64_t rcar_pwrc_saved_cntpct_el0; +static uint32_t rcar_pwrc_saved_cntfid; + +#if RCAR_SYSTEM_SUSPEND +static void rcar_pwrc_save_timer_state(void) +{ + rcar_pwrc_saved_cntpct_el0 = read_cntpct_el0(); + + rcar_pwrc_saved_cntfid = + mmio_read_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF)); +} +#endif /* RCAR_SYSTEM_SUSPEND */ + +void rcar_pwrc_restore_timer_state(void) +{ + /* Stop timer before restoring counter value */ + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), 0U); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVL_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 & 0xFFFFFFFFU)); + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCVU_OFF), + (uint32_t)(rcar_pwrc_saved_cntpct_el0 >> 32U)); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTFID_OFF), + rcar_pwrc_saved_cntfid); + + /* Start generic timer back */ + write_cntfrq_el0((u_register_t)plat_get_syscnt_freq2()); + + mmio_write_32((uintptr_t)(RCAR_CNTC_BASE + RCAR_CNTCR_OFF), + (RCAR_CNTCR_FCREQ(0U) | RCAR_CNTCR_EN)); +} + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void) +{ + mmio_write_32(RCAR_SRESCR, 0x5AA50000U | BIT_SOFTRESET); +} +#endif /* PMIC_ROHM_BD9571 */ + +#define RST_CA53_CPU0_BARH (0xE6160080U) +#define RST_CA53_CPU0_BARL (0xE6160084U) +#define RST_CA57_CPU0_BARH (0xE61600C0U) +#define RST_CA57_CPU0_BARL (0xE61600C4U) + +void rcar_pwrc_setup(void) +{ + uintptr_t rst_barh; + uintptr_t rst_barl; + uint32_t i, j; + uint64_t reset = (uint64_t) (&plat_secondary_reset) & 0xFFFFFFFF; + + const uint32_t cluster[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t reg_barh[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARH, + RST_CA57_CPU0_BARH + }; + const uintptr_t reg_barl[PLATFORM_CLUSTER_COUNT] = { + RST_CA53_CPU0_BARL, + RST_CA57_CPU0_BARL + }; + + for (i = 0; i < PLATFORM_CLUSTER_COUNT; i++) { + rst_barh = reg_barh[i]; + rst_barl = reg_barl[i]; + for (j = 0; j < rcar_pwrc_get_cpu_num(cluster[i]); j++) { + mmio_write_32(rst_barh, 0); + mmio_write_32(rst_barl, (uint32_t) reset); + rst_barh += 0x10; + rst_barl += 0x10; + } + } + + rcar_lock_init(); +} + +#if RCAR_SYSTEM_SUSPEND +#define DBCAM_FLUSH(__bit) \ +do { \ + ; \ +} while (!(mmio_read_32(DBSC4_REG_DBCAM##__bit##STAT0) & DBSC4_BIT_DBCAMxSTAT0)) + + +static void __attribute__ ((section(".system_ram"))) + rcar_pwrc_set_self_refresh(void) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t cut, product; + + product = reg & PRR_PRODUCT_MASK; + cut = reg & PRR_CUT_MASK; + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) { + goto self_refresh; + } + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) { + goto self_refresh; + } + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + +self_refresh: + + /* DFI_PHYMSTR_ACK setting */ + mmio_write_32(DBSC4_REG_DBDFIPMSTRCNF, + mmio_read_32(DBSC4_REG_DBDFIPMSTRCNF) & + (~DBSC4_BIT_DBDFIPMSTRCNF_PMSTREN)); + + /* Set the Self-Refresh mode */ + mmio_write_32(DBSC4_REG_DBACEN, 0); + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + rcar_micro_delay(100); + else if (product == PRR_PRODUCT_H3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + DBCAM_FLUSH(2); + DBCAM_FLUSH(3); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else if (product == PRR_PRODUCT_M3) { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + DBCAM_FLUSH(1); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } else { + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 1); + DBCAM_FLUSH(0); + mmio_write_32(DBSC4_REG_DBCAM0CTRL0, 0); + } + + /* Set the SDRAM calibration configuration register */ + mmio_write_32(DBSC4_REG_DBCALCNF, 0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Self-Refresh entry command */ + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Mode Register Write command. (ODT disabled) */ + reg = DBSC4_SET_DBCMD_OPC_MRW | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_MRW_ODTC; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Power Down entry command */ + reg = DBSC4_SET_DBCMD_OPC_PD | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* Set the auto-refresh enable register */ + mmio_write_32(DBSC4_REG_DBRFEN, 0U); + rcar_micro_delay(1U); + + if (product == PRR_PRODUCT_M3 && cut < PRR_PRODUCT_30) + return; + + if (product == PRR_PRODUCT_H3 && cut < PRR_PRODUCT_20) + return; + + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +static void __attribute__ ((section(".system_ram"))) +rcar_pwrc_set_self_refresh_e3(void) +{ + uint32_t ddr_md; + uint32_t reg; + + ddr_md = (mmio_read_32(RST_MODEMR) >> 19) & RST_MODEMR_BIT0; + + /* Write enable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_ENABLE); + mmio_write_32(DBSC4_REG_DBACEN, 0); + DBCAM_FLUSH(0); + + reg = DBSC4_SET_DBCMD_OPC_PRE | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ALL; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + reg = DBSC4_SET_DBCMD_OPC_SR | DBSC4_SET_DBCMD_CH_ALL | + DBSC4_SET_DBCMD_RANK_ALL | DBSC4_SET_DBCMD_ARG_ENTER; + mmio_write_32(DBSC4_REG_DBCMD, reg); + while (mmio_read_32(DBSC4_REG_DBWAIT)) + ; + + /* + * Set the auto-refresh enable register + * Set the ARFEN bit to 0 in the DBRFEN + */ + mmio_write_32(DBSC4_REG_DBRFEN, 0); + + mmio_write_32(DBSC4_REG_DBPDLK0, DBSC4_SET_DBPDLK0_PHY_ACCESS); + + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR0); + + /* DDR_DXCCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DXCCR); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DXCCR); + + /* DDR_PGCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_PGCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_PGCR1); + + /* DDR_ACIOCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR1); + + /* DDR_ACIOCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR3); + + /* DDR_ACIOCR5 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ACIOCR5); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_ACIOCR5); + + /* DDR_DX0GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR2); + + /* DDR_DX1GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR2); + + /* DDR_DX2GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR2); + + /* DDR_DX3GCR2 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR2); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR2); + + /* DDR_ZQCR */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_ZQCR); + + mmio_write_32(DBSC4_REG_DBPDRGD0, ddr_md == 0 ? + DBSC4_SET_DBPDRGD0_ZQCR_MD19_0 : + DBSC4_SET_DBPDRGD0_ZQCR_MD19_1); + + /* DDR_DX0GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR0); + + /* DDR_DX1GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR0); + + /* DDR_DX2GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR0); + + /* DDR_DX3GCR0 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR0); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR0); + + /* DDR_DX0GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR1); + + /* DDR_DX1GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR1); + + /* DDR_DX2GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR1); + + /* DDR_DX3GCR1 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR1); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR1); + + /* DDR_DX0GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX0GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX0GCR3); + + /* DDR_DX1GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX1GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX1GCR3); + + /* DDR_DX2GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX2GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX2GCR3); + + /* DDR_DX3GCR3 */ + mmio_write_32(DBSC4_REG_DBPDRGA0, DBSC4_SET_DBPDRGA0_DX3GCR3); + mmio_write_32(DBSC4_REG_DBPDRGD0, DBSC4_SET_DBPDRGD0_DX3GCR3); + + /* Write disable */ + mmio_write_32(DBSC4_REG_DBSYSCNT0, DBSC4_SET_DBSYSCNT0_WRITE_DISABLE); +} + +void __attribute__ ((section(".system_ram"))) __attribute__ ((noinline)) +rcar_pwrc_go_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + int32_t rc = -1, qllm = -1; + uint8_t mode; + uint32_t i; +#endif + uint32_t reg, product; + + reg = mmio_read_32(RCAR_PRR); + product = reg & PRR_PRODUCT_MASK; + + if (product != PRR_PRODUCT_E3) + rcar_pwrc_set_self_refresh(); + else + rcar_pwrc_set_self_refresh_e3(); + +#if PMIC_ROHM_BD9571 + /* Set QLLM Cnt Disable */ + for (i = 0; (i < PMIC_RETRY_MAX) && (qllm != 0); i++) + qllm = rcar_iic_dvfs_send(PMIC, PMIC_QLLM_CNT, 0); + + /* Set trigger of power down to PMIV */ + for (i = 0; (i < PMIC_RETRY_MAX) && (rc != 0) && (qllm == 0); i++) { + rc = rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode); + if (rc == 0) { + mode |= BIT_BKUP_CTRL_OUT; + rc = rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode); + } + } +#endif + wfi(); + + while (1) + ; +} + +void rcar_pwrc_set_suspend_to_ram(void) +{ + uintptr_t jump = (uintptr_t) &rcar_pwrc_go_suspend_to_ram; + uintptr_t stack = (uintptr_t) (DEVICE_SRAM_STACK_BASE + + DEVICE_SRAM_STACK_SIZE); + uint32_t sctlr; + + rcar_pwrc_save_timer_state(); + + /* disable MMU */ + sctlr = (uint32_t) read_sctlr_el3(); + sctlr &= (uint32_t) ~SCTLR_EL3_M_BIT; + write_sctlr_el3((uint64_t) sctlr); + + rcar_pwrc_switch_stack(jump, stack, NULL); +} + +void rcar_pwrc_init_suspend_to_ram(void) +{ +#if PMIC_ROHM_BD9571 + uint8_t mode; + + if (rcar_iic_dvfs_receive(PMIC, PMIC_BKUP_MODE_CNT, &mode)) + panic(); + + mode &= (uint8_t) (~BIT_BKUP_CTRL_OUT); + if (rcar_iic_dvfs_send(PMIC, PMIC_BKUP_MODE_CNT, mode)) + panic(); +#endif +} + +void rcar_pwrc_suspend_to_ram(void) +{ +#if RCAR_SYSTEM_RESET_KEEPON_DDR + int32_t error; + + error = rcar_iic_dvfs_send(PMIC, REG_KEEP10, 0); + if (error) { + ERROR("Failed send KEEP10 init ret=%d\n", error); + return; + } +#endif + rcar_pwrc_set_suspend_to_ram(); +} +#endif + +void rcar_pwrc_code_copy_to_system_ram(void) +{ + int ret __attribute__ ((unused)); /* in assert */ + uint32_t attr; + struct device_sram_t { + uintptr_t base; + size_t len; + } sram = { + .base = (uintptr_t) DEVICE_SRAM_BASE, + .len = DEVICE_SRAM_SIZE, + }; + struct ddr_code_t { + void *base; + size_t len; + } code = { + .base = (void *) SRAM_COPY_START, + .len = SYSTEM_RAM_END - SYSTEM_RAM_START, + }; + + attr = MT_MEMORY | MT_RW | MT_SECURE | MT_EXECUTE_NEVER; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + + memcpy((void *)sram.base, code.base, code.len); + flush_dcache_range((uint64_t) sram.base, code.len); + + attr = MT_MEMORY | MT_RO | MT_SECURE | MT_EXECUTE; + ret = xlat_change_mem_attributes(sram.base, sram.len, attr); + assert(ret == 0); + + /* Invalidate instruction cache */ + plat_invalidate_icache(); + dsb(); + isb(); +} + +uint32_t rcar_pwrc_get_cluster(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + + if (reg & (1U << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + return RCAR_CLUSTER_CA57; + + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_A53A57; +} + +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr) +{ + uint32_t c = rcar_pwrc_get_cluster(); + + if (IS_A53A57(c)) { + if (mpidr & MPIDR_CLUSTER_MASK) + return RCAR_CLUSTER_CA53; + + return RCAR_CLUSTER_CA57; + } + + return c; +} + +#if RCAR_LSI == RCAR_D3 +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + return 1; +} +#else +uint32_t rcar_pwrc_get_cpu_num(uint32_t c) +{ + uint32_t reg = mmio_read_32(RCAR_PRR); + uint32_t count = 0, i; + + if (IS_A53A57(c) || IS_CA53(c)) { + if (reg & (1 << (STATE_CA53_CPU + RCAR_CA53CPU_NUM_MAX))) + goto count_ca57; + + for (i = 0; i < RCAR_CA53CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA53_CPU + i))) + continue; + count++; + } + } + +count_ca57: + if (IS_A53A57(c) || IS_CA57(c)) { + if (reg & (1U << (STATE_CA57_CPU + RCAR_CA57CPU_NUM_MAX))) + goto done; + + for (i = 0; i < RCAR_CA57CPU_NUM_MAX; i++) { + if (reg & (1 << (STATE_CA57_CPU + i))) + continue; + count++; + } + } + +done: + return count; +} +#endif + +int32_t rcar_pwrc_cpu_on_check(u_register_t mpidr) +{ + uint64_t i; + uint64_t j; + uint64_t cpu_count; + uintptr_t reg_PSTR; + uint32_t status; + uint64_t my_cpu; + int32_t rtn; + uint32_t my_cluster_type; + const uint32_t cluster_type[PLATFORM_CLUSTER_COUNT] = { + RCAR_CLUSTER_CA53, + RCAR_CLUSTER_CA57 + }; + const uintptr_t registerPSTR[PLATFORM_CLUSTER_COUNT] = { + RCAR_CA53PSTR, + RCAR_CA57PSTR + }; + + my_cluster_type = rcar_pwrc_get_cluster(); + + rtn = 0; + my_cpu = mpidr & ((uint64_t)(MPIDR_CPU_MASK)); + for (i = 0U; i < ((uint64_t)(PLATFORM_CLUSTER_COUNT)); i++) { + cpu_count = rcar_pwrc_get_cpu_num(cluster_type[i]); + reg_PSTR = registerPSTR[i]; + for (j = 0U; j < cpu_count; j++) { + if ((my_cluster_type != cluster_type[i]) || (my_cpu != j)) { + status = mmio_read_32(reg_PSTR) >> (j * 4U); + if ((status & 0x00000003U) == 0U) { + rtn--; + } + } + } + } + + return rtn; +} diff --git a/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h new file mode 100644 index 0000000..eefa62f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2015-2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PWRC_H +#define PWRC_H + +#define PPOFFR_OFF 0x0 +#define PPONR_OFF 0x4 +#define PCOFFR_OFF 0x8 +#define PWKUPR_OFF 0xc +#define PSYSR_OFF 0x10 + +#define PWKUPR_WEN (1ull << 31) + +#define PSYSR_AFF_L2 (1U << 31) +#define PSYSR_AFF_L1 (1 << 30) +#define PSYSR_AFF_L0 (1 << 29) +#define PSYSR_WEN (1 << 28) +#define PSYSR_PC (1 << 27) +#define PSYSR_PP (1 << 26) + +#define PSYSR_WK_SHIFT (24) +#define PSYSR_WK_MASK (0x3) +#define PSYSR_WK(x) (((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK) + +#define WKUP_COLD 0x0 +#define WKUP_RESET 0x1 +#define WKUP_PPONR 0x2 +#define WKUP_GICREQ 0x3 + +#define RCAR_INVALID (0xffffffffU) +#define PSYSR_INVALID 0xffffffff + +#define RCAR_CLUSTER_A53A57 (0U) +#define RCAR_CLUSTER_CA53 (1U) +#define RCAR_CLUSTER_CA57 (2U) + +extern u_register_t rcar_boot_mpidr; + +#ifndef __ASSEMBLER__ +void rcar_pwrc_disable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_enable_interrupt_wakeup(u_register_t mpidr); +void rcar_pwrc_all_disable_interrupt_wakeup(void); +void rcar_pwrc_clusteroff(u_register_t mpidr); +void rcar_pwrc_cpuoff(u_register_t mpidr); +void rcar_pwrc_cpuon(u_register_t mpidr); +int32_t rcar_pwrc_cpu_on_check(u_register_t mpidr); +void rcar_pwrc_setup(void); + +uint32_t rcar_pwrc_get_cpu_wkr(u_register_t mpidr); +uint32_t rcar_pwrc_status(u_register_t mpidr); +uint32_t rcar_pwrc_get_cluster(void); +uint32_t rcar_pwrc_get_mpidr_cluster(u_register_t mpidr); +uint32_t rcar_pwrc_get_cpu_num(uint32_t cluster_type); +void rcar_pwrc_restore_timer_state(void); +void plat_secondary_reset(void); + +void rcar_pwrc_code_copy_to_system_ram(void); + +#if !PMIC_ROHM_BD9571 +void rcar_pwrc_system_reset(void); +#endif + +#if RCAR_SYSTEM_SUSPEND +void rcar_pwrc_go_suspend_to_ram(void); +void rcar_pwrc_set_suspend_to_ram(void); +void rcar_pwrc_init_suspend_to_ram(void); +void rcar_pwrc_suspend_to_ram(void); +#endif + +extern uint32_t rcar_pwrc_switch_stack(uintptr_t jump, uintptr_t stack, + void *arg); +#endif + +#endif /* PWRC_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/qos_reg.h b/arm-trusted-firmware/drivers/renesas/common/qos_reg.h new file mode 100644 index 0000000..f2012fa --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/qos_reg.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_REG_H +#define QOS_REG_H + +#define RCAR_QOS_NONE 3U +#define RCAR_QOS_TYPE_DEFAULT 0U + +#define RCAR_DRAM_SPLIT_LINEAR 0U +#define RCAR_DRAM_SPLIT_4CH 1U +#define RCAR_DRAM_SPLIT_2CH 2U +#define RCAR_DRAM_SPLIT_AUTO 3U +#define RST_BASE (0xE6160000U) +#define RST_MODEMR (RST_BASE + 0x0060U) + +#define DBSC_BASE 0xE6790000U +#define DBSC_DBSYSCNT0 (DBSC_BASE + 0x0100U) +#define DBSC_AXARB (DBSC_BASE + 0x0800U) +#define DBSC_DBCAM0CNF1 (DBSC_BASE + 0x0904U) +#define DBSC_DBCAM0CNF2 (DBSC_BASE + 0x0908U) +#define DBSC_DBCAM0CNF3 (DBSC_BASE + 0x090CU) +#define DBSC_DBSCHCNT0 (DBSC_BASE + 0x1000U) +#define DBSC_DBSCHCNT1 (DBSC_BASE + 0x1004U) +#define DBSC_DBSCHSZ0 (DBSC_BASE + 0x1010U) +#define DBSC_DBSCHRW0 (DBSC_BASE + 0x1020U) +#define DBSC_DBSCHRW1 (DBSC_BASE + 0x1024U) +#define DBSC_DBSCHQOS00 (DBSC_BASE + 0x1030U) +#define DBSC_DBSCHQOS01 (DBSC_BASE + 0x1034U) +#define DBSC_DBSCHQOS02 (DBSC_BASE + 0x1038U) +#define DBSC_DBSCHQOS03 (DBSC_BASE + 0x103CU) +#define DBSC_DBSCHQOS40 (DBSC_BASE + 0x1070U) +#define DBSC_DBSCHQOS41 (DBSC_BASE + 0x1074U) +#define DBSC_DBSCHQOS42 (DBSC_BASE + 0x1078U) +#define DBSC_DBSCHQOS43 (DBSC_BASE + 0x107CU) +#define DBSC_DBSCHQOS90 (DBSC_BASE + 0x10C0U) +#define DBSC_DBSCHQOS91 (DBSC_BASE + 0x10C4U) +#define DBSC_DBSCHQOS92 (DBSC_BASE + 0x10C8U) +#define DBSC_DBSCHQOS93 (DBSC_BASE + 0x10CCU) +#define DBSC_DBSCHQOS120 (DBSC_BASE + 0x10F0U) +#define DBSC_DBSCHQOS121 (DBSC_BASE + 0x10F4U) +#define DBSC_DBSCHQOS122 (DBSC_BASE + 0x10F8U) +#define DBSC_DBSCHQOS123 (DBSC_BASE + 0x10FCU) +#define DBSC_DBSCHQOS130 (DBSC_BASE + 0x1100U) +#define DBSC_DBSCHQOS131 (DBSC_BASE + 0x1104U) +#define DBSC_DBSCHQOS132 (DBSC_BASE + 0x1108U) +#define DBSC_DBSCHQOS133 (DBSC_BASE + 0x110CU) +#define DBSC_DBSCHQOS140 (DBSC_BASE + 0x1110U) +#define DBSC_DBSCHQOS141 (DBSC_BASE + 0x1114U) +#define DBSC_DBSCHQOS142 (DBSC_BASE + 0x1118U) +#define DBSC_DBSCHQOS143 (DBSC_BASE + 0x111CU) +#define DBSC_DBSCHQOS150 (DBSC_BASE + 0x1120U) +#define DBSC_DBSCHQOS151 (DBSC_BASE + 0x1124U) +#define DBSC_DBSCHQOS152 (DBSC_BASE + 0x1128U) +#define DBSC_DBSCHQOS153 (DBSC_BASE + 0x112CU) +#define DBSC_SCFCTST0 (DBSC_BASE + 0x1700U) +#define DBSC_SCFCTST1 (DBSC_BASE + 0x1708U) +#define DBSC_SCFCTST2 (DBSC_BASE + 0x170CU) + +#define AXI_BASE 0xE6784000U +#define AXI_ADSPLCR0 (AXI_BASE + 0x0008U) +#define AXI_ADSPLCR1 (AXI_BASE + 0x000CU) +#define AXI_ADSPLCR2 (AXI_BASE + 0x0010U) +#define AXI_ADSPLCR3 (AXI_BASE + 0x0014U) +#define AXI_MMCR (AXI_BASE + 0x0300U) +#define ADSPLCR0_ADRMODE_DEFAULT ((uint32_t)0U << 31U) +#define ADSPLCR0_ADRMODE_GEN2 ((uint32_t)1U << 31U) +#define ADSPLCR0_SPLITSEL(x) ((uint32_t)(x) << 16U) +#define ADSPLCR0_AREA(x) ((uint32_t)(x) << 8U) +#define ADSPLCR0_SWP 0x0CU + +#define AXI_TR3CR 0xE67D100CU +#define AXI_TR4CR 0xE67D1014U + +#define QOS_BASE0 0xE67E0000U +#define QOSBW_FIX_QOS_BANK0 (QOS_BASE0 + 0x0000U) +#define QOSBW_FIX_QOS_BANK1 (QOS_BASE0 + 0x1000U) +#define QOSBW_BE_QOS_BANK0 (QOS_BASE0 + 0x2000U) +#define QOSBW_BE_QOS_BANK1 (QOS_BASE0 + 0x3000U) +#define QOSCTRL_SL_INIT (QOS_BASE0 + 0x8000U) +#define QOSCTRL_REF_ARS (QOS_BASE0 + 0x8004U) +#define QOSCTRL_STATQC (QOS_BASE0 + 0x8008U) + +#define QOS_BASE1 0xE67F0000U +#define QOSCTRL_RAS (QOS_BASE1 + 0x0000U) +#define QOSCTRL_FIXTH (QOS_BASE1 + 0x0004U) +#define QOSCTRL_RAEN (QOS_BASE1 + 0x0018U) +#define QOSCTRL_REGGD (QOS_BASE1 + 0x0020U) +#define QOSCTRL_DANN (QOS_BASE1 + 0x0030U) +#define QOSCTRL_DANT (QOS_BASE1 + 0x0038U) +#define QOSCTRL_EC (QOS_BASE1 + 0x003CU) +#define QOSCTRL_EMS (QOS_BASE1 + 0x0040U) +#define QOSCTRL_FSS (QOS_BASE1 + 0x0048U) +#define QOSCTRL_INSFC (QOS_BASE1 + 0x0050U) +#define QOSCTRL_BERR (QOS_BASE1 + 0x0054U) +#define QOSCTRL_EARLYR (QOS_BASE1 + 0x0060U) +#define QOSCTRL_RACNT0 (QOS_BASE1 + 0x0080U) +#define QOSCTRL_STATGEN0 (QOS_BASE1 + 0x0088U) + +#define GPU_ACT_GRD 0xFD820808U +#define GPU_ACT0 0xFD820800U +#define GPU_ACT1 0xFD821800U +#define GPU_ACT2 0xFD822800U +#define GPU_ACT3 0xFD823800U +#define GPU_ACT4 0xFD824800U +#define GPU_ACT5 0xFD825800U +#define GPU_ACT6 0xFD826800U +#define GPU_ACT7 0xFD827800U + +#define RT_ACT0 0xFFC50800U +#define RT_ACT1 0xFFC51800U + +#define CPU_ACT0 0xF1300800U +#define CPU_ACT1 0xF1340800U +#define CPU_ACT2 0xF1380800U +#define CPU_ACT3 0xF13C0800U + +#define RCAR_REWT_TRAINING_DISABLE 0U +#define RCAR_REWT_TRAINING_ENABLE 1U + +#define QOSWT_FIX_WTQOS_BANK0 (QOSBW_FIX_QOS_BANK0 + 0x0800U) +#define QOSWT_FIX_WTQOS_BANK1 (QOSBW_FIX_QOS_BANK1 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK0 (QOSBW_BE_QOS_BANK0 + 0x0800U) +#define QOSWT_BE_WTQOS_BANK1 (QOSBW_BE_QOS_BANK1 + 0x0800U) +#define QOSWT_WTEN (QOS_BASE0 + 0x8030U) +#define QOSWT_WTREF (QOS_BASE0 + 0x8034U) +#define QOSWT_WTSET0 (QOS_BASE0 + 0x8038U) +#define QOSWT_WTSET1 (QOS_BASE0 + 0x803CU) + +#endif /* QOS_REG_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c new file mode 100644 index 0000000..fda2815 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "rcar_def.h" +#include "rom_api.h" + +typedef uint32_t(*rom_secure_boot_api_f) (uint32_t *key, uint32_t *cert, + rom_read_flash_f pFuncReadFlash); + +typedef uint32_t(*rom_get_lcs_api_f) (uint32_t *lcs); + +#define OLD_API_TABLE1 (0U) /* H3 Ver.1.0/Ver.1.1 */ +#define OLD_API_TABLE2 (1U) /* H3 Ver.2.0 */ +#define OLD_API_TABLE3 (2U) /* M3 Ver.1.0 */ +#define NEW_API_TABLE (3U) /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ +#define NEW_API_TABLE2 (4U) /* V3M WS1.0 */ +#define API_TABLE_MAX (5U) /* table max */ + /* Later than H3 Ver.2.0 */ + +static uint32_t get_table_index(void) +{ + uint32_t product; + uint32_t cut_ver; + uint32_t index; + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut_ver = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + switch (product) { + case PRR_PRODUCT_H3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_11) + index = OLD_API_TABLE1; + else if (cut_ver == PRR_PRODUCT_20) + index = OLD_API_TABLE2; + else + /* Later than H3 Ver.2.0 */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_M3: + if (cut_ver == PRR_PRODUCT_10) + index = OLD_API_TABLE3; + else + /* M3 Ver.1.1 or later */ + index = NEW_API_TABLE; + break; + case PRR_PRODUCT_V3M: + if (cut_ver == PRR_PRODUCT_10) + /* V3M WS1.0 */ + index = NEW_API_TABLE2; + else + /* V3M WS2.0 or later */ + index = NEW_API_TABLE; + break; + default: + index = NEW_API_TABLE; + break; + } + + return index; +} + +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f read_flash) +{ + static const uintptr_t rom_api_table[API_TABLE_MAX] = { + 0xEB10DD64U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB116ED4U, /* H3 Ver.2.0 */ + 0xEB1102FCU, /* M3 Ver.1.0 */ + 0xEB100180U, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB110128U, /* V3M WS1.0 */ + }; + rom_secure_boot_api_f secure_boot; + uint32_t index; + + index = get_table_index(); + secure_boot = (rom_secure_boot_api_f) rom_api_table[index]; + + return secure_boot(key, cert, read_flash); +} + +uint32_t rcar_rom_get_lcs(uint32_t *lcs) +{ + static const uintptr_t rom_get_lcs_table[API_TABLE_MAX] = { + 0xEB10DFE0U, /* H3 Ver.1.0/Ver.1.1 */ + 0xEB117150U, /* H3 Ver.2.0 */ + 0xEB110578U, /* M3 Ver.1.0 */ + 0xEB10018CU, /* H3 Ver.3.0, M3 Ver.1.1 or later, M3N, E3, D3, V3M WS2.0 */ + 0xEB1103A4U, /* V3M WS1.0 */ + }; + rom_get_lcs_api_f get_lcs; + uint32_t index; + + index = get_table_index(); + get_lcs = (rom_get_lcs_api_f) rom_get_lcs_table[index]; + + return get_lcs(lcs); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h new file mode 100644 index 0000000..1d5b03d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROM_API_H +#define ROM_API_H + +#include + +#define SBROM_OK (0x00000000U) +#define SBROM_ILLEGAL_INPUT_PARAM_ERR (0x0B000001U) +#define SBROM_ILLEGAL_OEM_HASH_VALUE_ERR (0x0B000008U) +#define SBROM_ILLEGAL_LCS_FOR_OPERATION_ERR (0x0B000010U) +#define SBROM_HASH_NOT_PROGRAMMED_ERR (0x0B000100U) +#define SBROM_PUB_KEY_HASH_VALIDATION_FAILURE (0xF1000006U) +#define SBROM_RSA_SIG_VERIFICATION_FAILED (0xF1000007U) + +#define LCS_CM (0x0U) +#define LCS_DM (0x1U) +#define LCS_SD (0x3U) +#define LCS_SE (0x5U) +#define LCS_FA (0x7U) + +typedef uint32_t(*rom_read_flash_f) (uint64_t src, uint8_t *dst, uint32_t len); +uint32_t rcar_rom_secure_boot_api(uint32_t *key, uint32_t *cert, + rom_read_flash_f f); +uint32_t rcar_rom_get_lcs(uint32_t *lcs); + +#endif /* ROM_API_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c new file mode 100644 index 0000000..63de5b8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#include "cpg_registers.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "rpc_registers.h" + +#define MSTPSR9_RPC_BIT (0x00020000U) +#define RPC_CMNCR_MD_BIT (0x80000000U) +#define RPC_PHYCNT_CAL BIT(31) +#define RPC_PHYCNT_STRTIM_M3V1 (0x6 << 15UL) +#define RPC_PHYCNT_STRTIM (0x7 << 15UL) + +static void rpc_enable(void) +{ + /* Enable clock supply to RPC. */ + mstpcr_write(CPG_SMSTPCR9, CPG_MSTPSR9, MSTPSR9_RPC_BIT); +} + +static void rpc_setup(void) +{ + uint32_t product, cut, reg, phy_strtim; + + if (mmio_read_32(RPC_CMNCR) & RPC_CMNCR_MD_BIT) + mmio_clrbits_32(RPC_CMNCR, RPC_CMNCR_MD_BIT); + + product = mmio_read_32(RCAR_PRR) & PRR_PRODUCT_MASK; + cut = mmio_read_32(RCAR_PRR) & PRR_CUT_MASK; + + if ((product == PRR_PRODUCT_M3) && (cut < PRR_PRODUCT_30)) + phy_strtim = RPC_PHYCNT_STRTIM_M3V1; + else + phy_strtim = RPC_PHYCNT_STRTIM; + + reg = mmio_read_32(RPC_PHYCNT); + reg &= ~RPC_PHYCNT_STRTIM; + reg |= phy_strtim; + mmio_write_32(RPC_PHYCNT, reg); + reg |= RPC_PHYCNT_CAL; + mmio_write_32(RPC_PHYCNT, reg); +} + +void rcar_rpc_init(void) +{ + rpc_enable(); + rpc_setup(); +} diff --git a/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h new file mode 100644 index 0000000..79aea85 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPC_REGISTERS_H +#define RPC_REGISTERS_H + +#define RPC_BASE (0xEE200000U) +#define RPC_CMNCR (RPC_BASE + 0x0000U) +#define RPC_SSLDR (RPC_BASE + 0x0004U) +#define RPC_DRCR (RPC_BASE + 0x000CU) +#define RPC_DRCMR (RPC_BASE + 0x0010U) +#define RPC_DRENR (RPC_BASE + 0x001CU) +#define RPC_SMCR (RPC_BASE + 0x0020U) +#define RPC_SMCMR (RPC_BASE + 0x0024U) +#define RPC_SMENR (RPC_BASE + 0x0030U) +#define RPC_CMNSR (RPC_BASE + 0x0048U) +#define RPC_DRDMCR (RPC_BASE + 0x0058U) +#define RPC_DRDRENR (RPC_BASE + 0x005CU) +#define RPC_PHYCNT (RPC_BASE + 0x007CU) +#define RPC_PHYINT (RPC_BASE + 0x0088U) + +#endif /* RPC_REGISTERS_H */ diff --git a/arm-trusted-firmware/drivers/renesas/common/scif/scif.S b/arm-trusted-firmware/drivers/renesas/common/scif/scif.S new file mode 100644 index 0000000..72b5b4b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/scif/scif.S @@ -0,0 +1,341 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define SCIF_INTERNAL_CLK 0 +#define SCIF_EXTARNAL_CLK 1 +#define SCIF_CLK SCIF_INTERNAL_CLK + +/* product register */ +#define PRR (0xFFF00044) +#define PRR_PRODUCT_MASK (0x00007F00) +#define PRR_CUT_MASK (0x000000FF) +#define PRR_PRODUCT_H3_VER_10 (0x00004F00) +#define PRR_PRODUCT_E3 (0x00005700) +#define PRR_PRODUCT_D3 (0x00005800) + +/* module stop */ +#define CPG_BASE (0xE6150000) +#define CPG_SMSTPCR2 (0x0138) +#define CPG_SMSTPCR3 (0x013C) +#define CPG_MSTPSR2 (0x0040) +#define CPG_MSTPSR3 (0x0048) +#define MSTP207 (1 << 7) +#define MSTP310 (1 << 10) +#define CPG_CPGWPR (0x0900) + +/* scif */ +#define SCIF0_BASE (0xE6E60000) +#define SCIF2_BASE (0xE6E88000) +#define SCIF_SCSMR (0x00) +#define SCIF_SCBRR (0x04) +#define SCIF_SCSCR (0x08) +#define SCIF_SCFTDR (0x0C) +#define SCIF_SCFSR (0x10) +#define SCIF_SCFRDR (0x14) +#define SCIF_SCFCR (0x18) +#define SCIF_SCFDR (0x1C) +#define SCIF_SCSPTR (0x20) +#define SCIF_SCLSR (0x24) +#define SCIF_DL (0x30) +#define SCIF_CKS (0x34) + +#if RCAR_LSI == RCAR_V3M +#define SCIF_BASE SCIF0_BASE +#define CPG_SMSTPCR CPG_SMSTPCR2 +#define CPG_MSTPSR CPG_MSTPSR2 +#define MSTP MSTP207 +#else +#define SCIF_BASE SCIF2_BASE +#define CPG_SMSTPCR CPG_SMSTPCR3 +#define CPG_MSTPSR CPG_MSTPSR3 +#define MSTP MSTP310 +#endif + +/* mode pin */ +#define RST_MODEMR (0xE6160060) +#define MODEMR_MD12 (0x00001000) + +#define SCSMR_CA_MASK (1 << 7) +#define SCSMR_CA_ASYNC (0x0000) +#define SCSMR_CHR_MASK (1 << 6) +#define SCSMR_CHR_8 (0x0000) +#define SCSMR_PE_MASK (1 << 5) +#define SCSMR_PE_DIS (0x0000) +#define SCSMR_STOP_MASK (1 << 3) +#define SCSMR_STOP_1 (0x0000) +#define SCSMR_CKS_MASK (3 << 0) +#define SCSMR_CKS_DIV1 (0x0000) +#define SCSMR_INIT_DATA (SCSMR_CA_ASYNC + \ + SCSMR_CHR_8 + \ + SCSMR_PE_DIS + \ + SCSMR_STOP_1 + \ + SCSMR_CKS_DIV1) +#define SCBRR_115200BPS (17) +#define SCBRR_115200BPS_D3_SSCG (16) +#define SCBRR_115200BPS_E3_SSCG (15) +#define SCBRR_230400BPS (8) + +#define SCSCR_TE_MASK (1 << 5) +#define SCSCR_TE_DIS (0x0000) +#define SCSCR_TE_EN (0x0020) +#define SCSCR_RE_MASK (1 << 4) +#define SCSCR_RE_DIS (0x0000) +#define SCSCR_RE_EN (0x0010) +#define SCSCR_CKE_MASK (3 << 0) +#define SCSCR_CKE_INT (0x0000) +#define SCSCR_CKE_BRG (0x0002) +#if SCIF_CLK == SCIF_EXTARNAL_CLK +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_BRG) +#else +#define SCFSR_TEND_MASK (1 << 6) +#define SCFSR_TEND_TRANS_END (0x0040) +#define SCSCR_CKE_INT_CLK (SCSCR_CKE_INT) +#endif +#define SCFSR_INIT_DATA (0x0000) +#define SCFCR_TTRG_MASK (3 << 4) +#define SCFCR_TTRG_8 (0x0000) +#define SCFCR_TTRG_0 (0x0030) +#define SCFCR_TFRST_MASK (1 << 2) +#define SCFCR_TFRST_DIS (0x0000) +#define SCFCR_TFRST_EN (0x0004) +#define SCFCR_RFRS_MASK (1 << 1) +#define SCFCR_RFRS_DIS (0x0000) +#define SCFCR_RFRS_EN (0x0002) +#define SCFCR_INIT_DATA (SCFCR_TTRG_8) +#define SCFDR_T_MASK (0x1f << 8) +#define DL_INIT_DATA (8) +#define CKS_CKS_DIV_MASK (1 << 15) +#define CKS_CKS_DIV_CLK (0x0000) +#define CKS_XIN_MASK (1 << 14) +#define CKS_XIN_SCIF_CLK (0x0000) +#define CKS_INIT_DATA (CKS_CKS_DIV_CLK + CKS_XIN_SCIF_CLK) + + .globl console_rcar_register + .globl console_rcar_init + .globl console_rcar_putc + .globl console_rcar_flush + + /* + * ----------------------------------------------- + * int console_rcar_register( + * uintptr_t base, uint32_t clk, uint32_t baud, + * console_t *console) + * Function to initialize and register a new rcar + * 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_rcar_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + bl console_rcar_init + + mov x0, x6 + mov x30, x7 + finish_console_register rcar, putc=1, getc=0, flush=1 + +register_fail: + ret x7 +endfunc console_rcar_register + + /* + * int console_rcar_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_rcar_register + * and crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success + * Clobber list : x1, x2 + */ +func console_rcar_init + ldr x0, =CPG_BASE + ldr w1, [x0, #CPG_SMSTPCR] + and w1, w1, #~MSTP + mvn w2, w1 + str w2, [x0, #CPG_CPGWPR] + str w1, [x0, #CPG_SMSTPCR] +5: + ldr w1, [x0, #CPG_MSTPSR] + and w1, w1, #MSTP + cbnz w1, 5b + + ldr x0, =SCIF_BASE + /* Clear bits TE and RE in SCSCR to 0 */ + mov w1, #(SCSCR_TE_DIS + SCSCR_RE_DIS) + strh w1, [x0, #SCIF_SCSCR] + /* Set bits TFRST and RFRST in SCFCR to 1 */ + ldrh w1, [x0, #SCIF_SCFCR] + orr w1, w1, #(SCFCR_TFRST_EN + SCFCR_RFRS_EN) + strh w1, [x0, #SCIF_SCFCR] + /* + * Read flags of ER, DR, BRK, and RDF in SCFSR and those of TO and ORER + * in SCLSR, then clear them to 0 + */ + mov w1, #SCFSR_INIT_DATA + strh w1, [x0, #SCIF_SCFSR] + mov w1, #0 + strh w1, [x0, #SCIF_SCLSR] + /* Set bits CKE[1:0] in SCSCR */ + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~SCSCR_CKE_MASK + mov w2, #SCSCR_CKE_INT_CLK + orr w1, w1, w2 + strh w1, [x0, #SCIF_SCSCR] + /* Set data transfer format in SCSMR */ + mov w1, #SCSMR_INIT_DATA + strh w1, [x0, #SCIF_SCSMR] + /* Set value in SCBRR */ +#if SCIF_CLK == SCIF_INTERNAL_CLK + ldr x1, =PRR + ldr w1, [x1] + and w1, w1, #(PRR_PRODUCT_MASK | PRR_CUT_MASK) + mov w2, #PRR_PRODUCT_H3_VER_10 + cmp w1, w2 + beq 3f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_D3 + cmp w1, w2 + beq 5f + and w1, w1, #PRR_PRODUCT_MASK + mov w2, #PRR_PRODUCT_E3 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (E3) */ + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (E3) */ + mov w1, #SCBRR_115200BPS_E3_SSCG + b 2f +5: + /* In case of D3 */ + ldr x1, =RST_MODEMR + ldr w1, [x1] + and w1, w1, #MODEMR_MD12 + mov w2, #MODEMR_MD12 + cmp w1, w2 + bne 4f + + /* When SSCG(MD12) on (D3) */ + mov w1, #SCBRR_115200BPS_D3_SSCG + b 2f +4: + /* In case of H3/M3/M3N or when SSCG(MD12) is off in E3/D3 */ + mov w1, #SCBRR_115200BPS + b 2f +3: + mov w1, #SCBRR_230400BPS +2: + strb w1, [x0, SCIF_SCBRR] +#else + mov w1, #DL_INIT_DATA + strh w1, [x0, #SCIF_DL] + mov w1, #CKS_INIT_DATA + strh w1, [x0, #SCIF_CKS] +#endif + /* 1-bit interval elapsed */ + mov w1, #100 +1: + subs w1, w1, #1 + cbnz w1, 1b + /* + * Set bits RTRG[1:0], TTRG[1:0], and MCE in SCFCR + * Clear bits FRST and RFRST to 0 + */ + mov w1, #SCFCR_INIT_DATA + strh w1, [x0, #SCIF_SCFCR] + /* Set bits TE and RE in SCSCR to 1 */ + ldrh w1, [x0, #SCIF_SCSCR] + orr w1, w1, #(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + mov x0, #1 + + ret +endfunc console_rcar_init + + /* + * int console_rcar_putc(int c, unsigned int 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 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + */ +func console_rcar_putc + ldr x1, =SCIF_BASE + cmp w0, #0xA + /* Prepend '\r' to '\n' */ + bne 2f +1: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 1b + mov w2, #0x0D + strb w2, [x1, #SCIF_SCFTDR] +2: + /* Check if the transmit FIFO is full */ + ldrh w2, [x1, #SCIF_SCFDR] + ubfx w2, w2, #8, #5 + cmp w2, #16 + bcs 2b + strb w0, [x1, #SCIF_SCFTDR] + + /* Clear TEND flag */ + ldrh w2, [x1, #SCIF_SCFSR] + and w2, w2, #~SCFSR_TEND_MASK + strh w2, [x1, #SCIF_SCFSR] + + ret +endfunc console_rcar_putc + + /* + * void console_rcar_flush(void) + * Function to force a write of all buffered + * data that hasn't been output. It returns void + * Clobber list : x0, x1 + */ +func console_rcar_flush + ldr x0, =SCIF_BASE +1: + /* Check TEND flag */ + ldrh w1, [x0, #SCIF_SCFSR] + and w1, w1, #SCFSR_TEND_MASK + cmp w1, #SCFSR_TEND_TRANS_END + bne 1b + + ldr x0, =SCIF_BASE + ldrh w1, [x0, #SCIF_SCSCR] + and w1, w1, #~(SCSCR_TE_EN + SCSCR_RE_EN) + strh w1, [x0, #SCIF_SCSCR] + + ret +endfunc console_rcar_flush diff --git a/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c b/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c new file mode 100644 index 0000000..29ef6f4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "rcar_def.h" + +extern void gicd_set_icenabler(uintptr_t base, unsigned int id); + +#define RST_BASE (0xE6160000U) +#define RST_WDTRSTCR (RST_BASE + 0x0054U) +#define SWDT_BASE (0xE6030000U) +#define SWDT_WTCNT (SWDT_BASE + 0x0000U) +#define SWDT_WTCSRA (SWDT_BASE + 0x0004U) +#define SWDT_WTCSRB (SWDT_BASE + 0x0008U) +#define SWDT_GICD_BASE (0xF1010000U) +#define SWDT_GICC_BASE (0xF1020000U) +#define SWDT_GICD_CTLR (SWDT_GICD_BASE + 0x0000U) +#define SWDT_GICD_IGROUPR (SWDT_GICD_BASE + 0x0080U) +#define SWDT_GICD_ISPRIORITYR (SWDT_GICD_BASE + 0x0400U) +#define SWDT_GICC_CTLR (SWDT_GICC_BASE + 0x0000U) +#define SWDT_GICC_PMR (SWDT_GICC_BASE + 0x0004U) +#define SWDT_GICD_ITARGETSR (SWDT_GICD_BASE + 0x0800U) +#define IGROUPR_NUM (16U) +#define ISPRIORITY_NUM (128U) +#define ITARGET_MASK (0x03U) + +#define WDTRSTCR_UPPER_BYTE (0xA55A0000U) +#define WTCSRA_UPPER_BYTE (0xA5A5A500U) +#define WTCSRB_UPPER_BYTE (0xA5A5A500U) +#define WTCNT_UPPER_BYTE (0x5A5A0000U) +#define WTCNT_RESET_VALUE (0xF488U) +#define WTCSRA_BIT_CKS (0x0007U) +#define WTCSRB_BIT_CKS (0x003FU) +#define SWDT_RSTMSK (1U << 1U) +#define WTCSRA_WOVFE (1U << 3U) +#define WTCSRA_WRFLG (1U << 5U) +#define SWDT_ENABLE (1U << 7U) + +#define WDTRSTCR_MASK_ALL (0x0000FFFFU) +#define WTCSRA_MASK_ALL (0x000000FFU) +#define WTCNT_INIT_DATA (WTCNT_UPPER_BYTE + WTCNT_RESET_VALUE) +#define WTCSRA_INIT_DATA (WTCSRA_UPPER_BYTE + 0x0FU) +#define WTCSRB_INIT_DATA (WTCSRB_UPPER_BYTE + 0x21U) + +#if RCAR_LSI == RCAR_D3 +#define WTCNT_COUNT_8p13k (0x10000U - 40760U) +#else +#define WTCNT_COUNT_8p13k (0x10000U - 40687U) +#endif +#define WTCNT_COUNT_8p13k_H3VER10 (0x10000U - 20343U) +#define WTCNT_COUNT_8p22k (0x10000U - 41115U) +#define WTCNT_COUNT_7p81k (0x10000U - 39062U) +#define WTCSRA_CKS_DIV16 (0x00000002U) + +static void swdt_disable(void) +{ + uint32_t rmsk; + + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK; + mmio_write_32(RST_WDTRSTCR, WDTRSTCR_UPPER_BYTE | rmsk); + + mmio_write_32(SWDT_WTCNT, WTCNT_INIT_DATA); + mmio_write_32(SWDT_WTCSRA, WTCSRA_INIT_DATA); + mmio_write_32(SWDT_WTCSRB, WTCSRB_INIT_DATA); + + /* Set the interrupt clear enable register */ + gicd_set_icenabler(RCAR_GICD_BASE, ARM_IRQ_SEC_WDT); +} + +void rcar_swdt_init(void) +{ + uint32_t rmsk, sr; +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RZ_G2E) + uint32_t reg, val, product_cut, chk_data; + + reg = mmio_read_32(RCAR_PRR); + product_cut = reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + reg = mmio_read_32(RCAR_MODEMR); + chk_data = reg & CHECK_MD13_MD14; +#endif + /* stop watchdog */ + if (mmio_read_32(SWDT_WTCSRA) & SWDT_ENABLE) + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE); + + mmio_write_32(SWDT_WTCSRA, WTCSRA_UPPER_BYTE | + WTCSRA_WOVFE | WTCSRA_CKS_DIV16); + +#if (RCAR_LSI == RCAR_E3) || (RCAR_LSI == RZ_G2E) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_7p81k); +#elif (RCAR_LSI == RCAR_D3) + mmio_write_32(SWDT_WTCNT, WTCNT_UPPER_BYTE | WTCNT_COUNT_8p13k); +#else + val = WTCNT_UPPER_BYTE; + + switch (chk_data) { + case MD14_MD13_TYPE_0: + case MD14_MD13_TYPE_2: + val |= WTCNT_COUNT_8p13k; + break; + case MD14_MD13_TYPE_1: + val |= WTCNT_COUNT_8p22k; + break; + case MD14_MD13_TYPE_3: + val |= product_cut == (PRR_PRODUCT_H3 | PRR_PRODUCT_10) ? + WTCNT_COUNT_8p13k_H3VER10 : WTCNT_COUNT_8p13k; + break; + default: + ERROR("MODEMR ERROR value = %x\n", chk_data); + panic(); + break; + } + + mmio_write_32(SWDT_WTCNT, val); +#endif + rmsk = mmio_read_32(RST_WDTRSTCR) & WDTRSTCR_MASK_ALL; + rmsk |= SWDT_RSTMSK | WDTRSTCR_UPPER_BYTE; + mmio_write_32(RST_WDTRSTCR, rmsk); + + while ((mmio_read_8(SWDT_WTCSRA) & WTCSRA_WRFLG) != 0U) + ; + + /* Start the System WatchDog Timer */ + sr = mmio_read_32(SWDT_WTCSRA) & WTCSRA_MASK_ALL; + mmio_write_32(SWDT_WTCSRA, (WTCSRA_UPPER_BYTE | sr | SWDT_ENABLE)); +} + +void rcar_swdt_release(void) +{ + uintptr_t itarget = SWDT_GICD_ITARGETSR + + (ARM_IRQ_SEC_WDT & ~ITARGET_MASK); + uint32_t i; + + /* Disable FIQ interrupt */ + write_daifset(DAIF_FIQ_BIT); + /* FIQ interrupts are not taken to EL3 */ + write_scr_el3(read_scr_el3() & ~SCR_FIQ_BIT); + + swdt_disable(); + gicv2_cpuif_disable(); + + for (i = 0; i < IGROUPR_NUM; i++) + mmio_write_32(SWDT_GICD_IGROUPR + i * 4, 0U); + + for (i = 0; i < ISPRIORITY_NUM; i++) + mmio_write_32(SWDT_GICD_ISPRIORITYR + i * 4, 0U); + + mmio_write_32(itarget, 0U); + mmio_write_32(SWDT_GICD_CTLR, 0U); + mmio_write_32(SWDT_GICC_CTLR, 0U); + mmio_write_32(SWDT_GICC_PMR, 0U); +} + +void rcar_swdt_exec(uint64_t p) +{ + gicv2_end_of_interrupt(ARM_IRQ_SEC_WDT); + rcar_swdt_release(); + ERROR("\n"); + ERROR("System WDT overflow, occurred address is %p\n", (void *)p); + panic(); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/board/board.c b/arm-trusted-firmware/drivers/renesas/rcar/board/board.c new file mode 100644 index 0000000..dbbaed6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/board/board.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include "board.h" + +#ifndef BOARD_DEFAULT +#if (RCAR_LSI == RCAR_D3) +#define BOARD_DEFAULT (BOARD_DRAAK << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RCAR_E3) +#define BOARD_DEFAULT (BOARD_EBISU << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RCAR_V3M) +#define BOARD_DEFAULT (BOARD_EAGLE << BOARD_CODE_SHIFT) +#else +#define BOARD_DEFAULT (BOARD_SALVATOR_X << BOARD_CODE_SHIFT) +#endif +#endif + +#define BOARD_CODE_MASK (0xF8) +#define BOARD_REV_MASK (0x07) +#define BOARD_CODE_SHIFT (0x03) +#define BOARD_ID_UNKNOWN (0xFF) + +#define SXS_ID { 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SX_ID { 0x10U, 0x11U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SKP_ID { 0x10U, 0x10U, 0x20U, 0x21U, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define SK_ID { 0x10U, 0x30U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EB4_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EB_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define DR_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EA_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define KK_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } + +const char *g_board_tbl[] = { + [BOARD_STARTER_KIT_PRE] = "Starter Kit Premier", + [BOARD_STARTER_KIT] = "Starter Kit", + [BOARD_SALVATOR_XS] = "Salvator-XS", + [BOARD_SALVATOR_X] = "Salvator-X", + [BOARD_EBISU_4D] = "Ebisu-4D", + [BOARD_KRIEK] = "Kriek", + [BOARD_EBISU] = "Ebisu", + [BOARD_DRAAK] = "Draak", + [BOARD_EAGLE] = "Eagle", + [BOARD_UNKNOWN] = "unknown" +}; + +int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev) +{ + int32_t ret = 0; + const uint8_t board_tbl[][8] = { + [BOARD_STARTER_KIT_PRE] = SKP_ID, + [BOARD_SALVATOR_XS] = SXS_ID, + [BOARD_STARTER_KIT] = SK_ID, + [BOARD_SALVATOR_X] = SX_ID, + [BOARD_EBISU_4D] = EB4_ID, + [BOARD_EBISU] = EB_ID, + [BOARD_DRAAK] = DR_ID, + [BOARD_EAGLE] = EA_ID, + [BOARD_KRIEK] = KK_ID, + }; + static uint8_t board_id = BOARD_ID_UNKNOWN; + + if (board_id != BOARD_ID_UNKNOWN) + goto get_type; + +#if PMIC_ROHM_BD9571 + /* Board ID detection from EEPROM */ + ret = rcar_iic_dvfs_receive(EEPROM, BOARD_ID, &board_id); + if (ret) { + board_id = BOARD_ID_UNKNOWN; + goto get_type; + } + + if (board_id == BOARD_ID_UNKNOWN) + board_id = BOARD_DEFAULT; +#else + board_id = BOARD_DEFAULT; +#endif + +get_type: + *type = ((uint32_t) board_id & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT; + + if (*type >= ARRAY_SIZE(board_tbl)) { + /* no revision information, set Rev0.0. */ + *rev = 0; + return ret; + } + + *rev = board_tbl[*type][(uint8_t) (board_id & BOARD_REV_MASK)]; + + return ret; +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/board/board.h b/arm-trusted-firmware/drivers/renesas/rcar/board/board.h new file mode 100644 index 0000000..51a8e30 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/board/board.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights + * reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_H +#define BOARD_H + +#define BOARD_SALVATOR_X (0x00) +#define BOARD_KRIEK (0x01) +#define BOARD_STARTER_KIT (0x02) +#define BOARD_SALVATOR_XS (0x04) +#define BOARD_EBISU (0x08) +#define BOARD_STARTER_KIT_PRE (0x0B) +#define BOARD_EBISU_4D (0x0DU) +#define BOARD_DRAAK (0x0EU) +#define BOARD_EAGLE (0x0FU) +#define BOARD_UNKNOWN (BOARD_EAGLE + 1U) + +#define BOARD_REV_UNKNOWN (0xFF) + +extern const char *g_board_tbl[]; + +/************************************************************************ + * Revisions are expressed in 8 bits. + * The upper 4 bits are major version. + * The lower 4 bits are minor version. + ************************************************************************/ +#define GET_BOARD_MAJOR(a) ((uint32_t)(a) >> 0x4) +#define GET_BOARD_MINOR(a) ((uint32_t)(a) & 0xF) +#define GET_BOARD_NAME(a) (g_board_tbl[(a)]) + +int32_t rcar_get_board_type(uint32_t *type, uint32_t *rev); + +#endif /* BOARD_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c new file mode 100644 index 0000000..5ffb2e1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "ulcb_cpld.h" + +#define SCLK 8 /* GP_6_8 */ +#define SSTBZ 3 /* GP_2_3 */ +#define MOSI 7 /* GP_6_7 */ + +#define CPLD_ADDR_RESET 0x80 /* RW */ + +/* LSI Multiplexed Pin Setting Mask Register */ +#define PFC_PMMR 0xE6060000 + +/* General output registers */ +#define GPIO_OUTDT2 0xE6052008 +#define GPIO_OUTDT6 0xE6055408 + +/* General input/output switching registers */ +#define GPIO_INOUTSEL2 0xE6052004 +#define GPIO_INOUTSEL6 0xE6055404 + +/* General IO/Interrupt Switching Register */ +#define GPIO_IOINTSEL6 0xE6055400 + +/* GPIO/perihperal function select */ +#define PFC_GPSR2 0xE6060108 +#define PFC_GPSR6 0xE6060118 + +static void gpio_set_value(uint32_t addr, uint8_t gpio, uint32_t val) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + if (val) + reg |= (1 << gpio); + else + reg &= ~(1 << gpio); + mmio_write_32(addr, reg); +} + +static void gpio_direction_output(uint32_t addr, uint8_t gpio) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg |= (1 << gpio); + mmio_write_32(addr, reg); +} + +static void gpio_pfc(uint32_t addr, uint8_t gpio) +{ + uint32_t reg; + + reg = mmio_read_32(addr); + reg &= ~(1 << gpio); + mmio_write_32(PFC_PMMR, ~reg); + mmio_write_32(addr, reg); +} + +static void cpld_write(uint8_t addr, uint32_t data) +{ + int i; + + for (i = 0; i < 32; i++) { + /* MSB first */ + gpio_set_value(GPIO_OUTDT6, MOSI, data & (1U << 31)); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + data <<= 1; + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + } + + for (i = 0; i < 8; i++) { + /* MSB first */ + gpio_set_value(GPIO_OUTDT6, MOSI, addr & 0x80); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + addr <<= 1; + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + } + + /* WRITE */ + gpio_set_value(GPIO_OUTDT6, MOSI, 1); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 0); + gpio_set_value(GPIO_OUTDT6, SCLK, 1); + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 1); +} + +static void cpld_init(void) +{ + gpio_pfc(PFC_GPSR6, SCLK); + gpio_pfc(PFC_GPSR2, SSTBZ); + gpio_pfc(PFC_GPSR6, MOSI); + + gpio_set_value(GPIO_IOINTSEL6, SCLK, 0); + gpio_set_value(GPIO_OUTDT6, SCLK, 0); + gpio_set_value(GPIO_OUTDT2, SSTBZ, 1); + gpio_set_value(GPIO_OUTDT6, MOSI, 0); + + gpio_direction_output(GPIO_INOUTSEL6, SCLK); + gpio_direction_output(GPIO_INOUTSEL2, SSTBZ); + gpio_direction_output(GPIO_INOUTSEL6, MOSI); +} + +void rcar_cpld_reset_cpu(void) +{ + cpld_init(); + + cpld_write(CPLD_ADDR_RESET, 1); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h new file mode 100644 index 0000000..1616d71 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_ULCB_CPLD_H__ +#define RCAR_ULCB_CPLD_H__ + +extern void rcar_cpld_reset_cpu(void); + +#endif /* RCAR_ULCB_CPLD_H__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c new file mode 100644 index 0000000..aaa3b43 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "pfc_init_d3.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1_TANS BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0_TANS BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_HDMI1_CEC BIT(3) +#define GPSR7_HDMI0_CEC BIT(2) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_HDMI0_CEC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_HDMI1_CEC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_d3(void) +{ + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, 0x00000000U); + pfc_reg_write(PFC_MOD_SEL1, 0x00000000U); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, 0x00000001U); + pfc_reg_write(PFC_IPSR1, 0x00000000U); + pfc_reg_write(PFC_IPSR2, 0x00000000U); + pfc_reg_write(PFC_IPSR3, 0x00000000U); + pfc_reg_write(PFC_IPSR4, 0x00002000U); + pfc_reg_write(PFC_IPSR5, 0x00000000U); + pfc_reg_write(PFC_IPSR6, 0x00000000U); + pfc_reg_write(PFC_IPSR7, 0x00000000U); + pfc_reg_write(PFC_IPSR8, 0x11003301U); + pfc_reg_write(PFC_IPSR9, 0x11111111U); + pfc_reg_write(PFC_IPSR10, 0x00020000U); + pfc_reg_write(PFC_IPSR11, 0x40001110U); + pfc_reg_write(PFC_IPSR12, 0x00000000U); + pfc_reg_write(PFC_IPSR13, 0x00000000U); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, 0x0000001FU); + pfc_reg_write(PFC_GPSR1, 0x3FFFFFFFU); + pfc_reg_write(PFC_GPSR2, 0xFFFFFFFFU); + pfc_reg_write(PFC_GPSR3, 0x000003FFU); + pfc_reg_write(PFC_GPSR4, 0xFC7F0F7EU); + pfc_reg_write(PFC_GPSR5, 0x001BFFFBU); + pfc_reg_write(PFC_GPSR6, 0x00003FFFU); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, 0xC00FFFFFU); + pfc_reg_write(PFC_POCCTRL2, 0XFFFFFFFEU); + pfc_reg_write(PFC_TDSELCTRL0, 0x00000000U); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x0047C1A2U); + pfc_reg_write(PFC_PUD1, 0x4E13ABFFU); + pfc_reg_write(PFC_PUD2, 0xFFFFFFFFU); + pfc_reg_write(PFC_PUD3, 0xFF0FFFFFU); + pfc_reg_write(PFC_PUD4, 0xE0000000U); + pfc_reg_write(PFC_PUD5, 0x60000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000000U); + pfc_reg_write(PFC_PUEN1, 0x00000000U); + pfc_reg_write(PFC_PUEN2, 0x00000000U); + pfc_reg_write(PFC_PUEN3, 0x000F008CU); + pfc_reg_write(PFC_PUEN4, 0x00000000U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00802000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h new file mode 100644 index 0000000..b7b1754 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_D3_H +#define PFC_INIT_D3_H + +void pfc_init_d3(void); + +#endif /* PFC_INIT_D3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c new file mode 100644 index 0000000..bd0048e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c @@ -0,0 +1,651 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_e3.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_SDA4 BIT(17) +#define GPSR0_SCL4 BIT(16) +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_WE0 BIT(22) +#define GPSR1_CS0 BIT(21) +#define GPSR1_CLKOUT BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_BIT27_REVERSED BIT(27) +#define GPSR2_BIT26_REVERSED BIT(26) +#define GPSR2_EX_WAIT0 BIT(25) +#define GPSR2_RD_WR BIT(24) +#define GPSR2_RD BIT(23) +#define GPSR2_BS BIT(22) +#define GPSR2_AVB_PHY_INT BIT(21) +#define GPSR2_AVB_TXCREFCLK BIT(20) +#define GPSR2_AVB_RD3 BIT(19) +#define GPSR2_AVB_RD2 BIT(18) +#define GPSR2_AVB_RD1 BIT(17) +#define GPSR2_AVB_RD0 BIT(16) +#define GPSR2_AVB_RXC BIT(15) +#define GPSR2_AVB_RX_CTL BIT(14) +#define GPSR2_RPC_RESET BIT(13) +#define GPSR2_RPC_RPC_INT BIT(12) +#define GPSR2_QSPI1_SSL BIT(11) +#define GPSR2_QSPI1_IO3 BIT(10) +#define GPSR2_QSPI1_IO2 BIT(9) +#define GPSR2_QSPI1_MISO_IO1 BIT(8) +#define GPSR2_QSPI1_MOSI_IO0 BIT(7) +#define GPSR2_QSPI1_SPCLK BIT(6) +#define GPSR2_QSPI0_SSL BIT(5) +#define GPSR2_QSPI0_IO3 BIT(4) +#define GPSR2_QSPI0_IO2 BIT(3) +#define GPSR2_QSPI0_MISO_IO1 BIT(2) +#define GPSR2_QSPI0_MOSI_IO0 BIT(1) +#define GPSR2_QSPI0_SPCLK BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(10) +#define GPSR4_SD3_DAT7 BIT(9) +#define GPSR4_SD3_DAT6 BIT(8) +#define GPSR4_SD3_DAT5 BIT(7) +#define GPSR4_SD3_DAT4 BIT(6) +#define GPSR4_SD3_DAT3 BIT(5) +#define GPSR4_SD3_DAT2 BIT(4) +#define GPSR4_SD3_DAT1 BIT(3) +#define GPSR4_SD3_DAT0 BIT(2) +#define GPSR4_SD3_CMD BIT(1) +#define GPSR4_SD3_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(19) +#define GPSR5_MLB_SIG BIT(18) +#define GPSR5_MLB_CLK BIT(17) +#define GPSR5_SSI_SDATA9 BIT(16) +#define GPSR5_MSIOF0_SS2 BIT(15) +#define GPSR5_MSIOF0_SS1 BIT(14) +#define GPSR5_MSIOF0_SYNC BIT(13) +#define GPSR5_MSIOF0_TXD BIT(12) +#define GPSR5_MSIOF0_RXD BIT(11) +#define GPSR5_MSIOF0_SCK BIT(10) +#define GPSR5_RX2_A BIT(9) +#define GPSR5_TX2_A BIT(8) +#define GPSR5_SCK2_A BIT(7) +#define GPSR5_TX1 BIT(6) +#define GPSR5_RX1 BIT(5) +#define GPSR5_RTS0_A BIT(4) +#define GPSR5_CTS0_A BIT(3) +#define GPSR5_TX0_A BIT(2) +#define GPSR5_RX0_A BIT(1) +#define GPSR5_SCK0_A BIT(0) +#define GPSR6_USB30_PWEN BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_USB30_OVC BIT(9) +#define GPSR6_AUDIO_CLKA BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS349 BIT(6) +#define GPSR6_SSI_SCK349 BIT(5) +#define GPSR6_SSI_SDATA2 BIT(4) +#define GPSR6_SSI_SDATA1 BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS01239 BIT(1) +#define GPSR6_SSI_SCK01239 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POCCTRL0_MASK (0x0007F000U) +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define POCCTRL2_MASK (0xFFFFFFFEU) +#define POC2_VREF_33V BIT(0) + +#define MOD_SEL0_ADGB_A ((uint32_t)0U << 29U) +#define MOD_SEL0_ADGB_B ((uint32_t)1U << 29U) +#define MOD_SEL0_ADGB_C ((uint32_t)2U << 29U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 28U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 28U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 26U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 26U) +#define MOD_SEL0_FM_C ((uint32_t)2U << 26U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 25U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 25U) +#define MOD_SEL0_HSCIF0_A ((uint32_t)0U << 24U) +#define MOD_SEL0_HSCIF0_B ((uint32_t)1U << 24U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 23U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 23U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 22U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C1_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C1_D ((uint32_t)3U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 17U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 17U) +#define MOD_SEL0_I2C2_C ((uint32_t)2U << 17U) +#define MOD_SEL0_I2C2_D ((uint32_t)3U << 17U) +#define MOD_SEL0_I2C2_E ((uint32_t)4U << 17U) +#define MOD_SEL0_NDFC_A ((uint32_t)0U << 16U) +#define MOD_SEL0_NDFC_B ((uint32_t)1U << 16U) +#define MOD_SEL0_PWM0_A ((uint32_t)0U << 15U) +#define MOD_SEL0_PWM0_B ((uint32_t)1U << 15U) +#define MOD_SEL0_PWM1_A ((uint32_t)0U << 14U) +#define MOD_SEL0_PWM1_B ((uint32_t)1U << 14U) +#define MOD_SEL0_PWM2_A ((uint32_t)0U << 12U) +#define MOD_SEL0_PWM2_B ((uint32_t)1U << 12U) +#define MOD_SEL0_PWM2_C ((uint32_t)2U << 12U) +#define MOD_SEL0_PWM3_A ((uint32_t)0U << 10U) +#define MOD_SEL0_PWM3_B ((uint32_t)1U << 10U) +#define MOD_SEL0_PWM3_C ((uint32_t)2U << 10U) +#define MOD_SEL0_PWM4_A ((uint32_t)0U << 9U) +#define MOD_SEL0_PWM4_B ((uint32_t)1U << 9U) +#define MOD_SEL0_PWM5_A ((uint32_t)0U << 8U) +#define MOD_SEL0_PWM5_B ((uint32_t)1U << 8U) +#define MOD_SEL0_PWM6_A ((uint32_t)0U << 7U) +#define MOD_SEL0_PWM6_B ((uint32_t)1U << 7U) +#define MOD_SEL0_REMOCON_A ((uint32_t)0U << 5U) +#define MOD_SEL0_REMOCON_B ((uint32_t)1U << 5U) +#define MOD_SEL0_REMOCON_C ((uint32_t)2U << 5U) +#define MOD_SEL0_SCIF_A ((uint32_t)0U << 4U) +#define MOD_SEL0_SCIF_B ((uint32_t)1U << 4U) +#define MOD_SEL0_SCIF0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_SCIF0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_SCIF2_A ((uint32_t)0U << 2U) +#define MOD_SEL0_SCIF2_B ((uint32_t)1U << 2U) +#define MOD_SEL0_SPEED_PULSE_IF_A ((uint32_t)0U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_B ((uint32_t)1U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_C ((uint32_t)2U << 0U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 31U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 31U) +#define MOD_SEL1_SSI2_A ((uint32_t)0U << 30U) +#define MOD_SEL1_SSI2_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 29U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 29U) +#define MOD_SEL1_USB20_CH0_A ((uint32_t)0U << 28U) +#define MOD_SEL1_USB20_CH0_B ((uint32_t)1U << 28U) +#define MOD_SEL1_DRIF2_A ((uint32_t)0U << 26U) +#define MOD_SEL1_DRIF2_B ((uint32_t)1U << 26U) +#define MOD_SEL1_DRIF3_A ((uint32_t)0U << 25U) +#define MOD_SEL1_DRIF3_B ((uint32_t)1U << 25U) +#define MOD_SEL1_HSCIF3_A ((uint32_t)0U << 22U) +#define MOD_SEL1_HSCIF3_B ((uint32_t)1U << 22U) +#define MOD_SEL1_HSCIF3_C ((uint32_t)2U << 22U) +#define MOD_SEL1_HSCIF3_D ((uint32_t)3U << 22U) +#define MOD_SEL1_HSCIF3_E ((uint32_t)4U << 22U) +#define MOD_SEL1_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL1_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL1_HSCIF4_C ((uint32_t)2U << 19U) +#define MOD_SEL1_HSCIF4_D ((uint32_t)3U << 19U) +#define MOD_SEL1_HSCIF4_E ((uint32_t)4U << 19U) +#define MOD_SEL1_I2C6_A ((uint32_t)0U << 18U) +#define MOD_SEL1_I2C6_B ((uint32_t)1U << 18U) +#define MOD_SEL1_I2C7_A ((uint32_t)0U << 17U) +#define MOD_SEL1_I2C7_B ((uint32_t)1U << 17U) +#define MOD_SEL1_MSIOF2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_MSIOF2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_MSIOF3_A ((uint32_t)0U << 15U) +#define MOD_SEL1_MSIOF3_B ((uint32_t)1U << 15U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF3_C ((uint32_t)2U << 13U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 11U) +#define MOD_SEL1_SCIF5_A ((uint32_t)0U << 9U) +#define MOD_SEL1_SCIF5_B ((uint32_t)1U << 9U) +#define MOD_SEL1_SCIF5_C ((uint32_t)2U << 9U) +#define MOD_SEL1_VIN4_A ((uint32_t)0U << 8U) +#define MOD_SEL1_VIN4_B ((uint32_t)1U << 8U) +#define MOD_SEL1_VIN5_A ((uint32_t)0U << 7U) +#define MOD_SEL1_VIN5_B ((uint32_t)1U << 7U) +#define MOD_SEL1_ADGC_A ((uint32_t)0U << 5U) +#define MOD_SEL1_ADGC_B ((uint32_t)1U << 5U) +#define MOD_SEL1_ADGC_C ((uint32_t)2U << 5U) +#define MOD_SEL1_SSI9_A ((uint32_t)0U << 4U) +#define MOD_SEL1_SSI9_B ((uint32_t)1U << 4U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_e3(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_ADGB_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_FM_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF0_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_NDFC_A + | MOD_SEL0_PWM0_A + | MOD_SEL0_PWM1_A + | MOD_SEL0_PWM2_A + | MOD_SEL0_PWM3_A + | MOD_SEL0_PWM4_A + | MOD_SEL0_PWM5_A + | MOD_SEL0_PWM6_A + | MOD_SEL0_REMOCON_A + | MOD_SEL0_SCIF_A + | MOD_SEL0_SCIF0_A + | MOD_SEL0_SCIF2_A + | MOD_SEL0_SPEED_PULSE_IF_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_SIMCARD_A + | MOD_SEL1_SSI2_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_USB20_CH0_B + | MOD_SEL1_DRIF2_A + | MOD_SEL1_DRIF3_A + | MOD_SEL1_HSCIF3_A + | MOD_SEL1_HSCIF4_A + | MOD_SEL1_I2C6_A + | MOD_SEL1_I2C7_A + | MOD_SEL1_MSIOF2_A + | MOD_SEL1_MSIOF3_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF5_A + | MOD_SEL1_VIN4_A + | MOD_SEL1_VIN5_A + | MOD_SEL1_ADGC_A + | MOD_SEL1_SSI9_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) /* QSPI1_MISO/IO1 */ + | IPSR_24_FUNC(0) /* QSPI1_MOSI/IO0 */ + | IPSR_20_FUNC(0) /* QSPI1_SPCLK */ + | IPSR_16_FUNC(0) /* QSPI0_IO3 */ + | IPSR_12_FUNC(0) /* QSPI0_IO2 */ + | IPSR_8_FUNC(0) /* QSPI0_MISO/IO1 */ + | IPSR_4_FUNC(0) /* QSPI0_MOSI/IO0 */ + | IPSR_0_FUNC(0)); /* QSPI0_SPCLK */ + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(0) /* AVB_RD2 */ + | IPSR_24_FUNC(0) /* AVB_RD1 */ + | IPSR_20_FUNC(0) /* AVB_RD0 */ + | IPSR_16_FUNC(0) /* RPC_RESET# */ + | IPSR_12_FUNC(0) /* RPC_INT# */ + | IPSR_8_FUNC(0) /* QSPI1_SSL */ + | IPSR_4_FUNC(0) /* QSPI1_IO3 */ + | IPSR_0_FUNC(0)); /* QSPI1_IO2 */ + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(1) /* IRQ0 */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(2) /* AVB_LINK */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) /* AVB_MDC */ + | IPSR_4_FUNC(0) /* AVB_MDIO */ + | IPSR_0_FUNC(0)); /* AVB_TXCREFCLK */ + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(5) /* DU_HSYNC */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(5) /* DU_DG4 */ + | IPSR_8_FUNC(5) /* DU_DOTCLKOUT0 */ + | IPSR_4_FUNC(5) /* DU_DISP */ + | IPSR_0_FUNC(1)); /* IRQ1 */ + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(5) /* DU_DB5 */ + | IPSR_24_FUNC(5) /* DU_DB4 */ + | IPSR_20_FUNC(5) /* DU_DB3 */ + | IPSR_16_FUNC(5) /* DU_DB2 */ + | IPSR_12_FUNC(5) /* DU_DG6 */ + | IPSR_8_FUNC(5) /* DU_VSYNC */ + | IPSR_4_FUNC(5) /* DU_DG5 */ + | IPSR_0_FUNC(5)); /* DU_DG7 */ + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(5) /* DU_DR3 */ + | IPSR_24_FUNC(5) /* DU_DB7 */ + | IPSR_20_FUNC(5) /* DU_DR2 */ + | IPSR_16_FUNC(5) /* DU_DR1 */ + | IPSR_12_FUNC(5) /* DU_DR0 */ + | IPSR_8_FUNC(5) /* DU_DB1 */ + | IPSR_4_FUNC(5) /* DU_DB0 */ + | IPSR_0_FUNC(5)); /* DU_DB6 */ + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(5) /* DU_DG1 */ + | IPSR_24_FUNC(5) /* DU_DG0 */ + | IPSR_20_FUNC(5) /* DU_DR7 */ + | IPSR_16_FUNC(2) /* IRQ5 */ + | IPSR_12_FUNC(5) /* DU_DR6 */ + | IPSR_8_FUNC(5) /* DU_DR5 */ + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(5)); /* DU_DR4 */ + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) /* SD0_CLK */ + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(5) /* DU_DOTCLKIN0 */ + | IPSR_16_FUNC(5) /* DU_DG3 */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(5)); /* DU_DG2 */ + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(0) /* SD1_DAT0 */ + | IPSR_24_FUNC(0) /* SD1_CMD */ + | IPSR_20_FUNC(0) /* SD1_CLK */ + | IPSR_16_FUNC(0) /* SD0_DAT3 */ + | IPSR_12_FUNC(0) /* SD0_DAT2 */ + | IPSR_8_FUNC(0) /* SD0_DAT1 */ + | IPSR_4_FUNC(0) /* SD0_DAT0 */ + | IPSR_0_FUNC(0)); /* SD0_CMD */ + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) /* SD3_DAT2 */ + | IPSR_24_FUNC(0) /* SD3_DAT1 */ + | IPSR_20_FUNC(0) /* SD3_DAT0 */ + | IPSR_16_FUNC(0) /* SD3_CMD */ + | IPSR_12_FUNC(0) /* SD3_CLK */ + | IPSR_8_FUNC(0) /* SD1_DAT3 */ + | IPSR_4_FUNC(0) /* SD1_DAT2 */ + | IPSR_0_FUNC(0)); /* SD1_DAT1 */ + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) /* SD0_WP */ + | IPSR_24_FUNC(0) /* SD0_CD */ + | IPSR_20_FUNC(0) /* SD3_DS */ + | IPSR_16_FUNC(0) /* SD3_DAT7 */ + | IPSR_12_FUNC(0) /* SD3_DAT6 */ + | IPSR_8_FUNC(0) /* SD3_DAT5 */ + | IPSR_4_FUNC(0) /* SD3_DAT4 */ + | IPSR_0_FUNC(0)); /* SD3_DAT3 */ + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(2) /* AUDIO_CLKOUT1_A */ + | IPSR_16_FUNC(2) /* AUDIO_CLKOUT_A */ + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) /* SD1_WP */ + | IPSR_0_FUNC(0)); /* SD1_CD */ + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) /* RX2_A */ + | IPSR_8_FUNC(0) /* TX2_A */ + | IPSR_4_FUNC(2) /* AUDIO_CLKB_A */ + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(2) /* AUDIO_CLKC_A */ + | IPSR_4_FUNC(1) /* HTX2_A */ + | IPSR_0_FUNC(1)); /* HRX2_A */ + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(3) /* USB0_PWEN_B */ + | IPSR_24_FUNC(0) /* SSI_SDATA4 */ + | IPSR_20_FUNC(0) /* SSI_SDATA3 */ + | IPSR_16_FUNC(0) /* SSI_WS349 */ + | IPSR_12_FUNC(0) /* SSI_SCK349 */ + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) /* SSI_SDATA1 */ + | IPSR_0_FUNC(0)); /* SSI_SDATA0 */ + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) /* USB30_OVC */ + | IPSR_24_FUNC(0) /* USB30_PWEN */ + | IPSR_20_FUNC(0) /* AUDIO_CLKA */ + | IPSR_16_FUNC(1) /* HRTS2#_A */ + | IPSR_12_FUNC(1) /* HCTS2#_A */ + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(3)); /* USB0_OVC_B */ + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_SCL4 + | GPSR0_D15 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8 + | GPSR0_D7 + | GPSR0_D6 + | GPSR0_D5 + | GPSR0_D3 + | GPSR0_D2 + | GPSR0_D1 + | GPSR0_D0); + pfc_reg_write(PFC_GPSR1, GPSR1_WE0 + | GPSR1_CS0 + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A11 + | GPSR1_A10 + | GPSR1_A9 + | GPSR1_A8 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_BIT27_REVERSED + | GPSR2_BIT26_REVERSED + | GPSR2_RD + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_TXCREFCLK + | GPSR2_AVB_RD3 + | GPSR2_AVB_RD2 + | GPSR2_AVB_RD1 + | GPSR2_AVB_RD0 + | GPSR2_AVB_RXC + | GPSR2_AVB_RX_CTL + | GPSR2_RPC_RESET + | GPSR2_RPC_RPC_INT + | GPSR2_QSPI1_SSL + | GPSR2_QSPI1_IO3 + | GPSR2_QSPI1_IO2 + | GPSR2_QSPI1_MISO_IO1 + | GPSR2_QSPI1_MOSI_IO0 + | GPSR2_QSPI1_SPCLK + | GPSR2_QSPI0_SSL + | GPSR2_QSPI0_IO3 + | GPSR2_QSPI0_IO2 + | GPSR2_QSPI0_MISO_IO1 + | GPSR2_QSPI0_MOSI_IO0 + | GPSR2_QSPI0_SPCLK); + pfc_reg_write(PFC_GPSR3, GPSR3_SD1_WP + | GPSR3_SD1_CD + | GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD1_CMD + | GPSR3_SD1_CLK + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DS + | GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT5 + | GPSR4_SD3_DAT4 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_SSI_SDATA9 + | GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2_A + | GPSR5_RTS0_A + | GPSR5_CTS0_A); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_PWEN + | GPSR6_SSI_SDATA6 + | GPSR6_SSI_WS6 + | GPSR6_SSI_WS5 + | GPSR6_SSI_SCK5 + | GPSR6_SSI_SDATA4 + | GPSR6_USB30_OVC + | GPSR6_AUDIO_CLKA + | GPSR6_SSI_SDATA3 + | GPSR6_SSI_WS349 + | GPSR6_SSI_SCK349 + | GPSR6_SSI_SDATA1 + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS01239 + | GPSR6_SSI_SCK01239); + + /* initialize POC control */ + reg = mmio_read_32(PFC_POCCTRL0); + reg = ((reg & POCCTRL0_MASK) | POC_SD1_DAT3_33V + | POC_SD1_DAT2_33V + | POC_SD1_DAT1_33V + | POC_SD1_DAT0_33V + | POC_SD1_CMD_33V + | POC_SD1_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + pfc_reg_write(PFC_POCCTRL0, reg); + reg = mmio_read_32(PFC_POCCTRL2); + reg = (reg & POCCTRL2_MASK); + pfc_reg_write(PFC_POCCTRL2, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0xFDF80000U); + pfc_reg_write(PFC_PUD1, 0xCE298464U); + pfc_reg_write(PFC_PUD2, 0xA4C380F4U); + pfc_reg_write(PFC_PUD3, 0x0000079FU); + pfc_reg_write(PFC_PUD4, 0xFFF0FFFFU); + pfc_reg_write(PFC_PUD5, 0x40000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0xFFF00000U); + pfc_reg_write(PFC_PUEN1, 0x00000000U); + pfc_reg_write(PFC_PUEN2, 0x00000004U); + pfc_reg_write(PFC_PUEN3, 0x00000000U); + pfc_reg_write(PFC_PUEN4, 0x07800010U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00020000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000010U); + mmio_write_32(GPIO_OUTDT1, 0x00100000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00008000U); + mmio_write_32(GPIO_OUTDT5, 0x00060000U); + mmio_write_32(GPIO_OUTDT6, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000010U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100020U); + mmio_write_32(GPIO_INOUTSEL2, 0x03000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00008000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00060000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00004000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h new file mode 100644 index 0000000..647a937 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_E3_H +#define PFC_INIT_E3_H + +void pfc_init_e3(void); + +#endif /* PFC_INIT_E3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c new file mode 100644 index 0000000..effdc76 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c @@ -0,0 +1,1183 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C6_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C6_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C6_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 19U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 19U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 18U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 18U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 15U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 15U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 14U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 14U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 13U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 12U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 12U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 11U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 11U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 10U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 9U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 9U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 6U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 4U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 4U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 4U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A ((uint32_t)0U << 1U) +#define MOD_SEL0_ADG_B ((uint32_t)1U << 1U) +#define MOD_SEL0_ADG_C ((uint32_t)2U << 1U) +#define MOD_SEL0_ADG_D ((uint32_t)3U << 1U) +#define MOD_SEL0_5LINE_A ((uint32_t)0U << 0U) +#define MOD_SEL0_5LINE_B ((uint32_t)1U << 0U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_h3_v1(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C6_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FM_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A + | MOD_SEL0_5LINE_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(2) + | DRVCTRL13_SD0_CMD(2) + | DRVCTRL13_SD0_DAT0(2) + | DRVCTRL13_SD0_DAT1(2) + | DRVCTRL13_SD0_DAT2(2) + | DRVCTRL13_SD0_DAT3(2)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(2) + | DRVCTRL15_SD3_CMD(2) + | DRVCTRL15_SD3_DAT0(2)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(2) + | DRVCTRL16_SD3_DAT2(2) + | DRVCTRL16_SD3_DAT3(2) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h new file mode 100644 index 0000000..2478e1c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_H3_V1_H +#define PFC_INIT_H3_V1_H + +void pfc_init_h3_v1(void); + +#endif /* PFC_INIT_H3_V1_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c new file mode 100644 index 0000000..a54b14b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c @@ -0,0 +1,1216 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_h3_v2.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_h3_v2(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h new file mode 100644 index 0000000..b02f93e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_H3_V2_H +#define PFC_INIT_H3_V2_H + +void pfc_init_h3_v2(void); + +#endif /* PFC_INIT_H3_V2_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c new file mode 100644 index 0000000..7684c62 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c @@ -0,0 +1,1311 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_m3.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_SCMSTPCR0 (CPG_BASE + 0x0B20U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define SCMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + reg &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == (PRR_PRODUCT_M3_CUT10)) { + /* Enable clock supply to RTDMAC. */ + mstpcr_write(CPG_SCMSTPCR0, CPG_MSTPSR0, SCMSTPCR0_RTDMAC); + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); + } +} + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + uint32_t prr; + + prr = mmio_read_32(RCAR_PRR); + prr &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + mmio_write_32(PFC_PMMR, ~data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } + mmio_write_32((uintptr_t)addr, data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } +} + +void pfc_init_m3(void) +{ + uint32_t reg; + + /* Work around for PFC eratta */ + start_rtdma0_descriptor(); + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h new file mode 100644 index 0000000..70885de --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_M3_H +#define PFC_INIT_M3_H + +void pfc_init_m3(void); + +#endif /* PFC_INIT_M3_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c new file mode 100644 index 0000000..5014556 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c @@ -0,0 +1,1218 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_m3n.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_m3n(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_A + | MOD_SEL2_I2C_3_A + | MOD_SEL2_I2C_0_A + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(1) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(1)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ5 + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_WP + | GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DS + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_SS2 + | GPSR5_MSIOF0_SS1 + | GPSR5_MSIOF0_SYNC + | GPSR5_HRTS0 + | GPSR5_HCTS0 + | GPSR5_HTX0 + | GPSR5_HRX0 + | GPSR5_HSCK0 + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_SCK2 + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_USB30_OVC + | GPSR6_USB30_PWEN + | GPSR6_USB1_OVC + | GPSR6_USB1_PWEN + | GPSR6_USB0_OVC + | GPSR6_USB0_PWEN + | GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_SDATA8 + | GPSR6_SSI_SDATA7 + | GPSR6_SSI_WS78 + | GPSR6_SSI_SCK78 + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD3_DS_33V + | POC_SD3_DAT7_33V + | POC_SD3_DAT6_33V + | POC_SD3_DAT5_33V + | POC_SD3_DAT4_33V + | POC_SD3_DAT3_33V + | POC_SD3_DAT2_33V + | POC_SD3_DAT1_33V + | POC_SD3_DAT0_33V + | POC_SD3_CMD_33V + | POC_SD3_CLK_33V + | POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300FFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x0000C000U); + mmio_write_32(GPIO_OUTDT5, 0x00000006U); + mmio_write_32(GPIO_OUTDT6, 0x00003880U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x01000A00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000400U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000C000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); +#if (RCAR_GEN3_ULCB == 1) + mmio_write_32(GPIO_INOUTSEL5, 0x0000000EU); +#else + mmio_write_32(GPIO_INOUTSEL5, 0x0000020EU); +#endif + mmio_write_32(GPIO_INOUTSEL6, 0x00013880U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h new file mode 100644 index 0000000..3e6f879 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_M3N_H +#define PFC_INIT_M3N_H + +void pfc_init_m3n(void); + +#endif /* PFC_INIT_M3N_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c new file mode 100644 index 0000000..6063758 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c @@ -0,0 +1,906 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ +#include +#include "pfc_init_v3m.h" +#include "include/rcar_def.h" +#include "rcar_private.h" +#include "../pfc_regs.h" + +/* Pin functon bit */ +#define GPSR0_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define GPSR0_DU_EXVSYNC_DU_VSYNC BIT(20) +#define GPSR0_DU_EXHSYNC_DU_HSYNC BIT(19) +#define GPSR0_DU_DOTCLKOUT BIT(18) +#define GPSR0_DU_DB7 BIT(17) +#define GPSR0_DU_DB6 BIT(16) +#define GPSR0_DU_DB5 BIT(15) +#define GPSR0_DU_DB4 BIT(14) +#define GPSR0_DU_DB3 BIT(13) +#define GPSR0_DU_DB2 BIT(12) +#define GPSR0_DU_DG7 BIT(11) +#define GPSR0_DU_DG6 BIT(10) +#define GPSR0_DU_DG5 BIT(9) +#define GPSR0_DU_DG4 BIT(8) +#define GPSR0_DU_DG3 BIT(7) +#define GPSR0_DU_DG2 BIT(6) +#define GPSR0_DU_DR7 BIT(5) +#define GPSR0_DU_DR6 BIT(4) +#define GPSR0_DU_DR5 BIT(3) +#define GPSR0_DU_DR4 BIT(2) +#define GPSR0_DU_DR3 BIT(1) +#define GPSR0_DU_DR2 BIT(0) + +#define GPSR1_DIGRF_CLKOUT BIT(27) +#define GPSR1_DIGRF_CLKIN BIT(26) +#define GPSR1_CANFD_CLK BIT(25) +#define GPSR1_CANFD1_RX BIT(24) +#define GPSR1_CANFD1_TX BIT(23) +#define GPSR1_CANFD0_RX BIT(22) +#define GPSR1_CANFD0_TX BIT(21) +#define GPSR1_AVB0_AVTP_CAPTURE BIT(20) +#define GPSR1_AVB0_AVTP_MATCH BIT(19) +#define GPSR1_AVB0_LINK BIT(18) +#define GPSR1_AVB0_PHY_INT BIT(17) +#define GPSR1_AVB0_MAGIC BIT(16) +#define GPSR1_AVB0_MDC BIT(15) +#define GPSR1_AVB0_MDIO BIT(14) +#define GPSR1_AVB0_TXCREFCLK BIT(13) +#define GPSR1_AVB0_TD3 BIT(12) +#define GPSR1_AVB0_TD2 BIT(11) +#define GPSR1_AVB0_TD1 BIT(10) +#define GPSR1_AVB0_TD0 BIT(9) +#define GPSR1_AVB0_TXC BIT(8) +#define GPSR1_AVB0_TX_CTL BIT(7) +#define GPSR1_AVB0_RD3 BIT(6) +#define GPSR1_AVB0_RD2 BIT(5) +#define GPSR1_AVB0_RD1 BIT(4) +#define GPSR1_AVB0_RD0 BIT(3) +#define GPSR1_AVB0_RXC BIT(2) +#define GPSR1_AVB0_RX_CTL BIT(1) +#define GPSR1_IRQ0 BIT(0) + +#define GPSR2_VI0_FIELD BIT(16) +#define GPSR2_VI0_DATA11 BIT(15) +#define GPSR2_VI0_DATA10 BIT(14) +#define GPSR2_VI0_DATA9 BIT(13) +#define GPSR2_VI0_DATA8 BIT(12) +#define GPSR2_VI0_DATA7 BIT(11) +#define GPSR2_VI0_DATA6 BIT(10) +#define GPSR2_VI0_DATA5 BIT(9) +#define GPSR2_VI0_DATA4 BIT(8) +#define GPSR2_VI0_DATA3 BIT(7) +#define GPSR2_VI0_DATA2 BIT(6) +#define GPSR2_VI0_DATA1 BIT(5) +#define GPSR2_VI0_DATA0 BIT(4) +#define GPSR2_VI0_VSYNC_N BIT(3) +#define GPSR2_VI0_HSYNC_N BIT(2) +#define GPSR2_VI0_CLKENB BIT(1) +#define GPSR2_VI0_CLK BIT(0) + +#define GPSR3_VI1_FIELD BIT(16) +#define GPSR3_VI1_DATA11 BIT(15) +#define GPSR3_VI1_DATA10 BIT(14) +#define GPSR3_VI1_DATA9 BIT(13) +#define GPSR3_VI1_DATA8 BIT(12) +#define GPSR3_VI1_DATA7 BIT(11) +#define GPSR3_VI1_DATA6 BIT(10) +#define GPSR3_VI1_DATA5 BIT(9) +#define GPSR3_VI1_DATA4 BIT(8) +#define GPSR3_VI1_DATA3 BIT(7) +#define GPSR3_VI1_DATA2 BIT(6) +#define GPSR3_VI1_DATA1 BIT(5) +#define GPSR3_VI1_DATA0 BIT(4) +#define GPSR3_VI1_VSYNC_N BIT(3) +#define GPSR3_VI1_HSYNC_N BIT(2) +#define GPSR3_VI1_CLKENB BIT(1) +#define GPSR3_VI1_CLK BIT(0) + +#define GPSR4_SDA2 BIT(5) +#define GPSR4_SCL2 BIT(4) +#define GPSR4_SDA1 BIT(3) +#define GPSR4_SCL1 BIT(2) +#define GPSR4_SDA0 BIT(1) +#define GPSR4_SCL0 BIT(0) + +#define GPSR5_RPC_INT_N BIT(14) +#define GPSR5_RPC_WP_N BIT(13) +#define GPSR5_RPC_RESET_N BIT(12) +#define GPSR5_QSPI1_SSL BIT(11) +#define GPSR5_QSPI1_IO3 BIT(10) +#define GPSR5_QSPI1_IO2 BIT(9) +#define GPSR5_QSPI1_MISO_IO1 BIT(8) +#define GPSR5_QSPI1_MOSI_IO0 BIT(7) +#define GPSR5_QSPI1_SPCLK BIT(6) +#define GPSR5_QSPI0_SSL BIT(5) +#define GPSR5_QSPI0_IO3 BIT(4) +#define GPSR5_QSPI0_IO2 BIT(3) +#define GPSR5_QSPI0_MISO_IO1 BIT(2) +#define GPSR5_QSPI0_MOSI_IO0 BIT(1) +#define GPSR5_QSPI0_SPCLK BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define IOCTRL30_POC_VI0_DATA5 BIT(31) +#define IOCTRL30_POC_VI0_DATA4 BIT(30) +#define IOCTRL30_POC_VI0_DATA3 BIT(29) +#define IOCTRL30_POC_VI0_DATA2 BIT(28) +#define IOCTRL30_POC_VI0_DATA1 BIT(27) +#define IOCTRL30_POC_VI0_DATA0 BIT(26) +#define IOCTRL30_POC_VI0_VSYNC_N BIT(25) +#define IOCTRL30_POC_VI0_HSYNC_N BIT(24) +#define IOCTRL30_POC_VI0_CLKENB BIT(23) +#define IOCTRL30_POC_VI0_CLK BIT(22) +#define IOCTRL30_POC_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define IOCTRL30_POC_DU_EXVSYNC_DU_VSYNC BIT(20) +#define IOCTRL30_POC_DU_EXHSYNC_DU_HSYNC BIT(19) +#define IOCTRL30_POC_DU_DOTCLKOUT BIT(18) +#define IOCTRL30_POC_DU_DB7 BIT(17) +#define IOCTRL30_POC_DU_DB6 BIT(16) +#define IOCTRL30_POC_DU_DB5 BIT(15) +#define IOCTRL30_POC_DU_DB4 BIT(14) +#define IOCTRL30_POC_DU_DB3 BIT(13) +#define IOCTRL30_POC_DU_DB2 BIT(12) +#define IOCTRL30_POC_DU_DG7 BIT(11) +#define IOCTRL30_POC_DU_DG6 BIT(10) +#define IOCTRL30_POC_DU_DG5 BIT(9) +#define IOCTRL30_POC_DU_DG4 BIT(8) +#define IOCTRL30_POC_DU_DG3 BIT(7) +#define IOCTRL30_POC_DU_DG2 BIT(6) +#define IOCTRL30_POC_DU_DR7 BIT(5) +#define IOCTRL30_POC_DU_DR6 BIT(4) +#define IOCTRL30_POC_DU_DR5 BIT(3) +#define IOCTRL30_POC_DU_DR4 BIT(2) +#define IOCTRL30_POC_DU_DR3 BIT(1) +#define IOCTRL30_POC_DU_DR2 BIT(0) + +#define IOCTRL31_POC_DUMMY_31 BIT(31) +#define IOCTRL31_POC_DUMMY_30 BIT(30) +#define IOCTRL31_POC_DUMMY_29 BIT(29) +#define IOCTRL31_POC_DUMMY_28 BIT(28) +#define IOCTRL31_POC_DUMMY_27 BIT(27) +#define IOCTRL31_POC_DUMMY_26 BIT(26) +#define IOCTRL31_POC_DUMMY_25 BIT(25) +#define IOCTRL31_POC_DUMMY_24 BIT(24) +#define IOCTRL31_POC_VI1_FIELD BIT(23) +#define IOCTRL31_POC_VI1_DATA11 BIT(22) +#define IOCTRL31_POC_VI1_DATA10 BIT(21) +#define IOCTRL31_POC_VI1_DATA9 BIT(20) +#define IOCTRL31_POC_VI1_DATA8 BIT(19) +#define IOCTRL31_POC_VI1_DATA7 BIT(18) +#define IOCTRL31_POC_VI1_DATA6 BIT(17) +#define IOCTRL31_POC_VI1_DATA5 BIT(16) +#define IOCTRL31_POC_VI1_DATA4 BIT(15) +#define IOCTRL31_POC_VI1_DATA3 BIT(14) +#define IOCTRL31_POC_VI1_DATA2 BIT(13) +#define IOCTRL31_POC_VI1_DATA1 BIT(12) +#define IOCTRL31_POC_VI1_DATA0 BIT(11) +#define IOCTRL31_POC_VI1_VSYNC_N BIT(10) +#define IOCTRL31_POC_VI1_HSYNC_N BIT(9) +#define IOCTRL31_POC_VI1_CLKENB BIT(8) +#define IOCTRL31_POC_VI1_CLK BIT(7) +#define IOCTRL31_POC_VI0_FIELD BIT(6) +#define IOCTRL31_POC_VI0_DATA11 BIT(5) +#define IOCTRL31_POC_VI0_DATA10 BIT(4) +#define IOCTRL31_POC_VI0_DATA9 BIT(3) +#define IOCTRL31_POC_VI0_DATA8 BIT(2) +#define IOCTRL31_POC_VI0_DATA7 BIT(1) +#define IOCTRL31_POC_VI0_DATA6 BIT(0) +#define IOCTRL32_POC2_VREF BIT(0) +#define IOCTRL40_SD0TDSEL1 BIT(1) +#define IOCTRL40_SD0TDSEL0 BIT(0) + +#define PUEN0_PUEN_VI0_CLK BIT(31) +#define PUEN0_PUEN_TDI BIT(30) +#define PUEN0_PUEN_TMS BIT(29) +#define PUEN0_PUEN_TCK BIT(28) +#define PUEN0_PUEN_TRST_N BIT(27) +#define PUEN0_PUEN_IRQ0 BIT(26) +#define PUEN0_PUEN_FSCLKST_N BIT(25) +#define PUEN0_PUEN_EXTALR BIT(24) +#define PUEN0_PUEN_PRESETOUT_N BIT(23) +#define PUEN0_PUEN_DU_DOTCLKIN BIT(22) +#define PUEN0_PUEN_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define PUEN0_PUEN_DU_EXVSYNC_DU_VSYNC BIT(20) +#define PUEN0_PUEN_DU_EXHSYNC_DU_HSYNC BIT(19) +#define PUEN0_PUEN_DU_DOTCLKOUT BIT(18) +#define PUEN0_PUEN_DU_DB7 BIT(17) +#define PUEN0_PUEN_DU_DB6 BIT(16) +#define PUEN0_PUEN_DU_DB5 BIT(15) +#define PUEN0_PUEN_DU_DB4 BIT(14) +#define PUEN0_PUEN_DU_DB3 BIT(13) +#define PUEN0_PUEN_DU_DB2 BIT(12) +#define PUEN0_PUEN_DU_DG7 BIT(11) +#define PUEN0_PUEN_DU_DG6 BIT(10) +#define PUEN0_PUEN_DU_DG5 BIT(9) +#define PUEN0_PUEN_DU_DG4 BIT(8) +#define PUEN0_PUEN_DU_DG3 BIT(7) +#define PUEN0_PUEN_DU_DG2 BIT(6) +#define PUEN0_PUEN_DU_DR7 BIT(5) +#define PUEN0_PUEN_DU_DR6 BIT(4) +#define PUEN0_PUEN_DU_DR5 BIT(3) +#define PUEN0_PUEN_DU_DR4 BIT(2) +#define PUEN0_PUEN_DU_DR3 BIT(1) +#define PUEN0_PUEN_DU_DR2 BIT(0) + +#define PUEN1_PUEN_VI1_DATA11 BIT(31) +#define PUEN1_PUEN_VI1_DATA10 BIT(30) +#define PUEN1_PUEN_VI1_DATA9 BIT(29) +#define PUEN1_PUEN_VI1_DATA8 BIT(28) +#define PUEN1_PUEN_VI1_DATA7 BIT(27) +#define PUEN1_PUEN_VI1_DATA6 BIT(26) +#define PUEN1_PUEN_VI1_DATA5 BIT(25) +#define PUEN1_PUEN_VI1_DATA4 BIT(24) +#define PUEN1_PUEN_VI1_DATA3 BIT(23) +#define PUEN1_PUEN_VI1_DATA2 BIT(22) +#define PUEN1_PUEN_VI1_DATA1 BIT(21) +#define PUEN1_PUEN_VI1_DATA0 BIT(20) +#define PUEN1_PUEN_VI1_VSYNC_N BIT(19) +#define PUEN1_PUEN_VI1_HSYNC_N BIT(18) +#define PUEN1_PUEN_VI1_CLKENB BIT(17) +#define PUEN1_PUEN_VI1_CLK BIT(16) +#define PUEN1_PUEN_VI0_FIELD BIT(15) +#define PUEN1_PUEN_VI0_DATA11 BIT(14) +#define PUEN1_PUEN_VI0_DATA10 BIT(13) +#define PUEN1_PUEN_VI0_DATA9 BIT(12) +#define PUEN1_PUEN_VI0_DATA8 BIT(11) +#define PUEN1_PUEN_VI0_DATA7 BIT(10) +#define PUEN1_PUEN_VI0_DATA6 BIT(9) +#define PUEN1_PUEN_VI0_DATA5 BIT(8) +#define PUEN1_PUEN_VI0_DATA4 BIT(7) +#define PUEN1_PUEN_VI0_DATA3 BIT(6) +#define PUEN1_PUEN_VI0_DATA2 BIT(5) +#define PUEN1_PUEN_VI0_DATA1 BIT(4) +#define PUEN1_PUEN_VI0_DATA0 BIT(3) +#define PUEN1_PUEN_VI0_VSYNC_N BIT(2) +#define PUEN1_PUEN_VI0_HSYNC_N BIT(1) +#define PUEN1_PUEN_VI0_CLKENB BIT(0) + +#define PUEN2_PUEN_CANFD_CLK BIT(31) +#define PUEN2_PUEN_CANFD1_RX BIT(30) +#define PUEN2_PUEN_CANFD1_TX BIT(29) +#define PUEN2_PUEN_CANFD0_RX BIT(28) +#define PUEN2_PUEN_CANFD0_TX BIT(27) +#define PUEN2_PUEN_AVB0_AVTP_CAPTURE BIT(26) +#define PUEN2_PUEN_AVB0_AVTP_MATCH BIT(25) +#define PUEN2_PUEN_AVB0_LINK BIT(24) +#define PUEN2_PUEN_AVB0_PHY_INT BIT(23) +#define PUEN2_PUEN_AVB0_MAGIC BIT(22) +#define PUEN2_PUEN_AVB0_MDC BIT(21) +#define PUEN2_PUEN_AVB0_MDIO BIT(20) +#define PUEN2_PUEN_AVB0_TXCREFCLK BIT(19) +#define PUEN2_PUEN_AVB0_TD3 BIT(18) +#define PUEN2_PUEN_AVB0_TD2 BIT(17) +#define PUEN2_PUEN_AVB0_TD1 BIT(16) +#define PUEN2_PUEN_AVB0_TD0 BIT(15) +#define PUEN2_PUEN_AVB0_TXC BIT(14) +#define PUEN2_PUEN_AVB0_TX_CTL BIT(13) +#define PUEN2_PUEN_AVB0_RD3 BIT(12) +#define PUEN2_PUEN_AVB0_RD2 BIT(11) +#define PUEN2_PUEN_AVB0_RD1 BIT(10) +#define PUEN2_PUEN_AVB0_RD0 BIT(9) +#define PUEN2_PUEN_AVB0_RXC BIT(8) +#define PUEN2_PUEN_AVB0_RX_CTL BIT(7) +#define PUEN2_PUEN_SDA2 BIT(6) +#define PUEN2_PUEN_SCL2 BIT(5) +#define PUEN2_PUEN_SDA1 BIT(4) +#define PUEN2_PUEN_SCL1 BIT(3) +#define PUEN2_PUEN_SDA0 BIT(2) +#define PUEN2_PUEN_SCL0 BIT(1) +#define PUEN2_PUEN_VI1_FIELD BIT(0) + +#define PUEN3_PUEN_DIGRF_CLKOUT BIT(16) +#define PUEN3_PUEN_DIGRF_CLKIN BIT(15) +#define PUEN3_PUEN_RPC_INT_N BIT(14) +#define PUEN3_PUEN_RPC_WP_N BIT(13) +#define PUEN3_PUEN_RPC_RESET_N BIT(12) +#define PUEN3_PUEN_QSPI1_SSL BIT(11) +#define PUEN3_PUEN_QSPI1_IO3 BIT(10) +#define PUEN3_PUEN_QSPI1_IO2 BIT(9) +#define PUEN3_PUEN_QSPI1_MISO_IO1 BIT(8) +#define PUEN3_PUEN_QSPI1_MOSI_IO0 BIT(7) +#define PUEN3_PUEN_QSPI1_SPCLK BIT(6) +#define PUEN3_PUEN_QSPI0_SSL BIT(5) +#define PUEN3_PUEN_QSPI0_IO3 BIT(4) +#define PUEN3_PUEN_QSPI0_IO2 BIT(3) +#define PUEN3_PUEN_QSPI0_MISO_IO1 BIT(2) +#define PUEN3_PUEN_QSPI0_MOSI_IO0 BIT(1) +#define PUEN3_PUEN_QSPI0_SPCLK BIT(0) + +#define PUD0_PUD_VI0_CLK BIT(31) +#define PUD0_PUD_IRQ0 BIT(26) +#define PUD0_PUD_FSCLKST_N BIT(25) +#define PUD0_PUD_PRESETOUT_N BIT(23) +#define PUD0_PUD_DU_EXODDF_DU_ODDF_DISP_CDE BIT(21) +#define PUD0_PUD_DU_EXVSYNC_DU_VSYNC BIT(20) +#define PUD0_PUD_DU_EXHSYNC_DU_HSYNC BIT(19) +#define PUD0_PUD_DU_DOTCLKOUT BIT(18) +#define PUD0_PUD_DU_DB7 BIT(17) +#define PUD0_PUD_DU_DB6 BIT(16) +#define PUD0_PUD_DU_DB5 BIT(15) +#define PUD0_PUD_DU_DB4 BIT(14) +#define PUD0_PUD_DU_DB3 BIT(13) +#define PUD0_PUD_DU_DB2 BIT(12) +#define PUD0_PUD_DU_DG7 BIT(11) +#define PUD0_PUD_DU_DG6 BIT(10) +#define PUD0_PUD_DU_DG5 BIT(9) +#define PUD0_PUD_DU_DG4 BIT(8) +#define PUD0_PUD_DU_DG3 BIT(7) +#define PUD0_PUD_DU_DG2 BIT(6) +#define PUD0_PUD_DU_DR7 BIT(5) +#define PUD0_PUD_DU_DR6 BIT(4) +#define PUD0_PUD_DU_DR5 BIT(3) +#define PUD0_PUD_DU_DR4 BIT(2) +#define PUD0_PUD_DU_DR3 BIT(1) +#define PUD0_PUD_DU_DR2 BIT(0) + +#define PUD1_PUD_VI1_DATA11 BIT(31) +#define PUD1_PUD_VI1_DATA10 BIT(30) +#define PUD1_PUD_VI1_DATA9 BIT(29) +#define PUD1_PUD_VI1_DATA8 BIT(28) +#define PUD1_PUD_VI1_DATA7 BIT(27) +#define PUD1_PUD_VI1_DATA6 BIT(26) +#define PUD1_PUD_VI1_DATA5 BIT(25) +#define PUD1_PUD_VI1_DATA4 BIT(24) +#define PUD1_PUD_VI1_DATA3 BIT(23) +#define PUD1_PUD_VI1_DATA2 BIT(22) +#define PUD1_PUD_VI1_DATA1 BIT(21) +#define PUD1_PUD_VI1_DATA0 BIT(20) +#define PUD1_PUD_VI1_VSYNC_N BIT(19) +#define PUD1_PUD_VI1_HSYNC_N BIT(18) +#define PUD1_PUD_VI1_CLKENB BIT(17) +#define PUD1_PUD_VI1_CLK BIT(16) +#define PUD1_PUD_VI0_FIELD BIT(15) +#define PUD1_PUD_VI0_DATA11 BIT(14) +#define PUD1_PUD_VI0_DATA10 BIT(13) +#define PUD1_PUD_VI0_DATA9 BIT(12) +#define PUD1_PUD_VI0_DATA8 BIT(11) +#define PUD1_PUD_VI0_DATA7 BIT(10) +#define PUD1_PUD_VI0_DATA6 BIT(9) +#define PUD1_PUD_VI0_DATA5 BIT(8) +#define PUD1_PUD_VI0_DATA4 BIT(7) +#define PUD1_PUD_VI0_DATA3 BIT(6) +#define PUD1_PUD_VI0_DATA2 BIT(5) +#define PUD1_PUD_VI0_DATA1 BIT(4) +#define PUD1_PUD_VI0_DATA0 BIT(3) +#define PUD1_PUD_VI0_VSYNC_N BIT(2) +#define PUD1_PUD_VI0_HSYNC_N BIT(1) +#define PUD1_PUD_VI0_CLKENB BIT(0) + +#define PUD2_PUD_CANFD_CLK BIT(31) +#define PUD2_PUD_CANFD1_RX BIT(30) +#define PUD2_PUD_CANFD1_TX BIT(29) +#define PUD2_PUD_CANFD0_RX BIT(28) +#define PUD2_PUD_CANFD0_TX BIT(27) +#define PUD2_PUD_AVB0_AVTP_CAPTURE BIT(26) +#define PUD2_PUD_AVB0_AVTP_MATCH BIT(25) +#define PUD2_PUD_AVB0_LINK BIT(24) +#define PUD2_PUD_AVB0_PHY_INT BIT(23) +#define PUD2_PUD_AVB0_MAGIC BIT(22) +#define PUD2_PUD_AVB0_MDC BIT(21) +#define PUD2_PUD_AVB0_MDIO BIT(20) +#define PUD2_PUD_AVB0_TXCREFCLK BIT(19) +#define PUD2_PUD_AVB0_TD3 BIT(18) +#define PUD2_PUD_AVB0_TD2 BIT(17) +#define PUD2_PUD_AVB0_TD1 BIT(16) +#define PUD2_PUD_AVB0_TD0 BIT(15) +#define PUD2_PUD_AVB0_TXC BIT(14) +#define PUD2_PUD_AVB0_TX_CTL BIT(13) +#define PUD2_PUD_AVB0_RD3 BIT(12) +#define PUD2_PUD_AVB0_RD2 BIT(11) +#define PUD2_PUD_AVB0_RD1 BIT(10) +#define PUD2_PUD_AVB0_RD0 BIT(9) +#define PUD2_PUD_AVB0_RXC BIT(8) +#define PUD2_PUD_AVB0_RX_CTL BIT(7) +#define PUD2_PUD_SDA2 BIT(6) +#define PUD2_PUD_SCL2 BIT(5) +#define PUD2_PUD_SDA1 BIT(4) +#define PUD2_PUD_SCL1 BIT(3) +#define PUD2_PUD_SDA0 BIT(2) +#define PUD2_PUD_SCL0 BIT(1) +#define PUD2_PUD_VI1_FIELD BIT(0) + +#define PUD3_PUD_DIGRF_CLKOUT BIT(16) +#define PUD3_PUD_DIGRF_CLKIN BIT(15) +#define PUD3_PUD_RPC_INT_N BIT(14) +#define PUD3_PUD_RPC_WP_N BIT(13) +#define PUD3_PUD_RPC_RESET_N BIT(12) +#define PUD3_PUD_QSPI1_SSL BIT(11) +#define PUD3_PUD_QSPI1_IO3 BIT(10) +#define PUD3_PUD_QSPI1_IO2 BIT(9) +#define PUD3_PUD_QSPI1_MISO_IO1 BIT(8) +#define PUD3_PUD_QSPI1_MOSI_IO0 BIT(7) +#define PUD3_PUD_QSPI1_SPCLK BIT(6) +#define PUD3_PUD_QSPI0_SSL BIT(5) +#define PUD3_PUD_QSPI0_IO3 BIT(4) +#define PUD3_PUD_QSPI0_IO2 BIT(3) +#define PUD3_PUD_QSPI0_MISO_IO1 BIT(2) +#define PUD3_PUD_QSPI0_MOSI_IO0 BIT(1) +#define PUD3_PUD_QSPI0_SPCLK BIT(0) + +#define MOD_SEL0_sel_hscif0 BIT(10) +#define MOD_SEL0_sel_scif1 BIT(9) +#define MOD_SEL0_sel_canfd0 BIT(8) +#define MOD_SEL0_sel_pwm4 BIT(7) +#define MOD_SEL0_sel_pwm3 BIT(6) +#define MOD_SEL0_sel_pwm2 BIT(5) +#define MOD_SEL0_sel_pwm1 BIT(4) +#define MOD_SEL0_sel_pwm0 BIT(3) +#define MOD_SEL0_sel_rfso BIT(2) +#define MOD_SEL0_sel_rsp BIT(1) +#define MOD_SEL0_sel_tmu BIT(0) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define CPG_RMSTPCR0 (CPG_BASE + 0x0110U) +#define RMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + /* Module stop clear */ + while ((mmio_read_32(CPG_MSTPSR0) & RMSTPCR0_RTDMAC) != 0U) { + reg = mmio_read_32(CPG_RMSTPCR0); + reg &= ~RMSTPCR0_RTDMAC; + cpg_write(CPG_RMSTPCR0, reg); + } + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); +} + +void pfc_init_v3m(void) +{ + /* Work around for PFC eratta */ + start_rtdma0_descriptor(); + + // pin function + // md[4:1]!=0000 + /* initialize GPIO/perihperal function select */ + + pfc_reg_write(PFC_GPSR0, 0x00000000); + + pfc_reg_write(PFC_GPSR1, GPSR1_CANFD_CLK); + + pfc_reg_write(PFC_GPSR2, 0x00000000); + + pfc_reg_write(PFC_GPSR3, 0x00000000); + + pfc_reg_write(PFC_GPSR4, GPSR4_SDA2 + | GPSR4_SCL2); + + pfc_reg_write(PFC_GPSR5, GPSR5_QSPI1_SSL + | GPSR5_QSPI1_IO3 + | GPSR5_QSPI1_IO2 + | GPSR5_QSPI1_MISO_IO1 + | GPSR5_QSPI1_MOSI_IO0 + | GPSR5_QSPI1_SPCLK + | GPSR5_QSPI0_SSL + | GPSR5_QSPI0_IO3 + | GPSR5_QSPI0_IO2 + | GPSR5_QSPI0_MISO_IO1 + | GPSR5_QSPI0_MOSI_IO0 + | GPSR5_QSPI0_SPCLK); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(4) + | IPSR_16_FUNC(4) + | IPSR_12_FUNC(4) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(4) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize POC Control */ + + pfc_reg_write(PFC_POCCTRL0, IOCTRL30_POC_VI0_DATA5 + | IOCTRL30_POC_VI0_DATA4 + | IOCTRL30_POC_VI0_DATA3 + | IOCTRL30_POC_VI0_DATA2 + | IOCTRL30_POC_VI0_DATA1 + | IOCTRL30_POC_VI0_DATA0 + | IOCTRL30_POC_VI0_VSYNC_N + | IOCTRL30_POC_VI0_HSYNC_N + | IOCTRL30_POC_VI0_CLKENB + | IOCTRL30_POC_VI0_CLK + | IOCTRL30_POC_DU_EXODDF_DU_ODDF_DISP_CDE + | IOCTRL30_POC_DU_EXVSYNC_DU_VSYNC + | IOCTRL30_POC_DU_EXHSYNC_DU_HSYNC + | IOCTRL30_POC_DU_DOTCLKOUT + | IOCTRL30_POC_DU_DB7 + | IOCTRL30_POC_DU_DB6 + | IOCTRL30_POC_DU_DB5 + | IOCTRL30_POC_DU_DB4 + | IOCTRL30_POC_DU_DB3 + | IOCTRL30_POC_DU_DB2 + | IOCTRL30_POC_DU_DG7 + | IOCTRL30_POC_DU_DG6 + | IOCTRL30_POC_DU_DG5 + | IOCTRL30_POC_DU_DG4 + | IOCTRL30_POC_DU_DG3 + | IOCTRL30_POC_DU_DG2 + | IOCTRL30_POC_DU_DR7 + | IOCTRL30_POC_DU_DR6 + | IOCTRL30_POC_DU_DR5 + | IOCTRL30_POC_DU_DR4 + | IOCTRL30_POC_DU_DR3 + | IOCTRL30_POC_DU_DR2); + + pfc_reg_write(PFC_IOCTRL31, IOCTRL31_POC_DUMMY_31 + | IOCTRL31_POC_DUMMY_30 + | IOCTRL31_POC_DUMMY_29 + | IOCTRL31_POC_DUMMY_28 + | IOCTRL31_POC_DUMMY_27 + | IOCTRL31_POC_DUMMY_26 + | IOCTRL31_POC_DUMMY_25 + | IOCTRL31_POC_DUMMY_24 + | IOCTRL31_POC_VI1_FIELD + | IOCTRL31_POC_VI1_DATA11 + | IOCTRL31_POC_VI1_DATA10 + | IOCTRL31_POC_VI1_DATA9 + | IOCTRL31_POC_VI1_DATA8 + | IOCTRL31_POC_VI1_DATA7 + | IOCTRL31_POC_VI1_DATA6 + | IOCTRL31_POC_VI1_DATA5 + | IOCTRL31_POC_VI1_DATA4 + | IOCTRL31_POC_VI1_DATA3 + | IOCTRL31_POC_VI1_DATA2 + | IOCTRL31_POC_VI1_DATA1 + | IOCTRL31_POC_VI1_DATA0 + | IOCTRL31_POC_VI1_VSYNC_N + | IOCTRL31_POC_VI1_HSYNC_N + | IOCTRL31_POC_VI1_CLKENB + | IOCTRL31_POC_VI1_CLK + | IOCTRL31_POC_VI0_FIELD + | IOCTRL31_POC_VI0_DATA11 + | IOCTRL31_POC_VI0_DATA10 + | IOCTRL31_POC_VI0_DATA9 + | IOCTRL31_POC_VI0_DATA8 + | IOCTRL31_POC_VI0_DATA7 + | IOCTRL31_POC_VI0_DATA6); + + pfc_reg_write(PFC_POCCTRL2, 0x00000000); + + pfc_reg_write(PFC_TDSELCTRL0, 0x00000000); + + /* initialize Pull enable */ + pfc_reg_write(PFC_PUEN0, PUEN0_PUEN_VI0_CLK + | PUEN0_PUEN_TDI + | PUEN0_PUEN_TMS + | PUEN0_PUEN_TCK + | PUEN0_PUEN_TRST_N + | PUEN0_PUEN_IRQ0 + | PUEN0_PUEN_FSCLKST_N + | PUEN0_PUEN_DU_EXHSYNC_DU_HSYNC + | PUEN0_PUEN_DU_DOTCLKOUT + | PUEN0_PUEN_DU_DB7 + | PUEN0_PUEN_DU_DB6 + | PUEN0_PUEN_DU_DB5 + | PUEN0_PUEN_DU_DB4 + | PUEN0_PUEN_DU_DB3 + | PUEN0_PUEN_DU_DB2 + | PUEN0_PUEN_DU_DG7 + | PUEN0_PUEN_DU_DG6 + | PUEN0_PUEN_DU_DG5 + | PUEN0_PUEN_DU_DG4 + | PUEN0_PUEN_DU_DG3 + | PUEN0_PUEN_DU_DG2 + | PUEN0_PUEN_DU_DR7 + | PUEN0_PUEN_DU_DR6 + | PUEN0_PUEN_DU_DR5 + | PUEN0_PUEN_DU_DR4 + | PUEN0_PUEN_DU_DR3 + | PUEN0_PUEN_DU_DR2); + + pfc_reg_write(PFC_PUEN1, PUEN1_PUEN_VI1_DATA11 + | PUEN1_PUEN_VI1_DATA10 + | PUEN1_PUEN_VI1_DATA9 + | PUEN1_PUEN_VI1_DATA8 + | PUEN1_PUEN_VI1_DATA7 + | PUEN1_PUEN_VI1_DATA6 + | PUEN1_PUEN_VI1_DATA5 + | PUEN1_PUEN_VI1_DATA4 + | PUEN1_PUEN_VI1_DATA3 + | PUEN1_PUEN_VI1_DATA2 + | PUEN1_PUEN_VI1_DATA1 + | PUEN1_PUEN_VI1_DATA0 + | PUEN1_PUEN_VI1_VSYNC_N + | PUEN1_PUEN_VI1_HSYNC_N + | PUEN1_PUEN_VI1_CLKENB + | PUEN1_PUEN_VI1_CLK + | PUEN1_PUEN_VI0_DATA11 + | PUEN1_PUEN_VI0_DATA10 + | PUEN1_PUEN_VI0_DATA9 + | PUEN1_PUEN_VI0_DATA8 + | PUEN1_PUEN_VI0_DATA7 + | PUEN1_PUEN_VI0_DATA6 + | PUEN1_PUEN_VI0_DATA5 + | PUEN1_PUEN_VI0_DATA4 + | PUEN1_PUEN_VI0_DATA3 + | PUEN1_PUEN_VI0_DATA2 + | PUEN1_PUEN_VI0_DATA1); + + pfc_reg_write(PFC_PUEN2, PUEN2_PUEN_CANFD_CLK + | PUEN2_PUEN_CANFD1_RX + | PUEN2_PUEN_CANFD1_TX + | PUEN2_PUEN_CANFD0_RX + | PUEN2_PUEN_CANFD0_TX + | PUEN2_PUEN_AVB0_AVTP_CAPTURE + | PUEN2_PUEN_AVB0_AVTP_MATCH + | PUEN2_PUEN_AVB0_LINK + | PUEN2_PUEN_AVB0_PHY_INT + | PUEN2_PUEN_AVB0_MAGIC + | PUEN2_PUEN_AVB0_TXCREFCLK + | PUEN2_PUEN_AVB0_TD3 + | PUEN2_PUEN_AVB0_TD2 + | PUEN2_PUEN_AVB0_TD1 + | PUEN2_PUEN_AVB0_TD0 + | PUEN2_PUEN_AVB0_TXC + | PUEN2_PUEN_AVB0_TX_CTL + | PUEN2_PUEN_AVB0_RD3 + | PUEN2_PUEN_AVB0_RD2 + | PUEN2_PUEN_AVB0_RD1 + | PUEN2_PUEN_AVB0_RD0 + | PUEN2_PUEN_AVB0_RXC + | PUEN2_PUEN_AVB0_RX_CTL + | PUEN2_PUEN_VI1_FIELD); + + pfc_reg_write(PFC_PUEN3, PUEN3_PUEN_DIGRF_CLKOUT + | PUEN3_PUEN_DIGRF_CLKIN); + + /* initialize PUD Control */ + pfc_reg_write(PFC_PUD0, PUD0_PUD_VI0_CLK + | PUD0_PUD_IRQ0 + | PUD0_PUD_FSCLKST_N + | PUD0_PUD_DU_EXODDF_DU_ODDF_DISP_CDE + | PUD0_PUD_DU_EXVSYNC_DU_VSYNC + | PUD0_PUD_DU_EXHSYNC_DU_HSYNC + | PUD0_PUD_DU_DOTCLKOUT + | PUD0_PUD_DU_DB7 + | PUD0_PUD_DU_DB6 + | PUD0_PUD_DU_DB5 + | PUD0_PUD_DU_DB4 + | PUD0_PUD_DU_DB3 + | PUD0_PUD_DU_DB2 + | PUD0_PUD_DU_DG7 + | PUD0_PUD_DU_DG6 + | PUD0_PUD_DU_DG5 + | PUD0_PUD_DU_DG4 + | PUD0_PUD_DU_DG3 + | PUD0_PUD_DU_DG2 + | PUD0_PUD_DU_DR7 + | PUD0_PUD_DU_DR6 + | PUD0_PUD_DU_DR5 + | PUD0_PUD_DU_DR4 + | PUD0_PUD_DU_DR3 + | PUD0_PUD_DU_DR2); + + pfc_reg_write(PFC_PUD1, PUD1_PUD_VI1_DATA11 + | PUD1_PUD_VI1_DATA10 + | PUD1_PUD_VI1_DATA9 + | PUD1_PUD_VI1_DATA8 + | PUD1_PUD_VI1_DATA7 + | PUD1_PUD_VI1_DATA6 + | PUD1_PUD_VI1_DATA5 + | PUD1_PUD_VI1_DATA4 + | PUD1_PUD_VI1_DATA3 + | PUD1_PUD_VI1_DATA2 + | PUD1_PUD_VI1_DATA1 + | PUD1_PUD_VI1_DATA0 + | PUD1_PUD_VI1_VSYNC_N + | PUD1_PUD_VI1_HSYNC_N + | PUD1_PUD_VI1_CLKENB + | PUD1_PUD_VI1_CLK + | PUD1_PUD_VI0_DATA11 + | PUD1_PUD_VI0_DATA10 + | PUD1_PUD_VI0_DATA9 + | PUD1_PUD_VI0_DATA8 + | PUD1_PUD_VI0_DATA7 + | PUD1_PUD_VI0_DATA6 + | PUD1_PUD_VI0_DATA5 + | PUD1_PUD_VI0_DATA4 + | PUD1_PUD_VI0_DATA3 + | PUD1_PUD_VI0_DATA2 + | PUD1_PUD_VI0_DATA1 + | PUD1_PUD_VI0_DATA0 + | PUD1_PUD_VI0_VSYNC_N + | PUD1_PUD_VI0_HSYNC_N + | PUD1_PUD_VI0_CLKENB); + + pfc_reg_write(PFC_PUD2, PUD2_PUD_CANFD_CLK + | PUD2_PUD_CANFD1_RX + | PUD2_PUD_CANFD1_TX + | PUD2_PUD_CANFD0_RX + | PUD2_PUD_CANFD0_TX + | PUD2_PUD_AVB0_AVTP_CAPTURE + | PUD2_PUD_VI1_FIELD); + + pfc_reg_write(PFC_PUD3, PUD3_PUD_DIGRF_CLKOUT + | PUD3_PUD_DIGRF_CLKIN); + + /* initialize Module Select */ + pfc_reg_write(PFC_MOD_SEL0, 0x00000000); + + // gpio + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000000U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h new file mode 100644 index 0000000..7bab92f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_V3M_H +#define PFC_INIT_V3M_H + +void pfc_init_v3m(void); + +#endif /* PFC_INIT_V3M_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk new file mode 100644 index 0000000..f1dd92c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc.mk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RCAR_H3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/E3/pfc_init_e3.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/D3/pfc_init_d3.c + endif +else + ifeq (${RCAR_LSI},${RCAR_H3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c + else +# LSI_CUT 20 or later + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3/pfc_init_m3.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/E3/pfc_init_e3.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/pfc/D3/pfc_init_d3.c + endif +endif + +BL2_SOURCES += drivers/renesas/rcar/pfc/pfc_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c new file mode 100644 index 0000000..8810667 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "rcar_def.h" +#if RCAR_LSI == RCAR_AUTO +#include "H3/pfc_init_h3_v1.h" +#include "H3/pfc_init_h3_v2.h" +#include "M3/pfc_init_m3.h" +#include "M3N/pfc_init_m3n.h" +#include "V3M/pfc_init_v3m.h" +#endif +#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) /* H3 */ +#include "H3/pfc_init_h3_v1.h" +#include "H3/pfc_init_h3_v2.h" +#endif +#if RCAR_LSI == RCAR_M3 /* M3 */ +#include "M3/pfc_init_m3.h" +#endif +#if RCAR_LSI == RCAR_M3N /* M3N */ +#include "M3N/pfc_init_m3n.h" +#endif +#if RCAR_LSI == RCAR_V3M /* V3M */ +#include "V3M/pfc_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_E3 /* E3 */ +#include "E3/pfc_init_e3.h" +#endif +#if RCAR_LSI == RCAR_D3 /* D3 */ +#include "D3/pfc_init_d3.h" +#endif + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) PFC initialize not supported.\n", \ + reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) PFC initialize not supported.\n", \ + reg); \ + panic();\ + } while (0) + +void rcar_pfc_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); +#if RCAR_LSI == RCAR_AUTO + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: /* H3 Ver.1.0 */ + pfc_init_h3_v1(); + break; + case PRR_PRODUCT_11: /* H3 Ver.1.1 */ + pfc_init_h3_v1(); + break; + default: /* H3 Ver.2.0 or later */ + pfc_init_h3_v2(); + break; + } + break; + case PRR_PRODUCT_M3: + pfc_init_m3(); + break; + case PRR_PRODUCT_M3N: + pfc_init_m3n(); + break; + case PRR_PRODUCT_V3M: + pfc_init_v3m(); + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#elif RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: +#if (RCAR_LSI != RCAR_H3) && (RCAR_LSI != RCAR_H3N) + PRR_PRODUCT_ERR(reg); +#else + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: /* H3 Ver.1.0 */ + pfc_init_h3_v1(); + break; + case PRR_PRODUCT_11: /* H3 Ver.1.1 */ + pfc_init_h3_v1(); + break; + default: /* H3 Ver.2.0 or later */ + pfc_init_h3_v2(); + break; + } +#endif + break; + case PRR_PRODUCT_M3: +#if RCAR_LSI != RCAR_M3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_m3(); +#endif + break; + case PRR_PRODUCT_M3N: +#if RCAR_LSI != RCAR_M3N + PRR_PRODUCT_ERR(reg); +#else + pfc_init_m3n(); +#endif + break; + case PRR_PRODUCT_V3M: +#if RCAR_LSI != RCAR_V3M + PRR_PRODUCT_ERR(reg); +#else + pfc_init_v3m(); +#endif + break; + case PRR_PRODUCT_E3: +#if RCAR_LSI != RCAR_E3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_e3(); +#endif + break; + case PRR_PRODUCT_D3: +#if RCAR_LSI != RCAR_D3 + PRR_PRODUCT_ERR(reg); +#else + pfc_init_d3(); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#else +#if (RCAR_LSI == RCAR_H3) || (RCAR_LSI == RCAR_H3N) /* H3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Ver.1.0 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v1(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Ver.1.1 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_11) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v1(); +#else + /* H3 Ver.2.0 or later */ + if (PRR_PRODUCT_H3 != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_h3_v2(); +#endif +#elif RCAR_LSI == RCAR_M3 /* M3 */ + if ((PRR_PRODUCT_M3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3(); +#elif RCAR_LSI == RCAR_M3N /* M3N */ + if ((PRR_PRODUCT_M3N) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3n(); +#elif RCAR_LSI == RCAR_V3M /* V3M */ + if ((PRR_PRODUCT_V3M) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_v3m(); +#elif RCAR_LSI == RCAR_E3 /* E3 */ + if ((PRR_PRODUCT_E3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_e3(); +#elif RCAR_LSI == RCAR_D3 /* D3 */ + if ((PRR_PRODUCT_D3) != (reg & PRR_PRODUCT_MASK)) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_d3(); +#else +#error "Don't have PFC initialize routine(unknown)." +#endif +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c new file mode 100644 index 0000000..b96e822 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_d3.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#include "qos_init_d3_mstat.h" + +struct rcar_gen3_dbsc_qos_settings d3_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000300 }, + { DBSC_DBSCHQOS91, 0x000002F0 }, + { DBSC_DBSCHQOS92, 0x00000200 }, + { DBSC_DBSCHQOS93, 0x00000100 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_d3(void) +{ + rcar_qos_dbsc_setting(d3_qos, ARRAY_SIZE(d3_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH + ERROR("DRAM Split 4ch not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + ERROR("DRAM Split 2ch not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO + ERROR("DRAM Split Auto not supported.(D3)"); + panic(); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_LINEAR +/* NOTICE("BL2: DRAM Split is OFF\n"); */ + /* Split setting(DDR 1ch) */ + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + ERROR("DRAM split is an invalid value.(D3)"); + panic(); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_RAEN, 0x00000001U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201U); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_EC, 0x00000000U); + io_write_64(QOSCTRL_EMS, 0x0000000000000000U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_EARLYR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + io_write_32(QOSCTRL_STATGEN0, 0x00000000U); + + /* GPU setting */ + io_write_32(0xFD812030U, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, 0x030500ACU); + io_write_32(QOSCTRL_REF_ARS, 0x00780000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT_GRD, 0x00001234U); + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h new file mode 100644 index 0000000..968ee7a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_D3__ +#define QOS_INIT_H_D3__ + +void qos_init_d3(void); + +#endif /* QOS_INIT_H_D3__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h new file mode 100644 index 0000000..cbf1f65 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004340000FFFFUL, + /* 0x0038, */ 0x001004140000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140B030000FFFFUL, + /* 0x0060, */ 0x001408610000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410620000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C041C0000FFFFUL, + /* 0x00A8, */ 0x000C04090000FFFFUL, + /* 0x00B0, */ 0x000C04110000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C041C0000FFFFUL, + /* 0x00C8, */ 0x000C04090000FFFFUL, + /* 0x00D0, */ 0x000C04110000FFFFUL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001018570000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001008570000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001008520000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00100CA30000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x000C04020000FFFFUL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02A0, */ 0x000C04050000FFFFUL, + /* 0x02A8, */ 0x000C04050000FFFFUL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04050000FFFFUL, + /* 0x02D8, */ 0x000C04050000FFFFUL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x00110090060FA001UL, + /* 0x01C8, */ 0x00110090060FA001UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0011001006004401UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0011001006004401UL, + /* 0x0218, */ 0x0011001006009801UL, + /* 0x0220, */ 0x0011001006009801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001006009801UL, + /* 0x0238, */ 0x0011001006009801UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0011001006003401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0011001006003401UL, + /* 0x02F0, */ 0x00110090060FA001UL, + /* 0x02F8, */ 0x00110090060FA001UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001006003401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x00120090060FA001UL, + /* 0x0360, */ 0x00120090060FA001UL, + /* 0x0368, */ 0x0012001006003401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001006003401UL, +}; +#endif + diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c new file mode 100644 index 0000000..6f4c66c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_e3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#define REF_ARS_ARBSTOPCYCLE_E3 (((SL_INIT_SSLOTCLK_E3) - 5U) << 16U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_e3_v10_mstat390.h" +#else +#include "qos_init_e3_v10_mstat780.h" +#endif + +#endif + +struct rcar_gen3_dbsc_qos_settings e3_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_e3_v10(void) +{ + rcar_qos_dbsc_setting(e3_qos, ARRAY_SIZE(e3_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_E3 +#error "Don't set DRAM Split 4ch(E3)" +#else + ERROR("DRAM Split 4ch not supported.(E3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_E3 +#error "Don't set DRAM Split 2ch(E3)" +#else + ERROR("DRAM Split 2ch not supported.(E3)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 7.8 usec\n"); +#endif + + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_E3); + io_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_E3); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h new file mode 100644 index 0000000..2c1d8c5 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_E3_V10_H +#define QOS_INIT_E3_V10_H + +void qos_init_e3_v10(void); + +#endif /* QOS_INIT_E3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h new file mode 100644 index 0000000..d7f9d14 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008620000FFFFUL, + /* 0x0038, */ 0x001008620000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415260000FFFFUL, + /* 0x0060, */ 0x001415260000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414930000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08380000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08380000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001018580000FFFFUL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001008580000FFFFUL, + /* 0x0118, */ 0x000C21E40000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008530000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C960000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001008530000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0010042A0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D8D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001008530000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005FFFC01UL, + /* 0x01c8, */ 0x0021060005FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005F79801UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005F79801UL, + /* 0x0218, */ 0x0011010005F79801UL, + /* 0x0220, */ 0x0011010005F79801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005F79801UL, + /* 0x0238, */ 0x0011010005F79801UL, + /* 0x0240, */ 0x0012010005F79801UL, + /* 0x0248, */ 0x0011010005F79801UL, + /* 0x0250, */ 0x0012010005F79801UL, + /* 0x0258, */ 0x0011010005F79801UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005FFFC01UL, + /* 0x02f8, */ 0x0011060005FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005FFFC01UL, + /* 0x0360, */ 0x0012060005FFFC01UL, + /* 0x0368, */ 0x0012001005F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005F03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h new file mode 100644 index 0000000..439cafe --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001010C40000FFFFUL, + /* 0x0038, */ 0x001010C40000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00142A4B0000FFFFUL, + /* 0x0060, */ 0x00142A4B0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001429260000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C10700000FFFFUL, + /* 0x00a8, */ 0x000C08210000FFFFUL, + /* 0x00b0, */ 0x000C082A0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C10700000FFFFUL, + /* 0x00c8, */ 0x000C08210000FFFFUL, + /* 0x00d0, */ 0x000C082A0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x00102CAF0000FFFFUL, + /* 0x00f8, */ 0x000C0C9D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100CAF0000FFFFUL, + /* 0x0118, */ 0x000C43C80000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010152C0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037190000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04040000FFFFUL, + /* 0x01f0, */ 0x000C08110000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04110000FFFFUL, + /* 0x0210, */ 0x000C08110000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C18530000FFFFUL, + /* 0x0268, */ 0x00141C070000FFFFUL, + /* 0x0270, */ 0x001404040000FFFFUL, + /* 0x0278, */ 0x000C0C210000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x00141C070000FFFFUL, + /* 0x0298, */ 0x001404040000FFFFUL, + /* 0x02a0, */ 0x000C04110000FFFFUL, + /* 0x02a8, */ 0x000C04110000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04040000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04110000FFFFUL, + /* 0x02d8, */ 0x000C04110000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04040000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04040000FFFFUL, + /* 0x0378, */ 0x000C04040000FFFFUL, + /* 0x0380, */ 0x000C04110000FFFFUL, + /* 0x0388, */ 0x000C04110000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001002F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060002FFFC01UL, + /* 0x01c8, */ 0x0021060002FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010002F3CC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010002F3CC01UL, + /* 0x0218, */ 0x0011010002F3CC01UL, + /* 0x0220, */ 0x0011010002F3CC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010002F3CC01UL, + /* 0x0238, */ 0x0011010002F3CC01UL, + /* 0x0240, */ 0x0012010002F3CC01UL, + /* 0x0248, */ 0x0011010002F3CC01UL, + /* 0x0250, */ 0x0012010002F3CC01UL, + /* 0x0258, */ 0x0011010002F3CC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060002FFFC01UL, + /* 0x02f8, */ 0x0011060002FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001002F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060002FFFC01UL, + /* 0x0360, */ 0x0012060002FFFC01UL, + /* 0x0368, */ 0x0012001002F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001002F03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c new file mode 100644 index 0000000..1fb43a7 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.36" + +#include "qos_init_h3_v10_mstat.h" + +void qos_init_h3_v10(void) +{ + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0xA8A90000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* AR Cache setting */ + io_write_32(0xE67D1000U, 0x00000100U); + io_write_32(0xE67D1008U, 0x00000100U); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000040U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000004U); + io_write_64(QOSCTRL_DANN, 0x0202000004040404UL); + io_write_32(QOSCTRL_DANT, 0x003C1110U); + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x0000003FU); + io_write_32(0xFD821800U, 0x0000003FU); + io_write_32(0xFD822800U, 0x0000003FU); + io_write_32(0xFD823800U, 0x0000003FU); + io_write_32(0xFD824800U, 0x0000003FU); + io_write_32(0xFD825800U, 0x0000003FU); + io_write_32(0xFD826800U, 0x0000003FU); + io_write_32(0xFD827800U, 0x0000003FU); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h new file mode 100644 index 0000000..f96182a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V10_H +#define QOS_INIT_H3_V10_H + +void qos_init_h3_v10(void); + +#endif /* QOS_INIT_H3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h new file mode 100644 index 0000000..fe63236 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x00140C050000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001404030000FFFFUL, + /* 0x0060, */ 0x001408060000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00140C050000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x001404020000FFFFUL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001004020000FFFFUL, + /* 0x0140, */ 0x001004020000FFFFUL, + /* 0x0148, */ 0x001004020000FFFFUL, + /* 0x0150, */ 0x001008050000FFFFUL, + /* 0x0158, */ 0x001008050000FFFFUL, + /* 0x0160, */ 0x001008050000FFFFUL, + /* 0x0168, */ 0x001008050000FFFFUL, + /* 0x0170, */ 0x001008050000FFFFUL, + /* 0x0178, */ 0x001004030000FFFFUL, + /* 0x0180, */ 0x001004030000FFFFUL, + /* 0x0188, */ 0x001004030000FFFFUL, + /* 0x0190, */ 0x001014140000FFFFUL, + /* 0x0198, */ 0x001014140000FFFFUL, + /* 0x01A0, */ 0x001008060000FFFFUL, + /* 0x01A8, */ 0x001008060000FFFFUL, + /* 0x01B0, */ 0x001008060000FFFFUL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001000100C8FFC01UL, + /* 0x0008, */ 0x001000100C8FFC01UL, + /* 0x0010, */ 0x001000100C8FFC01UL, + /* 0x0018, */ 0x001000100C8FFC01UL, + /* 0x0020, */ 0x001000100C8FFC01UL, + /* 0x0028, */ 0x001000100C8FFC01UL, + /* 0x0030, */ 0x001000100C8FFC01UL, + /* 0x0038, */ 0x001000100C8FFC01UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001000100C8FFC01UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x001000100C8FFC01UL, + /* 0x0070, */ 0x001000100C8FFC01UL, + /* 0x0078, */ 0x001000100C8FFC01UL, + /* 0x0080, */ 0x001000100C8FFC01UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x001000100C8FFC01UL, + /* 0x00A8, */ 0x001000100C8FFC01UL, + /* 0x00B0, */ 0x001000100C8FFC01UL, + /* 0x00B8, */ 0x001000100C8FFC01UL, + /* 0x00C0, */ 0x001000100C8FFC01UL, + /* 0x00C8, */ 0x001000100C8FFC01UL, + /* 0x00D0, */ 0x001000100C8FFC01UL, + /* 0x00D8, */ 0x002000200C8FFC01UL, + /* 0x00E0, */ 0x002000200C8FFC01UL, + /* 0x00E8, */ 0x001000100C8FFC01UL, + /* 0x00F0, */ 0x001000100C8FFC01UL, + /* 0x00F8, */ 0x001000100C8FFC01UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x002000200C8FFC01UL, + /* 0x0110, */ 0x001000100C8FFC01UL, + /* 0x0118, */ 0x001000100C8FFC01UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x002000200C8FFC01UL, + /* 0x0130, */ 0x001000100C8FFC01UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x001000100C8FFC01UL, + /* 0x01C0, */ 0x001000200C8FFC01UL, + /* 0x01C8, */ 0x001000200C8FFC01UL, + /* 0x01D0, */ 0x001000200C8FFC01UL, + /* 0x01D8, */ 0x001000200C8FFC01UL, + /* 0x01E0, */ 0x001000100C8FFC01UL, + /* 0x01E8, */ 0x001000100C8FFC01UL, + /* 0x01F0, */ 0x001000100C8FFC01UL, + /* 0x01F8, */ 0x001000100C8FFC01UL, + /* 0x0200, */ 0x001000100C8FFC01UL, + /* 0x0208, */ 0x001000100C8FFC01UL, + /* 0x0210, */ 0x001000100C8FFC01UL, + /* 0x0218, */ 0x001000100C8FFC01UL, + /* 0x0220, */ 0x001000100C8FFC01UL, + /* 0x0228, */ 0x001000100C8FFC01UL, + /* 0x0230, */ 0x001000100C8FFC01UL, + /* 0x0238, */ 0x001000100C8FFC01UL, + /* 0x0240, */ 0x001000100C8FFC01UL, + /* 0x0248, */ 0x001000100C8FFC01UL, + /* 0x0250, */ 0x001000100C8FFC01UL, + /* 0x0258, */ 0x001000100C8FFC01UL, + /* 0x0260, */ 0x001000100C8FFC01UL, + /* 0x0268, */ 0x001000100C8FFC01UL, + /* 0x0270, */ 0x001000100C8FFC01UL, + /* 0x0278, */ 0x001000100C8FFC01UL, + /* 0x0280, */ 0x001000100C8FFC01UL, + /* 0x0288, */ 0x001000100C8FFC01UL, + /* 0x0290, */ 0x001000100C8FFC01UL, + /* 0x0298, */ 0x001000100C8FFC01UL, + /* 0x02A0, */ 0x001000100C8FFC01UL, + /* 0x02A8, */ 0x001000100C8FFC01UL, + /* 0x02B0, */ 0x001000100C8FFC01UL, + /* 0x02B8, */ 0x001000100C8FFC01UL, + /* 0x02C0, */ 0x001000100C8FFC01UL, + /* 0x02C8, */ 0x001000100C8FFC01UL, + /* 0x02D0, */ 0x001000100C8FFC01UL, + /* 0x02D8, */ 0x001000100C8FFC01UL, + /* 0x02E0, */ 0x001000100C8FFC01UL, + /* 0x02E8, */ 0x001000100C8FFC01UL, + /* 0x02F0, */ 0x001000200C8FFC01UL, + /* 0x02F8, */ 0x001000300C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001000200C8FFC01UL, + /* 0x0310, */ 0x001000300C8FFC01UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x001000200C8FFC01UL, + /* 0x0328, */ 0x001000300C8FFC01UL, + /* 0x0330, */ 0x001000200C8FFC01UL, + /* 0x0338, */ 0x001000300C8FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c new file mode 100644 index 0000000..329bcb8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v11.h" + +#define RCAR_QOS_VERSION "rev.0.37" + +#include "qos_init_h3_v11_mstat.h" + +struct rcar_gen3_dbsc_qos_settings h3_v11_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00044218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + /* DBSC_DBCAM0CNF3 not set */ + { DBSC_DBSCHCNT0, 0x080F0037 }, + { DBSC_DBSCHCNT1, 0x00001010 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x0000F000 }, + { DBSC_DBSCHQOS01, 0x0000E000 }, + { DBSC_DBSCHQOS02, 0x00007000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000E00 }, + { DBSC_DBSCHQOS41, 0x00000DFF }, + { DBSC_DBSCHQOS42, 0x00000400 }, + { DBSC_DBSCHQOS43, 0x00000200 }, + { DBSC_DBSCHQOS90, 0x00000C00 }, + { DBSC_DBSCHQOS91, 0x00000BFF }, + { DBSC_DBSCHQOS92, 0x00000400 }, + { DBSC_DBSCHQOS93, 0x00000200 }, + { DBSC_DBSCHQOS130, 0x00000980 }, + { DBSC_DBSCHQOS131, 0x0000097F }, + { DBSC_DBSCHQOS132, 0x00000300 }, + { DBSC_DBSCHQOS133, 0x00000180 }, + { DBSC_DBSCHQOS140, 0x00000800 }, + { DBSC_DBSCHQOS141, 0x000007FF }, + { DBSC_DBSCHQOS142, 0x00000300 }, + { DBSC_DBSCHQOS143, 0x00000180 }, + { DBSC_DBSCHQOS150, 0x000007D0 }, + { DBSC_DBSCHQOS151, 0x000007CF }, + { DBSC_DBSCHQOS152, 0x000005D0 }, + { DBSC_DBSCHQOS153, 0x000003D0 }, +}; + +void qos_init_h3_v11(void) +{ + rcar_qos_dbsc_setting(h3_v11_qos, ARRAY_SIZE(h3_v11_qos), false); + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0xA8A90000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00000000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* AR Cache setting */ + io_write_32(0xE67D1000U, 0x00000100U); + io_write_32(0xE67D1008U, 0x00000100U); + + /* Resource Alloc setting */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + io_write_32(QOSCTRL_RAS, 0x00000020U); +#else + io_write_32(QOSCTRL_RAS, 0x00000040U); +#endif + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + io_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + io_write_32(QOSCTRL_DANT, 0x00181008U); +#else + io_write_64(QOSCTRL_DANN, 0x0101000004040401UL); + io_write_32(QOSCTRL_DANT, 0x003C2010U); +#endif + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x0000003FU); + io_write_32(0xFD821800U, 0x0000003FU); + io_write_32(0xFD822800U, 0x0000003FU); + io_write_32(0xFD823800U, 0x0000003FU); + io_write_32(0xFD824800U, 0x0000003FU); + io_write_32(0xFD825800U, 0x0000003FU); + io_write_32(0xFD826800U, 0x0000003FU); + io_write_32(0xFD827800U, 0x0000003FU); + + /* VIO bus Leaf setting */ + io_write_32(0xFEB89800, 0x00000001U); + io_write_32(0xFEB8A800, 0x00000001U); + io_write_32(0xFEB8B800, 0x00000001U); + io_write_32(0xFEB8C800, 0x00000001U); + + /* HSC bus Leaf setting */ + io_write_32(0xE6430800, 0x00000001U); + io_write_32(0xE6431800, 0x00000001U); + io_write_32(0xE6432800, 0x00000001U); + io_write_32(0xE6433800, 0x00000001U); + + /* MP bus Leaf setting */ + io_write_32(0xEC620800, 0x00000001U); + io_write_32(0xEC621800, 0x00000001U); + + /* PERIE bus Leaf setting */ + io_write_32(0xE7760800, 0x00000001U); + io_write_32(0xE7768800, 0x00000001U); + + /* PERIW bus Leaf setting */ + io_write_32(0xE6760800, 0x00000001U); + io_write_32(0xE6768800, 0x00000001U); + + /* RT bus Leaf setting */ + io_write_32(0xFFC50800, 0x00000001U); + io_write_32(0xFFC51800, 0x00000001U); + + /* CCI bus Leaf setting */ + uint32_t modemr = io_read_32(RCAR_MODEMR); + + modemr &= MODEMR_BOOT_CPU_MASK; + + if ((modemr == MODEMR_BOOT_CPU_CA57) || + (modemr == MODEMR_BOOT_CPU_CA53)) { + io_write_32(0xF1300800, 0x00000001U); + io_write_32(0xF1340800, 0x00000001U); + io_write_32(0xF1380800, 0x00000001U); + io_write_32(0xF13C0800, 0x00000001U); + } + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 v1.* */ +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h new file mode 100644 index 0000000..3faeb4f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V11_H +#define QOS_INIT_H3_V11_H + +void qos_init_h3_v11(void); + +#endif /* QOS_INIT_H3_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h new file mode 100644 index 0000000..46c68c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001008060000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C0C0000FFFFUL, + /* 0x0060, */ 0x00140C0C0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001008060000FFFFUL, + /* 0x0080, */ 0x001004020000FFFFUL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x00140C0C0000FFFFUL, + /* 0x0098, */ 0x001408080000FFFFUL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x001010080000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x000C04030000FFFFUL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x001010080000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x000C100E0000FFFFUL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008050000FFFFUL, + /* 0x0140, */ 0x001008050000FFFFUL, + /* 0x0148, */ 0x001008050000FFFFUL, + /* 0x0150, */ 0x001008050000FFFFUL, + /* 0x0158, */ 0x001008050000FFFFUL, + /* 0x0160, */ 0x001008050000FFFFUL, + /* 0x0168, */ 0x001008050000FFFFUL, + /* 0x0170, */ 0x001008050000FFFFUL, + /* 0x0178, */ 0x001004030000FFFFUL, + /* 0x0180, */ 0x001004030000FFFFUL, + /* 0x0188, */ 0x001004030000FFFFUL, + /* 0x0190, */ 0x001014140000FFFFUL, + /* 0x0198, */ 0x001014140000FFFFUL, + /* 0x01A0, */ 0x001008050000FFFFUL, + /* 0x01A8, */ 0x001008050000FFFFUL, + /* 0x01B0, */ 0x001008050000FFFFUL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x001100100C803401UL, + /* 0x0028, */ 0x001100100C80FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x001100100C803401UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x001100100C803401UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x001100100C803401UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x001100100C803401UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x001100100C803401UL, + /* 0x01C0, */ 0x001100800C8FFC01UL, + /* 0x01C8, */ 0x001100800C8FFC01UL, + /* 0x01D0, */ 0x001100800C8FFC01UL, + /* 0x01D8, */ 0x001100800C8FFC01UL, + /* 0x01E0, */ 0x001100100C80FC01UL, + /* 0x01E8, */ 0x001200100C80FC01UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x001100100C803401UL, + /* 0x0200, */ 0x001100100C80FC01UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x001100100C803401UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100200C8FFC01UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100200C8FFC01UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x001100100C803401UL, + /* 0x0288, */ 0x001100100C803401UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x001100100C803401UL, + /* 0x02C8, */ 0x001100100C803401UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x001100100C803401UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x001100300C8FFC01UL, + /* 0x0328, */ 0x001100500C8FFC01UL, + /* 0x0330, */ 0x001100300C8FFC01UL, + /* 0x0338, */ 0x001100500C8FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c new file mode 100644 index 0000000..c20ab08 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v20.h" + +#define RCAR_QOS_VERSION "rev.0.21" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_20 (SL_INIT_SSLOTCLK_H3_20 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3_20 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_20) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3_20 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_20) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v20_mstat195.h" +#else +#include "qos_init_h3_v20_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v20_qoswt195.h" +#else +#include "qos_init_h3_v20_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3_v20_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3_v20(void) +{ + rcar_qos_dbsc_setting(h3_v20_qos, ARRAY_SIZE(h3_v20_qos), true); + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch\n"); + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0x00001054U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1BU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404010002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3_20); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_20 << 16))); +#else + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + io_write_32(GPU_ACT4, 0x00000000U); + io_write_32(GPU_ACT5, 0x00000000U); + io_write_32(GPU_ACT6, 0x00000000U); + io_write_32(GPU_ACT7, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3_20 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3_20 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h new file mode 100644 index 0000000..9b7619e --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V20_H +#define QOS_INIT_H3_V20_H + +void qos_init_h3_v20(void); + +#endif /* QOS_INIT_H3_V20_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h new file mode 100644 index 0000000..3995df3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424110000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001410100000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008070000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424110000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C08070000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C10100000FFFFUL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100700BDFFC01UL, + /* 0x01c8, */ 0x002100700BDFFC01UL, + /* 0x01d0, */ 0x002100700BDFFC01UL, + /* 0x01d8, */ 0x002100700BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100400BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100400BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h new file mode 100644 index 0000000..770c022 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x001444210000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014201F0000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0010100D0000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001444210000FFFFUL, + /* 0x0090, */ 0x00141C190000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C20200000FFFFUL, + /* 0x0120, */ 0x000C20200000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100D005EFFC01UL, + /* 0x01c8, */ 0x002100D005EFFC01UL, + /* 0x01d0, */ 0x002100D005EFFC01UL, + /* 0x01d8, */ 0x002100D005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011007005EFFC01UL, + /* 0x0328, */ 0x001100B005EFFC01UL, + /* 0x0330, */ 0x0011007005EFFC01UL, + /* 0x0338, */ 0x001100B005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h new file mode 100644 index 0000000..82e4b01 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424110000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001410100000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008070000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424110000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h new file mode 100644 index 0000000..f3e7360 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x001444210000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014201F0000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0010100D0000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001444210000FFF0UL, + /* 0x0090, */ 0x00141C190000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c new file mode 100644 index 0000000..1fe6182 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3_v30.h" + +#define RCAR_QOS_VERSION "rev.0.11" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_30 (SL_INIT_SSLOTCLK_H3_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3_30 (QOSWT_WTSET0_PERIOD0_H3_30) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v30_mstat195.h" +#else +#include "qos_init_h3_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3_v30_qoswt195.h" +#else +#include "qos_init_h3_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3_v30(void) +{ + unsigned int split_area; + + rcar_qos_dbsc_setting(h3_v30_qos, ARRAY_SIZE(h3_v30_qos), true); + +#if RCAR_DRAM_LPDDR4_MEMCONF == 0 /* 1GB */ + split_area = 0x1BU; +#else /* default 2GB */ + split_area = 0x1CU; +#endif + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 4ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR1, 0x00000000U); + io_write_32(AXI_ADSPLCR2, 0x00001054U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#elif RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404010002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3_30); + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3_30 << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + io_write_32(AXI_MMCR, 0x00010008U); + io_write_32(AXI_TR3CR, 0x00010000U); + io_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3_30 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3_30 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h new file mode 100644 index 0000000..d33b43c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3_V30_H +#define QOS_INIT_H3_V30_H + +void qos_init_h3_v30(void); + +#endif /* QOS_INIT_H3_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h new file mode 100644 index 0000000..28a240f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008070000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h new file mode 100644 index 0000000..def6585 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0010100D0000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x00141C190000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h new file mode 100644 index 0000000..b0c11cc --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008070000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h new file mode 100644 index 0000000..a1e4c72 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0010100D0000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x00141C190000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c new file mode 100644 index 0000000..f1ee41b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2018-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_h3n_v30.h" + +#define RCAR_QOS_VERSION "rev.0.07" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3N (SL_INIT_SSLOTCLK_H3N - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_H3N \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_H3N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_H3N (QOSWT_WTSET0_PERIOD0_H3N) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3n_v30_mstat195.h" +#else +#include "qos_init_h3n_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_h3n_v30_qoswt195.h" +#else +#include "qos_init_h3n_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + +#endif + +struct rcar_gen3_dbsc_qos_settings h3n_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_h3n_v30(void) +{ + unsigned int split_area; + + rcar_qos_dbsc_setting(h3n_v30_qos, ARRAY_SIZE(h3n_v30_qos), true); + + /* use 1(2GB) for RCAR_DRAM_LPDDR4_MEMCONF for H3N */ + split_area = 0x1CU; + + /* DRAM Split Address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) +#if RCAR_LSI == RCAR_H3N +#error "Don't set DRAM Split 4ch(H3N)" +#else + ERROR("DRAM Split 4ch not supported.(H3N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(split_area) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + io_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_H3N); + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_H3N << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + io_write_32(AXI_MMCR, 0x00010008U); + io_write_32(AXI_TR3CR, 0x00010000U); + io_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_H3N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_H3N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h new file mode 100644 index 0000000..46f3440 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H3N_V30_H +#define QOS_INIT_H3N_V30_H + +void qos_init_h3n_v30(void); + +#endif /* QOS_INIT_H3N_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h new file mode 100644 index 0000000..6dbc88a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h new file mode 100644 index 0000000..880211c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h new file mode 100644 index 0000000..affd013 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h new file mode 100644 index 0000000..1c48d28 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c new file mode 100644 index 0000000..a8264cb --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v10.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#include "qos_init_m3_v10_mstat.h" + +struct rcar_gen3_dbsc_qos_settings m3_v10_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x080F0037 }, + /* DBSC_DBSCHCNT1 not set */ + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000300 }, + { DBSC_DBSCHQOS91, 0x000002F0 }, + { DBSC_DBSCHQOS92, 0x00000200 }, + { DBSC_DBSCHQOS93, 0x00000100 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v10(void) +{ + rcar_qos_dbsc_setting(m3_v10_qos, ARRAY_SIZE(m3_v10_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3 +#error "Don't set DRAM Split 4ch(M3)" +#else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1CU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x089A0000U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000028U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000000U); + io_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_EC, 0x00000000U); + io_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + io_write_32(QOSCTRL_FSS, 0x000003e8U); + io_write_32(QOSCTRL_INSFC, 0xC7840001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + io_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + io_write_32(0xFD820808U, 0x00001234U); + io_write_32(0xFD820800U, 0x00000006U); + io_write_32(0xFD821800U, 0x00000006U); + io_write_32(0xFD822800U, 0x00000006U); + io_write_32(0xFD823800U, 0x00000006U); + io_write_32(0xFD824800U, 0x00000006U); + io_write_32(0xFD825800U, 0x00000006U); + io_write_32(0xFD826800U, 0x00000006U); + io_write_32(0xFD827800U, 0x00000006U); + + /* RT bus Leaf setting */ + io_write_32(0xFFC50800U, 0x00000000U); + io_write_32(0xFFC51800U, 0x00000000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h new file mode 100644 index 0000000..01ef46c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3_V10_H +#define QOS_INIT_M3_V10_H + +void qos_init_m3_v10(void); + +#endif /* QOS_INIT_M3_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h new file mode 100644 index 0000000..b78b5f1 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001004030000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C090000FFFFUL, + /* 0x0060, */ 0x00140C090000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001004020000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C0A0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008050000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001028280000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x00100C0A0000FFFFUL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001100100C803401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x001100500C8FFC01UL, + /* 0x01C8, */ 0x001100500C8FFC01UL, + /* 0x01D0, */ 0x001100500C8FFC01UL, + /* 0x01D8, */ 0x001100500C8FFC01UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x001200100C803401UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100100C8EA401UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100100C8EA401UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c new file mode 100644 index 0000000..22fd83a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v11.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_11 (SL_INIT_SSLOTCLK_M3_11 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_11) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_11) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v11_mstat195.h" +#else +#include "qos_init_m3_v11_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v11_qoswt195.h" +#else +#include "qos_init_m3_v11_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3_v11_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS120, 0x00000040 }, + { DBSC_DBSCHQOS121, 0x00000030 }, + { DBSC_DBSCHQOS122, 0x00000020 }, + { DBSC_DBSCHQOS123, 0x00000010 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v11(void) +{ + rcar_qos_dbsc_setting(m3_v11_qos, ARRAY_SIZE(m3_v11_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3 +#error "Don't set DRAM Split 4ch(M3)" +#else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1CU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_M3_11); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + io_write_32(QOSCTRL_REF_ARS, + ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_11 << 16))); +#else + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + io_write_32(GPU_ACT_GRD, 0x00001234U); + io_write_32(GPU_ACT0, 0x00000000U); + io_write_32(GPU_ACT1, 0x00000000U); + io_write_32(GPU_ACT2, 0x00000000U); + io_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_M3_11 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_M3_11 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h new file mode 100644 index 0000000..1552fb6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3_V11_H +#define QOS_INIT_M3_V11_H + +void qos_init_m3_v11(void); + +#endif /* QOS_INIT_M3_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h new file mode 100644 index 0000000..d7e7777 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C14120000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h new file mode 100644 index 0000000..a9520c3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C24230000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h new file mode 100644 index 0000000..04c7efd --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h new file mode 100644 index 0000000..73f81f5 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c new file mode 100644 index 0000000..43d21d7 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3_v30.h" + +#define RCAR_QOS_VERSION "rev.0.04" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30 (SL_INIT_SSLOTCLK_M3_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3_30) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v30_mstat195.h" +#else +#include "qos_init_m3_v30_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3_v30_qoswt195.h" +#else +#include "qos_init_m3_v30_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBCAM0CNF3, 0x00000000 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS120, 0x00000040 }, + { DBSC_DBSCHQOS121, 0x00000030 }, + { DBSC_DBSCHQOS122, 0x00000020 }, + { DBSC_DBSCHQOS123, 0x00000010 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3_v30(void) +{ + rcar_qos_dbsc_setting(m3_v30_qos, ARRAY_SIZE(m3_v30_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH + #if RCAR_LSI == RCAR_M3 + #error "Don't set DRAM Split 4ch(M3)" + #else + ERROR("DRAM Split 4ch not supported.(M3)"); + panic(); + #endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + io_write_32(AXI_ADSPLCR0, 0x00000000U); + io_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT + | ADSPLCR0_SPLITSEL(0xFFU) + | ADSPLCR0_AREA(0x1DU) + | ADSPLCR0_SWP); + io_write_32(AXI_ADSPLCR2, 0x00001004U); + io_write_32(AXI_ADSPLCR3, 0x00000000U); +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000044U); + io_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + io_write_32(QOSCTRL_DANT, 0x0020100AU); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000001U); + io_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + /* GPU Boost Mode */ + io_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + io_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_M3_30); + io_write_32(QOSCTRL_REF_ARS, ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_M3_30 << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + io_write_32(CPU_ACT2, 0x00000003U); + io_write_32(CPU_ACT3, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, ((QOSWT_WTSET0_PERIOD0_M3_30 << 16) | (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, ((QOSWT_WTSET1_PERIOD1_M3_30 << 16) | (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h new file mode 100644 index 0000000..a89d512 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_M3_V30__ +#define QOS_INIT_H_M3_V30__ + +void qos_init_m3_v30(void); + +#endif /* QOS_INIT_H_M3_V30__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h new file mode 100644 index 0000000..2ab14da --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C10100000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h new file mode 100644 index 0000000..faac3d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C201F0000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C201F0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h new file mode 100644 index 0000000..6761f5d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h new file mode 100644 index 0000000..1deed59 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h @@ -0,0 +1,225 @@ +/* + * Copyright (c) 2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c new file mode 100644 index 0000000..446340b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c @@ -0,0 +1,203 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_m3n_v10.h" + +#define RCAR_QOS_VERSION "rev.0.09" + +#define REF_ARS_ARBSTOPCYCLE_M3N \ + (((SL_INIT_SSLOTCLK_M3N) - 5U) << 16U) + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN QOSWT_WTREF_SLOT0_EN + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_M3N \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_M3N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_M3N QOSWT_WTSET0_PERIOD0_M3N +#define QOSWT_WTSET1_SSLOT1 QOSWT_WTSET0_SSLOT0 +#define QOSWT_WTSET1_SLOTSLOT1 QOSWT_WTSET0_SLOTSLOT0 + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3n_v10_mstat195.h" +#else +#include "qos_init_m3n_v10_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_m3n_v10_qoswt195.h" +#else +#include "qos_init_m3n_v10_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +struct rcar_gen3_dbsc_qos_settings m3n_v10_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x000F0037 }, + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00 }, + { DBSC_DBSCHQOS01, 0x00000B00 }, + { DBSC_DBSCHQOS02, 0x00000000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x00000300 }, + { DBSC_DBSCHQOS41, 0x000002F0 }, + { DBSC_DBSCHQOS42, 0x00000200 }, + { DBSC_DBSCHQOS43, 0x00000100 }, + { DBSC_DBSCHQOS90, 0x00000100 }, + { DBSC_DBSCHQOS91, 0x000000F0 }, + { DBSC_DBSCHQOS92, 0x000000A0 }, + { DBSC_DBSCHQOS93, 0x00000040 }, + { DBSC_DBSCHQOS130, 0x00000100 }, + { DBSC_DBSCHQOS131, 0x000000F0 }, + { DBSC_DBSCHQOS132, 0x000000A0 }, + { DBSC_DBSCHQOS133, 0x00000040 }, + { DBSC_DBSCHQOS140, 0x000000C0 }, + { DBSC_DBSCHQOS141, 0x000000B0 }, + { DBSC_DBSCHQOS142, 0x00000080 }, + { DBSC_DBSCHQOS143, 0x00000040 }, + { DBSC_DBSCHQOS150, 0x00000040 }, + { DBSC_DBSCHQOS151, 0x00000030 }, + { DBSC_DBSCHQOS152, 0x00000020 }, + { DBSC_DBSCHQOS153, 0x00000010 }, +}; + +void qos_init_m3n_v10(void) +{ + rcar_qos_dbsc_setting(m3n_v10_qos, ARRAY_SIZE(m3n_v10_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_M3N +#error "Don't set DRAM Split 4ch(M3N)" +#else + ERROR("DRAM Split 4ch not supported.(M3N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_M3N +#error "Don't set DRAM Split 2ch(M3N)" +#else + ERROR("DRAM Split 2ch not supported.(M3N)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_RAS, 0x00000028U); + io_write_64(QOSCTRL_DANN, 0x0402000002020201UL); + io_write_32(QOSCTRL_DANT, 0x00100804U); + io_write_32(QOSCTRL_FSS, 0x0000000AU); + io_write_32(QOSCTRL_INSFC, 0x06330001U); + io_write_32(QOSCTRL_EARLYR, 0x00000001U); + io_write_32(QOSCTRL_RACNT0, 0x00010003U); + + io_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_M3N); + io_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_M3N); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + io_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8, + qoswt_fix[i]); + io_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8, + qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + io_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8, qoswt_be[i]); + io_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + io_write_32(RT_ACT0, 0x00000000U); + io_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + io_write_32(CPU_ACT0, 0x00000003U); + io_write_32(CPU_ACT1, 0x00000003U); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + io_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + io_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_M3N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + io_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_M3N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + io_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + io_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + io_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h new file mode 100644 index 0000000..0cd0c85 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_M3N_V10_H +#define QOS_INIT_M3N_V10_H + +void qos_init_m3n_v10(void); + +#endif /* QOS_INIT_M3N_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h new file mode 100644 index 0000000..9b8b9e9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000FFFFUL, + /* 0x0038, */ 0x001004320000FFFFUL, + /* 0x0040, */ 0x00140C5D0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404040000FFFFUL, + /* 0x0058, */ 0x00140C940000FFFFUL, + /* 0x0060, */ 0x00140C940000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404040000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C041D0000FFFFUL, + /* 0x00a8, */ 0x000C04090000FFFFUL, + /* 0x00b0, */ 0x000C040B0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C041D0000FFFFUL, + /* 0x00c8, */ 0x000C04090000FFFFUL, + /* 0x00d0, */ 0x000C040B0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024840000FFFFUL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C840000FFFFUL, + /* 0x0118, */ 0x000C21E60000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001010C90000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D9D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04050000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04050000FFFFUL, + /* 0x0210, */ 0x000C04050000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFFFUL, + /* 0x0268, */ 0x001408020000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04090000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04050000FFFFUL, + /* 0x02a8, */ 0x000C04050000FFFFUL, + /* 0x02b0, */ 0x001408050000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04050000FFFFUL, + /* 0x02d8, */ 0x000C04050000FFFFUL, + /* 0x02e0, */ 0x001408050000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04010000FFFFUL, + /* 0x0378, */ 0x000C04010000FFFFUL, + /* 0x0380, */ 0x000C04050000FFFFUL, + /* 0x0388, */ 0x000C04050000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002106000BDFFC01UL, + /* 0x01c8, */ 0x002106000BDFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002101000BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002101000BDF2401UL, + /* 0x0218, */ 0x001101000BDF2401UL, + /* 0x0220, */ 0x001101000BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001101000BDF2401UL, + /* 0x0238, */ 0x001101000BDF2401UL, + /* 0x0240, */ 0x001201000BDF2401UL, + /* 0x0248, */ 0x001101000BDF2401UL, + /* 0x0250, */ 0x001201000BDF2401UL, + /* 0x0258, */ 0x001101000BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001106000BDFFC01UL, + /* 0x02f8, */ 0x001106000BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x001206000BDFFC01UL, + /* 0x0360, */ 0x001206000BDFFC01UL, + /* 0x0368, */ 0x001200100BD03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x001200100BD03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h new file mode 100644 index 0000000..19143ed --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000FFFFUL, + /* 0x0038, */ 0x001008630000FFFFUL, + /* 0x0040, */ 0x001418BA0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404070000FFFFUL, + /* 0x0058, */ 0x001415270000FFFFUL, + /* 0x0060, */ 0x001415270000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404070000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08390000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08390000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001045080000FFFFUL, + /* 0x00f8, */ 0x000C0C9E0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001015080000FFFFUL, + /* 0x0118, */ 0x000C43CB0000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0010194A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101D910000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0010194A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100CA50000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037390000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0010194A0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x00140C090000FFFFUL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x00140C090000FFFFUL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005EFFC01UL, + /* 0x01c8, */ 0x0021060005EFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005E79401UL, + /* 0x0218, */ 0x0011010005E79401UL, + /* 0x0220, */ 0x0011010005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005E79401UL, + /* 0x0238, */ 0x0011010005E79401UL, + /* 0x0240, */ 0x0012010005E79401UL, + /* 0x0248, */ 0x0011010005E79401UL, + /* 0x0250, */ 0x0012010005E79401UL, + /* 0x0258, */ 0x0011010005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005EFFC01UL, + /* 0x02f8, */ 0x0011060005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005EFFC01UL, + /* 0x0360, */ 0x0012060005EFFC01UL, + /* 0x0368, */ 0x0012001005E03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005E03401UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h new file mode 100644 index 0000000..d2e8040 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000C010UL, + /* 0x0038, */ 0x001004320000C010UL, + /* 0x0040, */ 0x00140C5D0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C940000C010UL, + /* 0x0060, */ 0x00140C940000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFF0UL, + /* 0x0268, */ 0x001408020000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04090000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h new file mode 100644 index 0000000..84f657a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000C010UL, + /* 0x0038, */ 0x001008630000C010UL, + /* 0x0040, */ 0x001418BA0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415270000C010UL, + /* 0x0060, */ 0x001415270000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFF0UL, + /* 0x0268, */ 0x001410040000FFF0UL, + /* 0x0270, */ 0x001404020000FFF0UL, + /* 0x0278, */ 0x000C08110000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFF0UL, + /* 0x0298, */ 0x001404020000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c new file mode 100644 index 0000000..076876c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "../qos_common.h" +#include "../qos_reg.h" +#include "qos_init_v3m.h" + +#define RCAR_QOS_VERSION "rev.0.01" + +#include "qos_init_v3m_mstat.h" + +struct rcar_gen3_dbsc_qos_settings v3m_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00044218 }, + { DBSC_DBCAM0CNF2, 0x000000F4 }, + { DBSC_DBSCHCNT0, 0x080F003F }, + { DBSC_DBSCHCNT1, 0x00001010 }, + + { DBSC_DBSCHSZ0, 0x00000001 }, + { DBSC_DBSCHRW0, 0x22421111 }, + { DBSC_DBSCHRW1, 0x00180034 }, + { DBSC_SCFCTST0, 0x180B1708 }, + { DBSC_SCFCTST1, 0x0808070C }, + { DBSC_SCFCTST2, 0x012F1123 }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x0000F000 }, + { DBSC_DBSCHQOS01, 0x0000E000 }, + { DBSC_DBSCHQOS02, 0x00007000 }, + { DBSC_DBSCHQOS03, 0x00000000 }, + { DBSC_DBSCHQOS40, 0x0000F000 }, + { DBSC_DBSCHQOS41, 0x0000EFFF }, + { DBSC_DBSCHQOS42, 0x0000B000 }, + { DBSC_DBSCHQOS43, 0x00000000 }, + { DBSC_DBSCHQOS90, 0x0000F000 }, + { DBSC_DBSCHQOS91, 0x0000EFFF }, + { DBSC_DBSCHQOS92, 0x0000D000 }, + { DBSC_DBSCHQOS93, 0x00000000 }, + { DBSC_DBSCHQOS130, 0x0000F000 }, + { DBSC_DBSCHQOS131, 0x0000EFFF }, + { DBSC_DBSCHQOS132, 0x0000E800 }, + { DBSC_DBSCHQOS133, 0x00007000 }, + { DBSC_DBSCHQOS140, 0x0000F000 }, + { DBSC_DBSCHQOS141, 0x0000EFFF }, + { DBSC_DBSCHQOS142, 0x0000E800 }, + { DBSC_DBSCHQOS143, 0x0000B000 }, + { DBSC_DBSCHQOS150, 0x000007D0 }, + { DBSC_DBSCHQOS151, 0x000007CF }, + { DBSC_DBSCHQOS152, 0x000005D0 }, + { DBSC_DBSCHQOS153, 0x000003D0 }, +}; + +void qos_init_v3m(void) +{ +return; + + rcar_qos_dbsc_setting(v3m_qos, ARRAY_SIZE(v3m_qos), false); + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + io_write_32(QOSCTRL_RAS, 0x00000020U); + io_write_32(QOSCTRL_FIXTH, 0x000F0005U); + io_write_32(QOSCTRL_REGGD, 0x00000004U); + io_write_64(QOSCTRL_DANN, 0x0202020104040200U); + io_write_32(QOSCTRL_DANT, 0x00201008U); + io_write_32(QOSCTRL_EC, 0x00080001U); /* need for H3 ES1 */ + io_write_64(QOSCTRL_EMS, 0x0000000000000000U); + io_write_32(QOSCTRL_INSFC, 0x63C20001U); + io_write_32(QOSCTRL_BERR, 0x00000000U); + + /* QOSBW setting */ + io_write_32(QOSCTRL_SL_INIT, 0x0305007DU); + io_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + io_write_64(QOSBW_FIX_QOS_BANK0 + i * 8, mstat_fix[i]); + io_write_64(QOSBW_FIX_QOS_BANK1 + i * 8, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + io_write_64(QOSBW_BE_QOS_BANK0 + i * 8, mstat_be[i]); + io_write_64(QOSBW_BE_QOS_BANK1 + i * 8, mstat_be[i]); + } + + /* AXI-IF arbitration setting */ + io_write_32(DBSC_AXARB, 0x18010000U); + + /* Resource Alloc start */ + io_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + io_write_32(QOSCTRL_STATQC, 0x00000001U); + +#else + NOTICE("BL2: QoS is None\n"); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h new file mode 100644 index 0000000..2c4278b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H_V3M__ +#define QOS_INIT_H_V3M__ + +void qos_init_v3m(void); + +#endif /* QOS_INIT_H_V3M__ */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h new file mode 100644 index 0000000..d0b7fc3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x000000000000FFFFUL, + /* 0x0008, */ 0x000000000000FFFFUL, + /* 0x0010, */ 0x000000000000FFFFUL, + /* 0x0018, */ 0x000000000000FFFFUL, + /* 0x0020, */ 0x001414090000FFFFUL, + /* 0x0028, */ 0x000C00000000FFFFUL, + /* 0x0030, */ 0x001008040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001004040000FFFFUL, + /* 0x0048, */ 0x000000000000FFFFUL, + /* 0x0050, */ 0x001004040000FFFFUL, + /* 0x0058, */ 0x001004040000FFFFUL, + /* 0x0060, */ 0x000000000000FFFFUL, + /* 0x0068, */ 0x001404040000FFFFUL, + /* 0x0070, */ 0x001008030000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x001004030000FFFFUL, + /* 0x0088, */ 0x000000000000FFFFUL, + /* 0x0090, */ 0x001004040000FFFFUL, + /* 0x0098, */ 0x001004040000FFFFUL, + /* 0x00A0, */ 0x000000000000FFFFUL, + /* 0x00A8, */ 0x000000000000FFFFUL, + /* 0x00B0, */ 0x000000000000FFFFUL, + /* 0x00B8, */ 0x000000000000FFFFUL, + /* 0x00C0, */ 0x000000000000FFFFUL, + /* 0x00C8, */ 0x000000000000FFFFUL, + /* 0x00D0, */ 0x000000000000FFFFUL, + /* 0x00D8, */ 0x000000000000FFFFUL, + /* 0x00E0, */ 0x001404020000FFFFUL, + /* 0x00E8, */ 0x000000000000FFFFUL, + /* 0x00F0, */ 0x000000000000FFFFUL, + /* 0x00F8, */ 0x000000000000FFFFUL, + /* 0x0100, */ 0x000000000000FFFFUL, + /* 0x0108, */ 0x000C04020000FFFFUL, + /* 0x0110, */ 0x000000000000FFFFUL, + /* 0x0118, */ 0x001404020000FFFFUL, + /* 0x0120, */ 0x000000000000FFFFUL, + /* 0x0128, */ 0x000000000000FFFFUL, + /* 0x0130, */ 0x000000000000FFFFUL, + /* 0x0138, */ 0x000000000000FFFFUL, + /* 0x0140, */ 0x000000000000FFFFUL, + /* 0x0148, */ 0x000000000000FFFFUL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x00100020447FFC01UL, + /* 0x0008, */ 0x00100020447FFC01UL, + /* 0x0010, */ 0x00100040447FFC01UL, + /* 0x0018, */ 0x00100040447FFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x00100010447FFC01UL, + /* 0x00A8, */ 0x00100010447FFC01UL, + /* 0x00B0, */ 0x00100010447FFC01UL, + /* 0x00B8, */ 0x00100010447FFC01UL, + /* 0x00C0, */ 0x00100010447FFC01UL, + /* 0x00C8, */ 0x00100010447FFC01UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x00100010447FFC01UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x00100010447FFC01UL, + /* 0x00F0, */ 0x00100010447FFC01UL, + /* 0x00F8, */ 0x00100010447FFC01UL, + /* 0x0100, */ 0x00100010447FFC01UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100010447FFC01UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x00100010447FFC01UL, + /* 0x0128, */ 0x00100010447FFC01UL, + /* 0x0130, */ 0x00100010447FFC01UL, + /* 0x0138, */ 0x00100010447FFC01UL, + /* 0x0140, */ 0x00100020447FFC01UL, + /* 0x0148, */ 0x00100020447FFC01UL, +}; +#endif diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk new file mode 100644 index 0000000..da10da2 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos.mk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) +# E3, H3N not available for LSI_AUTO + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RCAR_H3}) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/qos/D3/qos_init_d3.c + endif +else + ifeq (${RCAR_LSI},${RCAR_H3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c + else ifeq (${LSI_CUT},20) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_H3N}) + ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_M3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + else ifeq (${LSI_CUT},13) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_M3N}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_V3M}) + BL2_SOURCES += drivers/renesas/rcar/qos/V3M/qos_init_v3m.c + endif + ifeq (${RCAR_LSI},${RCAR_E3}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c + endif + endif + ifeq (${RCAR_LSI},${RCAR_D3}) + BL2_SOURCES += drivers/renesas/rcar/qos/E3/qos_init_d3.c + endif +endif + +BL2_SOURCES += drivers/renesas/rcar/qos/qos_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h new file mode 100644 index 0000000..2c130ae --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_COMMON_H +#define QOS_COMMON_H + +#define RCAR_REF_DEFAULT 0U + +/* define used for get_refperiod. */ +/* REFPERIOD_CYCLE need smaller than QOSWT_WTSET0_CYCLEs */ +/* refere to plat/renesas/rcar/ddr/ddr_a/ddr_init_e3.h for E3. */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF default */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((126 * BASE_SUB_SLOT_NUM * 1000U) / 400) +#else /* REF option */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((252 * BASE_SUB_SLOT_NUM * 1000U) / 400) +#endif + +#if (RCAR_LSI == RCAR_E3) +/* define used for E3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_E3 0xAFU /* 175 */ +#else /* REF 7.8usec */ +#define SUB_SLOT_CYCLE_E3 0x15EU /* 350 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define OPERATING_FREQ_E3 266U /* MHz */ +#define SL_INIT_SSLOTCLK_E3 (SUB_SLOT_CYCLE_E3 - 1U) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) +/* define used for M3N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_M3N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_M3N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_M3N (SUB_SLOT_CYCLE_M3N - 1U) +#define QOSWT_WTSET0_CYCLE_M3N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) +/* define used for H3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_H3_20 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_H3_20 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_H3_20 (SUB_SLOT_CYCLE_H3_20 - 1U) +#define QOSWT_WTSET0_CYCLE_H3_20 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3_20 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +/* define used for H3 Cut 30 */ +#define SUB_SLOT_CYCLE_H3_30 (SUB_SLOT_CYCLE_H3_20) /* same as H3 Cut 20 */ +#define SL_INIT_SSLOTCLK_H3_30 (SUB_SLOT_CYCLE_H3_30 - 1U) +#define QOSWT_WTSET0_CYCLE_H3_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#endif + +#if (RCAR_LSI == RCAR_H3N) +/* define used for H3N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_H3N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_H3N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_H3N (SUB_SLOT_CYCLE_H3N - 1U) +#define QOSWT_WTSET0_CYCLE_H3N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_H3N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) +/* define used for M3 */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_M3_11 0x7EU /* 126 */ +#define SUB_SLOT_CYCLE_M3_30 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_M3_11 0xFCU /* 252 */ +#define SUB_SLOT_CYCLE_M3_30 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_M3_11 (SUB_SLOT_CYCLE_M3_11 - 1U) +#define SL_INIT_SSLOTCLK_M3_30 (SUB_SLOT_CYCLE_M3_30 - 1U) +#define QOSWT_WTSET0_CYCLE_M3_11 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3_11 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#define QOSWT_WTSET0_CYCLE_M3_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_M3_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#define OPERATING_FREQ 400U /* MHz */ +#define BASE_SUB_SLOT_NUM 0x6U +#define SUB_SLOT_CYCLE 0x7EU /* 126 */ + +#define QOSWT_WTSET0_CYCLE /* unit:ns */ \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#define SL_INIT_REFFSSLOT (0x3U << 24U) +#define SL_INIT_SLOTSSLOT ((BASE_SUB_SLOT_NUM - 1U) << 16U) +#define SL_INIT_SSLOTCLK (SUB_SLOT_CYCLE - 1U) + +static inline void io_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t *)addr = value; +} + +static inline uint32_t io_read_32(uintptr_t addr) +{ + return *(volatile uint32_t *)addr; +} + +static inline void io_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t *)addr = value; +} + +typedef struct { + uintptr_t addr; + uint64_t value; +} mstat_slot_t; + +struct rcar_gen3_dbsc_qos_settings { + uint32_t reg; + uint32_t val; +}; + +extern uint32_t qos_init_ddr_ch; +extern uint8_t qos_init_ddr_phyvalid; + +void rcar_qos_dbsc_setting(struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren); + +#endif /* QOS_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c new file mode 100644 index 0000000..d0f1730 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c @@ -0,0 +1,394 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init.h" +#include "qos_common.h" +#include "qos_reg.h" +#include "rcar_def.h" +#if RCAR_LSI == RCAR_AUTO +#include "H3/qos_init_h3_v10.h" +#include "H3/qos_init_h3_v11.h" +#include "H3/qos_init_h3_v20.h" +#include "H3/qos_init_h3_v30.h" +#include "M3/qos_init_m3_v10.h" +#include "M3/qos_init_m3_v11.h" +#include "M3/qos_init_m3_v30.h" +#include "M3N/qos_init_m3n_v10.h" +#include "V3M/qos_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_H3 /* H3 */ +#include "H3/qos_init_h3_v10.h" +#include "H3/qos_init_h3_v11.h" +#include "H3/qos_init_h3_v20.h" +#include "H3/qos_init_h3_v30.h" +#endif +#if RCAR_LSI == RCAR_H3N /* H3 */ +#include "H3/qos_init_h3n_v30.h" +#endif +#if RCAR_LSI == RCAR_M3 /* M3 */ +#include "M3/qos_init_m3_v10.h" +#include "M3/qos_init_m3_v11.h" +#include "M3/qos_init_m3_v30.h" +#endif +#if RCAR_LSI == RCAR_M3N /* M3N */ +#include "M3N/qos_init_m3n_v10.h" +#endif +#if RCAR_LSI == RCAR_V3M /* V3M */ +#include "V3M/qos_init_v3m.h" +#endif +#if RCAR_LSI == RCAR_E3 /* E3 */ +#include "E3/qos_init_e3_v10.h" +#endif +#if RCAR_LSI == RCAR_D3 /* D3 */ +#include "D3/qos_init_d3.h" +#endif + +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) + +#define DRAM_CH_CNT 0x04 +uint32_t qos_init_ddr_ch; +uint8_t qos_init_ddr_phyvalid; +#endif + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } while (0) + +void rcar_qos_init(void) +{ + uint32_t reg; +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) + uint32_t i; + + qos_init_ddr_ch = 0; + qos_init_ddr_phyvalid = get_boardcnf_phyvalid(); + for (i = 0; i < DRAM_CH_CNT; i++) { + if ((qos_init_ddr_phyvalid & (1 << i))) { + qos_init_ddr_ch++; + } + } +#endif + + reg = mmio_read_32(PRR); +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_H3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_h3_v10(); + break; + case PRR_PRODUCT_11: + qos_init_h3_v11(); + break; + case PRR_PRODUCT_20: + qos_init_h3_v20(); + break; + case PRR_PRODUCT_30: + default: + qos_init_h3_v30(); + break; + } +#elif (RCAR_LSI == RCAR_H3N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + qos_init_h3n_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_M3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_m3_v10(); + break; + case PRR_PRODUCT_21: /* M3 Cut 13 */ + qos_init_m3_v11(); + break; + case PRR_PRODUCT_30: /* M3 Cut 30 */ + default: + qos_init_m3_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_M3N: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_m3n_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_V3M: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_V3M) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + case PRR_PRODUCT_20: + default: + qos_init_v3m(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_E3: +#if (RCAR_LSI == RCAR_E3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_e3_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + case PRR_PRODUCT_D3: +#if (RCAR_LSI == RCAR_D3) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_d3(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } +#else +#if RCAR_LSI == RCAR_H3 /* H3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Cut 10 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Cut 11 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_11) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_20 + /* H3 Cut 20 */ + if ((PRR_PRODUCT_H3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v20(); +#else + /* H3 Cut 30 or later */ + if ((PRR_PRODUCT_H3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3_v30(); +#endif +#elif RCAR_LSI == RCAR_H3N /* H3 */ + /* H3N Cut 30 or later */ + if ((PRR_PRODUCT_H3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_h3n_v30(); +#elif RCAR_LSI == RCAR_M3 /* M3 */ +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* M3 Cut 10 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* M3 Cut 11 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_13 + /* M3 Cut 13 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_21) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v11(); +#else + /* M3 Cut 30 or later */ + if ((PRR_PRODUCT_M3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3_v30(); +#endif +#elif RCAR_LSI == RCAR_M3N /* M3N */ + /* M3N Cut 10 or later */ + if ((PRR_PRODUCT_M3N) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_m3n_v10(); +#elif RCAR_LSI == RCAR_V3M /* V3M */ + /* V3M Cut 10 or later */ + if ((PRR_PRODUCT_V3M) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_v3m(); +#elif RCAR_LSI == RCAR_D3 /* D3 */ + /* D3 Cut 10 or later */ + if ((PRR_PRODUCT_D3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_d3(); +#elif RCAR_LSI == RCAR_E3 /* E3 */ + /* E3 Cut 10 or later */ + if ((PRR_PRODUCT_E3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_e3_v10(); +#else +#error "Don't have QoS initialize routine(Unknown chip)." +#endif +#endif +} + +#if (RCAR_LSI != RCAR_E3) && (RCAR_LSI != RCAR_D3) && (RCAR_LSI != RCAR_V3M) +uint32_t get_refperiod(void) +{ + uint32_t refperiod = QOSWT_WTSET0_CYCLE; + +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + uint32_t reg; + + reg = mmio_read_32(PRR); + switch (reg & PRR_PRODUCT_MASK) { +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_H3) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + case PRR_PRODUCT_11: + break; + case PRR_PRODUCT_20: + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#elif (RCAR_LSI == RCAR_H3N) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3) + case PRR_PRODUCT_M3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + break; + case PRR_PRODUCT_20: /* M3 Cut 11 */ + case PRR_PRODUCT_21: /* M3 Cut 13 */ + case PRR_PRODUCT_30: /* M3 Cut 30 */ + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RCAR_M3N) + case PRR_PRODUCT_M3N: + refperiod = REFPERIOD_CYCLE; + break; +#endif + default: + break; + } +#elif RCAR_LSI == RCAR_H3 +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* H3 Cut 10 */ +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* H3 Cut 11 */ +#else + /* H3 Cut 20 */ + /* H3 Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif +#elif RCAR_LSI == RCAR_H3N + /* H3N Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#elif RCAR_LSI == RCAR_M3 +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* M3 Cut 10 */ +#else + /* M3 Cut 11 */ + /* M3 Cut 13 */ + /* M3 Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif +#elif RCAR_LSI == RCAR_M3N /* for M3N */ + refperiod = REFPERIOD_CYCLE; +#endif + + return refperiod; +} +#endif + +void rcar_qos_dbsc_setting(struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren) +{ + int i; + + /* Register write enable */ + if (dbsc_wren) + io_write_32(DBSC_DBSYSCNT0, 0x00001234U); + + for (i = 0; i < qos_size; i++) + io_write_32(qos[i].reg, qos[i].val); + + /* Register write protect */ + if (dbsc_wren) + io_write_32(DBSC_DBSYSCNT0, 0x00000000U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h new file mode 100644 index 0000000..1b64992 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_H +#define QOS_INIT_H + +extern void rcar_qos_init(void); +extern uint8_t get_boardcnf_phyvalid(void); + +#endif /* QOS_INIT_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/board/board.c b/arm-trusted-firmware/drivers/renesas/rzg/board/board.c new file mode 100644 index 0000000..7636372 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/board/board.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "board.h" +#include "rcar_def.h" + +#ifndef BOARD_DEFAULT +#if (RCAR_LSI == RZ_G2H) +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2H << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RZ_G2N) +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2N << BOARD_CODE_SHIFT) +#elif (RCAR_LSI == RZ_G2E) +#define BOARD_DEFAULT (BOARD_EK874_RZ_G2E << BOARD_CODE_SHIFT) +#else +#define BOARD_DEFAULT (BOARD_HIHOPE_RZ_G2M << BOARD_CODE_SHIFT) +#endif /* RCAR_LSI == RZ_G2H */ +#endif /* BOARD_DEFAULT */ + +#define BOARD_CODE_MASK (0xF8U) +#define BOARD_REV_MASK (0x07U) +#define BOARD_CODE_SHIFT (0x03) +#define BOARD_ID_UNKNOWN (0xFFU) + +#define GPIO_INDT5 0xE605500C +#define GP5_19_BIT (0x01U << 19) +#define GP5_21_BIT (0x01U << 21) +#define GP5_25_BIT (0x01U << 25) + +#define HM_ID { 0x10U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define HH_ID HM_ID +#define HN_ID { 0x20U, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU, 0xFFU } +#define EK_ID HM_ID + +const char *g_board_tbl[] = { + [BOARD_HIHOPE_RZ_G2M] = "HiHope RZ/G2M", + [BOARD_HIHOPE_RZ_G2H] = "HiHope RZ/G2H", + [BOARD_HIHOPE_RZ_G2N] = "HiHope RZ/G2N", + [BOARD_EK874_RZ_G2E] = "EK874 RZ/G2E", + [BOARD_UNKNOWN] = "unknown" +}; + +void rzg_get_board_type(uint32_t *type, uint32_t *rev) +{ + static uint8_t board_id = BOARD_ID_UNKNOWN; + const uint8_t board_tbl[][8] = { + [BOARD_HIHOPE_RZ_G2M] = HM_ID, + [BOARD_HIHOPE_RZ_G2H] = HH_ID, + [BOARD_HIHOPE_RZ_G2N] = HN_ID, + [BOARD_EK874_RZ_G2E] = EK_ID, + }; + uint32_t reg; +#if (RCAR_LSI != RZ_G2E) + uint32_t boardInfo; +#endif /* RCAR_LSI == RZ_G2E */ + + if (board_id == BOARD_ID_UNKNOWN) { + board_id = BOARD_DEFAULT; + } + + *type = ((uint32_t) board_id & BOARD_CODE_MASK) >> BOARD_CODE_SHIFT; + + if (*type >= ARRAY_SIZE(board_tbl)) { + /* no revision information, set Rev0.0. */ + *rev = 0; + return; + } + + reg = mmio_read_32(RCAR_PRR); +#if (RCAR_LSI == RZ_G2E) + if (reg & RCAR_MINOR_MASK) { + *rev = 0x30U; + } else { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } +#else + if ((reg & PRR_CUT_MASK) == RCAR_M3_CUT_VER11) { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } else { + reg = mmio_read_32(GPIO_INDT5); + if (reg & GP5_25_BIT) { + *rev = board_tbl[*type][(uint8_t)(board_id & BOARD_REV_MASK)]; + } else { + boardInfo = reg & (GP5_19_BIT | GP5_21_BIT); + *rev = (((boardInfo & GP5_19_BIT) >> 14) | + ((boardInfo & GP5_21_BIT) >> 17)) + 0x30U; + } + } +#endif /* RCAR_LSI == RZ_G2E */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/board/board.h b/arm-trusted-firmware/drivers/renesas/rzg/board/board.h new file mode 100644 index 0000000..1a76849 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/board/board.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZ_G2_BOARD_H +#define RZ_G2_BOARD_H + +enum rzg2_board_id { + BOARD_HIHOPE_RZ_G2M = 0, + BOARD_HIHOPE_RZ_G2H, + BOARD_HIHOPE_RZ_G2N, + BOARD_EK874_RZ_G2E, + BOARD_UNKNOWN +}; + +#define BOARD_REV_UNKNOWN (0xFFU) + +extern const char *g_board_tbl[]; + +/************************************************************************ + * Revisions are expressed in 8 bits. + * The upper 4 bits are major version. + * The lower 4 bits are minor version. + ************************************************************************/ +#define GET_BOARD_MAJOR(a) ((uint32_t)(a) >> 0x4) +#define GET_BOARD_MINOR(a) ((uint32_t)(a) & 0xF) +#define GET_BOARD_NAME(a) (g_board_tbl[(a)]) + +void rzg_get_board_type(uint32_t *type, uint32_t *rev); + +#endif /* RZ_G2_BOARD_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c new file mode 100644 index 0000000..663df50 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c @@ -0,0 +1,700 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2e.h" +#include "rcar_def.h" + +#include "../pfc_regs.h" + +/* PFC */ +#define GPSR0_SDA4 BIT(17) +#define GPSR0_SCL4 BIT(16) +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_WE0 BIT(22) +#define GPSR1_CS0 BIT(21) +#define GPSR1_CLKOUT BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_BIT27_REVERSED BIT(27) +#define GPSR2_BIT26_REVERSED BIT(26) +#define GPSR2_EX_WAIT0 BIT(25) +#define GPSR2_RD_WR BIT(24) +#define GPSR2_RD BIT(23) +#define GPSR2_BS BIT(22) +#define GPSR2_AVB_PHY_INT BIT(21) +#define GPSR2_AVB_TXCREFCLK BIT(20) +#define GPSR2_AVB_RD3 BIT(19) +#define GPSR2_AVB_RD2 BIT(18) +#define GPSR2_AVB_RD1 BIT(17) +#define GPSR2_AVB_RD0 BIT(16) +#define GPSR2_AVB_RXC BIT(15) +#define GPSR2_AVB_RX_CTL BIT(14) +#define GPSR2_RPC_RESET BIT(13) +#define GPSR2_RPC_RPC_INT BIT(12) +#define GPSR2_QSPI1_SSL BIT(11) +#define GPSR2_QSPI1_IO3 BIT(10) +#define GPSR2_QSPI1_IO2 BIT(9) +#define GPSR2_QSPI1_MISO_IO1 BIT(8) +#define GPSR2_QSPI1_MOSI_IO0 BIT(7) +#define GPSR2_QSPI1_SPCLK BIT(6) +#define GPSR2_QSPI0_SSL BIT(5) +#define GPSR2_QSPI0_IO3 BIT(4) +#define GPSR2_QSPI0_IO2 BIT(3) +#define GPSR2_QSPI0_MISO_IO1 BIT(2) +#define GPSR2_QSPI0_MOSI_IO0 BIT(1) +#define GPSR2_QSPI0_SPCLK BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(10) +#define GPSR4_SD3_DAT7 BIT(9) +#define GPSR4_SD3_DAT6 BIT(8) +#define GPSR4_SD3_DAT5 BIT(7) +#define GPSR4_SD3_DAT4 BIT(6) +#define GPSR4_SD3_DAT3 BIT(5) +#define GPSR4_SD3_DAT2 BIT(4) +#define GPSR4_SD3_DAT1 BIT(3) +#define GPSR4_SD3_DAT0 BIT(2) +#define GPSR4_SD3_CMD BIT(1) +#define GPSR4_SD3_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(19) +#define GPSR5_MLB_SIG BIT(18) +#define GPSR5_MLB_CLK BIT(17) +#define GPSR5_SSI_SDATA9 BIT(16) +#define GPSR5_MSIOF0_SS2 BIT(15) +#define GPSR5_MSIOF0_SS1 BIT(14) +#define GPSR5_MSIOF0_SYNC BIT(13) +#define GPSR5_MSIOF0_TXD BIT(12) +#define GPSR5_MSIOF0_RXD BIT(11) +#define GPSR5_MSIOF0_SCK BIT(10) +#define GPSR5_RX2_A BIT(9) +#define GPSR5_TX2_A BIT(8) +#define GPSR5_SCK2_A BIT(7) +#define GPSR5_TX1 BIT(6) +#define GPSR5_RX1 BIT(5) +#define GPSR5_RTS0_A BIT(4) +#define GPSR5_CTS0_A BIT(3) +#define GPSR5_TX0_A BIT(2) +#define GPSR5_RX0_A BIT(1) +#define GPSR5_SCK0_A BIT(0) +#define GPSR6_USB30_PWEN BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_USB30_OVC BIT(9) +#define GPSR6_AUDIO_CLKA BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS349 BIT(6) +#define GPSR6_SSI_SCK349 BIT(5) +#define GPSR6_SSI_SDATA2 BIT(4) +#define GPSR6_SSI_SDATA1 BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS01239 BIT(1) +#define GPSR6_SSI_SCK01239 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POCCTRL0_MASK (0x0007F000U) +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define POCCTRL2_MASK (0xFFFFFFFEU) +#define POC2_VREF_33V BIT(0) + +#define MOD_SEL0_ADGB_A ((uint32_t)0U << 29U) +#define MOD_SEL0_ADGB_B ((uint32_t)1U << 29U) +#define MOD_SEL0_ADGB_C ((uint32_t)2U << 29U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 28U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 28U) +#define MOD_SEL0_FM_A ((uint32_t)0U << 26U) +#define MOD_SEL0_FM_B ((uint32_t)1U << 26U) +#define MOD_SEL0_FM_C ((uint32_t)2U << 26U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 25U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 25U) +#define MOD_SEL0_HSCIF0_A ((uint32_t)0U << 24U) +#define MOD_SEL0_HSCIF0_B ((uint32_t)1U << 24U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 23U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 23U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 22U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_I2C1_C ((uint32_t)2U << 20U) +#define MOD_SEL0_I2C1_D ((uint32_t)3U << 20U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 17U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 17U) +#define MOD_SEL0_I2C2_C ((uint32_t)2U << 17U) +#define MOD_SEL0_I2C2_D ((uint32_t)3U << 17U) +#define MOD_SEL0_I2C2_E ((uint32_t)4U << 17U) +#define MOD_SEL0_NDFC_A ((uint32_t)0U << 16U) +#define MOD_SEL0_NDFC_B ((uint32_t)1U << 16U) +#define MOD_SEL0_PWM0_A ((uint32_t)0U << 15U) +#define MOD_SEL0_PWM0_B ((uint32_t)1U << 15U) +#define MOD_SEL0_PWM1_A ((uint32_t)0U << 14U) +#define MOD_SEL0_PWM1_B ((uint32_t)1U << 14U) +#define MOD_SEL0_PWM2_A ((uint32_t)0U << 12U) +#define MOD_SEL0_PWM2_B ((uint32_t)1U << 12U) +#define MOD_SEL0_PWM2_C ((uint32_t)2U << 12U) +#define MOD_SEL0_PWM3_A ((uint32_t)0U << 10U) +#define MOD_SEL0_PWM3_B ((uint32_t)1U << 10U) +#define MOD_SEL0_PWM3_C ((uint32_t)2U << 10U) +#define MOD_SEL0_PWM4_A ((uint32_t)0U << 9U) +#define MOD_SEL0_PWM4_B ((uint32_t)1U << 9U) +#define MOD_SEL0_PWM5_A ((uint32_t)0U << 8U) +#define MOD_SEL0_PWM5_B ((uint32_t)1U << 8U) +#define MOD_SEL0_PWM6_A ((uint32_t)0U << 7U) +#define MOD_SEL0_PWM6_B ((uint32_t)1U << 7U) +#define MOD_SEL0_REMOCON_A ((uint32_t)0U << 5U) +#define MOD_SEL0_REMOCON_B ((uint32_t)1U << 5U) +#define MOD_SEL0_REMOCON_C ((uint32_t)2U << 5U) +#define MOD_SEL0_SCIF_A ((uint32_t)0U << 4U) +#define MOD_SEL0_SCIF_B ((uint32_t)1U << 4U) +#define MOD_SEL0_SCIF0_A ((uint32_t)0U << 3U) +#define MOD_SEL0_SCIF0_B ((uint32_t)1U << 3U) +#define MOD_SEL0_SCIF2_A ((uint32_t)0U << 2U) +#define MOD_SEL0_SCIF2_B ((uint32_t)1U << 2U) +#define MOD_SEL0_SPEED_PULSE_IF_A ((uint32_t)0U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_B ((uint32_t)1U << 0U) +#define MOD_SEL0_SPEED_PULSE_IF_C ((uint32_t)2U << 0U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 31U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 31U) +#define MOD_SEL1_SSI2_A ((uint32_t)0U << 30U) +#define MOD_SEL1_SSI2_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 29U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 29U) +#define MOD_SEL1_USB20_CH0_A ((uint32_t)0U << 28U) +#define MOD_SEL1_USB20_CH0_B ((uint32_t)1U << 28U) +#define MOD_SEL1_DRIF2_A ((uint32_t)0U << 26U) +#define MOD_SEL1_DRIF2_B ((uint32_t)1U << 26U) +#define MOD_SEL1_DRIF3_A ((uint32_t)0U << 25U) +#define MOD_SEL1_DRIF3_B ((uint32_t)1U << 25U) +#define MOD_SEL1_HSCIF3_A ((uint32_t)0U << 22U) +#define MOD_SEL1_HSCIF3_B ((uint32_t)1U << 22U) +#define MOD_SEL1_HSCIF3_C ((uint32_t)2U << 22U) +#define MOD_SEL1_HSCIF3_D ((uint32_t)3U << 22U) +#define MOD_SEL1_HSCIF3_E ((uint32_t)4U << 22U) +#define MOD_SEL1_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL1_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL1_HSCIF4_C ((uint32_t)2U << 19U) +#define MOD_SEL1_HSCIF4_D ((uint32_t)3U << 19U) +#define MOD_SEL1_HSCIF4_E ((uint32_t)4U << 19U) +#define MOD_SEL1_I2C6_A ((uint32_t)0U << 18U) +#define MOD_SEL1_I2C6_B ((uint32_t)1U << 18U) +#define MOD_SEL1_I2C7_A ((uint32_t)0U << 17U) +#define MOD_SEL1_I2C7_B ((uint32_t)1U << 17U) +#define MOD_SEL1_MSIOF2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_MSIOF2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_MSIOF3_A ((uint32_t)0U << 15U) +#define MOD_SEL1_MSIOF3_B ((uint32_t)1U << 15U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF3_C ((uint32_t)2U << 13U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 11U) +#define MOD_SEL1_SCIF5_A ((uint32_t)0U << 9U) +#define MOD_SEL1_SCIF5_B ((uint32_t)1U << 9U) +#define MOD_SEL1_SCIF5_C ((uint32_t)2U << 9U) +#define MOD_SEL1_VIN4_A ((uint32_t)0U << 8U) +#define MOD_SEL1_VIN4_B ((uint32_t)1U << 8U) +#define MOD_SEL1_VIN5_A ((uint32_t)0U << 7U) +#define MOD_SEL1_VIN5_B ((uint32_t)1U << 7U) +#define MOD_SEL1_ADGC_A ((uint32_t)0U << 5U) +#define MOD_SEL1_ADGC_B ((uint32_t)1U << 5U) +#define MOD_SEL1_ADGC_C ((uint32_t)2U << 5U) +#define MOD_SEL1_SSI9_A ((uint32_t)0U << 4U) +#define MOD_SEL1_SSI9_B ((uint32_t)1U << 4U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2e(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_ADGB_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_FM_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF0_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_NDFC_A | + MOD_SEL0_PWM0_A | + MOD_SEL0_PWM1_A | + MOD_SEL0_PWM2_A | + MOD_SEL0_PWM3_A | + MOD_SEL0_PWM4_A | + MOD_SEL0_PWM5_A | + MOD_SEL0_PWM6_A | + MOD_SEL0_REMOCON_A | + MOD_SEL0_SCIF_A | + MOD_SEL0_SCIF0_A | + MOD_SEL0_SCIF2_A | + MOD_SEL0_SPEED_PULSE_IF_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SSI2_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_USB20_CH0_B | + MOD_SEL1_DRIF2_A | + MOD_SEL1_DRIF3_A | + MOD_SEL1_HSCIF3_C | + MOD_SEL1_HSCIF4_B | + MOD_SEL1_I2C6_A | + MOD_SEL1_I2C7_A | + MOD_SEL1_MSIOF2_A | + MOD_SEL1_MSIOF3_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF5_A | + MOD_SEL1_VIN4_A | + MOD_SEL1_VIN5_A | + MOD_SEL1_ADGC_A | + MOD_SEL1_SSI9_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(2) | /* HRX4_B */ + IPSR_24_FUNC(2) | /* HTX4_B */ + IPSR_20_FUNC(0) | /* QSPI1_SPCLK */ + IPSR_16_FUNC(0) | /* QSPI0_IO3 */ + IPSR_12_FUNC(0) | /* QSPI0_IO2 */ + IPSR_8_FUNC(0) | /* QSPI0_MISO/IO1 */ + IPSR_4_FUNC(0) | /* QSPI0_MOSI/IO0 */ + IPSR_0_FUNC(0)); /* QSPI0_SPCLK */ + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(0) | /* AVB_RD2 */ + IPSR_24_FUNC(0) | /* AVB_RD1 */ + IPSR_20_FUNC(0) | /* AVB_RD0 */ + IPSR_16_FUNC(0) | /* RPC_RESET# */ + IPSR_12_FUNC(0) | /* RPC_INT# */ + IPSR_8_FUNC(0) | /* QSPI1_SSL */ + IPSR_4_FUNC(2) | /* HRX3_C */ + IPSR_0_FUNC(2)); /* HTX3_C */ + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(1) | /* IRQ0 */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(2) | /* AVB_LINK */ + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | /* AVB_MDC */ + IPSR_4_FUNC(0) | /* AVB_MDIO */ + IPSR_0_FUNC(0)); /* AVB_TXCREFCLK */ + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(5) | /* DU_HSYNC */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(5) | /* DU_DG4 */ + IPSR_8_FUNC(5) | /* DU_DOTCLKOUT0 */ + IPSR_4_FUNC(5) | /* DU_DISP */ + IPSR_0_FUNC(1)); /* IRQ1 */ + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(5) | /* DU_DB5 */ + IPSR_24_FUNC(5) | /* DU_DB4 */ + IPSR_20_FUNC(5) | /* DU_DB3 */ + IPSR_16_FUNC(5) | /* DU_DB2 */ + IPSR_12_FUNC(5) | /* DU_DG6 */ + IPSR_8_FUNC(5) | /* DU_VSYNC */ + IPSR_4_FUNC(5) | /* DU_DG5 */ + IPSR_0_FUNC(5)); /* DU_DG7 */ + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(5) | /* DU_DR3 */ + IPSR_24_FUNC(5) | /* DU_DB7 */ + IPSR_20_FUNC(5) | /* DU_DR2 */ + IPSR_16_FUNC(5) | /* DU_DR1 */ + IPSR_12_FUNC(5) | /* DU_DR0 */ + IPSR_8_FUNC(5) | /* DU_DB1 */ + IPSR_4_FUNC(5) | /* DU_DB0 */ + IPSR_0_FUNC(5)); /* DU_DB6 */ + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(5) | /* DU_DG1 */ + IPSR_24_FUNC(5) | /* DU_DG0 */ + IPSR_20_FUNC(5) | /* DU_DR7 */ + IPSR_16_FUNC(1) | /* CANFD1_RX */ + IPSR_12_FUNC(5) | /* DU_DR6 */ + IPSR_8_FUNC(5) | /* DU_DR5 */ + IPSR_4_FUNC(1) | /* CANFD1_TX */ + IPSR_0_FUNC(5)); /* DU_DR4 */ + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | /* SD0_CLK */ + IPSR_24_FUNC(0) | + IPSR_20_FUNC(5) | /* DU_DOTCLKIN0 */ + IPSR_16_FUNC(5) | /* DU_DG3 */ + IPSR_12_FUNC(1) | /* CAN_CLK */ + IPSR_8_FUNC(1) | /* CANFD0_RX */ + IPSR_4_FUNC(1) | /* CANFD0_TX */ + IPSR_0_FUNC(5)); /* DU_DG2 */ + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(0) | /* SD1_DAT0 */ + IPSR_24_FUNC(0) | /* SD1_CMD */ + IPSR_20_FUNC(0) | /* SD1_CLK */ + IPSR_16_FUNC(0) | /* SD0_DAT3 */ + IPSR_12_FUNC(0) | /* SD0_DAT2 */ + IPSR_8_FUNC(0) | /* SD0_DAT1 */ + IPSR_4_FUNC(0) | /* SD0_DAT0 */ + IPSR_0_FUNC(0)); /* SD0_CMD */ + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | /* SD3_DAT2 */ + IPSR_24_FUNC(0) | /* SD3_DAT1 */ + IPSR_20_FUNC(0) | /* SD3_DAT0 */ + IPSR_16_FUNC(0) | /* SD3_CMD */ + IPSR_12_FUNC(0) | /* SD3_CLK */ + IPSR_8_FUNC(0) | /* SD1_DAT3 */ + IPSR_4_FUNC(0) | /* SD1_DAT2 */ + IPSR_0_FUNC(0)); /* SD1_DAT1 */ + + pfc_reg_write(PFC_IPSR10, + IPSR_24_FUNC(0) | /* SD0_CD */ + IPSR_20_FUNC(0) | /* SD3_DS */ + IPSR_16_FUNC(0) | /* SD3_DAT7 */ + IPSR_12_FUNC(0) | /* SD3_DAT6 */ + IPSR_8_FUNC(0) | /* SD3_DAT5 */ + IPSR_4_FUNC(0) | /* SD3_DAT4 */ + IPSR_0_FUNC(0)); /* SD3_DAT3 */ + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(8) | /* USB0_ID */ + IPSR_20_FUNC(2) | /* AUDIO_CLKOUT1_A */ + IPSR_16_FUNC(0) | /* CTS0#_A */ + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | /* SD1_WP */ + IPSR_0_FUNC(0)); /* SD1_CD */ + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | /* RX2_A */ + IPSR_8_FUNC(0) | /* TX2_A */ + IPSR_4_FUNC(0) | /* SCK2_A */ + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(4) | /* SDA1_B */ + IPSR_12_FUNC(4) | /* SCL1_B */ + IPSR_8_FUNC(0) | /* SSI_SDATA9 */ + IPSR_4_FUNC(1) | /* HTX2_A */ + IPSR_0_FUNC(1)); /* HRX2_A */ + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | /* SSI_SCK5 */ + IPSR_24_FUNC(0) | /* SSI_SDATA4 */ + IPSR_20_FUNC(0) | /* SSI_SDATA3 */ + IPSR_16_FUNC(0) | /* SSI_WS349 */ + IPSR_12_FUNC(0) | /* SSI_SCK349 */ + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | /* SSI_SDATA1 */ + IPSR_0_FUNC(0));/* SSI_SDATA0 */ + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | /* USB30_OVC */ + IPSR_24_FUNC(0) | /* USB30_PWEN */ + IPSR_20_FUNC(0) | /* AUDIO_CLKA */ + IPSR_16_FUNC(1) | /* HRTS2#_A */ + IPSR_12_FUNC(1) | /* HCTS2#_A */ + IPSR_8_FUNC(3) | /* TPU0TO1 */ + IPSR_4_FUNC(3) | /* TPU0TO0 */ + IPSR_0_FUNC(0)); /* SSI_WS5 */ + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_SCL4 | + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D1 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_WE0 | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A11 | + GPSR1_A10 | + GPSR1_A9 | + GPSR1_A8 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_BIT27_REVERSED | + GPSR2_BIT26_REVERSED | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_TXCREFCLK | + GPSR2_AVB_RD3 | + GPSR2_AVB_RD2 | + GPSR2_AVB_RD1 | + GPSR2_AVB_RD0 | + GPSR2_AVB_RXC | + GPSR2_AVB_RX_CTL | + GPSR2_RPC_RESET | + GPSR2_RPC_RPC_INT | + GPSR2_QSPI1_IO3 | + GPSR2_QSPI1_IO2 | + GPSR2_QSPI1_MISO_IO1 | + GPSR2_QSPI1_MOSI_IO0 | + GPSR2_QSPI0_SSL | + GPSR2_QSPI0_IO3 | + GPSR2_QSPI0_IO2 | + GPSR2_QSPI0_MISO_IO1 | + GPSR2_QSPI0_MOSI_IO0 | + GPSR2_QSPI0_SPCLK); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD1_CMD | + GPSR3_SD1_CLK | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MLB_SIG | + GPSR5_MLB_CLK | + GPSR5_SSI_SDATA9 | + GPSR5_MSIOF0_SS2 | + GPSR5_MSIOF0_SS1 | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS0_A | + GPSR5_SCK0_A); + + pfc_reg_write(PFC_GPSR6, + GPSR6_USB30_PWEN | + GPSR6_SSI_SDATA6 | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA5 | + GPSR6_SSI_SCK5 | + GPSR6_SSI_SDATA4 | + GPSR6_USB30_OVC | + GPSR6_AUDIO_CLKA | + GPSR6_SSI_SDATA3 | + GPSR6_SSI_WS349 | + GPSR6_SSI_SCK349 | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS01239 | + GPSR6_SSI_SCK01239); + + /* initialize POC control */ + reg = mmio_read_32(PFC_POCCTRL0); + reg = (reg & POCCTRL0_MASK) | + POC_SD1_DAT3_33V | + POC_SD1_DAT2_33V | + POC_SD1_DAT1_33V | + POC_SD1_DAT0_33V | + POC_SD1_CMD_33V | + POC_SD1_CLK_33V | + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V; + pfc_reg_write(PFC_POCCTRL0, reg); + + reg = mmio_read_32(PFC_POCCTRL2); + reg = ((reg & POCCTRL2_MASK) & ~POC2_VREF_33V); + pfc_reg_write(PFC_POCCTRL2, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00080000U); + pfc_reg_write(PFC_PUD1, 0xCE398464U); + pfc_reg_write(PFC_PUD2, 0xA4C380F4U); + pfc_reg_write(PFC_PUD3, 0x0000079FU); + pfc_reg_write(PFC_PUD4, 0xFFF0FFFFU); + pfc_reg_write(PFC_PUD5, 0x40000000U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000000U); + pfc_reg_write(PFC_PUEN1, 0x00300000U); + pfc_reg_write(PFC_PUEN2, 0x00400074U); + pfc_reg_write(PFC_PUEN3, 0x00000000U); + pfc_reg_write(PFC_PUEN4, 0x07900600U); + pfc_reg_write(PFC_PUEN5, 0x00000000U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000000U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000000U); + mmio_write_32(GPIO_OUTDT3, 0x00006000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00000000U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00020000U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100000U); + mmio_write_32(GPIO_INOUTSEL2, 0x03000000U); + mmio_write_32(GPIO_INOUTSEL3, 0x0000E000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000440U); + mmio_write_32(GPIO_INOUTSEL5, 0x00080000U); + mmio_write_32(GPIO_INOUTSEL6, 0x00000010U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h new file mode 100644 index 0000000..677591a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2E_H +#define PFC_INIT_G2E_H + +void pfc_init_g2e(void); + +#endif /* PFC_INIT_G2E_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c new file mode 100644 index 0000000..90a1c99 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c @@ -0,0 +1,1310 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2h.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2h(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_MSIOF3_A | + MOD_SEL0_MSIOF2_A | + MOD_SEL0_MSIOF1_A | + MOD_SEL0_LBSC_A | + MOD_SEL0_IEBUS_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_HSCIF4_A | + MOD_SEL0_HSCIF3_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_ETHERAVB_A | + MOD_SEL0_DRIF3_A | + MOD_SEL0_DRIF2_A | + MOD_SEL0_DRIF1_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_CANFD0_A | + MOD_SEL0_ADG_A_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_TSIF1_A | + MOD_SEL1_TSIF0_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_SSP1_1_A | + MOD_SEL1_SSP1_0_A | + MOD_SEL1_SSI_A | + MOD_SEL1_SPEED_PULSE_IF_A | + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SDHI2_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF2_A | + MOD_SEL1_SCIF1_A | + MOD_SEL1_SCIF_A | + MOD_SEL1_REMOCON_A | + MOD_SEL1_RCAN0_A | + MOD_SEL1_PWM6_A | + MOD_SEL1_PWM5_A | + MOD_SEL1_PWM4_A | + MOD_SEL1_PWM3_A | + MOD_SEL1_PWM2_A | + MOD_SEL1_PWM1_A); + + pfc_reg_write(PFC_MOD_SEL2, + MOD_SEL2_I2C_5_B | + MOD_SEL2_I2C_3_B | + MOD_SEL2_I2C_0_B | + MOD_SEL2_FM_A | + MOD_SEL2_SCIF5_A | + MOD_SEL2_I2C6_A | + MOD_SEL2_NDF_A | + MOD_SEL2_SSI2_A | + MOD_SEL2_SSI9_A | + MOD_SEL2_TIMER_TMU2_A | + MOD_SEL2_ADG_B_A | + MOD_SEL2_ADG_C_A | + MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(3) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(3)); + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(1) | + IPSR_24_FUNC(1) | + IPSR_20_FUNC(1) | + IPSR_16_FUNC(1) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR10, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(4) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(4) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(8) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(8)); + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR16, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR17, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(1) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR18, + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_CLKOUT | + GPSR1_EX_WAIT0_A | + GPSR1_WE1 | + GPSR1_RD | + GPSR1_RD_WR | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A7 | + GPSR1_A6 | + GPSR1_A5 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_AVB_AVTP_CAPTURE_A | + GPSR2_AVB_AVTP_MATCH_A | + GPSR2_AVB_LINK | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_MDC | + GPSR2_PWM2_A | + GPSR2_PWM1_A | + GPSR2_IRQ4 | + GPSR2_IRQ3 | + GPSR2_IRQ2 | + GPSR2_IRQ1 | + GPSR2_IRQ0); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DS | + GPSR4_SD3_DAT7 | + GPSR4_SD3_DAT6 | + GPSR4_SD3_DAT5 | + GPSR4_SD3_DAT4 | + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK | + GPSR4_SD2_DAT3 | + GPSR4_SD2_DAT2 | + GPSR4_SD2_DAT1 | + GPSR4_SD2_DAT0 | + GPSR4_SD2_CMD | + GPSR4_SD2_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS1 | + GPSR5_CTS1 | + GPSR5_TX1_A | + GPSR5_RX1_A | + GPSR5_RTS0 | + GPSR5_SCK0); + + pfc_reg_write(PFC_GPSR6, + GPSR6_AUDIO_CLKB_B | + GPSR6_AUDIO_CLKA_A | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA4 | + GPSR6_SSI_WS4 | + GPSR6_SSI_SCK4 | + GPSR6_SSI_SDATA1_A | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS0129 | + GPSR6_SSI_SCK0129); + + pfc_reg_write(PFC_GPSR7, + GPSR7_AVS2 | + GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = (reg & DRVCTRL0_MASK) | + DRVCTRL0_QSPI0_SPCLK(3) | + DRVCTRL0_QSPI0_MOSI_IO0(3) | + DRVCTRL0_QSPI0_MISO_IO1(3) | + DRVCTRL0_QSPI0_IO2(3) | + DRVCTRL0_QSPI0_IO3(3) | + DRVCTRL0_QSPI0_SSL(3) | + DRVCTRL0_QSPI1_SPCLK(3) | + DRVCTRL0_QSPI1_MOSI_IO0(3); + pfc_reg_write(PFC_DRVCTRL0, reg); + + reg = mmio_read_32(PFC_DRVCTRL1); + reg = (reg & DRVCTRL1_MASK) | + DRVCTRL1_QSPI1_MISO_IO1(3) | + DRVCTRL1_QSPI1_IO2(3) | + DRVCTRL1_QSPI1_IO3(3) | + DRVCTRL1_QSPI1_SS(3) | + DRVCTRL1_RPC_INT(3) | + DRVCTRL1_RPC_WP(3) | + DRVCTRL1_RPC_RESET(3) | + DRVCTRL1_AVB_RX_CTL(7); + pfc_reg_write(PFC_DRVCTRL1, reg); + + reg = mmio_read_32(PFC_DRVCTRL2); + reg = (reg & DRVCTRL2_MASK) | + DRVCTRL2_AVB_RXC(7) | + DRVCTRL2_AVB_RD0(7) | + DRVCTRL2_AVB_RD1(7) | + DRVCTRL2_AVB_RD2(7) | + DRVCTRL2_AVB_RD3(7) | + DRVCTRL2_AVB_TX_CTL(3) | + DRVCTRL2_AVB_TXC(3) | + DRVCTRL2_AVB_TD0(3); + pfc_reg_write(PFC_DRVCTRL2, reg); + + reg = mmio_read_32(PFC_DRVCTRL3); + reg = (reg & DRVCTRL3_MASK) | + DRVCTRL3_AVB_TD1(3) | + DRVCTRL3_AVB_TD2(3) | + DRVCTRL3_AVB_TD3(3) | + DRVCTRL3_AVB_TXCREFCLK(7) | + DRVCTRL3_AVB_MDIO(7) | + DRVCTRL3_AVB_MDC(7) | + DRVCTRL3_AVB_MAGIC(7) | + DRVCTRL3_AVB_PHY_INT(7); + pfc_reg_write(PFC_DRVCTRL3, reg); + + reg = mmio_read_32(PFC_DRVCTRL4); + reg = (reg & DRVCTRL4_MASK) | + DRVCTRL4_AVB_LINK(7) | + DRVCTRL4_AVB_AVTP_MATCH(7) | + DRVCTRL4_AVB_AVTP_CAPTURE(7) | + DRVCTRL4_IRQ0(7) | + DRVCTRL4_IRQ1(7) | + DRVCTRL4_IRQ2(7) | + DRVCTRL4_IRQ3(7) | + DRVCTRL4_IRQ4(7); + pfc_reg_write(PFC_DRVCTRL4, reg); + + reg = mmio_read_32(PFC_DRVCTRL5); + reg = (reg & DRVCTRL5_MASK) | + DRVCTRL5_IRQ5(7) | + DRVCTRL5_PWM0(7) | + DRVCTRL5_PWM1(7) | + DRVCTRL5_PWM2(7) | + DRVCTRL5_A0(3) | + DRVCTRL5_A1(3) | + DRVCTRL5_A2(3) | + DRVCTRL5_A3(3); + pfc_reg_write(PFC_DRVCTRL5, reg); + + reg = mmio_read_32(PFC_DRVCTRL6); + reg = (reg & DRVCTRL6_MASK) | + DRVCTRL6_A4(3) | + DRVCTRL6_A5(3) | + DRVCTRL6_A6(3) | + DRVCTRL6_A7(3) | + DRVCTRL6_A8(7) | + DRVCTRL6_A9(7) | + DRVCTRL6_A10(7) | + DRVCTRL6_A11(7); + pfc_reg_write(PFC_DRVCTRL6, reg); + + reg = mmio_read_32(PFC_DRVCTRL7); + reg = (reg & DRVCTRL7_MASK) | + DRVCTRL7_A12(3) | + DRVCTRL7_A13(3) | + DRVCTRL7_A14(3) | + DRVCTRL7_A15(3) | + DRVCTRL7_A16(3) | + DRVCTRL7_A17(3) | + DRVCTRL7_A18(3) | + DRVCTRL7_A19(3); + pfc_reg_write(PFC_DRVCTRL7, reg); + + reg = mmio_read_32(PFC_DRVCTRL8); + reg = (reg & DRVCTRL8_MASK) | + DRVCTRL8_CLKOUT(7) | + DRVCTRL8_CS0(7) | + DRVCTRL8_CS1_A2(7) | + DRVCTRL8_BS(7) | + DRVCTRL8_RD(7) | + DRVCTRL8_RD_W(7) | + DRVCTRL8_WE0(7) | + DRVCTRL8_WE1(7); + pfc_reg_write(PFC_DRVCTRL8, reg); + + reg = mmio_read_32(PFC_DRVCTRL9); + reg = (reg & DRVCTRL9_MASK) | + DRVCTRL9_EX_WAIT0(7) | + DRVCTRL9_PRESETOU(7) | + DRVCTRL9_D0(7) | + DRVCTRL9_D1(7) | + DRVCTRL9_D2(7) | + DRVCTRL9_D3(7) | + DRVCTRL9_D4(7) | + DRVCTRL9_D5(7); + pfc_reg_write(PFC_DRVCTRL9, reg); + + reg = mmio_read_32(PFC_DRVCTRL10); + reg = (reg & DRVCTRL10_MASK) | + DRVCTRL10_D6(7) | + DRVCTRL10_D7(7) | + DRVCTRL10_D8(3) | + DRVCTRL10_D9(3) | + DRVCTRL10_D10(3) | + DRVCTRL10_D11(3) | + DRVCTRL10_D12(3) | + DRVCTRL10_D13(3); + pfc_reg_write(PFC_DRVCTRL10, reg); + + reg = mmio_read_32(PFC_DRVCTRL11); + reg = (reg & DRVCTRL11_MASK) | + DRVCTRL11_D14(3) | + DRVCTRL11_D15(3) | + DRVCTRL11_AVS1(7) | + DRVCTRL11_AVS2(7) | + DRVCTRL11_GP7_02(7) | + DRVCTRL11_GP7_03(7) | + DRVCTRL11_DU_DOTCLKIN0(3) | + DRVCTRL11_DU_DOTCLKIN1(3); + pfc_reg_write(PFC_DRVCTRL11, reg); + + reg = mmio_read_32(PFC_DRVCTRL12); + reg = (reg & DRVCTRL12_MASK) | + DRVCTRL12_DU_DOTCLKIN2(3) | + DRVCTRL12_DU_DOTCLKIN3(3) | + DRVCTRL12_DU_FSCLKST(3) | + DRVCTRL12_DU_TMS(3); + pfc_reg_write(PFC_DRVCTRL12, reg); + + reg = mmio_read_32(PFC_DRVCTRL13); + reg = (reg & DRVCTRL13_MASK) | + DRVCTRL13_TDO(3) | + DRVCTRL13_ASEBRK(3) | + DRVCTRL13_SD0_CLK(7) | + DRVCTRL13_SD0_CMD(7) | + DRVCTRL13_SD0_DAT0(7) | + DRVCTRL13_SD0_DAT1(7) | + DRVCTRL13_SD0_DAT2(7) | + DRVCTRL13_SD0_DAT3(7); + pfc_reg_write(PFC_DRVCTRL13, reg); + + reg = mmio_read_32(PFC_DRVCTRL14); + reg = (reg & DRVCTRL14_MASK) | + DRVCTRL14_SD1_CLK(7) | + DRVCTRL14_SD1_CMD(7) | + DRVCTRL14_SD1_DAT0(5) | + DRVCTRL14_SD1_DAT1(5) | + DRVCTRL14_SD1_DAT2(5) | + DRVCTRL14_SD1_DAT3(5) | + DRVCTRL14_SD2_CLK(5) | + DRVCTRL14_SD2_CMD(5); + pfc_reg_write(PFC_DRVCTRL14, reg); + + reg = mmio_read_32(PFC_DRVCTRL15); + reg = (reg & DRVCTRL15_MASK) | + DRVCTRL15_SD2_DAT0(5) | + DRVCTRL15_SD2_DAT1(5) | + DRVCTRL15_SD2_DAT2(5) | + DRVCTRL15_SD2_DAT3(5) | + DRVCTRL15_SD2_DS(5) | + DRVCTRL15_SD3_CLK(7) | + DRVCTRL15_SD3_CMD(7) | + DRVCTRL15_SD3_DAT0(7); + pfc_reg_write(PFC_DRVCTRL15, reg); + + reg = mmio_read_32(PFC_DRVCTRL16); + reg = (reg & DRVCTRL16_MASK) | + DRVCTRL16_SD3_DAT1(7) | + DRVCTRL16_SD3_DAT2(7) | + DRVCTRL16_SD3_DAT3(7) | + DRVCTRL16_SD3_DAT4(7) | + DRVCTRL16_SD3_DAT5(7) | + DRVCTRL16_SD3_DAT6(7) | + DRVCTRL16_SD3_DAT7(7) | + DRVCTRL16_SD3_DS(7); + pfc_reg_write(PFC_DRVCTRL16, reg); + + reg = mmio_read_32(PFC_DRVCTRL17); + reg = (reg & DRVCTRL17_MASK) | + DRVCTRL17_SD0_CD(7) | + DRVCTRL17_SD0_WP(7) | + DRVCTRL17_SD1_CD(7) | + DRVCTRL17_SD1_WP(7) | + DRVCTRL17_SCK0(7) | + DRVCTRL17_RX0(7) | + DRVCTRL17_TX0(7) | + DRVCTRL17_CTS0(7); + pfc_reg_write(PFC_DRVCTRL17, reg); + + reg = mmio_read_32(PFC_DRVCTRL18); + reg = (reg & DRVCTRL18_MASK) | + DRVCTRL18_RTS0_TANS(7) | + DRVCTRL18_RX1(7) | + DRVCTRL18_TX1(7) | + DRVCTRL18_CTS1(7) | + DRVCTRL18_RTS1_TANS(7) | + DRVCTRL18_SCK2(7) | + DRVCTRL18_TX2(7) | + DRVCTRL18_RX2(7); + pfc_reg_write(PFC_DRVCTRL18, reg); + + reg = mmio_read_32(PFC_DRVCTRL19); + reg = (reg & DRVCTRL19_MASK) | + DRVCTRL19_HSCK0(7) | + DRVCTRL19_HRX0(7) | + DRVCTRL19_HTX0(7) | + DRVCTRL19_HCTS0(7) | + DRVCTRL19_HRTS0(7) | + DRVCTRL19_MSIOF0_SCK(7) | + DRVCTRL19_MSIOF0_SYNC(7) | + DRVCTRL19_MSIOF0_SS1(7); + pfc_reg_write(PFC_DRVCTRL19, reg); + + reg = mmio_read_32(PFC_DRVCTRL20); + reg = (reg & DRVCTRL20_MASK) | + DRVCTRL20_MSIOF0_TXD(7) | + DRVCTRL20_MSIOF0_SS2(7) | + DRVCTRL20_MSIOF0_RXD(7) | + DRVCTRL20_MLB_CLK(7) | + DRVCTRL20_MLB_SIG(7) | + DRVCTRL20_MLB_DAT(7) | + DRVCTRL20_MLB_REF(7) | + DRVCTRL20_SSI_SCK0129(7); + pfc_reg_write(PFC_DRVCTRL20, reg); + + reg = mmio_read_32(PFC_DRVCTRL21); + reg = (reg & DRVCTRL21_MASK) | + DRVCTRL21_SSI_WS0129(7) | + DRVCTRL21_SSI_SDATA0(7) | + DRVCTRL21_SSI_SDATA1(7) | + DRVCTRL21_SSI_SDATA2(7) | + DRVCTRL21_SSI_SCK34(7) | + DRVCTRL21_SSI_WS34(7) | + DRVCTRL21_SSI_SDATA3(7) | + DRVCTRL21_SSI_SCK4(7); + pfc_reg_write(PFC_DRVCTRL21, reg); + + reg = mmio_read_32(PFC_DRVCTRL22); + reg = (reg & DRVCTRL22_MASK) | + DRVCTRL22_SSI_WS4(7) | + DRVCTRL22_SSI_SDATA4(7) | + DRVCTRL22_SSI_SCK5(7) | + DRVCTRL22_SSI_WS5(7) | + DRVCTRL22_SSI_SDATA5(7) | + DRVCTRL22_SSI_SCK6(7) | + DRVCTRL22_SSI_WS6(7) | + DRVCTRL22_SSI_SDATA6(7); + pfc_reg_write(PFC_DRVCTRL22, reg); + + reg = mmio_read_32(PFC_DRVCTRL23); + reg = (reg & DRVCTRL23_MASK) | + DRVCTRL23_SSI_SCK78(7) | + DRVCTRL23_SSI_WS78(7) | + DRVCTRL23_SSI_SDATA7(7) | + DRVCTRL23_SSI_SDATA8(7) | + DRVCTRL23_SSI_SDATA9(7) | + DRVCTRL23_AUDIO_CLKA(7) | + DRVCTRL23_AUDIO_CLKB(7) | + DRVCTRL23_USB0_PWEN(7); + pfc_reg_write(PFC_DRVCTRL23, reg); + + reg = mmio_read_32(PFC_DRVCTRL24); + reg = (reg & DRVCTRL24_MASK) | + DRVCTRL24_USB0_OVC(7) | + DRVCTRL24_USB1_PWEN(7) | + DRVCTRL24_USB1_OVC(7) | + DRVCTRL24_USB30_PWEN(7) | + DRVCTRL24_USB30_OVC(7) | + DRVCTRL24_USB31_PWEN(7) | + DRVCTRL24_USB31_OVC(7); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h new file mode 100644 index 0000000..5efce45 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2H_H +#define PFC_INIT_G2H_H + +void pfc_init_g2h(void); + +#endif /* PFC_INIT_G2H_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c new file mode 100644 index 0000000..f76b83f --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c @@ -0,0 +1,1300 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* for uint32_t */ + +#include + +#include "pfc_init_g2m.h" +#include "rcar_def.h" +#include "rcar_private.h" +#include "pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +/* SCIF3 Registers for Dummy write */ +#define SCIF3_BASE (0xE6C50000U) +#define SCIF3_SCFCR (SCIF3_BASE + 0x0018U) +#define SCIF3_SCFDR (SCIF3_BASE + 0x001CU) +#define SCFCR_DATA (0x0000U) + +/* Realtime module stop control */ +#define CPG_BASE (0xE6150000U) +#define CPG_SCMSTPCR0 (CPG_BASE + 0x0B20U) +#define CPG_MSTPSR0 (CPG_BASE + 0x0030U) +#define SCMSTPCR0_RTDMAC (0x00200000U) + +/* RT-DMAC Registers */ +#define RTDMAC_CH (0U) /* choose 0 to 15 */ + +#define RTDMAC_BASE (0xFFC10000U) +#define RTDMAC_RDMOR (RTDMAC_BASE + 0x0060U) +#define RTDMAC_RDMCHCLR (RTDMAC_BASE + 0x0080U) +#define RTDMAC_RDMSAR(x) (RTDMAC_BASE + 0x8000U + (0x80U * (x))) +#define RTDMAC_RDMDAR(x) (RTDMAC_BASE + 0x8004U + (0x80U * (x))) +#define RTDMAC_RDMTCR(x) (RTDMAC_BASE + 0x8008U + (0x80U * (x))) +#define RTDMAC_RDMCHCR(x) (RTDMAC_BASE + 0x800CU + (0x80U * (x))) +#define RTDMAC_RDMCHCRB(x) (RTDMAC_BASE + 0x801CU + (0x80U * (x))) +#define RTDMAC_RDMDPBASE(x) (RTDMAC_BASE + 0x8050U + (0x80U * (x))) +#define RTDMAC_DESC_BASE (RTDMAC_BASE + 0xA000U) +#define RTDMAC_DESC_RDMSAR (RTDMAC_DESC_BASE + 0x0000U) +#define RTDMAC_DESC_RDMDAR (RTDMAC_DESC_BASE + 0x0004U) +#define RTDMAC_DESC_RDMTCR (RTDMAC_DESC_BASE + 0x0008U) + +#define RDMOR_DME (0x0001U) /* DMA Master Enable */ +#define RDMCHCR_DPM_INFINITE (0x30000000U) /* Infinite repeat mode */ +#define RDMCHCR_RPT_TCR (0x02000000U) /* enable to update TCR */ +#define RDMCHCR_TS_2 (0x00000008U) /* Word(2byte) units transfer */ +#define RDMCHCR_RS_AUTO (0x00000400U) /* Auto request */ +#define RDMCHCR_DE (0x00000001U) /* DMA Enable */ +#define RDMCHCRB_DRST (0x00008000U) /* Descriptor reset */ +#define RDMCHCRB_SLM_256 (0x00000080U) /* once in 256 clock cycle */ +#define RDMDPBASE_SEL_EXT (0x00000001U) /* External memory use */ + +static void start_rtdma0_descriptor(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); + reg &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + if (reg == (PRR_PRODUCT_M3_CUT10)) { + /* Enable clock supply to RTDMAC. */ + mstpcr_write(CPG_SCMSTPCR0, CPG_MSTPSR0, SCMSTPCR0_RTDMAC); + + /* Initialize ch0, Reset Descriptor */ + mmio_write_32(RTDMAC_RDMCHCLR, BIT(RTDMAC_CH)); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_DRST); + + /* Enable DMA */ + mmio_write_16(RTDMAC_RDMOR, RDMOR_DME); + + /* Set first transfer */ + mmio_write_32(RTDMAC_RDMSAR(RTDMAC_CH), RCAR_PRR); + mmio_write_32(RTDMAC_RDMDAR(RTDMAC_CH), SCIF3_SCFDR); + mmio_write_32(RTDMAC_RDMTCR(RTDMAC_CH), 0x00000001U); + + /* Set descriptor */ + mmio_write_32(RTDMAC_DESC_RDMSAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMDAR, 0x00000000U); + mmio_write_32(RTDMAC_DESC_RDMTCR, 0x00200000U); + mmio_write_32(RTDMAC_RDMCHCRB(RTDMAC_CH), RDMCHCRB_SLM_256); + mmio_write_32(RTDMAC_RDMDPBASE(RTDMAC_CH), RTDMAC_DESC_BASE + | RDMDPBASE_SEL_EXT); + + /* Set transfer parameter, Start transfer */ + mmio_write_32(RTDMAC_RDMCHCR(RTDMAC_CH), RDMCHCR_DPM_INFINITE + | RDMCHCR_RPT_TCR + | RDMCHCR_TS_2 + | RDMCHCR_RS_AUTO + | RDMCHCR_DE); + } +} + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + uint32_t prr; + + prr = mmio_read_32(RCAR_PRR); + prr &= (PRR_PRODUCT_MASK | PRR_CUT_MASK); + + mmio_write_32(PFC_PMMR, ~data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } + mmio_write_32((uintptr_t)addr, data); + if (prr == (PRR_PRODUCT_M3_CUT10)) { + mmio_write_16(SCIF3_SCFCR, SCFCR_DATA); /* Dummy write */ + } +} + +void pfc_init_g2m(void) +{ + uint32_t reg; + + /* + * PFC write access problem seen on older SoC's. Added a workaround + * in RT-DMAC for fixing the same. + */ + start_rtdma0_descriptor(); + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, MOD_SEL0_MSIOF3_A + | MOD_SEL0_MSIOF2_A + | MOD_SEL0_MSIOF1_A + | MOD_SEL0_LBSC_A + | MOD_SEL0_IEBUS_A + | MOD_SEL0_I2C2_A + | MOD_SEL0_I2C1_A + | MOD_SEL0_HSCIF4_A + | MOD_SEL0_HSCIF3_A + | MOD_SEL0_HSCIF1_A + | MOD_SEL0_FSO_A + | MOD_SEL0_HSCIF2_A + | MOD_SEL0_ETHERAVB_A + | MOD_SEL0_DRIF3_A + | MOD_SEL0_DRIF2_A + | MOD_SEL0_DRIF1_A + | MOD_SEL0_DRIF0_A + | MOD_SEL0_CANFD0_A + | MOD_SEL0_ADG_A_A); + pfc_reg_write(PFC_MOD_SEL1, MOD_SEL1_TSIF1_A + | MOD_SEL1_TSIF0_A + | MOD_SEL1_TIMER_TMU_A + | MOD_SEL1_SSP1_1_A + | MOD_SEL1_SSP1_0_A + | MOD_SEL1_SSI_A + | MOD_SEL1_SPEED_PULSE_IF_A + | MOD_SEL1_SIMCARD_A + | MOD_SEL1_SDHI2_A + | MOD_SEL1_SCIF4_A + | MOD_SEL1_SCIF3_A + | MOD_SEL1_SCIF2_A + | MOD_SEL1_SCIF1_A + | MOD_SEL1_SCIF_A + | MOD_SEL1_REMOCON_A + | MOD_SEL1_RCAN0_A + | MOD_SEL1_PWM6_A + | MOD_SEL1_PWM5_A + | MOD_SEL1_PWM4_A + | MOD_SEL1_PWM3_A + | MOD_SEL1_PWM2_A + | MOD_SEL1_PWM1_A); + pfc_reg_write(PFC_MOD_SEL2, MOD_SEL2_I2C_5_B + | MOD_SEL2_I2C_3_B + | MOD_SEL2_I2C_0_B + | MOD_SEL2_FM_A + | MOD_SEL2_SCIF5_A + | MOD_SEL2_I2C6_A + | MOD_SEL2_NDF_A + | MOD_SEL2_SSI2_A + | MOD_SEL2_SSI9_A + | MOD_SEL2_TIMER_TMU2_A + | MOD_SEL2_ADG_B_A + | MOD_SEL2_ADG_C_A + | MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR1, IPSR_28_FUNC(6) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(3) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(3)); + pfc_reg_write(PFC_IPSR2, IPSR_28_FUNC(0) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR3, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR4, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR5, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR6, IPSR_28_FUNC(6) + | IPSR_24_FUNC(6) + | IPSR_20_FUNC(6) + | IPSR_16_FUNC(6) + | IPSR_12_FUNC(6) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR7, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(6) + | IPSR_4_FUNC(6) + | IPSR_0_FUNC(6)); + pfc_reg_write(PFC_IPSR8, IPSR_28_FUNC(1) + | IPSR_24_FUNC(1) + | IPSR_20_FUNC(1) + | IPSR_16_FUNC(1) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR9, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR10, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR11, IPSR_28_FUNC(0) + | IPSR_24_FUNC(4) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR12, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(4) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR13, IPSR_28_FUNC(8) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(3) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR14, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(3) + | IPSR_0_FUNC(8)); + pfc_reg_write(PFC_IPSR15, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR16, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR17, IPSR_28_FUNC(0) + | IPSR_24_FUNC(0) + | IPSR_20_FUNC(0) + | IPSR_16_FUNC(0) + | IPSR_12_FUNC(0) + | IPSR_8_FUNC(0) + | IPSR_4_FUNC(1) + | IPSR_0_FUNC(0)); + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) + | IPSR_0_FUNC(0)); + + /* initialize GPIO/perihperal function select */ + pfc_reg_write(PFC_GPSR0, GPSR0_D15 + | GPSR0_D14 + | GPSR0_D13 + | GPSR0_D12 + | GPSR0_D11 + | GPSR0_D10 + | GPSR0_D9 + | GPSR0_D8 + | GPSR0_D7 + | GPSR0_D6 + | GPSR0_D5 + | GPSR0_D4 + | GPSR0_D3 + | GPSR0_D2 + | GPSR0_D0); + pfc_reg_write(PFC_GPSR1, GPSR1_CLKOUT + | GPSR1_EX_WAIT0_A + | GPSR1_WE1 + | GPSR1_RD + | GPSR1_RD_WR + | GPSR1_CS0 + | GPSR1_A19 + | GPSR1_A18 + | GPSR1_A17 + | GPSR1_A16 + | GPSR1_A15 + | GPSR1_A14 + | GPSR1_A13 + | GPSR1_A12 + | GPSR1_A7 + | GPSR1_A6 + | GPSR1_A5 + | GPSR1_A4 + | GPSR1_A3 + | GPSR1_A2 + | GPSR1_A1 + | GPSR1_A0); + pfc_reg_write(PFC_GPSR2, GPSR2_AVB_AVTP_CAPTURE_A + | GPSR2_AVB_AVTP_MATCH_A + | GPSR2_AVB_LINK + | GPSR2_AVB_PHY_INT + | GPSR2_AVB_MDC + | GPSR2_PWM2_A + | GPSR2_PWM1_A + | GPSR2_IRQ4 + | GPSR2_IRQ3 + | GPSR2_IRQ2 + | GPSR2_IRQ1 + | GPSR2_IRQ0); + pfc_reg_write(PFC_GPSR3, GPSR3_SD0_CD + | GPSR3_SD1_DAT3 + | GPSR3_SD1_DAT2 + | GPSR3_SD1_DAT1 + | GPSR3_SD1_DAT0 + | GPSR3_SD0_DAT3 + | GPSR3_SD0_DAT2 + | GPSR3_SD0_DAT1 + | GPSR3_SD0_DAT0 + | GPSR3_SD0_CMD + | GPSR3_SD0_CLK); + pfc_reg_write(PFC_GPSR4, GPSR4_SD3_DS + | GPSR4_SD3_DAT7 + | GPSR4_SD3_DAT6 + | GPSR4_SD3_DAT5 + | GPSR4_SD3_DAT4 + | GPSR4_SD3_DAT3 + | GPSR4_SD3_DAT2 + | GPSR4_SD3_DAT1 + | GPSR4_SD3_DAT0 + | GPSR4_SD3_CMD + | GPSR4_SD3_CLK + | GPSR4_SD2_DAT3 + | GPSR4_SD2_DAT2 + | GPSR4_SD2_DAT1 + | GPSR4_SD2_DAT0 + | GPSR4_SD2_CMD + | GPSR4_SD2_CLK); + pfc_reg_write(PFC_GPSR5, GPSR5_MSIOF0_RXD + | GPSR5_MSIOF0_TXD + | GPSR5_MSIOF0_SYNC + | GPSR5_MSIOF0_SCK + | GPSR5_RX2_A + | GPSR5_TX2_A + | GPSR5_RTS1 + | GPSR5_CTS1 + | GPSR5_TX1_A + | GPSR5_RX1_A + | GPSR5_RTS0 + | GPSR5_SCK0); + pfc_reg_write(PFC_GPSR6, GPSR6_AUDIO_CLKB_B + | GPSR6_AUDIO_CLKA_A + | GPSR6_SSI_WS6 + | GPSR6_SSI_SCK6 + | GPSR6_SSI_SDATA4 + | GPSR6_SSI_WS4 + | GPSR6_SSI_SCK4 + | GPSR6_SSI_SDATA1_A + | GPSR6_SSI_SDATA0 + | GPSR6_SSI_WS0129 + | GPSR6_SSI_SCK0129); + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 + | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, POC_SD0_DAT3_33V + | POC_SD0_DAT2_33V + | POC_SD0_DAT1_33V + | POC_SD0_DAT0_33V + | POC_SD0_CMD_33V + | POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = ((reg & DRVCTRL0_MASK) | DRVCTRL0_QSPI0_SPCLK(3) + | DRVCTRL0_QSPI0_MOSI_IO0(3) + | DRVCTRL0_QSPI0_MISO_IO1(3) + | DRVCTRL0_QSPI0_IO2(3) + | DRVCTRL0_QSPI0_IO3(3) + | DRVCTRL0_QSPI0_SSL(3) + | DRVCTRL0_QSPI1_SPCLK(3) + | DRVCTRL0_QSPI1_MOSI_IO0(3)); + pfc_reg_write(PFC_DRVCTRL0, reg); + reg = mmio_read_32(PFC_DRVCTRL1); + reg = ((reg & DRVCTRL1_MASK) | DRVCTRL1_QSPI1_MISO_IO1(3) + | DRVCTRL1_QSPI1_IO2(3) + | DRVCTRL1_QSPI1_IO3(3) + | DRVCTRL1_QSPI1_SS(3) + | DRVCTRL1_RPC_INT(3) + | DRVCTRL1_RPC_WP(3) + | DRVCTRL1_RPC_RESET(3) + | DRVCTRL1_AVB_RX_CTL(7)); + pfc_reg_write(PFC_DRVCTRL1, reg); + reg = mmio_read_32(PFC_DRVCTRL2); + reg = ((reg & DRVCTRL2_MASK) | DRVCTRL2_AVB_RXC(7) + | DRVCTRL2_AVB_RD0(7) + | DRVCTRL2_AVB_RD1(7) + | DRVCTRL2_AVB_RD2(7) + | DRVCTRL2_AVB_RD3(7) + | DRVCTRL2_AVB_TX_CTL(3) + | DRVCTRL2_AVB_TXC(3) + | DRVCTRL2_AVB_TD0(3)); + pfc_reg_write(PFC_DRVCTRL2, reg); + reg = mmio_read_32(PFC_DRVCTRL3); + reg = ((reg & DRVCTRL3_MASK) | DRVCTRL3_AVB_TD1(3) + | DRVCTRL3_AVB_TD2(3) + | DRVCTRL3_AVB_TD3(3) + | DRVCTRL3_AVB_TXCREFCLK(7) + | DRVCTRL3_AVB_MDIO(7) + | DRVCTRL3_AVB_MDC(7) + | DRVCTRL3_AVB_MAGIC(7) + | DRVCTRL3_AVB_PHY_INT(7)); + pfc_reg_write(PFC_DRVCTRL3, reg); + reg = mmio_read_32(PFC_DRVCTRL4); + reg = ((reg & DRVCTRL4_MASK) | DRVCTRL4_AVB_LINK(7) + | DRVCTRL4_AVB_AVTP_MATCH(7) + | DRVCTRL4_AVB_AVTP_CAPTURE(7) + | DRVCTRL4_IRQ0(7) + | DRVCTRL4_IRQ1(7) + | DRVCTRL4_IRQ2(7) + | DRVCTRL4_IRQ3(7) + | DRVCTRL4_IRQ4(7)); + pfc_reg_write(PFC_DRVCTRL4, reg); + reg = mmio_read_32(PFC_DRVCTRL5); + reg = ((reg & DRVCTRL5_MASK) | DRVCTRL5_IRQ5(7) + | DRVCTRL5_PWM0(7) + | DRVCTRL5_PWM1(7) + | DRVCTRL5_PWM2(7) + | DRVCTRL5_A0(3) + | DRVCTRL5_A1(3) + | DRVCTRL5_A2(3) + | DRVCTRL5_A3(3)); + pfc_reg_write(PFC_DRVCTRL5, reg); + reg = mmio_read_32(PFC_DRVCTRL6); + reg = ((reg & DRVCTRL6_MASK) | DRVCTRL6_A4(3) + | DRVCTRL6_A5(3) + | DRVCTRL6_A6(3) + | DRVCTRL6_A7(3) + | DRVCTRL6_A8(7) + | DRVCTRL6_A9(7) + | DRVCTRL6_A10(7) + | DRVCTRL6_A11(7)); + pfc_reg_write(PFC_DRVCTRL6, reg); + reg = mmio_read_32(PFC_DRVCTRL7); + reg = ((reg & DRVCTRL7_MASK) | DRVCTRL7_A12(3) + | DRVCTRL7_A13(3) + | DRVCTRL7_A14(3) + | DRVCTRL7_A15(3) + | DRVCTRL7_A16(3) + | DRVCTRL7_A17(3) + | DRVCTRL7_A18(3) + | DRVCTRL7_A19(3)); + pfc_reg_write(PFC_DRVCTRL7, reg); + reg = mmio_read_32(PFC_DRVCTRL8); + reg = ((reg & DRVCTRL8_MASK) | DRVCTRL8_CLKOUT(7) + | DRVCTRL8_CS0(7) + | DRVCTRL8_CS1_A2(7) + | DRVCTRL8_BS(7) + | DRVCTRL8_RD(7) + | DRVCTRL8_RD_W(7) + | DRVCTRL8_WE0(7) + | DRVCTRL8_WE1(7)); + pfc_reg_write(PFC_DRVCTRL8, reg); + reg = mmio_read_32(PFC_DRVCTRL9); + reg = ((reg & DRVCTRL9_MASK) | DRVCTRL9_EX_WAIT0(7) + | DRVCTRL9_PRESETOU(7) + | DRVCTRL9_D0(7) + | DRVCTRL9_D1(7) + | DRVCTRL9_D2(7) + | DRVCTRL9_D3(7) + | DRVCTRL9_D4(7) + | DRVCTRL9_D5(7)); + pfc_reg_write(PFC_DRVCTRL9, reg); + reg = mmio_read_32(PFC_DRVCTRL10); + reg = ((reg & DRVCTRL10_MASK) | DRVCTRL10_D6(7) + | DRVCTRL10_D7(7) + | DRVCTRL10_D8(3) + | DRVCTRL10_D9(3) + | DRVCTRL10_D10(3) + | DRVCTRL10_D11(3) + | DRVCTRL10_D12(3) + | DRVCTRL10_D13(3)); + pfc_reg_write(PFC_DRVCTRL10, reg); + reg = mmio_read_32(PFC_DRVCTRL11); + reg = ((reg & DRVCTRL11_MASK) | DRVCTRL11_D14(3) + | DRVCTRL11_D15(3) + | DRVCTRL11_AVS1(7) + | DRVCTRL11_AVS2(7) + | DRVCTRL11_GP7_02(7) + | DRVCTRL11_GP7_03(7) + | DRVCTRL11_DU_DOTCLKIN0(3) + | DRVCTRL11_DU_DOTCLKIN1(3)); + pfc_reg_write(PFC_DRVCTRL11, reg); + reg = mmio_read_32(PFC_DRVCTRL12); + reg = ((reg & DRVCTRL12_MASK) | DRVCTRL12_DU_DOTCLKIN2(3) + | DRVCTRL12_DU_DOTCLKIN3(3) + | DRVCTRL12_DU_FSCLKST(3) + | DRVCTRL12_DU_TMS(3)); + pfc_reg_write(PFC_DRVCTRL12, reg); + reg = mmio_read_32(PFC_DRVCTRL13); + reg = ((reg & DRVCTRL13_MASK) | DRVCTRL13_TDO(3) + | DRVCTRL13_ASEBRK(3) + | DRVCTRL13_SD0_CLK(7) + | DRVCTRL13_SD0_CMD(7) + | DRVCTRL13_SD0_DAT0(7) + | DRVCTRL13_SD0_DAT1(7) + | DRVCTRL13_SD0_DAT2(7) + | DRVCTRL13_SD0_DAT3(7)); + pfc_reg_write(PFC_DRVCTRL13, reg); + reg = mmio_read_32(PFC_DRVCTRL14); + reg = ((reg & DRVCTRL14_MASK) | DRVCTRL14_SD1_CLK(7) + | DRVCTRL14_SD1_CMD(7) + | DRVCTRL14_SD1_DAT0(5) + | DRVCTRL14_SD1_DAT1(5) + | DRVCTRL14_SD1_DAT2(5) + | DRVCTRL14_SD1_DAT3(5) + | DRVCTRL14_SD2_CLK(5) + | DRVCTRL14_SD2_CMD(5)); + pfc_reg_write(PFC_DRVCTRL14, reg); + reg = mmio_read_32(PFC_DRVCTRL15); + reg = ((reg & DRVCTRL15_MASK) | DRVCTRL15_SD2_DAT0(5) + | DRVCTRL15_SD2_DAT1(5) + | DRVCTRL15_SD2_DAT2(5) + | DRVCTRL15_SD2_DAT3(5) + | DRVCTRL15_SD2_DS(5) + | DRVCTRL15_SD3_CLK(7) + | DRVCTRL15_SD3_CMD(7) + | DRVCTRL15_SD3_DAT0(7)); + pfc_reg_write(PFC_DRVCTRL15, reg); + reg = mmio_read_32(PFC_DRVCTRL16); + reg = ((reg & DRVCTRL16_MASK) | DRVCTRL16_SD3_DAT1(7) + | DRVCTRL16_SD3_DAT2(7) + | DRVCTRL16_SD3_DAT3(7) + | DRVCTRL16_SD3_DAT4(7) + | DRVCTRL16_SD3_DAT5(7) + | DRVCTRL16_SD3_DAT6(7) + | DRVCTRL16_SD3_DAT7(7) + | DRVCTRL16_SD3_DS(7)); + pfc_reg_write(PFC_DRVCTRL16, reg); + reg = mmio_read_32(PFC_DRVCTRL17); + reg = ((reg & DRVCTRL17_MASK) | DRVCTRL17_SD0_CD(7) + | DRVCTRL17_SD0_WP(7) + | DRVCTRL17_SD1_CD(7) + | DRVCTRL17_SD1_WP(7) + | DRVCTRL17_SCK0(7) + | DRVCTRL17_RX0(7) + | DRVCTRL17_TX0(7) + | DRVCTRL17_CTS0(7)); + pfc_reg_write(PFC_DRVCTRL17, reg); + reg = mmio_read_32(PFC_DRVCTRL18); + reg = ((reg & DRVCTRL18_MASK) | DRVCTRL18_RTS0_TANS(7) + | DRVCTRL18_RX1(7) + | DRVCTRL18_TX1(7) + | DRVCTRL18_CTS1(7) + | DRVCTRL18_RTS1_TANS(7) + | DRVCTRL18_SCK2(7) + | DRVCTRL18_TX2(7) + | DRVCTRL18_RX2(7)); + pfc_reg_write(PFC_DRVCTRL18, reg); + reg = mmio_read_32(PFC_DRVCTRL19); + reg = ((reg & DRVCTRL19_MASK) | DRVCTRL19_HSCK0(7) + | DRVCTRL19_HRX0(7) + | DRVCTRL19_HTX0(7) + | DRVCTRL19_HCTS0(7) + | DRVCTRL19_HRTS0(7) + | DRVCTRL19_MSIOF0_SCK(7) + | DRVCTRL19_MSIOF0_SYNC(7) + | DRVCTRL19_MSIOF0_SS1(7)); + pfc_reg_write(PFC_DRVCTRL19, reg); + reg = mmio_read_32(PFC_DRVCTRL20); + reg = ((reg & DRVCTRL20_MASK) | DRVCTRL20_MSIOF0_TXD(7) + | DRVCTRL20_MSIOF0_SS2(7) + | DRVCTRL20_MSIOF0_RXD(7) + | DRVCTRL20_MLB_CLK(7) + | DRVCTRL20_MLB_SIG(7) + | DRVCTRL20_MLB_DAT(7) + | DRVCTRL20_MLB_REF(7) + | DRVCTRL20_SSI_SCK0129(7)); + pfc_reg_write(PFC_DRVCTRL20, reg); + reg = mmio_read_32(PFC_DRVCTRL21); + reg = ((reg & DRVCTRL21_MASK) | DRVCTRL21_SSI_WS0129(7) + | DRVCTRL21_SSI_SDATA0(7) + | DRVCTRL21_SSI_SDATA1(7) + | DRVCTRL21_SSI_SDATA2(7) + | DRVCTRL21_SSI_SCK34(7) + | DRVCTRL21_SSI_WS34(7) + | DRVCTRL21_SSI_SDATA3(7) + | DRVCTRL21_SSI_SCK4(7)); + pfc_reg_write(PFC_DRVCTRL21, reg); + reg = mmio_read_32(PFC_DRVCTRL22); + reg = ((reg & DRVCTRL22_MASK) | DRVCTRL22_SSI_WS4(7) + | DRVCTRL22_SSI_SDATA4(7) + | DRVCTRL22_SSI_SCK5(7) + | DRVCTRL22_SSI_WS5(7) + | DRVCTRL22_SSI_SDATA5(7) + | DRVCTRL22_SSI_SCK6(7) + | DRVCTRL22_SSI_WS6(7) + | DRVCTRL22_SSI_SDATA6(7)); + pfc_reg_write(PFC_DRVCTRL22, reg); + reg = mmio_read_32(PFC_DRVCTRL23); + reg = ((reg & DRVCTRL23_MASK) | DRVCTRL23_SSI_SCK78(7) + | DRVCTRL23_SSI_WS78(7) + | DRVCTRL23_SSI_SDATA7(7) + | DRVCTRL23_SSI_SDATA8(7) + | DRVCTRL23_SSI_SDATA9(7) + | DRVCTRL23_AUDIO_CLKA(7) + | DRVCTRL23_AUDIO_CLKB(7) + | DRVCTRL23_USB0_PWEN(7)); + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = ((reg & DRVCTRL24_MASK) | DRVCTRL24_USB0_OVC(7) + | DRVCTRL24_USB1_PWEN(7) + | DRVCTRL24_USB1_OVC(7) + | DRVCTRL24_USB30_PWEN(7) + | DRVCTRL24_USB30_OVC(7) + | DRVCTRL24_USB31_PWEN(7) + | DRVCTRL24_USB31_OVC(7)); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); + +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h new file mode 100644 index 0000000..3315cd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2M_H +#define PFC_INIT_G2M_H + +void pfc_init_g2m(void); + +#endif /* PFC_INIT_G2M_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c new file mode 100644 index 0000000..c951e0a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c @@ -0,0 +1,1306 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "pfc_init_g2n.h" +#include "rcar_def.h" +#include "../pfc_regs.h" + +#define GPSR0_D15 BIT(15) +#define GPSR0_D14 BIT(14) +#define GPSR0_D13 BIT(13) +#define GPSR0_D12 BIT(12) +#define GPSR0_D11 BIT(11) +#define GPSR0_D10 BIT(10) +#define GPSR0_D9 BIT(9) +#define GPSR0_D8 BIT(8) +#define GPSR0_D7 BIT(7) +#define GPSR0_D6 BIT(6) +#define GPSR0_D5 BIT(5) +#define GPSR0_D4 BIT(4) +#define GPSR0_D3 BIT(3) +#define GPSR0_D2 BIT(2) +#define GPSR0_D1 BIT(1) +#define GPSR0_D0 BIT(0) +#define GPSR1_CLKOUT BIT(28) +#define GPSR1_EX_WAIT0_A BIT(27) +#define GPSR1_WE1 BIT(26) +#define GPSR1_WE0 BIT(25) +#define GPSR1_RD_WR BIT(24) +#define GPSR1_RD BIT(23) +#define GPSR1_BS BIT(22) +#define GPSR1_CS1_A26 BIT(21) +#define GPSR1_CS0 BIT(20) +#define GPSR1_A19 BIT(19) +#define GPSR1_A18 BIT(18) +#define GPSR1_A17 BIT(17) +#define GPSR1_A16 BIT(16) +#define GPSR1_A15 BIT(15) +#define GPSR1_A14 BIT(14) +#define GPSR1_A13 BIT(13) +#define GPSR1_A12 BIT(12) +#define GPSR1_A11 BIT(11) +#define GPSR1_A10 BIT(10) +#define GPSR1_A9 BIT(9) +#define GPSR1_A8 BIT(8) +#define GPSR1_A7 BIT(7) +#define GPSR1_A6 BIT(6) +#define GPSR1_A5 BIT(5) +#define GPSR1_A4 BIT(4) +#define GPSR1_A3 BIT(3) +#define GPSR1_A2 BIT(2) +#define GPSR1_A1 BIT(1) +#define GPSR1_A0 BIT(0) +#define GPSR2_AVB_AVTP_CAPTURE_A BIT(14) +#define GPSR2_AVB_AVTP_MATCH_A BIT(13) +#define GPSR2_AVB_LINK BIT(12) +#define GPSR2_AVB_PHY_INT BIT(11) +#define GPSR2_AVB_MAGIC BIT(10) +#define GPSR2_AVB_MDC BIT(9) +#define GPSR2_PWM2_A BIT(8) +#define GPSR2_PWM1_A BIT(7) +#define GPSR2_PWM0 BIT(6) +#define GPSR2_IRQ5 BIT(5) +#define GPSR2_IRQ4 BIT(4) +#define GPSR2_IRQ3 BIT(3) +#define GPSR2_IRQ2 BIT(2) +#define GPSR2_IRQ1 BIT(1) +#define GPSR2_IRQ0 BIT(0) +#define GPSR3_SD1_WP BIT(15) +#define GPSR3_SD1_CD BIT(14) +#define GPSR3_SD0_WP BIT(13) +#define GPSR3_SD0_CD BIT(12) +#define GPSR3_SD1_DAT3 BIT(11) +#define GPSR3_SD1_DAT2 BIT(10) +#define GPSR3_SD1_DAT1 BIT(9) +#define GPSR3_SD1_DAT0 BIT(8) +#define GPSR3_SD1_CMD BIT(7) +#define GPSR3_SD1_CLK BIT(6) +#define GPSR3_SD0_DAT3 BIT(5) +#define GPSR3_SD0_DAT2 BIT(4) +#define GPSR3_SD0_DAT1 BIT(3) +#define GPSR3_SD0_DAT0 BIT(2) +#define GPSR3_SD0_CMD BIT(1) +#define GPSR3_SD0_CLK BIT(0) +#define GPSR4_SD3_DS BIT(17) +#define GPSR4_SD3_DAT7 BIT(16) +#define GPSR4_SD3_DAT6 BIT(15) +#define GPSR4_SD3_DAT5 BIT(14) +#define GPSR4_SD3_DAT4 BIT(13) +#define GPSR4_SD3_DAT3 BIT(12) +#define GPSR4_SD3_DAT2 BIT(11) +#define GPSR4_SD3_DAT1 BIT(10) +#define GPSR4_SD3_DAT0 BIT(9) +#define GPSR4_SD3_CMD BIT(8) +#define GPSR4_SD3_CLK BIT(7) +#define GPSR4_SD2_DS BIT(6) +#define GPSR4_SD2_DAT3 BIT(5) +#define GPSR4_SD2_DAT2 BIT(4) +#define GPSR4_SD2_DAT1 BIT(3) +#define GPSR4_SD2_DAT0 BIT(2) +#define GPSR4_SD2_CMD BIT(1) +#define GPSR4_SD2_CLK BIT(0) +#define GPSR5_MLB_DAT BIT(25) +#define GPSR5_MLB_SIG BIT(24) +#define GPSR5_MLB_CLK BIT(23) +#define GPSR5_MSIOF0_RXD BIT(22) +#define GPSR5_MSIOF0_SS2 BIT(21) +#define GPSR5_MSIOF0_TXD BIT(20) +#define GPSR5_MSIOF0_SS1 BIT(19) +#define GPSR5_MSIOF0_SYNC BIT(18) +#define GPSR5_MSIOF0_SCK BIT(17) +#define GPSR5_HRTS0 BIT(16) +#define GPSR5_HCTS0 BIT(15) +#define GPSR5_HTX0 BIT(14) +#define GPSR5_HRX0 BIT(13) +#define GPSR5_HSCK0 BIT(12) +#define GPSR5_RX2_A BIT(11) +#define GPSR5_TX2_A BIT(10) +#define GPSR5_SCK2 BIT(9) +#define GPSR5_RTS1 BIT(8) +#define GPSR5_CTS1 BIT(7) +#define GPSR5_TX1_A BIT(6) +#define GPSR5_RX1_A BIT(5) +#define GPSR5_RTS0 BIT(4) +#define GPSR5_CTS0 BIT(3) +#define GPSR5_TX0 BIT(2) +#define GPSR5_RX0 BIT(1) +#define GPSR5_SCK0 BIT(0) +#define GPSR6_USB31_OVC BIT(31) +#define GPSR6_USB31_PWEN BIT(30) +#define GPSR6_USB30_OVC BIT(29) +#define GPSR6_USB30_PWEN BIT(28) +#define GPSR6_USB1_OVC BIT(27) +#define GPSR6_USB1_PWEN BIT(26) +#define GPSR6_USB0_OVC BIT(25) +#define GPSR6_USB0_PWEN BIT(24) +#define GPSR6_AUDIO_CLKB_B BIT(23) +#define GPSR6_AUDIO_CLKA_A BIT(22) +#define GPSR6_SSI_SDATA9_A BIT(21) +#define GPSR6_SSI_SDATA8 BIT(20) +#define GPSR6_SSI_SDATA7 BIT(19) +#define GPSR6_SSI_WS78 BIT(18) +#define GPSR6_SSI_SCK78 BIT(17) +#define GPSR6_SSI_SDATA6 BIT(16) +#define GPSR6_SSI_WS6 BIT(15) +#define GPSR6_SSI_SCK6 BIT(14) +#define GPSR6_SSI_SDATA5 BIT(13) +#define GPSR6_SSI_WS5 BIT(12) +#define GPSR6_SSI_SCK5 BIT(11) +#define GPSR6_SSI_SDATA4 BIT(10) +#define GPSR6_SSI_WS4 BIT(9) +#define GPSR6_SSI_SCK4 BIT(8) +#define GPSR6_SSI_SDATA3 BIT(7) +#define GPSR6_SSI_WS34 BIT(6) +#define GPSR6_SSI_SCK34 BIT(5) +#define GPSR6_SSI_SDATA2_A BIT(4) +#define GPSR6_SSI_SDATA1_A BIT(3) +#define GPSR6_SSI_SDATA0 BIT(2) +#define GPSR6_SSI_WS0129 BIT(1) +#define GPSR6_SSI_SCK0129 BIT(0) +#define GPSR7_AVS2 BIT(1) +#define GPSR7_AVS1 BIT(0) + +#define IPSR_28_FUNC(x) ((uint32_t)(x) << 28U) +#define IPSR_24_FUNC(x) ((uint32_t)(x) << 24U) +#define IPSR_20_FUNC(x) ((uint32_t)(x) << 20U) +#define IPSR_16_FUNC(x) ((uint32_t)(x) << 16U) +#define IPSR_12_FUNC(x) ((uint32_t)(x) << 12U) +#define IPSR_8_FUNC(x) ((uint32_t)(x) << 8U) +#define IPSR_4_FUNC(x) ((uint32_t)(x) << 4U) +#define IPSR_0_FUNC(x) ((uint32_t)(x) << 0U) + +#define POC_SD3_DS_33V BIT(29) +#define POC_SD3_DAT7_33V BIT(28) +#define POC_SD3_DAT6_33V BIT(27) +#define POC_SD3_DAT5_33V BIT(26) +#define POC_SD3_DAT4_33V BIT(25) +#define POC_SD3_DAT3_33V BIT(24) +#define POC_SD3_DAT2_33V BIT(23) +#define POC_SD3_DAT1_33V BIT(22) +#define POC_SD3_DAT0_33V BIT(21) +#define POC_SD3_CMD_33V BIT(20) +#define POC_SD3_CLK_33V BIT(19) +#define POC_SD2_DS_33V BIT(18) +#define POC_SD2_DAT3_33V BIT(17) +#define POC_SD2_DAT2_33V BIT(16) +#define POC_SD2_DAT1_33V BIT(15) +#define POC_SD2_DAT0_33V BIT(14) +#define POC_SD2_CMD_33V BIT(13) +#define POC_SD2_CLK_33V BIT(12) +#define POC_SD1_DAT3_33V BIT(11) +#define POC_SD1_DAT2_33V BIT(10) +#define POC_SD1_DAT1_33V BIT(9) +#define POC_SD1_DAT0_33V BIT(8) +#define POC_SD1_CMD_33V BIT(7) +#define POC_SD1_CLK_33V BIT(6) +#define POC_SD0_DAT3_33V BIT(5) +#define POC_SD0_DAT2_33V BIT(4) +#define POC_SD0_DAT1_33V BIT(3) +#define POC_SD0_DAT0_33V BIT(2) +#define POC_SD0_CMD_33V BIT(1) +#define POC_SD0_CLK_33V BIT(0) + +#define DRVCTRL0_MASK (0xCCCCCCCCU) +#define DRVCTRL1_MASK (0xCCCCCCC8U) +#define DRVCTRL2_MASK (0x88888888U) +#define DRVCTRL3_MASK (0x88888888U) +#define DRVCTRL4_MASK (0x88888888U) +#define DRVCTRL5_MASK (0x88888888U) +#define DRVCTRL6_MASK (0x88888888U) +#define DRVCTRL7_MASK (0x88888888U) +#define DRVCTRL8_MASK (0x88888888U) +#define DRVCTRL9_MASK (0x88888888U) +#define DRVCTRL10_MASK (0x88888888U) +#define DRVCTRL11_MASK (0x888888CCU) +#define DRVCTRL12_MASK (0xCCCFFFCFU) +#define DRVCTRL13_MASK (0xCC888888U) +#define DRVCTRL14_MASK (0x88888888U) +#define DRVCTRL15_MASK (0x88888888U) +#define DRVCTRL16_MASK (0x88888888U) +#define DRVCTRL17_MASK (0x88888888U) +#define DRVCTRL18_MASK (0x88888888U) +#define DRVCTRL19_MASK (0x88888888U) +#define DRVCTRL20_MASK (0x88888888U) +#define DRVCTRL21_MASK (0x88888888U) +#define DRVCTRL22_MASK (0x88888888U) +#define DRVCTRL23_MASK (0x88888888U) +#define DRVCTRL24_MASK (0x8888888FU) + +#define DRVCTRL0_QSPI0_SPCLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL0_QSPI0_MOSI_IO0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL0_QSPI0_MISO_IO1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL0_QSPI0_IO2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL0_QSPI0_IO3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL0_QSPI0_SSL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL0_QSPI1_SPCLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL0_QSPI1_MOSI_IO0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL1_QSPI1_MISO_IO1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL1_QSPI1_IO2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL1_QSPI1_IO3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL1_QSPI1_SS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL1_RPC_INT(x) ((uint32_t)(x) << 12U) +#define DRVCTRL1_RPC_WP(x) ((uint32_t)(x) << 8U) +#define DRVCTRL1_RPC_RESET(x) ((uint32_t)(x) << 4U) +#define DRVCTRL1_AVB_RX_CTL(x) ((uint32_t)(x) << 0U) +#define DRVCTRL2_AVB_RXC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL2_AVB_RD0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL2_AVB_RD1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL2_AVB_RD2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL2_AVB_RD3(x) ((uint32_t)(x) << 12U) +#define DRVCTRL2_AVB_TX_CTL(x) ((uint32_t)(x) << 8U) +#define DRVCTRL2_AVB_TXC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL2_AVB_TD0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL3_AVB_TD1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL3_AVB_TD2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL3_AVB_TD3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL3_AVB_TXCREFCLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL3_AVB_MDIO(x) ((uint32_t)(x) << 12U) +#define DRVCTRL3_AVB_MDC(x) ((uint32_t)(x) << 8U) +#define DRVCTRL3_AVB_MAGIC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL3_AVB_PHY_INT(x) ((uint32_t)(x) << 0U) +#define DRVCTRL4_AVB_LINK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL4_AVB_AVTP_MATCH(x) ((uint32_t)(x) << 24U) +#define DRVCTRL4_AVB_AVTP_CAPTURE(x) ((uint32_t)(x) << 20U) +#define DRVCTRL4_IRQ0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL4_IRQ1(x) ((uint32_t)(x) << 12U) +#define DRVCTRL4_IRQ2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL4_IRQ3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL4_IRQ4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL5_IRQ5(x) ((uint32_t)(x) << 28U) +#define DRVCTRL5_PWM0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL5_PWM1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL5_PWM2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL5_A0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL5_A1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL5_A2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL5_A3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL6_A4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL6_A5(x) ((uint32_t)(x) << 24U) +#define DRVCTRL6_A6(x) ((uint32_t)(x) << 20U) +#define DRVCTRL6_A7(x) ((uint32_t)(x) << 16U) +#define DRVCTRL6_A8(x) ((uint32_t)(x) << 12U) +#define DRVCTRL6_A9(x) ((uint32_t)(x) << 8U) +#define DRVCTRL6_A10(x) ((uint32_t)(x) << 4U) +#define DRVCTRL6_A11(x) ((uint32_t)(x) << 0U) +#define DRVCTRL7_A12(x) ((uint32_t)(x) << 28U) +#define DRVCTRL7_A13(x) ((uint32_t)(x) << 24U) +#define DRVCTRL7_A14(x) ((uint32_t)(x) << 20U) +#define DRVCTRL7_A15(x) ((uint32_t)(x) << 16U) +#define DRVCTRL7_A16(x) ((uint32_t)(x) << 12U) +#define DRVCTRL7_A17(x) ((uint32_t)(x) << 8U) +#define DRVCTRL7_A18(x) ((uint32_t)(x) << 4U) +#define DRVCTRL7_A19(x) ((uint32_t)(x) << 0U) +#define DRVCTRL8_CLKOUT(x) ((uint32_t)(x) << 28U) +#define DRVCTRL8_CS0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL8_CS1_A2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL8_BS(x) ((uint32_t)(x) << 16U) +#define DRVCTRL8_RD(x) ((uint32_t)(x) << 12U) +#define DRVCTRL8_RD_W(x) ((uint32_t)(x) << 8U) +#define DRVCTRL8_WE0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL8_WE1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL9_EX_WAIT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL9_PRESETOU(x) ((uint32_t)(x) << 24U) +#define DRVCTRL9_D0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL9_D1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL9_D2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL9_D3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL9_D4(x) ((uint32_t)(x) << 4U) +#define DRVCTRL9_D5(x) ((uint32_t)(x) << 0U) +#define DRVCTRL10_D6(x) ((uint32_t)(x) << 28U) +#define DRVCTRL10_D7(x) ((uint32_t)(x) << 24U) +#define DRVCTRL10_D8(x) ((uint32_t)(x) << 20U) +#define DRVCTRL10_D9(x) ((uint32_t)(x) << 16U) +#define DRVCTRL10_D10(x) ((uint32_t)(x) << 12U) +#define DRVCTRL10_D11(x) ((uint32_t)(x) << 8U) +#define DRVCTRL10_D12(x) ((uint32_t)(x) << 4U) +#define DRVCTRL10_D13(x) ((uint32_t)(x) << 0U) +#define DRVCTRL11_D14(x) ((uint32_t)(x) << 28U) +#define DRVCTRL11_D15(x) ((uint32_t)(x) << 24U) +#define DRVCTRL11_AVS1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL11_AVS2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL11_GP7_02(x) ((uint32_t)(x) << 12U) +#define DRVCTRL11_GP7_03(x) ((uint32_t)(x) << 8U) +#define DRVCTRL11_DU_DOTCLKIN0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL11_DU_DOTCLKIN1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL12_DU_DOTCLKIN2(x) ((uint32_t)(x) << 28U) +#define DRVCTRL12_DU_DOTCLKIN3(x) ((uint32_t)(x) << 24U) +#define DRVCTRL12_DU_FSCLKST(x) ((uint32_t)(x) << 20U) +#define DRVCTRL12_DU_TMS(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_TDO(x) ((uint32_t)(x) << 28U) +#define DRVCTRL13_ASEBRK(x) ((uint32_t)(x) << 24U) +#define DRVCTRL13_SD0_CLK(x) ((uint32_t)(x) << 20U) +#define DRVCTRL13_SD0_CMD(x) ((uint32_t)(x) << 16U) +#define DRVCTRL13_SD0_DAT0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL13_SD0_DAT1(x) ((uint32_t)(x) << 8U) +#define DRVCTRL13_SD0_DAT2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL13_SD0_DAT3(x) ((uint32_t)(x) << 0U) +#define DRVCTRL14_SD1_CLK(x) ((uint32_t)(x) << 28U) +#define DRVCTRL14_SD1_CMD(x) ((uint32_t)(x) << 24U) +#define DRVCTRL14_SD1_DAT0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL14_SD1_DAT1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL14_SD1_DAT2(x) ((uint32_t)(x) << 12U) +#define DRVCTRL14_SD1_DAT3(x) ((uint32_t)(x) << 8U) +#define DRVCTRL14_SD2_CLK(x) ((uint32_t)(x) << 4U) +#define DRVCTRL14_SD2_CMD(x) ((uint32_t)(x) << 0U) +#define DRVCTRL15_SD2_DAT0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL15_SD2_DAT1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL15_SD2_DAT2(x) ((uint32_t)(x) << 20U) +#define DRVCTRL15_SD2_DAT3(x) ((uint32_t)(x) << 16U) +#define DRVCTRL15_SD2_DS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL15_SD3_CLK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL15_SD3_CMD(x) ((uint32_t)(x) << 4U) +#define DRVCTRL15_SD3_DAT0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL16_SD3_DAT1(x) ((uint32_t)(x) << 28U) +#define DRVCTRL16_SD3_DAT2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL16_SD3_DAT3(x) ((uint32_t)(x) << 20U) +#define DRVCTRL16_SD3_DAT4(x) ((uint32_t)(x) << 16U) +#define DRVCTRL16_SD3_DAT5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL16_SD3_DAT6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL16_SD3_DAT7(x) ((uint32_t)(x) << 4U) +#define DRVCTRL16_SD3_DS(x) ((uint32_t)(x) << 0U) +#define DRVCTRL17_SD0_CD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL17_SD0_WP(x) ((uint32_t)(x) << 24U) +#define DRVCTRL17_SD1_CD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL17_SD1_WP(x) ((uint32_t)(x) << 16U) +#define DRVCTRL17_SCK0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL17_RX0(x) ((uint32_t)(x) << 8U) +#define DRVCTRL17_TX0(x) ((uint32_t)(x) << 4U) +#define DRVCTRL17_CTS0(x) ((uint32_t)(x) << 0U) +#define DRVCTRL18_RTS0_TANS(x) ((uint32_t)(x) << 28U) +#define DRVCTRL18_RX1(x) ((uint32_t)(x) << 24U) +#define DRVCTRL18_TX1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL18_CTS1(x) ((uint32_t)(x) << 16U) +#define DRVCTRL18_RTS1_TANS(x) ((uint32_t)(x) << 12U) +#define DRVCTRL18_SCK2(x) ((uint32_t)(x) << 8U) +#define DRVCTRL18_TX2(x) ((uint32_t)(x) << 4U) +#define DRVCTRL18_RX2(x) ((uint32_t)(x) << 0U) +#define DRVCTRL19_HSCK0(x) ((uint32_t)(x) << 28U) +#define DRVCTRL19_HRX0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL19_HTX0(x) ((uint32_t)(x) << 20U) +#define DRVCTRL19_HCTS0(x) ((uint32_t)(x) << 16U) +#define DRVCTRL19_HRTS0(x) ((uint32_t)(x) << 12U) +#define DRVCTRL19_MSIOF0_SCK(x) ((uint32_t)(x) << 8U) +#define DRVCTRL19_MSIOF0_SYNC(x) ((uint32_t)(x) << 4U) +#define DRVCTRL19_MSIOF0_SS1(x) ((uint32_t)(x) << 0U) +#define DRVCTRL20_MSIOF0_TXD(x) ((uint32_t)(x) << 28U) +#define DRVCTRL20_MSIOF0_SS2(x) ((uint32_t)(x) << 24U) +#define DRVCTRL20_MSIOF0_RXD(x) ((uint32_t)(x) << 20U) +#define DRVCTRL20_MLB_CLK(x) ((uint32_t)(x) << 16U) +#define DRVCTRL20_MLB_SIG(x) ((uint32_t)(x) << 12U) +#define DRVCTRL20_MLB_DAT(x) ((uint32_t)(x) << 8U) +#define DRVCTRL20_MLB_REF(x) ((uint32_t)(x) << 4U) +#define DRVCTRL20_SSI_SCK0129(x) ((uint32_t)(x) << 0U) +#define DRVCTRL21_SSI_WS0129(x) ((uint32_t)(x) << 28U) +#define DRVCTRL21_SSI_SDATA0(x) ((uint32_t)(x) << 24U) +#define DRVCTRL21_SSI_SDATA1(x) ((uint32_t)(x) << 20U) +#define DRVCTRL21_SSI_SDATA2(x) ((uint32_t)(x) << 16U) +#define DRVCTRL21_SSI_SCK34(x) ((uint32_t)(x) << 12U) +#define DRVCTRL21_SSI_WS34(x) ((uint32_t)(x) << 8U) +#define DRVCTRL21_SSI_SDATA3(x) ((uint32_t)(x) << 4U) +#define DRVCTRL21_SSI_SCK4(x) ((uint32_t)(x) << 0U) +#define DRVCTRL22_SSI_WS4(x) ((uint32_t)(x) << 28U) +#define DRVCTRL22_SSI_SDATA4(x) ((uint32_t)(x) << 24U) +#define DRVCTRL22_SSI_SCK5(x) ((uint32_t)(x) << 20U) +#define DRVCTRL22_SSI_WS5(x) ((uint32_t)(x) << 16U) +#define DRVCTRL22_SSI_SDATA5(x) ((uint32_t)(x) << 12U) +#define DRVCTRL22_SSI_SCK6(x) ((uint32_t)(x) << 8U) +#define DRVCTRL22_SSI_WS6(x) ((uint32_t)(x) << 4U) +#define DRVCTRL22_SSI_SDATA6(x) ((uint32_t)(x) << 0U) +#define DRVCTRL23_SSI_SCK78(x) ((uint32_t)(x) << 28U) +#define DRVCTRL23_SSI_WS78(x) ((uint32_t)(x) << 24U) +#define DRVCTRL23_SSI_SDATA7(x) ((uint32_t)(x) << 20U) +#define DRVCTRL23_SSI_SDATA8(x) ((uint32_t)(x) << 16U) +#define DRVCTRL23_SSI_SDATA9(x) ((uint32_t)(x) << 12U) +#define DRVCTRL23_AUDIO_CLKA(x) ((uint32_t)(x) << 8U) +#define DRVCTRL23_AUDIO_CLKB(x) ((uint32_t)(x) << 4U) +#define DRVCTRL23_USB0_PWEN(x) ((uint32_t)(x) << 0U) +#define DRVCTRL24_USB0_OVC(x) ((uint32_t)(x) << 28U) +#define DRVCTRL24_USB1_PWEN(x) ((uint32_t)(x) << 24U) +#define DRVCTRL24_USB1_OVC(x) ((uint32_t)(x) << 20U) +#define DRVCTRL24_USB30_PWEN(x) ((uint32_t)(x) << 16U) +#define DRVCTRL24_USB30_OVC(x) ((uint32_t)(x) << 12U) +#define DRVCTRL24_USB31_PWEN(x) ((uint32_t)(x) << 8U) +#define DRVCTRL24_USB31_OVC(x) ((uint32_t)(x) << 4U) + +#define MOD_SEL0_MSIOF3_A ((uint32_t)0U << 29U) +#define MOD_SEL0_MSIOF3_B ((uint32_t)1U << 29U) +#define MOD_SEL0_MSIOF3_C ((uint32_t)2U << 29U) +#define MOD_SEL0_MSIOF3_D ((uint32_t)3U << 29U) +#define MOD_SEL0_MSIOF3_E ((uint32_t)4U << 29U) +#define MOD_SEL0_MSIOF2_A ((uint32_t)0U << 27U) +#define MOD_SEL0_MSIOF2_B ((uint32_t)1U << 27U) +#define MOD_SEL0_MSIOF2_C ((uint32_t)2U << 27U) +#define MOD_SEL0_MSIOF2_D ((uint32_t)3U << 27U) +#define MOD_SEL0_MSIOF1_A ((uint32_t)0U << 24U) +#define MOD_SEL0_MSIOF1_B ((uint32_t)1U << 24U) +#define MOD_SEL0_MSIOF1_C ((uint32_t)2U << 24U) +#define MOD_SEL0_MSIOF1_D ((uint32_t)3U << 24U) +#define MOD_SEL0_MSIOF1_E ((uint32_t)4U << 24U) +#define MOD_SEL0_MSIOF1_F ((uint32_t)5U << 24U) +#define MOD_SEL0_MSIOF1_G ((uint32_t)6U << 24U) +#define MOD_SEL0_LBSC_A ((uint32_t)0U << 23U) +#define MOD_SEL0_LBSC_B ((uint32_t)1U << 23U) +#define MOD_SEL0_IEBUS_A ((uint32_t)0U << 22U) +#define MOD_SEL0_IEBUS_B ((uint32_t)1U << 22U) +#define MOD_SEL0_I2C2_A ((uint32_t)0U << 21U) +#define MOD_SEL0_I2C2_B ((uint32_t)1U << 21U) +#define MOD_SEL0_I2C1_A ((uint32_t)0U << 20U) +#define MOD_SEL0_I2C1_B ((uint32_t)1U << 20U) +#define MOD_SEL0_HSCIF4_A ((uint32_t)0U << 19U) +#define MOD_SEL0_HSCIF4_B ((uint32_t)1U << 19U) +#define MOD_SEL0_HSCIF3_A ((uint32_t)0U << 17U) +#define MOD_SEL0_HSCIF3_B ((uint32_t)1U << 17U) +#define MOD_SEL0_HSCIF3_C ((uint32_t)2U << 17U) +#define MOD_SEL0_HSCIF3_D ((uint32_t)3U << 17U) +#define MOD_SEL0_HSCIF1_A ((uint32_t)0U << 16U) +#define MOD_SEL0_HSCIF1_B ((uint32_t)1U << 16U) +#define MOD_SEL0_FSO_A ((uint32_t)0U << 15U) +#define MOD_SEL0_FSO_B ((uint32_t)1U << 15U) +#define MOD_SEL0_HSCIF2_A ((uint32_t)0U << 13U) +#define MOD_SEL0_HSCIF2_B ((uint32_t)1U << 13U) +#define MOD_SEL0_HSCIF2_C ((uint32_t)2U << 13U) +#define MOD_SEL0_ETHERAVB_A ((uint32_t)0U << 12U) +#define MOD_SEL0_ETHERAVB_B ((uint32_t)1U << 12U) +#define MOD_SEL0_DRIF3_A ((uint32_t)0U << 11U) +#define MOD_SEL0_DRIF3_B ((uint32_t)1U << 11U) +#define MOD_SEL0_DRIF2_A ((uint32_t)0U << 10U) +#define MOD_SEL0_DRIF2_B ((uint32_t)1U << 10U) +#define MOD_SEL0_DRIF1_A ((uint32_t)0U << 8U) +#define MOD_SEL0_DRIF1_B ((uint32_t)1U << 8U) +#define MOD_SEL0_DRIF1_C ((uint32_t)2U << 8U) +#define MOD_SEL0_DRIF0_A ((uint32_t)0U << 6U) +#define MOD_SEL0_DRIF0_B ((uint32_t)1U << 6U) +#define MOD_SEL0_DRIF0_C ((uint32_t)2U << 6U) +#define MOD_SEL0_CANFD0_A ((uint32_t)0U << 5U) +#define MOD_SEL0_CANFD0_B ((uint32_t)1U << 5U) +#define MOD_SEL0_ADG_A_A ((uint32_t)0U << 3U) +#define MOD_SEL0_ADG_A_B ((uint32_t)1U << 3U) +#define MOD_SEL0_ADG_A_C ((uint32_t)2U << 3U) +#define MOD_SEL1_TSIF1_A ((uint32_t)0U << 30U) +#define MOD_SEL1_TSIF1_B ((uint32_t)1U << 30U) +#define MOD_SEL1_TSIF1_C ((uint32_t)2U << 30U) +#define MOD_SEL1_TSIF1_D ((uint32_t)3U << 30U) +#define MOD_SEL1_TSIF0_A ((uint32_t)0U << 27U) +#define MOD_SEL1_TSIF0_B ((uint32_t)1U << 27U) +#define MOD_SEL1_TSIF0_C ((uint32_t)2U << 27U) +#define MOD_SEL1_TSIF0_D ((uint32_t)3U << 27U) +#define MOD_SEL1_TSIF0_E ((uint32_t)4U << 27U) +#define MOD_SEL1_TIMER_TMU_A ((uint32_t)0U << 26U) +#define MOD_SEL1_TIMER_TMU_B ((uint32_t)1U << 26U) +#define MOD_SEL1_SSP1_1_A ((uint32_t)0U << 24U) +#define MOD_SEL1_SSP1_1_B ((uint32_t)1U << 24U) +#define MOD_SEL1_SSP1_1_C ((uint32_t)2U << 24U) +#define MOD_SEL1_SSP1_1_D ((uint32_t)3U << 24U) +#define MOD_SEL1_SSP1_0_A ((uint32_t)0U << 21U) +#define MOD_SEL1_SSP1_0_B ((uint32_t)1U << 21U) +#define MOD_SEL1_SSP1_0_C ((uint32_t)2U << 21U) +#define MOD_SEL1_SSP1_0_D ((uint32_t)3U << 21U) +#define MOD_SEL1_SSP1_0_E ((uint32_t)4U << 21U) +#define MOD_SEL1_SSI_A ((uint32_t)0U << 20U) +#define MOD_SEL1_SSI_B ((uint32_t)1U << 20U) +#define MOD_SEL1_SPEED_PULSE_IF_A ((uint32_t)0U << 19U) +#define MOD_SEL1_SPEED_PULSE_IF_B ((uint32_t)1U << 19U) +#define MOD_SEL1_SIMCARD_A ((uint32_t)0U << 17U) +#define MOD_SEL1_SIMCARD_B ((uint32_t)1U << 17U) +#define MOD_SEL1_SIMCARD_C ((uint32_t)2U << 17U) +#define MOD_SEL1_SIMCARD_D ((uint32_t)3U << 17U) +#define MOD_SEL1_SDHI2_A ((uint32_t)0U << 16U) +#define MOD_SEL1_SDHI2_B ((uint32_t)1U << 16U) +#define MOD_SEL1_SCIF4_A ((uint32_t)0U << 14U) +#define MOD_SEL1_SCIF4_B ((uint32_t)1U << 14U) +#define MOD_SEL1_SCIF4_C ((uint32_t)2U << 14U) +#define MOD_SEL1_SCIF3_A ((uint32_t)0U << 13U) +#define MOD_SEL1_SCIF3_B ((uint32_t)1U << 13U) +#define MOD_SEL1_SCIF2_A ((uint32_t)0U << 12U) +#define MOD_SEL1_SCIF2_B ((uint32_t)1U << 12U) +#define MOD_SEL1_SCIF1_A ((uint32_t)0U << 11U) +#define MOD_SEL1_SCIF1_B ((uint32_t)1U << 11U) +#define MOD_SEL1_SCIF_A ((uint32_t)0U << 10U) +#define MOD_SEL1_SCIF_B ((uint32_t)1U << 10U) +#define MOD_SEL1_REMOCON_A ((uint32_t)0U << 9U) +#define MOD_SEL1_REMOCON_B ((uint32_t)1U << 9U) +#define MOD_SEL1_RCAN0_A ((uint32_t)0U << 6U) +#define MOD_SEL1_RCAN0_B ((uint32_t)1U << 6U) +#define MOD_SEL1_PWM6_A ((uint32_t)0U << 5U) +#define MOD_SEL1_PWM6_B ((uint32_t)1U << 5U) +#define MOD_SEL1_PWM5_A ((uint32_t)0U << 4U) +#define MOD_SEL1_PWM5_B ((uint32_t)1U << 4U) +#define MOD_SEL1_PWM4_A ((uint32_t)0U << 3U) +#define MOD_SEL1_PWM4_B ((uint32_t)1U << 3U) +#define MOD_SEL1_PWM3_A ((uint32_t)0U << 2U) +#define MOD_SEL1_PWM3_B ((uint32_t)1U << 2U) +#define MOD_SEL1_PWM2_A ((uint32_t)0U << 1U) +#define MOD_SEL1_PWM2_B ((uint32_t)1U << 1U) +#define MOD_SEL1_PWM1_A ((uint32_t)0U << 0U) +#define MOD_SEL1_PWM1_B ((uint32_t)1U << 0U) +#define MOD_SEL2_I2C_5_A ((uint32_t)0U << 31U) +#define MOD_SEL2_I2C_5_B ((uint32_t)1U << 31U) +#define MOD_SEL2_I2C_3_A ((uint32_t)0U << 30U) +#define MOD_SEL2_I2C_3_B ((uint32_t)1U << 30U) +#define MOD_SEL2_I2C_0_A ((uint32_t)0U << 29U) +#define MOD_SEL2_I2C_0_B ((uint32_t)1U << 29U) +#define MOD_SEL2_FM_A ((uint32_t)0U << 27U) +#define MOD_SEL2_FM_B ((uint32_t)1U << 27U) +#define MOD_SEL2_FM_C ((uint32_t)2U << 27U) +#define MOD_SEL2_FM_D ((uint32_t)3U << 27U) +#define MOD_SEL2_SCIF5_A ((uint32_t)0U << 26U) +#define MOD_SEL2_SCIF5_B ((uint32_t)1U << 26U) +#define MOD_SEL2_I2C6_A ((uint32_t)0U << 23U) +#define MOD_SEL2_I2C6_B ((uint32_t)1U << 23U) +#define MOD_SEL2_I2C6_C ((uint32_t)2U << 23U) +#define MOD_SEL2_NDF_A ((uint32_t)0U << 22U) +#define MOD_SEL2_NDF_B ((uint32_t)1U << 22U) +#define MOD_SEL2_SSI2_A ((uint32_t)0U << 21U) +#define MOD_SEL2_SSI2_B ((uint32_t)1U << 21U) +#define MOD_SEL2_SSI9_A ((uint32_t)0U << 20U) +#define MOD_SEL2_SSI9_B ((uint32_t)1U << 20U) +#define MOD_SEL2_TIMER_TMU2_A ((uint32_t)0U << 19U) +#define MOD_SEL2_TIMER_TMU2_B ((uint32_t)1U << 19U) +#define MOD_SEL2_ADG_B_A ((uint32_t)0U << 18U) +#define MOD_SEL2_ADG_B_B ((uint32_t)1U << 18U) +#define MOD_SEL2_ADG_C_A ((uint32_t)0U << 17U) +#define MOD_SEL2_ADG_C_B ((uint32_t)1U << 17U) +#define MOD_SEL2_VIN4_A ((uint32_t)0U << 0U) +#define MOD_SEL2_VIN4_B ((uint32_t)1U << 0U) + +static void pfc_reg_write(uint32_t addr, uint32_t data) +{ + mmio_write_32(PFC_PMMR, ~data); + mmio_write_32((uintptr_t)addr, data); +} + +void pfc_init_g2n(void) +{ + uint32_t reg; + + /* initialize module select */ + pfc_reg_write(PFC_MOD_SEL0, + MOD_SEL0_MSIOF3_A | + MOD_SEL0_MSIOF2_A | + MOD_SEL0_MSIOF1_A | + MOD_SEL0_LBSC_A | + MOD_SEL0_IEBUS_A | + MOD_SEL0_I2C2_A | + MOD_SEL0_I2C1_A | + MOD_SEL0_HSCIF4_A | + MOD_SEL0_HSCIF3_A | + MOD_SEL0_HSCIF1_A | + MOD_SEL0_FSO_A | + MOD_SEL0_HSCIF2_A | + MOD_SEL0_ETHERAVB_A | + MOD_SEL0_DRIF3_A | + MOD_SEL0_DRIF2_A | + MOD_SEL0_DRIF1_A | + MOD_SEL0_DRIF0_A | + MOD_SEL0_CANFD0_A | + MOD_SEL0_ADG_A_A); + + pfc_reg_write(PFC_MOD_SEL1, + MOD_SEL1_TSIF1_A | + MOD_SEL1_TSIF0_A | + MOD_SEL1_TIMER_TMU_A | + MOD_SEL1_SSP1_1_A | + MOD_SEL1_SSP1_0_A | + MOD_SEL1_SSI_A | + MOD_SEL1_SPEED_PULSE_IF_A | + MOD_SEL1_SIMCARD_A | + MOD_SEL1_SDHI2_A | + MOD_SEL1_SCIF4_A | + MOD_SEL1_SCIF3_A | + MOD_SEL1_SCIF2_A | + MOD_SEL1_SCIF1_A | + MOD_SEL1_SCIF_A | + MOD_SEL1_REMOCON_A | + MOD_SEL1_RCAN0_A | + MOD_SEL1_PWM6_A | + MOD_SEL1_PWM5_A | + MOD_SEL1_PWM4_A | + MOD_SEL1_PWM3_A | + MOD_SEL1_PWM2_A | + MOD_SEL1_PWM1_A); + + pfc_reg_write(PFC_MOD_SEL2, + MOD_SEL2_I2C_5_B | + MOD_SEL2_I2C_3_B | + MOD_SEL2_I2C_0_B | + MOD_SEL2_FM_A | + MOD_SEL2_SCIF5_A | + MOD_SEL2_I2C6_A | + MOD_SEL2_NDF_A | + MOD_SEL2_SSI2_A | + MOD_SEL2_SSI9_A | + MOD_SEL2_TIMER_TMU2_A | + MOD_SEL2_ADG_B_A | + MOD_SEL2_ADG_C_A | + MOD_SEL2_VIN4_A); + + /* initialize peripheral function select */ + pfc_reg_write(PFC_IPSR0, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR1, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(3) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(3)); + + pfc_reg_write(PFC_IPSR2, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR3, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR4, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR5, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR6, + IPSR_28_FUNC(6) | + IPSR_24_FUNC(6) | + IPSR_20_FUNC(6) | + IPSR_16_FUNC(6) | + IPSR_12_FUNC(6) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR7, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(6) | + IPSR_4_FUNC(6) | + IPSR_0_FUNC(6)); + + pfc_reg_write(PFC_IPSR8, + IPSR_28_FUNC(1) | + IPSR_24_FUNC(1) | + IPSR_20_FUNC(1) | + IPSR_16_FUNC(1) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR9, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR10, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR11, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(4) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR12, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(4) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR13, + IPSR_28_FUNC(8) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(3) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR14, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(3) | + IPSR_0_FUNC(8)); + + pfc_reg_write(PFC_IPSR15, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR16, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(0) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR17, + IPSR_28_FUNC(0) | + IPSR_24_FUNC(0) | + IPSR_20_FUNC(0) | + IPSR_16_FUNC(0) | + IPSR_12_FUNC(0) | + IPSR_8_FUNC(0) | + IPSR_4_FUNC(1) | + IPSR_0_FUNC(0)); + + pfc_reg_write(PFC_IPSR18, IPSR_4_FUNC(0) | IPSR_0_FUNC(0)); + + /* initialize GPIO/peripheral function select */ + pfc_reg_write(PFC_GPSR0, + GPSR0_D15 | + GPSR0_D14 | + GPSR0_D13 | + GPSR0_D12 | + GPSR0_D11 | + GPSR0_D10 | + GPSR0_D9 | + GPSR0_D8 | + GPSR0_D7 | + GPSR0_D6 | + GPSR0_D5 | + GPSR0_D4 | + GPSR0_D3 | + GPSR0_D2 | + GPSR0_D0); + + pfc_reg_write(PFC_GPSR1, + GPSR1_CLKOUT | + GPSR1_EX_WAIT0_A | + GPSR1_WE1 | + GPSR1_RD | + GPSR1_RD_WR | + GPSR1_CS0 | + GPSR1_A19 | + GPSR1_A18 | + GPSR1_A17 | + GPSR1_A16 | + GPSR1_A15 | + GPSR1_A14 | + GPSR1_A13 | + GPSR1_A12 | + GPSR1_A7 | + GPSR1_A6 | + GPSR1_A5 | + GPSR1_A4 | + GPSR1_A3 | + GPSR1_A2 | + GPSR1_A1 | + GPSR1_A0); + + pfc_reg_write(PFC_GPSR2, + GPSR2_AVB_AVTP_CAPTURE_A | + GPSR2_AVB_AVTP_MATCH_A | + GPSR2_AVB_LINK | + GPSR2_AVB_PHY_INT | + GPSR2_AVB_MDC | + GPSR2_PWM2_A | + GPSR2_PWM1_A | + GPSR2_IRQ4 | + GPSR2_IRQ3 | + GPSR2_IRQ2 | + GPSR2_IRQ1 | + GPSR2_IRQ0); + + pfc_reg_write(PFC_GPSR3, + GPSR3_SD0_CD | + GPSR3_SD1_DAT3 | + GPSR3_SD1_DAT2 | + GPSR3_SD1_DAT1 | + GPSR3_SD1_DAT0 | + GPSR3_SD0_DAT3 | + GPSR3_SD0_DAT2 | + GPSR3_SD0_DAT1 | + GPSR3_SD0_DAT0 | + GPSR3_SD0_CMD | + GPSR3_SD0_CLK); + + pfc_reg_write(PFC_GPSR4, + GPSR4_SD3_DS | + GPSR4_SD3_DAT7 | + GPSR4_SD3_DAT6 | + GPSR4_SD3_DAT5 | + GPSR4_SD3_DAT4 | + GPSR4_SD3_DAT3 | + GPSR4_SD3_DAT2 | + GPSR4_SD3_DAT1 | + GPSR4_SD3_DAT0 | + GPSR4_SD3_CMD | + GPSR4_SD3_CLK | + GPSR4_SD2_DAT3 | + GPSR4_SD2_DAT2 | + GPSR4_SD2_DAT1 | + GPSR4_SD2_DAT0 | + GPSR4_SD2_CMD | + GPSR4_SD2_CLK); + + pfc_reg_write(PFC_GPSR5, + GPSR5_MSIOF0_RXD | + GPSR5_MSIOF0_TXD | + GPSR5_MSIOF0_SYNC | + GPSR5_MSIOF0_SCK | + GPSR5_RX2_A | + GPSR5_TX2_A | + GPSR5_RTS1 | + GPSR5_CTS1 | + GPSR5_TX1_A | + GPSR5_RX1_A | + GPSR5_RTS0 | + GPSR5_SCK0); + + pfc_reg_write(PFC_GPSR6, + GPSR6_AUDIO_CLKB_B | + GPSR6_AUDIO_CLKA_A | + GPSR6_SSI_WS6 | + GPSR6_SSI_SCK6 | + GPSR6_SSI_SDATA4 | + GPSR6_SSI_WS4 | + GPSR6_SSI_SCK4 | + GPSR6_SSI_SDATA1_A | + GPSR6_SSI_SDATA0 | + GPSR6_SSI_WS0129 | + GPSR6_SSI_SCK0129); + + pfc_reg_write(PFC_GPSR7, GPSR7_AVS2 | GPSR7_AVS1); + + /* initialize POC control register */ + pfc_reg_write(PFC_POCCTRL0, + POC_SD0_DAT3_33V | + POC_SD0_DAT2_33V | + POC_SD0_DAT1_33V | + POC_SD0_DAT0_33V | + POC_SD0_CMD_33V | + POC_SD0_CLK_33V); + + /* initialize DRV control register */ + reg = mmio_read_32(PFC_DRVCTRL0); + reg = (reg & DRVCTRL0_MASK) | + DRVCTRL0_QSPI0_SPCLK(3) | + DRVCTRL0_QSPI0_MOSI_IO0(3) | + DRVCTRL0_QSPI0_MISO_IO1(3) | + DRVCTRL0_QSPI0_IO2(3) | + DRVCTRL0_QSPI0_IO3(3) | + DRVCTRL0_QSPI0_SSL(3) | + DRVCTRL0_QSPI1_SPCLK(3) | + DRVCTRL0_QSPI1_MOSI_IO0(3); + pfc_reg_write(PFC_DRVCTRL0, reg); + + reg = mmio_read_32(PFC_DRVCTRL1); + reg = (reg & DRVCTRL1_MASK) | + DRVCTRL1_QSPI1_MISO_IO1(3) | + DRVCTRL1_QSPI1_IO2(3) | + DRVCTRL1_QSPI1_IO3(3) | + DRVCTRL1_QSPI1_SS(3) | + DRVCTRL1_RPC_INT(3) | + DRVCTRL1_RPC_WP(3) | + DRVCTRL1_RPC_RESET(3) | + DRVCTRL1_AVB_RX_CTL(7); + pfc_reg_write(PFC_DRVCTRL1, reg); + + reg = mmio_read_32(PFC_DRVCTRL2); + reg = (reg & DRVCTRL2_MASK) | + DRVCTRL2_AVB_RXC(7) | + DRVCTRL2_AVB_RD0(7) | + DRVCTRL2_AVB_RD1(7) | + DRVCTRL2_AVB_RD2(7) | + DRVCTRL2_AVB_RD3(7) | + DRVCTRL2_AVB_TX_CTL(3) | + DRVCTRL2_AVB_TXC(3) | + DRVCTRL2_AVB_TD0(3); + pfc_reg_write(PFC_DRVCTRL2, reg); + + reg = mmio_read_32(PFC_DRVCTRL3); + reg = (reg & DRVCTRL3_MASK) | + DRVCTRL3_AVB_TD1(3) | + DRVCTRL3_AVB_TD2(3) | + DRVCTRL3_AVB_TD3(3) | + DRVCTRL3_AVB_TXCREFCLK(7) | + DRVCTRL3_AVB_MDIO(7) | + DRVCTRL3_AVB_MDC(7) | + DRVCTRL3_AVB_MAGIC(7) | + DRVCTRL3_AVB_PHY_INT(7); + pfc_reg_write(PFC_DRVCTRL3, reg); + + reg = mmio_read_32(PFC_DRVCTRL4); + reg = (reg & DRVCTRL4_MASK) | + DRVCTRL4_AVB_LINK(7) | + DRVCTRL4_AVB_AVTP_MATCH(7) | + DRVCTRL4_AVB_AVTP_CAPTURE(7) | + DRVCTRL4_IRQ0(7) | + DRVCTRL4_IRQ1(7) | + DRVCTRL4_IRQ2(7) | + DRVCTRL4_IRQ3(7) | + DRVCTRL4_IRQ4(7); + pfc_reg_write(PFC_DRVCTRL4, reg); + + reg = mmio_read_32(PFC_DRVCTRL5); + reg = (reg & DRVCTRL5_MASK) | + DRVCTRL5_IRQ5(7) | + DRVCTRL5_PWM0(7) | + DRVCTRL5_PWM1(7) | + DRVCTRL5_PWM2(7) | + DRVCTRL5_A0(3) | + DRVCTRL5_A1(3) | + DRVCTRL5_A2(3) | + DRVCTRL5_A3(3); + pfc_reg_write(PFC_DRVCTRL5, reg); + + reg = mmio_read_32(PFC_DRVCTRL6); + reg = (reg & DRVCTRL6_MASK) | + DRVCTRL6_A4(3) | + DRVCTRL6_A5(3) | + DRVCTRL6_A6(3) | + DRVCTRL6_A7(3) | + DRVCTRL6_A8(7) | + DRVCTRL6_A9(7) | + DRVCTRL6_A10(7) | + DRVCTRL6_A11(7); + pfc_reg_write(PFC_DRVCTRL6, reg); + + reg = mmio_read_32(PFC_DRVCTRL7); + reg = (reg & DRVCTRL7_MASK) | + DRVCTRL7_A12(3) | + DRVCTRL7_A13(3) | + DRVCTRL7_A14(3) | + DRVCTRL7_A15(3) | + DRVCTRL7_A16(3) | + DRVCTRL7_A17(3) | + DRVCTRL7_A18(3) | + DRVCTRL7_A19(3); + pfc_reg_write(PFC_DRVCTRL7, reg); + + reg = mmio_read_32(PFC_DRVCTRL8); + reg = (reg & DRVCTRL8_MASK) | + DRVCTRL8_CLKOUT(7) | + DRVCTRL8_CS0(7) | + DRVCTRL8_CS1_A2(7) | + DRVCTRL8_BS(7) | + DRVCTRL8_RD(7) | + DRVCTRL8_RD_W(7) | + DRVCTRL8_WE0(7) | + DRVCTRL8_WE1(7); + pfc_reg_write(PFC_DRVCTRL8, reg); + + reg = mmio_read_32(PFC_DRVCTRL9); + reg = (reg & DRVCTRL9_MASK) | + DRVCTRL9_EX_WAIT0(7) | + DRVCTRL9_PRESETOU(7) | + DRVCTRL9_D0(7) | + DRVCTRL9_D1(7) | + DRVCTRL9_D2(7) | + DRVCTRL9_D3(7) | + DRVCTRL9_D4(7) | + DRVCTRL9_D5(7); + pfc_reg_write(PFC_DRVCTRL9, reg); + + reg = mmio_read_32(PFC_DRVCTRL10); + reg = (reg & DRVCTRL10_MASK) | + DRVCTRL10_D6(7) | + DRVCTRL10_D7(7) | + DRVCTRL10_D8(3) | + DRVCTRL10_D9(3) | + DRVCTRL10_D10(3) | + DRVCTRL10_D11(3) | + DRVCTRL10_D12(3) | + DRVCTRL10_D13(3); + pfc_reg_write(PFC_DRVCTRL10, reg); + + reg = mmio_read_32(PFC_DRVCTRL11); + reg = (reg & DRVCTRL11_MASK) | + DRVCTRL11_D14(3) | + DRVCTRL11_D15(3) | + DRVCTRL11_AVS1(7) | + DRVCTRL11_AVS2(7) | + DRVCTRL11_GP7_02(7) | + DRVCTRL11_GP7_03(7) | + DRVCTRL11_DU_DOTCLKIN0(3) | + DRVCTRL11_DU_DOTCLKIN1(3); + pfc_reg_write(PFC_DRVCTRL11, reg); + + reg = mmio_read_32(PFC_DRVCTRL12); + reg = (reg & DRVCTRL12_MASK) | + DRVCTRL12_DU_DOTCLKIN2(3) | + DRVCTRL12_DU_DOTCLKIN3(3) | + DRVCTRL12_DU_FSCLKST(3) | + DRVCTRL12_DU_TMS(3); + pfc_reg_write(PFC_DRVCTRL12, reg); + + reg = mmio_read_32(PFC_DRVCTRL13); + reg = (reg & DRVCTRL13_MASK) | + DRVCTRL13_TDO(3) | + DRVCTRL13_ASEBRK(3) | + DRVCTRL13_SD0_CLK(7) | + DRVCTRL13_SD0_CMD(7) | + DRVCTRL13_SD0_DAT0(7) | + DRVCTRL13_SD0_DAT1(7) | + DRVCTRL13_SD0_DAT2(7) | + DRVCTRL13_SD0_DAT3(7); + pfc_reg_write(PFC_DRVCTRL13, reg); + + reg = mmio_read_32(PFC_DRVCTRL14); + reg = (reg & DRVCTRL14_MASK) | + DRVCTRL14_SD1_CLK(7) | + DRVCTRL14_SD1_CMD(7) | + DRVCTRL14_SD1_DAT0(5) | + DRVCTRL14_SD1_DAT1(5) | + DRVCTRL14_SD1_DAT2(5) | + DRVCTRL14_SD1_DAT3(5) | + DRVCTRL14_SD2_CLK(5) | + DRVCTRL14_SD2_CMD(5); + pfc_reg_write(PFC_DRVCTRL14, reg); + + reg = mmio_read_32(PFC_DRVCTRL15); + reg = (reg & DRVCTRL15_MASK) | + DRVCTRL15_SD2_DAT0(5) | + DRVCTRL15_SD2_DAT1(5) | + DRVCTRL15_SD2_DAT2(5) | + DRVCTRL15_SD2_DAT3(5) | + DRVCTRL15_SD2_DS(5) | + DRVCTRL15_SD3_CLK(7) | + DRVCTRL15_SD3_CMD(7) | + DRVCTRL15_SD3_DAT0(7); + pfc_reg_write(PFC_DRVCTRL15, reg); + + reg = mmio_read_32(PFC_DRVCTRL16); + reg = (reg & DRVCTRL16_MASK) | + DRVCTRL16_SD3_DAT1(7) | + DRVCTRL16_SD3_DAT2(7) | + DRVCTRL16_SD3_DAT3(7) | + DRVCTRL16_SD3_DAT4(7) | + DRVCTRL16_SD3_DAT5(7) | + DRVCTRL16_SD3_DAT6(7) | + DRVCTRL16_SD3_DAT7(7) | + DRVCTRL16_SD3_DS(7); + pfc_reg_write(PFC_DRVCTRL16, reg); + + reg = mmio_read_32(PFC_DRVCTRL17); + reg = (reg & DRVCTRL17_MASK) | + DRVCTRL17_SD0_CD(7) | + DRVCTRL17_SD0_WP(7) | + DRVCTRL17_SD1_CD(7) | + DRVCTRL17_SD1_WP(7) | + DRVCTRL17_SCK0(7) | + DRVCTRL17_RX0(7) | + DRVCTRL17_TX0(7) | + DRVCTRL17_CTS0(7); + pfc_reg_write(PFC_DRVCTRL17, reg); + + reg = mmio_read_32(PFC_DRVCTRL18); + reg = (reg & DRVCTRL18_MASK) | + DRVCTRL18_RTS0_TANS(7) | + DRVCTRL18_RX1(7) | + DRVCTRL18_TX1(7) | + DRVCTRL18_CTS1(7) | + DRVCTRL18_RTS1_TANS(7) | + DRVCTRL18_SCK2(7) | + DRVCTRL18_TX2(7) | + DRVCTRL18_RX2(7); + pfc_reg_write(PFC_DRVCTRL18, reg); + + reg = mmio_read_32(PFC_DRVCTRL19); + reg = (reg & DRVCTRL19_MASK) | + DRVCTRL19_HSCK0(7) | + DRVCTRL19_HRX0(7) | + DRVCTRL19_HTX0(7) | + DRVCTRL19_HCTS0(7) | + DRVCTRL19_HRTS0(7) | + DRVCTRL19_MSIOF0_SCK(7) | + DRVCTRL19_MSIOF0_SYNC(7) | + DRVCTRL19_MSIOF0_SS1(7); + pfc_reg_write(PFC_DRVCTRL19, reg); + + reg = mmio_read_32(PFC_DRVCTRL20); + reg = (reg & DRVCTRL20_MASK) | + DRVCTRL20_MSIOF0_TXD(7) | + DRVCTRL20_MSIOF0_SS2(7) | + DRVCTRL20_MSIOF0_RXD(7) | + DRVCTRL20_MLB_CLK(7) | + DRVCTRL20_MLB_SIG(7) | + DRVCTRL20_MLB_DAT(7) | + DRVCTRL20_MLB_REF(7) | + DRVCTRL20_SSI_SCK0129(7); + pfc_reg_write(PFC_DRVCTRL20, reg); + + reg = mmio_read_32(PFC_DRVCTRL21); + reg = (reg & DRVCTRL21_MASK) | + DRVCTRL21_SSI_WS0129(7) | + DRVCTRL21_SSI_SDATA0(7) | + DRVCTRL21_SSI_SDATA1(7) | + DRVCTRL21_SSI_SDATA2(7) | + DRVCTRL21_SSI_SCK34(7) | + DRVCTRL21_SSI_WS34(7) | + DRVCTRL21_SSI_SDATA3(7) | + DRVCTRL21_SSI_SCK4(7); + pfc_reg_write(PFC_DRVCTRL21, reg); + + reg = mmio_read_32(PFC_DRVCTRL22); + reg = (reg & DRVCTRL22_MASK) | + DRVCTRL22_SSI_WS4(7) | + DRVCTRL22_SSI_SDATA4(7) | + DRVCTRL22_SSI_SCK5(7) | + DRVCTRL22_SSI_WS5(7) | + DRVCTRL22_SSI_SDATA5(7) | + DRVCTRL22_SSI_SCK6(7) | + DRVCTRL22_SSI_WS6(7) | + DRVCTRL22_SSI_SDATA6(7); + pfc_reg_write(PFC_DRVCTRL22, reg); + + reg = mmio_read_32(PFC_DRVCTRL23); + reg = (reg & DRVCTRL23_MASK) | + DRVCTRL23_SSI_SCK78(7) | + DRVCTRL23_SSI_WS78(7) | + DRVCTRL23_SSI_SDATA7(7) | + DRVCTRL23_SSI_SDATA8(7) | + DRVCTRL23_SSI_SDATA9(7) | + DRVCTRL23_AUDIO_CLKA(7) | + DRVCTRL23_AUDIO_CLKB(7) | + DRVCTRL23_USB0_PWEN(7); + + pfc_reg_write(PFC_DRVCTRL23, reg); + reg = mmio_read_32(PFC_DRVCTRL24); + reg = (reg & DRVCTRL24_MASK) | + DRVCTRL24_USB0_OVC(7) | + DRVCTRL24_USB1_PWEN(7) | + DRVCTRL24_USB1_OVC(7) | + DRVCTRL24_USB30_PWEN(7) | + DRVCTRL24_USB30_OVC(7) | + DRVCTRL24_USB31_PWEN(7) | + DRVCTRL24_USB31_OVC(7); + pfc_reg_write(PFC_DRVCTRL24, reg); + + /* initialize LSI pin pull-up/down control */ + pfc_reg_write(PFC_PUD0, 0x00005FBFU); + pfc_reg_write(PFC_PUD1, 0x00300EFEU); + pfc_reg_write(PFC_PUD2, 0x330001E6U); + pfc_reg_write(PFC_PUD3, 0x000002E0U); + pfc_reg_write(PFC_PUD4, 0xFFFFFF00U); + pfc_reg_write(PFC_PUD5, 0x7F5FFF87U); + pfc_reg_write(PFC_PUD6, 0x00000055U); + + /* initialize LSI pin pull-enable register */ + pfc_reg_write(PFC_PUEN0, 0x00000FFFU); + pfc_reg_write(PFC_PUEN1, 0x00100234U); + pfc_reg_write(PFC_PUEN2, 0x000004C4U); + pfc_reg_write(PFC_PUEN3, 0x00000200U); + pfc_reg_write(PFC_PUEN4, 0x3E000000U); + pfc_reg_write(PFC_PUEN5, 0x1F000805U); + pfc_reg_write(PFC_PUEN6, 0x00000006U); + + /* initialize positive/negative logic select */ + mmio_write_32(GPIO_POSNEG0, 0x00000000U); + mmio_write_32(GPIO_POSNEG1, 0x00000000U); + mmio_write_32(GPIO_POSNEG2, 0x00000000U); + mmio_write_32(GPIO_POSNEG3, 0x00000000U); + mmio_write_32(GPIO_POSNEG4, 0x00000000U); + mmio_write_32(GPIO_POSNEG5, 0x00000000U); + mmio_write_32(GPIO_POSNEG6, 0x00000000U); + mmio_write_32(GPIO_POSNEG7, 0x00000000U); + + /* initialize general IO/interrupt switching */ + mmio_write_32(GPIO_IOINTSEL0, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL1, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL2, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL3, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL4, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL5, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL6, 0x00000000U); + mmio_write_32(GPIO_IOINTSEL7, 0x00000000U); + + /* initialize general output register */ + mmio_write_32(GPIO_OUTDT0, 0x00000001U); + mmio_write_32(GPIO_OUTDT1, 0x00000000U); + mmio_write_32(GPIO_OUTDT2, 0x00000400U); + mmio_write_32(GPIO_OUTDT3, 0x00000000U); + mmio_write_32(GPIO_OUTDT4, 0x00000000U); + mmio_write_32(GPIO_OUTDT5, 0x00000000U); + mmio_write_32(GPIO_OUTDT6, 0x00003800U); + mmio_write_32(GPIO_OUTDT7, 0x00000003U); + + /* initialize general input/output switching */ + mmio_write_32(GPIO_INOUTSEL0, 0x00000001U); + mmio_write_32(GPIO_INOUTSEL1, 0x00100B00U); + mmio_write_32(GPIO_INOUTSEL2, 0x00000418U); + mmio_write_32(GPIO_INOUTSEL3, 0x00002000U); + mmio_write_32(GPIO_INOUTSEL4, 0x00000040U); + mmio_write_32(GPIO_INOUTSEL5, 0x00000208U); + mmio_write_32(GPIO_INOUTSEL6, 0x00013F00U); + mmio_write_32(GPIO_INOUTSEL7, 0x00000003U); +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h new file mode 100644 index 0000000..f0616b6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PFC_INIT_G2N_H +#define PFC_INIT_G2N_H + +void pfc_init_g2n(void); + +#endif /* PFC_INIT_G2N_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk new file mode 100644 index 0000000..15d0e8d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc.mk @@ -0,0 +1,41 @@ +# +# Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + +else ifdef RCAR_LSI_CUT_COMPAT + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + endif +else + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c + endif +endif + +BL2_SOURCES += drivers/renesas/rzg/pfc/pfc_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c new file mode 100644 index 0000000..762450c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include + +#if RCAR_LSI == RCAR_AUTO +#include "G2E/pfc_init_g2e.h" +#include "G2H/pfc_init_g2h.h" +#include "G2M/pfc_init_g2m.h" +#include "G2N/pfc_init_g2n.h" +#endif /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2E) +#include "G2E/pfc_init_g2e.h" +#endif /* RCAR_LSI == RZ_G2N */ +#if (RCAR_LSI == RZ_G2H) +#include "G2H/pfc_init_g2h.h" +#endif /* RCAR_LSI == RZ_G2H */ +#if (RCAR_LSI == RZ_G2M) +#include "G2M/pfc_init_g2m.h" +#endif /* RCAR_LSI == RZ_G2M */ +#if (RCAR_LSI == RZ_G2N) +#include "G2N/pfc_init_g2n.h" +#endif /* RCAR_LSI == RZ_G2N */ +#include "rcar_def.h" + +#define PRR_PRODUCT_ERR(reg) \ + do { \ + ERROR("LSI Product ID(PRR=0x%x) PFC init not supported.\n", \ + reg); \ + panic(); \ + } while (0) + +#define PRR_CUT_ERR(reg) \ + do { \ + ERROR("LSI Cut ID(PRR=0x%x) PFC init not supported.\n", \ + reg); \ + panic();\ + } while (0) + +void rzg_pfc_init(void) +{ + uint32_t reg; + + reg = mmio_read_32(RCAR_PRR); +#if RCAR_LSI == RCAR_AUTO + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: + pfc_init_g2m(); + break; + case PRR_PRODUCT_H3: + pfc_init_g2h(); + break; + case PRR_PRODUCT_M3N: + pfc_init_g2n(); + break; + case PRR_PRODUCT_E3: + pfc_init_g2e(); + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#elif RCAR_LSI_CUT_COMPAT /* RCAR_LSI == RCAR_AUTO */ + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: +#if RCAR_LSI != RZ_G2M + PRR_PRODUCT_ERR(reg); +#else /* RCAR_LSI != RZ_G2M */ + pfc_init_g2m(); +#endif /* RCAR_LSI != RZ_G2M */ + break; + case PRR_PRODUCT_H3: +#if (RCAR_LSI != RZ_G2H) + PRR_PRODUCT_ERR(reg); +#else /* RCAR_LSI != RZ_G2H */ + pfc_init_g2h(); +#endif /* RCAR_LSI != RZ_G2H */ + break; + case PRR_PRODUCT_M3N: +#if RCAR_LSI != RZ_G2N + PRR_PRODUCT_ERR(reg); +#else + pfc_init_g2n(); +#endif /* RCAR_LSI != RZ_G2N */ + break; + case PRR_PRODUCT_E3: +#if RCAR_LSI != RZ_G2E + PRR_PRODUCT_ERR(reg); +#else + pfc_init_g2e(); +#endif + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } + +#else /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2M) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_M3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_m3(); +#elif (RCAR_LSI == RZ_G2H) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_H3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2h(); +#elif (RCAR_LSI == RZ_G2N) /* G2N */ + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_M3N) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2n(); +#elif (RCAR_LSI == RZ_G2E) + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_E3) { + PRR_PRODUCT_ERR(reg); + } + pfc_init_g2e(); +#else /* RCAR_LSI == RZ_G2M */ +#error "Don't have PFC initialize routine(unknown)." +#endif /* RCAR_LSI == RZ_G2M */ +#endif /* RCAR_LSI == RCAR_AUTO */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c new file mode 100644 index 0000000..14ccc21 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2e_v10.h" +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.05" + +#define REF_ARS_ARBSTOPCYCLE_G2E (((SL_INIT_SSLOTCLK_G2E) - 5U) << 16U) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2e_v10_mstat390.h" +#else +#include "qos_init_g2e_v10_mstat780.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +static const struct rcar_gen3_dbsc_qos_settings g2e_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2e_v10(void) +{ + rzg_qos_dbsc_setting(g2e_qos, ARRAY_SIZE(g2e_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RCAR_RZ_G2E +#error "Don't set DRAM Split 4ch(G2E)" +#else + ERROR("DRAM Split 4ch not supported.(G2E)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RCAR_RZ_G2E +#error "Don't set DRAM Split 2ch(G2E)" +#else + ERROR("DRAM Split 2ch not supported.(G2E)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 7.8 usec\n"); +#endif + + mmio_write_32(QOSCTRL_RAS, 0x00000020U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000000U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2E); + mmio_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_G2E); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h new file mode 100644 index 0000000..d27de1b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_H +#define QOS_INIT_G2E_V10_H + +void qos_init_g2e_v10(void); + +#endif /* QOS_INIT_G2E_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h new file mode 100644 index 0000000..63b08c4 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_MSTAT390_H +#define QOS_INIT_G2E_V10_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008620000FFFFUL, + /* 0x0038, */ 0x001008620000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415260000FFFFUL, + /* 0x0060, */ 0x001415260000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414930000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08380000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08380000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x000C21E40000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001008530000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C960000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001008530000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0010042A0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D8D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001008530000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005FFFC01UL, + /* 0x01c8, */ 0x0021060005FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0011010005F79801UL, + /* 0x0220, */ 0x0011010005F79801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005F79801UL, + /* 0x0238, */ 0x0011010005F79801UL, + /* 0x0240, */ 0x0012010005F79801UL, + /* 0x0248, */ 0x0011010005F79801UL, + /* 0x0250, */ 0x0012010005F79801UL, + /* 0x0258, */ 0x0011010005F79801UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005FFFC01UL, + /* 0x02f8, */ 0x0011060005FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005FFFC01UL, + /* 0x0360, */ 0x0012060005FFFC01UL, + /* 0x0368, */ 0x0012001005F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005F03401UL, +}; +#endif /* QOS_INIT_G2E_V10_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h new file mode 100644 index 0000000..3b888ea --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2E_V10_MSTAT780_H +#define QOS_INIT_G2E_V10_MSTAT780_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001010C40000FFFFUL, + /* 0x0038, */ 0x001010C40000FFFFUL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00142A4B0000FFFFUL, + /* 0x0060, */ 0x00142A4B0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001429260000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C10700000FFFFUL, + /* 0x00a8, */ 0x000C08210000FFFFUL, + /* 0x00b0, */ 0x000C082A0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C10700000FFFFUL, + /* 0x00c8, */ 0x000C08210000FFFFUL, + /* 0x00d0, */ 0x000C082A0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x00102CAF0000FFFFUL, + /* 0x00f8, */ 0x000C0C9D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100CAF0000FFFFUL, + /* 0x0118, */ 0x000C43C80000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010152C0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037190000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04040000FFFFUL, + /* 0x01f0, */ 0x000C08110000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04110000FFFFUL, + /* 0x0210, */ 0x000C08110000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C18530000FFFFUL, + /* 0x0268, */ 0x00141C070000FFFFUL, + /* 0x0270, */ 0x001404040000FFFFUL, + /* 0x0278, */ 0x000C0C210000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x00141C070000FFFFUL, + /* 0x0298, */ 0x001404040000FFFFUL, + /* 0x02a0, */ 0x000C04110000FFFFUL, + /* 0x02a8, */ 0x000C04110000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x000C04040000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04110000FFFFUL, + /* 0x02d8, */ 0x000C04110000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x000C04040000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04040000FFFFUL, + /* 0x0378, */ 0x000C04040000FFFFUL, + /* 0x0380, */ 0x000C04110000FFFFUL, + /* 0x0388, */ 0x000C04110000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001002F03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060002FFFC01UL, + /* 0x01c8, */ 0x0021060002FFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010002F3CC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010002F3CC01UL, + /* 0x0218, */ 0x0011010002F3CC01UL, + /* 0x0220, */ 0x0011010002F3CC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010002F3CC01UL, + /* 0x0238, */ 0x0011010002F3CC01UL, + /* 0x0240, */ 0x0012010002F3CC01UL, + /* 0x0248, */ 0x0011010002F3CC01UL, + /* 0x0250, */ 0x0012010002F3CC01UL, + /* 0x0258, */ 0x0011010002F3CC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060002FFFC01UL, + /* 0x02f8, */ 0x0011060002FFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001002F03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060002FFFC01UL, + /* 0x0360, */ 0x0012060002FFFC01UL, + /* 0x0368, */ 0x0012001002F03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001002F03401UL, +}; + +#endif /* QOS_INIT_G2E_V10_MSTAT780_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h new file mode 100644 index 0000000..7bb34aa --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_MSTAT195_H +#define QOS_INIT_G2H_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001410070000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x0014100D0000FFFFUL, + /* 0x0060, */ 0x0014100D0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x001024090000FFFFUL, + /* 0x00e0, */ 0x00100C090000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x000C100D0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x000C1C1B0000FFFFUL, + /* 0x0120, */ 0x000C1C1B0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x00100C0B0000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0010100D0000FFFFUL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x00100C0B0000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x001008060000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x00102C2C0000FFFFUL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x00100C0B0000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200600BDFFC01UL, + /* 0x0008, */ 0x001200600BDFFC01UL, + /* 0x0010, */ 0x001200600BDFFC01UL, + /* 0x0018, */ 0x001200600BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100100BDF2401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100100BDF2401UL, + /* 0x0218, */ 0x001100100BDF2401UL, + /* 0x0220, */ 0x001100100BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100BDF2401UL, + /* 0x0238, */ 0x001100100BDF2401UL, + /* 0x0240, */ 0x001200100BDF2401UL, + /* 0x0248, */ 0x001100100BDF2401UL, + /* 0x0250, */ 0x001200100BDF2401UL, + /* 0x0258, */ 0x001100100BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100600BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100600BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x001100600BDFFC01UL, + /* 0x0328, */ 0x001100600BDFFC01UL, + /* 0x0330, */ 0x001100600BDFFC01UL, + /* 0x0338, */ 0x001100600BDFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x001200100BD0FC01UL, +}; + +#endif /* QOS_INIT_G2H_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h new file mode 100644 index 0000000..9696a40 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_MSTAT390_H +#define QOS_INIT_G2H_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x0010100D0000FFFFUL, + /* 0x0040, */ 0x00141C0E0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001408010000FFFFUL, + /* 0x0058, */ 0x00141C190000FFFFUL, + /* 0x0060, */ 0x00141C190000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001408010000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x001044110000FFFFUL, + /* 0x00e0, */ 0x001014110000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x000C1C1A0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x000C38360000FFFFUL, + /* 0x0120, */ 0x000C38360000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x001018150000FFFFUL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x00101C190000FFFFUL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x001018150000FFFFUL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x00100C0B0000FFFFUL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x001058570000FFFFUL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x001018150000FFFFUL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012006005EFFC01UL, + /* 0x0008, */ 0x0012006005EFFC01UL, + /* 0x0010, */ 0x0012006005EFFC01UL, + /* 0x0018, */ 0x0012006005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E0FC01UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021006005EFFC01UL, + /* 0x01c8, */ 0x0021006005EFFC01UL, + /* 0x01d0, */ 0x0021006005EFFC01UL, + /* 0x01d8, */ 0x0021006005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021001005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021001005E79401UL, + /* 0x0218, */ 0x0011001005E79401UL, + /* 0x0220, */ 0x0011001005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011001005E79401UL, + /* 0x0238, */ 0x0011001005E79401UL, + /* 0x0240, */ 0x0012001005E79401UL, + /* 0x0248, */ 0x0011001005E79401UL, + /* 0x0250, */ 0x0012001005E79401UL, + /* 0x0258, */ 0x0011001005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011006005EFFC01UL, + /* 0x02f8, */ 0x0011006005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011006005EFFC01UL, + /* 0x0310, */ 0x0011006005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0011006005EFFC01UL, + /* 0x0328, */ 0x0011006005EFFC01UL, + /* 0x0330, */ 0x0011006005EFFC01UL, + /* 0x0338, */ 0x0011006005EFFC01UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0012001005E0FC01UL, +}; + +#endif /* QOS_INIT_G2H_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h new file mode 100644 index 0000000..044f246 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_QOSWT195_H +#define QOS_INIT_G2H_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001410070000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0014100D0000C010UL, + /* 0x0060, */ 0x0014100D0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001410070000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2H_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h new file mode 100644 index 0000000..2ae07ab --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_QOSWT390_H +#define QOS_INIT_G2H_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x0010100D0000C010UL, + /* 0x0040, */ 0x00141C0E0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00141C190000C010UL, + /* 0x0060, */ 0x00141C190000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x00141C0E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2H_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c new file mode 100644 index 0000000..7f466c8 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2h_v30.h" +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.07" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2H (SL_INIT_SSLOTCLK_G2H - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2H ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2H) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2H (QOSWT_WTSET0_PERIOD0_G2H) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_SSLOT0) +#define QOSWT_WTSET1_SLOTSLOT1 (QOSWT_WTSET0_SLOTSLOT0) + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2h_mstat195.h" +#else +#include "qos_init_g2h_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2h_qoswt195.h" +#else +#include "qos_init_g2h_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +static const struct rcar_gen3_dbsc_qos_settings g2h_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2h_v30(void) +{ + unsigned int split_area; + + rzg_qos_dbsc_setting(g2h_v30_qos, ARRAY_SIZE(g2h_v30_qos), true); + + /* use 1(2GB) for RCAR_DRAM_LPDDR4_MEMCONF for G2H */ + split_area = 0x1CU; + + /* DRAM split address mapping */ +#if (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH) +#if RCAR_LSI == RZ_G2H +#error "Don't set DRAM Split 4ch(G2H)" +#else /* RCAR_LSI == RZ_G2H */ + ERROR("DRAM split 4ch not supported.(G2H)"); + panic(); +#endif /* RCAR_LSI == RZ_G2H */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch(DDR %x)\n", (int)qos_init_ddr_phyvalid); + + mmio_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(split_area) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + mmio_write_32(AXI_ADSPLCR0, ADSPLCR0_AREA(split_area)); + NOTICE("BL2: DRAM Split is OFF(DDR %x)\n", (int)qos_init_ddr_phyvalid); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + /* GPU Boost Mode */ + mmio_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2H); + mmio_write_32(QOSCTRL_REF_ARS, ((QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2H << 16))); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* AXI setting */ + mmio_write_32(AXI_MMCR, 0x00010008U); + mmio_write_32(AXI_TR3CR, 0x00010000U); + mmio_write_32(AXI_TR4CR, 0x00010000U); + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + mmio_write_32(QOSWT_WTSET0, + ((QOSWT_WTSET0_PERIOD0_G2H << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + mmio_write_32(QOSWT_WTSET1, + ((QOSWT_WTSET1_PERIOD1_G2H << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h new file mode 100644 index 0000000..acd9627 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2H_V30_H +#define QOS_INIT_G2H_V30_H + +void qos_init_g2h_v30(void); + +#endif /* QOS_INIT_G2H_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c new file mode 100644 index 0000000..ceaad25 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v10.h" +#include "qos_init_g2m_v10_mstat.h" +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +static const struct rcar_gen3_dbsc_qos_settings g2m_v10_qos[] = { + /* BUFCAM settings */ + /* DBSC_DBCAM0CNF0 not set */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x080F0037U }, + /* DBSC_DBSCHCNT1 not set */ + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000300U }, + { DBSC_DBSCHQOS91, 0x000002F0U }, + { DBSC_DBSCHQOS92, 0x00000200U }, + { DBSC_DBSCHQOS93, 0x00000100U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v10(void) +{ + rzg_qos_dbsc_setting(g2m_v10_qos, ARRAY_SIZE(g2m_v10_qos), false); + + /* DRAM split address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M +#error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1CU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x089A0000U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + + /* Resource Alloc setting */ + mmio_write_32(QOSCTRL_RAS, 0x00000028U); + mmio_write_32(QOSCTRL_FIXTH, 0x000F0005U); + mmio_write_32(QOSCTRL_REGGD, 0x00000000U); + mmio_write_64(QOSCTRL_DANN, 0x0101010102020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_EC, 0x00000000U); + mmio_write_64(QOSCTRL_EMS, 0x0000000000000000UL); + mmio_write_32(QOSCTRL_FSS, 0x000003e8U); + mmio_write_32(QOSCTRL_INSFC, 0xC7840001U); + mmio_write_32(QOSCTRL_BERR, 0x00000000U); + mmio_write_32(QOSCTRL_RACNT0, 0x00000000U); + + /* QOSBW setting */ + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK); + mmio_write_32(QOSCTRL_REF_ARS, 0x00330000U); + + /* QOSBW SRAM setting */ + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } + + /* 3DG bus Leaf setting */ + mmio_write_32(0xFD820808U, 0x00001234U); + mmio_write_32(0xFD820800U, 0x00000006U); + mmio_write_32(0xFD821800U, 0x00000006U); + mmio_write_32(0xFD822800U, 0x00000006U); + mmio_write_32(0xFD823800U, 0x00000006U); + mmio_write_32(0xFD824800U, 0x00000006U); + mmio_write_32(0xFD825800U, 0x00000006U); + mmio_write_32(0xFD826800U, 0x00000006U); + mmio_write_32(0xFD827800U, 0x00000006U); + + /* RT bus Leaf setting */ + mmio_write_32(0xFFC50800U, 0x00000000U); + mmio_write_32(0xFFC51800U, 0x00000000U); + + /* Resource Alloc start */ + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + + /* QOSBW start */ + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + /* Resource Alloc setting */ + mmio_write_32(QOSCTRL_EC, 0x00000000U); + /* Resource Alloc start */ + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h new file mode 100644 index 0000000..627974a --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V10_H +#define QOS_INIT_G2M_V10_H + +void qos_init_g2m_v10(void); + +#endif /* QOS_INIT_G2M_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h new file mode 100644 index 0000000..c37915c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h @@ -0,0 +1,232 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V10_MSTAT_H +#define QOS_INIT_G2M_V10_MSTAT_H + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +static const uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004030000FFFFUL, + /* 0x0038, */ 0x001004030000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001410010000FFFFUL, + /* 0x0058, */ 0x00140C090000FFFFUL, + /* 0x0060, */ 0x00140C090000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001410010000FFFFUL, + /* 0x0078, */ 0x001004020000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408060000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x000C08020000FFFFUL, + /* 0x00A8, */ 0x000C04010000FFFFUL, + /* 0x00B0, */ 0x000C04010000FFFFUL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x000C08020000FFFFUL, + /* 0x00C8, */ 0x000C04010000FFFFUL, + /* 0x00D0, */ 0x000C04010000FFFFUL, + /* 0x00D8, */ 0x000C04030000FFFFUL, + /* 0x00E0, */ 0x000C100F0000FFFFUL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x001010080000FFFFUL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001010080000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00100C0A0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008050000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001028280000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x00100C0A0000FFFFUL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x0000000000000000UL, + /* 0x01C8, */ 0x0000000000000000UL, + /* 0x01D0, */ 0x0000000000000000UL, + /* 0x01D8, */ 0x0000000000000000UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x0000000000000000UL, + /* 0x01F0, */ 0x0000000000000000UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02A0, */ 0x000C04010000FFFFUL, + /* 0x02A8, */ 0x000C04010000FFFFUL, + /* 0x02B0, */ 0x001404010000FFFFUL, + /* 0x02B8, */ 0x0000000000000000UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x000C04010000FFFFUL, + /* 0x02D8, */ 0x000C04010000FFFFUL, + /* 0x02E0, */ 0x001404010000FFFFUL, + /* 0x02E8, */ 0x0000000000000000UL, + /* 0x02F0, */ 0x0000000000000000UL, + /* 0x02F8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static const uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200100C89C401UL, + /* 0x0008, */ 0x001200100C89C401UL, + /* 0x0010, */ 0x001200100C89C401UL, + /* 0x0018, */ 0x001200100C89C401UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001100100C803401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00A0, */ 0x0000000000000000UL, + /* 0x00A8, */ 0x0000000000000000UL, + /* 0x00B0, */ 0x0000000000000000UL, + /* 0x00B8, */ 0x0000000000000000UL, + /* 0x00C0, */ 0x0000000000000000UL, + /* 0x00C8, */ 0x0000000000000000UL, + /* 0x00D0, */ 0x0000000000000000UL, + /* 0x00D8, */ 0x0000000000000000UL, + /* 0x00E0, */ 0x0000000000000000UL, + /* 0x00E8, */ 0x0000000000000000UL, + /* 0x00F0, */ 0x0000000000000000UL, + /* 0x00F8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01A0, */ 0x0000000000000000UL, + /* 0x01A8, */ 0x0000000000000000UL, + /* 0x01B0, */ 0x0000000000000000UL, + /* 0x01B8, */ 0x0000000000000000UL, + /* 0x01C0, */ 0x001100500C8FFC01UL, + /* 0x01C8, */ 0x001100500C8FFC01UL, + /* 0x01D0, */ 0x001100500C8FFC01UL, + /* 0x01D8, */ 0x001100500C8FFC01UL, + /* 0x01E0, */ 0x0000000000000000UL, + /* 0x01E8, */ 0x001200100C803401UL, + /* 0x01F0, */ 0x001100100C80FC01UL, + /* 0x01F8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x001200100C80FC01UL, + /* 0x0210, */ 0x001100100C80FC01UL, + /* 0x0218, */ 0x001100100C825801UL, + /* 0x0220, */ 0x001100100C825801UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100100C825801UL, + /* 0x0238, */ 0x001100100C825801UL, + /* 0x0240, */ 0x001200100C8BB801UL, + /* 0x0248, */ 0x001100100C8EA401UL, + /* 0x0250, */ 0x001200100C8BB801UL, + /* 0x0258, */ 0x001100100C8EA401UL, + /* 0x0260, */ 0x001100100C84E401UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x001100100C81F401UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02A0, */ 0x0000000000000000UL, + /* 0x02A8, */ 0x0000000000000000UL, + /* 0x02B0, */ 0x0000000000000000UL, + /* 0x02B8, */ 0x001100100C803401UL, + /* 0x02C0, */ 0x0000000000000000UL, + /* 0x02C8, */ 0x0000000000000000UL, + /* 0x02D0, */ 0x0000000000000000UL, + /* 0x02D8, */ 0x0000000000000000UL, + /* 0x02E0, */ 0x0000000000000000UL, + /* 0x02E8, */ 0x001100100C803401UL, + /* 0x02F0, */ 0x001100300C8FFC01UL, + /* 0x02F8, */ 0x001100500C8FFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100300C8FFC01UL, + /* 0x0310, */ 0x001100500C8FFC01UL, + /* 0x0318, */ 0x001200100C803401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +#endif /* QOS_INIT_G2M_V10_MSTAT_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c new file mode 100644 index 0000000..db61858 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v11.h" +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v11_mstat195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v11_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v11_qoswt195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v11_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.19" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_11 (SL_INIT_SSLOTCLK_G2M_11 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2M_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_11) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2M_11 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_11) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +static const struct rcar_gen3_dbsc_qos_settings g2m_v11_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v11(void) +{ + uint32_t i; + + rzg_qos_dbsc_setting(g2m_v11_qos, ARRAY_SIZE(g2m_v11_qos), false); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M +#error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1CU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + mmio_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_G2M_11); +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + mmio_write_32(QOSCTRL_REF_ARS, + QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_11 << 16); +#else /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + mmio_write_32(QOSCTRL_REF_ARS, 0x00330000U); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* 3DG bus Leaf setting */ + mmio_write_32(GPU_ACT_GRD, 0x00001234U); + mmio_write_32(GPU_ACT0, 0x00000000U); + mmio_write_32(GPU_ACT1, 0x00000000U); + mmio_write_32(GPU_ACT2, 0x00000000U); + mmio_write_32(GPU_ACT3, 0x00000000U); + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + (QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN); + mmio_write_32(QOSWT_WTSET0, + (QOSWT_WTSET0_PERIOD0_G2M_11 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0); + mmio_write_32(QOSWT_WTSET1, + (QOSWT_WTSET1_PERIOD1_G2M_11 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h new file mode 100644 index 0000000..d042493 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_H +#define QOS_INIT_G2M_V11_H + +void qos_init_g2m_v11(void); + +#endif /* QOS_INIT_G2M_V11_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h new file mode 100644 index 0000000..950abd6 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_MSTAT195_H +#define QOS_INIT_G2M_V11_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C14120000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h new file mode 100644 index 0000000..5c6fd24 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_MSTAT390_H +#define QOS_INIT_G2M_V11_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C24230000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h new file mode 100644 index 0000000..f526a82 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_QOSWT195_H +#define QOS_INIT_G2M_V11_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h new file mode 100644 index 0000000..bfb80e3 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V11_QOSWT390_H +#define QOS_INIT_G2M_V11_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V11_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c new file mode 100644 index 0000000..321cd2b --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c @@ -0,0 +1,210 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "../qos_common.h" +#include "qos_init_g2m_v30.h" +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v30_mstat195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v30_mstat390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2m_v30_qoswt195.h" +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#include "qos_init_g2m_v30_qoswt390.h" +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif /* RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT */ +#include "qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.04" + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_30 (SL_INIT_SSLOTCLK_G2M_30 - 0x5U) + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN \ + ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2M_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_30) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2M_30 \ + ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2M_30) - 1U) +#define QOSWT_WTSET1_SSLOT1 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET1_SLOTSLOT1 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +static const struct rcar_gen3_dbsc_qos_settings g2m_v30_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBCAM0CNF3, 0x00000000U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS120, 0x00000040U }, + { DBSC_DBSCHQOS121, 0x00000030U }, + { DBSC_DBSCHQOS122, 0x00000020U }, + { DBSC_DBSCHQOS123, 0x00000010U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2m_v30(void) +{ + uint32_t i; + + rzg_qos_dbsc_setting(g2m_v30_qos, ARRAY_SIZE(g2m_v30_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2M + #error "Don't set DRAM Split 4ch(G2M)" +#else /* RCAR_LSI == RZ_G2M */ + ERROR("DRAM Split 4ch not supported.(G2M)"); + panic(); +#endif /* RCAR_LSI == RZ_G2M */ +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) || \ + (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_AUTO) + NOTICE("BL2: DRAM Split is 2ch\n"); + mmio_write_32(AXI_ADSPLCR0, 0x00000000U); + mmio_write_32(AXI_ADSPLCR1, ADSPLCR0_ADRMODE_DEFAULT | + ADSPLCR0_SPLITSEL(0xFFU) | ADSPLCR0_AREA(0x1DU) | + ADSPLCR0_SWP); + mmio_write_32(AXI_ADSPLCR2, 0x00001004U); + mmio_write_32(AXI_ADSPLCR3, 0x00000000U); +#else /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + NOTICE("BL2: DRAM Split is OFF\n"); +#endif /* RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH */ + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif /* RCAR_REF_INT == RCAR_REF_DEFAULT */ + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000044U); + mmio_write_64(QOSCTRL_DANN, 0x0404020002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x0020100AU); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000001U); + mmio_write_32(QOSCTRL_RACNT0, 0x02010003U); /* GPU Boost Mode ON */ + + /* GPU Boost Mode */ + mmio_write_32(QOSCTRL_STATGEN0, 0x00000001U); + + mmio_write_32(QOSCTRL_SL_INIT, + SL_INIT_REFFSSLOT | SL_INIT_SLOTSSLOT | + SL_INIT_SSLOTCLK_G2M_30); + mmio_write_32(QOSCTRL_REF_ARS, + QOSCTRL_REF_ARS_ARBSTOPCYCLE_G2M_30 << 16); + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + mmio_write_32(CPU_ACT2, 0x00000003U); + mmio_write_32(CPU_ACT3, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, + (QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN); + mmio_write_32(QOSWT_WTSET0, (QOSWT_WTSET0_PERIOD0_G2M_30 << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0); + mmio_write_32(QOSWT_WTSET1, (QOSWT_WTSET1_PERIOD1_G2M_30 << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h new file mode 100644 index 0000000..f89eabf --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_H +#define QOS_INIT_G2M_V30_H + +void qos_init_g2m_v30(void); + +#endif /* QOS_INIT_G2M_V30_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h new file mode 100644 index 0000000..fd15788 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_MSTAT195_H +#define QOS_INIT_G2M_V30_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000FFFFUL, + /* 0x0038, */ 0x001004040000FFFFUL, + /* 0x0040, */ 0x001414090000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x00140C0A0000FFFFUL, + /* 0x0060, */ 0x00140C0A0000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001004030000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFFFUL, + /* 0x0090, */ 0x001408070000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C04020000FFFFUL, + /* 0x00a8, */ 0x000C04010000FFFFUL, + /* 0x00b0, */ 0x000C04010000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C04020000FFFFUL, + /* 0x00c8, */ 0x000C04010000FFFFUL, + /* 0x00d0, */ 0x000C04010000FFFFUL, + /* 0x00d8, */ 0x000C08050000FFFFUL, + /* 0x00e0, */ 0x000C10100000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001024090000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x00100C090000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C10100000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100C0B0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0010100D0000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100C0B0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008060000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00102C2C0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100C0B0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFFFUL, + /* 0x0268, */ 0x001408010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C04010000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x001408010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x001408010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x001200200BDFFC01UL, + /* 0x0008, */ 0x001200200BDFFC01UL, + /* 0x0010, */ 0x001200200BDFFC01UL, + /* 0x0018, */ 0x001200200BDFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100600BDFFC01UL, + /* 0x01c8, */ 0x002100600BDFFC01UL, + /* 0x01d0, */ 0x002100600BDFFC01UL, + /* 0x01d8, */ 0x002100600BDFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x002100200BDFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x002100200BDFFC01UL, + /* 0x0218, */ 0x001100200BDFFC01UL, + /* 0x0220, */ 0x001100200BDFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001100200BDFFC01UL, + /* 0x0238, */ 0x001100200BDFFC01UL, + /* 0x0240, */ 0x001200200BDFFC01UL, + /* 0x0248, */ 0x001100200BDFFC01UL, + /* 0x0250, */ 0x001200200BDFFC01UL, + /* 0x0258, */ 0x001100200BDFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001100400BDFFC01UL, + /* 0x02f8, */ 0x001100600BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x001100400BDFFC01UL, + /* 0x0310, */ 0x001100600BDFFC01UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h new file mode 100644 index 0000000..aa2036d --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_MSTAT390_H +#define QOS_INIT_G2M_V30_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000FFFFUL, + /* 0x0038, */ 0x001008070000FFFFUL, + /* 0x0040, */ 0x001424120000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404010000FFFFUL, + /* 0x0058, */ 0x001414130000FFFFUL, + /* 0x0060, */ 0x001414130000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404010000FFFFUL, + /* 0x0078, */ 0x001008050000FFFFUL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFFFUL, + /* 0x0090, */ 0x0014100D0000FFFFUL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08040000FFFFUL, + /* 0x00a8, */ 0x000C04020000FFFFUL, + /* 0x00b0, */ 0x000C04020000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08040000FFFFUL, + /* 0x00c8, */ 0x000C04020000FFFFUL, + /* 0x00d0, */ 0x000C04020000FFFFUL, + /* 0x00d8, */ 0x000C0C0A0000FFFFUL, + /* 0x00e0, */ 0x000C201F0000FFFFUL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001044110000FFFFUL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001014110000FFFFUL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x000C201F0000FFFFUL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x001018150000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101C190000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x001018150000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100C0B0000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001058570000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x001018150000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x000C04010000FFFFUL, + /* 0x01d8, */ 0x000C04010000FFFFUL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04010000FFFFUL, + /* 0x01f0, */ 0x000C04010000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04010000FFFFUL, + /* 0x0210, */ 0x000C04010000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFFFUL, + /* 0x0268, */ 0x001410010000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x000C08020000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04010000FFFFUL, + /* 0x02a8, */ 0x000C04010000FFFFUL, + /* 0x02b0, */ 0x00140C010000FFFFUL, + /* 0x02b8, */ 0x000C04010000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04010000FFFFUL, + /* 0x02d8, */ 0x000C04010000FFFFUL, + /* 0x02e0, */ 0x00140C010000FFFFUL, + /* 0x02e8, */ 0x000C04010000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0012003005EFFC01UL, + /* 0x0008, */ 0x0012003005EFFC01UL, + /* 0x0010, */ 0x0012003005EFFC01UL, + /* 0x0018, */ 0x0012003005EFFC01UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002100B005EFFC01UL, + /* 0x01c8, */ 0x002100B005EFFC01UL, + /* 0x01d0, */ 0x002100B005EFFC01UL, + /* 0x01d8, */ 0x002100B005EFFC01UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021003005EFFC01UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021003005EFFC01UL, + /* 0x0218, */ 0x0011003005EFFC01UL, + /* 0x0220, */ 0x0011003005EFFC01UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011003005EFFC01UL, + /* 0x0238, */ 0x0011003005EFFC01UL, + /* 0x0240, */ 0x0012003005EFFC01UL, + /* 0x0248, */ 0x0011003005EFFC01UL, + /* 0x0250, */ 0x0012003005EFFC01UL, + /* 0x0258, */ 0x0011003005EFFC01UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011007005EFFC01UL, + /* 0x02f8, */ 0x001100B005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0011007005EFFC01UL, + /* 0x0310, */ 0x001100B005EFFC01UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h new file mode 100644 index 0000000..27c9c51 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_QOSWT195_H +#define QOS_INIT_G2M_V30_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004040000C010UL, + /* 0x0038, */ 0x001004040000C010UL, + /* 0x0040, */ 0x001414090000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C0A0000C010UL, + /* 0x0060, */ 0x00140C0A0000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001004030000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001414090000FFF0UL, + /* 0x0090, */ 0x001408070000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08020000FFF0UL, + /* 0x0268, */ 0x001408010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04010000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h new file mode 100644 index 0000000..5d18212 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2M_V30_QOSWT390_H +#define QOS_INIT_G2M_V30_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008070000C010UL, + /* 0x0038, */ 0x001008070000C010UL, + /* 0x0040, */ 0x001424120000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001414130000C010UL, + /* 0x0060, */ 0x001414130000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x001008050000C010UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x001424120000FFF0UL, + /* 0x0090, */ 0x0014100D0000C010UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C030000FFF0UL, + /* 0x0268, */ 0x001410010000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C08020000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410010000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, +}; + +#endif /* QOS_INIT_G2M_V30_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c new file mode 100644 index 0000000..00b0948 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "qos_init_g2n_v10.h" + +#include "../qos_common.h" +#include "../qos_reg.h" + +#define RCAR_QOS_VERSION "rev.0.09" + +#define REF_ARS_ARBSTOPCYCLE_G2N (((SL_INIT_SSLOTCLK_G2N) - 5U) << 16U) + +#define QOSWT_TIME_BANK0 20000000U /* unit:ns */ + +#define QOSWT_WTEN_ENABLE 0x1U + +#define OSWT_WTREF_SLOT0_EN_REQ1_SLOT 3U +#define OSWT_WTREF_SLOT0_EN_REQ2_SLOT 9U +#define QOSWT_WTREF_SLOT0_EN ((0x1U << OSWT_WTREF_SLOT0_EN_REQ1_SLOT) | \ + (0x1U << OSWT_WTREF_SLOT0_EN_REQ2_SLOT)) +#define QOSWT_WTREF_SLOT1_EN QOSWT_WTREF_SLOT0_EN + +#define QOSWT_WTSET0_REQ_SSLOT0 5U +#define WT_BASE_SUB_SLOT_NUM0 12U +#define QOSWT_WTSET0_PERIOD0_G2N ((QOSWT_TIME_BANK0 / QOSWT_WTSET0_CYCLE_G2N) - 1U) +#define QOSWT_WTSET0_SSLOT0 (QOSWT_WTSET0_REQ_SSLOT0 - 1U) +#define QOSWT_WTSET0_SLOTSLOT0 (WT_BASE_SUB_SLOT_NUM0 - 1U) + +#define QOSWT_WTSET1_PERIOD1_G2N QOSWT_WTSET0_PERIOD0_G2N +#define QOSWT_WTSET1_SSLOT1 QOSWT_WTSET0_SSLOT0 +#define QOSWT_WTSET1_SLOTSLOT1 QOSWT_WTSET0_SLOTSLOT0 + +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2n_v10_mstat195.h" +#else +#include "qos_init_g2n_v10_mstat390.h" +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + +#if RCAR_REF_INT == RCAR_REF_DEFAULT +#include "qos_init_g2n_v10_qoswt195.h" +#else +#include "qos_init_g2n_v10_qoswt390.h" +#endif + +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ +#endif + +static const struct rcar_gen3_dbsc_qos_settings g2n_v10_qos[] = { + /* BUFCAM settings */ + { DBSC_DBCAM0CNF1, 0x00043218U }, + { DBSC_DBCAM0CNF2, 0x000000F4U }, + { DBSC_DBSCHCNT0, 0x000F0037U }, + { DBSC_DBSCHSZ0, 0x00000001U }, + { DBSC_DBSCHRW0, 0x22421111U }, + + /* DDR3 */ + { DBSC_SCFCTST2, 0x012F1123U }, + + /* QoS Settings */ + { DBSC_DBSCHQOS00, 0x00000F00U }, + { DBSC_DBSCHQOS01, 0x00000B00U }, + { DBSC_DBSCHQOS02, 0x00000000U }, + { DBSC_DBSCHQOS03, 0x00000000U }, + { DBSC_DBSCHQOS40, 0x00000300U }, + { DBSC_DBSCHQOS41, 0x000002F0U }, + { DBSC_DBSCHQOS42, 0x00000200U }, + { DBSC_DBSCHQOS43, 0x00000100U }, + { DBSC_DBSCHQOS90, 0x00000100U }, + { DBSC_DBSCHQOS91, 0x000000F0U }, + { DBSC_DBSCHQOS92, 0x000000A0U }, + { DBSC_DBSCHQOS93, 0x00000040U }, + { DBSC_DBSCHQOS130, 0x00000100U }, + { DBSC_DBSCHQOS131, 0x000000F0U }, + { DBSC_DBSCHQOS132, 0x000000A0U }, + { DBSC_DBSCHQOS133, 0x00000040U }, + { DBSC_DBSCHQOS140, 0x000000C0U }, + { DBSC_DBSCHQOS141, 0x000000B0U }, + { DBSC_DBSCHQOS142, 0x00000080U }, + { DBSC_DBSCHQOS143, 0x00000040U }, + { DBSC_DBSCHQOS150, 0x00000040U }, + { DBSC_DBSCHQOS151, 0x00000030U }, + { DBSC_DBSCHQOS152, 0x00000020U }, + { DBSC_DBSCHQOS153, 0x00000010U }, +}; + +void qos_init_g2n_v10(void) +{ + rzg_qos_dbsc_setting(g2n_v10_qos, ARRAY_SIZE(g2n_v10_qos), true); + + /* DRAM Split Address mapping */ +#if RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_4CH +#if RCAR_LSI == RZ_G2N +#error "Don't set DRAM Split 4ch(G2N)" +#else + ERROR("DRAM Split 4ch not supported.(G2N)"); + panic(); +#endif +#elif (RCAR_DRAM_SPLIT == RCAR_DRAM_SPLIT_2CH) +#if RCAR_LSI == RZ_G2N +#error "Don't set DRAM Split 2ch(G2N)" +#else + ERROR("DRAM Split 2ch not supported.(G2N)"); + panic(); +#endif +#else + NOTICE("BL2: DRAM Split is OFF\n"); +#endif + +#if !(RCAR_QOS_TYPE == RCAR_QOS_NONE) +#if RCAR_QOS_TYPE == RCAR_QOS_TYPE_DEFAULT + NOTICE("BL2: QoS is default setting(%s)\n", RCAR_QOS_VERSION); +#endif + +#if RCAR_REF_INT == RCAR_REF_DEFAULT + NOTICE("BL2: DRAM refresh interval 1.95 usec\n"); +#else + NOTICE("BL2: DRAM refresh interval 3.9 usec\n"); +#endif + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + NOTICE("BL2: Periodic Write DQ Training\n"); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_RAS, 0x00000028U); + mmio_write_64(QOSCTRL_DANN, 0x0402000002020201UL); + mmio_write_32(QOSCTRL_DANT, 0x00100804U); + mmio_write_32(QOSCTRL_FSS, 0x0000000AU); + mmio_write_32(QOSCTRL_INSFC, 0x06330001U); + mmio_write_32(QOSCTRL_EARLYR, 0x00000001U); + mmio_write_32(QOSCTRL_RACNT0, 0x00010003U); + + mmio_write_32(QOSCTRL_SL_INIT, SL_INIT_REFFSSLOT | + SL_INIT_SLOTSSLOT | SL_INIT_SSLOTCLK_G2N); + mmio_write_32(QOSCTRL_REF_ARS, REF_ARS_ARBSTOPCYCLE_G2N); + + uint32_t i; + + for (i = 0U; i < ARRAY_SIZE(mstat_fix); i++) { + mmio_write_64(QOSBW_FIX_QOS_BANK0 + i * 8U, mstat_fix[i]); + mmio_write_64(QOSBW_FIX_QOS_BANK1 + i * 8U, mstat_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(mstat_be); i++) { + mmio_write_64(QOSBW_BE_QOS_BANK0 + i * 8U, mstat_be[i]); + mmio_write_64(QOSBW_BE_QOS_BANK1 + i * 8U, mstat_be[i]); + } +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + for (i = 0U; i < ARRAY_SIZE(qoswt_fix); i++) { + mmio_write_64(QOSWT_FIX_WTQOS_BANK0 + i * 8U, qoswt_fix[i]); + mmio_write_64(QOSWT_FIX_WTQOS_BANK1 + i * 8U, qoswt_fix[i]); + } + for (i = 0U; i < ARRAY_SIZE(qoswt_be); i++) { + mmio_write_64(QOSWT_BE_WTQOS_BANK0 + i * 8U, qoswt_be[i]); + mmio_write_64(QOSWT_BE_WTQOS_BANK1 + i * 8U, qoswt_be[i]); + } +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + /* RT bus Leaf setting */ + mmio_write_32(RT_ACT0, 0x00000000U); + mmio_write_32(RT_ACT1, 0x00000000U); + + /* CCI bus Leaf setting */ + mmio_write_32(CPU_ACT0, 0x00000003U); + mmio_write_32(CPU_ACT1, 0x00000003U); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); + +#if RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE + /* re-write training setting */ + mmio_write_32(QOSWT_WTREF, ((QOSWT_WTREF_SLOT1_EN << 16) | QOSWT_WTREF_SLOT0_EN)); + mmio_write_32(QOSWT_WTSET0, ((QOSWT_WTSET0_PERIOD0_G2N << 16) | + (QOSWT_WTSET0_SSLOT0 << 8) | QOSWT_WTSET0_SLOTSLOT0)); + mmio_write_32(QOSWT_WTSET1, ((QOSWT_WTSET1_PERIOD1_G2N << 16) | + (QOSWT_WTSET1_SSLOT1 << 8) | QOSWT_WTSET1_SLOTSLOT1)); + + mmio_write_32(QOSWT_WTEN, QOSWT_WTEN_ENABLE); +#endif /* RCAR_REWT_TRAINING != RCAR_REWT_TRAINING_DISABLE */ + + mmio_write_32(QOSCTRL_STATQC, 0x00000001U); +#else + NOTICE("BL2: QoS is None\n"); + + mmio_write_32(QOSCTRL_RAEN, 0x00000001U); +#endif /* !(RCAR_QOS_TYPE == RCAR_QOS_NONE) */ +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h new file mode 100644 index 0000000..c7f02d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_V10_H +#define QOS_INIT_G2N_V10_H + +void qos_init_g2n_v10(void); + +#endif /* QOS_INIT_G2N_V10_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h new file mode 100644 index 0000000..6e304b0 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_MSTAT195_H +#define QOS_INIT_G2N_MSTAT195_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000FFFFUL, + /* 0x0038, */ 0x001004320000FFFFUL, + /* 0x0040, */ 0x00140C5D0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404040000FFFFUL, + /* 0x0058, */ 0x00140C940000FFFFUL, + /* 0x0060, */ 0x00140C940000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404040000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C041D0000FFFFUL, + /* 0x00a8, */ 0x000C04090000FFFFUL, + /* 0x00b0, */ 0x000C040B0000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C041D0000FFFFUL, + /* 0x00c8, */ 0x000C04090000FFFFUL, + /* 0x00d0, */ 0x000C040B0000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x000C084F0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x000C21E60000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x00100CA50000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x001010C90000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x00100CA50000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x001008530000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x00101D9D0000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x00100CA50000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x001408020000FFFFUL, + /* 0x0270, */ 0x001404010000FFFFUL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFFFUL, + /* 0x0298, */ 0x001404010000FFFFUL, + /* 0x02a0, */ 0x000C04050000FFFFUL, + /* 0x02a8, */ 0x000C04050000FFFFUL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04050000FFFFUL, + /* 0x02d8, */ 0x000C04050000FFFFUL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x000C04050000FFFFUL, + /* 0x0388, */ 0x000C04050000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x001200100BD03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x002106000BDFFC01UL, + /* 0x01c8, */ 0x002106000BDFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x001101000BDF2401UL, + /* 0x0220, */ 0x001101000BDF2401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x001101000BDF2401UL, + /* 0x0238, */ 0x001101000BDF2401UL, + /* 0x0240, */ 0x001201000BDF2401UL, + /* 0x0248, */ 0x001101000BDF2401UL, + /* 0x0250, */ 0x001201000BDF2401UL, + /* 0x0258, */ 0x001101000BDF2401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x001106000BDFFC01UL, + /* 0x02f8, */ 0x001106000BDFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x001200100BD03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x001206000BDFFC01UL, + /* 0x0360, */ 0x001206000BDFFC01UL, + /* 0x0368, */ 0x001200100BD03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x001200100BD03401UL, +}; +#endif /* QOS_INIT_G2N_MSTAT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h new file mode 100644 index 0000000..4632413 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_MSTAT390_H +#define QOS_INIT_G2N_MSTAT390_H + +static uint64_t mstat_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000FFFFUL, + /* 0x0038, */ 0x001008630000FFFFUL, + /* 0x0040, */ 0x001418BA0000FFFFUL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x001404070000FFFFUL, + /* 0x0058, */ 0x001415270000FFFFUL, + /* 0x0060, */ 0x001415270000FFFFUL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x001404070000FFFFUL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFFFUL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x000C08390000FFFFUL, + /* 0x00a8, */ 0x000C04110000FFFFUL, + /* 0x00b0, */ 0x000C04150000FFFFUL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x000C08390000FFFFUL, + /* 0x00c8, */ 0x000C04110000FFFFUL, + /* 0x00d0, */ 0x000C04150000FFFFUL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x001045080000FFFFUL, + /* 0x00f8, */ 0x000C0C9E0000FFFFUL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x001015080000FFFFUL, + /* 0x0118, */ 0x000C43CB0000FFFFUL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0010194A0000FFFFUL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x00101D910000FFFFUL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0010194A0000FFFFUL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x00100CA50000FFFFUL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x001037390000FFFFUL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0010194A0000FFFFUL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x000C04010000FFFFUL, + /* 0x01c8, */ 0x000C04010000FFFFUL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x000C04020000FFFFUL, + /* 0x01f0, */ 0x000C04090000FFFFUL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x000C04090000FFFFUL, + /* 0x0210, */ 0x000C04090000FFFFUL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFFFUL, + /* 0x0268, */ 0x001410040000FFFFUL, + /* 0x0270, */ 0x001404020000FFFFUL, + /* 0x0278, */ 0x000C08110000FFFFUL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFFFUL, + /* 0x0298, */ 0x001404020000FFFFUL, + /* 0x02a0, */ 0x000C04090000FFFFUL, + /* 0x02a8, */ 0x000C04090000FFFFUL, + /* 0x02b0, */ 0x00140C090000FFFFUL, + /* 0x02b8, */ 0x000C04020000FFFFUL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x000C04090000FFFFUL, + /* 0x02d8, */ 0x000C04090000FFFFUL, + /* 0x02e0, */ 0x00140C090000FFFFUL, + /* 0x02e8, */ 0x000C04020000FFFFUL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x000C04020000FFFFUL, + /* 0x0378, */ 0x000C04020000FFFFUL, + /* 0x0380, */ 0x000C04090000FFFFUL, + /* 0x0388, */ 0x000C04090000FFFFUL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t mstat_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0012001005E03401UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0021060005EFFC01UL, + /* 0x01c8, */ 0x0021060005EFFC01UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0021010005E79401UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0021010005E79401UL, + /* 0x0218, */ 0x0011010005E79401UL, + /* 0x0220, */ 0x0011010005E79401UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0011010005E79401UL, + /* 0x0238, */ 0x0011010005E79401UL, + /* 0x0240, */ 0x0012010005E79401UL, + /* 0x0248, */ 0x0011010005E79401UL, + /* 0x0250, */ 0x0012010005E79401UL, + /* 0x0258, */ 0x0011010005E79401UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0011060005EFFC01UL, + /* 0x02f8, */ 0x0011060005EFFC01UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0012001005E03401UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0012060005EFFC01UL, + /* 0x0360, */ 0x0012060005EFFC01UL, + /* 0x0368, */ 0x0012001005E03401UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0012001005E03401UL, +}; +#endif /* QOS_INIT_G2N_MSTAT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h new file mode 100644 index 0000000..eea1fce --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_QOSWT195_H +#define QOS_INIT_G2N_QOSWT195_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001004320000C010UL, + /* 0x0038, */ 0x001004320000C010UL, + /* 0x0040, */ 0x00140C5D0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x00140C940000C010UL, + /* 0x0060, */ 0x00140C940000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014041F0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C08150000FFF0UL, + /* 0x0268, */ 0x001408020000FFF0UL, + /* 0x0270, */ 0x001404010000FFF0UL, + /* 0x0278, */ 0x000C04090000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001408020000FFF0UL, + /* 0x0298, */ 0x001404010000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; +#endif /* QOS_INIT_G2N_QOSWT195_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h new file mode 100644 index 0000000..7043303 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h @@ -0,0 +1,245 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_INIT_G2N_QOSWT390_H +#define QOS_INIT_G2N_QOSWT390_H + +static uint64_t qoswt_fix[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x001008630000C010UL, + /* 0x0038, */ 0x001008630000C010UL, + /* 0x0040, */ 0x001418BA0000FFF0UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x001415270000C010UL, + /* 0x0060, */ 0x001415270000C010UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0014083E0000FFF0UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x000C0C2A0000FFF0UL, + /* 0x0268, */ 0x001410040000FFF0UL, + /* 0x0270, */ 0x001404020000FFF0UL, + /* 0x0278, */ 0x000C08110000FFF0UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x001410040000FFF0UL, + /* 0x0298, */ 0x001404020000FFF0UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; + +static uint64_t qoswt_be[] = { + /* 0x0000, */ 0x0000000000000000UL, + /* 0x0008, */ 0x0000000000000000UL, + /* 0x0010, */ 0x0000000000000000UL, + /* 0x0018, */ 0x0000000000000000UL, + /* 0x0020, */ 0x0000000000000000UL, + /* 0x0028, */ 0x0000000000000000UL, + /* 0x0030, */ 0x0000000000000000UL, + /* 0x0038, */ 0x0000000000000000UL, + /* 0x0040, */ 0x0000000000000000UL, + /* 0x0048, */ 0x0000000000000000UL, + /* 0x0050, */ 0x0000000000000000UL, + /* 0x0058, */ 0x0000000000000000UL, + /* 0x0060, */ 0x0000000000000000UL, + /* 0x0068, */ 0x0000000000000000UL, + /* 0x0070, */ 0x0000000000000000UL, + /* 0x0078, */ 0x0000000000000000UL, + /* 0x0080, */ 0x0000000000000000UL, + /* 0x0088, */ 0x0000000000000000UL, + /* 0x0090, */ 0x0000000000000000UL, + /* 0x0098, */ 0x0000000000000000UL, + /* 0x00a0, */ 0x0000000000000000UL, + /* 0x00a8, */ 0x0000000000000000UL, + /* 0x00b0, */ 0x0000000000000000UL, + /* 0x00b8, */ 0x0000000000000000UL, + /* 0x00c0, */ 0x0000000000000000UL, + /* 0x00c8, */ 0x0000000000000000UL, + /* 0x00d0, */ 0x0000000000000000UL, + /* 0x00d8, */ 0x0000000000000000UL, + /* 0x00e0, */ 0x0000000000000000UL, + /* 0x00e8, */ 0x0000000000000000UL, + /* 0x00f0, */ 0x0000000000000000UL, + /* 0x00f8, */ 0x0000000000000000UL, + /* 0x0100, */ 0x0000000000000000UL, + /* 0x0108, */ 0x0000000000000000UL, + /* 0x0110, */ 0x0000000000000000UL, + /* 0x0118, */ 0x0000000000000000UL, + /* 0x0120, */ 0x0000000000000000UL, + /* 0x0128, */ 0x0000000000000000UL, + /* 0x0130, */ 0x0000000000000000UL, + /* 0x0138, */ 0x0000000000000000UL, + /* 0x0140, */ 0x0000000000000000UL, + /* 0x0148, */ 0x0000000000000000UL, + /* 0x0150, */ 0x0000000000000000UL, + /* 0x0158, */ 0x0000000000000000UL, + /* 0x0160, */ 0x0000000000000000UL, + /* 0x0168, */ 0x0000000000000000UL, + /* 0x0170, */ 0x0000000000000000UL, + /* 0x0178, */ 0x0000000000000000UL, + /* 0x0180, */ 0x0000000000000000UL, + /* 0x0188, */ 0x0000000000000000UL, + /* 0x0190, */ 0x0000000000000000UL, + /* 0x0198, */ 0x0000000000000000UL, + /* 0x01a0, */ 0x0000000000000000UL, + /* 0x01a8, */ 0x0000000000000000UL, + /* 0x01b0, */ 0x0000000000000000UL, + /* 0x01b8, */ 0x0000000000000000UL, + /* 0x01c0, */ 0x0000000000000000UL, + /* 0x01c8, */ 0x0000000000000000UL, + /* 0x01d0, */ 0x0000000000000000UL, + /* 0x01d8, */ 0x0000000000000000UL, + /* 0x01e0, */ 0x0000000000000000UL, + /* 0x01e8, */ 0x0000000000000000UL, + /* 0x01f0, */ 0x0000000000000000UL, + /* 0x01f8, */ 0x0000000000000000UL, + /* 0x0200, */ 0x0000000000000000UL, + /* 0x0208, */ 0x0000000000000000UL, + /* 0x0210, */ 0x0000000000000000UL, + /* 0x0218, */ 0x0000000000000000UL, + /* 0x0220, */ 0x0000000000000000UL, + /* 0x0228, */ 0x0000000000000000UL, + /* 0x0230, */ 0x0000000000000000UL, + /* 0x0238, */ 0x0000000000000000UL, + /* 0x0240, */ 0x0000000000000000UL, + /* 0x0248, */ 0x0000000000000000UL, + /* 0x0250, */ 0x0000000000000000UL, + /* 0x0258, */ 0x0000000000000000UL, + /* 0x0260, */ 0x0000000000000000UL, + /* 0x0268, */ 0x0000000000000000UL, + /* 0x0270, */ 0x0000000000000000UL, + /* 0x0278, */ 0x0000000000000000UL, + /* 0x0280, */ 0x0000000000000000UL, + /* 0x0288, */ 0x0000000000000000UL, + /* 0x0290, */ 0x0000000000000000UL, + /* 0x0298, */ 0x0000000000000000UL, + /* 0x02a0, */ 0x0000000000000000UL, + /* 0x02a8, */ 0x0000000000000000UL, + /* 0x02b0, */ 0x0000000000000000UL, + /* 0x02b8, */ 0x0000000000000000UL, + /* 0x02c0, */ 0x0000000000000000UL, + /* 0x02c8, */ 0x0000000000000000UL, + /* 0x02d0, */ 0x0000000000000000UL, + /* 0x02d8, */ 0x0000000000000000UL, + /* 0x02e0, */ 0x0000000000000000UL, + /* 0x02e8, */ 0x0000000000000000UL, + /* 0x02f0, */ 0x0000000000000000UL, + /* 0x02f8, */ 0x0000000000000000UL, + /* 0x0300, */ 0x0000000000000000UL, + /* 0x0308, */ 0x0000000000000000UL, + /* 0x0310, */ 0x0000000000000000UL, + /* 0x0318, */ 0x0000000000000000UL, + /* 0x0320, */ 0x0000000000000000UL, + /* 0x0328, */ 0x0000000000000000UL, + /* 0x0330, */ 0x0000000000000000UL, + /* 0x0338, */ 0x0000000000000000UL, + /* 0x0340, */ 0x0000000000000000UL, + /* 0x0348, */ 0x0000000000000000UL, + /* 0x0350, */ 0x0000000000000000UL, + /* 0x0358, */ 0x0000000000000000UL, + /* 0x0360, */ 0x0000000000000000UL, + /* 0x0368, */ 0x0000000000000000UL, + /* 0x0370, */ 0x0000000000000000UL, + /* 0x0378, */ 0x0000000000000000UL, + /* 0x0380, */ 0x0000000000000000UL, + /* 0x0388, */ 0x0000000000000000UL, + /* 0x0390, */ 0x0000000000000000UL, +}; +#endif /* QOS_INIT_G2N_QOSWT390_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk new file mode 100644 index 0000000..f05d126 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos.mk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${RCAR_LSI},${RCAR_AUTO}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c +else ifeq (${RCAR_LSI_CUT_COMPAT},1) + ifeq (${RCAR_LSI},${RZ_G2M}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + endif +else + ifeq (${RCAR_LSI},${RZ_G2M}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c + else ifeq (${LSI_CUT},11) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + else ifeq (${LSI_CUT},13) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c + else ifeq (${LSI_CUT},30) + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + else +# LSI_CUT 30 or later + BL2_SOURCES += drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c + endif + endif + ifeq (${RCAR_LSI},${RZ_G2H}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c + endif + ifeq (${RCAR_LSI},${RZ_G2N}) + ifeq (${LSI_CUT},10) + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + else +# LSI_CUT 10 or later + BL2_SOURCES += drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c + endif + endif + ifeq (${RCAR_LSI},${RZ_G2E}) + BL2_SOURCES += drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c + endif +endif + +BL2_SOURCES += drivers/renesas/rzg/qos/qos_init.c diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h new file mode 100644 index 0000000..535bf4c --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QOS_COMMON_H +#define QOS_COMMON_H + +#define RCAR_REF_DEFAULT 0U + +/* define used for get_refperiod. */ +/* REFPERIOD_CYCLE need smaller than QOSWT_WTSET0_CYCLEs */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF default */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((126U * BASE_SUB_SLOT_NUM * 1000U) / 400U) +#else /* REF option */ +#define REFPERIOD_CYCLE /* unit:ns */ \ + ((252U * BASE_SUB_SLOT_NUM * 1000U) / 400U) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) +/* define used for G2M */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2M_11 0x7EU /* 126 */ +#define SUB_SLOT_CYCLE_G2M_30 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2M_11 0xFCU /* 252 */ +#define SUB_SLOT_CYCLE_G2M_30 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2M_11 (SUB_SLOT_CYCLE_G2M_11 - 1U) +#define SL_INIT_SSLOTCLK_G2M_30 (SUB_SLOT_CYCLE_G2M_30 - 1U) +#define QOSWT_WTSET0_CYCLE_G2M_11 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2M_11 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#define QOSWT_WTSET0_CYCLE_G2M_30 /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2M_30 * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) +/* define used for G2N */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2N 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2N 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2N (SUB_SLOT_CYCLE_G2N - 1U) +#define QOSWT_WTSET0_CYCLE_G2N /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2N * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif /* (RCAR_LSI == RZ_G2N) */ + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) +/* define used for G2H */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 1.95usec */ +#define SUB_SLOT_CYCLE_G2H 0x7EU /* 126 */ +#else /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2H 0xFCU /* 252 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define SL_INIT_SSLOTCLK_G2H (SUB_SLOT_CYCLE_G2H - 1U) +#define QOSWT_WTSET0_CYCLE_G2H /* unit:ns */ \ + ((SUB_SLOT_CYCLE_G2H * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) +#endif + +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) +/* define used for G2E */ +#if (RCAR_REF_INT == RCAR_REF_DEFAULT) /* REF 3.9usec */ +#define SUB_SLOT_CYCLE_G2E 0xAFU /* 175 */ +#else /* REF 7.8usec */ +#define SUB_SLOT_CYCLE_G2E 0x15EU /* 350 */ +#endif /* (RCAR_REF_INT == RCAR_REF_DEFAULT) */ + +#define OPERATING_FREQ_G2E 266U /* MHz */ +#define SL_INIT_SSLOTCLK_G2E (SUB_SLOT_CYCLE_G2E - 1U) +#endif + +#define OPERATING_FREQ 400U /* MHz */ +#define BASE_SUB_SLOT_NUM 0x6U +#define SUB_SLOT_CYCLE 0x7EU /* 126 */ + +#define QOSWT_WTSET0_CYCLE /* unit:ns */ \ + ((SUB_SLOT_CYCLE * BASE_SUB_SLOT_NUM * 1000U) / OPERATING_FREQ) + +#define SL_INIT_REFFSSLOT (0x3U << 24U) +#define SL_INIT_SLOTSSLOT ((BASE_SUB_SLOT_NUM - 1U) << 16U) +#define SL_INIT_SSLOTCLK (SUB_SLOT_CYCLE - 1U) + +typedef struct { + uintptr_t addr; + uint64_t value; +} mstat_slot_t; + +struct rcar_gen3_dbsc_qos_settings { + uint32_t reg; + uint32_t val; +}; + +extern uint32_t qos_init_ddr_ch; +extern uint8_t qos_init_ddr_phyvalid; + +void rzg_qos_dbsc_setting(const struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren); + +#endif /* QOS_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c new file mode 100644 index 0000000..e527a61 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#if RCAR_LSI == RCAR_AUTO +#include "G2E/qos_init_g2e_v10.h" +#include "G2H/qos_init_g2h_v30.h" +#include "G2M/qos_init_g2m_v10.h" +#include "G2M/qos_init_g2m_v11.h" +#include "G2M/qos_init_g2m_v30.h" +#include "G2N/qos_init_g2n_v10.h" +#endif /* RCAR_LSI == RCAR_AUTO */ +#if (RCAR_LSI == RZ_G2M) +#include "G2M/qos_init_g2m_v10.h" +#include "G2M/qos_init_g2m_v11.h" +#include "G2M/qos_init_g2m_v30.h" +#endif /* RCAR_LSI == RZ_G2M */ +#if RCAR_LSI == RZ_G2H +#include "G2H/qos_init_g2h_v30.h" +#endif /* RCAR_LSI == RZ_G2H */ +#if RCAR_LSI == RZ_G2N +#include "G2N/qos_init_g2n_v10.h" +#endif /* RCAR_LSI == RZ_G2N */ +#if RCAR_LSI == RZ_G2E +#include "G2E/qos_init_g2e_v10.h" +#endif /* RCAR_LSI == RZ_G2E */ +#include "qos_common.h" +#include "qos_init.h" +#include "qos_reg.h" +#include "rcar_def.h" + +#if (RCAR_LSI != RZ_G2E) +#define DRAM_CH_CNT 0x04U +uint32_t qos_init_ddr_ch; +uint8_t qos_init_ddr_phyvalid; +#endif /* RCAR_LSI != RZ_G2E */ + +#define PRR_PRODUCT_ERR(reg) \ + { \ + ERROR("LSI Product ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } + +#define PRR_CUT_ERR(reg) \ + { \ + ERROR("LSI Cut ID(PRR=0x%x) QoS " \ + "initialize not supported.\n", reg); \ + panic(); \ + } + +void rzg_qos_init(void) +{ + uint32_t reg; +#if (RCAR_LSI != RZ_G2E) + uint32_t i; + + qos_init_ddr_ch = 0U; + qos_init_ddr_phyvalid = get_boardcnf_phyvalid(); + for (i = 0U; i < DRAM_CH_CNT; i++) { + if ((qos_init_ddr_phyvalid & (1U << i))) { + qos_init_ddr_ch++; + } + } +#endif /* RCAR_LSI != RZ_G2E */ + + reg = mmio_read_32(PRR); +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + switch (reg & PRR_PRODUCT_MASK) { + case PRR_PRODUCT_M3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + qos_init_g2m_v10(); + break; + case PRR_PRODUCT_21: /* G2M Cut 13 */ + qos_init_g2m_v11(); + break; + case PRR_PRODUCT_30: /* G2M Cut 30 */ + default: + qos_init_g2m_v30(); + break; + } +#else /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ + break; + case PRR_PRODUCT_H3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + qos_init_g2h_v30(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) */ + break; + case PRR_PRODUCT_M3N: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_g2n_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) */ + break; + case PRR_PRODUCT_E3: +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + default: + qos_init_g2e_v10(); + break; + } +#else + PRR_PRODUCT_ERR(reg); +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2E) */ + break; + default: + PRR_PRODUCT_ERR(reg); + break; + } +#else /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ +#if (RCAR_LSI == RZ_G2M) +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* G2M Cut 10 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_10) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v10(); +#elif RCAR_LSI_CUT == RCAR_CUT_11 + /* G2M Cut 11 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_20) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v11(); +#elif RCAR_LSI_CUT == RCAR_CUT_13 + /* G2M Cut 13 */ + if ((PRR_PRODUCT_M3 | PRR_PRODUCT_21) + != (reg & (PRR_PRODUCT_MASK | PRR_CUT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v11(); +#else + /* G2M Cut 30 or later */ + if ((PRR_PRODUCT_M3) + != (reg & (PRR_PRODUCT_MASK))) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2m_v30(); +#endif /* RCAR_LSI_CUT == RCAR_CUT_10 */ +#elif (RCAR_LSI == RZ_G2H) + /* G2H Cut 30 or later */ + if ((reg & PRR_PRODUCT_MASK) != PRR_PRODUCT_H3) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2h_v30(); +#elif (RCAR_LSI == RZ_G2N) + /* G2N Cut 10 or later */ + if ((reg & (PRR_PRODUCT_MASK)) != PRR_PRODUCT_M3N) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2n_v10(); +#elif RCAR_LSI == RZ_G2E + /* G2E Cut 10 or later */ + if ((reg & (PRR_PRODUCT_MASK)) != PRR_PRODUCT_E3) { + PRR_PRODUCT_ERR(reg); + } + qos_init_g2e_v10(); +#else /* (RCAR_LSI == RZ_G2M) */ +#error "Don't have QoS initialize routine(Unknown chip)." +#endif /* (RCAR_LSI == RZ_G2M) */ +#endif /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ +} + +#if (RCAR_LSI != RZ_G2E) +uint32_t get_refperiod(void) +{ + uint32_t refperiod = QOSWT_WTSET0_CYCLE; + +#if (RCAR_LSI == RCAR_AUTO) || RCAR_LSI_CUT_COMPAT + uint32_t reg; + + reg = mmio_read_32(PRR); + switch (reg & PRR_PRODUCT_MASK) { +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) + case PRR_PRODUCT_M3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_10: + break; + case PRR_PRODUCT_20: /* G2M Cut 11 */ + case PRR_PRODUCT_21: /* G2M Cut 13 */ + case PRR_PRODUCT_30: /* G2M Cut 30 */ + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2M) */ +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) + case PRR_PRODUCT_H3: + switch (reg & PRR_CUT_MASK) { + case PRR_PRODUCT_30: + default: + refperiod = REFPERIOD_CYCLE; + break; + } + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2H) */ +#if (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) + case PRR_PRODUCT_M3N: + refperiod = REFPERIOD_CYCLE; + break; +#endif /* (RCAR_LSI == RCAR_AUTO) || (RCAR_LSI == RZ_G2N) */ + default: + break; + } +#elif RCAR_LSI == RZ_G2M +#if RCAR_LSI_CUT == RCAR_CUT_10 + /* G2M Cut 10 */ +#else /* RCAR_LSI_CUT == RCAR_CUT_10 */ + /* G2M Cut 11|13|30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif /* RCAR_LSI_CUT == RCAR_CUT_10 */ +#elif RCAR_LSI == RZ_G2N + refperiod = REFPERIOD_CYCLE; +#elif RCAR_LSI == RZ_G2H + /* G2H Cut 30 or later */ + refperiod = REFPERIOD_CYCLE; +#endif /* RCAR_LSI == RCAR_AUTO || RCAR_LSI_CUT_COMPAT */ + return refperiod; +} +#endif /* RCAR_LSI != RZ_G2E */ + +void rzg_qos_dbsc_setting(const struct rcar_gen3_dbsc_qos_settings *qos, + unsigned int qos_size, bool dbsc_wren) +{ + unsigned int i; + + /* Register write enable */ + if (dbsc_wren) { + mmio_write_32(DBSC_DBSYSCNT0, 0x00001234U); + } + + for (i = 0; i < qos_size; i++) { + mmio_write_32(qos[i].reg, qos[i].val); + } + + /* Register write protect */ + if (dbsc_wren) { + mmio_write_32(DBSC_DBSYSCNT0, 0x00000000U); + } +} diff --git a/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h new file mode 100644 index 0000000..3d62744 --- /dev/null +++ b/arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RZG_QOS_INIT_H +#define RZG_QOS_INIT_H + +void rzg_qos_init(void); +uint8_t get_boardcnf_phyvalid(void); + +#endif /* RZG_QOS_INIT_H */ diff --git a/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c b/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c new file mode 100644 index 0000000..f938f56 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +static uintptr_t reg_base; + +static int rpi3_gpio_get_direction(int gpio); +static void rpi3_gpio_set_direction(int gpio, int direction); +static int rpi3_gpio_get_value(int gpio); +static void rpi3_gpio_set_value(int gpio, int value); +static void rpi3_gpio_set_pull(int gpio, int pull); + +static const gpio_ops_t rpi3_gpio_ops = { + .get_direction = rpi3_gpio_get_direction, + .set_direction = rpi3_gpio_set_direction, + .get_value = rpi3_gpio_get_value, + .set_value = rpi3_gpio_set_value, + .set_pull = rpi3_gpio_set_pull, +}; + +/** + * Get selection of GPIO pinmux settings. + * + * @param gpio The pin number of GPIO. From 0 to 53. + * @return The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, + * RPI3_GPIO_FUNC_OUTPUT: output, + * RPI3_GPIO_FUNC_ALT0: alt-0, + * RPI3_GPIO_FUNC_ALT1: alt-1, + * RPI3_GPIO_FUNC_ALT2: alt-2, + * RPI3_GPIO_FUNC_ALT3: alt-3, + * RPI3_GPIO_FUNC_ALT4: alt-4, + * RPI3_GPIO_FUNC_ALT5: alt-5 + */ +int rpi3_gpio_get_select(int gpio) +{ + int ret; + int regN = gpio / 10; + int shift = 3 * (gpio % 10); + uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); + uint32_t sel = mmio_read_32(reg_sel); + + ret = (sel >> shift) & 0x07; + + return ret; +} + +/** + * Set selection of GPIO pinmux settings. + * + * @param gpio The pin number of GPIO. From 0 to 53. + * @param fsel The selection of pinmux. RPI3_GPIO_FUNC_INPUT: input, + * RPI3_GPIO_FUNC_OUTPUT: output, + * RPI3_GPIO_FUNC_ALT0: alt-0, + * RPI3_GPIO_FUNC_ALT1: alt-1, + * RPI3_GPIO_FUNC_ALT2: alt-2, + * RPI3_GPIO_FUNC_ALT3: alt-3, + * RPI3_GPIO_FUNC_ALT4: alt-4, + * RPI3_GPIO_FUNC_ALT5: alt-5 + */ +void rpi3_gpio_set_select(int gpio, int fsel) +{ + int regN = gpio / 10; + int shift = 3 * (gpio % 10); + uintptr_t reg_sel = reg_base + RPI3_GPIO_GPFSEL(regN); + uint32_t sel = mmio_read_32(reg_sel); + uint32_t mask = U(0x07) << shift; + + sel = (sel & (~mask)) | ((fsel << shift) & mask); + mmio_write_32(reg_sel, sel); +} + +static int rpi3_gpio_get_direction(int gpio) +{ + int result = rpi3_gpio_get_select(gpio); + + if (result == RPI3_GPIO_FUNC_INPUT) + return GPIO_DIR_IN; + else if (result == RPI3_GPIO_FUNC_OUTPUT) + return GPIO_DIR_OUT; + + return GPIO_DIR_IN; +} + +static void rpi3_gpio_set_direction(int gpio, int direction) +{ + switch (direction) { + case GPIO_DIR_IN: + rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_INPUT); + break; + case GPIO_DIR_OUT: + rpi3_gpio_set_select(gpio, RPI3_GPIO_FUNC_OUTPUT); + break; + } +} + +static int rpi3_gpio_get_value(int gpio) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_lev = reg_base + RPI3_GPIO_GPLEV(regN); + uint32_t value = mmio_read_32(reg_lev); + + if ((value >> shift) & 0x01) + return GPIO_LEVEL_HIGH; + return GPIO_LEVEL_LOW; +} + +static void rpi3_gpio_set_value(int gpio, int value) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_set = reg_base + RPI3_GPIO_GPSET(regN); + uintptr_t reg_clr = reg_base + RPI3_GPIO_GPSET(regN); + + switch (value) { + case GPIO_LEVEL_LOW: + mmio_write_32(reg_clr, U(1) << shift); + break; + case GPIO_LEVEL_HIGH: + mmio_write_32(reg_set, U(1) << shift); + break; + } +} + +static void rpi3_gpio_set_pull(int gpio, int pull) +{ + int regN = gpio / 32; + int shift = gpio % 32; + uintptr_t reg_pud = reg_base + RPI3_GPIO_GPPUD; + uintptr_t reg_clk = reg_base + RPI3_GPIO_GPPUDCLK(regN); + + switch (pull) { + case GPIO_PULL_NONE: + mmio_write_32(reg_pud, 0x0); + break; + case GPIO_PULL_UP: + mmio_write_32(reg_pud, 0x2); + break; + case GPIO_PULL_DOWN: + mmio_write_32(reg_pud, 0x1); + break; + } + mdelay(150); + mmio_write_32(reg_clk, U(1) << shift); + mdelay(150); + mmio_write_32(reg_clk, 0x0); + mmio_write_32(reg_pud, 0x0); +} + +void rpi3_gpio_init(void) +{ + reg_base = RPI3_GPIO_BASE; + gpio_init(&rpi3_gpio_ops); +} diff --git a/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c b/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c new file mode 100644 index 0000000..aef1f39 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +#include + +#define RPI3_MAILBOX_MAX_RETRIES U(1000000) + +/******************************************************************************* + * Routine to send requests to the VideoCore using the mailboxes. + ******************************************************************************/ +void rpi3_vc_mailbox_request_send(rpi3_mbox_request_t *req, int req_size) +{ + uint32_t st, data; + uintptr_t resp_addr, addr; + unsigned int retries; + + /* This is the location of the request buffer */ + addr = (uintptr_t)req; + + /* Make sure that the changes are seen by the VideoCore */ + flush_dcache_range(addr, req_size); + + /* Wait until the outbound mailbox is empty */ + retries = 0U; + + do { + st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX1_STATUS_OFFSET); + + retries++; + if (retries == RPI3_MAILBOX_MAX_RETRIES) { + ERROR("rpi3: mbox: Send request timeout\n"); + return; + } + + } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) == 0U); + + /* Send base address of this message to start request */ + mmio_write_32(RPI3_MBOX_BASE + RPI3_MBOX1_WRITE_OFFSET, + RPI3_CHANNEL_ARM_TO_VC | (uint32_t) addr); + + /* Wait until the inbound mailbox isn't empty */ + retries = 0U; + + do { + st = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_STATUS_OFFSET); + + retries++; + if (retries == RPI3_MAILBOX_MAX_RETRIES) { + ERROR("rpi3: mbox: Receive response timeout\n"); + return; + } + + } while ((st & RPI3_MBOX_STATUS_EMPTY_MASK) != 0U); + + /* Get location and channel */ + data = mmio_read_32(RPI3_MBOX_BASE + RPI3_MBOX0_READ_OFFSET); + + if ((data & RPI3_CHANNEL_MASK) != RPI3_CHANNEL_ARM_TO_VC) { + ERROR("rpi3: mbox: Wrong channel: 0x%08x\n", data); + panic(); + } + + resp_addr = (uintptr_t)(data & ~RPI3_CHANNEL_MASK); + if (addr != resp_addr) { + ERROR("rpi3: mbox: Unexpected address: 0x%08x\n", data); + panic(); + } + + /* Make sure that the data seen by the CPU is up to date */ + inv_dcache_range(addr, req_size); +} diff --git a/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c b/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c new file mode 100644 index 0000000..b6bf005 --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include + +/* Initial amount of values to discard */ +#define RNG_WARMUP_COUNT U(0x40000) + +static void rpi3_rng_initialize(void) +{ + uint32_t int_mask, ctrl; + + /* Return if it is already enabled */ + ctrl = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET); + if ((ctrl & RPI3_RNG_CTRL_ENABLE) != 0U) { + return; + } + + /* Mask interrupts */ + int_mask = mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET); + int_mask |= RPI3_RNG_INT_MASK_DISABLE; + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_INT_MASK_OFFSET, int_mask); + + /* Discard several values when initializing to give it time to warmup */ + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET, RNG_WARMUP_COUNT); + + mmio_write_32(RPI3_RNG_BASE + RPI3_RNG_CTRL_OFFSET, + RPI3_RNG_CTRL_ENABLE); +} + +static uint32_t rpi3_rng_get_word(void) +{ + size_t nwords; + + do { + /* Get number of available words to read */ + nwords = (mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_STATUS_OFFSET) + >> RPI3_RNG_STATUS_NUM_WORDS_SHIFT) + & RPI3_RNG_STATUS_NUM_WORDS_MASK; + } while (nwords == 0U); + + return mmio_read_32(RPI3_RNG_BASE + RPI3_RNG_DATA_OFFSET); +} + +void rpi3_rng_read(void *buf, size_t len) +{ + uint32_t data; + size_t left = len; + uint32_t *dst = buf; + + assert(buf != NULL); + assert(len != 0U); + assert(check_uptr_overflow((uintptr_t) buf, (uintptr_t) len) == 0); + + rpi3_rng_initialize(); + + while (left >= sizeof(uint32_t)) { + data = rpi3_rng_get_word(); + *dst++ = data; + left -= sizeof(uint32_t); + } + + if (left > 0U) { + data = rpi3_rng_get_word(); + memcpy(dst, &data, left); + } +} diff --git a/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c b/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c new file mode 100644 index 0000000..c4b6fca --- /dev/null +++ b/arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void rpi3_sdhost_initialize(void); +static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd); +static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width); +static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size); +static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size); +static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops rpi3_sdhost_ops = { + .init = rpi3_sdhost_initialize, + .send_cmd = rpi3_sdhost_send_cmd, + .set_ios = rpi3_sdhost_set_ios, + .prepare = rpi3_sdhost_prepare, + .read = rpi3_sdhost_read, + .write = rpi3_sdhost_write, +}; + +static struct rpi3_sdhost_params rpi3_sdhost_params; + +/** + * Wait for command being processed. + * + * This function waits the command being processed. It compares + * the ENABLE flag of the HC_COMMAND register. When ENABLE flag disappeared + * it means the command is processed by the SDHOST. + * The timeout is currently 1000*100 us = 100 ms. + * + * @return 0: command finished. 1: command timed out. + */ +static int rpi3_sdhost_waitcommand(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + volatile int timeout = 1000; + + while ((mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_ENABLE) + && (--timeout > 0)) { + udelay(100); + } + + return ((timeout > 0) ? 0 : (-(ETIMEDOUT))); +} + +/** + * Send the command and argument to the SDHOST + * + * This function will wait for the previous command finished. And then + * clear any error status of previous command. And then + * send out the command and args. The command will be turned on the ENABLE + * flag before sending out. + */ +static void send_command_raw(unsigned int cmd, unsigned int arg) +{ + unsigned int status; + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + /* wait for previous command finish */ + rpi3_sdhost_waitcommand(); + + /* clean error status */ + status = mmio_read_32(reg_base + HC_HOSTSTATUS); + if (status & HC_HSTST_MASK_ERROR_ALL) + mmio_write_32(reg_base + HC_HOSTSTATUS, status); + + /* recording the command */ + rpi3_sdhost_params.current_cmd = cmd & HC_CMD_COMMAND_MASK; + + /* send the argument and command */ + mmio_write_32(reg_base + HC_ARGUMENT, arg); + mmio_write_32(reg_base + HC_COMMAND, cmd | HC_CMD_ENABLE); +} + +/** + * Send the command and argument to the SDHOST, decorated with control + * flags. + * + * This function will use send_command_raw to send the commands to SDHOST. + * But before sending it will decorate the command with control flags specific + * to SDHOST. + */ +static void send_command_decorated(unsigned int cmd, unsigned int arg) +{ + unsigned int cmd_flags = 0; + + switch (cmd & HC_CMD_COMMAND_MASK) { + case MMC_CMD(0): + cmd_flags |= HC_CMD_RESPONSE_NONE; + break; + case MMC_ACMD(51): + cmd_flags |= HC_CMD_READ; + break; + case MMC_CMD(8): + case MMC_CMD(11): + case MMC_CMD(17): + case MMC_CMD(18): + cmd_flags |= HC_CMD_READ; + break; + case MMC_CMD(20): + case MMC_CMD(24): + case MMC_CMD(25): + cmd_flags |= HC_CMD_WRITE; + break; + case MMC_CMD(12): + cmd_flags |= HC_CMD_BUSY; + break; + default: + break; + } + send_command_raw(cmd | cmd_flags, arg); +} + +/** + * drains the FIFO on DATA port + * + * This function drains any data left in the DATA port. + */ +static void rpi3_drain_fifo(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + volatile int timeout = 100000; + + rpi3_sdhost_waitcommand(); + + while (mmio_read_32(reg_base + HC_HOSTSTATUS) & HC_HSTST_HAVEDATA) { + mmio_read_32(reg_base + HC_DATAPORT); + udelay(100); + } + + while (1) { + uint32_t edm, fsm; + + edm = mmio_read_32(reg_base + HC_DEBUG); + fsm = edm & HC_DBG_FSM_MASK; + + if ((fsm == HC_DBG_FSM_IDENTMODE) || + (fsm == HC_DBG_FSM_DATAMODE)) + break; + + if ((fsm == HC_DBG_FSM_READWAIT) || + (fsm == HC_DBG_FSM_WRITESTART1) || + (fsm == HC_DBG_FSM_READDATA)) { + mmio_write_32(reg_base + HC_DEBUG, + edm | HC_DBG_FORCE_DATA_MODE); + break; + } + + if (--timeout <= 0) { + ERROR("rpi3_sdhost: %s cannot recover stat\n", + __func__); + return; + } + } +} + +/** + * Dump SDHOST registers + */ +static void rpi3_sdhost_print_regs(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + INFO("rpi3_sdhost: HC_COMMAND: 0x%08x\n", + mmio_read_32(reg_base + HC_COMMAND)); + INFO("rpi3_sdhost: HC_ARGUMENT: 0x%08x\n", + mmio_read_32(reg_base + HC_ARGUMENT)); + INFO("rpi3_sdhost: HC_TIMEOUTCOUNTER: 0x%08x\n", + mmio_read_32(reg_base + HC_TIMEOUTCOUNTER)); + INFO("rpi3_sdhost: HC_CLOCKDIVISOR: 0x%08x\n", + mmio_read_32(reg_base + HC_CLOCKDIVISOR)); + INFO("rpi3_sdhost: HC_RESPONSE_0: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_0)); + INFO("rpi3_sdhost: HC_RESPONSE_1: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_1)); + INFO("rpi3_sdhost: HC_RESPONSE_2: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_2)); + INFO("rpi3_sdhost: HC_RESPONSE_3: 0x%08x\n", + mmio_read_32(reg_base + HC_RESPONSE_3)); + INFO("rpi3_sdhost: HC_HOSTSTATUS: 0x%08x\n", + mmio_read_32(reg_base + HC_HOSTSTATUS)); + INFO("rpi3_sdhost: HC_POWER: 0x%08x\n", + mmio_read_32(reg_base + HC_POWER)); + INFO("rpi3_sdhost: HC_DEBUG: 0x%08x\n", + mmio_read_32(reg_base + HC_DEBUG)); + INFO("rpi3_sdhost: HC_HOSTCONFIG: 0x%08x\n", + mmio_read_32(reg_base + HC_HOSTCONFIG)); + INFO("rpi3_sdhost: HC_BLOCKSIZE: 0x%08x\n", + mmio_read_32(reg_base + HC_BLOCKSIZE)); + INFO("rpi3_sdhost: HC_BLOCKCOUNT: 0x%08x\n", + mmio_read_32(reg_base + HC_BLOCKCOUNT)); +} + +/** + * Reset SDHOST + */ +static void rpi3_sdhost_reset(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + unsigned int dbg; + uint32_t tmp1; + + mmio_write_32(reg_base + HC_POWER, 0); + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + + mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_DEFAULT); + mmio_write_32(reg_base + HC_CLOCKDIVISOR, 0); + mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_RESET); + mmio_write_32(reg_base + HC_HOSTCONFIG, 0); + mmio_write_32(reg_base + HC_BLOCKSIZE, 0); + mmio_write_32(reg_base + HC_BLOCKCOUNT, 0); + + dbg = mmio_read_32(reg_base + HC_DEBUG); + dbg &= ~((HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_READ_SHIFT) | + (HC_DBG_FIFO_THRESH_MASK << HC_DBG_FIFO_THRESH_WRITE_SHIFT)); + dbg |= (HC_FIFO_THRESH_READ << HC_DBG_FIFO_THRESH_READ_SHIFT) | + (HC_FIFO_THRESH_WRITE << HC_DBG_FIFO_THRESH_WRITE_SHIFT); + mmio_write_32(reg_base + HC_DEBUG, dbg); + mdelay(250); + mmio_write_32(reg_base + HC_POWER, 1); + mdelay(250); + rpi3_sdhost_params.clk_rate = 0; + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_MAXVAL); + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 | HC_HSTCF_INT_BUSY); +} + +static void rpi3_sdhost_initialize(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + assert((rpi3_sdhost_params.reg_base & MMC_BLOCK_MASK) == 0); + + rpi3_sdhost_reset(); + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_PREFERVAL); + udelay(300); +} + +static int rpi3_sdhost_send_cmd(struct mmc_cmd *cmd) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int err = 0; + uint32_t cmd_idx; + uint32_t cmd_arg; + uint32_t cmd_flags = 0; + uint32_t intmask; + + /* Wait for the command done */ + err = rpi3_sdhost_waitcommand(); + if (err != 0) { + WARN("previous command not done yet\n"); + return err; + } + + cmd_idx = cmd->cmd_idx & HC_CMD_COMMAND_MASK; + + cmd_arg = cmd->cmd_arg; + if (cmd_idx == MMC_ACMD(51)) { + /* if previous cmd send to SDHOST is not MMC_CMD(55). + * It means this MMC_ACMD(51) is a resend. + * And we must also resend MMC_CMD(55) in this case + */ + if (rpi3_sdhost_params.current_cmd != MMC_CMD(55)) { + send_command_decorated( + MMC_CMD(55), + rpi3_sdhost_params.sdcard_rca << + RCA_SHIFT_OFFSET); + rpi3_sdhost_params.mmc_app_cmd = 1; + rpi3_sdhost_waitcommand(); + + /* Also we need to call prepare to clean the buffer */ + rpi3_sdhost_prepare(0, (uintptr_t)NULL, 8); + } + } + + /* We ignore MMC_CMD(12) sending from the TF-A's MMC driver + * because we send MMC_CMD(12) by ourselves. + */ + if (cmd_idx == MMC_CMD(12)) + return 0; + + if ((cmd->resp_type & MMC_RSP_136) && + (cmd->resp_type & MMC_RSP_BUSY)) { + ERROR("rpi3_sdhost: unsupported response type!\n"); + return -(EOPNOTSUPP); + } + + if (cmd->resp_type & MMC_RSP_48 && cmd->resp_type != MMC_RESPONSE_R2) { + /* 48-bit command + * We don't need to set any flags here because it is default. + */ + } else if (cmd->resp_type & MMC_RSP_136) { + /* 136-bit command */ + cmd_flags |= HC_CMD_RESPONSE_LONG; + } else { + /* no respond command */ + cmd_flags |= HC_CMD_RESPONSE_NONE; + } + + rpi3_sdhost_params.cmdbusy = 0; + if (cmd->resp_type & MMC_RSP_BUSY) { + cmd_flags |= HC_CMD_BUSY; + rpi3_sdhost_params.cmdbusy = 1; + } + + if (rpi3_sdhost_params.mmc_app_cmd) { + switch (cmd_idx) { + case MMC_ACMD(41): + if (cmd_arg == OCR_HCS) + cmd_arg |= OCR_3_3_3_4; + break; + default: + break; + } + rpi3_sdhost_params.mmc_app_cmd = 0; + } + + if (cmd_idx == MMC_CMD(55)) + rpi3_sdhost_params.mmc_app_cmd = 1; + + send_command_decorated(cmd_idx | cmd_flags, cmd_arg); + + intmask = mmio_read_32(reg_base + HC_HOSTSTATUS); + if (rpi3_sdhost_params.cmdbusy && (intmask & HC_HSTST_INT_BUSY)) { + mmio_write_32(reg_base + HC_HOSTSTATUS, HC_HSTST_INT_BUSY); + rpi3_sdhost_params.cmdbusy = 0; + } + + if (!(cmd_flags & HC_CMD_RESPONSE_NONE)) { + err = rpi3_sdhost_waitcommand(); + if (err != 0) + ERROR("rpi3_sdhost: cmd cannot be finished\n"); + } + + cmd->resp_data[0] = mmio_read_32(reg_base + HC_RESPONSE_0); + cmd->resp_data[1] = mmio_read_32(reg_base + HC_RESPONSE_1); + cmd->resp_data[2] = mmio_read_32(reg_base + HC_RESPONSE_2); + cmd->resp_data[3] = mmio_read_32(reg_base + HC_RESPONSE_3); + + if (mmio_read_32(reg_base + HC_COMMAND) & HC_CMD_FAILED) { + uint32_t sdhsts = mmio_read_32(reg_base + HC_HOSTSTATUS); + + mmio_write_32(reg_base + HC_HOSTSTATUS, + HC_HSTST_MASK_ERROR_ALL); + + /* + * If the command SEND_OP_COND returns with CRC7 error, + * it can be considered as having completed successfully. + */ + if (!(sdhsts & HC_HSTST_ERROR_CRC7) + || (cmd_idx != MMC_CMD(1))) { + if (sdhsts & HC_HSTST_TIMEOUT_CMD) { + ERROR("rpi3_sdhost: timeout status 0x%x\n", + sdhsts); + err = -(ETIMEDOUT); + } else { + ERROR("rpi3_sdhost: unknown err, cmd = 0x%x\n", + mmio_read_32(reg_base + HC_COMMAND)); + ERROR("rpi3_sdhost status: 0x%x\n", sdhsts); + err = -(EILSEQ); + } + } + } + + if ((!err) && (cmd_idx == MMC_CMD(3))) { + /* we keep the RCA in case to send MMC_CMD(55) ourselves */ + rpi3_sdhost_params.sdcard_rca = (cmd->resp_data[0] + & 0xFFFF0000U) >> 16; + } + + return err; +} + +static int rpi3_sdhost_set_clock(unsigned int clk) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + uint32_t max_clk = 250000000; + uint32_t div; + + if (clk < 100000) { + mmio_write_32(reg_base + HC_CLOCKDIVISOR, + HC_CLOCKDIVISOR_MAXVAL); + return 0; + } + + div = max_clk / clk; + if (div < 2) + div = 2; + + if ((max_clk / div) > clk) + div++; + + div -= 2; + if (div > HC_CLOCKDIVISOR_MAXVAL) + div = HC_CLOCKDIVISOR_MAXVAL; + + rpi3_sdhost_params.clk_rate = max_clk / (div + 2); + rpi3_sdhost_params.ns_per_fifo_word = (1000000000 / + rpi3_sdhost_params.clk_rate) + * 8; + + mmio_write_32(reg_base + HC_CLOCKDIVISOR, div); + return 0; +} + +static int rpi3_sdhost_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + uint32_t tmp1; + + rpi3_sdhost_set_clock(clk); + VERBOSE("rpi3_sdhost: Changing clock to %dHz for data mode\n", clk); + + if (width != MMC_BUS_WIDTH_4 && width != MMC_BUS_WIDTH_1) { + ERROR("rpi3_sdhost: width %d not supported\n", width); + return -(EOPNOTSUPP); + } + rpi3_sdhost_params.bus_width = width; + + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + tmp1 &= ~(HC_HSTCF_EXTBUS_4BIT); + if (rpi3_sdhost_params.bus_width == MMC_BUS_WIDTH_4) + tmp1 |= HC_HSTCF_EXTBUS_4BIT; + + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1); + tmp1 = mmio_read_32(reg_base + HC_HOSTCONFIG); + mmio_write_32(reg_base + HC_HOSTCONFIG, tmp1 | + HC_HSTCF_SLOW_CARD | HC_HSTCF_INTBUS_WIDE); + + return 0; +} + +static int rpi3_sdhost_prepare(int lba, uintptr_t buf, size_t size) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + size_t blocks; + size_t blocksize; + + if (size < 512) { + blocksize = size; + blocks = 1; + } else { + blocksize = 512; + blocks = size / blocksize; + if (size % blocksize != 0) + blocks++; + } + + rpi3_drain_fifo(); + + mmio_write_32(reg_base + HC_BLOCKSIZE, blocksize); + mmio_write_32(reg_base + HC_BLOCKCOUNT, blocks); + udelay(100); + return 0; +} + +static int rpi3_sdhost_read(int lba, uintptr_t buf, size_t size) +{ + int err = 0; + uint32_t *buf1 = ((uint32_t *) buf); + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int timeout = 100000; + int remaining_words = 0; + + for (int i = 0; i < size / 4; i++) { + volatile int t = timeout; + uint32_t hsts_err; + + while ((mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_HAVEDATA) == 0) { + if (t == 0) { + ERROR("rpi3_sdhost: fifo timeout after %dus\n", + timeout); + err = -(ETIMEDOUT); + break; + } + t--; + udelay(10); + } + if (t == 0) + break; + + uint32_t data = mmio_read_32(reg_base + HC_DATAPORT); + + hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_MASK_ERROR_ALL; + if (hsts_err) { + ERROR("rpi3_sdhost: transfer FIFO word %d: 0x%x\n", + i, + mmio_read_32(reg_base + HC_HOSTSTATUS)); + rpi3_sdhost_print_regs(); + + err = -(EILSEQ); + + /* clean the error status */ + mmio_write_32(reg_base + HC_HOSTSTATUS, hsts_err); + } + + if (buf1) + buf1[i] = data; + + /* speeding up if the remaining words are still a lot */ + remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4) + & HC_DBG_FIFO_THRESH_MASK; + if (remaining_words >= 7) + continue; + + /* delay. slowing down the read process */ + udelay(100); + } + + /* We decide to stop by ourselves. + * It is because MMC_CMD(18) -> MMC_CMD(13) -> MMC_CMD(12) + * doesn't work for RPi3 SDHost. + */ + if (rpi3_sdhost_params.current_cmd == MMC_CMD(18)) + send_command_decorated(MMC_CMD(12), 0); + + return err; +} + +static int rpi3_sdhost_write(int lba, uintptr_t buf, size_t size) +{ + uint32_t *buf1 = ((uint32_t *) buf); + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + int err = 0; + int remaining_words = 0; + + for (int i = 0; i < size / 4; i++) { + uint32_t hsts_err; + uint32_t data = buf1[i]; + uint32_t dbg; + uint32_t fsm_state; + + mmio_write_32(reg_base + HC_DATAPORT, data); + + dbg = mmio_read_32(reg_base + HC_DEBUG); + fsm_state = dbg & HC_DBG_FSM_MASK; + if (fsm_state != HC_DBG_FSM_WRITEDATA + && fsm_state != HC_DBG_FSM_WRITESTART1 + && fsm_state != HC_DBG_FSM_WRITESTART2 + && fsm_state != HC_DBG_FSM_WRITECRC + && fsm_state != HC_DBG_FSM_WRITEWAIT1 + && fsm_state != HC_DBG_FSM_WRITEWAIT2) { + hsts_err = mmio_read_32(reg_base + HC_HOSTSTATUS) + & HC_HSTST_MASK_ERROR_ALL; + if (hsts_err) + err = -(EILSEQ); + } + + /* speeding up if the remaining words are not many */ + remaining_words = (mmio_read_32(reg_base + HC_DEBUG) >> 4) + & HC_DBG_FIFO_THRESH_MASK; + if (remaining_words <= 4) + continue; + + udelay(100); + } + + /* We decide to stop by ourselves. + * It is because MMC_CMD(25) -> MMC_CMD(13) -> MMC_CMD(12) + * doesn't work for RPi3 SDHost. + */ + if (rpi3_sdhost_params.current_cmd == MMC_CMD(25)) + send_command_decorated(MMC_CMD(12), 0); + + return err; +} + +void rpi3_sdhost_init(struct rpi3_sdhost_params *params, + struct mmc_device_info *mmc_dev_info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0)); + + memcpy(&rpi3_sdhost_params, params, sizeof(struct rpi3_sdhost_params)); + + /* backup GPIO 48 to 53 configurations */ + for (int i = 48; i <= 53; i++) { + rpi3_sdhost_params.gpio48_pinselect[i - 48] + = rpi3_gpio_get_select(i); + VERBOSE("rpi3_sdhost: Original GPIO state %d: %d\n", + i, + rpi3_sdhost_params.gpio48_pinselect[i - 48]); + } + + /* setting pull resistors for 48 to 53. + * It is debatable to set SD_CLK to UP or NONE. We massively + * tested different brands of SD Cards and found NONE works + * most stable. + * + * GPIO 48 (SD_CLK) to GPIO_PULL_NONE + * GPIO 49 (SD_CMD) to GPIO_PULL_UP + * GPIO 50 (SD_D0) to GPIO_PULL_UP + * GPIO 51 (SD_D1) to GPIO_PULL_UP + * GPIO 52 (SD_D2) to GPIO_PULL_UP + * GPIO 53 (SD_D3) to GPIO_PULL_UP + */ + gpio_set_pull(48, GPIO_PULL_NONE); + for (int i = 49; i <= 53; i++) + gpio_set_pull(i, GPIO_PULL_UP); + + /* Set pin 48-53 to alt-0. It means route SDHOST to card slot */ + for (int i = 48; i <= 53; i++) + rpi3_gpio_set_select(i, RPI3_GPIO_FUNC_ALT0); + + mmc_init(&rpi3_sdhost_ops, params->clk_rate, params->bus_width, + params->flags, mmc_dev_info); +} + +void rpi3_sdhost_stop(void) +{ + uintptr_t reg_base = rpi3_sdhost_params.reg_base; + + VERBOSE("rpi3_sdhost: Shutting down: drain FIFO out\n"); + rpi3_drain_fifo(); + + VERBOSE("rpi3_sdhost: Shutting down: slowing down the clock\n"); + mmio_write_32(reg_base+HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_SLOWVAL); + udelay(500); + + VERBOSE("rpi3_sdhost: Shutting down: put SDHost into idle state\n"); + send_command_decorated(MMC_CMD(0), 0); + udelay(500); + + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + mmio_write_32(reg_base + HC_TIMEOUTCOUNTER, HC_TIMEOUT_IDLE); + mmio_write_32(reg_base + HC_CLOCKDIVISOR, HC_CLOCKDIVISOR_STOPVAL); + + udelay(100); + + mmio_write_32(reg_base + HC_POWER, 0); + mmio_write_32(reg_base + HC_HOSTCONFIG, 0); + mmio_write_32(reg_base + HC_BLOCKSIZE, 0x400); + mmio_write_32(reg_base + HC_BLOCKCOUNT, 0); + mmio_write_32(reg_base + HC_HOSTSTATUS, 0x7f8); + + mmio_write_32(reg_base + HC_COMMAND, 0); + mmio_write_32(reg_base + HC_ARGUMENT, 0); + + udelay(100); + + /* Restore the pinmux to original state */ + for (int i = 48; i <= 53; i++) { + rpi3_gpio_set_select(i, + rpi3_sdhost_params.gpio48_pinselect[i-48]); + } + + /* Reset the pull resistors before entering BL33. + * GPIO 48 (SD_CLK) to GPIO_PULL_UP + * GPIO 49 (SD_CMD) to GPIO_PULL_UP + * GPIO 50 (SD_D0) to GPIO_PULL_UP + * GPIO 51 (SD_D1) to GPIO_PULL_UP + * GPIO 52 (SD_D2) to GPIO_PULL_UP + * GPIO 53 (SD_D3) to GPIO_PULL_UP + */ + for (int i = 48; i <= 53; i++) + gpio_set_pull(i, GPIO_PULL_UP); +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/base.c b/arm-trusted-firmware/drivers/scmi-msg/base.c new file mode 100644 index 0000000..2d72034 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/base.c @@ -0,0 +1,198 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include +#include + +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_BASE, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t protocol_count = plat_scmi_protocol_count(); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* Null agent count since agent discovery is not supported */ + .attributes = SCMI_BASE_PROTOCOL_ATTRIBUTES(protocol_count, 0U), + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_vendor_name(); + struct scmi_base_discover_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_sub_vendor(struct scmi_msg *msg) +{ + const char *name = plat_scmi_sub_vendor_name(); + struct scmi_base_discover_sub_vendor_p2a return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + COPY_NAME_IDENTIFIER(return_values.sub_vendor_identifier, name); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void discover_implementation_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_IMPL_VERSION, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static unsigned int count_protocols_in_list(const uint8_t *protocol_list) +{ + unsigned int count = 0U; + + if (protocol_list != NULL) { + while (protocol_list[count] != 0U) { + count++; + } + } + + return count; +} + +#define MAX_PROTOCOL_IN_LIST 8U + +static void discover_list_protocols(struct scmi_msg *msg) +{ + const struct scmi_base_discover_list_protocols_a2p *a2p = NULL; + struct scmi_base_discover_list_protocols_p2a p2a = { + .status = SCMI_SUCCESS, + }; + uint8_t outargs[sizeof(p2a) + MAX_PROTOCOL_IN_LIST] = { 0U }; + const uint8_t *list = NULL; + unsigned int count = 0U; + + if (msg->in_size != sizeof(*a2p)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + assert(msg->out_size > sizeof(outargs)); + + a2p = (void *)msg->in; + + list = plat_scmi_protocol_list(msg->agent_id); + count = count_protocols_in_list(list); + if (count > a2p->skip) { + count = MIN(count - a2p->skip, MAX_PROTOCOL_IN_LIST); + } else { + count = 0U; + } + + p2a.num_protocols = count; + + memcpy(outargs, &p2a, sizeof(p2a)); + memcpy(outargs + sizeof(p2a), list + a2p->skip, count); + + scmi_write_response(msg, outargs, sizeof(outargs)); +} + +static const scmi_msg_handler_t scmi_base_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_BASE_DISCOVER_VENDOR] = discover_vendor, + [SCMI_BASE_DISCOVER_SUB_VENDOR] = discover_sub_vendor, + [SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION] = + discover_implementation_version, + [SCMI_BASE_DISCOVER_LIST_PROTOCOLS] = discover_list_protocols, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return (message_id < ARRAY_SIZE(scmi_base_handler_table)) && + (scmi_base_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg) +{ + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= ARRAY_SIZE(scmi_base_handler_table)) { + VERBOSE("Base handle not found %u\n", msg->message_id); + return NULL; + } + + return scmi_base_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/base.h b/arm-trusted-firmware/drivers/scmi-msg/base.h new file mode 100644 index 0000000..c4a9c64 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/base.h @@ -0,0 +1,75 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ + +#ifndef SCMI_MSG_BASE_H +#define SCMI_MSG_BASE_H + +#include + +#define SCMI_PROTOCOL_VERSION_BASE 0x20000U + +#define SCMI_DEFAULT_STRING_LENGTH 16U + +enum scmi_base_message_id { + SCMI_BASE_DISCOVER_VENDOR = 0x003, + SCMI_BASE_DISCOVER_SUB_VENDOR = 0x004, + SCMI_BASE_DISCOVER_IMPLEMENTATION_VERSION = 0x005, + SCMI_BASE_DISCOVER_LIST_PROTOCOLS = 0x006, + SCMI_BASE_DISCOVER_AGENT = 0x007, + SCMI_BASE_NOTIFY_ERRORS = 0x008, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS 0 +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS 8 + +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK 0xFFU +#define SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK 0xFF00U + +#define SCMI_BASE_PROTOCOL_ATTRIBUTES(NUM_PROTOCOLS, NUM_AGENTS) \ + ((((NUM_PROTOCOLS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_PROTOCOLS_MASK) | \ + (((NUM_AGENTS) << SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_POS) & \ + SCMI_BASE_PROTOCOL_ATTRS_NUM_AGENTS_MASK)) + +/* + * BASE_DISCOVER_VENDOR + */ +struct scmi_base_discover_vendor_p2a { + int32_t status; + char vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_SUB_VENDOR + */ +struct scmi_base_discover_sub_vendor_p2a { + int32_t status; + char sub_vendor_identifier[SCMI_DEFAULT_STRING_LENGTH]; +}; + +/* + * BASE_DISCOVER_IMPLEMENTATION_VERSION + * No special structure right now, see protocol_version. + */ + +/* + * BASE_DISCOVER_LIST_PROTOCOLS + */ +struct scmi_base_discover_list_protocols_a2p { + uint32_t skip; +}; + +struct scmi_base_discover_list_protocols_p2a { + int32_t status; + uint32_t num_protocols; + uint32_t protocols[]; +}; + +#endif /* SCMI_MSG_BASE_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/clock.c b/arm-trusted-firmware/drivers/scmi-msg/clock.c new file mode 100644 index 0000000..e96cede --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/clock.c @@ -0,0 +1,381 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include + +#include "common.h" + +#pragma weak plat_scmi_clock_count +#pragma weak plat_scmi_clock_get_name +#pragma weak plat_scmi_clock_rates_array +#pragma weak plat_scmi_clock_rates_by_step +#pragma weak plat_scmi_clock_get_rate +#pragma weak plat_scmi_clock_set_rate +#pragma weak plat_scmi_clock_get_state +#pragma weak plat_scmi_clock_set_state + +static bool message_id_is_supported(unsigned int message_id); + +size_t plat_scmi_clock_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_clock_get_name(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t plat_scmi_clock_rates_array(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long *rates __unused, + size_t *nb_elts __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long *steps __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +unsigned long plat_scmi_clock_get_rate(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return 0U; +} + +int32_t plat_scmi_clock_set_rate(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned long rate __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_get_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_clock_set_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + bool enable_not_disable __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_CLOCK, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + size_t agent_count = plat_scmi_clock_count(msg->agent_id); + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = SCMI_CLOCK_PROTOCOL_ATTRIBUTES(1U, agent_count), + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_attributes(struct scmi_msg *msg) +{ + const struct scmi_clock_attributes_a2p *in_args = (void *)msg->in; + struct scmi_clock_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + + name = plat_scmi_clock_get_name(msg->agent_id, clock_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.clock_name, name); + + return_values.attributes = plat_scmi_clock_get_state(msg->agent_id, + clock_id); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_get(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_get_a2p *in_args = (void *)msg->in; + unsigned long rate = 0U; + struct scmi_clock_rate_get_p2a return_values = { + .status = SCMI_SUCCESS, + }; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + rate = plat_scmi_clock_get_rate(msg->agent_id, clock_id); + + return_values.rate[0] = (uint32_t)rate; + return_values.rate[1] = (uint32_t)((uint64_t)rate >> 32); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_clock_rate_set(struct scmi_msg *msg) +{ + const struct scmi_clock_rate_set_a2p *in_args = (void *)msg->in; + unsigned long rate = 0U; + int32_t status = 0; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + rate = (unsigned long)(((uint64_t)in_args->rate[1] << 32) | + in_args->rate[0]); + + status = plat_scmi_clock_set_rate(msg->agent_id, clock_id, rate); + + scmi_status_response(msg, status); +} + +static void scmi_clock_config_set(struct scmi_msg *msg) +{ + const struct scmi_clock_config_set_a2p *in_args = (void *)msg->in; + int32_t status = SCMI_GENERIC_ERROR; + bool enable = false; + unsigned int clock_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + enable = in_args->attributes & SCMI_CLOCK_CONFIG_SET_ENABLE_MASK; + + status = plat_scmi_clock_set_state(msg->agent_id, clock_id, enable); + + scmi_status_response(msg, status); +} + +#define RATES_ARRAY_SIZE_MAX (SCMI_PLAYLOAD_MAX - \ + sizeof(struct scmi_clock_describe_rates_p2a)) + +#define SCMI_RATES_BY_ARRAY(_nb_rates, _rem_rates) \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS((_nb_rates), \ + SCMI_CLOCK_RATE_FORMAT_LIST, \ + (_rem_rates)) +#define SCMI_RATES_BY_STEP \ + SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(3U, \ + SCMI_CLOCK_RATE_FORMAT_RANGE, \ + 0U) + +#define RATE_DESC_SIZE sizeof(struct scmi_clock_rate) + +static void write_rate_desc_array_in_buffer(char *dest, unsigned long *rates, + size_t nb_elt) +{ + uint32_t *out = (uint32_t *)(uintptr_t)dest; + size_t n; + + ASSERT_SYM_PTR_ALIGN(out); + + for (n = 0U; n < nb_elt; n++) { + out[2 * n] = (uint32_t)rates[n]; + out[2 * n + 1] = (uint32_t)((uint64_t)rates[n] >> 32); + } +} + +static void scmi_clock_describe_rates(struct scmi_msg *msg) +{ + const struct scmi_clock_describe_rates_a2p *in_args = (void *)msg->in; + struct scmi_clock_describe_rates_p2a p2a = { + .status = SCMI_SUCCESS, + }; + size_t nb_rates; + int32_t status; + unsigned int clock_id; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + clock_id = SPECULATION_SAFE_VALUE(in_args->clock_id); + + if (clock_id >= plat_scmi_clock_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + /* Platform may support array rate description */ + status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, NULL, + &nb_rates); + if (status == SCMI_SUCCESS) { + /* Currently 12 cells mex, so it's affordable for the stack */ + unsigned long plat_rates[RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE]; + size_t max_nb = RATES_ARRAY_SIZE_MAX / RATE_DESC_SIZE; + size_t ret_nb = MIN(nb_rates - in_args->rate_index, max_nb); + size_t rem_nb = nb_rates - in_args->rate_index - ret_nb; + + status = plat_scmi_clock_rates_array(msg->agent_id, clock_id, + plat_rates, &ret_nb); + if (status == SCMI_SUCCESS) { + write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), + plat_rates, ret_nb); + + p2a.num_rates_flags = SCMI_RATES_BY_ARRAY(ret_nb, + rem_nb); + p2a.status = SCMI_SUCCESS; + + memcpy(msg->out, &p2a, sizeof(p2a)); + msg->out_size_out = sizeof(p2a) + + ret_nb * RATE_DESC_SIZE; + } + } else if (status == SCMI_NOT_SUPPORTED) { + unsigned long triplet[3] = { 0U, 0U, 0U }; + + /* Platform may support min§max/step triplet description */ + status = plat_scmi_clock_rates_by_step(msg->agent_id, clock_id, + triplet); + if (status == SCMI_SUCCESS) { + write_rate_desc_array_in_buffer(msg->out + sizeof(p2a), + triplet, 3U); + + p2a.num_rates_flags = SCMI_RATES_BY_STEP; + p2a.status = SCMI_SUCCESS; + + memcpy(msg->out, &p2a, sizeof(p2a)); + msg->out_size_out = sizeof(p2a) + (3U * RATE_DESC_SIZE); + } + } else { + /* Fallthrough generic exit sequence below with error status */ + } + + if (status != SCMI_SUCCESS) { + scmi_status_response(msg, status); + } else { + /* + * Message payload is already writen to msg->out, and + * msg->out_size_out updated. + */ + } +} + +static const scmi_msg_handler_t scmi_clock_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_CLOCK_ATTRIBUTES] = scmi_clock_attributes, + [SCMI_CLOCK_DESCRIBE_RATES] = scmi_clock_describe_rates, + [SCMI_CLOCK_RATE_SET] = scmi_clock_rate_set, + [SCMI_CLOCK_RATE_GET] = scmi_clock_rate_get, + [SCMI_CLOCK_CONFIG_SET] = scmi_clock_config_set, +}; + +static bool message_id_is_supported(size_t message_id) +{ + return (message_id < ARRAY_SIZE(scmi_clock_handler_table)) && + (scmi_clock_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_clock_handler_table); + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= array_size) { + VERBOSE("Clock handle not found %u", msg->message_id); + return NULL; + } + + return scmi_clock_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/clock.h b/arm-trusted-firmware/drivers/scmi-msg/clock.h new file mode 100644 index 0000000..a637934 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/clock.h @@ -0,0 +1,150 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_CLOCK_H +#define SCMI_MSG_CLOCK_H + +#include + +#include + +#define SCMI_PROTOCOL_VERSION_CLOCK 0x20000U + +/* + * Identifiers of the SCMI Clock Management Protocol commands + */ +enum scmi_clock_command_id { + SCMI_CLOCK_ATTRIBUTES = 0x003, + SCMI_CLOCK_DESCRIBE_RATES = 0x004, + SCMI_CLOCK_RATE_SET = 0x005, + SCMI_CLOCK_RATE_GET = 0x006, + SCMI_CLOCK_CONFIG_SET = 0x007, +}; + +/* Protocol attributes */ +#define SCMI_CLOCK_CLOCK_COUNT_MASK GENMASK(15, 0) +#define SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK GENMASK(23, 16) + +#define SCMI_CLOCK_PROTOCOL_ATTRIBUTES(_max_pending, _clk_count) \ + ((((_max_pending) << 16) & SCMI_CLOCK_MAX_PENDING_TRANSITIONS_MASK) | \ + (((_clk_count) & SCMI_CLOCK_CLOCK_COUNT_MASK))) + +struct scmi_clock_attributes_a2p { + uint32_t clock_id; +}; + +#define SCMI_CLOCK_NAME_LENGTH_MAX 16U + +struct scmi_clock_attributes_p2a { + int32_t status; + uint32_t attributes; + char clock_name[SCMI_CLOCK_NAME_LENGTH_MAX]; +}; + +/* + * Clock Rate Get + */ + +struct scmi_clock_rate_get_a2p { + uint32_t clock_id; +}; + +struct scmi_clock_rate_get_p2a { + int32_t status; + uint32_t rate[2]; +}; + +/* + * Clock Rate Set + */ + +/* If set, set the new clock rate asynchronously */ +#define SCMI_CLOCK_RATE_SET_ASYNC_POS 0 +/* If set, do not send a delayed asynchronous response */ +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS 1 +/* Round up, if set, otherwise round down */ +#define SCMI_CLOCK_RATE_SET_ROUND_UP_POS 2 +/* If set, the platform chooses the appropriate rounding mode */ +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS 3 + +#define SCMI_CLOCK_RATE_SET_ASYNC_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ASYNC_POS) +#define SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_MASK \ + BIT(SCMI_CLOCK_RATE_SET_NO_DELAYED_RESPONSE_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_UP_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_UP_POS) +#define SCMI_CLOCK_RATE_SET_ROUND_AUTO_MASK \ + BIT(SCMI_CLOCK_RATE_SET_ROUND_AUTO_POS) + +struct scmi_clock_rate_set_a2p { + uint32_t flags; + uint32_t clock_id; + uint32_t rate[2]; +}; + +struct scmi_clock_rate_set_p2a { + int32_t status; +}; + +/* + * Clock Config Set + */ + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_POS 0 + +#define SCMI_CLOCK_CONFIG_SET_ENABLE_MASK \ + BIT(SCMI_CLOCK_CONFIG_SET_ENABLE_POS) + +struct scmi_clock_config_set_a2p { + uint32_t clock_id; + uint32_t attributes; +}; + +struct scmi_clock_config_set_p2a { + int32_t status; +}; + +/* + * Clock Describe Rates + */ + +#define SCMI_CLOCK_RATE_FORMAT_RANGE 1U +#define SCMI_CLOCK_RATE_FORMAT_LIST 0U + +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK GENMASK_32(31, 16) +#define SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS 16 + +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK BIT(12) +#define SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS 12 + +#define SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK GENMASK_32(11, 0) + +#define SCMI_CLOCK_DESCRIBE_RATES_NUM_RATES_FLAGS(_count, _fmt, _rem_rates) \ + ( \ + ((_count) & SCMI_CLOCK_DESCRIBE_RATES_COUNT_MASK) | \ + (((_rem_rates) << SCMI_CLOCK_DESCRIBE_RATES_REMAINING_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_REMAINING_MASK) | \ + (((_fmt) << SCMI_CLOCK_DESCRIBE_RATES_FORMAT_POS) & \ + SCMI_CLOCK_DESCRIBE_RATES_FORMAT_MASK) \ + ) + +struct scmi_clock_rate { + uint32_t low; + uint32_t high; +}; + +struct scmi_clock_describe_rates_a2p { + uint32_t clock_id; + uint32_t rate_index; +}; + +struct scmi_clock_describe_rates_p2a { + int32_t status; + uint32_t num_rates_flags; + struct scmi_clock_rate rates[]; +}; + +#endif /* SCMI_MSG_CLOCK_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/common.h b/arm-trusted-firmware/drivers/scmi-msg/common.h new file mode 100644 index 0000000..62f3087 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/common.h @@ -0,0 +1,144 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#ifndef SCMI_MSG_COMMON_H +#define SCMI_MSG_COMMON_H + +#include +#include +#include +#include + +#include "base.h" +#include "clock.h" +#include "power_domain.h" +#include "reset_domain.h" + +#define SCMI_VERSION 0x20000U +#define SCMI_IMPL_VERSION 0U + +#define SCMI_PLAYLOAD_MAX 92U + +/* + * Copy name identifier in target buffer following the SCMI specification + * that state name identifier shall be a null terminated string. + */ +#define COPY_NAME_IDENTIFIER(_dst_array, _name) \ + do { \ + assert(strlen(_name) < sizeof(_dst_array)); \ + strlcpy((_dst_array), (_name), sizeof(_dst_array)); \ + } while (0) + +/* Common command identifiers shared by all procotols */ +enum scmi_common_message_id { + SCMI_PROTOCOL_VERSION = 0x000, + SCMI_PROTOCOL_ATTRIBUTES = 0x001, + SCMI_PROTOCOL_MESSAGE_ATTRIBUTES = 0x002 +}; + +/* Common platform-to-agent (p2a) PROTOCOL_VERSION structure */ +struct scmi_protocol_version_p2a { + int32_t status; + uint32_t version; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_ATTRIBUTES structure */ +struct scmi_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Generic agent-to-platform (a2p) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_a2p { + uint32_t message_id; +}; + +/* Generic platform-to-agent (p2a) PROTOCOL_MESSAGE_ATTRIBUTES structure */ +struct scmi_protocol_message_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* + * struct scmi_msg - SCMI message context + * + * @agent_id: SCMI agent ID, safely set from secure world + * @protocol_id: SCMI protocol ID for the related message, set by caller agent + * @message_id: SCMI message ID for the related message, set by caller agent + * @in: Address of the incoming message payload copied in secure memory + * @in_size: Byte length of the incoming message payload, set by caller agent + * @out: Address of of the output message payload message in non-secure memory + * @out_size: Byte length of the provisionned output buffer + * @out_size_out: Byte length of the output message payload + */ +struct scmi_msg { + unsigned int agent_id; + unsigned int protocol_id; + unsigned int message_id; + char *in; + size_t in_size; + char *out; + size_t out_size; + size_t out_size_out; +}; + +/* + * Type scmi_msg_handler_t is used by procotol drivers to safely find + * the handler function for the incoming message ID. + */ +typedef void (*scmi_msg_handler_t)(struct scmi_msg *msg); + +/* + * scmi_msg_get_base_handler - Return a handler for a base message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_base_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_clock_handler - Return a handler for a clock message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_rstd_handler - Return a handler for a reset domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg); + +/* + * scmi_msg_get_pd_handler - Return a handler for a power domain message + * @msg - message to process + * Return a function handler for the message or NULL + */ +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg); + +/* + * Process Read, process and write response for input SCMI message + * + * @msg: SCMI message context + */ +void scmi_process_message(struct scmi_msg *msg); + +/* + * Write SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @payload: Output message payload + * @size: Byte size of output message payload + */ +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size); + +/* + * Write status only SCMI response payload to output message shared memory + * + * @msg: SCMI message context + * @status: SCMI status value returned to caller + */ +void scmi_status_response(struct scmi_msg *msg, int32_t status); +#endif /* SCMI_MSG_COMMON_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/entry.c b/arm-trusted-firmware/drivers/scmi-msg/entry.c new file mode 100644 index 0000000..399115c --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/entry.c @@ -0,0 +1,91 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ + +#include + +#include +#include + +#include "common.h" + +#pragma weak scmi_msg_get_clock_handler +#pragma weak scmi_msg_get_rstd_handler +#pragma weak scmi_msg_get_pd_handler +#pragma weak scmi_msg_get_voltage_handler + +scmi_msg_handler_t scmi_msg_get_clock_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +scmi_msg_handler_t scmi_msg_get_voltage_handler(struct scmi_msg *msg __unused) +{ + return NULL; +} + +void scmi_status_response(struct scmi_msg *msg, int32_t status) +{ + assert(msg->out && msg->out_size >= sizeof(int32_t)); + + memcpy(msg->out, &status, sizeof(int32_t)); + msg->out_size_out = sizeof(int32_t); +} + +void scmi_write_response(struct scmi_msg *msg, void *payload, size_t size) +{ + /* + * Output payload shall be at least the size of the status + * Output buffer shall be at least be the size of the status + * Output paylaod shall fit in output buffer + */ + assert(payload && size >= sizeof(int32_t) && size <= msg->out_size && + msg->out && msg->out_size >= sizeof(int32_t)); + + memcpy(msg->out, payload, size); + msg->out_size_out = size; +} + +void scmi_process_message(struct scmi_msg *msg) +{ + scmi_msg_handler_t handler = NULL; + + switch (msg->protocol_id) { + case SCMI_PROTOCOL_ID_BASE: + handler = scmi_msg_get_base_handler(msg); + break; + case SCMI_PROTOCOL_ID_CLOCK: + handler = scmi_msg_get_clock_handler(msg); + break; + case SCMI_PROTOCOL_ID_RESET_DOMAIN: + handler = scmi_msg_get_rstd_handler(msg); + break; + case SCMI_PROTOCOL_ID_POWER_DOMAIN: + handler = scmi_msg_get_pd_handler(msg); + break; + default: + break; + } + + if (handler) { + handler(msg); + return; + } + + ERROR("Agent %u Protocol 0x%x Message 0x%x: not supported\n", + msg->agent_id, msg->protocol_id, msg->message_id); + + scmi_status_response(msg, SCMI_NOT_SUPPORTED); +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/power_domain.c b/arm-trusted-firmware/drivers/scmi-msg/power_domain.c new file mode 100644 index 0000000..c4e1289 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/power_domain.c @@ -0,0 +1,239 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include + +#include "common.h" + +#pragma weak plat_scmi_pd_count +#pragma weak plat_scmi_pd_get_name +#pragma weak plat_scmi_pd_get_state +#pragma weak plat_scmi_pd_set_state +#pragma weak plat_scmi_pd_statistics +#pragma weak plat_scmi_pd_get_attributes + +static bool message_id_is_supported(size_t message_id); + +size_t plat_scmi_pd_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_pd_get_name(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return NULL; +} + +unsigned int plat_scmi_pd_statistics(unsigned int agent_id __unused, + unsigned long *pd_id __unused) +{ + return 0U; +} + +unsigned int plat_scmi_pd_get_attributes(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return 0U; +} + +unsigned int plat_scmi_pd_get_state(unsigned int agent_id __unused, + unsigned int pd_id __unused) +{ + return 0U; +} + +int32_t plat_scmi_pd_set_state(unsigned int agent_id __unused, + unsigned int flags __unused, + unsigned int pd_id __unused, + unsigned int state __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_PD, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + unsigned long addr = 0UL; + unsigned int len; + + struct scmi_protocol_attributes_p2a_pd return_values = { + .status = SCMI_SUCCESS, + }; + + if (msg->in_size != 0) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + return_values.attributes = plat_scmi_pd_count(msg->agent_id); + len = plat_scmi_pd_statistics(msg->agent_id, &addr); + if (len != 0U) { + return_values.statistics_addr_low = (unsigned int)addr; + return_values.statistics_addr_high = (uint32_t)(addr >> 32); + return_values.statistics_len = len; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_attributes(struct scmi_msg *msg) +{ + const struct scmi_pd_attributes_a2p *in_args = (void *)msg->in; + struct scmi_pd_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + }; + const char *name = NULL; + unsigned int pd_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + name = plat_scmi_pd_get_name(msg->agent_id, pd_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + COPY_NAME_IDENTIFIER(return_values.pd_name, name); + + return_values.attributes = plat_scmi_pd_get_attributes(msg->agent_id, pd_id); + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_state_get(struct scmi_msg *msg) +{ + const struct scmi_pd_state_get_a2p *in_args = (void *)msg->in; + unsigned int state = 0U; + struct scmi_pd_state_get_p2a return_values = { + .status = SCMI_SUCCESS, + }; + unsigned int pd_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + state = plat_scmi_pd_get_state(msg->agent_id, pd_id); + + return_values.power_state = state; + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void scmi_pd_state_set(struct scmi_msg *msg) +{ + const struct scmi_pd_state_set_a2p *in_args = (void *)msg->in; + unsigned int flags = 0U; + int32_t status = 0; + unsigned int pd_id = 0U; + unsigned int state = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + pd_id = SPECULATION_SAFE_VALUE(in_args->pd_id); + + if (pd_id >= plat_scmi_pd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + flags = SPECULATION_SAFE_VALUE(in_args->flags); + state = SPECULATION_SAFE_VALUE(in_args->power_state); + + status = plat_scmi_pd_set_state(msg->agent_id, flags, pd_id, state); + + scmi_status_response(msg, status); +} + +static const scmi_msg_handler_t scmi_pd_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_PD_ATTRIBUTES] = scmi_pd_attributes, + [SCMI_PD_STATE_SET] = scmi_pd_state_set, + [SCMI_PD_STATE_GET] = scmi_pd_state_get, +}; + +static bool message_id_is_supported(size_t message_id) +{ + return (message_id < ARRAY_SIZE(scmi_pd_handler_table)) && + (scmi_pd_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_pd_handler(struct scmi_msg *msg) +{ + const size_t array_size = ARRAY_SIZE(scmi_pd_handler_table); + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= array_size) { + VERBOSE("pd handle not found %u", msg->message_id); + return NULL; + } + + return scmi_pd_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/power_domain.h b/arm-trusted-firmware/drivers/scmi-msg/power_domain.h new file mode 100644 index 0000000..48551fd --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/power_domain.h @@ -0,0 +1,72 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright 2021 NXP + */ + +#ifndef SCMI_MSG_PD_H +#define SCMI_MSG_PD_H + +#include + +#include + +#define SCMI_PROTOCOL_VERSION_PD 0x21000U + +/* + * Identifiers of the SCMI POWER DOMAIN Protocol commands + */ +enum scmi_pd_command_id { + SCMI_PD_ATTRIBUTES = 0x003, + SCMI_PD_STATE_SET = 0x004, + SCMI_PD_STATE_GET = 0x005, +}; + +/* Protocol attributes */ +struct scmi_pd_attributes_a2p { + uint32_t pd_id; +}; + +struct scmi_protocol_attributes_p2a_pd { + int32_t status; + uint32_t attributes; + uint32_t statistics_addr_low; + uint32_t statistics_addr_high; + uint32_t statistics_len; +}; + +#define SCMI_PD_NAME_LENGTH_MAX 16U + +struct scmi_pd_attributes_p2a { + int32_t status; + uint32_t attributes; + char pd_name[SCMI_PD_NAME_LENGTH_MAX]; +}; + +/* + * Power Domain State Get + */ + +struct scmi_pd_state_get_a2p { + uint32_t pd_id; +}; + +struct scmi_pd_state_get_p2a { + int32_t status; + uint32_t power_state; +}; + +/* + * Power domain State Set + */ + +struct scmi_pd_state_set_a2p { + uint32_t flags; + uint32_t pd_id; + uint32_t power_state; +}; + +struct scmi_pd_state_set_p2a { + int32_t status; +}; + +#endif /* SCMI_MSG_PD_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c new file mode 100644 index 0000000..76ac47e --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.c @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2020, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include + +#include +#include +#include +#include + +#include "common.h" + +static bool message_id_is_supported(unsigned int message_id); + +#pragma weak plat_scmi_rstd_count +#pragma weak plat_scmi_rstd_get_name +#pragma weak plat_scmi_rstd_autonomous +#pragma weak plat_scmi_rstd_set_state + +size_t plat_scmi_rstd_count(unsigned int agent_id __unused) +{ + return 0U; +} + +const char *plat_scmi_rstd_get_name(unsigned int agent_id __unused, + unsigned int scmi_id __unused) +{ + return NULL; +} + +int32_t plat_scmi_rstd_autonomous(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + unsigned int state __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +int32_t plat_scmi_rstd_set_state(unsigned int agent_id __unused, + unsigned int scmi_id __unused, + bool assert_not_deassert __unused) +{ + return SCMI_NOT_SUPPORTED; +} + +static void report_version(struct scmi_msg *msg) +{ + struct scmi_protocol_version_p2a return_values = { + .status = SCMI_SUCCESS, + .version = SCMI_PROTOCOL_VERSION_RESET_DOMAIN, + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + .attributes = plat_scmi_rstd_count(msg->agent_id), + }; + + if (msg->in_size != 0U) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void report_message_attributes(struct scmi_msg *msg) +{ + struct scmi_protocol_message_attributes_a2p *in_args = (void *)msg->in; + struct scmi_protocol_message_attributes_p2a return_values = { + .status = SCMI_SUCCESS, + /* For this protocol, attributes shall be zero */ + .attributes = 0U, + }; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + if (!message_id_is_supported(in_args->message_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_domain_attributes(struct scmi_msg *msg) +{ + struct scmi_reset_domain_attributes_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_attributes_p2a return_values; + const char *name = NULL; + unsigned int domain_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); + + if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_INVALID_PARAMETERS); + return; + } + + name = plat_scmi_rstd_get_name(msg->agent_id, domain_id); + if (name == NULL) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + zeromem(&return_values, sizeof(return_values)); + COPY_NAME_IDENTIFIER(return_values.name, name); + return_values.status = SCMI_SUCCESS; + return_values.flags = 0U; /* Async and Notif are not supported */ + return_values.latency = SCMI_RESET_DOMAIN_ATTR_UNK_LAT; + + scmi_write_response(msg, &return_values, sizeof(return_values)); +} + +static void reset_request(struct scmi_msg *msg) +{ + struct scmi_reset_domain_request_a2p *in_args = (void *)msg->in; + struct scmi_reset_domain_request_p2a out_args = { + .status = SCMI_SUCCESS, + }; + unsigned int domain_id = 0U; + + if (msg->in_size != sizeof(*in_args)) { + scmi_status_response(msg, SCMI_PROTOCOL_ERROR); + return; + } + + domain_id = SPECULATION_SAFE_VALUE(in_args->domain_id); + + if (domain_id >= plat_scmi_rstd_count(msg->agent_id)) { + scmi_status_response(msg, SCMI_NOT_FOUND); + return; + } + + if ((in_args->flags & SCMI_RESET_DOMAIN_AUTO) != 0U) { + out_args.status = plat_scmi_rstd_autonomous(msg->agent_id, + domain_id, + in_args->reset_state); + } else if ((in_args->flags & SCMI_RESET_DOMAIN_EXPLICIT) != 0U) { + out_args.status = plat_scmi_rstd_set_state(msg->agent_id, + domain_id, true); + } else { + out_args.status = plat_scmi_rstd_set_state(msg->agent_id, + domain_id, false); + } + + if (out_args.status != SCMI_SUCCESS) { + scmi_status_response(msg, out_args.status); + } else { + scmi_write_response(msg, &out_args, sizeof(out_args)); + } +} + +static const scmi_msg_handler_t scmi_rstd_handler_table[] = { + [SCMI_PROTOCOL_VERSION] = report_version, + [SCMI_PROTOCOL_ATTRIBUTES] = report_attributes, + [SCMI_PROTOCOL_MESSAGE_ATTRIBUTES] = report_message_attributes, + [SCMI_RESET_DOMAIN_ATTRIBUTES] = reset_domain_attributes, + [SCMI_RESET_DOMAIN_REQUEST] = reset_request, +}; + +static bool message_id_is_supported(unsigned int message_id) +{ + return (message_id < ARRAY_SIZE(scmi_rstd_handler_table)) && + (scmi_rstd_handler_table[message_id] != NULL); +} + +scmi_msg_handler_t scmi_msg_get_rstd_handler(struct scmi_msg *msg) +{ + unsigned int message_id = SPECULATION_SAFE_VALUE(msg->message_id); + + if (message_id >= ARRAY_SIZE(scmi_rstd_handler_table)) { + VERBOSE("Reset domain handle not found %u\n", msg->message_id); + return NULL; + } + + return scmi_rstd_handler_table[message_id]; +} diff --git a/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h new file mode 100644 index 0000000..47bee5e --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/reset_domain.h @@ -0,0 +1,122 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ +#ifndef SCMI_MSG_RESET_DOMAIN_H +#define SCMI_MSG_RESET_DOMAIN_H + +#include +#include + +#include + +#define SCMI_PROTOCOL_VERSION_RESET_DOMAIN 0x10000U + +#define SCMI_RESET_STATE_ARCH BIT(31) +#define SCMI_RESET_STATE_IMPL 0U + +/* + * Identifiers of the SCMI Reset Domain Management Protocol commands + */ +enum scmi_reset_domain_command_id { + SCMI_RESET_DOMAIN_ATTRIBUTES = 0x03, + SCMI_RESET_DOMAIN_REQUEST = 0x04, + SCMI_RESET_DOMAIN_NOTIFY = 0x05, +}; + +/* + * Identifiers of the SCMI Reset Domain Management Protocol responses + */ +enum scmi_reset_domain_response_id { + SCMI_RESET_ISSUED = 0x00, + SCMI_RESET_COMPLETE = 0x04, +}; + +/* + * PROTOCOL_ATTRIBUTES + */ + +#define SCMI_RESET_DOMAIN_COUNT_MASK GENMASK_32(15, 0) + +struct scmi_reset_domain_protocol_attributes_p2a { + int32_t status; + uint32_t attributes; +}; + +/* Value for scmi_reset_domain_attributes_p2a:flags */ +#define SCMI_RESET_DOMAIN_ATTR_ASYNC BIT(31) +#define SCMI_RESET_DOMAIN_ATTR_NOTIF BIT(30) + +/* Value for scmi_reset_domain_attributes_p2a:latency */ +#define SCMI_RESET_DOMAIN_ATTR_UNK_LAT 0x7fffffffU +#define SCMI_RESET_DOMAIN_ATTR_MAX_LAT 0x7ffffffeU + +/* Macro for scmi_reset_domain_attributes_p2a:name */ +#define SCMI_RESET_DOMAIN_ATTR_NAME_SZ 16U + +struct scmi_reset_domain_attributes_a2p { + uint32_t domain_id; +}; + +struct scmi_reset_domain_attributes_p2a { + int32_t status; + uint32_t flags; + uint32_t latency; + char name[SCMI_RESET_DOMAIN_ATTR_NAME_SZ]; +}; + +/* + * RESET + */ + +/* Values for scmi_reset_domain_request_a2p:flags */ +#define SCMI_RESET_DOMAIN_ASYNC BIT(2) +#define SCMI_RESET_DOMAIN_EXPLICIT BIT(1) +#define SCMI_RESET_DOMAIN_AUTO BIT(0) + +struct scmi_reset_domain_request_a2p { + uint32_t domain_id; + uint32_t flags; + uint32_t reset_state; +}; + +struct scmi_reset_domain_request_p2a { + int32_t status; +}; + +/* + * RESET_NOTIFY + */ + +/* Values for scmi_reset_notify_p2a:flags */ +#define SCMI_RESET_DOMAIN_DO_NOTIFY BIT(0) + +struct scmi_reset_domain_notify_a2p { + uint32_t domain_id; + uint32_t notify_enable; +}; + +struct scmi_reset_domain_notify_p2a { + int32_t status; +}; + +/* + * RESET_COMPLETE + */ + +struct scmi_reset_domain_complete_p2a { + int32_t status; + uint32_t domain_id; +}; + +/* + * RESET_ISSUED + */ + +struct scmi_reset_domain_issued_p2a { + uint32_t domain_id; + uint32_t reset_state; +}; + +#endif /* SCMI_MSG_RESET_DOMAIN_H */ diff --git a/arm-trusted-firmware/drivers/scmi-msg/smt.c b/arm-trusted-firmware/drivers/scmi-msg/smt.c new file mode 100644 index 0000000..9b079c7 --- /dev/null +++ b/arm-trusted-firmware/drivers/scmi-msg/smt.c @@ -0,0 +1,206 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Linaro Limited + */ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" + +/* Legacy SMT/SCMI messages are 128 bytes at most including SMT header */ +#define SCMI_PLAYLOAD_MAX 92U +#define SCMI_PLAYLOAD_U32_MAX (SCMI_PLAYLOAD_MAX / sizeof(uint32_t)) + +/** + * struct smt_header - SMT formatted header for SMT base shared memory transfer + * + * @status: Bit flags, see SMT_STATUS_* + * @flags: Bit flags, see SMT_FLAG_* + * @length: Byte size of message payload (variable) + ::message_header (32bit) + * payload: SCMI message payload data + */ +struct smt_header { + uint32_t reserved0; + uint32_t status; + uint64_t reserved1; + uint32_t flags; + uint32_t length; /* message_header + payload */ + uint32_t message_header; + uint32_t payload[]; +}; + +CASSERT(SCMI_PLAYLOAD_MAX + sizeof(struct smt_header) <= SMT_BUF_SLOT_SIZE, + assert_scmi_message_max_length_fits_in_smt_buffer_slot); + +/* Flag set in smt_header::status when SMT does not contain pending message */ +#define SMT_STATUS_FREE BIT_32(0) +/* Flag set in smt_header::status when SMT reports an error */ +#define SMT_STATUS_ERROR BIT_32(1) + +/* Flag set in smt_header::flags when SMT uses interrupts */ +#define SMT_FLAG_INTR_ENABLED BIT_32(1) + +/* Bit fields packed in smt_header::message_header */ +#define SMT_MSG_ID_MASK GENMASK_32(7, 0) +#define SMT_HDR_MSG_ID(_hdr) ((_hdr) & SMT_MSG_ID_MASK) + +#define SMT_MSG_TYPE_MASK GENMASK_32(9, 8) +#define SMT_HDR_TYPE_ID(_hdr) (((_hdr) & SMT_MSG_TYPE_MASK) >> 8) + +#define SMT_MSG_PROT_ID_MASK GENMASK_32(17, 10) +#define SMT_HDR_PROT_ID(_hdr) (((_hdr) & SMT_MSG_PROT_ID_MASK) >> 10) + +/* + * Provision input message payload buffers for fastcall SMC context entries + * and for interrupt context execution entries. + */ +static uint32_t fast_smc_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; +static uint32_t interrupt_payload[PLATFORM_CORE_COUNT][SCMI_PLAYLOAD_U32_MAX]; + +/* SMP protection on channel access */ +static struct spinlock smt_channels_lock; + +/* If channel is not busy, set busy and return true, otherwise return false */ +static bool channel_set_busy(struct scmi_msg_channel *chan) +{ + bool channel_is_busy; + + spin_lock(&smt_channels_lock); + + channel_is_busy = chan->busy; + + if (!channel_is_busy) { + chan->busy = true; + } + + spin_unlock(&smt_channels_lock); + + return !channel_is_busy; +} + +static void channel_release_busy(struct scmi_msg_channel *chan) +{ + chan->busy = false; +} + +static struct smt_header *channel_to_smt_hdr(struct scmi_msg_channel *chan) +{ + return (struct smt_header *)chan->shm_addr; +} + +/* + * Creates a SCMI message instance in secure memory and pushes it in the SCMI + * message drivers. Message structure contains SCMI protocol meta-data and + * references to input payload in secure memory and output message buffer + * in shared memory. + */ +static void scmi_proccess_smt(unsigned int agent_id, uint32_t *payload_buf) +{ + struct scmi_msg_channel *chan; + struct smt_header *smt_hdr; + size_t in_payload_size; + uint32_t smt_status; + struct scmi_msg msg; + bool error = true; + + chan = plat_scmi_get_channel(agent_id); + if (chan == NULL) { + return; + } + + smt_hdr = channel_to_smt_hdr(chan); + assert(smt_hdr); + + smt_status = __atomic_load_n(&smt_hdr->status, __ATOMIC_RELAXED); + + if (!channel_set_busy(chan)) { + VERBOSE("SCMI channel %u busy", agent_id); + goto out; + } + + in_payload_size = __atomic_load_n(&smt_hdr->length, __ATOMIC_RELAXED) - + sizeof(smt_hdr->message_header); + + if (in_payload_size > SCMI_PLAYLOAD_MAX) { + VERBOSE("SCMI payload too big %zu", in_payload_size); + goto out; + } + + if ((smt_status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)) != 0U) { + VERBOSE("SCMI channel bad status 0x%x", + smt_hdr->status & (SMT_STATUS_ERROR | SMT_STATUS_FREE)); + goto out; + } + + /* Fill message */ + zeromem(&msg, sizeof(msg)); + msg.in = (char *)payload_buf; + msg.in_size = in_payload_size; + msg.out = (char *)smt_hdr->payload; + msg.out_size = chan->shm_size - sizeof(*smt_hdr); + + assert((msg.out != NULL) && (msg.out_size >= sizeof(int32_t))); + + /* Here the payload is copied in secure memory */ + memcpy(msg.in, smt_hdr->payload, in_payload_size); + + msg.protocol_id = SMT_HDR_PROT_ID(smt_hdr->message_header); + msg.message_id = SMT_HDR_MSG_ID(smt_hdr->message_header); + msg.agent_id = agent_id; + + scmi_process_message(&msg); + + /* Update message length with the length of the response message */ + smt_hdr->length = msg.out_size_out + sizeof(smt_hdr->message_header); + + channel_release_busy(chan); + error = false; + +out: + if (error) { + VERBOSE("SCMI error"); + smt_hdr->status |= SMT_STATUS_ERROR | SMT_STATUS_FREE; + } else { + smt_hdr->status |= SMT_STATUS_FREE; + } +} + +void scmi_smt_fastcall_smc_entry(unsigned int agent_id) +{ + scmi_proccess_smt(agent_id, + fast_smc_payload[plat_my_core_pos()]); +} + +void scmi_smt_interrupt_entry(unsigned int agent_id) +{ + scmi_proccess_smt(agent_id, + interrupt_payload[plat_my_core_pos()]); +} + +/* Init a SMT header for a shared memory buffer: state it a free/no-error */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan) +{ + if (chan != NULL) { + struct smt_header *smt_header = channel_to_smt_hdr(chan); + + if (smt_header != NULL) { + memset(smt_header, 0, sizeof(*smt_header)); + smt_header->status = SMT_STATUS_FREE; + + return; + } + } + + panic(); +} diff --git a/arm-trusted-firmware/drivers/st/bsec/bsec2.c b/arm-trusted-firmware/drivers/st/bsec/bsec2.c new file mode 100644 index 0000000..68d3a5b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/bsec/bsec2.c @@ -0,0 +1,961 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +#define BSEC_IP_VERSION_1_1 U(0x11) +#define BSEC_IP_VERSION_2_0 U(0x20) +#define BSEC_IP_ID_2 U(0x100032) + +#define OTP_ACCESS_SIZE (round_up(OTP_MAX_SIZE, __WORD_BIT) / __WORD_BIT) + +static uint32_t otp_nsec_access[OTP_ACCESS_SIZE] __unused; + +static uint32_t bsec_power_safmem(bool power); + +/* BSEC access protection */ +static spinlock_t bsec_spinlock; +static uintptr_t bsec_base; + +static void bsec_lock(void) +{ + if (stm32mp_lock_available()) { + spin_lock(&bsec_spinlock); + } +} + +static void bsec_unlock(void) +{ + if (stm32mp_lock_available()) { + spin_unlock(&bsec_spinlock); + } +} + +static bool is_otp_invalid_mode(void) +{ + bool ret = ((bsec_get_status() & BSEC_MODE_INVALID) == BSEC_MODE_INVALID); + + if (ret) { + ERROR("OTP mode is OTP-INVALID\n"); + } + + return ret; +} + +#if defined(IMAGE_BL32) +static int bsec_get_dt_node(struct dt_node_info *info) +{ + int node; + + node = dt_get_node(info, -1, DT_BSEC_COMPAT); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return node; +} + +static void enable_non_secure_access(uint32_t otp) +{ + otp_nsec_access[otp / __WORD_BIT] |= BIT(otp % __WORD_BIT); + + if (bsec_shadow_register(otp) != BSEC_OK) { + panic(); + } +} + +static bool non_secure_can_access(uint32_t otp) +{ + return (otp_nsec_access[otp / __WORD_BIT] & + BIT(otp % __WORD_BIT)) != 0U; +} + +static void bsec_dt_otp_nsec_access(void *fdt, int bsec_node) +{ + int bsec_subnode; + + fdt_for_each_subnode(bsec_subnode, fdt, bsec_node) { + const fdt32_t *cuint; + uint32_t otp; + uint32_t i; + uint32_t size; + uint32_t offset; + uint32_t length; + + cuint = fdt_getprop(fdt, bsec_subnode, "reg", NULL); + if (cuint == NULL) { + panic(); + } + + offset = fdt32_to_cpu(*cuint); + cuint++; + length = fdt32_to_cpu(*cuint); + + otp = offset / sizeof(uint32_t); + + if (otp < STM32MP1_UPPER_OTP_START) { + unsigned int otp_end = round_up(offset + length, + sizeof(uint32_t)) / + sizeof(uint32_t); + + if (otp_end > STM32MP1_UPPER_OTP_START) { + /* + * OTP crosses Lower/Upper boundary, consider + * only the upper part. + */ + otp = STM32MP1_UPPER_OTP_START; + length -= (STM32MP1_UPPER_OTP_START * + sizeof(uint32_t)) - offset; + offset = STM32MP1_UPPER_OTP_START * + sizeof(uint32_t); + + WARN("OTP crosses Lower/Upper boundary\n"); + } else { + continue; + } + } + + if ((fdt_getprop(fdt, bsec_subnode, + "st,non-secure-otp", NULL)) == NULL) { + continue; + } + + if (((offset % sizeof(uint32_t)) != 0U) || + ((length % sizeof(uint32_t)) != 0U)) { + ERROR("Unaligned non-secure OTP\n"); + panic(); + } + + size = length / sizeof(uint32_t); + + for (i = otp; i < (otp + size); i++) { + enable_non_secure_access(i); + } + } +} + +static void bsec_late_init(void) +{ + void *fdt; + int node; + struct dt_node_info bsec_info; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = bsec_get_dt_node(&bsec_info); + if (node < 0) { + panic(); + } + + assert(bsec_base == bsec_info.base); + + bsec_dt_otp_nsec_access(fdt, node); +} +#endif + +static uint32_t otp_bank_offset(uint32_t otp) +{ + assert(otp <= STM32MP1_OTP_MAX_ID); + + return ((otp & ~BSEC_OTP_MASK) >> BSEC_OTP_BANK_SHIFT) * + sizeof(uint32_t); +} + +/* + * bsec_check_error: check BSEC error status. + * otp: OTP number. + * check_disturbed: check only error (false), + * or error and disturbed status (true). + * return value: BSEC_OK if no error. + */ +static uint32_t bsec_check_error(uint32_t otp, bool check_disturbed) +{ + uint32_t bit = BIT(otp & BSEC_OTP_MASK); + uint32_t bank = otp_bank_offset(otp); + + if ((mmio_read_32(bsec_base + BSEC_ERROR_OFF + bank) & bit) != 0U) { + return BSEC_ERROR; + } + + if (!check_disturbed) { + return BSEC_OK; + } + + if ((mmio_read_32(bsec_base + BSEC_DISTURBED_OFF + bank) & bit) != 0U) { + return BSEC_DISTURBED; + } + + return BSEC_OK; +} + +/* + * bsec_probe: initialize BSEC driver. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_probe(void) +{ + bsec_base = BSEC_BASE; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if ((((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_1_1) && + ((bsec_get_version() & BSEC_IPVR_MSK) != BSEC_IP_VERSION_2_0)) || + (bsec_get_id() != BSEC_IP_ID_2)) { + panic(); + } + +#if defined(IMAGE_BL32) + bsec_late_init(); +#endif + return BSEC_OK; +} + +/* + * bsec_get_base: return BSEC base address. + */ +uint32_t bsec_get_base(void) +{ + return bsec_base; +} + +/* + * bsec_set_config: enable and configure BSEC. + * cfg: pointer to param structure used to set register. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_config(struct bsec_config *cfg) +{ + uint32_t value; + uint32_t result; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + value = ((((uint32_t)cfg->freq << BSEC_CONF_FRQ_SHIFT) & + BSEC_CONF_FRQ_MASK) | + (((uint32_t)cfg->pulse_width << BSEC_CONF_PRG_WIDTH_SHIFT) & + BSEC_CONF_PRG_WIDTH_MASK) | + (((uint32_t)cfg->tread << BSEC_CONF_TREAD_SHIFT) & + BSEC_CONF_TREAD_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, value); + + bsec_unlock(); + + result = bsec_power_safmem((bool)cfg->power & + BSEC_CONF_POWER_UP_MASK); + if (result != BSEC_OK) { + return result; + } + + value = ((((uint32_t)cfg->upper_otp_lock << UPPER_OTP_LOCK_SHIFT) & + UPPER_OTP_LOCK_MASK) | + (((uint32_t)cfg->den_lock << DENREG_LOCK_SHIFT) & + DENREG_LOCK_MASK) | + (((uint32_t)cfg->prog_lock << GPLOCK_LOCK_SHIFT) & + GPLOCK_LOCK_MASK)); + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_LOCK_OFF, value); + + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_get_config: return config parameters set in BSEC registers. + * cfg: config param return. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_get_config(struct bsec_config *cfg) +{ + uint32_t value; + + if (cfg == NULL) { + return BSEC_INVALID_PARAM; + } + + value = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + cfg->power = (uint8_t)((value & BSEC_CONF_POWER_UP_MASK) >> + BSEC_CONF_POWER_UP_SHIFT); + cfg->freq = (uint8_t)((value & BSEC_CONF_FRQ_MASK) >> + BSEC_CONF_FRQ_SHIFT); + cfg->pulse_width = (uint8_t)((value & BSEC_CONF_PRG_WIDTH_MASK) >> + BSEC_CONF_PRG_WIDTH_SHIFT); + cfg->tread = (uint8_t)((value & BSEC_CONF_TREAD_MASK) >> + BSEC_CONF_TREAD_SHIFT); + + value = mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF); + cfg->upper_otp_lock = (uint8_t)((value & UPPER_OTP_LOCK_MASK) >> + UPPER_OTP_LOCK_SHIFT); + cfg->den_lock = (uint8_t)((value & DENREG_LOCK_MASK) >> + DENREG_LOCK_SHIFT); + cfg->prog_lock = (uint8_t)((value & GPLOCK_LOCK_MASK) >> + GPLOCK_LOCK_SHIFT); + + return BSEC_OK; +} + +/* + * bsec_shadow_register: copy SAFMEM OTP to BSEC data. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_register(uint32_t otp) +{ + uint32_t result; + bool value; + bool power_up = false; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sr_lock(otp, &value); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-read bit read Error %u\n", otp, result); + return result; + } + + if (value) { + VERBOSE("BSEC: OTP %u is locked and will not be refreshed\n", + otp); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_READ); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + result = bsec_check_error(otp, true); + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_read_otp: read an OTP data value. + * val: read value. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp) +{ + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + *val = mmio_read_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t))); + + return BSEC_OK; +} + +/* + * bsec_write_otp: write value in BSEC data register. + * val: value to write. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_write_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + bool value; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sw_lock(otp, &value); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-write bit read Error %u\n", otp, result); + return result; + } + + if (value) { + VERBOSE("BSEC: OTP %u is locked and write will be ignored\n", + otp); + } + + /* Ensure integrity of each register access sequence */ + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_DATA_OFF + + (otp * sizeof(uint32_t)), val); + + bsec_unlock(); + + return result; +} + +/* + * bsec_program_otp: program a bit in SAFMEM after the prog. + * The OTP data is not refreshed. + * val: value to program. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_program_otp(uint32_t val, uint32_t otp) +{ + uint32_t result; + bool power_up = false; + bool sp_lock; + bool perm_lock; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + result = bsec_read_sp_lock(otp, &sp_lock); + if (result != BSEC_OK) { + ERROR("BSEC: %u Sticky-prog bit read Error %u\n", otp, result); + return result; + } + + result = bsec_read_permanent_lock(otp, &perm_lock); + if (result != BSEC_OK) { + ERROR("BSEC: %u permanent bit read Error %u\n", otp, result); + return result; + } + + if (sp_lock || perm_lock) { + WARN("BSEC: OTP locked, prog will be ignored\n"); + return BSEC_PROG_FAIL; + } + + if ((mmio_read_32(bsec_base + BSEC_OTP_LOCK_OFF) & + BIT(BSEC_LOCK_PROGRAM)) != 0U) { + WARN("BSEC: GPLOCK activated, prog will be ignored\n"); + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, val); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, otp | BSEC_WRITE); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp, true); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_permanent_lock_otp: permanent lock of OTP in SAFMEM. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_permanent_lock_otp(uint32_t otp) +{ + uint32_t result; + bool power_up = false; + uint32_t data; + uint32_t addr; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if ((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) { + result = bsec_power_safmem(true); + + if (result != BSEC_OK) { + return result; + } + + power_up = true; + } + + if (otp < STM32MP1_UPPER_OTP_START) { + addr = otp >> ADDR_LOWER_OTP_PERLOCK_SHIFT; + data = DATA_LOWER_OTP_PERLOCK_BIT << + ((otp & DATA_LOWER_OTP_PERLOCK_MASK) << 1U); + } else { + addr = (otp >> ADDR_UPPER_OTP_PERLOCK_SHIFT) + 2U; + data = DATA_UPPER_OTP_PERLOCK_BIT << + (otp & DATA_UPPER_OTP_PERLOCK_MASK); + } + + bsec_lock(); + + mmio_write_32(bsec_base + BSEC_OTP_WRDATA_OFF, data); + + mmio_write_32(bsec_base + BSEC_OTP_CTRL_OFF, + addr | BSEC_WRITE | BSEC_LOCK); + + while ((bsec_get_status() & BSEC_MODE_BUSY_MASK) != 0U) { + ; + } + + if ((bsec_get_status() & BSEC_MODE_PROGFAIL_MASK) != 0U) { + result = BSEC_PROG_FAIL; + } else { + result = bsec_check_error(otp, false); + } + + bsec_unlock(); + + if (power_up) { + if (bsec_power_safmem(false) != BSEC_OK) { + panic(); + } + } + + return result; +} + +/* + * bsec_write_debug_conf: write value in debug feature. + * to enable/disable debug service. + * val: value to write. + * return value: none. + */ +void bsec_write_debug_conf(uint32_t val) +{ + if (is_otp_invalid_mode()) { + return; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_DEN_OFF, val & BSEC_DEN_ALL_MSK); + bsec_unlock(); +} + +/* + * bsec_read_debug_conf: return debug configuration register value. + */ +uint32_t bsec_read_debug_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_DEN_OFF); +} + +/* + * bsec_write_scratch: write value in scratch register. + * val: value to write. + * return value: none. + */ +void bsec_write_scratch(uint32_t val) +{ +#if defined(IMAGE_BL32) + if (is_otp_invalid_mode()) { + return; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SCRATCH_OFF, val); + bsec_unlock(); +#else + mmio_write_32(BSEC_BASE + BSEC_SCRATCH_OFF, val); +#endif +} + +/* + * bsec_read_scratch: return scratch register value. + */ +uint32_t bsec_read_scratch(void) +{ + return mmio_read_32(bsec_base + BSEC_SCRATCH_OFF); +} + +/* + * bsec_get_status: return status register value. + */ +uint32_t bsec_get_status(void) +{ + return mmio_read_32(bsec_base + BSEC_OTP_STATUS_OFF); +} + +/* + * bsec_get_hw_conf: return hardware configuration register value. + */ +uint32_t bsec_get_hw_conf(void) +{ + return mmio_read_32(bsec_base + BSEC_IPHW_CFG_OFF); +} + +/* + * bsec_get_version: return BSEC version register value. + */ +uint32_t bsec_get_version(void) +{ + return mmio_read_32(bsec_base + BSEC_IPVR_OFF); +} + +/* + * bsec_get_id: return BSEC ID register value. + */ +uint32_t bsec_get_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_ID_OFF); +} + +/* + * bsec_get_magic_id: return BSEC magic number register value. + */ +uint32_t bsec_get_magic_id(void) +{ + return mmio_read_32(bsec_base + BSEC_IP_MAGIC_ID_OFF); +} + +/* + * bsec_set_sr_lock: set shadow-read lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sr_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SRLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sr_lock: read shadow-read lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sr_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SRLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_set_sw_lock: set shadow-write lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sw_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SWLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sw_lock: read shadow-write lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sw_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SWLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_set_sp_lock: set shadow-program lock. + * otp: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_set_sp_lock(uint32_t otp) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bsec_lock(); + mmio_write_32(bsec_base + BSEC_SPLOCK_OFF + bank, otp_mask); + bsec_unlock(); + + return BSEC_OK; +} + +/* + * bsec_read_sp_lock: read shadow-program lock. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_sp_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_SPLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_read_permanent_lock: Read permanent lock status. + * otp: OTP number. + * value: read value (true or false). + * return value: BSEC_OK if no error. + */ +uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value) +{ + uint32_t bank = otp_bank_offset(otp); + uint32_t otp_mask = BIT(otp & BSEC_OTP_MASK); + uint32_t bank_value; + + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + bank_value = mmio_read_32(bsec_base + BSEC_WRLOCK_OFF + bank); + + *value = ((bank_value & otp_mask) != 0U); + + return BSEC_OK; +} + +/* + * bsec_otp_lock: Lock Upper OTP or Global Programming or Debug Enable. + * service: Service to lock, see header file. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_otp_lock(uint32_t service) +{ + uintptr_t reg = bsec_base + BSEC_OTP_LOCK_OFF; + + if (is_otp_invalid_mode()) { + return BSEC_ERROR; + } + + switch (service) { + case BSEC_LOCK_UPPER_OTP: + mmio_write_32(reg, BIT(BSEC_LOCK_UPPER_OTP)); + break; + case BSEC_LOCK_DEBUG: + mmio_write_32(reg, BIT(BSEC_LOCK_DEBUG)); + break; + case BSEC_LOCK_PROGRAM: + mmio_write_32(reg, BIT(BSEC_LOCK_PROGRAM)); + break; + default: + return BSEC_INVALID_PARAM; + } + + return BSEC_OK; +} + +/* + * bsec_power_safmem: Activate or deactivate SAFMEM power. + * power: true to power up, false to power down. + * return value: BSEC_OK if no error. + */ +static uint32_t bsec_power_safmem(bool power) +{ + uint32_t register_val; + uint32_t timeout = BSEC_TIMEOUT_VALUE; + + bsec_lock(); + + register_val = mmio_read_32(bsec_base + BSEC_OTP_CONF_OFF); + + if (power) { + register_val |= BSEC_CONF_POWER_UP_MASK; + } else { + register_val &= ~BSEC_CONF_POWER_UP_MASK; + } + + mmio_write_32(bsec_base + BSEC_OTP_CONF_OFF, register_val); + + if (power) { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) == 0U) && + (timeout != 0U)) { + timeout--; + } + } else { + while (((bsec_get_status() & BSEC_MODE_PWR_MASK) != 0U) && + (timeout != 0U)) { + timeout--; + } + } + + bsec_unlock(); + + if (timeout == 0U) { + return BSEC_TIMEOUT; + } + + return BSEC_OK; +} + +/* + * bsec_shadow_read_otp: Load OTP from SAFMEM and provide its value. + * otp_value: read value. + * word: OTP number. + * return value: BSEC_OK if no error. + */ +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word) +{ + uint32_t result; + + result = bsec_shadow_register(word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Shadowing Error %u\n", word, result); + return result; + } + + result = bsec_read_otp(otp_value, word); + if (result != BSEC_OK) { + ERROR("BSEC: %u Read Error %u\n", word, result); + } + + return result; +} + +/* + * bsec_check_nsec_access_rights: check non-secure access rights to target OTP. + * otp: OTP number. + * return value: BSEC_OK if authorized access. + */ +uint32_t bsec_check_nsec_access_rights(uint32_t otp) +{ +#if defined(IMAGE_BL32) + if (otp > STM32MP1_OTP_MAX_ID) { + return BSEC_INVALID_PARAM; + } + + if (otp >= STM32MP1_UPPER_OTP_START) { + if (!non_secure_can_access(otp)) { + return BSEC_ERROR; + } + } +#endif + + return BSEC_OK; +} + diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c new file mode 100644 index 0000000..355c9da --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c @@ -0,0 +1,1097 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include "clk-stm32-core.h" +#include +#include +#include +#include +#include +#include +#include + +static struct spinlock reg_lock; +static struct spinlock refcount_lock; + +static struct stm32_clk_priv *stm32_clock_data; + +const struct stm32_clk_ops clk_mux_ops; + +struct stm32_clk_priv *clk_stm32_get_priv(void) +{ + return stm32_clock_data; +} + +static void stm32mp1_clk_lock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + /* Assume interrupts are masked */ + spin_lock(lock); + } +} + +static void stm32mp1_clk_unlock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + spin_unlock(lock); + } +} + +void stm32mp1_clk_rcc_regs_lock(void) +{ + stm32mp1_clk_lock(®_lock); +} + +void stm32mp1_clk_rcc_regs_unlock(void) +{ + stm32mp1_clk_unlock(®_lock); +} + +#define TIMEOUT_US_1S U(1000000) +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_osc_cfg *osc_cfg = clk->clock_cfg; + int osc_id = osc_cfg->osc_id; + + return &priv->osci_data[osc_id]; +} + +void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_bypass *bypass_data = osc_data->bypass; + uintptr_t address; + + if (bypass_data == NULL) { + return; + } + + address = priv->base + bypass_data->offset; + + if (digbyp) { + mmio_setbits_32(address, BIT(bypass_data->bit_digbyp)); + } + + if (bypass || digbyp) { + mmio_setbits_32(address, BIT(bypass_data->bit_byp)); + } +} + +void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_css *css_data = osc_data->css; + uintptr_t address; + + if (css_data == NULL) { + return; + } + + address = priv->base + css_data->offset; + + if (css) { + mmio_setbits_32(address, BIT(css_data->bit_css)); + } +} + +void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + struct stm32_clk_drive *drive_data = osc_data->drive; + uintptr_t address; + uint32_t mask; + uint32_t value; + + if (drive_data == NULL) { + return; + } + + address = priv->base + drive_data->offset; + + mask = (BIT(drive_data->drv_width) - 1U) << drive_data->drv_shift; + + /* + * Warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (mmio_read_32(address) & mask) >> drive_data->drv_shift; + + while (value != lsedrv) { + if (value > lsedrv) { + value--; + } else { + value++; + } + + mmio_clrsetbits_32(address, mask, value << drive_data->drv_shift); + } +} + +int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return _clk_stm32_gate_wait_ready(priv, osc_data->gate_id, ready_on); +} + +int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id) +{ + return clk_oscillator_wait_ready(priv, id, true); +} + +int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id) +{ + return clk_oscillator_wait_ready(priv, id, false); +} + +static int clk_gate_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + mmio_setbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); + + return 0; +} + +static void clk_gate_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + mmio_clrbits_32(priv->base + cfg->offset, BIT(cfg->bit_idx)); +} + +static bool clk_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_gate_cfg *cfg = clk->clock_cfg; + + return ((mmio_read_32(priv->base + cfg->offset) & BIT(cfg->bit_idx)) != 0U); +} + +const struct stm32_clk_ops clk_gate_ops = { + .enable = clk_gate_enable, + .disable = clk_gate_disable, + .is_enabled = clk_gate_is_enabled, +}; + +void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); + } else { + mmio_clrbits_32(addr, BIT(gate->bit_idx)); + } +} + +int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr, BIT(gate->bit_idx)); + + } else { + mmio_setbits_32(addr, BIT(gate->bit_idx)); + } + + return 0; +} + +const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id) +{ + return priv->clks[id].name; +} + +const char *clk_stm32_get_name(struct stm32_clk_priv *priv, + unsigned long binding_id) +{ + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return NULL; + } + + return _clk_stm32_get_name(priv, id); +} + +const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id) +{ + if ((unsigned int)id < priv->num) { + return &priv->clks[id]; + } + + return NULL; +} + +#define clk_div_mask(_width) GENMASK(((_width) - 1U), 0U) + +static unsigned int _get_table_div(const struct clk_div_table *table, + unsigned int val) +{ + const struct clk_div_table *clkt; + + for (clkt = table; clkt->div; clkt++) { + if (clkt->val == val) { + return clkt->div; + } + } + + return 0; +} + +static unsigned int _get_div(const struct clk_div_table *table, + unsigned int val, unsigned long flags, + uint8_t width) +{ + if ((flags & CLK_DIVIDER_ONE_BASED) != 0UL) { + return val; + } + + if ((flags & CLK_DIVIDER_POWER_OF_TWO) != 0UL) { + return BIT(val); + } + + if ((flags & CLK_DIVIDER_MAX_AT_ZERO) != 0UL) { + return (val != 0U) ? val : BIT(width); + } + + if (table != NULL) { + return _get_table_div(table, val); + } + + return val + 1U; +} + +#define TIMEOUT_US_200MS U(200000) +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS + +int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel) +{ + const struct parent_cfg *parents = &priv->parents[pid & MUX_PARENT_MASK]; + const struct mux_cfg *mux = parents->mux; + uintptr_t address = priv->base + mux->offset; + uint32_t mask; + uint64_t timeout; + + mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + + mmio_clrsetbits_32(address, mask, (sel << mux->shift) & mask); + + if (mux->bitrdy == MUX_NO_BIT_RDY) { + return 0; + } + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + + mask = BIT(mux->bitrdy); + + while ((mmio_read_32(address) & mask) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int clk, int clkp) +{ + const struct parent_cfg *parents; + uint16_t pid; + uint8_t sel; + int old_parent; + + pid = priv->clks[clk].parent; + + if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { + return -EINVAL; + } + + old_parent = _clk_stm32_get_parent(priv, clk); + if (old_parent == clkp) { + return 0; + } + + parents = &priv->parents[pid & MUX_PARENT_MASK]; + + for (sel = 0; sel < parents->num_parents; sel++) { + if (parents->id_parents[sel] == (uint16_t)clkp) { + bool clk_was_enabled = _clk_stm32_is_enabled(priv, clk); + int err = 0; + + /* Enable the parents (for glitch free mux) */ + _clk_stm32_enable(priv, clkp); + _clk_stm32_enable(priv, old_parent); + + err = clk_mux_set_parent(priv, pid, sel); + + _clk_stm32_disable(priv, old_parent); + + if (clk_was_enabled) { + _clk_stm32_disable(priv, old_parent); + } else { + _clk_stm32_disable(priv, clkp); + } + + return err; + } + } + + return -EINVAL; +} + +int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id) +{ + const struct parent_cfg *parent; + const struct mux_cfg *mux; + uint32_t mask; + + if (mux_id >= priv->nb_parents) { + panic(); + } + + parent = &priv->parents[mux_id]; + mux = parent->mux; + + mask = MASK_WIDTH_SHIFT(mux->width, mux->shift); + + return (mmio_read_32(priv->base + mux->offset) & mask) >> mux->shift; +} + +int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel) +{ + uint16_t pid; + + pid = priv->clks[clk].parent; + + if ((pid == CLK_IS_ROOT) || (pid < MUX_MAX_PARENTS)) { + return -EINVAL; + } + + return clk_mux_set_parent(priv, pid, sel); +} + +int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int clk_id) +{ + const struct clk_stm32 *clk = _clk_get(priv, clk_id); + const struct parent_cfg *parent; + uint16_t mux_id; + int sel; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + parent = &priv->parents[mux_id]; + + if (clk->ops->get_parent != NULL) { + sel = clk->ops->get_parent(priv, clk_id); + } else { + sel = clk_mux_get_parent(priv, mux_id); + } + + if (sel < parent->num_parents) { + return parent->id_parents[sel]; + } + + return -EINVAL; +} + +int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id) +{ + uint16_t mux_id; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + + return clk_mux_get_parent(priv, mux_id); +} + +int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx) +{ + const struct parent_cfg *parent; + uint16_t mux_id; + + mux_id = priv->clks[clk_id].parent; + if (mux_id == CLK_IS_ROOT) { + return CLK_IS_ROOT; + } + + if (mux_id < MUX_MAX_PARENTS) { + return mux_id & MUX_PARENT_MASK; + } + + mux_id &= MUX_PARENT_MASK; + parent = &priv->parents[mux_id]; + + if (idx < parent->num_parents) { + return parent->id_parents[idx]; + } + + return -EINVAL; +} + +int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id) +{ + unsigned int i; + + for (i = 0U; i < priv->num; i++) { + if (binding_id == priv->clks[i].binding) { + return (int)i; + } + } + + return -EINVAL; +} + +unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + int parent; + unsigned long rate = 0UL; + + if ((unsigned int)id >= priv->num) { + return rate; + } + + parent = _clk_stm32_get_parent(priv, id); + + if (clk->ops->recalc_rate != NULL) { + unsigned long prate = 0UL; + + if (parent != CLK_IS_ROOT) { + prate = _clk_stm32_get_rate(priv, parent); + } + + rate = clk->ops->recalc_rate(priv, id, prate); + + return rate; + } + + switch (parent) { + case CLK_IS_ROOT: + panic(); + + default: + rate = _clk_stm32_get_rate(priv, parent); + break; + } + return rate; + +} + +unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id) +{ + int parent_id = _clk_stm32_get_parent(priv, id); + + return _clk_stm32_get_rate(priv, parent_id); +} + +static uint8_t _stm32_clk_get_flags(struct stm32_clk_priv *priv, int id) +{ + return priv->clks[id].flags; +} + +bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag) +{ + if (_stm32_clk_get_flags(priv, id) & flag) { + return true; + } + + return false; +} + +int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->enable != NULL) { + clk->ops->enable(priv, id); + } + + return 0; +} + +static int _clk_stm32_enable_core(struct stm32_clk_priv *priv, int id) +{ + int parent; + int ret = 0; + + if (priv->gate_refcounts[id] == 0U) { + parent = _clk_stm32_get_parent(priv, id); + if (parent != CLK_IS_ROOT) { + ret = _clk_stm32_enable_core(priv, parent); + if (ret) { + return ret; + } + } + clk_stm32_enable_call_ops(priv, id); + } + + priv->gate_refcounts[id]++; + + if (priv->gate_refcounts[id] == UINT_MAX) { + ERROR("%s: %d max enable count !", __func__, id); + panic(); + } + + return 0; +} + +int _clk_stm32_enable(struct stm32_clk_priv *priv, int id) +{ + int ret; + + stm32mp1_clk_lock(&refcount_lock); + ret = _clk_stm32_enable_core(priv, id); + stm32mp1_clk_unlock(&refcount_lock); + + return ret; +} + +void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->disable != NULL) { + clk->ops->disable(priv, id); + } +} + +static void _clk_stm32_disable_core(struct stm32_clk_priv *priv, int id) +{ + int parent; + + if ((priv->gate_refcounts[id] == 1U) && _stm32_clk_is_flags(priv, id, CLK_IS_CRITICAL)) { + return; + } + + if (priv->gate_refcounts[id] == 0U) { + /* case of clock ignore unused */ + if (_clk_stm32_is_enabled(priv, id)) { + clk_stm32_disable_call_ops(priv, id); + return; + } + VERBOSE("%s: %d already disabled !\n\n", __func__, id); + return; + } + + if (--priv->gate_refcounts[id] > 0U) { + return; + } + + clk_stm32_disable_call_ops(priv, id); + + parent = _clk_stm32_get_parent(priv, id); + if (parent != CLK_IS_ROOT) { + _clk_stm32_disable_core(priv, parent); + } +} + +void _clk_stm32_disable(struct stm32_clk_priv *priv, int id) +{ + stm32mp1_clk_lock(&refcount_lock); + + _clk_stm32_disable_core(priv, id); + + stm32mp1_clk_unlock(&refcount_lock); +} + +bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + + if (clk->ops->is_enabled != NULL) { + return clk->ops->is_enabled(priv, id); + } + + return priv->gate_refcounts[id]; +} + +static int clk_stm32_enable(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return id; + } + + return _clk_stm32_enable(priv, id); +} + +static void clk_stm32_disable(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id != -EINVAL) { + _clk_stm32_disable(priv, id); + } +} + +static bool clk_stm32_is_enabled(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return false; + } + + return _clk_stm32_is_enabled(priv, id); +} + +static unsigned long clk_stm32_get_rate(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return 0UL; + } + + return _clk_stm32_get_rate(priv, id); +} + +static int clk_stm32_get_parent(unsigned long binding_id) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int id; + + id = clk_get_index(priv, binding_id); + if (id == -EINVAL) { + return id; + } + + return _clk_stm32_get_parent(priv, id); +} + +static const struct clk_ops stm32mp_clk_ops = { + .enable = clk_stm32_enable, + .disable = clk_stm32_disable, + .is_enabled = clk_stm32_is_enabled, + .get_rate = clk_stm32_get_rate, + .get_parent = clk_stm32_get_parent, +}; + +void clk_stm32_enable_critical_clocks(void) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + unsigned int i; + + for (i = 0U; i < priv->num; i++) { + if (_stm32_clk_is_flags(priv, i, CLK_IS_CRITICAL)) { + _clk_stm32_enable(priv, i); + } + } +} + +static void stm32_clk_register(void) +{ + clk_register(&stm32mp_clk_ops); +} + +uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id) +{ + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = 0; + + val = mmio_read_32(priv->base + divider->offset) >> divider->shift; + val &= clk_div_mask(divider->width); + + return val; +} + +unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, + int div_id, + unsigned long prate) +{ + const struct div_cfg *divider = &priv->div[div_id]; + uint32_t val = clk_stm32_div_get_value(priv, div_id); + unsigned int div = 0U; + + div = _get_div(divider->table, val, divider->flags, divider->width); + if (div == 0U) { + return prate; + } + + return div_round_up((uint64_t)prate, div); +} + +unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_div_cfg *div_cfg = clk->clock_cfg; + + return _clk_stm32_divider_recalc(priv, div_cfg->id, prate); +} + +const struct stm32_clk_ops clk_stm32_divider_ops = { + .recalc_rate = clk_stm32_divider_recalc, +}; + +int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value) +{ + const struct div_cfg *divider; + uintptr_t address; + uint64_t timeout; + uint32_t mask; + + if (div_id >= priv->nb_div) { + panic(); + } + + divider = &priv->div[div_id]; + address = priv->base + divider->offset; + + mask = MASK_WIDTH_SHIFT(divider->width, divider->shift); + mmio_clrsetbits_32(address, mask, (value << divider->shift) & mask); + + if (divider->bitrdy == DIV_NO_BIT_RDY) { + return 0; + } + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + mask = BIT(divider->bitrdy); + + while ((mmio_read_32(address) & mask) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, + bool ready_on) +{ + const struct gate_cfg *gate = &priv->gates[gate_id]; + uintptr_t address = priv->base + gate->offset; + uint32_t mask_rdy = BIT(gate->bit_idx); + uint64_t timeout; + uint32_t mask_test; + + if (ready_on) { + mask_test = BIT(gate->bit_idx); + } else { + mask_test = 0U; + } + + timeout = timeout_init_us(OSCRDY_TIMEOUT); + + while ((mmio_read_32(address) & mask_rdy) != mask_test) { + if (timeout_elapsed(timeout)) { + break; + } + } + + if ((mmio_read_32(address) & mask_rdy) != mask_test) + return -ETIMEDOUT; + + return 0; +} + +int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + const struct gate_cfg *gate = &priv->gates[cfg->id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr, BIT(gate->bit_idx)); + + } else { + mmio_setbits_32(addr, BIT(gate->bit_idx)); + } + + return 0; +} + +void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + const struct gate_cfg *gate = &priv->gates[cfg->id]; + uintptr_t addr = priv->base + gate->offset; + + if (gate->set_clr != 0U) { + mmio_write_32(addr + RCC_MP_ENCLRR_OFFSET, BIT(gate->bit_idx)); + } else { + mmio_clrbits_32(addr, BIT(gate->bit_idx)); + } +} + +bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id) +{ + const struct gate_cfg *gate; + uint32_t addr; + + gate = &priv->gates[gate_id]; + addr = priv->base + gate->offset; + + return ((mmio_read_32(addr) & BIT(gate->bit_idx)) != 0U); +} + +bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_gate_cfg *cfg = clk->clock_cfg; + + return _clk_stm32_gate_is_enabled(priv, cfg->id); +} + +const struct stm32_clk_ops clk_stm32_gate_ops = { + .enable = clk_stm32_gate_enable, + .disable = clk_stm32_gate_disable, + .is_enabled = clk_stm32_gate_is_enabled, +}; + +const struct stm32_clk_ops clk_fixed_factor_ops = { + .recalc_rate = fixed_factor_recalc_rate, +}; + +unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + const struct fixed_factor_cfg *cfg = clk->clock_cfg; + unsigned long long rate; + + rate = (unsigned long long)prate * cfg->mult; + + if (cfg->div == 0U) { + ERROR("division by zero\n"); + panic(); + } + + return (unsigned long)(rate / cfg->div); +}; + +#define APB_DIV_MASK GENMASK(2, 0) +#define TIM_PRE_MASK BIT(0) + +static unsigned long timer_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + const struct clk_timer_cfg *cfg = clk->clock_cfg; + uint32_t prescaler, timpre; + uintptr_t rcc_base = priv->base; + + prescaler = mmio_read_32(rcc_base + cfg->apbdiv) & + APB_DIV_MASK; + + timpre = mmio_read_32(rcc_base + cfg->timpre) & + TIM_PRE_MASK; + + if (prescaler == 0U) { + return prate; + } + + return prate * (timpre + 1U) * 2U; +}; + +const struct stm32_clk_ops clk_timer_ops = { + .recalc_rate = timer_recalc_rate, +}; + +static unsigned long clk_fixed_rate_recalc(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct clk_stm32_fixed_rate_cfg *cfg = clk->clock_cfg; + + return cfg->rate; +} + +const struct stm32_clk_ops clk_stm32_fixed_rate_ops = { + .recalc_rate = clk_fixed_rate_recalc, +}; + +static unsigned long clk_stm32_osc_recalc_rate(struct stm32_clk_priv *priv, + int id, unsigned long prate) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return osc_data->frequency; +}; + +bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + return _clk_stm32_gate_is_enabled(priv, osc_data->gate_id); + +} + +int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + _clk_stm32_gate_enable(priv, osc_data->gate_id); + + if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, true) != 0U) { + ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); + panic(); + } + + return 0; +} + +void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + + _clk_stm32_gate_disable(priv, osc_data->gate_id); + + if (_clk_stm32_gate_wait_ready(priv, osc_data->gate_rdy_id, false) != 0U) { + ERROR("%s: %s (%d)\n", __func__, osc_data->name, __LINE__); + panic(); + } +} + +static unsigned long clk_stm32_get_dt_oscillator_frequency(const char *name) +{ + void *fdt = NULL; + int node = 0; + int subnode = 0; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return 0UL; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar = NULL; + const fdt32_t *cuint = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + continue; + } + + if (strncmp(cchar, name, (size_t)ret) || + fdt_get_status(subnode) == DT_DISABLED) { + continue; + } + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); + if (cuint == NULL) { + return 0UL; + } + + return fdt32_to_cpu(*cuint); + } + + return 0UL; +} + +void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, id); + const char *name = osc_data->name; + + osc_data->frequency = clk_stm32_get_dt_oscillator_frequency(name); +} + +const struct stm32_clk_ops clk_stm32_osc_ops = { + .recalc_rate = clk_stm32_osc_recalc_rate, + .is_enabled = clk_stm32_osc_gate_is_enabled, + .enable = clk_stm32_osc_gate_enable, + .disable = clk_stm32_osc_gate_disable, + .init = clk_stm32_osc_init, +}; + +const struct stm32_clk_ops clk_stm32_osc_nogate_ops = { + .recalc_rate = clk_stm32_osc_recalc_rate, + .init = clk_stm32_osc_init, +}; + +int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb) +{ + const fdt32_t *cell; + int len = 0; + uint32_t i; + + cell = fdt_getprop(fdt, node, name, &len); + if (cell != NULL) { + for (i = 0; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t val = fdt32_to_cpu(cell[i]); + + tab[i] = val; + } + } + + *nb = (uint32_t)len / sizeof(uint32_t); + + return 0; +} + +int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base) +{ + unsigned int i; + + stm32_clock_data = priv; + + priv->base = base; + + for (i = 0U; i < priv->num; i++) { + const struct clk_stm32 *clk = _clk_get(priv, i); + + assert(clk->ops != NULL); + + if (clk->ops->init != NULL) { + clk->ops->init(priv, i); + } + } + + stm32_clk_register(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h new file mode 100644 index 0000000..809d05f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h @@ -0,0 +1,405 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef CLK_STM32_CORE_H +#define CLK_STM32_CORE_H + +struct mux_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t bitrdy; +}; + +struct gate_cfg { + uint16_t offset; + uint8_t bit_idx; + uint8_t set_clr; +}; + +struct clk_div_table { + unsigned int val; + unsigned int div; +}; + +struct div_cfg { + uint16_t offset; + uint8_t shift; + uint8_t width; + uint8_t flags; + uint8_t bitrdy; + const struct clk_div_table *table; +}; + +struct parent_cfg { + uint8_t num_parents; + const uint16_t *id_parents; + struct mux_cfg *mux; +}; + +struct stm32_clk_priv; + +struct stm32_clk_ops { + unsigned long (*recalc_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate); + int (*get_parent)(struct stm32_clk_priv *priv, int id); + int (*set_rate)(struct stm32_clk_priv *priv, int id, unsigned long rate, + unsigned long prate); + int (*enable)(struct stm32_clk_priv *priv, int id); + void (*disable)(struct stm32_clk_priv *priv, int id); + bool (*is_enabled)(struct stm32_clk_priv *priv, int id); + void (*init)(struct stm32_clk_priv *priv, int id); +}; + +struct clk_stm32 { + const char *name; + uint16_t binding; + uint16_t parent; + uint8_t flags; + void *clock_cfg; + const struct stm32_clk_ops *ops; +}; + +struct stm32_clk_priv { + uintptr_t base; + const uint32_t num; + const struct clk_stm32 *clks; + const struct parent_cfg *parents; + const uint32_t nb_parents; + const struct gate_cfg *gates; + const uint32_t nb_gates; + const struct div_cfg *div; + const uint32_t nb_div; + struct clk_oscillator_data *osci_data; + const uint32_t nb_osci_data; + uint32_t *gate_refcounts; + void *pdata; +}; + +struct stm32_clk_bypass { + uint16_t offset; + uint8_t bit_byp; + uint8_t bit_digbyp; +}; + +struct stm32_clk_css { + uint16_t offset; + uint8_t bit_css; +}; + +struct stm32_clk_drive { + uint16_t offset; + uint8_t drv_shift; + uint8_t drv_width; + uint8_t drv_default; +}; + +struct clk_oscillator_data { + const char *name; + uint16_t id_clk; + unsigned long frequency; + uint16_t gate_id; + uint16_t gate_rdy_id; + struct stm32_clk_bypass *bypass; + struct stm32_clk_css *css; + struct stm32_clk_drive *drive; +}; + +struct clk_fixed_rate { + const char *name; + unsigned long fixed_rate; +}; + +struct clk_gate_cfg { + uint32_t offset; + uint8_t bit_idx; +}; + +/* CLOCK FLAGS */ +#define CLK_IS_CRITICAL BIT(0) +#define CLK_IGNORE_UNUSED BIT(1) +#define CLK_SET_RATE_PARENT BIT(2) + +#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_DIVIDER_BIG_ENDIAN BIT(7) + +#define MUX_MAX_PARENTS U(0x8000) +#define MUX_PARENT_MASK GENMASK(14, 0) +#define MUX_FLAG U(0x8000) +#define MUX(mux) ((mux) | MUX_FLAG) + +#define NO_GATE 0 +#define _NO_ID UINT16_MAX +#define CLK_IS_ROOT UINT16_MAX +#define MUX_NO_BIT_RDY UINT8_MAX +#define DIV_NO_BIT_RDY UINT8_MAX + +#define MASK_WIDTH_SHIFT(_width, _shift) \ + GENMASK(((_width) + (_shift) - 1U), (_shift)) + +int clk_stm32_init(struct stm32_clk_priv *priv, uintptr_t base); +void clk_stm32_enable_critical_clocks(void); + +struct stm32_clk_priv *clk_stm32_get_priv(void); + +int clk_get_index(struct stm32_clk_priv *priv, unsigned long binding_id); +const struct clk_stm32 *_clk_get(struct stm32_clk_priv *priv, int id); + +void clk_oscillator_set_bypass(struct stm32_clk_priv *priv, int id, bool digbyp, bool bypass); +void clk_oscillator_set_drive(struct stm32_clk_priv *priv, int id, uint8_t lsedrv); +void clk_oscillator_set_css(struct stm32_clk_priv *priv, int id, bool css); + +int _clk_stm32_gate_wait_ready(struct stm32_clk_priv *priv, uint16_t gate_id, bool ready_on); + +int clk_oscillator_wait_ready(struct stm32_clk_priv *priv, int id, bool ready_on); +int clk_oscillator_wait_ready_on(struct stm32_clk_priv *priv, int id); +int clk_oscillator_wait_ready_off(struct stm32_clk_priv *priv, int id); + +const char *_clk_stm32_get_name(struct stm32_clk_priv *priv, int id); +const char *clk_stm32_get_name(struct stm32_clk_priv *priv, unsigned long binding_id); +int clk_stm32_get_counter(unsigned long binding_id); + +void _clk_stm32_gate_disable(struct stm32_clk_priv *priv, uint16_t gate_id); +int _clk_stm32_gate_enable(struct stm32_clk_priv *priv, uint16_t gate_id); + +int _clk_stm32_set_parent(struct stm32_clk_priv *priv, int id, int src_id); +int _clk_stm32_set_parent_by_index(struct stm32_clk_priv *priv, int clk, int sel); + +int _clk_stm32_get_parent(struct stm32_clk_priv *priv, int id); +int _clk_stm32_get_parent_by_index(struct stm32_clk_priv *priv, int clk_id, int idx); +int _clk_stm32_get_parent_index(struct stm32_clk_priv *priv, int clk_id); + +unsigned long _clk_stm32_get_rate(struct stm32_clk_priv *priv, int id); +unsigned long _clk_stm32_get_parent_rate(struct stm32_clk_priv *priv, int id); + +bool _stm32_clk_is_flags(struct stm32_clk_priv *priv, int id, uint8_t flag); + +int _clk_stm32_enable(struct stm32_clk_priv *priv, int id); +void _clk_stm32_disable(struct stm32_clk_priv *priv, int id); + +int clk_stm32_enable_call_ops(struct stm32_clk_priv *priv, uint16_t id); +void clk_stm32_disable_call_ops(struct stm32_clk_priv *priv, uint16_t id); + +bool _clk_stm32_is_enabled(struct stm32_clk_priv *priv, int id); + +int _clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int div_id, + unsigned long rate, unsigned long parent_rate); + +int clk_stm32_divider_set_rate(struct stm32_clk_priv *priv, int id, unsigned long rate, + unsigned long prate); + +unsigned long _clk_stm32_divider_recalc(struct stm32_clk_priv *priv, + int div_id, + unsigned long prate); + +unsigned long clk_stm32_divider_recalc(struct stm32_clk_priv *priv, int idx, + unsigned long prate); + +int clk_stm32_gate_enable(struct stm32_clk_priv *priv, int idx); +void clk_stm32_gate_disable(struct stm32_clk_priv *priv, int idx); + +bool _clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int gate_id); +bool clk_stm32_gate_is_enabled(struct stm32_clk_priv *priv, int idx); + +uint32_t clk_stm32_div_get_value(struct stm32_clk_priv *priv, int div_id); +int clk_stm32_set_div(struct stm32_clk_priv *priv, uint32_t div_id, uint32_t value); +int clk_mux_set_parent(struct stm32_clk_priv *priv, uint16_t pid, uint8_t sel); +int clk_mux_get_parent(struct stm32_clk_priv *priv, uint32_t mux_id); + +int stm32_clk_parse_fdt_by_name(void *fdt, int node, const char *name, uint32_t *tab, uint32_t *nb); + +#ifdef CFG_STM32_CLK_DEBUG +void clk_stm32_display_clock_info(void); +#endif + +struct clk_stm32_div_cfg { + int id; +}; + +#define STM32_DIV(idx, _binding, _parent, _flags, _div_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_div_cfg){\ + .id = (_div_id),\ + },\ + .ops = &clk_stm32_divider_ops,\ + } + +struct clk_stm32_gate_cfg { + int id; +}; + +#define STM32_GATE(idx, _binding, _parent, _flags, _gate_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_gate_cfg){\ + .id = (_gate_id),\ + },\ + .ops = &clk_stm32_gate_ops,\ + } + +struct fixed_factor_cfg { + unsigned int mult; + unsigned int div; +}; + +unsigned long fixed_factor_recalc_rate(struct stm32_clk_priv *priv, + int _idx, unsigned long prate); + +#define FIXED_FACTOR(idx, _idx, _parent, _mult, _div) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .clock_cfg = &(struct fixed_factor_cfg){\ + .mult = (_mult),\ + .div = (_div),\ + },\ + .ops = &clk_fixed_factor_ops,\ + } + +#define GATE(idx, _binding, _parent, _flags, _offset, _bit_idx) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_gate_cfg){\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + },\ + .ops = &clk_gate_ops,\ + } + +#define STM32_MUX(idx, _binding, _mux_id, _flags) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (MUX(_mux_id)),\ + .flags = (_flags),\ + .clock_cfg = NULL,\ + .ops = (&clk_mux_ops),\ + } + +struct clk_timer_cfg { + uint32_t apbdiv; + uint32_t timpre; +}; + +#define CK_TIMER(idx, _idx, _parent, _flags, _apbdiv, _timpre) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = (CLK_SET_RATE_PARENT | (_flags)),\ + .clock_cfg = &(struct clk_timer_cfg){\ + .apbdiv = (_apbdiv),\ + .timpre = (_timpre),\ + },\ + .ops = &clk_timer_ops,\ + } + +struct clk_stm32_fixed_rate_cfg { + unsigned long rate; +}; + +#define CLK_FIXED_RATE(idx, _binding, _rate) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_binding),\ + .parent = (CLK_IS_ROOT),\ + .clock_cfg = &(struct clk_stm32_fixed_rate_cfg){\ + .rate = (_rate),\ + },\ + .ops = &clk_stm32_fixed_rate_ops,\ + } + +#define BYPASS(_offset, _bit_byp, _bit_digbyp) &(struct stm32_clk_bypass){\ + .offset = (_offset),\ + .bit_byp = (_bit_byp),\ + .bit_digbyp = (_bit_digbyp),\ +} + +#define CSS(_offset, _bit_css) &(struct stm32_clk_css){\ + .offset = (_offset),\ + .bit_css = (_bit_css),\ +} + +#define DRIVE(_offset, _shift, _width, _default) &(struct stm32_clk_drive){\ + .offset = (_offset),\ + .drv_shift = (_shift),\ + .drv_width = (_width),\ + .drv_default = (_default),\ +} + +#define OSCILLATOR(idx_osc, _id, _name, _gate_id, _gate_rdy_id, _bypass, _css, _drive) \ + [(idx_osc)] = (struct clk_oscillator_data){\ + .name = (_name),\ + .id_clk = (_id),\ + .gate_id = (_gate_id),\ + .gate_rdy_id = (_gate_rdy_id),\ + .bypass = (_bypass),\ + .css = (_css),\ + .drive = (_drive),\ + } + +struct clk_oscillator_data *clk_oscillator_get_data(struct stm32_clk_priv *priv, int id); + +void clk_stm32_osc_init(struct stm32_clk_priv *priv, int id); +bool clk_stm32_osc_gate_is_enabled(struct stm32_clk_priv *priv, int id); +int clk_stm32_osc_gate_enable(struct stm32_clk_priv *priv, int id); +void clk_stm32_osc_gate_disable(struct stm32_clk_priv *priv, int id); + +struct stm32_osc_cfg { + int osc_id; +}; + +#define CLK_OSC(idx, _idx, _parent, _osc_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = CLK_IS_CRITICAL,\ + .clock_cfg = &(struct stm32_osc_cfg){\ + .osc_id = (_osc_id),\ + },\ + .ops = &clk_stm32_osc_ops,\ + } + +#define CLK_OSC_FIXED(idx, _idx, _parent, _osc_id) \ + [(idx)] = (struct clk_stm32){ \ + .name = #idx,\ + .binding = (_idx),\ + .parent = (_parent),\ + .flags = CLK_IS_CRITICAL,\ + .clock_cfg = &(struct stm32_osc_cfg){\ + .osc_id = (_osc_id),\ + },\ + .ops = &clk_stm32_osc_nogate_ops,\ + } + +extern const struct stm32_clk_ops clk_mux_ops; +extern const struct stm32_clk_ops clk_stm32_divider_ops; +extern const struct stm32_clk_ops clk_stm32_gate_ops; +extern const struct stm32_clk_ops clk_fixed_factor_ops; +extern const struct stm32_clk_ops clk_gate_ops; +extern const struct stm32_clk_ops clk_timer_ops; +extern const struct stm32_clk_ops clk_stm32_fixed_rate_ops; +extern const struct stm32_clk_ops clk_stm32_osc_ops; +extern const struct stm32_clk_ops clk_stm32_osc_nogate_ops; + +#endif /* CLK_STM32_CORE_H */ diff --git a/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c b/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c new file mode 100644 index 0000000..d360767 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c @@ -0,0 +1,2334 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include "clk-stm32-core.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +struct stm32_osci_dt_cfg { + unsigned long freq; + bool bypass; + bool digbyp; + bool css; + uint32_t drive; +}; + +enum pll_mn { + PLL_CFG_M, + PLL_CFG_N, + PLL_DIV_MN_NB +}; + +enum pll_pqr { + PLL_CFG_P, + PLL_CFG_Q, + PLL_CFG_R, + PLL_DIV_PQR_NB +}; + +enum pll_csg { + PLL_CSG_MOD_PER, + PLL_CSG_INC_STEP, + PLL_CSG_SSCG_MODE, + PLL_CSG_NB +}; + +struct stm32_pll_vco { + uint32_t status; + uint32_t src; + uint32_t div_mn[PLL_DIV_MN_NB]; + uint32_t frac; + bool csg_enabled; + uint32_t csg[PLL_CSG_NB]; +}; + +struct stm32_pll_output { + uint32_t output[PLL_DIV_PQR_NB]; +}; + +struct stm32_pll_dt_cfg { + struct stm32_pll_vco vco; + struct stm32_pll_output output; +}; + +struct stm32_clk_platdata { + uint32_t nosci; + struct stm32_osci_dt_cfg *osci; + uint32_t npll; + struct stm32_pll_dt_cfg *pll; + uint32_t nclksrc; + uint32_t *clksrc; + uint32_t nclkdiv; + uint32_t *clkdiv; +}; + +enum stm32_clock { + /* ROOT CLOCKS */ + _CK_OFF, + _CK_HSI, + _CK_HSE, + _CK_CSI, + _CK_LSI, + _CK_LSE, + _I2SCKIN, + _CSI_DIV122, + _HSE_DIV, + _HSE_DIV2, + _CK_PLL1, + _CK_PLL2, + _CK_PLL3, + _CK_PLL4, + _PLL1P, + _PLL1P_DIV, + _PLL2P, + _PLL2Q, + _PLL2R, + _PLL3P, + _PLL3Q, + _PLL3R, + _PLL4P, + _PLL4Q, + _PLL4R, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _PCLK6, + _CKMPU, + _CKAXI, + _CKMLAHB, + _CKPER, + _CKTIMG1, + _CKTIMG2, + _CKTIMG3, + _USB_PHY_48, + _MCO1_K, + _MCO2_K, + _TRACECK, + /* BUS and KERNEL CLOCKS */ + _DDRC1, + _DDRC1LP, + _DDRPHYC, + _DDRPHYCLP, + _DDRCAPB, + _DDRCAPBLP, + _AXIDCG, + _DDRPHYCAPB, + _DDRPHYCAPBLP, + _SYSCFG, + _DDRPERFM, + _IWDG2APB, + _USBPHY_K, + _USBO_K, + _RTCAPB, + _TZC, + _ETZPC, + _IWDG1APB, + _BSEC, + _STGENC, + _USART1_K, + _USART2_K, + _I2C3_K, + _I2C4_K, + _I2C5_K, + _TIM12, + _TIM15, + _RTCCK, + _GPIOA, + _GPIOB, + _GPIOC, + _GPIOD, + _GPIOE, + _GPIOF, + _GPIOG, + _GPIOH, + _GPIOI, + _PKA, + _SAES_K, + _CRYP1, + _HASH1, + _RNG1_K, + _BKPSRAM, + _SDMMC1_K, + _SDMMC2_K, + _DBGCK, + _USART3_K, + _UART4_K, + _UART5_K, + _UART7_K, + _UART8_K, + _USART6_K, + _MCE, + _FMC_K, + _QSPI_K, +#if defined(IMAGE_BL32) + _LTDC, + _DMA1, + _DMA2, + _MDMA, + _ETH1MAC, + _USBH, + _TIM2, + _TIM3, + _TIM4, + _TIM5, + _TIM6, + _TIM7, + _LPTIM1_K, + _SPI2_K, + _SPI3_K, + _SPDIF_K, + _TIM1, + _TIM8, + _SPI1_K, + _SAI1_K, + _SAI2_K, + _DFSDM, + _FDCAN_K, + _TIM13, + _TIM14, + _TIM16, + _TIM17, + _SPI4_K, + _SPI5_K, + _I2C1_K, + _I2C2_K, + _ADFSDM, + _LPTIM2_K, + _LPTIM3_K, + _LPTIM4_K, + _LPTIM5_K, + _VREF, + _DTS, + _PMBCTRL, + _HDP, + _STGENRO, + _DCMIPP_K, + _DMAMUX1, + _DMAMUX2, + _DMA3, + _ADC1_K, + _ADC2_K, + _TSC, + _AXIMC, + _ETH1CK, + _ETH1TX, + _ETH1RX, + _CRC1, + _ETH2CK, + _ETH2TX, + _ETH2RX, + _ETH2MAC, +#endif + CK_LAST +}; + +/* PARENT CONFIG */ +static const uint16_t RTC_src[] = { + _CK_OFF, _CK_LSE, _CK_LSI, _CK_HSE +}; + +static const uint16_t MCO1_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _CK_LSI, _CK_LSE +}; + +static const uint16_t MCO2_src[] = { + _CKMPU, _CKAXI, _CKMLAHB, _PLL4P, _CK_HSE, _CK_HSI +}; + +static const uint16_t PLL12_src[] = { + _CK_HSI, _CK_HSE +}; + +static const uint16_t PLL3_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI +}; + +static const uint16_t PLL4_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _I2SCKIN +}; + +static const uint16_t MPU_src[] = { + _CK_HSI, _CK_HSE, _PLL1P, _PLL1P_DIV +}; + +static const uint16_t AXI_src[] = { + _CK_HSI, _CK_HSE, _PLL2P +}; + +static const uint16_t MLAHBS_src[] = { + _CK_HSI, _CK_HSE, _CK_CSI, _PLL3P +}; + +static const uint16_t CKPER_src[] = { + _CK_HSI, _CK_CSI, _CK_HSE, _CK_OFF +}; + +static const uint16_t I2C12_src[] = { + _PCLK1, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C3_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C4_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t I2C5_src[] = { + _PCLK6, _PLL4R, _CK_HSI, _CK_CSI +}; + +static const uint16_t SPI1_src[] = { + _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SPI23_src[] = { + _PLL4P, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SPI4_src[] = { + _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE, _I2SCKIN +}; + +static const uint16_t SPI5_src[] = { + _PCLK6, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART1_src[] = { + _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE +}; + +static const uint16_t UART2_src[] = { + _PCLK6, _PLL3Q, _CK_HSI, _CK_CSI, _PLL4Q, _CK_HSE +}; + +static const uint16_t UART35_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART4_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART6_src[] = { + _PCLK2, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t UART78_src[] = { + _PCLK1, _PLL4Q, _CK_HSI, _CK_CSI, _CK_HSE +}; + +static const uint16_t LPTIM1_src[] = { + _PCLK1, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER +}; + +static const uint16_t LPTIM2_src[] = { + _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI +}; + +static const uint16_t LPTIM3_src[] = { + _PCLK3, _PLL4Q, _CKPER, _CK_LSE, _CK_LSI +}; + +static const uint16_t LPTIM45_src[] = { + _PCLK3, _PLL4P, _PLL3Q, _CK_LSE, _CK_LSI, _CKPER +}; + +static const uint16_t SAI1_src[] = { + _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _PLL3R +}; + +static const uint16_t SAI2_src[] = { + _PLL4Q, _PLL3Q, _I2SCKIN, _CKPER, _NO_ID, _PLL3R +}; + +static const uint16_t FDCAN_src[] = { + _CK_HSE, _PLL3Q, _PLL4Q, _PLL4R +}; + +static const uint16_t SPDIF_src[] = { + _PLL4P, _PLL3Q, _CK_HSI +}; + +static const uint16_t ADC1_src[] = { + _PLL4R, _CKPER, _PLL3Q +}; + +static const uint16_t ADC2_src[] = { + _PLL4R, _CKPER, _PLL3Q +}; + +static const uint16_t SDMMC1_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CK_HSI +}; + +static const uint16_t SDMMC2_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CK_HSI +}; + +static const uint16_t ETH1_src[] = { + _PLL4P, _PLL3Q +}; + +static const uint16_t ETH2_src[] = { + _PLL4P, _PLL3Q +}; + +static const uint16_t USBPHY_src[] = { + _CK_HSE, _PLL4R, _HSE_DIV2 +}; + +static const uint16_t USBO_src[] = { + _PLL4R, _USB_PHY_48 +}; + +static const uint16_t QSPI_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CKPER +}; + +static const uint16_t FMC_src[] = { + _CKAXI, _PLL3R, _PLL4P, _CKPER +}; + +/* Position 2 of RNG1 mux is reserved */ +static const uint16_t RNG1_src[] = { + _CK_CSI, _PLL4R, _CK_OFF, _CK_LSI +}; + +static const uint16_t STGEN_src[] = { + _CK_HSI, _CK_HSE +}; + +static const uint16_t DCMIPP_src[] = { + _CKAXI, _PLL2Q, _PLL4P, _CKPER +}; + +static const uint16_t SAES_src[] = { + _CKAXI, _CKPER, _PLL4R, _CK_LSI +}; + +#define MUX_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .id_parents = src,\ + .num_parents = ARRAY_SIZE(src),\ + .mux = &(struct mux_cfg) {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .bitrdy = MUX_NO_BIT_RDY,\ + },\ +} + +#define MUX_RDY_CFG(id, src, _offset, _shift, _witdh)[id] = {\ + .id_parents = src,\ + .num_parents = ARRAY_SIZE(src),\ + .mux = &(struct mux_cfg) {\ + .offset = (_offset),\ + .shift = (_shift),\ + .width = (_witdh),\ + .bitrdy = 31,\ + },\ +} + +static const struct parent_cfg parent_mp13[] = { + MUX_CFG(MUX_ADC1, ADC1_src, RCC_ADC12CKSELR, 0, 2), + MUX_CFG(MUX_ADC2, ADC2_src, RCC_ADC12CKSELR, 2, 2), + MUX_RDY_CFG(MUX_AXI, AXI_src, RCC_ASSCKSELR, 0, 3), + MUX_CFG(MUX_CKPER, CKPER_src, RCC_CPERCKSELR, 0, 2), + MUX_CFG(MUX_DCMIPP, DCMIPP_src, RCC_DCMIPPCKSELR, 0, 2), + MUX_CFG(MUX_ETH1, ETH1_src, RCC_ETH12CKSELR, 0, 2), + MUX_CFG(MUX_ETH2, ETH2_src, RCC_ETH12CKSELR, 8, 2), + MUX_CFG(MUX_FDCAN, FDCAN_src, RCC_FDCANCKSELR, 0, 2), + MUX_CFG(MUX_FMC, FMC_src, RCC_FMCCKSELR, 0, 2), + MUX_CFG(MUX_I2C12, I2C12_src, RCC_I2C12CKSELR, 0, 3), + MUX_CFG(MUX_I2C3, I2C3_src, RCC_I2C345CKSELR, 0, 3), + MUX_CFG(MUX_I2C4, I2C4_src, RCC_I2C345CKSELR, 3, 3), + MUX_CFG(MUX_I2C5, I2C5_src, RCC_I2C345CKSELR, 6, 3), + MUX_CFG(MUX_LPTIM1, LPTIM1_src, RCC_LPTIM1CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM2, LPTIM2_src, RCC_LPTIM23CKSELR, 0, 3), + MUX_CFG(MUX_LPTIM3, LPTIM3_src, RCC_LPTIM23CKSELR, 3, 3), + MUX_CFG(MUX_LPTIM45, LPTIM45_src, RCC_LPTIM45CKSELR, 0, 3), + MUX_CFG(MUX_MCO1, MCO1_src, RCC_MCO1CFGR, 0, 3), + MUX_CFG(MUX_MCO2, MCO2_src, RCC_MCO2CFGR, 0, 3), + MUX_RDY_CFG(MUX_MLAHB, MLAHBS_src, RCC_MSSCKSELR, 0, 2), + MUX_RDY_CFG(MUX_MPU, MPU_src, RCC_MPCKSELR, 0, 2), + MUX_RDY_CFG(MUX_PLL12, PLL12_src, RCC_RCK12SELR, 0, 2), + MUX_RDY_CFG(MUX_PLL3, PLL3_src, RCC_RCK3SELR, 0, 2), + MUX_RDY_CFG(MUX_PLL4, PLL4_src, RCC_RCK4SELR, 0, 2), + MUX_CFG(MUX_QSPI, QSPI_src, RCC_QSPICKSELR, 0, 2), + MUX_CFG(MUX_RNG1, RNG1_src, RCC_RNG1CKSELR, 0, 2), + MUX_CFG(MUX_RTC, RTC_src, RCC_BDCR, 16, 2), + MUX_CFG(MUX_SAES, SAES_src, RCC_SAESCKSELR, 0, 2), + MUX_CFG(MUX_SAI1, SAI1_src, RCC_SAI1CKSELR, 0, 3), + MUX_CFG(MUX_SAI2, SAI2_src, RCC_SAI2CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC1, SDMMC1_src, RCC_SDMMC12CKSELR, 0, 3), + MUX_CFG(MUX_SDMMC2, SDMMC2_src, RCC_SDMMC12CKSELR, 3, 3), + MUX_CFG(MUX_SPDIF, SPDIF_src, RCC_SPDIFCKSELR, 0, 2), + MUX_CFG(MUX_SPI1, SPI1_src, RCC_SPI2S1CKSELR, 0, 3), + MUX_CFG(MUX_SPI23, SPI23_src, RCC_SPI2S23CKSELR, 0, 3), + MUX_CFG(MUX_SPI4, SPI4_src, RCC_SPI45CKSELR, 0, 3), + MUX_CFG(MUX_SPI5, SPI5_src, RCC_SPI45CKSELR, 3, 3), + MUX_CFG(MUX_STGEN, STGEN_src, RCC_STGENCKSELR, 0, 2), + MUX_CFG(MUX_UART1, UART1_src, RCC_UART12CKSELR, 0, 3), + MUX_CFG(MUX_UART2, UART2_src, RCC_UART12CKSELR, 3, 3), + MUX_CFG(MUX_UART35, UART35_src, RCC_UART35CKSELR, 0, 3), + MUX_CFG(MUX_UART4, UART4_src, RCC_UART4CKSELR, 0, 3), + MUX_CFG(MUX_UART6, UART6_src, RCC_UART6CKSELR, 0, 3), + MUX_CFG(MUX_UART78, UART78_src, RCC_UART78CKSELR, 0, 3), + MUX_CFG(MUX_USBO, USBO_src, RCC_USBCKSELR, 4, 1), + MUX_CFG(MUX_USBPHY, USBPHY_src, RCC_USBCKSELR, 0, 2), +}; + +/* + * GATE CONFIG + */ + +enum enum_gate_cfg { + GATE_ZERO, /* reserved for no gate */ + GATE_LSE, + GATE_RTCCK, + GATE_LSI, + GATE_HSI, + GATE_CSI, + GATE_HSE, + GATE_LSI_RDY, + GATE_CSI_RDY, + GATE_LSE_RDY, + GATE_HSE_RDY, + GATE_HSI_RDY, + GATE_MCO1, + GATE_MCO2, + GATE_DBGCK, + GATE_TRACECK, + GATE_PLL1, + GATE_PLL1_DIVP, + GATE_PLL1_DIVQ, + GATE_PLL1_DIVR, + GATE_PLL2, + GATE_PLL2_DIVP, + GATE_PLL2_DIVQ, + GATE_PLL2_DIVR, + GATE_PLL3, + GATE_PLL3_DIVP, + GATE_PLL3_DIVQ, + GATE_PLL3_DIVR, + GATE_PLL4, + GATE_PLL4_DIVP, + GATE_PLL4_DIVQ, + GATE_PLL4_DIVR, + GATE_DDRC1, + GATE_DDRC1LP, + GATE_DDRPHYC, + GATE_DDRPHYCLP, + GATE_DDRCAPB, + GATE_DDRCAPBLP, + GATE_AXIDCG, + GATE_DDRPHYCAPB, + GATE_DDRPHYCAPBLP, + GATE_TIM2, + GATE_TIM3, + GATE_TIM4, + GATE_TIM5, + GATE_TIM6, + GATE_TIM7, + GATE_LPTIM1, + GATE_SPI2, + GATE_SPI3, + GATE_USART3, + GATE_UART4, + GATE_UART5, + GATE_UART7, + GATE_UART8, + GATE_I2C1, + GATE_I2C2, + GATE_SPDIF, + GATE_TIM1, + GATE_TIM8, + GATE_SPI1, + GATE_USART6, + GATE_SAI1, + GATE_SAI2, + GATE_DFSDM, + GATE_ADFSDM, + GATE_FDCAN, + GATE_LPTIM2, + GATE_LPTIM3, + GATE_LPTIM4, + GATE_LPTIM5, + GATE_VREF, + GATE_DTS, + GATE_PMBCTRL, + GATE_HDP, + GATE_SYSCFG, + GATE_DCMIPP, + GATE_DDRPERFM, + GATE_IWDG2APB, + GATE_USBPHY, + GATE_STGENRO, + GATE_LTDC, + GATE_RTCAPB, + GATE_TZC, + GATE_ETZPC, + GATE_IWDG1APB, + GATE_BSEC, + GATE_STGENC, + GATE_USART1, + GATE_USART2, + GATE_SPI4, + GATE_SPI5, + GATE_I2C3, + GATE_I2C4, + GATE_I2C5, + GATE_TIM12, + GATE_TIM13, + GATE_TIM14, + GATE_TIM15, + GATE_TIM16, + GATE_TIM17, + GATE_DMA1, + GATE_DMA2, + GATE_DMAMUX1, + GATE_DMA3, + GATE_DMAMUX2, + GATE_ADC1, + GATE_ADC2, + GATE_USBO, + GATE_TSC, + GATE_GPIOA, + GATE_GPIOB, + GATE_GPIOC, + GATE_GPIOD, + GATE_GPIOE, + GATE_GPIOF, + GATE_GPIOG, + GATE_GPIOH, + GATE_GPIOI, + GATE_PKA, + GATE_SAES, + GATE_CRYP1, + GATE_HASH1, + GATE_RNG1, + GATE_BKPSRAM, + GATE_AXIMC, + GATE_MCE, + GATE_ETH1CK, + GATE_ETH1TX, + GATE_ETH1RX, + GATE_ETH1MAC, + GATE_FMC, + GATE_QSPI, + GATE_SDMMC1, + GATE_SDMMC2, + GATE_CRC1, + GATE_USBH, + GATE_ETH2CK, + GATE_ETH2TX, + GATE_ETH2RX, + GATE_ETH2MAC, + GATE_MDMA, + + LAST_GATE +}; + +#define GATE_CFG(id, _offset, _bit_idx, _offset_clr)[id] = {\ + .offset = (_offset),\ + .bit_idx = (_bit_idx),\ + .set_clr = (_offset_clr),\ +} + +static const struct gate_cfg gates_mp13[LAST_GATE] = { + GATE_CFG(GATE_LSE, RCC_BDCR, 0, 0), + GATE_CFG(GATE_RTCCK, RCC_BDCR, 20, 0), + GATE_CFG(GATE_LSI, RCC_RDLSICR, 0, 0), + GATE_CFG(GATE_HSI, RCC_OCENSETR, 0, 1), + GATE_CFG(GATE_CSI, RCC_OCENSETR, 4, 1), + GATE_CFG(GATE_HSE, RCC_OCENSETR, 8, 1), + GATE_CFG(GATE_LSI_RDY, RCC_RDLSICR, 1, 0), + GATE_CFG(GATE_CSI_RDY, RCC_OCRDYR, 4, 0), + GATE_CFG(GATE_LSE_RDY, RCC_BDCR, 2, 0), + GATE_CFG(GATE_HSE_RDY, RCC_OCRDYR, 8, 0), + GATE_CFG(GATE_HSI_RDY, RCC_OCRDYR, 0, 0), + GATE_CFG(GATE_MCO1, RCC_MCO1CFGR, 12, 0), + GATE_CFG(GATE_MCO2, RCC_MCO2CFGR, 12, 0), + GATE_CFG(GATE_DBGCK, RCC_DBGCFGR, 8, 0), + GATE_CFG(GATE_TRACECK, RCC_DBGCFGR, 9, 0), + GATE_CFG(GATE_PLL1, RCC_PLL1CR, 0, 0), + GATE_CFG(GATE_PLL1_DIVP, RCC_PLL1CR, 4, 0), + GATE_CFG(GATE_PLL1_DIVQ, RCC_PLL1CR, 5, 0), + GATE_CFG(GATE_PLL1_DIVR, RCC_PLL1CR, 6, 0), + GATE_CFG(GATE_PLL2, RCC_PLL2CR, 0, 0), + GATE_CFG(GATE_PLL2_DIVP, RCC_PLL2CR, 4, 0), + GATE_CFG(GATE_PLL2_DIVQ, RCC_PLL2CR, 5, 0), + GATE_CFG(GATE_PLL2_DIVR, RCC_PLL2CR, 6, 0), + GATE_CFG(GATE_PLL3, RCC_PLL3CR, 0, 0), + GATE_CFG(GATE_PLL3_DIVP, RCC_PLL3CR, 4, 0), + GATE_CFG(GATE_PLL3_DIVQ, RCC_PLL3CR, 5, 0), + GATE_CFG(GATE_PLL3_DIVR, RCC_PLL3CR, 6, 0), + GATE_CFG(GATE_PLL4, RCC_PLL4CR, 0, 0), + GATE_CFG(GATE_PLL4_DIVP, RCC_PLL4CR, 4, 0), + GATE_CFG(GATE_PLL4_DIVQ, RCC_PLL4CR, 5, 0), + GATE_CFG(GATE_PLL4_DIVR, RCC_PLL4CR, 6, 0), + GATE_CFG(GATE_DDRC1, RCC_DDRITFCR, 0, 0), + GATE_CFG(GATE_DDRC1LP, RCC_DDRITFCR, 1, 0), + GATE_CFG(GATE_DDRPHYC, RCC_DDRITFCR, 4, 0), + GATE_CFG(GATE_DDRPHYCLP, RCC_DDRITFCR, 5, 0), + GATE_CFG(GATE_DDRCAPB, RCC_DDRITFCR, 6, 0), + GATE_CFG(GATE_DDRCAPBLP, RCC_DDRITFCR, 7, 0), + GATE_CFG(GATE_AXIDCG, RCC_DDRITFCR, 8, 0), + GATE_CFG(GATE_DDRPHYCAPB, RCC_DDRITFCR, 9, 0), + GATE_CFG(GATE_DDRPHYCAPBLP, RCC_DDRITFCR, 10, 0), + GATE_CFG(GATE_TIM2, RCC_MP_APB1ENSETR, 0, 1), + GATE_CFG(GATE_TIM3, RCC_MP_APB1ENSETR, 1, 1), + GATE_CFG(GATE_TIM4, RCC_MP_APB1ENSETR, 2, 1), + GATE_CFG(GATE_TIM5, RCC_MP_APB1ENSETR, 3, 1), + GATE_CFG(GATE_TIM6, RCC_MP_APB1ENSETR, 4, 1), + GATE_CFG(GATE_TIM7, RCC_MP_APB1ENSETR, 5, 1), + GATE_CFG(GATE_LPTIM1, RCC_MP_APB1ENSETR, 9, 1), + GATE_CFG(GATE_SPI2, RCC_MP_APB1ENSETR, 11, 1), + GATE_CFG(GATE_SPI3, RCC_MP_APB1ENSETR, 12, 1), + GATE_CFG(GATE_USART3, RCC_MP_APB1ENSETR, 15, 1), + GATE_CFG(GATE_UART4, RCC_MP_APB1ENSETR, 16, 1), + GATE_CFG(GATE_UART5, RCC_MP_APB1ENSETR, 17, 1), + GATE_CFG(GATE_UART7, RCC_MP_APB1ENSETR, 18, 1), + GATE_CFG(GATE_UART8, RCC_MP_APB1ENSETR, 19, 1), + GATE_CFG(GATE_I2C1, RCC_MP_APB1ENSETR, 21, 1), + GATE_CFG(GATE_I2C2, RCC_MP_APB1ENSETR, 22, 1), + GATE_CFG(GATE_SPDIF, RCC_MP_APB1ENSETR, 26, 1), + GATE_CFG(GATE_TIM1, RCC_MP_APB2ENSETR, 0, 1), + GATE_CFG(GATE_TIM8, RCC_MP_APB2ENSETR, 1, 1), + GATE_CFG(GATE_SPI1, RCC_MP_APB2ENSETR, 8, 1), + GATE_CFG(GATE_USART6, RCC_MP_APB2ENSETR, 13, 1), + GATE_CFG(GATE_SAI1, RCC_MP_APB2ENSETR, 16, 1), + GATE_CFG(GATE_SAI2, RCC_MP_APB2ENSETR, 17, 1), + GATE_CFG(GATE_DFSDM, RCC_MP_APB2ENSETR, 20, 1), + GATE_CFG(GATE_ADFSDM, RCC_MP_APB2ENSETR, 21, 1), + GATE_CFG(GATE_FDCAN, RCC_MP_APB2ENSETR, 24, 1), + GATE_CFG(GATE_LPTIM2, RCC_MP_APB3ENSETR, 0, 1), + GATE_CFG(GATE_LPTIM3, RCC_MP_APB3ENSETR, 1, 1), + GATE_CFG(GATE_LPTIM4, RCC_MP_APB3ENSETR, 2, 1), + GATE_CFG(GATE_LPTIM5, RCC_MP_APB3ENSETR, 3, 1), + GATE_CFG(GATE_VREF, RCC_MP_APB3ENSETR, 13, 1), + GATE_CFG(GATE_DTS, RCC_MP_APB3ENSETR, 16, 1), + GATE_CFG(GATE_PMBCTRL, RCC_MP_APB3ENSETR, 17, 1), + GATE_CFG(GATE_HDP, RCC_MP_APB3ENSETR, 20, 1), + GATE_CFG(GATE_SYSCFG, RCC_MP_S_APB3ENSETR, 0, 1), + GATE_CFG(GATE_DCMIPP, RCC_MP_APB4ENSETR, 1, 1), + GATE_CFG(GATE_DDRPERFM, RCC_MP_APB4ENSETR, 8, 1), + GATE_CFG(GATE_IWDG2APB, RCC_MP_APB4ENSETR, 15, 1), + GATE_CFG(GATE_USBPHY, RCC_MP_APB4ENSETR, 16, 1), + GATE_CFG(GATE_STGENRO, RCC_MP_APB4ENSETR, 20, 1), + GATE_CFG(GATE_LTDC, RCC_MP_S_APB4ENSETR, 0, 1), + GATE_CFG(GATE_RTCAPB, RCC_MP_APB5ENSETR, 8, 1), + GATE_CFG(GATE_TZC, RCC_MP_APB5ENSETR, 11, 1), + GATE_CFG(GATE_ETZPC, RCC_MP_APB5ENSETR, 13, 1), + GATE_CFG(GATE_IWDG1APB, RCC_MP_APB5ENSETR, 15, 1), + GATE_CFG(GATE_BSEC, RCC_MP_APB5ENSETR, 16, 1), + GATE_CFG(GATE_STGENC, RCC_MP_APB5ENSETR, 20, 1), + GATE_CFG(GATE_USART1, RCC_MP_APB6ENSETR, 0, 1), + GATE_CFG(GATE_USART2, RCC_MP_APB6ENSETR, 1, 1), + GATE_CFG(GATE_SPI4, RCC_MP_APB6ENSETR, 2, 1), + GATE_CFG(GATE_SPI5, RCC_MP_APB6ENSETR, 3, 1), + GATE_CFG(GATE_I2C3, RCC_MP_APB6ENSETR, 4, 1), + GATE_CFG(GATE_I2C4, RCC_MP_APB6ENSETR, 5, 1), + GATE_CFG(GATE_I2C5, RCC_MP_APB6ENSETR, 6, 1), + GATE_CFG(GATE_TIM12, RCC_MP_APB6ENSETR, 7, 1), + GATE_CFG(GATE_TIM13, RCC_MP_APB6ENSETR, 8, 1), + GATE_CFG(GATE_TIM14, RCC_MP_APB6ENSETR, 9, 1), + GATE_CFG(GATE_TIM15, RCC_MP_APB6ENSETR, 10, 1), + GATE_CFG(GATE_TIM16, RCC_MP_APB6ENSETR, 11, 1), + GATE_CFG(GATE_TIM17, RCC_MP_APB6ENSETR, 12, 1), + GATE_CFG(GATE_DMA1, RCC_MP_AHB2ENSETR, 0, 1), + GATE_CFG(GATE_DMA2, RCC_MP_AHB2ENSETR, 1, 1), + GATE_CFG(GATE_DMAMUX1, RCC_MP_AHB2ENSETR, 2, 1), + GATE_CFG(GATE_DMA3, RCC_MP_AHB2ENSETR, 3, 1), + GATE_CFG(GATE_DMAMUX2, RCC_MP_AHB2ENSETR, 4, 1), + GATE_CFG(GATE_ADC1, RCC_MP_AHB2ENSETR, 5, 1), + GATE_CFG(GATE_ADC2, RCC_MP_AHB2ENSETR, 6, 1), + GATE_CFG(GATE_USBO, RCC_MP_AHB2ENSETR, 8, 1), + GATE_CFG(GATE_TSC, RCC_MP_AHB4ENSETR, 15, 1), + + GATE_CFG(GATE_GPIOA, RCC_MP_S_AHB4ENSETR, 0, 1), + GATE_CFG(GATE_GPIOB, RCC_MP_S_AHB4ENSETR, 1, 1), + GATE_CFG(GATE_GPIOC, RCC_MP_S_AHB4ENSETR, 2, 1), + GATE_CFG(GATE_GPIOD, RCC_MP_S_AHB4ENSETR, 3, 1), + GATE_CFG(GATE_GPIOE, RCC_MP_S_AHB4ENSETR, 4, 1), + GATE_CFG(GATE_GPIOF, RCC_MP_S_AHB4ENSETR, 5, 1), + GATE_CFG(GATE_GPIOG, RCC_MP_S_AHB4ENSETR, 6, 1), + GATE_CFG(GATE_GPIOH, RCC_MP_S_AHB4ENSETR, 7, 1), + GATE_CFG(GATE_GPIOI, RCC_MP_S_AHB4ENSETR, 8, 1), + + GATE_CFG(GATE_PKA, RCC_MP_AHB5ENSETR, 2, 1), + GATE_CFG(GATE_SAES, RCC_MP_AHB5ENSETR, 3, 1), + GATE_CFG(GATE_CRYP1, RCC_MP_AHB5ENSETR, 4, 1), + GATE_CFG(GATE_HASH1, RCC_MP_AHB5ENSETR, 5, 1), + GATE_CFG(GATE_RNG1, RCC_MP_AHB5ENSETR, 6, 1), + GATE_CFG(GATE_BKPSRAM, RCC_MP_AHB5ENSETR, 8, 1), + GATE_CFG(GATE_AXIMC, RCC_MP_AHB5ENSETR, 16, 1), + GATE_CFG(GATE_MCE, RCC_MP_AHB6ENSETR, 1, 1), + GATE_CFG(GATE_ETH1CK, RCC_MP_AHB6ENSETR, 7, 1), + GATE_CFG(GATE_ETH1TX, RCC_MP_AHB6ENSETR, 8, 1), + GATE_CFG(GATE_ETH1RX, RCC_MP_AHB6ENSETR, 9, 1), + GATE_CFG(GATE_ETH1MAC, RCC_MP_AHB6ENSETR, 10, 1), + GATE_CFG(GATE_FMC, RCC_MP_AHB6ENSETR, 12, 1), + GATE_CFG(GATE_QSPI, RCC_MP_AHB6ENSETR, 14, 1), + GATE_CFG(GATE_SDMMC1, RCC_MP_AHB6ENSETR, 16, 1), + GATE_CFG(GATE_SDMMC2, RCC_MP_AHB6ENSETR, 17, 1), + GATE_CFG(GATE_CRC1, RCC_MP_AHB6ENSETR, 20, 1), + GATE_CFG(GATE_USBH, RCC_MP_AHB6ENSETR, 24, 1), + GATE_CFG(GATE_ETH2CK, RCC_MP_AHB6ENSETR, 27, 1), + GATE_CFG(GATE_ETH2TX, RCC_MP_AHB6ENSETR, 28, 1), + GATE_CFG(GATE_ETH2RX, RCC_MP_AHB6ENSETR, 29, 1), + GATE_CFG(GATE_ETH2MAC, RCC_MP_AHB6ENSETR, 30, 1), + GATE_CFG(GATE_MDMA, RCC_MP_S_AHB6ENSETR, 0, 1), +}; + +/* + * DIV CONFIG + */ + +static const struct clk_div_table axi_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 }, + { 4, 4 }, { 5, 4 }, { 6, 4 }, { 7, 4 }, + { 0 }, +}; + +static const struct clk_div_table mlahb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 }, + { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 }, + { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 }, + { 0 }, +}; + +static const struct clk_div_table apb_div_table[] = { + { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 }, + { 4, 16 }, { 5, 16 }, { 6, 16 }, { 7, 16 }, + { 0 }, +}; + +#define DIV_CFG(id, _offset, _shift, _width, _flags, _table, _bitrdy)[id] = {\ + .offset = _offset,\ + .shift = _shift,\ + .width = _width,\ + .flags = _flags,\ + .table = _table,\ + .bitrdy = _bitrdy,\ +} + +static const struct div_cfg dividers_mp13[] = { + DIV_CFG(DIV_PLL1DIVP, RCC_PLL1CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVP, RCC_PLL2CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVQ, RCC_PLL2CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL2DIVR, RCC_PLL2CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVP, RCC_PLL3CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVQ, RCC_PLL3CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL3DIVR, RCC_PLL3CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVP, RCC_PLL4CFGR2, 0, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVQ, RCC_PLL4CFGR2, 8, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_PLL4DIVR, RCC_PLL4CFGR2, 16, 7, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MPU, RCC_MPCKDIVR, 0, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_AXI, RCC_AXIDIVR, 0, 3, 0, axi_div_table, 31), + DIV_CFG(DIV_MLAHB, RCC_MLAHBDIVR, 0, 4, 0, mlahb_div_table, 31), + DIV_CFG(DIV_APB1, RCC_APB1DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB2, RCC_APB2DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB3, RCC_APB3DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB4, RCC_APB4DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB5, RCC_APB5DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_APB6, RCC_APB6DIVR, 0, 3, 0, apb_div_table, 31), + DIV_CFG(DIV_RTC, RCC_RTCDIVR, 0, 6, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MCO1, RCC_MCO1CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_MCO2, RCC_MCO2CFGR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + + DIV_CFG(DIV_HSI, RCC_HSICFGR, 0, 2, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_TRACE, RCC_DBGCFGR, 0, 3, CLK_DIVIDER_POWER_OF_TWO, NULL, DIV_NO_BIT_RDY), + + DIV_CFG(DIV_ETH1PTP, RCC_ETH12CKSELR, 4, 4, 0, NULL, DIV_NO_BIT_RDY), + DIV_CFG(DIV_ETH2PTP, RCC_ETH12CKSELR, 12, 4, 0, NULL, DIV_NO_BIT_RDY), +}; + +#define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 + +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) + +#define PLLRDY_TIMEOUT TIMEOUT_US_200MS +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS +#define CLKDIV_TIMEOUT TIMEOUT_US_200MS +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +enum stm32_osc { + OSC_HSI, + OSC_HSE, + OSC_CSI, + OSC_LSI, + OSC_LSE, + OSC_I2SCKIN, + NB_OSCILLATOR +}; + +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_2000, + PLL_TYPE_NB +}; + +#define RCC_OFFSET_PLLXCR 0 +#define RCC_OFFSET_PLLXCFGR1 4 +#define RCC_OFFSET_PLLXCFGR2 8 +#define RCC_OFFSET_PLLXFRACR 12 +#define RCC_OFFSET_PLLXCSGR 16 + +struct stm32_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t clk_id; + uint16_t reg_pllxcr; +}; + +struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; +}; + +/* Define characteristic of PLL according type */ +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + }, + [PLL_2000] = { + .refclk_min = 8, + .refclk_max = 16, + }, +}; + +#if STM32MP_USB_PROGRAMMER +static bool pll4_bootrom; +#endif + +/* RCC clock device driver private */ +static unsigned int refcounts_mp13[CK_LAST]; + +static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx); + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER +static void clk_oscillator_check_bypass(struct stm32_clk_priv *priv, int idx, + bool digbyp, bool bypass) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, idx); + struct stm32_clk_bypass *bypass_data = osc_data->bypass; + uintptr_t address; + + if (bypass_data == NULL) { + return; + } + + address = priv->base + bypass_data->offset; + if ((mmio_read_32(address) & RCC_OCENR_HSEBYP) && + (!(digbyp || bypass))) { + panic(); + } +} +#endif + +static void stm32_enable_oscillator_hse(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_HSE]; + bool digbyp = osci->digbyp; + bool bypass = osci->bypass; + bool css = osci->css; + + if (_clk_stm32_get_rate(priv, _CK_HSE) == 0U) { + return; + } + + clk_oscillator_set_bypass(priv, _CK_HSE, digbyp, bypass); + + _clk_stm32_enable(priv, _CK_HSE); + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + clk_oscillator_check_bypass(priv, _CK_HSE, digbyp, bypass); +#endif + + clk_oscillator_set_css(priv, _CK_HSE, css); +} + +static void stm32_enable_oscillator_lse(struct stm32_clk_priv *priv) +{ + struct clk_oscillator_data *osc_data = clk_oscillator_get_data(priv, _CK_LSE); + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + bool digbyp = osci->digbyp; + bool bypass = osci->bypass; + uint8_t drive = osci->drive; + + if (_clk_stm32_get_rate(priv, _CK_LSE) == 0U) { + return; + } + + clk_oscillator_set_bypass(priv, _CK_LSE, digbyp, bypass); + + clk_oscillator_set_drive(priv, _CK_LSE, drive); + + _clk_stm32_gate_enable(priv, osc_data->gate_id); +} + +static int stm32mp1_set_hsidiv(uint8_t hsidiv) +{ + uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t address = rcc_base + RCC_OCRDYR; + + mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, + RCC_HSICFGR_HSIDIV_MASK, + RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); + + timeout = timeout_init_us(HSIDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", + address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_hsidiv(unsigned long hsifreq) +{ + uint8_t hsidiv; + uint32_t hsidivfreq = MAX_HSI_HZ; + + for (hsidiv = 0; hsidiv < 4U; hsidiv++) { + if (hsidivfreq == hsifreq) { + break; + } + + hsidivfreq /= 2U; + } + + if (hsidiv == 4U) { + ERROR("Invalid clk-hsi frequency\n"); + return -EINVAL; + } + + if (hsidiv != 0U) { + return stm32mp1_set_hsidiv(hsidiv); + } + + return 0; +} + +static int stm32_clk_oscillators_lse_set_css(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + struct stm32_osci_dt_cfg *osci = &pdata->osci[OSC_LSE]; + + clk_oscillator_set_css(priv, _CK_LSE, osci->css); + + return 0; +} + +static int stm32mp1_come_back_to_hsi(void) +{ + int ret; + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + + /* Come back to HSI */ + ret = _clk_stm32_set_parent(priv, _CKMPU, _CK_HSI); + if (ret != 0) { + return ret; + } + + ret = _clk_stm32_set_parent(priv, _CKAXI, _CK_HSI); + if (ret != 0) { + return ret; + } + + ret = _clk_stm32_set_parent(priv, _CKMLAHB, _CK_HSI); + if (ret != 0) { + return ret; + } + + return 0; +} + +static int stm32_clk_configure_clk_get_binding_id(struct stm32_clk_priv *priv, uint32_t data) +{ + unsigned long binding_id = ((unsigned long)data & CLK_ID_MASK) >> CLK_ID_SHIFT; + + return clk_get_index(priv, binding_id); +} + +static int stm32_clk_configure_clk(struct stm32_clk_priv *priv, uint32_t data) +{ + int sel = (data & CLK_SEL_MASK) >> CLK_SEL_SHIFT; + int enable = (data & CLK_ON_MASK) >> CLK_ON_SHIFT; + int clk_id; + int ret; + + clk_id = stm32_clk_configure_clk_get_binding_id(priv, data); + if (clk_id < 0) { + return clk_id; + } + + ret = _clk_stm32_set_parent_by_index(priv, clk_id, sel); + if (ret != 0) { + return ret; + } + + if (enable) { + clk_stm32_enable_call_ops(priv, clk_id); + } else { + clk_stm32_disable_call_ops(priv, clk_id); + } + + return 0; +} + +static int stm32_clk_configure_mux(struct stm32_clk_priv *priv, uint32_t data) +{ + int mux = (data & MUX_ID_MASK) >> MUX_ID_SHIFT; + int sel = (data & MUX_SEL_MASK) >> MUX_SEL_SHIFT; + + return clk_mux_set_parent(priv, mux, sel); +} + +static int stm32_clk_dividers_configure(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + uint32_t i; + + for (i = 0; i < pdata->nclkdiv; i++) { + int div_id, div_n; + int val; + int ret; + + val = pdata->clkdiv[i] & CMD_DATA_MASK; + div_id = (val & DIV_ID_MASK) >> DIV_ID_SHIFT; + div_n = (val & DIV_DIVN_MASK) >> DIV_DIVN_SHIFT; + + ret = clk_stm32_set_div(priv, div_id, div_n); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static int stm32_clk_source_configure(struct stm32_clk_priv *priv) +{ + struct stm32_clk_platdata *pdata = priv->pdata; + bool ckper_disabled = false; + int clk_id; + int ret; + uint32_t i; + + for (i = 0; i < pdata->nclksrc; i++) { + uint32_t val = pdata->clksrc[i]; + uint32_t cmd, cmd_data; + + if (val == (uint32_t)CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + + if (val == (uint32_t)CLK_RTC_DISABLED) { + continue; + } + + cmd = (val & CMD_MASK) >> CMD_SHIFT; + cmd_data = val & ~CMD_MASK; + + switch (cmd) { + case CMD_MUX: + ret = stm32_clk_configure_mux(priv, cmd_data); + break; + + case CMD_CLK: + clk_id = stm32_clk_configure_clk_get_binding_id(priv, cmd_data); + + if (clk_id == _RTCCK) { + if ((_clk_stm32_is_enabled(priv, _RTCCK) == true)) { + continue; + } + } + + ret = stm32_clk_configure_clk(priv, cmd_data); + break; + default: + ret = -EINVAL; + break; + } + + if (ret != 0) { + return ret; + } + } + + /* + * CKPER is source for some peripheral clocks + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivate CKPER only after switching clock + */ + if (ckper_disabled) { + ret = stm32_clk_configure_mux(priv, CLK_CKPER_DISABLED & CMD_MASK); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static int stm32_clk_stgen_configure(struct stm32_clk_priv *priv, int id) +{ + unsigned long stgen_freq; + + stgen_freq = _clk_stm32_get_rate(priv, id); + + stm32mp_stgen_config(stgen_freq); + + return 0; +} + +#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ + [(_idx)] = {\ + .clk_id = (_clk_id),\ + .plltype = (_type),\ + .reg_pllxcr = (_reg),\ + } + +static int clk_stm32_pll_compute_cfgr1(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco, + uint32_t *value) +{ + uint32_t divm = vco->div_mn[PLL_CFG_M]; + uint32_t divn = vco->div_mn[PLL_CFG_N]; + unsigned long prate = 0UL; + unsigned long refclk = 0UL; + + prate = _clk_stm32_get_parent_rate(priv, pll->clk_id); + refclk = prate / (divm + 1U); + + if ((refclk < (stm32mp1_pll[pll->plltype].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[pll->plltype].refclk_max * 1000000U))) { + return -EINVAL; + } + + *value = 0; + + if ((pll->plltype == PLL_800) && (refclk >= 8000000U)) { + *value = 1U << RCC_PLLNCFGR1_IFRGE_SHIFT; + } + + *value |= (divn << RCC_PLLNCFGR1_DIVN_SHIFT) & RCC_PLLNCFGR1_DIVN_MASK; + *value |= (divm << RCC_PLLNCFGR1_DIVM_SHIFT) & RCC_PLLNCFGR1_DIVM_MASK; + + return 0; +} + +static uint32_t clk_stm32_pll_compute_cfgr2(struct stm32_pll_output *out) +{ + uint32_t value = 0; + + value |= (out->output[PLL_CFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & RCC_PLLNCFGR2_DIVP_MASK; + value |= (out->output[PLL_CFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & RCC_PLLNCFGR2_DIVQ_MASK; + value |= (out->output[PLL_CFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & RCC_PLLNCFGR2_DIVR_MASK; + + return value; +} + +static void clk_stm32_pll_config_vco(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + if (clk_stm32_pll_compute_cfgr1(priv, pll, vco, &value) != 0) { + ERROR("Invalid Vref clock !\n"); + panic(); + } + + /* Write N / M / IFREGE fields */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR1, value); + + /* Fractional configuration */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, 0); + + /* Frac must be enabled only once its configuration is loaded */ + mmio_write_32(pll_base + RCC_OFFSET_PLLXFRACR, vco->frac << RCC_PLLNFRACR_FRACV_SHIFT); + mmio_setbits_32(pll_base + RCC_OFFSET_PLLXFRACR, RCC_PLLNFRACR_FRACLE); +} + +static void clk_stm32_pll_config_csg(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll, + struct stm32_pll_vco *vco) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t mod_per = 0; + uint32_t inc_step = 0; + uint32_t sscg_mode = 0; + uint32_t value = 0; + + if (!vco->csg_enabled) { + return; + } + + mod_per = vco->csg[PLL_CSG_MOD_PER]; + inc_step = vco->csg[PLL_CSG_INC_STEP]; + sscg_mode = vco->csg[PLL_CSG_SSCG_MODE]; + + value |= (mod_per << RCC_PLLNCSGR_MOD_PER_SHIFT) & RCC_PLLNCSGR_MOD_PER_MASK; + value |= (inc_step << RCC_PLLNCSGR_INC_STEP_SHIFT) & RCC_PLLNCSGR_INC_STEP_MASK; + value |= (sscg_mode << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & RCC_PLLNCSGR_SSCG_MODE_MASK; + + mmio_write_32(pll_base + RCC_OFFSET_PLLXCSGR, value); + mmio_setbits_32(pll_base + RCC_OFFSET_PLLXCR, RCC_PLLNCR_SSCG_CTRL); +} + +static void clk_stm32_pll_config_out(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll, + struct stm32_pll_output *out) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t value = 0; + + value = clk_stm32_pll_compute_cfgr2(out); + + mmio_write_32(pll_base + RCC_OFFSET_PLLXCFGR2, value); +} + +static inline struct stm32_pll_dt_cfg *clk_stm32_pll_get_pdata(int pll_idx) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + struct stm32_clk_platdata *pdata = priv->pdata; + + return &pdata->pll[pll_idx]; +} + +static bool _clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + return ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLON) != 0U); +} + +static void _clk_stm32_pll_set_on(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + mmio_clrsetbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); +} + +static void _clk_stm32_pll_set_off(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + + /* Stop all output */ + mmio_clrbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + /* Stop PLL */ + mmio_clrbits_32(pll_base, RCC_PLLNCR_PLLON); +} + +static int _clk_stm32_pll_wait_ready_on(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%d clock start failed @ 0x%x: 0x%x\n", + pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); + return -EINVAL; + } + } + + return 0; +} + +static int _clk_stm32_pll_wait_ready_off(struct stm32_clk_priv *priv, + const struct stm32_clk_pll *pll) +{ + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pll_base) & RCC_PLLNCR_PLLRDY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%d clock stop failed @ 0x%x: 0x%x\n", + pll->clk_id, pll->reg_pllxcr, mmio_read_32(pll_base)); + return -EINVAL; + } + } + + return 0; +} + +static int _clk_stm32_pll_enable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + if (_clk_stm32_pll_is_enabled(priv, pll)) { + return 0; + } + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + _clk_stm32_pll_set_on(priv, pll); + + /* Wait PLL lock */ + return _clk_stm32_pll_wait_ready_on(priv, pll); +} + +static void _clk_stm32_pll_disable(struct stm32_clk_priv *priv, const struct stm32_clk_pll *pll) +{ + if (!_clk_stm32_pll_is_enabled(priv, pll)) { + return; + } + + /* Stop all outputs and the PLL */ + _clk_stm32_pll_set_off(priv, pll); + + /* Wait PLL stopped */ + _clk_stm32_pll_wait_ready_off(priv, pll); +} + +static int _clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx, + struct stm32_pll_dt_cfg *pll_conf) +{ + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_idx); + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + int ret = 0; + + /* Configure PLLs source */ + ret = stm32_clk_configure_mux(priv, pll_conf->vco.src); + if (ret) { + return ret; + } + +#if STM32MP_USB_PROGRAMMER + if ((pll_idx == _PLL4) && pll4_bootrom) { + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + + mmio_setbits_32(pll_base, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + return 0; + } +#endif + /* Stop the PLL before */ + _clk_stm32_pll_disable(priv, pll); + + clk_stm32_pll_config_vco(priv, pll, &pll_conf->vco); + clk_stm32_pll_config_out(priv, pll, &pll_conf->output); + clk_stm32_pll_config_csg(priv, pll, &pll_conf->vco); + + ret = _clk_stm32_pll_enable(priv, pll); + if (ret != 0) { + return ret; + } + + mmio_setbits_32(pll_base, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN); + + return 0; +} + +static int clk_stm32_pll_init(struct stm32_clk_priv *priv, int pll_idx) +{ + struct stm32_pll_dt_cfg *pll_conf = clk_stm32_pll_get_pdata(pll_idx); + + if (pll_conf->vco.status) { + return _clk_stm32_pll_init(priv, pll_idx, pll_conf); + } + + return 0; +} + +static int stm32_clk_pll_configure(struct stm32_clk_priv *priv) +{ + int err = 0; + + err = clk_stm32_pll_init(priv, _PLL1); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL2); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL3); + if (err) { + return err; + } + + err = clk_stm32_pll_init(priv, _PLL4); + if (err) { + return err; + } + + return 0; +} + +static int stm32_clk_oscillators_wait_lse_ready(struct stm32_clk_priv *priv) +{ + int ret = 0; + + if (_clk_stm32_get_rate(priv, _CK_LSE) != 0U) { + ret = clk_oscillator_wait_ready_on(priv, _CK_LSE); + } + + return ret; +} + +static void stm32_clk_oscillators_enable(struct stm32_clk_priv *priv) +{ + stm32_enable_oscillator_hse(priv); + stm32_enable_oscillator_lse(priv); + _clk_stm32_enable(priv, _CK_LSI); + _clk_stm32_enable(priv, _CK_CSI); +} + +static int stm32_clk_hsidiv_configure(struct stm32_clk_priv *priv) +{ + return stm32mp1_hsidiv(_clk_stm32_get_rate(priv, _CK_HSI)); +} + +#if STM32MP_USB_PROGRAMMER +static bool stm32mp1_clk_is_pll4_used_by_bootrom(struct stm32_clk_priv *priv, int usbphy_p) +{ + /* Don't initialize PLL4, when used by BOOTROM */ + if ((stm32mp_get_boot_itf_selected() == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && + (usbphy_p == _PLL4R)) { + return true; + } + + return false; +} + +static int stm32mp1_clk_check_usb_conflict(struct stm32_clk_priv *priv, int usbphy_p, int usbo_p) +{ + int _usbo_p; + int _usbphy_p; + + if (!pll4_bootrom) { + return 0; + } + + _usbo_p = _clk_stm32_get_parent(priv, _USBO_K); + _usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); + + if ((_usbo_p != usbo_p) || (_usbphy_p != usbphy_p)) { + return -FDT_ERR_BADVALUE; + } + + return 0; +} +#endif + +static struct clk_oscillator_data stm32mp13_osc_data[NB_OSCILLATOR] = { + OSCILLATOR(OSC_HSI, _CK_HSI, "clk-hsi", GATE_HSI, GATE_HSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSI, _CK_LSI, "clk-lsi", GATE_LSI, GATE_LSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_CSI, _CK_CSI, "clk-csi", GATE_CSI, GATE_CSI_RDY, + NULL, NULL, NULL), + + OSCILLATOR(OSC_LSE, _CK_LSE, "clk-lse", GATE_LSE, GATE_LSE_RDY, + BYPASS(RCC_BDCR, 1, 3), + CSS(RCC_BDCR, 8), + DRIVE(RCC_BDCR, 4, 2, 2)), + + OSCILLATOR(OSC_HSE, _CK_HSE, "clk-hse", GATE_HSE, GATE_HSE_RDY, + BYPASS(RCC_OCENSETR, 10, 7), + CSS(RCC_OCENSETR, 11), + NULL), + + OSCILLATOR(OSC_I2SCKIN, _I2SCKIN, "i2s_ckin", NO_GATE, NO_GATE, + NULL, NULL, NULL), +}; + +static const char *clk_stm32_get_oscillator_name(enum stm32_osc id) +{ + if (id < NB_OSCILLATOR) { + return stm32mp13_osc_data[id].name; + } + + return NULL; +} + +#define CLK_PLL_CFG(_idx, _clk_id, _type, _reg)\ + [(_idx)] = {\ + .clk_id = (_clk_id),\ + .plltype = (_type),\ + .reg_pllxcr = (_reg),\ + } + +static const struct stm32_clk_pll stm32_mp13_clk_pll[_PLL_NB] = { + CLK_PLL_CFG(_PLL1, _CK_PLL1, PLL_2000, RCC_PLL1CR), + CLK_PLL_CFG(_PLL2, _CK_PLL2, PLL_1600, RCC_PLL2CR), + CLK_PLL_CFG(_PLL3, _CK_PLL3, PLL_800, RCC_PLL3CR), + CLK_PLL_CFG(_PLL4, _CK_PLL4, PLL_800, RCC_PLL4CR), +}; + +static const struct stm32_clk_pll *clk_st32_pll_data(unsigned int idx) +{ + return &stm32_mp13_clk_pll[idx]; +} + +struct stm32_pll_cfg { + int pll_id; +}; + +static unsigned long clk_stm32_pll_recalc_rate(struct stm32_clk_priv *priv, int id, + unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + uintptr_t pll_base = priv->base + pll->reg_pllxcr; + uint32_t cfgr1, fracr, divm, divn; + unsigned long fvco; + + cfgr1 = mmio_read_32(pll_base + RCC_OFFSET_PLLXCFGR1); + fracr = mmio_read_32(pll_base + RCC_OFFSET_PLLXFRACR); + + divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + unsigned long long numerator, denominator; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = prate * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(prate * (divn + 1U) / (divm + 1U)); + } + + return fvco; +}; + +static bool clk_stm32_pll_is_enabled(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + return _clk_stm32_pll_is_enabled(priv, pll); +} + +static int clk_stm32_pll_enable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + return _clk_stm32_pll_enable(priv, pll); +} + +static void clk_stm32_pll_disable(struct stm32_clk_priv *priv, int id) +{ + const struct clk_stm32 *clk = _clk_get(priv, id); + struct stm32_pll_cfg *pll_cfg = clk->clock_cfg; + const struct stm32_clk_pll *pll = clk_st32_pll_data(pll_cfg->pll_id); + + _clk_stm32_pll_disable(priv, pll); +} + +static const struct stm32_clk_ops clk_stm32_pll_ops = { + .recalc_rate = clk_stm32_pll_recalc_rate, + .enable = clk_stm32_pll_enable, + .disable = clk_stm32_pll_disable, + .is_enabled = clk_stm32_pll_is_enabled, +}; + +#define CLK_PLL(idx, _idx, _parent, _gate, _pll_id, _flags)[idx] = {\ + .name = #idx,\ + .binding = _idx,\ + .parent = _parent,\ + .flags = (_flags),\ + .clock_cfg = &(struct stm32_pll_cfg) {\ + .pll_id = _pll_id,\ + },\ + .ops = &clk_stm32_pll_ops,\ +} + +struct clk_stm32_composite_cfg { + int gate_id; + int div_id; +}; + +static unsigned long clk_stm32_composite_recalc_rate(struct stm32_clk_priv *priv, + int idx, unsigned long prate) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_divider_recalc(priv, composite_cfg->div_id, prate); +}; + +static bool clk_stm32_composite_gate_is_enabled(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_gate_is_enabled(priv, composite_cfg->gate_id); +} + +static int clk_stm32_composite_gate_enable(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + return _clk_stm32_gate_enable(priv, composite_cfg->gate_id); +} + +static void clk_stm32_composite_gate_disable(struct stm32_clk_priv *priv, int idx) +{ + const struct clk_stm32 *clk = _clk_get(priv, idx); + struct clk_stm32_composite_cfg *composite_cfg = clk->clock_cfg; + + _clk_stm32_gate_disable(priv, composite_cfg->gate_id); +} + +static const struct stm32_clk_ops clk_stm32_composite_ops = { + .recalc_rate = clk_stm32_composite_recalc_rate, + .is_enabled = clk_stm32_composite_gate_is_enabled, + .enable = clk_stm32_composite_gate_enable, + .disable = clk_stm32_composite_gate_disable, +}; + +#define STM32_COMPOSITE(idx, _binding, _parent, _flags, _gate_id,\ + _div_id)[idx] = {\ + .name = #idx,\ + .binding = (_binding),\ + .parent = (_parent),\ + .flags = (_flags),\ + .clock_cfg = &(struct clk_stm32_composite_cfg) {\ + .gate_id = (_gate_id),\ + .div_id = (_div_id),\ + },\ + .ops = &clk_stm32_composite_ops,\ +} + +static const struct clk_stm32 stm32mp13_clk[CK_LAST] = { + /* ROOT CLOCKS */ + CLK_FIXED_RATE(_CK_OFF, _NO_ID, 0), + CLK_OSC(_CK_HSE, CK_HSE, CLK_IS_ROOT, OSC_HSE), + CLK_OSC(_CK_HSI, CK_HSI, CLK_IS_ROOT, OSC_HSI), + CLK_OSC(_CK_CSI, CK_CSI, CLK_IS_ROOT, OSC_CSI), + CLK_OSC(_CK_LSI, CK_LSI, CLK_IS_ROOT, OSC_LSI), + CLK_OSC(_CK_LSE, CK_LSE, CLK_IS_ROOT, OSC_LSE), + + CLK_OSC_FIXED(_I2SCKIN, _NO_ID, CLK_IS_ROOT, OSC_I2SCKIN), + + CLK_FIXED_RATE(_USB_PHY_48, _NO_ID, USB_PHY_48_MHZ), + + STM32_DIV(_HSE_DIV, _NO_ID, _CK_HSE, 0, DIV_RTC), + + FIXED_FACTOR(_HSE_DIV2, CK_HSE_DIV2, _CK_HSE, 1, 2), + FIXED_FACTOR(_CSI_DIV122, _NO_ID, _CK_CSI, 1, 122), + + CLK_PLL(_CK_PLL1, PLL1, MUX(MUX_PLL12), GATE_PLL1, _PLL1, 0), + CLK_PLL(_CK_PLL2, PLL2, MUX(MUX_PLL12), GATE_PLL2, _PLL2, 0), + CLK_PLL(_CK_PLL3, PLL3, MUX(MUX_PLL3), GATE_PLL3, _PLL3, 0), + CLK_PLL(_CK_PLL4, PLL4, MUX(MUX_PLL4), GATE_PLL4, _PLL4, 0), + + STM32_COMPOSITE(_PLL1P, PLL1_P, _CK_PLL1, CLK_IS_CRITICAL, GATE_PLL1_DIVP, DIV_PLL1DIVP), + STM32_DIV(_PLL1P_DIV, _NO_ID, _CK_PLL1, 0, DIV_MPU), + + STM32_COMPOSITE(_PLL2P, PLL2_P, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVP, DIV_PLL2DIVP), + STM32_COMPOSITE(_PLL2Q, PLL2_Q, _CK_PLL2, 0, GATE_PLL2_DIVQ, DIV_PLL2DIVQ), + STM32_COMPOSITE(_PLL2R, PLL2_R, _CK_PLL2, CLK_IS_CRITICAL, GATE_PLL2_DIVR, DIV_PLL2DIVR), + + STM32_COMPOSITE(_PLL3P, PLL3_P, _CK_PLL3, 0, GATE_PLL3_DIVP, DIV_PLL3DIVP), + STM32_COMPOSITE(_PLL3Q, PLL3_Q, _CK_PLL3, 0, GATE_PLL3_DIVQ, DIV_PLL3DIVQ), + STM32_COMPOSITE(_PLL3R, PLL3_R, _CK_PLL3, 0, GATE_PLL3_DIVR, DIV_PLL3DIVR), + + STM32_COMPOSITE(_PLL4P, PLL4_P, _CK_PLL4, 0, GATE_PLL4_DIVP, DIV_PLL4DIVP), + STM32_COMPOSITE(_PLL4Q, PLL4_Q, _CK_PLL4, 0, GATE_PLL4_DIVQ, DIV_PLL4DIVQ), + STM32_COMPOSITE(_PLL4R, PLL4_R, _CK_PLL4, 0, GATE_PLL4_DIVR, DIV_PLL4DIVR), + + STM32_MUX(_CKMPU, CK_MPU, MUX_MPU, 0), + STM32_DIV(_CKAXI, CK_AXI, MUX(MUX_AXI), 0, DIV_AXI), + STM32_DIV(_CKMLAHB, CK_MLAHB, MUX(MUX_MLAHB), CLK_IS_CRITICAL, DIV_MLAHB), + STM32_MUX(_CKPER, CK_PER, MUX(MUX_CKPER), 0), + + STM32_DIV(_PCLK1, PCLK1, _CKMLAHB, 0, DIV_APB1), + STM32_DIV(_PCLK2, PCLK2, _CKMLAHB, 0, DIV_APB2), + STM32_DIV(_PCLK3, PCLK3, _CKMLAHB, 0, DIV_APB3), + STM32_DIV(_PCLK4, PCLK4, _CKAXI, 0, DIV_APB4), + STM32_DIV(_PCLK5, PCLK5, _CKAXI, 0, DIV_APB5), + STM32_DIV(_PCLK6, PCLK6, _CKMLAHB, 0, DIV_APB6), + + CK_TIMER(_CKTIMG1, CK_TIMG1, _PCLK1, 0, RCC_APB1DIVR, RCC_TIMG1PRER), + CK_TIMER(_CKTIMG2, CK_TIMG2, _PCLK2, 0, RCC_APB2DIVR, RCC_TIMG2PRER), + CK_TIMER(_CKTIMG3, CK_TIMG3, _PCLK6, 0, RCC_APB6DIVR, RCC_TIMG3PRER), + + /* END ROOT CLOCKS */ + + STM32_GATE(_DDRC1, DDRC1, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1), + STM32_GATE(_DDRC1LP, DDRC1LP, _CKAXI, CLK_IS_CRITICAL, GATE_DDRC1LP), + STM32_GATE(_DDRPHYC, DDRPHYC, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYC), + STM32_GATE(_DDRPHYCLP, DDRPHYCLP, _PLL2R, CLK_IS_CRITICAL, GATE_DDRPHYCLP), + STM32_GATE(_DDRCAPB, DDRCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPB), + STM32_GATE(_DDRCAPBLP, DDRCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRCAPBLP), + STM32_GATE(_AXIDCG, AXIDCG, _CKAXI, CLK_IS_CRITICAL, GATE_AXIDCG), + STM32_GATE(_DDRPHYCAPB, DDRPHYCAPB, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPB), + STM32_GATE(_DDRPHYCAPBLP, DDRPHYCAPBLP, _PCLK4, CLK_IS_CRITICAL, GATE_DDRPHYCAPBLP), + + STM32_GATE(_SYSCFG, SYSCFG, _PCLK3, 0, GATE_SYSCFG), + STM32_GATE(_DDRPERFM, DDRPERFM, _PCLK4, 0, GATE_DDRPERFM), + STM32_GATE(_IWDG2APB, IWDG2, _PCLK4, 0, GATE_IWDG2APB), + STM32_GATE(_USBPHY_K, USBPHY_K, MUX(MUX_USBPHY), 0, GATE_USBPHY), + STM32_GATE(_USBO_K, USBO_K, MUX(MUX_USBO), 0, GATE_USBO), + + STM32_GATE(_RTCAPB, RTCAPB, _PCLK5, CLK_IS_CRITICAL, GATE_RTCAPB), + STM32_GATE(_TZC, TZC, _PCLK5, CLK_IS_CRITICAL, GATE_TZC), + STM32_GATE(_ETZPC, TZPC, _PCLK5, CLK_IS_CRITICAL, GATE_ETZPC), + STM32_GATE(_IWDG1APB, IWDG1, _PCLK5, 0, GATE_IWDG1APB), + STM32_GATE(_BSEC, BSEC, _PCLK5, CLK_IS_CRITICAL, GATE_BSEC), + STM32_GATE(_STGENC, STGEN_K, MUX(MUX_STGEN), CLK_IS_CRITICAL, GATE_STGENC), + + STM32_GATE(_USART1_K, USART1_K, MUX(MUX_UART1), 0, GATE_USART1), + STM32_GATE(_USART2_K, USART2_K, MUX(MUX_UART2), 0, GATE_USART2), + STM32_GATE(_I2C3_K, I2C3_K, MUX(MUX_I2C3), 0, GATE_I2C3), + STM32_GATE(_I2C4_K, I2C4_K, MUX(MUX_I2C4), 0, GATE_I2C4), + STM32_GATE(_I2C5_K, I2C5_K, MUX(MUX_I2C5), 0, GATE_I2C5), + STM32_GATE(_TIM12, TIM12_K, _CKTIMG3, 0, GATE_TIM12), + STM32_GATE(_TIM15, TIM15_K, _CKTIMG3, 0, GATE_TIM15), + + STM32_GATE(_RTCCK, RTC, MUX(MUX_RTC), 0, GATE_RTCCK), + + STM32_GATE(_GPIOA, GPIOA, _CKMLAHB, 0, GATE_GPIOA), + STM32_GATE(_GPIOB, GPIOB, _CKMLAHB, 0, GATE_GPIOB), + STM32_GATE(_GPIOC, GPIOC, _CKMLAHB, 0, GATE_GPIOC), + STM32_GATE(_GPIOD, GPIOD, _CKMLAHB, 0, GATE_GPIOD), + STM32_GATE(_GPIOE, GPIOE, _CKMLAHB, 0, GATE_GPIOE), + STM32_GATE(_GPIOF, GPIOF, _CKMLAHB, 0, GATE_GPIOF), + STM32_GATE(_GPIOG, GPIOG, _CKMLAHB, 0, GATE_GPIOG), + STM32_GATE(_GPIOH, GPIOH, _CKMLAHB, 0, GATE_GPIOH), + STM32_GATE(_GPIOI, GPIOI, _CKMLAHB, 0, GATE_GPIOI), + + STM32_GATE(_PKA, PKA, _CKAXI, 0, GATE_PKA), + STM32_GATE(_SAES_K, SAES_K, MUX(MUX_SAES), 0, GATE_SAES), + STM32_GATE(_CRYP1, CRYP1, _PCLK5, 0, GATE_CRYP1), + STM32_GATE(_HASH1, HASH1, _PCLK5, 0, GATE_HASH1), + + STM32_GATE(_RNG1_K, RNG1_K, MUX(MUX_RNG1), 0, GATE_RNG1), + STM32_GATE(_BKPSRAM, BKPSRAM, _PCLK5, CLK_IS_CRITICAL, GATE_BKPSRAM), + + STM32_GATE(_SDMMC1_K, SDMMC1_K, MUX(MUX_SDMMC1), 0, GATE_SDMMC1), + STM32_GATE(_SDMMC2_K, SDMMC2_K, MUX(MUX_SDMMC2), 0, GATE_SDMMC2), + STM32_GATE(_DBGCK, CK_DBG, _CKAXI, 0, GATE_DBGCK), + +/* TODO: CHECK CLOCK FOR BL2/BL32 AND IF ONLY FOR TEST OR NOT */ + STM32_GATE(_USART3_K, USART3_K, MUX(MUX_UART35), 0, GATE_USART3), + STM32_GATE(_UART4_K, UART4_K, MUX(MUX_UART4), 0, GATE_UART4), + STM32_GATE(_UART5_K, UART5_K, MUX(MUX_UART35), 0, GATE_UART5), + STM32_GATE(_UART7_K, UART7_K, MUX(MUX_UART78), 0, GATE_UART7), + STM32_GATE(_UART8_K, UART8_K, MUX(MUX_UART78), 0, GATE_UART8), + STM32_GATE(_USART6_K, USART6_K, MUX(MUX_UART6), 0, GATE_USART6), + STM32_GATE(_MCE, MCE, _CKAXI, CLK_IS_CRITICAL, GATE_MCE), + STM32_GATE(_FMC_K, FMC_K, MUX(MUX_FMC), 0, GATE_FMC), + STM32_GATE(_QSPI_K, QSPI_K, MUX(MUX_QSPI), 0, GATE_QSPI), + + STM32_COMPOSITE(_MCO1_K, CK_MCO1, MUX(MUX_MCO1), 0, GATE_MCO1, DIV_MCO1), + STM32_COMPOSITE(_MCO2_K, CK_MCO2, MUX(MUX_MCO2), 0, GATE_MCO2, DIV_MCO2), + STM32_COMPOSITE(_TRACECK, CK_TRACE, _CKAXI, 0, GATE_TRACECK, DIV_TRACE), + +#if defined(IMAGE_BL32) + STM32_GATE(_TIM2, TIM2_K, _CKTIMG1, 0, GATE_TIM2), + STM32_GATE(_TIM3, TIM3_K, _CKTIMG1, 0, GATE_TIM3), + STM32_GATE(_TIM4, TIM4_K, _CKTIMG1, 0, GATE_TIM4), + STM32_GATE(_TIM5, TIM5_K, _CKTIMG1, 0, GATE_TIM5), + STM32_GATE(_TIM6, TIM6_K, _CKTIMG1, 0, GATE_TIM6), + STM32_GATE(_TIM7, TIM7_K, _CKTIMG1, 0, GATE_TIM7), + STM32_GATE(_TIM13, TIM13_K, _CKTIMG3, 0, GATE_TIM13), + STM32_GATE(_TIM14, TIM14_K, _CKTIMG3, 0, GATE_TIM14), + STM32_GATE(_LPTIM1_K, LPTIM1_K, MUX(MUX_LPTIM1), 0, GATE_LPTIM1), + STM32_GATE(_SPI2_K, SPI2_K, MUX(MUX_SPI23), 0, GATE_SPI2), + STM32_GATE(_SPI3_K, SPI3_K, MUX(MUX_SPI23), 0, GATE_SPI3), + STM32_GATE(_SPDIF_K, SPDIF_K, MUX(MUX_SPDIF), 0, GATE_SPDIF), + STM32_GATE(_TIM1, TIM1_K, _CKTIMG2, 0, GATE_TIM1), + STM32_GATE(_TIM8, TIM8_K, _CKTIMG2, 0, GATE_TIM8), + STM32_GATE(_TIM16, TIM16_K, _CKTIMG3, 0, GATE_TIM16), + STM32_GATE(_TIM17, TIM17_K, _CKTIMG3, 0, GATE_TIM17), + STM32_GATE(_SPI1_K, SPI1_K, MUX(MUX_SPI1), 0, GATE_SPI1), + STM32_GATE(_SPI4_K, SPI4_K, MUX(MUX_SPI4), 0, GATE_SPI4), + STM32_GATE(_SPI5_K, SPI5_K, MUX(MUX_SPI5), 0, GATE_SPI5), + STM32_GATE(_SAI1_K, SAI1_K, MUX(MUX_SAI1), 0, GATE_SAI1), + STM32_GATE(_SAI2_K, SAI2_K, MUX(MUX_SAI2), 0, GATE_SAI2), + STM32_GATE(_DFSDM, DFSDM_K, MUX(MUX_SAI1), 0, GATE_DFSDM), + STM32_GATE(_FDCAN_K, FDCAN_K, MUX(MUX_FDCAN), 0, GATE_FDCAN), + STM32_GATE(_USBH, USBH, _CKAXI, 0, GATE_USBH), + STM32_GATE(_I2C1_K, I2C1_K, MUX(MUX_I2C12), 0, GATE_I2C1), + STM32_GATE(_I2C2_K, I2C2_K, MUX(MUX_I2C12), 0, GATE_I2C2), + STM32_GATE(_ADFSDM, ADFSDM_K, MUX(MUX_SAI1), 0, GATE_ADFSDM), + STM32_GATE(_LPTIM2_K, LPTIM2_K, MUX(MUX_LPTIM2), 0, GATE_LPTIM2), + STM32_GATE(_LPTIM3_K, LPTIM3_K, MUX(MUX_LPTIM3), 0, GATE_LPTIM3), + STM32_GATE(_LPTIM4_K, LPTIM4_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM4), + STM32_GATE(_LPTIM5_K, LPTIM5_K, MUX(MUX_LPTIM45), 0, GATE_LPTIM5), + STM32_GATE(_VREF, VREF, _PCLK3, 0, GATE_VREF), + STM32_GATE(_DTS, TMPSENS, _PCLK3, 0, GATE_DTS), + STM32_GATE(_PMBCTRL, PMBCTRL, _PCLK3, 0, GATE_HDP), + STM32_GATE(_HDP, HDP, _PCLK3, 0, GATE_PMBCTRL), + STM32_GATE(_STGENRO, STGENRO, _PCLK4, 0, GATE_DCMIPP), + STM32_GATE(_DCMIPP_K, DCMIPP_K, MUX(MUX_DCMIPP), 0, GATE_DCMIPP), + STM32_GATE(_DMAMUX1, DMAMUX1, _CKAXI, 0, GATE_DMAMUX1), + STM32_GATE(_DMAMUX2, DMAMUX2, _CKAXI, 0, GATE_DMAMUX2), + STM32_GATE(_DMA3, DMA3, _CKAXI, 0, GATE_DMAMUX2), + STM32_GATE(_ADC1_K, ADC1_K, MUX(MUX_ADC1), 0, GATE_ADC1), + STM32_GATE(_ADC2_K, ADC2_K, MUX(MUX_ADC2), 0, GATE_ADC2), + STM32_GATE(_TSC, TSC, _CKAXI, 0, GATE_TSC), + STM32_GATE(_AXIMC, AXIMC, _CKAXI, 0, GATE_AXIMC), + STM32_GATE(_CRC1, CRC1, _CKAXI, 0, GATE_ETH1TX), + STM32_GATE(_ETH1CK, ETH1CK_K, MUX(MUX_ETH1), 0, GATE_ETH1CK), + STM32_GATE(_ETH1TX, ETH1TX, _CKAXI, 0, GATE_ETH1TX), + STM32_GATE(_ETH1RX, ETH1RX, _CKAXI, 0, GATE_ETH1RX), + STM32_GATE(_ETH2CK, ETH2CK_K, MUX(MUX_ETH2), 0, GATE_ETH2CK), + STM32_GATE(_ETH2TX, ETH2TX, _CKAXI, 0, GATE_ETH2TX), + STM32_GATE(_ETH2RX, ETH2RX, _CKAXI, 0, GATE_ETH2RX), + STM32_GATE(_ETH2MAC, ETH2MAC, _CKAXI, 0, GATE_ETH2MAC), +#endif +}; + +static struct stm32_pll_dt_cfg mp13_pll[_PLL_NB]; + +static struct stm32_osci_dt_cfg mp13_osci[NB_OSCILLATOR]; + +static uint32_t mp13_clksrc[MUX_MAX]; + +static uint32_t mp13_clkdiv[DIV_MAX]; + +static struct stm32_clk_platdata stm32mp13_clock_pdata = { + .osci = mp13_osci, + .nosci = NB_OSCILLATOR, + .pll = mp13_pll, + .npll = _PLL_NB, + .clksrc = mp13_clksrc, + .nclksrc = MUX_MAX, + .clkdiv = mp13_clkdiv, + .nclkdiv = DIV_MAX, +}; + +static struct stm32_clk_priv stm32mp13_clock_data = { + .base = RCC_BASE, + .num = ARRAY_SIZE(stm32mp13_clk), + .clks = stm32mp13_clk, + .parents = parent_mp13, + .nb_parents = ARRAY_SIZE(parent_mp13), + .gates = gates_mp13, + .nb_gates = ARRAY_SIZE(gates_mp13), + .div = dividers_mp13, + .nb_div = ARRAY_SIZE(dividers_mp13), + .osci_data = stm32mp13_osc_data, + .nb_osci_data = ARRAY_SIZE(stm32mp13_osc_data), + .gate_refcounts = refcounts_mp13, + .pdata = &stm32mp13_clock_pdata, +}; + +static int stm32mp1_init_clock_tree(void) +{ + struct stm32_clk_priv *priv = clk_stm32_get_priv(); + int ret; + +#if STM32MP_USB_PROGRAMMER + int usbphy_p = _clk_stm32_get_parent(priv, _USBPHY_K); + int usbo_p = _clk_stm32_get_parent(priv, _USBO_K); + + /* Don't initialize PLL4, when used by BOOTROM */ + pll4_bootrom = stm32mp1_clk_is_pll4_used_by_bootrom(priv, usbphy_p); +#endif + + /* + * Switch ON oscillators found in device-tree. + * Note: HSI already ON after BootROM stage. + */ + stm32_clk_oscillators_enable(priv); + + /* Come back to HSI */ + ret = stm32mp1_come_back_to_hsi(); + if (ret != 0) { + return ret; + } + + ret = stm32_clk_hsidiv_configure(priv); + if (ret != 0) { + return ret; + } + + ret = stm32_clk_stgen_configure(priv, _STGENC); + if (ret != 0) { + panic(); + } + + ret = stm32_clk_dividers_configure(priv); + if (ret != 0) { + panic(); + } + + ret = stm32_clk_pll_configure(priv); + if (ret != 0) { + panic(); + } + + /* Wait LSE ready before to use it */ + ret = stm32_clk_oscillators_wait_lse_ready(priv); + if (ret != 0) { + panic(); + } + + /* Configure with expected clock source */ + ret = stm32_clk_source_configure(priv); + if (ret != 0) { + panic(); + } + + /* Configure LSE css after RTC source configuration */ + ret = stm32_clk_oscillators_lse_set_css(priv); + if (ret != 0) { + panic(); + } + +#if STM32MP_USB_PROGRAMMER + ret = stm32mp1_clk_check_usb_conflict(priv, usbphy_p, usbo_p); + if (ret != 0) { + return ret; + } +#endif + /* reconfigure STGEN with DT config */ + ret = stm32_clk_stgen_configure(priv, _STGENC); + if (ret != 0) { + panic(); + } + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + mmio_clrsetbits_32(priv->base + RCC_DDRITFCR, + RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} + +#define LSEDRV_MEDIUM_HIGH 2 + +static int clk_stm32_parse_oscillator_fdt(void *fdt, int node, const char *name, + struct stm32_osci_dt_cfg *osci) +{ + int subnode = 0; + + /* default value oscillator not found, freq=0 */ + osci->freq = 0; + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar = NULL; + const fdt32_t *cuint = NULL; + int ret = 0; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return ret; + } + + if (strncmp(cchar, name, (size_t)ret) || + fdt_get_status(subnode) == DT_DISABLED) { + continue; + } + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", &ret); + if (cuint == NULL) { + return ret; + } + + osci->freq = fdt32_to_cpu(*cuint); + + if (fdt_getprop(fdt, subnode, "st,bypass", NULL) != NULL) { + osci->bypass = true; + } + + if (fdt_getprop(fdt, subnode, "st,digbypass", NULL) != NULL) { + osci->digbyp = true; + } + + if (fdt_getprop(fdt, subnode, "st,css", NULL) != NULL) { + osci->css = true; + } + + osci->drive = fdt_read_uint32_default(fdt, subnode, "st,drive", LSEDRV_MEDIUM_HIGH); + + return 0; + } + + return 0; +} + +static int stm32_clk_parse_fdt_all_oscillator(void *fdt, struct stm32_clk_platdata *pdata) +{ + int fdt_err = 0; + uint32_t i = 0; + int node = 0; + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + for (i = 0; i < pdata->nosci; i++) { + const char *name = NULL; + + name = clk_stm32_get_oscillator_name((enum stm32_osc)i); + if (name == NULL) { + continue; + } + + fdt_err = clk_stm32_parse_oscillator_fdt(fdt, node, name, &pdata->osci[i]); + if (fdt_err < 0) { + panic(); + } + } + + return 0; +} + +#define RCC_PLL_NAME_SIZE 12 + +static int clk_stm32_load_vco_config(void *fdt, int subnode, struct stm32_pll_vco *vco) +{ + int err = 0; + + err = fdt_read_uint32_array(fdt, subnode, "divmn", (int)PLL_DIV_MN_NB, vco->div_mn); + if (err != 0) { + return err; + } + + err = fdt_read_uint32_array(fdt, subnode, "csg", (int)PLL_CSG_NB, vco->csg); + + vco->csg_enabled = (err == 0); + + if (err == -FDT_ERR_NOTFOUND) { + err = 0; + } + + if (err != 0) { + return err; + } + + vco->status = RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | RCC_PLLNCR_DIVREN | RCC_PLLNCR_PLLON; + + vco->frac = fdt_read_uint32_default(fdt, subnode, "frac", 0); + + vco->src = fdt_read_uint32_default(fdt, subnode, "src", UINT32_MAX); + + return 0; +} + +static int clk_stm32_load_output_config(void *fdt, int subnode, struct stm32_pll_output *output) +{ + int err = 0; + + err = fdt_read_uint32_array(fdt, subnode, "st,pll_div_pqr", (int)PLL_DIV_PQR_NB, + output->output); + if (err != 0) { + return err; + } + + return 0; +} + +static int clk_stm32_parse_pll_fdt(void *fdt, int subnode, struct stm32_pll_dt_cfg *pll) +{ + const fdt32_t *cuint = NULL; + int subnode_pll = 0; + int subnode_vco = 0; + int err = 0; + + cuint = fdt_getprop(fdt, subnode, "st,pll", NULL); + if (!cuint) { + return -FDT_ERR_NOTFOUND; + } + + subnode_pll = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_pll < 0) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, subnode_pll, "st,pll_vco", NULL); + if (!cuint) { + return -FDT_ERR_NOTFOUND; + } + + subnode_vco = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (subnode_vco < 0) { + return -FDT_ERR_NOTFOUND; + } + + err = clk_stm32_load_vco_config(fdt, subnode_vco, &pll->vco); + if (err != 0) { + return err; + } + + err = clk_stm32_load_output_config(fdt, subnode_pll, &pll->output); + if (err != 0) { + return err; + } + + return 0; +} + +static int stm32_clk_parse_fdt_all_pll(void *fdt, int node, struct stm32_clk_platdata *pdata) +{ + size_t i = 0U; + + for (i = _PLL1; i < pdata->npll; i++) { + struct stm32_pll_dt_cfg *pll = pdata->pll + i; + char name[RCC_PLL_NAME_SIZE]; + int subnode = 0; + int err = 0; + + snprintf(name, sizeof(name), "st,pll@%u", i); + + subnode = fdt_subnode_offset(fdt, node, name); + if (!fdt_check_node(subnode)) { + continue; + } + + err = clk_stm32_parse_pll_fdt(fdt, subnode, pll); + if (err != 0) { + panic(); + } + } + + return 0; +} + +static int stm32_clk_parse_fdt(struct stm32_clk_platdata *pdata) +{ + void *fdt = NULL; + int node; + uint32_t err; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + if (node < 0) { + panic(); + } + + err = stm32_clk_parse_fdt_all_oscillator(fdt, pdata); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_all_pll(fdt, node, pdata); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clkdiv", pdata->clkdiv, &pdata->nclkdiv); + if (err != 0) { + return err; + } + + err = stm32_clk_parse_fdt_by_name(fdt, node, "st,clksrc", pdata->clksrc, &pdata->nclksrc); + if (err != 0) { + return err; + } + + return 0; +} + +int stm32mp1_clk_init(void) +{ + return 0; +} + +int stm32mp1_clk_probe(void) +{ + uintptr_t base = RCC_BASE; + int ret; + + ret = stm32_clk_parse_fdt(&stm32mp13_clock_pdata); + if (ret != 0) { + return ret; + } + + ret = clk_stm32_init(&stm32mp13_clock_data, base); + if (ret != 0) { + return ret; + } + + ret = stm32mp1_init_clock_tree(); + if (ret != 0) { + return ret; + } + + clk_stm32_enable_critical_clocks(); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c b/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c new file mode 100644 index 0000000..534ee3b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c @@ -0,0 +1,2376 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define MAX_HSI_HZ 64000000 +#define USB_PHY_48_MHZ 48000000 + +#define TIMEOUT_US_200MS U(200000) +#define TIMEOUT_US_1S U(1000000) + +#define PLLRDY_TIMEOUT TIMEOUT_US_200MS +#define CLKSRC_TIMEOUT TIMEOUT_US_200MS +#define CLKDIV_TIMEOUT TIMEOUT_US_200MS +#define HSIDIV_TIMEOUT TIMEOUT_US_200MS +#define OSCRDY_TIMEOUT TIMEOUT_US_1S + +const char *stm32mp_osc_node_label[NB_OSC] = { + [_LSI] = "clk-lsi", + [_LSE] = "clk-lse", + [_HSI] = "clk-hsi", + [_HSE] = "clk-hse", + [_CSI] = "clk-csi", + [_I2S_CKIN] = "i2s_ckin", +}; + +enum stm32mp1_parent_id { +/* Oscillators are defined in enum stm32mp_osc_id */ + +/* Other parent source */ + _HSI_KER = NB_OSC, + _HSE_KER, + _HSE_KER_DIV2, + _HSE_RTC, + _CSI_KER, + _PLL1_P, + _PLL1_Q, + _PLL1_R, + _PLL2_P, + _PLL2_Q, + _PLL2_R, + _PLL3_P, + _PLL3_Q, + _PLL3_R, + _PLL4_P, + _PLL4_Q, + _PLL4_R, + _ACLK, + _PCLK1, + _PCLK2, + _PCLK3, + _PCLK4, + _PCLK5, + _HCLK6, + _HCLK2, + _CK_PER, + _CK_MPU, + _CK_MCU, + _USB_PHY_48, + _PARENT_NB, + _UNKNOWN_ID = 0xff, +}; + +/* Lists only the parent clock we are interested in */ +enum stm32mp1_parent_sel { + _I2C12_SEL, + _I2C35_SEL, + _STGEN_SEL, + _I2C46_SEL, + _SPI6_SEL, + _UART1_SEL, + _RNG1_SEL, + _UART6_SEL, + _UART24_SEL, + _UART35_SEL, + _UART78_SEL, + _SDMMC12_SEL, + _SDMMC3_SEL, + _QSPI_SEL, + _FMC_SEL, + _AXIS_SEL, + _MCUS_SEL, + _USBPHY_SEL, + _USBO_SEL, + _MPU_SEL, + _CKPER_SEL, + _RTC_SEL, + _PARENT_SEL_NB, + _UNKNOWN_SEL = 0xff, +}; + +/* State the parent clock ID straight related to a clock */ +static const uint8_t parent_id_clock_id[_PARENT_NB] = { + [_HSE] = CK_HSE, + [_HSI] = CK_HSI, + [_CSI] = CK_CSI, + [_LSE] = CK_LSE, + [_LSI] = CK_LSI, + [_I2S_CKIN] = _UNKNOWN_ID, + [_USB_PHY_48] = _UNKNOWN_ID, + [_HSI_KER] = CK_HSI, + [_HSE_KER] = CK_HSE, + [_HSE_KER_DIV2] = CK_HSE_DIV2, + [_HSE_RTC] = _UNKNOWN_ID, + [_CSI_KER] = CK_CSI, + [_PLL1_P] = PLL1_P, + [_PLL1_Q] = PLL1_Q, + [_PLL1_R] = PLL1_R, + [_PLL2_P] = PLL2_P, + [_PLL2_Q] = PLL2_Q, + [_PLL2_R] = PLL2_R, + [_PLL3_P] = PLL3_P, + [_PLL3_Q] = PLL3_Q, + [_PLL3_R] = PLL3_R, + [_PLL4_P] = PLL4_P, + [_PLL4_Q] = PLL4_Q, + [_PLL4_R] = PLL4_R, + [_ACLK] = CK_AXI, + [_PCLK1] = CK_AXI, + [_PCLK2] = CK_AXI, + [_PCLK3] = CK_AXI, + [_PCLK4] = CK_AXI, + [_PCLK5] = CK_AXI, + [_CK_PER] = CK_PER, + [_CK_MPU] = CK_MPU, + [_CK_MCU] = CK_MCU, +}; + +static unsigned int clock_id2parent_id(unsigned long id) +{ + unsigned int n; + + for (n = 0U; n < ARRAY_SIZE(parent_id_clock_id); n++) { + if (parent_id_clock_id[n] == id) { + return n; + } + } + + return _UNKNOWN_ID; +} + +enum stm32mp1_pll_id { + _PLL1, + _PLL2, + _PLL3, + _PLL4, + _PLL_NB +}; + +enum stm32mp1_div_id { + _DIV_P, + _DIV_Q, + _DIV_R, + _DIV_NB, +}; + +enum stm32mp1_clksrc_id { + CLKSRC_MPU, + CLKSRC_AXI, + CLKSRC_MCU, + CLKSRC_PLL12, + CLKSRC_PLL3, + CLKSRC_PLL4, + CLKSRC_RTC, + CLKSRC_MCO1, + CLKSRC_MCO2, + CLKSRC_NB +}; + +enum stm32mp1_clkdiv_id { + CLKDIV_MPU, + CLKDIV_AXI, + CLKDIV_MCU, + CLKDIV_APB1, + CLKDIV_APB2, + CLKDIV_APB3, + CLKDIV_APB4, + CLKDIV_APB5, + CLKDIV_RTC, + CLKDIV_MCO1, + CLKDIV_MCO2, + CLKDIV_NB +}; + +enum stm32mp1_pllcfg { + PLLCFG_M, + PLLCFG_N, + PLLCFG_P, + PLLCFG_Q, + PLLCFG_R, + PLLCFG_O, + PLLCFG_NB +}; + +enum stm32mp1_pllcsg { + PLLCSG_MOD_PER, + PLLCSG_INC_STEP, + PLLCSG_SSCG_MODE, + PLLCSG_NB +}; + +enum stm32mp1_plltype { + PLL_800, + PLL_1600, + PLL_TYPE_NB +}; + +struct stm32mp1_pll { + uint8_t refclk_min; + uint8_t refclk_max; + uint8_t divn_max; +}; + +struct stm32mp1_clk_gate { + uint16_t offset; + uint8_t bit; + uint8_t index; + uint8_t set_clr; + uint8_t secure; + uint8_t sel; /* Relates to enum stm32mp1_parent_sel */ + uint8_t fixed; /* Relates to enum stm32mp1_parent_id */ +}; + +struct stm32mp1_clk_sel { + uint16_t offset; + uint8_t src; + uint8_t msk; + uint8_t nb_parent; + const uint8_t *parent; +}; + +#define REFCLK_SIZE 4 +struct stm32mp1_clk_pll { + enum stm32mp1_plltype plltype; + uint16_t rckxselr; + uint16_t pllxcfgr1; + uint16_t pllxcfgr2; + uint16_t pllxfracr; + uint16_t pllxcr; + uint16_t pllxcsgr; + enum stm32mp_osc_id refclk[REFCLK_SIZE]; +}; + +/* Clocks with selectable source and non set/clr register access */ +#define _CLK_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ + .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and non set/clr register access */ +#define _CLK_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 0, \ + .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } + +/* Clocks with selectable source and set/clr register access */ +#define _CLK_SC_SELEC(sec, off, b, idx, s) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ + .secure = (sec), \ + .sel = (s), \ + .fixed = _UNKNOWN_ID, \ + } + +/* Clocks with fixed source and set/clr register access */ +#define _CLK_SC_FIXED(sec, off, b, idx, f) \ + { \ + .offset = (off), \ + .bit = (b), \ + .index = (idx), \ + .set_clr = 1, \ + .secure = (sec), \ + .sel = _UNKNOWN_SEL, \ + .fixed = (f), \ + } + +#define _CLK_PARENT_SEL(_label, _rcc_selr, _parents) \ + [_ ## _label ## _SEL] = { \ + .offset = _rcc_selr, \ + .src = _rcc_selr ## _ ## _label ## SRC_SHIFT, \ + .msk = (_rcc_selr ## _ ## _label ## SRC_MASK) >> \ + (_rcc_selr ## _ ## _label ## SRC_SHIFT), \ + .parent = (_parents), \ + .nb_parent = ARRAY_SIZE(_parents) \ + } + +#define _CLK_PLL(idx, type, off1, off2, off3, \ + off4, off5, off6, \ + p1, p2, p3, p4) \ + [(idx)] = { \ + .plltype = (type), \ + .rckxselr = (off1), \ + .pllxcfgr1 = (off2), \ + .pllxcfgr2 = (off3), \ + .pllxfracr = (off4), \ + .pllxcr = (off5), \ + .pllxcsgr = (off6), \ + .refclk[0] = (p1), \ + .refclk[1] = (p2), \ + .refclk[2] = (p3), \ + .refclk[3] = (p4), \ + } + +#define NB_GATES ARRAY_SIZE(stm32mp1_clk_gate) + +#define SEC 1 +#define N_S 0 + +static const struct stm32mp1_clk_gate stm32mp1_clk_gate[] = { + _CLK_FIXED(SEC, RCC_DDRITFCR, 0, DDRC1, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 1, DDRC1LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 2, DDRC2, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 3, DDRC2LP, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 4, DDRPHYC, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 5, DDRPHYCLP, _PLL2_R), + _CLK_FIXED(SEC, RCC_DDRITFCR, 6, DDRCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 7, DDRCAPBLP, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 8, AXIDCG, _ACLK), + _CLK_FIXED(SEC, RCC_DDRITFCR, 9, DDRPHYCAPB, _PCLK4), + _CLK_FIXED(SEC, RCC_DDRITFCR, 10, DDRPHYCAPBLP, _PCLK4), + +#if defined(IMAGE_BL32) + _CLK_SC_FIXED(N_S, RCC_MP_APB1ENSETR, 6, TIM12_K, _PCLK1), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 14, USART2_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 15, USART3_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 16, UART4_K, _UART24_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 17, UART5_K, _UART35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 18, UART7_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 19, UART8_K, _UART78_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 21, I2C1_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 22, I2C2_K, _I2C12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 23, I2C3_K, _I2C35_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB1ENSETR, 24, I2C5_K, _I2C35_SEL), + +#if defined(IMAGE_BL32) + _CLK_SC_FIXED(N_S, RCC_MP_APB2ENSETR, 2, TIM15_K, _PCLK2), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_APB2ENSETR, 13, USART6_K, _UART6_SEL), + + _CLK_SC_FIXED(N_S, RCC_MP_APB3ENSETR, 11, SYSCFG, _UNKNOWN_ID), + + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 8, DDRPERFM, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 15, IWDG2, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_APB4ENSETR, 16, USBPHY_K, _USBPHY_SEL), + + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 0, SPI6_K, _SPI6_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 2, I2C4_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 3, I2C6_K, _I2C46_SEL), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 4, USART1_K, _UART1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 8, RTCAPB, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 11, TZC1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 12, TZC2, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 13, TZPC, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 15, IWDG1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_APB5ENSETR, 16, BSEC, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_APB5ENSETR, 20, STGEN_K, _STGEN_SEL), + +#if defined(IMAGE_BL32) + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 8, USBO_K, _USBO_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB2ENSETR, 16, SDMMC3_K, _SDMMC3_SEL), +#endif + + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 0, GPIOA, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 1, GPIOB, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 2, GPIOC, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 3, GPIOD, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 4, GPIOE, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 5, GPIOF, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 6, GPIOG, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 7, GPIOH, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 8, GPIOI, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 9, GPIOJ, _UNKNOWN_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB4ENSETR, 10, GPIOK, _UNKNOWN_SEL), + + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 0, GPIOZ, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 4, CRYP1, _PCLK5), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 5, HASH1, _PCLK5), + _CLK_SC_SELEC(SEC, RCC_MP_AHB5ENSETR, 6, RNG1_K, _RNG1_SEL), + _CLK_SC_FIXED(SEC, RCC_MP_AHB5ENSETR, 8, BKPSRAM, _PCLK5), + +#if defined(IMAGE_BL2) + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 12, FMC_K, _FMC_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 14, QSPI_K, _QSPI_SEL), +#endif + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 16, SDMMC1_K, _SDMMC12_SEL), + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 17, SDMMC2_K, _SDMMC12_SEL), +#if defined(IMAGE_BL32) + _CLK_SC_SELEC(N_S, RCC_MP_AHB6ENSETR, 24, USBH, _UNKNOWN_SEL), +#endif + + _CLK_SELEC(SEC, RCC_BDCR, 20, RTC, _RTC_SEL), + _CLK_SELEC(N_S, RCC_DBGCFGR, 8, CK_DBG, _UNKNOWN_SEL), +}; + +static const uint8_t i2c12_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t i2c35_parents[] = { + _PCLK1, _PLL4_R, _HSI_KER, _CSI_KER +}; + +static const uint8_t stgen_parents[] = { + _HSI_KER, _HSE_KER +}; + +static const uint8_t i2c46_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER +}; + +static const uint8_t spi6_parents[] = { + _PCLK5, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER, _PLL3_Q +}; + +static const uint8_t usart1_parents[] = { + _PCLK5, _PLL3_Q, _HSI_KER, _CSI_KER, _PLL4_Q, _HSE_KER +}; + +static const uint8_t rng1_parents[] = { + _CSI, _PLL4_R, _LSE, _LSI +}; + +static const uint8_t uart6_parents[] = { + _PCLK2, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t uart234578_parents[] = { + _PCLK1, _PLL4_Q, _HSI_KER, _CSI_KER, _HSE_KER +}; + +static const uint8_t sdmmc12_parents[] = { + _HCLK6, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t sdmmc3_parents[] = { + _HCLK2, _PLL3_R, _PLL4_P, _HSI_KER +}; + +static const uint8_t qspi_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t fmc_parents[] = { + _ACLK, _PLL3_R, _PLL4_P, _CK_PER +}; + +static const uint8_t axiss_parents[] = { + _HSI, _HSE, _PLL2_P +}; + +static const uint8_t mcuss_parents[] = { + _HSI, _HSE, _CSI, _PLL3_P +}; + +static const uint8_t usbphy_parents[] = { + _HSE_KER, _PLL4_R, _HSE_KER_DIV2 +}; + +static const uint8_t usbo_parents[] = { + _PLL4_R, _USB_PHY_48 +}; + +static const uint8_t mpu_parents[] = { + _HSI, _HSE, _PLL1_P, _PLL1_P /* specific div */ +}; + +static const uint8_t per_parents[] = { + _HSI, _HSE, _CSI, +}; + +static const uint8_t rtc_parents[] = { + _UNKNOWN_ID, _LSE, _LSI, _HSE_RTC +}; + +static const struct stm32mp1_clk_sel stm32mp1_clk_sel[_PARENT_SEL_NB] = { + _CLK_PARENT_SEL(I2C12, RCC_I2C12CKSELR, i2c12_parents), + _CLK_PARENT_SEL(I2C35, RCC_I2C35CKSELR, i2c35_parents), + _CLK_PARENT_SEL(STGEN, RCC_STGENCKSELR, stgen_parents), + _CLK_PARENT_SEL(I2C46, RCC_I2C46CKSELR, i2c46_parents), + _CLK_PARENT_SEL(SPI6, RCC_SPI6CKSELR, spi6_parents), + _CLK_PARENT_SEL(UART1, RCC_UART1CKSELR, usart1_parents), + _CLK_PARENT_SEL(RNG1, RCC_RNG1CKSELR, rng1_parents), + _CLK_PARENT_SEL(MPU, RCC_MPCKSELR, mpu_parents), + _CLK_PARENT_SEL(CKPER, RCC_CPERCKSELR, per_parents), + _CLK_PARENT_SEL(RTC, RCC_BDCR, rtc_parents), + _CLK_PARENT_SEL(UART6, RCC_UART6CKSELR, uart6_parents), + _CLK_PARENT_SEL(UART24, RCC_UART24CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART35, RCC_UART35CKSELR, uart234578_parents), + _CLK_PARENT_SEL(UART78, RCC_UART78CKSELR, uart234578_parents), + _CLK_PARENT_SEL(SDMMC12, RCC_SDMMC12CKSELR, sdmmc12_parents), + _CLK_PARENT_SEL(SDMMC3, RCC_SDMMC3CKSELR, sdmmc3_parents), + _CLK_PARENT_SEL(QSPI, RCC_QSPICKSELR, qspi_parents), + _CLK_PARENT_SEL(FMC, RCC_FMCCKSELR, fmc_parents), + _CLK_PARENT_SEL(AXIS, RCC_ASSCKSELR, axiss_parents), + _CLK_PARENT_SEL(MCUS, RCC_MSSCKSELR, mcuss_parents), + _CLK_PARENT_SEL(USBPHY, RCC_USBCKSELR, usbphy_parents), + _CLK_PARENT_SEL(USBO, RCC_USBCKSELR, usbo_parents), +}; + +/* Define characteristic of PLL according type */ +#define DIVN_MIN 24 +static const struct stm32mp1_pll stm32mp1_pll[PLL_TYPE_NB] = { + [PLL_800] = { + .refclk_min = 4, + .refclk_max = 16, + .divn_max = 99, + }, + [PLL_1600] = { + .refclk_min = 8, + .refclk_max = 16, + .divn_max = 199, + }, +}; + +/* PLLNCFGR2 register divider by output */ +static const uint8_t pllncfgr2[_DIV_NB] = { + [_DIV_P] = RCC_PLLNCFGR2_DIVP_SHIFT, + [_DIV_Q] = RCC_PLLNCFGR2_DIVQ_SHIFT, + [_DIV_R] = RCC_PLLNCFGR2_DIVR_SHIFT, +}; + +static const struct stm32mp1_clk_pll stm32mp1_clk_pll[_PLL_NB] = { + _CLK_PLL(_PLL1, PLL_1600, + RCC_RCK12SELR, RCC_PLL1CFGR1, RCC_PLL1CFGR2, + RCC_PLL1FRACR, RCC_PLL1CR, RCC_PLL1CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL2, PLL_1600, + RCC_RCK12SELR, RCC_PLL2CFGR1, RCC_PLL2CFGR2, + RCC_PLL2FRACR, RCC_PLL2CR, RCC_PLL2CSGR, + _HSI, _HSE, _UNKNOWN_OSC_ID, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL3, PLL_800, + RCC_RCK3SELR, RCC_PLL3CFGR1, RCC_PLL3CFGR2, + RCC_PLL3FRACR, RCC_PLL3CR, RCC_PLL3CSGR, + _HSI, _HSE, _CSI, _UNKNOWN_OSC_ID), + _CLK_PLL(_PLL4, PLL_800, + RCC_RCK4SELR, RCC_PLL4CFGR1, RCC_PLL4CFGR2, + RCC_PLL4FRACR, RCC_PLL4CR, RCC_PLL4CSGR, + _HSI, _HSE, _CSI, _I2S_CKIN), +}; + +/* Prescaler table lookups for clock computation */ +/* div = /1 /2 /4 /8 / 16 /64 /128 /512 */ +static const uint8_t stm32mp1_mcu_div[16] = { + 0, 1, 2, 3, 4, 6, 7, 8, 9, 9, 9, 9, 9, 9, 9, 9 +}; + +/* div = /1 /2 /4 /8 /16 : same divider for PMU and APBX */ +#define stm32mp1_mpu_div stm32mp1_mpu_apbx_div +#define stm32mp1_apbx_div stm32mp1_mpu_apbx_div +static const uint8_t stm32mp1_mpu_apbx_div[8] = { + 0, 1, 2, 3, 4, 4, 4, 4 +}; + +/* div = /1 /2 /3 /4 */ +static const uint8_t stm32mp1_axi_div[8] = { + 1, 2, 3, 4, 4, 4, 4, 4 +}; + +static const char * const stm32mp1_clk_parent_name[_PARENT_NB] __unused = { + [_HSI] = "HSI", + [_HSE] = "HSE", + [_CSI] = "CSI", + [_LSI] = "LSI", + [_LSE] = "LSE", + [_I2S_CKIN] = "I2S_CKIN", + [_HSI_KER] = "HSI_KER", + [_HSE_KER] = "HSE_KER", + [_HSE_KER_DIV2] = "HSE_KER_DIV2", + [_HSE_RTC] = "HSE_RTC", + [_CSI_KER] = "CSI_KER", + [_PLL1_P] = "PLL1_P", + [_PLL1_Q] = "PLL1_Q", + [_PLL1_R] = "PLL1_R", + [_PLL2_P] = "PLL2_P", + [_PLL2_Q] = "PLL2_Q", + [_PLL2_R] = "PLL2_R", + [_PLL3_P] = "PLL3_P", + [_PLL3_Q] = "PLL3_Q", + [_PLL3_R] = "PLL3_R", + [_PLL4_P] = "PLL4_P", + [_PLL4_Q] = "PLL4_Q", + [_PLL4_R] = "PLL4_R", + [_ACLK] = "ACLK", + [_PCLK1] = "PCLK1", + [_PCLK2] = "PCLK2", + [_PCLK3] = "PCLK3", + [_PCLK4] = "PCLK4", + [_PCLK5] = "PCLK5", + [_HCLK6] = "KCLK6", + [_HCLK2] = "HCLK2", + [_CK_PER] = "CK_PER", + [_CK_MPU] = "CK_MPU", + [_CK_MCU] = "CK_MCU", + [_USB_PHY_48] = "USB_PHY_48", +}; + +/* RCC clock device driver private */ +static unsigned long stm32mp1_osc[NB_OSC]; +static struct spinlock reg_lock; +static unsigned int gate_refcounts[NB_GATES]; +static struct spinlock refcount_lock; + +static const struct stm32mp1_clk_gate *gate_ref(unsigned int idx) +{ + return &stm32mp1_clk_gate[idx]; +} + +#if defined(IMAGE_BL32) +static bool gate_is_non_secure(const struct stm32mp1_clk_gate *gate) +{ + return gate->secure == N_S; +} +#endif + +static const struct stm32mp1_clk_sel *clk_sel_ref(unsigned int idx) +{ + return &stm32mp1_clk_sel[idx]; +} + +static const struct stm32mp1_clk_pll *pll_ref(unsigned int idx) +{ + return &stm32mp1_clk_pll[idx]; +} + +static void stm32mp1_clk_lock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + /* Assume interrupts are masked */ + spin_lock(lock); + } +} + +static void stm32mp1_clk_unlock(struct spinlock *lock) +{ + if (stm32mp_lock_available()) { + spin_unlock(lock); + } +} + +bool stm32mp1_rcc_is_secure(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t mask = RCC_TZCR_TZEN; + + return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; +} + +bool stm32mp1_rcc_is_mckprot(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t mask = RCC_TZCR_TZEN | RCC_TZCR_MCKPROT; + + return (mmio_read_32(rcc_base + RCC_TZCR) & mask) == mask; +} + +void stm32mp1_clk_rcc_regs_lock(void) +{ + stm32mp1_clk_lock(®_lock); +} + +void stm32mp1_clk_rcc_regs_unlock(void) +{ + stm32mp1_clk_unlock(®_lock); +} + +static unsigned long stm32mp1_clk_get_fixed(enum stm32mp_osc_id idx) +{ + if (idx >= NB_OSC) { + return 0; + } + + return stm32mp1_osc[idx]; +} + +static int stm32mp1_clk_get_gated_id(unsigned long id) +{ + unsigned int i; + + for (i = 0U; i < NB_GATES; i++) { + if (gate_ref(i)->index == id) { + return i; + } + } + + ERROR("%s: clk id %lu not found\n", __func__, id); + + return -EINVAL; +} + +static enum stm32mp1_parent_sel stm32mp1_clk_get_sel(int i) +{ + return (enum stm32mp1_parent_sel)(gate_ref(i)->sel); +} + +static enum stm32mp1_parent_id stm32mp1_clk_get_fixed_parent(int i) +{ + return (enum stm32mp1_parent_id)(gate_ref(i)->fixed); +} + +static int stm32mp1_clk_get_parent(unsigned long id) +{ + const struct stm32mp1_clk_sel *sel; + uint32_t p_sel; + int i; + enum stm32mp1_parent_id p; + enum stm32mp1_parent_sel s; + uintptr_t rcc_base = stm32mp_rcc_base(); + + /* Few non gateable clock have a static parent ID, find them */ + i = (int)clock_id2parent_id(id); + if (i != _UNKNOWN_ID) { + return i; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + panic(); + } + + p = stm32mp1_clk_get_fixed_parent(i); + if (p < _PARENT_NB) { + return (int)p; + } + + s = stm32mp1_clk_get_sel(i); + if (s == _UNKNOWN_SEL) { + return -EINVAL; + } + if (s >= _PARENT_SEL_NB) { + panic(); + } + + sel = clk_sel_ref(s); + p_sel = (mmio_read_32(rcc_base + sel->offset) & + (sel->msk << sel->src)) >> sel->src; + if (p_sel < sel->nb_parent) { + return (int)sel->parent[p_sel]; + } + + return -EINVAL; +} + +static unsigned long stm32mp1_pll_get_fref(const struct stm32mp1_clk_pll *pll) +{ + uint32_t selr = mmio_read_32(stm32mp_rcc_base() + pll->rckxselr); + uint32_t src = selr & RCC_SELR_REFCLK_SRC_MASK; + + return stm32mp1_clk_get_fixed(pll->refclk[src]); +} + +/* + * pll_get_fvco() : return the VCO or (VCO / 2) frequency for the requested PLL + * - PLL1 & PLL2 => return VCO / 2 with Fpll_y_ck = FVCO / 2 * (DIVy + 1) + * - PLL3 & PLL4 => return VCO with Fpll_y_ck = FVCO / (DIVy + 1) + * => in all cases Fpll_y_ck = pll_get_fvco() / (DIVy + 1) + */ +static unsigned long stm32mp1_pll_get_fvco(const struct stm32mp1_clk_pll *pll) +{ + unsigned long refclk, fvco; + uint32_t cfgr1, fracr, divm, divn; + uintptr_t rcc_base = stm32mp_rcc_base(); + + cfgr1 = mmio_read_32(rcc_base + pll->pllxcfgr1); + fracr = mmio_read_32(rcc_base + pll->pllxfracr); + + divm = (cfgr1 & (RCC_PLLNCFGR1_DIVM_MASK)) >> RCC_PLLNCFGR1_DIVM_SHIFT; + divn = cfgr1 & RCC_PLLNCFGR1_DIVN_MASK; + + refclk = stm32mp1_pll_get_fref(pll); + + /* + * With FRACV : + * Fvco = Fck_ref * ((DIVN + 1) + FRACV / 2^13) / (DIVM + 1) + * Without FRACV + * Fvco = Fck_ref * ((DIVN + 1) / (DIVM + 1) + */ + if ((fracr & RCC_PLLNFRACR_FRACLE) != 0U) { + uint32_t fracv = (fracr & RCC_PLLNFRACR_FRACV_MASK) >> + RCC_PLLNFRACR_FRACV_SHIFT; + unsigned long long numerator, denominator; + + numerator = (((unsigned long long)divn + 1U) << 13) + fracv; + numerator = refclk * numerator; + denominator = ((unsigned long long)divm + 1U) << 13; + fvco = (unsigned long)(numerator / denominator); + } else { + fvco = (unsigned long)(refclk * (divn + 1U) / (divm + 1U)); + } + + return fvco; +} + +static unsigned long stm32mp1_read_pll_freq(enum stm32mp1_pll_id pll_id, + enum stm32mp1_div_id div_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + unsigned long dfout; + uint32_t cfgr2, divy; + + if (div_id >= _DIV_NB) { + return 0; + } + + cfgr2 = mmio_read_32(stm32mp_rcc_base() + pll->pllxcfgr2); + divy = (cfgr2 >> pllncfgr2[div_id]) & RCC_PLLNCFGR2_DIVX_MASK; + + dfout = stm32mp1_pll_get_fvco(pll) / (divy + 1U); + + return dfout; +} + +static unsigned long get_clock_rate(int p) +{ + uint32_t reg, clkdiv; + unsigned long clock = 0; + uintptr_t rcc_base = stm32mp_rcc_base(); + + switch (p) { + case _CK_MPU: + /* MPU sub system */ + reg = mmio_read_32(rcc_base + RCC_MPCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MPCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_MPCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_MPCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case RCC_MPCKSELR_PLL_MPUDIV: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + + reg = mmio_read_32(rcc_base + RCC_MPCKDIVR); + clkdiv = reg & RCC_MPUDIV_MASK; + clock >>= stm32mp1_mpu_div[clkdiv]; + break; + default: + break; + } + break; + /* AXI sub system */ + case _ACLK: + case _HCLK2: + case _HCLK6: + case _PCLK4: + case _PCLK5: + reg = mmio_read_32(rcc_base + RCC_ASSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_ASSCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_ASSCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_ASSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + default: + break; + } + + /* System clock divider */ + reg = mmio_read_32(rcc_base + RCC_AXIDIVR); + clock /= stm32mp1_axi_div[reg & RCC_AXIDIV_MASK]; + + switch (p) { + case _PCLK4: + reg = mmio_read_32(rcc_base + RCC_APB4DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK5: + reg = mmio_read_32(rcc_base + RCC_APB5DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + default: + break; + } + break; + /* MCU sub system */ + case _CK_MCU: + case _PCLK1: + case _PCLK2: + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_MSSCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_MSSCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_MSSCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_MSSCKSELR_CSI: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + case RCC_MSSCKSELR_PLL: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + default: + break; + } + + /* MCU clock divider */ + reg = mmio_read_32(rcc_base + RCC_MCUDIVR); + clock >>= stm32mp1_mcu_div[reg & RCC_MCUDIV_MASK]; + + switch (p) { + case _PCLK1: + reg = mmio_read_32(rcc_base + RCC_APB1DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK2: + reg = mmio_read_32(rcc_base + RCC_APB2DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _PCLK3: + reg = mmio_read_32(rcc_base + RCC_APB3DIVR); + clock >>= stm32mp1_apbx_div[reg & RCC_APBXDIV_MASK]; + break; + case _CK_MCU: + default: + break; + } + break; + case _CK_PER: + reg = mmio_read_32(rcc_base + RCC_CPERCKSELR); + switch (reg & RCC_SELR_SRC_MASK) { + case RCC_CPERCKSELR_HSI: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case RCC_CPERCKSELR_HSE: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case RCC_CPERCKSELR_CSI: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + default: + break; + } + break; + case _HSI: + case _HSI_KER: + clock = stm32mp1_clk_get_fixed(_HSI); + break; + case _CSI: + case _CSI_KER: + clock = stm32mp1_clk_get_fixed(_CSI); + break; + case _HSE: + case _HSE_KER: + clock = stm32mp1_clk_get_fixed(_HSE); + break; + case _HSE_KER_DIV2: + clock = stm32mp1_clk_get_fixed(_HSE) >> 1; + break; + case _HSE_RTC: + clock = stm32mp1_clk_get_fixed(_HSE); + clock /= (mmio_read_32(rcc_base + RCC_RTCDIVR) & RCC_DIVR_DIV_MASK) + 1U; + break; + case _LSI: + clock = stm32mp1_clk_get_fixed(_LSI); + break; + case _LSE: + clock = stm32mp1_clk_get_fixed(_LSE); + break; + /* PLL */ + case _PLL1_P: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_P); + break; + case _PLL1_Q: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_Q); + break; + case _PLL1_R: + clock = stm32mp1_read_pll_freq(_PLL1, _DIV_R); + break; + case _PLL2_P: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_P); + break; + case _PLL2_Q: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_Q); + break; + case _PLL2_R: + clock = stm32mp1_read_pll_freq(_PLL2, _DIV_R); + break; + case _PLL3_P: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_P); + break; + case _PLL3_Q: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_Q); + break; + case _PLL3_R: + clock = stm32mp1_read_pll_freq(_PLL3, _DIV_R); + break; + case _PLL4_P: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_P); + break; + case _PLL4_Q: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_Q); + break; + case _PLL4_R: + clock = stm32mp1_read_pll_freq(_PLL4, _DIV_R); + break; + /* Other */ + case _USB_PHY_48: + clock = USB_PHY_48_MHZ; + break; + default: + break; + } + + return clock; +} + +static void __clk_enable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + VERBOSE("Enable clock %u\n", gate->index); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset, BIT(gate->bit)); + } else { + mmio_setbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } +} + +static void __clk_disable(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + VERBOSE("Disable clock %u\n", gate->index); + + if (gate->set_clr != 0U) { + mmio_write_32(rcc_base + gate->offset + RCC_MP_ENCLRR_OFFSET, + BIT(gate->bit)); + } else { + mmio_clrbits_32(rcc_base + gate->offset, BIT(gate->bit)); + } +} + +static bool __clk_is_enabled(struct stm32mp1_clk_gate const *gate) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + return mmio_read_32(rcc_base + gate->offset) & BIT(gate->bit); +} + +/* Oscillators and PLLs are not gated at runtime */ +static bool clock_is_always_on(unsigned long id) +{ + switch (id) { + case CK_HSE: + case CK_CSI: + case CK_LSI: + case CK_LSE: + case CK_HSI: + case CK_HSE_DIV2: + 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 CK_AXI: + case CK_MPU: + case CK_MCU: + case RTC: + return true; + default: + return false; + } +} + +static void __stm32mp1_clk_enable(unsigned long id, bool with_refcnt) +{ + const struct stm32mp1_clk_gate *gate; + int i; + + if (clock_is_always_on(id)) { + return; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %lu can't be enabled\n", id); + panic(); + } + + gate = gate_ref(i); + + if (!with_refcnt) { + __clk_enable(gate); + return; + } + +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Enable non-secure clock w/o any refcounting */ + __clk_enable(gate); + return; + } +#endif + + stm32mp1_clk_lock(&refcount_lock); + + if (gate_refcounts[i] == 0U) { + __clk_enable(gate); + } + + gate_refcounts[i]++; + if (gate_refcounts[i] == UINT_MAX) { + ERROR("Clock %lu refcount reached max value\n", id); + panic(); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +static void __stm32mp1_clk_disable(unsigned long id, bool with_refcnt) +{ + const struct stm32mp1_clk_gate *gate; + int i; + + if (clock_is_always_on(id)) { + return; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + ERROR("Clock %lu can't be disabled\n", id); + panic(); + } + + gate = gate_ref(i); + + if (!with_refcnt) { + __clk_disable(gate); + return; + } + +#if defined(IMAGE_BL32) + if (gate_is_non_secure(gate)) { + /* Don't disable non-secure clocks */ + return; + } +#endif + + stm32mp1_clk_lock(&refcount_lock); + + if (gate_refcounts[i] == 0U) { + ERROR("Clock %lu refcount reached 0\n", id); + panic(); + } + gate_refcounts[i]--; + + if (gate_refcounts[i] == 0U) { + __clk_disable(gate); + } + + stm32mp1_clk_unlock(&refcount_lock); +} + +static int stm32mp_clk_enable(unsigned long id) +{ + __stm32mp1_clk_enable(id, true); + + return 0; +} + +static void stm32mp_clk_disable(unsigned long id) +{ + __stm32mp1_clk_disable(id, true); +} + +static bool stm32mp_clk_is_enabled(unsigned long id) +{ + int i; + + if (clock_is_always_on(id)) { + return true; + } + + i = stm32mp1_clk_get_gated_id(id); + if (i < 0) { + panic(); + } + + return __clk_is_enabled(gate_ref(i)); +} + +static unsigned long stm32mp_clk_get_rate(unsigned long id) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + int p = stm32mp1_clk_get_parent(id); + uint32_t prescaler, timpre; + unsigned long parent_rate; + + if (p < 0) { + return 0; + } + + parent_rate = get_clock_rate(p); + + switch (id) { + case TIM2_K: + case TIM3_K: + case TIM4_K: + case TIM5_K: + case TIM6_K: + case TIM7_K: + case TIM12_K: + case TIM13_K: + case TIM14_K: + prescaler = mmio_read_32(rcc_base + RCC_APB1DIVR) & + RCC_APBXDIV_MASK; + timpre = mmio_read_32(rcc_base + RCC_TIMG1PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + + case TIM1_K: + case TIM8_K: + case TIM15_K: + case TIM16_K: + case TIM17_K: + prescaler = mmio_read_32(rcc_base + RCC_APB2DIVR) & + RCC_APBXDIV_MASK; + timpre = mmio_read_32(rcc_base + RCC_TIMG2PRER) & + RCC_TIMGXPRER_TIMGXPRE; + break; + + default: + return parent_rate; + } + + if (prescaler == 0U) { + return parent_rate; + } + + return parent_rate * (timpre + 1U) * 2U; +} + +static void stm32mp1_ls_osc_set(bool enable, uint32_t offset, uint32_t mask_on) +{ + uintptr_t address = stm32mp_rcc_base() + offset; + + if (enable) { + mmio_setbits_32(address, mask_on); + } else { + mmio_clrbits_32(address, mask_on); + } +} + +static void stm32mp1_hs_ocs_set(bool enable, uint32_t mask_on) +{ + uint32_t offset = enable ? RCC_OCENSETR : RCC_OCENCLRR; + uintptr_t address = stm32mp_rcc_base() + offset; + + mmio_write_32(address, mask_on); +} + +static int stm32mp1_osc_wait(bool enable, uint32_t offset, uint32_t mask_rdy) +{ + uint64_t timeout; + uint32_t mask_test; + uintptr_t address = stm32mp_rcc_base() + offset; + + if (enable) { + mask_test = mask_rdy; + } else { + mask_test = 0; + } + + timeout = timeout_init_us(OSCRDY_TIMEOUT); + while ((mmio_read_32(address) & mask_rdy) != mask_test) { + if (timeout_elapsed(timeout)) { + ERROR("OSC %x @ %lx timeout for enable=%d : 0x%x\n", + mask_rdy, address, enable, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_lse_enable(bool bypass, bool digbyp, uint32_t lsedrv) +{ + uint32_t value; + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_DIGBYP); + } + + if (bypass || digbyp) { + mmio_setbits_32(rcc_base + RCC_BDCR, RCC_BDCR_LSEBYP); + } + + /* + * Warning: not recommended to switch directly from "high drive" + * to "medium low drive", and vice-versa. + */ + value = (mmio_read_32(rcc_base + RCC_BDCR) & RCC_BDCR_LSEDRV_MASK) >> + RCC_BDCR_LSEDRV_SHIFT; + + while (value != lsedrv) { + if (value > lsedrv) { + value--; + } else { + value++; + } + + mmio_clrsetbits_32(rcc_base + RCC_BDCR, + RCC_BDCR_LSEDRV_MASK, + value << RCC_BDCR_LSEDRV_SHIFT); + } + + stm32mp1_ls_osc_set(true, RCC_BDCR, RCC_BDCR_LSEON); +} + +static void stm32mp1_lse_wait(void) +{ + if (stm32mp1_osc_wait(true, RCC_BDCR, RCC_BDCR_LSERDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_lsi_set(bool enable) +{ + stm32mp1_ls_osc_set(enable, RCC_RDLSICR, RCC_RDLSICR_LSION); + + if (stm32mp1_osc_wait(enable, RCC_RDLSICR, RCC_RDLSICR_LSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_hse_enable(bool bypass, bool digbyp, bool css) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + + if (digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_DIGBYP); + } + + if (bypass || digbyp) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSEBYP); + } + + stm32mp1_hs_ocs_set(true, RCC_OCENR_HSEON); + if (stm32mp1_osc_wait(true, RCC_OCRDYR, RCC_OCRDYR_HSERDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } + + if (css) { + mmio_write_32(rcc_base + RCC_OCENSETR, RCC_OCENR_HSECSSON); + } + +#if STM32MP_UART_PROGRAMMER || STM32MP_USB_PROGRAMMER + if ((mmio_read_32(rcc_base + RCC_OCENSETR) & RCC_OCENR_HSEBYP) && + (!(digbyp || bypass))) { + panic(); + } +#endif +} + +static void stm32mp1_csi_set(bool enable) +{ + stm32mp1_hs_ocs_set(enable, RCC_OCENR_CSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_CSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static void stm32mp1_hsi_set(bool enable) +{ + stm32mp1_hs_ocs_set(enable, RCC_OCENR_HSION); + if (stm32mp1_osc_wait(enable, RCC_OCRDYR, RCC_OCRDYR_HSIRDY) != 0) { + VERBOSE("%s: failed\n", __func__); + } +} + +static int stm32mp1_set_hsidiv(uint8_t hsidiv) +{ + uint64_t timeout; + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t address = rcc_base + RCC_OCRDYR; + + mmio_clrsetbits_32(rcc_base + RCC_HSICFGR, + RCC_HSICFGR_HSIDIV_MASK, + RCC_HSICFGR_HSIDIV_MASK & (uint32_t)hsidiv); + + timeout = timeout_init_us(HSIDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_OCRDYR_HSIDIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("HSIDIV failed @ 0x%lx: 0x%x\n", + address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_hsidiv(unsigned long hsifreq) +{ + uint8_t hsidiv; + uint32_t hsidivfreq = MAX_HSI_HZ; + + for (hsidiv = 0; hsidiv < 4U; hsidiv++) { + if (hsidivfreq == hsifreq) { + break; + } + + hsidivfreq /= 2U; + } + + if (hsidiv == 4U) { + ERROR("Invalid clk-hsi frequency\n"); + return -1; + } + + if (hsidiv != 0U) { + return stm32mp1_set_hsidiv(hsidiv); + } + + return 0; +} + +static bool stm32mp1_check_pll_conf(enum stm32mp1_pll_id pll_id, + unsigned int clksrc, + uint32_t *pllcfg, int plloff) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + uintptr_t pllxcr = rcc_base + pll->pllxcr; + enum stm32mp1_plltype type = pll->plltype; + uintptr_t clksrc_address = rcc_base + (clksrc >> 4); + unsigned long refclk; + uint32_t ifrge = 0U; + uint32_t src, value, fracv = 0; + void *fdt; + + /* Check PLL output */ + if (mmio_read_32(pllxcr) != RCC_PLLNCR_PLLON) { + return false; + } + + /* Check current clksrc */ + src = mmio_read_32(clksrc_address) & RCC_SELR_SRC_MASK; + if (src != (clksrc & RCC_SELR_SRC_MASK)) { + return false; + } + + /* Check Div */ + src = mmio_read_32(rcc_base + pll->rckxselr) & RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); + + if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { + return false; + } + + if ((type == PLL_800) && (refclk >= 8000000U)) { + ifrge = 1U; + } + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & + RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & + RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & + RCC_PLLNCFGR1_IFRGE_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr1) != value) { + return false; + } + + /* Fractional configuration */ + if (fdt_get_address(&fdt) == 1) { + fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); + } + + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + value |= RCC_PLLNFRACR_FRACLE; + if (mmio_read_32(rcc_base + pll->pllxfracr) != value) { + return false; + } + + /* Output config */ + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + if (mmio_read_32(rcc_base + pll->pllxcfgr2) != value) { + return false; + } + + return true; +} + +static void stm32mp1_pll_start(enum stm32mp1_pll_id pll_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + + /* Preserve RCC_PLLNCR_SSCG_CTRL value */ + mmio_clrsetbits_32(pllxcr, + RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN, + RCC_PLLNCR_PLLON); +} + +static int stm32mp1_pll_output(enum stm32mp1_pll_id pll_id, uint32_t output) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + uint64_t timeout = timeout_init_us(PLLRDY_TIMEOUT); + + /* Wait PLL lock */ + while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("PLL%u start failed @ 0x%lx: 0x%x\n", + pll_id, pllxcr, mmio_read_32(pllxcr)); + return -ETIMEDOUT; + } + } + + /* Start the requested output */ + mmio_setbits_32(pllxcr, output << RCC_PLLNCR_DIVEN_SHIFT); + + return 0; +} + +static int stm32mp1_pll_stop(enum stm32mp1_pll_id pll_id) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t pllxcr = stm32mp_rcc_base() + pll->pllxcr; + uint64_t timeout; + + /* Stop all output */ + mmio_clrbits_32(pllxcr, RCC_PLLNCR_DIVPEN | RCC_PLLNCR_DIVQEN | + RCC_PLLNCR_DIVREN); + + /* Stop PLL */ + mmio_clrbits_32(pllxcr, RCC_PLLNCR_PLLON); + + timeout = timeout_init_us(PLLRDY_TIMEOUT); + /* Wait PLL stopped */ + while ((mmio_read_32(pllxcr) & RCC_PLLNCR_PLLRDY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("PLL%u stop failed @ 0x%lx: 0x%x\n", + pll_id, pllxcr, mmio_read_32(pllxcr)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_pll_config_output(enum stm32mp1_pll_id pll_id, + uint32_t *pllcfg) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t value; + + value = (pllcfg[PLLCFG_P] << RCC_PLLNCFGR2_DIVP_SHIFT) & + RCC_PLLNCFGR2_DIVP_MASK; + value |= (pllcfg[PLLCFG_Q] << RCC_PLLNCFGR2_DIVQ_SHIFT) & + RCC_PLLNCFGR2_DIVQ_MASK; + value |= (pllcfg[PLLCFG_R] << RCC_PLLNCFGR2_DIVR_SHIFT) & + RCC_PLLNCFGR2_DIVR_MASK; + mmio_write_32(rcc_base + pll->pllxcfgr2, value); +} + +static int stm32mp1_pll_config(enum stm32mp1_pll_id pll_id, + uint32_t *pllcfg, uint32_t fracv) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uintptr_t rcc_base = stm32mp_rcc_base(); + enum stm32mp1_plltype type = pll->plltype; + unsigned long refclk; + uint32_t ifrge = 0; + uint32_t src, value; + + src = mmio_read_32(rcc_base + pll->rckxselr) & + RCC_SELR_REFCLK_SRC_MASK; + + refclk = stm32mp1_clk_get_fixed(pll->refclk[src]) / + (pllcfg[PLLCFG_M] + 1U); + + if ((refclk < (stm32mp1_pll[type].refclk_min * 1000000U)) || + (refclk > (stm32mp1_pll[type].refclk_max * 1000000U))) { + return -EINVAL; + } + + if ((type == PLL_800) && (refclk >= 8000000U)) { + ifrge = 1U; + } + + value = (pllcfg[PLLCFG_N] << RCC_PLLNCFGR1_DIVN_SHIFT) & + RCC_PLLNCFGR1_DIVN_MASK; + value |= (pllcfg[PLLCFG_M] << RCC_PLLNCFGR1_DIVM_SHIFT) & + RCC_PLLNCFGR1_DIVM_MASK; + value |= (ifrge << RCC_PLLNCFGR1_IFRGE_SHIFT) & + RCC_PLLNCFGR1_IFRGE_MASK; + mmio_write_32(rcc_base + pll->pllxcfgr1, value); + + /* Fractional configuration */ + value = 0; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + value = fracv << RCC_PLLNFRACR_FRACV_SHIFT; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + value |= RCC_PLLNFRACR_FRACLE; + mmio_write_32(rcc_base + pll->pllxfracr, value); + + stm32mp1_pll_config_output(pll_id, pllcfg); + + return 0; +} + +static void stm32mp1_pll_csg(enum stm32mp1_pll_id pll_id, uint32_t *csg) +{ + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + uint32_t pllxcsg = 0; + + pllxcsg |= (csg[PLLCSG_MOD_PER] << RCC_PLLNCSGR_MOD_PER_SHIFT) & + RCC_PLLNCSGR_MOD_PER_MASK; + + pllxcsg |= (csg[PLLCSG_INC_STEP] << RCC_PLLNCSGR_INC_STEP_SHIFT) & + RCC_PLLNCSGR_INC_STEP_MASK; + + pllxcsg |= (csg[PLLCSG_SSCG_MODE] << RCC_PLLNCSGR_SSCG_MODE_SHIFT) & + RCC_PLLNCSGR_SSCG_MODE_MASK; + + mmio_write_32(stm32mp_rcc_base() + pll->pllxcsgr, pllxcsg); + + mmio_setbits_32(stm32mp_rcc_base() + pll->pllxcr, + RCC_PLLNCR_SSCG_CTRL); +} + +static int stm32mp1_set_clksrc(unsigned int clksrc) +{ + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); + uint64_t timeout; + + mmio_clrsetbits_32(clksrc_address, RCC_SELR_SRC_MASK, + clksrc & RCC_SELR_SRC_MASK); + + timeout = timeout_init_us(CLKSRC_TIMEOUT); + while ((mmio_read_32(clksrc_address) & RCC_SELR_SRCRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("CLKSRC %x start failed @ 0x%lx: 0x%x\n", clksrc, + clksrc_address, mmio_read_32(clksrc_address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32mp1_set_clkdiv(unsigned int clkdiv, uintptr_t address) +{ + uint64_t timeout; + + mmio_clrsetbits_32(address, RCC_DIVR_DIV_MASK, + clkdiv & RCC_DIVR_DIV_MASK); + + timeout = timeout_init_us(CLKDIV_TIMEOUT); + while ((mmio_read_32(address) & RCC_DIVR_DIVRDY) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("CLKDIV %x start failed @ 0x%lx: 0x%x\n", + clkdiv, address, mmio_read_32(address)); + return -ETIMEDOUT; + } + } + + return 0; +} + +static void stm32mp1_mco_csg(uint32_t clksrc, uint32_t clkdiv) +{ + uintptr_t clksrc_address = stm32mp_rcc_base() + (clksrc >> 4); + + /* + * Binding clksrc : + * bit15-4 offset + * bit3: disable + * bit2-0: MCOSEL[2:0] + */ + if ((clksrc & 0x8U) != 0U) { + mmio_clrbits_32(clksrc_address, RCC_MCOCFG_MCOON); + } else { + mmio_clrsetbits_32(clksrc_address, + RCC_MCOCFG_MCOSRC_MASK, + clksrc & RCC_MCOCFG_MCOSRC_MASK); + mmio_clrsetbits_32(clksrc_address, + RCC_MCOCFG_MCODIV_MASK, + clkdiv << RCC_MCOCFG_MCODIV_SHIFT); + mmio_setbits_32(clksrc_address, RCC_MCOCFG_MCOON); + } +} + +static void stm32mp1_set_rtcsrc(unsigned int clksrc, bool lse_css) +{ + uintptr_t address = stm32mp_rcc_base() + RCC_BDCR; + + if (((mmio_read_32(address) & RCC_BDCR_RTCCKEN) == 0U) || + (clksrc != (uint32_t)CLK_RTC_DISABLED)) { + mmio_clrsetbits_32(address, + RCC_BDCR_RTCSRC_MASK, + (clksrc & RCC_SELR_SRC_MASK) << RCC_BDCR_RTCSRC_SHIFT); + + mmio_setbits_32(address, RCC_BDCR_RTCCKEN); + } + + if (lse_css) { + mmio_setbits_32(address, RCC_BDCR_LSECSSON); + } +} + +static void stm32mp1_pkcs_config(uint32_t pkcs) +{ + uintptr_t address = stm32mp_rcc_base() + ((pkcs >> 4) & 0xFFFU); + uint32_t value = pkcs & 0xFU; + uint32_t mask = 0xFU; + + if ((pkcs & BIT(31)) != 0U) { + mask <<= 4; + value <<= 4; + } + + mmio_clrsetbits_32(address, mask, value); +} + +static int clk_get_pll_settings_from_dt(int plloff, unsigned int *pllcfg, + uint32_t *fracv, uint32_t *csg, + bool *csg_set) +{ + void *fdt; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_read_uint32_array(fdt, plloff, "cfg", (uint32_t)PLLCFG_NB, + pllcfg); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + *fracv = fdt_read_uint32_default(fdt, plloff, "frac", 0); + + ret = fdt_read_uint32_array(fdt, plloff, "csg", (uint32_t)PLLCSG_NB, + csg); + + *csg_set = (ret == 0); + + if (ret == -FDT_ERR_NOTFOUND) { + ret = 0; + } + + return ret; +} + +int stm32mp1_clk_init(void) +{ + uintptr_t rcc_base = stm32mp_rcc_base(); + uint32_t pllfracv[_PLL_NB]; + uint32_t pllcsg[_PLL_NB][PLLCSG_NB]; + unsigned int clksrc[CLKSRC_NB]; + unsigned int clkdiv[CLKDIV_NB]; + unsigned int pllcfg[_PLL_NB][PLLCFG_NB]; + int plloff[_PLL_NB]; + int ret, len; + enum stm32mp1_pll_id i; + bool pllcsg_set[_PLL_NB]; + bool pllcfg_valid[_PLL_NB]; + bool lse_css = false; + bool pll3_preserve = false; + bool pll4_preserve = false; + bool pll4_bootrom = false; + const fdt32_t *pkcs_cell; + void *fdt; + int stgen_p = stm32mp1_clk_get_parent(STGEN_K); + int usbphy_p = stm32mp1_clk_get_parent(USBPHY_K); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_rcc_read_uint32_array("st,clksrc", (uint32_t)CLKSRC_NB, + clksrc); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_rcc_read_uint32_array("st,clkdiv", (uint32_t)CLKDIV_NB, + clkdiv); + if (ret < 0) { + return -FDT_ERR_NOTFOUND; + } + + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + char name[12]; + + snprintf(name, sizeof(name), "st,pll@%u", i); + plloff[i] = fdt_rcc_subnode_offset(name); + + pllcfg_valid[i] = fdt_check_node(plloff[i]); + if (!pllcfg_valid[i]) { + continue; + } + + ret = clk_get_pll_settings_from_dt(plloff[i], pllcfg[i], + &pllfracv[i], pllcsg[i], + &pllcsg_set[i]); + if (ret != 0) { + return ret; + } + } + + stm32mp1_mco_csg(clksrc[CLKSRC_MCO1], clkdiv[CLKDIV_MCO1]); + stm32mp1_mco_csg(clksrc[CLKSRC_MCO2], clkdiv[CLKDIV_MCO2]); + + /* + * Switch ON oscillator found in device-tree. + * Note: HSI already ON after BootROM stage. + */ + if (stm32mp1_osc[_LSI] != 0U) { + stm32mp1_lsi_set(true); + } + if (stm32mp1_osc[_LSE] != 0U) { + const char *name = stm32mp_osc_node_label[_LSE]; + bool bypass, digbyp; + uint32_t lsedrv; + + bypass = fdt_clk_read_bool(name, "st,bypass"); + digbyp = fdt_clk_read_bool(name, "st,digbypass"); + lse_css = fdt_clk_read_bool(name, "st,css"); + lsedrv = fdt_clk_read_uint32_default(name, "st,drive", + LSEDRV_MEDIUM_HIGH); + stm32mp1_lse_enable(bypass, digbyp, lsedrv); + } + if (stm32mp1_osc[_HSE] != 0U) { + const char *name = stm32mp_osc_node_label[_HSE]; + bool bypass, digbyp, css; + + bypass = fdt_clk_read_bool(name, "st,bypass"); + digbyp = fdt_clk_read_bool(name, "st,digbypass"); + css = fdt_clk_read_bool(name, "st,css"); + stm32mp1_hse_enable(bypass, digbyp, css); + } + /* + * CSI is mandatory for automatic I/O compensation (SYSCFG_CMPCR) + * => switch on CSI even if node is not present in device tree + */ + stm32mp1_csi_set(true); + + /* Come back to HSI */ + ret = stm32mp1_set_clksrc(CLK_MPU_HSI); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(CLK_AXI_HSI); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(CLK_MCU_HSI); + if (ret != 0) { + return ret; + } + + if ((mmio_read_32(rcc_base + RCC_MP_RSTSCLRR) & + RCC_MP_RSTSCLRR_MPUP0RSTF) != 0) { + if (pllcfg_valid[_PLL3]) { + pll3_preserve = + stm32mp1_check_pll_conf(_PLL3, + clksrc[CLKSRC_PLL3], + pllcfg[_PLL3], + plloff[_PLL3]); + } + + if (pllcfg_valid[_PLL4]) { + pll4_preserve = + stm32mp1_check_pll_conf(_PLL4, + clksrc[CLKSRC_PLL4], + pllcfg[_PLL4], + plloff[_PLL4]); + } + } + /* Don't initialize PLL4, when used by BOOTROM */ + if ((stm32mp_get_boot_itf_selected() == + BOOT_API_CTX_BOOT_INTERFACE_SEL_SERIAL_USB) && + ((stgen_p == (int)_PLL4_R) || (usbphy_p == (int)_PLL4_R))) { + pll4_bootrom = true; + pll4_preserve = true; + } + + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve)) { + continue; + } + + ret = stm32mp1_pll_stop(i); + if (ret != 0) { + return ret; + } + } + + /* Configure HSIDIV */ + if (stm32mp1_osc[_HSI] != 0U) { + ret = stm32mp1_hsidiv(stm32mp1_osc[_HSI]); + if (ret != 0) { + return ret; + } + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + } + + /* Select DIV */ + /* No ready bit when MPUSRC != CLK_MPU_PLL1P_DIV, MPUDIV is disabled */ + mmio_write_32(rcc_base + RCC_MPCKDIVR, + clkdiv[CLKDIV_MPU] & RCC_DIVR_DIV_MASK); + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_AXI], rcc_base + RCC_AXIDIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB4], rcc_base + RCC_APB4DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB5], rcc_base + RCC_APB5DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_MCU], rcc_base + RCC_MCUDIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB1], rcc_base + RCC_APB1DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB2], rcc_base + RCC_APB2DIVR); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clkdiv(clkdiv[CLKDIV_APB3], rcc_base + RCC_APB3DIVR); + if (ret != 0) { + return ret; + } + + /* No ready bit for RTC */ + mmio_write_32(rcc_base + RCC_RTCDIVR, + clkdiv[CLKDIV_RTC] & RCC_DIVR_DIV_MASK); + + /* Configure PLLs source */ + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL12]); + if (ret != 0) { + return ret; + } + + if (!pll3_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL3]); + if (ret != 0) { + return ret; + } + } + + if (!pll4_preserve) { + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_PLL4]); + if (ret != 0) { + return ret; + } + } + + /* Configure and start PLLs */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (((i == _PLL3) && pll3_preserve) || + ((i == _PLL4) && pll4_preserve && !pll4_bootrom)) { + continue; + } + + if (!pllcfg_valid[i]) { + continue; + } + + if ((i == _PLL4) && pll4_bootrom) { + /* Set output divider if not done by the Bootrom */ + stm32mp1_pll_config_output(i, pllcfg[i]); + continue; + } + + ret = stm32mp1_pll_config(i, pllcfg[i], pllfracv[i]); + if (ret != 0) { + return ret; + } + + if (pllcsg_set[i]) { + stm32mp1_pll_csg(i, pllcsg[i]); + } + + stm32mp1_pll_start(i); + } + /* Wait and start PLLs ouptut when ready */ + for (i = (enum stm32mp1_pll_id)0; i < _PLL_NB; i++) { + if (!pllcfg_valid[i]) { + continue; + } + + ret = stm32mp1_pll_output(i, pllcfg[i][PLLCFG_O]); + if (ret != 0) { + return ret; + } + } + /* Wait LSE ready before to use it */ + if (stm32mp1_osc[_LSE] != 0U) { + stm32mp1_lse_wait(); + } + + /* Configure with expected clock source */ + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MPU]); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_AXI]); + if (ret != 0) { + return ret; + } + ret = stm32mp1_set_clksrc(clksrc[CLKSRC_MCU]); + if (ret != 0) { + return ret; + } + stm32mp1_set_rtcsrc(clksrc[CLKSRC_RTC], lse_css); + + /* Configure PKCK */ + pkcs_cell = fdt_rcc_read_prop("st,pkcs", &len); + if (pkcs_cell != NULL) { + bool ckper_disabled = false; + uint32_t j; + uint32_t usbreg_bootrom = 0U; + + if (pll4_bootrom) { + usbreg_bootrom = mmio_read_32(rcc_base + RCC_USBCKSELR); + } + + for (j = 0; j < ((uint32_t)len / sizeof(uint32_t)); j++) { + uint32_t pkcs = fdt32_to_cpu(pkcs_cell[j]); + + if (pkcs == (uint32_t)CLK_CKPER_DISABLED) { + ckper_disabled = true; + continue; + } + stm32mp1_pkcs_config(pkcs); + } + + /* + * CKPER is source for some peripheral clocks + * (FMC-NAND / QPSI-NOR) and switching source is allowed + * only if previous clock is still ON + * => deactivated CKPER only after switching clock + */ + if (ckper_disabled) { + stm32mp1_pkcs_config(CLK_CKPER_DISABLED); + } + + if (pll4_bootrom) { + uint32_t usbreg_value, usbreg_mask; + const struct stm32mp1_clk_sel *sel; + + sel = clk_sel_ref(_USBPHY_SEL); + usbreg_mask = (uint32_t)sel->msk << sel->src; + sel = clk_sel_ref(_USBO_SEL); + usbreg_mask |= (uint32_t)sel->msk << sel->src; + + usbreg_value = mmio_read_32(rcc_base + RCC_USBCKSELR) & + usbreg_mask; + usbreg_bootrom &= usbreg_mask; + if (usbreg_bootrom != usbreg_value) { + VERBOSE("forbidden new USB clk path\n"); + VERBOSE("vs bootrom on USB boot\n"); + return -FDT_ERR_BADVALUE; + } + } + } + + /* Switch OFF HSI if not found in device-tree */ + if (stm32mp1_osc[_HSI] == 0U) { + stm32mp1_hsi_set(false); + } + + stm32mp_stgen_config(stm32mp_clk_get_rate(STGEN_K)); + + /* Software Self-Refresh mode (SSR) during DDR initilialization */ + mmio_clrsetbits_32(rcc_base + RCC_DDRITFCR, + RCC_DDRITFCR_DDRCKMOD_MASK, + RCC_DDRITFCR_DDRCKMOD_SSR << + RCC_DDRITFCR_DDRCKMOD_SHIFT); + + return 0; +} + +static void stm32mp1_osc_clk_init(const char *name, + enum stm32mp_osc_id index) +{ + uint32_t frequency; + + if (fdt_osc_read_freq(name, &frequency) == 0) { + stm32mp1_osc[index] = frequency; + } +} + +static void stm32mp1_osc_init(void) +{ + enum stm32mp_osc_id i; + + for (i = (enum stm32mp_osc_id)0 ; i < NB_OSC; i++) { + stm32mp1_osc_clk_init(stm32mp_osc_node_label[i], i); + } +} + +#ifdef STM32MP_SHARED_RESOURCES +/* + * Get the parent ID of the target parent clock, for tagging as secure + * shared clock dependencies. + */ +static int get_parent_id_parent(unsigned int parent_id) +{ + enum stm32mp1_parent_sel s = _UNKNOWN_SEL; + enum stm32mp1_pll_id pll_id; + uint32_t p_sel; + uintptr_t rcc_base = stm32mp_rcc_base(); + + switch (parent_id) { + case _ACLK: + case _PCLK4: + case _PCLK5: + s = _AXIS_SEL; + break; + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + pll_id = _PLL1; + break; + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + pll_id = _PLL2; + break; + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + pll_id = _PLL3; + break; + case _PLL4_P: + case _PLL4_Q: + case _PLL4_R: + pll_id = _PLL4; + break; + case _PCLK1: + case _PCLK2: + case _HCLK2: + case _HCLK6: + case _CK_PER: + case _CK_MPU: + case _CK_MCU: + case _USB_PHY_48: + /* We do not expect to access these */ + panic(); + break; + default: + /* Other parents have no parent */ + return -1; + } + + if (s != _UNKNOWN_SEL) { + const struct stm32mp1_clk_sel *sel = clk_sel_ref(s); + + p_sel = (mmio_read_32(rcc_base + sel->offset) >> sel->src) & + sel->msk; + + if (p_sel < sel->nb_parent) { + return (int)sel->parent[p_sel]; + } + } else { + const struct stm32mp1_clk_pll *pll = pll_ref(pll_id); + + p_sel = mmio_read_32(rcc_base + pll->rckxselr) & + RCC_SELR_REFCLK_SRC_MASK; + + if (pll->refclk[p_sel] != _UNKNOWN_OSC_ID) { + return (int)pll->refclk[p_sel]; + } + } + + VERBOSE("No parent selected for %s\n", + stm32mp1_clk_parent_name[parent_id]); + + return -1; +} + +static void secure_parent_clocks(unsigned long parent_id) +{ + int grandparent_id; + + switch (parent_id) { + case _PLL3_P: + case _PLL3_Q: + case _PLL3_R: + stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); + break; + + /* These clocks are always secure when RCC is secure */ + case _ACLK: + case _HCLK2: + case _HCLK6: + case _PCLK4: + case _PCLK5: + case _PLL1_P: + case _PLL1_Q: + case _PLL1_R: + case _PLL2_P: + case _PLL2_Q: + case _PLL2_R: + case _HSI: + case _HSI_KER: + case _LSI: + case _CSI: + case _CSI_KER: + case _HSE: + case _HSE_KER: + case _HSE_KER_DIV2: + case _HSE_RTC: + case _LSE: + break; + + default: + VERBOSE("Cannot secure parent clock %s\n", + stm32mp1_clk_parent_name[parent_id]); + panic(); + } + + grandparent_id = get_parent_id_parent(parent_id); + if (grandparent_id >= 0) { + secure_parent_clocks(grandparent_id); + } +} + +void stm32mp1_register_clock_parents_secure(unsigned long clock_id) +{ + int parent_id; + + if (!stm32mp1_rcc_is_secure()) { + return; + } + + switch (clock_id) { + case PLL1: + case PLL2: + /* PLL1/PLL2 are always secure: nothing to do */ + break; + case PLL3: + stm32mp_register_secure_periph(STM32MP1_SHRES_PLL3); + break; + case PLL4: + ERROR("PLL4 cannot be secured\n"); + panic(); + break; + default: + /* Others are expected gateable clock */ + parent_id = stm32mp1_clk_get_parent(clock_id); + if (parent_id < 0) { + INFO("No parent found for clock %lu\n", clock_id); + } else { + secure_parent_clocks(parent_id); + } + break; + } +} +#endif /* STM32MP_SHARED_RESOURCES */ + +static void sync_earlyboot_clocks_state(void) +{ + unsigned int idx; + const unsigned long secure_enable[] = { + AXIDCG, + BSEC, + DDRC1, DDRC1LP, + DDRC2, DDRC2LP, + DDRCAPB, DDRPHYCAPB, DDRPHYCAPBLP, + DDRPHYC, DDRPHYCLP, + RTCAPB, + TZC1, TZC2, + TZPC, + STGEN_K, + }; + + for (idx = 0U; idx < ARRAY_SIZE(secure_enable); idx++) { + stm32mp_clk_enable(secure_enable[idx]); + } +} + +static const struct clk_ops stm32mp_clk_ops = { + .enable = stm32mp_clk_enable, + .disable = stm32mp_clk_disable, + .is_enabled = stm32mp_clk_is_enabled, + .get_rate = stm32mp_clk_get_rate, + .get_parent = stm32mp1_clk_get_parent, +}; + +int stm32mp1_clk_probe(void) +{ +#if defined(IMAGE_BL32) + if (!fdt_get_rcc_secure_state()) { + mmio_write_32(stm32mp_rcc_base() + RCC_TZCR, 0U); + } +#endif + + stm32mp1_osc_init(); + + sync_earlyboot_clocks_state(); + + clk_register(&stm32mp_clk_ops); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c b/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c new file mode 100644 index 0000000..80c2f41 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c @@ -0,0 +1,378 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DT_UART_COMPAT "st,stm32h7-uart" +/* + * Get the frequency of an oscillator from its name in device tree. + * @param name: oscillator name + * @param freq: stores the frequency of the oscillator + * @return: 0 on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_osc_read_freq(const char *name, uint32_t *freq) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return ret; + } + + if ((strncmp(cchar, name, (size_t)ret) == 0) && + (fdt_get_status(subnode) != DT_DISABLED)) { + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, subnode, "clock-frequency", + &ret); + if (cuint == NULL) { + return ret; + } + + *freq = fdt32_to_cpu(*cuint); + + return 0; + } + } + + /* Oscillator not found, freq=0 */ + *freq = 0; + return 0; +} + +/* + * Check the presence of an oscillator property from its id. + * @param node_label: clock node name + * @param prop_name: property name + * @return: true/false regarding search result. + */ +bool fdt_clk_read_bool(const char *node_label, const char *prop_name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return false; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return false; + } + + if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + + if (fdt_getprop(fdt, subnode, prop_name, NULL) != NULL) { + return true; + } + } + + return false; +} + +/* + * Get the value of a oscillator property from its name. + * @param node_label: oscillator name + * @param prop_name: property name + * @param dflt_value: default value + * @return oscillator value on success, default value if property not found. + */ +uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, uint32_t dflt_value) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return dflt_value; + } + + node = fdt_path_offset(fdt, "/clocks"); + if (node < 0) { + return dflt_value; + } + + fdt_for_each_subnode(subnode, fdt, node) { + const char *cchar; + int ret; + + cchar = fdt_get_name(fdt, subnode, &ret); + if (cchar == NULL) { + return dflt_value; + } + + if (strncmp(cchar, node_label, (size_t)ret) != 0) { + continue; + } + + return fdt_read_uint32_default(fdt, subnode, prop_name, + dflt_value); + } + + return dflt_value; +} + +/* + * Get the RCC node offset from the device tree + * @param fdt: Device tree reference + * @return: Node offset or a negative value on error + */ +static int fdt_get_rcc_node(void *fdt) +{ + static int node; + + if (node <= 0) { + node = fdt_node_offset_by_compatible(fdt, -1, DT_RCC_CLK_COMPAT); + } + + return node; +} + +/* + * Read a series of parameters in rcc-clk section in device tree + * @param prop_name: Name of the RCC property to be read + * @param array: the array to store the property parameters + * @param count: number of parameters to be read + * @return: 0 on succes or a negative value on error + */ +int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + uint32_t *array) +{ + int node; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + return fdt_read_uint32_array(fdt, node, prop_name, count, array); +} + +/* + * Get the subnode offset in rcc-clk section from its name in device tree + * @param name: name of the RCC property + * @return: offset on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_rcc_subnode_offset(const char *name) +{ + int node, subnode; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return -FDT_ERR_NOTFOUND; + } + + subnode = fdt_subnode_offset(fdt, node, name); + if (subnode <= 0) { + return -FDT_ERR_NOTFOUND; + } + + return subnode; +} + +/* + * Get the pointer to a rcc-clk property from its name. + * @param name: name of the RCC property + * @param lenp: stores the length of the property. + * @return: pointer to the property on success, and NULL value on failure. + */ +const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp) +{ + const fdt32_t *cuint; + int node, len; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return NULL; + } + + node = fdt_get_rcc_node(fdt); + if (node < 0) { + return NULL; + } + + cuint = fdt_getprop(fdt, node, prop_name, &len); + if (cuint == NULL) { + return NULL; + } + + *lenp = len; + return cuint; +} + +/* + * Get the secure state for rcc node in device tree. + * @return: true if rcc is configured for secure world access, false if not. + */ +bool fdt_get_rcc_secure_state(void) +{ + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return false; + } + + if (fdt_node_offset_by_compatible(fdt, -1, DT_RCC_SEC_CLK_COMPAT) < 0) { + return false; + } + + return true; +} + +/* + * Get the clock ID of the given node in device tree. + * @param node: node offset + * @return: Clock ID on success, and a negative FDT/ERRNO error code on failure. + */ +int fdt_get_clock_id(int node) +{ + const fdt32_t *cuint; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + cuint = fdt_getprop(fdt, node, "clocks", NULL); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + cuint++; + return (int)fdt32_to_cpu(*cuint); +} + +/* + * Get the frequency of the specified UART instance. + * @param instance: UART interface registers base address. + * @return: clock frequency on success, 0 value on failure. + */ +unsigned long fdt_get_uart_clock_freq(uintptr_t instance) +{ + void *fdt; + int node; + int clk_id; + + if (fdt_get_address(&fdt) == 0) { + return 0UL; + } + + /* Check for UART nodes */ + node = dt_match_instance_by_compatible(DT_UART_COMPAT, instance); + if (node < 0) { + return 0UL; + } + + clk_id = fdt_get_clock_id(node); + if (clk_id < 0) { + return 0UL; + } + + return clk_get_rate((unsigned long)clk_id); +} + +/******************************************************************************* + * This function configures and restores the STGEN counter depending on the + * connected clock. + ******************************************************************************/ +void stm32mp_stgen_config(unsigned long rate) +{ + uint32_t cntfid0; + unsigned long long counter; + + cntfid0 = mmio_read_32(STGEN_BASE + CNTFID_OFF); + + if (cntfid0 == rate) { + return; + } + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + counter = stm32mp_stgen_get_counter() * rate / cntfid0; + + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)counter); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(counter >> 32)); + mmio_write_32(STGEN_BASE + CNTFID_OFF, rate); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + + write_cntfrq_el0(rate); + + /* Need to update timer with new frequency */ + generic_delay_timer_init(); +} + +/******************************************************************************* + * This function returns the STGEN counter value. + ******************************************************************************/ +unsigned long long stm32mp_stgen_get_counter(void) +{ + return (((unsigned long long)mmio_read_32(STGEN_BASE + CNTCVU_OFF) << 32) | + mmio_read_32(STGEN_BASE + CNTCVL_OFF)); +} + +/******************************************************************************* + * This function restores the STGEN counter value. + * It takes a first input value as a counter backup value to be restored and a + * offset in ms to be added. + ******************************************************************************/ +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms) +{ + unsigned long long cnt; + + cnt = value + ((offset_in_ms * + mmio_read_32(STGEN_BASE + CNTFID_OFF)) / 1000U); + + mmio_clrbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); + mmio_write_32(STGEN_BASE + CNTCVL_OFF, (uint32_t)cnt); + mmio_write_32(STGEN_BASE + CNTCVU_OFF, (uint32_t)(cnt >> 32)); + mmio_setbits_32(STGEN_BASE + CNTCR_OFF, CNTCR_EN); +} diff --git a/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c b/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c new file mode 100644 index 0000000..6a1d476 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/crypto/stm32_hash.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DT_HASH_COMPAT "st,stm32f756-hash" + +#define HASH_CR 0x00U +#define HASH_DIN 0x04U +#define HASH_STR 0x08U +#define HASH_SR 0x24U +#define HASH_HREG(x) (0x310U + ((x) * 0x04U)) + +/* Control Register */ +#define HASH_CR_INIT BIT(2) +#define HASH_CR_DATATYPE_SHIFT U(4) + +#define HASH_CR_ALGO_SHA1 0x0U +#define HASH_CR_ALGO_MD5 BIT(7) +#define HASH_CR_ALGO_SHA224 BIT(18) +#define HASH_CR_ALGO_SHA256 (BIT(18) | BIT(7)) + +/* Status Flags */ +#define HASH_SR_DCIS BIT(1) +#define HASH_SR_BUSY BIT(3) + +/* STR Register */ +#define HASH_STR_NBLW_MASK GENMASK(4, 0) +#define HASH_STR_DCAL BIT(8) + +#define MD5_DIGEST_SIZE 16U +#define SHA1_DIGEST_SIZE 20U +#define SHA224_DIGEST_SIZE 28U +#define SHA256_DIGEST_SIZE 32U + +#define RESET_TIMEOUT_US_1MS 1000U +#define HASH_TIMEOUT_US 10000U + +enum stm32_hash_data_format { + HASH_DATA_32_BITS, + HASH_DATA_16_BITS, + HASH_DATA_8_BITS, + HASH_DATA_1_BIT +}; + +struct stm32_hash_instance { + uintptr_t base; + unsigned int clock; + size_t digest_size; +}; + +struct stm32_hash_remain { + uint32_t buffer; + size_t length; +}; + +/* Expect a single HASH peripheral */ +static struct stm32_hash_instance stm32_hash; +static struct stm32_hash_remain stm32_remain; + +static uintptr_t hash_base(void) +{ + return stm32_hash.base; +} + +static int hash_wait_busy(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_BUSY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_wait_computation(void) +{ + uint64_t timeout = timeout_init_us(HASH_TIMEOUT_US); + + while ((mmio_read_32(hash_base() + HASH_SR) & HASH_SR_DCIS) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int hash_write_data(uint32_t data) +{ + int ret; + + ret = hash_wait_busy(); + if (ret != 0) { + return ret; + } + + mmio_write_32(hash_base() + HASH_DIN, data); + + return 0; +} + +static void hash_hw_init(enum stm32_hash_algo_mode mode) +{ + uint32_t reg; + + reg = HASH_CR_INIT | (HASH_DATA_8_BITS << HASH_CR_DATATYPE_SHIFT); + + switch (mode) { + case HASH_MD5SUM: + reg |= HASH_CR_ALGO_MD5; + stm32_hash.digest_size = MD5_DIGEST_SIZE; + break; + case HASH_SHA1: + reg |= HASH_CR_ALGO_SHA1; + stm32_hash.digest_size = SHA1_DIGEST_SIZE; + break; + case HASH_SHA224: + reg |= HASH_CR_ALGO_SHA224; + stm32_hash.digest_size = SHA224_DIGEST_SIZE; + break; + /* Default selected algo is SHA256 */ + case HASH_SHA256: + default: + reg |= HASH_CR_ALGO_SHA256; + stm32_hash.digest_size = SHA256_DIGEST_SIZE; + break; + } + + mmio_write_32(hash_base() + HASH_CR, reg); +} + +static int hash_get_digest(uint8_t *digest) +{ + int ret; + uint32_t i; + uint32_t dsg; + + ret = hash_wait_computation(); + if (ret != 0) { + return ret; + } + + for (i = 0U; i < (stm32_hash.digest_size / sizeof(uint32_t)); i++) { + dsg = __builtin_bswap32(mmio_read_32(hash_base() + + HASH_HREG(i))); + memcpy(digest + (i * sizeof(uint32_t)), &dsg, sizeof(uint32_t)); + } + +#if defined(IMAGE_BL2) + /* + * Clean hardware context as HASH could be used later + * by non-secure software + */ + hash_hw_init(HASH_SHA256); +#endif + return 0; +} + +int stm32_hash_update(const uint8_t *buffer, size_t length) +{ + size_t remain_length = length; + int ret = 0; + + if ((length == 0U) || (buffer == NULL)) { + return 0; + } + + clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + uint32_t copysize; + + copysize = MIN((sizeof(uint32_t) - stm32_remain.length), + length); + memcpy(((uint8_t *)&stm32_remain.buffer) + stm32_remain.length, + buffer, copysize); + remain_length -= copysize; + buffer += copysize; + if (stm32_remain.length == sizeof(uint32_t)) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + goto exit; + } + + zeromem(&stm32_remain, sizeof(stm32_remain)); + } + } + + while (remain_length / sizeof(uint32_t) != 0U) { + uint32_t tmp_buf; + + memcpy(&tmp_buf, buffer, sizeof(uint32_t)); + ret = hash_write_data(tmp_buf); + if (ret != 0) { + goto exit; + } + + buffer += sizeof(uint32_t); + remain_length -= sizeof(uint32_t); + } + + if (remain_length != 0U) { + assert(stm32_remain.length == 0U); + + memcpy((uint8_t *)&stm32_remain.buffer, buffer, remain_length); + stm32_remain.length = remain_length; + } + +exit: + clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final(uint8_t *digest) +{ + int ret; + + clk_enable(stm32_hash.clock); + + if (stm32_remain.length != 0U) { + ret = hash_write_data(stm32_remain.buffer); + if (ret != 0) { + clk_disable(stm32_hash.clock); + return ret; + } + + mmio_clrsetbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK, + 8U * stm32_remain.length); + zeromem(&stm32_remain, sizeof(stm32_remain)); + } else { + mmio_clrbits_32(hash_base() + HASH_STR, HASH_STR_NBLW_MASK); + } + + mmio_setbits_32(hash_base() + HASH_STR, HASH_STR_DCAL); + + ret = hash_get_digest(digest); + + clk_disable(stm32_hash.clock); + + return ret; +} + +int stm32_hash_final_update(const uint8_t *buffer, uint32_t length, + uint8_t *digest) +{ + int ret; + + ret = stm32_hash_update(buffer, length); + if (ret != 0) { + return ret; + } + + return stm32_hash_final(digest); +} + +void stm32_hash_init(enum stm32_hash_algo_mode mode) +{ + clk_enable(stm32_hash.clock); + + hash_hw_init(mode); + + clk_disable(stm32_hash.clock); + + zeromem(&stm32_remain, sizeof(stm32_remain)); +} + +int stm32_hash_register(void) +{ + struct dt_node_info hash_info; + int node; + + for (node = dt_get_node(&hash_info, -1, DT_HASH_COMPAT); + node != -FDT_ERR_NOTFOUND; + node = dt_get_node(&hash_info, node, DT_HASH_COMPAT)) { +#if defined(IMAGE_BL2) + if (hash_info.status != DT_DISABLED) { + break; + } +#else + /* BL32 uses hash if it is assigned only to secure world */ + if (hash_info.status == DT_SECURE) { + stm32mp_register_secure_periph_iomem(hash_info.base); + break; + } +#endif + } + + if (node == -FDT_ERR_NOTFOUND) { + return -ENODEV; + } + + if (hash_info.clock < 0) { + return -EINVAL; + } + + stm32_hash.base = hash_info.base; + stm32_hash.clock = hash_info.clock; + + clk_enable(stm32_hash.clock); + + if (hash_info.reset >= 0) { + uint32_t id = (uint32_t)hash_info.reset; + + if (stm32mp_reset_assert(id, RESET_TIMEOUT_US_1MS) != 0) { + panic(); + } + udelay(20); + if (stm32mp_reset_deassert(id, RESET_TIMEOUT_US_1MS) != 0) { + panic(); + } + } + + clk_disable(stm32_hash.clock); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c new file mode 100644 index 0000000..4719e1e --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DDRCTL_REG(x, y) \ + { \ + .name = #x, \ + .offset = offsetof(struct stm32mp_ddrctl, x), \ + .par_offset = offsetof(struct y, x) \ + } + +#define DDRPHY_REG(x, y) \ + { \ + .name = #x, \ + .offset = offsetof(struct stm32mp_ddrphy, x), \ + .par_offset = offsetof(struct y, x) \ + } + +/* + * PARAMETERS: value get from device tree : + * size / order need to be aligned with binding + * modification NOT ALLOWED !!! + */ +#define DDRCTL_REG_REG_SIZE 25 /* st,ctl-reg */ +#define DDRCTL_REG_TIMING_SIZE 12 /* st,ctl-timing */ +#define DDRCTL_REG_MAP_SIZE 9 /* st,ctl-map */ +#if STM32MP_DDR_DUAL_AXI_PORT +#define DDRCTL_REG_PERF_SIZE 17 /* st,ctl-perf */ +#else +#define DDRCTL_REG_PERF_SIZE 11 /* st,ctl-perf */ +#endif + +#if STM32MP_DDR_32BIT_INTERFACE +#define DDRPHY_REG_REG_SIZE 11 /* st,phy-reg */ +#else +#define DDRPHY_REG_REG_SIZE 9 /* st,phy-reg */ +#endif +#define DDRPHY_REG_TIMING_SIZE 10 /* st,phy-timing */ + +#define DDRCTL_REG_REG(x) DDRCTL_REG(x, stm32mp1_ddrctrl_reg) +static const struct stm32mp_ddr_reg_desc ddr_reg[DDRCTL_REG_REG_SIZE] = { + DDRCTL_REG_REG(mstr), + DDRCTL_REG_REG(mrctrl0), + DDRCTL_REG_REG(mrctrl1), + DDRCTL_REG_REG(derateen), + DDRCTL_REG_REG(derateint), + DDRCTL_REG_REG(pwrctl), + DDRCTL_REG_REG(pwrtmg), + DDRCTL_REG_REG(hwlpctl), + DDRCTL_REG_REG(rfshctl0), + DDRCTL_REG_REG(rfshctl3), + DDRCTL_REG_REG(crcparctl0), + DDRCTL_REG_REG(zqctl0), + DDRCTL_REG_REG(dfitmg0), + DDRCTL_REG_REG(dfitmg1), + DDRCTL_REG_REG(dfilpcfg0), + DDRCTL_REG_REG(dfiupd0), + DDRCTL_REG_REG(dfiupd1), + DDRCTL_REG_REG(dfiupd2), + DDRCTL_REG_REG(dfiphymstr), + DDRCTL_REG_REG(odtmap), + DDRCTL_REG_REG(dbg0), + DDRCTL_REG_REG(dbg1), + DDRCTL_REG_REG(dbgcmd), + DDRCTL_REG_REG(poisoncfg), + DDRCTL_REG_REG(pccfg), +}; + +#define DDRCTL_REG_TIMING(x) DDRCTL_REG(x, stm32mp1_ddrctrl_timing) +static const struct stm32mp_ddr_reg_desc ddr_timing[DDRCTL_REG_TIMING_SIZE] = { + DDRCTL_REG_TIMING(rfshtmg), + DDRCTL_REG_TIMING(dramtmg0), + DDRCTL_REG_TIMING(dramtmg1), + DDRCTL_REG_TIMING(dramtmg2), + DDRCTL_REG_TIMING(dramtmg3), + DDRCTL_REG_TIMING(dramtmg4), + DDRCTL_REG_TIMING(dramtmg5), + DDRCTL_REG_TIMING(dramtmg6), + DDRCTL_REG_TIMING(dramtmg7), + DDRCTL_REG_TIMING(dramtmg8), + DDRCTL_REG_TIMING(dramtmg14), + DDRCTL_REG_TIMING(odtcfg), +}; + +#define DDRCTL_REG_MAP(x) DDRCTL_REG(x, stm32mp1_ddrctrl_map) +static const struct stm32mp_ddr_reg_desc ddr_map[DDRCTL_REG_MAP_SIZE] = { + DDRCTL_REG_MAP(addrmap1), + DDRCTL_REG_MAP(addrmap2), + DDRCTL_REG_MAP(addrmap3), + DDRCTL_REG_MAP(addrmap4), + DDRCTL_REG_MAP(addrmap5), + DDRCTL_REG_MAP(addrmap6), + DDRCTL_REG_MAP(addrmap9), + DDRCTL_REG_MAP(addrmap10), + DDRCTL_REG_MAP(addrmap11), +}; + +#define DDRCTL_REG_PERF(x) DDRCTL_REG(x, stm32mp1_ddrctrl_perf) +static const struct stm32mp_ddr_reg_desc ddr_perf[DDRCTL_REG_PERF_SIZE] = { + DDRCTL_REG_PERF(sched), + DDRCTL_REG_PERF(sched1), + DDRCTL_REG_PERF(perfhpr1), + DDRCTL_REG_PERF(perflpr1), + DDRCTL_REG_PERF(perfwr1), + DDRCTL_REG_PERF(pcfgr_0), + DDRCTL_REG_PERF(pcfgw_0), + DDRCTL_REG_PERF(pcfgqos0_0), + DDRCTL_REG_PERF(pcfgqos1_0), + DDRCTL_REG_PERF(pcfgwqos0_0), + DDRCTL_REG_PERF(pcfgwqos1_0), +#if STM32MP_DDR_DUAL_AXI_PORT + DDRCTL_REG_PERF(pcfgr_1), + DDRCTL_REG_PERF(pcfgw_1), + DDRCTL_REG_PERF(pcfgqos0_1), + DDRCTL_REG_PERF(pcfgqos1_1), + DDRCTL_REG_PERF(pcfgwqos0_1), + DDRCTL_REG_PERF(pcfgwqos1_1), +#endif +}; + +#define DDRPHY_REG_REG(x) DDRPHY_REG(x, stm32mp1_ddrphy_reg) +static const struct stm32mp_ddr_reg_desc ddrphy_reg[DDRPHY_REG_REG_SIZE] = { + DDRPHY_REG_REG(pgcr), + DDRPHY_REG_REG(aciocr), + DDRPHY_REG_REG(dxccr), + DDRPHY_REG_REG(dsgcr), + DDRPHY_REG_REG(dcr), + DDRPHY_REG_REG(odtcr), + DDRPHY_REG_REG(zq0cr1), + DDRPHY_REG_REG(dx0gcr), + DDRPHY_REG_REG(dx1gcr), +#if STM32MP_DDR_32BIT_INTERFACE + DDRPHY_REG_REG(dx2gcr), + DDRPHY_REG_REG(dx3gcr), +#endif +}; + +#define DDRPHY_REG_TIMING(x) DDRPHY_REG(x, stm32mp1_ddrphy_timing) +static const struct stm32mp_ddr_reg_desc ddrphy_timing[DDRPHY_REG_TIMING_SIZE] = { + DDRPHY_REG_TIMING(ptr0), + DDRPHY_REG_TIMING(ptr1), + DDRPHY_REG_TIMING(ptr2), + DDRPHY_REG_TIMING(dtpr0), + DDRPHY_REG_TIMING(dtpr1), + DDRPHY_REG_TIMING(dtpr2), + DDRPHY_REG_TIMING(mr0), + DDRPHY_REG_TIMING(mr1), + DDRPHY_REG_TIMING(mr2), + DDRPHY_REG_TIMING(mr3), +}; + +/* + * REGISTERS ARRAY: used to parse device tree and interactive mode + */ +static const struct stm32mp_ddr_reg_info ddr_registers[REG_TYPE_NB] = { + [REG_REG] = { + .name = "static", + .desc = ddr_reg, + .size = DDRCTL_REG_REG_SIZE, + .base = DDR_BASE + }, + [REG_TIMING] = { + .name = "timing", + .desc = ddr_timing, + .size = DDRCTL_REG_TIMING_SIZE, + .base = DDR_BASE + }, + [REG_PERF] = { + .name = "perf", + .desc = ddr_perf, + .size = DDRCTL_REG_PERF_SIZE, + .base = DDR_BASE + }, + [REG_MAP] = { + .name = "map", + .desc = ddr_map, + .size = DDRCTL_REG_MAP_SIZE, + .base = DDR_BASE + }, + [REGPHY_REG] = { + .name = "static", + .desc = ddrphy_reg, + .size = DDRPHY_REG_REG_SIZE, + .base = DDRPHY_BASE + }, + [REGPHY_TIMING] = { + .name = "timing", + .desc = ddrphy_timing, + .size = DDRPHY_REG_TIMING_SIZE, + .base = DDRPHY_BASE + }, +}; + +static void stm32mp1_ddrphy_idone_wait(struct stm32mp_ddrphy *phy) +{ + uint32_t pgsr; + int error = 0; + uint64_t timeout = timeout_init_us(TIMEOUT_US_1S); + + do { + pgsr = mmio_read_32((uintptr_t)&phy->pgsr); + + VERBOSE(" > [0x%lx] pgsr = 0x%x &\n", + (uintptr_t)&phy->pgsr, pgsr); + + if (timeout_elapsed(timeout)) { + panic(); + } + + if ((pgsr & DDRPHYC_PGSR_DTERR) != 0U) { + VERBOSE("DQS Gate Trainig Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_DTIERR) != 0U) { + VERBOSE("DQS Gate Trainig Intermittent Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_DFTERR) != 0U) { + VERBOSE("DQS Drift Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_RVERR) != 0U) { + VERBOSE("Read Valid Training Error\n"); + error++; + } + + if ((pgsr & DDRPHYC_PGSR_RVEIRR) != 0U) { + VERBOSE("Read Valid Training Intermittent Error\n"); + error++; + } + } while (((pgsr & DDRPHYC_PGSR_IDONE) == 0U) && (error == 0)); + VERBOSE("\n[0x%lx] pgsr = 0x%x\n", + (uintptr_t)&phy->pgsr, pgsr); +} + +static void stm32mp1_ddrphy_init(struct stm32mp_ddrphy *phy, uint32_t pir) +{ + uint32_t pir_init = pir | DDRPHYC_PIR_INIT; + + mmio_write_32((uintptr_t)&phy->pir, pir_init); + VERBOSE("[0x%lx] pir = 0x%x -> 0x%x\n", + (uintptr_t)&phy->pir, pir_init, + mmio_read_32((uintptr_t)&phy->pir)); + + /* Need to wait 10 configuration clock before start polling */ + udelay(10); + + /* Wait DRAM initialization and Gate Training Evaluation complete */ + stm32mp1_ddrphy_idone_wait(phy); +} + +/* Wait quasi dynamic register update */ +static void stm32mp1_wait_operating_mode(struct stm32mp_ddr_priv *priv, uint32_t mode) +{ + uint64_t timeout; + uint32_t stat; + int break_loop = 0; + + timeout = timeout_init_us(TIMEOUT_US_1S); + for ( ; ; ) { + uint32_t operating_mode; + uint32_t selref_type; + + stat = mmio_read_32((uintptr_t)&priv->ctl->stat); + operating_mode = stat & DDRCTRL_STAT_OPERATING_MODE_MASK; + selref_type = stat & DDRCTRL_STAT_SELFREF_TYPE_MASK; + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); + if (timeout_elapsed(timeout)) { + panic(); + } + + if (mode == DDRCTRL_STAT_OPERATING_MODE_SR) { + /* + * Self-refresh due to software + * => checking also STAT.selfref_type. + */ + if ((operating_mode == + DDRCTRL_STAT_OPERATING_MODE_SR) && + (selref_type == DDRCTRL_STAT_SELFREF_TYPE_SR)) { + break_loop = 1; + } + } else if (operating_mode == mode) { + break_loop = 1; + } else if ((mode == DDRCTRL_STAT_OPERATING_MODE_NORMAL) && + (operating_mode == DDRCTRL_STAT_OPERATING_MODE_SR) && + (selref_type == DDRCTRL_STAT_SELFREF_TYPE_ASR)) { + /* Normal mode: handle also automatic self refresh */ + break_loop = 1; + } + + if (break_loop == 1) { + break; + } + } + + VERBOSE("[0x%lx] stat = 0x%x\n", + (uintptr_t)&priv->ctl->stat, stat); +} + +/* Mode Register Writes (MRW or MRS) */ +static void stm32mp1_mode_register_write(struct stm32mp_ddr_priv *priv, uint8_t addr, + uint32_t data) +{ + uint32_t mrctrl0; + + VERBOSE("MRS: %d = %x\n", addr, data); + + /* + * 1. Poll MRSTAT.mr_wr_busy until it is '0'. + * This checks that there is no outstanding MR transaction. + * No write should be performed to MRCTRL0 and MRCTRL1 + * if MRSTAT.mr_wr_busy = 1. + */ + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & + DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { + ; + } + + /* + * 2. Write the MRCTRL0.mr_type, MRCTRL0.mr_addr, MRCTRL0.mr_rank + * and (for MRWs) MRCTRL1.mr_data to define the MR transaction. + */ + mrctrl0 = DDRCTRL_MRCTRL0_MR_TYPE_WRITE | + DDRCTRL_MRCTRL0_MR_RANK_ALL | + (((uint32_t)addr << DDRCTRL_MRCTRL0_MR_ADDR_SHIFT) & + DDRCTRL_MRCTRL0_MR_ADDR_MASK); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); + VERBOSE("[0x%lx] mrctrl0 = 0x%x (0x%x)\n", + (uintptr_t)&priv->ctl->mrctrl0, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl0), mrctrl0); + mmio_write_32((uintptr_t)&priv->ctl->mrctrl1, data); + VERBOSE("[0x%lx] mrctrl1 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl1, + mmio_read_32((uintptr_t)&priv->ctl->mrctrl1)); + + /* + * 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 access can be + * initiated until it is deasserted. + */ + mrctrl0 |= DDRCTRL_MRCTRL0_MR_WR; + mmio_write_32((uintptr_t)&priv->ctl->mrctrl0, mrctrl0); + + while ((mmio_read_32((uintptr_t)&priv->ctl->mrstat) & + DDRCTRL_MRSTAT_MR_WR_BUSY) != 0U) { + ; + } + + VERBOSE("[0x%lx] mrctrl0 = 0x%x\n", + (uintptr_t)&priv->ctl->mrctrl0, mrctrl0); +} + +/* Switch DDR3 from DLL-on to DLL-off */ +static void stm32mp1_ddr3_dll_off(struct stm32mp_ddr_priv *priv) +{ + uint32_t mr1 = mmio_read_32((uintptr_t)&priv->phy->mr1); + uint32_t mr2 = mmio_read_32((uintptr_t)&priv->phy->mr2); + uint32_t dbgcam; + + VERBOSE("mr1: 0x%x\n", mr1); + VERBOSE("mr2: 0x%x\n", mr2); + + /* + * 1. Set the DBG1.dis_hif = 1. + * This prevents further reads/writes being received on the HIF. + */ + mmio_setbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); + + /* + * 2. Ensure all commands have been flushed from the uMCTL2 by polling + * DBGCAM.wr_data_pipeline_empty = 1, + * DBGCAM.rd_data_pipeline_empty = 1, + * DBGCAM.dbg_wr_q_depth = 0 , + * DBGCAM.dbg_lpr_q_depth = 0, and + * DBGCAM.dbg_hpr_q_depth = 0. + */ + do { + dbgcam = mmio_read_32((uintptr_t)&priv->ctl->dbgcam); + VERBOSE("[0x%lx] dbgcam = 0x%x\n", + (uintptr_t)&priv->ctl->dbgcam, dbgcam); + } while ((((dbgcam & DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY) == + DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY)) && + ((dbgcam & DDRCTRL_DBGCAM_DBG_Q_DEPTH) == 0U)); + + /* + * 3. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to disable RTT_NOM: + * a. DDR3: Write to MR1[9], MR1[6] and MR1[2] + * b. DDR4: Write to MR1[10:8] + */ + mr1 &= ~(BIT(9) | BIT(6) | BIT(2)); + stm32mp1_mode_register_write(priv, 1, mr1); + + /* + * 4. For DDR4 only: Perform an MRS command + * (using MRCTRL0 and MRCTRL1 registers) to write to MR5[8:6] + * to disable RTT_PARK + */ + + /* + * 5. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to write to MR2[10:9], to disable RTT_WR + * (and therefore disable dynamic ODT). + * This applies for both DDR3 and DDR4. + */ + mr2 &= ~GENMASK(10, 9); + stm32mp1_mode_register_write(priv, 2, mr2); + + /* + * 6. Perform an MRS command (using MRCTRL0 and MRCTRL1 registers) + * to disable the DLL. The timing of this MRS is automatically + * handled by the uMCTL2. + * a. DDR3: Write to MR1[0] + * b. DDR4: Write to MR1[0] + */ + mr1 |= BIT(0); + stm32mp1_mode_register_write(priv, 1, mr1); + + /* + * 7. Put the SDRAM into self-refresh mode by setting + * PWRCTL.selfref_sw = 1, and polling STAT.operating_mode to ensure + * the DDRC has entered self-refresh. + */ + mmio_setbits_32((uintptr_t)&priv->ctl->pwrctl, + DDRCTRL_PWRCTL_SELFREF_SW); + VERBOSE("[0x%lx] pwrctl = 0x%x\n", + (uintptr_t)&priv->ctl->pwrctl, + mmio_read_32((uintptr_t)&priv->ctl->pwrctl)); + + /* + * 8. Wait until STAT.operating_mode[1:0]==11 indicating that the + * DWC_ddr_umctl2 core is in self-refresh mode. + * Ensure transition to self-refresh was due to software + * by checking that STAT.selfref_type[1:0]=2. + */ + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_SR); + + /* + * 9. Set the MSTR.dll_off_mode = 1. + * warning: MSTR.dll_off_mode is a quasi-dynamic type 2 field + */ + stm32mp_ddr_start_sw_done(priv->ctl); + + mmio_setbits_32((uintptr_t)&priv->ctl->mstr, DDRCTRL_MSTR_DLL_OFF_MODE); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); + + stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* 10. Change the clock frequency to the desired value. */ + + /* + * 11. Update any registers which may be required to change for the new + * frequency. This includes static and dynamic registers. + * This includes both uMCTL2 registers and PHY registers. + */ + + /* Change Bypass Mode Frequency Range */ + if (clk_get_rate(DDRPHYC) < 100000000U) { + mmio_clrbits_32((uintptr_t)&priv->phy->dllgcr, + DDRPHYC_DLLGCR_BPS200); + } else { + mmio_setbits_32((uintptr_t)&priv->phy->dllgcr, + DDRPHYC_DLLGCR_BPS200); + } + + mmio_setbits_32((uintptr_t)&priv->phy->acdllcr, DDRPHYC_ACDLLCR_DLLDIS); + + mmio_setbits_32((uintptr_t)&priv->phy->dx0dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx1dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); +#if STM32MP_DDR_32BIT_INTERFACE + mmio_setbits_32((uintptr_t)&priv->phy->dx2dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); + mmio_setbits_32((uintptr_t)&priv->phy->dx3dllcr, + DDRPHYC_DXNDLLCR_DLLDIS); +#endif + + /* 12. Exit the self-refresh state by setting PWRCTL.selfref_sw = 0. */ + mmio_clrbits_32((uintptr_t)&priv->ctl->pwrctl, + DDRCTRL_PWRCTL_SELFREF_SW); + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* + * 13. If ZQCTL0.dis_srx_zqcl = 0, the uMCTL2 performs a ZQCL command + * at this point. + */ + + /* + * 14. 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). + */ + + /* 15. Write DBG1.dis_hif = 0 to re-enable reads and writes. */ + mmio_clrbits_32((uintptr_t)&priv->ctl->dbg1, DDRCTRL_DBG1_DIS_HIF); + VERBOSE("[0x%lx] dbg1 = 0x%x\n", + (uintptr_t)&priv->ctl->dbg1, + mmio_read_32((uintptr_t)&priv->ctl->dbg1)); +} + +static void stm32mp1_refresh_disable(struct stm32mp_ddrctl *ctl) +{ + stm32mp_ddr_start_sw_done(ctl); + /* Quasi-dynamic register update*/ + mmio_setbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); + mmio_clrbits_32((uintptr_t)&ctl->pwrctl, DDRCTRL_PWRCTL_POWERDOWN_EN); + mmio_clrbits_32((uintptr_t)&ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + stm32mp_ddr_wait_sw_done_ack(ctl); +} + +static void stm32mp1_refresh_restore(struct stm32mp_ddrctl *ctl, + uint32_t rfshctl3, uint32_t pwrctl) +{ + stm32mp_ddr_start_sw_done(ctl); + if ((rfshctl3 & DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH) == 0U) { + mmio_clrbits_32((uintptr_t)&ctl->rfshctl3, + DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH); + } + if ((pwrctl & DDRCTRL_PWRCTL_POWERDOWN_EN) != 0U) { + mmio_setbits_32((uintptr_t)&ctl->pwrctl, + DDRCTRL_PWRCTL_POWERDOWN_EN); + } + mmio_setbits_32((uintptr_t)&ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + stm32mp_ddr_wait_sw_done_ack(ctl); +} + +void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, + struct stm32mp_ddr_config *config) +{ + uint32_t pir; + int ret = -EINVAL; + + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_DDR3); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR2) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR2); + } else if ((config->c_reg.mstr & DDRCTRL_MSTR_LPDDR3) != 0U) { + ret = stm32mp_board_ddr_power_init(STM32MP_LPDDR3); + } else { + ERROR("DDR type not supported\n"); + } + + if (ret != 0) { + panic(); + } + + VERBOSE("name = %s\n", config->info.name); + VERBOSE("speed = %u kHz\n", config->info.speed); + VERBOSE("size = 0x%x\n", config->info.size); + + /* DDR INIT SEQUENCE */ + + /* + * 1. Program the DWC_ddr_umctl2 registers + * nota: check DFIMISC.dfi_init_complete = 0 + */ + + /* 1.1 RESETS: presetn, core_ddrc_rstn, aresetn */ + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + + /* 1.2. start CLOCK */ + if (stm32mp1_ddr_clk_enable(priv, config->info.speed) != 0) { + panic(); + } + + /* 1.3. deassert reset */ + /* De-assert PHY rstn and ctl_rstn via DPHYRST and DPHYCTLRST. */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYRST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYCTLRST); + /* + * De-assert presetn once the clocks are active + * and stable via DDRCAPBRST bit. + */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAPBRST); + + /* 1.4. wait 128 cycles to permit initialization of end logic */ + udelay(2); + /* For PCLK = 133MHz => 1 us is enough, 2 to allow lower frequency */ + + /* 1.5. initialize registers ddr_umctl2 */ + /* Stop uMCTL2 before PHY is ready */ + mmio_clrbits_32((uintptr_t)&priv->ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + + stm32mp_ddr_set_reg(priv, REG_REG, &config->c_reg, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & + (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) + == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { + VERBOSE("deactivate DLL OFF in mstr\n"); + mmio_clrbits_32((uintptr_t)&priv->ctl->mstr, + DDRCTRL_MSTR_DLL_OFF_MODE); + VERBOSE("[0x%lx] mstr = 0x%x\n", + (uintptr_t)&priv->ctl->mstr, + mmio_read_32((uintptr_t)&priv->ctl->mstr)); + } + + stm32mp_ddr_set_reg(priv, REG_TIMING, &config->c_timing, ddr_registers); + stm32mp_ddr_set_reg(priv, REG_MAP, &config->c_map, ddr_registers); + + /* Skip CTRL init, SDRAM init is done by PHY PUBL */ + mmio_clrsetbits_32((uintptr_t)&priv->ctl->init0, + DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK, + DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL); + VERBOSE("[0x%lx] init0 = 0x%x\n", + (uintptr_t)&priv->ctl->init0, + mmio_read_32((uintptr_t)&priv->ctl->init0)); + + stm32mp_ddr_set_reg(priv, REG_PERF, &config->c_perf, ddr_registers); + + /* 2. deassert reset signal core_ddrc_rstn, aresetn and presetn */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCORERST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DDRCAXIRST); + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_DPHYAPBRST); + + /* + * 3. start PHY init by accessing relevant PUBL registers + * (DXGCR, DCR, PTR*, MR*, DTPR*) + */ + stm32mp_ddr_set_reg(priv, REGPHY_REG, &config->p_reg, ddr_registers); + stm32mp_ddr_set_reg(priv, REGPHY_TIMING, &config->p_timing, ddr_registers); + + /* DDR3 = don't set DLLOFF for init mode */ + if ((config->c_reg.mstr & + (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) + == (DDRCTRL_MSTR_DDR3 | DDRCTRL_MSTR_DLL_OFF_MODE)) { + VERBOSE("deactivate DLL OFF in mr1\n"); + mmio_clrbits_32((uintptr_t)&priv->phy->mr1, BIT(0)); + VERBOSE("[0x%lx] mr1 = 0x%x\n", + (uintptr_t)&priv->phy->mr1, + mmio_read_32((uintptr_t)&priv->phy->mr1)); + } + + /* + * 4. Monitor PHY init status by polling PUBL register PGSR.IDONE + * Perform DDR PHY DRAM initialization and Gate Training Evaluation + */ + stm32mp1_ddrphy_idone_wait(priv->phy); + + /* + * 5. Indicate to PUBL that controller performs SDRAM initialization + * by setting PIR.INIT and PIR CTLDINIT and pool PGSR.IDONE + * DRAM init is done by PHY, init0.skip_dram.init = 1 + */ + + pir = DDRPHYC_PIR_DLLSRST | DDRPHYC_PIR_DLLLOCK | DDRPHYC_PIR_ZCAL | + DDRPHYC_PIR_ITMSRST | DDRPHYC_PIR_DRAMINIT | DDRPHYC_PIR_ICPC; + + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) != 0U) { + pir |= DDRPHYC_PIR_DRAMRST; /* Only for DDR3 */ + } + + stm32mp1_ddrphy_init(priv->phy, pir); + + /* + * 6. SET DFIMISC.dfi_init_complete_en to 1 + * Enable quasi-dynamic register programming. + */ + stm32mp_ddr_start_sw_done(priv->ctl); + + mmio_setbits_32((uintptr_t)&priv->ctl->dfimisc, + DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN); + VERBOSE("[0x%lx] dfimisc = 0x%x\n", + (uintptr_t)&priv->ctl->dfimisc, + mmio_read_32((uintptr_t)&priv->ctl->dfimisc)); + + stm32mp_ddr_wait_sw_done_ack(priv->ctl); + + /* + * 7. Wait for DWC_ddr_umctl2 to move to normal operation mode + * by monitoring STAT.operating_mode signal + */ + + /* Wait uMCTL2 ready */ + stm32mp1_wait_operating_mode(priv, DDRCTRL_STAT_OPERATING_MODE_NORMAL); + + /* Switch to DLL OFF mode */ + if ((config->c_reg.mstr & DDRCTRL_MSTR_DLL_OFF_MODE) != 0U) { + stm32mp1_ddr3_dll_off(priv); + } + + VERBOSE("DDR DQS training : "); + + /* + * 8. Disable Auto refresh and power down by setting + * - RFSHCTL3.dis_au_refresh = 1 + * - PWRCTL.powerdown_en = 0 + * - DFIMISC.dfiinit_complete_en = 0 + */ + stm32mp1_refresh_disable(priv->ctl); + + /* + * 9. Program PUBL PGCR to enable refresh during training + * and rank to train + * not done => keep the programed value in PGCR + */ + + /* + * 10. configure PUBL PIR register to specify which training step + * to run + * RVTRN is executed only on LPDDR2/LPDDR3 + */ + pir = DDRPHYC_PIR_QSTRN; + if ((config->c_reg.mstr & DDRCTRL_MSTR_DDR3) == 0U) { + pir |= DDRPHYC_PIR_RVTRN; + } + + stm32mp1_ddrphy_init(priv->phy, pir); + + /* 11. monitor PUB PGSR.IDONE to poll cpmpletion of training sequence */ + stm32mp1_ddrphy_idone_wait(priv->phy); + + /* + * 12. set back registers in step 8 to the orginal values if desidered + */ + stm32mp1_refresh_restore(priv->ctl, config->c_reg.rfshctl3, + config->c_reg.pwrctl); + + stm32mp_ddr_enable_axi_port(priv->ctl); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c new file mode 100644 index 0000000..e0621b5 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +void ddr_enable_clock(void) +{ + stm32mp1_clk_rcc_regs_lock(); + + mmio_setbits_32(stm32mp_rcc_base() + RCC_DDRITFCR, + RCC_DDRITFCR_DDRC1EN | +#if STM32MP_DDR_DUAL_AXI_PORT + RCC_DDRITFCR_DDRC2EN | +#endif + RCC_DDRITFCR_DDRPHYCEN | + RCC_DDRITFCR_DDRPHYCAPBEN | + RCC_DDRITFCR_DDRCAPBEN); + + stm32mp1_clk_rcc_regs_unlock(); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c new file mode 100644 index 0000000..b510c8f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c @@ -0,0 +1,151 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +static struct stm32mp_ddr_priv ddr_priv_data; + +int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed) +{ + unsigned long ddrphy_clk, ddr_clk, mem_speed_hz; + + ddr_enable_clock(); + + ddrphy_clk = clk_get_rate(DDRPHYC); + + VERBOSE("DDR: mem_speed (%u kHz), RCC %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + + mem_speed_hz = mem_speed * 1000U; + + /* Max 10% frequency delta */ + if (ddrphy_clk > mem_speed_hz) { + ddr_clk = ddrphy_clk - mem_speed_hz; + } else { + ddr_clk = mem_speed_hz - ddrphy_clk; + } + if (ddr_clk > (mem_speed_hz / 10)) { + ERROR("DDR expected freq %u kHz, current is %lu kHz\n", + mem_speed, ddrphy_clk / 1000U); + return -1; + } + return 0; +} + +static int stm32mp1_ddr_setup(void) +{ + struct stm32mp_ddr_priv *priv = &ddr_priv_data; + int ret; + struct stm32mp_ddr_config config; + int node; + uint32_t uret; + void *fdt; + + const struct stm32mp_ddr_param param[] = { + CTL_PARAM(reg), + CTL_PARAM(timing), + CTL_PARAM(map), + CTL_PARAM(perf), + PHY_PARAM(reg), + PHY_PARAM(timing), + }; + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_DDR_COMPAT); + if (node < 0) { + ERROR("%s: Cannot read DDR node in DT\n", __func__); + return -EINVAL; + } + + ret = stm32mp_ddr_dt_get_info(fdt, node, &config.info); + if (ret < 0) { + return ret; + } + + ret = stm32mp_ddr_dt_get_param(fdt, node, param, ARRAY_SIZE(param), (uintptr_t)&config); + if (ret < 0) { + return ret; + } + + /* Disable axidcg clock gating during init */ + mmio_clrbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); + + stm32mp1_ddr_init(priv, &config); + + /* Enable axidcg clock gating */ + mmio_setbits_32(priv->rcc + RCC_DDRITFCR, RCC_DDRITFCR_AXIDCGEN); + + priv->info.size = config.info.size; + + VERBOSE("%s : ram size(%x, %x)\n", __func__, + (uint32_t)priv->info.base, (uint32_t)priv->info.size); + + if (stm32mp_map_ddr_non_cacheable() != 0) { + panic(); + } + + uret = stm32mp_ddr_test_data_bus(); + if (uret != 0U) { + ERROR("DDR data bus test: can't access memory @ 0x%x\n", + uret); + panic(); + } + + uret = stm32mp_ddr_test_addr_bus(config.info.size); + if (uret != 0U) { + ERROR("DDR addr bus test: can't access memory @ 0x%x\n", + uret); + panic(); + } + + uret = stm32mp_ddr_check_size(); + if (uret < config.info.size) { + ERROR("DDR size: 0x%x does not match DT config: 0x%x\n", + uret, config.info.size); + panic(); + } + + if (stm32mp_unmap_ddr() != 0) { + panic(); + } + + return 0; +} + +int stm32mp1_ddr_probe(void) +{ + struct stm32mp_ddr_priv *priv = &ddr_priv_data; + + VERBOSE("STM32MP DDR probe\n"); + + priv->ctl = (struct stm32mp_ddrctl *)stm32mp_ddrctrl_base(); + priv->phy = (struct stm32mp_ddrphy *)stm32mp_ddrphyc_base(); + priv->pwr = stm32mp_pwr_base(); + priv->rcc = stm32mp_rcc_base(); + + priv->info.base = STM32MP_DDR_BASE; + priv->info.size = 0; + + return stm32mp1_ddr_setup(); +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c new file mode 100644 index 0000000..6776e3b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define INVALID_OFFSET 0xFFU + +static uintptr_t get_base_addr(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_base_type base) +{ + if (base == DDRPHY_BASE) { + return (uintptr_t)priv->phy; + } else { + return (uintptr_t)priv->ctl; + } +} + +void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, + const void *param, const struct stm32mp_ddr_reg_info *ddr_registers) +{ + unsigned int i; + unsigned int value; + enum stm32mp_ddr_base_type base = ddr_registers[type].base; + uintptr_t base_addr = get_base_addr(priv, base); + const struct stm32mp_ddr_reg_desc *desc = ddr_registers[type].desc; + + VERBOSE("init %s\n", ddr_registers[type].name); + for (i = 0; i < ddr_registers[type].size; i++) { + uintptr_t ptr = base_addr + desc[i].offset; + + if (desc[i].par_offset == INVALID_OFFSET) { + ERROR("invalid parameter offset for %s", desc[i].name); + panic(); + } else { + value = *((uint32_t *)((uintptr_t)param + + desc[i].par_offset)); + mmio_write_32(ptr, value); + } + } +} + +/* Start quasi dynamic register update */ +void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl) +{ + mmio_clrbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); +} + +/* Wait quasi dynamic register update */ +void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl) +{ + uint64_t timeout; + uint32_t swstat; + + mmio_setbits_32((uintptr_t)&ctl->swctl, DDRCTRL_SWCTL_SW_DONE); + VERBOSE("[0x%lx] swctl = 0x%x\n", + (uintptr_t)&ctl->swctl, mmio_read_32((uintptr_t)&ctl->swctl)); + + timeout = timeout_init_us(TIMEOUT_US_1S); + do { + swstat = mmio_read_32((uintptr_t)&ctl->swstat); + VERBOSE("[0x%lx] swstat = 0x%x ", + (uintptr_t)&ctl->swstat, swstat); + if (timeout_elapsed(timeout)) { + panic(); + } + } while ((swstat & DDRCTRL_SWSTAT_SW_DONE_ACK) == 0U); + + VERBOSE("[0x%lx] swstat = 0x%x\n", + (uintptr_t)&ctl->swstat, swstat); +} + +void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl) +{ + /* Enable uMCTL2 AXI port 0 */ + mmio_setbits_32((uintptr_t)&ctl->pctrl_0, DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_0 = 0x%x\n", (uintptr_t)&ctl->pctrl_0, + mmio_read_32((uintptr_t)&ctl->pctrl_0)); + +#if STM32MP_DDR_DUAL_AXI_PORT + /* Enable uMCTL2 AXI port 1 */ + mmio_setbits_32((uintptr_t)&ctl->pctrl_1, DDRCTRL_PCTRL_N_PORT_EN); + VERBOSE("[0x%lx] pctrl_1 = 0x%x\n", (uintptr_t)&ctl->pctrl_1, + mmio_read_32((uintptr_t)&ctl->pctrl_1)); +#endif + +} + +int stm32mp_board_ddr_power_init(enum ddr_type ddr_type) +{ + if (dt_pmic_status() > 0) { + return pmic_ddr_power_init(ddr_type); + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c new file mode 100644 index 0000000..6733cc6 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#define DDR_PATTERN 0xAAAAAAAAU +#define DDR_ANTIPATTERN 0x55555555U + +/******************************************************************************* + * This function tests a simple read/write access to the DDR. + * Note that the previous content is restored after test. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_rw_access(void) +{ + uint32_t saved_value = mmio_read_32(STM32MP_DDR_BASE); + + mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + return (uint32_t)STM32MP_DDR_BASE; + } + + mmio_write_32(STM32MP_DDR_BASE, saved_value); + + return 0U; +} + +/******************************************************************************* + * This function tests the DDR data bus wiring. + * This is inspired from the Data Bus Test algorithm written by Michael Barr + * in "Programming Embedded Systems in C and C++" book. + * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ + * File: memtest.c - This source code belongs to Public Domain. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_data_bus(void) +{ + uint32_t pattern; + + for (pattern = 1U; pattern != 0U; pattern <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE, pattern); + + if (mmio_read_32(STM32MP_DDR_BASE) != pattern) { + return (uint32_t)STM32MP_DDR_BASE; + } + } + + return 0; +} + +/******************************************************************************* + * This function tests the DDR address bus wiring. + * This is inspired from the Data Bus Test algorithm written by Michael Barr + * in "Programming Embedded Systems in C and C++" book. + * resources.oreilly.com/examples/9781565923546/blob/master/Chapter6/ + * File: memtest.c - This source code belongs to Public Domain. + * size: size in bytes of the DDR memory device. + * Returns 0 if success, and address value else. + ******************************************************************************/ +uint32_t stm32mp_ddr_test_addr_bus(uint64_t size) +{ + uint64_t addressmask = size - 1U; + uint64_t offset; + uint64_t testoffset = 0U; + + /* Write the default pattern at each of the power-of-two offsets. */ + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)offset, + DDR_PATTERN); + } + + /* Check for address bits stuck high. */ + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_ANTIPATTERN); + + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1U) { + if (mmio_read_32(STM32MP_DDR_BASE + (uint32_t)offset) != + DDR_PATTERN) { + return (uint32_t)(STM32MP_DDR_BASE + offset); + } + } + + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, DDR_PATTERN); + + /* Check for address bits stuck low or shorted. */ + for (testoffset = sizeof(uint32_t); (testoffset & addressmask) != 0U; + testoffset <<= 1U) { + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_ANTIPATTERN); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + return STM32MP_DDR_BASE; + } + + for (offset = sizeof(uint32_t); (offset & addressmask) != 0U; + offset <<= 1) { + if ((mmio_read_32(STM32MP_DDR_BASE + + (uint32_t)offset) != DDR_PATTERN) && + (offset != testoffset)) { + return (uint32_t)(STM32MP_DDR_BASE + offset); + } + } + + mmio_write_32(STM32MP_DDR_BASE + (uint32_t)testoffset, + DDR_PATTERN); + } + + return 0U; +} + +/******************************************************************************* + * This function checks the DDR size. It has to be run with Data Cache off. + * This test is run before data have been put in DDR, and is only done for + * cold boot. The DDR data can then be overwritten, and it is not useful to + * restore its content. + * Returns DDR computed size. + ******************************************************************************/ +uint32_t stm32mp_ddr_check_size(void) +{ + uint32_t offset = sizeof(uint32_t); + + mmio_write_32(STM32MP_DDR_BASE, DDR_PATTERN); + + while (offset < STM32MP_DDR_MAX_SIZE) { + mmio_write_32(STM32MP_DDR_BASE + offset, DDR_ANTIPATTERN); + dsb(); + + if (mmio_read_32(STM32MP_DDR_BASE) != DDR_PATTERN) { + break; + } + + offset <<= 1U; + } + + INFO("Memory size = 0x%x (%u MB)\n", offset, offset / (1024U * 1024U)); + + return offset; +} diff --git a/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c new file mode 100644 index 0000000..0804568 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include + +int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info) +{ + int ret; + + ret = fdt_read_uint32(fdt, node, "st,mem-speed", &info->speed); + if (ret < 0) { + VERBOSE("%s: no st,mem-speed\n", __func__); + return -EINVAL; + } + ret = fdt_read_uint32(fdt, node, "st,mem-size", &info->size); + if (ret < 0) { + VERBOSE("%s: no st,mem-size\n", __func__); + return -EINVAL; + } + info->name = fdt_getprop(fdt, node, "st,mem-name", NULL); + if (info->name == NULL) { + VERBOSE("%s: no st,mem-name\n", __func__); + return -EINVAL; + } + + INFO("RAM: %s\n", info->name); + + return 0; +} + +int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, + uint32_t param_size, uintptr_t config) +{ + int ret; + uint32_t idx; + + for (idx = 0U; idx < param_size; idx++) { + ret = fdt_read_uint32_array(fdt, node, param[idx].name, param[idx].size, + (void *)(config + param[idx].offset)); + + VERBOSE("%s: %s[0x%x] = %d\n", __func__, param[idx].name, param[idx].size, ret); + if (ret != 0) { + ERROR("%s: Cannot read %s, error=%d\n", __func__, param[idx].name, ret); + return -EINVAL; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/etzpc/etzpc.c b/arm-trusted-firmware/drivers/st/etzpc/etzpc.c new file mode 100644 index 0000000..ff52a22 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/etzpc/etzpc.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Device Tree related definitions */ +#define ETZPC_COMPAT "st,stm32-etzpc" +#define ETZPC_LOCK_MASK 0x1U +#define ETZPC_MODE_SHIFT 8 +#define ETZPC_MODE_MASK GENMASK(1, 0) +#define ETZPC_ID_SHIFT 16 +#define ETZPC_ID_MASK GENMASK(7, 0) + +/* ID Registers */ +#define ETZPC_TZMA0_SIZE 0x000U +#define ETZPC_DECPROT0 0x010U +#define ETZPC_DECPROT_LOCK0 0x030U +#define ETZPC_HWCFGR 0x3F0U +#define ETZPC_VERR 0x3F4U + +/* ID Registers fields */ +#define ETZPC_TZMA0_SIZE_LOCK BIT(31) +#define ETZPC_DECPROT0_MASK GENMASK(1, 0) +#define ETZPC_HWCFGR_NUM_TZMA_SHIFT 0 +#define ETZPC_HWCFGR_NUM_PER_SEC_SHIFT 8 +#define ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT 16 +#define ETZPC_HWCFGR_CHUNCKS1N4_SHIFT 24 + +#define DECPROT_SHIFT 1 +#define IDS_PER_DECPROT_REGS 16U +#define IDS_PER_DECPROT_LOCK_REGS 32U + +/* + * etzpc_instance. + * base : register base address set during init given by user + * chunk_size : supported TZMA size steps + * num_tzma: number of TZMA zone read from register at init + * num_ahb_sec : number of securable AHB master zone read from register + * num_per_sec : number of securable AHB & APB Peripherals read from register + * revision : IP revision read from register at init + */ +struct etzpc_instance { + uintptr_t base; + uint8_t chunck_size; + uint8_t num_tzma; + uint8_t num_per_sec; + uint8_t num_ahb_sec; + uint8_t revision; +}; + +/* Only 1 instance of the ETZPC is expected per platform */ +static struct etzpc_instance etzpc_dev; + +/* + * Implementation uses uint8_t to store each securable DECPROT configuration. + * When resuming from deep suspend, the DECPROT configurations are restored. + */ +#define PERIPH_LOCK_BIT BIT(7) +#define PERIPH_ATTR_MASK GENMASK(2, 0) + +#if ENABLE_ASSERTIONS +static bool valid_decprot_id(unsigned int id) +{ + return id < (unsigned int)etzpc_dev.num_per_sec; +} + +static bool valid_tzma_id(unsigned int id) +{ + return id < (unsigned int)etzpc_dev.num_tzma; +} +#endif + +/* + * etzpc_configure_decprot : Load a DECPROT configuration + * decprot_id : ID of the IP + * decprot_attr : Restriction access attribute + */ +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + uint32_t masked_decprot = (uint32_t)decprot_attr & ETZPC_DECPROT0_MASK; + + assert(valid_decprot_id(decprot_id)); + + mmio_clrsetbits_32(etzpc_dev.base + ETZPC_DECPROT0 + offset, + (uint32_t)ETZPC_DECPROT0_MASK << shift, + masked_decprot << shift); +} + +/* + * etzpc_get_decprot : Get the DECPROT attribute + * decprot_id : ID of the IP + * return : Attribute of this DECPROT + */ +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_REGS); + uint32_t shift = (decprot_id % IDS_PER_DECPROT_REGS) << DECPROT_SHIFT; + uintptr_t base_decprot = etzpc_dev.base + offset; + uint32_t value; + + assert(valid_decprot_id(decprot_id)); + + value = (mmio_read_32(base_decprot + ETZPC_DECPROT0) >> shift) & + ETZPC_DECPROT0_MASK; + + return (enum etzpc_decprot_attributes)value; +} + +/* + * etzpc_lock_decprot : Lock access to the DECPROT attribute + * decprot_id : ID of the IP + */ +void etzpc_lock_decprot(uint32_t decprot_id) +{ + uintptr_t offset = 4U * (decprot_id / IDS_PER_DECPROT_LOCK_REGS); + uint32_t shift = BIT(decprot_id % IDS_PER_DECPROT_LOCK_REGS); + uintptr_t base_decprot = etzpc_dev.base + offset; + + assert(valid_decprot_id(decprot_id)); + + mmio_write_32(base_decprot + ETZPC_DECPROT_LOCK0, shift); +} + +/* + * etzpc_configure_tzma : Configure the target TZMA read only size + * tzma_id : ID of the memory + * tzma_value : read-only size + */ +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value) +{ + assert(valid_tzma_id(tzma_id)); + + mmio_write_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id), tzma_value); +} + +/* + * etzpc_get_tzma : Get the target TZMA read only size + * tzma_id : TZMA ID + * return : Size of read only size + */ +uint16_t etzpc_get_tzma(uint32_t tzma_id) +{ + assert(valid_tzma_id(tzma_id)); + + return (uint16_t)mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id)); +} + +/* + * etzpc_lock_tzma : Lock the target TZMA + * tzma_id : TZMA ID + */ +void etzpc_lock_tzma(uint32_t tzma_id) +{ + assert(valid_tzma_id(tzma_id)); + + mmio_setbits_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id), ETZPC_TZMA0_SIZE_LOCK); +} + +/* + * etzpc_get_lock_tzma : Return the lock status of the target TZMA + * tzma_id : TZMA ID + * return : True if TZMA is locked, false otherwise + */ +bool etzpc_get_lock_tzma(uint32_t tzma_id) +{ + uint32_t tzma_size; + + assert(valid_tzma_id(tzma_id)); + + tzma_size = mmio_read_32(etzpc_dev.base + ETZPC_TZMA0_SIZE + + (sizeof(uint32_t) * tzma_id)); + + return (tzma_size & ETZPC_TZMA0_SIZE_LOCK) != 0; +} + +/* + * etzpc_get_num_per_sec : Return the DECPROT ID limit value + */ +uint8_t etzpc_get_num_per_sec(void) +{ + return etzpc_dev.num_per_sec; +} + +/* + * etzpc_get_revision : Return the ETZPC IP revision + */ +uint8_t etzpc_get_revision(void) +{ + return etzpc_dev.revision; +} + +/* + * etzpc_get_base_address : Return the ETZPC IP base address + */ +uintptr_t etzpc_get_base_address(void) +{ + return etzpc_dev.base; +} + +/* + * etzpc_init : Initialize the ETZPC driver + * Return 0 on success and a negative errno on failure + */ +int etzpc_init(void) +{ + uint32_t hwcfg; + int node; + struct dt_node_info etzpc_info; + + node = dt_get_node(&etzpc_info, -1, ETZPC_COMPAT); + if (node < 0) { + return -EIO; + } + + /* Check ETZPC is secure only */ + if (etzpc_info.status != DT_SECURE) { + return -EACCES; + } + + etzpc_dev.base = etzpc_info.base; + + hwcfg = mmio_read_32(etzpc_dev.base + ETZPC_HWCFGR); + + etzpc_dev.num_tzma = (uint8_t)(hwcfg >> ETZPC_HWCFGR_NUM_TZMA_SHIFT); + etzpc_dev.num_per_sec = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_NUM_PER_SEC_SHIFT); + etzpc_dev.num_ahb_sec = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_NUM_AHB_SEC_SHIFT); + etzpc_dev.chunck_size = (uint8_t)(hwcfg >> + ETZPC_HWCFGR_CHUNCKS1N4_SHIFT); + + etzpc_dev.revision = mmio_read_8(etzpc_dev.base + ETZPC_VERR); + + VERBOSE("ETZPC version 0x%x", etzpc_dev.revision); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c b/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c new file mode 100644 index 0000000..9bdc854 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c @@ -0,0 +1,934 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Timeout for device interface reset */ +#define TIMEOUT_US_1_MS 1000U + +/* FMC2 Compatibility */ +#define DT_FMC2_EBI_COMPAT "st,stm32mp1-fmc2-ebi" +#define DT_FMC2_NFC_COMPAT "st,stm32mp1-fmc2-nfc" +#define MAX_CS 2U +#define MAX_BANK 5U + +/* FMC2 Controller Registers */ +#define FMC2_BCR1 0x00U +#define FMC2_PCR 0x80U +#define FMC2_SR 0x84U +#define FMC2_PMEM 0x88U +#define FMC2_PATT 0x8CU +#define FMC2_HECCR 0x94U +#define FMC2_BCHISR 0x254U +#define FMC2_BCHICR 0x258U +#define FMC2_BCHDSR0 0x27CU +#define FMC2_BCHDSR1 0x280U +#define FMC2_BCHDSR2 0x284U +#define FMC2_BCHDSR3 0x288U +#define FMC2_BCHDSR4 0x28CU + +/* FMC2_BCR1 register */ +#define FMC2_BCR1_FMC2EN BIT(31) +/* FMC2_PCR register */ +#define FMC2_PCR_PWAITEN BIT(1) +#define FMC2_PCR_PBKEN BIT(2) +#define FMC2_PCR_PWID_MASK GENMASK_32(5, 4) +#define FMC2_PCR_PWID(x) (((x) << 4) & FMC2_PCR_PWID_MASK) +#define FMC2_PCR_PWID_8 0x0U +#define FMC2_PCR_PWID_16 0x1U +#define FMC2_PCR_ECCEN BIT(6) +#define FMC2_PCR_ECCALG BIT(8) +#define FMC2_PCR_TCLR_MASK GENMASK_32(12, 9) +#define FMC2_PCR_TCLR(x) (((x) << 9) & FMC2_PCR_TCLR_MASK) +#define FMC2_PCR_TCLR_DEFAULT 0xFU +#define FMC2_PCR_TAR_MASK GENMASK_32(16, 13) +#define FMC2_PCR_TAR(x) (((x) << 13) & FMC2_PCR_TAR_MASK) +#define FMC2_PCR_TAR_DEFAULT 0xFU +#define FMC2_PCR_ECCSS_MASK GENMASK_32(19, 17) +#define FMC2_PCR_ECCSS(x) (((x) << 17) & FMC2_PCR_ECCSS_MASK) +#define FMC2_PCR_ECCSS_512 0x1U +#define FMC2_PCR_ECCSS_2048 0x3U +#define FMC2_PCR_BCHECC BIT(24) +#define FMC2_PCR_WEN BIT(25) +/* FMC2_SR register */ +#define FMC2_SR_NWRF BIT(6) +/* FMC2_PMEM register*/ +#define FMC2_PMEM_MEMSET(x) (((x) & GENMASK_32(7, 0)) << 0) +#define FMC2_PMEM_MEMWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) +#define FMC2_PMEM_MEMHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) +#define FMC2_PMEM_MEMHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) +#define FMC2_PMEM_DEFAULT 0x0A0A0A0AU +/* FMC2_PATT register */ +#define FMC2_PATT_ATTSET(x) (((x) & GENMASK_32(7, 0)) << 0) +#define FMC2_PATT_ATTWAIT(x) (((x) & GENMASK_32(7, 0)) << 8) +#define FMC2_PATT_ATTHOLD(x) (((x) & GENMASK_32(7, 0)) << 16) +#define FMC2_PATT_ATTHIZ(x) (((x) & GENMASK_32(7, 0)) << 24) +#define FMC2_PATT_DEFAULT 0x0A0A0A0AU +/* FMC2_BCHISR register */ +#define FMC2_BCHISR_DERF BIT(1) +/* FMC2_BCHICR register */ +#define FMC2_BCHICR_CLEAR_IRQ GENMASK_32(4, 0) +/* FMC2_BCHDSR0 register */ +#define FMC2_BCHDSR0_DUE BIT(0) +#define FMC2_BCHDSR0_DEF BIT(1) +#define FMC2_BCHDSR0_DEN_MASK GENMASK_32(7, 4) +#define FMC2_BCHDSR0_DEN_SHIFT 4U +/* FMC2_BCHDSR1 register */ +#define FMC2_BCHDSR1_EBP1_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR1_EBP2_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR1_EBP2_SHIFT 16U +/* FMC2_BCHDSR2 register */ +#define FMC2_BCHDSR2_EBP3_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR2_EBP4_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR2_EBP4_SHIFT 16U +/* FMC2_BCHDSR3 register */ +#define FMC2_BCHDSR3_EBP5_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR3_EBP6_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR3_EBP6_SHIFT 16U +/* FMC2_BCHDSR4 register */ +#define FMC2_BCHDSR4_EBP7_MASK GENMASK_32(12, 0) +#define FMC2_BCHDSR4_EBP8_MASK GENMASK_32(28, 16) +#define FMC2_BCHDSR4_EBP8_SHIFT 16U + +/* Timings */ +#define FMC2_THIZ 0x01U +#define FMC2_TIO 8000U +#define FMC2_TSYNC 3000U +#define FMC2_PCR_TIMING_MASK GENMASK_32(3, 0) +#define FMC2_PMEM_PATT_TIMING_MASK GENMASK_32(7, 0) + +#define FMC2_BBM_LEN 2U +#define FMC2_MAX_ECC_BYTES 14U +#define TIMEOUT_US_10_MS 10000U +#define FMC2_PSEC_PER_MSEC (1000UL * 1000UL * 1000UL) + +enum stm32_fmc2_ecc { + FMC2_ECC_HAM = 1U, + FMC2_ECC_BCH4 = 4U, + FMC2_ECC_BCH8 = 8U +}; + +struct stm32_fmc2_cs_reg { + uintptr_t data_base; + uintptr_t cmd_base; + uintptr_t addr_base; +}; + +struct stm32_fmc2_nand_timings { + uint8_t tclr; + uint8_t tar; + uint8_t thiz; + uint8_t twait; + uint8_t thold_mem; + uint8_t tset_mem; + uint8_t thold_att; + uint8_t tset_att; +}; + +struct stm32_fmc2_nfc { + uintptr_t reg_base; + struct stm32_fmc2_cs_reg cs[MAX_CS]; + unsigned long clock_id; + unsigned int reset_id; + uint8_t cs_sel; +}; + +static struct stm32_fmc2_nfc stm32_fmc2; + +static uintptr_t fmc2_base(void) +{ + return stm32_fmc2.reg_base; +} + +static void stm32_fmc2_nand_setup_timing(void) +{ + struct stm32_fmc2_nand_timings tims; + unsigned long hclk = clk_get_rate(stm32_fmc2.clock_id); + unsigned long hclkp = FMC2_PSEC_PER_MSEC / (hclk / 1000U); + unsigned long timing, tar, tclr, thiz, twait; + unsigned long tset_mem, tset_att, thold_mem, thold_att; + uint32_t pcr, pmem, patt; + + tar = MAX(hclkp, NAND_TAR_MIN); + timing = div_round_up(tar, hclkp) - 1U; + tims.tar = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); + + tclr = MAX(hclkp, NAND_TCLR_MIN); + timing = div_round_up(tclr, hclkp) - 1U; + tims.tclr = MIN(timing, (unsigned long)FMC2_PCR_TIMING_MASK); + + tims.thiz = FMC2_THIZ; + thiz = (tims.thiz + 1U) * hclkp; + + /* + * tWAIT > tRP + * tWAIT > tWP + * tWAIT > tREA + tIO + */ + twait = MAX(hclkp, NAND_TRP_MIN); + twait = MAX(twait, NAND_TWP_MIN); + twait = MAX(twait, NAND_TREA_MAX + FMC2_TIO); + timing = div_round_up(twait, hclkp); + tims.twait = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_MEM > tCS - tWAIT + * tSETUP_MEM > tALS - tWAIT + * tSETUP_MEM > tDS - (tWAIT - tHIZ) + */ + tset_mem = hclkp; + if ((twait < NAND_TCS_MIN) && (tset_mem < (NAND_TCS_MIN - twait))) { + tset_mem = NAND_TCS_MIN - twait; + } + if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && + (tset_mem < (NAND_TDS_MIN - (twait - thiz)))) { + tset_mem = NAND_TDS_MIN - (twait - thiz); + } + timing = div_round_up(tset_mem, hclkp); + tims.tset_mem = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_MEM > tCH + * tHOLD_MEM > tREH - tSETUP_MEM + * tHOLD_MEM > max(tRC, tWC) - (tSETUP_MEM + tWAIT) + */ + thold_mem = MAX(hclkp, NAND_TCH_MIN); + if ((tset_mem < NAND_TREH_MIN) && + (thold_mem < (NAND_TREH_MIN - tset_mem))) { + thold_mem = NAND_TREH_MIN - tset_mem; + } + if (((tset_mem + twait) < NAND_TRC_MIN) && + (thold_mem < (NAND_TRC_MIN - (tset_mem + twait)))) { + thold_mem = NAND_TRC_MIN - (tset_mem + twait); + } + if (((tset_mem + twait) < NAND_TWC_MIN) && + (thold_mem < (NAND_TWC_MIN - (tset_mem + twait)))) { + thold_mem = NAND_TWC_MIN - (tset_mem + twait); + } + timing = div_round_up(thold_mem, hclkp); + tims.thold_mem = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tSETUP_ATT > tCS - tWAIT + * tSETUP_ATT > tCLS - tWAIT + * tSETUP_ATT > tALS - tWAIT + * tSETUP_ATT > tRHW - tHOLD_MEM + * tSETUP_ATT > tDS - (tWAIT - tHIZ) + */ + tset_att = hclkp; + if ((twait < NAND_TCS_MIN) && (tset_att < (NAND_TCS_MIN - twait))) { + tset_att = NAND_TCS_MIN - twait; + } + if ((thold_mem < NAND_TRHW_MIN) && + (tset_att < (NAND_TRHW_MIN - thold_mem))) { + tset_att = NAND_TRHW_MIN - thold_mem; + } + if ((twait > thiz) && ((twait - thiz) < NAND_TDS_MIN) && + (tset_att < (NAND_TDS_MIN - (twait - thiz)))) { + tset_att = NAND_TDS_MIN - (twait - thiz); + } + timing = div_round_up(tset_att, hclkp); + tims.tset_att = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + /* + * tHOLD_ATT > tALH + * tHOLD_ATT > tCH + * tHOLD_ATT > tCLH + * tHOLD_ATT > tCOH + * tHOLD_ATT > tDH + * tHOLD_ATT > tWB + tIO + tSYNC - tSETUP_MEM + * tHOLD_ATT > tADL - tSETUP_MEM + * tHOLD_ATT > tWH - tSETUP_MEM + * tHOLD_ATT > tWHR - tSETUP_MEM + * tHOLD_ATT > tRC - (tSETUP_ATT + tWAIT) + * tHOLD_ATT > tWC - (tSETUP_ATT + tWAIT) + */ + thold_att = MAX(hclkp, NAND_TALH_MIN); + thold_att = MAX(thold_att, NAND_TCH_MIN); + thold_att = MAX(thold_att, NAND_TCLH_MIN); + thold_att = MAX(thold_att, NAND_TCOH_MIN); + thold_att = MAX(thold_att, NAND_TDH_MIN); + if (((NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC) > tset_mem) && + (thold_att < (NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem))) { + thold_att = NAND_TWB_MAX + FMC2_TIO + FMC2_TSYNC - tset_mem; + } + if ((tset_mem < NAND_TADL_MIN) && + (thold_att < (NAND_TADL_MIN - tset_mem))) { + thold_att = NAND_TADL_MIN - tset_mem; + } + if ((tset_mem < NAND_TWH_MIN) && + (thold_att < (NAND_TWH_MIN - tset_mem))) { + thold_att = NAND_TWH_MIN - tset_mem; + } + if ((tset_mem < NAND_TWHR_MIN) && + (thold_att < (NAND_TWHR_MIN - tset_mem))) { + thold_att = NAND_TWHR_MIN - tset_mem; + } + if (((tset_att + twait) < NAND_TRC_MIN) && + (thold_att < (NAND_TRC_MIN - (tset_att + twait)))) { + thold_att = NAND_TRC_MIN - (tset_att + twait); + } + if (((tset_att + twait) < NAND_TWC_MIN) && + (thold_att < (NAND_TWC_MIN - (tset_att + twait)))) { + thold_att = NAND_TWC_MIN - (tset_att + twait); + } + timing = div_round_up(thold_att, hclkp); + tims.thold_att = CLAMP(timing, 1UL, + (unsigned long)FMC2_PMEM_PATT_TIMING_MASK); + + VERBOSE("NAND timings: %u - %u - %u - %u - %u - %u - %u - %u\n", + tims.tclr, tims.tar, tims.thiz, tims.twait, + tims.thold_mem, tims.tset_mem, + tims.thold_att, tims.tset_att); + + /* Set tclr/tar timings */ + pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(tims.tclr); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(tims.tar); + + /* Set tset/twait/thold/thiz timings in common bank */ + pmem = FMC2_PMEM_MEMSET(tims.tset_mem); + pmem |= FMC2_PMEM_MEMWAIT(tims.twait); + pmem |= FMC2_PMEM_MEMHOLD(tims.thold_mem); + pmem |= FMC2_PMEM_MEMHIZ(tims.thiz); + + /* Set tset/twait/thold/thiz timings in attribute bank */ + patt = FMC2_PATT_ATTSET(tims.tset_att); + patt |= FMC2_PATT_ATTWAIT(tims.twait); + patt |= FMC2_PATT_ATTHOLD(tims.thold_att); + patt |= FMC2_PATT_ATTHIZ(tims.thiz); + + mmio_write_32(fmc2_base() + FMC2_PCR, pcr); + mmio_write_32(fmc2_base() + FMC2_PMEM, pmem); + mmio_write_32(fmc2_base() + FMC2_PATT, patt); +} + +static void stm32_fmc2_set_buswidth_16(bool set) +{ + mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_PWID_MASK, + (set ? FMC2_PCR_PWID(FMC2_PCR_PWID_16) : 0U)); +} + +static void stm32_fmc2_set_ecc(bool enable) +{ + mmio_clrsetbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_ECCEN, + (enable ? FMC2_PCR_ECCEN : 0U)); +} + +static int stm32_fmc2_ham_correct(uint8_t *buffer, uint8_t *eccbuffer, + uint8_t *ecc) +{ + uint8_t xor_ecc_ones; + uint16_t xor_ecc_1b, xor_ecc_2b, xor_ecc_3b; + union { + uint32_t val; + uint8_t bytes[4]; + } xor_ecc; + + /* Page size--------ECC_Code Size + * 256---------------22 bits LSB (ECC_CODE & 0x003FFFFF) + * 512---------------24 bits (ECC_CODE & 0x00FFFFFF) + * 1024--------------26 bits (ECC_CODE & 0x03FFFFFF) + * 2048--------------28 bits (ECC_CODE & 0x0FFFFFFF) + * 4096--------------30 bits (ECC_CODE & 0x3FFFFFFF) + * 8192--------------32 bits (ECC_CODE & 0xFFFFFFFF) + */ + + /* For Page size 512, ECC_Code size 24 bits */ + xor_ecc_1b = ecc[0] ^ eccbuffer[0]; + xor_ecc_2b = ecc[1] ^ eccbuffer[1]; + xor_ecc_3b = ecc[2] ^ eccbuffer[2]; + + xor_ecc.val = 0U; + xor_ecc.bytes[2] = xor_ecc_3b; + xor_ecc.bytes[1] = xor_ecc_2b; + xor_ecc.bytes[0] = xor_ecc_1b; + + if (xor_ecc.val == 0U) { + return 0; /* No Error */ + } + + xor_ecc_ones = __builtin_popcount(xor_ecc.val); + if (xor_ecc_ones < 23U) { + if (xor_ecc_ones == 12U) { + uint16_t bit_address, byte_address; + + /* Correctable ERROR */ + bit_address = ((xor_ecc_1b >> 1) & BIT(0)) | + ((xor_ecc_1b >> 2) & BIT(1)) | + ((xor_ecc_1b >> 3) & BIT(2)); + + byte_address = ((xor_ecc_1b >> 7) & BIT(0)) | + ((xor_ecc_2b) & BIT(1)) | + ((xor_ecc_2b >> 1) & BIT(2)) | + ((xor_ecc_2b >> 2) & BIT(3)) | + ((xor_ecc_2b >> 3) & BIT(4)) | + ((xor_ecc_3b << 4) & BIT(5)) | + ((xor_ecc_3b << 3) & BIT(6)) | + ((xor_ecc_3b << 2) & BIT(7)) | + ((xor_ecc_3b << 1) & BIT(8)); + + /* Correct bit error in the data */ + buffer[byte_address] = + buffer[byte_address] ^ BIT(bit_address); + VERBOSE("Hamming: 1 ECC error corrected\n"); + + return 0; + } + + /* Non Correctable ERROR */ + ERROR("%s: Uncorrectable ECC Errors\n", __func__); + return -1; + } + + /* ECC ERROR */ + ERROR("%s: Hamming correction error\n", __func__); + return -1; +} + + +static int stm32_fmc2_ham_calculate(uint8_t *buffer, uint8_t *ecc) +{ + uint32_t heccr; + uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((mmio_read_32(fmc2_base() + FMC2_SR) & FMC2_SR_NWRF) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + heccr = mmio_read_32(fmc2_base() + FMC2_HECCR); + + ecc[0] = heccr; + ecc[1] = heccr >> 8; + ecc[2] = heccr >> 16; + + /* Disable ECC */ + stm32_fmc2_set_ecc(false); + + return 0; +} + +static int stm32_fmc2_bch_correct(uint8_t *buffer, unsigned int eccsize) +{ + uint32_t bchdsr0, bchdsr1, bchdsr2, bchdsr3, bchdsr4; + uint16_t pos[8]; + int i, den; + uint64_t timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((mmio_read_32(fmc2_base() + FMC2_BCHISR) & + FMC2_BCHISR_DERF) == 0U) { + if (timeout_elapsed(timeout)) { + return -ETIMEDOUT; + } + } + + bchdsr0 = mmio_read_32(fmc2_base() + FMC2_BCHDSR0); + bchdsr1 = mmio_read_32(fmc2_base() + FMC2_BCHDSR1); + bchdsr2 = mmio_read_32(fmc2_base() + FMC2_BCHDSR2); + bchdsr3 = mmio_read_32(fmc2_base() + FMC2_BCHDSR3); + bchdsr4 = mmio_read_32(fmc2_base() + FMC2_BCHDSR4); + + /* Disable ECC */ + stm32_fmc2_set_ecc(false); + + /* No error found */ + if ((bchdsr0 & FMC2_BCHDSR0_DEF) == 0U) { + return 0; + } + + /* Too many errors detected */ + if ((bchdsr0 & FMC2_BCHDSR0_DUE) != 0U) { + return -EBADMSG; + } + + pos[0] = bchdsr1 & FMC2_BCHDSR1_EBP1_MASK; + pos[1] = (bchdsr1 & FMC2_BCHDSR1_EBP2_MASK) >> FMC2_BCHDSR1_EBP2_SHIFT; + pos[2] = bchdsr2 & FMC2_BCHDSR2_EBP3_MASK; + pos[3] = (bchdsr2 & FMC2_BCHDSR2_EBP4_MASK) >> FMC2_BCHDSR2_EBP4_SHIFT; + pos[4] = bchdsr3 & FMC2_BCHDSR3_EBP5_MASK; + pos[5] = (bchdsr3 & FMC2_BCHDSR3_EBP6_MASK) >> FMC2_BCHDSR3_EBP6_SHIFT; + pos[6] = bchdsr4 & FMC2_BCHDSR4_EBP7_MASK; + pos[7] = (bchdsr4 & FMC2_BCHDSR4_EBP8_MASK) >> FMC2_BCHDSR4_EBP8_SHIFT; + + den = (bchdsr0 & FMC2_BCHDSR0_DEN_MASK) >> FMC2_BCHDSR0_DEN_SHIFT; + for (i = 0; i < den; i++) { + if (pos[i] < (eccsize * 8U)) { + uint8_t bitmask = BIT(pos[i] % 8U); + uint32_t offset = pos[i] / 8U; + + *(buffer + offset) ^= bitmask; + } + } + + return 0; +} + +static void stm32_fmc2_hwctl(struct nand_device *nand) +{ + stm32_fmc2_set_ecc(false); + + if (nand->ecc.max_bit_corr != FMC2_ECC_HAM) { + mmio_clrbits_32(fmc2_base() + FMC2_PCR, FMC2_PCR_WEN); + mmio_write_32(fmc2_base() + FMC2_BCHICR, FMC2_BCHICR_CLEAR_IRQ); + } + + stm32_fmc2_set_ecc(true); +} + +static int stm32_fmc2_read_page(struct nand_device *nand, + unsigned int page, uintptr_t buffer) +{ + unsigned int eccsize = nand->ecc.size; + unsigned int eccbytes = nand->ecc.bytes; + unsigned int eccsteps = nand->page_size / eccsize; + uint8_t ecc_corr[FMC2_MAX_ECC_BYTES]; + uint8_t ecc_cal[FMC2_MAX_ECC_BYTES] = {0U}; + uint8_t *p; + unsigned int i; + unsigned int s; + int ret; + + VERBOSE(">%s page %u buffer %lx\n", __func__, page, buffer); + + ret = nand_read_page_cmd(page, 0U, 0U, 0U); + if (ret != 0) { + return ret; + } + + for (s = 0U, i = nand->page_size + FMC2_BBM_LEN, p = (uint8_t *)buffer; + s < eccsteps; + s++, i += eccbytes, p += eccsize) { + stm32_fmc2_hwctl(nand); + + /* Read the NAND page sector (512 bytes) */ + ret = nand_change_read_column_cmd(s * eccsize, (uintptr_t)p, + eccsize); + if (ret != 0) { + return ret; + } + + if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { + ret = stm32_fmc2_ham_calculate(p, ecc_cal); + if (ret != 0) { + return ret; + } + } + + /* Read the corresponding ECC bytes */ + ret = nand_change_read_column_cmd(i, (uintptr_t)ecc_corr, + eccbytes); + if (ret != 0) { + return ret; + } + + /* Correct the data */ + if (nand->ecc.max_bit_corr == FMC2_ECC_HAM) { + ret = stm32_fmc2_ham_correct(p, ecc_corr, ecc_cal); + } else { + ret = stm32_fmc2_bch_correct(p, eccsize); + } + + if (ret != 0) { + return ret; + } + } + + return 0; +} + +static void stm32_fmc2_read_data(struct nand_device *nand, + uint8_t *buff, unsigned int length, + bool use_bus8) +{ + uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + stm32_fmc2_set_buswidth_16(false); + } + + if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { + *buff = mmio_read_8(data_base); + buff += sizeof(uint8_t); + length -= sizeof(uint8_t); + } + + if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && + (length >= sizeof(uint16_t))) { + *(uint16_t *)buff = mmio_read_16(data_base); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + /* 32bit aligned */ + while (length >= sizeof(uint32_t)) { + *(uint32_t *)buff = mmio_read_32(data_base); + buff += sizeof(uint32_t); + length -= sizeof(uint32_t); + } + + /* Read remaining bytes */ + if (length >= sizeof(uint16_t)) { + *(uint16_t *)buff = mmio_read_16(data_base); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + if (length != 0U) { + *buff = mmio_read_8(data_base); + } + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(true); + } +} + +static void stm32_fmc2_write_data(struct nand_device *nand, + uint8_t *buff, unsigned int length, + bool use_bus8) +{ + uintptr_t data_base = stm32_fmc2.cs[stm32_fmc2.cs_sel].data_base; + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 8-bit */ + stm32_fmc2_set_buswidth_16(false); + } + + if ((((uintptr_t)buff & BIT(0)) != 0U) && (length != 0U)) { + mmio_write_8(data_base, *buff); + buff += sizeof(uint8_t); + length -= sizeof(uint8_t); + } + + if ((((uintptr_t)buff & GENMASK_32(1, 0)) != 0U) && + (length >= sizeof(uint16_t))) { + mmio_write_16(data_base, *(uint16_t *)buff); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + /* 32bits aligned */ + while (length >= sizeof(uint32_t)) { + mmio_write_32(data_base, *(uint32_t *)buff); + buff += sizeof(uint32_t); + length -= sizeof(uint32_t); + } + + /* Read remaining bytes */ + if (length >= sizeof(uint16_t)) { + mmio_write_16(data_base, *(uint16_t *)buff); + buff += sizeof(uint16_t); + length -= sizeof(uint16_t); + } + + if (length != 0U) { + mmio_write_8(data_base, *buff); + } + + if (use_bus8 && (nand->buswidth == NAND_BUS_WIDTH_16)) { + /* Reconfigure bus width to 16-bit */ + stm32_fmc2_set_buswidth_16(true); + } +} + +static void stm32_fmc2_ctrl_init(void) +{ + uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + uint32_t bcr1 = mmio_read_32(fmc2_base() + FMC2_BCR1); + + /* Enable wait feature and NAND flash memory bank */ + pcr |= FMC2_PCR_PWAITEN; + pcr |= FMC2_PCR_PBKEN; + + /* Set buswidth to 8 bits mode for identification */ + pcr &= ~FMC2_PCR_PWID_MASK; + + /* ECC logic is disabled */ + pcr &= ~FMC2_PCR_ECCEN; + + /* Default mode */ + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + pcr &= ~FMC2_PCR_WEN; + + /* Set default ECC sector size */ + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_2048); + + /* Set default TCLR/TAR timings */ + pcr &= ~FMC2_PCR_TCLR_MASK; + pcr |= FMC2_PCR_TCLR(FMC2_PCR_TCLR_DEFAULT); + pcr &= ~FMC2_PCR_TAR_MASK; + pcr |= FMC2_PCR_TAR(FMC2_PCR_TAR_DEFAULT); + + /* Enable FMC2 controller */ + bcr1 |= FMC2_BCR1_FMC2EN; + + mmio_write_32(fmc2_base() + FMC2_BCR1, bcr1); + mmio_write_32(fmc2_base() + FMC2_PCR, pcr); + mmio_write_32(fmc2_base() + FMC2_PMEM, FMC2_PMEM_DEFAULT); + mmio_write_32(fmc2_base() + FMC2_PATT, FMC2_PATT_DEFAULT); +} + +static int stm32_fmc2_exec(struct nand_req *req) +{ + int ret = 0; + + switch (req->type & NAND_REQ_MASK) { + case NAND_REQ_CMD: + VERBOSE("Write CMD %x\n", (uint8_t)req->type); + mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].cmd_base, + (uint8_t)req->type); + break; + case NAND_REQ_ADDR: + VERBOSE("Write ADDR %x\n", *(req->addr)); + mmio_write_8(stm32_fmc2.cs[stm32_fmc2.cs_sel].addr_base, + *(req->addr)); + break; + case NAND_REQ_DATAIN: + VERBOSE("Read data\n"); + stm32_fmc2_read_data(req->nand, req->addr, req->length, + ((req->type & NAND_REQ_BUS_WIDTH_8) != + 0U)); + break; + case NAND_REQ_DATAOUT: + VERBOSE("Write data\n"); + stm32_fmc2_write_data(req->nand, req->addr, req->length, + ((req->type & NAND_REQ_BUS_WIDTH_8) != + 0U)); + break; + case NAND_REQ_WAIT: + VERBOSE("WAIT Ready\n"); + ret = nand_wait_ready(req->delay_ms); + break; + default: + ret = -EINVAL; + break; + }; + + return ret; +} + +static void stm32_fmc2_setup(struct nand_device *nand) +{ + uint32_t pcr = mmio_read_32(fmc2_base() + FMC2_PCR); + + /* Set buswidth */ + pcr &= ~FMC2_PCR_PWID_MASK; + if (nand->buswidth == NAND_BUS_WIDTH_16) { + pcr |= FMC2_PCR_PWID(FMC2_PCR_PWID_16); + } + + if (nand->ecc.mode == NAND_ECC_HW) { + nand->mtd_read_page = stm32_fmc2_read_page; + + pcr &= ~FMC2_PCR_ECCALG; + pcr &= ~FMC2_PCR_BCHECC; + + pcr &= ~FMC2_PCR_ECCSS_MASK; + pcr |= FMC2_PCR_ECCSS(FMC2_PCR_ECCSS_512); + + switch (nand->ecc.max_bit_corr) { + case FMC2_ECC_HAM: + nand->ecc.bytes = 3; + break; + case FMC2_ECC_BCH8: + pcr |= FMC2_PCR_ECCALG; + pcr |= FMC2_PCR_BCHECC; + nand->ecc.bytes = 13; + break; + default: + /* Use FMC2 ECC BCH4 */ + pcr |= FMC2_PCR_ECCALG; + nand->ecc.bytes = 7; + break; + } + + if ((nand->buswidth & NAND_BUS_WIDTH_16) != 0) { + nand->ecc.bytes++; + } + } + + mmio_write_32(stm32_fmc2.reg_base + FMC2_PCR, pcr); +} + +static const struct nand_ctrl_ops ctrl_ops = { + .setup = stm32_fmc2_setup, + .exec = stm32_fmc2_exec +}; + +int stm32_fmc2_init(void) +{ + int fmc_ebi_node; + int fmc_nfc_node; + int fmc_flash_node = 0; + int nchips = 0; + unsigned int i; + void *fdt = NULL; + const fdt32_t *cuint; + struct dt_node_info info; + uintptr_t bank_address[MAX_BANK] = { 0, 0, 0, 0, 0 }; + uint8_t bank_assigned = 0; + uint8_t bank; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + fmc_ebi_node = dt_get_node(&info, -1, DT_FMC2_EBI_COMPAT); + if (fmc_ebi_node < 0) { + return fmc_ebi_node; + } + + if (info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + stm32_fmc2.reg_base = info.base; + + if ((info.clock < 0) || (info.reset < 0)) { + return -FDT_ERR_BADVALUE; + } + + stm32_fmc2.clock_id = (unsigned long)info.clock; + stm32_fmc2.reset_id = (unsigned int)info.reset; + + cuint = fdt_getprop(fdt, fmc_ebi_node, "ranges", NULL); + if (cuint == NULL) { + return -FDT_ERR_BADVALUE; + } + + for (i = 0U; i < MAX_BANK; i++) { + bank = fdt32_to_cpu(*cuint); + if ((bank >= MAX_BANK) || ((bank_assigned & BIT(bank)) != 0U)) { + return -FDT_ERR_BADVALUE; + } + bank_assigned |= BIT(bank); + bank_address[bank] = fdt32_to_cpu(*(cuint + 2)); + cuint += 4; + } + + /* Pinctrl initialization */ + if (dt_set_pinctrl_config(fmc_ebi_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + /* Parse NFC controller node */ + fmc_nfc_node = fdt_node_offset_by_compatible(fdt, fmc_ebi_node, + DT_FMC2_NFC_COMPAT); + if (fmc_nfc_node < 0) { + return fmc_nfc_node; + } + + if (fdt_get_status(fmc_nfc_node) == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, fmc_nfc_node, "reg", NULL); + if (cuint == NULL) { + return -FDT_ERR_BADVALUE; + } + + for (i = 0U; i < MAX_CS; i++) { + bank = fdt32_to_cpu(*cuint); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].data_base = fdt32_to_cpu(*(cuint + 1)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 3)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].cmd_base = fdt32_to_cpu(*(cuint + 4)) + + bank_address[bank]; + + bank = fdt32_to_cpu(*(cuint + 6)); + if (bank >= MAX_BANK) { + return -FDT_ERR_BADVALUE; + } + stm32_fmc2.cs[i].addr_base = fdt32_to_cpu(*(cuint + 7)) + + bank_address[bank]; + + cuint += 9; + } + + /* Parse flash nodes */ + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { + nchips++; + } + + if (nchips != 1) { + WARN("Only one SLC NAND device supported\n"); + return -FDT_ERR_BADVALUE; + } + + fdt_for_each_subnode(fmc_flash_node, fdt, fmc_nfc_node) { + /* Get chip select */ + cuint = fdt_getprop(fdt, fmc_flash_node, "reg", NULL); + if (cuint == NULL) { + WARN("Chip select not well defined\n"); + return -FDT_ERR_BADVALUE; + } + + stm32_fmc2.cs_sel = fdt32_to_cpu(*cuint); + if (stm32_fmc2.cs_sel >= MAX_CS) { + return -FDT_ERR_BADVALUE; + } + + VERBOSE("NAND CS %i\n", stm32_fmc2.cs_sel); + } + + /* Enable Clock */ + clk_enable(stm32_fmc2.clock_id); + + /* Reset IP */ + ret = stm32mp_reset_assert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + ret = stm32mp_reset_deassert(stm32_fmc2.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + + /* Setup default IP registers */ + stm32_fmc2_ctrl_init(); + + /* Setup default timings */ + stm32_fmc2_nand_setup_timing(); + + /* Init NAND RAW framework */ + nand_raw_ctrl_init(&ctrl_ops); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c b/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c new file mode 100644 index 0000000..708989f --- /dev/null +++ b/arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c @@ -0,0 +1,323 @@ +/* + * Copyright (c) 2016-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define DT_GPIO_BANK_SHIFT 12 +#define DT_GPIO_BANK_MASK GENMASK(16, 12) +#define DT_GPIO_PIN_SHIFT 8 +#define DT_GPIO_PIN_MASK GENMASK(11, 8) +#define DT_GPIO_MODE_MASK GENMASK(7, 0) + +static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, + uint32_t speed, uint32_t pull, uint32_t od, + uint32_t alternate, uint8_t status); + +/******************************************************************************* + * This function gets GPIO bank node in DT. + * Returns node offset if status is okay in DT, else return 0 + ******************************************************************************/ +static int ckeck_gpio_bank(void *fdt, uint32_t bank, int pinctrl_node) +{ + int pinctrl_subnode; + uint32_t bank_offset = stm32_get_gpio_bank_offset(bank); + + fdt_for_each_subnode(pinctrl_subnode, fdt, pinctrl_node) { + const fdt32_t *cuint; + + if (fdt_getprop(fdt, pinctrl_subnode, + "gpio-controller", NULL) == NULL) { + continue; + } + + cuint = fdt_getprop(fdt, pinctrl_subnode, "reg", NULL); + if (cuint == NULL) { + continue; + } + + if ((fdt32_to_cpu(*cuint) == bank_offset) && + (fdt_get_status(pinctrl_subnode) != DT_DISABLED)) { + return pinctrl_subnode; + } + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT error code on failure. + ******************************************************************************/ +static int dt_set_gpio_config(void *fdt, int node, uint8_t status) +{ + const fdt32_t *cuint, *slewrate; + int len; + int pinctrl_node; + uint32_t i; + uint32_t speed = GPIO_SPEED_LOW; + uint32_t pull = GPIO_NO_PULL; + + cuint = fdt_getprop(fdt, node, "pinmux", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + pinctrl_node = fdt_parent_offset(fdt, fdt_parent_offset(fdt, node)); + if (pinctrl_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + slewrate = fdt_getprop(fdt, node, "slew-rate", NULL); + if (slewrate != NULL) { + speed = fdt32_to_cpu(*slewrate); + } + + if (fdt_getprop(fdt, node, "bias-pull-up", NULL) != NULL) { + pull = GPIO_PULL_UP; + } else if (fdt_getprop(fdt, node, "bias-pull-down", NULL) != NULL) { + pull = GPIO_PULL_DOWN; + } else { + VERBOSE("No bias configured in node %d\n", node); + } + + for (i = 0U; i < ((uint32_t)len / sizeof(uint32_t)); i++) { + uint32_t pincfg; + uint32_t bank; + uint32_t pin; + uint32_t mode; + uint32_t alternate = GPIO_ALTERNATE_(0); + uint32_t type; + uint32_t od = GPIO_OD_OUTPUT_LOW; + int bank_node; + int clk; + + pincfg = fdt32_to_cpu(*cuint); + cuint++; + + bank = (pincfg & DT_GPIO_BANK_MASK) >> DT_GPIO_BANK_SHIFT; + + pin = (pincfg & DT_GPIO_PIN_MASK) >> DT_GPIO_PIN_SHIFT; + + mode = pincfg & DT_GPIO_MODE_MASK; + + switch (mode) { + case 0: + mode = GPIO_MODE_INPUT; + break; + case 1 ... 16: + alternate = mode - 1U; + mode = GPIO_MODE_ALTERNATE; + break; + case 17: + mode = GPIO_MODE_ANALOG; + break; + default: + mode = GPIO_MODE_OUTPUT; + break; + } + + if (fdt_getprop(fdt, node, "drive-open-drain", NULL) != NULL) { + type = GPIO_TYPE_OPEN_DRAIN; + } else { + type = GPIO_TYPE_PUSH_PULL; + } + + if (fdt_getprop(fdt, node, "output-high", NULL) != NULL) { + if (mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + od = GPIO_OD_OUTPUT_HIGH; + } + } + + if (fdt_getprop(fdt, node, "output-low", NULL) != NULL) { + if (mode == GPIO_MODE_INPUT) { + mode = GPIO_MODE_OUTPUT; + od = GPIO_OD_OUTPUT_LOW; + } + } + + bank_node = ckeck_gpio_bank(fdt, bank, pinctrl_node); + if (bank_node == 0) { + ERROR("PINCTRL inconsistent in DT\n"); + panic(); + } + + clk = fdt_get_clock_id(bank_node); + if (clk < 0) { + return -FDT_ERR_NOTFOUND; + } + + /* Platform knows the clock: assert it is okay */ + assert((unsigned long)clk == stm32_get_gpio_bank_clock(bank)); + + set_gpio(bank, pin, mode, type, speed, pull, od, alternate, status); + } + + return 0; +} + +/******************************************************************************* + * This function gets the pin settings from DT information. + * When analyze and parsing is done, set the GPIO registers. + * Returns 0 on success and a negative FDT/ERRNO error code on failure. + ******************************************************************************/ +int dt_set_pinctrl_config(int node) +{ + const fdt32_t *cuint; + int lenp; + uint32_t i; + uint8_t status; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + status = fdt_get_status(node); + if (status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + cuint = fdt_getprop(fdt, node, "pinctrl-0", &lenp); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + for (i = 0; i < ((uint32_t)lenp / 4U); i++) { + int p_node, p_subnode; + + p_node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (p_node < 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_subnode(p_subnode, fdt, p_node) { + int ret = dt_set_gpio_config(fdt, p_subnode, status); + + if (ret < 0) { + return ret; + } + } + + cuint++; + } + + return 0; +} + +static void set_gpio(uint32_t bank, uint32_t pin, uint32_t mode, uint32_t type, + uint32_t speed, uint32_t pull, uint32_t od, + uint32_t alternate, uint8_t status) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + clk_enable(clock); + + mmio_clrsetbits_32(base + GPIO_MODE_OFFSET, + (uint32_t)GPIO_MODE_MASK << (pin << 1), + mode << (pin << 1)); + + mmio_clrsetbits_32(base + GPIO_TYPE_OFFSET, + (uint32_t)GPIO_TYPE_MASK << pin, + type << pin); + + mmio_clrsetbits_32(base + GPIO_SPEED_OFFSET, + (uint32_t)GPIO_SPEED_MASK << (pin << 1), + speed << (pin << 1)); + + mmio_clrsetbits_32(base + GPIO_PUPD_OFFSET, + (uint32_t)GPIO_PULL_MASK << (pin << 1), + pull << (pin << 1)); + + if (pin < GPIO_ALT_LOWER_LIMIT) { + mmio_clrsetbits_32(base + GPIO_AFRL_OFFSET, + (uint32_t)GPIO_ALTERNATE_MASK << (pin << 2), + alternate << (pin << 2)); + } else { + size_t shift = (pin - GPIO_ALT_LOWER_LIMIT) << 2; + + mmio_clrsetbits_32(base + GPIO_AFRH_OFFSET, + (uint32_t)GPIO_ALTERNATE_MASK << shift, + alternate << shift); + } + + mmio_clrsetbits_32(base + GPIO_OD_OFFSET, + (uint32_t)GPIO_OD_MASK << pin, + od << pin); + + VERBOSE("GPIO %u mode set to 0x%x\n", bank, + mmio_read_32(base + GPIO_MODE_OFFSET)); + VERBOSE("GPIO %u type set to 0x%x\n", bank, + mmio_read_32(base + GPIO_TYPE_OFFSET)); + VERBOSE("GPIO %u speed set to 0x%x\n", bank, + mmio_read_32(base + GPIO_SPEED_OFFSET)); + VERBOSE("GPIO %u mode pull to 0x%x\n", bank, + mmio_read_32(base + GPIO_PUPD_OFFSET)); + VERBOSE("GPIO %u mode alternate low to 0x%x\n", bank, + mmio_read_32(base + GPIO_AFRL_OFFSET)); + VERBOSE("GPIO %u mode alternate high to 0x%x\n", bank, + mmio_read_32(base + GPIO_AFRH_OFFSET)); + VERBOSE("GPIO %u output data set to 0x%x\n", bank, + mmio_read_32(base + GPIO_OD_OFFSET)); + + clk_disable(clock); + + if (status == DT_SECURE) { + stm32mp_register_secure_gpio(bank, pin); +#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, true); +#endif + + } else { + stm32mp_register_non_secure_gpio(bank, pin); +#if !IMAGE_BL2 + set_gpio_secure_cfg(bank, pin, false); +#endif + } +} + +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure) +{ + uintptr_t base = stm32_get_gpio_bank_base(bank); + unsigned long clock = stm32_get_gpio_bank_clock(bank); + + assert(pin <= GPIO_PIN_MAX); + + clk_enable(clock); + + if (secure) { + mmio_setbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } else { + mmio_clrbits_32(base + GPIO_SECR_OFFSET, BIT(pin)); + } + + clk_disable(clock); +} + +void set_gpio_reset_cfg(uint32_t bank, uint32_t pin) +{ + set_gpio(bank, pin, GPIO_MODE_ANALOG, GPIO_TYPE_PUSH_PULL, + GPIO_SPEED_LOW, GPIO_NO_PULL, GPIO_OD_OUTPUT_LOW, + GPIO_ALTERNATE_(0), DT_DISABLED); + set_gpio_secure_cfg(bank, pin, stm32_gpio_is_secure_at_reset(bank)); +} diff --git a/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c b/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c new file mode 100644 index 0000000..bf6c3ee --- /dev/null +++ b/arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c @@ -0,0 +1,982 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* STM32 I2C registers offsets */ +#define I2C_CR1 0x00U +#define I2C_CR2 0x04U +#define I2C_OAR1 0x08U +#define I2C_OAR2 0x0CU +#define I2C_TIMINGR 0x10U +#define I2C_TIMEOUTR 0x14U +#define I2C_ISR 0x18U +#define I2C_ICR 0x1CU +#define I2C_PECR 0x20U +#define I2C_RXDR 0x24U +#define I2C_TXDR 0x28U + +#define TIMINGR_CLEAR_MASK 0xF0FFFFFFU + +#define MAX_NBYTE_SIZE 255U + +#define I2C_NSEC_PER_SEC 1000000000L + +/* I2C Timing hard-coded value, for I2C clock source is HSI at 64MHz */ +#define I2C_TIMING 0x10D07DB5 + +static void notif_i2c_timeout(struct i2c_handle_s *hi2c) +{ + hi2c->i2c_err |= I2C_ERROR_TIMEOUT; + hi2c->i2c_mode = I2C_MODE_NONE; + hi2c->i2c_state = I2C_STATE_READY; +} + +/* + * @brief Configure I2C Analog noise filter. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C peripheral. + * @param analog_filter: New state of the Analog filter + * @retval 0 if OK, negative value else + */ +static int i2c_config_analog_filter(struct i2c_handle_s *hi2c, + uint32_t analog_filter) +{ + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + hi2c->lock = 1; + + hi2c->i2c_state = I2C_STATE_BUSY; + + /* Disable the selected I2C peripheral */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + /* Reset I2Cx ANOFF bit */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_ANFOFF); + + /* Set analog filter bit*/ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, analog_filter); + + /* Enable the selected I2C peripheral */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_state = I2C_STATE_READY; + + hi2c->lock = 0; + + return 0; +} + +/* + * @brief Get I2C setup information from the device tree and set pinctrl + * configuration. + * @param fdt: Pointer to the device tree + * @param node: I2C node offset + * @param init: Ref to the initialization configuration structure + * @retval 0 if OK, negative value else + */ +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init) +{ + const fdt32_t *cuint; + + cuint = fdt_getprop(fdt, node, "i2c-scl-rising-time-ns", NULL); + if (cuint == NULL) { + init->rise_time = STM32_I2C_RISE_TIME_DEFAULT; + } else { + init->rise_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "i2c-scl-falling-time-ns", NULL); + if (cuint == NULL) { + init->fall_time = STM32_I2C_FALL_TIME_DEFAULT; + } else { + init->fall_time = fdt32_to_cpu(*cuint); + } + + cuint = fdt_getprop(fdt, node, "clock-frequency", NULL); + if (cuint == NULL) { + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + } else { + switch (fdt32_to_cpu(*cuint)) { + case STANDARD_RATE: + init->speed_mode = I2C_SPEED_STANDARD; + break; + case FAST_RATE: + init->speed_mode = I2C_SPEED_FAST; + break; + case FAST_PLUS_RATE: + init->speed_mode = I2C_SPEED_FAST_PLUS; + break; + default: + init->speed_mode = STM32_I2C_SPEED_DEFAULT; + break; + } + } + + return dt_set_pinctrl_config(node); +} + +/* + * @brief Initialize the I2C device. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param init_data: Initialization configuration structure + * @retval 0 if OK, negative value else + */ +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data) +{ + int rc = 0; + uint32_t timing = I2C_TIMING; + + if (hi2c == NULL) { + return -ENOENT; + } + + if (hi2c->i2c_state == I2C_STATE_RESET) { + hi2c->lock = 0; + } + + hi2c->i2c_state = I2C_STATE_BUSY; + + clk_enable(hi2c->clock); + + /* Disable the selected I2C peripheral */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + /* Configure I2Cx: Frequency range */ + mmio_write_32(hi2c->i2c_base_addr + I2C_TIMINGR, + timing & TIMINGR_CLEAR_MASK); + + /* Disable Own Address1 before set the Own Address1 configuration */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR1, I2C_OAR1_OA1EN); + + /* Configure I2Cx: Own Address1 and ack own address1 mode */ + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_7BIT) { + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, + I2C_OAR1_OA1EN | init_data->own_address1); + } else { /* I2C_ADDRESSINGMODE_10BIT */ + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR1, + I2C_OAR1_OA1EN | I2C_OAR1_OA1MODE | + init_data->own_address1); + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, 0); + + /* Configure I2Cx: Addressing Master mode */ + if (init_data->addressing_mode == I2C_ADDRESSINGMODE_10BIT) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_CR2_ADD10); + } + + /* + * Enable the AUTOEND by default, and enable NACK + * (should be disabled only during Slave process). + */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, + I2C_CR2_AUTOEND | I2C_CR2_NACK); + + /* Disable Own Address2 before set the Own Address2 configuration */ + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_OAR2, I2C_DUALADDRESS_ENABLE); + + /* Configure I2Cx: Dual mode and Own Address2 */ + mmio_write_32(hi2c->i2c_base_addr + I2C_OAR2, + init_data->dual_address_mode | + init_data->own_address2 | + (init_data->own_address2_masks << 8)); + + /* Configure I2Cx: Generalcall and NoStretch mode */ + mmio_write_32(hi2c->i2c_base_addr + I2C_CR1, + init_data->general_call_mode | + init_data->no_stretch_mode); + + /* Enable the selected I2C peripheral */ + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR1, I2C_CR1_PE); + + hi2c->i2c_err = I2C_ERROR_NONE; + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = i2c_config_analog_filter(hi2c, init_data->analog_filter ? + I2C_ANALOGFILTER_ENABLE : + I2C_ANALOGFILTER_DISABLE); + if (rc != 0) { + ERROR("Cannot initialize I2C analog filter (%d)\n", rc); + clk_disable(hi2c->clock); + return rc; + } + + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief I2C Tx data register flush process. + * @param hi2c: I2C handle + * @retval None + */ +static void i2c_flush_txdr(struct i2c_handle_s *hi2c) +{ + /* + * If a pending TXIS flag is set, + * write a dummy data in TXDR to clear it. + */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXIS) != + 0U) { + mmio_write_32(hi2c->i2c_base_addr + I2C_TXDR, 0); + } + + /* Flush TX register if not empty */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_TXE) == + 0U) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_ISR, + I2C_FLAG_TXE); + } +} + +/* + * @brief This function handles I2C Communication timeout. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param flag: Specifies the I2C flag to check + * @param awaited_value: The awaited bit value for the flag (0 or 1) + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_flag(struct i2c_handle_s *hi2c, uint32_t flag, + uint8_t awaited_value, uint64_t timeout_ref) +{ + for ( ; ; ) { + uint32_t isr = mmio_read_32(hi2c->i2c_base_addr + I2C_ISR); + + if (!!(isr & flag) != !!awaited_value) { + return 0; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } +} + +/* + * @brief This function handles Acknowledge failed detection during + * an I2C Communication. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_ack_failed(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_AF) == 0U) { + return 0; + } + + /* + * Wait until STOP Flag is reset. + * AutoEnd should be initiate after AF. + */ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_STOPF) == 0U) { + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + i2c_flush_txdr(hi2c); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_err |= I2C_ERROR_AF; + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + hi2c->lock = 0; + + return -EIO; +} + +/* + * @brief This function handles I2C Communication timeout for specific usage + * of TXIS flag. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_txis(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_TXIS) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + return 0; +} + +/* + * @brief This function handles I2C Communication timeout for specific + * usage of STOP flag. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_wait_stop(struct i2c_handle_s *hi2c, uint64_t timeout_ref) +{ + while ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_STOPF) == 0U) { + if (i2c_ack_failed(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + hi2c->lock = 0; + + return -EIO; + } + } + + return 0; +} + +/* + * @brief Handles I2Cx communication when starting transfer or during transfer + * (TC or TCR flag are set). + * @param hi2c: I2C handle + * @param dev_addr: Specifies the slave address to be programmed + * @param size: Specifies the number of bytes to be programmed. + * This parameter must be a value between 0 and 255. + * @param i2c_mode: New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_RELOAD_MODE: Enable Reload mode. + * @arg @ref I2C_AUTOEND_MODE: Enable Automatic end mode. + * @arg @ref I2C_SOFTEND_MODE: Enable Software end mode. + * @param request: New state of the I2C START condition generation. + * This parameter can be one of the following values: + * @arg @ref I2C_NO_STARTSTOP: Don't Generate stop and start condition. + * @arg @ref I2C_GENERATE_STOP: Generate stop condition + * (size should be set to 0). + * @arg @ref I2C_GENERATE_START_READ: Generate Restart for read request. + * @arg @ref I2C_GENERATE_START_WRITE: Generate Restart for write request. + * @retval None + */ +static void i2c_transfer_config(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t size, uint32_t i2c_mode, + uint32_t request) +{ + uint32_t clr_value, set_value; + + clr_value = (I2C_CR2_SADD | I2C_CR2_NBYTES | I2C_CR2_RELOAD | + I2C_CR2_AUTOEND | I2C_CR2_START | I2C_CR2_STOP) | + (I2C_CR2_RD_WRN & (request >> (31U - I2C_CR2_RD_WRN_OFFSET))); + + set_value = ((uint32_t)dev_addr & I2C_CR2_SADD) | + (((uint32_t)size << I2C_CR2_NBYTES_OFFSET) & I2C_CR2_NBYTES) | + i2c_mode | request; + + mmio_clrsetbits_32(hi2c->i2c_base_addr + I2C_CR2, clr_value, set_value); +} + +/* + * @brief Master sends target device address followed by internal memory + * address for write request. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_request_memory_write(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint16_t mem_addr, + uint16_t mem_add_size, uint64_t timeout_ref) +{ + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { + /* Send Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } else { + /* Send MSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)((mem_addr & 0xFF00U) >> 8)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + /* Send LSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, timeout_ref) != 0) { + return -EIO; + } + + return 0; +} + +/* + * @brief Master sends target device address followed by internal memory + * address for read request. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param timeout_ref: Reference to target timeout + * @retval 0 if OK, negative value else + */ +static int i2c_request_memory_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint64_t timeout_ref) +{ + i2c_transfer_config(hi2c, dev_addr, mem_add_size, I2C_SOFTEND_MODE, + I2C_GENERATE_START_WRITE); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + if (mem_add_size == I2C_MEMADD_SIZE_8BIT) { + /* Send Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } else { + /* Send MSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)((mem_addr & 0xFF00U) >> 8)); + + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + return -EIO; + } + + /* Send LSB of Memory Address */ + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, + (uint8_t)(mem_addr & 0x00FFU)); + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_TC, 0, timeout_ref) != 0) { + return -EIO; + } + + return 0; +} +/* + * @brief Generic function to write an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_size; + uint32_t xfer_count = size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY_TX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; + + timeout_ref = timeout_init_us(timeout_ms * 1000); + + if (mode == I2C_MODE_MEM) { + /* In Memory Mode, Send Slave Address and Memory Address */ + if (i2c_request_memory_write(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_NO_STARTSTOP); + } + } else { + /* In Master Mode, Send Slave Address */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, + I2C_GENERATE_START_WRITE); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, + I2C_GENERATE_START_WRITE); + } + } + + do { + if (i2c_wait_txis(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_8(hi2c->i2c_base_addr + I2C_TXDR, *p_buff); + p_buff++; + xfer_count--; + xfer_size--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + /* Wait until TCR flag is set */ + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = 0; + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief Write an amount of data in blocking mode to a specific memory + * address. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms) +{ + return i2c_write(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Transmits in master mode an amount of data in blocking mode. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_write(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @brief Generic function to read an amount of data in blocking mode + * (for Memory Mode and Master Mode) + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address (if Memory Mode) + * @param mem_add_size: Size of internal memory address (if Memory Mode) + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @param mode: Communication mode + * @retval 0 if OK, negative value else + */ +static int i2c_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms, + enum i2c_mode_e mode) +{ + uint64_t timeout_ref; + int rc = -EIO; + uint8_t *p_buff = p_data; + uint32_t xfer_count = size; + uint32_t xfer_size; + + if ((mode != I2C_MODE_MASTER) && (mode != I2C_MODE_MEM)) { + return -1; + } + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return -EBUSY; + } + + if ((p_data == NULL) || (size == 0U)) { + return -EINVAL; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + + timeout_ref = timeout_init_us(I2C_TIMEOUT_BUSY_MS * 1000); + if (i2c_wait_flag(hi2c, I2C_FLAG_BUSY, 1, timeout_ref) != 0) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY_RX; + hi2c->i2c_mode = mode; + hi2c->i2c_err = I2C_ERROR_NONE; + + if (mode == I2C_MODE_MEM) { + /* Send Memory Address */ + if (i2c_request_memory_read(hi2c, dev_addr, mem_addr, + mem_add_size, timeout_ref) != 0) { + goto bail; + } + } + + /* + * Send Slave Address. + * Set NBYTES to write and reload if xfer_count > MAX_NBYTE_SIZE + * and generate RESTART. + */ + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_RELOAD_MODE, I2C_GENERATE_START_READ); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, xfer_size, + I2C_AUTOEND_MODE, I2C_GENERATE_START_READ); + } + + do { + if (i2c_wait_flag(hi2c, I2C_FLAG_RXNE, 0, timeout_ref) != 0) { + goto bail; + } + + *p_buff = mmio_read_8(hi2c->i2c_base_addr + I2C_RXDR); + p_buff++; + xfer_size--; + xfer_count--; + + if ((xfer_count != 0U) && (xfer_size == 0U)) { + if (i2c_wait_flag(hi2c, I2C_FLAG_TCR, 0, + timeout_ref) != 0) { + goto bail; + } + + if (xfer_count > MAX_NBYTE_SIZE) { + xfer_size = MAX_NBYTE_SIZE; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_RELOAD_MODE, + I2C_NO_STARTSTOP); + } else { + xfer_size = xfer_count; + i2c_transfer_config(hi2c, dev_addr, + xfer_size, + I2C_AUTOEND_MODE, + I2C_NO_STARTSTOP); + } + } + } while (xfer_count > 0U); + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is reset. + */ + if (i2c_wait_stop(hi2c, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + mmio_clrbits_32(hi2c->i2c_base_addr + I2C_CR2, I2C_RESET_CR2); + + hi2c->i2c_state = I2C_STATE_READY; + hi2c->i2c_mode = I2C_MODE_NONE; + + rc = 0; + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + +/* + * @brief Read an amount of data in blocking mode from a specific memory + * address. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param mem_addr: Internal memory address + * @param mem_add_size: Size of internal memory address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms) +{ + return i2c_read(hi2c, dev_addr, mem_addr, mem_add_size, + p_data, size, timeout_ms, I2C_MODE_MEM); +} + +/* + * @brief Receives in master mode an amount of data in blocking mode. + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param p_data: Pointer to data buffer + * @param size: Amount of data to be sent + * @param timeout_ms: Timeout duration in milliseconds + * @retval 0 if OK, negative value else + */ +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms) +{ + return i2c_read(hi2c, dev_addr, 0, 0, + p_data, size, timeout_ms, I2C_MODE_MASTER); +} + +/* + * @brief Checks if target device is ready for communication. + * @note This function is used with Memory devices + * @param hi2c: Pointer to a struct i2c_handle_s structure that contains + * the configuration information for the specified I2C. + * @param dev_addr: Target device address + * @param trials: Number of trials + * @param timeout_ms: Timeout duration in milliseconds + * @retval True if device is ready, false else + */ +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, + uint16_t dev_addr, uint32_t trials, + uint32_t timeout_ms) +{ + uint32_t i2c_trials = 0U; + bool rc = false; + + if ((hi2c->i2c_state != I2C_STATE_READY) || (hi2c->lock != 0U)) { + return rc; + } + + clk_enable(hi2c->clock); + + hi2c->lock = 1; + hi2c->i2c_mode = I2C_MODE_NONE; + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & I2C_FLAG_BUSY) != + 0U) { + goto bail; + } + + hi2c->i2c_state = I2C_STATE_BUSY; + hi2c->i2c_err = I2C_ERROR_NONE; + + do { + uint64_t timeout_ref; + + /* Generate Start */ + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_OAR1) & + I2C_OAR1_OA1MODE) == 0) { + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, + (((uint32_t)dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_AUTOEND) & + ~I2C_CR2_RD_WRN); + } else { + mmio_write_32(hi2c->i2c_base_addr + I2C_CR2, + (((uint32_t)dev_addr & I2C_CR2_SADD) | + I2C_CR2_START | I2C_CR2_ADD10) & + ~I2C_CR2_RD_WRN); + } + + /* + * No need to Check TC flag, with AUTOEND mode the stop + * is automatically generated. + * Wait until STOPF flag is set or a NACK flag is set. + */ + timeout_ref = timeout_init_us(timeout_ms * 1000); + do { + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + (I2C_FLAG_STOPF | I2C_FLAG_AF)) != 0U) { + break; + } + + if (timeout_elapsed(timeout_ref)) { + notif_i2c_timeout(hi2c); + goto bail; + } + } while (true); + + if ((mmio_read_32(hi2c->i2c_base_addr + I2C_ISR) & + I2C_FLAG_AF) == 0U) { + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, + timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + + hi2c->i2c_state = I2C_STATE_READY; + + rc = true; + goto bail; + } + + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_AF); + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, I2C_FLAG_STOPF); + + if (i2c_trials == trials) { + mmio_setbits_32(hi2c->i2c_base_addr + I2C_CR2, + I2C_CR2_STOP); + + if (i2c_wait_flag(hi2c, I2C_FLAG_STOPF, 0, + timeout_ref) != 0) { + goto bail; + } + + mmio_write_32(hi2c->i2c_base_addr + I2C_ICR, + I2C_FLAG_STOPF); + } + + i2c_trials++; + } while (i2c_trials < trials); + + notif_i2c_timeout(hi2c); + +bail: + hi2c->lock = 0; + clk_disable(hi2c->clock); + + return rc; +} + diff --git a/arm-trusted-firmware/drivers/st/io/io_mmc.c b/arm-trusted-firmware/drivers/st/io/io_mmc.c new file mode 100644 index 0000000..2bf88e6 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/io/io_mmc.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* SDMMC device functions */ +static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info); +static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); +static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params); +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset); +static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); +static int mmc_block_close(io_entity_t *entity); +static int mmc_dev_close(io_dev_info_t *dev_info); +static io_type_t device_type_mmc(void); + +static signed long long seek_offset; +static size_t (*_read_blocks)(int lba, uintptr_t buf, size_t size); + +static const io_dev_connector_t mmc_dev_connector = { + .dev_open = mmc_dev_open +}; + +static const io_dev_funcs_t mmc_dev_funcs = { + .type = device_type_mmc, + .open = mmc_block_open, + .seek = mmc_block_seek, + .size = NULL, + .read = mmc_block_read, + .write = NULL, + .close = mmc_block_close, + .dev_init = mmc_dev_init, + .dev_close = mmc_dev_close, +}; + +static const io_dev_info_t mmc_dev_info = { + .funcs = &mmc_dev_funcs, + .info = 0, +}; + +/* Identify the device type as mmc device */ +static io_type_t device_type_mmc(void) +{ + return IO_TYPE_MMC; +} + +/* Open a connection to the mmc device */ +static int mmc_dev_open(const uintptr_t init_params, io_dev_info_t **dev_info) +{ + struct io_mmc_dev_spec *device_spec = + (struct io_mmc_dev_spec *)init_params; + + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&mmc_dev_info; + + _read_blocks = !device_spec->use_boot_part ? + mmc_read_blocks : mmc_boot_part_read_blocks; + + return 0; +} + +static int mmc_dev_init(io_dev_info_t *dev_info, const uintptr_t init_params) +{ + return 0; +} + +/* Close a connection to the mmc device */ +static int mmc_dev_close(io_dev_info_t *dev_info) +{ + return 0; +} + +/* Open a file on the mmc device */ +static int mmc_block_open(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity) +{ + seek_offset = 0; + return 0; +} + +/* Seek to a particular file offset on the mmc device */ +static int mmc_block_seek(io_entity_t *entity, int mode, + signed long long offset) +{ + seek_offset = offset; + return 0; +} + +/* Read data from a file on the mmc device */ +static int mmc_block_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + uint8_t retries; + + for (retries = 0U; retries < 3U; retries++) { + *length_read = _read_blocks(seek_offset / MMC_BLOCK_SIZE, + buffer, length); + + if (*length_read == length) { + return 0; + } + WARN("%s: length_read = %lu (!= %lu), retry %u\n", __func__, + (unsigned long)*length_read, (unsigned long)length, + retries + 1U); + } + + return -EIO; +} + +/* Close a file on the mmc device */ +static int mmc_block_close(io_entity_t *entity) +{ + return 0; +} + +/* Register the mmc driver with the IO abstraction */ +int register_io_dev_mmc(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&mmc_dev_info); + if (result == 0) { + *dev_con = &mmc_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/st/io/io_stm32image.c b/arm-trusted-firmware/drivers/st/io/io_stm32image.c new file mode 100644 index 0000000..9fa0c50 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/io/io_stm32image.c @@ -0,0 +1,379 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +static uintptr_t backend_dev_handle; +static uintptr_t backend_image_spec; +static uint32_t *stm32_img; +static uint8_t first_lba_buffer[MAX_LBA_SIZE] __aligned(4); +static struct stm32image_part_info *current_part; + +/* STM32 Image driver functions */ +static int stm32image_dev_open(const uintptr_t init_params, + io_dev_info_t **dev_info); +static int stm32image_partition_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity); +static int stm32image_partition_size(io_entity_t *entity, size_t *length); +static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read); +static int stm32image_partition_close(io_entity_t *entity); +static int stm32image_dev_init(io_dev_info_t *dev_info, + const uintptr_t init_params); +static int stm32image_dev_close(io_dev_info_t *dev_info); + +/* Identify the device type as a virtual driver */ +static io_type_t device_type_stm32image(void) +{ + return IO_TYPE_STM32IMAGE; +} + +static const io_dev_connector_t stm32image_dev_connector = { + .dev_open = stm32image_dev_open +}; + +static const io_dev_funcs_t stm32image_dev_funcs = { + .type = device_type_stm32image, + .open = stm32image_partition_open, + .size = stm32image_partition_size, + .read = stm32image_partition_read, + .close = stm32image_partition_close, + .dev_init = stm32image_dev_init, + .dev_close = stm32image_dev_close, +}; + +static io_dev_info_t stm32image_dev_info = { + .funcs = &stm32image_dev_funcs, + .info = (uintptr_t)0, +}; + +static struct stm32image_device_info stm32image_dev; + +static int get_part_idx_by_binary_type(uint32_t binary_type) +{ + int i; + + for (i = 0; i < STM32_PART_NUM; i++) { + if (stm32image_dev.part_info[i].binary_type == binary_type) { + return i; + } + } + + return -EINVAL; +} + +/* Open a connection to the STM32IMAGE device */ +static int stm32image_dev_open(const uintptr_t init_params, + io_dev_info_t **dev_info) +{ + int i; + struct stm32image_device_info *device_info = + (struct stm32image_device_info *)init_params; + + assert(dev_info != NULL); + *dev_info = (io_dev_info_t *)&stm32image_dev_info; + + stm32image_dev.device_size = device_info->device_size; + stm32image_dev.lba_size = device_info->lba_size; + + for (i = 0; i < STM32_PART_NUM; i++) { + memcpy(stm32image_dev.part_info[i].name, + device_info->part_info[i].name, MAX_PART_NAME_SIZE); + stm32image_dev.part_info[i].binary_type = + device_info->part_info[i].binary_type; + stm32image_dev.part_info[i].part_offset = + device_info->part_info[i].part_offset; + stm32image_dev.part_info[i].bkp_offset = + device_info->part_info[i].bkp_offset; + } + + return 0; +} + +/* Do some basic package checks */ +static int stm32image_dev_init(io_dev_info_t *dev_info, + const uintptr_t init_params) +{ + int result; + + if ((backend_dev_handle != 0U) || (backend_image_spec != 0U)) { + ERROR("STM32 Image io supports only one session\n"); + return -ENOMEM; + } + + /* Obtain a reference to the image by querying the platform layer */ + result = plat_get_image_source(STM32_IMAGE_ID, &backend_dev_handle, + &backend_image_spec); + if (result != 0) { + ERROR("STM32 image error (%i)\n", result); + return -EINVAL; + } + + return result; +} + +/* Close a connection to the STM32 Image device */ +static int stm32image_dev_close(io_dev_info_t *dev_info) +{ + backend_dev_handle = 0U; + backend_image_spec = 0U; + stm32_img = NULL; + + return 0; +} + +/* Open a partition */ +static int stm32image_partition_open(io_dev_info_t *dev_info, + const uintptr_t spec, io_entity_t *entity) +{ + const struct stm32image_part_info *partition_spec; + int idx; + + assert(entity != NULL); + + partition_spec = (struct stm32image_part_info *)spec; + assert(partition_spec != NULL); + + idx = get_part_idx_by_binary_type(partition_spec->binary_type); + if ((idx < 0) || (idx > STM32_PART_NUM)) { + ERROR("Wrong partition index (%d)\n", idx); + return -EINVAL; + } + + current_part = &stm32image_dev.part_info[idx]; + stm32_img = (uint32_t *)¤t_part->part_offset; + + return 0; +} + +/* Return the size of a partition */ +static int stm32image_partition_size(io_entity_t *entity, size_t *length) +{ + int result; + uintptr_t backend_handle; + size_t bytes_read; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_lba_buffer; + + assert(entity != NULL); + assert(length != NULL); + + /* Attempt to access the image */ + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + + if (result < 0) { + ERROR("%s: io_open (%i)\n", __func__, result); + return result; + } + + /* Reset magic header value */ + header->magic = 0; + + while (header->magic == 0U) { + result = io_seek(backend_handle, IO_SEEK_SET, *stm32_img); + if (result != 0) { + ERROR("%s: io_seek (%i)\n", __func__, result); + break; + } + + result = io_read(backend_handle, (uintptr_t)header, + MAX_LBA_SIZE, (size_t *)&bytes_read); + if (result != 0) { + if (current_part->bkp_offset == 0U) { + ERROR("%s: io_read (%i)\n", __func__, result); + } + header->magic = 0; + } + + if ((header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) || + (header->binary_type != current_part->binary_type) || + (header->image_length >= stm32image_dev.device_size)) { + VERBOSE("%s: partition %s not found at %x\n", + __func__, current_part->name, *stm32_img); + + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } + + /* Header not correct, check next offset for backup */ + *stm32_img += current_part->bkp_offset; + if (*stm32_img > stm32image_dev.device_size) { + /* No backup found, end of device reached */ + WARN("%s : partition %s not found\n", + __func__, current_part->name); + result = -ENOMEM; + break; + } + header->magic = 0; + } + } + + io_close(backend_handle); + + if (result != 0) { + return result; + } + + if (header->image_length < stm32image_dev.lba_size) { + *length = stm32image_dev.lba_size; + } else { + *length = header->image_length; + } + + INFO("STM32 Image size : %lu\n", (unsigned long)*length); + + return 0; +} + +/* Read data from a partition */ +static int stm32image_partition_read(io_entity_t *entity, uintptr_t buffer, + size_t length, size_t *length_read) +{ + int result = -EINVAL; + uint8_t *local_buffer; + boot_api_image_header_t *header = + (boot_api_image_header_t *)first_lba_buffer; + size_t hdr_sz = sizeof(boot_api_image_header_t); + + assert(entity != NULL); + assert(buffer != 0U); + assert(length_read != NULL); + + local_buffer = (uint8_t *)buffer; + *length_read = 0U; + + while (*length_read == 0U) { + int offset; + int local_length; + uintptr_t backend_handle; + + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { + /* Check for backup as image is corrupted */ + if (current_part->bkp_offset == 0U) { + result = -ENOMEM; + break; + } + + *stm32_img += current_part->bkp_offset; + if (*stm32_img >= stm32image_dev.device_size) { + /* End of device reached */ + result = -ENOMEM; + break; + } + + local_buffer = (uint8_t *)buffer; + + result = stm32image_partition_size(entity, &length); + if (result != 0) { + break; + } + } + + /* Part of image already loaded with the header */ + memcpy(local_buffer, (uint8_t *)first_lba_buffer + hdr_sz, + MAX_LBA_SIZE - hdr_sz); + local_buffer += MAX_LBA_SIZE - hdr_sz; + offset = MAX_LBA_SIZE; + + /* New image length to be read */ + local_length = round_up(length - ((MAX_LBA_SIZE) - hdr_sz), + stm32image_dev.lba_size); + + if ((header->load_address != 0U) && + (header->load_address != buffer)) { + ERROR("Wrong load address\n"); + panic(); + } + + result = io_open(backend_dev_handle, backend_image_spec, + &backend_handle); + + if (result != 0) { + ERROR("%s: io_open (%i)\n", __func__, result); + break; + } + + result = io_seek(backend_handle, IO_SEEK_SET, + *stm32_img + offset); + + if (result != 0) { + ERROR("%s: io_seek (%i)\n", __func__, result); + *length_read = 0; + io_close(backend_handle); + break; + } + + result = io_read(backend_handle, (uintptr_t)local_buffer, + local_length, length_read); + + /* Adding part of size already read from header */ + *length_read += MAX_LBA_SIZE - hdr_sz; + + if (result != 0) { + ERROR("%s: io_read (%i)\n", __func__, result); + *length_read = 0; + header->magic = 0; + continue; + } + + result = stm32mp_check_header(header, buffer); + if (result != 0) { + ERROR("Header check failed\n"); + *length_read = 0; + header->magic = 0; + } + + result = stm32mp_auth_image(header, buffer); + if (result != 0) { + ERROR("Authentication Failed (%i)\n", result); + return result; + } + + inv_dcache_range(round_up((uintptr_t)(local_buffer + length - hdr_sz), + CACHE_WRITEBACK_GRANULE), *length_read - length + hdr_sz); + + io_close(backend_handle); + } + + return result; +} + +/* Close a partition */ +static int stm32image_partition_close(io_entity_t *entity) +{ + current_part = NULL; + + return 0; +} + +/* Register the stm32image driver with the IO abstraction */ +int register_io_dev_stm32image(const io_dev_connector_t **dev_con) +{ + int result; + + assert(dev_con != NULL); + + result = io_register_device(&stm32image_dev_info); + if (result == 0) { + *dev_con = &stm32image_dev_connector; + } + + return result; +} diff --git a/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c b/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c new file mode 100644 index 0000000..74451d7 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* IWDG registers offsets */ +#define IWDG_KR_OFFSET 0x00U + +/* Registers values */ +#define IWDG_KR_RELOAD_KEY 0xAAAA + +struct stm32_iwdg_instance { + uintptr_t base; + unsigned long clock; + uint8_t flags; + int num_irq; +}; + +static struct stm32_iwdg_instance stm32_iwdg[IWDG_MAX_INSTANCE]; + +static int stm32_iwdg_get_dt_node(struct dt_node_info *info, int offset) +{ + int node; + + node = dt_get_node(info, offset, DT_IWDG_COMPAT); + if (node < 0) { + if (offset == -1) { + VERBOSE("%s: No IDWG found\n", __func__); + } + return -FDT_ERR_NOTFOUND; + } + + return node; +} + +void stm32_iwdg_refresh(void) +{ + uint8_t i; + + for (i = 0U; i < IWDG_MAX_INSTANCE; i++) { + struct stm32_iwdg_instance *iwdg = &stm32_iwdg[i]; + + /* 0x00000000 is not a valid address for IWDG peripherals */ + if (iwdg->base != 0U) { + clk_enable(iwdg->clock); + + mmio_write_32(iwdg->base + IWDG_KR_OFFSET, + IWDG_KR_RELOAD_KEY); + + clk_disable(iwdg->clock); + } + } +} + +int stm32_iwdg_init(void) +{ + int node = -1; + struct dt_node_info dt_info; + void *fdt; + uint32_t __unused count = 0; + + if (fdt_get_address(&fdt) == 0) { + panic(); + } + + for (node = stm32_iwdg_get_dt_node(&dt_info, node); + node != -FDT_ERR_NOTFOUND; + node = stm32_iwdg_get_dt_node(&dt_info, node)) { + struct stm32_iwdg_instance *iwdg; + uint32_t hw_init; + uint32_t idx; + + count++; + + idx = stm32_iwdg_get_instance(dt_info.base); + iwdg = &stm32_iwdg[idx]; + iwdg->base = dt_info.base; + iwdg->clock = (unsigned long)dt_info.clock; + + /* DT can specify low power cases */ + if (fdt_getprop(fdt, node, "stm32,enable-on-stop", NULL) == + NULL) { + iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + + if (fdt_getprop(fdt, node, "stm32,enable-on-standby", NULL) == + NULL) { + iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + /* Explicit list of supported bit flags */ + hw_init = stm32_iwdg_get_otp_config(idx); + + if ((hw_init & IWDG_HW_ENABLED) != 0) { + if (dt_info.status == DT_DISABLED) { + ERROR("OTP enabled but iwdg%u DT-disabled\n", + idx + 1U); + panic(); + } + iwdg->flags |= IWDG_HW_ENABLED; + } + + if (dt_info.status == DT_DISABLED) { + zeromem((void *)iwdg, + sizeof(struct stm32_iwdg_instance)); + continue; + } + + if ((hw_init & IWDG_DISABLE_ON_STOP) != 0) { + iwdg->flags |= IWDG_DISABLE_ON_STOP; + } + + if ((hw_init & IWDG_DISABLE_ON_STANDBY) != 0) { + iwdg->flags |= IWDG_DISABLE_ON_STANDBY; + } + + VERBOSE("IWDG%u found, %ssecure\n", idx + 1U, + ((dt_info.status & DT_NON_SECURE) != 0) ? + "non-" : ""); + + if ((dt_info.status & DT_NON_SECURE) != 0) { + stm32mp_register_non_secure_periph_iomem(iwdg->base); + } else { + stm32mp_register_secure_periph_iomem(iwdg->base); + } + +#if defined(IMAGE_BL2) + if (stm32_iwdg_shadow_update(idx, iwdg->flags) != BSEC_OK) { + return -1; + } +#endif + } + + VERBOSE("%u IWDG instance%s found\n", count, (count > 1U) ? "s" : ""); + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c b/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c new file mode 100644 index 0000000..40641b5 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c @@ -0,0 +1,776 @@ +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* Registers offsets */ +#define SDMMC_POWER 0x00U +#define SDMMC_CLKCR 0x04U +#define SDMMC_ARGR 0x08U +#define SDMMC_CMDR 0x0CU +#define SDMMC_RESPCMDR 0x10U +#define SDMMC_RESP1R 0x14U +#define SDMMC_RESP2R 0x18U +#define SDMMC_RESP3R 0x1CU +#define SDMMC_RESP4R 0x20U +#define SDMMC_DTIMER 0x24U +#define SDMMC_DLENR 0x28U +#define SDMMC_DCTRLR 0x2CU +#define SDMMC_DCNTR 0x30U +#define SDMMC_STAR 0x34U +#define SDMMC_ICR 0x38U +#define SDMMC_MASKR 0x3CU +#define SDMMC_ACKTIMER 0x40U +#define SDMMC_IDMACTRLR 0x50U +#define SDMMC_IDMABSIZER 0x54U +#define SDMMC_IDMABASE0R 0x58U +#define SDMMC_IDMABASE1R 0x5CU +#define SDMMC_FIFOR 0x80U + +/* SDMMC power control register */ +#define SDMMC_POWER_PWRCTRL GENMASK(1, 0) +#define SDMMC_POWER_PWRCTRL_PWR_CYCLE BIT(1) +#define SDMMC_POWER_DIRPOL BIT(4) + +/* SDMMC clock control register */ +#define SDMMC_CLKCR_WIDBUS_4 BIT(14) +#define SDMMC_CLKCR_WIDBUS_8 BIT(15) +#define SDMMC_CLKCR_NEGEDGE BIT(16) +#define SDMMC_CLKCR_HWFC_EN BIT(17) +#define SDMMC_CLKCR_SELCLKRX_0 BIT(20) + +/* SDMMC command register */ +#define SDMMC_CMDR_CMDTRANS BIT(6) +#define SDMMC_CMDR_CMDSTOP BIT(7) +#define SDMMC_CMDR_WAITRESP GENMASK(9, 8) +#define SDMMC_CMDR_WAITRESP_SHORT BIT(8) +#define SDMMC_CMDR_WAITRESP_SHORT_NOCRC BIT(9) +#define SDMMC_CMDR_CPSMEN BIT(12) + +/* SDMMC data control register */ +#define SDMMC_DCTRLR_DTEN BIT(0) +#define SDMMC_DCTRLR_DTDIR BIT(1) +#define SDMMC_DCTRLR_DTMODE GENMASK(3, 2) +#define SDMMC_DCTRLR_DBLOCKSIZE GENMASK(7, 4) +#define SDMMC_DCTRLR_DBLOCKSIZE_SHIFT 4 +#define SDMMC_DCTRLR_FIFORST BIT(13) + +#define SDMMC_DCTRLR_CLEAR_MASK (SDMMC_DCTRLR_DTEN | \ + SDMMC_DCTRLR_DTDIR | \ + SDMMC_DCTRLR_DTMODE | \ + SDMMC_DCTRLR_DBLOCKSIZE) + +/* SDMMC status register */ +#define SDMMC_STAR_CCRCFAIL BIT(0) +#define SDMMC_STAR_DCRCFAIL BIT(1) +#define SDMMC_STAR_CTIMEOUT BIT(2) +#define SDMMC_STAR_DTIMEOUT BIT(3) +#define SDMMC_STAR_TXUNDERR BIT(4) +#define SDMMC_STAR_RXOVERR BIT(5) +#define SDMMC_STAR_CMDREND BIT(6) +#define SDMMC_STAR_CMDSENT BIT(7) +#define SDMMC_STAR_DATAEND BIT(8) +#define SDMMC_STAR_DBCKEND BIT(10) +#define SDMMC_STAR_DPSMACT BIT(12) +#define SDMMC_STAR_RXFIFOHF BIT(15) +#define SDMMC_STAR_RXFIFOE BIT(19) +#define SDMMC_STAR_IDMATE BIT(27) +#define SDMMC_STAR_IDMABTC BIT(28) + +/* SDMMC DMA control register */ +#define SDMMC_IDMACTRLR_IDMAEN BIT(0) + +#define SDMMC_STATIC_FLAGS (SDMMC_STAR_CCRCFAIL | \ + SDMMC_STAR_DCRCFAIL | \ + SDMMC_STAR_CTIMEOUT | \ + SDMMC_STAR_DTIMEOUT | \ + SDMMC_STAR_TXUNDERR | \ + SDMMC_STAR_RXOVERR | \ + SDMMC_STAR_CMDREND | \ + SDMMC_STAR_CMDSENT | \ + SDMMC_STAR_DATAEND | \ + SDMMC_STAR_DBCKEND | \ + SDMMC_STAR_IDMATE | \ + SDMMC_STAR_IDMABTC) + +#define TIMEOUT_US_1_MS 1000U +#define TIMEOUT_US_10_MS 10000U +#define TIMEOUT_US_1_S 1000000U + +/* Power cycle delays in ms */ +#define VCC_POWER_OFF_DELAY 2 +#define VCC_POWER_ON_DELAY 2 +#define POWER_CYCLE_DELAY 2 +#define POWER_OFF_DELAY 2 +#define POWER_ON_DELAY 1 + +#ifndef DT_SDMMC2_COMPAT +#define DT_SDMMC2_COMPAT "st,stm32-sdmmc2" +#endif + +static void stm32_sdmmc2_init(void); +static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd); +static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd); +static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width); +static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size); +static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size); +static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops stm32_sdmmc2_ops = { + .init = stm32_sdmmc2_init, + .send_cmd = stm32_sdmmc2_send_cmd, + .set_ios = stm32_sdmmc2_set_ios, + .prepare = stm32_sdmmc2_prepare, + .read = stm32_sdmmc2_read, + .write = stm32_sdmmc2_write, +}; + +static struct stm32_sdmmc2_params sdmmc2_params; + +#pragma weak plat_sdmmc2_use_dma +bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory) +{ + return false; +} + +static void stm32_sdmmc2_init(void) +{ + uint32_t clock_div; + uint32_t freq = STM32MP_MMC_INIT_FREQ; + uintptr_t base = sdmmc2_params.reg_base; + int ret; + + if (sdmmc2_params.max_freq != 0U) { + freq = MIN(sdmmc2_params.max_freq, freq); + } + + if (sdmmc2_params.vmmc_regu != NULL) { + ret = regulator_disable(sdmmc2_params.vmmc_regu); + if (ret < 0) { + panic(); + } + } + + mdelay(VCC_POWER_OFF_DELAY); + + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL_PWR_CYCLE | sdmmc2_params.dirpol); + mdelay(POWER_CYCLE_DELAY); + + if (sdmmc2_params.vmmc_regu != NULL) { + ret = regulator_enable(sdmmc2_params.vmmc_regu); + if (ret < 0) { + panic(); + } + } + + mdelay(VCC_POWER_ON_DELAY); + + mmio_write_32(base + SDMMC_POWER, sdmmc2_params.dirpol); + mdelay(POWER_OFF_DELAY); + + clock_div = div_round_up(sdmmc2_params.clk_rate, freq * 2U); + + mmio_write_32(base + SDMMC_CLKCR, SDMMC_CLKCR_HWFC_EN | clock_div | + sdmmc2_params.negedge | + sdmmc2_params.pin_ckin); + + mmio_write_32(base + SDMMC_POWER, + SDMMC_POWER_PWRCTRL | sdmmc2_params.dirpol); + + mdelay(POWER_ON_DELAY); +} + +static int stm32_sdmmc2_stop_transfer(void) +{ + struct mmc_cmd cmd_stop; + + zeromem(&cmd_stop, sizeof(struct mmc_cmd)); + + cmd_stop.cmd_idx = MMC_CMD(12); + cmd_stop.resp_type = MMC_RESPONSE_R1B; + + return stm32_sdmmc2_send_cmd(&cmd_stop); +} + +static int stm32_sdmmc2_send_cmd_req(struct mmc_cmd *cmd) +{ + uint64_t timeout; + uint32_t flags_cmd, status; + uint32_t flags_data = 0; + int err = 0; + uintptr_t base = sdmmc2_params.reg_base; + unsigned int cmd_reg, arg_reg; + + if (cmd == NULL) { + return -EINVAL; + } + + flags_cmd = SDMMC_STAR_CTIMEOUT; + arg_reg = cmd->cmd_arg; + + if ((mmio_read_32(base + SDMMC_CMDR) & SDMMC_CMDR_CPSMEN) != 0U) { + mmio_write_32(base + SDMMC_CMDR, 0); + } + + cmd_reg = cmd->cmd_idx | SDMMC_CMDR_CPSMEN; + + if (cmd->resp_type == 0U) { + flags_cmd |= SDMMC_STAR_CMDSENT; + } + + if ((cmd->resp_type & MMC_RSP_48) != 0U) { + if ((cmd->resp_type & MMC_RSP_136) != 0U) { + flags_cmd |= SDMMC_STAR_CMDREND; + cmd_reg |= SDMMC_CMDR_WAITRESP; + } else if ((cmd->resp_type & MMC_RSP_CRC) != 0U) { + flags_cmd |= SDMMC_STAR_CMDREND | SDMMC_STAR_CCRCFAIL; + cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT; + } else { + flags_cmd |= SDMMC_STAR_CMDREND; + cmd_reg |= SDMMC_CMDR_WAITRESP_SHORT_NOCRC; + } + } + + switch (cmd->cmd_idx) { + case MMC_CMD(1): + arg_reg |= OCR_POWERUP; + break; + case MMC_CMD(8): + if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + cmd_reg |= SDMMC_CMDR_CMDTRANS; + } + break; + case MMC_CMD(12): + cmd_reg |= SDMMC_CMDR_CMDSTOP; + break; + case MMC_CMD(17): + case MMC_CMD(18): + cmd_reg |= SDMMC_CMDR_CMDTRANS; + if (sdmmc2_params.use_dma) { + flags_data |= SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT | + SDMMC_STAR_DATAEND | + SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE; + } + break; + case MMC_ACMD(41): + arg_reg |= OCR_3_2_3_3 | OCR_3_3_3_4; + break; + case MMC_ACMD(51): + cmd_reg |= SDMMC_CMDR_CMDTRANS; + if (sdmmc2_params.use_dma) { + flags_data |= SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT | + SDMMC_STAR_DATAEND | + SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE | + SDMMC_STAR_DBCKEND; + } + break; + default: + break; + } + + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + /* + * Clear the SDMMC_DCTRLR if the command does not await data. + * Skip CMD55 as the next command could be data related, and + * the register could have been set in prepare function. + */ + if (((cmd_reg & SDMMC_CMDR_CMDTRANS) == 0U) && + (cmd->cmd_idx != MMC_CMD(55))) { + mmio_write_32(base + SDMMC_DCTRLR, 0U); + } + + if ((cmd->resp_type & MMC_RSP_BUSY) != 0U) { + mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + } + + mmio_write_32(base + SDMMC_ARGR, arg_reg); + + mmio_write_32(base + SDMMC_CMDR, cmd_reg); + + status = mmio_read_32(base + SDMMC_STAR); + + timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((status & flags_cmd) == 0U) { + if (timeout_elapsed(timeout)) { + err = -ETIMEDOUT; + ERROR("%s: timeout 10ms (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + goto err_exit; + } + + status = mmio_read_32(base + SDMMC_STAR); + } + + if ((status & (SDMMC_STAR_CTIMEOUT | SDMMC_STAR_CCRCFAIL)) != 0U) { + if ((status & SDMMC_STAR_CTIMEOUT) != 0U) { + err = -ETIMEDOUT; + /* + * Those timeouts can occur, and framework will handle + * the retries. CMD8 is expected to return this timeout + * for eMMC + */ + if (!((cmd->cmd_idx == MMC_CMD(1)) || + (cmd->cmd_idx == MMC_CMD(13)) || + ((cmd->cmd_idx == MMC_CMD(8)) && + (cmd->resp_type == MMC_RESPONSE_R7)))) { + ERROR("%s: CTIMEOUT (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + } + } else { + err = -EIO; + ERROR("%s: CRCFAIL (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + } + + goto err_exit; + } + + if ((cmd_reg & SDMMC_CMDR_WAITRESP) != 0U) { + if ((cmd->cmd_idx == MMC_CMD(9)) && + ((cmd_reg & SDMMC_CMDR_WAITRESP) == SDMMC_CMDR_WAITRESP)) { + /* Need to invert response to match CSD structure */ + cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP4R); + cmd->resp_data[1] = mmio_read_32(base + SDMMC_RESP3R); + cmd->resp_data[2] = mmio_read_32(base + SDMMC_RESP2R); + cmd->resp_data[3] = mmio_read_32(base + SDMMC_RESP1R); + } else { + cmd->resp_data[0] = mmio_read_32(base + SDMMC_RESP1R); + if ((cmd_reg & SDMMC_CMDR_WAITRESP) == + SDMMC_CMDR_WAITRESP) { + cmd->resp_data[1] = mmio_read_32(base + + SDMMC_RESP2R); + cmd->resp_data[2] = mmio_read_32(base + + SDMMC_RESP3R); + cmd->resp_data[3] = mmio_read_32(base + + SDMMC_RESP4R); + } + } + } + + if (flags_data == 0U) { + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + return 0; + } + + status = mmio_read_32(base + SDMMC_STAR); + + timeout = timeout_init_us(TIMEOUT_US_10_MS); + + while ((status & flags_data) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: timeout 10ms (cmd = %u,status = %x)\n", + __func__, cmd->cmd_idx, status); + err = -ETIMEDOUT; + goto err_exit; + } + + status = mmio_read_32(base + SDMMC_STAR); + }; + + if ((status & (SDMMC_STAR_DTIMEOUT | SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_TXUNDERR | SDMMC_STAR_RXOVERR | + SDMMC_STAR_IDMATE)) != 0U) { + ERROR("%s: Error flag (cmd = %u,status = %x)\n", __func__, + cmd->cmd_idx, status); + err = -EIO; + } + +err_exit: + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + mmio_clrbits_32(base + SDMMC_CMDR, SDMMC_CMDR_CMDTRANS); + + if ((err != 0) && ((status & SDMMC_STAR_DPSMACT) != 0U)) { + int ret_stop = stm32_sdmmc2_stop_transfer(); + + if (ret_stop != 0) { + return ret_stop; + } + } + + return err; +} + +static int stm32_sdmmc2_send_cmd(struct mmc_cmd *cmd) +{ + uint8_t retry; + int err; + + assert(cmd != NULL); + + for (retry = 0U; retry < 3U; retry++) { + err = stm32_sdmmc2_send_cmd_req(cmd); + if (err == 0) { + return 0; + } + + if ((cmd->cmd_idx == MMC_CMD(1)) || + (cmd->cmd_idx == MMC_CMD(13))) { + return 0; /* Retry managed by framework */ + } + + /* Command 8 is expected to fail for eMMC */ + if (cmd->cmd_idx != MMC_CMD(8)) { + WARN(" CMD%u, Retry: %u, Error: %d\n", + cmd->cmd_idx, retry + 1U, err); + } + + udelay(10U); + } + + return err; +} + +static int stm32_sdmmc2_set_ios(unsigned int clk, unsigned int width) +{ + uintptr_t base = sdmmc2_params.reg_base; + uint32_t bus_cfg = 0; + uint32_t clock_div, max_freq, freq; + uint32_t clk_rate = sdmmc2_params.clk_rate; + uint32_t max_bus_freq = sdmmc2_params.device_info->max_bus_freq; + + switch (width) { + case MMC_BUS_WIDTH_1: + break; + case MMC_BUS_WIDTH_4: + bus_cfg |= SDMMC_CLKCR_WIDBUS_4; + break; + case MMC_BUS_WIDTH_8: + bus_cfg |= SDMMC_CLKCR_WIDBUS_8; + break; + default: + panic(); + break; + } + + if (sdmmc2_params.device_info->mmc_dev_type == MMC_IS_EMMC) { + if (max_bus_freq >= 52000000U) { + max_freq = STM32MP_EMMC_HIGH_SPEED_MAX_FREQ; + } else { + max_freq = STM32MP_EMMC_NORMAL_SPEED_MAX_FREQ; + } + } else { + if (max_bus_freq >= 50000000U) { + max_freq = STM32MP_SD_HIGH_SPEED_MAX_FREQ; + } else { + max_freq = STM32MP_SD_NORMAL_SPEED_MAX_FREQ; + } + } + + if (sdmmc2_params.max_freq != 0U) { + freq = MIN(sdmmc2_params.max_freq, max_freq); + } else { + freq = max_freq; + } + + clock_div = div_round_up(clk_rate, freq * 2U); + + mmio_write_32(base + SDMMC_CLKCR, + SDMMC_CLKCR_HWFC_EN | clock_div | bus_cfg | + sdmmc2_params.negedge | + sdmmc2_params.pin_ckin); + + return 0; +} + +static int stm32_sdmmc2_prepare(int lba, uintptr_t buf, size_t size) +{ + struct mmc_cmd cmd; + int ret; + uintptr_t base = sdmmc2_params.reg_base; + uint32_t data_ctrl = SDMMC_DCTRLR_DTDIR; + uint32_t arg_size; + + assert(size != 0U); + + if (size > MMC_BLOCK_SIZE) { + arg_size = MMC_BLOCK_SIZE; + } else { + arg_size = size; + } + + sdmmc2_params.use_dma = plat_sdmmc2_use_dma(base, buf); + + if (sdmmc2_params.use_dma) { + inv_dcache_range(buf, size); + } + + /* Prepare CMD 16*/ + mmio_write_32(base + SDMMC_DTIMER, 0); + + mmio_write_32(base + SDMMC_DLENR, 0); + + mmio_write_32(base + SDMMC_DCTRLR, 0); + + zeromem(&cmd, sizeof(struct mmc_cmd)); + + cmd.cmd_idx = MMC_CMD(16); + cmd.cmd_arg = arg_size; + cmd.resp_type = MMC_RESPONSE_R1; + + ret = stm32_sdmmc2_send_cmd(&cmd); + if (ret != 0) { + ERROR("CMD16 failed\n"); + return ret; + } + + /* Prepare data command */ + mmio_write_32(base + SDMMC_DTIMER, UINT32_MAX); + + mmio_write_32(base + SDMMC_DLENR, size); + + if (sdmmc2_params.use_dma) { + mmio_write_32(base + SDMMC_IDMACTRLR, + SDMMC_IDMACTRLR_IDMAEN); + mmio_write_32(base + SDMMC_IDMABASE0R, buf); + + flush_dcache_range(buf, size); + } + + data_ctrl |= __builtin_ctz(arg_size) << SDMMC_DCTRLR_DBLOCKSIZE_SHIFT; + + mmio_clrsetbits_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_CLEAR_MASK, + data_ctrl); + + return 0; +} + +static int stm32_sdmmc2_read(int lba, uintptr_t buf, size_t size) +{ + uint32_t error_flags = SDMMC_STAR_RXOVERR | SDMMC_STAR_DCRCFAIL | + SDMMC_STAR_DTIMEOUT; + uint32_t flags = error_flags | SDMMC_STAR_DATAEND; + uint32_t status; + uint32_t *buffer; + uintptr_t base = sdmmc2_params.reg_base; + uintptr_t fifo_reg = base + SDMMC_FIFOR; + uint64_t timeout; + int ret; + + /* Assert buf is 4 bytes aligned */ + assert((buf & GENMASK(1, 0)) == 0U); + + buffer = (uint32_t *)buf; + + if (sdmmc2_params.use_dma) { + inv_dcache_range(buf, size); + + return 0; + } + + if (size <= MMC_BLOCK_SIZE) { + flags |= SDMMC_STAR_DBCKEND; + } + + timeout = timeout_init_us(TIMEOUT_US_1_S); + + do { + status = mmio_read_32(base + SDMMC_STAR); + + if ((status & error_flags) != 0U) { + ERROR("%s: Read error (status = %x)\n", __func__, + status); + mmio_write_32(base + SDMMC_DCTRLR, + SDMMC_DCTRLR_FIFORST); + + mmio_write_32(base + SDMMC_ICR, + SDMMC_STATIC_FLAGS); + + ret = stm32_sdmmc2_stop_transfer(); + if (ret != 0) { + return ret; + } + + return -EIO; + } + + if (timeout_elapsed(timeout)) { + ERROR("%s: timeout 1s (status = %x)\n", + __func__, status); + mmio_write_32(base + SDMMC_ICR, + SDMMC_STATIC_FLAGS); + + ret = stm32_sdmmc2_stop_transfer(); + if (ret != 0) { + return ret; + } + + return -ETIMEDOUT; + } + + if (size < (8U * sizeof(uint32_t))) { + if ((mmio_read_32(base + SDMMC_DCNTR) > 0U) && + ((status & SDMMC_STAR_RXFIFOE) == 0U)) { + *buffer = mmio_read_32(fifo_reg); + buffer++; + } + } else if ((status & SDMMC_STAR_RXFIFOHF) != 0U) { + uint32_t count; + + /* Read data from SDMMC Rx FIFO */ + for (count = 0; count < 8U; count++) { + *buffer = mmio_read_32(fifo_reg); + buffer++; + } + } + } while ((status & flags) == 0U); + + mmio_write_32(base + SDMMC_ICR, SDMMC_STATIC_FLAGS); + + if ((status & SDMMC_STAR_DPSMACT) != 0U) { + WARN("%s: DPSMACT=1, send stop\n", __func__); + return stm32_sdmmc2_stop_transfer(); + } + + return 0; +} + +static int stm32_sdmmc2_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +static int stm32_sdmmc2_dt_get_config(void) +{ + int sdmmc_node; + void *fdt = NULL; + const fdt32_t *cuint; + struct dt_node_info dt_info; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + if (fdt == NULL) { + return -FDT_ERR_NOTFOUND; + } + + sdmmc_node = dt_match_instance_by_compatible(DT_SDMMC2_COMPAT, + sdmmc2_params.reg_base); + if (sdmmc_node == -FDT_ERR_NOTFOUND) { + return -FDT_ERR_NOTFOUND; + } + + dt_fill_device_info(&dt_info, sdmmc_node); + if (dt_info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + if (dt_set_pinctrl_config(sdmmc_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + sdmmc2_params.clock_id = dt_info.clock; + sdmmc2_params.reset_id = dt_info.reset; + + if ((fdt_getprop(fdt, sdmmc_node, "st,use-ckin", NULL)) != NULL) { + sdmmc2_params.pin_ckin = SDMMC_CLKCR_SELCLKRX_0; + } + + if ((fdt_getprop(fdt, sdmmc_node, "st,sig-dir", NULL)) != NULL) { + sdmmc2_params.dirpol = SDMMC_POWER_DIRPOL; + } + + if ((fdt_getprop(fdt, sdmmc_node, "st,neg-edge", NULL)) != NULL) { + sdmmc2_params.negedge = SDMMC_CLKCR_NEGEDGE; + } + + cuint = fdt_getprop(fdt, sdmmc_node, "bus-width", NULL); + if (cuint != NULL) { + switch (fdt32_to_cpu(*cuint)) { + case 4: + sdmmc2_params.bus_width = MMC_BUS_WIDTH_4; + break; + + case 8: + sdmmc2_params.bus_width = MMC_BUS_WIDTH_8; + break; + + default: + break; + } + } + + cuint = fdt_getprop(fdt, sdmmc_node, "max-frequency", NULL); + if (cuint != NULL) { + sdmmc2_params.max_freq = fdt32_to_cpu(*cuint); + } + + sdmmc2_params.vmmc_regu = regulator_get_by_supply_name(fdt, sdmmc_node, "vmmc"); + + return 0; +} + +unsigned long long stm32_sdmmc2_mmc_get_device_size(void) +{ + return sdmmc2_params.device_info->device_size; +} + +int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params) +{ + int rc; + + assert((params != NULL) && + ((params->reg_base & MMC_BLOCK_MASK) == 0U) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&sdmmc2_params, params, sizeof(struct stm32_sdmmc2_params)); + + sdmmc2_params.vmmc_regu = NULL; + + if (stm32_sdmmc2_dt_get_config() != 0) { + ERROR("%s: DT error\n", __func__); + return -ENOMEM; + } + + clk_enable(sdmmc2_params.clock_id); + + rc = stm32mp_reset_assert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); + if (rc != 0) { + panic(); + } + udelay(2); + rc = stm32mp_reset_deassert(sdmmc2_params.reset_id, TIMEOUT_US_1_MS); + if (rc != 0) { + panic(); + } + mdelay(1); + + sdmmc2_params.clk_rate = clk_get_rate(sdmmc2_params.clock_id); + sdmmc2_params.device_info->ocr_voltage = OCR_3_2_3_3 | OCR_3_3_3_4; + + return mmc_init(&stm32_sdmmc2_ops, sdmmc2_params.clk_rate, + sdmmc2_params.bus_width, sdmmc2_params.flags, + sdmmc2_params.device_info); +} diff --git a/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c b/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c new file mode 100644 index 0000000..5b43760 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#define PMIC_NODE_NOT_FOUND 1 + +static struct i2c_handle_s i2c_handle; +static uint32_t pmic_i2c_addr; + +static int register_pmic(void); + +static int dt_get_pmic_node(void *fdt) +{ + static int node = -FDT_ERR_BADOFFSET; + + if (node == -FDT_ERR_BADOFFSET) { + node = fdt_node_offset_by_compatible(fdt, -1, "st,stpmic1"); + } + + return node; +} + +int dt_pmic_status(void) +{ + static int status = -FDT_ERR_BADVALUE; + int node; + void *fdt; + + if (status != -FDT_ERR_BADVALUE) { + return status; + } + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + node = dt_get_pmic_node(fdt); + if (node <= 0) { + status = -FDT_ERR_NOTFOUND; + + return status; + } + + status = (int)fdt_get_status(node); + + return status; +} + +static bool dt_pmic_is_secure(void) +{ + int status = dt_pmic_status(); + + return (status >= 0) && + (status == DT_SECURE) && + (i2c_handle.dt_status == DT_SECURE); +} + +/* + * Get PMIC and its I2C bus configuration from the device tree. + * Return 0 on success, negative on error, 1 if no PMIC node is defined. + */ +static int dt_pmic_i2c_config(struct dt_node_info *i2c_info, + struct stm32_i2c_init_s *init) +{ + static int i2c_node = -FDT_ERR_NOTFOUND; + void *fdt; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + if (i2c_node == -FDT_ERR_NOTFOUND) { + int pmic_node; + const fdt32_t *cuint; + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) { + return PMIC_NODE_NOT_FOUND; + } + + cuint = fdt_getprop(fdt, pmic_node, "reg", NULL); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + pmic_i2c_addr = fdt32_to_cpu(*cuint) << 1; + if (pmic_i2c_addr > UINT16_MAX) { + return -FDT_ERR_BADVALUE; + } + + i2c_node = fdt_parent_offset(fdt, pmic_node); + if (i2c_node < 0) { + return -FDT_ERR_NOTFOUND; + } + } + + dt_fill_device_info(i2c_info, i2c_node); + if (i2c_info->base == 0U) { + return -FDT_ERR_NOTFOUND; + } + + return stm32_i2c_get_setup_from_fdt(fdt, i2c_node, init); +} + +bool initialize_pmic_i2c(void) +{ + int ret; + struct dt_node_info i2c_info; + struct i2c_handle_s *i2c = &i2c_handle; + struct stm32_i2c_init_s i2c_init; + + ret = dt_pmic_i2c_config(&i2c_info, &i2c_init); + if (ret < 0) { + ERROR("I2C configuration failed %d\n", ret); + panic(); + } + + if (ret != 0) { + return false; + } + + /* Initialize PMIC I2C */ + i2c->i2c_base_addr = i2c_info.base; + i2c->dt_status = i2c_info.status; + i2c->clock = i2c_info.clock; + i2c->i2c_state = I2C_STATE_RESET; + i2c_init.own_address1 = pmic_i2c_addr; + i2c_init.addressing_mode = I2C_ADDRESSINGMODE_7BIT; + i2c_init.dual_address_mode = I2C_DUALADDRESS_DISABLE; + i2c_init.own_address2 = 0; + i2c_init.own_address2_masks = I2C_OAR2_OA2NOMASK; + i2c_init.general_call_mode = I2C_GENERALCALL_DISABLE; + i2c_init.no_stretch_mode = I2C_NOSTRETCH_DISABLE; + i2c_init.analog_filter = 1; + i2c_init.digital_filter_coef = 0; + + ret = stm32_i2c_init(i2c, &i2c_init); + if (ret != 0) { + ERROR("Cannot initialize I2C %x (%d)\n", + i2c->i2c_base_addr, ret); + panic(); + } + + if (!stm32_i2c_is_device_ready(i2c, pmic_i2c_addr, 1, + I2C_TIMEOUT_BUSY_MS)) { + ERROR("I2C device not ready\n"); + panic(); + } + + stpmic1_bind_i2c(i2c, (uint16_t)pmic_i2c_addr); + + return true; +} + +static void register_pmic_shared_peripherals(void) +{ + uintptr_t i2c_base = i2c_handle.i2c_base_addr; + + if (dt_pmic_is_secure()) { + stm32mp_register_secure_periph_iomem(i2c_base); + } else { + if (i2c_base != 0U) { + stm32mp_register_non_secure_periph_iomem(i2c_base); + } + } +} + +void initialize_pmic(void) +{ + if (!initialize_pmic_i2c()) { + VERBOSE("No PMIC\n"); + return; + } + + register_pmic_shared_peripherals(); + + if (register_pmic() < 0) { + panic(); + } + + if (stpmic1_powerctrl_on() < 0) { + panic(); + } + +} + +#if DEBUG +void print_pmic_info_and_debug(void) +{ + unsigned long pmic_version; + + if (stpmic1_get_version(&pmic_version) != 0) { + ERROR("Failed to access PMIC\n"); + panic(); + } + + INFO("PMIC version = 0x%02lx\n", pmic_version); +} +#endif + +int pmic_ddr_power_init(enum ddr_type ddr_type) +{ + int status; + uint16_t buck3_min_mv; + struct rdev *buck2, *buck3, *vref; + struct rdev *ldo3 __unused; + + buck2 = regulator_get_by_name("buck2"); + if (buck2 == NULL) { + return -ENOENT; + } + +#if STM32MP15 + ldo3 = regulator_get_by_name("ldo3"); + if (ldo3 == NULL) { + return -ENOENT; + } +#endif + + vref = regulator_get_by_name("vref_ddr"); + if (vref == NULL) { + return -ENOENT; + } + + switch (ddr_type) { + case STM32MP_DDR3: +#if STM32MP15 + status = regulator_set_flag(ldo3, REGUL_SINK_SOURCE); + if (status != 0) { + return status; + } +#endif + + status = regulator_set_min_voltage(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(vref); + if (status != 0) { + return status; + } + +#if STM32MP15 + status = regulator_enable(ldo3); + if (status != 0) { + return status; + } +#endif + break; + + case STM32MP_LPDDR2: + case STM32MP_LPDDR3: + /* + * Set LDO3 to 1.8V + * Set LDO3 to bypass mode if BUCK3 = 1.8V + * Set LDO3 to normal mode if BUCK3 != 1.8V + */ + buck3 = regulator_get_by_name("buck3"); + if (buck3 == NULL) { + return -ENOENT; + } + + regulator_get_range(buck3, &buck3_min_mv, NULL); + +#if STM32MP15 + if (buck3_min_mv != 1800) { + status = regulator_set_min_voltage(ldo3); + if (status != 0) { + return status; + } + } else { + status = regulator_set_flag(ldo3, REGUL_ENABLE_BYPASS); + if (status != 0) { + return status; + } + } +#endif + + status = regulator_set_min_voltage(buck2); + if (status != 0) { + return status; + } + +#if STM32MP15 + status = regulator_enable(ldo3); + if (status != 0) { + return status; + } +#endif + + status = regulator_enable(buck2); + if (status != 0) { + return status; + } + + status = regulator_enable(vref); + if (status != 0) { + return status; + } + break; + + default: + break; + }; + + return 0; +} + +int pmic_voltages_init(void) +{ +#if STM32MP13 + struct rdev *buck1, *buck4; + int status; + + buck1 = regulator_get_by_name("buck1"); + if (buck1 == NULL) { + return -ENOENT; + } + + buck4 = regulator_get_by_name("buck4"); + if (buck4 == NULL) { + return -ENOENT; + } + + status = regulator_set_min_voltage(buck1); + if (status != 0) { + return status; + } + + status = regulator_set_min_voltage(buck4); + if (status != 0) { + return status; + } +#endif + + return 0; +} + +enum { + STPMIC1_BUCK1 = 0, + STPMIC1_BUCK2, + STPMIC1_BUCK3, + STPMIC1_BUCK4, + STPMIC1_LDO1, + STPMIC1_LDO2, + STPMIC1_LDO3, + STPMIC1_LDO4, + STPMIC1_LDO5, + STPMIC1_LDO6, + STPMIC1_VREF_DDR, + STPMIC1_BOOST, + STPMIC1_VBUS_OTG, + STPMIC1_SW_OUT, +}; + +static int pmic_set_state(const struct regul_description *desc, bool enable) +{ + VERBOSE("%s: set state to %d\n", desc->node_name, enable); + + if (enable == STATE_ENABLE) { + return stpmic1_regulator_enable(desc->node_name); + } else { + return stpmic1_regulator_disable(desc->node_name); + } +} + +static int pmic_get_state(const struct regul_description *desc) +{ + VERBOSE("%s: get state\n", desc->node_name); + + return stpmic1_is_regulator_enabled(desc->node_name); +} + +static int pmic_get_voltage(const struct regul_description *desc) +{ + VERBOSE("%s: get volt\n", desc->node_name); + + return stpmic1_regulator_voltage_get(desc->node_name); +} + +static int pmic_set_voltage(const struct regul_description *desc, uint16_t mv) +{ + VERBOSE("%s: get volt\n", desc->node_name); + + return stpmic1_regulator_voltage_set(desc->node_name, mv); +} + +static int pmic_list_voltages(const struct regul_description *desc, + const uint16_t **levels, size_t *count) +{ + VERBOSE("%s: list volt\n", desc->node_name); + + return stpmic1_regulator_levels_mv(desc->node_name, levels, count); +} + +static int pmic_set_flag(const struct regul_description *desc, uint16_t flag) +{ + VERBOSE("%s: set_flag 0x%x\n", desc->node_name, flag); + + switch (flag) { + case REGUL_OCP: + return stpmic1_regulator_icc_set(desc->node_name); + + case REGUL_ACTIVE_DISCHARGE: + return stpmic1_active_discharge_mode_set(desc->node_name); + + case REGUL_PULL_DOWN: + return stpmic1_regulator_pull_down_set(desc->node_name); + + case REGUL_MASK_RESET: + return stpmic1_regulator_mask_reset_set(desc->node_name); + + case REGUL_SINK_SOURCE: + return stpmic1_regulator_sink_mode_set(desc->node_name); + + case REGUL_ENABLE_BYPASS: + return stpmic1_regulator_bypass_mode_set(desc->node_name); + + default: + return -EINVAL; + } +} + +static const struct regul_ops pmic_ops = { + .set_state = pmic_set_state, + .get_state = pmic_get_state, + .set_voltage = pmic_set_voltage, + .get_voltage = pmic_get_voltage, + .list_voltages = pmic_list_voltages, + .set_flag = pmic_set_flag, +}; + +#define DEFINE_REGU(name) { \ + .node_name = name, \ + .ops = &pmic_ops, \ + .driver_data = NULL, \ + .enable_ramp_delay = 1000, \ +} + +static const struct regul_description pmic_regs[] = { + [STPMIC1_BUCK1] = DEFINE_REGU("buck1"), + [STPMIC1_BUCK2] = DEFINE_REGU("buck2"), + [STPMIC1_BUCK3] = DEFINE_REGU("buck3"), + [STPMIC1_BUCK4] = DEFINE_REGU("buck4"), + [STPMIC1_LDO1] = DEFINE_REGU("ldo1"), + [STPMIC1_LDO2] = DEFINE_REGU("ldo2"), + [STPMIC1_LDO3] = DEFINE_REGU("ldo3"), + [STPMIC1_LDO4] = DEFINE_REGU("ldo4"), + [STPMIC1_LDO5] = DEFINE_REGU("ldo5"), + [STPMIC1_LDO6] = DEFINE_REGU("ldo6"), + [STPMIC1_VREF_DDR] = DEFINE_REGU("vref_ddr"), + [STPMIC1_BOOST] = DEFINE_REGU("boost"), + [STPMIC1_VBUS_OTG] = DEFINE_REGU("pwr_sw1"), + [STPMIC1_SW_OUT] = DEFINE_REGU("pwr_sw2"), +}; + +#define NB_REG ARRAY_SIZE(pmic_regs) + +static int register_pmic(void) +{ + void *fdt; + int pmic_node, regulators_node, subnode; + + VERBOSE("Register pmic\n"); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + pmic_node = dt_get_pmic_node(fdt); + if (pmic_node < 0) { + return pmic_node; + } + + regulators_node = fdt_subnode_offset(fdt, pmic_node, "regulators"); + if (regulators_node < 0) { + return -ENOENT; + } + + fdt_for_each_subnode(subnode, fdt, regulators_node) { + const char *reg_name = fdt_get_name(fdt, subnode, NULL); + const struct regul_description *desc; + unsigned int i; + int ret; + + for (i = 0; i < NB_REG; i++) { + desc = &pmic_regs[i]; + if (strcmp(desc->node_name, reg_name) == 0) { + break; + } + } + assert(i < NB_REG); + + ret = regulator_register(desc, subnode); + if (ret != 0) { + WARN("%s:%d failed to register %s\n", __func__, + __LINE__, reg_name); + return ret; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/pmic/stpmic1.c b/arm-trusted-firmware/drivers/st/pmic/stpmic1.c new file mode 100644 index 0000000..37eb50b --- /dev/null +++ b/arm-trusted-firmware/drivers/st/pmic/stpmic1.c @@ -0,0 +1,937 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +#define I2C_TIMEOUT_MS 25 + +struct regul_struct { + const char *dt_node_name; + const uint16_t *voltage_table; + uint8_t voltage_table_size; + uint8_t control_reg; + uint8_t enable_mask; + uint8_t low_power_reg; + uint8_t pull_down_reg; + uint8_t pull_down; + uint8_t mask_reset_reg; + uint8_t mask_reset; + uint8_t icc_reg; + uint8_t icc_mask; +}; + +static struct i2c_handle_s *pmic_i2c_handle; +static uint16_t pmic_i2c_addr; +/* + * Special mode corresponds to LDO3 in sink source mode or in bypass mode. + * LDO3 doesn't switch back from special to normal mode. + */ +static bool ldo3_special_mode; + +/* Voltage tables in mV */ +static const uint16_t buck1_voltage_table[] = { + 725, + 725, + 725, + 725, + 725, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1325, + 1350, + 1375, + 1400, + 1425, + 1450, + 1475, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, + 1500, +}; + +static const uint16_t buck2_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1050, + 1050, + 1100, + 1100, + 1150, + 1150, + 1200, + 1200, + 1250, + 1250, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, +}; + +static const uint16_t buck3_voltage_table[] = { + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1000, + 1100, + 1100, + 1100, + 1100, + 1200, + 1200, + 1200, + 1200, + 1300, + 1300, + 1300, + 1300, + 1400, + 1400, + 1400, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, +}; + +static const uint16_t buck4_voltage_table[] = { + 600, + 625, + 650, + 675, + 700, + 725, + 750, + 775, + 800, + 825, + 850, + 875, + 900, + 925, + 950, + 975, + 1000, + 1025, + 1050, + 1075, + 1100, + 1125, + 1150, + 1175, + 1200, + 1225, + 1250, + 1275, + 1300, + 1300, + 1350, + 1350, + 1400, + 1400, + 1450, + 1450, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo1_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo2_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo3_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, + 3300, +}; + +/* Special mode table is used for sink source OR bypass mode */ +static const uint16_t ldo3_special_mode_table[] = { + 0, +}; + +static const uint16_t ldo5_voltage_table[] = { + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, + 3400, + 3500, + 3600, + 3700, + 3800, + 3900, +}; + +static const uint16_t ldo6_voltage_table[] = { + 900, + 1000, + 1100, + 1200, + 1300, + 1400, + 1500, + 1600, + 1700, + 1800, + 1900, + 2000, + 2100, + 2200, + 2300, + 2400, + 2500, + 2600, + 2700, + 2800, + 2900, + 3000, + 3100, + 3200, + 3300, +}; + +static const uint16_t ldo4_voltage_table[] = { + 3300, +}; + +static const uint16_t vref_ddr_voltage_table[] = { + 3300, +}; + +static const uint16_t fixed_5v_voltage_table[] = { + 5000, +}; + +/* Table of Regulators in PMIC SoC */ +static const struct regul_struct regulators_table[] = { + { + .dt_node_name = "buck1", + .voltage_table = buck1_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck1_voltage_table), + .control_reg = BUCK1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK1_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK1_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK1_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK1_ICC_SHIFT, + }, + { + .dt_node_name = "buck2", + .voltage_table = buck2_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck2_voltage_table), + .control_reg = BUCK2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK2_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK2_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK2_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK2_ICC_SHIFT, + }, + { + .dt_node_name = "buck3", + .voltage_table = buck3_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck3_voltage_table), + .control_reg = BUCK3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK3_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK3_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK3_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK3_ICC_SHIFT, + }, + { + .dt_node_name = "buck4", + .voltage_table = buck4_voltage_table, + .voltage_table_size = ARRAY_SIZE(buck4_voltage_table), + .control_reg = BUCK4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = BUCK4_PWRCTRL_REG, + .pull_down_reg = BUCK_PULL_DOWN_REG, + .pull_down = BUCK4_PULL_DOWN_SHIFT, + .mask_reset_reg = MASK_RESET_BUCK_REG, + .mask_reset = BUCK4_MASK_RESET, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BUCK4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo1", + .voltage_table = ldo1_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo1_voltage_table), + .control_reg = LDO1_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO1_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO1_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO1_ICC_SHIFT, + }, + { + .dt_node_name = "ldo2", + .voltage_table = ldo2_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo2_voltage_table), + .control_reg = LDO2_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO2_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO2_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO2_ICC_SHIFT, + }, + { + .dt_node_name = "ldo3", + .voltage_table = ldo3_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo3_voltage_table), + .control_reg = LDO3_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO3_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO3_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO3_ICC_SHIFT, + }, + { + .dt_node_name = "ldo4", + .voltage_table = ldo4_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo4_voltage_table), + .control_reg = LDO4_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO4_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO4_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO4_ICC_SHIFT, + }, + { + .dt_node_name = "ldo5", + .voltage_table = ldo5_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo5_voltage_table), + .control_reg = LDO5_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO5_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO5_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO5_ICC_SHIFT, + }, + { + .dt_node_name = "ldo6", + .voltage_table = ldo6_voltage_table, + .voltage_table_size = ARRAY_SIZE(ldo6_voltage_table), + .control_reg = LDO6_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = LDO6_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = LDO6_MASK_RESET, + .icc_reg = LDO_ICC_TURNOFF_REG, + .icc_mask = LDO6_ICC_SHIFT, + }, + { + .dt_node_name = "vref_ddr", + .voltage_table = vref_ddr_voltage_table, + .voltage_table_size = ARRAY_SIZE(vref_ddr_voltage_table), + .control_reg = VREF_DDR_CONTROL_REG, + .enable_mask = LDO_BUCK_ENABLE_MASK, + .low_power_reg = VREF_DDR_PWRCTRL_REG, + .mask_reset_reg = MASK_RESET_LDO_REG, + .mask_reset = VREF_DDR_MASK_RESET, + }, + { + .dt_node_name = "boost", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = BOOST_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = BOOST_ICC_SHIFT, + }, + { + .dt_node_name = "pwr_sw1", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = USBSW_OTG_SWITCH_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = PWR_SW1_ICC_SHIFT, + }, + { + .dt_node_name = "pwr_sw2", + .voltage_table = fixed_5v_voltage_table, + .voltage_table_size = ARRAY_SIZE(fixed_5v_voltage_table), + .control_reg = USB_CONTROL_REG, + .enable_mask = SWIN_SWOUT_ENABLED, + .icc_reg = BUCK_ICC_TURNOFF_REG, + .icc_mask = PWR_SW2_ICC_SHIFT, + }, +}; + +#define MAX_REGUL ARRAY_SIZE(regulators_table) + +static const struct regul_struct *get_regulator_data(const char *name) +{ + uint8_t i; + + for (i = 0 ; i < MAX_REGUL ; i++) { + if (strncmp(name, regulators_table[i].dt_node_name, + strlen(regulators_table[i].dt_node_name)) == 0) { + return ®ulators_table[i]; + } + } + + /* Regulator not found */ + panic(); + return NULL; +} + +static uint8_t voltage_to_index(const char *name, uint16_t millivolts) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t i; + + for (i = 0 ; i < regul->voltage_table_size ; i++) { + if (regul->voltage_table[i] == millivolts) { + return i; + } + } + + /* Voltage not found */ + panic(); + + return 0; +} + +int stpmic1_powerctrl_on(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, PWRCTRL_PIN_VALID, + PWRCTRL_PIN_VALID); +} + +int stpmic1_switch_off(void) +{ + return stpmic1_register_update(MAIN_CONTROL_REG, 1, + SOFTWARE_SWITCH_OFF_ENABLED); +} + +int stpmic1_regulator_enable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, regul->enable_mask, + regul->enable_mask); +} + +int stpmic1_regulator_disable(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + return stpmic1_register_update(regul->control_reg, 0, + regul->enable_mask); +} + +bool stpmic1_is_regulator_enabled(const char *name) +{ + uint8_t val; + const struct regul_struct *regul = get_regulator_data(name); + + if (stpmic1_register_read(regul->control_reg, &val) != 0) { + panic(); + } + + return (val & regul->enable_mask) == regul->enable_mask; +} + +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts) +{ + uint8_t voltage_index = voltage_to_index(name, millivolts); + const struct regul_struct *regul = get_regulator_data(name); + uint8_t mask; + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + /* + * when the LDO3 is in special mode, we do not change voltage, + * because by setting voltage, the LDO would leaves sink-source + * mode. There is obviously no reason to leave sink-source mode + * at runtime. + */ + return 0; + } + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 5) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + return stpmic1_register_update(regul->control_reg, + voltage_index << LDO_BUCK_VOLTAGE_SHIFT, + mask); +} + +int stpmic1_regulator_pull_down_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->pull_down_reg != 0) { + return stpmic1_register_update(regul->pull_down_reg, + BIT(regul->pull_down), + LDO_BUCK_PULL_DOWN_MASK << + regul->pull_down); + } + + return 0; +} + +int stpmic1_regulator_mask_reset_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->mask_reset_reg == 0U) { + return -EPERM; + } + + return stpmic1_register_update(regul->mask_reset_reg, + BIT(regul->mask_reset), + LDO_BUCK_RESET_MASK << + regul->mask_reset); +} + +int stpmic1_regulator_icc_set(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if (regul->mask_reset_reg == 0U) { + return -EPERM; + } + + return stpmic1_register_update(regul->icc_reg, + BIT(regul->icc_mask), + BIT(regul->icc_mask)); +} + +int stpmic1_regulator_sink_mode_set(const char *name) +{ + if (strncmp(name, "ldo3", 5) != 0) { + return -EPERM; + } + + ldo3_special_mode = true; + + /* disable bypass mode, enable sink mode */ + return stpmic1_register_update(LDO3_CONTROL_REG, + LDO3_DDR_SEL << LDO_BUCK_VOLTAGE_SHIFT, + LDO3_BYPASS | LDO_VOLTAGE_MASK); +} + +int stpmic1_regulator_bypass_mode_set(const char *name) +{ + if (strncmp(name, "ldo3", 5) != 0) { + return -EPERM; + } + + ldo3_special_mode = true; + + /* enable bypass mode, disable sink mode */ + return stpmic1_register_update(LDO3_CONTROL_REG, + LDO3_BYPASS, + LDO3_BYPASS | LDO_VOLTAGE_MASK); +} + +int stpmic1_active_discharge_mode_set(const char *name) +{ + if (strncmp(name, "pwr_sw1", 8) == 0) { + return stpmic1_register_update(USB_CONTROL_REG, + VBUS_OTG_DISCHARGE, + VBUS_OTG_DISCHARGE); + } + + if (strncmp(name, "pwr_sw2", 8) == 0) { + return stpmic1_register_update(USB_CONTROL_REG, + SW_OUT_DISCHARGE, + SW_OUT_DISCHARGE); + } + + return -EPERM; +} + +int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, + size_t *levels_count) +{ + const struct regul_struct *regul = get_regulator_data(name); + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + *levels_count = ARRAY_SIZE(ldo3_special_mode_table); + *levels = ldo3_special_mode_table; + } else { + *levels_count = regul->voltage_table_size; + *levels = regul->voltage_table; + } + + return 0; +} + +int stpmic1_regulator_voltage_get(const char *name) +{ + const struct regul_struct *regul = get_regulator_data(name); + uint8_t value; + uint8_t mask; + int status; + + if ((strncmp(name, "ldo3", 5) == 0) && ldo3_special_mode) { + return 0; + } + + /* Voltage can be set for buck or ldo (except ldo4) regulators */ + if (strncmp(name, "buck", 4) == 0) { + mask = BUCK_VOLTAGE_MASK; + } else if ((strncmp(name, "ldo", 3) == 0) && + (strncmp(name, "ldo4", 5) != 0)) { + mask = LDO_VOLTAGE_MASK; + } else { + return 0; + } + + status = stpmic1_register_read(regul->control_reg, &value); + if (status < 0) { + return status; + } + + value = (value & mask) >> LDO_BUCK_VOLTAGE_SHIFT; + + if (value > regul->voltage_table_size) { + return -ERANGE; + } + + return (int)regul->voltage_table[value]; +} + +int stpmic1_register_read(uint8_t register_id, uint8_t *value) +{ + return stm32_i2c_mem_read(pmic_i2c_handle, pmic_i2c_addr, + (uint16_t)register_id, + I2C_MEMADD_SIZE_8BIT, value, + 1, I2C_TIMEOUT_MS); +} + +int stpmic1_register_write(uint8_t register_id, uint8_t value) +{ + int status; + + status = stm32_i2c_mem_write(pmic_i2c_handle, pmic_i2c_addr, + (uint16_t)register_id, + I2C_MEMADD_SIZE_8BIT, &value, + 1, I2C_TIMEOUT_MS); + +#if ENABLE_ASSERTIONS + if (status != 0) { + return status; + } + + if ((register_id != WATCHDOG_CONTROL_REG) && (register_id <= 0x40U)) { + uint8_t readval; + + status = stpmic1_register_read(register_id, &readval); + if (status != 0) { + return status; + } + + if (readval != value) { + return -EIO; + } + } +#endif + + return status; +} + +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask) +{ + int status; + uint8_t val; + + status = stpmic1_register_read(register_id, &val); + if (status != 0) { + return status; + } + + val = (val & ~mask) | (value & mask); + + return stpmic1_register_write(register_id, val); +} + +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr) +{ + pmic_i2c_handle = i2c_handle; + pmic_i2c_addr = i2c_addr; +} + +void stpmic1_dump_regulators(void) +{ + uint32_t i; + + for (i = 0U; i < MAX_REGUL; i++) { + const char *name __unused = regulators_table[i].dt_node_name; + + VERBOSE("PMIC regul %s: %sable, %dmV", + name, + stpmic1_is_regulator_enabled(name) ? "en" : "dis", + stpmic1_regulator_voltage_get(name)); + } +} + +int stpmic1_get_version(unsigned long *version) +{ + uint8_t read_val; + int status; + + status = stpmic1_register_read(VERSION_STATUS_REG, &read_val); + if (status < 0) { + return status; + } + + *version = (unsigned long)read_val; + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/regulator/regulator_core.c b/arm-trusted-firmware/drivers/st/regulator/regulator_core.c new file mode 100644 index 0000000..5cc8329 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/regulator/regulator_core.c @@ -0,0 +1,560 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#define MAX_PROPERTY_LEN 64 + +static struct rdev rdev_array[PLAT_NB_RDEVS]; + +#define for_each_rdev(rdev) \ + for (rdev = rdev_array; rdev < (rdev_array + PLAT_NB_RDEVS); rdev++) + +#define for_each_registered_rdev(rdev) \ + for (rdev = rdev_array; \ + (rdev < (rdev_array + PLAT_NB_RDEVS)) && (rdev->desc != NULL); rdev++) + +static void lock_driver(const struct rdev *rdev) +{ + if (rdev->desc->ops->lock != NULL) { + rdev->desc->ops->lock(rdev->desc); + } +} + +static void unlock_driver(const struct rdev *rdev) +{ + if (rdev->desc->ops->unlock != NULL) { + rdev->desc->ops->unlock(rdev->desc); + } +} + +static struct rdev *regulator_get_by_phandle(int32_t phandle) +{ + struct rdev *rdev; + + for_each_registered_rdev(rdev) { + if (rdev->phandle == phandle) { + return rdev; + } + } + + WARN("%s: phandle %d not found\n", __func__, phandle); + return NULL; +} + +/* + * Get a regulator from its node name + * + * @fdt - pointer to device tree memory + * @node_name - name of the node "ldo1" + * Return pointer to rdev if succeed, NULL else. + */ +struct rdev *regulator_get_by_name(const char *node_name) +{ + struct rdev *rdev; + + assert(node_name != NULL); + VERBOSE("get %s\n", node_name); + + for_each_registered_rdev(rdev) { + if (strcmp(rdev->desc->node_name, node_name) == 0) { + return rdev; + } + } + + WARN("%s: %s not found\n", __func__, node_name); + return NULL; +} + +static int32_t get_supply_phandle(const void *fdt, int node, const char *name) +{ + const fdt32_t *cuint; + int len __unused; + int supply_phandle = -FDT_ERR_NOTFOUND; + char prop_name[MAX_PROPERTY_LEN]; + + len = snprintf(prop_name, MAX_PROPERTY_LEN - 1, "%s-supply", name); + assert((len >= 0) && (len < MAX_PROPERTY_LEN - 1)); + + cuint = fdt_getprop(fdt, node, prop_name, NULL); + if (cuint != NULL) { + supply_phandle = fdt32_to_cpu(*cuint); + VERBOSE("%s: supplied by %d\n", name, supply_phandle); + } + + return supply_phandle; +} + +/* + * Get a regulator from a supply name + * + * @fdt - pointer to device tree memory + * @node - offset of the node that contains the supply description + * @name - name of the supply "vdd" for "vdd-supply' + * Return pointer to rdev if succeed, NULL else. + */ +struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name) +{ + const int p = get_supply_phandle(fdt, node, name); + + if (p < 0) { + return NULL; + } + + return regulator_get_by_phandle(p); +} + +static int __regulator_set_state(struct rdev *rdev, bool state) +{ + if (rdev->desc->ops->set_state == NULL) { + return -ENODEV; + } + + return rdev->desc->ops->set_state(rdev->desc, state); +} + +/* + * Enable regulator + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_enable(struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + ret = __regulator_set_state(rdev, STATE_ENABLE); + + udelay(rdev->enable_ramp_delay); + + return ret; +} + +/* + * Disable regulator + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_disable(struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + if (rdev->flags & REGUL_ALWAYS_ON) { + return 0; + } + + ret = __regulator_set_state(rdev, STATE_DISABLE); + + udelay(rdev->enable_ramp_delay); + + return ret; +} + +/* + * Regulator enabled query + * + * @rdev - pointer to rdev struct + * Return 0 if disabled, 1 if enabled, <0 else. + */ +int regulator_is_enabled(const struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: is en\n", rdev->desc->node_name); + + if (rdev->desc->ops->get_state == NULL) { + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->get_state(rdev->desc); + if (ret < 0) { + ERROR("regul %s get state failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * Set regulator voltage + * + * @rdev - pointer to rdev struct + * @mvolt - Target voltage level in millivolt + * Return 0 if succeed, non 0 else. + */ +int regulator_set_voltage(struct rdev *rdev, uint16_t mvolt) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: set mvolt\n", rdev->desc->node_name); + + if (rdev->desc->ops->set_voltage == NULL) { + return -ENODEV; + } + + if ((mvolt < rdev->min_mv) || (mvolt > rdev->max_mv)) { + return -EPERM; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->set_voltage(rdev->desc, mvolt); + if (ret < 0) { + ERROR("regul %s set volt failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * Set regulator min voltage + * + * @rdev - pointer to rdev struct + * Return 0 if succeed, non 0 else. + */ +int regulator_set_min_voltage(struct rdev *rdev) +{ + return regulator_set_voltage(rdev, rdev->min_mv); +} + +/* + * Get regulator voltage + * + * @rdev - pointer to rdev struct + * Return milli volts if succeed, <0 else. + */ +int regulator_get_voltage(const struct rdev *rdev) +{ + int ret; + + assert(rdev != NULL); + + VERBOSE("%s: get volt\n", rdev->desc->node_name); + + if (rdev->desc->ops->get_voltage == NULL) { + return rdev->min_mv; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->get_voltage(rdev->desc); + if (ret < 0) { + ERROR("regul %s get voltage failed: err:%d\n", + rdev->desc->node_name, ret); + } + + unlock_driver(rdev); + + return ret; +} + +/* + * List regulator voltages + * + * @rdev - pointer to rdev struct + * @levels - out: array of supported millitvolt levels from min to max value + * @count - out: number of possible millivolt values + * Return 0 if succeed, non 0 else. + */ +int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count) +{ + int ret; + size_t n; + + assert(rdev != NULL); + assert(levels != NULL); + assert(count != NULL); + + VERBOSE("%s: list volt\n", rdev->desc->node_name); + + if (rdev->desc->ops->list_voltages == NULL) { + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->list_voltages(rdev->desc, levels, count); + + unlock_driver(rdev); + + if (ret < 0) { + ERROR("regul %s list_voltages failed: err: %d\n", + rdev->desc->node_name, ret); + return ret; + } + + /* + * Reduce the possible values depending on min and max from device-tree + */ + n = *count; + while ((n > 1U) && ((*levels)[n - 1U] > rdev->max_mv)) { + n--; + } + + /* Verify that max val is a valid value */ + if (rdev->max_mv != (*levels)[n - 1]) { + ERROR("regul %s: max value %u is invalid\n", + rdev->desc->node_name, rdev->max_mv); + return -EINVAL; + } + + while ((n > 1U) && ((*levels[0U]) < rdev->min_mv)) { + (*levels)++; + n--; + } + + /* Verify that min is not too high */ + if (n == 0U) { + ERROR("regul %s set min voltage is too high\n", + rdev->desc->node_name); + return -EINVAL; + } + + /* Verify that min val is a valid vlue */ + if (rdev->min_mv != (*levels)[0U]) { + ERROR("regul %s: min value %u is invalid\n", + rdev->desc->node_name, rdev->min_mv); + return -EINVAL; + } + + *count = n; + + VERBOSE("rdev->min_mv=%u rdev->max_mv=%u\n", rdev->min_mv, rdev->max_mv); + + return 0; +} + +/* + * Get regulator voltages range + * + * @rdev - pointer to rdev struct + * @min_mv - out: min possible millivolt value + * @max_mv - out: max possible millivolt value + * Return 0 if succeed, non 0 else. + */ +void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv) +{ + assert(rdev != NULL); + + if (min_mv != NULL) { + *min_mv = rdev->min_mv; + } + if (max_mv != NULL) { + *max_mv = rdev->max_mv; + } +} + +/* + * Set regulator flag + * + * @rdev - pointer to rdev struct + * @flag - flag value to set (eg: REGUL_OCP) + * Return 0 if succeed, non 0 else. + */ +int regulator_set_flag(struct rdev *rdev, uint16_t flag) +{ + int ret; + + /* check that only one bit is set on flag */ + if (__builtin_popcount(flag) != 1) { + return -EINVAL; + } + + /* REGUL_ALWAYS_ON and REGUL_BOOT_ON are internal properties of the core */ + if ((flag == REGUL_ALWAYS_ON) || (flag == REGUL_BOOT_ON)) { + rdev->flags |= flag; + return 0; + } + + if (rdev->desc->ops->set_flag == NULL) { + ERROR("%s can not set any flag\n", rdev->desc->node_name); + return -ENODEV; + } + + lock_driver(rdev); + + ret = rdev->desc->ops->set_flag(rdev->desc, flag); + + unlock_driver(rdev); + + if (ret != 0) { + ERROR("%s: could not set flag %d ret=%d\n", + rdev->desc->node_name, flag, ret); + return ret; + } + + rdev->flags |= flag; + + return 0; +} + +static int parse_properties(const void *fdt, struct rdev *rdev, int node) +{ + int ret; + + if (fdt_getprop(fdt, node, "regulator-always-on", NULL) != NULL) { + VERBOSE("%s: set regulator-always-on\n", rdev->desc->node_name); + ret = regulator_set_flag(rdev, REGUL_ALWAYS_ON); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* + * Parse the device-tree for a regulator + * + * Read min/max voltage from dt and check its validity + * Read the properties, and call the driver to set flags + * Read power supply phandle + * Read and store low power mode states + * + * @rdev - pointer to rdev struct + * @node - device-tree node offset of the regulator + * Return 0 if disabled, 1 if enabled, <0 else. + */ +static int parse_dt(struct rdev *rdev, int node) +{ + void *fdt; + const fdt32_t *cuint; + const uint16_t *levels; + size_t size; + int ret; + + VERBOSE("%s: parse dt\n", rdev->desc->node_name); + + if (fdt_get_address(&fdt) == 0) { + return -ENOENT; + } + + rdev->phandle = fdt_get_phandle(fdt, node); + + cuint = fdt_getprop(fdt, node, "regulator-min-microvolt", NULL); + if (cuint != NULL) { + uint16_t min_mv; + + min_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + VERBOSE("%s: min_mv=%d\n", rdev->desc->node_name, (int)min_mv); + if (min_mv <= rdev->max_mv) { + rdev->min_mv = min_mv; + } else { + ERROR("%s: min_mv=%d is too high\n", + rdev->desc->node_name, (int)min_mv); + return -EINVAL; + } + } + + cuint = fdt_getprop(fdt, node, "regulator-max-microvolt", NULL); + if (cuint != NULL) { + uint16_t max_mv; + + max_mv = (uint16_t)(fdt32_to_cpu(*cuint) / 1000U); + VERBOSE("%s: max_mv=%d\n", rdev->desc->node_name, (int)max_mv); + if (max_mv >= rdev->min_mv) { + rdev->max_mv = max_mv; + } else { + ERROR("%s: max_mv=%d is too low\n", + rdev->desc->node_name, (int)max_mv); + return -EINVAL; + } + } + + /* validate that min and max values can be used */ + ret = regulator_list_voltages(rdev, &levels, &size); + if ((ret != 0) && (ret != -ENODEV)) { + return ret; + } + + ret = parse_properties(fdt, rdev, node); + if (ret != 0) { + return ret; + } + + return 0; +} + +/* + * Register a regulator driver in regulator framework. + * Initialize voltage range from driver description + * + * @desc - pointer to the regulator description + * @node - device-tree node offset of the regulator + * Return 0 if succeed, non 0 else. + */ +int regulator_register(const struct regul_description *desc, int node) +{ + struct rdev *rdev; + + assert(desc != NULL); + + VERBOSE("register %s\n", desc->node_name); + + for_each_rdev(rdev) { + if (rdev->desc == NULL) { + break; + } + } + + if (rdev == rdev_array + PLAT_NB_RDEVS) { + WARN("Not enough place for regulators, PLAT_NB_RDEVS should be increased.\n"); + return -ENOMEM; + } + + rdev->desc = desc; + rdev->enable_ramp_delay = rdev->desc->enable_ramp_delay; + + if (rdev->desc->ops->list_voltages != NULL) { + int ret; + const uint16_t *levels; + size_t count; + + lock_driver(rdev); + + ret = rdev->desc->ops->list_voltages(rdev->desc, &levels, &count); + + unlock_driver(rdev); + + if (ret < 0) { + ERROR("regul %s set state failed: err:%d\n", + rdev->desc->node_name, ret); + return ret; + } + + rdev->min_mv = levels[0]; + rdev->max_mv = levels[count - 1U]; + } else { + rdev->max_mv = UINT16_MAX; + } + + return parse_dt(rdev, node); +} diff --git a/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c b/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c new file mode 100644 index 0000000..f1c224e --- /dev/null +++ b/arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#ifndef PLAT_NB_FIXED_REGS +#error "Missing PLAT_NB_FIXED_REGS" +#endif + +#define FIXED_NAME_LEN 32 + +struct fixed_data { + char name[FIXED_NAME_LEN]; + uint16_t volt; + struct regul_description desc; +}; + +static struct fixed_data data[PLAT_NB_FIXED_REGS]; + +static int fixed_set_state(const struct regul_description *desc, bool state) +{ + return 0; +} + +static int fixed_get_state(const struct regul_description *desc) +{ + return 1; +} + +static struct regul_ops fixed_ops = { + .set_state = fixed_set_state, + .get_state = fixed_get_state, +}; + +int fixed_regulator_register(void) +{ + uint32_t count = 0; + void *fdt; + int node; + + VERBOSE("fixed reg init!\n"); + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + fdt_for_each_compatible_node(fdt, node, "regulator-fixed") { + int len __unused; + int ret; + struct fixed_data *d = &data[count]; + const char *reg_name; + + reg_name = fdt_get_name(fdt, node, NULL); + + VERBOSE("register fixed reg %s!\n", reg_name); + + len = snprintf(d->name, FIXED_NAME_LEN - 1, "%s", reg_name); + assert((len > 0) && (len < (FIXED_NAME_LEN - 1))); + + d->desc.node_name = d->name; + d->desc.driver_data = d; + d->desc.ops = &fixed_ops; + + ret = regulator_register(&d->desc, node); + if (ret != 0) { + WARN("%s:%d failed to register %s\n", __func__, + __LINE__, reg_name); + return ret; + } + + count++; + assert(count <= PLAT_NB_FIXED_REGS); + + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c b/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c new file mode 100644 index 0000000..98c8dcf --- /dev/null +++ b/arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +static uint32_t id2reg_offset(unsigned int reset_id) +{ + return ((reset_id & GENMASK(31, 5)) >> 5) * sizeof(uint32_t); +} + +static uint8_t id2reg_bit_pos(unsigned int reset_id) +{ + return (uint8_t)(reset_id & GENMASK(4, 0)); +} + +int stm32mp_reset_assert(uint32_t id, unsigned int to_us) +{ + uint32_t offset = id2reg_offset(id); + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uintptr_t rcc_base = stm32mp_rcc_base(); + + mmio_write_32(rcc_base + offset, bitmsk); + + if (to_us != 0U) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while ((mmio_read_32(rcc_base + offset) & bitmsk) == 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + } + + return 0; +} + +int stm32mp_reset_deassert(uint32_t id, unsigned int to_us) +{ + uint32_t offset = id2reg_offset(id) + RCC_RSTCLRR_OFFSET; + uint32_t bitmsk = BIT(id2reg_bit_pos(id)); + uintptr_t rcc_base = stm32mp_rcc_base(); + + mmio_write_32(rcc_base + offset, bitmsk); + + if (to_us != 0U) { + uint64_t timeout_ref = timeout_init_us(to_us); + + while ((mmio_read_32(rcc_base + offset) & bitmsk) != 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + } + + return 0; +} diff --git a/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c b/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c new file mode 100644 index 0000000..d3c26d9 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/spi/stm32_qspi.c @@ -0,0 +1,513 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Timeout for device interface reset */ +#define TIMEOUT_US_1_MS 1000U + +/* QUADSPI registers */ +#define QSPI_CR 0x00U +#define QSPI_DCR 0x04U +#define QSPI_SR 0x08U +#define QSPI_FCR 0x0CU +#define QSPI_DLR 0x10U +#define QSPI_CCR 0x14U +#define QSPI_AR 0x18U +#define QSPI_ABR 0x1CU +#define QSPI_DR 0x20U +#define QSPI_PSMKR 0x24U +#define QSPI_PSMAR 0x28U +#define QSPI_PIR 0x2CU +#define QSPI_LPTR 0x30U + +/* QUADSPI control register */ +#define QSPI_CR_EN BIT(0) +#define QSPI_CR_ABORT BIT(1) +#define QSPI_CR_DMAEN BIT(2) +#define QSPI_CR_TCEN BIT(3) +#define QSPI_CR_SSHIFT BIT(4) +#define QSPI_CR_DFM BIT(6) +#define QSPI_CR_FSEL BIT(7) +#define QSPI_CR_FTHRES_SHIFT 8U +#define QSPI_CR_TEIE BIT(16) +#define QSPI_CR_TCIE BIT(17) +#define QSPI_CR_FTIE BIT(18) +#define QSPI_CR_SMIE BIT(19) +#define QSPI_CR_TOIE BIT(20) +#define QSPI_CR_APMS BIT(22) +#define QSPI_CR_PMM BIT(23) +#define QSPI_CR_PRESCALER_MASK GENMASK_32(31, 24) +#define QSPI_CR_PRESCALER_SHIFT 24U + +/* QUADSPI device configuration register */ +#define QSPI_DCR_CKMODE BIT(0) +#define QSPI_DCR_CSHT_MASK GENMASK_32(10, 8) +#define QSPI_DCR_CSHT_SHIFT 8U +#define QSPI_DCR_FSIZE_MASK GENMASK_32(20, 16) +#define QSPI_DCR_FSIZE_SHIFT 16U + +/* QUADSPI status register */ +#define QSPI_SR_TEF BIT(0) +#define QSPI_SR_TCF BIT(1) +#define QSPI_SR_FTF BIT(2) +#define QSPI_SR_SMF BIT(3) +#define QSPI_SR_TOF BIT(4) +#define QSPI_SR_BUSY BIT(5) + +/* QUADSPI flag clear register */ +#define QSPI_FCR_CTEF BIT(0) +#define QSPI_FCR_CTCF BIT(1) +#define QSPI_FCR_CSMF BIT(3) +#define QSPI_FCR_CTOF BIT(4) + +/* QUADSPI communication configuration register */ +#define QSPI_CCR_DDRM BIT(31) +#define QSPI_CCR_DHHC BIT(30) +#define QSPI_CCR_SIOO BIT(28) +#define QSPI_CCR_FMODE_SHIFT 26U +#define QSPI_CCR_DMODE_SHIFT 24U +#define QSPI_CCR_DCYC_SHIFT 18U +#define QSPI_CCR_ABSIZE_SHIFT 16U +#define QSPI_CCR_ABMODE_SHIFT 14U +#define QSPI_CCR_ADSIZE_SHIFT 12U +#define QSPI_CCR_ADMODE_SHIFT 10U +#define QSPI_CCR_IMODE_SHIFT 8U +#define QSPI_CCR_IND_WRITE 0U +#define QSPI_CCR_IND_READ 1U +#define QSPI_CCR_MEM_MAP 3U + +#define QSPI_MAX_CHIP 2U + +#define QSPI_FIFO_TIMEOUT_US 30U +#define QSPI_CMD_TIMEOUT_US 1000U +#define QSPI_BUSY_TIMEOUT_US 100U +#define QSPI_ABT_TIMEOUT_US 100U + +#define DT_QSPI_COMPAT "st,stm32f469-qspi" + +#define FREQ_100MHZ 100000000U + +struct stm32_qspi_ctrl { + uintptr_t reg_base; + uintptr_t mm_base; + size_t mm_size; + unsigned long clock_id; + unsigned int reset_id; +}; + +static struct stm32_qspi_ctrl stm32_qspi; + +static uintptr_t qspi_base(void) +{ + return stm32_qspi.reg_base; +} + +static int stm32_qspi_wait_for_not_busy(void) +{ + uint64_t timeout = timeout_init_us(QSPI_BUSY_TIMEOUT_US); + + while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_BUSY) != 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: busy timeout\n", __func__); + return -ETIMEDOUT; + } + } + + return 0; +} + +static int stm32_qspi_wait_cmd(const struct spi_mem_op *op) +{ + int ret = 0; + uint64_t timeout; + + if (op->data.nbytes == 0U) { + return stm32_qspi_wait_for_not_busy(); + } + + timeout = timeout_init_us(QSPI_CMD_TIMEOUT_US); + while ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TCF) == 0U) { + if (timeout_elapsed(timeout)) { + ret = -ETIMEDOUT; + break; + } + } + + if (ret == 0) { + if ((mmio_read_32(qspi_base() + QSPI_SR) & QSPI_SR_TEF) != 0U) { + ERROR("%s: transfer error\n", __func__); + ret = -EIO; + } + } else { + ERROR("%s: cmd timeout\n", __func__); + } + + /* Clear flags */ + mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF | QSPI_FCR_CTEF); + + return ret; +} + +static void stm32_qspi_read_fifo(uint8_t *val, uintptr_t addr) +{ + *val = mmio_read_8(addr); +} + +static void stm32_qspi_write_fifo(uint8_t *val, uintptr_t addr) +{ + mmio_write_8(addr, *val); +} + +static int stm32_qspi_poll(const struct spi_mem_op *op) +{ + void (*fifo)(uint8_t *val, uintptr_t addr); + uint32_t len; + uint8_t *buf; + + if (op->data.dir == SPI_MEM_DATA_IN) { + fifo = stm32_qspi_read_fifo; + } else { + fifo = stm32_qspi_write_fifo; + } + + buf = (uint8_t *)op->data.buf; + + for (len = op->data.nbytes; len != 0U; len--) { + uint64_t timeout = timeout_init_us(QSPI_FIFO_TIMEOUT_US); + + while ((mmio_read_32(qspi_base() + QSPI_SR) & + QSPI_SR_FTF) == 0U) { + if (timeout_elapsed(timeout)) { + ERROR("%s: fifo timeout\n", __func__); + return -ETIMEDOUT; + } + } + + fifo(buf++, qspi_base() + QSPI_DR); + } + + return 0; +} + +static int stm32_qspi_mm(const struct spi_mem_op *op) +{ + memcpy(op->data.buf, + (void *)(stm32_qspi.mm_base + (size_t)op->addr.val), + op->data.nbytes); + + return 0; +} + +static int stm32_qspi_tx(const struct spi_mem_op *op, uint8_t mode) +{ + if (op->data.nbytes == 0U) { + return 0; + } + + if (mode == QSPI_CCR_MEM_MAP) { + return stm32_qspi_mm(op); + } + + return stm32_qspi_poll(op); +} + +static unsigned int stm32_qspi_get_mode(uint8_t buswidth) +{ + if (buswidth == 4U) { + return 3U; + } + + return buswidth; +} + +static int stm32_qspi_exec_op(const struct spi_mem_op *op) +{ + uint64_t timeout; + uint32_t ccr; + size_t addr_max; + uint8_t mode = QSPI_CCR_IND_WRITE; + int ret; + + VERBOSE("%s: cmd:%x mode:%d.%d.%d.%d addr:%" PRIx64 " len:%x\n", + __func__, op->cmd.opcode, op->cmd.buswidth, op->addr.buswidth, + op->dummy.buswidth, op->data.buswidth, + op->addr.val, op->data.nbytes); + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + addr_max = op->addr.val + op->data.nbytes + 1U; + + if ((op->data.dir == SPI_MEM_DATA_IN) && (op->data.nbytes != 0U)) { + if ((addr_max < stm32_qspi.mm_size) && + (op->addr.buswidth != 0U)) { + mode = QSPI_CCR_MEM_MAP; + } else { + mode = QSPI_CCR_IND_READ; + } + } + + if (op->data.nbytes != 0U) { + mmio_write_32(qspi_base() + QSPI_DLR, op->data.nbytes - 1U); + } + + ccr = mode << QSPI_CCR_FMODE_SHIFT; + ccr |= op->cmd.opcode; + ccr |= stm32_qspi_get_mode(op->cmd.buswidth) << QSPI_CCR_IMODE_SHIFT; + + if (op->addr.nbytes != 0U) { + ccr |= (op->addr.nbytes - 1U) << QSPI_CCR_ADSIZE_SHIFT; + ccr |= stm32_qspi_get_mode(op->addr.buswidth) << + QSPI_CCR_ADMODE_SHIFT; + } + + if ((op->dummy.buswidth != 0U) && (op->dummy.nbytes != 0U)) { + ccr |= (op->dummy.nbytes * 8U / op->dummy.buswidth) << + QSPI_CCR_DCYC_SHIFT; + } + + if (op->data.nbytes != 0U) { + ccr |= stm32_qspi_get_mode(op->data.buswidth) << + QSPI_CCR_DMODE_SHIFT; + } + + mmio_write_32(qspi_base() + QSPI_CCR, ccr); + + if ((op->addr.nbytes != 0U) && (mode != QSPI_CCR_MEM_MAP)) { + mmio_write_32(qspi_base() + QSPI_AR, op->addr.val); + } + + ret = stm32_qspi_tx(op, mode); + + /* + * Abort in: + * - Error case. + * - Memory mapped read: prefetching must be stopped if we read the last + * byte of device (device size - fifo size). If device size is not + * known then prefetching is always stopped. + */ + if ((ret != 0) || (mode == QSPI_CCR_MEM_MAP)) { + goto abort; + } + + /* Wait end of TX in indirect mode */ + ret = stm32_qspi_wait_cmd(op); + if (ret != 0) { + goto abort; + } + + return 0; + +abort: + mmio_setbits_32(qspi_base() + QSPI_CR, QSPI_CR_ABORT); + + /* Wait clear of abort bit by hardware */ + timeout = timeout_init_us(QSPI_ABT_TIMEOUT_US); + while ((mmio_read_32(qspi_base() + QSPI_CR) & QSPI_CR_ABORT) != 0U) { + if (timeout_elapsed(timeout)) { + ret = -ETIMEDOUT; + break; + } + } + + mmio_write_32(qspi_base() + QSPI_FCR, QSPI_FCR_CTCF); + + if (ret != 0) { + ERROR("%s: exec op error\n", __func__); + } + + return ret; +} + +static int stm32_qspi_claim_bus(unsigned int cs) +{ + uint32_t cr; + + if (cs >= QSPI_MAX_CHIP) { + return -ENODEV; + } + + /* Set chip select and enable the controller */ + cr = QSPI_CR_EN; + if (cs == 1U) { + cr |= QSPI_CR_FSEL; + } + + mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_FSEL, cr); + + return 0; +} + +static void stm32_qspi_release_bus(void) +{ + mmio_clrbits_32(qspi_base() + QSPI_CR, QSPI_CR_EN); +} + +static int stm32_qspi_set_speed(unsigned int hz) +{ + unsigned long qspi_clk = clk_get_rate(stm32_qspi.clock_id); + uint32_t prescaler = UINT8_MAX; + uint32_t csht; + int ret; + + if (qspi_clk == 0U) { + return -EINVAL; + } + + if (hz > 0U) { + prescaler = div_round_up(qspi_clk, hz) - 1U; + if (prescaler > UINT8_MAX) { + prescaler = UINT8_MAX; + } + } + + csht = div_round_up((5U * qspi_clk) / (prescaler + 1U), FREQ_100MHZ); + csht = ((csht - 1U) << QSPI_DCR_CSHT_SHIFT) & QSPI_DCR_CSHT_MASK; + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + mmio_clrsetbits_32(qspi_base() + QSPI_CR, QSPI_CR_PRESCALER_MASK, + prescaler << QSPI_CR_PRESCALER_SHIFT); + + mmio_clrsetbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CSHT_MASK, csht); + + VERBOSE("%s: speed=%lu\n", __func__, qspi_clk / (prescaler + 1U)); + + return 0; +} + +static int stm32_qspi_set_mode(unsigned int mode) +{ + int ret; + + ret = stm32_qspi_wait_for_not_busy(); + if (ret != 0) { + return ret; + } + + if ((mode & SPI_CS_HIGH) != 0U) { + return -ENODEV; + } + + if (((mode & SPI_CPHA) != 0U) && ((mode & SPI_CPOL) != 0U)) { + mmio_setbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); + } else if (((mode & SPI_CPHA) == 0U) && ((mode & SPI_CPOL) == 0U)) { + mmio_clrbits_32(qspi_base() + QSPI_DCR, QSPI_DCR_CKMODE); + } else { + return -ENODEV; + } + + VERBOSE("%s: mode=0x%x\n", __func__, mode); + + if ((mode & SPI_RX_QUAD) != 0U) { + VERBOSE("rx: quad\n"); + } else if ((mode & SPI_RX_DUAL) != 0U) { + VERBOSE("rx: dual\n"); + } else { + VERBOSE("rx: single\n"); + } + + if ((mode & SPI_TX_QUAD) != 0U) { + VERBOSE("tx: quad\n"); + } else if ((mode & SPI_TX_DUAL) != 0U) { + VERBOSE("tx: dual\n"); + } else { + VERBOSE("tx: single\n"); + } + + return 0; +} + +static const struct spi_bus_ops stm32_qspi_bus_ops = { + .claim_bus = stm32_qspi_claim_bus, + .release_bus = stm32_qspi_release_bus, + .set_speed = stm32_qspi_set_speed, + .set_mode = stm32_qspi_set_mode, + .exec_op = stm32_qspi_exec_op, +}; + +int stm32_qspi_init(void) +{ + size_t size; + int qspi_node; + struct dt_node_info info; + void *fdt = NULL; + int ret; + + if (fdt_get_address(&fdt) == 0) { + return -FDT_ERR_NOTFOUND; + } + + qspi_node = dt_get_node(&info, -1, DT_QSPI_COMPAT); + if (qspi_node < 0) { + ERROR("No QSPI ctrl found\n"); + return -FDT_ERR_NOTFOUND; + } + + if (info.status == DT_DISABLED) { + return -FDT_ERR_NOTFOUND; + } + + ret = fdt_get_reg_props_by_name(fdt, qspi_node, "qspi", + &stm32_qspi.reg_base, &size); + if (ret != 0) { + return ret; + } + + ret = fdt_get_reg_props_by_name(fdt, qspi_node, "qspi_mm", + &stm32_qspi.mm_base, + &stm32_qspi.mm_size); + if (ret != 0) { + return ret; + } + + if (dt_set_pinctrl_config(qspi_node) != 0) { + return -FDT_ERR_BADVALUE; + } + + if ((info.clock < 0) || (info.reset < 0)) { + return -FDT_ERR_BADVALUE; + } + + stm32_qspi.clock_id = (unsigned long)info.clock; + stm32_qspi.reset_id = (unsigned int)info.reset; + + clk_enable(stm32_qspi.clock_id); + + ret = stm32mp_reset_assert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + ret = stm32mp_reset_deassert(stm32_qspi.reset_id, TIMEOUT_US_1_MS); + if (ret != 0) { + panic(); + } + + mmio_write_32(qspi_base() + QSPI_CR, QSPI_CR_SSHIFT); + mmio_write_32(qspi_base() + QSPI_DCR, QSPI_DCR_FSIZE_MASK); + + return spi_mem_init_slave(fdt, qspi_node, &stm32_qspi_bus_ops); +}; diff --git a/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S b/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S new file mode 100644 index 0000000..e467f09 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S @@ -0,0 +1,255 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +#define USART_TIMEOUT 0x1000 + + /* + * "core" functions are low-level implementations that don't require + * writeable memory and are thus safe to call in BL1 crash context. + */ + .globl console_stm32_core_init + .globl console_stm32_core_putc + .globl console_stm32_core_getc + .globl console_stm32_core_flush + + .globl console_stm32_putc + .globl console_stm32_flush + + + + /* ----------------------------------------------------------------- + * int console_core_init(uintptr_t base_addr, + * unsigned int uart_clk, + * unsigned int baud_rate) + * + * Function to initialize the console without a C Runtime to print + * debug information. This function will be accessed by console_init + * and crash reporting. + * + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success else 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------------------------- + */ +func console_stm32_core_init + /* Check the input base address */ + cmp r0, #0 + beq core_init_fail +#if !defined(IMAGE_BL2) + /* Skip UART initialization if it is already enabled */ + ldr r3, [r0, #USART_CR1] + ands r3, r3, #USART_CR1_UE + bne 1f +#endif /* IMAGE_BL2 */ + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq core_init_fail + cmp r2, #0 + beq core_init_fail + /* Disable UART */ + ldr r3, [r0, #USART_CR1] + bic r3, r3, #USART_CR1_UE + str r3, [r0, #USART_CR1] + /* Configure UART */ + orr r3, r3, #(USART_CR1_TE | USART_CR1_FIFOEN) + str r3, [r0, #USART_CR1] + ldr r3, [r0, #USART_CR2] + bic r3, r3, #USART_CR2_STOP + str r3, [r0, #USART_CR2] + /* Divisor = (Uart clock + (baudrate / 2)) / baudrate */ + lsr r3, r2, #1 + add r3, r1, r3 + udiv r3, r3, r2 + cmp r3, #16 + bhi 2f + /* Oversampling 8 */ + /* Divisor = (2 * Uart clock + (baudrate / 2)) / baudrate */ + lsr r3, r2, #1 + add r3, r3, r1, lsl #1 + udiv r3, r3, r2 + and r1, r3, #USART_BRR_DIV_FRACTION + lsr r1, r1, #1 + bic r3, r3, #USART_BRR_DIV_FRACTION + orr r3, r3, r1 + ldr r1, [r0, #USART_CR1] + orr r1, r1, #USART_CR1_OVER8 + str r1, [r0, #USART_CR1] +2: + str r3, [r0, #USART_BRR] + /* Enable UART */ + ldr r3, [r0, #USART_CR1] + orr r3, r3, #USART_CR1_UE + str r3, [r0, #USART_CR1] + /* Check TEACK bit */ + mov r2, #USART_TIMEOUT +teack_loop: + subs r2, r2, #1 + beq core_init_fail + ldr r3, [r0, #USART_ISR] + tst r3, #USART_ISR_TEACK + beq teack_loop +1: + mov r0, #1 + bx lr +core_init_fail: + mov r0, #0 + bx lr +endfunc console_stm32_core_init + + .globl console_stm32_register + + /* ------------------------------------------------------- + * int console_stm32_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new STM32 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_stm32_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + bl console_stm32_core_init + cmp r0, #0 + beq register_fail + + mov r0, r4 + pop {r4, lr} + finish_console_register stm32 putc=1, getc=0, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_stm32_register + + /* --------------------------------------------------------------- + * int console_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 : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * --------------------------------------------------------------- + */ +func console_stm32_core_putc + /* Check the input parameter */ + cmp r1, #0 + beq putc_error + + /* Check Transmit Data Register Empty */ +txe_loop: + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TXE + beq txe_loop + str r0, [r1, #USART_TDR] + /* Check transmit complete flag */ +tc_loop: + ldr r2, [r1, #USART_ISR] + tst r2, #USART_ISR_TC + beq tc_loop + bx lr +putc_error: + mov r0, #-1 + bx lr +endfunc console_stm32_core_putc + + /* ------------------------------------------------------------ + * int console_stm32_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: r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list: r2 + * ------------------------------------------------------------ + */ +func console_stm32_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_stm32_core_putc +endfunc console_stm32_putc + + /* ----------------------------------------------------------- + * int console_core_getc(uintptr_t base_addr) + * + * Function to get a character from the console. + * It returns the character grabbed on success or -1 on error. + * + * In : r0 - console base address + * Out : return -1. + * Clobber list : r0, r1 + * ----------------------------------------------------------- + */ +func console_stm32_core_getc + /* Not supported */ + mov r0, #-1 + bx lr +endfunc console_stm32_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 : r0 - console base address + * Out : void. + * Clobber list : r0, r1 + * --------------------------------------------------------------- + */ +func console_stm32_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + /* Check Transmit Data Register Empty */ +txe_loop_3: + ldr r1, [r0, #USART_ISR] + tst r1, #USART_ISR_TXE + beq txe_loop_3 + bx lr +endfunc console_stm32_core_flush + + /* ------------------------------------------------------ + * void console_stm32_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void. + * Clobber list: r0, r1 + * ------------------------------------------------------ + */ +func console_stm32_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_stm32_core_flush +endfunc console_stm32_flush diff --git a/arm-trusted-firmware/drivers/st/uart/stm32_uart.c b/arm-trusted-firmware/drivers/st/uart/stm32_uart.c new file mode 100644 index 0000000..e2e5405 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/uart/stm32_uart.c @@ -0,0 +1,404 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* UART time-out value */ +#define STM32_UART_TIMEOUT_US 20000U + +/* Mask to clear ALL the configuration registers */ + +#define STM32_UART_CR1_FIELDS \ + (USART_CR1_M | USART_CR1_PCE | USART_CR1_PS | USART_CR1_TE | \ + USART_CR1_RE | USART_CR1_OVER8 | USART_CR1_FIFOEN) + +#define STM32_UART_CR2_FIELDS \ + (USART_CR2_SLVEN | USART_CR2_DIS_NSS | USART_CR2_ADDM7 | \ + USART_CR2_LBDL | USART_CR2_LBDIE | USART_CR2_LBCL | \ + USART_CR2_CPHA | USART_CR2_CPOL | USART_CR2_CLKEN | \ + USART_CR2_STOP | USART_CR2_LINEN | USART_CR2_SWAP | \ + USART_CR2_RXINV | USART_CR2_TXINV | USART_CR2_DATAINV | \ + USART_CR2_MSBFIRST | USART_CR2_ABREN | USART_CR2_ABRMODE | \ + USART_CR2_RTOEN | USART_CR2_ADD) + +#define STM32_UART_CR3_FIELDS \ + (USART_CR3_EIE | USART_CR3_IREN | USART_CR3_IRLP | \ + USART_CR3_HDSEL | USART_CR3_NACK | USART_CR3_SCEN | \ + USART_CR3_DMAR | USART_CR3_DMAT | USART_CR3_RTSE | \ + USART_CR3_CTSE | USART_CR3_CTSIE | USART_CR3_ONEBIT | \ + USART_CR3_OVRDIS | USART_CR3_DDRE | USART_CR3_DEM | \ + USART_CR3_DEP | USART_CR3_SCARCNT | USART_CR3_WUS | \ + USART_CR3_WUFIE | USART_CR3_TXFTIE | USART_CR3_TCBGTIE | \ + USART_CR3_RXFTCFG | USART_CR3_RXFTIE | USART_CR3_TXFTCFG) + +#define STM32_UART_ISR_ERRORS \ + (USART_ISR_ORE | USART_ISR_NE | USART_ISR_FE | USART_ISR_PE) + +static const uint16_t presc_table[STM32_UART_PRESCALER_NB] = { + 1U, 2U, 4U, 6U, 8U, 10U, 12U, 16U, 32U, 64U, 128U, 256U +}; + +/* @brief BRR division operation to set BRR register in 8-bit oversampling + * mode. + * @param clockfreq: UART clock. + * @param baud_rate: Baud rate set by the user. + * @param prescaler: UART prescaler value. + * @retval Division result. + */ +static uint32_t uart_div_sampling8(unsigned long clockfreq, + uint32_t baud_rate, + uint32_t prescaler) +{ + uint32_t scaled_freq = clockfreq / presc_table[prescaler]; + + return ((scaled_freq * 2) + (baud_rate / 2)) / baud_rate; + +} + +/* @brief BRR division operation to set BRR register in 16-bit oversampling + * mode. + * @param clockfreq: UART clock. + * @param baud_rate: Baud rate set by the user. + * @param prescaler: UART prescaler value. + * @retval Division result. + */ +static uint32_t uart_div_sampling16(unsigned long clockfreq, + uint32_t baud_rate, + uint32_t prescaler) +{ + uint32_t scaled_freq = clockfreq / presc_table[prescaler]; + + return (scaled_freq + (baud_rate / 2)) / baud_rate; + +} + +/* + * @brief Return the UART clock frequency. + * @param huart: UART handle. + * @retval Frequency value in Hz. + */ +static unsigned long uart_get_clock_freq(struct stm32_uart_handle_s *huart) +{ + return fdt_get_uart_clock_freq((uintptr_t)huart->base); +} + +/* + * @brief Configure the UART peripheral. + * @param huart: UART handle. + * @retval UART status. + */ +static int uart_set_config(struct stm32_uart_handle_s *huart, + const struct stm32_uart_init_s *init) +{ + uint32_t tmpreg; + unsigned long clockfreq; + uint32_t brrtemp; + + /* + * ---------------------- USART CR1 Configuration -------------------- + * Clear M, PCE, PS, TE, RE and OVER8 bits and configure + * the UART word length, parity, mode and oversampling: + * - set the M bits according to init->word_length value, + * - set PCE and PS bits according to init->parity value, + * - set TE and RE bits according to init->mode value, + * - set OVER8 bit according to init->over_sampling value. + */ + tmpreg = init->word_length | + init->parity | + init->mode | + init->over_sampling | + init->fifo_mode; + mmio_clrsetbits_32(huart->base + USART_CR1, STM32_UART_CR1_FIELDS, tmpreg); + + /* + * --------------------- USART CR2 Configuration --------------------- + * Configure the UART Stop Bits: Set STOP[13:12] bits according + * to init->stop_bits value. + */ + mmio_clrsetbits_32(huart->base + USART_CR2, STM32_UART_CR2_FIELDS, + init->stop_bits); + + /* + * --------------------- USART CR3 Configuration --------------------- + * Configure: + * - UART HardWare Flow Control: set CTSE and RTSE bits according + * to init->hw_flow_control value, + * - one-bit sampling method versus three samples' majority rule + * according to init->one_bit_sampling (not applicable to + * LPUART), + * - set TXFTCFG bit according to init->tx_fifo_threshold value, + * - set RXFTCFG bit according to init->rx_fifo_threshold value. + */ + tmpreg = init->hw_flow_control | init->one_bit_sampling; + + if (init->fifo_mode == USART_CR1_FIFOEN) { + tmpreg |= init->tx_fifo_threshold | + init->rx_fifo_threshold; + } + + mmio_clrsetbits_32(huart->base + USART_CR3, STM32_UART_CR3_FIELDS, tmpreg); + + /* + * --------------------- USART PRESC Configuration ------------------- + * Configure UART Clock Prescaler : set PRESCALER according to + * init->prescaler value. + */ + assert(init->prescaler < STM32_UART_PRESCALER_NB); + mmio_clrsetbits_32(huart->base + USART_PRESC, USART_PRESC_PRESCALER, + init->prescaler); + + /*---------------------- USART BRR configuration --------------------*/ + clockfreq = uart_get_clock_freq(huart); + if (clockfreq == 0UL) { + return -ENODEV; + } + + if (init->over_sampling == STM32_UART_OVERSAMPLING_8) { + uint32_t usartdiv = uart_div_sampling8(clockfreq, + init->baud_rate, + init->prescaler); + + brrtemp = (usartdiv & USART_BRR_DIV_MANTISSA) | + ((usartdiv & USART_BRR_DIV_FRACTION) >> 1); + } else { + brrtemp = uart_div_sampling16(clockfreq, + init->baud_rate, + init->prescaler) & + (USART_BRR_DIV_FRACTION | USART_BRR_DIV_MANTISSA); + } + mmio_write_32(huart->base + USART_BRR, brrtemp); + + return 0; +} + +/* + * @brief Handle UART communication timeout. + * @param huart: UART handle. + * @param flag: Specifies the UART flag to check. + * @retval UART status. + */ +static int stm32_uart_wait_flag(struct stm32_uart_handle_s *huart, uint32_t flag) +{ + uint64_t timeout_ref = timeout_init_us(STM32_UART_TIMEOUT_US); + + while ((mmio_read_32(huart->base + USART_ISR) & flag) == 0U) { + if (timeout_elapsed(timeout_ref)) { + return -ETIMEDOUT; + } + } + + return 0; +} + +/* + * @brief Check the UART idle State. + * @param huart: UART handle. + * @retval UART status. + */ +static int stm32_uart_check_idle(struct stm32_uart_handle_s *huart) +{ + int ret; + + /* Check if the transmitter is enabled */ + if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_TE) == USART_CR1_TE) { + ret = stm32_uart_wait_flag(huart, USART_ISR_TEACK); + if (ret != 0) { + return ret; + } + } + + /* Check if the receiver is enabled */ + if ((mmio_read_32(huart->base + USART_CR1) & USART_CR1_RE) == USART_CR1_RE) { + ret = stm32_uart_wait_flag(huart, USART_ISR_REACK); + if (ret != 0) { + return ret; + } + } + + return 0; +} + +/* + * @brief Compute RDR register mask depending on word length. + * @param huart: UART handle. + * @retval Mask value. + */ +static unsigned int stm32_uart_rdr_mask(const struct stm32_uart_init_s *init) +{ + unsigned int mask = 0U; + + switch (init->word_length) { + case STM32_UART_WORDLENGTH_9B: + mask = GENMASK(8, 0); + break; + case STM32_UART_WORDLENGTH_8B: + mask = GENMASK(7, 0); + break; + case STM32_UART_WORDLENGTH_7B: + mask = GENMASK(6, 0); + break; + default: + break; /* not reached */ + } + + if (init->parity != STM32_UART_PARITY_NONE) { + mask >>= 1; + } + + return mask; +} + +/* + * @brief Check interrupt and status errors. + * @retval True if error detected, false otherwise. + */ +static bool stm32_uart_error_detected(struct stm32_uart_handle_s *huart) +{ + return (mmio_read_32(huart->base + USART_ISR) & STM32_UART_ISR_ERRORS) != 0U; +} + +/* + * @brief Clear status errors. + */ +static void stm32_uart_error_clear(struct stm32_uart_handle_s *huart) +{ + mmio_write_32(huart->base + USART_ICR, STM32_UART_ISR_ERRORS); +} + +/* + * @brief Stop the UART. + * @param base: UART base address. + */ +void stm32_uart_stop(uintptr_t base) +{ + mmio_clrbits_32(base + USART_CR1, USART_CR1_UE); +} + +/* + * @brief Initialize UART. + * @param huart: UART handle. + * @param base_addr: base address of UART. + * @param init: UART initialization parameter. + * @retval UART status. + */ + +int stm32_uart_init(struct stm32_uart_handle_s *huart, + uintptr_t base_addr, + const struct stm32_uart_init_s *init) +{ + int ret; + + if (huart == NULL || init == NULL || base_addr == 0U) { + return -EINVAL; + } + + huart->base = base_addr; + + /* Disable the peripheral */ + stm32_uart_stop(huart->base); + + /* Computation of UART mask to apply to RDR register */ + huart->rdr_mask = stm32_uart_rdr_mask(init); + + /* Init the peripheral */ + ret = uart_set_config(huart, init); + if (ret != 0) { + return ret; + } + + /* Enable the peripheral */ + mmio_setbits_32(huart->base + USART_CR1, USART_CR1_UE); + + /* TEACK and/or REACK to check */ + return stm32_uart_check_idle(huart); +} + +/* + * @brief Transmit one data in no blocking mode. + * @param huart: UART handle. + * @param c: data to sent. + * @retval UART status. + */ +int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c) +{ + int ret; + + if (huart == NULL) { + return -EINVAL; + } + + ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); + if (ret != 0) { + return ret; + } + + mmio_write_32(huart->base + USART_TDR, c); + if (stm32_uart_error_detected(huart)) { + stm32_uart_error_clear(huart); + return -EFAULT; + } + + return 0; +} + +/* + * @brief Flush TX Transmit fifo + * @param huart: UART handle. + * @retval UART status. + */ +int stm32_uart_flush(struct stm32_uart_handle_s *huart) +{ + int ret; + + if (huart == NULL) { + return -EINVAL; + } + + ret = stm32_uart_wait_flag(huart, USART_ISR_TXE); + if (ret != 0) { + return ret; + } + + return stm32_uart_wait_flag(huart, USART_ISR_TC); +} + +/* + * @brief Receive a data in no blocking mode. + * @retval value if >0 or UART status. + */ +int stm32_uart_getc(struct stm32_uart_handle_s *huart) +{ + uint32_t data; + + if (huart == NULL) { + return -EINVAL; + } + + /* Check if data is available */ + if ((mmio_read_32(huart->base + USART_ISR) & USART_ISR_RXNE) == 0U) { + return -EAGAIN; + } + + data = mmio_read_32(huart->base + USART_RDR) & huart->rdr_mask; + + if (stm32_uart_error_detected(huart)) { + stm32_uart_error_clear(huart); + return -EFAULT; + } + + return (int)data; +} diff --git a/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c b/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c new file mode 100644 index 0000000..9a49690 --- /dev/null +++ b/arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c @@ -0,0 +1,1091 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +#define USB_OTG_MODE_DEVICE 0U +#define USB_OTG_MODE_HOST 1U +#define USB_OTG_MODE_DRD 2U + +#define EP_TYPE_CTRL 0U +#define EP_TYPE_ISOC 1U +#define EP_TYPE_BULK 2U +#define EP_TYPE_INTR 3U + +#define USBD_FIFO_FLUSH_TIMEOUT_US 1000U +#define EP0_FIFO_SIZE 64U + +/* OTG registers offsets */ +#define OTG_GOTGINT 0x004U +#define OTG_GAHBCFG 0x008U +#define OTG_GUSBCFG 0x00CU +#define OTG_GRSTCTL 0x010U +#define OTG_GINTSTS 0x014U +#define OTG_GINTMSK 0x018U +#define OTG_GRXSTSP 0x020U +#define OTG_GLPMCFG 0x054U +#define OTG_DCFG 0x800U +#define OTG_DCTL 0x804U +#define OTG_DSTS 0x808U +#define OTG_DIEPMSK 0x810U +#define OTG_DOEPMSK 0x814U +#define OTG_DAINT 0x818U +#define OTG_DAINTMSK 0x81CU +#define OTG_DIEPEMPMSK 0x834U + +/* Definitions for OTG_DIEPx registers */ +#define OTG_DIEP_BASE 0x900U +#define OTG_DIEP_SIZE 0x20U +#define OTG_DIEPCTL 0x00U +#define OTG_DIEPINT 0x08U +#define OTG_DIEPTSIZ 0x10U +#define OTG_DIEPDMA 0x14U +#define OTG_DTXFSTS 0x18U +#define OTG_DIEP_MAX_NB 9U + +/* Definitions for OTG_DOEPx registers */ +#define OTG_DOEP_BASE 0xB00U +#define OTG_DOEP_SIZE 0x20U +#define OTG_DOEPCTL 0x00U +#define OTG_DOEPINT 0x08U +#define OTG_DOEPTSIZ 0x10U +#define OTG_DOEPDMA 0x14U +#define OTG_D0EP_MAX_NB 9U + +/* Definitions for OTG_DAINT registers */ +#define OTG_DAINT_OUT_MASK GENMASK(31, 16) +#define OTG_DAINT_OUT_SHIFT 16U +#define OTG_DAINT_IN_MASK GENMASK(15, 0) +#define OTG_DAINT_IN_SHIFT 0U + +#define OTG_DAINT_EP0_IN BIT(16) +#define OTG_DAINT_EP0_OUT BIT(0) + +/* Definitions for FIFOs */ +#define OTG_FIFO_BASE 0x1000U +#define OTG_FIFO_SIZE 0x1000U + +/* Bit definitions for OTG_GOTGINT register */ +#define OTG_GOTGINT_SEDET BIT(2) + +/* Bit definitions for OTG_GAHBCFG register */ +#define OTG_GAHBCFG_GINT BIT(0) + +/* Bit definitions for OTG_GUSBCFG register */ +#define OTG_GUSBCFG_TRDT GENMASK(13, 10) +#define OTG_GUSBCFG_TRDT_SHIFT 10U + +#define USBD_HS_TRDT_VALUE 9U + +/* Bit definitions for OTG_GRSTCTL register */ +#define OTG_GRSTCTL_RXFFLSH BIT(4) +#define OTG_GRSTCTL_TXFFLSH BIT(5) +#define OTG_GRSTCTL_TXFNUM_SHIFT 6U + +/* Bit definitions for OTG_GINTSTS register */ +#define OTG_GINTSTS_CMOD BIT(0) +#define OTG_GINTSTS_MMIS BIT(1) +#define OTG_GINTSTS_OTGINT BIT(2) +#define OTG_GINTSTS_SOF BIT(3) +#define OTG_GINTSTS_RXFLVL BIT(4) +#define OTG_GINTSTS_USBSUSP BIT(11) +#define OTG_GINTSTS_USBRST BIT(12) +#define OTG_GINTSTS_ENUMDNE BIT(13) +#define OTG_GINTSTS_IEPINT BIT(18) +#define OTG_GINTSTS_OEPINT BIT(19) +#define OTG_GINTSTS_IISOIXFR BIT(20) +#define OTG_GINTSTS_IPXFR_INCOMPISOOUT BIT(21) +#define OTG_GINTSTS_LPMINT BIT(27) +#define OTG_GINTSTS_SRQINT BIT(30) +#define OTG_GINTSTS_WKUPINT BIT(31) + +/* Bit definitions for OTG_GRXSTSP register */ +#define OTG_GRXSTSP_EPNUM GENMASK(3, 0) +#define OTG_GRXSTSP_BCNT GENMASK(14, 4) +#define OTG_GRXSTSP_BCNT_SHIFT 4U +#define OTG_GRXSTSP_PKTSTS GENMASK(20, 17) +#define OTG_GRXSTSP_PKTSTS_SHIFT 17U + +#define STS_GOUT_NAK 1U +#define STS_DATA_UPDT 2U +#define STS_XFER_COMP 3U +#define STS_SETUP_COMP 4U +#define STS_SETUP_UPDT 6U + +/* Bit definitions for OTG_GLPMCFG register */ +#define OTG_GLPMCFG_BESL GENMASK(5, 2) + +/* Bit definitions for OTG_DCFG register */ +#define OTG_DCFG_DAD GENMASK(10, 4) +#define OTG_DCFG_DAD_SHIFT 4U + +/* Bit definitions for OTG_DCTL register */ +#define OTG_DCTL_RWUSIG BIT(0) +#define OTG_DCTL_SDIS BIT(1) +#define OTG_DCTL_CGINAK BIT(8) + +/* Bit definitions for OTG_DSTS register */ +#define OTG_DSTS_SUSPSTS BIT(0) +#define OTG_DSTS_ENUMSPD_MASK GENMASK(2, 1) +#define OTG_DSTS_FNSOF0 BIT(8) + +#define OTG_DSTS_ENUMSPD(val) ((val) << 1) +#define OTG_DSTS_ENUMSPD_HS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(0U) +#define OTG_DSTS_ENUMSPD_FS_PHY_30MHZ_OR_60MHZ OTG_DSTS_ENUMSPD(1U) +#define OTG_DSTS_ENUMSPD_LS_PHY_6MHZ OTG_DSTS_ENUMSPD(2U) +#define OTG_DSTS_ENUMSPD_FS_PHY_48MHZ OTG_DSTS_ENUMSPD(3U) + +/* Bit definitions for OTG_DIEPMSK register */ +#define OTG_DIEPMSK_XFRCM BIT(0) +#define OTG_DIEPMSK_EPDM BIT(1) +#define OTG_DIEPMSK_TOM BIT(3) + +/* Bit definitions for OTG_DOEPMSK register */ +#define OTG_DOEPMSK_XFRCM BIT(0) +#define OTG_DOEPMSK_EPDM BIT(1) +#define OTG_DOEPMSK_STUPM BIT(3) + +/* Bit definitions for OTG_DIEPCTLx registers */ +#define OTG_DIEPCTL_MPSIZ GENMASK(10, 0) +#define OTG_DIEPCTL_STALL BIT(21) +#define OTG_DIEPCTL_CNAK BIT(26) +#define OTG_DIEPCTL_SD0PID_SEVNFRM BIT(28) +#define OTG_DIEPCTL_SODDFRM BIT(29) +#define OTG_DIEPCTL_EPDIS BIT(30) +#define OTG_DIEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DIEPINTx registers */ +#define OTG_DIEPINT_XFRC BIT(0) +#define OTG_DIEPINT_EPDISD BIT(1) +#define OTG_DIEPINT_TOC BIT(3) +#define OTG_DIEPINT_ITTXFE BIT(4) +#define OTG_DIEPINT_INEPNE BIT(6) +#define OTG_DIEPINT_TXFE BIT(7) +#define OTG_DIEPINT_TXFE_SHIFT 7U + +#define OTG_DIEPINT_MASK (BIT(13) | BIT(11) | GENMASK(9, 0)) + +/* Bit definitions for OTG_DIEPTSIZx registers */ +#define OTG_DIEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DIEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DIEPTSIZ_PKTCNT_SHIFT 19U +#define OTG_DIEPTSIZ_MCNT_MASK GENMASK(30, 29) +#define OTG_DIEPTSIZ_MCNT_DATA0 BIT(29) + +#define OTG_DIEPTSIZ_PKTCNT_1 BIT(19) + +/* Bit definitions for OTG_DTXFSTSx registers */ +#define OTG_DTXFSTS_INEPTFSAV GENMASK(15, 0) + +/* Bit definitions for OTG_DOEPCTLx registers */ +#define OTG_DOEPCTL_STALL BIT(21) +#define OTG_DOEPCTL_CNAK BIT(26) +#define OTG_DOEPCTL_SD0PID_SEVNFRM BIT(28) /* other than endpoint 0 */ +#define OTG_DOEPCTL_SD1PID_SODDFRM BIT(29) /* other than endpoint 0 */ +#define OTG_DOEPCTL_EPDIS BIT(30) +#define OTG_DOEPCTL_EPENA BIT(31) + +/* Bit definitions for OTG_DOEPTSIZx registers */ +#define OTG_DOEPTSIZ_XFRSIZ GENMASK(18, 0) +#define OTG_DOEPTSIZ_PKTCNT GENMASK(28, 19) +#define OTG_DOEPTSIZ_RXDPID_STUPCNT GENMASK(30, 29) + +/* Bit definitions for OTG_DOEPINTx registers */ +#define OTG_DOEPINT_XFRC BIT(0) +#define OTG_DOEPINT_STUP BIT(3) +#define OTG_DOEPINT_OTEPDIS BIT(4) + +#define OTG_DOEPINT_MASK (GENMASK(15, 12) | GENMASK(9, 8) | GENMASK(6, 0)) + +#define EP_NB 15U +#define EP_ALL 0x10U + +/* + * Flush TX FIFO. + * handle: PCD handle. + * num: FIFO number. + * This parameter can be a value from 1 to 15 or EP_ALL. + * EP_ALL= 0x10 means Flush all TX FIFOs + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_tx_fifo(void *handle, uint32_t num) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, + OTG_GRSTCTL_TXFFLSH | (uint32_t)(num << OTG_GRSTCTL_TXFNUM_SHIFT)); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_TXFFLSH) == OTG_GRSTCTL_TXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Flush RX FIFO. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_flush_rx_fifo(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint64_t timeout = timeout_init_us(USBD_FIFO_FLUSH_TIMEOUT_US); + + mmio_write_32(usb_base_addr + OTG_GRSTCTL, OTG_GRSTCTL_RXFFLSH); + + while ((mmio_read_32(usb_base_addr + OTG_GRSTCTL) & + OTG_GRSTCTL_RXFFLSH) == OTG_GRSTCTL_RXFFLSH) { + if (timeout_elapsed(timeout)) { + return USBD_TIMEOUT; + } + } + + return USBD_OK; +} + +/* + * Return the global USB interrupt status. + * handle: PCD handle. + * return: Interrupt register value. + */ +static uint32_t usb_dwc2_read_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & + mmio_read_32(usb_base_addr + OTG_GINTMSK); +} + +/* + * Return the USB device OUT endpoints interrupt. + * handle: PCD handle. + * return: Device OUT endpoint interrupts. + */ +static uint32_t usb_dwc2_all_out_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_OUT_MASK) >> OTG_DAINT_OUT_SHIFT; +} + +/* + * Return the USB device IN endpoints interrupt. + * handle: PCD handle. + * return: Device IN endpoint interrupts. + */ +static uint32_t usb_dwc2_all_in_ep_int(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return ((mmio_read_32(usb_base_addr + OTG_DAINT) & + mmio_read_32(usb_base_addr + OTG_DAINTMSK)) & + OTG_DAINT_IN_MASK) >> OTG_DAINT_IN_SHIFT; +} + +/* + * Return Device OUT EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device OUT EP Interrupt register. + */ +static uint32_t usb_dwc2_out_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_DOEP_BASE + + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT) & + mmio_read_32(usb_base_addr + OTG_DOEPMSK); +} + +/* + * Return Device IN EP interrupt register. + * handle: PCD handle. + * epnum: Endpoint number. + * This parameter can be a value from 0 to 15. + * return: Device IN EP Interrupt register. + */ +static uint32_t usb_dwc2_in_ep_int(void *handle, uint8_t epnum) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t msk; + uint32_t emp; + + msk = mmio_read_32(usb_base_addr + OTG_DIEPMSK); + emp = mmio_read_32(usb_base_addr + OTG_DIEPEMPMSK); + msk |= ((emp >> epnum) << OTG_DIEPINT_TXFE_SHIFT) & OTG_DIEPINT_TXFE; + + return mmio_read_32(usb_base_addr + OTG_DIEP_BASE + + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT) & msk; +} + +/* + * Return USB core mode. + * handle: PCD handle. + * return: Core mode. + * This parameter can be 0 (host) or 1 (device). + */ +static uint32_t usb_dwc2_get_mode(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + return mmio_read_32(usb_base_addr + OTG_GINTSTS) & OTG_GINTSTS_CMOD; +} + +/* + * Activate EP0 for detup transactions. + * handle: PCD handle. + * return: USB status. + */ +static enum usb_status usb_dwc2_activate_setup(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE; + + /* Set the MPS of the IN EP based on the enumeration speed */ + mmio_clrbits_32(reg_offset + OTG_DIEPCTL, OTG_DIEPCTL_MPSIZ); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_ENUMSPD_MASK) == + OTG_DSTS_ENUMSPD_LS_PHY_6MHZ) { + mmio_setbits_32(reg_offset + OTG_DIEPCTL, 3U); + } + + mmio_setbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_CGINAK); + + return USBD_OK; +} + +/* + * Prepare the EP0 to start the first control setup. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_out_start(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uintptr_t reg_offset = usb_base_addr + OTG_DIEP_BASE + OTG_DIEPTSIZ; + uint32_t reg_value = 0U; + + /* PKTCNT = 1 and XFRSIZ = 24 bytes for endpoint 0 */ + reg_value |= OTG_DIEPTSIZ_PKTCNT_1; + reg_value |= (EP0_FIFO_SIZE & OTG_DIEPTSIZ_XFRSIZ); + reg_value |= OTG_DOEPTSIZ_RXDPID_STUPCNT; + + mmio_write_32(reg_offset, reg_value); + + return USBD_OK; +} + +/* + * Write a packet into the TX FIFO associated with the EP/channel. + * handle: Selected device. + * src: Pointer to source buffer. + * ch_ep_num: Endpoint or host channel number. + * len: Number of bytes to write. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_packet(void *handle, uint8_t *src, + uint8_t ch_ep_num, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE + + (ch_ep_num * OTG_FIFO_SIZE); + + for (i = 0U; i < count32b; i++) { + uint32_t src_copy = 0U; + uint32_t j; + + /* Data written to FIFO need to be 4 bytes aligned */ + for (j = 0U; j < 4U; j++) { + src_copy += (*(src + j)) << (8U * j); + } + + mmio_write_32(reg_offset, src_copy); + src += 4U; + } + + return USBD_OK; +} + +/* + * Read a packet from the RX FIFO associated with the EP/channel. + * handle: Selected device. + * dst: Destination pointer. + * len: Number of bytes to read. + * return: Pointer to destination buffer. + */ +static void *usb_dwc2_read_packet(void *handle, uint8_t *dest, uint16_t len) +{ + uint32_t reg_offset; + uint32_t count32b = (len + 3U) / 4U; + uint32_t i; + + VERBOSE("read packet length %i to 0x%lx\n", len, (uintptr_t)dest); + + reg_offset = (uintptr_t)handle + OTG_FIFO_BASE; + + for (i = 0U; i < count32b; i++) { + *(uint32_t *)dest = mmio_read_32(reg_offset); + dest += 4U; + dsb(); + } + + return (void *)dest; +} + +/* + * Setup and start a transfer over an EP. + * handle: Selected device + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + uint32_t clear_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + (ep->num * OTG_DIEP_SIZE); + clear_value = OTG_DIEPTSIZ_PKTCNT | OTG_DIEPTSIZ_XFRSIZ; + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + reg_value = (OTG_DIEPTSIZ_PKTCNT & + (((ep->xfer_len + ep->maxpacket - 1U) / + ep->maxpacket) << OTG_DIEPTSIZ_PKTCNT_SHIFT)) + | ep->xfer_len; + + if (ep->type == EP_TYPE_ISOC) { + clear_value |= OTG_DIEPTSIZ_MCNT_MASK; + reg_value |= OTG_DIEPTSIZ_MCNT_DATA0; + } + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, clear_value, reg_value); + + if ((ep->type != EP_TYPE_ISOC) && (ep->xfer_len > 0U)) { + /* Enable the TX FIFO empty interrupt for this EP */ + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + reg_value = OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DIEPCTL_SODDFRM; + } else { + reg_value |= OTG_DIEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DIEPCTL, reg_value); + + if (ep->type == EP_TYPE_ISOC) { + usb_dwc2_write_packet(handle, ep->xfer_buff, ep->num, ep->xfer_len); + } + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + (ep->num * OTG_DOEP_SIZE); + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len == 0U) { + reg_value = ep->maxpacket | OTG_DIEPTSIZ_PKTCNT_1; + } else { + uint16_t pktcnt = (ep->xfer_len + ep->maxpacket - 1U) / ep->maxpacket; + + reg_value = (pktcnt << OTG_DIEPTSIZ_PKTCNT_SHIFT) | + (ep->maxpacket * pktcnt); + } + + mmio_clrsetbits_32(reg_offset + OTG_DOEPTSIZ, + OTG_DOEPTSIZ_XFRSIZ & OTG_DOEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + reg_value = OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA; + + if (ep->type == EP_TYPE_ISOC) { + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & OTG_DSTS_FNSOF0) == 0U) { + reg_value |= OTG_DOEPCTL_SD1PID_SODDFRM; + } else { + reg_value |= OTG_DOEPCTL_SD0PID_SEVNFRM; + } + } + + mmio_setbits_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Setup and start a transfer over the EP0. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep0_start_xfer(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + + if (ep->xfer_len == 0U) { + reg_value = OTG_DIEPTSIZ_PKTCNT_1; + } else { + /* + * Program the transfer size and packet count + * as follows: + * xfersize = N * maxpacket + short_packet + * pktcnt = N + (short_packet exist ? 1 : 0) + */ + + if (ep->xfer_len > ep->maxpacket) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->xfer_len; + } + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* Enable the TX FIFO empty interrupt for this EP */ + if (ep->xfer_len > 0U) { + mmio_setbits_32(usb_base_addr + OTG_DIEPEMPMSK, + BIT(ep->num)); + } + + /* EP enable, IN data in FIFO */ + mmio_setbits_32(reg_offset + OTG_DIEPCTL, + OTG_DIEPCTL_CNAK | OTG_DIEPCTL_EPENA); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + + /* + * Program the transfer size and packet count as follows: + * pktcnt = N + * xfersize = N * maxpacket + */ + if (ep->xfer_len > 0U) { + ep->xfer_len = ep->maxpacket; + } + + reg_value = OTG_DIEPTSIZ_PKTCNT_1 | ep->maxpacket; + + mmio_clrsetbits_32(reg_offset + OTG_DIEPTSIZ, + OTG_DIEPTSIZ_XFRSIZ | OTG_DIEPTSIZ_PKTCNT, + reg_value); + + /* EP enable */ + mmio_setbits_32(reg_offset + OTG_DOEPCTL, + OTG_DOEPCTL_CNAK | OTG_DOEPCTL_EPENA); + } + + return USBD_OK; +} + +/* + * Set a stall condition over an EP. + * handle: Selected device. + * ep: Pointer to endpoint structure. + * return: USB status. + */ +static enum usb_status usb_dwc2_ep_set_stall(void *handle, struct usbd_ep *ep) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + uint32_t reg_value; + + if (ep->is_in) { + reg_offset = usb_base_addr + OTG_DIEP_BASE + + (ep->num * OTG_DIEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DIEPCTL); + + if ((reg_value & OTG_DIEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DIEPCTL_EPDIS; + } + + reg_value |= OTG_DIEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DIEPCTL, reg_value); + } else { + reg_offset = usb_base_addr + OTG_DOEP_BASE + + (ep->num * OTG_DOEP_SIZE); + reg_value = mmio_read_32(reg_offset + OTG_DOEPCTL); + + if ((reg_value & OTG_DOEPCTL_EPENA) == 0U) { + reg_value &= ~OTG_DOEPCTL_EPDIS; + } + + reg_value |= OTG_DOEPCTL_STALL; + + mmio_write_32(reg_offset + OTG_DOEPCTL, reg_value); + } + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * return: USB status. + */ +static enum usb_status usb_dwc2_stop_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t i; + + /* Disable Int */ + mmio_clrbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + /* Clear pending interrupts */ + for (i = 0U; i < EP_NB; i++) { + mmio_write_32(usb_base_addr + OTG_DIEP_BASE + (i * OTG_DIEP_SIZE) + OTG_DIEPINT, + OTG_DIEPINT_MASK); + mmio_write_32(usb_base_addr + OTG_DOEP_BASE + (i * OTG_DOEP_SIZE) + OTG_DOEPINT, + OTG_DOEPINT_MASK); + } + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + + /* Clear interrupt masks */ + mmio_write_32(usb_base_addr + OTG_DIEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DOEPMSK, 0U); + mmio_write_32(usb_base_addr + OTG_DAINTMSK, 0U); + + /* Flush the FIFO */ + usb_dwc2_flush_rx_fifo(handle); + usb_dwc2_flush_tx_fifo(handle, EP_ALL); + + /* Disconnect the USB device by disabling the pull-up/pull-down */ + mmio_setbits_32((uintptr_t)handle + OTG_DCTL, OTG_DCTL_SDIS); + + return USBD_OK; +} + +/* + * Stop the USB device mode. + * handle: Selected device. + * address: New device address to be assigned. + * This parameter can be a value from 0 to 255. + * return: USB status. + */ +static enum usb_status usb_dwc2_set_address(void *handle, uint8_t address) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrsetbits_32(usb_base_addr + OTG_DCFG, + OTG_DCFG_DAD, + address << OTG_DCFG_DAD_SHIFT); + + return USBD_OK; +} + +/* + * Check FIFO for the next packet to be loaded. + * handle: Selected device. + * epnum : Endpoint number. + * xfer_len: Block length. + * xfer_count: Number of blocks. + * maxpacket: Max packet length. + * xfer_buff: Buffer pointer. + * return: USB status. + */ +static enum usb_status usb_dwc2_write_empty_tx_fifo(void *handle, + uint32_t epnum, + uint32_t xfer_len, + uint32_t *xfer_count, + uint32_t maxpacket, + uint8_t **xfer_buff) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t reg_offset; + int32_t len; + uint32_t len32b; + enum usb_status ret; + + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE); + + while (((mmio_read_32(reg_offset + OTG_DTXFSTS) & + OTG_DTXFSTS_INEPTFSAV) > len32b) && + (*xfer_count < xfer_len) && (xfer_len != 0U)) { + /* Write the FIFO */ + len = xfer_len - *xfer_count; + + if ((len > 0) && ((uint32_t)len > maxpacket)) { + len = maxpacket; + } + + len32b = (len + 3U) / 4U; + + ret = usb_dwc2_write_packet(handle, *xfer_buff, epnum, len); + if (ret != USBD_OK) { + return ret; + } + + *xfer_buff += len; + *xfer_count += len; + } + + if (len <= 0) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + } + + return USBD_OK; +} + +/* + * Handle PCD interrupt request. + * handle: PCD handle. + * param: Pointer to information updated by the IT handling. + * return: Action to do after IT handling. + */ +static enum usb_action usb_dwc2_it_handler(void *handle, uint32_t *param) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + uint32_t ep_intr; + uint32_t epint; + uint32_t epnum; + uint32_t temp; + enum usb_status ret; + + if (usb_dwc2_get_mode(handle) != USB_OTG_MODE_DEVICE) { + return USB_NOTHING; + } + + /* Avoid spurious interrupt */ + if (usb_dwc2_read_int(handle) == 0U) { + return USB_NOTHING; + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_MMIS) != 0U) { + /* Incorrect mode, acknowledge the interrupt */ + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_MMIS); + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_out_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DOEP_BASE + (epnum * OTG_DOEP_SIZE) + OTG_DOEPINT; + + epint = usb_dwc2_out_ep_int(handle, epnum); + + if ((epint & OTG_DOEPINT_XFRC) == OTG_DOEPINT_XFRC) { + mmio_write_32(reg_offset, OTG_DOEPINT_XFRC); + *param = epnum; + + return USB_DATA_OUT; + } + + if ((epint & OTG_DOEPINT_STUP) == OTG_DOEPINT_STUP) { + /* Inform that a setup packet is available */ + mmio_write_32(reg_offset, OTG_DOEPINT_STUP); + + return USB_SETUP; + } + + if ((epint & OTG_DOEPINT_OTEPDIS) == OTG_DOEPINT_OTEPDIS) { + mmio_write_32(reg_offset, OTG_DOEPINT_OTEPDIS); + } + } + + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IEPINT) != 0U) { + uint32_t reg_offset; + + /* Read in the device interrupt bits */ + ep_intr = usb_dwc2_all_in_ep_int(handle); + epnum = 0U; + while ((ep_intr & BIT(0)) != BIT(0)) { + epnum++; + ep_intr >>= 1; + } + + reg_offset = usb_base_addr + OTG_DIEP_BASE + (epnum * OTG_DIEP_SIZE) + OTG_DIEPINT; + + epint = usb_dwc2_in_ep_int(handle, epnum); + + if ((epint & OTG_DIEPINT_XFRC) == OTG_DIEPINT_XFRC) { + mmio_clrbits_32(usb_base_addr + OTG_DIEPEMPMSK, BIT(epnum)); + mmio_write_32(reg_offset, OTG_DIEPINT_XFRC); + *param = epnum; + + return USB_DATA_IN; + } + + if ((epint & OTG_DIEPINT_TOC) == OTG_DIEPINT_TOC) { + mmio_write_32(reg_offset, OTG_DIEPINT_TOC); + } + + if ((epint & OTG_DIEPINT_ITTXFE) == OTG_DIEPINT_ITTXFE) { + mmio_write_32(reg_offset, OTG_DIEPINT_ITTXFE); + } + + if ((epint & OTG_DIEPINT_INEPNE) == OTG_DIEPINT_INEPNE) { + mmio_write_32(reg_offset, OTG_DIEPINT_INEPNE); + } + + if ((epint & OTG_DIEPINT_EPDISD) == OTG_DIEPINT_EPDISD) { + mmio_write_32(reg_offset, OTG_DIEPINT_EPDISD); + } + + if ((epint & OTG_DIEPINT_TXFE) == OTG_DIEPINT_TXFE) { + *param = epnum; + + return USB_WRITE_EMPTY; + } + } + + /* Handle resume interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_WKUPINT) != 0U) { + INFO("handle USB : Resume\n"); + + /* Clear the remote wake-up signaling */ + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_WKUPINT); + + return USB_RESUME; + } + + /* Handle suspend interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBSUSP) != 0U) { + INFO("handle USB : Suspend int\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBSUSP); + + if ((mmio_read_32(usb_base_addr + OTG_DSTS) & + OTG_DSTS_SUSPSTS) == OTG_DSTS_SUSPSTS) { + return USB_SUSPEND; + } + } + + /* Handle LPM interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_LPMINT) != 0U) { + INFO("handle USB : LPM int enter in suspend\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_LPMINT); + *param = (mmio_read_32(usb_base_addr + OTG_GLPMCFG) & + OTG_GLPMCFG_BESL) >> 2; + + return USB_LPM; + } + + /* Handle reset interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_USBRST) != 0U) { + INFO("handle USB : Reset\n"); + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_RWUSIG); + + usb_dwc2_flush_tx_fifo(handle, 0U); + + mmio_write_32(usb_base_addr + OTG_DAINT, OTG_DAINT_IN_MASK | OTG_DAINT_OUT_MASK); + mmio_setbits_32(usb_base_addr + OTG_DAINTMSK, OTG_DAINT_EP0_IN | OTG_DAINT_EP0_OUT); + + mmio_setbits_32(usb_base_addr + OTG_DOEPMSK, OTG_DOEPMSK_STUPM | + OTG_DOEPMSK_XFRCM | + OTG_DOEPMSK_EPDM); + mmio_setbits_32(usb_base_addr + OTG_DIEPMSK, OTG_DIEPMSK_TOM | + OTG_DIEPMSK_XFRCM | + OTG_DIEPMSK_EPDM); + + /* Set default address to 0 */ + mmio_clrbits_32(usb_base_addr + OTG_DCFG, OTG_DCFG_DAD); + + /* Setup EP0 to receive SETUP packets */ + ret = usb_dwc2_ep0_out_start(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_USBRST); + + return USB_RESET; + } + + /* Handle enumeration done interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_ENUMDNE) != 0U) { + ret = usb_dwc2_activate_setup(handle); + if (ret != USBD_OK) { + return ret; + } + + mmio_clrbits_32(usb_base_addr + OTG_GUSBCFG, OTG_GUSBCFG_TRDT); + + mmio_setbits_32(usb_base_addr + OTG_GUSBCFG, + (USBD_HS_TRDT_VALUE << OTG_GUSBCFG_TRDT_SHIFT) & OTG_GUSBCFG_TRDT); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_ENUMDNE); + + return USB_ENUM_DONE; + } + + /* Handle RXQLevel interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_RXFLVL) != 0U) { + mmio_clrbits_32(usb_base_addr + OTG_GINTMSK, + OTG_GINTSTS_RXFLVL); + + temp = mmio_read_32(usb_base_addr + OTG_GRXSTSP); + + *param = temp & OTG_GRXSTSP_EPNUM; + *param |= (temp & OTG_GRXSTSP_BCNT) << (USBD_OUT_COUNT_SHIFT - + OTG_GRXSTSP_BCNT_SHIFT); + + if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == STS_DATA_UPDT) { + if ((temp & OTG_GRXSTSP_BCNT) != 0U) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_DATA_PACKET; + } + } else if (((temp & OTG_GRXSTSP_PKTSTS) >> OTG_GRXSTSP_PKTSTS_SHIFT) == + STS_SETUP_UPDT) { + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + + return USB_READ_SETUP_PACKET; + } + + mmio_setbits_32(usb_base_addr + OTG_GINTMSK, OTG_GINTSTS_RXFLVL); + } + + /* Handle SOF interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SOF) != 0U) { + INFO("handle USB : SOF\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SOF); + + return USB_SOF; + } + + /* Handle incomplete ISO IN interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IISOIXFR) != 0U) { + INFO("handle USB : ISO IN\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IISOIXFR); + } + + /* Handle incomplete ISO OUT interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_IPXFR_INCOMPISOOUT) != + 0U) { + INFO("handle USB : ISO OUT\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, + OTG_GINTSTS_IPXFR_INCOMPISOOUT); + } + + /* Handle connection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_SRQINT) != 0U) { + INFO("handle USB : Connect\n"); + + mmio_write_32(usb_base_addr + OTG_GINTSTS, OTG_GINTSTS_SRQINT); + } + + /* Handle disconnection event interrupt */ + if ((usb_dwc2_read_int(handle) & OTG_GINTSTS_OTGINT) != 0U) { + INFO("handle USB : Disconnect\n"); + + temp = mmio_read_32(usb_base_addr + OTG_GOTGINT); + + if ((temp & OTG_GOTGINT_SEDET) == OTG_GOTGINT_SEDET) { + return USB_DISCONNECT; + } + } + + return USB_NOTHING; +} + +/* + * Start the usb device mode + * usb_core_handle: USB core driver handle. + * return USB status. + */ +static enum usb_status usb_dwc2_start_device(void *handle) +{ + uintptr_t usb_base_addr = (uintptr_t)handle; + + mmio_clrbits_32(usb_base_addr + OTG_DCTL, OTG_DCTL_SDIS); + mmio_setbits_32(usb_base_addr + OTG_GAHBCFG, OTG_GAHBCFG_GINT); + + return USBD_OK; +} + +static const struct usb_driver usb_dwc2driver = { + .ep0_out_start = usb_dwc2_ep0_out_start, + .ep_start_xfer = usb_dwc2_ep_start_xfer, + .ep0_start_xfer = usb_dwc2_ep0_start_xfer, + .write_packet = usb_dwc2_write_packet, + .read_packet = usb_dwc2_read_packet, + .ep_set_stall = usb_dwc2_ep_set_stall, + .start_device = usb_dwc2_start_device, + .stop_device = usb_dwc2_stop_device, + .set_address = usb_dwc2_set_address, + .write_empty_tx_fifo = usb_dwc2_write_empty_tx_fifo, + .it_handler = usb_dwc2_it_handler +}; + +/* + * Initialize USB DWC2 driver. + * usb_core_handle: USB core driver handle. + * pcd_handle: PCD handle. + * base_register: USB global register base address. + */ +void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, + struct pcd_handle *pcd_handle, + void *base_register) +{ + register_usb_driver(usb_core_handle, pcd_handle, &usb_dwc2driver, + base_register); +} diff --git a/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c b/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c new file mode 100644 index 0000000..04f4673 --- /dev/null +++ b/arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c @@ -0,0 +1,432 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#define DWMMC_CTRL (0x00) +#define CTRL_IDMAC_EN (1 << 25) +#define CTRL_DMA_EN (1 << 5) +#define CTRL_INT_EN (1 << 4) +#define CTRL_DMA_RESET (1 << 2) +#define CTRL_FIFO_RESET (1 << 1) +#define CTRL_RESET (1 << 0) +#define CTRL_RESET_ALL (CTRL_DMA_RESET | CTRL_FIFO_RESET | \ + CTRL_RESET) + +#define DWMMC_PWREN (0x04) +#define DWMMC_CLKDIV (0x08) +#define DWMMC_CLKSRC (0x0c) +#define DWMMC_CLKENA (0x10) +#define DWMMC_TMOUT (0x14) +#define DWMMC_CTYPE (0x18) +#define CTYPE_8BIT (1 << 16) +#define CTYPE_4BIT (1) +#define CTYPE_1BIT (0) + +#define DWMMC_BLKSIZ (0x1c) +#define DWMMC_BYTCNT (0x20) +#define DWMMC_INTMASK (0x24) +#define INT_EBE (1 << 15) +#define INT_SBE (1 << 13) +#define INT_HLE (1 << 12) +#define INT_FRUN (1 << 11) +#define INT_DRT (1 << 9) +#define INT_RTO (1 << 8) +#define INT_DCRC (1 << 7) +#define INT_RCRC (1 << 6) +#define INT_RXDR (1 << 5) +#define INT_TXDR (1 << 4) +#define INT_DTO (1 << 3) +#define INT_CMD_DONE (1 << 2) +#define INT_RE (1 << 1) + +#define DWMMC_CMDARG (0x28) +#define DWMMC_CMD (0x2c) +#define CMD_START (U(1) << 31) +#define CMD_USE_HOLD_REG (1 << 29) /* 0 if SDR50/100 */ +#define CMD_UPDATE_CLK_ONLY (1 << 21) +#define CMD_SEND_INIT (1 << 15) +#define CMD_STOP_ABORT_CMD (1 << 14) +#define CMD_WAIT_PRVDATA_COMPLETE (1 << 13) +#define CMD_WRITE (1 << 10) +#define CMD_DATA_TRANS_EXPECT (1 << 9) +#define CMD_CHECK_RESP_CRC (1 << 8) +#define CMD_RESP_LEN (1 << 7) +#define CMD_RESP_EXPECT (1 << 6) +#define CMD(x) (x & 0x3f) + +#define DWMMC_RESP0 (0x30) +#define DWMMC_RESP1 (0x34) +#define DWMMC_RESP2 (0x38) +#define DWMMC_RESP3 (0x3c) +#define DWMMC_RINTSTS (0x44) +#define DWMMC_STATUS (0x48) +#define STATUS_DATA_BUSY (1 << 9) + +#define DWMMC_FIFOTH (0x4c) +#define FIFOTH_TWMARK(x) (x & 0xfff) +#define FIFOTH_RWMARK(x) ((x & 0x1ff) << 16) +#define FIFOTH_DMA_BURST_SIZE(x) ((x & 0x7) << 28) + +#define DWMMC_DEBNCE (0x64) +#define DWMMC_BMOD (0x80) +#define BMOD_ENABLE (1 << 7) +#define BMOD_FB (1 << 1) +#define BMOD_SWRESET (1 << 0) + +#define DWMMC_DBADDR (0x88) +#define DWMMC_IDSTS (0x8c) +#define DWMMC_IDINTEN (0x90) +#define DWMMC_CARDTHRCTL (0x100) +#define CARDTHRCTL_RD_THR(x) ((x & 0xfff) << 16) +#define CARDTHRCTL_RD_THR_EN (1 << 0) + +#define IDMAC_DES0_DIC (1 << 1) +#define IDMAC_DES0_LD (1 << 2) +#define IDMAC_DES0_FS (1 << 3) +#define IDMAC_DES0_CH (1 << 4) +#define IDMAC_DES0_ER (1 << 5) +#define IDMAC_DES0_CES (1 << 30) +#define IDMAC_DES0_OWN (U(1) << 31) +#define IDMAC_DES1_BS1(x) ((x) & 0x1fff) +#define IDMAC_DES2_BS2(x) (((x) & 0x1fff) << 13) + +#define DWMMC_DMA_MAX_BUFFER_SIZE (512 * 8) + +#define DWMMC_8BIT_MODE (1 << 6) + +#define DWMMC_ADDRESS_MASK U(0x0f) + +#define TIMEOUT 100000 + +struct dw_idmac_desc { + unsigned int des0; + unsigned int des1; + unsigned int des2; + unsigned int des3; +}; + +static void dw_init(void); +static int dw_send_cmd(struct mmc_cmd *cmd); +static int dw_set_ios(unsigned int clk, unsigned int width); +static int dw_prepare(int lba, uintptr_t buf, size_t size); +static int dw_read(int lba, uintptr_t buf, size_t size); +static int dw_write(int lba, uintptr_t buf, size_t size); + +static const struct mmc_ops dw_mmc_ops = { + .init = dw_init, + .send_cmd = dw_send_cmd, + .set_ios = dw_set_ios, + .prepare = dw_prepare, + .read = dw_read, + .write = dw_write, +}; + +static dw_mmc_params_t dw_params; + +static void dw_update_clk(void) +{ + unsigned int data; + + mmio_write_32(dw_params.reg_base + DWMMC_CMD, + CMD_WAIT_PRVDATA_COMPLETE | CMD_UPDATE_CLK_ONLY | + CMD_START); + while (1) { + data = mmio_read_32(dw_params.reg_base + DWMMC_CMD); + if ((data & CMD_START) == 0) + break; + data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); + assert((data & INT_HLE) == 0); + } +} + +static void dw_set_clk(int clk) +{ + unsigned int data; + int div; + + assert(clk > 0); + + for (div = 1; div < 256; div++) { + if ((dw_params.clk_rate / (2 * div)) <= clk) { + break; + } + } + assert(div < 256); + + /* wait until controller is idle */ + do { + data = mmio_read_32(dw_params.reg_base + DWMMC_STATUS); + } while (data & STATUS_DATA_BUSY); + + /* disable clock before change clock rate */ + mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 0); + dw_update_clk(); + + mmio_write_32(dw_params.reg_base + DWMMC_CLKDIV, div); + dw_update_clk(); + + /* enable clock */ + mmio_write_32(dw_params.reg_base + DWMMC_CLKENA, 1); + mmio_write_32(dw_params.reg_base + DWMMC_CLKSRC, 0); + dw_update_clk(); +} + +static void dw_init(void) +{ + unsigned int data; + uintptr_t base; + + assert((dw_params.reg_base & MMC_BLOCK_MASK) == 0); + + base = dw_params.reg_base; + mmio_write_32(base + DWMMC_PWREN, 1); + mmio_write_32(base + DWMMC_CTRL, CTRL_RESET_ALL); + do { + data = mmio_read_32(base + DWMMC_CTRL); + } while (data); + + /* enable DMA in CTRL */ + data = CTRL_INT_EN | CTRL_DMA_EN | CTRL_IDMAC_EN; + mmio_write_32(base + DWMMC_CTRL, data); + mmio_write_32(base + DWMMC_RINTSTS, ~0); + mmio_write_32(base + DWMMC_INTMASK, 0); + mmio_write_32(base + DWMMC_TMOUT, ~0); + mmio_write_32(base + DWMMC_IDINTEN, ~0); + mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); + mmio_write_32(base + DWMMC_BYTCNT, 256 * 1024); + mmio_write_32(base + DWMMC_DEBNCE, 0x00ffffff); + mmio_write_32(base + DWMMC_BMOD, BMOD_SWRESET); + do { + data = mmio_read_32(base + DWMMC_BMOD); + } while (data & BMOD_SWRESET); + /* enable DMA in BMOD */ + data |= BMOD_ENABLE | BMOD_FB; + mmio_write_32(base + DWMMC_BMOD, data); + + udelay(100); + dw_set_clk(MMC_BOOT_CLK_RATE); + udelay(100); +} + +static int dw_send_cmd(struct mmc_cmd *cmd) +{ + unsigned int op, data, err_mask; + uintptr_t base; + int timeout; + + assert(cmd); + + base = dw_params.reg_base; + + switch (cmd->cmd_idx) { + case 0: + op = CMD_SEND_INIT; + break; + case 12: + op = CMD_STOP_ABORT_CMD; + break; + case 13: + op = CMD_WAIT_PRVDATA_COMPLETE; + break; + case 8: + if (dw_params.mmc_dev_type == MMC_IS_EMMC) + op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; + else + op = CMD_WAIT_PRVDATA_COMPLETE; + break; + case 17: + case 18: + op = CMD_DATA_TRANS_EXPECT | CMD_WAIT_PRVDATA_COMPLETE; + break; + case 24: + case 25: + op = CMD_WRITE | CMD_DATA_TRANS_EXPECT | + CMD_WAIT_PRVDATA_COMPLETE; + break; + case 51: + op = CMD_DATA_TRANS_EXPECT; + break; + default: + op = 0; + break; + } + op |= CMD_USE_HOLD_REG | CMD_START; + switch (cmd->resp_type) { + case 0: + break; + case MMC_RESPONSE_R2: + op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC | + CMD_RESP_LEN; + break; + case MMC_RESPONSE_R3: + op |= CMD_RESP_EXPECT; + break; + default: + op |= CMD_RESP_EXPECT | CMD_CHECK_RESP_CRC; + break; + } + timeout = TIMEOUT; + do { + data = mmio_read_32(base + DWMMC_STATUS); + if (--timeout <= 0) + panic(); + } while (data & STATUS_DATA_BUSY); + + mmio_write_32(base + DWMMC_RINTSTS, ~0); + mmio_write_32(base + DWMMC_CMDARG, cmd->cmd_arg); + mmio_write_32(base + DWMMC_CMD, op | cmd->cmd_idx); + + err_mask = INT_EBE | INT_HLE | INT_RTO | INT_RCRC | INT_RE | + INT_DCRC | INT_DRT | INT_SBE; + timeout = TIMEOUT; + do { + udelay(500); + data = mmio_read_32(base + DWMMC_RINTSTS); + + if (data & err_mask) + return -EIO; + if (data & INT_DTO) + break; + if (--timeout == 0) { + ERROR("%s, RINTSTS:0x%x\n", __func__, data); + panic(); + } + } while (!(data & INT_CMD_DONE)); + + if (op & CMD_RESP_EXPECT) { + cmd->resp_data[0] = mmio_read_32(base + DWMMC_RESP0); + if (op & CMD_RESP_LEN) { + cmd->resp_data[1] = mmio_read_32(base + DWMMC_RESP1); + cmd->resp_data[2] = mmio_read_32(base + DWMMC_RESP2); + cmd->resp_data[3] = mmio_read_32(base + DWMMC_RESP3); + } + } + return 0; +} + +static int dw_set_ios(unsigned int clk, unsigned int width) +{ + switch (width) { + case MMC_BUS_WIDTH_1: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_1BIT); + break; + case MMC_BUS_WIDTH_4: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_4BIT); + break; + case MMC_BUS_WIDTH_8: + mmio_write_32(dw_params.reg_base + DWMMC_CTYPE, CTYPE_8BIT); + break; + default: + assert(0); + break; + } + dw_set_clk(clk); + return 0; +} + +static int dw_prepare(int lba, uintptr_t buf, size_t size) +{ + struct dw_idmac_desc *desc; + int desc_cnt, i, last; + uintptr_t base; + + assert(((buf & DWMMC_ADDRESS_MASK) == 0) && + (dw_params.desc_size > 0) && + ((dw_params.reg_base & MMC_BLOCK_MASK) == 0) && + ((dw_params.desc_base & MMC_BLOCK_MASK) == 0) && + ((dw_params.desc_size & MMC_BLOCK_MASK) == 0)); + + flush_dcache_range(buf, size); + + desc_cnt = (size + DWMMC_DMA_MAX_BUFFER_SIZE - 1) / + DWMMC_DMA_MAX_BUFFER_SIZE; + assert(desc_cnt * sizeof(struct dw_idmac_desc) < dw_params.desc_size); + + base = dw_params.reg_base; + desc = (struct dw_idmac_desc *)dw_params.desc_base; + mmio_write_32(base + DWMMC_BYTCNT, size); + + if (size < MMC_BLOCK_SIZE) + mmio_write_32(base + DWMMC_BLKSIZ, size); + else + mmio_write_32(base + DWMMC_BLKSIZ, MMC_BLOCK_SIZE); + + mmio_write_32(base + DWMMC_RINTSTS, ~0); + for (i = 0; i < desc_cnt; i++) { + desc[i].des0 = IDMAC_DES0_OWN | IDMAC_DES0_CH | IDMAC_DES0_DIC; + desc[i].des1 = IDMAC_DES1_BS1(DWMMC_DMA_MAX_BUFFER_SIZE); + desc[i].des2 = buf + DWMMC_DMA_MAX_BUFFER_SIZE * i; + desc[i].des3 = dw_params.desc_base + + (sizeof(struct dw_idmac_desc)) * (i + 1); + } + /* first descriptor */ + desc->des0 |= IDMAC_DES0_FS; + /* last descriptor */ + last = desc_cnt - 1; + (desc + last)->des0 |= IDMAC_DES0_LD; + (desc + last)->des0 &= ~(IDMAC_DES0_DIC | IDMAC_DES0_CH); + (desc + last)->des1 = IDMAC_DES1_BS1(size - (last * + DWMMC_DMA_MAX_BUFFER_SIZE)); + /* set next descriptor address as 0 */ + (desc + last)->des3 = 0; + + mmio_write_32(base + DWMMC_DBADDR, dw_params.desc_base); + flush_dcache_range(dw_params.desc_base, + desc_cnt * DWMMC_DMA_MAX_BUFFER_SIZE); + + + return 0; +} + +static int dw_read(int lba, uintptr_t buf, size_t size) +{ + uint32_t data = 0; + int timeout = TIMEOUT; + + do { + data = mmio_read_32(dw_params.reg_base + DWMMC_RINTSTS); + udelay(50); + } while (!(data & INT_DTO) && timeout-- > 0); + + inv_dcache_range(buf, size); + + return 0; +} + +static int dw_write(int lba, uintptr_t buf, size_t size) +{ + return 0; +} + +void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info) +{ + assert((params != 0) && + ((params->reg_base & MMC_BLOCK_MASK) == 0) && + ((params->desc_base & MMC_BLOCK_MASK) == 0) && + ((params->desc_size & MMC_BLOCK_MASK) == 0) && + (params->desc_size > 0) && + (params->clk_rate > 0) && + ((params->bus_width == MMC_BUS_WIDTH_1) || + (params->bus_width == MMC_BUS_WIDTH_4) || + (params->bus_width == MMC_BUS_WIDTH_8))); + + memcpy(&dw_params, params, sizeof(dw_mmc_params_t)); + dw_params.mmc_dev_type = info->mmc_dev_type; + mmc_init(&dw_mmc_ops, params->clk_rate, params->bus_width, + params->flags, info); +} diff --git a/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c b/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c new file mode 100644 index 0000000..6bed981 --- /dev/null +++ b/arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +static int dwufs_phy_init(ufs_params_t *params) +{ + uintptr_t base; + unsigned int fsm0, fsm1; + unsigned int data; + int result; + + assert((params != NULL) && (params->reg_base != 0)); + + base = params->reg_base; + + /* Unipro VS_MPHY disable */ + ufshc_dme_set(VS_MPHY_DISABLE_OFFSET, 0, VS_MPHY_DISABLE_MPHYDIS); + ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2); + /* MPHY CBRATESEL */ + ufshc_dme_set(0x8114, 0, 1); + /* MPHY CBOVRCTRL2 */ + ufshc_dme_set(0x8121, 0, 0x2d); + /* MPHY CBOVRCTRL3 */ + ufshc_dme_set(0x8122, 0, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + /* MPHY RXOVRCTRL4 rx0 */ + ufshc_dme_set(0x800d, 4, 0x58); + /* MPHY RXOVRCTRL4 rx1 */ + ufshc_dme_set(0x800d, 5, 0x58); + /* MPHY RXOVRCTRL5 rx0 */ + ufshc_dme_set(0x800e, 4, 0xb); + /* MPHY RXOVRCTRL5 rx1 */ + ufshc_dme_set(0x800e, 5, 0xb); + /* MPHY RXSQCONTROL rx0 */ + ufshc_dme_set(0x8009, 4, 0x1); + /* MPHY RXSQCONTROL rx1 */ + ufshc_dme_set(0x8009, 5, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + ufshc_dme_set(0x8113, 0, 0x1); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a); + ufshc_dme_set(RX_HS_G3_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a); + ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 4, 0x4a); + ufshc_dme_set(RX_HS_G2_SYNC_LENGTH_CAP_OFFSET, 5, 0x4a); + ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 4, 0x7); + ufshc_dme_set(RX_MIN_ACTIVATETIME_CAP_OFFSET, 5, 0x7); + ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 0, 0x5); + ufshc_dme_set(TX_HIBERN8TIME_CAP_OFFSET, 1, 0x5); + ufshc_dme_set(VS_MPHY_CFG_UPDT_OFFSET, 0, 1); + + result = ufshc_dme_get(VS_MPHY_DISABLE_OFFSET, 0, &data); + assert((result == 0) && (data == VS_MPHY_DISABLE_MPHYDIS)); + /* enable Unipro VS MPHY */ + ufshc_dme_set(VS_MPHY_DISABLE_OFFSET, 0, 0); + + while (1) { + result = ufshc_dme_get(TX_FSM_STATE_OFFSET, 0, &fsm0); + assert(result == 0); + result = ufshc_dme_get(TX_FSM_STATE_OFFSET, 1, &fsm1); + assert(result == 0); + if ((fsm0 == TX_FSM_STATE_HIBERN8) && + (fsm1 == TX_FSM_STATE_HIBERN8)) + break; + } + + mmio_write_32(base + HCLKDIV, 0xE4); + mmio_clrbits_32(base + AHIT, 0x3FF); + + ufshc_dme_set(PA_LOCAL_TX_LCC_ENABLE_OFFSET, 0, 0); + ufshc_dme_set(VS_MK2_EXTN_SUPPORT_OFFSET, 0, 0); + + result = ufshc_dme_get(VS_MK2_EXTN_SUPPORT_OFFSET, 0, &data); + assert((result == 0) && (data == 0)); + + ufshc_dme_set(DL_AFC0_CREDIT_THRESHOLD_OFFSET, 0, 0); + ufshc_dme_set(DL_TC0_OUT_ACK_THRESHOLD_OFFSET, 0, 0); + ufshc_dme_set(DL_TC0_TX_FC_THRESHOLD_OFFSET, 0, 9); + (void)result; + return 0; +} + +static int dwufs_phy_set_pwr_mode(ufs_params_t *params) +{ + int result; + unsigned int data, tx_lanes, rx_lanes; + uintptr_t base; + unsigned int flags; + + assert((params != NULL) && (params->reg_base != 0)); + + base = params->reg_base; + flags = params->flags; + if ((flags & UFS_FLAGS_VENDOR_SKHYNIX) != 0U) { + NOTICE("ufs: H**** device must set VS_DebugSaveConfigTime 0x10\n"); + /* VS_DebugSaveConfigTime */ + result = ufshc_dme_set(0xd0a0, 0x0, 0x10); + assert(result == 0); + /* sync length */ + result = ufshc_dme_set(0x1556, 0x0, 0x48); + assert(result == 0); + } + + result = ufshc_dme_get(PA_TACTIVATE_OFFSET, 0, &data); + assert(result == 0); + if (data < 7) { + result = ufshc_dme_set(PA_TACTIVATE_OFFSET, 0, 7); + assert(result == 0); + } + result = ufshc_dme_get(PA_CONNECTED_TX_DATA_LANES_OFFSET, 0, &tx_lanes); + assert(result == 0); + result = ufshc_dme_get(PA_CONNECTED_RX_DATA_LANES_OFFSET, 0, &rx_lanes); + assert(result == 0); + + result = ufshc_dme_set(PA_TX_SKIP_OFFSET, 0, 0); + assert(result == 0); + result = ufshc_dme_set(PA_TX_GEAR_OFFSET, 0, 3); + assert(result == 0); + result = ufshc_dme_set(PA_RX_GEAR_OFFSET, 0, 3); + assert(result == 0); + result = ufshc_dme_set(PA_HS_SERIES_OFFSET, 0, 2); + assert(result == 0); + result = ufshc_dme_set(PA_TX_TERMINATION_OFFSET, 0, 1); + assert(result == 0); + result = ufshc_dme_set(PA_RX_TERMINATION_OFFSET, 0, 1); + assert(result == 0); + result = ufshc_dme_set(PA_SCRAMBLING_OFFSET, 0, 0); + assert(result == 0); + result = ufshc_dme_set(PA_ACTIVE_TX_DATA_LANES_OFFSET, 0, tx_lanes); + assert(result == 0); + result = ufshc_dme_set(PA_ACTIVE_RX_DATA_LANES_OFFSET, 0, rx_lanes); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA0_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA1_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA2_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(DME_FC0_PROTECTION_TIMEOUT_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(DME_TC0_REPLAY_TIMEOUT_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(DME_AFC0_REQ_TIMEOUT_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA3_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA4_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(PA_PWR_MODE_USER_DATA5_OFFSET, 0, 32767); + assert(result == 0); + result = ufshc_dme_set(DME_FC1_PROTECTION_TIMEOUT_OFFSET, 0, 8191); + assert(result == 0); + result = ufshc_dme_set(DME_TC1_REPLAY_TIMEOUT_OFFSET, 0, 65535); + assert(result == 0); + result = ufshc_dme_set(DME_AFC1_REQ_TIMEOUT_OFFSET, 0, 32767); + assert(result == 0); + + result = ufshc_dme_set(PA_PWR_MODE_OFFSET, 0, 0x11); + assert(result == 0); + do { + data = mmio_read_32(base + IS); + } while ((data & UFS_INT_UPMS) == 0); + mmio_write_32(base + IS, UFS_INT_UPMS); + data = mmio_read_32(base + HCS); + if ((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL) + INFO("ufs: change power mode success\n"); + else + WARN("ufs: HCS.UPMCRS error, HCS:0x%x\n", data); + (void)result; + return 0; +} + +static const ufs_ops_t dw_ufs_ops = { + .phy_init = dwufs_phy_init, + .phy_set_pwr_mode = dwufs_phy_set_pwr_mode, +}; + +int dw_ufs_init(dw_ufs_params_t *params) +{ + ufs_params_t ufs_params; + + memset(&ufs_params, 0, sizeof(ufs_params)); + ufs_params.reg_base = params->reg_base; + ufs_params.desc_base = params->desc_base; + ufs_params.desc_size = params->desc_size; + ufs_params.flags = params->flags; + ufs_init(&dw_ufs_ops, &ufs_params); + return 0; +} diff --git a/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S b/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S new file mode 100644 index 0000000..0429f87 --- /dev/null +++ b/arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_16550_core_init + .globl console_16550_core_putc + .globl console_16550_core_getc + .globl console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: r0 - console base address + * r1 - Uart clock in Hz + * r2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : r1, r2, r3 + * ----------------------------------------------- + */ +func console_16550_core_init + /* Check the input base address */ + cmp r0, #0 + beq init_fail + /* Check baud rate and uart clock for sanity */ + cmp r1, #0 + beq init_fail + cmp r2, #0 + beq init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl r2, r2, #4 + udiv r2, r1, r2 + and r1, r2, #0xff /* w1 = DLL */ + lsr r2, r2, #8 + and r2, r2, #0xff /* w2 = DLLM */ + ldr r3, [r0, #UARTLCR] + orr r3, r3, #UARTLCR_DLAB + str r3, [r0, #UARTLCR] /* enable DLL, DLLM programming */ + str r1, [r0, #UARTDLL] /* program DLL */ + str r2, [r0, #UARTDLLM] /* program DLLM */ + mov r2, #~UARTLCR_DLAB + and r3, r3, r2 + str r3, [r0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov r3, #3 + str r3, [r0, #UARTLCR] + /* no interrupt */ + mov r3, #0 + str r3, [r0, #UARTIER] +#ifdef TI_16550_MDR_QUIRK + /* UART must be enabled on some platforms via the MDR register */ + str r3, [r0, #UARTMDR1] +#endif /* TI_16550_MDR_QUIRK */ + /* enable fifo, DMA */ + mov r3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN) + str r3, [r0, #UARTFCR] + /* DTR + RTS */ + mov r3, #3 + str r3, [r0, #UARTMCR] + mov r0, #1 + bx lr +init_fail: + mov r0, #0 + bx lr +endfunc console_16550_core_init + + .globl console_16550_register + + /* ------------------------------------------------------- + * int console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If r1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. r2 is ignored then as well. + * In: r0 - UART register base address + * r1 - UART clock in Hz + * r2 - Baud rate (ignored if r1 is 0) + * r3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : r0, r1, r2 + * ------------------------------------------------------- + */ +func console_16550_register + push {r4, lr} + mov r4, r3 + cmp r4, #0 + beq register_fail + str r0, [r4, #CONSOLE_T_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cmp r1, #0 + beq register_16550 + + bl console_16550_core_init + cmp r0, #0 + beq register_fail + +register_16550: + mov r0, r4 + pop {r4, lr} + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + pop {r4, pc} +endfunc console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - console base address + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp r0, #0xA + bne 2f + /* Check if the transmit FIFO is full */ +1: ldr r2, [r1, #UARTLSR] + and r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r2, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 1b + mov r2, #0xD /* '\r' */ + str r2, [r1, #UARTTX] + + /* Check if the transmit FIFO is full */ +2: ldr r2, [r1, #UARTLSR] + and r2, r2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r2, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 2b + str r0, [r1, #UARTTX] + bx lr +endfunc console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : r0 - character to be printed + * r1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : r2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r1, [r1, #CONSOLE_T_BASE] + b console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : r0 - console base address + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldr r1, [r0, #UARTLSR] + tst r1, #UARTLSR_RDR_BIT + beq no_char + ldr r1, [r0, #UARTRX] + mov r0, r1 + bx lr +no_char: + mov r0, #ERROR_NO_PENDING_CHAR + bx lr +endfunc console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : r0 - pointer to console_t stucture + * Out : r0 - character if available, else -1 + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * void console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - console base address + * Out : void. + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldr r1, [r0, #UARTLSR] + and r1, r1, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp r1, #(UARTLSR_TEMT | UARTLSR_THRE) + bne 1b + + bx lr +endfunc console_16550_core_flush + + /* --------------------------------------------- + * void console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : r0 - pointer to console_t structure + * Out : void + * Clobber list : r0, r1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr r0, [r0, #CONSOLE_T_BASE] + b console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S b/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S new file mode 100644 index 0000000..cb21512 --- /dev/null +++ b/arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + /* + * "core" functions are low-level implementations that don't require + * writable memory and are thus safe to call in BL1 crash context. + */ + .globl console_16550_core_init + .globl console_16550_core_putc + .globl console_16550_core_getc + .globl console_16550_core_flush + + .globl console_16550_putc + .globl console_16550_getc + .globl console_16550_flush + + /* ----------------------------------------------- + * int console_16550_core_init(uintptr_t base_addr, + * unsigned int uart_clk, unsigned int baud_rate) + * Function to initialize the console without a + * C Runtime to print debug information. This + * function will be accessed by console_init and + * crash reporting. + * In: x0 - console base address + * w1 - Uart clock in Hz + * w2 - Baud rate + * Out: return 1 on success, 0 on error + * Clobber list : x1, x2, x3 + * ----------------------------------------------- + */ +func console_16550_core_init + /* Check the input base address */ + cbz x0, init_fail + /* Check baud rate and uart clock for sanity */ + cbz w1, init_fail + cbz w2, init_fail + + /* Program the baudrate */ + /* Divisor = Uart clock / (16 * baudrate) */ + lsl w2, w2, #4 + udiv w2, w1, w2 + and w1, w2, #0xff /* w1 = DLL */ + lsr w2, w2, #8 + and w2, w2, #0xff /* w2 = DLLM */ + ldr w3, [x0, #UARTLCR] + orr w3, w3, #UARTLCR_DLAB + str w3, [x0, #UARTLCR] /* enable DLL, DLLM programming */ + str w1, [x0, #UARTDLL] /* program DLL */ + str w2, [x0, #UARTDLLM] /* program DLLM */ + mov w2, #~UARTLCR_DLAB + and w3, w3, w2 + str w3, [x0, #UARTLCR] /* disable DLL, DLLM programming */ + + /* 8n1 */ + mov w3, #3 + str w3, [x0, #UARTLCR] + /* no interrupt */ + mov w3, #0 + str w3, [x0, #UARTIER] +#ifdef TI_16550_MDR_QUIRK + /* UART must be enabled on some platforms via the MDR register */ + str w3, [x0, #UARTMDR1] +#endif /* TI_16550_MDR_QUIRK */ + /* enable fifo, DMA */ + mov w3, #(UARTFCR_FIFOEN | UARTFCR_DMAEN) + str w3, [x0, #UARTFCR] + /* DTR + RTS */ + mov w3, #3 + str w3, [x0, #UARTMCR] + mov w0, #1 + ret +init_fail: + mov w0, #0 + ret +endfunc console_16550_core_init + + .globl console_16550_register + + /* ----------------------------------------------- + * int console_16550_register(uintptr_t baseaddr, + * uint32_t clock, uint32_t baud, + * console_t *console); + * Function to initialize and register a new 16550 + * console. Storage passed in for the console struct + * *must* be persistent (i.e. not from the stack). + * If w1 (UART clock) is 0, initialisation will be + * skipped, relying on previous code to have done + * this already. w2 is ignored then as well. + * In: x0 - UART register base address + * w1 - UART clock in Hz + * w2 - Baud rate (ignored if w1 is 0) + * x3 - pointer to empty console_t struct + * Out: return 1 on success, 0 on error + * Clobber list : x0, x1, x2, x6, x7, x14 + * ----------------------------------------------- + */ +func console_16550_register + mov x7, x30 + mov x6, x3 + cbz x6, register_fail + str x0, [x6, #CONSOLE_T_BASE] + + /* A clock rate of zero means to skip the initialisation. */ + cbz w1, register_16550 + + bl console_16550_core_init + cbz x0, register_fail + +register_16550: + mov x0, x6 + mov x30, x7 + finish_console_register 16550 putc=1, getc=1, flush=1 + +register_fail: + ret x7 +endfunc console_16550_register + + /* -------------------------------------------------------- + * int console_16550_core_putc(int c, uintptr_t base_addr) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - console base address + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_core_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Prepend '\r' to '\n' */ + cmp w0, #0xA + b.ne 2f + /* Check if the transmit FIFO is full */ +1: ldr w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 1b + mov w2, #0xD /* '\r' */ + str w2, [x1, #UARTTX] + + /* Check if the transmit FIFO is full */ +2: ldr w2, [x1, #UARTLSR] + and w2, w2, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w2, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 2b + str w0, [x1, #UARTTX] + ret +endfunc console_16550_core_putc + + /* -------------------------------------------------------- + * int console_16550_putc(int c, console_t *console) + * Function to output a character over the console. It + * returns the character printed on success or -1 on error. + * In : w0 - character to be printed + * x1 - pointer to console_t structure + * Out : return -1 on error else return character. + * Clobber list : x2 + * -------------------------------------------------------- + */ +func console_16550_putc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x1, [x1, #CONSOLE_T_BASE] + b console_16550_core_putc +endfunc console_16550_putc + + /* --------------------------------------------- + * int console_16550_core_getc(uintptr_t base_addr) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - console base address + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_core_getc +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Check if the receive FIFO is empty */ +1: ldr w1, [x0, #UARTLSR] + tbz w1, #UARTLSR_RDR_BIT, no_char + ldr w0, [x0, #UARTRX] + ret +no_char: + mov w0, #ERROR_NO_PENDING_CHAR + ret +endfunc console_16550_core_getc + + /* --------------------------------------------- + * int console_16550_getc(console_t *console) + * Function to get a character from the console. + * It returns the character grabbed on success + * or -1 on if no character is available. + * In : x0 - pointer to console_t stucture + * Out : w0 - character if available, else -1 + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_getc +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_16550_core_getc +endfunc console_16550_getc + + /* --------------------------------------------- + * void console_16550_core_flush(uintptr_t base_addr) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - console base address + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_core_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* Loop until the transmit FIFO is empty */ +1: ldr w1, [x0, #UARTLSR] + and w1, w1, #(UARTLSR_TEMT | UARTLSR_THRE) + cmp w1, #(UARTLSR_TEMT | UARTLSR_THRE) + b.ne 1b + + ret +endfunc console_16550_core_flush + + /* --------------------------------------------- + * void console_16550_flush(console_t *console) + * Function to force a write of all buffered + * data that hasn't been output. + * In : x0 - pointer to console_t structure + * Out : void. + * Clobber list : x0, x1 + * --------------------------------------------- + */ +func console_16550_flush +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + ldr x0, [x0, #CONSOLE_T_BASE] + b console_16550_core_flush +endfunc console_16550_flush diff --git a/arm-trusted-firmware/drivers/ufs/ufs.c b/arm-trusted-firmware/drivers/ufs/ufs.c new file mode 100644 index 0000000..3c27aff --- /dev/null +++ b/arm-trusted-firmware/drivers/ufs/ufs.c @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#define CDB_ADDR_MASK 127 +#define ALIGN_CDB(x) (((x) + CDB_ADDR_MASK) & ~CDB_ADDR_MASK) +#define ALIGN_8(x) (((x) + 7) & ~7) + +#define UFS_DESC_SIZE 0x400 +#define MAX_UFS_DESC_SIZE 0x8000 /* 32 descriptors */ + +#define MAX_PRDT_SIZE 0x40000 /* 256KB */ + +static ufs_params_t ufs_params; +static int nutrs; /* Number of UTP Transfer Request Slots */ + +int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd) +{ + unsigned int data; + + if (base == 0 || cmd == NULL) + return -EINVAL; + + data = mmio_read_32(base + HCS); + if ((data & HCS_UCRDY) == 0) + return -EBUSY; + mmio_write_32(base + IS, ~0); + mmio_write_32(base + UCMDARG1, cmd->arg1); + mmio_write_32(base + UCMDARG2, cmd->arg2); + mmio_write_32(base + UCMDARG3, cmd->arg3); + mmio_write_32(base + UICCMD, cmd->op); + + do { + data = mmio_read_32(base + IS); + } while ((data & UFS_INT_UCCS) == 0); + mmio_write_32(base + IS, UFS_INT_UCCS); + return mmio_read_32(base + UCMDARG2) & CONFIG_RESULT_CODE_MASK; +} + +int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val) +{ + uintptr_t base; + unsigned int data; + int result, retries; + uic_cmd_t cmd; + + assert(ufs_params.reg_base != 0); + + if (val == NULL) + return -EINVAL; + + base = ufs_params.reg_base; + for (retries = 0; retries < 100; retries++) { + data = mmio_read_32(base + HCS); + if ((data & HCS_UCRDY) != 0) + break; + mdelay(1); + } + if (retries >= 100) + return -EBUSY; + + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = 0; + cmd.op = DME_GET; + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; + data = mmio_read_32(base + IS); + if (data & UFS_INT_UE) + return -EINVAL; + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; + + *val = mmio_read_32(base + UCMDARG3); + return 0; +} + +int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val) +{ + uintptr_t base; + unsigned int data; + int result, retries; + uic_cmd_t cmd; + + assert((ufs_params.reg_base != 0)); + + base = ufs_params.reg_base; + cmd.arg1 = (attr << 16) | GEN_SELECTOR_IDX(idx); + cmd.arg2 = 0; + cmd.arg3 = val; + cmd.op = DME_SET; + + for (retries = 0; retries < UFS_UIC_COMMAND_RETRIES; ++retries) { + result = ufshc_send_uic_cmd(base, &cmd); + if (result == 0) + break; + data = mmio_read_32(base + IS); + if (data & UFS_INT_UE) + return -EINVAL; + } + if (retries >= UFS_UIC_COMMAND_RETRIES) + return -EIO; + + return 0; +} + +static int ufshc_hce_enable(uintptr_t base) +{ + unsigned int data; + int retries; + + /* Enable Host Controller */ + mmio_write_32(base + HCE, HCE_ENABLE); + + /* Wait until basic initialization sequence completed */ + for (retries = 0; retries < HCE_ENABLE_INNER_RETRIES; ++retries) { + data = mmio_read_32(base + HCE); + if (data & HCE_ENABLE) { + break; + } + udelay(HCE_ENABLE_TIMEOUT_US); + } + if (retries >= HCE_ENABLE_INNER_RETRIES) { + return -ETIMEDOUT; + } + + return 0; +} + +static int ufshc_reset(uintptr_t base) +{ + unsigned int data; + int retries, result; + + for (retries = 0; retries < HCE_ENABLE_OUTER_RETRIES; ++retries) { + result = ufshc_hce_enable(base); + if (result == 0) { + break; + } + } + if (retries >= HCE_ENABLE_OUTER_RETRIES) { + return -EIO; + } + + /* Enable Interrupts */ + data = UFS_INT_UCCS | UFS_INT_ULSS | UFS_INT_UE | UFS_INT_UTPES | + UFS_INT_DFES | UFS_INT_HCFES | UFS_INT_SBFES; + mmio_write_32(base + IE, data); + + return 0; +} + +static int ufshc_dme_link_startup(uintptr_t base) +{ + uic_cmd_t cmd; + + memset(&cmd, 0, sizeof(cmd)); + cmd.op = DME_LINKSTARTUP; + return ufshc_send_uic_cmd(base, &cmd); +} + +static int ufshc_link_startup(uintptr_t base) +{ + int data, result; + int retries; + + for (retries = DME_LINKSTARTUP_RETRIES; retries > 0; retries--) { + result = ufshc_dme_link_startup(base); + if (result != 0) { + /* Reset controller before trying again */ + result = ufshc_reset(base); + if (result != 0) { + return result; + } + continue; + } + while ((mmio_read_32(base + HCS) & HCS_DP) == 0) + ; + data = mmio_read_32(base + IS); + if (data & UFS_INT_ULSS) + mmio_write_32(base + IS, UFS_INT_ULSS); + return 0; + } + return -EIO; +} + +/* Check Door Bell register to get an empty slot */ +static int get_empty_slot(int *slot) +{ + unsigned int data; + int i; + + data = mmio_read_32(ufs_params.reg_base + UTRLDBR); + for (i = 0; i < nutrs; i++) { + if ((data & 1) == 0) + break; + data = data >> 1; + } + if (i >= nutrs) + return -EBUSY; + *slot = i; + return 0; +} + +static void get_utrd(utp_utrd_t *utrd) +{ + uintptr_t base; + int slot = 0, result; + utrd_header_t *hd; + + assert(utrd != NULL); + result = get_empty_slot(&slot); + assert(result == 0); + + /* clear utrd */ + memset((void *)utrd, 0, sizeof(utp_utrd_t)); + base = ufs_params.desc_base + (slot * UFS_DESC_SIZE); + /* clear the descriptor */ + memset((void *)base, 0, UFS_DESC_SIZE); + + utrd->header = base; + utrd->task_tag = slot + 1; + /* CDB address should be aligned with 128 bytes */ + utrd->upiu = ALIGN_CDB(utrd->header + sizeof(utrd_header_t)); + utrd->resp_upiu = ALIGN_8(utrd->upiu + sizeof(cmd_upiu_t)); + utrd->size_upiu = utrd->resp_upiu - utrd->upiu; + utrd->size_resp_upiu = ALIGN_8(sizeof(resp_upiu_t)); + utrd->prdt = utrd->resp_upiu + utrd->size_resp_upiu; + + hd = (utrd_header_t *)utrd->header; + hd->ucdba = utrd->upiu & UINT32_MAX; + hd->ucdbau = (utrd->upiu >> 32) & UINT32_MAX; + /* Both RUL and RUO is based on DWORD */ + hd->rul = utrd->size_resp_upiu >> 2; + hd->ruo = utrd->size_upiu >> 2; + (void)result; +} + +/* + * Prepare UTRD, Command UPIU, Response UPIU. + */ +static int ufs_prepare_cmd(utp_utrd_t *utrd, uint8_t op, uint8_t lun, + int lba, uintptr_t buf, size_t length) +{ + utrd_header_t *hd; + cmd_upiu_t *upiu; + prdt_t *prdt; + unsigned int ulba; + unsigned int lba_cnt; + int prdt_size; + + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->upiu >> 32) & UINT32_MAX); + + hd = (utrd_header_t *)utrd->header; + upiu = (cmd_upiu_t *)utrd->upiu; + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + upiu->trans_type = CMD_UPIU; + upiu->task_tag = utrd->task_tag; + upiu->cdb[0] = op; + ulba = (unsigned int)lba; + lba_cnt = (unsigned int)(length >> UFS_BLOCK_SHIFT); + switch (op) { + case CDBCMD_TEST_UNIT_READY: + break; + case CDBCMD_READ_CAPACITY_10: + hd->dd = DD_OUT; + upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + break; + case CDBCMD_READ_10: + hd->dd = DD_OUT; + upiu->flags = UPIU_FLAGS_R | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + upiu->cdb[1] = RW_WITHOUT_CACHE; + /* set logical block address */ + upiu->cdb[2] = (ulba >> 24) & 0xff; + upiu->cdb[3] = (ulba >> 16) & 0xff; + upiu->cdb[4] = (ulba >> 8) & 0xff; + upiu->cdb[5] = ulba & 0xff; + /* set transfer length */ + upiu->cdb[7] = (lba_cnt >> 8) & 0xff; + upiu->cdb[8] = lba_cnt & 0xff; + break; + case CDBCMD_WRITE_10: + hd->dd = DD_IN; + upiu->flags = UPIU_FLAGS_W | UPIU_FLAGS_ATTR_S; + upiu->lun = lun; + upiu->cdb[1] = RW_WITHOUT_CACHE; + /* set logical block address */ + upiu->cdb[2] = (ulba >> 24) & 0xff; + upiu->cdb[3] = (ulba >> 16) & 0xff; + upiu->cdb[4] = (ulba >> 8) & 0xff; + upiu->cdb[5] = ulba & 0xff; + /* set transfer length */ + upiu->cdb[7] = (lba_cnt >> 8) & 0xff; + upiu->cdb[8] = lba_cnt & 0xff; + break; + default: + assert(0); + break; + } + if (hd->dd == DD_IN) + flush_dcache_range(buf, length); + else if (hd->dd == DD_OUT) + inv_dcache_range(buf, length); + if (length) { + upiu->exp_data_trans_len = htobe32(length); + assert(lba_cnt <= UINT16_MAX); + prdt = (prdt_t *)utrd->prdt; + + prdt_size = 0; + while (length > 0) { + prdt->dba = (unsigned int)(buf & UINT32_MAX); + prdt->dbau = (unsigned int)((buf >> 32) & UINT32_MAX); + /* prdt->dbc counts from 0 */ + if (length > MAX_PRDT_SIZE) { + prdt->dbc = MAX_PRDT_SIZE - 1; + length = length - MAX_PRDT_SIZE; + } else { + prdt->dbc = length - 1; + length = 0; + } + buf += MAX_PRDT_SIZE; + prdt++; + prdt_size += sizeof(prdt_t); + } + utrd->size_prdt = ALIGN_8(prdt_size); + hd->prdtl = utrd->size_prdt >> 2; + hd->prdto = (utrd->size_upiu + utrd->size_resp_upiu) >> 2; + } + + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); + return 0; +} + +static int ufs_prepare_query(utp_utrd_t *utrd, uint8_t op, uint8_t idn, + uint8_t index, uint8_t sel, + uintptr_t buf, size_t length) +{ + utrd_header_t *hd; + query_upiu_t *query_upiu; + + + hd = (utrd_header_t *)utrd->header; + query_upiu = (query_upiu_t *)utrd->upiu; + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->header >> 32) & UINT32_MAX); + + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + query_upiu->trans_type = QUERY_REQUEST_UPIU; + query_upiu->task_tag = utrd->task_tag; + query_upiu->ts.desc.opcode = op; + query_upiu->ts.desc.idn = idn; + query_upiu->ts.desc.index = index; + query_upiu->ts.desc.selector = sel; + switch (op) { + case QUERY_READ_DESC: + query_upiu->query_func = QUERY_FUNC_STD_READ; + query_upiu->ts.desc.length = htobe16(length); + break; + case QUERY_WRITE_DESC: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + query_upiu->ts.desc.length = htobe16(length); + memcpy((void *)(utrd->upiu + sizeof(query_upiu_t)), + (void *)buf, length); + break; + case QUERY_READ_ATTR: + case QUERY_READ_FLAG: + query_upiu->query_func = QUERY_FUNC_STD_READ; + break; + case QUERY_CLEAR_FLAG: + case QUERY_SET_FLAG: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + break; + case QUERY_WRITE_ATTR: + query_upiu->query_func = QUERY_FUNC_STD_WRITE; + memcpy((void *)&query_upiu->ts.attr.value, (void *)buf, length); + break; + default: + assert(0); + break; + } + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); + return 0; +} + +static void ufs_prepare_nop_out(utp_utrd_t *utrd) +{ + utrd_header_t *hd; + nop_out_upiu_t *nop_out; + + mmio_write_32(ufs_params.reg_base + UTRLBA, + utrd->header & UINT32_MAX); + mmio_write_32(ufs_params.reg_base + UTRLBAU, + (utrd->header >> 32) & UINT32_MAX); + + hd = (utrd_header_t *)utrd->header; + nop_out = (nop_out_upiu_t *)utrd->upiu; + + hd->i = 1; + hd->ct = CT_UFS_STORAGE; + hd->ocs = OCS_MASK; + + nop_out->trans_type = 0; + nop_out->task_tag = utrd->task_tag; + flush_dcache_range((uintptr_t)utrd, sizeof(utp_utrd_t)); + flush_dcache_range((uintptr_t)utrd->header, UFS_DESC_SIZE); +} + +static void ufs_send_request(int task_tag) +{ + unsigned int data; + int slot; + + slot = task_tag - 1; + /* clear all interrupts */ + mmio_write_32(ufs_params.reg_base + IS, ~0); + + mmio_write_32(ufs_params.reg_base + UTRLRSR, 1); + do { + data = mmio_read_32(ufs_params.reg_base + UTRLRSR); + } while (data == 0); + + data = UTRIACR_IAEN | UTRIACR_CTR | UTRIACR_IACTH(0x1F) | + UTRIACR_IATOVAL(0xFF); + mmio_write_32(ufs_params.reg_base + UTRIACR, data); + /* send request */ + mmio_setbits_32(ufs_params.reg_base + UTRLDBR, 1 << slot); +} + +static int ufs_check_resp(utp_utrd_t *utrd, int trans_type) +{ + utrd_header_t *hd; + resp_upiu_t *resp; + unsigned int data; + int slot; + + hd = (utrd_header_t *)utrd->header; + resp = (resp_upiu_t *)utrd->resp_upiu; + inv_dcache_range((uintptr_t)hd, UFS_DESC_SIZE); + do { + data = mmio_read_32(ufs_params.reg_base + IS); + if ((data & ~(UFS_INT_UCCS | UFS_INT_UTRCS)) != 0) + return -EIO; + } while ((data & UFS_INT_UTRCS) == 0); + slot = utrd->task_tag - 1; + + data = mmio_read_32(ufs_params.reg_base + UTRLDBR); + assert((data & (1 << slot)) == 0); + assert(hd->ocs == OCS_SUCCESS); + assert((resp->trans_type & TRANS_TYPE_CODE_MASK) == trans_type); + (void)resp; + (void)slot; + return 0; +} + +static void ufs_send_cmd(utp_utrd_t *utrd, uint8_t cmd_op, uint8_t lun, int lba, uintptr_t buf, + size_t length) +{ + int result; + + get_utrd(utrd); + + result = ufs_prepare_cmd(utrd, cmd_op, lun, lba, buf, length); + assert(result == 0); + ufs_send_request(utrd->task_tag); + result = ufs_check_resp(utrd, RESPONSE_UPIU); + assert(result == 0); + (void)result; +} + +#ifdef UFS_RESP_DEBUG +static void dump_upiu(utp_utrd_t *utrd) +{ + utrd_header_t *hd; + int i; + + hd = (utrd_header_t *)utrd->header; + INFO("utrd:0x%x, ruo:0x%x, rul:0x%x, ocs:0x%x, UTRLDBR:0x%x\n", + (unsigned int)(uintptr_t)utrd, hd->ruo, hd->rul, hd->ocs, + mmio_read_32(ufs_params.reg_base + UTRLDBR)); + for (i = 0; i < sizeof(utrd_header_t); i += 4) { + INFO("[%lx]:0x%x\n", + (uintptr_t)utrd->header + i, + *(unsigned int *)((uintptr_t)utrd->header + i)); + } + + for (i = 0; i < sizeof(cmd_upiu_t); i += 4) { + INFO("cmd[%lx]:0x%x\n", + utrd->upiu + i, + *(unsigned int *)(utrd->upiu + i)); + } + for (i = 0; i < sizeof(resp_upiu_t); i += 4) { + INFO("resp[%lx]:0x%x\n", + utrd->resp_upiu + i, + *(unsigned int *)(utrd->resp_upiu + i)); + } + for (i = 0; i < sizeof(prdt_t); i += 4) { + INFO("prdt[%lx]:0x%x\n", + utrd->prdt + i, + *(unsigned int *)(utrd->prdt + i)); + } +} +#endif + +static void ufs_verify_init(void) +{ + utp_utrd_t utrd; + int result; + + get_utrd(&utrd); + ufs_prepare_nop_out(&utrd); + ufs_send_request(utrd.task_tag); + result = ufs_check_resp(&utrd, NOP_IN_UPIU); + assert(result == 0); + (void)result; +} + +static void ufs_verify_ready(void) +{ + utp_utrd_t utrd; + ufs_send_cmd(&utrd, CDBCMD_TEST_UNIT_READY, 0, 0, 0, 0); +} + +static void ufs_query(uint8_t op, uint8_t idn, uint8_t index, uint8_t sel, + uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + query_resp_upiu_t *resp; + int result; + + switch (op) { + case QUERY_READ_FLAG: + case QUERY_READ_ATTR: + case QUERY_READ_DESC: + case QUERY_WRITE_DESC: + case QUERY_WRITE_ATTR: + assert(((buf & 3) == 0) && (size != 0)); + break; + default: + /* Do nothing in default case */ + break; + } + get_utrd(&utrd); + ufs_prepare_query(&utrd, op, idn, index, sel, buf, size); + ufs_send_request(utrd.task_tag); + result = ufs_check_resp(&utrd, QUERY_RESPONSE_UPIU); + assert(result == 0); + resp = (query_resp_upiu_t *)utrd.resp_upiu; +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + assert(resp->query_resp == QUERY_RESP_SUCCESS); + + switch (op) { + case QUERY_READ_FLAG: + *(uint32_t *)buf = (uint32_t)resp->ts.flag.value; + break; + case QUERY_READ_ATTR: + case QUERY_READ_DESC: + memcpy((void *)buf, + (void *)(utrd.resp_upiu + sizeof(query_resp_upiu_t)), + size); + break; + default: + /* Do nothing in default case */ + break; + } + (void)result; +} + +unsigned int ufs_read_attr(int idn) +{ + unsigned int value; + + ufs_query(QUERY_READ_ATTR, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); + return value; +} + +void ufs_write_attr(int idn, unsigned int value) +{ + ufs_query(QUERY_WRITE_ATTR, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); +} + +unsigned int ufs_read_flag(int idn) +{ + unsigned int value; + + ufs_query(QUERY_READ_FLAG, idn, 0, 0, + (uintptr_t)&value, sizeof(value)); + return value; +} + +void ufs_set_flag(int idn) +{ + ufs_query(QUERY_SET_FLAG, idn, 0, 0, 0, 0); +} + +void ufs_clear_flag(int idn) +{ + ufs_query(QUERY_CLEAR_FLAG, idn, 0, 0, 0, 0); +} + +void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size) +{ + ufs_query(QUERY_READ_DESC, idn, index, 0, buf, size); +} + +void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size) +{ + ufs_query(QUERY_WRITE_DESC, idn, index, 0, buf, size); +} + +static void ufs_read_capacity(int lun, unsigned int *num, unsigned int *size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + sense_data_t *sense; + unsigned char data[CACHE_WRITEBACK_GRANULE << 1]; + uintptr_t buf; + int result; + int retry; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE) && + (num != NULL) && (size != NULL)); + + /* align buf address */ + buf = (uintptr_t)data; + buf = (buf + CACHE_WRITEBACK_GRANULE - 1) & + ~(CACHE_WRITEBACK_GRANULE - 1); + memset((void *)buf, 0, CACHE_WRITEBACK_GRANULE); + flush_dcache_range(buf, CACHE_WRITEBACK_GRANULE); + do { + ufs_send_cmd(&utrd, CDBCMD_READ_CAPACITY_10, lun, 0, + buf, READ_CAPACITY_LENGTH); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + retry = 0; + sense = &resp->sd.sense; + if (sense->resp_code == SENSE_DATA_VALID) { + if ((sense->sense_key == SENSE_KEY_UNIT_ATTENTION) && + (sense->asc == 0x29) && (sense->ascq == 0)) { + retry = 1; + } + } + inv_dcache_range(buf, CACHE_WRITEBACK_GRANULE); + /* last logical block address */ + *num = be32toh(*(unsigned int *)buf); + if (*num) + *num += 1; + /* logical block length in bytes */ + *size = be32toh(*(unsigned int *)(buf + 4)); + } while (retry); + (void)result; +} + +size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + int result; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE)); + + ufs_send_cmd(&utrd, CDBCMD_READ_10, lun, lba, buf, size); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + (void)result; + return size - resp->res_trans_cnt; +} + +size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size) +{ + utp_utrd_t utrd; + resp_upiu_t *resp; + int result; + + assert((ufs_params.reg_base != 0) && + (ufs_params.desc_base != 0) && + (ufs_params.desc_size >= UFS_DESC_SIZE)); + + ufs_send_cmd(&utrd, CDBCMD_WRITE_10, lun, lba, buf, size); +#ifdef UFS_RESP_DEBUG + dump_upiu(&utrd); +#endif + resp = (resp_upiu_t *)utrd.resp_upiu; + (void)result; + return size - resp->res_trans_cnt; +} + +static void ufs_enum(void) +{ + unsigned int blk_num, blk_size; + int i; + + ufs_verify_init(); + ufs_verify_ready(); + + ufs_set_flag(FLAG_DEVICE_INIT); + mdelay(200); + /* dump available LUNs */ + for (i = 0; i < UFS_MAX_LUNS; i++) { + ufs_read_capacity(i, &blk_num, &blk_size); + if (blk_num && blk_size) { + INFO("UFS LUN%d contains %d blocks with %d-byte size\n", + i, blk_num, blk_size); + } + } +} + +static void ufs_get_device_info(struct ufs_dev_desc *card_data) +{ + uint8_t desc_buf[DESC_DEVICE_MAX_SIZE]; + + ufs_query(QUERY_READ_DESC, DESC_TYPE_DEVICE, 0, 0, + (uintptr_t)desc_buf, DESC_DEVICE_MAX_SIZE); + + /* + * getting vendor (manufacturerID) and Bank Index in big endian + * format + */ + card_data->wmanufacturerid = (uint16_t)((desc_buf[DEVICE_DESC_PARAM_MANF_ID] << 8) | + (desc_buf[DEVICE_DESC_PARAM_MANF_ID + 1])); +} + +int ufs_init(const ufs_ops_t *ops, ufs_params_t *params) +{ + int result; + unsigned int data; + uic_cmd_t cmd; + struct ufs_dev_desc card = {0}; + + assert((params != NULL) && + (params->reg_base != 0) && + (params->desc_base != 0) && + (params->desc_size >= UFS_DESC_SIZE)); + + memcpy(&ufs_params, params, sizeof(ufs_params_t)); + + /* 0 means 1 slot */ + nutrs = (mmio_read_32(ufs_params.reg_base + CAP) & CAP_NUTRS_MASK) + 1; + if (nutrs > (ufs_params.desc_size / UFS_DESC_SIZE)) { + nutrs = ufs_params.desc_size / UFS_DESC_SIZE; + } + + + if (ufs_params.flags & UFS_FLAGS_SKIPINIT) { + result = ufshc_dme_get(0x1571, 0, &data); + assert(result == 0); + result = ufshc_dme_get(0x41, 0, &data); + assert(result == 0); + if (data == 1) { + /* prepare to exit hibernate mode */ + memset(&cmd, 0, sizeof(uic_cmd_t)); + cmd.op = DME_HIBERNATE_EXIT; + result = ufshc_send_uic_cmd(ufs_params.reg_base, + &cmd); + assert(result == 0); + data = mmio_read_32(ufs_params.reg_base + UCMDARG2); + assert(data == 0); + do { + data = mmio_read_32(ufs_params.reg_base + IS); + } while ((data & UFS_INT_UHXS) == 0); + mmio_write_32(ufs_params.reg_base + IS, UFS_INT_UHXS); + data = mmio_read_32(ufs_params.reg_base + HCS); + assert((data & HCS_UPMCRS_MASK) == HCS_PWR_LOCAL); + } + result = ufshc_dme_get(0x1568, 0, &data); + assert(result == 0); + assert((data > 0) && (data <= 3)); + } else { + assert((ops != NULL) && (ops->phy_init != NULL) && + (ops->phy_set_pwr_mode != NULL)); + + result = ufshc_reset(ufs_params.reg_base); + assert(result == 0); + ops->phy_init(&ufs_params); + result = ufshc_link_startup(ufs_params.reg_base); + assert(result == 0); + + ufs_enum(); + + ufs_get_device_info(&card); + if (card.wmanufacturerid == UFS_VENDOR_SKHYNIX) { + ufs_params.flags |= UFS_FLAGS_VENDOR_SKHYNIX; + } + + ops->phy_set_pwr_mode(&ufs_params); + } + + (void)result; + return 0; +} diff --git a/arm-trusted-firmware/drivers/usb/usb_device.c b/arm-trusted-firmware/drivers/usb/usb_device.c new file mode 100644 index 0000000..701f301 --- /dev/null +++ b/arm-trusted-firmware/drivers/usb/usb_device.c @@ -0,0 +1,845 @@ +/* + * Copyright (c) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* Define for EP address */ +#define EP_DIR_MASK BIT(7) +#define EP_DIR_IN BIT(7) +#define EP_NUM_MASK GENMASK(3, 0) + +#define EP0_IN (0U | EP_DIR_IN) +#define EP0_OUT 0U + +/* USB address between 1 through 127 = 0x7F mask */ +#define ADDRESS_MASK GENMASK(6, 0) + +/* + * Set a STALL condition over an endpoint + * pdev: USB handle + * ep_addr: endpoint address + * return : status + */ +static enum usb_status usb_core_set_stall(struct usb_handle *pdev, uint8_t ep_addr) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + if ((EP_DIR_MASK & ep_addr) == EP_DIR_IN) { + ep = &hpcd->in_ep[num]; + ep->is_in = true; + } else { + ep = &hpcd->out_ep[num]; + ep->is_in = false; + } + ep->num = num; + + pdev->driver->ep_set_stall(hpcd->instance, ep); + if (num == 0U) { + pdev->driver->ep0_out_start(hpcd->instance); + } + + return USBD_OK; +} + +/* + * usb_core_get_desc + * Handle Get Descriptor requests + * pdev : device instance + * req : usb request + */ +static void usb_core_get_desc(struct usb_handle *pdev, struct usb_setup_req *req) +{ + uint16_t len; + uint8_t *pbuf; + uint8_t desc_type = HIBYTE(req->value); + uint8_t desc_idx = LOBYTE(req->value); + + switch (desc_type) { + case USB_DESC_TYPE_DEVICE: + pbuf = pdev->desc->get_device_desc(&len); + break; + + case USB_DESC_TYPE_CONFIGURATION: + pbuf = pdev->desc->get_config_desc(&len); + break; + + case USB_DESC_TYPE_STRING: + switch (desc_idx) { + case USBD_IDX_LANGID_STR: + pbuf = pdev->desc->get_lang_id_desc(&len); + break; + + case USBD_IDX_MFC_STR: + pbuf = pdev->desc->get_manufacturer_desc(&len); + break; + + case USBD_IDX_PRODUCT_STR: + pbuf = pdev->desc->get_product_desc(&len); + break; + + case USBD_IDX_SERIAL_STR: + pbuf = pdev->desc->get_serial_desc(&len); + break; + + case USBD_IDX_CONFIG_STR: + pbuf = pdev->desc->get_configuration_desc(&len); + break; + + case USBD_IDX_INTERFACE_STR: + pbuf = pdev->desc->get_interface_desc(&len); + break; + + /* For all USER string */ + case USBD_IDX_USER0_STR: + default: + pbuf = pdev->desc->get_usr_desc(desc_idx - USBD_IDX_USER0_STR, &len); + break; + } + break; + + case USB_DESC_TYPE_DEVICE_QUALIFIER: + pbuf = pdev->desc->get_device_qualifier_desc(&len); + break; + + case USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION: + if (pdev->desc->get_other_speed_config_desc == NULL) { + usb_core_ctl_error(pdev); + return; + } + pbuf = pdev->desc->get_other_speed_config_desc(&len); + break; + + default: + ERROR("Unknown request %i\n", desc_type); + usb_core_ctl_error(pdev); + return; + } + + if ((len != 0U) && (req->length != 0U)) { + len = MIN(len, req->length); + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, pbuf, len); + } +} + +/* + * usb_core_set_config + * Handle Set device configuration request + * pdev : device instance + * req : usb request + */ +static void usb_core_set_config(struct usb_handle *pdev, struct usb_setup_req *req) +{ + static uint8_t cfgidx; + + cfgidx = LOBYTE(req->value); + + if (cfgidx > USBD_MAX_NUM_CONFIGURATION) { + usb_core_ctl_error(pdev); + return; + } + + switch (pdev->dev_state) { + case USBD_STATE_ADDRESSED: + if (cfgidx != 0U) { + pdev->dev_config = cfgidx; + pdev->dev_state = USBD_STATE_CONFIGURED; + if (!pdev->class) { + usb_core_ctl_error(pdev); + return; + } + /* Set configuration and Start the Class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + case USBD_STATE_CONFIGURED: + if (cfgidx == 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + pdev->dev_config = cfgidx; + pdev->class->de_init(pdev, cfgidx); + } else if (cfgidx != pdev->dev_config) { + if (pdev->class == NULL) { + usb_core_ctl_error(pdev); + return; + } + /* Clear old configuration */ + pdev->class->de_init(pdev, pdev->dev_config); + /* Set new configuration */ + pdev->dev_config = cfgidx; + /* Set configuration and start the USB class */ + if (pdev->class->init(pdev, cfgidx) != 0U) { + usb_core_ctl_error(pdev); + return; + } + } + break; + + default: + usb_core_ctl_error(pdev); + return; + } + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); +} + +/* + * usb_core_get_status + * Handle Get Status request + * pdev : device instance + * req : usb request + */ +static void usb_core_get_status(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if ((pdev->dev_state != USBD_STATE_ADDRESSED) && + (pdev->dev_state != USBD_STATE_CONFIGURED)) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_config_status = USB_CONFIG_SELF_POWERED; + + if (pdev->dev_remote_wakeup != 0U) { + pdev->dev_config_status |= USB_CONFIG_REMOTE_WAKEUP; + } + + /* Start the transfer */ + usb_core_transmit_ep0(pdev, (uint8_t *)&pdev->dev_config_status, 2U); +} + +/* + * usb_core_set_address + * Set device address + * pdev : device instance + * req : usb request + */ +static void usb_core_set_address(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + uint8_t dev_addr; + + if ((req->index != 0U) || (req->length != 0U)) { + usb_core_ctl_error(pdev); + return; + } + + dev_addr = req->value & ADDRESS_MASK; + if (pdev->dev_state != USBD_STATE_DEFAULT) { + usb_core_ctl_error(pdev); + return; + } + + pdev->dev_address = dev_addr; + pdev->driver->set_address(((struct pcd_handle *)(pdev->data))->instance, dev_addr); + + /* Send status */ + usb_core_transmit_ep0(pdev, NULL, 0U); + + if (dev_addr != 0U) { + pdev->dev_state = USBD_STATE_ADDRESSED; + } else { + pdev->dev_state = USBD_STATE_DEFAULT; + } +} + +/* + * usb_core_dev_req + * Handle standard usb device requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_dev_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + VERBOSE("receive request %i\n", req->b_request); + switch (req->b_request) { + case USB_REQ_GET_DESCRIPTOR: + usb_core_get_desc(pdev, req); + break; + + case USB_REQ_SET_CONFIGURATION: + usb_core_set_config(pdev, req); + break; + + case USB_REQ_GET_STATUS: + usb_core_get_status(pdev, req); + break; + + case USB_REQ_SET_ADDRESS: + usb_core_set_address(pdev, req); + break; + + case USB_REQ_GET_CONFIGURATION: + case USB_REQ_SET_FEATURE: + case USB_REQ_CLEAR_FEATURE: + default: + ERROR("NOT SUPPORTED %i\n", req->b_request); + usb_core_ctl_error(pdev); + break; + } + + return USBD_OK; +} + +/* + * usb_core_itf_req + * Handle standard usb interface requests + * pdev : device instance + * req : usb request + * return : status + */ +static enum usb_status usb_core_itf_req(struct usb_handle *pdev, + struct usb_setup_req *req) +{ + if (pdev->dev_state != USBD_STATE_CONFIGURED) { + usb_core_ctl_error(pdev); + return USBD_OK; + } + + if (LOBYTE(req->index) <= USBD_MAX_NUM_INTERFACES) { + pdev->class->setup(pdev, req); + + if (req->length == 0U) { + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } else { + usb_core_ctl_error(pdev); + } + + return USBD_OK; +} + +/* + * usb_core_setup_stage + * Handle the setup stage + * pdev: device instance + * psetup : setup buffer + * return : status + */ +static enum usb_status usb_core_setup_stage(struct usb_handle *pdev, + uint8_t *psetup) +{ + struct usb_setup_req *req = &pdev->request; + + /* Copy setup buffer into req structure */ + req->bm_request = psetup[0]; + req->b_request = psetup[1]; + req->value = psetup[2] + (psetup[3] << 8); + req->index = psetup[4] + (psetup[5] << 8); + req->length = psetup[6] + (psetup[7] << 8); + + pdev->ep0_state = USBD_EP0_SETUP; + pdev->ep0_data_len = pdev->request.length; + + switch (pdev->request.bm_request & USB_REQ_RECIPIENT_MASK) { + case USB_REQ_RECIPIENT_DEVICE: + usb_core_dev_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_INTERFACE: + usb_core_itf_req(pdev, &pdev->request); + break; + + case USB_REQ_RECIPIENT_ENDPOINT: + default: + ERROR("receive unsupported request %u", + pdev->request.bm_request & USB_REQ_RECIPIENT_MASK); + usb_core_set_stall(pdev, pdev->request.bm_request & USB_REQ_DIRECTION); + return USBD_FAIL; + } + + return USBD_OK; +} + +/* + * usb_core_data_out + * Handle data OUT stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to sent + * return : status + */ +static enum usb_status usb_core_data_out(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + struct usb_endpoint *pep; + + if (epnum == 0U) { + pep = &pdev->ep_out[0]; + if (pdev->ep0_state == USBD_EP0_DATA_OUT) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_receive(pdev, 0U, pdata, + MIN(pep->rem_length, + pep->maxpacket)); + } else { + if (pdev->class->ep0_rx_ready && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->ep0_rx_ready(pdev); + } + + usb_core_transmit_ep0(pdev, NULL, 0U); + } + } + } else if (pdev->class->data_out != NULL && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_out(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_data_in + * Handle data in stage + * pdev: device instance + * epnum: endpoint index + * pdata: buffer to fill + * return : status + */ +static enum usb_status usb_core_data_in(struct usb_handle *pdev, uint8_t epnum, + uint8_t *pdata) +{ + if (epnum == 0U) { + struct usb_endpoint *pep = &pdev->ep_in[0]; + + if (pdev->ep0_state == USBD_EP0_DATA_IN) { + if (pep->rem_length > pep->maxpacket) { + pep->rem_length -= pep->maxpacket; + + usb_core_transmit(pdev, 0U, pdata, + pep->rem_length); + + /* Prepare EP for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + /* Last packet is MPS multiple, send ZLP packet */ + if ((pep->total_length % pep->maxpacket == 0U) && + (pep->total_length >= pep->maxpacket) && + (pep->total_length < pdev->ep0_data_len)) { + usb_core_transmit(pdev, 0U, NULL, 0U); + + pdev->ep0_data_len = 0U; + + /* Prepare endpoint for premature end of transfer */ + usb_core_receive(pdev, 0U, NULL, 0U); + } else { + if (pdev->class->ep0_tx_sent != NULL && + (pdev->dev_state == + USBD_STATE_CONFIGURED)) { + pdev->class->ep0_tx_sent(pdev); + } + /* Start the transfer */ + usb_core_receive_ep0(pdev, NULL, 0U); + } + } + } + } else if ((pdev->class->data_in != NULL) && + (pdev->dev_state == USBD_STATE_CONFIGURED)) { + pdev->class->data_in(pdev, epnum); + } + + return USBD_OK; +} + +/* + * usb_core_suspend + * Handle suspend event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_suspend(struct usb_handle *pdev) +{ + INFO("USB Suspend mode\n"); + pdev->dev_old_state = pdev->dev_state; + pdev->dev_state = USBD_STATE_SUSPENDED; + + return USBD_OK; +} + +/* + * usb_core_resume + * Handle resume event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_resume(struct usb_handle *pdev) +{ + INFO("USB Resume\n"); + pdev->dev_state = pdev->dev_old_state; + + return USBD_OK; +} + +/* + * usb_core_sof + * Handle SOF event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_sof(struct usb_handle *pdev) +{ + if (pdev->dev_state == USBD_STATE_CONFIGURED) { + if (pdev->class->sof != NULL) { + pdev->class->sof(pdev); + } + } + + return USBD_OK; +} + +/* + * usb_core_disconnect + * Handle device disconnection event + * pdev : device instance + * return : status + */ +static enum usb_status usb_core_disconnect(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->class->de_init(pdev, pdev->dev_config); + + return USBD_OK; +} + +enum usb_status usb_core_handle_it(struct usb_handle *pdev) +{ + uint32_t param = 0U; + uint32_t len = 0U; + struct usbd_ep *ep; + + switch (pdev->driver->it_handler(pdev->data->instance, ¶m)) { + case USB_DATA_OUT: + usb_core_data_out(pdev, param, + pdev->data->out_ep[param].xfer_buff); + break; + + case USB_DATA_IN: + usb_core_data_in(pdev, param, + pdev->data->in_ep[param].xfer_buff); + break; + + case USB_SETUP: + usb_core_setup_stage(pdev, (uint8_t *)pdev->data->setup); + break; + + case USB_ENUM_DONE: + break; + + case USB_READ_DATA_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> USBD_OUT_COUNT_SHIFT; + pdev->driver->read_packet(pdev->data->instance, + ep->xfer_buff, len); + ep->xfer_buff += len; + ep->xfer_count += len; + break; + + case USB_READ_SETUP_PACKET: + ep = &pdev->data->out_ep[param & USBD_OUT_EPNUM_MASK]; + len = (param & USBD_OUT_COUNT_MASK) >> 0x10; + pdev->driver->read_packet(pdev->data->instance, + (uint8_t *)pdev->data->setup, 8); + ep->xfer_count += len; + break; + + case USB_RESET: + pdev->dev_state = USBD_STATE_DEFAULT; + break; + + case USB_RESUME: + if (pdev->data->lpm_state == LPM_L1) { + pdev->data->lpm_state = LPM_L0; + } else { + usb_core_resume(pdev); + } + break; + + case USB_SUSPEND: + usb_core_suspend(pdev); + break; + + case USB_LPM: + if (pdev->data->lpm_state == LPM_L0) { + pdev->data->lpm_state = LPM_L1; + } else { + usb_core_suspend(pdev); + } + break; + + case USB_SOF: + usb_core_sof(pdev); + break; + + case USB_DISCONNECT: + usb_core_disconnect(pdev); + break; + + case USB_WRITE_EMPTY: + pdev->driver->write_empty_tx_fifo(pdev->data->instance, param, + pdev->data->in_ep[param].xfer_len, + (uint32_t *)&pdev->data->in_ep[param].xfer_count, + pdev->data->in_ep[param].maxpacket, + &pdev->data->in_ep[param].xfer_buff); + break; + + case USB_NOTHING: + default: + break; + } + + return USBD_OK; +} + +static void usb_core_start_xfer(struct usb_handle *pdev, + void *handle, + struct usbd_ep *ep) +{ + if (ep->num == 0U) { + pdev->driver->ep0_start_xfer(handle, ep); + } else { + pdev->driver->ep_start_xfer(handle, ep); + } +} + +/* + * usb_core_receive + * Receive an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->out_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = false; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_transmit + * Send an amount of data + * pdev: USB handle + * ep_addr: endpoint address + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *buf, uint32_t len) +{ + struct usbd_ep *ep; + struct pcd_handle *hpcd = (struct pcd_handle *)pdev->data; + uint8_t num; + + num = ep_addr & EP_NUM_MASK; + if (num >= USBD_EP_NB) { + return USBD_FAIL; + } + ep = &hpcd->in_ep[num]; + + /* Setup and start the Xfer */ + ep->xfer_buff = buf; + ep->xfer_len = len; + ep->xfer_count = 0U; + ep->is_in = true; + ep->num = num; + + usb_core_start_xfer(pdev, hpcd->instance, ep); + + return USBD_OK; +} + +/* + * usb_core_receive_ep0 + * Receive an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the reception buffer + * len: amount of data to be received + * return : status + */ +enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Prepare the reception of the buffer over EP0 */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_OUT; + } else { + pdev->ep0_state = USBD_EP0_STATUS_OUT; + } + + pdev->ep_out[0].total_length = len; + pdev->ep_out[0].rem_length = len; + + /* Start the transfer */ + return usb_core_receive(pdev, 0U, buf, len); +} + +/* + * usb_core_transmit_ep0 + * Send an amount of data on ep0 + * pdev: USB handle + * buf: pointer to the transmission buffer + * len: amount of data to be sent + * return : status + */ +enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *buf, + uint32_t len) +{ + /* Set EP0 State */ + if (len != 0U) { + pdev->ep0_state = USBD_EP0_DATA_IN; + } else { + pdev->ep0_state = USBD_EP0_STATUS_IN; + } + + pdev->ep_in[0].total_length = len; + pdev->ep_in[0].rem_length = len; + + /* Start the transfer */ + return usb_core_transmit(pdev, 0U, buf, len); +} + +/* + * usb_core_ctl_error + * Handle USB low level error + * pdev: device instance + * req: usb request + * return : None + */ + +void usb_core_ctl_error(struct usb_handle *pdev) +{ + ERROR("%s : Send an ERROR\n", __func__); + usb_core_set_stall(pdev, EP0_IN); + usb_core_set_stall(pdev, EP0_OUT); +} + +/* + * usb_core_start + * Start the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_start(struct usb_handle *pdev) +{ + /* Start the low level driver */ + pdev->driver->start_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * usb_core_stop + * Stop the USB device core. + * pdev: Device Handle + * return : USBD Status + */ +enum usb_status usb_core_stop(struct usb_handle *pdev) +{ + /* Free class resources */ + pdev->class->de_init(pdev, pdev->dev_config); + + /* Stop the low level driver */ + pdev->driver->stop_device(pdev->data->instance); + + return USBD_OK; +} + +/* + * register_usb_driver + * Stop the USB device core. + * pdev: Device Handle + * pcd_handle: PCD handle + * driver: USB driver + * driver_handle: USB driver handle + * return : USBD Status + */ +enum usb_status register_usb_driver(struct usb_handle *pdev, + struct pcd_handle *pcd_handle, + const struct usb_driver *driver, + void *driver_handle) +{ + uint8_t i; + + assert(pdev != NULL); + assert(pcd_handle != NULL); + assert(driver != NULL); + assert(driver_handle != NULL); + + /* Free class resources */ + pdev->driver = driver; + pdev->data = pcd_handle; + pdev->data->instance = driver_handle; + pdev->dev_state = USBD_STATE_DEFAULT; + pdev->ep0_state = USBD_EP0_IDLE; + + /* Copy endpoint information */ + for (i = 0U; i < USBD_EP_NB; i++) { + pdev->ep_in[i].maxpacket = pdev->data->in_ep[i].maxpacket; + pdev->ep_out[i].maxpacket = pdev->data->out_ep[i].maxpacket; + } + + return USBD_OK; +} + +/* + * register_platform + * Register the USB device core. + * pdev: Device Handle + * plat_call_back: callback + * return : USBD Status + */ +enum usb_status register_platform(struct usb_handle *pdev, + const struct usb_desc *plat_call_back) +{ + assert(pdev != NULL); + assert(plat_call_back != NULL); + + /* Save platform info in class resources */ + pdev->desc = plat_call_back; + + return USBD_OK; +} diff --git a/arm-trusted-firmware/fdts/a5ds.dts b/arm-trusted-firmware/fdts/a5ds.dts new file mode 100644 index 0000000..c6f5be6 --- /dev/null +++ b/arm-trusted-firmware/fdts/a5ds.dts @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "A5DS"; + compatible = "arm,A5DS"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_on = <0x84000003>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + enable-method = "psci"; + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + next-level-cache = <&L2>; + }; + cpu@1 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <1>; + next-level-cache = <&L2>; + }; + cpu@2 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <2>; + next-level-cache = <&L2>; + }; + cpu@3 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <3>; + next-level-cache = <&L2>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x7F000000>; + }; + + L2: cache-controller@1C010000 { + compatible = "arm,pl310-cache"; + reg = <0x1C010000 0x1000>; + interrupts = <0 84 4>; + cache-level = <2>; + cache-unified; + arm,data-latency = <1 1 1>; + arm,tag-latency = <1 1 1>; + }; + + refclk7500khz: refclk7500khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <7500000>; + clock-output-names = "apb_pclk"; + }; + + refclk24mhz: refclk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "apb_pclk"; + }; + + smbclk: refclk24mhzx2 { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + + rtc@1a220000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x1a220000 0x1000>; + clocks = <&refclk24mhz>; + interrupts = <0 6 0xf04>; + clock-names = "apb_pclk"; + }; + + gic: interrupt-controller@1c001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1c001000 0x1000>, + <0x1c000100 0x100>; + interrupts = <1 9 0xf04>; + }; + + serial0: uart@1a200000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a200000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 8 0xf04>; + clocks = <&refclk7500khz>; + clock-names = "apb_pclk"; + }; + + serial1: uart@1a210000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a210000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 9 0xf04>; + clocks = <&refclk7500khz>; + clock-names = "apb_pclk"; + }; + + timer0: timer@1a040000 { + compatible = "arm,armv7-timer-mem"; + #address-cells = <1>; + #size-cells = <1>; + ranges; + reg = <0x1a040000 0x1000>; + clock-frequency = <7500000>; + + frame@1a050000 { + frame-number = <0>; + interrupts = <0 2 0xf04>; + reg = <0x1a050000 0x1000>; + }; + }; + v2m_fixed_3v3: fixed-regulator-0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + ethernet@4020000 { + compatible = "smsc,lan9220", "smsc,lan9115"; + reg = <0x40200000 0x10000>; + interrupt-parent = <&gic>; + interrupts = <0 43 0xf04>; + reg-io-width = <4>; + phy-mode = "mii"; + smsc,irq-active-high; + vdd33a-supply = <&v2m_fixed_3v3>; + vddvario-supply = <&v2m_fixed_3v3>; + }; +}; diff --git a/arm-trusted-firmware/fdts/arm_fpga.dts b/arm-trusted-firmware/fdts/arm_fpga.dts new file mode 100644 index 0000000..c0efd09 --- /dev/null +++ b/arm-trusted-firmware/fdts/arm_fpga.dts @@ -0,0 +1,108 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * Devicetree for the Arm Ltd. FPGA platform + * Number and kind of CPU cores differs from image to image, so the + * topology is auto-detected by BL31, and the /cpus node is created and + * populated accordingly at runtime. + */ + +#include + +/dts-v1/; + +/ { + model = "ARM FPGA"; + compatible = "arm,fpga", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &dbg_uart; + }; + + chosen { + stdout-path = "serial0:38400n8"; + bootargs = "console=ttyAMA0,38400n8 earlycon"; + /* Allow to upload a generous 100MB initrd payload. */ + linux,initrd-start = <0x0 0x84000000>; + linux,initrd-end = <0x0 0x8a400000>; + }; + + /* /cpus node will be added by BL31 at runtime. */ + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + /* This node will be removed at runtime on cores without SPE. */ + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x0 0x80000000 0x0 0x80000000>, + <0x8 0x80000000 0x1 0x80000000>; + }; + + + bus_refclk: refclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + uartclk: baudclock { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <10000000>; + clock-output-names = "uartclk"; + }; + + dbg_uart: serial@7ff80000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x7ff80000 0x0 0x00001000>; + interrupts = ; + clocks = <&uartclk>, <&bus_refclk>; + clock-names = "uartclk", "apb_pclk"; + }; + + gic: interrupt-controller@30000000 { + compatible = "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0x0 0x00010000>, /* GICD */ + /* The GICR size will be adjusted at runtime to match the cores. */ + <0x0 0x30040000 0x0 0x00020000>; /* GICR for one core */ + interrupts = ; + + its: msi-controller@30040000 { + compatible = "arm,gic-v3-its"; + reg = <0x0 0x30040000 0x0 0x40000>; + #msi-cells = <1>; + msi-controller; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/corstone700.dtsi b/arm-trusted-firmware/fdts/corstone700.dtsi new file mode 100644 index 0000000..2372207 --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700.dtsi @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/ { + compatible = "arm,Corstone-700"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + chosen { }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0>; + next-level-cache = <&L2_0>; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x80000000>; + }; + + gic: interrupt-controller@1c000000 { + compatible = "arm,gic-400"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x1c010000 0x1000>, + <0x1c02f000 0x2000>, + <0x1c04f000 0x1000>, + <0x1c06f000 0x2000>; + interrupts = <1 9 0xf08>; + }; + + L2_0: l2-cache0 { + compatible = "cache"; + }; + + refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + uartclk: uartclk { + /* UART clock - 32MHz */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32000000>; + clock-output-names = "uartclk"; + }; + + serial0: uart@1a510000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a510000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 19 4>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + serial1: uart@1a520000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x1a520000 0x1000>; + interrupt-parent = <&gic>; + interrupts = <0 20 4>; + clocks = <&uartclk>, <&refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <1 13 0xf08>, + <1 14 0xf08>, + <1 11 0xf08>, + <1 10 0xf08>; + }; + + refclk: refclk@1a220000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x1a220000 0x1000>; + #address-cells = <1>; + #size-cells = <1>; + ranges; + + frame@1a230000 { + frame-number = <0>; + interrupts = <0 2 0xf04>; + reg = <0x1a230000 0x1000>; + }; + }; + + mbox_es0mhu0: mhu@1b000000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b000000 0x1000>, + <0x1b010000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 12 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-es0-mhu0"; + }; + + mbox_es0mhu1: mhu@1b020000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b020000 0x1000>, + <0x1b030000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 47 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-es0-mhu1"; + }; + + mbox_semhu1: mhu@1b820000 { + compatible = "arm,mhuv2","arm,primecell"; + reg = <0x1b820000 0x1000>, + <0x1b830000 0x1000>; + clocks = <&refclk100mhz>; + clock-names = "apb_pclk"; + interrupts = <0 45 4>; + interrupt-names = "mhu_rx"; + #mbox-cells = <1>; + mbox-name = "arm-se-mhu1"; + }; + + client { + compatible = "arm,client"; + mboxes = <&mbox_es0mhu0 0>, <&mbox_es0mhu1 0>, <&mbox_semhu1 0>; + mbox-names = "es0mhu0", "es0mhu1", "semhu1"; + }; + + extsys0: extsys@1A010310 { + compatible = "arm,extsys_ctrl"; + reg = <0x1A010310 0x4>, + <0x1A010314 0x4>; + reg-names = "rstreg", "streg"; + }; +}; diff --git a/arm-trusted-firmware/fdts/corstone700_fpga.dts b/arm-trusted-firmware/fdts/corstone700_fpga.dts new file mode 100644 index 0000000..1ac0d4b --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700_fpga.dts @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "corstone700.dtsi" + +/ { + model = "corstone700-fpga"; + + ethernet: eth@40100000 { + compatible = "smsc,lan9115"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupt-parent = <&gic>; + interrupts = ; + reg-io-width = <2>; + smsc,irq-push-pull; + }; + + usb: usb@4020000 { + compatible = "nxp,usb-isp1763"; + reg = <0x40200000 0x100000>; + interrupt-parent = <&gic>; + interrupts = ; + }; +}; + +&refclk { + clock-frequency = <32000000>; +}; diff --git a/arm-trusted-firmware/fdts/corstone700_fvp.dts b/arm-trusted-firmware/fdts/corstone700_fvp.dts new file mode 100644 index 0000000..3b1202d --- /dev/null +++ b/arm-trusted-firmware/fdts/corstone700_fvp.dts @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "corstone700.dtsi" + +/ { + model = "corstone700-fvp"; + + /* + * Intel StrataFlash J3 NOR flash: 2 x 16-bit interleaved components + * Flash total size: 32 MB + * Allocated flash space: 8 MB + */ + + flash@8500000 { + compatible = "cfi-flash"; + reg = <0x8500000 0x800000>; + bank-width = <4>; + device-width= <2>; + }; + + ethernet: eth@4010000 { + compatible = "smsc,lan91c111"; + reg = <0x40100000 0x10000>; + phy-mode = "mii"; + interrupt-parent = <&gic>; + interrupts = ; + reg-io-width = <2>; + smsc,irq-push-pull; + }; +}; + +&refclk { + clock-frequency = <50000000>; +}; diff --git a/arm-trusted-firmware/fdts/cot_descriptors.dtsi b/arm-trusted-firmware/fdts/cot_descriptors.dtsi new file mode 100644 index 0000000..411bae6 --- /dev/null +++ b/arm-trusted-firmware/fdts/cot_descriptors.dtsi @@ -0,0 +1,320 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +cot { + manifests { + compatible = "arm, cert-descs"; + + trusted_boot_fw_cert: trusted_boot_fw_cert { + root-certificate; + image-id =; + antirollback-counter = <&trusted_nv_counter>; + + tb_fw_hash: tb_fw_hash { + oid = TRUSTED_BOOT_FW_HASH_OID; + }; + tb_fw_config_hash: tb_fw_config_hash { + oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID; + }; + hw_config_hash: hw_config_hash { + oid = HW_CONFIG_HASH_OID; + }; + fw_config_hash: fw_config_hash { + oid = FW_CONFIG_HASH_OID; + }; + }; + + trusted_key_cert: trusted_key_cert { + root-certificate; + image-id = ; + antirollback-counter = <&trusted_nv_counter>; + + trusted_world_pk: trusted_world_pk { + oid = TRUSTED_WORLD_PK_OID; + }; + non_trusted_world_pk: non_trusted_world_pk { + oid = NON_TRUSTED_WORLD_PK_OID; + }; + }; + + scp_fw_key_cert: scp_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_content_pk: scp_fw_content_pk { + oid = SCP_FW_CONTENT_CERT_PK_OID; + }; + }; + + scp_fw_content_cert: scp_fw_content_cert { + image-id = ; + parent = <&scp_fw_key_cert>; + signing-key = <&scp_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + scp_fw_hash: scp_fw_hash { + oid = SCP_FW_HASH_OID; + }; + }; + + soc_fw_key_cert: soc_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + soc_fw_content_pk: soc_fw_content_pk { + oid = SOC_FW_CONTENT_CERT_PK_OID; + }; + }; + + soc_fw_content_cert: soc_fw_content_cert { + image-id = ; + parent = <&soc_fw_key_cert>; + signing-key = <&soc_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + soc_fw_hash: soc_fw_hash { + oid = SOC_AP_FW_HASH_OID; + }; + soc_fw_config_hash: soc_fw_config_hash { + oid = SOC_FW_CONFIG_HASH_OID; + }; + }; + + trusted_os_fw_key_cert: trusted_os_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + tos_fw_content_pk: tos_fw_content_pk { + oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID; + }; + }; + + trusted_os_fw_content_cert: trusted_os_fw_content_cert { + image-id = ; + parent = <&trusted_os_fw_key_cert>; + signing-key = <&tos_fw_content_pk>; + antirollback-counter = <&trusted_nv_counter>; + + tos_fw_hash: tos_fw_hash { + oid = TRUSTED_OS_FW_HASH_OID; + }; + tos_fw_extra1_hash: tos_fw_extra1_hash { + oid = TRUSTED_OS_FW_EXTRA1_HASH_OID; + }; + tos_fw_extra2_hash: tos_fw_extra2_hash { + oid = TRUSTED_OS_FW_EXTRA2_HASH_OID; + }; + tos_fw_config_hash: tos_fw_config_hash { + oid = TRUSTED_OS_FW_CONFIG_HASH_OID; + }; + }; + + non_trusted_fw_key_cert: non_trusted_fw_key_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&non_trusted_world_pk>; + antirollback-counter = <&non_trusted_nv_counter>; + + nt_fw_content_pk: nt_fw_content_pk { + oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID; + }; + }; + + non_trusted_fw_content_cert: non_trusted_fw_content_cert { + image-id = ; + parent = <&non_trusted_fw_key_cert>; + signing-key = <&nt_fw_content_pk>; + antirollback-counter = <&non_trusted_nv_counter>; + + nt_world_bl_hash: nt_world_bl_hash { + oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID; + }; + nt_fw_config_hash: nt_fw_config_hash { + oid = NON_TRUSTED_FW_CONFIG_HASH_OID; + }; + }; + +#if defined(SPD_spmd) + sip_sp_content_cert: sip_sp_content_cert { + image-id = ; + parent = <&trusted_key_cert>; + signing-key = <&trusted_world_pk>; + antirollback-counter = <&trusted_nv_counter>; + + sp_pkg1_hash: sp_pkg1_hash { + oid = SP_PKG1_HASH_OID; + }; + sp_pkg2_hash: sp_pkg2_hash { + oid = SP_PKG2_HASH_OID; + }; + sp_pkg3_hash: sp_pkg3_hash { + oid = SP_PKG3_HASH_OID; + }; + sp_pkg4_hash: sp_pkg4_hash { + oid = SP_PKG4_HASH_OID; + }; + sp_pkg5_hash: sp_pkg5_hash { + oid = SP_PKG5_HASH_OID; + }; + sp_pkg6_hash: sp_pkg6_hash { + oid = SP_PKG6_HASH_OID; + }; + sp_pkg7_hash: sp_pkg7_hash { + oid = SP_PKG7_HASH_OID; + }; + sp_pkg8_hash: sp_pkg8_hash { + oid = SP_PKG8_HASH_OID; + }; + }; +#endif + }; + + images { + compatible = "arm, img-descs"; + + hw_config { + image-id = ; + parent = <&trusted_boot_fw_cert>; + hash = <&hw_config_hash>; + }; + + tb_fw_config { + image-id = ; + parent = <&trusted_boot_fw_cert>; + hash = <&tb_fw_config_hash>; + }; + + scp_bl2_image { + image-id = ; + parent = <&scp_fw_content_cert>; + hash = <&scp_fw_hash>; + }; + + bl31_image { + image-id = ; + parent = <&soc_fw_content_cert>; + hash = <&soc_fw_hash>; + }; + + soc_fw_config { + image-id = ; + parent = <&soc_fw_content_cert>; + hash = <&soc_fw_config_hash>; + }; + + bl32_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_hash>; + }; + + bl32_extra1_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_extra1_hash>; + }; + + bl32_extra2_image { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_extra2_hash>; + }; + + tos_fw_config { + image-id = ; + parent = <&trusted_os_fw_content_cert>; + hash = <&tos_fw_config_hash>; + }; + + bl33_image { + image-id = ; + parent = <&non_trusted_fw_content_cert>; + hash = <&nt_world_bl_hash>; + }; + + nt_fw_config { + image-id = ; + parent = <&non_trusted_fw_content_cert>; + hash = <&nt_fw_config_hash>; + }; + +#if defined(SPD_spmd) + sp_pkg1 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg1_hash>; + }; + + sp_pkg2 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg2_hash>; + }; + + sp_pkg3 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg3_hash>; + }; + + sp_pkg4 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg4_hash>; + }; + + sp_pkg5 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg5_hash>; + }; + + sp_pkg6 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg6_hash>; + }; + + sp_pkg7 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg7_hash>; + }; + + sp_pkg8 { + image-id = ; + parent = <&sip_sp_content_cert>; + hash = <&sp_pkg8_hash>; + }; +#endif + }; +}; + +non_volatile_counters: non_volatile_counters { + compatible = "arm, non-volatile-counter"; + + #address-cells = <1>; + #size-cells = <0>; + + trusted_nv_counter: trusted_nv_counter { + id = ; + oid = TRUSTED_FW_NVCOUNTER_OID; + }; + + non_trusted_nv_counter: non_trusted_nv_counter { + id = ; + oid = NON_TRUSTED_FW_NVCOUNTER_OID; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts new file mode 100644 index 0000000..3a921f4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts @@ -0,0 +1,220 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define REG_32 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 6 &gic 0 6 4>, + <0 0 7 &gic 0 7 4>, + <0 0 8 &gic 0 8 4>, + <0 0 9 &gic 0 9 4>, + <0 0 10 &gic 0 10 4>, + <0 0 11 &gic 0 11 4>, + <0 0 12 &gic 0 12 4>, + <0 0 13 &gic 0 13 4>, + <0 0 14 &gic 0 14 4>, + <0 0 15 &gic 0 15 4>, + <0 0 16 &gic 0 16 4>, + <0 0 17 &gic 0 17 4>, + <0 0 18 &gic 0 18 4>, + <0 0 19 &gic 0 19 4>, + <0 0 20 &gic 0 20 4>, + <0 0 21 &gic 0 21 4>, + <0 0 22 &gic 0 22 4>, + <0 0 23 &gic 0 23 4>, + <0 0 24 &gic 0 24 4>, + <0 0 25 &gic 0 25 4>, + <0 0 26 &gic 0 26 4>, + <0 0 27 &gic 0 27 4>, + <0 0 28 &gic 0 28 4>, + <0 0 29 &gic 0 29 4>, + <0 0 30 &gic 0 30 4>, + <0 0 31 &gic 0 31 4>, + <0 0 32 &gic 0 32 4>, + <0 0 33 &gic 0 33 4>, + <0 0 34 &gic 0 34 4>, + <0 0 35 &gic 0 35 4>, + <0 0 36 &gic 0 36 4>, + <0 0 37 &gic 0 37 4>, + <0 0 38 &gic 0 38 4>, + <0 0 39 &gic 0 39 4>, + <0 0 40 &gic 0 40 4>, + <0 0 41 &gic 0 41 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts new file mode 100644 index 0000000..e99719e --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "rtsm_ve-motherboard.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts new file mode 100644 index 0000000..c5e0424 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */ + +/dts-v1/; + +#define AFF 00 + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts new file mode 100644 index 0000000..a31c703 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs with 1 thread per each */ + +/dts-v1/; + +#define AFF 00 +#define REG_32 + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-aarch32-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi new file mode 100644 index 0000000..85988e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0x84000001>; + cpu_off = <0x84000002>; + cpu_on = <0x84000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 0 0 4>, + <0 0 1 &gic 0 0 0 1 4>, + <0 0 2 &gic 0 0 0 2 4>, + <0 0 3 &gic 0 0 0 3 4>, + <0 0 4 &gic 0 0 0 4 4>, + <0 0 5 &gic 0 0 0 5 4>, + <0 0 6 &gic 0 0 0 6 4>, + <0 0 7 &gic 0 0 0 7 4>, + <0 0 8 &gic 0 0 0 8 4>, + <0 0 9 &gic 0 0 0 9 4>, + <0 0 10 &gic 0 0 0 10 4>, + <0 0 11 &gic 0 0 0 11 4>, + <0 0 12 &gic 0 0 0 12 4>, + <0 0 13 &gic 0 0 0 13 4>, + <0 0 14 &gic 0 0 0 14 4>, + <0 0 15 &gic 0 0 0 15 4>, + <0 0 16 &gic 0 0 0 16 4>, + <0 0 17 &gic 0 0 0 17 4>, + <0 0 18 &gic 0 0 0 18 4>, + <0 0 19 &gic 0 0 0 19 4>, + <0 0 20 &gic 0 0 0 20 4>, + <0 0 21 &gic 0 0 0 21 4>, + <0 0 22 &gic 0 0 0 22 4>, + <0 0 23 &gic 0 0 0 23 4>, + <0 0 24 &gic 0 0 0 24 4>, + <0 0 25 &gic 0 0 0 25 4>, + <0 0 26 &gic 0 0 0 26 4>, + <0 0 27 &gic 0 0 0 27 4>, + <0 0 28 &gic 0 0 0 28 4>, + <0 0 29 &gic 0 0 0 29 4>, + <0 0 30 &gic 0 0 0 30 4>, + <0 0 31 &gic 0 0 0 31 4>, + <0 0 32 &gic 0 0 0 32 4>, + <0 0 33 &gic 0 0 0 33 4>, + <0 0 34 &gic 0 0 0 34 4>, + <0 0 35 &gic 0 0 0 35 4>, + <0 0 36 &gic 0 0 0 36 4>, + <0 0 37 &gic 0 0 0 37 4>, + <0 0 38 &gic 0 0 0 38 4>, + <0 0 39 &gic 0 0 0 39 4>, + <0 0 40 &gic 0 0 0 40 4>, + <0 0 41 &gic 0 0 0 41 4>, + <0 0 42 &gic 0 0 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; + + panels { + panel@0 { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts new file mode 100644 index 0000000..971b2e4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define REG_32 +#define AFF + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-aarch32-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi new file mode 100644 index 0000000..3cb613f --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define LEVEL 0 +#define EDGE 2 +#define SDEI_NORMAL 0x70 +#define HIGHEST_SEC 0 + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Base"; + compatible = "arm,vfp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + +#if (ENABLE_RME == 1) + chosen { bootargs = "mem=1G console=ttyAMA0 earlycon=pl011,0x1c090000 root=/dev/vda ip=on";}; +#else + chosen {}; +#endif + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + +#if SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF + firmware { +#if SDEI_IN_FCONF + sdei { + compatible = "arm,sdei-1.0"; + method = "smc"; + private_event_count = <3>; + shared_event_count = <3>; + /* + * Each event descriptor has typically 3 fields: + * 1. Event number + * 2. Interrupt number the event is bound to or + * if event is dynamic, specified as SDEI_DYN_IRQ + * 3. Bit map of event flags + */ + private_events = <1000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <1001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <1002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>; + shared_events = <2000 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <2001 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>, + <2002 SDEI_DYN_IRQ SDEI_MAPF_DYNAMIC>; + }; +#endif /* SDEI_IN_FCONF */ + +#if SEC_INT_DESC_IN_FCONF + sec_interrupts { + compatible = "arm,secure_interrupt_desc"; + /* Number of G0 and G1 secure interrupts defined by the platform */ + g0_intr_cnt = <2>; + g1s_intr_cnt = <9>; + /* + * Define a list of Group 1 Secure and Group 0 interrupts as per GICv3 + * terminology. Each interrupt property descriptor has 3 fields: + * 1. Interrupt number + * 2. Interrupt priority + * 3. Type of interrupt (Edge or Level configured) + */ + g0_intr_desc = < 8 SDEI_NORMAL EDGE>, + <14 HIGHEST_SEC EDGE>; + + g1s_intr_desc = < 9 HIGHEST_SEC EDGE>, + <10 HIGHEST_SEC EDGE>, + <11 HIGHEST_SEC EDGE>, + <12 HIGHEST_SEC EDGE>, + <13 HIGHEST_SEC EDGE>, + <15 HIGHEST_SEC EDGE>, + <29 HIGHEST_SEC LEVEL>, + <56 HIGHEST_SEC LEVEL>, + <57 HIGHEST_SEC LEVEL>; + }; +#endif /* SEC_INT_DESC_IN_FCONF */ + }; +#endif /* SDEI_IN_FCONF || SEC_INT_DESC_IN_FCONF */ + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; +#if (ENABLE_RME == 1) + reg = <0x00000000 0x80000000 0 0x7C000000>, + <0x00000008 0x80000000 0 0x80000000>; +#else + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; +#endif + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb@0,0 { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "rtsm_ve-motherboard.dtsi" + }; + + panels { + panel { + compatible = "panel"; + mode = "XVGA"; + refresh = <60>; + xres = <1024>; + yres = <768>; + pixclock = <15748>; + left_margin = <152>; + right_margin = <48>; + upper_margin = <23>; + lower_margin = <3>; + hsync_len = <104>; + vsync_len = <4>; + sync = <0>; + vmode = "FB_VMODE_NONINTERLACED"; + tim2 = "TIM2_BCD", "TIM2_IPC"; + cntl = "CNTL_LCDTFT", "CNTL_BGR", "CNTL_LCDVCOMP(1)"; + caps = "CLCD_CAP_5551", "CLCD_CAP_565", "CLCD_CAP_888"; + bpp = <16>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts new file mode 100644 index 0000000..bda4b8d --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* DynamIQ configuration: 1 cluster with up to 8 CPUs with 2 threads per each */ + +/* Set default value if not passed from platform's makefile */ +#ifdef FVP_MAX_PE_PER_CPU +#define PE_PER_CPU FVP_MAX_PE_PER_CPU +#else +#define PE_PER_CPU 2 +#endif + +/dts-v1/; + +#include "fvp-base-gicv3-psci-dynamiq-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi new file mode 100644 index 0000000..42a439f --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi @@ -0,0 +1,10 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +#include "fvp-defs-dynamiq.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts new file mode 100644 index 0000000..b693f75 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* DynamIQ configuration: 1 cluster with up to 8 CPUs */ + +/* Set default value if not passed from platform's makefile */ +#ifdef FVP_MAX_PE_PER_CPU +#define PE_PER_CPU FVP_MAX_PE_PER_CPU +#else +#define PE_PER_CPU 1 +#endif + +/dts-v1/; + +#include "fvp-base-gicv3-psci-dynamiq-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts new file mode 100644 index 0000000..eb99472 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: max 4 clusters with up to 4 CPUs */ + +/dts-v1/; + +#define AFF + +#include "fvp-defs.dtsi" +#include "fvp-base-gicv3-psci-common.dtsi" diff --git a/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi b/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi new file mode 100644 index 0000000..3659cd3 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi @@ -0,0 +1,289 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEFS_DYNAMIQ_DTSI +#define FVP_DEFS_DYNAMIQ_DTSI + +/* Set default topology values if not passed from platform's makefile */ +#ifdef FVP_CLUSTER_COUNT +#define CLUSTER_COUNT FVP_CLUSTER_COUNT +#else +#define CLUSTER_COUNT 1 +#endif + +#ifdef FVP_MAX_CPUS_PER_CLUSTER +#define CPUS_PER_CLUSTER FVP_MAX_CPUS_PER_CLUSTER +#else +#define CPUS_PER_CLUSTER 8 +#endif + +#define CONCAT(x, y) x##y +#define CONC(x, y) CONCAT(x, y) + +/* + * n - CPU number + * r - MPID + */ +#define CPU(n, r) \ + CPU##n:cpu@r## { \ + device_type = "cpu"; \ + compatible = "arm,armv8"; \ + reg = <0x0 0x##r>; \ + enable-method = "psci"; \ + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; \ + next-level-cache = <&L2_0>; \ + }; + +#if (PE_PER_CPU == 2) +#define THREAD(n) \ + thread##n { \ + cpu = <&CONC(CPU, __COUNTER__)>; \ + }; + +#define CORE(n) \ + core##n { \ + THREAD(0) \ + THREAD(1) \ + }; + +#else /* PE_PER_CPU == 1 */ +#define CORE(n) \ + core##n { \ + cpu = <&CPU##n>;\ + }; +#endif /* PE_PER_CORE */ + +#if (CPUS_PER_CLUSTER == 1) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + }; + +#elif (CPUS_PER_CLUSTER == 2) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + }; + +#elif (CPUS_PER_CLUSTER == 3) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + }; + +#elif (CPUS_PER_CLUSTER == 4) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + }; + +#elif (CPUS_PER_CLUSTER == 5) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + }; + +#elif (CPUS_PER_CLUSTER == 6) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + }; + +#elif (CPUS_PER_CLUSTER == 7) +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) \ + CPU(6, 600) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) \ + CPU(12, 600) \ + CPU(13, 601) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + CORE(6) \ + }; + +#else +#if (PE_PER_CPU == 1) +#define CPUS \ + CPU(0, 0) \ + CPU(1, 100) \ + CPU(2, 200) \ + CPU(3, 300) \ + CPU(4, 400) \ + CPU(5, 500) \ + CPU(6, 600) \ + CPU(7, 700) +#else +#define CPUS \ + CPU(0, 0) \ + CPU(1, 1) \ + CPU(2, 100) \ + CPU(3, 101) \ + CPU(4, 200) \ + CPU(5, 201) \ + CPU(6, 300) \ + CPU(7, 301) \ + CPU(8, 400) \ + CPU(9, 401) \ + CPU(10, 500) \ + CPU(11, 501) \ + CPU(12, 600) \ + CPU(13, 601) \ + CPU(14, 700) \ + CPU(15, 701) +#endif +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + CORE(4) \ + CORE(5) \ + CORE(6) \ + CORE(7) \ + }; +#endif /* CPUS_PER_CLUSTER */ + +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + }; + +#endif /* FVP_DEFS_DYNAMIQ_DTSI */ diff --git a/arm-trusted-firmware/fdts/fvp-defs.dtsi b/arm-trusted-firmware/fdts/fvp-defs.dtsi new file mode 100644 index 0000000..1ffe65a --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-defs.dtsi @@ -0,0 +1,400 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_DEFS_DTSI +#define FVP_DEFS_DTSI + +/* Set default topology values if not passed from platform's makefile */ +#ifndef CLUSTER_COUNT +#ifdef FVP_CLUSTER_COUNT +#define CLUSTER_COUNT FVP_CLUSTER_COUNT +#else +#define CLUSTER_COUNT 2 +#endif +#endif /* CLUSTER_COUNT */ + +#ifndef CPUS_PER_CLUSTER +#ifdef FVP_MAX_CPUS_PER_CLUSTER +#define CPUS_PER_CLUSTER FVP_MAX_CPUS_PER_CLUSTER +#else +#define CPUS_PER_CLUSTER 4 +#endif +#endif /* CPUS_PER_CLUSTER */ + +/* Get platform's topology */ +#define CPUS_COUNT (CLUSTER_COUNT * CPUS_PER_CLUSTER) + +#define CONCAT(x, y) x##y +#define CONC(x, y) CONCAT(x, y) + +/* CPU's cluster */ +#define CLS(n) (n / CPUS_PER_CLUSTER) + +/* CPU's position in cluster */ +#define POS(n) (n % CPUS_PER_CLUSTER) + +#define ADR(n, c, p) \ + CPU##n:cpu@CONC(c, CONC(p, AFF)) { + +#define PRE \ + device_type = "cpu"; \ + compatible = "arm,armv8"; + +#ifdef REG_32 +/* 32-bit address */ +#define REG(c, p) \ + reg = ; +#else +/* 64-bit address */ +#define REG(c, p) \ + reg = <0x0 CONC(0x, CONC(c, CONC(p, AFF)))>; +#endif /* REG_32 */ + +#define POST \ + enable-method = "psci"; \ + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; \ + next-level-cache = <&L2_0>; \ + }; + +#ifdef REG_32 +#define CPU_0 \ + CPU0:cpu@0 { \ + PRE \ + reg = <0x0>; \ + POST +#else +#define CPU_0 \ + CPU0:cpu@0 { \ + PRE \ + reg = <0x0 0x0>;\ + POST +#endif /* REG_32 */ + +/* + * n - CPU number + */ +#define CPU(n, c, p) \ + ADR(n, c, p) \ + PRE \ + REG(c, p) \ + POST + +/* 2 CPUs */ +#if (CPUS_COUNT > 1) +#if (CLS(1) == 0) +#define c1 +#define p1 1 +#else +#define c1 10 +#define p1 0 +#endif + +#define CPU_1 CPU(1, c1, p1) /* CPU1: 0.1; 1.0 */ + +/* 3 CPUs */ +#if (CPUS_COUNT > 2) +#if (CLS(2) == 0) +#define c2 +#define p2 2 +#elif (CLS(2) == 1) +#define c2 10 +#define p2 0 +#else +#define c2 20 +#define p2 0 +#endif + +#define CPU_2 CPU(2, c2, p2) /* CPU2: 0.2; 1.0; 2.0 */ + +/* 4 CPUs */ +#if (CPUS_COUNT > 3) +#if (CLS(3) == 0) +#define c3 +#elif (CLS(3) == 1) +#define c3 10 +#else +#define c3 30 +#endif + +#if (POS(3) == 0) +#define p3 0 +#elif (POS(3) == 1) +#define p3 1 +#else +#define p3 3 +#endif + +#define CPU_3 CPU(3, c3, p3) /* CPU3: 0.3; 1.0; 1.1; 3.0 */ + +/* 6 CPUs */ +#if (CPUS_COUNT > 4) +#if (CLS(4) == 1) +#define c4 10 +#else +#define c4 20 +#endif + +#if (POS(4) == 0) +#define p4 0 +#else +#define p4 1 +#endif + +#if (CLS(5) == 1) +#define c5 10 +#else +#define c5 20 +#endif + +#if (POS(5) == 1) +#define p5 1 +#else +#define p5 2 +#endif + +#define CPU_4 CPU(4, c4, p4) /* CPU4: 1.0; 1.1; 2.0 */ +#define CPU_5 CPU(5, c5, p5) /* CPU5: 1.1; 1.2; 2.1 */ + +/* 8 CPUs */ +#if (CPUS_COUNT > 6) +#if (CLS(6) == 1) +#define c6 10 +#define p6 2 +#elif (CLS(6) == 2) +#define c6 20 +#define p6 0 +#else +#define c6 30 +#define p6 0 +#endif + +#if (CLS(7) == 1) +#define c7 10 +#define p7 3 +#elif (CLS(7) == 2) +#define c7 20 +#define p7 1 +#else +#define c7 30 +#define p7 1 +#endif + +#define CPU_6 CPU(6, c6, p6) /* CPU6: 1.2; 2.0; 3.0 */ +#define CPU_7 CPU(7, c7, p7) /* CPU7: 1.3; 2.1; 3.1 */ + +/* 9 CPUs */ +#if (CPUS_COUNT > 8) +#if (POS(8) == 0) +#define p8 0 +#else +#define p8 2 +#endif + +#define CPU_8 CPU(8, 20, p8) /* CPU8: 2.0; 2.2 */ + +/* 12 CPUs */ +#if (CPUS_COUNT > 9) +#if (CLS(9) == 2) +#define c9 20 +#define p9 1 +#else +#define c9 30 +#define p9 0 +#endif + +#if (CLS(10) == 2) +#define c10 20 +#define p10 2 +#else +#define c10 30 +#define p10 1 +#endif + +#if (CLS(11) == 2) +#define c11 20 +#define p11 3 +#else +#define c11 30 +#define p11 2 +#endif + +#define CPU_9 CPU(9, c9, p9) /* CPU9: 2.1; 3.0 */ +#define CPU_10 CPU(10, c10, p10) /* CPU10: 2.2; 3.1 */ +#define CPU_11 CPU(11, c11, p11) /* CPU11: 2.3; 3.2 */ + +/* 16 CPUs */ +#if (CPUS_COUNT > 12) +#define CPU_12 CPU(12, 30, 0) /* CPU12: 3.0 */ +#define CPU_13 CPU(13, 30, 1) /* CPU13: 3.1 */ +#define CPU_14 CPU(14, 30, 2) /* CPU14: 3.2 */ +#define CPU_15 CPU(15, 30, 3) /* CPU15: 3.3 */ +#endif /* > 12 */ +#endif /* > 9 */ +#endif /* > 8 */ +#endif /* > 6 */ +#endif /* > 4 */ +#endif /* > 3 */ +#endif /* > 2 */ +#endif /* > 1 */ + +#if (CPUS_COUNT == 1) +#define CPUS \ + CPU_0 + +#elif (CPUS_COUNT == 2) +#define CPUS \ + CPU_0 \ + CPU_1 + +#elif (CPUS_COUNT == 3) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 + +#elif (CPUS_COUNT == 4) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 + +#elif (CPUS_COUNT == 6) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 + +#elif (CPUS_COUNT == 8) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 + +#elif (CPUS_COUNT == 9) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 + +#elif (CPUS_COUNT == 12) +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 \ + CPU_9 \ + CPU_10 \ + CPU_11 + +#else +#define CPUS \ + CPU_0 \ + CPU_1 \ + CPU_2 \ + CPU_3 \ + CPU_4 \ + CPU_5 \ + CPU_6 \ + CPU_7 \ + CPU_8 \ + CPU_9 \ + CPU_10 \ + CPU_11 \ + CPU_12 \ + CPU_13 \ + CPU_14 \ + CPU_15 +#endif /* CPUS_COUNT */ + +#define CORE(n) \ + core##n { \ + cpu = <&CONC(CPU, __COUNTER__)>; \ + }; + +/* Max 4 CPUs per cluster */ +#if (CPUS_PER_CLUSTER == 1) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + }; +#elif (CPUS_PER_CLUSTER == 2) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + }; + +#elif (CPUS_PER_CLUSTER == 3) +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + }; + +#else +#define CLUSTER(n) \ + cluster##n { \ + CORE(0) \ + CORE(1) \ + CORE(2) \ + CORE(3) \ + }; +#endif /* CPUS_PER_CLUSTER */ + +/* Max 4 clusters */ +#if (CLUSTER_COUNT == 1) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + }; + +#elif (CLUSTER_COUNT == 2) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + }; + +#elif (CLUSTER_COUNT == 3) +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + CLUSTER(2) \ + }; + +#else +#define CPU_MAP \ + cpu-map { \ + CLUSTER(0) \ + CLUSTER(1) \ + CLUSTER(2) \ + CLUSTER(3) \ + }; +#endif /* CLUSTER_COUNT */ + +#endif /* FVP_DEFS_DTSI */ diff --git a/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts b/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts new file mode 100644 index 0000000..5a82c46 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: 1 cluster with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define CLUSTER_COUNT 1 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Foundation"; + compatible = "arm,fvp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,cortex-a15-gic", "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, + <0x0 0x2c000000 0 0x2000>, + <0x0 0x2c010000 0 0x2000>, + <0x0 0x2c02F000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "fvp-foundation-motherboard.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts b/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts new file mode 100644 index 0000000..e1249d4 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Configuration: 1 cluster with up to 4 CPUs */ + +/dts-v1/; + +#define AFF +#define CLUSTER_COUNT 1 + +#include +#include "fvp-defs.dtsi" + +/memreserve/ 0x80000000 0x00010000; + +/ { +}; + +/ { + model = "FVP Foundation"; + compatible = "arm,fvp-base", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + chosen { }; + + aliases { + serial0 = &v2m_serial0; + serial1 = &v2m_serial1; + serial2 = &v2m_serial2; + serial3 = &v2m_serial3; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2", "arm,psci"; + method = "smc"; + cpu_suspend = <0xc4000001>; + cpu_off = <0x84000002>; + cpu_on = <0xc4000003>; + sys_poweroff = <0x84000008>; + sys_reset = <0x84000009>; + max-pwr-lvl = <2>; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + CPU_MAP + + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x0010000>; + entry-latency-us = <40>; + exit-latency-us = <100>; + min-residency-us = <150>; + }; + + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + local-timer-stop; + arm,psci-suspend-param = <0x1010000>; + entry-latency-us = <500>; + exit-latency-us = <1000>; + min-residency-us = <2500>; + }; + }; + + CPUS + + L2_0: l2-cache0 { + compatible = "cache"; + }; + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0 0x7F000000>, + <0x00000008 0x80000000 0 0x80000000>; + }; + + gic: interrupt-controller@2f000000 { + compatible = "arm,gic-v3"; + #interrupt-cells = <3>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x2f000000 0 0x10000>, // GICD + <0x0 0x2f100000 0 0x200000>, // GICR + <0x0 0x2c000000 0 0x2000>, // GICC + <0x0 0x2c010000 0 0x2000>, // GICH + <0x0 0x2c02f000 0 0x2000>; // GICV + interrupts = <1 9 4>; + + its: its@2f020000 { + compatible = "arm,gic-v3-its"; + msi-controller; + reg = <0x0 0x2f020000 0x0 0x20000>; // GITS + }; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + clock-frequency = <100000000>; + }; + + timer@2a810000 { + compatible = "arm,armv7-timer-mem"; + reg = <0x0 0x2a810000 0x0 0x10000>; + clock-frequency = <100000000>; + #address-cells = <2>; + #size-cells = <2>; + ranges; + frame@2a830000 { + frame-number = <1>; + interrupts = <0 26 4>; + reg = <0x0 0x2a830000 0x0 0x10000>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = <0 60 4>, + <0 61 4>, + <0 62 4>, + <0 63 4>; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #include "fvp-foundation-motherboard.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi b/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi new file mode 100644 index 0000000..9ee5b64 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi @@ -0,0 +1,184 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + ranges; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <0 15 4>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <0 5 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <0 7 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <0 8 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0 0 4>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <0 2 4>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <0 3 4>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <0 4 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0 0x2a 4>; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts new file mode 100644 index 0000000..9d2d1d5 --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2P-CA5s"; + compatible = "arm,vexpress,v2p-ca5s", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a5"; + reg = <0>; + }; + + }; + + memory@80000000 { + device_type = "memory"; + reg = <0x80000000 0x1000000>; + }; + + hdlcd@2a110000 { + compatible = "arm,hdlcd"; + reg = <0x2a110000 0x1000>; + interrupts = <0 85 4>; + clocks = <&oscclk3>; + clock-names = "pxlclk"; + }; + + scu@2c000000 { + compatible = "arm,cortex-a5-scu"; + reg = <0x2c000000 0x58>; + }; + + watchdog@2c000620 { + compatible = "arm,cortex-a5-twd-wdt"; + reg = <0x2c000620 0x20>; + interrupts = <1 14 0x304>; + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a9-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0x2c001000 0x1000>, + <0x2c000100 0x100>; + }; + + dcc { + compatible = "arm,vexpress,config-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + oscclk0: osc@0 { + /* CPU and internal AXI reference clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 0>; + freq-range = <50000000 100000000>; + #clock-cells = <0>; + clock-output-names = "oscclk0"; + }; + + oscclk1: osc@1 { + /* Multiplexed AXI master clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <5000000 50000000>; + #clock-cells = <0>; + clock-output-names = "oscclk1"; + }; + + osc@2 { + /* DDR2 */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 2>; + freq-range = <80000000 120000000>; + #clock-cells = <0>; + clock-output-names = "oscclk2"; + }; + + oscclk3: osc@3 { + /* HDLCD */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 3>; + freq-range = <23750000 165000000>; + #clock-cells = <0>; + clock-output-names = "oscclk3"; + }; + + osc@4 { + /* Test chip gate configuration */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 4>; + freq-range = <80000000 80000000>; + #clock-cells = <0>; + clock-output-names = "oscclk4"; + }; + + smbclk: osc@5 { + /* SMB clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 5>; + freq-range = <25000000 60000000>; + #clock-cells = <0>; + clock-output-names = "oscclk5"; + }; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0x08000000 0x04000000>, + <1 0 0x14000000 0x04000000>, + <2 0 0x18000000 0x04000000>, + <3 0 0x1c000000 0x04000000>, + <4 0 0x0c000000 0x04000000>, + <5 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts new file mode 100644 index 0000000..28de91d --- /dev/null +++ b/arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + model = "V2F-1XV7 Cortex-A7x1 SMM"; + compatible = "arm,vexpress,v2f-1xv7", "arm,vexpress"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu@0 { + device_type = "cpu"; + compatible = "arm,cortex-a7"; + reg = <0 0>; + }; + }; + + memory@0,80000000 { + device_type = "memory"; + reg = <0 0x80000000 0 0x80000000>; /* 2GB @ 2GB */ + }; + + gic: interrupt-controller@2c001000 { + compatible = "arm,cortex-a15-gic"; + #interrupt-cells = <3>; + #address-cells = <0>; + interrupt-controller; + reg = <0 0x2c001000 0 0x1000>, + <0 0x2c002000 0 0x1000>, + <0 0x2c004000 0 0x2000>, + <0 0x2c006000 0 0x2000>; + interrupts = <1 9 0xf04>; + }; + + smbclk: refclk24mhzx2 { + /* Reference 24MHz clock x 2 */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <48000000>; + clock-output-names = "smclk"; + }; + + smb { + compatible = "simple-bus"; + + #address-cells = <2>; + #size-cells = <1>; + ranges = <0 0 0 0x08000000 0x04000000>, + <1 0 0 0x14000000 0x04000000>, + <2 0 0 0x18000000 0x04000000>, + <3 0 0 0x1c000000 0x04000000>, + <4 0 0 0x0c000000 0x04000000>, + <5 0 0 0x10000000 0x04000000>; + + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 63>; + interrupt-map = <0 0 0 &gic 0 0 4>, + <0 0 1 &gic 0 1 4>, + <0 0 2 &gic 0 2 4>, + <0 0 3 &gic 0 3 4>, + <0 0 4 &gic 0 4 4>, + <0 0 5 &gic 0 5 4>, + <0 0 42 &gic 0 42 4>; + + #include "rtsm_ve-motherboard-aarch32.dtsi" + }; +}; diff --git a/arm-trusted-firmware/fdts/juno-ethosn.dtsi b/arm-trusted-firmware/fdts/juno-ethosn.dtsi new file mode 100644 index 0000000..e2f3355 --- /dev/null +++ b/arm-trusted-firmware/fdts/juno-ethosn.dtsi @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * For examples of multi-core and multi-device NPU, refer to the examples given in the + * Arm Ethos-N NPU driver stack. + * https://github.com/ARM-software/ethos-n-driver-stack + */ + +/ { + #address-cells = <2>; + #size-cells = <2>; + + ethosn0: ethosn@6f300000 { + compatible = "ethosn"; + reg = <0 0x6f300000 0 0x00100000>; + status = "okay"; + + core0 { + compatible = "ethosn-core"; + status = "okay"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/juno.dts b/arm-trusted-firmware/fdts/juno.dts new file mode 100644 index 0000000..56fe167 --- /dev/null +++ b/arm-trusted-firmware/fdts/juno.dts @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + +}; + +#if ARM_ETHOSN_NPU_DRIVER + #include "juno-ethosn.dtsi" +#endif diff --git a/arm-trusted-firmware/fdts/morello-fvp.dts b/arm-trusted-firmware/fdts/morello-fvp.dts new file mode 100644 index 0000000..55c87bf --- /dev/null +++ b/arm-trusted-firmware/fdts/morello-fvp.dts @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +#include "morello.dtsi" + +/ { + + chosen { + stdout-path = "serial0:115200n8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure-firmware@ff000000 { + reg = <0 0xff000000 0 0x01000000>; + no-map; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + }; + cluster1 { + core0 { + cpu = <&CPU2>; + }; + core1 { + cpu = <&CPU3>; + }; + }; + }; + CPU0: cpu0@0 { + compatible = "arm,armv8"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + CPU1: cpu1@100 { + compatible = "arm,armv8"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + CPU2: cpu2@10000 { + compatible = "arm,armv8"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + CPU3: cpu3@10100 { + compatible = "arm,armv8"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + }; + + /* The first bank of memory, memory map is actually provided by UEFI. */ + memory@80000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x80000000-0xffffffff] */ + reg = <0x00000000 0x80000000 0x0 0x80000000>; + }; + + memory@8080000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x8080000000-0x83ffffffff] */ + reg = <0x00000080 0x80000000 0x1 0x80000000>; + }; + + virtio_block@1c170000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c170000 0x0 0x200>; + interrupts = ; + }; + + virtio_net@1c180000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c180000 0x0 0x200>; + interrupts = ; + }; + + virtio_rng@1c190000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c190000 0x0 0x200>; + interrupts = ; + }; + + virtio_p9@1c1a0000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c1a0000 0x0 0x200>; + interrupts = ; + }; + + ethernet@1d100000 { + compatible = "smsc,lan91c111"; + reg = <0x0 0x1d100000 0x0 0x10000>; + interrupts = ; + }; + + kmi@1c150000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x1c150000 0x0 0x1000>; + interrupts = ; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@1c160000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x1c160000 0x0 0x1000>; + interrupts = ; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + firmware { + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mailbox 1 0 &mailbox 1 1>; + shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + }; + }; + + bp_clock24mhz: clock24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; +}; + +&gic { + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + interrupts = ; +}; diff --git a/arm-trusted-firmware/fdts/morello-soc.dts b/arm-trusted-firmware/fdts/morello-soc.dts new file mode 100644 index 0000000..8464634 --- /dev/null +++ b/arm-trusted-firmware/fdts/morello-soc.dts @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; +#include "morello.dtsi" + +/ { + + chosen { + stdout-path = "soc_uart0:115200n8"; + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + secure-firmware@ff000000 { + reg = <0 0xff000000 0 0x01000000>; + no-map; + }; + }; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + cpu0@0 { + compatible = "arm,armv8"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + cpu1@100 { + compatible = "arm,armv8"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + }; + cpu2@10000 { + compatible = "arm,armv8"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + cpu3@10100 { + compatible = "arm,armv8"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + }; + }; + + /* The first bank of memory, memory map is actually provided by UEFI. */ + memory@80000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x80000000-0xffffffff] */ + reg = <0x00000000 0x80000000 0x0 0x7F000000>; + }; + + memory@8080000000 { + #address-cells = <2>; + #size-cells = <2>; + device_type = "memory"; + /* [0x8080000000-0x83f7ffffff] */ + reg = <0x00000080 0x80000000 0x3 0x78000000>; + }; + + smmu_pcie: iommu@4f400000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f400000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; + msi-parent = <&its2 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_ctlr: pcie@28c0000000 { + compatible = "pci-host-ecam-generic"; + device_type = "pci"; + reg = <0x28 0xC0000000 0 0x10000000>; + bus-range = <0 255>; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x6F000000 0x00 0x00800000>, + <0x02000000 0x00 0x60000000 0x00 0x60000000 0x00 0x0F000000>, + <0x42000000 0x09 0x00000000 0x09 0x00000000 0x1F 0xC0000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_pcie 0 0x10000>; + iommu-map = <0 &smmu_pcie 0 0x10000>; + status = "okay"; + }; + + smmu_ccix: iommu@4f000000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f000000 0 0x40000>; + interrupts = , + , + , + ; + interrupt-names = "eventq", "priq", "cmdq-sync", "gerror"; + msi-parent = <&its1 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + ccix_pcie_ctlr: pcie@4fc0000000 { + compatible = "pci-host-ecam-generic"; + device_type = "pci"; + reg = <0x4F 0xC0000000 0 0x10000000>; + bus-range = <0 255>; + linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x7F000000 0x00 0x00800000>, + <0x02000000 0x00 0x70000000 0x00 0x70000000 0x00 0x0F000000>, + <0x42000000 0x30 0x00000000 0x30 0x00000000 0x1F 0xC0000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_ccix 0 0x10000>; + iommu-map = <0 &smmu_ccix 0 0x10000>; + status = "okay"; + }; + + smmu_dp: iommu@2ce00000 { + compatible = "arm,smmu-v3"; + reg = <0 0x2ce00000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + #iommu-cells = <1>; + }; + + dp0: display@2cc00000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,mali-d32"; + reg = <0 0x2cc00000 0 0x20000>; + interrupts = <0 69 4>; + interrupt-names = "DPU"; + clocks = <&dpu_aclk>; + clock-names = "aclk"; + iommus = <&smmu_dp 0>, <&smmu_dp 1>, <&smmu_dp 2>, <&smmu_dp 3>, + <&smmu_dp 8>; + + pl0: pipeline@0 { + reg = <0>; + clocks = <&scmi_clk 1>; + clock-names = "pxclk"; + pl_id = <0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dp_pl0_out0: endpoint { + remote-endpoint = <&tda998x_0_input>; + }; + }; + }; + }; + }; + + i2c@1c0f0000 { + compatible = "cdns,i2c-r1p14"; + reg = <0x0 0x1c0f0000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <100000>; + i2c-sda-hold-time-ns = <500>; + interrupts = ; + clocks = <&dpu_aclk>; + + hdmi-transmitter@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + video-ports = <0x234501>; + port { + tda998x_0_input: endpoint { + remote-endpoint = <&dp_pl0_out0>; + }; + }; + }; + }; + + dpu_aclk: dpu_aclk { + /* 77.1 MHz derived from 24 MHz reference clock */ + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <350000000>; + clock-output-names = "aclk"; + }; + + firmware { + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mailbox 1 0 &mailbox 1 1>; + shmem = <&cpu_scp_hpri0 &cpu_scp_hpri1>; + #address-cells = <1>; + #size-cells = <0>; + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + }; +}; + +&gic { + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + interrupts = ; + + its1: its@30040000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30040000 0x0 0x20000>; + }; + + its2: its@30060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30060000 0x0 0x20000>; + }; + + its_ccix: its@30080000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30080000 0x0 0x20000>; + }; + + its_pcie: its@300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x300a0000 0x0 0x20000>; + }; +}; diff --git a/arm-trusted-firmware/fdts/morello.dtsi b/arm-trusted-firmware/fdts/morello.dtsi new file mode 100644 index 0000000..f119820 --- /dev/null +++ b/arm-trusted-firmware/fdts/morello.dtsi @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/ { + compatible = "arm,morello"; + + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &soc_uart0; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-600", "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + mailbox: mhu@45000000 { + compatible = "arm,mhu-doorbell", "arm,primecell"; + reg = <0x0 0x45000000 0x0 0x1000>; + interrupts = , + ; + interrupt-names = "mhu_lpri_rx", + "mhu_hpri_rx"; + #mbox-cells = <2>; + mbox-name = "ARM-MHU"; + clocks = <&soc_refclk50mhz>; + clock-names = "apb_pclk"; + }; + + sram: sram@45200000 { + compatible = "mmio-sram"; + reg = <0x0 0x06000000 0x0 0x8000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x06000000 0x8000>; + + cpu_scp_hpri0: scp-shmem@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x80>; + }; + + cpu_scp_hpri1: scp-shmem@80 { + compatible = "arm,scmi-shmem"; + reg = <0x80 0x80>; + }; + }; + + soc_refclk50mhz: refclk50mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "apb_pclk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc_uart0: uart@2a400000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x2a400000 0x0 0x1000>; + interrupts = ; + clocks = <&soc_uartclk>, <&soc_refclk50mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "okay"; + }; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts b/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts new file mode 100644 index 0000000..8932dfc --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp-multi-chip.dts @@ -0,0 +1,113 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +#include "n1sdp-single-chip.dts" + +/ { + cpus { + cpu4@100000000 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x0>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu5@100000100 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00000100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu6@100010000 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00010000>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + cpu7@100010100 { + compatible = "arm,neoverse-n1"; + reg = <0x1 0x00010100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <1>; + }; + }; + + /* Remote N1SDP board address is mapped at offset 4TB. + * First DRAM Bank of remote N1SDP board is mapped at 4TB + 2GB. + */ + memory@40080000000 { + device_type = "memory"; + reg = <0x00000400 0x80000000 0x0 0x80000000>, + <0x00000480 0x80000000 0x3 0x80000000>; + numa-node-id = <1>; + }; + + distance-map { + compatible = "numa-distance-map-v1"; + distance-matrix = <0 0 10>, + <0 1 20>, + <1 1 10>; + }; + + smmu_slave_pcie: iommu@4004f400000 { + compatible = "arm,smmu-v3"; + reg = <0x400 0x4f400000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its2_slave 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_slave_ctlr: pcie@40070000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0x400 0x70000000 0 0x1200000>; + bus-range = <0 0xff>; + linux,pci-domain = <2>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x400 0x75200000 0x00 0x00010000>, + <0x02000000 0x00 0x71200000 0x400 0x71200000 0x00 0x04000000>, + <0x42000000 0x09 0x00000000 0x409 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 649 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 650 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 651 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 652 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_slave_pcie 0 0x10000>; + iommu-map = <0 &smmu_slave_pcie 0 0x10000>; + status = "okay"; + }; + +}; + +&gic { + #redistributor-regions = <2>; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>, /* GICR */ + <0x400 0x300c0000 0 0x80000>; /* GICR */ + + its2_slave: its@40030060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x30060000 0x0 0x20000>; + }; + + its_slave_pcie: its@400300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x400 0x300a0000 0x0 0x20000>; + }; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp-single-chip.dts b/arm-trusted-firmware/fdts/n1sdp-single-chip.dts new file mode 100644 index 0000000..3c091ac --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp-single-chip.dts @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +/dts-v1/; + +#include "n1sdp.dtsi" + +/ { + model = "Arm Neoverse N1 System Development Platform"; + compatible = "arm,neoverse-n1-sdp", "arm,neoverse-n1-soc"; + + aliases { + serial0 = &soc_uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + /* This configuration assumes that standard setup with two DIMM modules. + * In the first 2GB of DRAM bank the top 16MB are reserved by firmware as secure memory. + * This configuration assumes 16GB of total DRAM being populated. + */ + memory@80000000 { + device_type = "memory"; + reg = <0x00000000 0x80000000 0x0 0x7f000000>, + <0x00000080 0x80000000 0x3 0x80000000>; + numa-node-id = <0>; + }; + + soc_refclk60mhz: refclk60mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <60000000>; + clock-output-names = "iofpga_clk"; + }; + + soc_hdlcdclk: hdlcdclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <23750000>; + clock-output-names = "hdlcdclk"; + }; + + hdlcd: hdlcd@1c050000 { + compatible = "arm,hdlcd"; + reg = <0 0x1c050000 0 0x1000>; + interrupts = ; + clocks = <&soc_hdlcdclk>; + clock-names = "pxlclk"; + + port { + hdlcd0_output: endpoint { + remote-endpoint = <&tda998x_0_input>; + }; + }; + }; + + i2c@1c0f0000 { + compatible = "arm,versatile-i2c"; + reg = <0x0 0x1c0f0000 0x0 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + clock-frequency = <400000>; + i2c-sda-hold-time-ns = <500>; + clocks = <&soc_refclk60mhz>; + + hdmi-transmitter@70 { + compatible = "nxp,tda998x"; + reg = <0x70>; + port { + tda998x_0_input: endpoint { + remote-endpoint = <&hdlcd0_output>; + }; + }; + }; + }; +}; + +&pcie_ctlr { + status = "okay"; +}; + +&ccix_pcie_ctlr { + status = "okay"; +}; + +&soc_uart0 { + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/n1sdp.dtsi b/arm-trusted-firmware/fdts/n1sdp.dtsi new file mode 100644 index 0000000..88f8734 --- /dev/null +++ b/arm-trusted-firmware/fdts/n1sdp.dtsi @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: (GPL-2.0 or BSD-3-Clause) +/* + * Copyright (c) 2019-2020, Arm Limited. + */ + +#include + +/ { + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + cpus { + #address-cells = <2>; + #size-cells = <0>; + + cpu0@0 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x0>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu1@100 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu2@10000 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x10000>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + cpu3@10100 { + compatible = "arm,neoverse-n1"; + reg = <0x0 0x10100>; + device_type = "cpu"; + enable-method = "psci"; + numa-node-id = <0>; + }; + }; + + pmu { + compatible = "arm,armv8-pmuv3"; + interrupts = ; + }; + + spe-pmu { + compatible = "arm,statistical-profiling-extension-v1"; + interrupts = ; + }; + + psci { + compatible = "arm,psci-0.2"; + method = "smc"; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = , + , + , + ; + }; + + soc_refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc { + compatible = "arm,neoverse-n1-soc", "simple-bus"; + #address-cells = <2>; + #size-cells = <2>; + ranges; + + gic: interrupt-controller@30000000 { + compatible = "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x300c0000 0 0x80000>; /* GICR */ + + interrupts = ; + + its1: its@30040000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30040000 0x0 0x20000>; + }; + + its2: its@30060000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30060000 0x0 0x20000>; + }; + + its_ccix: its@30080000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x30080000 0x0 0x20000>; + }; + + its_pcie: its@300a0000 { + compatible = "arm,gic-v3-its"; + msi-controller; + #msi-cells = <1>; + reg = <0x0 0x300a0000 0x0 0x20000>; + }; + }; + + smmu_ccix: iommu@4f000000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f000000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its1 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + smmu_pcie: iommu@4f400000 { + compatible = "arm,smmu-v3"; + reg = <0 0x4f400000 0 0x40000>; + interrupts = , + , + ; + interrupt-names = "eventq", "cmdq-sync", "gerror"; + msi-parent = <&its2 0>; + #iommu-cells = <1>; + dma-coherent; + }; + + pcie_ctlr: pcie@70000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0 0x70000000 0 0x1200000>; + bus-range = <0 17>; + linux,pci-domain = <0>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x75200000 0x00 0x00010000>, + <0x02000000 0x00 0x71200000 0x00 0x71200000 0x00 0x04000000>, + <0x42000000 0x09 0x00000000 0x09 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 169 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 170 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 171 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 172 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_pcie 0 0x10000>; + iommu-map = <0 &smmu_pcie 0 0x10000>; + status = "disabled"; + }; + + ccix_pcie_ctlr: pcie@68000000 { + compatible = "arm,n1sdp-pcie"; + device_type = "pci"; + reg = <0 0x68000000 0 0x1200000>; + bus-range = <0 17>; + linux,pci-domain = <1>; + #address-cells = <3>; + #size-cells = <2>; + dma-coherent; + ranges = <0x01000000 0x00 0x00000000 0x00 0x6d200000 0x00 0x00010000>, + <0x02000000 0x00 0x69200000 0x00 0x69200000 0x00 0x04000000>, + <0x42000000 0x29 0x00000000 0x29 0x00000000 0x20 0x00000000>; + #interrupt-cells = <1>; + interrupt-map-mask = <0 0 0 7>; + interrupt-map = <0 0 0 1 &gic 0 0 0 201 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 2 &gic 0 0 0 202 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 3 &gic 0 0 0 203 IRQ_TYPE_LEVEL_HIGH>, + <0 0 0 4 &gic 0 0 0 204 IRQ_TYPE_LEVEL_HIGH>; + msi-map = <0 &its_ccix 0 0x10000>; + iommu-map = <0 &smmu_ccix 0 0x10000>; + status = "disabled"; + }; + + soc_uart0: serial@2a400000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x2a400000 0x0 0x1000>; + interrupts = ; + clocks = <&soc_uartclk>, <&soc_refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi b/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi new file mode 100644 index 0000000..7a8af8e --- /dev/null +++ b/arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + #interrupt-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <15>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@40000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <11>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@50000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <9 10>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@60000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <12>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@70000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <13>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <5>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <6>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <7>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <8>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <2>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <3>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <14>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + mode = "XVGA"; + use_dma = <0>; + framebuffer = <0x18000000 0x00180000>; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0x2a>; + }; + }; + + v2m_fixed_3v3: fixedregulator@0 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc@1 { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga@0 { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode@0 { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi b/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi new file mode 100644 index 0000000..486f8a9 --- /dev/null +++ b/arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi @@ -0,0 +1,251 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + motherboard { + arm,v2m-memory-map = "rs1"; + compatible = "arm,vexpress,v2m-p1", "simple-bus"; + #address-cells = <2>; /* SMB chipselect number and offset */ + #size-cells = <1>; + ranges; + + flash@0,00000000 { + compatible = "arm,vexpress-flash", "cfi-flash"; + reg = <0 0x00000000 0x04000000>, + <4 0x00000000 0x04000000>; + bank-width = <4>; + }; + + vram@2,00000000 { + compatible = "arm,vexpress-vram"; + reg = <2 0x00000000 0x00800000>; + }; + + ethernet@2,02000000 { + compatible = "smsc,lan91c111"; + reg = <2 0x02000000 0x10000>; + interrupts = <0 15 4>; + }; + + v2m_clk24mhz: clk24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "v2m:clk24mhz"; + }; + + v2m_refclk1mhz: refclk1mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <1000000>; + clock-output-names = "v2m:refclk1mhz"; + }; + + v2m_refclk32khz: refclk32khz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <32768>; + clock-output-names = "v2m:refclk32khz"; + }; + + iofpga@3,00000000 { + compatible = "arm,amba-bus", "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 3 0 0x200000>; + + v2m_sysreg: sysreg@10000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x010000 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + v2m_sysctl: sysctl@20000 { + compatible = "arm,sp810", "arm,primecell"; + reg = <0x020000 0x1000>; + clocks = <&v2m_refclk32khz>, <&v2m_refclk1mhz>, <&v2m_clk24mhz>; + clock-names = "refclk", "timclk", "apb_pclk"; + #clock-cells = <1>; + clock-output-names = "timerclken0", "timerclken1", "timerclken2", "timerclken3"; + }; + + aaci@40000 { + compatible = "arm,pl041", "arm,primecell"; + reg = <0x040000 0x1000>; + interrupts = <0 11 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + mmci@50000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x050000 0x1000>; + interrupts = <0 9 4 0 10 4>; + cd-gpios = <&v2m_sysreg 0 0>; + wp-gpios = <&v2m_sysreg 1 0>; + max-frequency = <12000000>; + vmmc-supply = <&v2m_fixed_3v3>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + kmi@60000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x060000 0x1000>; + interrupts = <0 12 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@70000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x070000 0x1000>; + interrupts = <0 13 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + v2m_serial0: uart@90000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x090000 0x1000>; + interrupts = <0 5 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial1: uart@a0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0a0000 0x1000>; + interrupts = <0 6 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial2: uart@b0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0b0000 0x1000>; + interrupts = <0 7 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + v2m_serial3: uart@c0000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0c0000 0x1000>; + interrupts = <0 8 4>; + clocks = <&v2m_clk24mhz>, <&v2m_clk24mhz>; + clock-names = "uartclk", "apb_pclk"; + }; + + wdt@f0000 { + compatible = "arm,sp805", "arm,primecell"; + reg = <0x0f0000 0x1000>; + interrupts = <0 0 4>; + clocks = <&v2m_refclk32khz>, <&v2m_clk24mhz>; + clock-names = "wdogclk", "apb_pclk"; + }; + + v2m_timer01: timer@110000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x110000 0x1000>; + interrupts = <0 2 4>; + clocks = <&v2m_sysctl 0>, <&v2m_sysctl 1>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + v2m_timer23: timer@120000 { + compatible = "arm,sp804", "arm,primecell"; + reg = <0x120000 0x1000>; + interrupts = <0 3 4>; + clocks = <&v2m_sysctl 2>, <&v2m_sysctl 3>, <&v2m_clk24mhz>; + clock-names = "timclken1", "timclken2", "apb_pclk"; + }; + + rtc@170000 { + compatible = "arm,pl031", "arm,primecell"; + reg = <0x170000 0x1000>; + interrupts = <0 4 4>; + clocks = <&v2m_clk24mhz>; + clock-names = "apb_pclk"; + }; + + clcd@1f0000 { + compatible = "arm,pl111", "arm,primecell"; + reg = <0x1f0000 0x1000>; + interrupts = <0 14 4>; + clocks = <&v2m_oscclk1>, <&v2m_clk24mhz>; + clock-names = "clcdclk", "apb_pclk"; + mode = "XVGA"; + use_dma = <0>; + framebuffer = <0x18000000 0x00180000>; + }; + + virtio_block@130000 { + compatible = "virtio,mmio"; + reg = <0x130000 0x1000>; + interrupts = <0 0x2a 4>; + }; + }; + + v2m_fixed_3v3: fixedregulator { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mcc { + compatible = "arm,vexpress,config-bus", "simple-bus"; + arm,vexpress,config-bridge = <&v2m_sysreg>; + + v2m_oscclk1: osc { + /* CLCD clock */ + compatible = "arm,vexpress-osc"; + arm,vexpress-sysreg,func = <1 1>; + freq-range = <23750000 63500000>; + #clock-cells = <0>; + clock-output-names = "v2m:oscclk1"; + }; + + /* + * Not supported in FVP models + * + * reset@0 { + * compatible = "arm,vexpress-reset"; + * arm,vexpress-sysreg,func = <5 0>; + * }; + */ + + muxfpga { + compatible = "arm,vexpress-muxfpga"; + arm,vexpress-sysreg,func = <7 0>; + }; + + /* + * Not used - Superseded by PSCI sys_poweroff + * + * shutdown@0 { + * compatible = "arm,vexpress-shutdown"; + * arm,vexpress-sysreg,func = <8 0>; + * }; + */ + + /* + * Not used - Superseded by PSCI sys_reset + * + * reboot@0 { + * compatible = "arm,vexpress-reboot"; + * arm,vexpress-sysreg,func = <9 0>; + * }; + */ + + dvimode { + compatible = "arm,vexpress-dvimode"; + arm,vexpress-sysreg,func = <11 0>; + }; + }; + }; diff --git a/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi b/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi new file mode 100644 index 0000000..41d6e2e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi @@ -0,0 +1,130 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + */ + +/ { + aliases { +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-property/ mmc0; + /delete-property/ mmc1; +#endif + /delete-property/ ethernet0; + /delete-property/ ethernet1; + }; + + cpus { + cpu@0 { + /delete-property/ operating-points-v2; + }; + }; + + /delete-node/ cpu0-opp-table; + /delete-node/ psci; + + soc { + /delete-node/ sram@30000000; + /delete-node/ timer@40000000; + /delete-node/ timer@40001000; + /delete-node/ timer@40002000; + /delete-node/ timer@40003000; + /delete-node/ timer@40004000; + /delete-node/ timer@40005000; + /delete-node/ timer@40009000; + /delete-node/ spi@4000b000; + /delete-node/ audio-controller@4000b000; + /delete-node/ spi@4000c000; + /delete-node/ audio-controller@4000c000; + /delete-node/ audio-controller@4000d000; + /delete-node/ i2c@40012000; + /delete-node/ i2c@40013000; + /delete-node/ timer@44000000; + /delete-node/ timer@44001000; + /delete-node/ spi@44004000; + /delete-node/ audio-controller@44004000; + /delete-node/ sai@4400a000; + /delete-node/ sai@4400b000; + /delete-node/ dfsdm@4400d000; + /delete-node/ can@4400e000; + /delete-node/ can@4400f000; + /delete-node/ dma-controller@48000000; + /delete-node/ dma-controller@48001000; + /delete-node/ dma-router@48002000; + /delete-node/ adc@48003000; + /delete-node/ adc@48004000; + /delete-node/ dma@48005000; + /delete-node/ dma-router@48006000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usb-otg@49000000; +#endif + /delete-node/ spi@4c002000; + /delete-node/ spi@4c003000; + /delete-node/ timer@4c007000; + /delete-node/ timer@4c008000; + /delete-node/ timer@4c009000; + /delete-node/ timer@4c00a000; + /delete-node/ timer@4c00b000; + /delete-node/ timer@4c00c000; + /delete-node/ timer@50021000; + /delete-node/ timer@50022000; + /delete-node/ timer@50023000; + /delete-node/ timer@50024000; + /delete-node/ vrefbuf@50025000; + /delete-node/ thermal@50028000; + /delete-node/ hdp@5002a000; + /delete-node/ dma-controller@58000000; +#if !STM32MP_RAW_NAND + /delete-node/ memory-controller@58002000; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ spi@58003000; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; +#endif + /delete-node/ crc@58009000; + /delete-node/ stmmac-axi-config; + /delete-node/ eth1@5800a000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbh-ohci@5800c000; + /delete-node/ usbh-ehci@5800d000; +#endif + /delete-node/ eth2@5800e000; + /delete-node/ dcmipp@5a000000; + /delete-node/ display-controller@5a001000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbphyc@5a006000; +#endif + /delete-node/ perf@5a007000; + /delete-node/ rtc@5c004000; + /delete-node/ tamp@5c00a000; + /delete-node/ stgen@5c008000; + + pin-controller@50002000 { +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc2-b4-0; +#endif + }; + }; + + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + + st-io_policies { + fip-handles { + compatible = "st,io-fip-handle"; + fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; + 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"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi b/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi new file mode 100644 index 0000000..56eb36e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi @@ -0,0 +1,184 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +&ddr { + st,mem-name = DDR_MEM_NAME; + st,mem-speed = ; + st,mem-size = ; + + st,ctl-reg = < + DDR_MSTR + DDR_MRCTRL0 + DDR_MRCTRL1 + DDR_DERATEEN + DDR_DERATEINT + DDR_PWRCTL + DDR_PWRTMG + DDR_HWLPCTL + DDR_RFSHCTL0 + DDR_RFSHCTL3 + DDR_CRCPARCTL0 + DDR_ZQCTL0 + DDR_DFITMG0 + DDR_DFITMG1 + DDR_DFILPCFG0 + DDR_DFIUPD0 + DDR_DFIUPD1 + DDR_DFIUPD2 + DDR_DFIPHYMSTR + DDR_ODTMAP + DDR_DBG0 + DDR_DBG1 + DDR_DBGCMD + DDR_POISONCFG + DDR_PCCFG + >; + + st,ctl-timing = < + DDR_RFSHTMG + DDR_DRAMTMG0 + DDR_DRAMTMG1 + DDR_DRAMTMG2 + DDR_DRAMTMG3 + DDR_DRAMTMG4 + DDR_DRAMTMG5 + DDR_DRAMTMG6 + DDR_DRAMTMG7 + DDR_DRAMTMG8 + DDR_DRAMTMG14 + DDR_ODTCFG + >; + + st,ctl-map = < + DDR_ADDRMAP1 + DDR_ADDRMAP2 + DDR_ADDRMAP3 + DDR_ADDRMAP4 + DDR_ADDRMAP5 + DDR_ADDRMAP6 + DDR_ADDRMAP9 + DDR_ADDRMAP10 + DDR_ADDRMAP11 + >; + + st,ctl-perf = < + DDR_SCHED + DDR_SCHED1 + DDR_PERFHPR1 + DDR_PERFLPR1 + DDR_PERFWR1 + DDR_PCFGR_0 + DDR_PCFGW_0 + DDR_PCFGQOS0_0 + DDR_PCFGQOS1_0 + DDR_PCFGWQOS0_0 + DDR_PCFGWQOS1_0 + >; + + st,phy-reg = < + DDR_PGCR + DDR_ACIOCR + DDR_DXCCR + DDR_DSGCR + DDR_DCR + DDR_ODTCR + DDR_ZQ0CR1 + DDR_DX0GCR + DDR_DX1GCR + >; + + st,phy-timing = < + DDR_PTR0 + DDR_PTR1 + DDR_PTR2 + DDR_DTPR0 + DDR_DTPR1 + DDR_DTPR2 + DDR_MR0 + DDR_MR1 + DDR_MR2 + DDR_MR3 + >; +}; + +#undef DDR_MEM_NAME +#undef DDR_MEM_SPEED +#undef DDR_MEM_SIZE +#undef DDR_MSTR +#undef DDR_MRCTRL0 +#undef DDR_MRCTRL1 +#undef DDR_DERATEEN +#undef DDR_DERATEINT +#undef DDR_PWRCTL +#undef DDR_PWRTMG +#undef DDR_HWLPCTL +#undef DDR_RFSHCTL0 +#undef DDR_RFSHCTL3 +#undef DDR_RFSHTMG +#undef DDR_CRCPARCTL0 +#undef DDR_DRAMTMG0 +#undef DDR_DRAMTMG1 +#undef DDR_DRAMTMG2 +#undef DDR_DRAMTMG3 +#undef DDR_DRAMTMG4 +#undef DDR_DRAMTMG5 +#undef DDR_DRAMTMG6 +#undef DDR_DRAMTMG7 +#undef DDR_DRAMTMG8 +#undef DDR_DRAMTMG14 +#undef DDR_ZQCTL0 +#undef DDR_DFITMG0 +#undef DDR_DFITMG1 +#undef DDR_DFILPCFG0 +#undef DDR_DFIUPD0 +#undef DDR_DFIUPD1 +#undef DDR_DFIUPD2 +#undef DDR_DFIPHYMSTR +#undef DDR_ADDRMAP1 +#undef DDR_ADDRMAP2 +#undef DDR_ADDRMAP3 +#undef DDR_ADDRMAP4 +#undef DDR_ADDRMAP5 +#undef DDR_ADDRMAP6 +#undef DDR_ADDRMAP9 +#undef DDR_ADDRMAP10 +#undef DDR_ADDRMAP11 +#undef DDR_ODTCFG +#undef DDR_ODTMAP +#undef DDR_SCHED +#undef DDR_SCHED1 +#undef DDR_PERFHPR1 +#undef DDR_PERFLPR1 +#undef DDR_PERFWR1 +#undef DDR_DBG0 +#undef DDR_DBG1 +#undef DDR_DBGCMD +#undef DDR_POISONCFG +#undef DDR_PCCFG +#undef DDR_PCFGR_0 +#undef DDR_PCFGW_0 +#undef DDR_PCFGQOS0_0 +#undef DDR_PCFGQOS1_0 +#undef DDR_PCFGWQOS0_0 +#undef DDR_PCFGWQOS1_0 +#undef DDR_PGCR +#undef DDR_PTR0 +#undef DDR_PTR1 +#undef DDR_PTR2 +#undef DDR_ACIOCR +#undef DDR_DXCCR +#undef DDR_DSGCR +#undef DDR_DCR +#undef DDR_DTPR0 +#undef DDR_DTPR1 +#undef DDR_DTPR2 +#undef DDR_MR0 +#undef DDR_MR1 +#undef DDR_MR2 +#undef DDR_MR3 +#undef DDR_ODTCR +#undef DDR_ZQ0CR1 +#undef DDR_DX0GCR +#undef DDR_DX1GCR diff --git a/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi b/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi new file mode 100644 index 0000000..a5f7989 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi @@ -0,0 +1,100 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * STM32MP135C DISCO BOARD configuration + * 1x DDR3L 4Gb, 16-bit, 533MHz. + * Reference used MT41K256M16TW-107 P from Micron + * + * DDR type / Platform DDR3/3L + * freq 533MHz + * width 16 + * datasheet 1 + * DDR density 4 + * timing mode optimized + * Scheduling/QoS options : type = 6 + * address mapping : RBC + * Tc > + 85C : N + */ +#define DDR_MEM_NAME "DDR3-1066 bin F 1x4Gb 533MHz v1.53" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00040401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041B +#define DDR_DRAMTMG2 0x0607080F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x07040607 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02050105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ADDRMAP1 0x00080808 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x00000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x07070707 +#define DDR_ADDRMAP6 0x0F070707 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000F01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x00000001 +#define DDR_PERFLPR1 0x04000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00000000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x00100009 +#define DDR_PCFGQOS1_0 0x00000020 +#define DDR_PCFGWQOS0_0 0x01100B03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x36D477D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000830 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 + +#include "stm32mp13-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi b/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi new file mode 100644 index 0000000..dc8ca1b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + */ + +#include +#include + +#include + +#ifndef DDR_SIZE +#error "DDR_SIZE is not defined" +#endif + +#define DDR_NS_BASE STM32MP_DDR_BASE +#define DDR_SEC_SIZE 0x01e00000 +#define DDR_SEC_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SEC_SIZE)) +#define DDR_SHARE_SIZE 0x00200000 +#define DDR_SHARE_BASE (DDR_SEC_BASE - DDR_SHARE_SIZE) +#define DDR_NS_SIZE (DDR_SHARE_BASE - DDR_NS_BASE) + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + hw-config { + load-address = <0x0 STM32MP_HW_CONFIG_BASE>; + max-size = ; + id = ; + }; + + nt_fw { + load-address = <0x0 STM32MP_BL33_BASE>; + max-size = ; + id = ; + }; + + tos_fw { + load-address = <0x0 DDR_SEC_BASE>; + max-size = ; + id = ; + }; + }; + + st-mem-firewall { + compatible = "st,mem-firewall"; + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR + DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) + DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi new file mode 100644 index 0000000..0ad06a4 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue + */ +#include + +&pinctrl { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + usart1_pins_a: usart1-0 { + pins1 { + pinmux = , /* USART1_TX */ + ; /* USART1_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART1_RX */ + ; /* USART1_CTS_NSS */ + bias-pull-up; + }; + }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-pull-up; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp131.dtsi b/arm-trusted-firmware/fdts/stm32mp131.dtsi new file mode 100644 index 0000000..dff1b33 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp131.dtsi @@ -0,0 +1,621 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; + clocks = <&rcc CK_MPU>; + clock-names = "cpu"; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; + }; + }; + + nvmem_layout: nvmem_layout@0 { + compatible = "st,stm32-nvmem-layout"; + + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&nand2_otp>, + <&uid_otp>, + <&hw2_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "nand2_otp", + "uid_otp", + "hw2_otp"; + }; + + clocks { + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts = ; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts = ; + clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts = ; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts = ; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts = ; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts = ; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; + reg = <0x49000000 0x40000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts = ; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + usb33d-supply = <&usb33>; + status = "disabled"; + }; + + usart1: serial@4c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c000000 0x400>; + interrupts = ; + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + usart2: serial@4c001000 { + compatible = "st,stm32h7-uart"; + reg = <0x4c001000 0x400>; + interrupts = ; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; + }; + + i2c3: i2c@4c004000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c004000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 23 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 74 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C3_K>; + resets = <&rcc I2C3_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x4>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c4: i2c@4c005000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c005000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 94 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + i2c-analog-filter; + status = "disabled"; + }; + + i2c5: i2c@4c006000 { + compatible = "st,stm32mp13-i2c"; + reg = <0x4c006000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 25 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 115 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C5_K>; + resets = <&rcc I2C5_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x10>; + i2c-analog-filter; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp13-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = ; + secure-interrupts = ; + secure-interrupt-names = "wakeup"; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + + reg11: reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18: reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33: usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp13-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + vrefbuf: vrefbuf@50025000 { + compatible = "st,stm32-vrefbuf"; + reg = <0x50025000 0x8>; + regulator-min-microvolt = <1500000>; + regulator-max-microvolt = <2500000>; + clocks = <&rcc VREF>; + status = "disabled"; + }; + + hash: hash@54003000 { + compatible = "st,stm32mp13-hash"; + reg = <0x54003000 0x400>; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + + rng: rng@54004000 { + compatible = "st,stm32mp13-rng"; + reg = <0x54004000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; + }; + + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + status = "disabled"; + }; + }; + + qspi: spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + status = "disabled"; + }; + + sdmmc1: mmc@58005000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x20253180>; + reg = <0x58005000 0x1000>, <0x58006000 0x1000>; + clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC1_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + sdmmc2: mmc@58007000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x20253180>; + reg = <0x58007000 0x1000>, <0x58008000 0x1000>; + clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC2_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + crc1: crc@58009000 { + compatible = "st,stm32f7-crc"; + reg = <0x58009000 0x400>; + clocks = <&rcc CRC1>; + }; + + usbh_ohci: usbh-ohci@5800c000 { + compatible = "generic-ohci"; + reg = <0x5800c000 0x1000>; + clocks = <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + status = "disabled"; + }; + + usbh_ehci: usbh-ehci@5800d000 { + compatible = "generic-ehci"; + reg = <0x5800d000 0x1000>; + clocks = <&rcc USBH>; + resets = <&rcc USBH_R>; + interrupts = ; + companion = <&usbh_ohci>; + status = "disabled"; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + ddr: ddr@5a003000{ + compatible = "st,stm32mp13-ddr"; + reg = <0x5a003000 0x550>, <0x5a004000 0x234>; + clocks = <&rcc AXIDCG>, + <&rcc DDRC1>, + <&rcc DDRPHYC>, + <&rcc DDRCAPB>, + <&rcc DDRPHYCAPB>; + clock-names = "axidcg", + "ddrc1", + "ddrphyc", + "ddrcapb", + "ddrphycapb"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { + #phy-cells = <0>; + reg = <0>; + }; + + usbphyc_port1: usb-phy@1 { + #phy-cells = <1>; + reg = <1>; + }; + }; + + iwdg1: watchdog@5c003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5c003000 0x400>; + interrupts = ; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x2>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x2>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: cfg9_otp@24 { + reg = <0x24 0x4>; + }; + nand2_otp: cfg10_otp@28 { + reg = <0x28 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + pkh_otp: pkh_otp@60 { + reg = <0x60 0x20>; + }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0xc>; + st,non-secure-otp; + }; + }; + + tamp: tamp@5c00a000 { + reg = <0x5c00a000 0x400>; + }; + + /* + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ + pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp135-pinctrl"; + ranges = <0 0x50002000 0x8400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA>; + st,bank-name = "GPIOA"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOB>; + st,bank-name = "GPIOB"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOC>; + st,bank-name = "GPIOC"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x3000 0x400>; + clocks = <&rcc GPIOD>; + st,bank-name = "GPIOD"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4000 0x400>; + clocks = <&rcc GPIOE>; + st,bank-name = "GPIOE"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000 0x400>; + clocks = <&rcc GPIOF>; + st,bank-name = "GPIOF"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x6000 0x400>; + clocks = <&rcc GPIOG>; + st,bank-name = "GPIOG"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x7000 0x400>; + clocks = <&rcc GPIOH>; + st,bank-name = "GPIOH"; + ngpios = <15>; + gpio-ranges = <&pinctrl 0 112 15>; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x8000 0x400>; + clocks = <&rcc GPIOI>; + st,bank-name = "GPIOI"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 128 8>; + }; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp133.dtsi b/arm-trusted-firmware/fdts/stm32mp133.dtsi new file mode 100644 index 0000000..8bbcc61 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp133.dtsi @@ -0,0 +1,21 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp131.dtsi" + +/ { + soc { + m_can1: can@4400e000 { + reg = <0x4400e000 0x400>, <0x44011000 0x1400>; + status = "disabled"; + }; + + m_can2: can@4400f000 { + reg = <0x4400f000 0x400>, <0x44011000 0x2800>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp135.dtsi b/arm-trusted-firmware/fdts/stm32mp135.dtsi new file mode 100644 index 0000000..415bb9b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135.dtsi @@ -0,0 +1,12 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp133.dtsi" + +/ { + soc { + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts new file mode 100644 index 0000000..21f8242 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp13-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp135f-dk.dts b/arm-trusted-firmware/fdts/stm32mp135f-dk.dts new file mode 100644 index 0000000..0fa064b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp135f-dk.dts @@ -0,0 +1,353 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include +#include "stm32mp135.dtsi" +#include "stm32mp13xf.dtsi" +#include "stm32mp13-ddr3-1x4Gb-1066-binF.dtsi" +#include "stm32mp13-pinctrl.dtsi" + +/ { + model = "STMicroelectronics STM32MP135F-DK Discovery Board"; + compatible = "st,stm32mp135f-dk", "st,stm32mp135"; + + aliases { + serial0 = &uart4; + serial1 = &usart1; + serial2 = &uart8; + serial3 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; + + v3v3_ao: v3v3_ao { + compatible = "regulator-fixed"; + regulator-name = "v3v3_ao"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@f0 { + reg = <0xf0 0x4>; + st,non-secure-otp; + }; +}; + +&cpu0 { + cpu-supply = <&vddcpu>; +}; + +&hash { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "disabled"; + secure-status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + + status = "disabled"; + secure-status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&vin>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&vin>; + vref_ddr-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&v3v3_ao>; + + vddcpu: buck1 { + regulator-name = "vddcpu"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-over-current-protection; + }; + + vddcore: buck4 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1250000>; + regulator-max-microvolt = <1250000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_adc: ldo1 { + regulator-name = "vdd_adc"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-boot-on; + }; + + v1v8_periph: ldo6 { + regulator-name = "v1v8_periph"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + v3v3_sw: pwr_sw2 { + regulator-name = "v3v3_sw"; + regulator-active-discharge = <1>; + regulator-always-on; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&nand2_otp>, + <&uid_otp>, + <&hw2_otp>, + <&pkh_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "nand2_otp", + "uid_otp", + "hw2_otp", + "pkh_otp", + "board_id"; +}; + +&pka { + secure-status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MLAHBS_PLL3 + CLK_CKPER_HSE + CLK_RTC_LSE + CLK_SDMMC1_PLL4P + CLK_SDMMC2_PLL4P + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_I2C4_HSI + CLK_USBO_USBPHY + CLK_I2C12_HSI + CLK_UART2_HSI + CLK_UART4_HSI + CLK_SAES_AXI + >; + + st,clkdiv = < + DIV(DIV_AXI, 0) + DIV(DIV_MLAHB, 0) + DIV(DIV_APB1, 1) + DIV(DIV_APB2, 1) + DIV(DIV_APB3, 1) + DIV(DIV_APB4, 1) + DIV(DIV_APB5, 2) + DIV(DIV_APB6, 1) + DIV(DIV_RTC, 0) + >; + + st,pll_vco { + pll1_vco_1300Mhz: pll1-vco-1300Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 80 >; + frac = < 0x800 >; + }; + + pll2_vco_1066Mhz: pll2-vco-1066Mhz { + src = < CLK_PLL12_HSE >; + divmn = < 2 65 >; + frac = < 0x1400 >; + }; + + pll3_vco_417_8Mhz: pll2-vco-417_8Mhz { + src = < CLK_PLL3_HSE >; + divmn = < 1 33 >; + frac = < 0x1a04 >; + }; + + pll4_vco_600Mhz: pll2-vco-600Mhz { + src = < CLK_PLL4_HSE >; + divmn = < 1 49 >; + }; + }; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1:st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + + st,pll = < &pll1_cfg1 >; + + pll1_cfg1: pll1_cfg1 { + st,pll_vco = < &pll1_vco_1300Mhz >; + st,pll_div_pqr = < 0 1 1 >; + }; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 266, R = 533 (DDR) */ + pll2:st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + + st,pll = < &pll2_cfg1 >; + + pll2_cfg1: pll2_cfg1 { + st,pll_vco = < &pll2_vco_1066Mhz >; + st,pll_div_pqr = < 1 1 0 >; + }; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 209 */ + pll3:st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + + st,pll = < &pll3_cfg1 >; + + pll3_cfg1: pll3_cfg1 { + st,pll_vco = < &pll3_vco_417_8Mhz >; + st,pll_div_pqr = < 1 16 1 >; + }; + }; + + /* VCO = 600.0 MHz => P = 50, Q = 10, R = 100 */ + pll4:st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + + st,pll = < &pll4_cfg1 >; + + pll4_cfg1: pll4_cfg1 { + st,pll_vco = < &pll4_vco_600Mhz >; + st,pll_div_pqr = < 11 59 5 >; + }; + }; +}; + +&rng { + status = "okay"; +}; + +&saes { + secure-status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&uart8 { + pinctrl-names = "default"; + pinctrl-0 = <&uart8_pins_a>; + status = "disabled"; +}; + +&usart1 { + pinctrl-names = "default"; + pinctrl-0 = <&usart1_pins_a>; + uart-has-rtscts; + status = "disabled"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13xa.dtsi b/arm-trusted-firmware/fdts/stm32mp13xa.dtsi new file mode 100644 index 0000000..0ef2fce --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xa.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ diff --git a/arm-trusted-firmware/fdts/stm32mp13xc.dtsi b/arm-trusted-firmware/fdts/stm32mp13xc.dtsi new file mode 100644 index 0000000..c03bd43 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xc.dtsi @@ -0,0 +1,36 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp13xa.dtsi" + +/ { + soc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32-saes"; + reg = <0x54005000 0x400>; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32-pka64"; + reg = <0x54006000 0x2000>; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp13xd.dtsi b/arm-trusted-firmware/fdts/stm32mp13xd.dtsi new file mode 100644 index 0000000..0ef2fce --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xd.dtsi @@ -0,0 +1,5 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ diff --git a/arm-trusted-firmware/fdts/stm32mp13xf.dtsi b/arm-trusted-firmware/fdts/stm32mp13xf.dtsi new file mode 100644 index 0000000..e467d71 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp13xf.dtsi @@ -0,0 +1,35 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ +#include "stm32mp13xd.dtsi" + +/ { + soc { + cryp: crypto@54002000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + + saes: saes@54005000 { + compatible = "st,stm32-saes"; + reg = <0x54005000 0x400>; + clocks = <&rcc SAES_K>; + resets = <&rcc SAES_R>; + status = "disabled"; + }; + + pka: pka@54006000 { + compatible = "st,stm32-pka64"; + reg = <0x54006000 0x2000>; + clocks = <&rcc PKA>; + resets = <&rcc PKA_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi b/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi new file mode 100644 index 0000000..d00e35b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi @@ -0,0 +1,92 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2020-2022 - All Rights Reserved + */ + +/ { +#if !STM32MP_EMMC && !STM32MP_SDMMC + aliases { + /delete-property/ mmc0; + /delete-property/ mmc1; + }; +#endif + + cpus { + /delete-node/ cpu@1; + }; + + /delete-node/ psci; + + soc { + /delete-node/ timer@40006000; + /delete-node/ timer@44006000; +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usb-otg@49000000; +#endif + /delete-node/ pwr_mcu@50001014; + /delete-node/ cryp@54001000; + /delete-node/ rng@54003000; +#if !STM32MP_RAW_NAND + /delete-node/ memory-controller@58002000; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ spi@58003000; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; +#endif +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbphyc@5a006000; +#endif + /delete-node/ spi@5c001000; + /delete-node/ rtc@5c004000; + /delete-node/ etzpc@5c007000; + /delete-node/ stgen@5c008000; + /delete-node/ i2c@5c009000; + /delete-node/ tamp@5c00a000; + + pin-controller@50002000 { +#if !STM32MP_RAW_NAND + /delete-node/ fmc-0; +#endif +#if !STM32MP_SPI_NAND && !STM32MP_SPI_NOR + /delete-node/ qspi-clk-0; + /delete-node/ qspi-bk1-0; + /delete-node/ qspi-bk2-0; +#endif +#if !STM32MP_EMMC && !STM32MP_SDMMC + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc1-dir-0; + /delete-node/ sdmmc2-b4-0; + /delete-node/ sdmmc2-b4-1; + /delete-node/ sdmmc2-d47-0; +#endif +#if !STM32MP_USB_PROGRAMMER + /delete-node/ usbotg_hs-0; + /delete-node/ usbotg-fs-dp-dm-0; +#endif + }; + }; + +#if !STM32MP_USE_STM32IMAGE + /* + * UUID's here are UUID RFC 4122 compliant meaning fieds are stored in + * network order (big endian) + */ + + st-io_policies { + fip-handles { + compatible = "st,io-fip-handle"; + fw_cfg_uuid = "5807e16a-8459-47be-8ed5-648e8dddab0e"; + 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"; + tos_fw_cfg_uuid = "26257c1a-dbc6-7f47-8d96-c4c4b0248021"; + nt_fw_cfg_uuid = "28da9815-93e8-7e44-ac66-1aaf801550f9"; + }; + }; +#endif /* !STM32MP_USE_STM32IMAGE */ +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi b/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi new file mode 100644 index 0000000..ca4bb3e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2020-2021 - All Rights Reserved + */ + +/ { + aliases { + /delete-property/ mmc0; + /delete-property/ mmc1; + }; + + cpus { + /delete-node/ cpu@1; + }; + + /delete-node/ psci; + + soc { + /delete-node/ usb-otg@49000000; + /delete-node/ hash@54002000; + /delete-node/ memory-controller@58002000; + /delete-node/ spi@58003000; + /delete-node/ mmc@58005000; + /delete-node/ mmc@58007000; + /delete-node/ usbphyc@5a006000; + /delete-node/ spi@5c001000; + /delete-node/ stgen@5c008000; + /delete-node/ i2c@5c009000; + + pin-controller@50002000 { + /delete-node/ fmc-0; + /delete-node/ qspi-clk-0; + /delete-node/ qspi-bk1-0; + /delete-node/ qspi-bk2-0; + /delete-node/ sdmmc1-b4-0; + /delete-node/ sdmmc1-dir-0; + /delete-node/ sdmmc2-b4-0; + /delete-node/ sdmmc2-b4-1; + /delete-node/ sdmmc2-d47-0; + /delete-node/ sdmmc2-d47-1; + /delete-node/ sdmmc2-d47-3; + /delete-node/ usbotg_hs-0; + /delete-node/ usbotg-fs-dp-dm-0; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi new file mode 100644 index 0000000..d0b3a17 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi @@ -0,0 +1,112 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +&ddr { + st,mem-name = DDR_MEM_NAME; + st,mem-speed = ; + st,mem-size = ; + + st,ctl-reg = < + DDR_MSTR + DDR_MRCTRL0 + DDR_MRCTRL1 + DDR_DERATEEN + DDR_DERATEINT + DDR_PWRCTL + DDR_PWRTMG + DDR_HWLPCTL + DDR_RFSHCTL0 + DDR_RFSHCTL3 + DDR_CRCPARCTL0 + DDR_ZQCTL0 + DDR_DFITMG0 + DDR_DFITMG1 + DDR_DFILPCFG0 + DDR_DFIUPD0 + DDR_DFIUPD1 + DDR_DFIUPD2 + DDR_DFIPHYMSTR + DDR_ODTMAP + DDR_DBG0 + DDR_DBG1 + DDR_DBGCMD + DDR_POISONCFG + DDR_PCCFG + >; + + st,ctl-timing = < + DDR_RFSHTMG + DDR_DRAMTMG0 + DDR_DRAMTMG1 + DDR_DRAMTMG2 + DDR_DRAMTMG3 + DDR_DRAMTMG4 + DDR_DRAMTMG5 + DDR_DRAMTMG6 + DDR_DRAMTMG7 + DDR_DRAMTMG8 + DDR_DRAMTMG14 + DDR_ODTCFG + >; + + st,ctl-map = < + DDR_ADDRMAP1 + DDR_ADDRMAP2 + DDR_ADDRMAP3 + DDR_ADDRMAP4 + DDR_ADDRMAP5 + DDR_ADDRMAP6 + DDR_ADDRMAP9 + DDR_ADDRMAP10 + DDR_ADDRMAP11 + >; + + st,ctl-perf = < + DDR_SCHED + DDR_SCHED1 + DDR_PERFHPR1 + DDR_PERFLPR1 + DDR_PERFWR1 + DDR_PCFGR_0 + DDR_PCFGW_0 + DDR_PCFGQOS0_0 + DDR_PCFGQOS1_0 + DDR_PCFGWQOS0_0 + DDR_PCFGWQOS1_0 + DDR_PCFGR_1 + DDR_PCFGW_1 + DDR_PCFGQOS0_1 + DDR_PCFGQOS1_1 + DDR_PCFGWQOS0_1 + DDR_PCFGWQOS1_1 + >; + + st,phy-reg = < + DDR_PGCR + DDR_ACIOCR + DDR_DXCCR + DDR_DSGCR + DDR_DCR + DDR_ODTCR + DDR_ZQ0CR1 + DDR_DX0GCR + DDR_DX1GCR + DDR_DX2GCR + DDR_DX3GCR + >; + + st,phy-timing = < + DDR_PTR0 + DDR_PTR1 + DDR_PTR2 + DDR_DTPR0 + DDR_DTPR1 + DDR_DTPR2 + DDR_MR0 + DDR_MR1 + DDR_MR2 + DDR_MR3 + >; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi new file mode 100644 index 0000000..5d1001d --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +/* + * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs + * DDR type: DDR3 / DDR3L + * DDR width: 16bits + * DDR density: 4Gb + * System frequency: 533000Khz + * Relaxed Timing Mode: false + * Address mapping type: RBC + * + * Save Date: 2020.02.20, save Time: 18:45:20 + */ + +#define DDR_MEM_NAME "DDR3-DDR3L 16bits 533000kHz" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x20000000 + +#define DDR_MSTR 0x00041401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041C +#define DDR_DRAMTMG2 0x0608090F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x08040608 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02060105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x01000001 +#define DDR_PERFLPR1 0x08000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00010000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_ADDRMAP1 0x00070707 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x1F000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x06060606 +#define DDR_ADDRMAP6 0x0F060606 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x38D488D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000840 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 +#define DDR_DX2GCR 0x0000CE80 +#define DDR_DX3GCR 0x0000CE80 + +#include "stm32mp15-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi b/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi new file mode 100644 index 0000000..6494ceb --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi @@ -0,0 +1,107 @@ +// SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + */ + +/* + * File generated by STMicroelectronics STM32CubeMX DDR Tool for MPUs + * DDR type: DDR3 / DDR3L + * DDR width: 32bits + * DDR density: 8Gb + * System frequency: 533000Khz + * Relaxed Timing Mode: false + * Address mapping type: RBC + * + * Save Date: 2020.02.20, save Time: 18:49:33 + */ + +#define DDR_MEM_NAME "DDR3-DDR3L 32bits 533000kHz" +#define DDR_MEM_SPEED 533000 +#define DDR_MEM_SIZE 0x40000000 + +#define DDR_MSTR 0x00040401 +#define DDR_MRCTRL0 0x00000010 +#define DDR_MRCTRL1 0x00000000 +#define DDR_DERATEEN 0x00000000 +#define DDR_DERATEINT 0x00800000 +#define DDR_PWRCTL 0x00000000 +#define DDR_PWRTMG 0x00400010 +#define DDR_HWLPCTL 0x00000000 +#define DDR_RFSHCTL0 0x00210000 +#define DDR_RFSHCTL3 0x00000000 +#define DDR_RFSHTMG 0x0081008B +#define DDR_CRCPARCTL0 0x00000000 +#define DDR_DRAMTMG0 0x121B2414 +#define DDR_DRAMTMG1 0x000A041C +#define DDR_DRAMTMG2 0x0608090F +#define DDR_DRAMTMG3 0x0050400C +#define DDR_DRAMTMG4 0x08040608 +#define DDR_DRAMTMG5 0x06060403 +#define DDR_DRAMTMG6 0x02020002 +#define DDR_DRAMTMG7 0x00000202 +#define DDR_DRAMTMG8 0x00001005 +#define DDR_DRAMTMG14 0x000000A0 +#define DDR_ZQCTL0 0xC2000040 +#define DDR_DFITMG0 0x02060105 +#define DDR_DFITMG1 0x00000202 +#define DDR_DFILPCFG0 0x07000000 +#define DDR_DFIUPD0 0xC0400003 +#define DDR_DFIUPD1 0x00000000 +#define DDR_DFIUPD2 0x00000000 +#define DDR_DFIPHYMSTR 0x00000000 +#define DDR_ODTCFG 0x06000600 +#define DDR_ODTMAP 0x00000001 +#define DDR_SCHED 0x00000C01 +#define DDR_SCHED1 0x00000000 +#define DDR_PERFHPR1 0x01000001 +#define DDR_PERFLPR1 0x08000200 +#define DDR_PERFWR1 0x08000400 +#define DDR_DBG0 0x00000000 +#define DDR_DBG1 0x00000000 +#define DDR_DBGCMD 0x00000000 +#define DDR_POISONCFG 0x00000000 +#define DDR_PCCFG 0x00000010 +#define DDR_PCFGR_0 0x00010000 +#define DDR_PCFGW_0 0x00000000 +#define DDR_PCFGQOS0_0 0x02100C03 +#define DDR_PCFGQOS1_0 0x00800100 +#define DDR_PCFGWQOS0_0 0x01100C03 +#define DDR_PCFGWQOS1_0 0x01000200 +#define DDR_PCFGR_1 0x00010000 +#define DDR_PCFGW_1 0x00000000 +#define DDR_PCFGQOS0_1 0x02100C03 +#define DDR_PCFGQOS1_1 0x00800040 +#define DDR_PCFGWQOS0_1 0x01100C03 +#define DDR_PCFGWQOS1_1 0x01000200 +#define DDR_ADDRMAP1 0x00080808 +#define DDR_ADDRMAP2 0x00000000 +#define DDR_ADDRMAP3 0x00000000 +#define DDR_ADDRMAP4 0x00001F1F +#define DDR_ADDRMAP5 0x07070707 +#define DDR_ADDRMAP6 0x0F070707 +#define DDR_ADDRMAP9 0x00000000 +#define DDR_ADDRMAP10 0x00000000 +#define DDR_ADDRMAP11 0x00000000 +#define DDR_PGCR 0x01442E02 +#define DDR_PTR0 0x0022AA5B +#define DDR_PTR1 0x04841104 +#define DDR_PTR2 0x042DA068 +#define DDR_ACIOCR 0x10400812 +#define DDR_DXCCR 0x00000C40 +#define DDR_DSGCR 0xF200011F +#define DDR_DCR 0x0000000B +#define DDR_DTPR0 0x38D488D0 +#define DDR_DTPR1 0x098B00D8 +#define DDR_DTPR2 0x10023600 +#define DDR_MR0 0x00000840 +#define DDR_MR1 0x00000000 +#define DDR_MR2 0x00000208 +#define DDR_MR3 0x00000000 +#define DDR_ODTCR 0x00010000 +#define DDR_ZQ0CR1 0x00000038 +#define DDR_DX0GCR 0x0000CE81 +#define DDR_DX1GCR 0x0000CE81 +#define DDR_DX2GCR 0x0000CE81 +#define DDR_DX3GCR 0x0000CE81 + +#include "stm32mp15-ddr.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi b/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi new file mode 100644 index 0000000..8aece28 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi @@ -0,0 +1,80 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#include +#include + +#include + +#ifndef DDR_SIZE +#error "DDR_SIZE is not defined" +#endif + +#define DDR_NS_BASE STM32MP_DDR_BASE +#ifdef AARCH32_SP_OPTEE +/* OP-TEE reserved shared memory: located at DDR top */ +#define DDR_SHARE_SIZE STM32MP_DDR_SHMEM_SIZE +#define DDR_SHARE_BASE (STM32MP_DDR_BASE + (DDR_SIZE - DDR_SHARE_SIZE)) +/* OP-TEE secure memory: located right below OP-TEE reserved shared memory */ +#define DDR_SEC_SIZE STM32MP_DDR_S_SIZE +#define DDR_SEC_BASE (DDR_SHARE_BASE - DDR_SEC_SIZE) +#define DDR_NS_SIZE (DDR_SEC_BASE - DDR_NS_BASE) +#else /* !AARCH32_SP_OPTEE */ +#define DDR_NS_SIZE DDR_SIZE +#endif /* AARCH32_SP_OPTEE */ + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + hw-config { + load-address = <0x0 STM32MP_HW_CONFIG_BASE>; + max-size = ; + id = ; + }; + + nt_fw { + load-address = <0x0 STM32MP_BL33_BASE>; + max-size = ; + id = ; + }; + +#ifdef AARCH32_SP_OPTEE + tos_fw { + load-address = <0x0 STM32MP_OPTEE_BASE>; + max-size = ; + id = ; + }; +#else + tos_fw { + load-address = <0x0 STM32MP_BL32_BASE>; + max-size = ; + id = ; + }; + + tos_fw-config { + load-address = <0x0 STM32MP_BL32_DTB_BASE>; + max-size = ; + id = ; + }; +#endif + }; + + st-mem-firewall { + compatible = "st,mem-firewall"; +#ifdef AARCH32_SP_OPTEE + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR + DDR_SEC_BASE DDR_SEC_SIZE TZC_REGION_S_RDWR 0 + DDR_SHARE_BASE DDR_SHARE_SIZE TZC_REGION_S_NONE + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID)>; +#else + memory-ranges = < + DDR_NS_BASE DDR_NS_SIZE TZC_REGION_S_NONE TZC_REGION_NSEC_ALL_ACCESS_RDWR>; +#endif + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi new file mode 100644 index 0000000..d74dc2b --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi @@ -0,0 +1,386 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include + +&pinctrl { + fmc_pins_a: fmc-0 { + pins1 { + pinmux = , /* FMC_NOE */ + , /* FMC_NWE */ + , /* FMC_A16_FMC_CLE */ + , /* FMC_A17_FMC_ALE */ + , /* FMC_D0 */ + , /* FMC_D1 */ + , /* FMC_D2 */ + , /* FMC_D3 */ + , /* FMC_D4 */ + , /* FMC_D5 */ + , /* FMC_D6 */ + , /* FMC_D7 */ + ; /* FMC_NE2_FMC_NCE */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* FMC_NWAIT */ + bias-pull-up; + }; + }; + + i2c2_pins_a: i2c2-0 { + pins { + pinmux = , /* I2C2_SCL */ + ; /* I2C2_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; + + qspi_clk_pins_a: qspi-clk-0 { + pins { + pinmux = ; /* QSPI_CLK */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + }; + + qspi_bk1_pins_a: qspi-bk1-0 { + pins1 { + pinmux = , /* QSPI_BK1_IO0 */ + , /* QSPI_BK1_IO1 */ + , /* QSPI_BK1_IO2 */ + ; /* QSPI_BK1_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK1_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + qspi_bk2_pins_a: qspi-bk2-0 { + pins1 { + pinmux = , /* QSPI_BK2_IO0 */ + , /* QSPI_BK2_IO1 */ + , /* QSPI_BK2_IO2 */ + ; /* QSPI_BK2_IO3 */ + bias-disable; + drive-push-pull; + slew-rate = <1>; + }; + pins2 { + pinmux = ; /* QSPI_BK2_NCS */ + bias-pull-up; + drive-push-pull; + slew-rate = <1>; + }; + }; + + sdmmc1_b4_pins_a: sdmmc1-b4-0 { + pins1 { + pinmux = , /* SDMMC1_D0 */ + , /* SDMMC1_D1 */ + , /* SDMMC1_D2 */ + , /* SDMMC1_D3 */ + ; /* SDMMC1_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC1_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc1_dir_pins_a: sdmmc1-dir-0 { + pins1 { + pinmux = , /* SDMMC1_D0DIR */ + , /* SDMMC1_D123DIR */ + ; /* SDMMC1_CDIR */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2{ + pinmux = ; /* SDMMC1_CKIN */ + bias-pull-up; + }; + }; + + sdmmc2_b4_pins_a: sdmmc2-b4-0 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_b4_pins_b: sdmmc2-b4-1 { + pins1 { + pinmux = , /* SDMMC2_D0 */ + , /* SDMMC2_D1 */ + , /* SDMMC2_D2 */ + , /* SDMMC2_D3 */ + ; /* SDMMC2_CMD */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + pins2 { + pinmux = ; /* SDMMC2_CK */ + slew-rate = <2>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_d47_pins_a: sdmmc2-d47-0 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-pull-up; + }; + }; + + sdmmc2_d47_pins_b: sdmmc2-d47-1 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + slew-rate = <1>; + drive-push-pull; + bias-disable; + }; + }; + + sdmmc2_d47_pins_d: sdmmc2-d47-3 { + pins { + pinmux = , /* SDMMC2_D4 */ + , /* SDMMC2_D5 */ + , /* SDMMC2_D6 */ + ; /* SDMMC2_D7 */ + }; + }; + + uart4_pins_a: uart4-0 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart4_pins_b: uart4-1 { + pins1 { + pinmux = ; /* UART4_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART4_RX */ + bias-disable; + }; + }; + + uart7_pins_a: uart7-0 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* UART7_RX */ + , /* UART7_CTS */ + ; /* UART7_RTS */ + bias-disable; + }; + }; + + uart7_pins_b: uart7-1 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-disable; + }; + }; + + uart7_pins_c: uart7-2 { + pins1 { + pinmux = ; /* UART7_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART7_RX */ + bias-disable; + }; + }; + + uart8_pins_a: uart8-0 { + pins1 { + pinmux = ; /* UART8_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* UART8_RX */ + bias-disable; + }; + }; + + usart2_pins_a: usart2-0 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_pins_b: usart2-1 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart2_pins_c: usart2-2 { + pins1 { + pinmux = , /* USART2_TX */ + ; /* USART2_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <3>; + }; + pins2 { + pinmux = , /* USART2_RX */ + ; /* USART2_CTS_NSS */ + bias-disable; + }; + }; + + usart3_pins_a: usart3-0 { + pins1 { + pinmux = ; /* USART3_TX */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = ; /* USART3_RX */ + bias-disable; + }; + }; + + usart3_pins_b: usart3-1 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + + usart3_pins_c: usart3-2 { + pins1 { + pinmux = , /* USART3_TX */ + ; /* USART3_RTS */ + bias-disable; + drive-push-pull; + slew-rate = <0>; + }; + pins2 { + pinmux = , /* USART3_RX */ + ; /* USART3_CTS_NSS */ + bias-disable; + }; + }; + + usbotg_hs_pins_a: usbotg-hs-0 { + pins { + pinmux = ; /* OTG_ID */ + }; + }; + + usbotg_fs_dp_dm_pins_a: usbotg-fs-dp-dm-0 { + pins { + pinmux = , /* OTG_FS_DM */ + ; /* OTG_FS_DP */ + }; + }; +}; + +&pinctrl_z { + i2c4_pins_a: i2c4-0 { + pins { + pinmux = , /* I2C4_SCL */ + ; /* I2C4_SDA */ + bias-disable; + drive-open-drain; + slew-rate = <0>; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp151.dtsi b/arm-trusted-firmware/fdts/stm32mp151.dtsi new file mode 100644 index 0000000..454e124 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp151.dtsi @@ -0,0 +1,708 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +#include +#include +#include + +/ { + #address-cells = <1>; + #size-cells = <1>; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu0: cpu@0 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <0>; + nvmem-cells = <&part_number_otp>; + nvmem-cell-names = "part_number"; + }; + }; + + nvmem_layout: nvmem_layout@0 { + compatible = "st,stm32-nvmem-layout"; + + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp"; + }; + + psci { + compatible = "arm,psci-1.0"; + method = "smc"; + }; + + intc: interrupt-controller@a0021000 { + compatible = "arm,cortex-a7-gic"; + #interrupt-cells = <3>; + interrupt-controller; + reg = <0xa0021000 0x1000>, + <0xa0022000 0x2000>; + }; + + clocks { + clk_hse: clk-hse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <24000000>; + }; + + clk_hsi: clk-hsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <64000000>; + }; + + clk_lse: clk-lse { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32768>; + }; + + clk_lsi: clk-lsi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <32000>; + }; + + clk_csi: clk-csi { + #clock-cells = <0>; + compatible = "fixed-clock"; + clock-frequency = <4000000>; + }; + }; + + soc { + compatible = "simple-bus"; + #address-cells = <1>; + #size-cells = <1>; + interrupt-parent = <&intc>; + ranges; + + timers12: timer@40006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x40006000 0x400>; + clocks = <&rcc TIM12_K>; + clock-names = "int"; + status = "disabled"; + }; + + usart2: serial@4000e000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000e000 0x400>; + interrupts-extended = <&exti 27 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART2_K>; + resets = <&rcc USART2_R>; + status = "disabled"; + }; + + usart3: serial@4000f000 { + compatible = "st,stm32h7-uart"; + reg = <0x4000f000 0x400>; + interrupts-extended = <&exti 28 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART3_K>; + resets = <&rcc USART3_R>; + status = "disabled"; + }; + + uart4: serial@40010000 { + compatible = "st,stm32h7-uart"; + reg = <0x40010000 0x400>; + interrupts-extended = <&exti 30 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART4_K>; + resets = <&rcc UART4_R>; + wakeup-source; + status = "disabled"; + }; + + uart5: serial@40011000 { + compatible = "st,stm32h7-uart"; + reg = <0x40011000 0x400>; + interrupts-extended = <&exti 31 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART5_K>; + resets = <&rcc UART5_R>; + status = "disabled"; + }; + + i2c2: i2c@40013000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x40013000 0x400>; + interrupt-names = "event", "error"; + interrupts = <&exti 22 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 34 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C2_K>; + resets = <&rcc I2C2_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x2>; + wakeup-source; + status = "disabled"; + }; + + uart7: serial@40018000 { + compatible = "st,stm32h7-uart"; + reg = <0x40018000 0x400>; + interrupts-extended = <&exti 32 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART7_K>; + resets = <&rcc UART7_R>; + status = "disabled"; + }; + + uart8: serial@40019000 { + compatible = "st,stm32h7-uart"; + reg = <0x40019000 0x400>; + interrupts-extended = <&exti 33 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc UART8_K>; + resets = <&rcc UART8_R>; + status = "disabled"; + }; + + usart6: serial@44003000 { + compatible = "st,stm32h7-uart"; + reg = <0x44003000 0x400>; + interrupts-extended = <&exti 29 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc USART6_K>; + resets = <&rcc USART6_R>; + status = "disabled"; + }; + + timers15: timer@44006000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32-timers"; + reg = <0x44006000 0x400>; + clocks = <&rcc TIM15_K>; + clock-names = "int"; + status = "disabled"; + }; + + usbotg_hs: usb-otg@49000000 { + compatible = "st,stm32mp15-hsotg", "snps,dwc2"; + reg = <0x49000000 0x10000>; + clocks = <&rcc USBO_K>; + clock-names = "otg"; + resets = <&rcc USBO_R>; + reset-names = "dwc2"; + interrupts-extended = <&exti 44 IRQ_TYPE_LEVEL_HIGH>; + g-rx-fifo-size = <512>; + g-np-tx-fifo-size = <32>; + g-tx-fifo-size = <256 16 16 16 16 16 16 16>; + dr_mode = "otg"; + usb33d-supply = <&usb33>; + status = "disabled"; + }; + + rcc: rcc@50000000 { + compatible = "st,stm32mp1-rcc", "syscon"; + reg = <0x50000000 0x1000>; + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <1>; + #reset-cells = <1>; + interrupts = ; + secure-interrupts = ; + secure-interrupt-names = "wakeup"; + }; + + pwr_regulators: pwr@50001000 { + compatible = "st,stm32mp1,pwr-reg"; + reg = <0x50001000 0x10>; + st,tzcr = <&rcc 0x0 0x1>; + + reg11: reg11 { + regulator-name = "reg11"; + regulator-min-microvolt = <1100000>; + regulator-max-microvolt = <1100000>; + }; + + reg18: reg18 { + regulator-name = "reg18"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + usb33: usb33 { + regulator-name = "usb33"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + }; + + pwr_mcu: pwr_mcu@50001014 { + compatible = "st,stm32mp151-pwr-mcu", "syscon"; + reg = <0x50001014 0x4>; + }; + + pwr_irq: pwr@50001020 { + compatible = "st,stm32mp1-pwr"; + reg = <0x50001020 0x100>; + interrupts = ; + interrupt-controller; + #interrupt-cells = <3>; + }; + + exti: interrupt-controller@5000d000 { + compatible = "st,stm32mp1-exti", "syscon"; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000d000 0x400>; + + /* exti_pwr is an extra interrupt controller used for + * EXTI 55 to 60. It's mapped on pwr interrupt + * controller. + */ + exti_pwr: exti-pwr { + interrupt-controller; + #interrupt-cells = <2>; + interrupt-parent = <&pwr_irq>; + st,irq-number = <6>; + }; + }; + + syscfg: syscon@50020000 { + compatible = "st,stm32mp157-syscfg", "syscon"; + reg = <0x50020000 0x400>; + clocks = <&rcc SYSCFG>; + }; + + hash1: hash@54002000 { + compatible = "st,stm32f756-hash"; + reg = <0x54002000 0x400>; + interrupts = ; + clocks = <&rcc HASH1>; + resets = <&rcc HASH1_R>; + status = "disabled"; + }; + + rng1: rng@54003000 { + compatible = "st,stm32-rng"; + reg = <0x54003000 0x400>; + clocks = <&rcc RNG1_K>; + resets = <&rcc RNG1_R>; + status = "disabled"; + }; + + fmc: memory-controller@58002000 { + #address-cells = <2>; + #size-cells = <1>; + compatible = "st,stm32mp1-fmc2-ebi"; + reg = <0x58002000 0x1000>; + clocks = <&rcc FMC_K>; + resets = <&rcc FMC_R>; + status = "disabled"; + + ranges = <0 0 0x60000000 0x04000000>, /* EBI CS 1 */ + <1 0 0x64000000 0x04000000>, /* EBI CS 2 */ + <2 0 0x68000000 0x04000000>, /* EBI CS 3 */ + <3 0 0x6c000000 0x04000000>, /* EBI CS 4 */ + <4 0 0x80000000 0x10000000>; /* NAND */ + + nand-controller@4,0 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32mp1-fmc2-nfc"; + reg = <4 0x00000000 0x1000>, + <4 0x08010000 0x1000>, + <4 0x08020000 0x1000>, + <4 0x01000000 0x1000>, + <4 0x09010000 0x1000>, + <4 0x09020000 0x1000>; + interrupts = ; + status = "disabled"; + }; + }; + + qspi: spi@58003000 { + compatible = "st,stm32f469-qspi"; + reg = <0x58003000 0x1000>, <0x70000000 0x10000000>; + reg-names = "qspi", "qspi_mm"; + interrupts = ; + clocks = <&rcc QSPI_K>; + resets = <&rcc QSPI_R>; + status = "disabled"; + }; + + sdmmc1: mmc@58005000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58005000 0x1000>, <0x58006000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC1_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC1_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + sdmmc2: mmc@58007000 { + compatible = "st,stm32-sdmmc2", "arm,pl18x", "arm,primecell"; + arm,primecell-periphid = <0x00253180>; + reg = <0x58007000 0x1000>, <0x58008000 0x1000>; + interrupts = ; + interrupt-names = "cmd_irq"; + clocks = <&rcc SDMMC2_K>; + clock-names = "apb_pclk"; + resets = <&rcc SDMMC2_R>; + cap-sd-highspeed; + cap-mmc-highspeed; + max-frequency = <120000000>; + status = "disabled"; + }; + + iwdg2: watchdog@5a002000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5a002000 0x400>; + secure-interrupts = ; + clocks = <&rcc IWDG2>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + ddr: ddr@5a003000{ + compatible = "st,stm32mp1-ddr"; + reg = <0x5A003000 0x550 0x5A004000 0x234>; + clocks = <&rcc AXIDCG>, + <&rcc DDRC1>, + <&rcc DDRC2>, + <&rcc DDRPHYC>, + <&rcc DDRCAPB>, + <&rcc DDRPHYCAPB>; + clock-names = "axidcg", + "ddrc1", + "ddrc2", + "ddrphyc", + "ddrcapb", + "ddrphycapb"; + status = "okay"; + }; + + usbphyc: usbphyc@5a006000 { + #address-cells = <1>; + #size-cells = <0>; + #clock-cells = <0>; + compatible = "st,stm32mp1-usbphyc"; + reg = <0x5a006000 0x1000>; + clocks = <&rcc USBPHY_K>; + resets = <&rcc USBPHY_R>; + vdda1v1-supply = <®11>; + vdda1v8-supply = <®18>; + status = "disabled"; + + usbphyc_port0: usb-phy@0 { + #phy-cells = <0>; + reg = <0>; + }; + + usbphyc_port1: usb-phy@1 { + #phy-cells = <1>; + reg = <1>; + }; + }; + + usart1: serial@5c000000 { + compatible = "st,stm32h7-uart"; + reg = <0x5c000000 0x400>; + interrupts = ; + clocks = <&rcc USART1_K>; + resets = <&rcc USART1_R>; + status = "disabled"; + }; + + spi6: spi@5c001000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "st,stm32h7-spi"; + reg = <0x5c001000 0x400>; + interrupts = ; + clocks = <&rcc SPI6_K>; + resets = <&rcc SPI6_R>; + status = "disabled"; + }; + + i2c4: i2c@5c002000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c002000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 24 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 96 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C4_K>; + resets = <&rcc I2C4_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x8>; + wakeup-source; + status = "disabled"; + }; + + iwdg1: watchdog@5c003000 { + compatible = "st,stm32mp1-iwdg"; + reg = <0x5C003000 0x400>; + interrupts = ; + clocks = <&rcc IWDG1>, <&rcc CK_LSI>; + clock-names = "pclk", "lsi"; + status = "disabled"; + }; + + rtc: rtc@5c004000 { + compatible = "st,stm32mp1-rtc"; + reg = <0x5c004000 0x400>; + clocks = <&rcc RTCAPB>, <&rcc RTC>; + clock-names = "pclk", "rtc_ck"; + interrupts-extended = <&exti 19 IRQ_TYPE_LEVEL_HIGH>; + status = "disabled"; + }; + + bsec: efuse@5c005000 { + compatible = "st,stm32mp15-bsec"; + reg = <0x5c005000 0x400>; + #address-cells = <1>; + #size-cells = <1>; + + cfg0_otp: cfg0_otp@0 { + reg = <0x0 0x1>; + }; + part_number_otp: part_number_otp@4 { + reg = <0x4 0x1>; + }; + monotonic_otp: monotonic_otp@10 { + reg = <0x10 0x4>; + }; + nand_otp: nand_otp@24 { + reg = <0x24 0x4>; + }; + uid_otp: uid_otp@34 { + reg = <0x34 0xc>; + }; + package_otp: package_otp@40 { + reg = <0x40 0x4>; + }; + hw2_otp: hw2_otp@48 { + reg = <0x48 0x4>; + }; + ts_cal1: calib@5c { + reg = <0x5c 0x2>; + }; + ts_cal2: calib@5e { + reg = <0x5e 0x2>; + }; + mac_addr: mac_addr@e4 { + reg = <0xe4 0x8>; + st,non-secure-otp; + }; + }; + + etzpc: etzpc@5c007000 { + compatible = "st,stm32-etzpc"; + reg = <0x5C007000 0x400>; + clocks = <&rcc TZPC>; + status = "disabled"; + secure-status = "okay"; + }; + + stgen: stgen@5c008000 { + compatible = "st,stm32-stgen"; + reg = <0x5C008000 0x1000>; + }; + + i2c6: i2c@5c009000 { + compatible = "st,stm32mp15-i2c"; + reg = <0x5c009000 0x400>; + interrupt-names = "event", "error"; + interrupts-extended = <&exti 54 IRQ_TYPE_LEVEL_HIGH>, + <&intc GIC_SPI 136 IRQ_TYPE_LEVEL_HIGH>; + clocks = <&rcc I2C6_K>; + resets = <&rcc I2C6_R>; + #address-cells = <1>; + #size-cells = <0>; + st,syscfg-fmp = <&syscfg 0x4 0x20>; + wakeup-source; + status = "disabled"; + }; + + tamp: tamp@5c00a000 { + compatible = "st,stm32-tamp", "simple-bus", "syscon", "simple-mfd"; + reg = <0x5c00a000 0x400>; + secure-interrupts = ; + clocks = <&rcc RTCAPB>; + }; + + /* + * Break node order to solve dependency probe issue between + * pinctrl and exti. + */ + pinctrl: pin-controller@50002000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-pinctrl"; + ranges = <0 0x50002000 0xa400>; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + pins-are-numbered; + + gpioa: gpio@50002000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x0 0x400>; + clocks = <&rcc GPIOA>; + st,bank-name = "GPIOA"; + status = "disabled"; + }; + + gpiob: gpio@50003000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x1000 0x400>; + clocks = <&rcc GPIOB>; + st,bank-name = "GPIOB"; + status = "disabled"; + }; + + gpioc: gpio@50004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x2000 0x400>; + clocks = <&rcc GPIOC>; + st,bank-name = "GPIOC"; + status = "disabled"; + }; + + gpiod: gpio@50005000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x3000 0x400>; + clocks = <&rcc GPIOD>; + st,bank-name = "GPIOD"; + status = "disabled"; + }; + + gpioe: gpio@50006000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x4000 0x400>; + clocks = <&rcc GPIOE>; + st,bank-name = "GPIOE"; + status = "disabled"; + }; + + gpiof: gpio@50007000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x5000 0x400>; + clocks = <&rcc GPIOF>; + st,bank-name = "GPIOF"; + status = "disabled"; + }; + + gpiog: gpio@50008000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x6000 0x400>; + clocks = <&rcc GPIOG>; + st,bank-name = "GPIOG"; + status = "disabled"; + }; + + gpioh: gpio@50009000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x7000 0x400>; + clocks = <&rcc GPIOH>; + st,bank-name = "GPIOH"; + status = "disabled"; + }; + + gpioi: gpio@5000a000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x8000 0x400>; + clocks = <&rcc GPIOI>; + st,bank-name = "GPIOI"; + status = "disabled"; + }; + + gpioj: gpio@5000b000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0x9000 0x400>; + clocks = <&rcc GPIOJ>; + st,bank-name = "GPIOJ"; + status = "disabled"; + }; + + gpiok: gpio@5000c000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0xa000 0x400>; + clocks = <&rcc GPIOK>; + st,bank-name = "GPIOK"; + status = "disabled"; + }; + }; + + pinctrl_z: pin-controller-z@54004000 { + #address-cells = <1>; + #size-cells = <1>; + compatible = "st,stm32mp157-z-pinctrl"; + ranges = <0 0x54004000 0x400>; + pins-are-numbered; + interrupt-parent = <&exti>; + st,syscfg = <&exti 0x60 0xff>; + + gpioz: gpio@54004000 { + gpio-controller; + #gpio-cells = <2>; + interrupt-controller; + #interrupt-cells = <2>; + reg = <0 0x400>; + clocks = <&rcc GPIOZ>; + st,bank-name = "GPIOZ"; + st,bank-ioport = <11>; + status = "disabled"; + }; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp153.dtsi b/arm-trusted-firmware/fdts/stm32mp153.dtsi new file mode 100644 index 0000000..0a0bb8d --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp153.dtsi @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp151.dtsi" + +/ { + cpus { + cpu1: cpu@1 { + compatible = "arm,cortex-a7"; + device_type = "cpu"; + reg = <1>; + clocks = <&rcc CK_MPU>; + clock-names = "cpu"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157.dtsi b/arm-trusted-firmware/fdts/stm32mp157.dtsi new file mode 100644 index 0000000..c834029 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157.dtsi @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include "stm32mp153.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts b/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts new file mode 100644 index 0000000..b967736 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts @@ -0,0 +1,307 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) Arrow Electronics 2019 - All Rights Reserved + * Author: Botond Kardos + * + * Copyright (C) Linaro Ltd 2019 - All Rights Reserved + * Author: Manivannan Sadhasivam + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + +/ { + model = "Arrow Electronics STM32MP157A Avenger96 board"; + compatible = "arrow,stm32mp157a-avenger96", "st,stm32mp157"; + + aliases { + mmc0 = &sdmmc1; + serial0 = &uart4; + serial1 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x40000000>; + }; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + st,main-control-register = <0x04>; + st,vin-control-register = <0xc0>; + st,usb-control-register = <0x30>; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_DISABLED + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 480.0 MHz => P = 120, Q = 40, R = 96 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <1 39 3 11 4 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + status = "okay"; +}; + +&uart4 { + /* On Low speed expansion header */ + label = "LS-UART1"; + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_b>; + status = "okay"; +}; + +&uart7 { + /* On Low speed expansion header */ + label = "LS-UART0"; + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts b/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts new file mode 100644 index 0000000..a73bef8 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-dk1.dts @@ -0,0 +1,27 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157A-DK1 Discovery Board"; + compatible = "st,stm32mp157a-dk1", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts b/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts new file mode 100644 index 0000000..be8300e --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-dk2.dts @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include "stm32mp15xx-dkx.dtsi" + +/ { + model = "STMicroelectronics STM32MP157C-DK2 Discovery Board"; + compatible = "st,stm32mp157c-dk2", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + serial1 = &usart3; + serial2 = &uart7; + serial3 = &usart2; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&cryp1 { + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts b/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts new file mode 100644 index 0000000..44c7016 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ed1.dts @@ -0,0 +1,363 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxaa-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-2x4Gb-1066-binG.dtsi" + +/ { + model = "STMicroelectronics STM32MP157C eval daughter"; + compatible = "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + memory@c0000000 { + device_type = "memory"; + reg = <0xC0000000 0x40000000>; + }; + + aliases { + serial0 = &uart4; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0 { + cpu-supply = <&vddcore>; +}; + +&cpu1 { + cpu-supply = <&vddcore>; +}; + +&cryp1 { + status = "okay"; +}; + +&hash1 { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + ldo1-supply = <&v3v3>; + ldo2-supply = <&v3v3>; + ldo3-supply = <&vdd_ddr>; + ldo5-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + vdda: ldo1 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + }; + + v2v8: ldo2 { + regulator-name = "v2v8"; + regulator-min-microvolt = <2800000>; + regulator-max-microvolt = <2800000>; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-always-on; + regulator-over-current-protection; + st,regulator-sink-source; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdd_sd: ldo5 { + regulator-name = "vdd_sd"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v8: ldo6 { + regulator-name = "v1v8"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + + onkey { + compatible = "st,stpmic1-onkey"; + power-off-time-sec = <10>; + status = "okay"; + }; + + watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp", + "board_id"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a &sdmmc1_dir_pins_a>; + disable-wp; + st,sig-dir; + st,neg-edge; + st,use-ckin; + bus-width = <4>; + vmmc-supply = <&vdd_sd>; + sd-uhs-sdr12; + sd-uhs-sdr25; + sd-uhs-sdr50; + sd-uhs-ddr50; + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_a>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd>; + mmc-ddr-3_3v; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts b/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts new file mode 100644 index 0000000..02840a2 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-ev1.dts @@ -0,0 +1,63 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * Author: Ludovic Barre for STMicroelectronics. + */ +/dts-v1/; + +#include "stm32mp157c-ed1.dts" + +/ { + model = "STMicroelectronics STM32MP157C eval daughter on eval mother"; + compatible = "st,stm32mp157c-ev1", "st,stm32mp157c-ed1", "st,stm32mp157"; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + aliases { + serial1 = &usart3; + }; +}; + +&fmc { + pinctrl-names = "default"; + pinctrl-0 = <&fmc_pins_a>; + status = "okay"; + + nand-controller@4,0 { + status = "okay"; + + nand@0 { + reg = <0>; + nand-on-flash-bbt; + #address-cells = <1>; + #size-cells = <1>; + }; + }; +}; + +&qspi { + pinctrl-names = "default"; + pinctrl-0 = <&qspi_clk_pins_a &qspi_bk1_pins_a>; + reg = <0x58003000 0x1000>, <0x70000000 0x4000000>; + #address-cells = <1>; + #size-cells = <0>; + status = "okay"; + + flash0: mx66l51235l@0 { + compatible = "jedec,spi-nor"; + reg = <0>; + spi-rx-bus-width = <4>; + spi-max-frequency = <108000000>; + #address-cells = <1>; + #size-cells = <1>; + }; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_b>; + uart-has-rtscts; + status = "disabled"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts new file mode 100644 index 0000000..9ee09e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts new file mode 100644 index 0000000..6f67712 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts @@ -0,0 +1,93 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + * Copyright (C) 2020 Ahmad Fatoum, Pengutronix + */ + +/dts-v1/; + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" +#include "stm32mp15xx-osd32.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" + +/ { + model = "Linux Automation MC-1 board"; + compatible = "lxa,stm32mp157c-mc1", "oct,stm32mp15xx-osd32", "st,stm32mp157"; + + aliases { + mmc0 = &sdmmc1; + mmc1 = &sdmmc2; + serial0 = &uart4; + }; + + chosen { + stdout-path = &uart4; + }; + + led-act { + compatible = "gpio-leds"; + + led-green { + label = "mc1:green:act"; + gpios = <&gpioa 13 1>; + linux,default-trigger = "heartbeat"; + }; + }; + + reg_3v3: regulator_3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + vin-supply = <&v3v3>; + }; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + bus-width = <4>; + cd-gpios = <&gpioh 3 1>; + disable-wp; + no-1-8-v; + st,neg-edge; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +&sdmmc1_b4_pins_a { + /* + * board lacks external pull-ups on SDMMC lines. Class 10 SD refuses to + * work, thus enable internal pull-ups. + */ + pins1 { + /delete-property/ bias-disable; + bias-pull-up; + }; + pins2 { + /delete-property/ bias-disable; + bias-pull-up; + }; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_b>; + bus-width = <8>; + no-1-8-v; + no-sd; + no-sdio; + non-removable; + st,neg-edge; + vmmc-supply = <®_3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts new file mode 100644 index 0000000..9ee09e9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi new file mode 100644 index 0000000..6bed339 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi @@ -0,0 +1,325 @@ +/* + * Copyright (C) 2019, STMicroelectronics. All Rights Reserved. + * Copyright (C) 2021, Grzegorz Szymaszek. + * + * SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) + */ + +#include "stm32mp157.dtsi" +#include "stm32mp15xc.dtsi" +#include "stm32mp15-pinctrl.dtsi" +#include "stm32mp15xxac-pinctrl.dtsi" +#include +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0 { + cpu-supply = <&vddcore>; +}; + +&cpu1 { + cpu-supply = <&vddcore>; +}; + +&cryp1 { + status = "okay"; +}; + +&hash1 { + status = "okay"; +}; + +&i2c2 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c2_pins_a>; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + + pmic_watchdog: watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = <2 80 0 0 0 PQR(1,0,0)>; + frac = <0x800>; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc2 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc2_b4_pins_a &sdmmc2_d47_pins_d>; + non-removable; + no-sd; + no-sdio; + st,neg-edge; + bus-width = <8>; + vmmc-supply = <&v3v3>; + vqmmc-supply = <&vdd>; + mmc-ddr-3_3v; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts b/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts new file mode 100644 index 0000000..03800f9 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2019, STMicroelectronics. All Rights Reserved. + * Copyright (C) 2021, Grzegorz Szymaszek. + * + * SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) + */ + +/dts-v1/; + +#include "stm32mp157c-odyssey-som.dtsi" + +/ { + model = "Seeed Studio Odyssey-STM32MP157C Board"; + compatible = "seeed,stm32mp157c-odyssey", + "seeed,stm32mp157c-odyssey-som", "st,stm32mp157"; + + aliases { + serial0 = &uart4; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts new file mode 100644 index 0000000..83116d1 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x20000000 /* 512MB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts b/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts new file mode 100644 index 0000000..2abbe50 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2020-2021, STMicroelectronics - All Rights Reserved + */ + +#define DDR_SIZE 0x40000000 /* 1GB */ +#include "stm32mp15-fw-config.dtsi" diff --git a/arm-trusted-firmware/fdts/stm32mp15xc.dtsi b/arm-trusted-firmware/fdts/stm32mp15xc.dtsi new file mode 100644 index 0000000..b06a55a --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xc.dtsi @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (C) STMicroelectronics 2019 - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +/ { + soc { + cryp1: cryp@54001000 { + compatible = "st,stm32mp1-cryp"; + reg = <0x54001000 0x400>; + interrupts = ; + clocks = <&rcc CRYP1>; + resets = <&rcc CRYP1_R>; + status = "disabled"; + }; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi b/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi new file mode 100644 index 0000000..2eb3a57 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi @@ -0,0 +1,367 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +#include +#include "stm32mp15-ddr3-1x4Gb-1066-binG.dtsi" + +/ { + memory@c0000000 { + device_type = "memory"; + reg = <0xc0000000 0x20000000>; + }; + + vin: vin { + compatible = "regulator-fixed"; + regulator-name = "vin"; + regulator-min-microvolt = <5000000>; + regulator-max-microvolt = <5000000>; + regulator-always-on; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + +&hash1 { + status = "okay"; +}; + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + clock-frequency = <400000>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&exti_pwr 55 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + status = "okay"; + + regulators { + compatible = "st,stpmic1-regulators"; + buck1-supply = <&vin>; + buck2-supply = <&vin>; + buck3-supply = <&vin>; + buck4-supply = <&vin>; + ldo1-supply = <&v3v3>; + ldo2-supply = <&vin>; + ldo3-supply = <&vdd_ddr>; + ldo4-supply = <&vin>; + ldo5-supply = <&vin>; + ldo6-supply = <&v3v3>; + vref_ddr-supply = <&vin>; + boost-supply = <&vin>; + pwr_sw1-supply = <&bst_out>; + pwr_sw2-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-always-on; + regulator-over-current-protection; + st,regulator-sink-source; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge = <1>; + }; + }; + }; +}; + +&iwdg2 { + timeout-sec = <32>; + status = "okay"; + secure-status = "okay"; +}; + +&nvmem_layout { + nvmem-cells = <&cfg0_otp>, + <&part_number_otp>, + <&monotonic_otp>, + <&nand_otp>, + <&uid_otp>, + <&package_otp>, + <&hw2_otp>, + <&board_id>; + + nvmem-cell-names = "cfg0_otp", + "part_number_otp", + "monotonic_otp", + "nand_otp", + "uid_otp", + "package_otp", + "hw2_otp", + "board_id"; +}; + +&pwr_regulators { + vdd-supply = <&vdd>; + vdd_3v3_usbfs-supply = <&vdd_usb>; +}; + +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = < 2 80 0 0 0 PQR(1,0,0) >; + frac = < 0x800 >; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; + +&rng1 { + status = "okay"; +}; + +&rtc { + status = "okay"; +}; + +&sdmmc1 { + pinctrl-names = "default"; + pinctrl-0 = <&sdmmc1_b4_pins_a>; + disable-wp; + st,neg-edge; + bus-width = <4>; + vmmc-supply = <&v3v3>; + status = "okay"; +}; + +&timers15 { + secure-status = "okay"; +}; + +&uart4 { + pinctrl-names = "default"; + pinctrl-0 = <&uart4_pins_a>; + status = "okay"; +}; + +&uart7 { + pinctrl-names = "default"; + pinctrl-0 = <&uart7_pins_c>; + status = "disabled"; +}; + +&usart3 { + pinctrl-names = "default"; + pinctrl-0 = <&usart3_pins_c>; + uart-has-rtscts; + status = "disabled"; +}; + +&usbotg_hs { + phys = <&usbphyc_port1 0>; + phy-names = "usb2-phy"; + usb-role-switch; + status = "okay"; +}; + +&usbphyc { + status = "okay"; +}; + +&usbphyc_port0 { + phy-supply = <&vdd_usb>; +}; + +&usbphyc_port1 { + phy-supply = <&vdd_usb>; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi b/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi new file mode 100644 index 0000000..76a2561 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi @@ -0,0 +1,281 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-3-Clause) */ +/* + * Copyright (C) 2020 STMicroelectronics - All Rights Reserved + * Copyright (C) 2020 Ahmad Fatoum, Pengutronix + */ + +#include "stm32mp15-pinctrl.dtsi" + +&i2c4 { + pinctrl-names = "default"; + pinctrl-0 = <&i2c4_pins_a>; + clock-frequency = <400000>; + i2c-scl-rising-time-ns = <185>; + i2c-scl-falling-time-ns = <20>; + status = "okay"; + + pmic: stpmic@33 { + compatible = "st,stpmic1"; + reg = <0x33>; + interrupts-extended = <&gpioa 0 IRQ_TYPE_EDGE_FALLING>; + interrupt-controller; + #interrupt-cells = <2>; + + regulators { + compatible = "st,stpmic1-regulators"; + + ldo1-supply = <&v3v3>; + ldo6-supply = <&v3v3>; + pwr_sw1-supply = <&bst_out>; + + vddcore: buck1 { + regulator-name = "vddcore"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd_ddr: buck2 { + regulator-name = "vdd_ddr"; + regulator-min-microvolt = <1350000>; + regulator-max-microvolt = <1350000>; + regulator-always-on; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + vdd: buck3 { + regulator-name = "vdd"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + st,mask-reset; + regulator-initial-mode = <0>; + regulator-over-current-protection; + }; + + v3v3: buck4 { + regulator-name = "v3v3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + regulator-over-current-protection; + regulator-initial-mode = <0>; + }; + + v1v8_audio: ldo1 { + regulator-name = "v1v8_audio"; + regulator-min-microvolt = <1800000>; + regulator-max-microvolt = <1800000>; + regulator-always-on; + }; + + v3v3_hdmi: ldo2 { + regulator-name = "v3v3_hdmi"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + vtt_ddr: ldo3 { + regulator-name = "vtt_ddr"; + regulator-min-microvolt = <500000>; + regulator-max-microvolt = <750000>; + regulator-always-on; + regulator-over-current-protection; + }; + + vdd_usb: ldo4 { + regulator-name = "vdd_usb"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + }; + + vdda: ldo5 { + regulator-name = "vdda"; + regulator-min-microvolt = <2900000>; + regulator-max-microvolt = <2900000>; + regulator-boot-on; + }; + + v1v2_hdmi: ldo6 { + regulator-name = "v1v2_hdmi"; + regulator-min-microvolt = <1200000>; + regulator-max-microvolt = <1200000>; + regulator-always-on; + }; + + vref_ddr: vref_ddr { + regulator-name = "vref_ddr"; + regulator-always-on; + regulator-over-current-protection; + }; + + bst_out: boost { + regulator-name = "bst_out"; + }; + + vbus_otg: pwr_sw1 { + regulator-name = "vbus_otg"; + regulator-active-discharge; + }; + + vbus_sw: pwr_sw2 { + regulator-name = "vbus_sw"; + regulator-active-discharge; + }; + }; + + pmic_watchdog: watchdog { + compatible = "st,stpmic1-wdt"; + status = "disabled"; + }; + }; +}; + +&rng1 { + status = "okay"; +}; + +/* ATF Specific */ +#include + +/ { + aliases { + gpio0 = &gpioa; + gpio1 = &gpiob; + gpio2 = &gpioc; + gpio3 = &gpiod; + gpio4 = &gpioe; + gpio5 = &gpiof; + gpio6 = &gpiog; + gpio7 = &gpioh; + gpio8 = &gpioi; + gpio25 = &gpioz; + i2c3 = &i2c4; + }; +}; + +&bsec { + board_id: board_id@ec { + reg = <0xec 0x4>; + st,non-secure-otp; + }; +}; + +&clk_hse { + st,digbypass; +}; + +&cpu0{ + cpu-supply = <&vddcore>; +}; + +&cpu1{ + cpu-supply = <&vddcore>; +}; + +&hash1 { + status = "okay"; +}; + +/* CLOCK init */ +&rcc { + secure-status = "disabled"; + st,clksrc = < + CLK_MPU_PLL1P + CLK_AXI_PLL2P + CLK_MCU_PLL3P + CLK_PLL12_HSE + CLK_PLL3_HSE + CLK_PLL4_HSE + CLK_RTC_LSE + CLK_MCO1_DISABLED + CLK_MCO2_DISABLED + >; + + st,clkdiv = < + 1 /*MPU*/ + 0 /*AXI*/ + 0 /*MCU*/ + 1 /*APB1*/ + 1 /*APB2*/ + 1 /*APB3*/ + 1 /*APB4*/ + 2 /*APB5*/ + 23 /*RTC*/ + 0 /*MCO1*/ + 0 /*MCO2*/ + >; + + st,pkcs = < + CLK_CKPER_HSE + CLK_FMC_ACLK + CLK_QSPI_ACLK + CLK_ETH_PLL4P + CLK_SDMMC12_PLL4P + CLK_DSI_DSIPLL + CLK_STGEN_HSE + CLK_USBPHY_HSE + CLK_SPI2S1_PLL3Q + CLK_SPI2S23_PLL3Q + CLK_SPI45_HSI + CLK_SPI6_HSI + CLK_I2C46_HSI + CLK_SDMMC3_PLL4P + CLK_USBO_USBPHY + CLK_ADC_CKPER + CLK_CEC_LSE + CLK_I2C12_HSI + CLK_I2C35_HSI + CLK_UART1_HSI + CLK_UART24_HSI + CLK_UART35_HSI + CLK_UART6_HSI + CLK_UART78_HSI + CLK_SPDIF_PLL4P + CLK_FDCAN_PLL4R + CLK_SAI1_PLL3Q + CLK_SAI2_PLL3Q + CLK_SAI3_PLL3Q + CLK_SAI4_PLL3Q + CLK_RNG1_LSI + CLK_RNG2_LSI + CLK_LPTIM1_PCLK1 + CLK_LPTIM23_PCLK3 + CLK_LPTIM45_LSE + >; + + /* VCO = 1300.0 MHz => P = 650 (CPU) */ + pll1: st,pll@0 { + compatible = "st,stm32mp1-pll"; + reg = <0>; + cfg = < 2 80 0 0 0 PQR(1,0,0) >; + frac = < 0x800 >; + }; + + /* VCO = 1066.0 MHz => P = 266 (AXI), Q = 533 (GPU), R = 533 (DDR) */ + pll2: st,pll@1 { + compatible = "st,stm32mp1-pll"; + reg = <1>; + cfg = <2 65 1 0 0 PQR(1,1,1)>; + frac = <0x1400>; + }; + + /* VCO = 417.8 MHz => P = 209, Q = 24, R = 11 */ + pll3: st,pll@2 { + compatible = "st,stm32mp1-pll"; + reg = <2>; + cfg = <1 33 1 16 36 PQR(1,1,1)>; + frac = <0x1a04>; + }; + + /* VCO = 594.0 MHz => P = 99, Q = 74, R = 74 */ + pll4: st,pll@3 { + compatible = "st,stm32mp1-pll"; + reg = <3>; + cfg = <3 98 5 7 7 PQR(1,1,1)>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi new file mode 100644 index 0000000..f1d540a --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi @@ -0,0 +1,85 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 128 16>; + }; + + gpioj: gpio@5000b000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 144 16>; + }; + + gpiok: gpio@5000c000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl 0 160 8>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi new file mode 100644 index 0000000..b58c7e2 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi new file mode 100644 index 0000000..11e7e03 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 80 16>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 96 16>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 112 16>; + }; + + gpioi: gpio@5000a000 { + status = "okay"; + ngpios = <12>; + gpio-ranges = <&pinctrl 0 128 12>; + }; +}; + +&pinctrl_z { + st,package = ; + + gpioz: gpio@54004000 { + status = "okay"; + ngpios = <8>; + gpio-ranges = <&pinctrl_z 0 400 8>; + }; +}; diff --git a/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi b/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi new file mode 100644 index 0000000..52806d6 --- /dev/null +++ b/arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * Author: Alexandre Torgue for STMicroelectronics. + */ + +&pinctrl { + st,package = ; + + gpioa: gpio@50002000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 0 16>; + }; + + gpiob: gpio@50003000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 16 16>; + }; + + gpioc: gpio@50004000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 32 16>; + }; + + gpiod: gpio@50005000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 48 16>; + }; + + gpioe: gpio@50006000 { + status = "okay"; + ngpios = <16>; + gpio-ranges = <&pinctrl 0 64 16>; + }; + + gpiof: gpio@50007000 { + status = "okay"; + ngpios = <6>; + gpio-ranges = <&pinctrl 6 86 6>; + }; + + gpiog: gpio@50008000 { + status = "okay"; + ngpios = <10>; + gpio-ranges = <&pinctrl 6 102 10>; + }; + + gpioh: gpio@50009000 { + status = "okay"; + ngpios = <2>; + gpio-ranges = <&pinctrl 0 112 2>; + }; +}; diff --git a/arm-trusted-firmware/fdts/tc.dts b/arm-trusted-firmware/fdts/tc.dts new file mode 100644 index 0000000..7c0e842 --- /dev/null +++ b/arm-trusted-firmware/fdts/tc.dts @@ -0,0 +1,552 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/dts-v1/; + +/ { + compatible = "arm,tc"; + interrupt-parent = <&gic>; + #address-cells = <2>; + #size-cells = <2>; + + aliases { + serial0 = &soc_uart0; + }; + + chosen { + stdout-path = "serial0:115200n8"; + }; + + cpus { + #address-cells = <1>; + #size-cells = <0>; + + cpu-map { + cluster0 { + core0 { + cpu = <&CPU0>; + }; + core1 { + cpu = <&CPU1>; + }; + core2 { + cpu = <&CPU2>; + }; + core3 { + cpu = <&CPU3>; + }; + core4 { + cpu = <&CPU4>; + }; + core5 { + cpu = <&CPU5>; + }; + core6 { + cpu = <&CPU6>; + }; + core7 { + cpu = <&CPU7>; + }; + }; + }; + + /* + * The timings below are just to demonstrate working cpuidle. + * These values may be inaccurate. + */ + idle-states { + entry-method = "arm,psci"; + + CPU_SLEEP_0: cpu-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x0010000>; + local-timer-stop; + entry-latency-us = <300>; + exit-latency-us = <1200>; + min-residency-us = <2000>; + }; + CLUSTER_SLEEP_0: cluster-sleep-0 { + compatible = "arm,idle-state"; + arm,psci-suspend-param = <0x1010000>; + local-timer-stop; + entry-latency-us = <400>; + exit-latency-us = <1200>; + min-residency-us = <2500>; + }; + }; + + amus { + amu: amu-0 { + #address-cells = <1>; + #size-cells = <0>; + + mpmm_gear0: counter@0 { + reg = <0>; + + enable-at-el3; + }; + + mpmm_gear1: counter@1 { + reg = <1>; + + enable-at-el3; + }; + + mpmm_gear2: counter@2 { + reg = <2>; + + enable-at-el3; + }; + }; + }; + + CPU0:cpu@0 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x0>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU1:cpu@100 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x100>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU2:cpu@200 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x200>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU3:cpu@300 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x300>; + enable-method = "psci"; + clocks = <&scmi_dvfs 0>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <406>; + amu = <&amu>; + supports-mpmm; + }; + + CPU4:cpu@400 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x400>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU5:cpu@500 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x500>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU6:cpu@600 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x600>; + enable-method = "psci"; + clocks = <&scmi_dvfs 1>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <912>; + amu = <&amu>; + supports-mpmm; + }; + + CPU7:cpu@700 { + device_type = "cpu"; + compatible = "arm,armv8"; + reg = <0x700>; + enable-method = "psci"; + clocks = <&scmi_dvfs 2>; + cpu-idle-states = <&CPU_SLEEP_0 &CLUSTER_SLEEP_0>; + capacity-dmips-mhz = <1024>; + amu = <&amu>; + supports-mpmm; + }; + + }; + + reserved-memory { + #address-cells = <2>; + #size-cells = <2>; + ranges; + + linux,cma { + compatible = "shared-dma-pool"; + reusable; + size = <0x0 0x8000000>; + linux,cma-default; + }; + + optee@0xfce00000 { + reg = <0x00000000 0xfce00000 0 0x00200000>; + no-map; + }; + }; + + psci { + compatible = "arm,psci-1.0", "arm,psci-0.2"; + method = "smc"; + }; + + sram: sram@6000000 { + compatible = "mmio-sram"; + reg = <0x0 0x06000000 0x0 0x8000>; + + #address-cells = <1>; + #size-cells = <1>; + ranges = <0 0x0 0x06000000 0x8000>; + + cpu_scp_scmi_mem: scp-shmem@0 { + compatible = "arm,scmi-shmem"; + reg = <0x0 0x80>; + }; + }; + + mbox_db_rx: mhu@45010000 { + compatible = "arm,mhuv2-rx","arm,primecell"; + reg = <0x0 0x45010000 0x0 0x1000>; + clocks = <&soc_refclk100mhz>; + clock-names = "apb_pclk"; + #mbox-cells = <2>; + interrupts = <0 317 4>; + interrupt-names = "mhu_rx"; + mhu-protocol = "doorbell"; + arm,mhuv2-protocols = <0 1>; + }; + + mbox_db_tx: mhu@45000000 { + compatible = "arm,mhuv2-tx","arm,primecell"; + reg = <0x0 0x45000000 0x0 0x1000>; + clocks = <&soc_refclk100mhz>; + clock-names = "apb_pclk"; + #mbox-cells = <2>; + interrupt-names = "mhu_tx"; + mhu-protocol = "doorbell"; + arm,mhuv2-protocols = <0 1>; + }; + + scmi { + compatible = "arm,scmi"; + mbox-names = "tx", "rx"; + mboxes = <&mbox_db_tx 0 0 &mbox_db_rx 0 0 >; + shmem = <&cpu_scp_scmi_mem &cpu_scp_scmi_mem>; + #address-cells = <1>; + #size-cells = <0>; + + scmi_dvfs: protocol@13 { + reg = <0x13>; + #clock-cells = <1>; + }; + + scmi_clk: protocol@14 { + reg = <0x14>; + #clock-cells = <1>; + }; + }; + + gic: interrupt-controller@2c010000 { + compatible = "arm,gic-600", "arm,gic-v3"; + #address-cells = <2>; + #interrupt-cells = <3>; + #size-cells = <2>; + ranges; + interrupt-controller; + reg = <0x0 0x30000000 0 0x10000>, /* GICD */ + <0x0 0x30080000 0 0x200000>; /* GICR */ + interrupts = <0x1 0x9 0x4>; + }; + + timer { + compatible = "arm,armv8-timer"; + interrupts = <0x1 13 0x8>, + <0x1 14 0x8>, + <0x1 11 0x8>, + <0x1 10 0x8>; + }; + + soc_refclk100mhz: refclk100mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <100000000>; + clock-output-names = "apb_pclk"; + }; + + soc_refclk60mhz: refclk60mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <60000000>; + clock-output-names = "iofpga_clk"; + }; + + soc_uartclk: uartclk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <50000000>; + clock-output-names = "uartclk"; + }; + + soc_uart0: uart@7ff80000 { + compatible = "arm,pl011", "arm,primecell"; + reg = <0x0 0x7ff80000 0x0 0x1000>; + interrupts = <0x0 116 0x4>; + clocks = <&soc_uartclk>, <&soc_refclk100mhz>; + clock-names = "uartclk", "apb_pclk"; + status = "okay"; + }; + + vencoder { + compatible = "drm,virtual-encoder"; + + port { + vencoder_in: endpoint { + remote-endpoint = <&dp_pl0_out0>; + }; + }; + + display-timings { + panel-timing { + clock-frequency = <25175000>; + hactive = <640>; + vactive = <480>; + hfront-porch = <16>; + hback-porch = <48>; + hsync-len = <96>; + vfront-porch = <10>; + vback-porch = <33>; + vsync-len = <2>; + }; + }; + + }; + + hdlcd: hdlcd@7ff60000 { + compatible = "arm,hdlcd"; + reg = <0x0 0x7ff60000 0x0 0x1000>; + interrupts = <0x0 117 0x4>; + clocks = <&fake_hdlcd_clk>; + clock-names = "pxlclk"; + status = "disabled"; + + port { + hdlcd_out: endpoint { + remote-endpoint = <&vencoder_in>; + }; + }; + }; + + fake_hdlcd_clk: fake-hdlcd-clk { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <25175000>; + clock-output-names = "pxlclk"; + }; + + ethernet@18000000 { + compatible = "smsc,lan91c111"; + reg = <0x0 0x18000000 0x0 0x10000>; + interrupts = <0 109 4>; + }; + + kmi@1c060000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x001c060000 0x0 0x1000>; + interrupts = <0 197 4>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + kmi@1c070000 { + compatible = "arm,pl050", "arm,primecell"; + reg = <0x0 0x001c070000 0x0 0x1000>; + interrupts = <0 103 4>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "KMIREFCLK", "apb_pclk"; + }; + + bp_clock24mhz: clock24mhz { + compatible = "fixed-clock"; + #clock-cells = <0>; + clock-frequency = <24000000>; + clock-output-names = "bp:clock24mhz"; + }; + + virtio_block@1c130000 { + compatible = "virtio,mmio"; + reg = <0x0 0x1c130000 0x0 0x200>; + interrupts = <0 204 4>; + }; + + sysreg: sysreg@1c010000 { + compatible = "arm,vexpress-sysreg"; + reg = <0x0 0x001c010000 0x0 0x1000>; + gpio-controller; + #gpio-cells = <2>; + }; + + fixed_3v3: v2m-3v3 { + compatible = "regulator-fixed"; + regulator-name = "3V3"; + regulator-min-microvolt = <3300000>; + regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + + mmci@1c050000 { + compatible = "arm,pl180", "arm,primecell"; + reg = <0x0 0x001c050000 0x0 0x1000>; + interrupts = <0 107 0x4>, + <0 108 0x4>; + cd-gpios = <&sysreg 0 0>; + wp-gpios = <&sysreg 1 0>; + bus-width = <8>; + max-frequency = <12000000>; + vmmc-supply = <&fixed_3v3>; + clocks = <&bp_clock24mhz>, <&bp_clock24mhz>; + clock-names = "mclk", "apb_pclk"; + }; + + gpu: gpu@2d000000 { + compatible = "arm,mali-midgard"; + reg = <0x0 0x2d000000 0x0 0x200000>; + interrupts = <0 66 4>, <0 67 4>, <0 65 4>; + interrupt-names = "JOB", "MMU", "GPU"; + clocks = <&soc_refclk100mhz>; + clock-names = "clk_mali"; + operating-points = < + /* KHz uV */ + 50000 820000 + >; + }; + + smmu: smmu@2ce00000 { + #iommu-cells = <1>; + compatible = "arm,smmu-v3"; + reg = <0x0 0x2ce00000 0x0 0x20000>; + status = "okay"; + }; + + dp0: display@2cc00000 { + #address-cells = <1>; + #size-cells = <0>; + compatible = "arm,mali-d71"; + reg = <0 0x2cc00000 0 0x20000>; + interrupts = <0 69 4>; + interrupt-names = "DPU"; + clocks = <&scmi_clk 0>; + clock-names = "aclk"; + iommus = <&smmu 0>, <&smmu 1>, <&smmu 2>, <&smmu 3>, + <&smmu 4>, <&smmu 5>, <&smmu 6>, <&smmu 7>, + <&smmu 8>, <&smmu 9>; + pl0: pipeline@0 { + reg = <0>; + clocks = <&scmi_clk 1>; + clock-names = "pxclk"; + pl_id = <0>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + dp_pl0_out0: endpoint { + remote-endpoint = <&vencoder_in>; + }; + }; + }; + }; + + pl1: pipeline@1 { + reg = <1>; + clocks = <&scmi_clk 2>; + clock-names = "pxclk"; + pl_id = <1>; + ports { + #address-cells = <1>; + #size-cells = <0>; + port@0 { + reg = <0>; + }; + }; + }; + }; + + ete0 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU0>; + }; + + ete1 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU1>; + }; + + ete2 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU2>; + }; + + ete3 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU3>; + }; + + ete4 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU4>; + }; + + ete5 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU5>; + }; + + ete6 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU6>; + }; + + ete7 { + compatible = "arm,embedded-trace-extension"; + cpu = <&CPU7>; + }; + + trbe0 { + compatible = "arm,trace-buffer-extension"; + interrupts = <1 2 4>; + }; +}; diff --git a/arm-trusted-firmware/include/arch/aarch32/arch.h b/arm-trusted-firmware/include/arch/aarch32/arch.h new file mode 100644 index 0000000..bdff25b --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch.h @@ -0,0 +1,778 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_H +#define ARCH_H + +#include + +/******************************************************************************* + * MIDR bit definitions + ******************************************************************************/ +#define MIDR_IMPL_MASK U(0xff) +#define MIDR_IMPL_SHIFT U(24) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (U(1) << 24) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK U(0xff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK U(0x00ffffff) +#define MPIDR_AFFLVL0 U(0) +#define MPIDR_AFFLVL1 U(1) +#define MPIDR_AFFLVL2 U(2) +#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n + +#define MPIDR_AFFLVL0_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL1_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL2_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL3_VAL(mpidr) U(0) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +#define MPID_MASK (MPIDR_MT_MASK |\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT)|\ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID U(0xFFFFFFFF) + +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + */ +#define MPIDR_MAX_AFFLVL U(2) + +/* Data Cache set/way op type defines */ +#define DC_OP_ISW U(0x0) +#define DC_OP_CISW U(0x1) +#if ERRATA_A53_827319 +#define DC_OP_CSW DC_OP_CISW +#else +#define DC_OP_CSW U(0x2) +#endif + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +/* Counter Count Value Lower register */ +#define CNTCVL_OFF U(0x008) +/* Counter Count Value Upper register */ +#define CNTCVU_OFF U(0x00C) +#define CNTFID_OFF U(0x020) + +#define CNTCR_EN (U(1) << 0) +#define CNTCR_HDBG (U(1) << 1) +#define CNTCR_FCREQ(x) ((x) << 8) + +/******************************************************************************* + * System register bit definitions + ******************************************************************************/ +/* CLIDR definitions */ +#define LOUIS_SHIFT U(21) +#define LOC_SHIFT U(24) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* ID_DFR0_EL1 definitions */ +#define ID_DFR0_COPTRC_SHIFT U(12) +#define ID_DFR0_COPTRC_MASK U(0xf) +#define ID_DFR0_COPTRC_SUPPORTED U(1) +#define ID_DFR0_COPTRC_LENGTH U(4) +#define ID_DFR0_TRACEFILT_SHIFT U(28) +#define ID_DFR0_TRACEFILT_MASK U(0xf) +#define ID_DFR0_TRACEFILT_SUPPORTED U(1) +#define ID_DFR0_TRACEFILT_LENGTH U(4) + +/* ID_DFR1_EL1 definitions */ +#define ID_DFR1_MTPMU_SHIFT U(0) +#define ID_DFR1_MTPMU_MASK U(0xf) +#define ID_DFR1_MTPMU_SUPPORTED U(1) + +/* ID_MMFR4 definitions */ +#define ID_MMFR4_CNP_SHIFT U(12) +#define ID_MMFR4_CNP_LENGTH U(4) +#define ID_MMFR4_CNP_MASK U(0xf) + +#define ID_MMFR4_CCIDX_SHIFT U(24) +#define ID_MMFR4_CCIDX_LENGTH U(4) +#define ID_MMFR4_CCIDX_MASK U(0xf) + +/* ID_PFR0 definitions */ +#define ID_PFR0_AMU_SHIFT U(20) +#define ID_PFR0_AMU_LENGTH U(4) +#define ID_PFR0_AMU_MASK U(0xf) +#define ID_PFR0_AMU_NOT_SUPPORTED U(0x0) +#define ID_PFR0_AMU_V1 U(0x1) +#define ID_PFR0_AMU_V1P1 U(0x2) + +#define ID_PFR0_DIT_SHIFT U(24) +#define ID_PFR0_DIT_LENGTH U(4) +#define ID_PFR0_DIT_MASK U(0xf) +#define ID_PFR0_DIT_SUPPORTED (U(1) << ID_PFR0_DIT_SHIFT) + +/* ID_PFR1 definitions */ +#define ID_PFR1_VIRTEXT_SHIFT U(12) +#define ID_PFR1_VIRTEXT_MASK U(0xf) +#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \ + & ID_PFR1_VIRTEXT_MASK) +#define ID_PFR1_GENTIMER_SHIFT U(16) +#define ID_PFR1_GENTIMER_MASK U(0xf) +#define ID_PFR1_GIC_SHIFT U(28) +#define ID_PFR1_GIC_MASK U(0xf) +#define ID_PFR1_SEC_SHIFT U(4) +#define ID_PFR1_SEC_MASK U(0xf) +#define ID_PFR1_ELx_ENABLED U(1) + +/* SCTLR definitions */ +#define SCTLR_RES1_DEF ((U(1) << 23) | (U(1) << 22) | (U(1) << 4) | \ + (U(1) << 3)) +#if ARM_ARCH_MAJOR == 7 +#define SCTLR_RES1 SCTLR_RES1_DEF +#else +#define SCTLR_RES1 (SCTLR_RES1_DEF | (U(1) << 11)) +#endif +#define SCTLR_M_BIT (U(1) << 0) +#define SCTLR_A_BIT (U(1) << 1) +#define SCTLR_C_BIT (U(1) << 2) +#define SCTLR_CP15BEN_BIT (U(1) << 5) +#define SCTLR_ITD_BIT (U(1) << 7) +#define SCTLR_Z_BIT (U(1) << 11) +#define SCTLR_I_BIT (U(1) << 12) +#define SCTLR_V_BIT (U(1) << 13) +#define SCTLR_RR_BIT (U(1) << 14) +#define SCTLR_NTWI_BIT (U(1) << 16) +#define SCTLR_NTWE_BIT (U(1) << 18) +#define SCTLR_WXN_BIT (U(1) << 19) +#define SCTLR_UWXN_BIT (U(1) << 20) +#define SCTLR_EE_BIT (U(1) << 25) +#define SCTLR_TRE_BIT (U(1) << 28) +#define SCTLR_AFE_BIT (U(1) << 29) +#define SCTLR_TE_BIT (U(1) << 30) +#define SCTLR_DSSBS_BIT (U(1) << 31) +#define SCTLR_RESET_VAL (SCTLR_RES1 | SCTLR_NTWE_BIT | \ + SCTLR_NTWI_BIT | SCTLR_CP15BEN_BIT) + +/* SDCR definitions */ +#define SDCR_SPD(x) ((x) << 14) +#define SDCR_SPD_LEGACY U(0x0) +#define SDCR_SPD_DISABLE U(0x2) +#define SDCR_SPD_ENABLE U(0x3) +#define SDCR_SCCD_BIT (U(1) << 23) +#define SDCR_TTRF_BIT (U(1) << 19) +#define SDCR_SPME_BIT (U(1) << 17) +#define SDCR_RESET_VAL U(0x0) +#define SDCR_MTPME_BIT (U(1) << 28) + +/* HSCTLR definitions */ +#define HSCTLR_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 4) | (U(1) << 3)) + +#define HSCTLR_M_BIT (U(1) << 0) +#define HSCTLR_A_BIT (U(1) << 1) +#define HSCTLR_C_BIT (U(1) << 2) +#define HSCTLR_CP15BEN_BIT (U(1) << 5) +#define HSCTLR_ITD_BIT (U(1) << 7) +#define HSCTLR_SED_BIT (U(1) << 8) +#define HSCTLR_I_BIT (U(1) << 12) +#define HSCTLR_WXN_BIT (U(1) << 19) +#define HSCTLR_EE_BIT (U(1) << 25) +#define HSCTLR_TE_BIT (U(1) << 30) + +/* CPACR definitions */ +#define CPACR_FPEN(x) ((x) << 20) +#define CPACR_FP_TRAP_PL0 UL(0x1) +#define CPACR_FP_TRAP_ALL UL(0x2) +#define CPACR_FP_TRAP_NONE UL(0x3) + +/* SCR definitions */ +#define SCR_TWE_BIT (UL(1) << 13) +#define SCR_TWI_BIT (UL(1) << 12) +#define SCR_SIF_BIT (UL(1) << 9) +#define SCR_HCE_BIT (UL(1) << 8) +#define SCR_SCD_BIT (UL(1) << 7) +#define SCR_NET_BIT (UL(1) << 6) +#define SCR_AW_BIT (UL(1) << 5) +#define SCR_FW_BIT (UL(1) << 4) +#define SCR_EA_BIT (UL(1) << 3) +#define SCR_FIQ_BIT (UL(1) << 2) +#define SCR_IRQ_BIT (UL(1) << 1) +#define SCR_NS_BIT (UL(1) << 0) +#define SCR_VALID_BIT_MASK U(0x33ff) +#define SCR_RESET_VAL U(0x0) + +#define GET_NS_BIT(scr) ((scr) & SCR_NS_BIT) + +/* HCR definitions */ +#define HCR_TGE_BIT (U(1) << 27) +#define HCR_AMO_BIT (U(1) << 5) +#define HCR_IMO_BIT (U(1) << 4) +#define HCR_FMO_BIT (U(1) << 3) +#define HCR_RESET_VAL U(0x0) + +/* CNTHCTL definitions */ +#define CNTHCTL_RESET_VAL U(0x0) +#define PL1PCEN_BIT (U(1) << 1) +#define PL1PCTEN_BIT (U(1) << 0) + +/* CNTKCTL definitions */ +#define PL0PTEN_BIT (U(1) << 9) +#define PL0VTEN_BIT (U(1) << 8) +#define PL0PCTEN_BIT (U(1) << 0) +#define PL0VCTEN_BIT (U(1) << 1) +#define EVNTEN_BIT (U(1) << 2) +#define EVNTDIR_BIT (U(1) << 3) +#define EVNTI_SHIFT U(4) +#define EVNTI_MASK U(0xf) + +/* HCPTR definitions */ +#define HCPTR_RES1 ((U(1) << 13) | (U(1) << 12) | U(0x3ff)) +#define TCPAC_BIT (U(1) << 31) +#define TAM_SHIFT U(30) +#define TAM_BIT (U(1) << TAM_SHIFT) +#define TTA_BIT (U(1) << 20) +#define TCP11_BIT (U(1) << 11) +#define TCP10_BIT (U(1) << 10) +#define HCPTR_RESET_VAL HCPTR_RES1 + +/* VTTBR defintions */ +#define VTTBR_RESET_VAL ULL(0x0) +#define VTTBR_VMID_MASK ULL(0xff) +#define VTTBR_VMID_SHIFT U(48) +#define VTTBR_BADDR_MASK ULL(0xffffffffffff) +#define VTTBR_BADDR_SHIFT U(0) + +/* HDCR definitions */ +#define HDCR_MTPME_BIT (U(1) << 28) +#define HDCR_HLP_BIT (U(1) << 26) +#define HDCR_HPME_BIT (U(1) << 7) +#define HDCR_RESET_VAL U(0x0) + +/* HSTR definitions */ +#define HSTR_RESET_VAL U(0x0) + +/* CNTHP_CTL definitions */ +#define CNTHP_CTL_RESET_VAL U(0x0) + +/* NSACR definitions */ +#define NSASEDIS_BIT (U(1) << 15) +#define NSTRCDIS_BIT (U(1) << 20) +#define NSACR_CP11_BIT (U(1) << 11) +#define NSACR_CP10_BIT (U(1) << 10) +#define NSACR_IMP_DEF_MASK (U(0x7) << 16) +#define NSACR_ENABLE_FP_ACCESS (NSACR_CP11_BIT | NSACR_CP10_BIT) +#define NSACR_RESET_VAL U(0x0) + +/* CPACR definitions */ +#define ASEDIS_BIT (U(1) << 31) +#define TRCDIS_BIT (U(1) << 28) +#define CPACR_CP11_SHIFT U(22) +#define CPACR_CP10_SHIFT U(20) +#define CPACR_ENABLE_FP_ACCESS ((U(0x3) << CPACR_CP11_SHIFT) |\ + (U(0x3) << CPACR_CP10_SHIFT)) +#define CPACR_RESET_VAL U(0x0) + +/* FPEXC definitions */ +#define FPEXC_RES1 ((U(1) << 10) | (U(1) << 9) | (U(1) << 8)) +#define FPEXC_EN_BIT (U(1) << 30) +#define FPEXC_RESET_VAL FPEXC_RES1 + +/* SPSR/CPSR definitions */ +#define SPSR_FIQ_BIT (U(1) << 0) +#define SPSR_IRQ_BIT (U(1) << 1) +#define SPSR_ABT_BIT (U(1) << 2) +#define SPSR_AIF_SHIFT U(6) +#define SPSR_AIF_MASK U(0x7) + +#define SPSR_E_SHIFT U(9) +#define SPSR_E_MASK U(0x1) +#define SPSR_E_LITTLE U(0) +#define SPSR_E_BIG U(1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0) +#define SPSR_T_THUMB U(1) + +#define SPSR_MODE_SHIFT U(0) +#define SPSR_MODE_MASK U(0x7) + +#define SPSR_SSBS_BIT BIT_32(23) + +#define DISABLE_ALL_EXCEPTIONS \ + (SPSR_FIQ_BIT | SPSR_IRQ_BIT | SPSR_ABT_BIT) + +#define CPSR_DIT_BIT (U(1) << 21) +/* + * TTBCR definitions + */ +#define TTBCR_EAE_BIT (U(1) << 31) + +#define TTBCR_SH1_NON_SHAREABLE (U(0x0) << 28) +#define TTBCR_SH1_OUTER_SHAREABLE (U(0x2) << 28) +#define TTBCR_SH1_INNER_SHAREABLE (U(0x3) << 28) + +#define TTBCR_RGN1_OUTER_NC (U(0x0) << 26) +#define TTBCR_RGN1_OUTER_WBA (U(0x1) << 26) +#define TTBCR_RGN1_OUTER_WT (U(0x2) << 26) +#define TTBCR_RGN1_OUTER_WBNA (U(0x3) << 26) + +#define TTBCR_RGN1_INNER_NC (U(0x0) << 24) +#define TTBCR_RGN1_INNER_WBA (U(0x1) << 24) +#define TTBCR_RGN1_INNER_WT (U(0x2) << 24) +#define TTBCR_RGN1_INNER_WBNA (U(0x3) << 24) + +#define TTBCR_EPD1_BIT (U(1) << 23) +#define TTBCR_A1_BIT (U(1) << 22) + +#define TTBCR_T1SZ_SHIFT U(16) +#define TTBCR_T1SZ_MASK U(0x7) +#define TTBCR_TxSZ_MIN U(0) +#define TTBCR_TxSZ_MAX U(7) + +#define TTBCR_SH0_NON_SHAREABLE (U(0x0) << 12) +#define TTBCR_SH0_OUTER_SHAREABLE (U(0x2) << 12) +#define TTBCR_SH0_INNER_SHAREABLE (U(0x3) << 12) + +#define TTBCR_RGN0_OUTER_NC (U(0x0) << 10) +#define TTBCR_RGN0_OUTER_WBA (U(0x1) << 10) +#define TTBCR_RGN0_OUTER_WT (U(0x2) << 10) +#define TTBCR_RGN0_OUTER_WBNA (U(0x3) << 10) + +#define TTBCR_RGN0_INNER_NC (U(0x0) << 8) +#define TTBCR_RGN0_INNER_WBA (U(0x1) << 8) +#define TTBCR_RGN0_INNER_WT (U(0x2) << 8) +#define TTBCR_RGN0_INNER_WBNA (U(0x3) << 8) + +#define TTBCR_EPD0_BIT (U(1) << 7) +#define TTBCR_T0SZ_SHIFT U(0) +#define TTBCR_T0SZ_MASK U(0x7) + +/* + * HTCR definitions + */ +#define HTCR_RES1 ((U(1) << 31) | (U(1) << 23)) + +#define HTCR_SH0_NON_SHAREABLE (U(0x0) << 12) +#define HTCR_SH0_OUTER_SHAREABLE (U(0x2) << 12) +#define HTCR_SH0_INNER_SHAREABLE (U(0x3) << 12) + +#define HTCR_RGN0_OUTER_NC (U(0x0) << 10) +#define HTCR_RGN0_OUTER_WBA (U(0x1) << 10) +#define HTCR_RGN0_OUTER_WT (U(0x2) << 10) +#define HTCR_RGN0_OUTER_WBNA (U(0x3) << 10) + +#define HTCR_RGN0_INNER_NC (U(0x0) << 8) +#define HTCR_RGN0_INNER_WBA (U(0x1) << 8) +#define HTCR_RGN0_INNER_WT (U(0x2) << 8) +#define HTCR_RGN0_INNER_WBNA (U(0x3) << 8) + +#define HTCR_T0SZ_SHIFT U(0) +#define HTCR_T0SZ_MASK U(0x7) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_32 U(0x1) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0x1f) +#define MODE32_usr U(0x10) +#define MODE32_fiq U(0x11) +#define MODE32_irq U(0x12) +#define MODE32_svc U(0x13) +#define MODE32_mon U(0x16) +#define MODE32_abt U(0x17) +#define MODE32_hyp U(0x1a) +#define MODE32_und U(0x1b) +#define MODE32_sys U(0x1f) + +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#define SPSR_MODE32(mode, isa, endian, aif) \ +( \ + ( \ + (MODE_RW_32 << MODE_RW_SHIFT) | \ + (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ + (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ + (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ + (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT) \ + ) & \ + (~(SPSR_SSBS_BIT)) \ +) + +/* + * TTBR definitions + */ +#define TTBR_CNP_BIT ULL(0x1) + +/* + * CTR definitions + */ +#define CTR_CWG_SHIFT U(24) +#define CTR_CWG_MASK U(0xf) +#define CTR_ERG_SHIFT U(20) +#define CTR_ERG_MASK U(0xf) +#define CTR_DMINLINE_SHIFT U(16) +#define CTR_DMINLINE_WIDTH U(4) +#define CTR_DMINLINE_MASK ((U(1) << 4) - U(1)) +#define CTR_L1IP_SHIFT U(14) +#define CTR_L1IP_MASK U(0x3) +#define CTR_IMINLINE_SHIFT U(0) +#define CTR_IMINLINE_MASK U(0xf) + +#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */ + +/* PMCR definitions */ +#define PMCR_N_SHIFT U(11) +#define PMCR_N_MASK U(0x1f) +#define PMCR_N_BITS (PMCR_N_MASK << PMCR_N_SHIFT) +#define PMCR_LP_BIT (U(1) << 7) +#define PMCR_LC_BIT (U(1) << 6) +#define PMCR_DP_BIT (U(1) << 5) +#define PMCR_RESET_VAL U(0x0) + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(0) +#define TLBI_ADDR_MASK U(0xFFFFF000) +#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTCTLBase Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +#define CNTCTLBASE_CNTFRQ U(0x0) +#define CNTNSAR U(0x4) +#define CNTNSAR_NS_SHIFT(x) (x) + +#define CNTACR_BASE(x) (U(0x40) + ((x) << 2)) +#define CNTACR_RPCT_SHIFT U(0x0) +#define CNTACR_RVCT_SHIFT U(0x1) +#define CNTACR_RFRQ_SHIFT U(0x2) +#define CNTACR_RVOFF_SHIFT U(0x3) +#define CNTACR_RWVT_SHIFT U(0x4) +#define CNTACR_RWPT_SHIFT U(0x5) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTBaseN Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +/* Physical Count register. */ +#define CNTPCT_LO U(0x0) +/* Counter Frequency register. */ +#define CNTBASEN_CNTFRQ U(0x10) +/* Physical Timer CompareValue register. */ +#define CNTP_CVAL_LO U(0x20) +/* Physical Timer Control register. */ +#define CNTP_CTL U(0x2c) + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT 0 +#define CNTP_CTL_IMASK_SHIFT 1 +#define CNTP_CTL_ISTATUS_SHIFT 2 + +#define CNTP_CTL_ENABLE_MASK U(1) +#define CNTP_CTL_IMASK_MASK U(1) +#define CNTP_CTL_ISTATUS_MASK U(1) + +/* MAIR macros */ +#define MAIR0_ATTR_SET(attr, index) ((attr) << ((index) << U(3))) +#define MAIR1_ATTR_SET(attr, index) ((attr) << (((index) - U(3)) << U(3))) + +/* System register defines The format is: coproc, opt1, CRn, CRm, opt2 */ +#define SCR p15, 0, c1, c1, 0 +#define SCTLR p15, 0, c1, c0, 0 +#define ACTLR p15, 0, c1, c0, 1 +#define SDCR p15, 0, c1, c3, 1 +#define MPIDR p15, 0, c0, c0, 5 +#define MIDR p15, 0, c0, c0, 0 +#define HVBAR p15, 4, c12, c0, 0 +#define VBAR p15, 0, c12, c0, 0 +#define MVBAR p15, 0, c12, c0, 1 +#define NSACR p15, 0, c1, c1, 2 +#define CPACR p15, 0, c1, c0, 2 +#define DCCIMVAC p15, 0, c7, c14, 1 +#define DCCMVAC p15, 0, c7, c10, 1 +#define DCIMVAC p15, 0, c7, c6, 1 +#define DCCISW p15, 0, c7, c14, 2 +#define DCCSW p15, 0, c7, c10, 2 +#define DCISW p15, 0, c7, c6, 2 +#define CTR p15, 0, c0, c0, 1 +#define CNTFRQ p15, 0, c14, c0, 0 +#define ID_MMFR4 p15, 0, c0, c2, 6 +#define ID_DFR0 p15, 0, c0, c1, 2 +#define ID_DFR1 p15, 0, c0, c3, 5 +#define ID_PFR0 p15, 0, c0, c1, 0 +#define ID_PFR1 p15, 0, c0, c1, 1 +#define MAIR0 p15, 0, c10, c2, 0 +#define MAIR1 p15, 0, c10, c2, 1 +#define TTBCR p15, 0, c2, c0, 2 +#define TTBR0 p15, 0, c2, c0, 0 +#define TTBR1 p15, 0, c2, c0, 1 +#define TLBIALL p15, 0, c8, c7, 0 +#define TLBIALLH p15, 4, c8, c7, 0 +#define TLBIALLIS p15, 0, c8, c3, 0 +#define TLBIMVA p15, 0, c8, c7, 1 +#define TLBIMVAA p15, 0, c8, c7, 3 +#define TLBIMVAAIS p15, 0, c8, c3, 3 +#define TLBIMVAHIS p15, 4, c8, c3, 1 +#define BPIALLIS p15, 0, c7, c1, 6 +#define BPIALL p15, 0, c7, c5, 6 +#define ICIALLU p15, 0, c7, c5, 0 +#define HSCTLR p15, 4, c1, c0, 0 +#define HCR p15, 4, c1, c1, 0 +#define HCPTR p15, 4, c1, c1, 2 +#define HSTR p15, 4, c1, c1, 3 +#define CNTHCTL p15, 4, c14, c1, 0 +#define CNTKCTL p15, 0, c14, c1, 0 +#define VPIDR p15, 4, c0, c0, 0 +#define VMPIDR p15, 4, c0, c0, 5 +#define ISR p15, 0, c12, c1, 0 +#define CLIDR p15, 1, c0, c0, 1 +#define CSSELR p15, 2, c0, c0, 0 +#define CCSIDR p15, 1, c0, c0, 0 +#define CCSIDR2 p15, 1, c0, c0, 2 +#define HTCR p15, 4, c2, c0, 2 +#define HMAIR0 p15, 4, c10, c2, 0 +#define ATS1CPR p15, 0, c7, c8, 0 +#define ATS1HR p15, 4, c7, c8, 0 +#define DBGOSDLR p14, 0, c1, c3, 4 + +/* Debug register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ +#define HDCR p15, 4, c1, c1, 1 +#define PMCR p15, 0, c9, c12, 0 +#define CNTHP_TVAL p15, 4, c14, c2, 0 +#define CNTHP_CTL p15, 4, c14, c2, 1 + +/* AArch32 coproc registers for 32bit MMU descriptor support */ +#define PRRR p15, 0, c10, c2, 0 +#define NMRR p15, 0, c10, c2, 1 +#define DACR p15, 0, c3, c0, 0 + +/* GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRn, CRm, opt2 */ +#define ICC_IAR1 p15, 0, c12, c12, 0 +#define ICC_IAR0 p15, 0, c12, c8, 0 +#define ICC_EOIR1 p15, 0, c12, c12, 1 +#define ICC_EOIR0 p15, 0, c12, c8, 1 +#define ICC_HPPIR1 p15, 0, c12, c12, 2 +#define ICC_HPPIR0 p15, 0, c12, c8, 2 +#define ICC_BPR1 p15, 0, c12, c12, 3 +#define ICC_BPR0 p15, 0, c12, c8, 3 +#define ICC_DIR p15, 0, c12, c11, 1 +#define ICC_PMR p15, 0, c4, c6, 0 +#define ICC_RPR p15, 0, c12, c11, 3 +#define ICC_CTLR p15, 0, c12, c12, 4 +#define ICC_MCTLR p15, 6, c12, c12, 4 +#define ICC_SRE p15, 0, c12, c12, 5 +#define ICC_HSRE p15, 4, c12, c9, 5 +#define ICC_MSRE p15, 6, c12, c12, 5 +#define ICC_IGRPEN0 p15, 0, c12, c12, 6 +#define ICC_IGRPEN1 p15, 0, c12, c12, 7 +#define ICC_MGRPEN1 p15, 6, c12, c12, 7 + +/* 64 bit system register defines The format is: coproc, opt1, CRm */ +#define TTBR0_64 p15, 0, c2 +#define TTBR1_64 p15, 1, c2 +#define CNTVOFF_64 p15, 4, c14 +#define VTTBR_64 p15, 6, c2 +#define CNTPCT_64 p15, 0, c14 +#define HTTBR_64 p15, 4, c2 +#define CNTHP_CVAL_64 p15, 6, c14 +#define PAR_64 p15, 0, c7 + +/* 64 bit GICv3 CPU Interface system register defines. The format is: coproc, opt1, CRm */ +#define ICC_SGI1R_EL1_64 p15, 0, c12 +#define ICC_ASGI1R_EL1_64 p15, 1, c12 +#define ICC_SGI0R_EL1_64 p15, 2, c12 + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE U(0x0) +#define MAIR_DEV_nGnRE U(0x4) +#define MAIR_DEV_nGRE U(0x8) +#define MAIR_DEV_GRE U(0xc) + +/* + * MAIR encodings for normal memory attributes. + * + * Cache Policy + * WT: Write Through + * WB: Write Back + * NC: Non-Cacheable + * + * Transient Hint + * NTR: Non-Transient + * TR: Transient + * + * Allocation Policy + * RA: Read Allocate + * WA: Write Allocate + * RWA: Read and Write Allocate + * NA: No Allocation + */ +#define MAIR_NORM_WT_TR_WA U(0x1) +#define MAIR_NORM_WT_TR_RA U(0x2) +#define MAIR_NORM_WT_TR_RWA U(0x3) +#define MAIR_NORM_NC U(0x4) +#define MAIR_NORM_WB_TR_WA U(0x5) +#define MAIR_NORM_WB_TR_RA U(0x6) +#define MAIR_NORM_WB_TR_RWA U(0x7) +#define MAIR_NORM_WT_NTR_NA U(0x8) +#define MAIR_NORM_WT_NTR_WA U(0x9) +#define MAIR_NORM_WT_NTR_RA U(0xa) +#define MAIR_NORM_WT_NTR_RWA U(0xb) +#define MAIR_NORM_WB_NTR_NA U(0xc) +#define MAIR_NORM_WB_NTR_WA U(0xd) +#define MAIR_NORM_WB_NTR_RA U(0xe) +#define MAIR_NORM_WB_NTR_RWA U(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ + ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/* PAR fields */ +#define PAR_F_SHIFT U(0) +#define PAR_F_MASK ULL(0x1) +#define PAR_ADDR_SHIFT U(12) +#define PAR_ADDR_MASK (BIT_64(40) - ULL(1)) /* 40-bits-wide page address */ + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1 + ******************************************************************************/ +#define AMCR p15, 0, c13, c2, 0 +#define AMCFGR p15, 0, c13, c2, 1 +#define AMCGCR p15, 0, c13, c2, 2 +#define AMUSERENR p15, 0, c13, c2, 3 +#define AMCNTENCLR0 p15, 0, c13, c2, 4 +#define AMCNTENSET0 p15, 0, c13, c2, 5 +#define AMCNTENCLR1 p15, 0, c13, c3, 0 +#define AMCNTENSET1 p15, 0, c13, c3, 1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00 p15, 0, c0 +#define AMEVCNTR01 p15, 1, c0 +#define AMEVCNTR02 p15, 2, c0 +#define AMEVCNTR03 p15, 3, c0 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00 p15, 0, c13, c6, 0 +#define AMEVTYPER01 p15, 0, c13, c6, 1 +#define AMEVTYPER02 p15, 0, c13, c6, 2 +#define AMEVTYPER03 p15, 0, c13, c6, 3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10 p15, 0, c4 +#define AMEVCNTR11 p15, 1, c4 +#define AMEVCNTR12 p15, 2, c4 +#define AMEVCNTR13 p15, 3, c4 +#define AMEVCNTR14 p15, 4, c4 +#define AMEVCNTR15 p15, 5, c4 +#define AMEVCNTR16 p15, 6, c4 +#define AMEVCNTR17 p15, 7, c4 +#define AMEVCNTR18 p15, 0, c5 +#define AMEVCNTR19 p15, 1, c5 +#define AMEVCNTR1A p15, 2, c5 +#define AMEVCNTR1B p15, 3, c5 +#define AMEVCNTR1C p15, 4, c5 +#define AMEVCNTR1D p15, 5, c5 +#define AMEVCNTR1E p15, 6, c5 +#define AMEVCNTR1F p15, 7, c5 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10 p15, 0, c13, c14, 0 +#define AMEVTYPER11 p15, 0, c13, c14, 1 +#define AMEVTYPER12 p15, 0, c13, c14, 2 +#define AMEVTYPER13 p15, 0, c13, c14, 3 +#define AMEVTYPER14 p15, 0, c13, c14, 4 +#define AMEVTYPER15 p15, 0, c13, c14, 5 +#define AMEVTYPER16 p15, 0, c13, c14, 6 +#define AMEVTYPER17 p15, 0, c13, c14, 7 +#define AMEVTYPER18 p15, 0, c13, c15, 0 +#define AMEVTYPER19 p15, 0, c13, c15, 1 +#define AMEVTYPER1A p15, 0, c13, c15, 2 +#define AMEVTYPER1B p15, 0, c13, c15, 3 +#define AMEVTYPER1C p15, 0, c13, c15, 4 +#define AMEVTYPER1D p15, 0, c13, c15, 5 +#define AMEVTYPER1E p15, 0, c13, c15, 6 +#define AMEVTYPER1F p15, 0, c13, c15, 7 + +/* AMCNTENSET0 definitions */ +#define AMCNTENSET0_Pn_SHIFT U(0) +#define AMCNTENSET0_Pn_MASK U(0xffff) + +/* AMCNTENSET1 definitions */ +#define AMCNTENSET1_Pn_SHIFT U(0) +#define AMCNTENSET1_Pn_MASK U(0xffff) + +/* AMCNTENCLR0 definitions */ +#define AMCNTENCLR0_Pn_SHIFT U(0) +#define AMCNTENCLR0_Pn_MASK U(0xffff) + +/* AMCNTENCLR1 definitions */ +#define AMCNTENCLR1_Pn_SHIFT U(0) +#define AMCNTENCLR1_Pn_MASK U(0xffff) + +/* AMCR definitions */ +#define AMCR_CG1RZ_SHIFT U(17) +#define AMCR_CG1RZ_BIT (ULL(1) << AMCR_CG1RZ_SHIFT) + +/* AMCFGR definitions */ +#define AMCFGR_NCG_SHIFT U(28) +#define AMCFGR_NCG_MASK U(0xf) +#define AMCFGR_N_SHIFT U(0) +#define AMCFGR_N_MASK U(0xff) + +/* AMCGCR definitions */ +#define AMCGCR_CG0NC_SHIFT U(0) +#define AMCGCR_CG0NC_MASK U(0xff) +#define AMCGCR_CG1NC_SHIFT U(8) +#define AMCGCR_CG1NC_MASK U(0xff) + +/******************************************************************************* + * Definitions for DynamicIQ Shared Unit registers + ******************************************************************************/ +#define CLUSTERPWRDN p15, 0, c15, c3, 6 + +/* CLUSTERPWRDN register definitions */ +#define DSU_CLUSTER_PWR_OFF 0 +#define DSU_CLUSTER_PWR_ON 1 +#define DSU_CLUSTER_PWR_MASK U(1) + +#endif /* ARCH_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/arch_features.h b/arm-trusted-firmware/include/arch/aarch32/arch_features.h new file mode 100644 index 0000000..ddf0968 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch_features.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_FEATURES_H +#define ARCH_FEATURES_H + +#include + +#include + +static inline bool is_armv7_gentimer_present(void) +{ + return ((read_id_pfr1() >> ID_PFR1_GENTIMER_SHIFT) & + ID_PFR1_GENTIMER_MASK) != 0U; +} + +static inline bool is_armv8_2_ttcnp_present(void) +{ + return ((read_id_mmfr4() >> ID_MMFR4_CNP_SHIFT) & + ID_MMFR4_CNP_MASK) != 0U; +} + +#endif /* ARCH_FEATURES_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h b/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h new file mode 100644 index 0000000..0330989 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/arch_helpers.h @@ -0,0 +1,470 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_HELPERS_H +#define ARCH_HELPERS_H + +#include +#include +#include +#include + +#include + +/********************************************************************** + * Macros which create inline functions to read or write CPU system + * registers + *********************************************************************/ + +#define _DEFINE_COPROCR_WRITE_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline void write_## _name(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC(_name, coproc, opc1, CRn, CRm, opc2) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrc "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : "=r" (v));\ + return v; \ +} + +/* + * The undocumented %Q and %R extended asm are used to implemented the below + * 64 bit `mrrc` and `mcrr` instructions. + */ + +#define _DEFINE_COPROCR_WRITE_FUNC_64(_name, coproc, opc1, CRm) \ +static inline void write64_## _name(uint64_t v) \ +{ \ + __asm__ volatile ("mcrr "#coproc","#opc1", %Q0, %R0,"#CRm : : "r" (v));\ +} + +#define _DEFINE_COPROCR_READ_FUNC_64(_name, coproc, opc1, CRm) \ +static inline uint64_t read64_## _name(void) \ +{ uint64_t v; \ + __asm__ volatile ("mrrc "#coproc","#opc1", %Q0, %R0,"#CRm : "=r" (v));\ + return v; \ +} + +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ +} + +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ +} + +#define _DEFINE_SYSREG_WRITE_CONST_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(const u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "i" (v)); \ +} + +/* Define read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) + +/* Define write function for coproc register */ +#define DEFINE_COPROCR_WRITE_FUNC(_name, ...) \ + _DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__) + +/* Define read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC(_name, __VA_ARGS__) + +/* Define 64 bit read function for coproc register */ +#define DEFINE_COPROCR_READ_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit write function for coproc register */ +#define DEFINE_COPROCR_WRITE_FUNC_64(_name, ...) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* Define 64 bit read & write function for coproc register */ +#define DEFINE_COPROCR_RW_FUNCS_64(_name, ...) \ + _DEFINE_COPROCR_READ_FUNC_64(_name, __VA_ARGS__) \ + _DEFINE_COPROCR_WRITE_FUNC_64(_name, __VA_ARGS__) + +/* Define read & write function for system register */ +#define DEFINE_SYSREG_RW_FUNCS(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _name) + +/********************************************************************** + * Macros to create inline functions for tlbi operations + *********************************************************************/ + +#define _DEFINE_TLBIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_BPIOP_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void bpi##_op(void) \ +{ \ + u_register_t v = 0; \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +#define _DEFINE_TLBIOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void tlbi##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for simple TLBI operation */ +#define DEFINE_TLBIOP_FUNC(_op, ...) \ + _DEFINE_TLBIOP_FUNC(_op, __VA_ARGS__) + +/* Define function for TLBI operation with register parameter */ +#define DEFINE_TLBIOP_PARAM_FUNC(_op, ...) \ + _DEFINE_TLBIOP_PARAM_FUNC(_op, __VA_ARGS__) + +/* Define function for simple BPI operation */ +#define DEFINE_BPIOP_FUNC(_op, ...) \ + _DEFINE_BPIOP_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * Macros to create inline functions for DC operations + *********************************************************************/ +#define _DEFINE_DCOP_PARAM_FUNC(_op, coproc, opc1, CRn, CRm, opc2) \ +static inline void dc##_op(u_register_t v) \ +{ \ + __asm__ volatile ("mcr "#coproc","#opc1",%0,"#CRn","#CRm","#opc2 : : "r" (v));\ +} + +/* Define function for DC operation with register parameter */ +#define DEFINE_DCOP_PARAM_FUNC(_op, ...) \ + _DEFINE_DCOP_PARAM_FUNC(_op, __VA_ARGS__) + +/********************************************************************** + * Macros to create inline functions for system instructions + *********************************************************************/ + /* Define function for simple system instruction */ +#define DEFINE_SYSOP_FUNC(_op) \ +static inline void _op(void) \ +{ \ + __asm__ (#_op); \ +} + + +/* Define function for system instruction with type specifier */ +#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ +static inline void _op ## _type(void) \ +{ \ + __asm__ (#_op " " #_type : : : "memory"); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ +static inline void _op ## _type(u_register_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +void flush_dcache_range(uintptr_t addr, size_t size); +void clean_dcache_range(uintptr_t addr, size_t size); +void inv_dcache_range(uintptr_t addr, size_t size); +bool is_dcache_enabled(void); + +void dcsw_op_louis(u_register_t op_type); +void dcsw_op_all(u_register_t op_type); + +void disable_mmu_secure(void); +void disable_mmu_icache_secure(void); + +DEFINE_SYSOP_FUNC(wfi) +DEFINE_SYSOP_FUNC(wfe) +DEFINE_SYSOP_FUNC(sev) +DEFINE_SYSOP_TYPE_FUNC(dsb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, st) + +/* dmb ld is not valid for armv7/thumb machines */ +#if ARM_ARCH_MAJOR != 7 +DEFINE_SYSOP_TYPE_FUNC(dmb, ld) +#endif + +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_FUNC(isb) + +void __dead2 smc(uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3, + uint32_t r4, uint32_t r5, uint32_t r6, uint32_t r7); + +DEFINE_SYSREG_RW_FUNCS(spsr) +DEFINE_SYSREG_RW_FUNCS(cpsr) + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_COPROCR_READ_FUNC(mpidr, MPIDR) +DEFINE_COPROCR_READ_FUNC(midr, MIDR) +DEFINE_COPROCR_READ_FUNC(id_mmfr4, ID_MMFR4) +DEFINE_COPROCR_READ_FUNC(id_dfr0, ID_DFR0) +DEFINE_COPROCR_READ_FUNC(id_pfr0, ID_PFR0) +DEFINE_COPROCR_READ_FUNC(id_pfr1, ID_PFR1) +DEFINE_COPROCR_READ_FUNC(isr, ISR) +DEFINE_COPROCR_READ_FUNC(clidr, CLIDR) +DEFINE_COPROCR_READ_FUNC_64(cntpct, CNTPCT_64) + +DEFINE_COPROCR_RW_FUNCS(scr, SCR) +DEFINE_COPROCR_RW_FUNCS(ctr, CTR) +DEFINE_COPROCR_RW_FUNCS(sctlr, SCTLR) +DEFINE_COPROCR_RW_FUNCS(actlr, ACTLR) +DEFINE_COPROCR_RW_FUNCS(hsctlr, HSCTLR) +DEFINE_COPROCR_RW_FUNCS(hcr, HCR) +DEFINE_COPROCR_RW_FUNCS(hcptr, HCPTR) +DEFINE_COPROCR_RW_FUNCS(cntfrq, CNTFRQ) +DEFINE_COPROCR_RW_FUNCS(cnthctl, CNTHCTL) +DEFINE_COPROCR_RW_FUNCS(mair0, MAIR0) +DEFINE_COPROCR_RW_FUNCS(mair1, MAIR1) +DEFINE_COPROCR_RW_FUNCS(hmair0, HMAIR0) +DEFINE_COPROCR_RW_FUNCS(ttbcr, TTBCR) +DEFINE_COPROCR_RW_FUNCS(htcr, HTCR) +DEFINE_COPROCR_RW_FUNCS(ttbr0, TTBR0) +DEFINE_COPROCR_RW_FUNCS_64(ttbr0, TTBR0_64) +DEFINE_COPROCR_RW_FUNCS(ttbr1, TTBR1) +DEFINE_COPROCR_RW_FUNCS_64(httbr, HTTBR_64) +DEFINE_COPROCR_RW_FUNCS(vpidr, VPIDR) +DEFINE_COPROCR_RW_FUNCS(vmpidr, VMPIDR) +DEFINE_COPROCR_RW_FUNCS_64(vttbr, VTTBR_64) +DEFINE_COPROCR_RW_FUNCS_64(ttbr1, TTBR1_64) +DEFINE_COPROCR_RW_FUNCS_64(cntvoff, CNTVOFF_64) +DEFINE_COPROCR_RW_FUNCS(csselr, CSSELR) +DEFINE_COPROCR_RW_FUNCS(hstr, HSTR) +DEFINE_COPROCR_RW_FUNCS(cnthp_ctl_el2, CNTHP_CTL) +DEFINE_COPROCR_RW_FUNCS(cnthp_tval_el2, CNTHP_TVAL) +DEFINE_COPROCR_RW_FUNCS_64(cnthp_cval_el2, CNTHP_CVAL_64) + +#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \ + CNTP_CTL_ENABLE_MASK) +#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \ + CNTP_CTL_IMASK_MASK) +#define get_cntp_ctl_istatus(x) (((x) >> CNTP_CTL_ISTATUS_SHIFT) & \ + CNTP_CTL_ISTATUS_MASK) + +#define set_cntp_ctl_enable(x) ((x) |= U(1) << CNTP_CTL_ENABLE_SHIFT) +#define set_cntp_ctl_imask(x) ((x) |= U(1) << CNTP_CTL_IMASK_SHIFT) + +#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT)) +#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT)) + +DEFINE_COPROCR_RW_FUNCS(icc_sre_el1, ICC_SRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el2, ICC_HSRE) +DEFINE_COPROCR_RW_FUNCS(icc_sre_el3, ICC_MSRE) +DEFINE_COPROCR_RW_FUNCS(icc_pmr_el1, ICC_PMR) +DEFINE_COPROCR_RW_FUNCS(icc_rpr_el1, ICC_RPR) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el3, ICC_MGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1) +DEFINE_COPROCR_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir0_el1, ICC_HPPIR0) +DEFINE_COPROCR_RW_FUNCS(icc_hppir1_el1, ICC_HPPIR1) +DEFINE_COPROCR_RW_FUNCS(icc_iar0_el1, ICC_IAR0) +DEFINE_COPROCR_RW_FUNCS(icc_iar1_el1, ICC_IAR1) +DEFINE_COPROCR_RW_FUNCS(icc_eoir0_el1, ICC_EOIR0) +DEFINE_COPROCR_RW_FUNCS(icc_eoir1_el1, ICC_EOIR1) +DEFINE_COPROCR_RW_FUNCS_64(icc_sgi0r_el1, ICC_SGI0R_EL1_64) +DEFINE_COPROCR_WRITE_FUNC_64(icc_sgi1r, ICC_SGI1R_EL1_64) + +DEFINE_COPROCR_RW_FUNCS(sdcr, SDCR) +DEFINE_COPROCR_RW_FUNCS(hdcr, HDCR) +DEFINE_COPROCR_RW_FUNCS(cnthp_ctl, CNTHP_CTL) +DEFINE_COPROCR_READ_FUNC(pmcr, PMCR) + +/* + * Address translation + */ +DEFINE_COPROCR_WRITE_FUNC(ats1cpr, ATS1CPR) +DEFINE_COPROCR_WRITE_FUNC(ats1hr, ATS1HR) +DEFINE_COPROCR_RW_FUNCS_64(par, PAR_64) + +DEFINE_COPROCR_RW_FUNCS(nsacr, NSACR) + +/* AArch32 coproc registers for 32bit MMU descriptor support */ +DEFINE_COPROCR_RW_FUNCS(prrr, PRRR) +DEFINE_COPROCR_RW_FUNCS(nmrr, NMRR) +DEFINE_COPROCR_RW_FUNCS(dacr, DACR) + +/* Coproc registers for 32bit AMU support */ +DEFINE_COPROCR_READ_FUNC(amcfgr, AMCFGR) +DEFINE_COPROCR_READ_FUNC(amcgcr, AMCGCR) +DEFINE_COPROCR_RW_FUNCS(amcr, AMCR) + +DEFINE_COPROCR_RW_FUNCS(amcntenset0, AMCNTENSET0) +DEFINE_COPROCR_RW_FUNCS(amcntenset1, AMCNTENSET1) +DEFINE_COPROCR_RW_FUNCS(amcntenclr0, AMCNTENCLR0) +DEFINE_COPROCR_RW_FUNCS(amcntenclr1, AMCNTENCLR1) + +/* Coproc registers for 64bit AMU support */ +DEFINE_COPROCR_RW_FUNCS_64(amevcntr00, AMEVCNTR00) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr01, AMEVCNTR01) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr02, AMEVCNTR02) +DEFINE_COPROCR_RW_FUNCS_64(amevcntr03, AMEVCNTR03) + +/* + * TLBI operation prototypes + */ +DEFINE_TLBIOP_FUNC(all, TLBIALL) +DEFINE_TLBIOP_FUNC(allis, TLBIALLIS) +DEFINE_TLBIOP_PARAM_FUNC(mva, TLBIMVA) +DEFINE_TLBIOP_PARAM_FUNC(mvaa, TLBIMVAA) +DEFINE_TLBIOP_PARAM_FUNC(mvaais, TLBIMVAAIS) +DEFINE_TLBIOP_PARAM_FUNC(mvahis, TLBIMVAHIS) + +/* + * BPI operation prototypes. + */ +DEFINE_BPIOP_FUNC(allis, BPIALLIS) + +/* + * DC operation prototypes + */ +DEFINE_DCOP_PARAM_FUNC(civac, DCCIMVAC) +DEFINE_DCOP_PARAM_FUNC(ivac, DCIMVAC) +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_PARAM_FUNC(cvac, DCCIMVAC) +#else +DEFINE_DCOP_PARAM_FUNC(cvac, DCCMVAC) +#endif + +/* + * DynamIQ Shared Unit power management + */ +DEFINE_COPROCR_RW_FUNCS(clusterpwrdn, CLUSTERPWRDN) + +/* Previously defined accessor functions with incomplete register names */ +#define dsb() dsbsy() +#define dmb() dmbsy() + +/* dmb ld is not valid for armv7/thumb machines, so alias it to dmb */ +#if ARM_ARCH_MAJOR == 7 +#define dmbld() dmb() +#endif + +#define IS_IN_SECURE() \ + (GET_NS_BIT(read_scr()) == 0) + +#define IS_IN_HYP() (GET_M32(read_cpsr()) == MODE32_hyp) +#define IS_IN_SVC() (GET_M32(read_cpsr()) == MODE32_svc) +#define IS_IN_MON() (GET_M32(read_cpsr()) == MODE32_mon) +#define IS_IN_EL2() IS_IN_HYP() +/* If EL3 is AArch32, then secure PL1 and monitor mode correspond to EL3 */ +#define IS_IN_EL3() \ + ((GET_M32(read_cpsr()) == MODE32_mon) || \ + (IS_IN_SECURE() && (GET_M32(read_cpsr()) != MODE32_usr))) + +static inline unsigned int get_current_el(void) +{ + if (IS_IN_EL3()) { + return 3U; + } else if (IS_IN_EL2()) { + return 2U; + } else { + return 1U; + } +} + +/* Macros for compatibility with AArch64 system registers */ +#define read_mpidr_el1() read_mpidr() + +#define read_scr_el3() read_scr() +#define write_scr_el3(_v) write_scr(_v) + +#define read_hcr_el2() read_hcr() +#define write_hcr_el2(_v) write_hcr(_v) + +#define read_cpacr_el1() read_cpacr() +#define write_cpacr_el1(_v) write_cpacr(_v) + +#define read_cntfrq_el0() read_cntfrq() +#define write_cntfrq_el0(_v) write_cntfrq(_v) +#define read_isr_el1() read_isr() + +#define read_cntpct_el0() read64_cntpct() + +#define read_ctr_el0() read_ctr() + +#define write_icc_sgi0r_el1(_v) write64_icc_sgi0r_el1(_v) + +#define read_daif() read_cpsr() +#define write_daif(flags) write_cpsr(flags) + +#define read_cnthp_cval_el2() read64_cnthp_cval_el2() +#define write_cnthp_cval_el2(v) write64_cnthp_cval_el2(v) + +#define read_amcntenset0_el0() read_amcntenset0() +#define read_amcntenset1_el0() read_amcntenset1() + +/* Helper functions to manipulate CPSR */ +static inline void enable_irq(void) +{ + /* + * The compiler memory barrier will prevent the compiler from + * scheduling non-volatile memory access after the write to the + * register. + * + * This could happen if some initialization code issues non-volatile + * accesses to an area used by an interrupt handler, in the assumption + * that it is safe as the interrupts are disabled at the time it does + * that (according to program order). However, non-volatile accesses + * are not necessarily in program order relatively with volatile inline + * assembly statements (and volatile accesses). + */ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie i"); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie a"); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsie f"); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid i"); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid a"); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + __asm__ volatile ("cpsid f"); + isb(); +} + +#endif /* ARCH_HELPERS_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/asm_macros.S b/arm-trusted-firmware/include/arch/aarch32/asm_macros.S new file mode 100644 index 0000000..483f9fe --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/asm_macros.S @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_S +#define ASM_MACROS_S + +#include +#include +#include + +/* + * TLBI instruction with type specifier that implements the workaround for + * errata 813419 of Cortex-A57. + */ +#if ERRATA_A57_813419 +#define TLB_INVALIDATE(_reg, _coproc) \ + stcopr _reg, _coproc; \ + dsb ish; \ + stcopr _reg, _coproc +#else +#define TLB_INVALIDATE(_reg, _coproc) \ + stcopr _reg, _coproc +#endif + +#define WORD_SIZE 4 + + /* + * Co processor register accessors + */ + .macro ldcopr reg, coproc, opc1, CRn, CRm, opc2 + mrc \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro ldcopr16 reg1, reg2, coproc, opc1, CRm + mrrc \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + .macro stcopr reg, coproc, opc1, CRn, CRm, opc2 + mcr \coproc, \opc1, \reg, \CRn, \CRm, \opc2 + .endm + + .macro stcopr16 reg1, reg2, coproc, opc1, CRm + mcrr \coproc, \opc1, \reg1, \reg2, \CRm + .endm + + /* Cache line size helpers */ + .macro dcache_line_size reg, tmp + ldcopr \tmp, CTR + ubfx \tmp, \tmp, #CTR_DMINLINE_SHIFT, #CTR_DMINLINE_WIDTH + mov \reg, #WORD_SIZE + lsl \reg, \reg, \tmp + .endm + + .macro icache_line_size reg, tmp + ldcopr \tmp, CTR + and \tmp, \tmp, #CTR_IMINLINE_MASK + mov \reg, #WORD_SIZE + lsl \reg, \reg, \tmp + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 32 byte boundary. + */ + .macro vector_base label + .section .vectors, "ax" + .align 5 + \label: + .endm + + /* + * This macro calculates the base address of the current CPU's multi + * processor(MP) stack using the plat_my_core_pos() index, the name of + * the stack storage and the size of each stack. + * Out: r0 = physical address of stack base + * Clobber: r14, r1, r2 + */ + .macro get_my_mp_stack _name, _size + bl plat_my_core_pos + ldr r2, =(\_name + \_size) + mov r1, #\_size + mla r0, r0, r1, r2 + .endm + + /* + * This macro calculates the base address of a uniprocessor(UP) stack + * using the name of the stack storage and the size of the stack + * Out: r0 = physical address of stack base + */ + .macro get_up_stack _name, _size + ldr r0, =(\_name + \_size) + .endm + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* + * Macro for mitigating against speculative execution. + * ARMv7 cores without Virtualization extension do not support the + * eret instruction. + */ + .macro exception_return + movs pc, lr + dsb nsh + isb + .endm + +#else + /* + * Macro for mitigating against speculative execution beyond ERET. Uses the + * speculation barrier instruction introduced by FEAT_SB, if it's enabled. + */ + .macro exception_return + eret +#if ENABLE_FEAT_SB + sb +#else + dsb nsh + isb +#endif + .endm +#endif + +#if (ARM_ARCH_MAJOR == 7) + /* ARMv7 does not support stl instruction */ + .macro stl _reg, _write_lock + dmb + str \_reg, \_write_lock + dsb + .endm +#endif + + /* + * Helper macro to generate the best mov/movw/movt combinations + * according to the value to be moved. + */ + .macro mov_imm _reg, _val + .if ((\_val) & 0xffff0000) == 0 + mov \_reg, #(\_val) + .else + movw \_reg, #((\_val) & 0xffff) + movt \_reg, #((\_val) >> 16) + .endif + .endm + + /* + * Macro to mark instances where we're jumping to a function and don't + * expect a return. To provide the function being jumped to with + * additional information, we use 'bl' instruction to jump rather than + * 'b'. + * + * Debuggers infer the location of a call from where LR points to, which + * is usually the instruction after 'bl'. If this macro expansion + * happens to be the last location in a function, that'll cause the LR + * to point a location beyond the function, thereby misleading debugger + * back trace. We therefore insert a 'nop' after the function call for + * debug builds, unless 'skip_nop' parameter is non-zero. + */ + .macro no_ret _func:req, skip_nop=0 + bl \_func +#if DEBUG + .ifeq \skip_nop + nop + .endif +#endif + .endm + + /* + * Reserve space for a spin lock in assembly file. + */ + .macro define_asm_spinlock _name:req + .align SPINLOCK_ASM_ALIGN + \_name: + .space SPINLOCK_ASM_SIZE + .endm + + /* + * Helper macro to OR the bottom 32 bits of `_val` into `_reg_l` + * and the top 32 bits of `_val` into `_reg_h`. If either the bottom + * or top word of `_val` is zero, the corresponding OR operation + * is skipped. + */ + .macro orr64_imm _reg_l, _reg_h, _val + .if (\_val >> 32) + orr \_reg_h, \_reg_h, #(\_val >> 32) + .endif + .if (\_val & 0xffffffff) + orr \_reg_l, \_reg_l, #(\_val & 0xffffffff) + .endif + .endm + + /* + * Helper macro to bitwise-clear bits in `_reg_l` and + * `_reg_h` given a 64 bit immediate `_val`. The set bits + * in the bottom word of `_val` dictate which bits from + * `_reg_l` should be cleared. Similarly, the set bits in + * the top word of `_val` dictate which bits from `_reg_h` + * should be cleared. If either the bottom or top word of + * `_val` is zero, the corresponding BIC operation is skipped. + */ + .macro bic64_imm _reg_l, _reg_h, _val + .if (\_val >> 32) + bic \_reg_h, \_reg_h, #(\_val >> 32) + .endif + .if (\_val & 0xffffffff) + bic \_reg_l, \_reg_l, #(\_val & 0xffffffff) + .endif + .endm + + /* + * Helper macro for carrying out division in software when + * hardware division is not suported. \top holds the dividend + * in the function call and the remainder after + * the function is executed. \bot holds the divisor. \div holds + * the quotient and \temp is a temporary registed used in calcualtion. + * The division algorithm has been obtained from: + * http://www.keil.com/support/man/docs/armasm/armasm_dom1359731155623.htm + */ + .macro softudiv div:req,top:req,bot:req,temp:req + + mov \temp, \bot + cmp \temp, \top, lsr #1 +div1: + movls \temp, \temp, lsl #1 + cmp \temp, \top, lsr #1 + bls div1 + mov \div, #0 + +div2: + cmp \top, \temp + subcs \top, \top,\temp + ADC \div, \div, \div + mov \temp, \temp, lsr #1 + cmp \temp, \bot + bhs div2 + .endm +#endif /* ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/assert_macros.S b/arm-trusted-firmware/include/arch/aarch32/assert_macros.S new file mode 100644 index 0000000..ab3a2eb --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/assert_macros.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASSERT_MACROS_S +#define ASSERT_MACROS_S + + /* + * Assembler macro to enable asm_assert. We assume that the stack is + * initialized prior to invoking this macro. + */ +#define ASM_ASSERT(_cc) \ +.ifndef .L_assert_filename ;\ + .pushsection .rodata.str1.1, "aS" ;\ + .L_assert_filename: ;\ + .string __FILE__ ;\ + .popsection ;\ +.endif ;\ + b##_cc 300f ;\ + ldr r0, =.L_assert_filename ;\ + ldr r1, =__LINE__ ;\ + b asm_assert;\ +300: + +#endif /* ASSERT_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/console_macros.S b/arm-trusted-firmware/include/arch/aarch32/console_macros.S new file mode 100644 index 0000000..996cb32 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/console_macros.S @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CONSOLE_MACROS_S +#define CONSOLE_MACROS_S + +#include + +/* + * This macro encapsulates the common setup that has to be done at the end of + * a console driver's register function. It will register all of the driver's + * callbacks in the console_t structure and initialize the flags field (by + * default consoles are enabled for the "boot" and "crash" states, this can be + * changed after registration with the console_set_scope() function). It ends + * with a tail call that will include return to the caller. + * REQUIRES console_t pointer in r0 and a valid return address in lr. + */ + .macro finish_console_register _driver, putc=0, getc=0, flush=0 + /* + * If any of the callback is not specified or set as 0, then the + * corresponding callback entry in console_t is set to 0. + */ + .ifne \putc + ldr r1, =console_\_driver\()_putc + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_PUTC] + + .ifne \getc + ldr r1, =console_\_driver\()_getc + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_GETC] + + .ifne \flush + ldr r1, =console_\_driver\()_flush + .else + mov r1, #0 + .endif + str r1, [r0, #CONSOLE_T_FLUSH] + + mov r1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) + str r1, [r0, #CONSOLE_T_FLAGS] + b console_register + .endm + +#endif /* CONSOLE_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S b/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S new file mode 100644 index 0000000..8b6765a --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S @@ -0,0 +1,458 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EL3_COMMON_MACROS_S +#define EL3_COMMON_MACROS_S + +#include +#include +#include +#include + +#define PAGE_START_MASK ~(PAGE_SIZE_MASK) + + /* + * Helper macro to initialise EL3 registers we care about. + */ + .macro el3_arch_init_common + /* --------------------------------------------------------------------- + * SCTLR has already been initialised - read current value before + * modifying. + * + * SCTLR.I: Enable the instruction cache. + * + * SCTLR.A: Enable Alignment fault checking. All instructions that load + * or store one or more registers have an alignment check that the + * address being accessed is aligned to the size of the data element(s) + * being accessed. + * --------------------------------------------------------------------- + */ + ldr r1, =(SCTLR_I_BIT | SCTLR_A_BIT) + ldcopr r0, SCTLR + orr r0, r0, r1 + stcopr r0, SCTLR + isb + + /* --------------------------------------------------------------------- + * Initialise SCR, setting all fields rather than relying on the hw. + * + * SCR.SIF: Enabled so that Secure state instruction fetches from + * Non-secure memory are not permitted. + * --------------------------------------------------------------------- + */ + ldr r0, =(SCR_RESET_VAL | SCR_SIF_BIT) + stcopr r0, SCR + + /* ----------------------------------------------------- + * Enable the Asynchronous data abort now that the + * exception vectors have been setup. + * ----------------------------------------------------- + */ + cpsie a + isb + + /* --------------------------------------------------------------------- + * Initialise NSACR, setting all the fields, except for the + * IMPLEMENTATION DEFINED field, rather than relying on the hw. Some + * fields are architecturally UNKNOWN on reset. + * + * NSACR_ENABLE_FP_ACCESS: Represents NSACR.cp11 and NSACR.cp10. The + * cp11 field is ignored, but is set to same value as cp10. The cp10 + * field is set to allow access to Advanced SIMD and floating point + * features from both Security states. + * + * NSACR.NSTRCDIS: When system register trace implemented, Set to one + * so that NS System register accesses to all implemented trace + * registers are disabled. + * When system register trace is not implemented, this bit is RES0 and + * hence set to zero. + * --------------------------------------------------------------------- + */ + ldcopr r0, NSACR + and r0, r0, #NSACR_IMP_DEF_MASK + orr r0, r0, #(NSACR_RESET_VAL | NSACR_ENABLE_FP_ACCESS) + ldcopr r1, ID_DFR0 + ubfx r1, r1, #ID_DFR0_COPTRC_SHIFT, #ID_DFR0_COPTRC_LENGTH + cmp r1, #ID_DFR0_COPTRC_SUPPORTED + bne 1f + orr r0, r0, #NSTRCDIS_BIT +1: + stcopr r0, NSACR + isb + + /* --------------------------------------------------------------------- + * Initialise CPACR, setting all fields rather than relying on hw. Some + * fields are architecturally UNKNOWN on reset. + * + * CPACR.TRCDIS: Trap control for PL0 and PL1 System register accesses + * to trace registers. Set to zero to allow access. + * + * CPACR_ENABLE_FP_ACCESS: Represents CPACR.cp11 and CPACR.cp10. The + * cp11 field is ignored, but is set to same value as cp10. The cp10 + * field is set to allow full access from PL0 and PL1 to floating-point + * and Advanced SIMD features. + * --------------------------------------------------------------------- + */ + ldr r0, =((CPACR_RESET_VAL | CPACR_ENABLE_FP_ACCESS) & ~(TRCDIS_BIT)) + stcopr r0, CPACR + isb + + /* --------------------------------------------------------------------- + * Initialise FPEXC, setting all fields rather than relying on hw. Some + * fields are architecturally UNKNOWN on reset and are set to zero + * except for field(s) listed below. + * + * FPEXC.EN: Enable access to Advanced SIMD and floating point features + * from all exception levels. + * + * __SOFTFP__: Predefined macro exposed by soft-float toolchain. + * ARMv7 and Cortex-A32(ARMv8/aarch32) has both soft-float and + * hard-float variants of toolchain, avoid compiling below code with + * soft-float toolchain as "vmsr" instruction will not be recognized. + * --------------------------------------------------------------------- + */ +#if ((ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_VFP)) && !(__SOFTFP__) + ldr r0, =(FPEXC_RESET_VAL | FPEXC_EN_BIT) + vmsr FPEXC, r0 + isb +#endif + +#if (ARM_ARCH_MAJOR > 7) + /* --------------------------------------------------------------------- + * Initialise SDCR, setting all the fields rather than relying on hw. + * + * SDCR.SPD: Disable AArch32 privileged debug. Debug exceptions from + * Secure EL1 are disabled. + * + * SDCR.SCCD: Set to one so that cycle counting by PMCCNTR is prohibited + * in Secure state. This bit is RES0 in versions of the architecture + * earlier than ARMv8.5, setting it to 1 doesn't have any effect on + * them. + * + * SDCR.TTRF: Set to one so that access to trace filter control + * registers in non-monitor mode generate Monitor trap exception, + * unless the access generates a higher priority exception when + * trace filter control(FEAT_TRF) is implemented. + * When FEAT_TRF is not implemented, this bit is RES0. + * --------------------------------------------------------------------- + */ + ldr r0, =((SDCR_RESET_VAL | SDCR_SPD(SDCR_SPD_DISABLE) | \ + SDCR_SCCD_BIT) & ~SDCR_TTRF_BIT) + ldcopr r1, ID_DFR0 + ubfx r1, r1, #ID_DFR0_TRACEFILT_SHIFT, #ID_DFR0_TRACEFILT_LENGTH + cmp r1, #ID_DFR0_TRACEFILT_SUPPORTED + bne 1f + orr r0, r0, #SDCR_TTRF_BIT +1: + stcopr r0, SDCR + + /* --------------------------------------------------------------------- + * Initialise PMCR, setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * PMCR.LP: Set to one so that event counter overflow, that + * is recorded in PMOVSCLR[0-30], occurs on the increment + * that changes PMEVCNTR[63] from 1 to 0, when ARMv8.5-PMU + * is implemented. This bit is RES0 in versions of the architecture + * earlier than ARMv8.5, setting it to 1 doesn't have any effect + * on them. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * PMCR.LC: Set to one so that cycle counter overflow, that + * is recorded in PMOVSCLR[31], occurs on the increment + * that changes PMCCNTR[63] from 1 to 0. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * PMCR.DP: Set to one to prohibit cycle counting whilst in Secure mode. + * --------------------------------------------------------------------- + */ + ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT | PMCR_LC_BIT | \ + PMCR_LP_BIT) +#else + ldr r0, =(PMCR_RESET_VAL | PMCR_DP_BIT) +#endif + stcopr r0, PMCR + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3 + */ + ldcopr r0, ID_PFR0 + and r0, r0, #(ID_PFR0_DIT_MASK << ID_PFR0_DIT_SHIFT) + cmp r0, #ID_PFR0_DIT_SUPPORTED + bne 1f + mrs r0, cpsr + orr r0, r0, #CPSR_DIT_BIT + msr cpsr_cxsf, r0 +1: + .endm + +/* ----------------------------------------------------------------------------- + * This is the super set of actions that need to be performed during a cold boot + * or a warm boot in EL3. This code is shared by BL1 and BL32 (SP_MIN). + * + * This macro will always perform reset handling, architectural initialisations + * and stack setup. The rest of the actions are optional because they might not + * be needed, depending on the context in which this macro is called. This is + * why this macro is parameterised ; each parameter allows to enable/disable + * some actions. + * + * _init_sctlr: + * Whether the macro needs to initialise the SCTLR register including + * configuring the endianness of data accesses. + * + * _warm_boot_mailbox: + * Whether the macro needs to detect the type of boot (cold/warm). The + * detection is based on the platform entrypoint address : if it is zero + * then it is a cold boot, otherwise it is a warm boot. In the latter case, + * this macro jumps on the platform entrypoint address. + * + * _secondary_cold_boot: + * Whether the macro needs to identify the CPU that is calling it: primary + * CPU or secondary CPU. The primary CPU will be allowed to carry on with + * the platform initialisations, while the secondaries will be put in a + * platform-specific state in the meantime. + * + * If the caller knows this macro will only be called by the primary CPU + * then this parameter can be defined to 0 to skip this step. + * + * _init_memory: + * Whether the macro needs to initialise the memory. + * + * _init_c_runtime: + * Whether the macro needs to initialise the C runtime environment. + * + * _exception_vectors: + * Address of the exception vectors to program in the VBAR_EL3 register. + * + * _pie_fixup_size: + * Size of memory region to fixup Global Descriptor Table (GDT). + * + * A non-zero value is expected when firmware needs GDT to be fixed-up. + * + * ----------------------------------------------------------------------------- + */ + .macro el3_entrypoint_common \ + _init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \ + _init_memory, _init_c_runtime, _exception_vectors, \ + _pie_fixup_size + + /* Make sure we are in Secure Mode */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCR + tst r0, #SCR_NS_BIT + ASM_ASSERT(eq) +#endif + + .if \_init_sctlr + /* ------------------------------------------------------------- + * This is the initialisation of SCTLR and so must ensure that + * all fields are explicitly set rather than relying on hw. Some + * fields reset to an IMPLEMENTATION DEFINED value. + * + * SCTLR.TE: Set to zero so that exceptions to an Exception + * Level executing at PL1 are taken to A32 state. + * + * SCTLR.EE: Set the CPU endianness before doing anything that + * might involve memory reads or writes. Set to zero to select + * Little Endian. + * + * SCTLR.V: Set to zero to select the normal exception vectors + * with base address held in VBAR. + * + * SCTLR.DSSBS: Set to zero to disable speculation store bypass + * safe behaviour upon exception entry to EL3. + * ------------------------------------------------------------- + */ + ldr r0, =(SCTLR_RESET_VAL & ~(SCTLR_TE_BIT | SCTLR_EE_BIT | \ + SCTLR_V_BIT | SCTLR_DSSBS_BIT)) + stcopr r0, SCTLR + isb + .endif /* _init_sctlr */ + + /* Switch to monitor mode */ + cps #MODE32_mon + isb + +#if DISABLE_MTPMU + bl mtpmu_disable +#endif + + .if \_warm_boot_mailbox + /* ------------------------------------------------------------- + * This code will be executed for both warm and cold resets. + * Now is the time to distinguish between the two. + * Query the platform entrypoint address and if it is not zero + * then it means it is a warm boot so jump to this address. + * ------------------------------------------------------------- + */ + bl plat_get_my_entrypoint + cmp r0, #0 + bxne r0 + .endif /* _warm_boot_mailbox */ + + .if \_pie_fixup_size +#if ENABLE_PIE + /* + * ------------------------------------------------------------ + * If PIE is enabled fixup the Global descriptor Table only + * once during primary core cold boot path. + * + * Compile time base address, required for fixup, is calculated + * using "pie_fixup" label present within first page. + * ------------------------------------------------------------ + */ + pie_fixup: + ldr r0, =pie_fixup + ldr r1, =PAGE_START_MASK + and r0, r0, r1 + mov_imm r1, \_pie_fixup_size + add r1, r1, r0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + .endif /* _pie_fixup_size */ + + /* --------------------------------------------------------------------- + * Set the exception vectors (VBAR/MVBAR). + * --------------------------------------------------------------------- + */ + ldr r0, =\_exception_vectors + stcopr r0, VBAR + stcopr r0, MVBAR + isb + + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler + + el3_arch_init_common + + .if \_secondary_cold_boot + /* ------------------------------------------------------------- + * Check if this is a primary or secondary CPU cold boot. + * The primary CPU will set up the platform while the + * secondaries are placed in a platform-specific state until the + * primary CPU performs the necessary actions to bring them out + * of that state and allows entry into the OS. + * ------------------------------------------------------------- + */ + bl plat_is_my_cpu_primary + cmp r0, #0 + bne do_primary_cold_boot + + /* This is a cold boot on a secondary CPU */ + bl plat_secondary_cold_boot_setup + /* plat_secondary_cold_boot_setup() is not supposed to return */ + no_ret plat_panic_handler + + do_primary_cold_boot: + .endif /* _secondary_cold_boot */ + + /* --------------------------------------------------------------------- + * Initialize memory now. Secondary CPU initialization won't get to this + * point. + * --------------------------------------------------------------------- + */ + + .if \_init_memory + bl platform_mem_init + .endif /* _init_memory */ + + /* --------------------------------------------------------------------- + * Init C runtime environment: + * - Zero-initialise the NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section (if any). + * - Relocate the data section from ROM to RAM, if required. + * --------------------------------------------------------------------- + */ + .if \_init_c_runtime +#if defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) + /* ----------------------------------------------------------------- + * Invalidate the RW memory used by the image. This + * includes the data and NOBITS sections. This is done to + * safeguard against possible corruption of this memory by + * dirty cache lines in a system cache as a result of use by + * an earlier boot loader stage. If PIE is enabled however, + * RO sections including the GOT may be modified during + * pie fixup. Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * ----------------------------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + ldr r0, =__TEXT_START__ +#else + ldr r0, =__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + ldr r0, =__RW_START__ +#endif /* ENABLE_PIE */ + ldr r1, =__RW_END__ + sub r1, r1, r0 + bl inv_dcache_range +#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION + ldr r0, =__BL2_NOLOAD_START__ + ldr r1, =__BL2_NOLOAD_END__ + sub r1, r1, r0 + bl inv_dcache_range +#endif +#endif + + /* + * zeromem uses r12 whereas it is used to save previous BL arg3, + * save it in r7 + */ + mov r7, r12 + ldr r0, =__BSS_START__ + ldr r1, =__BSS_END__ + sub r1, r1, r0 + bl zeromem + +#if USE_COHERENT_MEM + ldr r0, =__COHERENT_RAM_START__ + ldr r1, =__COHERENT_RAM_END_UNALIGNED__ + sub r1, r1, r0 + bl zeromem +#endif + + /* Restore r12 */ + mov r12, r7 + +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + /* ----------------------------------------------------- + * Copy data from ROM to RAM. + * ----------------------------------------------------- + */ + ldr r0, =__DATA_RAM_START__ + ldr r1, =__DATA_ROM_START__ + ldr r2, =__DATA_RAM_END__ + sub r2, r2, r0 + bl memcpy4 +#endif + .endif /* _init_c_runtime */ + + /* --------------------------------------------------------------------- + * Allocate a stack whose memory will be marked as Normal-IS-WBWA when + * the MMU is enabled. There is no risk of reading stale stack memory + * after enabling the MMU as only the primary CPU is running at the + * moment. + * --------------------------------------------------------------------- + */ + bl plat_set_my_stack + +#if STACK_PROTECTOR_ENABLED + .if \_init_c_runtime + bl update_stack_protector_canary + .endif /* _init_c_runtime */ +#endif + .endm + +#endif /* EL3_COMMON_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h b/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h new file mode 100644 index 0000000..2ce7874 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_HELPERS_H +#define SMCCC_HELPERS_H + +#include + +/* These are offsets to registers in smc_ctx_t */ +#define SMC_CTX_GPREG_R0 U(0x0) +#define SMC_CTX_GPREG_R1 U(0x4) +#define SMC_CTX_GPREG_R2 U(0x8) +#define SMC_CTX_GPREG_R3 U(0xC) +#define SMC_CTX_GPREG_R4 U(0x10) +#define SMC_CTX_GPREG_R5 U(0x14) +#define SMC_CTX_SP_USR U(0x34) +#define SMC_CTX_SPSR_MON U(0x78) +#define SMC_CTX_SP_MON U(0x7C) +#define SMC_CTX_LR_MON U(0x80) +#define SMC_CTX_SCR U(0x84) +#define SMC_CTX_PMCR U(0x88) +#define SMC_CTX_SIZE U(0x90) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * The generic structure to save arguments and callee saved registers during + * an SMC. Also this structure is used to store the result return values after + * the completion of SMC service. + */ +typedef struct smc_ctx { + u_register_t r0; + u_register_t r1; + u_register_t r2; + u_register_t r3; + u_register_t r4; + u_register_t r5; + u_register_t r6; + u_register_t r7; + u_register_t r8; + u_register_t r9; + u_register_t r10; + u_register_t r11; + u_register_t r12; + /* spsr_usr doesn't exist */ + u_register_t sp_usr; + u_register_t lr_usr; + u_register_t spsr_irq; + u_register_t sp_irq; + u_register_t lr_irq; + u_register_t spsr_fiq; + u_register_t sp_fiq; + u_register_t lr_fiq; + u_register_t spsr_svc; + u_register_t sp_svc; + u_register_t lr_svc; + u_register_t spsr_abt; + u_register_t sp_abt; + u_register_t lr_abt; + u_register_t spsr_und; + u_register_t sp_und; + u_register_t lr_und; + u_register_t spsr_mon; + /* + * `sp_mon` will point to the C runtime stack in monitor mode. But prior + * to exit from SMC, this will point to the `smc_ctx_t` so that + * on next entry due to SMC, the `smc_ctx_t` can be easily accessed. + */ + u_register_t sp_mon; + u_register_t lr_mon; + u_register_t scr; + u_register_t pmcr; + /* + * The workaround for CVE-2017-5715 requires storing information in + * the bottom 3 bits of the stack pointer. Add a padding field to + * force the size of the struct to be a multiple of 8. + */ + u_register_t pad; +} smc_ctx_t __aligned(8); + +/* + * Compile time assertions related to the 'smc_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(SMC_CTX_GPREG_R0 == __builtin_offsetof(smc_ctx_t, r0), \ + assert_smc_ctx_greg_r0_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R1 == __builtin_offsetof(smc_ctx_t, r1), \ + assert_smc_ctx_greg_r1_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R2 == __builtin_offsetof(smc_ctx_t, r2), \ + assert_smc_ctx_greg_r2_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R3 == __builtin_offsetof(smc_ctx_t, r3), \ + assert_smc_ctx_greg_r3_offset_mismatch); +CASSERT(SMC_CTX_GPREG_R4 == __builtin_offsetof(smc_ctx_t, r4), \ + assert_smc_ctx_greg_r4_offset_mismatch); +CASSERT(SMC_CTX_SP_USR == __builtin_offsetof(smc_ctx_t, sp_usr), \ + assert_smc_ctx_sp_usr_offset_mismatch); +CASSERT(SMC_CTX_LR_MON == __builtin_offsetof(smc_ctx_t, lr_mon), \ + assert_smc_ctx_lr_mon_offset_mismatch); +CASSERT(SMC_CTX_SPSR_MON == __builtin_offsetof(smc_ctx_t, spsr_mon), \ + assert_smc_ctx_spsr_mon_offset_mismatch); + +CASSERT((sizeof(smc_ctx_t) & 0x7U) == 0U, assert_smc_ctx_not_aligned); +CASSERT(SMC_CTX_SIZE == sizeof(smc_ctx_t), assert_smc_ctx_size_mismatch); + +/* Convenience macros to return from SMC handler */ +#define SMC_RET0(_h) { \ + return (uintptr_t)(_h); \ +} +#define SMC_RET1(_h, _r0) { \ + ((smc_ctx_t *)(_h))->r0 = (_r0); \ + SMC_RET0(_h); \ +} +#define SMC_RET2(_h, _r0, _r1) { \ + ((smc_ctx_t *)(_h))->r1 = (_r1); \ + SMC_RET1(_h, (_r0)); \ +} +#define SMC_RET3(_h, _r0, _r1, _r2) { \ + ((smc_ctx_t *)(_h))->r2 = (_r2); \ + SMC_RET2(_h, (_r0), (_r1)); \ +} +#define SMC_RET4(_h, _r0, _r1, _r2, _r3) { \ + ((smc_ctx_t *)(_h))->r3 = (_r3); \ + SMC_RET3(_h, (_r0), (_r1), (_r2)); \ +} +#define SMC_RET5(_h, _r0, _r1, _r2, _r3, _r4) { \ + ((smc_ctx_t *)(_h))->r4 = (_r4); \ + SMC_RET4(_h, (_r0), (_r1), (_r2), (_r3)); \ +} +#define SMC_RET6(_h, _r0, _r1, _r2, _r3, _r4, _r5) { \ + ((smc_ctx_t *)(_h))->r5 = (_r5); \ + SMC_RET5(_h, (_r0), (_r1), (_r2), (_r3), (_r4)); \ +} +#define SMC_RET7(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6) { \ + ((smc_ctx_t *)(_h))->r6 = (_r6); \ + SMC_RET6(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5)); \ +} +#define SMC_RET8(_h, _r0, _r1, _r2, _r3, _r4, _r5, _r6, _r7) { \ + ((smc_ctx_t *)(_h))->r7 = (_r7); \ + SMC_RET7(_h, (_r0), (_r1), (_r2), (_r3), (_r4), (_r5), (_r6)); \ +} + +/* + * Helper macro to retrieve the SMC parameters from smc_ctx_t. + */ +#define get_smc_params_from_ctx(_hdl, _r1, _r2, _r3, _r4) { \ + _r1 = ((smc_ctx_t *)_hdl)->r1; \ + _r2 = ((smc_ctx_t *)_hdl)->r2; \ + _r3 = ((smc_ctx_t *)_hdl)->r3; \ + _r4 = ((smc_ctx_t *)_hdl)->r4; \ + } + +/* ------------------------------------------------------------------------ + * Helper APIs for setting and retrieving appropriate `smc_ctx_t`. + * These functions need to implemented by the BL including this library. + * ------------------------------------------------------------------------ + */ + +/* Get the pointer to `smc_ctx_t` corresponding to the security state. */ +void *smc_get_ctx(unsigned int security_state); + +/* Set the next `smc_ctx_t` corresponding to the security state. */ +void smc_set_next_ctx(unsigned int security_state); + +/* Get the pointer to next `smc_ctx_t` already set by `smc_set_next_ctx()`. */ +void *smc_get_next_ctx(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* SMCCC_HELPERS_H */ diff --git a/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S b/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S new file mode 100644 index 0000000..ea7835a --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch32/smccc_macros.S @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SMCCC_MACROS_S +#define SMCCC_MACROS_S + +#include + +/* + * Macro to save the General purpose registers (r0 - r12), the banked + * spsr, lr, sp registers and the `scr` register to the SMC context on entry + * due a SMC call. The `lr` of the current mode (monitor) is expected to be + * already saved. The `sp` must point to the `smc_ctx_t` to save to. + * Additionally, also save the 'pmcr' register as this is updated whilst + * executing in the secure world. + */ + .macro smccc_save_gp_mode_regs + /* Save r0 - r12 in the SMC context */ + stm sp, {r0-r12} + mov r0, sp + add r0, r0, #SMC_CTX_SP_USR + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + stm r0!, {sp, lr} + + cps #MODE32_irq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_fiq + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_svc + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_abt + mrs r2, spsr + stm r0!, {r2, sp, lr} + + cps #MODE32_und + mrs r2, spsr + stm r0!, {r2, sp, lr} + + /* lr_mon is already saved by caller */ + cps #MODE32_mon + mrs r2, spsr + stm r0!, {r2} + + stcopr r4, SCR +#else + /* Save the banked registers including the current SPSR and LR */ + mrs r4, sp_usr + mrs r5, lr_usr + mrs r6, spsr_irq + mrs r7, sp_irq + mrs r8, lr_irq + mrs r9, spsr_fiq + mrs r10, sp_fiq + mrs r11, lr_fiq + mrs r12, spsr_svc + stm r0!, {r4-r12} + + mrs r4, sp_svc + mrs r5, lr_svc + mrs r6, spsr_abt + mrs r7, sp_abt + mrs r8, lr_abt + mrs r9, spsr_und + mrs r10, sp_und + mrs r11, lr_und + mrs r12, spsr + stm r0!, {r4-r12} + /* lr_mon is already saved by caller */ + + ldcopr r4, SCR + +#if ARM_ARCH_MAJOR > 7 + /* + * Check if earlier initialization of SDCR.SCCD to 1 + * failed, meaning that ARMv8-PMU is not implemented, + * cycle counting is not disabled and PMCR should be + * saved in Non-secure context. + */ + ldcopr r5, SDCR + tst r5, #SDCR_SCCD_BIT + bne 1f +#endif + /* Secure Cycle Counter is not disabled */ +#endif + ldcopr r5, PMCR + + /* Check caller's security state */ + tst r4, #SCR_NS_BIT + beq 2f + + /* Save PMCR if called from Non-secure state */ + str r5, [sp, #SMC_CTX_PMCR] + + /* Disable cycle counter when event counting is prohibited */ +2: orr r5, r5, #PMCR_DP_BIT + stcopr r5, PMCR + isb +1: str r4, [sp, #SMC_CTX_SCR] + .endm + +/* + * Macro to restore the `smc_ctx_t`, which includes the General purpose + * registers and banked mode registers, and exit from the monitor mode. + * r0 must point to the `smc_ctx_t` to restore from. + */ + .macro monitor_exit + /* + * Save the current sp and restore the smc context + * pointer to sp which will be used for handling the + * next SMC. + */ + str sp, [r0, #SMC_CTX_SP_MON] + mov sp, r0 + + /* + * Restore SCR first so that we access the right banked register + * when the other mode registers are restored. + */ + ldr r1, [r0, #SMC_CTX_SCR] + stcopr r1, SCR + isb + + /* + * Restore PMCR when returning to Non-secure state + */ + tst r1, #SCR_NS_BIT + beq 2f + + /* + * Back to Non-secure state + */ +#if ARM_ARCH_MAJOR > 7 + /* + * Check if earlier initialization SDCR.SCCD to 1 + * failed, meaning that ARMv8-PMU is not implemented and + * PMCR should be restored from Non-secure context. + */ + ldcopr r1, SDCR + tst r1, #SDCR_SCCD_BIT + bne 2f +#endif + /* + * Restore the PMCR register. + */ + ldr r1, [r0, #SMC_CTX_PMCR] + stcopr r1, PMCR +2: + /* Restore the banked registers including the current SPSR */ + add r1, r0, #SMC_CTX_SP_USR + +#if ARM_ARCH_MAJOR == 7 && !defined(ARMV7_SUPPORTS_VIRTUALIZATION) + /* Must be in secure state to restore Monitor mode */ + ldcopr r4, SCR + bic r2, r4, #SCR_NS_BIT + stcopr r2, SCR + isb + + cps #MODE32_sys + ldm r1!, {sp, lr} + + cps #MODE32_irq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_fiq + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_svc + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_abt + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_und + ldm r1!, {r2, sp, lr} + msr spsr_fsxc, r2 + + cps #MODE32_mon + ldm r1!, {r2} + msr spsr_fsxc, r2 + + stcopr r4, SCR + isb +#else + ldm r1!, {r4-r12} + msr sp_usr, r4 + msr lr_usr, r5 + msr spsr_irq, r6 + msr sp_irq, r7 + msr lr_irq, r8 + msr spsr_fiq, r9 + msr sp_fiq, r10 + msr lr_fiq, r11 + msr spsr_svc, r12 + + ldm r1!, {r4-r12} + msr sp_svc, r4 + msr lr_svc, r5 + msr spsr_abt, r6 + msr sp_abt, r7 + msr lr_abt, r8 + msr spsr_und, r9 + msr sp_und, r10 + msr lr_und, r11 + /* + * Use the `_fsxc` suffix explicitly to instruct the assembler + * to update all the 32 bits of SPSR. Else, by default, the + * assembler assumes `_fc` suffix which only modifies + * f->[31:24] and c->[7:0] bits of SPSR. + */ + msr spsr_fsxc, r12 +#endif + + /* Restore the LR */ + ldr lr, [r0, #SMC_CTX_LR_MON] + + /* Restore the rest of the general purpose registers */ + ldm r0, {r0-r12} + exception_return + .endm + +#endif /* SMCCC_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch.h b/arm-trusted-firmware/include/arch/aarch64/arch.h new file mode 100644 index 0000000..fd655c0 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch.h @@ -0,0 +1,1273 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_H +#define ARCH_H + +#include + +/******************************************************************************* + * MIDR bit definitions + ******************************************************************************/ +#define MIDR_IMPL_MASK U(0xff) +#define MIDR_IMPL_SHIFT U(0x18) +#define MIDR_VAR_SHIFT U(20) +#define MIDR_VAR_BITS U(4) +#define MIDR_VAR_MASK U(0xf) +#define MIDR_REV_SHIFT U(0) +#define MIDR_REV_BITS U(4) +#define MIDR_REV_MASK U(0xf) +#define MIDR_PN_MASK U(0xfff) +#define MIDR_PN_SHIFT U(0x4) + +/******************************************************************************* + * MPIDR macros + ******************************************************************************/ +#define MPIDR_MT_MASK (ULL(1) << 24) +#define MPIDR_CPU_MASK MPIDR_AFFLVL_MASK +#define MPIDR_CLUSTER_MASK (MPIDR_AFFLVL_MASK << MPIDR_AFFINITY_BITS) +#define MPIDR_AFFINITY_BITS U(8) +#define MPIDR_AFFLVL_MASK ULL(0xff) +#define MPIDR_AFF0_SHIFT U(0) +#define MPIDR_AFF1_SHIFT U(8) +#define MPIDR_AFF2_SHIFT U(16) +#define MPIDR_AFF3_SHIFT U(32) +#define MPIDR_AFF_SHIFT(_n) MPIDR_AFF##_n##_SHIFT +#define MPIDR_AFFINITY_MASK ULL(0xff00ffffff) +#define MPIDR_AFFLVL_SHIFT U(3) +#define MPIDR_AFFLVL0 ULL(0x0) +#define MPIDR_AFFLVL1 ULL(0x1) +#define MPIDR_AFFLVL2 ULL(0x2) +#define MPIDR_AFFLVL3 ULL(0x3) +#define MPIDR_AFFLVL(_n) MPIDR_AFFLVL##_n +#define MPIDR_AFFLVL0_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF0_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL1_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF1_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL2_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK) +#define MPIDR_AFFLVL3_VAL(mpidr) \ + (((mpidr) >> MPIDR_AFF3_SHIFT) & MPIDR_AFFLVL_MASK) +/* + * The MPIDR_MAX_AFFLVL count starts from 0. Take care to + * add one while using this macro to define array sizes. + * TODO: Support only the first 3 affinity levels for now. + */ +#define MPIDR_MAX_AFFLVL U(2) + +#define MPID_MASK (MPIDR_MT_MASK | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF3_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF2_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF1_SHIFT) | \ + (MPIDR_AFFLVL_MASK << MPIDR_AFF0_SHIFT)) + +#define MPIDR_AFF_ID(mpid, n) \ + (((mpid) >> MPIDR_AFF_SHIFT(n)) & MPIDR_AFFLVL_MASK) + +/* + * An invalid MPID. This value can be used by functions that return an MPID to + * indicate an error. + */ +#define INVALID_MPID U(0xFFFFFFFF) + +/******************************************************************************* + * Definitions for CPU system register interface to GICv3 + ******************************************************************************/ +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_SGI1R S3_0_C12_C11_5 +#define ICC_SRE_EL1 S3_0_C12_C12_5 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_RPR_EL1 S3_0_C12_C11_3 +#define ICC_IGRPEN1_EL3 S3_6_c12_c12_7 +#define ICC_IGRPEN0_EL1 S3_0_c12_c12_6 +#define ICC_HPPIR0_EL1 S3_0_c12_c8_2 +#define ICC_HPPIR1_EL1 S3_0_c12_c12_2 +#define ICC_IAR0_EL1 S3_0_c12_c8_0 +#define ICC_IAR1_EL1 S3_0_c12_c12_0 +#define ICC_EOIR0_EL1 S3_0_c12_c8_1 +#define ICC_EOIR1_EL1 S3_0_c12_c12_1 +#define ICC_SGI0R_EL1 S3_0_c12_c11_7 + +/******************************************************************************* + * Definitions for EL2 system registers for save/restore routine + ******************************************************************************/ + +#define CNTPOFF_EL2 S3_4_C14_C0_6 +#define HAFGRTR_EL2 S3_4_C3_C1_6 +#define HDFGRTR_EL2 S3_4_C3_C1_4 +#define HDFGWTR_EL2 S3_4_C3_C1_5 +#define HFGITR_EL2 S3_4_C1_C1_6 +#define HFGRTR_EL2 S3_4_C1_C1_4 +#define HFGWTR_EL2 S3_4_C1_C1_5 +#define ICH_HCR_EL2 S3_4_C12_C11_0 +#define ICH_VMCR_EL2 S3_4_C12_C11_7 +#define MPAMVPM0_EL2 S3_4_C10_C5_0 +#define MPAMVPM1_EL2 S3_4_C10_C5_1 +#define MPAMVPM2_EL2 S3_4_C10_C5_2 +#define MPAMVPM3_EL2 S3_4_C10_C5_3 +#define MPAMVPM4_EL2 S3_4_C10_C5_4 +#define MPAMVPM5_EL2 S3_4_C10_C5_5 +#define MPAMVPM6_EL2 S3_4_C10_C5_6 +#define MPAMVPM7_EL2 S3_4_C10_C5_7 +#define MPAMVPMV_EL2 S3_4_C10_C4_1 +#define TRFCR_EL2 S3_4_C1_C2_1 +#define PMSCR_EL2 S3_4_C9_C9_0 +#define TFSR_EL2 S3_4_C5_C6_0 + +/******************************************************************************* + * Generic timer memory mapped registers & offsets + ******************************************************************************/ +#define CNTCR_OFF U(0x000) +#define CNTCV_OFF U(0x008) +#define CNTFID_OFF U(0x020) + +#define CNTCR_EN (U(1) << 0) +#define CNTCR_HDBG (U(1) << 1) +#define CNTCR_FCREQ(x) ((x) << 8) + +/******************************************************************************* + * System register bit definitions + ******************************************************************************/ +/* CLIDR definitions */ +#define LOUIS_SHIFT U(21) +#define LOC_SHIFT U(24) +#define CTYPE_SHIFT(n) U(3 * (n - 1)) +#define CLIDR_FIELD_WIDTH U(3) + +/* CSSELR definitions */ +#define LEVEL_SHIFT U(1) + +/* Data cache set/way op type defines */ +#define DCISW U(0x0) +#define DCCISW U(0x1) +#if ERRATA_A53_827319 +#define DCCSW DCCISW +#else +#define DCCSW U(0x2) +#endif + +/* ID_AA64PFR0_EL1 definitions */ +#define ID_AA64PFR0_EL0_SHIFT U(0) +#define ID_AA64PFR0_EL1_SHIFT U(4) +#define ID_AA64PFR0_EL2_SHIFT U(8) +#define ID_AA64PFR0_EL3_SHIFT U(12) +#define ID_AA64PFR0_AMU_SHIFT U(44) +#define ID_AA64PFR0_AMU_MASK ULL(0xf) +#define ID_AA64PFR0_AMU_NOT_SUPPORTED U(0x0) +#define ID_AA64PFR0_AMU_V1 U(0x1) +#define ID_AA64PFR0_AMU_V1P1 U(0x2) +#define ID_AA64PFR0_ELX_MASK ULL(0xf) +#define ID_AA64PFR0_GIC_SHIFT U(24) +#define ID_AA64PFR0_GIC_WIDTH U(4) +#define ID_AA64PFR0_GIC_MASK ULL(0xf) +#define ID_AA64PFR0_SVE_SHIFT U(32) +#define ID_AA64PFR0_SVE_MASK ULL(0xf) +#define ID_AA64PFR0_SVE_LENGTH U(4) +#define ID_AA64PFR0_SEL2_SHIFT U(36) +#define ID_AA64PFR0_SEL2_MASK ULL(0xf) +#define ID_AA64PFR0_MPAM_SHIFT U(40) +#define ID_AA64PFR0_MPAM_MASK ULL(0xf) +#define ID_AA64PFR0_DIT_SHIFT U(48) +#define ID_AA64PFR0_DIT_MASK ULL(0xf) +#define ID_AA64PFR0_DIT_LENGTH U(4) +#define ID_AA64PFR0_DIT_SUPPORTED U(1) +#define ID_AA64PFR0_CSV2_SHIFT U(56) +#define ID_AA64PFR0_CSV2_MASK ULL(0xf) +#define ID_AA64PFR0_CSV2_LENGTH U(4) +#define ID_AA64PFR0_FEAT_RME_SHIFT U(52) +#define ID_AA64PFR0_FEAT_RME_MASK ULL(0xf) +#define ID_AA64PFR0_FEAT_RME_LENGTH U(4) +#define ID_AA64PFR0_FEAT_RME_NOT_SUPPORTED U(0) +#define ID_AA64PFR0_FEAT_RME_V1 U(1) + +/* Exception level handling */ +#define EL_IMPL_NONE ULL(0) +#define EL_IMPL_A64ONLY ULL(1) +#define EL_IMPL_A64_A32 ULL(2) + +/* ID_AA64DFR0_EL1.TraceVer definitions */ +#define ID_AA64DFR0_TRACEVER_SHIFT U(4) +#define ID_AA64DFR0_TRACEVER_MASK ULL(0xf) +#define ID_AA64DFR0_TRACEVER_SUPPORTED ULL(1) +#define ID_AA64DFR0_TRACEVER_LENGTH U(4) +#define ID_AA64DFR0_TRACEFILT_SHIFT U(40) +#define ID_AA64DFR0_TRACEFILT_MASK U(0xf) +#define ID_AA64DFR0_TRACEFILT_SUPPORTED U(1) +#define ID_AA64DFR0_TRACEFILT_LENGTH U(4) + +/* ID_AA64DFR0_EL1.PMS definitions (for ARMv8.2+) */ +#define ID_AA64DFR0_PMS_SHIFT U(32) +#define ID_AA64DFR0_PMS_MASK ULL(0xf) + +/* ID_AA64DFR0_EL1.TraceBuffer definitions */ +#define ID_AA64DFR0_TRACEBUFFER_SHIFT U(44) +#define ID_AA64DFR0_TRACEBUFFER_MASK ULL(0xf) +#define ID_AA64DFR0_TRACEBUFFER_SUPPORTED ULL(1) + +/* ID_AA64DFR0_EL1.MTPMU definitions (for ARMv8.6+) */ +#define ID_AA64DFR0_MTPMU_SHIFT U(48) +#define ID_AA64DFR0_MTPMU_MASK ULL(0xf) +#define ID_AA64DFR0_MTPMU_SUPPORTED ULL(1) + +/* ID_AA64ISAR0_EL1 definitions */ +#define ID_AA64ISAR0_RNDR_SHIFT U(60) +#define ID_AA64ISAR0_RNDR_MASK ULL(0xf) + +/* ID_AA64ISAR1_EL1 definitions */ +#define ID_AA64ISAR1_EL1 S3_0_C0_C6_1 +#define ID_AA64ISAR1_GPI_SHIFT U(28) +#define ID_AA64ISAR1_GPI_MASK ULL(0xf) +#define ID_AA64ISAR1_GPA_SHIFT U(24) +#define ID_AA64ISAR1_GPA_MASK ULL(0xf) +#define ID_AA64ISAR1_API_SHIFT U(8) +#define ID_AA64ISAR1_API_MASK ULL(0xf) +#define ID_AA64ISAR1_APA_SHIFT U(4) +#define ID_AA64ISAR1_APA_MASK ULL(0xf) + +/* ID_AA64MMFR0_EL1 definitions */ +#define ID_AA64MMFR0_EL1_PARANGE_SHIFT U(0) +#define ID_AA64MMFR0_EL1_PARANGE_MASK ULL(0xf) + +#define PARANGE_0000 U(32) +#define PARANGE_0001 U(36) +#define PARANGE_0010 U(40) +#define PARANGE_0011 U(42) +#define PARANGE_0100 U(44) +#define PARANGE_0101 U(48) +#define PARANGE_0110 U(52) + +#define ID_AA64MMFR0_EL1_ECV_SHIFT U(60) +#define ID_AA64MMFR0_EL1_ECV_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_ECV_NOT_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_ECV_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_ECV_SELF_SYNCH ULL(0x2) + +#define ID_AA64MMFR0_EL1_FGT_SHIFT U(56) +#define ID_AA64MMFR0_EL1_FGT_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_FGT_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_FGT_NOT_SUPPORTED ULL(0x0) + +#define ID_AA64MMFR0_EL1_TGRAN4_SHIFT U(28) +#define ID_AA64MMFR0_EL1_TGRAN4_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN4_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN64_SHIFT U(24) +#define ID_AA64MMFR0_EL1_TGRAN64_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED ULL(0x0) +#define ID_AA64MMFR0_EL1_TGRAN64_NOT_SUPPORTED ULL(0xf) + +#define ID_AA64MMFR0_EL1_TGRAN16_SHIFT U(20) +#define ID_AA64MMFR0_EL1_TGRAN16_MASK ULL(0xf) +#define ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED ULL(0x1) +#define ID_AA64MMFR0_EL1_TGRAN16_NOT_SUPPORTED ULL(0x0) + +/* ID_AA64MMFR1_EL1 definitions */ +#define ID_AA64MMFR1_EL1_TWED_SHIFT U(32) +#define ID_AA64MMFR1_EL1_TWED_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_TWED_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_TWED_NOT_SUPPORTED ULL(0x0) + +#define ID_AA64MMFR1_EL1_PAN_SHIFT U(20) +#define ID_AA64MMFR1_EL1_PAN_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_PAN_NOT_SUPPORTED ULL(0x0) +#define ID_AA64MMFR1_EL1_PAN_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_PAN2_SUPPORTED ULL(0x2) +#define ID_AA64MMFR1_EL1_PAN3_SUPPORTED ULL(0x3) + +#define ID_AA64MMFR1_EL1_VHE_SHIFT U(8) +#define ID_AA64MMFR1_EL1_VHE_MASK ULL(0xf) + +#define ID_AA64MMFR1_EL1_HCX_SHIFT U(40) +#define ID_AA64MMFR1_EL1_HCX_MASK ULL(0xf) +#define ID_AA64MMFR1_EL1_HCX_SUPPORTED ULL(0x1) +#define ID_AA64MMFR1_EL1_HCX_NOT_SUPPORTED ULL(0x0) + +/* ID_AA64MMFR2_EL1 definitions */ +#define ID_AA64MMFR2_EL1 S3_0_C0_C7_2 + +#define ID_AA64MMFR2_EL1_ST_SHIFT U(28) +#define ID_AA64MMFR2_EL1_ST_MASK ULL(0xf) + +#define ID_AA64MMFR2_EL1_CCIDX_SHIFT U(20) +#define ID_AA64MMFR2_EL1_CCIDX_MASK ULL(0xf) +#define ID_AA64MMFR2_EL1_CCIDX_LENGTH U(4) + +#define ID_AA64MMFR2_EL1_CNP_SHIFT U(0) +#define ID_AA64MMFR2_EL1_CNP_MASK ULL(0xf) + +/* ID_AA64PFR1_EL1 definitions */ +#define ID_AA64PFR1_EL1_SSBS_SHIFT U(4) +#define ID_AA64PFR1_EL1_SSBS_MASK ULL(0xf) + +#define SSBS_UNAVAILABLE ULL(0) /* No architectural SSBS support */ + +#define ID_AA64PFR1_EL1_BT_SHIFT U(0) +#define ID_AA64PFR1_EL1_BT_MASK ULL(0xf) + +#define BTI_IMPLEMENTED ULL(1) /* The BTI mechanism is implemented */ + +#define ID_AA64PFR1_EL1_MTE_SHIFT U(8) +#define ID_AA64PFR1_EL1_MTE_MASK ULL(0xf) + +/* Memory Tagging Extension is not implemented */ +#define MTE_UNIMPLEMENTED U(0) +/* FEAT_MTE: MTE instructions accessible at EL0 are implemented */ +#define MTE_IMPLEMENTED_EL0 U(1) +/* FEAT_MTE2: Full MTE is implemented */ +#define MTE_IMPLEMENTED_ELX U(2) +/* + * FEAT_MTE3: MTE is implemented with support for + * asymmetric Tag Check Fault handling + */ +#define MTE_IMPLEMENTED_ASY U(3) + +#define ID_AA64PFR1_MPAM_FRAC_SHIFT ULL(16) +#define ID_AA64PFR1_MPAM_FRAC_MASK ULL(0xf) + +#define ID_AA64PFR1_EL1_SME_SHIFT U(24) +#define ID_AA64PFR1_EL1_SME_MASK ULL(0xf) + +/* ID_PFR1_EL1 definitions */ +#define ID_PFR1_VIRTEXT_SHIFT U(12) +#define ID_PFR1_VIRTEXT_MASK U(0xf) +#define GET_VIRT_EXT(id) (((id) >> ID_PFR1_VIRTEXT_SHIFT) \ + & ID_PFR1_VIRTEXT_MASK) + +/* SCTLR definitions */ +#define SCTLR_EL2_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) + +#define SCTLR_EL1_RES1 ((UL(1) << 29) | (UL(1) << 28) | (UL(1) << 23) | \ + (UL(1) << 22) | (UL(1) << 20) | (UL(1) << 11)) + +#define SCTLR_AARCH32_EL1_RES1 \ + ((U(1) << 23) | (U(1) << 22) | (U(1) << 11) | \ + (U(1) << 4) | (U(1) << 3)) + +#define SCTLR_EL3_RES1 ((U(1) << 29) | (U(1) << 28) | (U(1) << 23) | \ + (U(1) << 22) | (U(1) << 18) | (U(1) << 16) | \ + (U(1) << 11) | (U(1) << 5) | (U(1) << 4)) + +#define SCTLR_M_BIT (ULL(1) << 0) +#define SCTLR_A_BIT (ULL(1) << 1) +#define SCTLR_C_BIT (ULL(1) << 2) +#define SCTLR_SA_BIT (ULL(1) << 3) +#define SCTLR_SA0_BIT (ULL(1) << 4) +#define SCTLR_CP15BEN_BIT (ULL(1) << 5) +#define SCTLR_nAA_BIT (ULL(1) << 6) +#define SCTLR_ITD_BIT (ULL(1) << 7) +#define SCTLR_SED_BIT (ULL(1) << 8) +#define SCTLR_UMA_BIT (ULL(1) << 9) +#define SCTLR_EnRCTX_BIT (ULL(1) << 10) +#define SCTLR_EOS_BIT (ULL(1) << 11) +#define SCTLR_I_BIT (ULL(1) << 12) +#define SCTLR_EnDB_BIT (ULL(1) << 13) +#define SCTLR_DZE_BIT (ULL(1) << 14) +#define SCTLR_UCT_BIT (ULL(1) << 15) +#define SCTLR_NTWI_BIT (ULL(1) << 16) +#define SCTLR_NTWE_BIT (ULL(1) << 18) +#define SCTLR_WXN_BIT (ULL(1) << 19) +#define SCTLR_TSCXT_BIT (ULL(1) << 20) +#define SCTLR_IESB_BIT (ULL(1) << 21) +#define SCTLR_EIS_BIT (ULL(1) << 22) +#define SCTLR_SPAN_BIT (ULL(1) << 23) +#define SCTLR_E0E_BIT (ULL(1) << 24) +#define SCTLR_EE_BIT (ULL(1) << 25) +#define SCTLR_UCI_BIT (ULL(1) << 26) +#define SCTLR_EnDA_BIT (ULL(1) << 27) +#define SCTLR_nTLSMD_BIT (ULL(1) << 28) +#define SCTLR_LSMAOE_BIT (ULL(1) << 29) +#define SCTLR_EnIB_BIT (ULL(1) << 30) +#define SCTLR_EnIA_BIT (ULL(1) << 31) +#define SCTLR_BT0_BIT (ULL(1) << 35) +#define SCTLR_BT1_BIT (ULL(1) << 36) +#define SCTLR_BT_BIT (ULL(1) << 36) +#define SCTLR_ITFSB_BIT (ULL(1) << 37) +#define SCTLR_TCF0_SHIFT U(38) +#define SCTLR_TCF0_MASK ULL(3) +#define SCTLR_ENTP2_BIT (ULL(1) << 60) + +/* Tag Check Faults in EL0 have no effect on the PE */ +#define SCTLR_TCF0_NO_EFFECT U(0) +/* Tag Check Faults in EL0 cause a synchronous exception */ +#define SCTLR_TCF0_SYNC U(1) +/* Tag Check Faults in EL0 are asynchronously accumulated */ +#define SCTLR_TCF0_ASYNC U(2) +/* + * Tag Check Faults in EL0 cause a synchronous exception on reads, + * and are asynchronously accumulated on writes + */ +#define SCTLR_TCF0_SYNCR_ASYNCW U(3) + +#define SCTLR_TCF_SHIFT U(40) +#define SCTLR_TCF_MASK ULL(3) + +/* Tag Check Faults in EL1 have no effect on the PE */ +#define SCTLR_TCF_NO_EFFECT U(0) +/* Tag Check Faults in EL1 cause a synchronous exception */ +#define SCTLR_TCF_SYNC U(1) +/* Tag Check Faults in EL1 are asynchronously accumulated */ +#define SCTLR_TCF_ASYNC U(2) +/* + * Tag Check Faults in EL1 cause a synchronous exception on reads, + * and are asynchronously accumulated on writes + */ +#define SCTLR_TCF_SYNCR_ASYNCW U(3) + +#define SCTLR_ATA0_BIT (ULL(1) << 42) +#define SCTLR_ATA_BIT (ULL(1) << 43) +#define SCTLR_DSSBS_SHIFT U(44) +#define SCTLR_DSSBS_BIT (ULL(1) << SCTLR_DSSBS_SHIFT) +#define SCTLR_TWEDEn_BIT (ULL(1) << 45) +#define SCTLR_TWEDEL_SHIFT U(46) +#define SCTLR_TWEDEL_MASK ULL(0xf) +#define SCTLR_EnASR_BIT (ULL(1) << 54) +#define SCTLR_EnAS0_BIT (ULL(1) << 55) +#define SCTLR_EnALS_BIT (ULL(1) << 56) +#define SCTLR_EPAN_BIT (ULL(1) << 57) +#define SCTLR_RESET_VAL SCTLR_EL3_RES1 + +/* CPACR_EL1 definitions */ +#define CPACR_EL1_FPEN(x) ((x) << 20) +#define CPACR_EL1_FP_TRAP_EL0 UL(0x1) +#define CPACR_EL1_FP_TRAP_ALL UL(0x2) +#define CPACR_EL1_FP_TRAP_NONE UL(0x3) + +/* SCR definitions */ +#define SCR_RES1_BITS ((U(1) << 4) | (U(1) << 5)) +#define SCR_NSE_SHIFT U(62) +#define SCR_NSE_BIT (ULL(1) << SCR_NSE_SHIFT) +#define SCR_GPF_BIT (UL(1) << 48) +#define SCR_TWEDEL_SHIFT U(30) +#define SCR_TWEDEL_MASK ULL(0xf) +#define SCR_HXEn_BIT (UL(1) << 38) +#define SCR_ENTP2_SHIFT U(41) +#define SCR_ENTP2_BIT (UL(1) << SCR_ENTP2_SHIFT) +#define SCR_AMVOFFEN_BIT (UL(1) << 35) +#define SCR_TWEDEn_BIT (UL(1) << 29) +#define SCR_ECVEN_BIT (UL(1) << 28) +#define SCR_FGTEN_BIT (UL(1) << 27) +#define SCR_ATA_BIT (UL(1) << 26) +#define SCR_EnSCXT_BIT (UL(1) << 25) +#define SCR_FIEN_BIT (UL(1) << 21) +#define SCR_EEL2_BIT (UL(1) << 18) +#define SCR_API_BIT (UL(1) << 17) +#define SCR_APK_BIT (UL(1) << 16) +#define SCR_TERR_BIT (UL(1) << 15) +#define SCR_TWE_BIT (UL(1) << 13) +#define SCR_TWI_BIT (UL(1) << 12) +#define SCR_ST_BIT (UL(1) << 11) +#define SCR_RW_BIT (UL(1) << 10) +#define SCR_SIF_BIT (UL(1) << 9) +#define SCR_HCE_BIT (UL(1) << 8) +#define SCR_SMD_BIT (UL(1) << 7) +#define SCR_EA_BIT (UL(1) << 3) +#define SCR_FIQ_BIT (UL(1) << 2) +#define SCR_IRQ_BIT (UL(1) << 1) +#define SCR_NS_BIT (UL(1) << 0) +#define SCR_VALID_BIT_MASK U(0x24000002F8F) +#define SCR_RESET_VAL SCR_RES1_BITS + +/* MDCR_EL3 definitions */ +#define MDCR_EnPMSN_BIT (ULL(1) << 36) +#define MDCR_MPMX_BIT (ULL(1) << 35) +#define MDCR_MCCD_BIT (ULL(1) << 34) +#define MDCR_NSTB(x) ((x) << 24) +#define MDCR_NSTB_EL1 ULL(0x3) +#define MDCR_NSTBE (ULL(1) << 26) +#define MDCR_MTPME_BIT (ULL(1) << 28) +#define MDCR_TDCC_BIT (ULL(1) << 27) +#define MDCR_SCCD_BIT (ULL(1) << 23) +#define MDCR_EPMAD_BIT (ULL(1) << 21) +#define MDCR_EDAD_BIT (ULL(1) << 20) +#define MDCR_TTRF_BIT (ULL(1) << 19) +#define MDCR_STE_BIT (ULL(1) << 18) +#define MDCR_SPME_BIT (ULL(1) << 17) +#define MDCR_SDD_BIT (ULL(1) << 16) +#define MDCR_SPD32(x) ((x) << 14) +#define MDCR_SPD32_LEGACY ULL(0x0) +#define MDCR_SPD32_DISABLE ULL(0x2) +#define MDCR_SPD32_ENABLE ULL(0x3) +#define MDCR_NSPB(x) ((x) << 12) +#define MDCR_NSPB_EL1 ULL(0x3) +#define MDCR_TDOSA_BIT (ULL(1) << 10) +#define MDCR_TDA_BIT (ULL(1) << 9) +#define MDCR_TPM_BIT (ULL(1) << 6) +#define MDCR_EL3_RESET_VAL ULL(0x0) + +/* MDCR_EL2 definitions */ +#define MDCR_EL2_MTPME (U(1) << 28) +#define MDCR_EL2_HLP (U(1) << 26) +#define MDCR_EL2_E2TB(x) ((x) << 24) +#define MDCR_EL2_E2TB_EL1 U(0x3) +#define MDCR_EL2_HCCD (U(1) << 23) +#define MDCR_EL2_TTRF (U(1) << 19) +#define MDCR_EL2_HPMD (U(1) << 17) +#define MDCR_EL2_TPMS (U(1) << 14) +#define MDCR_EL2_E2PB(x) ((x) << 12) +#define MDCR_EL2_E2PB_EL1 U(0x3) +#define MDCR_EL2_TDRA_BIT (U(1) << 11) +#define MDCR_EL2_TDOSA_BIT (U(1) << 10) +#define MDCR_EL2_TDA_BIT (U(1) << 9) +#define MDCR_EL2_TDE_BIT (U(1) << 8) +#define MDCR_EL2_HPME_BIT (U(1) << 7) +#define MDCR_EL2_TPM_BIT (U(1) << 6) +#define MDCR_EL2_TPMCR_BIT (U(1) << 5) +#define MDCR_EL2_RESET_VAL U(0x0) + +/* HSTR_EL2 definitions */ +#define HSTR_EL2_RESET_VAL U(0x0) +#define HSTR_EL2_T_MASK U(0xff) + +/* CNTHP_CTL_EL2 definitions */ +#define CNTHP_CTL_ENABLE_BIT (U(1) << 0) +#define CNTHP_CTL_RESET_VAL U(0x0) + +/* VTTBR_EL2 definitions */ +#define VTTBR_RESET_VAL ULL(0x0) +#define VTTBR_VMID_MASK ULL(0xff) +#define VTTBR_VMID_SHIFT U(48) +#define VTTBR_BADDR_MASK ULL(0xffffffffffff) +#define VTTBR_BADDR_SHIFT U(0) + +/* HCR definitions */ +#define HCR_RESET_VAL ULL(0x0) +#define HCR_AMVOFFEN_SHIFT U(51) +#define HCR_AMVOFFEN_BIT (ULL(1) << HCR_AMVOFFEN_SHIFT) +#define HCR_TEA_BIT (ULL(1) << 47) +#define HCR_API_BIT (ULL(1) << 41) +#define HCR_APK_BIT (ULL(1) << 40) +#define HCR_E2H_BIT (ULL(1) << 34) +#define HCR_HCD_BIT (ULL(1) << 29) +#define HCR_TGE_BIT (ULL(1) << 27) +#define HCR_RW_SHIFT U(31) +#define HCR_RW_BIT (ULL(1) << HCR_RW_SHIFT) +#define HCR_TWE_BIT (ULL(1) << 14) +#define HCR_TWI_BIT (ULL(1) << 13) +#define HCR_AMO_BIT (ULL(1) << 5) +#define HCR_IMO_BIT (ULL(1) << 4) +#define HCR_FMO_BIT (ULL(1) << 3) + +/* ISR definitions */ +#define ISR_A_SHIFT U(8) +#define ISR_I_SHIFT U(7) +#define ISR_F_SHIFT U(6) + +/* CNTHCTL_EL2 definitions */ +#define CNTHCTL_RESET_VAL U(0x0) +#define EVNTEN_BIT (U(1) << 2) +#define EL1PCEN_BIT (U(1) << 1) +#define EL1PCTEN_BIT (U(1) << 0) + +/* CNTKCTL_EL1 definitions */ +#define EL0PTEN_BIT (U(1) << 9) +#define EL0VTEN_BIT (U(1) << 8) +#define EL0PCTEN_BIT (U(1) << 0) +#define EL0VCTEN_BIT (U(1) << 1) +#define EVNTEN_BIT (U(1) << 2) +#define EVNTDIR_BIT (U(1) << 3) +#define EVNTI_SHIFT U(4) +#define EVNTI_MASK U(0xf) + +/* CPTR_EL3 definitions */ +#define TCPAC_BIT (U(1) << 31) +#define TAM_SHIFT U(30) +#define TAM_BIT (U(1) << TAM_SHIFT) +#define TTA_BIT (U(1) << 20) +#define ESM_BIT (U(1) << 12) +#define TFP_BIT (U(1) << 10) +#define CPTR_EZ_BIT (U(1) << 8) +#define CPTR_EL3_RESET_VAL ((TCPAC_BIT | TAM_BIT | TTA_BIT | TFP_BIT) & \ + ~(CPTR_EZ_BIT | ESM_BIT)) + +/* CPTR_EL2 definitions */ +#define CPTR_EL2_RES1 ((U(1) << 13) | (U(1) << 12) | (U(0x3ff))) +#define CPTR_EL2_TCPAC_BIT (U(1) << 31) +#define CPTR_EL2_TAM_SHIFT U(30) +#define CPTR_EL2_TAM_BIT (U(1) << CPTR_EL2_TAM_SHIFT) +#define CPTR_EL2_SMEN_MASK ULL(0x3) +#define CPTR_EL2_SMEN_SHIFT U(24) +#define CPTR_EL2_TTA_BIT (U(1) << 20) +#define CPTR_EL2_TSM_BIT (U(1) << 12) +#define CPTR_EL2_TFP_BIT (U(1) << 10) +#define CPTR_EL2_TZ_BIT (U(1) << 8) +#define CPTR_EL2_RESET_VAL CPTR_EL2_RES1 + +/* VTCR_EL2 definitions */ +#define VTCR_RESET_VAL U(0x0) +#define VTCR_EL2_MSA (U(1) << 31) + +/* CPSR/SPSR definitions */ +#define DAIF_FIQ_BIT (U(1) << 0) +#define DAIF_IRQ_BIT (U(1) << 1) +#define DAIF_ABT_BIT (U(1) << 2) +#define DAIF_DBG_BIT (U(1) << 3) +#define SPSR_DAIF_SHIFT U(6) +#define SPSR_DAIF_MASK U(0xf) + +#define SPSR_AIF_SHIFT U(6) +#define SPSR_AIF_MASK U(0x7) + +#define SPSR_E_SHIFT U(9) +#define SPSR_E_MASK U(0x1) +#define SPSR_E_LITTLE U(0x0) +#define SPSR_E_BIG U(0x1) + +#define SPSR_T_SHIFT U(5) +#define SPSR_T_MASK U(0x1) +#define SPSR_T_ARM U(0x0) +#define SPSR_T_THUMB U(0x1) + +#define SPSR_M_SHIFT U(4) +#define SPSR_M_MASK U(0x1) +#define SPSR_M_AARCH64 U(0x0) +#define SPSR_M_AARCH32 U(0x1) +#define SPSR_M_EL2H U(0x9) + +#define SPSR_EL_SHIFT U(2) +#define SPSR_EL_WIDTH U(2) + +#define SPSR_SSBS_SHIFT_AARCH64 U(12) +#define SPSR_SSBS_BIT_AARCH64 (ULL(1) << SPSR_SSBS_SHIFT_AARCH64) +#define SPSR_SSBS_SHIFT_AARCH32 U(23) +#define SPSR_SSBS_BIT_AARCH32 (ULL(1) << SPSR_SSBS_SHIFT_AARCH32) + +#define SPSR_PAN_BIT BIT_64(22) + +#define SPSR_DIT_BIT BIT(24) + +#define SPSR_TCO_BIT_AARCH64 BIT_64(25) + +#define DISABLE_ALL_EXCEPTIONS \ + (DAIF_FIQ_BIT | DAIF_IRQ_BIT | DAIF_ABT_BIT | DAIF_DBG_BIT) + +#define DISABLE_INTERRUPTS (DAIF_FIQ_BIT | DAIF_IRQ_BIT) + +/* + * RMR_EL3 definitions + */ +#define RMR_EL3_RR_BIT (U(1) << 1) +#define RMR_EL3_AA64_BIT (U(1) << 0) + +/* + * HI-VECTOR address for AArch32 state + */ +#define HI_VECTOR_BASE U(0xFFFF0000) + +/* + * TCR defintions + */ +#define TCR_EL3_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) +#define TCR_EL2_RES1 ((ULL(1) << 31) | (ULL(1) << 23)) +#define TCR_EL1_IPS_SHIFT U(32) +#define TCR_EL2_PS_SHIFT U(16) +#define TCR_EL3_PS_SHIFT U(16) + +#define TCR_TxSZ_MIN ULL(16) +#define TCR_TxSZ_MAX ULL(39) +#define TCR_TxSZ_MAX_TTST ULL(48) + +#define TCR_T0SZ_SHIFT U(0) +#define TCR_T1SZ_SHIFT U(16) + +/* (internal) physical address size bits in EL3/EL1 */ +#define TCR_PS_BITS_4GB ULL(0x0) +#define TCR_PS_BITS_64GB ULL(0x1) +#define TCR_PS_BITS_1TB ULL(0x2) +#define TCR_PS_BITS_4TB ULL(0x3) +#define TCR_PS_BITS_16TB ULL(0x4) +#define TCR_PS_BITS_256TB ULL(0x5) + +#define ADDR_MASK_48_TO_63 ULL(0xFFFF000000000000) +#define ADDR_MASK_44_TO_47 ULL(0x0000F00000000000) +#define ADDR_MASK_42_TO_43 ULL(0x00000C0000000000) +#define ADDR_MASK_40_TO_41 ULL(0x0000030000000000) +#define ADDR_MASK_36_TO_39 ULL(0x000000F000000000) +#define ADDR_MASK_32_TO_35 ULL(0x0000000F00000000) + +#define TCR_RGN_INNER_NC (ULL(0x0) << 8) +#define TCR_RGN_INNER_WBA (ULL(0x1) << 8) +#define TCR_RGN_INNER_WT (ULL(0x2) << 8) +#define TCR_RGN_INNER_WBNA (ULL(0x3) << 8) + +#define TCR_RGN_OUTER_NC (ULL(0x0) << 10) +#define TCR_RGN_OUTER_WBA (ULL(0x1) << 10) +#define TCR_RGN_OUTER_WT (ULL(0x2) << 10) +#define TCR_RGN_OUTER_WBNA (ULL(0x3) << 10) + +#define TCR_SH_NON_SHAREABLE (ULL(0x0) << 12) +#define TCR_SH_OUTER_SHAREABLE (ULL(0x2) << 12) +#define TCR_SH_INNER_SHAREABLE (ULL(0x3) << 12) + +#define TCR_RGN1_INNER_NC (ULL(0x0) << 24) +#define TCR_RGN1_INNER_WBA (ULL(0x1) << 24) +#define TCR_RGN1_INNER_WT (ULL(0x2) << 24) +#define TCR_RGN1_INNER_WBNA (ULL(0x3) << 24) + +#define TCR_RGN1_OUTER_NC (ULL(0x0) << 26) +#define TCR_RGN1_OUTER_WBA (ULL(0x1) << 26) +#define TCR_RGN1_OUTER_WT (ULL(0x2) << 26) +#define TCR_RGN1_OUTER_WBNA (ULL(0x3) << 26) + +#define TCR_SH1_NON_SHAREABLE (ULL(0x0) << 28) +#define TCR_SH1_OUTER_SHAREABLE (ULL(0x2) << 28) +#define TCR_SH1_INNER_SHAREABLE (ULL(0x3) << 28) + +#define TCR_TG0_SHIFT U(14) +#define TCR_TG0_MASK ULL(3) +#define TCR_TG0_4K (ULL(0) << TCR_TG0_SHIFT) +#define TCR_TG0_64K (ULL(1) << TCR_TG0_SHIFT) +#define TCR_TG0_16K (ULL(2) << TCR_TG0_SHIFT) + +#define TCR_TG1_SHIFT U(30) +#define TCR_TG1_MASK ULL(3) +#define TCR_TG1_16K (ULL(1) << TCR_TG1_SHIFT) +#define TCR_TG1_4K (ULL(2) << TCR_TG1_SHIFT) +#define TCR_TG1_64K (ULL(3) << TCR_TG1_SHIFT) + +#define TCR_EPD0_BIT (ULL(1) << 7) +#define TCR_EPD1_BIT (ULL(1) << 23) + +#define MODE_SP_SHIFT U(0x0) +#define MODE_SP_MASK U(0x1) +#define MODE_SP_EL0 U(0x0) +#define MODE_SP_ELX U(0x1) + +#define MODE_RW_SHIFT U(0x4) +#define MODE_RW_MASK U(0x1) +#define MODE_RW_64 U(0x0) +#define MODE_RW_32 U(0x1) + +#define MODE_EL_SHIFT U(0x2) +#define MODE_EL_MASK U(0x3) +#define MODE_EL_WIDTH U(0x2) +#define MODE_EL3 U(0x3) +#define MODE_EL2 U(0x2) +#define MODE_EL1 U(0x1) +#define MODE_EL0 U(0x0) + +#define MODE32_SHIFT U(0) +#define MODE32_MASK U(0xf) +#define MODE32_usr U(0x0) +#define MODE32_fiq U(0x1) +#define MODE32_irq U(0x2) +#define MODE32_svc U(0x3) +#define MODE32_mon U(0x6) +#define MODE32_abt U(0x7) +#define MODE32_hyp U(0xa) +#define MODE32_und U(0xb) +#define MODE32_sys U(0xf) + +#define GET_RW(mode) (((mode) >> MODE_RW_SHIFT) & MODE_RW_MASK) +#define GET_EL(mode) (((mode) >> MODE_EL_SHIFT) & MODE_EL_MASK) +#define GET_SP(mode) (((mode) >> MODE_SP_SHIFT) & MODE_SP_MASK) +#define GET_M32(mode) (((mode) >> MODE32_SHIFT) & MODE32_MASK) + +#define SPSR_64(el, sp, daif) \ + (((MODE_RW_64 << MODE_RW_SHIFT) | \ + (((el) & MODE_EL_MASK) << MODE_EL_SHIFT) | \ + (((sp) & MODE_SP_MASK) << MODE_SP_SHIFT) | \ + (((daif) & SPSR_DAIF_MASK) << SPSR_DAIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH64))) + +#define SPSR_MODE32(mode, isa, endian, aif) \ + (((MODE_RW_32 << MODE_RW_SHIFT) | \ + (((mode) & MODE32_MASK) << MODE32_SHIFT) | \ + (((isa) & SPSR_T_MASK) << SPSR_T_SHIFT) | \ + (((endian) & SPSR_E_MASK) << SPSR_E_SHIFT) | \ + (((aif) & SPSR_AIF_MASK) << SPSR_AIF_SHIFT)) & \ + (~(SPSR_SSBS_BIT_AARCH32))) + +/* + * TTBR Definitions + */ +#define TTBR_CNP_BIT ULL(0x1) + +/* + * CTR_EL0 definitions + */ +#define CTR_CWG_SHIFT U(24) +#define CTR_CWG_MASK U(0xf) +#define CTR_ERG_SHIFT U(20) +#define CTR_ERG_MASK U(0xf) +#define CTR_DMINLINE_SHIFT U(16) +#define CTR_DMINLINE_MASK U(0xf) +#define CTR_L1IP_SHIFT U(14) +#define CTR_L1IP_MASK U(0x3) +#define CTR_IMINLINE_SHIFT U(0) +#define CTR_IMINLINE_MASK U(0xf) + +#define MAX_CACHE_LINE_SIZE U(0x800) /* 2KB */ + +/* Physical timer control register bit fields shifts and masks */ +#define CNTP_CTL_ENABLE_SHIFT U(0) +#define CNTP_CTL_IMASK_SHIFT U(1) +#define CNTP_CTL_ISTATUS_SHIFT U(2) + +#define CNTP_CTL_ENABLE_MASK U(1) +#define CNTP_CTL_IMASK_MASK U(1) +#define CNTP_CTL_ISTATUS_MASK U(1) + +/* Physical timer control macros */ +#define CNTP_CTL_ENABLE_BIT (U(1) << CNTP_CTL_ENABLE_SHIFT) +#define CNTP_CTL_IMASK_BIT (U(1) << CNTP_CTL_IMASK_SHIFT) + +/* Exception Syndrome register bits and bobs */ +#define ESR_EC_SHIFT U(26) +#define ESR_EC_MASK U(0x3f) +#define ESR_EC_LENGTH U(6) +#define ESR_ISS_SHIFT U(0) +#define ESR_ISS_LENGTH U(25) +#define EC_UNKNOWN U(0x0) +#define EC_WFE_WFI U(0x1) +#define EC_AARCH32_CP15_MRC_MCR U(0x3) +#define EC_AARCH32_CP15_MRRC_MCRR U(0x4) +#define EC_AARCH32_CP14_MRC_MCR U(0x5) +#define EC_AARCH32_CP14_LDC_STC U(0x6) +#define EC_FP_SIMD U(0x7) +#define EC_AARCH32_CP10_MRC U(0x8) +#define EC_AARCH32_CP14_MRRC_MCRR U(0xc) +#define EC_ILLEGAL U(0xe) +#define EC_AARCH32_SVC U(0x11) +#define EC_AARCH32_HVC U(0x12) +#define EC_AARCH32_SMC U(0x13) +#define EC_AARCH64_SVC U(0x15) +#define EC_AARCH64_HVC U(0x16) +#define EC_AARCH64_SMC U(0x17) +#define EC_AARCH64_SYS U(0x18) +#define EC_IABORT_LOWER_EL U(0x20) +#define EC_IABORT_CUR_EL U(0x21) +#define EC_PC_ALIGN U(0x22) +#define EC_DABORT_LOWER_EL U(0x24) +#define EC_DABORT_CUR_EL U(0x25) +#define EC_SP_ALIGN U(0x26) +#define EC_AARCH32_FP U(0x28) +#define EC_AARCH64_FP U(0x2c) +#define EC_SERROR U(0x2f) +#define EC_BRK U(0x3c) + +/* + * External Abort bit in Instruction and Data Aborts synchronous exception + * syndromes. + */ +#define ESR_ISS_EABORT_EA_BIT U(9) + +#define EC_BITS(x) (((x) >> ESR_EC_SHIFT) & ESR_EC_MASK) + +/* Reset bit inside the Reset management register for EL3 (RMR_EL3) */ +#define RMR_RESET_REQUEST_SHIFT U(0x1) +#define RMR_WARM_RESET_CPU (U(1) << RMR_RESET_REQUEST_SHIFT) + +/******************************************************************************* + * Definitions of register offsets, fields and macros for CPU system + * instructions. + ******************************************************************************/ + +#define TLBI_ADDR_SHIFT U(12) +#define TLBI_ADDR_MASK ULL(0x00000FFFFFFFFFFF) +#define TLBI_ADDR(x) (((x) >> TLBI_ADDR_SHIFT) & TLBI_ADDR_MASK) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTCTLBase Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +#define CNTCTLBASE_CNTFRQ U(0x0) +#define CNTNSAR U(0x4) +#define CNTNSAR_NS_SHIFT(x) (x) + +#define CNTACR_BASE(x) (U(0x40) + ((x) << 2)) +#define CNTACR_RPCT_SHIFT U(0x0) +#define CNTACR_RVCT_SHIFT U(0x1) +#define CNTACR_RFRQ_SHIFT U(0x2) +#define CNTACR_RVOFF_SHIFT U(0x3) +#define CNTACR_RWVT_SHIFT U(0x4) +#define CNTACR_RWPT_SHIFT U(0x5) + +/******************************************************************************* + * Definitions of register offsets and fields in the CNTBaseN Frame of the + * system level implementation of the Generic Timer. + ******************************************************************************/ +/* Physical Count register. */ +#define CNTPCT_LO U(0x0) +/* Counter Frequency register. */ +#define CNTBASEN_CNTFRQ U(0x10) +/* Physical Timer CompareValue register. */ +#define CNTP_CVAL_LO U(0x20) +/* Physical Timer Control register. */ +#define CNTP_CTL U(0x2c) + +/* PMCR_EL0 definitions */ +#define PMCR_EL0_RESET_VAL U(0x0) +#define PMCR_EL0_N_SHIFT U(11) +#define PMCR_EL0_N_MASK U(0x1f) +#define PMCR_EL0_N_BITS (PMCR_EL0_N_MASK << PMCR_EL0_N_SHIFT) +#define PMCR_EL0_LP_BIT (U(1) << 7) +#define PMCR_EL0_LC_BIT (U(1) << 6) +#define PMCR_EL0_DP_BIT (U(1) << 5) +#define PMCR_EL0_X_BIT (U(1) << 4) +#define PMCR_EL0_D_BIT (U(1) << 3) +#define PMCR_EL0_C_BIT (U(1) << 2) +#define PMCR_EL0_P_BIT (U(1) << 1) +#define PMCR_EL0_E_BIT (U(1) << 0) + +/******************************************************************************* + * Definitions for system register interface to SVE + ******************************************************************************/ +#define ZCR_EL3 S3_6_C1_C2_0 +#define ZCR_EL2 S3_4_C1_C2_0 + +/* ZCR_EL3 definitions */ +#define ZCR_EL3_LEN_MASK U(0xf) + +/* ZCR_EL2 definitions */ +#define ZCR_EL2_LEN_MASK U(0xf) + +/******************************************************************************* + * Definitions for system register interface to SME as needed in EL3 + ******************************************************************************/ +#define ID_AA64SMFR0_EL1 S3_0_C0_C4_5 +#define SMCR_EL3 S3_6_C1_C2_6 + +/* ID_AA64SMFR0_EL1 definitions */ +#define ID_AA64SMFR0_EL1_FA64_BIT (UL(1) << 63) + +/* SMCR_ELx definitions */ +#define SMCR_ELX_LEN_SHIFT U(0) +#define SMCR_ELX_LEN_MASK U(0x1ff) +#define SMCR_ELX_FA64_BIT (U(1) << 31) + +/******************************************************************************* + * Definitions of MAIR encodings for device and normal memory + ******************************************************************************/ +/* + * MAIR encodings for device memory attributes. + */ +#define MAIR_DEV_nGnRnE ULL(0x0) +#define MAIR_DEV_nGnRE ULL(0x4) +#define MAIR_DEV_nGRE ULL(0x8) +#define MAIR_DEV_GRE ULL(0xc) + +/* + * MAIR encodings for normal memory attributes. + * + * Cache Policy + * WT: Write Through + * WB: Write Back + * NC: Non-Cacheable + * + * Transient Hint + * NTR: Non-Transient + * TR: Transient + * + * Allocation Policy + * RA: Read Allocate + * WA: Write Allocate + * RWA: Read and Write Allocate + * NA: No Allocation + */ +#define MAIR_NORM_WT_TR_WA ULL(0x1) +#define MAIR_NORM_WT_TR_RA ULL(0x2) +#define MAIR_NORM_WT_TR_RWA ULL(0x3) +#define MAIR_NORM_NC ULL(0x4) +#define MAIR_NORM_WB_TR_WA ULL(0x5) +#define MAIR_NORM_WB_TR_RA ULL(0x6) +#define MAIR_NORM_WB_TR_RWA ULL(0x7) +#define MAIR_NORM_WT_NTR_NA ULL(0x8) +#define MAIR_NORM_WT_NTR_WA ULL(0x9) +#define MAIR_NORM_WT_NTR_RA ULL(0xa) +#define MAIR_NORM_WT_NTR_RWA ULL(0xb) +#define MAIR_NORM_WB_NTR_NA ULL(0xc) +#define MAIR_NORM_WB_NTR_WA ULL(0xd) +#define MAIR_NORM_WB_NTR_RA ULL(0xe) +#define MAIR_NORM_WB_NTR_RWA ULL(0xf) + +#define MAIR_NORM_OUTER_SHIFT U(4) + +#define MAKE_MAIR_NORMAL_MEMORY(inner, outer) \ + ((inner) | ((outer) << MAIR_NORM_OUTER_SHIFT)) + +/* PAR_EL1 fields */ +#define PAR_F_SHIFT U(0) +#define PAR_F_MASK ULL(0x1) +#define PAR_ADDR_SHIFT U(12) +#define PAR_ADDR_MASK (BIT(40) - ULL(1)) /* 40-bits-wide page address */ + +/******************************************************************************* + * Definitions for system register interface to SPE + ******************************************************************************/ +#define PMBLIMITR_EL1 S3_0_C9_C10_0 + +/******************************************************************************* + * Definitions for system register interface to MPAM + ******************************************************************************/ +#define MPAMIDR_EL1 S3_0_C10_C4_4 +#define MPAM2_EL2 S3_4_C10_C5_0 +#define MPAMHCR_EL2 S3_4_C10_C4_0 +#define MPAM3_EL3 S3_6_C10_C5_0 + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1 + ******************************************************************************/ +#define AMCR_EL0 S3_3_C13_C2_0 +#define AMCFGR_EL0 S3_3_C13_C2_1 +#define AMCGCR_EL0 S3_3_C13_C2_2 +#define AMUSERENR_EL0 S3_3_C13_C2_3 +#define AMCNTENCLR0_EL0 S3_3_C13_C2_4 +#define AMCNTENSET0_EL0 S3_3_C13_C2_5 +#define AMCNTENCLR1_EL0 S3_3_C13_C3_0 +#define AMCNTENSET1_EL0 S3_3_C13_C3_1 + +/* Activity Monitor Group 0 Event Counter Registers */ +#define AMEVCNTR00_EL0 S3_3_C13_C4_0 +#define AMEVCNTR01_EL0 S3_3_C13_C4_1 +#define AMEVCNTR02_EL0 S3_3_C13_C4_2 +#define AMEVCNTR03_EL0 S3_3_C13_C4_3 + +/* Activity Monitor Group 0 Event Type Registers */ +#define AMEVTYPER00_EL0 S3_3_C13_C6_0 +#define AMEVTYPER01_EL0 S3_3_C13_C6_1 +#define AMEVTYPER02_EL0 S3_3_C13_C6_2 +#define AMEVTYPER03_EL0 S3_3_C13_C6_3 + +/* Activity Monitor Group 1 Event Counter Registers */ +#define AMEVCNTR10_EL0 S3_3_C13_C12_0 +#define AMEVCNTR11_EL0 S3_3_C13_C12_1 +#define AMEVCNTR12_EL0 S3_3_C13_C12_2 +#define AMEVCNTR13_EL0 S3_3_C13_C12_3 +#define AMEVCNTR14_EL0 S3_3_C13_C12_4 +#define AMEVCNTR15_EL0 S3_3_C13_C12_5 +#define AMEVCNTR16_EL0 S3_3_C13_C12_6 +#define AMEVCNTR17_EL0 S3_3_C13_C12_7 +#define AMEVCNTR18_EL0 S3_3_C13_C13_0 +#define AMEVCNTR19_EL0 S3_3_C13_C13_1 +#define AMEVCNTR1A_EL0 S3_3_C13_C13_2 +#define AMEVCNTR1B_EL0 S3_3_C13_C13_3 +#define AMEVCNTR1C_EL0 S3_3_C13_C13_4 +#define AMEVCNTR1D_EL0 S3_3_C13_C13_5 +#define AMEVCNTR1E_EL0 S3_3_C13_C13_6 +#define AMEVCNTR1F_EL0 S3_3_C13_C13_7 + +/* Activity Monitor Group 1 Event Type Registers */ +#define AMEVTYPER10_EL0 S3_3_C13_C14_0 +#define AMEVTYPER11_EL0 S3_3_C13_C14_1 +#define AMEVTYPER12_EL0 S3_3_C13_C14_2 +#define AMEVTYPER13_EL0 S3_3_C13_C14_3 +#define AMEVTYPER14_EL0 S3_3_C13_C14_4 +#define AMEVTYPER15_EL0 S3_3_C13_C14_5 +#define AMEVTYPER16_EL0 S3_3_C13_C14_6 +#define AMEVTYPER17_EL0 S3_3_C13_C14_7 +#define AMEVTYPER18_EL0 S3_3_C13_C15_0 +#define AMEVTYPER19_EL0 S3_3_C13_C15_1 +#define AMEVTYPER1A_EL0 S3_3_C13_C15_2 +#define AMEVTYPER1B_EL0 S3_3_C13_C15_3 +#define AMEVTYPER1C_EL0 S3_3_C13_C15_4 +#define AMEVTYPER1D_EL0 S3_3_C13_C15_5 +#define AMEVTYPER1E_EL0 S3_3_C13_C15_6 +#define AMEVTYPER1F_EL0 S3_3_C13_C15_7 + +/* AMCNTENSET0_EL0 definitions */ +#define AMCNTENSET0_EL0_Pn_SHIFT U(0) +#define AMCNTENSET0_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENSET1_EL0 definitions */ +#define AMCNTENSET1_EL0_Pn_SHIFT U(0) +#define AMCNTENSET1_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENCLR0_EL0 definitions */ +#define AMCNTENCLR0_EL0_Pn_SHIFT U(0) +#define AMCNTENCLR0_EL0_Pn_MASK ULL(0xffff) + +/* AMCNTENCLR1_EL0 definitions */ +#define AMCNTENCLR1_EL0_Pn_SHIFT U(0) +#define AMCNTENCLR1_EL0_Pn_MASK ULL(0xffff) + +/* AMCFGR_EL0 definitions */ +#define AMCFGR_EL0_NCG_SHIFT U(28) +#define AMCFGR_EL0_NCG_MASK U(0xf) +#define AMCFGR_EL0_N_SHIFT U(0) +#define AMCFGR_EL0_N_MASK U(0xff) + +/* AMCGCR_EL0 definitions */ +#define AMCGCR_EL0_CG0NC_SHIFT U(0) +#define AMCGCR_EL0_CG0NC_MASK U(0xff) +#define AMCGCR_EL0_CG1NC_SHIFT U(8) +#define AMCGCR_EL0_CG1NC_MASK U(0xff) + +/* MPAM register definitions */ +#define MPAM3_EL3_MPAMEN_BIT (ULL(1) << 63) +#define MPAMHCR_EL2_TRAP_MPAMIDR_EL1 (ULL(1) << 31) + +#define MPAM2_EL2_TRAPMPAM0EL1 (ULL(1) << 49) +#define MPAM2_EL2_TRAPMPAM1EL1 (ULL(1) << 48) + +#define MPAMIDR_HAS_HCR_BIT (ULL(1) << 17) + +/******************************************************************************* + * Definitions for system register interface to AMU for FEAT_AMUv1p1 + ******************************************************************************/ + +/* Definition for register defining which virtual offsets are implemented. */ +#define AMCG1IDR_EL0 S3_3_C13_C2_6 +#define AMCG1IDR_CTR_MASK ULL(0xffff) +#define AMCG1IDR_CTR_SHIFT U(0) +#define AMCG1IDR_VOFF_MASK ULL(0xffff) +#define AMCG1IDR_VOFF_SHIFT U(16) + +/* New bit added to AMCR_EL0 */ +#define AMCR_CG1RZ_SHIFT U(17) +#define AMCR_CG1RZ_BIT (ULL(0x1) << AMCR_CG1RZ_SHIFT) + +/* + * Definitions for virtual offset registers for architected activity monitor + * event counters. + * AMEVCNTVOFF01_EL2 intentionally left undefined, as it does not exist. + */ +#define AMEVCNTVOFF00_EL2 S3_4_C13_C8_0 +#define AMEVCNTVOFF02_EL2 S3_4_C13_C8_2 +#define AMEVCNTVOFF03_EL2 S3_4_C13_C8_3 + +/* + * Definitions for virtual offset registers for auxiliary activity monitor event + * counters. + */ +#define AMEVCNTVOFF10_EL2 S3_4_C13_C10_0 +#define AMEVCNTVOFF11_EL2 S3_4_C13_C10_1 +#define AMEVCNTVOFF12_EL2 S3_4_C13_C10_2 +#define AMEVCNTVOFF13_EL2 S3_4_C13_C10_3 +#define AMEVCNTVOFF14_EL2 S3_4_C13_C10_4 +#define AMEVCNTVOFF15_EL2 S3_4_C13_C10_5 +#define AMEVCNTVOFF16_EL2 S3_4_C13_C10_6 +#define AMEVCNTVOFF17_EL2 S3_4_C13_C10_7 +#define AMEVCNTVOFF18_EL2 S3_4_C13_C11_0 +#define AMEVCNTVOFF19_EL2 S3_4_C13_C11_1 +#define AMEVCNTVOFF1A_EL2 S3_4_C13_C11_2 +#define AMEVCNTVOFF1B_EL2 S3_4_C13_C11_3 +#define AMEVCNTVOFF1C_EL2 S3_4_C13_C11_4 +#define AMEVCNTVOFF1D_EL2 S3_4_C13_C11_5 +#define AMEVCNTVOFF1E_EL2 S3_4_C13_C11_6 +#define AMEVCNTVOFF1F_EL2 S3_4_C13_C11_7 + +/******************************************************************************* + * Realm management extension register definitions + ******************************************************************************/ +#define GPCCR_EL3 S3_6_C2_C1_6 +#define GPTBR_EL3 S3_6_C2_C1_4 + +/******************************************************************************* + * RAS system registers + ******************************************************************************/ +#define DISR_EL1 S3_0_C12_C1_1 +#define DISR_A_BIT U(31) + +#define ERRIDR_EL1 S3_0_C5_C3_0 +#define ERRIDR_MASK U(0xffff) + +#define ERRSELR_EL1 S3_0_C5_C3_1 + +/* System register access to Standard Error Record registers */ +#define ERXFR_EL1 S3_0_C5_C4_0 +#define ERXCTLR_EL1 S3_0_C5_C4_1 +#define ERXSTATUS_EL1 S3_0_C5_C4_2 +#define ERXADDR_EL1 S3_0_C5_C4_3 +#define ERXPFGF_EL1 S3_0_C5_C4_4 +#define ERXPFGCTL_EL1 S3_0_C5_C4_5 +#define ERXPFGCDN_EL1 S3_0_C5_C4_6 +#define ERXMISC0_EL1 S3_0_C5_C5_0 +#define ERXMISC1_EL1 S3_0_C5_C5_1 + +#define ERXCTLR_ED_BIT (U(1) << 0) +#define ERXCTLR_UE_BIT (U(1) << 4) + +#define ERXPFGCTL_UC_BIT (U(1) << 1) +#define ERXPFGCTL_UEU_BIT (U(1) << 2) +#define ERXPFGCTL_CDEN_BIT (U(1) << 31) + +/******************************************************************************* + * Armv8.3 Pointer Authentication Registers + ******************************************************************************/ +#define APIAKeyLo_EL1 S3_0_C2_C1_0 +#define APIAKeyHi_EL1 S3_0_C2_C1_1 +#define APIBKeyLo_EL1 S3_0_C2_C1_2 +#define APIBKeyHi_EL1 S3_0_C2_C1_3 +#define APDAKeyLo_EL1 S3_0_C2_C2_0 +#define APDAKeyHi_EL1 S3_0_C2_C2_1 +#define APDBKeyLo_EL1 S3_0_C2_C2_2 +#define APDBKeyHi_EL1 S3_0_C2_C2_3 +#define APGAKeyLo_EL1 S3_0_C2_C3_0 +#define APGAKeyHi_EL1 S3_0_C2_C3_1 + +/******************************************************************************* + * Armv8.4 Data Independent Timing Registers + ******************************************************************************/ +#define DIT S3_3_C4_C2_5 +#define DIT_BIT BIT(24) + +/******************************************************************************* + * Armv8.5 - new MSR encoding to directly access PSTATE.SSBS field + ******************************************************************************/ +#define SSBS S3_3_C4_C2_6 + +/******************************************************************************* + * Armv8.5 - Memory Tagging Extension Registers + ******************************************************************************/ +#define TFSRE0_EL1 S3_0_C5_C6_1 +#define TFSR_EL1 S3_0_C5_C6_0 +#define RGSR_EL1 S3_0_C1_C0_5 +#define GCR_EL1 S3_0_C1_C0_6 + +/******************************************************************************* + * FEAT_HCX - Extended Hypervisor Configuration Register + ******************************************************************************/ +#define HCRX_EL2 S3_4_C1_C2_2 +#define HCRX_EL2_FGTnXS_BIT (UL(1) << 4) +#define HCRX_EL2_FnXS_BIT (UL(1) << 3) +#define HCRX_EL2_EnASR_BIT (UL(1) << 2) +#define HCRX_EL2_EnALS_BIT (UL(1) << 1) +#define HCRX_EL2_EnAS0_BIT (UL(1) << 0) + +/******************************************************************************* + * Definitions for DynamicIQ Shared Unit registers + ******************************************************************************/ +#define CLUSTERECTLR_EL1 S3_0_C15_C3_4 +#define CLUSTERPWRDN_EL1 S3_0_c15_c3_6 + +/* CLUSTERPWRDN_EL1 register definitions */ +#define DSU_CLUSTER_PWR_OFF 0 +#define DSU_CLUSTER_PWR_ON 1 +#define DSU_CLUSTER_PWR_MASK U(1) + +/* CLUSTERECTLR_EL1 register definitions */ +#define DSU_NC_CTRL_BIT BIT(0) +#define DSU_WRITEEVICT_BIT BIT(14) + +/******************************************************************************* + * Definitions for CPU Power/Performance Management registers + ******************************************************************************/ + +#define CPUPPMCR_EL3 S3_6_C15_C2_0 +#define CPUPPMCR_EL3_MPMMPINCTL_SHIFT UINT64_C(0) +#define CPUPPMCR_EL3_MPMMPINCTL_MASK UINT64_C(0x1) + +#define CPUMPMMCR_EL3 S3_6_C15_C2_1 +#define CPUMPMMCR_EL3_MPMM_EN_SHIFT UINT64_C(0) +#define CPUMPMMCR_EL3_MPMM_EN_MASK UINT64_C(0x1) + +/******************************************************************************* + * Definitions for Pointer Authentication controls Unit registers + ******************************************************************************/ +#define CPUPSELR_EL3 S3_6_c15_c8_0 +#define CPUPCR_EL3 S3_6_c15_c8_1 +#define CPUPOR_EL3 S3_6_c15_c8_2 +#define CPUPMR_EL3 S3_6_c15_c8_3 + +#endif /* ARCH_H */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch_features.h b/arm-trusted-firmware/include/arch/aarch64/arch_features.h new file mode 100644 index 0000000..a260f03 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch_features.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_FEATURES_H +#define ARCH_FEATURES_H + +#include + +#include + +static inline bool is_armv7_gentimer_present(void) +{ + /* The Generic Timer is always present in an ARMv8-A implementation */ + return true; +} + +static inline bool is_armv8_1_pan_present(void) +{ + return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_PAN_SHIFT) & + ID_AA64MMFR1_EL1_PAN_MASK) != 0U; +} + +static inline bool is_armv8_1_vhe_present(void) +{ + return ((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_VHE_SHIFT) & + ID_AA64MMFR1_EL1_VHE_MASK) != 0U; +} + +static inline bool is_armv8_2_ttcnp_present(void) +{ + return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_CNP_SHIFT) & + ID_AA64MMFR2_EL1_CNP_MASK) != 0U; +} + +static inline bool is_armv8_3_pauth_present(void) +{ + uint64_t mask = (ID_AA64ISAR1_GPI_MASK << ID_AA64ISAR1_GPI_SHIFT) | + (ID_AA64ISAR1_GPA_MASK << ID_AA64ISAR1_GPA_SHIFT) | + (ID_AA64ISAR1_API_MASK << ID_AA64ISAR1_API_SHIFT) | + (ID_AA64ISAR1_APA_MASK << ID_AA64ISAR1_APA_SHIFT); + + /* If any of the fields is not zero, PAuth is present */ + return (read_id_aa64isar1_el1() & mask) != 0U; +} + +static inline bool is_armv8_4_dit_present(void) +{ + return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_DIT_SHIFT) & + ID_AA64PFR0_DIT_MASK) == 1U; +} + +static inline bool is_armv8_4_ttst_present(void) +{ + return ((read_id_aa64mmfr2_el1() >> ID_AA64MMFR2_EL1_ST_SHIFT) & + ID_AA64MMFR2_EL1_ST_MASK) == 1U; +} + +static inline bool is_armv8_5_bti_present(void) +{ + return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_BT_SHIFT) & + ID_AA64PFR1_EL1_BT_MASK) == BTI_IMPLEMENTED; +} + +static inline unsigned int get_armv8_5_mte_support(void) +{ + return ((read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_MTE_SHIFT) & + ID_AA64PFR1_EL1_MTE_MASK); +} + +static inline bool is_armv8_4_sel2_present(void) +{ + return ((read_id_aa64pfr0_el1() >> ID_AA64PFR0_SEL2_SHIFT) & + ID_AA64PFR0_SEL2_MASK) == 1ULL; +} + +static inline bool is_armv8_6_twed_present(void) +{ + return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_TWED_SHIFT) & + ID_AA64MMFR1_EL1_TWED_MASK) == ID_AA64MMFR1_EL1_TWED_SUPPORTED); +} + +static inline bool is_armv8_6_fgt_present(void) +{ + return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_FGT_SHIFT) & + ID_AA64MMFR0_EL1_FGT_MASK) == ID_AA64MMFR0_EL1_FGT_SUPPORTED; +} + +static inline unsigned long int get_armv8_6_ecv_support(void) +{ + return ((read_id_aa64mmfr0_el1() >> ID_AA64MMFR0_EL1_ECV_SHIFT) & + ID_AA64MMFR0_EL1_ECV_MASK); +} + +static inline bool is_armv8_5_rng_present(void) +{ + return ((read_id_aa64isar0_el1() >> ID_AA64ISAR0_RNDR_SHIFT) & + ID_AA64ISAR0_RNDR_MASK); +} + +static inline bool is_armv8_6_feat_amuv1p1_present(void) +{ + return (((read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) & + ID_AA64PFR0_AMU_MASK) >= ID_AA64PFR0_AMU_V1P1); +} + +/* + * Return MPAM version: + * + * 0x00: None Armv8.0 or later + * 0x01: v0.1 Armv8.4 or later + * 0x10: v1.0 Armv8.2 or later + * 0x11: v1.1 Armv8.4 or later + * + */ +static inline unsigned int get_mpam_version(void) +{ + return (unsigned int)((((read_id_aa64pfr0_el1() >> + ID_AA64PFR0_MPAM_SHIFT) & ID_AA64PFR0_MPAM_MASK) << 4) | + ((read_id_aa64pfr1_el1() >> + ID_AA64PFR1_MPAM_FRAC_SHIFT) & ID_AA64PFR1_MPAM_FRAC_MASK)); +} + +static inline bool is_feat_hcx_present(void) +{ + return (((read_id_aa64mmfr1_el1() >> ID_AA64MMFR1_EL1_HCX_SHIFT) & + ID_AA64MMFR1_EL1_HCX_MASK) == ID_AA64MMFR1_EL1_HCX_SUPPORTED); +} + +static inline unsigned int get_armv9_2_feat_rme_support(void) +{ + /* + * Return the RME version, zero if not supported. This function can be + * used as both an integer value for the RME version or compared to zero + * to detect RME presence. + */ + return (unsigned int)(read_id_aa64pfr0_el1() >> + ID_AA64PFR0_FEAT_RME_SHIFT) & ID_AA64PFR0_FEAT_RME_MASK; +} + +#endif /* ARCH_FEATURES_H */ diff --git a/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h b/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h new file mode 100644 index 0000000..7ce86df --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/arch_helpers.h @@ -0,0 +1,671 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARCH_HELPERS_H +#define ARCH_HELPERS_H + +#include +#include +#include +#include + +#include + +/********************************************************************** + * Macros which create inline functions to read or write CPU system + * registers + *********************************************************************/ + +#define _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ +static inline u_register_t read_ ## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("mrs %0, " #_reg_name : "=r" (v)); \ + return v; \ +} + +#define _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) \ +static inline void write_ ## _name(u_register_t v) \ +{ \ + __asm__ volatile ("msr " #_reg_name ", %0" : : "r" (v)); \ +} + +#define SYSREG_WRITE_CONST(reg_name, v) \ + __asm__ volatile ("msr " #reg_name ", %0" : : "i" (v)) + +/* Define read function for system register */ +#define DEFINE_SYSREG_READ_FUNC(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) + +/* Define read & write function for system register */ +#define DEFINE_SYSREG_RW_FUNCS(_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _name) + +/* Define read & write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_RW_FUNCS(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/* Define read function for renamed system register */ +#define DEFINE_RENAME_SYSREG_READ_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_READ_FUNC(_name, _reg_name) + +/* Define write function for renamed system register */ +#define DEFINE_RENAME_SYSREG_WRITE_FUNC(_name, _reg_name) \ + _DEFINE_SYSREG_WRITE_FUNC(_name, _reg_name) + +/********************************************************************** + * Macros to create inline functions for system instructions + *********************************************************************/ + +/* Define function for simple system instruction */ +#define DEFINE_SYSOP_FUNC(_op) \ +static inline void _op(void) \ +{ \ + __asm__ (#_op); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_PARAM_FUNC(_op) \ +static inline void _op(uint64_t v) \ +{ \ + __asm__ (#_op " %0" : : "r" (v)); \ +} + +/* Define function for system instruction with type specifier */ +#define DEFINE_SYSOP_TYPE_FUNC(_op, _type) \ +static inline void _op ## _type(void) \ +{ \ + __asm__ (#_op " " #_type : : : "memory"); \ +} + +/* Define function for system instruction with register parameter */ +#define DEFINE_SYSOP_TYPE_PARAM_FUNC(_op, _type) \ +static inline void _op ## _type(uint64_t v) \ +{ \ + __asm__ (#_op " " #_type ", %0" : : "r" (v)); \ +} + +/******************************************************************************* + * TLB maintenance accessor prototypes + ******************************************************************************/ + +#if ERRATA_A57_813419 || ERRATA_A76_1286807 +/* + * Define function for TLBI instruction with type specifier that implements + * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of + * Cortex-A76. + */ +#define DEFINE_TLBIOP_ERRATA_TYPE_FUNC(_type)\ +static inline void tlbi ## _type(void) \ +{ \ + __asm__("tlbi " #_type "\n" \ + "dsb ish\n" \ + "tlbi " #_type); \ +} + +/* + * Define function for TLBI instruction with register parameter that implements + * the workaround for errata 813419 of Cortex-A57 or errata 1286807 of + * Cortex-A76. + */ +#define DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(_type) \ +static inline void tlbi ## _type(uint64_t v) \ +{ \ + __asm__("tlbi " #_type ", %0\n" \ + "dsb ish\n" \ + "tlbi " #_type ", %0" : : "r" (v)); \ +} +#endif /* ERRATA_A57_813419 */ + +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +/* + * Define function for DC instruction with register parameter that enables + * the workaround for errata 819472, 824069 and 827319 of Cortex-A53. + */ +#define DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(_name, _type) \ +static inline void dc ## _name(uint64_t v) \ +{ \ + __asm__("dc " #_type ", %0" : : "r" (v)); \ +} +#endif /* ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 */ + +#if ERRATA_A57_813419 +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) +#elif ERRATA_A76_1286807 +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle1is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle2is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(alle3is) +DEFINE_TLBIOP_ERRATA_TYPE_FUNC(vmalle1) +#else +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle1is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle2is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3) +DEFINE_SYSOP_TYPE_FUNC(tlbi, alle3is) +DEFINE_SYSOP_TYPE_FUNC(tlbi, vmalle1) +#endif + +#if ERRATA_A57_813419 +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is) +#elif ERRATA_A76_1286807 +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaae1is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vaale1is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale2is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vae3is) +DEFINE_TLBIOP_ERRATA_TYPE_PARAM_FUNC(vale3is) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaae1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vaale1is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale2is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vae3is) +DEFINE_SYSOP_TYPE_PARAM_FUNC(tlbi, vale3is) +#endif + +/******************************************************************************* + * Cache maintenance accessor prototypes + ******************************************************************************/ +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, isw) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cisw) +#if ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(csw, cisw) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, csw) +#endif +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvac, civac) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvac) +#endif +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, ivac) +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, civac) +#if ERRATA_A53_819472 || ERRATA_A53_824069 || ERRATA_A53_827319 +DEFINE_DCOP_ERRATA_A53_TYPE_PARAM_FUNC(cvau, civac) +#else +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, cvau) +#endif +DEFINE_SYSOP_TYPE_PARAM_FUNC(dc, zva) + +/******************************************************************************* + * Address translation accessor prototypes + ******************************************************************************/ +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e1w) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s12e0w) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e1r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e2r) +DEFINE_SYSOP_TYPE_PARAM_FUNC(at, s1e3r) + +/******************************************************************************* + * Strip Pointer Authentication Code + ******************************************************************************/ +DEFINE_SYSOP_PARAM_FUNC(xpaci) + +void flush_dcache_range(uintptr_t addr, size_t size); +void flush_dcache_to_popa_range(uintptr_t addr, size_t size); +void clean_dcache_range(uintptr_t addr, size_t size); +void inv_dcache_range(uintptr_t addr, size_t size); +bool is_dcache_enabled(void); + +void dcsw_op_louis(u_register_t op_type); +void dcsw_op_all(u_register_t op_type); + +void disable_mmu_el1(void); +void disable_mmu_el3(void); +void disable_mpu_el2(void); +void disable_mmu_icache_el1(void); +void disable_mmu_icache_el3(void); +void disable_mpu_icache_el2(void); + +/******************************************************************************* + * Misc. accessor prototypes + ******************************************************************************/ + +#define write_daifclr(val) SYSREG_WRITE_CONST(daifclr, val) +#define write_daifset(val) SYSREG_WRITE_CONST(daifset, val) + +DEFINE_SYSREG_RW_FUNCS(par_el1) +DEFINE_SYSREG_READ_FUNC(id_pfr1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64isar0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64isar1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64pfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64pfr1_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64dfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_afr0_el1) +DEFINE_SYSREG_READ_FUNC(CurrentEl) +DEFINE_SYSREG_READ_FUNC(ctr_el0) +DEFINE_SYSREG_RW_FUNCS(daif) +DEFINE_SYSREG_RW_FUNCS(spsr_el1) +DEFINE_SYSREG_RW_FUNCS(spsr_el2) +DEFINE_SYSREG_RW_FUNCS(spsr_el3) +DEFINE_SYSREG_RW_FUNCS(elr_el1) +DEFINE_SYSREG_RW_FUNCS(elr_el2) +DEFINE_SYSREG_RW_FUNCS(elr_el3) +DEFINE_SYSREG_RW_FUNCS(mdccsr_el0) +DEFINE_SYSREG_RW_FUNCS(dbgdtrrx_el0) +DEFINE_SYSREG_RW_FUNCS(dbgdtrtx_el0) + +DEFINE_SYSOP_FUNC(wfi) +DEFINE_SYSOP_FUNC(wfe) +DEFINE_SYSOP_FUNC(sev) +DEFINE_SYSOP_TYPE_FUNC(dsb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, sy) +DEFINE_SYSOP_TYPE_FUNC(dmb, st) +DEFINE_SYSOP_TYPE_FUNC(dmb, ld) +DEFINE_SYSOP_TYPE_FUNC(dsb, ish) +DEFINE_SYSOP_TYPE_FUNC(dsb, osh) +DEFINE_SYSOP_TYPE_FUNC(dsb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dsb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dsb, oshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, oshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, osh) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshld) +DEFINE_SYSOP_TYPE_FUNC(dmb, nshst) +DEFINE_SYSOP_TYPE_FUNC(dmb, nsh) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishld) +DEFINE_SYSOP_TYPE_FUNC(dmb, ishst) +DEFINE_SYSOP_TYPE_FUNC(dmb, ish) +DEFINE_SYSOP_FUNC(isb) + +static inline void enable_irq(void) +{ + /* + * The compiler memory barrier will prevent the compiler from + * scheduling non-volatile memory access after the write to the + * register. + * + * This could happen if some initialization code issues non-volatile + * accesses to an area used by an interrupt handler, in the assumption + * that it is safe as the interrupts are disabled at the time it does + * that (according to program order). However, non-volatile accesses + * are not necessarily in program order relatively with volatile inline + * assembly statements (and volatile accesses). + */ + COMPILER_BARRIER(); + write_daifclr(DAIF_IRQ_BIT); + isb(); +} + +static inline void enable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_FIQ_BIT); + isb(); +} + +static inline void enable_serror(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_ABT_BIT); + isb(); +} + +static inline void enable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifclr(DAIF_DBG_BIT); + isb(); +} + +static inline void disable_irq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_IRQ_BIT); + isb(); +} + +static inline void disable_fiq(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_FIQ_BIT); + isb(); +} + +static inline void disable_serror(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_ABT_BIT); + isb(); +} + +static inline void disable_debug_exceptions(void) +{ + COMPILER_BARRIER(); + write_daifset(DAIF_DBG_BIT); + isb(); +} + +void __dead2 smc(uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, uint64_t x5, uint64_t x6, uint64_t x7); + +/******************************************************************************* + * System register accessor prototypes + ******************************************************************************/ +DEFINE_SYSREG_READ_FUNC(midr_el1) +DEFINE_SYSREG_READ_FUNC(mpidr_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64mmfr0_el1) +DEFINE_SYSREG_READ_FUNC(id_aa64mmfr1_el1) + +DEFINE_SYSREG_RW_FUNCS(scr_el3) +DEFINE_SYSREG_RW_FUNCS(hcr_el2) + +DEFINE_SYSREG_RW_FUNCS(vbar_el1) +DEFINE_SYSREG_RW_FUNCS(vbar_el2) +DEFINE_SYSREG_RW_FUNCS(vbar_el3) + +DEFINE_SYSREG_RW_FUNCS(sctlr_el1) +DEFINE_SYSREG_RW_FUNCS(sctlr_el2) +DEFINE_SYSREG_RW_FUNCS(sctlr_el3) + +DEFINE_SYSREG_RW_FUNCS(actlr_el1) +DEFINE_SYSREG_RW_FUNCS(actlr_el2) +DEFINE_SYSREG_RW_FUNCS(actlr_el3) + +DEFINE_SYSREG_RW_FUNCS(esr_el1) +DEFINE_SYSREG_RW_FUNCS(esr_el2) +DEFINE_SYSREG_RW_FUNCS(esr_el3) + +DEFINE_SYSREG_RW_FUNCS(afsr0_el1) +DEFINE_SYSREG_RW_FUNCS(afsr0_el2) +DEFINE_SYSREG_RW_FUNCS(afsr0_el3) + +DEFINE_SYSREG_RW_FUNCS(afsr1_el1) +DEFINE_SYSREG_RW_FUNCS(afsr1_el2) +DEFINE_SYSREG_RW_FUNCS(afsr1_el3) + +DEFINE_SYSREG_RW_FUNCS(far_el1) +DEFINE_SYSREG_RW_FUNCS(far_el2) +DEFINE_SYSREG_RW_FUNCS(far_el3) + +DEFINE_SYSREG_RW_FUNCS(mair_el1) +DEFINE_SYSREG_RW_FUNCS(mair_el2) +DEFINE_SYSREG_RW_FUNCS(mair_el3) + +DEFINE_SYSREG_RW_FUNCS(amair_el1) +DEFINE_SYSREG_RW_FUNCS(amair_el2) +DEFINE_SYSREG_RW_FUNCS(amair_el3) + +DEFINE_SYSREG_READ_FUNC(rvbar_el1) +DEFINE_SYSREG_READ_FUNC(rvbar_el2) +DEFINE_SYSREG_READ_FUNC(rvbar_el3) + +DEFINE_SYSREG_RW_FUNCS(rmr_el1) +DEFINE_SYSREG_RW_FUNCS(rmr_el2) +DEFINE_SYSREG_RW_FUNCS(rmr_el3) + +DEFINE_SYSREG_RW_FUNCS(tcr_el1) +DEFINE_SYSREG_RW_FUNCS(tcr_el2) +DEFINE_SYSREG_RW_FUNCS(tcr_el3) + +DEFINE_SYSREG_RW_FUNCS(ttbr0_el1) +DEFINE_SYSREG_RW_FUNCS(ttbr0_el2) +DEFINE_SYSREG_RW_FUNCS(ttbr0_el3) + +DEFINE_SYSREG_RW_FUNCS(ttbr1_el1) + +DEFINE_SYSREG_RW_FUNCS(vttbr_el2) + +DEFINE_SYSREG_RW_FUNCS(cptr_el2) +DEFINE_SYSREG_RW_FUNCS(cptr_el3) + +DEFINE_SYSREG_RW_FUNCS(cpacr_el1) +DEFINE_SYSREG_RW_FUNCS(cntfrq_el0) +DEFINE_SYSREG_RW_FUNCS(cnthp_ctl_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_tval_el2) +DEFINE_SYSREG_RW_FUNCS(cnthp_cval_el2) +DEFINE_SYSREG_RW_FUNCS(cntps_ctl_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_tval_el1) +DEFINE_SYSREG_RW_FUNCS(cntps_cval_el1) +DEFINE_SYSREG_RW_FUNCS(cntp_ctl_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_tval_el0) +DEFINE_SYSREG_RW_FUNCS(cntp_cval_el0) +DEFINE_SYSREG_READ_FUNC(cntpct_el0) +DEFINE_SYSREG_RW_FUNCS(cnthctl_el2) + +DEFINE_SYSREG_RW_FUNCS(vtcr_el2) + +#define get_cntp_ctl_enable(x) (((x) >> CNTP_CTL_ENABLE_SHIFT) & \ + CNTP_CTL_ENABLE_MASK) +#define get_cntp_ctl_imask(x) (((x) >> CNTP_CTL_IMASK_SHIFT) & \ + CNTP_CTL_IMASK_MASK) +#define get_cntp_ctl_istatus(x) (((x) >> CNTP_CTL_ISTATUS_SHIFT) & \ + CNTP_CTL_ISTATUS_MASK) + +#define set_cntp_ctl_enable(x) ((x) |= (U(1) << CNTP_CTL_ENABLE_SHIFT)) +#define set_cntp_ctl_imask(x) ((x) |= (U(1) << CNTP_CTL_IMASK_SHIFT)) + +#define clr_cntp_ctl_enable(x) ((x) &= ~(U(1) << CNTP_CTL_ENABLE_SHIFT)) +#define clr_cntp_ctl_imask(x) ((x) &= ~(U(1) << CNTP_CTL_IMASK_SHIFT)) + +DEFINE_SYSREG_RW_FUNCS(tpidr_el3) + +DEFINE_SYSREG_RW_FUNCS(cntvoff_el2) + +DEFINE_SYSREG_RW_FUNCS(vpidr_el2) +DEFINE_SYSREG_RW_FUNCS(vmpidr_el2) + +DEFINE_SYSREG_READ_FUNC(isr_el1) + +DEFINE_SYSREG_RW_FUNCS(mdcr_el2) +DEFINE_SYSREG_RW_FUNCS(mdcr_el3) +DEFINE_SYSREG_RW_FUNCS(hstr_el2) +DEFINE_SYSREG_RW_FUNCS(pmcr_el0) + +/* GICv3 System Registers */ + +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el1, ICC_SRE_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el2, ICC_SRE_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sre_el3, ICC_SRE_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_pmr_el1, ICC_PMR_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_rpr_el1, ICC_RPR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el3, ICC_IGRPEN1_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen1_el1, ICC_IGRPEN1_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_igrpen0_el1, ICC_IGRPEN0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir0_el1, ICC_HPPIR0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_hppir1_el1, ICC_HPPIR1_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar0_el1, ICC_IAR0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(icc_iar1_el1, ICC_IAR1_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir0_el1, ICC_EOIR0_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_eoir1_el1, ICC_EOIR1_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(icc_sgi0r_el1, ICC_SGI0R_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(icc_sgi1r, ICC_SGI1R) + +DEFINE_RENAME_SYSREG_READ_FUNC(amcfgr_el0, AMCFGR_EL0) +DEFINE_RENAME_SYSREG_READ_FUNC(amcgcr_el0, AMCGCR_EL0) +DEFINE_RENAME_SYSREG_READ_FUNC(amcg1idr_el0, AMCG1IDR_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcr_el0, AMCR_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr0_el0, AMCNTENCLR0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset0_el0, AMCNTENSET0_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenclr1_el0, AMCNTENCLR1_EL0) +DEFINE_RENAME_SYSREG_RW_FUNCS(amcntenset1_el0, AMCNTENSET1_EL0) + +DEFINE_RENAME_SYSREG_READ_FUNC(mpamidr_el1, MPAMIDR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam3_el3, MPAM3_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpam2_el2, MPAM2_EL2) +DEFINE_RENAME_SYSREG_RW_FUNCS(mpamhcr_el2, MPAMHCR_EL2) + +DEFINE_RENAME_SYSREG_RW_FUNCS(pmblimitr_el1, PMBLIMITR_EL1) + +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el3, ZCR_EL3) +DEFINE_RENAME_SYSREG_WRITE_FUNC(zcr_el2, ZCR_EL2) + +DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64smfr0_el1, ID_AA64SMFR0_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(smcr_el3, SMCR_EL3) + +DEFINE_RENAME_SYSREG_READ_FUNC(erridr_el1, ERRIDR_EL1) +DEFINE_RENAME_SYSREG_WRITE_FUNC(errselr_el1, ERRSELR_EL1) + +DEFINE_RENAME_SYSREG_READ_FUNC(erxfr_el1, ERXFR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(erxctlr_el1, ERXCTLR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(erxstatus_el1, ERXSTATUS_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxaddr_el1, ERXADDR_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc0_el1, ERXMISC0_EL1) +DEFINE_RENAME_SYSREG_READ_FUNC(erxmisc1_el1, ERXMISC1_EL1) + +/* Armv8.2 Registers */ +DEFINE_RENAME_SYSREG_READ_FUNC(id_aa64mmfr2_el1, ID_AA64MMFR2_EL1) + +/* Armv8.3 Pointer Authentication Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeyhi_el1, APIAKeyHi_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(apiakeylo_el1, APIAKeyLo_EL1) + +/* Armv8.4 Data Independent Timing Register */ +DEFINE_RENAME_SYSREG_RW_FUNCS(dit, DIT) + +/* Armv8.5 MTE Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(tfsre0_el1, TFSRE0_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(tfsr_el1, TFSR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(rgsr_el1, RGSR_EL1) +DEFINE_RENAME_SYSREG_RW_FUNCS(gcr_el1, GCR_EL1) + +/* Armv8.5 FEAT_RNG Registers */ +DEFINE_SYSREG_READ_FUNC(rndr) +DEFINE_SYSREG_READ_FUNC(rndrrs) + +/* FEAT_HCX Register */ +DEFINE_RENAME_SYSREG_RW_FUNCS(hcrx_el2, HCRX_EL2) + +/* DynamIQ Shared Unit registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(clusterectlr_el1, CLUSTERECTLR_EL1) + +/* DynamIQ Shared Unit power management */ +DEFINE_RENAME_SYSREG_RW_FUNCS(clusterpwrdn_el1, CLUSTERPWRDN_EL1) + +/* CPU Power/Performance Management registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(cpuppmcr_el3, CPUPPMCR_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(cpumpmmcr_el3, CPUMPMMCR_EL3) + +/* Armv9.2 RME Registers */ +DEFINE_RENAME_SYSREG_RW_FUNCS(gptbr_el3, GPTBR_EL3) +DEFINE_RENAME_SYSREG_RW_FUNCS(gpccr_el3, GPCCR_EL3) + +#define IS_IN_EL(x) \ + (GET_EL(read_CurrentEl()) == MODE_EL##x) + +#define IS_IN_EL1() IS_IN_EL(1) +#define IS_IN_EL2() IS_IN_EL(2) +#define IS_IN_EL3() IS_IN_EL(3) + +static inline unsigned int get_current_el(void) +{ + return GET_EL(read_CurrentEl()); +} + +static inline unsigned int get_current_el_maybe_constant(void) +{ +#if defined(IMAGE_AT_EL1) + return 1; +#elif defined(IMAGE_AT_EL2) + return 2; /* no use-case in TF-A */ +#elif defined(IMAGE_AT_EL3) + return 3; +#else + /* + * If we do not know which exception level this is being built for + * (e.g. built for library), fall back to run-time detection. + */ + return get_current_el(); +#endif +} + +/* + * Check if an EL is implemented from AA64PFR0 register fields. + */ +static inline uint64_t el_implemented(unsigned int el) +{ + if (el > 3U) { + return EL_IMPL_NONE; + } else { + unsigned int shift = ID_AA64PFR0_EL1_SHIFT * el; + + return (read_id_aa64pfr0_el1() >> shift) & ID_AA64PFR0_ELX_MASK; + } +} + +/* + * TLBIPAALLOS instruction + * (TLB Inivalidate GPT Information by PA, + * All Entries, Outer Shareable) + */ +static inline void tlbipaallos(void) +{ + __asm__("SYS #6,c8,c1,#4"); +} + +/* + * Invalidate TLBs of GPT entries by Physical address, last level. + * + * @pa: the starting address for the range + * of invalidation + * @size: size of the range of invalidation + */ +void gpt_tlbi_by_pa_ll(uint64_t pa, size_t size); + + +/* Previously defined accessor functions with incomplete register names */ + +#define read_current_el() read_CurrentEl() + +#define dsb() dsbsy() + +#define read_midr() read_midr_el1() + +#define read_mpidr() read_mpidr_el1() + +#define read_scr() read_scr_el3() +#define write_scr(_v) write_scr_el3(_v) + +#define read_hcr() read_hcr_el2() +#define write_hcr(_v) write_hcr_el2(_v) + +#define read_cpacr() read_cpacr_el1() +#define write_cpacr(_v) write_cpacr_el1(_v) + +#define read_clusterpwrdn() read_clusterpwrdn_el1() +#define write_clusterpwrdn(_v) write_clusterpwrdn_el1(_v) + +#if ERRATA_SPECULATIVE_AT +/* + * Assuming SCTLR.M bit is already enabled + * 1. Enable page table walk by clearing TCR_EL1.EPDx bits + * 2. Execute AT instruction for lower EL1/0 + * 3. Disable page table walk by setting TCR_EL1.EPDx bits + */ +#define AT(_at_inst, _va) \ +{ \ + assert((read_sctlr_el1() & SCTLR_M_BIT) != 0ULL); \ + write_tcr_el1(read_tcr_el1() & ~(TCR_EPD0_BIT | TCR_EPD1_BIT)); \ + isb(); \ + _at_inst(_va); \ + write_tcr_el1(read_tcr_el1() | (TCR_EPD0_BIT | TCR_EPD1_BIT)); \ + isb(); \ +} +#else +#define AT(_at_inst, _va) _at_inst(_va); +#endif + +#endif /* ARCH_HELPERS_H */ diff --git a/arm-trusted-firmware/include/arch/aarch64/asm_macros.S b/arm-trusted-firmware/include/arch/aarch64/asm_macros.S new file mode 100644 index 0000000..7706cd8 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/asm_macros.S @@ -0,0 +1,231 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_S +#define ASM_MACROS_S + +#include +#include +#include + +/* + * TLBI instruction with type specifier that implements the workaround for + * errata 813419 of Cortex-A57 or errata 1286807 of Cortex-A76. + */ +#if ERRATA_A57_813419 || ERRATA_A76_1286807 +#define TLB_INVALIDATE(_type) \ + tlbi _type; \ + dsb ish; \ + tlbi _type +#else +#define TLB_INVALIDATE(_type) \ + tlbi _type +#endif + + + .macro func_prologue + stp x29, x30, [sp, #-0x10]! + mov x29,sp + .endm + + .macro func_epilogue + ldp x29, x30, [sp], #0x10 + .endm + + + .macro dcache_line_size reg, tmp + mrs \tmp, ctr_el0 + ubfx \tmp, \tmp, #16, #4 + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + + .macro icache_line_size reg, tmp + mrs \tmp, ctr_el0 + and \tmp, \tmp, #0xf + mov \reg, #4 + lsl \reg, \reg, \tmp + .endm + + + .macro smc_check label + mrs x0, esr_el3 + ubfx x0, x0, #ESR_EC_SHIFT, #ESR_EC_LENGTH + cmp x0, #EC_AARCH64_SMC + b.ne $label + .endm + + /* + * Declare the exception vector table, enforcing it is aligned on a + * 2KB boundary, as required by the ARMv8 architecture. + * Use zero bytes as the fill value to be stored in the padding bytes + * so that it inserts illegal AArch64 instructions. This increases + * security, robustness and potentially facilitates debugging. + */ + .macro vector_base label, section_name=.vectors + .section \section_name, "ax" + .align 11, 0 + \label: + .endm + + /* + * Create an entry in the exception vector table, enforcing it is + * aligned on a 128-byte boundary, as required by the ARMv8 architecture. + * Use zero bytes as the fill value to be stored in the padding bytes + * so that it inserts illegal AArch64 instructions. This increases + * security, robustness and potentially facilitates debugging. + */ + .macro vector_entry label, section_name=.vectors + .cfi_sections .debug_frame + .section \section_name, "ax" + .align 7, 0 + .type \label, %function + .cfi_startproc + \label: + .endm + + /* + * Add the bytes until fill the full exception vector, whose size is always + * 32 instructions. If there are more than 32 instructions in the + * exception vector then an error is emitted. + */ + .macro end_vector_entry label + .cfi_endproc + .fill \label + (32 * 4) - . + .endm + + /* + * This macro calculates the base address of the current CPU's MP stack + * using the plat_my_core_pos() index, the name of the stack storage + * and the size of each stack + * Out: X0 = physical address of stack base + * Clobber: X30, X1, X2 + */ + .macro get_my_mp_stack _name, _size + bl plat_my_core_pos + adrp x2, (\_name + \_size) + add x2, x2, :lo12:(\_name + \_size) + mov x1, #\_size + madd x0, x0, x1, x2 + .endm + + /* + * This macro calculates the base address of a UP stack using the + * name of the stack storage and the size of the stack + * Out: X0 = physical address of stack base + */ + .macro get_up_stack _name, _size + adrp x0, (\_name + \_size) + add x0, x0, :lo12:(\_name + \_size) + .endm + + /* + * Helper macro to generate the best mov/movk combinations according + * the value to be moved. The 16 bits from '_shift' are tested and + * if not zero, they are moved into '_reg' without affecting + * other bits. + */ + .macro _mov_imm16 _reg, _val, _shift + .if (\_val >> \_shift) & 0xffff + .if (\_val & (1 << \_shift - 1)) + movk \_reg, (\_val >> \_shift) & 0xffff, LSL \_shift + .else + mov \_reg, \_val & (0xffff << \_shift) + .endif + .endif + .endm + + /* + * Helper macro to load arbitrary values into 32 or 64-bit registers + * which generates the best mov/movk combinations. Many base addresses + * are 64KB aligned the macro will eliminate updating bits 15:0 in + * that case + */ + .macro mov_imm _reg, _val + .if (\_val) == 0 + mov \_reg, #0 + .else + _mov_imm16 \_reg, (\_val), 0 + _mov_imm16 \_reg, (\_val), 16 + _mov_imm16 \_reg, (\_val), 32 + _mov_imm16 \_reg, (\_val), 48 + .endif + .endm + + /* + * Macro to mark instances where we're jumping to a function and don't + * expect a return. To provide the function being jumped to with + * additional information, we use 'bl' instruction to jump rather than + * 'b'. + * + * Debuggers infer the location of a call from where LR points to, which + * is usually the instruction after 'bl'. If this macro expansion + * happens to be the last location in a function, that'll cause the LR + * to point a location beyond the function, thereby misleading debugger + * back trace. We therefore insert a 'nop' after the function call for + * debug builds, unless 'skip_nop' parameter is non-zero. + */ + .macro no_ret _func:req, skip_nop=0 + bl \_func +#if DEBUG + .ifeq \skip_nop + nop + .endif +#endif + .endm + + /* + * Reserve space for a spin lock in assembly file. + */ + .macro define_asm_spinlock _name:req + .align SPINLOCK_ASM_ALIGN + \_name: + .space SPINLOCK_ASM_SIZE + .endm + +#if RAS_EXTENSION + .macro esb + .inst 0xd503221f + .endm +#endif + + /* + * Helper macro to read system register value into x0 + */ + .macro read reg:req +#if ENABLE_BTI + bti j +#endif + mrs x0, \reg + ret + .endm + + /* + * Helper macro to write value from x1 to system register + */ + .macro write reg:req +#if ENABLE_BTI + bti j +#endif + msr \reg, x1 + ret + .endm + + /* + * Macro for mitigating against speculative execution beyond ERET. Uses the + * speculation barrier instruction introduced by FEAT_SB, if it's enabled. + */ + .macro exception_return + eret +#if ENABLE_FEAT_SB + sb +#else + dsb nsh + isb +#endif + .endm + +#endif /* ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/assert_macros.S b/arm-trusted-firmware/include/arch/aarch64/assert_macros.S new file mode 100644 index 0000000..06371c4 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/assert_macros.S @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASSERT_MACROS_S +#define ASSERT_MACROS_S + + /* + * Assembler macro to enable asm_assert. Use this macro wherever + * assert is required in assembly. Please note that the macro makes + * use of label '300' to provide the logic and the caller + * should make sure that this label is not used to branch prior + * to calling this macro. + */ +#define ASM_ASSERT(_cc) \ +.ifndef .L_assert_filename ;\ + .pushsection .rodata.str1.1, "aS" ;\ + .L_assert_filename: ;\ + .string __FILE__ ;\ + .popsection ;\ +.endif ;\ + b._cc 300f ;\ + adr x0, .L_assert_filename ;\ + mov x1, __LINE__ ;\ + b asm_assert ;\ +300: + +#endif /* ASSERT_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/console_macros.S b/arm-trusted-firmware/include/arch/aarch64/console_macros.S new file mode 100644 index 0000000..3285d85 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/console_macros.S @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CONSOLE_MACROS_S +#define CONSOLE_MACROS_S + +#include + +/* + * This macro encapsulates the common setup that has to be done at the end of + * a console driver's register function. It will register all of the driver's + * callbacks in the console_t structure and initialize the flags field (by + * default consoles are enabled for the "boot" and "crash" states, this can be + * changed after registration with the console_set_scope() function). It ends + * with a tail call that will include return to the caller. + * REQUIRES console_t pointer in x0 and a valid return address in x30. + */ + .macro finish_console_register _driver, putc=0, getc=0, flush=0 + /* + * If any of the callback is not specified or set as 0, then the + * corresponding callback entry in console_t is set to 0. + */ + .ifne \putc + adrp x1, console_\_driver\()_putc + add x1, x1, :lo12:console_\_driver\()_putc + str x1, [x0, #CONSOLE_T_PUTC] + .else + str xzr, [x0, #CONSOLE_T_PUTC] + .endif + + .ifne \getc + adrp x1, console_\_driver\()_getc + add x1, x1, :lo12:console_\_driver\()_getc + str x1, [x0, #CONSOLE_T_GETC] + .else + str xzr, [x0, #CONSOLE_T_GETC] + .endif + + .ifne \flush + adrp x1, console_\_driver\()_flush + add x1, x1, :lo12:console_\_driver\()_flush + str x1, [x0, #CONSOLE_T_FLUSH] + .else + str xzr, [x0, #CONSOLE_T_FLUSH] + .endif + + mov x1, #(CONSOLE_FLAG_BOOT | CONSOLE_FLAG_CRASH) + str x1, [x0, #CONSOLE_T_FLAGS] + b console_register + .endm + +#endif /* CONSOLE_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S b/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S new file mode 100644 index 0000000..7bf4806 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S @@ -0,0 +1,422 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EL2_COMMON_MACROS_S +#define EL2_COMMON_MACROS_S + +#include +#include +#include +#include + +#include + + /* + * Helper macro to initialise system registers at EL2. + */ + .macro el2_arch_init_common + + /* --------------------------------------------------------------------- + * SCTLR_EL2 has already been initialised - read current value before + * modifying. + * + * SCTLR_EL2.I: Enable the instruction cache. + * + * SCTLR_EL2.SA: Enable Stack Alignment check. A SP alignment fault + * exception is generated if a load or store instruction executed at + * EL2 uses the SP as the base address and the SP is not aligned to a + * 16-byte boundary. + * + * SCTLR_EL2.A: Enable Alignment fault checking. All instructions that + * load or store one or more registers have an alignment check that the + * address being accessed is aligned to the size of the data element(s) + * being accessed. + * --------------------------------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el2 + orr x0, x0, x1 + msr sctlr_el2, x0 + isb + + /* --------------------------------------------------------------------- + * Initialise HCR_EL2, setting all fields rather than relying on HW. + * All fields are architecturally UNKNOWN on reset. The following fields + * do not change during the TF lifetime. The remaining fields are set to + * zero here but are updated ahead of transitioning to a lower EL in the + * function cm_init_context_common(). + * + * HCR_EL2.TWE: Set to zero so that execution of WFE instructions at + * EL2, EL1 and EL0 are not trapped to EL2. + * + * HCR_EL2.TWI: Set to zero so that execution of WFI instructions at + * EL2, EL1 and EL0 are not trapped to EL2. + * + * HCR_EL2.HCD: Set to zero to enable HVC calls at EL1 and above, + * from both Security states and both Execution states. + * + * HCR_EL2.TEA: Set to one to route External Aborts and SError + * Interrupts to EL2 when executing at any EL. + * + * HCR_EL2.{API,APK}: For Armv8.3 pointer authentication feature, + * disable traps to EL2 when accessing key registers or using + * pointer authentication instructions from lower ELs. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((HCR_RESET_VAL | HCR_TEA_BIT) \ + & ~(HCR_TWE_BIT | HCR_TWI_BIT | HCR_HCD_BIT)) +#if CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers are saved during world + * switches, enable pointer authentication everywhere, as it is safe to + * do so. + */ + orr x0, x0, #(HCR_API_BIT | HCR_APK_BIT) +#endif /* CTX_INCLUDE_PAUTH_REGS */ + msr hcr_el2, x0 + + /* --------------------------------------------------------------------- + * Initialise MDCR_EL2, setting all fields rather than relying on + * hw. Some fields are architecturally UNKNOWN on reset. + * + * MDCR_EL2.TDOSA: Set to zero so that EL2 and EL2 System register + * access to the powerdown debug registers do not trap to EL2. + * + * MDCR_EL2.TDA: Set to zero to allow EL0, EL1 and EL2 access to the + * debug registers, other than those registers that are controlled by + * MDCR_EL2.TDOSA. + * + * MDCR_EL2.TPM: Set to zero so that EL0, EL1, and EL2 System + * register accesses to all Performance Monitors registers do not trap + * to EL2. + * + * MDCR_EL2.HPMD: Set to zero so that event counting by the program- + * mable counters PMEVCNTR_EL0 is prohibited in Secure state. If + * ARMv8.2 Debug is not implemented this bit does not have any effect + * on the counters unless there is support for the implementation + * defined authentication interface + * ExternalSecureNoninvasiveDebugEnabled(). + * --------------------------------------------------------------------- + */ + mov_imm x0, ((MDCR_EL2_RESET_VAL | \ + MDCR_SPD32(MDCR_SPD32_DISABLE)) \ + & ~(MDCR_EL2_HPMD | MDCR_TDOSA_BIT | \ + MDCR_TDA_BIT | MDCR_TPM_BIT)) + + msr mdcr_el2, x0 + + /* --------------------------------------------------------------------- + * Initialise PMCR_EL0 setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * PMCR_EL0.DP: Set to one so that the cycle counter, + * PMCCNTR_EL0 does not count when event counting is prohibited. + * + * PMCR_EL0.X: Set to zero to disable export of events. + * + * PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0 + * counts on every clock cycle. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_DP_BIT) & \ + ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT)) + + msr pmcr_el0, x0 + + /* --------------------------------------------------------------------- + * Enable External Aborts and SError Interrupts now that the exception + * vectors have been setup. + * --------------------------------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------------------------------- + * Initialise CPTR_EL2, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. + * + * CPTR_EL2.TCPAC: Set to zero so that any accesses to CPACR_EL1 do + * not trap to EL2. + * + * CPTR_EL2.TTA: Set to zero so that System register accesses to the + * trace registers do not trap to EL2. + * + * CPTR_EL2.TFP: Set to zero so that accesses to the V- or Z- registers + * by Advanced SIMD, floating-point or SVE instructions (if implemented) + * do not trap to EL2. + */ + + mov_imm x0, (CPTR_EL2_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) + msr cptr_el2, x0 + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL2 + */ + mrs x0, id_aa64pfr0_el1 + ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH + cmp x0, #ID_AA64PFR0_DIT_SUPPORTED + bne 1f + mov x0, #DIT_BIT + msr DIT, x0 +1: + .endm + +/* ----------------------------------------------------------------------------- + * This is the super set of actions that need to be performed during a cold boot + * or a warm boot in EL2. This code is shared by BL1 and BL31. + * + * This macro will always perform reset handling, architectural initialisations + * and stack setup. The rest of the actions are optional because they might not + * be needed, depending on the context in which this macro is called. This is + * why this macro is parameterised ; each parameter allows to enable/disable + * some actions. + * + * _init_sctlr: + * Whether the macro needs to initialise SCTLR_EL2, including configuring + * the endianness of data accesses. + * + * _warm_boot_mailbox: + * Whether the macro needs to detect the type of boot (cold/warm). The + * detection is based on the platform entrypoint address : if it is zero + * then it is a cold boot, otherwise it is a warm boot. In the latter case, + * this macro jumps on the platform entrypoint address. + * + * _secondary_cold_boot: + * Whether the macro needs to identify the CPU that is calling it: primary + * CPU or secondary CPU. The primary CPU will be allowed to carry on with + * the platform initialisations, while the secondaries will be put in a + * platform-specific state in the meantime. + * + * If the caller knows this macro will only be called by the primary CPU + * then this parameter can be defined to 0 to skip this step. + * + * _init_memory: + * Whether the macro needs to initialise the memory. + * + * _init_c_runtime: + * Whether the macro needs to initialise the C runtime environment. + * + * _exception_vectors: + * Address of the exception vectors to program in the VBAR_EL2 register. + * + * _pie_fixup_size: + * Size of memory region to fixup Global Descriptor Table (GDT). + * + * A non-zero value is expected when firmware needs GDT to be fixed-up. + * + * ----------------------------------------------------------------------------- + */ + .macro el2_entrypoint_common \ + _init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \ + _init_memory, _init_c_runtime, _exception_vectors, \ + _pie_fixup_size + + .if \_init_sctlr + /* ------------------------------------------------------------- + * This is the initialisation of SCTLR_EL2 and so must ensure + * that all fields are explicitly set rather than relying on hw. + * Some fields reset to an IMPLEMENTATION DEFINED value and + * others are architecturally UNKNOWN on reset. + * + * SCTLR.EE: Set the CPU endianness before doing anything that + * might involve memory reads or writes. Set to zero to select + * Little Endian. + * + * SCTLR_EL2.WXN: For the EL2 translation regime, this field can + * force all memory regions that are writeable to be treated as + * XN (Execute-never). Set to zero so that this control has no + * effect on memory access permissions. + * + * SCTLR_EL2.SA: Set to zero to disable Stack Alignment check. + * + * SCTLR_EL2.A: Set to zero to disable Alignment fault checking. + * + * SCTLR.DSSBS: Set to zero to disable speculation store bypass + * safe behaviour upon exception entry to EL2. + * ------------------------------------------------------------- + */ + mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \ + | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT)) + msr sctlr_el2, x0 + isb + .endif /* _init_sctlr */ + +#if DISABLE_MTPMU + bl mtpmu_disable +#endif + + .if \_warm_boot_mailbox + /* ------------------------------------------------------------- + * This code will be executed for both warm and cold resets. + * Now is the time to distinguish between the two. + * Query the platform entrypoint address and if it is not zero + * then it means it is a warm boot so jump to this address. + * ------------------------------------------------------------- + */ + bl plat_get_my_entrypoint + cbz x0, do_cold_boot + br x0 + + do_cold_boot: + .endif /* _warm_boot_mailbox */ + + .if \_pie_fixup_size +#if ENABLE_PIE + /* + * ------------------------------------------------------------ + * If PIE is enabled fixup the Global descriptor Table only + * once during primary core cold boot path. + * + * Compile time base address, required for fixup, is calculated + * using "pie_fixup" label present within first page. + * ------------------------------------------------------------ + */ + pie_fixup: + ldr x0, =pie_fixup + and x0, x0, #~(PAGE_SIZE_MASK) + mov_imm x1, \_pie_fixup_size + add x1, x1, x0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + .endif /* _pie_fixup_size */ + + /* --------------------------------------------------------------------- + * Set the exception vectors. + * --------------------------------------------------------------------- + */ + adr x0, \_exception_vectors + msr vbar_el2, x0 + isb + + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler + + el2_arch_init_common + + .if \_secondary_cold_boot + /* ------------------------------------------------------------- + * Check if this is a primary or secondary CPU cold boot. + * The primary CPU will set up the platform while the + * secondaries are placed in a platform-specific state until the + * primary CPU performs the necessary actions to bring them out + * of that state and allows entry into the OS. + * ------------------------------------------------------------- + */ + bl plat_is_my_cpu_primary + cbnz w0, do_primary_cold_boot + + /* This is a cold boot on a secondary CPU */ + bl plat_secondary_cold_boot_setup + /* plat_secondary_cold_boot_setup() is not supposed to return */ + bl el2_panic + do_primary_cold_boot: + .endif /* _secondary_cold_boot */ + + /* --------------------------------------------------------------------- + * Initialize memory now. Secondary CPU initialization won't get to this + * point. + * --------------------------------------------------------------------- + */ + + .if \_init_memory + bl platform_mem_init + .endif /* _init_memory */ + + /* --------------------------------------------------------------------- + * Init C runtime environment: + * - Zero-initialise the NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section (if any). + * - Relocate the data section from ROM to RAM, if required. + * --------------------------------------------------------------------- + */ + .if \_init_c_runtime + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + adrp x0, __DATA_RAM_START__ + add x0, x0, :lo12:__DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 + bl memcpy16 +#endif + .endif /* _init_c_runtime */ + + /* --------------------------------------------------------------------- + * Use SP_EL0 for the C runtime stack. + * --------------------------------------------------------------------- + */ + msr spsel, #0 + + /* --------------------------------------------------------------------- + * Allocate a stack whose memory will be marked as Normal-IS-WBWA when + * the MMU is enabled. There is no risk of reading stale stack memory + * after enabling the MMU as only the primary CPU is running at the + * moment. + * --------------------------------------------------------------------- + */ + bl plat_set_my_stack + +#if STACK_PROTECTOR_ENABLED + .if \_init_c_runtime + bl update_stack_protector_canary + .endif /* _init_c_runtime */ +#endif + .endm + + .macro apply_at_speculative_wa +#if ERRATA_SPECULATIVE_AT + /* + * Explicitly save x30 so as to free up a register and to enable + * branching and also, save x29 which will be used in the called + * function + */ + stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + bl save_and_update_ptw_el1_sys_regs + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] +#endif + .endm + + .macro restore_ptw_el1_sys_regs +#if ERRATA_SPECULATIVE_AT + /* ----------------------------------------------------------- + * In case of ERRATA_SPECULATIVE_AT, must follow below order + * to ensure that page table walk is not enabled until + * restoration of all EL1 system registers. TCR_EL1 register + * should be updated at the end which restores previous page + * table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB + * ensures that CPU does below steps in order. + * + * 1. Ensure all other system registers are written before + * updating SCTLR_EL1 using ISB. + * 2. Restore SCTLR_EL1 register. + * 3. Ensure SCTLR_EL1 written successfully using ISB. + * 4. Restore TCR_EL1 register. + * ----------------------------------------------------------- + */ + isb + ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1] + msr sctlr_el1, x28 + isb + msr tcr_el1, x29 +#endif + .endm + +#endif /* EL2_COMMON_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S b/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S new file mode 100644 index 0000000..de2b931 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S @@ -0,0 +1,570 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EL3_COMMON_MACROS_S +#define EL3_COMMON_MACROS_S + +#include +#include +#include +#include +#include + + /* + * Helper macro to initialise EL3 registers we care about. + */ + .macro el3_arch_init_common + /* --------------------------------------------------------------------- + * SCTLR_EL3 has already been initialised - read current value before + * modifying. + * + * SCTLR_EL3.I: Enable the instruction cache. + * + * SCTLR_EL3.SA: Enable Stack Alignment check. A SP alignment fault + * exception is generated if a load or store instruction executed at + * EL3 uses the SP as the base address and the SP is not aligned to a + * 16-byte boundary. + * + * SCTLR_EL3.A: Enable Alignment fault checking. All instructions that + * load or store one or more registers have an alignment check that the + * address being accessed is aligned to the size of the data element(s) + * being accessed. + * --------------------------------------------------------------------- + */ + mov x1, #(SCTLR_I_BIT | SCTLR_A_BIT | SCTLR_SA_BIT) + mrs x0, sctlr_el3 + orr x0, x0, x1 + msr sctlr_el3, x0 + isb + +#ifdef IMAGE_BL31 + /* --------------------------------------------------------------------- + * Initialise the per-cpu cache pointer to the CPU. + * This is done early to enable crash reporting to have access to crash + * stack. Since crash reporting depends on cpu_data to report the + * unhandled exception, not doing so can lead to recursive exceptions + * due to a NULL TPIDR_EL3. + * --------------------------------------------------------------------- + */ + bl init_cpu_data_ptr +#endif /* IMAGE_BL31 */ + + /* --------------------------------------------------------------------- + * Initialise SCR_EL3, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. The following fields + * do not change during the TF lifetime. The remaining fields are set to + * zero here but are updated ahead of transitioning to a lower EL in the + * function cm_init_context_common(). + * + * SCR_EL3.TWE: Set to zero so that execution of WFE instructions at + * EL2, EL1 and EL0 are not trapped to EL3. + * + * SCR_EL3.TWI: Set to zero so that execution of WFI instructions at + * EL2, EL1 and EL0 are not trapped to EL3. + * + * SCR_EL3.SIF: Set to one to disable instruction fetches from + * Non-secure memory. + * + * SCR_EL3.SMD: Set to zero to enable SMC calls at EL1 and above, from + * both Security states and both Execution states. + * + * SCR_EL3.EA: Set to one to route External Aborts and SError Interrupts + * to EL3 when executing at any EL. + * + * SCR_EL3.{API,APK}: For Armv8.3 pointer authentication feature, + * disable traps to EL3 when accessing key registers or using pointer + * authentication instructions from lower ELs. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((SCR_RESET_VAL | SCR_EA_BIT | SCR_SIF_BIT) \ + & ~(SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT)) +#if CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers are saved during world + * switches, enable pointer authentication everywhere, as it is safe to + * do so. + */ + orr x0, x0, #(SCR_API_BIT | SCR_APK_BIT) +#endif +#if ENABLE_RME + /* + * TODO: Settting the EEL2 bit to allow EL3 access to secure only registers + * in context management. This will need to be refactored. + */ + orr x0, x0, #SCR_EEL2_BIT +#endif + msr scr_el3, x0 + + /* --------------------------------------------------------------------- + * Initialise MDCR_EL3, setting all fields rather than relying on hw. + * Some fields are architecturally UNKNOWN on reset. + * + * MDCR_EL3.SDD: Set to one to disable AArch64 Secure self-hosted debug. + * Debug exceptions, other than Breakpoint Instruction exceptions, are + * disabled from all ELs in Secure state. + * + * MDCR_EL3.SPD32: Set to 0b10 to disable AArch32 Secure self-hosted + * privileged debug from S-EL1. + * + * MDCR_EL3.TDOSA: Set to zero so that EL2 and EL2 System register + * access to the powerdown debug registers do not trap to EL3. + * + * MDCR_EL3.TDA: Set to zero to allow EL0, EL1 and EL2 access to the + * debug registers, other than those registers that are controlled by + * MDCR_EL3.TDOSA. + * + * MDCR_EL3.TPM: Set to zero so that EL0, EL1, and EL2 System register + * accesses to all Performance Monitors registers do not trap to EL3. + * + * MDCR_EL3.SCCD: Set to one so that cycle counting by PMCCNTR_EL0 is + * prohibited in Secure state. This bit is RES0 in versions of the + * architecture with FEAT_PMUv3p5 not implemented, setting it to 1 + * doesn't have any effect on them. + * + * MDCR_EL3.MCCD: Set to one so that cycle counting by PMCCNTR_EL0 is + * prohibited in EL3. This bit is RES0 in versions of the + * architecture with FEAT_PMUv3p7 not implemented, setting it to 1 + * doesn't have any effect on them. + * + * MDCR_EL3.SPME: Set to zero so that event counting by the programmable + * counters PMEVCNTR_EL0 is prohibited in Secure state. If ARMv8.2 + * Debug is not implemented this bit does not have any effect on the + * counters unless there is support for the implementation defined + * authentication interface ExternalSecureNoninvasiveDebugEnabled(). + * + * MDCR_EL3.NSTB, MDCR_EL3.NSTBE: Set to zero so that Trace Buffer + * owning security state is Secure state. If FEAT_TRBE is implemented, + * accesses to Trace Buffer control registers at EL2 and EL1 in any + * security state generates trap exceptions to EL3. + * If FEAT_TRBE is not implemented, these bits are RES0. + * + * MDCR_EL3.TTRF: Set to one so that access to trace filter control + * registers in non-monitor mode generate EL3 trap exception, + * unless the access generates a higher priority exception when trace + * filter control(FEAT_TRF) is implemented. + * When FEAT_TRF is not implemented, this bit is RES0. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((MDCR_EL3_RESET_VAL | MDCR_SDD_BIT | \ + MDCR_SPD32(MDCR_SPD32_DISABLE) | MDCR_SCCD_BIT | \ + MDCR_MCCD_BIT) & ~(MDCR_SPME_BIT | MDCR_TDOSA_BIT | \ + MDCR_TDA_BIT | MDCR_TPM_BIT | MDCR_NSTB(MDCR_NSTB_EL1) | \ + MDCR_NSTBE | MDCR_TTRF_BIT)) + + mrs x1, id_aa64dfr0_el1 + ubfx x1, x1, #ID_AA64DFR0_TRACEFILT_SHIFT, #ID_AA64DFR0_TRACEFILT_LENGTH + cbz x1, 1f + orr x0, x0, #MDCR_TTRF_BIT +1: + msr mdcr_el3, x0 + + /* --------------------------------------------------------------------- + * Initialise PMCR_EL0 setting all fields rather than relying + * on hw. Some fields are architecturally UNKNOWN on reset. + * + * PMCR_EL0.LP: Set to one so that event counter overflow, that + * is recorded in PMOVSCLR_EL0[0-30], occurs on the increment + * that changes PMEVCNTR_EL0[63] from 1 to 0, when ARMv8.5-PMU + * is implemented. This bit is RES0 in versions of the architecture + * earlier than ARMv8.5, setting it to 1 doesn't have any effect + * on them. + * + * PMCR_EL0.LC: Set to one so that cycle counter overflow, that + * is recorded in PMOVSCLR_EL0[31], occurs on the increment + * that changes PMCCNTR_EL0[63] from 1 to 0. + * + * PMCR_EL0.DP: Set to one so that the cycle counter, + * PMCCNTR_EL0 does not count when event counting is prohibited. + * + * PMCR_EL0.X: Set to zero to disable export of events. + * + * PMCR_EL0.D: Set to zero so that, when enabled, PMCCNTR_EL0 + * counts on every clock cycle. + * --------------------------------------------------------------------- + */ + mov_imm x0, ((PMCR_EL0_RESET_VAL | PMCR_EL0_LP_BIT | \ + PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT) & \ + ~(PMCR_EL0_X_BIT | PMCR_EL0_D_BIT)) + + msr pmcr_el0, x0 + + /* --------------------------------------------------------------------- + * Enable External Aborts and SError Interrupts now that the exception + * vectors have been setup. + * --------------------------------------------------------------------- + */ + msr daifclr, #DAIF_ABT_BIT + + /* --------------------------------------------------------------------- + * Initialise CPTR_EL3, setting all fields rather than relying on hw. + * All fields are architecturally UNKNOWN on reset. + * + * CPTR_EL3.TCPAC: Set to zero so that any accesses to CPACR_EL1, + * CPTR_EL2, CPACR, or HCPTR do not trap to EL3. + * + * CPTR_EL3.TTA: Set to one so that accesses to the trace system + * registers trap to EL3 from all exception levels and security + * states when system register trace is implemented. + * When system register trace is not implemented, this bit is RES0 and + * hence set to zero. + * + * CPTR_EL3.TTA: Set to zero so that System register accesses to the + * trace registers do not trap to EL3. + * + * CPTR_EL3.TFP: Set to zero so that accesses to the V- or Z- registers + * by Advanced SIMD, floating-point or SVE instructions (if implemented) + * do not trap to EL3. + * + * CPTR_EL3.TAM: Set to one so that Activity Monitor access is + * trapped to EL3 by default. + * + * CPTR_EL3.EZ: Set to zero so that all SVE functionality is trapped + * to EL3 by default. + * + * CPTR_EL3.ESM: Set to zero so that all SME functionality is trapped + * to EL3 by default. + */ + + mov_imm x0, (CPTR_EL3_RESET_VAL & ~(TCPAC_BIT | TTA_BIT | TFP_BIT)) + mrs x1, id_aa64dfr0_el1 + ubfx x1, x1, #ID_AA64DFR0_TRACEVER_SHIFT, #ID_AA64DFR0_TRACEVER_LENGTH + cbz x1, 1f + orr x0, x0, #TTA_BIT +1: + msr cptr_el3, x0 + + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3. + * First assert that the FEAT_DIT build flag matches the feature id + * register value for DIT. + */ +#if ENABLE_FEAT_DIT +#if ENABLE_ASSERTIONS + mrs x0, id_aa64pfr0_el1 + ubfx x0, x0, #ID_AA64PFR0_DIT_SHIFT, #ID_AA64PFR0_DIT_LENGTH + cmp x0, #ID_AA64PFR0_DIT_SUPPORTED + ASM_ASSERT(eq) +#endif /* ENABLE_ASSERTIONS */ + mov x0, #DIT_BIT + msr DIT, x0 +#endif + .endm + +/* ----------------------------------------------------------------------------- + * This is the super set of actions that need to be performed during a cold boot + * or a warm boot in EL3. This code is shared by BL1 and BL31. + * + * This macro will always perform reset handling, architectural initialisations + * and stack setup. The rest of the actions are optional because they might not + * be needed, depending on the context in which this macro is called. This is + * why this macro is parameterised ; each parameter allows to enable/disable + * some actions. + * + * _init_sctlr: + * Whether the macro needs to initialise SCTLR_EL3, including configuring + * the endianness of data accesses. + * + * _warm_boot_mailbox: + * Whether the macro needs to detect the type of boot (cold/warm). The + * detection is based on the platform entrypoint address : if it is zero + * then it is a cold boot, otherwise it is a warm boot. In the latter case, + * this macro jumps on the platform entrypoint address. + * + * _secondary_cold_boot: + * Whether the macro needs to identify the CPU that is calling it: primary + * CPU or secondary CPU. The primary CPU will be allowed to carry on with + * the platform initialisations, while the secondaries will be put in a + * platform-specific state in the meantime. + * + * If the caller knows this macro will only be called by the primary CPU + * then this parameter can be defined to 0 to skip this step. + * + * _init_memory: + * Whether the macro needs to initialise the memory. + * + * _init_c_runtime: + * Whether the macro needs to initialise the C runtime environment. + * + * _exception_vectors: + * Address of the exception vectors to program in the VBAR_EL3 register. + * + * _pie_fixup_size: + * Size of memory region to fixup Global Descriptor Table (GDT). + * + * A non-zero value is expected when firmware needs GDT to be fixed-up. + * + * ----------------------------------------------------------------------------- + */ + .macro el3_entrypoint_common \ + _init_sctlr, _warm_boot_mailbox, _secondary_cold_boot, \ + _init_memory, _init_c_runtime, _exception_vectors, \ + _pie_fixup_size + + .if \_init_sctlr + /* ------------------------------------------------------------- + * This is the initialisation of SCTLR_EL3 and so must ensure + * that all fields are explicitly set rather than relying on hw. + * Some fields reset to an IMPLEMENTATION DEFINED value and + * others are architecturally UNKNOWN on reset. + * + * SCTLR.EE: Set the CPU endianness before doing anything that + * might involve memory reads or writes. Set to zero to select + * Little Endian. + * + * SCTLR_EL3.WXN: For the EL3 translation regime, this field can + * force all memory regions that are writeable to be treated as + * XN (Execute-never). Set to zero so that this control has no + * effect on memory access permissions. + * + * SCTLR_EL3.SA: Set to zero to disable Stack Alignment check. + * + * SCTLR_EL3.A: Set to zero to disable Alignment fault checking. + * + * SCTLR.DSSBS: Set to zero to disable speculation store bypass + * safe behaviour upon exception entry to EL3. + * ------------------------------------------------------------- + */ + mov_imm x0, (SCTLR_RESET_VAL & ~(SCTLR_EE_BIT | SCTLR_WXN_BIT \ + | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT)) + msr sctlr_el3, x0 + isb + .endif /* _init_sctlr */ + +#if DISABLE_MTPMU + bl mtpmu_disable +#endif + + .if \_warm_boot_mailbox + /* ------------------------------------------------------------- + * This code will be executed for both warm and cold resets. + * Now is the time to distinguish between the two. + * Query the platform entrypoint address and if it is not zero + * then it means it is a warm boot so jump to this address. + * ------------------------------------------------------------- + */ + bl plat_get_my_entrypoint + cbz x0, do_cold_boot + br x0 + + do_cold_boot: + .endif /* _warm_boot_mailbox */ + + .if \_pie_fixup_size +#if ENABLE_PIE + /* + * ------------------------------------------------------------ + * If PIE is enabled fixup the Global descriptor Table only + * once during primary core cold boot path. + * + * Compile time base address, required for fixup, is calculated + * using "pie_fixup" label present within first page. + * ------------------------------------------------------------ + */ + pie_fixup: + ldr x0, =pie_fixup + and x0, x0, #~(PAGE_SIZE_MASK) + mov_imm x1, \_pie_fixup_size + add x1, x1, x0 + bl fixup_gdt_reloc +#endif /* ENABLE_PIE */ + .endif /* _pie_fixup_size */ + + /* --------------------------------------------------------------------- + * Set the exception vectors. + * --------------------------------------------------------------------- + */ + adr x0, \_exception_vectors + msr vbar_el3, x0 + isb + +#if !(defined(IMAGE_BL2) && ENABLE_RME) + /* --------------------------------------------------------------------- + * It is a cold boot. + * Perform any processor specific actions upon reset e.g. cache, TLB + * invalidations etc. + * --------------------------------------------------------------------- + */ + bl reset_handler +#endif + + el3_arch_init_common + + .if \_secondary_cold_boot + /* ------------------------------------------------------------- + * Check if this is a primary or secondary CPU cold boot. + * The primary CPU will set up the platform while the + * secondaries are placed in a platform-specific state until the + * primary CPU performs the necessary actions to bring them out + * of that state and allows entry into the OS. + * ------------------------------------------------------------- + */ + bl plat_is_my_cpu_primary + cbnz w0, do_primary_cold_boot + + /* This is a cold boot on a secondary CPU */ + bl plat_secondary_cold_boot_setup + /* plat_secondary_cold_boot_setup() is not supposed to return */ + bl el3_panic + + do_primary_cold_boot: + .endif /* _secondary_cold_boot */ + + /* --------------------------------------------------------------------- + * Initialize memory now. Secondary CPU initialization won't get to this + * point. + * --------------------------------------------------------------------- + */ + + .if \_init_memory + bl platform_mem_init + .endif /* _init_memory */ + + /* --------------------------------------------------------------------- + * Init C runtime environment: + * - Zero-initialise the NOBITS sections. There are 2 of them: + * - the .bss section; + * - the coherent memory section (if any). + * - Relocate the data section from ROM to RAM, if required. + * --------------------------------------------------------------------- + */ + .if \_init_c_runtime +#if defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \ + ((BL2_AT_EL3 && BL2_INV_DCACHE) || ENABLE_RME)) + /* ------------------------------------------------------------- + * Invalidate the RW memory used by the BL31 image. This + * includes the data and NOBITS sections. This is done to + * safeguard against possible corruption of this memory by + * dirty cache lines in a system cache as a result of use by + * an earlier boot loader stage. If PIE is enabled however, + * RO sections including the GOT may be modified during + * pie fixup. Therefore, to be on the safe side, invalidate + * the entire image region if PIE is enabled. + * ------------------------------------------------------------- + */ +#if ENABLE_PIE +#if SEPARATE_CODE_AND_RODATA + adrp x0, __TEXT_START__ + add x0, x0, :lo12:__TEXT_START__ +#else + adrp x0, __RO_START__ + add x0, x0, :lo12:__RO_START__ +#endif /* SEPARATE_CODE_AND_RODATA */ +#else + adrp x0, __RW_START__ + add x0, x0, :lo12:__RW_START__ +#endif /* ENABLE_PIE */ + adrp x1, __RW_END__ + add x1, x1, :lo12:__RW_END__ + sub x1, x1, x0 + bl inv_dcache_range +#if defined(IMAGE_BL31) && SEPARATE_NOBITS_REGION + adrp x0, __NOBITS_START__ + add x0, x0, :lo12:__NOBITS_START__ + adrp x1, __NOBITS_END__ + add x1, x1, :lo12:__NOBITS_END__ + sub x1, x1, x0 + bl inv_dcache_range +#endif +#if defined(IMAGE_BL2) && SEPARATE_BL2_NOLOAD_REGION + adrp x0, __BL2_NOLOAD_START__ + add x0, x0, :lo12:__BL2_NOLOAD_START__ + adrp x1, __BL2_NOLOAD_END__ + add x1, x1, :lo12:__BL2_NOLOAD_END__ + sub x1, x1, x0 + bl inv_dcache_range +#endif +#endif + adrp x0, __BSS_START__ + add x0, x0, :lo12:__BSS_START__ + + adrp x1, __BSS_END__ + add x1, x1, :lo12:__BSS_END__ + sub x1, x1, x0 + bl zeromem + +#if USE_COHERENT_MEM + adrp x0, __COHERENT_RAM_START__ + add x0, x0, :lo12:__COHERENT_RAM_START__ + adrp x1, __COHERENT_RAM_END_UNALIGNED__ + add x1, x1, :lo12: __COHERENT_RAM_END_UNALIGNED__ + sub x1, x1, x0 + bl zeromem +#endif + +#if defined(IMAGE_BL1) || (defined(IMAGE_BL2) && BL2_AT_EL3 && BL2_IN_XIP_MEM) + adrp x0, __DATA_RAM_START__ + add x0, x0, :lo12:__DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 + bl memcpy16 +#endif + .endif /* _init_c_runtime */ + + /* --------------------------------------------------------------------- + * Use SP_EL0 for the C runtime stack. + * --------------------------------------------------------------------- + */ + msr spsel, #0 + + /* --------------------------------------------------------------------- + * Allocate a stack whose memory will be marked as Normal-IS-WBWA when + * the MMU is enabled. There is no risk of reading stale stack memory + * after enabling the MMU as only the primary CPU is running at the + * moment. + * --------------------------------------------------------------------- + */ + bl plat_set_my_stack + +#if STACK_PROTECTOR_ENABLED + .if \_init_c_runtime + bl update_stack_protector_canary + .endif /* _init_c_runtime */ +#endif + .endm + + .macro apply_at_speculative_wa +#if ERRATA_SPECULATIVE_AT + /* + * Explicitly save x30 so as to free up a register and to enable + * branching and also, save x29 which will be used in the called + * function + */ + stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + bl save_and_update_ptw_el1_sys_regs + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] +#endif + .endm + + .macro restore_ptw_el1_sys_regs +#if ERRATA_SPECULATIVE_AT + /* ----------------------------------------------------------- + * In case of ERRATA_SPECULATIVE_AT, must follow below order + * to ensure that page table walk is not enabled until + * restoration of all EL1 system registers. TCR_EL1 register + * should be updated at the end which restores previous page + * table walk setting of stage1 i.e.(TCR_EL1.EPDx) bits. ISB + * ensures that CPU does below steps in order. + * + * 1. Ensure all other system registers are written before + * updating SCTLR_EL1 using ISB. + * 2. Restore SCTLR_EL1 register. + * 3. Ensure SCTLR_EL1 written successfully using ISB. + * 4. Restore TCR_EL1 register. + * ----------------------------------------------------------- + */ + isb + ldp x28, x29, [sp, #CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1] + msr sctlr_el1, x28 + isb + msr tcr_el1, x29 +#endif + .endm + +#endif /* EL3_COMMON_MACROS_S */ diff --git a/arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h b/arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h new file mode 100644 index 0000000..fac6fd9 --- /dev/null +++ b/arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_HELPERS_H +#define SMCCC_HELPERS_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* Convenience macros to return from SMC handler */ +#define SMC_RET0(_h) { \ + return (uint64_t) (_h); \ +} +#define SMC_RET1(_h, _x0) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X0), (_x0)); \ + SMC_RET0(_h); \ +} +#define SMC_RET2(_h, _x0, _x1) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X1), (_x1)); \ + SMC_RET1(_h, (_x0)); \ +} +#define SMC_RET3(_h, _x0, _x1, _x2) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X2), (_x2)); \ + SMC_RET2(_h, (_x0), (_x1)); \ +} +#define SMC_RET4(_h, _x0, _x1, _x2, _x3) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X3), (_x3)); \ + SMC_RET3(_h, (_x0), (_x1), (_x2)); \ +} +#define SMC_RET5(_h, _x0, _x1, _x2, _x3, _x4) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X4), (_x4)); \ + SMC_RET4(_h, (_x0), (_x1), (_x2), (_x3)); \ +} +#define SMC_RET6(_h, _x0, _x1, _x2, _x3, _x4, _x5) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X5), (_x5)); \ + SMC_RET5(_h, (_x0), (_x1), (_x2), (_x3), (_x4)); \ +} +#define SMC_RET7(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X6), (_x6)); \ + SMC_RET6(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5)); \ +} +#define SMC_RET8(_h, _x0, _x1, _x2, _x3, _x4, _x5, _x6, _x7) { \ + write_ctx_reg((get_gpregs_ctx(_h)), (CTX_GPREG_X7), (_x7)); \ + SMC_RET7(_h, (_x0), (_x1), (_x2), (_x3), (_x4), (_x5), (_x6)); \ +} + +/* + * Convenience macros to access general purpose registers using handle provided + * to SMC handler. These take the offset values defined in context.h + */ +#define SMC_GET_GP(_h, _g) \ + read_ctx_reg((get_gpregs_ctx(_h)), (_g)) +#define SMC_SET_GP(_h, _g, _v) \ + write_ctx_reg((get_gpregs_ctx(_h)), (_g), (_v)) + +/* + * Convenience macros to access EL3 context registers using handle provided to + * SMC handler. These take the offset values defined in context.h + */ +#define SMC_GET_EL3(_h, _e) \ + read_ctx_reg((get_el3state_ctx(_h)), (_e)) +#define SMC_SET_EL3(_h, _e, _v) \ + write_ctx_reg((get_el3state_ctx(_h)), (_e), (_v)) + +/* + * Helper macro to retrieve the SMC parameters from cpu_context_t. + */ +#define get_smc_params_from_ctx(_hdl, _x1, _x2, _x3, _x4) \ + do { \ + const gp_regs_t *regs = get_gpregs_ctx(_hdl); \ + _x1 = read_ctx_reg(regs, CTX_GPREG_X1); \ + _x2 = read_ctx_reg(regs, CTX_GPREG_X2); \ + _x3 = read_ctx_reg(regs, CTX_GPREG_X3); \ + _x4 = read_ctx_reg(regs, CTX_GPREG_X4); \ + } while (false) + +#endif /*__ASSEMBLER__*/ + +#endif /* SMCCC_HELPERS_H */ diff --git a/arm-trusted-firmware/include/bl1/bl1.h b/arm-trusted-firmware/include/bl1/bl1.h new file mode 100644 index 0000000..21d3ae7 --- /dev/null +++ b/arm-trusted-firmware/include/bl1/bl1.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL1_H +#define BL1_H + +#include + +/* + * Defines for BL1 SMC function ids. + */ +#define BL1_SMC_CALL_COUNT 0x0 +#define BL1_SMC_UID 0x1 +/* SMC #0x2 reserved */ +#define BL1_SMC_VERSION 0x3 + +/* + * Corresponds to the function ID of the SMC that + * the BL1 exception handler service to execute BL31. + */ +#define BL1_SMC_RUN_IMAGE 0x4 + +/* + * BL1 SMC version + */ +#define BL1_SMC_MAJOR_VER UL(0x0) +#define BL1_SMC_MINOR_VER UL(0x1) + +/* + * Defines for FWU SMC function ids. + */ + +#define FWU_SMC_IMAGE_COPY 0x10 +#define FWU_SMC_IMAGE_AUTH 0x11 +#define FWU_SMC_IMAGE_EXECUTE 0x12 +#define FWU_SMC_IMAGE_RESUME 0x13 +#define FWU_SMC_SEC_IMAGE_DONE 0x14 +#define FWU_SMC_UPDATE_DONE 0x15 +#define FWU_SMC_IMAGE_RESET 0x16 + +/* + * Number of FWU calls (above) implemented + */ +#define FWU_NUM_SMC_CALLS 7 + +#if TRUSTED_BOARD_BOOT +# define BL1_NUM_SMC_CALLS (FWU_NUM_SMC_CALLS + 4) +#else +# define BL1_NUM_SMC_CALLS 4 +#endif + +/* + * The macros below are used to identify FWU + * calls from the SMC function ID + */ +#define FWU_SMC_FID_START FWU_SMC_IMAGE_COPY +#define FWU_SMC_FID_END FWU_SMC_IMAGE_RESET +#define is_fwu_fid(_fid) \ + ((_fid >= FWU_SMC_FID_START) && (_fid <= FWU_SMC_FID_END)) + +#ifndef __ASSEMBLER__ + +#include + +struct entry_point_info; + +u_register_t bl1_smc_wrapper(uint32_t smc_fid, + void *cookie, + void *handle, + unsigned int flags); + +u_register_t bl1_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, + unsigned int flags); + +void bl1_print_next_bl_ep_info(const struct entry_point_info *bl_ep_info); + +void bl1_setup(void); +void bl1_main(void); +void bl1_plat_prepare_exit(entry_point_info_t *ep_info); + +/* + * Check if the total number of FWU SMC calls are as expected. + */ +CASSERT(FWU_NUM_SMC_CALLS == \ + (FWU_SMC_FID_END - FWU_SMC_FID_START + 1),\ + assert_FWU_NUM_SMC_CALLS_mismatch); + +/* Utility functions */ +void bl1_calc_bl2_mem_layout(const meminfo_t *bl1_mem_layout, + meminfo_t *bl2_mem_layout); + +#endif /* __ASSEMBLER__ */ +#endif /* BL1_H */ diff --git a/arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h b/arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h new file mode 100644 index 0000000..db15cdb --- /dev/null +++ b/arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_IMG_DESC_H +#define TBBR_IMG_DESC_H + +#include + +extern image_desc_t bl1_tbbr_image_descs[]; + +#endif /* TBBR_IMG_DESC_H */ diff --git a/arm-trusted-firmware/include/bl2/bl2.h b/arm-trusted-firmware/include/bl2/bl2.h new file mode 100644 index 0000000..73f5ac7 --- /dev/null +++ b/arm-trusted-firmware/include/bl2/bl2.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2_H +#define BL2_H + +#include + +void bl2_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl2_el3_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl2_main(void); + +#endif /* BL2_H */ diff --git a/arm-trusted-firmware/include/bl2u/bl2u.h b/arm-trusted-firmware/include/bl2u/bl2u.h new file mode 100644 index 0000000..387eaf8 --- /dev/null +++ b/arm-trusted-firmware/include/bl2u/bl2u.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL2U_H +#define BL2U_H + +void bl2u_main(void); + +#endif /* BL2U_H */ diff --git a/arm-trusted-firmware/include/bl31/bl31.h b/arm-trusted-firmware/include/bl31/bl31.h new file mode 100644 index 0000000..1d58ef9 --- /dev/null +++ b/arm-trusted-firmware/include/bl31/bl31.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL31_H +#define BL31_H + +#include + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void bl31_setup(u_register_t arg0, u_register_t arg1, u_register_t arg2, + u_register_t arg3); +void bl31_next_el_arch_setup(uint32_t security_state); +void bl31_set_next_image_type(uint32_t security_state); +uint32_t bl31_get_next_image_type(void); +void bl31_prepare_next_image_entry(void); +void bl31_register_bl32_init(int32_t (*func)(void)); +void bl31_register_rmm_init(int32_t (*func)(void)); +void bl31_warm_entrypoint(void); +void bl31_main(void); +void bl31_lib_init(void); + +#endif /* BL31_H */ diff --git a/arm-trusted-firmware/include/bl31/ea_handle.h b/arm-trusted-firmware/include/bl31/ea_handle.h new file mode 100644 index 0000000..68f012c --- /dev/null +++ b/arm-trusted-firmware/include/bl31/ea_handle.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EA_HANDLE_H +#define EA_HANDLE_H + +/* Constants indicating the reason for an External Abort */ + +/* External Abort received at SError vector */ +#define ERROR_EA_ASYNC 0 + +/* Synchronous External Abort received at Synchronous exception vector */ +#define ERROR_EA_SYNC 1 + +/* External Abort synchronized by ESB instruction */ +#define ERROR_EA_ESB 2 + +/* RAS event signalled as peripheral interrupt */ +#define ERROR_INTERRUPT 3 + +#endif /* EA_HANDLE_H */ diff --git a/arm-trusted-firmware/include/bl31/ehf.h b/arm-trusted-firmware/include/bl31/ehf.h new file mode 100644 index 0000000..c13d28c --- /dev/null +++ b/arm-trusted-firmware/include/bl31/ehf.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EHF_H +#define EHF_H + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +/* Valid priorities set bit 0 of the priority handler. */ +#define EHF_PRI_VALID_ BIT(0) + +/* Marker for no handler registered for a valid priority */ +#define EHF_NO_HANDLER_ (0U | EHF_PRI_VALID_) + +/* Extract the specified number of top bits from 7 lower bits of priority */ +#define EHF_PRI_TO_IDX(pri, plat_bits) \ + ((((unsigned) (pri)) & 0x7fu) >> (7u - (plat_bits))) + +/* Install exception priority descriptor at a suitable index */ +#define EHF_PRI_DESC(plat_bits, priority) \ + [EHF_PRI_TO_IDX(priority, plat_bits)] = { \ + .ehf_handler = EHF_NO_HANDLER_, \ + } + +/* Macro for platforms to regiter its exception priorities */ +#define EHF_REGISTER_PRIORITIES(priorities, num, bits) \ + const ehf_priorities_t exception_data = { \ + .num_priorities = (num), \ + .ehf_priorities = (priorities), \ + .pri_bits = (bits), \ + } + +/* + * Priority stack, managed as a bitmap. + * + * Currently only supports 32 priority levels, allowing platforms to use up to 5 + * top bits of priority. But the type can be changed to uint64_t should need + * arise to support 64 priority levels, allowing platforms to use up to 6 top + * bits of priority. + */ +typedef uint32_t ehf_pri_bits_t; + +/* + * Per-PE exception data. The data for each PE is kept as a per-CPU data field. + * See cpu_data.h. + */ +typedef struct { + ehf_pri_bits_t active_pri_bits; + + /* Priority mask value before any priority levels were active */ + uint8_t init_pri_mask; + + /* Non-secure priority mask value stashed during Secure execution */ + uint8_t ns_pri_mask; +} __aligned(sizeof(uint64_t)) pe_exc_data_t; + +typedef int (*ehf_handler_t)(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); + +typedef struct ehf_pri_desc { + /* + * 4-byte-aligned exception handler. Bit 0 indicates the corresponding + * priority level is valid. This is effectively of ehf_handler_t type, + * but left as uintptr_t in order to make pointer arithmetic convenient. + */ + uintptr_t ehf_handler; +} ehf_pri_desc_t; + +typedef struct ehf_priority_type { + ehf_pri_desc_t *ehf_priorities; + unsigned int num_priorities; + unsigned int pri_bits; +} ehf_priorities_t; + +void ehf_init(void); +void ehf_activate_priority(unsigned int priority); +void ehf_deactivate_priority(unsigned int priority); +void ehf_register_priority_handler(unsigned int pri, ehf_handler_t handler); +void ehf_allow_ns_preemption(uint64_t preempt_ret_code); +unsigned int ehf_is_ns_preemption_allowed(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* EHF_H */ diff --git a/arm-trusted-firmware/include/bl31/interrupt_mgmt.h b/arm-trusted-firmware/include/bl31/interrupt_mgmt.h new file mode 100644 index 0000000..935bf77 --- /dev/null +++ b/arm-trusted-firmware/include/bl31/interrupt_mgmt.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERRUPT_MGMT_H +#define INTERRUPT_MGMT_H + +#include +#include + +/******************************************************************************* + * Constants for the types of interrupts recognised by the IM framework + ******************************************************************************/ +#define INTR_TYPE_S_EL1 U(0) +#define INTR_TYPE_EL3 U(1) +#define INTR_TYPE_NS U(2) +#define MAX_INTR_TYPES U(3) +#define INTR_TYPE_INVAL MAX_INTR_TYPES + +/* Interrupt routing modes */ +#define INTR_ROUTING_MODE_PE 0 +#define INTR_ROUTING_MODE_ANY 1 + +/* + * Constant passed to the interrupt handler in the 'id' field when the + * framework does not read the gic registers to determine the interrupt id. + */ +#define INTR_ID_UNAVAILABLE U(0xFFFFFFFF) + + +/******************************************************************************* + * Mask for _both_ the routing model bits in the 'flags' parameter and + * constants to define the valid routing models for each supported interrupt + * type + ******************************************************************************/ +#define INTR_RM_FLAGS_SHIFT U(0x0) +#define INTR_RM_FLAGS_MASK U(0x3) +/* Routed to EL3 from NS. Taken to S-EL1 from Secure */ +#define INTR_SEL1_VALID_RM0 U(0x2) +/* Routed to EL3 from NS and Secure */ +#define INTR_SEL1_VALID_RM1 U(0x3) +/* Routed to EL1/EL2 from NS and to S-EL1 from Secure */ +#define INTR_NS_VALID_RM0 U(0x0) +/* Routed to EL1/EL2 from NS and to EL3 from Secure */ +#define INTR_NS_VALID_RM1 U(0x1) +/* Routed to EL3 from NS. Taken to S-EL1 from Secure and handed over to EL3 */ +#define INTR_EL3_VALID_RM0 U(0x2) +/* Routed to EL3 from NS and Secure */ +#define INTR_EL3_VALID_RM1 U(0x3) +/* This is the default routing model */ +#define INTR_DEFAULT_RM U(0x0) + +/******************************************************************************* + * Constants for the _individual_ routing model bits in the 'flags' field for + * each interrupt type and mask to validate the 'flags' parameter while + * registering an interrupt handler + ******************************************************************************/ +#define INTR_TYPE_FLAGS_MASK U(0xFFFFFFFC) + +#define INTR_RM_FROM_SEC_SHIFT SECURE /* BIT[0] */ +#define INTR_RM_FROM_NS_SHIFT NON_SECURE /* BIT[1] */ +#define INTR_RM_FROM_FLAG_MASK U(1) +#define get_interrupt_rm_flag(flag, ss) \ + ((((flag) >> INTR_RM_FLAGS_SHIFT) >> (ss)) & INTR_RM_FROM_FLAG_MASK) +#define set_interrupt_rm_flag(flag, ss) ((flag) |= U(1) << (ss)) +#define clr_interrupt_rm_flag(flag, ss) ((flag) &= ~(U(1) << (ss))) + +/******************************************************************************* + * Macros to set the 'flags' parameter passed to an interrupt type handler. Only + * the flag to indicate the security state when the exception was generated is + * supported. + ******************************************************************************/ +#define INTR_SRC_SS_FLAG_SHIFT U(0) /* BIT[0] */ +#define INTR_SRC_SS_FLAG_MASK U(1) +#define set_interrupt_src_ss(flag, val) ((flag) |= (val) << INTR_SRC_SS_FLAG_SHIFT) +#define clr_interrupt_src_ss(flag) ((flag) &= ~(U(1) << INTR_SRC_SS_FLAG_SHIFT)) +#define get_interrupt_src_ss(flag) (((flag) >> INTR_SRC_SS_FLAG_SHIFT) & \ + INTR_SRC_SS_FLAG_MASK) + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Helpers to validate the routing model bits in the 'flags' for a type + * of interrupt. If the model does not match one of the valid masks + * -EINVAL is returned. + ******************************************************************************/ +static inline int32_t validate_sel1_interrupt_rm(uint32_t x) +{ + if ((x == INTR_SEL1_VALID_RM0) || (x == INTR_SEL1_VALID_RM1)) + return 0; + + return -EINVAL; +} + +static inline int32_t validate_ns_interrupt_rm(uint32_t x) +{ + if ((x == INTR_NS_VALID_RM0) || (x == INTR_NS_VALID_RM1)) + return 0; + + return -EINVAL; +} + +static inline int32_t validate_el3_interrupt_rm(uint32_t x) +{ +#if EL3_EXCEPTION_HANDLING + /* + * With EL3 exception handling, EL3 interrupts are always routed to EL3 + * from both Secure and Non-secure, and therefore INTR_EL3_VALID_RM1 is + * the only valid routing model. + */ + if (x == INTR_EL3_VALID_RM1) + return 0; +#else + if ((x == INTR_EL3_VALID_RM0) || (x == INTR_EL3_VALID_RM1)) + return 0; +#endif + + return -EINVAL; +} + +/******************************************************************************* + * Prototype for defining a handler for an interrupt type + ******************************************************************************/ +typedef uint64_t (*interrupt_type_handler_t)(uint32_t id, + uint32_t flags, + void *handle, + void *cookie); + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +u_register_t get_scr_el3_from_routing_model(uint32_t security_state); +int32_t set_routing_model(uint32_t type, uint32_t flags); +int32_t register_interrupt_type_handler(uint32_t type, + interrupt_type_handler_t handler, + uint32_t flags); +interrupt_type_handler_t get_interrupt_type_handler(uint32_t type); +int disable_intr_rm_local(uint32_t type, uint32_t security_state); +int enable_intr_rm_local(uint32_t type, uint32_t security_state); + +#endif /*__ASSEMBLER__*/ +#endif /* INTERRUPT_MGMT_H */ diff --git a/arm-trusted-firmware/include/bl32/payloads/tlk.h b/arm-trusted-firmware/include/bl32/payloads/tlk.h new file mode 100644 index 0000000..290f329 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/payloads/tlk.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 TLK_H +#define TLK_H + +#include + +/* + * Generate function IDs for the Trusted OS/Apps + */ +#define TLK_TOS_YIELD_FID(fid) ((fid) | 0x72000000 | (0 << 31)) +#define TLK_TA_YIELD_FID(fid) ((fid) | 0x70000000 | (0 << 31)) + +/* + * Trusted OS specific function IDs + */ +#define TLK_REGISTER_LOGBUF TLK_TOS_YIELD_FID(0x1) +#define TLK_REGISTER_REQBUF TLK_TOS_YIELD_FID(0x2) +#define TLK_SS_REGISTER_HANDLER TLK_TOS_YIELD_FID(0x3) +#define TLK_REGISTER_NS_DRAM_RANGES TLK_TOS_YIELD_FID(0x4) +#define TLK_SET_ROOT_OF_TRUST TLK_TOS_YIELD_FID(0x5) +#define TLK_SET_BL_VERSION TLK_TOS_YIELD_FID(0x6) +#define TLK_LOCK_BL_INTERFACE TLK_TOS_YIELD_FID(0x7) +#define TLK_BL_RPMB_SERVICE TLK_TOS_YIELD_FID(0x8) +#define TLK_RESUME_FID TLK_TOS_YIELD_FID(0x100) +#define TLK_SYSTEM_SUSPEND TLK_TOS_YIELD_FID(0xE001) +#define TLK_SYSTEM_RESUME TLK_TOS_YIELD_FID(0xE002) +#define TLK_IRQ_FIRED TLK_TOS_YIELD_FID(0xE004) + +/* + * SMC function IDs that TLK uses to signal various forms of completions + * to the secure payload dispatcher. + */ +#define TLK_REQUEST_DONE (0x32000001 | (ULL(1) << 31)) +#define TLK_PREEMPTED (0x32000002 | (ULL(1) << 31)) +#define TLK_ENTRY_DONE (0x32000003 | (ULL(1) << 31)) +#define TLK_VA_TRANSLATE (0x32000004 | (ULL(1) << 31)) +#define TLK_SUSPEND_DONE (0x32000005 | (ULL(1) << 31)) +#define TLK_RESUME_DONE (0x32000006 | (ULL(1) << 31)) +#define TLK_IRQ_DONE (0x32000008 | (ULL(1) << 31)) + +/* + * Trusted Application specific function IDs + */ +#define TLK_OPEN_TA_SESSION TLK_TA_YIELD_FID(0x1) +#define TLK_CLOSE_TA_SESSION TLK_TA_YIELD_FID(0x2) +#define TLK_TA_LAUNCH_OP TLK_TA_YIELD_FID(0x3) +#define TLK_TA_SEND_EVENT TLK_TA_YIELD_FID(0x4) + +/* + * Total number of function IDs implemented for services offered to NS clients. + */ +#define TLK_NUM_FID 7 + +/* TLK implementation version numbers */ +#define TLK_VERSION_MAJOR 0x0 /* Major version */ +#define TLK_VERSION_MINOR 0x1 /* Minor version */ + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define TOS_CALL_COUNT 0xbf00ff00 /* Number of calls implemented */ +#define TOS_UID 0xbf00ff01 /* Implementation UID */ +#define TOS_CALL_VERSION 0xbf00ff03 /* Trusted OS Call Version */ + +#endif /* TLK_H */ diff --git a/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h b/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h new file mode 100644 index 0000000..971f661 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_SP_MIN_H +#define PLATFORM_SP_MIN_H + +#include + +/******************************************************************************* + * Mandatory SP_MIN functions + ******************************************************************************/ +void sp_min_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void sp_min_platform_setup(void); +void sp_min_plat_runtime_setup(void); +void sp_min_plat_arch_setup(void); +entry_point_info_t *sp_min_plat_get_bl33_ep_info(void); +void sp_min_warm_entrypoint(void); + +/* Platforms that enable SP_MIN_WITH_SECURE_FIQ shall implement this api */ +void sp_min_plat_fiq_handler(uint32_t id); + +#endif /* PLATFORM_SP_MIN_H */ diff --git a/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h b/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h new file mode 100644 index 0000000..fe8a2c9 --- /dev/null +++ b/arm-trusted-firmware/include/bl32/tsp/platform_tsp.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_TSP_H +#define PLATFORM_TSP_H + +/******************************************************************************* + * Mandatory TSP functions (only if platform contains a TSP) + ******************************************************************************/ +void tsp_early_platform_setup(void); +void tsp_plat_arch_setup(void); +void tsp_platform_setup(void); + +#endif /* PLATFORM_TSP_H */ diff --git a/arm-trusted-firmware/include/bl32/tsp/tsp.h b/arm-trusted-firmware/include/bl32/tsp/tsp.h new file mode 100644 index 0000000..285bfbe --- /dev/null +++ b/arm-trusted-firmware/include/bl32/tsp/tsp.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSP_H +#define TSP_H + +/* + * SMC function IDs that TSP uses to signal various forms of completions + * to the secure payload dispatcher. + */ +#define TSP_ENTRY_DONE 0xf2000000 +#define TSP_ON_DONE 0xf2000001 +#define TSP_OFF_DONE 0xf2000002 +#define TSP_SUSPEND_DONE 0xf2000003 +#define TSP_RESUME_DONE 0xf2000004 +#define TSP_PREEMPTED 0xf2000005 +#define TSP_ABORT_DONE 0xf2000007 +#define TSP_SYSTEM_OFF_DONE 0xf2000008 +#define TSP_SYSTEM_RESET_DONE 0xf2000009 + +/* + * Function identifiers to handle S-EL1 interrupt through the synchronous + * handling model. If the TSP was previously interrupted then control has to + * be returned to the TSPD after handling the interrupt else execution can + * remain in the TSP. + */ +#define TSP_HANDLED_S_EL1_INTR 0xf2000006 + +/* SMC function ID that TSP uses to request service from secure monitor */ +#define TSP_GET_ARGS 0xf2001000 + +/* + * Identifiers for various TSP services. Corresponding function IDs (whether + * fast or yielding) are generated by macros defined below + */ +#define TSP_ADD 0x2000 +#define TSP_SUB 0x2001 +#define TSP_MUL 0x2002 +#define TSP_DIV 0x2003 +#define TSP_HANDLE_SEL1_INTR_AND_RETURN 0x2004 +#define TSP_CHECK_DIT 0x2005 + +/* + * Identify a TSP service from function ID filtering the last 16 bits from the + * SMC function ID + */ +#define TSP_BARE_FID(fid) ((fid) & 0xffff) + +/* + * Generate function IDs for TSP services to be used in SMC calls, by + * appropriately setting bit 31 to differentiate yielding and fast SMC calls + */ +#define TSP_YIELD_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000)) +#define TSP_FAST_FID(fid) ((TSP_BARE_FID(fid) | 0x72000000) | (1u << 31)) + +/* SMC function ID to request a previously preempted yielding smc */ +#define TSP_FID_RESUME TSP_YIELD_FID(0x3000) +/* + * SMC function ID to request abortion of a previously preempted yielding SMC. A + * fast SMC is used so that the TSP abort handler does not have to be + * reentrant. + */ +#define TSP_FID_ABORT TSP_FAST_FID(0x3001) + +/* + * Total number of function IDs implemented for services offered to NS clients. + * The function IDs are defined above + */ +#define TSP_NUM_FID 0x5 + +/* TSP implementation version numbers */ +#define TSP_VERSION_MAJOR 0x0 /* Major version */ +#define TSP_VERSION_MINOR 0x1 /* Minor version */ + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define TOS_CALL_COUNT 0xbf00ff00 /* Number of calls implemented */ +#define TOS_UID 0xbf00ff01 /* Implementation UID */ +/* 0xbf00ff02 is reserved */ +#define TOS_CALL_VERSION 0xbf00ff03 /* Trusted OS Call Version */ + + +#ifndef __ASSEMBLER__ + +#include + + +typedef uint32_t tsp_vector_isn_t; + +typedef struct tsp_vectors { + tsp_vector_isn_t yield_smc_entry; + tsp_vector_isn_t fast_smc_entry; + tsp_vector_isn_t cpu_on_entry; + tsp_vector_isn_t cpu_off_entry; + tsp_vector_isn_t cpu_resume_entry; + tsp_vector_isn_t cpu_suspend_entry; + tsp_vector_isn_t sel1_intr_entry; + tsp_vector_isn_t system_off_entry; + tsp_vector_isn_t system_reset_entry; + tsp_vector_isn_t abort_yield_smc_entry; +} tsp_vectors_t; + +void tsp_setup(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* TSP_H */ diff --git a/arm-trusted-firmware/include/common/asm_macros_common.S b/arm-trusted-firmware/include/common/asm_macros_common.S new file mode 100644 index 0000000..fd0ea81 --- /dev/null +++ b/arm-trusted-firmware/include/common/asm_macros_common.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ASM_MACROS_COMMON_S +#define ASM_MACROS_COMMON_S + + /* + * This macro is used to create a function label and place the + * code into a separate text section based on the function name + * to enable elimination of unused code during linking. It also adds + * basic debug information to enable call stack printing most of the + * time. The optional _align parameter can be used to force a + * non-standard alignment (indicated in powers of 2). The default is + * _align=2 because both Aarch32 and Aarch64 instructions must be + * word aligned. Do *not* try to use a raw .align directive. Since func + * switches to a new section, this would not have the desired effect. + */ + .macro func _name, _align=2 + /* + * Add Call Frame Information entry in the .debug_frame section for + * debugger consumption. This enables callstack printing in debuggers. + * This does not use any space in the final loaded binary, only in the + * ELF file. + * Note that a function manipulating the CFA pointer location (i.e. the + * x29 frame pointer on AArch64) should declare it using the + * appropriate .cfi* directives, or be prepared to have a degraded + * debugging experience. + */ + .cfi_sections .debug_frame + .section .text.asm.\_name, "ax" + .type \_name, %function + /* + * .cfi_startproc and .cfi_endproc are needed to output entries in + * .debug_frame + */ + .cfi_startproc + .align \_align + \_name: +#if ENABLE_BTI + /* When Branch Target Identification is enabled, insert "bti jc" + * instruction to enable indirect calls and branches + */ + bti jc +#endif + .endm + + /* + * This macro is used to mark the end of a function. + */ + .macro endfunc _name + .cfi_endproc + .size \_name, . - \_name + .endm + + /* + * Theses macros are used to create function labels for deprecated + * APIs. If ERROR_DEPRECATED is non zero, the callers of these APIs + * will fail to link and cause build failure. + */ +#if ERROR_DEPRECATED + .macro func_deprecated _name + func deprecated\_name + .endm + + .macro endfunc_deprecated _name + endfunc deprecated\_name + .endm +#else + .macro func_deprecated _name + func \_name + .endm + + .macro endfunc_deprecated _name + endfunc \_name + .endm +#endif + + /* + * Helper assembler macro to count trailing zeros. The output is + * populated in the `TZ_COUNT` symbol. + */ + .macro count_tz _value, _tz_count + .if \_value + count_tz "(\_value >> 1)", "(\_tz_count + 1)" + .else + .equ TZ_COUNT, (\_tz_count - 1) + .endif + .endm + + /* + * This macro declares an array of 1 or more stacks, properly + * aligned and in the requested section + */ +#define DEFAULT_STACK_ALIGN (1 << 6) /* In case the caller doesnt provide alignment */ + + .macro declare_stack _name, _section, _size, _count, _align=DEFAULT_STACK_ALIGN + count_tz \_align, 0 + .if (\_align - (1 << TZ_COUNT)) + .error "Incorrect stack alignment specified (Must be a power of 2)." + .endif + .if ((\_size & ((1 << TZ_COUNT) - 1)) <> 0) + .error "Stack size not correctly aligned" + .endif + .section \_section, "aw", %nobits + .align TZ_COUNT + \_name: + .space ((\_count) * (\_size)), 0 + .endm + + +#endif /* ASM_MACROS_COMMON_S */ diff --git a/arm-trusted-firmware/include/common/bl_common.h b/arm-trusted-firmware/include/common/bl_common.h new file mode 100644 index 0000000..8cb4990 --- /dev/null +++ b/arm-trusted-firmware/include/common/bl_common.h @@ -0,0 +1,190 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL_COMMON_H +#define BL_COMMON_H + +#include +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define UP U(1) +#define DOWN U(0) + +/******************************************************************************* + * Constants to identify the location of a memory region in a given memory + * layout. +******************************************************************************/ +#define TOP U(0x1) +#define BOTTOM U(0x0) + +/******************************************************************************* + * Constants to indicate type of exception to the common exception handler. + ******************************************************************************/ +#define SYNC_EXCEPTION_SP_EL0 U(0x0) +#define IRQ_SP_EL0 U(0x1) +#define FIQ_SP_EL0 U(0x2) +#define SERROR_SP_EL0 U(0x3) +#define SYNC_EXCEPTION_SP_ELX U(0x4) +#define IRQ_SP_ELX U(0x5) +#define FIQ_SP_ELX U(0x6) +#define SERROR_SP_ELX U(0x7) +#define SYNC_EXCEPTION_AARCH64 U(0x8) +#define IRQ_AARCH64 U(0x9) +#define FIQ_AARCH64 U(0xa) +#define SERROR_AARCH64 U(0xb) +#define SYNC_EXCEPTION_AARCH32 U(0xc) +#define IRQ_AARCH32 U(0xd) +#define FIQ_AARCH32 U(0xe) +#define SERROR_AARCH32 U(0xf) + +/* + * Mapping to connect linker symbols from .ld.S with their counterparts + * from .scat for the BL31 image + */ +#if defined(USE_ARM_LINK) +#define __BL31_END__ Load$$LR$$LR_END$$Base +#define __BSS_START__ Load$$LR$$LR_BSS$$Base +#define __BSS_END__ Load$$LR$$LR_BSS$$Limit +#define __BSS_SIZE__ Load$$LR$$LR_BSS$$Length +#define __COHERENT_RAM_START__ Load$$LR$$LR_COHERENT_RAM$$Base +#define __COHERENT_RAM_END_UNALIGNED__ Load$$__COHERENT_RAM_EPILOGUE_UNALIGNED__$$Base +#define __COHERENT_RAM_END__ Load$$LR$$LR_COHERENT_RAM$$Limit +#define __COHERENT_RAM_UNALIGNED_SIZE__ Load$$__COHERENT_RAM__$$Length +#define __CPU_OPS_START__ Load$$__CPU_OPS__$$Base +#define __CPU_OPS_END__ Load$$__CPU_OPS__$$Limit +#define __DATA_START__ Load$$__DATA__$$Base +#define __DATA_END__ Load$$__DATA__$$Limit +#define __GOT_START__ Load$$__GOT__$$Base +#define __GOT_END__ Load$$__GOT__$$Limit +#define __PERCPU_BAKERY_LOCK_START__ Load$$__BAKERY_LOCKS__$$Base +#define __PERCPU_BAKERY_LOCK_END__ Load$$__BAKERY_LOCKS_EPILOGUE__$$Base +#define __PMF_SVC_DESCS_START__ Load$$__PMF_SVC_DESCS__$$Base +#define __PMF_SVC_DESCS_END__ Load$$__PMF_SVC_DESCS__$$Limit +#define __PMF_TIMESTAMP_START__ Load$$__PMF_TIMESTAMP__$$Base +#define __PMF_TIMESTAMP_END__ Load$$__PER_CPU_TIMESTAMPS__$$Limit +#define __PMF_PERCPU_TIMESTAMP_END__ Load$$__PMF_TIMESTAMP_EPILOGUE__$$Base +#define __RELA_END__ Load$$__RELA__$$Limit +#define __RELA_START__ Load$$__RELA__$$Base +#define __RODATA_START__ Load$$__RODATA__$$Base +#define __RODATA_END__ Load$$__RODATA_EPILOGUE__$$Base +#define __RT_SVC_DESCS_START__ Load$$__RT_SVC_DESCS__$$Base +#define __RT_SVC_DESCS_END__ Load$$__RT_SVC_DESCS__$$Limit +#define __RW_START__ Load$$LR$$LR_RW_DATA$$Base +#define __RW_END__ Load$$LR$$LR_END$$Base +#define __SPM_SHIM_EXCEPTIONS_START__ Load$$__SPM_SHIM_EXCEPTIONS__$$Base +#define __SPM_SHIM_EXCEPTIONS_END__ Load$$__SPM_SHIM_EXCEPTIONS_EPILOGUE__$$Base +#define __STACKS_START__ Load$$__STACKS__$$Base +#define __STACKS_END__ Load$$__STACKS__$$Limit +#define __TEXT_START__ Load$$__TEXT__$$Base +#define __TEXT_END__ Load$$__TEXT_EPILOGUE__$$Base +#endif /* USE_ARM_LINK */ + +#ifndef __ASSEMBLER__ + +/* + * Declarations of linker defined symbols to help determine memory layout of + * BL images + */ +#if SEPARATE_CODE_AND_RODATA +IMPORT_SYM(uintptr_t, __TEXT_START__, BL_CODE_BASE); +IMPORT_SYM(uintptr_t, __TEXT_END__, BL_CODE_END); +IMPORT_SYM(uintptr_t, __RODATA_START__, BL_RO_DATA_BASE); +IMPORT_SYM(uintptr_t, __RODATA_END__, BL_RO_DATA_END); +#else +IMPORT_SYM(uintptr_t, __RO_START__, BL_CODE_BASE); +IMPORT_SYM(uintptr_t, __RO_END__, BL_CODE_END); +#endif +#if SEPARATE_NOBITS_REGION +IMPORT_SYM(uintptr_t, __NOBITS_START__, BL_NOBITS_BASE); +IMPORT_SYM(uintptr_t, __NOBITS_END__, BL_NOBITS_END); +#endif +IMPORT_SYM(uintptr_t, __RW_END__, BL_END); + +#if defined(IMAGE_BL1) +IMPORT_SYM(uintptr_t, __BL1_ROM_END__, BL1_ROM_END); + +IMPORT_SYM(uintptr_t, __BL1_RAM_START__, BL1_RAM_BASE); +IMPORT_SYM(uintptr_t, __BL1_RAM_END__, BL1_RAM_LIMIT); +#elif defined(IMAGE_BL2) +IMPORT_SYM(uintptr_t, __BL2_END__, BL2_END); +#elif defined(IMAGE_BL2U) +IMPORT_SYM(uintptr_t, __BL2U_END__, BL2U_END); +#elif defined(IMAGE_BL31) +IMPORT_SYM(uintptr_t, __BL31_START__, BL31_START); +IMPORT_SYM(uintptr_t, __BL31_END__, BL31_END); +#elif defined(IMAGE_BL32) +IMPORT_SYM(uintptr_t, __BL32_END__, BL32_END); +#elif defined(IMAGE_RMM) +IMPORT_SYM(uintptr_t, __RMM_END__, RMM_END); +#endif /* IMAGE_BLX */ + +/* The following symbols are only exported from the BL2 at EL3 linker script. */ +#if BL2_IN_XIP_MEM && defined(IMAGE_BL2) +IMPORT_SYM(uintptr_t, __BL2_ROM_END__, BL2_ROM_END); + +IMPORT_SYM(uintptr_t, __BL2_RAM_START__, BL2_RAM_BASE); +IMPORT_SYM(uintptr_t, __BL2_RAM_END__, BL2_RAM_END); +#endif /* BL2_IN_XIP_MEM */ + +/* + * The next 2 constants identify the extents of the coherent memory region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __COHERENT_RAM_START__ and __COHERENT_RAM_END__ linker symbols refer to + * page-aligned addresses. + */ +#if USE_COHERENT_MEM +IMPORT_SYM(uintptr_t, __COHERENT_RAM_START__, BL_COHERENT_RAM_BASE); +IMPORT_SYM(uintptr_t, __COHERENT_RAM_END__, BL_COHERENT_RAM_END); +#endif + +/******************************************************************************* + * Structure used for telling the next BL how much of a particular type of + * memory is available for its use and how much is already used. + ******************************************************************************/ +typedef struct meminfo { + uintptr_t total_base; + size_t total_size; +} meminfo_t; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +int load_auth_image(unsigned int image_id, image_info_t *image_data); + +#if TRUSTED_BOARD_BOOT && defined(DYN_DISABLE_AUTH) +/* + * API to dynamically disable authentication. Only meant for development + * systems. + */ +void dyn_disable_auth(void); +#endif + +extern const char build_message[]; +extern const char version_string[]; + +void print_entry_point_info(const entry_point_info_t *ep_info); +uintptr_t page_align(uintptr_t value, unsigned dir); + +struct mmap_region; + +void setup_page_tables(const struct mmap_region *bl_regions, + const struct mmap_region *plat_regions); + +void bl_handle_pauth(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* BL_COMMON_H */ diff --git a/arm-trusted-firmware/include/common/bl_common.ld.h b/arm-trusted-firmware/include/common/bl_common.ld.h new file mode 100644 index 0000000..5147e37 --- /dev/null +++ b/arm-trusted-firmware/include/common/bl_common.ld.h @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BL_COMMON_LD_H +#define BL_COMMON_LD_H + +#include + +#ifdef __aarch64__ +#define STRUCT_ALIGN 8 +#define BSS_ALIGN 16 +#else +#define STRUCT_ALIGN 4 +#define BSS_ALIGN 8 +#endif + +#ifndef DATA_ALIGN +#define DATA_ALIGN 1 +#endif + +#define CPU_OPS \ + . = ALIGN(STRUCT_ALIGN); \ + __CPU_OPS_START__ = .; \ + KEEP(*(cpu_ops)) \ + __CPU_OPS_END__ = .; + +#define PARSER_LIB_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __PARSER_LIB_DESCS_START__ = .; \ + KEEP(*(.img_parser_lib_descs)) \ + __PARSER_LIB_DESCS_END__ = .; + +#define RT_SVC_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __RT_SVC_DESCS_START__ = .; \ + KEEP(*(rt_svc_descs)) \ + __RT_SVC_DESCS_END__ = .; + +#define PMF_SVC_DESCS \ + . = ALIGN(STRUCT_ALIGN); \ + __PMF_SVC_DESCS_START__ = .; \ + KEEP(*(pmf_svc_descs)) \ + __PMF_SVC_DESCS_END__ = .; + +#define FCONF_POPULATOR \ + . = ALIGN(STRUCT_ALIGN); \ + __FCONF_POPULATOR_START__ = .; \ + KEEP(*(.fconf_populator)) \ + __FCONF_POPULATOR_END__ = .; + +/* + * 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 pointer size alignment. + */ +#define GOT \ + . = ALIGN(STRUCT_ALIGN); \ + __GOT_START__ = .; \ + *(.got) \ + __GOT_END__ = .; + +/* + * The base xlat table + * + * It is put into the rodata section if PLAT_RO_XLAT_TABLES=1, + * or into the bss section otherwise. + */ +#define BASE_XLAT_TABLE \ + . = ALIGN(16); \ + *(base_xlat_table) + +#if PLAT_RO_XLAT_TABLES +#define BASE_XLAT_TABLE_RO BASE_XLAT_TABLE +#define BASE_XLAT_TABLE_BSS +#else +#define BASE_XLAT_TABLE_RO +#define BASE_XLAT_TABLE_BSS BASE_XLAT_TABLE +#endif + +#define RODATA_COMMON \ + RT_SVC_DESCS \ + FCONF_POPULATOR \ + PMF_SVC_DESCS \ + PARSER_LIB_DESCS \ + CPU_OPS \ + GOT \ + BASE_XLAT_TABLE_RO + +/* + * .data must be placed at a lower address than the stacks if the stack + * protector is enabled. Alternatively, the .data.stack_protector_canary + * section can be placed independently of the main .data section. + */ +#define DATA_SECTION \ + .data . : ALIGN(DATA_ALIGN) { \ + __DATA_START__ = .; \ + *(SORT_BY_ALIGNMENT(.data*)) \ + __DATA_END__ = .; \ + } + +/* + * .rela.dyn needs to come after .data for the read-elf utility to parse + * this section correctly. + */ +#if __aarch64__ +#define RELA_DYN_NAME .rela.dyn +#define RELOC_SECTIONS_PATTERN *(.rela*) +#else +#define RELA_DYN_NAME .rel.dyn +#define RELOC_SECTIONS_PATTERN *(.rel*) +#endif + +#define RELA_SECTION \ + RELA_DYN_NAME : ALIGN(STRUCT_ALIGN) { \ + __RELA_START__ = .; \ + RELOC_SECTIONS_PATTERN \ + __RELA_END__ = .; \ + } + +#if !(defined(IMAGE_BL31) && RECLAIM_INIT_CODE) +#define STACK_SECTION \ + stacks (NOLOAD) : { \ + __STACKS_START__ = .; \ + *(tzfw_normal_stacks) \ + __STACKS_END__ = .; \ + } +#endif + +/* + * If BL doesn't use any bakery lock then __PERCPU_BAKERY_LOCK_SIZE__ + * will be zero. For this reason, the only two valid values for + * __PERCPU_BAKERY_LOCK_SIZE__ are 0 or the platform defined value + * PLAT_PERCPU_BAKERY_LOCK_SIZE. + */ +#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE +#define BAKERY_LOCK_SIZE_CHECK \ + ASSERT((__PERCPU_BAKERY_LOCK_SIZE__ == 0) || \ + (__PERCPU_BAKERY_LOCK_SIZE__ == PLAT_PERCPU_BAKERY_LOCK_SIZE), \ + "PLAT_PERCPU_BAKERY_LOCK_SIZE does not match bakery lock requirements"); +#else +#define BAKERY_LOCK_SIZE_CHECK +#endif + +/* + * 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 + */ +#if !USE_COHERENT_MEM +#define BAKERY_LOCK_NORMAL \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __BAKERY_LOCK_START__ = .; \ + __PERCPU_BAKERY_LOCK_START__ = .; \ + *(bakery_lock) \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PERCPU_BAKERY_LOCK_END__ = .; \ + __PERCPU_BAKERY_LOCK_SIZE__ = ABSOLUTE(__PERCPU_BAKERY_LOCK_END__ - __PERCPU_BAKERY_LOCK_START__); \ + . = . + (__PERCPU_BAKERY_LOCK_SIZE__ * (PLATFORM_CORE_COUNT - 1)); \ + __BAKERY_LOCK_END__ = .; \ + BAKERY_LOCK_SIZE_CHECK +#else +#define BAKERY_LOCK_NORMAL +#endif + +/* + * 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 CPUs is allocated by the + * linker script + */ +#define PMF_TIMESTAMP \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PMF_TIMESTAMP_START__ = .; \ + KEEP(*(pmf_timestamp_array)) \ + . = ALIGN(CACHE_WRITEBACK_GRANULE); \ + __PMF_PERCPU_TIMESTAMP_END__ = .; \ + __PERCPU_TIMESTAMP_SIZE__ = ABSOLUTE(. - __PMF_TIMESTAMP_START__); \ + . = . + (__PERCPU_TIMESTAMP_SIZE__ * (PLATFORM_CORE_COUNT - 1)); \ + __PMF_TIMESTAMP_END__ = .; + + +/* + * The .bss section gets initialised to 0 at runtime. + * Its base address has bigger alignment for better performance of the + * zero-initialization code. + */ +#define BSS_SECTION \ + .bss (NOLOAD) : ALIGN(BSS_ALIGN) { \ + __BSS_START__ = .; \ + *(SORT_BY_ALIGNMENT(.bss*)) \ + *(COMMON) \ + BAKERY_LOCK_NORMAL \ + PMF_TIMESTAMP \ + BASE_XLAT_TABLE_BSS \ + __BSS_END__ = .; \ + } + +/* + * The xlat_table section is for full, aligned page tables (4K). + * Removing them from .bss avoids forcing 4K alignment on + * the .bss section. The tables are initialized to zero by the translation + * tables library. + */ +#define XLAT_TABLE_SECTION \ + xlat_table (NOLOAD) : { \ + *(xlat_table) \ + } + +#endif /* BL_COMMON_LD_H */ diff --git a/arm-trusted-firmware/include/common/debug.h b/arm-trusted-firmware/include/common/debug.h new file mode 100644 index 0000000..a7ca0d7 --- /dev/null +++ b/arm-trusted-firmware/include/common/debug.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* + * The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE U(0) +#define LOG_LEVEL_ERROR U(10) +#define LOG_LEVEL_NOTICE U(20) +#define LOG_LEVEL_WARNING U(30) +#define LOG_LEVEL_INFO U(40) +#define LOG_LEVEL_VERBOSE U(50) + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include + +#include + +/* + * Define Log Markers corresponding to each log level which will + * be embedded in the format string and is expected by tf_log() to determine + * the log level. + */ +#define LOG_MARKER_ERROR "\xa" /* 10 */ +#define LOG_MARKER_NOTICE "\x14" /* 20 */ +#define LOG_MARKER_WARNING "\x1e" /* 30 */ +#define LOG_MARKER_INFO "\x28" /* 40 */ +#define LOG_MARKER_VERBOSE "\x32" /* 50 */ + +/* + * If the log output is too low then this macro is used in place of tf_log() + * below. The intent is to get the compiler to evaluate the function call for + * type checking and format specifier correctness but let it optimize it out. + */ +#define no_tf_log(fmt, ...) \ + do { \ + if (false) { \ + tf_log(fmt, ##__VA_ARGS__); \ + } \ + } while (false) + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) tf_log(LOG_MARKER_ERROR __VA_ARGS__) +# define ERROR_NL() tf_log_newline(LOG_MARKER_ERROR) +#else +# define ERROR(...) no_tf_log(LOG_MARKER_ERROR __VA_ARGS__) +# define ERROR_NL() +#endif + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) tf_log(LOG_MARKER_NOTICE __VA_ARGS__) +#else +# define NOTICE(...) no_tf_log(LOG_MARKER_NOTICE __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) tf_log(LOG_MARKER_WARNING __VA_ARGS__) +#else +# define WARN(...) no_tf_log(LOG_MARKER_WARNING __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) tf_log(LOG_MARKER_INFO __VA_ARGS__) +#else +# define INFO(...) no_tf_log(LOG_MARKER_INFO __VA_ARGS__) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) tf_log(LOG_MARKER_VERBOSE __VA_ARGS__) +#else +# define VERBOSE(...) no_tf_log(LOG_MARKER_VERBOSE __VA_ARGS__) +#endif + +#if ENABLE_BACKTRACE +void backtrace(const char *cookie); +const char *get_el_str(unsigned int el); +#else +#define backtrace(x) +#endif + +void __dead2 do_panic(void); + +#define panic() \ + do { \ + backtrace(__func__); \ + console_flush(); \ + do_panic(); \ + } while (false) + +/* Function called when stack protection check code detects a corrupted stack */ +void __dead2 __stack_chk_fail(void); + +void tf_log(const char *fmt, ...) __printflike(1, 2); +void tf_log_newline(const char log_fmt[2]); +void tf_log_set_max_level(unsigned int log_level); + +#endif /* __ASSEMBLER__ */ +#endif /* DEBUG_H */ diff --git a/arm-trusted-firmware/include/common/desc_image_load.h b/arm-trusted-firmware/include/common/desc_image_load.h new file mode 100644 index 0000000..b044f3e --- /dev/null +++ b/arm-trusted-firmware/include/common/desc_image_load.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef DESC_IMAGE_LOAD_H +#define DESC_IMAGE_LOAD_H + +#include + +/* Following structure is used to store BL ep/image info. */ +typedef struct bl_mem_params_node { + unsigned int image_id; + image_info_t image_info; + entry_point_info_t ep_info; + unsigned int next_handoff_image_id; + bl_load_info_node_t load_node_mem; + bl_params_node_t params_node_mem; +} bl_mem_params_node_t; + +extern bl_mem_params_node_t *bl_mem_params_desc_ptr; +extern unsigned int bl_mem_params_desc_num; + +/* + * Macro to register list of BL image descriptors, + * defined as an array of bl_mem_params_node_t. + */ +#define REGISTER_BL_IMAGE_DESCS(_img_desc) \ + bl_mem_params_node_t *bl_mem_params_desc_ptr = &_img_desc[0]; \ + unsigned int bl_mem_params_desc_num = ARRAY_SIZE(_img_desc); + +/* BL image loading utility functions */ +void flush_bl_params_desc(void); +void flush_bl_params_desc_args(bl_mem_params_node_t *mem_params_desc_ptr, + unsigned int mem_params_desc_num, + bl_params_t *next_bl_params_ptr); +int get_bl_params_node_index(unsigned int image_id); +bl_mem_params_node_t *get_bl_mem_params_node(unsigned int image_id); +bl_load_info_t *get_bl_load_info_from_mem_params_desc(void); +bl_params_t *get_next_bl_params_from_mem_params_desc(void); +void populate_next_bl_params_config(bl_params_t *bl2_to_next_bl_params); + +/* Helper to extract BL32/BL33 entry point info from arg0 passed to BL31. */ +void bl31_params_parse_helper(u_register_t param, + entry_point_info_t *bl32_ep_info_out, + entry_point_info_t *bl33_ep_info_out); + +#endif /* DESC_IMAGE_LOAD_H */ diff --git a/arm-trusted-firmware/include/common/ep_info.h b/arm-trusted-firmware/include/common/ep_info.h new file mode 100644 index 0000000..771572c --- /dev/null +++ b/arm-trusted-firmware/include/common/ep_info.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EP_INFO_H +#define EP_INFO_H + +#include + +#ifndef __ASSEMBLER__ +#include +#include +#endif /* __ASSEMBLER__ */ + +#include + +#define SECURE EP_SECURE +#define NON_SECURE EP_NON_SECURE +#define REALM EP_REALM +#if ENABLE_RME +#define sec_state_is_valid(s) (((s) == SECURE) || \ + ((s) == NON_SECURE) || \ + ((s) == REALM)) +#else +#define sec_state_is_valid(s) (((s) == SECURE) || ((s) == NON_SECURE)) +#endif + +#define PARAM_EP_SECURITY_MASK EP_SECURITY_MASK + +#define NON_EXECUTABLE EP_NON_EXECUTABLE +#define EXECUTABLE EP_EXECUTABLE + +/* Get/set security state of an image */ +#define GET_SECURITY_STATE(x) ((x) & EP_SECURITY_MASK) +#define SET_SECURITY_STATE(x, security) \ + ((x) = ((x) & ~EP_SECURITY_MASK) | (security)) + +#ifndef __ASSEMBLER__ + +/* + * Compile time assertions related to the 'entry_point_info' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(ENTRY_POINT_INFO_PC_OFFSET == + __builtin_offsetof(entry_point_info_t, pc), \ + assert_BL31_pc_offset_mismatch); + +#ifndef __aarch64__ +CASSERT(ENTRY_POINT_INFO_LR_SVC_OFFSET == + __builtin_offsetof(entry_point_info_t, lr_svc), + assert_entrypoint_lr_offset_error); +#endif + +CASSERT(ENTRY_POINT_INFO_ARGS_OFFSET == \ + __builtin_offsetof(entry_point_info_t, args), \ + assert_BL31_args_offset_mismatch); + +CASSERT(sizeof(uintptr_t) == + __builtin_offsetof(entry_point_info_t, spsr) - \ + __builtin_offsetof(entry_point_info_t, pc), \ + assert_entrypoint_and_spsr_should_be_adjacent); + +#endif /*__ASSEMBLER__*/ + +#endif /* EP_INFO_H */ diff --git a/arm-trusted-firmware/include/common/fdt_fixup.h b/arm-trusted-firmware/include/common/fdt_fixup.h new file mode 100644 index 0000000..7a590b2 --- /dev/null +++ b/arm-trusted-firmware/include/common/fdt_fixup.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FDT_FIXUP_H +#define FDT_FIXUP_H + +#define INVALID_BASE_ADDR ((uintptr_t)~0UL) + +int dt_add_psci_node(void *fdt); +int dt_add_psci_cpu_enable_methods(void *fdt); +int fdt_add_reserved_memory(void *dtb, const char *node_name, + uintptr_t base, size_t size); +int fdt_add_cpus_node(void *dtb, unsigned int afflv0, + unsigned int afflv1, unsigned int afflv2); +int fdt_adjust_gic_redist(void *dtb, unsigned int nr_cores, uintptr_t gicr_base, + unsigned int gicr_frame_size); + +#endif /* FDT_FIXUP_H */ diff --git a/arm-trusted-firmware/include/common/fdt_wrappers.h b/arm-trusted-firmware/include/common/fdt_wrappers.h new file mode 100644 index 0000000..9c7180c --- /dev/null +++ b/arm-trusted-firmware/include/common/fdt_wrappers.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Helper functions to offer easier navigation of Device Tree Blob */ + +#ifndef FDT_WRAPPERS_H +#define FDT_WRAPPERS_H + +#include + +/* Number of cells, given total length in bytes. Each cell is 4 bytes long */ +#define NCELLS(len) ((len) / 4U) + +int fdt_read_uint32(const void *dtb, int node, const char *prop_name, + uint32_t *value); +uint32_t fdt_read_uint32_default(const void *dtb, int node, + const char *prop_name, uint32_t dflt_value); +int fdt_read_uint64(const void *dtb, int node, const char *prop_name, + uint64_t *value); +int fdt_read_uint32_array(const void *dtb, int node, const char *prop_name, + unsigned int cells, uint32_t *value); +int fdtw_read_string(const void *dtb, int node, const char *prop, + char *str, size_t size); +int fdtw_read_uuid(const void *dtb, int node, const char *prop, + unsigned int length, uint8_t *uuid); +int fdtw_write_inplace_cells(void *dtb, int node, const char *prop, + unsigned int cells, void *value); +int fdtw_read_bytes(const void *dtb, int node, const char *prop, + unsigned int length, void *value); +int fdtw_write_inplace_bytes(void *dtb, int node, const char *prop, + unsigned int length, const void *data); +int fdt_get_reg_props_by_index(const void *dtb, int node, int index, + uintptr_t *base, size_t *size); +int fdt_get_reg_props_by_name(const void *dtb, int node, const char *name, + uintptr_t *base, size_t *size); +int fdt_get_stdout_node_offset(const void *dtb); + +uint64_t fdtw_translate_address(const void *dtb, int bus_node, + uint64_t base_address); + +int fdtw_for_each_cpu(const void *fdt, + int (*callback)(const void *dtb, int node, uintptr_t mpidr)); + +static inline uint32_t fdt_blob_size(const void *dtb) +{ + const uint32_t *dtb_header = dtb; + + return fdt32_to_cpu(dtb_header[1]); +} + +#define fdt_for_each_compatible_node(dtb, node, compatible_str) \ +for (node = fdt_node_offset_by_compatible(dtb, -1, compatible_str); \ + node >= 0; \ + node = fdt_node_offset_by_compatible(dtb, node, compatible_str)) + +#endif /* FDT_WRAPPERS_H */ diff --git a/arm-trusted-firmware/include/common/image_decompress.h b/arm-trusted-firmware/include/common/image_decompress.h new file mode 100644 index 0000000..bb35c3b --- /dev/null +++ b/arm-trusted-firmware/include/common/image_decompress.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMAGE_DECOMPRESS_H +#define IMAGE_DECOMPRESS_H + +#include +#include + +struct image_info; + +typedef int (decompressor_t)(uintptr_t *in_buf, size_t in_len, + uintptr_t *out_buf, size_t out_len, + uintptr_t work_buf, size_t work_len); + +void image_decompress_init(uintptr_t buf_base, uint32_t buf_size, + decompressor_t *decompressor); +void image_decompress_prepare(struct image_info *info); +int image_decompress(struct image_info *info); + +#endif /* IMAGE_DECOMPRESS_H */ diff --git a/arm-trusted-firmware/include/common/interrupt_props.h b/arm-trusted-firmware/include/common/interrupt_props.h new file mode 100644 index 0000000..07bafaa --- /dev/null +++ b/arm-trusted-firmware/include/common/interrupt_props.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef INTERRUPT_PROPS_H +#define INTERRUPT_PROPS_H + +#ifndef __ASSEMBLER__ + +/* Create an interrupt property descriptor from various interrupt properties */ +#define INTR_PROP_DESC(num, pri, grp, cfg) \ + { \ + .intr_num = (num), \ + .intr_pri = (pri), \ + .intr_grp = (grp), \ + .intr_cfg = (cfg), \ + } + +typedef struct interrupt_prop { + unsigned int intr_num:10; + unsigned int intr_pri:8; + unsigned int intr_grp:2; + unsigned int intr_cfg:2; +} interrupt_prop_t; + +#endif /* __ASSEMBLER__ */ +#endif /* INTERRUPT_PROPS_H */ diff --git a/arm-trusted-firmware/include/common/nv_cntr_ids.h b/arm-trusted-firmware/include/common/nv_cntr_ids.h new file mode 100644 index 0000000..a15c431 --- /dev/null +++ b/arm-trusted-firmware/include/common/nv_cntr_ids.h @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define TRUSTED_NV_CTR_ID U(0) +#define NON_TRUSTED_NV_CTR_ID U(1) +#define MAX_NV_CTR_IDS U(2) diff --git a/arm-trusted-firmware/include/common/param_header.h b/arm-trusted-firmware/include/common/param_header.h new file mode 100644 index 0000000..4dab4e3 --- /dev/null +++ b/arm-trusted-firmware/include/common/param_header.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PARAM_HEADER_H +#define PARAM_HEADER_H + +#include + +#ifndef __ASSEMBLER__ +#include +#endif /*__ASSEMBLER__*/ + +#include + +#define VERSION_1 PARAM_VERSION_1 +#define VERSION_2 PARAM_VERSION_2 + +#define SET_PARAM_HEAD(_p, _type, _ver, _attr) do { \ + (_p)->h.type = (uint8_t)(_type); \ + (_p)->h.version = (uint8_t)(_ver); \ + (_p)->h.size = (uint16_t)sizeof(*(_p)); \ + (_p)->h.attr = (uint32_t)(_attr) ; \ + } while (false) + +/* Following is used for populating structure members statically. */ +#define SET_STATIC_PARAM_HEAD(_p, _type, _ver, _p_type, _attr) \ + ._p.h.type = (uint8_t)(_type), \ + ._p.h.version = (uint8_t)(_ver), \ + ._p.h.size = (uint16_t)sizeof(_p_type), \ + ._p.h.attr = (uint32_t)(_attr) + +#endif /* PARAM_HEADER_H */ diff --git a/arm-trusted-firmware/include/common/romlib.h b/arm-trusted-firmware/include/common/romlib.h new file mode 100644 index 0000000..7f53c47 --- /dev/null +++ b/arm-trusted-firmware/include/common/romlib.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ROMLIB_H +#define ROMLIB_H + +#define ROMLIB_MAJOR 0 +#define ROMLIB_MINOR 1 +#define ROMLIB_VERSION ((ROMLIB_MAJOR << 8) | ROMLIB_MINOR) + +int rom_lib_init(int version); + +#endif /* ROMLIB_H */ diff --git a/arm-trusted-firmware/include/common/runtime_svc.h b/arm-trusted-firmware/include/common/runtime_svc.h new file mode 100644 index 0000000..472a32a --- /dev/null +++ b/arm-trusted-firmware/include/common/runtime_svc.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RUNTIME_SVC_H +#define RUNTIME_SVC_H + +#include /* to include exception types */ +#include +#include +#include /* to include SMCCC definitions */ + +/******************************************************************************* + * Structure definition, typedefs & constants for the runtime service framework + ******************************************************************************/ + +/* + * Constants to allow the assembler access a runtime service + * descriptor + */ +#ifdef __aarch64__ +#define RT_SVC_SIZE_LOG2 U(5) +#define RT_SVC_DESC_INIT U(16) +#define RT_SVC_DESC_HANDLE U(24) +#else +#define RT_SVC_SIZE_LOG2 U(4) +#define RT_SVC_DESC_INIT U(8) +#define RT_SVC_DESC_HANDLE U(12) +#endif /* __aarch64__ */ +#define SIZEOF_RT_SVC_DESC (U(1) << RT_SVC_SIZE_LOG2) + + +/* + * In SMCCC 1.X, the function identifier has 6 bits for the owning entity number + * and a single bit for the type of smc call. When taken together, those values + * limit the maximum number of runtime services to 128. + */ +#define MAX_RT_SVCS U(128) + +#ifndef __ASSEMBLER__ + +/* Prototype for runtime service initializing function */ +typedef int32_t (*rt_svc_init_t)(void); + +/* + * Prototype for runtime service SMC handler function. x0 (SMC Function ID) to + * x4 are as passed by the caller. Rest of the arguments to SMC and the context + * can be accessed using the handle pointer. The cookie parameter is reserved + * for future use + */ +typedef uintptr_t (*rt_svc_handle_t)(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); +typedef struct rt_svc_desc { + uint8_t start_oen; + uint8_t end_oen; + uint8_t call_type; + const char *name; + rt_svc_init_t init; + rt_svc_handle_t handle; +} rt_svc_desc_t; + +/* + * Convenience macros to declare a service descriptor + */ +#define DECLARE_RT_SVC(_name, _start, _end, _type, _setup, _smch) \ + static const rt_svc_desc_t __svc_desc_ ## _name \ + __section("rt_svc_descs") __used = { \ + .start_oen = (_start), \ + .end_oen = (_end), \ + .call_type = (_type), \ + .name = #_name, \ + .init = (_setup), \ + .handle = (_smch) \ + } + +/* + * Compile time assertions related to the 'rt_svc_desc' structure to: + * 1. ensure that the assembler and the compiler view of the size + * of the structure are the same. + * 2. ensure that the assembler and the compiler see the initialisation + * routine at the same offset. + * 3. ensure that the assembler and the compiler see the handler + * routine at the same offset. + */ +CASSERT((sizeof(rt_svc_desc_t) == SIZEOF_RT_SVC_DESC), \ + assert_sizeof_rt_svc_desc_mismatch); +CASSERT(RT_SVC_DESC_INIT == __builtin_offsetof(rt_svc_desc_t, init), \ + assert_rt_svc_desc_init_offset_mismatch); +CASSERT(RT_SVC_DESC_HANDLE == __builtin_offsetof(rt_svc_desc_t, handle), \ + assert_rt_svc_desc_handle_offset_mismatch); + + +/* + * This function combines the call type and the owning entity number + * corresponding to a runtime service to generate a unique owning entity number. + * This unique oen is used to access an entry in the 'rt_svc_descs_indices' + * array. The entry contains the index of the service descriptor in the + * 'rt_svc_descs' array. + */ +static inline uint32_t get_unique_oen(uint32_t oen, uint32_t call_type) +{ + return ((call_type & FUNCID_TYPE_MASK) << FUNCID_OEN_WIDTH) | + (oen & FUNCID_OEN_MASK); +} + +/* + * This function generates the unique owning entity number from the SMC Function + * ID. This unique oen is used to access an entry in the 'rt_svc_descs_indices' + * array to invoke the corresponding runtime service handler during SMC + * handling. + */ +static inline uint32_t get_unique_oen_from_smc_fid(uint32_t fid) +{ + return get_unique_oen(GET_SMC_OEN(fid), GET_SMC_TYPE(fid)); +} + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void runtime_svc_init(void); +uintptr_t handle_runtime_svc(uint32_t smc_fid, void *cookie, void *handle, + unsigned int flags); +IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_START__, RT_SVC_DESCS_START); +IMPORT_SYM(uintptr_t, __RT_SVC_DESCS_END__, RT_SVC_DESCS_END); +void init_crash_reporting(void); + +extern uint8_t rt_svc_descs_indices[MAX_RT_SVCS]; + +#endif /*__ASSEMBLER__*/ +#endif /* RUNTIME_SVC_H */ diff --git a/arm-trusted-firmware/include/common/tbbr/cot_def.h b/arm-trusted-firmware/include/common/tbbr/cot_def.h new file mode 100644 index 0000000..800ad07 --- /dev/null +++ b/arm-trusted-firmware/include/common/tbbr/cot_def.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef COT_DEF_H +#define COT_DEF_H + +#ifdef MBEDTLS_CONFIG_FILE +#include MBEDTLS_CONFIG_FILE +#endif + +/* TBBR CoT definitions */ +#if defined(SPD_spmd) +#define COT_MAX_VERIFIED_PARAMS 8 +#else +#define COT_MAX_VERIFIED_PARAMS 4 +#endif + +/* + * Maximum key and hash sizes (in DER format). + * + * Both RSA and ECDSA keys may be used at the same time. In this case, the key + * buffers must be big enough to hold either. As RSA keys are bigger than ECDSA + * ones for all key sizes we support, they impose the minimum size of these + * buffers. + */ +#if TF_MBEDTLS_USE_RSA +#if TF_MBEDTLS_KEY_SIZE == 1024 +#define PK_DER_LEN 162 +#elif TF_MBEDTLS_KEY_SIZE == 2048 +#define PK_DER_LEN 294 +#elif TF_MBEDTLS_KEY_SIZE == 3072 +#define PK_DER_LEN 422 +#elif TF_MBEDTLS_KEY_SIZE == 4096 +#define PK_DER_LEN 550 +#else +#error "Invalid value for TF_MBEDTLS_KEY_SIZE" +#endif +#else /* Only using ECDSA keys. */ +#define PK_DER_LEN 91 +#endif + +#if TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA256 +#define HASH_DER_LEN 51 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA384 +#define HASH_DER_LEN 67 +#elif TF_MBEDTLS_HASH_ALG_ID == TF_MBEDTLS_SHA512 +#define HASH_DER_LEN 83 +#else +#error "Invalid value for TF_MBEDTLS_HASH_ALG_ID" +#endif + +#endif /* COT_DEF_H */ diff --git a/arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h b/arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h new file mode 100644 index 0000000..e1c8c29 --- /dev/null +++ b/arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_IMG_DEF_H +#define TBBR_IMG_DEF_H + +#include + +#if defined(SPD_spmd) +#define SIP_SP_CONTENT_CERT_ID MAX_IMAGE_IDS +#define PLAT_SP_CONTENT_CERT_ID (MAX_IMAGE_IDS + 1) +#define SP_PKG1_ID (MAX_IMAGE_IDS + 2) +#define SP_PKG2_ID (MAX_IMAGE_IDS + 3) +#define SP_PKG3_ID (MAX_IMAGE_IDS + 4) +#define SP_PKG4_ID (MAX_IMAGE_IDS + 5) +#define SP_PKG5_ID (MAX_IMAGE_IDS + 6) +#define SP_PKG6_ID (MAX_IMAGE_IDS + 7) +#define SP_PKG7_ID (MAX_IMAGE_IDS + 8) +#define SP_PKG8_ID (MAX_IMAGE_IDS + 9) +#define MAX_SP_IDS U(8) +#define MAX_IMG_IDS_WITH_SPMDS (MAX_IMAGE_IDS + MAX_SP_IDS + U(2)) +#else +#define MAX_IMG_IDS_WITH_SPMDS MAX_IMAGE_IDS +#endif + +#ifdef PLAT_TBBR_IMG_DEF +#include +#endif + +#ifndef MAX_NUMBER_IDS +#define MAX_NUMBER_IDS MAX_IMG_IDS_WITH_SPMDS +#endif + +#endif /* TBBR_IMG_DEF_H */ diff --git a/arm-trusted-firmware/include/common/tf_crc32.h b/arm-trusted-firmware/include/common/tf_crc32.h new file mode 100644 index 0000000..38c56a5 --- /dev/null +++ b/arm-trusted-firmware/include/common/tf_crc32.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TF_CRC32_H +#define TF_CRC32_H + +#include +#include + +/* compute CRC using Arm intrinsic function */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size); + +#endif /* TF_CRC32_H */ diff --git a/arm-trusted-firmware/include/common/uuid.h b/arm-trusted-firmware/include/common/uuid.h new file mode 100644 index 0000000..5651d0d --- /dev/null +++ b/arm-trusted-firmware/include/common/uuid.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UUID_H +#define UUID_H + +#define UUID_BYTES_LENGTH 16 +#define UUID_STRING_LENGTH 36 + +int read_uuid(uint8_t *dest, char *uuid); + +#endif /* UUID_H */ diff --git a/arm-trusted-firmware/include/drivers/allwinner/axp.h b/arm-trusted-firmware/include/drivers/allwinner/axp.h new file mode 100644 index 0000000..8b90c7f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/allwinner/axp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AXP_H +#define AXP_H + +#include + +#define AXP20X_MODE_REG 0x3e +#define AXP20X_MODE_I2C 0x00 +#define AXP20X_MODE_RSB 0x7c + +#define NA 0xff + +enum { + AXP803_CHIP_ID = 0x41, + AXP805_CHIP_ID = 0x40, +}; + +struct axp_regulator { + const char *dt_name; + uint16_t min_volt; + uint16_t max_volt; + uint16_t step; + unsigned char split; + unsigned char volt_reg; + unsigned char switch_reg; + unsigned char switch_bit; +}; + +extern const uint8_t axp_chip_id; +extern const char *const axp_compatible; +extern const struct axp_regulator axp_regulators[]; + +/* + * Since the PMIC can be connected to multiple bus types, + * low-level read/write functions must be provided by the platform + */ +int axp_read(uint8_t reg); +int axp_write(uint8_t reg, uint8_t val); +int axp_clrsetbits(uint8_t reg, uint8_t clr_mask, uint8_t set_mask); +#define axp_clrbits(reg, clr_mask) axp_clrsetbits(reg, clr_mask, 0) +#define axp_setbits(reg, set_mask) axp_clrsetbits(reg, 0, set_mask) + +int axp_check_id(void); +void axp_power_off(void); + +#if SUNXI_SETUP_REGULATORS == 1 +void axp_setup_regulators(const void *fdt); +#else +static inline void axp_setup_regulators(const void *fdt) +{ +} +#endif + +#endif /* AXP_H */ diff --git a/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h b/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h new file mode 100644 index 0000000..3d003ce --- /dev/null +++ b/arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017-2018 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SUNXI_RSB_H +#define SUNXI_RSB_H + +#include + +int rsb_init_controller(void); +int rsb_set_bus_speed(uint32_t source_freq, uint32_t bus_freq); +int rsb_set_device_mode(uint32_t device_mode); +int rsb_assign_runtime_address(uint16_t hw_addr, uint8_t rt_addr); + +int rsb_read(uint8_t rt_addr, uint8_t reg_addr); +int rsb_write(uint8_t rt_addr, uint8_t reg_addr, uint8_t value); + +#endif /* SUNXI_RSB_H */ diff --git a/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h b/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h new file mode 100644 index 0000000..52129a6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SHA_DMA_H +#define SHA_DMA_H + +#define SHA256_HASHSZ 32 +#define SHA256_BLOCKSZ 0x40 + +enum ASD_MODE { + ASM_INVAL, + ASM_SHA256, + ASM_SHA224, +}; + +struct asd_ctx { + uint8_t digest[SHA256_HASHSZ]; + uint8_t block[SHA256_BLOCKSZ]; + size_t blocksz; + enum ASD_MODE mode; + uint8_t started; +}; + +static inline void asd_sha_init(struct asd_ctx *ctx, enum ASD_MODE mode) +{ + ctx->started = 0; + ctx->mode = mode; + ctx->blocksz = 0; +} + +void asd_sha_update(struct asd_ctx *ctx, void *data, size_t len); +void asd_sha_finalize(struct asd_ctx *ctx); + +#endif diff --git a/arm-trusted-firmware/include/drivers/amlogic/meson_console.h b/arm-trusted-firmware/include/drivers/amlogic/meson_console.h new file mode 100644 index 0000000..8d52d79 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/amlogic/meson_console.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MESON_CONSOLE_H +#define MESON_CONSOLE_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new meson 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. + * + * NOTE: The clock is actually fixed to 24 MHz. The argument is only there in + * order to make this function future-proof. + */ +int console_meson_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* MESON_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h b/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h new file mode 100644 index 0000000..d1e93be --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_GICV3_COMMON_H +#define ARM_GICV3_COMMON_H + +/******************************************************************************* + * GIC500/GIC600 Re-distributor interface registers & constants + ******************************************************************************/ + +/* GICR_WAKER implementation-defined bit definitions */ +#define WAKER_SL_SHIFT 0 +#define WAKER_QSC_SHIFT 31 + +#define WAKER_SL_BIT (1U << WAKER_SL_SHIFT) +#define WAKER_QSC_BIT (1U << WAKER_QSC_SHIFT) + +#define IIDR_MODEL_ARM_GIC_600 U(0x0200043b) +#define IIDR_MODEL_ARM_GIC_600AE U(0x0300043b) +#define IIDR_MODEL_ARM_GIC_700 U(0x0400043b) + +#define PIDR_COMPONENT_ARM_DIST U(0x492) +#define PIDR_COMPONENT_ARM_REDIST U(0x493) +#define PIDR_COMPONENT_ARM_ITS U(0x494) + +#endif /* ARM_GICV3_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/cci.h b/arm-trusted-firmware/include/drivers/arm/cci.h new file mode 100644 index 0000000..5aea95a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cci.h @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCI_H +#define CCI_H + +#include + +/* Slave interface offsets from PERIPHBASE */ +#define SLAVE_IFACE6_OFFSET UL(0x7000) +#define SLAVE_IFACE5_OFFSET UL(0x6000) +#define SLAVE_IFACE4_OFFSET UL(0x5000) +#define SLAVE_IFACE3_OFFSET UL(0x4000) +#define SLAVE_IFACE2_OFFSET UL(0x3000) +#define SLAVE_IFACE1_OFFSET UL(0x2000) +#define SLAVE_IFACE0_OFFSET UL(0x1000) +#define SLAVE_IFACE_OFFSET(index) (SLAVE_IFACE0_OFFSET + \ + (UL(0x1000) * (index))) + +/* Slave interface event and count register offsets from PERIPHBASE */ +#define EVENT_SELECT7_OFFSET UL(0x80000) +#define EVENT_SELECT6_OFFSET UL(0x70000) +#define EVENT_SELECT5_OFFSET UL(0x60000) +#define EVENT_SELECT4_OFFSET UL(0x50000) +#define EVENT_SELECT3_OFFSET UL(0x40000) +#define EVENT_SELECT2_OFFSET UL(0x30000) +#define EVENT_SELECT1_OFFSET UL(0x20000) +#define EVENT_SELECT0_OFFSET UL(0x10000) +#define EVENT_OFFSET(index) (EVENT_SELECT0_OFFSET + \ + (UL(0x10000) * (index))) + +/* Control and ID register offsets */ +#define CTRL_OVERRIDE_REG U(0x0) +#define SECURE_ACCESS_REG U(0x8) +#define STATUS_REG U(0xc) +#define IMPRECISE_ERR_REG U(0x10) +#define PERFMON_CTRL_REG U(0x100) +#define IFACE_MON_CTRL_REG U(0x104) + +/* Component and peripheral ID registers */ +#define PERIPHERAL_ID0 U(0xFE0) +#define PERIPHERAL_ID1 U(0xFE4) +#define PERIPHERAL_ID2 U(0xFE8) +#define PERIPHERAL_ID3 U(0xFEC) +#define PERIPHERAL_ID4 U(0xFD0) +#define PERIPHERAL_ID5 U(0xFD4) +#define PERIPHERAL_ID6 U(0xFD8) +#define PERIPHERAL_ID7 U(0xFDC) + +#define COMPONENT_ID0 U(0xFF0) +#define COMPONENT_ID1 U(0xFF4) +#define COMPONENT_ID2 U(0xFF8) +#define COMPONENT_ID3 U(0xFFC) +#define COMPONENT_ID4 U(0x1000) +#define COMPONENT_ID5 U(0x1004) +#define COMPONENT_ID6 U(0x1008) +#define COMPONENT_ID7 U(0x100C) + +/* Slave interface register offsets */ +#define SNOOP_CTRL_REG U(0x0) +#define SH_OVERRIDE_REG U(0x4) +#define READ_CHNL_QOS_VAL_OVERRIDE_REG U(0x100) +#define WRITE_CHNL_QOS_VAL_OVERRIDE_REG U(0x104) +#define MAX_OT_REG U(0x110) + +/* Snoop Control register bit definitions */ +#define DVM_EN_BIT BIT_32(1) +#define SNOOP_EN_BIT BIT_32(0) +#define SUPPORT_SNOOPS BIT_32(30) +#define SUPPORT_DVM BIT_32(31) + +/* Status register bit definitions */ +#define CHANGE_PENDING_BIT BIT_32(0) + +/* Event and count register offsets */ +#define EVENT_SELECT_REG U(0x0) +#define EVENT_COUNT_REG U(0x4) +#define COUNT_CNTRL_REG U(0x8) +#define COUNT_OVERFLOW_REG U(0xC) + +/* Slave interface monitor registers */ +#define INT_MON_REG_SI0 U(0x90000) +#define INT_MON_REG_SI1 U(0x90004) +#define INT_MON_REG_SI2 U(0x90008) +#define INT_MON_REG_SI3 U(0x9000C) +#define INT_MON_REG_SI4 U(0x90010) +#define INT_MON_REG_SI5 U(0x90014) +#define INT_MON_REG_SI6 U(0x90018) + +/* Master interface monitor registers */ +#define INT_MON_REG_MI0 U(0x90100) +#define INT_MON_REG_MI1 U(0x90104) +#define INT_MON_REG_MI2 U(0x90108) +#define INT_MON_REG_MI3 U(0x9010c) +#define INT_MON_REG_MI4 U(0x90110) +#define INT_MON_REG_MI5 U(0x90114) + +#define SLAVE_IF_UNUSED -1 + +#ifndef __ASSEMBLER__ + +#include + +/* Function declarations */ + +/* + * The ARM CCI driver needs the following: + * 1. Base address of the CCI product + * 2. An array of map between AMBA 4 master ids and ACE/ACE lite slave + * interfaces. + * 3. Size of the array. + * + * SLAVE_IF_UNUSED should be used in the map to represent no AMBA 4 master exists + * for that interface. + */ +void cci_init(uintptr_t base, const int *map, unsigned int num_cci_masters); + +void cci_enable_snoop_dvm_reqs(unsigned int master_id); +void cci_disable_snoop_dvm_reqs(unsigned int master_id); + +#endif /* __ASSEMBLER__ */ +#endif /* CCI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/ccn.h b/arm-trusted-firmware/include/drivers/arm/ccn.h new file mode 100644 index 0000000..7f73768 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/ccn.h @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CCN_H +#define CCN_H + +/* + * This macro defines the maximum number of master interfaces that reside on + * Request nodes which the CCN driver can accommodate. The driver APIs to add + * and remove Request nodes from snoop/dvm domains take a bit map of master + * interfaces as inputs. The largest C data type that can be used is a 64-bit + * unsigned integer. Hence the value of 64. The platform will have to ensure + * that the master interfaces are numbered from 0-63. + */ +#define CCN_MAX_RN_MASTERS 64 + +/* + * The following constants define the various run modes that the platform can + * request the CCN driver to place the L3 cache in. These map to the + * programmable P-State values in a HN-F P-state register. + */ +#define CCN_L3_RUN_MODE_NOL3 0x0 /* HNF_PM_NOL3 */ +#define CCN_L3_RUN_MODE_SFONLY 0x1 /* HNF_PM_SFONLY */ +#define CCN_L3_RUN_MODE_HAM 0x2 /* HNF_PM_HALF */ +#define CCN_L3_RUN_MODE_FAM 0x3 /* HNF_PM_FULL */ + +/* part 0 IDs for various CCN variants */ +#define CCN_502_PART0_ID 0x30 +#define CCN_504_PART0_ID 0x26 +#define CCN_505_PART0_ID 0x27 +#define CCN_508_PART0_ID 0x28 +#define CCN_512_PART0_ID 0x29 + +/* + * The following macro takes the value returned from a read of a HN-F P-state + * status register and returns the retention state value. + */ +#define CCN_GET_RETENTION_STATE(pstate) ((pstate >> 4) & 0x3) + +/* + * The following macro takes the value returned from a read of a HN-F P-state + * status register and returns the run state value. + */ +#define CCN_GET_RUN_STATE(pstate) (pstate & 0xf) + +#ifndef __ASSEMBLER__ +#include + +/* + * This structure describes some of the implementation defined attributes of the + * CCN IP. It is used by the platform port to specify these attributes in order + * to initialise the CCN driver. The attributes are described below. + * + * 1. The 'num_masters' field specifies the total number of master interfaces + * resident on Request nodes. + * + * 2. The 'master_to_rn_id_map' field is a ponter to an array in which each + * index corresponds to a master interface and its value corresponds to the + * Request node on which the master interface resides. + * This field is not simply defined as an array of size CCN_MAX_RN_MASTERS. + * In reality, a platform will have much fewer master * interfaces than + * CCN_MAX_RN_MASTERS. With an array of this size, it would also have to + * set the unused entries to a suitable value. Zeroing the array would not + * be enough since 0 is also a valid node id. Hence, such an array is not + * used. + * + * 3. The 'periphbase' field is the base address of the programmer's view of the + * CCN IP. + */ +typedef struct ccn_desc { + unsigned int num_masters; + const unsigned char *master_to_rn_id_map; + uintptr_t periphbase; +} ccn_desc_t; + +/* Enum used to loop through all types of nodes in CCN*/ +typedef enum node_types { + NODE_TYPE_RNF = 0, + NODE_TYPE_RNI, + NODE_TYPE_RND, + NODE_TYPE_HNF, + NODE_TYPE_HNI, + NODE_TYPE_SN, + NUM_NODE_TYPES +} node_types_t; + +void ccn_init(const ccn_desc_t *plat_ccn_desc); +void ccn_enter_snoop_dvm_domain(unsigned long long master_iface_map); +void ccn_exit_snoop_dvm_domain(unsigned long long master_iface_map); +void ccn_enter_dvm_domain(unsigned long long master_iface_map); +void ccn_exit_dvm_domain(unsigned long long master_iface_map); +void ccn_set_l3_run_mode(unsigned int mode); +void ccn_program_sys_addrmap(unsigned int sn0_id, + unsigned int sn1_id, + unsigned int sn2_id, + unsigned int top_addr_bit0, + unsigned int top_addr_bit1, + unsigned char three_sn_en); +unsigned int ccn_get_l3_run_mode(void); +int ccn_get_part0_id(uintptr_t periphbase); + +void ccn_write_node_reg(node_types_t node_type, unsigned int node_id, + unsigned int reg_offset, + unsigned long long val); +unsigned long long ccn_read_node_reg(node_types_t node_type, + unsigned int node_id, + unsigned int reg_offset); + +#endif /* __ASSEMBLER__ */ +#endif /* CCN_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h new file mode 100644 index 0000000..2cb8938 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_CRYPTO_BOOT_DEFS_H +#define _CC_CRYPTO_BOOT_DEFS_H + +/*! @file +@brief This file contains SBROM definitions +*/ + +/*! Version counters value. */ +typedef enum { + + CC_SW_VERSION_COUNTER1 = 1, /*!< Counter 1 - trusted version. */ + CC_SW_VERSION_COUNTER2, /*!< Counter 2 - non trusted version. */ + + CC_SW_VERSION_MAX = 0x7FFFFFFF + +} CCSbSwVersionId_t; + +/* HASH boot key definition */ +typedef enum { + CC_SB_HASH_BOOT_KEY_0_128B = 0, /*!< 128-bit truncated SHA256 digest of public key 0. */ + CC_SB_HASH_BOOT_KEY_1_128B = 1, /*!< 128-bit truncated SHA256 digest of public key 1. */ + CC_SB_HASH_BOOT_KEY_256B = 2, /*!< 256-bit SHA256 digest of public key. */ + CC_SB_HASH_BOOT_NOT_USED = 0xFF, + CC_SB_HASH_MAX_NUM = 0x7FFFFFFF, /*!\internal use external 128-bit truncated SHA256 digest */ +} CCSbPubKeyIndexType_t; + + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h new file mode 100644 index 0000000..212a710 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! +@file +@brief This file contains the platform-dependent definitions that are used in the SBROM code. +*/ + +#ifndef _CC_PAL_SB_PLAT_H +#define _CC_PAL_SB_PLAT_H + +#include "cc_pal_types.h" + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Definition of DMA address type, can be 32 bits or 64 bits according to CryptoCell's HW. */ +typedef uint64_t CCDmaAddr_t; +/*! Definition of CryptoCell address type, can be 32 bits or 64 bits according to platform. */ +typedef uintptr_t CCAddr_t; + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h new file mode 100644 index 0000000..8c09b23 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CC_PAL_TYPES_H +#define CC_PAL_TYPES_H + +/*! +@file +@brief This file contains platform-dependent definitions and types. +*/ + +#include "cc_pal_types_plat.h" + +typedef enum { + CC_FALSE = 0, + CC_TRUE = 1 +} CCBool; + +#define CC_SUCCESS 0UL +#define CC_FAIL 1UL + +#define CC_1K_SIZE_IN_BYTES 1024 +#define CC_BITS_IN_BYTE 8 +#define CC_BITS_IN_32BIT_WORD 32 +#define CC_32BIT_WORD_SIZE (sizeof(uint32_t)) + +#define CC_OK CC_SUCCESS + +#define CC_UNUSED_PARAM(prm) ((void)prm) + +#define CC_MAX_UINT32_VAL (0xFFFFFFFF) + +#define CALC_FULL_BYTES(numBits) (((numBits) + (CC_BITS_IN_BYTE - 1))/CC_BITS_IN_BYTE) +#define CALC_FULL_32BIT_WORDS(numBits) (((numBits) + (CC_BITS_IN_32BIT_WORD - 1))/CC_BITS_IN_32BIT_WRD) +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) (((sizeBytes) + CC_32BIT_WORD_SIZE - 1)/CC_32BIT_WORD_SIZE) + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h new file mode 100644 index 0000000..8410024 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! @file +@brief This file contains basic type definitions that are platform-dependent. +*/ +#ifndef _CC_PAL_TYPES_PLAT_H +#define _CC_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include + +typedef uint32_t CCStatus; + +#define CCError_t CCStatus +#define CC_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*_CC_PAL_TYPES_PLAT_H*/ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h new file mode 100644 index 0000000..d419218 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_SEC_DEFS_H +#define _CC_SEC_DEFS_H + +/*! +@file +@brief This file contains general hash definitions and types. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! The hashblock size in words. */ +#define HASH_BLOCK_SIZE_IN_WORDS 16 +/*! The hash - SHA2 results in words. */ +#define HASH_RESULT_SIZE_IN_WORDS 8 +#define HASH_RESULT_SIZE_IN_BYTES 32 + +/*! Definition for hash result array. */ +typedef uint32_t CCHashResult_t[HASH_RESULT_SIZE_IN_WORDS]; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h new file mode 100644 index 0000000..18104dd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CRYPTO_DRIVER_H +#define _CRYPTO_DRIVER_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_sb_plat.h" +#include "cc_sec_defs.h" + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ +/*! + * @brief This function gives the functionality of integrated hash + * + * @param[in] hwBaseAddress - CryptoCell base address + * @param[out] hashResult - the HASH result. + * + */ +CCError_t SBROM_CryptoHash(unsigned long hwBaseAddress, CCDmaAddr_t inputDataAddr, uint32_t BlockSize, + CCHashResult_t hashResult); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h new file mode 100644 index 0000000..a70289f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _NVM__H +#define _NVM__H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_crypto_boot_defs.h" +#include "cc_pal_types.h" +#include "cc_sec_defs.h" + +/*------------------------------------ + DEFINES +-------------------------------------*/ + +/** + * @brief This function reads the LCS from the SRAM/NVM + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in/out] lcs_ptr - pointer to memory to store the LCS + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_GetLCS(unsigned long hwBaseAddress, uint32_t *lcs_ptr); + +/** + * @brief The NVM_ReadHASHPubKey function is a NVM interface function - + * The function retrieves the HASH of the device Public key from the SRAM/NVM + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] pubKeyIndex - Index of HASH in the OTP + * + * @param[out] PubKeyHASH - the public key HASH. + * + * @param[in] hashSizeInWords - hash size (valid values: 4W, 8W) + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ + +CCError_t NVM_ReadHASHPubKey(unsigned long hwBaseAddress, CCSbPubKeyIndexType_t pubKeyIndex, CCHashResult_t PubKeyHASH, uint32_t hashSizeInWords); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h new file mode 100644 index 0000000..390d62b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _NVM_OTP_H +#define _NVM_OTP_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_crypto_boot_defs.h" +#include "cc_pal_types.h" + +/*------------------------------------ + DEFINES +-------------------------------------*/ + + + +/** + * @brief The NVM_GetSwVersion function is a NVM interface function - + * The function retrieves the SW version from the SRAM/NVM. + * In case of OTP, we support up to 16 anti-rollback counters (taken from the certificate) + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] counterId - relevant only for OTP (valid values: 1,2) + * + * @param[out] swVersion - the minimum SW version + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_GetSwVersion(unsigned long hwBaseAddress, CCSbSwVersionId_t counterId, uint32_t *swVersion); + + +/** + * @brief The NVM_SetSwVersion function is a NVM interface function - + * The function writes the SW version into the SRAM/NVM. + * In case of OTP, we support up to 16 anti-rollback counters (taken from the certificate) + * + * @param[in] hwBaseAddress - CryptoCell base address + * + * @param[in] counterId - relevant only for OTP (valid values: 1,2) + * + * @param[in] swVersion - the minimum SW version + * + * @return CCError_t - On success the value CC_OK is returned, and on failure -a value from NVM_error.h + */ +CCError_t NVM_SetSwVersion(unsigned long hwBaseAddress, CCSbSwVersionId_t counterId, uint32_t swVersion); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h new file mode 100644 index 0000000..825214d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RSA_H +#define RSA_H + +/* + * All the includes that are needed for code using this module to + * compile correctly should be #included here. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/************************ Defines ******************************/ + +/* the modulus size in bits */ +#if (KEY_SIZE == 2048) +#define RSA_MOD_SIZE_IN_BITS 2048UL +#elif (KEY_SIZE == 3072) +#define RSA_MOD_SIZE_IN_BITS 3072UL +#else +#error Unsupported CryptoCell key size requested +#endif + +#define RSA_MOD_SIZE_IN_BYTES (CALC_FULL_BYTES(RSA_MOD_SIZE_IN_BITS)) +#define RSA_MOD_SIZE_IN_WORDS (CALC_FULL_32BIT_WORDS(RSA_MOD_SIZE_IN_BITS)) +#define RSA_MOD_SIZE_IN_256BITS (RSA_MOD_SIZE_IN_WORDS/8) +#define RSA_EXP_SIZE_IN_BITS 17UL +#define RSA_EXP_SIZE_IN_BYTES (CALC_FULL_BYTES(RSA_EXP_SIZE_IN_BITS)) + +/* + * @brief The RSA_CalcNp calculates Np value and saves it into Np_ptr: + * + * + + * @param[in] hwBaseAddress - HW base address. Relevant for HW + * implementation, for SW it is ignored. + * @N_ptr[in] - The pointer to the modulus buffer. + * @Np_ptr[out] - pointer to Np vector buffer. Its size must be >= 160. + */ +void RSA_CalcNp(unsigned long hwBaseAddress, + uint32_t *N_ptr, + uint32_t *Np_ptr); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h new file mode 100644 index 0000000..de83546 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SBROM_BSV_API_H +#define _SBROM_BSV_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This file contains all SBROM library APIs and definitions. +*/ +#include "cc_pal_types.h" + +/* Life cycle state definitions */ +#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 /*!< CM lifecycle value. */ +#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 /*!< DM lifecycle value. */ +#define CC_BSV_SECURITY_DISABLED_LCS 0x3 /*!< SD lifecycle value. */ +#define CC_BSV_SECURE_LCS 0x5 /*!< Secure lifecycle value. */ +#define CC_BSV_RMA_LCS 0x7 /*!< RMA lifecycle value. */ + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function should be the first ARM TrustZone CryptoCell TEE SBROM library API called. +It verifies the HW product and version numbers. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvSbromInit( + unsigned long hwBaseAddress /*!< [in] HW registers base address. */ + ); + + +/*! +@brief This function can be used for checking the LCS value, after CC_BsvLcsGetAndInit was called by the Boot ROM. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + uint32_t *pLcs /*!< [out] Returned lifecycle state. */ + ); + +/*! +@brief This function retrieves the HW security lifecycle state, performs validity checks, +and additional initializations in case the LCS is RMA (sets the Kce to fixed value). +\note Invalid LCS results in an error returned. +In this case, the customer's code must completely disable the device. + +@return CC_OK On success. +@return A non-zero value from sbrom_bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGetAndInit( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + uint32_t *pLcs /*!< [out] Returned lifecycle state. */ + ); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h new file mode 100644 index 0000000..6db596e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SECURE_BOOT_BASE_FUNC_H +#define _SECURE_BOOT_BASE_FUNC_H + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" +#include "secureboot_gen_defs.h" + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/** + * @brief This function calculates the HASH over the given data and than verify + * RSA signature on that hashed data + * + * @param[in] hwBaseAddr - CryptoCell base address + * @param[in] pData - pointer to the data to be verified + * @param[in] pNParams - a pointer to the public key parameters + * @param[in] pSignature - a pointer to the signature structure + * @param[in] sizeOfData - size of the data to calculate the HASH on (in bytes) + * @param[in] RSAAlg - RSA algorithm to use + * + * @return CCError_t - On success the value CC_OK is returned, + * on failure - a value from BootImagesVerifier_error.h + */ +CCError_t CCSbVerifySignature(unsigned long hwBaseAddress, + uint32_t *pData, + CCSbNParams_t *pNParams, + CCSbSignature_t *pSignature, + uint32_t sizeOfData, + CCSbRsaAlg_t RSAAlg); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h new file mode 100644 index 0000000..ed1f283 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _SECURE_BOOT_GEN_DEFS_H +#define _SECURE_BOOT_GEN_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! @file +@brief This file contains all of the definitions and structures that are used for the secure boot. +*/ + +#include "cc_pal_sb_plat.h" +#include "cc_sec_defs.h" + + +/* General definitions */ +/***********************/ + +/*RSA definitions*/ +#if (KEY_SIZE == 2048) +#define SB_RSA_MOD_SIZE_IN_WORDS 64 +#elif (KEY_SIZE == 3072) +#define SB_RSA_MOD_SIZE_IN_WORDS 96 +#else +#error Unsupported CryptoCell key size requested +#endif + +#define SB_RSA_HW_PKI_PKA_BARRETT_MOD_TAG_SIZE_IN_WORDS 5 + + +/*! Public key data structure. */ +typedef struct { + uint32_t N[SB_RSA_MOD_SIZE_IN_WORDS]; /*!< N public key, big endian representation. */ + uint32_t Np[SB_RSA_HW_PKI_PKA_BARRETT_MOD_TAG_SIZE_IN_WORDS]; /*!< Np (Barrett n' value). */ +} CCSbNParams_t; + +/*! Signature structure. */ +typedef struct { + uint32_t sig[SB_RSA_MOD_SIZE_IN_WORDS]; /*!< RSA PSS signature. */ +} CCSbSignature_t; + + +/********* Supported algorithms definitions ***********/ + +/*! RSA supported algorithms */ +/* Note: this applies to either 2k or 3k based on CryptoCell SBROM library + * version - it means 2k in version 1 and 3k in version 2 (yes, really). + */ +typedef enum { + RSA_PSS = 0x01, /*!< RSA PSS after hash SHA 256 */ + RSA_PKCS15 = 0x02, /*!< RSA PKX15 */ + RSA_Last = 0x7FFFFFFF +} CCSbRsaAlg_t; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h new file mode 100644 index 0000000..18fb599 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTIL_H +#define UTIL_H + +/* + * All the includes that are needed for code using this module to + * compile correctly should be #included here. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/************************ Defines ******************************/ + +/* invers the bytes on a word- used for output from HASH */ +#ifdef BIG__ENDIAN +#define UTIL_INVERSE_UINT32_BYTES(val) (val) +#else +#define UTIL_INVERSE_UINT32_BYTES(val) \ + (((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) +#endif + +/* invers the bytes on a word - used for input data for HASH */ +#ifdef BIG__ENDIAN +#define UTIL_REVERT_UINT32_BYTES(val) \ + (((val) >> 24) | (((val) & 0x00FF0000) >> 8) | (((val) & 0x0000FF00) << 8) | (((val) & 0x000000FF) << 24)) +#else +#define UTIL_REVERT_UINT32_BYTES(val) (val) +#endif + + /* ------------------------------------------------------------ + ** + * @brief This function executes a reverse bytes copying from one buffer to another buffer. + * + * @param[in] dst_ptr - The pointer to destination buffer. + * @param[in] src_ptr - The pointer to source buffer. + * @param[in] size - The size in bytes. + * + */ + +void UTIL_ReverseMemCopy(uint8_t *dst_ptr, uint8_t *src_ptr, uint32_t size); + + + /* ------------------------------------------------------------ + ** + * @brief This function executes a reversed byte copy on a specified buffer. + * + * on a 6 byte byffer: + * + * buff[5] <---> buff[0] + * buff[4] <---> buff[1] + * buff[3] <---> buff[2] + * + * @param[in] dst_ptr - The counter buffer. + * @param[in] src_ptr - The counter size in bytes. + * + */ +void UTIL_ReverseBuff(uint8_t *buff_ptr, uint32_t size); + + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h new file mode 100644 index 0000000..dc49473 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h @@ -0,0 +1,221 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_API_H +#define _BSV_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the Boot Services APIs and definitions. + +@defgroup cc_bsv_api CryptoCell Boot Services APIs and definitions +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_sec_defs.h" +#include "cc_boot_defs.h" + +/* Life cycle state definitions. */ +#define CC_BSV_CHIP_MANUFACTURE_LCS 0x0 /*!< The CM life-cycle state (LCS) value. */ +#define CC_BSV_DEVICE_MANUFACTURE_LCS 0x1 /*!< The DM life-cycle state (LCS) value. */ +#define CC_BSV_SECURE_LCS 0x5 /*!< The Secure life-cycle state (LCS) value. */ +#define CC_BSV_RMA_LCS 0x7 /*!< The RMA life-cycle state (LCS) value. */ +#define CC_BSV_INVALID_LCS 0xff /*!< The invalid life-cycle state (LCS) value. */ + +/*---------------------------- + TYPES +-----------------------------------*/ + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + + +/*! +@brief This function verifies the product and version numbers of the HW, and initializes it. + +\warning This function must be the first CryptoCell-7xx SBROM library API called. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvInit( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function retrieves the HW LCS and performs validity checks. + +If the LCS is RMA, it also sets the OTP secret keys to a fixed value. + +@note An error is returned if there is an invalid LCS. If this happens, your code must +completely disable the device. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvGetAndInitLcs( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint32_t *pLcs /*!< [out] The value of the current LCS. */ + ); + +/*! +@brief This function retrieves the LCS from the NVM manager. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvLcsGet( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint32_t *pLcs /*!< [out] The value of the current LCS. */ + ); + +/*! +@brief This function reads software revocation counter from OTP memory, according to the provided sw version index. +SW version is stored in NVM counter and represented by ones. Meaning seVersion=5 would be stored as binary 0b11111; +hence: + the maximal of trusted is 32 + the maximal of non-trusted is 224 + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSwVersionGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbSwVersionId_t id, /*!< [in] Enumeration defining the trusted/non-trusted counter to read. */ + uint32_t *swVersion /*!< [out] The value of the requested counter as read from OTP memory. */ + ); + +/*! +@brief This function sets the NVM counter according to swVersionID (trusted/non-trusted). + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSwVersionSet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbSwVersionId_t id, /*!< [in] Enumeration defining the trusted/non-trusted counter to read. */ + uint32_t swVersion /*!< [in] New value of the counter to be programmed in OTP memory. */ + ); + +/*! +@brief This function sets the "fatal error" flag in the NVM manager, to disable the use of +any HW keys or security services. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvFatalErrorSet( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function retrieves the public key hash from OTP memory, according to the provided index. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvPubKeyHashGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCSbPubKeyIndexType_t keyIndex, /*!< [in] Enumeration defining the key hash to retrieve: 128-bit HBK0, 128-bit HBK1, or 256-bit HBK. */ + uint32_t *hashedPubKey, /*!< [out] A buffer to contain the public key HASH. */ + uint32_t hashResultSizeWords /*!< [in] The size of the hash in 32-bit words: + - Must be 4 for 128-bit hash. + - Must be 8 for 256bit hash. */ + ); + +/*! +@brief This function permanently sets the RMA LCS for the ICV and the OEM. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRMAModeEnable( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function is called by the ICV code, to disable the OEM code from changing the ICV RMA bit flag. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvICVRMAFlagBitLock( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); + +/*! +@brief This function locks the defined ICV class keys from further usage. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvICVKeyLock( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCBool_t isICVProvisioningKeyLock, /*!< [in] Should the provisioning key be locked. */ + CCBool_t isICVCodeEncKeyLock /*!< [in] Should the encryption key be locked. */ + ); + + +/*! +@brief This function retrieves the value of "secure disable" bit. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSecureDisableGet( + unsigned long hwBaseAddress, /*!< [in] HW registers base address. */ + CCBool_t *isSDEnabled /*!< [out] The value of the SD Enable bit. */ + ); + + +/*! +@brief This function derives the platform key (Kplt) from the Kpicv, and then decrypts the customer key (Kcst) +from the EKcst (burned in the OTP). The decryption is done only in Secure and RMA LCS mode using AES-ECB. +The customer ROM should invoke this function during early boot, prior to running any non-ROM code, only if Kcst exists. +The resulting Kcst is saved in a HW register. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvCustomerKeyDecrypt( + unsigned long hwBaseAddress /*!< [in] The base address of the CryptoCell HW registers. */ + ); +#ifdef __cplusplus +} +#endif + +/*! +@brief This function derives the unique SoC_ID for the device, as hashed (Hbk || AES_CMAC (HUK)). + +@note SoC_ID is required to create debug certificates. + +The OEM or ICV must provide a method for a developer to discover the SoC_ID of a target +device without having to first enable debugging. +One suggested implementation is to have the device ROM code compute the SoC_ID and place +it in a specific location in the flash memory, from where it can be accessed by the developer. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSocIDCompute( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCHashResult_t hashResult /*!< [out] The derived SoC_ID. */ + ); + +#endif /* _BSV_API_H */ + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h new file mode 100644 index 0000000..1e60579 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_API_H +#define _BSV_CRYPTO_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the cryptographic ROM APIs of the Boot Services. + +@defgroup cc_bsv_crypto_api CryptoCell Boot Services cryptographic ROM APIs +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_sec_defs.h" +#include "cc_address_defs.h" +#include "bsv_crypto_defs.h" + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function calculates the SHA-256 digest over contiguous memory +in an integrated operation. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvSha256( + unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + uint8_t *pDataIn, /*!< [in] A pointer to the input buffer to be hashed. The buffer must be contiguous. */ + size_t dataSize, /*!< [in] The size of the data to be hashed, in bytes. */ + CCHashResult_t hashBuff /*!< [out] A pointer to a word-aligned 32-byte buffer. */ + ); + + +/*! +@brief This function allows you to calculate SHA256 digest of an image with decryption base on AES-CTR, +with HW or user key. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. (in this case, hashBuff will be returned clean, while the output data should be cleaned by the user). +*/ +CCError_t CC_BsvCryptoImageDecrypt( unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvflowMode_t flow, /*!< [in] The supported operations are: HASH, AES to HASH, AES and HASH. */ + CCBsvKeyType_t keyType, /*!< [in] The key type to use: Kce, Kceicv, or user key. */ + uint8_t *pUserKey, /*!< [in] A pointer to the user key buffer in case keyType is CC_BSV_USER_KEY. */ + size_t userKeySize, /*!< [in] The user key size in bytes (128bits) in case keyType is CC_BSV_USER_KEY. */ + uint8_t *pIvBuf, /*!< [in] A pointer to the IV / counter buffer. */ + uint8_t *pInputData, /*!< [in] A pointer to the input data. */ + uint8_t *pOutputData, /*!< [out] A pointer to the output buffer. (optional – should be null in case of hash only). */ + size_t dataSize, /*!< [in] The size of the input data in bytes. MUST be multiple of AES block size. */ + CCHashResult_t hashBuff /*!< [out] A pointer to a word-aligned 32-byte digest output buffer. */ + ); + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h new file mode 100644 index 0000000..406e1ef --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_ASYM_API_H +#define _BSV_CRYPTO_ASYM_API_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the cryptographic Asymmetric ROM APIs of the Boot Services. + +@defgroup cc_bsv_crypto_asym_api CryptoCell Boot Services cryptographic Asymmetric ROM APIs +@{ +@ingroup cc_bsv +*/ + +#include "cc_pal_types.h" +#include "cc_pka_hw_plat_defs.h" +#include "cc_sec_defs.h" +#include "bsv_crypto_api.h" + +/*! Defines the workspace size in bytes needed for internal Asymmetric operations. */ +#define BSV_RSA_WORKSPACE_MIN_SIZE (4*BSV_CERT_RSA_KEY_SIZE_IN_BYTES +\ + 2*RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES) + +/*! Definition for the RSA public modulus array. */ +typedef uint32_t CCBsvNBuff_t[BSV_CERT_RSA_KEY_SIZE_IN_WORDS]; + +/*! Definition for the RSA Barrett mod tag array. */ +typedef uint32_t CCBsvNpBuff_t[RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES]; + +/*! Definition for the RSA signature array. */ +typedef uint32_t CCBsvSignature_t[BSV_CERT_RSA_KEY_SIZE_IN_WORDS]; + + +/*---------------------------- + PUBLIC FUNCTIONS +-----------------------------------*/ + +/*! +@brief This function performs the primitive operation of RSA, meaning exponent and modulus. + outBuff = (pInBuff ^ Exp) mod NBuff. ( Exp = 0x10001 ) + + The function supports 2k and 3K bit size of modulus, based on compile time define. + There are no restriction on pInBuff location, however its size must be equal to BSV_RSA_KEY_SIZE_IN_BYTES and its + value must be smaller than the modulus. + + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRsaPrimVerify (unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvNBuff_t NBuff, /*!< [in] The modulus buffer big endian format. */ + CCBsvNpBuff_t NpBuff, /*!< [in] The barret tag buffer big endian format - optional. */ + uint32_t *pInBuff, /*!< [in] The DataIn buffer to be encrypted. */ + size_t inBuffSize, /*!< [in] The DataIn buffer size in bytes, must be BSV_RSA_KEY_SIZE_IN_BYTES. */ + CCBsvSignature_t pOutBuff, /*!< [out] The encrypted buffer in big endian format. */ + uint32_t *pWorkSpace, /*!< [in] The pointer to user allocated buffer for internal use. */ + size_t workBufferSize /*!< [in] The size in bytes of pWorkSpace, must be at-least BSV_RSA_WORKSPACE_MIN_SIZE. */ +); + + +/*! +@brief This function performs RSA PSS verify. + + The function should support 2k and 3K bit size of modulus, based on compile time define. + +@return \c CC_OK on success. +@return A non-zero value from bsv_error.h on failure. +*/ +CCError_t CC_BsvRsaPssVerify (unsigned long hwBaseAddress, /*!< [in] The base address of the CryptoCell HW registers. */ + CCBsvNBuff_t NBuff, /*!< [in] The modulus buffer big endian format. */ + CCBsvNpBuff_t NpBuff, /*!< [in] The barret tag buffer big endian format - optional. */ + CCBsvSignature_t signature, /*!< [in] The signature buffer to verify - big endian format. */ + CCHashResult_t hashedData, /*!< [in] The data-in buffer to be verified as sha256 digest. */ + uint32_t *pWorkSpace, /*!< [in] The pointer to user allocated buffer for internal use. */ + size_t workBufferSize, /*!< [in] The size in bytes of pWorkSpace, must be at-least BSV_RSA_WORKSPACE_MIN_SIZE. */ + CCBool_t *pIsVerified /*!< [out] The flag indicates whether the signature is verified or not. + If verified value will be CC_TRUE, otherwise CC_FALSE */ +); + + + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h new file mode 100644 index 0000000..9ea354d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_CRYPTO_DEFS_H +#define _BSV_CRYPTO_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file contains the definitions of the cryptographic ROM APIs. + +@defgroup cc_bsv_crypto_defs CryptoCell Boot Services cryptographic ROM API definitions +@{ +@ingroup cc_bsv +*/ + +/*! AES supported HW key code table. */ +typedef enum { + + CC_BSV_USER_KEY = 0, /*!< Definition for a user key. */ + CC_BSV_HUK_KEY = 1, /*!< Definition for the HW unique key. */ + CC_BSV_RTL_KEY = 2, /*!< Definition for the RTL key. */ + CC_BSV_SESSION_KEY = 3, /*!< Definition for the Session key. */ + CC_BSV_CE_KEY = 4, /*!< Definition for the Kce. */ + CC_BSV_PLT_KEY = 5, /*!< Definition for the Platform key. */ + CC_BSV_KCST_KEY = 6, /*!< Definition for Kcst. */ + CC_BSV_ICV_PROV_KEY = 0xd, /*!< Definition for the Kpicv. */ + CC_BSV_ICV_CE_KEY = 0xe, /*!< Definition for the Kceicv. */ + CC_BSV_PROV_KEY = 0xf, /*!< Definition for the Kcp. */ + CC_BSV_END_OF_KEY_TYPE = INT32_MAX, /*!< Reserved. */ +}CCBsvKeyType_t; + +/*! AES directions. */ +typedef enum bsvAesDirection { + BSV_AES_DIRECTION_ENCRYPT = 0, /*!< Encrypt.*/ + BSV_AES_DIRECTION_DECRYPT = 1, /*!< Decrypt.*/ + BSV_AES_NUM_OF_ENCRYPT_MODES, /*!< The maximal number of operations. */ + BSV_AES_DIRECTION_RESERVE32B = INT32_MAX /*!< Reserved.*/ +}bsvAesDirection_t; + +/*! Definitions of the cryptographic flow supported as part of the Secure Boot. */ +typedef enum { + CC_BSV_CRYPTO_HASH_MODE = 0, /*!< Hash mode only. */ + CC_BSV_CRYPTO_AES_CTR_AND_HASH_MODE = 1, /*!< Data goes into the AES and Hash engines. */ + CC_BSV_CRYPTO_AES_CTR_TO_HASH_MODE = 2 /*!< Data goes into the AES and from the AES to the Hash engine. */ +}CCBsvflowMode_t; + +/*! CryptoImage HW completion sequence mode */ +typedef enum +{ + BSV_CRYPTO_COMPLETION_NO_WAIT = 0, /*!< The driver waits only before reading the output. */ + BSV_CRYPTO_COMPLETION_WAIT_UPON_END = 1 /*!< The driver waits after each chunk of data. */ +}bsvCryptoCompletionMode_t; + + +/*! AES-CMAC result size, in words. */ +#define CC_BSV_CMAC_RESULT_SIZE_IN_WORDS 4 /* 128b */ +/*! AES-CMAC result size, in bytes. */ +#define CC_BSV_CMAC_RESULT_SIZE_IN_BYTES 16 /* 128b */ +/*! AES-CCM 128bit key size, in bytes. */ +#define CC_BSV_CCM_KEY_SIZE_BYTES 16 +/*! AES-CCM 128bit key size, in words. */ +#define CC_BSV_CCM_KEY_SIZE_WORDS 4 +/*! AES-CCM NONCE size, in bytes. */ +#define CC_BSV_CCM_NONCE_SIZE_BYTES 12 + + +/*! AES-CMAC result buffer. */ +typedef uint32_t CCBsvCmacResult_t[CC_BSV_CMAC_RESULT_SIZE_IN_WORDS]; +/*! AES-CCM key buffer.*/ +typedef uint32_t CCBsvCcmKey_t[CC_BSV_CCM_KEY_SIZE_WORDS]; +/*! AES-CCM nonce buffer.*/ +typedef uint8_t CCBsvCcmNonce_t[CC_BSV_CCM_NONCE_SIZE_BYTES]; +/*! AES-CCM MAC buffer.*/ +typedef uint8_t CCBsvCcmMacRes_t[CC_BSV_CMAC_RESULT_SIZE_IN_BYTES]; + + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h new file mode 100644 index 0000000..4d72e60 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _BSV_ERROR_H +#define _BSV_ERROR_H + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! +@file +@brief This file defines the error code types that are returned from the Boot Services APIs. + +@defgroup cc_bsv_error CryptoCell Boot Services error codes +@{ +@ingroup cc_bsv +*/ + +/*! Defines the base address for Boot Services errors. */ +#define CC_BSV_BASE_ERROR 0x0B000000 +/*! Defines the base address for Boot Services cryptographic errors. */ +#define CC_BSV_CRYPTO_ERROR 0x0C000000 + +/*! Illegal input parameter. */ +#define CC_BSV_ILLEGAL_INPUT_PARAM_ERR (CC_BSV_BASE_ERROR + 0x00000001) +/*! Illegal HUK value. */ +#define CC_BSV_ILLEGAL_HUK_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000002) +/*! Illegal Kcp value. */ +#define CC_BSV_ILLEGAL_KCP_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000003) +/*! Illegal Kce value. */ +#define CC_BSV_ILLEGAL_KCE_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000004) +/*! Illegal Kpicv value. */ +#define CC_BSV_ILLEGAL_KPICV_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000005) +/*! Illegal Kceicv value. */ +#define CC_BSV_ILLEGAL_KCEICV_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000006) +/*! Illegal EKcst value. */ +#define CC_BSV_ILLEGAL_EKCST_VALUE_ERR (CC_BSV_BASE_ERROR + 0x00000007) +/*! Hash boot key not programmed in the OTP. */ +#define CC_BSV_HASH_NOT_PROGRAMMED_ERR (CC_BSV_BASE_ERROR + 0x00000008) +/*! Illegal Hash boot key zero count in the OTP. */ +#define CC_BSV_HBK_ZERO_COUNT_ERR (CC_BSV_BASE_ERROR + 0x00000009) +/*! Illegal LCS. */ +#define CC_BSV_ILLEGAL_LCS_ERR (CC_BSV_BASE_ERROR + 0x0000000A) +/*! OTP write compare failure. */ +#define CC_BSV_OTP_WRITE_CMP_FAIL_ERR (CC_BSV_BASE_ERROR + 0x0000000B) +/*! OTP access error */ +#define CC_BSV_OTP_ACCESS_ERR (CC_BSV_BASE_ERROR + 0x0000000C) +/*! Erase key in OTP failed. */ +#define CC_BSV_ERASE_KEY_FAILED_ERR (CC_BSV_BASE_ERROR + 0x0000000D) +/*! Illegal PIDR. */ +#define CC_BSV_ILLEGAL_PIDR_ERR (CC_BSV_BASE_ERROR + 0x0000000E) +/*! Illegal CIDR. */ +#define CC_BSV_ILLEGAL_CIDR_ERR (CC_BSV_BASE_ERROR + 0x0000000F) +/*! Device failed to move to fatal error state. */ +#define CC_BSV_FAILED_TO_SET_FATAL_ERR (CC_BSV_BASE_ERROR + 0x00000010) +/*! Failed to set RMA LCS. */ +#define CC_BSV_FAILED_TO_SET_RMA_ERR (CC_BSV_BASE_ERROR + 0x00000011) +/*! Illegal RMA indication. */ +#define CC_BSV_ILLEGAL_RMA_INDICATION_ERR (CC_BSV_BASE_ERROR + 0x00000012) +/*! Boot Services version is not initialized. */ +#define CC_BSV_VER_IS_NOT_INITIALIZED_ERR (CC_BSV_BASE_ERROR + 0x00000013) +/*! APB secure mode is locked. */ +#define CC_BSV_APB_SECURE_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000014) +/*! APB privilege mode is locked. */ +#define CC_BSV_APB_PRIVILEG_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000015) +/*! Illegal operation. */ +#define CC_BSV_ILLEGAL_OPERATION_ERR (CC_BSV_BASE_ERROR + 0x00000016) +/*! Illegal asset size. */ +#define CC_BSV_ILLEGAL_ASSET_SIZE_ERR (CC_BSV_BASE_ERROR + 0x00000017) +/*! Illegal asset value. */ +#define CC_BSV_ILLEGAL_ASSET_VAL_ERR (CC_BSV_BASE_ERROR + 0x00000018) +/*! Kpicv is locked. */ +#define CC_BSV_KPICV_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000019) +/*! Illegal SW version. */ +#define CC_BSV_ILLEGAL_SW_VERSION_ERR (CC_BSV_BASE_ERROR + 0x0000001A) +/*! AO write operation. */ +#define CC_BSV_AO_WRITE_FAILED_ERR (CC_BSV_BASE_ERROR + 0x0000001B) +/*! Chip state is already initialized. */ +#define CC_BSV_CHIP_INITIALIZED_ERR (CC_BSV_BASE_ERROR + 0x0000001C) +/*! SP is not enabled. */ +#define CC_BSV_SP_NOT_ENABLED_ERR (CC_BSV_BASE_ERROR + 0x0000001D) +/*! Production secure provisioning - header fields. */ +#define CC_BSV_PROD_PKG_HEADER_ERR (CC_BSV_BASE_ERROR + 0x0000001E) +/*! Production secure provisioning - header MAC. */ +#define CC_BSV_PROD_PKG_HEADER_MAC_ERR (CC_BSV_BASE_ERROR + 0x0000001F) +/*! Overrun buffer or size. */ +#define CC_BSV_OVERRUN_ERR (CC_BSV_BASE_ERROR + 0x00000020) +/*! Kceicv is locked. */ +#define CC_BSV_KCEICV_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000021) +/*! Chip indication is CHIP_STATE_ERROR. */ +#define CC_BSV_CHIP_INDICATION_ERR (CC_BSV_BASE_ERROR + 0x00000022) +/*! Device is locked in fatal error state. */ +#define CC_BSV_FATAL_ERR_IS_LOCKED_ERR (CC_BSV_BASE_ERROR + 0x00000023) +/*! Device has security disable feature enabled. */ +#define CC_BSV_SECURE_DISABLE_ERROR (CC_BSV_BASE_ERROR + 0x00000024) +/*! Device has Kcst in disabled state */ +#define CC_BSV_KCST_DISABLE_ERROR (CC_BSV_BASE_ERROR + 0x00000025) + + +/*! Illegal data-in pointer. */ +#define CC_BSV_CRYPTO_INVALID_DATA_IN_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000001) +/*! Illegal data-out pointer. */ +#define CC_BSV_CRYPTO_INVALID_DATA_OUT_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000002) +/*! Illegal data size. */ +#define CC_BSV_CRYPTO_INVALID_DATA_SIZE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000003) +/*! Illegal key type. */ +#define CC_BSV_CRYPTO_INVALID_KEY_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000004) +/*! Illegal key size. */ +#define CC_BSV_CRYPTO_INVALID_KEY_SIZE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000005) +/*! Invalid key pointer. */ +#define CC_BSV_CRYPTO_INVALID_KEY_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000006) +/*! Illegal key DMA type. */ +#define CC_BSV_CRYPTO_INVALID_KEY_DMA_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000007) +/*! Illegal IV pointer. */ +#define CC_BSV_CRYPTO_INVALID_IV_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000008) +/*! Illegal cipher mode. */ +#define CC_BSV_CRYPTO_INVALID_CIPHER_MODE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000009) +/*! Illegal result buffer pointer. */ +#define CC_BSV_CRYPTO_INVALID_RESULT_BUFFER_POINTER_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000A) +/*! Invalid DMA type. */ +#define CC_BSV_CRYPTO_INVALID_DMA_TYPE_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000B) +/*! Invalid in/out buffers overlapping. */ +#define CC_BSV_CRYPTO_DATA_OUT_DATA_IN_OVERLAP_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000C) +/*! Invalid KDF label size. */ +#define CC_BSV_CRYPTO_ILLEGAL_KDF_LABEL_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000D) +/*! Invalid KDF Context size. */ +#define CC_BSV_CRYPTO_ILLEGAL_KDF_CONTEXT_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000E) +/*! Invalid CCM key. */ +#define CC_BSV_CCM_INVALID_KEY_ERROR (CC_BSV_CRYPTO_ERROR + 0x0000000f) +/*! Invalid CCM Nonce. */ +#define CC_BSV_CCM_INVALID_NONCE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000010) +/*! Invalid CCM associated data. */ +#define CC_BSV_CCM_INVALID_ASSOC_DATA_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000011) +/*! Invalid CCM text data. */ +#define CC_BSV_CCM_INVALID_TEXT_DATA_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000012) +/*! Invalid CCM-MAC buffer. */ +#define CC_BSV_CCM_INVALID_MAC_BUF_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000013) +/*! CCM-MAC comparison failed. */ +#define CC_BSV_CCM_TAG_LENGTH_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000014) +/*! CCM-MAC comparison failed. */ +#define CC_BSV_CCM_MAC_INVALID_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000015) +/*! Illegal flow mode. */ +#define CC_BSV_CRYPTO_INVALID_FLOW_MODE_ERROR (CC_BSV_CRYPTO_ERROR + 0x00000016) + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h new file mode 100644 index 0000000..0abc15c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_ADDRESS_DEFS_H +#define _CC_ADDRESS_DEFS_H + +/*! +@file +@brief This file contains general definitions. +*/ + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/************************ Defines ******************************/ + +/** + * Address types within CC + */ +/*! Definition of DMA address type, can be 32 bits or 64 bits according to CryptoCell's HW. */ +typedef uint64_t CCDmaAddr_t; +/*! Definition of CryptoCell address type, can be 32 bits or 64 bits according to platform. */ +typedef uint64_t CCAddr_t; +/*! Definition of CC SRAM address type, can be 32 bits according to CryptoCell's HW. */ +typedef uint32_t CCSramAddr_t; + +/* + * CCSramAddr_t is being cast into pointer type which can be 64 bit. + */ +/*! Definition of MACRO that casts SRAM addresses to pointer types. */ +#define CCSramAddr2Ptr(sramAddr) ((uintptr_t)sramAddr) + +#ifdef __cplusplus +} +#endif + +#endif + +/** + @} + */ + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h new file mode 100644 index 0000000..4d29a6d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_BOOT_DEFS_H +#define _CC_BOOT_DEFS_H + +/*! + @file + @brief This file contains general definitions of types and enums of Boot APIs. + */ + +#ifdef __cplusplus +extern "C" +{ +#endif + +/*! Version counters value. */ +typedef enum { + + CC_SW_VERSION_TRUSTED = 0, /*!< Trusted counter. */ + CC_SW_VERSION_NON_TRUSTED, /*!< Non trusted counter. */ + CC_SW_VERSION_MAX = 0x7FFFFFFF /*!< Reserved */ +} CCSbSwVersionId_t; + +/*! The hash boot key definition. */ +typedef enum { + CC_SB_HASH_BOOT_KEY_0_128B = 0, /*!< Hbk0: 128-bit truncated SHA-256 digest of PubKB0. Used by ICV */ + CC_SB_HASH_BOOT_KEY_1_128B = 1, /*!< Hbk1: 128-bit truncated SHA-256 digest of PubKB1. Used by OEM */ + CC_SB_HASH_BOOT_KEY_256B = 2, /*!< Hbk: 256-bit SHA-256 digest of public key. */ + CC_SB_HASH_BOOT_NOT_USED = 0xF, /*!< Hbk is not used. */ + CC_SB_HASH_MAX_NUM = 0x7FFFFFFF, /*!< Reserved. */ +} CCSbPubKeyIndexType_t; + +/*! Chip state. */ +typedef enum { + CHIP_STATE_NOT_INITIALIZED = 0, /*! Chip is not initialized. */ + CHIP_STATE_TEST = 1, /*! Chip is in Production state. */ + CHIP_STATE_PRODUCTION = 2, /*! Chip is in Production state. */ + CHIP_STATE_ERROR = 3, /*! Chip is in Error state. */ +} CCBsvChipState_t; +#ifdef __cplusplus +} +#endif + +#endif /*_CC_BOOT_DEFS_H */ + +/** +@} + */ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h new file mode 100644 index 0000000..4ab3960 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CC_PAL_TYPES_H +#define CC_PAL_TYPES_H + +/*! +@file +@brief This file contains platform-dependent definitions and types of the PAL layer. + +@defgroup cc_pal_types CryptoCell platform-dependent PAL layer definitions and types +@{ +@ingroup cc_pal + + @{ + @ingroup cc_pal + @} +*/ + +#include "cc_pal_types_plat.h" + +/*! Definition of Boolean type.*/ +typedef enum { + /*! Boolean false.*/ + CC_FALSE = 0, + /*! Boolean true.*/ + CC_TRUE = 1 +} CCBool_t; + +/*! Success. */ +#define CC_SUCCESS 0UL +/*! Failure. */ +#define CC_FAIL 1UL + +/*! Success (OK). */ +#define CC_OK 0 + +/*! This macro handles unused parameters in the code, to avoid compilation warnings. */ +#define CC_UNUSED_PARAM(prm) ((void)prm) + +/*! The maximal uint32 value.*/ +#define CC_MAX_UINT32_VAL (0xFFFFFFFF) + + +/* Minimal and Maximal macros */ +#ifdef min +/*! Definition for minimal calculation. */ +#define CC_MIN(a,b) min( a , b ) +#else +/*! Definition for minimal calculation. */ +#define CC_MIN( a , b ) ( ( (a) < (b) ) ? (a) : (b) ) +#endif + +#ifdef max +/*! Definition for maximal calculation. */ +#define CC_MAX(a,b) max( a , b ) +#else +/*! Definition for maximal calculation.. */ +#define CC_MAX( a , b ) ( ( (a) > (b) ) ? (a) : (b) ) +#endif + +/*! This macro calculates the number of full Bytes from bits, where seven bits are one Byte. */ +#define CALC_FULL_BYTES(numBits) ((numBits)/CC_BITS_IN_BYTE + (((numBits) & (CC_BITS_IN_BYTE-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from bits where 31 bits are one word. */ +#define CALC_FULL_32BIT_WORDS(numBits) ((numBits)/CC_BITS_IN_32BIT_WORD + (((numBits) & (CC_BITS_IN_32BIT_WORD-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from Bytes where three Bytes are one word. */ +#define CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) ((sizeBytes)/CC_32BIT_WORD_SIZE + (((sizeBytes) & (CC_32BIT_WORD_SIZE-1)) > 0)) +/*! This macro calculates the number of full 32-bit words from 64-bits dwords. */ +#define CALC_32BIT_WORDS_FROM_64BIT_DWORD(sizeWords) (sizeWords * CC_32BIT_WORD_IN_64BIT_DWORD) +/*! This macro rounds up bits to 32-bit words. */ +#define ROUNDUP_BITS_TO_32BIT_WORD(numBits) (CALC_FULL_32BIT_WORDS(numBits) * CC_BITS_IN_32BIT_WORD) +/*! This macro rounds up bits to Bytes. */ +#define ROUNDUP_BITS_TO_BYTES(numBits) (CALC_FULL_BYTES(numBits) * CC_BITS_IN_BYTE) +/*! This macro rounds up bytes to 32-bit words. */ +#define ROUNDUP_BYTES_TO_32BIT_WORD(sizeBytes) (CALC_32BIT_WORDS_FROM_BYTES(sizeBytes) * CC_32BIT_WORD_SIZE) +/*! This macro calculates the number Bytes from words. */ +#define CALC_WORDS_TO_BYTES(numwords) ((numwords)*CC_32BIT_WORD_SIZE) +/*! Definition of 1 KB in Bytes. */ +#define CC_1K_SIZE_IN_BYTES 1024 +/*! Definition of number of bits in a Byte. */ +#define CC_BITS_IN_BYTE 8 +/*! Definition of number of bits in a 32-bits word. */ +#define CC_BITS_IN_32BIT_WORD 32 +/*! Definition of number of Bytes in a 32-bits word. */ +#define CC_32BIT_WORD_SIZE 4 +/*! Definition of number of 32-bits words in a 64-bits dword. */ +#define CC_32BIT_WORD_IN_64BIT_DWORD 2 + + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h new file mode 100644 index 0000000..9848472 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/*! @file +@brief This file contains basic type definitions that are platform-dependent. +*/ +#ifndef _CC_PAL_TYPES_PLAT_H +#define _CC_PAL_TYPES_PLAT_H +/* Host specific types for standard (ISO-C99) compilant platforms */ + +#include +#include + +typedef uint32_t CCStatus; + +#define CCError_t CCStatus +#define CC_INFINITE 0xFFFFFFFF + +#define CEXPORT_C +#define CIMPORT_C + +#endif /*_CC_PAL_TYPES_PLAT_H*/ diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h new file mode 100644 index 0000000..1a1bce0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_PKA_HW_PLAT_DEFS_H +#define _CC_PKA_HW_PLAT_DEFS_H + +#ifdef __cplusplus +extern "C" +{ +#endif + + +#include "cc_pal_types.h" +/*! +@file +@brief Contains the enums and definitions that are used in the PKA code (definitions that are platform dependent). +*/ + +/*! The size of the PKA engine word. */ +#define CC_PKA_WORD_SIZE_IN_BITS 128 + +/*! The maximal supported size of modulus in RSA in bits. */ +#define CC_RSA_MAX_VALID_KEY_SIZE_VALUE_IN_BITS 4096 +/*! The maximal supported size of key-generation in RSA in bits. */ +#define CC_RSA_MAX_KEY_GENERATION_HW_SIZE_BITS 4096 + +/*! Secure boot/debug certificate RSA public modulus key size in bits. */ +#if (KEY_SIZE == 3072) + #define BSV_CERT_RSA_KEY_SIZE_IN_BITS 3072 +#else + #define BSV_CERT_RSA_KEY_SIZE_IN_BITS 2048 +#endif +/*! Secure boot/debug certificate RSA public modulus key size in bytes. */ +#define BSV_CERT_RSA_KEY_SIZE_IN_BYTES (BSV_CERT_RSA_KEY_SIZE_IN_BITS/CC_BITS_IN_BYTE) +/*! Secure boot/debug certificate RSA public modulus key size in words. */ +#define BSV_CERT_RSA_KEY_SIZE_IN_WORDS (BSV_CERT_RSA_KEY_SIZE_IN_BITS/CC_BITS_IN_32BIT_WORD) + +/*! The maximal count of extra bits in PKA operations. */ +#define PKA_EXTRA_BITS 8 +/*! The number of memory registers in PKA operations. */ +#define PKA_MAX_COUNT_OF_PHYS_MEM_REGS 32 + +/*! Size of buffer for Barrett modulus tag in words. */ +#define RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS 5 +/*! Size of buffer for Barrett modulus tag in bytes. */ +#define RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_BYTES (RSA_PKA_BARRETT_MOD_TAG_BUFF_SIZE_IN_WORDS*CC_32BIT_WORD_SIZE) + + + +#ifdef __cplusplus +} +#endif + +#endif //_CC_PKA_HW_PLAT_DEFS_H + +/** + @} + */ + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h new file mode 100644 index 0000000..8fb698f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2020 ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_SEC_DEFS_H +#define _CC_SEC_DEFS_H + +/*! +@file +@brief This file contains general definitions and types. +*/ + + +#ifdef __cplusplus +extern "C" +{ +#endif + +#include "cc_pal_types.h" + +/*! Hashblock size in words. */ +#define HASH_BLOCK_SIZE_IN_WORDS 16 +/*! Hash - SHA2 results in words. */ +#define HASH_RESULT_SIZE_IN_WORDS 8 +/*! Hash - SHA2 results in bytes. */ +#define HASH_RESULT_SIZE_IN_BYTES 32 + +/*! Definition for hash result array. */ +typedef uint32_t CCHashResult_t[HASH_RESULT_SIZE_IN_WORDS]; + +/*! Definition for converting pointer to Host address. */ +#define CONVERT_TO_ADDR(ptr) (unsigned long)ptr + +/*! Definition for converting pointer to SRAM address. */ +#define CONVERT_TO_SRAM_ADDR(ptr) (0xFFFFFFFF & ptr) + +/*! The data size of the signed SW image, in bytes. */ +/*!\internal ContentCertImageRecord_t includes: HS(8W) + 64-b dstAddr(2W) + imgSize(1W) + isCodeEncUsed(1W) */ +#define SW_REC_SIGNED_DATA_SIZE_IN_BYTES 48 + +/*! The data size of the unsigned SW image, in bytes. */ +/*!\internal CCSbSwImgAddData_t includes: 64-b srcAddr(2W)*/ +#define SW_REC_NONE_SIGNED_DATA_SIZE_IN_BYTES 8 + +/*! The additional data size - storage address and length of the unsigned SW image, in words. */ +#define SW_REC_NONE_SIGNED_DATA_SIZE_IN_WORDS SW_REC_NONE_SIGNED_DATA_SIZE_IN_BYTES/CC_32BIT_WORD_SIZE + +/*! The additional data section size, in bytes. */ +#define CC_SB_MAX_SIZE_ADDITIONAL_DATA_BYTES 128 + +/*! Indication of whether or not to load the SW image to memory. */ +#define CC_SW_COMP_NO_MEM_LOAD_INDICATION 0xFFFFFFFFFFFFFFFFUL + +/*! Indication of product version, stored in certificate version field. */ +#define CC_SB_CERT_VERSION_PROJ_PRD 0x713 + +#ifdef __cplusplus +} +#endif + +#endif + +/** +@} + */ + + + diff --git a/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h b/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h new file mode 100644 index 0000000..9398496 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef _CC_ROTPK_H +#define _CC_ROTPK_H + +int cc_get_rotpk_hash(unsigned char *dst, unsigned int len, + unsigned int *flags); + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h b/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h new file mode 100644 index 0000000..ff04ae4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_mhu.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_MHU_H +#define CSS_MHU_H + +#include + +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 /* CSS_MHU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h b/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h new file mode 100644 index 0000000..88302fd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_MHU_DOORBELL_H +#define CSS_MHU_DOORBELL_H + +#include + +#include + +/* MHUv2 Frame Base Mask */ +#define MHU_V2_FRAME_BASE_MASK UL(~0xFFF) + +/* MHUv2 Control Registers Offsets */ +#define MHU_V2_MSG_NO_CAP_OFFSET UL(0xF80) +#define MHU_V2_ACCESS_REQ_OFFSET UL(0xF88) +#define MHU_V2_ACCESS_READY_OFFSET UL(0xF8C) + +#define SENDER_REG_STAT(_channel) (0x20 * (_channel)) +#define SENDER_REG_SET(_channel) ((0x20 * (_channel)) + 0xC) + +/* Helper macro to ring doorbell */ +#define MHU_RING_DOORBELL(addr, modify_mask, preserve_mask) do { \ + uint32_t db = mmio_read_32(addr) & (preserve_mask); \ + mmio_write_32(addr, db | (modify_mask)); \ + } while (0) + +#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) + +struct scmi_channel_plat_info; +void mhu_ring_doorbell(struct scmi_channel_plat_info *plat_info); +void mhuv2_ring_doorbell(struct scmi_channel_plat_info *plat_info); + +#endif /* CSS_MHU_DOORBELL_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_scp.h b/arm-trusted-firmware/include/drivers/arm/css/css_scp.h new file mode 100644 index 0000000..2b506ea --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_scp.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_SCP_H +#define CSS_SCP_H + +#include + +#include + +#include + +/* Forward declarations */ +struct psci_power_state; + +/* API for power management by SCP */ +int css_system_reset2(int is_vendor, int reset_type, u_register_t cookie); +void css_scp_suspend(const struct psci_power_state *target_state); +void css_scp_off(const struct psci_power_state *target_state); +void css_scp_on(u_register_t mpidr); +int css_scp_get_power_state(u_register_t mpidr, unsigned int power_level); +void __dead2 css_scp_sys_shutdown(void); +void __dead2 css_scp_sys_reboot(void); +void __dead2 css_scp_system_off(int state); + +/* API for SCP Boot Image transfer. Return 0 on success, -1 on error */ +int css_scp_boot_image_xfer(void *image, unsigned int image_size); + +/* + * API to wait for SCP to signal till it's ready after booting the transferred + * image. + */ +int css_scp_boot_ready(void); + +#if CSS_LOAD_SCP_IMAGES + +/* + * All CSS platforms load SCP_BL2/SCP_BL2U just below BL2 (this is where BL31 + * usually resides except when ARM_BL31_IN_DRAM is + * set). Ensure that SCP_BL2/SCP_BL2U do not overflow into fw_config. + */ +CASSERT(SCP_BL2_LIMIT <= BL2_BASE, assert_scp_bl2_overwrite_bl2); +CASSERT(SCP_BL2U_LIMIT <= BL2_BASE, assert_scp_bl2u_overwrite_bl2); + +CASSERT(SCP_BL2_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2_overflow); +CASSERT(SCP_BL2U_BASE >= ARM_FW_CONFIG_LIMIT, assert_scp_bl2u_overflow); +#endif + +#endif /* CSS_SCP_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h b/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h new file mode 100644 index 0000000..68fc60a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/css_scpi.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_SCPI_H +#define CSS_SCPI_H + +#include +#include + +/* + * 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_CSS_POWER_STATE = 0x03, + SCPI_CMD_GET_CSS_POWER_STATE = 0x04, + SCPI_CMD_SYS_POWER_STATE = 0x05 +} scpi_command_t; + +/* + * Macros to parse SCP response to GET_CSS_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_CSS_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; + +int scpi_wait_ready(void); +void scpi_set_css_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_css_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 /* CSS_SCPI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/scmi.h b/arm-trusted-firmware/include/drivers/arm/css/scmi.h new file mode 100644 index 0000000..9dd08e5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/scmi.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCMI_H +#define SCMI_H + +#include +#include + +#include +#include +#include + +/* Supported SCMI Protocol Versions */ +#define SCMI_AP_CORE_PROTO_VER MAKE_SCMI_VERSION(1, 0) +#define SCMI_PWR_DMN_PROTO_VER MAKE_SCMI_VERSION(2, 0) +#define SCMI_SYS_PWR_PROTO_VER MAKE_SCMI_VERSION(1, 0) + +#define GET_SCMI_MAJOR_VER(ver) (((ver) >> 16) & 0xffff) +#define GET_SCMI_MINOR_VER(ver) ((ver) & 0xffff) + +#define MAKE_SCMI_VERSION(maj, min) \ + ((((maj) & 0xffff) << 16) | ((min) & 0xffff)) + +/* + * Check that the driver's version is same or higher than the reported SCMI + * version. We accept lower major version numbers, as all affected protocols + * so far stay backwards compatible. This might need to be revisited in the + * future. + */ +#define is_scmi_version_compatible(drv, scmi) \ + ((GET_SCMI_MAJOR_VER(drv) > GET_SCMI_MAJOR_VER(scmi)) || \ + ((GET_SCMI_MAJOR_VER(drv) == GET_SCMI_MAJOR_VER(scmi)) && \ + (GET_SCMI_MINOR_VER(drv) <= GET_SCMI_MINOR_VER(scmi)))) + +/* SCMI Protocol identifiers */ +#define SCMI_PWR_DMN_PROTO_ID 0x11 +#define SCMI_SYS_PWR_PROTO_ID 0x12 +/* The AP core protocol is a CSS platform-specific extension */ +#define SCMI_AP_CORE_PROTO_ID 0x90 + +/* Mandatory messages IDs for all SCMI protocols */ +#define SCMI_PROTO_VERSION_MSG 0x0 +#define SCMI_PROTO_ATTR_MSG 0x1 +#define SCMI_PROTO_MSG_ATTR_MSG 0x2 + +/* SCMI power domain management protocol message IDs */ +#define SCMI_PWR_STATE_SET_MSG 0x4 +#define SCMI_PWR_STATE_GET_MSG 0x5 + +/* SCMI system power management protocol message IDs */ +#define SCMI_SYS_PWR_STATE_SET_MSG 0x3 +#define SCMI_SYS_PWR_STATE_GET_MSG 0x4 + +/* SCMI AP core protocol message IDs */ +#define SCMI_AP_CORE_RESET_ADDR_SET_MSG 0x3 +#define SCMI_AP_CORE_RESET_ADDR_GET_MSG 0x4 + +/* Helper macros for system power management protocol commands */ + +/* + * Macros to describe the bit-fields of the `attribute` of system power domain + * protocol PROTOCOL_MSG_ATTRIBUTE message. + */ +#define SYS_PWR_ATTR_WARM_RESET_SHIFT 31 +#define SCMI_SYS_PWR_WARM_RESET_SUPPORTED (1U << SYS_PWR_ATTR_WARM_RESET_SHIFT) + +#define SYS_PWR_ATTR_SUSPEND_SHIFT 30 +#define SCMI_SYS_PWR_SUSPEND_SUPPORTED (1 << SYS_PWR_ATTR_SUSPEND_SHIFT) + +/* + * Macros to describe the bit-fields of the `flags` parameter of system power + * domain protocol SYSTEM_POWER_STATE_SET message. + */ +#define SYS_PWR_SET_GRACEFUL_REQ_SHIFT 0 +#define SCMI_SYS_PWR_GRACEFUL_REQ (1 << SYS_PWR_SET_GRACEFUL_REQ_SHIFT) +#define SCMI_SYS_PWR_FORCEFUL_REQ (0 << SYS_PWR_SET_GRACEFUL_REQ_SHIFT) + +/* + * Macros to describe the `system_state` parameter of system power + * domain protocol SYSTEM_POWER_STATE_SET message. + */ +#define SCMI_SYS_PWR_SHUTDOWN 0x0 +#define SCMI_SYS_PWR_COLD_RESET 0x1 +#define SCMI_SYS_PWR_WARM_RESET 0x2 +#define SCMI_SYS_PWR_POWER_UP 0x3 +#define SCMI_SYS_PWR_SUSPEND 0x4 + +/* + * Macros to describe the bit-fields of the `attribute` of AP core protocol + * AP_CORE_RESET_ADDR set/get messages. + */ +#define SCMI_AP_CORE_LOCK_ATTR_SHIFT 0x0 +#define SCMI_AP_CORE_LOCK_ATTR (1U << SCMI_AP_CORE_LOCK_ATTR_SHIFT) + +/* SCMI Error code definitions */ +#define SCMI_E_QUEUED 1 +#define SCMI_E_SUCCESS 0 +#define SCMI_E_NOT_SUPPORTED -1 +#define SCMI_E_INVALID_PARAM -2 +#define SCMI_E_DENIED -3 +#define SCMI_E_NOT_FOUND -4 +#define SCMI_E_OUT_OF_RANGE -5 +#define SCMI_E_BUSY -6 + +/* + * SCMI driver platform information. The details of the doorbell mechanism + * can be found in the SCMI specification. + */ +typedef struct scmi_channel_plat_info { + /* SCMI mailbox memory */ + uintptr_t scmi_mbx_mem; + /* The door bell register address */ + uintptr_t db_reg_addr; + /* The bit mask that need to be preserved when ringing doorbell */ + uint32_t db_preserve_mask; + /* The bit mask that need to be set to ring doorbell */ + uint32_t db_modify_mask; + /* The handler for ringing doorbell */ + void (*ring_doorbell)(struct scmi_channel_plat_info *plat_info); + /* cookie is unused now. But added for future enhancements. */ + void *cookie; +} scmi_channel_plat_info_t; + + +#if HW_ASSISTED_COHERENCY +typedef spinlock_t scmi_lock_t; +#else +typedef bakery_lock_t scmi_lock_t; +#endif + +/* + * Structure to represent an SCMI channel. + */ +typedef struct scmi_channel { + scmi_channel_plat_info_t *info; + /* The lock for channel access */ + scmi_lock_t *lock; + /* Indicate whether the channel is initialized */ + int is_initialized; +} scmi_channel_t; + +/* External Common API */ +void *scmi_init(scmi_channel_t *ch); +int scmi_proto_msg_attr(void *p, uint32_t proto_id, uint32_t command_id, + uint32_t *attr); +int scmi_proto_version(void *p, uint32_t proto_id, uint32_t *version); + +/* + * Power domain protocol commands. Refer to the SCMI specification for more + * details on these commands. + */ +int scmi_pwr_state_set(void *p, uint32_t domain_id, uint32_t scmi_pwr_state); +int scmi_pwr_state_get(void *p, uint32_t domain_id, uint32_t *scmi_pwr_state); + +/* + * System power management protocol commands. Refer SCMI specification for more + * details on these commands. + */ +int scmi_sys_pwr_state_set(void *p, uint32_t flags, uint32_t system_state); +int scmi_sys_pwr_state_get(void *p, uint32_t *system_state); + +/* SCMI AP core configuration protocol commands. */ +int scmi_ap_core_set_reset_addr(void *p, uint64_t reset_addr, uint32_t attr); +int scmi_ap_core_get_reset_addr(void *p, uint64_t *reset_addr, uint32_t *attr); + +/* API to get the platform specific SCMI channel information. */ +scmi_channel_plat_info_t *plat_css_get_scmi_info(int channel_id); + +/* API to override default PSCI callbacks for platforms that support SCMI. */ +const plat_psci_ops_t *css_scmi_override_pm_ops(plat_psci_ops_t *ops); + +#endif /* SCMI_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/css/sds.h b/arm-trusted-firmware/include/drivers/arm/css/sds.h new file mode 100644 index 0000000..db4cbaa --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/css/sds.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDS_H +#define SDS_H + +/* SDS Structure Identifier defines */ +/* AP CPU INFO defines */ +#define SDS_AP_CPU_INFO_STRUCT_ID 1 +#define SDS_AP_CPU_INFO_PRIMARY_CPUID_OFFSET 0x0 +#define SDS_AP_CPU_INFO_PRIMARY_CPUID_SIZE 0x4 + +/* ROM Firmware Version defines */ +#define SDS_ROM_VERSION_STRUCT_ID 2 +#define SDS_ROM_VERSION_OFFSET 0x0 +#define SDS_ROM_VERSION_SIZE 0x4 + +/* RAM Firmware version defines */ +#define SDS_RAM_VERSION_STRUCT_ID 3 +#define SDS_RAM_VERSION_OFFSET 0x0 +#define SDS_RAM_VERSION_SIZE 0x4 + +/* Platform Identity defines */ +#define SDS_PLATFORM_IDENTITY_STRUCT_ID 4 +#define SDS_PLATFORM_IDENTITY_ID_OFFSET 0x0 +#define SDS_PLATFORM_IDENTITY_ID_SIZE 0x4 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_SHIFT 28 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH 4 +#define SDS_PLATFORM_IDENTITY_ID_CONFIG_MASK \ + ((1 << SDS_PLATFORM_IDENTITY_ID_CONFIG_WIDTH) - 1) + +#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_OFFSET 0x4 +#define SDS_PLATFORM_IDENTITY_PLAT_TYPE_SIZE 0x4 + +/* Reset Syndrome defines */ +#define SDS_RESET_SYNDROME_STRUCT_ID 5 +#define SDS_RESET_SYNDROME_OFFSET 0 +#define SDS_RESET_SYNDROME_SIZE 4 +#define SDS_RESET_SYNDROME_POW_ON_RESET_BIT (1 << 0) +#define SDS_RESET_SYNDROME_SCP_WD_RESET_BIT (1 << 1) +#define SDS_RESET_SYNDROME_AP_WD_RESET_BIT (1 << 2) +#define SDS_RESET_SYNDROME_SYS_RESET_REQ_BIT (1 << 3) +#define SDS_RESET_SYNDROME_M3_LOCKUP_BIT (1 << 4) + +/* SCP Firmware Feature Availability defines */ +#define SDS_FEATURE_AVAIL_STRUCT_ID 6 +#define SDS_FEATURE_AVAIL_OFFSET 0 +#define SDS_FEATURE_AVAIL_SIZE 4 +#define SDS_FEATURE_AVAIL_SCP_RAM_READY_BIT (1 << 0) +#define SDS_FEATURE_AVAIL_DMC_READY_BIT (1 << 1) +#define SDS_FEATURE_AVAIL_MSG_IF_READY_BIT (1 << 2) + +/* SCP BL2 Image Metadata defines */ +#define SDS_SCP_IMG_STRUCT_ID 9 +#define SDS_SCP_IMG_FLAG_OFFSET 0 +#define SDS_SCP_IMG_FLAG_SIZE 4 +#define SDS_SCP_IMG_VALID_FLAG_BIT (1 << 0) +#define SDS_SCP_IMG_ADDR_OFFSET 4 +#define SDS_SCP_IMG_ADDR_SIZE 4 +#define SDS_SCP_IMG_SIZE_OFFSET 8 +#define SDS_SCP_IMG_SIZE_SIZE 4 + +/* SDS Driver Error Codes */ +#define SDS_OK 0 +#define SDS_ERR_FAIL -1 +#define SDS_ERR_INVALID_PARAMS -2 +#define SDS_ERR_STRUCT_NOT_FOUND -3 +#define SDS_ERR_STRUCT_NOT_FINALIZED -4 + +#ifndef __ASSEMBLER__ +#include +#include + +typedef enum { + SDS_ACCESS_MODE_NON_CACHED, + SDS_ACCESS_MODE_CACHED, +} sds_access_mode_t; + +int sds_init(void); +int sds_struct_exists(unsigned int structure_id); +int sds_struct_read(uint32_t structure_id, unsigned int fld_off, void *data, + size_t size, sds_access_mode_t mode); +int sds_struct_write(uint32_t structure_id, unsigned int fld_off, void *data, + size_t size, sds_access_mode_t mode); +#endif /*__ASSEMBLER__ */ + +#endif /* SDS_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/dcc.h b/arm-trusted-firmware/include/drivers/arm/dcc.h new file mode 100644 index 0000000..1f1fd03 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/dcc.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Xilinx Inc. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DCC_H +#define DCC_H + +#include +#include + +/* + * Initialize a new dcc console instance and register it with the console + * framework. + */ +int console_dcc_register(void); + +#endif /* DCC */ diff --git a/arm-trusted-firmware/include/drivers/arm/dsu.h b/arm-trusted-firmware/include/drivers/arm/dsu.h new file mode 100644 index 0000000..ad4a1f0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/dsu.h @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DSU_H +#define DSU_H + +#include + +#include + +#include + +/******************************************************************************* + * DSU Power Policy Unit registers + ******************************************************************************/ +#define PPU_PWPR U(0x000) +#define PPU_PMER U(0x004) +#define PPU_PWSR U(0x008) +#define PPU_DISR U(0x010) +#define PPU_MISR U(0x014) +#define PPU_STSR U(0x018) +#define PPU_UNLK U(0x01C) +#define PPU_PWCR U(0x020) +#define PPU_PTCR U(0x024) +#define PPU_IMR U(0x030) +#define PPU_AIMR U(0x034) +#define PPU_ISR U(0x038) +#define PPU_AISR U(0x03C) +#define PPU_IESR U(0x040) +#define PPU_OPSR U(0x044) +#define PPU_FUNRR U(0x050) +#define PPU_FULRR U(0x054) +#define PPU_MEMRR U(0x058) +#define PPU_DCDR0 U(0x170) +#define PPU_DCDR1 U(0x174) +#define PPU_IDR0 U(0xFB0) +#define PPU_IDR1 U(0xFB4) +#define PPU_IIDR U(0xFC8) +#define PPU_AIDR U(0xFCC) +#define PPU_PIDR4 U(0xFD0) +#define PPU_PIDR5 U(0xFD4) +#define PPU_PIDR6 U(0xFD8) +#define PPU_PIDR7 U(0xFDC) +#define PPU_PIDR0 U(0xFE0) +#define PPU_PIDR1 U(0xFE4) +#define PPU_PIDR2 U(0xFE8) +#define PPU_PIDR3 U(0xFEC) +#define PPU_CIDR0 U(0xFF0) +#define PPU_CIDR1 U(0xFF4) +#define PPU_CIDR2 U(0xFF8) +#define PPU_CIDR3 U(0xFFC) + +/******************************************************************************* + * PPU_PWPR and PPU_PWSR constants + ******************************************************************************/ +#define OP_DYN_EN_BIT BIT(24) +#define OP_POLICY_MODE_00 U(0x0) +#define OP_POLICY_MODE_01 U(0x1) +#define OP_POLICY_MODE_03 U(0x3) +#define OP_POLICY_MODE_04 U(0x4) +#define OP_POLICY_MODE_05 U(0x5) +#define OP_POLICY_MODE_07 U(0x7) +#define OP_POLICY_MODE_SHIFT U(16) +#define OP_POLICY_MODE_MASK U(0xF) +#define LOCK_EN_BIT BIT(12) +#define PWR_DYN_EN_BIT BIT(8) +#define PWR_POLICY_OFF U(0x0) +#define PWR_POLICY_OFF_EMU U(0x1) +#define PWR_POLICY_MEM_RET U(0x2) +#define PWR_POLICY_MEM_RET__EMU U(0x3) +#define PWR_POLICY_OFF_FUNC_RET U(0x7) +#define PWR_POLICY_ON U(0x8) +#define PWR_POLICY_WARM_RST U(0x9) +#define PWR_POLICY_DBG_RECOV U(0x10) +#define PWR_POLICY_SHIFT U(0) +#define PWR_POLICY_MASK U(0xF) + +/******************************************************************************* + * Helper macros + ******************************************************************************/ +#define PPU_REGION_SIZE U(0x100000) +#define CLUSTER_PPU_BASE(n) ((PPU_REGION_SIZE * n) + U(0x30000)) +#define CORE_PPU_BASE(n) ((PPU_REGION_SIZE * n) + U(0x80000)) + +/******************************************************************************* + * Accessor functions + ******************************************************************************/ +static inline void dsu_ppu_cluster_write_32(uint32_t core_pos, + uint64_t ub_base, uint32_t offset, uint32_t value) +{ + uint64_t base = ub_base + CLUSTER_PPU_BASE(core_pos); + + mmio_write_32(base + offset, value); +} + +static inline uint32_t dsu_ppu_cluster_read_32(uint32_t core_pos, + uint64_t ub_base, uint32_t offset) +{ + uint64_t base = ub_base + CLUSTER_PPU_BASE(core_pos); + + return mmio_read_32(base + offset); +} + +static inline void dsu_ppu_core_write_32(uint32_t core_pos, uint64_t ub_base, + uint32_t offset, uint32_t value) +{ + uint64_t base = ub_base + CORE_PPU_BASE(core_pos); + + mmio_write_32(base + offset, value); +} + +static inline uint32_t dsu_ppu_core_read_32(uint32_t core_pos, uint64_t ub_base, + uint32_t offset) +{ + uint64_t base = ub_base + CORE_PPU_BASE(core_pos); + + return mmio_read_32(base + offset); +} + +/******************************************************************************* + * Public functions + ******************************************************************************/ +int dsu_ppu_setup(uint64_t base, uint64_t per_socket_mmio_size, + unsigned int num_cpus_per_socket); +int dsu_ppu_core_power_on(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr); +int dsu_ppu_core_power_off(uint32_t socket, uint32_t core, + uint32_t cluster_ppu_pwpr, uint32_t core_ppu_pwpr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/arm/ethosn.h b/arm-trusted-firmware/include/drivers/arm/ethosn.h new file mode 100644 index 0000000..9310733 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/ethosn.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ETHOSN_H +#define ETHOSN_H + +#include + +/* Function numbers */ +#define ETHOSN_FNUM_VERSION U(0x50) +#define ETHOSN_FNUM_IS_SEC U(0x51) +#define ETHOSN_FNUM_HARD_RESET U(0x52) +#define ETHOSN_FNUM_SOFT_RESET U(0x53) +/* 0x54-0x5F reserved for future use */ + +/* SMC64 function IDs */ +#define ETHOSN_FID_64(func_num) U(0xC2000000 | func_num) +#define ETHOSN_FID_VERSION_64 ETHOSN_FID_64(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_64 ETHOSN_FID_64(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_64 ETHOSN_FID_64(ETHOSN_FNUM_SOFT_RESET) + +/* SMC32 function IDs */ +#define ETHOSN_FID_32(func_num) U(0x82000000 | func_num) +#define ETHOSN_FID_VERSION_32 ETHOSN_FID_32(ETHOSN_FNUM_VERSION) +#define ETHOSN_FID_IS_SEC_32 ETHOSN_FID_32(ETHOSN_FNUM_IS_SEC) +#define ETHOSN_FID_HARD_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_HARD_RESET) +#define ETHOSN_FID_SOFT_RESET_32 ETHOSN_FID_32(ETHOSN_FNUM_SOFT_RESET) + +#define ETHOSN_NUM_SMC_CALLS 8 + +/* Macro to identify function calls */ +#define ETHOSN_FID_MASK U(0xFFF0) +#define ETHOSN_FID_VALUE U(0x50) +#define is_ethosn_fid(_fid) (((_fid) & ETHOSN_FID_MASK) == ETHOSN_FID_VALUE) + +/* Service version */ +#define ETHOSN_VERSION_MAJOR U(1) +#define ETHOSN_VERSION_MINOR U(0) + +/* Return codes for function calls */ +#define ETHOSN_SUCCESS 0 +#define ETHOSN_NOT_SUPPORTED -1 +/* -2 Reserved for NOT_REQUIRED */ +/* -3 Reserved for INVALID_PARAMETER */ +#define ETHOSN_FAILURE -4 +#define ETHOSN_UNKNOWN_CORE_ADDRESS -5 + +uintptr_t ethosn_smc_handler(uint32_t smc_fid, + u_register_t core_addr, + u_register_t x2, + u_register_t x3, + u_register_t x4, + void *cookie, + void *handle, + u_register_t flags); + +#endif /* ETHOSN_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h b/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h new file mode 100644 index 0000000..39e2516 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_PWRC_H +#define FVP_PWRC_H + +/* FVP Power controller register offset etc */ +#define PPOFFR_OFF U(0x0) +#define PPONR_OFF U(0x4) +#define PCOFFR_OFF U(0x8) +#define PWKUPR_OFF U(0xc) +#define PSYSR_OFF U(0x10) + +#define PWKUPR_WEN BIT_32(31) + +#define PSYSR_AFF_L2 BIT_32(31) +#define PSYSR_AFF_L1 BIT_32(30) +#define PSYSR_AFF_L0 BIT_32(29) +#define PSYSR_WEN BIT_32(28) +#define PSYSR_PC BIT_32(27) +#define PSYSR_PP BIT_32(26) + +#define PSYSR_WK_SHIFT 24 +#define PSYSR_WK_WIDTH 0x2 +#define PSYSR_WK_MASK ((1U << PSYSR_WK_WIDTH) - 1U) +#define PSYSR_WK(x) ((x) >> PSYSR_WK_SHIFT) & PSYSR_WK_MASK + +#define WKUP_COLD U(0x0) +#define WKUP_RESET U(0x1) +#define WKUP_PPONR U(0x2) +#define WKUP_GICREQ U(0x3) + +#define PSYSR_INVALID U(0xffffffff) + +#ifndef __ASSEMBLER__ + +#include + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void fvp_pwrc_write_pcoffr(u_register_t mpidr); +void fvp_pwrc_write_ppoffr(u_register_t mpidr); +void fvp_pwrc_write_pponr(u_register_t mpidr); +void fvp_pwrc_set_wen(u_register_t mpidr); +void fvp_pwrc_clr_wen(u_register_t mpidr); +unsigned int fvp_pwrc_read_psysr(u_register_t mpidr); +unsigned int fvp_pwrc_get_cpu_wkr(u_register_t mpidr); + +#endif /*__ASSEMBLER__*/ + +#endif /* FVP_PWRC_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gic600_multichip.h b/arm-trusted-firmware/include/drivers/arm/gic600_multichip.h new file mode 100644 index 0000000..bda406b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gic600_multichip.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600_MULTICHIP_H +#define GIC600_MULTICHIP_H + +#include + +/* + * GIC-600 microarchitecture supports coherent multichip environments containing + * up to 16 chips. + */ +#define GIC600_MAX_MULTICHIP 16 + +/* SPI IDs array consist of min and max ids */ +#define GIC600_SPI_IDS_SIZE 2 + +/******************************************************************************* + * GIC-600 multichip data structure describes platform specific attributes + * related to GIC-600 multichip. Platform port is expected to define these + * attributes to initialize the multichip related registers and create + * successful connections between the GIC-600s in a multichip system. + * + * The 'rt_owner_base' field contains the base address of the GIC Distributor + * which owns the routing table. + * + * The 'rt_owner' field contains the chip number which owns the routing table. + * Chip number or chip_id starts from 0. + * + * The 'chip_count' field contains the total number of chips in a multichip + * system. This should match the number of entries in 'chip_addrs' and 'spi_ids' + * fields. + * + * The 'chip_addrs' field contains array of chip addresses. These addresses are + * implementation specific values. + * + * The 'spi_ids' field contains array of minimum and maximum SPI interrupt ids + * that each chip owns. Note that SPI interrupt ids can range from 32 to 960 and + * it should be group of 32 (i.e., SPI minimum and (SPI maximum + 1) should be + * a multiple of 32). If a chip doesn't own any SPI interrupts a value of {0, 0} + * should be passed. + ******************************************************************************/ +struct gic600_multichip_data { + uintptr_t rt_owner_base; + unsigned int rt_owner; + unsigned int chip_count; + uint64_t chip_addrs[GIC600_MAX_MULTICHIP]; + unsigned int spi_ids[GIC600_MAX_MULTICHIP][GIC600_SPI_IDS_SIZE]; +}; + +void gic600_multichip_init(struct gic600_multichip_data *multichip_data); +#endif /* GIC600_MULTICHIP_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h b/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h new file mode 100644 index 0000000..88b87b9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2021-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC600AE_FMU_H +#define GIC600AE_FMU_H + +/******************************************************************************* + * GIC600-AE FMU register offsets and constants + ******************************************************************************/ +#define GICFMU_ERRFR_LO U(0x000) +#define GICFMU_ERRFR_HI U(0x004) +#define GICFMU_ERRCTLR_LO U(0x008) +#define GICFMU_ERRCTLR_HI U(0x00C) +#define GICFMU_ERRSTATUS_LO U(0x010) +#define GICFMU_ERRSTATUS_HI U(0x014) +#define GICFMU_ERRGSR_LO U(0xE00) +#define GICFMU_ERRGSR_HI U(0xE04) +#define GICFMU_KEY U(0xEA0) +#define GICFMU_PINGCTLR U(0xEA4) +#define GICFMU_PINGNOW U(0xEA8) +#define GICFMU_SMEN U(0xEB0) +#define GICFMU_SMINJERR U(0xEB4) +#define GICFMU_PINGMASK_LO U(0xEC0) +#define GICFMU_PINGMASK_HI U(0xEC4) +#define GICFMU_STATUS U(0xF00) +#define GICFMU_ERRIDR U(0xFC8) + +/* ERRCTLR bits */ +#define FMU_ERRCTLR_ED_BIT BIT(0) +#define FMU_ERRCTLR_CE_EN_BIT BIT(1) +#define FMU_ERRCTLR_UI_BIT BIT(2) +#define FMU_ERRCTLR_CI_BIT BIT(3) + +/* SMEN constants */ +#define FMU_SMEN_BLK_SHIFT U(8) +#define FMU_SMEN_SMID_SHIFT U(24) +#define FMU_SMEN_EN_BIT BIT(0) + +/* Error record IDs */ +#define FMU_BLK_GICD U(0) +#define FMU_BLK_SPICOL U(1) +#define FMU_BLK_WAKERQ U(2) +#define FMU_BLK_ITS0 U(4) +#define FMU_BLK_ITS1 U(5) +#define FMU_BLK_ITS2 U(6) +#define FMU_BLK_ITS3 U(7) +#define FMU_BLK_ITS4 U(8) +#define FMU_BLK_ITS5 U(9) +#define FMU_BLK_ITS6 U(10) +#define FMU_BLK_ITS7 U(11) +#define FMU_BLK_PPI0 U(12) +#define FMU_BLK_PPI1 U(13) +#define FMU_BLK_PPI2 U(14) +#define FMU_BLK_PPI3 U(15) +#define FMU_BLK_PPI4 U(16) +#define FMU_BLK_PPI5 U(17) +#define FMU_BLK_PPI6 U(18) +#define FMU_BLK_PPI7 U(19) +#define FMU_BLK_PPI8 U(20) +#define FMU_BLK_PPI9 U(21) +#define FMU_BLK_PPI10 U(22) +#define FMU_BLK_PPI11 U(23) +#define FMU_BLK_PPI12 U(24) +#define FMU_BLK_PPI13 U(25) +#define FMU_BLK_PPI14 U(26) +#define FMU_BLK_PPI15 U(27) +#define FMU_BLK_PPI16 U(28) +#define FMU_BLK_PPI17 U(29) +#define FMU_BLK_PPI18 U(30) +#define FMU_BLK_PPI19 U(31) +#define FMU_BLK_PPI20 U(32) +#define FMU_BLK_PPI21 U(33) +#define FMU_BLK_PPI22 U(34) +#define FMU_BLK_PPI23 U(35) +#define FMU_BLK_PPI24 U(36) +#define FMU_BLK_PPI25 U(37) +#define FMU_BLK_PPI26 U(38) +#define FMU_BLK_PPI27 U(39) +#define FMU_BLK_PPI28 U(40) +#define FMU_BLK_PPI29 U(41) +#define FMU_BLK_PPI30 U(42) +#define FMU_BLK_PPI31 U(43) +#define FMU_BLK_PRESENT_MASK U(0xFFFFFFFFFFF) + +/* Safety Mechamism limit */ +#define FMU_SMID_GICD_MAX U(33) +#define FMU_SMID_PPI_MAX U(12) +#define FMU_SMID_ITS_MAX U(14) +#define FMU_SMID_SPICOL_MAX U(5) +#define FMU_SMID_WAKERQ_MAX U(2) + +/* MBIST Safety Mechanism ID */ +#define GICD_MBIST_REQ_ERROR U(23) +#define GICD_FMU_CLKGATE_ERROR U(33) +#define PPI_MBIST_REQ_ERROR U(10) +#define PPI_FMU_CLKGATE_ERROR U(12) +#define ITS_MBIST_REQ_ERROR U(13) +#define ITS_FMU_CLKGATE_ERROR U(14) + +/* ERRSTATUS bits */ +#define FMU_ERRSTATUS_BLKID_SHIFT U(32) +#define FMU_ERRSTATUS_BLKID_MASK U(0xFF) +#define FMU_ERRSTATUS_V_BIT BIT(30) +#define FMU_ERRSTATUS_UE_BIT BIT(29) +#define FMU_ERRSTATUS_OV_BIT BIT(27) +#define FMU_ERRSTATUS_CE_BITS (BIT(25) | BIT(24)) +#define FMU_ERRSTATUS_CLEAR (FMU_ERRSTATUS_V_BIT | FMU_ERRSTATUS_UE_BIT | \ + FMU_ERRSTATUS_OV_BIT | FMU_ERRSTATUS_CE_BITS) +#define FMU_ERRSTATUS_IERR_MASK U(0xFF) +#define FMU_ERRSTATUS_IERR_SHIFT U(8) +#define FMU_ERRSTATUS_SERR_MASK U(0xFF) + +/* PINGCTLR constants */ +#define FMU_PINGCTLR_INTDIFF_SHIFT U(16) +#define FMU_PINGCTLR_TIMEOUTVAL_SHIFT U(4) +#define FMU_PINGCTLR_EN_BIT BIT(0) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/******************************************************************************* + * GIC600 FMU EL3 driver API + ******************************************************************************/ +uint64_t gic_fmu_read_errfr(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errctlr(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errstatus(uintptr_t base, unsigned int n); +uint64_t gic_fmu_read_errgsr(uintptr_t base); +uint32_t gic_fmu_read_pingctlr(uintptr_t base); +uint32_t gic_fmu_read_pingnow(uintptr_t base); +uint64_t gic_fmu_read_pingmask(uintptr_t base); +uint32_t gic_fmu_read_status(uintptr_t base); +uint32_t gic_fmu_read_erridr(uintptr_t base); +void gic_fmu_write_errctlr(uintptr_t base, unsigned int n, uint64_t val); +void gic_fmu_write_errstatus(uintptr_t base, unsigned int n, uint64_t val); +void gic_fmu_write_pingctlr(uintptr_t base, uint32_t val); +void gic_fmu_write_pingnow(uintptr_t base, uint32_t val); +void gic_fmu_write_smen(uintptr_t base, uint32_t val); +void gic_fmu_write_sminjerr(uintptr_t base, uint32_t val); +void gic_fmu_write_pingmask(uintptr_t base, uint64_t val); +void gic_fmu_disable_all_sm_blkid(uintptr_t base, unsigned int blkid); + +void gic600_fmu_init(uint64_t base, uint64_t blk_present_mask, bool errctlr_ce_en, bool errctlr_ue_en); +void gic600_fmu_enable_ping(uint64_t base, uint64_t blk_present_mask, + unsigned int timeout_val, unsigned int interval_diff); +void gic600_fmu_print_sm_info(uint64_t base, unsigned int blk, unsigned int smid); +int gic600_fmu_probe(uint64_t base, int *probe_data); +int gic600_fmu_ras_handler(uint64_t base, int probe_data); + +#endif /* __ASSEMBLER__ */ + +#endif /* GIC600AE_FMU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gic_common.h b/arm-trusted-firmware/include/drivers/arm/gic_common.h new file mode 100644 index 0000000..c385708 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gic_common.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GIC_COMMON_H +#define GIC_COMMON_H + +#include + +/******************************************************************************* + * GIC Distributor interface general definitions + ******************************************************************************/ +/* Constants to categorise interrupts */ +#define MIN_SGI_ID U(0) +#define MIN_SEC_SGI_ID U(8) +#define MIN_PPI_ID U(16) +#define MIN_SPI_ID U(32) +#define MAX_SPI_ID U(1019) + +#define TOTAL_SPI_INTR_NUM (MAX_SPI_ID - MIN_SPI_ID + U(1)) +#define TOTAL_PCPU_INTR_NUM (MIN_SPI_ID - MIN_SGI_ID) + +/* Mask for the priority field common to all GIC interfaces */ +#define GIC_PRI_MASK U(0xff) + +/* Mask for the configuration field common to all GIC interfaces */ +#define GIC_CFG_MASK U(0x3) + +/* Constant to indicate a spurious interrupt in all GIC versions */ +#define GIC_SPURIOUS_INTERRUPT U(1023) + +/* Interrupt configurations: 2-bit fields with LSB reserved */ +#define GIC_INTR_CFG_LEVEL (0 << 1) +#define GIC_INTR_CFG_EDGE (1 << 1) + +/* Highest possible interrupt priorities */ +#define GIC_HIGHEST_SEC_PRIORITY U(0x00) +#define GIC_HIGHEST_NS_PRIORITY U(0x80) + +/******************************************************************************* + * Common GIC Distributor interface register offsets + ******************************************************************************/ +#define GICD_CTLR U(0x0) +#define GICD_TYPER U(0x4) +#define GICD_IIDR U(0x8) +#define GICD_SAC U(0x24) +#define GICD_IGROUPR U(0x80) +#define GICD_ISENABLER U(0x100) +#define GICD_ICENABLER U(0x180) +#define GICD_ISPENDR U(0x200) +#define GICD_ICPENDR U(0x280) +#define GICD_ISACTIVER U(0x300) +#define GICD_ICACTIVER U(0x380) +#define GICD_IPRIORITYR U(0x400) +#define GICD_ICFGR U(0xc00) +#define GICD_NSACR U(0xe00) + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G0_SHIFT 0 +#define CTLR_ENABLE_G0_MASK U(0x1) +#define CTLR_ENABLE_G0_BIT BIT_32(CTLR_ENABLE_G0_SHIFT) + +/* GICD_SAC bit definitions */ +#define SAC_GICTNS BIT(1) +#define SAC_GICPNS BIT(2) + +/******************************************************************************* + * Common GIC Distributor interface register constants + ******************************************************************************/ +#define PIDR2_ARCH_REV_SHIFT 4 +#define PIDR2_ARCH_REV_MASK U(0xf) + +/* GIC revision as reported by PIDR2.ArchRev register field */ +#define ARCH_REV_GICV1 U(0x1) +#define ARCH_REV_GICV2 U(0x2) +#define ARCH_REV_GICV3 U(0x3) +#define ARCH_REV_GICV4 U(0x4) + +#define IGROUPR_SHIFT 5 +#define ISENABLER_SHIFT 5 +#define ICENABLER_SHIFT ISENABLER_SHIFT +#define ISPENDR_SHIFT 5 +#define ICPENDR_SHIFT ISPENDR_SHIFT +#define ISACTIVER_SHIFT 5 +#define ICACTIVER_SHIFT ISACTIVER_SHIFT +#define IPRIORITYR_SHIFT 2 +#define ITARGETSR_SHIFT 2 +#define ICFGR_SHIFT 4 +#define NSACR_SHIFT 4 + +/* GICD_TYPER shifts and masks */ +#define TYPER_IT_LINES_NO_SHIFT U(0) +#define TYPER_IT_LINES_NO_MASK U(0x1f) + +/* Value used to initialize Normal world interrupt priorities four at a time */ +#define GICD_IPRIORITYR_DEF_VAL \ + (GIC_HIGHEST_NS_PRIORITY | \ + (GIC_HIGHEST_NS_PRIORITY << 8) | \ + (GIC_HIGHEST_NS_PRIORITY << 16) | \ + (GIC_HIGHEST_NS_PRIORITY << 24)) + +#endif /* GIC_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gicv2.h b/arm-trusted-firmware/include/drivers/arm/gicv2.h new file mode 100644 index 0000000..b960194 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gicv2.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV2_H +#define GICV2_H + +#include +#include + +/******************************************************************************* + * GICv2 miscellaneous definitions + ******************************************************************************/ + +/* Interrupt group definitions */ +#define GICV2_INTR_GROUP0 U(0) +#define GICV2_INTR_GROUP1 U(1) + +/* Interrupt IDs reported by the HPPIR and IAR registers */ +#define PENDING_G1_INTID U(1022) + +/* GICv2 can only target up to 8 PEs */ +#define GICV2_MAX_TARGET_PE U(8) + +/******************************************************************************* + * GICv2 specific Distributor interface register offsets and constants. + ******************************************************************************/ +#define GICD_ITARGETSR U(0x800) +#define GICD_SGIR U(0xF00) +#define GICD_CPENDSGIR U(0xF10) +#define GICD_SPENDSGIR U(0xF20) + +/* + * Some GICv2 implementations violate the specification and have this register + * at a different address. Allow overriding it in platform_def.h as workaround. + */ +#ifndef GICD_PIDR2_GICV2 +#define GICD_PIDR2_GICV2 U(0xFE8) +#endif + +#define ITARGETSR_SHIFT 2 +#define GIC_TARGET_CPU_MASK U(0xff) + +#define CPENDSGIR_SHIFT 2 +#define SPENDSGIR_SHIFT CPENDSGIR_SHIFT + +#define SGIR_TGTLSTFLT_SHIFT 24 +#define SGIR_TGTLSTFLT_MASK U(0x3) +#define SGIR_TGTLST_SHIFT 16 +#define SGIR_TGTLST_MASK U(0xff) +#define SGIR_INTID_MASK ULL(0xf) + +#define SGIR_TGT_SPECIFIC U(0) + +#define GICV2_SGIR_VALUE(tgt_lst_flt, tgt, intid) \ + ((((tgt_lst_flt) & SGIR_TGTLSTFLT_MASK) << SGIR_TGTLSTFLT_SHIFT) | \ + (((tgt) & SGIR_TGTLST_MASK) << SGIR_TGTLST_SHIFT) | \ + ((intid) & SGIR_INTID_MASK)) + +/******************************************************************************* + * GICv2 specific CPU interface register offsets and constants. + ******************************************************************************/ +/* Physical CPU Interface registers */ +#define GICC_CTLR U(0x0) +#define GICC_PMR U(0x4) +#define GICC_BPR U(0x8) +#define GICC_IAR U(0xC) +#define GICC_EOIR U(0x10) +#define GICC_RPR U(0x14) +#define GICC_HPPIR U(0x18) +#define GICC_AHPPIR U(0x28) +#define GICC_IIDR U(0xFC) +#define GICC_DIR U(0x1000) +#define GICC_PRIODROP GICC_EOIR + +/* GICC_CTLR bit definitions */ +#define EOI_MODE_NS BIT_32(10) +#define EOI_MODE_S BIT_32(9) +#define IRQ_BYP_DIS_GRP1 BIT_32(8) +#define FIQ_BYP_DIS_GRP1 BIT_32(7) +#define IRQ_BYP_DIS_GRP0 BIT_32(6) +#define FIQ_BYP_DIS_GRP0 BIT_32(5) +#define CBPR BIT_32(4) +#define FIQ_EN_SHIFT 3 +#define FIQ_EN_BIT BIT_32(FIQ_EN_SHIFT) +#define ACK_CTL BIT_32(2) + +/* GICC_IIDR bit masks and shifts */ +#define GICC_IIDR_PID_SHIFT 20 +#define GICC_IIDR_ARCH_SHIFT 16 +#define GICC_IIDR_REV_SHIFT 12 +#define GICC_IIDR_IMP_SHIFT 0 + +#define GICC_IIDR_PID_MASK U(0xfff) +#define GICC_IIDR_ARCH_MASK U(0xf) +#define GICC_IIDR_REV_MASK U(0xf) +#define GICC_IIDR_IMP_MASK U(0xfff) + +/* HYP view virtual CPU Interface registers */ +#define GICH_CTL U(0x0) +#define GICH_VTR U(0x4) +#define GICH_ELRSR0 U(0x30) +#define GICH_ELRSR1 U(0x34) +#define GICH_APR0 U(0xF0) +#define GICH_LR_BASE U(0x100) + +/* Virtual CPU Interface registers */ +#define GICV_CTL U(0x0) +#define GICV_PRIMASK U(0x4) +#define GICV_BP U(0x8) +#define GICV_INTACK U(0xC) +#define GICV_EOI U(0x10) +#define GICV_RUNNINGPRI U(0x14) +#define GICV_HIGHESTPEND U(0x18) +#define GICV_DEACTIVATE U(0x1000) + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G1_SHIFT 1 +#define CTLR_ENABLE_G1_MASK U(0x1) +#define CTLR_ENABLE_G1_BIT BIT_32(CTLR_ENABLE_G1_SHIFT) + +/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */ +#define INT_ID_MASK U(0x3ff) + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +/******************************************************************************* + * This structure describes some of the implementation defined attributes of + * the GICv2 IP. It is used by the platform port to specify these attributes + * in order to initialize the GICv2 driver. The attributes are described + * below. + * + * The 'gicd_base' field contains the base address of the Distributor interface + * programmer's view. + * + * The 'gicc_base' field contains the base address of the CPU Interface + * programmer's view. + * + * The 'target_masks' is a pointer to an array containing 'target_masks_num' + * elements. The GIC driver will populate the array with per-PE target mask to + * use to when targeting interrupts. + * + * The 'interrupt_props' field is a pointer to an array that enumerates secure + * interrupts and their properties. If this field is not NULL, both + * 'g0_interrupt_array' and 'g1s_interrupt_array' fields are ignored. + * + * The 'interrupt_props_num' field contains the number of entries in the + * 'interrupt_props' array. If this field is non-zero, 'g0_interrupt_num' is + * ignored. + ******************************************************************************/ +typedef struct gicv2_driver_data { + uintptr_t gicd_base; + uintptr_t gicc_base; + unsigned int *target_masks; + unsigned int target_masks_num; + const interrupt_prop_t *interrupt_props; + unsigned int interrupt_props_num; +} gicv2_driver_data_t; + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void gicv2_driver_init(const gicv2_driver_data_t *plat_driver_data); +void gicv2_distif_init(void); +void gicv2_pcpu_distif_init(void); +void gicv2_cpuif_enable(void); +void gicv2_cpuif_disable(void); +unsigned int gicv2_is_fiq_enabled(void); +unsigned int gicv2_get_pending_interrupt_type(void); +unsigned int gicv2_get_pending_interrupt_id(void); +unsigned int gicv2_acknowledge_interrupt(void); +void gicv2_end_of_interrupt(unsigned int id); +unsigned int gicv2_get_interrupt_group(unsigned int id); +unsigned int gicv2_get_running_priority(void); +void gicv2_set_pe_target_mask(unsigned int proc_num); +unsigned int gicv2_get_interrupt_active(unsigned int id); +void gicv2_enable_interrupt(unsigned int id); +void gicv2_disable_interrupt(unsigned int id); +void gicv2_set_interrupt_priority(unsigned int id, unsigned int priority); +void gicv2_set_interrupt_type(unsigned int id, unsigned int type); +void gicv2_raise_sgi(int sgi_num, int proc_num); +void gicv2_set_spi_routing(unsigned int id, int proc_num); +void gicv2_set_interrupt_pending(unsigned int id); +void gicv2_clear_interrupt_pending(unsigned int id); +unsigned int gicv2_set_pmr(unsigned int mask); +void gicv2_interrupt_set_cfg(unsigned int id, unsigned int cfg); + +#endif /* __ASSEMBLER__ */ +#endif /* GICV2_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/gicv3.h b/arm-trusted-firmware/include/drivers/arm/gicv3.h new file mode 100644 index 0000000..5efefb6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/gicv3.h @@ -0,0 +1,547 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GICV3_H +#define GICV3_H + +/******************************************************************************* + * GICv3 and 3.1 miscellaneous definitions + ******************************************************************************/ +/* Interrupt group definitions */ +#define INTR_GROUP1S U(0) +#define INTR_GROUP0 U(1) +#define INTR_GROUP1NS U(2) + +/* Interrupt IDs reported by the HPPIR and IAR registers */ +#define PENDING_G1S_INTID U(1020) +#define PENDING_G1NS_INTID U(1021) + +/* Constant to categorize LPI interrupt */ +#define MIN_LPI_ID U(8192) + +/* GICv3 can only target up to 16 PEs with SGI */ +#define GICV3_MAX_SGI_TARGETS U(16) + +/* PPIs INTIDs 16-31 */ +#define MAX_PPI_ID U(31) + +#if GIC_EXT_INTID + +/* GICv3.1 extended PPIs INTIDs 1056-1119 */ +#define MIN_EPPI_ID U(1056) +#define MAX_EPPI_ID U(1119) + +/* Total number of GICv3.1 EPPIs */ +#define TOTAL_EPPI_INTR_NUM (MAX_EPPI_ID - MIN_EPPI_ID + U(1)) + +/* Total number of GICv3.1 PPIs and EPPIs */ +#define TOTAL_PRIVATE_INTR_NUM (TOTAL_PCPU_INTR_NUM + TOTAL_EPPI_INTR_NUM) + +/* GICv3.1 extended SPIs INTIDs 4096 - 5119 */ +#define MIN_ESPI_ID U(4096) +#define MAX_ESPI_ID U(5119) + +/* Total number of GICv3.1 ESPIs */ +#define TOTAL_ESPI_INTR_NUM (MAX_ESPI_ID - MIN_ESPI_ID + U(1)) + +/* Total number of GICv3.1 SPIs and ESPIs */ +#define TOTAL_SHARED_INTR_NUM (TOTAL_SPI_INTR_NUM + TOTAL_ESPI_INTR_NUM) + +/* SGIs: 0-15, PPIs: 16-31, EPPIs: 1056-1119 */ +#define IS_SGI_PPI(id) (((id) <= MAX_PPI_ID) || \ + (((id) >= MIN_EPPI_ID) && \ + ((id) <= MAX_EPPI_ID))) + +/* SPIs: 32-1019, ESPIs: 4096-5119 */ +#define IS_SPI(id) ((((id) >= MIN_SPI_ID) && \ + ((id) <= MAX_SPI_ID)) || \ + (((id) >= MIN_ESPI_ID) && \ + ((id) <= MAX_ESPI_ID))) +#else /* GICv3 */ + +/* Total number of GICv3 PPIs */ +#define TOTAL_PRIVATE_INTR_NUM TOTAL_PCPU_INTR_NUM + +/* Total number of GICv3 SPIs */ +#define TOTAL_SHARED_INTR_NUM TOTAL_SPI_INTR_NUM + +/* SGIs: 0-15, PPIs: 16-31 */ +#define IS_SGI_PPI(id) ((id) <= MAX_PPI_ID) + +/* SPIs: 32-1019 */ +#define IS_SPI(id) (((id) >= MIN_SPI_ID) && ((id) <= MAX_SPI_ID)) + +#endif /* GIC_EXT_INTID */ + +/******************************************************************************* + * GICv3 and 3.1 specific Distributor interface register offsets and constants + ******************************************************************************/ +#define GICD_TYPER2 U(0x0c) +#define GICD_STATUSR U(0x10) +#define GICD_SETSPI_NSR U(0x40) +#define GICD_CLRSPI_NSR U(0x48) +#define GICD_SETSPI_SR U(0x50) +#define GICD_CLRSPI_SR U(0x58) +#define GICD_IGRPMODR U(0xd00) +#define GICD_IGROUPRE U(0x1000) +#define GICD_ISENABLERE U(0x1200) +#define GICD_ICENABLERE U(0x1400) +#define GICD_ISPENDRE U(0x1600) +#define GICD_ICPENDRE U(0x1800) +#define GICD_ISACTIVERE U(0x1a00) +#define GICD_ICACTIVERE U(0x1c00) +#define GICD_IPRIORITYRE U(0x2000) +#define GICD_ICFGRE U(0x3000) +#define GICD_IGRPMODRE U(0x3400) +#define GICD_NSACRE U(0x3600) +/* + * GICD_IROUTER register is at 0x6000 + 8n, where n is the interrupt ID + * and n >= 32, making the effective offset as 0x6100 + */ +#define GICD_IROUTER U(0x6000) +#define GICD_IROUTERE U(0x8000) + +#define GICD_PIDR0_GICV3 U(0xffe0) +#define GICD_PIDR1_GICV3 U(0xffe4) +#define GICD_PIDR2_GICV3 U(0xffe8) + +#define IGRPMODR_SHIFT 5 + +/* GICD_CTLR bit definitions */ +#define CTLR_ENABLE_G1NS_SHIFT 1 +#define CTLR_ENABLE_G1S_SHIFT 2 +#define CTLR_ARE_S_SHIFT 4 +#define CTLR_ARE_NS_SHIFT 5 +#define CTLR_DS_SHIFT 6 +#define CTLR_E1NWF_SHIFT 7 +#define GICD_CTLR_RWP_SHIFT 31 + +#define CTLR_ENABLE_G1NS_MASK U(0x1) +#define CTLR_ENABLE_G1S_MASK U(0x1) +#define CTLR_ARE_S_MASK U(0x1) +#define CTLR_ARE_NS_MASK U(0x1) +#define CTLR_DS_MASK U(0x1) +#define CTLR_E1NWF_MASK U(0x1) +#define GICD_CTLR_RWP_MASK U(0x1) + +#define CTLR_ENABLE_G1NS_BIT BIT_32(CTLR_ENABLE_G1NS_SHIFT) +#define CTLR_ENABLE_G1S_BIT BIT_32(CTLR_ENABLE_G1S_SHIFT) +#define CTLR_ARE_S_BIT BIT_32(CTLR_ARE_S_SHIFT) +#define CTLR_ARE_NS_BIT BIT_32(CTLR_ARE_NS_SHIFT) +#define CTLR_DS_BIT BIT_32(CTLR_DS_SHIFT) +#define CTLR_E1NWF_BIT BIT_32(CTLR_E1NWF_SHIFT) +#define GICD_CTLR_RWP_BIT BIT_32(GICD_CTLR_RWP_SHIFT) + +/* GICD_IROUTER shifts and masks */ +#define IROUTER_SHIFT 0 +#define IROUTER_IRM_SHIFT 31 +#define IROUTER_IRM_MASK U(0x1) + +#define GICV3_IRM_PE U(0) +#define GICV3_IRM_ANY U(1) + +#define NUM_OF_DIST_REGS 30 + +/* GICD_TYPER shifts and masks */ +#define TYPER_ESPI U(1 << 8) +#define TYPER_DVIS U(1 << 18) +#define TYPER_ESPI_RANGE_MASK U(0x1f) +#define TYPER_ESPI_RANGE_SHIFT U(27) +#define TYPER_ESPI_RANGE U(TYPER_ESPI_MASK << TYPER_ESPI_SHIFT) + +/******************************************************************************* + * Common GIC Redistributor interface registers & constants + ******************************************************************************/ +#define GICR_V4_PCPUBASE_SHIFT 0x12 +#define GICR_V3_PCPUBASE_SHIFT 0x11 +#define GICR_SGIBASE_OFFSET U(65536) /* 64 KB */ +#define GICR_CTLR U(0x0) +#define GICR_IIDR U(0x04) +#define GICR_TYPER U(0x08) +#define GICR_STATUSR U(0x10) +#define GICR_WAKER U(0x14) +#define GICR_PROPBASER U(0x70) +#define GICR_PENDBASER U(0x78) +#define GICR_IGROUPR0 (GICR_SGIBASE_OFFSET + U(0x80)) +#define GICR_ISENABLER0 (GICR_SGIBASE_OFFSET + U(0x100)) +#define GICR_ICENABLER0 (GICR_SGIBASE_OFFSET + U(0x180)) +#define GICR_ISPENDR0 (GICR_SGIBASE_OFFSET + U(0x200)) +#define GICR_ICPENDR0 (GICR_SGIBASE_OFFSET + U(0x280)) +#define GICR_ISACTIVER0 (GICR_SGIBASE_OFFSET + U(0x300)) +#define GICR_ICACTIVER0 (GICR_SGIBASE_OFFSET + U(0x380)) +#define GICR_IPRIORITYR (GICR_SGIBASE_OFFSET + U(0x400)) +#define GICR_ICFGR0 (GICR_SGIBASE_OFFSET + U(0xc00)) +#define GICR_ICFGR1 (GICR_SGIBASE_OFFSET + U(0xc04)) +#define GICR_IGRPMODR0 (GICR_SGIBASE_OFFSET + U(0xd00)) +#define GICR_NSACR (GICR_SGIBASE_OFFSET + U(0xe00)) + +#define GICR_IGROUPR GICR_IGROUPR0 +#define GICR_ISENABLER GICR_ISENABLER0 +#define GICR_ICENABLER GICR_ICENABLER0 +#define GICR_ISPENDR GICR_ISPENDR0 +#define GICR_ICPENDR GICR_ICPENDR0 +#define GICR_ISACTIVER GICR_ISACTIVER0 +#define GICR_ICACTIVER GICR_ICACTIVER0 +#define GICR_ICFGR GICR_ICFGR0 +#define GICR_IGRPMODR GICR_IGRPMODR0 + +/* GICR_CTLR bit definitions */ +#define GICR_CTLR_UWP_SHIFT 31 +#define GICR_CTLR_UWP_MASK U(0x1) +#define GICR_CTLR_UWP_BIT BIT_32(GICR_CTLR_UWP_SHIFT) +#define GICR_CTLR_RWP_SHIFT 3 +#define GICR_CTLR_RWP_MASK U(0x1) +#define GICR_CTLR_RWP_BIT BIT_32(GICR_CTLR_RWP_SHIFT) +#define GICR_CTLR_EN_LPIS_BIT BIT_32(0) + +/* GICR_WAKER bit definitions */ +#define WAKER_CA_SHIFT 2 +#define WAKER_PS_SHIFT 1 + +#define WAKER_CA_MASK U(0x1) +#define WAKER_PS_MASK U(0x1) + +#define WAKER_CA_BIT BIT_32(WAKER_CA_SHIFT) +#define WAKER_PS_BIT BIT_32(WAKER_PS_SHIFT) + +/* GICR_TYPER bit definitions */ +#define TYPER_AFF_VAL_SHIFT 32 +#define TYPER_PROC_NUM_SHIFT 8 +#define TYPER_LAST_SHIFT 4 +#define TYPER_VLPI_SHIFT 1 + +#define TYPER_AFF_VAL_MASK U(0xffffffff) +#define TYPER_PROC_NUM_MASK U(0xffff) +#define TYPER_LAST_MASK U(0x1) + +#define TYPER_LAST_BIT BIT_32(TYPER_LAST_SHIFT) +#define TYPER_VLPI_BIT BIT_32(TYPER_VLPI_SHIFT) + +#define TYPER_PPI_NUM_SHIFT U(27) +#define TYPER_PPI_NUM_MASK U(0x1f) + +/* GICR_IIDR bit definitions */ +#define IIDR_PRODUCT_ID_MASK U(0xff000000) +#define IIDR_VARIANT_MASK U(0x000f0000) +#define IIDR_REVISION_MASK U(0x0000f000) +#define IIDR_IMPLEMENTER_MASK U(0x00000fff) +#define IIDR_MODEL_MASK (IIDR_PRODUCT_ID_MASK | \ + IIDR_IMPLEMENTER_MASK) + +/******************************************************************************* + * GICv3 and 3.1 CPU interface registers & constants + ******************************************************************************/ +/* ICC_SRE bit definitions */ +#define ICC_SRE_EN_BIT BIT_32(3) +#define ICC_SRE_DIB_BIT BIT_32(2) +#define ICC_SRE_DFB_BIT BIT_32(1) +#define ICC_SRE_SRE_BIT BIT_32(0) + +/* ICC_IGRPEN1_EL3 bit definitions */ +#define IGRPEN1_EL3_ENABLE_G1NS_SHIFT 0 +#define IGRPEN1_EL3_ENABLE_G1S_SHIFT 1 + +#define IGRPEN1_EL3_ENABLE_G1NS_BIT BIT_32(IGRPEN1_EL3_ENABLE_G1NS_SHIFT) +#define IGRPEN1_EL3_ENABLE_G1S_BIT BIT_32(IGRPEN1_EL3_ENABLE_G1S_SHIFT) + +/* ICC_IGRPEN0_EL1 bit definitions */ +#define IGRPEN1_EL1_ENABLE_G0_SHIFT 0 +#define IGRPEN1_EL1_ENABLE_G0_BIT BIT_32(IGRPEN1_EL1_ENABLE_G0_SHIFT) + +/* ICC_HPPIR0_EL1 bit definitions */ +#define HPPIR0_EL1_INTID_SHIFT 0 +#define HPPIR0_EL1_INTID_MASK U(0xffffff) + +/* ICC_HPPIR1_EL1 bit definitions */ +#define HPPIR1_EL1_INTID_SHIFT 0 +#define HPPIR1_EL1_INTID_MASK U(0xffffff) + +/* ICC_IAR0_EL1 bit definitions */ +#define IAR0_EL1_INTID_SHIFT 0 +#define IAR0_EL1_INTID_MASK U(0xffffff) + +/* ICC_IAR1_EL1 bit definitions */ +#define IAR1_EL1_INTID_SHIFT 0 +#define IAR1_EL1_INTID_MASK U(0xffffff) + +/* ICC SGI macros */ +#define SGIR_TGT_MASK ULL(0xffff) +#define SGIR_AFF1_SHIFT 16 +#define SGIR_INTID_SHIFT 24 +#define SGIR_INTID_MASK ULL(0xf) +#define SGIR_AFF2_SHIFT 32 +#define SGIR_IRM_SHIFT 40 +#define SGIR_IRM_MASK ULL(0x1) +#define SGIR_AFF3_SHIFT 48 +#define SGIR_AFF_MASK ULL(0xf) + +#define SGIR_IRM_TO_AFF U(0) + +#define GICV3_SGIR_VALUE(_aff3, _aff2, _aff1, _intid, _irm, _tgt) \ + ((((uint64_t) (_aff3) & SGIR_AFF_MASK) << SGIR_AFF3_SHIFT) | \ + (((uint64_t) (_irm) & SGIR_IRM_MASK) << SGIR_IRM_SHIFT) | \ + (((uint64_t) (_aff2) & SGIR_AFF_MASK) << SGIR_AFF2_SHIFT) | \ + (((_intid) & SGIR_INTID_MASK) << SGIR_INTID_SHIFT) | \ + (((_aff1) & SGIR_AFF_MASK) << SGIR_AFF1_SHIFT) | \ + ((_tgt) & SGIR_TGT_MASK)) + +/***************************************************************************** + * GICv3 and 3.1 ITS registers and constants + *****************************************************************************/ +#define GITS_CTLR U(0x0) +#define GITS_IIDR U(0x4) +#define GITS_TYPER U(0x8) +#define GITS_CBASER U(0x80) +#define GITS_CWRITER U(0x88) +#define GITS_CREADR U(0x90) +#define GITS_BASER U(0x100) + +/* GITS_CTLR bit definitions */ +#define GITS_CTLR_ENABLED_BIT BIT_32(0) +#define GITS_CTLR_QUIESCENT_BIT BIT_32(1) + +#define GITS_TYPER_VSGI BIT_64(39) + +#ifndef __ASSEMBLER__ + +#include +#include + +#include +#include +#include +#include + +static inline uintptr_t gicv3_redist_size(uint64_t typer_val) +{ +#if GIC_ENABLE_V4_EXTN + if ((typer_val & TYPER_VLPI_BIT) != 0U) { + return 1U << GICR_V4_PCPUBASE_SHIFT; + } else { + return 1U << GICR_V3_PCPUBASE_SHIFT; + } +#else + return 1U << GICR_V3_PCPUBASE_SHIFT; +#endif +} + +unsigned int gicv3_get_component_partnum(const uintptr_t gic_frame); + +static inline bool gicv3_is_intr_id_special_identifier(unsigned int id) +{ + return (id >= PENDING_G1S_INTID) && (id <= GIC_SPURIOUS_INTERRUPT); +} + +/******************************************************************************* + * Helper GICv3 and 3.1 macros for SEL1 + ******************************************************************************/ +static inline uint32_t gicv3_acknowledge_interrupt_sel1(void) +{ + return (uint32_t)read_icc_iar1_el1() & IAR1_EL1_INTID_MASK; +} + +static inline uint32_t gicv3_get_pending_interrupt_id_sel1(void) +{ + return (uint32_t)read_icc_hppir1_el1() & HPPIR1_EL1_INTID_MASK; +} + +static inline void gicv3_end_of_interrupt_sel1(unsigned int id) +{ + /* + * Interrupt request deassertion from peripheral to GIC happens + * by clearing interrupt condition by a write to the peripheral + * register. It is desired that the write transfer is complete + * before the core tries to change GIC state from 'AP/Active' to + * a new state on seeing 'EOI write'. + * Since ICC interface writes are not ordered against Device + * memory writes, a barrier is required to ensure the ordering. + * The dsb will also ensure *completion* of previous writes with + * DEVICE nGnRnE attribute. + */ + dsbishst(); + write_icc_eoir1_el1(id); +} + +/******************************************************************************* + * Helper GICv3 macros for EL3 + ******************************************************************************/ +static inline uint32_t gicv3_acknowledge_interrupt(void) +{ + return (uint32_t)read_icc_iar0_el1() & IAR0_EL1_INTID_MASK; +} + +static inline void gicv3_end_of_interrupt(unsigned int id) +{ + /* + * Interrupt request deassertion from peripheral to GIC happens + * by clearing interrupt condition by a write to the peripheral + * register. It is desired that the write transfer is complete + * before the core tries to change GIC state from 'AP/Active' to + * a new state on seeing 'EOI write'. + * Since ICC interface writes are not ordered against Device + * memory writes, a barrier is required to ensure the ordering. + * The dsb will also ensure *completion* of previous writes with + * DEVICE nGnRnE attribute. + */ + dsbishst(); + return write_icc_eoir0_el1(id); +} + +/* + * This macro returns the total number of GICD/GICR registers corresponding to + * the register name + */ +#define GICD_NUM_REGS(reg_name) \ + DIV_ROUND_UP_2EVAL(TOTAL_SHARED_INTR_NUM, (1 << reg_name##_SHIFT)) + +#define GICR_NUM_REGS(reg_name) \ + DIV_ROUND_UP_2EVAL(TOTAL_PRIVATE_INTR_NUM, (1 << reg_name##_SHIFT)) + +/* Interrupt ID mask for HPPIR, AHPPIR, IAR and AIAR CPU Interface registers */ +#define INT_ID_MASK U(0xffffff) + +/******************************************************************************* + * This structure describes some of the implementation defined attributes of the + * GICv3 IP. It is used by the platform port to specify these attributes in order + * to initialise the GICV3 driver. The attributes are described below. + * + * The 'gicd_base' field contains the base address of the Distributor interface + * programmer's view. + * + * The 'gicr_base' field contains the base address of the Re-distributor + * interface programmer's view. + * + * The 'interrupt_props' field is a pointer to an array that enumerates secure + * interrupts and their properties. If this field is not NULL, both + * 'g0_interrupt_array' and 'g1s_interrupt_array' fields are ignored. + * + * The 'interrupt_props_num' field contains the number of entries in the + * 'interrupt_props' array. If this field is non-zero, both 'g0_interrupt_num' + * and 'g1s_interrupt_num' are ignored. + * + * The 'rdistif_num' field contains the number of Redistributor interfaces the + * GIC implements. This is equal to the number of CPUs or CPU interfaces + * instantiated in the GIC. + * + * The 'rdistif_base_addrs' field is a pointer to an array that has an entry for + * storing the base address of the Redistributor interface frame of each CPU in + * the system. The size of the array = 'rdistif_num'. The base addresses are + * detected during driver initialisation. + * + * The 'mpidr_to_core_pos' field is a pointer to a hash function which the + * driver will use to convert an MPIDR value to a linear core index. This index + * will be used for accessing the 'rdistif_base_addrs' array. This is an + * optional field. A GICv3 implementation maps each MPIDR to a linear core index + * as well. This mapping can be found by reading the "Affinity Value" and + * "Processor Number" fields in the GICR_TYPER. It is IMP. DEF. if the + * "Processor Numbers" are suitable to index into an array to access core + * specific information. If this not the case, the platform port must provide a + * hash function. Otherwise, the "Processor Number" field will be used to access + * the array elements. + ******************************************************************************/ +typedef unsigned int (*mpidr_hash_fn)(u_register_t mpidr); + +typedef struct gicv3_driver_data { + uintptr_t gicd_base; + uintptr_t gicr_base; + const interrupt_prop_t *interrupt_props; + unsigned int interrupt_props_num; + unsigned int rdistif_num; + uintptr_t *rdistif_base_addrs; + mpidr_hash_fn mpidr_to_core_pos; +} gicv3_driver_data_t; + +typedef struct gicv3_redist_ctx { + /* 64 bits registers */ + uint64_t gicr_propbaser; + uint64_t gicr_pendbaser; + + /* 32 bits registers */ + uint32_t gicr_ctlr; + uint32_t gicr_igroupr[GICR_NUM_REGS(IGROUPR)]; + uint32_t gicr_isenabler[GICR_NUM_REGS(ISENABLER)]; + uint32_t gicr_ispendr[GICR_NUM_REGS(ISPENDR)]; + uint32_t gicr_isactiver[GICR_NUM_REGS(ISACTIVER)]; + uint32_t gicr_ipriorityr[GICR_NUM_REGS(IPRIORITYR)]; + uint32_t gicr_icfgr[GICR_NUM_REGS(ICFGR)]; + uint32_t gicr_igrpmodr[GICR_NUM_REGS(IGRPMODR)]; + uint32_t gicr_nsacr; +} gicv3_redist_ctx_t; + +typedef struct gicv3_dist_ctx { + /* 64 bits registers */ + uint64_t gicd_irouter[TOTAL_SHARED_INTR_NUM]; + + /* 32 bits registers */ + uint32_t gicd_ctlr; + uint32_t gicd_igroupr[GICD_NUM_REGS(IGROUPR)]; + uint32_t gicd_isenabler[GICD_NUM_REGS(ISENABLER)]; + uint32_t gicd_ispendr[GICD_NUM_REGS(ISPENDR)]; + uint32_t gicd_isactiver[GICD_NUM_REGS(ISACTIVER)]; + uint32_t gicd_ipriorityr[GICD_NUM_REGS(IPRIORITYR)]; + uint32_t gicd_icfgr[GICD_NUM_REGS(ICFGR)]; + uint32_t gicd_igrpmodr[GICD_NUM_REGS(IGRPMODR)]; + uint32_t gicd_nsacr[GICD_NUM_REGS(NSACR)]; +} gicv3_dist_ctx_t; + +typedef struct gicv3_its_ctx { + /* 64 bits registers */ + uint64_t gits_cbaser; + uint64_t gits_cwriter; + uint64_t gits_baser[8]; + + /* 32 bits registers */ + uint32_t gits_ctlr; +} gicv3_its_ctx_t; + +/******************************************************************************* + * GICv3 EL3 driver API + ******************************************************************************/ +void gicv3_driver_init(const gicv3_driver_data_t *plat_driver_data); +int gicv3_rdistif_probe(const uintptr_t gicr_frame); +void gicv3_distif_init(void); +void gicv3_rdistif_init(unsigned int proc_num); +void gicv3_rdistif_on(unsigned int proc_num); +void gicv3_rdistif_off(unsigned int proc_num); +unsigned int gicv3_rdistif_get_number_frames(const uintptr_t gicr_frame); +void gicv3_cpuif_enable(unsigned int proc_num); +void gicv3_cpuif_disable(unsigned int proc_num); +unsigned int gicv3_get_pending_interrupt_type(void); +unsigned int gicv3_get_pending_interrupt_id(void); +unsigned int gicv3_get_interrupt_type(unsigned int id, + unsigned int proc_num); +void gicv3_distif_init_restore(const gicv3_dist_ctx_t * const dist_ctx); +void gicv3_distif_save(gicv3_dist_ctx_t * const dist_ctx); +/* + * gicv3_distif_post_restore and gicv3_distif_pre_save must be implemented if + * gicv3_distif_save and gicv3_rdistif_init_restore are used. If no + * implementation-defined sequence is needed at these steps, an empty function + * can be provided. + */ +void gicv3_distif_post_restore(unsigned int proc_num); +void gicv3_distif_pre_save(unsigned int proc_num); +void gicv3_rdistif_init_restore(unsigned int proc_num, const gicv3_redist_ctx_t * const rdist_ctx); +void gicv3_rdistif_save(unsigned int proc_num, gicv3_redist_ctx_t * const rdist_ctx); +void gicv3_its_save_disable(uintptr_t gits_base, gicv3_its_ctx_t * const its_ctx); +void gicv3_its_restore(uintptr_t gits_base, const gicv3_its_ctx_t * const its_ctx); + +unsigned int gicv3_get_running_priority(void); +unsigned int gicv3_get_interrupt_active(unsigned int id, unsigned int proc_num); +void gicv3_enable_interrupt(unsigned int id, unsigned int proc_num); +void gicv3_disable_interrupt(unsigned int id, unsigned int proc_num); +void gicv3_set_interrupt_priority(unsigned int id, unsigned int proc_num, + unsigned int priority); +void gicv3_set_interrupt_type(unsigned int id, unsigned int proc_num, + unsigned int type); +void gicv3_raise_secure_g0_sgi(unsigned int sgi_num, u_register_t target); +void gicv3_set_spi_routing(unsigned int id, unsigned int irm, + u_register_t mpidr); +void gicv3_set_interrupt_pending(unsigned int id, unsigned int proc_num); +void gicv3_clear_interrupt_pending(unsigned int id, unsigned int proc_num); +unsigned int gicv3_set_pmr(unsigned int mask); + +#endif /* __ASSEMBLER__ */ +#endif /* GICV3_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/nic_400.h b/arm-trusted-firmware/include/drivers/arm/nic_400.h new file mode 100644 index 0000000..bb74982 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/nic_400.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NIC_400_H +#define NIC_400_H + +/* + * Address of slave 'n' security setting in the NIC-400 address region + * control + */ +#define NIC400_ADDR_CTRL_SECURITY_REG(n) (0x8 + (n) * 4) + +#endif /* NIC_400_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/pl011.h b/arm-trusted-firmware/include/drivers/arm/pl011.h new file mode 100644 index 0000000..ebc6643 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/pl011.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PL011_H +#define PL011_H + +#include + +/* PL011 Registers */ +#define UARTDR 0x000 +#define UARTRSR 0x004 +#define UARTECR 0x004 +#define UARTFR 0x018 +#define UARTIMSC 0x038 +#define UARTRIS 0x03C +#define UARTICR 0x044 + +/* PL011 registers (out of the SBSA specification) */ +#if !PL011_GENERIC_UART +#define UARTILPR 0x020 +#define UARTIBRD 0x024 +#define UARTFBRD 0x028 +#define UARTLCR_H 0x02C +#define UARTCR 0x030 +#define UARTIFLS 0x034 +#define UARTMIS 0x040 +#define UARTDMACR 0x048 +#endif /* !PL011_GENERIC_UART */ + +/* Data status bits */ +#define UART_DATA_ERROR_MASK 0x0F00 + +/* Status reg bits */ +#define UART_STATUS_ERROR_MASK 0x0F + +/* Flag reg bits */ +#define PL011_UARTFR_RI (1 << 8) /* Ring indicator */ +#define PL011_UARTFR_TXFE (1 << 7) /* Transmit FIFO empty */ +#define PL011_UARTFR_RXFF (1 << 6) /* Receive FIFO full */ +#define PL011_UARTFR_TXFF (1 << 5) /* Transmit FIFO full */ +#define PL011_UARTFR_RXFE (1 << 4) /* Receive FIFO empty */ +#define PL011_UARTFR_BUSY (1 << 3) /* UART busy */ +#define PL011_UARTFR_DCD (1 << 2) /* Data carrier detect */ +#define PL011_UARTFR_DSR (1 << 1) /* Data set ready */ +#define PL011_UARTFR_CTS (1 << 0) /* Clear to send */ + +#define PL011_UARTFR_TXFF_BIT 5 /* Transmit FIFO full bit in UARTFR register */ +#define PL011_UARTFR_RXFE_BIT 4 /* Receive FIFO empty bit in UARTFR register */ +#define PL011_UARTFR_BUSY_BIT 3 /* UART busy bit in UARTFR register */ + +/* Control reg bits */ +#if !PL011_GENERIC_UART +#define PL011_UARTCR_CTSEN (1 << 15) /* CTS hardware flow control enable */ +#define PL011_UARTCR_RTSEN (1 << 14) /* RTS hardware flow control enable */ +#define PL011_UARTCR_RTS (1 << 11) /* Request to send */ +#define PL011_UARTCR_DTR (1 << 10) /* Data transmit ready. */ +#define PL011_UARTCR_RXE (1 << 9) /* Receive enable */ +#define PL011_UARTCR_TXE (1 << 8) /* Transmit enable */ +#define PL011_UARTCR_LBE (1 << 7) /* Loopback enable */ +#define PL011_UARTCR_UARTEN (1 << 0) /* UART Enable */ + +#if !defined(PL011_LINE_CONTROL) +/* FIFO Enabled / No Parity / 8 Data bit / One Stop Bit */ +#define PL011_LINE_CONTROL (PL011_UARTLCR_H_FEN | PL011_UARTLCR_H_WLEN_8) +#endif + +/* Line Control Register Bits */ +#define PL011_UARTLCR_H_SPS (1 << 7) /* Stick parity select */ +#define PL011_UARTLCR_H_WLEN_8 (3 << 5) +#define PL011_UARTLCR_H_WLEN_7 (2 << 5) +#define PL011_UARTLCR_H_WLEN_6 (1 << 5) +#define PL011_UARTLCR_H_WLEN_5 (0 << 5) +#define PL011_UARTLCR_H_FEN (1 << 4) /* FIFOs Enable */ +#define PL011_UARTLCR_H_STP2 (1 << 3) /* Two stop bits select */ +#define PL011_UARTLCR_H_EPS (1 << 2) /* Even parity select */ +#define PL011_UARTLCR_H_PEN (1 << 1) /* Parity Enable */ +#define PL011_UARTLCR_H_BRK (1 << 0) /* Send break */ + +#endif /* !PL011_GENERIC_UART */ + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new PL011 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_pl011_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* PL011_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h b/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h new file mode 100644 index 0000000..68238c9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/pl061_gpio.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PL061_GPIO_H +#define PL061_GPIO_H + +#include + +void pl061_gpio_register(uintptr_t base_addr, int gpio_dev); +void pl061_gpio_init(void); + +#endif /* PL061_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sbsa.h b/arm-trusted-firmware/include/drivers/arm/sbsa.h new file mode 100644 index 0000000..9403634 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sbsa.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SBSA_H +#define SBSA_H + +#include + +/* Register Offsets */ +#define SBSA_WDOG_WCS_OFFSET UL(0x000) +#define SBSA_WDOG_WOR_LOW_OFFSET UL(0x008) +#define SBSA_WDOG_WOR_HIGH_OFFSET UL(0x00C) + +#define SBSA_WDOG_WCS_EN U(0x1) + +#define SBSA_WDOG_WOR_WIDTH UL(48) + +void sbsa_wdog_start(uintptr_t base, uint64_t ms); +void sbsa_wdog_stop(uintptr_t base); + +#endif /* SBSA_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/scu.h b/arm-trusted-firmware/include/drivers/arm/scu.h new file mode 100644 index 0000000..992539f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/scu.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCU_H +#define SCU_H + +#include + +#define SCU_CTRL_REG 0x00 +#define SCU_CFG_REG 0x04 + +#define SCU_ENABLE_BIT (1 << 0) + +void enable_snoop_ctrl_unit(uintptr_t base); +uint32_t read_snoop_ctrl_unit_cfg(uintptr_t base); + +#endif /* SCU_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/smmu_v3.h b/arm-trusted-firmware/include/drivers/arm/smmu_v3.h new file mode 100644 index 0000000..a820a44 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/smmu_v3.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMMU_V3_H +#define SMMU_V3_H + +#include +#include + +/* SMMUv3 register offsets from device base */ +#define SMMU_GBPA U(0x0044) +#define SMMU_S_IDR1 U(0x8004) +#define SMMU_S_INIT U(0x803c) +#define SMMU_S_GBPA U(0x8044) + +/* SMMU_GBPA register fields */ +#define SMMU_GBPA_UPDATE (1UL << 31) +#define SMMU_GBPA_ABORT (1UL << 20) + +/* SMMU_S_IDR1 register fields */ +#define SMMU_S_IDR1_SECURE_IMPL (1UL << 31) + +/* SMMU_S_INIT register fields */ +#define SMMU_S_INIT_INV_ALL (1UL << 0) + +/* SMMU_S_GBPA register fields */ +#define SMMU_S_GBPA_UPDATE (1UL << 31) +#define SMMU_S_GBPA_ABORT (1UL << 20) + +int smmuv3_init(uintptr_t smmu_base); +int smmuv3_security_init(uintptr_t smmu_base); + +#endif /* SMMU_V3_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h b/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h new file mode 100644 index 0000000..f8769e8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP804_DELAY_TIMER_H +#define SP804_DELAY_TIMER_H + +#include + +#include + +uint32_t sp804_get_timer_value(void); + +void sp804_timer_ops_init(uintptr_t base_addr, const timer_ops_t *ops); + +#define sp804_timer_init(base_addr, clk_mult, clk_div) \ + do { \ + static const timer_ops_t sp804_timer_ops = { \ + sp804_get_timer_value, \ + (clk_mult), \ + (clk_div) \ + }; \ + sp804_timer_ops_init((base_addr), &sp804_timer_ops); \ + } while (0) + +#endif /* SP804_DELAY_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/sp805.h b/arm-trusted-firmware/include/drivers/arm/sp805.h new file mode 100644 index 0000000..b00ede1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/sp805.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SP805_H +#define SP805_H + +#include + +/* SP805 register offset */ +#define SP805_WDOG_LOAD_OFF UL(0x000) +#define SP805_WDOG_CTR_OFF UL(0x008) +#define SP805_WDOG_LOCK_OFF UL(0xc00) + +/* Magic word to unlock the wd registers */ +#define WDOG_UNLOCK_KEY U(0x1ACCE551) + +/* Register field definitions */ +#define SP805_CTR_RESEN (U(1) << 1) +#define SP805_CTR_INTEN (U(1) << 0) + +#ifndef __ASSEMBLER__ + +#include + +/* Public high level API */ + +void sp805_start(uintptr_t base, unsigned int ticks); +void sp805_stop(uintptr_t base); +void sp805_refresh(uintptr_t base, unsigned int ticks); + +#endif /* __ASSEMBLER__ */ + +#endif /* SP805_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc380.h b/arm-trusted-firmware/include/drivers/arm/tzc380.h new file mode 100644 index 0000000..9bd5f21 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc380.h @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC380_H +#define TZC380_H + +#include +#include + +#define TZC380_CONFIGURATION_OFF U(0x000) +#define ACTION_OFF U(0x004) +#define LOCKDOWN_RANGE_OFF U(0x008) +#define LOCKDOWN_SELECT_OFF U(0x00C) +#define INT_STATUS U(0x010) +#define INT_CLEAR U(0x014) + +#define FAIL_ADDRESS_LOW_OFF U(0x020) +#define FAIL_ADDRESS_HIGH_OFF U(0x024) +#define FAIL_CONTROL_OFF U(0x028) +#define FAIL_ID U(0x02c) + +#define SPECULATION_CTRL_OFF U(0x030) +#define SECURITY_INV_EN_OFF U(0x034) + +#define REGION_SETUP_LOW_OFF(n) U(0x100 + (n) * 0x10) +#define REGION_SETUP_HIGH_OFF(n) U(0x104 + (n) * 0x10) +#define REGION_ATTRIBUTES_OFF(n) U(0x108 + (n) * 0x10) + +#define BUILD_CONFIG_AW_SHIFT 8 +#define BUILD_CONFIG_AW_MASK U(0x3f) +#define BUILD_CONFIG_NR_SHIFT 0 +#define BUILD_CONFIG_NR_MASK U(0xf) + +#define ACTION_RV_SHIFT 0 +#define ACTION_RV_MASK U(0x3) +#define ACTION_RV_LOWOK U(0x0) +#define ACTION_RV_LOWERR U(0x1) +#define ACTION_RV_HIGHOK U(0x2) +#define ACTION_RV_HIGHERR U(0x3) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT_32(1) +#define SPECULATION_CTRL_READ_DISABLE BIT_32(0) + +#define INT_STATUS_OVERRUN_SHIFT 1 +#define INT_STATUS_OVERRUN_MASK U(0x1) +#define INT_STATUS_STATUS_SHIFT 0 +#define INT_STATUS_STATUS_MASK U(0x1) + +#define INT_CLEAR_CLEAR_SHIFT 0 +#define INT_CLEAR_CLEAR_MASK U(0x1) + +#define TZC380_COMPONENT_ID U(0xb105f00d) +#define TZC380_PERIPH_ID_LOW U(0x001bb380) +#define TZC380_PERIPH_ID_HIGH U(0x00000004) + +#define TZC_SP_NS_W BIT_32(0) +#define TZC_SP_NS_R BIT_32(1) +#define TZC_SP_S_W BIT_32(2) +#define TZC_SP_S_R BIT_32(3) + +#define TZC_ATTR_SP_SHIFT 28 +#define TZC_ATTR_SP_ALL ((TZC_SP_S_W | TZC_SP_S_R | TZC_SP_NS_W | \ + TZC_SP_NS_R) << TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_S_RW ((TZC_SP_S_W | TZC_SP_S_R) << \ + TZC_ATTR_SP_SHIFT) +#define TZC_ATTR_SP_NS_RW ((TZC_SP_NS_W | TZC_SP_NS_R) << \ + TZC_ATTR_SP_SHIFT) + +#define TZC_REGION_SIZE_32K U(0xe) +#define TZC_REGION_SIZE_64K U(0xf) +#define TZC_REGION_SIZE_128K U(0x10) +#define TZC_REGION_SIZE_256K U(0x11) +#define TZC_REGION_SIZE_512K U(0x12) +#define TZC_REGION_SIZE_1M U(0x13) +#define TZC_REGION_SIZE_2M U(0x14) +#define TZC_REGION_SIZE_4M U(0x15) +#define TZC_REGION_SIZE_8M U(0x16) +#define TZC_REGION_SIZE_16M U(0x17) +#define TZC_REGION_SIZE_32M U(0x18) +#define TZC_REGION_SIZE_64M U(0x19) +#define TZC_REGION_SIZE_128M U(0x1a) +#define TZC_REGION_SIZE_256M U(0x1b) +#define TZC_REGION_SIZE_512M U(0x1c) +#define TZC_REGION_SIZE_1G U(0x1d) +#define TZC_REGION_SIZE_2G U(0x1e) +#define TZC_REGION_SIZE_4G U(0x1f) +#define TZC_REGION_SIZE_8G U(0x20) +#define TZC_REGION_SIZE_16G U(0x21) +#define TZC_REGION_SIZE_32G U(0x22) +#define TZC_REGION_SIZE_64G U(0x23) +#define TZC_REGION_SIZE_128G U(0x24) +#define TZC_REGION_SIZE_256G U(0x25) +#define TZC_REGION_SIZE_512G U(0x26) +#define TZC_REGION_SIZE_1T U(0x27) +#define TZC_REGION_SIZE_2T U(0x28) +#define TZC_REGION_SIZE_4T U(0x29) +#define TZC_REGION_SIZE_8T U(0x2a) +#define TZC_REGION_SIZE_16T U(0x2b) +#define TZC_REGION_SIZE_32T U(0x2c) +#define TZC_REGION_SIZE_64T U(0x2d) +#define TZC_REGION_SIZE_128T U(0x2e) +#define TZC_REGION_SIZE_256T U(0x2f) +#define TZC_REGION_SIZE_512T U(0x30) +#define TZC_REGION_SIZE_1P U(0x31) +#define TZC_REGION_SIZE_2P U(0x32) +#define TZC_REGION_SIZE_4P U(0x33) +#define TZC_REGION_SIZE_8P U(0x34) +#define TZC_REGION_SIZE_16P U(0x35) +#define TZC_REGION_SIZE_32P U(0x36) +#define TZC_REGION_SIZE_64P U(0x37) +#define TZC_REGION_SIZE_128P U(0x38) +#define TZC_REGION_SIZE_256P U(0x39) +#define TZC_REGION_SIZE_512P U(0x3a) +#define TZC_REGION_SIZE_1E U(0x3b) +#define TZC_REGION_SIZE_2E U(0x3c) +#define TZC_REGION_SIZE_4E U(0x3d) +#define TZC_REGION_SIZE_8E U(0x3e) +#define TZC_REGION_SIZE_16E U(0x3f) + +#define TZC_SUBREGION_DIS_SHIFT 0x8 +#define TZC_SUBREGION_DIS_MASK U(0xff) +#define TZC_ATTR_SUBREG_DIS(s) (((s) & TZC_SUBREGION_DIS_MASK) \ + << TZC_SUBREGION_DIS_SHIFT) + +#define TZC_REGION_SIZE_SHIFT 0x1 +#define TZC_REGION_SIZE_MASK U(0x7e) +#define TZC_ATTR_REGION_SIZE(s) ((s) << TZC_REGION_SIZE_SHIFT) + +#define TZC_ATTR_REGION_EN_SHIFT 0x0 +#define TZC_ATTR_REGION_EN_MASK U(0x1) + +#define TZC_ATTR_REGION_EN +#define TZC_ATTR_REGION_ENABLE U(0x1) +#define TZC_ATTR_REGION_DISABLE U(0x0) + +#define REGION_MAX 16 + +void tzc380_init(uintptr_t base); +void tzc380_configure_region(uint8_t region, + uintptr_t region_base, + unsigned int attr); +void tzc380_set_action(unsigned int action); +static inline void tzc_init(uintptr_t base) +{ + tzc380_init(base); +} + +static inline void tzc_configure_region(uint8_t region, + uintptr_t region_base, + unsigned int attr) +{ + tzc380_configure_region(region, region_base, attr); +} + +static inline void tzc_set_action(unsigned int action) +{ + tzc380_set_action(action); +} + +#endif /* TZC380_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc400.h b/arm-trusted-firmware/include/drivers/arm/tzc400.h new file mode 100644 index 0000000..765c130 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc400.h @@ -0,0 +1,160 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC400_H +#define TZC400_H + +#include +#include + +#define BUILD_CONFIG_OFF U(0x000) +#define GATE_KEEPER_OFF U(0x008) +#define SPECULATION_CTRL_OFF U(0x00c) +#define INT_STATUS U(0x010) +#define INT_CLEAR U(0x014) + +#define FAIL_ADDRESS_LOW_OFF U(0x020) +#define FAIL_ADDRESS_HIGH_OFF U(0x024) +#define FAIL_CONTROL_OFF U(0x028) +#define FAIL_ID U(0x02c) + +/* ID registers not common across different varieties of TZC */ +#define PID5 U(0xFD4) +#define PID6 U(0xFD8) +#define PID7 U(0xFDC) + +#define BUILD_CONFIG_NF_SHIFT 24 +#define BUILD_CONFIG_NF_MASK U(0x3) +#define BUILD_CONFIG_AW_SHIFT 8 +#define BUILD_CONFIG_AW_MASK U(0x3f) +#define BUILD_CONFIG_NR_SHIFT 0 +#define BUILD_CONFIG_NR_MASK U(0x1f) + +/* + * Number of gate keepers is implementation defined. But we know the max for + * this device is 4. Get implementation details from BUILD_CONFIG. + */ +#define GATE_KEEPER_OS_SHIFT 16 +#define GATE_KEEPER_OS_MASK U(0xf) +#define GATE_KEEPER_OR_SHIFT 0 +#define GATE_KEEPER_OR_MASK U(0xf) +#define GATE_KEEPER_FILTER_MASK U(0x1) + +/* Speculation is enabled by default. */ +#define SPECULATION_CTRL_WRITE_DISABLE BIT_32(1) +#define SPECULATION_CTRL_READ_DISABLE BIT_32(0) + +/* Max number of filters allowed is 4. */ +#define INT_STATUS_OVERLAP_SHIFT 16 +#define INT_STATUS_OVERLAP_MASK U(0xf) +#define INT_STATUS_OVERRUN_SHIFT 8 +#define INT_STATUS_OVERRUN_MASK U(0xf) +#define INT_STATUS_STATUS_SHIFT 0 +#define INT_STATUS_STATUS_MASK U(0xf) + +#define INT_CLEAR_CLEAR_SHIFT 0 +#define INT_CLEAR_CLEAR_MASK U(0xf) + +#define FAIL_CONTROL_DIR_SHIFT 24 +#define FAIL_CONTROL_DIR_READ U(0) +#define FAIL_CONTROL_DIR_WRITE U(1) +#define FAIL_CONTROL_NS_SHIFT 21 +#define FAIL_CONTROL_NS_SECURE U(0) +#define FAIL_CONTROL_NS_NONSECURE U(1) +#define FAIL_CONTROL_PRIV_SHIFT 20 +#define FAIL_CONTROL_PRIV_UNPRIV U(0) +#define FAIL_CONTROL_PRIV_PRIV U(1) + +/* + * FAIL_ID_ID_MASK depends on AID_WIDTH which is platform specific. + * Platform should provide the value on initialisation. + */ +#define FAIL_ID_VNET_SHIFT 24 +#define FAIL_ID_VNET_MASK U(0xf) +#define FAIL_ID_ID_SHIFT 0 + +#define TZC_400_PERIPHERAL_ID U(0x460) + +/* Filter enable bits in a TZC */ +#define TZC_400_REGION_ATTR_F_EN_MASK U(0xf) +#define TZC_400_REGION_ATTR_FILTER_BIT(x) (U(1) << (x)) +#define TZC_400_REGION_ATTR_FILTER_BIT_ALL TZC_400_REGION_ATTR_F_EN_MASK + +/* + * All TZC region configuration registers are placed one after another. It + * depicts size of block of registers for programming each region. + */ +#define TZC_400_REGION_SIZE U(0x20) +#define TZC_400_ACTION_OFF U(0x4) + +#define FILTER_OFFSET U(0x10) + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void tzc400_init(uintptr_t base); +void tzc400_configure_region0(unsigned int sec_attr, + unsigned int ns_device_access); +void tzc400_configure_region(unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc400_update_filters(unsigned int region, unsigned int filters); +void tzc400_set_action(unsigned int action); +void tzc400_enable_filters(void); +void tzc400_disable_filters(void); +int tzc400_it_handler(void); + +static inline void tzc_init(uintptr_t base) +{ + tzc400_init(base); +} + +static inline void tzc_configure_region0( + unsigned int sec_attr, + unsigned int ns_device_access) +{ + tzc400_configure_region0(sec_attr, ns_device_access); +} + +static inline void tzc_configure_region( + unsigned int filters, + unsigned int region, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int ns_device_access) +{ + tzc400_configure_region(filters, region, region_base, + region_top, sec_attr, ns_device_access); +} + +static inline void tzc_set_action(unsigned int action) +{ + tzc400_set_action(action); +} + + +static inline void tzc_enable_filters(void) +{ + tzc400_enable_filters(); +} + +static inline void tzc_disable_filters(void) +{ + tzc400_disable_filters(); +} + +#endif /* __ASSEMBLER__ */ + +#endif /* TZC400_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc_common.h b/arm-trusted-firmware/include/drivers/arm/tzc_common.h new file mode 100644 index 0000000..e58201c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc_common.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_COMMON_H +#define TZC_COMMON_H + +#include + +/* + * Offset of core registers from the start of the base of configuration + * registers for each region. + */ + +/* ID Registers */ +#define PID0_OFF U(0xfe0) +#define PID1_OFF U(0xfe4) +#define PID2_OFF U(0xfe8) +#define PID3_OFF U(0xfec) +#define PID4_OFF U(0xfd0) +#define CID0_OFF U(0xff0) +#define CID1_OFF U(0xff4) +#define CID2_OFF U(0xff8) +#define CID3_OFF U(0xffc) + +/* + * What type of action is expected when an access violation occurs. + * The memory requested is returned as zero. But we can also raise an event to + * let the system know it happened. + * We can raise an interrupt(INT) and/or cause an exception(ERR). + * TZC_ACTION_NONE - No interrupt, no Exception + * TZC_ACTION_ERR - No interrupt, raise exception -> sync external + * data abort + * TZC_ACTION_INT - Raise interrupt, no exception + * TZC_ACTION_ERR_INT - Raise interrupt, raise exception -> sync + * external data abort + */ +#define TZC_ACTION_NONE U(0) +#define TZC_ACTION_ERR U(1) +#define TZC_ACTION_INT U(2) +#define TZC_ACTION_ERR_INT (TZC_ACTION_ERR | TZC_ACTION_INT) + +/* Bit positions of TZC_ACTION registers */ +#define TZC_ACTION_RV_SHIFT 0 +#define TZC_ACTION_RV_MASK U(0x3) +#define TZC_ACTION_RV_LOWOK U(0x0) +#define TZC_ACTION_RV_LOWERR U(0x1) +#define TZC_ACTION_RV_HIGHOK U(0x2) +#define TZC_ACTION_RV_HIGHERR U(0x3) + +/* + * Controls secure access to a region. If not enabled secure access is not + * allowed to region. + */ +#define TZC_REGION_S_NONE U(0) +#define TZC_REGION_S_RD U(1) +#define TZC_REGION_S_WR U(2) +#define TZC_REGION_S_RDWR (TZC_REGION_S_RD | TZC_REGION_S_WR) + +#define TZC_REGION_ATTR_S_RD_SHIFT 30 +#define TZC_REGION_ATTR_S_WR_SHIFT 31 +#define TZC_REGION_ATTR_F_EN_SHIFT 0 +#define TZC_REGION_ATTR_SEC_SHIFT 30 +#define TZC_REGION_ATTR_S_RD_MASK U(0x1) +#define TZC_REGION_ATTR_S_WR_MASK U(0x1) +#define TZC_REGION_ATTR_SEC_MASK U(0x3) + +#define TZC_REGION_ACCESS_WR_EN_SHIFT 16 +#define TZC_REGION_ACCESS_RD_EN_SHIFT 0 +#define TZC_REGION_ACCESS_ID_MASK U(0xf) + +/* Macros for allowing Non-Secure access to a region based on NSAID */ +#define TZC_REGION_ACCESS_RD(nsaid) \ + ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \ + TZC_REGION_ACCESS_RD_EN_SHIFT) +#define TZC_REGION_ACCESS_WR(nsaid) \ + ((U(1) << ((nsaid) & TZC_REGION_ACCESS_ID_MASK)) << \ + TZC_REGION_ACCESS_WR_EN_SHIFT) +#define TZC_REGION_ACCESS_RDWR(nsaid) \ + (TZC_REGION_ACCESS_RD(nsaid) | \ + TZC_REGION_ACCESS_WR(nsaid)) + +/* Returns offset of registers to program for a given region no */ +#define TZC_REGION_OFFSET(region_size, region_no) \ + ((region_size) * (region_no)) + +#endif /* TZC_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h b/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h new file mode 100644 index 0000000..cce074c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_DMC500_H +#define TZC_DMC500_H + +#include +#include + +#define SI_STATUS_OFFSET U(0x000) +#define SI_STATE_CTRL_OFFSET U(0x030) +#define SI_FLUSH_CTRL_OFFSET U(0x034) +#define SI_INT_CONTROL_OFFSET U(0x048) + +#define SI_INT_STATUS_OFFSET U(0x004) +#define SI_TZ_FAIL_ADDRESS_LOW_OFFSET U(0x008) +#define SI_TZ_FAIL_ADDRESS_HIGH_OFFSET U(0x00c) +#define SI_FAIL_CONTROL_OFFSET U(0x010) +#define SI_FAIL_ID_OFFSET U(0x014) +#define SI_INT_CLR_OFFSET U(0x04c) + +/* + * DMC-500 has 2 system interfaces each having a similar set of regs + * to configure each interface. + */ +#define SI0_BASE U(0x0000) +#define SI1_BASE U(0x0200) + +/* Bit positions of SIx_SI_STATUS */ +#define SI_EMPTY_SHIFT 1 +#define SI_STALL_ACK_SHIFT 0 +#define SI_EMPTY_MASK U(0x01) +#define SI_STALL_ACK_MASK U(0x01) + +/* Bit positions of SIx_SI_INT_STATUS */ +#define PMU_REQ_INT_OVERFLOW_STATUS_SHIFT 18 +#define FAILED_ACCESS_INT_OVERFLOW_STATUS_SHIFT 16 +#define PMU_REQ_INT_STATUS_SHIFT 2 +#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_SHIFT 1 +#define FAILED_ACCESS_INT_STATUS_SHIFT 0 +#define PMU_REQ_INT_OVERFLOW_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_OVERFLOW_STATUS_MASK U(0x1) +#define PMU_REQ_INT_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_TZ_OVERLAP_STATUS_MASK U(0x1) +#define FAILED_ACCESS_INT_STATUS_MASK U(0x1) + +/* Bit positions of SIx_TZ_FAIL_CONTROL */ +#define DIRECTION_SHIFT 24 +#define NON_SECURE_SHIFT 21 +#define PRIVILEGED_SHIFT 20 +#define FAILED_ACCESS_INT_INFO_RANK_MASKED_SHIFT 3 +#define FAILED_ACCESS_INT_INFO_UNMAPPED_SHIFT 2 +#define FAILED_ACCESS_INT_TZ_FAIL_SHIFT 1 +#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_SHIFT 0 +#define DIRECTION_MASK U(0x1) +#define NON_SECURE_MASK U(0x1) +#define PRIVILEGED_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_RANK_MASKED_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_UNMAPPED_MASK U(0x1) +#define FAILED_ACCESS_INT_TZ_FAIL_MASK U(0x1) +#define FAILED_ACCESS_INT_INFO_OUTSIDE_DEFAULT_MASK U(0x1) + +/* Bit positions of SIx_FAIL_STATUS */ +#define FAIL_ID_VNET_SHIFT 24 +#define FAIL_ID_ID_SHIFT 0 +#define FAIL_ID_VNET_MASK U(0xf) +#define FAIL_ID_ID_MASK U(0xffffff) + +/* Bit positions of SIx_SI_STATE_CONTRL */ +#define SI_STALL_REQ_GO 0x0 +#define SI_STALL_REQ_STALL 0x1 + +/* Bit positions of SIx_SI_FLUSH_CONTROL */ +#define SI_FLUSH_REQ_INACTIVE 0x0 +#define SI_FLUSH_REQ_ACTIVE 0x1 +#define SI_FLUSH_REQ_MASK 0x1 + +/* Bit positions of SIx_SI_INT_CONTROL */ +#define PMU_REQ_INT_EN_SHIFT 2 +#define OVERLAP_DETECT_INT_EN_SHIFT 1 +#define FAILED_ACCESS_INT_EN_SHIFT 0 +#define PMU_REQ_INT_EN_MASK U(0x1) +#define OVERLAP_DETECT_INT_EN_MASK U(0x1) +#define FAILED_ACCESS_INT_EN_MASK U(0x1) +#define PMU_REQ_INT_EN U(0x1) +#define OVERLAP_DETECT_INT_EN U(0x1) +#define FAILED_ACCESS_INT_EN U(0x1) + +/* Bit positions of SIx_SI_INT_CLR */ +#define PMU_REQ_OFLOW_CLR_SHIFT 18 +#define FAILED_ACCESS_OFLOW_CLR_SHIFT 16 +#define PMU_REQ_INT_CLR_SHIFT 2 +#define FAILED_ACCESS_INT_CLR_SHIFT 0 +#define PMU_REQ_OFLOW_CLR_MASK U(0x1) +#define FAILED_ACCESS_OFLOW_CLR_MASK U(0x1) +#define PMU_REQ_INT_CLR_MASK U(0x1) +#define FAILED_ACCESS_INT_CLR_MASK U(0x1) +#define PMU_REQ_OFLOW_CLR U(0x1) +#define FAILED_ACCESS_OFLOW_CLR U(0x1) +#define PMU_REQ_INT_CLR U(0x1) +#define FAILED_ACCESS_INT_CLR U(0x1) + +/* Macro to get the correct base register for a system interface */ +#define IFACE_OFFSET(sys_if) ((sys_if) ? SI1_BASE : SI0_BASE) + +#define MAX_SYS_IF_COUNT U(2) +#define MAX_REGION_VAL 8 + +/* DMC-500 supports striping across a max of 4 DMC instances */ +#define MAX_DMC_COUNT 4 + +/* Consist of part_number_1 and part_number_0 */ +#define DMC500_PERIPHERAL_ID U(0x0450) + +/* Filter enable bits in a TZC */ +#define TZC_DMC500_REGION_ATTR_F_EN_MASK U(0x1) + +/* Length of registers for configuring each region */ +#define TZC_DMC500_REGION_SIZE U(0x018) + +#ifndef __ASSEMBLER__ + +#include + +/* + * Contains the base addresses of all the DMC instances. + */ +typedef struct tzc_dmc500_driver_data { + uintptr_t dmc_base[MAX_DMC_COUNT]; + int dmc_count; + unsigned int sys_if_count; +} tzc_dmc500_driver_data_t; + +void tzc_dmc500_driver_init(const tzc_dmc500_driver_data_t *plat_driver_data); +void tzc_dmc500_configure_region0(unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc_dmc500_configure_region(unsigned int region_no, + unsigned long long region_base, + unsigned long long region_top, + unsigned int sec_attr, + unsigned int nsaid_permissions); +void tzc_dmc500_set_action(unsigned int action); +void tzc_dmc500_config_complete(void); +int tzc_dmc500_verify_complete(void); + + +#endif /* __ASSEMBLER__ */ +#endif /* TZC_DMC500_H */ diff --git a/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h b/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h new file mode 100644 index 0000000..26c444d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TZC_DMC620_H +#define TZC_DMC620_H + +#include + +/* DMC-620 memc register offsets */ +#define DMC620_MEMC_STATUS U(0x0000) +#define DMC620_MEMC_CMD U(0x0008) + +/* Mask value to check the status of memc_cmd register */ +#define DMC620_MEMC_CMD_MASK U(0x00000007) + +/* memc_cmd register's action values */ +#define DMC620_MEMC_CMD_GO U(0x00000003) +#define DMC620_MEMC_CMD_EXECUTE U(0x00000004) + +/* Address offsets of access address next region 0 registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE U(0x0080) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE U(0x0084) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE U(0x0088) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE U(0x008c) + +/* Length of one block of access address next register region */ +#define DMC620_ACC_ADDR_NEXT_SIZE U(0x0010) + +/* Address offsets of access address next registers */ +#define DMC620_ACC_ADDR_MIN_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_31_00_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MIN_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MIN_47_32_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_31_00_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_31_00_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) +#define DMC620_ACC_ADDR_MAX_47_32_NEXT(region_no) \ + (DMC620_ACC_ADDR_MAX_47_32_NEXT_BASE + \ + ((region_no) * DMC620_ACC_ADDR_NEXT_SIZE)) + +/* Number of TZC address regions in DMC-620 */ +#define DMC620_ACC_ADDR_COUNT U(8) +/* Width of access address registers */ +#define DMC620_ACC_ADDR_WIDTH U(32) + +/* Peripheral ID registers offsets */ +#define DMC620_PERIPHERAL_ID_0 U(0x1fe0) + +/* Default values in id registers */ +#define DMC620_PERIPHERAL_ID_0_VALUE U(0x00000054) + +/* Secure access region attributes. */ +#define TZC_DMC620_REGION_NS_RD U(0x00000001) +#define TZC_DMC620_REGION_NS_WR U(0x00000002) +#define TZC_DMC620_REGION_NS_RDWR \ + (TZC_DMC620_REGION_NS_RD | TZC_DMC620_REGION_NS_WR) +#define TZC_DMC620_REGION_S_RD U(0x00000004) +#define TZC_DMC620_REGION_S_WR U(0x00000008) +#define TZC_DMC620_REGION_S_RDWR \ + (TZC_DMC620_REGION_S_RD | TZC_DMC620_REGION_S_WR) +#define TZC_DMC620_REGION_S_NS_RDWR \ + (TZC_DMC620_REGION_NS_RDWR | TZC_DMC620_REGION_S_RDWR) + +/* + * Contains pointer to the base addresses of all the DMC-620 instances. + * 'dmc_count' specifies the number of DMC base addresses contained in the + * array pointed to by dmc_base. + */ +typedef struct tzc_dmc620_driver_data { + const uintptr_t *dmc_base; + const unsigned int dmc_count; +} tzc_dmc620_driver_data_t; + +/* + * Contains region base, region top addresses and corresponding attributes + * for configuring TZC access region registers. + */ +typedef struct tzc_dmc620_acc_addr_data { + const unsigned long long region_base; + const unsigned long long region_top; + const unsigned int sec_attr; +} tzc_dmc620_acc_addr_data_t; + +/* + * Contains platform specific data for configuring TZC region base and + * region top address. 'acc_addr_count' specifies the number of + * valid entries in 'plat_acc_addr_data' array. + */ +typedef struct tzc_dmc620_config_data { + const tzc_dmc620_driver_data_t *plat_drv_data; + const tzc_dmc620_acc_addr_data_t *plat_acc_addr_data; + const uint8_t acc_addr_count; +} tzc_dmc620_config_data_t; + +/* Function prototypes */ +void arm_tzc_dmc620_setup(const tzc_dmc620_config_data_t *plat_config_data); + +#endif /* TZC_DMC620_H */ + diff --git a/arm-trusted-firmware/include/drivers/auth/auth_common.h b/arm-trusted-firmware/include/drivers/auth/auth_common.h new file mode 100644 index 0000000..e6859fd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/auth_common.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_COMMON_H +#define AUTH_COMMON_H + +/* + * Authentication framework common types + */ + +/* + * Type of parameters that can be extracted from an image and + * used for authentication + */ +typedef enum auth_param_type_enum { + AUTH_PARAM_NONE, + AUTH_PARAM_RAW_DATA, /* Raw image data */ + AUTH_PARAM_SIG, /* The image signature */ + AUTH_PARAM_SIG_ALG, /* The image signature algorithm */ + AUTH_PARAM_HASH, /* A hash (including the algorithm) */ + AUTH_PARAM_PUB_KEY, /* A public key */ + AUTH_PARAM_NV_CTR, /* A non-volatile counter */ +} auth_param_type_t; + +/* + * Defines an authentication parameter. The cookie will be interpreted by the + * image parser module. + */ +typedef struct auth_param_type_desc_s { + auth_param_type_t type; + void *cookie; +} auth_param_type_desc_t; + +/* + * Store a pointer to the authentication parameter and its length + */ +typedef struct auth_param_data_desc_s { + void *ptr; + unsigned int len; +} auth_param_data_desc_t; + +/* + * Authentication parameter descriptor, including type and value + */ +typedef struct auth_param_desc_s { + auth_param_type_desc_t *type_desc; + auth_param_data_desc_t data; +} auth_param_desc_t; + +/* + * The method type defines how an image is authenticated + */ +typedef enum auth_method_type_enum { + AUTH_METHOD_NONE = 0, + AUTH_METHOD_HASH, /* Authenticate by hash matching */ + AUTH_METHOD_SIG, /* Authenticate by PK operation */ + AUTH_METHOD_NV_CTR, /* Authenticate by Non-Volatile Counter */ + AUTH_METHOD_NUM /* Number of methods */ +} auth_method_type_t; + +/* + * Parameters for authentication by hash matching + */ +typedef struct auth_method_param_hash_s { + auth_param_type_desc_t *data; /* Data to hash */ + auth_param_type_desc_t *hash; /* Hash to match with */ +} auth_method_param_hash_t; + +/* + * Parameters for authentication by signature + */ +typedef struct auth_method_param_sig_s { + auth_param_type_desc_t *pk; /* Public key */ + auth_param_type_desc_t *sig; /* Signature to check */ + auth_param_type_desc_t *alg; /* Signature algorithm */ + auth_param_type_desc_t *data; /* Data signed */ +} auth_method_param_sig_t; + +/* + * Parameters for authentication by NV counter + */ +typedef struct auth_method_param_nv_ctr_s { + auth_param_type_desc_t *cert_nv_ctr; /* NV counter in certificate */ + auth_param_type_desc_t *plat_nv_ctr; /* NV counter in platform */ +} auth_method_param_nv_ctr_t; + +/* + * Authentication method descriptor + */ +typedef struct auth_method_desc_s { + auth_method_type_t type; + union { + auth_method_param_hash_t hash; + auth_method_param_sig_t sig; + auth_method_param_nv_ctr_t nv_ctr; + } param; +} auth_method_desc_t; + +/* + * Helper macro to define an authentication parameter type descriptor + */ +#define AUTH_PARAM_TYPE_DESC(_type, _cookie) \ + { \ + .type = _type, \ + .cookie = (void *)_cookie \ + } + +/* + * Helper macro to define an authentication parameter data descriptor + */ +#define AUTH_PARAM_DATA_DESC(_ptr, _len) \ + { \ + .ptr = (void *)_ptr, \ + .len = (unsigned int)_len \ + } + +#endif /* AUTH_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/auth_mod.h b/arm-trusted-firmware/include/drivers/auth/auth_mod.h new file mode 100644 index 0000000..94537f6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/auth_mod.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AUTH_MOD_H +#define AUTH_MOD_H + +#include +#include +#include +#include + +#include + +/* + * Image flags + */ +#define IMG_FLAG_AUTHENTICATED (1 << 0) + +#if COT_DESC_IN_DTB && !IMAGE_BL1 +/* + * Authentication image descriptor + */ +typedef struct auth_img_desc_s { + unsigned int img_id; + img_type_t img_type; + const struct auth_img_desc_s *parent; + auth_method_desc_t *img_auth_methods; + auth_param_desc_t *authenticated_data; +} auth_img_desc_t; +#else +/* + * Authentication image descriptor + */ +typedef struct auth_img_desc_s { + unsigned int img_id; + img_type_t img_type; + const struct auth_img_desc_s *parent; + const auth_method_desc_t *const img_auth_methods; + const auth_param_desc_t *const authenticated_data; +} auth_img_desc_t; +#endif /* COT_DESC_IN_DTB && !IMAGE_BL1 */ + +/* Public functions */ +#if TRUSTED_BOARD_BOOT +void auth_mod_init(void); +#else +static inline void auth_mod_init(void) +{ +} +#endif /* TRUSTED_BOARD_BOOT */ +int auth_mod_get_parent_id(unsigned int img_id, unsigned int *parent_id); +int auth_mod_verify_img(unsigned int img_id, + void *img_ptr, + unsigned int img_len); + +/* Macro to register a CoT defined as an array of auth_img_desc_t pointers */ +#define REGISTER_COT(_cot) \ + const auth_img_desc_t *const *const cot_desc_ptr = (_cot); \ + const size_t cot_desc_size = ARRAY_SIZE(_cot); \ + unsigned int auth_img_flags[MAX_NUMBER_IDS] + +extern const auth_img_desc_t *const *const cot_desc_ptr; +extern const size_t cot_desc_size; +extern unsigned int auth_img_flags[MAX_NUMBER_IDS]; + +#if defined(SPD_spmd) + +#define DEFINE_SIP_SP_PKG(n) DEFINE_SP_PKG(n, sip_sp_content_cert) +#define DEFINE_PLAT_SP_PKG(n) DEFINE_SP_PKG(n, plat_sp_content_cert) + +#define DEFINE_SP_PKG(n, cert) \ + static const auth_img_desc_t sp_pkg##n = { \ + .img_id = SP_PKG##n##_ID, \ + .img_type = IMG_RAW, \ + .parent = &cert, \ + .img_auth_methods = (const auth_method_desc_t[AUTH_METHOD_NUM]) { \ + [0] = { \ + .type = AUTH_METHOD_HASH, \ + .param.hash = { \ + .data = &raw_data, \ + .hash = &sp_pkg##n##_hash \ + } \ + } \ + } \ + } + +#endif + +#endif /* AUTH_MOD_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/crypto_mod.h b/arm-trusted-firmware/include/drivers/auth/crypto_mod.h new file mode 100644 index 0000000..73b2b99 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/crypto_mod.h @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CRYPTO_MOD_H +#define CRYPTO_MOD_H + +/* Return values */ +enum crypto_ret_value { + CRYPTO_SUCCESS = 0, + CRYPTO_ERR_INIT, + CRYPTO_ERR_HASH, + CRYPTO_ERR_SIGNATURE, + CRYPTO_ERR_DECRYPTION, + CRYPTO_ERR_UNKNOWN +}; + +#define CRYPTO_MAX_IV_SIZE 16U +#define CRYPTO_MAX_TAG_SIZE 16U + +/* Decryption algorithm */ +enum crypto_dec_algo { + CRYPTO_GCM_DECRYPT = 0 +}; + +/* Message digest algorithm */ +enum crypto_md_algo { + CRYPTO_MD_SHA256, + CRYPTO_MD_SHA384, + CRYPTO_MD_SHA512, +}; + +/* Maximum size as per the known stronger hash algorithm i.e.SHA512 */ +#define CRYPTO_MD_MAX_SIZE 64U + +/* + * Cryptographic library descriptor + */ +typedef struct crypto_lib_desc_s { + const char *name; + + /* Initialize library. This function is not expected to fail. All errors + * must be handled inside the function, asserting or panicing in case of + * a non-recoverable error */ + void (*init)(void); + + /* Verify a digital signature. Return one of the + * 'enum crypto_ret_value' options */ + int (*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); + + /* Verify a hash. Return one of the 'enum crypto_ret_value' options */ + int (*verify_hash)(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); + +#if MEASURED_BOOT + /* Calculate a hash. Return hash value */ + int (*calc_hash)(enum crypto_md_algo md_alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]); +#endif /* MEASURED_BOOT */ + + /* + * Authenticated decryption. Return one of the + * 'enum crypto_ret_value' options. + */ + int (*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); +} crypto_lib_desc_t; + +/* Public functions */ +#if CRYPTO_SUPPORT +void crypto_mod_init(void); +#else +static inline void crypto_mod_init(void) +{ +} +#endif /* CRYPTO_SUPPORT */ + +int crypto_mod_verify_signature(void *data_ptr, unsigned int data_len, + void *sig_ptr, unsigned int sig_len, + void *sig_alg_ptr, unsigned int sig_alg_len, + void *pk_ptr, unsigned int pk_len); +int crypto_mod_verify_hash(void *data_ptr, unsigned int data_len, + void *digest_info_ptr, unsigned int digest_info_len); +int crypto_mod_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); + +#if MEASURED_BOOT +int crypto_mod_calc_hash(enum crypto_md_algo alg, void *data_ptr, + unsigned int data_len, + unsigned char output[CRYPTO_MD_MAX_SIZE]); +#endif /* MEASURED_BOOT */ + +#if MEASURED_BOOT && TRUSTED_BOARD_BOOT +/* Macro to register a cryptographic library */ +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ + _calc_hash, _auth_decrypt) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .verify_signature = _verify_signature, \ + .verify_hash = _verify_hash, \ + .calc_hash = _calc_hash, \ + .auth_decrypt = _auth_decrypt \ + } +#elif TRUSTED_BOARD_BOOT +#define REGISTER_CRYPTO_LIB(_name, _init, _verify_signature, _verify_hash, \ + _auth_decrypt) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .verify_signature = _verify_signature, \ + .verify_hash = _verify_hash, \ + .auth_decrypt = _auth_decrypt \ + } +#elif MEASURED_BOOT +#define REGISTER_CRYPTO_LIB(_name, _init, _calc_hash) \ + const crypto_lib_desc_t crypto_lib_desc = { \ + .name = _name, \ + .init = _init, \ + .calc_hash = _calc_hash, \ + } +#endif /* MEASURED_BOOT && TRUSTED_BOARD_BOOT */ + +extern const crypto_lib_desc_t crypto_lib_desc; + +#endif /* CRYPTO_MOD_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/img_parser_mod.h b/arm-trusted-firmware/include/drivers/auth/img_parser_mod.h new file mode 100644 index 0000000..b2fb60e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/img_parser_mod.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMG_PARSER_MOD_H +#define IMG_PARSER_MOD_H + +#include + +/* + * Return values + */ +enum img_parser_ret_value { + IMG_PARSER_OK, + IMG_PARSER_ERR, /* Parser internal error */ + IMG_PARSER_ERR_FORMAT, /* Malformed image */ + IMG_PARSER_ERR_NOT_FOUND /* Authentication data not found */ +}; + +/* + * Image types. A parser should be instantiated and registered for each type + */ +typedef enum img_type_enum { + IMG_RAW, /* Binary image */ + IMG_PLAT, /* Platform specific format */ + IMG_CERT, /* X509v3 certificate */ + IMG_MAX_TYPES, +} img_type_t; + +/* Image parser library structure */ +typedef struct img_parser_lib_desc_s { + img_type_t img_type; + const char *name; + + void (*init)(void); + int (*check_integrity)(void *img, unsigned int img_len); + int (*get_auth_param)(const auth_param_type_desc_t *type_desc, + void *img, unsigned int img_len, + void **param, unsigned int *param_len); +} img_parser_lib_desc_t; + +/* Exported functions */ +void img_parser_init(void); +int img_parser_check_integrity(img_type_t img_type, + void *img_ptr, unsigned int img_len); +int img_parser_get_auth_param(img_type_t img_type, + const auth_param_type_desc_t *type_desc, + void *img_ptr, unsigned int img_len, + void **param_ptr, unsigned int *param_len); + +/* Macro to register an image parser library */ +#define REGISTER_IMG_PARSER_LIB(_type, _name, _init, _check_int, _get_param) \ + static const img_parser_lib_desc_t __img_parser_lib_desc_##_type \ + __section(".img_parser_lib_descs") __used = { \ + .img_type = _type, \ + .name = _name, \ + .init = _init, \ + .check_integrity = _check_int, \ + .get_auth_param = _get_param \ + } + +#endif /* IMG_PARSER_MOD_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h new file mode 100644 index 0000000..a9c2352 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MBEDTLS_COMMON_H +#define MBEDTLS_COMMON_H + +void mbedtls_init(void); + +#endif /* MBEDTLS_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h new file mode 100644 index 0000000..8ad6d7a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2015-2021, Arm Limited. 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_RSA 1 +#define TF_MBEDTLS_ECDSA 2 +#define TF_MBEDTLS_RSA_AND_ECDSA 3 + +#define TF_MBEDTLS_USE_RSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA \ + || TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA) +#define TF_MBEDTLS_USE_ECDSA (TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_ECDSA \ + || TF_MBEDTLS_KEY_ALG_ID == TF_MBEDTLS_RSA_AND_ECDSA) + +/* + * 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 either Trusted Boot or Measured Boot require a stronger algorithm than + * SHA-256, pull in SHA-512 support. + */ +#if (TF_MBEDTLS_HASH_ALG_ID != TF_MBEDTLS_SHA256) /* TBB hash algo */ +#define MBEDTLS_SHA512_C +#else + /* TBB uses SHA-256, what about measured boot? */ +#if defined(TF_MBEDTLS_TPM_HASH_ALG_ID) && \ + (TF_MBEDTLS_TPM_HASH_ALG_ID != TF_MBEDTLS_SHA256) +#define MBEDTLS_SHA512_C +#endif +#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 +#include +#endif + +/* + * Determine Mbed TLS heap size + * 13312 = 13*1024 + * 11264 = 11*1024 + * 7168 = 7*1024 + */ +#if TF_MBEDTLS_USE_ECDSA +#define TF_MBEDTLS_HEAP_SIZE U(13312) +#elif TF_MBEDTLS_USE_RSA +#if TF_MBEDTLS_KEY_SIZE <= 2048 +#define TF_MBEDTLS_HEAP_SIZE U(7168) +#else +#define TF_MBEDTLS_HEAP_SIZE U(11264) +#endif +#endif + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h b/arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h new file mode 100644 index 0000000..a51faee --- /dev/null +++ b/arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_COT_COMMON_H +#define TBBR_COT_COMMON_H + +#include + +extern unsigned char tb_fw_hash_buf[HASH_DER_LEN]; +extern unsigned char scp_fw_hash_buf[HASH_DER_LEN]; +extern unsigned char nt_world_bl_hash_buf[HASH_DER_LEN]; + +extern auth_param_type_desc_t trusted_nv_ctr; +extern auth_param_type_desc_t subject_pk; +extern auth_param_type_desc_t sig; +extern auth_param_type_desc_t sig_alg; +extern auth_param_type_desc_t raw_data; + +extern auth_param_type_desc_t tb_fw_hash; +extern auth_param_type_desc_t tb_fw_config_hash; +extern auth_param_type_desc_t fw_config_hash; + +extern const auth_img_desc_t trusted_boot_fw_cert; +extern const auth_img_desc_t hw_config; + +#endif /* TBBR_COT_COMMON_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/chimp.h b/arm-trusted-firmware/include/drivers/brcm/chimp.h new file mode 100644 index 0000000..02d528b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/chimp.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SR_CHIMP_H +#define SR_CHIMP_H + +#include +#include +#include + +#include + +#define CHIMP_WINDOW_SIZE 0x400000 +#define CHIMP_ERROR_OFFSET 28 +#define CHIMP_ERROR_MASK 0xf0000000 + +#ifndef EMULATION_SETUP +#define CHIMP_HANDSHAKE_TIMEOUT_MS 10000 +#else +/* + * 1hr timeout for test in emulator + * By doing this ChiMP is given a chance to boot + * fully from the QSPI + * (on Palladium this takes upto 50 min depending on QSPI clk) + */ + +#define CHIMP_HANDSHAKE_TIMEOUT_MS 3600000 +#endif + +#define CHIMP_BPE_MODE_ID_PATTERN (0x25000000) +#define CHIMP_BPE_MODE_ID_MASK (0x7f000000) +#define NIC_RESET_RELEASE_TIMEOUT_US (10) + +/* written by M0, used by ChiMP ROM */ +#define SR_IN_SMARTNIC_MODE_BIT 0 +/* written by M0, used by ChiMP ROM */ +#define SR_CHIMP_SECURE_BOOT_BIT 1 +/* cleared by AP, set by ChiMP BC2 code */ +#define SR_FLASH_ACCESS_DONE_BIT 2 + +#ifdef USE_CHIMP +void bcm_chimp_write(uintptr_t addr, uint32_t value); +uint32_t bcm_chimp_read(uintptr_t addr); +uint32_t bcm_chimp_read_ctrl(uint32_t offset); +void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits); +void bcm_chimp_setbits(uintptr_t addr, uint32_t bits); +int bcm_chimp_is_nic_mode(void); +void bcm_chimp_fru_prog_done(bool status); +int bcm_chimp_handshake_done(void); +int bcm_chimp_wait_handshake(void); +/* Fastboot-related*/ +int bcm_chimp_initiate_fastboot(int fastboot_type); +#else +static inline void bcm_chimp_write(uintptr_t addr, uint32_t value) +{ +} +static inline uint32_t bcm_chimp_read(uintptr_t addr) +{ + return 0; +} +static inline uint32_t bcm_chimp_read_ctrl(uint32_t offset) +{ + return 0; +} +static inline void bcm_chimp_clrbits(uintptr_t addr, uint32_t bits) +{ +} +static inline void bcm_chimp_setbits(uintptr_t addr, uint32_t bits) +{ +} +static inline int bcm_chimp_is_nic_mode(void) +{ + return 0; +} +static inline void bcm_chimp_fru_prog_done(bool status) +{ +} +static inline int bcm_chimp_handshake_done(void) +{ + return 0; +} +static inline int bcm_chimp_wait_handshake(void) +{ + return 0; +} +static inline int bcm_chimp_initiate_fastboot(int fastboot_type) +{ + return 0; +} +#endif /* USE_CHIMP */ +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h b/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h new file mode 100644 index 0000000..9be361f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h @@ -0,0 +1,419 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BNXNVM_DEFS_H +#define BNXNVM_DEFS_H + +#if defined(__GNUC__) + #define PACKED_STRUCT __packed +#else /* non-GCC compiler */ + +#ifndef DOS_DRIVERS + #pragma pack(push) + #pragma pack(1) +#endif + #define PACKED_STRUCT +#endif + +typedef uint32_t u32_t; +typedef uint8_t u8_t; +typedef uint16_t u16_t; + +#define BNXNVM_DEFAULT_BLOCK_SIZE 4096 +#define BNXNVM_UNUSED_BYTE_VALUE 0xff + +#define NV_MAX_BLOCK_SIZE 16384 + +#define BITS_PER_BYTE (8) +#define SIZEOF_IN_BITS(x) (sizeof(x)*BITS_PER_BYTE) + +/************************/ +/* byte-swapping macros */ +/************************/ +#define BYTE_SWAP_16(x) \ + ((((u16_t)(x) & 0xff00) >> 8) | \ + (((u16_t)(x) & 0x00ff) << 8)) +#define BYTE_SWAP_32(x) \ + ((((u32_t)(x) & 0xff000000) >> 24) | \ + (((u32_t)(x) & 0x00ff0000) >> 8) | \ + (((u32_t)(x) & 0x0000ff00) << 8) | \ + (((u32_t)(x) & 0x000000ff) << 24)) + +/* auto-detect integer size */ +#define BYTE_SWAP_INT(x) \ + (SIZEOF_IN_BITS(x) == 16 ? BYTE_SWAP_16(x) : \ + SIZEOF_IN_BITS(x) == 32 ? BYTE_SWAP_32(x) : (x)) + +/********************************/ +/* Architecture-specific macros */ +/********************************/ +#ifdef __BIG_ENDIAN__ /* e.g. Motorola */ + + #define BE_INT16(x) (x) + #define BE_INT32(x) (x) + #define BE_INT(x) (x) + #define LE_INT16(x) BYTE_SWAP_16(x) + #define LE_INT32(x) BYTE_SWAP_32(x) + #define LE_INT(x) BYTE_SWAP_INT(x) + +#else /* Little Endian (e.g. Intel) */ + + #define LE_INT16(x) (x) + #define LE_INT32(x) (x) + #define LE_INT(x) (x) + #define BE_INT16(x) BYTE_SWAP_16(x) + #define BE_INT32(x) BYTE_SWAP_32(x) + #define BE_INT(x) BYTE_SWAP_INT(x) + +#endif + + +enum { + NV_OK = 0, + NV_NOT_NVRAM, + NV_BAD_MB, + NV_BAD_DIR_HEADER, + NV_BAD_DIR_ENTRY, + NV_FW_NOT_FOUND, +}; + +typedef struct { +#define BNXNVM_MASTER_BLOCK_SIG BE_INT32(0x424E5834) /*"BNX4"*/ + /* Signature*/ + u32_t sig; + /* Length of Master Block Header, in bytes [32] */ + u32_t length; + /* Block size, in bytes [4096] */ + u32_t block_size; + /* Byte-offset to Directory Block (translated) */ + u32_t directory_offset; + /* Byte-offset to Block Redirection Table (non-translated) */ + u32_t redirect_offset; + /* Size, in bytes of Reserved Blocks region (at end of NVRAM) */ + u32_t reserved_size; + /* + * Size of NVRAM (in bytes) - may be used to + * override auto-detected size + */ + u32_t nvram_size; + /* CRC-32 (IEEE 802.3 compatible) of the above */ + u32_t chksum; +} PACKED_STRUCT bnxnvm_master_block_header_t; + +typedef struct { +#define BNXNVM_DIRECTORY_BLOCK_SIG BE_INT32(0x44697230) /* "Dir0" */ + /* Signature */ + u32_t sig; + /* Length of Directory Header, in bytes [16] */ + u32_t length; + /* Number of Directory Entries */ + u32_t entries; + /* Length of each Directory Entry, in bytes [24] */ + u32_t entry_length; +} PACKED_STRUCT bnxnvm_directory_block_header_t; + +typedef struct { + /* Directory Entry Type (see enum bnxnvm_directory_type) */ + u16_t type; + /* Instance of this Directory Entry type (0-based) */ + u16_t ordinal; + /* + * Directory Entry Extension flags used to identify + * secondary instances of a type:ordinal combinations + */ + u16_t ext; + /* Directory Entry Attribute flags used to describe the item contents */ + u16_t attr; + /* Item location in NVRAM specified as offset (in bytes) */ + u32_t item_location; + /* + * Length of NVRAM item in bytes + * (including padding - multiple of block size) + */ + u32_t item_length; + /* Length of item data in bytes (excluding padding) */ + u32_t data_length; + /* + * CRC-32 (IEEE 802.3 compatible) of item data + * (excluding padding) (optional) + */ + u32_t data_chksum; +} PACKED_STRUCT bnxnvm_directory_entry_t; + +enum bnxnvm_version_format { + /* US-ASCII string (not necessarily null-terminated) */ + BNX_VERSION_FMT_ASCII = 0, + /* Each field 16-bits, displayed as unpadded decimal (e.g. "1.2.3.4") */ + BNX_VERSION_FMT_DEC = 1, + /* A single hexadecimal value, up to 64-bits (no dots) */ + BNX_VERSION_FMT_HEX = 2, + /* Multiple version values (three 8-bit version fields) */ + BNX_VERSION_FMT_MULTI = 3 +}; + +/* This structure definition must not change: */ +typedef struct { + u16_t flags; /* bit-flags (defaults to 0x0000) */ + u8_t version_format; /* enum bnxnvm_version_format */ + u8_t version_length; /* in bytes */ + u8_t version[16]; /* version value */ + u16_t dir_type; /* enum bnxnvm_directory_type */ + /* size of the entire trailer (to locate end of component data) */ + u16_t trailer_length; +#define BNXNVM_COMPONENT_TRAILER_SIG BE_INT32(0x54726c72) /* "Trlr" */ + u32_t sig; + u32_t chksum; /* CRC-32 of all bytes to this point */ +} PACKED_STRUCT bnxnvm_component_trailer_base_t; + +typedef struct { + /* + * new trailer members (e.g. digital signature) + * go here (insert at top): + */ + u8_t rsa_sig[256]; /* 2048-bit RSA-encrypted SHA-256 hash */ + bnxnvm_component_trailer_base_t base; +} PACKED_STRUCT bnxnvm_component_trailer_t; + +#define BNX_MAX_LEN_DIR_NAME 12 +#define BNX_MAX_LEN_DIR_DESC 50 +/********************************************************* + * NVRAM Directory Entry/Item Types, Names, and Descriptions + * + * If you see a name or description that needs improvement, + * please correct it or raise for discussion. + * When adding a new directory type, it would be appreciated + * if you also updated ../../libs/nvm/bnxt_nvm_str.c. + * DIR_NAME macros may contain up to 12 alpha-numeric + * US-ASCII characters only, camelCase is preferred for clarity. + * DIR_DESC macros may contain up to 50 US-ASCII characters + * providing a verbose description of the directory type. + */ +enum bnxnvm_directory_type { + /* 0x00 Unused directory entry, available for use */ + BNX_DIR_TYPE_UNUSED = 0, +#define BNX_DIR_NAME_UNUSED "unused" +#define BNX_DIR_DESC_UNUSED "Deleted directory entry, available for reuse" + /* 0x01 Package installation log */ + BNX_DIR_TYPE_PKG_LOG = 1, +#define BNX_DIR_NAME_PKG_LOG "pkgLog" +#define BNX_DIR_DESC_PKG_LOG "Package Installation Log" + BNX_DIR_TYPE_CHIMP_PATCH = 3, +#define BNX_DIR_NAME_CHIMP_PATCH "chimpPatch" +#define BNX_DIR_DESC_CHIMP_PATCH "ChiMP Patch Firmware" + /* 0x04 ChiMP firmware: Boot Code phase 1 */ + BNX_DIR_TYPE_BOOTCODE = 4, +#define BNX_DIR_NAME_BOOTCODE "chimpBoot" +#define BNX_DIR_DESC_BOOTCODE "Chip Management Processor Boot Firmware" + /* 0x05 VPD data block */ + BNX_DIR_TYPE_VPD = 5, +#define BNX_DIR_NAME_VPD "VPD" +#define BNX_DIR_DESC_VPD "Vital Product Data" + /* 0x06 Exp ROM MBA */ + BNX_DIR_TYPE_EXP_ROM_MBA = 6, +#define BNX_DIR_NAME_EXP_ROM_MBA "MBA" +#define BNX_DIR_DESC_EXP_ROM_MBA "Multiple Boot Agent Expansion ROM" + BNX_DIR_TYPE_AVS = 7, /* 0x07 AVS FW */ +#define BNX_DIR_NAME_AVS "AVS" +#define BNX_DIR_DESC_AVS "Adaptive Voltage Scaling Firmware" + BNX_DIR_TYPE_PCIE = 8, /* 0x08 PCIE FW */ +#define BNX_DIR_NAME_PCIE "PCIEucode" +#define BNX_DIR_DESC_PCIE "PCIe Microcode" + BNX_DIR_TYPE_PORT_MACRO = 9, /* 0x09 PORT MACRO FW */ +#define BNX_DIR_NAME_PORT_MACRO "portMacro" +#define BNX_DIR_DESC_PORT_MACRO "Port Macro Firmware" + BNX_DIR_TYPE_APE_FW = 10, /* 0x0A APE Firmware */ +#define BNX_DIR_NAME_APE_FW "apeFW" +#define BNX_DIR_DESC_APE_FW "Application Processing Engine Firmware" + /* 0x0B Patch firmware executed by APE ROM */ + BNX_DIR_TYPE_APE_PATCH = 11, +#define BNX_DIR_NAME_APE_PATCH "apePatch" +#define BNX_DIR_DESC_APE_PATCH "APE Patch Firmware" + BNX_DIR_TYPE_KONG_FW = 12, /* 0x0C Kong Firmware */ +#define BNX_DIR_NAME_KONG_FW "kongFW" +#define BNX_DIR_DESC_KONG_FW "Kong Firmware" + /* 0x0D Patch firmware executed by Kong ROM */ + BNX_DIR_TYPE_KONG_PATCH = 13, +#define BNX_DIR_NAME_KONG_PATCH "kongPatch" +#define BNX_DIR_DESC_KONG_PATCH "Kong Patch Firmware" + BNX_DIR_TYPE_BONO_FW = 14, /* 0x0E Bono Firmware */ +#define BNX_DIR_NAME_BONO_FW "bonoFW" +#define BNX_DIR_DESC_BONO_FW "Bono Firmware" + /* 0x0F Patch firmware executed by Bono ROM */ + BNX_DIR_TYPE_BONO_PATCH = 15, +#define BNX_DIR_NAME_BONO_PATCH "bonoPatch" +#define BNX_DIR_DESC_BONO_PATCH "Bono Patch Firmware" + BNX_DIR_TYPE_TANG_FW = 16, /* 0x10 Tang firmware */ +#define BNX_DIR_NAME_TANG_FW "tangFW" +#define BNX_DIR_DESC_TANG_FW "Tang Firmware" + /* 0x11 Patch firmware executed by Tang ROM */ + BNX_DIR_TYPE_TANG_PATCH = 17, +#define BNX_DIR_NAME_TANG_PATCH "tangPatch" +#define BNX_DIR_DESC_TANG_PATCH "Tang Patch Firmware" + /* 0x12 ChiMP firmware: Boot Code phase 2 (loaded by phase 1) */ + BNX_DIR_TYPE_BOOTCODE_2 = 18, +#define BNX_DIR_NAME_BOOTCODE_2 "chimpHWRM" +#define BNX_DIR_DESC_BOOTCODE_2 "ChiMP Hardware Resource Manager Firmware" + BNX_DIR_TYPE_CCM = 19, /* 0x13 CCM ROM binary */ +#define BNX_DIR_NAME_CCM "CCM" +#define BNX_DIR_DESC_CCM "Comprehensive Configuration Management" + /* 0x14 PCI-IDs, PCI-related configuration properties */ + BNX_DIR_TYPE_PCI_CFG = 20, +#define BNX_DIR_NAME_PCI_CFG "pciCFG" +#define BNX_DIR_DESC_PCI_CFG "PCIe Configuration Data" + + BNX_DIR_TYPE_TSCF_UCODE = 21, /* 0x15 TSCF micro-code */ +#define BNX_DIR_NAME_TSCF_UCODE "PHYucode" +#define BNX_DIR_DESC_TSCF_UCODE "Falcon PHY Microcode" + BNX_DIR_TYPE_ISCSI_BOOT = 22, /* 0x16 iSCSI Boot */ +#define BNX_DIR_NAME_ISCSI_BOOT "iSCSIboot" +#define BNX_DIR_DESC_ISCSI_BOOT "iSCSI Boot Software Initiator" + /* 0x18 iSCSI Boot IPV6 - ***DEPRECATED*** */ + BNX_DIR_TYPE_ISCSI_BOOT_IPV6 = 24, + /* 0x19 iSCSI Boot IPV4N6 - ***DEPRECATED*** */ + BNX_DIR_TYPE_ISCSI_BOOT_IPV4N6 = 25, + BNX_DIR_TYPE_ISCSI_BOOT_CFG = 26, /* 0x1a iSCSI Boot CFG v6 */ +#define BNX_DIR_NAME_ISCSI_BOOT_CFG "iSCSIcfg" +#define BNX_DIR_DESC_ISCSI_BOOT_CFG "iSCSI Boot Configuration Data" + BNX_DIR_TYPE_EXT_PHY = 27, /* 0x1b External PHY FW */ +#define BNX_DIR_NAME_EXT_PHY "extPHYfw" +#define BNX_DIR_DESC_EXT_PHY "External PHY Firmware" + BNX_DIR_TYPE_MODULES_PN = 28, /* 0x1c Modules PartNum list */ +#define BNX_DIR_NAME_MODULES_PN "modPartNums" +#define BNX_DIR_DESC_MODULES_PN "Optical Modules Part Number List" + BNX_DIR_TYPE_SHARED_CFG = 40, /* 0x28 shared configuration block */ +#define BNX_DIR_NAME_SHARED_CFG "sharedCFG" +#define BNX_DIR_DESC_SHARED_CFG "Shared Configuration Data" + BNX_DIR_TYPE_PORT_CFG = 41, /* 0x29 port configuration block */ +#define BNX_DIR_NAME_PORT_CFG "portCFG" +#define BNX_DIR_DESC_PORT_CFG "Port Configuration Data" + BNX_DIR_TYPE_FUNC_CFG = 42, /* 0x2A func configuration block */ +#define BNX_DIR_NAME_FUNC_CFG "funcCFG" +#define BNX_DIR_DESC_FUNC_CFG "Function Configuration Data" + + /* Management Firmware (TruManage) related dir entries*/ + /* 0x30 Management firmware configuration (see BMCFG library)*/ + BNX_DIR_TYPE_MGMT_CFG = 48, +#define BNX_DIR_NAME_MGMT_CFG "mgmtCFG" +#define BNX_DIR_DESC_MGMT_CFG "Out-of-band Management Configuration Data" + BNX_DIR_TYPE_MGMT_DATA = 49, /* 0x31 "Opaque Management Data" */ +#define BNX_DIR_NAME_MGMT_DATA "mgmtData" +#define BNX_DIR_DESC_MGMT_DATA "Out-of-band Management Data" + BNX_DIR_TYPE_MGMT_WEB_DATA = 50, /* 0x32 "Web GUI" file data */ +#define BNX_DIR_NAME_MGMT_WEB_DATA "webData" +#define BNX_DIR_DESC_MGMT_WEB_DATA "Out-of-band Management Web Data" + /* 0x33 "Web GUI" file metadata */ + BNX_DIR_TYPE_MGMT_WEB_META = 51, +#define BNX_DIR_NAME_MGMT_WEB_META "webMeta" +#define BNX_DIR_DESC_MGMT_WEB_META "Out-of-band Management Web Metadata" + /* 0x34 Management firmware Event Log (a.k.a. "SEL") */ + BNX_DIR_TYPE_MGMT_EVENT_LOG = 52, +#define BNX_DIR_NAME_MGMT_EVENT_LOG "eventLog" +#define BNX_DIR_DESC_MGMT_EVENT_LOG "Out-of-band Management Event Log" + /* 0x35 Management firmware Audit Log */ + BNX_DIR_TYPE_MGMT_AUDIT_LOG = 53 +#define BNX_DIR_NAME_MGMT_AUDIT_LOG "auditLog" +#define BNX_DIR_DESC_MGMT_AUDIT_LOG "Out-of-band Management Audit Log" + +}; + +/* For backwards compatibility only, may be removed later */ +#define BNX_DIR_TYPE_ISCSI_BOOT_CFG6 BNX_DIR_TYPE_ISCSI_BOOT_CFG + +/* Firmware NVM items of "APE BIN" format are identified with + * the following macro: + */ +#define BNX_DIR_TYPE_IS_APE_BIN_FMT(type)\ + ((type) == BNX_DIR_TYPE_CHIMP_PATCH \ + || (type) == BNX_DIR_TYPE_BOOTCODE \ + || (type) == BNX_DIR_TYPE_BOOTCODE_2 \ + || (type) == BNX_DIR_TYPE_APE_FW \ + || (type) == BNX_DIR_TYPE_APE_PATCH \ + || (type) == BNX_DIR_TYPE_TANG_FW \ + || (type) == BNX_DIR_TYPE_TANG_PATCH \ + || (type) == BNX_DIR_TYPE_KONG_FW \ + || (type) == BNX_DIR_TYPE_KONG_PATCH \ + || (type) == BNX_DIR_TYPE_BONO_FW \ + || (type) == BNX_DIR_TYPE_BONO_PATCH \ + ) + +/* Other (non APE BIN) executable NVM items are identified with + * the following macro: + */ +#define BNX_DIR_TYPE_IS_OTHER_EXEC(type)\ + ((type) == BNX_DIR_TYPE_AVS \ + || (type) == BNX_DIR_TYPE_EXP_ROM_MBA \ + || (type) == BNX_DIR_TYPE_PCIE \ + || (type) == BNX_DIR_TYPE_TSCF_UCODE \ + || (type) == BNX_DIR_TYPE_EXT_PHY \ + || (type) == BNX_DIR_TYPE_CCM \ + || (type) == BNX_DIR_TYPE_ISCSI_BOOT \ + ) + +/* Executable NVM items (e.g. microcode, firmware, software) identified + * with the following macro + */ +#define BNX_DIR_TYPE_IS_EXECUTABLE(type) \ + (BNX_DIR_TYPE_IS_APE_BIN_FMT(type) \ + || BNX_DIR_TYPE_IS_OTHER_EXEC(type)) + +#define BNX_DIR_ORDINAL_FIRST 0 /* Ordinals are 0-based */ + +/* No extension flags for this directory entry */ +#define BNX_DIR_EXT_NONE 0 +/* Directory entry is inactive (not used, not hidden, + * not available for reuse) + */ +#define BNX_DIR_EXT_INACTIVE (1 << 0) +/* Directory content is a temporary staging location for + * updating the primary (non-update) directory entry contents + * (e.g. performing a secure firmware update) + */ +#define BNX_DIR_EXT_UPDATE (1 << 1) + +/* No attribute flags set for this directory entry */ +#define BNX_DIR_ATTR_NONE 0 +/* Directory entry checksum of contents is purposely incorrect */ +#define BNX_DIR_ATTR_NO_CHKSUM (1 << 0) +/* Directory contents are in the form of a property-stream + * (e.g. configuration properties) + */ +#define BNX_DIR_ATTR_PROP_STREAM (1 << 1) +/* Directory content (e.g. iSCSI boot) supports IPv4 */ +#define BNX_DIR_ATTR_IPv4 (1 << 2) +/* Directory content (e.g. iSCSI boot) supports IPv6 */ +#define BNX_DIR_ATTR_IPv6 (1 << 3) +/* Directory content includes standard NVM component trailer + * (bnxnvm_component_trailer_t) + */ +#define BNX_DIR_ATTR_TRAILER (1 << 4) + +/* Index of tab-delimited fields in each package log + * (BNX_DIR_TYPE_PKG_LOG) record (\n-terminated line): + */ +enum bnxnvm_pkglog_field_index { + /* Package installation date/time in ISO-8601 format */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_TIMESTAMP = 0, + /* Installed package description (from package header) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_DESCRIPTION = 1, + /* Installed package version string (from package header) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_VERSION = 2, + /* Installed package creation/modification timestamp (ISO-8601) */ + BNX_PKG_LOG_FIELD_IDX_PKG_TIMESTAMP = 3, + /* Installed package checksum in hexadecimal (CRC-32) or "N/A" */ + BNX_PKG_LOG_FIELD_IDX_PKG_CHECKSUM = 4, + /* Total number of packaged items applied in this installation */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_ITEMS = 5, + /* Hexadecimal bit-mask identifying which items were installed */ + BNX_PKG_LOG_FIELD_IDX_INSTALLED_MASK = 6 +}; + +#if !defined(__GNUC__) +#ifndef DOS_DRIVERS + #pragma pack(pop) /* original packing */ +#endif +#endif + +#endif /* Don't add anything after this line */ diff --git a/arm-trusted-firmware/include/drivers/brcm/dmu.h b/arm-trusted-firmware/include/drivers/brcm/dmu.h new file mode 100644 index 0000000..3a57bbd --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/dmu.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DMU_H +#define DMU_H + +/* Clock field should be 2 bits only */ +#define CLKCONFIG_MASK 0x3 + +/* argument */ +struct DmuBlockEnable { + uint32_t sotp:1; + uint32_t pka_rng:1; + uint32_t crypto:1; + uint32_t spl:1; + uint32_t cdru_vgm:1; + uint32_t apbs_s0_idm:1; + uint32_t smau_s0_idm:1; +}; + +/* prototype */ +uint32_t bcm_dmu_block_enable(struct DmuBlockEnable dbe); +uint32_t bcm_dmu_block_disable(struct DmuBlockEnable dbe); +uint32_t bcm_set_ihost_pll_freq(uint32_t cluster_num, int ihost_pll_freq_sel); +uint32_t bcm_get_ihost_pll_freq(uint32_t cluster_num); + +#define PLL_FREQ_BYPASS 0x0 +#define PLL_FREQ_FULL 0x1 +#define PLL_FREQ_HALF 0x2 +#define PLL_FREQ_QRTR 0x3 + +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h b/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h new file mode 100644 index 0000000..67f0602 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_H +#define EMMC_H + +#include + +#include + +#include + +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_pboot_hal_memory_drv.h" + +/* ------------------------------------------------------------------- */ +#define EXT_CSD_SIZE 512 + +#ifdef PLAT_SD_MAX_READ_LENGTH +#define SD_MAX_READ_LENGTH PLAT_SD_MAX_READ_LENGTH +#ifdef USE_EMMC_LARGE_BLK_TRANSFER_LENGTH +#define SD_MAX_BLK_TRANSFER_LENGTH 0x10000000 +#else +#define SD_MAX_BLK_TRANSFER_LENGTH 0x1000 +#endif +#else +#define SD_MAX_READ_LENGTH EMMC_BLOCK_SIZE +#define SD_MAX_BLK_TRANSFER_LENGTH EMMC_BLOCK_SIZE +#endif + +struct emmc_global_buffer { + union { + uint8_t Ext_CSD_storage[EXT_CSD_SIZE]; + uint8_t tempbuf[SD_MAX_READ_LENGTH]; + } u; +}; + +struct emmc_global_vars { + struct sd_card_data cardData; + struct sd_handle sdHandle; + struct sd_dev sdDevice; + struct sd_card_info sdCard; + unsigned int init_done; +}; + +#define ICFG_SDIO0_CAP0__SLOT_TYPE_R 27 +#define ICFG_SDIO0_CAP0__INT_MODE_R 26 +#define ICFG_SDIO0_CAP0__SYS_BUS_64BIT_R 25 +#define ICFG_SDIO0_CAP0__VOLTAGE_1P8V_R 24 +#define ICFG_SDIO0_CAP0__VOLTAGE_3P0V_R 23 +#define ICFG_SDIO0_CAP0__VOLTAGE_3P3V_R 22 +#define ICFG_SDIO0_CAP0__SUSPEND_RESUME_R 21 +#define ICFG_SDIO0_CAP0__SDMA_R 20 +#define ICFG_SDIO0_CAP0__HIGH_SPEED_R 19 +#define ICFG_SDIO0_CAP0__ADMA2_R 18 +#define ICFG_SDIO0_CAP0__EXTENDED_MEDIA_R 17 +#define ICFG_SDIO0_CAP0__MAX_BLOCK_LEN_R 15 +#define ICFG_SDIO0_CAP0__BASE_CLK_FREQ_R 7 +#define ICFG_SDIO0_CAP0__TIMEOUT_UNIT_R 6 +#define ICFG_SDIO0_CAP0__TIMEOUT_CLK_FREQ_R 0 +#define ICFG_SDIO0_CAP1__SPI_BLOCK_MODE_R 22 +#define ICFG_SDIO0_CAP1__SPI_MODE_R 21 +#define ICFG_SDIO0_CAP1__CLK_MULT_R 13 +#define ICFG_SDIO0_CAP1__RETUNING_MODE_R 11 +#define ICFG_SDIO0_CAP1__TUNE_SDR50_R 10 +#define ICFG_SDIO0_CAP1__TIME_RETUNE_R 6 +#define ICFG_SDIO0_CAP1__DRIVER_D_R 5 +#define ICFG_SDIO0_CAP1__DRIVER_C_R 4 +#define ICFG_SDIO0_CAP1__DRIVER_A_R 3 +#define ICFG_SDIO0_CAP1__DDR50_R 2 +#define ICFG_SDIO0_CAP1__SDR104_R 1 +#define ICFG_SDIO0_CAP1__SDR50_R 0 + +#define SDIO0_CTRL_REGS_BASE_ADDR (SDIO0_EMMCSDXC_SYSADDR) +#define SDIO0_IDM_RESET_CTRL_ADDR (SDIO_IDM0_IDM_RESET_CONTROL) + +#define EMMC_CTRL_REGS_BASE_ADDR SDIO0_CTRL_REGS_BASE_ADDR +#define EMMC_IDM_RESET_CTRL_ADDR SDIO0_IDM_RESET_CTRL_ADDR +#define EMMC_IDM_IO_CTRL_DIRECT_ADDR SDIO_IDM0_IO_CONTROL_DIRECT + +extern struct emmc_global_buffer *emmc_global_buf_ptr; + +extern struct emmc_global_vars *emmc_global_vars_ptr; + +#define EMMC_CARD_DETECT_TIMEOUT_MS 1200 +#define EMMC_CMD_TIMEOUT_MS 200 +#define EMMC_BUSY_CMD_TIMEOUT_MS 200 +#define EMMC_CLOCK_SETTING_TIMEOUT_MS 100 +#define EMMC_WFE_RETRY 40000 +#define EMMC_WFE_RETRY_DELAY_US 10 + +#ifdef EMMC_DEBUG +#define EMMC_TRACE INFO +#else +#define EMMC_TRACE(...) +#endif + +#endif /* EMMC_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h new file mode 100644 index 0000000..c4c2a58 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EMMC_API_H +#define EMMC_API_H + +#include "bcm_emmc.h" +#include "emmc_pboot_hal_memory_drv.h" + +#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 + * EMMC_ERASE_GROUP_SIZE is the number of writeable + * units (each unit is 512 bytes) + */ + +/* Start address (sector) */ +#define EMMC_ERASE_START_BLOCK 0x0 +/* Number of blocks to be erased */ +#define EMMC_ERASE_BLOCK_COUNT 0x1 + +#define EMMC_ERASE_USER_AREA 0 +#define EMMC_ERASE_BOOT_PARTITION1 1 +#define EMMC_ERASE_BOOT_PARTITION2 2 + +/* eMMC partition to be erased */ +#define EMMC_ERASE_PARTITION EMMC_ERASE_USER_AREA +#endif + +uint32_t bcm_emmc_init(bool card_rdy_only); +void emmc_deinit(void); + +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int emmc_erase(uintptr_t mem_addr, size_t num_of_blocks, uint32_t partition); +#endif + +uint32_t emmc_partition_select(uint32_t partition); +uint32_t emmc_read(uintptr_t mem_addr, uintptr_t storage_addr, + size_t storage_size, size_t bytes_to_read); +uint32_t emmc_write(uintptr_t mem_addr, uintptr_t data_addr, + size_t bytes_to_write); +#endif /* EMMC_API_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h new file mode 100644 index 0000000..96c333d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h @@ -0,0 +1,1116 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_RDB_SD4_EMMC_TOP_H +#define BRCM_RDB_SD4_EMMC_TOP_H + +#define SD4_EMMC_TOP_SYSADDR_OFFSET 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_TYPE uint32_t +#define SD4_EMMC_TOP_SYSADDR_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_SYSADDR_SYSADDR_SHIFT 0 +#define SD4_EMMC_TOP_SYSADDR_SYSADDR_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_BLOCK_OFFSET 0x00000004 +#define SD4_EMMC_TOP_BLOCK_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BLOCK_TYPE uint32_t +#define SD4_EMMC_TOP_BLOCK_RESERVED_MASK 0x00008000 +#define SD4_EMMC_TOP_BLOCK_BCNT_SHIFT 16 +#define SD4_EMMC_TOP_BLOCK_BCNT_MASK 0xFFFF0000 +#define SD4_EMMC_TOP_BLOCK_HSBS_SHIFT 12 +#define SD4_EMMC_TOP_BLOCK_HSBS_MASK 0x00007000 +#define SD4_EMMC_TOP_BLOCK_TBS_SHIFT 0 +#define SD4_EMMC_TOP_BLOCK_TBS_MASK 0x00000FFF + +#define SD4_EMMC_TOP_ARG_OFFSET 0x00000008 +#define SD4_EMMC_TOP_ARG_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ARG_TYPE uint32_t +#define SD4_EMMC_TOP_ARG_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ARG_ARG_SHIFT 0 +#define SD4_EMMC_TOP_ARG_ARG_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_CMD_OFFSET 0x0000000C +#define SD4_EMMC_TOP_CMD_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMD_TYPE uint32_t +#define SD4_EMMC_TOP_CMD_RESERVED_MASK 0xC004FFC0 +#define SD4_EMMC_TOP_CMD_CIDX_SHIFT 24 +#define SD4_EMMC_TOP_CMD_CIDX_MASK 0x3F000000 +#define SD4_EMMC_TOP_CMD_CTYP_SHIFT 22 +#define SD4_EMMC_TOP_CMD_CTYP_MASK 0x00C00000 +#define SD4_EMMC_TOP_CMD_DPS_SHIFT 21 +#define SD4_EMMC_TOP_CMD_DPS_MASK 0x00200000 +#define SD4_EMMC_TOP_CMD_CCHK_EN_SHIFT 20 +#define SD4_EMMC_TOP_CMD_CCHK_EN_MASK 0x00100000 +#define SD4_EMMC_TOP_CMD_CRC_EN_SHIFT 19 +#define SD4_EMMC_TOP_CMD_CRC_EN_MASK 0x00080000 +#define SD4_EMMC_TOP_CMD_RTSEL_SHIFT 16 +#define SD4_EMMC_TOP_CMD_RTSEL_MASK 0x00030000 +#define SD4_EMMC_TOP_CMD_MSBS_SHIFT 5 +#define SD4_EMMC_TOP_CMD_MSBS_MASK 0x00000020 +#define SD4_EMMC_TOP_CMD_DTDS_SHIFT 4 +#define SD4_EMMC_TOP_CMD_DTDS_MASK 0x00000010 +#define SD4_EMMC_TOP_CMD_ACMDEN_SHIFT 2 +#define SD4_EMMC_TOP_CMD_ACMDEN_MASK 0x0000000C +#define SD4_EMMC_TOP_CMD_BCEN_SHIFT 1 +#define SD4_EMMC_TOP_CMD_BCEN_MASK 0x00000002 +#define SD4_EMMC_TOP_CMD_DMA_SHIFT 0 +#define SD4_EMMC_TOP_CMD_DMA_MASK 0x00000001 + +#define SD4_EMMC_TOP_CMD_SD4_OFFSET 0x0000000C +#define SD4_EMMC_TOP_CMD_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMD_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CMD_SD4_RESERVED_MASK 0xC004FE00 +#define SD4_EMMC_TOP_CMD_SD4_CIDX_SHIFT 24 +#define SD4_EMMC_TOP_CMD_SD4_CIDX_MASK 0x3F000000 +#define SD4_EMMC_TOP_CMD_SD4_CTYP_SHIFT 22 +#define SD4_EMMC_TOP_CMD_SD4_CTYP_MASK 0x00C00000 +#define SD4_EMMC_TOP_CMD_SD4_DPS_SHIFT 21 +#define SD4_EMMC_TOP_CMD_SD4_DPS_MASK 0x00200000 +#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_SHIFT 20 +#define SD4_EMMC_TOP_CMD_SD4_CCHK_EN_MASK 0x00100000 +#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_SHIFT 19 +#define SD4_EMMC_TOP_CMD_SD4_CRC_EN_MASK 0x00080000 +#define SD4_EMMC_TOP_CMD_SD4_RTSEL_SHIFT 16 +#define SD4_EMMC_TOP_CMD_SD4_RTSEL_MASK 0x00030000 +#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_SHIFT 8 +#define SD4_EMMC_TOP_CMD_SD4_RESPIRQDIS_MASK 0x00000100 +#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_SHIFT 7 +#define SD4_EMMC_TOP_CMD_SD4_RESPERRCHKEN_MASK 0x00000080 +#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_SHIFT 6 +#define SD4_EMMC_TOP_CMD_SD4_RESPR1R5_MASK 0x00000040 +#define SD4_EMMC_TOP_CMD_SD4_MSBS_SHIFT 5 +#define SD4_EMMC_TOP_CMD_SD4_MSBS_MASK 0x00000020 +#define SD4_EMMC_TOP_CMD_SD4_DTDS_SHIFT 4 +#define SD4_EMMC_TOP_CMD_SD4_DTDS_MASK 0x00000010 +#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_SHIFT 2 +#define SD4_EMMC_TOP_CMD_SD4_ACMDEN_MASK 0x0000000C +#define SD4_EMMC_TOP_CMD_SD4_BCEN_SHIFT 1 +#define SD4_EMMC_TOP_CMD_SD4_BCEN_MASK 0x00000002 +#define SD4_EMMC_TOP_CMD_SD4_DMA_SHIFT 0 +#define SD4_EMMC_TOP_CMD_SD4_DMA_MASK 0x00000001 + +#define SD4_EMMC_TOP_RESP0_OFFSET 0x00000010 +#define SD4_EMMC_TOP_RESP0_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP0_TYPE uint32_t +#define SD4_EMMC_TOP_RESP0_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP0_RESP0_SHIFT 0 +#define SD4_EMMC_TOP_RESP0_RESP0_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP2_OFFSET 0x00000014 +#define SD4_EMMC_TOP_RESP2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP2_TYPE uint32_t +#define SD4_EMMC_TOP_RESP2_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP2_RESP2_SHIFT 0 +#define SD4_EMMC_TOP_RESP2_RESP2_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP4_OFFSET 0x00000018 +#define SD4_EMMC_TOP_RESP4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP4_TYPE uint32_t +#define SD4_EMMC_TOP_RESP4_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP4_RESP4_SHIFT 0 +#define SD4_EMMC_TOP_RESP4_RESP4_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_RESP6_OFFSET 0x0000001C +#define SD4_EMMC_TOP_RESP6_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_RESP6_TYPE uint32_t +#define SD4_EMMC_TOP_RESP6_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_RESP6_RESP6_SHIFT 0 +#define SD4_EMMC_TOP_RESP6_RESP6_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_BUFDAT_OFFSET 0x00000020 +#define SD4_EMMC_TOP_BUFDAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BUFDAT_TYPE uint32_t +#define SD4_EMMC_TOP_BUFDAT_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_BUFDAT_BUFDAT_SHIFT 0 +#define SD4_EMMC_TOP_BUFDAT_BUFDAT_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_PSTATE_OFFSET 0x00000024 +#define SD4_EMMC_TOP_PSTATE_DEFAULT 0x1FFC0000 +#define SD4_EMMC_TOP_PSTATE_TYPE uint32_t +#define SD4_EMMC_TOP_PSTATE_RESERVED_MASK 0xE000F0F0 +#define SD4_EMMC_TOP_PSTATE_DLS7_4_SHIFT 25 +#define SD4_EMMC_TOP_PSTATE_DLS7_4_MASK 0x1E000000 +#define SD4_EMMC_TOP_PSTATE_CLSL_SHIFT 24 +#define SD4_EMMC_TOP_PSTATE_CLSL_MASK 0x01000000 +#define SD4_EMMC_TOP_PSTATE_DLS3_0_SHIFT 20 +#define SD4_EMMC_TOP_PSTATE_DLS3_0_MASK 0x00F00000 +#define SD4_EMMC_TOP_PSTATE_WPSL_SHIFT 19 +#define SD4_EMMC_TOP_PSTATE_WPSL_MASK 0x00080000 +#define SD4_EMMC_TOP_PSTATE_CDPL_SHIFT 18 +#define SD4_EMMC_TOP_PSTATE_CDPL_MASK 0x00040000 +#define SD4_EMMC_TOP_PSTATE_CSS_SHIFT 17 +#define SD4_EMMC_TOP_PSTATE_CSS_MASK 0x00020000 +#define SD4_EMMC_TOP_PSTATE_CINS_SHIFT 16 +#define SD4_EMMC_TOP_PSTATE_CINS_MASK 0x00010000 +#define SD4_EMMC_TOP_PSTATE_BREN_SHIFT 11 +#define SD4_EMMC_TOP_PSTATE_BREN_MASK 0x00000800 +#define SD4_EMMC_TOP_PSTATE_BWEN_SHIFT 10 +#define SD4_EMMC_TOP_PSTATE_BWEN_MASK 0x00000400 +#define SD4_EMMC_TOP_PSTATE_RXACT_SHIFT 9 +#define SD4_EMMC_TOP_PSTATE_RXACT_MASK 0x00000200 +#define SD4_EMMC_TOP_PSTATE_WXACT_SHIFT 8 +#define SD4_EMMC_TOP_PSTATE_WXACT_MASK 0x00000100 +#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_SHIFT 3 +#define SD4_EMMC_TOP_PSTATE_RETUNE_REQ_MASK 0x00000008 +#define SD4_EMMC_TOP_PSTATE_DATACT_SHIFT 2 +#define SD4_EMMC_TOP_PSTATE_DATACT_MASK 0x00000004 +#define SD4_EMMC_TOP_PSTATE_DATINH_SHIFT 1 +#define SD4_EMMC_TOP_PSTATE_DATINH_MASK 0x00000002 +#define SD4_EMMC_TOP_PSTATE_CMDINH_SHIFT 0 +#define SD4_EMMC_TOP_PSTATE_CMDINH_MASK 0x00000001 + +#define SD4_EMMC_TOP_PSTATE_SD4_OFFSET 0x00000024 +#define SD4_EMMC_TOP_PSTATE_SD4_DEFAULT 0x01FC00F0 +#define SD4_EMMC_TOP_PSTATE_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_PSTATE_SD4_RESERVED_MASK 0x1E00F000 +#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_SHIFT 31 +#define SD4_EMMC_TOP_PSTATE_SD4_STBLDET_MASK 0x80000000 +#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_SHIFT 30 +#define SD4_EMMC_TOP_PSTATE_SD4_LANESYNC_MASK 0x40000000 +#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_SHIFT 29 +#define SD4_EMMC_TOP_PSTATE_SD4_INDORMNTSTATE_MASK 0x20000000 +#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_SHIFT 24 +#define SD4_EMMC_TOP_PSTATE_SD4_CLSL_MASK 0x01000000 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_SHIFT 20 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS3_0_MASK 0x00F00000 +#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_SHIFT 19 +#define SD4_EMMC_TOP_PSTATE_SD4_WPSL_MASK 0x00080000 +#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_SHIFT 18 +#define SD4_EMMC_TOP_PSTATE_SD4_CDPL_MASK 0x00040000 +#define SD4_EMMC_TOP_PSTATE_SD4_CSS_SHIFT 17 +#define SD4_EMMC_TOP_PSTATE_SD4_CSS_MASK 0x00020000 +#define SD4_EMMC_TOP_PSTATE_SD4_CINS_SHIFT 16 +#define SD4_EMMC_TOP_PSTATE_SD4_CINS_MASK 0x00010000 +#define SD4_EMMC_TOP_PSTATE_SD4_BREN_SHIFT 11 +#define SD4_EMMC_TOP_PSTATE_SD4_BREN_MASK 0x00000800 +#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_SHIFT 10 +#define SD4_EMMC_TOP_PSTATE_SD4_BWEN_MASK 0x00000400 +#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_SHIFT 9 +#define SD4_EMMC_TOP_PSTATE_SD4_RXACT_MASK 0x00000200 +#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_SHIFT 8 +#define SD4_EMMC_TOP_PSTATE_SD4_WXACT_MASK 0x00000100 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_SHIFT 4 +#define SD4_EMMC_TOP_PSTATE_SD4_DLS7_4_MASK 0x000000F0 +#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_SHIFT 3 +#define SD4_EMMC_TOP_PSTATE_SD4_RETUNE_REQ_MASK 0x00000008 +#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_SHIFT 2 +#define SD4_EMMC_TOP_PSTATE_SD4_DATACT_MASK 0x00000004 +#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_SHIFT 1 +#define SD4_EMMC_TOP_PSTATE_SD4_DATINH_MASK 0x00000002 +#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_SHIFT 0 +#define SD4_EMMC_TOP_PSTATE_SD4_CMDINH_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL_OFFSET 0x00000028 +#define SD4_EMMC_TOP_CTRL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL_RESERVED_MASK 0xF800E000 +#define SD4_EMMC_TOP_CTRL_WAKENRMV_SHIFT 26 +#define SD4_EMMC_TOP_CTRL_WAKENRMV_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL_WAKENINS_SHIFT 25 +#define SD4_EMMC_TOP_CTRL_WAKENINS_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL_WAKENIRQ_SHIFT 24 +#define SD4_EMMC_TOP_CTRL_WAKENIRQ_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL_BOOTACK_SHIFT 23 +#define SD4_EMMC_TOP_CTRL_BOOTACK_MASK 0x00800000 +#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_SHIFT 22 +#define SD4_EMMC_TOP_CTRL_ATLBOOTEN_MASK 0x00400000 +#define SD4_EMMC_TOP_CTRL_BOOTEN_SHIFT 21 +#define SD4_EMMC_TOP_CTRL_BOOTEN_MASK 0x00200000 +#define SD4_EMMC_TOP_CTRL_SPIMODE_SHIFT 20 +#define SD4_EMMC_TOP_CTRL_SPIMODE_MASK 0x00100000 +#define SD4_EMMC_TOP_CTRL_BLKIRQ_SHIFT 19 +#define SD4_EMMC_TOP_CTRL_BLKIRQ_MASK 0x00080000 +#define SD4_EMMC_TOP_CTRL_RDWTCRTL_SHIFT 18 +#define SD4_EMMC_TOP_CTRL_RDWTCRTL_MASK 0x00040000 +#define SD4_EMMC_TOP_CTRL_CONTREQ_SHIFT 17 +#define SD4_EMMC_TOP_CTRL_CONTREQ_MASK 0x00020000 +#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_SHIFT 16 +#define SD4_EMMC_TOP_CTRL_BLKSTPREQ_MASK 0x00010000 +#define SD4_EMMC_TOP_CTRL_HRESET_SHIFT 12 +#define SD4_EMMC_TOP_CTRL_HRESET_MASK 0x00001000 +#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_SHIFT 9 +#define SD4_EMMC_TOP_CTRL_SDVSELVDD1_MASK 0x00000E00 +#define SD4_EMMC_TOP_CTRL_SDPWR_SHIFT 8 +#define SD4_EMMC_TOP_CTRL_SDPWR_MASK 0x00000100 +#define SD4_EMMC_TOP_CTRL_CDSD_SHIFT 7 +#define SD4_EMMC_TOP_CTRL_CDSD_MASK 0x00000080 +#define SD4_EMMC_TOP_CTRL_CDTL_SHIFT 6 +#define SD4_EMMC_TOP_CTRL_CDTL_MASK 0x00000040 +#define SD4_EMMC_TOP_CTRL_SDB_SHIFT 5 +#define SD4_EMMC_TOP_CTRL_SDB_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL_DMASEL_SHIFT 3 +#define SD4_EMMC_TOP_CTRL_DMASEL_MASK 0x00000018 +#define SD4_EMMC_TOP_CTRL_HSEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL_HSEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL_DXTW_SHIFT 1 +#define SD4_EMMC_TOP_CTRL_DXTW_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL_LEDCTL_SHIFT 0 +#define SD4_EMMC_TOP_CTRL_LEDCTL_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL_SD4_OFFSET 0x00000028 +#define SD4_EMMC_TOP_CTRL_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL_SD4_RESERVED_MASK 0xF8F00000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_SHIFT 26 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENRMV_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_SHIFT 25 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENINS_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_SHIFT 24 +#define SD4_EMMC_TOP_CTRL_SD4_WAKENIRQ_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_SHIFT 19 +#define SD4_EMMC_TOP_CTRL_SD4_BLKIRQ_MASK 0x00080000 +#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_SHIFT 18 +#define SD4_EMMC_TOP_CTRL_SD4_RDWTCRTL_MASK 0x00040000 +#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_SHIFT 17 +#define SD4_EMMC_TOP_CTRL_SD4_CONTREQ_MASK 0x00020000 +#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_SHIFT 16 +#define SD4_EMMC_TOP_CTRL_SD4_BLKSTPREQ_MASK 0x00010000 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_SHIFT 13 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD2_MASK 0x0000E000 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_SHIFT 12 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWRVDD2_MASK 0x00001000 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_SHIFT 9 +#define SD4_EMMC_TOP_CTRL_SD4_SDVSELVDD1_MASK 0x00000E00 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_SHIFT 8 +#define SD4_EMMC_TOP_CTRL_SD4_SDPWR_MASK 0x00000100 +#define SD4_EMMC_TOP_CTRL_SD4_CDSD_SHIFT 7 +#define SD4_EMMC_TOP_CTRL_SD4_CDSD_MASK 0x00000080 +#define SD4_EMMC_TOP_CTRL_SD4_CDTL_SHIFT 6 +#define SD4_EMMC_TOP_CTRL_SD4_CDTL_MASK 0x00000040 +#define SD4_EMMC_TOP_CTRL_SD4_SDB_SHIFT 5 +#define SD4_EMMC_TOP_CTRL_SD4_SDB_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_SHIFT 3 +#define SD4_EMMC_TOP_CTRL_SD4_DMASEL_MASK 0x00000018 +#define SD4_EMMC_TOP_CTRL_SD4_HSEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL_SD4_HSEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL_SD4_DXTW_SHIFT 1 +#define SD4_EMMC_TOP_CTRL_SD4_DXTW_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_SHIFT 0 +#define SD4_EMMC_TOP_CTRL_SD4_LEDCTL_MASK 0x00000001 + +#define SD4_EMMC_TOP_CTRL1_OFFSET 0x0000002C +#define SD4_EMMC_TOP_CTRL1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CTRL1_TYPE uint32_t +#define SD4_EMMC_TOP_CTRL1_RESERVED_MASK 0xF8F00018 +#define SD4_EMMC_TOP_CTRL1_DATRST_SHIFT 26 +#define SD4_EMMC_TOP_CTRL1_DATRST_MASK 0x04000000 +#define SD4_EMMC_TOP_CTRL1_CMDRST_SHIFT 25 +#define SD4_EMMC_TOP_CTRL1_CMDRST_MASK 0x02000000 +#define SD4_EMMC_TOP_CTRL1_RST_SHIFT 24 +#define SD4_EMMC_TOP_CTRL1_RST_MASK 0x01000000 +#define SD4_EMMC_TOP_CTRL1_DTCNT_SHIFT 16 +#define SD4_EMMC_TOP_CTRL1_DTCNT_MASK 0x000F0000 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_SHIFT 8 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_SHIFT 6 +#define SD4_EMMC_TOP_CTRL1_SDCLKSEL_UP_MASK 0x000000C0 +#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_SHIFT 5 +#define SD4_EMMC_TOP_CTRL1_CLKGENSEL_MASK 0x00000020 +#define SD4_EMMC_TOP_CTRL1_SDCLKEN_SHIFT 2 +#define SD4_EMMC_TOP_CTRL1_SDCLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_CTRL1_ICLKSTB_SHIFT 1 +#define SD4_EMMC_TOP_CTRL1_ICLKSTB_MASK 0x00000002 +#define SD4_EMMC_TOP_CTRL1_ICLKEN_SHIFT 0 +#define SD4_EMMC_TOP_CTRL1_ICLKEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTR_OFFSET 0x00000030 +#define SD4_EMMC_TOP_INTR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTR_TYPE uint32_t +#define SD4_EMMC_TOP_INTR_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTR_TRESPERR_SHIFT 28 +#define SD4_EMMC_TOP_INTR_TRESPERR_MASK 0x10000000 +#define SD4_EMMC_TOP_INTR_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_INTR_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_INTR_CMDERROR_SHIFT 24 +#define SD4_EMMC_TOP_INTR_CMDERROR_MASK 0x01000000 +#define SD4_EMMC_TOP_INTR_IERR_SHIFT 23 +#define SD4_EMMC_TOP_INTR_IERR_MASK 0x00800000 +#define SD4_EMMC_TOP_INTR_DEBERR_SHIFT 22 +#define SD4_EMMC_TOP_INTR_DEBERR_MASK 0x00400000 +#define SD4_EMMC_TOP_INTR_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_INTR_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_INTR_DTOERR_SHIFT 20 +#define SD4_EMMC_TOP_INTR_DTOERR_MASK 0x00100000 +#define SD4_EMMC_TOP_INTR_CMDIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_INTR_CMDIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_INTR_CEBERR_SHIFT 18 +#define SD4_EMMC_TOP_INTR_CEBERR_MASK 0x00040000 +#define SD4_EMMC_TOP_INTR_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_INTR_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_INTR_CTOERR_SHIFT 16 +#define SD4_EMMC_TOP_INTR_CTOERR_MASK 0x00010000 +#define SD4_EMMC_TOP_INTR_ERRIRQ_SHIFT 15 +#define SD4_EMMC_TOP_INTR_ERRIRQ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTR_BTIRQ_SHIFT 14 +#define SD4_EMMC_TOP_INTR_BTIRQ_MASK 0x00004000 +#define SD4_EMMC_TOP_INTR_BTACKRX_SHIFT 13 +#define SD4_EMMC_TOP_INTR_BTACKRX_MASK 0x00002000 +#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_SHIFT 12 +#define SD4_EMMC_TOP_INTR_RETUNE_EVENT_MASK 0x00001000 +#define SD4_EMMC_TOP_INTR_INT_C_SHIFT 11 +#define SD4_EMMC_TOP_INTR_INT_C_MASK 0x00000800 +#define SD4_EMMC_TOP_INTR_INT_B_SHIFT 10 +#define SD4_EMMC_TOP_INTR_INT_B_MASK 0x00000400 +#define SD4_EMMC_TOP_INTR_INT_A_SHIFT 9 +#define SD4_EMMC_TOP_INTR_INT_A_MASK 0x00000200 +#define SD4_EMMC_TOP_INTR_CRDIRQ_SHIFT 8 +#define SD4_EMMC_TOP_INTR_CRDIRQ_MASK 0x00000100 +#define SD4_EMMC_TOP_INTR_CRDRMV_SHIFT 7 +#define SD4_EMMC_TOP_INTR_CRDRMV_MASK 0x00000080 +#define SD4_EMMC_TOP_INTR_CRDINS_SHIFT 6 +#define SD4_EMMC_TOP_INTR_CRDINS_MASK 0x00000040 +#define SD4_EMMC_TOP_INTR_BRRDY_SHIFT 5 +#define SD4_EMMC_TOP_INTR_BRRDY_MASK 0x00000020 +#define SD4_EMMC_TOP_INTR_BWRDY_SHIFT 4 +#define SD4_EMMC_TOP_INTR_BWRDY_MASK 0x00000010 +#define SD4_EMMC_TOP_INTR_DMAIRQ_SHIFT 3 +#define SD4_EMMC_TOP_INTR_DMAIRQ_MASK 0x00000008 +#define SD4_EMMC_TOP_INTR_BLKENT_SHIFT 2 +#define SD4_EMMC_TOP_INTR_BLKENT_MASK 0x00000004 +#define SD4_EMMC_TOP_INTR_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTR_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTR_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTR_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTR_SD4_OFFSET 0x00000030 +#define SD4_EMMC_TOP_INTR_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTR_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTR_SD4_RESERVED_MASK 0xF0006000 +#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_SHIFT 27 +#define SD4_EMMC_TOP_INTR_SD4_TRESPERR_MASK 0x08000000 +#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_SHIFT 26 +#define SD4_EMMC_TOP_INTR_SD4_TUNEERR_MASK 0x04000000 +#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_INTR_SD4_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_SHIFT 24 +#define SD4_EMMC_TOP_INTR_SD4_CMDERROR_MASK 0x01000000 +#define SD4_EMMC_TOP_INTR_SD4_IERR_SHIFT 23 +#define SD4_EMMC_TOP_INTR_SD4_IERR_MASK 0x00800000 +#define SD4_EMMC_TOP_INTR_SD4_DEBERR_SHIFT 22 +#define SD4_EMMC_TOP_INTR_SD4_DEBERR_MASK 0x00400000 +#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_INTR_SD4_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_INTR_SD4_DTOERR_SHIFT 20 +#define SD4_EMMC_TOP_INTR_SD4_DTOERR_MASK 0x00100000 +#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_INTR_SD4_CMDIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_INTR_SD4_CEBERR_SHIFT 18 +#define SD4_EMMC_TOP_INTR_SD4_CEBERR_MASK 0x00040000 +#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_INTR_SD4_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_INTR_SD4_CTOERR_SHIFT 16 +#define SD4_EMMC_TOP_INTR_SD4_CTOERR_MASK 0x00010000 +#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_SHIFT 15 +#define SD4_EMMC_TOP_INTR_SD4_ERRIRQ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_SHIFT 12 +#define SD4_EMMC_TOP_INTR_SD4_RETUNE_EVENT_MASK 0x00001000 +#define SD4_EMMC_TOP_INTR_SD4_INT_C_SHIFT 11 +#define SD4_EMMC_TOP_INTR_SD4_INT_C_MASK 0x00000800 +#define SD4_EMMC_TOP_INTR_SD4_INT_B_SHIFT 10 +#define SD4_EMMC_TOP_INTR_SD4_INT_B_MASK 0x00000400 +#define SD4_EMMC_TOP_INTR_SD4_INT_A_SHIFT 9 +#define SD4_EMMC_TOP_INTR_SD4_INT_A_MASK 0x00000200 +#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_SHIFT 8 +#define SD4_EMMC_TOP_INTR_SD4_CRDIRQ_MASK 0x00000100 +#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_SHIFT 7 +#define SD4_EMMC_TOP_INTR_SD4_CRDRMV_MASK 0x00000080 +#define SD4_EMMC_TOP_INTR_SD4_CRDINS_SHIFT 6 +#define SD4_EMMC_TOP_INTR_SD4_CRDINS_MASK 0x00000040 +#define SD4_EMMC_TOP_INTR_SD4_BRRDY_SHIFT 5 +#define SD4_EMMC_TOP_INTR_SD4_BRRDY_MASK 0x00000020 +#define SD4_EMMC_TOP_INTR_SD4_BWRDY_SHIFT 4 +#define SD4_EMMC_TOP_INTR_SD4_BWRDY_MASK 0x00000010 +#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_SHIFT 3 +#define SD4_EMMC_TOP_INTR_SD4_DMAIRQ_MASK 0x00000008 +#define SD4_EMMC_TOP_INTR_SD4_BLKENT_SHIFT 2 +#define SD4_EMMC_TOP_INTR_SD4_BLKENT_MASK 0x00000004 +#define SD4_EMMC_TOP_INTR_SD4_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTR_SD4_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTR_SD4_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN1_OFFSET 0x00000034 +#define SD4_EMMC_TOP_INTREN1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN1_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN1_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTREN1_TRESPERREN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN1_TRESPERREN_MASK 0x10000000 +#define SD4_EMMC_TOP_INTREN1_ADMAEREN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN1_ADMAEREN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN1_CMDERREN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN1_CMDERREN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN1_ILIMERREN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN1_ILIMERREN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN1_DEBERREN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN1_DEBERREN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN1_DCRCERREN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN1_DCRCERREN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN1_DTOERREN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN1_DTOERREN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN1_CIDXERREN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN1_CIDXERREN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN1_CEBERREN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN1_CEBERREN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN1_CMDCRCEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN1_CMDTOEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN1_CMDTOEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN1_FIXZ_SHIFT 15 +#define SD4_EMMC_TOP_INTREN1_FIXZ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN1_BTIRQEN_SHIFT 14 +#define SD4_EMMC_TOP_INTREN1_BTIRQEN_MASK 0x00004000 +#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_SHIFT 13 +#define SD4_EMMC_TOP_INTREN1_BTACKRXEN_MASK 0x00002000 +#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN1_RETUNE_EVENTEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN1_INT_C_EN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN1_INT_C_EN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN1_INT_B_EN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN1_INT_B_EN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN1_INT_A_EN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN1_INT_A_EN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN1_CIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN1_CIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN1_CRDRMVEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN1_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN1_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN1_BUFRREN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN1_BUFRREN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN1_BUFWREN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN1_BUFWREN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN1_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN1_BLKEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN1_BLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN1_TXDONEEN_SHIFT 1 +#define SD4_EMMC_TOP_INTREN1_TXDONEEN_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_SHIFT 0 +#define SD4_EMMC_TOP_INTREN1_CMDDONEEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN1_SD4_OFFSET 0x00000034 +#define SD4_EMMC_TOP_INTREN1_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN1_SD4_RESERVED_MASK 0x00006000 +#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN1_SD4_VNDRERREN_MASK 0xF0000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_SHIFT 27 +#define SD4_EMMC_TOP_INTREN1_SD4_TRESPERREN_MASK 0x08000000 +#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_SHIFT 26 +#define SD4_EMMC_TOP_INTREN1_SD4_TUNEERREN_MASK 0x04000000 +#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN1_SD4_ADMAEREN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDERREN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN1_SD4_ILIMERREN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN1_SD4_DEBERREN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN1_SD4_DCRCERREN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN1_SD4_DTOERREN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN1_SD4_CIDXERREN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN1_SD4_CEBERREN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDCRCEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDTOEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_SHIFT 15 +#define SD4_EMMC_TOP_INTREN1_SD4_FIXZ_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN1_SD4_RETUNE_EVENTEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_C_EN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_B_EN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN1_SD4_INT_A_EN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN1_SD4_CIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDRMVEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN1_SD4_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFRREN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN1_SD4_BUFWREN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN1_SD4_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN1_SD4_BLKEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_SHIFT 1 +#define SD4_EMMC_TOP_INTREN1_SD4_TXDONEEN_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_SHIFT 0 +#define SD4_EMMC_TOP_INTREN1_SD4_CMDDONEEN_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN2_OFFSET 0x00000038 +#define SD4_EMMC_TOP_INTREN2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN2_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN2_RESERVED_MASK 0xEC000000 +#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_SHIFT 28 +#define SD4_EMMC_TOP_INTREN2_TRESPERRSEN_MASK 0x10000000 +#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN2_ADMASIGEN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN2_CMDSIGEN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN2_ILIMSIGEN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN2_DEBSIGEN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN2_DCRCSIGEN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN2_DTOSIGEN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN2_CIDXSIGEN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN2_CEBSIGEN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN2_CMDCRCSIGEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN2_CMDTOSIGEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN2_FIXZERO_SHIFT 15 +#define SD4_EMMC_TOP_INTREN2_FIXZERO_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_SHIFT 14 +#define SD4_EMMC_TOP_INTREN2_BTIRQSEN_MASK 0x00004000 +#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_SHIFT 13 +#define SD4_EMMC_TOP_INTREN2_BTACKRXSEN_MASK 0x00002000 +#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN2_RETUNE_EVENTSIGEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN2_INT_C_SIGEN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN2_INT_B_SIGEN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN2_INT_A_SIGEN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN2_CRDIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN2_CRDRVMEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN2_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN2_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN2_BUFRRDYEN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN2_BUFWRDYEN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN2_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN2_BLKGAPEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN2_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTREN2_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN2_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTREN2_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_INTREN2_SD4_OFFSET 0x00000038 +#define SD4_EMMC_TOP_INTREN2_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_INTREN2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_INTREN2_SD4_RESERVED_MASK 0xF0006000 +#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_SHIFT 27 +#define SD4_EMMC_TOP_INTREN2_SD4_TRESPERRSEN_MASK 0x08000000 +#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_SHIFT 26 +#define SD4_EMMC_TOP_INTREN2_SD4_TUNERRSIGEN_MASK 0x04000000 +#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_SHIFT 25 +#define SD4_EMMC_TOP_INTREN2_SD4_ADMASIGEN_MASK 0x02000000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_SHIFT 24 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDSIGEN_MASK 0x01000000 +#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_SHIFT 23 +#define SD4_EMMC_TOP_INTREN2_SD4_ILIMSIGEN_MASK 0x00800000 +#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_SHIFT 22 +#define SD4_EMMC_TOP_INTREN2_SD4_DEBSIGEN_MASK 0x00400000 +#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_SHIFT 21 +#define SD4_EMMC_TOP_INTREN2_SD4_DCRCSIGEN_MASK 0x00200000 +#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_SHIFT 20 +#define SD4_EMMC_TOP_INTREN2_SD4_DTOSIGEN_MASK 0x00100000 +#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_SHIFT 19 +#define SD4_EMMC_TOP_INTREN2_SD4_CIDXSIGEN_MASK 0x00080000 +#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_SHIFT 18 +#define SD4_EMMC_TOP_INTREN2_SD4_CEBSIGEN_MASK 0x00040000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_SHIFT 17 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDCRCSIGEN_MASK 0x00020000 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_SHIFT 16 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDTOSIGEN_MASK 0x00010000 +#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_SHIFT 15 +#define SD4_EMMC_TOP_INTREN2_SD4_FIXZERO_MASK 0x00008000 +#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_SHIFT 12 +#define SD4_EMMC_TOP_INTREN2_SD4_RETUNE_EVENTSIGEN_MASK 0x00001000 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_SHIFT 11 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_C_SIGEN_MASK 0x00000800 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_SHIFT 10 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_B_SIGEN_MASK 0x00000400 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_SHIFT 9 +#define SD4_EMMC_TOP_INTREN2_SD4_INT_A_SIGEN_MASK 0x00000200 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_SHIFT 8 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDIRQEN_MASK 0x00000100 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_SHIFT 7 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDRVMEN_MASK 0x00000080 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_SHIFT 6 +#define SD4_EMMC_TOP_INTREN2_SD4_CRDINSEN_MASK 0x00000040 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_SHIFT 5 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFRRDYEN_MASK 0x00000020 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_SHIFT 4 +#define SD4_EMMC_TOP_INTREN2_SD4_BUFWRDYEN_MASK 0x00000010 +#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_SHIFT 3 +#define SD4_EMMC_TOP_INTREN2_SD4_DMAIRQEN_MASK 0x00000008 +#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_SHIFT 2 +#define SD4_EMMC_TOP_INTREN2_SD4_BLKGAPEN_MASK 0x00000004 +#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_SHIFT 1 +#define SD4_EMMC_TOP_INTREN2_SD4_TXDONE_MASK 0x00000002 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_SHIFT 0 +#define SD4_EMMC_TOP_INTREN2_SD4_CMDDONE_MASK 0x00000001 + +#define SD4_EMMC_TOP_ERRSTAT_OFFSET 0x0000003C +#define SD4_EMMC_TOP_ERRSTAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ERRSTAT_TYPE uint32_t +#define SD4_EMMC_TOP_ERRSTAT_RESERVED_MASK 0x3F00FF60 +#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_SHIFT 31 +#define SD4_EMMC_TOP_ERRSTAT_PRESETEN_MASK 0x80000000 +#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_SHIFT 30 +#define SD4_EMMC_TOP_ERRSTAT_ASYNC_INTREN_MASK 0x40000000 +#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_SHIFT 23 +#define SD4_EMMC_TOP_ERRSTAT_SAMPLECLOCKSEL_MASK 0x00800000 +#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_SHIFT 22 +#define SD4_EMMC_TOP_ERRSTAT_EXECTUNE_MASK 0x00400000 +#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_SHIFT 20 +#define SD4_EMMC_TOP_ERRSTAT_DRVSTRESEL_MASK 0x00300000 +#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_SHIFT 19 +#define SD4_EMMC_TOP_ERRSTAT_EN1P8V_MASK 0x00080000 +#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_SHIFT 16 +#define SD4_EMMC_TOP_ERRSTAT_UHSMODESEL_MASK 0x00070000 +#define SD4_EMMC_TOP_ERRSTAT_NOCMD_SHIFT 7 +#define SD4_EMMC_TOP_ERRSTAT_NOCMD_MASK 0x00000080 +#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_SHIFT 4 +#define SD4_EMMC_TOP_ERRSTAT_CMDIDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_SHIFT 3 +#define SD4_EMMC_TOP_ERRSTAT_CMDENDERR_MASK 0x00000008 +#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_SHIFT 2 +#define SD4_EMMC_TOP_ERRSTAT_CMDCRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_SHIFT 1 +#define SD4_EMMC_TOP_ERRSTAT_CMDTOERR_MASK 0x00000002 +#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_SHIFT 0 +#define SD4_EMMC_TOP_ERRSTAT_CMDNOEXEC_MASK 0x00000001 + +#define SD4_EMMC_TOP_ERRSTAT_SD4_OFFSET 0x0000003C +#define SD4_EMMC_TOP_ERRSTAT_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_ERRSTAT_SD4_RESERVED_MASK 0x0E00FF40 +#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_SHIFT 31 +#define SD4_EMMC_TOP_ERRSTAT_SD4_PRESETEN_MASK 0x80000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_SHIFT 30 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ASYNC_INTREN_MASK 0x40000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_SHIFT 29 +#define SD4_EMMC_TOP_ERRSTAT_SD4_ADDR64_MASK 0x20000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_SHIFT 28 +#define SD4_EMMC_TOP_ERRSTAT_SD4_HOSTVER4_00_MASK 0x10000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_SHIFT 24 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHS2INTFEN_MASK 0x01000000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_SHIFT 23 +#define SD4_EMMC_TOP_ERRSTAT_SD4_SAMPLECLOCKSEL_MASK 0x00800000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_SHIFT 22 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EXECTUNE_MASK 0x00400000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_SHIFT 20 +#define SD4_EMMC_TOP_ERRSTAT_SD4_DRVSTRESEL_MASK 0x00300000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_SHIFT 19 +#define SD4_EMMC_TOP_ERRSTAT_SD4_EN1P8V_MASK 0x00080000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_SHIFT 16 +#define SD4_EMMC_TOP_ERRSTAT_SD4_UHSMODESEL_MASK 0x00070000 +#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_SHIFT 7 +#define SD4_EMMC_TOP_ERRSTAT_SD4_NOCMD_MASK 0x00000080 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_SHIFT 5 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDRESPERR_MASK 0x00000020 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_SHIFT 4 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDIDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_SHIFT 3 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDENDERR_MASK 0x00000008 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_SHIFT 2 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDCRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_SHIFT 1 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDTOERR_MASK 0x00000002 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_SHIFT 0 +#define SD4_EMMC_TOP_ERRSTAT_SD4_CMDNOEXEC_MASK 0x00000001 + +#define SD4_EMMC_TOP_CAPABILITIES1_OFFSET 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES1_DEFAULT 0x17EFD0B0 +#define SD4_EMMC_TOP_CAPABILITIES1_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES1_RESERVED_MASK 0x08100040 +#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_SHIFT 30 +#define SD4_EMMC_TOP_CAPABILITIES1_SLOTTYPE_MASK 0xC0000000 +#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_SHIFT 29 +#define SD4_EMMC_TOP_CAPABILITIES1_ASYNCHIRQ_MASK 0x20000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES1_SYSBUS64_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V18_SHIFT 26 +#define SD4_EMMC_TOP_CAPABILITIES1_V18_MASK 0x04000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V3_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES1_V3_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES1_V33_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES1_V33_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_SHIFT 23 +#define SD4_EMMC_TOP_CAPABILITIES1_SUPRSM_MASK 0x00800000 +#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_SHIFT 22 +#define SD4_EMMC_TOP_CAPABILITIES1_SDMA_MASK 0x00400000 +#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_SHIFT 21 +#define SD4_EMMC_TOP_CAPABILITIES1_HSPEED_MASK 0x00200000 +#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_SHIFT 19 +#define SD4_EMMC_TOP_CAPABILITIES1_ADMA2_MASK 0x00080000 +#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_SHIFT 18 +#define SD4_EMMC_TOP_CAPABILITIES1_EXTBUSMED_MASK 0x00040000 +#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES1_MAXBLK_MASK 0x00030000 +#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES1_BCLK_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_SHIFT 7 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUT_MASK 0x00000080 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES1_TOUTFREQ_MASK 0x0000003F + +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_OFFSET 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_DEFAULT 0x10E934B4 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_RESERVED_MASK 0x08100040 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_SHIFT 30 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SLOTTYPE_MASK 0xC0000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_SHIFT 29 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ASYNCHIRQ_MASK 0x20000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SYSBUS64_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_SHIFT 26 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V18_MASK 0x04000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V3_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_V33_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_SHIFT 23 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SUPRSM_MASK 0x00800000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_SHIFT 22 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_SDMA_MASK 0x00400000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_SHIFT 21 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_HSPEED_MASK 0x00200000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_SHIFT 19 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_ADMA2_MASK 0x00080000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_SHIFT 18 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_EXTBUSMED_MASK 0x00040000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_MAXBLK_MASK 0x00030000 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_BCLK_MASK 0x0000FF00 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_SHIFT 7 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUT_MASK 0x00000080 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES1_SD4_TOUTFREQ_MASK 0x0000003F + +#define SD4_EMMC_TOP_CAPABILITIES2_OFFSET 0x00000044 +#define SD4_EMMC_TOP_CAPABILITIES2_DEFAULT 0x03002177 +#define SD4_EMMC_TOP_CAPABILITIES2_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES2_RESERVED_MASK 0xFC001088 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_SHIFT 25 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIBLOCKMODE_MASK 0x02000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_SHIFT 24 +#define SD4_EMMC_TOP_CAPABILITIES2_SPIMODE_CAP_MASK 0x01000000 +#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES2_CLOCKMULT_MASK 0x00FF0000 +#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_SHIFT 14 +#define SD4_EMMC_TOP_CAPABILITIES2_RETUNE_MODE_MASK 0x0000C000 +#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_SHIFT 13 +#define SD4_EMMC_TOP_CAPABILITIES2_USETUNE_SDR50_MASK 0x00002000 +#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES2_TMRCNT_RETUNE_MASK 0x00000F00 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_SHIFT 6 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPED_MASK 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_SHIFT 5 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEC_MASK 0x00000020 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_SHIFT 4 +#define SD4_EMMC_TOP_CAPABILITIES2_DRVR_TYPEA_MASK 0x00000010 +#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_SHIFT 2 +#define SD4_EMMC_TOP_CAPABILITIES2_DDR50_MASK 0x00000004 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_SHIFT 1 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR104_MASK 0x00000002 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES2_SDR50_MASK 0x00000001 + +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_OFFSET 0x00000044 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DEFAULT 0x10000064 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RESERVED_MASK 0xE7001080 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_SHIFT 28 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_VDD2_18_MASK 0x10000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_SHIFT 27 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_ADMA3_MASK 0x08000000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_SHIFT 16 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_CLOCKMULT_MASK 0x00FF0000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_SHIFT 14 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_RETUNE_MODE_MASK 0x0000C000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_SHIFT 13 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_USETUNE_SDR50_MASK 0x00002000 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_SHIFT 8 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_TMRCNT_RETUNE_MASK 0x00000F00 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_SHIFT 6 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPED_MASK 0x00000040 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_SHIFT 5 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEC_MASK 0x00000020 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_SHIFT 4 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DRVR_TYPEA_MASK 0x00000010 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_SHIFT 3 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_UHS_II_MASK 0x00000008 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_SHIFT 2 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_DDR50_MASK 0x00000004 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_SHIFT 1 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR104_MASK 0x00000002 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_SHIFT 0 +#define SD4_EMMC_TOP_CAPABILITIES2_SD4_SDR50_MASK 0x00000001 + +#define SD4_EMMC_TOP_MAX_A1_OFFSET 0x00000048 +#define SD4_EMMC_TOP_MAX_A1_DEFAULT 0x00000001 +#define SD4_EMMC_TOP_MAX_A1_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A1_RESERVED_MASK 0xFF000000 +#define SD4_EMMC_TOP_MAX_A1_MAXA18_SHIFT 16 +#define SD4_EMMC_TOP_MAX_A1_MAXA18_MASK 0x00FF0000 +#define SD4_EMMC_TOP_MAX_A1_MAXA30_SHIFT 8 +#define SD4_EMMC_TOP_MAX_A1_MAXA30_MASK 0x0000FF00 +#define SD4_EMMC_TOP_MAX_A1_MAXA33_SHIFT 0 +#define SD4_EMMC_TOP_MAX_A1_MAXA33_MASK 0x000000FF + +#define SD4_EMMC_TOP_MAX_A2_OFFSET 0x0000004C +#define SD4_EMMC_TOP_MAX_A2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_MAX_A2_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A2_RESERVED_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_MAX_A2_SD4_OFFSET 0x0000004C +#define SD4_EMMC_TOP_MAX_A2_SD4_DEFAULT 0x00000001 +#define SD4_EMMC_TOP_MAX_A2_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_MAX_A2_SD4_RESERVED_MASK 0xFFFFFF00 +#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_SHIFT 0 +#define SD4_EMMC_TOP_MAX_A2_SD4_MAXAVDD2_MASK 0x000000FF + +#define SD4_EMMC_TOP_CMDENTSTAT_OFFSET 0x00000050 +#define SD4_EMMC_TOP_CMDENTSTAT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMDENTSTAT_TYPE uint32_t +#define SD4_EMMC_TOP_CMDENTSTAT_RESERVED_MASK 0x2C00FF60 +#define SD4_EMMC_TOP_CMDENTSTAT_VSES_SHIFT 30 +#define SD4_EMMC_TOP_CMDENTSTAT_VSES_MASK 0xC0000000 +#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_SHIFT 28 +#define SD4_EMMC_TOP_CMDENTSTAT_TRERR_MASK 0x10000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_CMDENTSTAT_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_SHIFT 24 +#define SD4_EMMC_TOP_CMDENTSTAT_ACMDERR_MASK 0x01000000 +#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_SHIFT 23 +#define SD4_EMMC_TOP_CMDENTSTAT_ILERR_MASK 0x00800000 +#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_SHIFT 22 +#define SD4_EMMC_TOP_CMDENTSTAT_DENDERR_MASK 0x00400000 +#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_CMDENTSTAT_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_SHIFT 20 +#define SD4_EMMC_TOP_CMDENTSTAT_DTOUTERR_MASK 0x00100000 +#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_CMDENTSTAT_CIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_SHIFT 18 +#define SD4_EMMC_TOP_CMDENTSTAT_CENDERR_MASK 0x00040000 +#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_CMDENTSTAT_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_SHIFT 16 +#define SD4_EMMC_TOP_CMDENTSTAT_CTOUTERR_MASK 0x00010000 +#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_SHIFT 7 +#define SD4_EMMC_TOP_CMDENTSTAT_NOFRCENT_MASK 0x00000080 +#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_SHIFT 4 +#define SD4_EMMC_TOP_CMDENTSTAT_IDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_SHIFT 3 +#define SD4_EMMC_TOP_CMDENTSTAT_EBITERR_MASK 0x00000008 +#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_SHIFT 2 +#define SD4_EMMC_TOP_CMDENTSTAT_CRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_SHIFT 1 +#define SD4_EMMC_TOP_CMDENTSTAT_TOUTERR_MASK 0x00000002 +#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_SHIFT 0 +#define SD4_EMMC_TOP_CMDENTSTAT_AUTONOEX_MASK 0x00000001 + +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_OFFSET 0x00000050 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESERVED_MASK 0x0000FF40 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_SHIFT 28 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_VSES_MASK 0xF0000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_SHIFT 27 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TRESPERR_MASK 0x08000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_SHIFT 26 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TUNERR_MASK 0x04000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_SHIFT 25 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ADMAERR_MASK 0x02000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_SHIFT 24 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ACMDERR_MASK 0x01000000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_SHIFT 23 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_ILERR_MASK 0x00800000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_SHIFT 22 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DENDERR_MASK 0x00400000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_SHIFT 21 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DCRCERR_MASK 0x00200000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_SHIFT 20 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_DTOUTERR_MASK 0x00100000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_SHIFT 19 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CIDXERR_MASK 0x00080000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_SHIFT 18 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CENDERR_MASK 0x00040000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_SHIFT 17 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CCRCERR_MASK 0x00020000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_SHIFT 16 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CTOUTERR_MASK 0x00010000 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_SHIFT 7 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_NOFRCENT_MASK 0x00000080 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_SHIFT 5 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_RESPERR_MASK 0x00000020 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_SHIFT 4 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_IDXERR_MASK 0x00000010 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_SHIFT 3 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_EBITERR_MASK 0x00000008 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_SHIFT 2 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_CRCERR_MASK 0x00000004 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_SHIFT 1 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_TOUTERR_MASK 0x00000002 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_SHIFT 0 +#define SD4_EMMC_TOP_CMDENTSTAT_SD4_AUTONOEX_MASK 0x00000001 + +#define SD4_EMMC_TOP_ADMAERR_OFFSET 0x00000054 +#define SD4_EMMC_TOP_ADMAERR_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAERR_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAERR_RESERVED_MASK 0xFFFFFFF8 +#define SD4_EMMC_TOP_ADMAERR_ADMALERR_SHIFT 2 +#define SD4_EMMC_TOP_ADMAERR_ADMALERR_MASK 0x00000004 +#define SD4_EMMC_TOP_ADMAERR_ADMAERR_SHIFT 0 +#define SD4_EMMC_TOP_ADMAERR_ADMAERR_MASK 0x00000003 + +#define SD4_EMMC_TOP_ADMAADDR0_OFFSET 0x00000058 +#define SD4_EMMC_TOP_ADMAADDR0_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR0_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAADDR0_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_SHIFT 0 +#define SD4_EMMC_TOP_ADMAADDR0_ADMAADDR0_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_ADMAADDR1_OFFSET 0x0000005C +#define SD4_EMMC_TOP_ADMAADDR1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR1_TYPE uint32_t +#define SD4_EMMC_TOP_ADMAADDR1_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_SHIFT 0 +#define SD4_EMMC_TOP_ADMAADDR1_ADMAADDR1_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_PRESETVAL1_OFFSET 0x00000060 +#define SD4_EMMC_TOP_PRESETVAL1_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL1_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL1_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_DFS_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_DFS_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_DFS_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL1_DRVS_SEL_INIT_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL1_CLKGENSEL_INIT_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL1_FREQ_SEL_INIT_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL2_OFFSET 0x00000064 +#define SD4_EMMC_TOP_PRESETVAL2_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL2_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL2_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_SDR12_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_SDR12_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_SDR12_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL2_DRVS_SEL_HS_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL2_CLKGENSEL_HS_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL2_FREQ_SEL_HS_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL3_OFFSET 0x00000068 +#define SD4_EMMC_TOP_PRESETVAL3_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL3_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL3_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR50_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR50_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR50_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL3_DRVS_SEL_SDR25_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL3_CLKGENSEL_SDR25_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL3_FREQ_SEL_SDR25_MASK 0x000003FF + +#define SD4_EMMC_TOP_PRESETVAL4_OFFSET 0x0000006C +#define SD4_EMMC_TOP_PRESETVAL4_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_PRESETVAL4_TYPE uint32_t +#define SD4_EMMC_TOP_PRESETVAL4_RESERVED_MASK 0x38003800 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_SHIFT 30 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_DDR50_MASK 0xC0000000 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_SHIFT 26 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_DDR50_MASK 0x04000000 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_SHIFT 16 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_DDR50_MASK 0x03FF0000 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_SHIFT 14 +#define SD4_EMMC_TOP_PRESETVAL4_DRVS_SEL_SDR104_MASK 0x0000C000 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_SHIFT 10 +#define SD4_EMMC_TOP_PRESETVAL4_CLKGENSEL_SDR104_MASK 0x00000400 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_SHIFT 0 +#define SD4_EMMC_TOP_PRESETVAL4_FREQ_SEL_SDR104_MASK 0x000003FF + +#define SD4_EMMC_TOP_BOOTTIMEOUT_OFFSET 0x00000070 +#define SD4_EMMC_TOP_BOOTTIMEOUT_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_BOOTTIMEOUT_TYPE uint32_t +#define SD4_EMMC_TOP_BOOTTIMEOUT_RESERVED_MASK 0x00000000 +#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_SHIFT 0 +#define SD4_EMMC_TOP_BOOTTIMEOUT_BOOTDATATIMEOUTCTRVALUE_MASK 0xFFFFFFFF + +#define SD4_EMMC_TOP_DBGSEL_OFFSET 0x00000074 +#define SD4_EMMC_TOP_DBGSEL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_DBGSEL_TYPE uint32_t +#define SD4_EMMC_TOP_DBGSEL_RESERVED_MASK 0xFFFFFFFE +#define SD4_EMMC_TOP_DBGSEL_DBGSEL_SHIFT 0 +#define SD4_EMMC_TOP_DBGSEL_DBGSEL_MASK 0x00000001 + +#define SD4_EMMC_TOP_UHS2_PRESETVAL_OFFSET 0x00000074 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DEFAULT 0x00000000 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_TYPE uint32_t +#define SD4_EMMC_TOP_UHS2_PRESETVAL_RESERVED_MASK 0xFFFF3800 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_SHIFT 14 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_DRVSTRVAL_MASK 0x0000C000 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_SHIFT 10 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_CLKGENSELVAL_MASK 0x00000400 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_SHIFT 0 +#define SD4_EMMC_TOP_UHS2_PRESETVAL_SDCLKFREQSELVAL_MASK 0x000003FF + +#define SD4_EMMC_TOP_HCVERSIRQ_OFFSET 0x000000FC +#define SD4_EMMC_TOP_HCVERSIRQ_DEFAULT 0x10020000 +#define SD4_EMMC_TOP_HCVERSIRQ_TYPE uint32_t +#define SD4_EMMC_TOP_HCVERSIRQ_RESERVED_MASK 0x0000FF00 +#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_SHIFT 24 +#define SD4_EMMC_TOP_HCVERSIRQ_VENDVER_MASK 0xFF000000 +#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_SHIFT 16 +#define SD4_EMMC_TOP_HCVERSIRQ_SPECVER_MASK 0x00FF0000 +#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_SHIFT 0 +#define SD4_EMMC_TOP_HCVERSIRQ_SIRQ_MASK 0x000000FF + +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_OFFSET 0x000000FC +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_DEFAULT 0x01030000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_TYPE uint32_t +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_RESERVED_MASK 0x0000FF00 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_SHIFT 24 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_VENDVER_MASK 0xFF000000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_SHIFT 16 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SPECVER_MASK 0x00FF0000 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_SHIFT 0 +#define SD4_EMMC_TOP_HCVERSIRQ_SD4_SIRQ_MASK 0x000000FF + +#endif /* BRCM_RDB_SD4_EMMC_TOP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h new file mode 100644 index 0000000..8d223f9 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CHAL_SD_H +#define CHAL_SD_H + +#include + +#define BASE_CLK_FREQ (200 * 1000 * 1000) +#define INIT_CLK_FREQ (400 * 1000) + +#define SD_ERROR_RECOVERABLE 0 +#define SD_ERROR_NON_RECOVERABLE 1 + +#define SD_OK 0 +#define SD_FAIL (-1) +#define SD_INVALID_HANDLE (-2) +#define SD_CEATA_INIT_ERROR (-3) +#define SD_RESET_ERROR (-4) +#define SD_CARD_INIT_ERROR (-5) +#define SD_INV_DATA_WIDTH (-6) +#define SD_SET_BUS_WIDTH_ERROR (-7) +#define SD_DMA_NOT_SUPPORT (-8) +#define SD_SDIO_READ_ERROR (-9) +#define SD_SDIO_WRITE_ERROR (-10) +#define SD_WRITE_ERROR (-11) +#define SD_READ_ERROR (-12) +#define SD_READ_SIZE_ERROR (-13) +#define SD_RW_ADDRESS_ERROR (-14) +#define SD_XFER_ADDRESS_ERROR (-15) +#define SD_DATA_XFER_ADDR_ERROR (-16) +#define SD_DATA_XFER_ERROR (-17) +#define SD_WRITE_SIZE_ERROR (-18) +#define SD_CMD_STATUS_UPDATE_ERR (-19) +#define SD_CMD12_ERROR (-20) +#define SD_CMD_DATA_ERROR (-21) +#define SD_CMD_TIMEOUT (-22) +#define SD_CMD_NO_RESPONSE (-22) +#define SD_CMD_ABORT_ERROR (-23) +#define SD_CMD_INVALID (-24) +#define SD_CMD_RESUME_ERROR (-25) +#define SD_CMD_ERR_INVALID_RESPONSE (-26) +#define SD_WAIT_TIMEOUT (-27) +#define SD_READ_TIMEOUT (-28) +#define SD_CEATA_REST_ERROR (-29) +#define SD_INIT_CAED_FAILED (-30) +#define SD_ERROR_CLOCK_OFFLIMIT (-31) +#define SD_INV_SLOT (-32) + +#define SD_NOR_INTERRUPTS 0x000000FF +#define SD_ERR_INTERRUPTS 0x03FF0000 +#define SD_CMD_ERROR_INT 0x010F0000 +#define SD_DAT_ERROR_INT 0x02F00000 +#define SD_DAT_TIMEOUT 0x00100000 + +/* Operation modes */ +#define SD_PIO_MODE 0 +#define SD_INT_MODE 1 + +/* Support both ADMA and SDMA (for version 2.0 and above) */ +#define SD_DMA_OFF 0 +#define SD_DMA_SDMA 1 +#define SD_DMA_ADMA 2 + +#define SD_NORMAL_SPEED 0 +#define SD_HIGH_SPEED 1 + +#define SD_XFER_CARD_TO_HOST 3 +#define SD_XFER_HOST_TO_CARD 4 + +#define SD_CARD_DETECT_AUTO 0 +#define SD_CARD_DETECT_SD 1 +#define SD_CARD_DETECT_SDIO 2 +#define SD_CARD_DETECT_MMC 3 +#define SD_CARD_DETECT_CEATA 4 + +#define SD_ABORT_SYNC_MODE 0 +#define SD_ABORT_ASYNC_MODE 1 + +#define SD_CMD_ERROR_FLAGS (0x18F << 16) +#define SD_DATA_ERROR_FLAGS (0x70 << 16) +#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F) + +#define SD_CARD_STATUS_ERROR 0x10000000 +#define SD_CMD_MISSING 0x80000000 +#define SD_ERROR_INT 0x8000 + +#define SD_TRAN_HIGH_SPEED 0x32 +#define SD_CARD_HIGH_CAPACITY 0x40000000 +#define SD_CARD_POWER_UP_STATUS 0x80000000 + +#define SD_HOST_CORE_TIMEOUT 0x0E + +/* SD CARD and Host Controllers bus width */ +#define SD_BUS_DATA_WIDTH_1BIT 0x00 +#define SD_BUS_DATA_WIDTH_4BIT 0x02 +#define SD_BUS_DATA_WIDTH_8BIT 0x20 + +/* dma boundary settings */ +#define SD_DMA_BOUNDARY_4K 0 +#define SD_DMA_BOUNDARY_8K (1 << 12) +#define SD_DMA_BOUNDARY_16K (2 << 12) +#define SD_DMA_BOUNDARY_32K (3 << 12) +#define SD_DMA_BOUNDARY_64K (4 << 12) +#define SD_DMA_BOUNDARY_128K (5 << 12) +#define SD_DMA_BOUNDARY_256K (6 << 12) +#define SD_DMA_BOUNDARY_512K (7 << 12) + +#define SD_CMDR_CMD_NORMAL 0x00000000 +#define SD_CMDR_CMD_SUSPEND 0x00400000 +#define SD_CMDR_CMD_RESUME 0x00800000 +#define SD_CMDR_CMD_ABORT 0x00c00000 + +#define SD_CMDR_RSP_TYPE_NONE 0x0 +#define SD_CMDR_RSP_TYPE_R2 0x1 +#define SD_CMDR_RSP_TYPE_R3_4 0x2 +#define SD_CMDR_RSP_TYPE_R1_5_6 0x2 +#define SD_CMDR_RSP_TYPE_R1b_5b 0x3 +#define SD_CMDR_RSP_TYPE_S 16 + +struct sd_ctrl_info { + uint32_t blkReg; /* current block register cache value */ + uint32_t cmdReg; /* current command register cache value */ + uint32_t argReg; /* current argument register cache value */ + uint32_t cmdIndex; /* current command index */ + uint32_t cmdStatus; /* current command status, cmd/data compelete */ + uint16_t rca; /* relative card address */ + uint32_t ocr; /* operation codition */ + uint32_t eventList; /* events list */ + uint32_t blkGapEnable; + + uint32_t capability; /* controller's capbilities */ + uint32_t maxCurrent; /* maximum current supported */ + uint32_t present; /* if card is inserted or removed */ + uint32_t version; /* SD spec version 1.0 or 2.0 */ + uint32_t vendor; /* vendor number */ + + uintptr_t sdRegBaseAddr; /* sdio control registers */ + uintptr_t hostRegBaseAddr; /* SD Host control registers */ +}; + +struct sd_cfg { + uint32_t mode; /* interrupt or polling */ + uint32_t dma; /* dma enabled or disabled */ + uint32_t retryLimit; /* command retry limit */ + uint32_t speedMode; /* speed mode, 0 standard, 1 high speed */ + uint32_t voltage; /* voltage level */ + uint32_t blockSize; /* access block size (512 for HC card) */ + uint32_t dmaBoundary; /* dma address boundary */ + uint32_t detSignal; /* card det signal src, for test purpose only */ + uint32_t rdWaiting; + uint32_t wakeupOut; + uint32_t wakeupIn; + uint32_t wakeupInt; + uint32_t wfe_retry; + uint32_t gapInt; + uint32_t readWait; + uint32_t led; +}; + +struct sd_dev { + struct sd_cfg cfg; /* SD configuration */ + struct sd_ctrl_info ctrl; /* SD info */ +}; + +int32_t chal_sd_start(CHAL_HANDLE *sdHandle, uint32_t mode, + uint32_t sdBase, uint32_t hostBase); +int32_t chal_sd_config(CHAL_HANDLE *sdHandle, uint32_t speed, + uint32_t retry, uint32_t boundary, + uint32_t blkSize, uint32_t dma); +int32_t chal_sd_stop(void); +int32_t chal_sd_set_dma(CHAL_HANDLE *sdHandle, uint32_t mode); +uintptr_t chal_sd_get_dma_addr(CHAL_HANDLE *handle); +int32_t chal_sd_config_bus_width(CHAL_HANDLE *sdHandle, int32_t width); +int32_t chal_sd_send_cmd(CHAL_HANDLE *sdHandle, uint32_t cmdIndex, + uint32_t arg, uint32_t options); +int32_t chal_sd_set_dma_addr(CHAL_HANDLE *sdHandle, uintptr_t address); +int32_t chal_sd_set_clock(CHAL_HANDLE *sdHandle, + uint32_t div_ctrl_setting, uint32_t on); +uint32_t chal_sd_freq_2_div_ctrl_setting(uint32_t desired_freq); +int32_t chal_sd_setup_xfer(CHAL_HANDLE *sdHandle, uint8_t *data, + uint32_t length, int32_t dir); +int32_t chal_sd_write_buffer(CHAL_HANDLE *sdHandle, uint32_t length, + uint8_t *data); +int32_t chal_sd_read_buffer(CHAL_HANDLE *sdHandle, uint32_t length, + uint8_t *data); +int32_t chal_sd_reset_line(CHAL_HANDLE *sdHandle, uint32_t line); +int32_t chal_sd_get_response(CHAL_HANDLE *sdHandle, uint32_t *resp); +int32_t chal_sd_clear_pending_irq(CHAL_HANDLE *sdHandle); +int32_t chal_sd_get_irq_status(CHAL_HANDLE *sdHandle); +int32_t chal_sd_clear_irq(CHAL_HANDLE *sdHandle, uint32_t mask); +uint32_t chal_sd_get_present_status(CHAL_HANDLE *sdHandle); +int32_t chal_sd_get_atuo12_error(CHAL_HANDLE *sdHandle); +void chal_sd_set_speed(CHAL_HANDLE *sdHandle, uint32_t speed); +int32_t chal_sd_check_cap(CHAL_HANDLE *sdHandle, uint32_t cap); +void chal_sd_set_irq_signal(CHAL_HANDLE *sdHandle, uint32_t mask, + uint32_t state); +void chal_sd_dump_fifo(CHAL_HANDLE *sdHandle); +#endif /* CHAL_SD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h new file mode 100644 index 0000000..9563273 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef CHAL_TYPES_H +#define CHAL_TYPES_H + +#include + +// +// Generic cHAL handler +// +#ifndef CHAL_HANDLE + typedef void *CHAL_HANDLE; ///< void pointer (32 bits wide) +#endif + +#endif /* _CHAL_TYPES_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h new file mode 100644 index 0000000..52b8bc8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_H +#define CSL_SD_H + +#define SD_CLOCK_BASE 104000000 +#define SD_CLOCK_52MHZ 52000000 +#define SD_CLOCK_26MHZ 26000000 +#define SD_CLOCK_17MHZ 17330000 +#define SD_CLOCK_13MHZ 13000000 +#define SD_CLOCK_10MHZ 10000000 +#define SD_CLOCK_9MHZ 9000000 +#define SD_CLOCK_7MHZ 7000000 +#define SD_CLOCK_5MHZ 5000000 +#define SD_CLOCK_1MHZ 1000000 +#define SD_CLOCK_400KHZ 400000 + +#define SD_DRIVE_STRENGTH_MASK 0x38000000 +#if defined(_BCM213x1_) || defined(_BCM21551_) || defined(_ATHENA_) +#define SD_DRIVE_STRENGTH 0x28000000 +#elif defined(_BCM2153_) +#define SD_DRIVE_STRENGTH 0x38000000 +#else +#define SD_DRIVE_STRENGTH 0x00000000 +#endif + +#define SD_NUM_HOST 2 + +#define SD_CARD_UNLOCK 0 +#define SD_CARD_LOCK 0x4 +#define SD_CARD_CLEAR_PWD 0x2 +#define SD_CARD_SET_PWD 0x1 +#define SD_CARD_ERASE_PWD 0x8 + +#define SD_CARD_LOCK_STATUS 0x02000000 +#define SD_CARD_UNLOCK_STATUS 0x01000000 + +#define SD_CMD_ERROR_FLAGS (0x18F << 16) +#define SD_DATA_ERROR_FLAGS (0x70 << 16) +#define SD_AUTO_CMD12_ERROR_FLAGS (0x9F) +#define SD_CARD_STATUS_ERROR 0x10000000 +#define SD_CMD_MISSING 0x80000000 + +#define SD_TRAN_HIGH_SPEED 0x32 +#define SD_CARD_HIGH_CAPACITY 0x40000000 +#define SD_CARD_POWER_UP_STATUS 0x80000000 + +struct sd_dev_info { + uint32_t mode; /* interrupt or polling */ + uint32_t dma; /* dma enabled or disabled */ + uint32_t voltage; /* voltage level */ + uint32_t slot; /* if the HC is locatd at slot 0 or slot 1 */ + uint32_t version; /* 1.0 or 2.0 */ + uint32_t curSystemAddr; /* system address */ + uint32_t dataWidth; /* data width for the controller */ + uint32_t clock; /* clock rate */ + uint32_t status; /* if device is active on transfer or not */ +}; + +void data_xfer_setup(struct sd_handle *handle, uint8_t *data, + uint32_t length, int dir); +int reset_card(struct sd_handle *handle); +int reset_host_ctrl(struct sd_handle *handle); +int init_card(struct sd_handle *handle, int detection); +int init_mmc_card(struct sd_handle *handle); +int write_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer); +int read_buffer(struct sd_handle *handle, uint32_t len, uint8_t *buffer); +int select_blk_sz(struct sd_handle *handle, uint16_t size); +int check_error(struct sd_handle *handle, uint32_t ints); + +int process_data_xfer(struct sd_handle *handle, uint8_t *buffer, + uint32_t addr, uint32_t length, int dir); +int read_block(struct sd_handle *handle, uint8_t *dst, uint32_t addr, + uint32_t len); +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int erase_card(struct sd_handle *handle, uint32_t addr, uint32_t blocks); +#endif +int write_block(struct sd_handle *handle, uint8_t *src, uint32_t addr, + uint32_t len); +int process_cmd_response(struct sd_handle *handle, uint32_t cmdIndex, + uint32_t rsp0, uint32_t rsp1, uint32_t rsp2, + uint32_t rsp3, struct sd_resp *resp); +int32_t set_config(struct sd_handle *handle, uint32_t speed, + uint32_t retry, uint32_t dma, uint32_t dmaBound, + uint32_t blkSize, uint32_t wfe_retry); + +uint32_t wait_for_event(struct sd_handle *handle, uint32_t mask, + uint32_t retry); +int set_boot_config(struct sd_handle *handle, uint32_t config); + +int mmc_cmd1(struct sd_handle *handle); +#endif /* CSL_SD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h new file mode 100644 index 0000000..425603f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_CMD_H +#define CSL_SD_CMD_H + +#define SD_CMD_OK 0 +#define SD_CMD_ERROR -1 + +#define SD_CMD_ERR_NO_IO_FUNC 5 +#define SD_CMD_ERR_INVALID_PARAMETER 6 +#define SD_CMD_ERR_R1_ILLEGAL_COMMAND 7 +#define SD_CMD_ERR_R1_COM_CRC_ERROR 8 +#define SD_CMD_ERR_R1_FUNC_NUM_ERROR 9 +#define SD_CMD_ERR_R1_ADDRESS_ERROR 10 +#define SD_CMD_ERR_R1_PARAMETER_ERROR 11 +#define SD_CMD_ERR_DATA_ERROR_TOKEN 12 +#define SD_CMD_ERR_DATA_NOT_ACCEPTED 13 +#define SD_CMD7_ARG_RCA_SHIFT 16 + +#define SD_CARD_STATUS_PENDING 0x01 +#define SD_CARD_STATUS_BUFFER_OVERFLOW 0x01 +#define SD_CARD_STATUS_DEVICE_BUSY 0x02 +#define SD_CARD_STATUS_UNSUCCESSFUL 0x03 +#define SD_CARD_STATUS_NOT_IMPLEMENTED 0x04 +#define SD_CARD_STATUS_ACCESS_VIOLATION 0x05 +#define SD_CARD_STATUS_INVALID_HANDLE 0x06 +#define SD_CARD_STATUS_INVALID_PARAMETER 0x07 +#define SD_CARD_STATUS_NO_SUCH_DEVICE 0x08 +#define SD_CARD_STATUS_INVALID_DEVICE_REQUEST 0x09 +#define SD_CARD_STATUS_NO_MEMORY 0x0A +#define SD_CARD_STATUS_BUS_DRIVER_NOT_READY 0x0B +#define SD_CARD_STATUS_DATA_ERROR 0x0C +#define SD_CARD_STATUS_CRC_ERROR 0x0D +#define SD_CARD_STATUS_INSUFFICIENT_RESOURCES 0x0E +#define SD_CARD_STATUS_DEVICE_NOT_CONNECTED 0x10 +#define SD_CARD_STATUS_DEVICE_REMOVED 0x11 +#define SD_CARD_STATUS_DEVICE_NOT_RESPONDING 0x12 +#define SD_CARD_STATUS_CANCELED 0x13 +#define SD_CARD_STATUS_RESPONSE_TIMEOUT 0x14 +#define SD_CARD_STATUS_DATA_TIMEOUT 0x15 +#define SD_CARD_STATUS_DEVICE_RESPONSE_ERROR 0x16 +#define SD_CARD_STATUS_DEVICE_UNSUPPORTED 0x17 + +/* Response structure */ +struct sd_r2_resp { + uint32_t rsp4; /* 127:96 */ + uint32_t rsp3; /* 95:64 */ + uint32_t rsp2; /* 63:32 */ + uint32_t rsp1; /* 31:0 */ +}; + +struct sd_r3_resp { + uint32_t ocr; +}; + +struct sd_r4_resp { + uint8_t cardReady; + uint8_t funcs; + uint8_t memPresent; + uint32_t ocr; +}; + +struct sd_r5_resp { + uint8_t data; +}; + +struct sd_r6_resp { + uint16_t rca; + uint16_t cardStatus; +}; + +struct sd_r7_resp { + uint16_t rca; +}; + +struct sd_resp { + uint8_t r1; + uint32_t cardStatus; + uint32_t rawData[4]; + union { + struct sd_r2_resp r2; + struct sd_r3_resp r3; + struct sd_r4_resp r4; + struct sd_r5_resp r5; + struct sd_r6_resp r6; + struct sd_r7_resp r7; + } data; +}; + +struct sd_card_info { + uint32_t type; /* card type SD, MMC or SDIO */ + uint64_t size; /* card size */ + uint32_t speed; /* card speed */ + uint32_t voltage; /* voltage supported */ + uint32_t mId; /* manufacturer ID */ + uint32_t oId; /* OEM ID */ + uint32_t classes; /* card class */ + uint32_t name1; /* product name part 1 */ + uint32_t name2; /* product name part 2 */ + uint32_t revision; /* revison */ + uint32_t sn; /* serial number */ + uint32_t numIoFuns; /* total I/O function number */ + uint32_t maxRdBlkLen; /* max read block length */ + uint32_t maxWtBlkLen; /* max write block length */ + uint32_t blkMode; /* sdio card block mode support */ + uint32_t f0Cis; /* sdio card block mode support */ + uint32_t f1Cis; /* sdio card block mode support */ + + uint8_t partRead; /* partial block read allowed */ + uint8_t partWrite; /* partial block write allowed */ + uint8_t dsr; /* card DSR */ + uint8_t rdCurMin; /* min current for read */ + uint8_t rdCurMax; /* max current for read */ + uint8_t wtCurMin; /* min current for write */ + uint8_t wtCurMax; /* max current for write */ + uint8_t erase; /* erase enable */ + uint8_t eraseSecSize; /* erase sector size */ + uint8_t proGrpSize; /* write protection group size */ + uint8_t protect; /* permanent write protection or not */ + uint8_t tmpProt; /* temp write protection or not */ + uint8_t wtSpeed; /* write speed relatively to read */ + uint8_t version; /* card version 0:1.0 - 1.01, 1:1.10, 2:2.0 */ + uint8_t eraseState; /* if the data will be 0 or 1 after erase */ + uint8_t bus; /* data with supported */ + uint8_t security; /* security support 0, 2:1.01 3:2.0 */ + uint8_t format; /* file format */ + uint8_t fileGrp; /* file group */ + char pwd[20]; /* password */ +}; + +struct sd_handle { + struct sd_dev *device; + struct sd_card_info *card; +}; + +int sd_cmd0(struct sd_handle *handle); +int sd_cmd1(struct sd_handle *handle, uint32_t initOcr, uint32_t *ocr); +int sd_cmd2(struct sd_handle *handle); +int sd_cmd3(struct sd_handle *handle); +int sd_cmd7(struct sd_handle *handle, uint32_t rca); +int sd_cmd9(struct sd_handle *handle, struct sd_card_data *card); +int sd_cmd13(struct sd_handle *handle, uint32_t *status); +int sd_cmd16(struct sd_handle *handle, uint32_t blockLen); +int sd_cmd17(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +int sd_cmd18(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +#ifdef INCLUDE_EMMC_DRIVER_WRITE_CODE +int sd_cmd24(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +int sd_cmd25(struct sd_handle *handle, + uint32_t addr, uint32_t len, uint8_t *buffer); +#endif +#ifdef INCLUDE_EMMC_DRIVER_ERASE_CODE +int sd_cmd35(struct sd_handle *handle, uint32_t start); +int sd_cmd36(struct sd_handle *handle, uint32_t end); +int sd_cmd38(struct sd_handle *handle); +#endif +int mmc_cmd6(struct sd_handle *handle, uint32_t argument); +int mmc_cmd8(struct sd_handle *handle, uint8_t *extCsdReg); + +int send_cmd(struct sd_handle *handle, uint32_t cmdIndex, + uint32_t argument, uint32_t options, struct sd_resp *resp); +#endif /* CSL_SD_CMD_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h new file mode 100644 index 0000000..597e1e0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h @@ -0,0 +1,435 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSL_SD_PROT_H +#define CSL_SD_PROT_H + +#define SD_CARD_UNKNOWN 0 /* bad type or unrecognized */ +#define SD_CARD_SD 1 /* IO only card */ +#define SD_CARD_SDIO 2 /* memory only card */ +#define SD_CARD_COMBO 3 /* IO and memory combo card */ +#define SD_CARD_MMC 4 /* memory only card */ +#define SD_CARD_CEATA 5 /* IO and memory combo card */ + +#define SD_IO_FIXED_ADDRESS 0 /* fix Address */ +#define SD_IO_INCREMENT_ADDRESS 1 + +#define SD_HIGH_CAPACITY_CARD 0x40000000 + +#define MMC_CMD_IDLE_RESET_ARG 0xF0F0F0F0 + +/* Supported operating voltages are 3.2-3.3 and 3.3-3.4 */ +#define MMC_OCR_OP_VOLT 0x00300000 +/* Enable sector access mode */ +#define MMC_OCR_SECTOR_ACCESS_MODE 0x40000000 + +/* command index */ +#define SD_CMD_GO_IDLE_STATE 0 /* mandatory for SDIO */ +#define SD_CMD_SEND_OPCOND 1 +#define SD_CMD_ALL_SEND_CID 2 +#define SD_CMD_MMC_SET_RCA 3 +#define SD_CMD_MMC_SET_DSR 4 +#define SD_CMD_IO_SEND_OP_COND 5 /* mandatory for SDIO */ +#define SD_ACMD_SET_BUS_WIDTH 6 +#define SD_CMD_SWITCH_FUNC 6 +#define SD_CMD_SELECT_DESELECT_CARD 7 +#define SD_CMD_READ_EXT_CSD 8 +#define SD_CMD_SEND_CSD 9 +#define SD_CMD_SEND_CID 10 +#define SD_CMD_STOP_TRANSMISSION 12 +#define SD_CMD_SEND_STATUS 13 +#define SD_ACMD_SD_STATUS 13 +#define SD_CMD_GO_INACTIVE_STATE 15 +#define SD_CMD_SET_BLOCKLEN 16 +#define SD_CMD_READ_SINGLE_BLOCK 17 +#define SD_CMD_READ_MULTIPLE_BLOCK 18 +#define SD_CMD_WRITE_BLOCK 24 +#define SD_CMD_WRITE_MULTIPLE_BLOCK 25 +#define SD_CMD_PROGRAM_CSD 27 +#define SD_CMD_SET_WRITE_PROT 28 +#define SD_CMD_CLR_WRITE_PROT 29 +#define SD_CMD_SEND_WRITE_PROT 30 +#define SD_CMD_ERASE_WR_BLK_START 32 +#define SD_CMD_ERASE_WR_BLK_END 33 +#define SD_CMD_ERASE_GROUP_START 35 +#define SD_CMD_ERASE_GROUP_END 36 +#define SD_CMD_ERASE 38 +#define SD_CMD_LOCK_UNLOCK 42 +#define SD_CMD_IO_RW_DIRECT 52 /* mandatory for SDIO */ +#define SD_CMD_IO_RW_EXTENDED 53 /* mandatory for SDIO */ +#define SD_CMD_APP_CMD 55 +#define SD_CMD_GEN_CMD 56 +#define SD_CMD_READ_OCR 58 +#define SD_CMD_CRC_ON_OFF 59 /* mandatory for SDIO */ +#define SD_ACMD_SEND_NUM_WR_BLOCKS 22 +#define SD_ACMD_SET_WR_BLOCK_ERASE_CNT 23 +#define SD_ACMD_SD_SEND_OP_COND 41 +#define SD_ACMD_SET_CLR_CARD_DETECT 42 +#define SD_ACMD_SEND_SCR 51 + +/* response parameters */ +#define SD_RSP_NO_NONE 0 +#define SD_RSP_NO_1 1 +#define SD_RSP_NO_2 2 +#define SD_RSP_NO_3 3 +#define SD_RSP_NO_4 4 +#define SD_RSP_NO_5 5 +#define SD_RSP_NO_6 6 + +/* Modified R6 response (to CMD3) */ +#define SD_RSP_MR6_COM_CRC_ERROR 0x8000 +#define SD_RSP_MR6_ILLEGAL_COMMAND 0x4000 +#define SD_RSP_MR6_ERROR 0x2000 + +/* Modified R1 in R4 Response (to CMD5) */ +#define SD_RSP_MR1_SBIT 0x80 +#define SD_RSP_MR1_PARAMETER_ERROR 0x40 +#define SD_RSP_MR1_RFU5 0x20 +#define SD_RSP_MR1_FUNC_NUM_ERROR 0x10 +#define SD_RSP_MR1_COM_CRC_ERROR 0x80 +#define SD_RSP_MR1_ILLEGAL_COMMAND 0x40 +#define SD_RSP_MR1_RFU1 0x20 +#define SD_RSP_MR1_IDLE_STATE 0x01 + +/* R5 response (to CMD52 and CMD53) */ +#define SD_RSP_R5_COM_CRC_ERROR 0x80 +#define SD_RSP_R5_ILLEGAL_COMMAND 0x40 +#define SD_RSP_R5_IO_CURRENTSTATE1 0x20 +#define SD_RSP_R5_IO_CURRENTSTATE0 0x10 +#define SD_RSP_R5_ERROR 0x80 +#define SD_RSP_R5_RFU 0x40 +#define SD_RSP_R5_FUNC_NUM_ERROR 0x20 +#define SD_RSP_R5_OUT_OF_RANGE 0x01 + +/* argument for SD_CMD_IO_RW_DIRECT and SD_CMD_IO_RW_EXTENDED */ +#define SD_OP_READ 0 /* Read_Write */ +#define SD_OP_WRITE 1 /* Read_Write */ + +#define SD_RW_NORMAL 0 /* no RAW */ +#define SD_RW_RAW 1 /* RAW */ + +#define SD_BYTE_MODE 0 /* Byte Mode */ +#define SD_BLOCK_MODE 1 /* BlockMode */ + +#define SD_FIXED_ADDRESS 0 /* fix Address */ +#define SD_INCREMENT_ADDRESS 1 /* IncrementAddress */ + +#define SD_CMD5_ARG_IO_OCR_MASK 0x00FFFFFF +#define SD_CMD5_ARG_IO_OCR_SHIFT 0 +#define SD_CMD55_ARG_RCA_SHIFT 16 +#define SD_CMD59_ARG_CRC_OPTION_MASK 0x01 +#define SD_CMD59_ARG_CRC_OPTION_SHIFT 0 + +/* SD_CMD_IO_RW_DIRECT Argument */ +#define SdioIoRWDirectArg(rw, raw, func, addr, data) \ + (((rw & 1) << 31) | ((func & 0x7) << 28) | \ + ((raw & 1) << 27) | ((addr & 0x1FFFF) << 9) | \ + (data & 0xFF)) + +/* build SD_CMD_IO_RW_EXTENDED Argument */ +#define SdioIoRWExtArg(rw, blk, func, addr, inc_addr, count) \ + (((rw & 1) << 31) | ((func & 0x7) << 28) | \ + ((blk & 1) << 27) | ((inc_addr & 1) << 26) | \ + ((addr & 0x1FFFF) << 9) | (count & 0x1FF)) + +/* + * The Common I/O area shall be implemented on all SDIO cards and + * is accessed the the host via I/O reads and writes to function 0, + * the registers within the CIA are provided to enable/disable + * the operationo fthe i/o funciton. + */ + +/* cccr_sdio_rev */ +#define SDIO_REV_SDIOID_MASK 0xf0 /* SDIO spec revision number */ +#define SDIO_REV_CCCRID_MASK 0x0f /* CCCR format version number */ + +/* sd_rev */ +#define SDIO_REV_PHY_MASK 0x0f /* SD format version number */ +#define SDIO_FUNC_ENABLE_1 0x02 /* function 1 I/O enable */ +#define SDIO_FUNC_READY_1 0x02 /* function 1 I/O ready */ +#define SDIO_INTR_CTL_FUNC1_EN 0x2 /* interrupt enable for function 1 */ +#define SDIO_INTR_CTL_MASTER_EN 0x1 /* interrupt enable master */ +#define SDIO_INTR_STATUS_FUNC1 0x2 /* interrupt pending for function 1 */ +#define SDIO_IO_ABORT_RESET_ALL 0x08 /* I/O card reset */ +#define SDIO_IO_ABORT_FUNC_MASK 0x07 /* abort selection: function x */ +#define SDIO_BUS_CARD_DETECT_DIS 0x80 /* Card Detect disable */ +#define SDIO_BUS_SPI_CONT_INTR_CAP 0x40 /* support continuous SPI interrupt */ +#define SDIO_BUS_SPI_CONT_INTR_EN 0x20 /* continuous SPI interrupt enable */ +#define SDIO_BUS_DATA_WIDTH_MASK 0x03 /* bus width mask */ +#define SDIO_BUS_DATA_WIDTH_4BIT 0x02 /* bus width 4-bit mode */ +#define SDIO_BUS_DATA_WIDTH_1BIT 0x00 /* bus width 1-bit mode */ + +/* capability */ +#define SDIO_CAP_4BLS 0x80 /* 4-bit support for low speed card */ +#define SDIO_CAP_LSC 0x40 /* low speed card */ +#define SDIO_CAP_E4MI 0x20 /* enable int between block in 4-bit mode */ +#define SDIO_CAP_S4MI 0x10 /* support int between block in 4-bit mode */ +#define SDIO_CAP_SBS 0x08 /* support suspend/resume */ +#define SDIO_CAP_SRW 0x04 /* support read wait */ +#define SDIO_CAP_SMB 0x02 /* support multi-block transfer */ +#define SDIO_CAP_SDC 0x01 /* Support Direct cmd during multi-uint8 transfer */ + +/* CIA FBR1 registers */ +#define SDIO_FUNC1_INFO 0x100 /* basic info for function 1 */ +#define SDIO_FUNC1_EXT 0x101 /* extension of standard I/O device */ +#define SDIO_CIS_FUNC1_BASE_LOW 0x109 /* function 1 cis address bit 0-7 */ +#define SDIO_CIS_FUNC1_BASE_MID 0x10A /* function 1 cis address bit 8-15 */ +#define SDIO_CIS_FUNC1_BASE_HIGH 0x10B /* function 1 cis address bit 16 */ +#define SDIO_CSA_BASE_LOW 0x10C /* CSA base address uint8_t 0 */ +#define SDIO_CSA_BASE_MID 0x10D /* CSA base address uint8_t 1 */ +#define SDIO_CSA_BASE_HIGH 0x10E /* CSA base address uint8_t 2 */ +#define SDIO_CSA_DATA_OFFSET 0x10F /* CSA data register */ +#define SDIO_IO_BLK_SIZE_LOW 0x110 /* I/O block size uint8_t 0 */ +#define SDIO_IO_BLK_SIZE_HIGH 0x111 /* I/O block size uint8_t 1 */ + +/* SD_SDIO_FUNC1_INFO bits */ +#define SDIO_FUNC1_INFO_DIC 0x0f /* device interface code */ +#define SDIO_FUNC1_INFO_CSA 0x40 /* CSA support flag */ +#define SDIO_FUNC1_INFO_CSA_EN 0x80 /* CSA enabled */ + +/* SD_SDIO_FUNC1_EXT bits */ +#define SDIO_FUNC1_EXT_SHP 0x03 /* support high power */ +#define SDIO_FUNC1_EXT_EHP 0x04 /* enable high power */ + +/* devctr */ +/* I/O device interface code */ +#define SDIO_DEVCTR_DEVINTER 0x0f +/* support CSA */ +#define SDIO_DEVCTR_CSA_SUP 0x40 +/* enable CSA */ +#define SDIO_DEVCTR_CSA_EN 0x80 + +/* ext_dev */ +/* supports high-power mask */ +#define SDIO_HIGHPWR_SUPPORT_M 0x3 +/* enable high power */ +#define SDIO_HIGHPWR_EN 0x4 +/* standard power function(up to 200mA */ +#define SDIO_HP_STD 0 +/* need high power to operate */ +#define SDIO_HP_REQUIRED 0x2 +/* can work with standard power, but prefer high power */ +#define SDIO_HP_DESIRED 0x3 + +/* misc define */ +/* macro to calculate fbr register base */ +#define FBR_REG_BASE(n) (n*0x100) +#define SDIO_FUNC_0 0 +#define SDIO_FUNC_1 1 +#define SDIO_FUNC_2 2 +#define SDIO_FUNC_3 3 +#define SDIO_FUNC_4 4 +#define SDIO_FUNC_5 5 +#define SDIO_FUNC_6 6 +#define SDIO_FUNC_7 7 + +/* maximum block size for block mode operation */ +#define SDIO_MAX_BLOCK_SIZE 2048 +/* minimum block size for block mode operation */ +#define SDIO_MIN_BLOCK_SIZE 1 + +/* Card registers: status bit position */ +#define SDIO_STATUS_OUTOFRANGE 31 +#define SDIO_STATUS_COMCRCERROR 23 +#define SDIO_STATUS_ILLEGALCOMMAND 22 +#define SDIO_STATUS_ERROR 19 +#define SDIO_STATUS_IOCURRENTSTATE3 12 +#define SDIO_STATUS_IOCURRENTSTATE2 11 +#define SDIO_STATUS_IOCURRENTSTATE1 10 +#define SDIO_STATUS_IOCURRENTSTATE0 9 +#define SDIO_STATUS_FUN_NUM_ERROR 4 + +#define GET_SDIOCARD_STATUS(x) ((x >> 9) & 0x0f) +#define SDIO_STATUS_STATE_IDLE 0 +#define SDIO_STATUS_STATE_READY 1 +#define SDIO_STATUS_STATE_IDENT 2 +#define SDIO_STATUS_STATE_STBY 3 +#define SDIO_STATUS_STATE_TRAN 4 +#define SDIO_STATUS_STATE_DATA 5 +#define SDIO_STATUS_STATE_RCV 6 +#define SDIO_STATUS_STATE_PRG 7 +#define SDIO_STATUS_STATE_DIS 8 + +/* sprom */ +#define SBSDIO_SPROM_CS 0x10000 /* command and status */ +#define SBSDIO_SPROM_INFO 0x10001 /* info register */ +#define SBSDIO_SPROM_DATA_LOW 0x10002 /* indirect access data uint8_t 0 */ +#define SBSDIO_SPROM_DATA_HIGH 0x10003 /* indirect access data uint8_t 1 */ +#define SBSDIO_SPROM_ADDR_LOW 0x10004 /* indirect access addr uint8_t 0 */ +#define SBSDIO_SPROM_ADDR_HIGH 0x10005 /* indirect access addr uint8_t 0 */ +#define SBSDIO_CHIP_CTRL_DATA 0x10006 /* xtal_pu data output */ +#define SBSDIO_CHIP_CTRL_EN 0x10007 /* xtal_pu enable */ +#define SBSDIO_WATERMARK 0x10008 /* retired in rev 7 */ +#define SBSDIO_DEVICE_CTL 0x10009 /* control busy signal generation */ + +#define SBSDIO_SPROM_IDLE 0 +#define SBSDIO_SPROM_WRITE 1 +#define SBSDIO_SPROM_READ 2 +#define SBSDIO_SPROM_WEN 4 +#define SBSDIO_SPROM_WDS 7 +#define SBSDIO_SPROM_DONE 8 + +/* SBSDIO_SPROM_INFO */ +#define SBSDIO_SROM_SZ_MASK 0x03 /* SROM size, 1: 4k, 2: 16k */ +#define SBSDIO_SROM_BLANK 0x04 /* depreciated in corerev 6 */ +#define SBSDIO_SROM_OTP 0x80 /* OTP present */ + +/* SBSDIO_CHIP_CTRL */ +/* or'd with onchip xtal_pu, 1: power on oscillator */ +#define SBSDIO_CHIP_CTRL_XTAL 0x01 + +/* SBSDIO_WATERMARK */ +/* number of bytes minus 1 for sd device to wait before sending data to host */ +#define SBSDIO_WATERMARK_MASK 0x3f + +/* SBSDIO_DEVICE_CTL */ +/* 1: device will assert busy signal when receiving CMD53 */ +#define SBSDIO_DEVCTL_SETBUSY 0x01 +/* 1: assertion of sdio interrupt is synchronous to the sdio clock */ +#define SBSDIO_DEVCTL_SPI_INTR_SYNC 0x02 + +/* function 1 OCP space */ +/* sb offset addr is <= 15 bits, 32k */ +#define SBSDIO_SB_OFT_ADDR_MASK 0x07FFF +#define SBSDIO_SB_OFT_ADDR_LIMIT 0x08000 +/* sdsdio function 1 OCP space has 16/32 bit section */ +#define SBSDIO_SB_ACCESS_2_4B_FLAG 0x08000 + +/* direct(mapped) cis space */ +/* MAPPED common CIS address */ +#define SBSDIO_CIS_BASE_COMMON 0x1000 +/* function 0(common) cis size in bytes */ +#define SBSDIO_CIS_FUNC0_LIMIT 0x020 +/* funciton 1 cis size in bytes */ +#define SBSDIO_CIS_SIZE_LIMIT 0x200 +/* cis offset addr is < 17 bits */ +#define SBSDIO_CIS_OFT_ADDR_MASK 0x1FFFF +/* manfid tuple length, include tuple, link bytes */ +#define SBSDIO_CIS_MANFID_TUPLE_LEN 6 + +/* indirect cis access (in sprom) */ +/* 8 control bytes first, CIS starts from 8th uint8_t */ +#define SBSDIO_SPROM_CIS_OFFSET 0x8 +/* sdio uint8_t mode: maximum length of one data comamnd */ +#define SBSDIO_BYTEMODE_DATALEN_MAX 64 +/* 4317 supports less */ +#define SBSDIO_BYTEMODE_DATALEN_MAX_4317 52 +/* sdio core function one address mask */ +#define SBSDIO_CORE_ADDR_MASK 0x1FFFF + +/* CEATA defines */ +#define CEATA_EXT_CSDBLOCK_SIZE 512 +#define CEATA_FAST_IO 39 +#define CEATA_MULTIPLE_REGISTER_RW 60 +#define CEATA_MULTIPLE_BLOCK_RW 61 + +/* defines CE ATA task file registers */ +#define CEATA_SCT_CNT_EXP_REG 0x02 +#define CEATA_LBA_LOW_EXP_REG 0x03 +#define CEATA_LBA_MID_EXP_REG 0x04 +#define CEATA_LBA_HIGH_EXP_REG 0x05 +#define CEATA_CNTRL_REG 0x06 +#define CEATA_FEATURE_REG 0x09 /* write */ +#define CEATA_ERROR_REG 0x09 /* read */ +#define CEATA_SCT_CNT_REG 0x0A +#define CEATA_LBA_LOW_REG 0x0B +#define CEATA_LBA_MID_REG 0x0C +#define CEATA_LBA_HIGH_REG 0x0D +#define CEATA_DEV_HEAD_REG 0x0E +#define CEATA_STA_REG 0x0F /* read */ +#define CEATA_CMD_REG 0x0F /* write */ + +/* defines CEATA control and status registers for ce ata client driver */ +#define CEATA_SCR_TEMPC_REG 0x80 +#define CEATA_SCR_TEMPMAXP_REG 0x84 +#define CEATA_TEMPMINP_REG 0x88 +#define CEATA_SCR_STATUS_REG 0x8C +#define CEATA_SCR_REALLOCSA_REG 0x90 +#define CEATA_SCR_ERETRACTSA_REG 0x94 +#define CEATA_SCR_CAPABILITIES_REG 0x98 +#define CEATA_SCR_CONTROL_REG 0xC0 + +/* defines for SCR capabilities register bits for ce ata client driver */ +#define CEATA_SCR_CAP_512 0x00000001 +#define CEATA_SCR_CAP_1K 0x00000002 +#define CEATA_SCR_CAP_4K 0x00000004 + +/* defines CE ATA Control reg bits for ce ata client driver */ +#define CEATA_CNTRL_ENABLE_INTR 0x00 +#define CEATA_CNTRL_DISABLE_INTR 0x02 +#define CEATA_CNTRL_SRST 0x04 +#define CEATA_CNTRL_RSRST 0x00 + +/* define CE ATA Status reg bits for ce ata client driver */ +#define CEATA_STA_ERROR_BIT 0x01 +#define CEATA_STA_OVR_BIT 0x02 +#define CEATA_STA_SPT_BIT 0x04 +#define CEATA_STA_DRQ_BIT 0x08 +#define CEATA_STA_DRDY_BIT 0x40 +#define CEATA_STA_BSY_BIT 0x80 + +/* define CE ATA Error reg bits for ce ata client driver */ +#define CEATA_ERROR_ABORTED_BIT 0x04 +#define CEATA_ERROR_IDNF_BIT 0x10 +#define CEATA_ERROR_UNCORRECTABLE_BIT 0x40 +#define CEATA_ERROR_ICRC_BIT 0x80 + +/* define CE ATA Commands for ce ata client driver */ +#define CEATA_CMD_IDENTIFY_DEVICE 0xEC +#define CEATA_CMD_READ_DMA_EXT 0x25 +#define CEATA_CMD_WRITE_DMA_EXT 0x35 +#define CEATA_CMD_STANDBY_IMMEDIATE 0xE0 +#define CEATA_CMD_FLUSH_CACHE_EXT 0xEA + +struct csd_mmc { + uint32_t padding:8; + uint32_t structure:2; + uint32_t csdSpecVer:4; + uint32_t reserved1:2; + uint32_t taac:8; + uint32_t nsac:8; + uint32_t speed:8; + uint32_t classes:12; + uint32_t rdBlkLen:4; + uint32_t rdBlkPartial:1; + uint32_t wrBlkMisalign:1; + uint32_t rdBlkMisalign:1; + uint32_t dsr:1; + uint32_t reserved2:2; + uint32_t size:12; + uint32_t vddRdCurrMin:3; + uint32_t vddRdCurrMax:3; + uint32_t vddWrCurrMin:3; + uint32_t vddWrCurrMax:3; + uint32_t devSizeMulti:3; + uint32_t eraseGrpSize:5; + uint32_t eraseGrpSizeMulti:5; + uint32_t wrProtGroupSize:5; + uint32_t wrProtGroupEnable:1; + uint32_t manuDefEcc:2; + uint32_t wrSpeedFactor:3; + uint32_t wrBlkLen:4; + uint32_t wrBlkPartial:1; + uint32_t reserved5:4; + uint32_t protAppl:1; + uint32_t fileFormatGrp:1; + uint32_t copyFlag:1; + uint32_t permWrProt:1; + uint32_t tmpWrProt:1; + uint32_t fileFormat:2; + uint32_t eccCode:2; +}; + +/* CSD register*/ +union sd_csd { + uint32_t csd[4]; + struct csd_mmc mmc; +}; + +struct sd_card_data { + union sd_csd csd; +}; +#endif /* CSL_SD_PROT_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h new file mode 100644 index 0000000..8e61b51 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PBOOT_HAL_MEMORY_EMMC_DRV_H +#define PBOOT_HAL_MEMORY_EMMC_DRV_H + +#include + +#include "emmc_chal_types.h" +#include "emmc_chal_sd.h" +#include "emmc_csl_sdprot.h" +#include "emmc_csl_sdcmd.h" +#include "emmc_csl_sd.h" +#include "emmc_brcm_rdb_sd4_top.h" + +#define CLK_SDIO_DIV_52MHZ 0x0 +#define SYSCFG_IOCR4_PAD_10MA 0x38000000 + +#define SDCLK_CNT_PER_MS 52000 +#define BOOT_ACK_TIMEOUT (50 * SDCLK_CNT_PER_MS) +#define BOOT_DATA_TIMEOUT (1000 * SDCLK_CNT_PER_MS) + +#define EMMC_BOOT_OK 0 +#define EMMC_BOOT_ERROR 1 +#define EMMC_BOOT_TIMEOUT 2 +#define EMMC_BOOT_INVALIDIMAGE 3 +#define EMMC_BOOT_NO_CARD 4 + +#define EMMC_USER_AREA 0 +#define EMMC_BOOT_PARTITION1 1 +#define EMMC_BOOT_PARTITION2 2 +#define EMMC_USE_CURRENT_PARTITION 3 + +#define EMMC_BOOT_PARTITION_SIZE (128*1024) +#define EMMC_BLOCK_SIZE 512 +#define EMMC_DMA_SIZE (4*1024) + +/* + * EMMC4.3 definitions + * Table 6 EXT_CSD access mode + * Access + * Bits Access Name Operation + * 00 Command Set The command set is changed according to the Cmd Set field of + * the argument + * 01 Set Bits The bits in the pointed uint8_t are set, + * according to the 1 bits in the Value field. + * 10 Clear Bits The bits in the pointed uint8_t are cleared, + * according to the 1 bits in the Value field. + * 11 Write Byte The Value field is written into the pointed uint8_t. + */ + +#define SDIO_HW_EMMC_EXT_CSD_WRITE_BYTE 0X03000000 + +/* Boot bus width1 BOOT_BUS_WIDTH 1 R/W [177] */ +#define SDIO_HW_EMMC_EXT_CSD_BOOT_BUS_WIDTH_OFFSET 0X00B10000 + +/* Boot configuration BOOT_CONFIG 1 R/W [179] */ +#define SDIO_HW_EMMC_EXT_CSD_BOOT_CONFIG_OFFSET 0X00B30000 + +/* Bus width mode BUS_WIDTH 1 WO [183] */ +#define SDIO_HW_EMMC_EXT_CSD_BUS_WIDTH_OFFSET 0X00B70000 + +/* + * Bit 6: BOOT_ACK (non-volatile) + * 0x0 : No boot acknowledge sent (default) + * 0x1 : Boot acknowledge sent during boot operation + * Bit[5:3] : BOOT_PARTITION_ENABLE (non-volatile) + * User selects boot data that will be sent to master + * 0x0 : Device not boot enabled (default) + * 0x1 : Boot partition 1 enabled for boot + * 0x2 : Boot partition 2 enabled for boot + * 0x3-0x6 : Reserved + * 0x7 : User area enabled for boot + * Bit[2:0] : BOOT_PARTITION_ACCESS + * User selects boot partition for read and write operation + * 0x0 : No access to boot partition (default) + * 0x1 : R/W boot partition 1 + * 0x2 : R/W boot partition 2 + * 0x3-0x7 : Reserved + */ + +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT1 0X00000100 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_BOOT2 0X00000200 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_ACC_USER 0X00000000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT1 0X00004800 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_BOOT2 0X00005000 +#define SDIO_HW_EMMC_EXT_CSD_BOOT_EN_USER 0X00007800 + +#define SD_US_DELAY(x) udelay(x) + +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/fru.h b/arm-trusted-firmware/include/drivers/brcm/fru.h new file mode 100644 index 0000000..ee863b4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/fru.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FRU_H +#define FRU_H + +#include +#include + +/* max string length */ +#define FRU_MAX_STR_LEN 32 + +/* max number of DDR channels */ +#define BCM_MAX_NR_DDR 3 + +/* max supported FRU table size */ +#define BCM_MAX_FRU_LEN 512 + +/* FRU table starting offset */ +#define BCM_FRU_TBL_OFFSET 0x300000 + +/* FRU time constants */ +#define MINS_PER_DAY 1440 +#define MINS_PER_HOUR 60 +#define FRU_YEAR_START 1996 +#define FRU_MONTH_START 1 +#define FRU_DAY_START 1 +#define MONTHS_PER_YEAR 12 + +/* + * FRU areas based on the spec + */ +enum fru_area_name { + FRU_AREA_INTERNAL = 0, + FRU_AREA_CHASSIS_INFO, + FRU_AREA_BOARD_INFO, + FRU_AREA_PRODUCT_INFO, + FRU_AREA_MRECORD_INFO, + FRU_MAX_NR_AREAS +}; + +/* + * FRU area information + * + * @use: indicate this area is being used + * @version: format version + * @offset: offset of this area from the beginning of the FRU table + * @len: total length of the area + */ +struct fru_area_info { + bool use; + uint8_t version; + unsigned int offset; + unsigned int len; +}; + +/* + * DDR MCB information + * + * @idx: DDR channel index + * @size_mb: DDR size of this channel in MB + * @ref_id: DDR MCB reference ID + */ +struct ddr_mcb { + unsigned int idx; + unsigned int size_mb; + uint32_t ref_id; +}; + +/* + * DDR information + * + * @ddr_info: array that contains MCB related info for each channel + */ +struct ddr_info { + struct ddr_mcb mcb[BCM_MAX_NR_DDR]; +}; + +/* + * FRU board area information + * + * @lang: Language code + * @mfg_date: Manufacturing date + * @manufacturer: Manufacturer + * @product_name: Product name + * @serial_number: Serial number + * @part_number: Part number + * @file_id: FRU file ID + */ +struct fru_board_info { + unsigned char lang; + unsigned int mfg_date; + unsigned char manufacturer[FRU_MAX_STR_LEN]; + unsigned char product_name[FRU_MAX_STR_LEN]; + unsigned char serial_number[FRU_MAX_STR_LEN]; + unsigned char part_number[FRU_MAX_STR_LEN]; + unsigned char file_id[FRU_MAX_STR_LEN]; +}; + +/* + * FRU manufacture date in human readable format + */ +struct fru_time { + unsigned int min; + unsigned int hour; + unsigned int day; + unsigned int month; + unsigned int year; +}; + +#ifdef USE_FRU +int fru_validate(uint8_t *data, struct fru_area_info *fru_area); +int fru_parse_ddr(uint8_t *data, struct fru_area_info *area, + struct ddr_info *ddr); +int fru_parse_board(uint8_t *data, struct fru_area_info *area, + struct fru_board_info *board); +void fru_format_time(unsigned int min, struct fru_time *tm); +#else +static inline int fru_validate(uint8_t *data, struct fru_area_info *fru_area) +{ + return -1; +} + +static inline int fru_parse_ddr(uint8_t *data, struct fru_area_info *area, + struct ddr_info *ddr) +{ + return -1; +} + +static inline int fru_parse_board(uint8_t *data, struct fru_area_info *area, + struct fru_board_info *board) +{ + return -1; +} + +static inline void fru_format_time(unsigned int min, struct fru_time *tm) +{ +} +#endif /* USE_FRU */ + +#endif /* FRU_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h new file mode 100644 index 0000000..24d42e2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h @@ -0,0 +1,161 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_H +#define I2C_H + +#include + +#define I2C_SPEED_100KHz 100000 +#define I2C_SPEED_400KHz 400000 +#define I2C_SPEED_DEFAULT I2C_SPEED_100KHz + +/* + * Function Name: i2c_probe + * + * Description: + * This function probes the I2C bus for the existence of the specified + * device. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_probe(uint32_t bus_id, uint8_t devaddr); + +/* + * Function Name: i2c_init + * + * Description: + * This function initializes the SMBUS. + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_init(uint32_t bus_id, int speed); + +/* + * Function Name: i2c_set_bus_speed + * + * Description: + * This function configures the SMBUS speed + * + * Parameters: + * bus_id - I2C bus ID + * speed - I2C bus speed in Hz + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_set_bus_speed(uint32_t bus_id, uint32_t speed); + +/* + * Function Name: i2c_get_bus_speed + * + * Description: + * This function returns the SMBUS speed. + * + * Parameters: + * bus_id - I2C bus ID + * + * Return: + * Bus speed in Hz, 0 on failure + */ +uint32_t i2c_get_bus_speed(uint32_t bus_id); + +/* + * Function Name: i2c_recv_byte + * + * Description: + * This function reads I2C data from a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Read + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_recv_byte(uint32_t bus_id, uint8_t devaddr, uint8_t *value); + +/* + * Function Name: i2c_send_byte + * + * Description: + * This function send I2C data to a device without specifying + * a command regsiter. + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * value - Data Send + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_send_byte(uint32_t bus_id, uint8_t devaddr, uint8_t value); + +/* + * Function Name: i2c_read + * + * Description: + * This function reads I2C data from a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_read(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len); + +/* + * Function Name: i2c_write + * + * Description: + * This function write I2C data to a device with a designated + * command register + * + * Parameters: + * bus_id - I2C bus ID + * devaddr - Device Address + * addr - Register Offset + * alen - Address Length, 1 for byte, 2 for word (not supported) + * buffer - Data Buffer + * len - Data Length in bytes + * + * Return: + * 0 on success, or -1 on failure. + */ +int i2c_write(uint32_t bus_id, + uint8_t devaddr, + uint32_t addr, + int alen, + uint8_t *buffer, + int len); + + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h new file mode 100644 index 0000000..74ea824 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef I2C_REGS +#define I2C_REGS + +/* SMBUS Config register */ +#define SMB_CFG_REG 0x0U + +#define SMB_CFG_RST_MASK 0x80000000U +#define SMB_CFG_RST_SHIFT 31U + +#define SMB_CFG_SMBEN_MASK 0x40000000U +#define SMB_CFG_SMBEN_SHIFT 30U + +#define SMB_CFG_BITBANGEN_MASK 0x20000000U +#define SMB_CFG_BITBANGEN_SHIFT 29U + +#define SMB_CFG_EN_NIC_SMBADDR0_MASK 0x10000000U +#define SMB_CFG_EN_NIC_SMBADDR0_SHIFT 28U + +#define SMB_CFG_PROMISCMODE_MASK 0x08000000U +#define SMB_CFG_PROMISCMODE_SHIFT 27U + +#define SMB_CFG_TSTMPCNTEN_MASK 0x04000000U +#define SMB_CFG_TSTMPCNTEN_SHIFT 26U + +#define SMB_CFG_MSTRRTRYCNT_MASK 0x000F0000U +#define SMB_CFG_MSTRRTRYCNT_SHIFT 16U + +/* SMBUS Timing config register */ +#define SMB_TIMGCFG_REG 0x4U + +#define SMB_TIMGCFG_MODE400_MASK 0x80000000U +#define SMB_TIMGCFG_MODE400_SHIFT 31U + +#define SMB_TIMGCFG_RNDSLVSTR_MASK 0x7F000000U +#define SMB_TIMGCFG_RNDSLVSTR_SHIFT 24U + +#define SMB_TIMGCFG_PERSLVSTR_MASK 0x00FF0000U +#define SMB_TIMGCFG_PERSLVSTR_SHIFT 16U + +#define SMB_TIMGCFG_IDLTIME_MASK 0x0000FF00U +#define SMB_TIMGCFG_IDLTIME_SHIFT 8U + +/* SMBUS Slave address register */ +#define SMB_ADDR_REG 0x8U + +#define SMB_EN_NIC_SMBADDR3_MASK 0x80000000U +#define SMB_EN_NIC_SMBADDR3_SHIFT 31U + +#define SMB_NIC_SMBADDR3_MASK 0x7F000000U +#define SMB_NIC_SMBADDR3_SHIFT 24U + +#define SMB_EN_NIC_SMBADDR2_MASK 0x00800000U +#define SMB_EN_NIC_SMBADDR2_SHIFT 23U + +#define SMB_NIC_SMBADDR2_MASK 0x007F0000U +#define SMB_NIC_SMBADDR2_SHIFT 16U + +#define SMB_EN_NIC_SMBADDR1_MASK 0x00008000U +#define SMB_EN_NIC_SMBADDR1_SHIFT 15U + +#define SMB_NIC_SMBADDR1_MASK 0x00007F00U +#define SMB_NIC_SMBADDR1_SHIFT 8U + +#define SMB_EN_NIC_SMBADDR0_MASK 0x00000080U +#define SMB_EN_NIC_SMBADDR0_SHIFT 7U + +#define SMB_NIC_SMBADDR0_MASK 0x0000007FU +#define SMB_NIC_SMBADDR0_SHIFT 0U + +/* SMBUS Master FIFO control register */ +#define SMB_MSTRFIFOCTL_REG 0xCU + +#define SMB_MSTRRXFIFOFLSH_MASK 0x80000000U +#define SMB_MSTRRXFIFOFLSH_SHIFT 31U + +#define SMB_MSTRTXFIFOFLSH_MASK 0x40000000U +#define SMB_MSTRTXFIFOFLSH_SHIFT 30U + +#define SMB_MSTRRXPKTCNT_MASK 0x007F0000U +#define SMB_MSTRRXPKTCNT_SHIFT 16U + +#define SMB_MSTRRXFIFOTHR_MASK 0x00003F00U +#define SMB_MSTRRXFIFOTHR_SHIFT 8U + +/* SMBUS Slave FIFO control register */ +#define SMB_SLVFIFOCTL_REG 0x10U + +#define SMB_SLVRXFIFOFLSH_MASK 0x80000000U +#define SMB_SLVRXFIFOFLSH_SHIFT 31U + +#define SMB_SLVTXFIFOFLSH_MASK 0x40000000U +#define SMB_SLVTXFIFOFLSH_SHIFT 30U + +#define SMB_SLVRXPKTCNT_MASK 0x007F0000U +#define SMB_SLVRXPKTCNT_SHIFT 16U + +#define SMB_SLVRXFIFOTHR_MASK 0x00003F00U +#define SMB_SLVRXFIFOTHR_SHIFT 8U + +/* SMBUS Bit-bang mode control register */ +#define SMB_BITBANGCTL_REG 0x14U + +#define SMB_SMBCLKIN_MASK 0x80000000U +#define SMB_SMBCLKIN_SHIFT 31U + +#define SMB_SMBCLKOUTEN_MASK 0x40000000U +#define SMB_SMBCLKOUTEN_SHIFT 30U + +#define SMB_SMBDATAIN_MASK 0x20000000U +#define SMB_SMBDATAIN_SHIFT 29U + +#define SMB_SMBDATAOUTEN_MASK 0x10000000U +#define SMB_SMBDATAOUTEN_SHIFT 28U + +/* SMBUS Master command register */ +#define SMB_MSTRCMD_REG 0x30U + +#define SMB_MSTRSTARTBUSYCMD_MASK 0x80000000U +#define SMB_MSTRSTARTBUSYCMD_SHIFT 31U + +#define SMB_MSTRABORT_MASK 0x40000000U +#define SMB_MSTRABORT_SHIFT 30U + +#define SMB_MSTRSTS_MASK 0x0E000000U +#define SMB_MSTRSTS_SHIFT 25U + +#define SMB_MSTRSMBUSPROTO_MASK 0x00001E00U +#define SMB_MSTRSMBUSPROTO_SHIFT 9U + +#define SMB_MSTRPEC_MASK 0x00000100U +#define SMB_MSTRPEC_SHIFT 8U + +#define SMB_MSTRRDBYTECNT_MASK 0x000000FFU +#define SMB_MSTRRDBYTECNT_SHIFT 0U + +/* SMBUS Slave command register */ +#define SMB_SLVCMD_REG 0x34U + +#define SMB_SLVSTARTBUSYCMD_MASK 0x80000000U +#define SMB_SLVSTARTBUSYCMD_SHIFT 31U + +#define SMB_SLVABORT_MASK 0x40000000U +#define SMB_SLVABORT_SHIFT 30U + +#define SMB_SLVSTS_MASK 0x03800000U +#define SMB_SLVSTS_SHIFT 23U + +#define SMB_SLVPEC_MASK 0x00000100U +#define SMB_SLVPEC_SHIFT 8U + +/* SMBUS Event enable register */ +#define SMB_EVTEN_REG 0x38U + +#define SMB_MSTRRXFIFOFULLEN_MASK 0x80000000U +#define SMB_MSTRRXFIFOFULLEN_SHIFT 31U + +#define SMB_MSTRRXFIFOTHRHITEN_MASK 0x40000000U +#define SMB_MSTRRXFIFOTHRHITEN_SHIFT 30U + +#define SMB_MSTRRXEVTEN_MASK 0x20000000U +#define SMB_MSTRRXEVTEN_SHIFT 29U + +#define SMB_MSTRSTARTBUSYEN_MASK 0x10000000U +#define SMB_MSTRSTARTBUSYEN_SHIFT 28U + +#define SMB_MSTRTXUNDEN_MASK 0x08000000U +#define SMB_MSTRTXUNDEN_SHIFT 27U + +#define SMB_SLVRXFIFOFULLEN_MASK 0x04000000U +#define SMB_SLVRXFIFOFULLEN_SHIFT 26U + +#define SMB_SLVRXFIFOTHRHITEN_MASK 0x02000000U +#define SMB_SLVRXFIFOTHRHITEN_SHIFT 25U + +#define SMB_SLVRXEVTEN_MASK 0x01000000U +#define SMB_SLVRXEVTEN_SHIFT 24U + +#define SMB_SLVSTARTBUSYEN_MASK 0x00800000U +#define SMB_SLVSTARTBUSYEN_SHIFT 23U + +#define SMB_SLVTXUNDEN_MASK 0x00400000U +#define SMB_SLVTXUNDEN_SHIFT 22U + +#define SMB_SLVRDEVTEN_MASK 0x00200000U +#define SMB_SLVRDEVTEN_SHIFT 21U + +/* SMBUS Event status register */ +#define SMB_EVTSTS_REG 0x3CU + +#define SMB_MSTRRXFIFOFULLSTS_MASK 0x80000000U +#define SMB_MSTRRXFIFOFULLSTS_SHIFT 31U + +#define SMB_MSTRRXFIFOTHRHITSTS_MASK 0x40000000U +#define SMB_MSTRRXFIFOTHRHITSTS_SHIFT 30U + +#define SMB_MSTRRXEVTSTS_MASK 0x20000000U +#define SMB_MSTRRXEVTSTS_SHIFT 29U + +#define SMB_MSTRSTARTBUSYSTS_MASK 0x10000000U +#define SMB_MSTRSTARTBUSYSTS_SHIFT 28U + +#define SMB_MSTRTXUNDSTS_MASK 0x08000000U +#define SMB_MSTRTXUNDSTS_SHIFT 27U + +#define SMB_SLVRXFIFOFULLSTS_MASK 0x04000000U +#define SMB_SLVRXFIFOFULLSTS_SHIFT 26U + +#define SMB_SLVRXFIFOTHRHITSTS_MASK 0x02000000U +#define SMB_SLVRXFIFOTHRHITSTS_SHIFT 25U + +#define SMB_SLVRXEVTSTS_MASK 0x01000000U +#define SMB_SLVRXEVTSTS_SHIFT 24U + +#define SMB_SLVSTARTBUSYSTS_MASK 0x00800000U +#define SMB_SLVSTARTBUSYSTS_SHIFT 23U + +#define SMB_SLVTXUNDSTS_MASK 0x00400000U +#define SMB_SLVTXUNDSTS_SHIFT 22U + +#define SMB_SLVRDEVTSTS_MASK 0x00200000U +#define SMB_SLVRDEVTSTS_SHIFT 21U + +/* SMBUS Master data write register */ +#define SMB_MSTRDATAWR_REG 0x40U + +#define SMB_MSTRWRSTS_MASK 0x80000000U +#define SMB_MSTRWRSTS_SHIFT 31U + +#define SMB_MSTRWRDATA_MASK 0x000000FFU +#define SMB_MSTRWRDATA_SHIFT 0U + +/* SMBUS Master data read register */ +#define SMB_MSTRDATARD_REG 0x44U + +#define SMB_MSTRRDSTS_MASK 0xC0000000U +#define SMB_MSTRRDSTS_SHIFT 30U + +#define SMB_MSTRRDPECERR_MASK 0x20000000U +#define SMB_MSTRRDPECERR_SHIFT 29U + +#define SMB_MSTRRDDATA_MASK 0x000000FFU +#define SMB_MSTRRDDATA_SHIFT 0U + +/* SMBUS Slave data write register */ +#define SMB_SLVDATAWR_REG 0x48U + +#define SMB_SLVWRSTS_MASK 0x80000000U +#define SMB_SLVWRSTS_SHIFT 31U + +#define SMB_SLVWRDATA_MASK 0x000000FFU +#define SMB_SLVWRDATA_SHIFT 0U + +/* SMBUS Slave data read register */ +#define SMB_SLVDATARD_REG 0x4CU + +#define SMB_SLVRDSTS_MASK 0xC0000000U +#define SMB_SLVRDSTS_SHIFT 30U + +#define SMB_SLVRDERRSTS_MASK 0x30000000U +#define SMB_SLVRDERRSTS_SHIFT 28U + +#define SMB_SLVRDDATA_MASK 0x000000FFU +#define SMB_SLVRDDATA_SHIFT 0U + +#endif /* I2C_REGS */ diff --git a/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h b/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h new file mode 100644 index 0000000..be971f6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IPROC_GPIO_H +#define IPROC_GPIO_H + +#ifdef USE_GPIO +void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base); +#else +static void iproc_gpio_init(uintptr_t base, int nr_gpios, uintptr_t pinmux_base, + uintptr_t pinconf_base) +{ +} +#endif /* IPROC_GPIO */ + +#endif /* IPROC_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h b/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h new file mode 100644 index 0000000..b27c7b3 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MDIO_H +#define MDIO_H + +#define CMIC_MIIM_PARAM (PLAT_CMIC_MIIM_BASE + 0x23cU) +#define MDIO_PARAM_MIIM_CYCLE 29U +#define MDIO_PARAM_INTERNAL_SEL 25U +#define MDIO_PARAM_BUSID 22U +#define MDIO_PARAM_BUSID_MASK 0x7U +#define MDIO_PARAM_C45_SEL 21U +#define MDIO_PARAM_PHYID 16U +#define MDIO_PARAM_PHYID_MASK 0x1FU +#define MDIO_PARAM_DATA 0U +#define MDIO_PARAM_DATA_MASK 0xFFFFU +#define CMIC_MIIM_READ_DATA (PLAT_CMIC_MIIM_BASE + 0x240U) +#define MDIO_READ_DATA_MASK 0xffffU +#define CMIC_MIIM_ADDRESS (PLAT_CMIC_MIIM_BASE + 0x244U) +#define CMIC_MIIM_CTRL (PLAT_CMIC_MIIM_BASE + 0x248U) +#define MDIO_CTRL_WRITE_OP 0x1U +#define MDIO_CTRL_READ_OP 0x2U +#define CMIC_MIIM_STAT (PLAT_CMIC_MIIM_BASE + 0x24cU) +#define MDIO_STAT_DONE 1U + +int mdio_write(uint16_t busid, uint16_t phyid, uint32_t reg, uint16_t val); +int mdio_read(uint16_t busid, uint16_t phyid, uint32_t reg); +#endif /* MDIO_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/ocotp.h b/arm-trusted-firmware/include/drivers/brcm/ocotp.h new file mode 100644 index 0000000..830b3e4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/ocotp.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OCOTP_H +#define OCOTP_H + +#include + +struct otpc_map { + /* in words. */ + uint32_t otpc_row_size; + /* 128 bit row / 4 words support. */ + uint16_t data_r_offset[4]; + /* 128 bit row / 4 words support. */ + uint16_t data_w_offset[4]; + int word_size; + int stride; +}; + +int bcm_otpc_init(struct otpc_map *map); +int bcm_otpc_read(unsigned int offset, void *val, uint32_t bytes, + uint32_t ecc_flag); + +#endif /* OCOTP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/scp.h b/arm-trusted-firmware/include/drivers/brcm/scp.h new file mode 100644 index 0000000..7806314 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/scp.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SCP_H +#define SCP_H + +#include + +int download_scp_patch(void *image, unsigned int image_size); + +#endif /* SCP_H */ diff --git a/arm-trusted-firmware/include/drivers/brcm/sf.h b/arm-trusted-firmware/include/drivers/brcm/sf.h new file mode 100644 index 0000000..c32cbeb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/sf.h @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SF_H +#define SF_H + +#include +#include + +#ifdef SPI_DEBUG +#define SPI_DEBUG(fmt, ...) INFO(fmt, ##__VA_ARGS__) +#else +#define SPI_DEBUG(fmt, ...) +#endif + +#define SPI_FLASH_MAX_ID_LEN 6 + +#define CMD_WRSR 0x01 /* Write status register */ +#define CMD_PAGE_PROGRAM 0x02 +#define CMD_READ_NORMAL 0x03 +#define CMD_RDSR 0x05 +#define CMD_WRITE_ENABLE 0x06 +#define CMD_RDFSR 0x70 +#define CMD_READ_ID 0x9f +#define CMD_ERASE_4K 0x20 +#define CMD_ERASE_64K 0xd8 +#define ERASE_SIZE_64K (64 * 1024) + +/* Common status */ +#define STATUS_WIP BIT(0) + +struct spi_flash { + struct spi_slave *spi; + uint32_t size; + uint32_t page_size; + uint32_t sector_size; + uint32_t erase_size; + uint8_t erase_cmd; + uint8_t read_cmd; + uint8_t write_cmd; + uint8_t flags; +}; + +struct spi_flash_info { + const char *name; + + /* + * This array stores the ID bytes. + * The first three bytes are the JEDIC ID. + * JEDEC ID zero means "no ID" (mostly older chips). + */ + uint8_t id[SPI_FLASH_MAX_ID_LEN]; + uint8_t id_len; + + uint32_t sector_size; + uint32_t n_sectors; + uint16_t page_size; + + uint8_t flags; +}; + +/* Enum list - Full read commands */ +enum spi_read_cmds { + ARRAY_SLOW = BIT(0), + ARRAY_FAST = BIT(1), + DUAL_OUTPUT_FAST = BIT(2), + DUAL_IO_FAST = BIT(3), + QUAD_OUTPUT_FAST = BIT(4), + QUAD_IO_FAST = BIT(5), +}; + +/* sf param flags */ +enum spi_param_flag { + SECT_4K = BIT(0), + SECT_32K = BIT(1), + E_FSR = BIT(2), + SST_BP = BIT(3), + SST_WP = BIT(4), + WR_QPP = BIT(5), +}; + +int spi_flash_cmd_read(const uint8_t *cmd, size_t cmd_len, + void *data, size_t data_len); +int spi_flash_cmd(uint8_t cmd, void *response, size_t len); +int spi_flash_cmd_write(const uint8_t *cmd, size_t cmd_len, + const void *data, size_t data_len); +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/sotp.h b/arm-trusted-firmware/include/drivers/brcm/sotp.h new file mode 100644 index 0000000..a93d687 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/sotp.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOTP_H +#define SOTP_H + +#include +#include + +#include + +#define SOTP_ROW_NO_ECC 0 +#define SOTP_ROW_ECC 1 + +#define SOTP_STATUS_1 (SOTP_REGS_OTP_BASE + 0x001c) +#define SOTP_FAIL_BITS 0x18000000000 +#define SOTP_ECC_ERR_DETECT 0x8000000000000000 + +#define SOTP_REGS_SOTP_CHIP_STATES (SOTP_REGS_OTP_BASE + 0x0028) +#define SOTP_REGS_OTP_WR_LOCK (SOTP_REGS_OTP_BASE + 0x0038) + +#define SOTP_CHIP_STATES_MANU_DEBUG_MASK (1 << 8) +#define SOTP_DEVICE_SECURE_CFG0_OTP_ERASED_MASK (3 << 16) +#define SOTP_REGS_SOTP_CHIP_STATES_OTP_ERASED_MASK (1 << 16) + +#define SOTP_DEVICE_SECURE_CFG0_CID_MASK (3 << 2) +#define SOTP_DEVICE_SECURE_CFG0_AB_MASK (3 << 6) +#define SOTP_DEVICE_SECURE_CFG0_DEV_MASK (3 << 8) + +#define SOTP_BOOT_SOURCE_SHIFT 8 +/* bits 14 and 15 */ +#define SOTP_BOOT_SOURCE_ENABLE_MASK (0xC0 << SOTP_BOOT_SOURCE_SHIFT) +/* bits 8 to 13 */ +#define SOTP_BOOT_SOURCE_BITS0 (0x03 << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_BITS1 (0x0C << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_BITS2 (0x30 << SOTP_BOOT_SOURCE_SHIFT) +#define SOTP_BOOT_SOURCE_MASK (0x3F << SOTP_BOOT_SOURCE_SHIFT) + +#define SOTP_ATF_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG2_ROW +/* bits 28 and 29 */ +#define SOTP_SBL_MASK (3 << 28) +/* bits 30 and 31 */ +#define SOTP_ATF_NVCOUNTER_ENABLE_MASK ((uint64_t)3 << 30) +/* bits 32 and 33 */ +#define SOTP_ATF_WATCHDOG_ENABLE_MASK ((uint64_t)3 << 32) +/* bits 34 and 35 */ +#define SOTP_ATF_PLL_ON ((uint64_t)3 << 34) +/* bits 36 and 37 */ +#define SOTP_ATF_RESET_RETRY ((uint64_t)3 << 36) +/* bits 38 to 40 */ +#define SOTP_ATF_LOG_LEVEL_SHIFT 38 +#define SOTP_ATF_LOG_LEVEL ((uint64_t)7 << SOTP_ATF_LOG_LEVEL_SHIFT) + +#define SOTP_ATF2_CFG_ROW_ID SOTP_DEVICE_SECURE_CFG3_ROW +/* bits 16 and 17 */ +#define SOTP_ROMKEY_MASK (3 << 16) +/* bits 18 and 19 */ +#define SOTP_EC_EN_MASK (3 << 18) + +#define SOTP_ENC_DEV_TYPE_AB_DEV ((uint64_t)0x19999800000) +#define SOTP_ENC_DEV_TYPE_MASK ((uint64_t)0x1ffff800000) + +uint64_t sotp_mem_read(uint32_t offset, uint32_t sotp_add_ecc); +void sotp_mem_write(uint32_t addr, uint32_t sotp_add_ecc, uint64_t wdata); +int sotp_read_key(uint8_t *key, size_t keysize, int start_row, int end_row); +int sotp_key_erased(void); +uint32_t sotp_redundancy_reduction(uint32_t sotp_row_data); +#endif diff --git a/arm-trusted-firmware/include/drivers/brcm/spi.h b/arm-trusted-firmware/include/drivers/brcm/spi.h new file mode 100644 index 0000000..9d92d8c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/spi.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPI_H +#define SPI_H + +#include + +#define SPI_XFER_BEGIN (1 << 0) /* Assert CS before transfer */ +#define SPI_XFER_END (1 << 1) /* De-assert CS after transfer */ +#define SPI_XFER_QUAD (1 << 2) + +int spi_init(void); +int spi_claim_bus(void); +void spi_release_bus(void); +int spi_xfer(uint32_t bitlen, const void *dout, void *din, uint32_t flags); + +#endif /* _SPI_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/spi_flash.h b/arm-trusted-firmware/include/drivers/brcm/spi_flash.h new file mode 100644 index 0000000..bbaaa50 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/spi_flash.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPI_FLASH_H +#define SPI_FLASH_H + +#include + +int spi_flash_probe(struct spi_flash *flash); +int spi_flash_erase(struct spi_flash *flash, uint32_t offset, uint32_t len); +int spi_flash_write(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *buf); +int spi_flash_read(struct spi_flash *flash, uint32_t offset, + uint32_t len, void *data); +#endif /* _SPI_FLASH_H_ */ diff --git a/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h b/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h new file mode 100644 index 0000000..93dec7b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h @@ -0,0 +1,4809 @@ +/* + * Copyright (c) 2017 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef USBH_XHCI_REGS_H +#define USBH_XHCI_REGS_H + +#include +#include + +#define XHCI_LEN (8096U) + +#define XHC_CPLIVER_OFFSET 0x000U +#define XHC_SPARAMS1_OFFSET 0x004U +#define XHC_SPARAMS2_OFFSET 0x008U +#define XHC_SPARAMS3_OFFSET 0x00cU +#define XHC_CPARAMS1_OFFSET 0x010U +#define XHC_DBOFF_OFFSET 0x014U +#define XHC_RTOFF_OFFSET 0x018U +#define XHC_CPARAMS2_OFFSET 0x01cU +#define XHC_USBCMD_OFFSET 0x020U +#define XHC_USBSTS_OFFSET 0x024U +#define XHC_PAGESIZE_OFFSET 0x028U +#define XHC_DNCTRL_OFFSET 0x034U +#define XHC_CRCRL_OFFSET 0x038U +#define XHC_CRCRH_OFFSET 0x03cU +#define XHC_DCBAAPL_OFFSET 0x050U +#define XHC_DCBAAPH_OFFSET 0x054U +#define XHC_CONFIG_OFFSET 0x058U +#define XHC_PORTSC1_OFFSET 0x420U +#define XHC_PORTPM1_OFFSET 0x424U +#define XHC_PORTLC1_OFFSET 0x428U +#define XHC_PORTSC2_OFFSET 0x430U +#define XHC_PORTPM2_OFFSET 0x434U +#define XHC_PORTLC2_OFFSET 0x43cU +#define XHC_PORTSC3_OFFSET 0x440U +#define XHC_PORTPM3_OFFSET 0x444U +#define XHC_PORTLI3_OFFSET 0x44cU +#define XHC_MFINDEX_OFFSET 0x4a0U +#define XHC_IMAN0_OFFSET 0x4c0U +#define XHC_IMOD0_OFFSET 0x4c4U +#define XHC_ERSTSZ0_OFFSET 0x4c8U +#define XHC_ERSTBAL0_OFFSET 0x4d0U +#define XHC_ERSTBAH0_OFFSET 0x4d4U +#define XHC_ERDPL0_OFFSET 0x4d8U +#define XHC_ERDPH0_OFFSET 0x4dcU +#define XHC_IMAN1_OFFSET 0x4e0U +#define XHC_IMOD1_OFFSET 0x4e4U +#define XHC_ERSTSZ1_OFFSET 0x4e8U +#define XHC_ERSTBAL1_OFFSET 0x4f0U +#define XHC_ERSTBAH1_OFFSET 0x4f4U +#define XHC_ERDPL1_OFFSET 0x4f8U +#define XHC_ERDPH1_OFFSET 0x4fcU +#define XHC_DBLCMD_OFFSET 0x8c0U +#define XHC_DBLDVX1_OFFSET 0x8c4U +#define XHC_DBLDVX2_OFFSET 0x8c8U +#define XHC_DBLDVX3_OFFSET 0x8ccU +#define XHC_DBLDVX4_OFFSET 0x8d0U +#define XHC_DBLDVX5_OFFSET 0x8d4U +#define XHC_DBLDVX6_OFFSET 0x8d8U +#define XHC_DBLDVX7_OFFSET 0x8dcU +#define XHC_DBLDVX8_OFFSET 0x8e0U +#define XHC_DBLDVX9_OFFSET 0x8e4U +#define XHC_DBLDVX10_OFFSET 0x8e8U +#define XHC_DBLDVX11_OFFSET 0x8ecU +#define XHC_DBLDVX12_OFFSET 0x8f0U +#define XHC_DBLDVX13_OFFSET 0x8f4U +#define XHC_DBLDVX14_OFFSET 0x8f8U +#define XHC_DBLDVX15_OFFSET 0x8fcU +#define XHC_DBLDVX16_OFFSET 0x900U +#define XHC_ECHSPT3_OFFSET 0x940U +#define XHC_PNSTR3_OFFSET 0x944U +#define XHC_PSUM3_OFFSET 0x948U +#define XHC_PTSLTYP3_OFFSET 0x94cU +#define XHC_ECHSPT2_OFFSET 0x950U +#define XHC_PNSTR2_OFFSET 0x954U +#define XHC_PSUM2_OFFSET 0x958U +#define XHC_PTSLTYP2_OFFSET 0x95cU +#define XHC_ECHRSVP_OFFSET 0x960U +#define XHC_ECHRSVI_OFFSET 0x968U +#define XHC_ECHRSVM_OFFSET 0xae8U +#define XHC_ECHRSVD_OFFSET 0xaf8U +#define XHC_ECHRSVO_OFFSET 0xb38U +#define XHC_ECHCTT_OFFSET 0xbf0U +#define XHC_CTTMTS0_OFFSET 0xbf8U +#define XHC_CTTMTS1_OFFSET 0xbfcU +#define XHC_ECHBIU_OFFSET 0xc00U +#define XHC_BIUSPC_OFFSET 0xc04U +#define XHC_AXIWRA_OFFSET 0xc08U +#define XHC_AXIRDA_OFFSET 0xc0cU +#define XHC_AXILPM_OFFSET 0xc10U +#define XHC_AXIQOS_OFFSET 0xc14U +#define XHC_ECHCSR_OFFSET 0xc20U +#define XHC_CSRSPC_OFFSET 0xc24U +#define XHC_ECHAIU_OFFSET 0xc30U +#define XHC_AIUDMA_OFFSET 0xc34U +#define XHC_AIUFLA_OFFSET 0xc38U +#define XHC_AIUCFG_OFFSET 0xc3cU +#define XHC_ECHFSC_OFFSET 0xc40U +#define XHC_FSCPOC_OFFSET 0xc54U +#define XHC_FSCGOC_OFFSET 0xc58U +#define XHC_FSCNOC_OFFSET 0xc5cU +#define XHC_FSCAIC_OFFSET 0xc60U +#define XHC_FSCPIC_OFFSET 0xc64U +#define XHC_FSCGIC_OFFSET 0xc68U +#define XHC_FSCNIC_OFFSET 0xc6cU +#define XHC_ECHPRT_OFFSET 0xc70U +#define XHC_PRTHSC_OFFSET 0xc78U +#define XHC_PRTHSR_OFFSET 0xc7cU +#define XHC_ECHRHS_OFFSET 0xc80U +#define XHC_RHSDES_OFFSET 0xc84U +#define XHC_RHSHSC0_OFFSET 0xc90U +#define XHC_RHSHSR0_OFFSET 0xc94U +#define XHC_RHSHSC1_OFFSET 0xc98U +#define XHC_RHSHSR1_OFFSET 0xc9cU +#define XHC_RHSHSC2_OFFSET 0xca0U +#define XHC_RHSHSR2_OFFSET 0xca4U +#define XHC_RHSHSC3_OFFSET 0xca8U +#define XHC_RHSHSR3_OFFSET 0xcacU +#define XHC_ECHSSP_OFFSET 0xcb0U +#define XHC_SSPVER_OFFSET 0xcb4U +#define XHC_SSPMGN_OFFSET 0xcb8U +#define XHC_ECHFSC2_OFFSET 0xcc0U +#define XHC_FSC2POC_OFFSET 0xcd4U +#define XHC_FSC2GOC_OFFSET 0xcd8U +#define XHC_FSC2NOC_OFFSET 0xcdcU +#define XHC_FSC2AIC_OFFSET 0xce0U +#define XHC_FSC2PIC_OFFSET 0xce4U +#define XHC_FSC2GIC_OFFSET 0xce8U +#define XHC_FSC2NIC_OFFSET 0xcecU +#define XHC_ECHPRT2_OFFSET 0xcf0U +#define XHC_PRT2HSC_OFFSET 0xcf8U +#define XHC_PRT2HSR_OFFSET 0xcfcU +#define XHC_ECHRH2_OFFSET 0xd00U +#define XHC_RH2DES_OFFSET 0xd04U +#define XHC_RH2HSC0_OFFSET 0xd10U +#define XHC_RH2HSR0_OFFSET 0xd14U +#define XHC_RH2HSC1_OFFSET 0xd18U +#define XHC_RH2HSR1_OFFSET 0xd1cU +#define XHC_RH2HSC2_OFFSET 0xd20U +#define XHC_RH2HSR2_OFFSET 0xd24U +#define XHC_RH2HSC3_OFFSET 0xd28U +#define XHC_RH2HSR3_OFFSET 0xd2cU +#define XHC_ECHU2P_OFFSET 0xd30U +#define XHC_U2PVER_OFFSET 0xd34U +#define XHC_U2PMGN_OFFSET 0xd38U +#define XHC_ECHRSV2_OFFSET 0xd40U +#define XHC_ECHIRA_OFFSET 0xf90U +#define XHC_IRAADR_OFFSET 0xf98U +#define XHC_IRADAT_OFFSET 0xf9cU +#define XHC_ECHHST_OFFSET 0xfa0U +#define XHC_HSTDBG_OFFSET 0xfa4U +#define XHC_HSTNPL_OFFSET 0xfa8U +#define XHC_HSTNPH_OFFSET 0xfacU +#define XHC_ECHRBV_OFFSET 0xfb0U +#define XHC_RBVPDT_OFFSET 0xfb4U +#define XHC_RBVMGN_OFFSET 0xfbcU + +#define XHC_CPLIVER_BASE 0x000U +#define XHC_CPLIVER__IVH_L 31U +#define XHC_CPLIVER__IVH_R 24U +#define XHC_CPLIVER__IVH_WIDTH 8U +#define XHC_CPLIVER__IVH_RESETVALUE 0x01U +#define XHC_CPLIVER__IVL_L 23U +#define XHC_CPLIVER__IVL_R 16U +#define XHC_CPLIVER__IVL_WIDTH 8U +#define XHC_CPLIVER__IVL_RESETVALUE 0x10U +#define XHC_CPLIVER__reserved_L 15U +#define XHC_CPLIVER__reserved_R 8U +#define XHC_CPLIVER__reserved_WIDTH 8U +#define XHC_CPLIVER__reserved_RESETVALUE 0x00U +#define XHC_CPLIVER__CPL_L 7U +#define XHC_CPLIVER__CPL_R 0U +#define XHC_CPLIVER__CPL_WIDTH 8U +#define XHC_CPLIVER__CPL_RESETVALUE 0x00U +#define XHC_CPLIVER_WIDTH 32U +#define XHC_CPLIVER__WIDTH 32U +#define XHC_CPLIVER_ALL_L 31U +#define XHC_CPLIVER_ALL_R 0U +#define XHC_CPLIVER__ALL_L 31U +#define XHC_CPLIVER__ALL_R 0U +#define XHC_CPLIVER_DATAMASK 0xffffffffU +#define XHC_CPLIVER_RDWRMASK 0x00000000U +#define XHC_CPLIVER_RESETVALUE 0x01100000U + +#define XHC_SPARAMS1_OFFSET 0x004U +#define XHC_SPARAMS1_BASE 0x004U +#define XHC_SPARAMS1__NPTS_L 31U +#define XHC_SPARAMS1__NPTS_R 24U +#define XHC_SPARAMS1__NPTS_WIDTH 8U +#define XHC_SPARAMS1__NPTS_RESETVALUE 0x00U +#define XHC_SPARAMS1__reserved_L 23U +#define XHC_SPARAMS1__reserved_R 19U +#define XHC_SPARAMS1__reserved_WIDTH 5U +#define XHC_SPARAMS1__reserved_RESETVALUE 0x0U +#define XHC_SPARAMS1__MITS_L 18U +#define XHC_SPARAMS1__MITS_R 8U +#define XHC_SPARAMS1__MITS_WIDTH 11U +#define XHC_SPARAMS1__MITS_RESETVALUE 0x1U +#define XHC_SPARAMS1__MSLS_L 7U +#define XHC_SPARAMS1__MSLS_R 0U +#define XHC_SPARAMS1__MSLS_WIDTH 8U +#define XHC_SPARAMS1__MSLS_RESETVALUE 0x00U +#define XHC_SPARAMS1_WIDTH 32U +#define XHC_SPARAMS1__WIDTH 32U +#define XHC_SPARAMS1_ALL_L 31U +#define XHC_SPARAMS1_ALL_R 0U +#define XHC_SPARAMS1__ALL_L 31U +#define XHC_SPARAMS1__ALL_R 0U +#define XHC_SPARAMS1_DATAMASK 0xffffffffU +#define XHC_SPARAMS1_RDWRMASK 0x00000000U +#define XHC_SPARAMS1_RESETVALUE 0x00000100U + +#define XHC_SPARAMS2_OFFSET 0x008U +#define XHC_SPARAMS2_BASE 0x008U +#define XHC_SPARAMS2__MSPBSL_L 31U +#define XHC_SPARAMS2__MSPBSL_R 27U +#define XHC_SPARAMS2__MSPBSL_WIDTH 5U +#define XHC_SPARAMS2__MSPBSL_RESETVALUE 0x0U +#define XHC_SPARAMS2__SPR 26U +#define XHC_SPARAMS2__SPR_L 26U +#define XHC_SPARAMS2__SPR_R 26U +#define XHC_SPARAMS2__SPR_WIDTH 1U +#define XHC_SPARAMS2__SPR_RESETVALUE 0x1U +#define XHC_SPARAMS2__MSPBSH_L 25U +#define XHC_SPARAMS2__MSPBSH_R 21U +#define XHC_SPARAMS2__MSPBSH_WIDTH 5U +#define XHC_SPARAMS2__MSPBSH_RESETVALUE 0x0U +#define XHC_SPARAMS2__reserved_L 20U +#define XHC_SPARAMS2__reserved_R 8U +#define XHC_SPARAMS2__reserved_WIDTH 13U +#define XHC_SPARAMS2__reserved_RESETVALUE 0x0U +#define XHC_SPARAMS2__MERST_L 7U +#define XHC_SPARAMS2__MERST_R 4U +#define XHC_SPARAMS2__MERST_WIDTH 4U +#define XHC_SPARAMS2__MERST_RESETVALUE 0x0U +#define XHC_SPARAMS2__IST_L 3U +#define XHC_SPARAMS2__IST_R 0U +#define XHC_SPARAMS2__IST_WIDTH 4U +#define XHC_SPARAMS2__IST_RESETVALUE 0x0U +#define XHC_SPARAMS2_WIDTH 32U +#define XHC_SPARAMS2__WIDTH 32U +#define XHC_SPARAMS2_ALL_L 31U +#define XHC_SPARAMS2_ALL_R 0U +#define XHC_SPARAMS2__ALL_L 31U +#define XHC_SPARAMS2__ALL_R 0U +#define XHC_SPARAMS2_DATAMASK 0xffffffffU +#define XHC_SPARAMS2_RDWRMASK 0x00000000U +#define XHC_SPARAMS2_RESETVALUE 0x04000000U + +#define XHC_SPARAMS3_OFFSET 0x00cU +#define XHC_SPARAMS3_BASE 0x00cU +#define XHC_SPARAMS3__U2L_L 31U +#define XHC_SPARAMS3__U2L_R 16U +#define XHC_SPARAMS3__U2L_WIDTH 16U +#define XHC_SPARAMS3__U2L_RESETVALUE 0x0000U +#define XHC_SPARAMS3__reserved_L 15U +#define XHC_SPARAMS3__reserved_R 8U +#define XHC_SPARAMS3__reserved_WIDTH 8U +#define XHC_SPARAMS3__reserved_RESETVALUE 0x00U +#define XHC_SPARAMS3__U1L_L 7U +#define XHC_SPARAMS3__U1L_R 0U +#define XHC_SPARAMS3__U1L_WIDTH 8U +#define XHC_SPARAMS3__U1L_RESETVALUE 0x00U +#define XHC_SPARAMS3_WIDTH 32U +#define XHC_SPARAMS3__WIDTH 32U +#define XHC_SPARAMS3_ALL_L 31U +#define XHC_SPARAMS3_ALL_R 0U +#define XHC_SPARAMS3__ALL_L 31U +#define XHC_SPARAMS3__ALL_R 0U +#define XHC_SPARAMS3_DATAMASK 0xffffffffU +#define XHC_SPARAMS3_RDWRMASK 0x00000000U +#define XHC_SPARAMS3_RESETVALUE 0x00000000U + +#define XHC_CPARAMS1_OFFSET 0x010U +#define XHC_CPARAMS1_BASE 0x010U +#define XHC_CPARAMS1__XECP_L 31U +#define XHC_CPARAMS1__XECP_R 16U +#define XHC_CPARAMS1__XECP_WIDTH 16U +#define XHC_CPARAMS1__XECP_RESETVALUE 0x0000U +#define XHC_CPARAMS1__MPSA_L 15U +#define XHC_CPARAMS1__MPSA_R 12U +#define XHC_CPARAMS1__MPSA_WIDTH 4U +#define XHC_CPARAMS1__MPSA_RESETVALUE 0x0U +#define XHC_CPARAMS1__CFC 11U +#define XHC_CPARAMS1__CFC_L 11U +#define XHC_CPARAMS1__CFC_R 11U +#define XHC_CPARAMS1__CFC_WIDTH 1U +#define XHC_CPARAMS1__CFC_RESETVALUE 0x0U +#define XHC_CPARAMS1__SEC 10U +#define XHC_CPARAMS1__SEC_L 10U +#define XHC_CPARAMS1__SEC_R 10U +#define XHC_CPARAMS1__SEC_WIDTH 1U +#define XHC_CPARAMS1__SEC_RESETVALUE 0x0U +#define XHC_CPARAMS1__SPC 9U +#define XHC_CPARAMS1__SPC_L 9U +#define XHC_CPARAMS1__SPC_R 9U +#define XHC_CPARAMS1__SPC_WIDTH 1U +#define XHC_CPARAMS1__SPC_RESETVALUE 0x0U +#define XHC_CPARAMS1__PAE 8U +#define XHC_CPARAMS1__PAE_L 8U +#define XHC_CPARAMS1__PAE_R 8U +#define XHC_CPARAMS1__PAE_WIDTH 1U +#define XHC_CPARAMS1__PAE_RESETVALUE 0x1U +#define XHC_CPARAMS1__NSS 7U +#define XHC_CPARAMS1__NSS_L 7U +#define XHC_CPARAMS1__NSS_R 7U +#define XHC_CPARAMS1__NSS_WIDTH 1U +#define XHC_CPARAMS1__NSS_RESETVALUE 0x0U +#define XHC_CPARAMS1__LTC 6U +#define XHC_CPARAMS1__LTC_L 6U +#define XHC_CPARAMS1__LTC_R 6U +#define XHC_CPARAMS1__LTC_WIDTH 1U +#define XHC_CPARAMS1__LTC_RESETVALUE 0x1U +#define XHC_CPARAMS1__LRC 5U +#define XHC_CPARAMS1__LRC_L 5U +#define XHC_CPARAMS1__LRC_R 5U +#define XHC_CPARAMS1__LRC_WIDTH 1U +#define XHC_CPARAMS1__LRC_RESETVALUE 0x0U +#define XHC_CPARAMS1__PIND 4U +#define XHC_CPARAMS1__PIND_L 4U +#define XHC_CPARAMS1__PIND_R 4U +#define XHC_CPARAMS1__PIND_WIDTH 1U +#define XHC_CPARAMS1__PIND_RESETVALUE 0x0U + +#define XHC_CPARAMS1__PPC_L 3U +#define XHC_CPARAMS1__PPC_R 3U +#define XHC_CPARAMS1__PPC_WIDTH 1U +#define XHC_CPARAMS1__PPC_RESETVALUE 0x0U +#define XHC_CPARAMS1__CSZ 2U +#define XHC_CPARAMS1__CSZ_L 2U +#define XHC_CPARAMS1__CSZ_R 2U +#define XHC_CPARAMS1__CSZ_WIDTH 1U +#define XHC_CPARAMS1__CSZ_RESETVALUE 0x1U +#define XHC_CPARAMS1__BNC 1U +#define XHC_CPARAMS1__BNC_L 1U +#define XHC_CPARAMS1__BNC_R 1U +#define XHC_CPARAMS1__BNC_WIDTH 1U +#define XHC_CPARAMS1__BNC_RESETVALUE 0x0U +#define XHC_CPARAMS1__AC64 0U +#define XHC_CPARAMS1__AC64_L 0U +#define XHC_CPARAMS1__AC64_R 0U +#define XHC_CPARAMS1__AC64_WIDTH 1U +#define XHC_CPARAMS1__AC64_RESETVALUE 0x0U +#define XHC_CPARAMS1_WIDTH 32U +#define XHC_CPARAMS1__WIDTH 32U +#define XHC_CPARAMS1_ALL_L 31U +#define XHC_CPARAMS1_ALL_R 0U +#define XHC_CPARAMS1__ALL_L 31U +#define XHC_CPARAMS1__ALL_R 0U +#define XHC_CPARAMS1_DATAMASK 0xffffffffU +#define XHC_CPARAMS1_RDWRMASK 0x00000000U +#define XHC_CPARAMS1_RESETVALUE 0x00000144U + +#define XHC_DBOFF_OFFSET 0x014U +#define XHC_DBOFF_BASE 0x014U +#define XHC_DBOFF__DBO_L 15U +#define XHC_DBOFF__DBO_R 2U +#define XHC_DBOFF__DBO_WIDTH 14U +#define XHC_DBOFF__DBO_RESETVALUE 0x0U +#define XHC_DBOFF__reserved_L 1U +#define XHC_DBOFF__reserved_R 0U +#define XHC_DBOFF__reserved_WIDTH 2U +#define XHC_DBOFF__reserved_RESETVALUE 0x0U +#define XHC_DBOFF__RESERVED_L 31U +#define XHC_DBOFF__RESERVED_R 16U +#define XHC_DBOFF_WIDTH 16U +#define XHC_DBOFF__WIDTH 16U +#define XHC_DBOFF_ALL_L 15U +#define XHC_DBOFF_ALL_R 0U +#define XHC_DBOFF__ALL_L 15U +#define XHC_DBOFF__ALL_R 0U +#define XHC_DBOFF_DATAMASK 0x0000ffffU +#define XHC_DBOFF_RDWRMASK 0xffff0000U +#define XHC_DBOFF_RESETVALUE 0x0000U + +#define XHC_RTOFF_OFFSET 0x018U +#define XHC_RTOFF_BASE 0x018U +#define XHC_RTOFF__RTO_L 15U +#define XHC_RTOFF__RTO_R 5U +#define XHC_RTOFF__RTO_WIDTH 11U +#define XHC_RTOFF__RTO_RESETVALUE 0x0U +#define XHC_RTOFF__reserved_L 4U +#define XHC_RTOFF__reserved_R 0U +#define XHC_RTOFF__reserved_WIDTH 5U +#define XHC_RTOFF__reserved_RESETVALUE 0x0U +#define XHC_RTOFF__RESERVED_L 31U +#define XHC_RTOFF__RESERVED_R 16U +#define XHC_RTOFF_WIDTH 16U +#define XHC_RTOFF__WIDTH 16U +#define XHC_RTOFF_ALL_L 15U +#define XHC_RTOFF_ALL_R 0U +#define XHC_RTOFF__ALL_L 15U +#define XHC_RTOFF__ALL_R 0U +#define XHC_RTOFF_DATAMASK 0x0000ffffU +#define XHC_RTOFF_RDWRMASK 0xffff0000U +#define XHC_RTOFF_RESETVALUE 0x0000U + +#define XHC_CPARAMS2_OFFSET 0x01cU +#define XHC_CPARAMS2_BASE 0x01cU +#define XHC_CPARAMS2__reserved_L 31U +#define XHC_CPARAMS2__reserved_R 6U +#define XHC_CPARAMS2__reserved_WIDTH 26U +#define XHC_CPARAMS2__reserved_RESETVALUE 0x0U +#define XHC_CPARAMS2__CIC 5U +#define XHC_CPARAMS2__CIC_L 5U +#define XHC_CPARAMS2__CIC_R 5U +#define XHC_CPARAMS2__CIC_WIDTH 1U +#define XHC_CPARAMS2__CIC_RESETVALUE 0x0U +#define XHC_CPARAMS2__LEC 4U +#define XHC_CPARAMS2__LEC_L 4U +#define XHC_CPARAMS2__LEC_R 4U +#define XHC_CPARAMS2__LEC_WIDTH 1U +#define XHC_CPARAMS2__LEC_RESETVALUE 0x0U +#define XHC_CPARAMS2__CTC 3U +#define XHC_CPARAMS2__CTC_L 3U +#define XHC_CPARAMS2__CTC_R 3U +#define XHC_CPARAMS2__CTC_WIDTH 1U +#define XHC_CPARAMS2__CTC_RESETVALUE 0x0U +#define XHC_CPARAMS2__FSC 2U +#define XHC_CPARAMS2__FSC_L 2U +#define XHC_CPARAMS2__FSC_R 2U +#define XHC_CPARAMS2__FSC_WIDTH 1U +#define XHC_CPARAMS2__FSC_RESETVALUE 0x0U +#define XHC_CPARAMS2__CMC 1U +#define XHC_CPARAMS2__CMC_L 1U +#define XHC_CPARAMS2__CMC_R 1U +#define XHC_CPARAMS2__CMC_WIDTH 1U +#define XHC_CPARAMS2__CMC_RESETVALUE 0x0U +#define XHC_CPARAMS2__U3C 0U +#define XHC_CPARAMS2__U3C_L 0U +#define XHC_CPARAMS2__U3C_R 0U +#define XHC_CPARAMS2__U3C_WIDTH 1U +#define XHC_CPARAMS2__U3C_RESETVALUE 0x0U +#define XHC_CPARAMS2_WIDTH 32U +#define XHC_CPARAMS2__WIDTH 32U +#define XHC_CPARAMS2_ALL_L 31U +#define XHC_CPARAMS2_ALL_R 0U +#define XHC_CPARAMS2__ALL_L 31U +#define XHC_CPARAMS2__ALL_R 0U +#define XHC_CPARAMS2_DATAMASK 0xffffffffU +#define XHC_CPARAMS2_RDWRMASK 0x00000000U +#define XHC_CPARAMS2_RESETVALUE 0x00000000U + +#define XHC_USBCMD_OFFSET 0x020U +#define XHC_USBCMD_BASE 0x020U +#define XHC_USBCMD__CME 13U +#define XHC_USBCMD__CME_L 13U +#define XHC_USBCMD__CME_R 13U +#define XHC_USBCMD__CME_WIDTH 1U +#define XHC_USBCMD__CME_RESETVALUE 0x0U +#define XHC_USBCMD__SPE 12U +#define XHC_USBCMD__SPE_L 12U +#define XHC_USBCMD__SPE_R 12U +#define XHC_USBCMD__SPE_WIDTH 1U +#define XHC_USBCMD__SPE_RESETVALUE 0x0U +#define XHC_USBCMD__EU3S 11U +#define XHC_USBCMD__EU3S_L 11U +#define XHC_USBCMD__EU3S_R 11U +#define XHC_USBCMD__EU3S_WIDTH 1U +#define XHC_USBCMD__EU3S_RESETVALUE 0x0U +#define XHC_USBCMD__EWE 10U +#define XHC_USBCMD__EWE_L 10U +#define XHC_USBCMD__EWE_R 10U +#define XHC_USBCMD__EWE_WIDTH 1U +#define XHC_USBCMD__EWE_RESETVALUE 0x0U +#define XHC_USBCMD__CRS 9U +#define XHC_USBCMD__CRS_L 9U +#define XHC_USBCMD__CRS_R 9U +#define XHC_USBCMD__CRS_WIDTH 1U +#define XHC_USBCMD__CRS_RESETVALUE 0x0U +#define XHC_USBCMD__CSS 8U +#define XHC_USBCMD__CSS_L 8U +#define XHC_USBCMD__CSS_R 8U +#define XHC_USBCMD__CSS_WIDTH 1U +#define XHC_USBCMD__CSS_RESETVALUE 0x0U +#define XHC_USBCMD__LRST 7U +#define XHC_USBCMD__LRST_L 7U +#define XHC_USBCMD__LRST_R 7U +#define XHC_USBCMD__LRST_WIDTH 1U +#define XHC_USBCMD__LRST_RESETVALUE 0x0U +#define XHC_USBCMD__reserved_L 6U +#define XHC_USBCMD__reserved_R 4U +#define XHC_USBCMD__reserved_WIDTH 3U +#define XHC_USBCMD__reserved_RESETVALUE 0x0U +#define XHC_USBCMD__HSEE 3U +#define XHC_USBCMD__HSEE_L 3U +#define XHC_USBCMD__HSEE_R 3U +#define XHC_USBCMD__HSEE_WIDTH 1U +#define XHC_USBCMD__HSEE_RESETVALUE 0x0U +#define XHC_USBCMD__INTE 2U +#define XHC_USBCMD__INTE_L 2U +#define XHC_USBCMD__INTE_R 2U +#define XHC_USBCMD__INTE_WIDTH 1U +#define XHC_USBCMD__INTE_RESETVALUE 0x0U +#define XHC_USBCMD__RST 1U +#define XHC_USBCMD__RST_L 1U +#define XHC_USBCMD__RST_R 1U +#define XHC_USBCMD__RST_WIDTH 1U +#define XHC_USBCMD__RST_RESETVALUE 0x0U +#define XHC_USBCMD__RS 0U +#define XHC_USBCMD__RS_L 0U +#define XHC_USBCMD__RS_R 0U +#define XHC_USBCMD__RS_WIDTH 1U +#define XHC_USBCMD__RS_RESETVALUE 0x0U +#define XHC_USBCMD__RESERVED_L 31U +#define XHC_USBCMD__RESERVED_R 14U +#define XHC_USBCMD_WIDTH 14U +#define XHC_USBCMD__WIDTH 14U +#define XHC_USBCMD_ALL_L 13U +#define XHC_USBCMD_ALL_R 0U +#define XHC_USBCMD__ALL_L 13U +#define XHC_USBCMD__ALL_R 0U +#define XHC_USBCMD_DATAMASK 0x00003fffU +#define XHC_USBCMD_RDWRMASK 0xffffc000U +#define XHC_USBCMD_RESETVALUE 0x0000U + +#define XHC_USBSTS_OFFSET 0x024U +#define XHC_USBSTS_BASE 0x024U +#define XHC_USBSTS__CE 12U +#define XHC_USBSTS__CE_L 12U +#define XHC_USBSTS__CE_R 12U +#define XHC_USBSTS__CE_WIDTH 1U +#define XHC_USBSTS__CE_RESETVALUE 0x0U +#define XHC_USBSTS__CNR 11U +#define XHC_USBSTS__CNR_L 11U +#define XHC_USBSTS__CNR_R 11U +#define XHC_USBSTS__CNR_WIDTH 1U +#define XHC_USBSTS__CNR_RESETVALUE 0x1U + +#define XHC_USBSTS__SRE 10U +#define XHC_USBSTS__SRE_L 10U +#define XHC_USBSTS__SRE_R 10U +#define XHC_USBSTS__SRE_WIDTH 1U +#define XHC_USBSTS__SRE_RESETVALUE 0x0U +#define XHC_USBSTS__RSS 9U +#define XHC_USBSTS__RSS_L 9U +#define XHC_USBSTS__RSS_R 9U +#define XHC_USBSTS__RSS_WIDTH 1U +#define XHC_USBSTS__RSS_RESETVALUE 0x0U +#define XHC_USBSTS__SSS 8U +#define XHC_USBSTS__SSS_L 8U +#define XHC_USBSTS__SSS_R 8U +#define XHC_USBSTS__SSS_WIDTH 1U +#define XHC_USBSTS__SSS_RESETVALUE 0x0U +#define XHC_USBSTS__PCD 4U +#define XHC_USBSTS__PCD_L 4U +#define XHC_USBSTS__PCD_R 4U +#define XHC_USBSTS__PCD_WIDTH 1U +#define XHC_USBSTS__PCD_RESETVALUE 0x0U +#define XHC_USBSTS__EINT 3U +#define XHC_USBSTS__EINT_L 3U +#define XHC_USBSTS__EINT_R 3U +#define XHC_USBSTS__EINT_WIDTH 1U +#define XHC_USBSTS__EINT_RESETVALUE 0x0U +#define XHC_USBSTS__HSE 2U +#define XHC_USBSTS__HSE_L 2U +#define XHC_USBSTS__HSE_R 2U +#define XHC_USBSTS__HSE_WIDTH 1U +#define XHC_USBSTS__HSE_RESETVALUE 0x0U +#define XHC_USBSTS__reserved 1U +#define XHC_USBSTS__reserved_L 1U +#define XHC_USBSTS__reserved_R 1U +#define XHC_USBSTS__reserved_WIDTH 1U +#define XHC_USBSTS__reserved_RESETVALUE 0x0U + +#define XHC_USBSTS__CH_L 0U +#define XHC_USBSTS__CH_R 0U +#define XHC_USBSTS__CH_WIDTH 1U +#define XHC_USBSTS__CH_RESETVALUE 0x1U +#define XHC_USBSTS__RESERVED_L 31U +#define XHC_USBSTS__RESERVED_R 13U +#define XHC_USBSTS_WIDTH 13U +#define XHC_USBSTS__WIDTH 13U +#define XHC_USBSTS_ALL_L 12U +#define XHC_USBSTS_ALL_R 0U +#define XHC_USBSTS__ALL_L 12U +#define XHC_USBSTS__ALL_R 0U +#define XHC_USBSTS_DATAMASK 0x00001f1fU +#define XHC_USBSTS_RDWRMASK 0xffffe0e0U +#define XHC_USBSTS_RESETVALUE 0x0801U + +#define XHC_PAGESIZE_OFFSET 0x028U +#define XHC_PAGESIZE_BASE 0x028U +#define XHC_PAGESIZE__reserved_L 31U +#define XHC_PAGESIZE__reserved_R 16U +#define XHC_PAGESIZE__reserved_WIDTH 16U +#define XHC_PAGESIZE__reserved_RESETVALUE 0x0000U +#define XHC_PAGESIZE__PS_L 15U +#define XHC_PAGESIZE__PS_R 0U +#define XHC_PAGESIZE__PS_WIDTH 16U +#define XHC_PAGESIZE__PS_RESETVALUE 0x0000U +#define XHC_PAGESIZE_WIDTH 32U +#define XHC_PAGESIZE__WIDTH 32U +#define XHC_PAGESIZE_ALL_L 31U +#define XHC_PAGESIZE_ALL_R 0U +#define XHC_PAGESIZE__ALL_L 31U +#define XHC_PAGESIZE__ALL_R 0U +#define XHC_PAGESIZE_DATAMASK 0xffffffffU +#define XHC_PAGESIZE_RDWRMASK 0x00000000U +#define XHC_PAGESIZE_RESETVALUE 0x00000000U + +#define XHC_DNCTRL_OFFSET 0x034U +#define XHC_DNCTRL_BASE 0x034U +#define XHC_DNCTRL__reserved_L 31U +#define XHC_DNCTRL__reserved_R 16U +#define XHC_DNCTRL__reserved_WIDTH 16U +#define XHC_DNCTRL__reserved_RESETVALUE 0x0000U +#define XHC_DNCTRL__DNE_L 15U +#define XHC_DNCTRL__DNE_R 0U +#define XHC_DNCTRL__DNE_WIDTH 16U +#define XHC_DNCTRL__DNE_RESETVALUE 0x0000U +#define XHC_DNCTRL_WIDTH 32U +#define XHC_DNCTRL__WIDTH 32U +#define XHC_DNCTRL_ALL_L 31U +#define XHC_DNCTRL_ALL_R 0U +#define XHC_DNCTRL__ALL_L 31U +#define XHC_DNCTRL__ALL_R 0U +#define XHC_DNCTRL_DATAMASK 0xffffffffU +#define XHC_DNCTRL_RDWRMASK 0x00000000U +#define XHC_DNCTRL_RESETVALUE 0x00000000U + +#define XHC_CRCRL_OFFSET 0x038U +#define XHC_CRCRL_BASE 0x038U +#define XHC_CRCRL__CRPL_L 31U +#define XHC_CRCRL__CRPL_R 6U +#define XHC_CRCRL__CRPL_WIDTH 26U +#define XHC_CRCRL__CRPL_RESETVALUE 0x0U +#define XHC_CRCRL__reserved_L 5U +#define XHC_CRCRL__reserved_R 4U +#define XHC_CRCRL__reserved_WIDTH 2U +#define XHC_CRCRL__reserved_RESETVALUE 0x0U +#define XHC_CRCRL__CRR 3U +#define XHC_CRCRL__CRR_L 3U +#define XHC_CRCRL__CRR_R 3U +#define XHC_CRCRL__CRR_WIDTH 1U +#define XHC_CRCRL__CRR_RESETVALUE 0x0U +#define XHC_CRCRL__CA 2U +#define XHC_CRCRL__CA_L 2U +#define XHC_CRCRL__CA_R 2U +#define XHC_CRCRL__CA_WIDTH 1U +#define XHC_CRCRL__CA_RESETVALUE 0x0U +#define XHC_CRCRL__CS 1U +#define XHC_CRCRL__CS_L 1U +#define XHC_CRCRL__CS_R 1U +#define XHC_CRCRL__CS_WIDTH 1U +#define XHC_CRCRL__CS_RESETVALUE 0x0U +#define XHC_CRCRL__RCS 0U +#define XHC_CRCRL__RCS_L 0U +#define XHC_CRCRL__RCS_R 0U +#define XHC_CRCRL__RCS_WIDTH 1U +#define XHC_CRCRL__RCS_RESETVALUE 0x0U +#define XHC_CRCRL_WIDTH 32U +#define XHC_CRCRL__WIDTH 32U +#define XHC_CRCRL_ALL_L 31U +#define XHC_CRCRL_ALL_R 0U +#define XHC_CRCRL__ALL_L 31U +#define XHC_CRCRL__ALL_R 0U +#define XHC_CRCRL_DATAMASK 0xffffffffU +#define XHC_CRCRL_RDWRMASK 0x00000000U +#define XHC_CRCRL_RESETVALUE 0x00000000U + +#define XHC_CRCRH_OFFSET 0x03cU +#define XHC_CRCRH_BASE 0x03cU +#define XHC_CRCRH__CRPH_L 31U +#define XHC_CRCRH__CRPH_R 0U +#define XHC_CRCRH__CRPH_WIDTH 32U +#define XHC_CRCRH__CRPH_RESETVALUE 0x00000000U +#define XHC_CRCRH_WIDTH 32U +#define XHC_CRCRH__WIDTH 32U +#define XHC_CRCRH_ALL_L 31U +#define XHC_CRCRH_ALL_R 0U +#define XHC_CRCRH__ALL_L 31U +#define XHC_CRCRH__ALL_R 0U +#define XHC_CRCRH_DATAMASK 0xffffffffU +#define XHC_CRCRH_RDWRMASK 0x00000000U +#define XHC_CRCRH_RESETVALUE 0x00000000U + +#define XHC_DCBAAPL_OFFSET 0x050U +#define XHC_DCBAAPL_BASE 0x050U +#define XHC_DCBAAPL__DCAL_L 31U +#define XHC_DCBAAPL__DCAL_R 6U +#define XHC_DCBAAPL__DCAL_WIDTH 26U +#define XHC_DCBAAPL__DCAL_RESETVALUE 0x0U + +#define XHC_DCBAAPL__reserved_L 5U +#define XHC_DCBAAPL__reserved_R 0U +#define XHC_DCBAAPL__reserved_WIDTH 6U +#define XHC_DCBAAPL__reserved_RESETVALUE 0x0U +#define XHC_DCBAAPL_WIDTH 32U +#define XHC_DCBAAPL__WIDTH 32U +#define XHC_DCBAAPL_ALL_L 31U +#define XHC_DCBAAPL_ALL_R 0U +#define XHC_DCBAAPL__ALL_L 31U +#define XHC_DCBAAPL__ALL_R 0U +#define XHC_DCBAAPL_DATAMASK 0xffffffffU +#define XHC_DCBAAPL_RDWRMASK 0x00000000U +#define XHC_DCBAAPL_RESETVALUE 0x00000000U + +#define XHC_DCBAAPH_OFFSET 0x054U +#define XHC_DCBAAPH_BASE 0x054U +#define XHC_DCBAAPH__DCAH_L 31U +#define XHC_DCBAAPH__DCAH_R 0U +#define XHC_DCBAAPH__DCAH_WIDTH 32U +#define XHC_DCBAAPH__DCAH_RESETVALUE 0x00000000U +#define XHC_DCBAAPH_WIDTH 32U +#define XHC_DCBAAPH__WIDTH 32U +#define XHC_DCBAAPH_ALL_L 31U +#define XHC_DCBAAPH_ALL_R 0U +#define XHC_DCBAAPH__ALL_L 31U +#define XHC_DCBAAPH__ALL_R 0U +#define XHC_DCBAAPH_DATAMASK 0xffffffffU +#define XHC_DCBAAPH_RDWRMASK 0x00000000U +#define XHC_DCBAAPH_RESETVALUE 0x00000000U + +#define XHC_CONFIG_OFFSET 0x058U +#define XHC_CONFIG_BASE 0x058U +#define XHC_CONFIG__reserved_L 31U +#define XHC_CONFIG__reserved_R 10U +#define XHC_CONFIG__reserved_WIDTH 22U +#define XHC_CONFIG__reserved_RESETVALUE 0x0U +#define XHC_CONFIG__CIE 9U +#define XHC_CONFIG__CIE_L 9U +#define XHC_CONFIG__CIE_R 9U +#define XHC_CONFIG__CIE_WIDTH 1U +#define XHC_CONFIG__CIE_RESETVALUE 0x0U +#define XHC_CONFIG__U3E 8U +#define XHC_CONFIG__U3E_L 8U +#define XHC_CONFIG__U3E_R 8U +#define XHC_CONFIG__U3E_WIDTH 1U +#define XHC_CONFIG__U3E_RESETVALUE 0x0U +#define XHC_CONFIG__MSE_L 7U +#define XHC_CONFIG__MSE_R 0U +#define XHC_CONFIG__MSE_WIDTH 8U +#define XHC_CONFIG__MSE_RESETVALUE 0x00U +#define XHC_CONFIG_WIDTH 32U +#define XHC_CONFIG__WIDTH 32U +#define XHC_CONFIG_ALL_L 31U +#define XHC_CONFIG_ALL_R 0U +#define XHC_CONFIG__ALL_L 31U +#define XHC_CONFIG__ALL_R 0U +#define XHC_CONFIG_DATAMASK 0xffffffffU +#define XHC_CONFIG_RDWRMASK 0x00000000U +#define XHC_CONFIG_RESETVALUE 0x00000000U + +#define XHC_PORTSC1_OFFSET 0x420U +#define XHC_PORTSC1_BASE 0x420U + +#define XHC_PORTSC1__WPR_L 31U +#define XHC_PORTSC1__WPR_R 31U +#define XHC_PORTSC1__WPR_WIDTH 1U +#define XHC_PORTSC1__WPR_RESETVALUE 0x0U + +#define XHC_PORTSC1__DNR_L 30U +#define XHC_PORTSC1__DNR_R 30U +#define XHC_PORTSC1__DNR_WIDTH 1U +#define XHC_PORTSC1__DNR_RESETVALUE 0x0U + +#define XHC_PORTSC1__WOE_L 27U +#define XHC_PORTSC1__WOE_R 27U +#define XHC_PORTSC1__WOE_WIDTH 1U +#define XHC_PORTSC1__WOE_RESETVALUE 0x0U + +#define XHC_PORTSC1__WDE_L 26U +#define XHC_PORTSC1__WDE_R 26U +#define XHC_PORTSC1__WDE_WIDTH 1U +#define XHC_PORTSC1__WDE_RESETVALUE 0x0U + +#define XHC_PORTSC1__WCE_L 25U +#define XHC_PORTSC1__WCE_R 25U +#define XHC_PORTSC1__WCE_WIDTH 1U +#define XHC_PORTSC1__WCE_RESETVALUE 0x0U + +#define XHC_PORTSC1__CAS_L 24U +#define XHC_PORTSC1__CAS_R 24U +#define XHC_PORTSC1__CAS_WIDTH 1U +#define XHC_PORTSC1__CAS_RESETVALUE 0x0U + +#define XHC_PORTSC1__CEC_L 23U +#define XHC_PORTSC1__CEC_R 23U +#define XHC_PORTSC1__CEC_WIDTH 1U +#define XHC_PORTSC1__CEC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PLC_L 22U +#define XHC_PORTSC1__PLC_R 22U +#define XHC_PORTSC1__PLC_WIDTH 1U +#define XHC_PORTSC1__PLC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PRC_L 21U +#define XHC_PORTSC1__PRC_R 21U +#define XHC_PORTSC1__PRC_WIDTH 1U +#define XHC_PORTSC1__PRC_RESETVALUE 0x0U + +#define XHC_PORTSC1__OCC_L 20U +#define XHC_PORTSC1__OCC_R 20U +#define XHC_PORTSC1__OCC_WIDTH 1U +#define XHC_PORTSC1__OCC_RESETVALUE 0x0U + +#define XHC_PORTSC1__WRC_L 19U +#define XHC_PORTSC1__WRC_R 19U +#define XHC_PORTSC1__WRC_WIDTH 1U +#define XHC_PORTSC1__WRC_RESETVALUE 0x0U + +#define XHC_PORTSC1__PEC_L 18U +#define XHC_PORTSC1__PEC_R 18U +#define XHC_PORTSC1__PEC_WIDTH 1U +#define XHC_PORTSC1__PEC_RESETVALUE 0x0U + +#define XHC_PORTSC1__CSC_L 17U +#define XHC_PORTSC1__CSC_R 17U +#define XHC_PORTSC1__CSC_WIDTH 1U +#define XHC_PORTSC1__CSC_RESETVALUE 0x0U + +#define XHC_PORTSC1__LWS_L 16U +#define XHC_PORTSC1__LWS_R 16U +#define XHC_PORTSC1__LWS_WIDTH 1U +#define XHC_PORTSC1__LWS_RESETVALUE 0x0U +#define XHC_PORTSC1__PIC_L 15U +#define XHC_PORTSC1__PIC_R 14U +#define XHC_PORTSC1__PIC_WIDTH 2U +#define XHC_PORTSC1__PIC_RESETVALUE 0x0U +#define XHC_PORTSC1__PS_L 13U +#define XHC_PORTSC1__PS_R 10U +#define XHC_PORTSC1__PS_WIDTH 4U +#define XHC_PORTSC1__PS_RESETVALUE 0x0U + +#define XHC_PORTSC1__PP_L 9U +#define XHC_PORTSC1__PP_R 9U +#define XHC_PORTSC1__PP_WIDTH 1U +#define XHC_PORTSC1__PP_RESETVALUE 0x0U +#define XHC_PORTSC1__PLS_L 8U +#define XHC_PORTSC1__PLS_R 5U +#define XHC_PORTSC1__PLS_WIDTH 4U +#define XHC_PORTSC1__PLS_RESETVALUE 0x5U + +#define XHC_PORTSC1__PRST_L 4U +#define XHC_PORTSC1__PRST_R 4U +#define XHC_PORTSC1__PRST_WIDTH 1U +#define XHC_PORTSC1__PRST_RESETVALUE 0x0U + +#define XHC_PORTSC1__OCA_L 3U +#define XHC_PORTSC1__OCA_R 3U +#define XHC_PORTSC1__OCA_WIDTH 1U +#define XHC_PORTSC1__OCA_RESETVALUE 0x0U +#define XHC_PORTSC1__reserved 2U +#define XHC_PORTSC1__reserved_L 2U +#define XHC_PORTSC1__reserved_R 2U +#define XHC_PORTSC1__reserved_WIDTH 1U +#define XHC_PORTSC1__reserved_RESETVALUE 0x0U + +#define XHC_PORTSC1__PED_L 1U +#define XHC_PORTSC1__PED_R 1U +#define XHC_PORTSC1__PED_WIDTH 1U +#define XHC_PORTSC1__PED_RESETVALUE 0x0U + +#define XHC_PORTSC1__CCS_L 0U +#define XHC_PORTSC1__CCS_R 0U +#define XHC_PORTSC1__CCS_WIDTH 1U +#define XHC_PORTSC1__CCS_RESETVALUE 0x0U +#define XHC_PORTSC1__RESERVED_L 29U +#define XHC_PORTSC1__RESERVED_R 28U +#define XHC_PORTSC1_WIDTH 32U +#define XHC_PORTSC1__WIDTH 32U +#define XHC_PORTSC1_ALL_L 31U +#define XHC_PORTSC1_ALL_R 0U +#define XHC_PORTSC1__ALL_L 31U +#define XHC_PORTSC1__ALL_R 0U +#define XHC_PORTSC1_DATAMASK 0xcfffffffU +#define XHC_PORTSC1_RDWRMASK 0x30000000U +#define XHC_PORTSC1_RESETVALUE 0x000000a0U + +#define XHC_PORTPM1_OFFSET 0x424U +#define XHC_PORTPM1_BASE 0x424U +#define XHC_PORTPM1__reserved_L 31U +#define XHC_PORTPM1__reserved_R 17U +#define XHC_PORTPM1__reserved_WIDTH 15U +#define XHC_PORTPM1__reserved_RESETVALUE 0x0U +#define XHC_PORTPM1__FLA 16U +#define XHC_PORTPM1__FLA_L 16U +#define XHC_PORTPM1__FLA_R 16U +#define XHC_PORTPM1__FLA_WIDTH 1U +#define XHC_PORTPM1__FLA_RESETVALUE 0x0U +#define XHC_PORTPM1__U2T_L 15U +#define XHC_PORTPM1__U2T_R 8U +#define XHC_PORTPM1__U2T_WIDTH 8U +#define XHC_PORTPM1__U2T_RESETVALUE 0x00U +#define XHC_PORTPM1__U1T_L 7U +#define XHC_PORTPM1__U1T_R 0U +#define XHC_PORTPM1__U1T_WIDTH 8U +#define XHC_PORTPM1__U1T_RESETVALUE 0x00U +#define XHC_PORTPM1_WIDTH 32U +#define XHC_PORTPM1__WIDTH 32U +#define XHC_PORTPM1_ALL_L 31U +#define XHC_PORTPM1_ALL_R 0U +#define XHC_PORTPM1__ALL_L 31U +#define XHC_PORTPM1__ALL_R 0U +#define XHC_PORTPM1_DATAMASK 0xffffffffU +#define XHC_PORTPM1_RDWRMASK 0x00000000U +#define XHC_PORTPM1_RESETVALUE 0x00000000U + +#define XHC_PORTLC1_OFFSET 0x428U +#define XHC_PORTLC1_BASE 0x428U +#define XHC_PORTLC1__reserved_L 31U +#define XHC_PORTLC1__reserved_R 0U +#define XHC_PORTLC1__reserved_WIDTH 32U +#define XHC_PORTLC1__reserved_RESETVALUE 0x00000000U +#define XHC_PORTLC1_WIDTH 32U +#define XHC_PORTLC1__WIDTH 32U +#define XHC_PORTLC1_ALL_L 31U +#define XHC_PORTLC1_ALL_R 0U +#define XHC_PORTLC1__ALL_L 31U +#define XHC_PORTLC1__ALL_R 0U +#define XHC_PORTLC1_DATAMASK 0xffffffffU +#define XHC_PORTLC1_RDWRMASK 0x00000000U +#define XHC_PORTLC1_RESETVALUE 0x00000000U + +#define XHC_PORTSC2_OFFSET 0x430U +#define XHC_PORTSC2_BASE 0x430U +#define XHC_PORTSC2__WPR 31U +#define XHC_PORTSC2__WPR_L 31U +#define XHC_PORTSC2__WPR_R 31U +#define XHC_PORTSC2__WPR_WIDTH 1U +#define XHC_PORTSC2__WPR_RESETVALUE 0x0U +#define XHC_PORTSC2__DNR 30U +#define XHC_PORTSC2__DNR_L 30U +#define XHC_PORTSC2__DNR_R 30U +#define XHC_PORTSC2__DNR_WIDTH 1U +#define XHC_PORTSC2__DNR_RESETVALUE 0x0U +#define XHC_PORTSC2__WOE 27U +#define XHC_PORTSC2__WOE_L 27U +#define XHC_PORTSC2__WOE_R 27U +#define XHC_PORTSC2__WOE_WIDTH 1U +#define XHC_PORTSC2__WOE_RESETVALUE 0x0U +#define XHC_PORTSC2__WDE 26U +#define XHC_PORTSC2__WDE_L 26U +#define XHC_PORTSC2__WDE_R 26U +#define XHC_PORTSC2__WDE_WIDTH 1U +#define XHC_PORTSC2__WDE_RESETVALUE 0x0U +#define XHC_PORTSC2__WCE 25U +#define XHC_PORTSC2__WCE_L 25U +#define XHC_PORTSC2__WCE_R 25U +#define XHC_PORTSC2__WCE_WIDTH 1U +#define XHC_PORTSC2__WCE_RESETVALUE 0x0U +#define XHC_PORTSC2__CAS 24U +#define XHC_PORTSC2__CAS_L 24U +#define XHC_PORTSC2__CAS_R 24U +#define XHC_PORTSC2__CAS_WIDTH 1U +#define XHC_PORTSC2__CAS_RESETVALUE 0x0U +#define XHC_PORTSC2__CEC 23U +#define XHC_PORTSC2__CEC_L 23U +#define XHC_PORTSC2__CEC_R 23U +#define XHC_PORTSC2__CEC_WIDTH 1U +#define XHC_PORTSC2__CEC_RESETVALUE 0x0U +#define XHC_PORTSC2__PLC 22U +#define XHC_PORTSC2__PLC_L 22U +#define XHC_PORTSC2__PLC_R 22U +#define XHC_PORTSC2__PLC_WIDTH 1U +#define XHC_PORTSC2__PLC_RESETVALUE 0x0U +#define XHC_PORTSC2__PRC 21U +#define XHC_PORTSC2__PRC_L 21U +#define XHC_PORTSC2__PRC_R 21U +#define XHC_PORTSC2__PRC_WIDTH 1U +#define XHC_PORTSC2__PRC_RESETVALUE 0x0U +#define XHC_PORTSC2__OCC 20U +#define XHC_PORTSC2__OCC_L 20U +#define XHC_PORTSC2__OCC_R 20U +#define XHC_PORTSC2__OCC_WIDTH 1U +#define XHC_PORTSC2__OCC_RESETVALUE 0x0U +#define XHC_PORTSC2__WRC 19U +#define XHC_PORTSC2__WRC_L 19U +#define XHC_PORTSC2__WRC_R 19U +#define XHC_PORTSC2__WRC_WIDTH 1U +#define XHC_PORTSC2__WRC_RESETVALUE 0x0U +#define XHC_PORTSC2__PEC 18U +#define XHC_PORTSC2__PEC_L 18U +#define XHC_PORTSC2__PEC_R 18U +#define XHC_PORTSC2__PEC_WIDTH 1U +#define XHC_PORTSC2__PEC_RESETVALUE 0x0U +#define XHC_PORTSC2__CSC 17U +#define XHC_PORTSC2__CSC_L 17U +#define XHC_PORTSC2__CSC_R 17U +#define XHC_PORTSC2__CSC_WIDTH 1U +#define XHC_PORTSC2__CSC_RESETVALUE 0x0U +#define XHC_PORTSC2__LWS 16U +#define XHC_PORTSC2__LWS_L 16U +#define XHC_PORTSC2__LWS_R 16U +#define XHC_PORTSC2__LWS_WIDTH 1U +#define XHC_PORTSC2__LWS_RESETVALUE 0x0U +#define XHC_PORTSC2__PIC_L 15U +#define XHC_PORTSC2__PIC_R 14U +#define XHC_PORTSC2__PIC_WIDTH 2U +#define XHC_PORTSC2__PIC_RESETVALUE 0x0U +#define XHC_PORTSC2__PS_L 13U +#define XHC_PORTSC2__PS_R 10U +#define XHC_PORTSC2__PS_WIDTH 4U +#define XHC_PORTSC2__PS_RESETVALUE 0x0U +#define XHC_PORTSC2__PP 9U +#define XHC_PORTSC2__PP_L 9U +#define XHC_PORTSC2__PP_R 9U +#define XHC_PORTSC2__PP_WIDTH 1U +#define XHC_PORTSC2__PP_RESETVALUE 0x0U +#define XHC_PORTSC2__PLS_L 8U +#define XHC_PORTSC2__PLS_R 5U +#define XHC_PORTSC2__PLS_WIDTH 4U +#define XHC_PORTSC2__PLS_RESETVALUE 0x5U + +#define XHC_PORTSC2__PRST_L 4U +#define XHC_PORTSC2__PRST_R 4U +#define XHC_PORTSC2__PRST_WIDTH 1U +#define XHC_PORTSC2__PRST_RESETVALUE 0x0U +#define XHC_PORTSC2__OCA 3U +#define XHC_PORTSC2__OCA_L 3U +#define XHC_PORTSC2__OCA_R 3U +#define XHC_PORTSC2__OCA_WIDTH 1U +#define XHC_PORTSC2__OCA_RESETVALUE 0x0U +#define XHC_PORTSC2__reserved 2U +#define XHC_PORTSC2__reserved_L 2U +#define XHC_PORTSC2__reserved_R 2U +#define XHC_PORTSC2__reserved_WIDTH 1U +#define XHC_PORTSC2__reserved_RESETVALUE 0x0U +#define XHC_PORTSC2__PED 1U +#define XHC_PORTSC2__PED_L 1U +#define XHC_PORTSC2__PED_R 1U +#define XHC_PORTSC2__PED_WIDTH 1U +#define XHC_PORTSC2__PED_RESETVALUE 0x0U +#define XHC_PORTSC2__CCS 0U +#define XHC_PORTSC2__CCS_L 0U +#define XHC_PORTSC2__CCS_R 0U +#define XHC_PORTSC2__CCS_WIDTH 1U +#define XHC_PORTSC2__CCS_RESETVALUE 0x0U +#define XHC_PORTSC2__RESERVED_L 29U +#define XHC_PORTSC2__RESERVED_R 28U +#define XHC_PORTSC2_WIDTH 32U +#define XHC_PORTSC2__WIDTH 32U +#define XHC_PORTSC2_ALL_L 31U +#define XHC_PORTSC2_ALL_R 0U +#define XHC_PORTSC2__ALL_L 31U +#define XHC_PORTSC2__ALL_R 0U +#define XHC_PORTSC2_DATAMASK 0xcfffffffU +#define XHC_PORTSC2_RDWRMASK 0x30000000U +#define XHC_PORTSC2_RESETVALUE 0x000000a0U + +#define XHC_PORTPM2_OFFSET 0x434U +#define XHC_PORTPM2_BASE 0x434U +#define XHC_PORTPM2__PTC_L 31U +#define XHC_PORTPM2__PTC_R 28U +#define XHC_PORTPM2__PTC_WIDTH 4U +#define XHC_PORTPM2__PTC_RESETVALUE 0x0U +#define XHC_PORTPM2__reserved_L 27U +#define XHC_PORTPM2__reserved_R 17U +#define XHC_PORTPM2__reserved_WIDTH 11U +#define XHC_PORTPM2__reserved_RESETVALUE 0x0U +#define XHC_PORTPM2__HLE 16U +#define XHC_PORTPM2__HLE_L 16U +#define XHC_PORTPM2__HLE_R 16U +#define XHC_PORTPM2__HLE_WIDTH 1U +#define XHC_PORTPM2__HLE_RESETVALUE 0x0U +#define XHC_PORTPM2__L1DS_L 15U +#define XHC_PORTPM2__L1DS_R 8U +#define XHC_PORTPM2__L1DS_WIDTH 8U +#define XHC_PORTPM2__L1DS_RESETVALUE 0x00U +#define XHC_PORTPM2__BESL_L 7U +#define XHC_PORTPM2__BESL_R 4U +#define XHC_PORTPM2__BESL_WIDTH 4U +#define XHC_PORTPM2__BESL_RESETVALUE 0x0U +#define XHC_PORTPM2__RWE 3U +#define XHC_PORTPM2__RWE_L 3U +#define XHC_PORTPM2__RWE_R 3U +#define XHC_PORTPM2__RWE_WIDTH 1U +#define XHC_PORTPM2__RWE_RESETVALUE 0x0U +#define XHC_PORTPM2__L1S_L 2U +#define XHC_PORTPM2__L1S_R 0U +#define XHC_PORTPM2__L1S_WIDTH 3U +#define XHC_PORTPM2__L1S_RESETVALUE 0x0U +#define XHC_PORTPM2_WIDTH 32U +#define XHC_PORTPM2__WIDTH 32U +#define XHC_PORTPM2_ALL_L 31U +#define XHC_PORTPM2_ALL_R 0U +#define XHC_PORTPM2__ALL_L 31U +#define XHC_PORTPM2__ALL_R 0U +#define XHC_PORTPM2_DATAMASK 0xffffffffU +#define XHC_PORTPM2_RDWRMASK 0x00000000U +#define XHC_PORTPM2_RESETVALUE 0x00000000U + +#define XHC_PORTLC2_OFFSET 0x43cU +#define XHC_PORTLC2_BASE 0x43cU +#define XHC_PORTLC2__reserved_L 31U +#define XHC_PORTLC2__reserved_R 14U +#define XHC_PORTLC2__reserved_WIDTH 18U +#define XHC_PORTLC2__reserved_RESETVALUE 0x0U +#define XHC_PORTLC2__BESLD_L 13U +#define XHC_PORTLC2__BESLD_R 10U +#define XHC_PORTLC2__BESLD_WIDTH 4U +#define XHC_PORTLC2__BESLD_RESETVALUE 0x0U +#define XHC_PORTLC2__L1T_L 9U +#define XHC_PORTLC2__L1T_R 2U +#define XHC_PORTLC2__L1T_WIDTH 8U +#define XHC_PORTLC2__L1T_RESETVALUE 0x00U +#define XHC_PORTLC2__HIRDM_L 1U +#define XHC_PORTLC2__HIRDM_R 0U +#define XHC_PORTLC2__HIRDM_WIDTH 2U +#define XHC_PORTLC2__HIRDM_RESETVALUE 0x0U +#define XHC_PORTLC2_WIDTH 32U +#define XHC_PORTLC2__WIDTH 32U +#define XHC_PORTLC2_ALL_L 31U +#define XHC_PORTLC2_ALL_R 0U +#define XHC_PORTLC2__ALL_L 31U +#define XHC_PORTLC2__ALL_R 0U +#define XHC_PORTLC2_DATAMASK 0xffffffffU +#define XHC_PORTLC2_RDWRMASK 0x00000000U +#define XHC_PORTLC2_RESETVALUE 0x00000000U + +#define XHC_PORTSC3_OFFSET 0x440U +#define XHC_PORTSC3_BASE 0x440U +#define XHC_PORTSC3__WPR 31U +#define XHC_PORTSC3__WPR_L 31U +#define XHC_PORTSC3__WPR_R 31U +#define XHC_PORTSC3__WPR_WIDTH 1U +#define XHC_PORTSC3__WPR_RESETVALUE 0x0U +#define XHC_PORTSC3__DNR 30U +#define XHC_PORTSC3__DNR_L 30U +#define XHC_PORTSC3__DNR_R 30U +#define XHC_PORTSC3__DNR_WIDTH 1U +#define XHC_PORTSC3__DNR_RESETVALUE 0x0U +#define XHC_PORTSC3__WOE 27U +#define XHC_PORTSC3__WOE_L 27U +#define XHC_PORTSC3__WOE_R 27U +#define XHC_PORTSC3__WOE_WIDTH 1U +#define XHC_PORTSC3__WOE_RESETVALUE 0x0U +#define XHC_PORTSC3__WDE 26U +#define XHC_PORTSC3__WDE_L 26U +#define XHC_PORTSC3__WDE_R 26U +#define XHC_PORTSC3__WDE_WIDTH 1U +#define XHC_PORTSC3__WDE_RESETVALUE 0x0U +#define XHC_PORTSC3__WCE 25U +#define XHC_PORTSC3__WCE_L 25U +#define XHC_PORTSC3__WCE_R 25U +#define XHC_PORTSC3__WCE_WIDTH 1U +#define XHC_PORTSC3__WCE_RESETVALUE 0x0U +#define XHC_PORTSC3__CAS 24U +#define XHC_PORTSC3__CAS_L 24U +#define XHC_PORTSC3__CAS_R 24U +#define XHC_PORTSC3__CAS_WIDTH 1U +#define XHC_PORTSC3__CAS_RESETVALUE 0x0U +#define XHC_PORTSC3__CEC 23U +#define XHC_PORTSC3__CEC_L 23U +#define XHC_PORTSC3__CEC_R 23U +#define XHC_PORTSC3__CEC_WIDTH 1U +#define XHC_PORTSC3__CEC_RESETVALUE 0x0U +#define XHC_PORTSC3__PLC 22U +#define XHC_PORTSC3__PLC_L 22U +#define XHC_PORTSC3__PLC_R 22U +#define XHC_PORTSC3__PLC_WIDTH 1U +#define XHC_PORTSC3__PLC_RESETVALUE 0x0U +#define XHC_PORTSC3__PRC 21U +#define XHC_PORTSC3__PRC_L 21U +#define XHC_PORTSC3__PRC_R 21U +#define XHC_PORTSC3__PRC_WIDTH 1U +#define XHC_PORTSC3__PRC_RESETVALUE 0x0U +#define XHC_PORTSC3__OCC 20U +#define XHC_PORTSC3__OCC_L 20U +#define XHC_PORTSC3__OCC_R 20U +#define XHC_PORTSC3__OCC_WIDTH 1U +#define XHC_PORTSC3__OCC_RESETVALUE 0x0U +#define XHC_PORTSC3__WRC 19U +#define XHC_PORTSC3__WRC_L 19U +#define XHC_PORTSC3__WRC_R 19U +#define XHC_PORTSC3__WRC_WIDTH 1U +#define XHC_PORTSC3__WRC_RESETVALUE 0x0U +#define XHC_PORTSC3__PEC 18U +#define XHC_PORTSC3__PEC_L 18U +#define XHC_PORTSC3__PEC_R 18U +#define XHC_PORTSC3__PEC_WIDTH 1U +#define XHC_PORTSC3__PEC_RESETVALUE 0x0U +#define XHC_PORTSC3__CSC 17U +#define XHC_PORTSC3__CSC_L 17U +#define XHC_PORTSC3__CSC_R 17U +#define XHC_PORTSC3__CSC_WIDTH 1U +#define XHC_PORTSC3__CSC_RESETVALUE 0x0U +#define XHC_PORTSC3__LWS 16U +#define XHC_PORTSC3__LWS_L 16U +#define XHC_PORTSC3__LWS_R 16U +#define XHC_PORTSC3__LWS_WIDTH 1U +#define XHC_PORTSC3__LWS_RESETVALUE 0x0U +#define XHC_PORTSC3__PIC_L 15U +#define XHC_PORTSC3__PIC_R 14U +#define XHC_PORTSC3__PIC_WIDTH 2U +#define XHC_PORTSC3__PIC_RESETVALUE 0x0U +#define XHC_PORTSC3__PS_L 13U +#define XHC_PORTSC3__PS_R 10U +#define XHC_PORTSC3__PS_WIDTH 4U +#define XHC_PORTSC3__PS_RESETVALUE 0x0U +#define XHC_PORTSC3__PP 9U +#define XHC_PORTSC3__PP_L 9U +#define XHC_PORTSC3__PP_R 9U +#define XHC_PORTSC3__PP_WIDTH 1U +#define XHC_PORTSC3__PP_RESETVALUE 0x0U +#define XHC_PORTSC3__PLS_L 8U +#define XHC_PORTSC3__PLS_R 5U +#define XHC_PORTSC3__PLS_WIDTH 4U +#define XHC_PORTSC3__PLS_RESETVALUE 0x5U +#define XHC_PORTSC3__PR 4U +#define XHC_PORTSC3__PR_L 4U +#define XHC_PORTSC3__PR_R 4U +#define XHC_PORTSC3__PR_WIDTH 1U +#define XHC_PORTSC3__PR_RESETVALUE 0x0U +#define XHC_PORTSC3__OCA 3U +#define XHC_PORTSC3__OCA_L 3U +#define XHC_PORTSC3__OCA_R 3U +#define XHC_PORTSC3__OCA_WIDTH 1U +#define XHC_PORTSC3__OCA_RESETVALUE 0x0U +#define XHC_PORTSC3__reserved 2U +#define XHC_PORTSC3__reserved_L 2U +#define XHC_PORTSC3__reserved_R 2U +#define XHC_PORTSC3__reserved_WIDTH 1U +#define XHC_PORTSC3__reserved_RESETVALUE 0x0U +#define XHC_PORTSC3__PED 1U +#define XHC_PORTSC3__PED_L 1U +#define XHC_PORTSC3__PED_R 1U +#define XHC_PORTSC3__PED_WIDTH 1U +#define XHC_PORTSC3__PED_RESETVALUE 0x0U +#define XHC_PORTSC3__CCS 0U +#define XHC_PORTSC3__CCS_L 0U +#define XHC_PORTSC3__CCS_R 0U +#define XHC_PORTSC3__CCS_WIDTH 1U +#define XHC_PORTSC3__CCS_RESETVALUE 0x0U +#define XHC_PORTSC3__RESERVED_L 29U +#define XHC_PORTSC3__RESERVED_R 28U +#define XHC_PORTSC3_WIDTH 32U +#define XHC_PORTSC3__WIDTH 32U +#define XHC_PORTSC3_ALL_L 31U +#define XHC_PORTSC3_ALL_R 0U +#define XHC_PORTSC3__ALL_L 31U +#define XHC_PORTSC3__ALL_R 0U +#define XHC_PORTSC3_DATAMASK 0xcfffffffU +#define XHC_PORTSC3_RDWRMASK 0x30000000U +#define XHC_PORTSC3_RESETVALUE 0x000000a0U + +#define XHC_PORTPM3_OFFSET 0x444U +#define XHC_PORTPM3_BASE 0x444U +#define XHC_PORTPM3__PTC_L 31U +#define XHC_PORTPM3__PTC_R 28U +#define XHC_PORTPM3__PTC_WIDTH 4U +#define XHC_PORTPM3__PTC_RESETVALUE 0x0U +#define XHC_PORTPM3__reserved_L 27U +#define XHC_PORTPM3__reserved_R 17U +#define XHC_PORTPM3__reserved_WIDTH 11U +#define XHC_PORTPM3__reserved_RESETVALUE 0x0U +#define XHC_PORTPM3__HLE 16U +#define XHC_PORTPM3__HLE_L 16U +#define XHC_PORTPM3__HLE_R 16U +#define XHC_PORTPM3__HLE_WIDTH 1U +#define XHC_PORTPM3__HLE_RESETVALUE 0x0U +#define XHC_PORTPM3__L1DS_L 15U +#define XHC_PORTPM3__L1DS_R 8U +#define XHC_PORTPM3__L1DS_WIDTH 8U +#define XHC_PORTPM3__L1DS_RESETVALUE 0x00U +#define XHC_PORTPM3__BESL_L 7U +#define XHC_PORTPM3__BESL_R 4U +#define XHC_PORTPM3__BESL_WIDTH 4U +#define XHC_PORTPM3__BESL_RESETVALUE 0x0U +#define XHC_PORTPM3__RWE 3U +#define XHC_PORTPM3__RWE_L 3U +#define XHC_PORTPM3__RWE_R 3U +#define XHC_PORTPM3__RWE_WIDTH 1U +#define XHC_PORTPM3__RWE_RESETVALUE 0x0U +#define XHC_PORTPM3__L1S_L 2U +#define XHC_PORTPM3__L1S_R 0U +#define XHC_PORTPM3__L1S_WIDTH 3U +#define XHC_PORTPM3__L1S_RESETVALUE 0x0U +#define XHC_PORTPM3_WIDTH 32U +#define XHC_PORTPM3__WIDTH 32U +#define XHC_PORTPM3_ALL_L 31U +#define XHC_PORTPM3_ALL_R 0U +#define XHC_PORTPM3__ALL_L 31U +#define XHC_PORTPM3__ALL_R 0U +#define XHC_PORTPM3_DATAMASK 0xffffffffU +#define XHC_PORTPM3_RDWRMASK 0x00000000U +#define XHC_PORTPM3_RESETVALUE 0x00000000U + +#define XHC_PORTLI3_OFFSET 0x44cU +#define XHC_PORTLI3_BASE 0x44cU +#define XHC_PORTLI3__reserved_L 31U +#define XHC_PORTLI3__reserved_R 0U +#define XHC_PORTLI3__reserved_WIDTH 32U +#define XHC_PORTLI3__reserved_RESETVALUE 0x00000000U +#define XHC_PORTLI3_WIDTH 32U +#define XHC_PORTLI3__WIDTH 32U +#define XHC_PORTLI3_ALL_L 31U +#define XHC_PORTLI3_ALL_R 0U +#define XHC_PORTLI3__ALL_L 31U +#define XHC_PORTLI3__ALL_R 0U +#define XHC_PORTLI3_DATAMASK 0xffffffffU +#define XHC_PORTLI3_RDWRMASK 0x00000000U +#define XHC_PORTLI3_RESETVALUE 0x00000000U + +#define XHC_MFINDEX_OFFSET 0x4a0U +#define XHC_MFINDEX_BASE 0x4a0U +#define XHC_MFINDEX__reserved_L 31U +#define XHC_MFINDEX__reserved_R 14U +#define XHC_MFINDEX__reserved_WIDTH 18U +#define XHC_MFINDEX__reserved_RESETVALUE 0x0U +#define XHC_MFINDEX__MFI_L 13U +#define XHC_MFINDEX__MFI_R 0U +#define XHC_MFINDEX__MFI_WIDTH 14U +#define XHC_MFINDEX__MFI_RESETVALUE 0x0U +#define XHC_MFINDEX_WIDTH 32U +#define XHC_MFINDEX__WIDTH 32U +#define XHC_MFINDEX_ALL_L 31U +#define XHC_MFINDEX_ALL_R 0U +#define XHC_MFINDEX__ALL_L 31U +#define XHC_MFINDEX__ALL_R 0U +#define XHC_MFINDEX_DATAMASK 0xffffffffU +#define XHC_MFINDEX_RDWRMASK 0x00000000U +#define XHC_MFINDEX_RESETVALUE 0x00000000U + +#define XHC_IMAN0_OFFSET 0x4c0U +#define XHC_IMAN0_BASE 0x4c0U +#define XHC_IMAN0__reserved_L 31U +#define XHC_IMAN0__reserved_R 2U +#define XHC_IMAN0__reserved_WIDTH 30U +#define XHC_IMAN0__reserved_RESETVALUE 0x0U +#define XHC_IMAN0__IE 1U +#define XHC_IMAN0__IE_L 1U +#define XHC_IMAN0__IE_R 1U +#define XHC_IMAN0__IE_WIDTH 1U +#define XHC_IMAN0__IE_RESETVALUE 0x0U +#define XHC_IMAN0__IP 0U +#define XHC_IMAN0__IP_L 0U +#define XHC_IMAN0__IP_R 0U +#define XHC_IMAN0__IP_WIDTH 1U +#define XHC_IMAN0__IP_RESETVALUE 0x0U +#define XHC_IMAN0_WIDTH 32U +#define XHC_IMAN0__WIDTH 32U +#define XHC_IMAN0_ALL_L 31U +#define XHC_IMAN0_ALL_R 0U +#define XHC_IMAN0__ALL_L 31U +#define XHC_IMAN0__ALL_R 0U +#define XHC_IMAN0_DATAMASK 0xffffffffU +#define XHC_IMAN0_RDWRMASK 0x00000000U +#define XHC_IMAN0_RESETVALUE 0x00000000U + +#define XHC_IMOD0_OFFSET 0x4c4U +#define XHC_IMOD0_BASE 0x4c4U +#define XHC_IMOD0__IMODC_L 31U +#define XHC_IMOD0__IMODC_R 16U +#define XHC_IMOD0__IMODC_WIDTH 16U +#define XHC_IMOD0__IMODC_RESETVALUE 0x0000U +#define XHC_IMOD0__IMODI_L 15U +#define XHC_IMOD0__IMODI_R 0U +#define XHC_IMOD0__IMODI_WIDTH 16U +#define XHC_IMOD0__IMODI_RESETVALUE 0x4000U +#define XHC_IMOD0_WIDTH 32U +#define XHC_IMOD0__WIDTH 32U +#define XHC_IMOD0_ALL_L 31U +#define XHC_IMOD0_ALL_R 0U +#define XHC_IMOD0__ALL_L 31U +#define XHC_IMOD0__ALL_R 0U +#define XHC_IMOD0_DATAMASK 0xffffffffU +#define XHC_IMOD0_RDWRMASK 0x00000000U +#define XHC_IMOD0_RESETVALUE 0x00004000U + +#define XHC_ERSTSZ0_OFFSET 0x4c8U +#define XHC_ERSTSZ0_BASE 0x4c8U +#define XHC_ERSTSZ0__reserved_L 31U +#define XHC_ERSTSZ0__reserved_R 16U +#define XHC_ERSTSZ0__reserved_WIDTH 16U +#define XHC_ERSTSZ0__reserved_RESETVALUE 0x0000U +#define XHC_ERSTSZ0__TSZ_L 15U +#define XHC_ERSTSZ0__TSZ_R 0U +#define XHC_ERSTSZ0__TSZ_WIDTH 16U +#define XHC_ERSTSZ0__TSZ_RESETVALUE 0x0000U +#define XHC_ERSTSZ0_WIDTH 32U +#define XHC_ERSTSZ0__WIDTH 32U +#define XHC_ERSTSZ0_ALL_L 31U +#define XHC_ERSTSZ0_ALL_R 0U +#define XHC_ERSTSZ0__ALL_L 31U +#define XHC_ERSTSZ0__ALL_R 0U +#define XHC_ERSTSZ0_DATAMASK 0xffffffffU +#define XHC_ERSTSZ0_RDWRMASK 0x00000000U +#define XHC_ERSTSZ0_RESETVALUE 0x00000000U + +#define XHC_ERSTBAL0_OFFSET 0x4d0U +#define XHC_ERSTBAL0_BASE 0x4d0U +#define XHC_ERSTBAL0__BAL_L 31U +#define XHC_ERSTBAL0__BAL_R 4U +#define XHC_ERSTBAL0__BAL_WIDTH 28U +#define XHC_ERSTBAL0__BAL_RESETVALUE 0x0000000U +#define XHC_ERSTBAL0__reserved_L 3U +#define XHC_ERSTBAL0__reserved_R 0U +#define XHC_ERSTBAL0__reserved_WIDTH 4U +#define XHC_ERSTBAL0__reserved_RESETVALUE 0x0U +#define XHC_ERSTBAL0_WIDTH 32U +#define XHC_ERSTBAL0__WIDTH 32U +#define XHC_ERSTBAL0_ALL_L 31U +#define XHC_ERSTBAL0_ALL_R 0U +#define XHC_ERSTBAL0__ALL_L 31U +#define XHC_ERSTBAL0__ALL_R 0U +#define XHC_ERSTBAL0_DATAMASK 0xffffffffU +#define XHC_ERSTBAL0_RDWRMASK 0x00000000U +#define XHC_ERSTBAL0_RESETVALUE 0x00000000U + +#define XHC_ERSTBAH0_OFFSET 0x4d4U +#define XHC_ERSTBAH0_BASE 0x4d4U +#define XHC_ERSTBAH0__BAH_L 31U +#define XHC_ERSTBAH0__BAH_R 0U +#define XHC_ERSTBAH0__BAH_WIDTH 32U +#define XHC_ERSTBAH0__BAH_RESETVALUE 0x00000000U +#define XHC_ERSTBAH0_WIDTH 32U +#define XHC_ERSTBAH0__WIDTH 32U +#define XHC_ERSTBAH0_ALL_L 31U +#define XHC_ERSTBAH0_ALL_R 0U +#define XHC_ERSTBAH0__ALL_L 31U +#define XHC_ERSTBAH0__ALL_R 0U +#define XHC_ERSTBAH0_DATAMASK 0xffffffffU +#define XHC_ERSTBAH0_RDWRMASK 0x00000000U +#define XHC_ERSTBAH0_RESETVALUE 0x00000000U + +#define XHC_ERDPL0_OFFSET 0x4d8U +#define XHC_ERDPL0_BASE 0x4d8U +#define XHC_ERDPL0__DPL_L 31U +#define XHC_ERDPL0__DPL_R 4U +#define XHC_ERDPL0__DPL_WIDTH 28U +#define XHC_ERDPL0__DPL_RESETVALUE 0x0000000U +#define XHC_ERDPL0__EHB 3U +#define XHC_ERDPL0__EHB_L 3U +#define XHC_ERDPL0__EHB_R 3U +#define XHC_ERDPL0__EHB_WIDTH 1U +#define XHC_ERDPL0__EHB_RESETVALUE 0x0U +#define XHC_ERDPL0__DESI_L 2U +#define XHC_ERDPL0__DESI_R 0U +#define XHC_ERDPL0__DESI_WIDTH 3U +#define XHC_ERDPL0__DESI_RESETVALUE 0x0U +#define XHC_ERDPL0_WIDTH 32U +#define XHC_ERDPL0__WIDTH 32U +#define XHC_ERDPL0_ALL_L 31U +#define XHC_ERDPL0_ALL_R 0U +#define XHC_ERDPL0__ALL_L 31U +#define XHC_ERDPL0__ALL_R 0U +#define XHC_ERDPL0_DATAMASK 0xffffffffU +#define XHC_ERDPL0_RDWRMASK 0x00000000U +#define XHC_ERDPL0_RESETVALUE 0x00000000U + +#define XHC_ERDPH0_OFFSET 0x4dcU +#define XHC_ERDPH0_BASE 0x4dcU +#define XHC_ERDPH0__DPH_L 31U +#define XHC_ERDPH0__DPH_R 0U +#define XHC_ERDPH0__DPH_WIDTH 32U +#define XHC_ERDPH0__DPH_RESETVALUE 0x00000000U +#define XHC_ERDPH0_WIDTH 32U +#define XHC_ERDPH0__WIDTH 32U +#define XHC_ERDPH0_ALL_L 31U +#define XHC_ERDPH0_ALL_R 0U +#define XHC_ERDPH0__ALL_L 31U +#define XHC_ERDPH0__ALL_R 0U +#define XHC_ERDPH0_DATAMASK 0xffffffffU +#define XHC_ERDPH0_RDWRMASK 0x00000000U +#define XHC_ERDPH0_RESETVALUE 0x00000000U + +#define XHC_IMAN1_OFFSET 0x4e0U +#define XHC_IMAN1_BASE 0x4e0U +#define XHC_IMAN1__reserved_L 31U +#define XHC_IMAN1__reserved_R 2U +#define XHC_IMAN1__reserved_WIDTH 30U +#define XHC_IMAN1__reserved_RESETVALUE 0x0U +#define XHC_IMAN1__IE 1U +#define XHC_IMAN1__IE_L 1U +#define XHC_IMAN1__IE_R 1U +#define XHC_IMAN1__IE_WIDTH 1U +#define XHC_IMAN1__IE_RESETVALUE 0x0U +#define XHC_IMAN1__IP 0U +#define XHC_IMAN1__IP_L 0U +#define XHC_IMAN1__IP_R 0U +#define XHC_IMAN1__IP_WIDTH 1U +#define XHC_IMAN1__IP_RESETVALUE 0x0U +#define XHC_IMAN1_WIDTH 32U +#define XHC_IMAN1__WIDTH 32U +#define XHC_IMAN1_ALL_L 31U +#define XHC_IMAN1_ALL_R 0U +#define XHC_IMAN1__ALL_L 31U +#define XHC_IMAN1__ALL_R 0U +#define XHC_IMAN1_DATAMASK 0xffffffffU +#define XHC_IMAN1_RDWRMASK 0x00000000U +#define XHC_IMAN1_RESETVALUE 0x00000000U + +#define XHC_IMOD1_OFFSET 0x4e4U +#define XHC_IMOD1_BASE 0x4e4U +#define XHC_IMOD1__IMODC_L 31U +#define XHC_IMOD1__IMODC_R 16U +#define XHC_IMOD1__IMODC_WIDTH 16U +#define XHC_IMOD1__IMODC_RESETVALUE 0x0000U +#define XHC_IMOD1__IMODI_L 15U +#define XHC_IMOD1__IMODI_R 0U +#define XHC_IMOD1__IMODI_WIDTH 16U +#define XHC_IMOD1__IMODI_RESETVALUE 0x4000U +#define XHC_IMOD1_WIDTH 32U +#define XHC_IMOD1__WIDTH 32U +#define XHC_IMOD1_ALL_L 31U +#define XHC_IMOD1_ALL_R 0U +#define XHC_IMOD1__ALL_L 31U +#define XHC_IMOD1__ALL_R 0U +#define XHC_IMOD1_DATAMASK 0xffffffffU +#define XHC_IMOD1_RDWRMASK 0x00000000U +#define XHC_IMOD1_RESETVALUE 0x00004000U + +#define XHC_ERSTSZ1_OFFSET 0x4e8U +#define XHC_ERSTSZ1_BASE 0x4e8U +#define XHC_ERSTSZ1__reserved_L 31U +#define XHC_ERSTSZ1__reserved_R 16U +#define XHC_ERSTSZ1__reserved_WIDTH 16U +#define XHC_ERSTSZ1__reserved_RESETVALUE 0x0000U +#define XHC_ERSTSZ1__TSZ_L 15U +#define XHC_ERSTSZ1__TSZ_R 0U +#define XHC_ERSTSZ1__TSZ_WIDTH 16U +#define XHC_ERSTSZ1__TSZ_RESETVALUE 0x0000U +#define XHC_ERSTSZ1_WIDTH 32U +#define XHC_ERSTSZ1__WIDTH 32U +#define XHC_ERSTSZ1_ALL_L 31U +#define XHC_ERSTSZ1_ALL_R 0U +#define XHC_ERSTSZ1__ALL_L 31U +#define XHC_ERSTSZ1__ALL_R 0U +#define XHC_ERSTSZ1_DATAMASK 0xffffffffU +#define XHC_ERSTSZ1_RDWRMASK 0x00000000U +#define XHC_ERSTSZ1_RESETVALUE 0x00000000U + +#define XHC_ERSTBAL1_OFFSET 0x4f0U +#define XHC_ERSTBAL1_BASE 0x4f0U +#define XHC_ERSTBAL1__BAL_L 31U +#define XHC_ERSTBAL1__BAL_R 4U +#define XHC_ERSTBAL1__BAL_WIDTH 28U +#define XHC_ERSTBAL1__BAL_RESETVALUE 0x0000000U +#define XHC_ERSTBAL1__reserved_L 3U +#define XHC_ERSTBAL1__reserved_R 0U +#define XHC_ERSTBAL1__reserved_WIDTH 4U +#define XHC_ERSTBAL1__reserved_RESETVALUE 0x0U +#define XHC_ERSTBAL1_WIDTH 32U +#define XHC_ERSTBAL1__WIDTH 32U +#define XHC_ERSTBAL1_ALL_L 31U +#define XHC_ERSTBAL1_ALL_R 0U +#define XHC_ERSTBAL1__ALL_L 31U +#define XHC_ERSTBAL1__ALL_R 0U +#define XHC_ERSTBAL1_DATAMASK 0xffffffffU +#define XHC_ERSTBAL1_RDWRMASK 0x00000000U +#define XHC_ERSTBAL1_RESETVALUE 0x00000000U + +#define XHC_ERSTBAH1_OFFSET 0x4f4U +#define XHC_ERSTBAH1_BASE 0x4f4U +#define XHC_ERSTBAH1__BAH_L 31U +#define XHC_ERSTBAH1__BAH_R 0U +#define XHC_ERSTBAH1__BAH_WIDTH 32U +#define XHC_ERSTBAH1__BAH_RESETVALUE 0x00000000U +#define XHC_ERSTBAH1_WIDTH 32U +#define XHC_ERSTBAH1__WIDTH 32U +#define XHC_ERSTBAH1_ALL_L 31U +#define XHC_ERSTBAH1_ALL_R 0U +#define XHC_ERSTBAH1__ALL_L 31U +#define XHC_ERSTBAH1__ALL_R 0U +#define XHC_ERSTBAH1_DATAMASK 0xffffffffU +#define XHC_ERSTBAH1_RDWRMASK 0x00000000U +#define XHC_ERSTBAH1_RESETVALUE 0x00000000U + +#define XHC_ERDPL1_OFFSET 0x4f8U +#define XHC_ERDPL1_BASE 0x4f8U +#define XHC_ERDPL1__DPL_L 31U +#define XHC_ERDPL1__DPL_R 4U +#define XHC_ERDPL1__DPL_WIDTH 28U +#define XHC_ERDPL1__DPL_RESETVALUE 0x0000000U +#define XHC_ERDPL1__EHB 3U +#define XHC_ERDPL1__EHB_L 3U +#define XHC_ERDPL1__EHB_R 3U +#define XHC_ERDPL1__EHB_WIDTH 1U +#define XHC_ERDPL1__EHB_RESETVALUE 0x0U +#define XHC_ERDPL1__DESI_L 2U +#define XHC_ERDPL1__DESI_R 0U +#define XHC_ERDPL1__DESI_WIDTH 3U +#define XHC_ERDPL1__DESI_RESETVALUE 0x0U +#define XHC_ERDPL1_WIDTH 32U +#define XHC_ERDPL1__WIDTH 32U +#define XHC_ERDPL1_ALL_L 31U +#define XHC_ERDPL1_ALL_R 0U +#define XHC_ERDPL1__ALL_L 31U +#define XHC_ERDPL1__ALL_R 0U +#define XHC_ERDPL1_DATAMASK 0xffffffffU +#define XHC_ERDPL1_RDWRMASK 0x00000000U +#define XHC_ERDPL1_RESETVALUE 0x00000000U + +#define XHC_ERDPH1_OFFSET 0x4fcU +#define XHC_ERDPH1_BASE 0x4fcU +#define XHC_ERDPH1__DPH_L 31U +#define XHC_ERDPH1__DPH_R 0U +#define XHC_ERDPH1__DPH_WIDTH 32U +#define XHC_ERDPH1__DPH_RESETVALUE 0x00000000U +#define XHC_ERDPH1_WIDTH 32U +#define XHC_ERDPH1__WIDTH 32U +#define XHC_ERDPH1_ALL_L 31U +#define XHC_ERDPH1_ALL_R 0U +#define XHC_ERDPH1__ALL_L 31U +#define XHC_ERDPH1__ALL_R 0U +#define XHC_ERDPH1_DATAMASK 0xffffffffU +#define XHC_ERDPH1_RDWRMASK 0x00000000U +#define XHC_ERDPH1_RESETVALUE 0x00000000U + +#define XHC_DBLCMD_OFFSET 0x8c0U +#define XHC_DBLCMD_BASE 0x8c0U +#define XHC_DBLCMD__SID_L 31U +#define XHC_DBLCMD__SID_R 16U +#define XHC_DBLCMD__SID_WIDTH 16U +#define XHC_DBLCMD__SID_RESETVALUE 0x0000U +#define XHC_DBLCMD__reserved_L 15U +#define XHC_DBLCMD__reserved_R 8U +#define XHC_DBLCMD__reserved_WIDTH 8U +#define XHC_DBLCMD__reserved_RESETVALUE 0x00U +#define XHC_DBLCMD__TGT_L 7U +#define XHC_DBLCMD__TGT_R 0U +#define XHC_DBLCMD__TGT_WIDTH 8U +#define XHC_DBLCMD__TGT_RESETVALUE 0x00U +#define XHC_DBLCMD_WIDTH 32U +#define XHC_DBLCMD__WIDTH 32U +#define XHC_DBLCMD_ALL_L 31U +#define XHC_DBLCMD_ALL_R 0U +#define XHC_DBLCMD__ALL_L 31U +#define XHC_DBLCMD__ALL_R 0U +#define XHC_DBLCMD_DATAMASK 0xffffffffU +#define XHC_DBLCMD_RDWRMASK 0x00000000U +#define XHC_DBLCMD_RESETVALUE 0x00000000U + +#define XHC_DBLDVX1_OFFSET 0x8c4U +#define XHC_DBLDVX1_BASE 0x8c4U +#define XHC_DBLDVX1__SID_L 31U +#define XHC_DBLDVX1__SID_R 16U +#define XHC_DBLDVX1__SID_WIDTH 16U +#define XHC_DBLDVX1__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX1__reserved_L 15U +#define XHC_DBLDVX1__reserved_R 8U +#define XHC_DBLDVX1__reserved_WIDTH 8U +#define XHC_DBLDVX1__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX1__TGT_L 7U +#define XHC_DBLDVX1__TGT_R 0U +#define XHC_DBLDVX1__TGT_WIDTH 8U +#define XHC_DBLDVX1__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX1_WIDTH 32U +#define XHC_DBLDVX1__WIDTH 32U +#define XHC_DBLDVX1_ALL_L 31U +#define XHC_DBLDVX1_ALL_R 0U +#define XHC_DBLDVX1__ALL_L 31U +#define XHC_DBLDVX1__ALL_R 0U +#define XHC_DBLDVX1_DATAMASK 0xffffffffU +#define XHC_DBLDVX1_RDWRMASK 0x00000000U +#define XHC_DBLDVX1_RESETVALUE 0x00000000U + +#define XHC_DBLDVX2_OFFSET 0x8c8U +#define XHC_DBLDVX2_BASE 0x8c8U +#define XHC_DBLDVX2__SID_L 31U +#define XHC_DBLDVX2__SID_R 16U +#define XHC_DBLDVX2__SID_WIDTH 16U +#define XHC_DBLDVX2__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX2__reserved_L 15U +#define XHC_DBLDVX2__reserved_R 8U +#define XHC_DBLDVX2__reserved_WIDTH 8U +#define XHC_DBLDVX2__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX2__TGT_L 7U +#define XHC_DBLDVX2__TGT_R 0U +#define XHC_DBLDVX2__TGT_WIDTH 8U +#define XHC_DBLDVX2__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX2_WIDTH 32U +#define XHC_DBLDVX2__WIDTH 32U +#define XHC_DBLDVX2_ALL_L 31U +#define XHC_DBLDVX2_ALL_R 0U +#define XHC_DBLDVX2__ALL_L 31U +#define XHC_DBLDVX2__ALL_R 0U +#define XHC_DBLDVX2_DATAMASK 0xffffffffU +#define XHC_DBLDVX2_RDWRMASK 0x00000000U +#define XHC_DBLDVX2_RESETVALUE 0x00000000U + +#define XHC_DBLDVX3_OFFSET 0x8ccU +#define XHC_DBLDVX3_BASE 0x8ccU +#define XHC_DBLDVX3__SID_L 31U +#define XHC_DBLDVX3__SID_R 16U +#define XHC_DBLDVX3__SID_WIDTH 16U +#define XHC_DBLDVX3__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX3__reserved_L 15U +#define XHC_DBLDVX3__reserved_R 8U +#define XHC_DBLDVX3__reserved_WIDTH 8U +#define XHC_DBLDVX3__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX3__TGT_L 7U +#define XHC_DBLDVX3__TGT_R 0U +#define XHC_DBLDVX3__TGT_WIDTH 8U +#define XHC_DBLDVX3__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX3_WIDTH 32U +#define XHC_DBLDVX3__WIDTH 32U +#define XHC_DBLDVX3_ALL_L 31U +#define XHC_DBLDVX3_ALL_R 0U +#define XHC_DBLDVX3__ALL_L 31U +#define XHC_DBLDVX3__ALL_R 0U +#define XHC_DBLDVX3_DATAMASK 0xffffffffU +#define XHC_DBLDVX3_RDWRMASK 0x00000000U +#define XHC_DBLDVX3_RESETVALUE 0x00000000U + +#define XHC_DBLDVX4_OFFSET 0x8d0U +#define XHC_DBLDVX4_BASE 0x8d0U +#define XHC_DBLDVX4__SID_L 31U +#define XHC_DBLDVX4__SID_R 16U +#define XHC_DBLDVX4__SID_WIDTH 16U +#define XHC_DBLDVX4__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX4__reserved_L 15U +#define XHC_DBLDVX4__reserved_R 8U +#define XHC_DBLDVX4__reserved_WIDTH 8U +#define XHC_DBLDVX4__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX4__TGT_L 7U +#define XHC_DBLDVX4__TGT_R 0U +#define XHC_DBLDVX4__TGT_WIDTH 8U +#define XHC_DBLDVX4__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX4_WIDTH 32U +#define XHC_DBLDVX4__WIDTH 32U +#define XHC_DBLDVX4_ALL_L 31U +#define XHC_DBLDVX4_ALL_R 0U +#define XHC_DBLDVX4__ALL_L 31U +#define XHC_DBLDVX4__ALL_R 0U +#define XHC_DBLDVX4_DATAMASK 0xffffffffU +#define XHC_DBLDVX4_RDWRMASK 0x00000000U +#define XHC_DBLDVX4_RESETVALUE 0x00000000U + +#define XHC_DBLDVX5_OFFSET 0x8d4U +#define XHC_DBLDVX5_BASE 0x8d4U +#define XHC_DBLDVX5__SID_L 31U +#define XHC_DBLDVX5__SID_R 16U +#define XHC_DBLDVX5__SID_WIDTH 16U +#define XHC_DBLDVX5__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX5__reserved_L 15U +#define XHC_DBLDVX5__reserved_R 8U +#define XHC_DBLDVX5__reserved_WIDTH 8U +#define XHC_DBLDVX5__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX5__TGT_L 7U +#define XHC_DBLDVX5__TGT_R 0U +#define XHC_DBLDVX5__TGT_WIDTH 8U +#define XHC_DBLDVX5__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX5_WIDTH 32U +#define XHC_DBLDVX5__WIDTH 32U +#define XHC_DBLDVX5_ALL_L 31U +#define XHC_DBLDVX5_ALL_R 0U +#define XHC_DBLDVX5__ALL_L 31U +#define XHC_DBLDVX5__ALL_R 0U +#define XHC_DBLDVX5_DATAMASK 0xffffffffU +#define XHC_DBLDVX5_RDWRMASK 0x00000000U +#define XHC_DBLDVX5_RESETVALUE 0x00000000U + +#define XHC_DBLDVX6_OFFSET 0x8d8U +#define XHC_DBLDVX6_BASE 0x8d8U +#define XHC_DBLDVX6__SID_L 31U +#define XHC_DBLDVX6__SID_R 16U +#define XHC_DBLDVX6__SID_WIDTH 16U +#define XHC_DBLDVX6__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX6__reserved_L 15U +#define XHC_DBLDVX6__reserved_R 8U +#define XHC_DBLDVX6__reserved_WIDTH 8U +#define XHC_DBLDVX6__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX6__TGT_L 7U +#define XHC_DBLDVX6__TGT_R 0U +#define XHC_DBLDVX6__TGT_WIDTH 8U +#define XHC_DBLDVX6__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX6_WIDTH 32U +#define XHC_DBLDVX6__WIDTH 32U +#define XHC_DBLDVX6_ALL_L 31U +#define XHC_DBLDVX6_ALL_R 0U +#define XHC_DBLDVX6__ALL_L 31U +#define XHC_DBLDVX6__ALL_R 0U +#define XHC_DBLDVX6_DATAMASK 0xffffffffU +#define XHC_DBLDVX6_RDWRMASK 0x00000000U +#define XHC_DBLDVX6_RESETVALUE 0x00000000U + +#define XHC_DBLDVX7_OFFSET 0x8dcU +#define XHC_DBLDVX7_BASE 0x8dcU +#define XHC_DBLDVX7__SID_L 31U +#define XHC_DBLDVX7__SID_R 16U +#define XHC_DBLDVX7__SID_WIDTH 16U +#define XHC_DBLDVX7__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX7__reserved_L 15U +#define XHC_DBLDVX7__reserved_R 8U +#define XHC_DBLDVX7__reserved_WIDTH 8U +#define XHC_DBLDVX7__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX7__TGT_L 7U +#define XHC_DBLDVX7__TGT_R 0U +#define XHC_DBLDVX7__TGT_WIDTH 8U +#define XHC_DBLDVX7__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX7_WIDTH 32U +#define XHC_DBLDVX7__WIDTH 32U +#define XHC_DBLDVX7_ALL_L 31U +#define XHC_DBLDVX7_ALL_R 0U +#define XHC_DBLDVX7__ALL_L 31U +#define XHC_DBLDVX7__ALL_R 0U +#define XHC_DBLDVX7_DATAMASK 0xffffffffU +#define XHC_DBLDVX7_RDWRMASK 0x00000000U +#define XHC_DBLDVX7_RESETVALUE 0x00000000U + +#define XHC_DBLDVX8_OFFSET 0x8e0U +#define XHC_DBLDVX8_BASE 0x8e0U +#define XHC_DBLDVX8__SID_L 31U +#define XHC_DBLDVX8__SID_R 16U +#define XHC_DBLDVX8__SID_WIDTH 16U +#define XHC_DBLDVX8__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX8__reserved_L 15U +#define XHC_DBLDVX8__reserved_R 8U +#define XHC_DBLDVX8__reserved_WIDTH 8U +#define XHC_DBLDVX8__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX8__TGT_L 7U +#define XHC_DBLDVX8__TGT_R 0U +#define XHC_DBLDVX8__TGT_WIDTH 8U +#define XHC_DBLDVX8__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX8_WIDTH 32U +#define XHC_DBLDVX8__WIDTH 32U +#define XHC_DBLDVX8_ALL_L 31U +#define XHC_DBLDVX8_ALL_R 0U +#define XHC_DBLDVX8__ALL_L 31U +#define XHC_DBLDVX8__ALL_R 0U +#define XHC_DBLDVX8_DATAMASK 0xffffffffU +#define XHC_DBLDVX8_RDWRMASK 0x00000000U +#define XHC_DBLDVX8_RESETVALUE 0x00000000U + +#define XHC_DBLDVX9_OFFSET 0x8e4U +#define XHC_DBLDVX9_BASE 0x8e4U +#define XHC_DBLDVX9__SID_L 31U +#define XHC_DBLDVX9__SID_R 16U +#define XHC_DBLDVX9__SID_WIDTH 16U +#define XHC_DBLDVX9__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX9__reserved_L 15U +#define XHC_DBLDVX9__reserved_R 8U +#define XHC_DBLDVX9__reserved_WIDTH 8U +#define XHC_DBLDVX9__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX9__TGT_L 7U +#define XHC_DBLDVX9__TGT_R 0U +#define XHC_DBLDVX9__TGT_WIDTH 8U +#define XHC_DBLDVX9__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX9_WIDTH 32U +#define XHC_DBLDVX9__WIDTH 32U +#define XHC_DBLDVX9_ALL_L 31U +#define XHC_DBLDVX9_ALL_R 0U +#define XHC_DBLDVX9__ALL_L 31U +#define XHC_DBLDVX9__ALL_R 0U +#define XHC_DBLDVX9_DATAMASK 0xffffffffU +#define XHC_DBLDVX9_RDWRMASK 0x00000000U +#define XHC_DBLDVX9_RESETVALUE 0x00000000U + +#define XHC_DBLDVX10_OFFSET 0x8e8U +#define XHC_DBLDVX10_BASE 0x8e8U +#define XHC_DBLDVX10__SID_L 31U +#define XHC_DBLDVX10__SID_R 16U +#define XHC_DBLDVX10__SID_WIDTH 16U +#define XHC_DBLDVX10__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX10__reserved_L 15U +#define XHC_DBLDVX10__reserved_R 8U +#define XHC_DBLDVX10__reserved_WIDTH 8U +#define XHC_DBLDVX10__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX10__TGT_L 7U +#define XHC_DBLDVX10__TGT_R 0U +#define XHC_DBLDVX10__TGT_WIDTH 8U +#define XHC_DBLDVX10__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX10_WIDTH 32U +#define XHC_DBLDVX10__WIDTH 32U +#define XHC_DBLDVX10_ALL_L 31U +#define XHC_DBLDVX10_ALL_R 0U +#define XHC_DBLDVX10__ALL_L 31U +#define XHC_DBLDVX10__ALL_R 0U +#define XHC_DBLDVX10_DATAMASK 0xffffffffU +#define XHC_DBLDVX10_RDWRMASK 0x00000000U +#define XHC_DBLDVX10_RESETVALUE 0x00000000U + +#define XHC_DBLDVX11_OFFSET 0x8ecU +#define XHC_DBLDVX11_BASE 0x8ecU +#define XHC_DBLDVX11__SID_L 31U +#define XHC_DBLDVX11__SID_R 16U +#define XHC_DBLDVX11__SID_WIDTH 16U +#define XHC_DBLDVX11__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX11__reserved_L 15U +#define XHC_DBLDVX11__reserved_R 8U +#define XHC_DBLDVX11__reserved_WIDTH 8U +#define XHC_DBLDVX11__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX11__TGT_L 7U +#define XHC_DBLDVX11__TGT_R 0U +#define XHC_DBLDVX11__TGT_WIDTH 8U +#define XHC_DBLDVX11__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX11_WIDTH 32U +#define XHC_DBLDVX11__WIDTH 32U +#define XHC_DBLDVX11_ALL_L 31U +#define XHC_DBLDVX11_ALL_R 0U +#define XHC_DBLDVX11__ALL_L 31U +#define XHC_DBLDVX11__ALL_R 0U +#define XHC_DBLDVX11_DATAMASK 0xffffffffU +#define XHC_DBLDVX11_RDWRMASK 0x00000000U +#define XHC_DBLDVX11_RESETVALUE 0x00000000U + +#define XHC_DBLDVX12_OFFSET 0x8f0U +#define XHC_DBLDVX12_BASE 0x8f0U +#define XHC_DBLDVX12__SID_L 31U +#define XHC_DBLDVX12__SID_R 16U +#define XHC_DBLDVX12__SID_WIDTH 16U +#define XHC_DBLDVX12__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX12__reserved_L 15U +#define XHC_DBLDVX12__reserved_R 8U +#define XHC_DBLDVX12__reserved_WIDTH 8U +#define XHC_DBLDVX12__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX12__TGT_L 7U +#define XHC_DBLDVX12__TGT_R 0U +#define XHC_DBLDVX12__TGT_WIDTH 8U +#define XHC_DBLDVX12__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX12_WIDTH 32U +#define XHC_DBLDVX12__WIDTH 32U +#define XHC_DBLDVX12_ALL_L 31U +#define XHC_DBLDVX12_ALL_R 0U +#define XHC_DBLDVX12__ALL_L 31U +#define XHC_DBLDVX12__ALL_R 0U +#define XHC_DBLDVX12_DATAMASK 0xffffffffU +#define XHC_DBLDVX12_RDWRMASK 0x00000000U +#define XHC_DBLDVX12_RESETVALUE 0x00000000U + +#define XHC_DBLDVX13_OFFSET 0x8f4U +#define XHC_DBLDVX13_BASE 0x8f4U +#define XHC_DBLDVX13__SID_L 31U +#define XHC_DBLDVX13__SID_R 16U +#define XHC_DBLDVX13__SID_WIDTH 16U +#define XHC_DBLDVX13__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX13__reserved_L 15U +#define XHC_DBLDVX13__reserved_R 8U +#define XHC_DBLDVX13__reserved_WIDTH 8U +#define XHC_DBLDVX13__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX13__TGT_L 7U +#define XHC_DBLDVX13__TGT_R 0U +#define XHC_DBLDVX13__TGT_WIDTH 8U +#define XHC_DBLDVX13__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX13_WIDTH 32U +#define XHC_DBLDVX13__WIDTH 32U +#define XHC_DBLDVX13_ALL_L 31U +#define XHC_DBLDVX13_ALL_R 0U +#define XHC_DBLDVX13__ALL_L 31U +#define XHC_DBLDVX13__ALL_R 0U +#define XHC_DBLDVX13_DATAMASK 0xffffffffU +#define XHC_DBLDVX13_RDWRMASK 0x00000000U +#define XHC_DBLDVX13_RESETVALUE 0x00000000U + +#define XHC_DBLDVX14_OFFSET 0x8f8U +#define XHC_DBLDVX14_BASE 0x8f8U +#define XHC_DBLDVX14__SID_L 31U +#define XHC_DBLDVX14__SID_R 16U +#define XHC_DBLDVX14__SID_WIDTH 16U +#define XHC_DBLDVX14__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX14__reserved_L 15U +#define XHC_DBLDVX14__reserved_R 8U +#define XHC_DBLDVX14__reserved_WIDTH 8U +#define XHC_DBLDVX14__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX14__TGT_L 7U +#define XHC_DBLDVX14__TGT_R 0U +#define XHC_DBLDVX14__TGT_WIDTH 8U +#define XHC_DBLDVX14__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX14_WIDTH 32U +#define XHC_DBLDVX14__WIDTH 32U +#define XHC_DBLDVX14_ALL_L 31U +#define XHC_DBLDVX14_ALL_R 0U +#define XHC_DBLDVX14__ALL_L 31U +#define XHC_DBLDVX14__ALL_R 0U +#define XHC_DBLDVX14_DATAMASK 0xffffffffU +#define XHC_DBLDVX14_RDWRMASK 0x00000000U +#define XHC_DBLDVX14_RESETVALUE 0x00000000U + +#define XHC_DBLDVX15_OFFSET 0x8fcU +#define XHC_DBLDVX15_BASE 0x8fcU +#define XHC_DBLDVX15__SID_L 31U +#define XHC_DBLDVX15__SID_R 16U +#define XHC_DBLDVX15__SID_WIDTH 16U +#define XHC_DBLDVX15__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX15__reserved_L 15U +#define XHC_DBLDVX15__reserved_R 8U +#define XHC_DBLDVX15__reserved_WIDTH 8U +#define XHC_DBLDVX15__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX15__TGT_L 7U +#define XHC_DBLDVX15__TGT_R 0U +#define XHC_DBLDVX15__TGT_WIDTH 8U +#define XHC_DBLDVX15__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX15_WIDTH 32U +#define XHC_DBLDVX15__WIDTH 32U +#define XHC_DBLDVX15_ALL_L 31U +#define XHC_DBLDVX15_ALL_R 0U +#define XHC_DBLDVX15__ALL_L 31U +#define XHC_DBLDVX15__ALL_R 0U +#define XHC_DBLDVX15_DATAMASK 0xffffffffU +#define XHC_DBLDVX15_RDWRMASK 0x00000000U +#define XHC_DBLDVX15_RESETVALUE 0x00000000U + +#define XHC_DBLDVX16_OFFSET 0x900U +#define XHC_DBLDVX16_BASE 0x900U +#define XHC_DBLDVX16__SID_L 31U +#define XHC_DBLDVX16__SID_R 16U +#define XHC_DBLDVX16__SID_WIDTH 16U +#define XHC_DBLDVX16__SID_RESETVALUE 0x0000U +#define XHC_DBLDVX16__reserved_L 15U +#define XHC_DBLDVX16__reserved_R 8U +#define XHC_DBLDVX16__reserved_WIDTH 8U +#define XHC_DBLDVX16__reserved_RESETVALUE 0x00U +#define XHC_DBLDVX16__TGT_L 7U +#define XHC_DBLDVX16__TGT_R 0U +#define XHC_DBLDVX16__TGT_WIDTH 8U +#define XHC_DBLDVX16__TGT_RESETVALUE 0x00U +#define XHC_DBLDVX16_WIDTH 32U +#define XHC_DBLDVX16__WIDTH 32U +#define XHC_DBLDVX16_ALL_L 31U +#define XHC_DBLDVX16_ALL_R 0U +#define XHC_DBLDVX16__ALL_L 31U +#define XHC_DBLDVX16__ALL_R 0U +#define XHC_DBLDVX16_DATAMASK 0xffffffffU +#define XHC_DBLDVX16_RDWRMASK 0x00000000U +#define XHC_DBLDVX16_RESETVALUE 0x00000000U + +#define XHC_ECHSPT3_OFFSET 0x940U +#define XHC_ECHSPT3_BASE 0x940U +#define XHC_ECHSPT3__RMAJ_L 31U +#define XHC_ECHSPT3__RMAJ_R 24U +#define XHC_ECHSPT3__RMAJ_WIDTH 8U +#define XHC_ECHSPT3__RMAJ_RESETVALUE 0x00U +#define XHC_ECHSPT3__RMIN_L 23U +#define XHC_ECHSPT3__RMIN_R 16U +#define XHC_ECHSPT3__RMIN_WIDTH 8U +#define XHC_ECHSPT3__RMIN_RESETVALUE 0x00U +#define XHC_ECHSPT3__NCP_L 15U +#define XHC_ECHSPT3__NCP_R 8U +#define XHC_ECHSPT3__NCP_WIDTH 8U +#define XHC_ECHSPT3__NCP_RESETVALUE 0x00U +#define XHC_ECHSPT3__CID_L 7U +#define XHC_ECHSPT3__CID_R 0U +#define XHC_ECHSPT3__CID_WIDTH 8U +#define XHC_ECHSPT3__CID_RESETVALUE 0x02U +#define XHC_ECHSPT3_WIDTH 32U +#define XHC_ECHSPT3__WIDTH 32U +#define XHC_ECHSPT3_ALL_L 31U +#define XHC_ECHSPT3_ALL_R 0U +#define XHC_ECHSPT3__ALL_L 31U +#define XHC_ECHSPT3__ALL_R 0U +#define XHC_ECHSPT3_DATAMASK 0xffffffffU +#define XHC_ECHSPT3_RDWRMASK 0x00000000U +#define XHC_ECHSPT3_RESETVALUE 0x00000002U + +#define XHC_PNSTR3_OFFSET 0x944U +#define XHC_PNSTR3_BASE 0x944U +#define XHC_PNSTR3__STR_L 31U +#define XHC_PNSTR3__STR_R 0U +#define XHC_PNSTR3__STR_WIDTH 32U +#define XHC_PNSTR3__STR_RESETVALUE 0x20425355U +#define XHC_PNSTR3_WIDTH 32U +#define XHC_PNSTR3__WIDTH 32U +#define XHC_PNSTR3_ALL_L 31U +#define XHC_PNSTR3_ALL_R 0U +#define XHC_PNSTR3__ALL_L 31U +#define XHC_PNSTR3__ALL_R 0U +#define XHC_PNSTR3_DATAMASK 0xffffffffU +#define XHC_PNSTR3_RDWRMASK 0x00000000U +#define XHC_PNSTR3_RESETVALUE 0x20425355U + +#define XHC_PSUM3_OFFSET 0x948U +#define XHC_PSUM3_BASE 0x948U +#define XHC_PSUM3__PSIC_L 31U +#define XHC_PSUM3__PSIC_R 28U +#define XHC_PSUM3__PSIC_WIDTH 4U +#define XHC_PSUM3__PSIC_RESETVALUE 0x0U +#define XHC_PSUM3__MHD_L 27U +#define XHC_PSUM3__MHD_R 25U +#define XHC_PSUM3__MHD_WIDTH 3U +#define XHC_PSUM3__MHD_RESETVALUE 0x0U +#define XHC_PSUM3__BLC 20U +#define XHC_PSUM3__BLC_L 20U +#define XHC_PSUM3__BLC_R 20U +#define XHC_PSUM3__BLC_WIDTH 1U +#define XHC_PSUM3__BLC_RESETVALUE 0x0U +#define XHC_PSUM3__HLC 19U +#define XHC_PSUM3__HLC_L 19U +#define XHC_PSUM3__HLC_R 19U +#define XHC_PSUM3__HLC_WIDTH 1U +#define XHC_PSUM3__HLC_RESETVALUE 0x1U +#define XHC_PSUM3__IHI 18U +#define XHC_PSUM3__IHI_L 18U +#define XHC_PSUM3__IHI_R 18U +#define XHC_PSUM3__IHI_WIDTH 1U +#define XHC_PSUM3__IHI_RESETVALUE 0x0U +#define XHC_PSUM3__HSO 17U +#define XHC_PSUM3__HSO_L 17U +#define XHC_PSUM3__HSO_R 17U +#define XHC_PSUM3__HSO_WIDTH 1U +#define XHC_PSUM3__HSO_RESETVALUE 0x0U +#define XHC_PSUM3__reserved 16U +#define XHC_PSUM3__reserved_L 16U +#define XHC_PSUM3__reserved_R 16U +#define XHC_PSUM3__reserved_WIDTH 1U +#define XHC_PSUM3__reserved_RESETVALUE 0x0U +#define XHC_PSUM3__CPC_L 15U +#define XHC_PSUM3__CPC_R 8U +#define XHC_PSUM3__CPC_WIDTH 8U +#define XHC_PSUM3__CPC_RESETVALUE 0x00U +#define XHC_PSUM3__CPO_L 7U +#define XHC_PSUM3__CPO_R 0U +#define XHC_PSUM3__CPO_WIDTH 8U +#define XHC_PSUM3__CPO_RESETVALUE 0x00U +#define XHC_PSUM3__RESERVED_L 24U +#define XHC_PSUM3__RESERVED_R 21U +#define XHC_PSUM3_WIDTH 32U +#define XHC_PSUM3__WIDTH 32U +#define XHC_PSUM3_ALL_L 31U +#define XHC_PSUM3_ALL_R 0U +#define XHC_PSUM3__ALL_L 31U +#define XHC_PSUM3__ALL_R 0U +#define XHC_PSUM3_DATAMASK 0xfe1fffffU +#define XHC_PSUM3_RDWRMASK 0x01e00000U +#define XHC_PSUM3_RESETVALUE 0x00080000U + +#define XHC_PTSLTYP3_OFFSET 0x94cU +#define XHC_PTSLTYP3_BASE 0x94cU +#define XHC_PTSLTYP3__reserved_L 31U +#define XHC_PTSLTYP3__reserved_R 5U +#define XHC_PTSLTYP3__reserved_WIDTH 27U +#define XHC_PTSLTYP3__reserved_RESETVALUE 0x0U +#define XHC_PTSLTYP3__PST_L 4U +#define XHC_PTSLTYP3__PST_R 0U +#define XHC_PTSLTYP3__PST_WIDTH 5U +#define XHC_PTSLTYP3__PST_RESETVALUE 0x0U +#define XHC_PTSLTYP3_WIDTH 32U +#define XHC_PTSLTYP3__WIDTH 32U +#define XHC_PTSLTYP3_ALL_L 31U +#define XHC_PTSLTYP3_ALL_R 0U +#define XHC_PTSLTYP3__ALL_L 31U +#define XHC_PTSLTYP3__ALL_R 0U +#define XHC_PTSLTYP3_DATAMASK 0xffffffffU +#define XHC_PTSLTYP3_RDWRMASK 0x00000000U +#define XHC_PTSLTYP3_RESETVALUE 0x00000000U + +#define XHC_ECHSPT2_OFFSET 0x950U +#define XHC_ECHSPT2_BASE 0x950U +#define XHC_ECHSPT2__RMAJ_L 31U +#define XHC_ECHSPT2__RMAJ_R 24U +#define XHC_ECHSPT2__RMAJ_WIDTH 8U +#define XHC_ECHSPT2__RMAJ_RESETVALUE 0x00U +#define XHC_ECHSPT2__RMIN_L 23U +#define XHC_ECHSPT2__RMIN_R 16U +#define XHC_ECHSPT2__RMIN_WIDTH 8U +#define XHC_ECHSPT2__RMIN_RESETVALUE 0x00U +#define XHC_ECHSPT2__NCP_L 15U +#define XHC_ECHSPT2__NCP_R 8U +#define XHC_ECHSPT2__NCP_WIDTH 8U +#define XHC_ECHSPT2__NCP_RESETVALUE 0x00U +#define XHC_ECHSPT2__CID_L 7U +#define XHC_ECHSPT2__CID_R 0U +#define XHC_ECHSPT2__CID_WIDTH 8U +#define XHC_ECHSPT2__CID_RESETVALUE 0x02U +#define XHC_ECHSPT2_WIDTH 32U +#define XHC_ECHSPT2__WIDTH 32U +#define XHC_ECHSPT2_ALL_L 31U +#define XHC_ECHSPT2_ALL_R 0U +#define XHC_ECHSPT2__ALL_L 31U +#define XHC_ECHSPT2__ALL_R 0U +#define XHC_ECHSPT2_DATAMASK 0xffffffffU +#define XHC_ECHSPT2_RDWRMASK 0x00000000U +#define XHC_ECHSPT2_RESETVALUE 0x00000002U + +#define XHC_PNSTR2_OFFSET 0x954U +#define XHC_PNSTR2_BASE 0x954U +#define XHC_PNSTR2__STR_L 31U +#define XHC_PNSTR2__STR_R 0U +#define XHC_PNSTR2__STR_WIDTH 32U +#define XHC_PNSTR2__STR_RESETVALUE 0x20425355U +#define XHC_PNSTR2_WIDTH 32U +#define XHC_PNSTR2__WIDTH 32U +#define XHC_PNSTR2_ALL_L 31U +#define XHC_PNSTR2_ALL_R 0U +#define XHC_PNSTR2__ALL_L 31U +#define XHC_PNSTR2__ALL_R 0U +#define XHC_PNSTR2_DATAMASK 0xffffffffU +#define XHC_PNSTR2_RDWRMASK 0x00000000U +#define XHC_PNSTR2_RESETVALUE 0x20425355U + +#define XHC_PSUM2_OFFSET 0x958U +#define XHC_PSUM2_BASE 0x958U +#define XHC_PSUM2__PSIC_L 31U +#define XHC_PSUM2__PSIC_R 28U +#define XHC_PSUM2__PSIC_WIDTH 4U +#define XHC_PSUM2__PSIC_RESETVALUE 0x0U +#define XHC_PSUM2__MHD_L 27U +#define XHC_PSUM2__MHD_R 25U +#define XHC_PSUM2__MHD_WIDTH 3U +#define XHC_PSUM2__MHD_RESETVALUE 0x0U +#define XHC_PSUM2__BLC 20U +#define XHC_PSUM2__BLC_L 20U +#define XHC_PSUM2__BLC_R 20U +#define XHC_PSUM2__BLC_WIDTH 1U +#define XHC_PSUM2__BLC_RESETVALUE 0x0U +#define XHC_PSUM2__HLC 19U +#define XHC_PSUM2__HLC_L 19U +#define XHC_PSUM2__HLC_R 19U +#define XHC_PSUM2__HLC_WIDTH 1U +#define XHC_PSUM2__HLC_RESETVALUE 0x1U +#define XHC_PSUM2__IHI 18U +#define XHC_PSUM2__IHI_L 18U +#define XHC_PSUM2__IHI_R 18U +#define XHC_PSUM2__IHI_WIDTH 1U +#define XHC_PSUM2__IHI_RESETVALUE 0x0U +#define XHC_PSUM2__HSO 17U +#define XHC_PSUM2__HSO_L 17U +#define XHC_PSUM2__HSO_R 17U +#define XHC_PSUM2__HSO_WIDTH 1U +#define XHC_PSUM2__HSO_RESETVALUE 0x0U +#define XHC_PSUM2__reserved 16U +#define XHC_PSUM2__reserved_L 16U +#define XHC_PSUM2__reserved_R 16U +#define XHC_PSUM2__reserved_WIDTH 1U +#define XHC_PSUM2__reserved_RESETVALUE 0x0U +#define XHC_PSUM2__CPC_L 15U +#define XHC_PSUM2__CPC_R 8U +#define XHC_PSUM2__CPC_WIDTH 8U +#define XHC_PSUM2__CPC_RESETVALUE 0x00U +#define XHC_PSUM2__CPO_L 7U +#define XHC_PSUM2__CPO_R 0U +#define XHC_PSUM2__CPO_WIDTH 8U +#define XHC_PSUM2__CPO_RESETVALUE 0x00U +#define XHC_PSUM2__RESERVED_L 24U +#define XHC_PSUM2__RESERVED_R 21U +#define XHC_PSUM2_WIDTH 32U +#define XHC_PSUM2__WIDTH 32U +#define XHC_PSUM2_ALL_L 31U +#define XHC_PSUM2_ALL_R 0U +#define XHC_PSUM2__ALL_L 31U +#define XHC_PSUM2__ALL_R 0U +#define XHC_PSUM2_DATAMASK 0xfe1fffffU +#define XHC_PSUM2_RDWRMASK 0x01e00000U +#define XHC_PSUM2_RESETVALUE 0x00080000U + +#define XHC_PTSLTYP2_OFFSET 0x95cU +#define XHC_PTSLTYP2_BASE 0x95cU +#define XHC_PTSLTYP2__reserved_L 31U +#define XHC_PTSLTYP2__reserved_R 5U +#define XHC_PTSLTYP2__reserved_WIDTH 27U +#define XHC_PTSLTYP2__reserved_RESETVALUE 0x0U +#define XHC_PTSLTYP2__PST_L 4U +#define XHC_PTSLTYP2__PST_R 0U +#define XHC_PTSLTYP2__PST_WIDTH 5U +#define XHC_PTSLTYP2__PST_RESETVALUE 0x0U +#define XHC_PTSLTYP2_WIDTH 32U +#define XHC_PTSLTYP2__WIDTH 32U +#define XHC_PTSLTYP2_ALL_L 31U +#define XHC_PTSLTYP2_ALL_R 0U +#define XHC_PTSLTYP2__ALL_L 31U +#define XHC_PTSLTYP2__ALL_R 0U +#define XHC_PTSLTYP2_DATAMASK 0xffffffffU +#define XHC_PTSLTYP2_RDWRMASK 0x00000000U +#define XHC_PTSLTYP2_RESETVALUE 0x00000000U + +#define XHC_ECHRSVP_OFFSET 0x960U +#define XHC_ECHRSVP_BASE 0x960U +#define XHC_ECHRSVP__reserved_L 31U +#define XHC_ECHRSVP__reserved_R 16U +#define XHC_ECHRSVP__reserved_WIDTH 16U +#define XHC_ECHRSVP__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVP__NCP_L 15U +#define XHC_ECHRSVP__NCP_R 8U +#define XHC_ECHRSVP__NCP_WIDTH 8U +#define XHC_ECHRSVP__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVP__CID_L 7U +#define XHC_ECHRSVP__CID_R 0U +#define XHC_ECHRSVP__CID_WIDTH 8U +#define XHC_ECHRSVP__CID_RESETVALUE 0xffU +#define XHC_ECHRSVP_WIDTH 32U +#define XHC_ECHRSVP__WIDTH 32U +#define XHC_ECHRSVP_ALL_L 31U +#define XHC_ECHRSVP_ALL_R 0U +#define XHC_ECHRSVP__ALL_L 31U +#define XHC_ECHRSVP__ALL_R 0U +#define XHC_ECHRSVP_DATAMASK 0xffffffffU +#define XHC_ECHRSVP_RDWRMASK 0x00000000U +#define XHC_ECHRSVP_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVI_OFFSET 0x968U +#define XHC_ECHRSVI_BASE 0x968U +#define XHC_ECHRSVI__reserved_L 31U +#define XHC_ECHRSVI__reserved_R 16U +#define XHC_ECHRSVI__reserved_WIDTH 16U +#define XHC_ECHRSVI__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVI__NCP_L 15U +#define XHC_ECHRSVI__NCP_R 8U +#define XHC_ECHRSVI__NCP_WIDTH 8U +#define XHC_ECHRSVI__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVI__CID_L 7U +#define XHC_ECHRSVI__CID_R 0U +#define XHC_ECHRSVI__CID_WIDTH 8U +#define XHC_ECHRSVI__CID_RESETVALUE 0xffU +#define XHC_ECHRSVI_WIDTH 32U +#define XHC_ECHRSVI__WIDTH 32U +#define XHC_ECHRSVI_ALL_L 31U +#define XHC_ECHRSVI_ALL_R 0U +#define XHC_ECHRSVI__ALL_L 31U +#define XHC_ECHRSVI__ALL_R 0U +#define XHC_ECHRSVI_DATAMASK 0xffffffffU +#define XHC_ECHRSVI_RDWRMASK 0x00000000U +#define XHC_ECHRSVI_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVM_OFFSET 0xae8U +#define XHC_ECHRSVM_BASE 0xae8U +#define XHC_ECHRSVM__reserved_L 31U +#define XHC_ECHRSVM__reserved_R 16U +#define XHC_ECHRSVM__reserved_WIDTH 16U +#define XHC_ECHRSVM__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVM__NCP_L 15U +#define XHC_ECHRSVM__NCP_R 8U +#define XHC_ECHRSVM__NCP_WIDTH 8U +#define XHC_ECHRSVM__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVM__CID_L 7U +#define XHC_ECHRSVM__CID_R 0U +#define XHC_ECHRSVM__CID_WIDTH 8U +#define XHC_ECHRSVM__CID_RESETVALUE 0xffU +#define XHC_ECHRSVM_WIDTH 32U +#define XHC_ECHRSVM__WIDTH 32U +#define XHC_ECHRSVM_ALL_L 31U +#define XHC_ECHRSVM_ALL_R 0U +#define XHC_ECHRSVM__ALL_L 31U +#define XHC_ECHRSVM__ALL_R 0U +#define XHC_ECHRSVM_DATAMASK 0xffffffffU +#define XHC_ECHRSVM_RDWRMASK 0x00000000U +#define XHC_ECHRSVM_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVD_OFFSET 0xaf8U +#define XHC_ECHRSVD_BASE 0xaf8U +#define XHC_ECHRSVD__reserved_L 31U +#define XHC_ECHRSVD__reserved_R 16U +#define XHC_ECHRSVD__reserved_WIDTH 16U +#define XHC_ECHRSVD__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVD__NCP_L 15U +#define XHC_ECHRSVD__NCP_R 8U +#define XHC_ECHRSVD__NCP_WIDTH 8U +#define XHC_ECHRSVD__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVD__CID_L 7U +#define XHC_ECHRSVD__CID_R 0U +#define XHC_ECHRSVD__CID_WIDTH 8U +#define XHC_ECHRSVD__CID_RESETVALUE 0xffU +#define XHC_ECHRSVD_WIDTH 32U +#define XHC_ECHRSVD__WIDTH 32U +#define XHC_ECHRSVD_ALL_L 31U +#define XHC_ECHRSVD_ALL_R 0U +#define XHC_ECHRSVD__ALL_L 31U +#define XHC_ECHRSVD__ALL_R 0U +#define XHC_ECHRSVD_DATAMASK 0xffffffffU +#define XHC_ECHRSVD_RDWRMASK 0x00000000U +#define XHC_ECHRSVD_RESETVALUE 0x000000ffU + +#define XHC_ECHRSVO_OFFSET 0xb38U +#define XHC_ECHRSVO_BASE 0xb38U +#define XHC_ECHRSVO__reserved_L 31U +#define XHC_ECHRSVO__reserved_R 16U +#define XHC_ECHRSVO__reserved_WIDTH 16U +#define XHC_ECHRSVO__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSVO__NCP_L 15U +#define XHC_ECHRSVO__NCP_R 8U +#define XHC_ECHRSVO__NCP_WIDTH 8U +#define XHC_ECHRSVO__NCP_RESETVALUE 0x00U +#define XHC_ECHRSVO__CID_L 7U +#define XHC_ECHRSVO__CID_R 0U +#define XHC_ECHRSVO__CID_WIDTH 8U +#define XHC_ECHRSVO__CID_RESETVALUE 0xffU +#define XHC_ECHRSVO_WIDTH 32U +#define XHC_ECHRSVO__WIDTH 32U +#define XHC_ECHRSVO_ALL_L 31U +#define XHC_ECHRSVO_ALL_R 0U +#define XHC_ECHRSVO__ALL_L 31U +#define XHC_ECHRSVO__ALL_R 0U +#define XHC_ECHRSVO_DATAMASK 0xffffffffU +#define XHC_ECHRSVO_RDWRMASK 0x00000000U +#define XHC_ECHRSVO_RESETVALUE 0x000000ffU + +#define XHC_ECHCTT_OFFSET 0xbf0U +#define XHC_ECHCTT_BASE 0xbf0U +#define XHC_ECHCTT__reserved_L 31U +#define XHC_ECHCTT__reserved_R 16U +#define XHC_ECHCTT__reserved_WIDTH 16U +#define XHC_ECHCTT__reserved_RESETVALUE 0x0000U +#define XHC_ECHCTT__NCP_L 15U +#define XHC_ECHCTT__NCP_R 8U +#define XHC_ECHCTT__NCP_WIDTH 8U +#define XHC_ECHCTT__NCP_RESETVALUE 0x04U +#define XHC_ECHCTT__CID_L 7U +#define XHC_ECHCTT__CID_R 0U +#define XHC_ECHCTT__CID_WIDTH 8U +#define XHC_ECHCTT__CID_RESETVALUE 0xe0U +#define XHC_ECHCTT_WIDTH 32U +#define XHC_ECHCTT__WIDTH 32U +#define XHC_ECHCTT_ALL_L 31U +#define XHC_ECHCTT_ALL_R 0U +#define XHC_ECHCTT__ALL_L 31U +#define XHC_ECHCTT__ALL_R 0U +#define XHC_ECHCTT_DATAMASK 0xffffffffU +#define XHC_ECHCTT_RDWRMASK 0x00000000U +#define XHC_ECHCTT_RESETVALUE 0x000004e0U + +#define XHC_CTTMTS0_OFFSET 0xbf8U +#define XHC_CTTMTS0_BASE 0xbf8U +#define XHC_CTTMTS0__DCM 31U +#define XHC_CTTMTS0__DCM_L 31U +#define XHC_CTTMTS0__DCM_R 31U +#define XHC_CTTMTS0__DCM_WIDTH 1U +#define XHC_CTTMTS0__DCM_RESETVALUE 0x0U +#define XHC_CTTMTS0__reserved_L 30U +#define XHC_CTTMTS0__reserved_R 10U +#define XHC_CTTMTS0__reserved_WIDTH 21U +#define XHC_CTTMTS0__reserved_RESETVALUE 0x0U +#define XHC_CTTMTS0__SLA_L 9U +#define XHC_CTTMTS0__SLA_R 0U +#define XHC_CTTMTS0__SLA_WIDTH 10U +#define XHC_CTTMTS0__SLA_RESETVALUE 0x0U +#define XHC_CTTMTS0_WIDTH 32U +#define XHC_CTTMTS0__WIDTH 32U +#define XHC_CTTMTS0_ALL_L 31U +#define XHC_CTTMTS0_ALL_R 0U +#define XHC_CTTMTS0__ALL_L 31U +#define XHC_CTTMTS0__ALL_R 0U +#define XHC_CTTMTS0_DATAMASK 0xffffffffU +#define XHC_CTTMTS0_RDWRMASK 0x00000000U +#define XHC_CTTMTS0_RESETVALUE 0x00000000U + +#define XHC_CTTMTS1_OFFSET 0xbfcU +#define XHC_CTTMTS1_BASE 0xbfcU +#define XHC_CTTMTS1__TXF_L 25U +#define XHC_CTTMTS1__TXF_R 16U +#define XHC_CTTMTS1__TXF_WIDTH 10U +#define XHC_CTTMTS1__TXF_RESETVALUE 0x0U +#define XHC_CTTMTS1__reserved_L 15U +#define XHC_CTTMTS1__reserved_R 10U +#define XHC_CTTMTS1__reserved_WIDTH 6U +#define XHC_CTTMTS1__reserved_RESETVALUE 0x0U +#define XHC_CTTMTS1__RXF_L 9U +#define XHC_CTTMTS1__RXF_R 0U +#define XHC_CTTMTS1__RXF_WIDTH 10U +#define XHC_CTTMTS1__RXF_RESETVALUE 0x0U +#define XHC_CTTMTS1__RESERVED_L 31U +#define XHC_CTTMTS1__RESERVED_R 26U +#define XHC_CTTMTS1_WIDTH 26U +#define XHC_CTTMTS1__WIDTH 26U +#define XHC_CTTMTS1_ALL_L 25U +#define XHC_CTTMTS1_ALL_R 0U +#define XHC_CTTMTS1__ALL_L 25U +#define XHC_CTTMTS1__ALL_R 0U +#define XHC_CTTMTS1_DATAMASK 0x03ffffffU +#define XHC_CTTMTS1_RDWRMASK 0xfc000000U +#define XHC_CTTMTS1_RESETVALUE 0x0000000U + +#define XHC_ECHBIU_OFFSET 0xc00U +#define XHC_ECHBIU_BASE 0xc00U +#define XHC_ECHBIU__CLK_L 31U +#define XHC_ECHBIU__CLK_R 21U +#define XHC_ECHBIU__CLK_WIDTH 11U +#define XHC_ECHBIU__CLK_RESETVALUE 0x0U +#define XHC_ECHBIU__reserved_L 20U +#define XHC_ECHBIU__reserved_R 19U +#define XHC_ECHBIU__reserved_WIDTH 2U +#define XHC_ECHBIU__reserved_RESETVALUE 0x0U +#define XHC_ECHBIU__WID_L 18U +#define XHC_ECHBIU__WID_R 16U +#define XHC_ECHBIU__WID_WIDTH 3U +#define XHC_ECHBIU__WID_RESETVALUE 0x0U +#define XHC_ECHBIU__NCP_L 15U +#define XHC_ECHBIU__NCP_R 8U +#define XHC_ECHBIU__NCP_WIDTH 8U +#define XHC_ECHBIU__NCP_RESETVALUE 0x08U +#define XHC_ECHBIU__CID_L 7U +#define XHC_ECHBIU__CID_R 0U +#define XHC_ECHBIU__CID_WIDTH 8U +#define XHC_ECHBIU__CID_RESETVALUE 0xc0U +#define XHC_ECHBIU_WIDTH 32U +#define XHC_ECHBIU__WIDTH 32U +#define XHC_ECHBIU_ALL_L 31U +#define XHC_ECHBIU_ALL_R 0U +#define XHC_ECHBIU__ALL_L 31U +#define XHC_ECHBIU__ALL_R 0U +#define XHC_ECHBIU_DATAMASK 0xffffffffU +#define XHC_ECHBIU_RDWRMASK 0x00000000U +#define XHC_ECHBIU_RESETVALUE 0x000008c0U + +#define XHC_BIUSPC_OFFSET 0xc04U +#define XHC_BIUSPC_BASE 0xc04U +#define XHC_BIUSPC__MAJ_L 31U +#define XHC_BIUSPC__MAJ_R 28U +#define XHC_BIUSPC__MAJ_WIDTH 4U +#define XHC_BIUSPC__MAJ_RESETVALUE 0x0U +#define XHC_BIUSPC__MIN_L 27U +#define XHC_BIUSPC__MIN_R 24U +#define XHC_BIUSPC__MIN_WIDTH 4U +#define XHC_BIUSPC__MIN_RESETVALUE 0x0U +#define XHC_BIUSPC__RLS_L 23U +#define XHC_BIUSPC__RLS_R 20U +#define XHC_BIUSPC__RLS_WIDTH 4U +#define XHC_BIUSPC__RLS_RESETVALUE 0x0U +#define XHC_BIUSPC__reserved_L 19U +#define XHC_BIUSPC__reserved_R 4U +#define XHC_BIUSPC__reserved_WIDTH 16U +#define XHC_BIUSPC__reserved_RESETVALUE 0x0000U +#define XHC_BIUSPC__SPI_L 3U +#define XHC_BIUSPC__SPI_R 2U +#define XHC_BIUSPC__SPI_WIDTH 2U +#define XHC_BIUSPC__SPI_RESETVALUE 0x3U +#define XHC_BIUSPC__TYP_L 1U +#define XHC_BIUSPC__TYP_R 0U +#define XHC_BIUSPC__TYP_WIDTH 2U +#define XHC_BIUSPC__TYP_RESETVALUE 0x0U +#define XHC_BIUSPC_WIDTH 32U +#define XHC_BIUSPC__WIDTH 32U +#define XHC_BIUSPC_ALL_L 31U +#define XHC_BIUSPC_ALL_R 0U +#define XHC_BIUSPC__ALL_L 31U +#define XHC_BIUSPC__ALL_R 0U +#define XHC_BIUSPC_DATAMASK 0xffffffffU +#define XHC_BIUSPC_RDWRMASK 0x00000000U +#define XHC_BIUSPC_RESETVALUE 0x0000000cU + +#define XHC_AXIWRA_OFFSET 0xc08U +#define XHC_AXIWRA_BASE 0xc08U +#define XHC_AXIWRA__WTS_L 31U +#define XHC_AXIWRA__WTS_R 28U +#define XHC_AXIWRA__WTS_WIDTH 4U +#define XHC_AXIWRA__WTS_RESETVALUE 0x2U +#define XHC_AXIWRA__WUA_L 24U +#define XHC_AXIWRA__WUA_R 16U +#define XHC_AXIWRA__WUA_WIDTH 9U +#define XHC_AXIWRA__WUA_RESETVALUE 0x0U +#define XHC_AXIWRA__reserved_L 15U +#define XHC_AXIWRA__reserved_R 10U +#define XHC_AXIWRA__reserved_WIDTH 6U +#define XHC_AXIWRA__reserved_RESETVALUE 0x0U +#define XHC_AXIWRA__BYP 9U +#define XHC_AXIWRA__BYP_L 9U +#define XHC_AXIWRA__BYP_R 9U +#define XHC_AXIWRA__BYP_WIDTH 1U +#define XHC_AXIWRA__BYP_RESETVALUE 0x0U +#define XHC_AXIWRA__WSA_L 8U +#define XHC_AXIWRA__WSA_R 0U +#define XHC_AXIWRA__WSA_WIDTH 9U +#define XHC_AXIWRA__WSA_RESETVALUE 0x0U +#define XHC_AXIWRA__RESERVED_L 27U +#define XHC_AXIWRA__RESERVED_R 25U +#define XHC_AXIWRA_WIDTH 32U +#define XHC_AXIWRA__WIDTH 32U +#define XHC_AXIWRA_ALL_L 31U +#define XHC_AXIWRA_ALL_R 0U +#define XHC_AXIWRA__ALL_L 31U +#define XHC_AXIWRA__ALL_R 0U +#define XHC_AXIWRA_DATAMASK 0xf1ffffffU +#define XHC_AXIWRA_RDWRMASK 0x0e000000U +#define XHC_AXIWRA_RESETVALUE 0x20000000U + +#define XHC_AXIRDA_OFFSET 0xc0cU +#define XHC_AXIRDA_BASE 0xc0cU +#define XHC_AXIRDA__RTS_L 31U +#define XHC_AXIRDA__RTS_R 28U +#define XHC_AXIRDA__RTS_WIDTH 4U +#define XHC_AXIRDA__RTS_RESETVALUE 0x2U +#define XHC_AXIRDA__RFPC 27U +#define XHC_AXIRDA__RFPC_L 27U +#define XHC_AXIRDA__RFPC_R 27U +#define XHC_AXIRDA__RFPC_WIDTH 1U +#define XHC_AXIRDA__RFPC_RESETVALUE 0x0U +#define XHC_AXIRDA__RUA_L 24U +#define XHC_AXIRDA__RUA_R 16U +#define XHC_AXIRDA__RUA_WIDTH 9U +#define XHC_AXIRDA__RUA_RESETVALUE 0x0U +#define XHC_AXIRDA__reserved_L 15U +#define XHC_AXIRDA__reserved_R 9U +#define XHC_AXIRDA__reserved_WIDTH 7U +#define XHC_AXIRDA__reserved_RESETVALUE 0x0U +#define XHC_AXIRDA__RSA_L 8U +#define XHC_AXIRDA__RSA_R 0U +#define XHC_AXIRDA__RSA_WIDTH 9U +#define XHC_AXIRDA__RSA_RESETVALUE 0x0U +#define XHC_AXIRDA__RESERVED_L 26U +#define XHC_AXIRDA__RESERVED_R 25U +#define XHC_AXIRDA_WIDTH 32U +#define XHC_AXIRDA__WIDTH 32U +#define XHC_AXIRDA_ALL_L 31U +#define XHC_AXIRDA_ALL_R 0U +#define XHC_AXIRDA__ALL_L 31U +#define XHC_AXIRDA__ALL_R 0U +#define XHC_AXIRDA_DATAMASK 0xf9ffffffU +#define XHC_AXIRDA_RDWRMASK 0x06000000U +#define XHC_AXIRDA_RESETVALUE 0x20000000U + +#define XHC_AXILPM_OFFSET 0xc10U +#define XHC_AXILPM_BASE 0xc10U +#define XHC_AXILPM__ENB 31U +#define XHC_AXILPM__ENB_L 31U +#define XHC_AXILPM__ENB_R 31U +#define XHC_AXILPM__ENB_WIDTH 1U +#define XHC_AXILPM__ENB_RESETVALUE 0x0U +#define XHC_AXILPM__reserved_L 30U +#define XHC_AXILPM__reserved_R 3U +#define XHC_AXILPM__reserved_WIDTH 28U +#define XHC_AXILPM__reserved_RESETVALUE 0x0000000U +#define XHC_AXILPM__ITT_L 2U +#define XHC_AXILPM__ITT_R 0U +#define XHC_AXILPM__ITT_WIDTH 3U +#define XHC_AXILPM__ITT_RESETVALUE 0x0U +#define XHC_AXILPM_WIDTH 32U +#define XHC_AXILPM__WIDTH 32U +#define XHC_AXILPM_ALL_L 31U +#define XHC_AXILPM_ALL_R 0U +#define XHC_AXILPM__ALL_L 31U +#define XHC_AXILPM__ALL_R 0U +#define XHC_AXILPM_DATAMASK 0xffffffffU +#define XHC_AXILPM_RDWRMASK 0x00000000U +#define XHC_AXILPM_RESETVALUE 0x00000000U + +#define XHC_AXIQOS_OFFSET 0xc14U +#define XHC_AXIQOS_BASE 0xc14U +#define XHC_AXIQOS__WQOS3_L 31U +#define XHC_AXIQOS__WQOS3_R 28U +#define XHC_AXIQOS__WQOS3_WIDTH 4U +#define XHC_AXIQOS__WQOS3_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS2_L 27U +#define XHC_AXIQOS__WQOS2_R 24U +#define XHC_AXIQOS__WQOS2_WIDTH 4U +#define XHC_AXIQOS__WQOS2_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS1_L 23U +#define XHC_AXIQOS__WQOS1_R 20U +#define XHC_AXIQOS__WQOS1_WIDTH 4U +#define XHC_AXIQOS__WQOS1_RESETVALUE 0x0U +#define XHC_AXIQOS__WQOS0_L 19U +#define XHC_AXIQOS__WQOS0_R 16U +#define XHC_AXIQOS__WQOS0_WIDTH 4U +#define XHC_AXIQOS__WQOS0_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS3_L 15U +#define XHC_AXIQOS__RQOS3_R 12U +#define XHC_AXIQOS__RQOS3_WIDTH 4U +#define XHC_AXIQOS__RQOS3_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS2_L 11U +#define XHC_AXIQOS__RQOS2_R 8U +#define XHC_AXIQOS__RQOS2_WIDTH 4U +#define XHC_AXIQOS__RQOS2_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS1_L 7U +#define XHC_AXIQOS__RQOS1_R 4U +#define XHC_AXIQOS__RQOS1_WIDTH 4U +#define XHC_AXIQOS__RQOS1_RESETVALUE 0x0U +#define XHC_AXIQOS__RQOS0_L 3U +#define XHC_AXIQOS__RQOS0_R 0U +#define XHC_AXIQOS__RQOS0_WIDTH 4U +#define XHC_AXIQOS__RQOS0_RESETVALUE 0x0U +#define XHC_AXIQOS_WIDTH 32U +#define XHC_AXIQOS__WIDTH 32U +#define XHC_AXIQOS_ALL_L 31U +#define XHC_AXIQOS_ALL_R 0U +#define XHC_AXIQOS__ALL_L 31U +#define XHC_AXIQOS__ALL_R 0U +#define XHC_AXIQOS_DATAMASK 0xffffffffU +#define XHC_AXIQOS_RDWRMASK 0x00000000U +#define XHC_AXIQOS_RESETVALUE 0x00000000U + +#define XHC_ECHCSR_OFFSET 0xc20U +#define XHC_ECHCSR_BASE 0xc20U +#define XHC_ECHCSR__CLK_L 31U +#define XHC_ECHCSR__CLK_R 21U +#define XHC_ECHCSR__CLK_WIDTH 11U +#define XHC_ECHCSR__CLK_RESETVALUE 0x0U +#define XHC_ECHCSR__reserved_L 20U +#define XHC_ECHCSR__reserved_R 19U +#define XHC_ECHCSR__reserved_WIDTH 2U +#define XHC_ECHCSR__reserved_RESETVALUE 0x0U +#define XHC_ECHCSR__WID_L 18U +#define XHC_ECHCSR__WID_R 16U +#define XHC_ECHCSR__WID_WIDTH 3U +#define XHC_ECHCSR__WID_RESETVALUE 0x0U +#define XHC_ECHCSR__NCP_L 15U +#define XHC_ECHCSR__NCP_R 8U +#define XHC_ECHCSR__NCP_WIDTH 8U +#define XHC_ECHCSR__NCP_RESETVALUE 0x04U +#define XHC_ECHCSR__CID_L 7U +#define XHC_ECHCSR__CID_R 0U +#define XHC_ECHCSR__CID_WIDTH 8U +#define XHC_ECHCSR__CID_RESETVALUE 0xc1U +#define XHC_ECHCSR_WIDTH 32U +#define XHC_ECHCSR__WIDTH 32U +#define XHC_ECHCSR_ALL_L 31U +#define XHC_ECHCSR_ALL_R 0U +#define XHC_ECHCSR__ALL_L 31U +#define XHC_ECHCSR__ALL_R 0U +#define XHC_ECHCSR_DATAMASK 0xffffffffU +#define XHC_ECHCSR_RDWRMASK 0x00000000U +#define XHC_ECHCSR_RESETVALUE 0x000004c1U + +#define XHC_CSRSPC_OFFSET 0xc24U +#define XHC_CSRSPC_BASE 0xc24U +#define XHC_CSRSPC__MAJ_L 31U +#define XHC_CSRSPC__MAJ_R 28U +#define XHC_CSRSPC__MAJ_WIDTH 4U +#define XHC_CSRSPC__MAJ_RESETVALUE 0x0U +#define XHC_CSRSPC__MIN_L 27U +#define XHC_CSRSPC__MIN_R 24U +#define XHC_CSRSPC__MIN_WIDTH 4U +#define XHC_CSRSPC__MIN_RESETVALUE 0x0U +#define XHC_CSRSPC__RLS_L 23U +#define XHC_CSRSPC__RLS_R 20U +#define XHC_CSRSPC__RLS_WIDTH 4U +#define XHC_CSRSPC__RLS_RESETVALUE 0x0U +#define XHC_CSRSPC__reserved_L 19U +#define XHC_CSRSPC__reserved_R 3U +#define XHC_CSRSPC__reserved_WIDTH 17U +#define XHC_CSRSPC__reserved_RESETVALUE 0x0U +#define XHC_CSRSPC__ASP 2U +#define XHC_CSRSPC__ASP_L 2U +#define XHC_CSRSPC__ASP_R 2U +#define XHC_CSRSPC__ASP_WIDTH 1U +#define XHC_CSRSPC__ASP_RESETVALUE 0x0U +#define XHC_CSRSPC__TYP_L 1U +#define XHC_CSRSPC__TYP_R 0U +#define XHC_CSRSPC__TYP_WIDTH 2U +#define XHC_CSRSPC__TYP_RESETVALUE 0x0U +#define XHC_CSRSPC_WIDTH 32U +#define XHC_CSRSPC__WIDTH 32U +#define XHC_CSRSPC_ALL_L 31U +#define XHC_CSRSPC_ALL_R 0U +#define XHC_CSRSPC__ALL_L 31U +#define XHC_CSRSPC__ALL_R 0U +#define XHC_CSRSPC_DATAMASK 0xffffffffU +#define XHC_CSRSPC_RDWRMASK 0x00000000U +#define XHC_CSRSPC_RESETVALUE 0x00000000U + +#define XHC_ECHAIU_OFFSET 0xc30U +#define XHC_ECHAIU_BASE 0xc30U +#define XHC_ECHAIU__DMA_L 31U +#define XHC_ECHAIU__DMA_R 30U +#define XHC_ECHAIU__DMA_WIDTH 2U +#define XHC_ECHAIU__DMA_RESETVALUE 0x1U +#define XHC_ECHAIU__PBRS_L 29U +#define XHC_ECHAIU__PBRS_R 28U +#define XHC_ECHAIU__PBRS_WIDTH 2U +#define XHC_ECHAIU__PBRS_RESETVALUE 0x0U +#define XHC_ECHAIU__PBR2_L 27U +#define XHC_ECHAIU__PBR2_R 26U +#define XHC_ECHAIU__PBR2_WIDTH 2U +#define XHC_ECHAIU__PBR2_RESETVALUE 0x0U +#define XHC_ECHAIU__SCHS_L 25U +#define XHC_ECHAIU__SCHS_R 24U +#define XHC_ECHAIU__SCHS_WIDTH 2U +#define XHC_ECHAIU__SCHS_RESETVALUE 0x0U +#define XHC_ECHAIU__SCH2_L 23U +#define XHC_ECHAIU__SCH2_R 22U +#define XHC_ECHAIU__SCH2_WIDTH 2U +#define XHC_ECHAIU__SCH2_RESETVALUE 0x0U +#define XHC_ECHAIU__CHMS_L 21U +#define XHC_ECHAIU__CHMS_R 20U +#define XHC_ECHAIU__CHMS_WIDTH 2U +#define XHC_ECHAIU__CHMS_RESETVALUE 0x3U +#define XHC_ECHAIU__CHM2_L 19U +#define XHC_ECHAIU__CHM2_R 18U +#define XHC_ECHAIU__CHM2_WIDTH 2U +#define XHC_ECHAIU__CHM2_RESETVALUE 0x0U +#define XHC_ECHAIU__reserved_L 17U +#define XHC_ECHAIU__reserved_R 16U +#define XHC_ECHAIU__reserved_WIDTH 2U +#define XHC_ECHAIU__reserved_RESETVALUE 0x0U +#define XHC_ECHAIU__NCP_L 15U +#define XHC_ECHAIU__NCP_R 8U +#define XHC_ECHAIU__NCP_WIDTH 8U +#define XHC_ECHAIU__NCP_RESETVALUE 0x04U +#define XHC_ECHAIU__CID_L 7U +#define XHC_ECHAIU__CID_R 0U +#define XHC_ECHAIU__CID_WIDTH 8U +#define XHC_ECHAIU__CID_RESETVALUE 0xc2U +#define XHC_ECHAIU_WIDTH 32U +#define XHC_ECHAIU__WIDTH 32U +#define XHC_ECHAIU_ALL_L 31U +#define XHC_ECHAIU_ALL_R 0U +#define XHC_ECHAIU__ALL_L 31U +#define XHC_ECHAIU__ALL_R 0U +#define XHC_ECHAIU_DATAMASK 0xffffffffU +#define XHC_ECHAIU_RDWRMASK 0x00000000U +#define XHC_ECHAIU_RESETVALUE 0x403004c2U + +#define XHC_AIUDMA_OFFSET 0xc34U +#define XHC_AIUDMA_BASE 0xc34U +#define XHC_AIUDMA__WRMB_L 31U +#define XHC_AIUDMA__WRMB_R 28U +#define XHC_AIUDMA__WRMB_WIDTH 4U +#define XHC_AIUDMA__WRMB_RESETVALUE 0x0U +#define XHC_AIUDMA__WRD_L 27U +#define XHC_AIUDMA__WRD_R 26U +#define XHC_AIUDMA__WRD_WIDTH 2U +#define XHC_AIUDMA__WRD_RESETVALUE 0x0U +#define XHC_AIUDMA__WED_L 25U +#define XHC_AIUDMA__WED_R 24U +#define XHC_AIUDMA__WED_WIDTH 2U +#define XHC_AIUDMA__WED_RESETVALUE 0x0U +#define XHC_AIUDMA__WMS_L 23U +#define XHC_AIUDMA__WMS_R 22U +#define XHC_AIUDMA__WMS_WIDTH 2U +#define XHC_AIUDMA__WMS_RESETVALUE 0x0U +#define XHC_AIUDMA__WMI_L 21U +#define XHC_AIUDMA__WMI_R 20U +#define XHC_AIUDMA__WMI_WIDTH 2U +#define XHC_AIUDMA__WMI_RESETVALUE 0x0U +#define XHC_AIUDMA__WPF_L 19U +#define XHC_AIUDMA__WPF_R 16U +#define XHC_AIUDMA__WPF_WIDTH 4U +#define XHC_AIUDMA__WPF_RESETVALUE 0x6U +#define XHC_AIUDMA__RRMB_L 15U +#define XHC_AIUDMA__RRMB_R 12U +#define XHC_AIUDMA__RRMB_WIDTH 4U +#define XHC_AIUDMA__RRMB_RESETVALUE 0x0U +#define XHC_AIUDMA__RTD_L 11U +#define XHC_AIUDMA__RTD_R 10U +#define XHC_AIUDMA__RTD_WIDTH 2U +#define XHC_AIUDMA__RTD_RESETVALUE 0x0U +#define XHC_AIUDMA__RTF_L 9U +#define XHC_AIUDMA__RTF_R 8U +#define XHC_AIUDMA__RTF_WIDTH 2U +#define XHC_AIUDMA__RTF_RESETVALUE 0x0U +#define XHC_AIUDMA__RM_S_L 7U +#define XHC_AIUDMA__RM_S_R 6U +#define XHC_AIUDMA__RM_S_WIDTH 2U +#define XHC_AIUDMA__RM_S_RESETVALUE 0x0U +#define XHC_AIUDMA__TFBS_L 5U +#define XHC_AIUDMA__TFBS_R 3U +#define XHC_AIUDMA__TFBS_WIDTH 3U +#define XHC_AIUDMA__TFBS_RESETVALUE 0x0U +#define XHC_AIUDMA__reserved_L 2U +#define XHC_AIUDMA__reserved_R 0U +#define XHC_AIUDMA__reserved_WIDTH 3U +#define XHC_AIUDMA__reserved_RESETVALUE 0x0U +#define XHC_AIUDMA_WIDTH 32U +#define XHC_AIUDMA__WIDTH 32U +#define XHC_AIUDMA_ALL_L 31U +#define XHC_AIUDMA_ALL_R 0U +#define XHC_AIUDMA__ALL_L 31U +#define XHC_AIUDMA__ALL_R 0U +#define XHC_AIUDMA_DATAMASK 0xffffffffU +#define XHC_AIUDMA_RDWRMASK 0x00000000U +#define XHC_AIUDMA_RESETVALUE 0x00060000U + +#define XHC_AIUFLA_OFFSET 0xc38U +#define XHC_AIUFLA_BASE 0xc38U +#define XHC_AIUFLA__ACLK_L 31U +#define XHC_AIUFLA__ACLK_R 23U +#define XHC_AIUFLA__ACLK_WIDTH 9U +#define XHC_AIUFLA__ACLK_RESETVALUE 0x0U +#define XHC_AIUFLA__MFLV_L 22U +#define XHC_AIUFLA__MFLV_R 7U +#define XHC_AIUFLA__MFLV_WIDTH 16U +#define XHC_AIUFLA__MFLV_RESETVALUE 0x0000U +#define XHC_AIUFLA__NFC 6U +#define XHC_AIUFLA__NFC_L 6U +#define XHC_AIUFLA__NFC_R 6U +#define XHC_AIUFLA__NFC_WIDTH 1U +#define XHC_AIUFLA__NFC_RESETVALUE 0x1U +#define XHC_AIUFLA__FLADJ_L 5U +#define XHC_AIUFLA__FLADJ_R 0U +#define XHC_AIUFLA__FLADJ_WIDTH 6U +#define XHC_AIUFLA__FLADJ_RESETVALUE 0x20U +#define XHC_AIUFLA_WIDTH 32U +#define XHC_AIUFLA__WIDTH 32U +#define XHC_AIUFLA_ALL_L 31U +#define XHC_AIUFLA_ALL_R 0U +#define XHC_AIUFLA__ALL_L 31U +#define XHC_AIUFLA__ALL_R 0U +#define XHC_AIUFLA_DATAMASK 0xffffffffU +#define XHC_AIUFLA_RDWRMASK 0x00000000U +#define XHC_AIUFLA_RESETVALUE 0x00000060U + +#define XHC_AIUCFG_OFFSET 0xc3cU +#define XHC_AIUCFG_BASE 0xc3cU +#define XHC_AIUCFG__ISO_L 30U +#define XHC_AIUCFG__ISO_R 28U +#define XHC_AIUCFG__ISO_WIDTH 3U +#define XHC_AIUCFG__ISO_RESETVALUE 0x0U +#define XHC_AIUCFG__EPC_L 26U +#define XHC_AIUCFG__EPC_R 24U +#define XHC_AIUCFG__EPC_WIDTH 3U +#define XHC_AIUCFG__EPC_RESETVALUE 0x5U +#define XHC_AIUCFG__PTQ_L 22U +#define XHC_AIUCFG__PTQ_R 20U +#define XHC_AIUCFG__PTQ_WIDTH 3U +#define XHC_AIUCFG__PTQ_RESETVALUE 0x3U +#define XHC_AIUCFG__NTQ_L 18U +#define XHC_AIUCFG__NTQ_R 16U +#define XHC_AIUCFG__NTQ_WIDTH 3U +#define XHC_AIUCFG__NTQ_RESETVALUE 0x3U +#define XHC_AIUCFG__HID 15U +#define XHC_AIUCFG__HID_L 15U +#define XHC_AIUCFG__HID_R 15U +#define XHC_AIUCFG__HID_WIDTH 1U +#define XHC_AIUCFG__HID_RESETVALUE 0x0U +#define XHC_AIUCFG__EPS_L 14U +#define XHC_AIUCFG__EPS_R 12U +#define XHC_AIUCFG__EPS_WIDTH 3U +#define XHC_AIUCFG__EPS_RESETVALUE 0x0U +#define XHC_AIUCFG__reserved_L 11U +#define XHC_AIUCFG__reserved_R 9U +#define XHC_AIUCFG__reserved_WIDTH 3U +#define XHC_AIUCFG__reserved_RESETVALUE 0x0U +#define XHC_AIUCFG__PEP2_L 8U +#define XHC_AIUCFG__PEP2_R 6U +#define XHC_AIUCFG__PEP2_WIDTH 3U +#define XHC_AIUCFG__PEP2_RESETVALUE 0x4U +#define XHC_AIUCFG__MELADJ_L 5U +#define XHC_AIUCFG__MELADJ_R 0U +#define XHC_AIUCFG__MELADJ_WIDTH 6U +#define XHC_AIUCFG__MELADJ_RESETVALUE 0x0U +#define XHC_AIUCFG__RESERVED_0 31U +#define XHC_AIUCFG__RESERVED_0_L 31U +#define XHC_AIUCFG__RESERVED_0_R 31U +#define XHC_AIUCFG__RESERVED_1 27U +#define XHC_AIUCFG__RESERVED_1_L 27U +#define XHC_AIUCFG__RESERVED_1_R 27U +#define XHC_AIUCFG__RESERVED_2 23U +#define XHC_AIUCFG__RESERVED_2_L 23U +#define XHC_AIUCFG__RESERVED_2_R 23U +#define XHC_AIUCFG__RESERVED_3 19U +#define XHC_AIUCFG__RESERVED_3_L 19U +#define XHC_AIUCFG__RESERVED_3_R 19U +#define XHC_AIUCFG_WIDTH 31U +#define XHC_AIUCFG__WIDTH 31U +#define XHC_AIUCFG_ALL_L 30U +#define XHC_AIUCFG_ALL_R 0U +#define XHC_AIUCFG__ALL_L 30U +#define XHC_AIUCFG__ALL_R 0U +#define XHC_AIUCFG_DATAMASK 0x7777ffffU +#define XHC_AIUCFG_RDWRMASK 0x88880000U +#define XHC_AIUCFG_RESETVALUE 0x05330100U + +#define XHC_ECHFSC_OFFSET 0xc40U +#define XHC_ECHFSC_BASE 0xc40U +#define XHC_ECHFSC__reserved_L 31U +#define XHC_ECHFSC__reserved_R 24U +#define XHC_ECHFSC__reserved_WIDTH 8U +#define XHC_ECHFSC__reserved_RESETVALUE 0x00U +#define XHC_ECHFSC__WRMB_L 23U +#define XHC_ECHFSC__WRMB_R 20U +#define XHC_ECHFSC__WRMB_WIDTH 4U +#define XHC_ECHFSC__WRMB_RESETVALUE 0x0U +#define XHC_ECHFSC__RRMB_L 19U +#define XHC_ECHFSC__RRMB_R 16U +#define XHC_ECHFSC__RRMB_WIDTH 4U +#define XHC_ECHFSC__RRMB_RESETVALUE 0x0U +#define XHC_ECHFSC__NCP_L 15U +#define XHC_ECHFSC__NCP_R 8U +#define XHC_ECHFSC__NCP_WIDTH 8U +#define XHC_ECHFSC__NCP_RESETVALUE 0x50U +#define XHC_ECHFSC__CID_L 7U +#define XHC_ECHFSC__CID_R 0U +#define XHC_ECHFSC__CID_WIDTH 8U +#define XHC_ECHFSC__CID_RESETVALUE 0xc3U +#define XHC_ECHFSC_WIDTH 32U +#define XHC_ECHFSC__WIDTH 32U +#define XHC_ECHFSC_ALL_L 31U +#define XHC_ECHFSC_ALL_R 0U +#define XHC_ECHFSC__ALL_L 31U +#define XHC_ECHFSC__ALL_R 0U +#define XHC_ECHFSC_DATAMASK 0xffffffffU +#define XHC_ECHFSC_RDWRMASK 0x00000000U +#define XHC_ECHFSC_RESETVALUE 0x000050c3U + +#define XHC_FSCPOC_OFFSET 0xc54U +#define XHC_FSCPOC_BASE 0xc54U +#define XHC_FSCPOC__NCS_L 31U +#define XHC_FSCPOC__NCS_R 28U +#define XHC_FSCPOC__NCS_WIDTH 4U +#define XHC_FSCPOC__NCS_RESETVALUE 0x0U +#define XHC_FSCPOC__FSIZ_L 22U +#define XHC_FSCPOC__FSIZ_R 18U +#define XHC_FSCPOC__FSIZ_WIDTH 5U +#define XHC_FSCPOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__PSIZ_L 16U +#define XHC_FSCPOC__PSIZ_R 12U +#define XHC_FSCPOC__PSIZ_WIDTH 5U +#define XHC_FSCPOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__reserved_L 11U +#define XHC_FSCPOC__reserved_R 5U +#define XHC_FSCPOC__reserved_WIDTH 7U +#define XHC_FSCPOC__reserved_RESETVALUE 0x0U +#define XHC_FSCPOC__TSIZ_L 4U +#define XHC_FSCPOC__TSIZ_R 0U +#define XHC_FSCPOC__TSIZ_WIDTH 5U +#define XHC_FSCPOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCPOC__RESERVED_L 27U +#define XHC_FSCPOC__RESERVED_R 23U +#define XHC_FSCPOC_WIDTH 32U +#define XHC_FSCPOC__WIDTH 32U +#define XHC_FSCPOC_ALL_L 31U +#define XHC_FSCPOC_ALL_R 0U +#define XHC_FSCPOC__ALL_L 31U +#define XHC_FSCPOC__ALL_R 0U +#define XHC_FSCPOC_DATAMASK 0xf07dffffU +#define XHC_FSCPOC_RDWRMASK 0x0f820000U +#define XHC_FSCPOC_RESETVALUE 0x00000000U + +#define XHC_FSCGOC_OFFSET 0xc58U +#define XHC_FSCGOC_BASE 0xc58U +#define XHC_FSCGOC__NCS_L 31U +#define XHC_FSCGOC__NCS_R 28U +#define XHC_FSCGOC__NCS_WIDTH 4U +#define XHC_FSCGOC__NCS_RESETVALUE 0x0U +#define XHC_FSCGOC__FSIZ_L 22U +#define XHC_FSCGOC__FSIZ_R 18U +#define XHC_FSCGOC__FSIZ_WIDTH 5U +#define XHC_FSCGOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__PSIZ_L 16U +#define XHC_FSCGOC__PSIZ_R 12U +#define XHC_FSCGOC__PSIZ_WIDTH 5U +#define XHC_FSCGOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__reserved_L 11U +#define XHC_FSCGOC__reserved_R 5U +#define XHC_FSCGOC__reserved_WIDTH 7U +#define XHC_FSCGOC__reserved_RESETVALUE 0x0U +#define XHC_FSCGOC__TSIZ_L 4U +#define XHC_FSCGOC__TSIZ_R 0U +#define XHC_FSCGOC__TSIZ_WIDTH 5U +#define XHC_FSCGOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCGOC__RESERVED_L 27U +#define XHC_FSCGOC__RESERVED_R 23U +#define XHC_FSCGOC_WIDTH 32U +#define XHC_FSCGOC__WIDTH 32U +#define XHC_FSCGOC_ALL_L 31U +#define XHC_FSCGOC_ALL_R 0U +#define XHC_FSCGOC__ALL_L 31U +#define XHC_FSCGOC__ALL_R 0U +#define XHC_FSCGOC_DATAMASK 0xf07dffffU +#define XHC_FSCGOC_RDWRMASK 0x0f820000U +#define XHC_FSCGOC_RESETVALUE 0x00000000U + +#define XHC_FSCNOC_OFFSET 0xc5cU +#define XHC_FSCNOC_BASE 0xc5cU +#define XHC_FSCNOC__NCS_L 31U +#define XHC_FSCNOC__NCS_R 28U +#define XHC_FSCNOC__NCS_WIDTH 4U +#define XHC_FSCNOC__NCS_RESETVALUE 0x0U +#define XHC_FSCNOC__FSIZ_L 22U +#define XHC_FSCNOC__FSIZ_R 18U +#define XHC_FSCNOC__FSIZ_WIDTH 5U +#define XHC_FSCNOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__PSIZ_L 16U +#define XHC_FSCNOC__PSIZ_R 12U +#define XHC_FSCNOC__PSIZ_WIDTH 5U +#define XHC_FSCNOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__reserved_L 11U +#define XHC_FSCNOC__reserved_R 5U +#define XHC_FSCNOC__reserved_WIDTH 7U +#define XHC_FSCNOC__reserved_RESETVALUE 0x0U +#define XHC_FSCNOC__TSIZ_L 4U +#define XHC_FSCNOC__TSIZ_R 0U +#define XHC_FSCNOC__TSIZ_WIDTH 5U +#define XHC_FSCNOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCNOC__RESERVED_L 27U +#define XHC_FSCNOC__RESERVED_R 23U +#define XHC_FSCNOC_WIDTH 32U +#define XHC_FSCNOC__WIDTH 32U +#define XHC_FSCNOC_ALL_L 31U +#define XHC_FSCNOC_ALL_R 0U +#define XHC_FSCNOC__ALL_L 31U +#define XHC_FSCNOC__ALL_R 0U +#define XHC_FSCNOC_DATAMASK 0xf07dffffU +#define XHC_FSCNOC_RDWRMASK 0x0f820000U +#define XHC_FSCNOC_RESETVALUE 0x00000000U + +#define XHC_FSCAIC_OFFSET 0xc60U +#define XHC_FSCAIC_BASE 0xc60U +#define XHC_FSCAIC__FSIZ_L 22U +#define XHC_FSCAIC__FSIZ_R 18U +#define XHC_FSCAIC__FSIZ_WIDTH 5U +#define XHC_FSCAIC__FSIZ_RESETVALUE 0x0U +#define XHC_FSCAIC__PSIZ_L 16U +#define XHC_FSCAIC__PSIZ_R 12U +#define XHC_FSCAIC__PSIZ_WIDTH 5U +#define XHC_FSCAIC__PSIZ_RESETVALUE 0x0U +#define XHC_FSCAIC__reserved_L 11U +#define XHC_FSCAIC__reserved_R 0U +#define XHC_FSCAIC__reserved_WIDTH 12U +#define XHC_FSCAIC__reserved_RESETVALUE 0x000U +#define XHC_FSCAIC__RESERVED_L 31U +#define XHC_FSCAIC__RESERVED_R 23U +#define XHC_FSCAIC_WIDTH 23U +#define XHC_FSCAIC__WIDTH 23U +#define XHC_FSCAIC_ALL_L 22U +#define XHC_FSCAIC_ALL_R 0U +#define XHC_FSCAIC__ALL_L 22U +#define XHC_FSCAIC__ALL_R 0U +#define XHC_FSCAIC_DATAMASK 0x007dffffU +#define XHC_FSCAIC_RDWRMASK 0xff820000U +#define XHC_FSCAIC_RESETVALUE 0x000000U + +#define XHC_FSCPIC_OFFSET 0xc64U +#define XHC_FSCPIC_BASE 0xc64U +#define XHC_FSCPIC__NCS_L 31U +#define XHC_FSCPIC__NCS_R 28U +#define XHC_FSCPIC__NCS_WIDTH 4U +#define XHC_FSCPIC__NCS_RESETVALUE 0x0U +#define XHC_FSCPIC__reserved_L 27U +#define XHC_FSCPIC__reserved_R 5U +#define XHC_FSCPIC__reserved_WIDTH 23U +#define XHC_FSCPIC__reserved_RESETVALUE 0x0U +#define XHC_FSCPIC__TSIZ_L 4U +#define XHC_FSCPIC__TSIZ_R 0U +#define XHC_FSCPIC__TSIZ_WIDTH 5U +#define XHC_FSCPIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCPIC_WIDTH 32U +#define XHC_FSCPIC__WIDTH 32U +#define XHC_FSCPIC_ALL_L 31U +#define XHC_FSCPIC_ALL_R 0U +#define XHC_FSCPIC__ALL_L 31U +#define XHC_FSCPIC__ALL_R 0U +#define XHC_FSCPIC_DATAMASK 0xffffffffU +#define XHC_FSCPIC_RDWRMASK 0x00000000U +#define XHC_FSCPIC_RESETVALUE 0x00000000U + +#define XHC_FSCGIC_OFFSET 0xc68U +#define XHC_FSCGIC_BASE 0xc68U +#define XHC_FSCGIC__NCS_L 31U +#define XHC_FSCGIC__NCS_R 28U +#define XHC_FSCGIC__NCS_WIDTH 4U +#define XHC_FSCGIC__NCS_RESETVALUE 0x0U +#define XHC_FSCGIC__reserved_L 27U +#define XHC_FSCGIC__reserved_R 5U +#define XHC_FSCGIC__reserved_WIDTH 23U +#define XHC_FSCGIC__reserved_RESETVALUE 0x0U +#define XHC_FSCGIC__TSIZ_L 4U +#define XHC_FSCGIC__TSIZ_R 0U +#define XHC_FSCGIC__TSIZ_WIDTH 5U +#define XHC_FSCGIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCGIC_WIDTH 32U +#define XHC_FSCGIC__WIDTH 32U +#define XHC_FSCGIC_ALL_L 31U +#define XHC_FSCGIC_ALL_R 0U +#define XHC_FSCGIC__ALL_L 31U +#define XHC_FSCGIC__ALL_R 0U +#define XHC_FSCGIC_DATAMASK 0xffffffffU +#define XHC_FSCGIC_RDWRMASK 0x00000000U +#define XHC_FSCGIC_RESETVALUE 0x00000000U + +#define XHC_FSCNIC_OFFSET 0xc6cU +#define XHC_FSCNIC_BASE 0xc6cU +#define XHC_FSCNIC__NCS_L 31U +#define XHC_FSCNIC__NCS_R 28U +#define XHC_FSCNIC__NCS_WIDTH 4U +#define XHC_FSCNIC__NCS_RESETVALUE 0x0U +#define XHC_FSCNIC__reserved_L 27U +#define XHC_FSCNIC__reserved_R 5U +#define XHC_FSCNIC__reserved_WIDTH 23U +#define XHC_FSCNIC__reserved_RESETVALUE 0x0U +#define XHC_FSCNIC__TSIZ_L 4U +#define XHC_FSCNIC__TSIZ_R 0U +#define XHC_FSCNIC__TSIZ_WIDTH 5U +#define XHC_FSCNIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSCNIC_WIDTH 32U +#define XHC_FSCNIC__WIDTH 32U +#define XHC_FSCNIC_ALL_L 31U +#define XHC_FSCNIC_ALL_R 0U +#define XHC_FSCNIC__ALL_L 31U +#define XHC_FSCNIC__ALL_R 0U +#define XHC_FSCNIC_DATAMASK 0xffffffffU +#define XHC_FSCNIC_RDWRMASK 0x00000000U +#define XHC_FSCNIC_RESETVALUE 0x00000000U + +#define XHC_ECHPRT_OFFSET 0xc70U +#define XHC_ECHPRT_BASE 0xc70U +#define XHC_ECHPRT__TDP 31U +#define XHC_ECHPRT__TDP_L 31U +#define XHC_ECHPRT__TDP_R 31U +#define XHC_ECHPRT__TDP_WIDTH 1U +#define XHC_ECHPRT__TDP_RESETVALUE 0x0U +#define XHC_ECHPRT__RDP 30U +#define XHC_ECHPRT__RDP_L 30U +#define XHC_ECHPRT__RDP_R 30U +#define XHC_ECHPRT__RDP_WIDTH 1U +#define XHC_ECHPRT__RDP_RESETVALUE 0x0U +#define XHC_ECHPRT__reserved_L 29U +#define XHC_ECHPRT__reserved_R 25U +#define XHC_ECHPRT__reserved_WIDTH 5U +#define XHC_ECHPRT__reserved_RESETVALUE 0x0U +#define XHC_ECHPRT__MFT_L 24U +#define XHC_ECHPRT__MFT_R 17U +#define XHC_ECHPRT__MFT_WIDTH 8U +#define XHC_ECHPRT__MFT_RESETVALUE 0x7dU +#define XHC_ECHPRT__HST 16U +#define XHC_ECHPRT__HST_L 16U +#define XHC_ECHPRT__HST_R 16U +#define XHC_ECHPRT__HST_WIDTH 1U +#define XHC_ECHPRT__HST_RESETVALUE 0x0U +#define XHC_ECHPRT__NCP_L 15U +#define XHC_ECHPRT__NCP_R 8U +#define XHC_ECHPRT__NCP_WIDTH 8U +#define XHC_ECHPRT__NCP_RESETVALUE 0x04U +#define XHC_ECHPRT__CID_L 7U +#define XHC_ECHPRT__CID_R 0U +#define XHC_ECHPRT__CID_WIDTH 8U +#define XHC_ECHPRT__CID_RESETVALUE 0xc4U +#define XHC_ECHPRT_WIDTH 32U +#define XHC_ECHPRT__WIDTH 32U +#define XHC_ECHPRT_ALL_L 31U +#define XHC_ECHPRT_ALL_R 0U +#define XHC_ECHPRT__ALL_L 31U +#define XHC_ECHPRT__ALL_R 0U +#define XHC_ECHPRT_DATAMASK 0xffffffffU +#define XHC_ECHPRT_RDWRMASK 0x00000000U +#define XHC_ECHPRT_RESETVALUE 0x00fa04c4U + +#define XHC_PRTHSC_OFFSET 0xc78U +#define XHC_PRTHSC_BASE 0xc78U +#define XHC_PRTHSC__TMR_L 31U +#define XHC_PRTHSC__TMR_R 16U +#define XHC_PRTHSC__TMR_WIDTH 16U +#define XHC_PRTHSC__TMR_RESETVALUE 0x0000U +#define XHC_PRTHSC__RSL_L 7U +#define XHC_PRTHSC__RSL_R 6U +#define XHC_PRTHSC__RSL_WIDTH 2U +#define XHC_PRTHSC__RSL_RESETVALUE 0x0U +#define XHC_PRTHSC__AS_M_L 5U +#define XHC_PRTHSC__AS_M_R 4U +#define XHC_PRTHSC__AS_M_WIDTH 2U +#define XHC_PRTHSC__AS_M_RESETVALUE 0x0U +#define XHC_PRTHSC__CMD_L 3U +#define XHC_PRTHSC__CMD_R 2U +#define XHC_PRTHSC__CMD_WIDTH 2U +#define XHC_PRTHSC__CMD_RESETVALUE 0x0U +#define XHC_PRTHSC__reserved 1U +#define XHC_PRTHSC__reserved_L 1U +#define XHC_PRTHSC__reserved_R 1U +#define XHC_PRTHSC__reserved_WIDTH 1U +#define XHC_PRTHSC__reserved_RESETVALUE 0x0U +#define XHC_PRTHSC__STB 0U +#define XHC_PRTHSC__STB_L 0U +#define XHC_PRTHSC__STB_R 0U +#define XHC_PRTHSC__STB_WIDTH 1U +#define XHC_PRTHSC__STB_RESETVALUE 0x0U +#define XHC_PRTHSC__RESERVED_L 15U +#define XHC_PRTHSC__RESERVED_R 8U +#define XHC_PRTHSC_WIDTH 32U +#define XHC_PRTHSC__WIDTH 32U +#define XHC_PRTHSC_ALL_L 31U +#define XHC_PRTHSC_ALL_R 0U +#define XHC_PRTHSC__ALL_L 31U +#define XHC_PRTHSC__ALL_R 0U +#define XHC_PRTHSC_DATAMASK 0xffff00ffU +#define XHC_PRTHSC_RDWRMASK 0x0000ff00U +#define XHC_PRTHSC_RESETVALUE 0x00000000U + +#define XHC_PRTHSR_OFFSET 0xc7cU +#define XHC_PRTHSR_BASE 0xc7cU +#define XHC_PRTHSR__RDLY_L 31U +#define XHC_PRTHSR__RDLY_R 24U +#define XHC_PRTHSR__RDLY_WIDTH 8U +#define XHC_PRTHSR__RDLY_RESETVALUE 0x00U +#define XHC_PRTHSR__TDPP_L 23U +#define XHC_PRTHSR__TDPP_R 16U +#define XHC_PRTHSR__TDPP_WIDTH 8U +#define XHC_PRTHSR__TDPP_RESETVALUE 0x00U +#define XHC_PRTHSR__RDPP_L 15U +#define XHC_PRTHSR__RDPP_R 8U +#define XHC_PRTHSR__RDPP_WIDTH 8U +#define XHC_PRTHSR__RDPP_RESETVALUE 0x00U +#define XHC_PRTHSR__TRTY_L 7U +#define XHC_PRTHSR__TRTY_R 0U +#define XHC_PRTHSR__TRTY_WIDTH 8U +#define XHC_PRTHSR__TRTY_RESETVALUE 0x00U +#define XHC_PRTHSR_WIDTH 32U +#define XHC_PRTHSR__WIDTH 32U +#define XHC_PRTHSR_ALL_L 31U +#define XHC_PRTHSR_ALL_R 0U +#define XHC_PRTHSR__ALL_L 31U +#define XHC_PRTHSR__ALL_R 0U +#define XHC_PRTHSR_DATAMASK 0xffffffffU +#define XHC_PRTHSR_RDWRMASK 0x00000000U +#define XHC_PRTHSR_RESETVALUE 0x00000000U + +#define XHC_ECHRHS_OFFSET 0xc80U +#define XHC_ECHRHS_BASE 0xc80U +#define XHC_ECHRHS__RPO_L 30U +#define XHC_ECHRHS__RPO_R 24U +#define XHC_ECHRHS__RPO_WIDTH 7U +#define XHC_ECHRHS__RPO_RESETVALUE 0x0U +#define XHC_ECHRHS__reserved_L 23U +#define XHC_ECHRHS__reserved_R 22U +#define XHC_ECHRHS__reserved_WIDTH 2U +#define XHC_ECHRHS__reserved_RESETVALUE 0x0U +#define XHC_ECHRHS__RPN_L 21U +#define XHC_ECHRHS__RPN_R 20U +#define XHC_ECHRHS__RPN_WIDTH 2U +#define XHC_ECHRHS__RPN_RESETVALUE 0x0U +#define XHC_ECHRHS__DNR_L 19U +#define XHC_ECHRHS__DNR_R 16U +#define XHC_ECHRHS__DNR_WIDTH 4U +#define XHC_ECHRHS__DNR_RESETVALUE 0x0U +#define XHC_ECHRHS__NCP_L 15U +#define XHC_ECHRHS__NCP_R 8U +#define XHC_ECHRHS__NCP_WIDTH 8U +#define XHC_ECHRHS__NCP_RESETVALUE 0x0cU +#define XHC_ECHRHS__CID_L 7U +#define XHC_ECHRHS__CID_R 0U +#define XHC_ECHRHS__CID_WIDTH 8U +#define XHC_ECHRHS__CID_RESETVALUE 0xc8U +#define XHC_ECHRHS__RESERVED 31U +#define XHC_ECHRHS__RESERVED_L 31U +#define XHC_ECHRHS__RESERVED_R 31U +#define XHC_ECHRHS_WIDTH 31U +#define XHC_ECHRHS__WIDTH 31U +#define XHC_ECHRHS_ALL_L 30U +#define XHC_ECHRHS_ALL_R 0U +#define XHC_ECHRHS__ALL_L 30U +#define XHC_ECHRHS__ALL_R 0U +#define XHC_ECHRHS_DATAMASK 0x7fffffffU +#define XHC_ECHRHS_RDWRMASK 0x80000000U +#define XHC_ECHRHS_RESETVALUE 0x00000cc8U + +#define XHC_RHSDES_OFFSET 0xc84U +#define XHC_RHSDES_BASE 0xc84U +#define XHC_RHSDES__PIS3_L 31U +#define XHC_RHSDES__PIS3_R 30U +#define XHC_RHSDES__PIS3_WIDTH 2U +#define XHC_RHSDES__PIS3_RESETVALUE 0x0U +#define XHC_RHSDES__HIST3 24U +#define XHC_RHSDES__HIST3_L 24U +#define XHC_RHSDES__HIST3_R 24U +#define XHC_RHSDES__HIST3_WIDTH 1U +#define XHC_RHSDES__HIST3_RESETVALUE 0x0U +#define XHC_RHSDES__PIS2_L 23U +#define XHC_RHSDES__PIS2_R 22U +#define XHC_RHSDES__PIS2_WIDTH 2U +#define XHC_RHSDES__PIS2_RESETVALUE 0x0U +#define XHC_RHSDES__HIST2 16U +#define XHC_RHSDES__HIST2_L 16U +#define XHC_RHSDES__HIST2_R 16U +#define XHC_RHSDES__HIST2_WIDTH 1U +#define XHC_RHSDES__HIST2_RESETVALUE 0x0U +#define XHC_RHSDES__PIS1_L 15U +#define XHC_RHSDES__PIS1_R 14U +#define XHC_RHSDES__PIS1_WIDTH 2U +#define XHC_RHSDES__PIS1_RESETVALUE 0x0U +#define XHC_RHSDES__HIST1 8U +#define XHC_RHSDES__HIST1_L 8U +#define XHC_RHSDES__HIST1_R 8U +#define XHC_RHSDES__HIST1_WIDTH 1U +#define XHC_RHSDES__HIST1_RESETVALUE 0x0U +#define XHC_RHSDES__PIS0_L 7U +#define XHC_RHSDES__PIS0_R 6U +#define XHC_RHSDES__PIS0_WIDTH 2U +#define XHC_RHSDES__PIS0_RESETVALUE 0x0U +#define XHC_RHSDES__reserved_L 5U +#define XHC_RHSDES__reserved_R 1U +#define XHC_RHSDES__reserved_WIDTH 5U +#define XHC_RHSDES__reserved_RESETVALUE 0x0U +#define XHC_RHSDES__HIST0 0U +#define XHC_RHSDES__HIST0_L 0U +#define XHC_RHSDES__HIST0_R 0U +#define XHC_RHSDES__HIST0_WIDTH 1U +#define XHC_RHSDES__HIST0_RESETVALUE 0x0U +#define XHC_RHSDES__RESERVED_0_L 29U +#define XHC_RHSDES__RESERVED_0_R 25U +#define XHC_RHSDES__RESERVED_1_L 21U +#define XHC_RHSDES__RESERVED_1_R 17U +#define XHC_RHSDES__RESERVED_2_L 13U +#define XHC_RHSDES__RESERVED_2_R 9U +#define XHC_RHSDES__RESERVED_L 29U +#define XHC_RHSDES__RESERVED_R 25U +#define XHC_RHSDES_WIDTH 32U +#define XHC_RHSDES__WIDTH 32U +#define XHC_RHSDES_ALL_L 31U +#define XHC_RHSDES_ALL_R 0U +#define XHC_RHSDES__ALL_L 31U +#define XHC_RHSDES__ALL_R 0U +#define XHC_RHSDES_DATAMASK 0xc1c1c1ffU +#define XHC_RHSDES_RDWRMASK 0x3e3e3e00U +#define XHC_RHSDES_RESETVALUE 0x00000000U + +#define XHC_RHSHSC0_OFFSET 0xc90U +#define XHC_RHSHSC0_BASE 0xc90U +#define XHC_RHSHSC0__TMR_L 31U +#define XHC_RHSHSC0__TMR_R 16U +#define XHC_RHSHSC0__TMR_WIDTH 16U +#define XHC_RHSHSC0__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC0__RSL_L 7U +#define XHC_RHSHSC0__RSL_R 6U +#define XHC_RHSHSC0__RSL_WIDTH 2U +#define XHC_RHSHSC0__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC0__AS_M_L 5U +#define XHC_RHSHSC0__AS_M_R 4U +#define XHC_RHSHSC0__AS_M_WIDTH 2U +#define XHC_RHSHSC0__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC0__CMD_L 3U +#define XHC_RHSHSC0__CMD_R 2U +#define XHC_RHSHSC0__CMD_WIDTH 2U +#define XHC_RHSHSC0__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC0__reserved 1U +#define XHC_RHSHSC0__reserved_L 1U +#define XHC_RHSHSC0__reserved_R 1U +#define XHC_RHSHSC0__reserved_WIDTH 1U +#define XHC_RHSHSC0__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC0__STB 0U +#define XHC_RHSHSC0__STB_L 0U +#define XHC_RHSHSC0__STB_R 0U +#define XHC_RHSHSC0__STB_WIDTH 1U +#define XHC_RHSHSC0__STB_RESETVALUE 0x0U +#define XHC_RHSHSC0__RESERVED_L 15U +#define XHC_RHSHSC0__RESERVED_R 8U +#define XHC_RHSHSC0_WIDTH 32U +#define XHC_RHSHSC0__WIDTH 32U +#define XHC_RHSHSC0_ALL_L 31U +#define XHC_RHSHSC0_ALL_R 0U +#define XHC_RHSHSC0__ALL_L 31U +#define XHC_RHSHSC0__ALL_R 0U +#define XHC_RHSHSC0_DATAMASK 0xffff00ffU +#define XHC_RHSHSC0_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC0_RESETVALUE 0x00000000U + +#define XHC_RHSHSR0_OFFSET 0xc94U +#define XHC_RHSHSR0_BASE 0xc94U +#define XHC_RHSHSR0__C2U_L 31U +#define XHC_RHSHSR0__C2U_R 24U +#define XHC_RHSHSR0__C2U_WIDTH 8U +#define XHC_RHSHSR0__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR0__C1U_L 23U +#define XHC_RHSHSR0__C1U_R 16U +#define XHC_RHSHSR0__C1U_WIDTH 8U +#define XHC_RHSHSR0__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR0__RCV_L 15U +#define XHC_RHSHSR0__RCV_R 8U +#define XHC_RHSHSR0__RCV_WIDTH 8U +#define XHC_RHSHSR0__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR0__RTY_L 7U +#define XHC_RHSHSR0__RTY_R 0U +#define XHC_RHSHSR0__RTY_WIDTH 8U +#define XHC_RHSHSR0__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR0_WIDTH 32U +#define XHC_RHSHSR0__WIDTH 32U +#define XHC_RHSHSR0_ALL_L 31U +#define XHC_RHSHSR0_ALL_R 0U +#define XHC_RHSHSR0__ALL_L 31U +#define XHC_RHSHSR0__ALL_R 0U +#define XHC_RHSHSR0_DATAMASK 0xffffffffU +#define XHC_RHSHSR0_RDWRMASK 0x00000000U +#define XHC_RHSHSR0_RESETVALUE 0x00000000U + +#define XHC_RHSHSC1_OFFSET 0xc98U +#define XHC_RHSHSC1_BASE 0xc98U +#define XHC_RHSHSC1__TMR_L 31U +#define XHC_RHSHSC1__TMR_R 16U +#define XHC_RHSHSC1__TMR_WIDTH 16U +#define XHC_RHSHSC1__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC1__RSL_L 7U +#define XHC_RHSHSC1__RSL_R 6U +#define XHC_RHSHSC1__RSL_WIDTH 2U +#define XHC_RHSHSC1__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC1__AS_M_L 5U +#define XHC_RHSHSC1__AS_M_R 4U +#define XHC_RHSHSC1__AS_M_WIDTH 2U +#define XHC_RHSHSC1__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC1__CMD_L 3U +#define XHC_RHSHSC1__CMD_R 2U +#define XHC_RHSHSC1__CMD_WIDTH 2U +#define XHC_RHSHSC1__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC1__reserved 1U +#define XHC_RHSHSC1__reserved_L 1U +#define XHC_RHSHSC1__reserved_R 1U +#define XHC_RHSHSC1__reserved_WIDTH 1U +#define XHC_RHSHSC1__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC1__STB 0U +#define XHC_RHSHSC1__STB_L 0U +#define XHC_RHSHSC1__STB_R 0U +#define XHC_RHSHSC1__STB_WIDTH 1U +#define XHC_RHSHSC1__STB_RESETVALUE 0x0U +#define XHC_RHSHSC1__RESERVED_L 15U +#define XHC_RHSHSC1__RESERVED_R 8U +#define XHC_RHSHSC1_WIDTH 32U +#define XHC_RHSHSC1__WIDTH 32U +#define XHC_RHSHSC1_ALL_L 31U +#define XHC_RHSHSC1_ALL_R 0U +#define XHC_RHSHSC1__ALL_L 31U +#define XHC_RHSHSC1__ALL_R 0U +#define XHC_RHSHSC1_DATAMASK 0xffff00ffU +#define XHC_RHSHSC1_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC1_RESETVALUE 0x00000000U + +#define XHC_RHSHSR1_OFFSET 0xc9cU +#define XHC_RHSHSR1_BASE 0xc9cU +#define XHC_RHSHSR1__C2U_L 31U +#define XHC_RHSHSR1__C2U_R 24U +#define XHC_RHSHSR1__C2U_WIDTH 8U +#define XHC_RHSHSR1__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR1__C1U_L 23U +#define XHC_RHSHSR1__C1U_R 16U +#define XHC_RHSHSR1__C1U_WIDTH 8U +#define XHC_RHSHSR1__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR1__RCV_L 15U +#define XHC_RHSHSR1__RCV_R 8U +#define XHC_RHSHSR1__RCV_WIDTH 8U +#define XHC_RHSHSR1__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR1__RTY_L 7U +#define XHC_RHSHSR1__RTY_R 0U +#define XHC_RHSHSR1__RTY_WIDTH 8U +#define XHC_RHSHSR1__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR1_WIDTH 32U +#define XHC_RHSHSR1__WIDTH 32U +#define XHC_RHSHSR1_ALL_L 31U +#define XHC_RHSHSR1_ALL_R 0U +#define XHC_RHSHSR1__ALL_L 31U +#define XHC_RHSHSR1__ALL_R 0U +#define XHC_RHSHSR1_DATAMASK 0xffffffffU +#define XHC_RHSHSR1_RDWRMASK 0x00000000U +#define XHC_RHSHSR1_RESETVALUE 0x00000000U + +#define XHC_RHSHSC2_OFFSET 0xca0U +#define XHC_RHSHSC2_BASE 0xca0U +#define XHC_RHSHSC2__TMR_L 31U +#define XHC_RHSHSC2__TMR_R 16U +#define XHC_RHSHSC2__TMR_WIDTH 16U +#define XHC_RHSHSC2__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC2__RSL_L 7U +#define XHC_RHSHSC2__RSL_R 6U +#define XHC_RHSHSC2__RSL_WIDTH 2U +#define XHC_RHSHSC2__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC2__AS_M_L 5U +#define XHC_RHSHSC2__AS_M_R 4U +#define XHC_RHSHSC2__AS_M_WIDTH 2U +#define XHC_RHSHSC2__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC2__CMD_L 3U +#define XHC_RHSHSC2__CMD_R 2U +#define XHC_RHSHSC2__CMD_WIDTH 2U +#define XHC_RHSHSC2__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC2__reserved 1U +#define XHC_RHSHSC2__reserved_L 1U +#define XHC_RHSHSC2__reserved_R 1U +#define XHC_RHSHSC2__reserved_WIDTH 1U +#define XHC_RHSHSC2__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC2__STB 0U +#define XHC_RHSHSC2__STB_L 0U +#define XHC_RHSHSC2__STB_R 0U +#define XHC_RHSHSC2__STB_WIDTH 1U +#define XHC_RHSHSC2__STB_RESETVALUE 0x0U +#define XHC_RHSHSC2__RESERVED_L 15U +#define XHC_RHSHSC2__RESERVED_R 8U +#define XHC_RHSHSC2_WIDTH 32U +#define XHC_RHSHSC2__WIDTH 32U +#define XHC_RHSHSC2_ALL_L 31U +#define XHC_RHSHSC2_ALL_R 0U +#define XHC_RHSHSC2__ALL_L 31U +#define XHC_RHSHSC2__ALL_R 0U +#define XHC_RHSHSC2_DATAMASK 0xffff00ffU +#define XHC_RHSHSC2_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC2_RESETVALUE 0x00000000U + +#define XHC_RHSHSR2_OFFSET 0xca4U +#define XHC_RHSHSR2_BASE 0xca4U +#define XHC_RHSHSR2__C2U_L 31U +#define XHC_RHSHSR2__C2U_R 24U +#define XHC_RHSHSR2__C2U_WIDTH 8U +#define XHC_RHSHSR2__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR2__C1U_L 23U +#define XHC_RHSHSR2__C1U_R 16U +#define XHC_RHSHSR2__C1U_WIDTH 8U +#define XHC_RHSHSR2__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR2__RCV_L 15U +#define XHC_RHSHSR2__RCV_R 8U +#define XHC_RHSHSR2__RCV_WIDTH 8U +#define XHC_RHSHSR2__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR2__RTY_L 7U +#define XHC_RHSHSR2__RTY_R 0U +#define XHC_RHSHSR2__RTY_WIDTH 8U +#define XHC_RHSHSR2__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR2_WIDTH 32U +#define XHC_RHSHSR2__WIDTH 32U +#define XHC_RHSHSR2_ALL_L 31U +#define XHC_RHSHSR2_ALL_R 0U +#define XHC_RHSHSR2__ALL_L 31U +#define XHC_RHSHSR2__ALL_R 0U +#define XHC_RHSHSR2_DATAMASK 0xffffffffU +#define XHC_RHSHSR2_RDWRMASK 0x00000000U +#define XHC_RHSHSR2_RESETVALUE 0x00000000U + +#define XHC_RHSHSC3_OFFSET 0xca8U +#define XHC_RHSHSC3_BASE 0xca8U +#define XHC_RHSHSC3__TMR_L 31U +#define XHC_RHSHSC3__TMR_R 16U +#define XHC_RHSHSC3__TMR_WIDTH 16U +#define XHC_RHSHSC3__TMR_RESETVALUE 0x0000U +#define XHC_RHSHSC3__RSL_L 7U +#define XHC_RHSHSC3__RSL_R 6U +#define XHC_RHSHSC3__RSL_WIDTH 2U +#define XHC_RHSHSC3__RSL_RESETVALUE 0x0U +#define XHC_RHSHSC3__AS_M_L 5U +#define XHC_RHSHSC3__AS_M_R 4U +#define XHC_RHSHSC3__AS_M_WIDTH 2U +#define XHC_RHSHSC3__AS_M_RESETVALUE 0x0U +#define XHC_RHSHSC3__CMD_L 3U +#define XHC_RHSHSC3__CMD_R 2U +#define XHC_RHSHSC3__CMD_WIDTH 2U +#define XHC_RHSHSC3__CMD_RESETVALUE 0x0U +#define XHC_RHSHSC3__reserved 1U +#define XHC_RHSHSC3__reserved_L 1U +#define XHC_RHSHSC3__reserved_R 1U +#define XHC_RHSHSC3__reserved_WIDTH 1U +#define XHC_RHSHSC3__reserved_RESETVALUE 0x0U +#define XHC_RHSHSC3__STB 0U +#define XHC_RHSHSC3__STB_L 0U +#define XHC_RHSHSC3__STB_R 0U +#define XHC_RHSHSC3__STB_WIDTH 1U +#define XHC_RHSHSC3__STB_RESETVALUE 0x0U +#define XHC_RHSHSC3__RESERVED_L 15U +#define XHC_RHSHSC3__RESERVED_R 8U +#define XHC_RHSHSC3_WIDTH 32U +#define XHC_RHSHSC3__WIDTH 32U +#define XHC_RHSHSC3_ALL_L 31U +#define XHC_RHSHSC3_ALL_R 0U +#define XHC_RHSHSC3__ALL_L 31U +#define XHC_RHSHSC3__ALL_R 0U +#define XHC_RHSHSC3_DATAMASK 0xffff00ffU +#define XHC_RHSHSC3_RDWRMASK 0x0000ff00U +#define XHC_RHSHSC3_RESETVALUE 0x00000000U + +#define XHC_RHSHSR3_OFFSET 0xcacU +#define XHC_RHSHSR3_BASE 0xcacU +#define XHC_RHSHSR3__C2U_L 31U +#define XHC_RHSHSR3__C2U_R 24U +#define XHC_RHSHSR3__C2U_WIDTH 8U +#define XHC_RHSHSR3__C2U_RESETVALUE 0x00U +#define XHC_RHSHSR3__C1U_L 23U +#define XHC_RHSHSR3__C1U_R 16U +#define XHC_RHSHSR3__C1U_WIDTH 8U +#define XHC_RHSHSR3__C1U_RESETVALUE 0x00U +#define XHC_RHSHSR3__RCV_L 15U +#define XHC_RHSHSR3__RCV_R 8U +#define XHC_RHSHSR3__RCV_WIDTH 8U +#define XHC_RHSHSR3__RCV_RESETVALUE 0x00U +#define XHC_RHSHSR3__RTY_L 7U +#define XHC_RHSHSR3__RTY_R 0U +#define XHC_RHSHSR3__RTY_WIDTH 8U +#define XHC_RHSHSR3__RTY_RESETVALUE 0x00U +#define XHC_RHSHSR3_WIDTH 32U +#define XHC_RHSHSR3__WIDTH 32U +#define XHC_RHSHSR3_ALL_L 31U +#define XHC_RHSHSR3_ALL_R 0U +#define XHC_RHSHSR3__ALL_L 31U +#define XHC_RHSHSR3__ALL_R 0U +#define XHC_RHSHSR3_DATAMASK 0xffffffffU +#define XHC_RHSHSR3_RDWRMASK 0x00000000U +#define XHC_RHSHSR3_RESETVALUE 0x00000000U + +#define XHC_ECHSSP_OFFSET 0xcb0U +#define XHC_ECHSSP_BASE 0xcb0U +#define XHC_ECHSSP__reserved_L 31U +#define XHC_ECHSSP__reserved_R 16U +#define XHC_ECHSSP__reserved_WIDTH 16U +#define XHC_ECHSSP__reserved_RESETVALUE 0x0000U +#define XHC_ECHSSP__NCP_L 15U +#define XHC_ECHSSP__NCP_R 8U +#define XHC_ECHSSP__NCP_WIDTH 8U +#define XHC_ECHSSP__NCP_RESETVALUE 0x04U +#define XHC_ECHSSP__CID_L 7U +#define XHC_ECHSSP__CID_R 0U +#define XHC_ECHSSP__CID_WIDTH 8U +#define XHC_ECHSSP__CID_RESETVALUE 0xc6U +#define XHC_ECHSSP_WIDTH 32U +#define XHC_ECHSSP__WIDTH 32U +#define XHC_ECHSSP_ALL_L 31U +#define XHC_ECHSSP_ALL_R 0U +#define XHC_ECHSSP__ALL_L 31U +#define XHC_ECHSSP__ALL_R 0U +#define XHC_ECHSSP_DATAMASK 0xffffffffU +#define XHC_ECHSSP_RDWRMASK 0x00000000U +#define XHC_ECHSSP_RESETVALUE 0x000004c6U + +#define XHC_SSPVER_OFFSET 0xcb4U +#define XHC_SSPVER_BASE 0xcb4U +#define XHC_SSPVER__MAJ_L 31U +#define XHC_SSPVER__MAJ_R 28U +#define XHC_SSPVER__MAJ_WIDTH 4U +#define XHC_SSPVER__MAJ_RESETVALUE 0x0U +#define XHC_SSPVER__MIN_L 27U +#define XHC_SSPVER__MIN_R 24U +#define XHC_SSPVER__MIN_WIDTH 4U +#define XHC_SSPVER__MIN_RESETVALUE 0x0U +#define XHC_SSPVER__RLS_L 23U +#define XHC_SSPVER__RLS_R 20U +#define XHC_SSPVER__RLS_WIDTH 4U +#define XHC_SSPVER__RLS_RESETVALUE 0x0U +#define XHC_SSPVER__reserved_L 19U +#define XHC_SSPVER__reserved_R 0U +#define XHC_SSPVER__reserved_WIDTH 20U +#define XHC_SSPVER__reserved_RESETVALUE 0x00000U +#define XHC_SSPVER_WIDTH 32U +#define XHC_SSPVER__WIDTH 32U +#define XHC_SSPVER_ALL_L 31U +#define XHC_SSPVER_ALL_R 0U +#define XHC_SSPVER__ALL_L 31U +#define XHC_SSPVER__ALL_R 0U +#define XHC_SSPVER_DATAMASK 0xffffffffU +#define XHC_SSPVER_RDWRMASK 0x00000000U +#define XHC_SSPVER_RESETVALUE 0x00000000U + +#define XHC_SSPMGN_OFFSET 0xcb8U +#define XHC_SSPMGN_BASE 0xcb8U +#define XHC_SSPMGN__MGN_L 31U +#define XHC_SSPMGN__MGN_R 0U +#define XHC_SSPMGN__MGN_WIDTH 32U +#define XHC_SSPMGN__MGN_RESETVALUE 0x4b535040U +#define XHC_SSPMGN_WIDTH 32U +#define XHC_SSPMGN__WIDTH 32U +#define XHC_SSPMGN_ALL_L 31U +#define XHC_SSPMGN_ALL_R 0U +#define XHC_SSPMGN__ALL_L 31U +#define XHC_SSPMGN__ALL_R 0U +#define XHC_SSPMGN_DATAMASK 0xffffffffU +#define XHC_SSPMGN_RDWRMASK 0x00000000U +#define XHC_SSPMGN_RESETVALUE 0x4b535040U + +#define XHC_ECHFSC2_OFFSET 0xcc0U +#define XHC_ECHFSC2_BASE 0xcc0U +#define XHC_ECHFSC2__reserved_L 31U +#define XHC_ECHFSC2__reserved_R 16U +#define XHC_ECHFSC2__reserved_WIDTH 16U +#define XHC_ECHFSC2__reserved_RESETVALUE 0x0000U +#define XHC_ECHFSC2__NCP_L 15U +#define XHC_ECHFSC2__NCP_R 8U +#define XHC_ECHFSC2__NCP_WIDTH 8U +#define XHC_ECHFSC2__NCP_RESETVALUE 0x50U +#define XHC_ECHFSC2__CID_L 7U +#define XHC_ECHFSC2__CID_R 0U +#define XHC_ECHFSC2__CID_WIDTH 8U +#define XHC_ECHFSC2__CID_RESETVALUE 0xc7U +#define XHC_ECHFSC2_WIDTH 32U +#define XHC_ECHFSC2__WIDTH 32U +#define XHC_ECHFSC2_ALL_L 31U +#define XHC_ECHFSC2_ALL_R 0U +#define XHC_ECHFSC2__ALL_L 31U +#define XHC_ECHFSC2__ALL_R 0U +#define XHC_ECHFSC2_DATAMASK 0xffffffffU +#define XHC_ECHFSC2_RDWRMASK 0x00000000U +#define XHC_ECHFSC2_RESETVALUE 0x000050c7U + +#define XHC_FSC2POC_OFFSET 0xcd4U +#define XHC_FSC2POC_BASE 0xcd4U +#define XHC_FSC2POC__NCS_L 31U +#define XHC_FSC2POC__NCS_R 28U +#define XHC_FSC2POC__NCS_WIDTH 4U +#define XHC_FSC2POC__NCS_RESETVALUE 0x0U +#define XHC_FSC2POC__FSIZ_L 22U +#define XHC_FSC2POC__FSIZ_R 18U +#define XHC_FSC2POC__FSIZ_WIDTH 5U +#define XHC_FSC2POC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__PSIZ_L 16U +#define XHC_FSC2POC__PSIZ_R 12U +#define XHC_FSC2POC__PSIZ_WIDTH 5U +#define XHC_FSC2POC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__reserved_L 11U +#define XHC_FSC2POC__reserved_R 5U +#define XHC_FSC2POC__reserved_WIDTH 7U +#define XHC_FSC2POC__reserved_RESETVALUE 0x0U +#define XHC_FSC2POC__TSIZ_L 4U +#define XHC_FSC2POC__TSIZ_R 0U +#define XHC_FSC2POC__TSIZ_WIDTH 5U +#define XHC_FSC2POC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2POC__RESERVED_L 27U +#define XHC_FSC2POC__RESERVED_R 23U +#define XHC_FSC2POC_WIDTH 32U +#define XHC_FSC2POC__WIDTH 32U +#define XHC_FSC2POC_ALL_L 31U +#define XHC_FSC2POC_ALL_R 0U +#define XHC_FSC2POC__ALL_L 31U +#define XHC_FSC2POC__ALL_R 0U +#define XHC_FSC2POC_DATAMASK 0xf07dffffU +#define XHC_FSC2POC_RDWRMASK 0x0f820000U +#define XHC_FSC2POC_RESETVALUE 0x00000000U + +#define XHC_FSC2GOC_OFFSET 0xcd8U +#define XHC_FSC2GOC_BASE 0xcd8U +#define XHC_FSC2GOC__NCS_L 31U +#define XHC_FSC2GOC__NCS_R 28U +#define XHC_FSC2GOC__NCS_WIDTH 4U +#define XHC_FSC2GOC__NCS_RESETVALUE 0x0U +#define XHC_FSC2GOC__FSIZ_L 22U +#define XHC_FSC2GOC__FSIZ_R 18U +#define XHC_FSC2GOC__FSIZ_WIDTH 5U +#define XHC_FSC2GOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__PSIZ_L 16U +#define XHC_FSC2GOC__PSIZ_R 12U +#define XHC_FSC2GOC__PSIZ_WIDTH 5U +#define XHC_FSC2GOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__reserved_L 11U +#define XHC_FSC2GOC__reserved_R 5U +#define XHC_FSC2GOC__reserved_WIDTH 7U +#define XHC_FSC2GOC__reserved_RESETVALUE 0x0U +#define XHC_FSC2GOC__TSIZ_L 4U +#define XHC_FSC2GOC__TSIZ_R 0U +#define XHC_FSC2GOC__TSIZ_WIDTH 5U +#define XHC_FSC2GOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2GOC__RESERVED_L 27U +#define XHC_FSC2GOC__RESERVED_R 23U +#define XHC_FSC2GOC_WIDTH 32U +#define XHC_FSC2GOC__WIDTH 32U +#define XHC_FSC2GOC_ALL_L 31U +#define XHC_FSC2GOC_ALL_R 0U +#define XHC_FSC2GOC__ALL_L 31U +#define XHC_FSC2GOC__ALL_R 0U +#define XHC_FSC2GOC_DATAMASK 0xf07dffffU +#define XHC_FSC2GOC_RDWRMASK 0x0f820000U +#define XHC_FSC2GOC_RESETVALUE 0x00000000U + +#define XHC_FSC2NOC_OFFSET 0xcdcU +#define XHC_FSC2NOC_BASE 0xcdcU +#define XHC_FSC2NOC__NCS_L 31U +#define XHC_FSC2NOC__NCS_R 28U +#define XHC_FSC2NOC__NCS_WIDTH 4U +#define XHC_FSC2NOC__NCS_RESETVALUE 0x0U +#define XHC_FSC2NOC__FSIZ_L 22U +#define XHC_FSC2NOC__FSIZ_R 18U +#define XHC_FSC2NOC__FSIZ_WIDTH 5U +#define XHC_FSC2NOC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__PSIZ_L 16U +#define XHC_FSC2NOC__PSIZ_R 12U +#define XHC_FSC2NOC__PSIZ_WIDTH 5U +#define XHC_FSC2NOC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__reserved_L 11U +#define XHC_FSC2NOC__reserved_R 5U +#define XHC_FSC2NOC__reserved_WIDTH 7U +#define XHC_FSC2NOC__reserved_RESETVALUE 0x0U +#define XHC_FSC2NOC__TSIZ_L 4U +#define XHC_FSC2NOC__TSIZ_R 0U +#define XHC_FSC2NOC__TSIZ_WIDTH 5U +#define XHC_FSC2NOC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2NOC__RESERVED_L 27U +#define XHC_FSC2NOC__RESERVED_R 23U +#define XHC_FSC2NOC_WIDTH 32U +#define XHC_FSC2NOC__WIDTH 32U +#define XHC_FSC2NOC_ALL_L 31U +#define XHC_FSC2NOC_ALL_R 0U +#define XHC_FSC2NOC__ALL_L 31U +#define XHC_FSC2NOC__ALL_R 0U +#define XHC_FSC2NOC_DATAMASK 0xf07dffffU +#define XHC_FSC2NOC_RDWRMASK 0x0f820000U +#define XHC_FSC2NOC_RESETVALUE 0x00000000U + +#define XHC_FSC2AIC_OFFSET 0xce0U +#define XHC_FSC2AIC_BASE 0xce0U +#define XHC_FSC2AIC__FSIZ_L 22U +#define XHC_FSC2AIC__FSIZ_R 18U +#define XHC_FSC2AIC__FSIZ_WIDTH 5U +#define XHC_FSC2AIC__FSIZ_RESETVALUE 0x0U +#define XHC_FSC2AIC__PSIZ_L 16U +#define XHC_FSC2AIC__PSIZ_R 12U +#define XHC_FSC2AIC__PSIZ_WIDTH 5U +#define XHC_FSC2AIC__PSIZ_RESETVALUE 0x0U +#define XHC_FSC2AIC__reserved_L 11U +#define XHC_FSC2AIC__reserved_R 0U +#define XHC_FSC2AIC__reserved_WIDTH 12U +#define XHC_FSC2AIC__reserved_RESETVALUE 0x000U +#define XHC_FSC2AIC__RESERVED_L 31U +#define XHC_FSC2AIC__RESERVED_R 23U +#define XHC_FSC2AIC_WIDTH 23U +#define XHC_FSC2AIC__WIDTH 23U +#define XHC_FSC2AIC_ALL_L 22U +#define XHC_FSC2AIC_ALL_R 0U +#define XHC_FSC2AIC__ALL_L 22U +#define XHC_FSC2AIC__ALL_R 0U +#define XHC_FSC2AIC_DATAMASK 0x007dffffU +#define XHC_FSC2AIC_RDWRMASK 0xff820000U +#define XHC_FSC2AIC_RESETVALUE 0x000000U + +#define XHC_FSC2PIC_OFFSET 0xce4U +#define XHC_FSC2PIC_BASE 0xce4U +#define XHC_FSC2PIC__NCS_L 31U +#define XHC_FSC2PIC__NCS_R 28U +#define XHC_FSC2PIC__NCS_WIDTH 4U +#define XHC_FSC2PIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2PIC__reserved_L 27U +#define XHC_FSC2PIC__reserved_R 5U +#define XHC_FSC2PIC__reserved_WIDTH 23U +#define XHC_FSC2PIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2PIC__TSIZ_L 4U +#define XHC_FSC2PIC__TSIZ_R 0U +#define XHC_FSC2PIC__TSIZ_WIDTH 5U +#define XHC_FSC2PIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2PIC_WIDTH 32U +#define XHC_FSC2PIC__WIDTH 32U +#define XHC_FSC2PIC_ALL_L 31U +#define XHC_FSC2PIC_ALL_R 0U +#define XHC_FSC2PIC__ALL_L 31U +#define XHC_FSC2PIC__ALL_R 0U +#define XHC_FSC2PIC_DATAMASK 0xffffffffU +#define XHC_FSC2PIC_RDWRMASK 0x00000000U +#define XHC_FSC2PIC_RESETVALUE 0x00000000U + +#define XHC_FSC2GIC_OFFSET 0xce8U +#define XHC_FSC2GIC_BASE 0xce8U +#define XHC_FSC2GIC__NCS_L 31U +#define XHC_FSC2GIC__NCS_R 28U +#define XHC_FSC2GIC__NCS_WIDTH 4U +#define XHC_FSC2GIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2GIC__reserved_L 27U +#define XHC_FSC2GIC__reserved_R 5U +#define XHC_FSC2GIC__reserved_WIDTH 23U +#define XHC_FSC2GIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2GIC__TSIZ_L 4U +#define XHC_FSC2GIC__TSIZ_R 0U +#define XHC_FSC2GIC__TSIZ_WIDTH 5U +#define XHC_FSC2GIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2GIC_WIDTH 32U +#define XHC_FSC2GIC__WIDTH 32U +#define XHC_FSC2GIC_ALL_L 31U +#define XHC_FSC2GIC_ALL_R 0U +#define XHC_FSC2GIC__ALL_L 31U +#define XHC_FSC2GIC__ALL_R 0U +#define XHC_FSC2GIC_DATAMASK 0xffffffffU +#define XHC_FSC2GIC_RDWRMASK 0x00000000U +#define XHC_FSC2GIC_RESETVALUE 0x00000000U + +#define XHC_FSC2NIC_OFFSET 0xcecU +#define XHC_FSC2NIC_BASE 0xcecU +#define XHC_FSC2NIC__NCS_L 31U +#define XHC_FSC2NIC__NCS_R 28U +#define XHC_FSC2NIC__NCS_WIDTH 4U +#define XHC_FSC2NIC__NCS_RESETVALUE 0x0U +#define XHC_FSC2NIC__reserved_L 27U +#define XHC_FSC2NIC__reserved_R 5U +#define XHC_FSC2NIC__reserved_WIDTH 23U +#define XHC_FSC2NIC__reserved_RESETVALUE 0x0U +#define XHC_FSC2NIC__TSIZ_L 4U +#define XHC_FSC2NIC__TSIZ_R 0U +#define XHC_FSC2NIC__TSIZ_WIDTH 5U +#define XHC_FSC2NIC__TSIZ_RESETVALUE 0x0U +#define XHC_FSC2NIC_WIDTH 32U +#define XHC_FSC2NIC__WIDTH 32U +#define XHC_FSC2NIC_ALL_L 31U +#define XHC_FSC2NIC_ALL_R 0U +#define XHC_FSC2NIC__ALL_L 31U +#define XHC_FSC2NIC__ALL_R 0U +#define XHC_FSC2NIC_DATAMASK 0xffffffffU +#define XHC_FSC2NIC_RDWRMASK 0x00000000U +#define XHC_FSC2NIC_RESETVALUE 0x00000000U + +#define XHC_ECHPRT2_OFFSET 0xcf0U +#define XHC_ECHPRT2_BASE 0xcf0U +#define XHC_ECHPRT2__HDP 31U +#define XHC_ECHPRT2__HDP_L 31U +#define XHC_ECHPRT2__HDP_R 31U +#define XHC_ECHPRT2__HDP_WIDTH 1U +#define XHC_ECHPRT2__HDP_RESETVALUE 0x0U +#define XHC_ECHPRT2__FDP 30U +#define XHC_ECHPRT2__FDP_L 30U +#define XHC_ECHPRT2__FDP_R 30U +#define XHC_ECHPRT2__FDP_WIDTH 1U +#define XHC_ECHPRT2__FDP_RESETVALUE 0x0U +#define XHC_ECHPRT2__reserved_L 29U +#define XHC_ECHPRT2__reserved_R 17U +#define XHC_ECHPRT2__reserved_WIDTH 13U +#define XHC_ECHPRT2__reserved_RESETVALUE 0x0U +#define XHC_ECHPRT2__HST 16U +#define XHC_ECHPRT2__HST_L 16U +#define XHC_ECHPRT2__HST_R 16U +#define XHC_ECHPRT2__HST_WIDTH 1U +#define XHC_ECHPRT2__HST_RESETVALUE 0x0U +#define XHC_ECHPRT2__NCP_L 15U +#define XHC_ECHPRT2__NCP_R 8U +#define XHC_ECHPRT2__NCP_WIDTH 8U +#define XHC_ECHPRT2__NCP_RESETVALUE 0x04U +#define XHC_ECHPRT2__CID_L 7U +#define XHC_ECHPRT2__CID_R 0U +#define XHC_ECHPRT2__CID_WIDTH 8U +#define XHC_ECHPRT2__CID_RESETVALUE 0xc8U +#define XHC_ECHPRT2_WIDTH 32U +#define XHC_ECHPRT2__WIDTH 32U +#define XHC_ECHPRT2_ALL_L 31U +#define XHC_ECHPRT2_ALL_R 0U +#define XHC_ECHPRT2__ALL_L 31U +#define XHC_ECHPRT2__ALL_R 0U +#define XHC_ECHPRT2_DATAMASK 0xffffffffU +#define XHC_ECHPRT2_RDWRMASK 0x00000000U +#define XHC_ECHPRT2_RESETVALUE 0x000004c8U + +#define XHC_PRT2HSC_OFFSET 0xcf8U +#define XHC_PRT2HSC_BASE 0xcf8U +#define XHC_PRT2HSC__TMR_L 31U +#define XHC_PRT2HSC__TMR_R 16U +#define XHC_PRT2HSC__TMR_WIDTH 16U +#define XHC_PRT2HSC__TMR_RESETVALUE 0x0000U +#define XHC_PRT2HSC__RSL_L 7U +#define XHC_PRT2HSC__RSL_R 6U +#define XHC_PRT2HSC__RSL_WIDTH 2U +#define XHC_PRT2HSC__RSL_RESETVALUE 0x0U +#define XHC_PRT2HSC__AS_M_L 5U +#define XHC_PRT2HSC__AS_M_R 4U +#define XHC_PRT2HSC__AS_M_WIDTH 2U +#define XHC_PRT2HSC__AS_M_RESETVALUE 0x0U +#define XHC_PRT2HSC__CMD_L 3U +#define XHC_PRT2HSC__CMD_R 2U +#define XHC_PRT2HSC__CMD_WIDTH 2U +#define XHC_PRT2HSC__CMD_RESETVALUE 0x0U +#define XHC_PRT2HSC__reserved 1U +#define XHC_PRT2HSC__reserved_L 1U +#define XHC_PRT2HSC__reserved_R 1U +#define XHC_PRT2HSC__reserved_WIDTH 1U +#define XHC_PRT2HSC__reserved_RESETVALUE 0x0U +#define XHC_PRT2HSC__STB 0U +#define XHC_PRT2HSC__STB_L 0U +#define XHC_PRT2HSC__STB_R 0U +#define XHC_PRT2HSC__STB_WIDTH 1U +#define XHC_PRT2HSC__STB_RESETVALUE 0x0U +#define XHC_PRT2HSC__RESERVED_L 15U +#define XHC_PRT2HSC__RESERVED_R 8U +#define XHC_PRT2HSC_WIDTH 32U +#define XHC_PRT2HSC__WIDTH 32U +#define XHC_PRT2HSC_ALL_L 31U +#define XHC_PRT2HSC_ALL_R 0U +#define XHC_PRT2HSC__ALL_L 31U +#define XHC_PRT2HSC__ALL_R 0U +#define XHC_PRT2HSC_DATAMASK 0xffff00ffU +#define XHC_PRT2HSC_RDWRMASK 0x0000ff00U +#define XHC_PRT2HSC_RESETVALUE 0x00000000U + +#define XHC_PRT2HSR_OFFSET 0xcfcU +#define XHC_PRT2HSR_BASE 0xcfcU +#define XHC_PRT2HSR__RNAK_L 31U +#define XHC_PRT2HSR__RNAK_R 24U +#define XHC_PRT2HSR__RNAK_WIDTH 8U +#define XHC_PRT2HSR__RNAK_RESETVALUE 0x00U +#define XHC_PRT2HSR__HSTX_L 23U +#define XHC_PRT2HSR__HSTX_R 16U +#define XHC_PRT2HSR__HSTX_WIDTH 8U +#define XHC_PRT2HSR__HSTX_RESETVALUE 0x00U +#define XHC_PRT2HSR__HSRX_L 15U +#define XHC_PRT2HSR__HSRX_R 8U +#define XHC_PRT2HSR__HSRX_WIDTH 8U +#define XHC_PRT2HSR__HSRX_RESETVALUE 0x00U +#define XHC_PRT2HSR__SPLT_L 7U +#define XHC_PRT2HSR__SPLT_R 0U +#define XHC_PRT2HSR__SPLT_WIDTH 8U +#define XHC_PRT2HSR__SPLT_RESETVALUE 0x00U +#define XHC_PRT2HSR_WIDTH 32U +#define XHC_PRT2HSR__WIDTH 32U +#define XHC_PRT2HSR_ALL_L 31U +#define XHC_PRT2HSR_ALL_R 0U +#define XHC_PRT2HSR__ALL_L 31U +#define XHC_PRT2HSR__ALL_R 0U +#define XHC_PRT2HSR_DATAMASK 0xffffffffU +#define XHC_PRT2HSR_RDWRMASK 0x00000000U +#define XHC_PRT2HSR_RESETVALUE 0x00000000U + +#define XHC_ECHRH2_OFFSET 0xd00U +#define XHC_ECHRH2_BASE 0xd00U +#define XHC_ECHRH2__MTT 31U +#define XHC_ECHRH2__MTT_L 31U +#define XHC_ECHRH2__MTT_R 31U +#define XHC_ECHRH2__MTT_WIDTH 1U +#define XHC_ECHRH2__MTT_RESETVALUE 0x0U +#define XHC_ECHRH2__RPO_L 30U +#define XHC_ECHRH2__RPO_R 24U +#define XHC_ECHRH2__RPO_WIDTH 7U +#define XHC_ECHRH2__RPO_RESETVALUE 0x0U +#define XHC_ECHRH2__reserved_L 23U +#define XHC_ECHRH2__reserved_R 22U +#define XHC_ECHRH2__reserved_WIDTH 2U +#define XHC_ECHRH2__reserved_RESETVALUE 0x0U +#define XHC_ECHRH2__RPN_L 21U +#define XHC_ECHRH2__RPN_R 20U +#define XHC_ECHRH2__RPN_WIDTH 2U +#define XHC_ECHRH2__RPN_RESETVALUE 0x0U +#define XHC_ECHRH2__DNR_L 19U +#define XHC_ECHRH2__DNR_R 16U +#define XHC_ECHRH2__DNR_WIDTH 4U +#define XHC_ECHRH2__DNR_RESETVALUE 0x0U +#define XHC_ECHRH2__NCP_L 15U +#define XHC_ECHRH2__NCP_R 8U +#define XHC_ECHRH2__NCP_WIDTH 8U +#define XHC_ECHRH2__NCP_RESETVALUE 0x0cU +#define XHC_ECHRH2__CID_L 7U +#define XHC_ECHRH2__CID_R 0U +#define XHC_ECHRH2__CID_WIDTH 8U +#define XHC_ECHRH2__CID_RESETVALUE 0xc9U +#define XHC_ECHRH2_WIDTH 32U +#define XHC_ECHRH2__WIDTH 32U +#define XHC_ECHRH2_ALL_L 31U +#define XHC_ECHRH2_ALL_R 0U +#define XHC_ECHRH2__ALL_L 31U +#define XHC_ECHRH2__ALL_R 0U +#define XHC_ECHRH2_DATAMASK 0xffffffffU +#define XHC_ECHRH2_RDWRMASK 0x00000000U +#define XHC_ECHRH2_RESETVALUE 0x00000cc9U + +#define XHC_RH2DES_OFFSET 0xd04U +#define XHC_RH2DES_BASE 0xd04U +#define XHC_RH2DES__PIS3_L 31U +#define XHC_RH2DES__PIS3_R 30U +#define XHC_RH2DES__PIS3_WIDTH 2U +#define XHC_RH2DES__PIS3_RESETVALUE 0x0U +#define XHC_RH2DES__HIST3 24U +#define XHC_RH2DES__HIST3_L 24U +#define XHC_RH2DES__HIST3_R 24U +#define XHC_RH2DES__HIST3_WIDTH 1U +#define XHC_RH2DES__HIST3_RESETVALUE 0x0U +#define XHC_RH2DES__PIS2_L 23U +#define XHC_RH2DES__PIS2_R 22U +#define XHC_RH2DES__PIS2_WIDTH 2U +#define XHC_RH2DES__PIS2_RESETVALUE 0x0U +#define XHC_RH2DES__HIST2 16U +#define XHC_RH2DES__HIST2_L 16U +#define XHC_RH2DES__HIST2_R 16U +#define XHC_RH2DES__HIST2_WIDTH 1U +#define XHC_RH2DES__HIST2_RESETVALUE 0x0U +#define XHC_RH2DES__PIS1_L 15U +#define XHC_RH2DES__PIS1_R 14U +#define XHC_RH2DES__PIS1_WIDTH 2U +#define XHC_RH2DES__PIS1_RESETVALUE 0x0U +#define XHC_RH2DES__HIST1 8U +#define XHC_RH2DES__HIST1_L 8U +#define XHC_RH2DES__HIST1_R 8U +#define XHC_RH2DES__HIST1_WIDTH 1U +#define XHC_RH2DES__HIST1_RESETVALUE 0x0U +#define XHC_RH2DES__PIS0_L 7U +#define XHC_RH2DES__PIS0_R 6U +#define XHC_RH2DES__PIS0_WIDTH 2U +#define XHC_RH2DES__PIS0_RESETVALUE 0x0U +#define XHC_RH2DES__reserved_L 5U +#define XHC_RH2DES__reserved_R 1U +#define XHC_RH2DES__reserved_WIDTH 5U +#define XHC_RH2DES__reserved_RESETVALUE 0x0U +#define XHC_RH2DES__HIST0 0U +#define XHC_RH2DES__HIST0_L 0U +#define XHC_RH2DES__HIST0_R 0U +#define XHC_RH2DES__HIST0_WIDTH 1U +#define XHC_RH2DES__HIST0_RESETVALUE 0x0U +#define XHC_RH2DES__RESERVED_0_L 29U +#define XHC_RH2DES__RESERVED_0_R 25U +#define XHC_RH2DES__RESERVED_1_L 21U +#define XHC_RH2DES__RESERVED_1_R 17U +#define XHC_RH2DES__RESERVED_2_L 13U +#define XHC_RH2DES__RESERVED_2_R 9U +#define XHC_RH2DES__RESERVED_L 29U +#define XHC_RH2DES__RESERVED_R 25U +#define XHC_RH2DES_WIDTH 32U +#define XHC_RH2DES__WIDTH 32U +#define XHC_RH2DES_ALL_L 31U +#define XHC_RH2DES_ALL_R 0U +#define XHC_RH2DES__ALL_L 31U +#define XHC_RH2DES__ALL_R 0U +#define XHC_RH2DES_DATAMASK 0xc1c1c1ffU +#define XHC_RH2DES_RDWRMASK 0x3e3e3e00U +#define XHC_RH2DES_RESETVALUE 0x00000000U + +#define XHC_RH2HSC0_OFFSET 0xd10U +#define XHC_RH2HSC0_BASE 0xd10U +#define XHC_RH2HSC0__TMR_L 31U +#define XHC_RH2HSC0__TMR_R 16U +#define XHC_RH2HSC0__TMR_WIDTH 16U +#define XHC_RH2HSC0__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC0__RSL_L 7U +#define XHC_RH2HSC0__RSL_R 6U +#define XHC_RH2HSC0__RSL_WIDTH 2U +#define XHC_RH2HSC0__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC0__AS_M_L 5U +#define XHC_RH2HSC0__AS_M_R 4U +#define XHC_RH2HSC0__AS_M_WIDTH 2U +#define XHC_RH2HSC0__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC0__CMD_L 3U +#define XHC_RH2HSC0__CMD_R 2U +#define XHC_RH2HSC0__CMD_WIDTH 2U +#define XHC_RH2HSC0__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC0__reserved 1U +#define XHC_RH2HSC0__reserved_L 1U +#define XHC_RH2HSC0__reserved_R 1U +#define XHC_RH2HSC0__reserved_WIDTH 1U +#define XHC_RH2HSC0__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC0__STB 0U +#define XHC_RH2HSC0__STB_L 0U +#define XHC_RH2HSC0__STB_R 0U +#define XHC_RH2HSC0__STB_WIDTH 1U +#define XHC_RH2HSC0__STB_RESETVALUE 0x0U +#define XHC_RH2HSC0__RESERVED_L 15U +#define XHC_RH2HSC0__RESERVED_R 8U +#define XHC_RH2HSC0_WIDTH 32U +#define XHC_RH2HSC0__WIDTH 32U +#define XHC_RH2HSC0_ALL_L 31U +#define XHC_RH2HSC0_ALL_R 0U +#define XHC_RH2HSC0__ALL_L 31U +#define XHC_RH2HSC0__ALL_R 0U +#define XHC_RH2HSC0_DATAMASK 0xffff00ffU +#define XHC_RH2HSC0_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC0_RESETVALUE 0x00000000U + +#define XHC_RH2HSR0_OFFSET 0xd14U +#define XHC_RH2HSR0_BASE 0xd14U +#define XHC_RH2HSR0__C2U_L 31U +#define XHC_RH2HSR0__C2U_R 24U +#define XHC_RH2HSR0__C2U_WIDTH 8U +#define XHC_RH2HSR0__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR0__C1U_L 23U +#define XHC_RH2HSR0__C1U_R 16U +#define XHC_RH2HSR0__C1U_WIDTH 8U +#define XHC_RH2HSR0__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR0__reserved_L 15U +#define XHC_RH2HSR0__reserved_R 8U +#define XHC_RH2HSR0__reserved_WIDTH 8U +#define XHC_RH2HSR0__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR0__RTY_L 7U +#define XHC_RH2HSR0__RTY_R 0U +#define XHC_RH2HSR0__RTY_WIDTH 8U +#define XHC_RH2HSR0__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR0_WIDTH 32U +#define XHC_RH2HSR0__WIDTH 32U +#define XHC_RH2HSR0_ALL_L 31U +#define XHC_RH2HSR0_ALL_R 0U +#define XHC_RH2HSR0__ALL_L 31U +#define XHC_RH2HSR0__ALL_R 0U +#define XHC_RH2HSR0_DATAMASK 0xffffffffU +#define XHC_RH2HSR0_RDWRMASK 0x00000000U +#define XHC_RH2HSR0_RESETVALUE 0x00000000U + +#define XHC_RH2HSC1_OFFSET 0xd18U +#define XHC_RH2HSC1_BASE 0xd18U +#define XHC_RH2HSC1__TMR_L 31U +#define XHC_RH2HSC1__TMR_R 16U +#define XHC_RH2HSC1__TMR_WIDTH 16U +#define XHC_RH2HSC1__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC1__RSL_L 7U +#define XHC_RH2HSC1__RSL_R 6U +#define XHC_RH2HSC1__RSL_WIDTH 2U +#define XHC_RH2HSC1__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC1__AS_M_L 5U +#define XHC_RH2HSC1__AS_M_R 4U +#define XHC_RH2HSC1__AS_M_WIDTH 2U +#define XHC_RH2HSC1__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC1__CMD_L 3U +#define XHC_RH2HSC1__CMD_R 2U +#define XHC_RH2HSC1__CMD_WIDTH 2U +#define XHC_RH2HSC1__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC1__reserved 1U +#define XHC_RH2HSC1__reserved_L 1U +#define XHC_RH2HSC1__reserved_R 1U +#define XHC_RH2HSC1__reserved_WIDTH 1U +#define XHC_RH2HSC1__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC1__STB 0U +#define XHC_RH2HSC1__STB_L 0U +#define XHC_RH2HSC1__STB_R 0U +#define XHC_RH2HSC1__STB_WIDTH 1U +#define XHC_RH2HSC1__STB_RESETVALUE 0x0U +#define XHC_RH2HSC1__RESERVED_L 15U +#define XHC_RH2HSC1__RESERVED_R 8U +#define XHC_RH2HSC1_WIDTH 32U +#define XHC_RH2HSC1__WIDTH 32U +#define XHC_RH2HSC1_ALL_L 31U +#define XHC_RH2HSC1_ALL_R 0U +#define XHC_RH2HSC1__ALL_L 31U +#define XHC_RH2HSC1__ALL_R 0U +#define XHC_RH2HSC1_DATAMASK 0xffff00ffU +#define XHC_RH2HSC1_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC1_RESETVALUE 0x00000000U + +#define XHC_RH2HSR1_OFFSET 0xd1cU +#define XHC_RH2HSR1_BASE 0xd1cU +#define XHC_RH2HSR1__C2U_L 31U +#define XHC_RH2HSR1__C2U_R 24U +#define XHC_RH2HSR1__C2U_WIDTH 8U +#define XHC_RH2HSR1__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR1__C1U_L 23U +#define XHC_RH2HSR1__C1U_R 16U +#define XHC_RH2HSR1__C1U_WIDTH 8U +#define XHC_RH2HSR1__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR1__reserved_L 15U +#define XHC_RH2HSR1__reserved_R 8U +#define XHC_RH2HSR1__reserved_WIDTH 8U +#define XHC_RH2HSR1__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR1__RTY_L 7U +#define XHC_RH2HSR1__RTY_R 0U +#define XHC_RH2HSR1__RTY_WIDTH 8U +#define XHC_RH2HSR1__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR1_WIDTH 32U +#define XHC_RH2HSR1__WIDTH 32U +#define XHC_RH2HSR1_ALL_L 31U +#define XHC_RH2HSR1_ALL_R 0U +#define XHC_RH2HSR1__ALL_L 31U +#define XHC_RH2HSR1__ALL_R 0U +#define XHC_RH2HSR1_DATAMASK 0xffffffffU +#define XHC_RH2HSR1_RDWRMASK 0x00000000U +#define XHC_RH2HSR1_RESETVALUE 0x00000000U + +#define XHC_RH2HSC2_OFFSET 0xd20U +#define XHC_RH2HSC2_BASE 0xd20U +#define XHC_RH2HSC2__TMR_L 31U +#define XHC_RH2HSC2__TMR_R 16U +#define XHC_RH2HSC2__TMR_WIDTH 16U +#define XHC_RH2HSC2__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC2__RSL_L 7U +#define XHC_RH2HSC2__RSL_R 6U +#define XHC_RH2HSC2__RSL_WIDTH 2U +#define XHC_RH2HSC2__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC2__AS_M_L 5U +#define XHC_RH2HSC2__AS_M_R 4U +#define XHC_RH2HSC2__AS_M_WIDTH 2U +#define XHC_RH2HSC2__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC2__CMD_L 3U +#define XHC_RH2HSC2__CMD_R 2U +#define XHC_RH2HSC2__CMD_WIDTH 2U +#define XHC_RH2HSC2__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC2__reserved 1U +#define XHC_RH2HSC2__reserved_L 1U +#define XHC_RH2HSC2__reserved_R 1U +#define XHC_RH2HSC2__reserved_WIDTH 1U +#define XHC_RH2HSC2__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC2__STB 0U +#define XHC_RH2HSC2__STB_L 0U +#define XHC_RH2HSC2__STB_R 0U +#define XHC_RH2HSC2__STB_WIDTH 1U +#define XHC_RH2HSC2__STB_RESETVALUE 0x0U +#define XHC_RH2HSC2__RESERVED_L 15U +#define XHC_RH2HSC2__RESERVED_R 8U +#define XHC_RH2HSC2_WIDTH 32U +#define XHC_RH2HSC2__WIDTH 32U +#define XHC_RH2HSC2_ALL_L 31U +#define XHC_RH2HSC2_ALL_R 0U +#define XHC_RH2HSC2__ALL_L 31U +#define XHC_RH2HSC2__ALL_R 0U +#define XHC_RH2HSC2_DATAMASK 0xffff00ffU +#define XHC_RH2HSC2_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC2_RESETVALUE 0x00000000U + +#define XHC_RH2HSR2_OFFSET 0xd24U +#define XHC_RH2HSR2_BASE 0xd24U +#define XHC_RH2HSR2__C2U_L 31U +#define XHC_RH2HSR2__C2U_R 24U +#define XHC_RH2HSR2__C2U_WIDTH 8U +#define XHC_RH2HSR2__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR2__C1U_L 23U +#define XHC_RH2HSR2__C1U_R 16U +#define XHC_RH2HSR2__C1U_WIDTH 8U +#define XHC_RH2HSR2__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR2__reserved_L 15U +#define XHC_RH2HSR2__reserved_R 8U +#define XHC_RH2HSR2__reserved_WIDTH 8U +#define XHC_RH2HSR2__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR2__RTY_L 7U +#define XHC_RH2HSR2__RTY_R 0U +#define XHC_RH2HSR2__RTY_WIDTH 8U +#define XHC_RH2HSR2__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR2_WIDTH 32U +#define XHC_RH2HSR2__WIDTH 32U +#define XHC_RH2HSR2_ALL_L 31U +#define XHC_RH2HSR2_ALL_R 0U +#define XHC_RH2HSR2__ALL_L 31U +#define XHC_RH2HSR2__ALL_R 0U +#define XHC_RH2HSR2_DATAMASK 0xffffffffU +#define XHC_RH2HSR2_RDWRMASK 0x00000000U +#define XHC_RH2HSR2_RESETVALUE 0x00000000U + +#define XHC_RH2HSC3_OFFSET 0xd28U +#define XHC_RH2HSC3_BASE 0xd28U +#define XHC_RH2HSC3__TMR_L 31U +#define XHC_RH2HSC3__TMR_R 16U +#define XHC_RH2HSC3__TMR_WIDTH 16U +#define XHC_RH2HSC3__TMR_RESETVALUE 0x0000U +#define XHC_RH2HSC3__RSL_L 7U +#define XHC_RH2HSC3__RSL_R 6U +#define XHC_RH2HSC3__RSL_WIDTH 2U +#define XHC_RH2HSC3__RSL_RESETVALUE 0x0U +#define XHC_RH2HSC3__AS_M_L 5U +#define XHC_RH2HSC3__AS_M_R 4U +#define XHC_RH2HSC3__AS_M_WIDTH 2U +#define XHC_RH2HSC3__AS_M_RESETVALUE 0x0U +#define XHC_RH2HSC3__CMD_L 3U +#define XHC_RH2HSC3__CMD_R 2U +#define XHC_RH2HSC3__CMD_WIDTH 2U +#define XHC_RH2HSC3__CMD_RESETVALUE 0x0U +#define XHC_RH2HSC3__reserved 1U +#define XHC_RH2HSC3__reserved_L 1U +#define XHC_RH2HSC3__reserved_R 1U +#define XHC_RH2HSC3__reserved_WIDTH 1U +#define XHC_RH2HSC3__reserved_RESETVALUE 0x0U +#define XHC_RH2HSC3__STB 0U +#define XHC_RH2HSC3__STB_L 0U +#define XHC_RH2HSC3__STB_R 0U +#define XHC_RH2HSC3__STB_WIDTH 1U +#define XHC_RH2HSC3__STB_RESETVALUE 0x0U +#define XHC_RH2HSC3__RESERVED_L 15U +#define XHC_RH2HSC3__RESERVED_R 8U +#define XHC_RH2HSC3_WIDTH 32U +#define XHC_RH2HSC3__WIDTH 32U +#define XHC_RH2HSC3_ALL_L 31U +#define XHC_RH2HSC3_ALL_R 0U +#define XHC_RH2HSC3__ALL_L 31U +#define XHC_RH2HSC3__ALL_R 0U +#define XHC_RH2HSC3_DATAMASK 0xffff00ffU +#define XHC_RH2HSC3_RDWRMASK 0x0000ff00U +#define XHC_RH2HSC3_RESETVALUE 0x00000000U + +#define XHC_RH2HSR3_OFFSET 0xd2cU +#define XHC_RH2HSR3_BASE 0xd2cU +#define XHC_RH2HSR3__C2U_L 31U +#define XHC_RH2HSR3__C2U_R 24U +#define XHC_RH2HSR3__C2U_WIDTH 8U +#define XHC_RH2HSR3__C2U_RESETVALUE 0x00U +#define XHC_RH2HSR3__C1U_L 23U +#define XHC_RH2HSR3__C1U_R 16U +#define XHC_RH2HSR3__C1U_WIDTH 8U +#define XHC_RH2HSR3__C1U_RESETVALUE 0x00U +#define XHC_RH2HSR3__reserved_L 15U +#define XHC_RH2HSR3__reserved_R 8U +#define XHC_RH2HSR3__reserved_WIDTH 8U +#define XHC_RH2HSR3__reserved_RESETVALUE 0x00U +#define XHC_RH2HSR3__RTY_L 7U +#define XHC_RH2HSR3__RTY_R 0U +#define XHC_RH2HSR3__RTY_WIDTH 8U +#define XHC_RH2HSR3__RTY_RESETVALUE 0x00U +#define XHC_RH2HSR3_WIDTH 32U +#define XHC_RH2HSR3__WIDTH 32U +#define XHC_RH2HSR3_ALL_L 31U +#define XHC_RH2HSR3_ALL_R 0U +#define XHC_RH2HSR3__ALL_L 31U +#define XHC_RH2HSR3__ALL_R 0U +#define XHC_RH2HSR3_DATAMASK 0xffffffffU +#define XHC_RH2HSR3_RDWRMASK 0x00000000U +#define XHC_RH2HSR3_RESETVALUE 0x00000000U + +#define XHC_ECHU2P_OFFSET 0xd30U +#define XHC_ECHU2P_BASE 0xd30U +#define XHC_ECHU2P__reserved_L 31U +#define XHC_ECHU2P__reserved_R 16U +#define XHC_ECHU2P__reserved_WIDTH 16U +#define XHC_ECHU2P__reserved_RESETVALUE 0x0000U +#define XHC_ECHU2P__NCP_L 15U +#define XHC_ECHU2P__NCP_R 8U +#define XHC_ECHU2P__NCP_WIDTH 8U +#define XHC_ECHU2P__NCP_RESETVALUE 0x04U +#define XHC_ECHU2P__CID_L 7U +#define XHC_ECHU2P__CID_R 0U +#define XHC_ECHU2P__CID_WIDTH 8U +#define XHC_ECHU2P__CID_RESETVALUE 0xcaU +#define XHC_ECHU2P_WIDTH 32U +#define XHC_ECHU2P__WIDTH 32U +#define XHC_ECHU2P_ALL_L 31U +#define XHC_ECHU2P_ALL_R 0U +#define XHC_ECHU2P__ALL_L 31U +#define XHC_ECHU2P__ALL_R 0U +#define XHC_ECHU2P_DATAMASK 0xffffffffU +#define XHC_ECHU2P_RDWRMASK 0x00000000U +#define XHC_ECHU2P_RESETVALUE 0x000004caU + +#define XHC_U2PVER_OFFSET 0xd34U +#define XHC_U2PVER_BASE 0xd34U +#define XHC_U2PVER__MAJ_L 31U +#define XHC_U2PVER__MAJ_R 28U +#define XHC_U2PVER__MAJ_WIDTH 4U +#define XHC_U2PVER__MAJ_RESETVALUE 0x0U +#define XHC_U2PVER__MIN_L 27U +#define XHC_U2PVER__MIN_R 24U +#define XHC_U2PVER__MIN_WIDTH 4U +#define XHC_U2PVER__MIN_RESETVALUE 0x0U +#define XHC_U2PVER__RLS_L 23U +#define XHC_U2PVER__RLS_R 20U +#define XHC_U2PVER__RLS_WIDTH 4U +#define XHC_U2PVER__RLS_RESETVALUE 0x0U +#define XHC_U2PVER__reserved_L 19U +#define XHC_U2PVER__reserved_R 0U +#define XHC_U2PVER__reserved_WIDTH 20U +#define XHC_U2PVER__reserved_RESETVALUE 0x00000U +#define XHC_U2PVER_WIDTH 32U +#define XHC_U2PVER__WIDTH 32U +#define XHC_U2PVER_ALL_L 31U +#define XHC_U2PVER_ALL_R 0U +#define XHC_U2PVER__ALL_L 31U +#define XHC_U2PVER__ALL_R 0U +#define XHC_U2PVER_DATAMASK 0xffffffffU +#define XHC_U2PVER_RDWRMASK 0x00000000U +#define XHC_U2PVER_RESETVALUE 0x00000000U + +#define XHC_U2PMGN_OFFSET 0xd38U +#define XHC_U2PMGN_BASE 0xd38U +#define XHC_U2PMGN__MGN_L 31U +#define XHC_U2PMGN__MGN_R 0U +#define XHC_U2PMGN__MGN_WIDTH 32U +#define XHC_U2PMGN__MGN_RESETVALUE 0x4b534b4dU +#define XHC_U2PMGN_WIDTH 32U +#define XHC_U2PMGN__WIDTH 32U +#define XHC_U2PMGN_ALL_L 31U +#define XHC_U2PMGN_ALL_R 0U +#define XHC_U2PMGN__ALL_L 31U +#define XHC_U2PMGN__ALL_R 0U +#define XHC_U2PMGN_DATAMASK 0xffffffffU +#define XHC_U2PMGN_RDWRMASK 0x00000000U +#define XHC_U2PMGN_RESETVALUE 0x4b534b4dU + +#define XHC_ECHRSV2_OFFSET 0xd40U +#define XHC_ECHRSV2_BASE 0xd40U +#define XHC_ECHRSV2__reserved_L 31U +#define XHC_ECHRSV2__reserved_R 16U +#define XHC_ECHRSV2__reserved_WIDTH 16U +#define XHC_ECHRSV2__reserved_RESETVALUE 0x0000U +#define XHC_ECHRSV2__NCP_L 15U +#define XHC_ECHRSV2__NCP_R 8U +#define XHC_ECHRSV2__NCP_WIDTH 8U +#define XHC_ECHRSV2__NCP_RESETVALUE 0x00U +#define XHC_ECHRSV2__CID_L 7U +#define XHC_ECHRSV2__CID_R 0U +#define XHC_ECHRSV2__CID_WIDTH 8U +#define XHC_ECHRSV2__CID_RESETVALUE 0xffU +#define XHC_ECHRSV2_WIDTH 32U +#define XHC_ECHRSV2__WIDTH 32U +#define XHC_ECHRSV2_ALL_L 31U +#define XHC_ECHRSV2_ALL_R 0U +#define XHC_ECHRSV2__ALL_L 31U +#define XHC_ECHRSV2__ALL_R 0U +#define XHC_ECHRSV2_DATAMASK 0xffffffffU +#define XHC_ECHRSV2_RDWRMASK 0x00000000U +#define XHC_ECHRSV2_RESETVALUE 0x000000ffU + +#define XHC_ECHIRA_OFFSET 0xf90U +#define XHC_ECHIRA_BASE 0xf90U +#define XHC_ECHIRA__reserved_L 31U +#define XHC_ECHIRA__reserved_R 16U +#define XHC_ECHIRA__reserved_WIDTH 16U +#define XHC_ECHIRA__reserved_RESETVALUE 0x0000U +#define XHC_ECHIRA__NCP_L 15U +#define XHC_ECHIRA__NCP_R 8U +#define XHC_ECHIRA__NCP_WIDTH 8U +#define XHC_ECHIRA__NCP_RESETVALUE 0x04U +#define XHC_ECHIRA__CID_L 7U +#define XHC_ECHIRA__CID_R 0U +#define XHC_ECHIRA__CID_WIDTH 8U +#define XHC_ECHIRA__CID_RESETVALUE 0xfdU +#define XHC_ECHIRA_WIDTH 32U +#define XHC_ECHIRA__WIDTH 32U +#define XHC_ECHIRA_ALL_L 31U +#define XHC_ECHIRA_ALL_R 0U +#define XHC_ECHIRA__ALL_L 31U +#define XHC_ECHIRA__ALL_R 0U +#define XHC_ECHIRA_DATAMASK 0xffffffffU +#define XHC_ECHIRA_RDWRMASK 0x00000000U +#define XHC_ECHIRA_RESETVALUE 0x000004fdU + +#define XHC_IRAADR_OFFSET 0xf98U +#define XHC_IRAADR_BASE 0xf98U +#define XHC_IRAADR__ADR_L 23U +#define XHC_IRAADR__ADR_R 2U +#define XHC_IRAADR__ADR_WIDTH 22U +#define XHC_IRAADR__ADR_RESETVALUE 0x0U +#define XHC_IRAADR__reserved 1U +#define XHC_IRAADR__reserved_L 1U +#define XHC_IRAADR__reserved_R 1U +#define XHC_IRAADR__reserved_WIDTH 1U +#define XHC_IRAADR__reserved_RESETVALUE 0x0U +#define XHC_IRAADR__MOD 0U +#define XHC_IRAADR__MOD_L 0U +#define XHC_IRAADR__MOD_R 0U +#define XHC_IRAADR__MOD_WIDTH 1U +#define XHC_IRAADR__MOD_RESETVALUE 0x0U +#define XHC_IRAADR__RESERVED_L 31U +#define XHC_IRAADR__RESERVED_R 24U +#define XHC_IRAADR_WIDTH 24U +#define XHC_IRAADR__WIDTH 24U +#define XHC_IRAADR_ALL_L 23U +#define XHC_IRAADR_ALL_R 0U +#define XHC_IRAADR__ALL_L 23U +#define XHC_IRAADR__ALL_R 0U +#define XHC_IRAADR_DATAMASK 0x00ffffffU +#define XHC_IRAADR_RDWRMASK 0xff000000U +#define XHC_IRAADR_RESETVALUE 0x000000U + +#define XHC_IRADAT_OFFSET 0xf9cU +#define XHC_IRADAT_BASE 0xf9cU +#define XHC_IRADAT__DAT_L 31U +#define XHC_IRADAT__DAT_R 0U +#define XHC_IRADAT__DAT_WIDTH 32U +#define XHC_IRADAT__DAT_RESETVALUE 0x00000000U +#define XHC_IRADAT_WIDTH 32U +#define XHC_IRADAT__WIDTH 32U +#define XHC_IRADAT_ALL_L 31U +#define XHC_IRADAT_ALL_R 0U +#define XHC_IRADAT__ALL_L 31U +#define XHC_IRADAT__ALL_R 0U +#define XHC_IRADAT_DATAMASK 0xffffffffU +#define XHC_IRADAT_RDWRMASK 0x00000000U +#define XHC_IRADAT_RESETVALUE 0x00000000U + + +#define XHC_ECHHST_OFFSET 0xfa0U +#define XHC_ECHHST_BASE 0xfa0U +#define XHC_ECHHST__CCC 31U +#define XHC_ECHHST__CCC_L 31U +#define XHC_ECHHST__CCC_R 31U +#define XHC_ECHHST__CCC_WIDTH 1U +#define XHC_ECHHST__CCC_RESETVALUE 0x1U +#define XHC_ECHHST__PME 30U +#define XHC_ECHHST__PME_L 30U +#define XHC_ECHHST__PME_R 30U +#define XHC_ECHHST__PME_WIDTH 1U +#define XHC_ECHHST__PME_RESETVALUE 0x0U +#define XHC_ECHHST__AUX_L 29U +#define XHC_ECHHST__AUX_R 24U +#define XHC_ECHHST__AUX_WIDTH 6U +#define XHC_ECHHST__AUX_RESETVALUE 0x0U +#define XHC_ECHHST__IRA 20U +#define XHC_ECHHST__IRA_L 20U +#define XHC_ECHHST__IRA_R 20U +#define XHC_ECHHST__IRA_WIDTH 1U +#define XHC_ECHHST__IRA_RESETVALUE 0x0U +#define XHC_ECHHST__ULS 19U +#define XHC_ECHHST__ULS_L 19U +#define XHC_ECHHST__ULS_R 19U +#define XHC_ECHHST__ULS_WIDTH 1U +#define XHC_ECHHST__ULS_RESETVALUE 0x0U +#define XHC_ECHHST__reserved 18U +#define XHC_ECHHST__reserved_L 18U +#define XHC_ECHHST__reserved_R 18U +#define XHC_ECHHST__reserved_WIDTH 1U +#define XHC_ECHHST__reserved_RESETVALUE 0x0U +#define XHC_ECHHST__TEDA 17U +#define XHC_ECHHST__TEDA_L 17U +#define XHC_ECHHST__TEDA_R 17U +#define XHC_ECHHST__TEDA_WIDTH 1U +#define XHC_ECHHST__TEDA_RESETVALUE 0x0U +#define XHC_ECHHST__FSW 16U +#define XHC_ECHHST__FSW_L 16U +#define XHC_ECHHST__FSW_R 16U +#define XHC_ECHHST__FSW_WIDTH 1U +#define XHC_ECHHST__FSW_RESETVALUE 0x1U +#define XHC_ECHHST__NCP_L 15U +#define XHC_ECHHST__NCP_R 8U +#define XHC_ECHHST__NCP_WIDTH 8U +#define XHC_ECHHST__NCP_RESETVALUE 0x04U +#define XHC_ECHHST__CID_L 7U +#define XHC_ECHHST__CID_R 0U +#define XHC_ECHHST__CID_WIDTH 8U +#define XHC_ECHHST__CID_RESETVALUE 0xfcU +#define XHC_ECHHST__RESERVED_L 23U +#define XHC_ECHHST__RESERVED_R 21U +#define XHC_ECHHST_WIDTH 32U +#define XHC_ECHHST__WIDTH 32U +#define XHC_ECHHST_ALL_L 31U +#define XHC_ECHHST_ALL_R 0U +#define XHC_ECHHST__ALL_L 31U +#define XHC_ECHHST__ALL_R 0U +#define XHC_ECHHST_DATAMASK 0xff1fffffU +#define XHC_ECHHST_RDWRMASK 0x00e00000U +#define XHC_ECHHST_RESETVALUE 0x800104fcU + +#define XHC_HSTDBG_OFFSET 0xfa4U +#define XHC_HSTDBG_BASE 0xfa4U +#define XHC_HSTDBG__ETE 31U +#define XHC_HSTDBG__ETE_L 31U +#define XHC_HSTDBG__ETE_R 31U +#define XHC_HSTDBG__ETE_WIDTH 1U +#define XHC_HSTDBG__ETE_RESETVALUE 0x0U +#define XHC_HSTDBG__reserved_L 30U +#define XHC_HSTDBG__reserved_R 16U +#define XHC_HSTDBG__reserved_WIDTH 15U +#define XHC_HSTDBG__reserved_RESETVALUE 0x0U +#define XHC_HSTDBG__OUTP_L 15U +#define XHC_HSTDBG__OUTP_R 8U +#define XHC_HSTDBG__OUTP_WIDTH 8U +#define XHC_HSTDBG__OUTP_RESETVALUE 0x00U +#define XHC_HSTDBG__INP_L 7U +#define XHC_HSTDBG__INP_R 0U +#define XHC_HSTDBG__INP_WIDTH 8U +#define XHC_HSTDBG__INP_RESETVALUE 0x00U +#define XHC_HSTDBG_WIDTH 32U +#define XHC_HSTDBG__WIDTH 32U +#define XHC_HSTDBG_ALL_L 31U +#define XHC_HSTDBG_ALL_R 0U +#define XHC_HSTDBG__ALL_L 31U +#define XHC_HSTDBG__ALL_R 0U +#define XHC_HSTDBG_DATAMASK 0xffffffffU +#define XHC_HSTDBG_RDWRMASK 0x00000000U +#define XHC_HSTDBG_RESETVALUE 0x00000000U + +#define XHC_HSTNPL_OFFSET 0xfa8U +#define XHC_HSTNPL_BASE 0xfa8U +#define XHC_HSTNPL__NPL_L 31U +#define XHC_HSTNPL__NPL_R 9U +#define XHC_HSTNPL__NPL_WIDTH 23U +#define XHC_HSTNPL__NPL_RESETVALUE 0x0U +#define XHC_HSTNPL__reserved_L 8U +#define XHC_HSTNPL__reserved_R 0U +#define XHC_HSTNPL__reserved_WIDTH 9U +#define XHC_HSTNPL__reserved_RESETVALUE 0x0U +#define XHC_HSTNPL_WIDTH 32U +#define XHC_HSTNPL__WIDTH 32U +#define XHC_HSTNPL_ALL_L 31U +#define XHC_HSTNPL_ALL_R 0U +#define XHC_HSTNPL__ALL_L 31U +#define XHC_HSTNPL__ALL_R 0U +#define XHC_HSTNPL_DATAMASK 0xffffffffU +#define XHC_HSTNPL_RDWRMASK 0x00000000U +#define XHC_HSTNPL_RESETVALUE 0x00000000U + +#define XHC_HSTNPH_OFFSET 0xfacU +#define XHC_HSTNPH_BASE 0xfacU +#define XHC_HSTNPH__NPH_L 31U +#define XHC_HSTNPH__NPH_R 0U +#define XHC_HSTNPH__NPH_WIDTH 32U +#define XHC_HSTNPH__NPH_RESETVALUE 0x00000000U +#define XHC_HSTNPH_WIDTH 32U +#define XHC_HSTNPH__WIDTH 32U +#define XHC_HSTNPH_ALL_L 31U +#define XHC_HSTNPH_ALL_R 0U +#define XHC_HSTNPH__ALL_L 31U +#define XHC_HSTNPH__ALL_R 0U +#define XHC_HSTNPH_DATAMASK 0xffffffffU +#define XHC_HSTNPH_RDWRMASK 0x00000000U +#define XHC_HSTNPH_RESETVALUE 0x00000000U + +#define XHC_ECHRBV_OFFSET 0xfb0U +#define XHC_ECHRBV_BASE 0xfb0U +#define XHC_ECHRBV__MAJ_L 31U +#define XHC_ECHRBV__MAJ_R 28U +#define XHC_ECHRBV__MAJ_WIDTH 4U +#define XHC_ECHRBV__MAJ_RESETVALUE 0x0U +#define XHC_ECHRBV__MIN_L 27U +#define XHC_ECHRBV__MIN_R 24U +#define XHC_ECHRBV__MIN_WIDTH 4U +#define XHC_ECHRBV__MIN_RESETVALUE 0x0U +#define XHC_ECHRBV__RLS_L 23U +#define XHC_ECHRBV__RLS_R 16U +#define XHC_ECHRBV__RLS_WIDTH 8U +#define XHC_ECHRBV__RLS_RESETVALUE 0x00U +#define XHC_ECHRBV__NCP_L 15U +#define XHC_ECHRBV__NCP_R 8U +#define XHC_ECHRBV__NCP_WIDTH 8U +#define XHC_ECHRBV__NCP_RESETVALUE 0x00U +#define XHC_ECHRBV__CID_L 7U +#define XHC_ECHRBV__CID_R 0U +#define XHC_ECHRBV__CID_WIDTH 8U +#define XHC_ECHRBV__CID_RESETVALUE 0xfeU +#define XHC_ECHRBV_WIDTH 32U +#define XHC_ECHRBV__WIDTH 32U +#define XHC_ECHRBV_ALL_L 31U +#define XHC_ECHRBV_ALL_R 0U +#define XHC_ECHRBV__ALL_L 31U +#define XHC_ECHRBV__ALL_R 0U +#define XHC_ECHRBV_DATAMASK 0xffffffffU +#define XHC_ECHRBV_RDWRMASK 0x00000000U +#define XHC_ECHRBV_RESETVALUE 0x000000feU + +#define XHC_RBVPDT_OFFSET 0xfb4U +#define XHC_RBVPDT_BASE 0xfb4U +#define XHC_RBVPDT__VDR_L 31U +#define XHC_RBVPDT__VDR_R 16U +#define XHC_RBVPDT__VDR_WIDTH 16U +#define XHC_RBVPDT__VDR_RESETVALUE 0x0a5cU +#define XHC_RBVPDT__PDT_L 15U +#define XHC_RBVPDT__PDT_R 0U +#define XHC_RBVPDT__PDT_WIDTH 16U +#define XHC_RBVPDT__PDT_RESETVALUE 0x0000U +#define XHC_RBVPDT_WIDTH 32U +#define XHC_RBVPDT__WIDTH 32U +#define XHC_RBVPDT_ALL_L 31U +#define XHC_RBVPDT_ALL_R 0U +#define XHC_RBVPDT__ALL_L 31U +#define XHC_RBVPDT__ALL_R 0U +#define XHC_RBVPDT_DATAMASK 0xffffffffU +#define XHC_RBVPDT_RDWRMASK 0x00000000U +#define XHC_RBVPDT_RESETVALUE 0x0a5c0000U + +#define XHC_RBVMGN_OFFSET 0xfbcU +#define XHC_RBVMGN_BASE 0xfbcU +#define XHC_RBVMGN__MGN_L 31U +#define XHC_RBVMGN__MGN_R 0U +#define XHC_RBVMGN__MGN_WIDTH 32U +#define XHC_RBVMGN__MGN_RESETVALUE 0x52535354U +#define XHC_RBVMGN_WIDTH 32U +#define XHC_RBVMGN__WIDTH 32U +#define XHC_RBVMGN_ALL_L 31U +#define XHC_RBVMGN_ALL_R 0U +#define XHC_RBVMGN__ALL_L 31U +#define XHC_RBVMGN__ALL_R 0U +#define XHC_RBVMGN_DATAMASK 0xffffffffU +#define XHC_RBVMGN_RDWRMASK 0x00000000U +#define XHC_RBVMGN_RESETVALUE 0x52535354U + +/* PORTSC field defines */ +#define XHC_PORTSC__PS_LINK_STATE_U0 0U +#define XHC_PORTSC__PS_LINK_STATE_U1 1U +#define XHC_PORTSC__PS_LINK_STATE_U2 2U +#define XHC_PORTSC__PS_LINK_STATE_U3 3U +#define XHC_PORTSC__PS_LINK_STATE_DISABLED 4U +#define XHC_PORTSC__PS_LINK_STATE_RX_DETECT 5U +#define XHC_PORTSC__PS_LINK_STATE_INACTIVE 6U +#define XHC_PORTSC__PS_LINK_STATE_POLLING 7U +#define XHC_PORTSC__PS_LINK_STATE_RECOVERY 8U +#define XHC_PORTSC__PS_LINK_STATE_HOT_RESET 9U +#define XHC_PORTSC__PS_LINK_STATE_COMPLIANCE 10U +#define XHC_PORTSC__PS_LINK_STATE_TEST 11U +#define XHC_PORTSC__PS_LINK_STATE_RESUME 15U + +#define XHC_PORTSC__PS_SPEED_UNDEFINED 0U +#define XHC_PORTSC__PS_FS 1U +#define XHC_PORTSC__PS_LS 2U +#define XHC_PORTSC__PS_HS 3U +#define XHC_PORTSC__PS_SS 4U + +/* macros and inline functions */ + +/* write 64bit ptr 'p' to destination 'd' with offset 'v' */ +inline void WRITE64_REG_PTRL(uint32_t r, uint32_t *p) +{ + uint32_t *ptr = (uint32_t *) (uint64_t) (XHC_BASE + r); + + *ptr = (uint32_t) ((uint64_t) p & (uint64_t) 0xffffffffU); +} + +inline void WRITE64_REG_PTRH(uint32_t r, uint32_t *p) +{ + uint32_t *ptr = (uint32_t *) (uint64_t) (XHC_BASE + r); + + *ptr = (uint32_t) ((uint64_t) p >> 32U); +} + +#define XHC_REG_RD(addr) mmio_read_32(XHC_BASE + addr) + +#define XHC_REG_WR(addr, val) mmio_write_32(XHC_BASE+addr, val) + +#endif /* USBH_XHCI_REGS_H */ + diff --git a/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h b/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h new file mode 100644 index 0000000..30ca910 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/cadence/cdns_uart.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CDNS_UART_H +#define CDNS_UART_H + +#include + +/* This is very minimalistic and will only work in QEMU. */ + +/* CADENCE Registers */ +#define R_UART_CR 0 +#define R_UART_CR_RXRST (1 << 0) /* RX logic reset */ +#define R_UART_CR_TXRST (1 << 1) /* TX logic reset */ +#define R_UART_CR_RX_EN (1 << 2) /* RX enabled */ +#define R_UART_CR_TX_EN (1 << 4) /* TX enabled */ + +#define R_UART_SR 0x2C +#define UART_SR_INTR_REMPTY_BIT 1 +#define UART_SR_INTR_TFUL_BIT 4 +#define UART_SR_INTR_TEMPTY_BIT 3 + +#define R_UART_TX 0x30 +#define R_UART_RX 0x30 + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new Cadence 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_cdns_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* CDNS_UART_H */ diff --git a/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h b/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h new file mode 100644 index 0000000..6beec50 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/cfi/v2m_flash.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef V2M_FLASH_H +#define V2M_FLASH_H + +#include + +/* First bus cycle */ +#define NOR_CMD_READ_ARRAY 0xFF +#define NOR_CMD_READ_ID_CODE 0x90 +#define NOR_CMD_READ_QUERY 0x98 +#define NOR_CMD_READ_STATUS_REG 0x70 +#define NOR_CMD_CLEAR_STATUS_REG 0x50 +#define NOR_CMD_WRITE_TO_BUFFER 0xE8 +#define NOR_CMD_WORD_PROGRAM 0x40 +#define NOR_CMD_BLOCK_ERASE 0x20 +#define NOR_CMD_LOCK_UNLOCK 0x60 +#define NOR_CMD_BLOCK_ERASE_ACK 0xD0 + +/* Second bus cycle */ +#define NOR_LOCK_BLOCK 0x01 +#define NOR_UNLOCK_BLOCK 0xD0 + +/* Status register bits */ +#define NOR_DWS (1 << 7) +#define NOR_ESS (1 << 6) +#define NOR_ES (1 << 5) +#define NOR_PS (1 << 4) +#define NOR_VPPS (1 << 3) +#define NOR_PSS (1 << 2) +#define NOR_BLS (1 << 1) +#define NOR_BWS (1 << 0) + +/* Public API */ +void nor_send_cmd(uintptr_t base_addr, unsigned long cmd); +int nor_word_program(uintptr_t base_addr, unsigned long data); +int nor_lock(uintptr_t base_addr); +int nor_unlock(uintptr_t base_addr); +int nor_erase(uintptr_t base_addr); + +#endif /* V2M_FLASH_H*/ diff --git a/arm-trusted-firmware/include/drivers/clk.h b/arm-trusted-firmware/include/drivers/clk.h new file mode 100644 index 0000000..a18f41f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/clk.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CLK_H +#define CLK_H + +#include + +struct clk_ops { + int (*enable)(unsigned long id); + void (*disable)(unsigned long id); + unsigned long (*get_rate)(unsigned long id); + int (*get_parent)(unsigned long id); + bool (*is_enabled)(unsigned long id); +}; + +int clk_enable(unsigned long id); +void clk_disable(unsigned long id); +unsigned long clk_get_rate(unsigned long id); +bool clk_is_enabled(unsigned long id); +int clk_get_parent(unsigned long id); + +void clk_register(const struct clk_ops *ops); + +#endif /* CLK_H */ diff --git a/arm-trusted-firmware/include/drivers/console.h b/arm-trusted-firmware/include/drivers/console.h new file mode 100644 index 0000000..99bf960 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/console.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONSOLE_H +#define CONSOLE_H + +#include + +#define CONSOLE_T_NEXT (U(0) * REGSZ) +#define CONSOLE_T_FLAGS (U(1) * REGSZ) +#define CONSOLE_T_PUTC (U(2) * REGSZ) +#define CONSOLE_T_GETC (U(3) * REGSZ) +#define CONSOLE_T_FLUSH (U(4) * REGSZ) +#define CONSOLE_T_BASE (U(5) * REGSZ) +#define CONSOLE_T_DRVDATA (U(6) * REGSZ) + +#define CONSOLE_FLAG_BOOT (U(1) << 0) +#define CONSOLE_FLAG_RUNTIME (U(1) << 1) +#define CONSOLE_FLAG_CRASH (U(1) << 2) +/* Bits 3 to 7 reserved for additional scopes in future expansion. */ +#define CONSOLE_FLAG_SCOPE_MASK ((U(1) << 8) - 1) +/* Bits 8 to 31 for non-scope use. */ +#define CONSOLE_FLAG_TRANSLATE_CRLF (U(1) << 8) + +/* Returned by getc callbacks when receive FIFO is empty. */ +#define ERROR_NO_PENDING_CHAR (-1) +/* Returned by console_xxx() if no registered console implements xxx. */ +#define ERROR_NO_VALID_CONSOLE (-128) + +#ifndef __ASSEMBLER__ + +#include + +typedef struct console { + struct console *next; + /* + * Only the low 32 bits are used. The type is u_register_t to align the + * fields of the struct to 64 bits in AArch64 and 32 bits in AArch32 + */ + u_register_t flags; + int (*const putc)(int character, struct console *console); + int (*const getc)(struct console *console); + void (*const flush)(struct console *console); + uintptr_t base; + /* Additional private driver data may follow here. */ +} console_t; + +/* offset macro assertions for console_t */ +#include + +/* + * Add a console_t instance to the console list. This should only be called by + * console drivers after they have initialized all fields in the console + * structure. Platforms seeking to register a new console need to call the + * respective console__register() function instead. + */ +int console_register(console_t *console); +/* Remove a single console_t instance from the console list. Return a pointer to + * the console that was removed if it was found, or NULL if not. */ +console_t *console_unregister(console_t *console); +/* Returns 1 if this console is already registered, 0 if not */ +int console_is_registered(console_t *console); +/* + * Set scope mask of a console that determines in what states it is active. + * By default they are registered with (CONSOLE_FLAG_BOOT|CONSOLE_FLAG_CRASH). + */ +void console_set_scope(console_t *console, unsigned int scope); + +/* Switch to a new global console state (CONSOLE_FLAG_BOOT/RUNTIME/CRASH). */ +void console_switch_state(unsigned int new_state); +/* Output a character on all consoles registered for the current state. */ +int console_putc(int c); +/* Read a character (blocking) from any console registered for current state. */ +int console_getc(void); +/* Flush all consoles registered for the current state. */ +void console_flush(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/console_assertions.h b/arm-trusted-firmware/include/drivers/console_assertions.h new file mode 100644 index 0000000..00caa31 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/console_assertions.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONSOLE_ASSERTIONS_H +#define CONSOLE_ASSERTIONS_H + +#include + +/* + * This file contains some separate assertions about console_t, moved here to + * keep them out of the way. Should only be included from . + */ +CASSERT(CONSOLE_T_NEXT == __builtin_offsetof(console_t, next), + assert_console_t_next_offset_mismatch); +CASSERT(CONSOLE_T_FLAGS == __builtin_offsetof(console_t, flags), + assert_console_t_flags_offset_mismatch); +CASSERT(CONSOLE_T_PUTC == __builtin_offsetof(console_t, putc), + assert_console_t_putc_offset_mismatch); +CASSERT(CONSOLE_T_GETC == __builtin_offsetof(console_t, getc), + assert_console_t_getc_offset_mismatch); +CASSERT(CONSOLE_T_FLUSH == __builtin_offsetof(console_t, flush), + assert_console_t_flush_offset_mismatch); +CASSERT(CONSOLE_T_DRVDATA == sizeof(console_t), + assert_console_t_drvdata_offset_mismatch); + +#endif /* CONSOLE_ASSERTIONS_H */ diff --git a/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h b/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h new file mode 100644 index 0000000..30b39f1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CBMEM_CONSOLE_H +#define CBMEM_CONSOLE_H + +#include + +#define CONSOLE_T_CBMC_SIZE CONSOLE_T_DRVDATA + +#ifndef __ASSEMBLER__ + +typedef struct { + console_t console; + uint32_t size; +} console_cbmc_t; + +int console_cbmc_register(uintptr_t base, console_cbmc_t *console); + +#endif /* __ASSEMBLER__ */ + +#endif /* CBMEM_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/delay_timer.h b/arm-trusted-firmware/include/drivers/delay_timer.h new file mode 100644 index 0000000..20a5543 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/delay_timer.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DELAY_TIMER_H +#define DELAY_TIMER_H + +#include +#include + +#include + +/******************************************************************** + * A simple timer driver providing synchronous delay functionality. + * The driver must be initialized with a structure that provides a + * function pointer to return the timer value and a clock + * multiplier/divider. The ratio of the multiplier and the divider is + * the clock period in microseconds. + ********************************************************************/ + +typedef struct timer_ops { + uint32_t (*get_timer_value)(void); + uint32_t clk_mult; + uint32_t clk_div; +} timer_ops_t; + +static inline uint64_t timeout_cnt_us2cnt(uint32_t us) +{ + return ((uint64_t)us * (uint64_t)read_cntfrq_el0()) / 1000000ULL; +} + +static inline uint64_t timeout_init_us(uint32_t us) +{ + uint64_t cnt = timeout_cnt_us2cnt(us); + + cnt += read_cntpct_el0(); + + return cnt; +} + +static inline bool timeout_elapsed(uint64_t expire_cnt) +{ + return read_cntpct_el0() > expire_cnt; +} + +void mdelay(uint32_t msec); +void udelay(uint32_t usec); +void timer_init(const timer_ops_t *ops_ptr); + +#endif /* DELAY_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/dw_ufs.h b/arm-trusted-firmware/include/drivers/dw_ufs.h new file mode 100644 index 0000000..13e53f1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/dw_ufs.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DW_UFS_H +#define DW_UFS_H + +#include + +/* Bus Throtting */ +#define BUSTHRTL 0xC0 +/* Outstanding OCP Requests */ +#define OOCPR 0xC4 +/* Fatal Error Interrupt Enable */ +#define FEIE 0xC8 +/* C-Port Direct Access Configuration register */ +#define CDACFG 0xD0 +/* C-Port Direct Access Transmit 1 register */ +#define CDATX1 0xD4 +/* C-Port Direct Access Transmit 2 register */ +#define CDATX2 0xD8 +/* C-Port Direct Access Receive 1 register */ +#define CDARX1 0xDC +/* C-Port Direct Access Receive 2 register */ +#define CDARX2 0xE0 +/* C-Port Direct Access Status register */ +#define CDASTA 0xE4 +/* UPIU Loopback Configuration register */ +#define LBMCFG 0xF0 +/* UPIU Loopback Status */ +#define LBMSTA 0xF4 +/* Debug register */ +#define DBG 0xF8 +/* HClk Divider register */ +#define HCLKDIV 0xFC + +#define TX_HIBERN8TIME_CAP_OFFSET 0x000F +#define TX_FSM_STATE_OFFSET 0x0041 +#define TX_FSM_STATE_LINE_RESET 7 +#define TX_FSM_STATE_LINE_CFG 6 +#define TX_FSM_STATE_HS_BURST 5 +#define TX_FSM_STATE_LS_BURST 4 +#define TX_FSM_STATE_STALL 3 +#define TX_FSM_STATE_SLEEP 2 +#define TX_FSM_STATE_HIBERN8 1 +#define TX_FSM_STATE_DISABLE 0 + +#define RX_MIN_ACTIVATETIME_CAP_OFFSET 0x008F +#define RX_HS_G2_SYNC_LENGTH_CAP_OFFSET 0x0094 +#define RX_HS_G3_SYNC_LENGTH_CAP_OFFSET 0x0095 + +#define PA_AVAIL_TX_DATA_LANES_OFFSET 0x1520 +#define PA_TX_SKIP_OFFSET 0x155C +#define PA_TX_SKIP_PERIOD_OFFSET 0x155D +#define PA_LOCAL_TX_LCC_ENABLE_OFFSET 0x155E +#define PA_ACTIVE_TX_DATA_LANES_OFFSET 0x1560 +#define PA_CONNECTED_TX_DATA_LANES_OFFSET 0x1561 +#define PA_TX_TRAILING_CLOCKS_OFFSET 0x1564 +#define PA_TX_GEAR_OFFSET 0x1568 +#define PA_TX_TERMINATION_OFFSET 0x1569 +#define PA_HS_SERIES_OFFSET 0x156A +#define PA_PWR_MODE_OFFSET 0x1571 +#define PA_ACTIVE_RX_DATA_LANES_OFFSET 0x1580 +#define PA_CONNECTED_RX_DATA_LANES_OFFSET 0x1581 +#define PA_RX_PWR_STATUS_OFFSET 0x1582 +#define PA_RX_GEAR_OFFSET 0x1583 +#define PA_RX_TERMINATION_OFFSET 0x1584 +#define PA_SCRAMBLING_OFFSET 0x1585 +#define PA_MAX_RX_PWM_GEAR_OFFSET 0x1586 +#define PA_MAX_RX_HS_GEAR_OFFSET 0x1587 +#define PA_PACP_REQ_TIMEOUT_OFFSET 0x1590 +#define PA_PACP_REQ_EOB_TIMEOUT_OFFSET 0x1591 +#define PA_REMOTE_VER_INFO_OFFSET 0x15A0 +#define PA_LOGICAL_LANE_MAP_OFFSET 0x15A1 +#define PA_TACTIVATE_OFFSET 0x15A8 +#define PA_PWR_MODE_USER_DATA0_OFFSET 0x15B0 +#define PA_PWR_MODE_USER_DATA1_OFFSET 0x15B1 +#define PA_PWR_MODE_USER_DATA2_OFFSET 0x15B2 +#define PA_PWR_MODE_USER_DATA3_OFFSET 0x15B3 +#define PA_PWR_MODE_USER_DATA4_OFFSET 0x15B4 +#define PA_PWR_MODE_USER_DATA5_OFFSET 0x15B5 + +#define DL_TC0_TX_FC_THRESHOLD_OFFSET 0x2040 +#define DL_AFC0_CREDIT_THRESHOLD_OFFSET 0x2044 +#define DL_TC0_OUT_ACK_THRESHOLD_OFFSET 0x2045 + +#define DME_FC0_PROTECTION_TIMEOUT_OFFSET 0xD041 +#define DME_TC0_REPLAY_TIMEOUT_OFFSET 0xD042 +#define DME_AFC0_REQ_TIMEOUT_OFFSET 0xD043 +#define DME_FC1_PROTECTION_TIMEOUT_OFFSET 0xD044 +#define DME_TC1_REPLAY_TIMEOUT_OFFSET 0xD045 +#define DME_AFC1_REQ_TIMEOUT_OFFSET 0xD046 + +#define VS_MPHY_CFG_UPDT_OFFSET 0xD085 +#define VS_MK2_EXTN_SUPPORT_OFFSET 0xD0AB +#define VS_MPHY_DISABLE_OFFSET 0xD0C1 +#define VS_MPHY_DISABLE_MPHYDIS (1 << 0) + +typedef struct dw_ufs_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + unsigned long flags; +} dw_ufs_params_t; + +int dw_ufs_init(dw_ufs_params_t *params); + +#endif /* DW_UFS_H */ diff --git a/arm-trusted-firmware/include/drivers/fwu/fwu.h b/arm-trusted-firmware/include/drivers/fwu/fwu.h new file mode 100644 index 0000000..9f18e22 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/fwu/fwu.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FWU_H +#define FWU_H + +#include + +void fwu_init(void); +bool fwu_is_trial_run_state(void); +const struct fwu_metadata *fwu_get_metadata(void); + +#endif /* FWU_H */ diff --git a/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h b/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h new file mode 100644 index 0000000..2e88de5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + * + * FWU metadata information as per the specification section 4.1: + * https://developer.arm.com/documentation/den0118/a/ + * + */ + +#ifndef FWU_METADATA_H +#define FWU_METADATA_H + +#include +#include + +/* Properties of image in a bank */ +struct fwu_image_properties { + + /* UUID of the image in this bank */ + uuid_t img_uuid; + + /* [0]: bit describing the image acceptance status – + * 1 means the image is accepted + * [31:1]: MBZ + */ + uint32_t accepted; + + /* reserved (MBZ) */ + uint32_t reserved; + +} __packed; + +/* Image entry information */ +struct fwu_image_entry { + + /* UUID identifying the image type */ + uuid_t img_type_uuid; + + /* UUID of the storage volume where the image is located */ + uuid_t location_uuid; + + /* Properties of images with img_type_uuid in the different FW banks */ + struct fwu_image_properties img_props[NR_OF_FW_BANKS]; + +} __packed; + +/* + * FWU metadata filled by the updater and consumed by TF-A for + * various purposes as below: + * 1. Get active FW bank. + * 2. Rollback to previous working FW bank. + * 3. Get properties of all images present in all banks. + */ +struct fwu_metadata { + + /* Metadata CRC value */ + uint32_t crc_32; + + /* Metadata version */ + uint32_t version; + + /* Bank index with which device boots */ + uint32_t active_index; + + /* Previous bank index with which device booted successfully */ + uint32_t previous_active_index; + + /* Image entry information */ + struct fwu_image_entry img_entry[NR_OF_IMAGES_IN_FW_BANK]; + +} __packed; + +#endif /* FWU_METADATA_H */ diff --git a/arm-trusted-firmware/include/drivers/generic_delay_timer.h b/arm-trusted-firmware/include/drivers/generic_delay_timer.h new file mode 100644 index 0000000..adba10f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/generic_delay_timer.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GENERIC_DELAY_TIMER_H +#define GENERIC_DELAY_TIMER_H + +#include + +void generic_delay_timer_init_args(uint32_t mult, uint32_t div); + +void generic_delay_timer_init(void); + +#endif /* GENERIC_DELAY_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/gpio.h b/arm-trusted-firmware/include/drivers/gpio.h new file mode 100644 index 0000000..9bba993 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/gpio.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPIO_H +#define GPIO_H + +#include + +#define GPIO_DIR_OUT ARM_TF_GPIO_DIR_OUT +#define GPIO_DIR_IN ARM_TF_GPIO_DIR_IN + +#define GPIO_LEVEL_LOW ARM_TF_GPIO_LEVEL_LOW +#define GPIO_LEVEL_HIGH ARM_TF_GPIO_LEVEL_HIGH + +#define GPIO_PULL_NONE ARM_TF_GPIO_PULL_NONE +#define GPIO_PULL_UP ARM_TF_GPIO_PULL_UP +#define GPIO_PULL_DOWN ARM_TF_GPIO_PULL_DOWN +#define GPIO_PULL_REPEATER ARM_TF_GPIO_PULL_REPEATER + +typedef struct gpio_ops { + int (*get_direction)(int gpio); + void (*set_direction)(int gpio, int direction); + int (*get_value)(int gpio); + void (*set_value)(int gpio, int value); + void (*set_pull)(int gpio, int pull); + int (*get_pull)(int gpio); +} gpio_ops_t; + +int gpio_get_direction(int gpio); +void gpio_set_direction(int gpio, int direction); +int gpio_get_value(int gpio); +void gpio_set_value(int gpio, int value); +void gpio_set_pull(int gpio, int pull); +int gpio_get_pull(int gpio); +void gpio_init(const gpio_ops_t *ops); + +#endif /* GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_block.h b/arm-trusted-firmware/include/drivers/io/io_block.h new file mode 100644 index 0000000..c99e8c7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_block.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_BLOCK_H +#define IO_BLOCK_H + +#include + +/* block devices ops */ +typedef struct io_block_ops { + size_t (*read)(int lba, uintptr_t buf, size_t size); + size_t (*write)(int lba, const uintptr_t buf, size_t size); +} io_block_ops_t; + +typedef struct io_block_dev_spec { + io_block_spec_t buffer; + io_block_ops_t ops; + size_t block_size; +} io_block_dev_spec_t; + +struct io_dev_connector; + +int register_io_dev_block(const struct io_dev_connector **dev_con); + +#endif /* IO_BLOCK_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_driver.h b/arm-trusted-firmware/include/drivers/io/io_driver.h new file mode 100644 index 0000000..d8bb435 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_driver.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_DRIVER_H +#define IO_DRIVER_H + +#include + +#include + +/* Generic IO entity structure,representing an accessible IO construct on the + * device, such as a file */ +typedef struct io_entity { + struct io_dev_info *dev_handle; + uintptr_t info; +} io_entity_t; + + +/* Device info structure, providing device-specific functions and a means of + * adding driver-specific state */ +typedef struct io_dev_info { + const struct io_dev_funcs *funcs; + uintptr_t info; +} io_dev_info_t; + + +/* Structure used to create a connection to a type of device */ +typedef struct io_dev_connector { + /* dev_open opens a connection to a particular device driver */ + int (*dev_open)(const uintptr_t dev_spec, io_dev_info_t **dev_info); +} io_dev_connector_t; + + +/* Structure to hold device driver function pointers */ +typedef struct io_dev_funcs { + io_type_t (*type)(void); + int (*open)(io_dev_info_t *dev_info, const uintptr_t spec, + io_entity_t *entity); + int (*seek)(io_entity_t *entity, int mode, signed long long offset); + int (*size)(io_entity_t *entity, size_t *length); + int (*read)(io_entity_t *entity, uintptr_t buffer, size_t length, + size_t *length_read); + int (*write)(io_entity_t *entity, const uintptr_t buffer, + size_t length, size_t *length_written); + int (*close)(io_entity_t *entity); + int (*dev_init)(io_dev_info_t *dev_info, const uintptr_t init_params); + int (*dev_close)(io_dev_info_t *dev_info); +} io_dev_funcs_t; + + +/* Operations intended to be performed during platform initialisation */ + +/* Register an IO device */ +int io_register_device(const io_dev_info_t *dev_info); + +#endif /* IO_DRIVER_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_dummy.h b/arm-trusted-firmware/include/drivers/io/io_dummy.h new file mode 100644 index 0000000..edfc699 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_dummy.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_DUMMY_H +#define IO_DUMMY_H + +int register_io_dev_dummy(const struct io_dev_connector **dev_con); + +#endif /* IO_DUMMY_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_encrypted.h b/arm-trusted-firmware/include/drivers/io/io_encrypted.h new file mode 100644 index 0000000..9dcf061 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_encrypted.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_ENCRYPTED_H +#define IO_ENCRYPTED_H + +struct io_dev_connector; + +int register_io_dev_enc(const struct io_dev_connector **dev_con); + +#endif /* IO_ENCRYPTED_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_fip.h b/arm-trusted-firmware/include/drivers/io/io_fip.h new file mode 100644 index 0000000..7e65436 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_fip.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_FIP_H +#define IO_FIP_H + +struct io_dev_connector; + +int register_io_dev_fip(const struct io_dev_connector **dev_con); +int fip_dev_get_plat_toc_flag(io_dev_info_t *dev_info, uint16_t *plat_toc_flag); + +#endif /* IO_FIP_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_memmap.h b/arm-trusted-firmware/include/drivers/io/io_memmap.h new file mode 100644 index 0000000..87e3466 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_memmap.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MEMMAP_H +#define IO_MEMMAP_H + +struct io_dev_connector; + +int register_io_dev_memmap(const struct io_dev_connector **dev_con); + +#endif /* IO_MEMMAP_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_mtd.h b/arm-trusted-firmware/include/drivers/io/io_mtd.h new file mode 100644 index 0000000..2b5d9b1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_mtd.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MTD_H +#define IO_MTD_H + +#include +#include + +#include + +/* MTD devices ops */ +typedef struct io_mtd_ops { + /* + * Initialize MTD framework and retrieve device information. + * + * @size: [out] MTD device size in bytes. + * @erase_size: [out] MTD erase size in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*init)(unsigned long long *size, unsigned int *erase_size); + + /* + * Execute a read memory operation. + * + * @offset: Offset in bytes to start read operation. + * @buffer: [out] Buffer to store read data. + * @length: Required length to be read in bytes. + * @out_length: [out] Length read in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*read)(unsigned int offset, uintptr_t buffer, size_t length, + size_t *out_length); + + /* + * Execute a write memory operation. + * + * @offset: Offset in bytes to start write operation. + * @buffer: Buffer to be written in device. + * @length: Required length to be written in bytes. + * Return 0 on success, a negative error code otherwise. + */ + int (*write)(unsigned int offset, uintptr_t buffer, size_t length); + + /* + * Look for an offset to be added to the given offset. + * + * @base: Base address of the area. + * @offset: Offset in bytes to start read operation. + * @extra_offset: [out] Offset to be added to the previous offset. + * Return 0 on success, a negative error code otherwise. + */ + int (*seek)(uintptr_t base, unsigned int offset, size_t *extra_offset); +} io_mtd_ops_t; + +typedef struct io_mtd_dev_spec { + unsigned long long device_size; + unsigned int erase_size; + size_t offset; + io_mtd_ops_t ops; +} io_mtd_dev_spec_t; + +struct io_dev_connector; + +int register_io_dev_mtd(const struct io_dev_connector **dev_con); + +#endif /* IO_MTD_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_semihosting.h b/arm-trusted-firmware/include/drivers/io/io_semihosting.h new file mode 100644 index 0000000..e90ea5c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_semihosting.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_SEMIHOSTING_H +#define IO_SEMIHOSTING_H + +struct io_dev_connector; + +int register_io_dev_sh(const struct io_dev_connector **dev_con); + +#endif /* IO_SEMIHOSTING_H */ diff --git a/arm-trusted-firmware/include/drivers/io/io_storage.h b/arm-trusted-firmware/include/drivers/io/io_storage.h new file mode 100644 index 0000000..f2d641c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/io/io_storage.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_STORAGE_H +#define IO_STORAGE_H + +#include +#include +#include /* For ssize_t */ + +#include + +/* Device type which can be used to enable policy decisions about which device + * to access */ +typedef enum { + IO_TYPE_INVALID, + IO_TYPE_SEMIHOSTING, + IO_TYPE_MEMMAP, + IO_TYPE_DUMMY, + IO_TYPE_FIRMWARE_IMAGE_PACKAGE, + IO_TYPE_BLOCK, + IO_TYPE_MTD, + IO_TYPE_MMC, + IO_TYPE_STM32IMAGE, + IO_TYPE_ENCRYPTED, + IO_TYPE_MAX +} io_type_t; + + +/* Modes used when seeking data on a supported device */ +typedef enum { + IO_SEEK_INVALID, + IO_SEEK_SET, + IO_SEEK_END, + IO_SEEK_CUR, + IO_SEEK_MAX +} io_seek_mode_t; + + +/* Connector type, providing a means of identifying a device to open */ +struct io_dev_connector; + + +/* File specification - used to refer to data on a device supporting file-like + * entities */ +typedef struct io_file_spec { + const char *path; + unsigned int mode; +} io_file_spec_t; + +/* UUID specification - used to refer to data accessed using UUIDs (i.e. FIP + * images) */ +typedef struct io_uuid_spec { + uuid_t uuid; +} io_uuid_spec_t; + +/* Block specification - used to refer to data on a device supporting + * block-like entities */ +typedef struct io_block_spec { + size_t offset; + size_t length; +} io_block_spec_t; + + +/* Access modes used when accessing data on a device */ +#define IO_MODE_INVALID (0) +#define IO_MODE_RO (1 << 0) +#define IO_MODE_RW (1 << 1) + + +/* Open a connection to a device */ +int io_dev_open(const struct io_dev_connector *dev_con, + const uintptr_t dev_spec, + uintptr_t *handle); + + +/* Initialise a device explicitly - to permit lazy initialisation or + * re-initialisation */ +int io_dev_init(uintptr_t dev_handle, const uintptr_t init_params); + +/* Close a connection to a device */ +int io_dev_close(uintptr_t dev_handle); + + +/* Synchronous operations */ +int io_open(uintptr_t dev_handle, const uintptr_t spec, uintptr_t *handle); + +int io_seek(uintptr_t handle, io_seek_mode_t mode, signed long long offset); + +int io_size(uintptr_t handle, size_t *length); + +int io_read(uintptr_t handle, uintptr_t buffer, size_t length, + size_t *length_read); + +int io_write(uintptr_t handle, const uintptr_t buffer, size_t length, + size_t *length_written); + +int io_close(uintptr_t handle); + + +#endif /* IO_STORAGE_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/addr_map.h b/arm-trusted-firmware/include/drivers/marvell/addr_map.h new file mode 100644 index 0000000..0d219f2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/addr_map.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Address map types for Marvell address translation unit drivers */ + +#ifndef ADDR_MAP_H +#define ADDR_MAP_H + +#include + +struct addr_map_win { + uint64_t base_addr; + uint64_t win_size; + uint32_t target_id; +}; + +#endif /* ADDR_MAP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/amb_adec.h b/arm-trusted-firmware/include/drivers/marvell/amb_adec.h new file mode 100644 index 0000000..a92db5b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/amb_adec.h @@ -0,0 +1,36 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AXI to M-Bridge decoding unit driver for Marvell Armada 8K and 8K+ SoCs */ + +#ifndef AMB_ADEC_H +#define AMB_ADEC_H + +#include + +enum amb_attribute_ids { + AMB_SPI0_CS0_ID = 0x1E, + AMB_SPI0_CS1_ID = 0x5E, + AMB_SPI0_CS2_ID = 0x9E, + AMB_SPI0_CS3_ID = 0xDE, + AMB_SPI1_CS0_ID = 0x1A, + AMB_SPI1_CS1_ID = 0x5A, + AMB_SPI1_CS2_ID = 0x9A, + AMB_SPI1_CS3_ID = 0xDA, + AMB_DEV_CS0_ID = 0x3E, + AMB_DEV_CS1_ID = 0x3D, + AMB_DEV_CS2_ID = 0x3B, + AMB_DEV_CS3_ID = 0x37, + AMB_BOOT_CS_ID = 0x2f, + AMB_BOOT_ROM_ID = 0x1D, +}; + +#define AMB_MAX_WIN_ID 7 + +int init_amb_adec(uintptr_t base); + +#endif /* AMB_ADEC_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h b/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h new file mode 100644 index 0000000..4353b83 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h @@ -0,0 +1,14 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef AP807_INIT_CLOCKS_H +#define AP807_INIT_CLOCKS_H + +void ap807_clocks_init(unsigned int freq_option); + +#endif /* AP807_INIT_CLOCKS_H */ + diff --git a/arm-trusted-firmware/include/drivers/marvell/aro.h b/arm-trusted-firmware/include/drivers/marvell/aro.h new file mode 100644 index 0000000..4d1094a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/aro.h @@ -0,0 +1,49 @@ +/* + * Copyright (C) 2017 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ +#ifndef ARO_H +#define ARO_H + +enum hws_freq { + CPU_FREQ_2000, + CPU_FREQ_1800, + CPU_FREQ_1600, + CPU_FREQ_1400, + CPU_FREQ_1300, + CPU_FREQ_1200, + CPU_FREQ_1000, + CPU_FREQ_600, + CPU_FREQ_800, + DDR_FREQ_LAST, + DDR_FREQ_SAR +}; + +#include + +enum cpu_clock_freq_mode { + CPU_2000_DDR_1200_RCLK_1200 = 0x0, + CPU_2000_DDR_1050_RCLK_1050 = 0x1, + CPU_1600_DDR_800_RCLK_800 = 0x4, + CPU_2200_DDR_1200_RCLK_1200 = 0x6, + CPU_1800_DDR_1050_RCLK_1050 = 0x7, + CPU_1600_DDR_900_RCLK_900 = 0x0B, + CPU_1600_DDR_1050_RCLK_1050 = 0x0D, + CPU_1600_DDR_1200_RCLK_1200 = 0x0D, + CPU_1600_DDR_900_RCLK_900_2 = 0x0E, + CPU_1000_DDR_650_RCLK_650 = 0x13, + CPU_1300_DDR_800_RCLK_800 = 0x14, + CPU_1300_DDR_650_RCLK_650 = 0x17, + CPU_1200_DDR_800_RCLK_800 = 0x19, + CPU_1400_DDR_800_RCLK_800 = 0x1a, + CPU_600_DDR_800_RCLK_800 = 0x1B, + CPU_800_DDR_800_RCLK_800 = 0x1C, + CPU_1000_DDR_800_RCLK_800 = 0x1D, + CPU_DDR_RCLK_INVALID +}; + +int init_aro(void); + +#endif /* ARO_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/cache_llc.h b/arm-trusted-firmware/include/drivers/marvell/cache_llc.h new file mode 100644 index 0000000..72111b3 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/cache_llc.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2018-2020 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* LLC driver is the Last Level Cache (L3C) driver + * for Marvell SoCs in AP806, AP807, and AP810 + */ + +#ifndef CACHE_LLC_H +#define CACHE_LLC_H + +#define LLC_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x100) +#define LLC_SECURE_CTRL(ap) (MVEBU_LLC_BASE(ap) + 0x10C) +#define LLC_SYNC(ap) (MVEBU_LLC_BASE(ap) + 0x700) +#define LLC_BANKED_MNT_AHR(ap) (MVEBU_LLC_BASE(ap) + 0x724) +#define LLC_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x77C) +#define LLC_BLK_ALOC(ap) (MVEBU_LLC_BASE(ap) + 0x78c) +#define LLC_CLEAN_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7BC) +#define LLC_CLEAN_INV_WAY(ap) (MVEBU_LLC_BASE(ap) + 0x7FC) +#define LLC_TCN_LOCK(ap, tc) (MVEBU_LLC_BASE(ap) + 0x920 + 4 * (tc)) + +#define MASTER_LLC_CTRL LLC_CTRL(MVEBU_AP0) +#define MASTER_LLC_INV_WAY LLC_INV_WAY(MVEBU_AP0) +#define MASTER_LLC_TC0_LOCK LLC_TCN_LOCK(MVEBU_AP0, 0) + +#define LLC_CTRL_EN 1 +#define LLC_EXCLUSIVE_EN 0x100 +#define LLC_ALL_WAYS_MASK 0xFFFFFFFF + +/* AP806/AP807 - 1MB 8-ways LLC */ +#define LLC_WAYS 8 +#define LLC_WAY_MASK ((1 << LLC_WAYS) - 1) +#define LLC_SIZE (1024 * 1024) +#define LLC_WAY_SIZE (LLC_SIZE / LLC_WAYS) +#define LLC_TC_NUM 15 + +#define LLC_BLK_ALOC_WAY_ID(way) ((way) & 0x1f) +#define LLC_BLK_ALOC_WAY_DATA_DSBL (0x0 << 6) +#define LLC_BLK_ALOC_WAY_DATA_CLR (0x1 << 6) +#define LLC_BLK_ALOC_WAY_DATA_SET (0x3 << 6) +#define LLC_BLK_ALOC_BASE_ADDR(addr) ((addr) & ~(LLC_WAY_SIZE - 1)) + +#ifndef __ASSEMBLER__ +void llc_cache_sync(int ap_index); +void llc_flush_all(int ap_index); +void llc_clean_all(int ap_index); +void llc_inv_all(int ap_index); +void llc_disable(int ap_index); +void llc_enable(int ap_index, int excl_mode); +int llc_is_exclusive(int ap_index); +void llc_runtime_enable(int ap_index); +#if LLC_SRAM +int llc_sram_enable(int ap_index, int size); +void llc_sram_disable(int ap_index); +int llc_sram_test(int ap_index, int size, char *msg); +#endif /* LLC_SRAM */ +#endif /* __ASSEMBLER__ */ + +#endif /* CACHE_LLC_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/ccu.h b/arm-trusted-firmware/include/drivers/marvell/ccu.h new file mode 100644 index 0000000..f8f0adf --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/ccu.h @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CCU unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#ifndef CCU_H +#define CCU_H + +#ifndef __ASSEMBLER__ +#include +#endif + +/* CCU registers definitions */ +#define CCU_WIN_CR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x0 + \ + (0x10 * win)) +#define CCU_TARGET_ID_OFFSET (8) +#define CCU_TARGET_ID_MASK (0x7F) + +#define CCU_WIN_SCR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x4 + \ + (0x10 * win)) +#define CCU_WIN_ENA_WRITE_SECURE (0x1) +#define CCU_WIN_ENA_READ_SECURE (0x2) + +#define CCU_WIN_ALR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0x8 + \ + (0x10 * win)) +#define CCU_WIN_AHR_OFFSET(ap, win) (MVEBU_CCU_BASE(ap) + 0xC + \ + (0x10 * win)) + +#define CCU_WIN_GCR_OFFSET(ap) (MVEBU_CCU_BASE(ap) + 0xD0) +#define CCU_GCR_TARGET_OFFSET (8) +#define CCU_GCR_TARGET_MASK (0xFF) + +#define CCU_SRAM_WIN_CR CCU_WIN_CR_OFFSET(MVEBU_AP0, 1) + +#ifndef __ASSEMBLER__ +int init_ccu(int); +void ccu_win_check(struct addr_map_win *win); +void ccu_enable_win(int ap_index, struct addr_map_win *win, uint32_t win_id); +void ccu_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void ccu_temp_win_remove(int ap_index, struct addr_map_win *win, int size); +void ccu_dram_win_config(int ap_index, struct addr_map_win *win); +void ccu_dram_target_set(int ap_index, uint32_t target); +void ccu_save_win_all(int ap_id); +void ccu_restore_win_all(int ap_id); +int ccu_is_win_enabled(int ap_index, uint32_t win_id); +void errata_wa_init(void); +#endif + +#endif /* CCU_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/gwin.h b/arm-trusted-firmware/include/drivers/marvell/gwin.h new file mode 100644 index 0000000..1b874a7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/gwin.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* GWIN unit device driver for Marvell AP810 SoC */ + +#ifndef GWIN_H +#define GWIN_H + +#include + +int init_gwin(int ap_index); +void gwin_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void gwin_temp_win_remove(int ap_index, struct addr_map_win *win, int size); + +#endif /* GWIN_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/i2c.h b/arm-trusted-firmware/include/drivers/marvell/i2c.h new file mode 100644 index 0000000..06c5114 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/i2c.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef I2C_H +#define I2C_H + + +void i2c_init(void); + +int i2c_read(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +int i2c_write(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/io_win.h b/arm-trusted-firmware/include/drivers/marvell/io_win.h new file mode 100644 index 0000000..7438d6b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/io_win.h @@ -0,0 +1,21 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IO Window unit device driver for Marvell AP807, AP807 and AP810 SoCs */ + +#ifndef IO_WIN_H +#define IO_WIN_H + +#include + +int init_io_win(int ap_index); +void iow_temp_win_insert(int ap_index, struct addr_map_win *win, int size); +void iow_temp_win_remove(int ap_index, struct addr_map_win *win, int size); +void iow_save_win_all(int ap_id); +void iow_restore_win_all(int ap_id); + +#endif /* IO_WIN_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/iob.h b/arm-trusted-firmware/include/drivers/marvell/iob.h new file mode 100644 index 0000000..9b5e515 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/iob.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* IOW unit device driver for Marvell CP110 and CP115 SoCs */ + +#ifndef IOB_H +#define IOB_H + +#include + +enum target_ids_iob { + INTERNAL_TID = 0x0, + MCI0_TID = 0x1, + PEX1_TID = 0x2, + PEX2_TID = 0x3, + PEX0_TID = 0x4, + NAND_TID = 0x5, + RUNIT_TID = 0x6, + MCI1_TID = 0x7, + IOB_MAX_TID +}; + +int init_iob(uintptr_t base); +void iob_cfg_space_update(int ap_idx, int cp_idx, + uintptr_t base, uintptr_t new_base); + +#endif /* IOB_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mci.h b/arm-trusted-firmware/include/drivers/marvell/mci.h new file mode 100644 index 0000000..af5d620 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mci.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* MCI bus driver for Marvell ARMADA 8K and 8K+ SoCs */ + +#ifndef MCI_H +#define MCI_H + +int mci_link_tune(int mci_index); +void mci_turn_link_down(void); +void mci_turn_link_on(void); +int mci_get_link_status(void); + +#endif /* MCI_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h b/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h new file mode 100644 index 0000000..5b0e75f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h @@ -0,0 +1,18 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* AP8xx Marvell SoC driver */ + +#ifndef AP_SETUP_H +#define AP_SETUP_H + +void ap_init(void); +void ap_ble_init(void); +int ap_get_count(void); +void update_cp110_default_win(int cp_id); + +#endif /* AP_SETUP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h b/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h new file mode 100644 index 0000000..4a69257 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h @@ -0,0 +1,66 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* CP110 Marvell SoC driver */ + +#ifndef CP110_SETUP_H +#define CP110_SETUP_H + +#include + +#include + +#define MVEBU_DEVICE_ID_REG (MVEBU_CP_DFX_OFFSET + 0x40) +#define MVEBU_DEVICE_ID_OFFSET (0) +#define MVEBU_DEVICE_ID_MASK (0xffff << MVEBU_DEVICE_ID_OFFSET) +#define MVEBU_DEVICE_REV_OFFSET (16) +#define MVEBU_DEVICE_REV_MASK (0xf << MVEBU_DEVICE_REV_OFFSET) +#define MVEBU_70X0_DEV_ID (0x7040) +#define MVEBU_70X0_CP115_DEV_ID (0x7045) +#define MVEBU_3900_DEV_ID (0x6025) +#define MVEBU_80X0_DEV_ID (0x8040) +#define MVEBU_80X0_CP115_DEV_ID (0x8045) +#define MVEBU_CN9130_DEV_ID (0x7025) +#define MVEBU_CP110_SA_DEV_ID (0x110) +#define MVEBU_CP110_REF_ID_A1 1 +#define MVEBU_CP110_REF_ID_A2 2 +#define MAX_STREAM_ID_PER_CP (0x10) +#define STREAM_ID_BASE (0x40) + +#define MVEBU_SECUREBOOT_CTRL_REG (MVEBU_RFU_BASE + 0x4730) +#define MVEBU_SECUREBOOT_EN_MASK BIT(0) + +static inline uint32_t cp110_device_id_get(uintptr_t base) +{ + /* Returns: + * - MVEBU_70X0_DEV_ID for A70X0 family + * - MVEBU_80X0_DEV_ID for A80X0 family + * - MVEBU_CP110_SA_DEV_ID for CP that connected stand alone + */ + return (mmio_read_32(base + MVEBU_DEVICE_ID_REG) >> + MVEBU_DEVICE_ID_OFFSET) & + MVEBU_DEVICE_ID_MASK; +} + +static inline uint32_t cp110_rev_id_get(uintptr_t base) +{ + return (mmio_read_32(base + MVEBU_DEVICE_ID_REG) & + MVEBU_DEVICE_REV_MASK) >> + MVEBU_DEVICE_REV_OFFSET; +} + +static inline uint32_t is_secure(void) +{ + return !!(mmio_read_32(MVEBU_SECUREBOOT_CTRL_REG) & + MVEBU_SECUREBOOT_EN_MASK); +} + +void cp110_init(uintptr_t cp110_base, uint32_t stream_id); +void cp110_ble_init(uintptr_t cp110_base); +void cp110_amb_init(uintptr_t base); + +#endif /* CP110_SETUP_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/thermal.h b/arm-trusted-firmware/include/drivers/marvell/thermal.h new file mode 100644 index 0000000..48376a7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/thermal.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* Driver for thermal unit located in Marvell ARMADA 8K and compatible SoCs */ + +#ifndef THERMAL_H +#define THERMAL_H + +struct tsen_config { + /* thermal temperature parameters */ + int tsen_offset; + int tsen_gain; + int tsen_divisor; + /* thermal data */ + int tsen_ready; + void *regs_base; + /* thermal functionality */ + int (*ptr_tsen_probe)(struct tsen_config *cfg); + int (*ptr_tsen_read)(struct tsen_config *cfg, int *temp); +}; + +/* Thermal driver APIs */ +int marvell_thermal_init(struct tsen_config *tsen_cfg); +int marvell_thermal_read(struct tsen_config *tsen_cfg, int *temp); +struct tsen_config *marvell_thermal_config_get(void); + +#endif /* THERMAL_H */ diff --git a/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h b/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h new file mode 100644 index 0000000..ce673a1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef A3700_CONSOLE_H +#define A3700_CONSOLE_H + +#include +#include + +/* MVEBU UART Registers */ +#define UART_RX_REG 0x00 +#define UART_TX_REG 0x04 +#define UART_CTRL_REG 0x08 +#define UART_STATUS_REG 0x0c +#define UART_BAUD_REG 0x10 +#define UART_POSSR_REG 0x14 + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_TXFIFOFULL (1 << 11) /* Tx Fifo Full */ +#define UARTLSR_TXEMPTY (1 << 6) /* Tx Empty */ +#define UARTLSR_RXRDY (1 << 4) /* Rx Ready */ + +/* UART Control Register bits */ +#define UART_CTRL_RXFIFO_RESET (1 << 14) +#define UART_CTRL_TXFIFO_RESET (1 << 15) + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new a3700 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_a3700_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* A3700_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h b/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h new file mode 100644 index 0000000..0a19f8a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EVENT_LOG_H +#define EVENT_LOG_H + +#include + +#include +#include +#include + +/* + * Set Event Log debug level to one of: + * + * LOG_LEVEL_ERROR + * LOG_LEVEL_INFO + * LOG_LEVEL_WARNING + * LOG_LEVEL_VERBOSE + */ +#if EVENT_LOG_LEVEL == LOG_LEVEL_ERROR +#define LOG_EVENT ERROR +#elif EVENT_LOG_LEVEL == LOG_LEVEL_NOTICE +#define LOG_EVENT NOTICE +#elif EVENT_LOG_LEVEL == LOG_LEVEL_WARNING +#define LOG_EVENT WARN +#elif EVENT_LOG_LEVEL == LOG_LEVEL_INFO +#define LOG_EVENT INFO +#elif EVENT_LOG_LEVEL == LOG_LEVEL_VERBOSE +#define LOG_EVENT VERBOSE +#else +#error "Not supported EVENT_LOG_LEVEL" +#endif + +/* Number of hashing algorithms supported */ +#define HASH_ALG_COUNT 1U + +#define EVLOG_INVALID_ID UINT32_MAX + +#define MEMBER_SIZE(type, member) sizeof(((type *)0)->member) + +/* + * Each event log entry has some metadata (i.e. a string) that identifies + * what is measured.These macros define these strings. + * Note that these strings follow the standardization recommendations + * defined in the Arm Server Base Security Guide (a.k.a. SBSG, Arm DEN 0086), + * where applicable. They should not be changed in the code. + * Where the SBSG does not make recommendations, we are free to choose any + * naming convention. + * The key thing is to choose meaningful strings so that when the TPM event + * log is used in attestation, the different components can be identified. + */ +#define EVLOG_BL2_STRING "BL_2" +#define EVLOG_BL31_STRING "SECURE_RT_EL3" +#if defined(SPD_opteed) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_OPTEE" +#elif defined(SPD_tspd) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TSPD" +#elif defined(SPD_tlkd) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TLKD" +#elif defined(SPD_trusty) +#define EVLOG_BL32_STRING "SECURE_RT_EL1_TRUSTY" +#else +#define EVLOG_BL32_STRING "SECURE_RT_EL1_UNKNOWN" +#endif +#define EVLOG_BL32_EXTRA1_STRING "SECURE_RT_EL1_OPTEE_EXTRA1" +#define EVLOG_BL32_EXTRA2_STRING "SECURE_RT_EL1_OPTEE_EXTRA2" +#define EVLOG_BL33_STRING "BL_33" +#define EVLOG_FW_CONFIG_STRING "FW_CONFIG" +#define EVLOG_HW_CONFIG_STRING "HW_CONFIG" +#define EVLOG_NT_FW_CONFIG_STRING "NT_FW_CONFIG" +#define EVLOG_SCP_BL2_STRING "SYS_CTRL_2" +#define EVLOG_SOC_FW_CONFIG_STRING "SOC_FW_CONFIG" +#define EVLOG_STM32_STRING "STM32" +#define EVLOG_TB_FW_CONFIG_STRING "TB_FW_CONFIG" +#define EVLOG_TOS_FW_CONFIG_STRING "TOS_FW_CONFIG" +#define EVLOG_RMM_STRING "RMM" + +typedef struct { + unsigned int id; + const char *name; + unsigned int pcr; +} event_log_metadata_t; + +#define ID_EVENT_SIZE (sizeof(id_event_headers_t) + \ + (sizeof(id_event_algorithm_size_t) * HASH_ALG_COUNT) + \ + sizeof(id_event_struct_data_t)) + +#define LOC_EVENT_SIZE (sizeof(event2_header_t) + \ + sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \ + sizeof(event2_data_t) + \ + sizeof(startup_locality_event_t)) + +#define LOG_MIN_SIZE (ID_EVENT_SIZE + LOC_EVENT_SIZE) + +#define EVENT2_HDR_SIZE (sizeof(event2_header_t) + \ + sizeof(tpmt_ha) + TCG_DIGEST_SIZE + \ + sizeof(event2_data_t)) + +/* Functions' declarations */ +void event_log_init(uint8_t *event_log_start, uint8_t *event_log_finish); +void event_log_write_header(void); +void dump_event_log(uint8_t *log_addr, size_t log_size); +const event_log_metadata_t *plat_event_log_get_metadata(void); +int event_log_measure_and_record(uintptr_t data_base, uint32_t data_size, + uint32_t data_id); +size_t event_log_get_cur_size(uint8_t *event_log_start); + +#endif /* EVENT_LOG_H */ diff --git a/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h b/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h new file mode 100644 index 0000000..ab27a08 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h @@ -0,0 +1,304 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TCG_H +#define TCG_H + +#include + +#define TCG_ID_EVENT_SIGNATURE_03 "Spec ID Event03" +#define TCG_STARTUP_LOCALITY_SIGNATURE "StartupLocality" + +#define TCG_SPEC_VERSION_MAJOR_TPM2 2 +#define TCG_SPEC_VERSION_MINOR_TPM2 0 +#define TCG_SPEC_ERRATA_TPM2 2 + +/* + * Event types + * Ref. Table 9 Events + * TCG PC Client Platform Firmware Profile Specification. + */ +#define EV_PREBOOT_CERT U(0x00000000) +#define EV_POST_CODE U(0x00000001) +#define EV_UNUSED U(0x00000002) +#define EV_NO_ACTION U(0x00000003) +#define EV_SEPARATOR U(0x00000004) +#define EV_ACTION U(0x00000005) +#define EV_EVENT_TAG U(0x00000006) +#define EV_S_CRTM_CONTENTS U(0x00000007) +#define EV_S_CRTM_VERSION U(0x00000008) +#define EV_CPU_MICROCODE U(0x00000009) +#define EV_PLATFORM_CONFIG_FLAGS U(0x0000000A) +#define EV_TABLE_OF_DEVICES U(0x0000000B) +#define EV_COMPACT_HASH U(0x0000000C) +#define EV_IPL U(0x0000000D) +#define EV_IPL_PARTITION_DATA U(0x0000000E) +#define EV_NONHOST_CODE U(0x0000000F) +#define EV_NONHOST_CONFIG U(0x00000010) +#define EV_NONHOST_INFO U(0x00000011) +#define EV_OMIT_BOOT_DEVICE_EVENTS U(0x00000012) +#define EV_EFI_EVENT_BASE U(0x80000000) +#define EV_EFI_VARIABLE_DRIVER_CONFIG U(0x80000001) +#define EV_EFI_VARIABLE_BOOT U(0x80000002) +#define EV_EFI_BOOT_SERVICES_APPLICATION U(0x80000003) +#define EV_EFI_BOOT_SERVICES_DRIVER U(0x80000004) +#define EV_EFI_RUNTIME_SERVICES_DRIVER U(0x80000005) +#define EV_EFI_GPT_EVENT U(0x80000006) +#define EV_EFI_ACTION U(0x80000007) +#define EV_EFI_PLATFORM_FIRMWARE_BLOB U(0x80000008) +#define EV_EFI_HANDOFF_TABLES U(0x80000009) +#define EV_EFI_HCRTM_EVENT U(0x80000010) +#define EV_EFI_VARIABLE_AUTHORITY U(0x800000E0) + +/* + * TPM_ALG_ID constants. + * Ref. Table 9 - Definition of (UINT16) TPM_ALG_ID Constants + * Trusted Platform Module Library. Part 2: Structures + */ +#define TPM_ALG_SHA256 0x000B +#define TPM_ALG_SHA384 0x000C +#define TPM_ALG_SHA512 0x000D + +/* TCG Platform Type */ +#define PLATFORM_CLASS_CLIENT 0 +#define PLATFORM_CLASS_SERVER 1 + +/* SHA digest sizes in bytes */ +#define SHA1_DIGEST_SIZE 20 +#define SHA256_DIGEST_SIZE 32 +#define SHA384_DIGEST_SIZE 48 +#define SHA512_DIGEST_SIZE 64 + +enum { + /* + * SRTM, BIOS, Host Platform Extensions, Embedded + * Option ROMs and PI Drivers + */ + PCR_0 = 0, + /* Host Platform Configuration */ + PCR_1, + /* UEFI driver and application Code */ + PCR_2, + /* UEFI driver and application Configuration and Data */ + PCR_3, + /* UEFI Boot Manager Code (usually the MBR) and Boot Attempts */ + PCR_4, + /* + * Boot Manager Code Configuration and Data (for use + * by the Boot Manager Code) and GPT/Partition Table + */ + PCR_5, + /* Host Platform Manufacturer Specific */ + PCR_6, + /* Secure Boot Policy */ + PCR_7, + /* 8-15: Defined for use by the Static OS */ + PCR_8, + /* Debug */ + PCR_16 = 16 +}; + +#pragma pack(push, 1) + +/* + * PCR Event Header + * TCG EFI Protocol Specification + * 5.3 Event Log Header + */ +typedef struct { + /* PCRIndex: + * The PCR Index to which this event is extended + */ + uint32_t pcr_index; + + /* EventType: + * SHALL be an EV_NO_ACTION event + */ + uint32_t event_type; + + /* SHALL be 20 Bytes of 0x00 */ + uint8_t digest[SHA1_DIGEST_SIZE]; + + /* The size of the event */ + uint32_t event_size; + + /* SHALL be a TCG_EfiSpecIdEvent */ + uint8_t event[]; /* [event_data_size] */ +} tcg_pcr_event_t; + +/* + * Log Header Entry Data + * Ref. Table 14 TCG_EfiSpecIdEventAlgorithmSize + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ +typedef struct { + /* Algorithm ID (hashAlg) of the Hash used by BIOS */ + uint16_t algorithm_id; + + /* The size of the digest produced by the implemented Hash algorithm */ + uint16_t digest_size; +} id_event_algorithm_size_t; + +/* + * TCG_EfiSpecIdEvent structure + * Ref. Table 15 TCG_EfiSpecIdEvent + * TCG PC Client Platform Firmware Profile 9.4.5.1 + */ +typedef struct { + /* + * The NUL-terminated ASCII string "Spec ID Event03". + * SHALL be set to {0x53, 0x70, 0x65, 0x63, 0x20, 0x49, 0x44, + * 0x20, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x33, 0x00}. + */ + uint8_t signature[16]; + + /* + * The value for the Platform Class. + * The enumeration is defined in the TCG ACPI Specification Client + * Common Header. + */ + uint32_t platform_class; + + /* + * The PC Client Platform Profile Specification minor version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x00. + */ + uint8_t spec_version_minor; + + /* + * The PC Client Platform Profile Specification major version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_version_major; + + /* + * The PC Client Platform Profile Specification errata version number + * this BIOS supports. + * Any BIOS supporting this version (2.0) MUST set this value to 0x02. + */ + uint8_t spec_errata; + + /* + * Specifies the size of the UINTN fields used in various data + * structures used in this specification. + * 0x01 indicates UINT32 and 0x02 indicates UINT64. + */ + uint8_t uintn_size; + + /* + * The number of Hash algorithms in the digestSizes field. + * This field MUST be set to a value of 0x01 or greater. + */ + uint32_t number_of_algorithms; + + /* + * Each TCG_EfiSpecIdEventAlgorithmSize SHALL contain an algorithmId + * and digestSize for each hash algorithm used in the TCG_PCR_EVENT2 + * structure, the first of which is a Hash algorithmID and the second + * is the size of the respective digest. + */ + id_event_algorithm_size_t digest_size[]; /* number_of_algorithms */ +} id_event_struct_header_t; + +typedef struct { + /* + * Size in bytes of the VendorInfo field. + * Maximum value MUST be FFh bytes. + */ + uint8_t vendor_info_size; + + /* + * Provided for use by Platform Firmware implementer. The value might + * be used, for example, to provide more detailed information about the + * specific BIOS such as BIOS revision numbers, etc. The values within + * this field are not standardized and are implementer-specific. + * Platform-specific or -unique information MUST NOT be provided in + * this field. + * + */ + uint8_t vendor_info[]; /* [vendorInfoSize] */ +} id_event_struct_data_t; + +typedef struct { + id_event_struct_header_t struct_header; + id_event_struct_data_t struct_data; +} id_event_struct_t; + +typedef struct { + tcg_pcr_event_t header; + id_event_struct_header_t struct_header; +} id_event_headers_t; + +/* TPMT_HA Structure */ +typedef struct { + /* Selector of the hash contained in the digest that implies + * the size of the digest + */ + uint16_t algorithm_id; /* AlgorithmId */ + + /* Digest, depends on AlgorithmId */ + uint8_t digest[]; /* Digest[] */ +} tpmt_ha; + +/* + * TPML_DIGEST_VALUES Structure + */ +typedef struct { + /* The number of digests in the list */ + uint32_t count; /* Count */ + + /* The list of tagged digests, as sent to the TPM as part of a + * TPM2_PCR_Extend or as received from a TPM2_PCR_Event command + */ + tpmt_ha digests[]; /* Digests[Count] */ +} tpml_digest_values; + +/* + * TCG_PCR_EVENT2 header + */ +typedef struct { + /* The PCR Index to which this event was extended */ + uint32_t pcr_index; /* PCRIndex */ + + /* Type of event */ + uint32_t event_type; /* EventType */ + + /* Digests: + * A counted list of tagged digests, which contain the digest of + * the event data (or external data) for all active PCR banks + */ + tpml_digest_values digests; /* Digests */ +} event2_header_t; + +typedef struct event2_data { + /* The size of the event data */ + uint32_t event_size; /* EventSize */ + + /* The data of the event */ + uint8_t event[]; /* Event[EventSize] */ +} event2_data_t; + +/* + * Startup Locality Event + * Ref. TCG PC Client Platform Firmware Profile 9.4.5.3 + */ +typedef struct { + /* + * The NUL-terminated ASCII string "StartupLocality" SHALL be + * set to {0x53 0x74 0x61 0x72 0x74 0x75 0x70 0x4C 0x6F 0x63 + * 0x61 0x6C 0x69 0x74 0x79 0x00} + */ + uint8_t signature[16]; + + /* The Locality Indicator which sent the TPM2_Startup command */ + uint8_t startup_locality; +} startup_locality_event_t; + +#pragma pack(pop) + +#endif /* TCG_H */ diff --git a/arm-trusted-firmware/include/drivers/mentor/mi2cv.h b/arm-trusted-firmware/include/drivers/mentor/mi2cv.h new file mode 100644 index 0000000..85b733b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/mentor/mi2cv.h @@ -0,0 +1,40 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * Copyright (C) 2018 Icenowy Zheng + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +/* This driver provides support for Mentor Graphics MI2CV IP core */ + +#ifndef MI2CV_H +#define MI2CV_H + +#include + +/* + * Initialization, must be called once on start up, may be called + * repeatedly to change the speed and slave addresses. + */ +void i2c_init(void *i2c_base); + +/* + * Read/Write interface: + * chip: I2C chip address, range 0..127 + * addr: Memory (register) address within the chip + * alen: Number of bytes to use for addr (typically 1, 2 for larger + * memories, 0 for register type devices with only one + * register) + * buffer: Where to read/write the data + * len: How many bytes to read/write + * + * Returns: 0 on success, not 0 on failure + */ +int i2c_read(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +int i2c_write(uint8_t chip, + unsigned int addr, int alen, uint8_t *buffer, int len); + +#endif /* MI2CV_H */ diff --git a/arm-trusted-firmware/include/drivers/mmc.h b/arm-trusted-firmware/include/drivers/mmc.h new file mode 100644 index 0000000..834a80f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/mmc.h @@ -0,0 +1,244 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MMC_H +#define MMC_H + +#include + +#include + +#define MMC_BLOCK_SIZE U(512) +#define MMC_BLOCK_MASK (MMC_BLOCK_SIZE - U(1)) +#define MMC_BOOT_CLK_RATE (400 * 1000) + +#define MMC_CMD(_x) U(_x) + +#define MMC_ACMD(_x) U(_x) + +#define OCR_POWERUP BIT(31) +#define OCR_HCS BIT(30) +#define OCR_BYTE_MODE (U(0) << 29) +#define OCR_SECTOR_MODE (U(2) << 29) +#define OCR_ACCESS_MODE_MASK (U(3) << 29) +#define OCR_3_5_3_6 BIT(23) +#define OCR_3_4_3_5 BIT(22) +#define OCR_3_3_3_4 BIT(21) +#define OCR_3_2_3_3 BIT(20) +#define OCR_3_1_3_2 BIT(19) +#define OCR_3_0_3_1 BIT(18) +#define OCR_2_9_3_0 BIT(17) +#define OCR_2_8_2_9 BIT(16) +#define OCR_2_7_2_8 BIT(15) +#define OCR_VDD_MIN_2V7 GENMASK(23, 15) +#define OCR_VDD_MIN_2V0 GENMASK(14, 8) +#define OCR_VDD_MIN_1V7 BIT(7) + +#define MMC_RSP_48 BIT(0) +#define MMC_RSP_136 BIT(1) /* 136 bit response */ +#define MMC_RSP_CRC BIT(2) /* expect valid crc */ +#define MMC_RSP_CMD_IDX BIT(3) /* response contains cmd idx */ +#define MMC_RSP_BUSY BIT(4) /* device may be busy */ + +/* JEDEC 4.51 chapter 6.12 */ +#define MMC_RESPONSE_R1 (MMC_RSP_48 | MMC_RSP_CMD_IDX | MMC_RSP_CRC) +#define MMC_RESPONSE_R1B (MMC_RESPONSE_R1 | MMC_RSP_BUSY) +#define MMC_RESPONSE_R2 (MMC_RSP_48 | MMC_RSP_136 | MMC_RSP_CRC) +#define MMC_RESPONSE_R3 (MMC_RSP_48) +#define MMC_RESPONSE_R4 (MMC_RSP_48) +#define MMC_RESPONSE_R5 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) +#define MMC_RESPONSE_R6 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) +#define MMC_RESPONSE_R7 (MMC_RSP_48 | MMC_RSP_CRC | MMC_RSP_CMD_IDX) + +/* Value randomly chosen for eMMC RCA, it should be > 1 */ +#define MMC_FIX_RCA 6 +#define RCA_SHIFT_OFFSET 16 + +#define CMD_EXTCSD_PARTITION_CONFIG 179 +#define CMD_EXTCSD_BUS_WIDTH 183 +#define CMD_EXTCSD_HS_TIMING 185 +#define CMD_EXTCSD_PART_SWITCH_TIME 199 +#define CMD_EXTCSD_SEC_CNT 212 + +#define EXT_CSD_PART_CONFIG_ACC_MASK GENMASK(2, 0) +#define PART_CFG_BOOT_PARTITION1_ENABLE (U(1) << 3) +#define PART_CFG_BOOT_PARTITION1_ACCESS (U(1) << 0) +#define PART_CFG_BOOT_PART_EN_MASK GENMASK(5, 3) +#define PART_CFG_BOOT_PART_EN_SHIFT 3 +#define PART_CFG_CURRENT_BOOT_PARTITION(x) (((x) & PART_CFG_BOOT_PART_EN_MASK) >> \ + PART_CFG_BOOT_PART_EN_SHIFT) + +/* Values in EXT CSD register */ +#define MMC_BUS_WIDTH_1 U(0) +#define MMC_BUS_WIDTH_4 U(1) +#define MMC_BUS_WIDTH_8 U(2) +#define MMC_BUS_WIDTH_DDR_4 U(5) +#define MMC_BUS_WIDTH_DDR_8 U(6) +#define MMC_BOOT_MODE_BACKWARD (U(0) << 3) +#define MMC_BOOT_MODE_HS_TIMING (U(1) << 3) +#define MMC_BOOT_MODE_DDR (U(2) << 3) + +#define EXTCSD_SET_CMD (U(0) << 24) +#define EXTCSD_SET_BITS (U(1) << 24) +#define EXTCSD_CLR_BITS (U(2) << 24) +#define EXTCSD_WRITE_BYTES (U(3) << 24) +#define EXTCSD_CMD(x) (((x) & 0xff) << 16) +#define EXTCSD_VALUE(x) (((x) & 0xff) << 8) +#define EXTCSD_CMD_SET_NORMAL U(1) + +#define CSD_TRAN_SPEED_UNIT_MASK GENMASK(2, 0) +#define CSD_TRAN_SPEED_MULT_MASK GENMASK(6, 3) +#define CSD_TRAN_SPEED_MULT_SHIFT 3 + +#define STATUS_CURRENT_STATE(x) (((x) & 0xf) << 9) +#define STATUS_READY_FOR_DATA BIT(8) +#define STATUS_SWITCH_ERROR BIT(7) +#define MMC_GET_STATE(x) (((x) >> 9) & 0xf) +#define MMC_STATE_IDLE 0 +#define MMC_STATE_READY 1 +#define MMC_STATE_IDENT 2 +#define MMC_STATE_STBY 3 +#define MMC_STATE_TRAN 4 +#define MMC_STATE_DATA 5 +#define MMC_STATE_RCV 6 +#define MMC_STATE_PRG 7 +#define MMC_STATE_DIS 8 +#define MMC_STATE_BTST 9 +#define MMC_STATE_SLP 10 + +#define MMC_FLAG_CMD23 (U(1) << 0) + +#define CMD8_CHECK_PATTERN U(0xAA) +#define VHS_2_7_3_6_V BIT(8) + +#define SD_SCR_BUS_WIDTH_1 BIT(8) +#define SD_SCR_BUS_WIDTH_4 BIT(10) + +struct mmc_cmd { + unsigned int cmd_idx; + unsigned int cmd_arg; + unsigned int resp_type; + unsigned int resp_data[4]; +}; + +struct mmc_ops { + void (*init)(void); + int (*send_cmd)(struct mmc_cmd *cmd); + int (*set_ios)(unsigned int clk, unsigned int width); + int (*prepare)(int lba, uintptr_t buf, size_t size); + int (*read)(int lba, uintptr_t buf, size_t size); + int (*write)(int lba, const uintptr_t buf, size_t size); +}; + +struct mmc_csd_emmc { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int ecc: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_1: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int default_ecc: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 5; + unsigned int erase_grp_mult: 5; + unsigned int erase_grp_size: 5; + unsigned int c_size_mult: 3; + unsigned int vdd_w_curr_max: 3; + unsigned int vdd_w_curr_min: 3; + unsigned int vdd_r_curr_max: 3; + unsigned int vdd_r_curr_min: 3; + unsigned int c_size_low: 2; + + unsigned int c_size_high: 10; + unsigned int reserved_2: 2; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_3: 2; + unsigned int spec_vers: 4; + unsigned int csd_structure: 2; +}; + +struct mmc_csd_sd_v2 { + unsigned int not_used: 1; + unsigned int crc: 7; + unsigned int reserved_1: 2; + unsigned int file_format: 2; + unsigned int tmp_write_protect: 1; + unsigned int perm_write_protect: 1; + unsigned int copy: 1; + unsigned int file_format_grp: 1; + + unsigned int reserved_2: 5; + unsigned int write_bl_partial: 1; + unsigned int write_bl_len: 4; + unsigned int r2w_factor: 3; + unsigned int reserved_3: 2; + unsigned int wp_grp_enable: 1; + + unsigned int wp_grp_size: 7; + unsigned int sector_size: 7; + unsigned int erase_block_en: 1; + unsigned int reserved_4: 1; + unsigned int c_size_low: 16; + + unsigned int c_size_high: 6; + unsigned int reserved_5: 6; + unsigned int dsr_imp: 1; + unsigned int read_blk_misalign: 1; + unsigned int write_blk_misalign: 1; + unsigned int read_bl_partial: 1; + unsigned int read_bl_len: 4; + unsigned int ccc: 12; + + unsigned int tran_speed: 8; + unsigned int nsac: 8; + unsigned int taac: 8; + unsigned int reserved_6: 6; + unsigned int csd_structure: 2; +}; + +enum mmc_device_type { + MMC_IS_EMMC, + MMC_IS_SD, + MMC_IS_SD_HC, +}; + +struct mmc_device_info { + unsigned long long device_size; /* Size of device in bytes */ + unsigned int block_size; /* Block size in bytes */ + unsigned int max_bus_freq; /* Max bus freq in Hz */ + unsigned int ocr_voltage; /* OCR voltage */ + enum mmc_device_type mmc_dev_type; /* Type of MMC */ +}; + +size_t mmc_read_blocks(int lba, uintptr_t buf, size_t size); +size_t mmc_write_blocks(int lba, const uintptr_t buf, size_t size); +size_t mmc_erase_blocks(int lba, size_t size); +size_t mmc_rpmb_read_blocks(int lba, uintptr_t buf, size_t size); +size_t mmc_rpmb_write_blocks(int lba, const uintptr_t buf, size_t size); +size_t mmc_rpmb_erase_blocks(int lba, size_t size); +size_t mmc_boot_part_read_blocks(int lba, uintptr_t buf, size_t size); +int mmc_init(const struct mmc_ops *ops_ptr, unsigned int clk, + unsigned int width, unsigned int flags, + struct mmc_device_info *device_info); + +#endif /* MMC_H */ diff --git a/arm-trusted-firmware/include/drivers/nand.h b/arm-trusted-firmware/include/drivers/nand.h new file mode 100644 index 0000000..1b78ad4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nand.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2019-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_NAND_H +#define DRIVERS_NAND_H + +#include +#include + +#include + +#define PSEC_TO_MSEC(x) div_round_up((x), 1000000000ULL) + +struct ecc { + unsigned int mode; /* ECC mode NAND_ECC_MODE_{NONE|HW|ONDIE} */ + unsigned int size; /* Data byte per ECC step */ + unsigned int bytes; /* ECC bytes per step */ + unsigned int max_bit_corr; /* Max correctible bits per ECC steps */ +}; + +struct nand_device { + unsigned int block_size; + unsigned int page_size; + unsigned long long size; + unsigned int nb_planes; + unsigned int buswidth; + struct ecc ecc; + int (*mtd_block_is_bad)(unsigned int block); + int (*mtd_read_page)(struct nand_device *nand, unsigned int page, + uintptr_t buffer); +}; + +/* + * Read bytes from NAND device + * + * @offset: Byte offset to read from in device + * @buffer: [out] Bytes read from device + * @length: Number of bytes to read + * @length_read: [out] Number of bytes read from device + * Return: 0 on success, a negative errno on failure + */ +int nand_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read); + +/* + * Look for an extra offset to be added in case of bad blocks + * + * @base: Base address of the area + * @offset: Byte offset to read from in device + * @extra_offset: [out] Extra offset to be added if bad blocks are found + * Return: 0 on success, a negative errno on failure + */ +int nand_seek_bb(uintptr_t base, unsigned int offset, size_t *extra_offset); + +/* + * Get NAND device instance + * + * Return: NAND device instance reference + */ +struct nand_device *get_nand_device(void); + +#endif /* DRIVERS_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h b/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h new file mode 100644 index 0000000..ae56d3b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h @@ -0,0 +1,155 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSF_HDR_H +#define CSF_HDR_H + +#include "caam.h" +#include "hash.h" +#include "rsa.h" + +/* Barker code size in bytes */ +#define CSF_BARKER_LEN 4 /* barker code length in ESBC uboot client */ + /* header */ + +#ifdef CSF_HDR_CH3 +struct csf_hdr { + uint8_t barker[CSF_BARKER_LEN]; /* 0x00 Barker code */ + uint32_t srk_tbl_off; /* 0x04 SRK Table Offset */ + + struct { + uint8_t num_srk; /* 0x08 No. of keys */ + uint8_t srk_sel; /* Key no. to be used */ + uint8_t reserve; /* 0x0a rseerved */ + } len_kr; + uint8_t ie_flag; + + uint32_t uid_flag; + + uint32_t psign; /* 0x10 signature offset */ + uint32_t sign_len; /* 0x14 length of signature */ + + union { + struct { + uint32_t sg_table_offset; /* 0x18 SG Table Offset */ + uint32_t sg_entries; /* 0x1c no of entries in SG */ + } sg_isbc; + uint64_t img_addr; /* 64 bit pointer to ESBC Image */ + }; + + union { + struct { + uint32_t img_size; /* ESBC client img size in bytes */ + uint32_t ie_key_sel; + } img; + uint64_t entry_point; /* 0x20-0x24 ESBC entry point */ + }; + + uint32_t fsl_uid_0; /* 0x28 Freescale unique id 0 */ + uint32_t fsl_uid_1; /* 0x2c Freescale unique id 1 */ + uint32_t oem_uid_0; /* 0x30 OEM unique id 0 */ + uint32_t oem_uid_1; /* 0x34 OEM unique id 1 */ + uint32_t oem_uid_2; /* 0x38 OEM unique id 2 */ + uint32_t oem_uid_3; /* 0x3c OEM unique id 3 */ + uint32_t oem_uid_4; /* 0x40 OEM unique id 4 */ + + uint32_t reserved[3]; /* 0x44 - 0x4f */ +}; + +/* Srk table and key revocation check */ +#define UNREVOCABLE_KEY 8 +#define REVOC_KEY_ALIGN 7 +#define MAX_KEY_ENTRIES 8 + +#else + +/* CSF header for Chassis 2 */ +struct csf_hdr { + uint8_t barker[CSF_BARKER_LEN]; /* barker code */ + union { + uint32_t pkey; /* public key offset */ + uint32_t srk_tbl_off; + }; + + union { + uint32_t key_len; /* pub key length in bytes */ + struct { + uint32_t srk_table_flag:8; + uint32_t srk_sel:8; + uint32_t num_srk:16; + } len_kr; + }; + + uint32_t psign; /* signature offset */ + uint32_t sign_len; /* length of the signature in bytes */ + + /* SG Table used by ISBC header */ + union { + struct { + uint32_t sg_table_offset; /* 0x14 SG Table Offset */ + uint32_t sg_entries; /* no of entries in SG table */ + } sg_isbc; + struct { + uint32_t reserved1; /* Reserved field */ + uint32_t img_size; /* ESBC img size in bytes */ + } img; + }; + + uint32_t entry_point; /* ESBC client entry point */ + uint32_t reserved2; /* Scatter gather flag */ + uint32_t uid_flag; + uint32_t fsl_uid_0; + uint32_t oem_uid_0; + uint32_t reserved3[2]; + uint32_t fsl_uid_1; + uint32_t oem_uid_1; + + /* The entries below aren't present in ISBC header */ + uint64_t img_addr; /* 64 bit pointer to ESBC Image */ + uint32_t ie_flag; + uint32_t ie_key_sel; +}; + +/* Srk table and key revocation check */ +#define UNREVOCABLE_KEY 4 +#define REVOC_KEY_ALIGN 3 +#define MAX_KEY_ENTRIES 4 + +#endif + +struct srk_table { + uint32_t key_len; + uint8_t pkey[2 * RSA_4K_KEY_SZ_BYTES]; +}; + +/* + * This struct contains the following fields + * length of the segment + * Destination Target ID + * source address + * destination address + */ +struct sg_table { + uint32_t len; /* Length of Image */ + uint32_t res1; + union { + uint64_t src_addr; /* SRC Address of Image */ + struct { + uint32_t src_addr; + uint32_t dst_addr; + } img; + }; +}; + +int validate_esbc_header(void *img_hdr, void **img_key, uint32_t *key_len, + void **img_sign, uint32_t *sign_len, + enum sig_alg *algo); + +int calc_img_hash(struct csf_hdr *hdr, void *img_addr, uint32_t img_size, + uint8_t *img_hash, uint32_t *hash_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h b/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h new file mode 100644 index 0000000..8b1b23a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/console/plat_console.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_CONSOLE_H +#define PLAT_CONSOLE_H + +#include +#include + +#if (NXP_CONSOLE == NS16550) +/* + * NXP specific UART - 16550 configuration + * + * Initialize a NXP 16550 console instance and register it with the console + * framework. The |console| pointer must point to storage that will be valid + * for the lifetime of the console, such as a global or static local variable. + * Its contents will be reinitialized from scratch. + * When |clock| has a value of 0, the UART will *not* be initialised. This + * means the UART should already be enabled and the baudrate and clock setup + * should have been done already, either by platform specific code or by + * previous firmware stages. The |baud| parameter will be ignored in this + * case as well. + */ +int nxp_console_16550_register(uintptr_t baseaddr, uint32_t clock, + uint32_t baud, console_t *console); +#endif +/* + * Function to initialize platform's console + * and register with console framework + */ +void plat_console_init(uintptr_t nxp_console_addr, uint32_t uart_clk_div, + uint32_t baud); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h new file mode 100644 index 0000000..6cc1f3d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h @@ -0,0 +1,53 @@ +/* + * Copyright 2017-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_H +#define CAAM_H + +#include "caam_io.h" +#include "sec_jr_driver.h" + + +/* Job ring 3 is reserved for usage by sec firmware */ +#define DEFAULT_JR 3 + +#if defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_2) +#define CAAM_JR0_OFFSET 0x10000 +#define CAAM_JR1_OFFSET 0x20000 +#define CAAM_JR2_OFFSET 0x30000 +#define CAAM_JR3_OFFSET 0x40000 +#endif + +enum sig_alg { + RSA, + ECC +}; + +/* This function does basic SEC Initialization */ +int sec_init(uintptr_t nxp_caam_addr); +int config_sec_block(void); +uintptr_t get_caam_addr(void); + +/* This function is used to submit jobs to JR */ +int run_descriptor_jr(struct job_descriptor *desc); + +/* This function is used to instatiate the HW RNG is already not instantiated */ +int hw_rng_instantiate(void); + +/* This function is used to return random bytes of byte_len from HW RNG */ +int get_rand_bytes_hw(uint8_t *bytes, int byte_len); + +/* This function is used to set the hw unique key from HW CAAM */ +int get_hw_unq_key_blob_hw(uint8_t *hw_key, int size); + +/* This function is used to fetch random number from + * CAAM of length either of 4 bytes or 8 bytes depending + * rngWidth value. + */ +unsigned long long get_random(int rngWidth); + +#endif /* CAAM_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h new file mode 100644 index 0000000..b68f836 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h @@ -0,0 +1,56 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CAAM_IO_H +#define CAAM_IO_H + +#include +#include + +typedef unsigned long long phys_addr_t; +typedef unsigned long long phys_size_t; + +/* Return higher 32 bits of physical address */ +#define PHYS_ADDR_HI(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) >> 32) + +/* Return lower 32 bits of physical address */ +#define PHYS_ADDR_LO(phys_addr) \ + (uint32_t)(((uint64_t)phys_addr) & 0xFFFFFFFF) + +#ifdef NXP_SEC_BE +#define sec_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr)) << 32) | \ + (sec_in32(((uintptr_t)(addr)) + 4))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)), (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)(val)); }) +#elif defined(NXP_SEC_LE) +#define sec_in32(a) mmio_read_32((uintptr_t)(a)) +#define sec_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#define sec_in64(addr) ( \ + ((uint64_t)sec_in32((uintptr_t)(addr) + 4) << 32) | \ + (sec_in32((uintptr_t)(addr)))) +#define sec_out64(addr, val) ({ \ + sec_out32(((uintptr_t)(addr)) + 4, (uint32_t)((val) >> 32)); \ + sec_out32(((uintptr_t)(addr)), (uint32_t)(val)); }) +#else +#error Please define CCSR SEC register endianness +#endif + +static inline void *ptov(phys_addr_t *ptr) +{ + return (void *)ptr; +} + +static inline phys_addr_t *vtop(void *ptr) +{ + return (phys_addr_t *)ptr; +} +#endif /* CAAM_IO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h new file mode 100644 index 0000000..9136dca --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h @@ -0,0 +1,85 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __HASH_H__ +#define __HASH_H__ + +#include + +/* List of hash algorithms */ +enum hash_algo { + SHA1 = 0, + SHA256 +}; + +/* number of bytes in the SHA256-256 digest */ +#define SHA256_DIGEST_SIZE 32 + +/* + * number of words in the digest - Digest is kept internally + * as 8 32-bit words + */ +#define _SHA256_DIGEST_LENGTH 8 + +/* + * block length - A block, treated as a sequence of + * 32-bit words + */ +#define SHA256_BLOCK_LENGTH 16 + +/* number of bytes in the block */ +#define SHA256_DATA_SIZE 64 + +#define MAX_SG 12 + +struct sg_entry { +#if defined(NXP_SEC_LE) + uint32_t addr_lo; /* Memory Address - lo */ + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ +#else + uint32_t addr_hi; /* Memory Address of start of buffer - hi */ + uint32_t addr_lo; /* Memory Address - lo */ +#endif + + uint32_t len_flag; /* Length of the data in the frame */ +#define SG_ENTRY_LENGTH_MASK 0x3FFFFFFF +#define SG_ENTRY_EXTENSION_BIT 0x80000000 +#define SG_ENTRY_FINAL_BIT 0x40000000 + uint32_t bpid_offset; +#define SG_ENTRY_BPID_MASK 0x00FF0000 +#define SG_ENTRY_BPID_SHIFT 16 +#define SG_ENTRY_OFFSET_MASK 0x00001FFF +#define SG_ENTRY_OFFSET_SHIFT 0 +}; + +/* + * SHA256-256 context + * contain the following fields + * State + * count low + * count high + * block data buffer + * index to the buffer + */ +struct hash_ctx { + struct sg_entry sg_tbl[MAX_SG]; + uint32_t hash_desc[64]; + uint8_t hash[SHA256_DIGEST_SIZE]; + uint32_t sg_num; + uint32_t len; + uint8_t *data; + enum hash_algo algo; + bool active; +}; + +int hash_init(enum hash_algo algo, void **ctx); +int hash_update(enum hash_algo algo, void *context, void *data_ptr, + unsigned int data_len); +int hash_final(enum hash_algo algo, void *context, void *hash_ptr, + unsigned int hash_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h new file mode 100644 index 0000000..efef228 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h @@ -0,0 +1,56 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef __JOBDESC_H +#define __JOBDESC_H + +#include + +#define DESC_LEN_MASK 0x7f +#define DESC_START_SHIFT 16 + +#define KEY_BLOB_SIZE 32 +#define MAC_SIZE 16 + +#define KEY_IDNFR_SZ_BYTES 16 +#define CLASS_SHIFT 25 +#define CLASS_2 (0x02 << CLASS_SHIFT) + +#define CMD_SHIFT 27 +#define CMD_OPERATION (U(0x10) << CMD_SHIFT) + +#define OP_TYPE_SHIFT 24 +#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT) + +/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */ +#define OP_PCLID_SHIFT 16 +#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT) + +#define BLOB_PROTO_INFO 0x00000002 + +uint32_t desc_length(uint32_t *desc); + +int cnstr_rng_jobdesc(uint32_t *desc, uint32_t state_handle, + uint32_t *add_inp, uint32_t add_ip_len, + uint8_t *out_data, uint32_t len); + +int cnstr_rng_instantiate_jobdesc(uint32_t *desc); + +/* Construct descriptor to generate hw key blob */ +int cnstr_hw_encap_blob_jobdesc(uint32_t *desc, + uint8_t *key_idnfr, uint32_t key_sz, + uint32_t key_class, uint8_t *plain_txt, + uint32_t in_sz, uint8_t *enc_blob, + uint32_t out_sz, uint32_t operation); + +void cnstr_hash_jobdesc(uint32_t *desc, uint8_t *msg, uint32_t msgsz, + uint8_t *digest); + +void cnstr_jobdesc_pkha_rsaexp(uint32_t *desc, + struct pk_in_params *pkin, uint8_t *out, + uint32_t out_siz); +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h new file mode 100644 index 0000000..1b3c447 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h @@ -0,0 +1,205 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_CONFIG_H_ +#define _JR_DRIVER_CONFIG_H_ + +/* Helper defines */ + + /* Define used for setting a flag on */ +#define ON 1 + /* Define used for setting a flag off */ +#define OFF 0 + + /* SEC is configured to start work in polling mode, */ +#define SEC_STARTUP_POLLING_MODE 0 +/* + * SEC is configured to start work in interrupt mode, + * when configured for NAPI notification style. + */ +#define SEC_STARTUP_INTERRUPT_MODE 1 + +/* + * SEC driver will use ONLY interrupts to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_IRQ 1 +/* + * SEC driver will use ONLY polling to receive notifications + * for processed packets from SEC engine hardware. + */ +#define SEC_NOTIFICATION_TYPE_POLL 2 + +/* + * Determines how SEC user space driver will receive notifications + * for processed packets from SEC engine. + * Valid values are: #SEC_NOTIFICATION_TYPE_POLL, #SEC_NOTIFICATION_TYPE_IRQ + */ +#define SEC_NOTIFICATION_TYPE SEC_NOTIFICATION_TYPE_POLL + + /* Maximum number of job rings supported by SEC hardware */ +#define MAX_SEC_JOB_RINGS 1 + +/* + * Size of cryptographic context that is used directly in communicating + * with SEC device. + * SEC device works only with physical addresses. This is the maximum size + * for a SEC descriptor ( = 64 words). + */ + +#define SEC_CRYPTO_DESCRIPTOR_SIZE 256 + +/* + * Size of job descriptor submitted to SEC device for each packet to be + * processed. + * Job descriptor contains 3 DMA address pointers: + * - to shared descriptor, to input buffer and to output buffer. + * The job descriptor contains other SEC specific commands as well: + * - HEADER command, SEQ IN PTR command SEQ OUT PTR command and opaque + * data, each measuring 4 bytes. + * Job descriptor size, depending on physical address representation: + * - 32 bit - size is 28 bytes - cacheline-aligned size is 64 bytes + * - 36 bit - size is 40 bytes - cacheline-aligned size is 64 bytes + * @note: Job descriptor must be cacheline-aligned to ensure efficient memory + * access. + * @note: If other format is used for job descriptor, then the size must be + * revised. + */ + +#define SEC_JOB_DESCRIPTOR_SIZE 64 + +/* + * Size of one entry in the input ring of a job ring. + * Input ring contains pointers to job descriptors. + * The memory used for an input ring and output ring must be physically + * contiguous. + */ + +#define SEC_JOB_INPUT_RING_ENTRY_SIZE sizeof(phys_addr_t) + +/* + * Size of one entry in the output ring of a job ring. + * Output ring entry is a pointer to a job descriptor followed by a 4 byte + * status word. + * The memory used for an input ring and output ring must be physically + * contiguous. + * @note If desired to use also the optional SEQ OUT indication in output + * ring entries, then 4 more bytes must be added to the size. + */ + +#define SEC_JOB_OUTPUT_RING_ENTRY_SIZE (SEC_JOB_INPUT_RING_ENTRY_SIZE + 4) + + /* DMA memory required for an input ring of a job ring. */ +#define SEC_DMA_MEM_INPUT_RING_SIZE \ + ((SEC_JOB_INPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + +/* + * DMA memory required for an output ring of a job ring. + * Required extra 4 byte for status word per each entry. + */ +#define SEC_DMA_MEM_OUTPUT_RING_SIZE \ + ((SEC_JOB_OUTPUT_RING_ENTRY_SIZE) * (SEC_JOB_RING_SIZE)) + + /* DMA memory required for descriptors of a job ring. */ +#define SEC_DMA_MEM_DESCRIPTORS \ + ((SEC_CRYPTO_DESCRIPTOR_SIZE)*(SEC_JOB_RING_SIZE)) + + /* DMA memory required for a job ring, including both input output rings. */ +#define SEC_DMA_MEM_JOB_RING_SIZE \ + ((SEC_DMA_MEM_INPUT_RING_SIZE) + \ + (SEC_DMA_MEM_OUTPUT_RING_SIZE)) + +/* + * When calling sec_init() UA will provide an area of virtual memory + * of size #SEC_DMA_MEMORY_SIZE to be used internally by the driver + * to allocate data (like SEC descriptors) that needs to be passed to + * SEC device in physical addressing and later on retrieved from SEC device. + * At initialization the UA provides specialized ptov/vtop functions/macros to + * translate addresses allocated from this memory area. + */ +#define SEC_DMA_MEMORY_SIZE \ + ((SEC_DMA_MEM_JOB_RING_SIZE) * (MAX_SEC_JOB_RINGS)) + +/* + * SEC DEVICE related configuration. + + * Enable/Disable logging support at compile time. + * Valid values: + * ON - enable logging + * OFF - disable logging + * The messages are logged at stdout. + */ + +#define SEC_DRIVER_LOGGING OFF + +/* + * Configure logging level at compile time. + * Valid values: + * SEC_DRIVER_LOG_ERROR - log only errors + * SEC_DRIVER_LOG_INFO - log errors and info messages + * SEC_DRIVER_LOG_DEBUG - log errors, info and debug messages + */ + +#define SEC_DRIVER_LOGGING_LEVEL SEC_DRIVER_LOG_DEBUG + +/* + * SEC JOB RING related configuration. + + * Configure the size of the JOB RING. + * The maximum size of the ring is hardware limited to 1024. + * However the number of packets in flight in a time interval of + * 1ms can be calculated + * from the traffic rate (Mbps) and packet size. + * Here it was considered a packet size of 40 bytes. + * @note Round up to nearest power of 2 for optimized update + * of producer/consumer indexes of each job ring + * \todo Should set to 750, according to the calculation above, but + * the JR size must be power of 2, thus the next closest value must + * be chosen (i.e. 512 since 1024 is not available) + * For firmware choose this to be 16 + */ + +#define SEC_JOB_RING_SIZE 16 + +/* + * Interrupt coalescing related configuration. + * NOTE: SEC hardware enabled interrupt + * coalescing is not supported on SEC version 3.1! + * SEC version 4.4 has support for interrupt + * coalescing. + */ + +#if SEC_NOTIFICATION_TYPE != SEC_NOTIFICATION_TYPE_POLL + +#define SEC_INT_COALESCING_ENABLE ON +/* + * Interrupt Coalescing Descriptor Count Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines + * how many Descriptors are completed before raising an interrupt. + * Valid values for this field are from 0 to 255. + * Note that a value of 1 functionally defeats the advantages of interrupt + * coalescing since the threshold value is reached each time that a + * Job Descriptor is completed. A value of 0 is treated in the same + * manner as a value of 1. + * + */ +#define SEC_INTERRUPT_COALESCING_DESCRIPTOR_COUNT_THRESH 10 + +/* + * Interrupt Coalescing Timer Threshold. + * While interrupt coalescing is enabled (ICEN=1), this value determines the + * maximum amount of time after processing a Descriptor before raising an + * interrupt. + * The threshold value is represented in units equal to 64 CAAM interface + * clocks. Valid values for this field are from 1 to 65535. + * A value of 0 results in behavior identical to that when interrupt + * coalescing is disabled. + */ +#define SEC_INTERRUPT_COALESCING_TIMER_THRESH 100 +#endif /* SEC_NOTIFICATION_TYPE_POLL */ + +#endif /* _JR_DRIVER_CONFIG_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h new file mode 100644 index 0000000..dd9ecdc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h @@ -0,0 +1,40 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _RSA_H__ +#define _RSA_H__ + +/* RSA key size defines */ +#define RSA_4K_KEY_SZ 4096 +#define RSA_4K_KEY_SZ_BYTES (RSA_4K_KEY_SZ/8) +#define RSA_2K_KEY_SZ 2048 +#define RSA_2K_KEY_SZ_BYTES (RSA_2K_KEY_SZ/8) +#define RSA_1K_KEY_SZ 1024 +#define RSA_1K_KEY_SZ_BYTES (RSA_1K_KEY_SZ/8) + +#define SHA256_BYTES (256/8) + +struct pk_in_params { + uint8_t *e; + uint32_t e_siz; + uint8_t *n; + uint32_t n_siz; + uint8_t *a; + uint32_t a_siz; + uint8_t *b; + uint32_t b_siz; +}; + +struct rsa_context { + struct pk_in_params pkin; +}; + +int rsa_verify_signature(void *hash_ptr, unsigned int hash_len, + void *sig_ptr, unsigned int sig_len, + void *pk_ptr, unsigned int pk_len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h new file mode 100644 index 0000000..9800793 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h @@ -0,0 +1,503 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _SEC_HW_SPECIFIC_H_ +#define _SEC_HW_SPECIFIC_H_ + +#include "caam.h" +#include "sec_jr_driver.h" + + /* DEFINES AND MACROS */ + +/* Used to retry resetting a job ring in SEC hardware. */ +#define SEC_TIMEOUT 100000 + +/* + * Offset to the registers of a job ring. + *Is different for each job ring. + */ +#define CHAN_BASE(jr) ((phys_addr_t)(jr)->register_base_addr) + +#define unlikely(x) __builtin_expect(!!(x), 0) + +#define SEC_JOB_RING_IS_FULL(pi, ci, ring_max_size, ring_threshold) \ + ((((pi) + 1 + ((ring_max_size) - (ring_threshold))) & \ + (ring_max_size - 1)) == ((ci))) + +#define SEC_CIRCULAR_COUNTER(x, max) (((x) + 1) & (max - 1)) + + /* Struct representing various job ring registers */ +struct jobring_regs { +#ifdef NXP_SEC_BE + unsigned int irba_h; + unsigned int irba_l; +#else + unsigned int irba_l; + unsigned int irba_h; +#endif + unsigned int rsvd1; + unsigned int irs; + unsigned int rsvd2; + unsigned int irsa; + unsigned int rsvd3; + unsigned int irja; +#ifdef NXP_SEC_BE + unsigned int orba_h; + unsigned int orba_l; +#else + unsigned int orba_l; + unsigned int orba_h; +#endif + unsigned int rsvd4; + unsigned int ors; + unsigned int rsvd5; + unsigned int orjr; + unsigned int rsvd6; + unsigned int orsf; + unsigned int rsvd7; + unsigned int jrsta; + unsigned int rsvd8; + unsigned int jrint; + unsigned int jrcfg0; + unsigned int jrcfg1; + unsigned int rsvd9; + unsigned int irri; + unsigned int rsvd10; + unsigned int orwi; + unsigned int rsvd11; + unsigned int jrcr; +}; + + /* Offsets representing common SEC Registers */ +#define SEC_REG_MCFGR_OFFSET 0x0004 +#define SEC_REG_SCFGR_OFFSET 0x000C +#define SEC_REG_JR0ICIDR_MS_OFFSET 0x0010 +#define SEC_REG_JR0ICIDR_LS_OFFSET 0x0014 +#define SEC_REG_JR1ICIDR_MS_OFFSET 0x0018 +#define SEC_REG_JR1ICIDR_LS_OFFSET 0x001C +#define SEC_REG_JR2ICIDR_MS_OFFSET 0x0020 +#define SEC_REG_JR2ICIDR_LS_OFFSET 0x0024 +#define SEC_REG_JR3ICIDR_MS_OFFSET 0x0028 +#define SEC_REG_JR3ICIDR_LS_OFFSET 0x002C +#define SEC_REG_JRSTARTR_OFFSET 0x005C +#define SEC_REG_CTPR_MS_OFFSET 0x0FA8 + + /* Offsets representing various RNG registers */ +#define RNG_REG_RTMCTL_OFFSET 0x0600 +#define RNG_REG_RTSDCTL_OFFSET 0x0610 +#define RNG_REG_RTFRQMIN_OFFSET 0x0618 +#define RNG_REG_RTFRQMAX_OFFSET 0x061C +#define RNG_REG_RDSTA_OFFSET 0x06C0 +#define ALG_AAI_SH_SHIFT 4 + + /* SEC Registers Bitmasks */ +#define MCFGR_PS_SHIFT 16 +#define MCFGR_AWCACHE_SHIFT 8 +#define MCFGR_AWCACHE_MASK (0xF << MCFGR_AWCACHE_SHIFT) +#define MCFGR_ARCACHE_SHIFT 12 +#define MCFGR_ARCACHE_MASK (0xF << MCFGR_ARCACHE_SHIFT) + +#define SCFGR_RNGSH0 0x00000200 +#define SCFGR_VIRT_EN 0x00008000 + +#define JRICID_MS_LICID 0x80000000 +#define JRICID_MS_LAMTD 0x00020000 +#define JRICID_MS_AMTDT 0x00010000 +#define JRICID_MS_TZ 0x00008000 +#define JRICID_LS_SDID_MASK 0x00000FFF +#define JRICID_LS_NSEQID_MASK 0x0FFF0000 +#define JRICID_LS_NSEQID_SHIFT 16 +#define JRICID_LS_SEQID_MASK 0x00000FFF + +#define JRSTARTR_STARTJR0 0x00000001 +#define JRSTARTR_STARTJR1 0x00000002 +#define JRSTARTR_STARTJR2 0x00000004 +#define JRSTARTR_STARTJR3 0x00000008 + +#define CTPR_VIRT_EN_POR 0x00000002 +#define CTPR_VIRT_EN_INC 0x00000001 + + /* RNG RDSTA bitmask */ +#define RNG_STATE0_HANDLE_INSTANTIATED 0x00000001 +#define RTMCTL_PRGM 0x00010000 /* 1 -> program mode, 0 -> run mode */ + /* use von Neumann data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_SC 0 + /* use raw data in both entropy shifter and statistical checker */ +#define RTMCTL_SAMP_MODE_RAW_ES_SC 1 + /* use von Neumann data in entropy shifter, raw data in statistical checker */ +#define RTMCTL_SAMP_MODE_VON_NEUMANN_ES_RAW_SC 2 + /* invalid combination */ +#define RTMCTL_SAMP_MODE_INVALID 3 +#define RTSDCTL_ENT_DLY_MIN 3200 +#define RTSDCTL_ENT_DLY_MAX 12800 +#define RTSDCTL_ENT_DLY_SHIFT 16 +#define RTSDCTL_ENT_DLY_MASK (U(0xffff) << RTSDCTL_ENT_DLY_SHIFT) +#define RTFRQMAX_DISABLE (1 << 20) + + /* Constants for error handling on job ring */ +#define JR_REG_JRINT_ERR_TYPE_SHIFT 8 +#define JR_REG_JRINT_ERR_ORWI_SHIFT 16 +#define JR_REG_JRINIT_JRE_SHIFT 1 + +#define JRINT_JRE (1 << JR_REG_JRINIT_JRE_SHIFT) +#define JRINT_ERR_WRITE_STATUS (1 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_INPUT_BASE (3 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_BAD_OUTPUT_BASE (4 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_IRBA (5 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_WRITE_2_ORBA (6 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_RES_B4_HALT (7 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_REM_TOO_MANY (8 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_ADD_TOO_MANY (9 << JR_REG_JRINT_ERR_TYPE_SHIFT) +#define JRINT_ERR_HALT_MASK 0x0C +#define JRINT_ERR_HALT_INPROGRESS 0x04 +#define JRINT_ERR_HALT_COMPLETE 0x08 + +#define JR_REG_JRCR_VAL_RESET 0x00000001 + +#define JR_REG_JRCFG_LO_ICTT_SHIFT 0x10 +#define JR_REG_JRCFG_LO_ICDCT_SHIFT 0x08 +#define JR_REG_JRCFG_LO_ICEN_EN 0x02 +#define JR_REG_JRCFG_LO_IMSK_EN 0x01 + + /* Constants for Descriptor Processing errors */ +#define SEC_HW_ERR_SSRC_NO_SRC 0x00 +#define SEC_HW_ERR_SSRC_CCB_ERR 0x02 +#define SEC_HW_ERR_SSRC_JMP_HALT_U 0x03 +#define SEC_HW_ERR_SSRC_DECO 0x04 +#define SEC_HW_ERR_SSRC_JR 0x06 +#define SEC_HW_ERR_SSRC_JMP_HALT_COND 0x07 + +#define SEC_HW_ERR_DECO_HFN_THRESHOLD 0xF1 +#define SEC_HW_ERR_CCB_ICV_CHECK_FAIL 0x0A + + /* Macros for extracting error codes for the job ring */ + +#define JR_REG_JRINT_ERR_TYPE_EXTRACT(value) \ + ((value) & 0x00000F00) + +#define JR_REG_JRINT_ERR_ORWI_EXTRACT(value) \ + (((value) & 0x3FFF0000) >> \ + JR_REG_JRINT_ERR_ORWI_SHIFT) + +#define JR_REG_JRINT_JRE_EXTRACT(value) \ + ((value) & JRINT_JRE) + + /* Macros for manipulating JR registers */ +typedef struct { +#ifdef NXP_SEC_BE + uint32_t high; + uint32_t low; +#else + uint32_t low; + uint32_t high; +#endif +} ptr_addr_t; + +#if defined(CONFIG_PHYS_64BIT) +#define sec_read_addr(a) sec_in64((a)) +#define sec_write_addr(a, v) sec_out64((a), (v)) +#else +#define sec_read_addr(a) sec_in32((a)) +#define sec_write_addr(a, v) sec_out32((a), (v)) +#endif + +#define JR_REG(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET) +#define JR_REG_LO(name, jr) (CHAN_BASE(jr) + JR_REG_##name##_OFFSET_LO) + +#define GET_JR_REG(name, jr) (sec_in32(JR_REG(name, (jr)))) +#define GET_JR_REG_LO(name, jr) (sec_in32(JR_REG_LO(name, (jr)))) + +#define SET_JR_REG(name, jr, val) \ + (sec_out32(JR_REG(name, (jr)), (val))) + +#define SET_JR_REG_LO(name, jr, val) \ + (sec_out32(JR_REG_LO(name, (jr)), (val))) + + /* STRUCTURES AND OTHER TYPEDEFS */ + /* Lists the possible states for a job ring. */ +typedef enum sec_job_ring_state_e { + SEC_JOB_RING_STATE_STARTED, /* Job ring is initialized */ + SEC_JOB_RING_STATE_RESET, /* Job ring reset is in progres */ +} sec_job_ring_state_t; + +struct sec_job_ring_t { + /* + * Consumer index for job ring (jobs array). + * @note: cidx and pidx are accessed from + * different threads. + * Place the cidx and pidx inside the structure + * so that they lay on different cachelines, to + * avoid false sharing between threads when the + * threads run on different cores! + */ + uint32_t cidx; + + /* Producer index for job ring (jobs array) */ + uint32_t pidx; + + /* Ring of input descriptors. Size of array is power of 2 to allow + * fast update of producer/consumer indexes with bitwise operations. + */ + phys_addr_t *input_ring; + + /* Ring of output descriptors. */ + struct sec_outring_entry *output_ring; + + /* The file descriptor used for polling for interrupts notifications */ + uint32_t irq_fd; + + /* Model used by SEC Driver to receive notifications from SEC. + * Can be either of the three: + * #SEC_NOTIFICATION_TYPE_IRQ or + * #SEC_NOTIFICATION_TYPE_POLL + */ + uint32_t jr_mode; + /* Base address for SEC's register memory for this job ring. */ + void *register_base_addr; + /* notifies if coelescing is enabled for the job ring */ + uint8_t coalescing_en; + /* The state of this job ring */ + sec_job_ring_state_t jr_state; +}; + + /* Forward structure declaration */ +typedef struct sec_job_ring_t sec_job_ring_t; + +struct sec_outring_entry { + phys_addr_t desc; /* Pointer to completed descriptor */ + uint32_t status; /* Status for completed descriptor */ +} __packed; + + /* Lists the states possible for the SEC user space driver. */ +typedef enum sec_driver_state_e { + SEC_DRIVER_STATE_IDLE, /*< Driver not initialized */ + SEC_DRIVER_STATE_STARTED, /*< Driver initialized and */ + SEC_DRIVER_STATE_RELEASE, /*< Driver release is in progress */ +} sec_driver_state_t; + + /* Union describing the possible error codes that */ + /* can be set in the descriptor status word */ + +union hw_error_code { + uint32_t error; + union { + struct { + uint32_t ssrc:4; + uint32_t ssed_val:28; + } __packed value; + struct { + uint32_t ssrc:4; + uint32_t res:28; + } __packed no_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cha_id:4; + uint32_t err_id:4; + } __packed ccb_status_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t offset:8; + } __packed jmp_halt_user_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t desc_err:8; + } __packed deco_src; + struct { + uint32_t ssrc:4; + uint32_t res:17; + uint32_t naddr:3; + uint32_t desc_err:8; + } __packed jr_src; + struct { + uint32_t ssrc:4; + uint32_t jmp:1; + uint32_t res:11; + uint32_t desc_idx:8; + uint32_t cond:8; + } __packed jmp_halt_cond_src; + } __packed error_desc; +} __packed; + + /* FUNCTION PROTOTYPES */ + +/* + * @brief Initialize a job ring/channel in SEC device. + * Write configuration register/s to properly initialize a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval other for error + */ +int hw_reset_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Reset a job ring/channel in SEC device. + * Write configuration register/s to reset a job ring. + * + * @param [in] job_ring The job ring + * + * @retval 0 for success + * @retval -1 in case job ring reset failed + */ +int hw_shutdown_job_ring(sec_job_ring_t *job_ring); + +/* + * @brief Handle a job ring/channel error in SEC device. + * Identify the error type and clear error bits if required. + * + * @param [in] job_ring The job ring + * @param [in] sec_error_code error code as first read from SEC engine + */ + +void hw_handle_job_ring_error(sec_job_ring_t *job_ring, + uint32_t sec_error_code); +/* + * @brief Handle a job ring error in the device. + * Identify the error type and printout a explanatory + * messages. + * + * @param [in] job_ring The job ring + * + */ + +int hw_job_ring_error(sec_job_ring_t *job_ring); + +/* @brief Set interrupt coalescing parameters on the Job Ring. + * @param [in] job_ring The job ring + * @param [in] irq_coalesing_timer + * Interrupt coalescing timer threshold. + * This value determines the maximum + * amount of time after processing a descriptor + * before raising an interrupt. + * @param [in] irq_coalescing_count + * Interrupt coalescing count threshold. + * This value determines how many descriptors + * are completed before raising an interrupt. + */ + +int hw_job_ring_set_coalescing_param(sec_job_ring_t *job_ring, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count); + +/* @brief Enable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_enable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Disable interrupt coalescing on a job ring + * @param [in] job_ring The job ring + */ + +int hw_job_ring_disable_coalescing(sec_job_ring_t *job_ring); + +/* + * @brief Poll the HW for already processed jobs in the JR + * and notify the available jobs to UA. + * + * @param [in] job_ring The job ring to poll. + * @param [in] limit The maximum number of jobs to notify. + * If set to negative value, all available + * jobs are notified. + * + * @retval >=0 for No of jobs notified to UA. + * @retval -1 for error + */ + +int hw_poll_job_ring(struct sec_job_ring_t *job_ring, int32_t limit); + +/* @brief Poll the HW for already processed jobs in the JR + * and silently discard the available jobs or notify them to UA + * with indicated error code. + + * @param [in,out] job_ring The job ring to poll. + * @param [in] do_notify Can be #TRUE or #FALSE. + * Indicates if descriptors to be discarded + * or notified to UA with given error_code. + * @param [in] error_code The detailed SEC error code. + * @param [out] notified_descs Number of notified descriptors. + * Can be NULL if do_notify is #FALSE + */ +void hw_flush_job_ring(struct sec_job_ring_t *job_ring, + uint32_t do_notify, + uint32_t error_code, uint32_t *notified_descs); + +/* + * @brief Flush job rings of any processed descs. + * The processed descs are silently dropped, + * WITHOUT being notified to UA. + */ +void flush_job_rings(void); + +/* + * @brief Handle desc that generated error in SEC engine. + * Identify the exact type of error and handle the error. + * Depending on the error type, the job ring could be reset. + * All descs that are submitted for processing on this job ring + * are notified to User Application with error status and detailed error code. + + * @param [in] job_ring Job ring + * @param [in] sec_error_code Error code read from job ring's Channel + * Status Register + * @param [out] notified_descs Number of notified descs. Can be NULL if + * do_notify is #FALSE + * @param [out] do_driver_shutdown If set to #TRUE, then UA is returned code + * #SEC_PROCESSING_ERROR + * which is indication that UA must call + * sec_release() after this. + */ +void sec_handle_desc_error(struct sec_job_ring_t *job_ring, + uint32_t sec_error_code, + uint32_t *notified_descs, + uint32_t *do_driver_shutdown); + +/* + * @brief Release the software and hardware resources tied to a job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int shutdown_job_ring(struct sec_job_ring_t *job_ring); + +/* + * @brief Enable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_enable_irqs(struct sec_job_ring_t *job_ring); + +/* + * @brief Disable irqs on associated job ring. + * @param [in] job_ring The job ring + * @retval 0 for success + * @retval -1 for error + */ +int jr_disable_irqs(struct sec_job_ring_t *job_ring); + + /* + * IRJA - Input Ring Jobs Added Register shows + * how many new jobs were added to the Input Ring. + */ +static inline void hw_enqueue_desc_on_job_ring(struct jobring_regs *regs, + int num) +{ + sec_out32(®s->irja, num); +} + +#endif /* _SEC_HW_SPECIFIC_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h new file mode 100644 index 0000000..57e0fa0 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h @@ -0,0 +1,178 @@ +/* + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef _JR_DRIVER_H_ +#define _JR_DRIVER_H_ + +#include "jr_driver_config.h" + +/* The maximum size of a SEC descriptor, in WORDs (32 bits). */ +#define MAX_DESC_SIZE_WORDS 64 + +#define CAAM_TIMEOUT 200000 /* ms */ + +/* Return codes for JR user space driver APIs */ +typedef enum sec_return_code_e { + SEC_SUCCESS = 0, + SEC_INVALID_INPUT_PARAM, + SEC_OUT_OF_MEMORY, + SEC_DESCRIPTOR_IN_FLIGHT, + SEC_LAST_DESCRIPTOR_IN_FLIGHT, + SEC_PROCESSING_ERROR, + SEC_DESC_PROCESSING_ERROR, + SEC_JR_IS_FULL, + SEC_DRIVER_RELEASE_IN_PROGRESS, + SEC_DRIVER_ALREADY_INITIALIZED, + SEC_DRIVER_NOT_INITIALIZED, + SEC_JOB_RING_RESET_IN_PROGRESS, + SEC_RESET_ENGINE_FAILED, + SEC_ENABLE_IRQS_FAILED, + SEC_DISABLE_IRQS_FAILED, + SEC_RETURN_CODE_MAX_VALUE, +} sec_return_code_t; + +/* STRUCTURES AND OTHER TYPEDEFS */ + +/* + * @brief Function called by JR User Space driver to notify every processed + * descriptor. + * + * Callback provided by the User Application. + * Callback is invoked by JR User Space driver for each descriptor processed by + * SEC + * @param [in] status Status word indicating processing result for + * this descriptor. + * @param [in] arg Opaque data passed by User Application + * It is opaque from JR driver's point of view. + * @param [in] job_ring The job ring handle on which the processed + * descriptor word was enqueued + */ +typedef void (*user_callback) (uint32_t *desc, uint32_t status, + void *arg, void *job_ring); + +/* + * Structure encompassing a job descriptor which is to be processed + * by SEC. User should also initialise this structure with the callback + * function pointer which will be called by driver after recieving proccessed + * descriptor from SEC. User data is also passed in this data structure which + * will be sent as an argument to the user callback function. + */ +struct job_descriptor { + uint32_t desc[MAX_DESC_SIZE_WORDS]; + void *arg; + user_callback callback; +}; + +/* + * @brief Initialize the JR User Space driver. + * This function will handle initialization of sec library + * along with registering platform specific callbacks, + * as well as local data initialization. + * Call once during application startup. + * @note Global SEC initialization is done in SEC kernel driver. + * @note The hardware IDs of the initialized Job Rings are opaque to the UA. + * The exact Job Rings used by this library are decided between SEC user + * space driver and SEC kernel driver. A static partitioning of Job Rings is + * assumed, configured in DTS(device tree specification) file. + * @param [in] platform_cb Registering the platform specific + * callbacks with driver + * @retval ::0 for successful execution + * @retval ::-1 failure + */ +int sec_jr_lib_init(void); + +/* + * @brief Initialize the software and hardware resources tied to a job ring. + * @param [in] jr_mode; Model to be used by SEC Driver to receive + * notifications from SEC. Can be either + * SEC_NOTIFICATION_TYPE_IRQ or + * SEC_NOTIFICATION_TYPE_POLL + * @param [in] irq_coalescing_timer This value determines the maximum + * amount of time after processing a + * descriptor before raising an interrupt. + * @param [in] irq_coalescing_count This value determines how many + * descriptors are completed before + * raising an interrupt. + * @param [in] reg_base_addr The job ring base address register + * @param [in] irq_id The job ring interrupt identification number. + * @retval job_ring_handle for successful job ring configuration + * @retval NULL on error + */ +void *init_job_ring(uint8_t jr_mode, + uint16_t irq_coalescing_timer, + uint8_t irq_coalescing_count, + void *reg_base_addr, uint32_t irq_id); + +/* + * @brief Release the resources used by the JR User Space driver. + * Reset and release SEC's job rings indicated by the User Application at + * init_job_ring() and free any memory allocated internally. + * Call once during application tear down. + * @note In case there are any descriptors in-flight (descriptors received by + * JR driver for processing and for which no response was yet provided to UA), + * the descriptors are discarded without any notifications to User Application. + * @retval ::0 is returned for a successful execution + * @retval ::-1 is returned if JR driver release is in progress + */ +int sec_release(void); + +/* + * @brief Submit a descriptor for SEC processing. + * This function creates a "job" which is meant to instruct SEC HW + * to perform the processing on the input buffer. The "job" is enqueued + * in the Job Ring associated. The function will return after the "job" + * enqueue is finished. The function will not wait for SEC to + * start or/and finish the "job" processing. + * After the processing is finished the SEC HW writes the processing result + * to the provided output buffer. + * The Caller must poll JR driver using jr_dequeue() + * to receive notifications of the processing completion + * status. The notifications are received by caller by means of callback + * (see ::user_callback). + * @param [in] job_ring_handle The handle of the job ring on which + * descriptor is to be enqueued + * @param [in] job_descriptor The job descriptor structure of type + * struct job_descriptor. This structure + * should be filled with job descriptor along + * with callback function to be called after + * processing of descriptor and some + * opaque data passed to be passed to the + * callback function + * + * @retval ::0 is returned for successful execution + * @retval ::-1 is returned if there is some enqueue failure + */ +int enq_jr_desc(void *job_ring_handle, struct job_descriptor *jobdescr); + +/* + * @brief Polls for available descriptors processed by SEC on a specific + * Job Ring + * This function polls the SEC Job Rings and delivers processed descriptors + * Each processed descriptor has a user_callback registered. + * This user_callback is invoked for each processed descriptor. + * The polling is stopped when "limit" descriptors are notified or when + * there are no more descriptors to notify. + * @note The dequeue_jr() API cannot be called from within a user_callback + * function + * @param [in] job_ring_handle The Job Ring handle. + * @param [in] limit This value represents the maximum number + * of processed descriptors that can be + * notified API call on this Job Ring. + * Note that fewer descriptors may be notified + * if enough processed descriptors are not + * available. + * If limit has a negative value, then all + * ready descriptors will be notified. + * + * @retval :: >=0 is returned where retval is the total + * Number of descriptors notified + * during this function call. + * @retval :: -1 is returned in case of some error + */ +int dequeue_jr(void *job_ring_handle, int32_t limit); + +#endif /* _JR_DRIVER_H_ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/csu/csu.h b/arm-trusted-firmware/include/drivers/nxp/csu/csu.h new file mode 100644 index 0000000..83f1834 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/csu/csu.h @@ -0,0 +1,42 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef CSU_H +#define CSU_H + +#define CSU_SEC_ACCESS_REG_OFFSET (0x0021CU) +/* Bit mask */ +#define TZASC_BYPASS_MUX_DISABLE (0x4U) + +/* Macros defining access permissions to configure + * the regions controlled by Central Security Unit. + */ +enum csu_cslx_access { + CSU_NS_SUP_R = (0x8U), + CSU_NS_SUP_W = (0x80U), + CSU_NS_SUP_RW = (0x88U), + CSU_NS_USER_R = (0x4U), + CSU_NS_USER_W = (0x40U), + CSU_NS_USER_RW = (0x44U), + CSU_S_SUP_R = (0x2U), + CSU_S_SUP_W = (0x20U), + CSU_S_SUP_RW = (0x22U), + CSU_S_USER_R = (0x1U), + CSU_S_USER_W = (0x10U), + CSU_S_USER_RW = (0x11U), + CSU_ALL_RW = (0xffU), +}; + +struct csu_ns_dev_st { + uintptr_t ind; + uint32_t val; +}; + +void enable_layerscape_ns_access(struct csu_ns_dev_st *csu_ns_dev, + uint32_t num, uintptr_t nxp_csu_addr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h new file mode 100644 index 0000000..cf29b12 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h @@ -0,0 +1,103 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_H +#define DCFG_H + +#include + +#if defined(CONFIG_CHASSIS_2) +#include +#elif defined(CONFIG_CHASSIS_3_2) || defined(CONFIG_CHASSIS_3) +#include +#endif + +#ifdef NXP_GUR_BE +#define gur_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_GUR_LE) +#define gur_in32(a) mmio_read_32((uintptr_t)(a)) +#define gur_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define CCSR GUR register endianness +#endif + +typedef struct { + union { + uint32_t val; + struct { + uint32_t min_ver:4; + uint32_t maj_ver:4; +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint32_t personality:6; + uint32_t rsv1:2; +#elif defined(CONFIG_CHASSIS_2) + uint32_t personality:8; + +#endif +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint32_t dev_id:6; + uint32_t rsv2:2; + uint32_t family:4; +#elif defined(CONFIG_CHASSIS_2) + uint32_t dev_id:12; +#endif + uint32_t mfr_id; + } __packed bf; + struct { + uint32_t maj_min:8; + uint32_t version; /* SoC version without major and minor info */ + } __packed bf_ver; + } __packed svr_reg; + bool sec_enabled; + bool is_populated; +} soc_info_t; + +typedef struct { + bool is_populated; + uint8_t ocram_present; + uint8_t ddrc1_present; +#if defined(CONFIG_CHASSIS_3) || defined(CONFIG_CHASSIS_3_2) + uint8_t ddrc2_present; +#endif +} devdisr5_info_t; + +typedef struct { + uint32_t porsr1; + uintptr_t g_nxp_dcfg_addr; + unsigned long nxp_sysclk_freq; + unsigned long nxp_ddrclk_freq; + unsigned int nxp_plat_clk_divider; +} dcfg_init_info_t; + + +struct sysinfo { + unsigned long freq_platform; + unsigned long freq_ddr_pll0; + unsigned long freq_ddr_pll1; +}; + +int get_clocks(struct sysinfo *sys); + +/* Read the PORSR1 register */ +uint32_t read_reg_porsr1(void); + +/******************************************************************************* + * Returns true if secur eboot is enabled on board + * mode = 0 (development mode - sb_en = 1) + * mode = 1 (production mode - ITS = 1) + ******************************************************************************/ +bool check_boot_mode_secure(uint32_t *mode); + +const soc_info_t *get_soc_info(); +const devdisr5_info_t *get_devdisr5_info(); + +void dcfg_init(dcfg_init_info_t *dcfg_init_data); +bool is_sec_enabled(void); + +void error_handler(int error_code); +#endif /* DCFG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h new file mode 100644 index 0000000..882ba5a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h @@ -0,0 +1,85 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_LSCH2_H +#define DCFG_LSCH2_H + +/* dcfg block register offsets and bitfields */ +#define DCFG_PORSR1_OFFSET 0x00 +#define DCFG_DEVDISR1_OFFSET 0x070 +#define DCFG_DEVDISR2_OFFSET 0x074 +#define DCFG_DEVDISR3_OFFSET 0x078 +#define DCFG_DEVDISR4_OFFSET 0x07C +#define DCFG_DEVDISR5_OFFSET 0x080 +#define DCFG_COREDISR_OFFSET 0x094 +#define RCWSR0_OFFSET 0x100 +#define RCWSR5_OFFSET 0x118 +#define DCFG_BOOTLOCPTRL_OFFSET 0x400 +#define DCFG_BOOTLOCPTRH_OFFSET 0x404 +#define DCFG_COREDISABLEDSR_OFFSET 0x990 +#define DCFG_SCRATCH4_OFFSET 0x20C +#define DCFG_SVR_OFFSET 0x0A4 +#define DCFG_BRR_OFFSET 0x0E4 + +#define DCFG_RSTCR_OFFSET 0x0B0 +#define RSTCR_RESET_REQ 0x2 + +#define DCFG_RSTRQSR1_OFFSET 0x0C8 +#define DCFG_RSTRQMR1_OFFSET 0x0C0 + +/* PORSR1 bit mask */ +#define PORSR1_RCW_MASK 0xff800000 +#define PORSR1_RCW_SHIFT 23 + +/* DCFG DCSR Macros */ +#define DCFG_DCSR_PORCR1_OFFSET 0x0 + +#define SVR_MFR_ID_MASK 0xF0000000 +#define SVR_MFR_ID_SHIFT 28 +#define SVR_DEV_ID_MASK 0xFFF0000 +#define SVR_DEV_ID_SHIFT 16 +#define SVR_PERSONALITY_MASK 0xFF00 +#define SVR_PERSONALITY_SHIFT 8 +#define SVR_SEC_MASK 0x100 +#define SVR_SEC_SHIFT 8 +#define SVR_MAJ_VER_MASK 0xF0 +#define SVR_MAJ_VER_SHIFT 4 +#define SVR_MIN_VER_MASK 0xF +#define SVR_MINOR_VER_0 0x00 +#define SVR_MINOR_VER_1 0x01 + +#define DISR5_DDRC1_MASK 0x1 +#define DISR5_OCRAM_MASK 0x40 + +/* DCFG regsiters bit masks */ +#define RCWSR0_SYS_PLL_RAT_SHIFT 25 +#define RCWSR0_SYS_PLL_RAT_MASK 0x1f +#define RCWSR0_MEM_PLL_RAT_SHIFT 16 +#define RCWSR0_MEM_PLL_RAT_MASK 0x3f +#define RCWSR0_MEM2_PLL_RAT_SHIFT 18 +#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f + +#define RCWSR_SB_EN_OFFSET RCWSR5_OFFSET +#define RCWSR_SBEN_MASK 0x1 +#define RCWSR_SBEN_SHIFT 21 + +/* RCW SRC NAND */ +#define RCW_SRC_NAND_MASK (0x100) +#define RCW_SRC_NAND_VAL (0x100) +#define NAND_RESERVED_MASK (0xFC) +#define NAND_RESERVED_1 (0x0) +#define NAND_RESERVED_2 (0x80) + +/* RCW SRC NOR */ +#define RCW_SRC_NOR_MASK (0x1F0) +#define NOR_8B_VAL (0x10) +#define NOR_16B_VAL (0x20) +#define SD_VAL (0x40) +#define QSPI_VAL1 (0x44) +#define QSPI_VAL2 (0x45) + +#endif /* DCFG_LSCH2_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h new file mode 100644 index 0000000..cde86fe --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h @@ -0,0 +1,80 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DCFG_LSCH3_H +#define DCFG_LSCH3_H + +/* dcfg block register offsets and bitfields */ +#define DCFG_PORSR1_OFFSET 0x00 + +#define DCFG_DEVDISR1_OFFSET 0x70 +#define DCFG_DEVDISR1_SEC (1 << 22) + +#define DCFG_DEVDISR2_OFFSET 0x74 + +#define DCFG_DEVDISR3_OFFSET 0x78 +#define DCFG_DEVDISR3_QBMAIN (1 << 12) + +#define DCFG_DEVDISR4_OFFSET 0x7C +#define DCFG_DEVDISR4_SPI_QSPI (1 << 4 | 1 << 5) + +#define DCFG_DEVDISR5_OFFSET 0x80 +#define DISR5_DDRC1_MASK 0x1 +#define DISR5_DDRC2_MASK 0x2 +#define DISR5_OCRAM_MASK 0x1000 +#define DEVDISR5_MASK_ALL_MEM 0x00001003 +#define DEVDISR5_MASK_DDR 0x00000003 +#define DEVDISR5_MASK_DBG 0x00000400 + +#define DCFG_DEVDISR6_OFFSET 0x84 +//#define DEVDISR6_MASK 0x00000001 + +#define DCFG_COREDISR_OFFSET 0x94 + +#define DCFG_SVR_OFFSET 0x0A4 +#define SVR_MFR_ID_MASK 0xF0000000 +#define SVR_MFR_ID_SHIFT 28 +#define SVR_FAMILY_MASK 0xF000000 +#define SVR_FAMILY_SHIFT 24 +#define SVR_DEV_ID_MASK 0x3F0000 +#define SVR_DEV_ID_SHIFT 16 +#define SVR_PERSONALITY_MASK 0x3E00 +#define SVR_PERSONALITY_SHIFT 9 +#define SVR_SEC_MASK 0x100 +#define SVR_SEC_SHIFT 8 +#define SVR_MAJ_VER_MASK 0xF0 +#define SVR_MAJ_VER_SHIFT 4 +#define SVR_MIN_VER_MASK 0xF + +#define RCWSR0_OFFSET 0x100 +#define RCWSR0_SYS_PLL_RAT_SHIFT 2 +#define RCWSR0_SYS_PLL_RAT_MASK 0x1f +#define RCWSR0_MEM_PLL_RAT_SHIFT 10 +#define RCWSR0_MEM_PLL_RAT_MASK 0x3f +#define RCWSR0_MEM2_PLL_RAT_SHIFT 18 +#define RCWSR0_MEM2_PLL_RAT_MASK 0x3f + +#define RCWSR5_OFFSET 0x110 +#define RCWSR9_OFFSET 0x120 +#define RCWSR_SB_EN_OFFSET RCWSR9_OFFSET +#define RCWSR_SBEN_MASK 0x1 +#define RCWSR_SBEN_SHIFT 10 + +#define RCW_SR27_OFFSET 0x168 +/* DCFG register to dump error code */ +#define DCFG_SCRATCH4_OFFSET 0x20C +#define DCFG_SCRATCHRW5_OFFSET 0x210 +#define DCFG_SCRATCHRW6_OFFSET 0x214 +#define DCFG_SCRATCHRW7_OFFSET 0x218 +#define DCFG_BOOTLOCPTRL_OFFSET 0x400 +#define DCFG_BOOTLOCPTRH_OFFSET 0x404 +#define DCFG_COREDISABLEDSR_OFFSET 0x990 + +/* Reset module bit field */ +#define RSTCR_RESET_REQ 0x2 + +#endif /* DCFG_LSCH3_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h b/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h new file mode 100644 index 0000000..8067de1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h @@ -0,0 +1,65 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SCFG_H +#define SCFG_H + +#ifdef CONFIG_CHASSIS_2 + +/* SCFG register offsets */ +#define SCFG_CORE0_SFT_RST_OFFSET 0x0130 +#define SCFG_SNPCNFGCR_OFFSET 0x01A4 +#define SCFG_CORESRENCR_OFFSET 0x0204 +#define SCFG_RVBAR0_0_OFFSET 0x0220 +#define SCFG_RVBAR0_1_OFFSET 0x0224 +#define SCFG_COREBCR_OFFSET 0x0680 +#define SCFG_RETREQCR_OFFSET 0x0424 + +#define SCFG_COREPMCR_OFFSET 0x042C +#define COREPMCR_WFIL2 0x1 + +#define SCFG_GIC400_ADDR_ALIGN_OFFSET 0x0188 +#define SCFG_BOOTLOCPTRH_OFFSET 0x0600 +#define SCFG_BOOTLOCPTRL_OFFSET 0x0604 +#define SCFG_SCRATCHRW2_OFFSET 0x0608 +#define SCFG_SCRATCHRW3_OFFSET 0x060C + +/* SCFG bit fields */ +#define SCFG_SNPCNFGCR_SECRDSNP 0x80000000 +#define SCFG_SNPCNFGCR_SECWRSNP 0x40000000 + +/* GIC Address Align Register */ +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_MASK 0x80000000 +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_EN 0x80000000 +#define SCFG_GIC400_ADDR_ALIGN_4KMODE_DIS 0x0 + +#endif /* CONFIG_CHASSIS_2 */ + +#ifndef __ASSEMBLER__ +#include +#include + +#ifdef NXP_SCFG_BE +#define scfg_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v) +#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v) +#define scfg_clrsetbits32(a, clear, set) \ + mmio_clrsetbits_32((uintptr_t)(a), clear, set) +#elif defined(NXP_SCFG_LE) +#define scfg_in32(a) mmio_read_32((uintptr_t)(a)) +#define scfg_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#define scfg_setbits32(a, v) mmio_setbits_32((uintptr_t)(a), v) +#define scfg_clrbits32(a, v) mmio_clrbits_32((uintptr_t)(a), v) +#define scfg_clrsetbits32(a, clear, set) \ + mmio_clrsetbits_32((uintptr_t)(a), clear, set) +#else +#error Please define CCSR SCFG register endianness +#endif +#endif /* __ASSEMBLER__ */ + +#endif /* SCFG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h new file mode 100644 index 0000000..0ef2870 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h @@ -0,0 +1,151 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_H +#define DDR_H + +#include "ddr_io.h" +#include "dimm.h" +#include "immap.h" + +#ifndef DDRC_NUM_CS +#define DDRC_NUM_CS 4 +#endif + +/* + * This is irrespective of what is the number of DDR controller, + * number of DIMM used. This is set to maximum + * Max controllers = 2 + * Max num of DIMM per controlle = 2 + * MAX NUM CS = 4 + * Not to be changed. + */ +#define MAX_DDRC_NUM 2 +#define MAX_DIMM_NUM 2 +#define MAX_CS_NUM 4 + +#include "opts.h" +#include "regs.h" +#include "utility.h" + +#ifdef DDR_DEBUG +#define debug(...) INFO(__VA_ARGS__) +#else +#define debug(...) VERBOSE(__VA_ARGS__) +#endif + +#ifndef DDRC_NUM_DIMM +#define DDRC_NUM_DIMM 1 +#endif + +#define CONFIG_CS_PER_SLOT \ + (DDRC_NUM_CS / DDRC_NUM_DIMM) + +/* Record of register values computed */ +struct ddr_cfg_regs { + struct { + unsigned int bnds; + unsigned int config; + unsigned int config_2; + } cs[MAX_CS_NUM]; + unsigned int dec[10]; + unsigned int timing_cfg[10]; + unsigned int sdram_cfg[3]; + unsigned int sdram_mode[16]; + unsigned int md_cntl; + unsigned int interval; + unsigned int data_init; + unsigned int clk_cntl; + unsigned int init_addr; + unsigned int init_ext_addr; + unsigned int zq_cntl; + unsigned int wrlvl_cntl[3]; + unsigned int ddr_sr_cntr; + unsigned int sdram_rcw[6]; + unsigned int dq_map[4]; + unsigned int eor; + unsigned int cdr[2]; + unsigned int err_disable; + unsigned int err_int_en; + unsigned int tx_cfg[4]; + unsigned int debug[64]; +}; + +struct ddr_conf { + int dimm_in_use[MAX_DIMM_NUM]; + int cs_in_use; /* bitmask, bit 0 for cs0, bit 1 for cs1, etc. */ + int cs_on_dimm[MAX_DIMM_NUM]; /* bitmask */ + unsigned long long cs_base_addr[MAX_CS_NUM]; + unsigned long long cs_size[MAX_CS_NUM]; + unsigned long long base_addr; + unsigned long long total_mem; +}; + +struct ddr_info { + unsigned long clk; + unsigned long long mem_base; + unsigned int num_ctlrs; + unsigned int dimm_on_ctlr; + struct dimm_params dimm; + struct memctl_opt opt; + struct ddr_conf conf; + struct ddr_cfg_regs ddr_reg; + struct ccsr_ddr *ddr[MAX_DDRC_NUM]; + uint16_t *phy[MAX_DDRC_NUM]; + int *spd_addr; + unsigned int ip_rev; + uintptr_t phy_gen2_fw_img_buf; + void *img_loadr; + int warm_boot_flag; +}; + +struct rc_timing { + unsigned int speed_bin; + unsigned int clk_adj; + unsigned int wrlvl; +}; + +struct board_timing { + unsigned int rc; + struct rc_timing const *p; + unsigned int add1; + unsigned int add2; +}; + +enum warm_boot { + DDR_COLD_BOOT = 0, + DDR_WARM_BOOT = 1, + DDR_WRM_BOOT_NT_SUPPORTED = -1, +}; + +int disable_unused_ddrc(struct ddr_info *priv, int mask, + uintptr_t nxp_ccn_hn_f0_addr); +int ddr_board_options(struct ddr_info *priv); +int compute_ddrc(const unsigned long clk, + const struct memctl_opt *popts, + const struct ddr_conf *conf, + struct ddr_cfg_regs *ddr, + const struct dimm_params *dimm_params, + const unsigned int ip_rev); +int compute_ddr_phy(struct ddr_info *priv); +int ddrc_set_regs(const unsigned long clk, + const struct ddr_cfg_regs *regs, + const struct ccsr_ddr *ddr, + int twopass); +int cal_board_params(struct ddr_info *priv, + const struct board_timing *dimm, + int len); +/* return bit mask of used DIMM(s) */ +int ddr_get_ddr_params(struct dimm_params *pdimm, struct ddr_conf *conf); +long long dram_init(struct ddr_info *priv +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) + , uintptr_t nxp_ccn_hn_f0_addr +#endif + ); +long long board_static_ddr(struct ddr_info *info); + +#endif /* DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h new file mode 100644 index 0000000..fbd7e97 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h @@ -0,0 +1,38 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IO_H +#define DDR_IO_H + +#include + +#include + +#define min(a, b) (((a) > (b)) ? (b) : (a)) + +#define max(a, b) (((a) > (b)) ? (a) : (b)) + +/* macro for memory barrier */ +#define mb() asm volatile("dsb sy" : : : "memory") + +#ifdef NXP_DDR_BE +#define ddr_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a),\ + bswap32(v)) +#elif defined(NXP_DDR_LE) +#define ddr_in32(a) mmio_read_32((uintptr_t)(a)) +#define ddr_out32(a, v) mmio_write_32((uintptr_t)(a), v) +#else +#error Please define CCSR DDR register endianness +#endif + +#define ddr_setbits32(a, v) ddr_out32((a), ddr_in32(a) | (v)) +#define ddr_clrbits32(a, v) ddr_out32((a), ddr_in32(a) & ~(v)) +#define ddr_clrsetbits32(a, c, s) ddr_out32((a), (ddr_in32(a) & ~(c)) \ + | (s)) + +#endif /* DDR_IO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h b/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h new file mode 100644 index 0000000..fcae179 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h @@ -0,0 +1,330 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DIMM_H +#define DIMM_H + +#define SPD_MEMTYPE_DDR4 0x0C + +#define DDR4_SPD_MODULETYPE_MASK 0x0f +#define DDR4_SPD_MODULETYPE_EXT 0x00 +#define DDR4_SPD_RDIMM 0x01 +#define DDR4_SPD_UDIMM 0x02 +#define DDR4_SPD_SO_DIMM 0x03 +#define DDR4_SPD_LRDIMM 0x04 +#define DDR4_SPD_MINI_RDIMM 0x05 +#define DDR4_SPD_MINI_UDIMM 0x06 +#define DDR4_SPD_72B_SO_RDIMM 0x08 +#define DDR4_SPD_72B_SO_UDIMM 0x09 +#define DDR4_SPD_16B_SO_DIMM 0x0c +#define DDR4_SPD_32B_SO_DIMM 0x0d + +#define SPD_SPA0_ADDRESS 0x36 +#define SPD_SPA1_ADDRESS 0x37 + +#define spd_to_ps(mtb, ftb) \ + ((mtb) * pdimm->mtb_ps + ((ftb) * pdimm->ftb_10th_ps) / 10) + +#ifdef DDR_DEBUG +#define dump_spd(spd, len) { \ + register int i; \ + register unsigned char *buf = (void *)(spd); \ + \ + for (i = 0; i < (len); i++) { \ + print_uint(i); \ + puts("\t: 0x"); \ + print_hex(buf[i]); \ + puts("\n"); \ + } \ +} +#else +#define dump_spd(spd, len) {} +#endif + +/* From JEEC Standard No. 21-C release 23A */ +struct ddr4_spd { + /* General Section: Bytes 0-127 */ + unsigned char info_size_crc; /* 0 # bytes */ + unsigned char spd_rev; /* 1 Total # bytes of SPD */ + unsigned char mem_type; /* 2 Key Byte / mem type */ + unsigned char module_type; /* 3 Key Byte / Module Type */ + unsigned char density_banks; /* 4 Density and Banks */ + unsigned char addressing; /* 5 Addressing */ + unsigned char package_type; /* 6 Package type */ + unsigned char opt_feature; /* 7 Optional features */ + unsigned char thermal_ref; /* 8 Thermal and refresh */ + unsigned char oth_opt_features; /* 9 Other optional features */ + unsigned char res_10; /* 10 Reserved */ + unsigned char module_vdd; /* 11 Module nominal voltage */ + unsigned char organization; /* 12 Module Organization */ + unsigned char bus_width; /* 13 Module Memory Bus Width */ + unsigned char therm_sensor; /* 14 Module Thermal Sensor */ + unsigned char ext_type; /* 15 Extended module type */ + unsigned char res_16; + unsigned char timebases; /* 17 MTb and FTB */ + unsigned char tck_min; /* 18 tCKAVGmin */ + unsigned char tck_max; /* 19 TCKAVGmax */ + unsigned char caslat_b1; /* 20 CAS latencies, 1st byte */ + unsigned char caslat_b2; /* 21 CAS latencies, 2nd byte */ + unsigned char caslat_b3; /* 22 CAS latencies, 3rd byte */ + unsigned char caslat_b4; /* 23 CAS latencies, 4th byte */ + unsigned char taa_min; /* 24 Min CAS Latency Time */ + unsigned char trcd_min; /* 25 Min RAS# to CAS# Delay Time */ + unsigned char trp_min; /* 26 Min Row Precharge Delay Time */ + unsigned char tras_trc_ext; /* 27 Upper Nibbles for tRAS and tRC */ + unsigned char tras_min_lsb; /* 28 tRASmin, lsb */ + unsigned char trc_min_lsb; /* 29 tRCmin, lsb */ + unsigned char trfc1_min_lsb; /* 30 Min Refresh Recovery Delay Time */ + unsigned char trfc1_min_msb; /* 31 Min Refresh Recovery Delay Time */ + unsigned char trfc2_min_lsb; /* 32 Min Refresh Recovery Delay Time */ + unsigned char trfc2_min_msb; /* 33 Min Refresh Recovery Delay Time */ + unsigned char trfc4_min_lsb; /* 34 Min Refresh Recovery Delay Time */ + unsigned char trfc4_min_msb; /* 35 Min Refresh Recovery Delay Time */ + unsigned char tfaw_msb; /* 36 Upper Nibble for tFAW */ + unsigned char tfaw_min; /* 37 tFAW, lsb */ + unsigned char trrds_min; /* 38 tRRD_Smin, MTB */ + unsigned char trrdl_min; /* 39 tRRD_Lmin, MTB */ + unsigned char tccdl_min; /* 40 tCCS_Lmin, MTB */ + unsigned char res_41[60-41]; /* 41 Rserved */ + unsigned char mapping[78-60]; /* 60~77 Connector to SDRAM bit map */ + unsigned char res_78[117-78]; /* 78~116, Reserved */ + signed char fine_tccdl_min; /* 117 Fine offset for tCCD_Lmin */ + signed char fine_trrdl_min; /* 118 Fine offset for tRRD_Lmin */ + signed char fine_trrds_min; /* 119 Fine offset for tRRD_Smin */ + signed char fine_trc_min; /* 120 Fine offset for tRCmin */ + signed char fine_trp_min; /* 121 Fine offset for tRPmin */ + signed char fine_trcd_min; /* 122 Fine offset for tRCDmin */ + signed char fine_taa_min; /* 123 Fine offset for tAAmin */ + signed char fine_tck_max; /* 124 Fine offset for tCKAVGmax */ + signed char fine_tck_min; /* 125 Fine offset for tCKAVGmin */ + /* CRC: Bytes 126-127 */ + unsigned char crc[2]; /* 126-127 SPD CRC */ + + /* Module-Specific Section: Bytes 128-255 */ + union { + struct { + /* 128 (Unbuffered) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Unbuffered) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Unbuffered) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 (Unbuffered) Address Mapping from + * Edge Connector to DRAM + */ + unsigned char addr_mapping; + /* 132~253 (Unbuffered) Reserved */ + unsigned char res_132[254-132]; + /* 254~255 CRC */ + unsigned char crc[2]; + } unbuffered; + struct { + /* 128 (Registered) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Registered) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Registered) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 DIMM Module Attributes */ + unsigned char modu_attr; + /* 132 RDIMM Thermal Heat Spreader Solution */ + unsigned char thermal; + /* 133 Register Manufacturer ID Code, LSB */ + unsigned char reg_id_lo; + /* 134 Register Manufacturer ID Code, MSB */ + unsigned char reg_id_hi; + /* 135 Register Revision Number */ + unsigned char reg_rev; + /* 136 Address mapping from register to DRAM */ + unsigned char reg_map; + unsigned char ca_stren; + unsigned char clk_stren; + /* 139~253 Reserved */ + unsigned char res_139[254-139]; + /* 254~255 CRC */ + unsigned char crc[2]; + } registered; + struct { + /* 128 (Loadreduced) Module Nominal Height */ + unsigned char mod_height; + /* 129 (Loadreduced) Module Maximum Thickness */ + unsigned char mod_thickness; + /* 130 (Loadreduced) Reference Raw Card Used */ + unsigned char ref_raw_card; + /* 131 DIMM Module Attributes */ + unsigned char modu_attr; + /* 132 RDIMM Thermal Heat Spreader Solution */ + unsigned char thermal; + /* 133 Register Manufacturer ID Code, LSB */ + unsigned char reg_id_lo; + /* 134 Register Manufacturer ID Code, MSB */ + unsigned char reg_id_hi; + /* 135 Register Revision Number */ + unsigned char reg_rev; + /* 136 Address mapping from register to DRAM */ + unsigned char reg_map; + /* 137 Register Output Drive Strength for CMD/Add*/ + unsigned char reg_drv; + /* 138 Register Output Drive Strength for CK */ + unsigned char reg_drv_ck; + /* 139 Data Buffer Revision Number */ + unsigned char data_buf_rev; + /* 140 DRAM VrefDQ for Package Rank 0 */ + unsigned char vrefqe_r0; + /* 141 DRAM VrefDQ for Package Rank 1 */ + unsigned char vrefqe_r1; + /* 142 DRAM VrefDQ for Package Rank 2 */ + unsigned char vrefqe_r2; + /* 143 DRAM VrefDQ for Package Rank 3 */ + unsigned char vrefqe_r3; + /* 144 Data Buffer VrefDQ for DRAM Interface */ + unsigned char data_intf; + /* + * 145 Data Buffer MDQ Drive Strength and RTT + * for data rate <= 1866 + */ + unsigned char data_drv_1866; + /* + * 146 Data Buffer MDQ Drive Strength and RTT + * for 1866 < data rate <= 2400 + */ + unsigned char data_drv_2400; + /* + * 147 Data Buffer MDQ Drive Strength and RTT + * for 2400 < data rate <= 3200 + */ + unsigned char data_drv_3200; + /* 148 DRAM Drive Strength */ + unsigned char dram_drv; + /* + * 149 DRAM ODT (RTT_WR, RTT_NOM) + * for data rate <= 1866 + */ + unsigned char dram_odt_1866; + /* + * 150 DRAM ODT (RTT_WR, RTT_NOM) + * for 1866 < data rate <= 2400 + */ + unsigned char dram_odt_2400; + /* + * 151 DRAM ODT (RTT_WR, RTT_NOM) + * for 2400 < data rate <= 3200 + */ + unsigned char dram_odt_3200; + /* + * 152 DRAM ODT (RTT_PARK) + * for data rate <= 1866 + */ + unsigned char dram_odt_park_1866; + /* + * 153 DRAM ODT (RTT_PARK) + * for 1866 < data rate <= 2400 + */ + unsigned char dram_odt_park_2400; + /* + * 154 DRAM ODT (RTT_PARK) + * for 2400 < data rate <= 3200 + */ + unsigned char dram_odt_park_3200; + unsigned char res_155[254-155]; /* Reserved */ + /* 254~255 CRC */ + unsigned char crc[2]; + } loadreduced; + unsigned char uc[128]; /* 128-255 Module-Specific Section */ + } mod_section; + + unsigned char res_256[320-256]; /* 256~319 Reserved */ + + /* Module supplier's data: Byte 320~383 */ + unsigned char mmid_lsb; /* 320 Module MfgID Code LSB */ + unsigned char mmid_msb; /* 321 Module MfgID Code MSB */ + unsigned char mloc; /* 322 Mfg Location */ + unsigned char mdate[2]; /* 323~324 Mfg Date */ + unsigned char sernum[4]; /* 325~328 Module Serial Number */ + unsigned char mpart[20]; /* 329~348 Mfg's Module Part Number */ + unsigned char mrev; /* 349 Module Revision Code */ + unsigned char dmid_lsb; /* 350 DRAM MfgID Code LSB */ + unsigned char dmid_msb; /* 351 DRAM MfgID Code MSB */ + unsigned char stepping; /* 352 DRAM stepping */ + unsigned char msd[29]; /* 353~381 Mfg's Specific Data */ + unsigned char res_382[2]; /* 382~383 Reserved */ +}; + +/* Parameters for a DDR dimm computed from the SPD */ +struct dimm_params { + /* DIMM organization parameters */ + char mpart[19]; /* guaranteed null terminated */ + + unsigned int n_ranks; + unsigned int die_density; + unsigned long long rank_density; + unsigned long long capacity; + unsigned int primary_sdram_width; + unsigned int ec_sdram_width; + unsigned int rdimm; + unsigned int package_3ds; /* number of dies in 3DS */ + unsigned int device_width; /* x4, x8, x16 components */ + unsigned int rc; + + /* SDRAM device parameters */ + unsigned int n_row_addr; + unsigned int n_col_addr; + unsigned int edc_config; /* 0 = none, 1 = parity, 2 = ECC */ + unsigned int bank_addr_bits; + unsigned int bank_group_bits; + unsigned int burst_lengths_bitmask; /* BL=4 bit 2, BL=8 = bit 3 */ + + /* mirrored DIMMs */ + unsigned int mirrored_dimm; /* only for ddr3 */ + + /* DIMM timing parameters */ + + int mtb_ps; /* medium timebase ps */ + int ftb_10th_ps; /* fine timebase, in 1/10 ps */ + int taa_ps; /* minimum CAS latency time */ + int tfaw_ps; /* four active window delay */ + + /* + * SDRAM clock periods + * The range for these are 1000-10000 so a short should be sufficient + */ + int tckmin_x_ps; + int tckmax_ps; + + /* SPD-defined CAS latencies */ + unsigned int caslat_x; + + /* basic timing parameters */ + int trcd_ps; + int trp_ps; + int tras_ps; + + int trfc1_ps; + int trfc2_ps; + int trfc4_ps; + int trrds_ps; + int trrdl_ps; + int tccdl_ps; + int trfc_slr_ps; + + int trc_ps; /* maximum = 254 ns + .75 ns = 254750 ps */ + int twr_ps; /* 15ns for all speed bins */ + + unsigned int refresh_rate_ps; + unsigned int extended_op_srt; + + /* RDIMM */ + unsigned char rcw[16]; /* Register Control Word 0-15 */ + unsigned int dq_mapping[18]; + unsigned int dq_mapping_ors; +}; + +int read_spd(unsigned char chip, void *buf, int len); +int crc16(unsigned char *ptr, int count); +int cal_dimm_params(const struct ddr4_spd *spd, struct dimm_params *pdimm); + +#endif /* DIMM_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h b/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h new file mode 100644 index 0000000..31db552 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h @@ -0,0 +1,173 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef FSL_MMDC_H +#define FSL_MMDC_H + +/* PHY Write Leveling Configuration and Error Status Register (MPWLGCR) */ +#define MPWLGCR_HW_WL_EN (1 << 0) + +/* PHY Pre-defined Compare and CA delay-line Configuration (MPPDCMPR2) */ +#define MPPDCMPR2_MPR_COMPARE_EN (1 << 0) + + +/* MMDC PHY Read DQS gating control register 0 (MPDGCTRL0) */ +#define AUTO_RD_DQS_GATING_CALIBRATION_EN (1 << 28) + +/* MMDC PHY Read Delay HW Calibration Control Register (MPRDDLHWCTL) */ +#define MPRDDLHWCTL_AUTO_RD_CALIBRATION_EN (1 << 4) + +/* MMDC Core Power Saving Control and Status Register (MMDC_MAPSR) */ +#define MMDC_MAPSR_PWR_SAV_CTRL_STAT 0x00001067 + +/* MMDC Core Refresh Control Register (MMDC_MDREF) */ +#define MDREF_START_REFRESH (1 << 0) + +/* MMDC Core Special Command Register (MDSCR) */ +#define CMD_ADDR_MSB_MR_OP(x) (x << 24) +#define CMD_ADDR_LSB_MR_ADDR(x) (x << 16) +#define MDSCR_DISABLE_CFG_REQ (0 << 15) +#define MDSCR_ENABLE_CON_REQ (1 << 15) +#define MDSCR_CON_ACK (1 << 14) +#define MDSCR_WL_EN (1 << 9) +#define CMD_NORMAL (0 << 4) +#define CMD_PRECHARGE (1 << 4) +#define CMD_AUTO_REFRESH (2 << 4) +#define CMD_LOAD_MODE_REG (3 << 4) +#define CMD_ZQ_CALIBRATION (4 << 4) +#define CMD_PRECHARGE_BANK_OPEN (5 << 4) +#define CMD_MRR (6 << 4) +#define CMD_BANK_ADDR_0 0x0 +#define CMD_BANK_ADDR_1 0x1 +#define CMD_BANK_ADDR_2 0x2 +#define CMD_BANK_ADDR_3 0x3 +#define CMD_BANK_ADDR_4 0x4 +#define CMD_BANK_ADDR_5 0x5 +#define CMD_BANK_ADDR_6 0x6 +#define CMD_BANK_ADDR_7 0x7 + +/* MMDC Core Control Register (MDCTL) */ +#define MDCTL_SDE0 (U(1) << 31) +#define MDCTL_SDE1 (1 << 30) + +/* MMDC PHY ZQ HW control register (MMDC_MPZQHWCTRL) */ +#define MPZQHWCTRL_ZQ_HW_FORCE (1 << 16) + +/* MMDC PHY Measure Unit Register (MMDC_MPMUR0) */ +#define MMDC_MPMUR0_FRC_MSR (1 << 11) + +/* MMDC PHY Read delay-lines Configuration Register (MMDC_MPRDDLCTL) */ +/* default 64 for a quarter cycle delay */ +#define MMDC_MPRDDLCTL_DEFAULT_DELAY 0x40404040 + +/* MMDC Registers */ +struct mmdc_regs { + unsigned int mdctl; + unsigned int mdpdc; + unsigned int mdotc; + unsigned int mdcfg0; + unsigned int mdcfg1; + unsigned int mdcfg2; + unsigned int mdmisc; + unsigned int mdscr; + unsigned int mdref; + unsigned int res1[2]; + unsigned int mdrwd; + unsigned int mdor; + unsigned int mdmrr; + unsigned int mdcfg3lp; + unsigned int mdmr4; + unsigned int mdasp; + unsigned int res2[239]; + unsigned int maarcr; + unsigned int mapsr; + unsigned int maexidr0; + unsigned int maexidr1; + unsigned int madpcr0; + unsigned int madpcr1; + unsigned int madpsr0; + unsigned int madpsr1; + unsigned int madpsr2; + unsigned int madpsr3; + unsigned int madpsr4; + unsigned int madpsr5; + unsigned int masbs0; + unsigned int masbs1; + unsigned int res3[2]; + unsigned int magenp; + unsigned int res4[239]; + unsigned int mpzqhwctrl; + unsigned int mpzqswctrl; + unsigned int mpwlgcr; + unsigned int mpwldectrl0; + unsigned int mpwldectrl1; + unsigned int mpwldlst; + unsigned int mpodtctrl; + unsigned int mprddqby0dl; + unsigned int mprddqby1dl; + unsigned int mprddqby2dl; + unsigned int mprddqby3dl; + unsigned int mpwrdqby0dl; + unsigned int mpwrdqby1dl; + unsigned int mpwrdqby2dl; + unsigned int mpwrdqby3dl; + unsigned int mpdgctrl0; + unsigned int mpdgctrl1; + unsigned int mpdgdlst0; + unsigned int mprddlctl; + unsigned int mprddlst; + unsigned int mpwrdlctl; + unsigned int mpwrdlst; + unsigned int mpsdctrl; + unsigned int mpzqlp2ctl; + unsigned int mprddlhwctl; + unsigned int mpwrdlhwctl; + unsigned int mprddlhwst0; + unsigned int mprddlhwst1; + unsigned int mpwrdlhwst0; + unsigned int mpwrdlhwst1; + unsigned int mpwlhwerr; + unsigned int mpdghwst0; + unsigned int mpdghwst1; + unsigned int mpdghwst2; + unsigned int mpdghwst3; + unsigned int mppdcmpr1; + unsigned int mppdcmpr2; + unsigned int mpswdar0; + unsigned int mpswdrdr0; + unsigned int mpswdrdr1; + unsigned int mpswdrdr2; + unsigned int mpswdrdr3; + unsigned int mpswdrdr4; + unsigned int mpswdrdr5; + unsigned int mpswdrdr6; + unsigned int mpswdrdr7; + unsigned int mpmur0; + unsigned int mpwrcadl; + unsigned int mpdccr; +}; + +struct fsl_mmdc_info { + unsigned int mdctl; + unsigned int mdpdc; + unsigned int mdotc; + unsigned int mdcfg0; + unsigned int mdcfg1; + unsigned int mdcfg2; + unsigned int mdmisc; + unsigned int mdref; + unsigned int mdrwd; + unsigned int mdor; + unsigned int mdasp; + unsigned int mpodtctrl; + unsigned int mpzqhwctrl; + unsigned int mprddlctl; +}; + +void mmdc_init(const struct fsl_mmdc_info *priv, uintptr_t nxp_ddr_addr); + +#endif /* FSL_MMDC_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h b/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h new file mode 100644 index 0000000..83b4de6 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/immap.h @@ -0,0 +1,125 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_IMMAP_H +#define DDR_IMMAP_H + +#define DDR_DBUS_64 0 +#define DDR_DBUS_32 1 +#define DDR_DBUS_16 2 + +/* + * DDRC register file for DDRC 5.0 and above + */ +struct ccsr_ddr { + struct { + unsigned int a; /* 0x0, 0x8, 0x10, 0x18 */ + unsigned int res; /* 0x4, 0xc, 0x14, 0x1c */ + } bnds[4]; + unsigned char res_20[0x40 - 0x20]; + unsigned int dec[10]; /* 0x40 */ + unsigned char res_68[0x80 - 0x68]; + unsigned int csn_cfg[4]; /* 0x80, 0x84, 0x88, 0x8c */ + unsigned char res_90[48]; + unsigned int csn_cfg_2[4]; /* 0xc0, 0xc4, 0xc8, 0xcc */ + unsigned char res_d0[48]; + unsigned int timing_cfg_3; /* SDRAM Timing Configuration 3 */ + unsigned int timing_cfg_0; /* SDRAM Timing Configuration 0 */ + unsigned int timing_cfg_1; /* SDRAM Timing Configuration 1 */ + unsigned int timing_cfg_2; /* SDRAM Timing Configuration 2 */ + unsigned int sdram_cfg; /* SDRAM Control Configuration */ + unsigned int sdram_cfg_2; /* SDRAM Control Configuration 2 */ + unsigned int sdram_mode; /* SDRAM Mode Configuration */ + unsigned int sdram_mode_2; /* SDRAM Mode Configuration 2 */ + unsigned int sdram_md_cntl; /* SDRAM Mode Control */ + unsigned int sdram_interval; /* SDRAM Interval Configuration */ + unsigned int sdram_data_init; /* SDRAM Data initialization */ + unsigned char res_12c[4]; + unsigned int sdram_clk_cntl; /* SDRAM Clock Control */ + unsigned char res_134[20]; + unsigned int init_addr; /* training init addr */ + unsigned int init_ext_addr; /* training init extended addr */ + unsigned char res_150[16]; + unsigned int timing_cfg_4; /* SDRAM Timing Configuration 4 */ + unsigned int timing_cfg_5; /* SDRAM Timing Configuration 5 */ + unsigned int timing_cfg_6; /* SDRAM Timing Configuration 6 */ + unsigned int timing_cfg_7; /* SDRAM Timing Configuration 7 */ + unsigned int zq_cntl; /* ZQ calibration control*/ + unsigned int wrlvl_cntl; /* write leveling control*/ + unsigned char reg_178[4]; + unsigned int ddr_sr_cntr; /* self refresh counter */ + unsigned int ddr_sdram_rcw_1; /* Control Words 1 */ + unsigned int ddr_sdram_rcw_2; /* Control Words 2 */ + unsigned char reg_188[8]; + unsigned int ddr_wrlvl_cntl_2; /* write leveling control 2 */ + unsigned int ddr_wrlvl_cntl_3; /* write leveling control 3 */ + unsigned char res_198[0x1a0-0x198]; + unsigned int ddr_sdram_rcw_3; + unsigned int ddr_sdram_rcw_4; + unsigned int ddr_sdram_rcw_5; + unsigned int ddr_sdram_rcw_6; + unsigned char res_1b0[0x200-0x1b0]; + unsigned int sdram_mode_3; /* SDRAM Mode Configuration 3 */ + unsigned int sdram_mode_4; /* SDRAM Mode Configuration 4 */ + unsigned int sdram_mode_5; /* SDRAM Mode Configuration 5 */ + unsigned int sdram_mode_6; /* SDRAM Mode Configuration 6 */ + unsigned int sdram_mode_7; /* SDRAM Mode Configuration 7 */ + unsigned int sdram_mode_8; /* SDRAM Mode Configuration 8 */ + unsigned char res_218[0x220-0x218]; + unsigned int sdram_mode_9; /* SDRAM Mode Configuration 9 */ + unsigned int sdram_mode_10; /* SDRAM Mode Configuration 10 */ + unsigned int sdram_mode_11; /* SDRAM Mode Configuration 11 */ + unsigned int sdram_mode_12; /* SDRAM Mode Configuration 12 */ + unsigned int sdram_mode_13; /* SDRAM Mode Configuration 13 */ + unsigned int sdram_mode_14; /* SDRAM Mode Configuration 14 */ + unsigned int sdram_mode_15; /* SDRAM Mode Configuration 15 */ + unsigned int sdram_mode_16; /* SDRAM Mode Configuration 16 */ + unsigned char res_240[0x250-0x240]; + unsigned int timing_cfg_8; /* SDRAM Timing Configuration 8 */ + unsigned int timing_cfg_9; /* SDRAM Timing Configuration 9 */ + unsigned int timing_cfg_10; /* SDRAM Timing COnfigurtion 10 */ + unsigned char res_258[0x260-0x25c]; + unsigned int sdram_cfg_3; + unsigned char res_264[0x270-0x264]; + unsigned int sdram_md_cntl_2; + unsigned char res_274[0x400-0x274]; + unsigned int dq_map[4]; + unsigned char res_410[0x800-0x410]; + unsigned int tx_cfg[4]; + unsigned char res_810[0xb20-0x810]; + unsigned int ddr_dsr1; /* Debug Status 1 */ + unsigned int ddr_dsr2; /* Debug Status 2 */ + unsigned int ddr_cdr1; /* Control Driver 1 */ + unsigned int ddr_cdr2; /* Control Driver 2 */ + unsigned char res_b30[200]; + unsigned int ip_rev1; /* IP Block Revision 1 */ + unsigned int ip_rev2; /* IP Block Revision 2 */ + unsigned int eor; /* Enhanced Optimization Register */ + unsigned char res_c04[252]; + unsigned int mtcr; /* Memory Test Control Register */ + unsigned char res_d04[28]; + unsigned int mtp[10]; /* Memory Test Patterns */ + unsigned char res_d48[184]; + unsigned int data_err_inject_hi; /* Data Path Err Injection Mask Hi*/ + unsigned int data_err_inject_lo;/* Data Path Err Injection Mask Lo*/ + unsigned int ecc_err_inject; /* Data Path Err Injection Mask ECC */ + unsigned char res_e0c[20]; + unsigned int capture_data_hi; /* Data Path Read Capture High */ + unsigned int capture_data_lo; /* Data Path Read Capture Low */ + unsigned int capture_ecc; /* Data Path Read Capture ECC */ + unsigned char res_e2c[20]; + unsigned int err_detect; /* Error Detect */ + unsigned int err_disable; /* Error Disable */ + unsigned int err_int_en; + unsigned int capture_attributes; /* Error Attrs Capture */ + unsigned int capture_address; /* Error Addr Capture */ + unsigned int capture_ext_address; /* Error Extended Addr Capture */ + unsigned int err_sbe; /* Single-Bit ECC Error Management */ + unsigned char res_e5c[164]; + unsigned int debug[64]; /* debug_1 to debug_64 */ +}; +#endif /* DDR_IMMAP_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h b/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h new file mode 100644 index 0000000..f32891b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/opts.h @@ -0,0 +1,119 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_OPTS_H +#define DDR_OPTS_H + +#define SDRAM_TYPE_DDR4 5 /* sdram_cfg register */ + +#define DDR_BC4 4 /* burst chop */ +#define DDR_OTF 6 /* on-the-fly BC4 and BL8 */ +#define DDR_BL8 8 /* burst length 8 */ + +#define DDR4_RTT_OFF 0 +#define DDR4_RTT_60_OHM 1 /* RZQ/4 */ +#define DDR4_RTT_120_OHM 2 /* RZQ/2 */ +#define DDR4_RTT_40_OHM 3 /* RZQ/6 */ +#define DDR4_RTT_240_OHM 4 /* RZQ/1 */ +#define DDR4_RTT_48_OHM 5 /* RZQ/5 */ +#define DDR4_RTT_80_OHM 6 /* RZQ/3 */ +#define DDR4_RTT_34_OHM 7 /* RZQ/7 */ +#define DDR4_RTT_WR_OFF 0 +#define DDR4_RTT_WR_120_OHM 1 +#define DDR4_RTT_WR_240_OHM 2 +#define DDR4_RTT_WR_HZ 3 +#define DDR4_RTT_WR_80_OHM 4 +#define DDR_ODT_NEVER 0x0 +#define DDR_ODT_CS 0x1 +#define DDR_ODT_ALL_OTHER_CS 0x2 +#define DDR_ODT_OTHER_DIMM 0x3 +#define DDR_ODT_ALL 0x4 +#define DDR_ODT_SAME_DIMM 0x5 +#define DDR_ODT_CS_AND_OTHER_DIMM 0x6 +#define DDR_ODT_OTHER_CS_ONSAMEDIMM 0x7 +#define DDR_BA_INTLV_CS01 0x40 +#define DDR_BA_INTLV_CS0123 0x64 +#define DDR_BA_NONE 0 +#define DDR_256B_INTLV 0x8 + +struct memctl_opt { + int rdimm; + unsigned int dbw_cap_shift; + struct local_opts_s { + unsigned int auto_precharge; + unsigned int odt_rd_cfg; + unsigned int odt_wr_cfg; + unsigned int odt_rtt_norm; + unsigned int odt_rtt_wr; + } cs_odt[DDRC_NUM_CS]; + int ctlr_intlv; + unsigned int ctlr_intlv_mode; + unsigned int ba_intlv; + int addr_hash; + int ecc_mode; + int ctlr_init_ecc; + int self_refresh_in_sleep; + int self_refresh_irq_en; + int dynamic_power; + /* memory data width 0 = 64-bit, 1 = 32-bit, 2 = 16-bit */ + unsigned int data_bus_dimm; + unsigned int data_bus_used; /* on individual board */ + unsigned int burst_length; /* BC4, OTF and BL8 */ + int otf_burst_chop_en; + int mirrored_dimm; + int quad_rank_present; + int output_driver_impedance; + int ap_en; + int x4_en; + + int caslat_override; + unsigned int caslat_override_value; + int addt_lat_override; + unsigned int addt_lat_override_value; + + unsigned int clk_adj; + unsigned int cpo_sample; + unsigned int wr_data_delay; + + unsigned int cswl_override; + unsigned int wrlvl_override; + unsigned int wrlvl_sample; + unsigned int wrlvl_start; + unsigned int wrlvl_ctl_2; + unsigned int wrlvl_ctl_3; + + int half_strength_drive_en; + int twot_en; + int threet_en; + unsigned int bstopre; + unsigned int tfaw_ps; + + int rtt_override; + unsigned int rtt_override_value; + unsigned int rtt_wr_override_value; + unsigned int rtt_park; + + int auto_self_refresh_en; + unsigned int sr_it; + unsigned int ddr_cdr1; + unsigned int ddr_cdr2; + + unsigned int trwt_override; + unsigned int trwt; + unsigned int twrt; + unsigned int trrt; + unsigned int twwt; + + unsigned int vref_phy; + unsigned int vref_dimm; + unsigned int odt; + unsigned int phy_tx_impedance; + unsigned int phy_atx_impedance; + unsigned int skip2d; +}; + +#endif /* DDR_OPTS_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h b/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h new file mode 100644 index 0000000..e85fd8f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/regs.h @@ -0,0 +1,109 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DDR_REG_H +#define DDR_REG_H + +#define SDRAM_CS_CONFIG_EN 0x80000000 + +/* DDR_SDRAM_CFG - DDR SDRAM Control Configuration + */ +#define SDRAM_CFG_MEM_EN 0x80000000 +#define SDRAM_CFG_SREN 0x40000000 +#define SDRAM_CFG_ECC_EN 0x20000000 +#define SDRAM_CFG_RD_EN 0x10000000 +#define SDRAM_CFG_SDRAM_TYPE_MASK 0x07000000 +#define SDRAM_CFG_SDRAM_TYPE_SHIFT 24 +#define SDRAM_CFG_DYN_PWR 0x00200000 +#define SDRAM_CFG_DBW_MASK 0x00180000 +#define SDRAM_CFG_DBW_SHIFT 19 +#define SDRAM_CFG_32_BW 0x00080000 +#define SDRAM_CFG_16_BW 0x00100000 +#define SDRAM_CFG_8_BW 0x00180000 +#define SDRAM_CFG_8_BE 0x00040000 +#define SDRAM_CFG_2T_EN 0x00008000 +#define SDRAM_CFG_MEM_HLT 0x00000002 +#define SDRAM_CFG_BI 0x00000001 + +#define SDRAM_CFG2_FRC_SR 0x80000000 +#define SDRAM_CFG2_FRC_SR_CLEAR ~(SDRAM_CFG2_FRC_SR) +#define SDRAM_CFG2_D_INIT 0x00000010 +#define SDRAM_CFG2_AP_EN 0x00000020 +#define SDRAM_CFG2_ODT_ONLY_READ 2 + +#define SDRAM_CFG3_DDRC_RST 0x80000000 + +#define SDRAM_INTERVAL_REFINT 0xFFFF0000 +#define SDRAM_INTERVAL_REFINT_CLEAR ~(SDRAM_INTERVAL_REFINT) +#define SDRAM_INTERVAL_BSTOPRE 0x3FFF + +/* DDR_MD_CNTL */ +#define MD_CNTL_MD_EN 0x80000000 +#define MD_CNTL_CS_SEL(x) (((x) & 0x7) << 28) +#define MD_CNTL_MD_SEL(x) (((x) & 0xf) << 24) +#define MD_CNTL_CKE(x) (((x) & 0x3) << 20) + +/* DDR_CDR1 */ +#define DDR_CDR1_DHC_EN 0x80000000 +#define DDR_CDR1_ODT_SHIFT 17 +#define DDR_CDR1_ODT_MASK 0x6 +#define DDR_CDR2_ODT_MASK 0x1 +#define DDR_CDR1_ODT(x) ((x & DDR_CDR1_ODT_MASK) << DDR_CDR1_ODT_SHIFT) +#define DDR_CDR2_ODT(x) (x & DDR_CDR2_ODT_MASK) +#define DDR_CDR2_VREF_OVRD(x) (0x00008080 | ((((x) - 37) & 0x3F) << 8)) +#define DDR_CDR2_VREF_TRAIN_EN 0x00000080 +#define DDR_CDR2_VREF_RANGE_2 0x00000040 +#define DDR_CDR_ODT_OFF 0x0 +#define DDR_CDR_ODT_100ohm 0x1 +#define DDR_CDR_ODT_120OHM 0x2 +#define DDR_CDR_ODT_80ohm 0x3 +#define DDR_CDR_ODT_60ohm 0x4 +#define DDR_CDR_ODT_40ohm 0x5 +#define DDR_CDR_ODT_50ohm 0x6 +#define DDR_CDR_ODT_30ohm 0x7 + + +/* DDR ERR_DISABLE */ +#define DDR_ERR_DISABLE_APED (1 << 8) /* Address parity error disable */ +#define DDR_ERR_DISABLE_SBED (1 << 2) /* Address parity error disable */ +#define DDR_ERR_DISABLE_MBED (1 << 3) /* Address parity error disable */ + +/* Mode Registers */ +#define DDR_MR5_CA_PARITY_LAT_4_CLK 0x1 /* for DDR4-1600/1866/2133 */ +#define DDR_MR5_CA_PARITY_LAT_5_CLK 0x2 /* for DDR4-2400 */ + +/* DDR DSR2 register */ +#define DDR_DSR_2_PHY_INIT_CMPLT 0x4 + +/* SDRAM TIMING_CFG_10 register */ +#define DDR_TIMING_CFG_10_T_STAB 0x7FFF + +/* DEBUG 2 register */ +#define DDR_DBG_2_MEM_IDLE 0x00000002 + +/* DEBUG 26 register */ +#define DDR_DEBUG_26_BIT_6 (0x1 << 6) +#define DDR_DEBUG_26_BIT_7 (0x1 << 7) +#define DDR_DEBUG_26_BIT_12 (0x1 << 12) +#define DDR_DEBUG_26_BIT_13 (0x1 << 13) +#define DDR_DEBUG_26_BIT_14 (0x1 << 14) +#define DDR_DEBUG_26_BIT_15 (0x1 << 15) +#define DDR_DEBUG_26_BIT_16 (0x1 << 16) +#define DDR_DEBUG_26_BIT_17 (0x1 << 17) +#define DDR_DEBUG_26_BIT_18 (0x1 << 18) +#define DDR_DEBUG_26_BIT_19 (0x1 << 19) +#define DDR_DEBUG_26_BIT_24 (0x1 << 24) +#define DDR_DEBUG_26_BIT_25 (0x1 << 25) + +#define DDR_DEBUG_26_BIT_24_CLEAR ~(DDR_DEBUG_26_BIT_24) + +/* DEBUG_29 register */ +#define DDR_TX_BD_DIS (1 << 10) /* Transmit Bit Deskew Disable */ + +#define DDR_INIT_ADDR_EXT_UIA (1 << 31) + +#endif /* DDR_REG_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h b/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h new file mode 100644 index 0000000..2e22ad5 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ddr/utility.h @@ -0,0 +1,24 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef UTILITY_H +#define UTILITY_H + +#include + +#if defined(NXP_HAS_CCN504) || defined(NXP_HAS_CCN508) +#define CCN_HN_F_SAM_CTL 0x8 +#define CCN_HN_F_REGION_SIZE 0x10000 +#endif + +unsigned long get_ddr_freq(struct sysinfo *sys, int ctrl_num); +unsigned int get_memory_clk_ps(unsigned long clk); +unsigned int picos_to_mclk(unsigned long data_rate, unsigned int picos); +unsigned int get_ddrc_version(const struct ccsr_ddr *ddr); +void print_ddr_info(struct ccsr_ddr *ddr); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h new file mode 100644 index 0000000..d0ffc86 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h @@ -0,0 +1,89 @@ +// SPDX-License-Identifier: BSD-3-Clause +/* + * Copyright 2020-2021 NXP + */ + +/** + * @Flash info + * + */ +#ifndef FLASH_INFO_H +#define FLASH_INFO_H + +#define SZ_16M_BYTES 0x1000000U + +/* Start of "if defined(CONFIG_MT25QU512A)" */ +#if defined(CONFIG_MT25QU512A) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MT25QU512A)" */ + +/* Start of "if defined(CONFIG_MX25U25645G)" */ +#elif defined(CONFIG_MX25U25645G) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x2000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MX25U25645G)" */ + +/* Start of "if defined(CONFIG_MX25U51245G)" */ +#elif defined(CONFIG_MX25U51245G) +#define F_SECTOR_64K 0x10000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_64K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +/* End of "if defined(CONFIG_MX25U51245G)" */ + +/* Start of "if defined(CONFIG_MT35XU512A)" */ +#elif defined(CONFIG_MT35XU512A) +#define F_SECTOR_128K 0x20000U +#define F_SECTOR_32K 0x8000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x4000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_128K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif +/* If Warm boot is enabled for the platform, + * count of arm instruction N-OP(s) to mark + * the completion of write operation to flash; + * varies from one flash to other. + */ +#ifdef NXP_WARM_BOOT +#define FLASH_WR_COMP_WAIT_BY_NOP_COUNT 0x20000 +#endif + +/* End of "if defined(CONFIG_MT35XU512A)" */ + +/* Start of #elif defined(CONFIG_MT35XU02G) */ +#elif defined(CONFIG_MT35XU02G) +#define F_SECTOR_128K 0x20000U +#define F_PAGE_256 0x100U +#define F_SECTOR_4K 0x1000U +#define F_FLASH_SIZE_BYTES 0x10000000U +#define F_SECTOR_ERASE_SZ F_SECTOR_128K +#ifdef CONFIG_FSPI_4K_ERASE +#define F_SECTOR_ERASE_SZ F_SECTOR_4K +#endif + +#endif /* End of #elif defined(CONFIG_MT35XU02G) */ + +#endif /* FLASH_INFO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h new file mode 100644 index 0000000..d0de543 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h @@ -0,0 +1,122 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +/*! + * @file fspi_api.h + * @brief This file contains the FlexSPI/FSPI API to communicate + * to attached Slave device. + * @addtogroup FSPI_API + * @{ + */ + +#ifndef FSPI_API_H +#define FSPI_API_H + +#if DEBUG_FLEXSPI +#define SZ_57M 0x3900000u +#endif + +/*! + * Basic set of APIs. + */ + +/*! + * @details AHB read/IP Read, decision to be internal to API + * Minimum Read size = 1Byte + * @param[in] src_off source offset from where data to read from flash + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details Sector erase, Minimum size + * 256KB(0x40000)/128KB(0x20000)/64K(0x10000)/4K(0x1000) + * depending upon flash, Calls xspi_wren() internally + * @param[out] erase_offset Destination erase location on flash which + * has to be erased, needs to be multiple of 0x40000/0x20000/0x10000 + * @param[in] erase_len length in bytes in Hex like 0x100000 for 1MB, minimum + * erase size is 1 sector(0x40000/0x20000/0x10000) + * + * @return XSPI_SUCCESS or error code + */ +int xspi_sector_erase(uint32_t erase_offset, uint32_t erase_len); +/*! + * @details IP write, For writing data to flash, calls xspi_wren() internally. + * Single/multiple page write can start @any offset, but performance will be low + * due to ERRATA + * @param[out] dst_off Destination location on flash where data needs to + * be written + * @param[in] src source offset from where data to be read + * @param[in] len length in bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_write(uint32_t dst_off, void *src, uint32_t len); +/*! + * @details fspi_init, Init function. + * @param[in] uint32_t base_reg_addr + * @param[in] uint32_t flash_start_addr + * + * @return XSPI_SUCCESS or error code + */ +int fspi_init(uint32_t base_reg_addr, uint32_t flash_start_addr); +/*! + * @details is_flash_busy, Check if any erase or write or lock is + * pending on flash/slave + * @param[in] void + * + * @return TRUE/FLASE + */ +bool is_flash_busy(void); + +/*! + * Advanced set of APIs. + */ + +/*! + * @details Write enable, to be used by advance users only. + * Step 1 for sending write commands to flash. + * @param[in] dst_off destination offset where data will be written + * + * @return XSPI_SUCCESS or error code + */ +int xspi_wren(uint32_t dst_off); +/*! + * @details AHB read, meaning direct memory mapped access to flash, + * Minimum Read size = 1Byte + * @param[in] src_off source offset from where data to read from flash, + * needs to be word aligned + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_ahb_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details IP read, READ via RX buffer from flash, minimum READ size = 1Byte + * @param[in] src_off source offset from where data to be read from flash + * @param[out] des Destination location where data needs to be copied + * @param[in] len length in Bytes,where 1-word=4-bytes/32-bits + * + * @return XSPI_SUCCESS or error code + */ +int xspi_ip_read(uint32_t src_off, uint32_t *des, uint32_t len); +/*! + * @details CHIP erase, Erase complete chip in one go + * + * @return XSPI_SUCCESS or error code + */ +int xspi_bulk_erase(void); + +/*! + * Add test cases to confirm flash read/erase/write functionality. + */ +void fspi_test(uint32_t fspi_test_addr, uint32_t size, int extra); +#endif /* FSPI_API_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h b/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h new file mode 100644 index 0000000..18b31eb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h @@ -0,0 +1,28 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +/* error codes */ +#ifndef XSPI_ERROR_CODES_H +#define XSPI_ERROR_CODES_H + +#include + +typedef enum { + XSPI_SUCCESS = 0, + XSPI_READ_FAIL = ELAST + 1, + XSPI_ERASE_FAIL, + XSPI_IP_READ_FAIL, + XSPI_AHB_READ_FAIL, + XSPI_IP_WRITE_FAIL, + XSPI_AHB_WRITE_FAIL, + XSPI_BLOCK_TIMEOUT, + XSPI_UNALIGN_ADDR, + XSPI_UNALIGN_SIZE, +} XSPI_STATUS_CODES; +#undef ELAST +#define ELAST XSPI_STATUS_CODES.XSPI_UNALIGN_SIZE +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h b/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h new file mode 100644 index 0000000..ff34744 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h @@ -0,0 +1,72 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GICV2_H +#define PLAT_GICV2_H + +#include + + /* register offsets */ +#define GICD_CTLR_OFFSET 0x0 +#define GICD_CPENDSGIR3_OFFSET 0xF1C +#define GICD_SPENDSGIR3_OFFSET 0xF2C +#define GICD_SGIR_OFFSET 0xF00 +#define GICD_IGROUPR0_OFFSET 0x080 +#define GICD_TYPER_OFFSET 0x0004 +#define GICD_ISENABLER0_OFFSET 0x0100 +#define GICD_ICENABLER0_OFFSET 0x0180 +#define GICD_IPRIORITYR3_OFFSET 0x040C +#define GICD_ISENABLERn_OFFSET 0x0100 +#define GICD_ISACTIVER0_OFFSET 0x300 + +#define GICC_CTLR_OFFSET 0x0 +#define GICC_PMR_OFFSET 0x0004 +#define GICC_IAR_OFFSET 0x000C +#define GICC_DIR_OFFSET 0x1000 +#define GICC_EOIR_OFFSET 0x0010 + + /* bitfield masks */ +#define GICC_CTLR_EN_GRP0 0x1 +#define GICC_CTLR_EN_GRP1 0x2 +#define GICC_CTLR_EOImodeS_MASK 0x200 +#define GICC_CTLR_DIS_BYPASS 0x60 +#define GICC_CTLR_CBPR_MASK 0x10 +#define GICC_CTLR_FIQ_EN_MASK 0x8 +#define GICC_CTLR_ACKCTL_MASK 0x4 +#define GICC_PMR_FILTER 0xFF + +#define GICD_CTLR_EN_GRP0 0x1 +#define GICD_CTLR_EN_GRP1 0x2 +#define GICD_IGROUP0_SGI15 0x8000 +#define GICD_ISENABLE0_SGI15 0x8000 +#define GICD_ICENABLE0_SGI15 0x8000 +#define GICD_ISACTIVER0_SGI15 0x8000 +#define GICD_CPENDSGIR_CLR_MASK 0xFF000000 +#define GICD_IPRIORITY_SGI15_MASK 0xFF000000 +#define GICD_SPENDSGIR3_SGI15_MASK 0xFF000000 +#define GICD_SPENDSGIR3_SGI15_OFFSET 0x18 + +#ifndef __ASSEMBLER__ + +/* GIC common API's */ +void plat_ls_gic_driver_init(const uintptr_t nxp_gicd_addr, + const uintptr_t nxp_gicc_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uint32_t *target_mask_array); +void plat_ls_gic_init(void); +void plat_ls_gic_cpuif_enable(void); +void plat_ls_gic_cpuif_disable(void); +void plat_ls_gic_redistif_on(void); +void plat_ls_gic_redistif_off(void); +void plat_gic_pcpu_init(void); +/* GIC utility functions */ +void get_gic_offset(uint32_t *gicc_base, uint32_t *gicd_base); +#endif + +#endif /* PLAT_GICV2_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h b/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h new file mode 100644 index 0000000..0c0d0fc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h @@ -0,0 +1,121 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GICV3_H +#define PLAT_GICV3_H + +#include + + /* offset between redistributors */ +#define GIC_RD_OFFSET 0x00020000 + /* offset between SGI's */ +#define GIC_SGI_OFFSET 0x00020000 + /* offset from rd base to sgi base */ +#define GIC_RD_2_SGI_OFFSET 0x00010000 + + /* register offsets */ +#define GICD_CTLR_OFFSET 0x0 +#define GICD_CLR_SPI_SR 0x58 +#define GICD_IGROUPR_2 0x88 +#define GICD_ISENABLER_1 0x104 +#define GICD_ICENABLER_1 0x184 +#define GICD_ISENABLER_2 0x108 +#define GICD_ICENABLER_2 0x188 +#define GICD_ISENABLER_3 0x10c +#define GICD_ICENABLER_3 0x18c +#define GICD_ICPENDR_2 0x288 +#define GICD_ICACTIVER_2 0x388 +#define GICD_IPRIORITYR_22 0x458 +#define GICD_ICFGR_5 0xC14 +#define GICD_IGRPMODR_2 0xD08 + +#define GICD_IROUTER60_OFFSET 0x61e0 +#define GICD_IROUTER76_OFFSET 0x6260 +#define GICD_IROUTER89_OFFSET 0x62C8 +#define GICD_IROUTER112_OFFSET 0x6380 +#define GICD_IROUTER113_OFFSET 0x6388 + +#define GICR_ICENABLER0_OFFSET 0x180 +#define GICR_CTLR_OFFSET 0x0 +#define GICR_IGROUPR0_OFFSET 0x80 +#define GICR_IGRPMODR0_OFFSET 0xD00 +#define GICR_IPRIORITYR3_OFFSET 0x40C +#define GICR_ICPENDR0_OFFSET 0x280 +#define GICR_ISENABLER0_OFFSET 0x100 +#define GICR_TYPER_OFFSET 0x8 +#define GICR_WAKER_OFFSET 0x14 +#define GICR_ICACTIVER0_OFFSET 0x380 +#define GICR_ICFGR0_OFFSET 0xC00 + + /* bitfield masks */ +#define GICD_CTLR_EN_GRP_MASK 0x7 +#define GICD_CTLR_EN_GRP_1NS 0x2 +#define GICD_CTLR_EN_GRP_1S 0x4 +#define GICD_CTLR_EN_GRP_0 0x1 +#define GICD_CTLR_ARE_S_MASK 0x10 +#define GICD_CTLR_RWP 0x80000000 + +#define GICR_ICENABLER0_SGI15 0x00008000 +#define GICR_CTLR_RWP 0x8 +#define GICR_CTLR_DPG0_MASK 0x2000000 +#define GICR_IGROUPR0_SGI15 0x00008000 +#define GICR_IGRPMODR0_SGI15 0x00008000 +#define GICR_ISENABLER0_SGI15 0x00008000 +#define GICR_IPRIORITYR3_SGI15_MASK 0xFF000000 +#define GICR_ICPENDR0_SGI15 0x8000 + +#define GIC_SPI_89_MASK 0x02000000 +#define GIC_SPI89_PRIORITY_MASK 0xFF00 +#define GIC_IRM_SPI89 0x80000000 + +#define GICD_IROUTER_VALUE 0x100 +#define GICD_ISENABLER_1_VALUE 0x10000000 +#define GICD_ISENABLER_2_VALUE 0x100 +#define GICD_ISENABLER_3_VALUE 0x20100 +#define GICR_WAKER_SLEEP_BIT 0x2 +#define GICR_WAKER_ASLEEP (1 << 2 | 1 << 1) + +#define ICC_SRE_EL3_SRE 0x1 +#define ICC_IGRPEN0_EL1_EN 0x1 +#define ICC_CTLR_EL3_CBPR_EL1S 0x1 +#define ICC_CTLR_EL3_RM 0x20 +#define ICC_CTLR_EL3_EOIMODE_EL3 0x4 +#define ICC_CTLR_EL3_PMHE 0x40 +#define ICC_PMR_EL1_P_FILTER 0xFF +#define ICC_IAR0_EL1_SGI15 0xF +#define ICC_SGI0R_EL1_INTID 0x0F000000 +#define ICC_IAR0_INTID_SPI_89 0x59 + +#define ICC_IGRPEN1_EL1 S3_0_C12_C12_7 +#define ICC_PMR_EL1 S3_0_C4_C6_0 +#define ICC_SRE_EL3 S3_6_C12_C12_5 +#define ICC_CTLR_EL3 S3_6_C12_C12_4 +#define ICC_SRE_EL2 S3_4_C12_C9_5 +#define ICC_CTLR_EL1 S3_0_C12_C12_4 + +#ifndef __ASSEMBLER__ + +/* GIC common API's */ +typedef unsigned int (*my_core_pos_fn)(void); + +void plat_ls_gic_driver_init(const uintptr_t nxp_gicd_addr, + const uintptr_t nxp_gicr_addr, + uint8_t plat_core_count, + interrupt_prop_t *ls_interrupt_props, + uint8_t ls_interrupt_prop_count, + uintptr_t *target_mask_array, + mpidr_hash_fn mpidr_to_core_pos); +//void plat_ls_gic_driver_init(void); +void plat_ls_gic_init(void); +void plat_ls_gic_cpuif_enable(void); +void plat_ls_gic_cpuif_disable(void); +void plat_ls_gic_redistif_on(void); +void plat_ls_gic_redistif_off(void); +void plat_gic_pcpu_init(void); +#endif + +#endif /* PLAT_GICV3_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h b/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h new file mode 100644 index 0000000..df75840 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h @@ -0,0 +1,53 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PLAT_GPIO_H +#define PLAT_GPIO_H + +#include +#include + +/* GPIO Register offset */ +#define GPIO_SEL_MASK 0x7F +#define GPIO_BIT_MASK 0x1F +#define GPDIR_REG_OFFSET 0x0 +#define GPDAT_REG_OFFSET 0x8 + +#define GPIO_ID_BASE_ADDR_SHIFT 5U +#define GPIO_BITS_PER_BASE_REG 32U + +#define GPIO_0 0 +#define GPIO_1 1 +#define GPIO_2 2 +#define GPIO_3 3 + +#define GPIO_SUCCESS 0x0 +#define GPIO_FAILURE 0x1 + +#ifdef NXP_GPIO_BE +#define gpio_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define gpio_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_GPIO_LE) +#define gpio_read32(a) mmio_read_32((uintptr_t)(a)) +#define gpio_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define GPIO register endianness +#endif + +typedef struct { + uintptr_t gpio1_base_addr; + uintptr_t gpio2_base_addr; + uintptr_t gpio3_base_addr; + uintptr_t gpio4_base_addr; +} gpio_init_info_t; + +void gpio_init(gpio_init_info_t *gpio_init_data); +uint32_t *select_gpio_n_bitnum(uint32_t povdd_gpio, uint32_t *bit_num); +int clr_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num); +int set_gpio_bit(uint32_t *gpio_base_addr, uint32_t bit_num); + +#endif /* PLAT_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h b/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h new file mode 100644 index 0000000..85e6eb4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h @@ -0,0 +1,52 @@ +/* + * Copyright 2016-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + + +#ifndef I2C_H +#define I2C_H + +#include + +#define I2C_TIMEOUT 1000 /* ms */ + +#define I2C_FD_CONSERV 0x7e +#define I2C_CR_DIS (1 << 7) +#define I2C_CR_EN (0 << 7) +#define I2C_CR_MA (1 << 5) +#define I2C_CR_TX (1 << 4) +#define I2C_CR_TX_NAK (1 << 3) +#define I2C_CR_RSTA (1 << 2) +#define I2C_SR_BB (1 << 5) +#define I2C_SR_IDLE (0 << 5) +#define I2C_SR_AL (1 << 4) +#define I2C_SR_IF (1 << 1) +#define I2C_SR_RX_NAK (1 << 0) +#define I2C_SR_RST (I2C_SR_AL | I2C_SR_IF) + +#define I2C_GLITCH_EN 0x8 + +#define i2c_in(a) mmio_read_8((uintptr_t)(a)) +#define i2c_out(a, v) mmio_write_8((uintptr_t)(a), (v)) + +struct ls_i2c { + unsigned char ad; /* I2c Bus Address Register */ + unsigned char fd; /* I2c Bus Frequency Dividor Register */ + unsigned char cr; /* I2c Bus Control Register */ + unsigned char sr; /* I2c Bus Status Register */ + unsigned char dr; /* I2C Bus Data I/O Register */ + unsigned char ic; /* I2C Bus Interrupt Config Register */ + unsigned char dbg; /* I2C Bus Debug Register */ +}; + +void i2c_init(uintptr_t nxp_i2c_addr); +int i2c_read(unsigned char chip, int addr, int alen, + unsigned char *buf, int len); +int i2c_write(unsigned char chip, int addr, int alen, + const unsigned char *buf, int len); +int i2c_probe_chip(unsigned char chip); + +#endif /* I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h new file mode 100644 index 0000000..dbcd762 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h @@ -0,0 +1,19 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IFC_NAND_H +#define IFC_NAND_H + +#define NXP_IFC_SRAM_BUFFER_SIZE UL(0x100000) /* 1M */ + +int ifc_nand_init(uintptr_t *block_dev_spec, + uintptr_t ifc_region_addr, + uintptr_t ifc_register_addr, + size_t ifc_sram_size, + uintptr_t ifc_nand_blk_offset, + size_t ifc_nand_blk_size); + +#endif /*IFC_NAND_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h new file mode 100644 index 0000000..ee14460 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h @@ -0,0 +1,14 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef IFC_NOR_H +#define IFC_NOR_H + + +int ifc_nor_init(uintptr_t flash_addr, size_t flash_size); + +#endif /*IFC_NOR_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h b/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h new file mode 100644 index 0000000..777089c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h @@ -0,0 +1,19 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef LS_INTERCONNECT_H +#define LS_INTERCONNECT_H + +#if (INTERCONNECT == CCI400) +#define CCI_TERMINATE_BARRIER_TX 0x8 +#endif + +/* Interconnect CCI/CCN functions */ +void plat_ls_interconnect_enter_coherency(unsigned int num_clusters); +void plat_ls_interconnect_exit_coherency(void); + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h b/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h new file mode 100644 index 0000000..28199e8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h @@ -0,0 +1,75 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef PMU_H +#define PMU_H + +/* PMU Registers' OFFSET */ +#define PMU_PCPW20SR_OFFSET 0x830 +#define PMU_CLL2FLUSHSETR_OFFSET 0x1110 +#define PMU_CLSL2FLUSHCLRR_OFFSET 0x1114 +#define PMU_CLL2FLUSHSR_OFFSET 0x1118 +#define PMU_POWMGTCSR_VAL (1 << 20) + +/* PMU Registers */ +#define CORE_TIMEBASE_ENBL_OFFSET 0x8A0 +#define CLUST_TIMER_BASE_ENBL_OFFSET 0x18A0 + +#define PMU_IDLE_CLUSTER_MASK 0x2 +#define PMU_FLUSH_CLUSTER_MASK 0x2 +#define PMU_IDLE_CORE_MASK 0xfe + +/* pmu register offsets and bitmaps */ +#define PMU_POWMGTDCR0_OFFSET 0xC20 +#define PMU_POWMGTCSR_OFFSET 0x4000 +#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_CLL2FLUSHCLRR_OFFSET 0x1114 +#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_IPPDEXPCR6_OFFSET 0x4058 +#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_IPSTPACKSR0_OFFSET 0x4140 +#define PMU_IPSTPACKSR1_OFFSET 0x4144 +#define PMU_IPSTPACKSR2_OFFSET 0x4148 +#define PMU_IPSTPACKSR3_OFFSET 0x414C +#define PMU_IPSTPACKSR4_OFFSET 0x4150 +#define PMU_IPSTPACKSR5_OFFSET 0x4154 +#define PMU_IPSTPACKSR6_OFFSET 0x4158 + +#define CLAINACT_DISABLE_ACP 0xFF +#define CLSINACT_DISABLE_SKY 0xFF +#define POWMGTDCR_STP_OV_EN 0x1 +#define POWMGTCSR_LPM20_REQ 0x00100000 + +/* Used by PMU */ +#define DEVDISR1_MASK 0x024F3504 +#define DEVDISR2_MASK 0x0003FFFF +#define DEVDISR3_MASK 0x0000303F +#define DEVDISR4_MASK 0x0000FFFF +#define DEVDISR5_MASK 0x00F07603 +#define DEVDISR6_MASK 0x00000001 + +#ifndef __ASSEMBLER__ +void enable_timer_base_to_cluster(uintptr_t nxp_pmu_addr); +void enable_core_tb(uintptr_t nxp_pmu_addr); +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h b/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h new file mode 100644 index 0000000..db11c3b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h @@ -0,0 +1,30 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef QSPI_H +#define QSPI_H + +#include +#include + +#define CHS_QSPI_MCR 0x01550000 +#define CHS_QSPI_64LE 0xC + +#ifdef NXP_QSPI_BE +#define qspi_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define qspi_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_QSPI_LE) +#define qspi_in32(a) mmio_read_32((uintptr_t)(a)) +#define qspi_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR QSPI register endianness +#endif + +int qspi_io_setup(uintptr_t nxp_qspi_flash_addr, + size_t nxp_qspi_flash_size, + uintptr_t fip_offset); +#endif /* __QSPI_H__ */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h b/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h new file mode 100644 index 0000000..32b41f1 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2015, 2016 Freescale Semiconductor, Inc. + * Copyright 2017-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SD_MMC_H +#define SD_MMC_H + +#include + +/* operating freq */ +#define CARD_IDENTIFICATION_FREQ 400000 +#define SD_SS_25MHZ 20000000 +#define SD_HS_50MHZ 40000000 +#define MMC_SS_20MHZ 15000000 +#define MMC_HS_26MHZ 20000000 +#define MMC_HS_52MHZ 40000000 + +/* Need to check this value ? */ +#define MAX_PLATFORM_CLOCK 800000000 + +/* eSDHC system control register defines */ +#define ESDHC_SYSCTL_DTOCV(t) (((t) & 0xF) << 16) +#define ESDHC_SYSCTL_SDCLKFS(f) (((f) & 0xFF) << 8) +#define ESDHC_SYSCTL_DVS(d) (((d) & 0xF) << 4) +#define ESDHC_SYSCTL_SDCLKEN (0x00000008) +#define ESDHC_SYSCTL_RSTA (0x01000000) + +/* Data timeout counter value. SDHC_CLK x 227 */ +#define TIMEOUT_COUNTER_SDCLK_2_27 0xE +#define ESDHC_SYSCTL_INITA 0x08000000 + +/* eSDHC interrupt status enable register defines */ +#define ESDHC_IRQSTATEN_CINS 0x00000040 +#define ESDHC_IRQSTATEN_BWR 0x00000010 + +/* eSDHC interrupt status register defines */ +#define ESDHC_IRQSTAT_DMAE (0x10000000) +#define ESDHC_IRQSTAT_AC12E (0x01000000) +#define ESDHC_IRQSTAT_DEBE (0x00400000) +#define ESDHC_IRQSTAT_DCE (0x00200000) +#define ESDHC_IRQSTAT_DTOE (0x00100000) +#define ESDHC_IRQSTAT_CIE (0x00080000) +#define ESDHC_IRQSTAT_CEBE (0x00040000) +#define ESDHC_IRQSTAT_CCE (0x00020000) +#define ESDHC_IRQSTAT_CTOE (0x00010000) +#define ESDHC_IRQSTAT_CINT (0x00000100) +#define ESDHC_IRQSTAT_CRM (0x00000080) +#define ESDHC_IRQSTAT_CINS (0x00000040) +#define ESDHC_IRQSTAT_BRR (0x00000020) +#define ESDHC_IRQSTAT_BWR (0x00000010) +#define ESDHC_IRQSTAT_DINT (0x00000008) +#define ESDHC_IRQSTAT_BGE (0x00000004) +#define ESDHC_IRQSTAT_TC (0x00000002) +#define ESDHC_IRQSTAT_CC (0x00000001) +#define ESDHC_IRQSTAT_CMD_ERR (ESDHC_IRQSTAT_CIE |\ + ESDHC_IRQSTAT_CEBE |\ + ESDHC_IRQSTAT_CCE) +#define ESDHC_IRQSTAT_DATA_ERR (ESDHC_IRQSTAT_DEBE |\ + ESDHC_IRQSTAT_DCE |\ + ESDHC_IRQSTAT_DTOE) +#define ESDHC_IRQSTAT_CLEAR_ALL (0xFFFFFFFF) + +/* eSDHC present state register defines */ +#define ESDHC_PRSSTAT_CLSL 0x00800000 +#define ESDHC_PRSSTAT_WPSPL 0x00080000 +#define ESDHC_PRSSTAT_CDPL 0x00040000 +#define ESDHC_PRSSTAT_CINS 0x00010000 +#define ESDHC_PRSSTAT_BREN 0x00000800 +#define ESDHC_PRSSTAT_BWEN 0x00000400 +#define ESDHC_PRSSTAT_RTA 0x00000200 +#define ESDHC_PRSSTAT_WTA 0x00000100 +#define ESDHC_PRSSTAT_SDOFF 0x00000080 +#define ESDHC_PRSSTAT_PEROFF 0x00000040 +#define ESDHC_PRSSTAT_HCKOFF 0x00000020 +#define ESDHC_PRSSTAT_IPGOFF 0x00000010 +#define ESDHC_PRSSTAT_DLA 0x00000004 +#define ESDHC_PRSSTAT_CDIHB 0x00000002 +#define ESDHC_PRSSTAT_CIHB 0x00000001 + +/* eSDHC protocol control register defines */ +#define ESDHC_PROCTL_EMODE_LE 0x00000020 +#define ESDHC_PROCTL_DTW_1BIT 0x00000000 +#define ESDHC_PROCTL_DTW_4BIT 0x00000002 +#define ESDHC_PROCTL_DTW_8BIT 0x00000004 + +/* Watermark Level Register (WML) */ +#define ESDHC_WML_RD_WML(w) ((w) & 0x7F) +#define ESDHC_WML_WR_WML(w) (((w) & 0x7F) << 16) +#define ESDHC_WML_RD_BRST(w) (((w) & 0xF) << 8) +#define ESDHC_WML_WR_BRST(w) (((w) & 0xF) << 24) +#define ESDHC_WML_WR_BRST_MASK (0x0F000000) +#define ESDHC_WML_RD_BRST_MASK (0x00000F00) +#define ESDHC_WML_RD_WML_MASK (0x0000007F) +#define ESDHC_WML_WR_WML_MASK (0x007F0000) +#define WML_512_BYTES (0x0) +#define BURST_128_BYTES (0x0) + +/* eSDHC control register define */ +#define ESDHC_DCR_SNOOP 0x00000040 + +/* ESDHC Block attributes register */ +#define ESDHC_BLKATTR_BLKCNT(c) (((c) & 0xffff) << 16) +#define ESDHC_BLKATTR_BLKSZE(s) ((s) & 0xfff) + +/* Transfer Type Register */ +#define ESDHC_XFERTYP_CMD(c) (((c) & 0x3F) << 24) +#define ESDHC_XFERTYP_CMDTYP_NORMAL (0x0) +#define ESDHC_XFERTYP_CMDTYP_SUSPEND (0x00400000) +#define ESDHC_XFERTYP_CMDTYP_RESUME (0x00800000) +#define ESDHC_XFERTYP_CMDTYP_ABORT (0x00C00000) +#define ESDHC_XFERTYP_DPSEL (0x00200000) +#define ESDHC_XFERTYP_CICEN (0x00100000) +#define ESDHC_XFERTYP_CCCEN (0x00080000) +#define ESDHC_XFERTYP_RSPTYP_NONE (0x0) +#define ESDHC_XFERTYP_RSPTYP_136 (0x00010000) +#define ESDHC_XFERTYP_RSPTYP_48 (0x00020000) +#define ESDHC_XFERTYP_RSPTYP_48_BUSY (0x00030000) +#define ESDHC_XFERTYP_MSBSEL (0x00000020) +#define ESDHC_XFERTYP_DTDSEL (0x00000010) +#define ESDHC_XFERTYP_AC12EN (0x00000004) +#define ESDHC_XFERTYP_BCEN (0x00000002) +#define ESDHC_XFERTYP_DMAEN (0x00000001) + +#define MMC_VDD_HIGH_VOLTAGE 0x00000100 + +/* command index */ +#define CMD0 0 +#define CMD1 1 +#define CMD2 2 +#define CMD3 3 +#define CMD5 5 +#define CMD6 6 +#define CMD7 7 +#define CMD8 8 +#define CMD9 9 +#define CMD12 12 +#define CMD13 13 +#define CMD14 14 +#define CMD16 16 +#define CMD17 17 +#define CMD18 18 +#define CMD19 19 +#define CMD24 24 +#define CMD41 41 +#define CMD42 42 +#define CMD51 51 +#define CMD55 55 +#define CMD56 56 +#define ACMD6 CMD6 +#define ACMD13 CMD13 +#define ACMD41 CMD41 +#define ACMD42 CMD42 +#define ACMD51 CMD51 + +/* commands abbreviations */ +#define CMD_GO_IDLE_STATE CMD0 +#define CMD_MMC_SEND_OP_COND CMD1 +#define CMD_ALL_SEND_CID CMD2 +#define CMD_SEND_RELATIVE_ADDR CMD3 +#define CMD_SET_DSR CMD4 +#define CMD_SWITCH_FUNC CMD6 +#define CMD_SELECT_CARD CMD7 +#define CMD_DESELECT_CARD CMD7 +#define CMD_SEND_IF_COND CMD8 +#define CMD_MMC_SEND_EXT_CSD CMD8 +#define CMD_SEND_CSD CMD9 +#define CMD_SEND_CID CMD10 +#define CMD_STOP_TRANSMISSION CMD12 +#define CMD_SEND_STATUS CMD13 +#define CMD_BUS_TEST_R CMD14 +#define CMD_GO_INACTIVE_STATE CMD15 +#define CMD_SET_BLOCKLEN CMD16 +#define CMD_READ_SINGLE_BLOCK CMD17 +#define CMD_READ_MULTIPLE_BLOCK CMD18 +#define CMD_WRITE_SINGLE_BLOCK CMD24 +#define CMD_BUS_TEST_W CMD19 +#define CMD_APP_CMD CMD55 +#define CMD_GEN_CMD CMD56 +#define CMD_SET_BUS_WIDTH ACMD6 +#define CMD_SD_STATUS ACMD13 +#define CMD_SD_SEND_OP_COND ACMD41 +#define CMD_SET_CLR_CARD_DETECT ACMD42 +#define CMD_SEND_SCR ACMD51 + +/* MMC card spec version */ +#define MMC_CARD_VERSION_1_2 0 +#define MMC_CARD_VERSION_1_4 1 +#define MMC_CARD_VERSION_2_X 2 +#define MMC_CARD_VERSION_3_X 3 +#define MMC_CARD_VERSION_4_X 4 + +/* SD Card Spec Version */ +/* May need to add version 3 here? */ +#define SD_CARD_VERSION_1_0 0 +#define SD_CARD_VERSION_1_10 1 +#define SD_CARD_VERSION_2_0 2 + +/* card types */ +#define MMC_CARD 0 +#define SD_CARD 1 +#define NOT_SD_CARD MMC_CARD + +/* Card rca */ +#define SD_MMC_CARD_RCA 0x1 +#define BLOCK_LEN_512 512 + +/* card state */ +#define STATE_IDLE 0 +#define STATE_READY 1 +#define STATE_IDENT 2 +#define STATE_STBY 3 +#define STATE_TRAN 4 +#define STATE_DATA 5 +#define STATE_RCV 6 +#define STATE_PRG 7 +#define STATE_DIS 8 + +/* Card OCR register */ +/* VDD voltage window 1,65 to 1.95 */ +#define MMC_OCR_VDD_165_195 0x00000080 +/* VDD voltage window 2.7-2.8 */ +#define MMC_OCR_VDD_FF8 0x00FF8000 +#define MMC_OCR_CCS 0x40000000/* Card Capacity */ +#define MMC_OCR_BUSY 0x80000000/* busy bit */ +#define SD_OCR_HCS 0x40000000/* High capacity host */ +#define MMC_OCR_SECTOR_MODE 0x40000000/* Access Mode as Sector */ + +/* mmc Switch function */ +#define SET_EXT_CSD_HS_TIMING 0x03B90100/* set High speed */ + +/* check supports switching or not */ +#define SD_SWITCH_FUNC_CHECK_MODE 0x00FFFFF1 +#define SD_SWITCH_FUNC_SWITCH_MODE 0x80FFFFF1/* switch */ +#define SD_SWITCH_FUNC_HIGH_SPEED 0x02/* HIGH SPEED FUNC */ +#define SWITCH_ERROR 0x00000080 + +/* errors in sending commands */ +#define RESP_TIMEOUT 0x1 +#define COMMAND_ERROR 0x2 +/* error in response */ +#define R1_ERROR (1 << 19) +#define R1_CURRENT_STATE(x) (((x) & 0x00001E00) >> 9) + +/* Host Controller Capabilities */ +#define ESDHC_HOSTCAPBLT_DMAS (0x00400000) + + +/* SD/MMC memory map */ +struct esdhc_regs { + uint32_t dsaddr; /* dma system address */ + uint32_t blkattr; /* Block attributes */ + uint32_t cmdarg; /* Command argument */ + uint32_t xfertyp; /* Command transfer type */ + uint32_t cmdrsp[4]; /* Command response0,1,2,3 */ + uint32_t datport; /* Data buffer access port */ + uint32_t prsstat; /* Present state */ + uint32_t proctl; /* Protocol control */ + uint32_t sysctl; /* System control */ + uint32_t irqstat; /* Interrupt status */ + uint32_t irqstaten; /* Interrupt status enable */ + uint32_t irqsigen; /* Interrupt signal enable */ + uint32_t autoc12err; /* Auto CMD12 status */ + uint32_t hostcapblt; /* Host controller capabilities */ + uint32_t wml; /* Watermark level */ + uint32_t res1[2]; + uint32_t fevt; /* Force event */ + uint32_t res2; + uint32_t adsaddrl; + uint32_t adsaddrh; + uint32_t res3[39]; + uint32_t hostver; /* Host controller version */ + uint32_t res4; + uint32_t dmaerr; /* DMA error address */ + uint32_t dmaerrh; /* DMA error address high */ + uint32_t dmaerrattr; /* DMA error atrribute */ + uint32_t res5; + uint32_t hostcapblt2;/* Host controller capabilities2 */ + uint32_t res6[2]; + uint32_t tcr; /* Tuning control */ + uint32_t res7[7]; + uint32_t dirctrl; /* Direction control */ + uint32_t ccr; /* Clock control */ + uint32_t res8[177]; + uint32_t ctl; /* Control register */ +}; + +/* SD/MMC card attributes */ +struct card_attributes { + uint32_t type; /* sd or mmc card */ + uint32_t version; /* version */ + uint32_t block_len; /* block length */ + uint32_t bus_freq; /* sdhc bus frequency */ + uint16_t rca; /* relative card address */ + uint8_t is_high_capacity; /* high capacity */ +}; + +struct mmc { + struct esdhc_regs *esdhc_regs; + struct card_attributes card; + + uint32_t block_len; + uint32_t voltages_caps; /* supported voltaes */ + uint32_t dma_support; /* DMA support */ +}; + +enum cntrl_num { + SDHC1 = 0, + SDHC2 +}; + +int sd_emmc_init(uintptr_t *block_dev_spec, + uintptr_t nxp_esdhc_addr, + size_t nxp_sd_block_offset, + size_t nxp_sd_block_size, + bool card_detect); + +int esdhc_emmc_init(struct mmc *mmc, bool card_detect); +int esdhc_read(struct mmc *mmc, uint32_t src_offset, uintptr_t dst, + size_t size); +int esdhc_write(struct mmc *mmc, uintptr_t src, uint32_t dst_offset, + size_t size); + +#ifdef NXP_ESDHC_BE +#define esdhc_in32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_ESDHC_LE) +#define esdhc_in32(a) mmio_read_32((uintptr_t)(a)) +#define esdhc_out32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR ESDHC register endianness +#endif + +#endif /*SD_MMC_H*/ diff --git a/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h b/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h new file mode 100644 index 0000000..4455383 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h @@ -0,0 +1,86 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SNVS_H +#define SNVS_H + + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +struct snvs_regs { + uint32_t reserved1; + uint32_t hp_com; /* 0x04 SNVS_HP Command Register */ + uint32_t reserved2[3]; + uint32_t hp_stat; /* 0x14 SNVS_HP Status Register */ +}; + +#ifdef NXP_SNVS_BE +#define snvs_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32((v))) +#elif defined(NXP_SNVS_LE) +#define snvs_read32(a) mmio_read_32((uintptr_t)(a)) +#define snvs_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR SNVS register endianness +#endif + +void snvs_init(uintptr_t nxp_snvs_addr); +uint32_t get_snvs_state(void); +void transition_snvs_non_secure(void); +void transition_snvs_soft_fail(void); +uint32_t transition_snvs_trusted(void); +uint32_t transition_snvs_secure(void); + +uint32_t snvs_read_lp_gpr_bit(uint32_t offset, uint32_t bit_pos); +void snvs_write_lp_gpr_bit(uint32_t offset, uint32_t bit_pos, bool flag_val); + +void snvs_disable_zeroize_lp_gpr(void); + +#if defined(NXP_NV_SW_MAINT_LAST_EXEC_DATA) && defined(NXP_COINED_BB) +uint32_t snvs_read_app_data(void); +uint32_t snvs_read_app_data_bit(uint32_t bit_pos); +void snvs_clear_app_data(void); +void snvs_write_app_data_bit(uint32_t bit_pos); +#endif + +#endif /* __ASSEMBLER__ */ + +/* SSM_ST field in SNVS status reg */ +#define HPSTS_CHECK_SSM_ST 0x900 /* SNVS is in check state */ +#define HPSTS_NON_SECURE_SSM_ST 0xb00 /* SNVS is in non secure state */ +#define HPSTS_TRUST_SSM_ST 0xd00 /* SNVS is in trusted state */ +#define HPSTS_SECURE_SSM_ST 0xf00 /* SNVS is in secure state */ +#define HPSTS_SOFT_FAIL_SSM_ST 0x300 /* SNVS is in soft fail state */ +#define HPSTS_MASK_SSM_ST 0xf00 /* SSM_ST field mask in SNVS reg */ + +/* SNVS register bits */ +#define HPCOM_SW_SV 0x100 /* Security Violation bit */ +#define HPCOM_SW_FSV 0x200 /* Fatal Security Violation bit */ +#define HPCOM_SSM_ST 0x1 /* SSM_ST field in SNVS command reg */ +#define HPCOM_SSM_ST_DIS 0x2 /* Disable Secure to Trusted State */ +#define HPCOM_SSM_SFNS_DIS 0x4 /* Disable Soft Fail to Non-Secure */ + +#define NXP_LP_GPR0_OFFSET 0x90 +#define NXP_LPCR_OFFSET 0x38 +#define NXP_GPR_Z_DIS_BIT 24 + +#ifdef NXP_COINED_BB + +#ifndef NXP_APP_DATA_LP_GPR_OFFSET +#define NXP_APP_DATA_LP_GPR_OFFSET NXP_LP_GPR0_OFFSET +#endif + +#define NXP_LPGPR_ZEROTH_BIT 0 + +#endif /* NXP_COINED_BB */ + +#endif /* SNVS_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h b/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h new file mode 100644 index 0000000..e015318 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h @@ -0,0 +1,83 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#if !defined(FUSE_PROV_H) && defined(POLICY_FUSE_PROVISION) +#define FUSE_PROV_H + +#include +#include + +#define MASK_NONE U(0xFFFFFFFF) +#define ERROR_WRITE U(0xA) +#define ERROR_ALREADY_BLOWN U(0xB) + +/* Flag bit shifts */ +#define FLAG_POVDD_SHIFT U(0) +#define FLAG_SYSCFG_SHIFT U(1) +#define FLAG_SRKH_SHIFT U(2) +#define FLAG_MC_SHIFT U(3) +#define FLAG_DCV0_SHIFT U(4) +#define FLAG_DCV1_SHIFT U(5) +#define FLAG_DRV0_SHIFT U(6) +#define FLAG_DRV1_SHIFT U(7) +#define FLAG_OUID0_SHIFT U(8) +#define FLAG_OUID1_SHIFT U(9) +#define FLAG_OUID2_SHIFT U(10) +#define FLAG_OUID3_SHIFT U(11) +#define FLAG_OUID4_SHIFT U(12) +#define FLAG_DBG_LVL_SHIFT U(13) +#define FLAG_OTPMK_SHIFT U(16) +#define FLAG_OUID_MASK U(0x1F) +#define FLAG_DEBUG_MASK U(0xF) +#define FLAG_OTPMK_MASK U(0xF) + +/* OTPMK flag values */ +#define PROG_OTPMK_MIN U(0x0) +#define PROG_OTPMK_RANDOM U(0x1) +#define PROG_OTPMK_USER U(0x2) +#define PROG_OTPMK_RANDOM_MIN U(0x5) +#define PROG_OTPMK_USER_MIN U(0x6) +#define PROG_NO_OTPMK U(0x8) + +#define OTPMK_MIM_BITS_MASK U(0xF0000000) + +/* System configuration bit shifts */ +#define SCB_WP_SHIFT U(0) +#define SCB_ITS_SHIFT U(2) +#define SCB_NSEC_SHIFT U(4) +#define SCB_ZD_SHIFT U(5) +#define SCB_K0_SHIFT U(15) +#define SCB_K1_SHIFT U(14) +#define SCB_K2_SHIFT U(13) +#define SCB_K3_SHIFT U(12) +#define SCB_K4_SHIFT U(11) +#define SCB_K5_SHIFT U(10) +#define SCB_K6_SHIFT U(9) +#define SCB_FR0_SHIFT U(30) +#define SCB_FR1_SHIFT U(31) + +/* Fuse Header Structure */ +struct fuse_hdr_t { + uint8_t barker[4]; /* 0x00 Barker code */ + uint32_t flags; /* 0x04 Script flags */ + uint32_t povdd_gpio; /* 0x08 GPIO for POVDD */ + uint32_t otpmk[8]; /* 0x0C-0x2B OTPMK */ + uint32_t srkh[8]; /* 0x2C-0x4B SRKH */ + uint32_t oem_uid[5]; /* 0x4C-0x5F OEM unique id's */ + uint32_t dcv[2]; /* 0x60-0x67 Debug Challenge */ + uint32_t drv[2]; /* 0x68-0x6F Debug Response */ + uint32_t ospr1; /* 0x70 OSPR1 */ + uint32_t sc; /* 0x74 OSPR0 (System Configuration) */ + uint32_t reserved[2]; /* 0x78-0x7F Reserved */ +}; + +/* Function to do fuse provisioning */ +int provision_fuses(unsigned long long fuse_scr_addr, + bool en_povdd_status); + +#define EFUSE_POWERUP_DELAY_mSec U(25) +#endif /* FUSE_PROV_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h new file mode 100644 index 0000000..2cb4c7d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h @@ -0,0 +1,100 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SFP_H +#define SFP_H + +#include +#include + +/* SFP Configuration Register Offsets */ +#define SFP_INGR_OFFSET U(0x20) +#define SFP_SVHESR_OFFSET U(0x24) +#define SFP_SFPCR_OFFSET U(0x28) +#define SFP_VER_OFFSET U(0x38) + +/* SFP Hamming register masks for OTPMK and DRV */ +#define SFP_SVHESR_DRV_MASK U(0x7F) +#define SFP_SVHESR_OTPMK_MASK U(0x7FC00) + +/* SFP commands */ +#define SFP_INGR_READFB_CMD U(0x1) +#define SFP_INGR_PROGFB_CMD U(0x2) +#define SFP_INGR_ERROR_MASK U(0x100) + +/* SFPCR Masks */ +#define SFP_SFPCR_WD U(0x80000000) +#define SFP_SFPCR_WDL U(0x40000000) + +/* SFPCR Masks */ +#define SFP_SFPCR_WD U(0x80000000) +#define SFP_SFPCR_WDL U(0x40000000) + +#define SFP_FUSE_REGS_OFFSET U(0x200) + +#ifdef NXP_SFP_VER_3_4 +#define OSPR0_SC_MASK U(0xC000FE35) +#elif defined(NXP_SFP_VER_3_2) +#define OSPR0_SC_MASK U(0x0000E035) +#endif + +#if defined(NXP_SFP_VER_3_4) +#define OSPR_KEY_REVOC_SHIFT U(9) +#define OSPR_KEY_REVOC_MASK U(0x0000fe00) +#elif defined(NXP_SFP_VER_3_2) +#define OSPR_KEY_REVOC_SHIFT U(13) +#define OSPR_KEY_REVOC_MASK U(0x0000e000) +#endif /* NXP_SFP_VER_3_4 */ + +#define OSPR1_MC_MASK U(0xFFFF0000) +#define OSPR1_DBG_LVL_MASK U(0x00000007) + +#define OSPR_ITS_MASK U(0x00000004) +#define OSPR_WP_MASK U(0x00000001) + +#define MAX_OEM_UID U(5) +#define SRK_HASH_SIZE U(32) + +/* SFP CCSR Register Map */ +struct sfp_ccsr_regs_t { + uint32_t ospr; /* 0x200 OSPR0 */ + uint32_t ospr1; /* 0x204 OSPR1 */ + uint32_t dcv[2]; /* 0x208 Debug Challenge Value */ + uint32_t drv[2]; /* 0x210 Debug Response Value */ + uint32_t fswpr; /* 0x218 FSL Section Write Protect */ + uint32_t fsl_uid[2]; /* 0x21c FSL UID 0 */ + uint32_t isbcr; /* 0x224 ISBC Configuration */ + uint32_t fsspr[3]; /* 0x228 FSL Scratch Pad */ + uint32_t otpmk[8]; /* 0x234 OTPMK */ + uint32_t srk_hash[SRK_HASH_SIZE/sizeof(uint32_t)]; + /* 0x254 Super Root Key Hash */ + uint32_t oem_uid[MAX_OEM_UID]; /* 0x274 OEM UID 0 */ +}; + +uintptr_t get_sfp_addr(void); +void sfp_init(uintptr_t nxp_sfp_addr); +uint32_t *get_sfp_srk_hash(void); +int sfp_check_its(void); +int sfp_check_oem_wp(void); +uint32_t get_key_revoc(void); +void set_sfp_wr_disable(void); +int sfp_program_fuses(void); + +uint32_t sfp_read_oem_uid(uint8_t oem_uid); +uint32_t sfp_write_oem_uid(uint8_t oem_uid, uint32_t sfp_val); + +#ifdef NXP_SFP_BE +#define sfp_read32(a) bswap32(mmio_read_32((uintptr_t)(a))) +#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), bswap32(v)) +#elif defined(NXP_SFP_LE) +#define sfp_read32(a) mmio_read_32((uintptr_t)(a)) +#define sfp_write32(a, v) mmio_write_32((uintptr_t)(a), (v)) +#else +#error Please define CCSR SFP register endianness +#endif + +#endif/* SFP_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h new file mode 100644 index 0000000..7be7a27 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h @@ -0,0 +1,40 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef SFP_ERROR_CODES_H +#define SFP_ERROR_CODES_H + + /* Error codes */ +#define ERROR_FUSE_BARKER 0x1 +#define ERROR_READFB_CMD 0x2 +#define ERROR_PROGFB_CMD 0x3 +#define ERROR_SRKH_ALREADY_BLOWN 0x4 +#define ERROR_SRKH_WRITE 0x5 +#define ERROR_OEMUID_ALREADY_BLOWN 0x6 +#define ERROR_OEMUID_WRITE 0x7 +#define ERROR_DCV_ALREADY_BLOWN 0x8 +#define ERROR_DCV_WRITE 0x9 +#define ERROR_DRV_ALREADY_BLOWN 0xa +#define ERROR_DRV_HAMMING_ERROR 0xb +#define ERROR_DRV_WRITE 0x18 +#define ERROR_OTPMK_ALREADY_BLOWN 0xc +#define ERROR_OTPMK_HAMMING_ERROR 0xd +#define ERROR_OTPMK_USER_MIN 0xe +#define ERROR_OSPR1_ALREADY_BLOWN 0xf +#define ERROR_OSPR1_WRITE 0x10 +#define ERROR_SC_ALREADY_BLOWN 0x11 +#define ERROR_SC_WRITE 0x12 +#define ERROR_POVDD_GPIO_FAIL 0x13 +#define ERROR_GPIO_SET_FAIL 0x14 +#define ERROR_GPIO_RESET_FAIL 0x15 +#define ERROR_OTPMK_SEC_DISABLED 0x16 +#define ERROR_OTPMK_SEC_ERROR 0x17 +#define ERROR_OTPMK_WRITE 0x19 +#define PLAT_ERROR_ENABLE_POVDD 0x20 +#define PLAT_ERROR_DISABLE_POVDD 0x21 + +#endif /* SFP_ERROR_CODES_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h b/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h new file mode 100644 index 0000000..d64c33b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h @@ -0,0 +1,30 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef NXP_SMMU_H +#define NXP_SMMU_H + +#define SMMU_SCR0 (0x0) +#define SMMU_NSCR0 (0x400) + +#define SCR0_CLIENTPD_MASK 0x00000001 +#define SCR0_USFCFG_MASK 0x00000400 + +static inline void bypass_smmu(uintptr_t smmu_base_addr) +{ + uint32_t val; + + val = (mmio_read_32(smmu_base_addr + SMMU_SCR0) | SCR0_CLIENTPD_MASK) & + ~(SCR0_USFCFG_MASK); + mmio_write_32((smmu_base_addr + SMMU_SCR0), val); + + val = (mmio_read_32(smmu_base_addr + SMMU_NSCR0) | SCR0_CLIENTPD_MASK) & + ~(SCR0_USFCFG_MASK); + mmio_write_32((smmu_base_addr + SMMU_NSCR0), val); +} + +#endif diff --git a/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h b/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h new file mode 100644 index 0000000..280e5b2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h @@ -0,0 +1,35 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +# +#ifndef NXP_TIMER_H +#define NXP_TIMER_H + + /* System Counter Offset and Bit Mask */ +#define SYS_COUNTER_CNTCR_OFFSET 0x0 +#define SYS_COUNTER_CNTCR_EN 0x00000001 +#define CNTCR_EN_MASK 0x1 + +#ifndef __ASSEMBLER__ +uint64_t get_timer_val(uint64_t start); + +#ifdef IMAGE_BL31 +void ls_configure_sys_timer(uintptr_t ls_sys_timctl_base, + uint8_t ls_config_cntacr, + uint8_t plat_ls_ns_timer_frame_id); +void enable_init_timer(void); +#endif + +/* + * Initialise the nxp on-chip free rolling usec counter as the delay + * timer. + */ +void delay_timer_init(uintptr_t nxp_timer_addr); +void ls_bl31_timer_init(uintptr_t nxp_timer_addr); +#endif /* __ASSEMBLER__ */ + +#endif /* NXP_TIMER_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h new file mode 100644 index 0000000..08d2148 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h @@ -0,0 +1,47 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if !defined(PLAT_TZC380_H) && defined(IMAGE_BL2) +#define PLAT_TZC380_H + +#include + +/* Number of DRAM regions to be configured + * for the platform can be over-written. + * + * Array tzc400_reg_list too, needs be over-written + * if there is any changes to default DRAM region + * configuration. + */ +#ifndef MAX_NUM_TZC_REGION +/* 3 regions: + * Region 0(default), + * Region 1 (DRAM0, Secure Memory), + * Region 2 (DRAM0, Shared memory) + */ +#define MAX_NUM_TZC_REGION 3 +#define DEFAULT_TZASC_CONFIG 1 +#endif + +struct tzc380_reg { + unsigned int secure; + unsigned int enabled; + uint64_t addr; + uint64_t size; + unsigned int sub_mask; +}; + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc380_reg *tzc380_reg_list); + +int populate_tzc380_reg_list(struct tzc380_reg *tzc380_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz); + +#endif /* PLAT_TZC380_H */ diff --git a/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h new file mode 100644 index 0000000..1b8e3a4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h @@ -0,0 +1,55 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#if !defined(PLAT_TZC400_H) && defined(IMAGE_BL2) +#define PLAT_TZC400_H + +#include + +/* Structure to configure TZC Regions' boundaries and attributes. */ +struct tzc400_reg { + uint8_t reg_filter_en; + unsigned long long start_addr; + unsigned long long end_addr; + unsigned int sec_attr; + unsigned int nsaid_permissions; +}; + +#define TZC_REGION_NS_NONE 0x00000000U + +/* NXP Platforms do not support NS Access ID (NSAID) based non-secure access. + * Supports only non secure through generic NS ACCESS ID + */ +#define TZC_NS_ACCESS_ID 0xFFFFFFFFU + +/* Number of DRAM regions to be configured + * for the platform can be over-written. + * + * Array tzc400_reg_list too, needs be over-written + * if there is any changes to default DRAM region + * configuration. + */ +#ifndef MAX_NUM_TZC_REGION +/* 3 regions: + * Region 0(default), + * Region 1 (DRAM0, Secure Memory), + * Region 2 (DRAM0, Shared memory) + */ +#define MAX_NUM_TZC_REGION NUM_DRAM_REGIONS + 3 +#define DEFAULT_TZASC_CONFIG 1 +#endif + +void mem_access_setup(uintptr_t base, uint32_t total_regions, + struct tzc400_reg *tzc400_reg_list); +int populate_tzc400_reg_list(struct tzc400_reg *tzc400_reg_list, + int dram_idx, int list_idx, + uint64_t dram_start_addr, + uint64_t dram_size, + uint32_t secure_dram_sz, + uint32_t shrd_dram_sz); + +#endif /* PLAT_TZC400_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/efi.h b/arm-trusted-firmware/include/drivers/partition/efi.h new file mode 100644 index 0000000..e463f96 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/efi.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Linaro Limited + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#ifndef DRIVERS_PARTITION_EFI_H +#define DRIVERS_PARTITION_EFI_H + +#include + +#include + +#define EFI_NAMELEN 36 + +static inline int guidcmp(const void *g1, const void *g2) +{ + return memcmp(g1, g2, sizeof(struct efi_guid)); +} + +static inline void *guidcpy(void *dst, const void *src) +{ + return memcpy(dst, src, sizeof(struct efi_guid)); +} + +#define EFI_GUID(a, b, c, d0, d1, d2, d3, d4, d5, d6, d7) \ + { (a) & 0xffffffff, \ + (b) & 0xffff, \ + (c) & 0xffff, \ + { (d0), (d1), (d2), (d3), (d4), (d5), (d6), (d7) } } + +#define NULL_GUID \ + EFI_GUID(0x00000000, 0x0000, 0x0000, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00) + +#endif /* DRIVERS_PARTITION_EFI_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/gpt.h b/arm-trusted-firmware/include/drivers/partition/gpt.h new file mode 100644 index 0000000..c2a229e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/gpt.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_H +#define GPT_H + +#include +#include +#include + +#define PARTITION_TYPE_GPT 0xee +#define GPT_HEADER_OFFSET PLAT_PARTITION_BLOCK_SIZE +#define GPT_ENTRY_OFFSET (GPT_HEADER_OFFSET + \ + PLAT_PARTITION_BLOCK_SIZE) + +#define GPT_SIGNATURE "EFI PART" + +typedef struct gpt_entry { + struct efi_guid type_uuid; + struct efi_guid unique_uuid; + unsigned long long first_lba; + unsigned long long last_lba; + unsigned long long attr; + unsigned short name[EFI_NAMELEN]; +} gpt_entry_t; + +typedef struct gpt_header { + unsigned char signature[8]; + unsigned int revision; + unsigned int size; + unsigned int header_crc; + unsigned int reserved; + unsigned long long current_lba; + unsigned long long backup_lba; + unsigned long long first_lba; + unsigned long long last_lba; + struct efi_guid disk_uuid; + /* starting LBA of array of partition entries */ + unsigned long long part_lba; + /* number of partition entries in array */ + unsigned int list_num; + /* size of a single partition entry (usually 128) */ + unsigned int part_size; + unsigned int part_crc; +} gpt_header_t; + +int parse_gpt_entry(gpt_entry_t *gpt_entry, partition_entry_t *entry); + +#endif /* GPT_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/mbr.h b/arm-trusted-firmware/include/drivers/partition/mbr.h new file mode 100644 index 0000000..1452c02 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/mbr.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MBR_H +#define MBR_H + +#define MBR_OFFSET 0 + +#define MBR_PRIMARY_ENTRY_OFFSET 0x1be +#define MBR_PRIMARY_ENTRY_SIZE 0x10 +#define MBR_PRIMARY_ENTRY_NUMBER 4 +#define MBR_CHS_ADDRESS_LEN 3 + +#define MBR_SIGNATURE_FIRST 0x55 +#define MBR_SIGNATURE_SECOND 0xAA + +typedef struct mbr_entry { + unsigned char status; + unsigned char first_sector[MBR_CHS_ADDRESS_LEN]; + unsigned char type; + unsigned char last_sector[MBR_CHS_ADDRESS_LEN]; + unsigned int first_lba; + unsigned int sector_nums; +} mbr_entry_t; + +#endif /* MBR_H */ diff --git a/arm-trusted-firmware/include/drivers/partition/partition.h b/arm-trusted-firmware/include/drivers/partition/partition.h new file mode 100644 index 0000000..b292ec7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/partition/partition.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PARTITION_H +#define PARTITION_H + +#include + +#include +#include +#include + +#if !PLAT_PARTITION_MAX_ENTRIES +# define PLAT_PARTITION_MAX_ENTRIES 128 +#endif /* PLAT_PARTITION_MAX_ENTRIES */ + +CASSERT(PLAT_PARTITION_MAX_ENTRIES <= 128, assert_plat_partition_max_entries); + +#if !PLAT_PARTITION_BLOCK_SIZE +# define PLAT_PARTITION_BLOCK_SIZE 512 +#endif /* PLAT_PARTITION_BLOCK_SIZE */ + +CASSERT((PLAT_PARTITION_BLOCK_SIZE == 512) || + (PLAT_PARTITION_BLOCK_SIZE == 4096), + assert_plat_partition_block_size); + +#define LEGACY_PARTITION_BLOCK_SIZE 512 + +typedef struct partition_entry { + uint64_t start; + uint64_t length; + char name[EFI_NAMELEN]; + struct efi_guid part_guid; +} partition_entry_t; + +typedef struct partition_entry_list { + partition_entry_t list[PLAT_PARTITION_MAX_ENTRIES]; + int entry_count; +} partition_entry_list_t; + +int load_partition_table(unsigned int image_id); +const partition_entry_t *get_partition_entry(const char *name); +const partition_entry_t *get_partition_entry_by_uuid(const uuid_t *part_uuid); +const partition_entry_list_t *get_partition_entry_list(void); +void partition_init(unsigned int image_id); + +#endif /* PARTITION_H */ diff --git a/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h b/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h new file mode 100644 index 0000000..6de8fc7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Marvell Technology Group Ltd. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#ifndef __TRNG_IP_76_H__ +#define __TRNG_IP_76_H__ + +#include +#include + +int32_t eip76_rng_read_rand_buf(void *data, bool wait); +int32_t eip76_rng_probe(uintptr_t base_addr); +int32_t eip76_rng_get_random(uint8_t *data, uint32_t len); + +#endif /* __TRNG_IP_76_H__ */ diff --git a/arm-trusted-firmware/include/drivers/raw_nand.h b/arm-trusted-firmware/include/drivers/raw_nand.h new file mode 100644 index 0000000..7152300 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/raw_nand.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2019-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_RAW_NAND_H +#define DRIVERS_RAW_NAND_H + +#include +#include + +#include + +/* NAND ONFI default value mode 0 in picosecond */ +#define NAND_TADL_MIN 400000UL +#define NAND_TALH_MIN 20000UL +#define NAND_TALS_MIN 50000UL +#define NAND_TAR_MIN 25000UL +#define NAND_TCCS_MIN 500000UL +#define NAND_TCEA_MIN 100000UL +#define NAND_TCEH_MIN 20000UL +#define NAND_TCH_MIN 20000UL +#define NAND_TCHZ_MAX 100000UL +#define NAND_TCLH_MIN 20000UL +#define NAND_TCLR_MIN 20000UL +#define NAND_TCLS_MIN 50000UL +#define NAND_TCOH_MIN 0UL +#define NAND_TCS_MIN 70000UL +#define NAND_TDH_MIN 20000UL +#define NAND_TDS_MIN 40000UL +#define NAND_TFEAT_MAX 1000000UL +#define NAND_TIR_MIN 10000UL +#define NAND_TITC_MIN 1000000UL +#define NAND_TR_MAX 200000000UL +#define NAND_TRC_MIN 100000UL +#define NAND_TREA_MAX 40000UL +#define NAND_TREH_MIN 30000UL +#define NAND_TRHOH_MIN 0UL +#define NAND_TRHW_MIN 200000UL +#define NAND_TRHZ_MAX 200000UL +#define NAND_TRLOH_MIN 0UL +#define NAND_TRP_MIN 50000UL +#define NAND_TRR_MIN 40000UL +#define NAND_TRST_MAX 250000000000ULL +#define NAND_TWB_MAX 200000UL +#define NAND_TWC_MIN 100000UL +#define NAND_TWH_MIN 30000UL +#define NAND_TWHR_MIN 120000UL +#define NAND_TWP_MIN 50000UL +#define NAND_TWW_MIN 100000UL + +/* NAND request types */ +#define NAND_REQ_CMD 0x0000U +#define NAND_REQ_ADDR 0x1000U +#define NAND_REQ_DATAIN 0x2000U +#define NAND_REQ_DATAOUT 0x3000U +#define NAND_REQ_WAIT 0x4000U +#define NAND_REQ_MASK GENMASK(14, 12) +#define NAND_REQ_BUS_WIDTH_8 BIT(15) + +#define PARAM_PAGE_SIZE 256 + +/* NAND ONFI commands */ +#define NAND_CMD_READ_1ST 0x00U +#define NAND_CMD_CHANGE_1ST 0x05U +#define NAND_CMD_READID_SIG_ADDR 0x20U +#define NAND_CMD_READ_2ND 0x30U +#define NAND_CMD_STATUS 0x70U +#define NAND_CMD_READID 0x90U +#define NAND_CMD_CHANGE_2ND 0xE0U +#define NAND_CMD_READ_PARAM_PAGE 0xECU +#define NAND_CMD_RESET 0xFFU + +#define ONFI_REV_21 BIT(3) +#define ONFI_FEAT_BUS_WIDTH_16 BIT(0) +#define ONFI_FEAT_EXTENDED_PARAM BIT(7) + +/* NAND ECC type */ +#define NAND_ECC_NONE U(0) +#define NAND_ECC_HW U(1) +#define NAND_ECC_ONDIE U(2) + +/* NAND bus width */ +#define NAND_BUS_WIDTH_8 U(0) +#define NAND_BUS_WIDTH_16 U(1) + +struct nand_req { + struct nand_device *nand; + uint16_t type; + uint8_t *addr; + unsigned int length; + unsigned int delay_ms; + unsigned int inst_delay; +}; + +struct nand_param_page { + /* Rev information and feature block */ + uint32_t page_sig; + uint16_t rev; + uint16_t features; + uint16_t opt_cmd; + uint8_t jtg; + uint8_t train_cmd; + uint16_t ext_param_length; + uint8_t nb_param_pages; + uint8_t reserved1[17]; + /* Manufacturer information */ + uint8_t manufacturer[12]; + uint8_t model[20]; + uint8_t manufacturer_id; + uint16_t data_code; + uint8_t reserved2[13]; + /* Memory organization */ + uint32_t bytes_per_page; + uint16_t spare_per_page; + uint32_t bytes_per_partial; + uint16_t spare_per_partial; + uint32_t num_pages_per_blk; + uint32_t num_blk_in_lun; + uint8_t num_lun; + uint8_t num_addr_cycles; + uint8_t bit_per_cell; + uint16_t max_bb_per_lun; + uint16_t blk_endur; + uint8_t valid_blk_begin; + uint16_t blk_enbur_valid; + uint8_t nb_prog_page; + uint8_t partial_prog_attr; + uint8_t nb_ecc_bits; + uint8_t plane_addr; + uint8_t mplanes_ops; + uint8_t ez_nand; + uint8_t reserved3[12]; + /* Electrical parameters */ + uint8_t io_pin_cap_max; + uint16_t sdr_timing_mode; + uint16_t sdr_prog_cache_timing; + uint16_t tprog; + uint16_t tbers; + uint16_t tr; + uint16_t tccs; + uint8_t nvddr_timing_mode; + uint8_t nvddr2_timing_mode; + uint8_t nvddr_features; + uint16_t clk_input_cap_typ; + uint16_t io_pin_cap_typ; + uint16_t input_pin_cap_typ; + uint8_t input_pin_cap_max; + uint8_t drv_strength_support; + uint16_t tr_max; + uint16_t tadl; + uint16_t tr_typ; + uint8_t reserved4[6]; + /* Vendor block */ + uint16_t vendor_revision; + uint8_t vendor[88]; + uint16_t crc16; +} __packed; + +struct nand_ctrl_ops { + int (*exec)(struct nand_req *req); + void (*setup)(struct nand_device *nand); +}; + +struct rawnand_device { + struct nand_device *nand_dev; + const struct nand_ctrl_ops *ops; +}; + +int nand_raw_init(unsigned long long *size, unsigned int *erase_size); +int nand_wait_ready(unsigned int delay_ms); +int nand_read_page_cmd(unsigned int page, unsigned int offset, + uintptr_t buffer, unsigned int len); +int nand_change_read_column_cmd(unsigned int offset, uintptr_t buffer, + unsigned int len); +void nand_raw_ctrl_init(const struct nand_ctrl_ops *ops); + +/* + * Platform can implement this to override default raw NAND instance + * configuration. + * + * @device: target raw NAND instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_raw_nand_data(struct rawnand_device *device); + +#endif /* DRIVERS_RAW_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h b/arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h new file mode 100644 index 0000000..7d5b5d3 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015-2019, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RCAR_PRINTF_H +#define RCAR_PRINTF_H + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new rcar 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_rcar_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* RCAR_PRINTF_H */ diff --git a/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h b/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h new file mode 100644 index 0000000..7bb3ee2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_GPIO_H +#define RPI3_GPIO_H + +#include +#include + +void rpi3_gpio_init(void); +int rpi3_gpio_get_select(int gpio); +void rpi3_gpio_set_select(int gpio, int fsel); + +#define RPI3_GPIO_GPFSEL(n) ((n) * U(0x04)) +#define RPI3_GPIO_GPSET(n) (((n) * U(0x04)) + U(0x1C)) +#define RPI3_GPIO_GPCLR(n) (((n) * U(0x04)) + U(0x28)) +#define RPI3_GPIO_GPLEV(n) (((n) * U(0x04)) + U(0x34)) +#define RPI3_GPIO_GPPUD U(0x94) +#define RPI3_GPIO_GPPUDCLK(n) (((n) * U(0x04)) + U(0x98)) + +#define RPI3_GPIO_FUNC_INPUT U(0) +#define RPI3_GPIO_FUNC_OUTPUT U(1) +#define RPI3_GPIO_FUNC_ALT0 U(4) +#define RPI3_GPIO_FUNC_ALT1 U(5) +#define RPI3_GPIO_FUNC_ALT2 U(6) +#define RPI3_GPIO_FUNC_ALT3 U(7) +#define RPI3_GPIO_FUNC_ALT4 U(3) +#define RPI3_GPIO_FUNC_ALT5 U(2) + +#endif /* RPI3_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h b/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h new file mode 100644 index 0000000..c107440 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_MBOX_H +#define RPI3_MBOX_H + +#include + +/* This struct must be aligned to 16 bytes */ +typedef struct __packed __aligned(16) rpi3_mbox_request { + uint32_t size; /* Buffer size in bytes */ + uint32_t code; /* Request/response code */ + uint32_t tags[0]; +} rpi3_mbox_request_t; + +#define RPI3_MBOX_BUFFER_SIZE U(256) + +/* Constants to perform a request/check the status of a request. */ +#define RPI3_MBOX_PROCESS_REQUEST U(0x00000000) +#define RPI3_MBOX_REQUEST_SUCCESSFUL U(0x80000000) +#define RPI3_MBOX_REQUEST_ERROR U(0x80000001) + +/* Command constants */ +#define RPI3_TAG_HARDWARE_GET_BOARD_REVISION U(0x00010002) +#define RPI3_TAG_END U(0x00000000) + +#define RPI3_TAG_REQUEST U(0x00000000) +#define RPI3_TAG_IS_RESPONSE U(0x80000000) /* Set if response */ +#define RPI3_TAG_RESPONSE_LENGTH_MASK U(0x7FFFFFFF) + +#define RPI3_CHANNEL_ARM_TO_VC U(0x8) +#define RPI3_CHANNEL_MASK U(0xF) + +void rpi3_vc_mailbox_request_send(rpi3_mbox_request_t *req, int req_size); + +#endif diff --git a/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h b/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h new file mode 100644 index 0000000..ea5a677 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_RNG_H +#define RPI3_RNG_H + +void rpi3_rng_read(void *buf, size_t len); + +#endif diff --git a/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h b/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h new file mode 100644 index 0000000..1653240 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2019, Linaro Limited + * Copyright (c) 2019, Ying-Chun Liu (PaulLiu) + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RPI3_SDHOST_H +#define RPI3_SDHOST_H + +#include +#include +#include + +struct rpi3_sdhost_params { + uintptr_t reg_base; + uint32_t clk_rate; + uint32_t bus_width; + uint32_t flags; + uint32_t current_cmd; + uint8_t cmdbusy; + uint8_t mmc_app_cmd; + uint32_t ns_per_fifo_word; + + uint32_t sdcard_rca; + uint32_t gpio48_pinselect[6]; +}; + +void rpi3_sdhost_init(struct rpi3_sdhost_params *params, + struct mmc_device_info *mmc_dev_info); +void rpi3_sdhost_stop(void); + +/* Registers */ +#define HC_COMMAND 0x00 /* Command and flags */ +#define HC_ARGUMENT 0x04 +#define HC_TIMEOUTCOUNTER 0x08 +#define HC_CLOCKDIVISOR 0x0c +#define HC_RESPONSE_0 0x10 +#define HC_RESPONSE_1 0x14 +#define HC_RESPONSE_2 0x18 +#define HC_RESPONSE_3 0x1c +#define HC_HOSTSTATUS 0x20 +#define HC_POWER 0x30 +#define HC_DEBUG 0x34 +#define HC_HOSTCONFIG 0x38 +#define HC_BLOCKSIZE 0x3c +#define HC_DATAPORT 0x40 +#define HC_BLOCKCOUNT 0x50 + +/* Flags for HC_COMMAND register */ +#define HC_CMD_ENABLE 0x8000 +#define HC_CMD_FAILED 0x4000 +#define HC_CMD_BUSY 0x0800 +#define HC_CMD_RESPONSE_NONE 0x0400 +#define HC_CMD_RESPONSE_LONG 0x0200 +#define HC_CMD_WRITE 0x0080 +#define HC_CMD_READ 0x0040 +#define HC_CMD_COMMAND_MASK 0x003f + +#define HC_CLOCKDIVISOR_MAXVAL 0x07ff +#define HC_CLOCKDIVISOR_PREFERVAL 0x027b +#define HC_CLOCKDIVISOR_SLOWVAL 0x0148 +#define HC_CLOCKDIVISOR_STOPVAL 0x01fb + +/* Flags for HC_HOSTSTATUS register */ +#define HC_HSTST_HAVEDATA 0x0001 +#define HC_HSTST_ERROR_FIFO 0x0008 +#define HC_HSTST_ERROR_CRC7 0x0010 +#define HC_HSTST_ERROR_CRC16 0x0020 +#define HC_HSTST_TIMEOUT_CMD 0x0040 +#define HC_HSTST_TIMEOUT_DATA 0x0080 +#define HC_HSTST_INT_BLOCK 0x0200 +#define HC_HSTST_INT_BUSY 0x0400 + +#define HC_HSTST_RESET 0xffff + +#define HC_HSTST_MASK_ERROR_DATA (HC_HSTST_ERROR_FIFO | \ + HC_HSTST_ERROR_CRC7 | \ + HC_HSTST_ERROR_CRC16 | \ + HC_HSTST_TIMEOUT_DATA) + +#define HC_HSTST_MASK_ERROR_ALL (HC_HSTST_MASK_ERROR_DATA | \ + HC_HSTST_TIMEOUT_CMD) + +/* Flags for HC_HOSTCONFIG register */ +#define HC_HSTCF_INTBUS_WIDE 0x0002 +#define HC_HSTCF_EXTBUS_4BIT 0x0004 +#define HC_HSTCF_SLOW_CARD 0x0008 +#define HC_HSTCF_INT_DATA 0x0010 +#define HC_HSTCF_INT_BLOCK 0x0100 +#define HC_HSTCF_INT_BUSY 0x0400 + +/* Flags for HC_DEBUG register */ +#define HC_DBG_FIFO_THRESH_WRITE_SHIFT 9 +#define HC_DBG_FIFO_THRESH_READ_SHIFT 14 +#define HC_DBG_FIFO_THRESH_MASK 0x001f +#define HC_DBG_FSM_MASK 0xf +#define HC_DBG_FSM_IDENTMODE 0x0 +#define HC_DBG_FSM_DATAMODE 0x1 +#define HC_DBG_FSM_READDATA 0x2 +#define HC_DBG_FSM_WRITEDATA 0x3 +#define HC_DBG_FSM_READWAIT 0x4 +#define HC_DBG_FSM_READCRC 0x5 +#define HC_DBG_FSM_WRITECRC 0x6 +#define HC_DBG_FSM_WRITEWAIT1 0x7 +#define HC_DBG_FSM_POWERDOWN 0x8 +#define HC_DBG_FSM_POWERUP 0x9 +#define HC_DBG_FSM_WRITESTART1 0xa +#define HC_DBG_FSM_WRITESTART2 0xb +#define HC_DBG_FSM_GENPULSES 0xc +#define HC_DBG_FSM_WRITEWAIT2 0xd +#define HC_DBG_FSM_STARTPOWDOWN 0xf +#define HC_DBG_FORCE_DATA_MODE 0x40000 + +/* Settings */ +#define HC_FIFO_SIZE 16 +#define HC_FIFO_THRESH_READ 4 +#define HC_FIFO_THRESH_WRITE 4 + +#define HC_TIMEOUT_DEFAULT 0x00f00000 +#define HC_TIMEOUT_IDLE 0x00a00000 + +#endif /* RPI3_SDHOST_H */ diff --git a/arm-trusted-firmware/include/drivers/scmi-msg.h b/arm-trusted-firmware/include/drivers/scmi-msg.h new file mode 100644 index 0000000..a9a99cf --- /dev/null +++ b/arm-trusted-firmware/include/drivers/scmi-msg.h @@ -0,0 +1,207 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited + */ + +#ifndef SCMI_MSG_H +#define SCMI_MSG_H + +#include +#include +#include + +/* Minimum size expected for SMT based shared memory message buffers */ +#define SMT_BUF_SLOT_SIZE 128U + +/* A channel abstract a communication path between agent and server */ +struct scmi_msg_channel; + +/* + * struct scmi_msg_channel - Shared memory buffer for a agent-to-server channel + * + * @shm_addr: Address of the shared memory for the SCMI channel + * @shm_size: Byte size of the shared memory for the SCMI channel + * @busy: True when channel is busy, flase when channel is free + * @agent_name: Agent name, SCMI protocol exposes 16 bytes max, or NULL + */ +struct scmi_msg_channel { + uintptr_t shm_addr; + size_t shm_size; + bool busy; + const char *agent_name; +}; + +/* + * Initialize SMT memory buffer, called by platform at init for each + * agent channel using the SMT header format. + * + * @chan: Pointer to the channel shared memory to be initialized + */ +void scmi_smt_init_agent_channel(struct scmi_msg_channel *chan); + +/* + * Process SMT formatted message in a fastcall SMC execution context. + * Called by platform on SMC entry. When returning, output message is + * available in shared memory for agent to read the response. + * + * @agent_id: SCMI agent ID the SMT belongs to + */ +void scmi_smt_fastcall_smc_entry(unsigned int agent_id); + +/* + * Process SMT formatted message in a secure interrupt execution context. + * Called by platform interrupt handler. When returning, output message is + * available in shared memory for agent to read the response. + * + * @agent_id: SCMI agent ID the SMT belongs to + */ +void scmi_smt_interrupt_entry(unsigned int agent_id); + +/* Platform callback functions */ + +/* + * Return the SCMI channel related to an agent + * @agent_id: SCMI agent ID + * Return a pointer to channel on success, NULL otherwise + */ +struct scmi_msg_channel *plat_scmi_get_channel(unsigned int agent_id); + +/* + * Return how many SCMI protocols supported by the platform + * According to the SCMI specification, this function does not target + * a specific agent ID and shall return all platform known capabilities. + */ +size_t plat_scmi_protocol_count(void); + +/* + * Get the count and list of SCMI protocols (but base) supported for an agent + * + * @agent_id: SCMI agent ID + * Return a pointer to a null terminated array supported protocol IDs. + */ +const uint8_t *plat_scmi_protocol_list(unsigned int agent_id); + +/* Get the name of the SCMI vendor for the platform */ +const char *plat_scmi_vendor_name(void); + +/* Get the name of the SCMI sub-vendor for the platform */ +const char *plat_scmi_sub_vendor_name(void); + +/* Handlers for SCMI Clock protocol services */ + +/* + * Return number of clock controllers for an agent + * @agent_id: SCMI agent ID + * Return number of clock controllers + */ +size_t plat_scmi_clock_count(unsigned int agent_id); + +/* + * Get clock controller string ID (aka name) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return pointer to name or NULL + */ +const char *plat_scmi_clock_get_name(unsigned int agent_id, + unsigned int scmi_id); + +/* + * Get clock possible rate as an array of frequencies in Hertz. + * + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @rates: If NULL, function returns, else output rates array + * @nb_elts: Array size of @rates. + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_array(unsigned int agent_id, unsigned int scmi_id, + unsigned long *rates, size_t *nb_elts); + +/* + * Get clock possible rate as range with regular steps in Hertz + * + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @min_max_step: 3 cell array for min, max and step rate data + * Return an SCMI compliant error code + */ +int32_t plat_scmi_clock_rates_by_step(unsigned int agent_id, + unsigned int scmi_id, + unsigned long *min_max_step); + +/* + * Get clock rate in Hertz + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return clock rate or 0 if not supported + */ +unsigned long plat_scmi_clock_get_rate(unsigned int agent_id, + unsigned int scmi_id); + +/* + * Set clock rate in Hertz + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @rate: Target clock frequency in Hertz + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_rate(unsigned int agent_id, unsigned int scmi_id, + unsigned long rate); + +/* + * Get clock state (enabled or disabled) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * Return 1 if clock is enabled, 0 if disables, or a negative SCMI error code + */ +int32_t plat_scmi_clock_get_state(unsigned int agent_id, unsigned int scmi_id); + +/* + * Get clock state (enabled or disabled) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI clock ID + * @enable_not_disable: Enable clock if true, disable clock otherwise + * Return a compliant SCMI error code + */ +int32_t plat_scmi_clock_set_state(unsigned int agent_id, unsigned int scmi_id, + bool enable_not_disable); + +/* Handlers for SCMI Reset Domain protocol services */ + +/* + * Return number of reset domains for the agent + * @agent_id: SCMI agent ID + * Return number of reset domains + */ +size_t plat_scmi_rstd_count(unsigned int agent_id); + +/* + * Get reset domain string ID (aka name) + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * Return pointer to name or NULL + */ +const char *plat_scmi_rstd_get_name(unsigned int agent_id, unsigned int scmi_id); + +/* + * Perform a reset cycle on a target reset domain + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * @state: Target reset state (see SCMI specification, 0 means context loss) + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rstd_autonomous(unsigned int agent_id, unsigned int scmi_id, + unsigned int state); + +/* + * Assert or deassert target reset domain + * @agent_id: SCMI agent ID + * @scmi_id: SCMI reset domain ID + * @assert_not_deassert: Assert domain if true, otherwise deassert domain + * Return a compliant SCMI error code + */ +int32_t plat_scmi_rstd_set_state(unsigned int agent_id, unsigned int scmi_id, + bool assert_not_deassert); + +#endif /* SCMI_MSG_H */ diff --git a/arm-trusted-firmware/include/drivers/scmi.h b/arm-trusted-firmware/include/drivers/scmi.h new file mode 100644 index 0000000..ac5dc38 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/scmi.h @@ -0,0 +1,29 @@ +/* SPDX-License-Identifier: BSD-3-Clause */ +/* + * Copyright (c) 2015-2019, Arm Limited and Contributors. All rights reserved. + */ +#ifndef SCMI_MSG_SCMI_H +#define SCMI_MSG_SCMI_H + +#define SCMI_PROTOCOL_ID_BASE 0x10U +#define SCMI_PROTOCOL_ID_POWER_DOMAIN 0x11U +#define SCMI_PROTOCOL_ID_SYS_POWER 0x12U +#define SCMI_PROTOCOL_ID_PERF 0x13U +#define SCMI_PROTOCOL_ID_CLOCK 0x14U +#define SCMI_PROTOCOL_ID_SENSOR 0x15U +#define SCMI_PROTOCOL_ID_RESET_DOMAIN 0x16U + +/* SCMI error codes reported to agent through server-to-agent messages */ +#define SCMI_SUCCESS 0 +#define SCMI_NOT_SUPPORTED (-1) +#define SCMI_INVALID_PARAMETERS (-2) +#define SCMI_DENIED (-3) +#define SCMI_NOT_FOUND (-4) +#define SCMI_OUT_OF_RANGE (-5) +#define SCMI_BUSY (-6) +#define SCMI_COMMS_ERROR (-7) +#define SCMI_GENERIC_ERROR (-8) +#define SCMI_HARDWARE_ERROR (-9) +#define SCMI_PROTOCOL_ERROR (-10) + +#endif /* SCMI_MSG_SCMI_H */ diff --git a/arm-trusted-firmware/include/drivers/spi_mem.h b/arm-trusted-firmware/include/drivers/spi_mem.h new file mode 100644 index 0000000..d1953ac --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_mem.h @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_MEM_H +#define DRIVERS_SPI_MEM_H + +#include +#include +#include + +#define SPI_MEM_BUSWIDTH_1_LINE 1U +#define SPI_MEM_BUSWIDTH_2_LINE 2U +#define SPI_MEM_BUSWIDTH_4_LINE 4U + +/* + * enum spi_mem_data_dir - Describes the direction of a SPI memory data + * transfer from the controller perspective. + * @SPI_MEM_DATA_IN: data coming from the SPI memory. + * @SPI_MEM_DATA_OUT: data sent to the SPI memory. + */ +enum spi_mem_data_dir { + SPI_MEM_DATA_IN, + SPI_MEM_DATA_OUT, +}; + +/* + * struct spi_mem_op - Describes a SPI memory operation. + * + * @cmd.buswidth: Number of IO lines used to transmit the command. + * @cmd.opcode: Operation opcode. + * @addr.nbytes: Number of address bytes to send. Can be zero if the operation + * does not need to send an address. + * @addr.buswidth: Number of IO lines used to transmit the address. + * @addr.val: Address value. This value is always sent MSB first on the bus. + * Note that only @addr.nbytes are taken into account in this + * address value, so users should make sure the value fits in the + * assigned number of bytes. + * @dummy.nbytes: Number of dummy bytes to send after an opcode or address. Can + * be zero if the operation does not require dummy bytes. + * @dummy.buswidth: Number of IO lines used to transmit the dummy bytes. + * @data.buswidth: Number of IO lines used to send/receive the data. + * @data.dir: Direction of the transfer. + * @data.nbytes: Number of data bytes to transfer. + * @data.buf: Input or output data buffer depending on data::dir. + */ +struct spi_mem_op { + struct { + uint8_t buswidth; + uint8_t opcode; + } cmd; + + struct { + uint8_t nbytes; + uint8_t buswidth; + uint64_t val; + } addr; + + struct { + uint8_t nbytes; + uint8_t buswidth; + } dummy; + + struct { + uint8_t buswidth; + enum spi_mem_data_dir dir; + unsigned int nbytes; + void *buf; + } data; +}; + +/* SPI mode flags */ +#define SPI_CPHA BIT(0) /* clock phase */ +#define SPI_CPOL BIT(1) /* clock polarity */ +#define SPI_CS_HIGH BIT(2) /* CS active high */ +#define SPI_LSB_FIRST BIT(3) /* per-word bits-on-wire */ +#define SPI_3WIRE BIT(4) /* SI/SO signals shared */ +#define SPI_PREAMBLE BIT(5) /* Skip preamble bytes */ +#define SPI_TX_DUAL BIT(6) /* transmit with 2 wires */ +#define SPI_TX_QUAD BIT(7) /* transmit with 4 wires */ +#define SPI_RX_DUAL BIT(8) /* receive with 2 wires */ +#define SPI_RX_QUAD BIT(9) /* receive with 4 wires */ + +struct spi_bus_ops { + /* + * Claim the bus and prepare it for communication. + * + * @cs: The chip select. + * Returns: 0 if the bus was claimed successfully, or a negative value + * if it wasn't. + */ + int (*claim_bus)(unsigned int cs); + + /* + * Release the SPI bus. + */ + void (*release_bus)(void); + + /* + * Set transfer speed. + * + * @hz: The transfer speed in Hertz. + * Returns: 0 on success, a negative error code otherwise. + */ + int (*set_speed)(unsigned int hz); + + /* + * Set the SPI mode/flags. + * + * @mode: Requested SPI mode (SPI_... flags). + * Returns: 0 on success, a negative error code otherwise. + */ + int (*set_mode)(unsigned int mode); + + /* + * Execute a SPI memory operation. + * + * @op: The memory operation to execute. + * Returns: 0 on success, a negative error code otherwise. + */ + int (*exec_op)(const struct spi_mem_op *op); +}; + +int spi_mem_exec_op(const struct spi_mem_op *op); +int spi_mem_init_slave(void *fdt, int bus_node, + const struct spi_bus_ops *ops); + +#endif /* DRIVERS_SPI_MEM_H */ diff --git a/arm-trusted-firmware/include/drivers/spi_nand.h b/arm-trusted-firmware/include/drivers/spi_nand.h new file mode 100644 index 0000000..40e2063 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_nand.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_NAND_H +#define DRIVERS_SPI_NAND_H + +#include +#include + +#define SPI_NAND_OP_GET_FEATURE 0x0FU +#define SPI_NAND_OP_SET_FEATURE 0x1FU +#define SPI_NAND_OP_READ_ID 0x9FU +#define SPI_NAND_OP_LOAD_PAGE 0x13U +#define SPI_NAND_OP_RESET 0xFFU +#define SPI_NAND_OP_READ_FROM_CACHE 0x03U +#define SPI_NAND_OP_READ_FROM_CACHE_2X 0x3BU +#define SPI_NAND_OP_READ_FROM_CACHE_4X 0x6BU + +/* Configuration register */ +#define SPI_NAND_REG_CFG 0xB0U +#define SPI_NAND_CFG_ECC_EN BIT(4) +#define SPI_NAND_CFG_QE BIT(0) + +/* Status register */ +#define SPI_NAND_REG_STATUS 0xC0U +#define SPI_NAND_STATUS_BUSY BIT(0) +#define SPI_NAND_STATUS_ECC_UNCOR BIT(5) + +struct spinand_device { + struct nand_device *nand_dev; + struct spi_mem_op spi_read_cache_op; + uint8_t cfg_cache; /* Cached value of SPI NAND device register CFG */ +}; + +int spi_nand_init(unsigned long long *size, unsigned int *erase_size); + +/* + * Platform can implement this to override default SPI-NAND instance + * configuration. + * + * @device: target SPI-NAND instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_spi_nand_data(struct spinand_device *device); + +#endif /* DRIVERS_SPI_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/spi_nor.h b/arm-trusted-firmware/include/drivers/spi_nor.h new file mode 100644 index 0000000..72cfe5b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/spi_nor.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_SPI_NOR_H +#define DRIVERS_SPI_NOR_H + +#include + +/* OPCODE */ +#define SPI_NOR_OP_WREN 0x06U /* Write enable */ +#define SPI_NOR_OP_WRSR 0x01U /* Write status register 1 byte */ +#define SPI_NOR_OP_READ_ID 0x9FU /* Read JEDEC ID */ +#define SPI_NOR_OP_READ_CR 0x35U /* Read configuration register */ +#define SPI_NOR_OP_READ_SR 0x05U /* Read status register */ +#define SPI_NOR_OP_READ_FSR 0x70U /* Read flag status register */ +#define SPINOR_OP_RDEAR 0xC8U /* Read Extended Address Register */ +#define SPINOR_OP_WREAR 0xC5U /* Write Extended Address Register */ + +/* Used for Spansion flashes only. */ +#define SPINOR_OP_BRWR 0x17U /* Bank register write */ +#define SPINOR_OP_BRRD 0x16U /* Bank register read */ + +#define SPI_NOR_OP_READ 0x03U /* Read data bytes (low frequency) */ +#define SPI_NOR_OP_READ_FAST 0x0BU /* Read data bytes (high frequency) */ +#define SPI_NOR_OP_READ_1_1_2 0x3BU /* Read data bytes (Dual Output SPI) */ +#define SPI_NOR_OP_READ_1_2_2 0xBBU /* Read data bytes (Dual I/O SPI) */ +#define SPI_NOR_OP_READ_1_1_4 0x6BU /* Read data bytes (Quad Output SPI) */ +#define SPI_NOR_OP_READ_1_4_4 0xEBU /* Read data bytes (Quad I/O SPI) */ + +/* Flags for NOR specific configuration */ +#define SPI_NOR_USE_FSR BIT(0) +#define SPI_NOR_USE_BANK BIT(1) + +struct nor_device { + struct spi_mem_op read_op; + uint32_t size; + uint32_t flags; + uint8_t selected_bank; + uint8_t bank_write_cmd; + uint8_t bank_read_cmd; +}; + +int spi_nor_read(unsigned int offset, uintptr_t buffer, size_t length, + size_t *length_read); +int spi_nor_init(unsigned long long *device_size, unsigned int *erase_size); + +/* + * Platform can implement this to override default NOR instance configuration. + * + * @device: target NOR instance. + * Return 0 on success, negative value otherwise. + */ +int plat_get_nor_data(struct nor_device *device); + +#endif /* DRIVERS_SPI_NOR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/bsec.h b/arm-trusted-firmware/include/drivers/st/bsec.h new file mode 100644 index 0000000..60dcf3c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/bsec.h @@ -0,0 +1,129 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC_H +#define BSEC_H + +#include +#include + +#include + +/* + * IP configuration + */ +#define BSEC_OTP_MASK GENMASK(4, 0) +#define BSEC_OTP_BANK_SHIFT 5 +#define BSEC_TIMEOUT_VALUE 0xFFFF + +/* + * Return status + */ +#define BSEC_OK 0U +#define BSEC_ERROR 0xFFFFFFFFU +#define BSEC_DISTURBED 0xFFFFFFFEU +#define BSEC_INVALID_PARAM 0xFFFFFFFCU +#define BSEC_PROG_FAIL 0xFFFFFFFBU +#define BSEC_LOCK_FAIL 0xFFFFFFFAU +#define BSEC_TIMEOUT 0xFFFFFFF9U +#define BSEC_RETRY 0xFFFFFFF8U +#define BSEC_NOT_SUPPORTED 0xFFFFFFF7U +#define BSEC_WRITE_LOCKED 0xFFFFFFF6U +#define BSEC_ERROR_INVALID_FVR 0xFFFFFFF5U + +/* + * OTP MODE + */ +#define BSEC_MODE_OPEN1 0x00U +#define BSEC_MODE_SECURED 0x01U +#define BSEC_MODE_OPEN2 0x02U +#define BSEC_MODE_INVALID 0x04U + +/* + * OTP Lock services definition. + * Value must corresponding to the bit number in the register. + * Special case: (bit number << 1) for BSEC3. + */ +#define BSEC_LOCK_UPPER_OTP 0x00 +#define BSEC_LOCK_GWLOCK 0x01 +#define BSEC_LOCK_DEBUG 0x02 +#define BSEC_LOCK_PROGRAM 0x03 +#define BSEC_LOCK_KVLOCK 0x04 + +/* + * Values for struct bsec_config::freq + */ +#define FREQ_10_20_MHZ 0x0 +#define FREQ_20_30_MHZ 0x1 +#define FREQ_30_45_MHZ 0x2 +#define FREQ_45_67_MHZ 0x3 + +/* + * Device info structure, providing device-specific functions and a means of + * adding driver-specific state. + */ +struct bsec_config { + uint8_t den_lock; /* + * Debug enable sticky lock + * 1 debug enable is locked until next reset + */ + + /* BSEC2 only */ + uint8_t tread; /* SAFMEM Reading current level default 0 */ + uint8_t pulse_width; /* SAFMEM Programming pulse width default 1 */ + uint8_t freq; /* + * SAFMEM CLOCK see freq value define + * default FREQ_45_67_MHZ + */ + uint8_t power; /* Power up SAFMEM. 1 power up, 0 power off */ + uint8_t prog_lock; /* + * Programming Sticky lock + * 1 programming is locked until next reset + */ + uint8_t upper_otp_lock; /* + * Shadowing of upper OTP sticky lock + * 1 shadowing of upper OTP is locked + * until next reset + */ +}; + +uint32_t bsec_probe(void); +uint32_t bsec_get_base(void); + +uint32_t bsec_set_config(struct bsec_config *cfg); +uint32_t bsec_get_config(struct bsec_config *cfg); + +uint32_t bsec_shadow_register(uint32_t otp); +uint32_t bsec_read_otp(uint32_t *val, uint32_t otp); +uint32_t bsec_write_otp(uint32_t val, uint32_t otp); +uint32_t bsec_program_otp(uint32_t val, uint32_t otp); +uint32_t bsec_permanent_lock_otp(uint32_t otp); + +void bsec_write_debug_conf(uint32_t val); +uint32_t bsec_read_debug_conf(void); + +void bsec_write_scratch(uint32_t val); +uint32_t bsec_read_scratch(void); + +uint32_t bsec_get_status(void); +uint32_t bsec_get_hw_conf(void); +uint32_t bsec_get_version(void); +uint32_t bsec_get_id(void); +uint32_t bsec_get_magic_id(void); + +uint32_t bsec_set_sr_lock(uint32_t otp); +uint32_t bsec_read_sr_lock(uint32_t otp, bool *value); +uint32_t bsec_set_sw_lock(uint32_t otp); +uint32_t bsec_read_sw_lock(uint32_t otp, bool *value); +uint32_t bsec_set_sp_lock(uint32_t otp); +uint32_t bsec_read_sp_lock(uint32_t otp, bool *value); +uint32_t bsec_read_permanent_lock(uint32_t otp, bool *value); +uint32_t bsec_otp_lock(uint32_t service); + +uint32_t bsec_shadow_read_otp(uint32_t *otp_value, uint32_t word); +uint32_t bsec_check_nsec_access_rights(uint32_t otp); + +#endif /* BSEC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/bsec2_reg.h b/arm-trusted-firmware/include/drivers/st/bsec2_reg.h new file mode 100644 index 0000000..f895020 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/bsec2_reg.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BSEC2_REG_H +#define BSEC2_REG_H + +#include + +/* IP configuration */ +#define ADDR_LOWER_OTP_PERLOCK_SHIFT 0x03 +#define DATA_LOWER_OTP_PERLOCK_BIT 0x03U /* 2 significants bits are used */ +#define DATA_LOWER_OTP_PERLOCK_MASK GENMASK(2, 0) +#define ADDR_UPPER_OTP_PERLOCK_SHIFT 0x04 +#define DATA_UPPER_OTP_PERLOCK_BIT 0x01U /* 1 significants bits are used */ +#define DATA_UPPER_OTP_PERLOCK_MASK GENMASK(3, 0) + +/* BSEC REGISTER OFFSET (base relative) */ +#define BSEC_OTP_CONF_OFF U(0x000) +#define BSEC_OTP_CTRL_OFF U(0x004) +#define BSEC_OTP_WRDATA_OFF U(0x008) +#define BSEC_OTP_STATUS_OFF U(0x00C) +#define BSEC_OTP_LOCK_OFF U(0x010) +#define BSEC_DEN_OFF U(0x014) +#define BSEC_DISTURBED_OFF U(0x01C) +#define BSEC_DISTURBED1_OFF U(0x020) +#define BSEC_DISTURBED2_OFF U(0x024) +#define BSEC_ERROR_OFF U(0x034) +#define BSEC_ERROR1_OFF U(0x038) +#define BSEC_ERROR2_OFF U(0x03C) +#define BSEC_WRLOCK_OFF U(0x04C) /* Safmem permanent lock */ +#define BSEC_WRLOCK1_OFF U(0x050) +#define BSEC_WRLOCK2_OFF U(0x054) +#define BSEC_SPLOCK_OFF U(0x064) /* Program safmem sticky lock */ +#define BSEC_SPLOCK1_OFF U(0x068) +#define BSEC_SPLOCK2_OFF U(0x06C) +#define BSEC_SWLOCK_OFF U(0x07C) /* Write in OTP sticky lock */ +#define BSEC_SWLOCK1_OFF U(0x080) +#define BSEC_SWLOCK2_OFF U(0x084) +#define BSEC_SRLOCK_OFF U(0x094) /* Shadowing sticky lock */ +#define BSEC_SRLOCK1_OFF U(0x098) +#define BSEC_SRLOCK2_OFF U(0x09C) +#define BSEC_JTAG_IN_OFF U(0x0AC) +#define BSEC_JTAG_OUT_OFF U(0x0B0) +#define BSEC_SCRATCH_OFF U(0x0B4) +#define BSEC_OTP_DATA_OFF U(0x200) +#define BSEC_IPHW_CFG_OFF U(0xFF0) +#define BSEC_IPVR_OFF U(0xFF4) +#define BSEC_IP_ID_OFF U(0xFF8) +#define BSEC_IP_MAGIC_ID_OFF U(0xFFC) + +#define BSEC_WRLOCK(n) (BSEC_WRLOCK_OFF + U(0x04) * (n)) +#define BSEC_SPLOCK(n) (BSEC_SPLOCK_OFF + U(0x04) * (n)) +#define BSEC_SWLOCK(n) (BSEC_SWLOCK_OFF + U(0x04) * (n)) +#define BSEC_SRLOCK(n) (BSEC_SRLOCK_OFF + U(0x04) * (n)) + +/* BSEC_CONFIGURATION Register */ +#define BSEC_CONF_POWER_UP_MASK BIT(0) +#define BSEC_CONF_POWER_UP_SHIFT 0 +#define BSEC_CONF_FRQ_MASK GENMASK(2, 1) +#define BSEC_CONF_FRQ_SHIFT 1 +#define BSEC_CONF_PRG_WIDTH_MASK GENMASK(6, 3) +#define BSEC_CONF_PRG_WIDTH_SHIFT 3 +#define BSEC_CONF_TREAD_MASK GENMASK(8, 7) +#define BSEC_CONF_TREAD_SHIFT 7 + +/* BSEC_CONTROL Register */ +#define BSEC_READ 0U +#define BSEC_WRITE BIT(8) +#define BSEC_LOCK BIT(9) + +/* BSEC_OTP_LOCK register */ +#define UPPER_OTP_LOCK_MASK BIT(0) +#define UPPER_OTP_LOCK_SHIFT 0 +#define DENREG_LOCK_MASK BIT(2) +#define DENREG_LOCK_SHIFT 2 +#define GPLOCK_LOCK_MASK BIT(4) +#define GPLOCK_LOCK_SHIFT 4 + +/* BSEC_OTP_STATUS Register */ +#define BSEC_MODE_STATUS_MASK GENMASK(2, 0) +#define BSEC_MODE_SECURE_MASK BIT(0) +#define BSEC_MODE_FULLDBG_MASK BIT(1) +#define BSEC_MODE_INVALID_MASK BIT(2) +#define BSEC_MODE_BUSY_MASK BIT(3) +#define BSEC_MODE_PROGFAIL_MASK BIT(4) +#define BSEC_MODE_PWR_MASK BIT(5) +#define BSEC_MODE_BIST1_LOCK_MASK BIT(6) +#define BSEC_MODE_BIST2_LOCK_MASK BIT(7) + +/* BSEC_DENABLE Register */ +#define BSEC_HDPEN BIT(4) +#define BSEC_SPIDEN BIT(5) +#define BSEC_SPINDEN BIT(6) +#define BSEC_DBGSWGEN BIT(10) +#define BSEC_DEN_ALL_MSK GENMASK(10, 0) + +/* BSEC_FENABLE Register */ +#define BSEC_FEN_ALL_MSK GENMASK(14, 0) + +/* BSEC_IPVR Register */ +#define BSEC_IPVR_MSK GENMASK(7, 0) + +#endif /* BSEC2_REG_H */ diff --git a/arm-trusted-firmware/include/drivers/st/etzpc.h b/arm-trusted-firmware/include/drivers/st/etzpc.h new file mode 100644 index 0000000..4cd2b4e --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/etzpc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DRIVERS_ST_ETZPC_H +#define DRIVERS_ST_ETZPC_H + +#include +#include + +/* Define security level for each peripheral (DECPROT) */ +enum etzpc_decprot_attributes { + ETZPC_DECPROT_S_RW = 0, + ETZPC_DECPROT_NS_R_S_W = 1, + ETZPC_DECPROT_MCU_ISOLATION = 2, + ETZPC_DECPROT_NS_RW = 3, + ETZPC_DECPROT_MAX = 4, +}; + +void etzpc_configure_decprot(uint32_t decprot_id, + enum etzpc_decprot_attributes decprot_attr); +enum etzpc_decprot_attributes etzpc_get_decprot(uint32_t decprot_id); +void etzpc_lock_decprot(uint32_t decprot_id); + +void etzpc_configure_tzma(uint32_t tzma_id, uint16_t tzma_value); +uint16_t etzpc_get_tzma(uint32_t tzma_id); +void etzpc_lock_tzma(uint32_t tzma_id); +bool etzpc_get_lock_tzma(uint32_t tzma_id); + +uint8_t etzpc_get_num_per_sec(void); +uint8_t etzpc_get_revision(void); +uintptr_t etzpc_get_base_address(void); + +int etzpc_init(void); + +#endif /* DRIVERS_ST_ETZPC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/io_mmc.h b/arm-trusted-firmware/include/drivers/st/io_mmc.h new file mode 100644 index 0000000..6179e89 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/io_mmc.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_MMC_H +#define IO_MMC_H + +#include + +struct io_mmc_dev_spec { + bool use_boot_part; +}; + +int register_io_dev_mmc(const io_dev_connector_t **dev_con); + +#endif /* IO_MMC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/io_stm32image.h b/arm-trusted-firmware/include/drivers/st/io_stm32image.h new file mode 100644 index 0000000..f9fa363 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/io_stm32image.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IO_STM32IMAGE_H +#define IO_STM32IMAGE_H + +#include +#include + +#define MAX_LBA_SIZE 512 +#define MAX_PART_NAME_SIZE (EFI_NAMELEN + 1) +#define STM32_PART_NUM (PLAT_PARTITION_MAX_ENTRIES - STM32_TF_A_COPIES) + +struct stm32image_part_info { + char name[MAX_PART_NAME_SIZE]; + uint32_t binary_type; + uintptr_t part_offset; + uint32_t bkp_offset; +}; + +struct stm32image_device_info { + struct stm32image_part_info part_info[STM32_PART_NUM]; + unsigned long long device_size; + uint32_t lba_size; +}; + +int register_io_dev_stm32image(const io_dev_connector_t **dev_con); + +#endif /* IO_STM32IMAGE_H */ diff --git a/arm-trusted-firmware/include/drivers/st/regulator.h b/arm-trusted-firmware/include/drivers/st/regulator.h new file mode 100644 index 0000000..bf583e2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/regulator.h @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef REGULATOR_H +#define REGULATOR_H + +#include + +#ifndef PLAT_NB_RDEVS +#error "Missing PLAT_NB_RDEVS" +#endif + +/* + * Consumer interface + */ + +/* regulator-always-on : regulator should never be disabled */ +#define REGUL_ALWAYS_ON BIT(0) +/* + * regulator-boot-on: + * It's expected that this regulator was left on by the bootloader. + * The core shouldn't prevent it from being turned off later. + * The regulator is needed to exit from suspend so it is turned on during suspend entry. + */ +#define REGUL_BOOT_ON BIT(1) +/* regulator-over-current-protection: Enable over current protection. */ +#define REGUL_OCP BIT(2) +/* regulator-active-discharge: enable active discharge. */ +#define REGUL_ACTIVE_DISCHARGE BIT(3) +/* regulator-pull-down: Enable pull down resistor when the regulator is disabled. */ +#define REGUL_PULL_DOWN BIT(4) +/* + * st,mask-reset: set mask reset for the regulator, meaning that the regulator + * setting is maintained during pmic reset. + */ +#define REGUL_MASK_RESET BIT(5) +/* st,regulator-sink-source: set the regulator in sink source mode */ +#define REGUL_SINK_SOURCE BIT(6) +/* st,regulator-bypass: set the regulator in bypass mode */ +#define REGUL_ENABLE_BYPASS BIT(7) + +struct rdev *regulator_get_by_name(const char *node_name); + +struct rdev *regulator_get_by_supply_name(const void *fdt, int node, const char *name); + +int regulator_enable(struct rdev *rdev); +int regulator_disable(struct rdev *rdev); +int regulator_is_enabled(const struct rdev *rdev); + +int regulator_set_voltage(struct rdev *rdev, uint16_t volt); +int regulator_set_min_voltage(struct rdev *rdev); +int regulator_get_voltage(const struct rdev *rdev); + +int regulator_list_voltages(const struct rdev *rdev, const uint16_t **levels, size_t *count); +void regulator_get_range(const struct rdev *rdev, uint16_t *min_mv, uint16_t *max_mv); +int regulator_set_flag(struct rdev *rdev, uint16_t flag); + +/* + * Driver Interface + */ + +/* set_state() arguments */ +#define STATE_DISABLE false +#define STATE_ENABLE true + +struct regul_description { + const char *node_name; + const struct regul_ops *ops; + const void *driver_data; + const char *supply_name; + const uint32_t enable_ramp_delay; +}; + +struct regul_ops { + int (*set_state)(const struct regul_description *desc, bool state); + int (*get_state)(const struct regul_description *desc); + int (*set_voltage)(const struct regul_description *desc, uint16_t mv); + int (*get_voltage)(const struct regul_description *desc); + int (*list_voltages)(const struct regul_description *desc, + const uint16_t **levels, size_t *count); + int (*set_flag)(const struct regul_description *desc, uint16_t flag); + void (*lock)(const struct regul_description *desc); + void (*unlock)(const struct regul_description *desc); +}; + +int regulator_register(const struct regul_description *desc, int node); + +/* + * Internal regulator structure + * The structure is internal to the core, and the content should not be used + * by a consumer nor a driver. + */ +struct rdev { + const struct regul_description *desc; + + int32_t phandle; + + uint16_t min_mv; + uint16_t max_mv; + + uint16_t flags; + + uint32_t enable_ramp_delay; +}; + +#endif /* REGULATOR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/regulator_fixed.h b/arm-trusted-firmware/include/drivers/st/regulator_fixed.h new file mode 100644 index 0000000..b981262 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/regulator_fixed.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef REGULATOR_FIXED_H +#define REGULATOR_FIXED_H + +int fixed_regulator_register(void); + +#endif /* REGULATOR_FIXED_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_console.h b/arm-trusted-firmware/include/drivers/st/stm32_console.h new file mode 100644 index 0000000..8d9187d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_console.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_CONSOLE_H +#define STM32_CONSOLE_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new STM32 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_stm32_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* STM32_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h b/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h new file mode 100644 index 0000000..81d5b9d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32_FMC2_NAND_H +#define STM32_FMC2_NAND_H + +int stm32_fmc2_init(void); + +#endif /* STM32_FMC2_NAND_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_gpio.h b/arm-trusted-firmware/include/drivers/st/stm32_gpio.h new file mode 100644 index 0000000..eeef9da --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_gpio.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_GPIO_H +#define STM32_GPIO_H + +#include + +#define GPIO_MODE_OFFSET U(0x00) +#define GPIO_TYPE_OFFSET U(0x04) +#define GPIO_SPEED_OFFSET U(0x08) +#define GPIO_PUPD_OFFSET U(0x0C) +#define GPIO_OD_OFFSET U(0x14) +#define GPIO_BSRR_OFFSET U(0x18) +#define GPIO_AFRL_OFFSET U(0x20) +#define GPIO_AFRH_OFFSET U(0x24) +#define GPIO_SECR_OFFSET U(0x30) + +#define GPIO_ALT_LOWER_LIMIT U(0x08) + +#define GPIO_PIN_(_x) U(_x) +#define GPIO_PIN_MAX GPIO_PIN_(15) + +#define GPIO_ALTERNATE_(_x) U(_x) +#define GPIO_ALTERNATE_MASK U(0x0F) + +#define GPIO_MODE_INPUT U(0x00) +#define GPIO_MODE_OUTPUT U(0x01) +#define GPIO_MODE_ALTERNATE U(0x02) +#define GPIO_MODE_ANALOG U(0x03) +#define GPIO_MODE_MASK U(0x03) + +#define GPIO_TYPE_PUSH_PULL U(0x00) +#define GPIO_TYPE_OPEN_DRAIN U(0x01) +#define GPIO_TYPE_MASK U(0x01) + +#define GPIO_SPEED_LOW U(0x00) +#define GPIO_SPEED_MEDIUM U(0x01) +#define GPIO_SPEED_HIGH U(0x02) +#define GPIO_SPEED_VERY_HIGH U(0x03) +#define GPIO_SPEED_MASK U(0x03) + +#define GPIO_NO_PULL U(0x00) +#define GPIO_PULL_UP U(0x01) +#define GPIO_PULL_DOWN U(0x02) +#define GPIO_PULL_MASK U(0x03) + +#define GPIO_OD_OUTPUT_LOW U(0x00) +#define GPIO_OD_OUTPUT_HIGH U(0x01) +#define GPIO_OD_MASK U(0x01) + +#ifndef __ASSEMBLER__ +#include + +int dt_set_pinctrl_config(int node); +void set_gpio_secure_cfg(uint32_t bank, uint32_t pin, bool secure); +void set_gpio_reset_cfg(uint32_t bank, uint32_t pin); +#endif /*__ASSEMBLER__*/ + +#endif /* STM32_GPIO_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_hash.h b/arm-trusted-firmware/include/drivers/st/stm32_hash.h new file mode 100644 index 0000000..df04730 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_hash.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_HASH_H +#define STM32_HASH_H + +enum stm32_hash_algo_mode { + HASH_MD5SUM, + HASH_SHA1, + HASH_SHA224, + HASH_SHA256 +}; + +int stm32_hash_update(const uint8_t *buffer, size_t length); +int stm32_hash_final(uint8_t *digest); +int stm32_hash_final_update(const uint8_t *buffer, uint32_t buf_length, + uint8_t *digest); +void stm32_hash_init(enum stm32_hash_algo_mode mode); +int stm32_hash_register(void); + +#endif /* STM32_HASH_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_i2c.h b/arm-trusted-firmware/include/drivers/st/stm32_i2c.h new file mode 100644 index 0000000..170d4cf --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_i2c.h @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2016-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_I2C_H +#define STM32_I2C_H + +#include + +#include + +/* Bit definition for I2C_CR1 register */ +#define I2C_CR1_PE BIT(0) +#define I2C_CR1_TXIE BIT(1) +#define I2C_CR1_RXIE BIT(2) +#define I2C_CR1_ADDRIE BIT(3) +#define I2C_CR1_NACKIE BIT(4) +#define I2C_CR1_STOPIE BIT(5) +#define I2C_CR1_TCIE BIT(6) +#define I2C_CR1_ERRIE BIT(7) +#define I2C_CR1_DNF GENMASK(11, 8) +#define I2C_CR1_ANFOFF BIT(12) +#define I2C_CR1_SWRST BIT(13) +#define I2C_CR1_TXDMAEN BIT(14) +#define I2C_CR1_RXDMAEN BIT(15) +#define I2C_CR1_SBC BIT(16) +#define I2C_CR1_NOSTRETCH BIT(17) +#define I2C_CR1_WUPEN BIT(18) +#define I2C_CR1_GCEN BIT(19) +#define I2C_CR1_SMBHEN BIT(22) +#define I2C_CR1_SMBDEN BIT(21) +#define I2C_CR1_ALERTEN BIT(22) +#define I2C_CR1_PECEN BIT(23) + +/* Bit definition for I2C_CR2 register */ +#define I2C_CR2_SADD GENMASK(9, 0) +#define I2C_CR2_RD_WRN BIT(10) +#define I2C_CR2_RD_WRN_OFFSET 10U +#define I2C_CR2_ADD10 BIT(11) +#define I2C_CR2_HEAD10R BIT(12) +#define I2C_CR2_START BIT(13) +#define I2C_CR2_STOP BIT(14) +#define I2C_CR2_NACK BIT(15) +#define I2C_CR2_NBYTES GENMASK(23, 16) +#define I2C_CR2_NBYTES_OFFSET 16U +#define I2C_CR2_RELOAD BIT(24) +#define I2C_CR2_AUTOEND BIT(25) +#define I2C_CR2_PECBYTE BIT(26) + +/* Bit definition for I2C_OAR1 register */ +#define I2C_OAR1_OA1 GENMASK(9, 0) +#define I2C_OAR1_OA1MODE BIT(10) +#define I2C_OAR1_OA1EN BIT(15) + +/* Bit definition for I2C_OAR2 register */ +#define I2C_OAR2_OA2 GENMASK(7, 1) +#define I2C_OAR2_OA2MSK GENMASK(10, 8) +#define I2C_OAR2_OA2NOMASK 0 +#define I2C_OAR2_OA2MASK01 BIT(8) +#define I2C_OAR2_OA2MASK02 BIT(9) +#define I2C_OAR2_OA2MASK03 GENMASK(9, 8) +#define I2C_OAR2_OA2MASK04 BIT(10) +#define I2C_OAR2_OA2MASK05 (BIT(8) | BIT(10)) +#define I2C_OAR2_OA2MASK06 (BIT(9) | BIT(10)) +#define I2C_OAR2_OA2MASK07 GENMASK(10, 8) +#define I2C_OAR2_OA2EN BIT(15) + +/* Bit definition for I2C_TIMINGR register */ +#define I2C_TIMINGR_SCLL GENMASK(7, 0) +#define I2C_TIMINGR_SCLH GENMASK(15, 8) +#define I2C_TIMINGR_SDADEL GENMASK(19, 16) +#define I2C_TIMINGR_SCLDEL GENMASK(23, 20) +#define I2C_TIMINGR_PRESC GENMASK(31, 28) + +/* Bit definition for I2C_TIMEOUTR register */ +#define I2C_TIMEOUTR_TIMEOUTA GENMASK(11, 0) +#define I2C_TIMEOUTR_TIDLE BIT(12) +#define I2C_TIMEOUTR_TIMOUTEN BIT(15) +#define I2C_TIMEOUTR_TIMEOUTB GENMASK(27, 16) +#define I2C_TIMEOUTR_TEXTEN BIT(31) + +/* Bit definition for I2C_ISR register */ +#define I2C_ISR_TXE BIT(0) +#define I2C_ISR_TXIS BIT(1) +#define I2C_ISR_RXNE BIT(2) +#define I2C_ISR_ADDR BIT(3) +#define I2C_ISR_NACKF BIT(4) +#define I2C_ISR_STOPF BIT(5) +#define I2C_ISR_TC BIT(6) +#define I2C_ISR_TCR BIT(7) +#define I2C_ISR_BERR BIT(8) +#define I2C_ISR_ARLO BIT(9) +#define I2C_ISR_OVR BIT(10) +#define I2C_ISR_PECERR BIT(11) +#define I2C_ISR_TIMEOUT BIT(12) +#define I2C_ISR_ALERT BIT(13) +#define I2C_ISR_BUSY BIT(15) +#define I2C_ISR_DIR BIT(16) +#define I2C_ISR_ADDCODE GENMASK(23, 17) + +/* Bit definition for I2C_ICR register */ +#define I2C_ICR_ADDRCF BIT(3) +#define I2C_ICR_NACKCF BIT(4) +#define I2C_ICR_STOPCF BIT(5) +#define I2C_ICR_BERRCF BIT(8) +#define I2C_ICR_ARLOCF BIT(9) +#define I2C_ICR_OVRCF BIT(10) +#define I2C_ICR_PECCF BIT(11) +#define I2C_ICR_TIMOUTCF BIT(12) +#define I2C_ICR_ALERTCF BIT(13) + +enum i2c_speed_e { + I2C_SPEED_STANDARD, /* 100 kHz */ + I2C_SPEED_FAST, /* 400 kHz */ + I2C_SPEED_FAST_PLUS, /* 1 MHz */ +}; + +#define STANDARD_RATE 100000 +#define FAST_RATE 400000 +#define FAST_PLUS_RATE 1000000 + +struct stm32_i2c_init_s { + uint32_t own_address1; /* + * Specifies the first device own + * address. This parameter can be a + * 7-bit or 10-bit address. + */ + + uint32_t addressing_mode; /* + * Specifies if 7-bit or 10-bit + * addressing mode is selected. + * This parameter can be a value of + * @ref I2C_ADDRESSING_MODE. + */ + + uint32_t dual_address_mode; /* + * Specifies if dual addressing mode is + * selected. + * This parameter can be a value of @ref + * I2C_DUAL_ADDRESSING_MODE. + */ + + uint32_t own_address2; /* + * Specifies the second device own + * address if dual addressing mode is + * selected. This parameter can be a + * 7-bit address. + */ + + uint32_t own_address2_masks; /* + * Specifies the acknowledge mask + * address second device own address + * if dual addressing mode is selected + * This parameter can be a value of @ref + * I2C_OWN_ADDRESS2_MASKS. + */ + + uint32_t general_call_mode; /* + * Specifies if general call mode is + * selected. + * This parameter can be a value of @ref + * I2C_GENERAL_CALL_ADDRESSING_MODE. + */ + + uint32_t no_stretch_mode; /* + * Specifies if nostretch mode is + * selected. + * This parameter can be a value of @ref + * I2C_NOSTRETCH_MODE. + */ + + uint32_t rise_time; /* + * Specifies the SCL clock pin rising + * time in nanoseconds. + */ + + uint32_t fall_time; /* + * Specifies the SCL clock pin falling + * time in nanoseconds. + */ + + enum i2c_speed_e speed_mode; /* + * Specifies the I2C clock source + * frequency mode. + * This parameter can be a value of @ref + * i2c_speed_mode_e. + */ + + int analog_filter; /* + * Specifies if the I2C analog noise + * filter is selected. + * This parameter can be 0 (filter + * off), all other values mean filter + * on. + */ + + uint8_t digital_filter_coef; /* + * Specifies the I2C digital noise + * filter coefficient. + * This parameter can be a value + * between 0 and + * STM32_I2C_DIGITAL_FILTER_MAX. + */ +}; + +enum i2c_state_e { + I2C_STATE_RESET = 0x00U, /* Not yet initialized */ + I2C_STATE_READY = 0x20U, /* Ready for use */ + I2C_STATE_BUSY = 0x24U, /* Internal process ongoing */ + I2C_STATE_BUSY_TX = 0x21U, /* Data Transmission ongoing */ + I2C_STATE_BUSY_RX = 0x22U, /* Data Reception ongoing */ +}; + +enum i2c_mode_e { + I2C_MODE_NONE = 0x00U, /* No active communication */ + I2C_MODE_MASTER = 0x10U, /* Communication in Master Mode */ + I2C_MODE_SLAVE = 0x20U, /* Communication in Slave Mode */ + I2C_MODE_MEM = 0x40U /* Communication in Memory Mode */ + +}; + +#define I2C_ERROR_NONE 0x00000000U /* No error */ +#define I2C_ERROR_BERR 0x00000001U /* BERR error */ +#define I2C_ERROR_ARLO 0x00000002U /* ARLO error */ +#define I2C_ERROR_AF 0x00000004U /* ACKF error */ +#define I2C_ERROR_OVR 0x00000008U /* OVR error */ +#define I2C_ERROR_DMA 0x00000010U /* DMA transfer error */ +#define I2C_ERROR_TIMEOUT 0x00000020U /* Timeout error */ +#define I2C_ERROR_SIZE 0x00000040U /* Size Management error */ + +struct i2c_handle_s { + uint32_t i2c_base_addr; /* Registers base address */ + unsigned int dt_status; /* DT nsec/sec status */ + unsigned int clock; /* Clock reference */ + uint8_t lock; /* Locking object */ + enum i2c_state_e i2c_state; /* Communication state */ + enum i2c_mode_e i2c_mode; /* Communication mode */ + uint32_t i2c_err; /* Error code */ +}; + +#define I2C_ADDRESSINGMODE_7BIT 0x00000001U +#define I2C_ADDRESSINGMODE_10BIT 0x00000002U + +#define I2C_DUALADDRESS_DISABLE 0x00000000U +#define I2C_DUALADDRESS_ENABLE I2C_OAR2_OA2EN + +#define I2C_GENERALCALL_DISABLE 0x00000000U +#define I2C_GENERALCALL_ENABLE I2C_CR1_GCEN + +#define I2C_NOSTRETCH_DISABLE 0x00000000U +#define I2C_NOSTRETCH_ENABLE I2C_CR1_NOSTRETCH + +#define I2C_MEMADD_SIZE_8BIT 0x00000001U +#define I2C_MEMADD_SIZE_16BIT 0x00000002U + +#define I2C_RELOAD_MODE I2C_CR2_RELOAD +#define I2C_AUTOEND_MODE I2C_CR2_AUTOEND +#define I2C_SOFTEND_MODE 0x00000000U + +#define I2C_NO_STARTSTOP 0x00000000U +#define I2C_GENERATE_STOP (BIT(31) | I2C_CR2_STOP) +#define I2C_GENERATE_START_READ (BIT(31) | I2C_CR2_START | \ + I2C_CR2_RD_WRN) +#define I2C_GENERATE_START_WRITE (BIT(31) | I2C_CR2_START) + +#define I2C_FLAG_TXE I2C_ISR_TXE +#define I2C_FLAG_TXIS I2C_ISR_TXIS +#define I2C_FLAG_RXNE I2C_ISR_RXNE +#define I2C_FLAG_ADDR I2C_ISR_ADDR +#define I2C_FLAG_AF I2C_ISR_NACKF +#define I2C_FLAG_STOPF I2C_ISR_STOPF +#define I2C_FLAG_TC I2C_ISR_TC +#define I2C_FLAG_TCR I2C_ISR_TCR +#define I2C_FLAG_BERR I2C_ISR_BERR +#define I2C_FLAG_ARLO I2C_ISR_ARLO +#define I2C_FLAG_OVR I2C_ISR_OVR +#define I2C_FLAG_PECERR I2C_ISR_PECERR +#define I2C_FLAG_TIMEOUT I2C_ISR_TIMEOUT +#define I2C_FLAG_ALERT I2C_ISR_ALERT +#define I2C_FLAG_BUSY I2C_ISR_BUSY +#define I2C_FLAG_DIR I2C_ISR_DIR + +#define I2C_RESET_CR2 (I2C_CR2_SADD | I2C_CR2_HEAD10R | \ + I2C_CR2_NBYTES | I2C_CR2_RELOAD | \ + I2C_CR2_RD_WRN) + +#define I2C_TIMEOUT_BUSY_MS 25U + +#define I2C_ANALOGFILTER_ENABLE 0x00000000U +#define I2C_ANALOGFILTER_DISABLE I2C_CR1_ANFOFF + +/* STM32 specific defines */ +#define STM32_I2C_RISE_TIME_DEFAULT 25 /* ns */ +#define STM32_I2C_FALL_TIME_DEFAULT 10 /* ns */ +#define STM32_I2C_SPEED_DEFAULT I2C_SPEED_STANDARD +#define STM32_I2C_ANALOG_FILTER_DELAY_MIN 50 /* ns */ +#define STM32_I2C_ANALOG_FILTER_DELAY_MAX 260 /* ns */ +#define STM32_I2C_DIGITAL_FILTER_MAX 16 + +int stm32_i2c_get_setup_from_fdt(void *fdt, int node, + struct stm32_i2c_init_s *init); +int stm32_i2c_init(struct i2c_handle_s *hi2c, + struct stm32_i2c_init_s *init_data); +int stm32_i2c_mem_write(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); +int stm32_i2c_mem_read(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint16_t mem_addr, uint16_t mem_add_size, + uint8_t *p_data, uint16_t size, uint32_t timeout_ms); +int stm32_i2c_master_transmit(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +int stm32_i2c_master_receive(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint8_t *p_data, uint16_t size, + uint32_t timeout_ms); +bool stm32_i2c_is_device_ready(struct i2c_handle_s *hi2c, uint16_t dev_addr, + uint32_t trials, uint32_t timeout_ms); + +#endif /* STM32_I2C_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h b/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h new file mode 100644 index 0000000..bad2524 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_iwdg.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_IWDG_H +#define STM32_IWDG_H + +#include + +#define IWDG_HW_ENABLED BIT(0) +#define IWDG_DISABLE_ON_STOP BIT(1) +#define IWDG_DISABLE_ON_STANDBY BIT(2) + +int stm32_iwdg_init(void); +void stm32_iwdg_refresh(void); + +#endif /* STM32_IWDG_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_qspi.h b/arm-trusted-firmware/include/drivers/st/stm32_qspi.h new file mode 100644 index 0000000..f47fca4 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_qspi.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32_QSPI_H +#define STM32_QSPI_H + +int stm32_qspi_init(void); + +#endif /* STM32_QSPI_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h b/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h new file mode 100644 index 0000000..c83f625 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2017-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_SDMMC2_H +#define STM32_SDMMC2_H + +#include + +#include +#include + +struct stm32_sdmmc2_params { + uintptr_t reg_base; + unsigned int clk_rate; + unsigned int bus_width; + unsigned int flags; + struct mmc_device_info *device_info; + unsigned int pin_ckin; + unsigned int negedge; + unsigned int dirpol; + unsigned int clock_id; + unsigned int reset_id; + unsigned int max_freq; + bool use_dma; + struct rdev *vmmc_regu; +}; + +unsigned long long stm32_sdmmc2_mmc_get_device_size(void); +int stm32_sdmmc2_mmc_init(struct stm32_sdmmc2_params *params); +bool plat_sdmmc2_use_dma(unsigned int instance, unsigned int memory); + +#endif /* STM32_SDMMC2_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_uart.h b/arm-trusted-firmware/include/drivers/st/stm32_uart.h new file mode 100644 index 0000000..212968f --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_uart.h @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_UART_H +#define STM32_UART_H + +/* UART word length */ +#define STM32_UART_WORDLENGTH_7B USART_CR1_M1 +#define STM32_UART_WORDLENGTH_8B 0x00000000U +#define STM32_UART_WORDLENGTH_9B USART_CR1_M0 + +/* UART number of stop bits */ +#define STM32_UART_STOPBITS_0_5 USART_CR2_STOP_0 +#define STM32_UART_STOPBITS_1 0x00000000U +#define STM32_UART_STOPBITS_1_5 (USART_CR2_STOP_0 | USART_CR2_STOP_1) +#define STM32_UART_STOPBITS_2 USART_CR2_STOP_1 + +/* UART parity */ +#define STM32_UART_PARITY_NONE 0x00000000U +#define STM32_UART_PARITY_EVEN USART_CR1_PCE +#define STM32_UART_PARITY_ODD (USART_CR1_PCE | USART_CR1_PS) + +/* UART transfer mode */ +#define STM32_UART_MODE_RX USART_CR1_RE +#define STM32_UART_MODE_TX USART_CR1_TE +#define STM32_UART_MODE_TX_RX (USART_CR1_TE | USART_CR1_RE) + +/* UART hardware flow control */ +#define STM32_UART_HWCONTROL_NONE 0x00000000U +#define STM32_UART_HWCONTROL_RTS USART_CR3_RTSE +#define STM32_UART_HWCONTROL_CTS USART_CR3_CTSE +#define STM32_UART_HWCONTROL_RTS_CTS (USART_CR3_RTSE | USART_CR3_CTSE) + +/* UART over sampling */ +#define STM32_UART_OVERSAMPLING_16 0x00000000U +#define STM32_UART_OVERSAMPLING_8 USART_CR1_OVER8 + +/* UART prescaler */ +#define STM32_UART_PRESCALER_DIV1 0x00000000U +#define STM32_UART_PRESCALER_DIV2 0x00000001U +#define STM32_UART_PRESCALER_DIV4 0x00000002U +#define STM32_UART_PRESCALER_DIV6 0x00000003U +#define STM32_UART_PRESCALER_DIV8 0x00000004U +#define STM32_UART_PRESCALER_DIV10 0x00000005U +#define STM32_UART_PRESCALER_DIV12 0x00000006U +#define STM32_UART_PRESCALER_DIV16 0x00000007U +#define STM32_UART_PRESCALER_DIV32 0x00000008U +#define STM32_UART_PRESCALER_DIV64 0x00000009U +#define STM32_UART_PRESCALER_DIV128 0x0000000AU +#define STM32_UART_PRESCALER_DIV256 0x0000000BU +#define STM32_UART_PRESCALER_NB 0x0000000CU + +/* UART fifo mode */ +#define STM32_UART_FIFOMODE_EN USART_CR1_FIFOEN +#define STM32_UART_FIFOMODE_DIS 0x00000000U + +/* UART TXFIFO threshold level */ +#define STM32_UART_TXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U +#define STM32_UART_TXFIFO_THRESHOLD_1QUARTERFUL USART_CR3_TXFTCFG_0 +#define STM32_UART_TXFIFO_THRESHOLD_HALFFULL USART_CR3_TXFTCFG_1 +#define STM32_UART_TXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_TXFTCFG_0 | USART_CR3_TXFTCFG_1) +#define STM32_UART_TXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_TXFTCFG_2 +#define STM32_UART_TXFIFO_THRESHOLD_EMPTY (USART_CR3_TXFTCFG_2 | USART_CR3_TXFTCFG_0) + +/* UART RXFIFO threshold level */ +#define STM32_UART_RXFIFO_THRESHOLD_1EIGHTHFULL 0x00000000U +#define STM32_UART_RXFIFO_THRESHOLD_1QUARTERFULL USART_CR3_RXFTCFG_0 +#define STM32_UART_RXFIFO_THRESHOLD_HALFFULL USART_CR3_RXFTCFG_1 +#define STM32_UART_RXFIFO_THRESHOLD_3QUARTERSFULL (USART_CR3_RXFTCFG_0 | USART_CR3_RXFTCFG_1) +#define STM32_UART_RXFIFO_THRESHOLD_7EIGHTHFULL USART_CR3_RXFTCFG_2 +#define STM32_UART_RXFIFO_THRESHOLD_FULL (USART_CR3_RXFTCFG_2 | USART_CR3_RXFTCFG_0) + +struct stm32_uart_init_s { + uint32_t baud_rate; /* + * Configures the UART communication + * baud rate. + */ + + uint32_t word_length; /* + * Specifies the number of data bits + * transmitted or received in a frame. + * This parameter can be a value of + * @ref STM32_UART_WORDLENGTH_*. + */ + + uint32_t stop_bits; /* + * Specifies the number of stop bits + * transmitted. This parameter can be + * a value of @ref STM32_UART_STOPBITS_*. + */ + + uint32_t parity; /* + * Specifies the parity mode. + * This parameter can be a value of + * @ref STM32_UART_PARITY_*. + */ + + uint32_t mode; /* + * Specifies whether the receive or + * transmit mode is enabled or + * disabled. This parameter can be a + * value of @ref @ref STM32_UART_MODE_*. + */ + + uint32_t hw_flow_control; /* + * Specifies whether the hardware flow + * control mode is enabled or + * disabled. This parameter can be a + * value of @ref STM32_UARTHWCONTROL_*. + */ + + uint32_t over_sampling; /* + * Specifies whether the over sampling + * 8 is enabled or disabled. + * This parameter can be a value of + * @ref STM32_UART_OVERSAMPLING_*. + */ + + uint32_t one_bit_sampling; /* + * Specifies whether a single sample + * or three samples' majority vote is + * selected. This parameter can be 0 + * or USART_CR3_ONEBIT. + */ + + uint32_t prescaler; /* + * Specifies the prescaler value used + * to divide the UART clock source. + * This parameter can be a value of + * @ref STM32_UART_PRESCALER_*. + */ + + uint32_t fifo_mode; /* + * Specifies if the FIFO mode will be + * used. This parameter can be a value + * of @ref STM32_UART_FIFOMODE_*. + */ + + uint32_t tx_fifo_threshold; /* + * Specifies the TXFIFO threshold + * level. This parameter can be a + * value of @ref + * STM32_UART_TXFIFO_THRESHOLD_*. + */ + + uint32_t rx_fifo_threshold; /* + * Specifies the RXFIFO threshold + * level. This parameter can be a + * value of @ref + * STM32_UART_RXFIFO_THRESHOLD_*. + */ +}; + +struct stm32_uart_handle_s { + uint32_t base; + uint32_t rdr_mask; +}; + +int stm32_uart_init(struct stm32_uart_handle_s *huart, + uintptr_t base_addr, + const struct stm32_uart_init_s *init); +void stm32_uart_stop(uintptr_t base_addr); +int stm32_uart_putc(struct stm32_uart_handle_s *huart, int c); +int stm32_uart_flush(struct stm32_uart_handle_s *huart); +int stm32_uart_getc(struct stm32_uart_handle_s *huart); + +#endif /* STM32_UART_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h b/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h new file mode 100644 index 0000000..14b296c --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h @@ -0,0 +1,199 @@ +/* + * Copyright (C) 2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32_UART_REGS_H +#define STM32_UART_REGS_H + +#include + +#define USART_CR1 U(0x00) +#define USART_CR2 U(0x04) +#define USART_CR3 U(0x08) +#define USART_BRR U(0x0C) +#define USART_GTPR U(0x10) +#define USART_RTOR U(0x14) +#define USART_RQR U(0x18) +#define USART_ISR U(0x1C) +#define USART_ICR U(0x20) +#define USART_RDR U(0x24) +#define USART_TDR U(0x28) +#define USART_PRESC U(0x2C) + +/* USART_CR1 register fields */ +#define USART_CR1_UE BIT(0) +#define USART_CR1_UESM BIT(1) +#define USART_CR1_RE BIT(2) +#define USART_CR1_TE BIT(3) +#define USART_CR1_IDLEIE BIT(4) +#define USART_CR1_RXNEIE BIT(5) +#define USART_CR1_TCIE BIT(6) +#define USART_CR1_TXEIE BIT(7) +#define USART_CR1_PEIE BIT(8) +#define USART_CR1_PS BIT(9) +#define USART_CR1_PCE BIT(10) +#define USART_CR1_WAKE BIT(11) +#define USART_CR1_M (BIT(28) | BIT(12)) +#define USART_CR1_M0 BIT(12) +#define USART_CR1_MME BIT(13) +#define USART_CR1_CMIE BIT(14) +#define USART_CR1_OVER8 BIT(15) +#define USART_CR1_DEDT GENMASK(20, 16) +#define USART_CR1_DEDT_0 BIT(16) +#define USART_CR1_DEDT_1 BIT(17) +#define USART_CR1_DEDT_2 BIT(18) +#define USART_CR1_DEDT_3 BIT(19) +#define USART_CR1_DEDT_4 BIT(20) +#define USART_CR1_DEAT GENMASK(25, 21) +#define USART_CR1_DEAT_0 BIT(21) +#define USART_CR1_DEAT_1 BIT(22) +#define USART_CR1_DEAT_2 BIT(23) +#define USART_CR1_DEAT_3 BIT(24) +#define USART_CR1_DEAT_4 BIT(25) +#define USART_CR1_RTOIE BIT(26) +#define USART_CR1_EOBIE BIT(27) +#define USART_CR1_M1 BIT(28) +#define USART_CR1_FIFOEN BIT(29) +#define USART_CR1_TXFEIE BIT(30) +#define USART_CR1_RXFFIE BIT(31) + +/* USART_CR2 register fields */ +#define USART_CR2_SLVEN BIT(0) +#define USART_CR2_DIS_NSS BIT(3) +#define USART_CR2_ADDM7 BIT(4) +#define USART_CR2_LBDL BIT(5) +#define USART_CR2_LBDIE BIT(6) +#define USART_CR2_LBCL BIT(8) +#define USART_CR2_CPHA BIT(9) +#define USART_CR2_CPOL BIT(10) +#define USART_CR2_CLKEN BIT(11) +#define USART_CR2_STOP GENMASK(13, 12) +#define USART_CR2_STOP_0 BIT(12) +#define USART_CR2_STOP_1 BIT(13) +#define USART_CR2_LINEN BIT(14) +#define USART_CR2_SWAP BIT(15) +#define USART_CR2_RXINV BIT(16) +#define USART_CR2_TXINV BIT(17) +#define USART_CR2_DATAINV BIT(18) +#define USART_CR2_MSBFIRST BIT(19) +#define USART_CR2_ABREN BIT(20) +#define USART_CR2_ABRMODE GENMASK(22, 21) +#define USART_CR2_ABRMODE_0 BIT(21) +#define USART_CR2_ABRMODE_1 BIT(22) +#define USART_CR2_RTOEN BIT(23) +#define USART_CR2_ADD GENMASK(31, 24) + +/* USART_CR3 register fields */ +#define USART_CR3_EIE BIT(0) +#define USART_CR3_IREN BIT(1) +#define USART_CR3_IRLP BIT(2) +#define USART_CR3_HDSEL BIT(3) +#define USART_CR3_NACK BIT(4) +#define USART_CR3_SCEN BIT(5) +#define USART_CR3_DMAR BIT(6) +#define USART_CR3_DMAT BIT(7) +#define USART_CR3_RTSE BIT(8) +#define USART_CR3_CTSE BIT(9) +#define USART_CR3_CTSIE BIT(10) +#define USART_CR3_ONEBIT BIT(11) +#define USART_CR3_OVRDIS BIT(12) +#define USART_CR3_DDRE BIT(13) +#define USART_CR3_DEM BIT(14) +#define USART_CR3_DEP BIT(15) +#define USART_CR3_SCARCNT GENMASK(19, 17) +#define USART_CR3_SCARCNT_0 BIT(17) +#define USART_CR3_SCARCNT_1 BIT(18) +#define USART_CR3_SCARCNT_2 BIT(19) +#define USART_CR3_WUS GENMASK(21, 20) +#define USART_CR3_WUS_0 BIT(20) +#define USART_CR3_WUS_1 BIT(21) +#define USART_CR3_WUFIE BIT(22) +#define USART_CR3_TXFTIE BIT(23) +#define USART_CR3_TCBGTIE BIT(24) +#define USART_CR3_RXFTCFG GENMASK(27, 25) +#define USART_CR3_RXFTCFG_0 BIT(25) +#define USART_CR3_RXFTCFG_1 BIT(26) +#define USART_CR3_RXFTCFG_2 BIT(27) +#define USART_CR3_RXFTIE BIT(28) +#define USART_CR3_TXFTCFG GENMASK(31, 29) +#define USART_CR3_TXFTCFG_0 BIT(29) +#define USART_CR3_TXFTCFG_1 BIT(30) +#define USART_CR3_TXFTCFG_2 BIT(31) + +/* USART_BRR register fields */ +#define USART_BRR_DIV_FRACTION GENMASK(3, 0) +#define USART_BRR_DIV_MANTISSA GENMASK(15, 4) + +/* USART_GTPR register fields */ +#define USART_GTPR_PSC GENMASK(7, 0) +#define USART_GTPR_GT GENMASK(15, 8) + +/* USART_RTOR register fields */ +#define USART_RTOR_RTO GENMASK(23, 0) +#define USART_RTOR_BLEN GENMASK(31, 24) + +/* USART_RQR register fields */ +#define USART_RQR_ABRRQ BIT(0) +#define USART_RQR_SBKRQ BIT(1) +#define USART_RQR_MMRQ BIT(2) +#define USART_RQR_RXFRQ BIT(3) +#define USART_RQR_TXFRQ BIT(4) + +/* USART_ISR register fields */ +#define USART_ISR_PE BIT(0) +#define USART_ISR_FE BIT(1) +#define USART_ISR_NE BIT(2) +#define USART_ISR_ORE BIT(3) +#define USART_ISR_IDLE BIT(4) +#define USART_ISR_RXNE BIT(5) +#define USART_ISR_TC BIT(6) +#define USART_ISR_TXE BIT(7) +#define USART_ISR_LBDF BIT(8) +#define USART_ISR_CTSIF BIT(9) +#define USART_ISR_CTS BIT(10) +#define USART_ISR_RTOF BIT(11) +#define USART_ISR_EOBF BIT(12) +#define USART_ISR_UDR BIT(13) +#define USART_ISR_ABRE BIT(14) +#define USART_ISR_ABRF BIT(15) +#define USART_ISR_BUSY BIT(16) +#define USART_ISR_CMF BIT(17) +#define USART_ISR_SBKF BIT(18) +#define USART_ISR_RWU BIT(19) +#define USART_ISR_WUF BIT(20) +#define USART_ISR_TEACK BIT(21) +#define USART_ISR_REACK BIT(22) +#define USART_ISR_TXFE BIT(23) +#define USART_ISR_RXFF BIT(24) +#define USART_ISR_TCBGT BIT(25) +#define USART_ISR_RXFT BIT(26) +#define USART_ISR_TXFT BIT(27) + +/* USART_ICR register fields */ +#define USART_ICR_PECF BIT(0) +#define USART_ICR_FECF BIT(1) +#define USART_ICR_NCF BIT(2) +#define USART_ICR_ORECF BIT(3) +#define USART_ICR_IDLECF BIT(4) +#define USART_ICR_TCCF BIT(6) +#define USART_ICR_TCBGT BIT(7) +#define USART_ICR_LBDCF BIT(8) +#define USART_ICR_CTSCF BIT(9) +#define USART_ICR_RTOCF BIT(11) +#define USART_ICR_EOBCF BIT(12) +#define USART_ICR_UDRCF BIT(13) +#define USART_ICR_CMCF BIT(17) +#define USART_ICR_WUCF BIT(20) + +/* USART_RDR register fields */ +#define USART_RDR_RDR GENMASK(8, 0) + +/* USART_TDR register fields */ +#define USART_TDR_TDR GENMASK(8, 0) + +/* USART_PRESC register fields */ +#define USART_PRESC_PRESCALER GENMASK(3, 0) + +#endif /* STM32_UART_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h new file mode 100644 index 0000000..1451c9a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h @@ -0,0 +1,1878 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP13_RCC_H +#define STM32MP13_RCC_H + +#include + +#define RCC_SECCFGR U(0X0) +#define RCC_MP_SREQSETR U(0X100) +#define RCC_MP_SREQCLRR U(0X104) +#define RCC_MP_APRSTCR U(0X108) +#define RCC_MP_APRSTSR U(0X10C) +#define RCC_PWRLPDLYCR U(0X110) +#define RCC_MP_GRSTCSETR U(0X114) +#define RCC_BR_RSTSCLRR U(0X118) +#define RCC_MP_RSTSSETR U(0X11C) +#define RCC_MP_RSTSCLRR U(0X120) +#define RCC_MP_IWDGFZSETR U(0X124) +#define RCC_MP_IWDGFZCLRR U(0X128) +#define RCC_MP_CIER U(0X200) +#define RCC_MP_CIFR U(0X204) +#define RCC_BDCR U(0X400) +#define RCC_RDLSICR U(0X404) +#define RCC_OCENSETR U(0X420) +#define RCC_OCENCLRR U(0X424) +#define RCC_OCRDYR U(0X428) +#define RCC_HSICFGR U(0X440) +#define RCC_CSICFGR U(0X444) +#define RCC_MCO1CFGR U(0X460) +#define RCC_MCO2CFGR U(0X464) +#define RCC_DBGCFGR U(0X468) +#define RCC_RCK12SELR U(0X480) +#define RCC_RCK3SELR U(0X484) +#define RCC_RCK4SELR U(0X488) +#define RCC_PLL1CR U(0X4A0) +#define RCC_PLL1CFGR1 U(0X4A4) +#define RCC_PLL1CFGR2 U(0X4A8) +#define RCC_PLL1FRACR U(0X4AC) +#define RCC_PLL1CSGR U(0X4B0) +#define RCC_PLL2CR U(0X4D0) +#define RCC_PLL2CFGR1 U(0X4D4) +#define RCC_PLL2CFGR2 U(0X4D8) +#define RCC_PLL2FRACR U(0X4DC) +#define RCC_PLL2CSGR U(0X4E0) +#define RCC_PLL3CR U(0X500) +#define RCC_PLL3CFGR1 U(0X504) +#define RCC_PLL3CFGR2 U(0X508) +#define RCC_PLL3FRACR U(0X50C) +#define RCC_PLL3CSGR U(0X510) +#define RCC_PLL4CR U(0X520) +#define RCC_PLL4CFGR1 U(0X524) +#define RCC_PLL4CFGR2 U(0X528) +#define RCC_PLL4FRACR U(0X52C) +#define RCC_PLL4CSGR U(0X530) +#define RCC_MPCKSELR U(0X540) +#define RCC_ASSCKSELR U(0X544) +#define RCC_MSSCKSELR U(0X548) +#define RCC_CPERCKSELR U(0X54C) +#define RCC_RTCDIVR U(0X560) +#define RCC_MPCKDIVR U(0X564) +#define RCC_AXIDIVR U(0X568) +#define RCC_MLAHBDIVR U(0X56C) +#define RCC_APB1DIVR U(0X570) +#define RCC_APB2DIVR U(0X574) +#define RCC_APB3DIVR U(0X578) +#define RCC_APB4DIVR U(0X57C) +#define RCC_APB5DIVR U(0X580) +#define RCC_APB6DIVR U(0X584) +#define RCC_TIMG1PRER U(0X5A0) +#define RCC_TIMG2PRER U(0X5A4) +#define RCC_TIMG3PRER U(0X5A8) +#define RCC_DDRITFCR U(0X5C0) +#define RCC_I2C12CKSELR U(0X600) +#define RCC_I2C345CKSELR U(0X604) +#define RCC_SPI2S1CKSELR U(0X608) +#define RCC_SPI2S23CKSELR U(0X60C) +#define RCC_SPI45CKSELR U(0X610) +#define RCC_UART12CKSELR U(0X614) +#define RCC_UART35CKSELR U(0X618) +#define RCC_UART4CKSELR U(0X61C) +#define RCC_UART6CKSELR U(0X620) +#define RCC_UART78CKSELR U(0X624) +#define RCC_LPTIM1CKSELR U(0X628) +#define RCC_LPTIM23CKSELR U(0X62C) +#define RCC_LPTIM45CKSELR U(0X630) +#define RCC_SAI1CKSELR U(0X634) +#define RCC_SAI2CKSELR U(0X638) +#define RCC_FDCANCKSELR U(0X63C) +#define RCC_SPDIFCKSELR U(0X640) +#define RCC_ADC12CKSELR U(0X644) +#define RCC_SDMMC12CKSELR U(0X648) +#define RCC_ETH12CKSELR U(0X64C) +#define RCC_USBCKSELR U(0X650) +#define RCC_QSPICKSELR U(0X654) +#define RCC_FMCCKSELR U(0X658) +#define RCC_RNG1CKSELR U(0X65C) +#define RCC_STGENCKSELR U(0X660) +#define RCC_DCMIPPCKSELR U(0X664) +#define RCC_SAESCKSELR U(0X668) +#define RCC_APB1RSTSETR U(0X6A0) +#define RCC_APB1RSTCLRR U(0X6A4) +#define RCC_APB2RSTSETR U(0X6A8) +#define RCC_APB2RSTCLRR U(0X6AC) +#define RCC_APB3RSTSETR U(0X6B0) +#define RCC_APB3RSTCLRR U(0X6B4) +#define RCC_APB4RSTSETR U(0X6B8) +#define RCC_APB4RSTCLRR U(0X6BC) +#define RCC_APB5RSTSETR U(0X6C0) +#define RCC_APB5RSTCLRR U(0X6C4) +#define RCC_APB6RSTSETR U(0X6C8) +#define RCC_APB6RSTCLRR U(0X6CC) +#define RCC_AHB2RSTSETR U(0X6D0) +#define RCC_AHB2RSTCLRR U(0X6D4) +#define RCC_AHB4RSTSETR U(0X6E0) +#define RCC_AHB4RSTCLRR U(0X6E4) +#define RCC_AHB5RSTSETR U(0X6E8) +#define RCC_AHB5RSTCLRR U(0X6EC) +#define RCC_AHB6RSTSETR U(0X6F0) +#define RCC_AHB6RSTCLRR U(0X6F4) +#define RCC_MP_APB1ENSETR U(0X700) +#define RCC_MP_APB1ENCLRR U(0X704) +#define RCC_MP_APB2ENSETR U(0X708) +#define RCC_MP_APB2ENCLRR U(0X70C) +#define RCC_MP_APB3ENSETR U(0X710) +#define RCC_MP_APB3ENCLRR U(0X714) +#define RCC_MP_S_APB3ENSETR U(0X718) +#define RCC_MP_S_APB3ENCLRR U(0X71C) +#define RCC_MP_NS_APB3ENSETR U(0X720) +#define RCC_MP_NS_APB3ENCLRR U(0X724) +#define RCC_MP_APB4ENSETR U(0X728) +#define RCC_MP_APB4ENCLRR U(0X72C) +#define RCC_MP_S_APB4ENSETR U(0X730) +#define RCC_MP_S_APB4ENCLRR U(0X734) +#define RCC_MP_NS_APB4ENSETR U(0X738) +#define RCC_MP_NS_APB4ENCLRR U(0X73C) +#define RCC_MP_APB5ENSETR U(0X740) +#define RCC_MP_APB5ENCLRR U(0X744) +#define RCC_MP_APB6ENSETR U(0X748) +#define RCC_MP_APB6ENCLRR U(0X74C) +#define RCC_MP_AHB2ENSETR U(0X750) +#define RCC_MP_AHB2ENCLRR U(0X754) +#define RCC_MP_AHB4ENSETR U(0X760) +#define RCC_MP_AHB4ENCLRR U(0X764) +#define RCC_MP_S_AHB4ENSETR U(0X768) +#define RCC_MP_S_AHB4ENCLRR U(0X76C) +#define RCC_MP_NS_AHB4ENSETR U(0X770) +#define RCC_MP_NS_AHB4ENCLRR U(0X774) +#define RCC_MP_AHB5ENSETR U(0X778) +#define RCC_MP_AHB5ENCLRR U(0X77C) +#define RCC_MP_AHB6ENSETR U(0X780) +#define RCC_MP_AHB6ENCLRR U(0X784) +#define RCC_MP_S_AHB6ENSETR U(0X788) +#define RCC_MP_S_AHB6ENCLRR U(0X78C) +#define RCC_MP_NS_AHB6ENSETR U(0X790) +#define RCC_MP_NS_AHB6ENCLRR U(0X794) +#define RCC_MP_APB1LPENSETR U(0X800) +#define RCC_MP_APB1LPENCLRR U(0X804) +#define RCC_MP_APB2LPENSETR U(0X808) +#define RCC_MP_APB2LPENCLRR U(0X80C) +#define RCC_MP_APB3LPENSETR U(0X810) +#define RCC_MP_APB3LPENCLRR U(0X814) +#define RCC_MP_S_APB3LPENSETR U(0X818) +#define RCC_MP_S_APB3LPENCLRR U(0X81C) +#define RCC_MP_NS_APB3LPENSETR U(0X820) +#define RCC_MP_NS_APB3LPENCLRR U(0X824) +#define RCC_MP_APB4LPENSETR U(0X828) +#define RCC_MP_APB4LPENCLRR U(0X82C) +#define RCC_MP_S_APB4LPENSETR U(0X830) +#define RCC_MP_S_APB4LPENCLRR U(0X834) +#define RCC_MP_NS_APB4LPENSETR U(0X838) +#define RCC_MP_NS_APB4LPENCLRR U(0X83C) +#define RCC_MP_APB5LPENSETR U(0X840) +#define RCC_MP_APB5LPENCLRR U(0X844) +#define RCC_MP_APB6LPENSETR U(0X848) +#define RCC_MP_APB6LPENCLRR U(0X84C) +#define RCC_MP_AHB2LPENSETR U(0X850) +#define RCC_MP_AHB2LPENCLRR U(0X854) +#define RCC_MP_AHB4LPENSETR U(0X858) +#define RCC_MP_AHB4LPENCLRR U(0X85C) +#define RCC_MP_S_AHB4LPENSETR U(0X868) +#define RCC_MP_S_AHB4LPENCLRR U(0X86C) +#define RCC_MP_NS_AHB4LPENSETR U(0X870) +#define RCC_MP_NS_AHB4LPENCLRR U(0X874) +#define RCC_MP_AHB5LPENSETR U(0X878) +#define RCC_MP_AHB5LPENCLRR U(0X87C) +#define RCC_MP_AHB6LPENSETR U(0X880) +#define RCC_MP_AHB6LPENCLRR U(0X884) +#define RCC_MP_S_AHB6LPENSETR U(0X888) +#define RCC_MP_S_AHB6LPENCLRR U(0X88C) +#define RCC_MP_NS_AHB6LPENSETR U(0X890) +#define RCC_MP_NS_AHB6LPENCLRR U(0X894) +#define RCC_MP_S_AXIMLPENSETR U(0X898) +#define RCC_MP_S_AXIMLPENCLRR U(0X89C) +#define RCC_MP_NS_AXIMLPENSETR U(0X8A0) +#define RCC_MP_NS_AXIMLPENCLRR U(0X8A4) +#define RCC_MP_MLAHBLPENSETR U(0X8A8) +#define RCC_MP_MLAHBLPENCLRR U(0X8AC) +#define RCC_APB3SECSR U(0X8C0) +#define RCC_APB4SECSR U(0X8C4) +#define RCC_APB5SECSR U(0X8C8) +#define RCC_APB6SECSR U(0X8CC) +#define RCC_AHB2SECSR U(0X8D0) +#define RCC_AHB4SECSR U(0X8D4) +#define RCC_AHB5SECSR U(0X8D8) +#define RCC_AHB6SECSR U(0X8DC) +#define RCC_VERR U(0XFF4) +#define RCC_IDR U(0XFF8) +#define RCC_SIDR U(0XFFC) + +/* RCC_SECCFGR register fields */ +#define RCC_SECCFGR_HSISEC BIT(0) +#define RCC_SECCFGR_CSISEC BIT(1) +#define RCC_SECCFGR_HSESEC BIT(2) +#define RCC_SECCFGR_LSISEC BIT(3) +#define RCC_SECCFGR_LSESEC BIT(4) +#define RCC_SECCFGR_PLL12SEC BIT(8) +#define RCC_SECCFGR_PLL3SEC BIT(9) +#define RCC_SECCFGR_PLL4SEC BIT(10) +#define RCC_SECCFGR_MPUSEC BIT(11) +#define RCC_SECCFGR_AXISEC BIT(12) +#define RCC_SECCFGR_MLAHBSEC BIT(13) +#define RCC_SECCFGR_APB3DIVSEC BIT(16) +#define RCC_SECCFGR_APB4DIVSEC BIT(17) +#define RCC_SECCFGR_APB5DIVSEC BIT(18) +#define RCC_SECCFGR_APB6DIVSEC BIT(19) +#define RCC_SECCFGR_TIMG3SEC BIT(20) +#define RCC_SECCFGR_CPERSEC BIT(21) +#define RCC_SECCFGR_MCO1SEC BIT(22) +#define RCC_SECCFGR_MCO2SEC BIT(23) +#define RCC_SECCFGR_STPSEC BIT(24) +#define RCC_SECCFGR_RSTSEC BIT(25) +#define RCC_SECCFGR_PWRSEC BIT(31) + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_VCPURSTF BIT(5) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STP2RSTF BIT(10) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_VCPURSTF BIT(5) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STP2RSTF BIT(10) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) + +#define RCC_BDCR_LSEBYP_BIT 1 +#define RCC_BDCR_LSERDY_BIT 2 +#define RCC_BDCR_DIGBYP_BIT 3 +#define RCC_BDCR_LSECSSON_BIT 8 + +#define RCC_BDCR_LSEDRV_WIDTH 2 + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_SPARE_SHIFT 27 + +#define RCC_RDLSICR_LSIRDY_BIT 1 + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) + +#define RCC_OCRDYR_HSIRDY_BIT 0 +#define RCC_OCRDYR_HSIDIVRDY_BIT 2 +#define RCC_OCRDYR_CSIRDY_BIT 4 +#define RCC_OCRDYR_HSERDY_BIT 8 + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_MASK GENMASK(27, 16) +#define RCC_HSICFGR_HSICAL_SHIFT 16 + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +#define RCC_MCO1CFGR_MCO1ON BIT(12) + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +#define RCC_MCO2CFGR_MCO2ON BIT(12) + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 +#define RCC_PLL1FRACR_FRACLE BIT(16) + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 +#define RCC_PLL2FRACR_FRACLE BIT(16) + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 +#define RCC_PLL3FRACR_FRACLE BIT(16) + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 +#define RCC_PLL4FRACR_FRACLE BIT(16) + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_MLAHBSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MLAHBSSRC_SHIFT 0 +#define RCC_MSSCKSELR_MLAHBSSRCRDY BIT(31) + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(3, 0) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) + +/* RCC_MLAHBDIVR register fields */ +#define RCC_MLAHBDIVR_MLAHBDIV_MASK GENMASK(3, 0) +#define RCC_MLAHBDIVR_MLAHBDIV_SHIFT 0 +#define RCC_MLAHBDIVR_MLAHBDIVRDY BIT(31) + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) + +/* RCC_APB6DIVR register fields */ +#define RCC_APB6DIVR_APB6DIV_MASK GENMASK(2, 0) +#define RCC_APB6DIVR_APB6DIV_SHIFT 0 +#define RCC_APB6DIVR_APB6DIVRDY BIT(31) + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_TIMG3PRER register fields */ +#define RCC_TIMG3PRER_TIMG3PRE BIT(0) +#define RCC_TIMG3PRER_TIMG3PRERDY BIT(31) + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C345CKSELR register fields */ +#define RCC_I2C345CKSELR_I2C3SRC_MASK GENMASK(2, 0) +#define RCC_I2C345CKSELR_I2C3SRC_SHIFT 0 +#define RCC_I2C345CKSELR_I2C4SRC_MASK GENMASK(5, 3) +#define RCC_I2C345CKSELR_I2C4SRC_SHIFT 3 +#define RCC_I2C345CKSELR_I2C5SRC_MASK GENMASK(8, 6) +#define RCC_I2C345CKSELR_I2C5SRC_SHIFT 6 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI4SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI4SRC_SHIFT 0 +#define RCC_SPI45CKSELR_SPI5SRC_MASK GENMASK(5, 3) +#define RCC_SPI45CKSELR_SPI5SRC_SHIFT 3 + +/* RCC_UART12CKSELR register fields */ +#define RCC_UART12CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART12CKSELR_UART1SRC_SHIFT 0 +#define RCC_UART12CKSELR_UART2SRC_MASK GENMASK(5, 3) +#define RCC_UART12CKSELR_UART2SRC_SHIFT 3 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART4CKSELR register fields */ +#define RCC_UART4CKSELR_UART4SRC_MASK GENMASK(2, 0) +#define RCC_UART4CKSELR_UART4SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM2SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM2SRC_SHIFT 0 +#define RCC_LPTIM23CKSELR_LPTIM3SRC_MASK GENMASK(5, 3) +#define RCC_LPTIM23CKSELR_LPTIM3SRC_SHIFT 3 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_ADC12CKSELR register fields */ +#define RCC_ADC12CKSELR_ADC1SRC_MASK GENMASK(1, 0) +#define RCC_ADC12CKSELR_ADC1SRC_SHIFT 0 +#define RCC_ADC12CKSELR_ADC2SRC_MASK GENMASK(3, 2) +#define RCC_ADC12CKSELR_ADC2SRC_SHIFT 2 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC1SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC1SRC_SHIFT 0 +#define RCC_SDMMC12CKSELR_SDMMC2SRC_MASK GENMASK(5, 3) +#define RCC_SDMMC12CKSELR_SDMMC2SRC_SHIFT 3 + +/* RCC_ETH12CKSELR register fields */ +#define RCC_ETH12CKSELR_ETH1SRC_MASK GENMASK(1, 0) +#define RCC_ETH12CKSELR_ETH1SRC_SHIFT 0 +#define RCC_ETH12CKSELR_ETH1PTPDIV_MASK GENMASK(7, 4) +#define RCC_ETH12CKSELR_ETH1PTPDIV_SHIFT 4 +#define RCC_ETH12CKSELR_ETH2SRC_MASK GENMASK(9, 8) +#define RCC_ETH12CKSELR_ETH2SRC_SHIFT 8 +#define RCC_ETH12CKSELR_ETH2PTPDIV_MASK GENMASK(15, 12) +#define RCC_ETH12CKSELR_ETH2PTPDIV_SHIFT 12 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC BIT(4) + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DCMIPPCKSELR register fields */ +#define RCC_DCMIPPCKSELR_DCMIPPSRC_MASK GENMASK(1, 0) +#define RCC_DCMIPPCKSELR_DCMIPPSRC_SHIFT 0 + +/* RCC_SAESCKSELR register fields */ +#define RCC_SAESCKSELR_SAESSRC_MASK GENMASK(1, 0) +#define RCC_SAESCKSELR_SAESSRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_DTSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_DTSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DCMIPPRST BIT(1) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DCMIPPRST BIT(1) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_APB6RSTSETR register fields */ +#define RCC_APB6RSTSETR_USART1RST BIT(0) +#define RCC_APB6RSTSETR_USART2RST BIT(1) +#define RCC_APB6RSTSETR_SPI4RST BIT(2) +#define RCC_APB6RSTSETR_SPI5RST BIT(3) +#define RCC_APB6RSTSETR_I2C3RST BIT(4) +#define RCC_APB6RSTSETR_I2C4RST BIT(5) +#define RCC_APB6RSTSETR_I2C5RST BIT(6) +#define RCC_APB6RSTSETR_TIM12RST BIT(7) +#define RCC_APB6RSTSETR_TIM13RST BIT(8) +#define RCC_APB6RSTSETR_TIM14RST BIT(9) +#define RCC_APB6RSTSETR_TIM15RST BIT(10) +#define RCC_APB6RSTSETR_TIM16RST BIT(11) +#define RCC_APB6RSTSETR_TIM17RST BIT(12) + +/* RCC_APB6RSTCLRR register fields */ +#define RCC_APB6RSTCLRR_USART1RST BIT(0) +#define RCC_APB6RSTCLRR_USART2RST BIT(1) +#define RCC_APB6RSTCLRR_SPI4RST BIT(2) +#define RCC_APB6RSTCLRR_SPI5RST BIT(3) +#define RCC_APB6RSTCLRR_I2C3RST BIT(4) +#define RCC_APB6RSTCLRR_I2C4RST BIT(5) +#define RCC_APB6RSTCLRR_I2C5RST BIT(6) +#define RCC_APB6RSTCLRR_TIM12RST BIT(7) +#define RCC_APB6RSTCLRR_TIM13RST BIT(8) +#define RCC_APB6RSTCLRR_TIM14RST BIT(9) +#define RCC_APB6RSTCLRR_TIM15RST BIT(10) +#define RCC_APB6RSTCLRR_TIM16RST BIT(11) +#define RCC_APB6RSTCLRR_TIM17RST BIT(12) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTSETR_DMA3RST BIT(3) +#define RCC_AHB2RSTSETR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTSETR_ADC1RST BIT(5) +#define RCC_AHB2RSTSETR_ADC2RST BIT(6) +#define RCC_AHB2RSTSETR_USBORST BIT(8) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUX1RST BIT(2) +#define RCC_AHB2RSTCLRR_DMA3RST BIT(3) +#define RCC_AHB2RSTCLRR_DMAMUX2RST BIT(4) +#define RCC_AHB2RSTCLRR_ADC1RST BIT(5) +#define RCC_AHB2RSTCLRR_ADC2RST BIT(6) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_TSCRST BIT(15) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_TSCRST BIT(15) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_PKARST BIT(2) +#define RCC_AHB5RSTSETR_SAESRST BIT(3) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_PKARST BIT(2) +#define RCC_AHB5RSTCLRR_SAESRST BIT(3) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_MDMARST BIT(0) +#define RCC_AHB6RSTSETR_MCERST BIT(1) +#define RCC_AHB6RSTSETR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) +#define RCC_AHB6RSTSETR_ETH2MACRST BIT(30) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_MDMARST BIT(0) +#define RCC_AHB6RSTCLRR_MCERST BIT(1) +#define RCC_AHB6RSTCLRR_ETH1MACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) +#define RCC_AHB6RSTCLRR_ETH2MACRST BIT(30) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_DTSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_DTSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_S_APB3ENSETR register fields */ +#define RCC_MP_S_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_S_APB3ENCLRR register fields */ +#define RCC_MP_S_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENSETR register fields */ +#define RCC_MP_NS_APB3ENSETR_SYSCFGEN BIT(0) + +/* RCC_MP_NS_APB3ENCLRR register fields */ +#define RCC_MP_NS_APB3ENCLRR_SYSCFGEN BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_DCMIPPEN BIT(1) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_S_APB4ENSETR register fields */ +#define RCC_MP_S_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_S_APB4ENCLRR register fields */ +#define RCC_MP_S_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENSETR register fields */ +#define RCC_MP_NS_APB4ENSETR_LTDCEN BIT(0) + +/* RCC_MP_NS_APB4ENCLRR register fields */ +#define RCC_MP_NS_APB4ENCLRR_LTDCEN BIT(0) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZCEN BIT(11) +#define RCC_MP_APB5ENSETR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENCEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZCEN BIT(11) +#define RCC_MP_APB5ENCLRR_ETZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENCEN BIT(20) + +/* RCC_MP_APB6ENSETR register fields */ +#define RCC_MP_APB6ENSETR_USART1EN BIT(0) +#define RCC_MP_APB6ENSETR_USART2EN BIT(1) +#define RCC_MP_APB6ENSETR_SPI4EN BIT(2) +#define RCC_MP_APB6ENSETR_SPI5EN BIT(3) +#define RCC_MP_APB6ENSETR_I2C3EN BIT(4) +#define RCC_MP_APB6ENSETR_I2C4EN BIT(5) +#define RCC_MP_APB6ENSETR_I2C5EN BIT(6) +#define RCC_MP_APB6ENSETR_TIM12EN BIT(7) +#define RCC_MP_APB6ENSETR_TIM13EN BIT(8) +#define RCC_MP_APB6ENSETR_TIM14EN BIT(9) +#define RCC_MP_APB6ENSETR_TIM15EN BIT(10) +#define RCC_MP_APB6ENSETR_TIM16EN BIT(11) +#define RCC_MP_APB6ENSETR_TIM17EN BIT(12) + +/* RCC_MP_APB6ENCLRR register fields */ +#define RCC_MP_APB6ENCLRR_USART1EN BIT(0) +#define RCC_MP_APB6ENCLRR_USART2EN BIT(1) +#define RCC_MP_APB6ENCLRR_SPI4EN BIT(2) +#define RCC_MP_APB6ENCLRR_SPI5EN BIT(3) +#define RCC_MP_APB6ENCLRR_I2C3EN BIT(4) +#define RCC_MP_APB6ENCLRR_I2C4EN BIT(5) +#define RCC_MP_APB6ENCLRR_I2C5EN BIT(6) +#define RCC_MP_APB6ENCLRR_TIM12EN BIT(7) +#define RCC_MP_APB6ENCLRR_TIM13EN BIT(8) +#define RCC_MP_APB6ENCLRR_TIM14EN BIT(9) +#define RCC_MP_APB6ENCLRR_TIM15EN BIT(10) +#define RCC_MP_APB6ENCLRR_TIM16EN BIT(11) +#define RCC_MP_APB6ENCLRR_TIM17EN BIT(12) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENSETR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENSETR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENSETR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENSETR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUX1EN BIT(2) +#define RCC_MP_AHB2ENCLRR_DMA3EN BIT(3) +#define RCC_MP_AHB2ENCLRR_DMAMUX2EN BIT(4) +#define RCC_MP_AHB2ENCLRR_ADC1EN BIT(5) +#define RCC_MP_AHB2ENCLRR_ADC2EN BIT(6) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_TSCEN BIT(15) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_TSCEN BIT(15) + +/* RCC_MP_S_AHB4ENSETR register fields */ +#define RCC_MP_S_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_S_AHB4ENCLRR register fields */ +#define RCC_MP_S_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_S_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_S_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_S_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_S_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_S_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_S_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_S_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_S_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENSETR register fields */ +#define RCC_MP_NS_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENSETR_GPIOIEN BIT(8) + +/* RCC_MP_NS_AHB4ENCLRR register fields */ +#define RCC_MP_NS_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_NS_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_NS_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_NS_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_NS_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_NS_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_NS_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_NS_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_NS_AHB4ENCLRR_GPIOIEN BIT(8) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_PKAEN BIT(2) +#define RCC_MP_AHB5ENSETR_SAESEN BIT(3) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_PKAEN BIT(2) +#define RCC_MP_AHB5ENCLRR_SAESEN BIT(3) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MCEEN BIT(1) +#define RCC_MP_AHB6ENSETR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) +#define RCC_MP_AHB6ENSETR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENSETR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENSETR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENSETR_ETH2MACEN BIT(30) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MCEEN BIT(1) +#define RCC_MP_AHB6ENCLRR_ETH1CKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETH1TXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETH1RXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETH1MACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) +#define RCC_MP_AHB6ENCLRR_ETH2CKEN BIT(27) +#define RCC_MP_AHB6ENCLRR_ETH2TXEN BIT(28) +#define RCC_MP_AHB6ENCLRR_ETH2RXEN BIT(29) +#define RCC_MP_AHB6ENCLRR_ETH2MACEN BIT(30) + +/* RCC_MP_S_AHB6ENSETR register fields */ +#define RCC_MP_S_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_S_AHB6ENCLRR register fields */ +#define RCC_MP_S_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENSETR register fields */ +#define RCC_MP_NS_AHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_NS_AHB6ENCLRR register fields */ +#define RCC_MP_NS_AHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_DTSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_S_APB3LPENSETR register fields */ +#define RCC_MP_S_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_S_APB3LPENCLRR register fields */ +#define RCC_MP_S_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENSETR register fields */ +#define RCC_MP_NS_APB3LPENSETR_SYSCFGLPEN BIT(0) + +/* RCC_MP_NS_APB3LPENCLRR register fields */ +#define RCC_MP_NS_APB3LPENCLRR_SYSCFGLPEN BIT(0) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_DCMIPPLPEN BIT(1) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_S_APB4LPENSETR register fields */ +#define RCC_MP_S_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_S_APB4LPENCLRR register fields */ +#define RCC_MP_S_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENSETR register fields */ +#define RCC_MP_NS_APB4LPENSETR_LTDCLPEN BIT(0) + +/* RCC_MP_NS_APB4LPENCLRR register fields */ +#define RCC_MP_NS_APB4LPENCLRR_LTDCLPEN BIT(0) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENSETR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZCLPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_ETZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENCLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENCSTPEN BIT(21) + +/* RCC_MP_APB6LPENSETR register fields */ +#define RCC_MP_APB6LPENSETR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENSETR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENSETR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENSETR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENSETR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENSETR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENSETR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENSETR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENSETR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENSETR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENSETR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENSETR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENSETR_TIM17LPEN BIT(12) + +/* RCC_MP_APB6LPENCLRR register fields */ +#define RCC_MP_APB6LPENCLRR_USART1LPEN BIT(0) +#define RCC_MP_APB6LPENCLRR_USART2LPEN BIT(1) +#define RCC_MP_APB6LPENCLRR_SPI4LPEN BIT(2) +#define RCC_MP_APB6LPENCLRR_SPI5LPEN BIT(3) +#define RCC_MP_APB6LPENCLRR_I2C3LPEN BIT(4) +#define RCC_MP_APB6LPENCLRR_I2C4LPEN BIT(5) +#define RCC_MP_APB6LPENCLRR_I2C5LPEN BIT(6) +#define RCC_MP_APB6LPENCLRR_TIM12LPEN BIT(7) +#define RCC_MP_APB6LPENCLRR_TIM13LPEN BIT(8) +#define RCC_MP_APB6LPENCLRR_TIM14LPEN BIT(9) +#define RCC_MP_APB6LPENCLRR_TIM15LPEN BIT(10) +#define RCC_MP_APB6LPENCLRR_TIM16LPEN BIT(11) +#define RCC_MP_APB6LPENCLRR_TIM17LPEN BIT(12) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENSETR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENSETR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUX1LPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_DMA3LPEN BIT(3) +#define RCC_MP_AHB2LPENCLRR_DMAMUX2LPEN BIT(4) +#define RCC_MP_AHB2LPENCLRR_ADC1LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_ADC2LPEN BIT(6) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_TSCLPEN BIT(15) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_TSCLPEN BIT(15) + +/* RCC_MP_S_AHB4LPENSETR register fields */ +#define RCC_MP_S_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_S_AHB4LPENCLRR register fields */ +#define RCC_MP_S_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_S_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_S_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_S_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_S_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_S_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_S_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_S_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_S_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENSETR register fields */ +#define RCC_MP_NS_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENSETR_GPIOILPEN BIT(8) + +/* RCC_MP_NS_AHB4LPENCLRR register fields */ +#define RCC_MP_NS_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_NS_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_NS_AHB4LPENCLRR_GPIOILPEN BIT(8) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENSETR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_PKALPEN BIT(2) +#define RCC_MP_AHB5LPENCLRR_SAESLPEN BIT(3) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENSETR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENSETR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENSETR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENSETR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENSETR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENSETR_ETH2STPEN BIT(31) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MCELPEN BIT(1) +#define RCC_MP_AHB6LPENCLRR_ETH1CKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETH1TXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETH1RXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETH1MACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETH1STPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) +#define RCC_MP_AHB6LPENCLRR_ETH2CKLPEN BIT(27) +#define RCC_MP_AHB6LPENCLRR_ETH2TXLPEN BIT(28) +#define RCC_MP_AHB6LPENCLRR_ETH2RXLPEN BIT(29) +#define RCC_MP_AHB6LPENCLRR_ETH2MACLPEN BIT(30) +#define RCC_MP_AHB6LPENCLRR_ETH2STPEN BIT(31) + +/* RCC_MP_S_AHB6LPENSETR register fields */ +#define RCC_MP_S_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_S_AHB6LPENCLRR register fields */ +#define RCC_MP_S_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENSETR register fields */ +#define RCC_MP_NS_AHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_NS_AHB6LPENCLRR register fields */ +#define RCC_MP_NS_AHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MP_S_AXIMLPENSETR register fields */ +#define RCC_MP_S_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_S_AXIMLPENCLRR register fields */ +#define RCC_MP_S_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENSETR register fields */ +#define RCC_MP_NS_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_NS_AXIMLPENCLRR register fields */ +#define RCC_MP_NS_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM3LPEN BIT(2) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM3LPEN BIT(2) + +/* RCC_APB3SECSR register fields */ +#define RCC_APB3SECSR_LPTIM2SECF BIT(0) +#define RCC_APB3SECSR_LPTIM3SECF BIT(1) +#define RCC_APB3SECSR_VREFSECF BIT(13) + +/* RCC_APB4SECSR register fields */ +#define RCC_APB4SECSR_DCMIPPSECF BIT(1) +#define RCC_APB4SECSR_USBPHYSECF BIT(16) + +/* RCC_APB5SECSR register fields */ +#define RCC_APB5SECSR_RTCSECF BIT(8) +#define RCC_APB5SECSR_TZCSECF BIT(11) +#define RCC_APB5SECSR_ETZPCSECF BIT(13) +#define RCC_APB5SECSR_IWDG1SECF BIT(15) +#define RCC_APB5SECSR_BSECSECF BIT(16) +#define RCC_APB5SECSR_STGENCSECF_MASK GENMASK(21, 20) +#define RCC_APB5SECSR_STGENCSECF_SHIFT 20 + +/* RCC_APB6SECSR register fields */ +#define RCC_APB6SECSR_USART1SECF BIT(0) +#define RCC_APB6SECSR_USART2SECF BIT(1) +#define RCC_APB6SECSR_SPI4SECF BIT(2) +#define RCC_APB6SECSR_SPI5SECF BIT(3) +#define RCC_APB6SECSR_I2C3SECF BIT(4) +#define RCC_APB6SECSR_I2C4SECF BIT(5) +#define RCC_APB6SECSR_I2C5SECF BIT(6) +#define RCC_APB6SECSR_TIM12SECF BIT(7) +#define RCC_APB6SECSR_TIM13SECF BIT(8) +#define RCC_APB6SECSR_TIM14SECF BIT(9) +#define RCC_APB6SECSR_TIM15SECF BIT(10) +#define RCC_APB6SECSR_TIM16SECF BIT(11) +#define RCC_APB6SECSR_TIM17SECF BIT(12) + +/* RCC_AHB2SECSR register fields */ +#define RCC_AHB2SECSR_DMA3SECF BIT(3) +#define RCC_AHB2SECSR_DMAMUX2SECF BIT(4) +#define RCC_AHB2SECSR_ADC1SECF BIT(5) +#define RCC_AHB2SECSR_ADC2SECF BIT(6) +#define RCC_AHB2SECSR_USBOSECF BIT(8) + +/* RCC_AHB4SECSR register fields */ +#define RCC_AHB4SECSR_TSCSECF BIT(15) + +/* RCC_AHB5SECSR register fields */ +#define RCC_AHB5SECSR_PKASECF BIT(2) +#define RCC_AHB5SECSR_SAESSECF BIT(3) +#define RCC_AHB5SECSR_CRYP1SECF BIT(4) +#define RCC_AHB5SECSR_HASH1SECF BIT(5) +#define RCC_AHB5SECSR_RNG1SECF BIT(6) +#define RCC_AHB5SECSR_BKPSRAMSECF BIT(8) + +/* RCC_AHB6SECSR register fields */ +#define RCC_AHB6SECSR_MCESECF BIT(1) +#define RCC_AHB6SECSR_ETH1SECF_MASK GENMASK(11, 7) +#define RCC_AHB6SECSR_ETH1SECF_SHIFT 7 +#define RCC_AHB6SECSR_FMCSECF BIT(12) +#define RCC_AHB6SECSR_QSPISECF BIT(14) +#define RCC_AHB6SECSR_SDMMC1SECF BIT(16) +#define RCC_AHB6SECSR_SDMMC2SECF BIT(17) +#define RCC_AHB6SECSR_ETH2SECF_MASK GENMASK(31, 27) +#define RCC_AHB6SECSR_ETH2SECF_SHIFT 27 + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MAJREV_SHIFT 4 + +/* RCC_IDR register fields */ +#define RCC_IDR_ID_MASK GENMASK(31, 0) +#define RCC_IDR_ID_SHIFT 0 + +/* RCC_SIDR register fields */ +#define RCC_SIDR_SID_MASK GENMASK(31, 0) +#define RCC_SIDR_SID_SHIFT 0 + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) + +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Values of RCC_MPCKSELR register */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 + +/* Values of RCC_ASSCKSELR register */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 + +/* Values of RCC_MSSCKSELR register */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 + +/* Values of RCC_CPERCKSELR register */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 + +/* Used for most of DIVR register: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK(2, 0) +#define RCC_MPUDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIV_MASK GENMASK(2, 0) +#define RCC_MLAHBDIV_MASK GENMASK(3, 0) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET U(4) + +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + +/* RCC_OCENSETR register fields */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +#define RCC_OCENR_DIGBYP_BIT 7 +#define RCC_OCENR_HSEBYP_BIT 10 +#define RCC_OCENR_HSECSSON_BIT 11 + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) + +#define RCC_UART4CKSELR_HSI 0x00000002 + +#define RCC_CPERCKSELR_PERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_PERSRC_SHIFT 0 + +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) + +#define RCC_DDRITFCR_DDRC2EN BIT(0) +#define RCC_DDRITFCR_DDRC2LPEN BIT(1) + +#define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_OFFSET_MASK GENMASK(11, 0) + +#endif /* STM32MP1_RCC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h new file mode 100644 index 0000000..ddc0397 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h @@ -0,0 +1,2328 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_RCC_H +#define STM32MP1_RCC_H + +#include + +#define RCC_TZCR U(0x00) +#define RCC_OCENSETR U(0x0C) +#define RCC_OCENCLRR U(0x10) +#define RCC_HSICFGR U(0x18) +#define RCC_CSICFGR U(0x1C) +#define RCC_MPCKSELR U(0x20) +#define RCC_ASSCKSELR U(0x24) +#define RCC_RCK12SELR U(0x28) +#define RCC_MPCKDIVR U(0x2C) +#define RCC_AXIDIVR U(0x30) +#define RCC_APB4DIVR U(0x3C) +#define RCC_APB5DIVR U(0x40) +#define RCC_RTCDIVR U(0x44) +#define RCC_MSSCKSELR U(0x48) +#define RCC_PLL1CR U(0x80) +#define RCC_PLL1CFGR1 U(0x84) +#define RCC_PLL1CFGR2 U(0x88) +#define RCC_PLL1FRACR U(0x8C) +#define RCC_PLL1CSGR U(0x90) +#define RCC_PLL2CR U(0x94) +#define RCC_PLL2CFGR1 U(0x98) +#define RCC_PLL2CFGR2 U(0x9C) +#define RCC_PLL2FRACR U(0xA0) +#define RCC_PLL2CSGR U(0xA4) +#define RCC_I2C46CKSELR U(0xC0) +#define RCC_SPI6CKSELR U(0xC4) +#define RCC_UART1CKSELR U(0xC8) +#define RCC_RNG1CKSELR U(0xCC) +#define RCC_CPERCKSELR U(0xD0) +#define RCC_STGENCKSELR U(0xD4) +#define RCC_DDRITFCR U(0xD8) +#define RCC_MP_BOOTCR U(0x100) +#define RCC_MP_SREQSETR U(0x104) +#define RCC_MP_SREQCLRR U(0x108) +#define RCC_MP_GCR U(0x10C) +#define RCC_MP_APRSTCR U(0x110) +#define RCC_MP_APRSTSR U(0x114) +#define RCC_BDCR U(0x140) +#define RCC_RDLSICR U(0x144) +#define RCC_APB4RSTSETR U(0x180) +#define RCC_APB4RSTCLRR U(0x184) +#define RCC_APB5RSTSETR U(0x188) +#define RCC_APB5RSTCLRR U(0x18C) +#define RCC_AHB5RSTSETR U(0x190) +#define RCC_AHB5RSTCLRR U(0x194) +#define RCC_AHB6RSTSETR U(0x198) +#define RCC_AHB6RSTCLRR U(0x19C) +#define RCC_TZAHB6RSTSETR U(0x1A0) +#define RCC_TZAHB6RSTCLRR U(0x1A4) +#define RCC_MP_APB4ENSETR U(0x200) +#define RCC_MP_APB4ENCLRR U(0x204) +#define RCC_MP_APB5ENSETR U(0x208) +#define RCC_MP_APB5ENCLRR U(0x20C) +#define RCC_MP_AHB5ENSETR U(0x210) +#define RCC_MP_AHB5ENCLRR U(0x214) +#define RCC_MP_AHB6ENSETR U(0x218) +#define RCC_MP_AHB6ENCLRR U(0x21C) +#define RCC_MP_TZAHB6ENSETR U(0x220) +#define RCC_MP_TZAHB6ENCLRR U(0x224) +#define RCC_MC_APB4ENSETR U(0x280) +#define RCC_MC_APB4ENCLRR U(0x284) +#define RCC_MC_APB5ENSETR U(0x288) +#define RCC_MC_APB5ENCLRR U(0x28C) +#define RCC_MC_AHB5ENSETR U(0x290) +#define RCC_MC_AHB5ENCLRR U(0x294) +#define RCC_MC_AHB6ENSETR U(0x298) +#define RCC_MC_AHB6ENCLRR U(0x29C) +#define RCC_MP_APB4LPENSETR U(0x300) +#define RCC_MP_APB4LPENCLRR U(0x304) +#define RCC_MP_APB5LPENSETR U(0x308) +#define RCC_MP_APB5LPENCLRR U(0x30C) +#define RCC_MP_AHB5LPENSETR U(0x310) +#define RCC_MP_AHB5LPENCLRR U(0x314) +#define RCC_MP_AHB6LPENSETR U(0x318) +#define RCC_MP_AHB6LPENCLRR U(0x31C) +#define RCC_MP_TZAHB6LPENSETR U(0x320) +#define RCC_MP_TZAHB6LPENCLRR U(0x324) +#define RCC_MC_APB4LPENSETR U(0x380) +#define RCC_MC_APB4LPENCLRR U(0x384) +#define RCC_MC_APB5LPENSETR U(0x388) +#define RCC_MC_APB5LPENCLRR U(0x38C) +#define RCC_MC_AHB5LPENSETR U(0x390) +#define RCC_MC_AHB5LPENCLRR U(0x394) +#define RCC_MC_AHB6LPENSETR U(0x398) +#define RCC_MC_AHB6LPENCLRR U(0x39C) +#define RCC_BR_RSTSCLRR U(0x400) +#define RCC_MP_GRSTCSETR U(0x404) +#define RCC_MP_RSTSCLRR U(0x408) +#define RCC_MP_IWDGFZSETR U(0x40C) +#define RCC_MP_IWDGFZCLRR U(0x410) +#define RCC_MP_CIER U(0x414) +#define RCC_MP_CIFR U(0x418) +#define RCC_PWRLPDLYCR U(0x41C) +#define RCC_MP_RSTSSETR U(0x420) +#define RCC_MCO1CFGR U(0x800) +#define RCC_MCO2CFGR U(0x804) +#define RCC_OCRDYR U(0x808) +#define RCC_DBGCFGR U(0x80C) +#define RCC_RCK3SELR U(0x820) +#define RCC_RCK4SELR U(0x824) +#define RCC_TIMG1PRER U(0x828) +#define RCC_TIMG2PRER U(0x82C) +#define RCC_MCUDIVR U(0x830) +#define RCC_APB1DIVR U(0x834) +#define RCC_APB2DIVR U(0x838) +#define RCC_APB3DIVR U(0x83C) +#define RCC_PLL3CR U(0x880) +#define RCC_PLL3CFGR1 U(0x884) +#define RCC_PLL3CFGR2 U(0x888) +#define RCC_PLL3FRACR U(0x88C) +#define RCC_PLL3CSGR U(0x890) +#define RCC_PLL4CR U(0x894) +#define RCC_PLL4CFGR1 U(0x898) +#define RCC_PLL4CFGR2 U(0x89C) +#define RCC_PLL4FRACR U(0x8A0) +#define RCC_PLL4CSGR U(0x8A4) +#define RCC_I2C12CKSELR U(0x8C0) +#define RCC_I2C35CKSELR U(0x8C4) +#define RCC_SAI1CKSELR U(0x8C8) +#define RCC_SAI2CKSELR U(0x8CC) +#define RCC_SAI3CKSELR U(0x8D0) +#define RCC_SAI4CKSELR U(0x8D4) +#define RCC_SPI2S1CKSELR U(0x8D8) +#define RCC_SPI2S23CKSELR U(0x8DC) +#define RCC_SPI45CKSELR U(0x8E0) +#define RCC_UART6CKSELR U(0x8E4) +#define RCC_UART24CKSELR U(0x8E8) +#define RCC_UART35CKSELR U(0x8EC) +#define RCC_UART78CKSELR U(0x8F0) +#define RCC_SDMMC12CKSELR U(0x8F4) +#define RCC_SDMMC3CKSELR U(0x8F8) +#define RCC_ETHCKSELR U(0x8FC) +#define RCC_QSPICKSELR U(0x900) +#define RCC_FMCCKSELR U(0x904) +#define RCC_FDCANCKSELR U(0x90C) +#define RCC_SPDIFCKSELR U(0x914) +#define RCC_CECCKSELR U(0x918) +#define RCC_USBCKSELR U(0x91C) +#define RCC_RNG2CKSELR U(0x920) +#define RCC_DSICKSELR U(0x924) +#define RCC_ADCCKSELR U(0x928) +#define RCC_LPTIM45CKSELR U(0x92C) +#define RCC_LPTIM23CKSELR U(0x930) +#define RCC_LPTIM1CKSELR U(0x934) +#define RCC_APB1RSTSETR U(0x980) +#define RCC_APB1RSTCLRR U(0x984) +#define RCC_APB2RSTSETR U(0x988) +#define RCC_APB2RSTCLRR U(0x98C) +#define RCC_APB3RSTSETR U(0x990) +#define RCC_APB3RSTCLRR U(0x994) +#define RCC_AHB2RSTSETR U(0x998) +#define RCC_AHB2RSTCLRR U(0x99C) +#define RCC_AHB3RSTSETR U(0x9A0) +#define RCC_AHB3RSTCLRR U(0x9A4) +#define RCC_AHB4RSTSETR U(0x9A8) +#define RCC_AHB4RSTCLRR U(0x9AC) +#define RCC_MP_APB1ENSETR U(0xA00) +#define RCC_MP_APB1ENCLRR U(0xA04) +#define RCC_MP_APB2ENSETR U(0xA08) +#define RCC_MP_APB2ENCLRR U(0xA0C) +#define RCC_MP_APB3ENSETR U(0xA10) +#define RCC_MP_APB3ENCLRR U(0xA14) +#define RCC_MP_AHB2ENSETR U(0xA18) +#define RCC_MP_AHB2ENCLRR U(0xA1C) +#define RCC_MP_AHB3ENSETR U(0xA20) +#define RCC_MP_AHB3ENCLRR U(0xA24) +#define RCC_MP_AHB4ENSETR U(0xA28) +#define RCC_MP_AHB4ENCLRR U(0xA2C) +#define RCC_MP_MLAHBENSETR U(0xA38) +#define RCC_MP_MLAHBENCLRR U(0xA3C) +#define RCC_MC_APB1ENSETR U(0xA80) +#define RCC_MC_APB1ENCLRR U(0xA84) +#define RCC_MC_APB2ENSETR U(0xA88) +#define RCC_MC_APB2ENCLRR U(0xA8C) +#define RCC_MC_APB3ENSETR U(0xA90) +#define RCC_MC_APB3ENCLRR U(0xA94) +#define RCC_MC_AHB2ENSETR U(0xA98) +#define RCC_MC_AHB2ENCLRR U(0xA9C) +#define RCC_MC_AHB3ENSETR U(0xAA0) +#define RCC_MC_AHB3ENCLRR U(0xAA4) +#define RCC_MC_AHB4ENSETR U(0xAA8) +#define RCC_MC_AHB4ENCLRR U(0xAAC) +#define RCC_MC_AXIMENSETR U(0xAB0) +#define RCC_MC_AXIMENCLRR U(0xAB4) +#define RCC_MC_MLAHBENSETR U(0xAB8) +#define RCC_MC_MLAHBENCLRR U(0xABC) +#define RCC_MP_APB1LPENSETR U(0xB00) +#define RCC_MP_APB1LPENCLRR U(0xB04) +#define RCC_MP_APB2LPENSETR U(0xB08) +#define RCC_MP_APB2LPENCLRR U(0xB0C) +#define RCC_MP_APB3LPENSETR U(0xB10) +#define RCC_MP_APB3LPENCLRR U(0xB14) +#define RCC_MP_AHB2LPENSETR U(0xB18) +#define RCC_MP_AHB2LPENCLRR U(0xB1C) +#define RCC_MP_AHB3LPENSETR U(0xB20) +#define RCC_MP_AHB3LPENCLRR U(0xB24) +#define RCC_MP_AHB4LPENSETR U(0xB28) +#define RCC_MP_AHB4LPENCLRR U(0xB2C) +#define RCC_MP_AXIMLPENSETR U(0xB30) +#define RCC_MP_AXIMLPENCLRR U(0xB34) +#define RCC_MP_MLAHBLPENSETR U(0xB38) +#define RCC_MP_MLAHBLPENCLRR U(0xB3C) +#define RCC_MC_APB1LPENSETR U(0xB80) +#define RCC_MC_APB1LPENCLRR U(0xB84) +#define RCC_MC_APB2LPENSETR U(0xB88) +#define RCC_MC_APB2LPENCLRR U(0xB8C) +#define RCC_MC_APB3LPENSETR U(0xB90) +#define RCC_MC_APB3LPENCLRR U(0xB94) +#define RCC_MC_AHB2LPENSETR U(0xB98) +#define RCC_MC_AHB2LPENCLRR U(0xB9C) +#define RCC_MC_AHB3LPENSETR U(0xBA0) +#define RCC_MC_AHB3LPENCLRR U(0xBA4) +#define RCC_MC_AHB4LPENSETR U(0xBA8) +#define RCC_MC_AHB4LPENCLRR U(0xBAC) +#define RCC_MC_AXIMLPENSETR U(0xBB0) +#define RCC_MC_AXIMLPENCLRR U(0xBB4) +#define RCC_MC_MLAHBLPENSETR U(0xBB8) +#define RCC_MC_MLAHBLPENCLRR U(0xBBC) +#define RCC_MC_RSTSCLRR U(0xC00) +#define RCC_MC_CIER U(0xC14) +#define RCC_MC_CIFR U(0xC18) +#define RCC_VERR U(0xFF4) +#define RCC_IDR U(0xFF8) +#define RCC_SIDR U(0xFFC) + +/* RCC_TZCR register fields */ +#define RCC_TZCR_TZEN BIT(0) +#define RCC_TZCR_MCKPROT BIT(1) + +/* RCC_OCENSETR register fields */ +#define RCC_OCENSETR_HSION BIT(0) +#define RCC_OCENSETR_HSIKERON BIT(1) +#define RCC_OCENSETR_CSION BIT(4) +#define RCC_OCENSETR_CSIKERON BIT(5) +#define RCC_OCENSETR_DIGBYP BIT(7) +#define RCC_OCENSETR_HSEON BIT(8) +#define RCC_OCENSETR_HSEKERON BIT(9) +#define RCC_OCENSETR_HSEBYP BIT(10) +#define RCC_OCENSETR_HSECSSON BIT(11) + +/* RCC_OCENCLRR register fields */ +#define RCC_OCENCLRR_HSION BIT(0) +#define RCC_OCENCLRR_HSIKERON BIT(1) +#define RCC_OCENCLRR_CSION BIT(4) +#define RCC_OCENCLRR_CSIKERON BIT(5) +#define RCC_OCENCLRR_DIGBYP BIT(7) +#define RCC_OCENCLRR_HSEON BIT(8) +#define RCC_OCENCLRR_HSEKERON BIT(9) +#define RCC_OCENCLRR_HSEBYP BIT(10) + +/* RCC_HSICFGR register fields */ +#define RCC_HSICFGR_HSIDIV_MASK GENMASK(1, 0) +#define RCC_HSICFGR_HSIDIV_SHIFT 0 +#define RCC_HSICFGR_HSITRIM_MASK GENMASK(14, 8) +#define RCC_HSICFGR_HSITRIM_SHIFT 8 +#define RCC_HSICFGR_HSICAL_MASK GENMASK(24, 16) +#define RCC_HSICFGR_HSICAL_SHIFT 16 +#define RCC_HSICFGR_HSICAL_TEMP_MASK GENMASK(27, 25) + +/* RCC_CSICFGR register fields */ +#define RCC_CSICFGR_CSITRIM_MASK GENMASK(12, 8) +#define RCC_CSICFGR_CSITRIM_SHIFT 8 +#define RCC_CSICFGR_CSICAL_MASK GENMASK(23, 16) +#define RCC_CSICFGR_CSICAL_SHIFT 16 + +/* RCC_MPCKSELR register fields */ +#define RCC_MPCKSELR_HSI 0x00000000 +#define RCC_MPCKSELR_HSE 0x00000001 +#define RCC_MPCKSELR_PLL 0x00000002 +#define RCC_MPCKSELR_PLL_MPUDIV 0x00000003 +#define RCC_MPCKSELR_MPUSRC_MASK GENMASK(1, 0) +#define RCC_MPCKSELR_MPUSRC_SHIFT 0 +#define RCC_MPCKSELR_MPUSRCRDY BIT(31) + +/* RCC_ASSCKSELR register fields */ +#define RCC_ASSCKSELR_HSI 0x00000000 +#define RCC_ASSCKSELR_HSE 0x00000001 +#define RCC_ASSCKSELR_PLL 0x00000002 +#define RCC_ASSCKSELR_AXISSRC_MASK GENMASK(2, 0) +#define RCC_ASSCKSELR_AXISSRC_SHIFT 0 +#define RCC_ASSCKSELR_AXISSRCRDY BIT(31) + +/* RCC_RCK12SELR register fields */ +#define RCC_RCK12SELR_PLL12SRC_MASK GENMASK(1, 0) +#define RCC_RCK12SELR_PLL12SRC_SHIFT 0 +#define RCC_RCK12SELR_PLL12SRCRDY BIT(31) + +/* RCC_MPCKDIVR register fields */ +#define RCC_MPCKDIVR_MPUDIV_MASK GENMASK(2, 0) +#define RCC_MPCKDIVR_MPUDIV_SHIFT 0 +#define RCC_MPCKDIVR_MPUDIVRDY BIT(31) + +/* RCC_AXIDIVR register fields */ +#define RCC_AXIDIVR_AXIDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIVR_AXIDIV_SHIFT 0 +#define RCC_AXIDIVR_AXIDIVRDY BIT(31) + +/* RCC_APB4DIVR register fields */ +#define RCC_APB4DIVR_APB4DIV_MASK GENMASK(2, 0) +#define RCC_APB4DIVR_APB4DIV_SHIFT 0 +#define RCC_APB4DIVR_APB4DIVRDY BIT(31) + +/* RCC_APB5DIVR register fields */ +#define RCC_APB5DIVR_APB5DIV_MASK GENMASK(2, 0) +#define RCC_APB5DIVR_APB5DIV_SHIFT 0 +#define RCC_APB5DIVR_APB5DIVRDY BIT(31) + +/* RCC_RTCDIVR register fields */ +#define RCC_RTCDIVR_RTCDIV_MASK GENMASK(5, 0) +#define RCC_RTCDIVR_RTCDIV_SHIFT 0 + +/* RCC_MSSCKSELR register fields */ +#define RCC_MSSCKSELR_HSI 0x00000000 +#define RCC_MSSCKSELR_HSE 0x00000001 +#define RCC_MSSCKSELR_CSI 0x00000002 +#define RCC_MSSCKSELR_PLL 0x00000003 +#define RCC_MSSCKSELR_MCUSSRC_MASK GENMASK(1, 0) +#define RCC_MSSCKSELR_MCUSSRC_SHIFT 0 +#define RCC_MSSCKSELR_MCUSSRCRDY BIT(31) + +/* RCC_PLL1CR register fields */ +#define RCC_PLL1CR_PLLON BIT(0) +#define RCC_PLL1CR_PLL1RDY BIT(1) +#define RCC_PLL1CR_SSCG_CTRL BIT(2) +#define RCC_PLL1CR_DIVPEN BIT(4) +#define RCC_PLL1CR_DIVQEN BIT(5) +#define RCC_PLL1CR_DIVREN BIT(6) + +/* RCC_PLL1CFGR1 register fields */ +#define RCC_PLL1CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL1CFGR1_DIVN_SHIFT 0 +#define RCC_PLL1CFGR1_DIVM1_MASK GENMASK(21, 16) +#define RCC_PLL1CFGR1_DIVM1_SHIFT 16 + +/* RCC_PLL1CFGR2 register fields */ +#define RCC_PLL1CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL1CFGR2_DIVP_SHIFT 0 +#define RCC_PLL1CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL1CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL1CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL1CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL1FRACR register fields */ +#define RCC_PLL1FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL1FRACR_FRACV_SHIFT 3 +#define RCC_PLL1FRACR_FRACLE BIT(16) + +/* RCC_PLL1CSGR register fields */ +#define RCC_PLL1CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL1CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL1CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL1CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL1CSGR_SSCG_MODE BIT(15) +#define RCC_PLL1CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL1CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL2CR register fields */ +#define RCC_PLL2CR_PLLON BIT(0) +#define RCC_PLL2CR_PLL2RDY BIT(1) +#define RCC_PLL2CR_SSCG_CTRL BIT(2) +#define RCC_PLL2CR_DIVPEN BIT(4) +#define RCC_PLL2CR_DIVQEN BIT(5) +#define RCC_PLL2CR_DIVREN BIT(6) + +/* RCC_PLL2CFGR1 register fields */ +#define RCC_PLL2CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL2CFGR1_DIVN_SHIFT 0 +#define RCC_PLL2CFGR1_DIVM2_MASK GENMASK(21, 16) +#define RCC_PLL2CFGR1_DIVM2_SHIFT 16 + +/* RCC_PLL2CFGR2 register fields */ +#define RCC_PLL2CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL2CFGR2_DIVP_SHIFT 0 +#define RCC_PLL2CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL2CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL2CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL2CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL2FRACR register fields */ +#define RCC_PLL2FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL2FRACR_FRACV_SHIFT 3 +#define RCC_PLL2FRACR_FRACLE BIT(16) + +/* RCC_PLL2CSGR register fields */ +#define RCC_PLL2CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL2CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL2CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL2CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL2CSGR_SSCG_MODE BIT(15) +#define RCC_PLL2CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL2CSGR_INC_STEP_SHIFT 16 + +/* RCC_I2C46CKSELR register fields */ +#define RCC_I2C46CKSELR_I2C46SRC_MASK GENMASK(2, 0) +#define RCC_I2C46CKSELR_I2C46SRC_SHIFT 0 + +/* RCC_SPI6CKSELR register fields */ +#define RCC_SPI6CKSELR_SPI6SRC_MASK GENMASK(2, 0) +#define RCC_SPI6CKSELR_SPI6SRC_SHIFT 0 + +/* RCC_UART1CKSELR register fields */ +#define RCC_UART1CKSELR_UART1SRC_MASK GENMASK(2, 0) +#define RCC_UART1CKSELR_UART1SRC_SHIFT 0 + +/* RCC_RNG1CKSELR register fields */ +#define RCC_RNG1CKSELR_RNG1SRC_MASK GENMASK(1, 0) +#define RCC_RNG1CKSELR_RNG1SRC_SHIFT 0 + +/* RCC_CPERCKSELR register fields */ +#define RCC_CPERCKSELR_HSI 0x00000000 +#define RCC_CPERCKSELR_CSI 0x00000001 +#define RCC_CPERCKSELR_HSE 0x00000002 +#define RCC_CPERCKSELR_CKPERSRC_MASK GENMASK(1, 0) +#define RCC_CPERCKSELR_CKPERSRC_SHIFT 0 + +/* RCC_STGENCKSELR register fields */ +#define RCC_STGENCKSELR_STGENSRC_MASK GENMASK(1, 0) +#define RCC_STGENCKSELR_STGENSRC_SHIFT 0 + +/* RCC_DDRITFCR register fields */ +#define RCC_DDRITFCR_DDRC1EN BIT(0) +#define RCC_DDRITFCR_DDRC1LPEN BIT(1) +#define RCC_DDRITFCR_DDRC2EN BIT(2) +#define RCC_DDRITFCR_DDRC2LPEN BIT(3) +#define RCC_DDRITFCR_DDRPHYCEN BIT(4) +#define RCC_DDRITFCR_DDRPHYCLPEN BIT(5) +#define RCC_DDRITFCR_DDRCAPBEN BIT(6) +#define RCC_DDRITFCR_DDRCAPBLPEN BIT(7) +#define RCC_DDRITFCR_AXIDCGEN BIT(8) +#define RCC_DDRITFCR_DDRPHYCAPBEN BIT(9) +#define RCC_DDRITFCR_DDRPHYCAPBLPEN BIT(10) +#define RCC_DDRITFCR_KERDCG_DLY_MASK GENMASK(13, 11) +#define RCC_DDRITFCR_KERDCG_DLY_SHIFT 11 +#define RCC_DDRITFCR_DDRCAPBRST BIT(14) +#define RCC_DDRITFCR_DDRCAXIRST BIT(15) +#define RCC_DDRITFCR_DDRCORERST BIT(16) +#define RCC_DDRITFCR_DPHYAPBRST BIT(17) +#define RCC_DDRITFCR_DPHYRST BIT(18) +#define RCC_DDRITFCR_DPHYCTLRST BIT(19) +#define RCC_DDRITFCR_DDRCKMOD_MASK GENMASK(22, 20) +#define RCC_DDRITFCR_DDRCKMOD_SHIFT 20 +#define RCC_DDRITFCR_DDRCKMOD_SSR 0 +#define RCC_DDRITFCR_DDRCKMOD_ASR1 BIT(20) +#define RCC_DDRITFCR_DDRCKMOD_HSR1 BIT(21) +#define RCC_DDRITFCR_GSKPMOD BIT(23) +#define RCC_DDRITFCR_GSKPCTRL BIT(24) +#define RCC_DDRITFCR_DFILP_WIDTH_MASK GENMASK(27, 25) +#define RCC_DDRITFCR_DFILP_WIDTH_SHIFT 25 +#define RCC_DDRITFCR_GSKP_DUR_MASK GENMASK(31, 28) +#define RCC_DDRITFCR_GSKP_DUR_SHIFT 28 + +/* RCC_MP_BOOTCR register fields */ +#define RCC_MP_BOOTCR_MCU_BEN BIT(0) +#define RCC_MP_BOOTCR_MPU_BEN BIT(1) + +/* RCC_MP_SREQSETR register fields */ +#define RCC_MP_SREQSETR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQSETR_STPREQ_P1 BIT(1) + +/* RCC_MP_SREQCLRR register fields */ +#define RCC_MP_SREQCLRR_STPREQ_P0 BIT(0) +#define RCC_MP_SREQCLRR_STPREQ_P1 BIT(1) + +/* RCC_MP_GCR register fields */ +#define RCC_MP_GCR_BOOT_MCU BIT(0) + +/* RCC_MP_APRSTCR register fields */ +#define RCC_MP_APRSTCR_RDCTLEN BIT(0) +#define RCC_MP_APRSTCR_RSTTO_MASK GENMASK(14, 8) +#define RCC_MP_APRSTCR_RSTTO_SHIFT 8 + +/* RCC_MP_APRSTSR register fields */ +#define RCC_MP_APRSTSR_RSTTOV_MASK GENMASK(14, 8) +#define RCC_MP_APRSTSR_RSTTOV_SHIFT 8 + +/* RCC_BDCR register fields */ +#define RCC_BDCR_LSEON BIT(0) +#define RCC_BDCR_LSEBYP BIT(1) +#define RCC_BDCR_LSERDY BIT(2) +#define RCC_BDCR_DIGBYP BIT(3) +#define RCC_BDCR_LSEDRV_MASK GENMASK(5, 4) +#define RCC_BDCR_LSEDRV_SHIFT 4 +#define RCC_BDCR_LSECSSON BIT(8) +#define RCC_BDCR_LSECSSD BIT(9) +#define RCC_BDCR_RTCSRC_MASK GENMASK(17, 16) +#define RCC_BDCR_RTCSRC_SHIFT 16 +#define RCC_BDCR_RTCCKEN BIT(20) +#define RCC_BDCR_VSWRST BIT(31) + +/* RCC_RDLSICR register fields */ +#define RCC_RDLSICR_LSION BIT(0) +#define RCC_RDLSICR_LSIRDY BIT(1) +#define RCC_RDLSICR_MRD_MASK GENMASK(20, 16) +#define RCC_RDLSICR_MRD_SHIFT 16 +#define RCC_RDLSICR_EADLY_MASK GENMASK(26, 24) +#define RCC_RDLSICR_EADLY_SHIFT 24 +#define RCC_RDLSICR_SPARE_MASK GENMASK(31, 27) +#define RCC_RDLSICR_SPARE_SHIFT 27 + +/* RCC_APB4RSTSETR register fields */ +#define RCC_APB4RSTSETR_LTDCRST BIT(0) +#define RCC_APB4RSTSETR_DSIRST BIT(4) +#define RCC_APB4RSTSETR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTSETR_USBPHYRST BIT(16) + +/* RCC_APB4RSTCLRR register fields */ +#define RCC_APB4RSTCLRR_LTDCRST BIT(0) +#define RCC_APB4RSTCLRR_DSIRST BIT(4) +#define RCC_APB4RSTCLRR_DDRPERFMRST BIT(8) +#define RCC_APB4RSTCLRR_USBPHYRST BIT(16) + +/* RCC_APB5RSTSETR register fields */ +#define RCC_APB5RSTSETR_SPI6RST BIT(0) +#define RCC_APB5RSTSETR_I2C4RST BIT(2) +#define RCC_APB5RSTSETR_I2C6RST BIT(3) +#define RCC_APB5RSTSETR_USART1RST BIT(4) +#define RCC_APB5RSTSETR_STGENRST BIT(20) + +/* RCC_APB5RSTCLRR register fields */ +#define RCC_APB5RSTCLRR_SPI6RST BIT(0) +#define RCC_APB5RSTCLRR_I2C4RST BIT(2) +#define RCC_APB5RSTCLRR_I2C6RST BIT(3) +#define RCC_APB5RSTCLRR_USART1RST BIT(4) +#define RCC_APB5RSTCLRR_STGENRST BIT(20) + +/* RCC_AHB5RSTSETR register fields */ +#define RCC_AHB5RSTSETR_GPIOZRST BIT(0) +#define RCC_AHB5RSTSETR_CRYP1RST BIT(4) +#define RCC_AHB5RSTSETR_HASH1RST BIT(5) +#define RCC_AHB5RSTSETR_RNG1RST BIT(6) +#define RCC_AHB5RSTSETR_AXIMCRST BIT(16) + +/* RCC_AHB5RSTCLRR register fields */ +#define RCC_AHB5RSTCLRR_GPIOZRST BIT(0) +#define RCC_AHB5RSTCLRR_CRYP1RST BIT(4) +#define RCC_AHB5RSTCLRR_HASH1RST BIT(5) +#define RCC_AHB5RSTCLRR_RNG1RST BIT(6) +#define RCC_AHB5RSTCLRR_AXIMCRST BIT(16) + +/* RCC_AHB6RSTSETR register fields */ +#define RCC_AHB6RSTSETR_GPURST BIT(5) +#define RCC_AHB6RSTSETR_ETHMACRST BIT(10) +#define RCC_AHB6RSTSETR_FMCRST BIT(12) +#define RCC_AHB6RSTSETR_QSPIRST BIT(14) +#define RCC_AHB6RSTSETR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTSETR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTSETR_CRC1RST BIT(20) +#define RCC_AHB6RSTSETR_USBHRST BIT(24) + +/* RCC_AHB6RSTCLRR register fields */ +#define RCC_AHB6RSTCLRR_ETHMACRST BIT(10) +#define RCC_AHB6RSTCLRR_FMCRST BIT(12) +#define RCC_AHB6RSTCLRR_QSPIRST BIT(14) +#define RCC_AHB6RSTCLRR_SDMMC1RST BIT(16) +#define RCC_AHB6RSTCLRR_SDMMC2RST BIT(17) +#define RCC_AHB6RSTCLRR_CRC1RST BIT(20) +#define RCC_AHB6RSTCLRR_USBHRST BIT(24) + +/* RCC_TZAHB6RSTSETR register fields */ +#define RCC_TZAHB6RSTSETR_MDMARST BIT(0) + +/* RCC_TZAHB6RSTCLRR register fields */ +#define RCC_TZAHB6RSTCLRR_MDMARST BIT(0) + +/* RCC_MP_APB4ENSETR register fields */ +#define RCC_MP_APB4ENSETR_LTDCEN BIT(0) +#define RCC_MP_APB4ENSETR_DSIEN BIT(4) +#define RCC_MP_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENSETR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MP_APB4ENCLRR register fields */ +#define RCC_MP_APB4ENCLRR_LTDCEN BIT(0) +#define RCC_MP_APB4ENCLRR_DSIEN BIT(4) +#define RCC_MP_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MP_APB4ENCLRR_IWDG2APBEN BIT(15) +#define RCC_MP_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MP_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MP_APB5ENSETR register fields */ +#define RCC_MP_APB5ENSETR_SPI6EN BIT(0) +#define RCC_MP_APB5ENSETR_I2C4EN BIT(2) +#define RCC_MP_APB5ENSETR_I2C6EN BIT(3) +#define RCC_MP_APB5ENSETR_USART1EN BIT(4) +#define RCC_MP_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENSETR_TZC1EN BIT(11) +#define RCC_MP_APB5ENSETR_TZC2EN BIT(12) +#define RCC_MP_APB5ENSETR_TZPCEN BIT(13) +#define RCC_MP_APB5ENSETR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENSETR_BSECEN BIT(16) +#define RCC_MP_APB5ENSETR_STGENEN BIT(20) + +/* RCC_MP_APB5ENCLRR register fields */ +#define RCC_MP_APB5ENCLRR_SPI6EN BIT(0) +#define RCC_MP_APB5ENCLRR_I2C4EN BIT(2) +#define RCC_MP_APB5ENCLRR_I2C6EN BIT(3) +#define RCC_MP_APB5ENCLRR_USART1EN BIT(4) +#define RCC_MP_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MP_APB5ENCLRR_TZC1EN BIT(11) +#define RCC_MP_APB5ENCLRR_TZC2EN BIT(12) +#define RCC_MP_APB5ENCLRR_TZPCEN BIT(13) +#define RCC_MP_APB5ENCLRR_IWDG1APBEN BIT(15) +#define RCC_MP_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MP_APB5ENCLRR_STGENEN BIT(20) + +/* RCC_MP_AHB5ENSETR register fields */ +#define RCC_MP_AHB5ENSETR_GPIOZEN BIT(0) +#define RCC_MP_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENSETR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENSETR_AXIMCEN BIT(16) + +/* RCC_MP_AHB5ENCLRR register fields */ +#define RCC_MP_AHB5ENCLRR_GPIOZEN BIT(0) +#define RCC_MP_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MP_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MP_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MP_AHB5ENCLRR_BKPSRAMEN BIT(8) +#define RCC_MP_AHB5ENCLRR_AXIMCEN BIT(16) + +/* RCC_MP_AHB6ENSETR register fields */ +#define RCC_MP_AHB6ENSETR_MDMAEN BIT(0) +#define RCC_MP_AHB6ENSETR_GPUEN BIT(5) +#define RCC_MP_AHB6ENSETR_ETHCKEN BIT(7) +#define RCC_MP_AHB6ENSETR_ETHTXEN BIT(8) +#define RCC_MP_AHB6ENSETR_ETHRXEN BIT(9) +#define RCC_MP_AHB6ENSETR_ETHMACEN BIT(10) +#define RCC_MP_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MP_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENSETR_USBHEN BIT(24) + +/* RCC_MP_AHB6ENCLRR register fields */ +#define RCC_MP_AHB6ENCLRR_MDMAEN BIT(0) +#define RCC_MP_AHB6ENCLRR_GPUEN BIT(5) +#define RCC_MP_AHB6ENCLRR_ETHCKEN BIT(7) +#define RCC_MP_AHB6ENCLRR_ETHTXEN BIT(8) +#define RCC_MP_AHB6ENCLRR_ETHRXEN BIT(9) +#define RCC_MP_AHB6ENCLRR_ETHMACEN BIT(10) +#define RCC_MP_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MP_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MP_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MP_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MP_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MP_AHB6ENCLRR_USBHEN BIT(24) + +/* RCC_MP_TZAHB6ENSETR register fields */ +#define RCC_MP_TZAHB6ENSETR_MDMAEN BIT(0) + +/* RCC_MP_TZAHB6ENCLRR register fields */ +#define RCC_MP_TZAHB6ENCLRR_MDMAEN BIT(0) + +/* RCC_MC_APB4ENSETR register fields */ +#define RCC_MC_APB4ENSETR_LTDCEN BIT(0) +#define RCC_MC_APB4ENSETR_DSIEN BIT(4) +#define RCC_MC_APB4ENSETR_DDRPERFMEN BIT(8) +#define RCC_MC_APB4ENSETR_USBPHYEN BIT(16) +#define RCC_MC_APB4ENSETR_STGENROEN BIT(20) + +/* RCC_MC_APB4ENCLRR register fields */ +#define RCC_MC_APB4ENCLRR_LTDCEN BIT(0) +#define RCC_MC_APB4ENCLRR_DSIEN BIT(4) +#define RCC_MC_APB4ENCLRR_DDRPERFMEN BIT(8) +#define RCC_MC_APB4ENCLRR_USBPHYEN BIT(16) +#define RCC_MC_APB4ENCLRR_STGENROEN BIT(20) + +/* RCC_MC_APB5ENSETR register fields */ +#define RCC_MC_APB5ENSETR_SPI6EN BIT(0) +#define RCC_MC_APB5ENSETR_I2C4EN BIT(2) +#define RCC_MC_APB5ENSETR_I2C6EN BIT(3) +#define RCC_MC_APB5ENSETR_USART1EN BIT(4) +#define RCC_MC_APB5ENSETR_RTCAPBEN BIT(8) +#define RCC_MC_APB5ENSETR_TZC1EN BIT(11) +#define RCC_MC_APB5ENSETR_TZC2EN BIT(12) +#define RCC_MC_APB5ENSETR_TZPCEN BIT(13) +#define RCC_MC_APB5ENSETR_BSECEN BIT(16) +#define RCC_MC_APB5ENSETR_STGENEN BIT(20) + +/* RCC_MC_APB5ENCLRR register fields */ +#define RCC_MC_APB5ENCLRR_SPI6EN BIT(0) +#define RCC_MC_APB5ENCLRR_I2C4EN BIT(2) +#define RCC_MC_APB5ENCLRR_I2C6EN BIT(3) +#define RCC_MC_APB5ENCLRR_USART1EN BIT(4) +#define RCC_MC_APB5ENCLRR_RTCAPBEN BIT(8) +#define RCC_MC_APB5ENCLRR_TZC1EN BIT(11) +#define RCC_MC_APB5ENCLRR_TZC2EN BIT(12) +#define RCC_MC_APB5ENCLRR_TZPCEN BIT(13) +#define RCC_MC_APB5ENCLRR_BSECEN BIT(16) +#define RCC_MC_APB5ENCLRR_STGENEN BIT(20) + +/* RCC_MC_AHB5ENSETR register fields */ +#define RCC_MC_AHB5ENSETR_GPIOZEN BIT(0) +#define RCC_MC_AHB5ENSETR_CRYP1EN BIT(4) +#define RCC_MC_AHB5ENSETR_HASH1EN BIT(5) +#define RCC_MC_AHB5ENSETR_RNG1EN BIT(6) +#define RCC_MC_AHB5ENSETR_BKPSRAMEN BIT(8) + +/* RCC_MC_AHB5ENCLRR register fields */ +#define RCC_MC_AHB5ENCLRR_GPIOZEN BIT(0) +#define RCC_MC_AHB5ENCLRR_CRYP1EN BIT(4) +#define RCC_MC_AHB5ENCLRR_HASH1EN BIT(5) +#define RCC_MC_AHB5ENCLRR_RNG1EN BIT(6) +#define RCC_MC_AHB5ENCLRR_BKPSRAMEN BIT(8) + +/* RCC_MC_AHB6ENSETR register fields */ +#define RCC_MC_AHB6ENSETR_MDMAEN BIT(0) +#define RCC_MC_AHB6ENSETR_GPUEN BIT(5) +#define RCC_MC_AHB6ENSETR_ETHCKEN BIT(7) +#define RCC_MC_AHB6ENSETR_ETHTXEN BIT(8) +#define RCC_MC_AHB6ENSETR_ETHRXEN BIT(9) +#define RCC_MC_AHB6ENSETR_ETHMACEN BIT(10) +#define RCC_MC_AHB6ENSETR_FMCEN BIT(12) +#define RCC_MC_AHB6ENSETR_QSPIEN BIT(14) +#define RCC_MC_AHB6ENSETR_SDMMC1EN BIT(16) +#define RCC_MC_AHB6ENSETR_SDMMC2EN BIT(17) +#define RCC_MC_AHB6ENSETR_CRC1EN BIT(20) +#define RCC_MC_AHB6ENSETR_USBHEN BIT(24) + +/* RCC_MC_AHB6ENCLRR register fields */ +#define RCC_MC_AHB6ENCLRR_MDMAEN BIT(0) +#define RCC_MC_AHB6ENCLRR_GPUEN BIT(5) +#define RCC_MC_AHB6ENCLRR_ETHCKEN BIT(7) +#define RCC_MC_AHB6ENCLRR_ETHTXEN BIT(8) +#define RCC_MC_AHB6ENCLRR_ETHRXEN BIT(9) +#define RCC_MC_AHB6ENCLRR_ETHMACEN BIT(10) +#define RCC_MC_AHB6ENCLRR_FMCEN BIT(12) +#define RCC_MC_AHB6ENCLRR_QSPIEN BIT(14) +#define RCC_MC_AHB6ENCLRR_SDMMC1EN BIT(16) +#define RCC_MC_AHB6ENCLRR_SDMMC2EN BIT(17) +#define RCC_MC_AHB6ENCLRR_CRC1EN BIT(20) +#define RCC_MC_AHB6ENCLRR_USBHEN BIT(24) + +/* RCC_MP_APB4LPENSETR register fields */ +#define RCC_MP_APB4LPENSETR_LTDCLPEN BIT(0) +#define RCC_MP_APB4LPENSETR_DSILPEN BIT(4) +#define RCC_MP_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENSETR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB4LPENCLRR register fields */ +#define RCC_MP_APB4LPENCLRR_LTDCLPEN BIT(0) +#define RCC_MP_APB4LPENCLRR_DSILPEN BIT(4) +#define RCC_MP_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MP_APB4LPENCLRR_IWDG2APBLPEN BIT(15) +#define RCC_MP_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MP_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MP_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MP_APB5LPENSETR register fields */ +#define RCC_MP_APB5LPENSETR_SPI6LPEN BIT(0) +#define RCC_MP_APB5LPENSETR_I2C4LPEN BIT(2) +#define RCC_MP_APB5LPENSETR_I2C6LPEN BIT(3) +#define RCC_MP_APB5LPENSETR_USART1LPEN BIT(4) +#define RCC_MP_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENSETR_TZC1LPEN BIT(11) +#define RCC_MP_APB5LPENSETR_TZC2LPEN BIT(12) +#define RCC_MP_APB5LPENSETR_TZPCLPEN BIT(13) +#define RCC_MP_APB5LPENSETR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENSETR_STGENLPEN BIT(20) +#define RCC_MP_APB5LPENSETR_STGENSTPEN BIT(21) + +/* RCC_MP_APB5LPENCLRR register fields */ +#define RCC_MP_APB5LPENCLRR_SPI6LPEN BIT(0) +#define RCC_MP_APB5LPENCLRR_I2C4LPEN BIT(2) +#define RCC_MP_APB5LPENCLRR_I2C6LPEN BIT(3) +#define RCC_MP_APB5LPENCLRR_USART1LPEN BIT(4) +#define RCC_MP_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MP_APB5LPENCLRR_TZC1LPEN BIT(11) +#define RCC_MP_APB5LPENCLRR_TZC2LPEN BIT(12) +#define RCC_MP_APB5LPENCLRR_TZPCLPEN BIT(13) +#define RCC_MP_APB5LPENCLRR_IWDG1APBLPEN BIT(15) +#define RCC_MP_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MP_APB5LPENCLRR_STGENLPEN BIT(20) +#define RCC_MP_APB5LPENCLRR_STGENSTPEN BIT(21) + +/* RCC_MP_AHB5LPENSETR register fields */ +#define RCC_MP_AHB5LPENSETR_GPIOZLPEN BIT(0) +#define RCC_MP_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB5LPENCLRR register fields */ +#define RCC_MP_AHB5LPENCLRR_GPIOZLPEN BIT(0) +#define RCC_MP_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MP_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MP_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MP_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MP_AHB6LPENSETR register fields */ +#define RCC_MP_AHB6LPENSETR_MDMALPEN BIT(0) +#define RCC_MP_AHB6LPENSETR_GPULPEN BIT(5) +#define RCC_MP_AHB6LPENSETR_ETHCKLPEN BIT(7) +#define RCC_MP_AHB6LPENSETR_ETHTXLPEN BIT(8) +#define RCC_MP_AHB6LPENSETR_ETHRXLPEN BIT(9) +#define RCC_MP_AHB6LPENSETR_ETHMACLPEN BIT(10) +#define RCC_MP_AHB6LPENSETR_ETHSTPEN BIT(11) +#define RCC_MP_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENSETR_USBHLPEN BIT(24) + +/* RCC_MP_AHB6LPENCLRR register fields */ +#define RCC_MP_AHB6LPENCLRR_MDMALPEN BIT(0) +#define RCC_MP_AHB6LPENCLRR_GPULPEN BIT(5) +#define RCC_MP_AHB6LPENCLRR_ETHCKLPEN BIT(7) +#define RCC_MP_AHB6LPENCLRR_ETHTXLPEN BIT(8) +#define RCC_MP_AHB6LPENCLRR_ETHRXLPEN BIT(9) +#define RCC_MP_AHB6LPENCLRR_ETHMACLPEN BIT(10) +#define RCC_MP_AHB6LPENCLRR_ETHSTPEN BIT(11) +#define RCC_MP_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MP_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MP_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MP_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MP_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MP_AHB6LPENCLRR_USBHLPEN BIT(24) + +/* RCC_MP_TZAHB6LPENSETR register fields */ +#define RCC_MP_TZAHB6LPENSETR_MDMALPEN BIT(0) + +/* RCC_MP_TZAHB6LPENCLRR register fields */ +#define RCC_MP_TZAHB6LPENCLRR_MDMALPEN BIT(0) + +/* RCC_MC_APB4LPENSETR register fields */ +#define RCC_MC_APB4LPENSETR_LTDCLPEN BIT(0) +#define RCC_MC_APB4LPENSETR_DSILPEN BIT(4) +#define RCC_MC_APB4LPENSETR_DDRPERFMLPEN BIT(8) +#define RCC_MC_APB4LPENSETR_USBPHYLPEN BIT(16) +#define RCC_MC_APB4LPENSETR_STGENROLPEN BIT(20) +#define RCC_MC_APB4LPENSETR_STGENROSTPEN BIT(21) + +/* RCC_MC_APB4LPENCLRR register fields */ +#define RCC_MC_APB4LPENCLRR_LTDCLPEN BIT(0) +#define RCC_MC_APB4LPENCLRR_DSILPEN BIT(4) +#define RCC_MC_APB4LPENCLRR_DDRPERFMLPEN BIT(8) +#define RCC_MC_APB4LPENCLRR_USBPHYLPEN BIT(16) +#define RCC_MC_APB4LPENCLRR_STGENROLPEN BIT(20) +#define RCC_MC_APB4LPENCLRR_STGENROSTPEN BIT(21) + +/* RCC_MC_APB5LPENSETR register fields */ +#define RCC_MC_APB5LPENSETR_SPI6LPEN BIT(0) +#define RCC_MC_APB5LPENSETR_I2C4LPEN BIT(2) +#define RCC_MC_APB5LPENSETR_I2C6LPEN BIT(3) +#define RCC_MC_APB5LPENSETR_USART1LPEN BIT(4) +#define RCC_MC_APB5LPENSETR_RTCAPBLPEN BIT(8) +#define RCC_MC_APB5LPENSETR_TZC1LPEN BIT(11) +#define RCC_MC_APB5LPENSETR_TZC2LPEN BIT(12) +#define RCC_MC_APB5LPENSETR_TZPCLPEN BIT(13) +#define RCC_MC_APB5LPENSETR_BSECLPEN BIT(16) +#define RCC_MC_APB5LPENSETR_STGENLPEN BIT(20) +#define RCC_MC_APB5LPENSETR_STGENSTPEN BIT(21) + +/* RCC_MC_APB5LPENCLRR register fields */ +#define RCC_MC_APB5LPENCLRR_SPI6LPEN BIT(0) +#define RCC_MC_APB5LPENCLRR_I2C4LPEN BIT(2) +#define RCC_MC_APB5LPENCLRR_I2C6LPEN BIT(3) +#define RCC_MC_APB5LPENCLRR_USART1LPEN BIT(4) +#define RCC_MC_APB5LPENCLRR_RTCAPBLPEN BIT(8) +#define RCC_MC_APB5LPENCLRR_TZC1LPEN BIT(11) +#define RCC_MC_APB5LPENCLRR_TZC2LPEN BIT(12) +#define RCC_MC_APB5LPENCLRR_TZPCLPEN BIT(13) +#define RCC_MC_APB5LPENCLRR_BSECLPEN BIT(16) +#define RCC_MC_APB5LPENCLRR_STGENLPEN BIT(20) +#define RCC_MC_APB5LPENCLRR_STGENSTPEN BIT(21) + +/* RCC_MC_AHB5LPENSETR register fields */ +#define RCC_MC_AHB5LPENSETR_GPIOZLPEN BIT(0) +#define RCC_MC_AHB5LPENSETR_CRYP1LPEN BIT(4) +#define RCC_MC_AHB5LPENSETR_HASH1LPEN BIT(5) +#define RCC_MC_AHB5LPENSETR_RNG1LPEN BIT(6) +#define RCC_MC_AHB5LPENSETR_BKPSRAMLPEN BIT(8) + +/* RCC_MC_AHB5LPENCLRR register fields */ +#define RCC_MC_AHB5LPENCLRR_GPIOZLPEN BIT(0) +#define RCC_MC_AHB5LPENCLRR_CRYP1LPEN BIT(4) +#define RCC_MC_AHB5LPENCLRR_HASH1LPEN BIT(5) +#define RCC_MC_AHB5LPENCLRR_RNG1LPEN BIT(6) +#define RCC_MC_AHB5LPENCLRR_BKPSRAMLPEN BIT(8) + +/* RCC_MC_AHB6LPENSETR register fields */ +#define RCC_MC_AHB6LPENSETR_MDMALPEN BIT(0) +#define RCC_MC_AHB6LPENSETR_GPULPEN BIT(5) +#define RCC_MC_AHB6LPENSETR_ETHCKLPEN BIT(7) +#define RCC_MC_AHB6LPENSETR_ETHTXLPEN BIT(8) +#define RCC_MC_AHB6LPENSETR_ETHRXLPEN BIT(9) +#define RCC_MC_AHB6LPENSETR_ETHMACLPEN BIT(10) +#define RCC_MC_AHB6LPENSETR_ETHSTPEN BIT(11) +#define RCC_MC_AHB6LPENSETR_FMCLPEN BIT(12) +#define RCC_MC_AHB6LPENSETR_QSPILPEN BIT(14) +#define RCC_MC_AHB6LPENSETR_SDMMC1LPEN BIT(16) +#define RCC_MC_AHB6LPENSETR_SDMMC2LPEN BIT(17) +#define RCC_MC_AHB6LPENSETR_CRC1LPEN BIT(20) +#define RCC_MC_AHB6LPENSETR_USBHLPEN BIT(24) + +/* RCC_MC_AHB6LPENCLRR register fields */ +#define RCC_MC_AHB6LPENCLRR_MDMALPEN BIT(0) +#define RCC_MC_AHB6LPENCLRR_GPULPEN BIT(5) +#define RCC_MC_AHB6LPENCLRR_ETHCKLPEN BIT(7) +#define RCC_MC_AHB6LPENCLRR_ETHTXLPEN BIT(8) +#define RCC_MC_AHB6LPENCLRR_ETHRXLPEN BIT(9) +#define RCC_MC_AHB6LPENCLRR_ETHMACLPEN BIT(10) +#define RCC_MC_AHB6LPENCLRR_ETHSTPEN BIT(11) +#define RCC_MC_AHB6LPENCLRR_FMCLPEN BIT(12) +#define RCC_MC_AHB6LPENCLRR_QSPILPEN BIT(14) +#define RCC_MC_AHB6LPENCLRR_SDMMC1LPEN BIT(16) +#define RCC_MC_AHB6LPENCLRR_SDMMC2LPEN BIT(17) +#define RCC_MC_AHB6LPENCLRR_CRC1LPEN BIT(20) +#define RCC_MC_AHB6LPENCLRR_USBHLPEN BIT(24) + +/* RCC_BR_RSTSCLRR register fields */ +#define RCC_BR_RSTSCLRR_PORRSTF BIT(0) +#define RCC_BR_RSTSCLRR_BORRSTF BIT(1) +#define RCC_BR_RSTSCLRR_PADRSTF BIT(2) +#define RCC_BR_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_BR_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_BR_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_BR_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_BR_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_BR_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_BR_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_BR_RSTSCLRR_MPUP1RSTF BIT(14) + +/* RCC_MP_GRSTCSETR register fields */ +#define RCC_MP_GRSTCSETR_MPSYSRST BIT(0) +#define RCC_MP_GRSTCSETR_MCURST BIT(1) +#define RCC_MP_GRSTCSETR_MPUP0RST BIT(4) +#define RCC_MP_GRSTCSETR_MPUP1RST BIT(5) + +/* RCC_MP_RSTSCLRR register fields */ +#define RCC_MP_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MP_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MP_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MP_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MP_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSCLRR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSCLRR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSCLRR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSCLRR_MPUP1RSTF BIT(14) +#define RCC_MP_RSTSCLRR_SPARE BIT(15) + +/* RCC_MP_IWDGFZSETR register fields */ +#define RCC_MP_IWDGFZSETR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZSETR_FZ_IWDG2 BIT(1) + +/* RCC_MP_IWDGFZCLRR register fields */ +#define RCC_MP_IWDGFZCLRR_FZ_IWDG1 BIT(0) +#define RCC_MP_IWDGFZCLRR_FZ_IWDG2 BIT(1) + +/* RCC_MP_CIER register fields */ +#define RCC_MP_CIER_LSIRDYIE BIT(0) +#define RCC_MP_CIER_LSERDYIE BIT(1) +#define RCC_MP_CIER_HSIRDYIE BIT(2) +#define RCC_MP_CIER_HSERDYIE BIT(3) +#define RCC_MP_CIER_CSIRDYIE BIT(4) +#define RCC_MP_CIER_PLL1DYIE BIT(8) +#define RCC_MP_CIER_PLL2DYIE BIT(9) +#define RCC_MP_CIER_PLL3DYIE BIT(10) +#define RCC_MP_CIER_PLL4DYIE BIT(11) +#define RCC_MP_CIER_LSECSSIE BIT(16) +#define RCC_MP_CIER_WKUPIE BIT(20) + +/* RCC_MP_CIFR register fields */ +#define RCC_MP_CIFR_MASK U(0x110F1F) +#define RCC_MP_CIFR_LSIRDYF BIT(0) +#define RCC_MP_CIFR_LSERDYF BIT(1) +#define RCC_MP_CIFR_HSIRDYF BIT(2) +#define RCC_MP_CIFR_HSERDYF BIT(3) +#define RCC_MP_CIFR_CSIRDYF BIT(4) +#define RCC_MP_CIFR_PLL1DYF BIT(8) +#define RCC_MP_CIFR_PLL2DYF BIT(9) +#define RCC_MP_CIFR_PLL3DYF BIT(10) +#define RCC_MP_CIFR_PLL4DYF BIT(11) +#define RCC_MP_CIFR_LSECSSF BIT(16) +#define RCC_MP_CIFR_WKUPF BIT(20) + +/* RCC_PWRLPDLYCR register fields */ +#define RCC_PWRLPDLYCR_PWRLP_DLY_MASK GENMASK(21, 0) +#define RCC_PWRLPDLYCR_PWRLP_DLY_SHIFT 0 +#define RCC_PWRLPDLYCR_MCTMPSKP BIT(24) + +/* RCC_MP_RSTSSETR register fields */ +#define RCC_MP_RSTSSETR_PORRSTF BIT(0) +#define RCC_MP_RSTSSETR_BORRSTF BIT(1) +#define RCC_MP_RSTSSETR_PADRSTF BIT(2) +#define RCC_MP_RSTSSETR_HCSSRSTF BIT(3) +#define RCC_MP_RSTSSETR_VCORERSTF BIT(4) +#define RCC_MP_RSTSSETR_MPSYSRSTF BIT(6) +#define RCC_MP_RSTSSETR_MCSYSRSTF BIT(7) +#define RCC_MP_RSTSSETR_IWDG1RSTF BIT(8) +#define RCC_MP_RSTSSETR_IWDG2RSTF BIT(9) +#define RCC_MP_RSTSSETR_STDBYRSTF BIT(11) +#define RCC_MP_RSTSSETR_CSTDBYRSTF BIT(12) +#define RCC_MP_RSTSSETR_MPUP0RSTF BIT(13) +#define RCC_MP_RSTSSETR_MPUP1RSTF BIT(14) +#define RCC_MP_RSTSSETR_SPARE BIT(15) + +/* RCC_MCO1CFGR register fields */ +#define RCC_MCO1CFGR_MCO1SEL_MASK GENMASK(2, 0) +#define RCC_MCO1CFGR_MCO1SEL_SHIFT 0 +#define RCC_MCO1CFGR_MCO1DIV_MASK GENMASK(7, 4) +#define RCC_MCO1CFGR_MCO1DIV_SHIFT 4 +#define RCC_MCO1CFGR_MCO1ON BIT(12) + +/* RCC_MCO2CFGR register fields */ +#define RCC_MCO2CFGR_MCO2SEL_MASK GENMASK(2, 0) +#define RCC_MCO2CFGR_MCO2SEL_SHIFT 0 +#define RCC_MCO2CFGR_MCO2DIV_MASK GENMASK(7, 4) +#define RCC_MCO2CFGR_MCO2DIV_SHIFT 4 +#define RCC_MCO2CFGR_MCO2ON BIT(12) + +/* RCC_OCRDYR register fields */ +#define RCC_OCRDYR_HSIRDY BIT(0) +#define RCC_OCRDYR_HSIDIVRDY BIT(2) +#define RCC_OCRDYR_CSIRDY BIT(4) +#define RCC_OCRDYR_HSERDY BIT(8) +#define RCC_OCRDYR_MPUCKRDY BIT(23) +#define RCC_OCRDYR_AXICKRDY BIT(24) +#define RCC_OCRDYR_CKREST BIT(25) + +/* RCC_DBGCFGR register fields */ +#define RCC_DBGCFGR_TRACEDIV_MASK GENMASK(2, 0) +#define RCC_DBGCFGR_TRACEDIV_SHIFT 0 +#define RCC_DBGCFGR_DBGCKEN BIT(8) +#define RCC_DBGCFGR_TRACECKEN BIT(9) +#define RCC_DBGCFGR_DBGRST BIT(12) + +/* RCC_RCK3SELR register fields */ +#define RCC_RCK3SELR_PLL3SRC_MASK GENMASK(1, 0) +#define RCC_RCK3SELR_PLL3SRC_SHIFT 0 +#define RCC_RCK3SELR_PLL3SRCRDY BIT(31) + +/* RCC_RCK4SELR register fields */ +#define RCC_RCK4SELR_PLL4SRC_MASK GENMASK(1, 0) +#define RCC_RCK4SELR_PLL4SRC_SHIFT 0 +#define RCC_RCK4SELR_PLL4SRCRDY BIT(31) + +/* RCC_TIMG1PRER register fields */ +#define RCC_TIMG1PRER_TIMG1PRE BIT(0) +#define RCC_TIMG1PRER_TIMG1PRERDY BIT(31) + +/* RCC_TIMG2PRER register fields */ +#define RCC_TIMG2PRER_TIMG2PRE BIT(0) +#define RCC_TIMG2PRER_TIMG2PRERDY BIT(31) + +/* RCC_MCUDIVR register fields */ +#define RCC_MCUDIVR_MCUDIV_MASK GENMASK(3, 0) +#define RCC_MCUDIVR_MCUDIV_SHIFT 0 +#define RCC_MCUDIVR_MCUDIVRDY BIT(31) + +/* RCC_APB1DIVR register fields */ +#define RCC_APB1DIVR_APB1DIV_MASK GENMASK(2, 0) +#define RCC_APB1DIVR_APB1DIV_SHIFT 0 +#define RCC_APB1DIVR_APB1DIVRDY BIT(31) + +/* RCC_APB2DIVR register fields */ +#define RCC_APB2DIVR_APB2DIV_MASK GENMASK(2, 0) +#define RCC_APB2DIVR_APB2DIV_SHIFT 0 +#define RCC_APB2DIVR_APB2DIVRDY BIT(31) + +/* RCC_APB3DIVR register fields */ +#define RCC_APB3DIVR_APB3DIV_MASK GENMASK(2, 0) +#define RCC_APB3DIVR_APB3DIV_SHIFT 0 +#define RCC_APB3DIVR_APB3DIVRDY BIT(31) + +/* RCC_PLL3CR register fields */ +#define RCC_PLL3CR_PLLON BIT(0) +#define RCC_PLL3CR_PLL3RDY BIT(1) +#define RCC_PLL3CR_SSCG_CTRL BIT(2) +#define RCC_PLL3CR_DIVPEN BIT(4) +#define RCC_PLL3CR_DIVQEN BIT(5) +#define RCC_PLL3CR_DIVREN BIT(6) + +/* RCC_PLL3CFGR1 register fields */ +#define RCC_PLL3CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL3CFGR1_DIVN_SHIFT 0 +#define RCC_PLL3CFGR1_DIVM3_MASK GENMASK(21, 16) +#define RCC_PLL3CFGR1_DIVM3_SHIFT 16 +#define RCC_PLL3CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL3CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL3CFGR2 register fields */ +#define RCC_PLL3CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL3CFGR2_DIVP_SHIFT 0 +#define RCC_PLL3CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL3CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL3CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL3CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL3FRACR register fields */ +#define RCC_PLL3FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL3FRACR_FRACV_SHIFT 3 +#define RCC_PLL3FRACR_FRACLE BIT(16) + +/* RCC_PLL3CSGR register fields */ +#define RCC_PLL3CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL3CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL3CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL3CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL3CSGR_SSCG_MODE BIT(15) +#define RCC_PLL3CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL3CSGR_INC_STEP_SHIFT 16 + +/* RCC_PLL4CR register fields */ +#define RCC_PLL4CR_PLLON BIT(0) +#define RCC_PLL4CR_PLL4RDY BIT(1) +#define RCC_PLL4CR_SSCG_CTRL BIT(2) +#define RCC_PLL4CR_DIVPEN BIT(4) +#define RCC_PLL4CR_DIVQEN BIT(5) +#define RCC_PLL4CR_DIVREN BIT(6) + +/* RCC_PLL4CFGR1 register fields */ +#define RCC_PLL4CFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLL4CFGR1_DIVN_SHIFT 0 +#define RCC_PLL4CFGR1_DIVM4_MASK GENMASK(21, 16) +#define RCC_PLL4CFGR1_DIVM4_SHIFT 16 +#define RCC_PLL4CFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLL4CFGR1_IFRGE_SHIFT 24 + +/* RCC_PLL4CFGR2 register fields */ +#define RCC_PLL4CFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLL4CFGR2_DIVP_SHIFT 0 +#define RCC_PLL4CFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLL4CFGR2_DIVQ_SHIFT 8 +#define RCC_PLL4CFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLL4CFGR2_DIVR_SHIFT 16 + +/* RCC_PLL4FRACR register fields */ +#define RCC_PLL4FRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLL4FRACR_FRACV_SHIFT 3 +#define RCC_PLL4FRACR_FRACLE BIT(16) + +/* RCC_PLL4CSGR register fields */ +#define RCC_PLL4CSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLL4CSGR_MOD_PER_SHIFT 0 +#define RCC_PLL4CSGR_TPDFN_DIS BIT(13) +#define RCC_PLL4CSGR_RPDFN_DIS BIT(14) +#define RCC_PLL4CSGR_SSCG_MODE BIT(15) +#define RCC_PLL4CSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLL4CSGR_INC_STEP_SHIFT 16 + +/* RCC_I2C12CKSELR register fields */ +#define RCC_I2C12CKSELR_I2C12SRC_MASK GENMASK(2, 0) +#define RCC_I2C12CKSELR_I2C12SRC_SHIFT 0 + +/* RCC_I2C35CKSELR register fields */ +#define RCC_I2C35CKSELR_I2C35SRC_MASK GENMASK(2, 0) +#define RCC_I2C35CKSELR_I2C35SRC_SHIFT 0 + +/* RCC_SAI1CKSELR register fields */ +#define RCC_SAI1CKSELR_SAI1SRC_MASK GENMASK(2, 0) +#define RCC_SAI1CKSELR_SAI1SRC_SHIFT 0 + +/* RCC_SAI2CKSELR register fields */ +#define RCC_SAI2CKSELR_SAI2SRC_MASK GENMASK(2, 0) +#define RCC_SAI2CKSELR_SAI2SRC_SHIFT 0 + +/* RCC_SAI3CKSELR register fields */ +#define RCC_SAI3CKSELR_SAI3SRC_MASK GENMASK(2, 0) +#define RCC_SAI3CKSELR_SAI3SRC_SHIFT 0 + +/* RCC_SAI4CKSELR register fields */ +#define RCC_SAI4CKSELR_SAI4SRC_MASK GENMASK(2, 0) +#define RCC_SAI4CKSELR_SAI4SRC_SHIFT 0 + +/* RCC_SPI2S1CKSELR register fields */ +#define RCC_SPI2S1CKSELR_SPI1SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S1CKSELR_SPI1SRC_SHIFT 0 + +/* RCC_SPI2S23CKSELR register fields */ +#define RCC_SPI2S23CKSELR_SPI23SRC_MASK GENMASK(2, 0) +#define RCC_SPI2S23CKSELR_SPI23SRC_SHIFT 0 + +/* RCC_SPI45CKSELR register fields */ +#define RCC_SPI45CKSELR_SPI45SRC_MASK GENMASK(2, 0) +#define RCC_SPI45CKSELR_SPI45SRC_SHIFT 0 + +/* RCC_UART6CKSELR register fields */ +#define RCC_UART6CKSELR_UART6SRC_MASK GENMASK(2, 0) +#define RCC_UART6CKSELR_UART6SRC_SHIFT 0 + +/* RCC_UART24CKSELR register fields */ +#define RCC_UART24CKSELR_HSI 0x00000002 +#define RCC_UART24CKSELR_UART24SRC_MASK GENMASK(2, 0) +#define RCC_UART24CKSELR_UART24SRC_SHIFT 0 + +/* RCC_UART35CKSELR register fields */ +#define RCC_UART35CKSELR_UART35SRC_MASK GENMASK(2, 0) +#define RCC_UART35CKSELR_UART35SRC_SHIFT 0 + +/* RCC_UART78CKSELR register fields */ +#define RCC_UART78CKSELR_UART78SRC_MASK GENMASK(2, 0) +#define RCC_UART78CKSELR_UART78SRC_SHIFT 0 + +/* RCC_SDMMC12CKSELR register fields */ +#define RCC_SDMMC12CKSELR_SDMMC12SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC12CKSELR_SDMMC12SRC_SHIFT 0 + +/* RCC_SDMMC3CKSELR register fields */ +#define RCC_SDMMC3CKSELR_SDMMC3SRC_MASK GENMASK(2, 0) +#define RCC_SDMMC3CKSELR_SDMMC3SRC_SHIFT 0 + +/* RCC_ETHCKSELR register fields */ +#define RCC_ETHCKSELR_ETHSRC_MASK GENMASK(1, 0) +#define RCC_ETHCKSELR_ETHSRC_SHIFT 0 +#define RCC_ETHCKSELR_ETHPTPDIV_MASK GENMASK(7, 4) +#define RCC_ETHCKSELR_ETHPTPDIV_SHIFT 4 + +/* RCC_QSPICKSELR register fields */ +#define RCC_QSPICKSELR_QSPISRC_MASK GENMASK(1, 0) +#define RCC_QSPICKSELR_QSPISRC_SHIFT 0 + +/* RCC_FMCCKSELR register fields */ +#define RCC_FMCCKSELR_FMCSRC_MASK GENMASK(1, 0) +#define RCC_FMCCKSELR_FMCSRC_SHIFT 0 + +/* RCC_FDCANCKSELR register fields */ +#define RCC_FDCANCKSELR_FDCANSRC_MASK GENMASK(1, 0) +#define RCC_FDCANCKSELR_FDCANSRC_SHIFT 0 + +/* RCC_SPDIFCKSELR register fields */ +#define RCC_SPDIFCKSELR_SPDIFSRC_MASK GENMASK(1, 0) +#define RCC_SPDIFCKSELR_SPDIFSRC_SHIFT 0 + +/* RCC_CECCKSELR register fields */ +#define RCC_CECCKSELR_CECSRC_MASK GENMASK(1, 0) +#define RCC_CECCKSELR_CECSRC_SHIFT 0 + +/* RCC_USBCKSELR register fields */ +#define RCC_USBCKSELR_USBPHYSRC_MASK GENMASK(1, 0) +#define RCC_USBCKSELR_USBPHYSRC_SHIFT 0 +#define RCC_USBCKSELR_USBOSRC BIT(4) +#define RCC_USBCKSELR_USBOSRC_MASK BIT(4) +#define RCC_USBCKSELR_USBOSRC_SHIFT 4 + +/* RCC_RNG2CKSELR register fields */ +#define RCC_RNG2CKSELR_RNG2SRC_MASK GENMASK(1, 0) +#define RCC_RNG2CKSELR_RNG2SRC_SHIFT 0 + +/* RCC_DSICKSELR register fields */ +#define RCC_DSICKSELR_DSISRC BIT(0) + +/* RCC_ADCCKSELR register fields */ +#define RCC_ADCCKSELR_ADCSRC_MASK GENMASK(1, 0) +#define RCC_ADCCKSELR_ADCSRC_SHIFT 0 + +/* RCC_LPTIM45CKSELR register fields */ +#define RCC_LPTIM45CKSELR_LPTIM45SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM45CKSELR_LPTIM45SRC_SHIFT 0 + +/* RCC_LPTIM23CKSELR register fields */ +#define RCC_LPTIM23CKSELR_LPTIM23SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM23CKSELR_LPTIM23SRC_SHIFT 0 + +/* RCC_LPTIM1CKSELR register fields */ +#define RCC_LPTIM1CKSELR_LPTIM1SRC_MASK GENMASK(2, 0) +#define RCC_LPTIM1CKSELR_LPTIM1SRC_SHIFT 0 + +/* RCC_APB1RSTSETR register fields */ +#define RCC_APB1RSTSETR_TIM2RST BIT(0) +#define RCC_APB1RSTSETR_TIM3RST BIT(1) +#define RCC_APB1RSTSETR_TIM4RST BIT(2) +#define RCC_APB1RSTSETR_TIM5RST BIT(3) +#define RCC_APB1RSTSETR_TIM6RST BIT(4) +#define RCC_APB1RSTSETR_TIM7RST BIT(5) +#define RCC_APB1RSTSETR_TIM12RST BIT(6) +#define RCC_APB1RSTSETR_TIM13RST BIT(7) +#define RCC_APB1RSTSETR_TIM14RST BIT(8) +#define RCC_APB1RSTSETR_LPTIM1RST BIT(9) +#define RCC_APB1RSTSETR_SPI2RST BIT(11) +#define RCC_APB1RSTSETR_SPI3RST BIT(12) +#define RCC_APB1RSTSETR_USART2RST BIT(14) +#define RCC_APB1RSTSETR_USART3RST BIT(15) +#define RCC_APB1RSTSETR_UART4RST BIT(16) +#define RCC_APB1RSTSETR_UART5RST BIT(17) +#define RCC_APB1RSTSETR_UART7RST BIT(18) +#define RCC_APB1RSTSETR_UART8RST BIT(19) +#define RCC_APB1RSTSETR_I2C1RST BIT(21) +#define RCC_APB1RSTSETR_I2C2RST BIT(22) +#define RCC_APB1RSTSETR_I2C3RST BIT(23) +#define RCC_APB1RSTSETR_I2C5RST BIT(24) +#define RCC_APB1RSTSETR_SPDIFRST BIT(26) +#define RCC_APB1RSTSETR_CECRST BIT(27) +#define RCC_APB1RSTSETR_DAC12RST BIT(29) +#define RCC_APB1RSTSETR_MDIOSRST BIT(31) + +/* RCC_APB1RSTCLRR register fields */ +#define RCC_APB1RSTCLRR_TIM2RST BIT(0) +#define RCC_APB1RSTCLRR_TIM3RST BIT(1) +#define RCC_APB1RSTCLRR_TIM4RST BIT(2) +#define RCC_APB1RSTCLRR_TIM5RST BIT(3) +#define RCC_APB1RSTCLRR_TIM6RST BIT(4) +#define RCC_APB1RSTCLRR_TIM7RST BIT(5) +#define RCC_APB1RSTCLRR_TIM12RST BIT(6) +#define RCC_APB1RSTCLRR_TIM13RST BIT(7) +#define RCC_APB1RSTCLRR_TIM14RST BIT(8) +#define RCC_APB1RSTCLRR_LPTIM1RST BIT(9) +#define RCC_APB1RSTCLRR_SPI2RST BIT(11) +#define RCC_APB1RSTCLRR_SPI3RST BIT(12) +#define RCC_APB1RSTCLRR_USART2RST BIT(14) +#define RCC_APB1RSTCLRR_USART3RST BIT(15) +#define RCC_APB1RSTCLRR_UART4RST BIT(16) +#define RCC_APB1RSTCLRR_UART5RST BIT(17) +#define RCC_APB1RSTCLRR_UART7RST BIT(18) +#define RCC_APB1RSTCLRR_UART8RST BIT(19) +#define RCC_APB1RSTCLRR_I2C1RST BIT(21) +#define RCC_APB1RSTCLRR_I2C2RST BIT(22) +#define RCC_APB1RSTCLRR_I2C3RST BIT(23) +#define RCC_APB1RSTCLRR_I2C5RST BIT(24) +#define RCC_APB1RSTCLRR_SPDIFRST BIT(26) +#define RCC_APB1RSTCLRR_CECRST BIT(27) +#define RCC_APB1RSTCLRR_DAC12RST BIT(29) +#define RCC_APB1RSTCLRR_MDIOSRST BIT(31) + +/* RCC_APB2RSTSETR register fields */ +#define RCC_APB2RSTSETR_TIM1RST BIT(0) +#define RCC_APB2RSTSETR_TIM8RST BIT(1) +#define RCC_APB2RSTSETR_TIM15RST BIT(2) +#define RCC_APB2RSTSETR_TIM16RST BIT(3) +#define RCC_APB2RSTSETR_TIM17RST BIT(4) +#define RCC_APB2RSTSETR_SPI1RST BIT(8) +#define RCC_APB2RSTSETR_SPI4RST BIT(9) +#define RCC_APB2RSTSETR_SPI5RST BIT(10) +#define RCC_APB2RSTSETR_USART6RST BIT(13) +#define RCC_APB2RSTSETR_SAI1RST BIT(16) +#define RCC_APB2RSTSETR_SAI2RST BIT(17) +#define RCC_APB2RSTSETR_SAI3RST BIT(18) +#define RCC_APB2RSTSETR_DFSDMRST BIT(20) +#define RCC_APB2RSTSETR_FDCANRST BIT(24) + +/* RCC_APB2RSTCLRR register fields */ +#define RCC_APB2RSTCLRR_TIM1RST BIT(0) +#define RCC_APB2RSTCLRR_TIM8RST BIT(1) +#define RCC_APB2RSTCLRR_TIM15RST BIT(2) +#define RCC_APB2RSTCLRR_TIM16RST BIT(3) +#define RCC_APB2RSTCLRR_TIM17RST BIT(4) +#define RCC_APB2RSTCLRR_SPI1RST BIT(8) +#define RCC_APB2RSTCLRR_SPI4RST BIT(9) +#define RCC_APB2RSTCLRR_SPI5RST BIT(10) +#define RCC_APB2RSTCLRR_USART6RST BIT(13) +#define RCC_APB2RSTCLRR_SAI1RST BIT(16) +#define RCC_APB2RSTCLRR_SAI2RST BIT(17) +#define RCC_APB2RSTCLRR_SAI3RST BIT(18) +#define RCC_APB2RSTCLRR_DFSDMRST BIT(20) +#define RCC_APB2RSTCLRR_FDCANRST BIT(24) + +/* RCC_APB3RSTSETR register fields */ +#define RCC_APB3RSTSETR_LPTIM2RST BIT(0) +#define RCC_APB3RSTSETR_LPTIM3RST BIT(1) +#define RCC_APB3RSTSETR_LPTIM4RST BIT(2) +#define RCC_APB3RSTSETR_LPTIM5RST BIT(3) +#define RCC_APB3RSTSETR_SAI4RST BIT(8) +#define RCC_APB3RSTSETR_SYSCFGRST BIT(11) +#define RCC_APB3RSTSETR_VREFRST BIT(13) +#define RCC_APB3RSTSETR_TMPSENSRST BIT(16) +#define RCC_APB3RSTSETR_PMBCTRLRST BIT(17) + +/* RCC_APB3RSTCLRR register fields */ +#define RCC_APB3RSTCLRR_LPTIM2RST BIT(0) +#define RCC_APB3RSTCLRR_LPTIM3RST BIT(1) +#define RCC_APB3RSTCLRR_LPTIM4RST BIT(2) +#define RCC_APB3RSTCLRR_LPTIM5RST BIT(3) +#define RCC_APB3RSTCLRR_SAI4RST BIT(8) +#define RCC_APB3RSTCLRR_SYSCFGRST BIT(11) +#define RCC_APB3RSTCLRR_VREFRST BIT(13) +#define RCC_APB3RSTCLRR_TMPSENSRST BIT(16) +#define RCC_APB3RSTCLRR_PMBCTRLRST BIT(17) + +/* RCC_AHB2RSTSETR register fields */ +#define RCC_AHB2RSTSETR_DMA1RST BIT(0) +#define RCC_AHB2RSTSETR_DMA2RST BIT(1) +#define RCC_AHB2RSTSETR_DMAMUXRST BIT(2) +#define RCC_AHB2RSTSETR_ADC12RST BIT(5) +#define RCC_AHB2RSTSETR_USBORST BIT(8) +#define RCC_AHB2RSTSETR_SDMMC3RST BIT(16) + +/* RCC_AHB2RSTCLRR register fields */ +#define RCC_AHB2RSTCLRR_DMA1RST BIT(0) +#define RCC_AHB2RSTCLRR_DMA2RST BIT(1) +#define RCC_AHB2RSTCLRR_DMAMUXRST BIT(2) +#define RCC_AHB2RSTCLRR_ADC12RST BIT(5) +#define RCC_AHB2RSTCLRR_USBORST BIT(8) +#define RCC_AHB2RSTCLRR_SDMMC3RST BIT(16) + +/* RCC_AHB3RSTSETR register fields */ +#define RCC_AHB3RSTSETR_DCMIRST BIT(0) +#define RCC_AHB3RSTSETR_CRYP2RST BIT(4) +#define RCC_AHB3RSTSETR_HASH2RST BIT(5) +#define RCC_AHB3RSTSETR_RNG2RST BIT(6) +#define RCC_AHB3RSTSETR_CRC2RST BIT(7) +#define RCC_AHB3RSTSETR_HSEMRST BIT(11) +#define RCC_AHB3RSTSETR_IPCCRST BIT(12) + +/* RCC_AHB3RSTCLRR register fields */ +#define RCC_AHB3RSTCLRR_DCMIRST BIT(0) +#define RCC_AHB3RSTCLRR_CRYP2RST BIT(4) +#define RCC_AHB3RSTCLRR_HASH2RST BIT(5) +#define RCC_AHB3RSTCLRR_RNG2RST BIT(6) +#define RCC_AHB3RSTCLRR_CRC2RST BIT(7) +#define RCC_AHB3RSTCLRR_HSEMRST BIT(11) +#define RCC_AHB3RSTCLRR_IPCCRST BIT(12) + +/* RCC_AHB4RSTSETR register fields */ +#define RCC_AHB4RSTSETR_GPIOARST BIT(0) +#define RCC_AHB4RSTSETR_GPIOBRST BIT(1) +#define RCC_AHB4RSTSETR_GPIOCRST BIT(2) +#define RCC_AHB4RSTSETR_GPIODRST BIT(3) +#define RCC_AHB4RSTSETR_GPIOERST BIT(4) +#define RCC_AHB4RSTSETR_GPIOFRST BIT(5) +#define RCC_AHB4RSTSETR_GPIOGRST BIT(6) +#define RCC_AHB4RSTSETR_GPIOHRST BIT(7) +#define RCC_AHB4RSTSETR_GPIOIRST BIT(8) +#define RCC_AHB4RSTSETR_GPIOJRST BIT(9) +#define RCC_AHB4RSTSETR_GPIOKRST BIT(10) + +/* RCC_AHB4RSTCLRR register fields */ +#define RCC_AHB4RSTCLRR_GPIOARST BIT(0) +#define RCC_AHB4RSTCLRR_GPIOBRST BIT(1) +#define RCC_AHB4RSTCLRR_GPIOCRST BIT(2) +#define RCC_AHB4RSTCLRR_GPIODRST BIT(3) +#define RCC_AHB4RSTCLRR_GPIOERST BIT(4) +#define RCC_AHB4RSTCLRR_GPIOFRST BIT(5) +#define RCC_AHB4RSTCLRR_GPIOGRST BIT(6) +#define RCC_AHB4RSTCLRR_GPIOHRST BIT(7) +#define RCC_AHB4RSTCLRR_GPIOIRST BIT(8) +#define RCC_AHB4RSTCLRR_GPIOJRST BIT(9) +#define RCC_AHB4RSTCLRR_GPIOKRST BIT(10) + +/* RCC_MP_APB1ENSETR register fields */ +#define RCC_MP_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MP_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MP_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MP_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MP_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MP_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MP_APB1ENSETR_TIM12EN BIT(6) +#define RCC_MP_APB1ENSETR_TIM13EN BIT(7) +#define RCC_MP_APB1ENSETR_TIM14EN BIT(8) +#define RCC_MP_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MP_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MP_APB1ENSETR_USART2EN BIT(14) +#define RCC_MP_APB1ENSETR_USART3EN BIT(15) +#define RCC_MP_APB1ENSETR_UART4EN BIT(16) +#define RCC_MP_APB1ENSETR_UART5EN BIT(17) +#define RCC_MP_APB1ENSETR_UART7EN BIT(18) +#define RCC_MP_APB1ENSETR_UART8EN BIT(19) +#define RCC_MP_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MP_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MP_APB1ENSETR_I2C3EN BIT(23) +#define RCC_MP_APB1ENSETR_I2C5EN BIT(24) +#define RCC_MP_APB1ENSETR_SPDIFEN BIT(26) +#define RCC_MP_APB1ENSETR_CECEN BIT(27) +#define RCC_MP_APB1ENSETR_DAC12EN BIT(29) +#define RCC_MP_APB1ENSETR_MDIOSEN BIT(31) + +/* RCC_MP_APB1ENCLRR register fields */ +#define RCC_MP_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MP_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MP_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MP_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MP_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MP_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MP_APB1ENCLRR_TIM12EN BIT(6) +#define RCC_MP_APB1ENCLRR_TIM13EN BIT(7) +#define RCC_MP_APB1ENCLRR_TIM14EN BIT(8) +#define RCC_MP_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MP_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MP_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MP_APB1ENCLRR_USART2EN BIT(14) +#define RCC_MP_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MP_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MP_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MP_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MP_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MP_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MP_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MP_APB1ENCLRR_I2C3EN BIT(23) +#define RCC_MP_APB1ENCLRR_I2C5EN BIT(24) +#define RCC_MP_APB1ENCLRR_SPDIFEN BIT(26) +#define RCC_MP_APB1ENCLRR_CECEN BIT(27) +#define RCC_MP_APB1ENCLRR_DAC12EN BIT(29) +#define RCC_MP_APB1ENCLRR_MDIOSEN BIT(31) + +/* RCC_MP_APB2ENSETR register fields */ +#define RCC_MP_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MP_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MP_APB2ENSETR_TIM15EN BIT(2) +#define RCC_MP_APB2ENSETR_TIM16EN BIT(3) +#define RCC_MP_APB2ENSETR_TIM17EN BIT(4) +#define RCC_MP_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MP_APB2ENSETR_SPI4EN BIT(9) +#define RCC_MP_APB2ENSETR_SPI5EN BIT(10) +#define RCC_MP_APB2ENSETR_USART6EN BIT(13) +#define RCC_MP_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MP_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MP_APB2ENSETR_SAI3EN BIT(18) +#define RCC_MP_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MP_APB2ENCLRR register fields */ +#define RCC_MP_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MP_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MP_APB2ENCLRR_TIM15EN BIT(2) +#define RCC_MP_APB2ENCLRR_TIM16EN BIT(3) +#define RCC_MP_APB2ENCLRR_TIM17EN BIT(4) +#define RCC_MP_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MP_APB2ENCLRR_SPI4EN BIT(9) +#define RCC_MP_APB2ENCLRR_SPI5EN BIT(10) +#define RCC_MP_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MP_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MP_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MP_APB2ENCLRR_SAI3EN BIT(18) +#define RCC_MP_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MP_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MP_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MP_APB3ENSETR register fields */ +#define RCC_MP_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENSETR_SAI4EN BIT(8) +#define RCC_MP_APB3ENSETR_SYSCFGEN BIT(11) +#define RCC_MP_APB3ENSETR_VREFEN BIT(13) +#define RCC_MP_APB3ENSETR_TMPSENSEN BIT(16) +#define RCC_MP_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MP_APB3ENCLRR register fields */ +#define RCC_MP_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MP_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MP_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MP_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MP_APB3ENCLRR_SAI4EN BIT(8) +#define RCC_MP_APB3ENCLRR_SYSCFGEN BIT(11) +#define RCC_MP_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MP_APB3ENCLRR_TMPSENSEN BIT(16) +#define RCC_MP_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MP_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MP_AHB2ENSETR register fields */ +#define RCC_MP_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENSETR_DMAMUXEN BIT(2) +#define RCC_MP_AHB2ENSETR_ADC12EN BIT(5) +#define RCC_MP_AHB2ENSETR_USBOEN BIT(8) +#define RCC_MP_AHB2ENSETR_SDMMC3EN BIT(16) + +/* RCC_MP_AHB2ENCLRR register fields */ +#define RCC_MP_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MP_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MP_AHB2ENCLRR_DMAMUXEN BIT(2) +#define RCC_MP_AHB2ENCLRR_ADC12EN BIT(5) +#define RCC_MP_AHB2ENCLRR_USBOEN BIT(8) +#define RCC_MP_AHB2ENCLRR_SDMMC3EN BIT(16) + +/* RCC_MP_AHB3ENSETR register fields */ +#define RCC_MP_AHB3ENSETR_DCMIEN BIT(0) +#define RCC_MP_AHB3ENSETR_CRYP2EN BIT(4) +#define RCC_MP_AHB3ENSETR_HASH2EN BIT(5) +#define RCC_MP_AHB3ENSETR_RNG2EN BIT(6) +#define RCC_MP_AHB3ENSETR_CRC2EN BIT(7) +#define RCC_MP_AHB3ENSETR_HSEMEN BIT(11) +#define RCC_MP_AHB3ENSETR_IPCCEN BIT(12) + +/* RCC_MP_AHB3ENCLRR register fields */ +#define RCC_MP_AHB3ENCLRR_DCMIEN BIT(0) +#define RCC_MP_AHB3ENCLRR_CRYP2EN BIT(4) +#define RCC_MP_AHB3ENCLRR_HASH2EN BIT(5) +#define RCC_MP_AHB3ENCLRR_RNG2EN BIT(6) +#define RCC_MP_AHB3ENCLRR_CRC2EN BIT(7) +#define RCC_MP_AHB3ENCLRR_HSEMEN BIT(11) +#define RCC_MP_AHB3ENCLRR_IPCCEN BIT(12) + +/* RCC_MP_AHB4ENSETR register fields */ +#define RCC_MP_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MP_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MP_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MP_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MP_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MP_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MP_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MP_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MP_AHB4ENSETR_GPIOIEN BIT(8) +#define RCC_MP_AHB4ENSETR_GPIOJEN BIT(9) +#define RCC_MP_AHB4ENSETR_GPIOKEN BIT(10) + +/* RCC_MP_AHB4ENCLRR register fields */ +#define RCC_MP_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MP_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MP_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MP_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MP_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MP_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MP_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MP_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MP_AHB4ENCLRR_GPIOIEN BIT(8) +#define RCC_MP_AHB4ENCLRR_GPIOJEN BIT(9) +#define RCC_MP_AHB4ENCLRR_GPIOKEN BIT(10) + +/* RCC_MP_MLAHBENSETR register fields */ +#define RCC_MP_MLAHBENSETR_RETRAMEN BIT(4) + +/* RCC_MP_MLAHBENCLRR register fields */ +#define RCC_MP_MLAHBENCLRR_RETRAMEN BIT(4) + +/* RCC_MC_APB1ENSETR register fields */ +#define RCC_MC_APB1ENSETR_TIM2EN BIT(0) +#define RCC_MC_APB1ENSETR_TIM3EN BIT(1) +#define RCC_MC_APB1ENSETR_TIM4EN BIT(2) +#define RCC_MC_APB1ENSETR_TIM5EN BIT(3) +#define RCC_MC_APB1ENSETR_TIM6EN BIT(4) +#define RCC_MC_APB1ENSETR_TIM7EN BIT(5) +#define RCC_MC_APB1ENSETR_TIM12EN BIT(6) +#define RCC_MC_APB1ENSETR_TIM13EN BIT(7) +#define RCC_MC_APB1ENSETR_TIM14EN BIT(8) +#define RCC_MC_APB1ENSETR_LPTIM1EN BIT(9) +#define RCC_MC_APB1ENSETR_SPI2EN BIT(11) +#define RCC_MC_APB1ENSETR_SPI3EN BIT(12) +#define RCC_MC_APB1ENSETR_USART2EN BIT(14) +#define RCC_MC_APB1ENSETR_USART3EN BIT(15) +#define RCC_MC_APB1ENSETR_UART4EN BIT(16) +#define RCC_MC_APB1ENSETR_UART5EN BIT(17) +#define RCC_MC_APB1ENSETR_UART7EN BIT(18) +#define RCC_MC_APB1ENSETR_UART8EN BIT(19) +#define RCC_MC_APB1ENSETR_I2C1EN BIT(21) +#define RCC_MC_APB1ENSETR_I2C2EN BIT(22) +#define RCC_MC_APB1ENSETR_I2C3EN BIT(23) +#define RCC_MC_APB1ENSETR_I2C5EN BIT(24) +#define RCC_MC_APB1ENSETR_SPDIFEN BIT(26) +#define RCC_MC_APB1ENSETR_CECEN BIT(27) +#define RCC_MC_APB1ENSETR_WWDG1EN BIT(28) +#define RCC_MC_APB1ENSETR_DAC12EN BIT(29) +#define RCC_MC_APB1ENSETR_MDIOSEN BIT(31) + +/* RCC_MC_APB1ENCLRR register fields */ +#define RCC_MC_APB1ENCLRR_TIM2EN BIT(0) +#define RCC_MC_APB1ENCLRR_TIM3EN BIT(1) +#define RCC_MC_APB1ENCLRR_TIM4EN BIT(2) +#define RCC_MC_APB1ENCLRR_TIM5EN BIT(3) +#define RCC_MC_APB1ENCLRR_TIM6EN BIT(4) +#define RCC_MC_APB1ENCLRR_TIM7EN BIT(5) +#define RCC_MC_APB1ENCLRR_TIM12EN BIT(6) +#define RCC_MC_APB1ENCLRR_TIM13EN BIT(7) +#define RCC_MC_APB1ENCLRR_TIM14EN BIT(8) +#define RCC_MC_APB1ENCLRR_LPTIM1EN BIT(9) +#define RCC_MC_APB1ENCLRR_SPI2EN BIT(11) +#define RCC_MC_APB1ENCLRR_SPI3EN BIT(12) +#define RCC_MC_APB1ENCLRR_USART2EN BIT(14) +#define RCC_MC_APB1ENCLRR_USART3EN BIT(15) +#define RCC_MC_APB1ENCLRR_UART4EN BIT(16) +#define RCC_MC_APB1ENCLRR_UART5EN BIT(17) +#define RCC_MC_APB1ENCLRR_UART7EN BIT(18) +#define RCC_MC_APB1ENCLRR_UART8EN BIT(19) +#define RCC_MC_APB1ENCLRR_I2C1EN BIT(21) +#define RCC_MC_APB1ENCLRR_I2C2EN BIT(22) +#define RCC_MC_APB1ENCLRR_I2C3EN BIT(23) +#define RCC_MC_APB1ENCLRR_I2C5EN BIT(24) +#define RCC_MC_APB1ENCLRR_SPDIFEN BIT(26) +#define RCC_MC_APB1ENCLRR_CECEN BIT(27) +#define RCC_MC_APB1ENCLRR_DAC12EN BIT(29) +#define RCC_MC_APB1ENCLRR_MDIOSEN BIT(31) + +/* RCC_MC_APB2ENSETR register fields */ +#define RCC_MC_APB2ENSETR_TIM1EN BIT(0) +#define RCC_MC_APB2ENSETR_TIM8EN BIT(1) +#define RCC_MC_APB2ENSETR_TIM15EN BIT(2) +#define RCC_MC_APB2ENSETR_TIM16EN BIT(3) +#define RCC_MC_APB2ENSETR_TIM17EN BIT(4) +#define RCC_MC_APB2ENSETR_SPI1EN BIT(8) +#define RCC_MC_APB2ENSETR_SPI4EN BIT(9) +#define RCC_MC_APB2ENSETR_SPI5EN BIT(10) +#define RCC_MC_APB2ENSETR_USART6EN BIT(13) +#define RCC_MC_APB2ENSETR_SAI1EN BIT(16) +#define RCC_MC_APB2ENSETR_SAI2EN BIT(17) +#define RCC_MC_APB2ENSETR_SAI3EN BIT(18) +#define RCC_MC_APB2ENSETR_DFSDMEN BIT(20) +#define RCC_MC_APB2ENSETR_ADFSDMEN BIT(21) +#define RCC_MC_APB2ENSETR_FDCANEN BIT(24) + +/* RCC_MC_APB2ENCLRR register fields */ +#define RCC_MC_APB2ENCLRR_TIM1EN BIT(0) +#define RCC_MC_APB2ENCLRR_TIM8EN BIT(1) +#define RCC_MC_APB2ENCLRR_TIM15EN BIT(2) +#define RCC_MC_APB2ENCLRR_TIM16EN BIT(3) +#define RCC_MC_APB2ENCLRR_TIM17EN BIT(4) +#define RCC_MC_APB2ENCLRR_SPI1EN BIT(8) +#define RCC_MC_APB2ENCLRR_SPI4EN BIT(9) +#define RCC_MC_APB2ENCLRR_SPI5EN BIT(10) +#define RCC_MC_APB2ENCLRR_USART6EN BIT(13) +#define RCC_MC_APB2ENCLRR_SAI1EN BIT(16) +#define RCC_MC_APB2ENCLRR_SAI2EN BIT(17) +#define RCC_MC_APB2ENCLRR_SAI3EN BIT(18) +#define RCC_MC_APB2ENCLRR_DFSDMEN BIT(20) +#define RCC_MC_APB2ENCLRR_ADFSDMEN BIT(21) +#define RCC_MC_APB2ENCLRR_FDCANEN BIT(24) + +/* RCC_MC_APB3ENSETR register fields */ +#define RCC_MC_APB3ENSETR_LPTIM2EN BIT(0) +#define RCC_MC_APB3ENSETR_LPTIM3EN BIT(1) +#define RCC_MC_APB3ENSETR_LPTIM4EN BIT(2) +#define RCC_MC_APB3ENSETR_LPTIM5EN BIT(3) +#define RCC_MC_APB3ENSETR_SAI4EN BIT(8) +#define RCC_MC_APB3ENSETR_SYSCFGEN BIT(11) +#define RCC_MC_APB3ENSETR_VREFEN BIT(13) +#define RCC_MC_APB3ENSETR_TMPSENSEN BIT(16) +#define RCC_MC_APB3ENSETR_PMBCTRLEN BIT(17) +#define RCC_MC_APB3ENSETR_HDPEN BIT(20) + +/* RCC_MC_APB3ENCLRR register fields */ +#define RCC_MC_APB3ENCLRR_LPTIM2EN BIT(0) +#define RCC_MC_APB3ENCLRR_LPTIM3EN BIT(1) +#define RCC_MC_APB3ENCLRR_LPTIM4EN BIT(2) +#define RCC_MC_APB3ENCLRR_LPTIM5EN BIT(3) +#define RCC_MC_APB3ENCLRR_SAI4EN BIT(8) +#define RCC_MC_APB3ENCLRR_SYSCFGEN BIT(11) +#define RCC_MC_APB3ENCLRR_VREFEN BIT(13) +#define RCC_MC_APB3ENCLRR_TMPSENSEN BIT(16) +#define RCC_MC_APB3ENCLRR_PMBCTRLEN BIT(17) +#define RCC_MC_APB3ENCLRR_HDPEN BIT(20) + +/* RCC_MC_AHB2ENSETR register fields */ +#define RCC_MC_AHB2ENSETR_DMA1EN BIT(0) +#define RCC_MC_AHB2ENSETR_DMA2EN BIT(1) +#define RCC_MC_AHB2ENSETR_DMAMUXEN BIT(2) +#define RCC_MC_AHB2ENSETR_ADC12EN BIT(5) +#define RCC_MC_AHB2ENSETR_USBOEN BIT(8) +#define RCC_MC_AHB2ENSETR_SDMMC3EN BIT(16) + +/* RCC_MC_AHB2ENCLRR register fields */ +#define RCC_MC_AHB2ENCLRR_DMA1EN BIT(0) +#define RCC_MC_AHB2ENCLRR_DMA2EN BIT(1) +#define RCC_MC_AHB2ENCLRR_DMAMUXEN BIT(2) +#define RCC_MC_AHB2ENCLRR_ADC12EN BIT(5) +#define RCC_MC_AHB2ENCLRR_USBOEN BIT(8) +#define RCC_MC_AHB2ENCLRR_SDMMC3EN BIT(16) + +/* RCC_MC_AHB3ENSETR register fields */ +#define RCC_MC_AHB3ENSETR_DCMIEN BIT(0) +#define RCC_MC_AHB3ENSETR_CRYP2EN BIT(4) +#define RCC_MC_AHB3ENSETR_HASH2EN BIT(5) +#define RCC_MC_AHB3ENSETR_RNG2EN BIT(6) +#define RCC_MC_AHB3ENSETR_CRC2EN BIT(7) +#define RCC_MC_AHB3ENSETR_HSEMEN BIT(11) +#define RCC_MC_AHB3ENSETR_IPCCEN BIT(12) + +/* RCC_MC_AHB3ENCLRR register fields */ +#define RCC_MC_AHB3ENCLRR_DCMIEN BIT(0) +#define RCC_MC_AHB3ENCLRR_CRYP2EN BIT(4) +#define RCC_MC_AHB3ENCLRR_HASH2EN BIT(5) +#define RCC_MC_AHB3ENCLRR_RNG2EN BIT(6) +#define RCC_MC_AHB3ENCLRR_CRC2EN BIT(7) +#define RCC_MC_AHB3ENCLRR_HSEMEN BIT(11) +#define RCC_MC_AHB3ENCLRR_IPCCEN BIT(12) + +/* RCC_MC_AHB4ENSETR register fields */ +#define RCC_MC_AHB4ENSETR_GPIOAEN BIT(0) +#define RCC_MC_AHB4ENSETR_GPIOBEN BIT(1) +#define RCC_MC_AHB4ENSETR_GPIOCEN BIT(2) +#define RCC_MC_AHB4ENSETR_GPIODEN BIT(3) +#define RCC_MC_AHB4ENSETR_GPIOEEN BIT(4) +#define RCC_MC_AHB4ENSETR_GPIOFEN BIT(5) +#define RCC_MC_AHB4ENSETR_GPIOGEN BIT(6) +#define RCC_MC_AHB4ENSETR_GPIOHEN BIT(7) +#define RCC_MC_AHB4ENSETR_GPIOIEN BIT(8) +#define RCC_MC_AHB4ENSETR_GPIOJEN BIT(9) +#define RCC_MC_AHB4ENSETR_GPIOKEN BIT(10) + +/* RCC_MC_AHB4ENCLRR register fields */ +#define RCC_MC_AHB4ENCLRR_GPIOAEN BIT(0) +#define RCC_MC_AHB4ENCLRR_GPIOBEN BIT(1) +#define RCC_MC_AHB4ENCLRR_GPIOCEN BIT(2) +#define RCC_MC_AHB4ENCLRR_GPIODEN BIT(3) +#define RCC_MC_AHB4ENCLRR_GPIOEEN BIT(4) +#define RCC_MC_AHB4ENCLRR_GPIOFEN BIT(5) +#define RCC_MC_AHB4ENCLRR_GPIOGEN BIT(6) +#define RCC_MC_AHB4ENCLRR_GPIOHEN BIT(7) +#define RCC_MC_AHB4ENCLRR_GPIOIEN BIT(8) +#define RCC_MC_AHB4ENCLRR_GPIOJEN BIT(9) +#define RCC_MC_AHB4ENCLRR_GPIOKEN BIT(10) + +/* RCC_MC_AXIMENSETR register fields */ +#define RCC_MC_AXIMENSETR_SYSRAMEN BIT(0) + +/* RCC_MC_AXIMENCLRR register fields */ +#define RCC_MC_AXIMENCLRR_SYSRAMEN BIT(0) + +/* RCC_MC_MLAHBENSETR register fields */ +#define RCC_MC_MLAHBENSETR_RETRAMEN BIT(4) + +/* RCC_MC_MLAHBENCLRR register fields */ +#define RCC_MC_MLAHBENCLRR_RETRAMEN BIT(4) + +/* RCC_MP_APB1LPENSETR register fields */ +#define RCC_MP_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENSETR_TIM12LPEN BIT(6) +#define RCC_MP_APB1LPENSETR_TIM13LPEN BIT(7) +#define RCC_MP_APB1LPENSETR_TIM14LPEN BIT(8) +#define RCC_MP_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENSETR_USART2LPEN BIT(14) +#define RCC_MP_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENSETR_I2C3LPEN BIT(23) +#define RCC_MP_APB1LPENSETR_I2C5LPEN BIT(24) +#define RCC_MP_APB1LPENSETR_SPDIFLPEN BIT(26) +#define RCC_MP_APB1LPENSETR_CECLPEN BIT(27) +#define RCC_MP_APB1LPENSETR_DAC12LPEN BIT(29) +#define RCC_MP_APB1LPENSETR_MDIOSLPEN BIT(31) + +/* RCC_MP_APB1LPENCLRR register fields */ +#define RCC_MP_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MP_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MP_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MP_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MP_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MP_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MP_APB1LPENCLRR_TIM12LPEN BIT(6) +#define RCC_MP_APB1LPENCLRR_TIM13LPEN BIT(7) +#define RCC_MP_APB1LPENCLRR_TIM14LPEN BIT(8) +#define RCC_MP_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MP_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MP_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MP_APB1LPENCLRR_USART2LPEN BIT(14) +#define RCC_MP_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MP_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MP_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MP_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MP_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MP_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MP_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MP_APB1LPENCLRR_I2C3LPEN BIT(23) +#define RCC_MP_APB1LPENCLRR_I2C5LPEN BIT(24) +#define RCC_MP_APB1LPENCLRR_SPDIFLPEN BIT(26) +#define RCC_MP_APB1LPENCLRR_CECLPEN BIT(27) +#define RCC_MP_APB1LPENCLRR_DAC12LPEN BIT(29) +#define RCC_MP_APB1LPENCLRR_MDIOSLPEN BIT(31) + +/* RCC_MP_APB2LPENSETR register fields */ +#define RCC_MP_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENSETR_TIM15LPEN BIT(2) +#define RCC_MP_APB2LPENSETR_TIM16LPEN BIT(3) +#define RCC_MP_APB2LPENSETR_TIM17LPEN BIT(4) +#define RCC_MP_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENSETR_SPI4LPEN BIT(9) +#define RCC_MP_APB2LPENSETR_SPI5LPEN BIT(10) +#define RCC_MP_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENSETR_SAI3LPEN BIT(18) +#define RCC_MP_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MP_APB2LPENCLRR register fields */ +#define RCC_MP_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MP_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MP_APB2LPENCLRR_TIM15LPEN BIT(2) +#define RCC_MP_APB2LPENCLRR_TIM16LPEN BIT(3) +#define RCC_MP_APB2LPENCLRR_TIM17LPEN BIT(4) +#define RCC_MP_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MP_APB2LPENCLRR_SPI4LPEN BIT(9) +#define RCC_MP_APB2LPENCLRR_SPI5LPEN BIT(10) +#define RCC_MP_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MP_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MP_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MP_APB2LPENCLRR_SAI3LPEN BIT(18) +#define RCC_MP_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MP_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MP_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MP_APB3LPENSETR register fields */ +#define RCC_MP_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENSETR_SAI4LPEN BIT(8) +#define RCC_MP_APB3LPENSETR_SYSCFGLPEN BIT(11) +#define RCC_MP_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENSETR_TMPSENSLPEN BIT(16) +#define RCC_MP_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_APB3LPENCLRR register fields */ +#define RCC_MP_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MP_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MP_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MP_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MP_APB3LPENCLRR_SAI4LPEN BIT(8) +#define RCC_MP_APB3LPENCLRR_SYSCFGLPEN BIT(11) +#define RCC_MP_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MP_APB3LPENCLRR_TMPSENSLPEN BIT(16) +#define RCC_MP_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MP_AHB2LPENSETR register fields */ +#define RCC_MP_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENSETR_DMAMUXLPEN BIT(2) +#define RCC_MP_AHB2LPENSETR_ADC12LPEN BIT(5) +#define RCC_MP_AHB2LPENSETR_USBOLPEN BIT(8) +#define RCC_MP_AHB2LPENSETR_SDMMC3LPEN BIT(16) + +/* RCC_MP_AHB2LPENCLRR register fields */ +#define RCC_MP_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MP_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MP_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +#define RCC_MP_AHB2LPENCLRR_ADC12LPEN BIT(5) +#define RCC_MP_AHB2LPENCLRR_USBOLPEN BIT(8) +#define RCC_MP_AHB2LPENCLRR_SDMMC3LPEN BIT(16) + +/* RCC_MP_AHB3LPENSETR register fields */ +#define RCC_MP_AHB3LPENSETR_DCMILPEN BIT(0) +#define RCC_MP_AHB3LPENSETR_CRYP2LPEN BIT(4) +#define RCC_MP_AHB3LPENSETR_HASH2LPEN BIT(5) +#define RCC_MP_AHB3LPENSETR_RNG2LPEN BIT(6) +#define RCC_MP_AHB3LPENSETR_CRC2LPEN BIT(7) +#define RCC_MP_AHB3LPENSETR_HSEMLPEN BIT(11) +#define RCC_MP_AHB3LPENSETR_IPCCLPEN BIT(12) + +/* RCC_MP_AHB3LPENCLRR register fields */ +#define RCC_MP_AHB3LPENCLRR_DCMILPEN BIT(0) +#define RCC_MP_AHB3LPENCLRR_CRYP2LPEN BIT(4) +#define RCC_MP_AHB3LPENCLRR_HASH2LPEN BIT(5) +#define RCC_MP_AHB3LPENCLRR_RNG2LPEN BIT(6) +#define RCC_MP_AHB3LPENCLRR_CRC2LPEN BIT(7) +#define RCC_MP_AHB3LPENCLRR_HSEMLPEN BIT(11) +#define RCC_MP_AHB3LPENCLRR_IPCCLPEN BIT(12) + +/* RCC_MP_AHB4LPENSETR register fields */ +#define RCC_MP_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MP_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MP_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MP_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MP_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MP_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MP_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MP_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MP_AHB4LPENSETR_GPIOILPEN BIT(8) +#define RCC_MP_AHB4LPENSETR_GPIOJLPEN BIT(9) +#define RCC_MP_AHB4LPENSETR_GPIOKLPEN BIT(10) + +/* RCC_MP_AHB4LPENCLRR register fields */ +#define RCC_MP_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MP_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MP_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MP_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MP_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MP_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MP_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MP_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MP_AHB4LPENCLRR_GPIOILPEN BIT(8) +#define RCC_MP_AHB4LPENCLRR_GPIOJLPEN BIT(9) +#define RCC_MP_AHB4LPENCLRR_GPIOKLPEN BIT(10) + +/* RCC_MP_AXIMLPENSETR register fields */ +#define RCC_MP_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MP_AXIMLPENCLRR register fields */ +#define RCC_MP_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MP_MLAHBLPENSETR register fields */ +#define RCC_MP_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENSETR_SRAM34LPEN BIT(2) +#define RCC_MP_MLAHBLPENSETR_RETRAMLPEN BIT(4) + +/* RCC_MP_MLAHBLPENCLRR register fields */ +#define RCC_MP_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MP_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MP_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +#define RCC_MP_MLAHBLPENCLRR_RETRAMLPEN BIT(4) + +/* RCC_MC_APB1LPENSETR register fields */ +#define RCC_MC_APB1LPENSETR_TIM2LPEN BIT(0) +#define RCC_MC_APB1LPENSETR_TIM3LPEN BIT(1) +#define RCC_MC_APB1LPENSETR_TIM4LPEN BIT(2) +#define RCC_MC_APB1LPENSETR_TIM5LPEN BIT(3) +#define RCC_MC_APB1LPENSETR_TIM6LPEN BIT(4) +#define RCC_MC_APB1LPENSETR_TIM7LPEN BIT(5) +#define RCC_MC_APB1LPENSETR_TIM12LPEN BIT(6) +#define RCC_MC_APB1LPENSETR_TIM13LPEN BIT(7) +#define RCC_MC_APB1LPENSETR_TIM14LPEN BIT(8) +#define RCC_MC_APB1LPENSETR_LPTIM1LPEN BIT(9) +#define RCC_MC_APB1LPENSETR_SPI2LPEN BIT(11) +#define RCC_MC_APB1LPENSETR_SPI3LPEN BIT(12) +#define RCC_MC_APB1LPENSETR_USART2LPEN BIT(14) +#define RCC_MC_APB1LPENSETR_USART3LPEN BIT(15) +#define RCC_MC_APB1LPENSETR_UART4LPEN BIT(16) +#define RCC_MC_APB1LPENSETR_UART5LPEN BIT(17) +#define RCC_MC_APB1LPENSETR_UART7LPEN BIT(18) +#define RCC_MC_APB1LPENSETR_UART8LPEN BIT(19) +#define RCC_MC_APB1LPENSETR_I2C1LPEN BIT(21) +#define RCC_MC_APB1LPENSETR_I2C2LPEN BIT(22) +#define RCC_MC_APB1LPENSETR_I2C3LPEN BIT(23) +#define RCC_MC_APB1LPENSETR_I2C5LPEN BIT(24) +#define RCC_MC_APB1LPENSETR_SPDIFLPEN BIT(26) +#define RCC_MC_APB1LPENSETR_CECLPEN BIT(27) +#define RCC_MC_APB1LPENSETR_WWDG1LPEN BIT(28) +#define RCC_MC_APB1LPENSETR_DAC12LPEN BIT(29) +#define RCC_MC_APB1LPENSETR_MDIOSLPEN BIT(31) + +/* RCC_MC_APB1LPENCLRR register fields */ +#define RCC_MC_APB1LPENCLRR_TIM2LPEN BIT(0) +#define RCC_MC_APB1LPENCLRR_TIM3LPEN BIT(1) +#define RCC_MC_APB1LPENCLRR_TIM4LPEN BIT(2) +#define RCC_MC_APB1LPENCLRR_TIM5LPEN BIT(3) +#define RCC_MC_APB1LPENCLRR_TIM6LPEN BIT(4) +#define RCC_MC_APB1LPENCLRR_TIM7LPEN BIT(5) +#define RCC_MC_APB1LPENCLRR_TIM12LPEN BIT(6) +#define RCC_MC_APB1LPENCLRR_TIM13LPEN BIT(7) +#define RCC_MC_APB1LPENCLRR_TIM14LPEN BIT(8) +#define RCC_MC_APB1LPENCLRR_LPTIM1LPEN BIT(9) +#define RCC_MC_APB1LPENCLRR_SPI2LPEN BIT(11) +#define RCC_MC_APB1LPENCLRR_SPI3LPEN BIT(12) +#define RCC_MC_APB1LPENCLRR_USART2LPEN BIT(14) +#define RCC_MC_APB1LPENCLRR_USART3LPEN BIT(15) +#define RCC_MC_APB1LPENCLRR_UART4LPEN BIT(16) +#define RCC_MC_APB1LPENCLRR_UART5LPEN BIT(17) +#define RCC_MC_APB1LPENCLRR_UART7LPEN BIT(18) +#define RCC_MC_APB1LPENCLRR_UART8LPEN BIT(19) +#define RCC_MC_APB1LPENCLRR_I2C1LPEN BIT(21) +#define RCC_MC_APB1LPENCLRR_I2C2LPEN BIT(22) +#define RCC_MC_APB1LPENCLRR_I2C3LPEN BIT(23) +#define RCC_MC_APB1LPENCLRR_I2C5LPEN BIT(24) +#define RCC_MC_APB1LPENCLRR_SPDIFLPEN BIT(26) +#define RCC_MC_APB1LPENCLRR_CECLPEN BIT(27) +#define RCC_MC_APB1LPENCLRR_WWDG1LPEN BIT(28) +#define RCC_MC_APB1LPENCLRR_DAC12LPEN BIT(29) +#define RCC_MC_APB1LPENCLRR_MDIOSLPEN BIT(31) + +/* RCC_MC_APB2LPENSETR register fields */ +#define RCC_MC_APB2LPENSETR_TIM1LPEN BIT(0) +#define RCC_MC_APB2LPENSETR_TIM8LPEN BIT(1) +#define RCC_MC_APB2LPENSETR_TIM15LPEN BIT(2) +#define RCC_MC_APB2LPENSETR_TIM16LPEN BIT(3) +#define RCC_MC_APB2LPENSETR_TIM17LPEN BIT(4) +#define RCC_MC_APB2LPENSETR_SPI1LPEN BIT(8) +#define RCC_MC_APB2LPENSETR_SPI4LPEN BIT(9) +#define RCC_MC_APB2LPENSETR_SPI5LPEN BIT(10) +#define RCC_MC_APB2LPENSETR_USART6LPEN BIT(13) +#define RCC_MC_APB2LPENSETR_SAI1LPEN BIT(16) +#define RCC_MC_APB2LPENSETR_SAI2LPEN BIT(17) +#define RCC_MC_APB2LPENSETR_SAI3LPEN BIT(18) +#define RCC_MC_APB2LPENSETR_DFSDMLPEN BIT(20) +#define RCC_MC_APB2LPENSETR_ADFSDMLPEN BIT(21) +#define RCC_MC_APB2LPENSETR_FDCANLPEN BIT(24) + +/* RCC_MC_APB2LPENCLRR register fields */ +#define RCC_MC_APB2LPENCLRR_TIM1LPEN BIT(0) +#define RCC_MC_APB2LPENCLRR_TIM8LPEN BIT(1) +#define RCC_MC_APB2LPENCLRR_TIM15LPEN BIT(2) +#define RCC_MC_APB2LPENCLRR_TIM16LPEN BIT(3) +#define RCC_MC_APB2LPENCLRR_TIM17LPEN BIT(4) +#define RCC_MC_APB2LPENCLRR_SPI1LPEN BIT(8) +#define RCC_MC_APB2LPENCLRR_SPI4LPEN BIT(9) +#define RCC_MC_APB2LPENCLRR_SPI5LPEN BIT(10) +#define RCC_MC_APB2LPENCLRR_USART6LPEN BIT(13) +#define RCC_MC_APB2LPENCLRR_SAI1LPEN BIT(16) +#define RCC_MC_APB2LPENCLRR_SAI2LPEN BIT(17) +#define RCC_MC_APB2LPENCLRR_SAI3LPEN BIT(18) +#define RCC_MC_APB2LPENCLRR_DFSDMLPEN BIT(20) +#define RCC_MC_APB2LPENCLRR_ADFSDMLPEN BIT(21) +#define RCC_MC_APB2LPENCLRR_FDCANLPEN BIT(24) + +/* RCC_MC_APB3LPENSETR register fields */ +#define RCC_MC_APB3LPENSETR_LPTIM2LPEN BIT(0) +#define RCC_MC_APB3LPENSETR_LPTIM3LPEN BIT(1) +#define RCC_MC_APB3LPENSETR_LPTIM4LPEN BIT(2) +#define RCC_MC_APB3LPENSETR_LPTIM5LPEN BIT(3) +#define RCC_MC_APB3LPENSETR_SAI4LPEN BIT(8) +#define RCC_MC_APB3LPENSETR_SYSCFGLPEN BIT(11) +#define RCC_MC_APB3LPENSETR_VREFLPEN BIT(13) +#define RCC_MC_APB3LPENSETR_TMPSENSLPEN BIT(16) +#define RCC_MC_APB3LPENSETR_PMBCTRLLPEN BIT(17) + +/* RCC_MC_APB3LPENCLRR register fields */ +#define RCC_MC_APB3LPENCLRR_LPTIM2LPEN BIT(0) +#define RCC_MC_APB3LPENCLRR_LPTIM3LPEN BIT(1) +#define RCC_MC_APB3LPENCLRR_LPTIM4LPEN BIT(2) +#define RCC_MC_APB3LPENCLRR_LPTIM5LPEN BIT(3) +#define RCC_MC_APB3LPENCLRR_SAI4LPEN BIT(8) +#define RCC_MC_APB3LPENCLRR_SYSCFGLPEN BIT(11) +#define RCC_MC_APB3LPENCLRR_VREFLPEN BIT(13) +#define RCC_MC_APB3LPENCLRR_TMPSENSLPEN BIT(16) +#define RCC_MC_APB3LPENCLRR_PMBCTRLLPEN BIT(17) + +/* RCC_MC_AHB2LPENSETR register fields */ +#define RCC_MC_AHB2LPENSETR_DMA1LPEN BIT(0) +#define RCC_MC_AHB2LPENSETR_DMA2LPEN BIT(1) +#define RCC_MC_AHB2LPENSETR_DMAMUXLPEN BIT(2) +#define RCC_MC_AHB2LPENSETR_ADC12LPEN BIT(5) +#define RCC_MC_AHB2LPENSETR_USBOLPEN BIT(8) +#define RCC_MC_AHB2LPENSETR_SDMMC3LPEN BIT(16) + +/* RCC_MC_AHB2LPENCLRR register fields */ +#define RCC_MC_AHB2LPENCLRR_DMA1LPEN BIT(0) +#define RCC_MC_AHB2LPENCLRR_DMA2LPEN BIT(1) +#define RCC_MC_AHB2LPENCLRR_DMAMUXLPEN BIT(2) +#define RCC_MC_AHB2LPENCLRR_ADC12LPEN BIT(5) +#define RCC_MC_AHB2LPENCLRR_USBOLPEN BIT(8) +#define RCC_MC_AHB2LPENCLRR_SDMMC3LPEN BIT(16) + +/* RCC_MC_AHB3LPENSETR register fields */ +#define RCC_MC_AHB3LPENSETR_DCMILPEN BIT(0) +#define RCC_MC_AHB3LPENSETR_CRYP2LPEN BIT(4) +#define RCC_MC_AHB3LPENSETR_HASH2LPEN BIT(5) +#define RCC_MC_AHB3LPENSETR_RNG2LPEN BIT(6) +#define RCC_MC_AHB3LPENSETR_CRC2LPEN BIT(7) +#define RCC_MC_AHB3LPENSETR_HSEMLPEN BIT(11) +#define RCC_MC_AHB3LPENSETR_IPCCLPEN BIT(12) + +/* RCC_MC_AHB3LPENCLRR register fields */ +#define RCC_MC_AHB3LPENCLRR_DCMILPEN BIT(0) +#define RCC_MC_AHB3LPENCLRR_CRYP2LPEN BIT(4) +#define RCC_MC_AHB3LPENCLRR_HASH2LPEN BIT(5) +#define RCC_MC_AHB3LPENCLRR_RNG2LPEN BIT(6) +#define RCC_MC_AHB3LPENCLRR_CRC2LPEN BIT(7) +#define RCC_MC_AHB3LPENCLRR_HSEMLPEN BIT(11) +#define RCC_MC_AHB3LPENCLRR_IPCCLPEN BIT(12) + +/* RCC_MC_AHB4LPENSETR register fields */ +#define RCC_MC_AHB4LPENSETR_GPIOALPEN BIT(0) +#define RCC_MC_AHB4LPENSETR_GPIOBLPEN BIT(1) +#define RCC_MC_AHB4LPENSETR_GPIOCLPEN BIT(2) +#define RCC_MC_AHB4LPENSETR_GPIODLPEN BIT(3) +#define RCC_MC_AHB4LPENSETR_GPIOELPEN BIT(4) +#define RCC_MC_AHB4LPENSETR_GPIOFLPEN BIT(5) +#define RCC_MC_AHB4LPENSETR_GPIOGLPEN BIT(6) +#define RCC_MC_AHB4LPENSETR_GPIOHLPEN BIT(7) +#define RCC_MC_AHB4LPENSETR_GPIOILPEN BIT(8) +#define RCC_MC_AHB4LPENSETR_GPIOJLPEN BIT(9) +#define RCC_MC_AHB4LPENSETR_GPIOKLPEN BIT(10) + +/* RCC_MC_AHB4LPENCLRR register fields */ +#define RCC_MC_AHB4LPENCLRR_GPIOALPEN BIT(0) +#define RCC_MC_AHB4LPENCLRR_GPIOBLPEN BIT(1) +#define RCC_MC_AHB4LPENCLRR_GPIOCLPEN BIT(2) +#define RCC_MC_AHB4LPENCLRR_GPIODLPEN BIT(3) +#define RCC_MC_AHB4LPENCLRR_GPIOELPEN BIT(4) +#define RCC_MC_AHB4LPENCLRR_GPIOFLPEN BIT(5) +#define RCC_MC_AHB4LPENCLRR_GPIOGLPEN BIT(6) +#define RCC_MC_AHB4LPENCLRR_GPIOHLPEN BIT(7) +#define RCC_MC_AHB4LPENCLRR_GPIOILPEN BIT(8) +#define RCC_MC_AHB4LPENCLRR_GPIOJLPEN BIT(9) +#define RCC_MC_AHB4LPENCLRR_GPIOKLPEN BIT(10) + +/* RCC_MC_AXIMLPENSETR register fields */ +#define RCC_MC_AXIMLPENSETR_SYSRAMLPEN BIT(0) + +/* RCC_MC_AXIMLPENCLRR register fields */ +#define RCC_MC_AXIMLPENCLRR_SYSRAMLPEN BIT(0) + +/* RCC_MC_MLAHBLPENSETR register fields */ +#define RCC_MC_MLAHBLPENSETR_SRAM1LPEN BIT(0) +#define RCC_MC_MLAHBLPENSETR_SRAM2LPEN BIT(1) +#define RCC_MC_MLAHBLPENSETR_SRAM34LPEN BIT(2) +#define RCC_MC_MLAHBLPENSETR_RETRAMLPEN BIT(4) + +/* RCC_MC_MLAHBLPENCLRR register fields */ +#define RCC_MC_MLAHBLPENCLRR_SRAM1LPEN BIT(0) +#define RCC_MC_MLAHBLPENCLRR_SRAM2LPEN BIT(1) +#define RCC_MC_MLAHBLPENCLRR_SRAM34LPEN BIT(2) +#define RCC_MC_MLAHBLPENCLRR_RETRAMLPEN BIT(4) + +/* RCC_MC_RSTSCLRR register fields */ +#define RCC_MC_RSTSCLRR_PORRSTF BIT(0) +#define RCC_MC_RSTSCLRR_BORRSTF BIT(1) +#define RCC_MC_RSTSCLRR_PADRSTF BIT(2) +#define RCC_MC_RSTSCLRR_HCSSRSTF BIT(3) +#define RCC_MC_RSTSCLRR_VCORERSTF BIT(4) +#define RCC_MC_RSTSCLRR_MCURSTF BIT(5) +#define RCC_MC_RSTSCLRR_MPSYSRSTF BIT(6) +#define RCC_MC_RSTSCLRR_MCSYSRSTF BIT(7) +#define RCC_MC_RSTSCLRR_IWDG1RSTF BIT(8) +#define RCC_MC_RSTSCLRR_IWDG2RSTF BIT(9) +#define RCC_MC_RSTSCLRR_WWDG1RSTF BIT(10) + +/* RCC_MC_CIER register fields */ +#define RCC_MC_CIER_LSIRDYIE BIT(0) +#define RCC_MC_CIER_LSERDYIE BIT(1) +#define RCC_MC_CIER_HSIRDYIE BIT(2) +#define RCC_MC_CIER_HSERDYIE BIT(3) +#define RCC_MC_CIER_CSIRDYIE BIT(4) +#define RCC_MC_CIER_PLL1DYIE BIT(8) +#define RCC_MC_CIER_PLL2DYIE BIT(9) +#define RCC_MC_CIER_PLL3DYIE BIT(10) +#define RCC_MC_CIER_PLL4DYIE BIT(11) +#define RCC_MC_CIER_LSECSSIE BIT(16) +#define RCC_MC_CIER_WKUPIE BIT(20) + +/* RCC_MC_CIFR register fields */ +#define RCC_MC_CIFR_LSIRDYF BIT(0) +#define RCC_MC_CIFR_LSERDYF BIT(1) +#define RCC_MC_CIFR_HSIRDYF BIT(2) +#define RCC_MC_CIFR_HSERDYF BIT(3) +#define RCC_MC_CIFR_CSIRDYF BIT(4) +#define RCC_MC_CIFR_PLL1DYF BIT(8) +#define RCC_MC_CIFR_PLL2DYF BIT(9) +#define RCC_MC_CIFR_PLL3DYF BIT(10) +#define RCC_MC_CIFR_PLL4DYF BIT(11) +#define RCC_MC_CIFR_LSECSSF BIT(16) +#define RCC_MC_CIFR_WKUPF BIT(20) + +/* RCC_VERR register fields */ +#define RCC_VERR_MINREV_MASK GENMASK(3, 0) +#define RCC_VERR_MINREV_SHIFT 0 +#define RCC_VERR_MAJREV_MASK GENMASK(7, 4) +#define RCC_VERR_MAJREV_SHIFT 4 + +/* Used for RCC_OCENSETR and RCC_OCENCLRR registers */ +#define RCC_OCENR_HSION BIT(0) +#define RCC_OCENR_HSIKERON BIT(1) +#define RCC_OCENR_CSION BIT(4) +#define RCC_OCENR_CSIKERON BIT(5) +#define RCC_OCENR_DIGBYP BIT(7) +#define RCC_OCENR_HSEON BIT(8) +#define RCC_OCENR_HSEKERON BIT(9) +#define RCC_OCENR_HSEBYP BIT(10) +#define RCC_OCENR_HSECSSON BIT(11) + +/* Offset between RCC_MP_xxxENSETR and RCC_MP_xxxENCLRR registers */ +#define RCC_MP_ENCLRR_OFFSET U(4) + +/* Offset between RCC_xxxRSTSETR and RCC_xxxRSTCLRR registers */ +#define RCC_RSTCLRR_OFFSET U(4) + +/* Used for most of DIVR register: max div for RTC */ +#define RCC_DIVR_DIV_MASK GENMASK(5, 0) +#define RCC_DIVR_DIVRDY BIT(31) + +/* Masks for specific DIVR registers */ +#define RCC_APBXDIV_MASK GENMASK(2, 0) +#define RCC_MPUDIV_MASK GENMASK(2, 0) +#define RCC_AXIDIV_MASK GENMASK(2, 0) +#define RCC_MCUDIV_MASK GENMASK(3, 0) + +/* Used for most of RCC_SELR registers */ +#define RCC_SELR_SRC_MASK GENMASK(2, 0) +#define RCC_SELR_REFCLK_SRC_MASK GENMASK(1, 0) +#define RCC_SELR_SRCRDY BIT(31) + +/* Used for all RCC_PLLCR registers */ +#define RCC_PLLNCR_PLLON BIT(0) +#define RCC_PLLNCR_PLLRDY BIT(1) +#define RCC_PLLNCR_SSCG_CTRL BIT(2) +#define RCC_PLLNCR_DIVPEN BIT(4) +#define RCC_PLLNCR_DIVQEN BIT(5) +#define RCC_PLLNCR_DIVREN BIT(6) +#define RCC_PLLNCR_DIVEN_SHIFT 4 + +/* Used for all RCC_PLLCFGR1 registers */ +#define RCC_PLLNCFGR1_DIVM_MASK GENMASK(21, 16) +#define RCC_PLLNCFGR1_DIVM_SHIFT 16 +#define RCC_PLLNCFGR1_DIVN_MASK GENMASK(8, 0) +#define RCC_PLLNCFGR1_DIVN_SHIFT 0 + +/* Only for PLL3 and PLL4 */ +#define RCC_PLLNCFGR1_IFRGE_MASK GENMASK(25, 24) +#define RCC_PLLNCFGR1_IFRGE_SHIFT 24 + +/* Used for all RCC_PLLCFGR2 registers */ +#define RCC_PLLNCFGR2_DIVX_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_MASK GENMASK(6, 0) +#define RCC_PLLNCFGR2_DIVP_SHIFT 0 +#define RCC_PLLNCFGR2_DIVQ_MASK GENMASK(14, 8) +#define RCC_PLLNCFGR2_DIVQ_SHIFT 8 +#define RCC_PLLNCFGR2_DIVR_MASK GENMASK(22, 16) +#define RCC_PLLNCFGR2_DIVR_SHIFT 16 + +/* Used for all RCC_PLLFRACR registers */ +#define RCC_PLLNFRACR_FRACV_SHIFT 3 +#define RCC_PLLNFRACR_FRACV_MASK GENMASK(15, 3) +#define RCC_PLLNFRACR_FRACLE BIT(16) + +/* Used for all RCC_PLLCSGR registers */ +#define RCC_PLLNCSGR_INC_STEP_SHIFT 16 +#define RCC_PLLNCSGR_INC_STEP_MASK GENMASK(30, 16) +#define RCC_PLLNCSGR_MOD_PER_SHIFT 0 +#define RCC_PLLNCSGR_MOD_PER_MASK GENMASK(12, 0) +#define RCC_PLLNCSGR_SSCG_MODE_SHIFT 15 +#define RCC_PLLNCSGR_SSCG_MODE_MASK BIT(15) + +/* Used for TIMER Prescaler */ +#define RCC_TIMGXPRER_TIMGXPRE BIT(0) + +/* Used for RCC_MCO related operations */ +#define RCC_MCOCFG_MCOON BIT(12) +#define RCC_MCOCFG_MCODIV_MASK GENMASK(7, 4) +#define RCC_MCOCFG_MCODIV_SHIFT 4 +#define RCC_MCOCFG_MCOSRC_MASK GENMASK(2, 0) + +#endif /* STM32MP1_RCC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h new file mode 100644 index 0000000..e2395bc --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_CLK_H +#define STM32MP1_CLK_H + +#include + +enum stm32mp_osc_id { + _HSI, + _HSE, + _CSI, + _LSI, + _LSE, + _I2S_CKIN, + NB_OSC, + _UNKNOWN_OSC_ID = 0xFF +}; + +extern const char *stm32mp_osc_node_label[NB_OSC]; + +int stm32mp1_clk_probe(void); +int stm32mp1_clk_init(void); + +bool stm32mp1_rcc_is_secure(void); +bool stm32mp1_rcc_is_mckprot(void); + +/* SMP protection on RCC registers access */ +void stm32mp1_clk_rcc_regs_lock(void); +void stm32mp1_clk_rcc_regs_unlock(void); + +#ifdef STM32MP_SHARED_RESOURCES +void stm32mp1_register_clock_parents_secure(unsigned long id); +#endif +#endif /* STM32MP1_CLK_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h new file mode 100644 index 0000000..df71f35 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_H +#define STM32MP1_DDR_H + +#include +#include + +#include + +struct stm32mp1_ddrctrl_reg { + uint32_t mstr; + uint32_t mrctrl0; + uint32_t mrctrl1; + uint32_t derateen; + uint32_t derateint; + uint32_t pwrctl; + uint32_t pwrtmg; + uint32_t hwlpctl; + uint32_t rfshctl0; + uint32_t rfshctl3; + uint32_t crcparctl0; + uint32_t zqctl0; + uint32_t dfitmg0; + uint32_t dfitmg1; + uint32_t dfilpcfg0; + uint32_t dfiupd0; + uint32_t dfiupd1; + uint32_t dfiupd2; + uint32_t dfiphymstr; + uint32_t odtmap; + uint32_t dbg0; + uint32_t dbg1; + uint32_t dbgcmd; + uint32_t poisoncfg; + uint32_t pccfg; +}; + +struct stm32mp1_ddrctrl_timing { + uint32_t rfshtmg; + uint32_t dramtmg0; + uint32_t dramtmg1; + uint32_t dramtmg2; + uint32_t dramtmg3; + uint32_t dramtmg4; + uint32_t dramtmg5; + uint32_t dramtmg6; + uint32_t dramtmg7; + uint32_t dramtmg8; + uint32_t dramtmg14; + uint32_t odtcfg; +}; + +struct stm32mp1_ddrctrl_map { + uint32_t addrmap1; + uint32_t addrmap2; + uint32_t addrmap3; + uint32_t addrmap4; + uint32_t addrmap5; + uint32_t addrmap6; + uint32_t addrmap9; + uint32_t addrmap10; + uint32_t addrmap11; +}; + +struct stm32mp1_ddrctrl_perf { + uint32_t sched; + uint32_t sched1; + uint32_t perfhpr1; + uint32_t perflpr1; + uint32_t perfwr1; + uint32_t pcfgr_0; + uint32_t pcfgw_0; + uint32_t pcfgqos0_0; + uint32_t pcfgqos1_0; + uint32_t pcfgwqos0_0; + uint32_t pcfgwqos1_0; +#if STM32MP_DDR_DUAL_AXI_PORT + uint32_t pcfgr_1; + uint32_t pcfgw_1; + uint32_t pcfgqos0_1; + uint32_t pcfgqos1_1; + uint32_t pcfgwqos0_1; + uint32_t pcfgwqos1_1; +#endif +}; + +struct stm32mp1_ddrphy_reg { + uint32_t pgcr; + uint32_t aciocr; + uint32_t dxccr; + uint32_t dsgcr; + uint32_t dcr; + uint32_t odtcr; + uint32_t zq0cr1; + uint32_t dx0gcr; + uint32_t dx1gcr; +#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; + uint32_t dx3gcr; +#endif +}; + +struct stm32mp1_ddrphy_timing { + uint32_t ptr0; + uint32_t ptr1; + uint32_t ptr2; + uint32_t dtpr0; + uint32_t dtpr1; + uint32_t dtpr2; + uint32_t mr0; + uint32_t mr1; + uint32_t mr2; + uint32_t mr3; +}; + +struct stm32mp_ddr_config { + struct stm32mp_ddr_info info; + struct stm32mp1_ddrctrl_reg c_reg; + struct stm32mp1_ddrctrl_timing c_timing; + struct stm32mp1_ddrctrl_map c_map; + struct stm32mp1_ddrctrl_perf c_perf; + struct stm32mp1_ddrphy_reg p_reg; + struct stm32mp1_ddrphy_timing p_timing; +}; + +int stm32mp1_ddr_clk_enable(struct stm32mp_ddr_priv *priv, uint32_t mem_speed); +void stm32mp1_ddr_init(struct stm32mp_ddr_priv *priv, struct stm32mp_ddr_config *config); + +#endif /* STM32MP1_DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h new file mode 100644 index 0000000..38f2415 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_HELPERS_H +#define STM32MP1_DDR_HELPERS_H + +void ddr_enable_clock(void); + +#endif /* STM32MP1_DDR_HELPERS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h new file mode 100644 index 0000000..2fbe1c8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP1_DDR_REGS_H +#define STM32MP1_DDR_REGS_H + +#include +#include + +/* DDR Physical Interface Control (DDRPHYC) registers*/ +struct stm32mp_ddrphy { + uint32_t ridr; /* 0x00 R Revision Identification */ + uint32_t pir; /* 0x04 R/W PHY Initialization */ + uint32_t pgcr; /* 0x08 R/W PHY General Configuration */ + uint32_t pgsr; /* 0x0C PHY General Status */ + uint32_t dllgcr; /* 0x10 R/W DLL General Control */ + uint32_t acdllcr; /* 0x14 R/W AC DLL Control */ + uint32_t ptr0; /* 0x18 R/W PHY Timing 0 */ + uint32_t ptr1; /* 0x1C R/W PHY Timing 1 */ + uint32_t ptr2; /* 0x20 R/W PHY Timing 2 */ + uint32_t aciocr; /* 0x24 AC I/O Configuration */ + uint32_t dxccr; /* 0x28 DATX8 Common Configuration */ + uint32_t dsgcr; /* 0x2C DDR System General Configuration */ + uint32_t dcr; /* 0x30 DRAM Configuration */ + uint32_t dtpr0; /* 0x34 DRAM Timing Parameters0 */ + uint32_t dtpr1; /* 0x38 DRAM Timing Parameters1 */ + uint32_t dtpr2; /* 0x3C DRAM Timing Parameters2 */ + uint32_t mr0; /* 0x40 Mode 0 */ + uint32_t mr1; /* 0x44 Mode 1 */ + uint32_t mr2; /* 0x48 Mode 2 */ + uint32_t mr3; /* 0x4C Mode 3 */ + uint32_t odtcr; /* 0x50 ODT Configuration */ + uint32_t dtar; /* 0x54 data training address */ + uint32_t dtdr0; /* 0x58 */ + uint32_t dtdr1; /* 0x5c */ + uint8_t res1[0x0c0 - 0x060]; /* 0x60 */ + uint32_t dcuar; /* 0xc0 Address */ + uint32_t dcudr; /* 0xc4 DCU Data */ + uint32_t dcurr; /* 0xc8 DCU Run */ + uint32_t dculr; /* 0xcc DCU Loop */ + uint32_t dcugcr; /* 0xd0 DCU General Configuration */ + uint32_t dcutpr; /* 0xd4 DCU Timing Parameters */ + uint32_t dcusr0; /* 0xd8 DCU Status 0 */ + uint32_t dcusr1; /* 0xdc DCU Status 1 */ + uint8_t res2[0x100 - 0xe0]; /* 0xe0 */ + uint32_t bistrr; /* 0x100 BIST Run */ + uint32_t bistmskr0; /* 0x104 BIST Mask 0 */ + uint32_t bistmskr1; /* 0x108 BIST Mask 0 */ + uint32_t bistwcr; /* 0x10c BIST Word Count */ + uint32_t bistlsr; /* 0x110 BIST LFSR Seed */ + uint32_t bistar0; /* 0x114 BIST Address 0 */ + uint32_t bistar1; /* 0x118 BIST Address 1 */ + uint32_t bistar2; /* 0x11c BIST Address 2 */ + uint32_t bistupdr; /* 0x120 BIST User Data Pattern */ + uint32_t bistgsr; /* 0x124 BIST General Status */ + uint32_t bistwer; /* 0x128 BIST Word Error */ + uint32_t bistber0; /* 0x12c BIST Bit Error 0 */ + uint32_t bistber1; /* 0x130 BIST Bit Error 1 */ + uint32_t bistber2; /* 0x134 BIST Bit Error 2 */ + uint32_t bistwcsr; /* 0x138 BIST Word Count Status */ + uint32_t bistfwr0; /* 0x13c BIST Fail Word 0 */ + uint32_t bistfwr1; /* 0x140 BIST Fail Word 1 */ + uint8_t res3[0x178 - 0x144]; /* 0x144 */ + uint32_t gpr0; /* 0x178 General Purpose 0 (GPR0) */ + uint32_t gpr1; /* 0x17C General Purpose 1 (GPR1) */ + uint32_t zq0cr0; /* 0x180 zq 0 control 0 */ + uint32_t zq0cr1; /* 0x184 zq 0 control 1 */ + uint32_t zq0sr0; /* 0x188 zq 0 status 0 */ + uint32_t zq0sr1; /* 0x18C zq 0 status 1 */ + uint8_t res4[0x1C0 - 0x190]; /* 0x190 */ + uint32_t dx0gcr; /* 0x1c0 Byte lane 0 General Configuration */ + uint32_t dx0gsr0; /* 0x1c4 Byte lane 0 General Status 0 */ + uint32_t dx0gsr1; /* 0x1c8 Byte lane 0 General Status 1 */ + uint32_t dx0dllcr; /* 0x1cc Byte lane 0 DLL Control */ + uint32_t dx0dqtr; /* 0x1d0 Byte lane 0 DQ Timing */ + uint32_t dx0dqstr; /* 0x1d4 Byte lane 0 DQS Timing */ + uint8_t res5[0x200 - 0x1d8]; /* 0x1d8 */ + uint32_t dx1gcr; /* 0x200 Byte lane 1 General Configuration */ + uint32_t dx1gsr0; /* 0x204 Byte lane 1 General Status 0 */ + uint32_t dx1gsr1; /* 0x208 Byte lane 1 General Status 1 */ + uint32_t dx1dllcr; /* 0x20c Byte lane 1 DLL Control */ + uint32_t dx1dqtr; /* 0x210 Byte lane 1 DQ Timing */ + uint32_t dx1dqstr; /* 0x214 Byte lane 1 QS Timing */ + uint8_t res6[0x240 - 0x218]; /* 0x218 */ +#if STM32MP_DDR_32BIT_INTERFACE + uint32_t dx2gcr; /* 0x240 Byte lane 2 General Configuration */ + uint32_t dx2gsr0; /* 0x244 Byte lane 2 General Status 0 */ + uint32_t dx2gsr1; /* 0x248 Byte lane 2 General Status 1 */ + uint32_t dx2dllcr; /* 0x24c Byte lane 2 DLL Control */ + uint32_t dx2dqtr; /* 0x250 Byte lane 2 DQ Timing */ + uint32_t dx2dqstr; /* 0x254 Byte lane 2 QS Timing */ + uint8_t res7[0x280 - 0x258]; /* 0x258 */ + uint32_t dx3gcr; /* 0x280 Byte lane 3 General Configuration */ + uint32_t dx3gsr0; /* 0x284 Byte lane 3 General Status 0 */ + uint32_t dx3gsr1; /* 0x288 Byte lane 3 General Status 1 */ + uint32_t dx3dllcr; /* 0x28c Byte lane 3 DLL Control */ + uint32_t dx3dqtr; /* 0x290 Byte lane 3 DQ Timing */ + uint32_t dx3dqstr; /* 0x294 Byte lane 3 QS Timing */ +#endif +} __packed; + +/* DDR PHY registers offsets */ +#define DDRPHYC_PIR 0x004 +#define DDRPHYC_PGCR 0x008 +#define DDRPHYC_PGSR 0x00C +#define DDRPHYC_DLLGCR 0x010 +#define DDRPHYC_ACDLLCR 0x014 +#define DDRPHYC_PTR0 0x018 +#define DDRPHYC_ACIOCR 0x024 +#define DDRPHYC_DXCCR 0x028 +#define DDRPHYC_DSGCR 0x02C +#define DDRPHYC_ZQ0CR0 0x180 +#define DDRPHYC_DX0GCR 0x1C0 +#define DDRPHYC_DX0DLLCR 0x1CC +#define DDRPHYC_DX1GCR 0x200 +#define DDRPHYC_DX1DLLCR 0x20C +#if STM32MP_DDR_32BIT_INTERFACE +#define DDRPHYC_DX2GCR 0x240 +#define DDRPHYC_DX2DLLCR 0x24C +#define DDRPHYC_DX3GCR 0x280 +#define DDRPHYC_DX3DLLCR 0x28C +#endif + +/* DDR PHY Register fields */ +#define DDRPHYC_PIR_INIT BIT(0) +#define DDRPHYC_PIR_DLLSRST BIT(1) +#define DDRPHYC_PIR_DLLLOCK BIT(2) +#define DDRPHYC_PIR_ZCAL BIT(3) +#define DDRPHYC_PIR_ITMSRST BIT(4) +#define DDRPHYC_PIR_DRAMRST BIT(5) +#define DDRPHYC_PIR_DRAMINIT BIT(6) +#define DDRPHYC_PIR_QSTRN BIT(7) +#define DDRPHYC_PIR_RVTRN BIT(8) +#define DDRPHYC_PIR_ICPC BIT(16) +#define DDRPHYC_PIR_ZCALBYP BIT(30) +#define DDRPHYC_PIR_INITSTEPS_MASK GENMASK(31, 7) + +#define DDRPHYC_PGCR_DFTCMP BIT(2) +#define DDRPHYC_PGCR_PDDISDX BIT(24) +#define DDRPHYC_PGCR_RFSHDT_MASK GENMASK(28, 25) + +#define DDRPHYC_PGSR_IDONE BIT(0) +#define DDRPHYC_PGSR_DTERR BIT(5) +#define DDRPHYC_PGSR_DTIERR BIT(6) +#define DDRPHYC_PGSR_DFTERR BIT(7) +#define DDRPHYC_PGSR_RVERR BIT(8) +#define DDRPHYC_PGSR_RVEIRR BIT(9) + +#define DDRPHYC_DLLGCR_BPS200 BIT(23) + +#define DDRPHYC_ACDLLCR_DLLSRST BIT(30) +#define DDRPHYC_ACDLLCR_DLLDIS BIT(31) + +#define DDRPHYC_PTR0_TDLLSRST_OFFSET 0 +#define DDRPHYC_PTR0_TDLLSRST_MASK GENMASK(5, 0) +#define DDRPHYC_PTR0_TDLLLOCK_OFFSET 6 +#define DDRPHYC_PTR0_TDLLLOCK_MASK GENMASK(17, 6) +#define DDRPHYC_PTR0_TITMSRST_OFFSET 18 +#define DDRPHYC_PTR0_TITMSRST_MASK GENMASK(21, 18) + +#define DDRPHYC_ACIOCR_ACPDD BIT(3) +#define DDRPHYC_ACIOCR_ACPDR BIT(4) +#define DDRPHYC_ACIOCR_CKPDD_MASK GENMASK(10, 8) +#define DDRPHYC_ACIOCR_CKPDD_0 BIT(8) +#define DDRPHYC_ACIOCR_CKPDR_MASK GENMASK(13, 11) +#define DDRPHYC_ACIOCR_CKPDR_0 BIT(11) +#define DDRPHYC_ACIOCR_CSPDD_MASK GENMASK(21, 18) +#define DDRPHYC_ACIOCR_CSPDD_0 BIT(18) +#define DDRPHYC_ACIOCR_RSTPDD BIT(27) +#define DDRPHYC_ACIOCR_RSTPDR BIT(28) + +#define DDRPHYC_DXCCR_DXPDD BIT(2) +#define DDRPHYC_DXCCR_DXPDR BIT(3) + +#define DDRPHYC_DSGCR_CKEPDD_MASK GENMASK(19, 16) +#define DDRPHYC_DSGCR_CKEPDD_0 BIT(16) +#define DDRPHYC_DSGCR_ODTPDD_MASK GENMASK(23, 20) +#define DDRPHYC_DSGCR_ODTPDD_0 BIT(20) +#define DDRPHYC_DSGCR_NL2PD BIT(24) + +#define DDRPHYC_ZQ0CRN_ZDATA_MASK GENMASK(27, 0) +#define DDRPHYC_ZQ0CRN_ZDATA_SHIFT 0 +#define DDRPHYC_ZQ0CRN_ZDEN BIT(28) +#define DDRPHYC_ZQ0CRN_ZQPD BIT(31) + +#define DDRPHYC_DXNGCR_DXEN BIT(0) + +#define DDRPHYC_DXNDLLCR_DLLSRST BIT(30) +#define DDRPHYC_DXNDLLCR_DLLDIS BIT(31) +#define DDRPHYC_DXNDLLCR_SDPHASE_MASK GENMASK(17, 14) +#define DDRPHYC_DXNDLLCR_SDPHASE_SHIFT 14 + +#endif /* STM32MP1_DDR_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h new file mode 100644 index 0000000..e17df44 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_PWR_H +#define STM32MP1_PWR_H + +#include + +#define PWR_CR1 U(0x00) +#define PWR_CR2 U(0x08) +#define PWR_CR3 U(0x0C) +#define PWR_MPUCR U(0x10) +#define PWR_WKUPCR U(0x20) +#define PWR_MPUWKUPENR U(0x28) + +#define PWR_CR1_LPDS BIT(0) +#define PWR_CR1_LPCFG BIT(1) +#define PWR_CR1_LVDS BIT(2) +#define PWR_CR1_DBP BIT(8) + +#define PWR_CR3_DDRSREN BIT(10) +#define PWR_CR3_DDRSRDIS BIT(11) +#define PWR_CR3_DDRRETEN BIT(12) + +#define PWR_MPUCR_PDDS BIT(0) +#define PWR_MPUCR_CSTDBYDIS BIT(3) +#define PWR_MPUCR_CSSF BIT(9) + +#endif /* STM32MP1_PWR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h new file mode 100644 index 0000000..38360e7 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2018, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_RAM_H +#define STM32MP1_RAM_H + +int stm32mp1_ddr_probe(void); + +#endif /* STM32MP1_RAM_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h new file mode 100644 index 0000000..d794225 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if STM32MP13 +#include "stm32mp13_rcc.h" +#endif +#if STM32MP15 +#include "stm32mp15_rcc.h" +#endif diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h b/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h new file mode 100644 index 0000000..06a34cb --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_USB_H +#define STM32MP1_USB_H + +#include + +void stm32mp1_usb_init_driver(struct usb_handle *usb_core_handle, + struct pcd_handle *pcd_handle, + void *base_register); + +#endif /* STM32MP1_USB_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h b/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h new file mode 100644 index 0000000..61286b2 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_CLKFUNC_H +#define STM32MP_CLKFUNC_H + +#include + +#include + +#include + +int fdt_osc_read_freq(const char *name, uint32_t *freq); +bool fdt_clk_read_bool(const char *node_label, const char *prop_name); +uint32_t fdt_clk_read_uint32_default(const char *node_label, + const char *prop_name, + uint32_t dflt_value); + +int fdt_rcc_read_uint32_array(const char *prop_name, uint32_t count, + uint32_t *array); +int fdt_rcc_subnode_offset(const char *name); +const fdt32_t *fdt_rcc_read_prop(const char *prop_name, int *lenp); +bool fdt_get_rcc_secure_state(void); + +int fdt_get_clock_id(int node); +unsigned long fdt_get_uart_clock_freq(uintptr_t instance); + +void stm32mp_stgen_config(unsigned long rate); +void stm32mp_stgen_restore_counter(unsigned long long value, + unsigned long long offset_in_ms); +unsigned long long stm32mp_stgen_get_counter(void); + +#endif /* STM32MP_CLKFUNC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h new file mode 100644 index 0000000..1efca42 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP_DDR_H +#define STM32MP_DDR_H + +#include + +enum stm32mp_ddr_base_type { + DDR_BASE, + DDRPHY_BASE, + NONE_BASE +}; + +enum stm32mp_ddr_reg_type { + REG_REG, + REG_TIMING, + REG_PERF, + REG_MAP, + REGPHY_REG, + REGPHY_TIMING, + REG_TYPE_NB +}; + +struct stm32mp_ddr_reg_desc { + const char *name; + uint16_t offset; /* Offset for base address */ + uint8_t par_offset; /* Offset for parameter array */ +}; + +struct stm32mp_ddr_reg_info { + const char *name; + const struct stm32mp_ddr_reg_desc *desc; + uint8_t size; + enum stm32mp_ddr_base_type base; +}; + +struct stm32mp_ddr_size { + uint64_t base; + uint64_t size; +}; + +struct stm32mp_ddr_priv { + struct stm32mp_ddr_size info; + struct stm32mp_ddrctl *ctl; + struct stm32mp_ddrphy *phy; + uintptr_t pwr; + uintptr_t rcc; +}; + +struct stm32mp_ddr_info { + const char *name; + uint32_t speed; /* in kHZ */ + uint32_t size; /* Memory size in byte = col * row * width */ +}; + +#define TIMEOUT_US_1S 1000000U + +void stm32mp_ddr_set_reg(const struct stm32mp_ddr_priv *priv, enum stm32mp_ddr_reg_type type, + const void *param, const struct stm32mp_ddr_reg_info *ddr_registers); +void stm32mp_ddr_start_sw_done(struct stm32mp_ddrctl *ctl); +void stm32mp_ddr_wait_sw_done_ack(struct stm32mp_ddrctl *ctl); +void stm32mp_ddr_enable_axi_port(struct stm32mp_ddrctl *ctl); +int stm32mp_board_ddr_power_init(enum ddr_type ddr_type); + +#endif /* STM32MP_DDR_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h new file mode 100644 index 0000000..34e522a --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_DDR_TEST_H +#define STM32MP_DDR_TEST_H + +#include + +uint32_t stm32mp_ddr_test_rw_access(void); +uint32_t stm32mp_ddr_test_data_bus(void); +uint32_t stm32mp_ddr_test_addr_bus(uint64_t size); +uint32_t stm32mp_ddr_check_size(void); + +#endif /* STM32MP_DDR_TEST_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h new file mode 100644 index 0000000..79de86b --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h @@ -0,0 +1,265 @@ +/* + * Copyright (c) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef STM32MP_DDRCTRL_REGS_H +#define STM32MP_DDRCTRL_REGS_H + +#include +#include + +#include + +/* DDR Controller (DDRCTRL) registers */ +struct stm32mp_ddrctl { + uint32_t mstr ; /* 0x0 Master */ + uint32_t stat; /* 0x4 Operating Mode Status */ + uint8_t reserved008[0x10 - 0x8]; + uint32_t mrctrl0; /* 0x10 Control 0 */ + uint32_t mrctrl1; /* 0x14 Control 1 */ + uint32_t mrstat; /* 0x18 Status */ + uint32_t mrctrl2; /* 0x1c Control 2 */ + uint32_t derateen; /* 0x20 Temperature Derate Enable */ + uint32_t derateint; /* 0x24 Temperature Derate Interval */ + uint32_t reserved028; + uint32_t deratectl; /* 0x2c Temperature Derate Control */ + uint32_t pwrctl; /* 0x30 Low Power Control */ + uint32_t pwrtmg; /* 0x34 Low Power Timing */ + uint32_t hwlpctl; /* 0x38 Hardware Low Power Control */ + uint8_t reserved03c[0x50 - 0x3c]; + uint32_t rfshctl0; /* 0x50 Refresh Control 0 */ + uint32_t rfshctl1; /* 0x54 Refresh Control 1 */ + uint32_t reserved058; /* 0x58 Refresh Control 2 */ + uint32_t reserved05C; + uint32_t rfshctl3; /* 0x60 Refresh Control 0 */ + uint32_t rfshtmg; /* 0x64 Refresh Timing */ + uint32_t rfshtmg1; /* 0x68 Refresh Timing 1 */ + uint8_t reserved06c[0xc0 - 0x6c]; + uint32_t crcparctl0; /* 0xc0 CRC Parity Control0 */ + uint32_t crcparctl1; /* 0xc4 CRC Parity Control1 */ + uint32_t reserved0c8; /* 0xc8 CRC Parity Control2 */ + uint32_t crcparstat; /* 0xcc CRC Parity Status */ + uint32_t init0; /* 0xd0 SDRAM Initialization 0 */ + uint32_t init1; /* 0xd4 SDRAM Initialization 1 */ + uint32_t init2; /* 0xd8 SDRAM Initialization 2 */ + uint32_t init3; /* 0xdc SDRAM Initialization 3 */ + uint32_t init4; /* 0xe0 SDRAM Initialization 4 */ + uint32_t init5; /* 0xe4 SDRAM Initialization 5 */ + uint32_t init6; /* 0xe8 SDRAM Initialization 6 */ + uint32_t init7; /* 0xec SDRAM Initialization 7 */ + uint32_t dimmctl; /* 0xf0 DIMM Control */ + uint32_t rankctl; /* 0xf4 Rank Control */ + uint8_t reserved0f4[0x100 - 0xf8]; + uint32_t dramtmg0; /* 0x100 SDRAM Timing 0 */ + uint32_t dramtmg1; /* 0x104 SDRAM Timing 1 */ + uint32_t dramtmg2; /* 0x108 SDRAM Timing 2 */ + uint32_t dramtmg3; /* 0x10c SDRAM Timing 3 */ + uint32_t dramtmg4; /* 0x110 SDRAM Timing 4 */ + uint32_t dramtmg5; /* 0x114 SDRAM Timing 5 */ + uint32_t dramtmg6; /* 0x118 SDRAM Timing 6 */ + uint32_t dramtmg7; /* 0x11c SDRAM Timing 7 */ + uint32_t dramtmg8; /* 0x120 SDRAM Timing 8 */ + uint32_t dramtmg9; /* 0x124 SDRAM Timing 9 */ + uint32_t dramtmg10; /* 0x128 SDRAM Timing 10 */ + uint32_t dramtmg11; /* 0x12c SDRAM Timing 11 */ + uint32_t dramtmg12; /* 0x130 SDRAM Timing 12 */ + uint32_t dramtmg13; /* 0x134 SDRAM Timing 13 */ + uint32_t dramtmg14; /* 0x138 SDRAM Timing 14 */ + uint32_t dramtmg15; /* 0x13c SDRAM Timing 15 */ + uint8_t reserved140[0x180 - 0x140]; + uint32_t zqctl0; /* 0x180 ZQ Control 0 */ + uint32_t zqctl1; /* 0x184 ZQ Control 1 */ + uint32_t zqctl2; /* 0x188 ZQ Control 2 */ + uint32_t zqstat; /* 0x18c ZQ Status */ + uint32_t dfitmg0; /* 0x190 DFI Timing 0 */ + uint32_t dfitmg1; /* 0x194 DFI Timing 1 */ + uint32_t dfilpcfg0; /* 0x198 DFI Low Power Configuration 0 */ + uint32_t dfilpcfg1; /* 0x19c DFI Low Power Configuration 1 */ + uint32_t dfiupd0; /* 0x1a0 DFI Update 0 */ + uint32_t dfiupd1; /* 0x1a4 DFI Update 1 */ + uint32_t dfiupd2; /* 0x1a8 DFI Update 2 */ + uint32_t reserved1ac; + uint32_t dfimisc; /* 0x1b0 DFI Miscellaneous Control */ + uint32_t dfitmg2; /* 0x1b4 DFI Timing 2 */ + uint32_t dfitmg3; /* 0x1b8 DFI Timing 3 */ + uint32_t dfistat; /* 0x1bc DFI Status */ + uint32_t dbictl; /* 0x1c0 DM/DBI Control */ + uint32_t dfiphymstr; /* 0x1c4 DFI PHY Master interface */ + uint8_t reserved1c8[0x200 - 0x1c8]; + uint32_t addrmap0; /* 0x200 Address Map 0 */ + uint32_t addrmap1; /* 0x204 Address Map 1 */ + uint32_t addrmap2; /* 0x208 Address Map 2 */ + uint32_t addrmap3; /* 0x20c Address Map 3 */ + uint32_t addrmap4; /* 0x210 Address Map 4 */ + uint32_t addrmap5; /* 0x214 Address Map 5 */ + uint32_t addrmap6; /* 0x218 Address Map 6 */ + uint32_t addrmap7; /* 0x21c Address Map 7 */ + uint32_t addrmap8; /* 0x220 Address Map 8 */ + uint32_t addrmap9; /* 0x224 Address Map 9 */ + uint32_t addrmap10; /* 0x228 Address Map 10 */ + uint32_t addrmap11; /* 0x22C Address Map 11 */ + uint8_t reserved230[0x240 - 0x230]; + uint32_t odtcfg; /* 0x240 ODT Configuration */ + uint32_t odtmap; /* 0x244 ODT/Rank Map */ + uint8_t reserved248[0x250 - 0x248]; + uint32_t sched; /* 0x250 Scheduler Control */ + uint32_t sched1; /* 0x254 Scheduler Control 1 */ + uint32_t reserved258; + uint32_t perfhpr1; /* 0x25c High Priority Read CAM 1 */ + uint32_t reserved260; + uint32_t perflpr1; /* 0x264 Low Priority Read CAM 1 */ + uint32_t reserved268; + uint32_t perfwr1; /* 0x26c Write CAM 1 */ + uint8_t reserved27c[0x300 - 0x270]; + uint32_t dbg0; /* 0x300 Debug 0 */ + uint32_t dbg1; /* 0x304 Debug 1 */ + uint32_t dbgcam; /* 0x308 CAM Debug */ + uint32_t dbgcmd; /* 0x30c Command Debug */ + uint32_t dbgstat; /* 0x310 Status Debug */ + uint8_t reserved314[0x320 - 0x314]; + uint32_t swctl; /* 0x320 Software Programming Control Enable */ + uint32_t swstat; /* 0x324 Software Programming Control Status */ + uint8_t reserved328[0x36c - 0x328]; + uint32_t poisoncfg; /* 0x36c AXI Poison Configuration Register */ + uint32_t poisonstat; /* 0x370 AXI Poison Status Register */ + uint8_t reserved374[0x3f0 - 0x374]; + uint32_t deratestat; /* 0x3f0 Temperature Derate Status */ + uint8_t reserved3f4[0x3fc - 0x3f4]; + + /* Multi Port registers */ + uint32_t pstat; /* 0x3fc Port Status */ + uint32_t pccfg; /* 0x400 Port Common Configuration */ + + /* PORT 0 */ + uint32_t pcfgr_0; /* 0x404 Configuration Read */ + uint32_t pcfgw_0; /* 0x408 Configuration Write */ + uint8_t reserved40c[0x490 - 0x40c]; + uint32_t pctrl_0; /* 0x490 Port Control Register */ + uint32_t pcfgqos0_0; /* 0x494 Read QoS Configuration 0 */ + uint32_t pcfgqos1_0; /* 0x498 Read QoS Configuration 1 */ + uint32_t pcfgwqos0_0; /* 0x49c Write QoS Configuration 0 */ + uint32_t pcfgwqos1_0; /* 0x4a0 Write QoS Configuration 1 */ + uint8_t reserved4a4[0x4b4 - 0x4a4]; + +#if STM32MP_DDR_DUAL_AXI_PORT + /* PORT 1 */ + uint32_t pcfgr_1; /* 0x4b4 Configuration Read */ + uint32_t pcfgw_1; /* 0x4b8 Configuration Write */ + uint8_t reserved4bc[0x540 - 0x4bc]; + uint32_t pctrl_1; /* 0x540 Port 2 Control Register */ + uint32_t pcfgqos0_1; /* 0x544 Read QoS Configuration 0 */ + uint32_t pcfgqos1_1; /* 0x548 Read QoS Configuration 1 */ + uint32_t pcfgwqos0_1; /* 0x54c Write QoS Configuration 0 */ + uint32_t pcfgwqos1_1; /* 0x550 Write QoS Configuration 1 */ +#endif + + uint8_t reserved554[0xff0 - 0x554]; + uint32_t umctl2_ver_number; /* 0xff0 UMCTL2 Version Number */ +} __packed; + +/* DDR Controller registers offsets */ +#define DDRCTRL_MSTR 0x000 +#define DDRCTRL_STAT 0x004 +#define DDRCTRL_MRCTRL0 0x010 +#define DDRCTRL_MRSTAT 0x018 +#define DDRCTRL_PWRCTL 0x030 +#define DDRCTRL_PWRTMG 0x034 +#define DDRCTRL_HWLPCTL 0x038 +#define DDRCTRL_RFSHCTL3 0x060 +#define DDRCTRL_RFSHTMG 0x064 +#define DDRCTRL_INIT0 0x0D0 +#define DDRCTRL_DFIMISC 0x1B0 +#define DDRCTRL_DBG1 0x304 +#define DDRCTRL_DBGCAM 0x308 +#define DDRCTRL_DBGCMD 0x30C +#define DDRCTRL_DBGSTAT 0x310 +#define DDRCTRL_SWCTL 0x320 +#define DDRCTRL_SWSTAT 0x324 +#define DDRCTRL_PSTAT 0x3FC +#define DDRCTRL_PCTRL_0 0x490 +#if STM32MP_DDR_DUAL_AXI_PORT +#define DDRCTRL_PCTRL_1 0x540 +#endif + +/* DDR Controller Register fields */ +#define DDRCTRL_MSTR_DDR3 BIT(0) +#define DDRCTRL_MSTR_LPDDR2 BIT(2) +#define DDRCTRL_MSTR_LPDDR3 BIT(3) +#define DDRCTRL_MSTR_DDR4 BIT(4) +#define DDRCTRL_MSTR_LPDDR4 BIT(5) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_MASK GENMASK(13, 12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_FULL 0 +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_HALF BIT(12) +#define DDRCTRL_MSTR_DATA_BUS_WIDTH_QUARTER BIT(13) +#define DDRCTRL_MSTR_DLL_OFF_MODE BIT(15) + +#define DDRCTRL_STAT_OPERATING_MODE_MASK GENMASK(2, 0) +#define DDRCTRL_STAT_OPERATING_MODE_NORMAL BIT(0) +#define DDRCTRL_STAT_OPERATING_MODE_SR (BIT(0) | BIT(1)) +#define DDRCTRL_STAT_SELFREF_TYPE_MASK GENMASK(5, 4) +#define DDRCTRL_STAT_SELFREF_TYPE_ASR (BIT(4) | BIT(5)) +#define DDRCTRL_STAT_SELFREF_TYPE_SR BIT(5) + +#define DDRCTRL_MRCTRL0_MR_TYPE_WRITE U(0) +/* Only one rank supported */ +#define DDRCTRL_MRCTRL0_MR_RANK_SHIFT 4 +#define DDRCTRL_MRCTRL0_MR_RANK_ALL \ + BIT(DDRCTRL_MRCTRL0_MR_RANK_SHIFT) +#define DDRCTRL_MRCTRL0_MR_ADDR_SHIFT 12 +#define DDRCTRL_MRCTRL0_MR_ADDR_MASK GENMASK(15, 12) +#define DDRCTRL_MRCTRL0_MR_WR BIT(31) + +#define DDRCTRL_MRSTAT_MR_WR_BUSY BIT(0) + +#define DDRCTRL_PWRCTL_SELFREF_EN BIT(0) +#define DDRCTRL_PWRCTL_POWERDOWN_EN BIT(1) +#define DDRCTRL_PWRCTL_EN_DFI_DRAM_CLK_DISABLE BIT(3) +#define DDRCTRL_PWRCTL_SELFREF_SW BIT(5) + +#define DDRCTRL_PWRTMG_SELFREF_TO_X32_MASK GENMASK(23, 16) +#define DDRCTRL_PWRTMG_SELFREF_TO_X32_0 BIT(16) + +#define DDRCTRL_RFSHCTL3_DIS_AUTO_REFRESH BIT(0) +#define DDRCTRL_RFSHCTL3_REFRESH_UPDATE_LEVEL BIT(1) + +#define DDRCTRL_HWLPCTL_HW_LP_EN BIT(0) + +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_MASK GENMASK(27, 16) +#define DDRCTRL_RFSHTMG_T_RFC_NOM_X1_X32_SHIFT 16 + +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_MASK GENMASK(31, 30) +#define DDRCTRL_INIT0_SKIP_DRAM_INIT_NORMAL BIT(30) + +#define DDRCTRL_DFIMISC_DFI_INIT_COMPLETE_EN BIT(0) +#define DDRCTRL_DFIMISC_DFI_INIT_START BIT(5) + +#define DDRCTRL_DFISTAT_DFI_INIT_COMPLETE BIT(0) + +#define DDRCTRL_DBG1_DIS_HIF BIT(1) + +#define DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY BIT(29) +#define DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY BIT(28) +#define DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY BIT(26) +#define DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH GENMASK(12, 8) +#define DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH GENMASK(4, 0) +#define DDRCTRL_DBGCAM_DATA_PIPELINE_EMPTY \ + (DDRCTRL_DBGCAM_WR_DATA_PIPELINE_EMPTY | \ + DDRCTRL_DBGCAM_RD_DATA_PIPELINE_EMPTY) +#define DDRCTRL_DBGCAM_DBG_Q_DEPTH \ + (DDRCTRL_DBGCAM_DBG_WR_Q_EMPTY | \ + DDRCTRL_DBGCAM_DBG_LPR_Q_DEPTH | \ + DDRCTRL_DBGCAM_DBG_HPR_Q_DEPTH) + +#define DDRCTRL_DBGCMD_RANK0_REFRESH BIT(0) + +#define DDRCTRL_DBGSTAT_RANK0_REFRESH_BUSY BIT(0) + +#define DDRCTRL_SWCTL_SW_DONE BIT(0) + +#define DDRCTRL_SWSTAT_SW_DONE_ACK BIT(0) + +#define DDRCTRL_PCTRL_N_PORT_EN BIT(0) + +#endif /* STM32MP_DDRCTRL_REGS_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h b/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h new file mode 100644 index 0000000..303c571 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_PMIC_H +#define STM32MP_PMIC_H + +#include + +#include + +/* + * dt_pmic_status - Check PMIC status from device tree + * + * Returns the status of the PMIC (secure, non-secure), or a negative value on + * error + */ +int dt_pmic_status(void); + +/* + * initialize_pmic_i2c - Initialize I2C for the PMIC control + * + * Returns true if PMIC is available, false if not found, panics on errors + */ +bool initialize_pmic_i2c(void); + +/* + * initialize_pmic - Main PMIC initialization function, called at platform init + * + * Panics on errors + */ +void initialize_pmic(void); + +#if DEBUG +void print_pmic_info_and_debug(void); +#else +static inline void print_pmic_info_and_debug(void) +{ +} +#endif + +/* + * pmic_ddr_power_init - Initialize regulators required for DDR + * + * Returns 0 on success, and negative values on errors + */ +int pmic_ddr_power_init(enum ddr_type ddr_type); + +/* + * pmic_voltages_init - Update voltages for platform init + * + * Returns 0 on success, and negative values on errors + */ +int pmic_voltages_init(void); + +#endif /* STM32MP_PMIC_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h b/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h new file mode 100644 index 0000000..6e1e21d --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_ram.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef STM32MP_RAM_H +#define STM32MP_RAM_H + +#include + +#include + +#define PARAM(x, y) \ + { \ + .name = x, \ + .offset = offsetof(struct stm32mp_ddr_config, y), \ + .size = sizeof(config.y) / sizeof(uint32_t), \ + } + +#define CTL_PARAM(x) PARAM("st,ctl-"#x, c_##x) +#define PHY_PARAM(x) PARAM("st,phy-"#x, p_##x) + +struct stm32mp_ddr_param { + const char *name; /* Name in DT */ + const uint32_t offset; /* Offset in config struct */ + const uint32_t size; /* Size of parameters */ +}; + +int stm32mp_ddr_dt_get_info(void *fdt, int node, struct stm32mp_ddr_info *info); +int stm32mp_ddr_dt_get_param(void *fdt, int node, const struct stm32mp_ddr_param *param, + uint32_t param_size, uintptr_t config); + +#endif /* STM32MP_RAM_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h b/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h new file mode 100644 index 0000000..8444805 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stm32mp_reset.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2018-2019, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_RESET_H +#define STM32MP_RESET_H + +#include + +/* + * Assert target reset, if @to_us non null, wait until reset is asserted + * + * @reset_id: Reset controller ID + * @to_us: Timeout in microsecond, or 0 if not waiting + * Return 0 on success and -ETIMEDOUT if waiting and timeout expired + */ +int stm32mp_reset_assert(uint32_t reset_id, unsigned int to_us); + +/* + * Enable reset control for target resource + * + * @reset_id: Reset controller ID + */ +static inline void stm32mp_reset_set(uint32_t reset_id) +{ + (void)stm32mp_reset_assert(reset_id, 0U); +} + +/* + * Deassert target reset, if @to_us non null, wait until reset is deasserted + * + * @reset_id: Reset controller ID + * @to_us: Timeout in microsecond, or 0 if not waiting + * Return 0 on success and -ETIMEDOUT if waiting and timeout expired + */ +int stm32mp_reset_deassert(uint32_t reset_id, unsigned int to_us); + +/* + * Release reset control for target resource + * + * @reset_id: Reset controller ID + */ +static inline void stm32mp_reset_release(uint32_t reset_id) +{ + (void)stm32mp_reset_deassert(reset_id, 0U); +} + +#endif /* STM32MP_RESET_H */ diff --git a/arm-trusted-firmware/include/drivers/st/stpmic1.h b/arm-trusted-firmware/include/drivers/st/stpmic1.h new file mode 100644 index 0000000..2dfc7f8 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/st/stpmic1.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016-2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STPMIC1_H +#define STPMIC1_H + +#include +#include + +#define TURN_ON_REG 0x1U +#define TURN_OFF_REG 0x2U +#define ICC_LDO_TURN_OFF_REG 0x3U +#define ICC_BUCK_TURN_OFF_REG 0x4U +#define RESET_STATUS_REG 0x5U +#define VERSION_STATUS_REG 0x6U +#define MAIN_CONTROL_REG 0x10U +#define PADS_PULL_REG 0x11U +#define BUCK_PULL_DOWN_REG 0x12U +#define LDO14_PULL_DOWN_REG 0x13U +#define LDO56_PULL_DOWN_REG 0x14U +#define VIN_CONTROL_REG 0x15U +#define PONKEY_TIMER_REG 0x16U +#define MASK_RANK_BUCK_REG 0x17U +#define MASK_RESET_BUCK_REG 0x18U +#define MASK_RANK_LDO_REG 0x19U +#define MASK_RESET_LDO_REG 0x1AU +#define WATCHDOG_CONTROL_REG 0x1BU +#define WATCHDOG_TIMER_REG 0x1CU +#define BUCK_ICC_TURNOFF_REG 0x1DU +#define LDO_ICC_TURNOFF_REG 0x1EU +#define BUCK_APM_CONTROL_REG 0x1FU +#define BUCK1_CONTROL_REG 0x20U +#define BUCK2_CONTROL_REG 0x21U +#define BUCK3_CONTROL_REG 0x22U +#define BUCK4_CONTROL_REG 0x23U +#define VREF_DDR_CONTROL_REG 0x24U +#define LDO1_CONTROL_REG 0x25U +#define LDO2_CONTROL_REG 0x26U +#define LDO3_CONTROL_REG 0x27U +#define LDO4_CONTROL_REG 0x28U +#define LDO5_CONTROL_REG 0x29U +#define LDO6_CONTROL_REG 0x2AU +#define BUCK1_PWRCTRL_REG 0x30U +#define BUCK2_PWRCTRL_REG 0x31U +#define BUCK3_PWRCTRL_REG 0x32U +#define BUCK4_PWRCTRL_REG 0x33U +#define VREF_DDR_PWRCTRL_REG 0x34U +#define LDO1_PWRCTRL_REG 0x35U +#define LDO2_PWRCTRL_REG 0x36U +#define LDO3_PWRCTRL_REG 0x37U +#define LDO4_PWRCTRL_REG 0x38U +#define LDO5_PWRCTRL_REG 0x39U +#define LDO6_PWRCTRL_REG 0x3AU +#define FREQUENCY_SPREADING_REG 0x3BU +#define USB_CONTROL_REG 0x40U +#define ITLATCH1_REG 0x50U +#define ITLATCH2_REG 0x51U +#define ITLATCH3_REG 0x52U +#define ITLATCH4_REG 0x53U +#define ITSETLATCH1_REG 0x60U +#define ITSETLATCH2_REG 0x61U +#define ITSETLATCH3_REG 0x62U +#define ITSETLATCH4_REG 0x63U +#define ITCLEARLATCH1_REG 0x70U +#define ITCLEARLATCH2_REG 0x71U +#define ITCLEARLATCH3_REG 0x72U +#define ITCLEARLATCH4_REG 0x73U +#define ITMASK1_REG 0x80U +#define ITMASK2_REG 0x81U +#define ITMASK3_REG 0x82U +#define ITMASK4_REG 0x83U +#define ITSETMASK1_REG 0x90U +#define ITSETMASK2_REG 0x91U +#define ITSETMASK3_REG 0x92U +#define ITSETMASK4_REG 0x93U +#define ITCLEARMASK1_REG 0xA0U +#define ITCLEARMASK2_REG 0xA1U +#define ITCLEARMASK3_REG 0xA2U +#define ITCLEARMASK4_REG 0xA3U +#define ITSOURCE1_REG 0xB0U +#define ITSOURCE2_REG 0xB1U +#define ITSOURCE3_REG 0xB2U +#define ITSOURCE4_REG 0xB3U + +/* Registers masks */ +#define LDO_VOLTAGE_MASK GENMASK(6, 2) +#define BUCK_VOLTAGE_MASK GENMASK(7, 2) +#define LDO_BUCK_VOLTAGE_SHIFT 2 +#define LDO_BUCK_ENABLE_MASK BIT(0) +#define LDO_BUCK_HPLP_ENABLE_MASK BIT(1) +#define LDO_BUCK_HPLP_SHIFT 1 +#define LDO_BUCK_RANK_MASK BIT(0) +#define LDO_BUCK_RESET_MASK BIT(0) +#define LDO_BUCK_PULL_DOWN_MASK GENMASK(1, 0) + +/* Pull down register */ +#define BUCK1_PULL_DOWN_SHIFT 0 +#define BUCK2_PULL_DOWN_SHIFT 2 +#define BUCK3_PULL_DOWN_SHIFT 4 +#define BUCK4_PULL_DOWN_SHIFT 6 +#define VREF_DDR_PULL_DOWN_SHIFT 4 + +/* ICC register */ +#define BUCK1_ICC_SHIFT 0 +#define BUCK2_ICC_SHIFT 1 +#define BUCK3_ICC_SHIFT 2 +#define BUCK4_ICC_SHIFT 3 +#define PWR_SW1_ICC_SHIFT 4 +#define PWR_SW2_ICC_SHIFT 5 +#define BOOST_ICC_SHIFT 6 + +#define LDO1_ICC_SHIFT 0 +#define LDO2_ICC_SHIFT 1 +#define LDO3_ICC_SHIFT 2 +#define LDO4_ICC_SHIFT 3 +#define LDO5_ICC_SHIFT 4 +#define LDO6_ICC_SHIFT 5 + +/* Buck Mask reset register */ +#define BUCK1_MASK_RESET 0 +#define BUCK2_MASK_RESET 1 +#define BUCK3_MASK_RESET 2 +#define BUCK4_MASK_RESET 3 + +/* LDO Mask reset register */ +#define LDO1_MASK_RESET 0 +#define LDO2_MASK_RESET 1 +#define LDO3_MASK_RESET 2 +#define LDO4_MASK_RESET 3 +#define LDO5_MASK_RESET 4 +#define LDO6_MASK_RESET 5 +#define VREF_DDR_MASK_RESET 6 + +/* LDO3 Special modes */ +#define LDO3_BYPASS BIT(7) +#define LDO3_DDR_SEL 31U + +/* Main PMIC Control Register (MAIN_CONTROL_REG) */ +#define ICC_EVENT_ENABLED BIT(4) +#define PWRCTRL_POLARITY_HIGH BIT(3) +#define PWRCTRL_PIN_VALID BIT(2) +#define RESTART_REQUEST_ENABLED BIT(1) +#define SOFTWARE_SWITCH_OFF_ENABLED BIT(0) + +/* Main PMIC PADS Control Register (PADS_PULL_REG) */ +#define WAKEUP_DETECTOR_DISABLED BIT(4) +#define PWRCTRL_PD_ACTIVE BIT(3) +#define PWRCTRL_PU_ACTIVE BIT(2) +#define WAKEUP_PD_ACTIVE BIT(1) +#define PONKEY_PU_ACTIVE BIT(0) + +/* Main PMIC VINLOW Control Register (VIN_CONTROL_REGC DMSC) */ +#define SWIN_DETECTOR_ENABLED BIT(7) +#define SWOUT_DETECTOR_ENABLED BIT(6) +#define VINLOW_HYST_MASK GENMASK(1, 0) +#define VINLOW_HYST_SHIFT 4 +#define VINLOW_THRESHOLD_MASK GENMASK(2, 0) +#define VINLOW_THRESHOLD_SHIFT 1 +#define VINLOW_ENABLED BIT(0) +#define VINLOW_CTRL_REG_MASK GENMASK(7, 0) + +/* USB Control Register */ +#define BOOST_OVP_DISABLED BIT(7) +#define VBUS_OTG_DETECTION_DISABLED BIT(6) +#define SW_OUT_DISCHARGE BIT(5) +#define VBUS_OTG_DISCHARGE BIT(4) +#define OCP_LIMIT_HIGH BIT(3) +#define SWIN_SWOUT_ENABLED BIT(2) +#define USBSW_OTG_SWITCH_ENABLED BIT(1) +#define BOOST_ENABLED BIT(0) + +int stpmic1_powerctrl_on(void); +int stpmic1_switch_off(void); +int stpmic1_register_read(uint8_t register_id, uint8_t *value); +int stpmic1_register_write(uint8_t register_id, uint8_t value); +int stpmic1_register_update(uint8_t register_id, uint8_t value, uint8_t mask); +int stpmic1_regulator_enable(const char *name); +int stpmic1_regulator_disable(const char *name); +bool stpmic1_is_regulator_enabled(const char *name); +int stpmic1_regulator_voltage_set(const char *name, uint16_t millivolts); +int stpmic1_regulator_levels_mv(const char *name, const uint16_t **levels, + size_t *levels_count); +int stpmic1_regulator_voltage_get(const char *name); +int stpmic1_regulator_pull_down_set(const char *name); +int stpmic1_regulator_mask_reset_set(const char *name); +int stpmic1_regulator_icc_set(const char *name); +int stpmic1_regulator_sink_mode_set(const char *name); +int stpmic1_regulator_bypass_mode_set(const char *name); +int stpmic1_active_discharge_mode_set(const char *name); +void stpmic1_bind_i2c(struct i2c_handle_s *i2c_handle, uint16_t i2c_addr); + +int stpmic1_get_version(unsigned long *version); +void stpmic1_dump_regulators(void); + +#endif /* STPMIC1_H */ diff --git a/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h b/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h new file mode 100644 index 0000000..2004355 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DW_MMC_H +#define DW_MMC_H + +#include + +typedef struct dw_mmc_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + int clk_rate; + int bus_width; + unsigned int flags; + enum mmc_device_type mmc_dev_type; +} dw_mmc_params_t; + +void dw_mmc_init(dw_mmc_params_t *params, struct mmc_device_info *info); + +#endif /* DW_MMC_H */ diff --git a/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h b/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h new file mode 100644 index 0000000..bddd997 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UART_16550_H +#define UART_16550_H + +#include + +/* UART16550 Registers */ +#define UARTTX 0x0 +#define UARTRX 0x0 +#define UARTDLL 0x0 +#define UARTIER 0x4 +#define UARTDLLM 0x4 +#define UARTIIR 0x8 +#define UARTFCR 0x8 +#define UARTLCR 0xc +#define UARTMCR 0x10 +#define UARTLSR 0x14 +#define UARTMSR 0x18 +#define UARTSPR 0x1c +#define UARTCSR 0x20 +/* Some instances have MDR1 defined as well */ +#define UARTMDR1 0x20 +#define UARTRXFIFOCFG 0x24 +#define UARTMIE 0x28 +#define UARTVNDR 0x2c +#define UARTASR 0x3c + +/* FIFO Control Register bits */ +#define UARTFCR_FIFOMD_16450 (0 << 6) +#define UARTFCR_FIFOMD_16550 (1 << 6) +#define UARTFCR_RXTRIG_1 (0 << 6) +#define UARTFCR_RXTRIG_4 (1 << 6) +#define UARTFCR_RXTRIG_8 (2 << 6) +#define UARTFCR_RXTRIG_16 (3 << 6) +#define UARTFCR_TXTRIG_1 (0 << 4) +#define UARTFCR_TXTRIG_4 (1 << 4) +#define UARTFCR_TXTRIG_8 (2 << 4) +#define UARTFCR_TXTRIG_16 (3 << 4) +#define UARTFCR_DMAEN (1 << 3) /* Enable DMA mode */ +#define UARTFCR_TXCLR (1 << 2) /* Clear contents of Tx FIFO */ +#define UARTFCR_RXCLR (1 << 1) /* Clear contents of Rx FIFO */ +#define UARTFCR_FIFOEN (1 << 0) /* Enable the Tx/Rx FIFO */ + +/* Line Control Register bits */ +#define UARTLCR_DLAB (1 << 7) /* Divisor Latch Access */ +#define UARTLCR_SETB (1 << 6) /* Set BREAK Condition */ +#define UARTLCR_SETP (1 << 5) /* Set Parity to LCR[4] */ +#define UARTLCR_EVEN (1 << 4) /* Even Parity Format */ +#define UARTLCR_PAR (1 << 3) /* Parity */ +#define UARTLCR_STOP (1 << 2) /* Stop Bit */ +#define UARTLCR_WORDSZ_5 0 /* Word Length of 5 */ +#define UARTLCR_WORDSZ_6 1 /* Word Length of 6 */ +#define UARTLCR_WORDSZ_7 2 /* Word Length of 7 */ +#define UARTLCR_WORDSZ_8 3 /* Word Length of 8 */ + +/* Line Status Register bits */ +#define UARTLSR_RXFIFOEMT (1 << 9) /* Rx Fifo Empty */ +#define UARTLSR_TXFIFOFULL (1 << 8) /* Tx Fifo Full */ +#define UARTLSR_RXFIFOERR (1 << 7) /* Rx Fifo Error */ +#define UARTLSR_TEMT (1 << 6) /* Tx Shift Register Empty */ +#define UARTLSR_THRE (1 << 5) /* Tx Holding Register Empty */ +#define UARTLSR_BRK (1 << 4) /* Break Condition Detected */ +#define UARTLSR_FERR (1 << 3) /* Framing Error */ +#define UARTLSR_PERR (1 << 3) /* Parity Error */ +#define UARTLSR_OVRF (1 << 2) /* Rx Overrun Error */ +#define UARTLSR_RDR_BIT (0) /* Rx Data Ready Bit */ +#define UARTLSR_RDR (1 << UARTLSR_RDR_BIT) /* Rx Data Ready */ + +#ifndef __ASSEMBLER__ + +#include + +/* + * Initialize a new 16550 console instance and register it with the console + * framework. The |console| pointer must point to storage that will be valid + * for the lifetime of the console, such as a global or static local variable. + * Its contents will be reinitialized from scratch. + * When |clock| has a value of 0, the UART will *not* be initialised. This + * means the UART should already be enabled and the baudrate and clock setup + * should have been done already, either by platform specific code or by + * previous firmware stages. The |baud| parameter will be ignored in this + * case as well. + */ +int console_16550_register(uintptr_t baseaddr, uint32_t clock, uint32_t baud, + console_t *console); + +#endif /*__ASSEMBLER__*/ + +#endif /* UART_16550_H */ diff --git a/arm-trusted-firmware/include/drivers/ufs.h b/arm-trusted-firmware/include/drivers/ufs.h new file mode 100644 index 0000000..c074e85 --- /dev/null +++ b/arm-trusted-firmware/include/drivers/ufs.h @@ -0,0 +1,559 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UFS_H +#define UFS_H + +#include + +/* register map of UFSHCI */ +/* Controller Capabilities */ +#define CAP 0x00 +#define CAP_NUTRS_MASK 0x1F + +/* UFS Version */ +#define VER 0x08 +/* Host Controller Identification - Product ID */ +#define HCDDID 0x10 +/* Host Controller Identification Descriptor - Manufacturer ID */ +#define HCPMID 0x14 +/* Auto-Hibernate Idle Timer */ +#define AHIT 0x18 +/* Interrupt Status */ +#define IS 0x20 +/* Interrupt Enable */ +#define IE 0x24 +/* System Bus Fatal Error Status */ +#define UFS_INT_SBFES (1 << 17) +/* Host Controller Fatal Error Status */ +#define UFS_INT_HCFES (1 << 16) +/* UTP Error Status */ +#define UFS_INT_UTPES (1 << 12) +/* Device Fatal Error Status */ +#define UFS_INT_DFES (1 << 11) +/* UIC Command Completion Status */ +#define UFS_INT_UCCS (1 << 10) +/* UTP Task Management Request Completion Status */ +#define UFS_INT_UTMRCS (1 << 9) +/* UIC Link Startup Status */ +#define UFS_INT_ULSS (1 << 8) +/* UIC Link Lost Status */ +#define UFS_INT_ULLS (1 << 7) +/* UIC Hibernate Enter Status */ +#define UFS_INT_UHES (1 << 6) +/* UIC Hibernate Exit Status */ +#define UFS_INT_UHXS (1 << 5) +/* UIC Power Mode Status */ +#define UFS_INT_UPMS (1 << 4) +/* UIC Test Mode Status */ +#define UFS_INT_UTMS (1 << 3) +/* UIC Error */ +#define UFS_INT_UE (1 << 2) +/* UIC DME_ENDPOINTRESET Indication */ +#define UFS_INT_UDEPRI (1 << 1) +/* UTP Transfer Request Completion Status */ +#define UFS_INT_UTRCS (1 << 0) + +/* Host Controller Status */ +#define HCS 0x30 +#define HCS_UPMCRS_MASK (7 << 8) +#define HCS_PWR_LOCAL (1 << 8) +#define HCS_UCRDY (1 << 3) +#define HCS_UTMRLRDY (1 << 2) +#define HCS_UTRLRDY (1 << 1) +#define HCS_DP (1 << 0) + +/* Host Controller Enable */ +#define HCE 0x34 +#define HCE_ENABLE 1 + +/* Host UIC Error Code PHY Adapter Layer */ +#define UECPA 0x38 +/* Host UIC Error Code Data Link Layer */ +#define UECDL 0x3C +/* Host UIC Error Code Network Layer */ +#define UECN 0x40 +/* Host UIC Error Code Transport Layer */ +#define UECT 0x44 +/* Host UIC Error Code */ +#define UECDME 0x48 +/* UTP Transfer Request Interrupt Aggregation Control Register */ +#define UTRIACR 0x4C +#define UTRIACR_IAEN (1U << 31) +#define UTRIACR_IAPWEN (1 << 24) +#define UTRIACR_IASB (1 << 20) +#define UTRIACR_CTR (1 << 16) +#define UTRIACR_IACTH(x) (((x) & 0x1F) << 8) +#define UTRIACR_IATOVAL(x) ((x) & 0xFF) + +/* UTP Transfer Request List Base Address */ +#define UTRLBA 0x50 +/* UTP Transfer Request List Base Address Upper 32-bits */ +#define UTRLBAU 0x54 +/* UTP Transfer Request List Door Bell Register */ +#define UTRLDBR 0x58 +/* UTP Transfer Request List Clear Register */ +#define UTRLCLR 0x5C +/* UTP Transfer Request List Run Stop Register */ +#define UTRLRSR 0x60 +#define UTMRLBA 0x70 +#define UTMRLBAU 0x74 +#define UTMRLDBR 0x78 +#define UTMRLCLR 0x7C +#define UTMRLRSR 0x80 +/* UIC Command */ +#define UICCMD 0x90 +/* UIC Command Argument 1 */ +#define UCMDARG1 0x94 +/* UIC Command Argument 2 */ +#define UCMDARG2 0x98 +/* UIC Command Argument 3 */ +#define UCMDARG3 0x9C + +#define UFS_BLOCK_SHIFT 12 /* 4KB */ +#define UFS_BLOCK_SIZE (1 << UFS_BLOCK_SHIFT) +#define UFS_BLOCK_MASK (UFS_BLOCK_SIZE - 1) +#define UFS_MAX_LUNS 8 + +/* UTP Transfer Request Descriptor */ +/* Command Type */ +#define CT_UFS_STORAGE 1 +#define CT_SCSI 0 + +/* Data Direction */ +#define DD_OUT 2 /* Device --> Host */ +#define DD_IN 1 /* Host --> Device */ +#define DD_NO_DATA_TRANSFER 0 + +#define UTP_TRD_SIZE 32 + +/* Transaction Type */ +#define TRANS_TYPE_HD (1 << 7) /* E2ECRC */ +#define TRANS_TYPE_DD (1 << 6) +#define TRANS_TYPE_CODE_MASK 0x3F +#define QUERY_RESPONSE_UPIU (0x36 << 0) +#define READY_TO_TRANSACTION_UPIU (0x31 << 0) +#define DATA_IN_UPIU (0x22 << 0) +#define RESPONSE_UPIU (0x21 << 0) +#define NOP_IN_UPIU (0x20 << 0) +#define QUERY_REQUEST_UPIU (0x16 << 0) +#define DATA_OUT_UPIU (0x02 << 0) +#define CMD_UPIU (0x01 << 0) +#define NOP_OUT_UPIU (0x00 << 0) + +#define OCS_SUCCESS 0x0 +#define OCS_INVALID_FUNC_ATTRIBUTE 0x1 +#define OCS_MISMATCH_REQUEST_SIZE 0x2 +#define OCS_MISMATCH_RESPONSE_SIZE 0x3 +#define OCS_PEER_COMMUNICATION_FAILURE 0x4 +#define OCS_ABORTED 0x5 +#define OCS_FATAL_ERROR 0x6 +#define OCS_MASK 0xF + +/* UIC Command */ +#define DME_GET 0x01 +#define DME_SET 0x02 +#define DME_PEER_GET 0x03 +#define DME_PEER_SET 0x04 +#define DME_POWERON 0x10 +#define DME_POWEROFF 0x11 +#define DME_ENABLE 0x12 +#define DME_RESET 0x14 +#define DME_ENDPOINTRESET 0x15 +#define DME_LINKSTARTUP 0x16 +#define DME_HIBERNATE_ENTER 0x17 +#define DME_HIBERNATE_EXIT 0x18 +#define DME_TEST_MODE 0x1A + +#define GEN_SELECTOR_IDX(x) ((x) & 0xFFFF) + +#define CONFIG_RESULT_CODE_MASK 0xFF + +#define CDBCMD_TEST_UNIT_READY 0x00 +#define CDBCMD_READ_6 0x08 +#define CDBCMD_WRITE_6 0x0A +#define CDBCMD_START_STOP_UNIT 0x1B +#define CDBCMD_READ_CAPACITY_10 0x25 +#define CDBCMD_READ_10 0x28 +#define CDBCMD_WRITE_10 0x2A +#define CDBCMD_READ_16 0x88 +#define CDBCMD_WRITE_16 0x8A +#define CDBCMD_READ_CAPACITY_16 0x9E +#define CDBCMD_REPORT_LUNS 0xA0 + +#define UPIU_FLAGS_R (1 << 6) +#define UPIU_FLAGS_W (1 << 5) +#define UPIU_FLAGS_ATTR_MASK (3 << 0) +#define UPIU_FLAGS_ATTR_S (0 << 0) /* Simple */ +#define UPIU_FLAGS_ATTR_O (1 << 0) /* Ordered */ +#define UPIU_FLAGS_ATTR_HQ (2 << 0) /* Head of Queue */ +#define UPIU_FLAGS_ATTR_ACA (3 << 0) +#define UPIU_FLAGS_O (1 << 6) +#define UPIU_FLAGS_U (1 << 5) +#define UPIU_FLAGS_D (1 << 4) + +#define QUERY_FUNC_STD_READ 0x01 +#define QUERY_FUNC_STD_WRITE 0x81 + +#define QUERY_NOP 0x00 +#define QUERY_READ_DESC 0x01 +#define QUERY_WRITE_DESC 0x02 +#define QUERY_READ_ATTR 0x03 +#define QUERY_WRITE_ATTR 0x04 +#define QUERY_READ_FLAG 0x05 +#define QUERY_SET_FLAG 0x06 +#define QUERY_CLEAR_FLAG 0x07 +#define QUERY_TOGGLE_FLAG 0x08 + +#define RW_WITHOUT_CACHE 0x18 + +#define DESC_TYPE_DEVICE 0x00 +#define DESC_TYPE_CONFIGURATION 0x01 +#define DESC_TYPE_UNIT 0x02 +#define DESC_TYPE_INTERCONNECT 0x04 +#define DESC_TYPE_STRING 0x05 + +#define DESC_DEVICE_MAX_SIZE 0x1F +#define DEVICE_DESC_PARAM_MANF_ID 0x18 + +#define ATTR_CUR_PWR_MODE 0x02 /* bCurrentPowerMode */ +#define ATTR_ACTIVECC 0x03 /* bActiveICCLevel */ + +#define DEVICE_DESCRIPTOR_LEN 0x40 +#define UNIT_DESCRIPTOR_LEN 0x23 + +#define QUERY_RESP_SUCCESS 0x00 +#define QUERY_RESP_OPCODE 0xFE +#define QUERY_RESP_GENERAL_FAIL 0xFF + +#define SENSE_KEY_NO_SENSE 0x00 +#define SENSE_KEY_RECOVERED_ERROR 0x01 +#define SENSE_KEY_NOT_READY 0x02 +#define SENSE_KEY_MEDIUM_ERROR 0x03 +#define SENSE_KEY_HARDWARE_ERROR 0x04 +#define SENSE_KEY_ILLEGAL_REQUEST 0x05 +#define SENSE_KEY_UNIT_ATTENTION 0x06 +#define SENSE_KEY_DATA_PROTECT 0x07 +#define SENSE_KEY_BLANK_CHECK 0x08 +#define SENSE_KEY_VENDOR_SPECIFIC 0x09 +#define SENSE_KEY_COPY_ABORTED 0x0A +#define SENSE_KEY_ABORTED_COMMAND 0x0B +#define SENSE_KEY_VOLUME_OVERFLOW 0x0D +#define SENSE_KEY_MISCOMPARE 0x0E + +#define SENSE_DATA_VALID 0x70 +#define SENSE_DATA_LENGTH 18 + +#define READ_CAPACITY_LENGTH 8 + +#define FLAG_DEVICE_INIT 0x01 + +#define UFS_VENDOR_SKHYNIX U(0x1AD) + +#define MAX_MODEL_LEN 16 + +/* maximum number of retries for a general UIC command */ +#define UFS_UIC_COMMAND_RETRIES 3 + +/* maximum number of link-startup retries */ +#define DME_LINKSTARTUP_RETRIES 10 + +#define HCE_ENABLE_OUTER_RETRIES 3 +#define HCE_ENABLE_INNER_RETRIES 50 +#define HCE_ENABLE_TIMEOUT_US 100 + +/** + * ufs_dev_desc - ufs device details from the device descriptor + * @wmanufacturerid: card details + * @model: card model + */ +struct ufs_dev_desc { + uint16_t wmanufacturerid; + int8_t model[MAX_MODEL_LEN + 1]; +}; + +/* UFS Driver Flags */ +#define UFS_FLAGS_SKIPINIT (1 << 0) +#define UFS_FLAGS_VENDOR_SKHYNIX (U(1) << 2) + +typedef struct sense_data { + uint8_t resp_code : 7; + uint8_t valid : 1; + uint8_t reserved0; + uint8_t sense_key : 4; + uint8_t reserved1 : 1; + uint8_t ili : 1; + uint8_t eom : 1; + uint8_t file_mark : 1; + uint8_t info[4]; + uint8_t asl; + uint8_t cmd_spec_len[4]; + uint8_t asc; + uint8_t ascq; + uint8_t fruc; + uint8_t sense_key_spec0 : 7; + uint8_t sksv : 1; + uint8_t sense_key_spec1; + uint8_t sense_key_spec2; +} sense_data_t; + +/* UTP Transfer Request Descriptor */ +typedef struct utrd_header { + uint32_t reserved0 : 24; + uint32_t i : 1; /* interrupt */ + uint32_t dd : 2; /* data direction */ + uint32_t reserved1 : 1; + uint32_t ct : 4; /* command type */ + uint32_t reserved2; + uint32_t ocs : 8; /* Overall Command Status */ + uint32_t reserved3 : 24; + uint32_t reserved4; + uint32_t ucdba; /* aligned to 128-byte */ + uint32_t ucdbau; /* Upper 32-bits */ + uint32_t rul : 16; /* Response UPIU Length */ + uint32_t ruo : 16; /* Response UPIU Offset */ + uint32_t prdtl : 16; /* PRDT Length */ + uint32_t prdto : 16; /* PRDT Offset */ +} utrd_header_t; /* 8 words with little endian */ + +/* UTP Task Management Request Descriptor */ +typedef struct utp_utmrd { + /* 4 words with little endian */ + uint32_t reserved0 : 24; + uint32_t i : 1; /* interrupt */ + uint32_t reserved1 : 7; + uint32_t reserved2; + uint32_t ocs : 8; /* Overall Command Status */ + uint32_t reserved3 : 24; + uint32_t reserved4; + + /* followed by 8 words UPIU with big endian */ + + /* followed by 8 words Response UPIU with big endian */ +} utp_utmrd_t; + +/* NOP OUT UPIU */ +typedef struct nop_out_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t reserved2; + uint8_t reserved3; + uint8_t reserved4; + uint8_t total_ehs_len; + uint8_t reserved5; + uint16_t data_segment_len; + uint32_t reserved6; + uint32_t reserved7; + uint32_t reserved8; + uint32_t reserved9; + uint32_t reserved10; + uint32_t e2ecrc; +} nop_out_upiu_t; /* 36 bytes with big endian */ + +/* NOP IN UPIU */ +typedef struct nop_in_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t reserved2; + uint8_t response; + uint8_t reserved3; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + uint32_t reserved4; + uint32_t reserved5; + uint32_t reserved6; + uint32_t reserved7; + uint32_t reserved8; + uint32_t e2ecrc; +} nop_in_upiu_t; /* 36 bytes with big endian */ + +/* Command UPIU */ +typedef struct cmd_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t lun; + uint8_t task_tag; + uint8_t cmd_set_type; + uint8_t reserved0; + uint8_t reserved1; + uint8_t reserved2; + uint8_t total_ehs_len; + uint8_t reserved3; + uint16_t data_segment_len; + uint32_t exp_data_trans_len; + /* + * A CDB has a fixed length of 16bytes or a variable length + * of between 12 and 260 bytes + */ + uint8_t cdb[16]; /* little endian */ +} cmd_upiu_t; /* 32 bytes with big endian except for cdb[] */ + +typedef struct query_desc { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[2]; + uint16_t length; + uint32_t reserved2[2]; +} query_desc_t; /* 16 bytes with big endian */ + +typedef struct query_flag { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[7]; + uint8_t value; + uint32_t reserved8; +} query_flag_t; /* 16 bytes with big endian */ + +typedef struct query_attr { + uint8_t opcode; + uint8_t idn; + uint8_t index; + uint8_t selector; + uint8_t reserved0[4]; + uint32_t value; /* little endian */ + uint32_t reserved4; +} query_attr_t; /* 16 bytes with big endian except for value */ + +/* Query Request UPIU */ +typedef struct query_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t query_func; + uint8_t reserved2; + uint8_t reserved3; + uint8_t total_ehs_len; + uint8_t reserved4; + uint16_t data_segment_len; + /* Transaction Specific Fields */ + union { + query_desc_t desc; + query_flag_t flag; + query_attr_t attr; + } ts; + uint32_t reserved5; +} query_upiu_t; /* 32 bytes with big endian */ + +/* Query Response UPIU */ +typedef struct query_resp_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t reserved0; + uint8_t task_tag; + uint8_t reserved1; + uint8_t query_func; + uint8_t query_resp; + uint8_t reserved2; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + union { + query_desc_t desc; + query_flag_t flag; + query_attr_t attr; + } ts; + uint32_t reserved3; +} query_resp_upiu_t; /* 32 bytes with big endian */ + +/* Response UPIU */ +typedef struct resp_upiu { + uint8_t trans_type; + uint8_t flags; + uint8_t lun; + uint8_t task_tag; + uint8_t cmd_set_type; + uint8_t reserved0; + uint8_t reserved1; + uint8_t status; + uint8_t total_ehs_len; + uint8_t dev_info; + uint16_t data_segment_len; + uint32_t res_trans_cnt; /* Residual Transfer Count */ + uint32_t reserved2[4]; + uint16_t sense_data_len; + union { + uint8_t sense_data[18]; + sense_data_t sense; + } sd; +} resp_upiu_t; /* 52 bytes with big endian */ + +typedef struct cmd_info { + uintptr_t buf; + size_t length; + int lba; + uint8_t op; + uint8_t direction; + uint8_t lun; +} cmd_info_t; + +typedef struct utp_utrd { + uintptr_t header; /* utrd_header_t */ + uintptr_t upiu; + uintptr_t resp_upiu; + uintptr_t prdt; + size_t size_upiu; + size_t size_resp_upiu; + size_t size_prdt; + int task_tag; +} utp_utrd_t; + +/* Physical Region Description Table */ +typedef struct prdt { + uint32_t dba; /* Data Base Address */ + uint32_t dbau; /* Data Base Address Upper 32-bits */ + uint32_t reserved0; + uint32_t dbc : 18; /* Data Byte Count */ + uint32_t reserved1 : 14; +} prdt_t; + +typedef struct uic_cmd { + uint32_t op; + uint32_t arg1; + uint32_t arg2; + uint32_t arg3; +} uic_cmd_t; + +typedef struct ufs_params { + uintptr_t reg_base; + uintptr_t desc_base; + size_t desc_size; + unsigned long flags; +} ufs_params_t; + +typedef struct ufs_ops { + int (*phy_init)(ufs_params_t *params); + int (*phy_set_pwr_mode)(ufs_params_t *params); +} ufs_ops_t; + +int ufshc_send_uic_cmd(uintptr_t base, uic_cmd_t *cmd); +int ufshc_dme_get(unsigned int attr, unsigned int idx, unsigned int *val); +int ufshc_dme_set(unsigned int attr, unsigned int idx, unsigned int val); + +unsigned int ufs_read_attr(int idn); +void ufs_write_attr(int idn, unsigned int value); +unsigned int ufs_read_flag(int idn); +void ufs_set_flag(int idn); +void ufs_clear_flag(int idn); +void ufs_read_desc(int idn, int index, uintptr_t buf, size_t size); +void ufs_write_desc(int idn, int index, uintptr_t buf, size_t size); +size_t ufs_read_blocks(int lun, int lba, uintptr_t buf, size_t size); +size_t ufs_write_blocks(int lun, int lba, const uintptr_t buf, size_t size); +int ufs_init(const ufs_ops_t *ops, ufs_params_t *params); + +#endif /* UFS_H */ diff --git a/arm-trusted-firmware/include/drivers/usb_device.h b/arm-trusted-firmware/include/drivers/usb_device.h new file mode 100644 index 0000000..8fdb6ae --- /dev/null +++ b/arm-trusted-firmware/include/drivers/usb_device.h @@ -0,0 +1,278 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef USB_DEVICE_H +#define USB_DEVICE_H + +#include + +#include + +#define USBD_MAX_NUM_INTERFACES 1U +#define USBD_MAX_NUM_CONFIGURATION 1U + +#define USB_LEN_DEV_QUALIFIER_DESC 0x0AU +#define USB_LEN_DEV_DESC 0x12U +#define USB_LEN_CFG_DESC 0x09U +#define USB_LEN_IF_DESC 0x09U +#define USB_LEN_EP_DESC 0x07U +#define USB_LEN_OTG_DESC 0x03U +#define USB_LEN_LANGID_STR_DESC 0x04U +#define USB_LEN_OTHER_SPEED_DESC_SIZ 0x09U + +#define USBD_IDX_LANGID_STR 0x00U +#define USBD_IDX_MFC_STR 0x01U +#define USBD_IDX_PRODUCT_STR 0x02U +#define USBD_IDX_SERIAL_STR 0x03U +#define USBD_IDX_CONFIG_STR 0x04U +#define USBD_IDX_INTERFACE_STR 0x05U +#define USBD_IDX_USER0_STR 0x06U + +#define USB_REQ_TYPE_STANDARD 0x00U +#define USB_REQ_TYPE_CLASS 0x20U +#define USB_REQ_TYPE_VENDOR 0x40U +#define USB_REQ_TYPE_MASK 0x60U + +#define USB_REQ_RECIPIENT_DEVICE 0x00U +#define USB_REQ_RECIPIENT_INTERFACE 0x01U +#define USB_REQ_RECIPIENT_ENDPOINT 0x02U +#define USB_REQ_RECIPIENT_MASK 0x1FU + +#define USB_REQ_DIRECTION 0x80U + +#define USB_REQ_GET_STATUS 0x00U +#define USB_REQ_CLEAR_FEATURE 0x01U +#define USB_REQ_SET_FEATURE 0x03U +#define USB_REQ_SET_ADDRESS 0x05U +#define USB_REQ_GET_DESCRIPTOR 0x06U +#define USB_REQ_SET_DESCRIPTOR 0x07U +#define USB_REQ_GET_CONFIGURATION 0x08U +#define USB_REQ_SET_CONFIGURATION 0x09U +#define USB_REQ_GET_INTERFACE 0x0AU +#define USB_REQ_SET_INTERFACE 0x0BU +#define USB_REQ_SYNCH_FRAME 0x0CU + +#define USB_DESC_TYPE_DEVICE 0x01U +#define USB_DESC_TYPE_CONFIGURATION 0x02U +#define USB_DESC_TYPE_STRING 0x03U +#define USB_DESC_TYPE_INTERFACE 0x04U +#define USB_DESC_TYPE_ENDPOINT 0x05U +#define USB_DESC_TYPE_DEVICE_QUALIFIER 0x06U +#define USB_DESC_TYPE_OTHER_SPEED_CONFIGURATION 0x07U +#define USB_DESC_TYPE_BOS 0x0FU + +#define USB_CONFIG_REMOTE_WAKEUP 2U +#define USB_CONFIG_SELF_POWERED 1U + +#define USB_MAX_EP0_SIZE 64U + +/* Device Status */ +#define USBD_STATE_DEFAULT 1U +#define USBD_STATE_ADDRESSED 2U +#define USBD_STATE_CONFIGURED 3U +#define USBD_STATE_SUSPENDED 4U + +/* EP0 State */ +#define USBD_EP0_IDLE 0U +#define USBD_EP0_SETUP 1U +#define USBD_EP0_DATA_IN 2U +#define USBD_EP0_DATA_OUT 3U +#define USBD_EP0_STATUS_IN 4U +#define USBD_EP0_STATUS_OUT 5U +#define USBD_EP0_STALL 6U + +#define USBD_EP_TYPE_CTRL 0U +#define USBD_EP_TYPE_ISOC 1U +#define USBD_EP_TYPE_BULK 2U +#define USBD_EP_TYPE_INTR 3U + +#define USBD_OUT_EPNUM_MASK GENMASK(15, 0) +#define USBD_OUT_COUNT_MASK GENMASK(31, 16) +#define USBD_OUT_COUNT_SHIFT 16U + +/* Number of EP supported, allow to reduce footprint: default max = 15 */ +#ifndef CONFIG_USBD_EP_NB +#define USBD_EP_NB 15U +#else +#define USBD_EP_NB CONFIG_USBD_EP_NB +#endif + +#define LOBYTE(x) ((uint8_t)((x) & 0x00FF)) +#define HIBYTE(x) ((uint8_t)(((x) & 0xFF00) >> 8)) + +struct usb_setup_req { + uint8_t bm_request; + uint8_t b_request; + uint16_t value; + uint16_t index; + uint16_t length; +}; + +struct usb_handle; + +struct usb_class { + uint8_t (*init)(struct usb_handle *pdev, uint8_t cfgidx); + uint8_t (*de_init)(struct usb_handle *pdev, uint8_t cfgidx); + /* Control Endpoints */ + uint8_t (*setup)(struct usb_handle *pdev, struct usb_setup_req *req); + uint8_t (*ep0_tx_sent)(struct usb_handle *pdev); + uint8_t (*ep0_rx_ready)(struct usb_handle *pdev); + /* Class Specific Endpoints */ + uint8_t (*data_in)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*data_out)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*sof)(struct usb_handle *pdev); + uint8_t (*iso_in_incomplete)(struct usb_handle *pdev, uint8_t epnum); + uint8_t (*iso_out_incomplete)(struct usb_handle *pdev, uint8_t epnum); +}; + +/* Following USB Device status */ +enum usb_status { + USBD_OK = 0U, + USBD_BUSY, + USBD_FAIL, + USBD_TIMEOUT +}; + +/* Action to do after IT handling */ +enum usb_action { + USB_NOTHING = 0U, + USB_DATA_OUT, + USB_DATA_IN, + USB_SETUP, + USB_ENUM_DONE, + USB_READ_DATA_PACKET, + USB_READ_SETUP_PACKET, + USB_RESET, + USB_RESUME, + USB_SUSPEND, + USB_LPM, + USB_SOF, + USB_DISCONNECT, + USB_WRITE_EMPTY +}; + +/* USB Device descriptors structure */ +struct usb_desc { + uint8_t *(*get_device_desc)(uint16_t *length); + uint8_t *(*get_lang_id_desc)(uint16_t *length); + uint8_t *(*get_manufacturer_desc)(uint16_t *length); + uint8_t *(*get_product_desc)(uint16_t *length); + uint8_t *(*get_serial_desc)(uint16_t *length); + uint8_t *(*get_configuration_desc)(uint16_t *length); + uint8_t *(*get_interface_desc)(uint16_t *length); + uint8_t *(*get_usr_desc)(uint8_t index, uint16_t *length); + uint8_t *(*get_config_desc)(uint16_t *length); + uint8_t *(*get_device_qualifier_desc)(uint16_t *length); + /* optional: high speed capable device operating at its other speed */ + uint8_t *(*get_other_speed_config_desc)(uint16_t *length); +}; + +/* USB Device handle structure */ +struct usb_endpoint { + uint32_t status; + uint32_t total_length; + uint32_t rem_length; + uint32_t maxpacket; +}; + +/* + * EndPoint descriptor + * num : Endpoint number, between 0 and 15 (limited by USBD_EP_NB) + * is_in: Endpoint direction + * type : Endpoint type + * maxpacket: Endpoint Max packet size: between 0 and 64KB + * xfer_buff: Pointer to transfer buffer + * xfer_len: Current transfer lengt + * hxfer_count: Partial transfer length in case of multi packet transfer + */ +struct usbd_ep { + uint8_t num; + bool is_in; + uint8_t type; + uint32_t maxpacket; + uint8_t *xfer_buff; + uint32_t xfer_len; + uint32_t xfer_count; +}; + +enum pcd_lpm_state { + LPM_L0 = 0x00U, /* on */ + LPM_L1 = 0x01U, /* LPM L1 sleep */ + LPM_L2 = 0x02U, /* suspend */ + LPM_L3 = 0x03U, /* off */ +}; + +/* USB Device descriptors structure */ +struct usb_driver { + enum usb_status (*ep0_out_start)(void *handle); + enum usb_status (*ep_start_xfer)(void *handle, struct usbd_ep *ep); + enum usb_status (*ep0_start_xfer)(void *handle, struct usbd_ep *ep); + enum usb_status (*write_packet)(void *handle, uint8_t *src, + uint8_t ch_ep_num, uint16_t len); + void *(*read_packet)(void *handle, uint8_t *dest, uint16_t len); + enum usb_status (*ep_set_stall)(void *handle, struct usbd_ep *ep); + enum usb_status (*start_device)(void *handle); + enum usb_status (*stop_device)(void *handle); + enum usb_status (*set_address)(void *handle, uint8_t address); + enum usb_status (*write_empty_tx_fifo)(void *handle, + uint32_t epnum, uint32_t xfer_len, + uint32_t *xfer_count, + uint32_t maxpacket, + uint8_t **xfer_buff); + enum usb_action (*it_handler)(void *handle, uint32_t *param); +}; + +/* USB Peripheral Controller Drivers */ +struct pcd_handle { + void *instance; /* Register base address */ + struct usbd_ep in_ep[USBD_EP_NB]; /* IN endpoint parameters */ + struct usbd_ep out_ep[USBD_EP_NB]; /* OUT endpoint parameters */ + uint32_t setup[12]; /* Setup packet buffer */ + enum pcd_lpm_state lpm_state; /* LPM State */ +}; + +/* USB Device handle structure */ +struct usb_handle { + uint8_t id; + uint32_t dev_config; + uint32_t dev_config_status; + struct usb_endpoint ep_in[USBD_EP_NB]; + struct usb_endpoint ep_out[USBD_EP_NB]; + uint32_t ep0_state; + uint32_t ep0_data_len; + uint8_t dev_state; + uint8_t dev_old_state; + uint8_t dev_address; + uint32_t dev_remote_wakeup; + struct usb_setup_req request; + const struct usb_desc *desc; + struct usb_class *class; + void *class_data; + void *user_data; + struct pcd_handle *data; + const struct usb_driver *driver; +}; + +enum usb_status usb_core_handle_it(struct usb_handle *pdev); +enum usb_status usb_core_receive(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *p_buf, uint32_t len); +enum usb_status usb_core_transmit(struct usb_handle *pdev, uint8_t ep_addr, + uint8_t *p_buf, uint32_t len); +enum usb_status usb_core_receive_ep0(struct usb_handle *pdev, uint8_t *p_buf, + uint32_t len); +enum usb_status usb_core_transmit_ep0(struct usb_handle *pdev, uint8_t *p_buf, + uint32_t len); +void usb_core_ctl_error(struct usb_handle *pdev); +enum usb_status usb_core_start(struct usb_handle *pdev); +enum usb_status usb_core_stop(struct usb_handle *pdev); +enum usb_status register_usb_driver(struct usb_handle *pdev, + struct pcd_handle *pcd_handle, + const struct usb_driver *driver, + void *driver_handle); +enum usb_status register_platform(struct usb_handle *pdev, + const struct usb_desc *plat_call_back); + +#endif /* USB_DEVICE_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h new file mode 100644 index 0000000..0d25ded --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h @@ -0,0 +1,12 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#if STM32MP13 +#include "stm32mp13-clks.h" +#endif +#if STM32MP15 +#include "stm32mp15-clks.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h new file mode 100644 index 0000000..d02ddcd --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2017-2022, STMicroelectronics - All Rights Reserved + */ + +#if STM32MP13 +#include "stm32mp13-clksrc.h" +#endif +#if STM32MP15 +#include "stm32mp15-clksrc.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h new file mode 100644 index 0000000..1d5bb78 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h @@ -0,0 +1,230 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_CLKS_H_ +#define _DT_BINDINGS_STM32MP13_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* PLL */ +#define PLL1 6 +#define PLL2 7 +#define PLL3 8 +#define PLL4 9 + +/* ODF */ +#define PLL1_P 10 +#define PLL1_Q 11 +#define PLL1_R 12 +#define PLL2_P 13 +#define PLL2_Q 14 +#define PLL2_R 15 +#define PLL3_P 16 +#define PLL3_Q 17 +#define PLL3_R 18 +#define PLL4_P 19 +#define PLL4_Q 20 +#define PLL4_R 21 + +#define PCLK1 22 +#define PCLK2 23 +#define PCLK3 24 +#define PCLK4 25 +#define PCLK5 26 +#define PCLK6 27 + +/* SYSTEM CLOCK */ +#define CK_PER 28 +#define CK_MPU 29 +#define CK_AXI 30 +#define CK_MLAHB 31 + +/* BASE TIMER */ +#define CK_TIMG1 32 +#define CK_TIMG2 33 +#define CK_TIMG3 34 + +/* AUX */ +#define RTC 35 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 36 +#define CK_TRACE 37 + +/* MCO clocks */ +#define CK_MCO1 38 +#define CK_MCO2 39 + +/* IP clocks */ +#define SYSCFG 40 +#define VREF 41 +#define TMPSENS 42 +#define PMBCTRL 43 +#define HDP 44 +#define IWDG2 45 +#define STGENRO 46 +#define USART1 47 +#define RTCAPB 48 +#define TZC 49 +#define TZPC 50 +#define IWDG1 51 +#define BSEC 52 +#define DMA1 53 +#define DMA2 54 +#define DMAMUX1 55 +#define DMAMUX2 56 +#define GPIOA 57 +#define GPIOB 58 +#define GPIOC 59 +#define GPIOD 60 +#define GPIOE 61 +#define GPIOF 62 +#define GPIOG 63 +#define GPIOH 64 +#define GPIOI 65 +#define CRYP1 66 +#define HASH1 67 +#define BKPSRAM 68 +#define MDMA 69 +#define CRC1 70 +#define USBH 71 +#define DMA3 72 +#define TSC 73 +#define PKA 74 +#define AXIMC 75 +#define MCE 76 +#define ETH1TX 77 +#define ETH2TX 78 +#define ETH1RX 79 +#define ETH2RX 80 +#define ETH1MAC 81 +#define ETH2MAC 82 +#define ETH1STP 83 +#define ETH2STP 84 + +/* IP clocks with parents */ +#define SDMMC1_K 85 +#define SDMMC2_K 86 +#define ADC1_K 87 +#define ADC2_K 88 +#define FMC_K 89 +#define QSPI_K 90 +#define RNG1_K 91 +#define USBPHY_K 92 +#define STGEN_K 93 +#define SPDIF_K 94 +#define SPI1_K 95 +#define SPI2_K 96 +#define SPI3_K 97 +#define SPI4_K 98 +#define SPI5_K 99 +#define I2C1_K 100 +#define I2C2_K 101 +#define I2C3_K 102 +#define I2C4_K 103 +#define I2C5_K 104 +#define TIM2_K 105 +#define TIM3_K 106 +#define TIM4_K 107 +#define TIM5_K 108 +#define TIM6_K 109 +#define TIM7_K 110 +#define TIM12_K 111 +#define TIM13_K 112 +#define TIM14_K 113 +#define TIM1_K 114 +#define TIM8_K 115 +#define TIM15_K 116 +#define TIM16_K 117 +#define TIM17_K 118 +#define LPTIM1_K 119 +#define LPTIM2_K 120 +#define LPTIM3_K 121 +#define LPTIM4_K 122 +#define LPTIM5_K 123 +#define USART1_K 124 +#define USART2_K 125 +#define USART3_K 126 +#define UART4_K 127 +#define UART5_K 128 +#define USART6_K 129 +#define UART7_K 130 +#define UART8_K 131 +#define DFSDM_K 132 +#define FDCAN_K 133 +#define SAI1_K 134 +#define SAI2_K 135 +#define ADFSDM_K 136 +#define USBO_K 137 +#define LTDC_PX 138 +#define ETH1CK_K 139 +#define ETH1PTP_K 140 +#define ETH2CK_K 141 +#define ETH2PTP_K 142 +#define DCMIPP_K 143 +#define SAES_K 144 +#define DTS_K 145 + +/* DDR */ +#define DDRC1 146 +#define DDRC1LP 147 +#define DDRC2 148 +#define DDRC2LP 149 +#define DDRPHYC 150 +#define DDRPHYCLP 151 +#define DDRCAPB 152 +#define DDRCAPBLP 153 +#define AXIDCG 154 +#define DDRPHYCAPB 155 +#define DDRPHYCAPBLP 156 +#define DDRPERFM 157 + +#define ADC1 158 +#define ADC2 159 +#define SAI1 160 +#define SAI2 161 + +#define STM32MP1_LAST_CLK 162 + +/* SCMI clock identifiers */ +#define CK_SCMI0_HSE 0 +#define CK_SCMI0_HSI 1 +#define CK_SCMI0_CSI 2 +#define CK_SCMI0_LSE 3 +#define CK_SCMI0_LSI 4 +#define CK_SCMI0_HSE_DIV2 5 +#define CK_SCMI0_PLL2_Q 6 +#define CK_SCMI0_PLL2_R 7 +#define CK_SCMI0_PLL3_P 8 +#define CK_SCMI0_PLL3_Q 9 +#define CK_SCMI0_PLL3_R 10 +#define CK_SCMI0_PLL4_P 11 +#define CK_SCMI0_PLL4_Q 12 +#define CK_SCMI0_PLL4_R 13 +#define CK_SCMI0_MPU 14 +#define CK_SCMI0_AXI 15 +#define CK_SCMI0_MLAHB 16 +#define CK_SCMI0_CKPER 17 +#define CK_SCMI0_PCLK1 18 +#define CK_SCMI0_PCLK2 19 +#define CK_SCMI0_PCLK3 20 +#define CK_SCMI0_PCLK4 21 +#define CK_SCMI0_PCLK5 22 +#define CK_SCMI0_PCLK6 23 +#define CK_SCMI0_CKTIMG1 24 +#define CK_SCMI0_CKTIMG2 25 +#define CK_SCMI0_CKTIMG3 26 +#define CK_SCMI0_RTC 27 +#define CK_SCMI0_RTCAPB 28 +#define CK_SCMI0_BSEC 29 + +#endif /* _DT_BINDINGS_STM32MP13_CLKS_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h new file mode 100644 index 0000000..0d54ab9 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h @@ -0,0 +1,394 @@ +/* + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ +#define _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ + +#define CMD_DIV 0 +#define CMD_MUX 1 +#define CMD_CLK 2 +#define CMD_RESERVED1 3 + +#define CMD_SHIFT 26 +#define CMD_MASK 0xFC000000 +#define CMD_DATA_MASK 0x03FFFFFF + +#define DIV_ID_SHIFT 8 +#define DIV_ID_MASK 0x0000FF00 + +#define DIV_DIVN_SHIFT 0 +#define DIV_DIVN_MASK 0x000000FF + +#define MUX_ID_SHIFT 4 +#define MUX_ID_MASK 0x00000FF0 + +#define MUX_SEL_SHIFT 0 +#define MUX_SEL_MASK 0x0000000F + +#define CLK_ID_MASK GENMASK_32(19, 11) +#define CLK_ID_SHIFT 11 +#define CLK_ON_MASK 0x00000400 +#define CLK_ON_SHIFT 10 +#define CLK_DIV_MASK GENMASK_32(9, 4) +#define CLK_DIV_SHIFT 4 +#define CLK_SEL_MASK GENMASK_32(3, 0) +#define CLK_SEL_SHIFT 0 + +#define DIV_PLL1DIVP 0 +#define DIV_PLL2DIVP 1 +#define DIV_PLL2DIVQ 2 +#define DIV_PLL2DIVR 3 +#define DIV_PLL3DIVP 4 +#define DIV_PLL3DIVQ 5 +#define DIV_PLL3DIVR 6 +#define DIV_PLL4DIVP 7 +#define DIV_PLL4DIVQ 8 +#define DIV_PLL4DIVR 9 +#define DIV_MPU 10 +#define DIV_AXI 11 +#define DIV_MLAHB 12 +#define DIV_APB1 13 +#define DIV_APB2 14 +#define DIV_APB3 15 +#define DIV_APB4 16 +#define DIV_APB5 17 +#define DIV_APB6 18 +#define DIV_RTC 19 +#define DIV_MCO1 20 +#define DIV_MCO2 21 +#define DIV_HSI 22 +#define DIV_TRACE 23 +#define DIV_ETH1PTP 24 +#define DIV_ETH2PTP 25 +#define DIV_MAX 26 + +#define DIV(div_id, div) ((CMD_DIV << CMD_SHIFT) |\ + ((div_id) << DIV_ID_SHIFT |\ + (div))) + +#define CLKSRC(mux_id, sel) ((CMD_MUX << CMD_SHIFT) |\ + ((mux_id) << MUX_ID_SHIFT |\ + (sel))) + +/* MCO output is enable */ +#define MCO_SRC(mco_id, sel) ((CMD_CLK << CMD_SHIFT) |\ + (((mco_id) << CLK_ID_SHIFT) |\ + (sel)) | CLK_ON_MASK) + +#define MCO_DISABLED(mco_id) ((CMD_CLK << CMD_SHIFT) |\ + ((mco_id) << CLK_ID_SHIFT)) + +/* CLK output is enable */ +#define CLK_SRC(clk_id, sel) ((CMD_CLK << CMD_SHIFT) |\ + (((clk_id) << CLK_ID_SHIFT) |\ + (sel)) | CLK_ON_MASK) + +#define CLK_DISABLED(clk_id) ((CMD_CLK << CMD_SHIFT) |\ + ((clk_id) << CLK_ID_SHIFT)) + +#define MUX_MPU 0 +#define MUX_AXI 1 +#define MUX_MLAHB 2 +#define MUX_PLL12 3 +#define MUX_PLL3 4 +#define MUX_PLL4 5 +#define MUX_RTC 6 +#define MUX_MCO1 7 +#define MUX_MCO2 8 +#define MUX_CKPER 9 +#define MUX_KERNEL_BEGIN 10 +#define MUX_ADC1 10 +#define MUX_ADC2 11 +#define MUX_DCMIPP 12 +#define MUX_ETH1 13 +#define MUX_ETH2 14 +#define MUX_FDCAN 15 +#define MUX_FMC 16 +#define MUX_I2C12 17 +#define MUX_I2C3 18 +#define MUX_I2C4 19 +#define MUX_I2C5 20 +#define MUX_LPTIM1 21 +#define MUX_LPTIM2 22 +#define MUX_LPTIM3 23 +#define MUX_LPTIM45 24 +#define MUX_QSPI 25 +#define MUX_RNG1 26 +#define MUX_SAES 27 +#define MUX_SAI1 28 +#define MUX_SAI2 29 +#define MUX_SDMMC1 30 +#define MUX_SDMMC2 31 +#define MUX_SPDIF 32 +#define MUX_SPI1 33 +#define MUX_SPI23 34 +#define MUX_SPI4 35 +#define MUX_SPI5 36 +#define MUX_STGEN 37 +#define MUX_UART1 38 +#define MUX_UART2 39 +#define MUX_UART35 40 +#define MUX_UART4 41 +#define MUX_UART6 42 +#define MUX_UART78 43 +#define MUX_USBO 44 +#define MUX_USBPHY 45 +#define MUX_MAX 46 + +#define CLK_MPU_HSI CLKSRC(MUX_MPU, 0) +#define CLK_MPU_HSE CLKSRC(MUX_MPU, 1) +#define CLK_MPU_PLL1P CLKSRC(MUX_MPU, 2) +#define CLK_MPU_PLL1P_DIV CLKSRC(MUX_MPU, 3) + +#define CLK_AXI_HSI CLKSRC(MUX_AXI, 0) +#define CLK_AXI_HSE CLKSRC(MUX_AXI, 1) +#define CLK_AXI_PLL2P CLKSRC(MUX_AXI, 2) + +#define CLK_MLAHBS_HSI CLKSRC(MUX_MLAHB, 0) +#define CLK_MLAHBS_HSE CLKSRC(MUX_MLAHB, 1) +#define CLK_MLAHBS_CSI CLKSRC(MUX_MLAHB, 2) +#define CLK_MLAHBS_PLL3 CLKSRC(MUX_MLAHB, 3) + +#define CLK_PLL12_HSI CLKSRC(MUX_PLL12, 0) +#define CLK_PLL12_HSE CLKSRC(MUX_PLL12, 1) + +#define CLK_PLL3_HSI CLKSRC(MUX_PLL3, 0) +#define CLK_PLL3_HSE CLKSRC(MUX_PLL3, 1) +#define CLK_PLL3_CSI CLKSRC(MUX_PLL3, 2) + +#define CLK_PLL4_HSI CLKSRC(MUX_PLL4, 0) +#define CLK_PLL4_HSE CLKSRC(MUX_PLL4, 1) +#define CLK_PLL4_CSI CLKSRC(MUX_PLL4, 2) + +#define CLK_RTC_DISABLED CLK_DISABLED(RTC) +#define CLK_RTC_LSE CLK_SRC(RTC, 1) +#define CLK_RTC_LSI CLK_SRC(RTC, 2) +#define CLK_RTC_HSE CLK_SRC(RTC, 3) + +#define CLK_MCO1_HSI CLK_SRC(CK_MCO1, 0) +#define CLK_MCO1_HSE CLK_SRC(CK_MCO1, 1) +#define CLK_MCO1_CSI CLK_SRC(CK_MCO1, 2) +#define CLK_MCO1_LSI CLK_SRC(CK_MCO1, 3) +#define CLK_MCO1_LSE CLK_SRC(CK_MCO1, 4) +#define CLK_MCO1_DISABLED CLK_DISABLED(CK_MCO1) + +#define CLK_MCO2_MPU CLK_SRC(CK_MCO2, 0) +#define CLK_MCO2_AXI CLK_SRC(CK_MCO2, 1) +#define CLK_MCO2_MLAHB CLK_SRC(CK_MCO2, 2) +#define CLK_MCO2_PLL4 CLK_SRC(CK_MCO2, 3) +#define CLK_MCO2_HSE CLK_SRC(CK_MCO2, 4) +#define CLK_MCO2_HSI CLK_SRC(CK_MCO2, 5) +#define CLK_MCO2_DISABLED CLK_DISABLED(CK_MCO2) + +#define CLK_CKPER_HSI CLKSRC(MUX_CKPER, 0) +#define CLK_CKPER_CSI CLKSRC(MUX_CKPER, 1) +#define CLK_CKPER_HSE CLKSRC(MUX_CKPER, 2) +#define CLK_CKPER_DISABLED CLKSRC(MUX_CKPER, 3) + +#define CLK_I2C12_PCLK1 CLKSRC(MUX_I2C12, 0) +#define CLK_I2C12_PLL4R CLKSRC(MUX_I2C12, 1) +#define CLK_I2C12_HSI CLKSRC(MUX_I2C12, 2) +#define CLK_I2C12_CSI CLKSRC(MUX_I2C12, 3) + +#define CLK_I2C3_PCLK6 CLKSRC(MUX_I2C3, 0) +#define CLK_I2C3_PLL4R CLKSRC(MUX_I2C3, 1) +#define CLK_I2C3_HSI CLKSRC(MUX_I2C3, 2) +#define CLK_I2C3_CSI CLKSRC(MUX_I2C3, 3) + +#define CLK_I2C4_PCLK6 CLKSRC(MUX_I2C4, 0) +#define CLK_I2C4_PLL4R CLKSRC(MUX_I2C4, 1) +#define CLK_I2C4_HSI CLKSRC(MUX_I2C4, 2) +#define CLK_I2C4_CSI CLKSRC(MUX_I2C4, 3) + +#define CLK_I2C5_PCLK6 CLKSRC(MUX_I2C5, 0) +#define CLK_I2C5_PLL4R CLKSRC(MUX_I2C5, 1) +#define CLK_I2C5_HSI CLKSRC(MUX_I2C5, 2) +#define CLK_I2C5_CSI CLKSRC(MUX_I2C5, 3) + +#define CLK_SPI1_PLL4P CLKSRC(MUX_SPI1, 0) +#define CLK_SPI1_PLL3Q CLKSRC(MUX_SPI1, 1) +#define CLK_SPI1_I2SCKIN CLKSRC(MUX_SPI1, 2) +#define CLK_SPI1_CKPER CLKSRC(MUX_SPI1, 3) +#define CLK_SPI1_PLL3R CLKSRC(MUX_SPI1, 4) + +#define CLK_SPI23_PLL4P CLKSRC(MUX_SPI23, 0) +#define CLK_SPI23_PLL3Q CLKSRC(MUX_SPI23, 1) +#define CLK_SPI23_I2SCKIN CLKSRC(MUX_SPI23, 2) +#define CLK_SPI23_CKPER CLKSRC(MUX_SPI23, 3) +#define CLK_SPI23_PLL3R CLKSRC(MUX_SPI23, 4) + +#define CLK_SPI4_PCLK6 CLKSRC(MUX_SPI4, 0) +#define CLK_SPI4_PLL4Q CLKSRC(MUX_SPI4, 1) +#define CLK_SPI4_HSI CLKSRC(MUX_SPI4, 2) +#define CLK_SPI4_CSI CLKSRC(MUX_SPI4, 3) +#define CLK_SPI4_HSE CLKSRC(MUX_SPI4, 4) +#define CLK_SPI4_I2SCKIN CLKSRC(MUX_SPI4, 5) + +#define CLK_SPI5_PCLK6 CLKSRC(MUX_SPI5, 0) +#define CLK_SPI5_PLL4Q CLKSRC(MUX_SPI5, 1) +#define CLK_SPI5_HSI CLKSRC(MUX_SPI5, 2) +#define CLK_SPI5_CSI CLKSRC(MUX_SPI5, 3) +#define CLK_SPI5_HSE CLKSRC(MUX_SPI5, 4) + +#define CLK_UART1_PCLK6 CLKSRC(MUX_UART1, 0) +#define CLK_UART1_PLL3Q CLKSRC(MUX_UART1, 1) +#define CLK_UART1_HSI CLKSRC(MUX_UART1, 2) +#define CLK_UART1_CSI CLKSRC(MUX_UART1, 3) +#define CLK_UART1_PLL4Q CLKSRC(MUX_UART1, 4) +#define CLK_UART1_HSE CLKSRC(MUX_UART1, 5) + +#define CLK_UART2_PCLK6 CLKSRC(MUX_UART2, 0) +#define CLK_UART2_PLL3Q CLKSRC(MUX_UART2, 1) +#define CLK_UART2_HSI CLKSRC(MUX_UART2, 2) +#define CLK_UART2_CSI CLKSRC(MUX_UART2, 3) +#define CLK_UART2_PLL4Q CLKSRC(MUX_UART2, 4) +#define CLK_UART2_HSE CLKSRC(MUX_UART2, 5) + +#define CLK_UART35_PCLK1 CLKSRC(MUX_UART35, 0) +#define CLK_UART35_PLL4Q CLKSRC(MUX_UART35, 1) +#define CLK_UART35_HSI CLKSRC(MUX_UART35, 2) +#define CLK_UART35_CSI CLKSRC(MUX_UART35, 3) +#define CLK_UART35_HSE CLKSRC(MUX_UART35, 4) + +#define CLK_UART4_PCLK1 CLKSRC(MUX_UART4, 0) +#define CLK_UART4_PLL4Q CLKSRC(MUX_UART4, 1) +#define CLK_UART4_HSI CLKSRC(MUX_UART4, 2) +#define CLK_UART4_CSI CLKSRC(MUX_UART4, 3) +#define CLK_UART4_HSE CLKSRC(MUX_UART4, 4) + +#define CLK_UART6_PCLK2 CLKSRC(MUX_UART6, 0) +#define CLK_UART6_PLL4Q CLKSRC(MUX_UART6, 1) +#define CLK_UART6_HSI CLKSRC(MUX_UART6, 2) +#define CLK_UART6_CSI CLKSRC(MUX_UART6, 3) +#define CLK_UART6_HSE CLKSRC(MUX_UART6, 4) + +#define CLK_UART78_PCLK1 CLKSRC(MUX_UART78, 0) +#define CLK_UART78_PLL4Q CLKSRC(MUX_UART78, 1) +#define CLK_UART78_HSI CLKSRC(MUX_UART78, 2) +#define CLK_UART78_CSI CLKSRC(MUX_UART78, 3) +#define CLK_UART78_HSE CLKSRC(MUX_UART78, 4) + +#define CLK_LPTIM1_PCLK1 CLKSRC(MUX_LPTIM1, 0) +#define CLK_LPTIM1_PLL4P CLKSRC(MUX_LPTIM1, 1) +#define CLK_LPTIM1_PLL3Q CLKSRC(MUX_LPTIM1, 2) +#define CLK_LPTIM1_LSE CLKSRC(MUX_LPTIM1, 3) +#define CLK_LPTIM1_LSI CLKSRC(MUX_LPTIM1, 4) +#define CLK_LPTIM1_CKPER CLKSRC(MUX_LPTIM1, 5) + +#define CLK_LPTIM2_PCLK3 CLKSRC(MUX_LPTIM2, 0) +#define CLK_LPTIM2_PLL4Q CLKSRC(MUX_LPTIM2, 1) +#define CLK_LPTIM2_CKPER CLKSRC(MUX_LPTIM2, 2) +#define CLK_LPTIM2_LSE CLKSRC(MUX_LPTIM2, 3) +#define CLK_LPTIM2_LSI CLKSRC(MUX_LPTIM2, 4) + +#define CLK_LPTIM3_PCLK3 CLKSRC(MUX_LPTIM3, 0) +#define CLK_LPTIM3_PLL4Q CLKSRC(MUX_LPTIM3, 1) +#define CLK_LPTIM3_CKPER CLKSRC(MUX_LPTIM3, 2) +#define CLK_LPTIM3_LSE CLKSRC(MUX_LPTIM3, 3) +#define CLK_LPTIM3_LSI CLKSRC(MUX_LPTIM3, 4) + +#define CLK_LPTIM45_PCLK3 CLKSRC(MUX_LPTIM45, 0) +#define CLK_LPTIM45_PLL4P CLKSRC(MUX_LPTIM45, 1) +#define CLK_LPTIM45_PLL3Q CLKSRC(MUX_LPTIM45, 2) +#define CLK_LPTIM45_LSE CLKSRC(MUX_LPTIM45, 3) +#define CLK_LPTIM45_LSI CLKSRC(MUX_LPTIM45, 4) +#define CLK_LPTIM45_CKPER CLKSRC(MUX_LPTIM45, 5) + +#define CLK_SAI1_PLL4Q CLKSRC(MUX_SAI1, 0) +#define CLK_SAI1_PLL3Q CLKSRC(MUX_SAI1, 1) +#define CLK_SAI1_I2SCKIN CLKSRC(MUX_SAI1, 2) +#define CLK_SAI1_CKPER CLKSRC(MUX_SAI1, 3) +#define CLK_SAI1_PLL3R CLKSRC(MUX_SAI1, 4) + +#define CLK_SAI2_PLL4Q CLKSRC(MUX_SAI2, 0) +#define CLK_SAI2_PLL3Q CLKSRC(MUX_SAI2, 1) +#define CLK_SAI2_I2SCKIN CLKSRC(MUX_SAI2, 2) +#define CLK_SAI2_CKPER CLKSRC(MUX_SAI2, 3) +#define CLK_SAI2_SPDIF CLKSRC(MUX_SAI2, 4) +#define CLK_SAI2_PLL3R CLKSRC(MUX_SAI2, 5) + +#define CLK_FDCAN_HSE CLKSRC(MUX_FDCAN, 0) +#define CLK_FDCAN_PLL3Q CLKSRC(MUX_FDCAN, 1) +#define CLK_FDCAN_PLL4Q CLKSRC(MUX_FDCAN, 2) +#define CLK_FDCAN_PLL4R CLKSRC(MUX_FDCAN, 3) + +#define CLK_SPDIF_PLL4P CLKSRC(MUX_SPDIF, 0) +#define CLK_SPDIF_PLL3Q CLKSRC(MUX_SPDIF, 1) +#define CLK_SPDIF_HSI CLKSRC(MUX_SPDIF, 2) + +#define CLK_ADC1_PLL4R CLKSRC(MUX_ADC1, 0) +#define CLK_ADC1_CKPER CLKSRC(MUX_ADC1, 1) +#define CLK_ADC1_PLL3Q CLKSRC(MUX_ADC1, 2) + +#define CLK_ADC2_PLL4R CLKSRC(MUX_ADC2, 0) +#define CLK_ADC2_CKPER CLKSRC(MUX_ADC2, 1) +#define CLK_ADC2_PLL3Q CLKSRC(MUX_ADC2, 2) + +#define CLK_SDMMC1_HCLK6 CLKSRC(MUX_SDMMC1, 0) +#define CLK_SDMMC1_PLL3R CLKSRC(MUX_SDMMC1, 1) +#define CLK_SDMMC1_PLL4P CLKSRC(MUX_SDMMC1, 2) +#define CLK_SDMMC1_HSI CLKSRC(MUX_SDMMC1, 3) + +#define CLK_SDMMC2_HCLK6 CLKSRC(MUX_SDMMC2, 0) +#define CLK_SDMMC2_PLL3R CLKSRC(MUX_SDMMC2, 1) +#define CLK_SDMMC2_PLL4P CLKSRC(MUX_SDMMC2, 2) +#define CLK_SDMMC2_HSI CLKSRC(MUX_SDMMC2, 3) + +#define CLK_ETH1_PLL4P CLKSRC(MUX_ETH1, 0) +#define CLK_ETH1_PLL3Q CLKSRC(MUX_ETH1, 1) + +#define CLK_ETH2_PLL4P CLKSRC(MUX_ETH2, 0) +#define CLK_ETH2_PLL3Q CLKSRC(MUX_ETH2, 1) + +#define CLK_USBPHY_HSE CLKSRC(MUX_USBPHY, 0) +#define CLK_USBPHY_PLL4R CLKSRC(MUX_USBPHY, 1) +#define CLK_USBPHY_HSE_DIV2 CLKSRC(MUX_USBPHY, 2) + +#define CLK_USBO_PLL4R CLKSRC(MUX_USBO, 0) +#define CLK_USBO_USBPHY CLKSRC(MUX_USBO, 1) + +#define CLK_QSPI_ACLK CLKSRC(MUX_QSPI, 0) +#define CLK_QSPI_PLL3R CLKSRC(MUX_QSPI, 1) +#define CLK_QSPI_PLL4P CLKSRC(MUX_QSPI, 2) +#define CLK_QSPI_CKPER CLKSRC(MUX_QSPI, 3) + +#define CLK_FMC_ACLK CLKSRC(MUX_FMC, 0) +#define CLK_FMC_PLL3R CLKSRC(MUX_FMC, 1) +#define CLK_FMC_PLL4P CLKSRC(MUX_FMC, 2) +#define CLK_FMC_CKPER CLKSRC(MUX_FMC, 3) + +#define CLK_RNG1_CSI CLKSRC(MUX_RNG1, 0) +#define CLK_RNG1_PLL4R CLKSRC(MUX_RNG1, 1) +/* WARNING: POSITION 2 OF RNG1 MUX IS RESERVED */ +#define CLK_RNG1_LSI CLKSRC(MUX_RNG1, 3) + +#define CLK_STGEN_HSI CLKSRC(MUX_STGEN, 0) +#define CLK_STGEN_HSE CLKSRC(MUX_STGEN, 1) + +#define CLK_DCMIPP_ACLK CLKSRC(MUX_DCMIPP, 0) +#define CLK_DCMIPP_PLL2Q CLKSRC(MUX_DCMIPP, 1) +#define CLK_DCMIPP_PLL4P CLKSRC(MUX_DCMIPP, 2) +#define CLK_DCMIPP_CKPER CLKSRC(MUX_DCMIPP, 3) + +#define CLK_SAES_AXI CLKSRC(MUX_SAES, 0) +#define CLK_SAES_CKPER CLKSRC(MUX_SAES, 1) +#define CLK_SAES_PLL4R CLKSRC(MUX_SAES, 2) +#define CLK_SAES_LSI CLKSRC(MUX_SAES, 3) + +/* PLL output is enable when x=1, with x=p,q or r */ +#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) + +/* define for st,pll /csg */ +#define SSCG_MODE_CENTER_SPREAD 0 +#define SSCG_MODE_DOWN_SPREAD 1 + +/* define for st,drive */ +#define LSEDRV_LOWEST 0 +#define LSEDRV_MEDIUM_LOW 1 +#define LSEDRV_MEDIUM_HIGH 2 +#define LSEDRV_HIGHEST 3 + +#endif /* _DT_BINDINGS_CLOCK_STM32MP13_CLKSRC_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h new file mode 100644 index 0000000..bef1368 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h @@ -0,0 +1,278 @@ +/* SPDX-License-Identifier: GPL-2.0+ or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP1_CLKS_H_ +#define _DT_BINDINGS_STM32MP1_CLKS_H_ + +/* OSCILLATOR clocks */ +#define CK_HSE 0 +#define CK_CSI 1 +#define CK_LSI 2 +#define CK_LSE 3 +#define CK_HSI 4 +#define CK_HSE_DIV2 5 + +/* Bus clocks */ +#define TIM2 6 +#define TIM3 7 +#define TIM4 8 +#define TIM5 9 +#define TIM6 10 +#define TIM7 11 +#define TIM12 12 +#define TIM13 13 +#define TIM14 14 +#define LPTIM1 15 +#define SPI2 16 +#define SPI3 17 +#define USART2 18 +#define USART3 19 +#define UART4 20 +#define UART5 21 +#define UART7 22 +#define UART8 23 +#define I2C1 24 +#define I2C2 25 +#define I2C3 26 +#define I2C5 27 +#define SPDIF 28 +#define CEC 29 +#define DAC12 30 +#define MDIO 31 +#define TIM1 32 +#define TIM8 33 +#define TIM15 34 +#define TIM16 35 +#define TIM17 36 +#define SPI1 37 +#define SPI4 38 +#define SPI5 39 +#define USART6 40 +#define SAI1 41 +#define SAI2 42 +#define SAI3 43 +#define DFSDM 44 +#define FDCAN 45 +#define LPTIM2 46 +#define LPTIM3 47 +#define LPTIM4 48 +#define LPTIM5 49 +#define SAI4 50 +#define SYSCFG 51 +#define VREF 52 +#define TMPSENS 53 +#define PMBCTRL 54 +#define HDP 55 +#define LTDC 56 +#define DSI 57 +#define IWDG2 58 +#define USBPHY 59 +#define STGENRO 60 +#define SPI6 61 +#define I2C4 62 +#define I2C6 63 +#define USART1 64 +#define RTCAPB 65 +#define TZC1 66 +#define TZPC 67 +#define IWDG1 68 +#define BSEC 69 +#define STGEN 70 +#define DMA1 71 +#define DMA2 72 +#define DMAMUX 73 +#define ADC12 74 +#define USBO 75 +#define SDMMC3 76 +#define DCMI 77 +#define CRYP2 78 +#define HASH2 79 +#define RNG2 80 +#define CRC2 81 +#define HSEM 82 +#define IPCC 83 +#define GPIOA 84 +#define GPIOB 85 +#define GPIOC 86 +#define GPIOD 87 +#define GPIOE 88 +#define GPIOF 89 +#define GPIOG 90 +#define GPIOH 91 +#define GPIOI 92 +#define GPIOJ 93 +#define GPIOK 94 +#define GPIOZ 95 +#define CRYP1 96 +#define HASH1 97 +#define RNG1 98 +#define BKPSRAM 99 +#define MDMA 100 +#define GPU 101 +#define ETHCK 102 +#define ETHTX 103 +#define ETHRX 104 +#define ETHMAC 105 +#define FMC 106 +#define QSPI 107 +#define SDMMC1 108 +#define SDMMC2 109 +#define CRC1 110 +#define USBH 111 +#define ETHSTP 112 +#define TZC2 113 + +/* Kernel clocks */ +#define SDMMC1_K 118 +#define SDMMC2_K 119 +#define SDMMC3_K 120 +#define FMC_K 121 +#define QSPI_K 122 +#define ETHCK_K 123 +#define RNG1_K 124 +#define RNG2_K 125 +#define GPU_K 126 +#define USBPHY_K 127 +#define STGEN_K 128 +#define SPDIF_K 129 +#define SPI1_K 130 +#define SPI2_K 131 +#define SPI3_K 132 +#define SPI4_K 133 +#define SPI5_K 134 +#define SPI6_K 135 +#define CEC_K 136 +#define I2C1_K 137 +#define I2C2_K 138 +#define I2C3_K 139 +#define I2C4_K 140 +#define I2C5_K 141 +#define I2C6_K 142 +#define LPTIM1_K 143 +#define LPTIM2_K 144 +#define LPTIM3_K 145 +#define LPTIM4_K 146 +#define LPTIM5_K 147 +#define USART1_K 148 +#define USART2_K 149 +#define USART3_K 150 +#define UART4_K 151 +#define UART5_K 152 +#define USART6_K 153 +#define UART7_K 154 +#define UART8_K 155 +#define DFSDM_K 156 +#define FDCAN_K 157 +#define SAI1_K 158 +#define SAI2_K 159 +#define SAI3_K 160 +#define SAI4_K 161 +#define ADC12_K 162 +#define DSI_K 163 +#define DSI_PX 164 +#define ADFSDM_K 165 +#define USBO_K 166 +#define LTDC_PX 167 +#define DAC12_K 168 +#define ETHPTP_K 169 + +/* PLL */ +#define PLL1 176 +#define PLL2 177 +#define PLL3 178 +#define PLL4 179 + +/* ODF */ +#define PLL1_P 180 +#define PLL1_Q 181 +#define PLL1_R 182 +#define PLL2_P 183 +#define PLL2_Q 184 +#define PLL2_R 185 +#define PLL3_P 186 +#define PLL3_Q 187 +#define PLL3_R 188 +#define PLL4_P 189 +#define PLL4_Q 190 +#define PLL4_R 191 + +/* AUX */ +#define RTC 192 + +/* MCLK */ +#define CK_PER 193 +#define CK_MPU 194 +#define CK_AXI 195 +#define CK_MCU 196 + +/* Time base */ +#define TIM2_K 197 +#define TIM3_K 198 +#define TIM4_K 199 +#define TIM5_K 200 +#define TIM6_K 201 +#define TIM7_K 202 +#define TIM12_K 203 +#define TIM13_K 204 +#define TIM14_K 205 +#define TIM1_K 206 +#define TIM8_K 207 +#define TIM15_K 208 +#define TIM16_K 209 +#define TIM17_K 210 + +/* MCO clocks */ +#define CK_MCO1 211 +#define CK_MCO2 212 + +/* TRACE & DEBUG clocks */ +#define CK_DBG 214 +#define CK_TRACE 215 + +/* DDR */ +#define DDRC1 220 +#define DDRC1LP 221 +#define DDRC2 222 +#define DDRC2LP 223 +#define DDRPHYC 224 +#define DDRPHYCLP 225 +#define DDRCAPB 226 +#define DDRCAPBLP 227 +#define AXIDCG 228 +#define DDRPHYCAPB 229 +#define DDRPHYCAPBLP 230 +#define DDRPERFM 231 + +#define STM32MP1_LAST_CLK 232 + +/* SCMI clock identifiers */ +#define CK_SCMI0_HSE 0 +#define CK_SCMI0_HSI 1 +#define CK_SCMI0_CSI 2 +#define CK_SCMI0_LSE 3 +#define CK_SCMI0_LSI 4 +#define CK_SCMI0_PLL2_Q 5 +#define CK_SCMI0_PLL2_R 6 +#define CK_SCMI0_MPU 7 +#define CK_SCMI0_AXI 8 +#define CK_SCMI0_BSEC 9 +#define CK_SCMI0_CRYP1 10 +#define CK_SCMI0_GPIOZ 11 +#define CK_SCMI0_HASH1 12 +#define CK_SCMI0_I2C4 13 +#define CK_SCMI0_I2C6 14 +#define CK_SCMI0_IWDG1 15 +#define CK_SCMI0_RNG1 16 +#define CK_SCMI0_RTC 17 +#define CK_SCMI0_RTCAPB 18 +#define CK_SCMI0_SPI6 19 +#define CK_SCMI0_USART1 20 + +#define CK_SCMI1_PLL3_Q 0 +#define CK_SCMI1_PLL3_R 1 +#define CK_SCMI1_MCU 2 + +#endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h new file mode 100644 index 0000000..3a3792d --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h @@ -0,0 +1,282 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2017-2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ +#define _DT_BINDINGS_CLOCK_STM32MP15_CLKSRC_H_ + +/* PLL output is enable when x=1, with x=p,q or r */ +#define PQR(p, q, r) (((p) & 1) | (((q) & 1) << 1) | (((r) & 1) << 2)) + +/* st,clksrc: mandatory clock source */ +#define CLK_MPU_HSI 0x00000200 +#define CLK_MPU_HSE 0x00000201 +#define CLK_MPU_PLL1P 0x00000202 +#define CLK_MPU_PLL1P_DIV 0x00000203 + +#define CLK_AXI_HSI 0x00000240 +#define CLK_AXI_HSE 0x00000241 +#define CLK_AXI_PLL2P 0x00000242 + +#define CLK_MCU_HSI 0x00000480 +#define CLK_MCU_HSE 0x00000481 +#define CLK_MCU_CSI 0x00000482 +#define CLK_MCU_PLL3P 0x00000483 + +#define CLK_PLL12_HSI 0x00000280 +#define CLK_PLL12_HSE 0x00000281 + +#define CLK_PLL3_HSI 0x00008200 +#define CLK_PLL3_HSE 0x00008201 +#define CLK_PLL3_CSI 0x00008202 + +#define CLK_PLL4_HSI 0x00008240 +#define CLK_PLL4_HSE 0x00008241 +#define CLK_PLL4_CSI 0x00008242 +#define CLK_PLL4_I2SCKIN 0x00008243 + +#define CLK_RTC_DISABLED 0x00001400 +#define CLK_RTC_LSE 0x00001401 +#define CLK_RTC_LSI 0x00001402 +#define CLK_RTC_HSE 0x00001403 + +#define CLK_MCO1_HSI 0x00008000 +#define CLK_MCO1_HSE 0x00008001 +#define CLK_MCO1_CSI 0x00008002 +#define CLK_MCO1_LSI 0x00008003 +#define CLK_MCO1_LSE 0x00008004 +#define CLK_MCO1_DISABLED 0x0000800F + +#define CLK_MCO2_MPU 0x00008040 +#define CLK_MCO2_AXI 0x00008041 +#define CLK_MCO2_MCU 0x00008042 +#define CLK_MCO2_PLL4P 0x00008043 +#define CLK_MCO2_HSE 0x00008044 +#define CLK_MCO2_HSI 0x00008045 +#define CLK_MCO2_DISABLED 0x0000804F + +/* st,pkcs: peripheral kernel clock source */ + +#define CLK_I2C12_PCLK1 0x00008C00 +#define CLK_I2C12_PLL4R 0x00008C01 +#define CLK_I2C12_HSI 0x00008C02 +#define CLK_I2C12_CSI 0x00008C03 +#define CLK_I2C12_DISABLED 0x00008C07 + +#define CLK_I2C35_PCLK1 0x00008C40 +#define CLK_I2C35_PLL4R 0x00008C41 +#define CLK_I2C35_HSI 0x00008C42 +#define CLK_I2C35_CSI 0x00008C43 +#define CLK_I2C35_DISABLED 0x00008C47 + +#define CLK_I2C46_PCLK5 0x00000C00 +#define CLK_I2C46_PLL3Q 0x00000C01 +#define CLK_I2C46_HSI 0x00000C02 +#define CLK_I2C46_CSI 0x00000C03 +#define CLK_I2C46_DISABLED 0x00000C07 + +#define CLK_SAI1_PLL4Q 0x00008C80 +#define CLK_SAI1_PLL3Q 0x00008C81 +#define CLK_SAI1_I2SCKIN 0x00008C82 +#define CLK_SAI1_CKPER 0x00008C83 +#define CLK_SAI1_PLL3R 0x00008C84 +#define CLK_SAI1_DISABLED 0x00008C87 + +#define CLK_SAI2_PLL4Q 0x00008CC0 +#define CLK_SAI2_PLL3Q 0x00008CC1 +#define CLK_SAI2_I2SCKIN 0x00008CC2 +#define CLK_SAI2_CKPER 0x00008CC3 +#define CLK_SAI2_SPDIF 0x00008CC4 +#define CLK_SAI2_PLL3R 0x00008CC5 +#define CLK_SAI2_DISABLED 0x00008CC7 + +#define CLK_SAI3_PLL4Q 0x00008D00 +#define CLK_SAI3_PLL3Q 0x00008D01 +#define CLK_SAI3_I2SCKIN 0x00008D02 +#define CLK_SAI3_CKPER 0x00008D03 +#define CLK_SAI3_PLL3R 0x00008D04 +#define CLK_SAI3_DISABLED 0x00008D07 + +#define CLK_SAI4_PLL4Q 0x00008D40 +#define CLK_SAI4_PLL3Q 0x00008D41 +#define CLK_SAI4_I2SCKIN 0x00008D42 +#define CLK_SAI4_CKPER 0x00008D43 +#define CLK_SAI4_PLL3R 0x00008D44 +#define CLK_SAI4_DISABLED 0x00008D47 + +#define CLK_SPI2S1_PLL4P 0x00008D80 +#define CLK_SPI2S1_PLL3Q 0x00008D81 +#define CLK_SPI2S1_I2SCKIN 0x00008D82 +#define CLK_SPI2S1_CKPER 0x00008D83 +#define CLK_SPI2S1_PLL3R 0x00008D84 +#define CLK_SPI2S1_DISABLED 0x00008D87 + +#define CLK_SPI2S23_PLL4P 0x00008DC0 +#define CLK_SPI2S23_PLL3Q 0x00008DC1 +#define CLK_SPI2S23_I2SCKIN 0x00008DC2 +#define CLK_SPI2S23_CKPER 0x00008DC3 +#define CLK_SPI2S23_PLL3R 0x00008DC4 +#define CLK_SPI2S23_DISABLED 0x00008DC7 + +#define CLK_SPI45_PCLK2 0x00008E00 +#define CLK_SPI45_PLL4Q 0x00008E01 +#define CLK_SPI45_HSI 0x00008E02 +#define CLK_SPI45_CSI 0x00008E03 +#define CLK_SPI45_HSE 0x00008E04 +#define CLK_SPI45_DISABLED 0x00008E07 + +#define CLK_SPI6_PCLK5 0x00000C40 +#define CLK_SPI6_PLL4Q 0x00000C41 +#define CLK_SPI6_HSI 0x00000C42 +#define CLK_SPI6_CSI 0x00000C43 +#define CLK_SPI6_HSE 0x00000C44 +#define CLK_SPI6_PLL3Q 0x00000C45 +#define CLK_SPI6_DISABLED 0x00000C47 + +#define CLK_UART6_PCLK2 0x00008E40 +#define CLK_UART6_PLL4Q 0x00008E41 +#define CLK_UART6_HSI 0x00008E42 +#define CLK_UART6_CSI 0x00008E43 +#define CLK_UART6_HSE 0x00008E44 +#define CLK_UART6_DISABLED 0x00008E47 + +#define CLK_UART24_PCLK1 0x00008E80 +#define CLK_UART24_PLL4Q 0x00008E81 +#define CLK_UART24_HSI 0x00008E82 +#define CLK_UART24_CSI 0x00008E83 +#define CLK_UART24_HSE 0x00008E84 +#define CLK_UART24_DISABLED 0x00008E87 + +#define CLK_UART35_PCLK1 0x00008EC0 +#define CLK_UART35_PLL4Q 0x00008EC1 +#define CLK_UART35_HSI 0x00008EC2 +#define CLK_UART35_CSI 0x00008EC3 +#define CLK_UART35_HSE 0x00008EC4 +#define CLK_UART35_DISABLED 0x00008EC7 + +#define CLK_UART78_PCLK1 0x00008F00 +#define CLK_UART78_PLL4Q 0x00008F01 +#define CLK_UART78_HSI 0x00008F02 +#define CLK_UART78_CSI 0x00008F03 +#define CLK_UART78_HSE 0x00008F04 +#define CLK_UART78_DISABLED 0x00008F07 + +#define CLK_UART1_PCLK5 0x00000C80 +#define CLK_UART1_PLL3Q 0x00000C81 +#define CLK_UART1_HSI 0x00000C82 +#define CLK_UART1_CSI 0x00000C83 +#define CLK_UART1_PLL4Q 0x00000C84 +#define CLK_UART1_HSE 0x00000C85 +#define CLK_UART1_DISABLED 0x00000C87 + +#define CLK_SDMMC12_HCLK6 0x00008F40 +#define CLK_SDMMC12_PLL3R 0x00008F41 +#define CLK_SDMMC12_PLL4P 0x00008F42 +#define CLK_SDMMC12_HSI 0x00008F43 +#define CLK_SDMMC12_DISABLED 0x00008F47 + +#define CLK_SDMMC3_HCLK2 0x00008F80 +#define CLK_SDMMC3_PLL3R 0x00008F81 +#define CLK_SDMMC3_PLL4P 0x00008F82 +#define CLK_SDMMC3_HSI 0x00008F83 +#define CLK_SDMMC3_DISABLED 0x00008F87 + +#define CLK_ETH_PLL4P 0x00008FC0 +#define CLK_ETH_PLL3Q 0x00008FC1 +#define CLK_ETH_DISABLED 0x00008FC3 + +#define CLK_QSPI_ACLK 0x00009000 +#define CLK_QSPI_PLL3R 0x00009001 +#define CLK_QSPI_PLL4P 0x00009002 +#define CLK_QSPI_CKPER 0x00009003 + +#define CLK_FMC_ACLK 0x00009040 +#define CLK_FMC_PLL3R 0x00009041 +#define CLK_FMC_PLL4P 0x00009042 +#define CLK_FMC_CKPER 0x00009043 + +#define CLK_FDCAN_HSE 0x000090C0 +#define CLK_FDCAN_PLL3Q 0x000090C1 +#define CLK_FDCAN_PLL4Q 0x000090C2 +#define CLK_FDCAN_PLL4R 0x000090C3 + +#define CLK_SPDIF_PLL4P 0x00009140 +#define CLK_SPDIF_PLL3Q 0x00009141 +#define CLK_SPDIF_HSI 0x00009142 +#define CLK_SPDIF_DISABLED 0x00009143 + +#define CLK_CEC_LSE 0x00009180 +#define CLK_CEC_LSI 0x00009181 +#define CLK_CEC_CSI_DIV122 0x00009182 +#define CLK_CEC_DISABLED 0x00009183 + +#define CLK_USBPHY_HSE 0x000091C0 +#define CLK_USBPHY_PLL4R 0x000091C1 +#define CLK_USBPHY_HSE_DIV2 0x000091C2 +#define CLK_USBPHY_DISABLED 0x000091C3 + +#define CLK_USBO_PLL4R 0x800091C0 +#define CLK_USBO_USBPHY 0x800091C1 + +#define CLK_RNG1_CSI 0x00000CC0 +#define CLK_RNG1_PLL4R 0x00000CC1 +#define CLK_RNG1_LSE 0x00000CC2 +#define CLK_RNG1_LSI 0x00000CC3 + +#define CLK_RNG2_CSI 0x00009200 +#define CLK_RNG2_PLL4R 0x00009201 +#define CLK_RNG2_LSE 0x00009202 +#define CLK_RNG2_LSI 0x00009203 + +#define CLK_CKPER_HSI 0x00000D00 +#define CLK_CKPER_CSI 0x00000D01 +#define CLK_CKPER_HSE 0x00000D02 +#define CLK_CKPER_DISABLED 0x00000D03 + +#define CLK_STGEN_HSI 0x00000D40 +#define CLK_STGEN_HSE 0x00000D41 +#define CLK_STGEN_DISABLED 0x00000D43 + +#define CLK_DSI_DSIPLL 0x00009240 +#define CLK_DSI_PLL4P 0x00009241 + +#define CLK_ADC_PLL4R 0x00009280 +#define CLK_ADC_CKPER 0x00009281 +#define CLK_ADC_PLL3Q 0x00009282 +#define CLK_ADC_DISABLED 0x00009283 + +#define CLK_LPTIM45_PCLK3 0x000092C0 +#define CLK_LPTIM45_PLL4P 0x000092C1 +#define CLK_LPTIM45_PLL3Q 0x000092C2 +#define CLK_LPTIM45_LSE 0x000092C3 +#define CLK_LPTIM45_LSI 0x000092C4 +#define CLK_LPTIM45_CKPER 0x000092C5 +#define CLK_LPTIM45_DISABLED 0x000092C7 + +#define CLK_LPTIM23_PCLK3 0x00009300 +#define CLK_LPTIM23_PLL4Q 0x00009301 +#define CLK_LPTIM23_CKPER 0x00009302 +#define CLK_LPTIM23_LSE 0x00009303 +#define CLK_LPTIM23_LSI 0x00009304 +#define CLK_LPTIM23_DISABLED 0x00009307 + +#define CLK_LPTIM1_PCLK1 0x00009340 +#define CLK_LPTIM1_PLL4P 0x00009341 +#define CLK_LPTIM1_PLL3Q 0x00009342 +#define CLK_LPTIM1_LSE 0x00009343 +#define CLK_LPTIM1_LSI 0x00009344 +#define CLK_LPTIM1_CKPER 0x00009345 +#define CLK_LPTIM1_DISABLED 0x00009347 + +/* define for st,pll /csg */ +#define SSCG_MODE_CENTER_SPREAD 0 +#define SSCG_MODE_DOWN_SPREAD 1 + +/* define for st,drive */ +#define LSEDRV_LOWEST 0 +#define LSEDRV_MEDIUM_LOW 1 +#define LSEDRV_MEDIUM_HIGH 2 +#define LSEDRV_HIGHEST 3 + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h new file mode 100644 index 0000000..803cd9c --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2019-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * This header provides constants for the ARM GIC. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_ARM_GIC_H + +#include + +/* interrupt specifier cell 0 */ + +#define GIC_SPI 0 +#define GIC_PPI 1 + +/* + * Interrupt specifier cell 2. + * The flags in irq.h are valid, plus those below. + */ +#define GIC_CPU_MASK_RAW(x) ((x) << 8) +#define GIC_CPU_MASK_SIMPLE(num) GIC_CPU_MASK_RAW((1 << (num)) - 1) + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h new file mode 100644 index 0000000..94e7f95 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: MIT + * + * This header provides constants for most IRQ bindings. + * + * Most IRQ bindings include a flags cell as part of the IRQ specifier. + * In most cases, the format of the flags cell uses the standard values + * defined in this header. + */ + +#ifndef _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H +#define _DT_BINDINGS_INTERRUPT_CONTROLLER_IRQ_H + +#define IRQ_TYPE_NONE 0 +#define IRQ_TYPE_EDGE_RISING 1 +#define IRQ_TYPE_EDGE_FALLING 2 +#define IRQ_TYPE_EDGE_BOTH (IRQ_TYPE_EDGE_FALLING | IRQ_TYPE_EDGE_RISING) +#define IRQ_TYPE_LEVEL_HIGH 4 +#define IRQ_TYPE_LEVEL_LOW 8 + +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h b/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h new file mode 100644 index 0000000..1bc2c40 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h @@ -0,0 +1,42 @@ +/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */ +/* + * Copyright (C) STMicroelectronics 2017 - All Rights Reserved + * Author: Torgue Alexandre for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32_PINFUNC_H +#define _DT_BINDINGS_STM32_PINFUNC_H + +/* define PIN modes */ +#define GPIO 0x0 +#define AF0 0x1 +#define AF1 0x2 +#define AF2 0x3 +#define AF3 0x4 +#define AF4 0x5 +#define AF5 0x6 +#define AF6 0x7 +#define AF7 0x8 +#define AF8 0x9 +#define AF9 0xa +#define AF10 0xb +#define AF11 0xc +#define AF12 0xd +#define AF13 0xe +#define AF14 0xf +#define AF15 0x10 +#define ANALOG 0x11 +#define RSVD 0x12 + +/* define Pins number*/ +#define PIN_NO(port, line) (((port) - 'A') * 0x10 + (line)) + +#define STM32_PINMUX(port, line, mode) (((PIN_NO(port, line)) << 8) | (mode)) + +/* package information */ +#define STM32MP_PKG_AA 0x1 +#define STM32MP_PKG_AB 0x2 +#define STM32MP_PKG_AC 0x4 +#define STM32MP_PKG_AD 0x8 + +#endif /* _DT_BINDINGS_STM32_PINFUNC_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h new file mode 100644 index 0000000..d40b1a2 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h @@ -0,0 +1,11 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2020-2022, STMicroelectronics - All Rights Reserved + */ + +#if STM32MP13 +#include "stm32mp13-resets.h" +#endif +#if STM32MP15 +#include "stm32mp15-resets.h" +#endif diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h new file mode 100644 index 0000000..8a0f80e --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP13_RESET_H_ +#define _DT_BINDINGS_STM32MP13_RESET_H_ + +#define TIM2_R 13568 +#define TIM3_R 13569 +#define TIM4_R 13570 +#define TIM5_R 13571 +#define TIM6_R 13572 +#define TIM7_R 13573 +#define LPTIM1_R 13577 +#define SPI2_R 13579 +#define SPI3_R 13580 +#define USART3_R 13583 +#define UART4_R 13584 +#define UART5_R 13585 +#define UART7_R 13586 +#define UART8_R 13587 +#define I2C1_R 13589 +#define I2C2_R 13590 +#define SPDIF_R 13594 +#define TIM1_R 13632 +#define TIM8_R 13633 +#define SPI1_R 13640 +#define USART6_R 13645 +#define SAI1_R 13648 +#define SAI2_R 13649 +#define DFSDM_R 13652 +#define FDCAN_R 13656 +#define LPTIM2_R 13696 +#define LPTIM3_R 13697 +#define LPTIM4_R 13698 +#define LPTIM5_R 13699 +#define SYSCFG_R 13707 +#define VREF_R 13709 +#define DTS_R 13712 +#define PMBCTRL_R 13713 +#define LTDC_R 13760 +#define DCMIPP_R 13761 +#define DDRPERFM_R 13768 +#define USBPHY_R 13776 +#define STGEN_R 13844 +#define USART1_R 13888 +#define USART2_R 13889 +#define SPI4_R 13890 +#define SPI5_R 13891 +#define I2C3_R 13892 +#define I2C4_R 13893 +#define I2C5_R 13894 +#define TIM12_R 13895 +#define TIM13_R 13896 +#define TIM14_R 13897 +#define TIM15_R 13898 +#define TIM16_R 13899 +#define TIM17_R 13900 +#define DMA1_R 13952 +#define DMA2_R 13953 +#define DMAMUX1_R 13954 +#define DMA3_R 13955 +#define DMAMUX2_R 13956 +#define ADC1_R 13957 +#define ADC2_R 13958 +#define USBO_R 13960 +#define GPIOA_R 14080 +#define GPIOB_R 14081 +#define GPIOC_R 14082 +#define GPIOD_R 14083 +#define GPIOE_R 14084 +#define GPIOF_R 14085 +#define GPIOG_R 14086 +#define GPIOH_R 14087 +#define GPIOI_R 14088 +#define TSC_R 14095 +#define PKA_R 14146 +#define SAES_R 14147 +#define CRYP1_R 14148 +#define HASH1_R 14149 +#define RNG1_R 14150 +#define AXIMC_R 14160 +#define MDMA_R 14208 +#define MCE_R 14209 +#define ETH1MAC_R 14218 +#define FMC_R 14220 +#define QSPI_R 14222 +#define SDMMC1_R 14224 +#define SDMMC2_R 14225 +#define CRC1_R 14228 +#define USBH_R 14232 +#define ETH2MAC_R 14238 + +#endif /* _DT_BINDINGS_STM32MP13_RESET_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h new file mode 100644 index 0000000..2b34864 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h @@ -0,0 +1,123 @@ +/* SPDX-License-Identifier: GPL-2.0 or BSD-3-Clause */ +/* + * Copyright (C) STMicroelectronics 2018-2022 - All Rights Reserved + * Author: Gabriel Fernandez for STMicroelectronics. + */ + +#ifndef _DT_BINDINGS_STM32MP15_RESET_H_ +#define _DT_BINDINGS_STM32MP15_RESET_H_ + +#define MCU_HOLD_BOOT_R 2144 +#define LTDC_R 3072 +#define DSI_R 3076 +#define DDRPERFM_R 3080 +#define USBPHY_R 3088 +#define SPI6_R 3136 +#define I2C4_R 3138 +#define I2C6_R 3139 +#define USART1_R 3140 +#define STGEN_R 3156 +#define GPIOZ_R 3200 +#define CRYP1_R 3204 +#define HASH1_R 3205 +#define RNG1_R 3206 +#define AXIM_R 3216 +#define GPU_R 3269 +#define ETHMAC_R 3274 +#define FMC_R 3276 +#define QSPI_R 3278 +#define SDMMC1_R 3280 +#define SDMMC2_R 3281 +#define CRC1_R 3284 +#define USBH_R 3288 +#define MDMA_R 3328 +#define MCU_R 8225 +#define TIM2_R 19456 +#define TIM3_R 19457 +#define TIM4_R 19458 +#define TIM5_R 19459 +#define TIM6_R 19460 +#define TIM7_R 19461 +#define TIM12_R 16462 +#define TIM13_R 16463 +#define TIM14_R 16464 +#define LPTIM1_R 19465 +#define SPI2_R 19467 +#define SPI3_R 19468 +#define USART2_R 19470 +#define USART3_R 19471 +#define UART4_R 19472 +#define UART5_R 19473 +#define UART7_R 19474 +#define UART8_R 19475 +#define I2C1_R 19477 +#define I2C2_R 19478 +#define I2C3_R 19479 +#define I2C5_R 19480 +#define SPDIF_R 19482 +#define CEC_R 19483 +#define DAC12_R 19485 +#define MDIO_R 19847 +#define TIM1_R 19520 +#define TIM8_R 19521 +#define TIM15_R 19522 +#define TIM16_R 19523 +#define TIM17_R 19524 +#define SPI1_R 19528 +#define SPI4_R 19529 +#define SPI5_R 19530 +#define USART6_R 19533 +#define SAI1_R 19536 +#define SAI2_R 19537 +#define SAI3_R 19538 +#define DFSDM_R 19540 +#define FDCAN_R 19544 +#define LPTIM2_R 19584 +#define LPTIM3_R 19585 +#define LPTIM4_R 19586 +#define LPTIM5_R 19587 +#define SAI4_R 19592 +#define SYSCFG_R 19595 +#define VREF_R 19597 +#define TMPSENS_R 19600 +#define PMBCTRL_R 19601 +#define DMA1_R 19648 +#define DMA2_R 19649 +#define DMAMUX_R 19650 +#define ADC12_R 19653 +#define USBO_R 19656 +#define SDMMC3_R 19664 +#define CAMITF_R 19712 +#define CRYP2_R 19716 +#define HASH2_R 19717 +#define RNG2_R 19718 +#define CRC2_R 19719 +#define HSEM_R 19723 +#define MBOX_R 19724 +#define GPIOA_R 19776 +#define GPIOB_R 19777 +#define GPIOC_R 19778 +#define GPIOD_R 19779 +#define GPIOE_R 19780 +#define GPIOF_R 19781 +#define GPIOG_R 19782 +#define GPIOH_R 19783 +#define GPIOI_R 19784 +#define GPIOJ_R 19785 +#define GPIOK_R 19786 + +/* SCMI reset domain identifiers */ +#define RST_SCMI0_SPI6 0 +#define RST_SCMI0_I2C4 1 +#define RST_SCMI0_I2C6 2 +#define RST_SCMI0_USART1 3 +#define RST_SCMI0_STGEN 4 +#define RST_SCMI0_GPIOZ 5 +#define RST_SCMI0_CRYP1 6 +#define RST_SCMI0_HASH1 7 +#define RST_SCMI0_RNG1 8 +#define RST_SCMI0_MDMA 9 +#define RST_SCMI0_MCU 10 +#define RST_SCMI0_MCU_HOLD_BOOT 11 + +#endif /* _DT_BINDINGS_STM32MP15_RESET_H_ */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h b/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h new file mode 100644 index 0000000..3f9fb3b --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2017-2020, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + */ + +#ifndef _DT_BINDINGS_STM32_ETZPC_H +#define _DT_BINDINGS_STM32_ETZPC_H + +/* DECPROT modes */ +#define DECPROT_S_RW 0x0 +#define DECPROT_NS_R_S_W 0x1 +#define DECPROT_MCU_ISOLATION 0x2 +#define DECPROT_NS_RW 0x3 + +/* DECPROT lock */ +#define DECPROT_UNLOCK 0x0 +#define DECPROT_LOCK 0x1 + +#endif /* _DT_BINDINGS_STM32_ETZPC_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h new file mode 100644 index 0000000..1cb2326 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h @@ -0,0 +1,35 @@ +/* + * SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause + * + * Copyright (C) 2022, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_STM32MP13_TZC400_H +#define _DT_BINDINGS_STM32MP13_TZC400_H + +#include + +#define STM32MP1_TZC_A7_ID U(0) +#define STM32MP1_TZC_LCD_ID U(3) +#define STM32MP1_TZC_MDMA_ID U(5) +#define STM32MP1_TZC_DMA_ID U(6) +#define STM32MP1_TZC_USB_HOST_ID U(7) +#define STM32MP1_TZC_USB_OTG_ID U(8) +#define STM32MP1_TZC_SDMMC_ID U(9) +#define STM32MP1_TZC_ETH_ID U(10) +#define STM32MP1_TZC_DCMIPP_ID U(11) +#define STM32MP1_TZC_DAP_ID U(15) + +#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ + (TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DCMIPP_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)) + +#endif /* _DT_BINDINGS_STM32MP13_TZC400_H */ diff --git a/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h new file mode 100644 index 0000000..54cd902 --- /dev/null +++ b/arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h @@ -0,0 +1,36 @@ +/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + */ + +#ifndef _DT_BINDINGS_STM32MP15_TZC400_H +#define _DT_BINDINGS_STM32MP15_TZC400_H + +#include + +#define STM32MP1_TZC_A7_ID U(0) +#define STM32MP1_TZC_M4_ID U(1) +#define STM32MP1_TZC_LCD_ID U(3) +#define STM32MP1_TZC_GPU_ID U(4) +#define STM32MP1_TZC_MDMA_ID U(5) +#define STM32MP1_TZC_DMA_ID U(6) +#define STM32MP1_TZC_USB_HOST_ID U(7) +#define STM32MP1_TZC_USB_OTG_ID U(8) +#define STM32MP1_TZC_SDMMC_ID U(9) +#define STM32MP1_TZC_ETH_ID U(10) +#define STM32MP1_TZC_DAP_ID U(15) + +#define TZC_REGION_NSEC_ALL_ACCESS_RDWR \ + (TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_A7_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_GPU_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_LCD_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_MDMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_M4_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DMA_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_HOST_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_USB_OTG_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_SDMMC_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_ETH_ID) | \ + TZC_REGION_ACCESS_RDWR(STM32MP1_TZC_DAP_ID)) + +#endif /* _DT_BINDINGS_STM32MP15_TZC400_H */ diff --git a/arm-trusted-firmware/include/export/README b/arm-trusted-firmware/include/export/README new file mode 100644 index 0000000..2de8d6b --- /dev/null +++ b/arm-trusted-firmware/include/export/README @@ -0,0 +1,33 @@ +All headers under include/export/ are export headers that are intended for +inclusion in third-party code which needs to interact with TF-A data structures +or interfaces. They must follow these special rules: + +- Header guards should start with ARM_TRUSTED_FIRMWARE_ to reduce clash risk. + +- All definitions should be sufficiently namespaced (e.g. with BL_ or TF_) to + make name clashes with third-party code unlikely. + +- They must not #include any headers except other export headers, and those + includes must use relative paths with "../double_quotes.h" notation. + +- They must not rely on any type definitions other that types defined + in the ISO C standard (i.e. uint64_t is fine, but not u_register_t). They + should still not #include . Instead, wrapper headers including + export headers need to ensure that they #include earlier in their + include order. + +- They must not rely on any macro definitions other than those which are + pre-defined by all common compilers (e.g. __ASSEMBLER__ or __aarch64__). + +- They must only contain macro, type and structure definitions, no prototypes. + +- They should avoid using integer types with architecture-dependent widths + (e.g. long, uintptr_t, pointer types) where possible. (Some existing export + headers are violating this for now.) + +- Their names should always end in "_exp.h". + +- Normal TF-A code should never include export headers directly. Instead, it + should include a wrapper header that ensures the export header is included in + the right manner. (The wrapper header for include/export/x/y/z_exp.h should + normally be placed at include/x/y/z.h.) diff --git a/arm-trusted-firmware/include/export/common/bl_common_exp.h b/arm-trusted-firmware/include/export/common/bl_common_exp.h new file mode 100644 index 0000000..8f09017 --- /dev/null +++ b/arm-trusted-firmware/include/export/common/bl_common_exp.h @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "ep_info_exp.h" +#include "tbbr/tbbr_img_def_exp.h" + +/* + * The following are used for image state attributes. + * Image can only be in one of the following state. + */ +#define IMAGE_STATE_RESET U(0) +#define IMAGE_STATE_COPIED U(1) +#define IMAGE_STATE_COPYING U(2) +#define IMAGE_STATE_AUTHENTICATED U(3) +#define IMAGE_STATE_EXECUTED U(4) +#define IMAGE_STATE_INTERRUPTED U(5) + +#define IMAGE_ATTRIB_SKIP_LOADING U(0x02) +#define IMAGE_ATTRIB_PLAT_SETUP U(0x04) + +#define INVALID_IMAGE_ID U(0xFFFFFFFF) + +#ifndef __ASSEMBLER__ + +/***************************************************************************** + * Image info binary provides information from the image loader that + * can be used by the firmware to manage available trusted RAM. + * More advanced firmware image formats can provide additional + * information that enables optimization or greater flexibility in the + * common firmware code + *****************************************************************************/ +typedef struct image_info { + param_header_t h; + uintptr_t image_base; /* physical address of base of image */ + uint32_t image_size; /* bytes read from image file */ + uint32_t image_max_size; +} image_info_t; + +/* BL image node in the BL image execution sequence */ +typedef struct bl_params_node { + unsigned int image_id; + image_info_t *image_info; + entry_point_info_t *ep_info; + struct bl_params_node *next_params_info; +} bl_params_node_t; + +/* + * BL image head node in the BL image execution sequence + * It is also used to pass information to next BL image. + */ +typedef struct bl_params { + param_header_t h; + bl_params_node_t *head; +} bl_params_t; + +/***************************************************************************** + * The image descriptor struct definition. + *****************************************************************************/ +typedef struct image_desc { + /* Contains unique image id for the image. */ + unsigned int image_id; + /* + * This member contains Image state information. + * Refer IMAGE_STATE_XXX defined above. + */ + unsigned int state; + uint32_t copied_size; /* image size copied in blocks */ + image_info_t image_info; + entry_point_info_t ep_info; +} image_desc_t; + +/* BL image node in the BL image loading sequence */ +typedef struct bl_load_info_node { + unsigned int image_id; + image_info_t *image_info; + struct bl_load_info_node *next_load_info; +} bl_load_info_node_t; + +/* BL image head node in the BL image loading sequence */ +typedef struct bl_load_info { + param_header_t h; + bl_load_info_node_t *head; +} bl_load_info_t; + +#endif /* __ASSEMBLER__ */ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_BL_COMMON_EXP_H */ diff --git a/arm-trusted-firmware/include/export/common/ep_info_exp.h b/arm-trusted-firmware/include/export/common/ep_info_exp.h new file mode 100644 index 0000000..a5bd10a --- /dev/null +++ b/arm-trusted-firmware/include/export/common/ep_info_exp.h @@ -0,0 +1,119 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" +#include "param_header_exp.h" + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'entry_point_info' structure at their correct offsets. + ******************************************************************************/ +#define ENTRY_POINT_INFO_PC_OFFSET U(0x08) +#ifdef __aarch64__ +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x18) +#else +#define ENTRY_POINT_INFO_LR_SVC_OFFSET U(0x10) +#define ENTRY_POINT_INFO_ARGS_OFFSET U(0x14) +#endif + +/* + * Security state of the image. Bit 0 and + * bit 5 are used to determine the security + * state of the image as follows: + * + * --------------------------------- + * Bit 5 | Bit 0 | Security state + * --------------------------------- + * 0 0 EP_SECURE + * 0 1 EP_NON_SECURE + * 1 1 EP_REALM + */ +#define EP_SECURITY_MASK UL(0x21) +#define EP_SECURITY_SHIFT UL(0) +#define EP_SECURE UL(0x0) +#define EP_NON_SECURE UL(0x1) +#define EP_REALM UL(0x21) + +/* Endianness of the image. */ +#define EP_EE_MASK U(0x2) +#define EP_EE_SHIFT U(1) +#define EP_EE_LITTLE U(0x0) +#define EP_EE_BIG U(0x2) +#define EP_GET_EE(x) ((x) & EP_EE_MASK) +#define EP_SET_EE(x, ee) ((x) = ((x) & ~EP_EE_MASK) | (ee)) + +/* Enable or disable access to the secure timer from secure images. */ +#define EP_ST_MASK U(0x4) +#define EP_ST_SHIFT U(2) +#define EP_ST_DISABLE U(0x0) +#define EP_ST_ENABLE U(0x4) +#define EP_GET_ST(x) ((x) & EP_ST_MASK) +#define EP_SET_ST(x, ee) ((x) = ((x) & ~EP_ST_MASK) | (ee)) + +/* Determine if an image is executable or not. */ +#define EP_EXE_MASK U(0x8) +#define EP_EXE_SHIFT U(3) +#define EP_NON_EXECUTABLE U(0x0) +#define EP_EXECUTABLE U(0x8) +#define EP_GET_EXE(x) ((x) & EP_EXE_MASK) +#define EP_SET_EXE(x, ee) ((x) = ((x) & ~EP_EXE_MASK) | (ee)) + +/* Flag to indicate the first image that is executed. */ +#define EP_FIRST_EXE_MASK U(0x10) +#define EP_FIRST_EXE_SHIFT U(4) +#define EP_FIRST_EXE U(0x10) +#define EP_GET_FIRST_EXE(x) ((x) & EP_FIRST_EXE_MASK) +#define EP_SET_FIRST_EXE(x, ee) ((x) = ((x) & ~EP_FIRST_EXE_MASK) | (ee)) + +#ifndef __ASSEMBLER__ + +typedef struct aapcs64_params { + uint64_t arg0; + uint64_t arg1; + uint64_t arg2; + uint64_t arg3; + uint64_t arg4; + uint64_t arg5; + uint64_t arg6; + uint64_t arg7; +} aapcs64_params_t; + +typedef struct aapcs32_params { + uint32_t arg0; + uint32_t arg1; + uint32_t arg2; + uint32_t arg3; +} aapcs32_params_t; + +/***************************************************************************** + * This structure represents the superset of information needed while + * switching exception levels. The only two mechanisms to do so are + * ERET & SMC. Security state is indicated using bit zero of header + * attribute + * NOTE: BL1 expects entrypoint followed by spsr at an offset from the start + * of this structure defined by the macro `ENTRY_POINT_INFO_PC_OFFSET` while + * processing SMC to jump to BL31. + *****************************************************************************/ +typedef struct entry_point_info { + param_header_t h; + uintptr_t pc; + uint32_t spsr; +#ifdef __aarch64__ + aapcs64_params_t args; +#else + uintptr_t lr_svc; + aapcs32_params_t args; +#endif +} entry_point_info_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_EP_INFO_EXP_H */ diff --git a/arm-trusted-firmware/include/export/common/param_header_exp.h b/arm-trusted-firmware/include/export/common/param_header_exp.h new file mode 100644 index 0000000..15bb6f2 --- /dev/null +++ b/arm-trusted-firmware/include/export/common/param_header_exp.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../lib/utils_def_exp.h" + +/* Param header types */ +#define PARAM_EP U(0x01) +#define PARAM_IMAGE_BINARY U(0x02) +#define PARAM_BL31 U(0x03) +#define PARAM_BL_LOAD_INFO U(0x04) +#define PARAM_BL_PARAMS U(0x05) +#define PARAM_PSCI_LIB_ARGS U(0x06) +#define PARAM_SP_IMAGE_BOOT_INFO U(0x07) + +/* Param header version */ +#define PARAM_VERSION_1 U(0x01) +#define PARAM_VERSION_2 U(0x02) + +#ifndef __ASSEMBLER__ + +/*************************************************************************** + * This structure provides version information and the size of the + * structure, attributes for the structure it represents + ***************************************************************************/ +typedef struct param_header { + uint8_t type; /* type of the structure */ + uint8_t version; /* version of this structure */ + uint16_t size; /* size of this structure in bytes */ + uint32_t attr; /* attributes: unused bits SBZ */ +} param_header_t; + +#endif /*__ASSEMBLER__*/ + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_PARAM_HEADER_EXP_H */ diff --git a/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h b/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h new file mode 100644 index 0000000..98544c0 --- /dev/null +++ b/arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../lib/utils_def_exp.h" + +/* Firmware Image Package */ +#define FIP_IMAGE_ID U(0) + +/* Trusted Boot Firmware BL2 */ +#define BL2_IMAGE_ID U(1) + +/* SCP Firmware SCP_BL2 */ +#define SCP_BL2_IMAGE_ID U(2) + +/* EL3 Runtime Firmware BL31 */ +#define BL31_IMAGE_ID U(3) + +/* Secure Payload BL32 (Trusted OS) */ +#define BL32_IMAGE_ID U(4) + +/* Non-Trusted Firmware BL33 */ +#define BL33_IMAGE_ID U(5) + +/* Certificates */ +#define TRUSTED_BOOT_FW_CERT_ID U(6) +#define TRUSTED_KEY_CERT_ID U(7) + +#define SCP_FW_KEY_CERT_ID U(8) +#define SOC_FW_KEY_CERT_ID U(9) +#define TRUSTED_OS_FW_KEY_CERT_ID U(10) +#define NON_TRUSTED_FW_KEY_CERT_ID U(11) + +#define SCP_FW_CONTENT_CERT_ID U(12) +#define SOC_FW_CONTENT_CERT_ID U(13) +#define TRUSTED_OS_FW_CONTENT_CERT_ID U(14) +#define NON_TRUSTED_FW_CONTENT_CERT_ID U(15) + +/* Non-Trusted ROM Firmware NS_BL1U */ +#define NS_BL1U_IMAGE_ID U(16) + +/* Trusted FWU Certificate */ +#define FWU_CERT_ID U(17) + +/* Trusted FWU SCP Firmware SCP_BL2U */ +#define SCP_BL2U_IMAGE_ID U(18) + +/* Trusted FWU Boot Firmware BL2U */ +#define BL2U_IMAGE_ID U(19) + +/* Non-Trusted FWU Firmware NS_BL2U */ +#define NS_BL2U_IMAGE_ID U(20) + +/* Secure Payload BL32_EXTRA1 (Trusted OS Extra1) */ +#define BL32_EXTRA1_IMAGE_ID U(21) + +/* Secure Payload BL32_EXTRA2 (Trusted OS Extra2) */ +#define BL32_EXTRA2_IMAGE_ID U(22) + +/* HW_CONFIG (e.g. Kernel DT) */ +#define HW_CONFIG_ID U(23) + +/* TB_FW_CONFIG */ +#define TB_FW_CONFIG_ID U(24) + +/* SOC_FW_CONFIG */ +#define SOC_FW_CONFIG_ID U(25) + +/* TOS_FW_CONFIG */ +#define TOS_FW_CONFIG_ID U(26) + +/* NT_FW_CONFIG */ +#define NT_FW_CONFIG_ID U(27) + +/* GPT Partition */ +#define GPT_IMAGE_ID U(28) + +/* Binary with STM32 header */ +#define STM32_IMAGE_ID U(29) + +/* Encrypted image identifier */ +#define ENC_IMAGE_ID U(30) + +/* FW_CONFIG */ +#define FW_CONFIG_ID U(31) + +/* + * Primary FWU metadata image ID + */ +#define FWU_METADATA_IMAGE_ID U(32) + +/* + * Backup FWU metadata image ID + */ +#define BKUP_FWU_METADATA_IMAGE_ID U(33) + +/* Realm Monitor Manager (RMM) */ +#define RMM_IMAGE_ID U(34) + +/* Max Images */ +#define MAX_IMAGE_IDS U(35) + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_COMMON_TBBR_TBBR_IMG_DEF_EXP_H */ diff --git a/arm-trusted-firmware/include/export/drivers/gpio_exp.h b/arm-trusted-firmware/include/export/drivers/gpio_exp.h new file mode 100644 index 0000000..e4112a9 --- /dev/null +++ b/arm-trusted-firmware/include/export/drivers/gpio_exp.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#define ARM_TF_GPIO_DIR_OUT 0 +#define ARM_TF_GPIO_DIR_IN 1 + +#define ARM_TF_GPIO_LEVEL_LOW 0 +#define ARM_TF_GPIO_LEVEL_HIGH 1 + +#define ARM_TF_GPIO_PULL_NONE 0 +#define ARM_TF_GPIO_PULL_UP 1 +#define ARM_TF_GPIO_PULL_DOWN 2 +#define ARM_TF_GPIO_PULL_REPEATER 3 + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_DRIVERS_GPIO_EXP_H */ diff --git a/arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h b/arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h new file mode 100644 index 0000000..7391dec --- /dev/null +++ b/arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../drivers/gpio_exp.h" + +/* + * This API implements a lightweight parameter passing mechanism that can be + * used to pass SoC Firmware configuration data from BL2 to BL31 by platforms or + * configurations that do not want to depend on libfdt. It is structured as a + * singly-linked list of parameter structures that all share the same common + * header but may have different (and differently-sized) structure bodies after + * that. The header contains a type field to indicate the parameter type (which + * is used to infer the structure length and how to interpret its contents) and + * a next pointer which contains the absolute physical address of the next + * parameter structure. The next pointer in the last structure block is set to + * NULL. The picture below shows how the parameters are kept in memory. + * + * head of list ---> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * +----| next | | + * | +----------------+ --+ + * | | parameter data | + * | +----------------+ + * | + * +--> +----------------+ --+ + * | type | | + * +----------------+ |--> struct bl_aux_param + * NULL <---| next | | + * +----------------+ --+ + * | parameter data | + * +----------------+ + * + * Note: The SCTLR_EL3.A bit (Alignment fault check enable) is set in TF-A, so + * BL2 must ensure that each parameter struct starts on a 64-bit aligned address + * to avoid alignment faults. Parameters may be allocated in any address range + * accessible at the time of BL31 handoff (e.g. SRAM, DRAM, SoC-internal scratch + * registers, etc.), in particular address ranges that may not be mapped in + * BL31's page tables, so the parameter list must be parsed before the MMU is + * enabled and any information that is required at a later point should be + * deep-copied out into BL31-internal data structures. + */ + +enum bl_aux_param_type { + BL_AUX_PARAM_NONE = 0, + BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST = 0x1, + /* 0x1 - 0x7fffffff can be used by vendor-specific handlers. */ + BL_AUX_PARAM_VENDOR_SPECIFIC_LAST = 0x7fffffff, + BL_AUX_PARAM_GENERIC_FIRST = 0x80000001, + BL_AUX_PARAM_COREBOOT_TABLE = BL_AUX_PARAM_GENERIC_FIRST, + /* 0x80000001 - 0xffffffff are reserved for the generic handler. */ + BL_AUX_PARAM_GENERIC_LAST = 0xffffffff, + /* Top 32 bits of the type field are reserved for future use. */ +}; + +/* common header for all BL aux parameters */ +struct bl_aux_param_header { + uint64_t type; + uint64_t next; +}; + +/* commonly useful parameter structures that can be shared by multiple types */ +struct bl_aux_param_uint64 { + struct bl_aux_param_header h; + uint64_t value; +}; + +struct bl_aux_gpio_info { + uint8_t polarity; + uint8_t direction; + uint8_t pull_mode; + uint8_t reserved; + uint32_t index; +}; + +struct bl_aux_param_gpio { + struct bl_aux_param_header h; + struct bl_aux_gpio_info gpio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_BL_AUX_PARAMS_EXP_H */ diff --git a/arm-trusted-firmware/include/export/lib/utils_def_exp.h b/arm-trusted-firmware/include/export/lib/utils_def_exp.h new file mode 100644 index 0000000..d4a4a85 --- /dev/null +++ b/arm-trusted-firmware/include/export/lib/utils_def_exp.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +/* + * For those constants to be shared between C and other sources, apply a 'U', + * 'UL', 'ULL', 'L' or 'LL' suffix to the argument only in C, to avoid + * undefined or unintended behaviour. + * + * The GNU assembler and linker do not support these suffixes (it causes the + * build process to fail) therefore the suffix is omitted when used in linker + * scripts and assembler files. +*/ +#if defined(__ASSEMBLER__) +# define U(_x) (_x) +# define UL(_x) (_x) +# define ULL(_x) (_x) +# define L(_x) (_x) +# define LL(_x) (_x) +#else +# define U_(_x) (_x##U) +# define U(_x) U_(_x) +# define UL(_x) (_x##UL) +# define ULL(_x) (_x##ULL) +# define L(_x) (_x##L) +# define LL(_x) (_x##LL) + +#endif + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_LIB_UTILS_DEF_EXP_H */ diff --git a/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h b/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h new file mode 100644 index 0000000..d650030 --- /dev/null +++ b/arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../../lib/bl_aux_params/bl_aux_params_exp.h" + +/* param type */ +enum bl_aux_mtk_param_type { + BL_AUX_PARAM_MTK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST, +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_MEDIATEK_COMMON_PLAT_PARAMS_EXP_H */ diff --git a/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h b/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h new file mode 100644 index 0000000..ccc9cd9 --- /dev/null +++ b/arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H +#define ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H + +/* EXPORT HEADER -- See include/export/README for details! -- EXPORT HEADER */ + +#include "../../../lib/bl_aux_params/bl_aux_params_exp.h" + +/* param type */ +enum bl_aux_rk_param_type { + BL_AUX_PARAM_RK_RESET_GPIO = BL_AUX_PARAM_VENDOR_SPECIFIC_FIRST, + BL_AUX_PARAM_RK_POWEROFF_GPIO, + BL_AUX_PARAM_RK_SUSPEND_GPIO, + BL_AUX_PARAM_RK_SUSPEND_APIO, +}; + +struct bl_aux_rk_apio_info { + uint8_t apio1 : 1; + uint8_t apio2 : 1; + uint8_t apio3 : 1; + uint8_t apio4 : 1; + uint8_t apio5 : 1; +}; + +struct bl_aux_param_rk_apio { + struct bl_aux_param_header h; + struct bl_aux_rk_apio_info apio; +}; + +#endif /* ARM_TRUSTED_FIRMWARE_EXPORT_PLAT_ROCKCHIP_COMMON_PLAT_PARAMS_EXP_H */ diff --git a/arm-trusted-firmware/include/lib/bakery_lock.h b/arm-trusted-firmware/include/lib/bakery_lock.h new file mode 100644 index 0000000..1fece01 --- /dev/null +++ b/arm-trusted-firmware/include/lib/bakery_lock.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BAKERY_LOCK_H +#define BAKERY_LOCK_H + +#include + +#define BAKERY_LOCK_MAX_CPUS PLATFORM_CORE_COUNT + +#ifndef __ASSEMBLER__ +#include +#include +#include + +#include + +/***************************************************************************** + * Internal helpers used by the bakery lock implementation. + ****************************************************************************/ + +/* Convert a ticket to priority */ +static inline unsigned int bakery_get_priority(unsigned int t, unsigned int pos) +{ + return (t << 8) | pos; +} + +#define CHOOSING_TICKET U(0x1) +#define CHOSEN_TICKET U(0x0) + +static inline bool bakery_is_choosing(unsigned int info) +{ + return (info & 1U) == CHOOSING_TICKET; +} + +static inline unsigned int bakery_ticket_number(unsigned int info) +{ + return (info >> 1) & 0x7FFFU; +} + +static inline uint16_t make_bakery_data(unsigned int choosing, unsigned int num) +{ + unsigned int val = (choosing & 0x1U) | (num << 1); + + return (uint16_t) val; +} + +/***************************************************************************** + * External bakery lock interface. + ****************************************************************************/ +#if USE_COHERENT_MEM +/* + * Bakery locks are stored in coherent memory + * + * Each lock's data is contiguous and fully allocated by the compiler + */ + +typedef struct bakery_lock { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data[BAKERY_LOCK_MAX_CPUS]; +} bakery_lock_t; + +#else +/* + * 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 + */ + +typedef struct bakery_info { + /* + * The lock_data is a bit-field of 2 members: + * Bit[0] : choosing. This field is set when the CPU is + * choosing its bakery number. + * Bits[1 - 15] : number. This is the bakery number allocated. + */ + volatile uint16_t lock_data; +} bakery_info_t; + +typedef bakery_info_t bakery_lock_t; + +#endif /* __USE_COHERENT_MEM__ */ + +static inline void bakery_lock_init(bakery_lock_t *bakery) {} +void bakery_lock_get(bakery_lock_t *bakery); +void bakery_lock_release(bakery_lock_t *bakery); + +#define DEFINE_BAKERY_LOCK(_name) bakery_lock_t _name __section("bakery_lock") + +#define DECLARE_BAKERY_LOCK(_name) extern bakery_lock_t _name + + +#endif /* __ASSEMBLER__ */ +#endif /* BAKERY_LOCK_H */ diff --git a/arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h b/arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h new file mode 100644 index 0000000..f6ce802 --- /dev/null +++ b/arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef LIB_BL_AUX_PARAMS_H +#define LIB_BL_AUX_PARAMS_H + +#include +#include + +#include + +/* + * Handler function that handles an individual aux parameter. Return true if + * the parameter was handled, and flase if bl_aux_params_parse() should make its + * own attempt at handling it (for generic parameters). + */ +typedef bool (*bl_aux_param_handler_t)(struct bl_aux_param_header *param); + +/* + * Interprets head as the start of an aux parameter list, and passes the + * parameters individually to handler(). Handles generic parameters directly if + * handler() hasn't already done so. If only generic parameters are expected, + * handler() can be NULL. + */ +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler); + +#endif /* LIB_BL_AUX_PARAMS_H */ diff --git a/arm-trusted-firmware/include/lib/cassert.h b/arm-trusted-firmware/include/lib/cassert.h new file mode 100644 index 0000000..bbfdfdb --- /dev/null +++ b/arm-trusted-firmware/include/lib/cassert.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CASSERT_H +#define CASSERT_H + +#include + +/******************************************************************************* + * Macro to flag a compile time assertion. It uses the preprocessor to generate + * an invalid C construct if 'cond' evaluates to false. + * The following compilation error is triggered if the assertion fails: + * "error: size of array 'msg' is negative" + * The 'unused' attribute ensures that the unused typedef does not emit a + * compiler warning. + ******************************************************************************/ +#define CASSERT(cond, msg) \ + typedef char msg[(cond) ? 1 : -1] __unused + +#endif /* CASSERT_H */ diff --git a/arm-trusted-firmware/include/lib/coreboot.h b/arm-trusted-firmware/include/lib/coreboot.h new file mode 100644 index 0000000..0aa6579 --- /dev/null +++ b/arm-trusted-firmware/include/lib/coreboot.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef COREBOOT_H +#define COREBOOT_H + +#include + +typedef struct { + uint32_t type; /* always 2 (memory-mapped) on ARM */ + uint32_t baseaddr; + uint32_t baud; + uint32_t regwidth; /* in bytes, i.e. usually 4 */ + uint32_t input_hertz; + uint32_t uart_pci_addr; /* unused on current ARM systems */ +} coreboot_serial_t; +extern coreboot_serial_t coreboot_serial; + +#define COREBOOT_MAX_MEMRANGES 32 /* libpayload also uses this limit */ + +typedef struct __packed { + uint64_t start; + uint64_t size; + uint32_t type; +} coreboot_memrange_t; +extern coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES]; + +typedef enum { + CB_MEM_NONE = 0, /* coreboot will never report this */ + CB_MEM_RAM = 1, + CB_MEM_RESERVED = 2, + CB_MEM_ACPI = 3, + CB_MEM_NVS = 4, + CB_MEM_UNUSABLE = 5, + CB_MEM_VENDOR_RSVD = 6, + CB_MEM_TABLE = 16, +} coreboot_memory_t; + +coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size); +void coreboot_table_setup(void *base); + +#endif /* COREBOOT_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h b/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h new file mode 100644 index 0000000..1d40cec --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AEM_GENERIC_H +#define AEM_GENERIC_H + +#include + +/* BASE AEM midr for revision 0 */ +#define BASE_AEM_MIDR U(0x410FD0F0) + +#endif /* AEM_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h new file mode 100644 index 0000000..abacdba --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A12_H +#define CORTEX_A12_H + +#include + +/******************************************************************************* + * Cortex-A12 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A12_MIDR U(0x410FC0D0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A12_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A12_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h new file mode 100644 index 0000000..9526a9c --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A15_H +#define CORTEX_A15_H + +#include + +/******************************************************************************* + * Auxiliary Control Register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A15_ACTLR2 p15, 1, c15, c0, 4 + +#define CORTEX_A15_ACTLR2_INV_DCC_BIT (U(1) << 0) + +/******************************************************************************* + * Cortex-A15 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A15_MIDR U(0x410FC0F0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A15_ACTLR_INV_BTB_BIT (U(1) << 0) +#define CORTEX_A15_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A15_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h new file mode 100644 index 0000000..89a8eb6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A17_H +#define CORTEX_A17_H + +#include + +/******************************************************************************* + * Cortex-A17 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A17_MIDR U(0x410FC0E0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A17_ACTLR_SMP_BIT (U(1) << 6) + +/******************************************************************************* + * Implementation defined register specific definitions. + ******************************************************************************/ +#define CORTEX_A17_IMP_DEF_REG1 p15, 0, c15, c0, 1 + +#endif /* CORTEX_A17_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h new file mode 100644 index 0000000..6ddd533 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A32_H +#define CORTEX_A32_H + +#include + +/* Cortex-A32 Main ID register for revision 0 */ +#define CORTEX_A32_MIDR U(0x410FD010) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + * CPUECTLR_EL1 is an implementation-specific register. + ******************************************************************************/ +#define CORTEX_A32_CPUECTLR_EL1 p15, 1, c15 +#define CORTEX_A32_CPUECTLR_SMPEN_BIT (ULL(1) << 6) + +#endif /* CORTEX_A32_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h new file mode 100644 index 0000000..76703b7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A5_H +#define CORTEX_A5_H + +#include + +/******************************************************************************* + * Cortex-A8 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A5_MIDR U(0x410FC050) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A5_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A5_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h new file mode 100644 index 0000000..8dd0192 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A53_H +#define CORTEX_A53_H + +#include + +/* Cortex-A53 midr for revision 0 */ +#define CORTEX_A53_MIDR U(0x410FD030) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_ECTLR p15, 1, c15 + +#define CORTEX_A53_ECTLR_SMP_BIT (U(1) << 6) + +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT) + +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT U(3) +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_MERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_CPUACTLR p15, 0, c15 + +#define CORTEX_A53_CPUACTLR_ENDCCASCI_SHIFT U(44) +#define CORTEX_A53_CPUACTLR_ENDCCASCI (ULL(1) << CORTEX_A53_CPUACTLR_ENDCCASCI_SHIFT) +#define CORTEX_A53_CPUACTLR_DTAH_SHIFT U(24) +#define CORTEX_A53_CPUACTLR_DTAH (ULL(1) << CORTEX_A53_CPUACTLR_DTAH_SHIFT) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ACTLR p15, 1, c15, c0, 0 + +#define CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN (U(1) << 14) +#define CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH (U(1) << 3) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ECTLR p15, 1, c9, c0, 3 + +#define CORTEX_A53_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_L2ECTLR_RET_CTRL_MASK (U(0x7) << L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A53_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h new file mode 100644 index 0000000..ffabd61 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A57_H +#define CORTEX_A57_H + +#include + +/* Cortex-A57 midr for revision 0 */ +#define CORTEX_A57_MIDR U(0x410FD070) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_ECTLR p15, 1, c15 + +#define CORTEX_A57_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUMERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUACTLR p15, 0, c15 + +#define CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_DMB (ULL(1) << 59) +#define CORTEX_A57_CPUACTLR_DIS_DMB_NULLIFICATION (ULL(1) << 58) +#define CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A57_CPUACTLR_GRE_NGRE_AS_NGNRE (ULL(1) << 54) +#define CORTEX_A57_CPUACTLR_DIS_OVERREAD (ULL(1) << 52) +#define CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A57_CPUACTLR_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH (ULL(1) << 38) +#define CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH (ULL(1) << 32) +#define CORTEX_A57_CPUACTLR_DIS_STREAMING (ULL(3) << 27) +#define CORTEX_A57_CPUACTLR_DIS_L1_STREAMING (ULL(3) << 25) +#define CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR (ULL(1) << 4) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2CTLR p15, 1, c9, c0, 2 + +#define CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2ECTLR p15, 1, c9, c0, 3 + +#define CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_L2ECTLR_RET_CTRL_MASK (U(0x7) << CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A57_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h new file mode 100644 index 0000000..730fdb5 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A7_H +#define CORTEX_A7_H + +#include + +/******************************************************************************* + * Cortex-A7 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A7_MIDR U(0x410FC070) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A7_ACTLR_SMP_BIT (U(1) << 6) + +#endif /* CORTEX_A7_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h new file mode 100644 index 0000000..4b1af61 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A72_H +#define CORTEX_A72_H + +#include + +/* Cortex-A72 midr for revision 0 */ +#define CORTEX_A72_MIDR U(0x410FD080) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_ECTLR p15, 1, c15 + +#define CORTEX_A72_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_MERRSR p15, 2, c15 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_CPUACTLR p15, 0, c15 + +#define CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH (ULL(1) << 56) +#define CORTEX_A72_CPUACTLR_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A72_CPUACTLR_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A72_CPUACTLR_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH (ULL(1) << 32) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2CTLR p15, 1, c9, c0, 2 + +#define CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES U(0x1) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2MERRSR p15, 3, c15 + +#endif /* CORTEX_A72_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h new file mode 100644 index 0000000..a8c978a --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A9_H +#define CORTEX_A9_H + +#include + +/******************************************************************************* + * Cortex-A9 midr with version/revision set to 0 + ******************************************************************************/ +#define CORTEX_A9_MIDR U(0x410FC090) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A9_ACTLR_SMP_BIT (U(1) << 6) +#define CORTEX_A9_ACTLR_FLZW_BIT (U(1) << 3) + +/******************************************************************************* + * CPU Power Control Register + ******************************************************************************/ +#define PCR p15, 0, c15, c0, 0 + +#ifndef __ASSEMBLER__ +#include +DEFINE_COPROCR_RW_FUNCS(pcr, PCR) +#endif + +#endif /* CORTEX_A9_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S b/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S new file mode 100644 index 0000000..a5ae6a4 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CPU_MACROS_S +#define CPU_MACROS_S + +#include +#include + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) +#define IMAGE_AT_EL3 +#endif + +#define CPU_IMPL_PN_MASK (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \ + (MIDR_PN_MASK << MIDR_PN_SHIFT) + +/* The number of CPU operations allowed */ +#define CPU_MAX_PWR_DWN_OPS 2 + +/* Special constant to specify that CPU has no reset function */ +#define CPU_NO_RESET_FUNC 0 + +/* Word size for 32-bit CPUs */ +#define CPU_WORD_SIZE 4 + +/* + * Whether errata status needs reporting. Errata status is printed in debug + * builds for both BL1 and BL32 images. + */ +#if (defined(IMAGE_BL1) || defined(IMAGE_BL32)) && DEBUG +# define REPORT_ERRATA 1 +#else +# define REPORT_ERRATA 0 +#endif + + + .equ CPU_MIDR_SIZE, CPU_WORD_SIZE + .equ CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS + .equ CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE + +#ifndef IMAGE_AT_EL3 + .equ CPU_RESET_FUNC_SIZE, 0 +#endif + +/* The power down core and cluster is needed only in BL32 */ +#ifndef IMAGE_BL32 + .equ CPU_PWR_DWN_OPS_SIZE, 0 +#endif + +/* Fields required to print errata status */ +#if !REPORT_ERRATA + .equ CPU_ERRATA_FUNC_SIZE, 0 +#endif + +/* Only BL32 requires mutual exclusion and printed flag. */ +#if !(REPORT_ERRATA && defined(IMAGE_BL32)) + .equ CPU_ERRATA_LOCK_SIZE, 0 + .equ CPU_ERRATA_PRINTED_SIZE, 0 +#endif + + +/* + * Define the offsets to the fields in cpu_ops structure. + * Every offset is defined based on the offset and size of the previous + * field. + */ + .equ CPU_MIDR, 0 + .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE + .equ CPU_PWR_DWN_OPS, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE + .equ CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE + .equ CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE + .equ CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE + .equ CPU_OPS_SIZE, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE + + /* + * Write given expressions as words + * + * _count: + * Write at least _count words. If the given number of expressions + * is less than _count, repeat the last expression to fill _count + * words in total + * _rest: + * Optional list of expressions. _this is for parameter extraction + * only, and has no significance to the caller + * + * Invoked as: + * fill_constants 2, foo, bar, blah, ... + */ + .macro fill_constants _count:req, _this, _rest:vararg + .ifgt \_count + /* Write the current expression */ + .ifb \_this + .error "Nothing to fill" + .endif + .word \_this + + /* Invoke recursively for remaining expressions */ + .ifnb \_rest + fill_constants \_count-1, \_rest + .else + fill_constants \_count-1, \_this + .endif + .endif + .endm + + /* + * Declare CPU operations + * + * _name: + * Name of the CPU for which operations are being specified + * _midr: + * Numeric value expected to read from CPU's MIDR + * _resetfunc: + * Reset function for the CPU. If there's no CPU reset function, + * specify CPU_NO_RESET_FUNC + * _power_down_ops: + * Comma-separated list of functions to perform power-down + * operatios on the CPU. At least one, and up to + * CPU_MAX_PWR_DWN_OPS number of functions may be specified. + * Starting at power level 0, these functions shall handle power + * down at subsequent power levels. If there aren't exactly + * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be + * used to handle power down at subsequent levels + */ + .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ + _power_down_ops:vararg + .section cpu_ops, "a" + .align 2 + .type cpu_ops_\_name, %object + .word \_midr +#if defined(IMAGE_AT_EL3) + .word \_resetfunc +#endif +#ifdef IMAGE_BL32 + /* Insert list of functions */ + fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops +#endif + +#if REPORT_ERRATA + .ifndef \_name\()_cpu_str + /* + * Place errata reported flag, and the spinlock to arbitrate access to + * it in the data section. + */ + .pushsection .data + define_asm_spinlock \_name\()_errata_lock + \_name\()_errata_reported: + .word 0 + .popsection + + /* Place CPU string in rodata */ + .pushsection .rodata + \_name\()_cpu_str: + .asciz "\_name" + .popsection + .endif + + /* + * Mandatory errata status printing function for CPUs of + * this class. + */ + .word \_name\()_errata_report + +#ifdef IMAGE_BL32 + /* Pointers to errata lock and reported flag */ + .word \_name\()_errata_lock + .word \_name\()_errata_reported +#endif +#endif + .endm + +#if REPORT_ERRATA + /* + * Print status of a CPU errata + * + * _chosen: + * Identifier indicating whether or not a CPU errata has been + * compiled in. + * _cpu: + * Name of the CPU + * _id: + * Errata identifier + * _rev_var: + * Register containing the combined value CPU revision and variant + * - typically the return value of cpu_get_rev_var + */ + .macro report_errata _chosen, _cpu, _id, _rev_var=r4 + /* Stash a string with errata ID */ + .pushsection .rodata + \_cpu\()_errata_\_id\()_str: + .asciz "\_id" + .popsection + + /* Check whether errata applies */ + mov r0, \_rev_var + bl check_errata_\_id + + .ifeq \_chosen + /* + * Errata workaround has not been compiled in. If the errata would have + * applied had it been compiled in, print its status as missing. + */ + cmp r0, #0 + movne r0, #ERRATA_MISSING + .endif + ldr r1, =\_cpu\()_cpu_str + ldr r2, =\_cpu\()_errata_\_id\()_str + bl errata_print_msg + .endm +#endif + /* + * 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: r0-r1 + */ + .macro jump_if_cpu_midr _cpu_midr, _label + ldcopr r0, MIDR + ubfx r0, r0, #MIDR_PN_SHIFT, #12 + ldr r1, =((\_cpu_midr >> MIDR_PN_SHIFT) & MIDR_PN_MASK) + cmp r0, r1 + beq \_label + .endm + +#endif /* CPU_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h b/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h new file mode 100644 index 0000000..6bb30a2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AEM_GENERIC_H +#define AEM_GENERIC_H + +#include + +/* BASE AEM midr for revision 0 */ +#define BASE_AEM_MIDR U(0x410FD0F0) + +/* Foundation AEM midr for revision 0 */ +#define FOUNDATION_AEM_MIDR U(0x410FD000) + +#endif /* AEM_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h new file mode 100644 index 0000000..5421478 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A35_H +#define CORTEX_A35_H + +#include + +/* Cortex-A35 Main ID register for revision 0 */ +#define CORTEX_A35_MIDR U(0x410FD040) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + * CPUECTLR_EL1 is an implementation-specific register. + ******************************************************************************/ +#define CORTEX_A35_CPUECTLR_EL1 S3_1_C15_C2_1 +#define CORTEX_A35_CPUECTLR_SMPEN_BIT (ULL(1) << 6) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A35_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A35_CPUACTLR_EL1_ENDCCASCI (ULL(1) << 44) + +#endif /* CORTEX_A35_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h new file mode 100644 index 0000000..2b8db14 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A510_H +#define CORTEX_A510_H + +#define CORTEX_A510_MIDR U(0x410FD460) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT U(19) +#define CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE U(1) +#define CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT U(23) +#define CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT U(46) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A510_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * Complex auxiliary control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CMPXACTLR_EL1 S3_0_C15_C1_3 + +/******************************************************************************* + * Auxiliary control register specific definitions + ******************************************************************************/ +#define CORTEX_A510_CPUACTLR_EL1 S3_0_C15_C1_0 + +#endif /* CORTEX_A510_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h new file mode 100644 index 0000000..54e646c --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A53_H +#define CORTEX_A53_H + +#include + +/* Cortex-A53 midr for revision 0 */ +#define CORTEX_A53_MIDR U(0x410FD030) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A53_ECTLR_SMP_BIT (ULL(1) << 6) + +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_CPU_RET_CTRL_SHIFT) + +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT U(3) +#define CORTEX_A53_ECTLR_FPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A53_ECTLR_FPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A53_CPUACTLR_EL1_ENDCCASCI_SHIFT U(44) +#define CORTEX_A53_CPUACTLR_EL1_ENDCCASCI (ULL(1) << CORTEX_A53_CPUACTLR_EL1_ENDCCASCI_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_RADIS_SHIFT U(27) +#define CORTEX_A53_CPUACTLR_EL1_RADIS (ULL(3) << CORTEX_A53_CPUACTLR_EL1_RADIS_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_L1RADIS_SHIFT U(25) +#define CORTEX_A53_CPUACTLR_EL1_L1RADIS (ULL(3) << CORTEX_A53_CPUACTLR_EL1_L1RADIS_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_DTAH_SHIFT U(24) +#define CORTEX_A53_CPUACTLR_EL1_DTAH (ULL(1) << CORTEX_A53_CPUACTLR_EL1_DTAH_SHIFT) +#define CORTEX_A53_CPUACTLR_EL1_L1PCTL_SHIFT U(13) +#define CORTEX_A53_CPUACTLR_EL1_L1PCTL (ULL(7) << CORTEX_A53_CPUACTLR_EL1_L1PCTL_SHIFT) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ACTLR_EL1 S3_1_C15_C0_0 + +#define CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN (U(1) << 14) +#define CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH (U(1) << 3) +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2ECTLR_EL1 S3_1_C11_C0_3 + +#define CORTEX_A53_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A53_L2ECTLR_RET_CTRL_MASK (U(0x7) << L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A53_L2MERRSR_EL1 S3_1_C15_C2_3 + +/******************************************************************************* + * Helper function to access a53_cpuectlr_el1 register on Cortex-A53 CPUs + ******************************************************************************/ +#ifndef __ASSEMBLER__ +DEFINE_RENAME_SYSREG_RW_FUNCS(a53_cpuectlr_el1, CORTEX_A53_ECTLR_EL1) +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A53_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h new file mode 100644 index 0000000..60ed957 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A55_H +#define CORTEX_A55_H + +#include + +/* Cortex-A55 MIDR for revision 0 */ +#define CORTEX_A55_MIDR U(0x410fd050) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A55_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define CORTEX_A55_CPUECTLR_EL1_L1WSCTL (ULL(3) << 25) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_WRITE_STREAMING (ULL(1) << 24) +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE (ULL(1) << 31) +#define CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS (ULL(1) << 49) + +/******************************************************************************* + * CPU Identification register specific definitions. + ******************************************************************************/ +#define CORTEX_A55_CLIDR_EL1 S3_1_C0_C0_1 + +#define CORTEX_A55_CLIDR_EL1_CTYPE3 (ULL(7) << 6) + +/* Definitions of register field mask in CORTEX_A55_CPUPWRCTLR_EL1 */ +#define CORTEX_A55_CORE_PWRDN_EN_MASK U(0x1) + +/* Instruction patching registers */ +#define CPUPSELR_EL3 S3_6_C15_C8_0 +#define CPUPCR_EL3 S3_6_C15_C8_1 +#define CPUPOR_EL3 S3_6_C15_C8_2 +#define CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* CORTEX_A55_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h new file mode 100644 index 0000000..dc40e31 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A57_H +#define CORTEX_A57_H + +#include + +/* Cortex-A57 midr for revision 0 */ +#define CORTEX_A57_MIDR U(0x410FD070) + +/* Retention timer tick definitions */ +#define RETENTION_ENTRY_TICKS_2 U(0x1) +#define RETENTION_ENTRY_TICKS_8 U(0x2) +#define RETENTION_ENTRY_TICKS_32 U(0x3) +#define RETENTION_ENTRY_TICKS_64 U(0x4) +#define RETENTION_ENTRY_TICKS_128 U(0x5) +#define RETENTION_ENTRY_TICKS_256 U(0x6) +#define RETENTION_ENTRY_TICKS_512 U(0x7) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A57_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_ECTLR_CPU_RET_CTRL_MASK (ULL(0x7) << CORTEX_A57_ECTLR_CPU_RET_CTRL_SHIFT) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_DMB (ULL(1) << 59) +#define CORTEX_A57_CPUACTLR_EL1_DIS_DMB_NULLIFICATION (ULL(1) << 58) +#define CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A57_CPUACTLR_EL1_GRE_NGRE_AS_NGNRE (ULL(1) << 54) +#define CORTEX_A57_CPUACTLR_EL1_DIS_OVERREAD (ULL(1) << 52) +#define CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH (ULL(1) << 38) +#define CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH (ULL(1) << 32) +#define CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING (ULL(3) << 27) +#define CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD (ULL(1) << 24) +#define CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING (ULL(3) << 25) +#define CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR (ULL(1) << 4) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2CTLR_EL1 S3_1_C11_C0_2 + +#define CORTEX_A57_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A57_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) + +#define CORTEX_A57_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A57_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +#define CORTEX_A57_L2_ECC_PARITY_PROTECTION_BIT (U(1) << 21) + +/******************************************************************************* + * L2 Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2ECTLR_EL1 S3_1_C11_C0_3 + +#define CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT U(0) +#define CORTEX_A57_L2ECTLR_RET_CTRL_MASK (U(0x7) << CORTEX_A57_L2ECTLR_RET_CTRL_SHIFT) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A57_L2MERRSR_EL1 S3_1_C15_C2_3 + +#endif /* CORTEX_A57_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h new file mode 100644 index 0000000..0df34c9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A65_H +#define CORTEX_A65_H + +#include + +#define CORTEX_A65_MIDR U(0x410FD060) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ + +#define CORTEX_A65_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A65_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* CORTEX_A65_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h new file mode 100644 index 0000000..bd4a881 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A65AE_H +#define CORTEX_A65AE_H + +#include + +#define CORTEX_A65AE_MIDR U(0x410FD430) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65AE_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions + ******************************************************************************/ +#define CORTEX_A65AE_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ + +#define CORTEX_A65AE_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A65AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* CORTEX_A65AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h new file mode 100644 index 0000000..09614ee --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A710_H +#define CORTEX_A710_H + +#define CORTEX_A710_MIDR U(0x410FD470) + +/* Cortex-A710 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A710_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_A710_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A710_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR_EL1 S3_0_C15_C1_0 +#define CORTEX_A710_CPUACTLR_EL1_BIT_46 (ULL(1) << 46) +#define CORTEX_A710_CPUACTLR_EL1_BIT_22 (ULL(1) << 22) + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR2_EL1 S3_0_C15_C1_1 + +/******************************************************************************* + * CPU Auxiliary Control register 5 specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define CORTEX_A710_CPUACTLR5_EL1_BIT_13 (ULL(1) << 13) +#define CORTEX_A710_CPUACTLR5_EL1_BIT_44 (ULL(1) << 44) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A710_CPUECTLR2_EL1 S3_0_C15_C1_5 +#define CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(9) +#define CPUECTLR2_EL1_PF_MODE_LSB U(11) +#define CPUECTLR2_EL1_PF_MODE_WIDTH U(4) + +#endif /* CORTEX_A710_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h new file mode 100644 index 0000000..1777645 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A72_H +#define CORTEX_A72_H + +#include + +/* Cortex-A72 midr for revision 0 */ +#define CORTEX_A72_MIDR U(0x410FD080) + +/* Cortex-A72 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A72_BHB_LOOP_COUNT U(8) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_ECTLR_EL1 S3_1_C15_C2_1 + +#define CORTEX_A72_ECTLR_SMP_BIT (ULL(1) << 6) +#define CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT (ULL(1) << 38) +#define CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK (ULL(0x3) << 35) +#define CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK (ULL(0x3) << 32) + +/******************************************************************************* + * CPU Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_MERRSR_EL1 S3_1_C15_C2_2 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_CPUACTLR_EL1 S3_1_C15_C2_0 + +#define CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH (ULL(1) << 56) +#define CORTEX_A72_CPUACTLR_EL1_DIS_LOAD_PASS_STORE (ULL(1) << 55) +#define CORTEX_A72_CPUACTLR_EL1_NO_ALLOC_WBWA (ULL(1) << 49) +#define CORTEX_A72_CPUACTLR_EL1_DCC_AS_DCCI (ULL(1) << 44) +#define CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH (ULL(1) << 32) + +/******************************************************************************* + * L2 Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2ACTLR_EL1 S3_1_C15_C0_0 + +#define CORTEX_A72_L2ACTLR_FORCE_TAG_BANK_CLK_ACTIVE (ULL(1) << 28) +#define CORTEX_A72_L2ACTLR_FORCE_L2_LOGIC_CLK_ACTIVE (ULL(1) << 27) +#define CORTEX_A72_L2ACTLR_FORCE_L2_GIC_TIMER_RCG_CLK_ACTIVE (ULL(1) << 26) +#define CORTEX_A72_L2ACTLR_ENABLE_UNIQUE_CLEAN (ULL(1) << 14) +#define CORTEX_A72_L2ACTLR_DISABLE_DSB_WITH_NO_DVM_SYNC (ULL(1) << 11) +#define CORTEX_A72_L2ACTLR_DISABLE_DVM_CMO_BROADCAST (ULL(1) << 8) +#define CORTEX_A72_L2ACTLR_ENABLE_HAZARD_DETECT_TIMEOUT (ULL(1) << 7) +#define CORTEX_A72_L2ACTLR_DISABLE_ACE_SH_OR_CHI (ULL(1) << 6) + +/******************************************************************************* + * L2 Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2CTLR_EL1 S3_1_C11_C0_2 + +#define CORTEX_A72_L2CTLR_DATA_RAM_LATENCY_SHIFT U(0) +#define CORTEX_A72_L2CTLR_DATA_RAM_SETUP_SHIFT U(5) +#define CORTEX_A72_L2CTLR_TAG_RAM_LATENCY_SHIFT U(6) +#define CORTEX_A72_L2CTLR_TAG_RAM_SETUP_SHIFT U(9) + +#define CORTEX_A72_L2_DATA_RAM_LATENCY_MASK U(0x7) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_MASK U(0x7) +#define CORTEX_A72_L2_DATA_RAM_LATENCY_3_CYCLES U(0x2) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_2_CYCLES U(0x1) +#define CORTEX_A72_L2_TAG_RAM_LATENCY_3_CYCLES U(0x2) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A72_L2MERRSR_EL1 S3_1_C15_C2_3 + +#endif /* CORTEX_A72_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h new file mode 100644 index 0000000..271a333 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A73_H +#define CORTEX_A73_H + +#include + +/* Cortex-A73 midr for revision 0 */ +#define CORTEX_A73_MIDR U(0x410FD090) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_CPUECTLR_EL1 S3_1_C15_C2_1 /* Instruction def. */ + +#define CORTEX_A73_CPUECTLR_SMP_BIT (ULL(1) << 6) + +/******************************************************************************* + * L2 Memory Error Syndrome register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_L2MERRSR_EL1 S3_1_C15_C2_3 /* Instruction def. */ + +/******************************************************************************* + * CPU implementation defined register specific definitions. + ******************************************************************************/ +#define CORTEX_A73_IMP_DEF_REG1 S3_0_C15_C0_0 + +#define CORTEX_A73_IMP_DEF_REG1_DISABLE_LOAD_PASS_STORE (ULL(1) << 3) + +#define CORTEX_A73_DIAGNOSTIC_REGISTER S3_0_C15_C0_1 + +#define CORTEX_A73_IMP_DEF_REG2 S3_0_C15_C0_2 + +/******************************************************************************* + * Helper function to access a73_cpuectlr_el1 register on Cortex-A73 CPUs + ******************************************************************************/ +#ifndef __ASSEMBLER__ +DEFINE_RENAME_SYSREG_RW_FUNCS(a73_cpuectlr_el1, CORTEX_A73_CPUECTLR_EL1) +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A73_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h new file mode 100644 index 0000000..e5ca1ba --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A75_H +#define CORTEX_A75_H + +#include + +/* Cortex-A75 MIDR */ +#define CORTEX_A75_MIDR U(0x410fd0a0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A75_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A75_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A75_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE (ULL(1) << 35) + +/* Definitions of register field mask in CORTEX_A75_CPUPWRCTLR_EL1 */ +#define CORTEX_A75_CORE_PWRDN_EN_MASK U(0x1) + +#define CORTEX_A75_ACTLR_AMEN_BIT (ULL(1) << 4) + +/* + * The Cortex-A75 core implements five counters, 0-4. Events 0, 1, 2, are + * fixed and are enabled (Group 0). Events 3 and 4 (Group 1) are + * programmable by programming the appropriate Event count bits in + * CPUAMEVTYPER register and are disabled by default. Platforms may + * enable this with suitable programming. + */ +#define CORTEX_A75_AMU_NR_COUNTERS U(5) +#define CORTEX_A75_AMU_GROUP0_MASK U(0x7) +#define CORTEX_A75_AMU_GROUP1_MASK (U(0) << 3) + +#ifndef __ASSEMBLER__ +#include + +uint64_t cortex_a75_amu_cnt_read(int idx); +void cortex_a75_amu_cnt_write(int idx, uint64_t val); +unsigned int cortex_a75_amu_read_cpuamcntenset_el0(void); +unsigned int cortex_a75_amu_read_cpuamcntenclr_el0(void); +void cortex_a75_amu_write_cpuamcntenset_el0(unsigned int mask); +void cortex_a75_amu_write_cpuamcntenclr_el0(unsigned int mask); +#endif /* __ASSEMBLER__ */ + +#endif /* CORTEX_A75_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h new file mode 100644 index 0000000..0c8b29e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A76_H +#define CORTEX_A76_H + +#include + +/* Cortex-A76 MIDR for revision 0 */ +#define CORTEX_A76_MIDR U(0x410fd0b0) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A76_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A76_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define CORTEX_A76_CPUECTLR_EL1_WS_THR_L2 (ULL(3) << 24) +#define CORTEX_A76_CPUECTLR_EL1_BIT_51 (ULL(1) << 51) + +/******************************************************************************* + * Definitions for CORTEX_A76_CPUECTLR_EL1 register related to Write-streaming. + ******************************************************************************/ +#define WS_THR_L2_256B (U(0) << 24) +#define WS_THR_L2_4KB (U(1) << 24) +#define WS_THR_L2_8KB (U(2) << 24) +#define WS_THR_L2_DISABLE (U(3) << 24) + +#define WS_THR_L3_768B (U(0) << 22) +#define WS_THR_L3_16KB (U(1) << 22) +#define WS_THR_L3_32KB (U(2) << 22) +#define WS_THR_L3_DISABLE (U(3) << 22) + +#define WS_THR_L4_16KB (U(0) << 20) +#define WS_THR_L4_64KB (U(1) << 20) +#define WS_THR_L4_128KB (U(2) << 20) +#define WS_THR_L4_DISABLE (U(3) << 20) + +#define WS_THR_DRAM_64KB (U(0) << 18) +/* 1MB, for memory designated as outer-allocate.*/ +#define WS_THR_DRAM_ALLOC_1MB (U(1) << 18) +/* 1MB, allocating irrespective of outer-allocation designation. */ +#define WS_THR_DRAM_1MB (U(2) << 18) +#define WS_THR_DRAM_DISABLE (U(3) << 18) + +#define WS_THR_DISABLE_ALL (WS_THR_L2_DISABLE | WS_THR_L3_DISABLE | WS_THR_L4_DISABLE | \ + WS_THR_DRAM_DISABLE) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION (ULL(1) << 6) + +#define CORTEX_A76_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define CORTEX_A76_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define CORTEX_A76_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) + +#define CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE (ULL(1) << 16) + +#define CORTEX_A76_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define CORTEX_A76_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + + +/* Definitions of register field mask in CORTEX_A76_CPUPWRCTLR_EL1 */ +#define CORTEX_A76_CORE_PWRDN_EN_MASK U(0x1) + +#endif /* CORTEX_A76_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h new file mode 100644 index 0000000..0d30f70 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A76AE_H +#define CORTEX_A76AE_H + +#include + +/* Cortex-A76AE MIDR for revision 0 */ +#define CORTEX_A76AE_MIDR U(0x410FD0E0) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A76AE_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A76AE_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in CORTEX_A76AE_CPUPWRCTLR_EL1 */ +#define CORTEX_A76AE_CORE_PWRDN_EN_MASK U(0x1) + +#define CORTEX_A76AE_CPUECTLR_EL1 S3_0_C15_C1_4 + +#endif /* CORTEX_A76AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h new file mode 100644 index 0000000..4a87168 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A77_H +#define CORTEX_A77_H + +#include + +/* Cortex-A77 MIDR */ +#define CORTEX_A77_MIDR U(0x410FD0D0) + +/* Cortex-A77 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A77_BHB_LOOP_COUNT U(24) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A77_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A77_ACTLR2_EL1 S3_0_C15_C1_1 +#define CORTEX_A77_ACTLR2_EL1_BIT_2 (ULL(1) << 2) + +#define CORTEX_A77_CPUPSELR_EL3 S3_6_C15_C8_0 +#define CORTEX_A77_CPUPCR_EL3 S3_6_C15_C8_1 +#define CORTEX_A77_CPUPOR_EL3 S3_6_C15_C8_2 +#define CORTEX_A77_CPUPMR_EL3 S3_6_C15_C8_3 +#define CORTEX_A77_CPUPOR2_EL3 S3_6_C15_C8_4 +#define CORTEX_A77_CPUPMR2_EL3 S3_6_C15_C8_5 + +#endif /* CORTEX_A77_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h new file mode 100644 index 0000000..31da99e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78_H +#define CORTEX_A78_H + +#include + +#define CORTEX_A78_MIDR U(0x410FD410) + +/* Cortex-A78 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_A78_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) +#define CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV ULL(3) +#define CPUECTLR_EL1_PF_MODE_LSB U(6) +#define CPUECTLR_EL1_PF_MODE_WIDTH U(2) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A78_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_ACTLR_TAM_BIT (ULL(1) << 30) + +#define CORTEX_A78_ACTLR2_EL1 S3_0_C15_C1_1 +#define CORTEX_A78_ACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define CORTEX_A78_ACTLR2_EL1_BIT_1 (ULL(1) << 1) +#define CORTEX_A78_ACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define CORTEX_A78_ACTLR2_EL1_BIT_40 (ULL(1) << 40) + +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR0_EL0 S3_3_C15_C2_4 +#define CPUAMCNTENSET0_EL0 S3_3_C15_C2_5 +#define CPUAMCNTENCLR1_EL0 S3_3_C15_C3_0 +#define CPUAMCNTENSET1_EL0 S3_3_C15_C3_1 + +#define CORTEX_A78_AMU_GROUP0_MASK U(0xF) +#define CORTEX_A78_AMU_GROUP1_MASK U(0x7) + +#endif /* CORTEX_A78_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h new file mode 100644 index 0000000..7587efc --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * Copyright (c) 2021-2023, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78_AE_H +#define CORTEX_A78_AE_H + +#include + +#define CORTEX_A78_AE_MIDR U(0x410FD420) + +/* Cortex-A78AE loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78_AE_BHB_LOOP_COUNT U(32) + +#define CORTEX_A78_AE_ACTLR_CLUSTERPMUEN_BIT (ULL(1) << 12) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78_AE_CPUECTLR_EL1 CORTEX_A78_CPUECTLR_EL1 +#define CORTEX_A78_AE_CPUECTLR_EL1_BIT_8 CORTEX_A78_CPUECTLR_EL1_BIT_8 + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define CORTEX_A78_AE_ACTLR2_EL1 CORTEX_A78_ACTLR2_EL1 +#define CORTEX_A78_AE_ACTLR2_EL1_BIT_0 CORTEX_A78_ACTLR2_EL1_BIT_0 +#define CORTEX_A78_AE_ACTLR2_EL1_BIT_40 CORTEX_A78_ACTLR2_EL1_BIT_40 + +/******************************************************************************* +* CPU Auxiliary Control register 5 specific definitions. + ******************************************************************************/ +#define CORTEX_A78_AE_ACTLR5_EL1 S3_0_C15_C9_0 +#define CORTEX_A78_AE_ACTLR5_EL1_BIT_55 (ULL(1) << 55) +#define CORTEX_A78_AE_ACTLR5_EL1_BIT_56 (ULL(1) << 56) + +#endif /* CORTEX_A78_AE_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h new file mode 100644 index 0000000..34c964f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_A78C_H +#define CORTEX_A78C_H + + +#define CORTEX_A78C_MIDR U(0x410FD4B1) + +#define CORTEX_A78C_ACTLR_CLUSTERPMUEN_BIT (ULL(1) << 12) + +/* Cortex-A76 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_A78C_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define CORTEX_A78C_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_A78C_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT U(1) + +#endif /* CORTEX_A78C_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h new file mode 100644 index 0000000..82022e9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_HAYES_H +#define CORTEX_HAYES_H + +#define CORTEX_HAYES_MIDR U(0x410FD800) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_HAYES_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_HAYES_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_HAYES_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h new file mode 100644 index 0000000..8b59fd9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_HUNTER_H +#define CORTEX_HUNTER_H + +#define CORTEX_HUNTER_MIDR U(0x410FD810) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_HUNTER_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_HUNTER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_HUNTER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_HUNTER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h new file mode 100644 index 0000000..4e0dc86 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_MAKALU_H +#define CORTEX_MAKALU_H + +#define CORTEX_MAKALU_MIDR U(0x410FD4D0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_MAKALU_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_MAKALU_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h new file mode 100644 index 0000000..a0d788e --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_MAKALU_ELP_ARM_H +#define CORTEX_MAKALU_ELP_ARM_H + +#define CORTEX_MAKALU_ELP_ARM_MIDR U(0x410FD4E0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_ELP_ARM_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* CORTEX_MAKALU_ELP_ARM_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h new file mode 100644 index 0000000..62530e2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CORTEX_X2_H +#define CORTEX_X2_H + +#define CORTEX_X2_MIDR U(0x410FD480) + +/* Cortex-X2 loop count for CVE-2022-23960 mitigation */ +#define CORTEX_X2_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUECTLR_EL1 S3_0_C15_C1_4 +#define CORTEX_X2_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Extended Control register 2 specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUECTLR2_EL1 S3_0_C15_C1_5 + +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT U(11) +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH U(4) +#define CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(0x9) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define CORTEX_X2_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control Register 5 definitions + ******************************************************************************/ +#define CORTEX_X2_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define CORTEX_X2_CPUACTLR5_EL1_BIT_17 (ULL(1) << 17) + +/******************************************************************************* + * CPU Implementation Specific Selected Instruction registers + ******************************************************************************/ +#define CORTEX_X2_IMP_CPUPSELR_EL3 S3_6_C15_C8_0 +#define CORTEX_X2_IMP_CPUPCR_EL3 S3_6_C15_C8_1 +#define CORTEX_X2_IMP_CPUPOR_EL3 S3_6_C15_C8_2 +#define CORTEX_X2_IMP_CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* CORTEX_X2_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S b/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S new file mode 100644 index 0000000..92e65ae --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S @@ -0,0 +1,314 @@ +/* + * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CPU_MACROS_S +#define CPU_MACROS_S + +#include +#include +#include + +#define CPU_IMPL_PN_MASK (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | \ + (MIDR_PN_MASK << MIDR_PN_SHIFT) + +/* The number of CPU operations allowed */ +#define CPU_MAX_PWR_DWN_OPS 2 + +/* Special constant to specify that CPU has no reset function */ +#define CPU_NO_RESET_FUNC 0 + +#define CPU_NO_EXTRA1_FUNC 0 +#define CPU_NO_EXTRA2_FUNC 0 +#define CPU_NO_EXTRA3_FUNC 0 + +/* Word size for 64-bit CPUs */ +#define CPU_WORD_SIZE 8 + +/* + * Whether errata status needs reporting. Errata status is printed in debug + * builds for both BL1 and BL31 images. + */ +#if (defined(IMAGE_BL1) || defined(IMAGE_BL31)) && DEBUG +# define REPORT_ERRATA 1 +#else +# define REPORT_ERRATA 0 +#endif + + + .equ CPU_MIDR_SIZE, CPU_WORD_SIZE + .equ CPU_EXTRA1_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_EXTRA2_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_EXTRA3_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_E_HANDLER_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_RESET_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_PWR_DWN_OPS_SIZE, CPU_WORD_SIZE * CPU_MAX_PWR_DWN_OPS + .equ CPU_ERRATA_FUNC_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_LOCK_SIZE, CPU_WORD_SIZE + .equ CPU_ERRATA_PRINTED_SIZE, CPU_WORD_SIZE + .equ CPU_REG_DUMP_SIZE, CPU_WORD_SIZE + +#ifndef IMAGE_AT_EL3 + .equ CPU_RESET_FUNC_SIZE, 0 +#endif + +/* The power down core and cluster is needed only in BL31 */ +#ifndef IMAGE_BL31 + .equ CPU_PWR_DWN_OPS_SIZE, 0 +#endif + +/* Fields required to print errata status. */ +#if !REPORT_ERRATA + .equ CPU_ERRATA_FUNC_SIZE, 0 +#endif + +/* Only BL31 requieres mutual exclusion and printed flag. */ +#if !(REPORT_ERRATA && defined(IMAGE_BL31)) + .equ CPU_ERRATA_LOCK_SIZE, 0 + .equ CPU_ERRATA_PRINTED_SIZE, 0 +#endif + +#if !defined(IMAGE_BL31) || !CRASH_REPORTING + .equ CPU_REG_DUMP_SIZE, 0 +#endif + +/* + * Define the offsets to the fields in cpu_ops structure. + * Every offset is defined based in the offset and size of the previous + * field. + */ + .equ CPU_MIDR, 0 + .equ CPU_RESET_FUNC, CPU_MIDR + CPU_MIDR_SIZE + .equ CPU_EXTRA1_FUNC, CPU_RESET_FUNC + CPU_RESET_FUNC_SIZE + .equ CPU_EXTRA2_FUNC, CPU_EXTRA1_FUNC + CPU_EXTRA1_FUNC_SIZE + .equ CPU_EXTRA3_FUNC, CPU_EXTRA2_FUNC + CPU_EXTRA2_FUNC_SIZE + .equ CPU_E_HANDLER_FUNC, CPU_EXTRA3_FUNC + CPU_EXTRA3_FUNC_SIZE + .equ CPU_PWR_DWN_OPS, CPU_E_HANDLER_FUNC + CPU_E_HANDLER_FUNC_SIZE + .equ CPU_ERRATA_FUNC, CPU_PWR_DWN_OPS + CPU_PWR_DWN_OPS_SIZE + .equ CPU_ERRATA_LOCK, CPU_ERRATA_FUNC + CPU_ERRATA_FUNC_SIZE + .equ CPU_ERRATA_PRINTED, CPU_ERRATA_LOCK + CPU_ERRATA_LOCK_SIZE + .equ CPU_REG_DUMP, CPU_ERRATA_PRINTED + CPU_ERRATA_PRINTED_SIZE + .equ CPU_OPS_SIZE, CPU_REG_DUMP + CPU_REG_DUMP_SIZE + + /* + * Write given expressions as quad words + * + * _count: + * Write at least _count quad words. If the given number of + * expressions is less than _count, repeat the last expression to + * fill _count quad words in total + * _rest: + * Optional list of expressions. _this is for parameter extraction + * only, and has no significance to the caller + * + * Invoked as: + * fill_constants 2, foo, bar, blah, ... + */ + .macro fill_constants _count:req, _this, _rest:vararg + .ifgt \_count + /* Write the current expression */ + .ifb \_this + .error "Nothing to fill" + .endif + .quad \_this + + /* Invoke recursively for remaining expressions */ + .ifnb \_rest + fill_constants \_count-1, \_rest + .else + fill_constants \_count-1, \_this + .endif + .endif + .endm + + /* + * Declare CPU operations + * + * _name: + * Name of the CPU for which operations are being specified + * _midr: + * Numeric value expected to read from CPU's MIDR + * _resetfunc: + * Reset function for the CPU. If there's no CPU reset function, + * specify CPU_NO_RESET_FUNC + * _extra1: + * This is a placeholder for future per CPU operations. Currently, + * some CPUs use this entry to set a test function to determine if + * the workaround for CVE-2017-5715 needs to be applied or not. + * _extra2: + * This is a placeholder for future per CPU operations. Currently + * some CPUs use this entry to set a function to disable the + * workaround for CVE-2018-3639. + * _extra3: + * This is a placeholder for future per CPU operations. Currently, + * some CPUs use this entry to set a test function to determine if + * the workaround for CVE-2022-23960 needs to be applied or not. + * _e_handler: + * This is a placeholder for future per CPU exception handlers. + * _power_down_ops: + * Comma-separated list of functions to perform power-down + * operatios on the CPU. At least one, and up to + * CPU_MAX_PWR_DWN_OPS number of functions may be specified. + * Starting at power level 0, these functions shall handle power + * down at subsequent power levels. If there aren't exactly + * CPU_MAX_PWR_DWN_OPS functions, the last specified one will be + * used to handle power down at subsequent levels + */ + .macro declare_cpu_ops_base _name:req, _midr:req, _resetfunc:req, \ + _extra1:req, _extra2:req, _extra3:req, _e_handler:req, _power_down_ops:vararg + .section cpu_ops, "a" + .align 3 + .type cpu_ops_\_name, %object + .quad \_midr +#if defined(IMAGE_AT_EL3) + .quad \_resetfunc +#endif + .quad \_extra1 + .quad \_extra2 + .quad \_extra3 + .quad \_e_handler +#ifdef IMAGE_BL31 + /* Insert list of functions */ + fill_constants CPU_MAX_PWR_DWN_OPS, \_power_down_ops +#endif + +#if REPORT_ERRATA + .ifndef \_name\()_cpu_str + /* + * Place errata reported flag, and the spinlock to arbitrate access to + * it in the data section. + */ + .pushsection .data + define_asm_spinlock \_name\()_errata_lock + \_name\()_errata_reported: + .word 0 + .popsection + + /* Place CPU string in rodata */ + .pushsection .rodata + \_name\()_cpu_str: + .asciz "\_name" + .popsection + .endif + + /* + * Mandatory errata status printing function for CPUs of + * this class. + */ + .quad \_name\()_errata_report + +#ifdef IMAGE_BL31 + /* Pointers to errata lock and reported flag */ + .quad \_name\()_errata_lock + .quad \_name\()_errata_reported +#endif +#endif + +#if defined(IMAGE_BL31) && CRASH_REPORTING + .quad \_name\()_cpu_reg_dump +#endif + .endm + + .macro declare_cpu_ops _name:req, _midr:req, _resetfunc:req, \ + _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, 0, 0, 0, 0, \ + \_power_down_ops + .endm + + .macro declare_cpu_ops_eh _name:req, _midr:req, _resetfunc:req, \ + _e_handler:req, _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ + 0, 0, 0, \_e_handler, \_power_down_ops + .endm + + .macro declare_cpu_ops_wa _name:req, _midr:req, \ + _resetfunc:req, _extra1:req, _extra2:req, \ + _extra3:req, _power_down_ops:vararg + declare_cpu_ops_base \_name, \_midr, \_resetfunc, \ + \_extra1, \_extra2, \_extra3, 0, \_power_down_ops + .endm + +#if REPORT_ERRATA + /* + * Print status of a CPU errata + * + * _chosen: + * Identifier indicating whether or not a CPU errata has been + * compiled in. + * _cpu: + * Name of the CPU + * _id: + * Errata identifier + * _rev_var: + * Register containing the combined value CPU revision and variant + * - typically the return value of cpu_get_rev_var + */ + .macro report_errata _chosen, _cpu, _id, _rev_var=x8 + /* Stash a string with errata ID */ + .pushsection .rodata + \_cpu\()_errata_\_id\()_str: + .asciz "\_id" + .popsection + + /* Check whether errata applies */ + mov x0, \_rev_var + /* Shall clobber: x0-x7 */ + bl check_errata_\_id + + .ifeq \_chosen + /* + * Errata workaround has not been compiled in. If the errata would have + * applied had it been compiled in, print its status as missing. + */ + cbz x0, 900f + mov x0, #ERRATA_MISSING + .endif +900: + adr x1, \_cpu\()_cpu_str + adr x2, \_cpu\()_errata_\_id\()_str + bl errata_print_msg + .endm +#endif + + /* + * This macro is used on some CPUs to detect if they are vulnerable + * to CVE-2017-5715. + */ + .macro cpu_check_csv2 _reg _label + mrs \_reg, id_aa64pfr0_el1 + ubfx \_reg, \_reg, #ID_AA64PFR0_CSV2_SHIFT, #ID_AA64PFR0_CSV2_LENGTH + /* + * If the field equals 1, branch targets trained in one context cannot + * affect speculative execution in a different context. + * + * If the field equals 2, it means that the system is also aware of + * SCXTNUM_ELx register contexts. We aren't using them in the TF, so we + * expect users of the registers to do the right thing. + * + * Only apply mitigations if the value of this field is 0. + */ +#if ENABLE_ASSERTIONS + cmp \_reg, #3 /* Only values 0 to 2 are expected */ + ASM_ASSERT(lo) +#endif + + cmp \_reg, #0 + bne \_label + .endm + + /* + * 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 + +#endif /* CPU_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h b/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h new file mode 100644 index 0000000..463f890 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CPUAMU_H +#define CPUAMU_H + +/******************************************************************************* + * CPU Activity Monitor Unit register specific definitions. + ******************************************************************************/ +#define CPUAMCNTENCLR_EL0 S3_3_C15_C9_7 +#define CPUAMCNTENSET_EL0 S3_3_C15_C9_6 +#define CPUAMCFGR_EL0 S3_3_C15_C10_6 +#define CPUAMUSERENR_EL0 S3_3_C15_C10_7 + +/* Activity Monitor Event Counter Registers */ +#define CPUAMEVCNTR0_EL0 S3_3_C15_C9_0 +#define CPUAMEVCNTR1_EL0 S3_3_C15_C9_1 +#define CPUAMEVCNTR2_EL0 S3_3_C15_C9_2 +#define CPUAMEVCNTR3_EL0 S3_3_C15_C9_3 +#define CPUAMEVCNTR4_EL0 S3_3_C15_C9_4 + +/* Activity Monitor Event Type Registers */ +#define CPUAMEVTYPER0_EL0 S3_3_C15_C10_0 +#define CPUAMEVTYPER1_EL0 S3_3_C15_C10_1 +#define CPUAMEVTYPER2_EL0 S3_3_C15_C10_2 +#define CPUAMEVTYPER3_EL0 S3_3_C15_C10_3 +#define CPUAMEVTYPER4_EL0 S3_3_C15_C10_4 + +#ifndef __ASSEMBLER__ +#include + +uint64_t cpuamu_cnt_read(unsigned int idx); +void cpuamu_cnt_write(unsigned int idx, uint64_t val); +unsigned int cpuamu_read_cpuamcntenset_el0(void); +unsigned int cpuamu_read_cpuamcntenclr_el0(void); +void cpuamu_write_cpuamcntenset_el0(unsigned int mask); +void cpuamu_write_cpuamcntenclr_el0(unsigned int mask); + +int midr_match(unsigned int cpu_midr); +void cpuamu_context_save(unsigned int nr_counters); +void cpuamu_context_restore(unsigned int nr_counters); + +#endif /* __ASSEMBLER__ */ + +#endif /* CPUAMU_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h b/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h new file mode 100644 index 0000000..826ab8f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/denver.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DENVER_H +#define DENVER_H + +/* MIDR values for Denver */ +#define DENVER_MIDR_PN0 U(0x4E0F0000) +#define DENVER_MIDR_PN1 U(0x4E0F0010) +#define DENVER_MIDR_PN2 U(0x4E0F0020) +#define DENVER_MIDR_PN3 U(0x4E0F0030) +#define DENVER_MIDR_PN4 U(0x4E0F0040) +#define DENVER_MIDR_PN5 U(0x4E0F0050) +#define DENVER_MIDR_PN6 U(0x4E0F0060) +#define DENVER_MIDR_PN7 U(0x4E0F0070) +#define DENVER_MIDR_PN8 U(0x4E0F0080) +#define DENVER_MIDR_PN9 U(0x4E0F0090) + +/* Implementer code in the MIDR register */ +#define DENVER_IMPL U(0x4E) + +/* CPU state ids - implementation defined */ +#define DENVER_CPU_STATE_POWER_DOWN U(0x3) + +/* Speculative store buffering */ +#define DENVER_CPU_DIS_SSB_EL3 (U(1) << 11) +#define DENVER_PN4_CPU_DIS_SSB_EL3 (U(1) << 18) + +/* Speculative memory disambiguation */ +#define DENVER_CPU_DIS_MD_EL3 (U(1) << 9) +#define DENVER_PN4_CPU_DIS_MD_EL3 (U(1) << 17) + +/* Core power management states */ +#define DENVER_CPU_PMSTATE_C1 U(0x1) +#define DENVER_CPU_PMSTATE_C6 U(0x6) +#define DENVER_CPU_PMSTATE_C7 U(0x7) +#define DENVER_CPU_PMSTATE_MASK U(0xF) + +/* ACTRL_ELx bits to enable dual execution*/ +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL2 (ULL(1) << 9) +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL3 (ULL(1) << 9) +#define DENVER_CPU_ENABLE_DUAL_EXEC_EL1 (U(1) << 4) + +/* + * ACTLR_EL3 bit to enable counting of events in the + * NVIDIA specific Performance Monitors extension. + */ +#define DENVER_CPU_ENABLE_SPME (U(1) << 6) + +#ifndef __ASSEMBLER__ + +/* Disable Dynamic Code Optimisation */ +void denver_disable_dco(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* DENVER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h b/arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h new file mode 100644 index 0000000..0969acf --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DSU_DEF_H +#define DSU_DEF_H + +#include + +/******************************************************************** + * DSU Cluster Configuration registers definitions + ********************************************************************/ +#define CLUSTERCFR_EL1 S3_0_C15_C3_0 + +#define CLUSTERCFR_ACP_SHIFT U(11) + +/******************************************************************** + * DSU Cluster Main Revision ID registers definitions + ********************************************************************/ +#define CLUSTERIDR_EL1 S3_0_C15_C3_1 + +#define CLUSTERIDR_REV_SHIFT U(0) +#define CLUSTERIDR_REV_BITS U(4) +#define CLUSTERIDR_VAR_SHIFT U(4) +#define CLUSTERIDR_VAR_BITS U(4) + +/******************************************************************** + * DSU Cluster Auxiliary Control registers definitions + ********************************************************************/ +#define CLUSTERACTLR_EL1 S3_0_C15_C3_3 + +#define CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING (ULL(1) << 15) + +/******************************************************************** + * Masks applied for DSU errata workarounds + ********************************************************************/ +#define DSU_ERRATA_936184_MASK (U(0x3) << 15) + +#endif /* DSU_DEF_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h b/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h new file mode 100644 index 0000000..53df587 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/generic.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserverd. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AARCH64_GENERIC_H +#define AARCH64_GENERIC_H + +#include + +/* + * 0x0 value on the MIDR implementer value is reserved for software use, + * so use an MIDR value of 0 for a default CPU library. + */ +#define AARCH64_GENERIC_MIDR U(0) + +#endif /* AARCH64_GENERIC_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h new file mode 100644 index 0000000..230ed66 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_DEMETER_H +#define NEOVERSE_DEMETER_H + +#define NEOVERSE_DEMETER_MIDR U(0x410FD4F0) + +/******************************************************************************* + * CPU Extended Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_DEMETER_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_DEMETER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* NEOVERSE_DEMETER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h new file mode 100644 index 0000000..96b4661 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_E1_H +#define NEOVERSE_E1_H + +#include + +#define NEOVERSE_E1_MIDR U(0x410FD4A0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_E1_ECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_E1_CPUACTLR_EL1 S3_0_C15_C1_0 + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ + +#define NEOVERSE_E1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_E1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT (U(1) << 0) + +#endif /* NEOVERSE_E1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h new file mode 100644 index 0000000..b6b8d8d --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N1_H +#define NEOVERSE_N1_H + +#include + +/* Neoverse N1 MIDR for revision 0 */ +#define NEOVERSE_N1_MIDR U(0x410fd0c0) + +/* Neoverse N1 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_N1_BHB_LOOP_COUNT U(24) + +/* Exception Syndrome register EC code for IC Trap */ +#define NEOVERSE_N1_EC_IC_TRAP U(0x1f) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in NEOVERSE_N1_CPUPWRCTLR_EL1 */ +#define NEOVERSE_N1_CORE_PWRDN_EN_MASK U(0x1) + +#define NEOVERSE_N1_ACTLR_AMEN_BIT (U(1) << 4) + +#define NEOVERSE_N1_AMU_NR_COUNTERS U(5) +#define NEOVERSE_N1_AMU_GROUP0_MASK U(0x1f) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define NEOVERSE_N1_WS_THR_L2_MASK (ULL(3) << 24) +#define NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT (ULL(1) << 51) +#define NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT (ULL(1) << 0) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N1_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define NEOVERSE_N1_CPUACTLR_EL1_BIT_6 (ULL(1) << 6) +#define NEOVERSE_N1_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define NEOVERSE_N1_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_11 (ULL(1) << 11) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_15 (ULL(1) << 15) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_16 (ULL(1) << 16) +#define NEOVERSE_N1_CPUACTLR2_EL1_BIT_59 (ULL(1) << 59) + +#define NEOVERSE_N1_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define NEOVERSE_N1_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + +/* Instruction patching registers */ +#define CPUPSELR_EL3 S3_6_C15_C8_0 +#define CPUPCR_EL3 S3_6_C15_C8_1 +#define CPUPOR_EL3 S3_6_C15_C8_2 +#define CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* NEOVERSE_N1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h new file mode 100644 index 0000000..0452b39 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N2_H +#define NEOVERSE_N2_H + +/* Neoverse N2 ID register for revision r0p0 */ +#define NEOVERSE_N2_MIDR U(0x410FD490) + +/* Neoverse N2 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_N2_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Power control register + ******************************************************************************/ +#define NEOVERSE_N2_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_N2_CORE_PWRDN_EN_BIT (ULL(1) << 0) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUECTLR_EL1 S3_0_C15_C1_4 +#define NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT (ULL(1) << 0) +#define NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT (ULL(1) << 8) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR_EL1 S3_0_C15_C1_0 +#define NEOVERSE_N2_CPUACTLR_EL1_BIT_46 (ULL(1) << 46) +#define NEOVERSE_N2_CPUACTLR_EL1_BIT_22 (ULL(1) << 22) + +/******************************************************************************* + * CPU Auxiliary Control register 2 specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR2_EL1 S3_0_C15_C1_1 +#define NEOVERSE_N2_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) + +/******************************************************************************* + * CPU Auxiliary Control register 5 specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUACTLR5_EL1 S3_0_C15_C8_0 +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_44 (ULL(1) << 44) +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_13 (ULL(1) << 13) +#define NEOVERSE_N2_CPUACTLR5_EL1_BIT_17 (ULL(1) << 17) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_N2_CPUECTLR2_EL1 S3_0_C15_C1_5 +#define NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV ULL(9) +#define CPUECTLR2_EL1_PF_MODE_LSB U(11) +#define CPUECTLR2_EL1_PF_MODE_WIDTH U(4) + +#endif /* NEOVERSE_N2_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h new file mode 100644 index 0000000..7cb91cd --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_N_COMMON_H +#define NEOVERSE_N_COMMON_H + +/****************************************************************************** + * Neoverse Nx CPU Configuration register definitions + *****************************************************************************/ +#define CPUCFR_EL1 S3_0_C15_C0_0 + +/* SCU bit of CPU Configuration Register, EL1 */ +#define SCU_SHIFT U(2) + +#endif /* NEOVERSE_N_COMMON_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h new file mode 100644 index 0000000..0a8b1d1 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_POSEIDON_H +#define NEOVERSE_POSEIDON_H + + +#define NEOVERSE_POSEIDON_MIDR U(0x410FD830) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_POSEIDON_CPUECTLR_EL1 S3_0_C15_C1_4 + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +#endif /* NEOVERSE_POSEIDON_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h new file mode 100644 index 0000000..a904c04 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef NEOVERSE_V1_H +#define NEOVERSE_V1_H + +#define NEOVERSE_V1_MIDR U(0x410FD400) + +/* Neoverse V1 loop count for CVE-2022-23960 mitigation */ +#define NEOVERSE_V1_BHB_LOOP_COUNT U(32) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_V1_CPUECTLR_EL1 S3_0_C15_C1_4 +#define NEOVERSE_V1_CPUECTLR_EL1_BIT_8 (ULL(1) << 8) +#define NEOVERSE_V1_CPUECTLR_EL1_BIT_53 (ULL(1) << 53) +#define NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV ULL(3) +#define CPUECTLR_EL1_PF_MODE_LSB U(6) +#define CPUECTLR_EL1_PF_MODE_WIDTH U(2) + +/******************************************************************************* + * CPU Power Control register specific definitions + ******************************************************************************/ +#define NEOVERSE_V1_CPUPWRCTLR_EL1 S3_0_C15_C2_7 +#define NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT U(1) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define NEOVERSE_V1_ACTLR2_EL1 S3_0_C15_C1_1 +#define NEOVERSE_V1_ACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define NEOVERSE_V1_ACTLR2_EL1_BIT_28 (ULL(1) << 28) + +#endif /* NEOVERSE_V1_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h b/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h new file mode 100644 index 0000000..14da170 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QEMU_MAX_H +#define QEMU_MAX_H + +#include + +/* + * QEMU MAX midr for revision 0 + * 00 - Reserved for software use + * 0 - Variant + * F - Architectural features identified in ID_* registers + * 051 - 'Q', in a 12-bit field. + * 0 - Revision + */ +#define QEMU_MAX_MIDR U(0x000F0510) + +#endif /* QEMU_MAX_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h b/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h new file mode 100644 index 0000000..978661f --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAINIER_H +#define RAINIER_H + +#include + +/* RAINIER MIDR for revision 0 */ +#define RAINIER_MIDR U(0x3f0f4120) + +/* Exception Syndrome register EC code for IC Trap */ +#define RAINIER_EC_IC_TRAP U(0x1f) + +/******************************************************************************* + * CPU Power Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUPWRCTLR_EL1 S3_0_C15_C2_7 + +/* Definitions of register field mask in RAINIER_CPUPWRCTLR_EL1 */ +#define RAINIER_CORE_PWRDN_EN_MASK U(0x1) + +#define RAINIER_ACTLR_AMEN_BIT (U(1) << 4) + +#define RAINIER_AMU_NR_COUNTERS U(5) +#define RAINIER_AMU_GROUP0_MASK U(0x1f) + +/******************************************************************************* + * CPU Extended Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUECTLR_EL1 S3_0_C15_C1_4 + +#define RAINIER_WS_THR_L2_MASK (ULL(3) << 24) +#define RAINIER_CPUECTLR_EL1_MM_TLBPF_DIS_BIT (ULL(1) << 51) + +/******************************************************************************* + * CPU Auxiliary Control register specific definitions. + ******************************************************************************/ +#define RAINIER_CPUACTLR_EL1 S3_0_C15_C1_0 + +#define RAINIER_CPUACTLR_EL1_BIT_6 (ULL(1) << 6) +#define RAINIER_CPUACTLR_EL1_BIT_13 (ULL(1) << 13) + +#define RAINIER_CPUACTLR2_EL1 S3_0_C15_C1_1 + +#define RAINIER_CPUACTLR2_EL1_BIT_0 (ULL(1) << 0) +#define RAINIER_CPUACTLR2_EL1_BIT_2 (ULL(1) << 2) +#define RAINIER_CPUACTLR2_EL1_BIT_11 (ULL(1) << 11) +#define RAINIER_CPUACTLR2_EL1_BIT_15 (ULL(1) << 15) +#define RAINIER_CPUACTLR2_EL1_BIT_16 (ULL(1) << 16) +#define RAINIER_CPUACTLR2_EL1_BIT_59 (ULL(1) << 59) + +#define RAINIER_CPUACTLR3_EL1 S3_0_C15_C1_2 + +#define RAINIER_CPUACTLR3_EL1_BIT_10 (ULL(1) << 10) + +/* Instruction patching registers */ +#define CPUPSELR_EL3 S3_6_C15_C8_0 +#define CPUPCR_EL3 S3_6_C15_C8_1 +#define CPUPOR_EL3 S3_6_C15_C8_2 +#define CPUPMR_EL3 S3_6_C15_C8_3 + +#endif /* RAINIER_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/errata_report.h b/arm-trusted-firmware/include/lib/cpus/errata_report.h new file mode 100644 index 0000000..efdedf0 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/errata_report.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ERRATA_REPORT_H +#define ERRATA_REPORT_H + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include + +#if DEBUG +void print_errata_status(void); +#else +static inline void print_errata_status(void) {} +#endif + +void errata_print_msg(unsigned int status, const char *cpu, const char *id); +int errata_needs_reporting(spinlock_t *lock, uint32_t *reported); + +#endif /* __ASSEMBLER__ */ + +/* Errata status */ +#define ERRATA_NOT_APPLIES 0 +#define ERRATA_APPLIES 1 +#define ERRATA_MISSING 2 + +/* Macro to get CPU revision code for checking errata version compatibility. */ +#define CPU_REV(r, p) ((r << 4) | p) + +#endif /* ERRATA_REPORT_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h new file mode 100644 index 0000000..940fc65 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2017_5715_H +#define WA_CVE_2017_5715_H + +int check_wa_cve_2017_5715(void); + +#endif /* WA_CVE_2017_5715_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h new file mode 100644 index 0000000..e37db37 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2018_3639_H +#define WA_CVE_2018_3639_H + +void *wa_cve_2018_3639_get_disable_ptr(void); + +#endif /* WA_CVE_2018_3639_H */ diff --git a/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h b/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h new file mode 100644 index 0000000..35b3fd8 --- /dev/null +++ b/arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WA_CVE_2022_23960_H +#define WA_CVE_2022_23960_H + +int check_smccc_arch_wa3_applies(void); + +#endif /* WA_CVE_2022_23960_H */ diff --git a/arm-trusted-firmware/include/lib/debugfs.h b/arm-trusted-firmware/include/lib/debugfs.h new file mode 100644 index 0000000..8ed237a --- /dev/null +++ b/arm-trusted-firmware/include/lib/debugfs.h @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUGFS_H +#define DEBUGFS_H + +#define NAMELEN 13 /* Maximum length of a file name */ +#define PATHLEN 41 /* Maximum length of a path */ +#define STATLEN 41 /* Size of static part of dir format */ +#define ROOTLEN (2 + 4) /* Size needed to encode root string */ +#define FILNAMLEN (2 + NAMELEN) /* Size needed to encode filename */ +#define DIRLEN (STATLEN + FILNAMLEN + 3*ROOTLEN) /* Size of dir entry */ + +#define KSEEK_SET 0 +#define KSEEK_CUR 1 +#define KSEEK_END 2 + +#define NELEM(tab) (sizeof(tab) / sizeof((tab)[0])) + +typedef unsigned short qid_t; /* FIXME: short type not recommended? */ + +/******************************************************************************* + * This structure contains the necessary information to represent a 9p + * directory. + ******************************************************************************/ +typedef struct { + char name[NAMELEN]; + long length; + unsigned char mode; + unsigned char index; + unsigned char dev; + qid_t qid; +} dir_t; + +/* Permission definitions used as flags */ +#define O_READ (1 << 0) +#define O_WRITE (1 << 1) +#define O_RDWR (1 << 2) +#define O_BIND (1 << 3) +#define O_DIR (1 << 4) +#define O_STAT (1 << 5) + +/* 9p interface */ +int mount(const char *srv, const char *mnt, const char *spec); +int create(const char *name, int flags); +int open(const char *name, int flags); +int close(int fd); +int read(int fd, void *buf, int n); +int write(int fd, void *buf, int n); +int seek(int fd, long off, int whence); +int bind(const char *path, const char *where); +int stat(const char *path, dir_t *dir); + +/* DebugFS initialization */ +void debugfs_init(void); +int debugfs_smc_setup(void); + +/* Debugfs version returned through SMC interface */ +#define DEBUGFS_VERSION (0x000000001U) + +/* Function ID for accessing the debugfs interface */ +#define DEBUGFS_FID_VALUE (0x30U) + +#define is_debugfs_fid(_fid) \ + (((_fid) & FUNCID_NUM_MASK) == DEBUGFS_FID_VALUE) + +/* Error code for debugfs SMC interface failures */ +#define DEBUGFS_E_INVALID_PARAMS (-2) +#define DEBUGFS_E_DENIED (-3) + +uintptr_t debugfs_smc_handler(unsigned int smc_fid, + u_register_t cmd, + u_register_t arg2, + u_register_t arg3, + u_register_t arg4, + void *cookie, + void *handle, + uintptr_t flags); + +#endif /* DEBUGFS_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h b/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h new file mode 100644 index 0000000..5604c8e --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'regs' + * structure at their correct offsets. + ******************************************************************************/ +#define CTX_REGS_OFFSET U(0x0) +#define CTX_GPREG_R0 U(0x0) +#define CTX_GPREG_R1 U(0x4) +#define CTX_GPREG_R2 U(0x8) +#define CTX_GPREG_R3 U(0xC) +#define CTX_LR U(0x10) +#define CTX_SCR U(0x14) +#define CTX_SPSR U(0x18) +#define CTX_NS_SCTLR U(0x1C) +#define CTX_REGS_END U(0x20) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * Common constants to help define the 'cpu_context' structure and its + * members below. + */ +#define WORD_SHIFT U(2) +#define DEFINE_REG_STRUCT(name, num_regs) \ + typedef struct name { \ + uint32_t ctx_regs[num_regs]; \ + } __aligned(8) name##_t + +/* Constants to determine the size of individual context structures */ +#define CTX_REG_ALL (CTX_REGS_END >> WORD_SHIFT) + +DEFINE_REG_STRUCT(regs, CTX_REG_ALL); + +#undef CTX_REG_ALL + +#define read_ctx_reg(ctx, offset) ((ctx)->ctx_regs[offset >> WORD_SHIFT]) +#define write_ctx_reg(ctx, offset, val) (((ctx)->ctx_regs[offset >> WORD_SHIFT]) \ + = val) +typedef struct cpu_context { + regs_t regs_ctx; +} cpu_context_t; + +/* Macros to access members of the 'cpu_context_t' structure */ +#define get_regs_ctx(h) (&((cpu_context_t *) h)->regs_ctx) + +/* + * Compile time assertions related to the 'cpu_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(CTX_REGS_OFFSET == __builtin_offsetof(cpu_context_t, regs_ctx), \ + assert_core_context_regs_offset_mismatch); + +#endif /* __ASSEMBLER__ */ + +#endif /* CONTEXT_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h b/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h new file mode 100644 index 0000000..512d196 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h @@ -0,0 +1,526 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONTEXT_H +#define CONTEXT_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'gp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#define CTX_GPREGS_OFFSET U(0x0) +#define CTX_GPREG_X0 U(0x0) +#define CTX_GPREG_X1 U(0x8) +#define CTX_GPREG_X2 U(0x10) +#define CTX_GPREG_X3 U(0x18) +#define CTX_GPREG_X4 U(0x20) +#define CTX_GPREG_X5 U(0x28) +#define CTX_GPREG_X6 U(0x30) +#define CTX_GPREG_X7 U(0x38) +#define CTX_GPREG_X8 U(0x40) +#define CTX_GPREG_X9 U(0x48) +#define CTX_GPREG_X10 U(0x50) +#define CTX_GPREG_X11 U(0x58) +#define CTX_GPREG_X12 U(0x60) +#define CTX_GPREG_X13 U(0x68) +#define CTX_GPREG_X14 U(0x70) +#define CTX_GPREG_X15 U(0x78) +#define CTX_GPREG_X16 U(0x80) +#define CTX_GPREG_X17 U(0x88) +#define CTX_GPREG_X18 U(0x90) +#define CTX_GPREG_X19 U(0x98) +#define CTX_GPREG_X20 U(0xa0) +#define CTX_GPREG_X21 U(0xa8) +#define CTX_GPREG_X22 U(0xb0) +#define CTX_GPREG_X23 U(0xb8) +#define CTX_GPREG_X24 U(0xc0) +#define CTX_GPREG_X25 U(0xc8) +#define CTX_GPREG_X26 U(0xd0) +#define CTX_GPREG_X27 U(0xd8) +#define CTX_GPREG_X28 U(0xe0) +#define CTX_GPREG_X29 U(0xe8) +#define CTX_GPREG_LR U(0xf0) +#define CTX_GPREG_SP_EL0 U(0xf8) +#define CTX_GPREGS_END U(0x100) + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'el3_state' + * structure at their correct offsets. Note that some of the registers are only + * 32-bits wide but are stored as 64-bit values for convenience + ******************************************************************************/ +#define CTX_EL3STATE_OFFSET (CTX_GPREGS_OFFSET + CTX_GPREGS_END) +#define CTX_SCR_EL3 U(0x0) +#define CTX_ESR_EL3 U(0x8) +#define CTX_RUNTIME_SP U(0x10) +#define CTX_SPSR_EL3 U(0x18) +#define CTX_ELR_EL3 U(0x20) +#define CTX_PMCR_EL0 U(0x28) +#define CTX_IS_IN_EL3 U(0x30) +#define CTX_CPTR_EL3 U(0x38) +#define CTX_ZCR_EL3 U(0x40) +#define CTX_EL3STATE_END U(0x50) /* Align to the next 16 byte boundary */ + +/******************************************************************************* + * Constants that allow assembler code to access members of and the + * 'el1_sys_regs' structure at their correct offsets. Note that some of the + * registers are only 32-bits wide but are stored as 64-bit values for + * convenience + ******************************************************************************/ +#define CTX_EL1_SYSREGS_OFFSET (CTX_EL3STATE_OFFSET + CTX_EL3STATE_END) +#define CTX_SPSR_EL1 U(0x0) +#define CTX_ELR_EL1 U(0x8) +#define CTX_SCTLR_EL1 U(0x10) +#define CTX_TCR_EL1 U(0x18) +#define CTX_CPACR_EL1 U(0x20) +#define CTX_CSSELR_EL1 U(0x28) +#define CTX_SP_EL1 U(0x30) +#define CTX_ESR_EL1 U(0x38) +#define CTX_TTBR0_EL1 U(0x40) +#define CTX_TTBR1_EL1 U(0x48) +#define CTX_MAIR_EL1 U(0x50) +#define CTX_AMAIR_EL1 U(0x58) +#define CTX_ACTLR_EL1 U(0x60) +#define CTX_TPIDR_EL1 U(0x68) +#define CTX_TPIDR_EL0 U(0x70) +#define CTX_TPIDRRO_EL0 U(0x78) +#define CTX_PAR_EL1 U(0x80) +#define CTX_FAR_EL1 U(0x88) +#define CTX_AFSR0_EL1 U(0x90) +#define CTX_AFSR1_EL1 U(0x98) +#define CTX_CONTEXTIDR_EL1 U(0xa0) +#define CTX_VBAR_EL1 U(0xa8) + +/* + * If the platform is AArch64-only, there is no need to save and restore these + * AArch32 registers. + */ +#if CTX_INCLUDE_AARCH32_REGS +#define CTX_SPSR_ABT U(0xb0) /* Align to the next 16 byte boundary */ +#define CTX_SPSR_UND U(0xb8) +#define CTX_SPSR_IRQ U(0xc0) +#define CTX_SPSR_FIQ U(0xc8) +#define CTX_DACR32_EL2 U(0xd0) +#define CTX_IFSR32_EL2 U(0xd8) +#define CTX_AARCH32_END U(0xe0) /* Align to the next 16 byte boundary */ +#else +#define CTX_AARCH32_END U(0xb0) /* Align to the next 16 byte boundary */ +#endif /* CTX_INCLUDE_AARCH32_REGS */ + +/* + * If the timer registers aren't saved and restored, we don't have to reserve + * space for them in the context + */ +#if NS_TIMER_SWITCH +#define CTX_CNTP_CTL_EL0 (CTX_AARCH32_END + U(0x0)) +#define CTX_CNTP_CVAL_EL0 (CTX_AARCH32_END + U(0x8)) +#define CTX_CNTV_CTL_EL0 (CTX_AARCH32_END + U(0x10)) +#define CTX_CNTV_CVAL_EL0 (CTX_AARCH32_END + U(0x18)) +#define CTX_CNTKCTL_EL1 (CTX_AARCH32_END + U(0x20)) +#define CTX_TIMER_SYSREGS_END (CTX_AARCH32_END + U(0x30)) /* Align to the next 16 byte boundary */ +#else +#define CTX_TIMER_SYSREGS_END CTX_AARCH32_END +#endif /* NS_TIMER_SWITCH */ + +#if CTX_INCLUDE_MTE_REGS +#define CTX_TFSRE0_EL1 (CTX_TIMER_SYSREGS_END + U(0x0)) +#define CTX_TFSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x8)) +#define CTX_RGSR_EL1 (CTX_TIMER_SYSREGS_END + U(0x10)) +#define CTX_GCR_EL1 (CTX_TIMER_SYSREGS_END + U(0x18)) + +/* Align to the next 16 byte boundary */ +#define CTX_MTE_REGS_END (CTX_TIMER_SYSREGS_END + U(0x20)) +#else +#define CTX_MTE_REGS_END CTX_TIMER_SYSREGS_END +#endif /* CTX_INCLUDE_MTE_REGS */ + +/* + * End of system registers. + */ +#define CTX_EL1_SYSREGS_END CTX_MTE_REGS_END + +/* + * EL2 register set + */ + +#if CTX_INCLUDE_EL2_REGS +/* For later discussion + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_LR_EL2 + */ +#define CTX_EL2_SYSREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END) + +#define CTX_ACTLR_EL2 U(0x0) +#define CTX_AFSR0_EL2 U(0x8) +#define CTX_AFSR1_EL2 U(0x10) +#define CTX_AMAIR_EL2 U(0x18) +#define CTX_CNTHCTL_EL2 U(0x20) +#define CTX_CNTVOFF_EL2 U(0x28) +#define CTX_CPTR_EL2 U(0x30) +#define CTX_DBGVCR32_EL2 U(0x38) +#define CTX_ELR_EL2 U(0x40) +#define CTX_ESR_EL2 U(0x48) +#define CTX_FAR_EL2 U(0x50) +#define CTX_HACR_EL2 U(0x58) +#define CTX_HCR_EL2 U(0x60) +#define CTX_HPFAR_EL2 U(0x68) +#define CTX_HSTR_EL2 U(0x70) +#define CTX_ICC_SRE_EL2 U(0x78) +#define CTX_ICH_HCR_EL2 U(0x80) +#define CTX_ICH_VMCR_EL2 U(0x88) +#define CTX_MAIR_EL2 U(0x90) +#define CTX_MDCR_EL2 U(0x98) +#define CTX_PMSCR_EL2 U(0xa0) +#define CTX_SCTLR_EL2 U(0xa8) +#define CTX_SPSR_EL2 U(0xb0) +#define CTX_SP_EL2 U(0xb8) +#define CTX_TCR_EL2 U(0xc0) +#define CTX_TPIDR_EL2 U(0xc8) +#define CTX_TTBR0_EL2 U(0xd0) +#define CTX_VBAR_EL2 U(0xd8) +#define CTX_VMPIDR_EL2 U(0xe0) +#define CTX_VPIDR_EL2 U(0xe8) +#define CTX_VTCR_EL2 U(0xf0) +#define CTX_VTTBR_EL2 U(0xf8) + +// Only if MTE registers in use +#define CTX_TFSR_EL2 U(0x100) + +// Only if ENABLE_MPAM_FOR_LOWER_ELS==1 +#define CTX_MPAM2_EL2 U(0x108) +#define CTX_MPAMHCR_EL2 U(0x110) +#define CTX_MPAMVPM0_EL2 U(0x118) +#define CTX_MPAMVPM1_EL2 U(0x120) +#define CTX_MPAMVPM2_EL2 U(0x128) +#define CTX_MPAMVPM3_EL2 U(0x130) +#define CTX_MPAMVPM4_EL2 U(0x138) +#define CTX_MPAMVPM5_EL2 U(0x140) +#define CTX_MPAMVPM6_EL2 U(0x148) +#define CTX_MPAMVPM7_EL2 U(0x150) +#define CTX_MPAMVPMV_EL2 U(0x158) + +// Starting with Armv8.6 +#define CTX_HDFGRTR_EL2 U(0x160) +#define CTX_HAFGRTR_EL2 U(0x168) +#define CTX_HDFGWTR_EL2 U(0x170) +#define CTX_HFGITR_EL2 U(0x178) +#define CTX_HFGRTR_EL2 U(0x180) +#define CTX_HFGWTR_EL2 U(0x188) +#define CTX_CNTPOFF_EL2 U(0x190) + +// Starting with Armv8.4 +#define CTX_CONTEXTIDR_EL2 U(0x198) +#define CTX_SDER32_EL2 U(0x1a0) +#define CTX_TTBR1_EL2 U(0x1a8) +#define CTX_VDISR_EL2 U(0x1b0) +#define CTX_VNCR_EL2 U(0x1b8) +#define CTX_VSESR_EL2 U(0x1c0) +#define CTX_VSTCR_EL2 U(0x1c8) +#define CTX_VSTTBR_EL2 U(0x1d0) +#define CTX_TRFCR_EL2 U(0x1d8) + +// Starting with Armv8.5 +#define CTX_SCXTNUM_EL2 U(0x1e0) + +// Register for FEAT_HCX +#define CTX_HCRX_EL2 U(0x1e8) + +/* Align to the next 16 byte boundary */ +#define CTX_EL2_SYSREGS_END U(0x1f0) + +#endif /* CTX_INCLUDE_EL2_REGS */ + +/******************************************************************************* + * Constants that allow assembler code to access members of and the 'fp_regs' + * structure at their correct offsets. + ******************************************************************************/ +#if CTX_INCLUDE_EL2_REGS +# define CTX_FPREGS_OFFSET (CTX_EL2_SYSREGS_OFFSET + CTX_EL2_SYSREGS_END) +#else +# define CTX_FPREGS_OFFSET (CTX_EL1_SYSREGS_OFFSET + CTX_EL1_SYSREGS_END) +#endif +#if CTX_INCLUDE_FPREGS +#define CTX_FP_Q0 U(0x0) +#define CTX_FP_Q1 U(0x10) +#define CTX_FP_Q2 U(0x20) +#define CTX_FP_Q3 U(0x30) +#define CTX_FP_Q4 U(0x40) +#define CTX_FP_Q5 U(0x50) +#define CTX_FP_Q6 U(0x60) +#define CTX_FP_Q7 U(0x70) +#define CTX_FP_Q8 U(0x80) +#define CTX_FP_Q9 U(0x90) +#define CTX_FP_Q10 U(0xa0) +#define CTX_FP_Q11 U(0xb0) +#define CTX_FP_Q12 U(0xc0) +#define CTX_FP_Q13 U(0xd0) +#define CTX_FP_Q14 U(0xe0) +#define CTX_FP_Q15 U(0xf0) +#define CTX_FP_Q16 U(0x100) +#define CTX_FP_Q17 U(0x110) +#define CTX_FP_Q18 U(0x120) +#define CTX_FP_Q19 U(0x130) +#define CTX_FP_Q20 U(0x140) +#define CTX_FP_Q21 U(0x150) +#define CTX_FP_Q22 U(0x160) +#define CTX_FP_Q23 U(0x170) +#define CTX_FP_Q24 U(0x180) +#define CTX_FP_Q25 U(0x190) +#define CTX_FP_Q26 U(0x1a0) +#define CTX_FP_Q27 U(0x1b0) +#define CTX_FP_Q28 U(0x1c0) +#define CTX_FP_Q29 U(0x1d0) +#define CTX_FP_Q30 U(0x1e0) +#define CTX_FP_Q31 U(0x1f0) +#define CTX_FP_FPSR U(0x200) +#define CTX_FP_FPCR U(0x208) +#if CTX_INCLUDE_AARCH32_REGS +#define CTX_FP_FPEXC32_EL2 U(0x210) +#define CTX_FPREGS_END U(0x220) /* Align to the next 16 byte boundary */ +#else +#define CTX_FPREGS_END U(0x210) /* Align to the next 16 byte boundary */ +#endif +#else +#define CTX_FPREGS_END U(0) +#endif + +/******************************************************************************* + * Registers related to CVE-2018-3639 + ******************************************************************************/ +#define CTX_CVE_2018_3639_OFFSET (CTX_FPREGS_OFFSET + CTX_FPREGS_END) +#define CTX_CVE_2018_3639_DISABLE U(0) +#define CTX_CVE_2018_3639_END U(0x10) /* Align to the next 16 byte boundary */ + +/******************************************************************************* + * Registers related to ARMv8.3-PAuth. + ******************************************************************************/ +#define CTX_PAUTH_REGS_OFFSET (CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_END) +#if CTX_INCLUDE_PAUTH_REGS +#define CTX_PACIAKEY_LO U(0x0) +#define CTX_PACIAKEY_HI U(0x8) +#define CTX_PACIBKEY_LO U(0x10) +#define CTX_PACIBKEY_HI U(0x18) +#define CTX_PACDAKEY_LO U(0x20) +#define CTX_PACDAKEY_HI U(0x28) +#define CTX_PACDBKEY_LO U(0x30) +#define CTX_PACDBKEY_HI U(0x38) +#define CTX_PACGAKEY_LO U(0x40) +#define CTX_PACGAKEY_HI U(0x48) +#define CTX_PAUTH_REGS_END U(0x50) /* Align to the next 16 byte boundary */ +#else +#define CTX_PAUTH_REGS_END U(0) +#endif /* CTX_INCLUDE_PAUTH_REGS */ + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * Common constants to help define the 'cpu_context' structure and its + * members below. + */ +#define DWORD_SHIFT U(3) +#define DEFINE_REG_STRUCT(name, num_regs) \ + typedef struct name { \ + uint64_t ctx_regs[num_regs]; \ + } __aligned(16) name##_t + +/* Constants to determine the size of individual context structures */ +#define CTX_GPREG_ALL (CTX_GPREGS_END >> DWORD_SHIFT) +#define CTX_EL1_SYSREGS_ALL (CTX_EL1_SYSREGS_END >> DWORD_SHIFT) +#if CTX_INCLUDE_EL2_REGS +# define CTX_EL2_SYSREGS_ALL (CTX_EL2_SYSREGS_END >> DWORD_SHIFT) +#endif +#if CTX_INCLUDE_FPREGS +# define CTX_FPREG_ALL (CTX_FPREGS_END >> DWORD_SHIFT) +#endif +#define CTX_EL3STATE_ALL (CTX_EL3STATE_END >> DWORD_SHIFT) +#define CTX_CVE_2018_3639_ALL (CTX_CVE_2018_3639_END >> DWORD_SHIFT) +#if CTX_INCLUDE_PAUTH_REGS +# define CTX_PAUTH_REGS_ALL (CTX_PAUTH_REGS_END >> DWORD_SHIFT) +#endif + +/* + * AArch64 general purpose register context structure. Usually x0-x18, + * lr are saved as the compiler is expected to preserve the remaining + * callee saved registers if used by the C runtime and the assembler + * does not touch the remaining. But in case of world switch during + * exception handling, we need to save the callee registers too. + */ +DEFINE_REG_STRUCT(gp_regs, CTX_GPREG_ALL); + +/* + * AArch64 EL1 system register context structure for preserving the + * architectural state during world switches. + */ +DEFINE_REG_STRUCT(el1_sysregs, CTX_EL1_SYSREGS_ALL); + + +/* + * AArch64 EL2 system register context structure for preserving the + * architectural state during world switches. + */ +#if CTX_INCLUDE_EL2_REGS +DEFINE_REG_STRUCT(el2_sysregs, CTX_EL2_SYSREGS_ALL); +#endif + +/* + * AArch64 floating point register context structure for preserving + * the floating point state during switches from one security state to + * another. + */ +#if CTX_INCLUDE_FPREGS +DEFINE_REG_STRUCT(fp_regs, CTX_FPREG_ALL); +#endif + +/* + * Miscellaneous registers used by EL3 firmware to maintain its state + * across exception entries and exits + */ +DEFINE_REG_STRUCT(el3_state, CTX_EL3STATE_ALL); + +/* Function pointer used by CVE-2018-3639 dynamic mitigation */ +DEFINE_REG_STRUCT(cve_2018_3639, CTX_CVE_2018_3639_ALL); + +/* Registers associated to ARMv8.3-PAuth */ +#if CTX_INCLUDE_PAUTH_REGS +DEFINE_REG_STRUCT(pauth, CTX_PAUTH_REGS_ALL); +#endif + +/* + * Macros to access members of any of the above structures using their + * offsets + */ +#define read_ctx_reg(ctx, offset) ((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) +#define write_ctx_reg(ctx, offset, val) (((ctx)->ctx_regs[(offset) >> DWORD_SHIFT]) \ + = (uint64_t) (val)) + +/* + * Top-level context structure which is used by EL3 firmware to preserve + * the state of a core at the next lower EL in a given security state and + * save enough EL3 meta data to be able to return to that EL and security + * state. The context management library will be used to ensure that + * SP_EL3 always points to an instance of this structure at exception + * entry and exit. + */ +typedef struct cpu_context { + gp_regs_t gpregs_ctx; + el3_state_t el3state_ctx; + el1_sysregs_t el1_sysregs_ctx; +#if CTX_INCLUDE_EL2_REGS + el2_sysregs_t el2_sysregs_ctx; +#endif +#if CTX_INCLUDE_FPREGS + fp_regs_t fpregs_ctx; +#endif + cve_2018_3639_t cve_2018_3639_ctx; +#if CTX_INCLUDE_PAUTH_REGS + pauth_t pauth_ctx; +#endif +} cpu_context_t; + +/* Macros to access members of the 'cpu_context_t' structure */ +#define get_el3state_ctx(h) (&((cpu_context_t *) h)->el3state_ctx) +#if CTX_INCLUDE_FPREGS +# define get_fpregs_ctx(h) (&((cpu_context_t *) h)->fpregs_ctx) +#endif +#define get_el1_sysregs_ctx(h) (&((cpu_context_t *) h)->el1_sysregs_ctx) +#if CTX_INCLUDE_EL2_REGS +# define get_el2_sysregs_ctx(h) (&((cpu_context_t *) h)->el2_sysregs_ctx) +#endif +#define get_gpregs_ctx(h) (&((cpu_context_t *) h)->gpregs_ctx) +#define get_cve_2018_3639_ctx(h) (&((cpu_context_t *) h)->cve_2018_3639_ctx) +#if CTX_INCLUDE_PAUTH_REGS +# define get_pauth_ctx(h) (&((cpu_context_t *) h)->pauth_ctx) +#endif + +/* + * Compile time assertions related to the 'cpu_context' structure to + * ensure that the assembler and the compiler view of the offsets of + * the structure members is the same. + */ +CASSERT(CTX_GPREGS_OFFSET == __builtin_offsetof(cpu_context_t, gpregs_ctx), \ + assert_core_context_gp_offset_mismatch); +CASSERT(CTX_EL1_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el1_sysregs_ctx), \ + assert_core_context_el1_sys_offset_mismatch); +#if CTX_INCLUDE_EL2_REGS +CASSERT(CTX_EL2_SYSREGS_OFFSET == __builtin_offsetof(cpu_context_t, el2_sysregs_ctx), \ + assert_core_context_el2_sys_offset_mismatch); +#endif +#if CTX_INCLUDE_FPREGS +CASSERT(CTX_FPREGS_OFFSET == __builtin_offsetof(cpu_context_t, fpregs_ctx), \ + assert_core_context_fp_offset_mismatch); +#endif +CASSERT(CTX_EL3STATE_OFFSET == __builtin_offsetof(cpu_context_t, el3state_ctx), \ + assert_core_context_el3state_offset_mismatch); +CASSERT(CTX_CVE_2018_3639_OFFSET == __builtin_offsetof(cpu_context_t, cve_2018_3639_ctx), \ + assert_core_context_cve_2018_3639_offset_mismatch); +#if CTX_INCLUDE_PAUTH_REGS +CASSERT(CTX_PAUTH_REGS_OFFSET == __builtin_offsetof(cpu_context_t, pauth_ctx), \ + assert_core_context_pauth_offset_mismatch); +#endif + +/* + * Helper macro to set the general purpose registers that correspond to + * parameters in an aapcs_64 call i.e. x0-x7 + */ +#define set_aapcs_args0(ctx, x0) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X0, x0); \ + } while (0) +#define set_aapcs_args1(ctx, x0, x1) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X1, x1); \ + set_aapcs_args0(ctx, x0); \ + } while (0) +#define set_aapcs_args2(ctx, x0, x1, x2) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X2, x2); \ + set_aapcs_args1(ctx, x0, x1); \ + } while (0) +#define set_aapcs_args3(ctx, x0, x1, x2, x3) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X3, x3); \ + set_aapcs_args2(ctx, x0, x1, x2); \ + } while (0) +#define set_aapcs_args4(ctx, x0, x1, x2, x3, x4) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X4, x4); \ + set_aapcs_args3(ctx, x0, x1, x2, x3); \ + } while (0) +#define set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X5, x5); \ + set_aapcs_args4(ctx, x0, x1, x2, x3, x4); \ + } while (0) +#define set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X6, x6); \ + set_aapcs_args5(ctx, x0, x1, x2, x3, x4, x5); \ + } while (0) +#define set_aapcs_args7(ctx, x0, x1, x2, x3, x4, x5, x6, x7) do { \ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_X7, x7); \ + set_aapcs_args6(ctx, x0, x1, x2, x3, x4, x5, x6); \ + } while (0) + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +void el1_sysregs_context_save(el1_sysregs_t *regs); +void el1_sysregs_context_restore(el1_sysregs_t *regs); + +#if CTX_INCLUDE_EL2_REGS +void el2_sysregs_context_save(el2_sysregs_t *regs); +void el2_sysregs_context_restore(el2_sysregs_t *regs); +#endif + +#if CTX_INCLUDE_FPREGS +void fpregs_context_save(fp_regs_t *regs); +void fpregs_context_restore(fp_regs_t *regs); +#endif + +#endif /* __ASSEMBLER__ */ + +#endif /* CONTEXT_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h b/arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h new file mode 100644 index 0000000..2090687 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CONTEXT_MGMT_H +#define CONTEXT_MGMT_H + +#include +#include +#include + +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct entry_point_info; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +void cm_init(void); +void *cm_get_context_by_index(unsigned int cpu_idx, + unsigned int security_state); +void cm_set_context_by_index(unsigned int cpu_idx, + void *context, + unsigned int security_state); +void *cm_get_context(uint32_t security_state); +void cm_set_context(void *context, uint32_t security_state); +void cm_init_my_context(const struct entry_point_info *ep); +void cm_init_context_by_index(unsigned int cpu_idx, + const struct entry_point_info *ep); +void cm_setup_context(cpu_context_t *ctx, const struct entry_point_info *ep); +void cm_prepare_el3_exit(uint32_t security_state); + +#ifdef __aarch64__ +#if CTX_INCLUDE_EL2_REGS +void cm_el2_sysregs_context_save(uint32_t security_state); +void cm_el2_sysregs_context_restore(uint32_t security_state); +#endif + +void cm_el1_sysregs_context_save(uint32_t security_state); +void cm_el1_sysregs_context_restore(uint32_t security_state); +void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint); +void cm_set_elr_spsr_el3(uint32_t security_state, + uintptr_t entrypoint, uint32_t spsr); +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value); +void cm_set_next_eret_context(uint32_t security_state); +u_register_t cm_get_scr_el3(uint32_t security_state); + +/* Inline definitions */ + +/******************************************************************************* + * This function is used to program the context that's used for exception + * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for + * the required security state + ******************************************************************************/ +static inline void cm_set_next_context(void *context) +{ +#if ENABLE_ASSERTIONS + uint64_t sp_mode; + + /* + * Check that this function is called with SP_EL0 as the stack + * pointer + */ + __asm__ volatile("mrs %0, SPSel\n" + : "=r" (sp_mode)); + + assert(sp_mode == MODE_SP_EL0); +#endif /* ENABLE_ASSERTIONS */ + + __asm__ volatile("msr spsel, #1\n" + "mov sp, %0\n" + "msr spsel, #0\n" + : : "r" (context)); +} + +#else +void *cm_get_next_context(void); +void cm_set_next_context(void *context); +#endif /* __aarch64__ */ + +#endif /* CONTEXT_MGMT_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h b/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h new file mode 100644 index 0000000..2c7b619 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h @@ -0,0 +1,237 @@ +/* + * Copyright (c) 2014-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CPU_DATA_H +#define CPU_DATA_H + +#include /* CACHE_WRITEBACK_GRANULE required */ + +#include + +/* Size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE 12 + +#ifdef __aarch64__ + +/* 8-bytes aligned size of psci_cpu_data structure */ +#define PSCI_CPU_DATA_SIZE_ALIGNED ((PSCI_CPU_DATA_SIZE + 7) & ~7) + +#if ENABLE_RME +/* Size of cpu_context array */ +#define CPU_DATA_CONTEXT_NUM 3 +/* Offset of cpu_ops_ptr, size 8 bytes */ +#define CPU_DATA_CPU_OPS_PTR 0x18 +#else /* ENABLE_RME */ +#define CPU_DATA_CONTEXT_NUM 2 +#define CPU_DATA_CPU_OPS_PTR 0x10 +#endif /* ENABLE_RME */ + +#if ENABLE_PAUTH +/* 8-bytes aligned offset of apiakey[2], size 16 bytes */ +#define CPU_DATA_APIAKEY_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \ + + CPU_DATA_CPU_OPS_PTR) +#define CPU_DATA_CRASH_BUF_OFFSET (0x10 + CPU_DATA_APIAKEY_OFFSET) +#else /* ENABLE_PAUTH */ +#define CPU_DATA_CRASH_BUF_OFFSET (0x8 + PSCI_CPU_DATA_SIZE_ALIGNED \ + + CPU_DATA_CPU_OPS_PTR) +#endif /* ENABLE_PAUTH */ + +/* need enough space in crash buffer to save 8 registers */ +#define CPU_DATA_CRASH_BUF_SIZE 64 + +#else /* !__aarch64__ */ + +#if CRASH_REPORTING +#error "Crash reporting is not supported in AArch32" +#endif +#define CPU_DATA_CPU_OPS_PTR 0x0 +#define CPU_DATA_CRASH_BUF_OFFSET (0x4 + PSCI_CPU_DATA_SIZE) + +#endif /* __aarch64__ */ + +#if CRASH_REPORTING +#define CPU_DATA_CRASH_BUF_END (CPU_DATA_CRASH_BUF_OFFSET + \ + CPU_DATA_CRASH_BUF_SIZE) +#else +#define CPU_DATA_CRASH_BUF_END CPU_DATA_CRASH_BUF_OFFSET +#endif + +/* cpu_data size is the data size rounded up to the platform cache line size */ +#define CPU_DATA_SIZE (((CPU_DATA_CRASH_BUF_END + \ + CACHE_WRITEBACK_GRANULE - 1) / \ + CACHE_WRITEBACK_GRANULE) * \ + CACHE_WRITEBACK_GRANULE) + +#if ENABLE_RUNTIME_INSTRUMENTATION +/* Temporary space to store PMF timestamps from assembly code */ +#define CPU_DATA_PMF_TS_COUNT 1 +#define CPU_DATA_PMF_TS0_OFFSET CPU_DATA_CRASH_BUF_END +#define CPU_DATA_PMF_TS0_IDX 0 +#endif + +#ifndef __ASSEMBLER__ + +#include +#include + +#include +#include +#include + +#include + +/* Offsets for the cpu_data structure */ +#define CPU_DATA_PSCI_LOCK_OFFSET __builtin_offsetof\ + (cpu_data_t, psci_svc_cpu_data.pcpu_bakery_info) + +#if PLAT_PCPU_DATA_SIZE +#define CPU_DATA_PLAT_PCPU_OFFSET __builtin_offsetof\ + (cpu_data_t, platform_cpu_data) +#endif + +typedef enum context_pas { + CPU_CONTEXT_SECURE = 0, + CPU_CONTEXT_NS, +#if ENABLE_RME + CPU_CONTEXT_REALM, +#endif + CPU_CONTEXT_NUM +} context_pas_t; + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ + +/******************************************************************************* + * Cache of frequently used per-cpu data: + * Pointers to non-secure, realm, and secure security state contexts + * Address of the crash stack + * It is aligned to the cache line boundary to allow efficient concurrent + * manipulation of these pointers on different cpus + * + * The data structure and the _cpu_data accessors should not be used directly + * by components that have per-cpu members. The member access macros should be + * used for this. + ******************************************************************************/ +typedef struct cpu_data { +#ifdef __aarch64__ + void *cpu_context[CPU_DATA_CONTEXT_NUM]; +#endif /* __aarch64__ */ + uintptr_t cpu_ops_ptr; + struct psci_cpu_data psci_svc_cpu_data; +#if ENABLE_PAUTH + uint64_t apiakey[2]; +#endif +#if CRASH_REPORTING + u_register_t crash_buf[CPU_DATA_CRASH_BUF_SIZE >> 3]; +#endif +#if ENABLE_RUNTIME_INSTRUMENTATION + uint64_t cpu_data_pmf_ts[CPU_DATA_PMF_TS_COUNT]; +#endif +#if PLAT_PCPU_DATA_SIZE + uint8_t platform_cpu_data[PLAT_PCPU_DATA_SIZE]; +#endif +#if defined(IMAGE_BL31) && EL3_EXCEPTION_HANDLING + pe_exc_data_t ehf_data; +#endif +} __aligned(CACHE_WRITEBACK_GRANULE) cpu_data_t; + +extern cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; + +#ifdef __aarch64__ +CASSERT(CPU_DATA_CONTEXT_NUM == CPU_CONTEXT_NUM, + assert_cpu_data_context_num_mismatch); +#endif + +#if ENABLE_PAUTH +CASSERT(CPU_DATA_APIAKEY_OFFSET == __builtin_offsetof + (cpu_data_t, apiakey), + assert_cpu_data_pauth_stack_offset_mismatch); +#endif + +#if CRASH_REPORTING +/* verify assembler offsets match data structures */ +CASSERT(CPU_DATA_CRASH_BUF_OFFSET == __builtin_offsetof + (cpu_data_t, crash_buf), + assert_cpu_data_crash_stack_offset_mismatch); +#endif + +CASSERT(CPU_DATA_SIZE == sizeof(cpu_data_t), + assert_cpu_data_size_mismatch); + +CASSERT(CPU_DATA_CPU_OPS_PTR == __builtin_offsetof + (cpu_data_t, cpu_ops_ptr), + assert_cpu_data_cpu_ops_ptr_offset_mismatch); + +#if ENABLE_RUNTIME_INSTRUMENTATION +CASSERT(CPU_DATA_PMF_TS0_OFFSET == __builtin_offsetof + (cpu_data_t, cpu_data_pmf_ts[0]), + assert_cpu_data_pmf_ts0_offset_mismatch); +#endif + +struct cpu_data *_cpu_data_by_index(uint32_t cpu_index); + +#ifdef __aarch64__ +/* Return the cpu_data structure for the current CPU. */ +static inline struct cpu_data *_cpu_data(void) +{ + return (cpu_data_t *)read_tpidr_el3(); +} +#else +struct cpu_data *_cpu_data(void); +#endif + +/* + * Returns the index of the cpu_context array for the given security state. + * All accesses to cpu_context should be through this helper to make sure + * an access is not out-of-bounds. The function assumes security_state is + * valid. + */ +static inline context_pas_t get_cpu_context_index(uint32_t security_state) +{ + if (security_state == SECURE) { + return CPU_CONTEXT_SECURE; + } else { +#if ENABLE_RME + if (security_state == NON_SECURE) { + return CPU_CONTEXT_NS; + } else { + assert(security_state == REALM); + return CPU_CONTEXT_REALM; + } +#else + assert(security_state == NON_SECURE); + return CPU_CONTEXT_NS; +#endif + } +} + +/************************************************************************** + * APIs for initialising and accessing per-cpu data + *************************************************************************/ + +void init_cpu_data_ptr(void); +void init_cpu_ops(void); + +#define get_cpu_data(_m) _cpu_data()->_m +#define set_cpu_data(_m, _v) _cpu_data()->_m = (_v) +#define get_cpu_data_by_index(_ix, _m) _cpu_data_by_index(_ix)->_m +#define set_cpu_data_by_index(_ix, _m, _v) _cpu_data_by_index(_ix)->_m = (_v) +/* ((cpu_data_t *)0)->_m is a dummy to get the sizeof the struct member _m */ +#define flush_cpu_data(_m) flush_dcache_range((uintptr_t) \ + &(_cpu_data()->_m), \ + sizeof(((cpu_data_t *)0)->_m)) +#define inv_cpu_data(_m) inv_dcache_range((uintptr_t) \ + &(_cpu_data()->_m), \ + sizeof(((cpu_data_t *)0)->_m)) +#define flush_cpu_data_by_index(_ix, _m) \ + flush_dcache_range((uintptr_t) \ + &(_cpu_data_by_index(_ix)->_m), \ + sizeof(((cpu_data_t *)0)->_m)) + + +#endif /* __ASSEMBLER__ */ +#endif /* CPU_DATA_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/pubsub.h b/arm-trusted-firmware/include/lib/el3_runtime/pubsub.h new file mode 100644 index 0000000..64fe5cc --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/pubsub.h @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PUBSUB_H +#define PUBSUB_H + +#ifdef __LINKER__ + +/* For the linker ... */ +#define __pubsub_start_sym(event) __pubsub_##event##_start +#define __pubsub_end_sym(event) __pubsub_##event##_end +#define __pubsub_section(event) __pubsub_##event + +/* + * REGISTER_PUBSUB_EVENT has a different definition between linker and compiler + * contexts. In linker context, this collects pubsub sections for each event, + * placing guard symbols around each. + */ +#if defined(USE_ARM_LINK) +#define REGISTER_PUBSUB_EVENT(event) \ + __pubsub_start_sym(event) +0 FIXED \ + { \ + *(__pubsub_section(event)) \ + } \ + __pubsub_end_sym(event) +0 FIXED EMPTY 0 \ + { \ + /* placeholder */ \ + } +#else +#define REGISTER_PUBSUB_EVENT(event) \ + __pubsub_start_sym(event) = .; \ + KEEP(*(__pubsub_section(event))); \ + __pubsub_end_sym(event) = . +#endif + +#else /* __LINKER__ */ + +/* For the compiler ... */ + +#include +#include +#include + +#include + +#if defined(USE_ARM_LINK) +#define __pubsub_start_sym(event) Load$$__pubsub_##event##_start$$Base +#define __pubsub_end_sym(event) Load$$__pubsub_##event##_end$$Base +#else +#define __pubsub_start_sym(event) __pubsub_##event##_start +#define __pubsub_end_sym(event) __pubsub_##event##_end +#endif + +#define __pubsub_section(event) __section("__pubsub_" #event) + +/* + * In compiler context, REGISTER_PUBSUB_EVENT declares the per-event symbols + * exported by the linker required for the other pubsub macros to work. + */ +#define REGISTER_PUBSUB_EVENT(event) \ + extern pubsub_cb_t __pubsub_start_sym(event)[]; \ + extern pubsub_cb_t __pubsub_end_sym(event)[] + +/* + * Have the function func called back when the specified event happens. This + * macro places the function address into the pubsub section, which is picked up + * and invoked by the invoke_pubsubs() function via the PUBLISH_EVENT* macros. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define SUBSCRIBE_TO_EVENT(event, func) \ + extern pubsub_cb_t __cb_func_##func##event __pubsub_section(event); \ + pubsub_cb_t __cb_func_##func##event __pubsub_section(event) = (func) + +/* + * Iterate over subscribed handlers for a defined event. 'event' is the name of + * the event, and 'subscriber' a local variable of type 'pubsub_cb_t *'. + */ +#define for_each_subscriber(event, subscriber) \ + for (subscriber = __pubsub_start_sym(event); \ + subscriber < __pubsub_end_sym(event); \ + subscriber++) + +/* + * Publish a defined event supplying an argument. All subscribed handlers are + * invoked, but the return value of handlers are ignored for now. + */ +#define PUBLISH_EVENT_ARG(event, arg) \ + do { \ + pubsub_cb_t *subscriber; \ + for_each_subscriber(event, subscriber) { \ + (*subscriber)(arg); \ + } \ + } while (0) + +/* Publish a defined event with NULL argument */ +#define PUBLISH_EVENT(event) PUBLISH_EVENT_ARG(event, NULL) + +/* Subscriber callback type */ +typedef void* (*pubsub_cb_t)(const void *arg); + +#endif /* __LINKER__ */ +#endif /* PUBSUB_H */ diff --git a/arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h b/arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h new file mode 100644 index 0000000..5012082 --- /dev/null +++ b/arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * This file defines a list of pubsub events, declared using + * REGISTER_PUBSUB_EVENT() macro. + */ + +/* + * Event published after a CPU has been powered up and finished its + * initialization. + */ +REGISTER_PUBSUB_EVENT(psci_cpu_on_finish); + +/* + * These events are published before/after a CPU has been powered down/up + * via the PSCI CPU SUSPEND API. + */ +REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_start); +REGISTER_PUBSUB_EVENT(psci_suspend_pwrdown_finish); + +#ifdef __aarch64__ +/* + * These events are published by the AArch64 context management framework + * after the secure context is restored/saved via + * cm_el1_sysregs_context_{restore,save}() API. + */ +REGISTER_PUBSUB_EVENT(cm_entering_secure_world); +REGISTER_PUBSUB_EVENT(cm_exited_secure_world); + +/* + * These events are published by the AArch64 context management framework + * after the normal context is restored/saved via + * cm_el1_sysregs_context_{restore,save}() API. + */ +REGISTER_PUBSUB_EVENT(cm_entering_normal_world); +REGISTER_PUBSUB_EVENT(cm_exited_normal_world); +#endif /* __aarch64__ */ diff --git a/arm-trusted-firmware/include/lib/extensions/amu.h b/arm-trusted-firmware/include/lib/extensions/amu.h new file mode 100644 index 0000000..6452f7e --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/amu.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AMU_H +#define AMU_H + +#include +#include + +#include + +#include + +#if __aarch64__ +void amu_enable(bool el2_unused, cpu_context_t *ctx); +#else +void amu_enable(bool el2_unused); +#endif + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * AMU data for a single core. + */ +struct amu_core { + uint16_t enable; /* Mask of auxiliary counters to enable */ +}; + +/* + * Topological platform data specific to the AMU. + */ +struct amu_topology { + struct amu_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */ +}; + +#if !ENABLE_AMU_FCONF +/* + * Retrieve the platform's AMU topology. A `NULL` return value is treated as a + * non-fatal error, in which case no auxiliary counters will be enabled. + */ +const struct amu_topology *plat_amu_topology(void); +#endif /* ENABLE_AMU_FCONF */ +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + +#endif /* AMU_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/mpam.h b/arm-trusted-firmware/include/lib/extensions/mpam.h new file mode 100644 index 0000000..414adcb --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/mpam.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPAM_H +#define MPAM_H + +#include + +void mpam_enable(bool el2_unused); + +#endif /* MPAM_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/pauth.h b/arm-trusted-firmware/include/lib/extensions/pauth.h new file mode 100644 index 0000000..2e780de --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/pauth.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PAUTH_H +#define PAUTH_H + +/******************************************************************************* + * ARMv8.3-PAuth support functions + ******************************************************************************/ + +/* Disable ARMv8.3 pointer authentication in EL1/EL3 */ +void pauth_disable_el1(void); +void pauth_disable_el3(void); + +#endif /* PAUTH_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/ras.h b/arm-trusted-firmware/include/lib/extensions/ras.h new file mode 100644 index 0000000..793ab9f --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/ras.h @@ -0,0 +1,203 @@ +/* + * 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 RAS_H +#define RAS_H + +#define ERR_HANDLER_VERSION 1U + +/* Error record access mechanism */ +#define ERR_ACCESS_SYSREG 0 +#define ERR_ACCESS_MEMMAP 1 + +/* + * Register all error records on the platform. + * + * This macro must be used in the same file as the array of error record info + * are declared. Only then would ARRAY_SIZE() yield a meaningful value. + */ +#define REGISTER_ERR_RECORD_INFO(_records) \ + const struct err_record_mapping err_record_mappings = { \ + .err_records = (_records), \ + .num_err_records = ARRAY_SIZE(_records), \ + } + +/* Error record info iterator */ +#define for_each_err_record_info(_i, _info) \ + for ((_i) = 0, (_info) = err_record_mappings.err_records; \ + (_i) < err_record_mappings.num_err_records; \ + (_i)++, (_info)++) + +#define ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + .probe = _probe, \ + .handler = _handler, \ + .aux_data = _aux, + +#define ERR_RECORD_SYSREG_V1(_idx_start, _num_idx, _probe, _handler, _aux) \ + { \ + .version = 1, \ + .sysreg.idx_start = _idx_start, \ + .sysreg.num_idx = _num_idx, \ + .access = ERR_ACCESS_SYSREG, \ + ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + } + +#define ERR_RECORD_MEMMAP_V1(_base_addr, _size_num_k, _probe, _handler, _aux) \ + { \ + .version = 1, \ + .memmap.base_addr = _base_addr, \ + .memmap.size_num_k = _size_num_k, \ + .access = ERR_ACCESS_MEMMAP, \ + ERR_RECORD_COMMON_(_probe, _handler, _aux) \ + } + +/* + * Macro to be used to name and declare an array of RAS interrupts along with + * their handlers. + * + * This macro must be used in the same file as the array of interrupts are + * declared. Only then would ARRAY_SIZE() yield a meaningful value. Also, the + * array is expected to be sorted in the increasing order of interrupt number. + */ +#define REGISTER_RAS_INTERRUPTS(_array) \ + const struct ras_interrupt_mapping ras_interrupt_mappings = { \ + .intrs = (_array), \ + .num_intrs = ARRAY_SIZE(_array), \ + } + +#ifndef __ASSEMBLER__ + +#include + +#include + +struct err_record_info; + +struct ras_interrupt { + /* Interrupt number, and the associated error record info */ + unsigned int intr_number; + struct err_record_info *err_record; + void *cookie; +}; + +/* Function to probe a error record group for error */ +typedef int (*err_record_probe_t)(const struct err_record_info *info, + int *probe_data); + +/* Data passed to error record group handler */ +struct err_handler_data { + /* Info passed on from top-level exception handler */ + uint64_t flags; + void *cookie; + void *handle; + + /* Data structure version */ + unsigned int version; + + /* Reason for EA: one the ERROR_* constants */ + unsigned int ea_reason; + + /* + * For EAs received at vector, the value read from ESR; for an EA + * synchronized by ESB, the value of DISR. + */ + uint32_t syndrome; + + /* For errors signalled via interrupt, the raw interrupt ID; otherwise, 0. */ + unsigned int interrupt; +}; + +/* Function to handle error from an error record group */ +typedef int (*err_record_handler_t)(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data); + +/* Error record information */ +struct err_record_info { + /* Function to probe error record group for errors */ + err_record_probe_t probe; + + /* Function to handle error record group errors */ + err_record_handler_t handler; + + /* Opaque group-specific data */ + void *aux_data; + + /* Additional information for Standard Error Records */ + union { + struct { + /* + * For a group accessed via memory-mapped register, + * base address of the page hosting error records, and + * the size of the record group. + */ + uintptr_t base_addr; + + /* Size of group in number of KBs */ + unsigned int size_num_k; + } memmap; + + struct { + /* + * For error records accessed via system register, index of + * the error record. + */ + unsigned int idx_start; + unsigned int num_idx; + } sysreg; + }; + + /* Data structure version */ + unsigned int version; + + /* Error record access mechanism */ + unsigned int access:1; +}; + +struct err_record_mapping { + struct err_record_info *err_records; + size_t num_err_records; +}; + +struct ras_interrupt_mapping { + struct ras_interrupt *intrs; + size_t num_intrs; +}; + +extern const struct err_record_mapping err_record_mappings; +extern const struct ras_interrupt_mapping ras_interrupt_mappings; + + +/* + * Helper functions to probe memory-mapped and system registers implemented in + * Standard Error Record format + */ +static inline int ras_err_ser_probe_memmap(const struct err_record_info *info, + int *probe_data) +{ + assert(info->version == ERR_HANDLER_VERSION); + + return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, + probe_data); +} + +static inline int ras_err_ser_probe_sysreg(const struct err_record_info *info, + int *probe_data) +{ + assert(info->version == ERR_HANDLER_VERSION); + + return ser_probe_sysreg(info->sysreg.idx_start, info->sysreg.num_idx, + probe_data); +} + +const char *ras_serr_to_str(unsigned int serr); +int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); +void ras_init(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* RAS_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/ras_arch.h b/arm-trusted-firmware/include/lib/extensions/ras_arch.h new file mode 100644 index 0000000..8d9e474 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/ras_arch.h @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RAS_ARCH_H +#define RAS_ARCH_H + +/* + * Size of nodes implementing Standard Error Records - currently only 4k is + * supported. + */ +#define STD_ERR_NODE_SIZE_NUM_K 4U + +/* + * Individual register offsets within an error record in Standard Error Record + * format when error records are accessed through memory-mapped registers. + */ +#define ERR_FR(n) (0x0ULL + (64ULL * (n))) +#define ERR_CTLR(n) (0x8ULL + (64ULL * (n))) +#define ERR_STATUS(n) (0x10ULL + (64ULL * (n))) +#define ERR_ADDR(n) (0x18ULL + (64ULL * (n))) +#define ERR_MISC0(n) (0x20ULL + (64ULL * (n))) +#define ERR_MISC1(n) (0x28ULL + (64ULL * (n))) +#define ERR_MISC2(n) (0x30ULL + (64ULL * (n))) +#define ERR_MISC3(n) (0x38ULL + (64ULL * (n))) + +/* Group Status Register (ERR_STATUS) offset */ +#define ERR_GSR(base, size_num_k, n) \ + ((base) + (0x380ULL * (size_num_k)) + (8ULL * (n))) + +/* Management register offsets */ +#define ERR_DEVID(base, size_num_k) \ + ((base) + ((0x400ULL * (size_num_k)) - 0x100ULL) + 0xc8ULL) + +#define ERR_DEVID_MASK 0xffffUL + +/* Standard Error Record status register fields */ +#define ERR_STATUS_AV_SHIFT 31 +#define ERR_STATUS_AV_MASK U(0x1) + +#define ERR_STATUS_V_SHIFT 30 +#define ERR_STATUS_V_MASK U(0x1) + +#define ERR_STATUS_UE_SHIFT 29 +#define ERR_STATUS_UE_MASK U(0x1) + +#define ERR_STATUS_ER_SHIFT 28 +#define ERR_STATUS_ER_MASK U(0x1) + +#define ERR_STATUS_OF_SHIFT 27 +#define ERR_STATUS_OF_MASK U(0x1) + +#define ERR_STATUS_MV_SHIFT 26 +#define ERR_STATUS_MV_MASK U(0x1) + +#define ERR_STATUS_CE_SHIFT 24 +#define ERR_STATUS_CE_MASK U(0x3) + +#define ERR_STATUS_DE_SHIFT 23 +#define ERR_STATUS_DE_MASK U(0x1) + +#define ERR_STATUS_PN_SHIFT 22 +#define ERR_STATUS_PN_MASK U(0x1) + +#define ERR_STATUS_UET_SHIFT 20 +#define ERR_STATUS_UET_MASK U(0x3) + +#define ERR_STATUS_IERR_SHIFT 8 +#define ERR_STATUS_IERR_MASK U(0xff) + +#define ERR_STATUS_SERR_SHIFT 0 +#define ERR_STATUS_SERR_MASK U(0xff) + +#define ERR_STATUS_GET_FIELD(_status, _field) \ + (((_status) >> ERR_STATUS_ ##_field ##_SHIFT) & ERR_STATUS_ ##_field ##_MASK) + +#define ERR_STATUS_CLR_FIELD(_status, _field) \ + (_status) &= ~(ERR_STATUS_ ##_field ##_MASK << ERR_STATUS_ ##_field ##_SHIFT) + +#define ERR_STATUS_SET_FIELD(_status, _field, _value) \ + (_status) |= (((_value) & ERR_STATUS_ ##_field ##_MASK) << ERR_STATUS_ ##_field ##_SHIFT) + +#define ERR_STATUS_WRITE_FIELD(_status, _field, _value) do { \ + ERR_STATUS_CLR_FIELD(_status, _field, _value); \ + ERR_STATUS_SET_FIELD(_status, _field, _value); \ + } while (0) + + +/* Standard Error Record control register fields */ +#define ERR_CTLR_WDUI_SHIFT 11 +#define ERR_CTLR_WDUI_MASK 0x1 + +#define ERR_CTLR_RDUI_SHIFT 10 +#define ERR_CTLR_RDUI_MASK 0x1 +#define ERR_CTLR_DUI_SHIFT ERR_CTLR_RDUI_SHIFT +#define ERR_CTLR_DUI_MASK ERR_CTLR_RDUI_MASK + +#define ERR_CTLR_WCFI_SHIFT 9 +#define ERR_CTLR_WCFI_MASK 0x1 + +#define ERR_CTLR_RCFI_SHIFT U(8) +#define ERR_CTLR_RCFI_MASK ULL(0x1) +#define ERR_CTLR_CFI_SHIFT ERR_CTLR_RCFI_SHIFT +#define ERR_CTLR_CFI_MASK ERR_CTLR_RCFI_MASK + +#define ERR_CTLR_WUE_SHIFT 7 +#define ERR_CTLR_WUE_MASK 0x1 + +#define ERR_CTLR_WFI_SHIFT 6 +#define ERR_CTLR_WFI_MASK 0x1 + +#define ERR_CTLR_WUI_SHIFT 5 +#define ERR_CTLR_WUI_MASK 0x1 + +#define ERR_CTLR_RUE_SHIFT 4 +#define ERR_CTLR_RUE_MASK 0x1 +#define ERR_CTLR_UE_SHIFT ERR_CTLR_RUE_SHIFT +#define ERR_CTLR_UE_MASK ERR_CTLR_RUE_MASK + +#define ERR_CTLR_RFI_SHIFT 3 +#define ERR_CTLR_RFI_MASK 0x1 +#define ERR_CTLR_FI_SHIFT ERR_CTLR_RFI_SHIFT +#define ERR_CTLR_FI_MASK ERR_CTLR_RFI_MASK + +#define ERR_CTLR_RUI_SHIFT 2 +#define ERR_CTLR_RUI_MASK 0x1 +#define ERR_CTLR_UI_SHIFT ERR_CTLR_RUI_SHIFT +#define ERR_CTLR_UI_MASK ERR_CTLR_RUI_MASK + +#define ERR_CTLR_ED_SHIFT 0 +#define ERR_CTLR_ED_MASK 0x1 + +#define ERR_CTLR_CLR_FIELD(_ctlr, _field) \ + (_ctlr) &= ~(ERR_CTLR_ ##_field _MASK << ERR_CTLR_ ##_field ##_SHIFT) + +#define ERR_CTLR_SET_FIELD(_ctlr, _field, _value) \ + (_ctlr) |= (((_value) & ERR_CTLR_ ##_field ##_MASK) << ERR_CTLR_ ##_field ##_SHIFT) + +#define ERR_CTLR_ENABLE_FIELD(_ctlr, _field) \ + ERR_CTLR_SET_FIELD(_ctlr, _field, ERR_CTLR_ ##_field ##_MASK) + +/* Uncorrected error types for Asynchronous exceptions */ +#define ERROR_STATUS_UET_UC 0x0 /* Uncontainable */ +#define ERROR_STATUS_UET_UEU 0x1 /* Unrecoverable */ +#define ERROR_STATUS_UET_UEO 0x2 /* Restable */ +#define ERROR_STATUS_UET_UER 0x3 /* Recoverable */ + +/* Error types for Synchronous exceptions */ +#define ERROR_STATUS_SET_UER 0x0 /* Recoverable */ +#define ERROR_STATUS_SET_UEO 0x1 /* Restable */ +#define ERROR_STATUS_SET_UC 0x2 /* Uncontainable */ +#define ERROR_STATUS_SET_CE 0x3 /* Corrected */ + +/* Number of architecturally-defined primary error codes */ +#define ERROR_STATUS_NUM_SERR U(22) + +/* Implementation Defined Syndrome bit in ESR */ +#define SERROR_IDS_BIT U(24) + +/* + * Asynchronous Error Type in exception syndrome. The field has same values in + * both DISR_EL1 and ESR_EL3 for SError. + */ +#define EABORT_AET_SHIFT U(10) +#define EABORT_AET_WIDTH U(3) +#define EABORT_AET_MASK U(0x7) + +/* DFSC field in Asynchronous exception syndrome */ +#define EABORT_DFSC_SHIFT U(0) +#define EABORT_DFSC_WIDTH U(6) +#define EABORT_DFSC_MASK U(0x3f) + +/* Synchronous Error Type in exception syndrome. */ +#define EABORT_SET_SHIFT U(11) +#define EABORT_SET_WIDTH U(2) +#define EABORT_SET_MASK U(0x3) + +/* DFSC code for SErrors */ +#define DFSC_SERROR 0x11 + +/* I/DFSC code for synchronous external abort */ +#define SYNC_EA_FSC 0x10 + +#ifndef __ASSEMBLER__ + +#include +#include +#include +#include +#include +#include + +/* + * Standard Error Record accessors for memory-mapped registers. + */ + +static inline uint64_t ser_get_feature(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_FR(idx)); +} + +static inline uint64_t ser_get_control(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_CTLR(idx)); +} + +static inline uint64_t ser_get_status(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_STATUS(idx)); +} + +/* + * Error handling agent would write to the status register to clear an + * identified/handled error. Most fields in the status register are + * conditional write-one-to-clear. + * + * Typically, to clear the status, it suffices to write back the same value + * previously read. However, if there were new, higher-priority errors recorded + * on the node since status was last read, writing read value won't clear the + * status. Therefore, an error handling agent must wait on and verify the status + * has indeed been cleared. + */ +static inline void ser_set_status(uintptr_t base, unsigned int idx, + uint64_t status) +{ + mmio_write_64(base + ERR_STATUS(idx), status); +} + +static inline uint64_t ser_get_addr(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_ADDR(idx)); +} + +static inline uint64_t ser_get_misc0(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_MISC0(idx)); +} + +static inline uint64_t ser_get_misc1(uintptr_t base, unsigned int idx) +{ + return mmio_read_64(base + ERR_MISC1(idx)); +} + + +/* + * Standard Error Record helpers for System registers. + */ +static inline void ser_sys_select_record(unsigned int idx) +{ + unsigned int max_idx __unused = + (unsigned int) read_erridr_el1() & ERRIDR_MASK; + + assert(idx < max_idx); + + write_errselr_el1(idx); + isb(); +} + +/* Library functions to probe Standard Error Record */ +int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data); +int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data); +#endif /* __ASSEMBLER__ */ + +#endif /* RAS_ARCH_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/sme.h b/arm-trusted-firmware/include/lib/extensions/sme.h new file mode 100644 index 0000000..893f9f2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sme.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SME_H +#define SME_H + +#include + +#include + +/* + * Maximum value of LEN field in SMCR_ELx. This is different than the maximum + * supported value which is platform dependent. In the first version of SME the + * LEN field is limited to 4 bits but will be expanded in future iterations. + * To support different versions, the code that discovers the supported vector + * lengths will write the max value into SMCR_ELx then read it back to see how + * many bits are implemented. + */ +#define SME_SMCR_LEN_MAX U(0x1FF) + +void sme_enable(cpu_context_t *context); +void sme_disable(cpu_context_t *context); + +#endif /* SME_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/spe.h b/arm-trusted-firmware/include/lib/extensions/spe.h new file mode 100644 index 0000000..d4b925f --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/spe.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPE_H +#define SPE_H + +#include + +bool spe_supported(void); +void spe_enable(bool el2_unused); +void spe_disable(void); + +#endif /* SPE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/sve.h b/arm-trusted-firmware/include/lib/extensions/sve.h new file mode 100644 index 0000000..4b66cdb --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sve.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SVE_H +#define SVE_H + +#include + +void sve_enable(cpu_context_t *context); +void sve_disable(cpu_context_t *context); + +#endif /* SVE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h b/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h new file mode 100644 index 0000000..74470fe --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SYS_REG_TRACE_H +#define SYS_REG_TRACE_H + +#include + +#if __aarch64__ +void sys_reg_trace_enable(cpu_context_t *context); +#else +void sys_reg_trace_enable(void); +#endif /* __aarch64__ */ + +#endif /* SYS_REG_TRACE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/trbe.h b/arm-trusted-firmware/include/lib/extensions/trbe.h new file mode 100644 index 0000000..1753ab6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/trbe.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRBE_H +#define TRBE_H + +void trbe_enable(void); + +#endif /* TRBE_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/trf.h b/arm-trusted-firmware/include/lib/extensions/trf.h new file mode 100644 index 0000000..18f17f3 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/trf.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRF_H +#define TRF_H + +void trf_enable(void); + +#endif /* TRF_H */ diff --git a/arm-trusted-firmware/include/lib/extensions/twed.h b/arm-trusted-firmware/include/lib/extensions/twed.h new file mode 100644 index 0000000..eac4aa3 --- /dev/null +++ b/arm-trusted-firmware/include/lib/extensions/twed.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TWED_H +#define TWED_H + +#include + +#define TWED_DISABLED U(0xFFFFFFFF) + +uint32_t plat_arm_set_twedel_scr_el3(void); + +#endif /* TWEDE_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf.h b/arm-trusted-firmware/include/lib/fconf/fconf.h new file mode 100644 index 0000000..917e053 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_H +#define FCONF_H + +#include + +/* Public API */ +#define FCONF_GET_PROPERTY(a, b, c) a##__##b##_getter(c) + +/* + * This macro takes three arguments: + * config: Configuration identifier + * name: property namespace + * callback: populate() function + */ +#define FCONF_REGISTER_POPULATOR(config, name, callback) \ + __attribute__((used, section(".fconf_populator"))) \ + const struct fconf_populator (name##__populator) = { \ + .config_type = (#config), \ + .info = (#name), \ + .populate = (callback) \ + }; + +/* + * Populator callback + * + * This structure are used by the fconf_populate function and should only be + * defined by the FCONF_REGISTER_POPULATOR macro. + */ +struct fconf_populator { + /* Description of the data loaded by the callback */ + const char *config_type; + const char *info; + + /* Callback used by fconf_populate function with a provided config dtb. + * Return 0 on success, err_code < 0 otherwise. + */ + int (*populate)(uintptr_t config); +}; + +/* This function supports to load tb_fw_config and fw_config dtb */ +int fconf_load_config(unsigned int image_id); + +/* Top level populate function + * + * This function takes a configuration dtb and calls all the registered + * populator callback with it. + * + * Panic on error. + */ +void fconf_populate(const char *config_type, uintptr_t config); + +/* FCONF specific getter */ +#define fconf__dtb_getter(prop) fconf_dtb_info.prop + +/* Structure used to locally keep a reference to the config dtb. */ +struct fconf_dtb_info_t { + uintptr_t base_addr; + size_t size; +}; + +extern struct fconf_dtb_info_t fconf_dtb_info; + +#endif /* FCONF_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h new file mode 100644 index 0000000..2faee73 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_AMU_GETTER_H +#define FCONF_AMU_GETTER_H + +#include + +#define amu__config_getter(id) fconf_amu_config.id + +struct fconf_amu_config { + const struct amu_topology *topology; +}; + +extern struct fconf_amu_config fconf_amu_config; + +#endif /* FCONF_AMU_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h new file mode 100644 index 0000000..ff51c6c --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_DYN_CFG_GETTER_H +#define FCONF_DYN_CFG_GETTER_H + +#include + +#define FCONF_INVALID_IDX 0xFFFFFFFFU + +/* Dynamic configuration related getter */ +#define dyn_cfg__dtb_getter(id) dyn_cfg_dtb_info_getter(id) + +struct dyn_cfg_dtb_info_t { + uintptr_t config_addr; + uint32_t config_max_size; + unsigned int config_id; +}; + +unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id); +struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id); +int fconf_populate_dtb_registry(uintptr_t config); + +/* Set config information in global DTB array */ +void set_config_info(uintptr_t config_addr, uint32_t config_max_size, + unsigned int config_id); + +#endif /* FCONF_DYN_CFG_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h new file mode 100644 index 0000000..50d991a --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_MPMM_GETTER_H +#define FCONF_MPMM_GETTER_H + +#include + +#define mpmm__config_getter(id) fconf_mpmm_config.id + +struct fconf_mpmm_config { + const struct mpmm_topology *topology; +}; + +extern struct fconf_mpmm_config fconf_mpmm_config; + +#endif /* FCONF_MPMM_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h b/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h new file mode 100644 index 0000000..db98b68 --- /dev/null +++ b/arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_TBBR_GETTER_H +#define FCONF_TBBR_GETTER_H + +#include + +#include + +/* TBBR related getter */ +#define tbbr__cot_getter(id) __extension__ ({ \ + assert((id) < cot_desc_size); \ + cot_desc_ptr[id]; \ +}) + +#define tbbr__dyn_config_getter(id) tbbr_dyn_config.id + +struct tbbr_dyn_config_t { + uint32_t disable_auth; + void *mbedtls_heap_addr; + size_t mbedtls_heap_size; +}; + +extern struct tbbr_dyn_config_t tbbr_dyn_config; + +int fconf_populate_tbbr_dyn_config(uintptr_t config); + +#endif /* FCONF_TBBR_GETTER_H */ diff --git a/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h b/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h new file mode 100644 index 0000000..94a88b0 --- /dev/null +++ b/arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_RME_H +#define GPT_RME_H + +#include + +#include + +/******************************************************************************/ +/* GPT helper macros and definitions */ +/******************************************************************************/ + +/* + * Structure for specifying a mapping range and it's properties. This should not + * be manually initialized, using the MAP_GPT_REGION_x macros is recommended as + * to avoid potential incompatibilities in the future. + */ +typedef struct pas_region { + uintptr_t base_pa; /* Base address for PAS. */ + size_t size; /* Size of the PAS. */ + unsigned int attrs; /* PAS GPI and entry type. */ +} pas_region_t; + +/* GPT GPI definitions */ +#define GPT_GPI_NO_ACCESS U(0x0) +#define GPT_GPI_SECURE U(0x8) +#define GPT_GPI_NS U(0x9) +#define GPT_GPI_ROOT U(0xA) +#define GPT_GPI_REALM U(0xB) +#define GPT_GPI_ANY U(0xF) +#define GPT_GPI_VAL_MASK UL(0xF) + +#define GPT_NSE_SECURE U(0b00) +#define GPT_NSE_ROOT U(0b01) +#define GPT_NSE_NS U(0b10) +#define GPT_NSE_REALM U(0b11) + +#define GPT_NSE_SHIFT U(62) + +/* PAS attribute GPI definitions. */ +#define GPT_PAS_ATTR_GPI_SHIFT U(0) +#define GPT_PAS_ATTR_GPI_MASK U(0xF) +#define GPT_PAS_ATTR_GPI(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_GPI_SHIFT) \ + & GPT_PAS_ATTR_GPI_MASK) + +/* PAS attribute mapping type definitions */ +#define GPT_PAS_ATTR_MAP_TYPE_BLOCK U(0x0) +#define GPT_PAS_ATTR_MAP_TYPE_GRANULE U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE_SHIFT U(4) +#define GPT_PAS_ATTR_MAP_TYPE_MASK U(0x1) +#define GPT_PAS_ATTR_MAP_TYPE(_attrs) (((_attrs) \ + >> GPT_PAS_ATTR_MAP_TYPE_SHIFT) \ + & GPT_PAS_ATTR_MAP_TYPE_MASK) + +/* + * Macro to initialize the attributes field in the pas_region_t structure. + * [31:5] Reserved + * [4] Mapping type (GPT_PAS_ATTR_MAP_TYPE_x definitions) + * [3:0] PAS GPI type (GPT_GPI_x definitions) + */ +#define GPT_PAS_ATTR(_type, _gpi) \ + ((((_type) & GPT_PAS_ATTR_MAP_TYPE_MASK) \ + << GPT_PAS_ATTR_MAP_TYPE_SHIFT) | \ + (((_gpi) & GPT_PAS_ATTR_GPI_MASK) \ + << GPT_PAS_ATTR_GPI_SHIFT)) + +/* + * Macro to create a GPT entry for this PAS range as a block descriptor. If this + * region does not fit the requirements for a block descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_BLOCK(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_BLOCK, (_gpi)), \ + } + +/* + * Macro to create a GPT entry for this PAS range as a table descriptor. If this + * region does not fit the requirements for a table descriptor then GPT + * initialization will fail. + */ +#define GPT_MAP_REGION_GRANULE(_pa, _sz, _gpi) \ + { \ + .base_pa = (_pa), \ + .size = (_sz), \ + .attrs = GPT_PAS_ATTR(GPT_PAS_ATTR_MAP_TYPE_GRANULE, (_gpi)), \ + } + +/******************************************************************************/ +/* GPT register field definitions */ +/******************************************************************************/ + +/* + * Least significant address bits protected by each entry in level 0 GPT. This + * field is read-only. + */ +#define GPCCR_L0GPTSZ_SHIFT U(20) +#define GPCCR_L0GPTSZ_MASK U(0xF) + +typedef enum { + GPCCR_L0GPTSZ_30BITS = U(0x0), + GPCCR_L0GPTSZ_34BITS = U(0x4), + GPCCR_L0GPTSZ_36BITS = U(0x6), + GPCCR_L0GPTSZ_39BITS = U(0x9) +} gpccr_l0gptsz_e; + +/* Granule protection check priority bit definitions */ +#define GPCCR_GPCP_SHIFT U(17) +#define GPCCR_GPCP_BIT (ULL(1) << GPCCR_EL3_GPCP_SHIFT) + +/* Granule protection check bit definitions */ +#define GPCCR_GPC_SHIFT U(16) +#define GPCCR_GPC_BIT (ULL(1) << GPCCR_GPC_SHIFT) + +/* Physical granule size bit definitions */ +#define GPCCR_PGS_SHIFT U(14) +#define GPCCR_PGS_MASK U(0x3) +#define SET_GPCCR_PGS(x) (((x) & GPCCR_PGS_MASK) << GPCCR_PGS_SHIFT) + +typedef enum { + GPCCR_PGS_4K = U(0x0), + GPCCR_PGS_64K = U(0x1), + GPCCR_PGS_16K = U(0x2) +} gpccr_pgs_e; + +/* GPT fetch shareability attribute bit definitions */ +#define GPCCR_SH_SHIFT U(12) +#define GPCCR_SH_MASK U(0x3) +#define SET_GPCCR_SH(x) (((x) & GPCCR_SH_MASK) << GPCCR_SH_SHIFT) + +typedef enum { + GPCCR_SH_NS = U(0x0), + GPCCR_SH_OS = U(0x2), + GPCCR_SH_IS = U(0x3) +} gpccr_sh_e; + +/* GPT fetch outer cacheability attribute bit definitions */ +#define GPCCR_ORGN_SHIFT U(10) +#define GPCCR_ORGN_MASK U(0x3) +#define SET_GPCCR_ORGN(x) (((x) & GPCCR_ORGN_MASK) << GPCCR_ORGN_SHIFT) + +typedef enum { + GPCCR_ORGN_NC = U(0x0), + GPCCR_ORGN_WB_RA_WA = U(0x1), + GPCCR_ORGN_WT_RA_NWA = U(0x2), + GPCCR_ORGN_WB_RA_NWA = U(0x3) +} gpccr_orgn_e; + +/* GPT fetch inner cacheability attribute bit definitions */ +#define GPCCR_IRGN_SHIFT U(8) +#define GPCCR_IRGN_MASK U(0x3) +#define SET_GPCCR_IRGN(x) (((x) & GPCCR_IRGN_MASK) << GPCCR_IRGN_SHIFT) + +typedef enum { + GPCCR_IRGN_NC = U(0x0), + GPCCR_IRGN_WB_RA_WA = U(0x1), + GPCCR_IRGN_WT_RA_NWA = U(0x2), + GPCCR_IRGN_WB_RA_NWA = U(0x3) +} gpccr_irgn_e; + +/* Protected physical address size bit definitions */ +#define GPCCR_PPS_SHIFT U(0) +#define GPCCR_PPS_MASK U(0x7) +#define SET_GPCCR_PPS(x) (((x) & GPCCR_PPS_MASK) << GPCCR_PPS_SHIFT) + +typedef enum { + GPCCR_PPS_4GB = U(0x0), + GPCCR_PPS_64GB = U(0x1), + GPCCR_PPS_1TB = U(0x2), + GPCCR_PPS_4TB = U(0x3), + GPCCR_PPS_16TB = U(0x4), + GPCCR_PPS_256TB = U(0x5), + GPCCR_PPS_4PB = U(0x6) +} gpccr_pps_e; + +/* Base Address for the GPT bit definitions */ +#define GPTBR_BADDR_SHIFT U(0) +#define GPTBR_BADDR_VAL_SHIFT U(12) +#define GPTBR_BADDR_MASK ULL(0xffffffffff) + +/******************************************************************************/ +/* GPT public APIs */ +/******************************************************************************/ + +/* + * Public API that initializes the entire protected space to GPT_GPI_ANY using + * the L0 tables (block descriptors). Ideally, this function is invoked prior + * to DDR discovery and initialization. The MMU must be initialized before + * calling this function. + * + * Parameters + * pps PPS value to use for table generation + * l0_mem_base Base address of L0 tables in memory. + * l0_mem_size Total size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_l0_tables(gpccr_pps_e pps, + uintptr_t l0_mem_base, + size_t l0_mem_size); + +/* + * Public API that carves out PAS regions from the L0 tables and builds any L1 + * tables that are needed. This function ideally is run after DDR discovery and + * initialization. The L0 tables must have already been initialized to GPI_ANY + * when this function is called. + * + * Parameters + * pgs PGS value to use for table generation. + * l1_mem_base Base address of memory used for L1 tables. + * l1_mem_size Total size of memory available for L1 tables. + * *pas_regions Pointer to PAS regions structure array. + * pas_count Total number of PAS regions. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, + uintptr_t l1_mem_base, + size_t l1_mem_size, + pas_region_t *pas_regions, + unsigned int pas_count); + +/* + * Public API to initialize the runtime gpt_config structure based on the values + * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization + * typically happens in a bootloader stage prior to setting up the EL3 runtime + * environment for the granule transition service so this function detects the + * initialization from a previous stage. Granule protection checks must be + * enabled already or this function will return an error. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_runtime_init(void); + +/* + * Public API to enable granule protection checks once the tables have all been + * initialized. This function is called at first initialization and then again + * later during warm boots of CPU cores. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_enable(void); + +/* + * Public API to disable granule protection checks. + */ +void gpt_disable(void); + +/* + * This function is the core of the granule transition service. When a granule + * transition request occurs it is routed to this function where the request is + * validated then fulfilled if possible. + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base: Base address of the region to transition, must be aligned to granule + * size. + * size: Size of region to transition, must be aligned to granule size. + * src_sec_state: Security state of the originating SMC invoking the API. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); +int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state); + +#endif /* GPT_RME_H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h b/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h new file mode 100644 index 0000000..0cf2c75 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/endian_.h @@ -0,0 +1,146 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 David E. O'Brien + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ENDIAN__H +#define ENDIAN__H + +#include + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#ifdef __ARMEB__ +#define _BYTE_ORDER _BIG_ENDIAN +#else +#define _BYTE_ORDER _LITTLE_ENDIAN +#endif /* __ARMEB__ */ + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#ifdef __ARMEB__ +#define _QUAD_HIGHWORD 0 +#define _QUAD_LOWWORD 1 +#define __ntohl(x) ((uint32_t)(x)) +#define __ntohs(x) ((uint16_t)(x)) +#define __htonl(x) ((uint32_t)(x)) +#define __htons(x) ((uint16_t)(x)) +#else +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#define __ntohl(x) (__bswap32(x)) +#define __ntohs(x) (__bswap16(x)) +#define __htonl(x) (__bswap32(x)) +#define __htons(x) (__bswap16(x)) +#endif /* __ARMEB__ */ + +static __inline uint64_t +__bswap64(uint64_t _x) +{ + + return ((_x >> 56) | ((_x >> 40) & 0xff00) | ((_x >> 24) & 0xff0000) | + ((_x >> 8) & 0xff000000) | ((_x << 8) & ((uint64_t)0xff << 32)) | + ((_x << 24) & ((uint64_t)0xff << 40)) | + ((_x << 40) & ((uint64_t)0xff << 48)) | ((_x << 56))); +} + +static __inline uint32_t +__bswap32_var(uint32_t v) +{ + uint32_t t1; + + __asm __volatile("eor %1, %0, %0, ror #16\n" + "bic %1, %1, #0x00ff0000\n" + "mov %0, %0, ror #8\n" + "eor %0, %0, %1, lsr #8\n" + : "+r" (v), "=r" (t1)); + + return (v); +} + +static __inline uint16_t +__bswap16_var(uint16_t v) +{ + uint32_t ret = v & 0xffff; + + __asm __volatile( + "mov %0, %0, ror #8\n" + "orr %0, %0, %0, lsr #16\n" + "bic %0, %0, %0, lsl #16" + : "+r" (ret)); + + return ((uint16_t)ret); +} + +#ifdef __OPTIMIZE__ + +#define __bswap32_constant(x) \ + ((((x) & 0xff000000U) >> 24) | \ + (((x) & 0x00ff0000U) >> 8) | \ + (((x) & 0x0000ff00U) << 8) | \ + (((x) & 0x000000ffU) << 24)) + +#define __bswap16_constant(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +#define __bswap16(x) \ + ((uint16_t)(__builtin_constant_p(x) ? \ + __bswap16_constant(x) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant(x) : \ + __bswap32_var(x))) + +#else +#define __bswap16(x) __bswap16_var(x) +#define __bswap32(x) __bswap32_var(x) + +#endif /* __OPTIMIZE__ */ +#endif /* ENDIAN__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h b/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h new file mode 100644 index 0000000..11d2d35 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES__H +#define INTTYPES__H + +#define PRId64 "lld" /* int64_t */ +#define PRIi64 "lli" /* int64_t */ +#define PRIo64 "llo" /* int64_t */ +#define PRIu64 "llu" /* uint64_t */ +#define PRIx64 "llx" /* uint64_t */ +#define PRIX64 "llX" /* uint64_t */ + +#endif /* INTTYPES__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/limits_.h b/arm-trusted-firmware/include/lib/libc/aarch32/limits_.h new file mode 100644 index 0000000..26cec17 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/limits_.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN - 1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX - 1) +#define UCHAR_MAX 0xFFU +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX 0xFFFFU +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX 0xFFFFFFFFU +#define LONG_MAX 0x7FFFFFFFL +#define LONG_MIN (-LONG_MAX - 1L) +#define ULONG_MAX 0xFFFFFFFFUL +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define LLONG_MIN (-LLONG_MAX - 1LL) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +#define __LONG_BIT 32 +#define __WORD_BIT 32 diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h new file mode 100644 index 0000000..36dc20b --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDDEF__H +#define STDDEF__H + +#ifndef SIZET_ +typedef unsigned int size_t; +#define SIZET_ +#endif + +#endif /* STDDEF__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h new file mode 100644 index 0000000..dafe142 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h @@ -0,0 +1,28 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT__H +#define STDINT__H + +#define INT64_MAX LLONG_MAX +#define INT64_MIN LLONG_MIN +#define UINT64_MAX ULLONG_MAX + +#define INT64_C(x) x ## LL +#define UINT64_C(x) x ## ULL + +typedef long long int64_t; +typedef unsigned long long uint64_t; +typedef long long int64_least_t; +typedef unsigned long long uint64_least_t; +typedef long long int64_fast_t; +typedef unsigned long long uint64_fast_t; + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h b/arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h new file mode 100644 index 0000000..5e49425 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDIO__H +#define STDIO__H + +#ifndef SSIZET_ +typedef int ssize_t; +#define SSIZET_ +#endif + +#endif /* STDIO__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/endian_.h b/arm-trusted-firmware/include/lib/libc/aarch64/endian_.h new file mode 100644 index 0000000..7c79fd4 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/endian_.h @@ -0,0 +1,128 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 2001 David E. O'Brien + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)endian.h 8.1 (Berkeley) 6/10/93 + * $NetBSD: endian.h,v 1.7 1999/08/21 05:53:51 simonb Exp $ + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ENDIAN__H +#define ENDIAN__H + +#include + +/* + * Definitions for byte order, according to byte significance from low + * address to high. + */ +#define _LITTLE_ENDIAN 1234 /* LSB first: i386, vax */ +#define _BIG_ENDIAN 4321 /* MSB first: 68000, ibm, net */ +#define _PDP_ENDIAN 3412 /* LSB first in word, MSW first in long */ + +#define _BYTE_ORDER _LITTLE_ENDIAN + +#if __BSD_VISIBLE +#define LITTLE_ENDIAN _LITTLE_ENDIAN +#define BIG_ENDIAN _BIG_ENDIAN +#define PDP_ENDIAN _PDP_ENDIAN +#define BYTE_ORDER _BYTE_ORDER +#endif + +#define _QUAD_HIGHWORD 1 +#define _QUAD_LOWWORD 0 +#define __ntohl(x) (__bswap32(x)) +#define __ntohs(x) (__bswap16(x)) +#define __htonl(x) (__bswap32(x)) +#define __htons(x) (__bswap16(x)) + +static __inline uint64_t +__bswap64(uint64_t x) +{ + uint64_t ret; + + __asm __volatile("rev %0, %1\n" + : "=&r" (ret), "+r" (x)); + + return (ret); +} + +static __inline uint32_t +__bswap32_var(uint32_t v) +{ + uint32_t ret; + + __asm __volatile("rev32 %x0, %x1\n" + : "=&r" (ret), "+r" (v)); + + return (ret); +} + +static __inline uint16_t +__bswap16_var(uint16_t v) +{ + uint32_t ret; + + __asm __volatile("rev16 %w0, %w1\n" + : "=&r" (ret), "+r" (v)); + + return ((uint16_t)ret); +} + +#ifdef __OPTIMIZE__ + +#define __bswap32_constant(x) \ + ((((x) & 0xff000000U) >> 24) | \ + (((x) & 0x00ff0000U) >> 8) | \ + (((x) & 0x0000ff00U) << 8) | \ + (((x) & 0x000000ffU) << 24)) + +#define __bswap16_constant(x) \ + ((((x) & 0xff00) >> 8) | \ + (((x) & 0x00ff) << 8)) + +#define __bswap16(x) \ + ((uint16_t)(__builtin_constant_p(x) ? \ + __bswap16_constant((uint16_t)(x)) : \ + __bswap16_var(x))) + +#define __bswap32(x) \ + ((uint32_t)(__builtin_constant_p(x) ? \ + __bswap32_constant((uint32_t)(x)) : \ + __bswap32_var(x))) + +#else +#define __bswap16(x) __bswap16_var(x) +#define __bswap32(x) __bswap32_var(x) + +#endif /* __OPTIMIZE__ */ +#endif /* ENDIAN__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h b/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h new file mode 100644 index 0000000..197d627 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h @@ -0,0 +1,21 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES__H +#define INTTYPES__H + +#define PRId64 "ld" /* int64_t */ +#define PRIi64 "li" /* int64_t */ +#define PRIo64 "lo" /* int64_t */ +#define PRIu64 "lu" /* uint64_t */ +#define PRIx64 "lx" /* uint64_t */ +#define PRIX64 "lX" /* uint64_t */ + +#endif /* INTTYPES__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/limits_.h b/arm-trusted-firmware/include/lib/libc/aarch64/limits_.h new file mode 100644 index 0000000..e36cfe7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/limits_.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define SCHAR_MAX 0x7F +#define SCHAR_MIN (-SCHAR_MIN - 1) +#define CHAR_MAX 0x7F +#define CHAR_MIN (-CHAR_MAX - 1) +#define UCHAR_MAX 0xFFU +#define SHRT_MAX 0x7FFF +#define SHRT_MIN (-SHRT_MAX - 1) +#define USHRT_MAX 0xFFFFU +#define INT_MAX 0x7FFFFFFF +#define INT_MIN (-INT_MAX - 1) +#define UINT_MAX 0xFFFFFFFFU +#define LONG_MAX 0x7FFFFFFFFFFFFFFFL +#define LONG_MIN (-LONG_MAX - 1L) +#define ULONG_MAX 0xFFFFFFFFFFFFFFFFUL +#define LLONG_MAX 0x7FFFFFFFFFFFFFFFLL +#define LLONG_MIN (-LLONG_MAX - 1LL) +#define ULLONG_MAX 0xFFFFFFFFFFFFFFFFULL + +#define __LONG_BIT 64 +#define __WORD_BIT 32 diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h b/arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h new file mode 100644 index 0000000..f880a17 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SETJMP__H +#define SETJMP__H + +#define JMP_CTX_X19 0x0 +#define JMP_CTX_X21 0x10 +#define JMP_CTX_X23 0x20 +#define JMP_CTX_X25 0x30 +#define JMP_CTX_X27 0x40 +#define JMP_CTX_X29 0x50 +#define JMP_CTX_SP 0x60 +#define JMP_CTX_END 0x70 /* Aligned to 16 bytes */ + +#define JMP_SIZE (JMP_CTX_END >> 3) + +#ifndef __ASSEMBLER__ + +#include + +/* Jump buffer hosting x18 - x30 and sp_el0 registers */ +typedef uint64_t jmp_buf[JMP_SIZE] __aligned(16); + +#endif /* __ASSEMBLER__ */ + +#endif /* SETJMP__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h new file mode 100644 index 0000000..6ecc606 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDDEF__H +#define STDDEF__H + +#ifndef SIZET_ +typedef unsigned long size_t; +#define SIZET_ +#endif + +#endif /* STDDEF__H */ diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h new file mode 100644 index 0000000..56e9f1b --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h @@ -0,0 +1,31 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT__H +#define STDINT__H + +#define INT64_MAX LONG_MAX +#define INT64_MIN LONG_MIN +#define UINT64_MAX ULONG_MAX + +#define INT64_C(x) x ## L +#define UINT64_C(x) x ## UL + +typedef long int64_t; +typedef unsigned long uint64_t; +typedef long int64_least_t; +typedef unsigned long uint64_least_t; +typedef long int64_fast_t; +typedef unsigned long uint64_fast_t; + +typedef __int128 int128_t; +typedef unsigned __int128 uint128_t; + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h b/arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h new file mode 100644 index 0000000..afaeadc --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDIO__H +#define STDIO__H + +#ifndef SSIZET_ +typedef long ssize_t; +#define SSIZET_ +#endif + +#endif /* STDIO__H */ diff --git a/arm-trusted-firmware/include/lib/libc/arm_acle.h b/arm-trusted-firmware/include/lib/libc/arm_acle.h new file mode 100644 index 0000000..eb08552 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/arm_acle.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2021 ARM Limited + * + * SPDX-License-Identifier: BSD-3-Clause + * + * The definitions below are a subset of what we would normally get by using + * the compiler's version of arm_acle.h. We can't use that directly because + * we specify -nostdinc in the Makefiles. + * + * We just define the functions we need so far. + */ + +#ifndef ARM_ACLE_H +#define ARM_ACLE_H + +#if !defined(__aarch64__) || defined(__clang__) +# define __crc32b __builtin_arm_crc32b +# define __crc32w __builtin_arm_crc32w +#else +# define __crc32b __builtin_aarch64_crc32b +# define __crc32w __builtin_aarch64_crc32w +#endif + +#endif /* ARM_ACLE_H */ diff --git a/arm-trusted-firmware/include/lib/libc/assert.h b/arm-trusted-firmware/include/lib/libc/assert.h new file mode 100644 index 0000000..486bbc2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/assert.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ASSERT_H +#define ASSERT_H + +#include + +#include + +#include + +#ifndef PLAT_LOG_LEVEL_ASSERT +#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL +#endif + +#if ENABLE_ASSERTIONS +# if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__, #e)) +# elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +# define assert(e) ((e) ? (void)0 : __assert(__FILE__, __LINE__)) +# else +# define assert(e) ((e) ? (void)0 : __assert()) +# endif +#else +#define assert(e) ((void)0) +#endif /* ENABLE_ASSERTIONS */ + +#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +void __dead2 __assert(const char *file, unsigned int line, + const char *assertion); +#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +void __dead2 __assert(const char *file, unsigned int line); +#else +void __dead2 __assert(void); +#endif + +#endif /* ASSERT_H */ diff --git a/arm-trusted-firmware/include/lib/libc/cdefs.h b/arm-trusted-firmware/include/lib/libc/cdefs.h new file mode 100644 index 0000000..0d00722 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/cdefs.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CDEFS_H +#define CDEFS_H + +#define __dead2 __attribute__((__noreturn__)) +#define __deprecated __attribute__((__deprecated__)) +#define __packed __attribute__((__packed__)) +#define __used __attribute__((__used__)) +#define __unused __attribute__((__unused__)) +#define __aligned(x) __attribute__((__aligned__(x))) +#define __section(x) __attribute__((__section__(x))) +#if RECLAIM_INIT_CODE +/* + * Add each function to a section that is unique so the functions can still + * be garbage collected + */ +#define __init __section(".text.init." __FILE__ "." __XSTRING(__LINE__)) +#else +#define __init +#endif + +#define __printflike(fmtarg, firstvararg) \ + __attribute__((__format__ (__printf__, fmtarg, firstvararg))) + +#define __weak_reference(sym, alias) \ + __asm__(".weak alias"); \ + __asm__(".equ alias, sym") + +#define __STRING(x) #x +#define __XSTRING(x) __STRING(x) + +#endif /* CDEFS_H */ diff --git a/arm-trusted-firmware/include/lib/libc/endian.h b/arm-trusted-firmware/include/lib/libc/endian.h new file mode 100644 index 0000000..4100f57 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/endian.h @@ -0,0 +1,191 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2002 Thomas Moestl + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ENDIAN_H +#define ENDIAN_H + +#include +#include +#include + +/* + * General byte order swapping functions. + */ +#define bswap16(x) __bswap16(x) +#define bswap32(x) __bswap32(x) +#define bswap64(x) __bswap64(x) + +/* + * Host to big endian, host to little endian, big endian to host, and little + * endian to host byte order functions as detailed in byteorder(9). + */ +#if _BYTE_ORDER == _LITTLE_ENDIAN +#define htobe16(x) bswap16((x)) +#define htobe32(x) bswap32((x)) +#define htobe64(x) bswap64((x)) +#define htole16(x) ((uint16_t)(x)) +#define htole32(x) ((uint32_t)(x)) +#define htole64(x) ((uint64_t)(x)) + +#define be16toh(x) bswap16((x)) +#define be32toh(x) bswap32((x)) +#define be64toh(x) bswap64((x)) +#define le16toh(x) ((uint16_t)(x)) +#define le32toh(x) ((uint32_t)(x)) +#define le64toh(x) ((uint64_t)(x)) +#else /* _BYTE_ORDER != _LITTLE_ENDIAN */ +#define htobe16(x) ((uint16_t)(x)) +#define htobe32(x) ((uint32_t)(x)) +#define htobe64(x) ((uint64_t)(x)) +#define htole16(x) bswap16((x)) +#define htole32(x) bswap32((x)) +#define htole64(x) bswap64((x)) + +#define be16toh(x) ((uint16_t)(x)) +#define be32toh(x) ((uint32_t)(x)) +#define be64toh(x) ((uint64_t)(x)) +#define le16toh(x) bswap16((x)) +#define le32toh(x) bswap32((x)) +#define le64toh(x) bswap64((x)) +#endif /* _BYTE_ORDER == _LITTLE_ENDIAN */ + +/* Alignment-agnostic encode/decode bytestream to/from little/big endian. */ + +static __inline uint16_t +be16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[0] << 8) | p[1]); +} + +static __inline uint32_t +be32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]); +} + +static __inline uint64_t +be64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)be32dec(p) << 32) | be32dec(p + 4)); +} + +static __inline uint16_t +le16dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return ((p[1] << 8) | p[0]); +} + +static __inline uint32_t +le32dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((unsigned)p[3] << 24) | (p[2] << 16) | (p[1] << 8) | p[0]); +} + +static __inline uint64_t +le64dec(const void *pp) +{ + uint8_t const *p = (uint8_t const *)pp; + + return (((uint64_t)le32dec(p + 4) << 32) | le32dec(p)); +} + +static __inline void +be16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 8) & 0xff; + p[1] = u & 0xff; +} + +static __inline void +be32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = (u >> 24) & 0xff; + p[1] = (u >> 16) & 0xff; + p[2] = (u >> 8) & 0xff; + p[3] = u & 0xff; +} + +static __inline void +be64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + be32enc(p, (uint32_t)(u >> 32)); + be32enc(p + 4, (uint32_t)(u & 0xffffffffU)); +} + +static __inline void +le16enc(void *pp, uint16_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; +} + +static __inline void +le32enc(void *pp, uint32_t u) +{ + uint8_t *p = (uint8_t *)pp; + + p[0] = u & 0xff; + p[1] = (u >> 8) & 0xff; + p[2] = (u >> 16) & 0xff; + p[3] = (u >> 24) & 0xff; +} + +static __inline void +le64enc(void *pp, uint64_t u) +{ + uint8_t *p = (uint8_t *)pp; + + le32enc(p, (uint32_t)(u & 0xffffffffU)); + le32enc(p + 4, (uint32_t)(u >> 32)); +} + +#endif /* ENDIAN_H */ diff --git a/arm-trusted-firmware/include/lib/libc/errno.h b/arm-trusted-firmware/include/lib/libc/errno.h new file mode 100644 index 0000000..029912f --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/errno.h @@ -0,0 +1,169 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1982, 1986, 1989, 1993 + * The Regents of the University of California. All rights reserved. + * (c) UNIX System Laboratories, Inc. + * All or some portions of this file are derived from material licensed + * to the University of California by American Telephone and Telegraph + * Co. or Unix System Laboratories, Inc. and are reproduced herein with + * the permission of UNIX System Laboratories, Inc. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * @(#)errno.h 8.5 (Berkeley) 1/21/94 + * $FreeBSD$ + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef ERRNO_H +#define ERRNO_H + +#define EPERM 1 /* Operation not permitted */ +#define ENOENT 2 /* No such file or directory */ +#define ESRCH 3 /* No such process */ +#define EINTR 4 /* Interrupted system call */ +#define EIO 5 /* Input/output error */ +#define ENXIO 6 /* Device not configured */ +#define E2BIG 7 /* Argument list too long */ +#define ENOEXEC 8 /* Exec format error */ +#define EBADF 9 /* Bad file descriptor */ +#define ECHILD 10 /* No child processes */ +#define EDEADLK 11 /* Resource deadlock avoided */ + /* 11 was EAGAIN */ +#define ENOMEM 12 /* Cannot allocate memory */ +#define EACCES 13 /* Permission denied */ +#define EFAULT 14 /* Bad address */ +#define ENOTBLK 15 /* Block device required */ +#define EBUSY 16 /* Device busy */ +#define EEXIST 17 /* File exists */ +#define EXDEV 18 /* Cross-device link */ +#define ENODEV 19 /* Operation not supported by device */ +#define ENOTDIR 20 /* Not a directory */ +#define EISDIR 21 /* Is a directory */ +#define EINVAL 22 /* Invalid argument */ +#define ENFILE 23 /* Too many open files in system */ +#define EMFILE 24 /* Too many open files */ +#define ENOTTY 25 /* Inappropriate ioctl for device */ +#define ETXTBSY 26 /* Text file busy */ +#define EFBIG 27 /* File too large */ +#define ENOSPC 28 /* No space left on device */ +#define ESPIPE 29 /* Illegal seek */ +#define EROFS 30 /* Read-only filesystem */ +#define EMLINK 31 /* Too many links */ +#define EPIPE 32 /* Broken pipe */ + +/* math software */ +#define EDOM 33 /* Numerical argument out of domain */ +#define ERANGE 34 /* Result too large */ + +/* non-blocking and interrupt i/o */ +#define EAGAIN 35 /* Resource temporarily unavailable */ +#define EWOULDBLOCK EAGAIN /* Operation would block */ +#define EINPROGRESS 36 /* Operation now in progress */ +#define EALREADY 37 /* Operation already in progress */ + +/* ipc/network software -- argument errors */ +#define ENOTSOCK 38 /* Socket operation on non-socket */ +#define EDESTADDRREQ 39 /* Destination address required */ +#define EMSGSIZE 40 /* Message too long */ +#define EPROTOTYPE 41 /* Protocol wrong type for socket */ +#define ENOPROTOOPT 42 /* Protocol not available */ +#define EPROTONOSUPPORT 43 /* Protocol not supported */ +#define ESOCKTNOSUPPORT 44 /* Socket type not supported */ +#define EOPNOTSUPP 45 /* Operation not supported */ +#define ENOTSUP EOPNOTSUPP /* Operation not supported */ +#define EPFNOSUPPORT 46 /* Protocol family not supported */ +#define EAFNOSUPPORT 47 /* Address family not supported by protocol family */ +#define EADDRINUSE 48 /* Address already in use */ +#define EADDRNOTAVAIL 49 /* Can't assign requested address */ + +/* ipc/network software -- operational errors */ +#define ENETDOWN 50 /* Network is down */ +#define ENETUNREACH 51 /* Network is unreachable */ +#define ENETRESET 52 /* Network dropped connection on reset */ +#define ECONNABORTED 53 /* Software caused connection abort */ +#define ECONNRESET 54 /* Connection reset by peer */ +#define ENOBUFS 55 /* No buffer space available */ +#define EISCONN 56 /* Socket is already connected */ +#define ENOTCONN 57 /* Socket is not connected */ +#define ESHUTDOWN 58 /* Can't send after socket shutdown */ +#define ETOOMANYREFS 59 /* Too many references: can't splice */ +#define ETIMEDOUT 60 /* Operation timed out */ +#define ECONNREFUSED 61 /* Connection refused */ + +#define ELOOP 62 /* Too many levels of symbolic links */ +#define ENAMETOOLONG 63 /* File name too long */ + +/* should be rearranged */ +#define EHOSTDOWN 64 /* Host is down */ +#define EHOSTUNREACH 65 /* No route to host */ +#define ENOTEMPTY 66 /* Directory not empty */ + +/* quotas & mush */ +#define EPROCLIM 67 /* Too many processes */ +#define EUSERS 68 /* Too many users */ +#define EDQUOT 69 /* Disc quota exceeded */ + +/* Network File System */ +#define ESTALE 70 /* Stale NFS file handle */ +#define EREMOTE 71 /* Too many levels of remote in path */ +#define EBADRPC 72 /* RPC struct is bad */ +#define ERPCMISMATCH 73 /* RPC version wrong */ +#define EPROGUNAVAIL 74 /* RPC prog. not avail */ +#define EPROGMISMATCH 75 /* Program version wrong */ +#define EPROCUNAVAIL 76 /* Bad procedure for program */ + +#define ENOLCK 77 /* No locks available */ +#define ENOSYS 78 /* Function not implemented */ + +#define EFTYPE 79 /* Inappropriate file type or format */ +#define EAUTH 80 /* Authentication error */ +#define ENEEDAUTH 81 /* Need authenticator */ +#define EIDRM 82 /* Identifier removed */ +#define ENOMSG 83 /* No message of desired type */ +#define EOVERFLOW 84 /* Value too large to be stored in data type */ +#define ECANCELED 85 /* Operation canceled */ +#define EILSEQ 86 /* Illegal byte sequence */ +#define ENOATTR 87 /* Attribute not found */ + +#define EDOOFUS 88 /* Programming error */ + +#define EBADMSG 89 /* Bad message */ +#define EMULTIHOP 90 /* Multihop attempted */ +#define ENOLINK 91 /* Link has been severed */ +#define EPROTO 92 /* Protocol error */ + +#define ENOTCAPABLE 93 /* Capabilities insufficient */ +#define ECAPMODE 94 /* Not permitted in capability mode */ +#define ENOTRECOVERABLE 95 /* State not recoverable */ +#define EOWNERDEAD 96 /* Previous owner died */ + +#define ELAST 96 /* Must be equal largest errno */ + +#endif /* ERRNO_H */ diff --git a/arm-trusted-firmware/include/lib/libc/inttypes.h b/arm-trusted-firmware/include/lib/libc/inttypes.h new file mode 100644 index 0000000..0f9e8c6 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/inttypes.h @@ -0,0 +1,47 @@ +/* + * Copyright 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INTTYPES_H +#define INTTYPES_H + +#include +#include + +#define PRId8 "d" /* int8_t */ +#define PRId16 "d" /* int16_t */ +#define PRId32 "d" /* int32_t */ +#define PRIdPTR "d" /* intptr_t */ + +#define PRIi8 "i" /* int8_t */ +#define PRIi16 "i" /* int16_t */ +#define PRIi32 "i" /* int32_t */ +#define PRIiPTR "i" /* intptr_t */ + +#define PRIo8 "o" /* int8_t */ +#define PRIo16 "o" /* int16_t */ +#define PRIo32 "o" /* int32_t */ +#define PRIoPTR "o" /* intptr_t */ + +#define PRIu8 "u" /* uint8_t */ +#define PRIu16 "u" /* uint16_t */ +#define PRIu32 "u" /* uint32_t */ +#define PRIuPTR "u" /* uintptr_t */ + +#define PRIx8 "x" /* uint8_t */ +#define PRIx16 "x" /* uint16_t */ +#define PRIx32 "x" /* uint32_t */ +#define PRIxPTR "x" /* uintptr_t */ + +#define PRIX8 "X" /* uint8_t */ +#define PRIX16 "X" /* uint16_t */ +#define PRIX32 "X" /* uint32_t */ +#define PRIXPTR "X" /* uintptr_t */ + +#endif diff --git a/arm-trusted-firmware/include/lib/libc/limits.h b/arm-trusted-firmware/include/lib/libc/limits.h new file mode 100644 index 0000000..41bb658 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/limits.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef LIMITS_H +#define LIMITS_H + +#include + +#define CHAR_BIT 8 +#define MB_LEN_MAX 1 + +#endif /* LIMITS_H */ diff --git a/arm-trusted-firmware/include/lib/libc/setjmp.h b/arm-trusted-firmware/include/lib/libc/setjmp.h new file mode 100644 index 0000000..be8e2c0 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/setjmp.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SETJMP_H +#define SETJMP_H + +#include + +#ifndef __ASSEMBLER__ + +#include + +int setjmp(jmp_buf env); +__dead2 void longjmp(jmp_buf env, int val); + +#endif /* __ASSEMBLER__ */ +#endif /* SETJMP_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdarg.h b/arm-trusted-firmware/include/lib/libc/stdarg.h new file mode 100644 index 0000000..e260b9b --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdarg.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDARG_H +#define STDARG_H + +#define va_list __builtin_va_list +#define va_start(ap, last) __builtin_va_start(ap, last) +#define va_end(ap) __builtin_va_end(ap) +#define va_copy(to, from) __builtin_va_copy(to, from) +#define va_arg(to, type) __builtin_va_arg(to, type) + +#endif /* STDARG_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdbool.h b/arm-trusted-firmware/include/lib/libc/stdbool.h new file mode 100644 index 0000000..b58334c --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdbool.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STDBOOL_H +#define STDBOOL_H + +#define bool _Bool + +#define true (0 < 1) +#define false (0 > 1) + +#define __bool_true_false_are_defined 1 + +#endif /* STDBOOL_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stddef.h b/arm-trusted-firmware/include/lib/libc/stddef.h new file mode 100644 index 0000000..58a519e --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stddef.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDDEF_H +#define STDDEF_H + +#include + +#ifndef _PTRDIFF_T +typedef long ptrdiff_t; +#define _PTRDIFF_T +#endif + +#ifndef NULL +#define NULL ((void *) 0) +#endif + +#define offsetof(st, m) __builtin_offsetof(st, m) + +#endif /* STDDEF_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdint.h b/arm-trusted-firmware/include/lib/libc/stdint.h new file mode 100644 index 0000000..e96a25c --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdint.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDINT_H +#define STDINT_H + +#include +#include + +#define INT8_MAX CHAR_MAX +#define INT8_MIN CHAR_MIN +#define UINT8_MAX UCHAR_MAX + +#define INT16_MAX SHRT_MAX +#define INT16_MIN SHRT_MIN +#define UINT16_MAX USHRT_MAX + +#define INT32_MAX INT_MAX +#define INT32_MIN INT_MIN +#define UINT32_MAX UINT_MAX + +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define UINT_LEAST8_MAX UINT8_MAX + +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define UINT_LEAST16_MAX UINT16_MAX + +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define UINT_LEAST32_MAX UINT32_MAX + +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +#define INT_FAST8_MIN INT32_MIN +#define INT_FAST8_MAX INT32_MAX +#define UINT_FAST8_MAX UINT32_MAX + +#define INT_FAST16_MIN INT32_MIN +#define INT_FAST16_MAX INT32_MAX +#define UINT_FAST16_MAX UINT32_MAX + +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define UINT_FAST32_MAX UINT32_MAX + +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST64_MAX UINT64_MAX + +#define INTPTR_MIN LONG_MIN +#define INTPTR_MAX LONG_MAX +#define UINTPTR_MAX ULONG_MAX + +#define INTMAX_MIN LLONG_MIN +#define INTMAX_MAX LLONG_MAX +#define UINTMAX_MAX ULLONG_MAX + +#define PTRDIFF_MIN LONG_MIN +#define PTRDIFF_MAX LONG_MAX + +#define SIZE_MAX ULONG_MAX + +#define INT8_C(x) x +#define INT16_C(x) x +#define INT32_C(x) x + +#define UINT8_C(x) x +#define UINT16_C(x) x +#define UINT32_C(x) x ## U + +#define INTMAX_C(x) x ## LL +#define UINTMAX_C(x) x ## ULL + +typedef signed char int8_t; +typedef short int16_t; +typedef int int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned int uint32_t; + +typedef signed char int8_least_t; +typedef short int16_least_t; +typedef int int32_least_t; + +typedef unsigned char uint8_least_t; +typedef unsigned short uint16_least_t; +typedef unsigned int uint32_least_t; + +typedef int int8_fast_t; +typedef int int16_fast_t; +typedef int int32_fast_t; + +typedef unsigned int uint8_fast_t; +typedef unsigned int uint16_fast_t; +typedef unsigned int uint32_fast_t; + +typedef long intptr_t; +typedef unsigned long uintptr_t; + +/* +* Conceptually, these are supposed to be the largest integers representable in C, +* but GCC and Clang define them as long long for compatibility. +*/ +typedef long long intmax_t; +typedef unsigned long long uintmax_t; + +typedef long register_t; +typedef unsigned long u_register_t; + +#endif /* STDINT_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdio.h b/arm-trusted-firmware/include/lib/libc/stdio.h new file mode 100644 index 0000000..ba13683 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdio.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDIO_H +#define STDIO_H + +#include +#include +#include + +#define EOF -1 + +int printf(const char *fmt, ...) __printflike(1, 2); +int snprintf(char *s, size_t n, const char *fmt, ...) __printflike(3, 4); + +#ifdef STDARG_H +int vprintf(const char *fmt, va_list args); +int vsnprintf(char *s, size_t n, const char *fmt, va_list args); +#endif + +int putchar(int c); +int puts(const char *s); + +#endif /* STDIO_H */ diff --git a/arm-trusted-firmware/include/lib/libc/stdlib.h b/arm-trusted-firmware/include/lib/libc/stdlib.h new file mode 100644 index 0000000..4641e56 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/stdlib.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012-2021 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STDLIB_H +#define STDLIB_H + +#include + +#define EXIT_FAILURE 1 +#define EXIT_SUCCESS 0 + +#define _ATEXIT_MAX 1 + +#define isspace(x) (((x) == ' ') || ((x) == '\r') || ((x) == '\n') || \ + ((x) == '\t') || ((x) == '\b')) + +extern void abort(void); +extern int atexit(void (*func)(void)); +extern void exit(int status); + +long strtol(const char *nptr, char **endptr, int base); +unsigned long strtoul(const char *nptr, char **endptr, int base); +long long strtoll(const char *nptr, char **endptr, int base); +unsigned long long strtoull(const char *nptr, char **endptr, int base); +#endif /* STDLIB_H */ diff --git a/arm-trusted-firmware/include/lib/libc/string.h b/arm-trusted-firmware/include/lib/libc/string.h new file mode 100644 index 0000000..9894483 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/string.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef STRING_H +#define STRING_H + +#include + +void *memcpy(void *dst, const void *src, size_t len); +void *memmove(void *dst, const void *src, size_t len); +int memcmp(const void *s1, const void *s2, size_t len); +int strcmp(const char *s1, const char *s2); +int strncmp(const char *s1, const char *s2, size_t n); +void *memchr(const void *src, int c, size_t len); +void *memrchr(const void *src, int c, size_t len); +char *strchr(const char *s, int c); +void *memset(void *dst, int val, size_t count); +size_t strlen(const char *s); +size_t strnlen(const char *s, size_t maxlen); +char *strrchr(const char *p, int ch); +size_t strlcpy(char * dst, const char * src, size_t dsize); +size_t strlcat(char * dst, const char * src, size_t dsize); +char *strtok_r(char *s, const char *delim, char **last); + +#endif /* STRING_H */ diff --git a/arm-trusted-firmware/include/lib/libc/time.h b/arm-trusted-firmware/include/lib/libc/time.h new file mode 100644 index 0000000..c1c95e5 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libc/time.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2012-2017 Roberto E. Vargas Caballero + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Portions copyright (c) 2018-2019, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef TIME_H +#define TIME_H + +#include + +typedef long int time_t; + +#endif /* TIME_H */ diff --git a/arm-trusted-firmware/include/lib/libfdt/fdt.h b/arm-trusted-firmware/include/lib/libfdt/fdt.h new file mode 100644 index 0000000..eb9edb7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/fdt.h @@ -0,0 +1,66 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef FDT_H +#define FDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#ifndef __ASSEMBLER__ + +struct fdt_header { + fdt32_t magic; /* magic word FDT_MAGIC */ + fdt32_t totalsize; /* total size of DT block */ + fdt32_t off_dt_struct; /* offset to structure */ + fdt32_t off_dt_strings; /* offset to strings */ + fdt32_t off_mem_rsvmap; /* offset to memory reserve map */ + fdt32_t version; /* format version */ + fdt32_t last_comp_version; /* last compatible version */ + + /* version 2 fields below */ + fdt32_t boot_cpuid_phys; /* Which physical CPU id we're + booting on */ + /* version 3 fields below */ + fdt32_t size_dt_strings; /* size of the strings block */ + + /* version 17 fields below */ + fdt32_t size_dt_struct; /* size of the structure block */ +}; + +struct fdt_reserve_entry { + fdt64_t address; + fdt64_t size; +}; + +struct fdt_node_header { + fdt32_t tag; + char name[0]; +}; + +struct fdt_property { + fdt32_t tag; + fdt32_t len; + fdt32_t nameoff; + char data[0]; +}; + +#endif /* !__ASSEMBLER__*/ + +#define FDT_MAGIC 0xd00dfeed /* 4: version, 4: total size */ +#define FDT_TAGSIZE sizeof(fdt32_t) + +#define FDT_BEGIN_NODE 0x1 /* Start node: full name */ +#define FDT_END_NODE 0x2 /* End node */ +#define FDT_PROP 0x3 /* Property: name off, + size, content */ +#define FDT_NOP 0x4 /* nop */ +#define FDT_END 0x9 + +#define FDT_V1_SIZE (7*sizeof(fdt32_t)) +#define FDT_V2_SIZE (FDT_V1_SIZE + sizeof(fdt32_t)) +#define FDT_V3_SIZE (FDT_V2_SIZE + sizeof(fdt32_t)) +#define FDT_V16_SIZE FDT_V3_SIZE +#define FDT_V17_SIZE (FDT_V16_SIZE + sizeof(fdt32_t)) + +#endif /* FDT_H */ diff --git a/arm-trusted-firmware/include/lib/libfdt/libfdt.h b/arm-trusted-firmware/include/lib/libfdt/libfdt.h new file mode 100644 index 0000000..544d3ef --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/libfdt.h @@ -0,0 +1,2080 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_H +#define LIBFDT_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define FDT_FIRST_SUPPORTED_VERSION 0x02 +#define FDT_LAST_SUPPORTED_VERSION 0x11 + +/* Error codes: informative error codes */ +#define FDT_ERR_NOTFOUND 1 + /* FDT_ERR_NOTFOUND: The requested node or property does not exist */ +#define FDT_ERR_EXISTS 2 + /* FDT_ERR_EXISTS: Attempted to create a node or property which + * already exists */ +#define FDT_ERR_NOSPACE 3 + /* FDT_ERR_NOSPACE: Operation needed to expand the device + * tree, but its buffer did not have sufficient space to + * contain the expanded tree. Use fdt_open_into() to move the + * device tree to a buffer with more space. */ + +/* Error codes: codes for bad parameters */ +#define FDT_ERR_BADOFFSET 4 + /* FDT_ERR_BADOFFSET: Function was passed a structure block + * offset which is out-of-bounds, or which points to an + * unsuitable part of the structure for the operation. */ +#define FDT_ERR_BADPATH 5 + /* FDT_ERR_BADPATH: Function was passed a badly formatted path + * (e.g. missing a leading / for a function which requires an + * absolute path) */ +#define FDT_ERR_BADPHANDLE 6 + /* FDT_ERR_BADPHANDLE: Function was passed an invalid phandle. + * This can be caused either by an invalid phandle property + * length, or the phandle value was either 0 or -1, which are + * not permitted. */ +#define FDT_ERR_BADSTATE 7 + /* FDT_ERR_BADSTATE: Function was passed an incomplete device + * tree created by the sequential-write functions, which is + * not sufficiently complete for the requested operation. */ + +/* Error codes: codes for bad device tree blobs */ +#define FDT_ERR_TRUNCATED 8 + /* FDT_ERR_TRUNCATED: FDT or a sub-block is improperly + * terminated (overflows, goes outside allowed bounds, or + * isn't properly terminated). */ +#define FDT_ERR_BADMAGIC 9 + /* FDT_ERR_BADMAGIC: Given "device tree" appears not to be a + * device tree at all - it is missing the flattened device + * tree magic number. */ +#define FDT_ERR_BADVERSION 10 + /* FDT_ERR_BADVERSION: Given device tree has a version which + * can't be handled by the requested operation. For + * read-write functions, this may mean that fdt_open_into() is + * required to convert the tree to the expected version. */ +#define FDT_ERR_BADSTRUCTURE 11 + /* FDT_ERR_BADSTRUCTURE: Given device tree has a corrupt + * structure block or other serious error (e.g. misnested + * nodes, or subnodes preceding properties). */ +#define FDT_ERR_BADLAYOUT 12 + /* FDT_ERR_BADLAYOUT: For read-write functions, the given + * device tree has it's sub-blocks in an order that the + * function can't handle (memory reserve map, then structure, + * then strings). Use fdt_open_into() to reorganize the tree + * into a form suitable for the read-write operations. */ + +/* "Can't happen" error indicating a bug in libfdt */ +#define FDT_ERR_INTERNAL 13 + /* FDT_ERR_INTERNAL: libfdt has failed an internal assertion. + * Should never be returned, if it is, it indicates a bug in + * libfdt itself. */ + +/* Errors in device tree content */ +#define FDT_ERR_BADNCELLS 14 + /* FDT_ERR_BADNCELLS: Device tree has a #address-cells, #size-cells + * or similar property with a bad format or value */ + +#define FDT_ERR_BADVALUE 15 + /* FDT_ERR_BADVALUE: Device tree has a property with an unexpected + * value. For example: a property expected to contain a string list + * is not NUL-terminated within the length of its value. */ + +#define FDT_ERR_BADOVERLAY 16 + /* FDT_ERR_BADOVERLAY: The device tree overlay, while + * correctly structured, cannot be applied due to some + * unexpected or missing value, property or node. */ + +#define FDT_ERR_NOPHANDLES 17 + /* FDT_ERR_NOPHANDLES: The device tree doesn't have any + * phandle available anymore without causing an overflow */ + +#define FDT_ERR_BADFLAGS 18 + /* FDT_ERR_BADFLAGS: The function was passed a flags field that + * contains invalid flags or an invalid combination of flags. */ + +#define FDT_ERR_MAX 18 + +/* constants */ +#define FDT_MAX_PHANDLE 0xfffffffe + /* Valid values for phandles range from 1 to 2^32-2. */ + +/**********************************************************************/ +/* Low-level functions (you probably don't need these) */ +/**********************************************************************/ + +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int checklen); +#endif +static inline void *fdt_offset_ptr_w(void *fdt, int offset, int checklen) +{ + return (void *)(uintptr_t)fdt_offset_ptr(fdt, offset, checklen); +} + +uint32_t fdt_next_tag(const void *fdt, int offset, int *nextoffset); + +/* + * Alignment helpers: + * These helpers access words from a device tree blob. They're + * built to work even with unaligned pointers on platforms (ike + * ARM) that don't like unaligned loads and stores + */ + +static inline uint32_t fdt32_ld(const fdt32_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint32_t)bp[0] << 24) + | ((uint32_t)bp[1] << 16) + | ((uint32_t)bp[2] << 8) + | bp[3]; +} + +static inline void fdt32_st(void *property, uint32_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 24; + bp[1] = (value >> 16) & 0xff; + bp[2] = (value >> 8) & 0xff; + bp[3] = value & 0xff; +} + +static inline uint64_t fdt64_ld(const fdt64_t *p) +{ + const uint8_t *bp = (const uint8_t *)p; + + return ((uint64_t)bp[0] << 56) + | ((uint64_t)bp[1] << 48) + | ((uint64_t)bp[2] << 40) + | ((uint64_t)bp[3] << 32) + | ((uint64_t)bp[4] << 24) + | ((uint64_t)bp[5] << 16) + | ((uint64_t)bp[6] << 8) + | bp[7]; +} + +static inline void fdt64_st(void *property, uint64_t value) +{ + uint8_t *bp = (uint8_t *)property; + + bp[0] = value >> 56; + bp[1] = (value >> 48) & 0xff; + bp[2] = (value >> 40) & 0xff; + bp[3] = (value >> 32) & 0xff; + bp[4] = (value >> 24) & 0xff; + bp[5] = (value >> 16) & 0xff; + bp[6] = (value >> 8) & 0xff; + bp[7] = value & 0xff; +} + +/**********************************************************************/ +/* Traversal functions */ +/**********************************************************************/ + +int fdt_next_node(const void *fdt, int offset, int *depth); + +/** + * fdt_first_subnode() - get offset of first direct subnode + * + * @fdt: FDT blob + * @offset: Offset of node to check + * @return offset of first subnode, or -FDT_ERR_NOTFOUND if there is none + */ +int fdt_first_subnode(const void *fdt, int offset); + +/** + * fdt_next_subnode() - get offset of next direct subnode + * + * After first calling fdt_first_subnode(), call this function repeatedly to + * get direct subnodes of a parent node. + * + * @fdt: FDT blob + * @offset: Offset of previous subnode + * @return offset of next subnode, or -FDT_ERR_NOTFOUND if there are no more + * subnodes + */ +int fdt_next_subnode(const void *fdt, int offset); + +/** + * fdt_for_each_subnode - iterate over all subnodes of a parent + * + * @node: child node (int, lvalue) + * @fdt: FDT blob (const void *) + * @parent: parent node (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_subnode(node, fdt, parent) { + * Use node + * ... + * } + * + * if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and @node is used as + * iterator in the loop. The parent variable be constant or even a + * literal. + * + */ +#define fdt_for_each_subnode(node, fdt, parent) \ + for (node = fdt_first_subnode(fdt, parent); \ + node >= 0; \ + node = fdt_next_subnode(fdt, node)) + +/**********************************************************************/ +/* General functions */ +/**********************************************************************/ +#define fdt_get_header(fdt, field) \ + (fdt32_ld(&((const struct fdt_header *)(fdt))->field)) +#define fdt_magic(fdt) (fdt_get_header(fdt, magic)) +#define fdt_totalsize(fdt) (fdt_get_header(fdt, totalsize)) +#define fdt_off_dt_struct(fdt) (fdt_get_header(fdt, off_dt_struct)) +#define fdt_off_dt_strings(fdt) (fdt_get_header(fdt, off_dt_strings)) +#define fdt_off_mem_rsvmap(fdt) (fdt_get_header(fdt, off_mem_rsvmap)) +#define fdt_version(fdt) (fdt_get_header(fdt, version)) +#define fdt_last_comp_version(fdt) (fdt_get_header(fdt, last_comp_version)) +#define fdt_boot_cpuid_phys(fdt) (fdt_get_header(fdt, boot_cpuid_phys)) +#define fdt_size_dt_strings(fdt) (fdt_get_header(fdt, size_dt_strings)) +#define fdt_size_dt_struct(fdt) (fdt_get_header(fdt, size_dt_struct)) + +#define fdt_set_hdr_(name) \ + static inline void fdt_set_##name(void *fdt, uint32_t val) \ + { \ + struct fdt_header *fdth = (struct fdt_header *)fdt; \ + fdth->name = cpu_to_fdt32(val); \ + } +fdt_set_hdr_(magic); +fdt_set_hdr_(totalsize); +fdt_set_hdr_(off_dt_struct); +fdt_set_hdr_(off_dt_strings); +fdt_set_hdr_(off_mem_rsvmap); +fdt_set_hdr_(version); +fdt_set_hdr_(last_comp_version); +fdt_set_hdr_(boot_cpuid_phys); +fdt_set_hdr_(size_dt_strings); +fdt_set_hdr_(size_dt_struct); +#undef fdt_set_hdr_ + +/** + * fdt_header_size - return the size of the tree's header + * @fdt: pointer to a flattened device tree + */ +size_t fdt_header_size(const void *fdt); + +/** + * fdt_header_size_ - internal function which takes a version number + */ +size_t fdt_header_size_(uint32_t version); + +/** + * fdt_check_header - sanity check a device tree header + + * @fdt: pointer to data which might be a flattened device tree + * + * fdt_check_header() checks that the given buffer contains what + * appears to be a flattened device tree, and that the header contains + * valid information (to the extent that can be determined from the + * header alone). + * + * returns: + * 0, if the buffer appears to contain a valid device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings, as above + */ +int fdt_check_header(const void *fdt); + +/** + * fdt_move - move a device tree around in memory + * @fdt: pointer to the device tree to move + * @buf: pointer to memory where the device is to be moved + * @bufsize: size of the memory space at buf + * + * fdt_move() relocates, if possible, the device tree blob located at + * fdt to the buffer at buf of size bufsize. The buffer may overlap + * with the existing device tree blob at fdt. Therefore, + * fdt_move(fdt, fdt, fdt_totalsize(fdt)) + * should always succeed. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient to contain the device tree + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_move(const void *fdt, void *buf, int bufsize); + +/**********************************************************************/ +/* Read-only functions */ +/**********************************************************************/ + +int fdt_check_full(const void *fdt, size_t bufsize); + +/** + * fdt_get_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * @lenp: optional pointer to return the string's length + * + * fdt_get_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt, and optionally also + * returns the string's length in *lenp. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp); + +/** + * fdt_string - retrieve a string from the strings block of a device tree + * @fdt: pointer to the device tree blob + * @stroffset: offset of the string within the strings block (native endian) + * + * fdt_string() retrieves a pointer to a single string from the + * strings block of the device tree blob at fdt. + * + * returns: + * a pointer to the string, on success + * NULL, if stroffset is out of bounds, or doesn't point to a valid string + */ +const char *fdt_string(const void *fdt, int stroffset); + +/** + * fdt_find_max_phandle - find and return the highest phandle in a tree + * @fdt: pointer to the device tree blob + * @phandle: return location for the highest phandle value found in the tree + * + * fdt_find_max_phandle() finds the highest phandle value in the given device + * tree. The value returned in @phandle is only valid if the function returns + * success. + * + * returns: + * 0 on success or a negative error code on failure + */ +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_get_max_phandle - retrieves the highest phandle in a tree + * @fdt: pointer to the device tree blob + * + * fdt_get_max_phandle retrieves the highest phandle in the given + * device tree. This will ignore badly formatted phandles, or phandles + * with a value of 0 or -1. + * + * This function is deprecated in favour of fdt_find_max_phandle(). + * + * returns: + * the highest phandle on success + * 0, if no phandle was found in the device tree + * -1, if an error occurred + */ +static inline uint32_t fdt_get_max_phandle(const void *fdt) +{ + uint32_t phandle; + int err; + + err = fdt_find_max_phandle(fdt, &phandle); + if (err < 0) + return (uint32_t)-1; + + return phandle; +} + +/** + * fdt_generate_phandle - return a new, unused phandle for a device tree blob + * @fdt: pointer to the device tree blob + * @phandle: return location for the new phandle + * + * Walks the device tree blob and looks for the highest phandle value. On + * success, the new, unused phandle value (one higher than the previously + * highest phandle value in the device tree blob) will be returned in the + * @phandle parameter. + * + * Returns: + * 0 on success or a negative error-code on failure + */ +int fdt_generate_phandle(const void *fdt, uint32_t *phandle); + +/** + * fdt_num_mem_rsv - retrieve the number of memory reserve map entries + * @fdt: pointer to the device tree blob + * + * Returns the number of entries in the device tree blob's memory + * reservation map. This does not include the terminating 0,0 entry + * or any other (0,0) entries reserved for expansion. + * + * returns: + * the number of entries + */ +int fdt_num_mem_rsv(const void *fdt); + +/** + * fdt_get_mem_rsv - retrieve one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: pointers to 64-bit variables + * + * On success, *address and *size will contain the address and size of + * the n-th reserve map entry from the device tree blob, in + * native-endian format. + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size); + +/** + * fdt_subnode_offset_namelen - find a subnode based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_subnode_offset(), but only examine the first + * namelen characters of name for matching the subnode name. This is + * useful for finding subnodes based on a portion of a larger string, + * such as a full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_subnode_offset_namelen(const void *fdt, int parentoffset, + const char *name, int namelen); +#endif +/** + * fdt_subnode_offset - find a subnode of a given node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_subnode_offset() finds a subnode of the node at structure block + * offset parentoffset with the given name. name may include a unit + * address, in which case fdt_subnode_offset() will find the subnode + * with that unit address, or the unit address may be omitted, in + * which case fdt_subnode_offset() will find an arbitrary subnode + * whose name excluding unit address matches the given name. + * + * returns: + * structure block offset of the requested subnode (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name); + +/** + * fdt_path_offset_namelen - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * @namelen: number of characters of path to consider + * + * Identical to fdt_path_offset(), but only consider the first namelen + * characters of path as the path name. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen); +#endif + +/** + * fdt_path_offset - find a tree node by its full path + * @fdt: pointer to the device tree blob + * @path: full path of the node to locate + * + * fdt_path_offset() finds a node of a given path in the device tree. + * Each path component may omit the unit address portion, but the + * results of this are undefined if any such path component is + * ambiguous (that is if there are multiple nodes at the relevant + * level matching the given component, differentiated only by unit + * address). + * + * returns: + * structure block offset of the node with the requested path (>=0), on + * success + * -FDT_ERR_BADPATH, given path does not begin with '/' or is invalid + * -FDT_ERR_NOTFOUND, if the requested node does not exist + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_path_offset(const void *fdt, const char *path); + +/** + * fdt_get_name - retrieve the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the starting node + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_name() retrieves the name (including unit address) of the + * device tree node at structure block offset nodeoffset. If lenp is + * non-NULL, the length of this name is also returned, in the integer + * pointed to by lenp. + * + * returns: + * pointer to the node's name, on success + * If lenp is non-NULL, *lenp contains the length of that name + * (>=0) + * NULL, on error + * if lenp is non-NULL *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +const char *fdt_get_name(const void *fdt, int nodeoffset, int *lenp); + +/** + * fdt_first_property_offset - find the offset of a node's first property + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * + * fdt_first_property_offset() finds the first property of the node at + * the given structure block offset. + * + * returns: + * structure block offset of the property (>=0), on success + * -FDT_ERR_NOTFOUND, if the requested node has no properties + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_first_property_offset(const void *fdt, int nodeoffset); + +/** + * fdt_next_property_offset - step through a node's properties + * @fdt: pointer to the device tree blob + * @offset: structure block offset of a property + * + * fdt_next_property_offset() finds the property immediately after the + * one at the given structure block offset. This will be a property + * of the same node as the given property. + * + * returns: + * structure block offset of the next property (>=0), on success + * -FDT_ERR_NOTFOUND, if the given property is the last in its node + * -FDT_ERR_BADOFFSET, if nodeoffset did not point to an FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_next_property_offset(const void *fdt, int offset); + +/** + * fdt_for_each_property_offset - iterate over all properties of a node + * + * @property_offset: property offset (int, lvalue) + * @fdt: FDT blob (const void *) + * @node: node offset (int) + * + * This is actually a wrapper around a for loop and would be used like so: + * + * fdt_for_each_property_offset(property, fdt, node) { + * Use property + * ... + * } + * + * if ((property < 0) && (property != -FDT_ERR_NOTFOUND)) { + * Error handling + * } + * + * Note that this is implemented as a macro and property is used as + * iterator in the loop. The node variable can be constant or even a + * literal. + */ +#define fdt_for_each_property_offset(property, fdt, node) \ + for (property = fdt_first_property_offset(fdt, node); \ + property >= 0; \ + property = fdt_next_property_offset(fdt, property)) + +/** + * fdt_get_property_by_offset - retrieve the property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to retrieve + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property_by_offset() retrieves a pointer to the + * fdt_property structure within the device tree blob at the given + * offset. If lenp is non-NULL, the length of the property value is + * also returned, in the integer pointed to by lenp. + * + * Note that this code only works on device tree versions >= 16. fdt_getprop() + * works on all versions. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp); + +/** + * fdt_get_property_namelen - find a property based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_get_property(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int nodeoffset, + const char *name, + int namelen, int *lenp); +#endif + +/** + * fdt_get_property - find a given property in a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_get_property() retrieves a pointer to the fdt_property + * structure within the device tree blob corresponding to the property + * named 'name' of the node at offset nodeoffset. If lenp is + * non-NULL, the length of the property value is also returned, in the + * integer pointed to by lenp. + * + * returns: + * pointer to the structure representing the property + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const struct fdt_property *fdt_get_property(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline struct fdt_property *fdt_get_property_w(void *fdt, int nodeoffset, + const char *name, + int *lenp) +{ + return (struct fdt_property *)(uintptr_t) + fdt_get_property(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_getprop_by_offset - retrieve the value of a property at a given offset + * @fdt: pointer to the device tree blob + * @offset: offset of the property to read + * @namep: pointer to a string variable (will be overwritten) or NULL + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop_by_offset() retrieves a pointer to the value of the + * property at structure block offset 'offset' (this will be a pointer + * to within the device blob itself, not a copy of the value). If + * lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. If namep is non-NULL, + * the property's namne will also be returned in the char * pointed to + * by namep (this will be a pointer to within the device tree's string + * block, not a new copy of the name). + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * if namep is non-NULL *namep contiains a pointer to the property + * name. + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_PROP tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* This function is not useful in Python */ +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp); +#endif + +/** + * fdt_getprop_namelen - get property value based on substring + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @namelen: number of characters of name to consider + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * Identical to fdt_getprop(), but only examine the first namelen + * characters of name for matching the property name. + */ +#ifndef SWIG /* Not available in Python */ +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp); +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset, + const char *name, int namelen, + int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name, + namelen, lenp); +} +#endif + +/** + * fdt_getprop - retrieve the value of a given property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to find + * @name: name of the property to find + * @lenp: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_getprop() retrieves a pointer to the value of the property + * named 'name' of the node at offset nodeoffset (this will be a + * pointer to within the device blob itself, not a copy of the value). + * If lenp is non-NULL, the length of the property value is also + * returned, in the integer pointed to by lenp. + * + * returns: + * pointer to the property's value + * if lenp is non-NULL, *lenp contains the length of the property + * value (>=0) + * NULL, on error + * if lenp is non-NULL, *lenp contains an error code (<0): + * -FDT_ERR_NOTFOUND, node does not have named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE + * tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp); +static inline void *fdt_getprop_w(void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return (void *)(uintptr_t)fdt_getprop(fdt, nodeoffset, name, lenp); +} + +/** + * fdt_get_phandle - retrieve the phandle of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of the node + * + * fdt_get_phandle() retrieves the phandle of the device tree node at + * structure block offset nodeoffset. + * + * returns: + * the phandle of the node at nodeoffset, on success (!= 0, != -1) + * 0, if the node has no phandle, or another error occurs + */ +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset); + +/** + * fdt_get_alias_namelen - get alias based on substring + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * @namelen: number of characters of name to consider + * + * Identical to fdt_get_alias(), but only examine the first namelen + * characters of name for matching the alias name. + */ +#ifndef SWIG /* Not available in Python */ +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen); +#endif + +/** + * fdt_get_alias - retrieve the path referenced by a given alias + * @fdt: pointer to the device tree blob + * @name: name of the alias th look up + * + * fdt_get_alias() retrieves the value of a given alias. That is, the + * value of the property named 'name' in the node /aliases. + * + * returns: + * a pointer to the expansion of the alias named 'name', if it exists + * NULL, if the given alias or the /aliases node does not exist + */ +const char *fdt_get_alias(const void *fdt, const char *name); + +/** + * fdt_get_path - determine the full path of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose path to find + * @buf: character buffer to contain the returned path (will be overwritten) + * @buflen: size of the character buffer at buf + * + * fdt_get_path() computes the full path of the node at offset + * nodeoffset, and records that path in the buffer at buf. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * 0, on success + * buf contains the absolute path of the node at + * nodeoffset, as a NUL-terminated string. + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOSPACE, the path of the given node is longer than (bufsize-1) + * characters and will not fit in the given buffer. + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen); + +/** + * fdt_supernode_atdepth_offset - find a specific ancestor of a node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * @supernodedepth: depth of the ancestor to find + * @nodedepth: pointer to an integer variable (will be overwritten) or NULL + * + * fdt_supernode_atdepth_offset() finds an ancestor of the given node + * at a specific depth from the root (where the root itself has depth + * 0, its immediate subnodes depth 1 and so forth). So + * fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, NULL); + * will always return 0, the offset of the root node. If the node at + * nodeoffset has depth D, then: + * fdt_supernode_atdepth_offset(fdt, nodeoffset, D, NULL); + * will return nodeoffset itself. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * structure block offset of the node at node offset's ancestor + * of depth supernodedepth (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_NOTFOUND, supernodedepth was greater than the depth of + * nodeoffset + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth); + +/** + * fdt_node_depth - find the depth of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_node_depth() finds the depth of a given node. The root node + * has depth 0, its immediate subnodes depth 1 and so forth. + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset. + * + * returns: + * depth of the node at nodeoffset (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_depth(const void *fdt, int nodeoffset); + +/** + * fdt_parent_offset - find the parent of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose parent to find + * + * fdt_parent_offset() locates the parent node of a given node (that + * is, it finds the offset of the node which contains the node at + * nodeoffset as a subnode). + * + * NOTE: This function is expensive, as it must scan the device tree + * structure from the start to nodeoffset, *twice*. + * + * returns: + * structure block offset of the parent of the node at nodeoffset + * (>=0), on success + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_parent_offset(const void *fdt, int nodeoffset); + +/** + * fdt_node_offset_by_prop_value - find nodes with a given property value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @propname: property name to check + * @propval: property value to search for + * @proplen: length of the value in propval + * + * fdt_node_offset_by_prop_value() returns the offset of the first + * node after startoffset, which has a property named propname whose + * value is of length proplen and has value equal to propval; or if + * startoffset is -1, the very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_prop_value(fdt, -1, propname, + * propval, proplen); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_prop_value(fdt, offset, propname, + * propval, proplen); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen); + +/** + * fdt_node_offset_by_phandle - find the node with a given phandle + * @fdt: pointer to the device tree blob + * @phandle: phandle value + * + * fdt_node_offset_by_phandle() returns the offset of the node + * which has the given phandle value. If there is more than one node + * in the tree with the given phandle (an invalid tree), results are + * undefined. + * + * returns: + * structure block offset of the located node (>= 0), on success + * -FDT_ERR_NOTFOUND, no node with that phandle exists + * -FDT_ERR_BADPHANDLE, given phandle value was invalid (0 or -1) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle); + +/** + * fdt_node_check_compatible: check a node's compatible property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @compatible: string to match against + * + * + * fdt_node_check_compatible() returns 0 if the given node contains a + * 'compatible' property with the given string as one of its elements, + * it returns non-zero otherwise, or on error. + * + * returns: + * 0, if the node has a 'compatible' property listing the given string + * 1, if the node has a 'compatible' property, but it does not list + * the given string + * -FDT_ERR_NOTFOUND, if the given node has no 'compatible' property + * -FDT_ERR_BADOFFSET, if nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible); + +/** + * fdt_node_offset_by_compatible - find nodes with a given 'compatible' value + * @fdt: pointer to the device tree blob + * @startoffset: only find nodes after this offset + * @compatible: 'compatible' string to match against + * + * fdt_node_offset_by_compatible() returns the offset of the first + * node after startoffset, which has a 'compatible' property which + * lists the given compatible string; or if startoffset is -1, the + * very first such node in the tree. + * + * To iterate through all nodes matching the criterion, the following + * idiom can be used: + * offset = fdt_node_offset_by_compatible(fdt, -1, compatible); + * while (offset != -FDT_ERR_NOTFOUND) { + * // other code here + * offset = fdt_node_offset_by_compatible(fdt, offset, compatible); + * } + * + * Note the -1 in the first call to the function, if 0 is used here + * instead, the function will never locate the root node, even if it + * matches the criterion. + * + * returns: + * structure block offset of the located node (>= 0, >startoffset), + * on success + * -FDT_ERR_NOTFOUND, no node matching the criterion exists in the + * tree after startoffset + * -FDT_ERR_BADOFFSET, nodeoffset does not refer to a BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, standard meanings + */ +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible); + +/** + * fdt_stringlist_contains - check a string list property for a string + * @strlist: Property containing a list of strings to check + * @listlen: Length of property + * @str: String to search for + * + * This is a utility function provided for convenience. The list contains + * one or more strings, each terminated by \0, as is found in a device tree + * "compatible" property. + * + * @return: 1 if the string is found in the list, 0 not found, or invalid list + */ +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str); + +/** + * fdt_stringlist_count - count the number of strings in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @return: + * the number of strings in the given property + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property); + +/** + * fdt_stringlist_search - find a string in a string list and return its index + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @string: string to look up in the string list + * + * Note that it is possible for this function to succeed on property values + * that are not NUL-terminated. That's because the function will stop after + * finding the first occurrence of @string. This can for example happen with + * small-valued cell properties, such as #address-cells, when searching for + * the empty string. + * + * @return: + * the index of the string in the list of strings + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist or does not contain + * the given string + */ +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string); + +/** + * fdt_stringlist_get() - obtain the string at a given index in a string list + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of a tree node + * @property: name of the property containing the string list + * @index: index of the string to return + * @lenp: return location for the string length or an error code on failure + * + * Note that this will successfully extract strings from properties with + * non-NUL-terminated values. For example on small-valued cell properties + * this function will return the empty string. + * + * If non-NULL, the length of the string (on success) or a negative error-code + * (on failure) will be stored in the integer pointer to by lenp. + * + * @return: + * A pointer to the string at the given index in the string list or NULL on + * failure. On success the length of the string will be stored in the memory + * location pointed to by the lenp parameter, if non-NULL. On failure one of + * the following negative error codes will be returned in the lenp parameter + * (if non-NULL): + * -FDT_ERR_BADVALUE if the property value is not NUL-terminated + * -FDT_ERR_NOTFOUND if the property does not exist + */ +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int index, + int *lenp); + +/**********************************************************************/ +/* Read-only functions (addressing related) */ +/**********************************************************************/ + +/** + * FDT_MAX_NCELLS - maximum value for #address-cells and #size-cells + * + * This is the maximum value for #address-cells, #size-cells and + * similar properties that will be processed by libfdt. IEE1275 + * requires that OF implementations handle values up to 4. + * Implementations may support larger values, but in practice higher + * values aren't used. + */ +#define FDT_MAX_NCELLS 4 + +/** + * fdt_address_cells - retrieve address size for a bus represented in the tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address size for + * + * When the node has a valid #address-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 2, if the node has no #address-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_address_cells(const void *fdt, int nodeoffset); + +/** + * fdt_size_cells - retrieve address range size for a bus represented in the + * tree + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to find the address range size for + * + * When the node has a valid #size-cells property, returns its value. + * + * returns: + * 0 <= n < FDT_MAX_NCELLS, on success + * 1, if the node has no #size-cells property + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #size-cells property + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_size_cells(const void *fdt, int nodeoffset); + + +/**********************************************************************/ +/* Write-in-place functions */ +/**********************************************************************/ + +/** + * fdt_setprop_inplace_namelen_partial - change a property's value, + * but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @namelen: number of characters of name to consider + * @idx: index of the property to change in the array + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * Identical to fdt_setprop_inplace(), but modifies the given property + * starting from the given index, and using only the first characters + * of the name. It is useful when you want to manipulate only one value of + * an array and you have a string that doesn't end with \0. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len); +#endif + +/** + * fdt_setprop_inplace - change a property's value, but not its size + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to replace the property value with + * @len: length of the property value + * + * fdt_setprop_inplace() replaces the value of a given property with + * the data in val, of length len. This function cannot change the + * size of a property, and so will only work if len is equal to the + * current length of the property. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if len is not equal to the property's current length + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#ifndef SWIG /* Not available in Python */ +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len); +#endif + +/** + * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to replace the property with + * + * fdt_setprop_inplace_u32() replaces the value of a given property + * with the 32-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 4. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 4 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_u64 - change the value of a 64-bit integer property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to replace the property with + * + * fdt_setprop_inplace_u64() replaces the value of a given property + * with the 64-bit integer value in val, converting val to big-endian + * if necessary. This function cannot change the size of a property, + * and so will only work if the property already exists and has length + * 8. + * + * This function will alter only the bytes in the blob which contain + * the given property value, and will not alter or move any other part + * of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, if the property's length is not equal to 8 + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_inplace_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_inplace_cell - change the value of a single-cell property + * + * This is an alternative name for fdt_setprop_inplace_u32() + */ +static inline int fdt_setprop_inplace_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_setprop_inplace_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_nop_property - replace a property with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_nop_property() will replace a given property's representation + * in the blob with FDT_NOP tags, effectively removing it from the + * tree. + * + * This function will alter only the bytes in the blob which contain + * the property, and will not alter or move any other part of the + * tree. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_property(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_nop_node - replace a node (subtree) with nop tags + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_nop_node() will replace a given node's representation in the + * blob, including all its subnodes, if any, with FDT_NOP tags, + * effectively removing it from the tree. + * + * This function will alter only the bytes in the blob which contain + * the node and its properties and subnodes, and will not alter or + * move any other part of the tree. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_nop_node(void *fdt, int nodeoffset); + +/**********************************************************************/ +/* Sequential write functions */ +/**********************************************************************/ + +/* fdt_create_with_flags flags */ +#define FDT_CREATE_FLAG_NO_NAME_DEDUP 0x1 + /* FDT_CREATE_FLAG_NO_NAME_DEDUP: Do not try to de-duplicate property + * names in the fdt. This can result in faster creation times, but + * a larger fdt. */ + +#define FDT_CREATE_FLAGS_ALL (FDT_CREATE_FLAG_NO_NAME_DEDUP) + +/** + * fdt_create_with_flags - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * @flags: a valid combination of FDT_CREATE_FLAG_ flags, or 0. + * + * fdt_create_with_flags() begins the process of creating a new fdt with + * the sequential write interface. + * + * fdt creation process must end with fdt_finished() to produce a valid fdt. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + * -FDT_ERR_BADFLAGS, flags is not valid + */ +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags); + +/** + * fdt_create - begin creation of a new fdt + * @fdt: pointer to memory allocated where fdt will be created + * @bufsize: size of the memory space at fdt + * + * fdt_create() is equivalent to fdt_create_with_flags() with flags=0. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, bufsize is insufficient for a minimal fdt + */ +int fdt_create(void *buf, int bufsize); + +int fdt_resize(void *fdt, void *buf, int bufsize); +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size); +int fdt_finish_reservemap(void *fdt); +int fdt_begin_node(void *fdt, const char *name); +int fdt_property(void *fdt, const char *name, const void *val, int len); +static inline int fdt_property_u32(void *fdt, const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} +static inline int fdt_property_u64(void *fdt, const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_property(fdt, name, &tmp, sizeof(tmp)); +} + +#ifndef SWIG /* Not available in Python */ +static inline int fdt_property_cell(void *fdt, const char *name, uint32_t val) +{ + return fdt_property_u32(fdt, name, val); +} +#endif + +/** + * fdt_property_placeholder - add a new property and return a ptr to its value + * + * @fdt: pointer to the device tree blob + * @name: name of property to add + * @len: length of property value in bytes + * @valp: returns a pointer to where where the value should be placed + * + * returns: + * 0, on success + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_NOSPACE, standard meanings + */ +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp); + +#define fdt_property_string(fdt, name, str) \ + fdt_property(fdt, name, str, strlen(str)+1) +int fdt_end_node(void *fdt); +int fdt_finish(void *fdt); + +/**********************************************************************/ +/* Read-write functions */ +/**********************************************************************/ + +int fdt_create_empty_tree(void *buf, int bufsize); +int fdt_open_into(const void *fdt, void *buf, int bufsize); +int fdt_pack(void *fdt); + +/** + * fdt_add_mem_rsv - add one memory reserve map entry + * @fdt: pointer to the device tree blob + * @address, @size: 64-bit values (native endian) + * + * Adds a reserve map entry to the given blob reserving a region at + * address address of length size. + * + * This function will insert data into the reserve map and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new reservation entry + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size); + +/** + * fdt_del_mem_rsv - remove a memory reserve map entry + * @fdt: pointer to the device tree blob + * @n: entry to remove + * + * fdt_del_mem_rsv() removes the n-th memory reserve map entry from + * the blob. + * + * This function will delete data from the reservation table and will + * therefore change the indexes of some entries in the table. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, there is no entry of the given index (i.e. there + * are less than n+1 reserve map entries) + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_mem_rsv(void *fdt, int n); + +/** + * fdt_set_name - change the name of a given node + * @fdt: pointer to the device tree blob + * @nodeoffset: structure block offset of a node + * @name: name to give the node + * + * fdt_set_name() replaces the name (including unit address, if any) + * of the given node with the given string. NOTE: this function can't + * efficiently check if the new name is unique amongst the given + * node's siblings; results are undefined if this function is invoked + * with a name equal to one of the given node's siblings. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob + * to contain the new name + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, standard meanings + */ +int fdt_set_name(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_setprop - create or change a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: pointer to data to set the property value to + * @len: length of the property value + * + * fdt_setprop() sets the value of the named property in the given + * node to the given value and length, creating the property if it + * does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_setprop_placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** + * fdt_setprop_u32 - set a property to a 32-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value for the property (native endian) + * + * fdt_setprop_u32() sets the value of the named property in the given + * node to the given 32-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u32(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_u64 - set a property to a 64-bit integer + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value for the property (native endian) + * + * fdt_setprop_u64() sets the value of the named property in the given + * node to the given 64-bit integer value (converting to big-endian if + * necessary), or creates a new property with that value if it does + * not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_setprop_u64(void *fdt, int nodeoffset, const char *name, + uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_setprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_setprop_cell - set a property to a single cell value + * + * This is an alternative name for fdt_setprop_u32() + */ +static inline int fdt_setprop_cell(void *fdt, int nodeoffset, const char *name, + uint32_t val) +{ + return fdt_setprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_setprop_string - set a property to a string value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value for the property + * + * fdt_setprop_string() sets the value of the named property in the + * given node to the given string value (using the length of the + * string to determine the new length of the property), or creates a + * new property with that value if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_string(fdt, nodeoffset, name, str) \ + fdt_setprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + + +/** + * fdt_setprop_empty - set a property to an empty value + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * + * fdt_setprop_empty() sets the value of the named property in the + * given node to an empty (zero length) value, or creates a new empty + * property if it does not already exist. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_setprop_empty(fdt, nodeoffset, name) \ + fdt_setprop((fdt), (nodeoffset), (name), NULL, 0) + +/** + * fdt_appendprop - append to or create a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to append to + * @val: pointer to data to append to the property value + * @len: length of the data to append to the property value + * + * fdt_appendprop() appends the value to the named property in the + * given node, creating the property if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len); + +/** + * fdt_appendprop_u32 - append a 32-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 32-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u32() appends the given 32-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u32(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + fdt32_t tmp = cpu_to_fdt32(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_u64 - append a 64-bit integer value to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @val: 64-bit integer value to append to the property (native endian) + * + * fdt_appendprop_u64() appends the given 64-bit integer value + * (converting to big-endian if necessary) to the value of the named + * property in the given node, or creates a new property with that + * value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +static inline int fdt_appendprop_u64(void *fdt, int nodeoffset, + const char *name, uint64_t val) +{ + fdt64_t tmp = cpu_to_fdt64(val); + return fdt_appendprop(fdt, nodeoffset, name, &tmp, sizeof(tmp)); +} + +/** + * fdt_appendprop_cell - append a single cell value to a property + * + * This is an alternative name for fdt_appendprop_u32() + */ +static inline int fdt_appendprop_cell(void *fdt, int nodeoffset, + const char *name, uint32_t val) +{ + return fdt_appendprop_u32(fdt, nodeoffset, name, val); +} + +/** + * fdt_appendprop_string - append a string to a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @str: string value to append to the property + * + * fdt_appendprop_string() appends the given string to the value of + * the named property in the given node, or creates a new property + * with that value if it does not already exist. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +#define fdt_appendprop_string(fdt, nodeoffset, name, str) \ + fdt_appendprop((fdt), (nodeoffset), (name), (str), strlen(str)+1) + +/** + * fdt_appendprop_addrrange - append a address range property + * @fdt: pointer to the device tree blob + * @parent: offset of the parent node + * @nodeoffset: offset of the node to add a property at + * @name: name of property + * @addr: start address of a given range + * @size: size of a given range + * + * fdt_appendprop_addrrange() appends an address range value (start + * address and size) to the value of the named property in the given + * node, or creates a new property with that value if it does not + * already exist. + * If "name" is not specified, a default "reg" is used. + * Cell sizes are determined by parent's #address-cells and #size-cells. + * + * This function may insert data into the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADNCELLS, if the node has a badly formatted or invalid + * #address-cells property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADVALUE, addr or size doesn't fit to respective cells size + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain a new property + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size); + +/** + * fdt_delprop - delete a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to nop + * @name: name of the property to nop + * + * fdt_del_property() will delete the given property. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOTFOUND, node does not have the named property + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_delprop(void *fdt, int nodeoffset, const char *name); + +/** + * fdt_add_subnode_namelen - creates a new node based on substring + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * @namelen: number of characters of name to consider + * + * Identical to fdt_add_subnode(), but use only the first namelen + * characters of name as the name of the new node. This is useful for + * creating subnodes based on a portion of a larger string, such as a + * full path. + */ +#ifndef SWIG /* Not available in Python */ +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen); +#endif + +/** + * fdt_add_subnode - creates a new node + * @fdt: pointer to the device tree blob + * @parentoffset: structure block offset of a node + * @name: name of the subnode to locate + * + * fdt_add_subnode() creates a new node as a subnode of the node at + * structure block offset parentoffset, with the given name (which + * should include the unit address, if any). + * + * This function will insert data into the blob, and will therefore + * change the offsets of some existing nodes. + + * returns: + * structure block offset of the created nodeequested subnode (>=0), on + * success + * -FDT_ERR_NOTFOUND, if the requested subnode does not exist + * -FDT_ERR_BADOFFSET, if parentoffset did not point to an FDT_BEGIN_NODE + * tag + * -FDT_ERR_EXISTS, if the node at parentoffset already has a subnode of + * the given name + * -FDT_ERR_NOSPACE, if there is insufficient free space in the + * blob to contain the new node + * -FDT_ERR_NOSPACE + * -FDT_ERR_BADLAYOUT + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings. + */ +int fdt_add_subnode(void *fdt, int parentoffset, const char *name); + +/** + * fdt_del_node - delete a node (subtree) + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node to nop + * + * fdt_del_node() will remove the given node, including all its + * subnodes if any, from the blob. + * + * This function will delete data from the blob, and will therefore + * change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_del_node(void *fdt, int nodeoffset); + +/** + * fdt_overlay_apply - Applies a DT overlay on a base DT + * @fdt: pointer to the base device tree blob + * @fdto: pointer to the device tree overlay blob + * + * fdt_overlay_apply() will apply the given device tree overlay on the + * given base device tree. + * + * Expect the base device tree to be modified, even if the function + * returns an error. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there's not enough space in the base device tree + * -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or + * properties in the base DT + * -FDT_ERR_BADPHANDLE, + * -FDT_ERR_BADOVERLAY, + * -FDT_ERR_NOPHANDLES, + * -FDT_ERR_INTERNAL, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADOFFSET, + * -FDT_ERR_BADPATH, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_overlay_apply(void *fdt, void *fdto); + +/**********************************************************************/ +/* Debugging / informational functions */ +/**********************************************************************/ + +const char *fdt_strerror(int errval); + +#ifdef __cplusplus +} +#endif + +#endif /* LIBFDT_H */ diff --git a/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h b/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h new file mode 100644 index 0000000..73b6d40 --- /dev/null +++ b/arm-trusted-firmware/include/lib/libfdt/libfdt_env.h @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_ENV_H +#define LIBFDT_ENV_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * Copyright 2012 Kim Phillips, Freescale Semiconductor. + */ + +#include +#include +#include +#include +#include +#include + +#ifdef __CHECKER__ +#define FDT_FORCE __attribute__((force)) +#define FDT_BITWISE __attribute__((bitwise)) +#else +#define FDT_FORCE +#define FDT_BITWISE +#endif + +typedef uint16_t FDT_BITWISE fdt16_t; +typedef uint32_t FDT_BITWISE fdt32_t; +typedef uint64_t FDT_BITWISE fdt64_t; + +#define EXTRACT_BYTE(x, n) ((unsigned long long)((uint8_t *)&x)[n]) +#define CPU_TO_FDT16(x) ((EXTRACT_BYTE(x, 0) << 8) | EXTRACT_BYTE(x, 1)) +#define CPU_TO_FDT32(x) ((EXTRACT_BYTE(x, 0) << 24) | (EXTRACT_BYTE(x, 1) << 16) | \ + (EXTRACT_BYTE(x, 2) << 8) | EXTRACT_BYTE(x, 3)) +#define CPU_TO_FDT64(x) ((EXTRACT_BYTE(x, 0) << 56) | (EXTRACT_BYTE(x, 1) << 48) | \ + (EXTRACT_BYTE(x, 2) << 40) | (EXTRACT_BYTE(x, 3) << 32) | \ + (EXTRACT_BYTE(x, 4) << 24) | (EXTRACT_BYTE(x, 5) << 16) | \ + (EXTRACT_BYTE(x, 6) << 8) | EXTRACT_BYTE(x, 7)) + +static inline uint16_t fdt16_to_cpu(fdt16_t x) +{ + return (FDT_FORCE uint16_t)CPU_TO_FDT16(x); +} +static inline fdt16_t cpu_to_fdt16(uint16_t x) +{ + return (FDT_FORCE fdt16_t)CPU_TO_FDT16(x); +} + +static inline uint32_t fdt32_to_cpu(fdt32_t x) +{ + return (FDT_FORCE uint32_t)CPU_TO_FDT32(x); +} +static inline fdt32_t cpu_to_fdt32(uint32_t x) +{ + return (FDT_FORCE fdt32_t)CPU_TO_FDT32(x); +} + +static inline uint64_t fdt64_to_cpu(fdt64_t x) +{ + return (FDT_FORCE uint64_t)CPU_TO_FDT64(x); +} +static inline fdt64_t cpu_to_fdt64(uint64_t x) +{ + return (FDT_FORCE fdt64_t)CPU_TO_FDT64(x); +} +#undef CPU_TO_FDT64 +#undef CPU_TO_FDT32 +#undef CPU_TO_FDT16 +#undef EXTRACT_BYTE + +#ifdef __APPLE__ +#include + +/* strnlen() is not available on Mac OS < 10.7 */ +# if !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < \ + MAC_OS_X_VERSION_10_7) + +#define strnlen fdt_strnlen + +/* + * fdt_strnlen: returns the length of a string or max_count - which ever is + * smallest. + * Input 1 string: the string whose size is to be determined + * Input 2 max_count: the maximum value returned by this function + * Output: length of the string or max_count (the smallest of the two) + */ +static inline size_t fdt_strnlen(const char *string, size_t max_count) +{ + const char *p = memchr(string, 0, max_count); + return p ? p - string : max_count; +} + +#endif /* !defined(MAC_OS_X_VERSION_10_7) || (MAC_OS_X_VERSION_MAX_ALLOWED < + MAC_OS_X_VERSION_10_7) */ + +#endif /* __APPLE__ */ + +#endif /* LIBFDT_ENV_H */ diff --git a/arm-trusted-firmware/include/lib/mmio.h b/arm-trusted-firmware/include/lib/mmio.h new file mode 100644 index 0000000..3242a7c --- /dev/null +++ b/arm-trusted-firmware/include/lib/mmio.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MMIO_H +#define MMIO_H + +#include + +static inline void mmio_write_8(uintptr_t addr, uint8_t value) +{ + *(volatile uint8_t*)addr = value; +} + +static inline uint8_t mmio_read_8(uintptr_t addr) +{ + return *(volatile uint8_t*)addr; +} + +static inline void mmio_write_16(uintptr_t addr, uint16_t value) +{ + *(volatile uint16_t*)addr = value; +} + +static inline uint16_t mmio_read_16(uintptr_t addr) +{ + return *(volatile uint16_t*)addr; +} + +static inline void mmio_clrsetbits_16(uintptr_t addr, + uint16_t clear, + uint16_t set) +{ + mmio_write_16(addr, (mmio_read_16(addr) & ~clear) | set); +} + +static inline void mmio_write_32(uintptr_t addr, uint32_t value) +{ + *(volatile uint32_t*)addr = value; +} + +static inline uint32_t mmio_read_32(uintptr_t addr) +{ + return *(volatile uint32_t*)addr; +} + +static inline void mmio_write_64(uintptr_t addr, uint64_t value) +{ + *(volatile uint64_t*)addr = value; +} + +static inline uint64_t mmio_read_64(uintptr_t addr) +{ + return *(volatile uint64_t*)addr; +} + +static inline void mmio_clrbits_32(uintptr_t addr, uint32_t clear) +{ + mmio_write_32(addr, mmio_read_32(addr) & ~clear); +} + +static inline void mmio_setbits_32(uintptr_t addr, uint32_t set) +{ + mmio_write_32(addr, mmio_read_32(addr) | set); +} + +static inline void mmio_clrsetbits_32(uintptr_t addr, + uint32_t clear, + uint32_t set) +{ + mmio_write_32(addr, (mmio_read_32(addr) & ~clear) | set); +} + +#endif /* MMIO_H */ diff --git a/arm-trusted-firmware/include/lib/mpmm/mpmm.h b/arm-trusted-firmware/include/lib/mpmm/mpmm.h new file mode 100644 index 0000000..955c530 --- /dev/null +++ b/arm-trusted-firmware/include/lib/mpmm/mpmm.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MPMM_H +#define MPMM_H + +#include + +#include + +/* + * Enable the Maximum Power Mitigation Mechanism. + * + * This function will enable MPMM for the current core. The AMU counters + * representing the MPMM gears must have been configured and enabled prior to + * calling this function. + */ +void mpmm_enable(void); + +/* + * MPMM core data. + * + * This structure represents per-core data retrieved from the hardware + * configuration device tree. + */ +struct mpmm_core { + /* + * Whether MPMM is supported. + * + * Cores with support for MPMM offer one or more auxiliary AMU counters + * representing MPMM gears. + */ + bool supported; +}; + +/* + * MPMM topology. + * + * This topology structure describes the system-wide representation of the + * information retrieved from the hardware configuration device tree. + */ +struct mpmm_topology { + struct mpmm_core cores[PLATFORM_CORE_COUNT]; /* Per-core data */ +}; + +#if !ENABLE_MPMM_FCONF +/* + * Retrieve the platform's MPMM topology. A `NULL` return value is treated as a + * non-fatal error, in which case MPMM will not be enabled for any core. + */ +const struct mpmm_topology *plat_mpmm_topology(void); +#endif /* ENABLE_MPMM_FCONF */ + +#endif /* MPMM_H */ diff --git a/arm-trusted-firmware/include/lib/object_pool.h b/arm-trusted-firmware/include/lib/object_pool.h new file mode 100644 index 0000000..66e8c47 --- /dev/null +++ b/arm-trusted-firmware/include/lib/object_pool.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OBJECT_POOL_H +#define OBJECT_POOL_H + +#include + +#include +#include + +/* + * Pool of statically allocated objects. + * + * Objects can be reserved but not freed. This is by design and it is not a + * limitation. We do not want to introduce complexity induced by memory freeing, + * such as use-after-free bugs, memory fragmentation and so on. + * + * The object size and capacity of the pool are fixed at build time. So is the + * address of the objects back store. + */ +struct object_pool { + /* Size of 1 object in the pool in byte unit. */ + const size_t obj_size; + + /* Number of objects in the pool. */ + const size_t capacity; + + /* Objects back store. */ + void *const objects; + + /* How many objects are currently allocated. */ + size_t used; +}; + +/* Create a static pool of objects. */ +#define OBJECT_POOL(_pool_name, _obj_backstore, _obj_size, _obj_count) \ + struct object_pool _pool_name = { \ + .objects = (_obj_backstore), \ + .obj_size = (_obj_size), \ + .capacity = (_obj_count), \ + .used = 0U, \ + } + +/* Create a static pool of objects out of an array of pre-allocated objects. */ +#define OBJECT_POOL_ARRAY(_pool_name, _obj_array) \ + OBJECT_POOL(_pool_name, (_obj_array), \ + sizeof((_obj_array)[0]), ARRAY_SIZE(_obj_array)) + +/* + * Allocate 'count' objects from a pool. + * Return the address of the first object. Panic on error. + */ +static inline void *pool_alloc_n(struct object_pool *pool, size_t count) +{ + if ((pool->used + count) > pool->capacity) { + ERROR("Cannot allocate %zu objects out of pool (%zu objects left).\n", + count, pool->capacity - pool->used); + panic(); + } + + void *obj = (char *)(pool->objects) + (pool->obj_size * pool->used); + pool->used += count; + return obj; +} + +/* + * Allocate 1 object from a pool. + * Return the address of the object. Panic on error. + */ +static inline void *pool_alloc(struct object_pool *pool) +{ + return pool_alloc_n(pool, 1U); +} + +#endif /* OBJECT_POOL_H */ diff --git a/arm-trusted-firmware/include/lib/optee_utils.h b/arm-trusted-firmware/include/lib/optee_utils.h new file mode 100644 index 0000000..06378eb --- /dev/null +++ b/arm-trusted-firmware/include/lib/optee_utils.h @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPTEE_UTILS_H +#define OPTEE_UTILS_H + +#include + +#include + +bool optee_header_is_valid(uintptr_t header_base); + +int parse_optee_header(entry_point_info_t *header_ep, + image_info_t *pager_image_info, + image_info_t *paged_image_info); + +#endif /* OPTEE_UTILS_H */ diff --git a/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S b/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S new file mode 100644 index 0000000..1dbb408 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_ASM_MACROS_S +#define PMF_ASM_MACROS_S + +#define PMF_TS_SIZE 8 + + /* + * This macro calculates the address of the per-cpu timestamp + * for the given service name and local timestamp id. + * Clobbers: r0 - r4 + */ + .macro pmf_calc_timestamp_addr _name, _tid + mov r4, lr + bl plat_my_core_pos + mov lr, r4 + ldr r1, =__PERCPU_TIMESTAMP_SIZE__ + mov r2, #(\_tid * PMF_TS_SIZE) + mla r0, r0, r1, r2 + ldr r1, =pmf_ts_mem_\_name + add r0, r0, r1 + .endm + +#endif /* PMF_ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S b/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S new file mode 100644 index 0000000..5f3e6b7 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_ASM_MACROS_S +#define PMF_ASM_MACROS_S + +#define PMF_TS_SIZE 8 + + /* + * This macro calculates the address of the per-cpu timestamp + * for the given service name and local timestamp id. + * Clobbers: x0 - x9 + */ + .macro pmf_calc_timestamp_addr _name, _tid + mov x9, x30 + bl plat_my_core_pos + mov x30, x9 + adr x2, __PMF_PERCPU_TIMESTAMP_END__ + adr x1, __PMF_TIMESTAMP_START__ + sub x1, x2, x1 + mov x2, #(\_tid * PMF_TS_SIZE) + madd x0, x0, x1, x2 + adr x1, pmf_ts_mem_\_name + add x0, x0, x1 + .endm + +#endif /* PMF_ASM_MACROS_S */ diff --git a/arm-trusted-firmware/include/lib/pmf/pmf.h b/arm-trusted-firmware/include/lib/pmf/pmf.h new file mode 100644 index 0000000..fa990d2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/pmf.h @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_H +#define PMF_H + +#include +#include +#include + +/* + * Constants used for/by PMF services. + */ +#define PMF_ARM_TIF_IMPL_ID UL(0x41) +#define PMF_TID_SHIFT 0 +#define PMF_TID_MASK (UL(0xFF) << PMF_TID_SHIFT) +#define PMF_SVC_ID_SHIFT 10 +#define PMF_SVC_ID_MASK (UL(0x3F) << PMF_SVC_ID_SHIFT) +#define PMF_IMPL_ID_SHIFT 24 +#define PMF_IMPL_ID_MASK (UL(0xFF) << PMF_IMPL_ID_SHIFT) + +/* + * Flags passed to PMF_REGISTER_SERVICE + */ +#define PMF_STORE_ENABLE (1 << 0) +#define PMF_DUMP_ENABLE (1 << 1) + +/* + * Flags passed to PMF_GET_TIMESTAMP_XXX + * and PMF_CAPTURE_TIMESTAMP + */ +#define PMF_CACHE_MAINT (U(1) << 0) +#define PMF_NO_CACHE_MAINT U(0) + +/* + * Defines for PMF SMC function ids. + */ +#define PMF_SMC_GET_TIMESTAMP_32 U(0x82000010) +#define PMF_SMC_GET_TIMESTAMP_64 U(0xC2000010) +#define PMF_NUM_SMC_CALLS 2 + +/* + * The macros below are used to identify + * PMF calls from the SMC function ID. + */ +#define PMF_FID_MASK U(0xffe0) +#define PMF_FID_VALUE U(0) +#define is_pmf_fid(_fid) (((_fid) & PMF_FID_MASK) == PMF_FID_VALUE) + +/* Following are the supported PMF service IDs */ +#define PMF_PSCI_STAT_SVC_ID 0 +#define PMF_RT_INSTR_SVC_ID 1 + +/******************************************************************************* + * Function & variable prototypes + ******************************************************************************/ +/* PMF common functions */ +int pmf_get_timestamp_smc(unsigned int tid, + u_register_t mpidr, + unsigned int flags, + unsigned long long *ts_value); +int pmf_setup(void); +uintptr_t pmf_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); + +#endif /* PMF_H */ diff --git a/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h b/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h new file mode 100644 index 0000000..b49c6da --- /dev/null +++ b/arm-trusted-firmware/include/lib/pmf/pmf_helpers.h @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMF_HELPERS_H +#define PMF_HELPERS_H + +#include +#include +#include + +#include +#include +#include + +/* + * Prototype for PMF service functions. + */ +typedef int (*pmf_svc_init_t)(void); +typedef unsigned long long (*pmf_svc_get_ts_t)(unsigned int tid, + u_register_t mpidr, + unsigned int flags); + +/* + * This is the definition of PMF service desc. + */ +typedef struct pmf_svc_desc { + /* Structure version information */ + param_header_t h; + + /* Name of the PMF service */ + const char *name; + + /* PMF service config: Implementer id, Service id and total id*/ + unsigned int svc_config; + + /* PMF service initialization handler */ + pmf_svc_init_t init; + + /* PMF service time-stamp retrieval handler */ + pmf_svc_get_ts_t get_ts; +} pmf_svc_desc_t; + +#if ENABLE_PMF +/* + * Convenience macros for capturing time-stamp. + */ +#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) \ + void pmf_capture_timestamp_with_cache_maint_ ## _name( \ + unsigned int tid, \ + unsigned long long ts); \ + void pmf_capture_timestamp_ ## _name( \ + unsigned int tid, \ + unsigned long long ts); + +#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) \ + do { \ + unsigned long long ts = read_cntpct_el0(); \ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), ts);\ + else \ + pmf_capture_timestamp_ ## _name((_tid), ts); \ + } while (0) + +#define PMF_CAPTURE_AND_GET_TIMESTAMP(_name, _tid, _flags, _tsval) \ + do { \ + (_tsval) = read_cntpct_el0(); \ + CASSERT(sizeof(_tsval) == sizeof(unsigned long long), invalid_tsval_size);\ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_tsval));\ + else \ + pmf_capture_timestamp_ ## _name((_tid), (_tsval));\ + } while (0) + +#define PMF_WRITE_TIMESTAMP(_name, _tid, _flags, _wrval) \ + do { \ + CASSERT(sizeof(_wrval) == sizeof(unsigned long long), invalid_wrval_size);\ + if (((_flags) & PMF_CACHE_MAINT) != 0U) \ + pmf_capture_timestamp_with_cache_maint_ ## _name((_tid), (_wrval));\ + else \ + pmf_capture_timestamp_ ## _name((_tid), (_wrval));\ + } while (0) + +/* + * Convenience macros for retrieving time-stamp. + */ +#define PMF_DECLARE_GET_TIMESTAMP(_name) \ + unsigned long long pmf_get_timestamp_by_index_ ## _name(\ + unsigned int tid, \ + unsigned int cpuid, \ + unsigned int flags); \ + unsigned long long pmf_get_timestamp_by_mpidr_ ## _name(\ + unsigned int tid, \ + u_register_t mpidr, \ + unsigned int flags); + +#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval)\ + _tsval = pmf_get_timestamp_by_mpidr_ ## _name(_tid, _mpidr, _flags) + +#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval)\ + _tsval = pmf_get_timestamp_by_index_ ## _name(_tid, _cpuid, _flags) + +/* Convenience macros to register a PMF service.*/ +/* + * This macro is used to register a PMF Service. It allocates PMF memory + * and defines default service-specific PMF functions. + */ +#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ + PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _totalid) \ + PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ + PMF_DEFINE_GET_TIMESTAMP(_name) + +/* + * This macro is used to register a PMF service, including an + * SMC interface to that service. + */ +#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags)\ + PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) \ + PMF_DEFINE_SERVICE_DESC(_name, PMF_ARM_TIF_IMPL_ID, \ + _svcid, _totalid, NULL, \ + pmf_get_timestamp_by_mpidr_ ## _name) + +/* + * This macro is used to register a PMF service that has an SMC interface + * but provides its own service-specific PMF functions. + */ +#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ + _init, _getts) \ + PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ + _init, _getts) + +#else + +#define PMF_REGISTER_SERVICE(_name, _svcid, _totalid, _flags) +#define PMF_REGISTER_SERVICE_SMC(_name, _svcid, _totalid, _flags) +#define PMF_REGISTER_SERVICE_SMC_OWN(_name, _implid, _svcid, _totalid, \ + _init, _getts) +#define PMF_DECLARE_CAPTURE_TIMESTAMP(_name) +#define PMF_DECLARE_GET_TIMESTAMP(_name) +#define PMF_CAPTURE_TIMESTAMP(_name, _tid, _flags) +#define PMF_GET_TIMESTAMP_BY_MPIDR(_name, _tid, _mpidr, _flags, _tsval) +#define PMF_GET_TIMESTAMP_BY_INDEX(_name, _tid, _cpuid, _flags, _tsval) + +#endif /* ENABLE_PMF */ + +/* + * Convenience macro to allocate memory for a PMF service. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_ALLOCATE_TIMESTAMP_MEMORY(_name, _total_id) \ + extern unsigned long long pmf_ts_mem_ ## _name[_total_id]; \ + unsigned long long pmf_ts_mem_ ## _name[_total_id] \ + __aligned(CACHE_WRITEBACK_GRANULE) \ + __section("pmf_timestamp_array") \ + __used; + +/* + * Convenience macro to validate tid index for the given TS array. + */ +#define PMF_VALIDATE_TID(_name, _tid) \ + assert((_tid & PMF_TID_MASK) < (ARRAY_SIZE(pmf_ts_mem_ ## _name))) + +/* + * Convenience macros for capturing time-stamp. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_DEFINE_CAPTURE_TIMESTAMP(_name, _flags) \ + void pmf_capture_timestamp_ ## _name( \ + unsigned int tid, \ + unsigned long long ts) \ + { \ + CASSERT(_flags != 0, select_proper_config); \ + PMF_VALIDATE_TID(_name, (uint64_t)tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + if (((_flags) & PMF_STORE_ENABLE) != 0) \ + __pmf_store_timestamp(base_addr, \ + (uint64_t)tid, ts); \ + if (((_flags) & PMF_DUMP_ENABLE) != 0) \ + __pmf_dump_timestamp((uint64_t)tid, ts); \ + } \ + void pmf_capture_timestamp_with_cache_maint_ ## _name( \ + unsigned int tid, \ + unsigned long long ts) \ + { \ + CASSERT(_flags != 0, select_proper_config); \ + PMF_VALIDATE_TID(_name, (uint64_t)tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + if (((_flags) & PMF_STORE_ENABLE) != 0) \ + __pmf_store_timestamp_with_cache_maint( \ + base_addr, (uint64_t)tid, ts); \ + if (((_flags) & PMF_DUMP_ENABLE) != 0) \ + __pmf_dump_timestamp((uint64_t)tid, ts); \ + } + +/* + * Convenience macros for retrieving time-stamp. + * + * The extern declaration is there to satisfy MISRA C-2012 rule 8.4. + */ +#define PMF_DEFINE_GET_TIMESTAMP(_name) \ + unsigned long long pmf_get_timestamp_by_index_ ## _name( \ + unsigned int tid, unsigned int cpuid, unsigned int flags)\ + { \ + PMF_VALIDATE_TID(_name, tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + return __pmf_get_timestamp(base_addr, tid, cpuid, flags);\ + } \ + unsigned long long pmf_get_timestamp_by_mpidr_ ## _name( \ + unsigned int tid, u_register_t mpidr, unsigned int flags)\ + { \ + PMF_VALIDATE_TID(_name, tid); \ + uintptr_t base_addr = (uintptr_t) pmf_ts_mem_ ## _name; \ + return __pmf_get_timestamp(base_addr, tid, \ + plat_core_pos_by_mpidr(mpidr), flags); \ + } + +/* + * Convenience macro to register a PMF service. + * This is needed for services that require SMC handling. + */ +#define PMF_DEFINE_SERVICE_DESC(_name, _implid, _svcid, _totalid, \ + _init, _getts_by_mpidr) \ + static const pmf_svc_desc_t __pmf_desc_ ## _name \ + __section("pmf_svc_descs") __used = { \ + .h.type = PARAM_EP, \ + .h.version = VERSION_1, \ + .h.size = sizeof(pmf_svc_desc_t), \ + .h.attr = 0, \ + .name = #_name, \ + .svc_config = ((((_implid) << PMF_IMPL_ID_SHIFT) & \ + PMF_IMPL_ID_MASK) | \ + (((_svcid) << PMF_SVC_ID_SHIFT) & \ + PMF_SVC_ID_MASK) | \ + (((_totalid) << PMF_TID_SHIFT) & \ + PMF_TID_MASK)), \ + .init = _init, \ + .get_ts = _getts_by_mpidr \ + }; + +/* PMF internal functions */ +void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts); +void __pmf_store_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts); +void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts); +unsigned long long __pmf_get_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid, + unsigned int flags); +#endif /* PMF_HELPERS_H */ diff --git a/arm-trusted-firmware/include/lib/psci/psci.h b/arm-trusted-firmware/include/lib/psci/psci.h new file mode 100644 index 0000000..b56e98b --- /dev/null +++ b/arm-trusted-firmware/include/lib/psci/psci.h @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_H +#define PSCI_H + +#include /* for PLAT_NUM_PWR_DOMAINS */ + +#include +#include +#include /* To maintain compatibility for SPDs */ +#include + +/******************************************************************************* + * Number of power domains whose state this PSCI implementation can track + ******************************************************************************/ +#ifdef PLAT_NUM_PWR_DOMAINS +#define PSCI_NUM_PWR_DOMAINS PLAT_NUM_PWR_DOMAINS +#else +#define PSCI_NUM_PWR_DOMAINS (U(2) * PLATFORM_CORE_COUNT) +#endif + +#define PSCI_NUM_NON_CPU_PWR_DOMAINS (PSCI_NUM_PWR_DOMAINS - \ + PLATFORM_CORE_COUNT) + +/* This is the power level corresponding to a CPU */ +#define PSCI_CPU_PWR_LVL U(0) + +/* + * The maximum power level supported by PSCI. Since PSCI CPU_SUSPEND + * uses the old power_state parameter format which has 2 bits to specify the + * power level, this constant is defined to be 3. + */ +#define PSCI_MAX_PWR_LVL U(3) + +/******************************************************************************* + * Defines for runtime services function ids + ******************************************************************************/ +#define PSCI_VERSION U(0x84000000) +#define PSCI_CPU_SUSPEND_AARCH32 U(0x84000001) +#define PSCI_CPU_SUSPEND_AARCH64 U(0xc4000001) +#define PSCI_CPU_OFF U(0x84000002) +#define PSCI_CPU_ON_AARCH32 U(0x84000003) +#define PSCI_CPU_ON_AARCH64 U(0xc4000003) +#define PSCI_AFFINITY_INFO_AARCH32 U(0x84000004) +#define PSCI_AFFINITY_INFO_AARCH64 U(0xc4000004) +#define PSCI_MIG_AARCH32 U(0x84000005) +#define PSCI_MIG_AARCH64 U(0xc4000005) +#define PSCI_MIG_INFO_TYPE U(0x84000006) +#define PSCI_MIG_INFO_UP_CPU_AARCH32 U(0x84000007) +#define PSCI_MIG_INFO_UP_CPU_AARCH64 U(0xc4000007) +#define PSCI_SYSTEM_OFF U(0x84000008) +#define PSCI_SYSTEM_RESET U(0x84000009) +#define PSCI_FEATURES U(0x8400000A) +#define PSCI_NODE_HW_STATE_AARCH32 U(0x8400000d) +#define PSCI_NODE_HW_STATE_AARCH64 U(0xc400000d) +#define PSCI_SYSTEM_SUSPEND_AARCH32 U(0x8400000E) +#define PSCI_SYSTEM_SUSPEND_AARCH64 U(0xc400000E) +#define PSCI_STAT_RESIDENCY_AARCH32 U(0x84000010) +#define PSCI_STAT_RESIDENCY_AARCH64 U(0xc4000010) +#define PSCI_STAT_COUNT_AARCH32 U(0x84000011) +#define PSCI_STAT_COUNT_AARCH64 U(0xc4000011) +#define PSCI_SYSTEM_RESET2_AARCH32 U(0x84000012) +#define PSCI_SYSTEM_RESET2_AARCH64 U(0xc4000012) +#define PSCI_MEM_PROTECT U(0x84000013) +#define PSCI_MEM_CHK_RANGE_AARCH32 U(0x84000014) +#define PSCI_MEM_CHK_RANGE_AARCH64 U(0xc4000014) + +/* + * Number of PSCI calls (above) implemented + */ +#if ENABLE_PSCI_STAT +#define PSCI_NUM_CALLS U(22) +#else +#define PSCI_NUM_CALLS U(18) +#endif + +/* The macros below are used to identify PSCI calls from the SMC function ID */ +#define PSCI_FID_MASK U(0xffe0) +#define PSCI_FID_VALUE U(0) +#define is_psci_fid(_fid) \ + (((_fid) & PSCI_FID_MASK) == PSCI_FID_VALUE) + +/******************************************************************************* + * PSCI Migrate and friends + ******************************************************************************/ +#define PSCI_TOS_UP_MIG_CAP 0 +#define PSCI_TOS_NOT_UP_MIG_CAP 1 +#define PSCI_TOS_NOT_PRESENT_MP 2 + +/******************************************************************************* + * PSCI CPU_SUSPEND 'power_state' parameter specific defines + ******************************************************************************/ +#define PSTATE_ID_SHIFT U(0) + +#if PSCI_EXTENDED_STATE_ID +#define PSTATE_VALID_MASK U(0xB0000000) +#define PSTATE_TYPE_SHIFT U(30) +#define PSTATE_ID_MASK U(0xfffffff) +#else +#define PSTATE_VALID_MASK U(0xFCFE0000) +#define PSTATE_TYPE_SHIFT U(16) +#define PSTATE_PWR_LVL_SHIFT U(24) +#define PSTATE_ID_MASK U(0xffff) +#define PSTATE_PWR_LVL_MASK U(0x3) + +#define psci_get_pstate_pwrlvl(pstate) (((pstate) >> PSTATE_PWR_LVL_SHIFT) & \ + PSTATE_PWR_LVL_MASK) +#define psci_make_powerstate(state_id, type, pwrlvl) \ + (((state_id) & PSTATE_ID_MASK) << PSTATE_ID_SHIFT) |\ + (((type) & PSTATE_TYPE_MASK) << PSTATE_TYPE_SHIFT) |\ + (((pwrlvl) & PSTATE_PWR_LVL_MASK) << PSTATE_PWR_LVL_SHIFT) +#endif /* __PSCI_EXTENDED_STATE_ID__ */ + +#define PSTATE_TYPE_STANDBY U(0x0) +#define PSTATE_TYPE_POWERDOWN U(0x1) +#define PSTATE_TYPE_MASK U(0x1) + +/******************************************************************************* + * PSCI CPU_FEATURES feature flag specific defines + ******************************************************************************/ +/* Features flags for CPU SUSPEND power state parameter format. Bits [1:1] */ +#define FF_PSTATE_SHIFT U(1) +#define FF_PSTATE_ORIG U(0) +#define FF_PSTATE_EXTENDED U(1) +#if PSCI_EXTENDED_STATE_ID +#define FF_PSTATE FF_PSTATE_EXTENDED +#else +#define FF_PSTATE FF_PSTATE_ORIG +#endif + +/* Features flags for CPU SUSPEND OS Initiated mode support. Bits [0:0] */ +#define FF_MODE_SUPPORT_SHIFT U(0) +#define FF_SUPPORTS_OS_INIT_MODE U(1) + +/******************************************************************************* + * PSCI version + ******************************************************************************/ +#define PSCI_MAJOR_VER (U(1) << 16) +#define PSCI_MINOR_VER U(0x1) + +/******************************************************************************* + * PSCI error codes + ******************************************************************************/ +#define PSCI_E_SUCCESS 0 +#define PSCI_E_NOT_SUPPORTED -1 +#define PSCI_E_INVALID_PARAMS -2 +#define PSCI_E_DENIED -3 +#define PSCI_E_ALREADY_ON -4 +#define PSCI_E_ON_PENDING -5 +#define PSCI_E_INTERN_FAIL -6 +#define PSCI_E_NOT_PRESENT -7 +#define PSCI_E_DISABLED -8 +#define PSCI_E_INVALID_ADDRESS -9 + +#define PSCI_INVALID_MPIDR ~((u_register_t)0) + +/* + * SYSTEM_RESET2 macros + */ +#define PSCI_RESET2_TYPE_VENDOR_SHIFT U(31) +#define PSCI_RESET2_TYPE_VENDOR (U(1) << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_TYPE_ARCH (U(0) << PSCI_RESET2_TYPE_VENDOR_SHIFT) +#define PSCI_RESET2_SYSTEM_WARM_RESET (PSCI_RESET2_TYPE_ARCH | U(0)) + +#ifndef __ASSEMBLER__ + +#include + +/* Function to help build the psci capabilities bitfield */ + +static inline unsigned int define_psci_cap(unsigned int x) +{ + return U(1) << (x & U(0x1f)); +} + + +/* Power state helper functions */ + +static inline unsigned int psci_get_pstate_id(unsigned int power_state) +{ + return ((power_state) >> PSTATE_ID_SHIFT) & PSTATE_ID_MASK; +} + +static inline unsigned int psci_get_pstate_type(unsigned int power_state) +{ + return ((power_state) >> PSTATE_TYPE_SHIFT) & PSTATE_TYPE_MASK; +} + +static inline unsigned int psci_check_power_state(unsigned int power_state) +{ + return ((power_state) & PSTATE_VALID_MASK); +} + +/* + * These are the states reported by the PSCI_AFFINITY_INFO API for the specified + * CPU. The definitions of these states can be found in Section 5.7.1 in the + * PSCI specification (ARM DEN 0022C). + */ +typedef enum { + AFF_STATE_ON = U(0), + AFF_STATE_OFF = U(1), + AFF_STATE_ON_PENDING = U(2) +} aff_info_state_t; + +/* + * These are the power states reported by PSCI_NODE_HW_STATE API for the + * specified CPU. The definitions of these states can be found in Section 5.15.3 + * of PSCI specification (ARM DEN 0022C). + */ +#define HW_ON 0 +#define HW_OFF 1 +#define HW_STANDBY 2 + +/* + * Macro to represent invalid affinity level within PSCI. + */ +#define PSCI_INVALID_PWR_LVL (PLAT_MAX_PWR_LVL + U(1)) + +/* + * Type for representing the local power state at a particular level. + */ +typedef uint8_t plat_local_state_t; + +/* The local state macro used to represent RUN state. */ +#define PSCI_LOCAL_STATE_RUN U(0) + +/* + * Function to test whether the plat_local_state is RUN state + */ +static inline int is_local_state_run(unsigned int plat_local_state) +{ + return (plat_local_state == PSCI_LOCAL_STATE_RUN) ? 1 : 0; +} + +/* + * Function to test whether the plat_local_state is RETENTION state + */ +static inline int is_local_state_retn(unsigned int plat_local_state) +{ + return ((plat_local_state > PSCI_LOCAL_STATE_RUN) && + (plat_local_state <= PLAT_MAX_RET_STATE)) ? 1 : 0; +} + +/* + * Function to test whether the plat_local_state is OFF state + */ +static inline int is_local_state_off(unsigned int plat_local_state) +{ + return ((plat_local_state > PLAT_MAX_RET_STATE) && + (plat_local_state <= PLAT_MAX_OFF_STATE)) ? 1 : 0; +} + +/***************************************************************************** + * This data structure defines the representation of the power state parameter + * for its exchange between the generic PSCI code and the platform port. For + * example, it is used by the platform port to specify the requested power + * states during a power management operation. It is used by the generic code to + * inform the platform about the target power states that each level should + * enter. + ****************************************************************************/ +typedef struct psci_power_state { + /* + * The pwr_domain_state[] stores the local power state at each level + * for the CPU. + */ + plat_local_state_t pwr_domain_state[PLAT_MAX_PWR_LVL + U(1)]; +} psci_power_state_t; + +/******************************************************************************* + * Structure used to store per-cpu information relevant to the PSCI service. + * It is populated in the per-cpu data array. In return we get a guarantee that + * this information will not reside on a cache line shared with another cpu. + ******************************************************************************/ +typedef struct psci_cpu_data { + /* State as seen by PSCI Affinity Info API */ + aff_info_state_t aff_info_state; + + /* + * Highest power level which takes part in a power management + * operation. + */ + unsigned int target_pwrlvl; + + /* The local power state of this CPU */ + plat_local_state_t local_state; +} psci_cpu_data_t; + +/******************************************************************************* + * Structure populated by platform specific code to export routines which + * perform common low level power management functions + ******************************************************************************/ +typedef struct plat_psci_ops { + void (*cpu_standby)(plat_local_state_t cpu_state); + int (*pwr_domain_on)(u_register_t mpidr); + void (*pwr_domain_off)(const psci_power_state_t *target_state); + void (*pwr_domain_suspend_pwrdown_early)( + const psci_power_state_t *target_state); + void (*pwr_domain_suspend)(const psci_power_state_t *target_state); + void (*pwr_domain_on_finish)(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); + void __dead2 (*pwr_domain_pwr_down_wfi)( + const psci_power_state_t *target_state); + void __dead2 (*system_off)(void); + void __dead2 (*system_reset)(void); + int (*validate_power_state)(unsigned int power_state, + psci_power_state_t *req_state); + int (*validate_ns_entrypoint)(uintptr_t ns_entrypoint); + void (*get_sys_suspend_power_state)( + psci_power_state_t *req_state); + int (*get_pwr_lvl_state_idx)(plat_local_state_t pwr_domain_state, + int pwrlvl); + int (*translate_power_state_by_mpidr)(u_register_t mpidr, + unsigned int power_state, + psci_power_state_t *output_state); + int (*get_node_hw_state)(u_register_t mpidr, unsigned int power_level); + int (*mem_protect_chk)(uintptr_t base, u_register_t length); + int (*read_mem_protect)(int *val); + int (*write_mem_protect)(int val); + int (*system_reset2)(int is_vendor, + int reset_type, u_register_t cookie); +} plat_psci_ops_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +unsigned int psci_version(void); +int psci_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id); +int psci_cpu_suspend(unsigned int power_state, + uintptr_t entrypoint, + u_register_t context_id); +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id); +int psci_cpu_off(void); +int psci_affinity_info(u_register_t target_affinity, + unsigned int lowest_affinity_level); +int psci_migrate(u_register_t target_cpu); +int psci_migrate_info_type(void); +u_register_t psci_migrate_info_up_cpu(void); +int psci_node_hw_state(u_register_t target_cpu, + unsigned int power_level); +int psci_features(unsigned int psci_fid); +void __dead2 psci_power_down_wfi(void); +void psci_arch_setup(void); + +#endif /*__ASSEMBLER__*/ + +#endif /* PSCI_H */ diff --git a/arm-trusted-firmware/include/lib/psci/psci_lib.h b/arm-trusted-firmware/include/lib/psci/psci_lib.h new file mode 100644 index 0000000..1ac45ad --- /dev/null +++ b/arm-trusted-firmware/include/lib/psci/psci_lib.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_LIB_H +#define PSCI_LIB_H + +#include + +#ifndef __ASSEMBLER__ + +#include +#include + +/******************************************************************************* + * Optional structure populated by the Secure Payload Dispatcher to be given a + * chance to perform any bookkeeping before PSCI executes a power management + * operation. It also allows PSCI to determine certain properties of the SP e.g. + * migrate capability etc. + ******************************************************************************/ +typedef struct spd_pm_ops { + void (*svc_on)(u_register_t target_cpu); + int32_t (*svc_off)(u_register_t __unused unused); + void (*svc_suspend)(u_register_t max_off_pwrlvl); + void (*svc_on_finish)(u_register_t __unused unused); + void (*svc_suspend_finish)(u_register_t max_off_pwrlvl); + int32_t (*svc_migrate)(u_register_t from_cpu, u_register_t to_cpu); + int32_t (*svc_migrate_info)(u_register_t *resident_cpu); + void (*svc_system_off)(void); + void (*svc_system_reset)(void); +} spd_pm_ops_t; + +/* + * Function prototype for the warmboot entrypoint function which will be + * programmed in the mailbox by the platform. + */ +typedef void (*mailbox_entrypoint_t)(void); + +/****************************************************************************** + * Structure to pass PSCI Library arguments. + *****************************************************************************/ +typedef struct psci_lib_args { + /* The version information of PSCI Library Interface */ + param_header_t h; + /* The warm boot entrypoint function */ + mailbox_entrypoint_t mailbox_ep; +} psci_lib_args_t; + +/* Helper macro to set the psci_lib_args_t structure at runtime */ +#define SET_PSCI_LIB_ARGS_V1(_p, _entry) do { \ + SET_PARAM_HEAD(_p, PARAM_PSCI_LIB_ARGS, VERSION_1, 0); \ + (_p)->mailbox_ep = (_entry); \ + } while (0) + +/* Helper macro to define the psci_lib_args_t statically */ +#define DEFINE_STATIC_PSCI_LIB_ARGS_V1(_name, _entry) \ + static const psci_lib_args_t (_name) = { \ + .h.type = (uint8_t)PARAM_PSCI_LIB_ARGS, \ + .h.version = (uint8_t)VERSION_1, \ + .h.size = (uint16_t)sizeof(_name), \ + .h.attr = 0U, \ + .mailbox_ep = (_entry) \ + } + +/* Helper macro to verify the pointer to psci_lib_args_t structure */ +#define VERIFY_PSCI_LIB_ARGS_V1(_p) (((_p) != NULL) \ + && ((_p)->h.type == PARAM_PSCI_LIB_ARGS) \ + && ((_p)->h.version == VERSION_1) \ + && ((_p)->h.size == sizeof(*(_p))) \ + && ((_p)->h.attr == 0) \ + && ((_p)->mailbox_ep != NULL)) + +/****************************************************************************** + * PSCI Library Interfaces + *****************************************************************************/ +u_register_t psci_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); +int psci_setup(const psci_lib_args_t *lib_args); +int psci_secondaries_brought_up(void); +void psci_warmboot_entrypoint(void); +void psci_register_spd_pm_hook(const spd_pm_ops_t *pm); +void psci_prepare_next_non_secure_ctx( + entry_point_info_t *next_image_info); +int psci_stop_other_cores(unsigned int wait_ms, + void (*stop_func)(u_register_t mpidr)); +#endif /* __ASSEMBLER__ */ + +#endif /* PSCI_LIB_H */ diff --git a/arm-trusted-firmware/include/lib/runtime_instr.h b/arm-trusted-firmware/include/lib/runtime_instr.h new file mode 100644 index 0000000..303f27e --- /dev/null +++ b/arm-trusted-firmware/include/lib/runtime_instr.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RUNTIME_INSTR_H +#define RUNTIME_INSTR_H + +#include + +#define RT_INSTR_ENTER_PSCI U(0) +#define RT_INSTR_EXIT_PSCI U(1) +#define RT_INSTR_ENTER_HW_LOW_PWR U(2) +#define RT_INSTR_EXIT_HW_LOW_PWR U(3) +#define RT_INSTR_ENTER_CFLUSH U(4) +#define RT_INSTR_EXIT_CFLUSH U(5) +#define RT_INSTR_TOTAL_IDS U(6) + +#ifndef __ASSEMBLER__ +PMF_DECLARE_CAPTURE_TIMESTAMP(rt_instr_svc) +PMF_DECLARE_GET_TIMESTAMP(rt_instr_svc) +#endif /* __ASSEMBLER__ */ + +#endif /* RUNTIME_INSTR_H */ diff --git a/arm-trusted-firmware/include/lib/semihosting.h b/arm-trusted-firmware/include/lib/semihosting.h new file mode 100644 index 0000000..24b030c --- /dev/null +++ b/arm-trusted-firmware/include/lib/semihosting.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SEMIHOSTING_H +#define SEMIHOSTING_H + +#include +#include /* For ssize_t */ + + +#define SEMIHOSTING_SYS_OPEN 0x01 +#define SEMIHOSTING_SYS_CLOSE 0x02 +#define SEMIHOSTING_SYS_WRITE0 0x04 +#define SEMIHOSTING_SYS_WRITEC 0x03 +#define SEMIHOSTING_SYS_WRITE 0x05 +#define SEMIHOSTING_SYS_READ 0x06 +#define SEMIHOSTING_SYS_READC 0x07 +#define SEMIHOSTING_SYS_SEEK 0x0A +#define SEMIHOSTING_SYS_FLEN 0x0C +#define SEMIHOSTING_SYS_REMOVE 0x0E +#define SEMIHOSTING_SYS_SYSTEM 0x12 +#define SEMIHOSTING_SYS_ERRNO 0x13 +#define SEMIHOSTING_SYS_EXIT 0x18 + +#define FOPEN_MODE_R 0x0 +#define FOPEN_MODE_RB 0x1 +#define FOPEN_MODE_RPLUS 0x2 +#define FOPEN_MODE_RPLUSB 0x3 +#define FOPEN_MODE_W 0x4 +#define FOPEN_MODE_WB 0x5 +#define FOPEN_MODE_WPLUS 0x6 +#define FOPEN_MODE_WPLUSB 0x7 +#define FOPEN_MODE_A 0x8 +#define FOPEN_MODE_AB 0x9 +#define FOPEN_MODE_APLUS 0xa +#define FOPEN_MODE_APLUSB 0xb + +long semihosting_connection_supported(void); +long semihosting_file_open(const char *file_name, size_t mode); +long semihosting_file_seek(long file_handle, ssize_t offset); +long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer); +long semihosting_file_write(long file_handle, + size_t *length, + const uintptr_t buffer); +long semihosting_file_close(long file_handle); +long semihosting_file_length(long file_handle); +long semihosting_system(char *command_line); +long semihosting_get_flen(const char *file_name); +long semihosting_download_file(const char *file_name, + size_t buf_size, + uintptr_t buf); +void semihosting_write_char(char character); +void semihosting_write_string(char *string); +char semihosting_read_char(void); +void semihosting_exit(uint32_t reason, uint32_t subcode); + +#endif /* SEMIHOSTING_H */ diff --git a/arm-trusted-firmware/include/lib/smccc.h b/arm-trusted-firmware/include/lib/smccc.h new file mode 100644 index 0000000..1a39f24 --- /dev/null +++ b/arm-trusted-firmware/include/lib/smccc.h @@ -0,0 +1,211 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SMCCC_H +#define SMCCC_H + +#include + +#define SMCCC_VERSION_MAJOR_SHIFT U(16) +#define SMCCC_VERSION_MAJOR_MASK U(0x7FFF) +#define SMCCC_VERSION_MINOR_SHIFT U(0) +#define SMCCC_VERSION_MINOR_MASK U(0xFFFF) +#define MAKE_SMCCC_VERSION(_major, _minor) \ + ((((uint32_t)(_major) & SMCCC_VERSION_MAJOR_MASK) << \ + SMCCC_VERSION_MAJOR_SHIFT) \ + | (((uint32_t)(_minor) & SMCCC_VERSION_MINOR_MASK) << \ + SMCCC_VERSION_MINOR_SHIFT)) + +#define SMCCC_MAJOR_VERSION U(1) +#define SMCCC_MINOR_VERSION U(2) + +/******************************************************************************* + * Bit definitions inside the function id as per the SMC calling convention + ******************************************************************************/ +#define FUNCID_TYPE_SHIFT U(31) +#define FUNCID_TYPE_MASK U(0x1) +#define FUNCID_TYPE_WIDTH U(1) + +#define FUNCID_CC_SHIFT U(30) +#define FUNCID_CC_MASK U(0x1) +#define FUNCID_CC_WIDTH U(1) + +#define FUNCID_OEN_SHIFT U(24) +#define FUNCID_OEN_MASK U(0x3f) +#define FUNCID_OEN_WIDTH U(6) + +#define FUNCID_NUM_SHIFT U(0) +#define FUNCID_NUM_MASK U(0xffff) +#define FUNCID_NUM_WIDTH U(16) + +#define GET_SMC_NUM(id) (((id) >> FUNCID_NUM_SHIFT) & \ + FUNCID_NUM_MASK) +#define GET_SMC_TYPE(id) (((id) >> FUNCID_TYPE_SHIFT) & \ + FUNCID_TYPE_MASK) +#define GET_SMC_CC(id) (((id) >> FUNCID_CC_SHIFT) & \ + FUNCID_CC_MASK) +#define GET_SMC_OEN(id) (((id) >> FUNCID_OEN_SHIFT) & \ + FUNCID_OEN_MASK) + +/******************************************************************************* + * SMCCC_ARCH_SOC_ID SoC version & revision bit definition + ******************************************************************************/ +#define SOC_ID_JEP_106_BANK_IDX_MASK GENMASK_32(30, 24) +#define SOC_ID_JEP_106_BANK_IDX_SHIFT U(24) +#define SOC_ID_JEP_106_ID_CODE_MASK GENMASK_32(23, 16) +#define SOC_ID_JEP_106_ID_CODE_SHIFT U(16) +#define SOC_ID_IMPL_DEF_MASK GENMASK_32(15, 0) +#define SOC_ID_IMPL_DEF_SHIFT U(0) +#define SOC_ID_SET_JEP_106(bkid, mfid) ((((bkid) << SOC_ID_JEP_106_BANK_IDX_SHIFT) & \ + SOC_ID_JEP_106_BANK_IDX_MASK) | \ + (((mfid) << SOC_ID_JEP_106_ID_CODE_SHIFT) & \ + SOC_ID_JEP_106_ID_CODE_MASK)) + +#define SOC_ID_REV_MASK GENMASK_32(30, 0) +#define SOC_ID_REV_SHIFT U(0) + +/******************************************************************************* + * Owning entity number definitions inside the function id as per the SMC + * calling convention + ******************************************************************************/ +#define OEN_ARM_START U(0) +#define OEN_ARM_END U(0) +#define OEN_CPU_START U(1) +#define OEN_CPU_END U(1) +#define OEN_SIP_START U(2) +#define OEN_SIP_END U(2) +#define OEN_OEM_START U(3) +#define OEN_OEM_END U(3) +#define OEN_STD_START U(4) /* Standard Service Calls */ +#define OEN_STD_END U(4) +#define OEN_STD_HYP_START U(5) /* Standard Hypervisor Service calls */ +#define OEN_STD_HYP_END U(5) +#define OEN_VEN_HYP_START U(6) /* Vendor Hypervisor Service calls */ +#define OEN_VEN_HYP_END U(6) +#define OEN_TAP_START U(48) /* Trusted Applications */ +#define OEN_TAP_END U(49) +#define OEN_TOS_START U(50) /* Trusted OS */ +#define OEN_TOS_END U(63) +#define OEN_LIMIT U(64) + +/* Flags and error codes */ +#define SMC_64 U(1) +#define SMC_32 U(0) + +#define SMC_TYPE_FAST UL(1) +#define SMC_TYPE_YIELD UL(0) + +#define SMC_OK ULL(0) +#define SMC_UNK -1 +#define SMC_PREEMPTED -2 /* Not defined by the SMCCC */ + +/* Return codes for Arm Architecture Service SMC calls */ +#define SMC_ARCH_CALL_SUCCESS 0 +#define SMC_ARCH_CALL_NOT_SUPPORTED -1 +#define SMC_ARCH_CALL_NOT_REQUIRED -2 +#define SMC_ARCH_CALL_INVAL_PARAM -3 + +/* + * Various flags passed to SMC handlers + * + * Bit 5 and bit 0 of the flag are used to + * determine the source security state as + * follows: + * --------------------------------- + * Bit 5 | Bit 0 | Security state + * --------------------------------- + * 0 0 SMC_FROM_SECURE + * 0 1 SMC_FROM_NON_SECURE + * 1 1 SMC_FROM_REALM + */ + +#define SMC_FROM_SECURE (U(0) << 0) +#define SMC_FROM_NON_SECURE (U(1) << 0) +#define SMC_FROM_REALM U(0x21) +#define SMC_FROM_MASK U(0x21) + +#ifndef __ASSEMBLER__ + +#include + +#include + +#if ENABLE_RME +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_NON_SECURE) +#define is_caller_secure(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_SECURE) +#define is_caller_realm(_f) (((_f) & SMC_FROM_MASK) \ + == SMC_FROM_REALM) +#define caller_sec_state(_f) ((_f) & SMC_FROM_MASK) +#else /* ENABLE_RME */ +#define is_caller_non_secure(_f) (((_f) & SMC_FROM_NON_SECURE) != U(0)) +#define is_caller_secure(_f) (!is_caller_non_secure(_f)) +#endif /* ENABLE_RME */ + +/* The macro below is used to identify a Standard Service SMC call */ +#define is_std_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_STD_START) + +/* The macro below is used to identify a Arm Architectural Service SMC call */ +#define is_arm_arch_svc_call(_fid) (GET_SMC_OEN(_fid) == OEN_ARM_START) + +/* The macro below is used to identify a valid Fast SMC call */ +#define is_valid_fast_smc(_fid) ((!(((_fid) >> 16) & U(0xff))) && \ + (GET_SMC_TYPE(_fid) \ + == (uint32_t)SMC_TYPE_FAST)) + +/* + * Macro to define UUID for services. Apart from defining and initializing a + * uuid_t structure, this macro verifies that the first word of the defined UUID + * does not equal SMC_UNK. This is to ensure that the caller won't mistake the + * returned UUID in x0 for an invalid SMC error return + */ +#define DEFINE_SVC_UUID2(_name, _tl, _tm, _th, _cl, _ch, \ + _n0, _n1, _n2, _n3, _n4, _n5) \ + CASSERT((uint32_t)(_tl) != (uint32_t)SMC_UNK, \ + invalid_svc_uuid_##_name); \ + static const uuid_t _name = { \ + {((_tl) >> 24) & 0xFF, \ + ((_tl) >> 16) & 0xFF, \ + ((_tl) >> 8) & 0xFF, \ + ((_tl) & 0xFF)}, \ + {((_tm) >> 8) & 0xFF, \ + ((_tm) & 0xFF)}, \ + {((_th) >> 8) & 0xFF, \ + ((_th) & 0xFF)}, \ + (_cl), (_ch), \ + { (_n0), (_n1), (_n2), (_n3), (_n4), (_n5) } \ + } + +/* + * Return a UUID in the SMC return registers. + * + * Acccording to section 5.3 of the SMCCC, UUIDs are returned as a single + * 128-bit value using the SMC32 calling convention. This value is mapped to + * argument registers x0-x3 on AArch64 (resp. r0-r3 on AArch32). x0 for example + * shall hold bytes 0 to 3, with byte 0 in the low-order bits. + */ +static inline uint32_t smc_uuid_word(uint8_t b0, uint8_t b1, uint8_t b2, uint8_t b3) +{ + return ((uint32_t) b0) | (((uint32_t) b1) << 8) | + (((uint32_t) b2) << 16) | (((uint32_t) b3) << 24); +} + +#define SMC_UUID_RET(_h, _uuid) \ + SMC_RET4(handle, \ + smc_uuid_word((_uuid).time_low[0], (_uuid).time_low[1], \ + (_uuid).time_low[2], (_uuid).time_low[3]), \ + smc_uuid_word((_uuid).time_mid[0], (_uuid).time_mid[1], \ + (_uuid).time_hi_and_version[0], \ + (_uuid).time_hi_and_version[1]), \ + smc_uuid_word((_uuid).clock_seq_hi_and_reserved, \ + (_uuid).clock_seq_low, (_uuid).node[0], \ + (_uuid).node[1]), \ + smc_uuid_word((_uuid).node[2], (_uuid).node[3], \ + (_uuid).node[4], (_uuid).node[5])) + +#endif /*__ASSEMBLER__*/ +#endif /* SMCCC_H */ diff --git a/arm-trusted-firmware/include/lib/spinlock.h b/arm-trusted-firmware/include/lib/spinlock.h new file mode 100644 index 0000000..0bf3ee0 --- /dev/null +++ b/arm-trusted-firmware/include/lib/spinlock.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPINLOCK_H +#define SPINLOCK_H + +#ifndef __ASSEMBLER__ + +#include + +typedef struct spinlock { + volatile uint32_t lock; +} spinlock_t; + +void spin_lock(spinlock_t *lock); +void spin_unlock(spinlock_t *lock); + +#else + +/* Spin lock definitions for use in assembly */ +#define SPINLOCK_ASM_ALIGN 2 +#define SPINLOCK_ASM_SIZE 4 + +#endif + +#endif /* SPINLOCK_H */ diff --git a/arm-trusted-firmware/include/lib/utils.h b/arm-trusted-firmware/include/lib/utils.h new file mode 100644 index 0000000..17ee936 --- /dev/null +++ b/arm-trusted-firmware/include/lib/utils.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UTILS_H +#define UTILS_H + +/* + * C code should be put in this part of the header to avoid breaking ASM files + * or linker scripts including it. + */ +#if !(defined(__LINKER__) || defined(__ASSEMBLER__)) + +#include +#include + +typedef struct mem_region { + uintptr_t base; + size_t nbytes; +} mem_region_t; + +/* + * zero_normalmem all the regions defined in tbl. + */ +void clear_mem_regions(mem_region_t *tbl, size_t nregions); + +/* + * zero_normalmem all the regions defined in region. It dynamically + * maps chunks of 'chunk_size' in 'va' virtual address and clears them. + * For this reason memory regions must be multiple of chunk_size and + * must be aligned to it as well. chunk_size and va can be selected + * in a way that they minimize the number of entries used in the + * translation tables. + */ +void clear_map_dyn_mem_regions(struct mem_region *regions, + size_t nregions, + uintptr_t va, + size_t chunk); + +/* + * checks that a region (addr + nbytes-1) of memory is totally covered by + * one of the regions defined in tbl. Caller must ensure that (addr+nbytes-1) + * doesn't overflow. + */ +int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, + uintptr_t addr, size_t nbytes); + +/* + * Fill a region of normal memory of size "length" in bytes with zero bytes. + * + * WARNING: This function can only operate on normal memory. This means that + * the MMU must be enabled when using this function. Otherwise, use + * zeromem. + */ +void zero_normalmem(void *mem, u_register_t length); + +/* + * Fill a region of memory of size "length" in bytes with null bytes. + * + * Unlike zero_normalmem, this function has no restriction on the type of + * memory targeted and can be used for any device memory as well as normal + * memory. This function must be used instead of zero_normalmem when MMU is + * disabled. + * + * NOTE: When data cache and MMU are enabled, prefer zero_normalmem for faster + * zeroing. + */ +void zeromem(void *mem, u_register_t length); + +/* + * Utility function to return the address of a symbol. By default, the + * compiler generates adr/adrp instruction pair to return the reference + * to the symbol and this utility is used to override this compiler + * generated to code to use `ldr` instruction. + * + * This helps when Position Independent Executable needs to reference a symbol + * which is constant and does not depend on the execute address of the binary. + */ +#define DEFINE_LOAD_SYM_ADDR(_name) \ +static inline u_register_t load_addr_## _name(void) \ +{ \ + u_register_t v; \ + __asm__ volatile ("ldr %0, =" #_name : "=r" (v) : "X" (#_name));\ + return v; \ +} + +/* Helper to invoke the function defined by DEFINE_LOAD_SYM_ADDR() */ +#define LOAD_ADDR_OF(_name) (typeof(_name) *) load_addr_## _name() + +#endif /* !(defined(__LINKER__) || defined(__ASSEMBLER__)) */ + +#endif /* UTILS_H */ diff --git a/arm-trusted-firmware/include/lib/utils_def.h b/arm-trusted-firmware/include/lib/utils_def.h new file mode 100644 index 0000000..7a7012d --- /dev/null +++ b/arm-trusted-firmware/include/lib/utils_def.h @@ -0,0 +1,171 @@ +/* + * 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 + */ + +#ifndef UTILS_DEF_H +#define UTILS_DEF_H + +#include + +/* Compute the number of elements in the given array */ +#define ARRAY_SIZE(a) \ + (sizeof(a) / sizeof((a)[0])) + +#define IS_POWER_OF_TWO(x) \ + (((x) & ((x) - 1)) == 0) + +#define SIZE_FROM_LOG2_WORDS(n) (U(4) << (n)) + +#define BIT_32(nr) (U(1) << (nr)) +#define BIT_64(nr) (ULL(1) << (nr)) + +#ifdef __aarch64__ +#define BIT BIT_64 +#else +#define BIT BIT_32 +#endif + +/* + * Create a contiguous bitmask starting at bit position @l and ending at + * position @h. For example + * GENMASK_64(39, 21) gives us the 64bit vector 0x000000ffffe00000. + */ +#if defined(__LINKER__) || defined(__ASSEMBLER__) +#define GENMASK_32(h, l) \ + (((0xFFFFFFFF) << (l)) & (0xFFFFFFFF >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + ((~0 << (l)) & (~0 >> (64 - 1 - (h)))) +#else +#define GENMASK_32(h, l) \ + (((~UINT32_C(0)) << (l)) & (~UINT32_C(0) >> (32 - 1 - (h)))) + +#define GENMASK_64(h, l) \ + (((~UINT64_C(0)) << (l)) & (~UINT64_C(0) >> (64 - 1 - (h)))) +#endif + +#ifdef __aarch64__ +#define GENMASK GENMASK_64 +#else +#define GENMASK GENMASK_32 +#endif + +/* + * This variant of div_round_up can be used in macro definition but should not + * be used in C code as the `div` parameter is evaluated twice. + */ +#define DIV_ROUND_UP_2EVAL(n, d) (((n) + (d) - 1) / (d)) + +#define div_round_up(val, div) __extension__ ({ \ + __typeof__(div) _div = (div); \ + ((val) + _div - (__typeof__(div)) 1) / _div; \ +}) + +#define MIN(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x < _y ? _x : _y; \ +}) + +#define MAX(x, y) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(y) _y = (y); \ + (void)(&_x == &_y); \ + _x > _y ? _x : _y; \ +}) + +#define CLAMP(x, min, max) __extension__ ({ \ + __typeof__(x) _x = (x); \ + __typeof__(min) _min = (min); \ + __typeof__(max) _max = (max); \ + (void)(&_x == &_min); \ + (void)(&_x == &_max); \ + (_x > _max ? _max : (_x < _min ? _min : _x)); \ +}) + +/* + * The round_up() macro rounds up a value to the given boundary in a + * type-agnostic yet type-safe manner. The boundary must be a power of two. + * In other words, it computes the smallest multiple of boundary which is + * greater than or equal to value. + * + * round_down() is similar but rounds the value down instead. + */ +#define round_boundary(value, boundary) \ + ((__typeof__(value))((boundary) - 1)) + +#define round_up(value, boundary) \ + ((((value) - 1) | round_boundary(value, boundary)) + 1) + +#define round_down(value, boundary) \ + ((value) & ~round_boundary(value, boundary)) + +/* + * Evaluates to 1 if (ptr + inc) overflows, 0 otherwise. + * Both arguments must be unsigned pointer values (i.e. uintptr_t). + */ +#define check_uptr_overflow(_ptr, _inc) \ + ((_ptr) > (UINTPTR_MAX - (_inc))) + +/* + * Evaluates to 1 if (u32 + inc) overflows, 0 otherwise. + * Both arguments must be 32-bit unsigned integers (i.e. effectively uint32_t). + */ +#define check_u32_overflow(_u32, _inc) \ + ((_u32) > (UINT32_MAX - (_inc))) + +/* Register size of the current architecture. */ +#ifdef __aarch64__ +#define REGSZ U(8) +#else +#define REGSZ U(4) +#endif + +/* + * Test for the current architecture version to be at least the version + * expected. + */ +#define ARM_ARCH_AT_LEAST(_maj, _min) \ + ((ARM_ARCH_MAJOR > (_maj)) || \ + ((ARM_ARCH_MAJOR == (_maj)) && (ARM_ARCH_MINOR >= (_min)))) + +/* + * Import an assembly or linker symbol as a C expression with the specified + * type + */ +#define IMPORT_SYM(type, sym, name) \ + extern char sym[];\ + static const __attribute__((unused)) type name = (type) sym; + +/* + * When the symbol is used to hold a pointer, its alignment can be asserted + * with this macro. For example, if there is a linker symbol that is going to + * be used as a 64-bit pointer, the value of the linker symbol must also be + * aligned to 64 bit. This macro makes sure this is the case. + */ +#define ASSERT_SYM_PTR_ALIGN(sym) assert(((size_t)(sym) % __alignof__(*(sym))) == 0) + +#define COMPILER_BARRIER() __asm__ volatile ("" ::: "memory") + +/* Compiler builtin of GCC >= 9 and planned in llvm */ +#ifdef __HAVE_SPECULATION_SAFE_VALUE +# define SPECULATION_SAFE_VALUE(var) __builtin_speculation_safe_value(var) +#else +# define SPECULATION_SAFE_VALUE(var) var +#endif + +/* + * Ticks elapsed in one second with a signal of 1 MHz + */ +#define MHZ_TICKS_PER_SEC U(1000000) + +/* + * Ticks elapsed in one second with a signal of 1 KHz + */ +#define KHZ_TICKS_PER_SEC U(1000) + +#endif /* UTILS_DEF_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h b/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h new file mode 100644 index 0000000..252b92c --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MPU_H +#define XLAT_MPU_H + +#ifndef __ASSEMBLER__ + +#include + +#define XLAT_TABLES_LIB_V2 1 + +void enable_mpu_el2(unsigned int flags); +void enable_mpu_direct_el2(unsigned int flags); + +/* + * Function to wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns addressed, + * but it nevertheless also explicitly turns off the MPU. + */ +void clear_all_mpu_regions(void); + +#endif /* __ASSEMBLER__ */ +#endif /* XLAT_MPU_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h b/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h new file mode 100644 index 0000000..30eb5e9 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH32_H +#define XLAT_TABLES_AARCH32_H + +#include +#include +#include + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * In AArch32 state, the MMU only supports 4KB page granularity, which means + * that the first translation table level is either 1 or 2. Both of them are + * allowed to have block and table descriptors. See section G4.5.6 of the + * ARMv8-A Architecture Reference Manual (DDI 0487A.k) for more information. + * + * The define below specifies the first table level that allows block + * descriptors. + */ +#if PAGE_SIZE != PAGE_SIZE_4KB +#error "Invalid granule size. AArch32 supports 4KB pages only." +#endif + +#define MIN_LVL_BLOCK_DESC U(1) + +#define XLAT_TABLE_LEVEL_MIN U(1) + +/* + * Define the architectural limits of the virtual address space in AArch32 + * state. + * + * TTBCR.TxSZ is calculated as 32 minus the width of said address space. The + * value of TTBCR.TxSZ must be in the range 0 to 7 [1], which means that the + * virtual address space width must be in the range 32 to 25 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_TxSZ_MAX)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(32) - TTBCR_TxSZ_MIN)) + +/* + * Here we calculate the initial lookup level from the value of the given + * virtual address space size. For a 4 KB page size, + * - level 1 supports virtual address spaces of widths 32 to 31 bits; + * - level 2 from 30 to 25. + * + * Wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as the initial lookup level with 4 KB granularity. + * See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information, Section G4.6.5 + * + * For example, for a 31-bit address space (i.e. virt_addr_space_size == + * 1 << 31), TTBCR.TxSZ will be programmed to (32 - 31) = 1. According to Table + * G4-5 in the ARM ARM, the initial lookup level for an address space like that + * is 1. + * + * Note that this macro assumes that the given virtual address space size is + * valid. + */ +#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ + (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) ? \ + U(1) : U(2)) + +#endif /* XLAT_TABLES_AARCH32_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h b/arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h new file mode 100644 index 0000000..3014c8f --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_AARCH64_H +#define XLAT_TABLES_AARCH64_H + +#include +#include +#include + +#if !defined(PAGE_SIZE) +#error "PAGE_SIZE is not defined." +#endif + +/* + * Encode a Physical Address Space size for its use in TCR_ELx. + */ +unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr); + +/* + * In AArch64 state, the MMU may support 4 KB, 16 KB and 64 KB page + * granularity. For 4KB granularity, a level 0 table descriptor doesn't support + * block translation. For 16KB, the same thing happens to levels 0 and 1. For + * 64KB, same for level 1. See section D4.3.1 of the ARMv8-A Architecture + * Reference Manual (DDI 0487A.k) for more information. + * + * The define below specifies the first table level that allows block + * descriptors. + */ +#if PAGE_SIZE == PAGE_SIZE_4KB +# define MIN_LVL_BLOCK_DESC U(1) +#elif (PAGE_SIZE == PAGE_SIZE_16KB) || (PAGE_SIZE == PAGE_SIZE_64KB) +# define MIN_LVL_BLOCK_DESC U(2) +#endif + +#define XLAT_TABLE_LEVEL_MIN U(0) + +/* + * Define the architectural limits of the virtual address space in AArch64 + * state. + * + * TCR.TxSZ is calculated as 64 minus the width of said address space. + * The value of TCR.TxSZ must be in the range 16 to 39 [1] or 48 [2], + * depending on Small Translation Table Support which means that + * the virtual address space width must be in the range 48 to 25 or 16 bits. + * + * [1] See the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information: + * Page 1730: 'Input address size', 'For all translation stages'. + * [2] See section 12.2.55 in the ARMv8-A Architecture Reference Manual + * (DDI 0487D.a) + */ +/* Maximum value of TCR_ELx.T(0,1)SZ is 39 */ +#define MIN_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MAX)) + +/* Maximum value of TCR_ELx.T(0,1)SZ is 48 */ +#define MIN_VIRT_ADDR_SPACE_SIZE_TTST \ + (ULL(1) << (U(64) - TCR_TxSZ_MAX_TTST)) +#define MAX_VIRT_ADDR_SPACE_SIZE (ULL(1) << (U(64) - TCR_TxSZ_MIN)) + +/* + * Here we calculate the initial lookup level from the value of the given + * virtual address space size. For a 4 KB page size, + * - level 0 supports virtual address spaces of widths 48 to 40 bits; + * - level 1 from 39 to 31; + * - level 2 from 30 to 22. + * - level 3 from 21 to 16. + * + * Small Translation Table (Armv8.4-TTST) support allows the starting level + * of the translation table from 3 for 4KB granularity. See section 12.2.55 in + * the ARMv8-A Architecture Reference Manual (DDI 0487D.a). In Armv8.3 and below + * wider or narrower address spaces are not supported. As a result, level 3 + * cannot be used as initial lookup level with 4 KB granularity. See section + * D4.2.5 in the ARMv8-A Architecture Reference Manual (DDI 0487A.j) for more + * information. + * + * For example, for a 35-bit address space (i.e. virt_addr_space_size == + * 1 << 35), TCR.TxSZ will be programmed to (64 - 35) = 29. According to Table + * D4-11 in the ARM ARM, the initial lookup level for an address space like that + * is 1. + * + * Note that this macro assumes that the given virtual address space size is + * valid. + */ +#define GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_sz) \ + (((_virt_addr_space_sz) > (ULL(1) << L0_XLAT_ADDRESS_SHIFT)) \ + ? 0U \ + : (((_virt_addr_space_sz) > (ULL(1) << L1_XLAT_ADDRESS_SHIFT)) \ + ? 1U \ + : (((_virt_addr_space_sz) > (ULL(1) << L2_XLAT_ADDRESS_SHIFT)) \ + ? 2U : 3U))) + +#endif /* XLAT_TABLES_AARCH64_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h new file mode 100644 index 0000000..269afd2 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MMU_HELPERS_H +#define XLAT_MMU_HELPERS_H + +/* + * The following flags are passed to enable_mmu_xxx() to override the default + * values used to program system registers while enabling the MMU. + */ + +/* + * When this flag is used, all data access to Normal memory from this EL and all + * Normal memory accesses to the translation tables of this EL are non-cacheable + * for all levels of data and unified cache until the caches are enabled by + * setting the bit SCTLR_ELx.C. + */ +#define DISABLE_DCACHE (U(1) << 0) + +/* + * Mark the translation tables as non-cacheable for the MMU table walker, which + * is a different observer from the PE/CPU. If the flag is not specified, the + * tables are cacheable for the MMU table walker. + * + * Note that, as far as the PE/CPU observer is concerned, the attributes used + * are the ones specified in the translation tables themselves. The MAIR + * register specifies the cacheability through the field AttrIndx of the lower + * attributes of the translation tables. The shareability is specified in the SH + * field of the lower attributes. + * + * The MMU table walker uses the attributes specified in the fields ORGNn, IRGNn + * and SHn of the TCR register to access the translation tables. + * + * The attributes specified in the TCR register and the tables can be different + * as there are no checks to prevent that. Special care must be taken to ensure + * that there aren't mismatches. The behaviour in that case is described in the + * sections 'Mismatched memory attributes' in the ARMv8 ARM. + */ +#define XLAT_TABLE_NC (U(1) << 1) + +/* + * Offsets into a mmu_cfg_params array generated by setup_mmu_cfg(). All + * parameters are 64 bits wide. + */ +#define MMU_CFG_MAIR 0 +#define MMU_CFG_TCR 1 +#define MMU_CFG_TTBR0 2 +#define MMU_CFG_PARAM_MAX 3 + +#ifndef __ASSEMBLER__ + +#include +#include +#include + +#include + +/* + * Return the values that the MMU configuration registers must contain for the + * specified translation context. `params` must be a pointer to array of size + * MMU_CFG_PARAM_MAX. + */ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime); + +#ifdef __aarch64__ +/* AArch64 specific translation table APIs */ +void enable_mmu_el1(unsigned int flags); +void enable_mmu_el2(unsigned int flags); +void enable_mmu_el3(unsigned int flags); +void enable_mmu(unsigned int flags); + +void enable_mmu_direct_el1(unsigned int flags); +void enable_mmu_direct_el2(unsigned int flags); +void enable_mmu_direct_el3(unsigned int flags); +#else +/* AArch32 specific translation table API */ +void enable_mmu_svc_mon(unsigned int flags); +void enable_mmu_hyp(unsigned int flags); + +void enable_mmu_direct_svc_mon(unsigned int flags); +void enable_mmu_direct_hyp(unsigned int flags); +#endif /* __aarch64__ */ + +bool xlat_arch_is_granule_size_supported(size_t size); +size_t xlat_arch_get_max_supported_granule_size(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* XLAT_MMU_HELPERS_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h new file mode 100644 index 0000000..a156969 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_H +#define XLAT_TABLES_H + +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include + +/* Helper macro to define entries for mmap_region_t. It creates + * identity mappings for each region. + */ +#define MAP_REGION_FLAT(adr, sz, attr) MAP_REGION(adr, adr, sz, attr) + +/* Helper macro to define entries for mmap_region_t. It allows to + * re-map address mappings from 'pa' to 'va' for each region. + */ +#define MAP_REGION(pa, va, sz, attr) {(pa), (va), (sz), (attr)} + +/* + * Shifts and masks to access fields of an mmap attribute + */ +#define MT_TYPE_MASK U(0x7) +#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) +/* Access permissions (RO/RW) */ +#define MT_PERM_SHIFT U(3) +/* Security state (SECURE/NS) */ +#define MT_SEC_SHIFT U(4) +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(5) + +/* + * Memory mapping attributes + */ + +/* + * Memory types supported. + * These are organised so that, going down the list, the memory types are + * getting weaker; conversely going up the list the memory types are getting + * stronger. + */ +#define MT_DEVICE U(0) +#define MT_NON_CACHEABLE U(1) +#define MT_MEMORY U(2) +/* Values up to 7 are reserved to add new memory types in the future */ + +#define MT_RO (U(0) << MT_PERM_SHIFT) +#define MT_RW (U(1) << MT_PERM_SHIFT) + +#define MT_SECURE (U(0) << MT_SEC_SHIFT) +#define MT_NS (U(1) << MT_SEC_SHIFT) + +/* + * Access permissions for instruction execution are only relevant for normal + * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially + * overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ +#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) +#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) + +/* Compound attributes for most common usages */ +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) + +/* Memory type for EL3 regions */ +#if ENABLE_RME +#error FEAT_RME requires version 2 of the Translation Tables Library +#else +#define EL3_PAS MT_SECURE +#endif + +/* + * Structure for specifying a single region of memory. + */ +typedef struct mmap_region { + unsigned long long base_pa; + uintptr_t base_va; + size_t size; + unsigned int attr; +} mmap_region_t; + +/* Generic translation table APIs */ +void init_xlat_tables(void); +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +void mmap_add(const mmap_region_t *mm); + +#endif /*__ASSEMBLER__*/ +#endif /* XLAT_TABLES_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h new file mode 100644 index 0000000..0ce0cac --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_ARCH_H +#define XLAT_TABLES_ARCH_H + +#ifdef __aarch64__ +#include "aarch64/xlat_tables_aarch64.h" +#else +#include "aarch32/xlat_tables_aarch32.h" +#endif + +/* + * Evaluates to 1 if the given physical address space size is a power of 2, + * or 0 if it's not. + */ +#define CHECK_PHY_ADDR_SPACE_SIZE(size) \ + (IS_POWER_OF_TWO(size)) + +/* + * Compute the number of entries required at the initial lookup level to address + * the whole virtual address space. + */ +#define GET_NUM_BASE_LEVEL_ENTRIES(addr_space_size) \ + ((addr_space_size) >> \ + XLAT_ADDR_SHIFT(GET_XLAT_TABLE_LEVEL_BASE(addr_space_size))) + +#endif /* XLAT_TABLES_ARCH_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h new file mode 100644 index 0000000..90768db --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h @@ -0,0 +1,11 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if XLAT_TABLES_LIB_V2 +#include +#else +#include +#endif diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h new file mode 100644 index 0000000..2d0949b --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h @@ -0,0 +1,183 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_DEFS_H +#define XLAT_TABLES_DEFS_H + +#include +#include +#include + +/* Miscellaneous MMU related constants */ +#define NUM_2MB_IN_GB (U(1) << 9) +#define NUM_4K_IN_2MB (U(1) << 9) +#define NUM_GB_IN_4GB (U(1) << 2) + +#define TWO_MB_SHIFT U(21) +#define ONE_GB_SHIFT U(30) +#define FOUR_KB_SHIFT U(12) + +#define ONE_GB_INDEX(x) ((x) >> ONE_GB_SHIFT) +#define TWO_MB_INDEX(x) ((x) >> TWO_MB_SHIFT) +#define FOUR_KB_INDEX(x) ((x) >> FOUR_KB_SHIFT) + +#define PAGE_SIZE_4KB U(4096) +#define PAGE_SIZE_16KB U(16384) +#define PAGE_SIZE_64KB U(65536) + +#define INVALID_DESC U(0x0) +/* + * A block descriptor points to a region of memory bigger than the granule size + * (e.g. a 2MB region when the granule size is 4KB). + */ +#define BLOCK_DESC U(0x1) /* Table levels 0-2 */ +/* A table descriptor points to the next level of translation table. */ +#define TABLE_DESC U(0x3) /* Table levels 0-2 */ +/* + * A page descriptor points to a page, i.e. a memory region whose size is the + * translation granule size (e.g. 4KB). + */ +#define PAGE_DESC U(0x3) /* Table level 3 */ + +#define DESC_MASK U(0x3) + +#define FIRST_LEVEL_DESC_N ONE_GB_SHIFT +#define SECOND_LEVEL_DESC_N TWO_MB_SHIFT +#define THIRD_LEVEL_DESC_N FOUR_KB_SHIFT + +/* XN: Translation regimes that support one VA range (EL2 and EL3). */ +#define XN (ULL(1) << 2) +/* UXN, PXN: Translation regimes that support two VA ranges (EL1&0). */ +#define UXN (ULL(1) << 2) +#define PXN (ULL(1) << 1) +#define CONT_HINT (ULL(1) << 0) +#define UPPER_ATTRS(x) (((x) & ULL(0x7)) << 52) + +#define NON_GLOBAL (U(1) << 9) +#define ACCESS_FLAG (U(1) << 8) +#define NSH (U(0x0) << 6) +#define OSH (U(0x2) << 6) +#define ISH (U(0x3) << 6) + +#ifdef __aarch64__ +/* Guarded Page bit */ +#define GP (ULL(1) << 50) +#endif + +#define TABLE_ADDR_MASK ULL(0x0000FFFFFFFFF000) + +/* + * The ARMv8-A architecture allows translation granule sizes of 4KB, 16KB or + * 64KB. However, only 4KB are supported at the moment. + */ +#define PAGE_SIZE_SHIFT FOUR_KB_SHIFT +#define PAGE_SIZE (UL(1) << PAGE_SIZE_SHIFT) +#define PAGE_SIZE_MASK (PAGE_SIZE - UL(1)) +#define IS_PAGE_ALIGNED(addr) (((addr) & PAGE_SIZE_MASK) == U(0)) + +#if (ARM_ARCH_MAJOR == 7) && !ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#define XLAT_ENTRY_SIZE_SHIFT U(2) /* Each MMU table entry is 4 bytes */ +#else +#define XLAT_ENTRY_SIZE_SHIFT U(3) /* Each MMU table entry is 8 bytes */ +#endif +#define XLAT_ENTRY_SIZE (U(1) << XLAT_ENTRY_SIZE_SHIFT) + +#define XLAT_TABLE_SIZE_SHIFT PAGE_SIZE_SHIFT /* Size of one complete table */ +#define XLAT_TABLE_SIZE (U(1) << XLAT_TABLE_SIZE_SHIFT) + +#define XLAT_TABLE_LEVEL_MAX U(3) + +/* Values for number of entries in each MMU translation table */ +#define XLAT_TABLE_ENTRIES_SHIFT (XLAT_TABLE_SIZE_SHIFT - XLAT_ENTRY_SIZE_SHIFT) +#define XLAT_TABLE_ENTRIES (U(1) << XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_TABLE_ENTRIES_MASK (XLAT_TABLE_ENTRIES - U(1)) + +/* Values to convert a memory address to an index into a translation table */ +#define L3_XLAT_ADDRESS_SHIFT PAGE_SIZE_SHIFT +#define L2_XLAT_ADDRESS_SHIFT (L3_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L1_XLAT_ADDRESS_SHIFT (L2_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define L0_XLAT_ADDRESS_SHIFT (L1_XLAT_ADDRESS_SHIFT + XLAT_TABLE_ENTRIES_SHIFT) +#define XLAT_ADDR_SHIFT(level) (PAGE_SIZE_SHIFT + \ + ((XLAT_TABLE_LEVEL_MAX - (level)) * XLAT_TABLE_ENTRIES_SHIFT)) + +#define XLAT_BLOCK_SIZE(level) (UL(1) << XLAT_ADDR_SHIFT(level)) +/* Mask to get the bits used to index inside a block of a certain level */ +#define XLAT_BLOCK_MASK(level) (XLAT_BLOCK_SIZE(level) - UL(1)) +/* Mask to get the address bits common to a block of a certain table level*/ +#define XLAT_ADDR_MASK(level) (~XLAT_BLOCK_MASK(level)) +/* + * Extract from the given virtual address the index into the given lookup level. + * This macro assumes the system is using the 4KB translation granule. + */ +#define XLAT_TABLE_IDX(virtual_addr, level) \ + (((virtual_addr) >> XLAT_ADDR_SHIFT(level)) & ULL(0x1FF)) + +/* + * The ARMv8 translation table descriptor format defines AP[2:1] as the Access + * Permissions bits, and does not define an AP[0] bit. + * + * AP[1] is valid only for a stage 1 translation that supports two VA ranges + * (i.e. in the ARMv8A.0 architecture, that is the S-EL1&0 regime). It is RES1 + * when stage 1 translations can only support one VA range. + */ +#define AP2_SHIFT U(0x7) +#define AP2_RO ULL(0x1) +#define AP2_RW ULL(0x0) + +#define AP1_SHIFT U(0x6) +#define AP1_ACCESS_UNPRIVILEGED ULL(0x1) +#define AP1_NO_ACCESS_UNPRIVILEGED ULL(0x0) +#define AP1_RES1 ULL(0x1) + +/* + * The following definitions must all be passed to the LOWER_ATTRS() macro to + * get the right bitmask. + */ +#define AP_RO (AP2_RO << 5) +#define AP_RW (AP2_RW << 5) +#define AP_ACCESS_UNPRIVILEGED (AP1_ACCESS_UNPRIVILEGED << 4) +#define AP_NO_ACCESS_UNPRIVILEGED (AP1_NO_ACCESS_UNPRIVILEGED << 4) +#define AP_ONE_VA_RANGE_RES1 (AP1_RES1 << 4) +#define NS (U(0x1) << 3) +#define EL3_S1_NSE (U(0x1) << 9) +#define ATTR_NON_CACHEABLE_INDEX ULL(0x2) +#define ATTR_DEVICE_INDEX ULL(0x1) +#define ATTR_IWBWA_OWBWA_NTR_INDEX ULL(0x0) +#define LOWER_ATTRS(x) (((x) & U(0xfff)) << 2) + +/* Normal Memory, Outer Write-Through non-transient, Inner Non-cacheable */ +#define ATTR_NON_CACHEABLE MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_NC, MAIR_NORM_NC) +/* Device-nGnRE */ +#define ATTR_DEVICE MAIR_DEV_nGnRE +/* Normal Memory, Outer Write-Back non-transient, Inner Write-Back non-transient */ +#define ATTR_IWBWA_OWBWA_NTR MAKE_MAIR_NORMAL_MEMORY(MAIR_NORM_WB_NTR_RWA, MAIR_NORM_WB_NTR_RWA) +#define MAIR_ATTR_SET(attr, index) ((attr) << ((index) << 3)) +#define ATTR_INDEX_MASK U(0x3) +#define ATTR_INDEX_GET(attr) (((attr) >> 2) & ATTR_INDEX_MASK) + +/* + * Shift values for the attributes fields in a block or page descriptor. + * See section D4.3.3 in the ARMv8-A ARM (issue B.a). + */ + +/* Memory attributes index field, AttrIndx[2:0]. */ +#define ATTR_INDEX_SHIFT 2 +/* Non-secure bit, NS. */ +#define NS_SHIFT 5 +/* Shareability field, SH[1:0] */ +#define SHAREABILITY_SHIFT 8 +/* The Access Flag, AF. */ +#define ACCESS_FLAG_SHIFT 10 +/* The not global bit, nG. */ +#define NOT_GLOBAL_SHIFT 11 +/* Contiguous hint bit. */ +#define CONT_HINT_SHIFT 52 +/* Execute-never bits, XN. */ +#define PXN_SHIFT 53 +#define XN_SHIFT 54 +#define UXN_SHIFT XN_SHIFT + +#endif /* XLAT_TABLES_DEFS_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h new file mode 100644 index 0000000..69ad027 --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h @@ -0,0 +1,416 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_V2_H +#define XLAT_TABLES_V2_H + +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include + +/* + * Default granularity size for an mmap_region_t. + * Useful when no specific granularity is required. + * + * By default, choose the biggest possible block size allowed by the + * architectural state and granule size in order to minimize the number of page + * tables required for the mapping. + */ +#define REGION_DEFAULT_GRANULARITY XLAT_BLOCK_SIZE(MIN_LVL_BLOCK_DESC) + +/* Helper macro to define an mmap_region_t. */ +#define MAP_REGION(_pa, _va, _sz, _attr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, REGION_DEFAULT_GRANULARITY) + +/* Helper macro to define an mmap_region_t with an identity mapping. */ +#define MAP_REGION_FLAT(_adr, _sz, _attr) \ + MAP_REGION(_adr, _adr, _sz, _attr) + +/* + * Helper macro to define entries for mmap_region_t. It allows to define 'pa' + * and sets 'va' to 0 for each region. To be used with mmap_add_alloc_va(). + */ +#define MAP_REGION_ALLOC_VA(pa, sz, attr) MAP_REGION(pa, 0, sz, attr) + +/* + * Helper macro to define an mmap_region_t to map with the desired granularity + * of translation tables. + * + * The granularity value passed to this macro must be a valid block or page + * size. When using a 4KB translation granule, this might be 4KB, 2MB or 1GB. + * Passing REGION_DEFAULT_GRANULARITY is also allowed and means that the library + * is free to choose the granularity for this region. In this case, it is + * equivalent to the MAP_REGION() macro. + */ +#define MAP_REGION2(_pa, _va, _sz, _attr, _gr) \ + MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) + +/* + * Shifts and masks to access fields of an mmap attribute + */ +#define MT_TYPE_MASK U(0x7) +#define MT_TYPE(_attr) ((_attr) & MT_TYPE_MASK) +/* Access permissions (RO/RW) */ +#define MT_PERM_SHIFT U(3) + +/* Physical address space (SECURE/NS/Root/Realm) */ +#define MT_PAS_SHIFT U(4) +#define MT_PAS_MASK (U(3) << MT_PAS_SHIFT) +#define MT_PAS(_attr) ((_attr) & MT_PAS_MASK) + +/* Access permissions for instruction execution (EXECUTE/EXECUTE_NEVER) */ +#define MT_EXECUTE_SHIFT U(6) +/* In the EL1&0 translation regime, User (EL0) or Privileged (EL1). */ +#define MT_USER_SHIFT U(7) + +/* Shareability attribute for the memory region */ +#define MT_SHAREABILITY_SHIFT U(8) +#define MT_SHAREABILITY_MASK (U(3) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY(_attr) ((_attr) & MT_SHAREABILITY_MASK) + +/* All other bits are reserved */ + +/* + * Memory mapping attributes + */ + +/* + * Memory types supported. + * These are organised so that, going down the list, the memory types are + * getting weaker; conversely going up the list the memory types are getting + * stronger. + */ +#define MT_DEVICE U(0) +#define MT_NON_CACHEABLE U(1) +#define MT_MEMORY U(2) +/* Values up to 7 are reserved to add new memory types in the future */ + +#define MT_RO (U(0) << MT_PERM_SHIFT) +#define MT_RW (U(1) << MT_PERM_SHIFT) + +#define MT_SECURE (U(0) << MT_PAS_SHIFT) +#define MT_NS (U(1) << MT_PAS_SHIFT) +#define MT_ROOT (U(2) << MT_PAS_SHIFT) +#define MT_REALM (U(3) << MT_PAS_SHIFT) + +/* + * Access permissions for instruction execution are only relevant for normal + * read-only memory, i.e. MT_MEMORY | MT_RO. They are ignored (and potentially + * overridden) otherwise: + * - Device memory is always marked as execute-never. + * - Read-write normal memory is always marked as execute-never. + */ +#define MT_EXECUTE (U(0) << MT_EXECUTE_SHIFT) +#define MT_EXECUTE_NEVER (U(1) << MT_EXECUTE_SHIFT) + +/* + * When mapping a region at EL0 or EL1, this attribute will be used to determine + * if a User mapping (EL0) will be created or a Privileged mapping (EL1). + */ +#define MT_USER (U(1) << MT_USER_SHIFT) +#define MT_PRIVILEGED (U(0) << MT_USER_SHIFT) + +/* + * Shareability defines the visibility of any cache changes to + * all masters belonging to a shareable domain. + * + * MT_SHAREABILITY_ISH: For inner shareable domain + * MT_SHAREABILITY_OSH: For outer shareable domain + * MT_SHAREABILITY_NSH: For non shareable domain + */ +#define MT_SHAREABILITY_ISH (U(1) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY_OSH (U(2) << MT_SHAREABILITY_SHIFT) +#define MT_SHAREABILITY_NSH (U(3) << MT_SHAREABILITY_SHIFT) + +/* Compound attributes for most common usages */ +#define MT_CODE (MT_MEMORY | MT_RO | MT_EXECUTE) +#define MT_RO_DATA (MT_MEMORY | MT_RO | MT_EXECUTE_NEVER) +#define MT_RW_DATA (MT_MEMORY | MT_RW | MT_EXECUTE_NEVER) + +/* + * Structure for specifying a single region of memory. + */ +typedef struct mmap_region { + unsigned long long base_pa; + uintptr_t base_va; + size_t size; + unsigned int attr; + /* Desired granularity. See the MAP_REGION2() macro for more details. */ + size_t granularity; +} mmap_region_t; + +/* + * Translation regimes supported by this library. EL_REGIME_INVALID tells the + * library to detect it at runtime. + */ +#define EL1_EL0_REGIME 1 +#define EL2_REGIME 2 +#define EL3_REGIME 3 +#define EL_REGIME_INVALID -1 + +/* Memory type for EL3 regions. With RME, EL3 is in ROOT PAS */ +#if ENABLE_RME +#define EL3_PAS MT_ROOT +#else +#define EL3_PAS MT_SECURE +#endif /* ENABLE_RME */ + +/* + * Declare the translation context type. + * Its definition is private. + */ +typedef struct xlat_ctx xlat_ctx_t; + +/* + * Statically allocate a translation context and associated structures. Also + * initialize them. + * + * _ctx_name: + * Prefix for the translation context variable. + * E.g. If _ctx_name is 'foo', the variable will be called 'foo_xlat_ctx'. + * Useful to distinguish multiple contexts from one another. + * + * _mmap_count: + * Number of mmap_region_t to allocate. + * Would typically be MAX_MMAP_REGIONS for the translation context describing + * the BL image currently executing. + * + * _xlat_tables_count: + * Number of sub-translation tables to allocate. + * Would typically be MAX_XLAT_TABLES for the translation context describing + * the BL image currently executing. + * Note that this is only for sub-tables ; at the initial lookup level, there + * is always a single table. + * + * _virt_addr_space_size, _phy_addr_space_size: + * Size (in bytes) of the virtual (resp. physical) address space. + * Would typically be PLAT_VIRT_ADDR_SPACE_SIZE + * (resp. PLAT_PHY_ADDR_SPACE_SIZE) for the translation context describing the + * BL image currently executing. + */ +#define REGISTER_XLAT_CONTEXT(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + EL_REGIME_INVALID, \ + "xlat_table", "base_xlat_table") + +/* + * Same as REGISTER_XLAT_CONTEXT plus the additional parameters: + * + * _xlat_regime: + * Specify the translation regime managed by this xlat_ctx_t instance. The + * values are the one from the EL*_REGIME definitions. + * + * _section_name: + * Specify the name of the section where the translation tables have to be + * placed by the linker. + * + * _base_table_section_name: + * Specify the name of the section where the base translation tables have to + * be placed by the linker. + */ +#define REGISTER_XLAT_CONTEXT2(_ctx_name, _mmap_count, _xlat_tables_count, \ + _virt_addr_space_size, _phy_addr_space_size, \ + _xlat_regime, _section_name, _base_table_section_name) \ + REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, (_mmap_count), \ + (_xlat_tables_count), \ + (_virt_addr_space_size), \ + (_phy_addr_space_size), \ + (_xlat_regime), \ + (_section_name), (_base_table_section_name) \ +) + +/****************************************************************************** + * Generic translation table APIs. + * Each API comes in 2 variants: + * - one that acts on the current translation context for this BL image + * - another that acts on the given translation context instead. This variant + * is named after the 1st version, with an additional '_ctx' suffix. + *****************************************************************************/ + +/* + * Initialize translation tables from the current list of mmap regions. Calling + * this function marks the transition point after which static regions can no + * longer be added. + */ +void init_xlat_tables(void); +void init_xlat_tables_ctx(xlat_ctx_t *ctx); + +/* + * Fill all fields of a dynamic translation tables context. It must be done + * either statically with REGISTER_XLAT_CONTEXT() or at runtime with this + * function. + */ +void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, + uintptr_t va_max, struct mmap_region *mmap, + unsigned int mmap_num, uint64_t **tables, + unsigned int tables_num, uint64_t *base_table, + int xlat_regime, int *mapped_regions); + +/* + * Add a static region with defined base PA and base VA. This function can only + * be used before initializing the translation tables. The region cannot be + * removed afterwards. + */ +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA and base VA. This + * function can only be used before initializing the translation tables. The + * regions cannot be removed afterwards. + */ +void mmap_add(const mmap_region_t *mm); +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm); + +/* + * Add a region with defined base PA. Returns base VA calculated using the + * highest existing region in the mmap array even if it fails to allocate the + * region. + */ +void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, + size_t size, unsigned int attr); +void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add an array of static regions with defined base PA, and fill the base VA + * field on the array of structs. This function can only be used before + * initializing the translation tables. The regions cannot be removed afterwards. + */ +void mmap_add_alloc_va(mmap_region_t *mm); + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Add a dynamic region with defined base PA and base VA. This type of region + * can be added and removed even after the translation tables are initialized. + * + * Returns: + * 0: Success. + * EINVAL: Invalid values were used as arguments. + * ERANGE: Memory limits were surpassed. + * ENOMEM: Not enough space in the mmap array or not enough free xlat tables. + * EPERM: It overlaps another region in an invalid way. + */ +int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Add a dynamic region with defined base PA. Returns base VA calculated using + * the highest existing region in the mmap array even if it fails to allocate + * the region. + * + * mmap_add_dynamic_region_alloc_va() returns the allocated VA in 'base_va'. + * mmap_add_dynamic_region_alloc_va_ctx() returns it in 'mm->base_va'. + * + * It returns the same error values as mmap_add_dynamic_region(). + */ +int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, + uintptr_t *base_va, + size_t size, unsigned int attr); +int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm); + +/* + * Remove a region with the specified base VA and size. Only dynamic regions can + * be removed, and they can be removed even if the translation tables are + * initialized. + * + * Returns: + * 0: Success. + * EINVAL: The specified region wasn't found. + * EPERM: Trying to remove a static region. + */ +int mmap_remove_dynamic_region(uintptr_t base_va, size_t size); +int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, + uintptr_t base_va, + size_t size); + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * Change the memory attributes of the memory region starting from a given + * virtual address in a set of translation tables. + * + * This function can only be used after the translation tables have been + * initialized. + * + * The base address of the memory region must be aligned on a page boundary. + * The size of this memory region must be a multiple of a page size. + * The memory region must be already mapped by the given translation tables + * and it must be mapped at the granularity of a page. + * + * Return 0 on success, a negative value on error. + * + * In case of error, the memory attributes remain unchanged and this function + * has no effect. + * + * ctx + * Translation context to work on. + * base_va: + * Virtual address of the 1st page to change the attributes of. + * size: + * Size in bytes of the memory region. + * attr: + * New attributes of the page tables. The attributes that can be changed are + * data access (MT_RO/MT_RW), instruction access (MT_EXECUTE_NEVER/MT_EXECUTE) + * and user/privileged access (MT_USER/MT_PRIVILEGED) in the case of contexts + * that are used in the EL1&0 translation regime. Also, note that this + * function doesn't allow to remap a region as RW and executable, or to remap + * device memory as executable. + * + * NOTE: The caller of this function must be able to write to the translation + * tables, i.e. the memory where they are stored must be mapped with read-write + * access permissions. This function assumes it is the case. If this is not + * the case then this function might trigger a data abort exception. + * + * NOTE2: The caller is responsible for making sure that the targeted + * translation tables are not modified by any other code while this function is + * executing. + */ +int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + size_t size, uint32_t attr); +int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr); + +#if PLAT_RO_XLAT_TABLES +/* + * Change the memory attributes of the memory region encompassing the higher + * level translation tables to secure read-only data. + * + * Return 0 on success, a negative error code on error. + */ +int xlat_make_tables_readonly(void); +#endif + +/* + * Query the memory attributes of a memory page in a set of translation tables. + * + * Return 0 on success, a negative error code on error. + * On success, the attributes are stored into *attr. + * + * ctx + * Translation context to work on. + * base_va + * Virtual address of the page to get the attributes of. + * There are no alignment restrictions on this address. The attributes of the + * memory page it lies within are returned. + * attr + * Output parameter where to store the attributes of the targeted memory page. + */ +int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + uint32_t *attr); +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr); + +#endif /*__ASSEMBLER__*/ +#endif /* XLAT_TABLES_V2_H */ diff --git a/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h new file mode 100644 index 0000000..62f853d --- /dev/null +++ b/arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * This header file contains internal definitions that are not supposed to be + * used outside of this library code. + */ + +#ifndef XLAT_TABLES_V2_HELPERS_H +#define XLAT_TABLES_V2_HELPERS_H + +#ifndef XLAT_TABLES_V2_H +#error "Do not include this header file directly. Include xlat_tables_v2.h instead." +#endif + +#ifndef __ASSEMBLER__ + +#include +#include + +#include + +#include +#include +#include +#include + +/* Forward declaration */ +struct mmap_region; + +/* + * Helper macro to define an mmap_region_t. This macro allows to specify all + * the fields of the structure but its parameter list is not guaranteed to + * remain stable as we add members to mmap_region_t. + */ +#define MAP_REGION_FULL_SPEC(_pa, _va, _sz, _attr, _gr) \ + { \ + .base_pa = (_pa), \ + .base_va = (_va), \ + .size = (_sz), \ + .attr = (_attr), \ + .granularity = (_gr), \ + } + +/* Struct that holds all information about the translation tables. */ +struct xlat_ctx { + /* + * Max allowed Virtual and Physical Addresses. + */ + unsigned long long pa_max_address; + uintptr_t va_max_address; + + /* + * Array of all memory regions stored in order of ascending end address + * and ascending size to simplify the code that allows overlapping + * regions. The list is terminated by the first entry with size == 0. + * The max size of the list is stored in `mmap_num`. `mmap` points to an + * array of mmap_num + 1 elements, so that there is space for the final + * null entry. + */ + struct mmap_region *mmap; + int mmap_num; + + /* + * Array of finer-grain translation tables. + * For example, if the initial lookup level is 1 then this array would + * contain both level-2 and level-3 entries. + */ + uint64_t (*tables)[XLAT_TABLE_ENTRIES]; + int tables_num; +#if PLAT_RO_XLAT_TABLES + bool readonly_tables; +#endif + /* + * Keep track of how many regions are mapped in each table. The base + * table can't be unmapped so it isn't needed to keep track of it. + */ +#if PLAT_XLAT_TABLES_DYNAMIC + int *tables_mapped_regions; +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + + int next_table; + + /* + * Base translation table. It doesn't need to have the same amount of + * entries as the ones used for other levels. + */ + uint64_t *base_table; + unsigned int base_table_entries; + + /* + * Max Physical and Virtual addresses currently in use by the + * translation tables. These might get updated as we map/unmap memory + * regions but they will never go beyond pa/va_max_address. + */ + unsigned long long max_pa; + uintptr_t max_va; + + /* Level of the base translation table. */ + unsigned int base_level; + + /* Set to true when the translation tables are initialized. */ + bool initialized; + + /* + * Translation regime managed by this xlat_ctx_t. It should be one of + * the EL*_REGIME defines. + */ + int xlat_regime; +}; + +#if PLAT_XLAT_TABLES_DYNAMIC +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + static int _ctx_name##_mapped_regions[_xlat_tables_count]; + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .tables_mapped_regions = _ctx_name##_mapped_regions, +#else +#define XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + /* do nothing */ + +#define XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + /* do nothing */ +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +#if PLAT_RO_XLAT_TABLES +#define XLAT_CTX_INIT_TABLE_ATTR() \ + .readonly_tables = false, +#else +#define XLAT_CTX_INIT_TABLE_ATTR() + /* do nothing */ +#endif + +#define REGISTER_XLAT_CONTEXT_FULL_SPEC(_ctx_name, _mmap_count, \ + _xlat_tables_count, _virt_addr_space_size, \ + _phy_addr_space_size, _xlat_regime, \ + _table_section, _base_table_section) \ + CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(_phy_addr_space_size), \ + assert_invalid_physical_addr_space_sizefor_##_ctx_name);\ + \ + static mmap_region_t _ctx_name##_mmap[_mmap_count + 1]; \ + \ + static uint64_t _ctx_name##_xlat_tables[_xlat_tables_count] \ + [XLAT_TABLE_ENTRIES] \ + __aligned(XLAT_TABLE_SIZE) __section(_table_section); \ + \ + static uint64_t _ctx_name##_base_xlat_table \ + [GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)] \ + __aligned(GET_NUM_BASE_LEVEL_ENTRIES(_virt_addr_space_size)\ + * sizeof(uint64_t)) \ + __section(_base_table_section); \ + \ + XLAT_ALLOC_DYNMAP_STRUCT(_ctx_name, _xlat_tables_count) \ + \ + static xlat_ctx_t _ctx_name##_xlat_ctx = { \ + .pa_max_address = (_phy_addr_space_size) - 1ULL, \ + .va_max_address = (_virt_addr_space_size) - 1UL, \ + .mmap = _ctx_name##_mmap, \ + .mmap_num = (_mmap_count), \ + .tables = _ctx_name##_xlat_tables, \ + .tables_num = ARRAY_SIZE(_ctx_name##_xlat_tables), \ + XLAT_CTX_INIT_TABLE_ATTR() \ + XLAT_REGISTER_DYNMAP_STRUCT(_ctx_name) \ + .next_table = 0, \ + .base_table = _ctx_name##_base_xlat_table, \ + .base_table_entries = \ + ARRAY_SIZE(_ctx_name##_base_xlat_table), \ + .max_pa = 0U, \ + .max_va = 0U, \ + .base_level = GET_XLAT_TABLE_LEVEL_BASE(_virt_addr_space_size),\ + .initialized = false, \ + .xlat_regime = (_xlat_regime) \ + } + +#endif /*__ASSEMBLER__*/ + +#endif /* XLAT_TABLES_V2_HELPERS_H */ diff --git a/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h b/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h new file mode 100644 index 0000000..741ba50 --- /dev/null +++ b/arm-trusted-firmware/include/lib/zlib/tf_gunzip.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TF_GUNZIP_H +#define TF_GUNZIP_H + +#include +#include + +int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, + size_t out_len, uintptr_t work_buf, size_t work_len); + +#endif /* TF_GUNZIP_H */ diff --git a/arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h b/arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h new file mode 100644 index 0000000..1963bf0 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_CSS_DEF_H +#define BOARD_CSS_DEF_H + +#include +#include +#include +#include + +/* + * Definitions common to all ARM CSS-based development platforms + */ + +/* Platform ID address */ +#define BOARD_CSS_PLAT_ID_REG_ADDR 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_ID_REG_VERSION_MASK 0xf00 +#define BOARD_CSS_PLAT_ID_REG_VERSION_SHIFT 0x8 +#define BOARD_CSS_PLAT_TYPE_RTL 0x00 +#define BOARD_CSS_PLAT_TYPE_FPGA 0x01 +#define BOARD_CSS_PLAT_TYPE_EMULATOR 0x02 +#define BOARD_CSS_PLAT_TYPE_FVP 0x03 + +#ifndef __ASSEMBLER__ + +#include + +#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) + +#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) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ SOC_CSS_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_UART0_BASE +#define PLAT_ARM_TSP_UART_CLK_IN_HZ V2M_IOFPGA_UART0_CLK_IN_HZ + +#endif /* BOARD_CSS_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h b/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h new file mode 100644 index 0000000..cb11dac --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef V2M_DEF_H +#define V2M_DEF_H + +#include + +/* Base address of all V2M */ +#ifdef PLAT_V2M_OFFSET +#define V2M_OFFSET PLAT_V2M_OFFSET +#else +#define V2M_OFFSET UL(0) +#endif + +/* V2M motherboard system registers & offsets */ +#define V2M_SYSREGS_BASE UL(0x1c010000) +#define V2M_SYS_ID UL(0x0) +#define V2M_SYS_SWITCH UL(0x4) +#define V2M_SYS_LED UL(0x8) +#define V2M_SYS_NVFLAGS UL(0x38) +#define V2M_SYS_NVFLAGSSET UL(0x38) +#define V2M_SYS_NVFLAGSCLR UL(0x3c) +#define V2M_SYS_CFGDATA UL(0xa0) +#define V2M_SYS_CFGCTRL UL(0xa4) +#define V2M_SYS_CFGSTATUS UL(0xa8) + +#define V2M_CFGCTRL_START BIT_32(31) +#define V2M_CFGCTRL_RW BIT_32(30) +#define V2M_CFGCTRL_FUNC_SHIFT 20 +#define V2M_CFGCTRL_FUNC(fn) ((fn) << V2M_CFGCTRL_FUNC_SHIFT) +#define V2M_FUNC_CLK_GEN U(0x01) +#define V2M_FUNC_TEMP U(0x04) +#define V2M_FUNC_DB_RESET U(0x05) +#define V2M_FUNC_SCC_CFG U(0x06) +#define V2M_FUNC_SHUTDOWN U(0x08) +#define V2M_FUNC_REBOOT U(0x09) + +/* NVFLAGS in the V2M motherboard which is preserved after a watchdog reset */ + #define V2M_SYS_NVFLAGS_ADDR (V2M_SYSREGS_BASE + V2M_SYS_NVFLAGS) + +/* + * 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 0x0 +#define V2M_SYS_LED_EL_SHIFT 0x1 +#define V2M_SYS_LED_EC_SHIFT 0x3 + +#define V2M_SYS_LED_SS_MASK U(0x1) +#define V2M_SYS_LED_EL_MASK U(0x3) +#define V2M_SYS_LED_EC_MASK U(0x1f) + +/* V2M sysid register bits */ +#define V2M_SYS_ID_REV_SHIFT 28 +#define V2M_SYS_ID_HBI_SHIFT 16 +#define V2M_SYS_ID_BLD_SHIFT 12 +#define V2M_SYS_ID_ARCH_SHIFT 8 +#define V2M_SYS_ID_FPGA_SHIFT 0 + +#define V2M_SYS_ID_REV_MASK U(0xf) +#define V2M_SYS_ID_HBI_MASK U(0xfff) +#define V2M_SYS_ID_BLD_MASK U(0xf) +#define V2M_SYS_ID_ARCH_MASK U(0xf) +#define V2M_SYS_ID_FPGA_MASK U(0xff) + +#define V2M_SYS_ID_BLD_LENGTH 4 + + +/* NOR Flash */ +#define V2M_FLASH0_BASE (V2M_OFFSET + UL(0x08000000)) +#define V2M_FLASH0_SIZE UL(0x04000000) +#define V2M_FLASH_BLOCK_SIZE UL(0x00040000) /* 256 KB */ + +#define V2M_IOFPGA_BASE (V2M_OFFSET + UL(0x1c000000)) +#define V2M_IOFPGA_SIZE UL(0x03000000) + +/* PL011 UART related constants */ +#define V2M_IOFPGA_UART0_BASE (V2M_OFFSET + UL(0x1c090000)) +#define V2M_IOFPGA_UART1_BASE (V2M_OFFSET + UL(0x1c0a0000)) +#define V2M_IOFPGA_UART2_BASE (V2M_OFFSET + UL(0x1c0b0000)) +#define V2M_IOFPGA_UART3_BASE (V2M_OFFSET + UL(0x1c0c0000)) + +#define V2M_IOFPGA_UART0_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART1_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART2_CLK_IN_HZ 24000000 +#define V2M_IOFPGA_UART3_CLK_IN_HZ 24000000 + +/* SP804 timer related constants */ +#define V2M_SP804_TIMER0_BASE (V2M_OFFSET + UL(0x1C110000)) +#define V2M_SP804_TIMER1_BASE (V2M_OFFSET + UL(0x1C120000)) + +/* SP810 controller */ +#define V2M_SP810_BASE (V2M_OFFSET + UL(0x1c020000)) +#define V2M_SP810_CTRL_TIM0_SEL BIT_32(15) +#define V2M_SP810_CTRL_TIM1_SEL BIT_32(17) +#define V2M_SP810_CTRL_TIM2_SEL BIT_32(19) +#define V2M_SP810_CTRL_TIM3_SEL BIT_32(21) + +/* + * 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 V2M_MAP_IOFPGA MAP_REGION_FLAT(V2M_IOFPGA_BASE,\ + V2M_IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* Region equivalent to V2M_MAP_IOFPGA suitable for mapping at EL0 */ +#define V2M_MAP_IOFPGA_EL0 MAP_REGION_FLAT( \ + V2M_IOFPGA_BASE, \ + V2M_IOFPGA_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE | MT_USER) + + +#endif /* V2M_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h b/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h new file mode 100644 index 0000000..0b41e67 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FVP_R_BL1_H +#define FVP_R_BL1_H + +void bl1_load_bl33(void); +void bl1_transfer_bl33(void); + +#endif /* FVP_R_BL1_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S b/arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S new file mode 100644 index 0000000..d47e4e0 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_MACROS_S +#define ARM_MACROS_S + +#include +#include +#include +#include + +.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)\nOffset\t\t\tValue\n" +newline: + .asciz "\n" +spacer: + .asciz ":\t\t 0x" +prefix: + .asciz "0x" + + /* --------------------------------------------- + * The below utility macro prints out relevant GIC + * registers whenever an unhandled exception is + * taken in BL31 on ARM standard platforms. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro arm_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 + + /* Print "0x" */ + adr x4, prefix + bl asm_print_str + + /* Print offset */ + sub x4, x7, x16 + mov x5, #12 + bl asm_print_hex_bits + + 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 /* ARM_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S b/arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S new file mode 100644 index 0000000..07f7cd3 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CCI_MACROS_S +#define CCI_MACROS_S + +#include +#include + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below required platform porting macro prints + * out relevant interconnect registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro print_cci_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_ARM_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_ARM_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_ARM_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 + +#endif /* CCI_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_config.h b/arm-trusted-firmware/include/plat/arm/common/arm_config.h new file mode 100644 index 0000000..c2b28df --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_CONFIG_H +#define ARM_CONFIG_H + +#include + +#include + +/* Whether Base memory map is in use */ +#define ARM_CONFIG_BASE_MMAP BIT(1) + +/* Whether TZC should be configured */ +#define ARM_CONFIG_HAS_TZC BIT(2) + +/* FVP model has shifted affinity */ +#define ARM_CONFIG_FVP_SHIFTED_AFF BIT(3) + +/* FVP model has SMMUv3 affinity */ +#define ARM_CONFIG_FVP_HAS_SMMUV3 BIT(4) + +/* FVP model has CCI (400 or 500/550) devices */ +#define ARM_CONFIG_FVP_HAS_CCI400 BIT(5) +#define ARM_CONFIG_FVP_HAS_CCI5XX BIT(6) + +typedef struct arm_config { + unsigned long flags; +} arm_config_t; + + +/* If used, arm_config must be defined and populated in the platform port */ +extern arm_config_t arm_config; + +static inline const arm_config_t *get_arm_config(void) +{ + return &arm_config; +} + + +#endif /* ARM_CONFIG_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_def.h new file mode 100644 index 0000000..2af8c11 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_def.h @@ -0,0 +1,737 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_DEF_H +#define ARM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * Root of trust key hash lengths + */ +#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) + +#define ARM_SYSTEM_COUNT U(1) + +#define ARM_CACHE_WRITEBACK_SHIFT 6 + +/* + * 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 +#define ARM_PWR_LVL3 MPIDR_AFFLVL3 + +/* + * 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) + +/* Memory location options for TSP */ +#define ARM_TRUSTED_SRAM_ID 0 +#define ARM_TRUSTED_DRAM_ID 1 +#define ARM_DRAM_ID 2 + +#ifdef PLAT_ARM_TRUSTED_SRAM_BASE +#define ARM_TRUSTED_SRAM_BASE PLAT_ARM_TRUSTED_SRAM_BASE +#else +#define ARM_TRUSTED_SRAM_BASE UL(0x04000000) +#endif /* PLAT_ARM_TRUSTED_SRAM_BASE */ + +#define ARM_SHARED_RAM_BASE ARM_TRUSTED_SRAM_BASE +#define ARM_SHARED_RAM_SIZE UL(0x00001000) /* 4 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) + +/* + * The top 16MB (or 64MB if RME is enabled) of DRAM1 is configured as + * follows: + * - SCP TZC DRAM: If present, DRAM reserved for SCP use + * - L1 GPT DRAM: Reserved for L1 GPT if RME is enabled + * - REALM DRAM: Reserved for Realm world if RME is enabled + * - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use + * + * RME enabled(64MB) RME not enabled(16MB) + * -------------------- ------------------- + * | | | | + * | AP TZC (~28MB) | | AP TZC (~14MB) | + * -------------------- ------------------- + * | | | | + * | REALM (32MB) | | EL3 TZC (2MB) | + * -------------------- ------------------- + * | | | | + * | EL3 TZC (3MB) | | SCP TZC | + * -------------------- 0xFFFF_FFFF------------------- + * | L1 GPT + SCP TZC | + * | (~1MB) | + * 0xFFFF_FFFF -------------------- + */ +#if ENABLE_RME +#define ARM_TZC_DRAM1_SIZE UL(0x04000000) /* 64MB */ +/* + * Define a region within the TZC secured DRAM for use by EL3 runtime + * firmware. This region is meant to be NOLOAD and will not be zero + * initialized. Data sections with the attribute `arm_el3_tzc_dram` will be + * placed here. 3MB region is reserved if RME is enabled, 2MB otherwise. + */ +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00300000) /* 3MB */ +#define ARM_L1_GPT_SIZE UL(0x00100000) /* 1MB */ +#define ARM_REALM_SIZE UL(0x02000000) /* 32MB */ +#else +#define ARM_TZC_DRAM1_SIZE UL(0x01000000) /* 16MB */ +#define ARM_EL3_TZC_DRAM1_SIZE UL(0x00200000) /* 2MB */ +#define ARM_L1_GPT_SIZE UL(0) +#define ARM_REALM_SIZE UL(0) +#endif /* ENABLE_RME */ + +#define ARM_SCP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_L1_GPT_SIZE)) +#define ARM_SCP_TZC_DRAM1_SIZE PLAT_ARM_SCP_TZC_DRAM1_SIZE +#define ARM_SCP_TZC_DRAM1_END (ARM_SCP_TZC_DRAM1_BASE + \ + ARM_SCP_TZC_DRAM1_SIZE - 1U) +#if ENABLE_RME +#define ARM_L1_GPT_ADDR_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + ARM_L1_GPT_SIZE) +#define ARM_L1_GPT_END (ARM_L1_GPT_ADDR_BASE + \ + ARM_L1_GPT_SIZE - 1U) + +#define ARM_REALM_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_EL3_TZC_DRAM1_SIZE + \ + ARM_REALM_SIZE + \ + ARM_L1_GPT_SIZE)) +#define ARM_REALM_END (ARM_REALM_BASE + ARM_REALM_SIZE - 1U) +#endif /* ENABLE_RME */ + +#define ARM_EL3_TZC_DRAM1_BASE (ARM_SCP_TZC_DRAM1_BASE - \ + ARM_EL3_TZC_DRAM1_SIZE) +#define ARM_EL3_TZC_DRAM1_END (ARM_EL3_TZC_DRAM1_BASE + \ + ARM_EL3_TZC_DRAM1_SIZE - 1U) + +#define ARM_AP_TZC_DRAM1_BASE (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE) +#define ARM_AP_TZC_DRAM1_SIZE (ARM_TZC_DRAM1_SIZE - \ + (ARM_SCP_TZC_DRAM1_SIZE + \ + ARM_EL3_TZC_DRAM1_SIZE + \ + ARM_REALM_SIZE + \ + ARM_L1_GPT_SIZE)) +#define ARM_AP_TZC_DRAM1_END (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE - 1U) + +/* Define the Access permissions for Secure peripherals to NS_DRAM */ +#if ARM_CRYPTOCELL_INTEG +/* + * Allow Secure peripheral to read NS DRAM when integrated with CryptoCell. + * This is required by CryptoCell to authenticate BL33 which is loaded + * into the Non Secure DDR. + */ +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_RD +#else +#define ARM_TZC_NS_DRAM_S_ACCESS TZC_REGION_S_NONE +#endif + +#ifdef SPD_opteed +/* + * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to + * load/authenticate the trusted os extra image. The first 512KB of + * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading + * for OPTEE is paged image which only include the paging part using + * virtual memory but without "init" data. OPTEE will copy the "init" data + * (from pager image) to the first 512KB of TZC_DRAM, and then copy the + * extra image behind the "init" data. + */ +#define ARM_OPTEE_PAGEABLE_LOAD_BASE (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE - \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE) +#define ARM_OPTEE_PAGEABLE_LOAD_SIZE UL(0x400000) +#define ARM_OPTEE_PAGEABLE_LOAD_MEM MAP_REGION_FLAT( \ + ARM_OPTEE_PAGEABLE_LOAD_BASE, \ + ARM_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Map the memory for the OP-TEE core (also known as OP-TEE pager when paging + * support is enabled). + */ +#define ARM_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_opteed */ + +#define ARM_NS_DRAM1_BASE ARM_DRAM1_BASE +#define ARM_NS_DRAM1_SIZE (ARM_DRAM1_SIZE - \ + ARM_TZC_DRAM1_SIZE) +#define ARM_NS_DRAM1_END (ARM_NS_DRAM1_BASE + \ + ARM_NS_DRAM1_SIZE - 1U) +#ifdef PLAT_ARM_DRAM1_BASE +#define ARM_DRAM1_BASE PLAT_ARM_DRAM1_BASE +#else +#define ARM_DRAM1_BASE ULL(0x80000000) +#endif /* PLAT_ARM_DRAM1_BASE */ + +#define ARM_DRAM1_SIZE ULL(0x80000000) +#define ARM_DRAM1_END (ARM_DRAM1_BASE + \ + ARM_DRAM1_SIZE - 1U) + +#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 - 1U) + +#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_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 ARM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + ARM_SHARED_RAM_BASE, \ + ARM_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | EL3_PAS) + +#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_TSP_SEC_MEM MAP_REGION_FLAT( \ + TSP_SEC_MEM_BASE, \ + TSP_SEC_MEM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#if ARM_BL31_IN_DRAM +#define ARM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_ARM_MAX_BL31_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#define ARM_MAP_EL3_TZC_DRAM MAP_REGION_FLAT( \ + ARM_EL3_TZC_DRAM1_BASE, \ + ARM_EL3_TZC_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#if defined(SPD_spmd) +#define ARM_MAP_TRUSTED_DRAM MAP_REGION_FLAT( \ + PLAT_ARM_TRUSTED_DRAM_BASE, \ + PLAT_ARM_TRUSTED_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#if ENABLE_RME +#define ARM_MAP_RMM_DRAM MAP_REGION_FLAT( \ + PLAT_ARM_RMM_BASE, \ + PLAT_ARM_RMM_SIZE, \ + MT_MEMORY | MT_RW | MT_REALM) + + +#define ARM_MAP_GPT_L1_DRAM MAP_REGION_FLAT( \ + ARM_L1_GPT_ADDR_BASE, \ + ARM_L1_GPT_SIZE, \ + MT_MEMORY | MT_RW | EL3_PAS) + +#endif /* ENABLE_RME */ + +/* + * 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_BL1_RW MAP_REGION_FLAT( \ + BL1_RW_BASE, \ + BL1_RW_LIMIT - BL1_RW_BASE, \ + 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 ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS), \ + MAP_REGION_FLAT( \ + BL_RO_DATA_BASE, \ + BL_RO_DATA_END \ + - BL_RO_DATA_BASE, \ + MT_RO_DATA | EL3_PAS) +#else +#define ARM_MAP_BL_RO MAP_REGION_FLAT( \ + BL_CODE_BASE, \ + BL_CODE_END - BL_CODE_BASE, \ + MT_CODE | EL3_PAS) +#endif +#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 | EL3_PAS) +#endif +#if USE_ROMLIB +#define ARM_MAP_ROMLIB_CODE MAP_REGION_FLAT( \ + ROMLIB_RO_BASE, \ + ROMLIB_RO_LIMIT - ROMLIB_RO_BASE,\ + MT_CODE | EL3_PAS) + +#define ARM_MAP_ROMLIB_DATA MAP_REGION_FLAT( \ + ROMLIB_RW_BASE, \ + ROMLIB_RW_END - ROMLIB_RW_BASE,\ + MT_MEMORY | MT_RW | EL3_PAS) +#endif + +/* + * Map mem_protect flash region with read and write permissions + */ +#define ARM_V2M_MAP_MEM_PROTECT MAP_REGION_FLAT(PLAT_ARM_MEM_PROT_ADDR, \ + V2M_FLASH_BLOCK_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +/* + * 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 | EL3_PAS) +/* + * Map L0_GPT with read and write permissions + */ +#if ENABLE_RME +#define ARM_MAP_L0_GPT_REGION MAP_REGION_FLAT(ARM_L0_GPT_ADDR_BASE, \ + ARM_L0_GPT_SIZE, \ + MT_MEMORY | MT_RW | MT_ROOT) +#endif + +/* + * 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 7 + +#define MAX_MMAP_REGIONS (PLAT_ARM_MMAP_ENTRIES + \ + ARM_BL_REGIONS) + +/* Memory mapped Generic timer interfaces */ +#ifdef PLAT_ARM_SYS_CNTCTL_BASE +#define ARM_SYS_CNTCTL_BASE PLAT_ARM_SYS_CNTCTL_BASE +#else +#define ARM_SYS_CNTCTL_BASE UL(0x2a430000) +#endif + +#ifdef PLAT_ARM_SYS_CNTREAD_BASE +#define ARM_SYS_CNTREAD_BASE PLAT_ARM_SYS_CNTREAD_BASE +#else +#define ARM_SYS_CNTREAD_BASE UL(0x2a800000) +#endif + +#ifdef PLAT_ARM_SYS_TIMCTL_BASE +#define ARM_SYS_TIMCTL_BASE PLAT_ARM_SYS_TIMCTL_BASE +#else +#define ARM_SYS_TIMCTL_BASE UL(0x2a810000) +#endif + +#ifdef PLAT_ARM_SYS_CNT_BASE_S +#define ARM_SYS_CNT_BASE_S PLAT_ARM_SYS_CNT_BASE_S +#else +#define ARM_SYS_CNT_BASE_S UL(0x2a820000) +#endif + +#ifdef PLAT_ARM_SYS_CNT_BASE_NS +#define ARM_SYS_CNT_BASE_NS PLAT_ARM_SYS_CNT_BASE_NS +#else +#define ARM_SYS_CNT_BASE_NS UL(0x2a830000) +#endif + +#define ARM_CONSOLE_BAUDRATE 115200 + +/* Trusted Watchdog constants */ +#ifdef PLAT_ARM_SP805_TWDG_BASE +#define ARM_SP805_TWDG_BASE PLAT_ARM_SP805_TWDG_BASE +#else +#define ARM_SP805_TWDG_BASE UL(0x2a490000) +#endif +#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) + +/****************************************************************************** + * Required platform porting definitions common to all ARM standard platforms + *****************************************************************************/ + +/* + * 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 + +/* + * 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)) + +/* + * 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)) + +#if ENABLE_RME +/* + * Store the L0 GPT on Trusted SRAM next to firmware + * configuration memory, 4KB aligned. + */ +#define ARM_L0_GPT_SIZE (PAGE_SIZE) +#define ARM_L0_GPT_ADDR_BASE (ARM_FW_CONFIGS_LIMIT) +#define ARM_L0_GPT_LIMIT (ARM_L0_GPT_ADDR_BASE + ARM_L0_GPT_SIZE) +#else +#define ARM_L0_GPT_SIZE U(0) +#endif + +/******************************************************************************* + * 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 PLAT_ARM_TRUSTED_ROM_BASE +#ifdef PLAT_BL1_RO_LIMIT +#define BL1_RO_LIMIT PLAT_BL1_RO_LIMIT +#else +#define BL1_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE \ + + (PLAT_ARM_TRUSTED_ROM_SIZE - \ + PLAT_ARM_MAX_ROMLIB_RO_SIZE)) +#endif + +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (ARM_BL_RAM_BASE + \ + ARM_BL_RAM_SIZE - \ + (PLAT_ARM_MAX_BL1_RW_SIZE +\ + PLAT_ARM_MAX_ROMLIB_RW_SIZE)) +#define BL1_RW_LIMIT (ARM_BL_RAM_BASE + \ + (ARM_BL_RAM_SIZE - PLAT_ARM_MAX_ROMLIB_RW_SIZE)) + +#define ROMLIB_RO_BASE BL1_RO_LIMIT +#define ROMLIB_RO_LIMIT (PLAT_ARM_TRUSTED_ROM_BASE + PLAT_ARM_TRUSTED_ROM_SIZE) + +#define ROMLIB_RW_BASE (BL1_RW_BASE + PLAT_ARM_MAX_BL1_RW_SIZE) +#define ROMLIB_RW_END (ROMLIB_RW_BASE + PLAT_ARM_MAX_ROMLIB_RW_SIZE) + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +#if BL2_AT_EL3 +/* Put BL2 towards the middle of the Trusted SRAM */ +#define BL2_BASE (ARM_TRUSTED_SRAM_BASE + \ + (PLAT_ARM_TRUSTED_SRAM_SIZE >> 1) + 0x2000) +#define BL2_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) + +#else +/* + * Put BL2 just below BL1. + */ +#define BL2_BASE (BL1_RW_BASE - PLAT_ARM_MAX_BL2_SIZE) +#define BL2_LIMIT BL1_RW_BASE +#endif + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#if ARM_BL31_IN_DRAM || SEPARATE_NOBITS_REGION +/* + * Put BL31 at the bottom of TZC secured DRAM + */ +#define BL31_BASE ARM_AP_TZC_DRAM1_BASE +#define BL31_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +/* + * For SEPARATE_NOBITS_REGION, BL31 PROGBITS are loaded in TZC secured DRAM. + * And BL31 NOBITS are loaded in Trusted SRAM such that BL2 is overwritten. + */ +#if SEPARATE_NOBITS_REGION +#define BL31_NOBITS_BASE BL2_BASE +#define BL31_NOBITS_LIMIT BL2_LIMIT +#endif /* SEPARATE_NOBITS_REGION */ +#elif (RESET_TO_BL31) +/* Ensure Position Independent support (PIE) is enabled for this config.*/ +# if !ENABLE_PIE +# error "BL31 must be a PIE if RESET_TO_BL31=1." +#endif +/* + * Since this is PIE, we can define BL31_BASE to 0x0 since this macro is solely + * used for building BL31 and not used for loading BL31. + */ +# define BL31_BASE 0x0 +# define BL31_LIMIT PLAT_ARM_MAX_BL31_SIZE +#else +/* Put BL31 below BL2 in the Trusted SRAM.*/ +#define BL31_BASE ((ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE)\ + - PLAT_ARM_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL2_BASE +/* + * For BL2_AT_EL3 make sure the BL31 can grow up until BL2_BASE. This is + * because in the BL2_AT_EL3 configuration, BL2 is always resident. + */ +#if BL2_AT_EL3 +#define BL31_LIMIT BL2_BASE +#else +#define BL31_LIMIT (ARM_BL_RAM_BASE + ARM_BL_RAM_SIZE) +#endif +#endif + +/****************************************************************************** + * RMM specific defines + *****************************************************************************/ +#if ENABLE_RME +#define RMM_BASE (ARM_REALM_BASE) +#define RMM_LIMIT (RMM_BASE + ARM_REALM_SIZE) +#endif + +#if !defined(__aarch64__) || JUNO_AARCH32_EL3_RUNTIME +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch32 mode + ******************************************************************************/ +# if RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME +/* Ensure Position Independent support (PIE) is enabled for this config.*/ +# if !ENABLE_PIE +# error "BL32 must be a PIE if RESET_TO_SP_MIN=1." +#endif +/* + * Since this is PIE, we can define BL32_BASE to 0x0 since this macro is solely + * used for building BL32 and not used for loading BL32. + */ +# define BL32_BASE 0x0 +# define BL32_LIMIT PLAT_ARM_MAX_BL32_SIZE +# else +/* Put BL32 below BL2 in the Trusted SRAM.*/ +# 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) +# endif /* RESET_TO_SP_MIN && !JUNO_AARCH32_EL3_RUNTIME */ + +#else +/******************************************************************************* + * BL32 specific defines for EL3 runtime in AArch64 mode + ******************************************************************************/ +/* + * On ARM standard platforms, the TSP can execute from Trusted SRAM, + * Trusted DRAM (if available) or the DRAM region secured by the TrustZone + * controller. + */ +# if SPM_MM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# elif defined(SPD_spmd) +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + ULL(0x200000)) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - ULL(0x200000)) +# define BL32_BASE PLAT_ARM_SPMC_BASE +# define BL32_LIMIT (PLAT_ARM_SPMC_BASE + \ + PLAT_ARM_SPMC_SIZE) +# elif ARM_BL31_IN_DRAM +# define TSP_SEC_MEM_BASE (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +# define TSP_SEC_MEM_SIZE (ARM_AP_TZC_DRAM1_SIZE - \ + PLAT_ARM_MAX_BL31_SIZE) +# define BL32_BASE (ARM_AP_TZC_DRAM1_BASE + \ + PLAT_ARM_MAX_BL31_SIZE) +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_SRAM_ID +# define TSP_SEC_MEM_BASE ARM_BL_RAM_BASE +# define TSP_SEC_MEM_SIZE ARM_BL_RAM_SIZE +# define TSP_PROGBITS_LIMIT BL31_BASE +# define BL32_BASE ARM_FW_CONFIGS_LIMIT +# define BL32_LIMIT BL31_BASE +# elif ARM_TSP_RAM_LOCATION_ID == ARM_TRUSTED_DRAM_ID +# define TSP_SEC_MEM_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define TSP_SEC_MEM_SIZE PLAT_ARM_TRUSTED_DRAM_SIZE +# define BL32_BASE PLAT_ARM_TRUSTED_DRAM_BASE +# define BL32_LIMIT (PLAT_ARM_TRUSTED_DRAM_BASE \ + + (UL(1) << 21)) +# elif ARM_TSP_RAM_LOCATION_ID == ARM_DRAM_ID +# define TSP_SEC_MEM_BASE ARM_AP_TZC_DRAM1_BASE +# define TSP_SEC_MEM_SIZE ARM_AP_TZC_DRAM1_SIZE +# define BL32_BASE ARM_AP_TZC_DRAM1_BASE +# define BL32_LIMIT (ARM_AP_TZC_DRAM1_BASE + \ + ARM_AP_TZC_DRAM1_SIZE) +# else +# error "Unsupported ARM_TSP_RAM_LOCATION_ID value" +# endif +#endif /* !__aarch64__ || JUNO_AARCH32_EL3_RUNTIME */ + +/* + * BL32 is mandatory in AArch32. In AArch64, undefine BL32_BASE if there is no + * SPD and no SPM-MM, as they are the only ones that can be used as BL32. + */ +#if defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME +# if defined(SPD_none) && !SPM_MM +# undef BL32_BASE +# endif /* defined(SPD_none) && !SPM_MM */ +#endif /* defined(__aarch64__) && !JUNO_AARCH32_EL3_RUNTIME */ + +/******************************************************************************* + * FWU Images: NS_BL1U, BL2U & NS_BL2U defines. + ******************************************************************************/ +#define BL2U_BASE BL2_BASE +#define BL2U_LIMIT BL2_LIMIT + +#define NS_BL2U_BASE ARM_NS_DRAM1_BASE +#define NS_BL1U_BASE (PLAT_ARM_NVM_BASE + UL(0x03EB8000)) + +/* + * ID of the secure physical generic timer interrupt used by the TSP. + */ +#define TSP_IRQ_SEC_PHY_TIMER ARM_IRQ_SEC_PHY_TIMER + + +/* + * One cache line needed for bakery locks on ARM platforms + */ +#define PLAT_PERCPU_BAKERY_LOCK_SIZE (1 * CACHE_WRITEBACK_GRANULE) + +/* Priority levels for ARM platforms */ +#define PLAT_RAS_PRI 0x10 +#define PLAT_SDEI_CRITICAL_PRI 0x60 +#define PLAT_SDEI_NORMAL_PRI 0x70 + +/* ARM platforms use 3 upper bits of secure interrupt priority */ +#define PLAT_PRI_BITS 3 + +/* SGI used for SDEI signalling */ +#define ARM_SDEI_SGI ARM_IRQ_SEC_SGI_0 + +#if SDEI_IN_FCONF +/* ARM SDEI dynamic private event max count */ +#define ARM_SDEI_DP_EVENT_MAX_CNT 3 + +/* ARM SDEI dynamic shared event max count */ +#define ARM_SDEI_DS_EVENT_MAX_CNT 3 +#else +/* ARM SDEI dynamic private event numbers */ +#define ARM_SDEI_DP_EVENT_0 1000 +#define ARM_SDEI_DP_EVENT_1 1001 +#define ARM_SDEI_DP_EVENT_2 1002 + +/* ARM SDEI dynamic shared event numbers */ +#define ARM_SDEI_DS_EVENT_0 2000 +#define ARM_SDEI_DS_EVENT_1 2001 +#define ARM_SDEI_DS_EVENT_2 2002 + +#define ARM_SDEI_PRIVATE_EVENTS \ + SDEI_DEFINE_EVENT_0(ARM_SDEI_SGI), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_PRIVATE_EVENT(ARM_SDEI_DP_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) + +#define ARM_SDEI_SHARED_EVENTS \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_0, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_1, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC), \ + SDEI_SHARED_EVENT(ARM_SDEI_DS_EVENT_2, SDEI_DYN_IRQ, SDEI_MAPF_DYNAMIC) +#endif /* SDEI_IN_FCONF */ + +#endif /* ARM_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h b/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h new file mode 100644 index 0000000..ff00fe7 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_DYN_CFG_HELPERS_H +#define ARM_DYN_CFG_HELPERS_H + +#include +#include + +/* Function declarations */ +int arm_dyn_tb_fw_cfg_init(void *dtb, int *node); +int arm_set_dtb_mbedtls_heap_info(void *dtb, void *heap_addr, + size_t heap_size); + +#endif /* ARM_DYN_CFG_HELPERS_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h new file mode 100644 index 0000000..8fd8c7a --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_FCONF_GETTER +#define ARM_FCONF_GETTER + +#include + +#include + +/* ARM io policies */ +#define arm__io_policies_getter(id) __extension__ ({ \ + assert((id) < MAX_NUMBER_IDS); \ + &policies[id]; \ +}) + +struct plat_io_policy { + uintptr_t *dev_handle; + uintptr_t image_spec; + int (*check)(const uintptr_t spec); +}; + +extern struct plat_io_policy policies[]; +int fconf_populate_arm_io_policies(uintptr_t config); + +#endif /* ARM_FCONF_GETTER */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h new file mode 100644 index 0000000..02ee66c --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_FCONF_IO_STORAGE_H +#define ARM_FCONF_IO_STORAGE_H + +#include + +/* IO devices handle */ +extern uintptr_t memmap_dev_handle; +extern uintptr_t fip_dev_handle; + +/* Function declarations */ +int open_fip(const uintptr_t spec); +int open_memmap(const uintptr_t spec); + +#endif /* ARM_FCONF_IO_STORAGE_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h new file mode 100644 index 0000000..4fee41b --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_PAS_DEF_H +#define ARM_PAS_DEF_H + +#include +#include + +/***************************************************************************** + * PAS regions used to initialize the Granule Protection Table (GPT) + ****************************************************************************/ + +/* + * The PA space is initially mapped in the GPT as follows: + * + * ============================================================================ + * Base Addr| Size |L? GPT|PAS |Content |Comment + * ============================================================================ + * 0GB | 1GB |L0 GPT|ANY |TBROM (EL3 code) |Fixed mapping + * | | | |TSRAM (EL3 data) | + * | | | |IO (incl.UARTs & GIC) | + * ---------------------------------------------------------------------------- + * 1GB | 1GB |L0 GPT|ANY |IO |Fixed mapping + * ---------------------------------------------------------------------------- + * 2GB | 1GB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip + * ---------------------------------------------------------------------------- + * 3GB |1GB-64MB |L1 GPT|NS |DRAM (NS Kernel) |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-64MB |64MB-32MB | | | | + * | -4MB |L1 GPT|SECURE|DRAM TZC |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-32MB | | | | | + * -3MB-1MB |32MB |L1 GPT|REALM |RMM |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-3MB | | | | | + * -1MB |3MB |L1 GPT|ROOT |EL3 DRAM data |Use T.Descrip + * ---------------------------------------------------------------------------- + * 4GB-1MB |1MB |L1 GPT|ROOT |DRAM (L1 GPTs, SCP TZC) |Fixed mapping + * ============================================================================ + * + * - 4KB of L0 GPT reside in TSRAM, on top of the CONFIG section. + * - ~1MB of L1 GPTs reside at the top of DRAM1 (TZC area). + * - The first 1GB region has GPT_GPI_ANY and, therefore, is not protected by + * the GPT. + * - The DRAM TZC area is split into three regions: the L1 GPT region and + * 3MB of region below that are defined as GPT_GPI_ROOT, 32MB Realm region + * below that is defined as GPT_GPI_REALM and the rest of it is defined as + * GPT_GPI_SECURE. + */ + +/* TODO: This might not be the best way to map the PAS */ + +/* Device memory 0 to 2GB */ +#define ARM_PAS_1_BASE (U(0)) +#define ARM_PAS_1_SIZE ((ULL(1)<<31)) /* 2GB */ + +/* NS memory 2GB to (end - 64MB) */ +#define ARM_PAS_2_BASE (ARM_PAS_1_BASE + ARM_PAS_1_SIZE) +#define ARM_PAS_2_SIZE (ARM_NS_DRAM1_SIZE) + +/* Secure TZC region */ +#define ARM_PAS_3_BASE (ARM_AP_TZC_DRAM1_BASE) +#define ARM_PAS_3_SIZE (ARM_AP_TZC_DRAM1_SIZE) + +#define ARM_PAS_GPI_ANY MAP_GPT_REGION(ARM_PAS_1_BASE, \ + ARM_PAS_1_SIZE, \ + GPT_GPI_ANY) +#define ARM_PAS_KERNEL GPT_MAP_REGION_GRANULE(ARM_PAS_2_BASE, \ + ARM_PAS_2_SIZE, \ + GPT_GPI_NS) + +#define ARM_PAS_SECURE GPT_MAP_REGION_GRANULE(ARM_PAS_3_BASE, \ + ARM_PAS_3_SIZE, \ + GPT_GPI_SECURE) + +#define ARM_PAS_REALM GPT_MAP_REGION_GRANULE(ARM_REALM_BASE, \ + ARM_REALM_SIZE, \ + GPT_GPI_REALM) + +#define ARM_PAS_EL3_DRAM GPT_MAP_REGION_GRANULE(ARM_EL3_TZC_DRAM1_BASE, \ + ARM_EL3_TZC_DRAM1_SIZE, \ + GPT_GPI_ROOT) + +#define ARM_PAS_GPTS GPT_MAP_REGION_GRANULE(ARM_L1_GPT_ADDR_BASE, \ + ARM_L1_GPT_SIZE, \ + GPT_GPI_ROOT) + +/* GPT Configuration options */ +#define PLATFORM_L0GPTSZ GPCCR_L0GPTSZ_30BITS + +#endif /* ARM_PAS_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S b/arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S new file mode 100644 index 0000000..717f65e --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_RECLAIM_INIT_LD_S +#define ARM_RECLAIM_INIT_LD_S + +SECTIONS +{ + .init __STACKS_START__ : { + . = . + PLATFORM_STACK_SIZE; + . = ALIGN(PAGE_SIZE); + __INIT_CODE_START__ = .; + *(*text.init*); + __INIT_CODE_END__ = .; + INIT_CODE_END_ALIGNED = ALIGN(PAGE_SIZE); + } >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(__INIT_CODE_END__ <= BL31_PROGBITS_LIMIT, + "BL31 init has exceeded progbits limit.") +#endif +} + +#define ABS ABSOLUTE + +#define STACK_SECTION \ + stacks (NOLOAD) : { \ + __STACKS_START__ = .; \ + *(tzfw_normal_stacks) \ + __STACKS_END__ = .; \ + /* Allow room for the init section where necessary. */ \ + OFFSET = ABS(SIZEOF(.init) - (. - __STACKS_START__)); \ + /* Offset sign */ \ + SIGN = ABS(OFFSET) & (1 << 63); \ + /* Offset mask */ \ + MASK = ABS(SIGN >> 63) - 1; \ + . += ABS(OFFSET) & ABS(MASK); \ + . = ALIGN(PAGE_SIZE); \ + } + +#endif /* ARM_RECLAIM_INIT_LD_S */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h b/arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h new file mode 100644 index 0000000..2eeed95 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016-2019,2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_SIP_SVC_H +#define ARM_SIP_SVC_H + +#include + +/* SMC function IDs for SiP Service queries */ + +#define ARM_SIP_SVC_CALL_COUNT U(0x8200ff00) +#define ARM_SIP_SVC_UID U(0x8200ff01) +/* U(0x8200ff02) is reserved */ +#define ARM_SIP_SVC_VERSION U(0x8200ff03) + +/* PMF_SMC_GET_TIMESTAMP_32 0x82000010 */ +/* PMF_SMC_GET_TIMESTAMP_64 0xC2000010 */ + +/* Function ID for requesting state switch of lower EL */ +#define ARM_SIP_SVC_EXE_STATE_SWITCH U(0x82000020) + +/* DEBUGFS_SMC_32 0x82000030U */ +/* DEBUGFS_SMC_64 0xC2000030U */ + +/* + * Arm Ethos-N NPU SiP SMC function IDs + * 0xC2000050-0xC200005F + * 0x82000050-0x8200005F + */ + +/* ARM SiP Service Calls version numbers */ +#define ARM_SIP_SVC_VERSION_MAJOR U(0x0) +#define ARM_SIP_SVC_VERSION_MINOR U(0x2) + +#endif /* ARM_SIP_SVC_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h b/arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h new file mode 100644 index 0000000..c43583d --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_SPM_DEF_H +#define ARM_SPM_DEF_H + +#include +#include + +/* + * If BL31 is placed in DRAM, place the Secure Partition in DRAM right after the + * region used by BL31. If BL31 it is placed in SRAM, put the Secure Partition + * at the base of DRAM. + */ +#define ARM_SP_IMAGE_BASE BL32_BASE +#define ARM_SP_IMAGE_LIMIT BL32_LIMIT +/* The maximum size of the S-EL0 payload can be 3MB */ +#define ARM_SP_IMAGE_SIZE ULL(0x300000) + +#ifdef IMAGE_BL2 +/* SPM Payload memory. Mapped as RW in BL2. */ +#define ARM_SP_IMAGE_MMAP MAP_REGION_FLAT( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif + +#ifdef IMAGE_BL31 +/* SPM Payload memory. Mapped as code in S-EL1 */ +#define ARM_SP_IMAGE_MMAP MAP_REGION2( \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_BASE, \ + ARM_SP_IMAGE_SIZE, \ + MT_CODE | MT_SECURE | MT_USER, \ + PAGE_SIZE) +#endif + +/* + * Memory shared between EL3 and S-EL0. It is used by EL3 to push data into + * S-EL0, so it is mapped with RW permission from EL3 and with RO permission + * from S-EL0. Placed after SPM Payload memory. + */ +#define PLAT_SPM_BUF_BASE (ARM_SP_IMAGE_BASE + ARM_SP_IMAGE_SIZE) +#define PLAT_SPM_BUF_SIZE ULL(0x100000) + +#define ARM_SPM_BUF_EL3_MMAP MAP_REGION_FLAT( \ + PLAT_SPM_BUF_BASE, \ + PLAT_SPM_BUF_SIZE, \ + MT_RW_DATA | MT_SECURE) +#define ARM_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) + +/* + * Memory shared between Normal world and S-EL0 for passing data during service + * requests. Mapped as RW and NS. Placed after the shared memory between EL3 and + * S-EL0. + */ +#define PLAT_SP_IMAGE_NS_BUF_BASE (PLAT_SPM_BUF_BASE + PLAT_SPM_BUF_SIZE) +#define PLAT_SP_IMAGE_NS_BUF_SIZE ULL(0x10000) +#define ARM_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) + +/* + * RW memory, which uses the remaining Trusted DRAM. Placed after the memory + * shared between Secure and Non-secure worlds, or after the platform specific + * buffers, if defined. First there is the stack memory for all CPUs and then + * there is the common heap memory. Both are mapped with RW permissions. + */ +#define PLAT_SP_IMAGE_STACK_BASE PLAT_ARM_SP_IMAGE_STACK_BASE +#define PLAT_SP_IMAGE_STACK_PCPU_SIZE ULL(0x2000) +#define ARM_SP_IMAGE_STACK_TOTAL_SIZE (PLATFORM_CORE_COUNT * \ + PLAT_SP_IMAGE_STACK_PCPU_SIZE) + +#define ARM_SP_IMAGE_HEAP_BASE (PLAT_SP_IMAGE_STACK_BASE + \ + ARM_SP_IMAGE_STACK_TOTAL_SIZE) +#define ARM_SP_IMAGE_HEAP_SIZE (ARM_SP_IMAGE_LIMIT - ARM_SP_IMAGE_HEAP_BASE) + +#define ARM_SP_IMAGE_RW_MMAP MAP_REGION2( \ + PLAT_SP_IMAGE_STACK_BASE, \ + PLAT_SP_IMAGE_STACK_BASE, \ + (ARM_SP_IMAGE_LIMIT - \ + PLAT_SP_IMAGE_STACK_BASE), \ + MT_RW_DATA | MT_SECURE | MT_USER,\ + PAGE_SIZE) + +/* Total number of memory regions with distinct properties */ +#define ARM_SP_IMAGE_NUM_MEM_REGIONS 6 + +/* Cookies passed to the Secure Partition at boot. Not used by ARM platforms. */ +#define PLAT_SPM_COOKIE_0 ULL(0) +#define PLAT_SPM_COOKIE_1 ULL(0) + +#endif /* ARM_SPM_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S b/arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S new file mode 100644 index 0000000..6dcea0b --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef ARM_TZC_DRAM_LD_S +#define ARM_TZC_DRAM_LD_S + +#include + +MEMORY { + EL3_SEC_DRAM (rw): ORIGIN = ARM_EL3_TZC_DRAM1_BASE, LENGTH = ARM_EL3_TZC_DRAM1_SIZE +} + +SECTIONS +{ + . = ARM_EL3_TZC_DRAM1_BASE; + ASSERT(. == ALIGN(PAGE_SIZE), + "ARM_EL3_TZC_DRAM_BASE address is not aligned on a page boundary.") + el3_tzc_dram (NOLOAD) : ALIGN(PAGE_SIZE) { + __EL3_SEC_DRAM_START__ = .; + *(arm_el3_tzc_dram) + __EL3_SEC_DRAM_UNALIGNED_END__ = .; + + . = ALIGN(PAGE_SIZE); + __EL3_SEC_DRAM_END__ = .; + } >EL3_SEC_DRAM +} + +#endif /* ARM_TZC_DRAM_LD_S */ diff --git a/arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h new file mode 100644 index 0000000..aa628df --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_ARM_SP_GETTER_H +#define FCONF_ARM_SP_GETTER_H + +#include +#include + +/* arm_sp getter */ +#define arm__sp_getter(prop) arm_sp.prop + +#define ARM_SP_MAX_SIZE U(0xb0000) +#define ARM_SP_OWNER_NAME_LEN U(8) + +struct arm_sp_t { + unsigned int number_of_sp; + union uuid_helper_t uuids[MAX_SP_IDS]; + uintptr_t load_addr[MAX_SP_IDS]; + char owner[MAX_SP_IDS][ARM_SP_OWNER_NAME_LEN]; +}; + +int fconf_populate_arm_sp(uintptr_t config); + +extern struct arm_sp_t arm_sp; + +extern bl_mem_params_node_t sp_mem_params_descs[MAX_SP_IDS]; + +#endif /* FCONF_ARM_SP_GETTER_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h new file mode 100644 index 0000000..fcdc31f --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_ETHOSN_GETTER_H +#define FCONF_ETHOSN_GETTER_H + +#include + +#include + +#define hw_config__ethosn_config_getter(prop) ethosn_config.prop +#define hw_config__ethosn_core_addr_getter(idx) __extension__ ({ \ + assert(idx < ethosn_config.num_cores); \ + ethosn_config.core[idx].addr; \ +}) + +#define ETHOSN_STATUS_DISABLED U(0) +#define ETHOSN_STATUS_ENABLED U(1) + +#define ETHOSN_CORE_NUM_MAX U(64) + +struct ethosn_core_t { + uint64_t addr; +}; + +struct ethosn_config_t { + uint32_t num_cores; + struct ethosn_core_t core[ETHOSN_CORE_NUM_MAX]; +}; + +int fconf_populate_arm_ethosn(uintptr_t config); + +extern struct ethosn_config_t ethosn_config; + +#endif /* FCONF_ETHOSN_GETTER_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h new file mode 100644 index 0000000..80a6000 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_NV_CNTR_GETTER_H +#define FCONF_NV_CNTR_GETTER_H + +#include +#include + +#define cot__nv_cntr_addr_getter(id) nv_cntr_base_addr[id] + +extern uintptr_t nv_cntr_base_addr[MAX_NV_CTR_IDS]; + +#endif /* FCONF_NV_CNTR_GETTER_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h b/arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h new file mode 100644 index 0000000..e0a97a6 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_SDEI_GETTER_H +#define FCONF_SDEI_GETTER_H + +#include + +#include + +#define sdei__dyn_config_getter(id) sdei_dyn_config.id + +struct sdei_dyn_config_t { + uint32_t private_ev_cnt; + int32_t private_ev_nums[PLAT_SDEI_DP_EVENT_MAX_CNT]; + unsigned int private_ev_intrs[PLAT_SDEI_DP_EVENT_MAX_CNT]; + unsigned int private_ev_flags[PLAT_SDEI_DP_EVENT_MAX_CNT]; + uint32_t shared_ev_cnt; + int32_t shared_ev_nums[PLAT_SDEI_DS_EVENT_MAX_CNT]; + unsigned int shared_ev_intrs[PLAT_SDEI_DS_EVENT_MAX_CNT]; + unsigned int shared_ev_flags[PLAT_SDEI_DS_EVENT_MAX_CNT]; +}; + +int fconf_populate_sdei_dyn_config(uintptr_t config); + +extern struct sdei_dyn_config_t sdei_dyn_config; + +#endif /* FCONF_SDEI_GETTER_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h b/arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h new file mode 100644 index 0000000..5d6b594 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FCONF_SEC_INTR_CONFIG_H +#define FCONF_SEC_INTR_CONFIG_H + +#include + +#include + +#define hw_config__sec_intr_prop_getter(id) sec_intr_prop.id + +#define SEC_INT_COUNT_MAX U(15) + +struct sec_intr_prop_t { + interrupt_prop_t descriptor[SEC_INT_COUNT_MAX]; + uint32_t count; +}; + +int fconf_populate_sec_intr_config(uintptr_t config); + +extern struct sec_intr_prop_t sec_intr_prop; + +#endif /* FCONF_SEC_INTR_CONFIG_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/plat_arm.h b/arm-trusted-firmware/include/plat/arm/common/plat_arm.h new file mode 100644 index 0000000..9618700 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/plat_arm.h @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLAT_ARM_H +#define PLAT_ARM_H + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct meminfo; +struct image_info; +struct bl_params; + +typedef struct arm_tzc_regions_info { + unsigned long long base; + unsigned long long end; + unsigned int sec_attr; + unsigned int nsaid_permissions; +} arm_tzc_regions_info_t; + +/******************************************************************************* + * Default mapping definition of the TrustZone Controller for ARM standard + * platforms. + * Configure: + * - Region 0 with no access; + * - Region 1 with secure access only; + * - the remaining DRAM regions access from the given Non-Secure masters. + ******************************************************************************/ +#if SPM_MM +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\ + TZC_REGION_S_RDWR, 0}, \ + {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {PLAT_SP_IMAGE_NS_BUF_BASE, (PLAT_SP_IMAGE_NS_BUF_BASE + \ + PLAT_SP_IMAGE_NS_BUF_SIZE) - 1, TZC_REGION_S_NONE, \ + PLAT_ARM_TZC_NS_DEV_ACCESS} + +#elif ENABLE_RME +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_AP_TZC_DRAM1_END, TZC_REGION_S_RDWR, 0},\ + {ARM_EL3_TZC_DRAM1_BASE, ARM_L1_GPT_END, TZC_REGION_S_RDWR, 0}, \ + {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_REALM_BASE, ARM_REALM_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS} + +#else +#define ARM_TZC_REGIONS_DEF \ + {ARM_AP_TZC_DRAM1_BASE, ARM_EL3_TZC_DRAM1_END + ARM_L1_GPT_SIZE,\ + TZC_REGION_S_RDWR, 0}, \ + {ARM_NS_DRAM1_BASE, ARM_NS_DRAM1_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS}, \ + {ARM_DRAM2_BASE, ARM_DRAM2_END, ARM_TZC_NS_DRAM_S_ACCESS, \ + PLAT_ARM_TZC_NS_DEV_ACCESS} +#endif + +#define ARM_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_arm_mmap) - 1) <= PLAT_ARM_MMAP_ENTRIES, \ + assert_plat_arm_mmap_mismatch); \ + CASSERT((PLAT_ARM_MMAP_ENTRIES + ARM_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions); + +void arm_setup_romlib(void); + +#if defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) +/* + * Use this macro to instantiate lock before it is used in below + * arm_lock_xxx() macros + */ +#define ARM_INSTANTIATE_LOCK static DEFINE_BAKERY_LOCK(arm_lock) +#define ARM_LOCK_GET_INSTANCE (&arm_lock) + +#if !HW_ASSISTED_COHERENCY +#define ARM_SCMI_INSTANTIATE_LOCK DEFINE_BAKERY_LOCK(arm_scmi_lock) +#else +#define ARM_SCMI_INSTANTIATE_LOCK spinlock_t arm_scmi_lock +#endif +#define ARM_SCMI_LOCK_GET_INSTANCE (&arm_scmi_lock) + +/* + * These are wrapper macros to the Coherent Memory Bakery Lock API. + */ +#define arm_lock_init() bakery_lock_init(&arm_lock) +#define arm_lock_get() bakery_lock_get(&arm_lock) +#define arm_lock_release() bakery_lock_release(&arm_lock) + +#else + +/* + * Empty macros for all other BL stages other than BL31 and BL32 + */ +#define ARM_INSTANTIATE_LOCK static int arm_lock __unused +#define ARM_LOCK_GET_INSTANCE 0 +#define arm_lock_init() +#define arm_lock_get() +#define arm_lock_release() + +#endif /* defined(IMAGE_BL31) || (!defined(__aarch64__) && defined(IMAGE_BL32)) */ + +#if ARM_RECOM_STATE_ID_ENC +/* + * Macros used to parse state information from State-ID if it is using the + * recommended encoding for State-ID. + */ +#define ARM_LOCAL_PSTATE_WIDTH 4 +#define ARM_LOCAL_PSTATE_MASK ((1 << ARM_LOCAL_PSTATE_WIDTH) - 1) + +/* Macros to construct the composite power state */ + +/* Make composite power state parameter till power level 0 */ +#if PSCI_EXTENDED_STATE_ID + +#define arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type) \ + (((lvl0_state) << PSTATE_ID_SHIFT) | ((type) << PSTATE_TYPE_SHIFT)) +#else +#define arm_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 arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl1_state) << ARM_LOCAL_PSTATE_WIDTH) | \ + arm_make_pwrstate_lvl0(lvl0_state, pwr_lvl, type)) + +/* Make composite power state parameter till power level 2 */ +#define arm_make_pwrstate_lvl2(lvl2_state, lvl1_state, lvl0_state, pwr_lvl, type) \ + (((lvl2_state) << (ARM_LOCAL_PSTATE_WIDTH * 2)) | \ + arm_make_pwrstate_lvl1(lvl1_state, lvl0_state, pwr_lvl, type)) + +#endif /* __ARM_RECOM_STATE_ID_ENC__ */ + +/* ARM State switch error codes */ +#define STATE_SW_E_PARAM (-2) +#define STATE_SW_E_DENIED (-3) + +/* plat_get_rotpk_info() flags */ +#define ARM_ROTPK_REGS_ID 1 +#define ARM_ROTPK_DEVEL_RSA_ID 2 +#define ARM_ROTPK_DEVEL_ECDSA_ID 3 + + +/* IO storage utility functions */ +int arm_io_setup(void); + +/* Set image specification in IO block policy */ +int arm_set_image_source(unsigned int image_id, const char *part_name, + uintptr_t *dev_handle, uintptr_t *image_spec); +void arm_set_fip_addr(uint32_t active_fw_bank_idx); + +/* Security utility functions */ +void arm_tzc400_setup(uintptr_t tzc_base, + const arm_tzc_regions_info_t *tzc_regions); +struct tzc_dmc500_driver_data; +void arm_tzc_dmc500_setup(struct tzc_dmc500_driver_data *plat_driver_data, + const arm_tzc_regions_info_t *tzc_regions); + +/* Console utility functions */ +void arm_console_boot_init(void); +void arm_console_boot_end(void); +void arm_console_runtime_init(void); +void arm_console_runtime_end(void); + +/* Systimer utility function */ +void arm_configure_sys_timer(void); + +/* PM utility functions */ +int arm_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state); +int arm_validate_psci_entrypoint(uintptr_t entrypoint); +int arm_validate_ns_entrypoint(uintptr_t entrypoint); +void arm_system_pwr_domain_save(void); +void arm_system_pwr_domain_resume(void); +int arm_psci_read_mem_protect(int *enabled); +int arm_nor_psci_write_mem_protect(int val); +void arm_nor_psci_do_static_mem_protect(void); +void arm_nor_psci_do_dyn_mem_protect(void); +int arm_psci_mem_protect_chk(uintptr_t base, u_register_t length); + +/* Topology utility function */ +int arm_check_mpidr(u_register_t mpidr); + +/* BL1 utility functions */ +void arm_bl1_early_platform_setup(void); +void arm_bl1_platform_setup(void); +void arm_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void arm_bl2_early_platform_setup(uintptr_t fw_config, struct meminfo *mem_layout); +void arm_bl2_platform_setup(void); +void arm_bl2_plat_arch_setup(void); +uint32_t arm_get_spsr_for_bl32_entry(void); +uint32_t arm_get_spsr_for_bl33_entry(void); +int arm_bl2_plat_handle_post_image_load(unsigned int image_id); +int arm_bl2_handle_post_image_load(unsigned int image_id); +struct bl_params *arm_get_next_bl_params(void); + +/* BL2 at EL3 functions */ +void arm_bl2_el3_early_platform_setup(void); +void arm_bl2_el3_plat_arch_setup(void); + +/* BL2U utility functions */ +void arm_bl2u_early_platform_setup(struct meminfo *mem_layout, + void *plat_info); +void arm_bl2u_platform_setup(void); +void arm_bl2u_plat_arch_setup(void); + +/* BL31 utility functions */ +void arm_bl31_early_platform_setup(void *from_bl2, uintptr_t soc_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2); +void arm_bl31_platform_setup(void); +void arm_bl31_plat_runtime_setup(void); +void arm_bl31_plat_arch_setup(void); + +/* TSP utility functions */ +void arm_tsp_early_platform_setup(void); + +/* SP_MIN utility functions */ +void arm_sp_min_early_platform_setup(void *from_bl2, uintptr_t tos_fw_config, + uintptr_t hw_config, void *plat_params_from_bl2); +void arm_sp_min_plat_runtime_setup(void); +void arm_sp_min_plat_arch_setup(void); + +/* FIP TOC validity check */ +bool arm_io_is_toc_valid(void); + +/* Utility functions for Dynamic Config */ +void arm_bl2_dyn_cfg_init(void); +void arm_bl1_set_mbedtls_heap(void); +int arm_get_mbedtls_heap(void **heap_addr, size_t *heap_size); + +#if MEASURED_BOOT +int arm_set_tos_fw_info(uintptr_t log_addr, size_t log_size); +int arm_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); +int arm_set_tb_fw_info(uintptr_t log_addr, size_t log_size); +int arm_get_tb_fw_info(uint64_t *log_addr, size_t *log_size); +#endif /* MEASURED_BOOT */ + +/* + * Free the memory storing initialization code only used during an images boot + * time so it can be reclaimed for runtime data + */ +void arm_free_init_memory(void); + +/* + * Make the higher level translation tables read-only + */ +void arm_xlat_make_tables_readonly(void); + +/* + * Mandatory functions required in ARM standard platforms + */ +unsigned int plat_arm_get_cluster_core_count(u_register_t mpidr); +void plat_arm_gic_driver_init(void); +void plat_arm_gic_init(void); +void plat_arm_gic_cpuif_enable(void); +void plat_arm_gic_cpuif_disable(void); +void plat_arm_gic_redistif_on(void); +void plat_arm_gic_redistif_off(void); +void plat_arm_gic_pcpu_init(void); +void plat_arm_gic_save(void); +void plat_arm_gic_resume(void); +void plat_arm_security_setup(void); +void plat_arm_pwrc_setup(void); +void plat_arm_interconnect_init(void); +void plat_arm_interconnect_enter_coherency(void); +void plat_arm_interconnect_exit_coherency(void); +void plat_arm_program_trusted_mailbox(uintptr_t address); +bool plat_arm_bl1_fwu_needed(void); +__dead2 void plat_arm_error_handler(int err); + +/* + * Optional functions in ARM standard platforms + */ +void plat_arm_override_gicr_frames(const uintptr_t *plat_gicr_frames); +int arm_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_regs(void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_cc(void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int arm_get_rotpk_info_dev(void **key_ptr, unsigned int *key_len, + unsigned int *flags); + +#if ARM_PLAT_MT +unsigned int plat_arm_get_cpu_pe_count(u_register_t mpidr); +#endif + +/* + * This function is called after loading SCP_BL2 image and it is used to perform + * any platform-specific actions required to handle the SCP firmware. + */ +int plat_arm_bl2_handle_scp_bl2(struct image_info *scp_bl2_image_info); + +/* + * Optional functions required in ARM standard platforms + */ +void plat_arm_io_setup(void); +int plat_arm_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_arm_calc_core_pos(u_register_t mpidr); +const mmap_region_t *plat_arm_get_mmap(void); + +/* Allow platform to override psci_pm_ops during runtime */ +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops); + +/* Execution state switch in ARM platforms */ +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); + +/* Optional functions for SP_MIN */ +void plat_arm_sp_min_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); + +/* global variables */ +extern plat_psci_ops_t plat_arm_psci_pm_ops; +extern const mmap_region_t plat_arm_mmap[]; +extern const unsigned int arm_pm_idle_states[]; + +/* secure watchdog */ +void plat_arm_secure_wdt_start(void); +void plat_arm_secure_wdt_stop(void); + +/* Get SOC-ID of ARM platform */ +uint32_t plat_arm_get_soc_id(void); + +#endif /* PLAT_ARM_H */ diff --git a/arm-trusted-firmware/include/plat/arm/common/smccc_def.h b/arm-trusted-firmware/include/plat/arm/common/smccc_def.h new file mode 100644 index 0000000..0f4e573 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/common/smccc_def.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef SMCCC_DEF_H +#define SMCCC_DEF_H + +/* Defines used to retrieve ARM SOC revision */ +#define ARM_SOC_CONTINUATION_CODE U(0x4) +#define ARM_SOC_IDENTIFICATION_CODE U(0x3B) + +#endif /* SMCCC_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S b/arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S new file mode 100644 index 0000000..85a7044 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef CSS_MACROS_S +#define CSS_MACROS_S + +#include +#include + + /* --------------------------------------------- + * 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 css_print_gic_regs + mov_imm x16, PLAT_ARM_GICD_BASE + mov_imm x17, PLAT_ARM_GICC_BASE + arm_print_gic_regs + .endm + +#endif /* CSS_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/arm/css/common/css_def.h b/arm-trusted-firmware/include/plat/arm/css/common/css_def.h new file mode 100644 index 0000000..dde174c --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/css/common/css_def.h @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_DEF_H +#define CSS_DEF_H + +#include +#include +#include + +/************************************************************************* + * Definitions common to all ARM Compute SubSystems (CSS) + *************************************************************************/ +#define NSROM_BASE 0x1f000000 +#define NSROM_SIZE 0x00001000 + +/* Following covers CSS Peripherals excluding NSROM and NSRAM */ +#define CSS_DEVICE_BASE 0x20000000 +#define CSS_DEVICE_SIZE 0x0e000000 + +/* System Security Control Registers */ +#define SSC_REG_BASE 0x2a420000 +#define SSC_GPRETN (SSC_REG_BASE + 0x030) + +/* System ID Registers Unit */ +#define SID_REG_BASE 0x2a4a0000 +#define SID_SYSTEM_ID_OFFSET 0x40 +#define SID_SYSTEM_CFG_OFFSET 0x70 +#define SID_NODE_ID_OFFSET 0x60 +#define SID_CHIP_ID_MASK 0xFF +#define SID_MULTI_CHIP_MODE_MASK 0x100 +#define SID_MULTI_CHIP_MODE_SHIFT 8 + +/* The slave_bootsecure controls access to GPU, DMC and CS. */ +#define CSS_NIC400_SLAVE_BOOTSECURE 8 + +/* Interrupt handling constants */ +#define CSS_IRQ_MHU 69 +#define CSS_IRQ_GPU_SMMU_0 71 +#define CSS_IRQ_TZC 80 +#define CSS_IRQ_TZ_WDOG 86 +#define CSS_IRQ_SEC_SYS_TIMER 91 + +/* MHU register offsets */ +#define MHU_CPU_INTR_S_SET_OFFSET 0x308 + +/* + * Define a list of Group 1 Secure interrupt properties as per GICv3 + * terminology. On a GICv2 system or mode, the interrupts will be treated as + * Group 0 interrupts. + */ +#define CSS_G1S_IRQ_PROPS(grp) \ + INTR_PROP_DESC(CSS_IRQ_MHU, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_GPU_SMMU_0, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_TZC, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_TZ_WDOG, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL), \ + INTR_PROP_DESC(CSS_IRQ_SEC_SYS_TIMER, GIC_HIGHEST_SEC_PRIORITY, grp, \ + GIC_INTR_CFG_LEVEL) + +#if CSS_USE_SCMI_SDS_DRIVER +/* Memory region for shared data storage */ +#define PLAT_ARM_SDS_MEM_BASE ARM_SHARED_RAM_BASE +#define PLAT_ARM_SDS_MEM_SIZE_MAX 0xDC0 /* 3520 bytes */ +/* + * The SCMI Channel is placed right after the SDS region + */ +#define CSS_SCMI_PAYLOAD_BASE (PLAT_ARM_SDS_MEM_BASE + PLAT_ARM_SDS_MEM_SIZE_MAX) +#define CSS_SCMI_MHU_DB_REG_OFF MHU_CPU_INTR_S_SET_OFFSET + +/* Trusted mailbox base address common to all CSS */ +/* If SDS is present, then mailbox is at top of SRAM */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE (ARM_SHARED_RAM_BASE + ARM_SHARED_RAM_SIZE - 0x8) + +/* Number of retries for SCP_RAM_READY flag */ +#define CSS_SCP_READY_10US_RETRIES 1000000 /* Effective timeout of 10000 ms */ + +#else +/* + * SCP <=> AP boot configuration + * + * The SCP/AP boot configuration is a 32-bit word located at a known offset from + * the start of the Trusted SRAM. + * + * Note that the value stored at this address is only valid at boot time, before + * the SCP_BL2 image is transferred to SCP. + */ +#define SCP_BOOT_CFG_ADDR PLAT_CSS_SCP_COM_SHARED_MEM_BASE + +/* Trusted mailbox base address common to all CSS */ +/* If SDS is not present, then the mailbox is at the bottom of SRAM */ +#define PLAT_ARM_TRUSTED_MAILBOX_BASE ARM_TRUSTED_SRAM_BASE + +#endif /* CSS_USE_SCMI_SDS_DRIVER */ + +#define CSS_MAP_DEVICE MAP_REGION_FLAT( \ + CSS_DEVICE_BASE, \ + CSS_DEVICE_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define CSS_MAP_NSRAM MAP_REGION_FLAT( \ + NSRAM_BASE, \ + NSRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_NS) + +#if defined(IMAGE_BL2U) +#define CSS_MAP_SCP_BL2U MAP_REGION_FLAT( \ + SCP_BL2U_BASE, \ + SCP_BL2U_LIMIT \ + - SCP_BL2U_BASE,\ + MT_RW_DATA | MT_SECURE) +#endif + +/* Platform ID address */ +#define SSC_VERSION_OFFSET 0x040 + +#define SSC_VERSION_CONFIG_SHIFT 28 +#define SSC_VERSION_MAJOR_REV_SHIFT 24 +#define SSC_VERSION_MINOR_REV_SHIFT 20 +#define SSC_VERSION_DESIGNER_ID_SHIFT 12 +#define SSC_VERSION_PART_NUM_SHIFT 0x0 +#define SSC_VERSION_CONFIG_MASK 0xf +#define SSC_VERSION_MAJOR_REV_MASK 0xf +#define SSC_VERSION_MINOR_REV_MASK 0xf +#define SSC_VERSION_DESIGNER_ID_MASK 0xff +#define SSC_VERSION_PART_NUM_MASK 0xfff + +#define SID_SYSTEM_ID_PART_NUM_MASK 0xfff + +/* SSC debug configuration registers */ +#define SSC_DBGCFG_SET 0x14 +#define SSC_DBGCFG_CLR 0x18 + +#define SPNIDEN_INT_CLR_SHIFT 4 +#define SPNIDEN_SEL_SET_SHIFT 5 +#define SPIDEN_INT_CLR_SHIFT 6 +#define SPIDEN_SEL_SET_SHIFT 7 + +#ifndef __ASSEMBLER__ + +/* SSC_VERSION related accessors */ + +/* Returns the part number of the platform */ +#define GET_SSC_VERSION_PART_NUM(val) \ + (((val) >> SSC_VERSION_PART_NUM_SHIFT) & \ + SSC_VERSION_PART_NUM_MASK) + +/* Returns the configuration number of the platform */ +#define GET_SSC_VERSION_CONFIG(val) \ + (((val) >> SSC_VERSION_CONFIG_SHIFT) & \ + SSC_VERSION_CONFIG_MASK) + +#endif /* __ASSEMBLER__ */ + +/************************************************************************* + * Required platform porting definitions common to all + * ARM Compute SubSystems (CSS) + ************************************************************************/ + +/* + * The loading of SCP images(SCP_BL2 or SCP_BL2U) is done if there + * respective base addresses are defined (i.e SCP_BL2_BASE, SCP_BL2U_BASE). + * Hence, `CSS_LOAD_SCP_IMAGES` needs to be set to 1 if BL2 needs to load + * an SCP_BL2/SCP_BL2U image. + */ +#if CSS_LOAD_SCP_IMAGES + +#if ARM_BL31_IN_DRAM +#error "SCP_BL2 is not expected to be loaded by BL2 for ARM_BL31_IN_DRAM config" +#endif + +/* + * Load address of SCP_BL2 in CSS platform ports + * SCP_BL2 is loaded to the same place as BL31 but it shouldn't overwrite BL1 + * rw data or BL2. Once SCP_BL2 is transferred to the SCP, it is discarded and + * BL31 is loaded over the top. + */ +#define SCP_BL2_BASE (BL2_BASE - PLAT_CSS_MAX_SCP_BL2_SIZE) +#define SCP_BL2_LIMIT BL2_BASE + +#define SCP_BL2U_BASE (BL2_BASE - PLAT_CSS_MAX_SCP_BL2U_SIZE) +#define SCP_BL2U_LIMIT BL2_BASE +#endif /* CSS_LOAD_SCP_IMAGES */ + +/* Load address of Non-Secure Image for CSS platform ports */ +#define PLAT_ARM_NS_IMAGE_BASE U(0xE0000000) + +/* + * Parsing of CPU and Cluster states, as returned by 'Get CSS Power State' SCP + * command + */ +#define CSS_CLUSTER_PWR_STATE_ON 0 +#define CSS_CLUSTER_PWR_STATE_OFF 3 + +#define CSS_CPU_PWR_STATE_ON 1 +#define CSS_CPU_PWR_STATE_OFF 0 +#define CSS_CPU_PWR_STATE(state, n) (((state) >> (n)) & 1) + +#endif /* CSS_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/arm/css/common/css_pm.h b/arm-trusted-firmware/include/plat/arm/css/common/css_pm.h new file mode 100644 index 0000000..e5357f5 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/css/common/css_pm.h @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CSS_PM_H +#define CSS_PM_H + +#include +#include + +#include + +/* Macros to read the CSS power domain state */ +#define CSS_CORE_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL0] +#define CSS_CLUSTER_PWR_STATE(state) (state)->pwr_domain_state[ARM_PWR_LVL1] + +static inline unsigned int css_system_pwr_state(const psci_power_state_t *state) +{ +#if (PLAT_MAX_PWR_LVL == CSS_SYSTEM_PWR_DMN_LVL) + return state->pwr_domain_state[CSS_SYSTEM_PWR_DMN_LVL]; +#else + return 0; +#endif +} + +int css_pwr_domain_on(u_register_t mpidr); +void css_pwr_domain_on_finish(const psci_power_state_t *target_state); +void css_pwr_domain_on_finish_late(const psci_power_state_t *target_state); +void css_pwr_domain_off(const psci_power_state_t *target_state); +void css_pwr_domain_suspend(const psci_power_state_t *target_state); +void css_pwr_domain_suspend_finish( + const psci_power_state_t *target_state); +void __dead2 css_system_off(void); +void __dead2 css_system_reset(void); +void css_cpu_standby(plat_local_state_t cpu_state); +void css_get_sys_suspend_power_state(psci_power_state_t *req_state); +int css_node_hw_state(u_register_t mpidr, unsigned int power_level); + +/* + * This mapping array has to be exported by the platform. Each element at + * a given index maps that core to an SCMI power domain. + */ +extern const uint32_t plat_css_core_pos_to_scmi_dmn_id_map[]; + +#define SCMI_DOMAIN_ID_MASK U(0xFFFF) +#define SCMI_CHANNEL_ID_MASK U(0xFFFF) +#define SCMI_CHANNEL_ID_SHIFT U(16) + +#define SET_SCMI_CHANNEL_ID(n) (((n) & SCMI_CHANNEL_ID_MASK) << \ + SCMI_CHANNEL_ID_SHIFT) +#define SET_SCMI_DOMAIN_ID(n) ((n) & SCMI_DOMAIN_ID_MASK) +#define GET_SCMI_CHANNEL_ID(n) (((n) >> SCMI_CHANNEL_ID_SHIFT) & \ + SCMI_CHANNEL_ID_MASK) +#define GET_SCMI_DOMAIN_ID(n) ((n) & SCMI_DOMAIN_ID_MASK) + +#endif /* CSS_PM_H */ diff --git a/arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h new file mode 100644 index 0000000..469928d --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_CSS_H +#define SOC_CSS_H + +/* + * Utility functions for ARM CSS SoCs + */ +void soc_css_init_nic400(void); +void soc_css_init_pcie(void); + +static inline void soc_css_security_setup(void) +{ + soc_css_init_nic400(); + soc_css_init_pcie(); +} + +#endif /* SOC_CSS_H */ diff --git a/arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h new file mode 100644 index 0000000..b4b6ba8 --- /dev/null +++ b/arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOC_CSS_DEF_H +#define SOC_CSS_DEF_H + +#include +#include + +/* + * Definitions common to all ARM CSS SoCs + */ + +/* Following covers ARM CSS SoC Peripherals and PCIe expansion area */ +#define SOC_CSS_DEVICE_BASE 0x40000000 +#define SOC_CSS_DEVICE_SIZE 0x40000000 +#define SOC_CSS_PCIE_CONTROL_BASE 0x7ff20000 + +/* PL011 UART related constants */ +#define SOC_CSS_UART0_BASE 0x7ff80000 +#define SOC_CSS_UART1_BASE 0x7ff70000 + +#define SOC_CSS_UART0_CLK_IN_HZ 7372800 +#define SOC_CSS_UART1_CLK_IN_HZ 7372800 + +/* SoC NIC-400 Global Programmers View (GPV) */ +#define SOC_CSS_NIC400_BASE 0x7fd00000 + +#define SOC_CSS_NIC400_USB_EHCI 0 +#define SOC_CSS_NIC400_TLX_MASTER 1 +#define SOC_CSS_NIC400_USB_OHCI 2 +#define SOC_CSS_NIC400_PL354_SMC 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 4 + +/* Non-volatile counters */ +#define SOC_TRUSTED_NVCTR_BASE 0x7fe70000 +#define TFW_NVCTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0000) +#define TFW_NVCTR_SIZE 4 +#define NTFW_CTR_BASE (SOC_TRUSTED_NVCTR_BASE + 0x0004) +#define NTFW_CTR_SIZE 4 + +/* Keys */ +#define SOC_KEYS_BASE 0x7fe80000 +#define TZ_PUB_KEY_HASH_BASE (SOC_KEYS_BASE + 0x0000) +#define TZ_PUB_KEY_HASH_SIZE 32 +#define HU_KEY_BASE (SOC_KEYS_BASE + 0x0020) +#define HU_KEY_SIZE 16 +#define END_KEY_BASE (SOC_KEYS_BASE + 0x0044) +#define END_KEY_SIZE 32 + +#define SOC_CSS_MAP_DEVICE MAP_REGION_FLAT( \ + SOC_CSS_DEVICE_BASE, \ + SOC_CSS_DEVICE_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 5 +#define SOC_CSS_NIC400_BOOTSEC_BRIDGE_UART1 (1 << 12) + +/* + * Required platform porting definitions common to all ARM CSS SoCs + */ +#if JUNO_AARCH32_EL3_RUNTIME +/* + * Following change is required to initialize TZC + * for enabling access to the HI_VECTOR (0xFFFF0000) + * location needed for JUNO AARCH32 support. + */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x8000) +#else +/* 2MB used for SCP DDR retraining */ +#define PLAT_ARM_SCP_TZC_DRAM1_SIZE ULL(0x00200000) +#endif + +#endif /* SOC_CSS_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h b/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h new file mode 100644 index 0000000..7b653d8 --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/bcm_console.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2018-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_CONSOLE_H +#define BCM_CONSOLE_H + +void bcm_console_boot_init(void); +void bcm_console_boot_end(void); +void bcm_console_runtime_init(void); +void bcm_console_runtime_end(void); + +#endif /* BCM_CONSOLE_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h b/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h new file mode 100644 index 0000000..ea4b169 --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2018 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BCM_ELOG_H +#define BCM_ELOG_H + +#ifndef __ASSEMBLER__ + +#include + +#if defined(BCM_ELOG) && (defined(IMAGE_BL2) || defined(IMAGE_BL31)) +int bcm_elog_init(void *base, uint32_t size, unsigned int level); +void bcm_elog_exit(void); +int bcm_elog_copy_log(void *dst, uint32_t max_size); +void bcm_elog(const char *fmt, ...); +#else +static inline int bcm_elog_init(void *base, uint32_t size, + unsigned int level) +{ + return 0; +} +static inline void bcm_elog_exit(void) +{ +} +static inline int bcm_elog_copy_log(void *dst, uint32_t max_size) +{ + return 0; +} +static inline void bcm_elog(const char *fmt, ...) +{ +} +#endif /* BCM_ELOG */ + +#endif /* __ASSEMBLER__ */ +#endif /* BCM_ELOG_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h b/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h new file mode 100644 index 0000000..c9137bc --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/brcm_def.h @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BRCM_DEF_H +#define BRCM_DEF_H + +#include +#include +#include +#include +#include + +#include + +#define PLAT_PHY_ADDR_SPACE_SIZE BIT_64(32) +#define PLAT_VIRT_ADDR_SPACE_SIZE BIT_64(32) + +#define BL11_DAUTH_ID 0x796C51ab +#define BL11_DAUTH_BASE BL11_RW_BASE + +/* We keep a table at the end of ROM for function pointers */ +#define ROM_TABLE_SIZE 32 +#define BL1_ROM_TABLE (BL1_RO_LIMIT - ROM_TABLE_SIZE) + +/* + * The top 16MB of DRAM1 is configured as secure access only using the TZC + * - SCP TZC DRAM: If present, DRAM reserved for SCP use + * - AP TZC DRAM: The remaining TZC secured DRAM reserved for AP use + */ +#define BRCM_TZC_DRAM1_SIZE ULL(0x01000000) + +#define BRCM_SCP_TZC_DRAM1_BASE (BRCM_DRAM1_BASE + \ + BRCM_DRAM1_SIZE - \ + BRCM_SCP_TZC_DRAM1_SIZE) +#define BRCM_SCP_TZC_DRAM1_SIZE PLAT_BRCM_SCP_TZC_DRAM1_SIZE + +#define BRCM_AP_TZC_DRAM1_BASE (BRCM_DRAM1_BASE + \ + BRCM_DRAM1_SIZE - \ + BRCM_TZC_DRAM1_SIZE) +#define BRCM_AP_TZC_DRAM1_SIZE (BRCM_TZC_DRAM1_SIZE - \ + BRCM_SCP_TZC_DRAM1_SIZE) + +#define BRCM_NS_DRAM1_BASE BRCM_DRAM1_BASE +#define BRCM_NS_DRAM1_SIZE (BRCM_DRAM1_SIZE - \ + BRCM_TZC_DRAM1_SIZE) + +#ifdef BRCM_SHARED_DRAM_BASE +#define BRCM_NS_SHARED_DRAM_BASE BRCM_SHARED_DRAM_BASE +#define BRCM_NS_SHARED_DRAM_SIZE BRCM_SHARED_DRAM_SIZE +#endif + +#define BRCM_MAP_SHARED_RAM MAP_REGION_FLAT( \ + BRCM_SHARED_RAM_BASE, \ + BRCM_SHARED_RAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define BRCM_MAP_NS_DRAM1 MAP_REGION_FLAT( \ + BRCM_NS_DRAM1_BASE, \ + BRCM_NS_DRAM1_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +#ifdef BRCM_SHARED_DRAM_BASE +#define BRCM_MAP_NS_SHARED_DRAM MAP_REGION_FLAT( \ + BRCM_NS_SHARED_DRAM_BASE, \ + BRCM_NS_SHARED_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) +#endif + +#ifdef BRCM_EXT_SRAM_BASE +#define BRCM_MAP_EXT_SRAM MAP_REGION_FLAT( \ + BRCM_EXT_SRAM_BASE, \ + BRCM_EXT_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#define BRCM_MAP_NAND_RO MAP_REGION_FLAT(NAND_BASE_ADDR,\ + NAND_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define BRCM_MAP_QSPI_RO MAP_REGION_FLAT(QSPI_BASE_ADDR,\ + QSPI_SIZE, \ + MT_MEMORY | MT_RO | MT_SECURE) + +#define HSLS_REGION MAP_REGION_FLAT(HSLS_BASE_ADDR, \ + HSLS_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define CCN_REGION MAP_REGION_FLAT(PLAT_BRCM_CCN_BASE, \ + CCN_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +#define GIC500_REGION MAP_REGION_FLAT(GIC500_BASE, \ + GIC500_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#ifdef PERIPH0_BASE +#define PERIPH0_REGION MAP_REGION_FLAT(PERIPH0_BASE, \ + PERIPH0_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef PERIPH1_BASE +#define PERIPH1_REGION MAP_REGION_FLAT(PERIPH1_BASE, \ + PERIPH1_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef PERIPH2_BASE +#define PERIPH2_REGION MAP_REGION_FLAT(PERIPH2_BASE, \ + PERIPH2_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#if BRCM_BL31_IN_DRAM +#if IMAGE_BL2 +#define BRCM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_BRCM_MAX_BL31_SIZE,\ + MT_DEVICE | MT_RW | MT_SECURE) +#else +#define BRCM_MAP_BL31_SEC_DRAM MAP_REGION_FLAT( \ + BL31_BASE, \ + PLAT_BRCM_MAX_BL31_SIZE,\ + MT_MEMORY | MT_RW | MT_SECURE) +#endif +#endif + +#if defined(USB_BASE) && defined(DRIVER_USB_ENABLE) +#define USB_REGION MAP_REGION_FLAT( \ + USB_BASE, \ + USB_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif + +#ifdef USE_CRMU_SRAM +#define CRMU_SRAM_REGION MAP_REGION_FLAT( \ + CRMU_SRAM_BASE, \ + CRMU_SRAM_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) +#endif +/* + * 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 BRCM_BL_REGIONS 3 +#else +#define BRCM_BL_REGIONS 2 +#endif + +#endif /* BRCM_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h b/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h new file mode 100644 index 0000000..66ed2cb --- /dev/null +++ b/arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_BRCM_H +#define PLAT_BRCM_H + +#include + +#include +#include +#include + +#include + +struct image_info; + +/* Global variables */ +extern const mmap_region_t plat_brcm_mmap[]; + +uint32_t brcm_get_spsr_for_bl32_entry(void); +uint32_t brcm_get_spsr_for_bl33_entry(void); +const mmap_region_t *plat_brcm_get_mmap(void); +int bcm_bl2_handle_scp_bl2(struct image_info *image_info); +unsigned int plat_brcm_calc_core_pos(u_register_t mpidr); +void plat_brcm_gic_driver_init(void); +void plat_brcm_gic_init(void); +void plat_brcm_gic_cpuif_enable(void); +void plat_brcm_gic_cpuif_disable(void); +void plat_brcm_gic_pcpu_init(void); +void plat_brcm_gic_redistif_on(void); +void plat_brcm_gic_redistif_off(void); +void plat_brcm_interconnect_init(void); +void plat_brcm_interconnect_enter_coherency(void); +void plat_brcm_interconnect_exit_coherency(void); +void plat_brcm_io_setup(void); +void plat_brcm_process_flags(uint16_t plat_toc_flags); + +#endif /* PLAT_BRCM_H */ diff --git a/arm-trusted-firmware/include/plat/common/common_def.h b/arm-trusted-firmware/include/plat/common/common_def.h new file mode 100644 index 0000000..1d3ac15 --- /dev/null +++ b/arm-trusted-firmware/include/plat/common/common_def.h @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef COMMON_DEF_H +#define COMMON_DEF_H + +#include +#include +#include + +#include + +#define SZ_32 U(0x00000020) +#define SZ_64 U(0x00000040) +#define SZ_128 U(0x00000080) +#define SZ_256 U(0x00000100) +#define SZ_512 U(0x00000200) + +#define SZ_1K U(0x00000400) +#define SZ_2K U(0x00000800) +#define SZ_4K U(0x00001000) +#define SZ_8K U(0x00002000) +#define SZ_16K U(0x00004000) +#define SZ_32K U(0x00008000) +#define SZ_64K U(0x00010000) +#define SZ_128K U(0x00020000) +#define SZ_256K U(0x00040000) +#define SZ_512K U(0x00080000) + +#define SZ_1M U(0x00100000) +#define SZ_2M U(0x00200000) +#define SZ_4M U(0x00400000) +#define SZ_8M U(0x00800000) +#define SZ_16M U(0x01000000) +#define SZ_32M U(0x02000000) +#define SZ_64M U(0x04000000) +#define SZ_128M U(0x08000000) +#define SZ_256M U(0x10000000) +#define SZ_512M U(0x20000000) + +#define SZ_1G U(0x40000000) +#define SZ_2G U(0x80000000) + +/****************************************************************************** + * Required platform porting definitions that are expected to be common to + * all platforms + *****************************************************************************/ + +/* + * 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__ */ + +/* + * Generic platform constants + */ +#define FIRMWARE_WELCOME_STR "Booting Trusted Firmware\n" + +#define BL2_IMAGE_DESC { \ + .image_id = BL2_IMAGE_ID, \ + SET_STATIC_PARAM_HEAD(image_info, PARAM_EP, \ + VERSION_2, image_info_t, 0), \ + .image_info.image_base = BL2_BASE, \ + .image_info.image_max_size = BL2_LIMIT - BL2_BASE,\ + SET_STATIC_PARAM_HEAD(ep_info, PARAM_EP, \ + VERSION_2, entry_point_info_t, SECURE | EXECUTABLE),\ + .ep_info.pc = BL2_BASE, \ +} + +/* + * The following constants identify the extents of the code & read-only data + * regions. These addresses are used by the MMU setup code and therefore they + * must be page-aligned. + * + * When the code and read-only data are mapped as a single atomic section + * (i.e. when SEPARATE_CODE_AND_RODATA=0) then we treat the whole section as + * code by specifying the read-only data section as empty. + * + * BL1 is different than the other images in the sense that its read-write data + * originally lives in Trusted ROM and needs to be relocated in Trusted SRAM at + * run-time. Therefore, the read-write data in ROM can be mapped with the same + * memory attributes as the read-only data region. For this reason, BL1 uses + * different macros. + * + * Note that BL1_ROM_END is not necessarily aligned on a page boundary as it + * just points to the end of BL1's actual content in Trusted ROM. Therefore it + * needs to be rounded up to the next page size in order to map the whole last + * page of it with the right memory attributes. + */ +#if SEPARATE_CODE_AND_RODATA + +#define BL1_CODE_END BL_CODE_END +#define BL1_RO_DATA_BASE BL_RO_DATA_BASE +#define BL1_RO_DATA_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_CODE_END BL_CODE_END +#define BL2_RO_DATA_BASE BL_RO_DATA_BASE +#define BL2_RO_DATA_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ +#else +#define BL_RO_DATA_BASE UL(0) +#define BL_RO_DATA_END UL(0) +#define BL1_CODE_END round_up(BL1_ROM_END, PAGE_SIZE) +#if BL2_IN_XIP_MEM +#define BL2_RO_DATA_BASE UL(0) +#define BL2_RO_DATA_END UL(0) +#define BL2_CODE_END round_up(BL2_ROM_END, PAGE_SIZE) +#endif /* BL2_IN_XIP_MEM */ +#endif /* SEPARATE_CODE_AND_RODATA */ + +#if MEASURED_BOOT +/* + * Start critical data Ids from 2^32/2 reserving Ids from 0 to (2^32/2 - 1) + * for Images, It is a critical data Id base for all platforms. + */ +#define CRITICAL_DATA_ID_BASE U(0x80000000) +#endif /* MEASURED_BOOT */ + +#endif /* COMMON_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/common/plat_trng.h b/arm-trusted-firmware/include/plat/common/plat_trng.h new file mode 100644 index 0000000..a9f73b6 --- /dev/null +++ b/arm-trusted-firmware/include/plat/common/plat_trng.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_TRNG_H +#define PLAT_TRNG_H + +#include + +/* TRNG platform functions */ + +extern uuid_t plat_trng_uuid; +void plat_entropy_setup(void); +bool plat_get_entropy(uint64_t *out); + +#endif /* PLAT_TRNG_H */ diff --git a/arm-trusted-firmware/include/plat/common/platform.h b/arm-trusted-firmware/include/plat/common/platform.h new file mode 100644 index 0000000..7664509 --- /dev/null +++ b/arm-trusted-firmware/include/plat/common/platform.h @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_H +#define PLATFORM_H + +#include + +#include +#if defined(SPD_spmd) + #include +#endif +#if TRNG_SUPPORT +#include "plat_trng.h" +#endif +#include + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct auth_img_desc_s; +struct meminfo; +struct image_info; +struct entry_point_info; +struct image_desc; +struct bl_load_info; +struct bl_params; +struct mmap_region; +struct spm_mm_boot_info; +struct sp_res_desc; +enum fw_enc_status_t; + +/******************************************************************************* + * plat_get_rotpk_info() flags + ******************************************************************************/ +#define ROTPK_IS_HASH (1 << 0) +/* Flag used to skip verification of the certificate ROTPK while the platform + ROTPK is not deployed */ +#define ROTPK_NOT_DEPLOYED (1 << 1) + +/******************************************************************************* + * plat_get_enc_key_info() flags + ******************************************************************************/ +/* + * Flag used to notify caller that information provided in key buffer is an + * identifier rather than an actual key. + */ +#define ENC_KEY_IS_IDENTIFIER (1 << 0) + +/******************************************************************************* + * Function declarations + ******************************************************************************/ +/******************************************************************************* + * Mandatory common functions + ******************************************************************************/ +unsigned int plat_get_syscnt_freq2(void); + +int plat_get_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +uintptr_t plat_get_ns_image_entrypoint(void); +unsigned int plat_my_core_pos(void); +int plat_core_pos_by_mpidr(u_register_t mpidr); +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size); + +#if STACK_PROTECTOR_ENABLED +/* + * Return a new value to be used for the stack protection's canary. + * + * Ideally, this value is a random number that is impossible to predict by an + * attacker. + */ +u_register_t plat_get_stack_protector_canary(void); +#endif /* STACK_PROTECTOR_ENABLED */ + +/******************************************************************************* + * Mandatory interrupt management functions + ******************************************************************************/ +uint32_t plat_ic_get_pending_interrupt_id(void); +uint32_t plat_ic_get_pending_interrupt_type(void); +uint32_t plat_ic_acknowledge_interrupt(void); +uint32_t plat_ic_get_interrupt_type(uint32_t id); +void plat_ic_end_of_interrupt(uint32_t id); +uint32_t plat_interrupt_type_to_line(uint32_t type, + uint32_t security_state); + +/******************************************************************************* + * Optional interrupt management functions, depending on chosen EL3 components. + ******************************************************************************/ +unsigned int plat_ic_get_running_priority(void); +int plat_ic_is_spi(unsigned int id); +int plat_ic_is_ppi(unsigned int id); +int plat_ic_is_sgi(unsigned int id); +unsigned int plat_ic_get_interrupt_active(unsigned int id); +void plat_ic_disable_interrupt(unsigned int id); +void plat_ic_enable_interrupt(unsigned int id); +int plat_ic_has_interrupt_type(unsigned int type); +void plat_ic_set_interrupt_type(unsigned int id, unsigned int type); +void plat_ic_set_interrupt_priority(unsigned int id, unsigned int priority); +void plat_ic_raise_el3_sgi(int sgi_num, u_register_t target); +void plat_ic_set_spi_routing(unsigned int id, unsigned int routing_mode, + u_register_t mpidr); +void plat_ic_set_interrupt_pending(unsigned int id); +void plat_ic_clear_interrupt_pending(unsigned int id); +unsigned int plat_ic_set_priority_mask(unsigned int mask); +unsigned int plat_ic_get_interrupt_id(unsigned int raw); + +/******************************************************************************* + * Optional common functions (may be overridden) + ******************************************************************************/ +uintptr_t plat_get_my_stack(void); +void plat_report_exception(unsigned int exception_type); +int plat_crash_console_init(void); +int plat_crash_console_putc(int c); +void plat_crash_console_flush(void); +void plat_error_handler(int err) __dead2; +void plat_panic_handler(void) __dead2; +const char *plat_log_get_prefix(unsigned int log_level); +void bl2_plat_preload_setup(void); +int plat_try_next_boot_source(void); + +#if MEASURED_BOOT +int plat_mboot_measure_image(unsigned int image_id, image_info_t *image_data); +int plat_mboot_measure_critical_data(unsigned int critical_data_id, + const void *base, + size_t size); +#else +static inline int plat_mboot_measure_image(unsigned int image_id __unused, + image_info_t *image_data __unused) +{ + return 0; +} +static inline int plat_mboot_measure_critical_data( + unsigned int critical_data_id __unused, + const void *base __unused, + size_t size __unused) +{ + return 0; +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * Mandatory BL1 functions + ******************************************************************************/ +void bl1_early_platform_setup(void); +void bl1_plat_arch_setup(void); +void bl1_platform_setup(void); +struct meminfo *bl1_plat_sec_mem_layout(void); + +/******************************************************************************* + * Optional EL3 component functions in BL31 + ******************************************************************************/ + +/* SDEI platform functions */ +#if SDEI_SUPPORT +void plat_sdei_setup(void); +int plat_sdei_validate_entry_point(uintptr_t ep, unsigned int client_mode); +void plat_sdei_handle_masked_trigger(uint64_t mpidr, unsigned int intr); +#endif + +void plat_default_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags); + +/* + * The following function is mandatory when the + * firmware update feature is used. + */ +int bl1_plat_mem_check(uintptr_t mem_base, unsigned int mem_size, + unsigned int flags); + +/******************************************************************************* + * Optional BL1 functions (may be overridden) + ******************************************************************************/ +/* + * The following functions are used for image loading process in BL1. + */ +void bl1_plat_set_ep_info(unsigned int image_id, + struct entry_point_info *ep_info); +/* + * The following functions are mandatory when firmware update + * feature is used and optional otherwise. + */ +unsigned int bl1_plat_get_next_image_id(void); +struct image_desc *bl1_plat_get_image_desc(unsigned int image_id); + +/* + * The following functions are used by firmware update + * feature and may optionally be overridden. + */ +__dead2 void bl1_plat_fwu_done(void *client_cookie, void *reserved); + +/* + * This BL1 function can be used by the platforms to update/use image + * information for a given `image_id`. + */ +int bl1_plat_handle_pre_image_load(unsigned int image_id); +int bl1_plat_handle_post_image_load(unsigned int image_id); + +#if MEASURED_BOOT +void bl1_plat_mboot_init(void); +void bl1_plat_mboot_finish(void); +#else +static inline void bl1_plat_mboot_init(void) +{ +} +static inline void bl1_plat_mboot_finish(void) +{ +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * Mandatory BL2 functions + ******************************************************************************/ +void bl2_early_platform_setup2(u_register_t arg0, u_register_t arg1, u_register_t arg2, u_register_t arg3); +void bl2_plat_arch_setup(void); +void bl2_platform_setup(void); +struct meminfo *bl2_plat_sec_mem_layout(void); + +/* + * 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); +int bl2_plat_handle_post_image_load(unsigned int image_id); + +/******************************************************************************* + * Optional BL2 functions (may be overridden) + ******************************************************************************/ +#if MEASURED_BOOT +void bl2_plat_mboot_init(void); +void bl2_plat_mboot_finish(void); +#else +static inline void bl2_plat_mboot_init(void) +{ +} +static inline void bl2_plat_mboot_finish(void) +{ +} +#endif /* MEASURED_BOOT */ + +/******************************************************************************* + * Mandatory BL2 at EL3 functions: Must be implemented if BL2_AT_EL3 image is + * supported + ******************************************************************************/ +void bl2_el3_early_platform_setup(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void bl2_el3_plat_arch_setup(void); + +/******************************************************************************* + * Optional BL2 at EL3 functions (may be overridden) + ******************************************************************************/ +void bl2_el3_plat_prepare_exit(void); + +/******************************************************************************* + * Mandatory BL2U functions. + ******************************************************************************/ +void bl2u_early_platform_setup(struct meminfo *mem_layout, + void *plat_info); +void bl2u_plat_arch_setup(void); +void bl2u_platform_setup(void); + +/******************************************************************************* + * Conditionally mandatory BL2U functions for CSS platforms. + ******************************************************************************/ +/* + * This function is used to perform any platform-specific actions required to + * handle the BL2U_SCP firmware. + */ +int bl2u_plat_handle_scp_bl2u(void); + +/******************************************************************************* + * Mandatory BL31 functions + ******************************************************************************/ +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3); +void bl31_plat_arch_setup(void); +void bl31_platform_setup(void); +void bl31_plat_runtime_setup(void); +struct entry_point_info *bl31_plat_get_next_image_ep_info(uint32_t type); + +/******************************************************************************* + * Mandatory PSCI functions (BL31) + ******************************************************************************/ +int plat_setup_psci_ops(uintptr_t sec_entrypoint, + const struct plat_psci_ops **psci_ops); +const unsigned char *plat_get_power_domain_tree_desc(void); + +/******************************************************************************* + * Optional PSCI functions (BL31). + ******************************************************************************/ +void plat_psci_stat_accounting_start(const psci_power_state_t *state_info); +void plat_psci_stat_accounting_stop(const psci_power_state_t *state_info); +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 plat_get_target_pwr_state(unsigned int lvl, + const plat_local_state_t *states, + unsigned int ncpu); + +/******************************************************************************* + * Mandatory BL31 functions when ENABLE_RME=1 + ******************************************************************************/ +int plat_get_cca_attest_token(uintptr_t buf, size_t *len, + uintptr_t hash, size_t hash_size); +int plat_get_cca_realm_attest_key(uintptr_t buf, size_t *len, + unsigned int type); + +/******************************************************************************* + * Optional BL31 functions (may be overridden) + ******************************************************************************/ +void bl31_plat_enable_mmu(uint32_t flags); + +/******************************************************************************* + * Optional BL32 functions (may be overridden) + ******************************************************************************/ +void bl32_plat_enable_mmu(uint32_t flags); + +/******************************************************************************* + * Trusted Board Boot functions + ******************************************************************************/ +int plat_get_rotpk_info(void *cookie, void **key_ptr, unsigned int *key_len, + unsigned int *flags); +int plat_get_nv_ctr(void *cookie, unsigned int *nv_ctr); +int plat_set_nv_ctr(void *cookie, unsigned int nv_ctr); +int plat_set_nv_ctr2(void *cookie, const struct auth_img_desc_s *img_desc, + unsigned int nv_ctr); +int get_mbedtls_heap_helper(void **heap_addr, size_t *heap_size); +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); + +/******************************************************************************* + * Secure Partitions functions + ******************************************************************************/ +const struct mmap_region *plat_get_secure_partition_mmap(void *cookie); +const struct spm_mm_boot_info *plat_get_secure_partition_boot_info( + void *cookie); +int plat_spm_sp_rd_load(struct sp_res_desc *rd, const void *ptr, size_t size); +int plat_spm_sp_get_next_address(void **sp_base, size_t *sp_size, + void **rd_base, size_t *rd_size); +#if defined(SPD_spmd) +int plat_spm_core_manifest_load(spmc_manifest_attribute_t *manifest, + const void *pm_addr); +#endif +/******************************************************************************* + * Mandatory BL image load functions(may be overridden). + ******************************************************************************/ +/* + * This function returns pointer to the list of images that the + * platform has populated to load. + */ +struct bl_load_info *plat_get_bl_image_load_info(void); + +/* + * This function returns a pointer to the shared memory that the + * platform has kept aside to pass trusted firmware related + * information that next BL image could need. + */ +struct bl_params *plat_get_next_bl_params(void); + +/* + * This function flushes to main memory all the params that are + * passed to next image. + */ +void plat_flush_next_bl_params(void); + +/* + * The below function enable Trusted Firmware components like SPDs which + * haven't migrated to the new platform API to compile on platforms which + * have the compatibility layer disabled. + */ +unsigned int platform_core_pos_helper(unsigned long mpidr); + +/* + * Optional function to get SOC version + */ +int32_t plat_get_soc_version(void); + +/* + * Optional function to get SOC revision + */ +int32_t plat_get_soc_revision(void); + +/* + * Optional function to check for SMCCC function availability for platform + */ +int32_t plat_is_smccc_feature_available(u_register_t fid); + +/******************************************************************************* + * FWU platform specific functions + ******************************************************************************/ +int plat_fwu_set_metadata_image_source(unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +void plat_fwu_set_images_source(const struct fwu_metadata *metadata); +uint32_t plat_fwu_get_boot_idx(void); + +#endif /* PLATFORM_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h new file mode 100644 index 0000000..c6953fb --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h @@ -0,0 +1,17 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef ARMADA_COMMON_H +#define ARMADA_COMMON_H + +#include + +#include + +int marvell_get_io_dec_win_conf(struct dec_win_config **win, uint32_t *size); + +#endif /* ARMADA_COMMON_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h new file mode 100644 index 0000000..bc3e04f --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef BOARD_MARVELL_DEF_H +#define BOARD_MARVELL_DEF_H + +/* + * Required platform porting definitions common to all ARM + * development platforms + */ + +/* Size of cacheable stacks */ +#if IMAGE_BL1 +#if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +#else +# define PLATFORM_STACK_SIZE 0x440 +#endif +#elif IMAGE_BL2 +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif IMAGE_BL31 +# define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL32 +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/* + * PLAT_MARVELL_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BLE +# define PLAT_MARVELL_MMAP_ENTRIES 3 +#endif +#if IMAGE_BL1 +# if TRUSTED_BOARD_BOOT +# define PLAT_MARVELL_MMAP_ENTRIES 7 +# else +# define PLAT_MARVELL_MMAP_ENTRIES 6 +# endif /* TRUSTED_BOARD_BOOT */ +#endif +#if IMAGE_BL2 +# define PLAT_MARVELL_MMAP_ENTRIES 8 +#endif +#if IMAGE_BL31 +#define PLAT_MARVELL_MMAP_ENTRIES 5 +#endif + +/* + * Platform specific page table and MMU setup constants + */ +#if IMAGE_BL1 +#define MAX_XLAT_TABLES 4 +#elif IMAGE_BLE +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL2 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL31 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL32 +# define MAX_XLAT_TABLES 4 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +#endif /* BOARD_MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h new file mode 100644 index 0000000..1394c05 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h @@ -0,0 +1,188 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_DEF_H +#define MARVELL_DEF_H + +#include + +#include +#include +#include +#include + +/**************************************************************************** + * Definitions common to all MARVELL standard platforms + **************************************************************************** + */ +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define MARVELL_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define PLAT_MARVELL_NORTHB_COUNT 1 + +#define PLAT_MARVELL_CLUSTER_COUNT 1 + +#define MARVELL_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to MARVELL Platform Power levels. + * The power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define MARVELL_PWR_LVL0 MPIDR_AFFLVL0 +#define MARVELL_PWR_LVL1 MPIDR_AFFLVL1 +#define MARVELL_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in Marvell platforms encoded by State-ID field + * within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define MARVELL_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define MARVELL_LOCAL_STATE_RET 1 +/* Local power state for OFF/power-down. + * Valid for CPU and cluster power domains + */ +#define MARVELL_LOCAL_STATE_OFF 2 + +/* This leaves a gap between end of DRAM and start of ROM block */ +#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */ + +/* The first 4KB of Trusted SRAM are used as shared memory */ +#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE +#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \ + MARVELL_SHARED_RAM_SIZE) +#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \ + MARVELL_SHARED_RAM_SIZE) + +#define MARVELL_DRAM_BASE ULL(0x0) +#define MARVELL_DRAM_SIZE ULL(0x20000000) +#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \ + MARVELL_DRAM_SIZE - 1) + +#define MARVELL_IRQ_SEC_PHY_TIMER 29 + +#define MARVELL_IRQ_SEC_SGI_0 8 +#define MARVELL_IRQ_SEC_SGI_1 9 +#define MARVELL_IRQ_SEC_SGI_2 10 +#define MARVELL_IRQ_SEC_SGI_3 11 +#define MARVELL_IRQ_SEC_SGI_4 12 +#define MARVELL_IRQ_SEC_SGI_5 13 +#define MARVELL_IRQ_SEC_SGI_6 14 +#define MARVELL_IRQ_SEC_SGI_7 15 + +#define MARVELL_MAP_SHARED_RAM MAP_REGION_FLAT( \ + MARVELL_SHARED_RAM_BASE, \ + MARVELL_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MARVELL_MAP_DRAM MAP_REGION_FLAT( \ + MARVELL_DRAM_BASE, \ + MARVELL_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * 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 MARVELL_BL_REGIONS 3 +#else +#define MARVELL_BL_REGIONS 2 +#endif + +#define MAX_MMAP_REGIONS (PLAT_MARVELL_MMAP_ENTRIES + \ + MARVELL_BL_REGIONS) + +#define MARVELL_CONSOLE_BAUDRATE 115200 + +/**************************************************************************** + * Required platform porting definitions common to all MARVELL std. platforms + **************************************************************************** + */ +#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 MARVELL_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 MARVELL_LOCAL_STATE_OFF + + +#define PLATFORM_CORE_COUNT PLAT_MARVELL_CLUSTER_CORE_COUNT + +/* + * 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 << MARVELL_CACHE_WRITEBACK_SHIFT) + + +/***************************************************************************** + * 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 PLAT_MARVELL_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_MARVELL_TRUSTED_ROM_BASE \ + + PLAT_MARVELL_TRUSTED_ROM_SIZE) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVELL_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (MARVELL_BL_RAM_BASE + MARVELL_BL_RAM_SIZE) + +/***************************************************************************** + * BL2 specific defines. + ***************************************************************************** + */ +/* + * Put BL2 just below BL31. + */ +#define BL2_BASE (BL31_BASE - PLAT_MARVELL_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/***************************************************************************** + * BL31 specific defines. + ***************************************************************************** + */ +/* + * Put BL31 at the top of the Trusted SRAM. + */ +#define BL31_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVEL_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE +#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE) + +/***************************************************************************** + * BL32 specific defines. + ***************************************************************************** + */ +#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE +#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +#endif /* MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h new file mode 100644 index 0000000..cb31481 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2016 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MARVELL_H +#define PLAT_MARVELL_H + +#include + +#include +#include +#include +#include + +/* + * Extern declarations common to Marvell standard platforms + */ +extern const mmap_region_t plat_marvell_mmap[]; + +#define MARVELL_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_marvell_mmap) + MARVELL_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions) + +/* + * Utility functions common to Marvell standard platforms + */ +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 +); + +/* Console utility functions */ +void marvell_console_boot_init(void); +void marvell_console_boot_end(void); +void marvell_console_runtime_init(void); +void marvell_console_runtime_end(void); + +/* IO storage utility functions */ +void marvell_io_setup(void); + +/* Systimer utility function */ +void marvell_configure_sys_timer(void); + +/* Topology utility function */ +int marvell_check_mpidr(u_register_t mpidr); + +/* BL1 utility functions */ +void marvell_bl1_early_platform_setup(void); +void marvell_bl1_platform_setup(void); +void marvell_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void marvell_bl2_early_platform_setup(meminfo_t *mem_layout); +void marvell_bl2_platform_setup(void); +void marvell_bl2_plat_arch_setup(void); +uint32_t marvell_get_spsr_for_bl32_entry(void); +uint32_t marvell_get_spsr_for_bl33_entry(void); + +/* BL31 utility functions */ +void marvell_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2); +void marvell_bl31_platform_setup(void); +void marvell_bl31_plat_runtime_setup(void); +void marvell_bl31_plat_arch_setup(void); + +/* FIP TOC validity check */ +int marvell_io_is_toc_valid(void); + +/* + * PSCI functionality + */ +void marvell_psci_arch_init(int idx); +void plat_marvell_system_reset(void); + +/* + * Optional functions required in Marvell standard platforms + */ +void plat_marvell_io_setup(void); +int plat_marvell_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_marvell_calc_core_pos(u_register_t mpidr); + +void plat_marvell_interconnect_init(void); +void plat_marvell_interconnect_enter_coherency(void); + +const mmap_region_t *plat_marvell_get_mmap(void); + +uint32_t get_ref_clk(void); + +#endif /* PLAT_MARVELL_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h new file mode 100644 index 0000000..709d009 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef ARMADA_COMMON_H +#define ARMADA_COMMON_H + +#include +#include +#include +#include + +/* + * This struct supports skip image request + * detection_method: the method used to detect the request "signal". + * info: + * GPIO: + * detection_method: HIGH (pressed button), LOW (unpressed button), + * num (button mpp number). + * i2c: + * i2c_addr: the address of the i2c chosen. + * i2d_reg: the i2c register chosen. + * test: + * choose the DIE you picked the button in (AP or CP). + * in case of CP(cp_index = 0 if CP0, cp_index = 1 if CP1) + */ +struct skip_image { + enum { + GPIO, + I2C, + USER_DEFINED + } detection_method; + + struct { + struct { + int num; + enum { + HIGH, + LOW + } button_state; + + } gpio; + + struct { + int i2c_addr; + int i2c_reg; + } i2c; + + struct { + enum { + CP, + AP + } cp_ap; + int cp_index; + } test; + } info; +}; + +/* + * This struct supports SoC power off method + * type: the method used to power off the SoC + * cfg: + * PMIC_GPIO: + * pin_count: current GPIO pin number used for toggling the signal for + * notifying external PMIC + * info: holds the GPIOs information, CP GPIO should be used and + * all GPIOs should be within same GPIO config. register + * step_count: current step number to toggle the GPIO for PMIC + * seq: GPIO toggling values in sequence, each bit represents a GPIO. + * For example, bit0 represents first GPIO used for toggling + * the GPIO the last step is used to trigger the power off + * signal + * delay_ms: transition interval for the GPIO setting to take effect + * in unit of ms + */ +/* Max GPIO number used to notify PMIC to power off the SoC */ +#define PMIC_GPIO_MAX_NUMBER 8 +/* Max GPIO toggling steps in sequence to power off the SoC */ +#define PMIC_GPIO_MAX_TOGGLE_STEP 8 + +enum gpio_output_state { + GPIO_LOW = 0, + GPIO_HIGH +}; + +typedef struct gpio_info { + int cp_index; + int gpio_index; +} gpio_info_t; + +struct power_off_method { + enum { + PMIC_GPIO, + } type; + + struct { + struct { + int pin_count; + struct gpio_info info[PMIC_GPIO_MAX_NUMBER]; + int step_count; + uint32_t seq[PMIC_GPIO_MAX_TOGGLE_STEP]; + int delay_ms; + } gpio; + } cfg; +}; + +int marvell_gpio_config(void); +uint32_t marvell_get_io_win_gcr_target(int ap_idx); +uint32_t marvell_get_ccu_gcr_target(int ap_idx); + + +/* + * The functions below are defined as Weak and may be overridden + * in specific Marvell standard platform + */ +int marvell_get_amb_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base); +int marvell_get_io_win_memory_map(int ap_idx, struct addr_map_win **win, + uint32_t *size); +int marvell_get_iob_memory_map(struct addr_map_win **win, + uint32_t *size, uintptr_t base); +int marvell_get_ccu_memory_map(int ap_idx, struct addr_map_win **win, + uint32_t *size); +int system_power_off(void); + +#endif /* ARMADA_COMMON_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h new file mode 100644 index 0000000..7e90f5f --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef BOARD_MARVELL_DEF_H +#define BOARD_MARVELL_DEF_H + +/* + * Required platform porting definitions common to all ARM + * development platforms + */ + +/* Size of cacheable stacks */ +#if IMAGE_BL1 +#if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +#else +# define PLATFORM_STACK_SIZE 0x440 +#endif +#elif IMAGE_BL2 +# if TRUSTED_BOARD_BOOT +# define PLATFORM_STACK_SIZE 0x1000 +# else +# define PLATFORM_STACK_SIZE 0x400 +# endif +#elif IMAGE_BL31 +# define PLATFORM_STACK_SIZE 0x400 +#elif IMAGE_BL32 +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/* + * PLAT_MARVELL_MMAP_ENTRIES depends on the number of entries in the + * plat_arm_mmap array defined for each BL stage. + */ +#if IMAGE_BLE +# define PLAT_MARVELL_MMAP_ENTRIES 3 +#endif +#if IMAGE_BL1 +# if TRUSTED_BOARD_BOOT +# define PLAT_MARVELL_MMAP_ENTRIES 7 +# else +# define PLAT_MARVELL_MMAP_ENTRIES 6 +# endif /* TRUSTED_BOARD_BOOT */ +#endif +#if IMAGE_BL2 +# define PLAT_MARVELL_MMAP_ENTRIES 8 +#endif +#if IMAGE_BL31 +#define PLAT_MARVELL_MMAP_ENTRIES 5 +#endif + +/* + * Platform specific page table and MMU setup constants + */ +#if IMAGE_BL1 +#define MAX_XLAT_TABLES 4 +#elif IMAGE_BLE +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL2 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL31 +# define MAX_XLAT_TABLES 4 +#elif IMAGE_BL32 +# define MAX_XLAT_TABLES 4 +#endif + +#define MAX_IO_DEVICES 3 +#define MAX_IO_HANDLES 4 + +#endif /* BOARD_MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h new file mode 100644 index 0000000..ff1d4a3 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2021 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef EFUSE_DEF_H +#define EFUSE_DEF_H + +#include + +#define MVEBU_AP_EFUSE_SRV_CTRL_REG (MVEBU_AP_GEN_MGMT_BASE + 0x8) +#define EFUSE_SRV_CTRL_LD_SELECT_OFFS 6 +#define EFUSE_SRV_CTRL_LD_SELECT_MASK (1 << EFUSE_SRV_CTRL_LD_SELECT_OFFS) + +#define MVEBU_AP_LD_EFUSE_BASE (MVEBU_AP_GEN_MGMT_BASE + 0xF00) +/* Bits [31:0] - 32 data bits total */ +#define MVEBU_AP_LDX_31_0_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE) +/* Bits [62:32] - 31 data bits total 32nd bit is parity for bits [62:0]*/ +#define MVEBU_AP_LDX_62_32_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x4) +/* Bits [94:63] - 32 data bits total */ +#define MVEBU_AP_LDX_94_63_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x8) +/* Bits [125:95] - 31 data bits total, 32nd bit is parity for bits [125:63] */ +#define MVEBU_AP_LDX_125_95_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0xC) +/* Bits [157:126] - 32 data bits total */ +#define MVEBU_AP_LDX_126_157_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x10) +/* Bits [188:158] - 31 data bits total, 32nd bit is parity for bits [188:126] */ +#define MVEBU_AP_LDX_188_158_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x14) +/* Bits [220:189] - 32 data bits total */ +#define MVEBU_AP_LDX_220_189_EFUSE_OFFS (MVEBU_AP_LD_EFUSE_BASE + 0x18) + +#endif /* EFUSE_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h new file mode 100644 index 0000000..1245b88 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_DEF_H +#define MARVELL_DEF_H + +#include + +#include +#include +#include +#include + +/****************************************************************************** + * Definitions common to all MARVELL standard platforms + *****************************************************************************/ + +/* Special value used to verify platform parameters from BL2 to BL31 */ +#define MARVELL_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + + +#define MARVELL_CACHE_WRITEBACK_SHIFT 6 + +/* + * Macros mapping the MPIDR Affinity levels to MARVELL Platform Power levels. + * The power levels have a 1:1 mapping with the MPIDR affinity levels. + */ +#define MARVELL_PWR_LVL0 MPIDR_AFFLVL0 +#define MARVELL_PWR_LVL1 MPIDR_AFFLVL1 +#define MARVELL_PWR_LVL2 MPIDR_AFFLVL2 + +/* + * Macros for local power states in Marvell platforms encoded by + * State-ID field within the power-state parameter. + */ +/* Local power state for power domains in Run state. */ +#define MARVELL_LOCAL_STATE_RUN 0 +/* Local power state for retention. Valid only for CPU power domains */ +#define MARVELL_LOCAL_STATE_RET 1 +/* + * Local power state for OFF/power-down. Valid for CPU + * and cluster power domains + */ +#define MARVELL_LOCAL_STATE_OFF 2 + +/* This leaves a gap between end of DRAM and start of ROM block */ +#define MARVELL_TRUSTED_DRAM_SIZE 0x80000 /* 512 KB */ + +/* The first 4KB of Trusted SRAM are used as shared memory */ +#define MARVELL_SHARED_RAM_BASE PLAT_MARVELL_ATF_BASE +#define MARVELL_SHARED_RAM_SIZE 0x00001000 /* 4 KB */ + +/* The remaining Trusted SRAM is used to load the BL images */ +#define MARVELL_BL_RAM_BASE (MARVELL_SHARED_RAM_BASE + \ + MARVELL_SHARED_RAM_SIZE) +#define MARVELL_BL_RAM_SIZE (MARVELL_TRUSTED_DRAM_SIZE - \ + MARVELL_SHARED_RAM_SIZE) +/* Non-shared DRAM */ +#define MARVELL_DRAM_BASE ULL(0x0) +#define MARVELL_DRAM_SIZE ULL(0x80000000) +#define MARVELL_DRAM_END (MARVELL_DRAM_BASE + \ + MARVELL_DRAM_SIZE - 1) + +#define MARVELL_IRQ_PIC0 28 +#define MARVELL_IRQ_SEC_PHY_TIMER 29 + +#define MARVELL_IRQ_SEC_SGI_0 8 +#define MARVELL_IRQ_SEC_SGI_1 9 +#define MARVELL_IRQ_SEC_SGI_2 10 +#define MARVELL_IRQ_SEC_SGI_3 11 +#define MARVELL_IRQ_SEC_SGI_4 12 +#define MARVELL_IRQ_SEC_SGI_5 13 +#define MARVELL_IRQ_SEC_SGI_6 14 +#define MARVELL_IRQ_SEC_SGI_7 15 + +#ifdef SPD_opteed +/* + * BL2 needs to map 4MB at the end of TZC_DRAM1 in order to + * load/authenticate the trusted os extra image. The first 512KB of + * TZC_DRAM1 are reserved for trusted os (OPTEE). The extra image loading + * for OPTEE is paged image which only include the paging part using + * virtual memory but without "init" data. OPTEE will copy the "init" data + * (from pager image) to the first 512KB of TZC_DRAM, and then copy the + * extra image behind the "init" data. + */ +#define MARVELL_OPTEE_PAGEABLE_LOAD_BASE \ + (PLAT_MARVELL_TRUSTED_RAM_BASE + \ + PLAT_MARVELL_TRUSTED_RAM_SIZE - \ + MARVELL_OPTEE_PAGEABLE_LOAD_SIZE) +#define MARVELL_OPTEE_PAGEABLE_LOAD_SIZE 0x400000 +#define MARVELL_OPTEE_PAGEABLE_LOAD_MEM \ + MAP_REGION_FLAT( \ + MARVELL_OPTEE_PAGEABLE_LOAD_BASE, \ + MARVELL_OPTEE_PAGEABLE_LOAD_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +/* + * Map the memory for the OP-TEE core (also known as OP-TEE pager when paging + * support is enabled). + */ +#define MARVELL_MAP_OPTEE_CORE_MEM MAP_REGION_FLAT( \ + BL32_BASE, \ + BL32_LIMIT - BL32_BASE, \ + MT_MEMORY | MT_RW | MT_SECURE) +#endif /* SPD_opteed */ + +#define MARVELL_MAP_SECURE_RAM MAP_REGION_FLAT( \ + MARVELL_SHARED_RAM_BASE, \ + MARVELL_SHARED_RAM_SIZE, \ + MT_MEMORY | MT_RW | MT_SECURE) + +#define MARVELL_MAP_DRAM MAP_REGION_FLAT( \ + MARVELL_DRAM_BASE, \ + MARVELL_DRAM_SIZE, \ + MT_MEMORY | MT_RW | MT_NS) + +/* + * 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 MARVELL_BL_REGIONS 3 +#else +#define MARVELL_BL_REGIONS 2 +#endif + +#define MAX_MMAP_REGIONS (PLAT_MARVELL_MMAP_ENTRIES + \ + MARVELL_BL_REGIONS) + +#define MARVELL_CONSOLE_BAUDRATE 115200 + +/****************************************************************************** + * Required platform porting definitions common to all MARVELL std. platforms + *****************************************************************************/ + +#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 MARVELL_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 MARVELL_LOCAL_STATE_OFF + + +#define PLATFORM_CORE_COUNT PLAT_MARVELL_CORE_COUNT +#define PLAT_NUM_PWR_DOMAINS (PLAT_MARVELL_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +/* + * 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 << MARVELL_CACHE_WRITEBACK_SHIFT) + + +/******************************************************************************* + * 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 PLAT_MARVELL_TRUSTED_ROM_BASE +#define BL1_RO_LIMIT (PLAT_MARVELL_TRUSTED_ROM_BASE \ + + PLAT_MARVELL_TRUSTED_ROM_SIZE) +/* + * Put BL1 RW at the top of the Trusted SRAM. + */ +#define BL1_RW_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVELL_MAX_BL1_RW_SIZE) +#define BL1_RW_LIMIT (MARVELL_BL_RAM_BASE + MARVELL_BL_RAM_SIZE) + +/******************************************************************************* + * BLE specific defines. + ******************************************************************************/ +#define BLE_BASE PLAT_MARVELL_SRAM_BASE +#define BLE_LIMIT PLAT_MARVELL_SRAM_END + +/******************************************************************************* + * BL2 specific defines. + ******************************************************************************/ +/* + * Put BL2 just below BL31. + */ +#define BL2_BASE (BL31_BASE - PLAT_MARVELL_MAX_BL2_SIZE) +#define BL2_LIMIT BL31_BASE + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +/* + * Put BL31 at the top of the Trusted SRAM. + */ +#define BL31_BASE (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE - \ + PLAT_MARVEL_MAX_BL31_SIZE) +#define BL31_PROGBITS_LIMIT BL1_RW_BASE +#define BL31_LIMIT (MARVELL_BL_RAM_BASE + \ + MARVELL_BL_RAM_SIZE) + +/******************************************************************************* + * BL32 specific defines. + ******************************************************************************/ +#define BL32_BASE PLAT_MARVELL_TRUSTED_RAM_BASE +#define BL32_LIMIT (BL32_BASE + PLAT_MARVELL_TRUSTED_RAM_SIZE) + +#ifdef SPD_none +#undef BL32_BASE +#endif /* SPD_none */ + +#endif /* MARVELL_DEF_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h new file mode 100644 index 0000000..5d805a7 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_MARVELL_H +#define PLAT_MARVELL_H + +#include + +#include +#include +#include +#include + +/* + * Extern declarations common to Marvell standard platforms + */ +extern const mmap_region_t plat_marvell_mmap[]; + +#define MARVELL_CASSERT_MMAP \ + CASSERT((ARRAY_SIZE(plat_marvell_mmap) + MARVELL_BL_REGIONS) \ + <= MAX_MMAP_REGIONS, \ + assert_max_mmap_regions) + +struct marvell_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; +}; + +/* + * Utility functions common to Marvell standard platforms + */ +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 +); + +/* Console utility functions */ +void marvell_console_boot_init(void); +void marvell_console_boot_end(void); +void marvell_console_runtime_init(void); +void marvell_console_runtime_end(void); + +/* IO storage utility functions */ +void marvell_io_setup(void); + +/* Systimer utility function */ +void marvell_configure_sys_timer(void); + +/* Topology utility function */ +int marvell_check_mpidr(u_register_t mpidr); + +/* BLE utility functions */ +int ble_plat_setup(int *skip); +void plat_marvell_dram_update_topology(void); +void ble_plat_pcie_ep_setup(void); +struct pci_hw_cfg *plat_get_pcie_hw_data(void); + +/* BL1 utility functions */ +void marvell_bl1_early_platform_setup(void); +void marvell_bl1_platform_setup(void); +void marvell_bl1_plat_arch_setup(void); + +/* BL2 utility functions */ +void marvell_bl2_early_platform_setup(meminfo_t *mem_layout); +void marvell_bl2_platform_setup(void); +void marvell_bl2_plat_arch_setup(void); +uint32_t marvell_get_spsr_for_bl32_entry(void); +uint32_t marvell_get_spsr_for_bl33_entry(void); + +/* BL31 utility functions */ +void marvell_bl31_early_platform_setup(void *from_bl2, + uintptr_t soc_fw_config, + uintptr_t hw_config, + void *plat_params_from_bl2); +void marvell_bl31_platform_setup(void); +void marvell_bl31_plat_runtime_setup(void); +void marvell_bl31_plat_arch_setup(void); + +/* Power management config to power off the SoC */ +void *plat_marvell_get_pm_cfg(void); + +/* Check if MSS AP CM3 firmware contains PM support */ +_Bool is_pm_fw_running(void); + +/* Bootrom image recovery utility functions */ +void *plat_marvell_get_skip_image_data(void); + +/* FIP TOC validity check */ +int marvell_io_is_toc_valid(void); + +/* + * PSCI functionality + */ +void marvell_psci_arch_init(int ap_idx); +void plat_marvell_system_reset(void); + +/* + * Miscellaneous platform SMC routines + */ +#ifdef MVEBU_PMU_IRQ_WA +void mvebu_pmu_interrupt_enable(void); +void mvebu_pmu_interrupt_disable(void); +#endif + +/* + * Optional functions required in Marvell standard platforms + */ +void plat_marvell_io_setup(void); +int plat_marvell_get_alt_image_source( + unsigned int image_id, + uintptr_t *dev_handle, + uintptr_t *image_spec); +unsigned int plat_marvell_calc_core_pos(u_register_t mpidr); + +const mmap_region_t *plat_marvell_get_mmap(void); +void marvell_ble_prepare_exit(void); +void marvell_exit_bootrom(uintptr_t base); + +int plat_marvell_early_cpu_powerdown(void); +int bl2_plat_handle_scp_bl2(image_info_t *scp_bl2_image_info); + +#endif /* PLAT_MARVELL_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h new file mode 100644 index 0000000..a954914 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h @@ -0,0 +1,99 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef PLAT_PM_TRACE_H +#define PLAT_PM_TRACE_H + +/* + * PM Trace is for Debug purpose only!!! + * It should not be enabled during System Run time + */ +#undef PM_TRACE_ENABLE + + +/* trace entry time */ +struct pm_trace_entry { + /* trace entry time stamp */ + unsigned int timestamp; + + /* trace info + * [16-31] - API Trace Id + * [00-15] - API Step Id + */ + unsigned int trace_info; +}; + +struct pm_trace_ctrl { + /* trace pointer - points to next free entry in trace cyclic queue */ + unsigned int trace_pointer; + + /* trace count - number of entries in the queue, clear upon read */ + unsigned int trace_count; +}; + +/* trace size definition */ +#define AP_MSS_ATF_CORE_INFO_SIZE (256) +#define AP_MSS_ATF_CORE_ENTRY_SIZE (8) +#define AP_MSS_ATF_TRACE_SIZE_MASK (0xFF) + +/* trace address definition */ +#define AP_MSS_TIMER_BASE (MVEBU_REGS_BASE_MASK + 0x580110) + +#define AP_MSS_ATF_CORE_0_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520140) +#define AP_MSS_ATF_CORE_1_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520150) +#define AP_MSS_ATF_CORE_2_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520160) +#define AP_MSS_ATF_CORE_3_CTRL_BASE (MVEBU_REGS_BASE_MASK + 0x520170) +#define AP_MSS_ATF_CORE_CTRL_BASE (AP_MSS_ATF_CORE_0_CTRL_BASE) + +#define AP_MSS_ATF_CORE_0_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5201C0) +#define AP_MSS_ATF_CORE_0_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5201C4) +#define AP_MSS_ATF_CORE_1_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5209C0) +#define AP_MSS_ATF_CORE_1_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5209C4) +#define AP_MSS_ATF_CORE_2_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5211C0) +#define AP_MSS_ATF_CORE_2_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5211C4) +#define AP_MSS_ATF_CORE_3_INFO_BASE (MVEBU_REGS_BASE_MASK + 0x5219C0) +#define AP_MSS_ATF_CORE_3_INFO_TRACE (MVEBU_REGS_BASE_MASK + 0x5219C4) +#define AP_MSS_ATF_CORE_INFO_BASE (AP_MSS_ATF_CORE_0_INFO_BASE) + +/* trace info definition */ +#define TRACE_PWR_DOMAIN_OFF (0x10000) +#define TRACE_PWR_DOMAIN_SUSPEND (0x20000) +#define TRACE_PWR_DOMAIN_SUSPEND_FINISH (0x30000) +#define TRACE_PWR_DOMAIN_ON (0x40000) +#define TRACE_PWR_DOMAIN_ON_FINISH (0x50000) + +#define TRACE_PWR_DOMAIN_ON_MASK (0xFF) + +#ifdef PM_TRACE_ENABLE + +/* trace API definition */ +void pm_core_0_trace(unsigned int trace); +void pm_core_1_trace(unsigned int trace); +void pm_core_2_trace(unsigned int trace); +void pm_core_3_trace(unsigned int trace); + +typedef void (*core_trace_func)(unsigned int); + +extern core_trace_func funcTbl[PLATFORM_CORE_COUNT]; + +#define PM_TRACE(trace) funcTbl[plat_my_core_pos()](trace) + +#else + +#define PM_TRACE(trace) + +#endif + +/******************************************************************************* + * pm_trace_add + * + * DESCRIPTION: Add PM trace + ****************************************************************************** + */ +void pm_trace_add(unsigned int trace, unsigned int core); + +#endif /* PLAT_PM_TRACE_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S new file mode 100644 index 0000000..b0a909b --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef CCI_MACROS_S +#define CCI_MACROS_S + +#include +#include + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below required platform porting macro prints + * out relevant interconnect registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro print_cci_regs + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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 + +#endif /* CCI_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S new file mode 100644 index 0000000..bfe2d41 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_MACROS_S +#define MARVELL_MACROS_S + +#include +#include +#include +#include +#include + +/* + * These Macros are required by ATF + */ + +.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", "" + +#ifdef USE_CCI +/* Applicable only to GICv3 with SRE enabled */ +icc_regs: + .asciz "icc_hppir0_el1", "icc_hppir1_el1", "icc_ctlr_el3", "" +#endif +/* 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 ARM standard platforms. + * Expects: GICD base in x16, GICC base in x17 + * Clobbers: x0 - x10, sp + * --------------------------------------------- + */ + .macro marvell_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 + +#ifdef USE_CCI + /* 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 +#endif + 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 + + +.section .rodata.cci_reg_name, "aS" +cci_iface_regs: + .asciz "cci_snoop_ctrl_cluster0", "cci_snoop_ctrl_cluster1" , "" + + /* ------------------------------------------------ + * The below required platform porting macro prints + * out relevant interconnect registers whenever an + * unhandled exception is taken in BL31. + * Clobbers: x0 - x9, sp + * ------------------------------------------------ + */ + .macro print_cci_regs +#ifdef USE_CCI + adr x6, cci_iface_regs + /* Store in x7 the base address of the first interface */ + mov_imm x7, (PLAT_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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_MARVELL_CCI_BASE + SLAVE_IFACE_OFFSET( \ + PLAT_MARVELL_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 /* MARVELL_MACROS_S */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h new file mode 100644 index 0000000..78b5331 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h @@ -0,0 +1,34 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_PLAT_PRIV_H +#define MARVELL_PLAT_PRIV_H + +#include + +/***************************************************************************** + * Function and variable prototypes + ***************************************************************************** + */ +void plat_delay_timer_init(void); + +uint64_t mvebu_get_dram_size(uint64_t ap_base_addr); + +/* + * GIC operation, mandatory functions required in Marvell standard platforms + */ +void plat_marvell_gic_driver_init(void); +void plat_marvell_gic_init(void); +void plat_marvell_gic_cpuif_enable(void); +void plat_marvell_gic_cpuif_disable(void); +void plat_marvell_gic_pcpu_init(void); +void plat_marvell_gic_irq_save(void); +void plat_marvell_gic_irq_restore(void); +void plat_marvell_gic_irq_pcpu_save(void); +void plat_marvell_gic_irq_pcpu_restore(void); + +#endif /* MARVELL_PLAT_PRIV_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h new file mode 100644 index 0000000..8f16607 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h @@ -0,0 +1,26 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MARVELL_PM_H +#define MARVELL_PM_H + +#define MVEBU_MAILBOX_MAGIC_NUM PLAT_MARVELL_MAILBOX_MAGIC_NUM +#define MVEBU_MAILBOX_SUSPEND_STATE 0xb007de7c + +/* Mailbox entry indexes */ +/* Magic number for validity check */ +#define MBOX_IDX_MAGIC 0 +/* Recovery from suspend entry point */ +#define MBOX_IDX_SEC_ADDR 1 +/* Suspend state magic number */ +#define MBOX_IDX_SUSPEND_MAGIC 2 +/* Recovery jump address for ROM bypass */ +#define MBOX_IDX_ROM_EXIT_ADDR 3 +/* BLE execution start counter value */ +#define MBOX_IDX_START_CNT 4 + +#endif /* MARVELL_PM_H */ diff --git a/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h b/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h new file mode 100644 index 0000000..35a0200 --- /dev/null +++ b/arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#ifndef MVEBU_H +#define MVEBU_H + +/* Use this functions only when printf is allowed */ +#define debug_enter() VERBOSE("----> Enter %s\n", __func__) +#define debug_exit() VERBOSE("<---- Exit %s\n", __func__) + +/* Macro for testing alignment. Positive if number is NOT aligned */ +#define IS_NOT_ALIGN(number, align) ((number) & ((align) - 1)) + +/* Macro for alignment up. For example, ALIGN_UP(0x0330, 0x20) = 0x0340 */ +#define ALIGN_UP(number, align) (((number) & ((align) - 1)) ? \ + (((number) + (align)) & ~((align)-1)) : (number)) + +/* Macro for testing whether a number is a power of 2. Positive if so */ +#define IS_POWER_OF_2(number) ((number) != 0 && \ + (((number) & ((number) - 1)) == 0)) + +/* + * Macro for ronding up to next power of 2 + * it is done by count leading 0 (clz assembly opcode) and see msb set bit. + * then you can shift it left and get number which power of 2 + * Note: this Macro is for 32 bit number + */ +#define ROUND_UP_TO_POW_OF_2(number) (1 << \ + (32 - __builtin_clz((number) - 1))) + +#define _1MB_ (1024ULL * 1024ULL) +#define _1GB_ (_1MB_ * 1024ULL) +#define _2GB_ (2 * _1GB_) + +#endif /* MVEBU_H */ diff --git a/arm-trusted-firmware/include/services/arm_arch_svc.h b/arm-trusted-firmware/include/services/arm_arch_svc.h new file mode 100644 index 0000000..42f62f5 --- /dev/null +++ b/arm-trusted-firmware/include/services/arm_arch_svc.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ARM_ARCH_SVC_H +#define ARM_ARCH_SVC_H + +#define SMCCC_VERSION U(0x80000000) +#define SMCCC_ARCH_FEATURES U(0x80000001) +#define SMCCC_ARCH_SOC_ID U(0x80000002) +#define SMCCC_ARCH_WORKAROUND_1 U(0x80008000) +#define SMCCC_ARCH_WORKAROUND_2 U(0x80007FFF) +#define SMCCC_ARCH_WORKAROUND_3 U(0x80003FFF) + +#define ARM_ARCH_SVC_CALL_COUNT U(0x8000ff00) +#define ARM_ARCH_SVC_UID U(0x8000ff01) +#define ARM_ARCH_SVC_VERSION U(0x8000ff03) + +#define ARM_ARCH_SVC_COUNT U(7) + +#define ARM_ARCH_SVC_VERSION_MAJOR U(0) +#define ARM_ARCH_SVC_VERSION_MINOR U(1) + +#define SMCCC_GET_SOC_VERSION U(0) +#define SMCCC_GET_SOC_REVISION U(1) + +#endif /* ARM_ARCH_SVC_H */ diff --git a/arm-trusted-firmware/include/services/ffa_svc.h b/arm-trusted-firmware/include/services/ffa_svc.h new file mode 100644 index 0000000..9a7c489 --- /dev/null +++ b/arm-trusted-firmware/include/services/ffa_svc.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FFA_SVC_H +#define FFA_SVC_H + +#include +#include +#include + +/* FFA error codes. */ +#define FFA_ERROR_NOT_SUPPORTED -1 +#define FFA_ERROR_INVALID_PARAMETER -2 +#define FFA_ERROR_NO_MEMORY -3 +#define FFA_ERROR_BUSY -4 +#define FFA_ERROR_INTERRUPTED -5 +#define FFA_ERROR_DENIED -6 +#define FFA_ERROR_RETRY -7 + +/* The macros below are used to identify FFA calls from the SMC function ID */ +#define FFA_FNUM_MIN_VALUE U(0x60) +#define FFA_FNUM_MAX_VALUE U(0x87) +#define is_ffa_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= FFA_FNUM_MIN_VALUE) && \ + (GET_SMC_NUM(_fid) <= FFA_FNUM_MAX_VALUE)); }) + +/* FFA_VERSION helpers */ +#define FFA_VERSION_MAJOR U(1) +#define FFA_VERSION_MAJOR_SHIFT 16 +#define FFA_VERSION_MAJOR_MASK U(0x7FFF) +#define FFA_VERSION_MINOR U(1) +#define FFA_VERSION_MINOR_SHIFT 0 +#define FFA_VERSION_MINOR_MASK U(0xFFFF) +#define FFA_VERSION_BIT31_MASK U(0x1u << 31) + + +#define MAKE_FFA_VERSION(major, minor) \ + ((((major) & FFA_VERSION_MAJOR_MASK) << FFA_VERSION_MAJOR_SHIFT) | \ + (((minor) & FFA_VERSION_MINOR_MASK) << FFA_VERSION_MINOR_SHIFT)) +#define FFA_VERSION_COMPILED MAKE_FFA_VERSION(FFA_VERSION_MAJOR, \ + FFA_VERSION_MINOR) + +/* FFA_MSG_SEND helpers */ +#define FFA_MSG_SEND_ATTRS_BLK_SHIFT U(0) +#define FFA_MSG_SEND_ATTRS_BLK_MASK U(0x1) +#define FFA_MSG_SEND_ATTRS_BLK U(0) +#define FFA_MSG_SEND_ATTRS_BLK_NOT U(1) +#define FFA_MSG_SEND_ATTRS(blk) \ + (((blk) & FFA_MSG_SEND_ATTRS_BLK_MASK) \ + << FFA_MSG_SEND_ATTRS_BLK_SHIFT) + +/* Get FFA fastcall std FID from function number */ +#define FFA_FID(smc_cc, func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((smc_cc) << FUNCID_CC_SHIFT) | \ + (OEN_STD_START << FUNCID_OEN_SHIFT) | \ + ((func_num) << FUNCID_NUM_SHIFT)) + +/* FFA function numbers */ +#define FFA_FNUM_ERROR U(0x60) +#define FFA_FNUM_SUCCESS U(0x61) +#define FFA_FNUM_INTERRUPT U(0x62) +#define FFA_FNUM_VERSION U(0x63) +#define FFA_FNUM_FEATURES U(0x64) +#define FFA_FNUM_RX_RELEASE U(0x65) +#define FFA_FNUM_RXTX_MAP U(0x66) +#define FFA_FNUM_RXTX_UNMAP U(0x67) +#define FFA_FNUM_PARTITION_INFO_GET U(0x68) +#define FFA_FNUM_ID_GET U(0x69) +#define FFA_FNUM_MSG_POLL U(0x6A) /* Legacy FF-A v1.0 */ +#define FFA_FNUM_MSG_WAIT U(0x6B) +#define FFA_FNUM_MSG_YIELD U(0x6C) +#define FFA_FNUM_MSG_RUN U(0x6D) +#define FFA_FNUM_MSG_SEND U(0x6E) /* Legacy FF-A v1.0 */ +#define FFA_FNUM_MSG_SEND_DIRECT_REQ U(0x6F) +#define FFA_FNUM_MSG_SEND_DIRECT_RESP U(0x70) +#define FFA_FNUM_MEM_DONATE U(0x71) +#define FFA_FNUM_MEM_LEND U(0x72) +#define FFA_FNUM_MEM_SHARE U(0x73) +#define FFA_FNUM_MEM_RETRIEVE_REQ U(0x74) +#define FFA_FNUM_MEM_RETRIEVE_RESP U(0x75) +#define FFA_FNUM_MEM_RELINQUISH U(0x76) +#define FFA_FNUM_MEM_RECLAIM U(0x77) +#define FFA_FNUM_NORMAL_WORLD_RESUME U(0x7C) + +/* FF-A v1.1 */ +#define FFA_FNUM_NOTIFICATION_BITMAP_CREATE U(0x7D) +#define FFA_FNUM_NOTIFICATION_BITMAP_DESTROY U(0x7E) +#define FFA_FNUM_NOTIFICATION_BIND U(0x7F) +#define FFA_FNUM_NOTIFICATION_UNBIND U(0x80) +#define FFA_FNUM_NOTIFICATION_SET U(0x81) +#define FFA_FNUM_NOTIFICATION_GET U(0x82) +#define FFA_FNUM_NOTIFICATION_INFO_GET U(0x83) +#define FFA_FNUM_RX_ACQUIRE U(0x84) +#define FFA_FNUM_SPM_ID_GET U(0x85) +#define FFA_FNUM_MSG_SEND2 U(0x86) +#define FFA_FNUM_SECONDARY_EP_REGISTER U(0x87) + +/* FFA SMC32 FIDs */ +#define FFA_ERROR FFA_FID(SMC_32, FFA_FNUM_ERROR) +#define FFA_SUCCESS_SMC32 FFA_FID(SMC_32, FFA_FNUM_SUCCESS) +#define FFA_INTERRUPT FFA_FID(SMC_32, FFA_FNUM_INTERRUPT) +#define FFA_VERSION FFA_FID(SMC_32, FFA_FNUM_VERSION) +#define FFA_FEATURES FFA_FID(SMC_32, FFA_FNUM_FEATURES) +#define FFA_RX_RELEASE FFA_FID(SMC_32, FFA_FNUM_RX_RELEASE) +#define FFA_RXTX_MAP_SMC32 FFA_FID(SMC_32, FFA_FNUM_RXTX_MAP) +#define FFA_RXTX_UNMAP FFA_FID(SMC_32, FFA_FNUM_RXTX_UNMAP) +#define FFA_PARTITION_INFO_GET FFA_FID(SMC_32, FFA_FNUM_PARTITION_INFO_GET) +#define FFA_ID_GET FFA_FID(SMC_32, FFA_FNUM_ID_GET) +#define FFA_MSG_POLL FFA_FID(SMC_32, FFA_FNUM_MSG_POLL) +#define FFA_MSG_WAIT FFA_FID(SMC_32, FFA_FNUM_MSG_WAIT) +#define FFA_MSG_YIELD FFA_FID(SMC_32, FFA_FNUM_MSG_YIELD) +#define FFA_MSG_RUN FFA_FID(SMC_32, FFA_FNUM_MSG_RUN) +#define FFA_MSG_SEND FFA_FID(SMC_32, FFA_FNUM_MSG_SEND) +#define FFA_MSG_SEND2 FFA_FID(SMC_32, FFA_FNUM_MSG_SEND2) +#define FFA_MSG_SEND_DIRECT_REQ_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_REQ) +#define FFA_MSG_SEND_DIRECT_RESP_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MSG_SEND_DIRECT_RESP) +#define FFA_MEM_DONATE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_DONATE) +#define FFA_MEM_LEND_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_LEND) +#define FFA_MEM_SHARE_SMC32 FFA_FID(SMC_32, FFA_FNUM_MEM_SHARE) +#define FFA_MEM_RETRIEVE_REQ_SMC32 \ + FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_REQ) +#define FFA_MEM_RETRIEVE_RESP FFA_FID(SMC_32, FFA_FNUM_MEM_RETRIEVE_RESP) +#define FFA_MEM_RELINQUISH FFA_FID(SMC_32, FFA_FNUM_MEM_RELINQUISH) +#define FFA_MEM_RECLAIM FFA_FID(SMC_32, FFA_FNUM_MEM_RECLAIM) +#define FFA_NOTIFICATION_BITMAP_CREATE \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_CREATE) +#define FFA_NOTIFICATION_BITMAP_DESTROY \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BITMAP_DESTROY) +#define FFA_NOTIFICATION_BIND FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_BIND) +#define FFA_NOTIFICATION_UNBIND FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_UNBIND) +#define FFA_NOTIFICATION_SET FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_SET) +#define FFA_NOTIFICATION_GET FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_GET) +#define FFA_NOTIFICATION_INFO_GET \ + FFA_FID(SMC_32, FFA_FNUM_NOTIFICATION_INFO_GET) +#define FFA_SPM_ID_GET FFA_FID(SMC_32, FFA_FNUM_SPM_ID_GET) +#define FFA_NORMAL_WORLD_RESUME FFA_FID(SMC_32, FFA_FNUM_NORMAL_WORLD_RESUME) + +/* FFA SMC64 FIDs */ +#define FFA_ERROR_SMC64 FFA_FID(SMC_64, FFA_FNUM_ERROR) +#define FFA_SUCCESS_SMC64 FFA_FID(SMC_64, FFA_FNUM_SUCCESS) +#define FFA_RXTX_MAP_SMC64 FFA_FID(SMC_64, FFA_FNUM_RXTX_MAP) +#define FFA_MSG_SEND_DIRECT_REQ_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_REQ) +#define FFA_MSG_SEND_DIRECT_RESP_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MSG_SEND_DIRECT_RESP) +#define FFA_MEM_DONATE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_DONATE) +#define FFA_MEM_LEND_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_LEND) +#define FFA_MEM_SHARE_SMC64 FFA_FID(SMC_64, FFA_FNUM_MEM_SHARE) +#define FFA_MEM_RETRIEVE_REQ_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_MEM_RETRIEVE_REQ) +#define FFA_SECONDARY_EP_REGISTER_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_SECONDARY_EP_REGISTER) +#define FFA_NOTIFICATION_INFO_GET_SMC64 \ + FFA_FID(SMC_64, FFA_FNUM_NOTIFICATION_INFO_GET) + +/* + * Reserve a special value for traffic targeted to the Hypervisor or SPM. + */ +#define FFA_TARGET_INFO_MBZ U(0x0) + +/* + * Reserve a special value for MBZ parameters. + */ +#define FFA_PARAM_MBZ U(0x0) + +/* + * Maximum FF-A endpoint id value + */ +#define FFA_ENDPOINT_ID_MAX U(1 << 16) + +/* + * Mask for source and destination endpoint id in + * a direct message request/response. + */ +#define FFA_DIRECT_MSG_ENDPOINT_ID_MASK U(0xffff) + +/* + * Bit shift for destination endpoint id in a direct message request/response. + */ +#define FFA_DIRECT_MSG_DESTINATION_SHIFT U(0) + +/* + * Bit shift for source endpoint id in a direct message request/response. + */ +#define FFA_DIRECT_MSG_SOURCE_SHIFT U(16) + +/****************************************************************************** + * ffa_endpoint_destination + *****************************************************************************/ +static inline uint16_t ffa_endpoint_destination(unsigned int ep) +{ + return (ep >> FFA_DIRECT_MSG_DESTINATION_SHIFT) & + FFA_DIRECT_MSG_ENDPOINT_ID_MASK; +} + +/****************************************************************************** + * ffa_endpoint_source + *****************************************************************************/ +static inline uint16_t ffa_endpoint_source(unsigned int ep) +{ + return (ep >> FFA_DIRECT_MSG_SOURCE_SHIFT) & + FFA_DIRECT_MSG_ENDPOINT_ID_MASK; +} + +#endif /* FFA_SVC_H */ diff --git a/arm-trusted-firmware/include/services/pci_svc.h b/arm-trusted-firmware/include/services/pci_svc.h new file mode 100644 index 0000000..664a742 --- /dev/null +++ b/arm-trusted-firmware/include/services/pci_svc.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PCI_SVC_H +#define PCI_SVC_H + +#include + +/* SMCCC PCI platform functions */ +#define SMC_PCI_VERSION U(0x84000130) +#define SMC_PCI_FEATURES U(0x84000131) +#define SMC_PCI_READ U(0x84000132) +#define SMC_PCI_WRITE U(0x84000133) +#define SMC_PCI_SEG_INFO U(0x84000134) + +#define is_pci_fid(_fid) (((_fid) >= SMC_PCI_VERSION) && \ + ((_fid) <= SMC_PCI_SEG_INFO)) + +uint64_t pci_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); + +#define PCI_ADDR_FUN(dev) ((dev) & U(0x7)) +#define PCI_ADDR_DEV(dev) (((dev) >> U(3)) & U(0x001F)) +#define PCI_ADDR_BUS(dev) (((dev) >> U(8)) & U(0x00FF)) +#define PCI_ADDR_SEG(dev) (((dev) >> U(16)) & U(0xFFFF)) +#define PCI_OFFSET_MASK U(0xFFF) +typedef union { + struct { + uint16_t minor; + uint16_t major; + } __packed; + uint32_t val; +} pcie_version; + +/* + * platforms are responsible for providing implementations of these + * three functions in a manner which conforms to the Arm PCI Configuration + * Space Access Firmware Interface (DEN0115) and the PCIe specification's + * sections on PCI configuration access. See the rpi4_pci_svc.c example. + */ +uint32_t pci_read_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t *val); +uint32_t pci_write_config(uint32_t addr, uint32_t off, uint32_t sz, uint32_t val); +uint32_t pci_get_bus_for_seg(uint32_t seg, uint32_t *bus_range, uint32_t *nseg); + +/* Return codes for Arm PCI Config Space Access Firmware SMC calls */ +#define SMC_PCI_CALL_SUCCESS U(0) +#define SMC_PCI_CALL_NOT_SUPPORTED -1 +#define SMC_PCI_CALL_INVAL_PARAM -2 +#define SMC_PCI_CALL_NOT_IMPL -3 + +#define SMC_PCI_SZ_8BIT U(1) +#define SMC_PCI_SZ_16BIT U(2) +#define SMC_PCI_SZ_32BIT U(4) + +#endif /* PCI_SVC_H */ diff --git a/arm-trusted-firmware/include/services/rmmd_svc.h b/arm-trusted-firmware/include/services/rmmd_svc.h new file mode 100644 index 0000000..2fbdddd --- /dev/null +++ b/arm-trusted-firmware/include/services/rmmd_svc.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_SVC_H +#define RMMD_SVC_H + +#include +#include + +/* Construct RMM fastcall std FID from function number */ +#define RMM_FID(smc_cc, func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((smc_cc) << FUNCID_CC_SHIFT) | \ + (OEN_STD_START << FUNCID_OEN_SHIFT) | \ + ((func_num) << FUNCID_NUM_SHIFT)) + +/* The macros below are used to identify RMI calls from the SMC function ID */ +#define RMI_FNUM_MIN_VALUE U(0x150) +#define RMI_FNUM_MAX_VALUE U(0x18F) + +#define is_rmi_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= RMI_FNUM_MIN_VALUE) && \ + (GET_SMC_NUM(_fid) <= RMI_FNUM_MAX_VALUE) && \ + (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \ + (GET_SMC_CC(_fid) == SMC_64) && \ + (GET_SMC_OEN(_fid) == OEN_STD_START) && \ + ((_fid & 0x00FE0000) == 0U)); }) + +/* + * RMI_FNUM_REQ_COMPLETE is the only function in the RMI rnage that originates + * from the Realm world and is handled by the RMMD. The RMI functions are + * always invoked by the Normal world, forwarded by RMMD and handled by the + * RMM + */ +#define RMI_FNUM_REQ_COMPLETE U(0x18F) +#define RMMD_RMI_REQ_COMPLETE RMM_FID(SMC_64, RMI_FNUM_REQ_COMPLETE) + +/* The SMC in the range 0x8400 0190 - 0x8400 01AF are reserved for RSIs.*/ + +/* + * EL3 - RMM SMCs used for requesting RMMD services. These SMCs originate in Realm + * world and return to Realm world. + * + * These are allocated from 0x8400 01B0 - 0x8400 01CF in the RMM Service range. + */ +#define RMMD_EL3_FNUM_MIN_VALUE U(0x1B0) +#define RMMD_EL3_FNUM_MAX_VALUE U(0x1CF) + +/* The macros below are used to identify GTSI calls from the SMC function ID */ +#define is_rmmd_el3_fid(fid) __extension__ ({ \ + __typeof__(fid) _fid = (fid); \ + ((GET_SMC_NUM(_fid) >= RMMD_EL3_FNUM_MIN_VALUE) &&\ + (GET_SMC_NUM(_fid) <= RMMD_EL3_FNUM_MAX_VALUE) &&\ + (GET_SMC_TYPE(_fid) == SMC_TYPE_FAST) && \ + (GET_SMC_CC(_fid) == SMC_64) && \ + (GET_SMC_OEN(_fid) == OEN_STD_START) && \ + ((_fid & 0x00FE0000) == 0U)); }) + +/* RMMD Service Function NUmbers */ +#define GTSI_DELEGATE U(0x1B0) +#define GTSI_UNDELEGATE U(0x1B1) +#define ATTEST_GET_REALM_KEY U(0x1B2) +#define ATTEST_GET_PLAT_TOKEN U(0x1B3) + +#define RMMD_GTSI_DELEGATE RMM_FID(SMC_64, GTSI_DELEGATE) +#define RMMD_GTSI_UNDELEGATE RMM_FID(SMC_64, GTSI_UNDELEGATE) + +/* Return error codes from RMM-EL3 SMCs */ +#define RMMD_OK 0 +#define RMMD_ERR_BAD_ADDR -2 +#define RMMD_ERR_BAD_PAS -3 +#define RMMD_ERR_NOMEM -4 +#define RMMD_ERR_INVAL -5 +#define RMMD_ERR_UNK -6 + +/* + * Retrieve Platform token from EL3. + * The arguments to this SMC are : + * arg0 - Function ID. + * arg1 - Platform attestation token buffer Physical address. (The challenge + * object is passed in this buffer.) + * arg2 - Platform attestation token buffer size (in bytes). + * arg3 - Challenge object size (in bytes). It has be one of the defined SHA hash + * sizes. + * The return arguments are : + * ret0 - Status / error. + * ret1 - Size of the platform token if successful. + */ +#define RMMD_ATTEST_GET_PLAT_TOKEN RMM_FID(SMC_64, ATTEST_GET_PLAT_TOKEN) + +/* Acceptable SHA sizes for Challenge object */ +#define SHA256_DIGEST_SIZE 32U +#define SHA384_DIGEST_SIZE 48U +#define SHA512_DIGEST_SIZE 64U + +/* + * Retrieve Realm attestation key from EL3. Only P-384 ECC curve key is + * supported. The arguments to this SMC are : + * arg0 - Function ID. + * arg1 - Realm attestation key buffer Physical address. + * arg2 - Realm attestation key buffer size (in bytes). + * arg3 - The type of the elliptic curve to which the requested + * attestation key belongs to. The value should be one of the + * defined curve types. + * The return arguments are : + * ret0 - Status / error. + * ret1 - Size of the realm attestation key if successful. + */ +#define RMMD_ATTEST_GET_REALM_KEY RMM_FID(SMC_64, ATTEST_GET_REALM_KEY) + +/* ECC Curve types for attest key generation */ +#define ATTEST_KEY_CURVE_ECC_SECP384R1 0 + + +#ifndef __ASSEMBLER__ +#include + +int rmmd_setup(void); +uint64_t rmmd_rmi_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 rmmd_rmm_el3_handler(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *cookie, + void *handle, + uint64_t flags); + +#endif /* __ASSEMBLER__ */ +#endif /* RMMD_SVC_H */ diff --git a/arm-trusted-firmware/include/services/sdei.h b/arm-trusted-firmware/include/services/sdei.h new file mode 100644 index 0000000..063ed6f --- /dev/null +++ b/arm-trusted-firmware/include/services/sdei.h @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_H +#define SDEI_H + +#include +#include +#include + +/* Range 0xC4000020 - 0xC400003F reserved for SDE 64bit smc calls */ +#define SDEI_VERSION 0xC4000020U +#define SDEI_EVENT_REGISTER 0xC4000021U +#define SDEI_EVENT_ENABLE 0xC4000022U +#define SDEI_EVENT_DISABLE 0xC4000023U +#define SDEI_EVENT_CONTEXT 0xC4000024U +#define SDEI_EVENT_COMPLETE 0xC4000025U +#define SDEI_EVENT_COMPLETE_AND_RESUME 0xC4000026U + +#define SDEI_EVENT_UNREGISTER 0xC4000027U +#define SDEI_EVENT_STATUS 0xC4000028U +#define SDEI_EVENT_GET_INFO 0xC4000029U +#define SDEI_EVENT_ROUTING_SET 0xC400002AU +#define SDEI_PE_MASK 0xC400002BU +#define SDEI_PE_UNMASK 0xC400002CU + +#define SDEI_INTERRUPT_BIND 0xC400002DU +#define SDEI_INTERRUPT_RELEASE 0xC400002EU +#define SDEI_EVENT_SIGNAL 0xC400002FU +#define SDEI_FEATURES 0xC4000030U +#define SDEI_PRIVATE_RESET 0xC4000031U +#define SDEI_SHARED_RESET 0xC4000032U + +/* SDEI_EVENT_REGISTER flags */ +#define SDEI_REGF_RM_ANY 0ULL +#define SDEI_REGF_RM_PE 1ULL + +/* SDEI_EVENT_COMPLETE status flags */ +#define SDEI_EV_HANDLED 0U +#define SDEI_EV_FAILED 1U + +/* Indices of private and shared mappings */ +#define SDEI_MAP_IDX_PRIV_ 0U +#define SDEI_MAP_IDX_SHRD_ 1U +#define SDEI_MAP_IDX_MAX_ 2U + +/* The macros below are used to identify SDEI calls from the SMC function ID */ +#define SDEI_FID_MASK U(0xffe0) +#define SDEI_FID_VALUE U(0x20) +#define is_sdei_fid(_fid) \ + ((((_fid) & SDEI_FID_MASK) == SDEI_FID_VALUE) && \ + (((_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64)) + +#define SDEI_EVENT_MAP(_event, _intr, _flags) \ + { \ + .ev_num = (_event), \ + .intr = (_intr), \ + .map_flags = (_flags) \ + } + +#define SDEI_SHARED_EVENT(_event, _intr, _flags) \ + SDEI_EVENT_MAP(_event, _intr, _flags) + +#define SDEI_PRIVATE_EVENT(_event, _intr, _flags) \ + SDEI_EVENT_MAP(_event, _intr, (_flags) | SDEI_MAPF_PRIVATE) + +#define SDEI_DEFINE_EVENT_0(_intr) \ + SDEI_PRIVATE_EVENT(SDEI_EVENT_0, (_intr), SDEI_MAPF_SIGNALABLE) + +#define SDEI_EXPLICIT_EVENT(_event, _pri) \ + SDEI_EVENT_MAP((_event), 0, (_pri) | SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE) + +/* + * Declare shared and private entries for each core. Also declare a global + * structure containing private and share entries. + * + * This macro must be used in the same file as the platform SDEI mappings are + * declared. Only then would ARRAY_SIZE() yield a meaningful value. + */ +#define REGISTER_SDEI_MAP(_private, _shared) \ + sdei_entry_t sdei_private_event_table \ + [PLATFORM_CORE_COUNT * ARRAY_SIZE(_private)]; \ + sdei_entry_t sdei_shared_event_table[ARRAY_SIZE(_shared)]; \ + const sdei_mapping_t sdei_global_mappings[] = { \ + [SDEI_MAP_IDX_PRIV_] = { \ + .map = (_private), \ + .num_maps = ARRAY_SIZE(_private) \ + }, \ + [SDEI_MAP_IDX_SHRD_] = { \ + .map = (_shared), \ + .num_maps = ARRAY_SIZE(_shared) \ + }, \ + } + +typedef uint8_t sdei_state_t; + +/* Runtime data of SDEI event */ +typedef struct sdei_entry { + uint64_t ep; /* Entry point */ + uint64_t arg; /* Entry point argument */ + uint64_t affinity; /* Affinity of shared event */ + unsigned int reg_flags; /* Registration flags */ + + /* Event handler states: registered, enabled, running */ + sdei_state_t state; +} sdei_entry_t; + +/* Mapping of SDEI events to interrupts, and associated data */ +typedef struct sdei_ev_map { + int32_t ev_num; /* Event number */ + unsigned int intr; /* Physical interrupt number for a bound map */ + unsigned int map_flags; /* Mapping flags, see SDEI_MAPF_* */ + int reg_count; /* Registration count */ + spinlock_t lock; /* Per-event lock */ +} sdei_ev_map_t; + +typedef struct sdei_mapping { + sdei_ev_map_t *map; + size_t num_maps; +} sdei_mapping_t; + +/* Handler to be called to handle SDEI smc calls */ +uint64_t sdei_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); + +void sdei_init(void); + +/* Public API to dispatch an event to Normal world */ +int sdei_dispatch_event(int ev_num); + +#endif /* SDEI_H */ diff --git a/arm-trusted-firmware/include/services/sdei_flags.h b/arm-trusted-firmware/include/services/sdei_flags.h new file mode 100644 index 0000000..d1308f8 --- /dev/null +++ b/arm-trusted-firmware/include/services/sdei_flags.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_FLAGS_H +#define SDEI_FLAGS_H + +#include + +/* Internal: SDEI flag bit positions */ +#define SDEI_MAPF_DYNAMIC_SHIFT_ 1U +#define SDEI_MAPF_BOUND_SHIFT_ 2U +#define SDEI_MAPF_SIGNALABLE_SHIFT_ 3U +#define SDEI_MAPF_PRIVATE_SHIFT_ 4U +#define SDEI_MAPF_CRITICAL_SHIFT_ 5U +#define SDEI_MAPF_EXPLICIT_SHIFT_ 6U + +/* SDEI event 0 */ +#define SDEI_EVENT_0 0 + +/* Placeholder interrupt for dynamic mapping */ +#define SDEI_DYN_IRQ 0U + +/* SDEI flags */ + +/* + * These flags determine whether or not an event can be associated with an + * interrupt. Static events are permanently associated with an interrupt, and + * can't be changed at runtime. Association of dynamic events with interrupts + * can be changed at run time using the SDEI_INTERRUPT_BIND and + * SDEI_INTERRUPT_RELEASE calls. + * + * SDEI_MAPF_DYNAMIC only indicates run time configurability, where as + * SDEI_MAPF_BOUND indicates interrupt association. For example: + * + * - Calling SDEI_INTERRUPT_BIND on a dynamic event will have both + * SDEI_MAPF_DYNAMIC and SDEI_MAPF_BOUND set. + * + * - Statically-bound events will always have SDEI_MAPF_BOUND set, and neither + * SDEI_INTERRUPT_BIND nor SDEI_INTERRUPT_RELEASE can be called on them. + * + * See also the is_map_bound() macro. + */ +#define SDEI_MAPF_DYNAMIC BIT(SDEI_MAPF_DYNAMIC_SHIFT_) +#define SDEI_MAPF_BOUND BIT(SDEI_MAPF_BOUND_SHIFT_) +#define SDEI_MAPF_EXPLICIT BIT(SDEI_MAPF_EXPLICIT_SHIFT_) + +#define SDEI_MAPF_SIGNALABLE BIT(SDEI_MAPF_SIGNALABLE_SHIFT_) +#define SDEI_MAPF_PRIVATE BIT(SDEI_MAPF_PRIVATE_SHIFT_) + +#define SDEI_MAPF_NORMAL 0 +#define SDEI_MAPF_CRITICAL BIT(SDEI_MAPF_CRITICAL_SHIFT_) + +#endif /* SDEI_FLAGS_H */ diff --git a/arm-trusted-firmware/include/services/spm_core_manifest.h b/arm-trusted-firmware/include/services/spm_core_manifest.h new file mode 100644 index 0000000..453b21c --- /dev/null +++ b/arm-trusted-firmware/include/services/spm_core_manifest.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_CORE_MANIFEST_H +#define SPM_CORE_MANIFEST_H + +#include + +/******************************************************************************* + * Attribute Section + ******************************************************************************/ + +typedef struct spm_core_manifest_sect_attribute { + /* + * FFA version (mandatory). + */ + uint32_t major_version; + uint32_t minor_version; + + /* + * Run-Time Execution state (optional): + * - 0: AArch64 (default) + * - 1: AArch32 + */ + uint32_t exec_state; + + /* + * Address of binary image containing SPM Core (optional). + */ + uint64_t load_address; + + /* + * Offset from the base of the partition's binary image to the entry + * point of the partition (optional). + */ + uint64_t entrypoint; + + /* + * Size of binary image containing SPM Core in bytes (mandatory). + */ + uint32_t binary_size; + + /* + * ID of the SPMC (mandatory) + */ + uint16_t spmc_id; + +} spmc_manifest_attribute_t; + +#endif /* SPM_CORE_MANIFEST_H */ diff --git a/arm-trusted-firmware/include/services/spm_mm_partition.h b/arm-trusted-firmware/include/services/spm_mm_partition.h new file mode 100644 index 0000000..ad5ceef --- /dev/null +++ b/arm-trusted-firmware/include/services/spm_mm_partition.h @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_PARTITION_H +#define SPM_MM_PARTITION_H + +#include + +#include + +/* + * Flags used by the spm_mm_mp_info structure to describe the + * characteristics of a cpu. Only a single flag is defined at the moment to + * indicate the primary cpu. + */ +#define MP_INFO_FLAG_PRIMARY_CPU U(0x00000001) + +/* + * This structure is used to provide information required to initialise a S-EL0 + * partition. + */ +typedef struct spm_mm_mp_info { + uint64_t mpidr; + uint32_t linear_id; + uint32_t flags; +} spm_mm_mp_info_t; + +typedef struct spm_mm_boot_info { + param_header_t h; + uint64_t sp_mem_base; + uint64_t sp_mem_limit; + uint64_t sp_image_base; + uint64_t sp_stack_base; + uint64_t sp_heap_base; + uint64_t sp_ns_comm_buf_base; + uint64_t sp_shared_buf_base; + uint64_t sp_image_size; + uint64_t sp_pcpu_stack_size; + uint64_t sp_heap_size; + uint64_t sp_ns_comm_buf_size; + uint64_t sp_shared_buf_size; + uint32_t num_sp_mem_regions; + uint32_t num_cpus; + spm_mm_mp_info_t *mp_info; +} spm_mm_boot_info_t; + +#endif /* SPM_MM_PARTITION_H */ diff --git a/arm-trusted-firmware/include/services/spm_mm_svc.h b/arm-trusted-firmware/include/services/spm_mm_svc.h new file mode 100644 index 0000000..3148beb --- /dev/null +++ b/arm-trusted-firmware/include/services/spm_mm_svc.h @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_SVC_H +#define SPM_MM_SVC_H + +#include + +/* + * The MM_VERSION_XXX definitions are used when responding to the + * MM_VERSION_AARCH32 service request. The version returned is different between + * this request and the SPM_MM_VERSION_AARCH32 request - both have been retained + * for compatibility. + */ +#define MM_VERSION_MAJOR U(1) +#define MM_VERSION_MAJOR_SHIFT 16 +#define MM_VERSION_MAJOR_MASK U(0x7FFF) +#define MM_VERSION_MINOR U(0) +#define MM_VERSION_MINOR_SHIFT 0 +#define MM_VERSION_MINOR_MASK U(0xFFFF) +#define MM_VERSION_FORM(major, minor) ((major << MM_VERSION_MAJOR_SHIFT) | \ + (minor)) +#define MM_VERSION_COMPILED MM_VERSION_FORM(MM_VERSION_MAJOR, \ + MM_VERSION_MINOR) + +#define SPM_MM_VERSION_MAJOR U(0) +#define SPM_MM_VERSION_MAJOR_SHIFT 16 +#define SPM_MM_VERSION_MAJOR_MASK U(0x7FFF) +#define SPM_MM_VERSION_MINOR U(1) +#define SPM_MM_VERSION_MINOR_SHIFT 0 +#define SPM_MM_VERSION_MINOR_MASK U(0xFFFF) +#define SPM_MM_VERSION_FORM(major, minor) ((major << \ + SPM_MM_VERSION_MAJOR_SHIFT) | \ + (minor)) +#define SPM_MM_VERSION_COMPILED SPM_MM_VERSION_FORM(SPM_MM_VERSION_MAJOR, \ + SPM_MM_VERSION_MINOR) + +/* These macros are used to identify SPM-MM calls using the SMC function ID */ +#define SPM_MM_FID_MASK U(0xffff) +#define SPM_MM_FID_MIN_VALUE U(0x40) +#define SPM_MM_FID_MAX_VALUE U(0x7f) +#define is_spm_mm_fid(_fid) \ + ((((_fid) & SPM_MM_FID_MASK) >= SPM_MM_FID_MIN_VALUE) && \ + (((_fid) & SPM_MM_FID_MASK) <= SPM_MM_FID_MAX_VALUE)) + +/* + * SMC IDs defined in [1] for accessing MM services from the Non-secure world. + * These FIDs occupy the range 0x40 - 0x5f. + * [1] DEN0060A_ARM_MM_Interface_Specification.pdf + */ +#define MM_VERSION_AARCH32 U(0x84000040) +#define MM_COMMUNICATE_AARCH64 U(0xC4000041) +#define MM_COMMUNICATE_AARCH32 U(0x84000041) + +/* + * SMC IDs defined for accessing services implemented by the Secure Partition + * Manager from the Secure Partition(s). These services enable a partition to + * handle delegated events and request privileged operations from the manager. + * They occupy the range 0x60-0x7f. + */ +#define SPM_MM_VERSION_AARCH32 U(0x84000060) +#define MM_SP_EVENT_COMPLETE_AARCH64 U(0xC4000061) +#define MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 U(0xC4000064) +#define MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 U(0xC4000065) + +/* + * Macros used by MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64. + */ + +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS U(0) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW U(1) +/* Value U(2) is reserved. */ +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO U(3) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK U(3) +#define MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT 0 + +#define MM_SP_MEMORY_ATTRIBUTES_EXEC (U(0) << 2) +#define MM_SP_MEMORY_ATTRIBUTES_NON_EXEC (U(1) << 2) + + +/* SPM error codes. */ +#define SPM_MM_SUCCESS 0 +#define SPM_MM_NOT_SUPPORTED -1 +#define SPM_MM_INVALID_PARAMETER -2 +#define SPM_MM_DENIED -3 +#define SPM_MM_NO_MEMORY -5 + +#ifndef __ASSEMBLER__ + +#include + +int32_t spm_mm_setup(void); + +uint64_t spm_mm_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); + +/* Helper to enter a secure partition */ +uint64_t spm_mm_sp_call(uint32_t smc_fid, + uint64_t x1, + uint64_t x2, + uint64_t x3); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPM_MM_SVC_H */ diff --git a/arm-trusted-firmware/include/services/spmd_svc.h b/arm-trusted-firmware/include/services/spmd_svc.h new file mode 100644 index 0000000..1e7e6aa --- /dev/null +++ b/arm-trusted-firmware/include/services/spmd_svc.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPMD_SVC_H +#define SPMD_SVC_H + +#ifndef __ASSEMBLER__ +#include +#include + +int spmd_setup(void); +uint64_t spmd_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); +#endif /* __ASSEMBLER__ */ + +#endif /* SPMD_SVC_H */ diff --git a/arm-trusted-firmware/include/services/std_svc.h b/arm-trusted-firmware/include/services/std_svc.h new file mode 100644 index 0000000..b0614fb --- /dev/null +++ b/arm-trusted-firmware/include/services/std_svc.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STD_SVC_H +#define STD_SVC_H + +/* SMC function IDs for Standard Service queries */ + +#define ARM_STD_SVC_CALL_COUNT 0x8400ff00 +#define ARM_STD_SVC_UID 0x8400ff01 +/* 0x8400ff02 is reserved */ +#define ARM_STD_SVC_VERSION 0x8400ff03 + +/* ARM Standard Service Calls version numbers */ +#define STD_SVC_VERSION_MAJOR 0x0 +#define STD_SVC_VERSION_MINOR 0x1 + +/* + * Get the ARM Standard Service argument from EL3 Runtime. + * This function must be implemented by EL3 Runtime and the + * `svc_mask` identifies the service. `svc_mask` is a bit + * mask identifying the range of SMC function IDs available + * to the service. + */ +uintptr_t get_arm_std_svc_args(unsigned int svc_mask); + +#endif /* STD_SVC_H */ diff --git a/arm-trusted-firmware/include/services/trng_svc.h b/arm-trusted-firmware/include/services/trng_svc.h new file mode 100644 index 0000000..ed4d557 --- /dev/null +++ b/arm-trusted-firmware/include/services/trng_svc.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_SVC_H +#define TRNG_SVC_H + +#include +#include + +#include + +/* SMC function IDs for TRNG queries */ +#define ARM_TRNG_VERSION U(0x84000050) +#define ARM_TRNG_FEATURES U(0x84000051) +#define ARM_TRNG_GET_UUID U(0x84000052) +#define ARM_TRNG_RND32 U(0x84000053) +#define ARM_TRNG_RND64 U(0xc4000053) + +/* TRNG version numbers */ +#define TRNG_VERSION_MAJOR (0x1) +#define TRNG_VERSION_MINOR (0x0) + +/* TRNG Error Numbers */ +#define TRNG_E_SUCCESS (0) +#define TRNG_E_NOT_SUPPORTED (-1) +#define TRNG_E_INVALID_PARAMS (-2) +#define TRNG_E_NO_ENTROPY (-3) +#define TRNG_E_NOT_IMPLEMENTED (-4) + +#if TRNG_SUPPORT +void trng_setup(void); +bool is_trng_fid(uint32_t smc_fid); +#else +static inline void trng_setup(void) +{ +} + +static inline bool is_trng_fid(uint32_t smc_fid) +{ + return false; +} +#endif +uintptr_t trng_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 +); + +#endif /* TRNG_SVC_H */ diff --git a/arm-trusted-firmware/include/services/trp/platform_trp.h b/arm-trusted-firmware/include/services/trp/platform_trp.h new file mode 100644 index 0000000..b34da85 --- /dev/null +++ b/arm-trusted-firmware/include/services/trp/platform_trp.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_TRP_H +#define PLATFORM_TRP_H + +/******************************************************************************* + * Mandatory TRP functions (only if platform contains a TRP) + ******************************************************************************/ +void trp_early_platform_setup(void); + +#endif /* PLATFORM_TRP_H */ diff --git a/arm-trusted-firmware/include/tools_share/dualroot_oid.h b/arm-trusted-firmware/include/tools_share/dualroot_oid.h new file mode 100644 index 0000000..3e88a6d --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/dualroot_oid.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DUALROOT_OID_H +#define DUALROOT_OID_H + +/* Reuse the Object IDs defined by TBBR for certificate extensions. */ +#include "tbbr_oid.h" + +/* + * Platform root-of-trust public key. + * Arbitrary value that does not conflict with any of the TBBR reserved OIDs. + */ +#define PROT_PK_OID "1.3.6.1.4.1.4128.2100.1102" + +#endif /* DUALROOT_OID_H */ diff --git a/arm-trusted-firmware/include/tools_share/firmware_encrypted.h b/arm-trusted-firmware/include/tools_share/firmware_encrypted.h new file mode 100644 index 0000000..7ca634f --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/firmware_encrypted.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIRMWARE_ENCRYPTED_H +#define FIRMWARE_ENCRYPTED_H + +#include + +/* This is used as a signature to validate the encryption header */ +#define ENC_HEADER_MAGIC 0xAA640001U + +/* Firmware encryption status flag mask */ +#define FW_ENC_STATUS_FLAG_MASK 0x1 + +/* + * SSK: Secret Symmetric Key + * BSSK: Binding Secret Symmetric Key + */ +enum fw_enc_status_t { + FW_ENC_WITH_SSK = 0, + FW_ENC_WITH_BSSK = 1, +}; + +#define ENC_MAX_IV_SIZE 16U +#define ENC_MAX_TAG_SIZE 16U +#define ENC_MAX_KEY_SIZE 32U + +struct fw_enc_hdr { + uint32_t magic; + uint16_t dec_algo; + uint16_t flags; + uint16_t iv_len; + uint16_t tag_len; + uint8_t iv[ENC_MAX_IV_SIZE]; + uint8_t tag[ENC_MAX_TAG_SIZE]; +}; + +#endif /* FIRMWARE_ENCRYPTED_H */ diff --git a/arm-trusted-firmware/include/tools_share/firmware_image_package.h b/arm-trusted-firmware/include/tools_share/firmware_image_package.h new file mode 100644 index 0000000..bd5b14b --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/firmware_image_package.h @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIRMWARE_IMAGE_PACKAGE_H +#define FIRMWARE_IMAGE_PACKAGE_H + +#include + +#include "uuid.h" + +/* This is used as a signature to validate the blob header */ +#define TOC_HEADER_NAME 0xAA640001 + + +/* ToC Entry UUIDs */ +#define UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U \ + {{0x65, 0x92, 0x27, 0x03}, {0x2f, 0x74}, {0xe6, 0x44}, 0x8d, 0xff, {0x57, 0x9a, 0xc1, 0xff, 0x06, 0x10} } +#define UUID_TRUSTED_UPDATE_FIRMWARE_BL2U \ + {{0x60, 0xb3, 0xeb, 0x37}, {0xc1, 0xe5}, {0xea, 0x41}, 0x9d, 0xf3, {0x19, 0xed, 0xa1, 0x1f, 0x68, 0x01} } +#define UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U \ + {{0x4f, 0x51, 0x1d, 0x11}, {0x2b, 0xe5}, {0x4e, 0x49}, 0xb4, 0xc5, {0x83, 0xc2, 0xf7, 0x15, 0x84, 0x0a} } +#define UUID_TRUSTED_FWU_CERT \ + {{0x71, 0x40, 0x8a, 0xb2}, {0x18, 0xd6}, {0x87, 0x4c}, 0x8b, 0x2e, {0xc6, 0xdc, 0xcd, 0x50, 0xf0, 0x96} } +#define UUID_TRUSTED_BOOT_FIRMWARE_BL2 \ + {{0x5f, 0xf9, 0xec, 0x0b}, {0x4d, 0x22}, {0x3e, 0x4d}, 0xa5, 0x44, {0xc3, 0x9d, 0x81, 0xc7, 0x3f, 0x0a} } +#define UUID_SCP_FIRMWARE_SCP_BL2 \ + {{0x97, 0x66, 0xfd, 0x3d}, {0x89, 0xbe}, {0xe8, 0x49}, 0xae, 0x5d, {0x78, 0xa1, 0x40, 0x60, 0x82, 0x13} } +#define UUID_EL3_RUNTIME_FIRMWARE_BL31 \ + {{0x47, 0xd4, 0x08, 0x6d}, {0x4c, 0xfe}, {0x98, 0x46}, 0x9b, 0x95, {0x29, 0x50, 0xcb, 0xbd, 0x5a, 0x00} } +#define UUID_SECURE_PAYLOAD_BL32 \ + {{0x05, 0xd0, 0xe1, 0x89}, {0x53, 0xdc}, {0x13, 0x47}, 0x8d, 0x2b, {0x50, 0x0a, 0x4b, 0x7a, 0x3e, 0x38} } +#define UUID_SECURE_PAYLOAD_BL32_EXTRA1 \ + {{0x0b, 0x70, 0xc2, 0x9b}, {0x2a, 0x5a}, {0x78, 0x40}, 0x9f, 0x65, {0x0a, 0x56, 0x82, 0x73, 0x82, 0x88} } +#define UUID_SECURE_PAYLOAD_BL32_EXTRA2 \ + {{0x8e, 0xa8, 0x7b, 0xb1}, {0xcf, 0xa2}, {0x3f, 0x4d}, 0x85, 0xfd, {0xe7, 0xbb, 0xa5, 0x02, 0x20, 0xd9} } +#define UUID_NON_TRUSTED_FIRMWARE_BL33 \ + {{0xd6, 0xd0, 0xee, 0xa7}, {0xfc, 0xea}, {0xd5, 0x4b}, 0x97, 0x82, {0x99, 0x34, 0xf2, 0x34, 0xb6, 0xe4} } +#define UUID_REALM_MONITOR_MGMT_FIRMWARE \ + {{0x6c, 0x07, 0x62, 0xa6}, {0x12, 0xf2}, {0x4b, 0x56}, 0x92, 0xcb, {0xba, 0x8f, 0x63, 0x36, 0x06, 0xd9} } +/* Key certificates */ +#define UUID_ROT_KEY_CERT \ + {{0x86, 0x2d, 0x1d, 0x72}, {0xf8, 0x60}, {0xe4, 0x11}, 0x92, 0x0b, {0x8b, 0xe7, 0x62, 0x16, 0x0f, 0x24} } +#define UUID_TRUSTED_KEY_CERT \ + {{0x82, 0x7e, 0xe8, 0x90}, {0xf8, 0x60}, {0xe4, 0x11}, 0xa1, 0xb4, {0x77, 0x7a, 0x21, 0xb4, 0xf9, 0x4c} } +#define UUID_NON_TRUSTED_WORLD_KEY_CERT \ + {{0x1c, 0x67, 0x87, 0x3d}, {0x5f, 0x63}, {0xe4, 0x11}, 0x97, 0x8d, {0x27, 0xc0, 0xc7, 0x14, 0x8a, 0xbd} } +#define UUID_SCP_FW_KEY_CERT \ + {{0x02, 0x42, 0x21, 0xa1}, {0xf8, 0x60}, {0xe4, 0x11}, 0x8d, 0x9b, {0xf3, 0x3c, 0x0e, 0x15, 0xa0, 0x14} } +#define UUID_SOC_FW_KEY_CERT \ + {{0x8a, 0xb8, 0xbe, 0xcc}, {0xf9, 0x60}, {0xe4, 0x11}, 0x9a, 0xd0, {0xeb, 0x48, 0x22, 0xd8, 0xdc, 0xf8} } +#define UUID_TRUSTED_OS_FW_KEY_CERT \ + {{0x94, 0x77, 0xd6, 0x03}, {0xfb, 0x60}, {0xe4, 0x11}, 0x85, 0xdd, {0xb7, 0x10, 0x5b, 0x8c, 0xee, 0x04} } +#define UUID_NON_TRUSTED_FW_KEY_CERT \ + {{0x8a, 0xd5, 0x83, 0x2a}, {0xfb, 0x60}, {0xe4, 0x11}, 0x8a, 0xaf, {0xdf, 0x30, 0xbb, 0xc4, 0x98, 0x59} } +/* Content certificates */ +#define UUID_TRUSTED_BOOT_FW_CERT \ + {{0xd6, 0xe2, 0x69, 0xea}, {0x5d, 0x63}, {0xe4, 0x11}, 0x8d, 0x8c, {0x9f, 0xba, 0xbe, 0x99, 0x56, 0xa5} } +#define UUID_SCP_FW_CONTENT_CERT \ + {{0x44, 0xbe, 0x6f, 0x04}, {0x5e, 0x63}, {0xe4, 0x11}, 0xb2, 0x8b, {0x73, 0xd8, 0xea, 0xae, 0x96, 0x56} } +#define UUID_SOC_FW_CONTENT_CERT \ + {{0xe2, 0xb2, 0x0c, 0x20}, {0x5e, 0x63}, {0xe4, 0x11}, 0x9c, 0xe8, {0xab, 0xcc, 0xf9, 0x2b, 0xb6, 0x66} } +#define UUID_TRUSTED_OS_FW_CONTENT_CERT \ + {{0xa4, 0x9f, 0x44, 0x11}, {0x5e, 0x63}, {0xe4, 0x11}, 0x87, 0x28, {0x3f, 0x05, 0x72, 0x2a, 0xf3, 0x3d} } +#define UUID_NON_TRUSTED_FW_CONTENT_CERT \ + {{0x8e, 0xc4, 0xc1, 0xf3}, {0x5d, 0x63}, {0xe4, 0x11}, 0xa7, 0xa9, {0x87, 0xee, 0x40, 0xb2, 0x3f, 0xa7} } +#define UUID_SIP_SECURE_PARTITION_CONTENT_CERT \ + {{0x77, 0x6d, 0xfd, 0x44}, {0x86, 0x97}, {0x4c, 0x3b}, 0x91, 0xeb, {0xc1, 0x3e, 0x02, 0x5a, 0x2a, 0x6f} } +#define UUID_PLAT_SECURE_PARTITION_CONTENT_CERT \ + {{0xdd, 0xcb, 0xbf, 0x4a}, {0xca, 0xd6}, {0x11, 0xea}, 0x87, 0xd0, {0x02, 0x42, 0xac, 0x13, 0x00, 0x03} } +/* Dynamic configs */ +#define UUID_HW_CONFIG \ + {{0x08, 0xb8, 0xf1, 0xd9}, {0xc9, 0xcf}, {0x93, 0x49}, 0xa9, 0x62, {0x6f, 0xbc, 0x6b, 0x72, 0x65, 0xcc} } +#define UUID_TB_FW_CONFIG \ + {{0x6c, 0x04, 0x58, 0xff}, {0xaf, 0x6b}, {0x7d, 0x4f}, 0x82, 0xed, {0xaa, 0x27, 0xbc, 0x69, 0xbf, 0xd2} } +#define UUID_SOC_FW_CONFIG \ + {{0x99, 0x79, 0x81, 0x4b}, {0x03, 0x76}, {0xfb, 0x46}, 0x8c, 0x8e, {0x8d, 0x26, 0x7f, 0x78, 0x59, 0xe0} } +#define UUID_TOS_FW_CONFIG \ + {{0x26, 0x25, 0x7c, 0x1a}, {0xdb, 0xc6}, {0x7f, 0x47}, 0x8d, 0x96, {0xc4, 0xc4, 0xb0, 0x24, 0x80, 0x21} } +#define UUID_NT_FW_CONFIG \ + {{0x28, 0xda, 0x98, 0x15}, {0x93, 0xe8}, {0x7e, 0x44}, 0xac, 0x66, {0x1a, 0xaf, 0x80, 0x15, 0x50, 0xf9} } +#define UUID_FW_CONFIG \ + {{0x58, 0x07, 0xe1, 0x6a}, {0x84, 0x59}, {0x47, 0xbe}, 0x8e, 0xd5, {0x64, 0x8e, 0x8d, 0xdd, 0xab, 0x0e} } + +#ifdef PLAT_DEF_FIP_UUID +#include +#endif + +typedef struct fip_toc_header { + uint32_t name; + uint32_t serial_number; + uint64_t flags; +} fip_toc_header_t; + +typedef struct fip_toc_entry { + uuid_t uuid; + uint64_t offset_address; + uint64_t size; + uint64_t flags; +} fip_toc_entry_t; + +#endif /* FIRMWARE_IMAGE_PACKAGE_H */ diff --git a/arm-trusted-firmware/include/tools_share/sptool.h b/arm-trusted-firmware/include/tools_share/sptool.h new file mode 100644 index 0000000..53668e0 --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/sptool.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPTOOL_H +#define SPTOOL_H + +#include + +/* 4 Byte magic name "SPKG" */ +#define SECURE_PARTITION_MAGIC 0x474B5053 + +/* Header for a secure partition package. */ +struct sp_pkg_header { + uint32_t magic; + uint32_t version; + uint32_t pm_offset; + uint32_t pm_size; + uint32_t img_offset; + uint32_t img_size; +}; + +#endif /* SPTOOL_H */ diff --git a/arm-trusted-firmware/include/tools_share/tbbr_oid.h b/arm-trusted-firmware/include/tools_share/tbbr_oid.h new file mode 100644 index 0000000..52b43ab --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/tbbr_oid.h @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_OID_H +#define TBBR_OID_H + +#define MAX_OID_NAME_LEN 30 + +/* + * The following is a list of OID values defined and reserved by ARM, which + * are used to define the extension fields of the certificate structure, as + * defined in the Trusted Board Boot Requirements (TBBR) specification, + * ARM DEN0006C-1. + */ + + +/* TrustedFirmwareNVCounter - Non-volatile counter extension */ +#define TRUSTED_FW_NVCOUNTER_OID "1.3.6.1.4.1.4128.2100.1" +/* NonTrustedFirmwareNVCounter - Non-volatile counter extension */ +#define NON_TRUSTED_FW_NVCOUNTER_OID "1.3.6.1.4.1.4128.2100.2" + + +/* + * Non-Trusted Firmware Updater Certificate + */ + +/* APFirmwareUpdaterConfigHash - BL2U */ +#define AP_FWU_CFG_HASH_OID "1.3.6.1.4.1.4128.2100.101" +/* SCPFirmwareUpdaterConfigHash - SCP_BL2U */ +#define SCP_FWU_CFG_HASH_OID "1.3.6.1.4.1.4128.2100.102" +/* FirmwareUpdaterHash - NS_BL2U */ +#define FWU_HASH_OID "1.3.6.1.4.1.4128.2100.103" +/* TrustedWatchdogRefreshTime */ +#define TRUSTED_WATCHDOG_TIME_OID "1.3.6.1.4.1.4128.2100.104" + + +/* + * Trusted Boot Firmware Certificate + */ + +/* TrustedBootFirmwareHash - BL2 */ +#define TRUSTED_BOOT_FW_HASH_OID "1.3.6.1.4.1.4128.2100.201" +#define TRUSTED_BOOT_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.202" +#define HW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.203" +#define FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.204" + +/* + * Trusted Key Certificate + */ + +/* PrimaryDebugCertificatePK */ +#define PRIMARY_DEBUG_PK_OID "1.3.6.1.4.1.4128.2100.301" +/* TrustedWorldPK */ +#define TRUSTED_WORLD_PK_OID "1.3.6.1.4.1.4128.2100.302" +/* NonTrustedWorldPK */ +#define NON_TRUSTED_WORLD_PK_OID "1.3.6.1.4.1.4128.2100.303" + + +/* + * Trusted Debug Certificate + */ + +/* DebugScenario */ +#define TRUSTED_DEBUG_SCENARIO_OID "1.3.6.1.4.1.4128.2100.401" +/* SoC Specific */ +#define TRUSTED_DEBUG_SOC_SPEC_OID "1.3.6.1.4.1.4128.2100.402" +/* SecondaryDebugCertPK */ +#define SECONDARY_DEBUG_PK_OID "1.3.6.1.4.1.4128.2100.403" + + +/* + * SoC Firmware Key Certificate + */ + +/* SoCFirmwareContentCertPK */ +#define SOC_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.501" + +/* + * SoC Firmware Content Certificate + */ + +/* APRomPatchHash - BL1_PATCH */ +#define APROM_PATCH_HASH_OID "1.3.6.1.4.1.4128.2100.601" +/* SoCConfigHash */ +#define SOC_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.602" +/* SoCAPFirmwareHash - BL31 */ +#define SOC_AP_FW_HASH_OID "1.3.6.1.4.1.4128.2100.603" +/* SoCFirmwareConfigHash = SOC_FW_CONFIG */ +#define SOC_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.604" + +/* + * SCP Firmware Key Certificate + */ + +/* SCPFirmwareContentCertPK */ +#define SCP_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.701" + + +/* + * SCP Firmware Content Certificate + */ + +/* SCPFirmwareHash - SCP_BL2 */ +#define SCP_FW_HASH_OID "1.3.6.1.4.1.4128.2100.801" +/* SCPRomPatchHash - SCP_BL1_PATCH */ +#define SCP_ROM_PATCH_HASH_OID "1.3.6.1.4.1.4128.2100.802" + + +/* + * Trusted OS Firmware Key Certificate + */ + +/* TrustedOSFirmwareContentCertPK */ +#define TRUSTED_OS_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.901" + + +/* + * Trusted OS Firmware Content Certificate + */ + +/* TrustedOSFirmwareHash - BL32 */ +#define TRUSTED_OS_FW_HASH_OID "1.3.6.1.4.1.4128.2100.1001" +/* TrustedOSExtra1FirmwareHash - BL32 Extra1 */ +#define TRUSTED_OS_FW_EXTRA1_HASH_OID "1.3.6.1.4.1.4128.2100.1002" +/* TrustedOSExtra2FirmwareHash - BL32 Extra2 */ +#define TRUSTED_OS_FW_EXTRA2_HASH_OID "1.3.6.1.4.1.4128.2100.1003" +/* TrustedOSFirmwareConfigHash - TOS_FW_CONFIG */ +#define TRUSTED_OS_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.1004" + + +/* + * Non-Trusted Firmware Key Certificate + */ + +/* NonTrustedFirmwareContentCertPK */ +#define NON_TRUSTED_FW_CONTENT_CERT_PK_OID "1.3.6.1.4.1.4128.2100.1101" + + +/* + * Non-Trusted Firmware Content Certificate + */ + +/* NonTrustedWorldBootloaderHash - BL33 */ +#define NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID "1.3.6.1.4.1.4128.2100.1201" +/* NonTrustedFirmwareConfigHash - NT_FW_CONFIG */ +#define NON_TRUSTED_FW_CONFIG_HASH_OID "1.3.6.1.4.1.4128.2100.1202" + +/* + * Secure Partitions Content Certificate + */ +#define SP_PKG1_HASH_OID "1.3.6.1.4.1.4128.2100.1301" +#define SP_PKG2_HASH_OID "1.3.6.1.4.1.4128.2100.1302" +#define SP_PKG3_HASH_OID "1.3.6.1.4.1.4128.2100.1303" +#define SP_PKG4_HASH_OID "1.3.6.1.4.1.4128.2100.1304" +#define SP_PKG5_HASH_OID "1.3.6.1.4.1.4128.2100.1305" +#define SP_PKG6_HASH_OID "1.3.6.1.4.1.4128.2100.1306" +#define SP_PKG7_HASH_OID "1.3.6.1.4.1.4128.2100.1307" +#define SP_PKG8_HASH_OID "1.3.6.1.4.1.4128.2100.1308" + +#ifdef PLAT_DEF_OID +#include +#endif +#endif /* TBBR_OID_H */ diff --git a/arm-trusted-firmware/include/tools_share/uuid.h b/arm-trusted-firmware/include/tools_share/uuid.h new file mode 100644 index 0000000..2ced3a3 --- /dev/null +++ b/arm-trusted-firmware/include/tools_share/uuid.h @@ -0,0 +1,74 @@ +/*- + * Copyright (c) 2002 Marcel Moolenaar + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. + * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * $FreeBSD$ + */ + +/* + * Portions copyright (c) 2014-2020, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef UUID_H +#define UUID_H + +/* Length of a node address (an IEEE 802 address). */ +#define _UUID_NODE_LEN 6 + +/* Length of UUID string including dashes. */ +#define _UUID_STR_LEN 36 + +/* + * See also: + * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt + * http://www.opengroup.org/onlinepubs/009629399/apdxa.htm + * + * A DCE 1.1 compatible source representation of UUIDs. + */ +struct uuid { + uint8_t time_low[4]; + uint8_t time_mid[2]; + uint8_t time_hi_and_version[2]; + uint8_t clock_seq_hi_and_reserved; + uint8_t clock_seq_low; + uint8_t node[_UUID_NODE_LEN]; +}; + +struct efi_guid { + uint32_t time_low; + uint16_t time_mid; + uint16_t time_hi_and_version; + uint8_t clock_seq_and_node[8]; +}; + +union uuid_helper_t { + struct uuid uuid_struct; + struct efi_guid efi_guid; +}; + +/* XXX namespace pollution? */ +typedef struct uuid uuid_t; + +#endif /* UUID_H */ diff --git a/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c new file mode 100644 index 0000000..ea8e2bb --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Form ABI specifications: + * int __aeabi_idiv(int numerator, int denominator); + * unsigned __aeabi_uidiv(unsigned numerator, unsigned denominator); + * + * typedef struct { int quot; int rem; } idiv_return; + * typedef struct { unsigned quot; unsigned rem; } uidiv_return; + * + * __value_in_regs idiv_return __aeabi_idivmod(int numerator, + * int *denominator); + * __value_in_regs uidiv_return __aeabi_uidivmod(unsigned *numerator, + * unsigned denominator); + */ + +/* struct qr - stores quotient/remainder to handle divmod EABI interfaces. */ +struct qr { + unsigned int q; /* computed quotient */ + unsigned int r; /* computed remainder */ + unsigned int q_n; /* specifies if quotient shall be negative */ + unsigned int r_n; /* specifies if remainder shall be negative */ +}; + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr); + +/* returns in R0 and R1 by tail calling an asm function */ +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator); + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator); + +/* returns in R0 and R1 by tail calling an asm function */ +signed int __aeabi_idivmod(signed int numerator, signed int denominator); + +signed int __aeabi_idiv(signed int numerator, signed int denominator); + +/* + * __ste_idivmod_ret_t __aeabi_idivmod(signed numerator, signed denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_idivmod_ret_t is returned in R0 and R1. + * + * __ste_uidivmod_ret_t __aeabi_uidivmod(unsigned numerator, + * unsigned denominator) + * Numerator and Denominator are received in R0 and R1. + * Where __ste_uidivmod_ret_t is returned in R0 and R1. + */ +#ifdef __GNUC__ +signed int ret_idivmod_values(signed int quotient, signed int remainder); +unsigned int ret_uidivmod_values(unsigned int quotient, unsigned int remainder); +#else +#error "Compiler not supported" +#endif + +static void division_qr(unsigned int n, unsigned int p, struct qr *qr) +{ + unsigned int i = 1, q = 0; + + if (p == 0) { + qr->r = 0xFFFFFFFF; /* division by 0 */ + return; + } + + while ((p >> 31) == 0) { + i = i << 1; /* count the max division steps */ + p = p << 1; /* increase p until it has maximum size*/ + } + + while (i > 0) { + q = q << 1; /* write bit in q at index (size-1) */ + if (n >= p) { + n -= p; + q++; + } + p = p >> 1; /* decrease p */ + i = i >> 1; /* decrease remaining size in q */ + } + qr->r = n; + qr->q = q; +} + +static void uint_div_qr(unsigned int numerator, unsigned int denominator, + struct qr *qr) +{ + division_qr(numerator, denominator, qr); + + /* negate quotient and/or remainder according to requester */ + if (qr->q_n) + qr->q = -qr->q; + if (qr->r_n) + qr->r = -qr->r; +} + +unsigned int __aeabi_uidiv(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +unsigned int __aeabi_uidivmod(unsigned int numerator, unsigned int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + uint_div_qr(numerator, denominator, &qr); + + return ret_uidivmod_values(qr.q, qr.r); +} + +signed int __aeabi_idiv(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return qr.q; +} + +signed int __aeabi_idivmod(signed int numerator, signed int denominator) +{ + struct qr qr = { .q_n = 0, .r_n = 0 }; + + if (((numerator < 0) && (denominator > 0)) || + ((numerator > 0) && (denominator < 0))) + qr.q_n = 1; /* quotient shall be negate */ + + if (numerator < 0) { + numerator = -numerator; + qr.r_n = 1; /* remainder shall be negate */ + } + + if (denominator < 0) + denominator = -denominator; + + uint_div_qr(numerator, denominator, &qr); + + return ret_idivmod_values(qr.q, qr.r); +} diff --git a/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S new file mode 100644 index 0000000..6915dcd --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * EABI wrappers from the udivmod and idivmod functions + */ + + .globl ret_uidivmod_values + .globl ret_idivmod_values + +/* + * signed ret_idivmod_values(signed quot, signed rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_idivmod_values + bx lr +endfunc ret_idivmod_values + +/* + * unsigned ret_uidivmod_values(unsigned quot, unsigned rem); + * return quotient and remaining the EABI way (regs r0,r1) + */ +func ret_uidivmod_values + bx lr +endfunc ret_uidivmod_values diff --git a/arm-trusted-firmware/lib/aarch32/armclang_printf.S b/arm-trusted-firmware/lib/aarch32/armclang_printf.S new file mode 100644 index 0000000..2b87bf7 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/armclang_printf.S @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* Symbols needed by armclang */ + + .globl __0printf + .globl __1printf + .globl __2printf + +func __0printf +__1printf: +__2printf: + b printf +endfunc __0printf diff --git a/arm-trusted-firmware/lib/aarch32/cache_helpers.S b/arm-trusted-firmware/lib/aarch32/cache_helpers.S new file mode 100644 index 0000000..13d1872 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/cache_helpers.S @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2016-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl flush_dcache_range + .globl clean_dcache_range + .globl inv_dcache_range + .globl dcsw_op_louis + .globl dcsw_op_all + .globl dcsw_op_level1 + .globl dcsw_op_level2 + .globl dcsw_op_level3 + +/* + * This macro can be used for implementing various data cache operations `op` + */ +.macro do_dcache_maintenance_by_mva op, coproc, opc1, CRn, CRm, opc2 + /* Exit early if size is zero */ + cmp r1, #0 + beq exit_loop_\op + dcache_line_size r2, r3 + add r1, r0, r1 + sub r3, r2, #1 + bic r0, r0, r3 +loop_\op: + stcopr r0, \coproc, \opc1, \CRn, \CRm, \opc2 + add r0, r0, r2 + cmp r0, r1 + blo loop_\op + dsb sy +exit_loop_\op: + bx lr +.endm + + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func flush_dcache_range + do_dcache_maintenance_by_mva cimvac, DCCIMVAC +endfunc flush_dcache_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func clean_dcache_range + do_dcache_maintenance_by_mva cmvac, DCCMVAC +endfunc clean_dcache_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'r0' = addr, 'r1' = size + * ------------------------------------------ + */ +func inv_dcache_range + do_dcache_maintenance_by_mva imvac, DCIMVAC +endfunc inv_dcache_range + + /* ---------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * r1: The cache level to begin operation from + * r2: clidr_el1 + * r3: The last cache level to operate on + * and will carry out the operation on each data cache from level 0 + * to the level in r3 in sequence + * + * The dcsw_op macro sets up the r2 and r3 parameters based on + * clidr_el1 cache information before invoking the main function + * ---------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + ldcopr r2, CLIDR + ubfx r3, r2, \shift, \fw + lsl r3, r3, \ls + mov r1, #0 + b do_dcsw_op + .endm + +func do_dcsw_op + push {r4-r12, lr} + ldcopr r8, ID_MMFR4 // stash FEAT_CCIDX identifier in r8 + ubfx r8, r8, #ID_MMFR4_CCIDX_SHIFT, #ID_MMFR4_CCIDX_LENGTH + adr r11, dcsw_loop_table // compute cache op based on the operation type + add r6, r11, r0, lsl #3 // cache op is 2x32-bit instructions +loop1: + add r10, r1, r1, LSR #1 // Work out 3x current cache level + mov r12, r2, LSR r10 // extract cache type bits from clidr + and r12, r12, #7 // mask the bits for current cache only + cmp r12, #2 // see what cache we have at this level + blo level_done // no cache or only instruction cache at this level + + stcopr r1, CSSELR // select current cache level in csselr + isb // isb to sych the new cssr&csidr + ldcopr r12, CCSIDR // read the new ccsidr + and r10, r12, #7 // extract the length of the cache lines + add r10, r10, #4 // add 4 (r10 = line length offset) + + cmp r8, #0 // check for FEAT_CCIDX for Associativity + beq 1f + ubfx r4, r12, #3, #21 // r4 = associativity CCSIDR[23:3] + b 2f +1: + ubfx r4, r12, #3, #10 // r4 = associativity CCSIDR[12:3] +2: + clz r5, r4 // r5 = the bit position of the way size increment + mov r9, r4 // r9 working copy of the aligned max way number + +loop2: + cmp r8, #0 // check for FEAT_CCIDX for NumSets + beq 3f + ldcopr r12, CCSIDR2 // FEAT_CCIDX numsets is in CCSIDR2 + ubfx r7, r12, #0, #24 // r7 = numsets CCSIDR2[23:0] + b loop3 +3: + ubfx r7, r12, #13, #15 // r7 = numsets CCSIDR[27:13] +loop3: + orr r0, r1, r9, LSL r5 // factor in the way number and cache level into r0 + orr r0, r0, r7, LSL r10 // factor in the set number + + blx r6 + subs r7, r7, #1 // decrement the set number + bhs loop3 + subs r9, r9, #1 // decrement the way number + bhs loop2 +level_done: + add r1, r1, #2 // increment the cache number + cmp r3, r1 + // Ensure completion of previous cache maintenance instruction. Note + // this also mitigates erratum 814220 on Cortex-A7 + dsb sy + bhi loop1 + + mov r6, #0 + stcopr r6, CSSELR //select cache level 0 in csselr + dsb sy + isb + pop {r4-r12, pc} + +dcsw_loop_table: + stcopr r0, DCISW + bx lr + stcopr r0, DCCISW + bx lr + stcopr r0, DCCSW + bx lr + +endfunc do_dcsw_op + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoU. + * + * The function requires : + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_louis + dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_louis + + /* --------------------------------------------------------------- + * Data cache operations by set/way till PoC. + * + * The function requires : + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_all + dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_all + + + /* --------------------------------------------------------------- + * Helper macro for data cache operations by set/way for the + * level specified + * --------------------------------------------------------------- + */ + .macro dcsw_op_level level + ldcopr r2, CLIDR + mov r3, \level + sub r1, r3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level1 + dcsw_op_level #(1 << LEVEL_SHIFT) +endfunc dcsw_op_level1 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 2 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level2 + dcsw_op_level #(2 << LEVEL_SHIFT) +endfunc dcsw_op_level2 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 3 cache + * + * The main function, do_dcsw_op requires: + * r0: The operation type (DC_OP_ISW, DC_OP_CISW, DC_OP_CSW), + * as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level3 + dcsw_op_level #(3 << LEVEL_SHIFT) +endfunc dcsw_op_level3 diff --git a/arm-trusted-firmware/lib/aarch32/misc_helpers.S b/arm-trusted-firmware/lib/aarch32/misc_helpers.S new file mode 100644 index 0000000..59e15bd --- /dev/null +++ b/arm-trusted-firmware/lib/aarch32/misc_helpers.S @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl smc + .globl zeromem + .globl zero_normalmem + .globl memcpy4 + .globl disable_mmu_icache_secure + .globl disable_mmu_secure + .globl fixup_gdt_reloc + +#define PAGE_START_MASK ~(PAGE_SIZE_MASK) + +func smc + /* + * For AArch32 only r0-r3 will be in the registers; + * rest r4-r6 will be pushed on to the stack. So here, we'll + * have to load them from the stack to registers r4-r6 explicitly. + * Clobbers: r4-r6 + */ + ldm sp, {r4, r5, r6} + smc #0 +endfunc smc + +/* ----------------------------------------------------------------------- + * void zeromem(void *mem, unsigned int length) + * + * Initialise a region in normal memory to 0. This functions complies with the + * AAPCS and can be called from C code. + * + * ----------------------------------------------------------------------- + */ +func zeromem + /* + * Readable names for registers + * + * Registers r0, r1 and r2 are also set by zeromem which + * branches into the fallback path directly, so cursor, length and + * stop_address should not be retargeted to other registers. + */ + cursor .req r0 /* Start address and then current address */ + length .req r1 /* Length in bytes of the region to zero out */ + /* + * Reusing the r1 register as length is only used at the beginning of + * the function. + */ + stop_address .req r1 /* Address past the last zeroed byte */ + zeroreg1 .req r2 /* Source register filled with 0 */ + zeroreg2 .req r3 /* Source register filled with 0 */ + tmp .req r12 /* Temporary scratch register */ + + mov zeroreg1, #0 + + /* stop_address is the address past the last to zero */ + add stop_address, cursor, length + + /* + * Length cannot be used anymore as it shares the same register with + * stop_address. + */ + .unreq length + + /* + * If the start address is already aligned to 8 bytes, skip this loop. + */ + tst cursor, #(8-1) + beq .Lzeromem_8bytes_aligned + + /* Calculate the next address aligned to 8 bytes */ + orr tmp, cursor, #(8-1) + adds tmp, tmp, #1 + /* If it overflows, fallback to byte per byte zeroing */ + beq .Lzeromem_1byte_aligned + /* If the next aligned address is after the stop address, fall back */ + cmp tmp, stop_address + bhs .Lzeromem_1byte_aligned + + /* zero byte per byte */ +1: + strb zeroreg1, [cursor], #1 + cmp cursor, tmp + bne 1b + + /* zero 8 bytes at a time */ +.Lzeromem_8bytes_aligned: + + /* Calculate the last 8 bytes aligned address. */ + bic tmp, stop_address, #(8-1) + + cmp cursor, tmp + bhs 2f + + mov zeroreg2, #0 +1: + stmia cursor!, {zeroreg1, zeroreg2} + cmp cursor, tmp + blo 1b +2: + + /* zero byte per byte */ +.Lzeromem_1byte_aligned: + cmp cursor, stop_address + beq 2f +1: + strb zeroreg1, [cursor], #1 + cmp cursor, stop_address + bne 1b +2: + bx lr + + .unreq cursor + /* + * length is already unreq'ed to reuse the register for another + * variable. + */ + .unreq stop_address + .unreq zeroreg1 + .unreq zeroreg2 + .unreq tmp +endfunc zeromem + +/* + * AArch32 does not have special ways of zeroing normal memory as AArch64 does + * using the DC ZVA instruction, so we just alias zero_normalmem to zeromem. + */ +.equ zero_normalmem, zeromem + +/* -------------------------------------------------------------------------- + * void memcpy4(void *dest, const void *src, unsigned int length) + * + * Copy length bytes from memory area src to memory area dest. + * The memory areas should not overlap. + * Destination and source addresses must be 4-byte aligned. + * -------------------------------------------------------------------------- + */ +func memcpy4 +#if ENABLE_ASSERTIONS + orr r3, r0, r1 + tst r3, #0x3 + ASM_ASSERT(eq) +#endif +/* copy 4 bytes at a time */ +m_loop4: + cmp r2, #4 + blo m_loop1 + ldr r3, [r1], #4 + str r3, [r0], #4 + subs r2, r2, #4 + bne m_loop4 + bx lr + +/* copy byte per byte */ +m_loop1: + ldrb r3, [r1], #1 + strb r3, [r0], #1 + subs r2, r2, #1 + bne m_loop1 + bx lr +endfunc memcpy4 + +/* --------------------------------------------------------------------------- + * Disable the MMU in Secure State + * --------------------------------------------------------------------------- + */ + +func disable_mmu_secure + mov r1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu: +#if ERRATA_A9_794073 + stcopr r0, BPIALL + dsb +#endif + ldcopr r0, SCTLR + bic r0, r0, r1 + stcopr r0, SCTLR + isb // ensure MMU is off + dsb sy + bx lr +endfunc disable_mmu_secure + + +func disable_mmu_icache_secure + ldr r1, =(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu +endfunc disable_mmu_icache_secure + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Descriptor table (GDT) and dynamic relocations + * (.rel.dyn) at runtime. + * + * This function is meant to be used when the firmware is compiled with -fpie + * and linked with -pie options. We rely on the linker script exporting + * appropriate markers for start and end of the section. For GOT, we + * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect + * __RELA_START__ and __RELA_END__. + * + * The function takes the limits of the memory to apply fixups to as + * arguments (which is usually the limits of the relocable BL image). + * r0 - the start of the fixup region + * r1 - the limit of the fixup region + * These addresses have to be 4KB page aligned. + * --------------------------------------------------------------------------- + */ + +/* Relocation codes */ +#define R_ARM_RELATIVE 23 + +func fixup_gdt_reloc + mov r6, r0 + mov r7, r1 + +#if ENABLE_ASSERTIONS + /* Test if the limits are 4K aligned */ + orr r0, r0, r1 + mov r1, #(PAGE_SIZE_MASK) + tst r0, r1 + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in lr. + * Assume that this function is called within a page at the start of + * fixup region. + */ + ldr r1, =PAGE_START_MASK + and r2, lr, r1 + subs r0, r2, r6 /* Diff(S) = Current Address - Compiled Address */ + beq 3f /* Diff(S) = 0. No relocation needed */ + + ldr r1, =__GOT_START__ + add r1, r1, r0 + ldr r2, =__GOT_END__ + add r2, r2, r0 + + /* + * GOT is an array of 32_bit addresses which must be fixed up as + * new_addr = old_addr + Diff(S). + * The new_addr is the address currently the binary is executing from + * and old_addr is the address at compile time. + */ +1: ldr r3, [r1] + + /* Skip adding offset if address is < lower limit */ + cmp r3, r6 + blo 2f + + /* Skip adding offset if address is > upper limit */ + cmp r3, r7 + bhi 2f + add r3, r3, r0 + str r3, [r1] + +2: add r1, r1, #4 + cmp r1, r2 + blo 1b + + /* Starting dynamic relocations. Use ldr to get RELA_START and END */ +3: ldr r1, =__RELA_START__ + add r1, r1, r0 + ldr r2, =__RELA_END__ + add r2, r2, r0 + + /* + * According to ELF-32 specification, the RELA data structure is as + * follows: + * typedef struct { + * Elf32_Addr r_offset; + * Elf32_Xword r_info; + * } Elf32_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * code 23 which corresponds to R_ARM_RELATIVE). + * + * Size of Elf32_Rela structure is 8 bytes. + */ + + /* Skip R_ARM_NONE entry with code 0 */ +1: ldr r3, [r1, #4] + ands r3, r3, #0xff + beq 2f + +#if ENABLE_ASSERTIONS + /* Assert that the relocation type is R_ARM_RELATIVE */ + cmp r3, #R_ARM_RELATIVE + ASM_ASSERT(eq) +#endif + ldr r3, [r1] /* r_offset */ + add r3, r0, r3 /* Diff(S) + r_offset */ + ldr r4, [r3] + + /* Skip adding offset if address is < lower limit */ + cmp r4, r6 + blo 2f + + /* Skip adding offset if address is > upper limit */ + cmp r4, r7 + bhi 2f + + add r4, r0, r4 + str r4, [r3] + +2: add r1, r1, #8 + cmp r1, r2 + blo 1b + bx lr +endfunc fixup_gdt_reloc diff --git a/arm-trusted-firmware/lib/aarch64/armclang_printf.S b/arm-trusted-firmware/lib/aarch64/armclang_printf.S new file mode 100644 index 0000000..52a6976 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch64/armclang_printf.S @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* Symbols needed by armclang */ + + .globl __0printf + .globl __1printf + .globl __2printf + +func __0printf + b printf +endfunc __0printf + +func __1printf + b printf +endfunc __1printf + +func __2printf + b printf +endfunc __2printf diff --git a/arm-trusted-firmware/lib/aarch64/cache_helpers.S b/arm-trusted-firmware/lib/aarch64/cache_helpers.S new file mode 100644 index 0000000..6faf545 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch64/cache_helpers.S @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl flush_dcache_range + .globl flush_dcache_to_popa_range + .globl clean_dcache_range + .globl inv_dcache_range + .globl dcsw_op_louis + .globl dcsw_op_all + .globl dcsw_op_level1 + .globl dcsw_op_level2 + .globl dcsw_op_level3 + +/* + * This macro can be used for implementing various data cache operations `op` + */ +.macro do_dcache_maintenance_by_mva op + /* Exit early if size is zero */ + cbz x1, exit_loop_\op + dcache_line_size x2, x3 + add x1, x0, x1 + sub x3, x2, #1 + bic x0, x0, x3 +loop_\op: + dc \op, x0 + add x0, x0, x2 + cmp x0, x1 + b.lo loop_\op + dsb sy +exit_loop_\op: + ret +.endm + /* ------------------------------------------ + * Clean+Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func flush_dcache_range + do_dcache_maintenance_by_mva civac +endfunc flush_dcache_range + + /* ------------------------------------------ + * Clean from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func clean_dcache_range + do_dcache_maintenance_by_mva cvac +endfunc clean_dcache_range + + /* ------------------------------------------ + * Invalidate from base address till + * size. 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func inv_dcache_range + do_dcache_maintenance_by_mva ivac +endfunc inv_dcache_range + + + /* + * On implementations with FEAT_MTE2, + * Root firmware must issue DC_CIGDPAPA instead of DC_CIPAPA , + * in order to additionally clean and invalidate Allocation Tags + * associated with the affected locations. + * + * ------------------------------------------ + * Clean+Invalidate by PA to POPA + * from base address till size. + * 'x0' = addr, 'x1' = size + * ------------------------------------------ + */ +func flush_dcache_to_popa_range + /* Exit early if size is zero */ + cbz x1, exit_loop_dc_cipapa + dcache_line_size x2, x3 + sub x3, x2, #1 + bic x0, x0, x3 + add x1, x1, x0 +loop_dc_cipapa: + sys #6, c7, c14, #1, x0 /* DC CIPAPA, */ + add x0, x0, x2 + cmp x0, x1 + b.lo loop_dc_cipapa + dsb osh +exit_loop_dc_cipapa: + ret +endfunc flush_dcache_to_popa_range + + /* --------------------------------------------------------------- + * Data cache operations by set/way to the level specified + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * x3: The last cache level to operate on + * x9: clidr_el1 + * x10: The cache level to begin operation from + * and will carry out the operation on each data cache from level 0 + * to the level in x3 in sequence + * + * The dcsw_op macro sets up the x3 and x9 parameters based on + * clidr_el1 cache information before invoking the main function + * --------------------------------------------------------------- + */ + + .macro dcsw_op shift, fw, ls + mrs x9, clidr_el1 + ubfx x3, x9, \shift, \fw + lsl x3, x3, \ls + mov x10, xzr + b do_dcsw_op + .endm + +func do_dcsw_op + cbz x3, exit + mrs x12, ID_AA64MMFR2_EL1 // stash FEAT_CCIDX identifier in x12 + ubfx x12, x12, #ID_AA64MMFR2_EL1_CCIDX_SHIFT, #ID_AA64MMFR2_EL1_CCIDX_LENGTH + adr x14, dcsw_loop_table // compute inner loop address + add x14, x14, x0, lsl #5 // inner loop is 8x32-bit instructions +#if ENABLE_BTI + add x14, x14, x0, lsl #2 // inner loop is + "bti j" instruction +#endif + mov x0, x9 + mov w8, #1 +loop1: + add x2, x10, x10, lsr #1 // work out 3x current cache level + lsr x1, x0, x2 // extract cache type bits from clidr + and x1, x1, #7 // mask the bits for current cache only + cmp x1, #2 // see what cache we have at this level + b.lo level_done // nothing to do if no cache or icache + + msr csselr_el1, x10 // select current cache level in csselr + isb // isb to sych the new cssr&csidr + mrs x1, ccsidr_el1 // read the new ccsidr + and x2, x1, #7 // extract the length of the cache lines + add x2, x2, #4 // add 4 (line length offset) + + cbz x12, 1f // check for FEAT_CCIDX for Associativity + ubfx x4, x1, #3, #21 // x4 = associativity CCSIDR_EL1[23:3] + b 2f +1: + ubfx x4, x1, #3, #10 // x4 = associativity CCSIDR_EL1[12:3] +2: + clz w5, w4 // bit position of way size increment + lsl w9, w4, w5 // w9 = aligned max way number + lsl w16, w8, w5 // w16 = way number loop decrement + orr w9, w10, w9 // w9 = combine way and cache number + + cbz x12, 3f // check for FEAT_CCIDX for NumSets + ubfx x6, x1, #32, #24 // x6 (w6) = numsets CCSIDR_EL1[55:32] + // ISA will not allow x->w ubfx + b 4f +3: + ubfx w6, w1, #13, #15 // w6 = numsets CCSIDR_EL1[27:13] +4: + lsl w17, w8, w2 // w17 = set number loop decrement + dsb sy // barrier before we start this level + br x14 // jump to DC operation specific loop + + .macro dcsw_loop _op +#if ENABLE_BTI + bti j +#endif +loop2_\_op: + lsl w7, w6, w2 // w7 = aligned max set number + +loop3_\_op: + orr w11, w9, w7 // combine cache, way and set number + dc \_op, x11 + subs w7, w7, w17 // decrement set number + b.hs loop3_\_op + + subs x9, x9, x16 // decrement way number + b.hs loop2_\_op + + b level_done + .endm + +level_done: + add x10, x10, #2 // increment cache number + cmp x3, x10 + b.hi loop1 + msr csselr_el1, xzr // select cache level 0 in csselr + dsb sy // barrier to complete final cache operation + isb +exit: + ret +endfunc do_dcsw_op + +dcsw_loop_table: + dcsw_loop isw + dcsw_loop cisw + dcsw_loop csw + + +func dcsw_op_louis + dcsw_op #LOUIS_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_louis + + +func dcsw_op_all + dcsw_op #LOC_SHIFT, #CLIDR_FIELD_WIDTH, #LEVEL_SHIFT +endfunc dcsw_op_all + + /* --------------------------------------------------------------- + * Helper macro for data cache operations by set/way for the + * level specified + * --------------------------------------------------------------- + */ + .macro dcsw_op_level level + mrs x9, clidr_el1 + mov x3, \level + sub x10, x3, #2 + b do_dcsw_op + .endm + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 1 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level1 + dcsw_op_level #(1 << LEVEL_SHIFT) +endfunc dcsw_op_level1 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 2 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level2 + dcsw_op_level #(2 << LEVEL_SHIFT) +endfunc dcsw_op_level2 + + /* --------------------------------------------------------------- + * Data cache operations by set/way for level 3 cache + * + * The main function, do_dcsw_op requires: + * x0: The operation type (0-2), as defined in arch.h + * --------------------------------------------------------------- + */ +func dcsw_op_level3 + dcsw_op_level #(3 << LEVEL_SHIFT) +endfunc dcsw_op_level3 diff --git a/arm-trusted-firmware/lib/aarch64/misc_helpers.S b/arm-trusted-firmware/lib/aarch64/misc_helpers.S new file mode 100644 index 0000000..e8110b0 --- /dev/null +++ b/arm-trusted-firmware/lib/aarch64/misc_helpers.S @@ -0,0 +1,613 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .globl smc + + .globl zero_normalmem + .globl zeromem + .globl memcpy16 + .globl gpt_tlbi_by_pa_ll + + .globl disable_mmu_el1 + .globl disable_mmu_el3 + .globl disable_mmu_icache_el1 + .globl disable_mmu_icache_el3 + .globl fixup_gdt_reloc +#if SUPPORT_VFP + .globl enable_vfp +#endif + +func smc + smc #0 +endfunc smc + +/* ----------------------------------------------------------------------- + * void zero_normalmem(void *mem, unsigned int length); + * + * Initialise a region in normal memory to 0. This functions complies with the + * AAPCS and can be called from C code. + * + * NOTE: MMU must be enabled when using this function as it can only operate on + * normal memory. It is intended to be mainly used from C code when MMU + * is usually enabled. + * ----------------------------------------------------------------------- + */ +.equ zero_normalmem, zeromem_dczva + +/* ----------------------------------------------------------------------- + * void zeromem(void *mem, unsigned int length); + * + * Initialise a region of device memory to 0. This functions complies with the + * AAPCS and can be called from C code. + * + * NOTE: When data caches and MMU are enabled, zero_normalmem can usually be + * used instead for faster zeroing. + * + * ----------------------------------------------------------------------- + */ +func zeromem + /* x2 is the address past the last zeroed address */ + add x2, x0, x1 + /* + * Uses the fallback path that does not use DC ZVA instruction and + * therefore does not need enabled MMU + */ + b .Lzeromem_dczva_fallback_entry +endfunc zeromem + +/* ----------------------------------------------------------------------- + * void zeromem_dczva(void *mem, unsigned int length); + * + * Fill a region of normal memory of size "length" in bytes with null bytes. + * MMU must be enabled and the memory be of + * normal type. This is because this function internally uses the DC ZVA + * instruction, which generates an Alignment fault if used on any type of + * Device memory (see section D3.4.9 of the ARMv8 ARM, issue k). When the MMU + * is disabled, all memory behaves like Device-nGnRnE memory (see section + * D4.2.8), hence the requirement on the MMU being enabled. + * NOTE: The code assumes that the block size as defined in DCZID_EL0 + * register is at least 16 bytes. + * + * ----------------------------------------------------------------------- + */ +func zeromem_dczva + + /* + * The function consists of a series of loops that zero memory one byte + * at a time, 16 bytes at a time or using the DC ZVA instruction to + * zero aligned block of bytes, which is assumed to be more than 16. + * In the case where the DC ZVA instruction cannot be used or if the + * first 16 bytes loop would overflow, there is fallback path that does + * not use DC ZVA. + * Note: The fallback path is also used by the zeromem function that + * branches to it directly. + * + * +---------+ zeromem_dczva + * | entry | + * +----+----+ + * | + * v + * +---------+ + * | checks |>o-------+ (If any check fails, fallback) + * +----+----+ | + * | |---------------+ + * v | Fallback path | + * +------+------+ |---------------+ + * | 1 byte loop | | + * +------+------+ .Lzeromem_dczva_initial_1byte_aligned_end + * | | + * v | + * +-------+-------+ | + * | 16 bytes loop | | + * +-------+-------+ | + * | | + * v | + * +------+------+ .Lzeromem_dczva_blocksize_aligned + * | DC ZVA loop | | + * +------+------+ | + * +--------+ | | + * | | | | + * | v v | + * | +-------+-------+ .Lzeromem_dczva_final_16bytes_aligned + * | | 16 bytes loop | | + * | +-------+-------+ | + * | | | + * | v | + * | +------+------+ .Lzeromem_dczva_final_1byte_aligned + * | | 1 byte loop | | + * | +-------------+ | + * | | | + * | v | + * | +---+--+ | + * | | exit | | + * | +------+ | + * | | + * | +--------------+ +------------------+ zeromem + * | | +----------------| zeromem function | + * | | | +------------------+ + * | v v + * | +-------------+ .Lzeromem_dczva_fallback_entry + * | | 1 byte loop | + * | +------+------+ + * | | + * +-----------+ + */ + + /* + * Readable names for registers + * + * Registers x0, x1 and x2 are also set by zeromem which + * branches into the fallback path directly, so cursor, length and + * stop_address should not be retargeted to other registers. + */ + cursor .req x0 /* Start address and then current address */ + length .req x1 /* Length in bytes of the region to zero out */ + /* Reusing x1 as length is never used after block_mask is set */ + block_mask .req x1 /* Bitmask of the block size read in DCZID_EL0 */ + stop_address .req x2 /* Address past the last zeroed byte */ + block_size .req x3 /* Size of a block in bytes as read in DCZID_EL0 */ + tmp1 .req x4 + tmp2 .req x5 + +#if ENABLE_ASSERTIONS + /* + * Check for M bit (MMU enabled) of the current SCTLR_EL(1|3) + * register value and panic if the MMU is disabled. + */ +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && \ + (BL2_AT_EL3 || ENABLE_RME)) + mrs tmp1, sctlr_el3 +#else + mrs tmp1, sctlr_el1 +#endif + + tst tmp1, #SCTLR_M_BIT + ASM_ASSERT(ne) +#endif /* ENABLE_ASSERTIONS */ + + /* stop_address is the address past the last to zero */ + add stop_address, cursor, length + + /* + * Get block_size = (log2() >> 2) (see encoding of + * dczid_el0 reg) + */ + mrs block_size, dczid_el0 + + /* + * Select the 4 lowest bits and convert the extracted log2() to + */ + ubfx block_size, block_size, #0, #4 + mov tmp2, #(1 << 2) + lsl block_size, tmp2, block_size + +#if ENABLE_ASSERTIONS + /* + * Assumes block size is at least 16 bytes to avoid manual realignment + * of the cursor at the end of the DCZVA loop. + */ + cmp block_size, #16 + ASM_ASSERT(hs) +#endif + /* + * Not worth doing all the setup for a region less than a block and + * protects against zeroing a whole block when the area to zero is + * smaller than that. Also, as it is assumed that the block size is at + * least 16 bytes, this also protects the initial aligning loops from + * trying to zero 16 bytes when length is less than 16. + */ + cmp length, block_size + b.lo .Lzeromem_dczva_fallback_entry + + /* + * Calculate the bitmask of the block alignment. It will never + * underflow as the block size is between 4 bytes and 2kB. + * block_mask = block_size - 1 + */ + sub block_mask, block_size, #1 + + /* + * length alias should not be used after this point unless it is + * defined as a register other than block_mask's. + */ + .unreq length + + /* + * If the start address is already aligned to zero block size, go + * straight to the cache zeroing loop. This is safe because at this + * point, the length cannot be smaller than a block size. + */ + tst cursor, block_mask + b.eq .Lzeromem_dczva_blocksize_aligned + + /* + * Calculate the first block-size-aligned address. It is assumed that + * the zero block size is at least 16 bytes. This address is the last + * address of this initial loop. + */ + orr tmp1, cursor, block_mask + add tmp1, tmp1, #1 + + /* + * If the addition overflows, skip the cache zeroing loops. This is + * quite unlikely however. + */ + cbz tmp1, .Lzeromem_dczva_fallback_entry + + /* + * If the first block-size-aligned address is past the last address, + * fallback to the simpler code. + */ + cmp tmp1, stop_address + b.hi .Lzeromem_dczva_fallback_entry + + /* + * If the start address is already aligned to 16 bytes, skip this loop. + * It is safe to do this because tmp1 (the stop address of the initial + * 16 bytes loop) will never be greater than the final stop address. + */ + tst cursor, #0xf + b.eq .Lzeromem_dczva_initial_1byte_aligned_end + + /* Calculate the next address aligned to 16 bytes */ + orr tmp2, cursor, #0xf + add tmp2, tmp2, #1 + /* If it overflows, fallback to the simple path (unlikely) */ + cbz tmp2, .Lzeromem_dczva_fallback_entry + /* + * Next aligned address cannot be after the stop address because the + * length cannot be smaller than 16 at this point. + */ + + /* First loop: zero byte per byte */ +1: + strb wzr, [cursor], #1 + cmp cursor, tmp2 + b.ne 1b +.Lzeromem_dczva_initial_1byte_aligned_end: + + /* + * Second loop: we need to zero 16 bytes at a time from cursor to tmp1 + * before being able to use the code that deals with block-size-aligned + * addresses. + */ + cmp cursor, tmp1 + b.hs 2f +1: + stp xzr, xzr, [cursor], #16 + cmp cursor, tmp1 + b.lo 1b +2: + + /* + * Third loop: zero a block at a time using DC ZVA cache block zeroing + * instruction. + */ +.Lzeromem_dczva_blocksize_aligned: + /* + * Calculate the last block-size-aligned address. If the result equals + * to the start address, the loop will exit immediately. + */ + bic tmp1, stop_address, block_mask + + cmp cursor, tmp1 + b.hs 2f +1: + /* Zero the block containing the cursor */ + dc zva, cursor + /* Increment the cursor by the size of a block */ + add cursor, cursor, block_size + cmp cursor, tmp1 + b.lo 1b +2: + + /* + * Fourth loop: zero 16 bytes at a time and then byte per byte the + * remaining area + */ +.Lzeromem_dczva_final_16bytes_aligned: + /* + * Calculate the last 16 bytes aligned address. It is assumed that the + * block size will never be smaller than 16 bytes so that the current + * cursor is aligned to at least 16 bytes boundary. + */ + bic tmp1, stop_address, #15 + + cmp cursor, tmp1 + b.hs 2f +1: + stp xzr, xzr, [cursor], #16 + cmp cursor, tmp1 + b.lo 1b +2: + + /* Fifth and final loop: zero byte per byte */ +.Lzeromem_dczva_final_1byte_aligned: + cmp cursor, stop_address + b.eq 2f +1: + strb wzr, [cursor], #1 + cmp cursor, stop_address + b.ne 1b +2: + ret + + /* Fallback for unaligned start addresses */ +.Lzeromem_dczva_fallback_entry: + /* + * If the start address is already aligned to 16 bytes, skip this loop. + */ + tst cursor, #0xf + b.eq .Lzeromem_dczva_final_16bytes_aligned + + /* Calculate the next address aligned to 16 bytes */ + orr tmp1, cursor, #15 + add tmp1, tmp1, #1 + /* If it overflows, fallback to byte per byte zeroing */ + cbz tmp1, .Lzeromem_dczva_final_1byte_aligned + /* If the next aligned address is after the stop address, fall back */ + cmp tmp1, stop_address + b.hs .Lzeromem_dczva_final_1byte_aligned + + /* Fallback entry loop: zero byte per byte */ +1: + strb wzr, [cursor], #1 + cmp cursor, tmp1 + b.ne 1b + + b .Lzeromem_dczva_final_16bytes_aligned + + .unreq cursor + /* + * length is already unreq'ed to reuse the register for another + * variable. + */ + .unreq stop_address + .unreq block_size + .unreq block_mask + .unreq tmp1 + .unreq tmp2 +endfunc zeromem_dczva + +/* -------------------------------------------------------------------------- + * void memcpy16(void *dest, const void *src, unsigned int length) + * + * Copy length bytes from memory area src to memory area dest. + * The memory areas should not overlap. + * Destination and source addresses must be 16-byte aligned. + * -------------------------------------------------------------------------- + */ +func memcpy16 +#if ENABLE_ASSERTIONS + orr x3, x0, x1 + tst x3, #0xf + ASM_ASSERT(eq) +#endif +/* copy 16 bytes at a time */ +m_loop16: + cmp x2, #16 + b.lo 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, m_end + ldrb w3, [x1], #1 + strb w3, [x0], #1 + subs x2, x2, #1 + b.ne m_loop1 +m_end: + ret +endfunc memcpy16 + +/* --------------------------------------------------------------------------- + * Disable the MMU at EL3 + * --------------------------------------------------------------------------- + */ + +func disable_mmu_el3 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu_el3: + mrs x0, sctlr_el3 + bic x0, x0, x1 + msr sctlr_el3, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mmu_el3 + + +func disable_mmu_icache_el3 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu_el3 +endfunc disable_mmu_icache_el3 + +/* --------------------------------------------------------------------------- + * Disable the MMU at EL1 + * --------------------------------------------------------------------------- + */ + +func disable_mmu_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT) +do_disable_mmu_el1: + mrs x0, sctlr_el1 + bic x0, x0, x1 + msr sctlr_el1, x0 + isb /* ensure MMU is off */ + dsb sy + ret +endfunc disable_mmu_el1 + + +func disable_mmu_icache_el1 + mov x1, #(SCTLR_M_BIT | SCTLR_C_BIT | SCTLR_I_BIT) + b do_disable_mmu_el1 +endfunc disable_mmu_icache_el1 + +/* --------------------------------------------------------------------------- + * Enable the use of VFP at EL3 + * --------------------------------------------------------------------------- + */ +#if SUPPORT_VFP +func enable_vfp + mrs x0, cpacr_el1 + orr x0, x0, #CPACR_VFP_BITS + msr cpacr_el1, x0 + mrs x0, cptr_el3 + mov x1, #AARCH64_CPTR_TFP + bic x0, x0, x1 + msr cptr_el3, x0 + isb + ret +endfunc enable_vfp +#endif + +/* --------------------------------------------------------------------------- + * Helper to fixup Global Descriptor table (GDT) and dynamic relocations + * (.rela.dyn) at runtime. + * + * This function is meant to be used when the firmware is compiled with -fpie + * and linked with -pie options. We rely on the linker script exporting + * appropriate markers for start and end of the section. For GOT, we + * expect __GOT_START__ and __GOT_END__. Similarly for .rela.dyn, we expect + * __RELA_START__ and __RELA_END__. + * + * The function takes the limits of the memory to apply fixups to as + * arguments (which is usually the limits of the relocable BL image). + * x0 - the start of the fixup region + * x1 - the limit of the fixup region + * These addresses have to be 4KB page aligned. + * --------------------------------------------------------------------------- + */ + +/* Relocation codes */ +#define R_AARCH64_NONE 0 +#define R_AARCH64_RELATIVE 1027 + +func fixup_gdt_reloc + mov x6, x0 + mov x7, x1 + +#if ENABLE_ASSERTIONS + /* Test if the limits are 4KB aligned */ + orr x0, x0, x1 + tst x0, #(PAGE_SIZE_MASK) + ASM_ASSERT(eq) +#endif + /* + * Calculate the offset based on return address in x30. + * Assume that this function is called within a page at the start of + * fixup region. + */ + and x2, x30, #~(PAGE_SIZE_MASK) + subs x0, x2, x6 /* Diff(S) = Current Address - Compiled Address */ + b.eq 3f /* Diff(S) = 0. No relocation needed */ + + adrp x1, __GOT_START__ + add x1, x1, :lo12:__GOT_START__ + adrp x2, __GOT_END__ + add x2, x2, :lo12:__GOT_END__ + + /* + * GOT is an array of 64_bit addresses which must be fixed up as + * new_addr = old_addr + Diff(S). + * The new_addr is the address currently the binary is executing from + * and old_addr is the address at compile time. + */ +1: ldr x3, [x1] + + /* Skip adding offset if address is < lower limit */ + cmp x3, x6 + b.lo 2f + + /* Skip adding offset if address is > upper limit */ + cmp x3, x7 + b.hi 2f + add x3, x3, x0 + str x3, [x1] + +2: add x1, x1, #8 + cmp x1, x2 + b.lo 1b + + /* Starting dynamic relocations. Use adrp/adr to get RELA_START and END */ +3: adrp x1, __RELA_START__ + add x1, x1, :lo12:__RELA_START__ + adrp x2, __RELA_END__ + add x2, x2, :lo12:__RELA_END__ + + /* + * According to ELF-64 specification, the RELA data structure is as + * follows: + * typedef struct { + * Elf64_Addr r_offset; + * Elf64_Xword r_info; + * Elf64_Sxword r_addend; + * } Elf64_Rela; + * + * r_offset is address of reference + * r_info is symbol index and type of relocation (in this case + * code 1027 which corresponds to R_AARCH64_RELATIVE). + * r_addend is constant part of expression. + * + * Size of Elf64_Rela structure is 24 bytes. + */ + + /* Skip R_AARCH64_NONE entry with code 0 */ +1: ldr x3, [x1, #8] + cbz x3, 2f + +#if ENABLE_ASSERTIONS + /* Assert that the relocation type is R_AARCH64_RELATIVE */ + cmp x3, #R_AARCH64_RELATIVE + ASM_ASSERT(eq) +#endif + ldr x3, [x1] /* r_offset */ + add x3, x0, x3 + ldr x4, [x1, #16] /* r_addend */ + + /* Skip adding offset if r_addend is < lower limit */ + cmp x4, x6 + b.lo 2f + + /* Skip adding offset if r_addend entry is > upper limit */ + cmp x4, x7 + b.hi 2f + + add x4, x0, x4 /* Diff(S) + r_addend */ + str x4, [x3] + +2: add x1, x1, #24 + cmp x1, x2 + b.lo 1b + ret +endfunc fixup_gdt_reloc + +/* + * TODO: Currently only supports size of 4KB, + * support other sizes as well. + */ +func gpt_tlbi_by_pa_ll +#if ENABLE_ASSERTIONS + cmp x1, #PAGE_SIZE_4KB + ASM_ASSERT(eq) + tst x0, #(PAGE_SIZE_MASK) + ASM_ASSERT(eq) +#endif + lsr x0, x0, #FOUR_KB_SHIFT /* 4KB size encoding is zero */ + sys #6, c8, c4, #7, x0 /* TLBI RPALOS, */ + dsb sy + ret +endfunc gpt_tlbi_by_pa_ll diff --git a/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c b/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c new file mode 100644 index 0000000..7f357b7 --- /dev/null +++ b/arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + +#include +#include +#include + +void bl_aux_params_parse(u_register_t head, + bl_aux_param_handler_t handler) +{ + struct bl_aux_param_header *p; + + for (p = (void *)head; p; p = (void *)(uintptr_t)p->next) { + if (handler && handler(p)) + continue; + + switch (p->type) { +#if COREBOOT + case BL_AUX_PARAM_COREBOOT_TABLE: + coreboot_table_setup((void *)(uintptr_t) + ((struct bl_aux_param_uint64 *)p)->value); + break; +#endif + default: + ERROR("Ignoring unknown BL aux parameter: 0x%" PRIx64, + p->type); + break; + } + } +} diff --git a/arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT b/arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT new file mode 100644 index 0000000..a17dc12 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT @@ -0,0 +1,91 @@ +============================================================================== +compiler_rt License +============================================================================== + +The compiler_rt library is dual licensed under both the University of Illinois +"BSD-Like" license and the MIT license. As a user of this code you may choose +to use it under either license. As a contributor, you agree to allow your code +to be used under both. + +Full text of the relevant licenses is included below. + +============================================================================== + +University of Illinois/NCSA +Open Source License + +Copyright (c) 2009-2016 by the contributors listed in CREDITS.TXT + +All rights reserved. + +Developed by: + + LLVM Team + + University of Illinois at Urbana-Champaign + + http://llvm.org + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal with +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies +of the Software, and to permit persons to whom the Software is furnished to do +so, subject to the following conditions: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimers. + + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimers in the + documentation and/or other materials provided with the distribution. + + * Neither the names of the LLVM Team, University of Illinois at + Urbana-Champaign, nor the names of its contributors may be used to + endorse or promote products derived from this Software without specific + prior written permission. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE +SOFTWARE. + +============================================================================== + +Copyright (c) 2009-2015 by the contributors listed in CREDITS.TXT + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. + +============================================================================== +Copyrights and Licenses for Third Party Software Distributed with LLVM: +============================================================================== +The LLVM software contains code written by third parties. Such software will +have its own individual LICENSE.TXT file in the directory in which it appears. +This file will describe the copyrights, license, and restrictions which apply +to that code. + +The disclaimer of warranty in the University of Illinois Open Source License +applies to all code in the LLVM Distribution, and nothing in any of the +other licenses gives permission to use the names of the LLVM Team or the +University of Illinois to endorse or promote products derived from this +Software. + diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S new file mode 100644 index 0000000..038ae5d --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S @@ -0,0 +1,46 @@ +//===-- aeabi_ldivmod.S - EABI ldivmod implementation ---------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// struct { int64_t quot, int64_t rem} +// __aeabi_ldivmod(int64_t numerator, int64_t denominator) { +// int64_t rem, quot; +// quot = __divmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + +#if defined(__MINGW32__) +#define __aeabi_ldivmod __rt_sdiv64 +#endif + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_ldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] +#if defined(__MINGW32__) + movs r6, r0 + movs r0, r2 + movs r2, r6 + movs r6, r1 + movs r1, r3 + movs r3, r6 +#endif + bl SYMBOL_NAME(__divmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_ldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S new file mode 100644 index 0000000..be343b6 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S @@ -0,0 +1,46 @@ +//===-- aeabi_uldivmod.S - EABI uldivmod implementation -------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../assembly.h" + +// struct { uint64_t quot, uint64_t rem} +// __aeabi_uldivmod(uint64_t numerator, uint64_t denominator) { +// uint64_t rem, quot; +// quot = __udivmoddi4(numerator, denominator, &rem); +// return {quot, rem}; +// } + +#if defined(__MINGW32__) +#define __aeabi_uldivmod __rt_udiv64 +#endif + + .syntax unified + .p2align 2 +DEFINE_COMPILERRT_FUNCTION(__aeabi_uldivmod) + push {r6, lr} + sub sp, sp, #16 + add r6, sp, #8 + str r6, [sp] +#if defined(__MINGW32__) + movs r6, r0 + movs r0, r2 + movs r2, r6 + movs r6, r1 + movs r1, r3 + movs r3, r6 +#endif + bl SYMBOL_NAME(__udivmoddi4) + ldr r2, [sp, #8] + ldr r3, [sp, #12] + add sp, sp, #16 + pop {r6, pc} +END_COMPILERRT_FUNCTION(__aeabi_uldivmod) + +NO_EXEC_STACK_DIRECTIVE + diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h b/arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h new file mode 100644 index 0000000..29d9f88 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h @@ -0,0 +1,169 @@ +/* ===-- assembly.h - compiler-rt assembler support macros -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file defines macros for use in compiler-rt assembler source. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef COMPILERRT_ASSEMBLY_H +#define COMPILERRT_ASSEMBLY_H + +#if defined(__POWERPC__) || defined(__powerpc__) || defined(__ppc__) +#define SEPARATOR @ +#else +#define SEPARATOR ; +#endif + +#if defined(__APPLE__) +#define HIDDEN(name) .private_extern name +#define LOCAL_LABEL(name) L_##name +// tell linker it can break up file at label boundaries +#define FILE_LEVEL_DIRECTIVE .subsections_via_symbols +#define SYMBOL_IS_FUNC(name) +#define CONST_SECTION .const + +#define NO_EXEC_STACK_DIRECTIVE + +#elif defined(__ELF__) + +#define HIDDEN(name) .hidden name +#define LOCAL_LABEL(name) .L_##name +#define FILE_LEVEL_DIRECTIVE +#if defined(__arm__) +#define SYMBOL_IS_FUNC(name) .type name,%function +#else +#define SYMBOL_IS_FUNC(name) .type name,@function +#endif +#define CONST_SECTION .section .rodata + +#if defined(__GNU__) || defined(__ANDROID__) || defined(__FreeBSD__) +#define NO_EXEC_STACK_DIRECTIVE .section .note.GNU-stack,"",%progbits +#else +#define NO_EXEC_STACK_DIRECTIVE +#endif + +#else // !__APPLE__ && !__ELF__ + +#define HIDDEN(name) +#define LOCAL_LABEL(name) .L ## name +#define FILE_LEVEL_DIRECTIVE +#define SYMBOL_IS_FUNC(name) \ + .def name SEPARATOR \ + .scl 2 SEPARATOR \ + .type 32 SEPARATOR \ + .endef +#define CONST_SECTION .section .rdata,"rd" + +#define NO_EXEC_STACK_DIRECTIVE + +#endif + +#if defined(__arm__) +#if defined(__ARM_ARCH_4T__) || __ARM_ARCH >= 5 +#define ARM_HAS_BX +#endif +#if !defined(__ARM_FEATURE_CLZ) && __ARM_ARCH_ISA_THUMB != 1 && \ + (__ARM_ARCH >= 6 || (__ARM_ARCH == 5 && !defined(__ARM_ARCH_5__))) +#define __ARM_FEATURE_CLZ +#endif + +#ifdef ARM_HAS_BX +#define JMP(r) bx r +#define JMPc(r, c) bx##c r +#else +#define JMP(r) mov pc, r +#define JMPc(r, c) mov##c pc, r +#endif + +// pop {pc} can't switch Thumb mode on ARMv4T +#if __ARM_ARCH >= 5 +#define POP_PC() pop {pc} +#else +#define POP_PC() \ + pop {ip}; \ + JMP(ip) +#endif + +#if __ARM_ARCH_ISA_THUMB == 2 +#define IT(cond) it cond +#define ITT(cond) itt cond +#else +#define IT(cond) +#define ITT(cond) +#endif + +#if __ARM_ARCH_ISA_THUMB == 2 +#define WIDE(op) op.w +#else +#define WIDE(op) op +#endif +#endif + +#define GLUE2(a, b) a##b +#define GLUE(a, b) GLUE2(a, b) +#define SYMBOL_NAME(name) GLUE(__USER_LABEL_PREFIX__, name) + +#ifdef VISIBILITY_HIDDEN +#define DECLARE_SYMBOL_VISIBILITY(name) \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR +#else +#define DECLARE_SYMBOL_VISIBILITY(name) +#endif + +#define DEFINE_COMPILERRT_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_THUMB_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(name) SEPARATOR \ + .thumb_func SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION(name) \ + FILE_LEVEL_DIRECTIVE SEPARATOR \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + HIDDEN(SYMBOL_NAME(name)) SEPARATOR \ + SYMBOL_NAME(name): + +#define DEFINE_COMPILERRT_PRIVATE_FUNCTION_UNMANGLED(name) \ + .globl name SEPARATOR \ + SYMBOL_IS_FUNC(name) SEPARATOR \ + HIDDEN(name) SEPARATOR \ + name: + +#define DEFINE_COMPILERRT_FUNCTION_ALIAS(name, target) \ + .globl SYMBOL_NAME(name) SEPARATOR \ + SYMBOL_IS_FUNC(SYMBOL_NAME(name)) SEPARATOR \ + DECLARE_SYMBOL_VISIBILITY(SYMBOL_NAME(name)) SEPARATOR \ + .set SYMBOL_NAME(name), SYMBOL_NAME(target) SEPARATOR + +#if defined(__ARM_EABI__) +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) \ + DEFINE_COMPILERRT_FUNCTION_ALIAS(aeabi_name, name) +#else +#define DEFINE_AEABI_FUNCTION_ALIAS(aeabi_name, name) +#endif + +#ifdef __ELF__ +#define END_COMPILERRT_FUNCTION(name) \ + .size SYMBOL_NAME(name), . - SYMBOL_NAME(name) +#else +#define END_COMPILERRT_FUNCTION(name) +#endif + +#endif /* COMPILERRT_ASSEMBLY_H */ diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c new file mode 100644 index 0000000..db3c6fd --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c @@ -0,0 +1,29 @@ +/* ===-- ctzdi2.c - Implement __ctzdi2 -------------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __ctzdi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: the number of trailing 0-bits */ + +/* Precondition: a != 0 */ + +COMPILER_RT_ABI si_int +__ctzdi2(di_int a) +{ + dwords x; + x.all = a; + const si_int f = -(x.s.low == 0); + return __builtin_ctz((x.s.high & f) | (x.s.low & ~f)) + + (f & ((si_int)(sizeof(si_int) * CHAR_BIT))); +} diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c b/arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c new file mode 100644 index 0000000..b8eebcb --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c @@ -0,0 +1,29 @@ +/* ===-- divdi3.c - Implement __divdi3 -------------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __divdi3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: a / b */ + +COMPILER_RT_ABI di_int +__divdi3(di_int a, di_int b) +{ + const int bits_in_dword_m1 = (int)(sizeof(di_int) * CHAR_BIT) - 1; + di_int s_a = a >> bits_in_dword_m1; /* s_a = a < 0 ? -1 : 0 */ + di_int s_b = b >> bits_in_dword_m1; /* s_b = b < 0 ? -1 : 0 */ + a = (a ^ s_a) - s_a; /* negate if s_a == -1 */ + b = (b ^ s_b) - s_b; /* negate if s_b == -1 */ + s_a ^= s_b; /*sign of quotient */ + return (__udivmoddi4(a, b, (du_int*)0) ^ s_a) - s_a; /* negate if s_a == -1 */ +} diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c b/arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c new file mode 100644 index 0000000..0d4df67 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c @@ -0,0 +1,25 @@ +/*===-- divmoddi4.c - Implement __divmoddi4 --------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __divmoddi4 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: a / b, *rem = a % b */ + +COMPILER_RT_ABI di_int +__divmoddi4(di_int a, di_int b, di_int* rem) +{ + di_int d = __divdi3(a,b); + *rem = a - (d*b); + return d; +} diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h new file mode 100644 index 0000000..7995ddb --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h @@ -0,0 +1,116 @@ +/* ===-- int_endianness.h - configuration header for compiler-rt ------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is a configuration header for compiler-rt. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef INT_ENDIANNESS_H +#define INT_ENDIANNESS_H + +#if defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && \ + defined(__ORDER_LITTLE_ENDIAN__) + +/* Clang and GCC provide built-in endianness definitions. */ +#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* __BYTE_ORDER__ */ + +#else /* Compilers other than Clang or GCC. */ + +#if defined(__SVR4) && defined(__sun) +#include + +#if defined(_BIG_ENDIAN) +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif defined(_LITTLE_ENDIAN) +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#else /* !_LITTLE_ENDIAN */ +#error "unknown endianness" +#endif /* !_LITTLE_ENDIAN */ + +#endif /* Solaris and AuroraUX. */ + +/* .. */ + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__DragonFly__) || \ + defined(__minix) +#include + +#if _BYTE_ORDER == _BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif _BYTE_ORDER == _LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* _BYTE_ORDER */ + +#endif /* *BSD */ + +#if defined(__OpenBSD__) || defined(__Bitrig__) +#include + +#if _BYTE_ORDER == _BIG_ENDIAN +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#elif _BYTE_ORDER == _LITTLE_ENDIAN +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif /* _BYTE_ORDER */ + +#endif /* OpenBSD and Bitrig. */ + +/* .. */ + +/* Mac OSX has __BIG_ENDIAN__ or __LITTLE_ENDIAN__ automatically set by the + * compiler (at least with GCC) */ +#if defined(__APPLE__) || defined(__ellcc__ ) + +#ifdef __BIG_ENDIAN__ +#if __BIG_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 0 +#define _YUGA_BIG_ENDIAN 1 +#endif +#endif /* __BIG_ENDIAN__ */ + +#ifdef __LITTLE_ENDIAN__ +#if __LITTLE_ENDIAN__ +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 +#endif +#endif /* __LITTLE_ENDIAN__ */ + +#endif /* Mac OSX */ + +/* .. */ + +#if defined(_WIN32) + +#define _YUGA_LITTLE_ENDIAN 1 +#define _YUGA_BIG_ENDIAN 0 + +#endif /* Windows */ + +#endif /* Clang or GCC. */ + +/* . */ + +#if !defined(_YUGA_LITTLE_ENDIAN) || !defined(_YUGA_BIG_ENDIAN) +#error Unable to determine endian +#endif /* Check we found an endianness correctly. */ + +#endif /* INT_ENDIANNESS_H */ diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h new file mode 100644 index 0000000..80a7c41 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h @@ -0,0 +1,127 @@ +/* ===-- int_lib.h - configuration header for compiler-rt -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is a configuration header for compiler-rt. + * This file is not part of the interface of this library. + * + * ===----------------------------------------------------------------------=== + */ + +/* + * Portions copyright (c) 2017-2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#ifndef INT_LIB_H +#define INT_LIB_H + +/* Assumption: Signed integral is 2's complement. */ +/* Assumption: Right shift of signed negative is arithmetic shift. */ +/* Assumption: Endianness is little or big (not mixed). */ + +#if defined(__ELF__) +#define FNALIAS(alias_name, original_name) \ + void alias_name() __attribute__((__alias__(#original_name))) +#define COMPILER_RT_ALIAS(aliasee) __attribute__((__alias__(#aliasee))) +#else +#define FNALIAS(alias, name) _Pragma("GCC error(\"alias unsupported on this file format\")") +#define COMPILER_RT_ALIAS(aliasee) _Pragma("GCC error(\"alias unsupported on this file format\")") +#endif + +/* ABI macro definitions */ + +#if __ARM_EABI__ +# ifdef COMPILER_RT_ARMHF_TARGET +# define COMPILER_RT_ABI +# else +# define COMPILER_RT_ABI __attribute__((__pcs__("aapcs"))) +# endif +#else +# define COMPILER_RT_ABI +#endif + +#define AEABI_RTABI __attribute__((__pcs__("aapcs"))) + +#if defined(_MSC_VER) && !defined(__clang__) +#define ALWAYS_INLINE __forceinline +#define NOINLINE __declspec(noinline) +#define NORETURN __declspec(noreturn) +#define UNUSED +#else +#define ALWAYS_INLINE __attribute__((always_inline)) +#define NOINLINE __attribute__((noinline)) +#define NORETURN __attribute__((noreturn)) +#define UNUSED __attribute__((unused)) +#endif + +/* + * Kernel and boot environment can't use normal headers, + * so use the equivalent system headers. + */ +# include +# include + +/* Include the commonly used internal type definitions. */ +#include "int_types.h" + +COMPILER_RT_ABI si_int __paritysi2(si_int a); +COMPILER_RT_ABI si_int __paritydi2(di_int a); + +COMPILER_RT_ABI di_int __divdi3(di_int a, di_int b); +COMPILER_RT_ABI si_int __divsi3(si_int a, si_int b); +COMPILER_RT_ABI su_int __udivsi3(su_int n, su_int d); + +COMPILER_RT_ABI su_int __udivmodsi4(su_int a, su_int b, su_int* rem); +COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int* rem); +#ifdef CRT_HAS_128BIT +COMPILER_RT_ABI si_int __clzti2(ti_int a); +COMPILER_RT_ABI tu_int __udivmodti4(tu_int a, tu_int b, tu_int* rem); +#endif + +/* Definitions for builtins unavailable on MSVC */ +#if defined(_MSC_VER) && !defined(__clang__) +#include + +uint32_t __inline __builtin_ctz(uint32_t value) { + unsigned long trailing_zero = 0; + if (_BitScanForward(&trailing_zero, value)) + return trailing_zero; + return 32; +} + +uint32_t __inline __builtin_clz(uint32_t value) { + unsigned long leading_zero = 0; + if (_BitScanReverse(&leading_zero, value)) + return 31 - leading_zero; + return 32; +} + +#if defined(_M_ARM) || defined(_M_X64) +uint32_t __inline __builtin_clzll(uint64_t value) { + unsigned long leading_zero = 0; + if (_BitScanReverse64(&leading_zero, value)) + return 63 - leading_zero; + return 64; +} +#else +uint32_t __inline __builtin_clzll(uint64_t value) { + if (value == 0) + return 64; + uint32_t msh = (uint32_t)(value >> 32); + uint32_t lsh = (uint32_t)(value & 0xFFFFFFFF); + if (msh != 0) + return __builtin_clz(msh); + return 32 + __builtin_clz(lsh); +} +#endif + +#define __builtin_clzl __builtin_clzll +#endif /* defined(_MSC_VER) && !defined(__clang__) */ + +#endif /* INT_LIB_H */ diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h new file mode 100644 index 0000000..fc81fb7 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h @@ -0,0 +1,114 @@ +/* ===-- int_math.h - internal math inlines ---------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===-----------------------------------------------------------------------=== + * + * This file is not part of the interface of this library. + * + * This file defines substitutes for the libm functions used in some of the + * compiler-rt implementations, defined in such a way that there is not a direct + * dependency on libm or math.h. Instead, we use the compiler builtin versions + * where available. This reduces our dependencies on the system SDK by foisting + * the responsibility onto the compiler. + * + * ===-----------------------------------------------------------------------=== + */ + +#ifndef INT_MATH_H +#define INT_MATH_H + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#include +#include +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define CRT_INFINITY INFINITY +#else +#define CRT_INFINITY __builtin_huge_valf() +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_isfinite(x) _finite((x)) +#define crt_isinf(x) !_finite((x)) +#define crt_isnan(x) _isnan((x)) +#else +/* Define crt_isfinite in terms of the builtin if available, otherwise provide + * an alternate version in terms of our other functions. This supports some + * versions of GCC which didn't have __builtin_isfinite. + */ +#if __has_builtin(__builtin_isfinite) +# define crt_isfinite(x) __builtin_isfinite((x)) +#elif defined(__GNUC__) +# define crt_isfinite(x) \ + __extension__(({ \ + __typeof((x)) x_ = (x); \ + !crt_isinf(x_) && !crt_isnan(x_); \ + })) +#else +# error "Do not know how to check for infinity" +#endif /* __has_builtin(__builtin_isfinite) */ +#define crt_isinf(x) __builtin_isinf((x)) +#define crt_isnan(x) __builtin_isnan((x)) +#endif /* _MSC_VER */ + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_copysign(x, y) copysign((x), (y)) +#define crt_copysignf(x, y) copysignf((x), (y)) +#define crt_copysignl(x, y) copysignl((x), (y)) +#else +#define crt_copysign(x, y) __builtin_copysign((x), (y)) +#define crt_copysignf(x, y) __builtin_copysignf((x), (y)) +#define crt_copysignl(x, y) __builtin_copysignl((x), (y)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_fabs(x) fabs((x)) +#define crt_fabsf(x) fabsf((x)) +#define crt_fabsl(x) fabs((x)) +#else +#define crt_fabs(x) __builtin_fabs((x)) +#define crt_fabsf(x) __builtin_fabsf((x)) +#define crt_fabsl(x) __builtin_fabsl((x)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_fmax(x, y) __max((x), (y)) +#define crt_fmaxf(x, y) __max((x), (y)) +#define crt_fmaxl(x, y) __max((x), (y)) +#else +#define crt_fmax(x, y) __builtin_fmax((x), (y)) +#define crt_fmaxf(x, y) __builtin_fmaxf((x), (y)) +#define crt_fmaxl(x, y) __builtin_fmaxl((x), (y)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_logb(x) logb((x)) +#define crt_logbf(x) logbf((x)) +#define crt_logbl(x) logbl((x)) +#else +#define crt_logb(x) __builtin_logb((x)) +#define crt_logbf(x) __builtin_logbf((x)) +#define crt_logbl(x) __builtin_logbl((x)) +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define crt_scalbn(x, y) scalbn((x), (y)) +#define crt_scalbnf(x, y) scalbnf((x), (y)) +#define crt_scalbnl(x, y) scalbnl((x), (y)) +#else +#define crt_scalbn(x, y) __builtin_scalbn((x), (y)) +#define crt_scalbnf(x, y) __builtin_scalbnf((x), (y)) +#define crt_scalbnl(x, y) __builtin_scalbnl((x), (y)) +#endif + +#endif /* INT_MATH_H */ diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h b/arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h new file mode 100644 index 0000000..660385e --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h @@ -0,0 +1,166 @@ +/* ===-- int_lib.h - configuration header for compiler-rt -----------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file is not part of the interface of this library. + * + * This file defines various standard types, most importantly a number of unions + * used to access parts of larger types. + * + * ===----------------------------------------------------------------------=== + */ + +#ifndef INT_TYPES_H +#define INT_TYPES_H + +#include "int_endianness.h" + +/* si_int is defined in Linux sysroot's asm-generic/siginfo.h */ +#ifdef si_int +#undef si_int +#endif +typedef int si_int; +typedef unsigned su_int; + +typedef long long di_int; +typedef unsigned long long du_int; + +typedef union +{ + di_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + su_int low; + si_int high; +#else + si_int high; + su_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} dwords; + +typedef union +{ + du_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + su_int low; + su_int high; +#else + su_int high; + su_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} udwords; + +/* MIPS64 issue: PR 20098 */ +#if (defined(__LP64__) || defined(__wasm__)) && \ + !(defined(__mips__) && defined(__clang__)) +#define CRT_HAS_128BIT +#endif + +#ifdef CRT_HAS_128BIT +typedef int ti_int __attribute__ ((mode (TI))); +typedef unsigned tu_int __attribute__ ((mode (TI))); + +typedef union +{ + ti_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + du_int low; + di_int high; +#else + di_int high; + du_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} twords; + +typedef union +{ + tu_int all; + struct + { +#if _YUGA_LITTLE_ENDIAN + du_int low; + du_int high; +#else + du_int high; + du_int low; +#endif /* _YUGA_LITTLE_ENDIAN */ + }s; +} utwords; + +static __inline ti_int make_ti(di_int h, di_int l) { + twords r; + r.s.high = h; + r.s.low = l; + return r.all; +} + +static __inline tu_int make_tu(du_int h, du_int l) { + utwords r; + r.s.high = h; + r.s.low = l; + return r.all; +} + +#endif /* CRT_HAS_128BIT */ + +typedef union +{ + su_int u; + float f; +} float_bits; + +typedef union +{ + udwords u; + double f; +} double_bits; + +typedef struct +{ +#if _YUGA_LITTLE_ENDIAN + udwords low; + udwords high; +#else + udwords high; + udwords low; +#endif /* _YUGA_LITTLE_ENDIAN */ +} uqwords; + +typedef union +{ + uqwords u; + long double f; +} long_double_bits; + +#if __STDC_VERSION__ >= 199901L +typedef float _Complex Fcomplex; +typedef double _Complex Dcomplex; +typedef long double _Complex Lcomplex; + +#define COMPLEX_REAL(x) __real__(x) +#define COMPLEX_IMAGINARY(x) __imag__(x) +#else +typedef struct { float real, imaginary; } Fcomplex; + +typedef struct { double real, imaginary; } Dcomplex; + +typedef struct { long double real, imaginary; } Lcomplex; + +#define COMPLEX_REAL(x) (x).real +#define COMPLEX_IMAGINARY(x) (x).imaginary +#endif +#endif /* INT_TYPES_H */ + diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c b/arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c new file mode 100644 index 0000000..67b2a76 --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c @@ -0,0 +1,45 @@ +/* ===-- lshrdi3.c - Implement __lshrdi3 -----------------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __lshrdi3 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: logical a >> b */ + +/* Precondition: 0 <= b < bits_in_dword */ + +COMPILER_RT_ABI di_int +__lshrdi3(di_int a, si_int b) +{ + const int bits_in_word = (int)(sizeof(si_int) * CHAR_BIT); + udwords input; + udwords result; + input.all = a; + if (b & bits_in_word) /* bits_in_word <= b < bits_in_dword */ + { + result.s.high = 0; + result.s.low = input.s.high >> (b - bits_in_word); + } + else /* 0 <= b < bits_in_word */ + { + if (b == 0) + return a; + result.s.high = input.s.high >> b; + result.s.low = (input.s.high << (bits_in_word - b)) | (input.s.low >> b); + } + return result.all; +} + +#if defined(__ARM_EABI__) +AEABI_RTABI di_int __aeabi_llsr(di_int a, si_int b) COMPILER_RT_ALIAS(__lshrdi3); +#endif diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c new file mode 100644 index 0000000..5e8a62f --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c @@ -0,0 +1,36 @@ +/* ===-- popcountdi2.c - Implement __popcountdi2 ----------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __popcountdi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: count of 1 bits */ + +COMPILER_RT_ABI si_int +__popcountdi2(di_int a) +{ + du_int x2 = (du_int)a; + x2 = x2 - ((x2 >> 1) & 0x5555555555555555uLL); + /* Every 2 bits holds the sum of every pair of bits (32) */ + x2 = ((x2 >> 2) & 0x3333333333333333uLL) + (x2 & 0x3333333333333333uLL); + /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) (16) */ + x2 = (x2 + (x2 >> 4)) & 0x0F0F0F0F0F0F0F0FuLL; + /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) (8) */ + su_int x = (su_int)(x2 + (x2 >> 32)); + /* The lower 32 bits hold four 16 bit sums (5 significant bits). */ + /* Upper 32 bits are garbage */ + x = x + (x >> 16); + /* The lower 16 bits hold two 32 bit sums (6 significant bits). */ + /* Upper 16 bits are garbage */ + return (x + (x >> 8)) & 0x0000007F; /* (7 significant bits) */ +} diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c new file mode 100644 index 0000000..44544ff --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c @@ -0,0 +1,33 @@ +/* ===-- popcountsi2.c - Implement __popcountsi2 ---------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __popcountsi2 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Returns: count of 1 bits */ + +COMPILER_RT_ABI si_int +__popcountsi2(si_int a) +{ + su_int x = (su_int)a; + x = x - ((x >> 1) & 0x55555555); + /* Every 2 bits holds the sum of every pair of bits */ + x = ((x >> 2) & 0x33333333) + (x & 0x33333333); + /* Every 4 bits holds the sum of every 4-set of bits (3 significant bits) */ + x = (x + (x >> 4)) & 0x0F0F0F0F; + /* Every 8 bits holds the sum of every 8-set of bits (4 significant bits) */ + x = (x + (x >> 16)); + /* The lower 16 bits hold two 8 bit sums (5 significant bits).*/ + /* Upper 16 bits are garbage */ + return (x + (x >> 8)) & 0x0000003F; /* (6 significant bits) */ +} diff --git a/arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c b/arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c new file mode 100644 index 0000000..0c8b4ff --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c @@ -0,0 +1,231 @@ +/* ===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------=== + * + * The LLVM Compiler Infrastructure + * + * This file is dual licensed under the MIT and the University of Illinois Open + * Source Licenses. See LICENSE.TXT for details. + * + * ===----------------------------------------------------------------------=== + * + * This file implements __udivmoddi4 for the compiler_rt library. + * + * ===----------------------------------------------------------------------=== + */ + +#include "int_lib.h" + +/* Effects: if rem != 0, *rem = a % b + * Returns: a / b + */ + +/* Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide */ + +COMPILER_RT_ABI du_int +__udivmoddi4(du_int a, du_int b, du_int* rem) +{ + const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT; + const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT; + udwords n; + n.all = a; + udwords d; + d.all = b; + udwords q; + udwords r; + unsigned sr; + /* special cases, X is unknown, K != 0 */ + if (n.s.high == 0) + { + if (d.s.high == 0) + { + /* 0 X + * --- + * 0 X + */ + if (rem) + *rem = n.s.low % d.s.low; + return n.s.low / d.s.low; + } + /* 0 X + * --- + * K X + */ + if (rem) + *rem = n.s.low; + return 0; + } + /* n.s.high != 0 */ + if (d.s.low == 0) + { + if (d.s.high == 0) + { + /* K X + * --- + * 0 0 + */ + if (rem) + *rem = n.s.high % d.s.low; + return n.s.high / d.s.low; + } + /* d.s.high != 0 */ + if (n.s.low == 0) + { + /* K 0 + * --- + * K 0 + */ + if (rem) + { + r.s.high = n.s.high % d.s.high; + r.s.low = 0; + *rem = r.all; + } + return n.s.high / d.s.high; + } + /* K K + * --- + * K 0 + */ + if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ + { + if (rem) + { + r.s.low = n.s.low; + r.s.high = n.s.high & (d.s.high - 1); + *rem = r.all; + } + return n.s.high >> __builtin_ctz(d.s.high); + } + /* K K + * --- + * K 0 + */ + sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); + /* 0 <= sr <= n_uword_bits - 2 or sr large */ + if (sr > n_uword_bits - 2) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + /* 1 <= sr <= n_uword_bits - 1 */ + /* q.all = n.all << (n_udword_bits - sr); */ + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + /* r.all = n.all >> sr; */ + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + else /* d.s.low != 0 */ + { + if (d.s.high == 0) + { + /* K X + * --- + * 0 K + */ + if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ + { + if (rem) + *rem = n.s.low & (d.s.low - 1); + if (d.s.low == 1) + return n.all; + sr = __builtin_ctz(d.s.low); + q.s.high = n.s.high >> sr; + q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + return q.all; + } + /* K X + * --- + * 0 K + */ + sr = 1 + n_uword_bits + __builtin_clz(d.s.low) - __builtin_clz(n.s.high); + /* 2 <= sr <= n_udword_bits - 1 + * q.all = n.all << (n_udword_bits - sr); + * r.all = n.all >> sr; + */ + if (sr == n_uword_bits) + { + q.s.low = 0; + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } + else if (sr < n_uword_bits) // 2 <= sr <= n_uword_bits - 1 + { + q.s.low = 0; + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + else // n_uword_bits + 1 <= sr <= n_udword_bits - 1 + { + q.s.low = n.s.low << (n_udword_bits - sr); + q.s.high = (n.s.high << (n_udword_bits - sr)) | + (n.s.low >> (sr - n_uword_bits)); + r.s.high = 0; + r.s.low = n.s.high >> (sr - n_uword_bits); + } + } + else + { + /* K X + * --- + * K K + */ + sr = __builtin_clz(d.s.high) - __builtin_clz(n.s.high); + /* 0 <= sr <= n_uword_bits - 1 or sr large */ + if (sr > n_uword_bits - 1) + { + if (rem) + *rem = n.all; + return 0; + } + ++sr; + /* 1 <= sr <= n_uword_bits */ + /* q.all = n.all << (n_udword_bits - sr); */ + q.s.low = 0; + if (sr == n_uword_bits) + { + q.s.high = n.s.low; + r.s.high = 0; + r.s.low = n.s.high; + } + else + { + q.s.high = n.s.low << (n_uword_bits - sr); + r.s.high = n.s.high >> sr; + r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr); + } + } + } + /* Not a special case + * q and r are initialized with: + * q.all = n.all << (n_udword_bits - sr); + * r.all = n.all >> sr; + * 1 <= sr <= n_udword_bits - 1 + */ + su_int carry = 0; + for (; sr > 0; --sr) + { + /* r:q = ((r:q) << 1) | carry */ + r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1)); + r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1)); + q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1)); + q.s.low = (q.s.low << 1) | carry; + /* carry = 0; + * if (r.all >= d.all) + * { + * r.all -= d.all; + * carry = 1; + * } + */ + const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1); + carry = s & 1; + r.all -= d.all & s; + } + q.all = (q.all << 1) | carry; + if (rem) + *rem = r.all; + return q.all; +} diff --git a/arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk b/arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk new file mode 100644 index 0000000..40c669f --- /dev/null +++ b/arm-trusted-firmware/lib/compiler-rt/compiler-rt.mk @@ -0,0 +1,42 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# Redistributions of source code must retain the above copyright notice, this +# list of conditions and the following disclaimer. +# +# Redistributions in binary form must reproduce the above copyright notice, +# this list of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# +# Neither the name of ARM nor the names of its contributors may be used +# to endorse or promote products derived from this software without specific +# prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +# POSSIBILITY OF SUCH DAMAGE. +# + +COMPILER_RT_SRCS := lib/compiler-rt/builtins/popcountdi2.c \ + lib/compiler-rt/builtins/popcountsi2.c + +ifeq (${ARCH},aarch32) +COMPILER_RT_SRCS += lib/compiler-rt/builtins/arm/aeabi_ldivmod.S \ + lib/compiler-rt/builtins/arm/aeabi_uldivmod.S \ + lib/compiler-rt/builtins/ctzdi2.c \ + lib/compiler-rt/builtins/divdi3.c \ + lib/compiler-rt/builtins/divmoddi4.c \ + lib/compiler-rt/builtins/lshrdi3.c \ + lib/compiler-rt/builtins/udivmoddi4.c +endif diff --git a/arm-trusted-firmware/lib/coreboot/coreboot.mk b/arm-trusted-firmware/lib/coreboot/coreboot.mk new file mode 100644 index 0000000..4201823 --- /dev/null +++ b/arm-trusted-firmware/lib/coreboot/coreboot.mk @@ -0,0 +1,22 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +COREBOOT := 0 +$(eval $(call assert_boolean,COREBOOT)) +$(eval $(call add_define,COREBOOT)) + +ifeq (${COREBOOT},1) + +ifneq (${ARCH},aarch64) +$(error "coreboot only supports Trusted Firmware on AArch64.") +endif + +BL31_SOURCES += $(addprefix lib/coreboot/, \ + coreboot_table.c) + +BL31_SOURCES += drivers/coreboot/cbmem_console/${ARCH}/cbmem_console.S + +endif # COREBOOT diff --git a/arm-trusted-firmware/lib/coreboot/coreboot_table.c b/arm-trusted-firmware/lib/coreboot/coreboot_table.c new file mode 100644 index 0000000..fb31ef1 --- /dev/null +++ b/arm-trusted-firmware/lib/coreboot/coreboot_table.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/* + * Structures describing coreboot's in-memory descriptor tables. See + * /src/commonlib/include/commonlib/coreboot_tables.h for + * canonical implementation. + */ + +typedef struct { + char signature[4]; + uint32_t header_bytes; + uint32_t header_checksum; + uint32_t table_bytes; + uint32_t table_checksum; + uint32_t table_entries; +} cb_header_t; + +typedef enum { + CB_TAG_MEMORY = 0x1, + CB_TAG_SERIAL = 0xf, + CB_TAG_CBMEM_CONSOLE = 0x17, +} cb_tag_t; + +typedef struct { + uint32_t tag; + uint32_t size; + union { + coreboot_memrange_t memranges[COREBOOT_MAX_MEMRANGES]; + coreboot_serial_t serial; + uint64_t uint64; + }; +} cb_entry_t; + +coreboot_memrange_t coreboot_memranges[COREBOOT_MAX_MEMRANGES]; +coreboot_serial_t coreboot_serial; + +/* + * The coreboot table is parsed before the MMU is enabled (i.e. with strongly + * ordered memory), so we cannot make unaligned accesses. The table entries + * immediately follow one another without padding, so nothing after the header + * is guaranteed to be naturally aligned. Therefore, we need to define safety + * functions that can read unaligned integers. + */ +static uint32_t read_le32(uint32_t *p) +{ + uintptr_t addr = (uintptr_t)p; + return mmio_read_8(addr) | + mmio_read_8(addr + 1) << 8 | + mmio_read_8(addr + 2) << 16 | + mmio_read_8(addr + 3) << 24; +} +static uint64_t read_le64(uint64_t *p) +{ + return read_le32((void *)p) | (uint64_t)read_le32((void *)p + 4) << 32; +} + +static void expand_and_mmap(uintptr_t baseaddr, size_t size) +{ + uintptr_t pageaddr = round_down(baseaddr, PAGE_SIZE); + size_t expanded = round_up(baseaddr - pageaddr + size, PAGE_SIZE); + mmap_add_region(pageaddr, pageaddr, expanded, + MT_MEMORY | MT_RW | MT_NS | MT_EXECUTE_NEVER); +} + +static void setup_cbmem_console(uintptr_t baseaddr) +{ + static console_cbmc_t console; + assert(!console.console.base); /* should only have one CBMEM console */ + + /* CBMEM console structure stores its size in first header field. */ + uint32_t size = *(uint32_t *)baseaddr; + expand_and_mmap(baseaddr, size); + console_cbmc_register(baseaddr, &console); + console_set_scope(&console.console, CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME | + CONSOLE_FLAG_CRASH); +} + +coreboot_memory_t coreboot_get_memory_type(uintptr_t start, size_t size) +{ + int i; + + for (i = 0; i < COREBOOT_MAX_MEMRANGES; i++) { + coreboot_memrange_t *range = &coreboot_memranges[i]; + + if (range->type == CB_MEM_NONE) + break; /* end of table reached */ + if ((start >= range->start) && + (start - range->start < range->size) && + (size <= range->size - (start - range->start))) { + return range->type; + } + } + + return CB_MEM_NONE; +} + +void coreboot_table_setup(void *base) +{ + cb_header_t *header = base; + void *ptr; + int i; + + if (strncmp(header->signature, "LBIO", 4)) { + ERROR("coreboot table signature corrupt!\n"); + return; + } + + ptr = base + header->header_bytes; + for (i = 0; i < header->table_entries; i++) { + size_t size; + cb_entry_t *entry = ptr; + + if (ptr - base >= header->header_bytes + header->table_bytes) { + ERROR("coreboot table exceeds its bounds!\n"); + break; + } + + switch (read_le32(&entry->tag)) { + case CB_TAG_MEMORY: + size = read_le32(&entry->size) - + offsetof(cb_entry_t, memranges); + if (size > sizeof(coreboot_memranges)) { + ERROR("Need to truncate coreboot memranges!\n"); + size = sizeof(coreboot_memranges); + } + memcpy(&coreboot_memranges, &entry->memranges, size); + break; + case CB_TAG_SERIAL: + memcpy(&coreboot_serial, &entry->serial, + sizeof(coreboot_serial)); + break; + case CB_TAG_CBMEM_CONSOLE: + setup_cbmem_console(read_le64(&entry->uint64)); + break; + default: + /* There are many tags TF doesn't need to care about. */ + break; + } + + ptr += read_le32(&entry->size); + } +} diff --git a/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S b/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S new file mode 100644 index 0000000..7bd586a --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include + +func aem_generic_core_pwr_dwn + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + /* --------------------------------------------- + * Flush L1 cache to PoU. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + b dcsw_op_louis +endfunc aem_generic_core_pwr_dwn + + +func aem_generic_cluster_pwr_dwn + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + /* --------------------------------------------- + * Flush L1 and L2 caches to PoC. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + b dcsw_op_all +endfunc aem_generic_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + bx lr +endfunc aem_generic_errata_report +#endif + +/* cpu_ops for Base AEM FVP */ +declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S new file mode 100644 index 0000000..5300fe0 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a12_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a12_disable_smp + +func cortex_a12_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A12_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a12_enable_smp + +func cortex_a12_reset_func + b cortex_a12_enable_smp +endfunc cortex_a12_reset_func + +func cortex_a12_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_core_pwr_dwn + +func cortex_a12_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a12_disable_smp +endfunc cortex_a12_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A12. Must follow AAPCS. + */ +func cortex_a12_errata_report + bx lr +endfunc cortex_a12_errata_report +#endif + +declare_cpu_ops cortex_a12, CORTEX_A12_MIDR, \ + cortex_a12_reset_func, \ + cortex_a12_core_pwr_dwn, \ + cortex_a12_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S new file mode 100644 index 0000000..ab136ad --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * Cortex-A15 support LPAE and Virtualization Extensions. + * Don't care if confiugration uses or not LPAE and VE. + * Therefore, where we don't check ARCH_IS_ARMV7_WITH_LPAE/VE + */ + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a15_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb +#if ERRATA_A15_816470 + /* + * Invalidate any TLB address + */ + mov r0, #0 + stcopr r0, TLBIMVA +#endif + dsb sy + bx lr +endfunc cortex_a15_disable_smp + +func cortex_a15_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a15_enable_smp + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A15 Errata #816470. + * This applies only to revision >= r3p0 of Cortex A15. + * ---------------------------------------------------- + */ +func check_errata_816470 + /* + * Even though this is only needed for revision >= r3p0, it is always + * applied because of the low cost of the workaround. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_816470 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A15 Errata #827671. + * This applies only to revision >= r3p0 of Cortex A15. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a15_827671_wa + /* + * Compare r0 against revision r3p0 + */ + mov r2, lr + bl check_errata_827671 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A15_ACTLR2 + orr r0, #CORTEX_A15_ACTLR2_INV_DCC_BIT + stcopr r0, CORTEX_A15_ACTLR2 + isb +1: + bx r2 +endfunc errata_a15_827671_wa + +func check_errata_827671 + mov r1, #0x30 + b cpu_rev_var_hs +endfunc check_errata_827671 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A15. Must follow AAPCS. + */ +func cortex_a15_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A15_816470, cortex_a15, 816470 + report_errata ERRATA_A15_827671, cortex_a15, 827671 + report_errata WORKAROUND_CVE_2017_5715, cortex_a15, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a15_errata_report +#endif + +func cortex_a15_reset_func + mov r5, lr + bl cpu_get_rev_var + +#if ERRATA_A15_827671 + bl errata_a15_827671_wa +#endif + +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldcopr r0, ACTLR + orr r0, #CORTEX_A15_ACTLR_INV_BTB_BIT + stcopr r0, ACTLR + ldr r0, =workaround_icache_inv_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + + mov lr, r5 + b cortex_a15_enable_smp +endfunc cortex_a15_reset_func + +func cortex_a15_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_core_pwr_dwn + +func cortex_a15_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a15_disable_smp +endfunc cortex_a15_cluster_pwr_dwn + +declare_cpu_ops cortex_a15, CORTEX_A15_MIDR, \ + cortex_a15_reset_func, \ + cortex_a15_core_pwr_dwn, \ + cortex_a15_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S new file mode 100644 index 0000000..b8abd33 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a17_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a17_disable_smp + +func cortex_a17_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A17_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a17_enable_smp + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A17 Errata #852421. + * This applies only to revision <= r1p2 of Cortex A17. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a17_852421_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_852421 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A17_IMP_DEF_REG1 + orr r0, r0, #(1<<24) + stcopr r0, CORTEX_A17_IMP_DEF_REG1 +1: + bx r2 +endfunc errata_a17_852421_wa + +func check_errata_852421 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_852421 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A17 Errata #852423. + * This applies only to revision <= r1p2 of Cortex A17. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * ---------------------------------------------------- + */ +func errata_a17_852423_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_852423 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A17_IMP_DEF_REG1 + orr r0, r0, #(1<<12) + stcopr r0, CORTEX_A17_IMP_DEF_REG1 +1: + bx r2 +endfunc errata_a17_852423_wa + +func check_errata_852423 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_852423 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A17. Must follow AAPCS. + */ +func cortex_a17_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A17_852421, cortex_a17, 852421 + report_errata ERRATA_A17_852423, cortex_a17, 852423 + report_errata WORKAROUND_CVE_2017_5715, cortex_a17, cve_2017_5715 + + pop {r12, lr} + bx lr +endfunc cortex_a17_errata_report +#endif + +func cortex_a17_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A17_852421 + mov r0, r4 + bl errata_a17_852421_wa +#endif + +#if ERRATA_A17_852423 + mov r0, r4 + bl errata_a17_852423_wa +#endif + +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + + mov lr, r5 + b cortex_a17_enable_smp +endfunc cortex_a17_reset_func + +func cortex_a17_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_core_pwr_dwn + +func cortex_a17_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a17_disable_smp +endfunc cortex_a17_cluster_pwr_dwn + +declare_cpu_ops cortex_a17, CORTEX_A17_MIDR, \ + cortex_a17_reset_func, \ + cortex_a17_core_pwr_dwn, \ + cortex_a17_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S new file mode 100644 index 0000000..c262276 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a32_disable_smp + ldcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + bic r0, r0, #CORTEX_A32_CPUECTLR_SMPEN_BIT + stcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + isb + dsb sy + bx lr +endfunc cortex_a32_disable_smp + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A32. + * Clobbers: r0-r1 + * ------------------------------------------------- + */ +func cortex_a32_reset_func + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + orr r0, r0, #CORTEX_A32_CPUECTLR_SMPEN_BIT + stcopr16 r0, r1, CORTEX_A32_CPUECTLR_EL1 + isb + bx lr +endfunc cortex_a32_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A32. + * Clobbers: r0-r3 + * ---------------------------------------------------- + */ +func cortex_a32_core_pwr_dwn + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a32_disable_smp +endfunc cortex_a32_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A32. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a32_cluster_pwr_dwn + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 cache. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 cache. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a32_disable_smp +endfunc cortex_a32_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A32. Must follow AAPCS. + */ +func cortex_a32_errata_report + bx lr +endfunc cortex_a32_errata_report +#endif + +declare_cpu_ops cortex_a32, CORTEX_A32_MIDR, \ + cortex_a32_reset_func, \ + cortex_a32_core_pwr_dwn, \ + cortex_a32_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S new file mode 100644 index 0000000..8abb66f --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a5_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a5_disable_smp + +func cortex_a5_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A5_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a5_enable_smp + +func cortex_a5_reset_func + b cortex_a5_enable_smp +endfunc cortex_a5_reset_func + +func cortex_a5_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_core_pwr_dwn + +func cortex_a5_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a5_disable_smp +endfunc cortex_a5_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A5. Must follow AAPCS. + */ +func cortex_a5_errata_report + bx lr +endfunc cortex_a5_errata_report +#endif + +declare_cpu_ops cortex_a5, CORTEX_A5_MIDR, \ + cortex_a5_reset_func, \ + cortex_a5_core_pwr_dwn, \ + cortex_a5_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S new file mode 100644 index 0000000..6e3ff81 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S @@ -0,0 +1,316 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if A53_DISABLE_NON_TEMPORAL_HINT +#undef ERRATA_A53_836870 +#define ERRATA_A53_836870 1 +#endif + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a53_disable_smp + ldcopr16 r0, r1, CORTEX_A53_ECTLR + bic64_imm r0, r1, CORTEX_A53_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A53_ECTLR + isb + dsb sy + bx lr +endfunc cortex_a53_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #819472. + * This applies only to revision <= r0p1 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_819472 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_819472 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #824069. + * This applies only to revision <= r0p2 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_824069 + /* + * Even though this is only needed for revision <= r0p2, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_824069 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #826319. + * This applies only to revision <= r0p2 of Cortex A53. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a53_826319_wa + /* + * Compare r0 against revision r0p2 + */ + mov r2, lr + bl check_errata_826319 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr r0, CORTEX_A53_L2ACTLR + bic r0, #CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN + orr r0, #CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH + stcopr r0, CORTEX_A53_L2ACTLR +1: + bx lr +endfunc errata_a53_826319_wa + +func check_errata_826319 + mov r1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_826319 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #827319. + * This applies only to revision <= r0p2 of Cortex A53. + * --------------------------------------------------- + */ +func check_errata_827319 + /* + * Even though this is only needed for revision <= r0p2, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_827319 + + /* --------------------------------------------------------------------- + * Disable the cache non-temporal hint. + * + * This ignores the Transient allocation hint in the MAIR and treats + * allocations the same as non-transient allocation types. As a result, + * the LDNP and STNP instructions in AArch64 behave the same as the + * equivalent LDP and STP instructions. + * + * This is relevant only for revisions <= r0p3 of Cortex-A53. + * From r0p4 and onwards, the bit to disable the hint is enabled by + * default at reset. + * + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------------------------- + */ +func a53_disable_non_temporal_hint + /* + * Compare r0 against revision r0p3 + */ + mov r2, lr + bl check_errata_disable_non_temporal_hint + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A53_CPUACTLR + orr64_imm r0, r1, CORTEX_A53_CPUACTLR_DTAH + stcopr16 r0, r1, CORTEX_A53_CPUACTLR +1: + bx lr +endfunc a53_disable_non_temporal_hint + +func check_errata_disable_non_temporal_hint + mov r1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_disable_non_temporal_hint + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #855873. + * + * This applies only to revisions >= r0p3 of Cortex A53. + * Earlier revisions of the core are affected as well, but don't + * have the chicken bit in the CPUACTLR register. It is expected that + * the rich OS takes care of that, especially as the workaround is + * shared with other erratas in those revisions of the CPU. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a53_855873_wa + /* + * Compare r0 against revision r0p3 and higher + */ + mov r2, lr + bl check_errata_855873 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A53_CPUACTLR + orr64_imm r0, r1, CORTEX_A53_CPUACTLR_ENDCCASCI + stcopr16 r0, r1, CORTEX_A53_CPUACTLR +1: + bx lr +endfunc errata_a53_855873_wa + +func check_errata_855873 + mov r1, #0x03 + b cpu_rev_var_hs +endfunc check_errata_855873 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A53. + * Shall clobber: r0-r6 + * ------------------------------------------------- + */ +func cortex_a53_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A53_826319 + mov r0, r4 + bl errata_a53_826319_wa +#endif + +#if ERRATA_A53_836870 + mov r0, r4 + bl a53_disable_non_temporal_hint +#endif + +#if ERRATA_A53_855873 + mov r0, r4 + bl errata_a53_855873_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A53_ECTLR + orr64_imm r0, r1, CORTEX_A53_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A53_ECTLR + isb + bx r5 +endfunc cortex_a53_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A53. + * ---------------------------------------------------- + */ +func cortex_a53_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a53_disable_smp +endfunc cortex_a53_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A53. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a53_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a53_disable_smp +endfunc cortex_a53_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A53. Must follow AAPCS. + */ +func cortex_a53_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A53_819472, cortex_a53, 819472 + report_errata ERRATA_A53_824069, cortex_a53, 824069 + report_errata ERRATA_A53_826319, cortex_a53, 826319 + report_errata ERRATA_A53_827319, cortex_a53, 827319 + report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + report_errata ERRATA_A53_855873, cortex_a53, 855873 + + pop {r12, lr} + bx lr +endfunc cortex_a53_errata_report +#endif + +declare_cpu_ops cortex_a53, CORTEX_A53_MIDR, \ + cortex_a53_reset_func, \ + cortex_a53_core_pwr_dwn, \ + cortex_a53_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S new file mode 100644 index 0000000..2e97abb --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S @@ -0,0 +1,612 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a57_disable_smp + ldcopr16 r0, r1, CORTEX_A57_ECTLR + bic64_imm r0, r1, CORTEX_A57_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A57_ECTLR + bx lr +endfunc cortex_a57_disable_smp + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * Clobbers: r0-r2 + * --------------------------------------------- + */ +func cortex_a57_disable_l2_prefetch + ldcopr16 r0, r1, CORTEX_A57_ECTLR + orr64_imm r0, r1, CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT + bic64_imm r0, r1, (CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK | \ + CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK) + stcopr16 r0, r1, CORTEX_A57_ECTLR + isb + dsb ish + bx lr +endfunc cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a57_disable_ext_debug + mov r0, #1 + stcopr r0, DBGOSDLR + isb +#if ERRATA_A57_817169 + /* + * Invalidate any TLB address + */ + mov r0, #0 + stcopr r0, TLBIMVA +#endif + dsb sy + bx lr +endfunc cortex_a57_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #806969. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * -------------------------------------------------- + */ +func errata_a57_806969_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_806969 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_806969_wa + +func check_errata_806969 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_806969 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813419. + * This applies only to revision r0p0 of Cortex A57. + * --------------------------------------------------- + */ +func check_errata_813419 + /* + * Even though this is only needed for revision r0p0, it + * is always applied due to limitations of the current + * errata framework. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_813419 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813420. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_813420_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_813420 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DCC_AS_DCCI + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_813420_wa + +func check_errata_813420 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_813420 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #814670. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_814670_wa + /* + * Compare r0 against revision r0p0 + */ + mov r2, lr + bl check_errata_814670 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_DMB_NULLIFICATION + stcopr16 r0, r1, CORTEX_A57_CPUACTLR + isb +1: + bx r2 +endfunc errata_a57_814670_wa + +func check_errata_814670 + mov r1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_814670 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #817169. + * This applies only to revision <= r0p1 of Cortex A57. + * ---------------------------------------------------- + */ +func check_errata_817169 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied because of the low cost of the workaround. + */ + mov r0, #ERRATA_APPLIES + bx lr +endfunc check_errata_817169 + + /* -------------------------------------------------------------------- + * Disable the over-read from the LDNP instruction. + * + * This applies to all revisions <= r1p2. The performance degradation + * observed with LDNP/STNP has been fixed on r1p3 and onwards. + * + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------------------------- + */ +func a57_disable_ldnp_overread + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_disable_ldnp_overread + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_OVERREAD + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc a57_disable_ldnp_overread + +func check_errata_disable_ldnp_overread + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_disable_ldnp_overread + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826974. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_826974_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_826974 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_DMB + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_826974_wa + +func check_errata_826974 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826974 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826977. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_826977_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_826977 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_GRE_NGRE_AS_NGNRE + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_826977_wa + +func check_errata_826977 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826977 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #828024. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_828024_wa + /* + * Compare r0 against revision r1p1 + */ + mov r2, lr + bl check_errata_828024 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + /* + * Setting the relevant bits in CORTEX_A57_CPUACTLR has to be done in 2 + * instructions here because the resulting bitmask doesn't fit in a + * 16-bit value so it cannot be encoded in a single instruction. + */ + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_NO_ALLOC_WBWA + orr64_imm r0, r1, (CORTEX_A57_CPUACTLR_DIS_L1_STREAMING | CORTEX_A57_CPUACTLR_DIS_STREAMING) + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_828024_wa + +func check_errata_828024 + mov r1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_828024 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #829520. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_829520_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_829520 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_INDIRECT_PREDICTOR + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_829520_wa + +func check_errata_829520 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_829520 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #833471. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_833471_wa + /* + * Compare r0 against revision r1p2 + */ + mov r2, lr + bl check_errata_833471 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r1, r1, CORTEX_A57_CPUACTLR_FORCE_FPSCR_FLUSH + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_833471_wa + +func check_errata_833471 + mov r1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_833471 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #859972. + * This applies only to revision <= r1p3 of Cortex A57. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a57_859972_wa + mov r2, lr + bl check_errata_859972 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r1, r1, CORTEX_A57_CPUACTLR_DIS_INSTR_PREFETCH + stcopr16 r0, r1, CORTEX_A57_CPUACTLR +1: + bx lr +endfunc errata_a57_859972_wa + +func check_errata_859972 + mov r1, #0x13 + b cpu_rev_var_ls +endfunc check_errata_859972 + +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A57. + * Shall clobber: r0-r6 + * ------------------------------------------------- + */ +func cortex_a57_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A57_806969 + mov r0, r4 + bl errata_a57_806969_wa +#endif + +#if ERRATA_A57_813420 + mov r0, r4 + bl errata_a57_813420_wa +#endif + +#if ERRATA_A57_814670 + mov r0, r4 + bl errata_a57_814670_wa +#endif + +#if A57_DISABLE_NON_TEMPORAL_HINT + mov r0, r4 + bl a57_disable_ldnp_overread +#endif + +#if ERRATA_A57_826974 + mov r0, r4 + bl errata_a57_826974_wa +#endif + +#if ERRATA_A57_826977 + mov r0, r4 + bl errata_a57_826977_wa +#endif + +#if ERRATA_A57_828024 + mov r0, r4 + bl errata_a57_828024_wa +#endif + +#if ERRATA_A57_829520 + mov r0, r4 + bl errata_a57_829520_wa +#endif + +#if ERRATA_A57_833471 + mov r0, r4 + bl errata_a57_833471_wa +#endif + +#if ERRATA_A57_859972 + mov r0, r4 + bl errata_a57_859972_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + ldcopr16 r0, r1, CORTEX_A57_CPUACTLR + orr64_imm r0, r1, CORTEX_A57_CPUACTLR_DIS_LOAD_PASS_STORE + stcopr16 r0, r1, CORTEX_A57_CPUACTLR + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A57_ECTLR + orr64_imm r0, r1, CORTEX_A57_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A57_ECTLR + isb + bx r5 +endfunc cortex_a57_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A57. + * ---------------------------------------------------- + */ +func cortex_a57_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a57_disable_ext_debug +endfunc cortex_a57_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A57. + * Clobbers: r0-r3 + * ------------------------------------------------------- + */ +func cortex_a57_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a57_disable_ext_debug +endfunc cortex_a57_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A57. Must follow AAPCS. + */ +func cortex_a57_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A57_806969, cortex_a57, 806969 + report_errata ERRATA_A57_813419, cortex_a57, 813419 + report_errata ERRATA_A57_813420, cortex_a57, 813420 + report_errata ERRATA_A57_814670, cortex_a57, 814670 + report_errata ERRATA_A57_817169, cortex_a57, 817169 + report_errata A57_DISABLE_NON_TEMPORAL_HINT, cortex_a57, \ + disable_ldnp_overread + report_errata ERRATA_A57_826974, cortex_a57, 826974 + report_errata ERRATA_A57_826977, cortex_a57, 826977 + report_errata ERRATA_A57_828024, cortex_a57, 828024 + report_errata ERRATA_A57_829520, cortex_a57, 829520 + report_errata ERRATA_A57_833471, cortex_a57, 833471 + report_errata ERRATA_A57_859972, cortex_a57, 859972 + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a57, cve_2018_3639 + + pop {r12, lr} + bx lr +endfunc cortex_a57_errata_report +#endif + +declare_cpu_ops cortex_a57, CORTEX_A57_MIDR, \ + cortex_a57_reset_func, \ + cortex_a57_core_pwr_dwn, \ + cortex_a57_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S new file mode 100644 index 0000000..4d4bb77 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a7_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a7_disable_smp + +func cortex_a7_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A7_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a7_enable_smp + +func cortex_a7_reset_func + b cortex_a7_enable_smp +endfunc cortex_a7_reset_func + +func cortex_a7_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_core_pwr_dwn + +func cortex_a7_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a7_disable_smp +endfunc cortex_a7_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A7. Must follow AAPCS. + */ +func cortex_a7_errata_report + bx lr +endfunc cortex_a7_errata_report +#endif + +declare_cpu_ops cortex_a7, CORTEX_A7_MIDR, \ + cortex_a7_reset_func, \ + cortex_a7_core_pwr_dwn, \ + cortex_a7_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S new file mode 100644 index 0000000..ff2b0e6 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a72_disable_l2_prefetch + ldcopr16 r0, r1, CORTEX_A72_ECTLR + orr64_imm r0, r1, CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT + bic64_imm r0, r1, (CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK | \ + CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK) + stcopr16 r0, r1, CORTEX_A72_ECTLR + isb + bx lr +endfunc cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ +func cortex_a72_disable_hw_prefetcher + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r0, r1, CORTEX_A72_CPUACTLR_DISABLE_L1_DCACHE_HW_PFTCH + stcopr16 r0, r1, CORTEX_A72_CPUACTLR + isb + dsb ish + bx lr +endfunc cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Disable intra-cluster coherency + * Clobbers: r0-r1 + * --------------------------------------------- + */ +func cortex_a72_disable_smp + ldcopr16 r0, r1, CORTEX_A72_ECTLR + bic64_imm r0, r1, CORTEX_A72_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A72_ECTLR + bx lr +endfunc cortex_a72_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a72_disable_ext_debug + mov r0, #1 + stcopr r0, DBGOSDLR + isb + dsb sy + bx lr +endfunc cortex_a72_disable_ext_debug + + /* --------------------------------------------------- + * Errata Workaround for Cortex A72 Errata #859971. + * This applies only to revision <= r0p3 of Cortex A72. + * Inputs: + * r0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: r0-r3 + * --------------------------------------------------- + */ +func errata_a72_859971_wa + mov r2,lr + bl check_errata_859971 + mov lr, r2 + cmp r0, #ERRATA_NOT_APPLIES + beq 1f + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r1, r1, CORTEX_A72_CPUACTLR_DIS_INSTR_PREFETCH + stcopr16 r0, r1, CORTEX_A72_CPUACTLR +1: + bx lr +endfunc errata_a72_859971_wa + +func check_errata_859971 + mov r1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_859971 + +func check_errata_cve_2017_5715 + mov r0, #ERRATA_MISSING + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A72. + * ------------------------------------------------- + */ +func cortex_a72_reset_func + mov r5, lr + bl cpu_get_rev_var + mov r4, r0 + +#if ERRATA_A72_859971 + mov r0, r4 + bl errata_a72_859971_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + ldcopr16 r0, r1, CORTEX_A72_CPUACTLR + orr64_imm r0, r1, CORTEX_A72_CPUACTLR_DIS_LOAD_PASS_STORE + stcopr16 r0, r1, CORTEX_A72_CPUACTLR + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + ldcopr16 r0, r1, CORTEX_A72_ECTLR + orr64_imm r0, r1, CORTEX_A72_ECTLR_SMP_BIT + stcopr16 r0, r1, CORTEX_A72_ECTLR + isb + bx r5 +endfunc cortex_a72_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A72. + * ---------------------------------------------------- + */ +func cortex_a72_core_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a72_disable_ext_debug +endfunc cortex_a72_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A72. + * ------------------------------------------------------- + */ +func cortex_a72_cluster_pwr_dwn + push {r12, lr} + + /* Assert if cache is enabled */ +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + +#if !SKIP_A72_L1_FLUSH_PWR_DWN + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 +#endif + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov r0, #DC_OP_CISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + pop {r12, lr} + b cortex_a72_disable_ext_debug +endfunc cortex_a72_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A72. Must follow AAPCS. + */ +func cortex_a72_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a72, cve_2018_3639 + + pop {r12, lr} + bx lr +endfunc cortex_a72_errata_report +#endif + +declare_cpu_ops cortex_a72, CORTEX_A72_MIDR, \ + cortex_a72_reset_func, \ + cortex_a72_core_pwr_dwn, \ + cortex_a72_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S new file mode 100644 index 0000000..7200343 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + + .macro assert_cache_enabled +#if ENABLE_ASSERTIONS + ldcopr r0, SCTLR + tst r0, #SCTLR_C_BIT + ASM_ASSERT(eq) +#endif + .endm + +func cortex_a9_disable_smp + ldcopr r0, ACTLR + bic r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + dsb sy + bx lr +endfunc cortex_a9_disable_smp + +func cortex_a9_enable_smp + ldcopr r0, ACTLR + orr r0, #CORTEX_A9_ACTLR_SMP_BIT + stcopr r0, ACTLR + isb + bx lr +endfunc cortex_a9_enable_smp + +func check_errata_a9_794073 +#if ERRATA_A9_794073 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov r0, #ERRATA_APPLIES +#else + mov r0, #ERRATA_MISSING +#endif + bx lr +endfunc check_errata_cve_2017_5715 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A9. Must follow AAPCS. + */ +func cortex_a9_errata_report + push {r12, lr} + + bl cpu_get_rev_var + mov r4, r0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, cortex_a9, cve_2017_5715 + report_errata ERRATA_A9_794073, cortex_a9, a9_79407 + + pop {r12, lr} + bx lr +endfunc cortex_a9_errata_report +#endif + +func cortex_a9_reset_func +#if IMAGE_BL32 && WORKAROUND_CVE_2017_5715 + ldr r0, =workaround_bpiall_runtime_exceptions + stcopr r0, VBAR + stcopr r0, MVBAR + /* isb will be applied in the course of the reset func */ +#endif + b cortex_a9_enable_smp +endfunc cortex_a9_reset_func + +func cortex_a9_core_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 cache */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_core_pwr_dwn + +func cortex_a9_cluster_pwr_dwn + push {r12, lr} + + assert_cache_enabled + + /* Flush L1 caches */ + mov r0, #DC_OP_CISW + bl dcsw_op_level1 + + bl plat_disable_acp + + /* Exit cluster coherency */ + pop {r12, lr} + b cortex_a9_disable_smp +endfunc cortex_a9_cluster_pwr_dwn + +declare_cpu_ops cortex_a9, CORTEX_A9_MIDR, \ + cortex_a9_reset_func, \ + cortex_a9_core_pwr_dwn, \ + cortex_a9_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S new file mode 100644 index 0000000..6ed800c --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S @@ -0,0 +1,264 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#if defined(IMAGE_BL1) || defined(IMAGE_BL32) || (defined(IMAGE_BL2) && BL2_AT_EL3) + /* + * The reset handler common to all platforms. After a matching + * cpu_ops structure entry is found, the correponding reset_handler + * in the cpu_ops is invoked. The reset handler is invoked very early + * in the boot sequence and it is assumed that we can clobber r0 - r10 + * without the need to follow AAPCS. + * Clobbers: r0 - r10 + */ + .globl reset_handler +func reset_handler + mov r8, lr + + /* The plat_reset_handler can clobber r0 - r7 */ + bl plat_reset_handler + + /* Get the matching cpu_ops pointer (clobbers: r0 - r5) */ + bl get_cpu_ops_ptr + +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the cpu_ops reset handler */ + ldr r1, [r0, #CPU_RESET_FUNC] + cmp r1, #0 + mov lr, r8 + bxne r1 + bx lr +endfunc reset_handler + +#endif + +#ifdef IMAGE_BL32 /* The power down core and cluster is needed only in BL32 */ + /* + * void prepare_cpu_pwr_dwn(unsigned int power_level) + * + * Prepare CPU power down function for all platforms. The function takes + * a domain level to be powered down as its parameter. After the cpu_ops + * pointer is retrieved from cpu_data, the handler for requested power + * level is called. + */ + .globl prepare_cpu_pwr_dwn +func prepare_cpu_pwr_dwn + /* + * If the given power level exceeds CPU_MAX_PWR_DWN_OPS, we call the + * power down handler for the last power level + */ + mov r2, #(CPU_MAX_PWR_DWN_OPS - 1) + cmp r0, r2 + movhi r0, r2 + + push {r0, lr} + bl _cpu_data + pop {r2, lr} + + ldr r0, [r0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the appropriate power down handler */ + mov r1, #CPU_PWR_DWN_OPS + add r1, r1, r2, lsl #2 + ldr r1, [r0, r1] +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif + bx r1 +endfunc prepare_cpu_pwr_dwn + + /* + * Initializes the cpu_ops_ptr if not already initialized + * in cpu_data. This must only be called after the data cache + * is enabled. AAPCS is followed. + */ + .globl init_cpu_ops +func init_cpu_ops + push {r4 - r6, lr} + bl _cpu_data + mov r6, r0 + ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] + cmp r1, #0 + bne 1f + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + str r0, [r6, #CPU_DATA_CPU_OPS_PTR]! +1: + pop {r4 - r6, pc} +endfunc init_cpu_ops + +#endif /* IMAGE_BL32 */ + + /* + * The below function returns the cpu_ops structure matching the + * midr of the core. It reads the MIDR and finds the matching + * entry in cpu_ops entries. Only the implementation and part number + * are used to match the entries. + * Return : + * r0 - The matching cpu_ops pointer on Success + * r0 - 0 on failure. + * Clobbers: r0 - r5 + */ + .globl get_cpu_ops_ptr +func get_cpu_ops_ptr + /* Get the cpu_ops start and end locations */ + ldr r4, =(__CPU_OPS_START__ + CPU_MIDR) + ldr r5, =(__CPU_OPS_END__ + CPU_MIDR) + + /* Initialize the return parameter */ + mov r0, #0 + + /* Read the MIDR_EL1 */ + ldcopr r2, MIDR + ldr r3, =CPU_IMPL_PN_MASK + + /* Retain only the implementation and part number using mask */ + and r2, r2, r3 +1: + /* Check if we have reached end of list */ + cmp r4, r5 + bhs error_exit + + /* load the midr from the cpu_ops */ + ldr r1, [r4], #CPU_OPS_SIZE + and r1, r1, r3 + + /* Check if midr matches to midr of this core */ + cmp r1, r2 + bne 1b + + /* Subtract the increment and offset to get the cpu-ops pointer */ + sub r0, r4, #(CPU_OPS_SIZE + CPU_MIDR) +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif +error_exit: + bx lr +endfunc get_cpu_ops_ptr + +/* + * Extract CPU revision and variant, and combine them into a single numeric for + * easier comparison. + */ + .globl cpu_get_rev_var +func cpu_get_rev_var + ldcopr r1, MIDR + + /* + * Extract the variant[23:20] and revision[3:0] from r1 and pack it in + * r0[0:7] as variant[7:4] and revision[3:0]: + * + * First extract r1[23:16] to r0[7:0] and zero fill the rest. Then + * extract r1[3:0] into r0[3:0] retaining other bits. + */ + ubfx r0, r1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfi r0, r1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + bx lr +endfunc cpu_get_rev_var + +/* + * Compare the CPU's revision-variant (r0) with a given value (r1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + cmp r0, r1 + movls r0, #ERRATA_APPLIES + movhi r0, #ERRATA_NOT_APPLIES + bx lr +endfunc cpu_rev_var_ls + +/* + * Compare the CPU's revision-variant (r0) with a given value (r1), for errata + * application purposes. If the revision-variant is higher than or same as a + * given value, indicates that errata applies; otherwise not. + */ + .globl cpu_rev_var_hs +func cpu_rev_var_hs + cmp r0, r1 + movge r0, #ERRATA_APPLIES + movlt r0, #ERRATA_NOT_APPLIES + bx lr +endfunc cpu_rev_var_hs + +#if REPORT_ERRATA +/* + * void print_errata_status(void); + * + * Function to print errata status for CPUs of its class. Must be called only: + * + * - with MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ + .globl print_errata_status +func print_errata_status + /* r12 is pushed only for the sake of 8-byte stack alignment */ + push {r4, r5, r12, lr} +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + bl get_cpu_ops_ptr + ldr r0, [r0, #CPU_ERRATA_FUNC] + cmp r0, #0 + blxne r0 +#else + /* + * Retrieve pointer to cpu_ops, and further, the errata printing + * function. If it's non-NULL, jump to the function in turn. + */ + bl _cpu_data +#if ENABLE_ASSERTIONS + cmp r0, #0 + ASM_ASSERT(ne) +#endif + ldr r1, [r0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp r1, #0 + ASM_ASSERT(ne) +#endif + ldr r0, [r1, #CPU_ERRATA_FUNC] + cmp r0, #0 + beq 1f + + mov r4, r0 + + /* + * Load pointers to errata lock and printed flag. Call + * errata_needs_reporting to check whether this CPU needs to report + * errata status pertaining to its class. + */ + ldr r0, [r1, #CPU_ERRATA_LOCK] + ldr r1, [r1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + cmp r0, #0 + blxne r4 +1: +#endif + pop {r4, r5, r12, pc} +endfunc print_errata_status +#endif diff --git a/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S b/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S new file mode 100644 index 0000000..6291e43 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +func aem_generic_core_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * AEM model supports L3 caches in which case L2 + * will be private per core caches and flush + * from L1 to L2 is not sufficient. + * --------------------------------------------- + */ + mrs x1, clidr_el1 + + /* --------------------------------------------- + * Check if L3 cache is implemented. + * --------------------------------------------- + */ + tst x1, ((1 << CLIDR_FIELD_WIDTH) - 1) << CTYPE_SHIFT(3) + + /* --------------------------------------------- + * There is no L3 cache, flush L1 to L2 only. + * --------------------------------------------- + */ + mov x0, #DCCISW + b.eq dcsw_op_level1 + + mov x18, x30 + + /* --------------------------------------------- + * Flush L1 cache to L2. + * --------------------------------------------- + */ + bl dcsw_op_level1 + mov x30, x18 + + /* --------------------------------------------- + * Flush L2 cache to L3. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_level2 +endfunc aem_generic_core_pwr_dwn + +func aem_generic_cluster_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush all caches to PoC. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_all +endfunc aem_generic_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for AEM. Must follow AAPCS. + */ +func aem_generic_errata_report + ret +endfunc aem_generic_errata_report +#endif + + /* --------------------------------------------- + * This function provides cpu 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.aem_generic_regs, "aS" +aem_generic_regs: /* The ascii list of register names to be reported */ + .asciz "" /* no registers to report */ + +func aem_generic_cpu_reg_dump + adr x6, aem_generic_regs + ret +endfunc aem_generic_cpu_reg_dump + + +/* cpu_ops for Base AEM FVP */ +declare_cpu_ops aem_generic, BASE_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn + +/* cpu_ops for Foundation FVP */ +declare_cpu_ops aem_generic, FOUNDATION_AEM_MIDR, CPU_NO_RESET_FUNC, \ + aem_generic_core_pwr_dwn, \ + aem_generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S new file mode 100644 index 0000000..be3c652 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a35_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a35_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a35_disable_smp + mrs x0, CORTEX_A35_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A35_CPUECTLR_SMPEN_BIT + msr CORTEX_A35_CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a35_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A35 Errata #855472. + * This applies to revisions r0p0 of Cortex A35. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a35_855472_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_855472 + cbz x0, 1f + mrs x1, CORTEX_A35_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A35_CPUACTLR_EL1_ENDCCASCI + msr CORTEX_A35_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a35_855472_wa + +func check_errata_855472 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_855472 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A35. + * Clobbers: x0 + * ------------------------------------------------- + */ +func cortex_a35_reset_func + mov x19, x30 + bl cpu_get_rev_var + +#if ERRATA_A35_855472 + bl errata_a35_855472_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A35_CPUECTLR_EL1 + orr x0, x0, #CORTEX_A35_CPUECTLR_SMPEN_BIT + msr CORTEX_A35_CPUECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a35_reset_func + +func cortex_a35_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a35_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a35_disable_smp +endfunc cortex_a35_core_pwr_dwn + +func cortex_a35_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a35_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a35_disable_smp +endfunc cortex_a35_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A35. Must follow AAPCS. + */ +func cortex_a35_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A35_855472, cortex_a35, 855472 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a35_errata_report +#endif + + + /* --------------------------------------------- + * This function provides cortex_a35 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.cortex_a35_regs, "aS" +cortex_a35_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a35_cpu_reg_dump + adr x6, cortex_a35_regs + mrs x8, CORTEX_A35_CPUECTLR_EL1 + ret +endfunc cortex_a35_cpu_reg_dump + +declare_cpu_ops cortex_a35, CORTEX_A35_MIDR, \ + cortex_a35_reset_func, \ + cortex_a35_core_pwr_dwn, \ + cortex_a35_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S new file mode 100644 index 0000000..34e1082 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A510 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A510 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #1922240. + * This applies only to revision r0p0 (fixed in r0p1) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_1922240_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1922240 + cbz x0, 1f + + /* Apply the workaround by setting IMP_CMPXACTLR_EL1[11:10] = 0b11. */ + mrs x0, CORTEX_A510_CMPXACTLR_EL1 + mov x1, #3 + bfi x0, x1, #10, #2 + msr CORTEX_A510_CMPXACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_1922240_wa + +func check_errata_1922240 + /* Applies to r0p0 only */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1922240 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2288014. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0. (fixed in r1p1) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2288014_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2288014 + cbz x0, 1f + + /* Apply the workaround by setting IMP_CPUACTLR_EL1[18] = 0b1. */ + mrs x0, CORTEX_A510_CPUACTLR_EL1 + mov x1, #1 + bfi x0, x1, #18, #1 + msr CORTEX_A510_CPUACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2288014_wa + +func check_errata_2288014 + /* Applies to r1p0 and below */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2288014 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2042739. + * This applies only to revisions r0p0, r0p1 and r0p2. + * (fixed in r0p3) + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2042739_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2042739 + cbz x0, 1f + + /* Apply the workaround by disabling ReadPreferUnique. */ + mrs x0, CORTEX_A510_CPUECTLR_EL1 + mov x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_DISABLE + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_READPREFERUNIQUE_SHIFT, #1 + msr CORTEX_A510_CPUECTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2042739_wa + +func check_errata_2042739 + /* Applies to revisions r0p0 - r0p2 */ + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_2042739 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2041909. + * This applies only to revision r0p2 and it is fixed in + * r0p3. The issue is also present in r0p0 and r0p1 but + * there is no workaround in those revisions. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x2, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2041909_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2041909 + cbz x0, 1f + + /* Apply workaround */ + mov x0, xzr + msr S3_6_C15_C4_0, x0 + isb + + mov x0, #0x8500000 + msr S3_6_C15_C4_2, x0 + + mov x0, #0x1F700000 + movk x0, #0x8, lsl #32 + msr S3_6_C15_C4_3, x0 + + mov x0, #0x3F1 + movk x0, #0x110, lsl #16 + msr S3_6_C15_C4_1, x0 + isb + +1: + ret x17 +endfunc errata_cortex_a510_2041909_wa + +func check_errata_2041909 + /* Applies only to revision r0p2 */ + mov x1, #0x02 + mov x2, #0x02 + b cpu_rev_var_range +endfunc check_errata_2041909 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2250311. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * This workaround is not a typical errata fix. MPMM + * is disabled here, but this conflicts with the BL31 + * MPMM support. So in addition to simply disabling + * the feature, a flag is set in the MPMM library + * indicating that it should not be enabled even if + * ENABLE_MPMM=1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2250311_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2250311 + cbz x0, 1f + + /* Disable MPMM */ + mrs x0, CPUMPMMCR_EL3 + bfm x0, xzr, #0, #0 /* bfc instruction does not work in GCC */ + msr CPUMPMMCR_EL3, x0 + +#if ENABLE_MPMM && IMAGE_BL31 + /* If ENABLE_MPMM is set, tell the runtime lib to skip enabling it. */ + bl mpmm_errata_disable +#endif + +1: + ret x17 +endfunc errata_cortex_a510_2250311_wa + +func check_errata_2250311 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2250311 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2218950. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2218950_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2218950 + cbz x0, 1f + + /* Source register for BFI */ + mov x1, #1 + + /* Set bit 18 in CPUACTLR_EL1 */ + mrs x0, CORTEX_A510_CPUACTLR_EL1 + bfi x0, x1, #18, #1 + msr CORTEX_A510_CPUACTLR_EL1, x0 + + /* Set bit 25 in CMPXACTLR_EL1 */ + mrs x0, CORTEX_A510_CMPXACTLR_EL1 + bfi x0, x1, #25, #1 + msr CORTEX_A510_CMPXACTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2218950_wa + +func check_errata_2218950 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2218950 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-A510 Errata #2172148. + * This applies only to revisions r0p0, r0p1, r0p2, + * r0p3 and r1p0, and is fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_a510_2172148_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2172148 + cbz x0, 1f + + /* + * Force L2 allocation of transient lines by setting + * CPUECTLR_EL1.RSCTL=0b01 and CPUECTLR_EL1.NTCTL=0b01. + */ + mrs x0, CORTEX_A510_CPUECTLR_EL1 + mov x1, #1 + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_RSCTL_SHIFT, #2 + bfi x0, x1, #CORTEX_A510_CPUECTLR_EL1_NTCTL_SHIFT, #2 + msr CORTEX_A510_CPUECTLR_EL1, x0 + +1: + ret x17 +endfunc errata_cortex_a510_2172148_wa + +func check_errata_2172148 + /* Applies to r1p0 and lower */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_2172148 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a510_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A510_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A510_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A510_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a510_core_pwr_dwn + + /* + * Errata printing function for Cortex-A510. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a510_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A510_1922240, cortex_a510, 1922240 + report_errata ERRATA_A510_2288014, cortex_a510, 2288014 + report_errata ERRATA_A510_2042739, cortex_a510, 2042739 + report_errata ERRATA_A510_2041909, cortex_a510, 2041909 + report_errata ERRATA_A510_2250311, cortex_a510, 2250311 + report_errata ERRATA_A510_2218950, cortex_a510, 2218950 + report_errata ERRATA_A510_2172148, cortex_a510, 2172148 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a510_errata_report +#endif + +func cortex_a510_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + + /* Get the CPU revision and stash it in x18. */ + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A510_1922240 + mov x0, x18 + bl errata_cortex_a510_1922240_wa +#endif + +#if ERRATA_A510_2288014 + mov x0, x18 + bl errata_cortex_a510_2288014_wa +#endif + +#if ERRATA_A510_2042739 + mov x0, x18 + bl errata_cortex_a510_2042739_wa +#endif + +#if ERRATA_A510_2041909 + mov x0, x18 + bl errata_cortex_a510_2041909_wa +#endif + +#if ERRATA_A510_2250311 + mov x0, x18 + bl errata_cortex_a510_2250311_wa +#endif + +#if ERRATA_A510_2218950 + mov x0, x18 + bl errata_cortex_a510_2218950_wa +#endif + +#if ERRATA_A510_2172148 + mov x0, x18 + bl errata_cortex_a510_2172148_wa +#endif + + ret x19 +endfunc cortex_a510_reset_func + + /* --------------------------------------------- + * This function provides Cortex-A510 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.cortex_a510_regs, "aS" +cortex_a510_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a510_cpu_reg_dump + adr x6, cortex_a510_regs + mrs x8, CORTEX_A510_CPUECTLR_EL1 + ret +endfunc cortex_a510_cpu_reg_dump + +declare_cpu_ops cortex_a510, CORTEX_A510_MIDR, \ + cortex_a510_reset_func, \ + cortex_a510_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S new file mode 100644 index 0000000..df11d86 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S @@ -0,0 +1,409 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#if A53_DISABLE_NON_TEMPORAL_HINT +#undef ERRATA_A53_836870 +#define ERRATA_A53_836870 1 +#endif + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a53_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a53_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a53_disable_smp + mrs x0, CORTEX_A53_ECTLR_EL1 + bic x0, x0, #CORTEX_A53_ECTLR_SMP_BIT + msr CORTEX_A53_ECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a53_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #819472. + * This applies only to revision <= r0p1 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_819472 +#if ERRATA_A53_819472 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x01 + b cpu_rev_var_ls +#endif +endfunc check_errata_819472 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #824069. + * This applies only to revision <= r0p2 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_824069 +#if ERRATA_A53_824069 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x02 + b cpu_rev_var_ls +#endif +endfunc check_errata_824069 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #826319. + * This applies only to revision <= r0p2 of Cortex A53. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a53_826319_wa + /* + * Compare x0 against revision r0p2 + */ + mov x17, x30 + bl check_errata_826319 + cbz x0, 1f + mrs x1, CORTEX_A53_L2ACTLR_EL1 + bic x1, x1, #CORTEX_A53_L2ACTLR_ENABLE_UNIQUECLEAN + orr x1, x1, #CORTEX_A53_L2ACTLR_DISABLE_CLEAN_PUSH + msr CORTEX_A53_L2ACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a53_826319_wa + +func check_errata_826319 + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_826319 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #827319. + * This applies only to revision <= r0p2 of Cortex A53. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_827319 +#if ERRATA_A53_827319 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x02 + b cpu_rev_var_ls +#endif +endfunc check_errata_827319 + + /* --------------------------------------------------------------------- + * Disable the cache non-temporal hint. + * + * This ignores the Transient allocation hint in the MAIR and treats + * allocations the same as non-transient allocation types. As a result, + * the LDNP and STNP instructions in AArch64 behave the same as the + * equivalent LDP and STP instructions. + * + * This is relevant only for revisions <= r0p3 of Cortex-A53. + * From r0p4 and onwards, the bit to disable the hint is enabled by + * default at reset. + * + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func a53_disable_non_temporal_hint + /* + * Compare x0 against revision r0p3 + */ + mov x17, x30 + bl check_errata_disable_non_temporal_hint + cbz x0, 1f + mrs x1, CORTEX_A53_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A53_CPUACTLR_EL1_DTAH + msr CORTEX_A53_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc a53_disable_non_temporal_hint + +func check_errata_disable_non_temporal_hint + mov x1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_disable_non_temporal_hint + + /* -------------------------------------------------- + * Errata Workaround for Cortex A53 Errata #855873. + * + * This applies only to revisions >= r0p3 of Cortex A53. + * Earlier revisions of the core are affected as well, but don't + * have the chicken bit in the CPUACTLR register. It is expected that + * the rich OS takes care of that, especially as the workaround is + * shared with other erratas in those revisions of the CPU. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a53_855873_wa + /* + * Compare x0 against revision r0p3 and higher + */ + mov x17, x30 + bl check_errata_855873 + cbz x0, 1f + + mrs x1, CORTEX_A53_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A53_CPUACTLR_EL1_ENDCCASCI + msr CORTEX_A53_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a53_855873_wa + +func check_errata_855873 + mov x1, #0x03 + b cpu_rev_var_hs +endfunc check_errata_855873 + +/* + * Errata workaround for Cortex A53 Errata #835769. + * This applies to revisions <= r0p4 of Cortex A53. + * This workaround is statically enabled at build time. + */ +func check_errata_835769 + cmp x0, #0x04 + b.hi errata_not_applies + /* + * Fix potentially available for revisions r0p2, r0p3 and r0p4. + * If r0p2, r0p3 or r0p4; check for fix in REVIDR, else exit. + */ + cmp x0, #0x01 + mov x0, #ERRATA_APPLIES + b.ls exit_check_errata_835769 + /* Load REVIDR. */ + mrs x1, revidr_el1 + /* If REVIDR[7] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */ + tbz x1, #7, exit_check_errata_835769 +errata_not_applies: + mov x0, #ERRATA_NOT_APPLIES +exit_check_errata_835769: + ret +endfunc check_errata_835769 + +/* + * Errata workaround for Cortex A53 Errata #843419. + * This applies to revisions <= r0p4 of Cortex A53. + * This workaround is statically enabled at build time. + */ +func check_errata_843419 + mov x1, #ERRATA_APPLIES + mov x2, #ERRATA_NOT_APPLIES + cmp x0, #0x04 + csel x0, x1, x2, ls + /* + * Fix potentially available for revision r0p4. + * If r0p4 check for fix in REVIDR, else exit. + */ + b.ne exit_check_errata_843419 + /* Load REVIDR. */ + mrs x3, revidr_el1 + /* If REVIDR[8] is set (fix exists) set ERRATA_NOT_APPLIES, else exit. */ + tbz x3, #8, exit_check_errata_843419 + mov x0, x2 +exit_check_errata_843419: + ret +endfunc check_errata_843419 + + /* -------------------------------------------------- + * Errata workaround for Cortex A53 Errata #1530924. + * This applies to all revisions of Cortex A53. + * -------------------------------------------------- + */ +func check_errata_1530924 +#if ERRATA_A53_1530924 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1530924 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A53. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a53_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + + +#if ERRATA_A53_826319 + mov x0, x18 + bl errata_a53_826319_wa +#endif + +#if ERRATA_A53_836870 + mov x0, x18 + bl a53_disable_non_temporal_hint +#endif + +#if ERRATA_A53_855873 + mov x0, x18 + bl errata_a53_855873_wa +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A53_ECTLR_EL1 + orr x0, x0, #CORTEX_A53_ECTLR_SMP_BIT + msr CORTEX_A53_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a53_reset_func + +func cortex_a53_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a53_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a53_disable_smp +endfunc cortex_a53_core_pwr_dwn + +func cortex_a53_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a53_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a53_disable_smp +endfunc cortex_a53_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A53. Must follow AAPCS. + */ +func cortex_a53_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A53_819472, cortex_a53, 819472 + report_errata ERRATA_A53_824069, cortex_a53, 824069 + report_errata ERRATA_A53_826319, cortex_a53, 826319 + report_errata ERRATA_A53_827319, cortex_a53, 827319 + report_errata ERRATA_A53_835769, cortex_a53, 835769 + report_errata ERRATA_A53_836870, cortex_a53, disable_non_temporal_hint + report_errata ERRATA_A53_843419, cortex_a53, 843419 + report_errata ERRATA_A53_855873, cortex_a53, 855873 + report_errata ERRATA_A53_1530924, cortex_a53, 1530924 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a53_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a53 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.cortex_a53_regs, "aS" +cortex_a53_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", \ + "cpuactlr_el1", "" + +func cortex_a53_cpu_reg_dump + adr x6, cortex_a53_regs + mrs x8, CORTEX_A53_ECTLR_EL1 + mrs x9, CORTEX_A53_MERRSR_EL1 + mrs x10, CORTEX_A53_L2MERRSR_EL1 + mrs x11, CORTEX_A53_CPUACTLR_EL1 + ret +endfunc cortex_a53_cpu_reg_dump + +declare_cpu_ops cortex_a53, CORTEX_A53_MIDR, \ + cortex_a53_reset_func, \ + cortex_a53_core_pwr_dwn, \ + cortex_a53_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S new file mode 100644 index 0000000..7838304 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S @@ -0,0 +1,351 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A55 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #768277. + * This applies only to revision r0p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a55_768277_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_768277 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_768277_wa + +func check_errata_768277 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_768277 + + /* ------------------------------------------------------------------ + * Errata Workaround for Cortex A55 Errata #778703. + * This applies only to revision r0p0 of Cortex A55 where L2 cache is + * not configured. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ------------------------------------------------------------------ + */ +func errata_a55_778703_wa + /* + * Compare x0 against revision r0p0 and check that no private L2 cache + * is configured + */ + mov x17, x30 + bl check_errata_778703 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUECTLR_EL1_L1WSCTL + msr CORTEX_A55_CPUECTLR_EL1, x1 + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_WRITE_STREAMING + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_778703_wa + +func check_errata_778703 + mov x16, x30 + mov x1, #0x00 + bl cpu_rev_var_ls + /* + * Check that no private L2 cache is configured + */ + mrs x1, CORTEX_A55_CLIDR_EL1 + and x1, x1, CORTEX_A55_CLIDR_EL1_CTYPE3 + cmp x1, #0 + mov x2, #ERRATA_NOT_APPLIES + csel x0, x0, x2, eq + ret x16 +endfunc check_errata_778703 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #798797. + * This applies only to revision r0p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a55_798797_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_798797 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_798797_wa + +func check_errata_798797 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_798797 + + /* -------------------------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #846532. + * This applies only to revisions <= r0p1 of Cortex A55. + * Disabling dual-issue has a small impact on performance. Disabling a + * power optimization feature is an alternate workaround with no impact + * on performance but with an increase in power consumption (see errata + * notice). + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------------------------- + */ +func errata_a55_846532_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_846532 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_DUAL_ISSUE + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_846532_wa + +func check_errata_846532 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_846532 + + /* ----------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #903758. + * This applies only to revisions <= r0p1 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ----------------------------------------------------- + */ +func errata_a55_903758_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_903758 + cbz x0, 1f + mrs x1, CORTEX_A55_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A55_CPUACTLR_EL1_DISABLE_L1_PAGEWALKS + msr CORTEX_A55_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a55_903758_wa + +func check_errata_903758 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_903758 + + /* ----------------------------------------------------- + * Errata Workaround for Cortex A55 Errata #1221012. + * This applies only to revisions <= r1p0 of Cortex A55. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ----------------------------------------------------- + */ +func errata_a55_1221012_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1221012 + cbz x0, 1f + mov x0, #0x0020 + movk x0, #0x0850, lsl #16 + msr CPUPOR_EL3, x0 + mov x0, #0x0000 + movk x0, #0x1FF0, lsl #16 + movk x0, #0x2, lsl #32 + msr CPUPMR_EL3, x0 + mov x0, #0x03fd + movk x0, #0x0110, lsl #16 + msr CPUPCR_EL3, x0 + mov x0, #0x1 + msr CPUPSELR_EL3, x0 + mov x0, #0x0040 + movk x0, #0x08D0, lsl #16 + msr CPUPOR_EL3, x0 + mov x0, #0x0040 + movk x0, #0x1FF0, lsl #16 + movk x0, #0x2, lsl #32 + msr CPUPMR_EL3, x0 + mov x0, #0x03fd + movk x0, #0x0110, lsl #16 + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_a55_1221012_wa + +func check_errata_1221012 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1221012 + + /* -------------------------------------------------- + * Errata workaround for Cortex A55 Errata #1530923. + * This applies to all revisions of Cortex A55. + * -------------------------------------------------- + */ +func check_errata_1530923 +#if ERRATA_A55_1530923 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1530923 + +func cortex_a55_reset_func + mov x19, x30 + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A55_768277 + mov x0, x18 + bl errata_a55_768277_wa +#endif + +#if ERRATA_A55_778703 + mov x0, x18 + bl errata_a55_778703_wa +#endif + +#if ERRATA_A55_798797 + mov x0, x18 + bl errata_a55_798797_wa +#endif + +#if ERRATA_A55_846532 + mov x0, x18 + bl errata_a55_846532_wa +#endif + +#if ERRATA_A55_903758 + mov x0, x18 + bl errata_a55_903758_wa +#endif + +#if ERRATA_A55_1221012 + mov x0, x18 + bl errata_a55_1221012_wa +#endif + + ret x19 +endfunc cortex_a55_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a55_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A55_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A55_CORE_PWRDN_EN_MASK + msr CORTEX_A55_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a55_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A55. Must follow AAPCS & can use stack. + */ +func cortex_a55_errata_report + stp x8, x30, [sp, #-16]! + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision variant information is at x8, where + * "report_errata" is expecting it and it doesn't corrupt it. + */ + report_errata ERRATA_DSU_798953, cortex_a55, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a55, dsu_936184 + report_errata ERRATA_A55_768277, cortex_a55, 768277 + report_errata ERRATA_A55_778703, cortex_a55, 778703 + report_errata ERRATA_A55_798797, cortex_a55, 798797 + report_errata ERRATA_A55_846532, cortex_a55, 846532 + report_errata ERRATA_A55_903758, cortex_a55, 903758 + report_errata ERRATA_A55_1221012, cortex_a55, 1221012 + report_errata ERRATA_A55_1530923, cortex_a55, 1530923 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a55_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a55 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.cortex_a55_regs, "aS" +cortex_a55_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a55_cpu_reg_dump + adr x6, cortex_a55_regs + mrs x8, CORTEX_A55_CPUECTLR_EL1 + ret +endfunc cortex_a55_cpu_reg_dump + +declare_cpu_ops cortex_a55, CORTEX_A55_MIDR, \ + cortex_a55_reset_func, \ + cortex_a55_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S new file mode 100644 index 0000000..3766ec7 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S @@ -0,0 +1,686 @@ +/* + * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a57_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a57_disable_l2_prefetch + mrs x0, CORTEX_A57_ECTLR_EL1 + orr x0, x0, #CORTEX_A57_ECTLR_DIS_TWD_ACC_PFTCH_BIT + mov x1, #CORTEX_A57_ECTLR_L2_IPFTCH_DIST_MASK + orr x1, x1, #CORTEX_A57_ECTLR_L2_DPFTCH_DIST_MASK + bic x0, x0, x1 + msr CORTEX_A57_ECTLR_EL1, x0 + isb + dsb ish + ret +endfunc cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a57_disable_smp + mrs x0, CORTEX_A57_ECTLR_EL1 + bic x0, x0, #CORTEX_A57_ECTLR_SMP_BIT + msr CORTEX_A57_ECTLR_EL1, x0 + ret +endfunc cortex_a57_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a57_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb +#if ERRATA_A57_817169 + /* + * Invalidate any TLB address + */ + mov x0, #0 + tlbi vae3, x0 +#endif + dsb sy + ret +endfunc cortex_a57_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #806969. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a57_806969_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_806969 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_806969_wa + +func check_errata_806969 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_806969 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813419. + * This applies only to revision r0p0 of Cortex A57. + * --------------------------------------------------- + */ +func check_errata_813419 + /* + * Even though this is only needed for revision r0p0, it + * is always applied due to limitations of the current + * errata framework. + */ + mov x0, #ERRATA_APPLIES + ret +endfunc check_errata_813419 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #813420. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_813420_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_813420 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DCC_AS_DCCI + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_813420_wa + +func check_errata_813420 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_813420 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #814670. + * This applies only to revision r0p0 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_814670_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_814670 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_DMB_NULLIFICATION + msr CORTEX_A57_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a57_814670_wa + +func check_errata_814670 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_814670 + + /* ---------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #817169. + * This applies only to revision <= r0p1 of Cortex A57. + * ---------------------------------------------------- + */ +func check_errata_817169 + /* + * Even though this is only needed for revision <= r0p1, it + * is always applied because of the low cost of the workaround. + */ + mov x0, #ERRATA_APPLIES + ret +endfunc check_errata_817169 + + /* -------------------------------------------------------------------- + * Disable the over-read from the LDNP instruction. + * + * This applies to all revisions <= r1p2. The performance degradation + * observed with LDNP/STNP has been fixed on r1p3 and onwards. + * + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func a57_disable_ldnp_overread + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_disable_ldnp_overread + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_OVERREAD + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc a57_disable_ldnp_overread + +func check_errata_disable_ldnp_overread + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_disable_ldnp_overread + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826974. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_826974_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_826974 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_DMB + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_826974_wa + +func check_errata_826974 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826974 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #826977. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_826977_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_826977 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_GRE_NGRE_AS_NGNRE + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_826977_wa + +func check_errata_826977 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_826977 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #828024. + * This applies only to revision <= r1p1 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_828024_wa + /* + * Compare x0 against revision r1p1 + */ + mov x17, x30 + bl check_errata_828024 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + /* + * Setting the relevant bits in CPUACTLR_EL1 has to be done in 2 + * instructions here because the resulting bitmask doesn't fit in a + * 16-bit value so it cannot be encoded in a single instruction. + */ + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_NO_ALLOC_WBWA + orr x1, x1, #(CORTEX_A57_CPUACTLR_EL1_DIS_L1_STREAMING | \ + CORTEX_A57_CPUACTLR_EL1_DIS_STREAMING) + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_828024_wa + +func check_errata_828024 + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_828024 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #829520. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_829520_wa + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_829520 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INDIRECT_PREDICTOR + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_829520_wa + +func check_errata_829520 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_829520 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #833471. + * This applies only to revision <= r1p2 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a57_833471_wa + /* + * Compare x0 against revision r1p2 + */ + mov x17, x30 + bl check_errata_833471 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_FORCE_FPSCR_FLUSH + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_833471_wa + +func check_errata_833471 + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_833471 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A57 Errata #859972. + * This applies only to revision <= r1p3 of Cortex A57. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: + * -------------------------------------------------- + */ +func errata_a57_859972_wa + mov x17, x30 + bl check_errata_859972 + cbz x0, 1f + mrs x1, CORTEX_A57_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A57_CPUACTLR_EL1_DIS_INSTR_PREFETCH + msr CORTEX_A57_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a57_859972_wa + +func check_errata_859972 + mov x1, #0x13 + b cpu_rev_var_ls +endfunc check_errata_859972 + +func check_errata_cve_2017_5715 +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* -------------------------------------------------- + * Errata workaround for Cortex A57 Errata #1319537. + * This applies to all revisions of Cortex A57. + * -------------------------------------------------- + */ +func check_errata_1319537 +#if ERRATA_A57_1319537 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1319537 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A57. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a57_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A57_806969 + mov x0, x18 + bl errata_a57_806969_wa +#endif + +#if ERRATA_A57_813420 + mov x0, x18 + bl errata_a57_813420_wa +#endif + +#if ERRATA_A57_814670 + mov x0, x18 + bl errata_a57_814670_wa +#endif + +#if A57_DISABLE_NON_TEMPORAL_HINT + mov x0, x18 + bl a57_disable_ldnp_overread +#endif + +#if ERRATA_A57_826974 + mov x0, x18 + bl errata_a57_826974_wa +#endif + +#if ERRATA_A57_826977 + mov x0, x18 + bl errata_a57_826977_wa +#endif + +#if ERRATA_A57_828024 + mov x0, x18 + bl errata_a57_828024_wa +#endif + +#if ERRATA_A57_829520 + mov x0, x18 + bl errata_a57_829520_wa +#endif + +#if ERRATA_A57_833471 + mov x0, x18 + bl errata_a57_833471_wa +#endif + +#if ERRATA_A57_859972 + mov x0, x18 + bl errata_a57_859972_wa +#endif + +#if IMAGE_BL31 && ( WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 ) + /* --------------------------------------------------------------- + * Override vector table & enable existing workaround if either of + * the build flags are enabled + * --------------------------------------------------------------- + */ + adr x0, wa_cve_2017_5715_mmu_vbar + msr vbar_el3, x0 + /* isb will be performed before returning from this function */ +#endif + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A57_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A57_CPUACTLR_EL1_DIS_LOAD_PASS_STORE + msr CORTEX_A57_CPUACTLR_EL1, x0 + isb + dsb sy +#endif + +#if A57_ENABLE_NONCACHEABLE_LOAD_FWD + /* --------------------------------------------- + * Enable higher performance non-cacheable load + * forwarding + * --------------------------------------------- + */ + mrs x0, CORTEX_A57_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A57_CPUACTLR_EL1_EN_NC_LOAD_FWD + msr CORTEX_A57_CPUACTLR_EL1, x0 +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A57_ECTLR_EL1 + orr x0, x0, #CORTEX_A57_ECTLR_SMP_BIT + msr CORTEX_A57_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a57_reset_func + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A57. + * ---------------------------------------------------- + */ +func cortex_a57_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a57_disable_ext_debug +endfunc cortex_a57_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A57. + * ------------------------------------------------------- + */ +func cortex_a57_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a57_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a57_disable_l2_prefetch + +#if !SKIP_A57_L1_FLUSH_PWR_DWN + /* ------------------------------------------------- + * Flush the L1 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 +#endif + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a57_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a57_disable_ext_debug +endfunc cortex_a57_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A57. Must follow AAPCS. + */ +func cortex_a57_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A57_806969, cortex_a57, 806969 + report_errata ERRATA_A57_813419, cortex_a57, 813419 + report_errata ERRATA_A57_813420, cortex_a57, 813420 + report_errata ERRATA_A57_814670, cortex_a57, 814670 + report_errata ERRATA_A57_817169, cortex_a57, 817169 + report_errata A57_DISABLE_NON_TEMPORAL_HINT, cortex_a57, \ + disable_ldnp_overread + report_errata ERRATA_A57_826974, cortex_a57, 826974 + report_errata ERRATA_A57_826977, cortex_a57, 826977 + report_errata ERRATA_A57_828024, cortex_a57, 828024 + report_errata ERRATA_A57_829520, cortex_a57, 829520 + report_errata ERRATA_A57_833471, cortex_a57, 833471 + report_errata ERRATA_A57_859972, cortex_a57, 859972 + report_errata ERRATA_A57_1319537, cortex_a57, 1319537 + report_errata WORKAROUND_CVE_2017_5715, cortex_a57, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a57, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a57, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a57_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a57 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.cortex_a57_regs, "aS" +cortex_a57_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", "" + +func cortex_a57_cpu_reg_dump + adr x6, cortex_a57_regs + mrs x8, CORTEX_A57_ECTLR_EL1 + mrs x9, CORTEX_A57_MERRSR_EL1 + mrs x10, CORTEX_A57_L2MERRSR_EL1 + ret +endfunc cortex_a57_cpu_reg_dump + +declare_cpu_ops_wa cortex_a57, CORTEX_A57_MIDR, \ + cortex_a57_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a57_core_pwr_dwn, \ + cortex_a57_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S new file mode 100644 index 0000000..666324c --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if !HW_ASSISTED_COHERENCY +#error "Cortex-A65 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS +#error "Cortex-A65 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A65. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a65_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a65_reset_func + +func cortex_a65_cpu_pwr_dwn + mrs x0, CORTEX_A65_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A65_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A65_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a65_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A65. Must follow AAPCS. + */ +func cortex_a65_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, cortex_a65, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a65_errata_report +#endif + +.section .rodata.cortex_a65_regs, "aS" +cortex_a65_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a65_cpu_reg_dump + adr x6, cortex_a65_regs + mrs x8, CORTEX_A65_ECTLR_EL1 + ret +endfunc cortex_a65_cpu_reg_dump + +declare_cpu_ops cortex_a65, CORTEX_A65_MIDR, \ + cortex_a65_reset_func, \ + cortex_a65_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S new file mode 100644 index 0000000..ac6583e --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if !HW_ASSISTED_COHERENCY +#error "Cortex-A65AE must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS +#error "Cortex-A65AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A65. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a65ae_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a65ae_reset_func + +func cortex_a65ae_cpu_pwr_dwn + mrs x0, CORTEX_A65AE_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A65AE_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A65AE_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a65ae_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A65AE. Must follow AAPCS. + */ +func cortex_a65ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, cortex_a65ae, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a65ae_errata_report +#endif + +.section .rodata.cortex_a65ae_regs, "aS" +cortex_a65ae_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a65ae_cpu_reg_dump + adr x6, cortex_a65ae_regs + mrs x8, CORTEX_A65AE_ECTLR_EL1 + ret +endfunc cortex_a65ae_cpu_reg_dump + +declare_cpu_ops cortex_a65ae, CORTEX_A65AE_MIDR, \ + cortex_a65ae_reset_func, \ + cortex_a65ae_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S new file mode 100644 index 0000000..aea62ae --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex A710 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex A710 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A710_BHB_LOOP_COUNT, cortex_a710 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 1987031. + * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. It is still + * open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a710_1987031_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1987031 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x7 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003f3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a710_1987031_wa + +func check_errata_1987031 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1987031 + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2081180. + * This applies to revision r0p0, r1p0 and r2p0 of Cortex-A710. + * It is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a710_2081180_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2081180 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x3 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003FF + msr S3_6_c15_c8_1,x0 + ldr x0,=0x4 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003F3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a710_2081180_wa + +func check_errata_2081180 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2081180 + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2055002. + * This applies to revision r1p0, r2p0 of Cortex-A710 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2055002_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2055002 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUACTLR_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_46 + msr CORTEX_A710_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a710_2055002_wa + +func check_errata_2055002 + /* Applies to r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2055002 + +/* ------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2017096. + * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ------------------------------------------------------------- + */ +func errata_a710_2017096_wa + /* Compare x0 against revision r0p0 to r2p0 */ + mov x17, x30 + bl check_errata_2017096 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUECTLR_EL1 + orr x1, x1, CORTEX_A710_CPUECTLR_EL1_PFSTIDIS_BIT + msr CORTEX_A710_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2017096_wa + +func check_errata_2017096 + /* Applies to r0p0, r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2017096 + + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2083908. + * This applies to revision r2p0 of Cortex-A710 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2083908_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2083908 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUACTLR5_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_13 + msr CORTEX_A710_CPUACTLR5_EL1, x1 +1: + ret x17 +endfunc errata_a710_2083908_wa + +func check_errata_2083908 + /* Applies to r2p0 */ + mov x1, #CPU_REV(2, 0) + mov x2, #CPU_REV(2, 0) + b cpu_rev_var_range +endfunc check_errata_2083908 + +/* --------------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2058056. + * This applies to revisions r0p0, r1p0 and r2p0 of Cortex-A710 and is still + * open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------------- + */ +func errata_a710_2058056_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2058056 + cbz x0, 1f + mrs x1, CORTEX_A710_CPUECTLR2_EL1 + mov x0, #CORTEX_A710_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH + msr CORTEX_A710_CPUECTLR2_EL1, x1 +1: + ret x17 +endfunc errata_a710_2058056_wa + +func check_errata_2058056 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2058056 + +/* -------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2267065. + * This applies to revisions r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_a710_2267065_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2267065 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, CORTEX_A710_CPUACTLR_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR_EL1_BIT_22 + msr CORTEX_A710_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a710_2267065_wa + +func check_errata_2267065 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2267065 + +/* --------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2136059. + * This applies to revision r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_a710_2136059_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2136059 + cbz x0, 1f + + /* Apply the workaround */ + mrs x1, CORTEX_A710_CPUACTLR5_EL1 + orr x1, x1, CORTEX_A710_CPUACTLR5_EL1_BIT_44 + msr CORTEX_A710_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2136059_wa + +func check_errata_2136059 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2136059 + +/* --------------------------------------------------------------- + * Errata Workaround for Cortex-A710 Erratum 2282622. + * This applies to revision r0p0, r1p0 and r2p0. + * It is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * --------------------------------------------------------------- + */ +func errata_a710_2282622_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_2282622 + cbz x0, 1f + + /* Apply the workaround */ + mrs x1, CORTEX_A710_CPUACTLR2_EL1 + orr x1, x1, BIT(0) + msr CORTEX_A710_CPUACTLR2_EL1, x1 + +1: + ret x17 +endfunc errata_a710_2282622_wa + +func check_errata_2282622 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2282622 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a710_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A710_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A710_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A710_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a710_core_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Cortex-A710. Must follow AAPCS. + */ +func cortex_a710_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A710_1987031, cortex_a710, 1987031 + report_errata ERRATA_A710_2081180, cortex_a710, 2081180 + report_errata ERRATA_A710_2055002, cortex_a710, 2055002 + report_errata ERRATA_A710_2017096, cortex_a710, 2017096 + report_errata ERRATA_A710_2083908, cortex_a710, 2083908 + report_errata ERRATA_A710_2058056, cortex_a710, 2058056 + report_errata ERRATA_A710_2267065, cortex_a710, 2267065 + report_errata ERRATA_A710_2136059, cortex_a710, 2136059 + report_errata ERRATA_A710_2282622, cortex_a710, 2282622 + report_errata WORKAROUND_CVE_2022_23960, cortex_a710, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a710_errata_report +#endif + +func cortex_a710_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A710_1987031 + mov x0, x18 + bl errata_a710_1987031_wa +#endif + +#if ERRATA_A710_2081180 + mov x0, x18 + bl errata_a710_2081180_wa +#endif + +#if ERRATA_A710_2055002 + mov x0, x18 + bl errata_a710_2055002_wa +#endif + +#if ERRATA_A710_2017096 + mov x0, x18 + bl errata_a710_2017096_wa +#endif + +#if ERRATA_A710_2083908 + mov x0, x18 + bl errata_a710_2083908_wa +#endif + +#if ERRATA_A710_2058056 + mov x0, x18 + bl errata_a710_2058056_wa +#endif + +#if ERRATA_A710_2267065 + mov x0, x18 + bl errata_a710_2267065_wa +#endif + +#if ERRATA_A710_2136059 + mov x0, x18 + bl errata_a710_2136059_wa +#endif + +#if ERRATA_A710_2282622 + mov x0, x18 + bl errata_a710_2282622_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A710 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a710 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a710_reset_func + + /* --------------------------------------------- + * This function provides Cortex-A710 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.cortex_a710_regs, "aS" +cortex_a710_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a710_cpu_reg_dump + adr x6, cortex_a710_regs + mrs x8, CORTEX_A710_CPUECTLR_EL1 + ret +endfunc cortex_a710_cpu_reg_dump + +declare_cpu_ops cortex_a710, CORTEX_A710_MIDR, \ + cortex_a710_reset_func, \ + cortex_a710_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S new file mode 100644 index 0000000..de2d36e --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S @@ -0,0 +1,374 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A72_BHB_LOOP_COUNT, cortex_a72 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func cortex_a72_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable all types of L2 prefetches. + * --------------------------------------------- + */ +func cortex_a72_disable_l2_prefetch + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CORTEX_A72_ECTLR_DIS_TWD_ACC_PFTCH_BIT + mov x1, #CORTEX_A72_ECTLR_L2_IPFTCH_DIST_MASK + orr x1, x1, #CORTEX_A72_ECTLR_L2_DPFTCH_DIST_MASK + bic x0, x0, x1 + msr CORTEX_A72_ECTLR_EL1, x0 + isb + ret +endfunc cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ +func cortex_a72_disable_hw_prefetcher + mrs x0, CORTEX_A72_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DISABLE_L1_DCACHE_HW_PFTCH + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + dsb ish + ret +endfunc cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a72_disable_smp + mrs x0, CORTEX_A72_ECTLR_EL1 + bic x0, x0, #CORTEX_A72_ECTLR_SMP_BIT + msr CORTEX_A72_ECTLR_EL1, x0 + ret +endfunc cortex_a72_disable_smp + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func cortex_a72_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb + dsb sy + ret +endfunc cortex_a72_disable_ext_debug + + /* -------------------------------------------------- + * Errata Workaround for Cortex A72 Errata #859971. + * This applies only to revision <= r0p3 of Cortex A72. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: + * -------------------------------------------------- + */ +func errata_a72_859971_wa + mov x17,x30 + bl check_errata_859971 + cbz x0, 1f + mrs x1, CORTEX_A72_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A72_CPUACTLR_EL1_DIS_INSTR_PREFETCH + msr CORTEX_A72_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_a72_859971_wa + +func check_errata_859971 + mov x1, #0x03 + b cpu_rev_var_ls +endfunc check_errata_859971 + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* -------------------------------------------------- + * Errata workaround for Cortex A72 Errata #1319367. + * This applies to all revisions of Cortex A72. + * -------------------------------------------------- + */ +func check_errata_1319367 +#if ERRATA_A72_1319367 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_1319367 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A72. + * ------------------------------------------------- + */ +func cortex_a72_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A72_859971 + mov x0, x18 + bl errata_a72_859971_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_mmu_vbar + msr vbar_el3, x0 + /* isb will be performed before returning from this function */ + + /* Skip CVE_2022_23960 mitigation if cve_2017_5715 mitigation applied */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A72 generic vectors are overridden to apply the + * mitigation on exception entry from lower ELs for revisions >= r1p0 + * which has CSV2 implemented. + */ + adr x0, wa_cve_vbar_cortex_a72 + msr vbar_el3, x0 + + /* isb will be performed before returning from this function */ +#endif /* WORKAROUND_CVE_2022_23960 */ +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A72_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A72_CPUACTLR_EL1_DIS_LOAD_PASS_STORE + msr CORTEX_A72_CPUACTLR_EL1, x0 + isb + dsb sy +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * --------------------------------------------- + */ + mrs x0, CORTEX_A72_ECTLR_EL1 + orr x0, x0, #CORTEX_A72_ECTLR_SMP_BIT + msr CORTEX_A72_ECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a72_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Cortex-A72. + * ---------------------------------------------------- + */ +func cortex_a72_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a72_disable_ext_debug +endfunc cortex_a72_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Cortex-A72. + * ------------------------------------------------------- + */ +func cortex_a72_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a72_disable_dcache + + /* --------------------------------------------- + * Disable the L2 prefetches. + * --------------------------------------------- + */ + bl cortex_a72_disable_l2_prefetch + + /* --------------------------------------------- + * Disable the load-store hardware prefetcher. + * --------------------------------------------- + */ + bl cortex_a72_disable_hw_prefetcher + +#if !SKIP_A72_L1_FLUSH_PWR_DWN + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 +#endif + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* ------------------------------------------------- + * Flush the L2 caches. + * ------------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + bl cortex_a72_disable_smp + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a72_disable_ext_debug +endfunc cortex_a72_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A72. Must follow AAPCS. + */ +func cortex_a72_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A72_859971, cortex_a72, 859971 + report_errata ERRATA_A72_1319367, cortex_a72, 1319367 + report_errata WORKAROUND_CVE_2017_5715, cortex_a72, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a72, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a72, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a72_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a72 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.cortex_a72_regs, "aS" +cortex_a72_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "cpumerrsr_el1", "l2merrsr_el1", "" + +func cortex_a72_cpu_reg_dump + adr x6, cortex_a72_regs + mrs x8, CORTEX_A72_ECTLR_EL1 + mrs x9, CORTEX_A72_MERRSR_EL1 + mrs x10, CORTEX_A72_L2MERRSR_EL1 + ret +endfunc cortex_a72_cpu_reg_dump + +declare_cpu_ops_wa cortex_a72, CORTEX_A72_MIDR, \ + cortex_a72_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a72_core_pwr_dwn, \ + cortex_a72_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S new file mode 100644 index 0000000..edcd1f5 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S @@ -0,0 +1,305 @@ +/* + * Copyright (c) 2016-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache + * --------------------------------------------- + */ +func cortex_a73_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc cortex_a73_disable_dcache + + /* --------------------------------------------- + * Disable intra-cluster coherency + * --------------------------------------------- + */ +func cortex_a73_disable_smp + mrs x0, CORTEX_A73_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A73_CPUECTLR_SMP_BIT + msr CORTEX_A73_CPUECTLR_EL1, x0 + isb + dsb sy + ret +endfunc cortex_a73_disable_smp + + /* --------------------------------------------------- + * Errata Workaround for Cortex A73 Errata #852427. + * This applies only to revision r0p0 of Cortex A73. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a73_852427_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_852427 + cbz x0, 1f + mrs x1, CORTEX_A73_DIAGNOSTIC_REGISTER + orr x1, x1, #(1 << 12) + msr CORTEX_A73_DIAGNOSTIC_REGISTER, x1 + isb +1: + ret x17 +endfunc errata_a73_852427_wa + +func check_errata_852427 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_852427 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A73 Errata #855423. + * This applies only to revision <= r0p1 of Cortex A73. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------- + */ +func errata_a73_855423_wa + /* + * Compare x0 against revision r0p1 + */ + mov x17, x30 + bl check_errata_855423 + cbz x0, 1f + mrs x1, CORTEX_A73_IMP_DEF_REG2 + orr x1, x1, #(1 << 7) + msr CORTEX_A73_IMP_DEF_REG2, x1 + isb +1: + ret x17 +endfunc errata_a73_855423_wa + +func check_errata_855423 + mov x1, #0x01 + b cpu_rev_var_ls +endfunc check_errata_855423 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A73. + * ------------------------------------------------- + */ + +func cortex_a73_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A73_852427 + mov x0, x18 + bl errata_a73_852427_wa +#endif + +#if ERRATA_A73_855423 + mov x0, x18 + bl errata_a73_855423_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb + /* Skip installing vector table again for CVE_2022_23960 */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A73_IMP_DEF_REG1 + orr x0, x0, #CORTEX_A73_IMP_DEF_REG1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A73_IMP_DEF_REG1, x0 + isb +#endif + + /* --------------------------------------------- + * Enable the SMP bit. + * Clobbers : x0 + * --------------------------------------------- + */ + mrs x0, CORTEX_A73_CPUECTLR_EL1 + orr x0, x0, #CORTEX_A73_CPUECTLR_SMP_BIT + msr CORTEX_A73_CPUECTLR_EL1, x0 + isb + ret x19 +endfunc cortex_a73_reset_func + +func cortex_a73_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a73_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a73_disable_smp +endfunc cortex_a73_core_pwr_dwn + +func cortex_a73_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl cortex_a73_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + /* --------------------------------------------- + * Come out of intra cluster coherency + * --------------------------------------------- + */ + mov x30, x18 + b cortex_a73_disable_smp +endfunc cortex_a73_cluster_pwr_dwn + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret + 1: +# if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +# else + mov x0, #ERRATA_MISSING +# endif /* WORKAROUND_CVE_2022_23960 */ + ret +#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */ + mov x0, #ERRATA_MISSING + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a73_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A73_852427, cortex_a73, 852427 + report_errata ERRATA_A73_855423, cortex_a73, 855423 + report_errata WORKAROUND_CVE_2017_5715, cortex_a73, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a73, cve_2018_3639 + report_errata WORKAROUND_CVE_2022_23960, cortex_a73, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a73_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a73 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.cortex_a73_regs, "aS" +cortex_a73_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "l2merrsr_el1", "" + +func cortex_a73_cpu_reg_dump + adr x6, cortex_a73_regs + mrs x8, CORTEX_A73_CPUECTLR_EL1 + mrs x9, CORTEX_A73_L2MERRSR_EL1 + ret +endfunc cortex_a73_cpu_reg_dump + +declare_cpu_ops_wa cortex_a73, CORTEX_A73_MIDR, \ + cortex_a73_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a73_core_pwr_dwn, \ + cortex_a73_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S new file mode 100644 index 0000000..d561be4 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A75 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + + /* -------------------------------------------------- + * Errata Workaround for Cortex A75 Errata #764081. + * This applies only to revision r0p0 of Cortex A75. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a75_764081_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_764081 + cbz x0, 1f + mrs x1, sctlr_el3 + orr x1, x1 ,#SCTLR_IESB_BIT + msr sctlr_el3, x1 + isb +1: + ret x17 +endfunc errata_a75_764081_wa + +func check_errata_764081 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_764081 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A75 Errata #790748. + * This applies only to revision r0p0 of Cortex A75. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a75_790748_wa + /* + * Compare x0 against revision r0p0 + */ + mov x17, x30 + bl check_errata_790748 + cbz x0, 1f + mrs x1, CORTEX_A75_CPUACTLR_EL1 + orr x1, x1 ,#(1 << 13) + msr CORTEX_A75_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a75_790748_wa + +func check_errata_790748 + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_790748 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A75. + * ------------------------------------------------- + */ +func cortex_a75_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A75_764081 + mov x0, x18 + bl errata_a75_764081_wa +#endif + +#if ERRATA_A75_790748 + mov x0, x18 + bl errata_a75_790748_wa +#endif + +#if IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) + cpu_check_csv2 x0, 1f + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb + /* Skip installing vector table again for CVE_2022_23960 */ + b 2f +1: +#if WORKAROUND_CVE_2022_23960 + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + isb +#endif +2: +#endif /* IMAGE_BL31 && (WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960) */ + +#if WORKAROUND_CVE_2018_3639 + mrs x0, CORTEX_A75_CPUACTLR_EL1 + orr x0, x0, #CORTEX_A75_CPUACTLR_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A75_CPUACTLR_EL1, x0 + isb +#endif + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el3, x0 + isb + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #CORTEX_A75_ACTLR_AMEN_BIT + msr actlr_el2, x0 + isb + + /* Enable group0 counters */ + mov x0, #CORTEX_A75_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 + isb + + /* Enable group1 counters */ + mov x0, #CORTEX_A75_AMU_GROUP1_MASK + msr CPUAMCNTENSET_EL0, x0 + isb +#endif + ret x19 +endfunc cortex_a75_reset_func + +func check_errata_cve_2017_5715 + cpu_check_csv2 x0, 1f +#if WORKAROUND_CVE_2017_5715 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 + cpu_check_csv2 x0, 1f + mov x0, #ERRATA_APPLIES + ret +1: +# if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +# else + mov x0, #ERRATA_MISSING +# endif /* WORKAROUND_CVE_2022_23960 */ + ret +#endif /* WORKAROUND_CVE_2017_5715 || WORKAROUND_CVE_2022_23960 */ + mov x0, #ERRATA_MISSING + ret +endfunc check_errata_cve_2022_23960 + +func check_smccc_arch_workaround_3 + mov x0, #ERRATA_APPLIES + ret +endfunc check_smccc_arch_workaround_3 + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a75_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A75_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A75_CORE_PWRDN_EN_MASK + msr CORTEX_A75_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a75_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A75. Must follow AAPCS. + */ +func cortex_a75_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A75_764081, cortex_a75, 764081 + report_errata ERRATA_A75_790748, cortex_a75, 790748 + report_errata WORKAROUND_CVE_2017_5715, cortex_a75, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, cortex_a75, cve_2018_3639 + report_errata ERRATA_DSU_798953, cortex_a75, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a75, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, cortex_a75, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a75_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a75 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.cortex_a75_regs, "aS" +cortex_a75_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a75_cpu_reg_dump + adr x6, cortex_a75_regs + mrs x8, CORTEX_A75_CPUECTLR_EL1 + ret +endfunc cortex_a75_cpu_reg_dump + +declare_cpu_ops_wa cortex_a75, CORTEX_A75_MIDR, \ + cortex_a75_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + check_smccc_arch_workaround_3, \ + cortex_a75_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c new file mode 100644 index 0000000..bd2c697 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void *cortex_a75_context_save(const void *arg) +{ + if (midr_match(CORTEX_A75_MIDR) != 0) + cpuamu_context_save(CORTEX_A75_AMU_NR_COUNTERS); + + return (void *)0; +} + +static void *cortex_a75_context_restore(const void *arg) +{ + if (midr_match(CORTEX_A75_MIDR) != 0) + cpuamu_context_restore(CORTEX_A75_AMU_NR_COUNTERS); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, cortex_a75_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, cortex_a75_context_restore); diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S new file mode 100644 index 0000000..50bd8cd --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S @@ -0,0 +1,812 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A76 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A76 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#define ESR_EL3_A64_SMC0 0x5e000000 +#define ESR_EL3_A32_SMC0 0x4e000000 + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* + * This macro applies the mitigation for CVE-2018-3639. + * It implements a fast path where `SMCCC_ARCH_WORKAROUND_2` + * SMC calls from a lower EL running in AArch32 or AArch64 + * will go through the fast and return early. + * + * The macro saves x2-x3 to the context. In the fast path + * x0-x3 registers do not need to be restored as the calling + * context will have saved them. The macro also saves + * x29-x30 to the context in the sync_exception path. + */ + .macro apply_cve_2018_3639_wa _is_sync_exception _esr_el3_val + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .if \_is_sync_exception + stp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + mov_imm w2, \_esr_el3_val + bl apply_cve_2018_3639_sync_wa + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + .endif + /* + * Always enable v4 mitigation during EL3 execution. This is not + * required for the fast path above because it does not perform any + * memory loads. + */ + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x2, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x2 + isb + + /* + * The caller may have passed arguments to EL3 via x2-x3. + * Restore these registers from the context before jumping to the + * main runtime vector table entry. + */ + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .endm +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960 +vector_base cortex_a76_wa_cve_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry cortex_a76_sync_exception_sp_el0 + +vector_entry cortex_a76_irq_sp_el0 + b irq_sp_el0 +end_vector_entry cortex_a76_irq_sp_el0 + +vector_entry cortex_a76_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry cortex_a76_fiq_sp_el0 + +vector_entry cortex_a76_serror_sp_el0 + b serror_sp_el0 +end_vector_entry cortex_a76_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry cortex_a76_sync_exception_sp_elx + +vector_entry cortex_a76_irq_sp_elx + b irq_sp_elx +end_vector_entry cortex_a76_irq_sp_elx + +vector_entry cortex_a76_fiq_sp_elx + b fiq_sp_elx +end_vector_entry cortex_a76_fiq_sp_elx + +vector_entry cortex_a76_serror_sp_elx + b serror_sp_elx +end_vector_entry cortex_a76_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b sync_exception_aarch64 +end_vector_entry cortex_a76_sync_exception_aarch64 + +vector_entry cortex_a76_irq_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b irq_aarch64 +end_vector_entry cortex_a76_irq_aarch64 + +vector_entry cortex_a76_fiq_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b fiq_aarch64 +end_vector_entry cortex_a76_fiq_aarch64 + +vector_entry cortex_a76_serror_aarch64 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b serror_aarch64 +end_vector_entry cortex_a76_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry cortex_a76_sync_exception_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b sync_exception_aarch32 +end_vector_entry cortex_a76_sync_exception_aarch32 + +vector_entry cortex_a76_irq_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b irq_aarch32 +end_vector_entry cortex_a76_irq_aarch32 + +vector_entry cortex_a76_fiq_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b fiq_aarch32 +end_vector_entry cortex_a76_fiq_aarch32 + +vector_entry cortex_a76_serror_aarch32 + +#if WORKAROUND_CVE_2022_23960 + apply_cve_2022_23960_bhb_wa CORTEX_A76_BHB_LOOP_COUNT +#endif /* WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + apply_cve_2018_3639_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639*/ + + b serror_aarch32 +end_vector_entry cortex_a76_serror_aarch32 +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 || WORKAROUND_CVE_2022_23960 */ + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* + * ----------------------------------------------------------------- + * This function applies the mitigation for CVE-2018-3639 + * specifically for sync exceptions. It implements a fast path + * where `SMCCC_ARCH_WORKAROUND_2` SMC calls from a lower EL + * running in AArch64 will go through the fast and return early. + * + * In the fast path x0-x3 registers do not need to be restored as the + * calling context will have saved them. + * + * Caller must pass value of esr_el3 to compare via x2. + * Save and restore these registers outside of this function from the + * context before jumping to the main runtime vector table entry. + * + * Shall clobber: x0-x3, x30 + * ----------------------------------------------------------------- + */ +func apply_cve_2018_3639_sync_wa + /* + * Ensure SMC is coming from A64/A32 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_2 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_2) ? (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + * X2 populated outside this function with the SMC FID. + */ + orr w3, wzr, #SMCCC_ARCH_WORKAROUND_2 + cmp x0, x3 + mrs x3, esr_el3 + + ccmp w2, w3, #0, eq + /* + * Static predictor will predict a fall-through, optimizing + * the `SMCCC_ARCH_WORKAROUND_2` fast path. + */ + bne 1f + + /* + * The sequence below implements the `SMCCC_ARCH_WORKAROUND_2` + * fast path. + */ + cmp x1, xzr /* enable/disable check */ + + /* + * When the calling context wants mitigation disabled, + * we program the mitigation disable function in the + * CPU context, which gets invoked on subsequent exits from + * EL3 via the `el3_exit` function. Otherwise NULL is + * programmed in the CPU context, which results in caller's + * inheriting the EL3 mitigation state (enabled) on subsequent + * `el3_exit`. + */ + mov x0, xzr + adr x1, cortex_a76_disable_wa_cve_2018_3639 + csel x1, x1, x0, eq + str x1, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] + + mrs x2, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + bic x3, x2, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + csel x3, x3, x1, eq + msr CORTEX_A76_CPUACTLR2_EL1, x3 + ldp x29, x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X29] + /* + * `SMCCC_ARCH_WORKAROUND_2`fast path return to lower EL. + */ + exception_return /* exception_return contains ISB */ +1: + ret +endfunc apply_cve_2018_3639_sync_wa +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1073348. + * This applies only to revision <= r1p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1073348_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1073348 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR_EL1 + orr x1, x1 ,#CORTEX_A76_CPUACTLR_EL1_DISABLE_STATIC_PREDICTION + msr CORTEX_A76_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1073348_wa + +func check_errata_1073348 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1073348 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1130799. + * This applies only to revision <= r2p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1130799_wa + /* + * Compare x0 against revision r2p0 + */ + mov x17, x30 + bl check_errata_1130799 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x1 ,#(1 << 59) + msr CORTEX_A76_CPUACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1130799_wa + +func check_errata_1130799 + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1130799 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1220197. + * This applies only to revision <= r2p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1220197_wa +/* + * Compare x0 against revision r2p0 + */ + mov x17, x30 + bl check_errata_1220197 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A76_CPUECTLR_EL1_WS_THR_L2 + msr CORTEX_A76_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1220197_wa + +func check_errata_1220197 + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1220197 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1257314. + * This applies only to revision <= r3p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1257314_wa + /* + * Compare x0 against revision r3p0 + */ + mov x17, x30 + bl check_errata_1257314 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR3_EL1 + orr x1, x1, CORTEX_A76_CPUACTLR3_EL1_BIT_10 + msr CORTEX_A76_CPUACTLR3_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1257314_wa + +func check_errata_1257314 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1257314 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1262888. + * This applies only to revision <= r3p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1262888_wa + /* + * Compare x0 against revision r3p0 + */ + mov x17, x30 + bl check_errata_1262888 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUECTLR_EL1 + orr x1, x1, CORTEX_A76_CPUECTLR_EL1_BIT_51 + msr CORTEX_A76_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1262888_wa + +func check_errata_1262888 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262888 + + /* --------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1286807. + * This applies only to revision <= r3p0 of Cortex A76. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * --------------------------------------------------- + */ +func check_errata_1286807 +#if ERRATA_A76_1286807 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x30 + b cpu_rev_var_ls +#endif +endfunc check_errata_1286807 + + /* -------------------------------------------------- + * Errata workaround for Cortex A76 Errata #1791580. + * This applies to revisions <= r4p0 of Cortex A76. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1791580_wa + /* Compare x0 against revision r4p0 */ + mov x17, x30 + bl check_errata_1791580 + cbz x0, 1f + mrs x1, CORTEX_A76_CPUACTLR2_EL1 + orr x1, x1, CORTEX_A76_CPUACTLR2_EL1_BIT_2 + msr CORTEX_A76_CPUACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a76_1791580_wa + +func check_errata_1791580 + /* Applies to everything <=r4p0. */ + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1791580 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1262606, + * #1275112, and #1868343. #1262606 and #1275112 + * apply to revisions <= r3p0 and #1868343 applies to + * revisions <= r4p0. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ + +func errata_a76_1262606_1275112_1868343_wa + mov x17, x30 + +/* Check for <= r3p0 cases and branch if check passes. */ +#if ERRATA_A76_1262606 || ERRATA_A76_1275112 + bl check_errata_1262606 + cbnz x0, 1f +#endif + +/* Check for <= r4p0 cases and branch if check fails. */ +#if ERRATA_A76_1868343 + bl check_errata_1868343 + cbz x0, 2f +#endif +1: + mrs x1, CORTEX_A76_CPUACTLR_EL1 + orr x1, x1, #CORTEX_A76_CPUACTLR_EL1_BIT_13 + msr CORTEX_A76_CPUACTLR_EL1, x1 + isb +2: + ret x17 +endfunc errata_a76_1262606_1275112_1868343_wa + +func check_errata_1262606 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262606 + +func check_errata_1275112 + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1275112 + +func check_errata_1868343 + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1868343 + +/* -------------------------------------------------- + * Errata Workaround for A76 Erratum 1946160. + * This applies to revisions r3p0 - r4p1 of A76. + * It also exists in r0p0 - r2p0 but there is no fix + * in those revisions. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a76_1946160_wa + /* Compare x0 against revisions r3p0 - r4p1 */ + mov x17, x30 + bl check_errata_1946160 + cbz x0, 1f + + mov x0, #3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #4 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #5 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_a76_1946160_wa + +func check_errata_1946160 + /* Applies to revisions r3p0 - r4p1. */ + mov x1, #0x30 + mov x2, #0x41 + b cpu_rev_var_range +endfunc check_errata_1946160 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + +func cortex_a76_disable_wa_cve_2018_3639 + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + bic x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb + ret +endfunc cortex_a76_disable_wa_cve_2018_3639 + + /* -------------------------------------------------------------- + * Errata Workaround for Cortex A76 Errata #1165522. + * This applies only to revisions <= r3p0 of Cortex A76. + * Due to the nature of the errata it is applied unconditionally + * when built in, report it as applicable in this case + * -------------------------------------------------------------- + */ +func check_errata_1165522 +#if ERRATA_A76_1165522 + mov x0, #ERRATA_APPLIES + ret +#else + mov x1, #0x30 + b cpu_rev_var_ls +#endif +endfunc check_errata_1165522 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif /* WORKAROUND_CVE_2022_23960 */ + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A76. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a76_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A76_1073348 + mov x0, x18 + bl errata_a76_1073348_wa +#endif + +#if ERRATA_A76_1130799 + mov x0, x18 + bl errata_a76_1130799_wa +#endif + +#if ERRATA_A76_1220197 + mov x0, x18 + bl errata_a76_1220197_wa +#endif + +#if ERRATA_A76_1257314 + mov x0, x18 + bl errata_a76_1257314_wa +#endif + +#if ERRATA_A76_1262606 || ERRATA_A76_1275112 || ERRATA_A76_1868343 + mov x0, x18 + bl errata_a76_1262606_1275112_1868343_wa +#endif + +#if ERRATA_A76_1262888 + mov x0, x18 + bl errata_a76_1262888_wa +#endif + +#if ERRATA_A76_1791580 + mov x0, x18 + bl errata_a76_1791580_wa +#endif + +#if ERRATA_A76_1946160 + mov x0, x18 + bl errata_a76_1946160_wa +#endif + +#if WORKAROUND_CVE_2018_3639 + /* If the PE implements SSBS, we don't need the dynamic workaround */ + mrs x0, id_aa64pfr1_el1 + lsr x0, x0, #ID_AA64PFR1_EL1_SSBS_SHIFT + and x0, x0, #ID_AA64PFR1_EL1_SSBS_MASK +#if !DYNAMIC_WORKAROUND_CVE_2018_3639 && ENABLE_ASSERTIONS + cmp x0, 0 + ASM_ASSERT(ne) +#endif +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cbnz x0, 1f + mrs x0, CORTEX_A76_CPUACTLR2_EL1 + orr x0, x0, #CORTEX_A76_CPUACTLR2_EL1_DISABLE_LOAD_PASS_STORE + msr CORTEX_A76_CPUACTLR2_EL1, x0 + isb + +#ifdef IMAGE_BL31 + /* + * The Cortex-A76 generic vectors are overwritten to use the vectors + * defined above. This is required in order to apply mitigation + * against CVE-2018-3639 on exception entry from lower ELs. + * If the below vector table is used, skip overriding it again for + * CVE_2022_23960 as both use the same vbar. + */ + adr x0, cortex_a76_wa_cve_vbar + msr vbar_el3, x0 + isb + b 2f +#endif /* IMAGE_BL31 */ + +1: +#endif /* DYNAMIC_WORKAROUND_CVE_2018_3639 */ +#endif /* WORKAROUND_CVE_2018_3639 */ + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A76 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. This will be bypassed + * if DYNAMIC_WORKAROUND_CVE_2018_3639 has overridden the vectors. + */ + adr x0, cortex_a76_wa_cve_vbar + msr vbar_el3, x0 + isb +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ +2: + +#if ERRATA_DSU_798953 + bl errata_dsu_798953_wa +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc cortex_a76_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a76_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A76_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A76_CORE_PWRDN_EN_MASK + msr CORTEX_A76_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a76_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A76. Must follow AAPCS. + */ +func cortex_a76_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A76_1073348, cortex_a76, 1073348 + report_errata ERRATA_A76_1130799, cortex_a76, 1130799 + report_errata ERRATA_A76_1220197, cortex_a76, 1220197 + report_errata ERRATA_A76_1257314, cortex_a76, 1257314 + report_errata ERRATA_A76_1262606, cortex_a76, 1262606 + report_errata ERRATA_A76_1262888, cortex_a76, 1262888 + report_errata ERRATA_A76_1275112, cortex_a76, 1275112 + report_errata ERRATA_A76_1286807, cortex_a76, 1286807 + report_errata ERRATA_A76_1791580, cortex_a76, 1791580 + report_errata ERRATA_A76_1165522, cortex_a76, 1165522 + report_errata ERRATA_A76_1868343, cortex_a76, 1868343 + report_errata ERRATA_A76_1946160, cortex_a76, 1946160 + report_errata WORKAROUND_CVE_2018_3639, cortex_a76, cve_2018_3639 + report_errata ERRATA_DSU_798953, cortex_a76, dsu_798953 + report_errata ERRATA_DSU_936184, cortex_a76, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, cortex_a76, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a76_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a76 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.cortex_a76_regs, "aS" +cortex_a76_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a76_cpu_reg_dump + adr x6, cortex_a76_regs + mrs x8, CORTEX_A76_CPUECTLR_EL1 + ret +endfunc cortex_a76_cpu_reg_dump + +declare_cpu_ops_wa cortex_a76, CORTEX_A76_MIDR, \ + cortex_a76_reset_func, \ + CPU_NO_EXTRA1_FUNC, \ + cortex_a76_disable_wa_cve_2018_3639, \ + CPU_NO_EXTRA3_FUNC, \ + cortex_a76_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S new file mode 100644 index 0000000..5c19548 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A76AE must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A76AE supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A76AE_BHB_LOOP_COUNT, cortex_a76ae +#endif /* WORKAROUND_CVE_2022_23960 */ + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif /* WORKAROUND_CVE_2022_23960 */ + ret +endfunc check_errata_cve_2022_23960 + + /* -------------------------------------------- + * The CPU Ops reset function for Cortex-A76AE. + * Shall clobber: x0-x19 + * -------------------------------------------- + */ +func cortex_a76ae_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A76ae generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a76ae + msr vbar_el3, x0 + isb +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + ret +endfunc cortex_a76ae_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a76ae_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A76AE_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A76AE_CORE_PWRDN_EN_MASK + msr CORTEX_A76AE_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a76ae_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A76AE. Must follow AAPCS. + */ +func cortex_a76ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2022_23960, cortex_a76ae, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a76ae_errata_report +#endif /* REPORT_ERRATA */ + + /* --------------------------------------------- + * This function provides cortex_a76ae 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.cortex_a76ae_regs, "aS" +cortex_a76ae_regs: /* The ASCII list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a76ae_cpu_reg_dump + adr x6, cortex_a76ae_regs + mrs x8, CORTEX_A76AE_CPUECTLR_EL1 + ret +endfunc cortex_a76ae_cpu_reg_dump + +declare_cpu_ops cortex_a76ae, CORTEX_A76AE_MIDR, cortex_a76ae_reset_func, \ + cortex_a76ae_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S new file mode 100644 index 0000000..e7365e2 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex-A77 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex-A77 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A77_BHB_LOOP_COUNT, cortex_a77 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1508412. + * This applies only to revision <= r1p0 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1508412_wa + /* + * Compare x0 against revision r1p0 + */ + mov x17, x30 + bl check_errata_1508412 + cbz x0, 3f + /* + * Compare x0 against revision r0p0 + */ + bl check_errata_1508412_0 + cbz x0, 1f + ldr x0, =0x0 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8400000 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FFE00000 + msr CORTEX_A77_CPUPMR_EL3, x0 + ldr x0, =0x4004003FF + msr CORTEX_A77_CPUPCR_EL3, x0 + ldr x0, =0x1 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8C00040 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FFE00040 + msr CORTEX_A77_CPUPMR_EL3, x0 + b 2f +1: + ldr x0, =0x0 + msr CORTEX_A77_CPUPSELR_EL3, x0 + ldr x0, =0x00E8400000 + msr CORTEX_A77_CPUPOR_EL3, x0 + ldr x0, =0x00FF600000 + msr CORTEX_A77_CPUPMR_EL3, x0 + ldr x0, =0x00E8E00080 + msr CORTEX_A77_CPUPOR2_EL3, x0 + ldr x0, =0x00FFE000C0 + msr CORTEX_A77_CPUPMR2_EL3, x0 +2: + ldr x0, =0x04004003FF + msr CORTEX_A77_CPUPCR_EL3, x0 + isb +3: + ret x17 +endfunc errata_a77_1508412_wa + +func check_errata_1508412 + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1508412 + +func check_errata_1508412_0 + mov x1, #0x0 + b cpu_rev_var_ls +endfunc check_errata_1508412_0 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1925769. + * This applies to revision <= r1p1 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1925769_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1925769 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x1, CORTEX_A77_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A77_CPUECTLR_EL1_BIT_8 + msr CORTEX_A77_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a77_1925769_wa + +func check_errata_1925769 + /* Applies to everything <= r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1925769 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1946167. + * This applies to revision <= r1p1 of Cortex A77. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1946167_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1946167 + cbz x0, 1f + + ldr x0,=0x4 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3900002 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF00083 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + ldr x0,=0x5 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3800082 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF00083 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + ldr x0,=0x6 + msr CORTEX_A77_CPUPSELR_EL3,x0 + ldr x0,=0x10E3800200 + msr CORTEX_A77_CPUPOR_EL3,x0 + ldr x0,=0x10FFF003E0 + msr CORTEX_A77_CPUPMR_EL3,x0 + ldr x0,=0x2001003FF + msr CORTEX_A77_CPUPCR_EL3,x0 + + isb +1: + ret x17 +endfunc errata_a77_1946167_wa + +func check_errata_1946167 + /* Applies to everything <= r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1946167 + + /* -------------------------------------------------- + * Errata Workaround for Cortex A77 Errata #1791578. + * This applies to revisions r0p0, r1p0, and r1p1 and is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a77_1791578_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1791578 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, CORTEX_A77_ACTLR2_EL1 + orr x1, x1, #CORTEX_A77_ACTLR2_EL1_BIT_2 + msr CORTEX_A77_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a77_1791578_wa + +func check_errata_1791578 + /* Applies to r0p0, r1p0, and r1p1 right now */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1791578 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A77. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func cortex_a77_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A77_1508412 + mov x0, x18 + bl errata_a77_1508412_wa +#endif + +#if ERRATA_A77_1925769 + mov x0, x18 + bl errata_a77_1925769_wa +#endif + +#if ERRATA_A77_1946167 + mov x0, x18 + bl errata_a77_1946167_wa +#endif + +#if ERRATA_A77_1791578 + mov x0, x18 + bl errata_a77_1791578_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A77 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a77 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a77_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a77_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A77_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A77_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_A77_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a77_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex-A77. Must follow AAPCS. + */ +func cortex_a77_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A77_1508412, cortex_a77, 1508412 + report_errata ERRATA_A77_1925769, cortex_a77, 1925769 + report_errata ERRATA_A77_1946167, cortex_a77, 1946167 + report_errata ERRATA_A77_1791578, cortex_a77, 1791578 + report_errata WORKAROUND_CVE_2022_23960, cortex_a77, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a77_errata_report +#endif + + + /* --------------------------------------------- + * This function provides Cortex-A77 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.cortex_a77_regs, "aS" +cortex_a77_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a77_cpu_reg_dump + adr x6, cortex_a77_regs + mrs x8, CORTEX_A77_CPUECTLR_EL1 + ret +endfunc cortex_a77_cpu_reg_dump + +declare_cpu_ops cortex_a77, CORTEX_A77_MIDR, \ + cortex_a77_reset_func, \ + cortex_a77_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S new file mode 100644 index 0000000..1a6f848 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78_BHB_LOOP_COUNT, cortex_a78 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for A78 Erratum 1688305. + * This applies to revision r0p0 and r1p0 of A78. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1688305_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1688305 + cbz x0, 1f + mrs x1, CORTEX_A78_ACTLR2_EL1 + orr x1, x1, #CORTEX_A78_ACTLR2_EL1_BIT_1 + msr CORTEX_A78_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1688305_wa + +func check_errata_1688305 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1688305 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata #1941498. + * This applies to revisions r0p0, r1p0, and r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1941498_wa + /* Compare x0 against revision <= r1p1 */ + mov x17, x30 + bl check_errata_1941498 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x1, CORTEX_A78_CPUECTLR_EL1 + orr x1, x1, #CORTEX_A78_CPUECTLR_EL1_BIT_8 + msr CORTEX_A78_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1941498_wa + +func check_errata_1941498 + /* Check for revision <= r1p1, might need to be updated later. */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1941498 + +/* -------------------------------------------------- + * Errata Workaround for A78 Erratum 1951500. + * This applies to revisions r1p0 and r1p1 of A78. + * The issue also exists in r0p0 but there is no fix + * in that revision. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1951500_wa + /* Compare x0 against revisions r1p0 - r1p1 */ + mov x17, x30 + bl check_errata_1951500 + cbz x0, 1f + + msr S3_6_c15_c8_0, xzr + ldr x0, =0x10E3900002 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #1 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + isb +1: + ret x17 +endfunc errata_a78_1951500_wa + +func check_errata_1951500 + /* Applies to revisions r1p0 and r1p1. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 1) + b cpu_rev_var_range +endfunc check_errata_1951500 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata #1821534. + * This applies to revisions r0p0 and r1p0. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1821534_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1821534 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, CORTEX_A78_ACTLR2_EL1 + orr x1, x1, #CORTEX_A78_ACTLR2_EL1_BIT_2 + msr CORTEX_A78_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_a78_1821534_wa + +func check_errata_1821534 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1821534 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata 1952683. + * This applies to revision r0p0. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_1952683_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_1952683 + cbz x0, 1f + + ldr x0,=0x5 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xEEE10A10 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0FFF + msr S3_6_c15_c8_3,x0 + ldr x0,=0x0010F000 + msr S3_6_c15_c8_4,x0 + ldr x0,=0x0010F000 + msr S3_6_c15_c8_5,x0 + ldr x0,=0x40000080023ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xEE640F34 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0FFF + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000080023ff + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_a78_1952683_wa + +func check_errata_1952683 + /* Applies to r0p0 only */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1952683 + +/* -------------------------------------------------- + * Errata Workaround for Cortex A78 Errata 2132060. + * This applies to revisions r0p0, r1p0, r1p1, and r1p2. + * It is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_a78_2132060_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2132060 + cbz x0, 1f + + /* Apply the workaround. */ + mrs x1, CORTEX_A78_CPUECTLR_EL1 + mov x0, #CORTEX_A78_CPUECTLR_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH + msr CORTEX_A78_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_a78_2132060_wa + +func check_errata_2132060 + /* Applies to r0p0, r0p1, r1p1, and r1p2 */ + mov x1, #0x12 + b cpu_rev_var_ls +endfunc check_errata_2132060 + +/* -------------------------------------------------------------------- + * Errata Workaround for A78 Erratum 2242635. + * This applies to revisions r1p0, r1p1, and r1p2 of the Cortex A78 + * processor and is still open. + * The issue also exists in r0p0 but there is no fix in that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------------------------- + */ +func errata_a78_2242635_wa + /* Compare x0 against revisions r1p0 - r1p2 */ + mov x17, x30 + bl check_errata_2242635 + cbz x0, 1f + + ldr x0, =0x5 + msr S3_6_c15_c8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 /* CPUPCR_EL3 */ + + isb +1: + ret x17 +endfunc errata_a78_2242635_wa + +func check_errata_2242635 + /* Applies to revisions r1p0 through r1p2. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 2) + b cpu_rev_var_range +endfunc check_errata_2242635 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78 + * ------------------------------------------------- + */ +func cortex_a78_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A78_1688305 + mov x0, x18 + bl errata_a78_1688305_wa +#endif + +#if ERRATA_A78_1941498 + mov x0, x18 + bl errata_a78_1941498_wa +#endif + +#if ERRATA_A78_1951500 + mov x0, x18 + bl errata_a78_1951500_wa +#endif + +#if ERRATA_A78_1821534 + mov x0, x18 + bl errata_a78_1821534_wa +#endif + +#if ERRATA_A78_1952683 + mov x0, x18 + bl errata_a78_1952683_wa +#endif + +#if ERRATA_A78_2132060 + mov x0, x18 + bl errata_a78_2132060_wa +#endif + +#if ERRATA_A78_2242635 + mov x0, x18 + bl errata_a78_2242635_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + bic x0, x0, #CORTEX_A78_ACTLR_TAM_BIT + msr actlr_el3, x0 + + /* Make sure accesses from non-secure EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + bic x0, x0, #CORTEX_A78_ACTLR_TAM_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #CORTEX_A78_AMU_GROUP0_MASK + msr CPUAMCNTENSET0_EL0, x0 + + /* Enable group1 counters */ + mov x0, #CORTEX_A78_AMU_GROUP1_MASK + msr CPUAMCNTENSET1_EL0, x0 +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a78_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func cortex_a78_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, CORTEX_A78_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a78_core_pwr_dwn + + /* + * Errata printing function for cortex_a78. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a78_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A78_1688305, cortex_a78, 1688305 + report_errata ERRATA_A78_1941498, cortex_a78, 1941498 + report_errata ERRATA_A78_1951500, cortex_a78, 1951500 + report_errata ERRATA_A78_1821534, cortex_a78, 1821534 + report_errata ERRATA_A78_1952683, cortex_a78, 1952683 + report_errata ERRATA_A78_2132060, cortex_a78, 2132060 + report_errata ERRATA_A78_2242635, cortex_a78, 2242635 + report_errata WORKAROUND_CVE_2022_23960, cortex_a78, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a78 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.cortex_a78_regs, "aS" +cortex_a78_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78_cpu_reg_dump + adr x6, cortex_a78_regs + mrs x8, CORTEX_A78_CPUECTLR_EL1 + ret +endfunc cortex_a78_cpu_reg_dump + +declare_cpu_ops cortex_a78, CORTEX_A78_MIDR, \ + cortex_a78_reset_func, \ + cortex_a78_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S new file mode 100644 index 0000000..ee536a4 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S @@ -0,0 +1,398 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * Copyright (c) 2021-2023, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78_ae must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78_AE_BHB_LOOP_COUNT, cortex_a78_ae +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 1941500. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_1941500_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_1941500 + cbz x0, 1f + + /* Set bit 8 in ECTLR_EL1 */ + mrs x0, CORTEX_A78_AE_CPUECTLR_EL1 + bic x0, x0, #CORTEX_A78_AE_CPUECTLR_EL1_BIT_8 + msr CORTEX_A78_AE_CPUECTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_1941500_wa + +func check_errata_1941500 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_1941500 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 1951502. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_1951502_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_1951502 + cbz x0, 1f + + msr S3_6_c15_c8_0, xzr + ldr x0, =0x10E3900002 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #1 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + mov x0, #2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_c15_c8_1, x0 + + isb +1: + ret x17 +endfunc errata_a78_ae_1951502_wa + +func check_errata_1951502 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_1951502 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 2376748. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_2376748_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_2376748 + cbz x0, 1f + + /* ------------------------------------------------------- + * Set CPUACTLR2_EL1[0] to 1 to force PLDW/PFRM ST to + * behave like PLD/PRFM LD and not cause invalidations to + * other PE caches. There might be a small performance + * degradation to this workaround for certain workloads + * that share data. + * ------------------------------------------------------- + */ + mrs x0, CORTEX_A78_AE_ACTLR2_EL1 + orr x0, x0, #CORTEX_A78_AE_ACTLR2_EL1_BIT_0 + msr CORTEX_A78_AE_ACTLR2_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_2376748_wa + +func check_errata_2376748 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_2376748 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 2395408. + * This applies to revisions r0p0 and r0p1 of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_a78_ae_2395408_wa + /* Compare x0 against revisions r0p0 - r0p1 */ + mov x17, x30 + bl check_errata_2395408 + cbz x0, 1f + + /* -------------------------------------------------------- + * Disable folding of demand requests into older prefetches + * with L2 miss requests outstanding by setting the + * CPUACTLR2_EL1[40] to 1. + * -------------------------------------------------------- + */ + mrs x0, CORTEX_A78_AE_ACTLR2_EL1 + orr x0, x0, #CORTEX_A78_AE_ACTLR2_EL1_BIT_40 + msr CORTEX_A78_AE_ACTLR2_EL1, x0 + isb +1: + ret x17 +endfunc errata_a78_ae_2395408_wa + +func check_errata_2395408 + /* Applies to revisions r0p0 and r0p1. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 1) + b cpu_rev_var_range +endfunc check_errata_2395408 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE Erratum 2466780. + * This applies can be avoided by flushing the mop cache + * following a write to registers SCR_EL3, HCR_EL2, or SCTLR_ELx + * -------------------------------------------------- + */ +func errata_a78_ae_2466780_wa + /* Compare x0 against revisions r0p0 - r0p2 */ + mov x17, x30 + bl check_errata_2466780 + cbz x0, 1f + + mov_imm x0, 0x3 + msr CPUPSELR_EL3, x0 + mov_imm x0, 0xEE010F10 + msr CPUPOR_EL3, x0 + mov_imm x0, 0xFF1F0FFE + msr CPUPMR_EL3, x0 + mov_imm x0, 0x100000004003FF + msr CPUPCR_EL3,x0 + isb +1: + ret x17 +endfunc errata_a78_ae_2466780_wa + +func check_errata_2466780 + /* Applies to revisions r0p0, r0p1 and r0p2. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 2) + b cpu_rev_var_range +endfunc check_errata_2466780 + +/* ------------------------------------------------------- + * Errata Workaround for Cortex Hercules AE Erratum 2743093. + * This applies to revisions <= r0p2. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * ------------------------------------------------------- + */ +func errata_a78_ae_2743093_wa + mov x17, x30 + bl check_errata_2743093 + cbz x0, 1f + + /* dsb before isb of power down sequence */ + dsb sy +1: + ret x17 +endfunc errata_a78_ae_2743093_wa + +func check_errata_2743093 + /* Applies to all revisions <= r0p2 */ + mov x1, #0x02 + b cpu_rev_var_ls +endfunc check_errata_2743093 + +/* -------------------------------------------------- + * Errata Workaround for A78 AE 2743229 + * This applies to revisions applies to r0p0, r0p1, and r0p2 + * of A78 AE. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Read CORTEX_A78_AE_ACTLR5_EL1 and set bit[56:55]=b'01 + * -------------------------------------------------- + */ +func errata_a78_ae_2743229 + /* Compare x0 against revisions r0p0 to r0p2 */ + mov x17, x30 + bl check_errata_2743229 + cbz x0, 1f + + /* Set bit [56:55]=b'01 in CPUACTLR5 */ + mrs x0, CORTEX_A78_AE_ACTLR5_EL1 + orr x0, x0, #CORTEX_A78_AE_ACTLR5_EL1_BIT_55 + bic x0, x0, #CORTEX_A78_AE_ACTLR5_EL1_BIT_56 + msr CORTEX_A78_AE_ACTLR5_EL1, x0 +1: + ret x17 +endfunc errata_a78_ae_2743229 + +func check_errata_2743229 + /* Applies to revisions r0p0 to r0p2. */ + mov x1, #CPU_REV(0, 0) + mov x2, #CPU_REV(0, 2) + b cpu_rev_var_range +endfunc check_errata_2743229 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78-AE + * ------------------------------------------------- + */ +func cortex_a78_ae_reset_func + mov x19, x30 + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_A78_AE_1941500 + mov x0, x18 + bl errata_a78_ae_1941500_wa +#endif + +#if ERRATA_A78_AE_1951502 + mov x0, x18 + bl errata_a78_ae_1951502_wa +#endif + +#if ERRATA_A78_AE_2376748 + mov x0, x18 + bl errata_a78_ae_2376748_wa +#endif + +#if ERRATA_A78_AE_2395408 + mov x0, x18 + bl errata_a78_ae_2395408_wa +#endif + +#if ERRATA_A78_AE_2466780 + mov x0, x18 + bl errata_a78_ae_2466780_wa +#endif + +#if ERRATA_A78_AE_2743229 + mov x0, x18 + bl errata_a78_ae_2743229 +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78AE generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78_ae + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_a78_ae_reset_func + + /* ------------------------------------------------------- + * HW will do the cache maintenance while powering down + * ------------------------------------------------------- + */ +func cortex_a78_ae_core_pwr_dwn + /* ------------------------------------------------------- + * Enable CPU power down bit in power control register + * ------------------------------------------------------- + */ + mrs x0, CORTEX_A78_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78_CPUPWRCTLR_EL1, x0 +#if ERRATA_A78_AE_2743093 + mov x15, x30 + bl cpu_get_rev_var + bl errata_a78_ae_2743093_wa + mov x30, x15 +#endif + isb + ret +endfunc cortex_a78_ae_core_pwr_dwn + + /* + * Errata printing function for cortex_a78_ae. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_a78_ae_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_A78_AE_1941500, cortex_a78_ae, 1941500 + report_errata ERRATA_A78_AE_1951502, cortex_a78_ae, 1951502 + report_errata ERRATA_A78_AE_2376748, cortex_a78_ae, 2376748 + report_errata ERRATA_A78_AE_2395408, cortex_a78_ae, 2395408 + report_errata ERRATA_A78_AE_2466780, cortex_a78_ae, 2466780 + report_errata ERRATA_A78_AE_2743093, cortex_a78_ae, 2743093 + report_errata ERRATA_A78_AE_2743229, cortex_a78_ae, 2743229 + report_errata WORKAROUND_CVE_2022_23960, cortex_a78_ae, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78_ae_errata_report +#endif + + /* ------------------------------------------------------- + * This function provides cortex_a78_ae 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.cortex_a78_ae_regs, "aS" +cortex_a78_ae_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78_ae_cpu_reg_dump + adr x6, cortex_a78_ae_regs + mrs x8, CORTEX_A78_CPUECTLR_EL1 + ret +endfunc cortex_a78_ae_cpu_reg_dump + +declare_cpu_ops cortex_a78_ae, CORTEX_A78_AE_MIDR, \ + cortex_a78_ae_reset_func, \ + cortex_a78_ae_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S new file mode 100644 index 0000000..0712109 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "cortex_a78c must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_A78C_BHB_LOOP_COUNT, cortex_a78c +#endif /* WORKAROUND_CVE_2022_23960 */ + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------------- + * The CPU Ops reset function for Cortex-A78C + * ------------------------------------------------- + */ +func cortex_a78c_reset_func +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-A78c generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_a78c + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + isb + ret +endfunc cortex_a78c_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_a78c_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_A78C_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_A78C_CPUPWRCTLR_EL1_CORE_PWRDN_EN_BIT + msr CORTEX_A78C_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_a78c_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex A78C. Must follow AAPCS. + */ +func cortex_a78c_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2022_23960, cortex_a78c, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_a78c_errata_report +#endif + + /* --------------------------------------------- + * This function provides cortex_a78c 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.cortex_a78c_regs, "aS" +cortex_a78c_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_a78c_cpu_reg_dump + adr x6, cortex_a78c_regs + mrs x8, CORTEX_A78C_CPUECTLR_EL1 + ret +endfunc cortex_a78c_cpu_reg_dump + +declare_cpu_ops cortex_a78c, CORTEX_A78C_MIDR, \ + cortex_a78c_reset_func, \ + cortex_a78c_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S new file mode 100644 index 0000000..445a691 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex Hayes must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Hayes supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_hayes_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_HAYES_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_HAYES_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_HAYES_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_hayes_core_pwr_dwn + + /* + * Errata printing function for Cortex Hayes. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_hayes_errata_report + ret +endfunc cortex_hayes_errata_report +#endif + +func cortex_hayes_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_hayes_reset_func + + /* --------------------------------------------- + * This function provides Cortex Hayes 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.cortex_hayes_regs, "aS" +cortex_hayes_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_hayes_cpu_reg_dump + adr x6, cortex_hayes_regs + mrs x8, CORTEX_HAYES_CPUECTLR_EL1 + ret +endfunc cortex_hayes_cpu_reg_dump + +declare_cpu_ops cortex_hayes, CORTEX_HAYES_MIDR, \ + cortex_hayes_reset_func, \ + cortex_hayes_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S new file mode 100644 index 0000000..2ab4296 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex Hunter must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Hunter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +func cortex_hunter_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_hunter_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_hunter_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_HUNTER_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_HUNTER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_HUNTER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_hunter_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Hunter. Must follow AAPCS. + */ +func cortex_hunter_errata_report + ret +endfunc cortex_hunter_errata_report +#endif + + /* --------------------------------------------- + * This function provides Cortex Hunter-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.cortex_hunter_regs, "aS" +cortex_hunter_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_hunter_cpu_reg_dump + adr x6, cortex_hunter_regs + mrs x8, CORTEX_HUNTER_CPUECTLR_EL1 + ret +endfunc cortex_hunter_cpu_reg_dump + +declare_cpu_ops cortex_hunter, CORTEX_HUNTER_MIDR, \ + cortex_hunter_reset_func, \ + cortex_hunter_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S new file mode 100644 index 0000000..98c7d6d --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex Makalu must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Makalu supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +func cortex_makalu_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_makalu_reset_func + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_makalu_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_MAKALU_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_MAKALU_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_MAKALU_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_makalu_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Makalu. Must follow AAPCS. + */ +func cortex_makalu_errata_report + ret +endfunc cortex_makalu_errata_report +#endif + + /* --------------------------------------------- + * This function provides Cortex Makalu-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.cortex_makalu_regs, "aS" +cortex_makalu_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_makalu_cpu_reg_dump + adr x6, cortex_makalu_regs + mrs x8, CORTEX_MAKALU_CPUECTLR_EL1 + ret +endfunc cortex_makalu_cpu_reg_dump + +declare_cpu_ops cortex_makalu, CORTEX_MAKALU_MIDR, \ + cortex_makalu_reset_func, \ + cortex_makalu_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S new file mode 100644 index 0000000..fbbf205 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex Makalu ELP must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex Makalu ELP supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_makalu_elp_arm_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_MAKALU_ELP_ARM_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_makalu_elp_arm_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Cortex Makalu ELP. Must follow AAPCS. + */ +func cortex_makalu_elp_arm_errata_report + ret +endfunc cortex_makalu_elp_arm_errata_report +#endif + +func cortex_makalu_elp_arm_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc cortex_makalu_elp_arm_reset_func + + /* --------------------------------------------- + * This function provides Cortex Makalu ELP- + * 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.cortex_makalu_elp_arm_regs, "aS" +cortex_makalu_elp_arm_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_makalu_elp_arm_cpu_reg_dump + adr x6, cortex_makalu_elp_arm_regs + mrs x8, CORTEX_MAKALU_ELP_ARM_CPUECTLR_EL1 + ret +endfunc cortex_makalu_elp_arm_cpu_reg_dump + +declare_cpu_ops cortex_makalu_elp_arm, CORTEX_MAKALU_ELP_ARM_MIDR, \ + cortex_makalu_elp_arm_reset_func, \ + cortex_makalu_elp_arm_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S b/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S new file mode 100644 index 0000000..9586a5b --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S @@ -0,0 +1,358 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Cortex X2 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Cortex X2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table CORTEX_X2_BHB_LOOP_COUNT, cortex_x2 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2002765. + * This applies to revisions r0p0, r1p0, and r2p0 and + * is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2002765_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2002765 + cbz x0, 1f + + ldr x0, =0x6 + msr S3_6_C15_C8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0xF3A08002 + msr S3_6_C15_C8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0xFFF0F7FE + msr S3_6_C15_C8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x40000001003ff + msr S3_6_C15_C8_1, x0 /* CPUPCR_EL3 */ + isb + +1: + ret x17 +endfunc errata_cortex_x2_2002765_wa + +func check_errata_2002765 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2002765 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2058056. + * This applies to revisions r0p0, r1p0, and r2p0 and + * is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2058056_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2058056 + cbz x0, 1f + + mrs x1, CORTEX_X2_CPUECTLR2_EL1 + mov x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_SHIFT, #CORTEX_X2_CPUECTLR2_EL1_PF_MODE_WIDTH + msr CORTEX_X2_CPUECTLR2_EL1, x1 + +1: + ret x17 +endfunc errata_cortex_x2_2058056_wa + +func check_errata_2058056 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2058056 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata #2083908. + * This applies to revision r2p0 and is open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x2, x17 + * -------------------------------------------------- + */ +func errata_cortex_x2_2083908_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2083908 + cbz x0, 1f + + /* Apply the workaround by setting bit 13 in CPUACTLR5_EL1. */ + mrs x1, CORTEX_X2_CPUACTLR5_EL1 + orr x1, x1, #BIT(13) + msr CORTEX_X2_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_cortex_x2_2083908_wa + +func check_errata_2083908 + /* Applies to r2p0 */ + mov x1, #0x20 + mov x2, #0x20 + b cpu_rev_var_range +endfunc check_errata_2083908 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-X2 Errata 2017096. + * This applies only to revisions r0p0, r1p0 and r2p0 + * and is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2017096_wa + /* Compare x0 against revision r0p0 to r2p0 */ + mov x17, x30 + bl check_errata_2017096 + cbz x0, 1f + mrs x1, CORTEX_X2_CPUECTLR_EL1 + orr x1, x1, CORTEX_X2_CPUECTLR_EL1_PFSTIDIS_BIT + msr CORTEX_X2_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_x2_2017096_wa + +func check_errata_2017096 + /* Applies to r0p0, r1p0, r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2017096 + + /* -------------------------------------------------- + * Errata Workaround for Cortex-X2 Errata 2081180. + * This applies to revision r0p0, r1p0 and r2p0 + * and is fixed in r2p1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2081180_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2081180 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x3 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0xF3A08002 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0xFFF0F7FE + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x10002001003FF + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + ldr x0, =0x4 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0xBF200000 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0xFFEF0000 + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x10002001003F3 + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_x2_2081180_wa + +func check_errata_2081180 + /* Applies to r0p0, r1p0 and r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2081180 + + /* -------------------------------------------------- + * Errata Workaround for Cortex X2 Errata 2216384. + * This applies to revisions r0p0, r1p0, and r2p0 + * and is fixed in r2p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1, x17 + * -------------------------------------------------- + */ +func errata_x2_2216384_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2216384 + cbz x0, 1f + + mrs x1, CORTEX_X2_CPUACTLR5_EL1 + orr x1, x1, CORTEX_X2_CPUACTLR5_EL1_BIT_17 + msr CORTEX_X2_CPUACTLR5_EL1, x1 + + /* Apply instruction patching sequence */ + ldr x0, =0x5 + msr CORTEX_X2_IMP_CPUPSELR_EL3, x0 + ldr x0, =0x10F600E000 + msr CORTEX_X2_IMP_CPUPOR_EL3, x0 + ldr x0, =0x10FF80E000 + msr CORTEX_X2_IMP_CPUPMR_EL3, x0 + ldr x0, =0x80000000003FF + msr CORTEX_X2_IMP_CPUPCR_EL3, x0 + isb + +1: + ret x17 +endfunc errata_x2_2216384_wa + +func check_errata_2216384 + /* Applies to r0p0 - r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_2216384 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func cortex_x2_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, CORTEX_X2_CPUPWRCTLR_EL1 + orr x0, x0, #CORTEX_X2_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr CORTEX_X2_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc cortex_x2_core_pwr_dwn + + /* + * Errata printing function for Cortex X2. Must follow AAPCS. + */ +#if REPORT_ERRATA +func cortex_x2_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_X2_2002765, cortex_x2, 2002765 + report_errata ERRATA_X2_2058056, cortex_x2, 2058056 + report_errata ERRATA_X2_2083908, cortex_x2, 2083908 + report_errata ERRATA_X2_2017096, cortex_x2, 2017096 + report_errata ERRATA_X2_2081180, cortex_x2, 2081180 + report_errata ERRATA_X2_2216384, cortex_x2, 2216384 + report_errata WORKAROUND_CVE_2022_23960, cortex_x2, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc cortex_x2_errata_report +#endif + +func cortex_x2_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + + /* Get the CPU revision and stash it in x18. */ + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_X2_2002765 + mov x0, x18 + bl errata_cortex_x2_2002765_wa +#endif + +#if ERRATA_X2_2058056 + mov x0, x18 + bl errata_cortex_x2_2058056_wa +#endif + +#if ERRATA_X2_2083908 + mov x0, x18 + bl errata_cortex_x2_2083908_wa +#endif + +#if ERRATA_X2_2017096 + mov x0, x18 + bl errata_x2_2017096_wa +#endif + +#if ERRATA_X2_2081180 + mov x0, x18 + bl errata_x2_2081180_wa +#endif + +#if ERRATA_X2_2216384 + mov x0, x18 + bl errata_x2_2216384_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Cortex-X2 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_cortex_x2 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc cortex_x2_reset_func + + /* --------------------------------------------- + * This function provides Cortex X2 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.cortex_x2_regs, "aS" +cortex_x2_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func cortex_x2_cpu_reg_dump + adr x6, cortex_x2_regs + mrs x8, CORTEX_X2_CPUECTLR_EL1 + ret +endfunc cortex_x2_cpu_reg_dump + +declare_cpu_ops cortex_x2, CORTEX_X2_MIDR, \ + cortex_x2_reset_func, \ + cortex_x2_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S new file mode 100644 index 0000000..2385627 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S @@ -0,0 +1,456 @@ +/* + * Copyright (c) 2014-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + + /* Reset fn is needed in BL at reset vector */ +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || (defined(IMAGE_BL2) && BL2_AT_EL3) + /* + * The reset handler common to all platforms. After a matching + * cpu_ops structure entry is found, the correponding reset_handler + * in the cpu_ops is invoked. + * Clobbers: x0 - x19, x30 + */ + .globl reset_handler +func reset_handler + mov x19, x30 + + /* The plat_reset_handler can clobber x0 - x18, x30 */ + bl plat_reset_handler + + /* Get the matching cpu_ops pointer */ + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the cpu_ops reset handler */ + ldr x2, [x0, #CPU_RESET_FUNC] + mov x30, x19 + cbz x2, 1f + + /* The cpu_ops reset handler can clobber x0 - x19, x30 */ + br x2 +1: + ret +endfunc reset_handler + +#endif + +#ifdef IMAGE_BL31 /* The power down core and cluster is needed only in BL31 */ + /* + * void prepare_cpu_pwr_dwn(unsigned int power_level) + * + * Prepare CPU power down function for all platforms. The function takes + * a domain level to be powered down as its parameter. After the cpu_ops + * pointer is retrieved from cpu_data, the handler for requested power + * level is called. + */ + .globl prepare_cpu_pwr_dwn +func prepare_cpu_pwr_dwn + /* + * If the given power level exceeds CPU_MAX_PWR_DWN_OPS, we call the + * power down handler for the last power level + */ + mov_imm x2, (CPU_MAX_PWR_DWN_OPS - 1) + cmp x0, x2 + csel x2, x2, x0, hi + + mrs x1, tpidr_el3 + ldr x0, [x1, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + + /* Get the appropriate power down handler */ + mov x1, #CPU_PWR_DWN_OPS + add x1, x1, x2, lsl #3 + ldr x1, [x0, x1] +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + br x1 +endfunc prepare_cpu_pwr_dwn + + + /* + * Initializes the cpu_ops_ptr if not already initialized + * in cpu_data. This can be called without a runtime stack, but may + * only be called after the MMU is enabled. + * clobbers: x0 - x6, x10 + */ + .globl init_cpu_ops +func init_cpu_ops + mrs x6, tpidr_el3 + ldr x0, [x6, #CPU_DATA_CPU_OPS_PTR] + cbnz x0, 1f + mov x10, x30 + bl get_cpu_ops_ptr +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + str x0, [x6, #CPU_DATA_CPU_OPS_PTR]! + mov x30, x10 +1: + ret +endfunc init_cpu_ops +#endif /* IMAGE_BL31 */ + +#if defined(IMAGE_BL31) && CRASH_REPORTING + /* + * The cpu specific registers which need to be reported in a crash + * are reported via cpu_ops cpu_reg_dump function. After a matching + * cpu_ops structure entry is found, the correponding cpu_reg_dump + * in the cpu_ops is invoked. + */ + .globl do_cpu_reg_dump +func do_cpu_reg_dump + mov x16, x30 + + /* Get the matching cpu_ops pointer */ + bl get_cpu_ops_ptr + cbz x0, 1f + + /* Get the cpu_ops cpu_reg_dump */ + ldr x2, [x0, #CPU_REG_DUMP] + cbz x2, 1f + blr x2 +1: + mov x30, x16 + ret +endfunc do_cpu_reg_dump +#endif + + /* + * The below function returns the cpu_ops structure matching the + * midr of the core. It reads the MIDR_EL1 and finds the matching + * entry in cpu_ops entries. Only the implementation and part number + * are used to match the entries. + * + * If cpu_ops for the MIDR_EL1 cannot be found and + * SUPPORT_UNKNOWN_MPID is enabled, it will try to look for a + * default cpu_ops with an MIDR value of 0. + * (Implementation number 0x0 should be reserved for software use + * and therefore no clashes should happen with that default value). + * + * Return : + * x0 - The matching cpu_ops pointer on Success + * x0 - 0 on failure. + * Clobbers : x0 - x5 + */ + .globl get_cpu_ops_ptr +func get_cpu_ops_ptr + /* Read the MIDR_EL1 */ + mrs x2, midr_el1 + mov_imm x3, CPU_IMPL_PN_MASK + + /* Retain only the implementation and part number using mask */ + and w2, w2, w3 + + /* Get the cpu_ops end location */ + adr x5, (__CPU_OPS_END__ + CPU_MIDR) + + /* Initialize the return parameter */ + mov x0, #0 +1: + /* Get the cpu_ops start location */ + adr x4, (__CPU_OPS_START__ + CPU_MIDR) + +2: + /* Check if we have reached end of list */ + cmp x4, x5 + b.eq search_def_ptr + + /* load the midr from the cpu_ops */ + ldr x1, [x4], #CPU_OPS_SIZE + and w1, w1, w3 + + /* Check if midr matches to midr of this core */ + cmp w1, w2 + b.ne 2b + + /* Subtract the increment and offset to get the cpu-ops pointer */ + sub x0, x4, #(CPU_OPS_SIZE + CPU_MIDR) +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif +#ifdef SUPPORT_UNKNOWN_MPID + cbnz x2, exit_mpid_found + /* Mark the unsupported MPID flag */ + adrp x1, unsupported_mpid_flag + add x1, x1, :lo12:unsupported_mpid_flag + str w2, [x1] +exit_mpid_found: +#endif + ret + + /* + * Search again for a default pointer (MIDR = 0x0) + * or return error if already searched. + */ +search_def_ptr: +#ifdef SUPPORT_UNKNOWN_MPID + cbz x2, error_exit + mov x2, #0 + b 1b +error_exit: +#endif + ret +endfunc get_cpu_ops_ptr + +/* + * Extract CPU revision and variant, and combine them into a single numeric for + * easier comparison. + */ + .globl cpu_get_rev_var +func cpu_get_rev_var + mrs x1, midr_el1 + + /* + * Extract the variant[23:20] and revision[3:0] from MIDR, and pack them + * as variant[7:4] and revision[3:0] of x0. + * + * First extract x1[23:16] to x0[7:0] and zero fill the rest. Then + * extract x1[3:0] into x0[3:0] retaining other bits. + */ + ubfx x0, x1, #(MIDR_VAR_SHIFT - MIDR_REV_BITS), #(MIDR_REV_BITS + MIDR_VAR_BITS) + bfxil x0, x1, #MIDR_REV_SHIFT, #MIDR_REV_BITS + ret +endfunc cpu_get_rev_var + +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is less than or same as a given + * value, indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x3 + */ + .globl cpu_rev_var_ls +func cpu_rev_var_ls + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, ls + ret +endfunc cpu_rev_var_ls + +/* + * Compare the CPU's revision-variant (x0) with a given value (x1), for errata + * application purposes. If the revision-variant is higher than or same as a + * given value, indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x3 + */ + .globl cpu_rev_var_hs +func cpu_rev_var_hs + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x0, x2, x3, hs + ret +endfunc cpu_rev_var_hs + +/* + * Compare the CPU's revision-variant (x0) with a given range (x1 - x2), for errata + * application purposes. If the revision-variant is between or includes the given + * values, this indicates that errata applies; otherwise not. + * + * Shall clobber: x0-x4 + */ + .globl cpu_rev_var_range +func cpu_rev_var_range + mov x3, #ERRATA_APPLIES + mov x4, #ERRATA_NOT_APPLIES + cmp x0, x1 + csel x1, x3, x4, hs + cbz x1, 1f + cmp x0, x2 + csel x1, x3, x4, ls +1: + mov x0, x1 + ret +endfunc cpu_rev_var_range + +#if REPORT_ERRATA +/* + * void print_errata_status(void); + * + * Function to print errata status for CPUs of its class. Must be called only: + * + * - with MMU and data caches are enabled; + * - after cpu_ops have been initialized in per-CPU data. + */ + .globl print_errata_status +func print_errata_status +#ifdef IMAGE_BL1 + /* + * BL1 doesn't have per-CPU data. So retrieve the CPU operations + * directly. + */ + stp xzr, x30, [sp, #-16]! + bl get_cpu_ops_ptr + ldp xzr, x30, [sp], #16 + ldr x1, [x0, #CPU_ERRATA_FUNC] + cbnz x1, .Lprint +#else + /* + * Retrieve pointer to cpu_ops from per-CPU data, and further, the + * errata printing function. If it's non-NULL, jump to the function in + * turn. + */ + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x1, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x1, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x1, #CPU_ERRATA_FUNC] + cbz x0, .Lnoprint + + /* + * Printing errata status requires atomically testing the printed flag. + */ + stp x19, x30, [sp, #-16]! + mov x19, x0 + + /* + * Load pointers to errata lock and printed flag. Call + * errata_needs_reporting to check whether this CPU needs to report + * errata status pertaining to its class. + */ + ldr x0, [x1, #CPU_ERRATA_LOCK] + ldr x1, [x1, #CPU_ERRATA_PRINTED] + bl errata_needs_reporting + mov x1, x19 + ldp x19, x30, [sp], #16 + cbnz x0, .Lprint +#endif +.Lnoprint: + ret +.Lprint: + /* Jump to errata reporting function for this CPU */ + br x1 +endfunc print_errata_status +#endif + +/* + * int check_wa_cve_2017_5715(void); + * + * This function returns: + * - ERRATA_APPLIES when firmware mitigation is required. + * - ERRATA_NOT_APPLIES when firmware mitigation is _not_ required. + * - ERRATA_MISSING when firmware mitigation would be required but + * is not compiled in. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl check_wa_cve_2017_5715 +func check_wa_cve_2017_5715 + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_EXTRA1_FUNC] + /* + * If the reserved function pointer is NULL, this CPU + * is unaffected by CVE-2017-5715 so bail out. + */ + cmp x0, #CPU_NO_EXTRA1_FUNC + beq 1f + br x0 +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_wa_cve_2017_5715 + +/* + * void *wa_cve_2018_3639_get_disable_ptr(void); + * + * Returns a function pointer which is used to disable mitigation + * for CVE-2018-3639. + * The function pointer is only returned on cores that employ + * dynamic mitigation. If the core uses static mitigation or is + * unaffected by CVE-2018-3639 this function returns NULL. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl wa_cve_2018_3639_get_disable_ptr +func wa_cve_2018_3639_get_disable_ptr + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_EXTRA2_FUNC] + ret +endfunc wa_cve_2018_3639_get_disable_ptr + +/* + * int check_smccc_arch_wa3_applies(void); + * + * This function checks whether SMCCC_ARCH_WORKAROUND_3 is enabled to mitigate + * CVE-2022-23960 for this CPU. It returns: + * - ERRATA_APPLIES when SMCCC_ARCH_WORKAROUND_3 can be invoked to mitigate + * the CVE. + * - ERRATA_NOT_APPLIES when SMCCC_ARCH_WORKAROUND_3 should not be invoked to + * mitigate the CVE. + * + * NOTE: Must be called only after cpu_ops have been initialized + * in per-CPU data. + */ + .globl check_smccc_arch_wa3_applies +func check_smccc_arch_wa3_applies + mrs x0, tpidr_el3 +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_DATA_CPU_OPS_PTR] +#if ENABLE_ASSERTIONS + cmp x0, #0 + ASM_ASSERT(ne) +#endif + ldr x0, [x0, #CPU_EXTRA3_FUNC] + /* + * If the reserved function pointer is NULL, this CPU + * is unaffected by CVE-2022-23960 so bail out. + */ + cmp x0, #CPU_NO_EXTRA3_FUNC + beq 1f + br x0 +1: + mov x0, #ERRATA_NOT_APPLIES + ret +endfunc check_smccc_arch_wa3_applies diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c new file mode 100644 index 0000000..3a2fa81 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define CPUAMU_NR_COUNTERS 5U + +struct cpuamu_ctx { + uint64_t cnts[CPUAMU_NR_COUNTERS]; + unsigned int mask; +}; + +static struct cpuamu_ctx cpuamu_ctxs[PLATFORM_CORE_COUNT]; + +int midr_match(unsigned int cpu_midr) +{ + unsigned int midr, midr_mask; + + midr = (unsigned int)read_midr(); + midr_mask = (MIDR_IMPL_MASK << MIDR_IMPL_SHIFT) | + (MIDR_PN_MASK << MIDR_PN_SHIFT); + return ((midr & midr_mask) == (cpu_midr & midr_mask)); +} + +void cpuamu_context_save(unsigned int nr_counters) +{ + struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()]; + unsigned int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* Save counter configuration */ + ctx->mask = cpuamu_read_cpuamcntenset_el0(); + + /* Disable counters */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Save counters */ + for (i = 0; i < nr_counters; i++) + ctx->cnts[i] = cpuamu_cnt_read(i); +} + +void cpuamu_context_restore(unsigned int nr_counters) +{ + struct cpuamu_ctx *ctx = &cpuamu_ctxs[plat_my_core_pos()]; + unsigned int i; + + assert(nr_counters <= CPUAMU_NR_COUNTERS); + + /* + * Disable counters. They were enabled early in the + * CPU reset function. + */ + cpuamu_write_cpuamcntenclr_el0(ctx->mask); + isb(); + + /* Restore counters */ + for (i = 0; i < nr_counters; i++) + cpuamu_cnt_write(i, ctx->cnts[i]); + isb(); + + /* Restore counter configuration */ + cpuamu_write_cpuamcntenset_el0(ctx->mask); +} diff --git a/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S new file mode 100644 index 0000000..5a77fc7 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl cpuamu_cnt_read + .globl cpuamu_cnt_write + .globl cpuamu_read_cpuamcntenset_el0 + .globl cpuamu_read_cpuamcntenclr_el0 + .globl cpuamu_write_cpuamcntenset_el0 + .globl cpuamu_write_cpuamcntenclr_el0 + +/* + * uint64_t cpuamu_cnt_read(unsigned int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func cpuamu_cnt_read + adr x1, 1f + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read CPUAMEVCNTR0_EL0 + read CPUAMEVCNTR1_EL0 + read CPUAMEVCNTR2_EL0 + read CPUAMEVCNTR3_EL0 + read CPUAMEVCNTR4_EL0 +endfunc cpuamu_cnt_read + +/* + * void cpuamu_cnt_write(unsigned int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func cpuamu_cnt_write + adr x2, 1f + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write CPUAMEVCNTR0_EL0 + write CPUAMEVCNTR1_EL0 + write CPUAMEVCNTR2_EL0 + write CPUAMEVCNTR3_EL0 + write CPUAMEVCNTR4_EL0 +endfunc cpuamu_cnt_write + +/* + * unsigned int cpuamu_read_cpuamcntenset_el0(void); + * + * Read the `CPUAMCNTENSET_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenset_el0 + mrs x0, CPUAMCNTENSET_EL0 + ret +endfunc cpuamu_read_cpuamcntenset_el0 + +/* + * unsigned int cpuamu_read_cpuamcntenclr_el0(void); + * + * Read the `CPUAMCNTENCLR_EL0` CPU register and return + * it in `x0`. + */ +func cpuamu_read_cpuamcntenclr_el0 + mrs x0, CPUAMCNTENCLR_EL0 + ret +endfunc cpuamu_read_cpuamcntenclr_el0 + +/* + * void cpuamu_write_cpuamcntenset_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENSET_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenset_el0 + msr CPUAMCNTENSET_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenset_el0 + +/* + * void cpuamu_write_cpuamcntenclr_el0(unsigned int mask); + * + * Write `mask` to the `CPUAMCNTENCLR_EL0` CPU register. + */ +func cpuamu_write_cpuamcntenclr_el0 + msr CPUAMCNTENCLR_EL0, x0 + ret +endfunc cpuamu_write_cpuamcntenclr_el0 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/denver.S b/arm-trusted-firmware/lib/cpus/aarch64/denver.S new file mode 100644 index 0000000..3c54a6f --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/denver.S @@ -0,0 +1,386 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + + /* ------------------------------------------------- + * CVE-2017-5715 mitigation + * + * Flush the indirect branch predictor and RSB on + * entry to EL3 by issuing a newly added instruction + * for Denver CPUs. + * + * To achieve this without performing any branch + * instruction, a per-cpu vbar is installed which + * executes the workaround and then branches off to + * the corresponding vector entry in the main vector + * table. + * ------------------------------------------------- + */ +vector_base workaround_bpflush_runtime_exceptions + + .macro apply_workaround + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + + /* Disable cycle counter when event counting is prohibited */ + mrs x1, pmcr_el0 + orr x0, x1, #PMCR_EL0_DP_BIT + msr pmcr_el0, x0 + isb + + /* ------------------------------------------------- + * A new write-only system register where a write of + * 1 to bit 0 will cause the indirect branch predictor + * and RSB to be flushed. + * + * A write of 0 to bit 0 will be ignored. A write of + * 1 to any other bit will cause an MCA. + * ------------------------------------------------- + */ + mov x0, #1 + msr s3_0_c15_c0_6, x0 + isb + + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + .endm + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry workaround_bpflush_sync_exception_sp_el0 + +vector_entry workaround_bpflush_irq_sp_el0 + b irq_sp_el0 +end_vector_entry workaround_bpflush_irq_sp_el0 + +vector_entry workaround_bpflush_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry workaround_bpflush_fiq_sp_el0 + +vector_entry workaround_bpflush_serror_sp_el0 + b serror_sp_el0 +end_vector_entry workaround_bpflush_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry workaround_bpflush_sync_exception_sp_elx + +vector_entry workaround_bpflush_irq_sp_elx + b irq_sp_elx +end_vector_entry workaround_bpflush_irq_sp_elx + +vector_entry workaround_bpflush_fiq_sp_elx + b fiq_sp_elx +end_vector_entry workaround_bpflush_fiq_sp_elx + +vector_entry workaround_bpflush_serror_sp_elx + b serror_sp_elx +end_vector_entry workaround_bpflush_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_aarch64 + apply_workaround + b sync_exception_aarch64 +end_vector_entry workaround_bpflush_sync_exception_aarch64 + +vector_entry workaround_bpflush_irq_aarch64 + apply_workaround + b irq_aarch64 +end_vector_entry workaround_bpflush_irq_aarch64 + +vector_entry workaround_bpflush_fiq_aarch64 + apply_workaround + b fiq_aarch64 +end_vector_entry workaround_bpflush_fiq_aarch64 + +vector_entry workaround_bpflush_serror_aarch64 + apply_workaround + b serror_aarch64 +end_vector_entry workaround_bpflush_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry workaround_bpflush_sync_exception_aarch32 + apply_workaround + b sync_exception_aarch32 +end_vector_entry workaround_bpflush_sync_exception_aarch32 + +vector_entry workaround_bpflush_irq_aarch32 + apply_workaround + b irq_aarch32 +end_vector_entry workaround_bpflush_irq_aarch32 + +vector_entry workaround_bpflush_fiq_aarch32 + apply_workaround + b fiq_aarch32 +end_vector_entry workaround_bpflush_fiq_aarch32 + +vector_entry workaround_bpflush_serror_aarch32 + apply_workaround + b serror_aarch32 +end_vector_entry workaround_bpflush_serror_aarch32 + + .global denver_disable_dco + + /* --------------------------------------------- + * Disable debug interfaces + * --------------------------------------------- + */ +func denver_disable_ext_debug + mov x0, #1 + msr osdlr_el1, x0 + isb + dsb sy + ret +endfunc denver_disable_ext_debug + + /* ---------------------------------------------------- + * Enable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ +func denver_enable_dco + /* DCO is not supported on PN5 and later */ + mrs x1, midr_el1 + mov_imm x2, DENVER_MIDR_PN4 + cmp x1, x2 + b.hi 1f + + mov x18, x30 + bl plat_my_core_pos + mov x1, #1 + lsl x1, x1, x0 + msr s3_0_c15_c0_2, x1 + mov x30, x18 +1: ret +endfunc denver_enable_dco + + /* ---------------------------------------------------- + * Disable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ +func denver_disable_dco + /* DCO is not supported on PN5 and later */ + mrs x1, midr_el1 + mov_imm x2, DENVER_MIDR_PN4 + cmp x1, x2 + b.hi 2f + + /* turn off background work */ + mov x18, x30 + bl plat_my_core_pos + mov x1, #1 + lsl x1, x1, x0 + lsl x2, x1, #16 + msr s3_0_c15_c0_2, x2 + isb + + /* wait till the background work turns off */ +1: mrs x2, s3_0_c15_c0_2 + lsr x2, x2, #32 + and w2, w2, 0xFFFF + and x2, x2, x1 + cbnz x2, 1b + + mov x30, x18 +2: ret +endfunc denver_disable_dco + +func check_errata_cve_2017_5715 + mov x0, #ERRATA_MISSING +#if WORKAROUND_CVE_2017_5715 + /* + * Check if the CPU supports the special instruction + * required to flush the indirect branch predictor and + * RSB. Support for this operation can be determined by + * comparing bits 19:16 of ID_AFR0_EL1 with 0b0001. + */ + mrs x1, id_afr0_el1 + mov x2, #0x10000 + and x1, x1, x2 + cbz x1, 1f + mov x0, #ERRATA_APPLIES +1: +#endif + ret +endfunc check_errata_cve_2017_5715 + +func check_errata_cve_2018_3639 +#if WORKAROUND_CVE_2018_3639 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2018_3639 + + /* ------------------------------------------------- + * The CPU Ops reset function for Denver. + * ------------------------------------------------- + */ +func denver_reset_func + + mov x19, x30 + +#if IMAGE_BL31 && WORKAROUND_CVE_2017_5715 + /* + * Check if the CPU supports the special instruction + * required to flush the indirect branch predictor and + * RSB. Support for this operation can be determined by + * comparing bits 19:16 of ID_AFR0_EL1 with 0b0001. + */ + mrs x0, id_afr0_el1 + mov x1, #0x10000 + and x0, x0, x1 + cmp x0, #0 + adr x1, workaround_bpflush_runtime_exceptions + mrs x2, vbar_el3 + csel x0, x1, x2, ne + msr vbar_el3, x0 +#endif + +#if WORKAROUND_CVE_2018_3639 + /* + * Denver CPUs with DENVER_MIDR_PN3 or earlier, use different + * bits in the ACTLR_EL3 register to disable speculative + * store buffer and memory disambiguation. + */ + mrs x0, midr_el1 + mov_imm x1, DENVER_MIDR_PN4 + cmp x0, x1 + mrs x0, actlr_el3 + mov x1, #(DENVER_CPU_DIS_MD_EL3 | DENVER_CPU_DIS_SSB_EL3) + mov x2, #(DENVER_PN4_CPU_DIS_MD_EL3 | DENVER_PN4_CPU_DIS_SSB_EL3) + csel x3, x1, x2, ne + orr x0, x0, x3 + msr actlr_el3, x0 + isb + dsb sy +#endif + + /* ---------------------------------------------------- + * Reset ACTLR.PMSTATE to C1 state + * ---------------------------------------------------- + */ + mrs x0, actlr_el1 + bic x0, x0, #DENVER_CPU_PMSTATE_MASK + orr x0, x0, #DENVER_CPU_PMSTATE_C1 + msr actlr_el1, x0 + + /* ---------------------------------------------------- + * Enable dynamic code optimizer (DCO) + * ---------------------------------------------------- + */ + bl denver_enable_dco + + ret x19 +endfunc denver_reset_func + + /* ---------------------------------------------------- + * The CPU Ops core power down function for Denver. + * ---------------------------------------------------- + */ +func denver_core_pwr_dwn + + mov x19, x30 + + /* --------------------------------------------- + * Force the debug interfaces to be quiescent + * --------------------------------------------- + */ + bl denver_disable_ext_debug + + ret x19 +endfunc denver_core_pwr_dwn + + /* ------------------------------------------------------- + * The CPU Ops cluster power down function for Denver. + * ------------------------------------------------------- + */ +func denver_cluster_pwr_dwn + ret +endfunc denver_cluster_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Denver. Must follow AAPCS. + */ +func denver_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata WORKAROUND_CVE_2017_5715, denver, cve_2017_5715 + report_errata WORKAROUND_CVE_2018_3639, denver, cve_2018_3639 + + ldp x8, x30, [sp], #16 + ret +endfunc denver_errata_report +#endif + + /* --------------------------------------------- + * This function provides Denver 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.denver_regs, "aS" +denver_regs: /* The ascii list of register names to be reported */ + .asciz "actlr_el1", "" + +func denver_cpu_reg_dump + adr x6, denver_regs + mrs x8, ACTLR_EL1 + ret +endfunc denver_cpu_reg_dump + +/* macro to declare cpu_ops for Denver SKUs */ +.macro denver_cpu_ops_wa midr + declare_cpu_ops_wa denver, \midr, \ + denver_reset_func, \ + check_errata_cve_2017_5715, \ + CPU_NO_EXTRA2_FUNC, \ + CPU_NO_EXTRA3_FUNC, \ + denver_core_pwr_dwn, \ + denver_cluster_pwr_dwn +.endm + +denver_cpu_ops_wa DENVER_MIDR_PN0 +denver_cpu_ops_wa DENVER_MIDR_PN1 +denver_cpu_ops_wa DENVER_MIDR_PN2 +denver_cpu_ops_wa DENVER_MIDR_PN3 +denver_cpu_ops_wa DENVER_MIDR_PN4 +denver_cpu_ops_wa DENVER_MIDR_PN5 +denver_cpu_ops_wa DENVER_MIDR_PN6 +denver_cpu_ops_wa DENVER_MIDR_PN7 +denver_cpu_ops_wa DENVER_MIDR_PN8 +denver_cpu_ops_wa DENVER_MIDR_PN9 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S b/arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S new file mode 100644 index 0000000..da052d5 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + /* ----------------------------------------------------------------------- + * DSU erratum 798953 check function + * Checks the DSU variant, revision and configuration to determine if + * the erratum applies. Erratum applies on all configurations of the + * DSU and if revision-variant is r0p0. + * + * The erratum was fixed in r0p1. + * + * This function is called from both assembly and C environment. So it + * follows AAPCS. + * + * Clobbers: x0-x3 + * ----------------------------------------------------------------------- + */ + .globl check_errata_dsu_798953 + .globl errata_dsu_798953_wa + +func check_errata_dsu_798953 + mov x2, #ERRATA_APPLIES + mov x3, #ERRATA_NOT_APPLIES + + /* Check if DSU is equal to r0p0 */ + mrs x1, CLUSTERIDR_EL1 + + /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */ + ubfx x0, x1, #CLUSTERIDR_REV_SHIFT,\ + #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS) + mov x1, #(0x0 << CLUSTERIDR_REV_SHIFT) + cmp x0, x1 + csel x0, x2, x3, EQ + ret +endfunc check_errata_dsu_798953 + + /* -------------------------------------------------- + * Errata Workaround for DSU erratum #798953. + * + * Can clobber only: x0-x17 + * -------------------------------------------------- + */ +func errata_dsu_798953_wa + mov x17, x30 + bl check_errata_dsu_798953 + cbz x0, 1f + + /* If erratum applies, disable high-level clock gating */ + mrs x0, CLUSTERACTLR_EL1 + orr x0, x0, #CLUSTERACTLR_EL1_DISABLE_CLOCK_GATING + msr CLUSTERACTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_dsu_798953_wa + + /* ----------------------------------------------------------------------- + * DSU erratum 936184 check function + * Checks the DSU variant, revision and configuration to determine if + * the erratum applies. Erratum applies if ACP interface is present + * in the DSU and revision-variant < r2p0. + * + * The erratum was fixed in r2p0. + * + * This function is called from both assembly and C environment. So it + * follows AAPCS. + * + * Clobbers: x0-x15 + * ----------------------------------------------------------------------- + */ + .globl check_errata_dsu_936184 + .globl errata_dsu_936184_wa + .weak is_scu_present_in_dsu + + /* -------------------------------------------------------------------- + * Default behaviour respresents SCU is always present with DSU. + * CPUs can override this definition if required. + * + * Can clobber only: x0-x14 + * -------------------------------------------------------------------- + */ +func is_scu_present_in_dsu + mov x0, #1 + ret +endfunc is_scu_present_in_dsu + +func check_errata_dsu_936184 + mov x15, x30 + bl is_scu_present_in_dsu + cmp x0, xzr + /* Default error status */ + mov x0, #ERRATA_NOT_APPLIES + + /* If SCU is not present, return without applying patch */ + b.eq 1f + + /* Erratum applies only if DSU has the ACP interface */ + mrs x1, CLUSTERCFR_EL1 + ubfx x1, x1, #CLUSTERCFR_ACP_SHIFT, #1 + cbz x1, 1f + + /* If ACP is present, check if DSU is older than r2p0 */ + mrs x1, CLUSTERIDR_EL1 + + /* DSU variant and revision bitfields in CLUSTERIDR are adjacent */ + ubfx x2, x1, #CLUSTERIDR_REV_SHIFT,\ + #(CLUSTERIDR_REV_BITS + CLUSTERIDR_VAR_BITS) + cmp x2, #(0x2 << CLUSTERIDR_VAR_SHIFT) + b.hs 1f + mov x0, #ERRATA_APPLIES +1: + ret x15 +endfunc check_errata_dsu_936184 + + /* -------------------------------------------------- + * Errata Workaround for DSU erratum #936184. + * + * Can clobber only: x0-x17 + * -------------------------------------------------- + */ +func errata_dsu_936184_wa + mov x17, x30 + bl check_errata_dsu_936184 + cbz x0, 1f + + /* If erratum applies, we set a mask to a DSU control register */ + mrs x0, CLUSTERACTLR_EL1 + ldr x1, =DSU_ERRATA_936184_MASK + orr x0, x0, x1 + msr CLUSTERACTLR_EL1, x0 + isb +1: + ret x17 +endfunc errata_dsu_936184_wa diff --git a/arm-trusted-firmware/lib/cpus/aarch64/generic.S b/arm-trusted-firmware/lib/cpus/aarch64/generic.S new file mode 100644 index 0000000..ef1f048 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/generic.S @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + /* --------------------------------------------- + * Disable L1 data cache and unified L2 cache + * --------------------------------------------- + */ +func generic_disable_dcache + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + ret +endfunc generic_disable_dcache + +func generic_core_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl generic_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + ret x18 +endfunc generic_core_pwr_dwn + +func generic_cluster_pwr_dwn + mov x18, x30 + + /* --------------------------------------------- + * Turn off caches. + * --------------------------------------------- + */ + bl generic_disable_dcache + + /* --------------------------------------------- + * Flush L1 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level1 + + /* --------------------------------------------- + * Disable the optional ACP. + * --------------------------------------------- + */ + bl plat_disable_acp + + /* --------------------------------------------- + * Flush L2 caches. + * --------------------------------------------- + */ + mov x0, #DCCISW + bl dcsw_op_level2 + + ret x18 + +endfunc generic_cluster_pwr_dwn + +/* --------------------------------------------- + * Unimplemented functions. + * --------------------------------------------- + */ +.equ generic_errata_report, 0 +.equ generic_cpu_reg_dump, 0 +.equ generic_reset_func, 0 + +declare_cpu_ops generic, AARCH64_GENERIC_MIDR, \ + generic_reset_func, \ + generic_core_pwr_dwn, \ + generic_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S new file mode 100644 index 0000000..f43c18b --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse Demeter must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse Demeter supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ---------------------------------------------------- + * HW will do the cache maintenance while powering down + * ---------------------------------------------------- + */ +func neoverse_demeter_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------------- + */ + mrs x0, NEOVERSE_DEMETER_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_DEMETER_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_DEMETER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_demeter_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse Demeter. Must follow AAPCS. + */ +func neoverse_demeter_errata_report + ret +endfunc neoverse_demeter_errata_report +#endif + +func neoverse_demeter_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc neoverse_demeter_reset_func + + /* --------------------------------------------- + * This function provides Neoverse Demeter- + * 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.neoverse_demeter_regs, "aS" +neoverse_demeter_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_demeter_cpu_reg_dump + adr x6, neoverse_demeter_regs + mrs x8, NEOVERSE_DEMETER_CPUECTLR_EL1 + ret +endfunc neoverse_demeter_cpu_reg_dump + +declare_cpu_ops neoverse_demeter, NEOVERSE_DEMETER_MIDR, \ + neoverse_demeter_reset_func, \ + neoverse_demeter_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S new file mode 100644 index 0000000..96b63cf --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse E1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-E1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* ------------------------------------------------- + * The CPU Ops reset function for Neoverse-E1. + * Shall clobber: x0-x19 + * ------------------------------------------------- + */ +func neoverse_e1_reset_func + mov x19, x30 + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + + ret x19 +endfunc neoverse_e1_reset_func + +func neoverse_e1_cpu_pwr_dwn + mrs x0, NEOVERSE_E1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_E1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_E1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_e1_cpu_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N1. Must follow AAPCS. + */ +func neoverse_e1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_DSU_936184, neoverse_e1, dsu_936184 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_e1_errata_report +#endif + + +.section .rodata.neoverse_e1_regs, "aS" +neoverse_e1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_e1_cpu_reg_dump + adr x6, neoverse_e1_regs + mrs x8, NEOVERSE_E1_ECTLR_EL1 + ret +endfunc neoverse_e1_cpu_reg_dump + +declare_cpu_ops neoverse_e1, NEOVERSE_E1_MIDR, \ + neoverse_e1_reset_func, \ + neoverse_e1_cpu_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S new file mode 100644 index 0000000..b75b0c1 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S @@ -0,0 +1,714 @@ +/* + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse N1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-N1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + .global neoverse_n1_errata_ic_trap_handler + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_N1_BHB_LOOP_COUNT, neoverse_n1 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1043202. + * This applies to revision r0p0 and r1p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1043202_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1043202 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x0 + msr CPUPSELR_EL3, x0 + ldr x0, =0xF3BF8F2F + msr CPUPOR_EL3, x0 + ldr x0, =0xFFFFFFFF + msr CPUPMR_EL3, x0 + ldr x0, =0x800200071 + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_n1_1043202_wa + +func check_errata_1043202 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1043202 + +/* -------------------------------------------------- + * Disable speculative loads if Neoverse N1 supports + * SSBS. + * + * Shall clobber: x0. + * -------------------------------------------------- + */ +func neoverse_n1_disable_speculative_loads + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr + +1: + ret +endfunc neoverse_n1_disable_speculative_loads + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1073348 + * This applies to revision r0p0 and r1p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1073348_wa + /* Compare x0 against revision r1p0 */ + mov x17, x30 + bl check_errata_1073348 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_6 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1073348_wa + +func check_errata_1073348 + /* Applies to r0p0 and r1p0 */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1073348 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1130799 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1130799_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1130799 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_59 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1130799_wa + +func check_errata_1130799 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1130799 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1165347 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1165347_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1165347 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_0 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_15 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1165347_wa + +func check_errata_1165347 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1165347 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1207823 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1207823_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1207823 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR2_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR2_EL1_BIT_11 + msr NEOVERSE_N1_CPUACTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n1_1207823_wa + +func check_errata_1207823 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1207823 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1220197 + * This applies to revision <=r2p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1220197_wa + /* Compare x0 against revision r2p0 */ + mov x17, x30 + bl check_errata_1220197 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N1_WS_THR_L2_MASK + msr NEOVERSE_N1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1220197_wa + +func check_errata_1220197 + /* Applies to <=r2p0 */ + mov x1, #0x20 + b cpu_rev_var_ls +endfunc check_errata_1220197 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1257314 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1257314_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1257314 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR3_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR3_EL1_BIT_10 + msr NEOVERSE_N1_CPUACTLR3_EL1, x1 +1: + ret x17 +endfunc errata_n1_1257314_wa + +func check_errata_1257314 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1257314 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1262606 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1262606_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1262606 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1262606_wa + +func check_errata_1262606 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262606 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1262888 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1262888_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1262888 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUECTLR_EL1_MM_TLBPF_DIS_BIT + msr NEOVERSE_N1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1262888_wa + +func check_errata_1262888 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1262888 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1275112 + * This applies to revision <=r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1275112_wa + /* Compare x0 against revision r3p0 */ + mov x17, x30 + bl check_errata_1275112 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n1_1275112_wa + +func check_errata_1275112 + /* Applies to <=r3p0 */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1275112 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1315703. + * This applies to revision <= r3p0 of Neoverse N1. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1315703_wa + /* Compare x0 against revision r3p1 */ + mov x17, x30 + bl check_errata_1315703 + cbz x0, 1f + + mrs x0, NEOVERSE_N1_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N1_CPUACTLR2_EL1_BIT_16 + msr NEOVERSE_N1_CPUACTLR2_EL1, x0 + +1: + ret x17 +endfunc errata_n1_1315703_wa + +func check_errata_1315703 + /* Applies to everything <= r3p0. */ + mov x1, #0x30 + b cpu_rev_var_ls +endfunc check_errata_1315703 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Erratum 1542419. + * This applies to revisions r3p0 - r4p0 of Neoverse N1 + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1542419_wa + /* Compare x0 against revision r3p0 and r4p0 */ + mov x17, x30 + bl check_errata_1542419 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0, =0x0 + msr CPUPSELR_EL3, x0 + ldr x0, =0xEE670D35 + msr CPUPOR_EL3, x0 + ldr x0, =0xFFFF0FFF + msr CPUPMR_EL3, x0 + ldr x0, =0x08000020007D + msr CPUPCR_EL3, x0 + isb +1: + ret x17 +endfunc errata_n1_1542419_wa + +func check_errata_1542419 + /* Applies to everything r3p0 - r4p0. */ + mov x1, #0x30 + mov x2, #0x40 + b cpu_rev_var_range +endfunc check_errata_1542419 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1868343. + * This applies to revision <= r4p0 of Neoverse N1. + * This workaround is the same as the workaround for + * errata 1262606 and 1275112 but applies to a wider + * revision range. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1868343_wa + /* + * Compare x0 against revision r4p0 + */ + mov x17, x30 + bl check_errata_1868343 + cbz x0, 1f + mrs x1, NEOVERSE_N1_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N1_CPUACTLR_EL1_BIT_13 + msr NEOVERSE_N1_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_n1_1868343_wa + +func check_errata_1868343 + /* Applies to everything <= r4p0 */ + mov x1, #0x40 + b cpu_rev_var_ls +endfunc check_errata_1868343 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1946160. + * This applies to revisions r3p0, r3p1, r4p0, and + * r4p1 of Neoverse N1. It also exists in r0p0, r1p0, + * and r2p0 but there is no fix in these revisions. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n1_1946160_wa + /* + * Compare x0 against r3p0 - r4p1 + */ + mov x17, x30 + bl check_errata_1946160 + cbz x0, 1f + + mov x0, #3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #4 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #5 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_n1_1946160_wa + +func check_errata_1946160 + /* Applies to r3p0 - r4p1. */ + mov x1, #0x30 + mov x2, #0x41 + b cpu_rev_var_range +endfunc check_errata_1946160 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + +func neoverse_n1_reset_func + mov x19, x30 + + bl neoverse_n1_disable_speculative_loads + + /* Forces all cacheable atomic instructions to be near */ + mrs x0, NEOVERSE_N1_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N1_CPUACTLR2_EL1_BIT_2 + msr NEOVERSE_N1_CPUACTLR2_EL1, x0 + isb + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N1_1043202 + mov x0, x18 + bl errata_n1_1043202_wa +#endif + +#if ERRATA_N1_1073348 + mov x0, x18 + bl errata_n1_1073348_wa +#endif + +#if ERRATA_N1_1130799 + mov x0, x18 + bl errata_n1_1130799_wa +#endif + +#if ERRATA_N1_1165347 + mov x0, x18 + bl errata_n1_1165347_wa +#endif + +#if ERRATA_N1_1207823 + mov x0, x18 + bl errata_n1_1207823_wa +#endif + +#if ERRATA_N1_1220197 + mov x0, x18 + bl errata_n1_1220197_wa +#endif + +#if ERRATA_N1_1257314 + mov x0, x18 + bl errata_n1_1257314_wa +#endif + +#if ERRATA_N1_1262606 + mov x0, x18 + bl errata_n1_1262606_wa +#endif + +#if ERRATA_N1_1262888 + mov x0, x18 + bl errata_n1_1262888_wa +#endif + +#if ERRATA_N1_1275112 + mov x0, x18 + bl errata_n1_1275112_wa +#endif + +#if ERRATA_N1_1315703 + mov x0, x18 + bl errata_n1_1315703_wa +#endif + +#if ERRATA_N1_1542419 + mov x0, x18 + bl errata_n1_1542419_wa +#endif + +#if ERRATA_N1_1868343 + mov x0, x18 + bl errata_n1_1868343_wa +#endif + +#if ERRATA_N1_1946160 + mov x0, x18 + bl errata_n1_1946160_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #NEOVERSE_N1_ACTLR_AMEN_BIT + msr actlr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #NEOVERSE_N1_ACTLR_AMEN_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #NEOVERSE_N1_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 +#endif + +#if NEOVERSE_Nx_EXTERNAL_LLC + /* Some system may have External LLC, core needs to be made aware */ + mrs x0, NEOVERSE_N1_CPUECTLR_EL1 + orr x0, x0, NEOVERSE_N1_CPUECTLR_EL1_EXTLLC_BIT + msr NEOVERSE_N1_CPUECTLR_EL1, x0 +#endif + +#if ERRATA_DSU_936184 + bl errata_dsu_936184_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-N1 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_n1 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_n1_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_n1_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_N1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_N1_CORE_PWRDN_EN_MASK + msr NEOVERSE_N1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_n1_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N1. Must follow AAPCS. + */ +func neoverse_n1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N1_1043202, neoverse_n1, 1043202 + report_errata ERRATA_N1_1073348, neoverse_n1, 1073348 + report_errata ERRATA_N1_1130799, neoverse_n1, 1130799 + report_errata ERRATA_N1_1165347, neoverse_n1, 1165347 + report_errata ERRATA_N1_1207823, neoverse_n1, 1207823 + report_errata ERRATA_N1_1220197, neoverse_n1, 1220197 + report_errata ERRATA_N1_1257314, neoverse_n1, 1257314 + report_errata ERRATA_N1_1262606, neoverse_n1, 1262606 + report_errata ERRATA_N1_1262888, neoverse_n1, 1262888 + report_errata ERRATA_N1_1275112, neoverse_n1, 1275112 + report_errata ERRATA_N1_1315703, neoverse_n1, 1315703 + report_errata ERRATA_N1_1542419, neoverse_n1, 1542419 + report_errata ERRATA_N1_1868343, neoverse_n1, 1868343 + report_errata ERRATA_N1_1946160, neoverse_n1, 1946160 + report_errata ERRATA_DSU_936184, neoverse_n1, dsu_936184 + report_errata WORKAROUND_CVE_2022_23960, neoverse_n1, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_n1_errata_report +#endif + +/* + * Handle trap of EL0 IC IVAU instructions to EL3 by executing a TLB + * inner-shareable invalidation to an arbitrary address followed by a DSB. + * + * x1: Exception Syndrome + */ +func neoverse_n1_errata_ic_trap_handler + cmp x1, #NEOVERSE_N1_EC_IC_TRAP + b.ne 1f + tlbi vae3is, xzr + dsb sy + + # Skip the IC instruction itself + mrs x3, elr_el3 + add x3, x3, #4 + msr elr_el3, x3 + + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +#if IMAGE_BL31 && RAS_EXTENSION + /* + * Issue Error Synchronization Barrier to synchronize SErrors before + * exiting EL3. We're running with EAs unmasked, so any synchronized + * errors would be taken immediately; therefore no need to inspect + * DISR_EL1 register. + */ + esb +#endif + exception_return +1: + ret +endfunc neoverse_n1_errata_ic_trap_handler + + /* --------------------------------------------- + * This function provides neoverse_n1 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.neoverse_n1_regs, "aS" +neoverse_n1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_n1_cpu_reg_dump + adr x6, neoverse_n1_regs + mrs x8, NEOVERSE_N1_CPUECTLR_EL1 + ret +endfunc neoverse_n1_cpu_reg_dump + +declare_cpu_ops_eh neoverse_n1, NEOVERSE_N1_MIDR, \ + neoverse_n1_reset_func, \ + neoverse_n1_errata_ic_trap_handler, \ + neoverse_n1_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c new file mode 100644 index 0000000..b1b7bb8 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static void *neoverse_n1_context_save(const void *arg) +{ + if (midr_match(NEOVERSE_N1_MIDR) != 0) + cpuamu_context_save(NEOVERSE_N1_AMU_NR_COUNTERS); + + return (void *)0; +} + +static void *neoverse_n1_context_restore(const void *arg) +{ + if (midr_match(NEOVERSE_N1_MIDR) != 0) + cpuamu_context_restore(NEOVERSE_N1_AMU_NR_COUNTERS); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, neoverse_n1_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, neoverse_n1_context_restore); diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S new file mode 100644 index 0000000..b93f2a6 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S @@ -0,0 +1,523 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse N2 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-N2 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_N2_BHB_LOOP_COUNT, neoverse_n2 +#endif /* WORKAROUND_CVE_2022_23960 */ + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2002655. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n2_2002655_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2002655 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x6 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003ff + msr S3_6_c15_c8_1,x0 + ldr x0,=0x7 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x40000001003f3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_n2_2002655_wa + +func check_errata_2002655 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2002655 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2067956. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2067956_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2067956 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_46 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2067956_wa + +func check_errata_2067956 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2067956 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2025414. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2025414_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2025414 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUECTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUECTLR_EL1_PFSTIDIS_BIT + msr NEOVERSE_N2_CPUECTLR_EL1, x1 + +1: + ret x17 +endfunc errata_n2_2025414_wa + +func check_errata_2025414 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2025414 + +/* --------------------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2189731. + * This applies to revision r0p0 of Neoverse N2 and is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * --------------------------------------------------------------- + */ +func errata_n2_2189731_wa + /* Compare x0 against revision r0p0 */ + mov x17, x30 + bl check_errata_2189731 + cbz x0, 1f + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_44 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 + +1: + ret x17 +endfunc errata_n2_2189731_wa + +func check_errata_2189731 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2189731 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138956. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_n2_2138956_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138956 + cbz x0, 1f + + /* Apply instruction patching sequence */ + ldr x0,=0x3 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xF3A08002 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFF0F7FE + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003FF + msr S3_6_c15_c8_1,x0 + ldr x0,=0x4 + msr S3_6_c15_c8_0,x0 + ldr x0,=0xBF200000 + msr S3_6_c15_c8_2,x0 + ldr x0,=0xFFEF0000 + msr S3_6_c15_c8_3,x0 + ldr x0,=0x10002001003F3 + msr S3_6_c15_c8_1,x0 + isb +1: + ret x17 +endfunc errata_n2_2138956_wa + +func check_errata_2138956 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138956 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2242415. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2242415_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2242415 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_22 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2242415_wa + +func check_errata_2242415 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2242415 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138953. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2138953_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138953 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUECTLR2_EL1 + mov x0, #NEOVERSE_N2_CPUECTLR2_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR2_EL1_PF_MODE_LSB, #CPUECTLR2_EL1_PF_MODE_WIDTH + msr NEOVERSE_N2_CPUECTLR2_EL1, x1 +1: + ret x17 +endfunc errata_n2_2138953_wa + +func check_errata_2138953 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138953 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2138958. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2138958_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2138958 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_13 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 +1: + ret x17 +endfunc errata_n2_2138958_wa + +func check_errata_2138958 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2138958 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2242400. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2242400_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2242400 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR5_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR5_EL1_BIT_17 + msr NEOVERSE_N2_CPUACTLR5_EL1, x1 + ldr x0, =0x2 + msr S3_6_c15_c8_0, x0 + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 + isb +1: + ret x17 +endfunc errata_n2_2242400_wa + +func check_errata_2242400 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2242400 + +/* -------------------------------------------------- + * Errata Workaround for Neoverse N2 Erratum 2280757. + * This applies to revision r0p0 of Neoverse N2. it is still open. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_n2_2280757_wa + /* Check revision. */ + mov x17, x30 + bl check_errata_2280757 + cbz x0, 1f + + /* Apply instruction patching sequence */ + mrs x1, NEOVERSE_N2_CPUACTLR_EL1 + orr x1, x1, NEOVERSE_N2_CPUACTLR_EL1_BIT_22 + msr NEOVERSE_N2_CPUACTLR_EL1, x1 +1: + ret x17 +endfunc errata_n2_2280757_wa + +func check_errata_2280757 + /* Applies to r0p0 */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_2280757 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* ------------------------------------------- + * The CPU Ops reset function for Neoverse N2. + * ------------------------------------------- + */ +func neoverse_n2_reset_func + mov x19, x30 + + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr +1: + /* Force all cacheable atomic instructions to be near */ + mrs x0, NEOVERSE_N2_CPUACTLR2_EL1 + orr x0, x0, #NEOVERSE_N2_CPUACTLR2_EL1_BIT_2 + msr NEOVERSE_N2_CPUACTLR2_EL1, x0 + +#if ERRATA_N2_2067956 + mov x0, x18 + bl errata_n2_2067956_wa +#endif + +#if ERRATA_N2_2025414 + mov x0, x18 + bl errata_n2_2025414_wa +#endif + +#if ERRATA_N2_2189731 + mov x0, x18 + bl errata_n2_2189731_wa +#endif + + +#if ERRATA_N2_2138956 + mov x0, x18 + bl errata_n2_2138956_wa +#endif + +#if ERRATA_N2_2138953 + mov x0, x18 + bl errata_n2_2138953_wa +#endif + +#if ERRATA_N2_2242415 + mov x0, x18 + bl errata_n2_2242415_wa +#endif + +#if ERRATA_N2_2138958 + mov x0, x18 + bl errata_n2_2138958_wa +#endif + +#if ERRATA_N2_2242400 + mov x0, x18 + bl errata_n2_2242400_wa +#endif + +#if ERRATA_N2_2280757 + mov x0, x18 + bl errata_n2_2280757_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, cptr_el3 + orr x0, x0, #TAM_BIT + msr cptr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, cptr_el2 + orr x0, x0, #TAM_BIT + msr cptr_el2, x0 + + /* No need to enable the counters as this would be done at el3 exit */ +#endif + +#if NEOVERSE_Nx_EXTERNAL_LLC + /* Some systems may have External LLC, core needs to be made aware */ + mrs x0, NEOVERSE_N2_CPUECTLR_EL1 + orr x0, x0, NEOVERSE_N2_CPUECTLR_EL1_EXTLLC_BIT + msr NEOVERSE_N2_CPUECTLR_EL1, x0 +#endif + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N2_2002655 + mov x0, x18 + bl errata_n2_2002655_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-N2 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_n2 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_n2_reset_func + +func neoverse_n2_core_pwr_dwn + /* --------------------------------------------------- + * Enable CPU power down bit in power control register + * No need to do cache maintenance here. + * --------------------------------------------------- + */ + mrs x0, NEOVERSE_N2_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_N2_CORE_PWRDN_EN_BIT + msr NEOVERSE_N2_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_n2_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Neoverse N2 cores. Must follow AAPCS. + */ +func neoverse_n2_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N2_2002655, neoverse_n2, 2002655 + report_errata ERRATA_N2_2067956, neoverse_n2, 2067956 + report_errata ERRATA_N2_2025414, neoverse_n2, 2025414 + report_errata ERRATA_N2_2189731, neoverse_n2, 2189731 + report_errata ERRATA_N2_2138956, neoverse_n2, 2138956 + report_errata ERRATA_N2_2138953, neoverse_n2, 2138953 + report_errata ERRATA_N2_2242415, neoverse_n2, 2242415 + report_errata ERRATA_N2_2138958, neoverse_n2, 2138958 + report_errata ERRATA_N2_2242400, neoverse_n2, 2242400 + report_errata ERRATA_N2_2280757, neoverse_n2, 2280757 + report_errata WORKAROUND_CVE_2022_23960, neoverse_n2, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_n2_errata_report +#endif + + /* --------------------------------------------- + * This function provides Neoverse N2 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.neoverse_n2_regs, "aS" +neoverse_n2_regs: /* The ASCII list of register names to be reported */ + .asciz "cpupwrctlr_el1", "" + +func neoverse_n2_cpu_reg_dump + adr x6, neoverse_n2_regs + mrs x8, NEOVERSE_N2_CPUPWRCTLR_EL1 + ret +endfunc neoverse_n2_cpu_reg_dump + +declare_cpu_ops neoverse_n2, NEOVERSE_N2_MIDR, \ + neoverse_n2_reset_func, \ + neoverse_n2_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S new file mode 100644 index 0000000..b816342 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global is_scu_present_in_dsu + +/* + * Check if the SCU L3 Unit is present on the DSU + * 1-> SCU present + * 0-> SCU not present + * + * This function is implemented as weak on dsu_helpers.S and must be + * overwritten for Neoverse Nx cores. + */ + +func is_scu_present_in_dsu + mrs x0, CPUCFR_EL1 + ubfx x0, x0, #SCU_SHIFT, #1 + eor x0, x0, #1 + ret +endfunc is_scu_present_in_dsu diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S new file mode 100644 index 0000000..43a93aa --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse Poseidon must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse Poseidon supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_poseidon_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_POSEIDON_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_POSEIDON_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_POSEIDON_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_poseidon_core_pwr_dwn + +#if REPORT_ERRATA + /* + * Errata printing function for Neoverse Poseidon. Must follow AAPCS. + */ +func neoverse_poseidon_errata_report + ret +endfunc neoverse_poseidon_errata_report +#endif + +func neoverse_poseidon_reset_func + /* Disable speculative loads */ + msr SSBS, xzr + isb + ret +endfunc neoverse_poseidon_reset_func + + /* --------------------------------------------- + * This function provides Neoverse-Poseidon 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.neoverse_poseidon_regs, "aS" +neoverse_poseidon_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_poseidon_cpu_reg_dump + adr x6, neoverse_poseidon_regs + mrs x8, NEOVERSE_POSEIDON_CPUECTLR_EL1 + ret +endfunc neoverse_poseidon_cpu_reg_dump + +declare_cpu_ops neoverse_poseidon, NEOVERSE_POSEIDON_MIDR, \ + neoverse_poseidon_reset_func, \ + neoverse_poseidon_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S new file mode 100644 index 0000000..6adb3a8 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S @@ -0,0 +1,474 @@ +/* + * Copyright (c) 2019-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include "wa_cve_2022_23960_bhb_vector.S" + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Neoverse V1 must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Neoverse-V1 supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +#if WORKAROUND_CVE_2022_23960 + wa_cve_2022_23960_bhb_vector_table NEOVERSE_V1_BHB_LOOP_COUNT, neoverse_v1 +#endif /* WORKAROUND_CVE_2022_23960 */ + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1774420. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1774420_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1774420 + cbz x0, 1f + + /* Set bit 53 in CPUECTLR_EL1 */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + orr x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_53 + msr NEOVERSE_V1_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1774420_wa + +func check_errata_1774420 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1774420 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1791573. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1791573_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1791573 + cbz x0, 1f + + /* Set bit 2 in ACTLR2_EL1 */ + mrs x1, NEOVERSE_V1_ACTLR2_EL1 + orr x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_2 + msr NEOVERSE_V1_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1791573_wa + +func check_errata_1791573 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1791573 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1852267. + * This applies to revisions r0p0 and r1p0, fixed in r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1852267_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1852267 + cbz x0, 1f + + /* Set bit 28 in ACTLR2_EL1 */ + mrs x1, NEOVERSE_V1_ACTLR2_EL1 + orr x1, x1, #NEOVERSE_V1_ACTLR2_EL1_BIT_28 + msr NEOVERSE_V1_ACTLR2_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1852267_wa + +func check_errata_1852267 + /* Applies to r0p0 and r1p0. */ + mov x1, #0x10 + b cpu_rev_var_ls +endfunc check_errata_1852267 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1925756. + * This applies to revisions <= r1p1. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1925756_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1925756 + cbz x0, 1f + + /* Set bit 8 in CPUECTLR_EL1 */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + orr x1, x1, #NEOVERSE_V1_CPUECTLR_EL1_BIT_8 + msr NEOVERSE_V1_CPUECTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_neoverse_v1_1925756_wa + +func check_errata_1925756 + /* Applies to <= r1p1. */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_1925756 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Erratum #1940577 + * This applies to revisions r1p0 - r1p1 and is open. + * It also exists in r0p0 but there is no fix in that + * revision. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1940577_wa + /* Compare x0 against revisions r1p0 - r1p1 */ + mov x17, x30 + bl check_errata_1940577 + cbz x0, 1f + + mov x0, #0 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3900002 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #1 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800082 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF00083 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + mov x0, #2 + msr S3_6_C15_C8_0, x0 + ldr x0, =0x10E3800200 + msr S3_6_C15_C8_2, x0 + ldr x0, =0x10FFF003E0 + msr S3_6_C15_C8_3, x0 + ldr x0, =0x2001003FF + msr S3_6_C15_C8_1, x0 + + isb +1: + ret x17 +endfunc errata_neoverse_v1_1940577_wa + +func check_errata_1940577 + /* Applies to revisions r1p0 - r1p1. */ + mov x1, #0x10 + mov x2, #0x11 + b cpu_rev_var_range +endfunc check_errata_1940577 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #1966096 + * This applies to revisions r1p0 - r1p1 and is open. + * It also exists in r0p0 but there is no workaround + * for that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_1966096_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_1966096 + cbz x0, 1f + + /* Apply the workaround. */ + mov x0, #0x3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0xEE010F12 + msr S3_6_C15_C8_2, x0 + ldr x0, =0xFFFF0FFF + msr S3_6_C15_C8_3, x0 + ldr x0, =0x80000000003FF + msr S3_6_C15_C8_1, x0 + isb + +1: + ret x17 +endfunc errata_neoverse_v1_1966096_wa + +func check_errata_1966096 + mov x1, #0x10 + mov x2, #0x11 + b cpu_rev_var_range +endfunc check_errata_1966096 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2139242. + * This applies to revisions r0p0, r1p0, and r1p1, it + * is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2139242_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2139242 + cbz x0, 1f + + /* Apply the workaround. */ + mov x0, #0x3 + msr S3_6_C15_C8_0, x0 + ldr x0, =0xEE720F14 + msr S3_6_C15_C8_2, x0 + ldr x0, =0xFFFF0FDF + msr S3_6_C15_C8_3, x0 + ldr x0, =0x40000005003FF + msr S3_6_C15_C8_1, x0 + isb + +1: + ret x17 +endfunc errata_neoverse_v1_2139242_wa + +func check_errata_2139242 + /* Applies to r0p0, r1p0, r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_2139242 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2108267. + * This applies to revisions r0p0, r1p0, and r1p1, it + * is still open. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x1, x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2108267_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2108267 + cbz x0, 1f + + /* Apply the workaround. */ + mrs x1, NEOVERSE_V1_CPUECTLR_EL1 + mov x0, #NEOVERSE_V1_CPUECTLR_EL1_PF_MODE_CNSRV + bfi x1, x0, #CPUECTLR_EL1_PF_MODE_LSB, #CPUECTLR_EL1_PF_MODE_WIDTH + msr NEOVERSE_V1_CPUECTLR_EL1, x1 +1: + ret x17 +endfunc errata_neoverse_v1_2108267_wa + +func check_errata_2108267 + /* Applies to r0p0, r1p0, r1p1 */ + mov x1, #0x11 + b cpu_rev_var_ls +endfunc check_errata_2108267 + + /* -------------------------------------------------- + * Errata Workaround for Neoverse V1 Errata #2216392. + * This applies to revisions r1p0 and r1p1 and is + * still open. + * This issue is also present in r0p0 but there is no + * workaround in that revision. + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0-x17 + * -------------------------------------------------- + */ +func errata_neoverse_v1_2216392_wa + /* Check workaround compatibility. */ + mov x17, x30 + bl check_errata_2216392 + cbz x0, 1f + + ldr x0, =0x5 + msr S3_6_c15_c8_0, x0 /* CPUPSELR_EL3 */ + ldr x0, =0x10F600E000 + msr S3_6_c15_c8_2, x0 /* CPUPOR_EL3 */ + ldr x0, =0x10FF80E000 + msr S3_6_c15_c8_3, x0 /* CPUPMR_EL3 */ + ldr x0, =0x80000000003FF + msr S3_6_c15_c8_1, x0 /* CPUPCR_EL3 */ + + isb +1: + ret x17 +endfunc errata_neoverse_v1_2216392_wa + +func check_errata_2216392 + /* Applies to revisions r1p0 and r1p1. */ + mov x1, #CPU_REV(1, 0) + mov x2, #CPU_REV(1, 1) + b cpu_rev_var_range +endfunc check_errata_2216392 + +func check_errata_cve_2022_23960 +#if WORKAROUND_CVE_2022_23960 + mov x0, #ERRATA_APPLIES +#else + mov x0, #ERRATA_MISSING +#endif + ret +endfunc check_errata_cve_2022_23960 + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func neoverse_v1_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, NEOVERSE_V1_CPUPWRCTLR_EL1 + orr x0, x0, #NEOVERSE_V1_CPUPWRCTLR_EL1_CORE_PWRDN_BIT + msr NEOVERSE_V1_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc neoverse_v1_core_pwr_dwn + + /* + * Errata printing function for Neoverse V1. Must follow AAPCS. + */ +#if REPORT_ERRATA +func neoverse_v1_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_V1_1774420, neoverse_v1, 1774420 + report_errata ERRATA_V1_1791573, neoverse_v1, 1791573 + report_errata ERRATA_V1_1852267, neoverse_v1, 1852267 + report_errata ERRATA_V1_1925756, neoverse_v1, 1925756 + report_errata ERRATA_V1_1940577, neoverse_v1, 1940577 + report_errata ERRATA_V1_1966096, neoverse_v1, 1966096 + report_errata ERRATA_V1_2139242, neoverse_v1, 2139242 + report_errata ERRATA_V1_2108267, neoverse_v1, 2108267 + report_errata ERRATA_V1_2216392, neoverse_v1, 2216392 + report_errata WORKAROUND_CVE_2022_23960, neoverse_v1, cve_2022_23960 + + ldp x8, x30, [sp], #16 + ret +endfunc neoverse_v1_errata_report +#endif + +func neoverse_v1_reset_func + mov x19, x30 + + /* Disable speculative loads */ + msr SSBS, xzr + isb + +#if ERRATA_V1_1774420 + mov x0, x18 + bl errata_neoverse_v1_1774420_wa +#endif + +#if ERRATA_V1_1791573 + mov x0, x18 + bl errata_neoverse_v1_1791573_wa +#endif + +#if ERRATA_V1_1852267 + mov x0, x18 + bl errata_neoverse_v1_1852267_wa +#endif + +#if ERRATA_V1_1925756 + mov x0, x18 + bl errata_neoverse_v1_1925756_wa +#endif + +#if ERRATA_V1_1940577 + mov x0, x18 + bl errata_neoverse_v1_1940577_wa +#endif + +#if ERRATA_V1_1966096 + mov x0, x18 + bl errata_neoverse_v1_1966096_wa +#endif + +#if ERRATA_V1_2139242 + mov x0, x18 + bl errata_neoverse_v1_2139242_wa +#endif + +#if ERRATA_V1_2108267 + mov x0, x18 + bl errata_neoverse_v1_2108267_wa +#endif + +#if ERRATA_V1_2216392 + mov x0, x18 + bl errata_neoverse_v1_2216392_wa +#endif + +#if IMAGE_BL31 && WORKAROUND_CVE_2022_23960 + /* + * The Neoverse-V1 generic vectors are overridden to apply errata + * mitigation on exception entry from lower ELs. + */ + adr x0, wa_cve_vbar_neoverse_v1 + msr vbar_el3, x0 +#endif /* IMAGE_BL31 && WORKAROUND_CVE_2022_23960 */ + + isb + ret x19 +endfunc neoverse_v1_reset_func + + /* --------------------------------------------- + * This function provides Neoverse-V1 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.neoverse_v1_regs, "aS" +neoverse_v1_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func neoverse_v1_cpu_reg_dump + adr x6, neoverse_v1_regs + mrs x8, NEOVERSE_V1_CPUECTLR_EL1 + ret +endfunc neoverse_v1_cpu_reg_dump + +declare_cpu_ops neoverse_v1, NEOVERSE_V1_MIDR, \ + neoverse_v1_reset_func, \ + neoverse_v1_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S b/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S new file mode 100644 index 0000000..8948fda --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include + +func qemu_max_core_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush L1 cache to L2. + * --------------------------------------------- + */ + mov x18, lr + mov x0, #DCCISW + bl dcsw_op_level1 + mov lr, x18 + ret +endfunc qemu_max_core_pwr_dwn + +func qemu_max_cluster_pwr_dwn + /* --------------------------------------------- + * Disable the Data Cache. + * --------------------------------------------- + */ + mrs x1, sctlr_el3 + bic x1, x1, #SCTLR_C_BIT + msr sctlr_el3, x1 + isb + + /* --------------------------------------------- + * Flush all caches to PoC. + * --------------------------------------------- + */ + mov x0, #DCCISW + b dcsw_op_all +endfunc qemu_max_cluster_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for QEMU "max". Must follow AAPCS. + */ +func qemu_max_errata_report + ret +endfunc qemu_max_errata_report +#endif + + /* --------------------------------------------- + * This function provides cpu 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.qemu_max_regs, "aS" +qemu_max_regs: /* The ascii list of register names to be reported */ + .asciz "" /* no registers to report */ + +func qemu_max_cpu_reg_dump + adr x6, qemu_max_regs + ret +endfunc qemu_max_cpu_reg_dump + + +/* cpu_ops for QEMU MAX */ +declare_cpu_ops qemu_max, QEMU_MAX_MIDR, CPU_NO_RESET_FUNC, \ + qemu_max_core_pwr_dwn, \ + qemu_max_cluster_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/rainier.S b/arm-trusted-firmware/lib/cpus/aarch64/rainier.S new file mode 100644 index 0000000..584ab97 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/rainier.S @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* Hardware handled coherency */ +#if HW_ASSISTED_COHERENCY == 0 +#error "Rainier CPU must be compiled with HW_ASSISTED_COHERENCY enabled" +#endif + +/* 64-bit only core */ +#if CTX_INCLUDE_AARCH32_REGS == 1 +#error "Rainier CPU supports only AArch64. Compile with CTX_INCLUDE_AARCH32_REGS=0" +#endif + +/* -------------------------------------------------- + * Disable speculative loads if Rainier supports + * SSBS. + * + * Shall clobber: x0. + * -------------------------------------------------- + */ +func rainier_disable_speculative_loads + /* Check if the PE implements SSBS */ + mrs x0, id_aa64pfr1_el1 + tst x0, #(ID_AA64PFR1_EL1_SSBS_MASK << ID_AA64PFR1_EL1_SSBS_SHIFT) + b.eq 1f + + /* Disable speculative loads */ + msr SSBS, xzr + +1: + ret +endfunc rainier_disable_speculative_loads + + /* -------------------------------------------------- + * Errata Workaround for Neoverse N1 Errata #1868343. + * This applies to revision <= r4p0 of Neoverse N1. + * This workaround is the same as the workaround for + * errata 1262606 and 1275112 but applies to a wider + * revision range. + * Rainier R0P0 is based on Neoverse N1 R4P0 so the + * workaround checks for r0p0 version of Rainier CPU. + * Inputs: + * x0: variant[4:7] and revision[0:3] of current cpu. + * Shall clobber: x0, x1 & x17 + * -------------------------------------------------- + */ +func errata_n1_1868343_wa + /* + * Compare x0 against revision r4p0 + */ + mov x17, x30 + bl check_errata_1868343 + cbz x0, 1f + mrs x1, RAINIER_CPUACTLR_EL1 + orr x1, x1, RAINIER_CPUACTLR_EL1_BIT_13 + msr RAINIER_CPUACTLR_EL1, x1 + isb +1: + ret x17 +endfunc errata_n1_1868343_wa + +func check_errata_1868343 + /* Applies to r0p0 of Rainier CPU */ + mov x1, #0x00 + b cpu_rev_var_ls +endfunc check_errata_1868343 + +func rainier_reset_func + mov x19, x30 + + bl rainier_disable_speculative_loads + + /* Forces all cacheable atomic instructions to be near */ + mrs x0, RAINIER_CPUACTLR2_EL1 + orr x0, x0, #RAINIER_CPUACTLR2_EL1_BIT_2 + msr RAINIER_CPUACTLR2_EL1, x0 + isb + + bl cpu_get_rev_var + mov x18, x0 + +#if ERRATA_N1_1868343 + mov x0, x18 + bl errata_n1_1868343_wa +#endif + +#if ENABLE_AMU + /* Make sure accesses from EL0/EL1 and EL2 are not trapped to EL3 */ + mrs x0, actlr_el3 + orr x0, x0, #RAINIER_ACTLR_AMEN_BIT + msr actlr_el3, x0 + + /* Make sure accesses from EL0/EL1 are not trapped to EL2 */ + mrs x0, actlr_el2 + orr x0, x0, #RAINIER_ACTLR_AMEN_BIT + msr actlr_el2, x0 + + /* Enable group0 counters */ + mov x0, #RAINIER_AMU_GROUP0_MASK + msr CPUAMCNTENSET_EL0, x0 +#endif + + isb + ret x19 +endfunc rainier_reset_func + + /* --------------------------------------------- + * HW will do the cache maintenance while powering down + * --------------------------------------------- + */ +func rainier_core_pwr_dwn + /* --------------------------------------------- + * Enable CPU power down bit in power control register + * --------------------------------------------- + */ + mrs x0, RAINIER_CPUPWRCTLR_EL1 + orr x0, x0, #RAINIER_CORE_PWRDN_EN_MASK + msr RAINIER_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc rainier_core_pwr_dwn + +#if REPORT_ERRATA +/* + * Errata printing function for Rainier. Must follow AAPCS. + */ +func rainier_errata_report + stp x8, x30, [sp, #-16]! + + bl cpu_get_rev_var + mov x8, x0 + + /* + * Report all errata. The revision-variant information is passed to + * checking functions of each errata. + */ + report_errata ERRATA_N1_1868343, rainier, 1868343 + + ldp x8, x30, [sp], #16 + ret +endfunc rainier_errata_report +#endif + + /* --------------------------------------------- + * This function provides Rainier 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.rainier_regs, "aS" +rainier_regs: /* The ascii list of register names to be reported */ + .asciz "cpuectlr_el1", "" + +func rainier_cpu_reg_dump + adr x6, rainier_regs + mrs x8, RAINIER_CPUECTLR_EL1 + ret +endfunc rainier_cpu_reg_dump + +declare_cpu_ops rainier, RAINIER_MIDR, \ + rainier_reset_func, \ + rainier_core_pwr_dwn diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S new file mode 100644 index 0000000..0222818 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl wa_cve_2017_5715_bpiall_vbar + +#define EMIT_BPIALL 0xee070fd5 +#define EMIT_SMC 0xe1600070 +#define ESR_EL3_A64_SMC0 0x5e000000 + + .macro apply_cve_2017_5715_wa _from_vector + /* + * Save register state to enable a call to AArch32 S-EL1 and return + * Identify the original calling vector in w2 (==_from_vector) + * Use w3-w6 for additional register state preservation while in S-EL1 + */ + + /* Save GP regs */ + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + + /* Identify the original exception vector */ + mov w2, \_from_vector + + /* Preserve 32-bit system registers in GP registers through the workaround */ + mrs x3, esr_el3 + mrs x4, spsr_el3 + mrs x5, scr_el3 + mrs x6, sctlr_el1 + + /* + * Preserve LR and ELR_EL3 registers in the GP regs context. + * Temporarily use the CTX_GPREG_SP_EL0 slot to preserve ELR_EL3 + * through the workaround. This is OK because at this point the + * current state for this context's SP_EL0 is in the live system + * register, which is unmodified by the workaround. + */ + mrs x7, elr_el3 + stp x30, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* + * Load system registers for entry to S-EL1. + */ + + /* Mask all interrupts and set AArch32 Supervisor mode */ + movz w8, SPSR_MODE32(MODE32_svc, SPSR_T_ARM, SPSR_E_LITTLE, SPSR_AIF_MASK) + + /* Switch EL3 exception vectors while the workaround is executing. */ + adr x9, wa_cve_2017_5715_bpiall_ret_vbar + + /* Setup SCTLR_EL1 with MMU off and I$ on */ + ldr x10, stub_sel1_sctlr + + /* Land at the S-EL1 workaround stub */ + adr x11, aarch32_stub + + /* + * Setting SCR_EL3 to all zeroes means that the NS, RW + * and SMD bits are configured as expected. + */ + msr scr_el3, xzr + msr spsr_el3, x8 + msr vbar_el3, x9 + msr sctlr_el1, x10 + msr elr_el3, x11 + + eret + .endm + + /* --------------------------------------------------------------------- + * This vector table is used at runtime to enter the workaround at + * AArch32 S-EL1 for Sync/IRQ/FIQ/SError exceptions. If the workaround + * is not enabled, the existing runtime exception vector table is used. + * --------------------------------------------------------------------- + */ +vector_base wa_cve_2017_5715_bpiall_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_sp_el0 + b sync_exception_sp_el0 + nop /* to force 8 byte alignment for the following stub */ + + /* + * Since each vector table entry is 128 bytes, we can store the + * stub context in the unused space to minimize memory footprint. + */ +stub_sel1_sctlr: + .quad SCTLR_AARCH32_EL1_RES1 | SCTLR_I_BIT + +aarch32_stub: + .word EMIT_BPIALL + .word EMIT_SMC + +end_vector_entry bpiall_sync_exception_sp_el0 + +vector_entry bpiall_irq_sp_el0 + b irq_sp_el0 +end_vector_entry bpiall_irq_sp_el0 + +vector_entry bpiall_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry bpiall_fiq_sp_el0 + +vector_entry bpiall_serror_sp_el0 + b serror_sp_el0 +end_vector_entry bpiall_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry bpiall_sync_exception_sp_elx + +vector_entry bpiall_irq_sp_elx + b irq_sp_elx +end_vector_entry bpiall_irq_sp_elx + +vector_entry bpiall_fiq_sp_elx + b fiq_sp_elx +end_vector_entry bpiall_fiq_sp_elx + +vector_entry bpiall_serror_sp_elx + b serror_sp_elx +end_vector_entry bpiall_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_aarch64 + apply_cve_2017_5715_wa 1 +end_vector_entry bpiall_sync_exception_aarch64 + +vector_entry bpiall_irq_aarch64 + apply_cve_2017_5715_wa 2 +end_vector_entry bpiall_irq_aarch64 + +vector_entry bpiall_fiq_aarch64 + apply_cve_2017_5715_wa 4 +end_vector_entry bpiall_fiq_aarch64 + +vector_entry bpiall_serror_aarch64 + apply_cve_2017_5715_wa 8 +end_vector_entry bpiall_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_sync_exception_aarch32 + apply_cve_2017_5715_wa 1 +end_vector_entry bpiall_sync_exception_aarch32 + +vector_entry bpiall_irq_aarch32 + apply_cve_2017_5715_wa 2 +end_vector_entry bpiall_irq_aarch32 + +vector_entry bpiall_fiq_aarch32 + apply_cve_2017_5715_wa 4 +end_vector_entry bpiall_fiq_aarch32 + +vector_entry bpiall_serror_aarch32 + apply_cve_2017_5715_wa 8 +end_vector_entry bpiall_serror_aarch32 + + /* --------------------------------------------------------------------- + * This vector table is used while the workaround is executing. It + * installs a simple SMC handler to allow the Sync/IRQ/FIQ/SError + * workaround stubs to enter EL3 from S-EL1. It restores the previous + * EL3 state before proceeding with the normal runtime exception vector. + * --------------------------------------------------------------------- + */ +vector_base wa_cve_2017_5715_bpiall_ret_vbar + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_sp_el0 + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_sp_el0 + +vector_entry bpiall_ret_irq_sp_el0 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_sp_el0 + +vector_entry bpiall_ret_fiq_sp_el0 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_sp_el0 + +vector_entry bpiall_ret_serror_sp_el0 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_sp_elx + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_sp_elx + +vector_entry bpiall_ret_irq_sp_elx + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_sp_elx + +vector_entry bpiall_ret_fiq_sp_elx + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_sp_elx + +vector_entry bpiall_ret_serror_sp_elx + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 (UNUSED) + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_aarch64 + b report_unhandled_exception +end_vector_entry bpiall_ret_sync_exception_aarch64 + +vector_entry bpiall_ret_irq_aarch64 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_irq_aarch64 + +vector_entry bpiall_ret_fiq_aarch64 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_aarch64 + +vector_entry bpiall_ret_serror_aarch64 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bpiall_ret_sync_exception_aarch32 + /* + * w2 indicates which SEL1 stub was run and thus which original vector was used + * w3-w6 contain saved system register state (esr_el3 in w3) + * Restore LR and ELR_EL3 register state from the GP regs context + */ + ldp x30, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + + /* Apply the restored system register state */ + msr esr_el3, x3 + msr spsr_el3, x4 + msr scr_el3, x5 + msr sctlr_el1, x6 + msr elr_el3, x7 + + /* + * Workaround is complete, so swap VBAR_EL3 to point + * to workaround entry table in preparation for subsequent + * Sync/IRQ/FIQ/SError exceptions. + */ + adr x0, wa_cve_2017_5715_bpiall_vbar + msr vbar_el3, x0 + + /* + * Restore all GP regs except x2 and x3 (esr). The value in x2 + * indicates the type of the original exception. + */ + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + + /* Fast path Sync exceptions. Static predictor will fall through. */ + tbz w2, #0, workaround_not_sync + + /* + * Check if SMC is coming from A64 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ? + * (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + */ + orr w2, wzr, #SMCCC_ARCH_WORKAROUND_1 + cmp w0, w2 + orr w2, wzr, #SMCCC_ARCH_WORKAROUND_3 + ccmp w0, w2, #4, ne + mov_imm w2, ESR_EL3_A64_SMC0 + ccmp w3, w2, #0, eq + /* Static predictor will predict a fall through */ + bne 1f + eret +1: + /* restore x2 and x3 and continue sync exception handling */ + b bpiall_ret_sync_exception_aarch32_tail +end_vector_entry bpiall_ret_sync_exception_aarch32 + +vector_entry bpiall_ret_irq_aarch32 + b report_unhandled_interrupt + + /* + * Post-workaround fan-out for non-sync exceptions + */ +workaround_not_sync: + tbnz w2, #3, bpiall_ret_serror + tbnz w2, #2, bpiall_ret_fiq + /* IRQ */ + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b irq_aarch64 + +bpiall_ret_fiq: + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b fiq_aarch64 + +bpiall_ret_serror: + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b serror_aarch64 +end_vector_entry bpiall_ret_irq_aarch32 + +vector_entry bpiall_ret_fiq_aarch32 + b report_unhandled_interrupt +end_vector_entry bpiall_ret_fiq_aarch32 + +vector_entry bpiall_ret_serror_aarch32 + b report_unhandled_exception +end_vector_entry bpiall_ret_serror_aarch32 + + /* + * Part of bpiall_ret_sync_exception_aarch32 to save vector space + */ +func bpiall_ret_sync_exception_aarch32_tail + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + b sync_exception_aarch64 +endfunc bpiall_ret_sync_exception_aarch32_tail diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S new file mode 100644 index 0000000..ed0a549 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S @@ -0,0 +1,152 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl wa_cve_2017_5715_mmu_vbar + +#define ESR_EL3_A64_SMC0 0x5e000000 +#define ESR_EL3_A32_SMC0 0x4e000000 + +vector_base wa_cve_2017_5715_mmu_vbar + + .macro apply_cve_2017_5715_wa _is_sync_exception _esr_el3_val + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + mrs x1, sctlr_el3 + /* Disable MMU */ + bic x1, x1, #SCTLR_M_BIT + msr sctlr_el3, x1 + isb + /* Enable MMU */ + orr x1, x1, #SCTLR_M_BIT + msr sctlr_el3, x1 + /* + * Defer ISB to avoid synchronizing twice in case we hit + * the workaround SMC call which will implicitly synchronize + * because of the ERET instruction. + */ + + /* + * Ensure SMC is coming from A64/A32 state on #0 + * with W0 = SMCCC_ARCH_WORKAROUND_1 or W0 = SMCCC_ARCH_WORKAROUND_3 + * + * This sequence evaluates as: + * (W0==SMCCC_ARCH_WORKAROUND_1) || (W0==SMCCC_ARCH_WORKAROUND_3) ? + * (ESR_EL3==SMC#0) : (NE) + * allowing use of a single branch operation + */ + .if \_is_sync_exception + orr w1, wzr, #SMCCC_ARCH_WORKAROUND_1 + cmp w0, w1 + orr w1, wzr, #SMCCC_ARCH_WORKAROUND_3 + ccmp w0, w1, #4, ne + mrs x0, esr_el3 + mov_imm w1, \_esr_el3_val + ccmp w0, w1, #0, eq + /* Static predictor will predict a fall through */ + bne 1f + exception_return +1: + .endif + + /* + * Synchronize now to enable the MMU. This is required + * to ensure the load pair below reads the data stored earlier. + */ + isb + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + .endm + + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_sp_el0 + b sync_exception_sp_el0 +end_vector_entry mmu_sync_exception_sp_el0 + +vector_entry mmu_irq_sp_el0 + b irq_sp_el0 +end_vector_entry mmu_irq_sp_el0 + +vector_entry mmu_fiq_sp_el0 + b fiq_sp_el0 +end_vector_entry mmu_fiq_sp_el0 + +vector_entry mmu_serror_sp_el0 + b serror_sp_el0 +end_vector_entry mmu_serror_sp_el0 + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_sp_elx + b sync_exception_sp_elx +end_vector_entry mmu_sync_exception_sp_elx + +vector_entry mmu_irq_sp_elx + b irq_sp_elx +end_vector_entry mmu_irq_sp_elx + +vector_entry mmu_fiq_sp_elx + b fiq_sp_elx +end_vector_entry mmu_fiq_sp_elx + +vector_entry mmu_serror_sp_elx + b serror_sp_elx +end_vector_entry mmu_serror_sp_elx + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A64_SMC0 + b sync_exception_aarch64 +end_vector_entry mmu_sync_exception_aarch64 + +vector_entry mmu_irq_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b irq_aarch64 +end_vector_entry mmu_irq_aarch64 + +vector_entry mmu_fiq_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b fiq_aarch64 +end_vector_entry mmu_fiq_aarch64 + +vector_entry mmu_serror_aarch64 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A64_SMC0 + b serror_aarch64 +end_vector_entry mmu_serror_aarch64 + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry mmu_sync_exception_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=1 _esr_el3_val=ESR_EL3_A32_SMC0 + b sync_exception_aarch32 +end_vector_entry mmu_sync_exception_aarch32 + +vector_entry mmu_irq_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b irq_aarch32 +end_vector_entry mmu_irq_aarch32 + +vector_entry mmu_fiq_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b fiq_aarch32 +end_vector_entry mmu_fiq_aarch32 + +vector_entry mmu_serror_aarch32 + apply_cve_2017_5715_wa _is_sync_exception=0 _esr_el3_val=ESR_EL3_A32_SMC0 + b serror_aarch32 +end_vector_entry mmu_serror_aarch32 diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S new file mode 100644 index 0000000..e0e41cc --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#if WORKAROUND_CVE_2022_23960 + /* + * This macro applies the mitigation for CVE-2022-23960. + * The macro saves x2-x3 to the CPU context. + * SP should point to the CPU context. + */ + .macro apply_cve_2022_23960_bhb_wa _bhb_loop_count + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + + /* CVE-BHB-NUM loop count */ + mov x2, \_bhb_loop_count + +1: + /* b pc+4 part of the workaround */ + b 2f +2: + subs x2, x2, #1 + bne 1b + dsb sy + isb + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + .endm +#endif /* WORKAROUND_CVE_2022_23960 */ diff --git a/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S new file mode 100644 index 0000000..220fa11 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include "wa_cve_2022_23960_bhb.S" + + /* + * This macro is used to isolate the vector table for relevant CPUs + * used in the mitigation for CVE_2022_23960. + */ + .macro wa_cve_2022_23960_bhb_vector_table _bhb_loop_count, _cpu + + .globl wa_cve_vbar_\_cpu + +vector_base wa_cve_vbar_\_cpu + /* --------------------------------------------------------------------- + * Current EL with SP_EL0 : 0x0 - 0x200 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_sp_el0_\_cpu + b sync_exception_sp_el0 +end_vector_entry bhb_sync_exception_sp_el0_\_cpu + +vector_entry bhb_irq_sp_el0_\_cpu + b irq_sp_el0 +end_vector_entry bhb_irq_sp_el0_\_cpu + +vector_entry bhb_fiq_sp_el0_\_cpu + b fiq_sp_el0 +end_vector_entry bhb_fiq_sp_el0_\_cpu + +vector_entry bhb_serror_sp_el0_\_cpu + b serror_sp_el0 +end_vector_entry bhb_serror_sp_el0_\_cpu + + /* --------------------------------------------------------------------- + * Current EL with SP_ELx: 0x200 - 0x400 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_sp_elx_\_cpu + b sync_exception_sp_elx +end_vector_entry bhb_sync_exception_sp_elx_\_cpu + +vector_entry bhb_irq_sp_elx_\_cpu + b irq_sp_elx +end_vector_entry bhb_irq_sp_elx_\_cpu + +vector_entry bhb_fiq_sp_elx_\_cpu + b fiq_sp_elx +end_vector_entry bhb_fiq_sp_elx_\_cpu + +vector_entry bhb_serror_sp_elx_\_cpu + b serror_sp_elx +end_vector_entry bhb_serror_sp_elx_\_cpu + + /* --------------------------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b sync_exception_aarch64 +end_vector_entry bhb_sync_exception_aarch64_\_cpu + +vector_entry bhb_irq_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b irq_aarch64 +end_vector_entry bhb_irq_aarch64_\_cpu + +vector_entry bhb_fiq_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b fiq_aarch64 +end_vector_entry bhb_fiq_aarch64_\_cpu + +vector_entry bhb_serror_aarch64_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b serror_aarch64 +end_vector_entry bhb_serror_aarch64_\_cpu + + /* --------------------------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * --------------------------------------------------------------------- + */ +vector_entry bhb_sync_exception_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b sync_exception_aarch32 +end_vector_entry bhb_sync_exception_aarch32_\_cpu + +vector_entry bhb_irq_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b irq_aarch32 +end_vector_entry bhb_irq_aarch32_\_cpu + +vector_entry bhb_fiq_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b fiq_aarch32 +end_vector_entry bhb_fiq_aarch32_\_cpu + +vector_entry bhb_serror_aarch32_\_cpu + apply_cve_2022_23960_bhb_wa \_bhb_loop_count + b serror_aarch32 +end_vector_entry bhb_serror_aarch32_\_cpu + .endm diff --git a/arm-trusted-firmware/lib/cpus/cpu-ops.mk b/arm-trusted-firmware/lib/cpus/cpu-ops.mk new file mode 100644 index 0000000..86c7d4b --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/cpu-ops.mk @@ -0,0 +1,1128 @@ +# +# Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Cortex A57 specific optimisation to skip L1 cache flush when +# cluster is powered down. +SKIP_A57_L1_FLUSH_PWR_DWN ?=0 + +# Flag to disable the cache non-temporal hint. +# It is enabled by default. +A53_DISABLE_NON_TEMPORAL_HINT ?=1 + +# Flag to disable the cache non-temporal hint. +# It is enabled by default. +A57_DISABLE_NON_TEMPORAL_HINT ?=1 + +# Flag to enable higher performance non-cacheable load forwarding. +# It is disabled by default. +A57_ENABLE_NONCACHEABLE_LOAD_FWD ?= 0 + +WORKAROUND_CVE_2017_5715 ?=1 +WORKAROUND_CVE_2018_3639 ?=1 +DYNAMIC_WORKAROUND_CVE_2018_3639 ?=0 +WORKAROUND_CVE_2022_23960 ?=1 + +# Flags to indicate internal or external Last level cache +# By default internal +NEOVERSE_Nx_EXTERNAL_LLC ?=0 + +# Process A57_ENABLE_NONCACHEABLE_LOAD_FWD flag +$(eval $(call assert_boolean,A57_ENABLE_NONCACHEABLE_LOAD_FWD)) +$(eval $(call add_define,A57_ENABLE_NONCACHEABLE_LOAD_FWD)) + +# Process SKIP_A57_L1_FLUSH_PWR_DWN flag +$(eval $(call assert_boolean,SKIP_A57_L1_FLUSH_PWR_DWN)) +$(eval $(call add_define,SKIP_A57_L1_FLUSH_PWR_DWN)) + +# Process A53_DISABLE_NON_TEMPORAL_HINT flag +$(eval $(call assert_boolean,A53_DISABLE_NON_TEMPORAL_HINT)) +$(eval $(call add_define,A53_DISABLE_NON_TEMPORAL_HINT)) + +# Process A57_DISABLE_NON_TEMPORAL_HINT flag +$(eval $(call assert_boolean,A57_DISABLE_NON_TEMPORAL_HINT)) +$(eval $(call add_define,A57_DISABLE_NON_TEMPORAL_HINT)) + +# Process WORKAROUND_CVE_2017_5715 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2017_5715)) +$(eval $(call add_define,WORKAROUND_CVE_2017_5715)) + +# Process WORKAROUND_CVE_2018_3639 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2018_3639)) +$(eval $(call add_define,WORKAROUND_CVE_2018_3639)) + +$(eval $(call assert_boolean,DYNAMIC_WORKAROUND_CVE_2018_3639)) +$(eval $(call add_define,DYNAMIC_WORKAROUND_CVE_2018_3639)) + +# Process WORKAROUND_CVE_2022_23960 flag +$(eval $(call assert_boolean,WORKAROUND_CVE_2022_23960)) +$(eval $(call add_define,WORKAROUND_CVE_2022_23960)) + +$(eval $(call assert_boolean,NEOVERSE_Nx_EXTERNAL_LLC)) +$(eval $(call add_define,NEOVERSE_Nx_EXTERNAL_LLC)) + +ifneq (${DYNAMIC_WORKAROUND_CVE_2018_3639},0) + ifeq (${WORKAROUND_CVE_2018_3639},0) + $(error "Error: WORKAROUND_CVE_2018_3639 must be 1 if DYNAMIC_WORKAROUND_CVE_2018_3639 is 1") + endif +endif + +# CPU Errata Build flags. +# These should be enabled by the platform if the erratum workaround needs to be +# applied. + +# Flag to apply erratum 794073 workaround when disabling mmu. +ERRATA_A9_794073 ?=0 + +# Flag to apply erratum 816470 workaround during power down. This erratum +# applies only to revision >= r3p0 of the Cortex A15 cpu. +ERRATA_A15_816470 ?=0 + +# Flag to apply erratum 827671 workaround during reset. This erratum applies +# only to revision >= r3p0 of the Cortex A15 cpu. +ERRATA_A15_827671 ?=0 + +# Flag to apply erratum 852421 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A17 cpu. +ERRATA_A17_852421 ?=0 + +# Flag to apply erratum 852423 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A17 cpu. +ERRATA_A17_852423 ?=0 + +# Flag to apply erratum 855472 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A35 cpu. +ERRATA_A35_855472 ?=0 + +# Flag to apply erratum 819472 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A53 cpu. +ERRATA_A53_819472 ?=0 + +# Flag to apply erratum 824069 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_824069 ?=0 + +# Flag to apply erratum 826319 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_826319 ?=0 + +# Flag to apply erratum 827319 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A53 cpu. +ERRATA_A53_827319 ?=0 + +# Flag to apply erratum 835769 workaround at compile and link time. This +# erratum applies to revision <= r0p4 of the Cortex A53 cpu. Enabling this +# workaround can lead the linker to create "*.stub" sections. +ERRATA_A53_835769 ?=0 + +# Flag to apply erratum 836870 workaround during reset. This erratum applies +# only to revision <= r0p3 of the Cortex A53 cpu. From r0p4 and onwards, this +# erratum workaround is enabled by default in hardware. +ERRATA_A53_836870 ?=0 + +# Flag to apply erratum 843419 workaround at link time. +# This erratum applies to revision <= r0p4 of the Cortex A53 cpu. Enabling this +# workaround could lead the linker to emit "*.stub" sections which are 4kB +# aligned. +ERRATA_A53_843419 ?=0 + +# Flag to apply errata 855873 during reset. This errata applies to all +# revisions of the Cortex A53 CPU, but this firmware workaround only works +# for revisions r0p3 and higher. Earlier revisions are taken care +# of by the rich OS. +ERRATA_A53_855873 ?=0 + +# Flag to apply erratum 1530924 workaround during reset. This erratum applies +# to all revisions of Cortex A53 cpu. +ERRATA_A53_1530924 ?=0 + +# Flag to apply erratum 768277 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_768277 ?=0 + +# Flag to apply erratum 778703 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_778703 ?=0 + +# Flag to apply erratum 798797 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A55 cpu. +ERRATA_A55_798797 ?=0 + +# Flag to apply erratum 846532 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A55 cpu. +ERRATA_A55_846532 ?=0 + +# Flag to apply erratum 903758 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A55 cpu. +ERRATA_A55_903758 ?=0 + +# Flag to apply erratum 1221012 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A55 cpu. +ERRATA_A55_1221012 ?=0 + +# Flag to apply erratum 1530923 workaround during reset. This erratum applies +# to all revisions of Cortex A55 cpu. +ERRATA_A55_1530923 ?=0 + +# Flag to apply erratum 806969 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_806969 ?=0 + +# Flag to apply erratum 813419 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_813419 ?=0 + +# Flag to apply erratum 813420 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_813420 ?=0 + +# Flag to apply erratum 814670 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A57 cpu. +ERRATA_A57_814670 ?=0 + +# Flag to apply erratum 817169 workaround during power down. This erratum +# applies only to revision <= r0p1 of the Cortex A57 cpu. +ERRATA_A57_817169 ?=0 + +# Flag to apply erratum 826974 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_826974 ?=0 + +# Flag to apply erratum 826977 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_826977 ?=0 + +# Flag to apply erratum 828024 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A57 cpu. +ERRATA_A57_828024 ?=0 + +# Flag to apply erratum 829520 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A57 cpu. +ERRATA_A57_829520 ?=0 + +# Flag to apply erratum 833471 workaround during reset. This erratum applies +# only to revision <= r1p2 of the Cortex A57 cpu. +ERRATA_A57_833471 ?=0 + +# Flag to apply erratum 855972 workaround during reset. This erratum applies +# only to revision <= r1p3 of the Cortex A57 cpu. +ERRATA_A57_859972 ?=0 + +# Flag to apply erratum 1319537 workaround during reset. This erratum applies +# to all revisions of Cortex A57 cpu. +ERRATA_A57_1319537 ?=0 + +# Flag to apply erratum 855971 workaround during reset. This erratum applies +# only to revision <= r0p3 of the Cortex A72 cpu. +ERRATA_A72_859971 ?=0 + +# Flag to apply erratum 1319367 workaround during reset. This erratum applies +# to all revisions of Cortex A72 cpu. +ERRATA_A72_1319367 ?=0 + +# Flag to apply erratum 852427 workaround during reset. This erratum applies +# only to revision r0p0 of the Cortex A73 cpu. +ERRATA_A73_852427 ?=0 + +# Flag to apply erratum 855423 workaround during reset. This erratum applies +# only to revision <= r0p1 of the Cortex A73 cpu. +ERRATA_A73_855423 ?=0 + +# Flag to apply erratum 764081 workaround during reset. This erratum applies +# only to revision <= r0p0 of the Cortex A75 cpu. +ERRATA_A75_764081 ?=0 + +# Flag to apply erratum 790748 workaround during reset. This erratum applies +# only to revision <= r0p0 of the Cortex A75 cpu. +ERRATA_A75_790748 ?=0 + +# Flag to apply erratum 1073348 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A76 cpu. +ERRATA_A76_1073348 ?=0 + +# Flag to apply erratum 1130799 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Cortex A76 cpu. +ERRATA_A76_1130799 ?=0 + +# Flag to apply erratum 1220197 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Cortex A76 cpu. +ERRATA_A76_1220197 ?=0 + +# Flag to apply erratum 1257314 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1257314 ?=0 + +# Flag to apply erratum 1262606 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1262606 ?=0 + +# Flag to apply erratum 1262888 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1262888 ?=0 + +# Flag to apply erratum 1275112 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1275112 ?=0 + +# Flag to apply erratum 1286807 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Cortex A76 cpu. +ERRATA_A76_1286807 ?=0 + +# Flag to apply erratum 1791580 workaround during reset. This erratum applies +# only to revision <= r4p0 of the Cortex A76 cpu. +ERRATA_A76_1791580 ?=0 + +# Flag to apply erratum 1165522 workaround during reset. This erratum applies +# to all revisions of Cortex A76 cpu. +ERRATA_A76_1165522 ?=0 + +# Flag to apply erratum 1868343 workaround during reset. This erratum applies +# only to revision <= r4p0 of the Cortex A76 cpu. +ERRATA_A76_1868343 ?=0 + +# Flag to apply erratum 1946160 workaround during reset. This erratum applies +# only to revisions r3p0 - r4p1 of the Cortex A76 cpu. +ERRATA_A76_1946160 ?=0 + +# Flag to apply erratum 1508412 workaround during reset. This erratum applies +# only to revision <= r1p0 of the Cortex A77 cpu. +ERRATA_A77_1508412 ?=0 + +# Flag to apply erratum 1925769 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A77 cpu. +ERRATA_A77_1925769 ?=0 + +# Flag to apply erratum 1946167 workaround during reset. This erratum applies +# only to revision <= r1p1 of the Cortex A77 cpu. +ERRATA_A77_1946167 ?=0 + +# Flag to apply erratum 1791578 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1, it is still open. +ERRATA_A77_1791578 ?=0 + +# Flag to apply erratum 1688305 workaround during reset. This erratum applies +# to revisions r0p0 - r1p0 of the A78 cpu. +ERRATA_A78_1688305 ?=0 + +# Flag to apply erratum 1941498 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the A78 cpu. +ERRATA_A78_1941498 ?=0 + +# Flag to apply erratum 1951500 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the A78 cpu. The issue is present in r0p0 as +# well but there is no workaround for that revision. +ERRATA_A78_1951500 ?=0 + +# Flag to apply erratum 1821534 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the A78 cpu. +ERRATA_A78_1821534 ?=0 + +# Flag to apply erratum 1952683 workaround during reset. This erratum applies +# to revision r0p0 of the A78 cpu and was fixed in the revision r1p0. +ERRATA_A78_1952683 ?=0 + +# Flag to apply erratum 2132060 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, r1p1, and r1p2 of the A78 cpu. It is still open. +ERRATA_A78_2132060 ?=0 + +# Flag to apply erratum 2242635 workaround during reset. This erratum applies +# to revisions r1p0, r1p1, and r1p2 of the A78 cpu and is open. The issue is +# present in r0p0 as well but there is no workaround for that revision. +ERRATA_A78_2242635 ?=0 + +# Flag to apply erratum 1941500 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_1941500 ?=0 + +# Flag to apply erratum 1951502 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_1951502 ?=0 + +# Flag to apply erratum 2376748 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_2376748 ?=0 + +# Flag to apply erratum 2395408 workaround during reset. This erratum applies +# to revisions r0p0 and r0p1 of the A78 AE cpu. It is still open. +ERRATA_A78_AE_2395408 ?=0 + +# Flag to apply erratum 2466780 workaround during reset. This erratum applies +# only to revision <= r0p2 of the Cortex A78 AE cpu. +ERRATA_A78_AE_2466780 ?=0 + +# Flag to apply erratum 2743093 workaround in core power down. +# This erratum applies only to revision <= r0p2 of the Cortex A78 AE cpu. +ERRATA_A78_AE_2743093 ?=0 + +# Flag to apply erratum 2743229 workaround during reset. This erratum applies +# to revision r0p0, r0p1, and r0p2 of the Cortex A78 AE cpu. +ERRATA_A78_AE_2743229 ?=0 + +# Flag to apply T32 CLREX workaround during reset. This erratum applies +# only to r0p0 and r1p0 of the Neoverse N1 cpu. +ERRATA_N1_1043202 ?=0 + +# Flag to apply erratum 1073348 workaround during reset. This erratum applies +# only to revision r0p0 and r1p0 of the Neoverse N1 cpu. +ERRATA_N1_1073348 ?=0 + +# Flag to apply erratum 1130799 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1130799 ?=0 + +# Flag to apply erratum 1165347 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1165347 ?=0 + +# Flag to apply erratum 1207823 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1207823 ?=0 + +# Flag to apply erratum 1220197 workaround during reset. This erratum applies +# only to revision <= r2p0 of the Neoverse N1 cpu. +ERRATA_N1_1220197 ?=0 + +# Flag to apply erratum 1257314 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1257314 ?=0 + +# Flag to apply erratum 1262606 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1262606 ?=0 + +# Flag to apply erratum 1262888 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1262888 ?=0 + +# Flag to apply erratum 1275112 workaround during reset. This erratum applies +# only to revision <= r3p0 of the Neoverse N1 cpu. +ERRATA_N1_1275112 ?=0 + +# Flag to apply erratum 1315703 workaround during reset. This erratum applies +# to revisions before r3p1 of the Neoverse N1 cpu. +ERRATA_N1_1315703 ?=0 + +# Flag to apply erratum 1542419 workaround during reset. This erratum applies +# to revisions r3p0 - r4p0 of the Neoverse N1 cpu. +ERRATA_N1_1542419 ?=0 + +# Flag to apply erratum 1868343 workaround during reset. This erratum applies +# to revision <= r4p0 of the Neoverse N1 cpu. +ERRATA_N1_1868343 ?=0 + +# Flag to apply erratum 1946160 workaround during reset. This erratum applies +# to revisions r3p0, r3p1, r4p0, and r4p1 of the Neoverse N1 cpu. The issue +# exists in revisions r0p0, r1p0, and r2p0 as well but there is no workaround. +ERRATA_N1_1946160 ?=0 + +# Flag to apply erratum 2002655 workaround during reset. This erratum applies +# to revisions r0p0 of the Neoverse-N2 cpu, it is still open. +ERRATA_N2_2002655 ?=0 + +# Flag to apply erratum 1774420 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1774420 ?=0 + +# Flag to apply erratum 1791573 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1791573 ?=0 + +# Flag to apply erratum 1852267 workaround during reset. This erratum applies +# to revisions r0p0 and r1p0 of the Neoverse V1 core, and was fixed in r1p1. +ERRATA_V1_1852267 ?=0 + +# Flag to apply erratum 1925756 workaround during reset. This needs to be +# enabled for r0p0, r1p0, and r1p1 of the Neoverse V1 core, it is still open. +ERRATA_V1_1925756 ?=0 + +# Flag to apply erratum 1940577 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 cpu. +ERRATA_V1_1940577 ?=0 + +# Flag to apply erratum 1966096 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 CPU and is open. This issue +# exists in r0p0 as well but there is no workaround for that revision. +ERRATA_V1_1966096 ?=0 + +# Flag to apply erratum 2139242 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open. +ERRATA_V1_2139242 ?=0 + +# Flag to apply erratum 2108267 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r1p1 of the Neoverse V1 cpu and is still open. +ERRATA_V1_2108267 ?=0 + +# Flag to apply erratum 2216392 workaround during reset. This erratum applies +# to revisions r1p0 and r1p1 of the Neoverse V1 cpu and is still open. This +# issue exists in r0p0 as well but there is no workaround for that revision. +ERRATA_V1_2216392 ?=0 + +# Flag to apply erratum 1987031 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_1987031 ?=0 + +# Flag to apply erratum 2081180 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2081180 ?=0 + +# Flag to apply erratum 2083908 workaround during reset. This erratum applies +# to revision r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2083908 ?=0 + +# Flag to apply erratum 2058056 workaround during reset. This erratum applies +# to revisions r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2058056 ?=0 + +# Flag to apply erratum 2055002 workaround during reset. This erratum applies +# to revision r1p0, r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2055002 ?=0 + +# Flag to apply erratum 2017096 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is still open. +ERRATA_A710_2017096 ?=0 + +# Flag to apply erratum 2267065 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2267065 ?=0 + +# Flag to apply erratum 2136059 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2136059 ?=0 + +# Flag to apply erratum 2282622 workaround during reset. This erratum applies +# to revision r0p0, r1p0 and r2p0 of the Cortex-A710 cpu and is fixed in r2p1. +ERRATA_A710_2282622 ?=0 + +# Flag to apply erratum 2067956 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2067956 ?=0 + +# Flag to apply erratum 2025414 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2025414 ?=0 + +# Flag to apply erratum 2189731 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2189731 ?=0 + +# Flag to apply erratum 2138956 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138956 ?=0 + +# Flag to apply erratum 2138953 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138953 ?=0 + +# Flag to apply erratum 2242415 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2242415 ?=0 + +# Flag to apply erratum 2138958 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2138958 ?=0 + +# Flag to apply erratum 2242400 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2242400 ?=0 + +# Flag to apply erratum 2280757 workaround during reset. This erratum applies +# to revision r0p0 of the Neoverse N2 cpu and is still open. +ERRATA_N2_2280757 ?=0 + +# Flag to apply erratum 2002765 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2002765 ?=0 + +# Flag to apply erratum 2058056 workaround during reset. This erratum applies +# to revisions r0p0, r1p0, and r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2058056 ?=0 + +# Flag to apply erratum 2083908 workaround during reset. This erratum applies +# to revision r2p0 of the Cortex-X2 cpu and is still open. +ERRATA_X2_2083908 ?=0 + +# Flag to apply erratum 2017096 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2017096 ?=0 + +# Flag to apply erratum 2081180 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2081180 ?=0 + +# Flag to apply erratum 2216384 workaround during reset. This erratum applies +# only to revisions r0p0, r1p0 and r2p0 of the Cortex-X2 cpu, it is fixed in +# r2p1. +ERRATA_X2_2216384 ?=0 + +# Flag to apply erratum 1922240 workaround during reset. This erratum applies +# to revision r0p0 of the Cortex-A510 cpu and is fixed in r0p1. +ERRATA_A510_1922240 ?=0 + +# Flag to apply erratum 2288014 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0 of the Cortex-A510 cpu and is +# fixed in r1p1. +ERRATA_A510_2288014 ?=0 + +# Flag to apply erratum 2042739 workaround during reset. This erratum applies +# to revisions r0p0, r0p1 and r0p2 of the Cortex-A510 cpu and is fixed in r0p3. +ERRATA_A510_2042739 ?=0 + +# Flag to apply erratum 2041909 workaround during reset. This erratum applies +# to revision r0p2 of the Cortex-A510 cpu and is fixed in r0p3. The issue is +# present in r0p0 and r0p1 but there is no workaround for those revisions. +ERRATA_A510_2041909 ?=0 + +# Flag to apply erratum 2250311 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2250311 ?=0 + +# Flag to apply erratum 2218950 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2218950 ?=0 + +# Flag to apply erratum 2172148 workaround during reset. This erratum applies +# to revisions r0p0, r0p1, r0p2, r0p3 and r1p0, and is fixed in r1p1. +ERRATA_A510_2172148 ?=0 + +# Flag to apply DSU erratum 798953. This erratum applies to DSUs revision r0p0. +# Applying the workaround results in higher DSU power consumption on idle. +ERRATA_DSU_798953 ?=0 + +# Flag to apply DSU erratum 936184. This erratum applies to DSUs containing +# the ACP interface and revision < r2p0. Applying the workaround results in +# higher DSU power consumption on idle. +ERRATA_DSU_936184 ?=0 + +# Process ERRATA_A9_794073 flag +$(eval $(call assert_boolean,ERRATA_A9_794073)) +$(eval $(call add_define,ERRATA_A9_794073)) + +# Process ERRATA_A15_816470 flag +$(eval $(call assert_boolean,ERRATA_A15_816470)) +$(eval $(call add_define,ERRATA_A15_816470)) + +# Process ERRATA_A15_827671 flag +$(eval $(call assert_boolean,ERRATA_A15_827671)) +$(eval $(call add_define,ERRATA_A15_827671)) + +# Process ERRATA_A17_852421 flag +$(eval $(call assert_boolean,ERRATA_A17_852421)) +$(eval $(call add_define,ERRATA_A17_852421)) + +# Process ERRATA_A17_852423 flag +$(eval $(call assert_boolean,ERRATA_A17_852423)) +$(eval $(call add_define,ERRATA_A17_852423)) + +# Process ERRATA_A35_855472 flag +$(eval $(call assert_boolean,ERRATA_A35_855472)) +$(eval $(call add_define,ERRATA_A35_855472)) + +# Process ERRATA_A53_819472 flag +$(eval $(call assert_boolean,ERRATA_A53_819472)) +$(eval $(call add_define,ERRATA_A53_819472)) + +# Process ERRATA_A53_824069 flag +$(eval $(call assert_boolean,ERRATA_A53_824069)) +$(eval $(call add_define,ERRATA_A53_824069)) + +# Process ERRATA_A53_826319 flag +$(eval $(call assert_boolean,ERRATA_A53_826319)) +$(eval $(call add_define,ERRATA_A53_826319)) + +# Process ERRATA_A53_827319 flag +$(eval $(call assert_boolean,ERRATA_A53_827319)) +$(eval $(call add_define,ERRATA_A53_827319)) + +# Process ERRATA_A53_835769 flag +$(eval $(call assert_boolean,ERRATA_A53_835769)) +$(eval $(call add_define,ERRATA_A53_835769)) + +# Process ERRATA_A53_836870 flag +$(eval $(call assert_boolean,ERRATA_A53_836870)) +$(eval $(call add_define,ERRATA_A53_836870)) + +# Process ERRATA_A53_843419 flag +$(eval $(call assert_boolean,ERRATA_A53_843419)) +$(eval $(call add_define,ERRATA_A53_843419)) + +# Process ERRATA_A53_855873 flag +$(eval $(call assert_boolean,ERRATA_A53_855873)) +$(eval $(call add_define,ERRATA_A53_855873)) + +# Process ERRATA_A53_1530924 flag +$(eval $(call assert_boolean,ERRATA_A53_1530924)) +$(eval $(call add_define,ERRATA_A53_1530924)) + +# Process ERRATA_A55_768277 flag +$(eval $(call assert_boolean,ERRATA_A55_768277)) +$(eval $(call add_define,ERRATA_A55_768277)) + +# Process ERRATA_A55_778703 flag +$(eval $(call assert_boolean,ERRATA_A55_778703)) +$(eval $(call add_define,ERRATA_A55_778703)) + +# Process ERRATA_A55_798797 flag +$(eval $(call assert_boolean,ERRATA_A55_798797)) +$(eval $(call add_define,ERRATA_A55_798797)) + +# Process ERRATA_A55_846532 flag +$(eval $(call assert_boolean,ERRATA_A55_846532)) +$(eval $(call add_define,ERRATA_A55_846532)) + +# Process ERRATA_A55_903758 flag +$(eval $(call assert_boolean,ERRATA_A55_903758)) +$(eval $(call add_define,ERRATA_A55_903758)) + +# Process ERRATA_A55_1221012 flag +$(eval $(call assert_boolean,ERRATA_A55_1221012)) +$(eval $(call add_define,ERRATA_A55_1221012)) + +# Process ERRATA_A55_1530923 flag +$(eval $(call assert_boolean,ERRATA_A55_1530923)) +$(eval $(call add_define,ERRATA_A55_1530923)) + +# Process ERRATA_A57_806969 flag +$(eval $(call assert_boolean,ERRATA_A57_806969)) +$(eval $(call add_define,ERRATA_A57_806969)) + +# Process ERRATA_A57_813419 flag +$(eval $(call assert_boolean,ERRATA_A57_813419)) +$(eval $(call add_define,ERRATA_A57_813419)) + +# Process ERRATA_A57_813420 flag +$(eval $(call assert_boolean,ERRATA_A57_813420)) +$(eval $(call add_define,ERRATA_A57_813420)) + +# Process ERRATA_A57_814670 flag +$(eval $(call assert_boolean,ERRATA_A57_814670)) +$(eval $(call add_define,ERRATA_A57_814670)) + +# Process ERRATA_A57_817169 flag +$(eval $(call assert_boolean,ERRATA_A57_817169)) +$(eval $(call add_define,ERRATA_A57_817169)) + +# Process ERRATA_A57_826974 flag +$(eval $(call assert_boolean,ERRATA_A57_826974)) +$(eval $(call add_define,ERRATA_A57_826974)) + +# Process ERRATA_A57_826977 flag +$(eval $(call assert_boolean,ERRATA_A57_826977)) +$(eval $(call add_define,ERRATA_A57_826977)) + +# Process ERRATA_A57_828024 flag +$(eval $(call assert_boolean,ERRATA_A57_828024)) +$(eval $(call add_define,ERRATA_A57_828024)) + +# Process ERRATA_A57_829520 flag +$(eval $(call assert_boolean,ERRATA_A57_829520)) +$(eval $(call add_define,ERRATA_A57_829520)) + +# Process ERRATA_A57_833471 flag +$(eval $(call assert_boolean,ERRATA_A57_833471)) +$(eval $(call add_define,ERRATA_A57_833471)) + +# Process ERRATA_A57_859972 flag +$(eval $(call assert_boolean,ERRATA_A57_859972)) +$(eval $(call add_define,ERRATA_A57_859972)) + +# Process ERRATA_A57_1319537 flag +$(eval $(call assert_boolean,ERRATA_A57_1319537)) +$(eval $(call add_define,ERRATA_A57_1319537)) + +# Process ERRATA_A72_859971 flag +$(eval $(call assert_boolean,ERRATA_A72_859971)) +$(eval $(call add_define,ERRATA_A72_859971)) + +# Process ERRATA_A72_1319367 flag +$(eval $(call assert_boolean,ERRATA_A72_1319367)) +$(eval $(call add_define,ERRATA_A72_1319367)) + +# Process ERRATA_A73_852427 flag +$(eval $(call assert_boolean,ERRATA_A73_852427)) +$(eval $(call add_define,ERRATA_A73_852427)) + +# Process ERRATA_A73_855423 flag +$(eval $(call assert_boolean,ERRATA_A73_855423)) +$(eval $(call add_define,ERRATA_A73_855423)) + +# Process ERRATA_A75_764081 flag +$(eval $(call assert_boolean,ERRATA_A75_764081)) +$(eval $(call add_define,ERRATA_A75_764081)) + +# Process ERRATA_A75_790748 flag +$(eval $(call assert_boolean,ERRATA_A75_790748)) +$(eval $(call add_define,ERRATA_A75_790748)) + +# Process ERRATA_A76_1073348 flag +$(eval $(call assert_boolean,ERRATA_A76_1073348)) +$(eval $(call add_define,ERRATA_A76_1073348)) + +# Process ERRATA_A76_1130799 flag +$(eval $(call assert_boolean,ERRATA_A76_1130799)) +$(eval $(call add_define,ERRATA_A76_1130799)) + +# Process ERRATA_A76_1220197 flag +$(eval $(call assert_boolean,ERRATA_A76_1220197)) +$(eval $(call add_define,ERRATA_A76_1220197)) + +# Process ERRATA_A76_1257314 flag +$(eval $(call assert_boolean,ERRATA_A76_1257314)) +$(eval $(call add_define,ERRATA_A76_1257314)) + +# Process ERRATA_A76_1262606 flag +$(eval $(call assert_boolean,ERRATA_A76_1262606)) +$(eval $(call add_define,ERRATA_A76_1262606)) + +# Process ERRATA_A76_1262888 flag +$(eval $(call assert_boolean,ERRATA_A76_1262888)) +$(eval $(call add_define,ERRATA_A76_1262888)) + +# Process ERRATA_A76_1275112 flag +$(eval $(call assert_boolean,ERRATA_A76_1275112)) +$(eval $(call add_define,ERRATA_A76_1275112)) + +# Process ERRATA_A76_1286807 flag +$(eval $(call assert_boolean,ERRATA_A76_1286807)) +$(eval $(call add_define,ERRATA_A76_1286807)) + +# Process ERRATA_A76_1791580 flag +$(eval $(call assert_boolean,ERRATA_A76_1791580)) +$(eval $(call add_define,ERRATA_A76_1791580)) + +# Process ERRATA_A76_1165522 flag +$(eval $(call assert_boolean,ERRATA_A76_1165522)) +$(eval $(call add_define,ERRATA_A76_1165522)) + +# Process ERRATA_A76_1868343 flag +$(eval $(call assert_boolean,ERRATA_A76_1868343)) +$(eval $(call add_define,ERRATA_A76_1868343)) + +# Process ERRATA_A76_1946160 flag +$(eval $(call assert_boolean,ERRATA_A76_1946160)) +$(eval $(call add_define,ERRATA_A76_1946160)) + +# Process ERRATA_A77_1508412 flag +$(eval $(call assert_boolean,ERRATA_A77_1508412)) +$(eval $(call add_define,ERRATA_A77_1508412)) + +# Process ERRATA_A77_1925769 flag +$(eval $(call assert_boolean,ERRATA_A77_1925769)) +$(eval $(call add_define,ERRATA_A77_1925769)) + +# Process ERRATA_A77_1946167 flag +$(eval $(call assert_boolean,ERRATA_A77_1946167)) +$(eval $(call add_define,ERRATA_A77_1946167)) + +# Process ERRATA_A77_1791578 flag +$(eval $(call assert_boolean,ERRATA_A77_1791578)) +$(eval $(call add_define,ERRATA_A77_1791578)) + +# Process ERRATA_A78_1688305 flag +$(eval $(call assert_boolean,ERRATA_A78_1688305)) +$(eval $(call add_define,ERRATA_A78_1688305)) + +# Process ERRATA_A78_1941498 flag +$(eval $(call assert_boolean,ERRATA_A78_1941498)) +$(eval $(call add_define,ERRATA_A78_1941498)) + +# Process ERRATA_A78_1951500 flag +$(eval $(call assert_boolean,ERRATA_A78_1951500)) +$(eval $(call add_define,ERRATA_A78_1951500)) + +# Process ERRATA_A78_1821534 flag +$(eval $(call assert_boolean,ERRATA_A78_1821534)) +$(eval $(call add_define,ERRATA_A78_1821534)) + +# Process ERRATA_A78_1952683 flag +$(eval $(call assert_boolean,ERRATA_A78_1952683)) +$(eval $(call add_define,ERRATA_A78_1952683)) + +# Process ERRATA_A78_2132060 flag +$(eval $(call assert_boolean,ERRATA_A78_2132060)) +$(eval $(call add_define,ERRATA_A78_2132060)) + +# Process ERRATA_A78_2242635 flag +$(eval $(call assert_boolean,ERRATA_A78_2242635)) +$(eval $(call add_define,ERRATA_A78_2242635)) + +# Process ERRATA_A78_AE_1941500 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_1941500)) +$(eval $(call add_define,ERRATA_A78_AE_1941500)) + +# Process ERRATA_A78_AE_1951502 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_1951502)) +$(eval $(call add_define,ERRATA_A78_AE_1951502)) + +# Process ERRATA_A78C_2132064 flag +$(eval $(call assert_boolean,ERRATA_A78C_2132064)) +$(eval $(call add_define,ERRATA_A78C_2132064)) + +# Process ERRATA_A78_AE_2376748 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2376748)) +$(eval $(call add_define,ERRATA_A78_AE_2376748)) + +# Process ERRATA_A78_AE_2395408 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2395408)) +$(eval $(call add_define,ERRATA_A78_AE_2395408)) + +# Process ERRATA_A78_AE_2466780 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2466780)) +$(eval $(call add_define,ERRATA_A78_AE_2466780)) + +# Process ERRATA_A78_AE_2743093 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2743093)) +$(eval $(call add_define,ERRATA_A78_AE_2743093)) + +# Process ERRATA_A78_AE_2743229 flag +$(eval $(call assert_boolean,ERRATA_A78_AE_2743229)) +$(eval $(call add_define,ERRATA_A78_AE_2743229)) + +# Process ERRATA_N1_1043202 flag +$(eval $(call assert_boolean,ERRATA_N1_1043202)) +$(eval $(call add_define,ERRATA_N1_1043202)) + +# Process ERRATA_N1_1073348 flag +$(eval $(call assert_boolean,ERRATA_N1_1073348)) +$(eval $(call add_define,ERRATA_N1_1073348)) + +# Process ERRATA_N1_1130799 flag +$(eval $(call assert_boolean,ERRATA_N1_1130799)) +$(eval $(call add_define,ERRATA_N1_1130799)) + +# Process ERRATA_N1_1165347 flag +$(eval $(call assert_boolean,ERRATA_N1_1165347)) +$(eval $(call add_define,ERRATA_N1_1165347)) + +# Process ERRATA_N1_1207823 flag +$(eval $(call assert_boolean,ERRATA_N1_1207823)) +$(eval $(call add_define,ERRATA_N1_1207823)) + +# Process ERRATA_N1_1220197 flag +$(eval $(call assert_boolean,ERRATA_N1_1220197)) +$(eval $(call add_define,ERRATA_N1_1220197)) + +# Process ERRATA_N1_1257314 flag +$(eval $(call assert_boolean,ERRATA_N1_1257314)) +$(eval $(call add_define,ERRATA_N1_1257314)) + +# Process ERRATA_N1_1262606 flag +$(eval $(call assert_boolean,ERRATA_N1_1262606)) +$(eval $(call add_define,ERRATA_N1_1262606)) + +# Process ERRATA_N1_1262888 flag +$(eval $(call assert_boolean,ERRATA_N1_1262888)) +$(eval $(call add_define,ERRATA_N1_1262888)) + +# Process ERRATA_N1_1275112 flag +$(eval $(call assert_boolean,ERRATA_N1_1275112)) +$(eval $(call add_define,ERRATA_N1_1275112)) + +# Process ERRATA_N1_1315703 flag +$(eval $(call assert_boolean,ERRATA_N1_1315703)) +$(eval $(call add_define,ERRATA_N1_1315703)) + +# Process ERRATA_N1_1542419 flag +$(eval $(call assert_boolean,ERRATA_N1_1542419)) +$(eval $(call add_define,ERRATA_N1_1542419)) + +# Process ERRATA_N1_1868343 flag +$(eval $(call assert_boolean,ERRATA_N1_1868343)) +$(eval $(call add_define,ERRATA_N1_1868343)) + +# Process ERRATA_N1_1946160 flag +$(eval $(call assert_boolean,ERRATA_N1_1946160)) +$(eval $(call add_define,ERRATA_N1_1946160)) + +# Process ERRATA_N2_2002655 flag +$(eval $(call assert_boolean,ERRATA_N2_2002655)) +$(eval $(call add_define,ERRATA_N2_2002655)) + +# Process ERRATA_V1_1774420 flag +$(eval $(call assert_boolean,ERRATA_V1_1774420)) +$(eval $(call add_define,ERRATA_V1_1774420)) + +# Process ERRATA_V1_1791573 flag +$(eval $(call assert_boolean,ERRATA_V1_1791573)) +$(eval $(call add_define,ERRATA_V1_1791573)) + +# Process ERRATA_V1_1852267 flag +$(eval $(call assert_boolean,ERRATA_V1_1852267)) +$(eval $(call add_define,ERRATA_V1_1852267)) + +# Process ERRATA_V1_1925756 flag +$(eval $(call assert_boolean,ERRATA_V1_1925756)) +$(eval $(call add_define,ERRATA_V1_1925756)) + +# Process ERRATA_V1_1940577 flag +$(eval $(call assert_boolean,ERRATA_V1_1940577)) +$(eval $(call add_define,ERRATA_V1_1940577)) + +# Process ERRATA_V1_1966096 flag +$(eval $(call assert_boolean,ERRATA_V1_1966096)) +$(eval $(call add_define,ERRATA_V1_1966096)) + +# Process ERRATA_V1_2139242 flag +$(eval $(call assert_boolean,ERRATA_V1_2139242)) +$(eval $(call add_define,ERRATA_V1_2139242)) + +# Process ERRATA_V1_2108267 flag +$(eval $(call assert_boolean,ERRATA_V1_2108267)) +$(eval $(call add_define,ERRATA_V1_2108267)) + +# Process ERRATA_V1_2216392 flag +$(eval $(call assert_boolean,ERRATA_V1_2216392)) +$(eval $(call add_define,ERRATA_V1_2216392)) + +# Process ERRATA_A710_1987031 flag +$(eval $(call assert_boolean,ERRATA_A710_1987031)) +$(eval $(call add_define,ERRATA_A710_1987031)) + +# Process ERRATA_A710_2081180 flag +$(eval $(call assert_boolean,ERRATA_A710_2081180)) +$(eval $(call add_define,ERRATA_A710_2081180)) + +# Process ERRATA_A710_2083908 flag +$(eval $(call assert_boolean,ERRATA_A710_2083908)) +$(eval $(call add_define,ERRATA_A710_2083908)) + +# Process ERRATA_A710_2058056 flag +$(eval $(call assert_boolean,ERRATA_A710_2058056)) +$(eval $(call add_define,ERRATA_A710_2058056)) + +# Process ERRATA_A710_2055002 flag +$(eval $(call assert_boolean,ERRATA_A710_2055002)) +$(eval $(call add_define,ERRATA_A710_2055002)) + +# Process ERRATA_A710_2017096 flag +$(eval $(call assert_boolean,ERRATA_A710_2017096)) +$(eval $(call add_define,ERRATA_A710_2017096)) + +# Process ERRATA_A710_2267065 flag +$(eval $(call assert_boolean,ERRATA_A710_2267065)) +$(eval $(call add_define,ERRATA_A710_2267065)) + +# Process ERRATA_A710_2136059 flag +$(eval $(call assert_boolean,ERRATA_A710_2136059)) +$(eval $(call add_define,ERRATA_A710_2136059)) + +# Process ERRATA_A710_2282622 flag +$(eval $(call assert_boolean,ERRATA_A710_2282622)) +$(eval $(call add_define,ERRATA_A710_2282622)) + +# Process ERRATA_N2_2067956 flag +$(eval $(call assert_boolean,ERRATA_N2_2067956)) +$(eval $(call add_define,ERRATA_N2_2067956)) + +# Process ERRATA_N2_2025414 flag +$(eval $(call assert_boolean,ERRATA_N2_2025414)) +$(eval $(call add_define,ERRATA_N2_2025414)) + +# Process ERRATA_N2_2189731 flag +$(eval $(call assert_boolean,ERRATA_N2_2189731)) +$(eval $(call add_define,ERRATA_N2_2189731)) + +# Process ERRATA_N2_2138956 flag +$(eval $(call assert_boolean,ERRATA_N2_2138956)) +$(eval $(call add_define,ERRATA_N2_2138956)) + +# Process ERRATA_N2_2138953 flag +$(eval $(call assert_boolean,ERRATA_N2_2138953)) +$(eval $(call add_define,ERRATA_N2_2138953)) + +# Process ERRATA_N2_2242415 flag +$(eval $(call assert_boolean,ERRATA_N2_2242415)) +$(eval $(call add_define,ERRATA_N2_2242415)) + +# Process ERRATA_N2_2138958 flag +$(eval $(call assert_boolean,ERRATA_N2_2138958)) +$(eval $(call add_define,ERRATA_N2_2138958)) + +# Process ERRATA_N2_2242400 flag +$(eval $(call assert_boolean,ERRATA_N2_2242400)) +$(eval $(call add_define,ERRATA_N2_2242400)) + +# Process ERRATA_N2_2280757 flag +$(eval $(call assert_boolean,ERRATA_N2_2280757)) +$(eval $(call add_define,ERRATA_N2_2280757)) + +# Process ERRATA_X2_2002765 flag +$(eval $(call assert_boolean,ERRATA_X2_2002765)) +$(eval $(call add_define,ERRATA_X2_2002765)) + +# Process ERRATA_X2_2058056 flag +$(eval $(call assert_boolean,ERRATA_X2_2058056)) +$(eval $(call add_define,ERRATA_X2_2058056)) + +# Process ERRATA_X2_2083908 flag +$(eval $(call assert_boolean,ERRATA_X2_2083908)) +$(eval $(call add_define,ERRATA_X2_2083908)) + +# Process ERRATA_X2_2017096 flag +$(eval $(call assert_boolean,ERRATA_X2_2017096)) +$(eval $(call add_define,ERRATA_X2_2017096)) + +# Process ERRATA_X2_2081180 flag +$(eval $(call assert_boolean,ERRATA_X2_2081180)) +$(eval $(call add_define,ERRATA_X2_2081180)) + +# Process ERRATA_X2_2216384 flag +$(eval $(call assert_boolean,ERRATA_X2_2216384)) +$(eval $(call add_define,ERRATA_X2_2216384)) + +# Process ERRATA_A510_1922240 flag +$(eval $(call assert_boolean,ERRATA_A510_1922240)) +$(eval $(call add_define,ERRATA_A510_1922240)) + +# Process ERRATA_A510_2288014 flag +$(eval $(call assert_boolean,ERRATA_A510_2288014)) +$(eval $(call add_define,ERRATA_A510_2288014)) + +# Process ERRATA_A510_2042739 flag +$(eval $(call assert_boolean,ERRATA_A510_2042739)) +$(eval $(call add_define,ERRATA_A510_2042739)) + +# Process ERRATA_A510_2041909 flag +$(eval $(call assert_boolean,ERRATA_A510_2041909)) +$(eval $(call add_define,ERRATA_A510_2041909)) + +# Process ERRATA_A510_2250311 flag +$(eval $(call assert_boolean,ERRATA_A510_2250311)) +$(eval $(call add_define,ERRATA_A510_2250311)) + +# Process ERRATA_A510_2218950 flag +$(eval $(call assert_boolean,ERRATA_A510_2218950)) +$(eval $(call add_define,ERRATA_A510_2218950)) + +# Process ERRATA_A510_2172148 flag +$(eval $(call assert_boolean,ERRATA_A510_2172148)) +$(eval $(call add_define,ERRATA_A510_2172148)) + +# Process ERRATA_DSU_798953 flag +$(eval $(call assert_boolean,ERRATA_DSU_798953)) +$(eval $(call add_define,ERRATA_DSU_798953)) + +# Process ERRATA_DSU_936184 flag +$(eval $(call assert_boolean,ERRATA_DSU_936184)) +$(eval $(call add_define,ERRATA_DSU_936184)) + +# Errata build flags +ifneq (${ERRATA_A53_843419},0) +TF_LDFLAGS_aarch64 += --fix-cortex-a53-843419 +endif + +ifneq (${ERRATA_A53_835769},0) +TF_CFLAGS_aarch64 += -mfix-cortex-a53-835769 +TF_LDFLAGS_aarch64 += --fix-cortex-a53-835769 +endif + +ifneq ($(filter 1,${ERRATA_A53_1530924} ${ERRATA_A55_1530923} \ + ${ERRATA_A57_1319537} ${ERRATA_A72_1319367} ${ERRATA_A76_1165522}),) +ERRATA_SPECULATIVE_AT := 1 +else +ERRATA_SPECULATIVE_AT := 0 +endif diff --git a/arm-trusted-firmware/lib/cpus/errata_report.c b/arm-trusted-firmware/lib/cpus/errata_report.c new file mode 100644 index 0000000..93b2744 --- /dev/null +++ b/arm-trusted-firmware/lib/cpus/errata_report.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Runtime firmware routines to report errata status for the current CPU. */ + +#include +#include + +#include +#include +#include +#include +#include + +#ifdef IMAGE_BL1 +# define BL_STRING "BL1" +#elif defined(__aarch64__) && defined(IMAGE_BL31) +# define BL_STRING "BL31" +#elif !defined(__aarch64__) && defined(IMAGE_BL32) +# define BL_STRING "BL32" +#elif defined(IMAGE_BL2) && BL2_AT_EL3 +# define BL_STRING "BL2" +#else +# error This image should not be printing errata status +#endif + +/* Errata format: BL stage, CPU, errata ID, message */ +#define ERRATA_FORMAT "%s: %s: CPU workaround for %s was %s\n" + +/* + * Returns whether errata needs to be reported. Passed arguments are private to + * a CPU type. + */ +int errata_needs_reporting(spinlock_t *lock, uint32_t *reported) +{ + bool report_now; + + /* If already reported, return false. */ + if (*reported != 0U) + return 0; + + /* + * Acquire lock. Determine whether status needs reporting, and then mark + * report status to true. + */ + spin_lock(lock); + report_now = (*reported == 0U); + if (report_now) + *reported = 1; + spin_unlock(lock); + + return report_now; +} + +/* + * Print errata status message. + * + * Unknown: WARN + * Missing: WARN + * Applied: INFO + * Not applied: VERBOSE + */ +void errata_print_msg(unsigned int status, const char *cpu, const char *id) +{ + /* Errata status strings */ + static const char *const errata_status_str[] = { + [ERRATA_NOT_APPLIES] = "not applied", + [ERRATA_APPLIES] = "applied", + [ERRATA_MISSING] = "missing!" + }; + static const char *const __unused bl_str = BL_STRING; + const char *msg __unused; + + + assert(status < ARRAY_SIZE(errata_status_str)); + assert(cpu != NULL); + assert(id != NULL); + + msg = errata_status_str[status]; + + switch (status) { + case ERRATA_NOT_APPLIES: + VERBOSE(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_APPLIES: + INFO(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + case ERRATA_MISSING: + WARN(ERRATA_FORMAT, bl_str, cpu, id, msg); + break; + + default: + WARN(ERRATA_FORMAT, bl_str, cpu, id, "unknown"); + break; + } +} diff --git a/arm-trusted-firmware/lib/debugfs/blobs.h b/arm-trusted-firmware/lib/debugfs/blobs.h new file mode 100644 index 0000000..54ca9f7 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/blobs.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "dev.h" + +static const dirtab_t blobtab[] = { + {"ctl", DEV_ROOT_QBLOBCTL, 0, O_READ}, + {"fip.bin", DEV_ROOT_QBLOBCTL + 1, 0x100000, O_READ, (void *)0x8000000} +}; diff --git a/arm-trusted-firmware/lib/debugfs/debugfs.mk b/arm-trusted-firmware/lib/debugfs/debugfs.mk new file mode 100644 index 0000000..138fc72 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/debugfs.mk @@ -0,0 +1,13 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +DEBUGFS_SRCS := $(addprefix lib/debugfs/, \ + dev.c \ + devc.c \ + devroot.c \ + devfip.c) + +DEBUGFS_SRCS += lib/debugfs/debugfs_smc.c diff --git a/arm-trusted-firmware/lib/debugfs/debugfs_smc.c b/arm-trusted-firmware/lib/debugfs/debugfs_smc.c new file mode 100644 index 0000000..400c166 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/debugfs_smc.c @@ -0,0 +1,209 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#define MAX_PATH_LEN 256 + +#define MOUNT 0 +#define CREATE 1 +#define OPEN 2 +#define CLOSE 3 +#define READ 4 +#define WRITE 5 +#define SEEK 6 +#define BIND 7 +#define STAT 8 +#define INIT 10 +#define VERSION 11 + +/* This is the virtual address to which we map the NS shared buffer */ +#define DEBUGFS_SHARED_BUF_VIRT ((void *)0x81000000U) + +static union debugfs_parms { + struct { + char fname[MAX_PATH_LEN]; + } open; + + struct { + char srv[MAX_PATH_LEN]; + char where[MAX_PATH_LEN]; + char spec[MAX_PATH_LEN]; + } mount; + + struct { + char path[MAX_PATH_LEN]; + dir_t dir; + } stat; + + struct { + char oldpath[MAX_PATH_LEN]; + char newpath[MAX_PATH_LEN]; + } bind; +} parms; + +/* debugfs_access_lock protects shared buffer and internal */ +/* FS functions from concurrent acccesses. */ +static spinlock_t debugfs_access_lock; + +static bool debugfs_initialized; + +uintptr_t debugfs_smc_handler(unsigned int smc_fid, + u_register_t cmd, + u_register_t arg2, + u_register_t arg3, + u_register_t arg4, + void *cookie, + void *handle, + u_register_t flags) +{ + int64_t smc_ret = DEBUGFS_E_INVALID_PARAMS, smc_resp = 0; + int ret; + + /* Allow calls from non-secure only */ + if (is_caller_secure(flags)) { + SMC_RET1(handle, DEBUGFS_E_DENIED); + } + + /* Expect a SiP service fast call */ + if ((GET_SMC_TYPE(smc_fid) != SMC_TYPE_FAST) || + (GET_SMC_OEN(smc_fid) != OEN_SIP_START)) { + SMC_RET1(handle, SMC_UNK); + } + + /* Truncate parameters if 32b SMC convention call */ + if (GET_SMC_CC(smc_fid) == SMC_32) { + arg2 &= 0xffffffff; + arg3 &= 0xffffffff; + arg4 &= 0xffffffff; + } + + spin_lock(&debugfs_access_lock); + + if (debugfs_initialized == true) { + /* Copy NS shared buffer to internal secure location */ + memcpy(&parms, (void *)DEBUGFS_SHARED_BUF_VIRT, + sizeof(union debugfs_parms)); + } + + switch (cmd) { + case INIT: + if (debugfs_initialized == false) { + /* TODO: check PA validity e.g. whether */ + /* it is an NS region. */ + ret = mmap_add_dynamic_region(arg2, + (uintptr_t)DEBUGFS_SHARED_BUF_VIRT, + PAGE_SIZE_4KB, + MT_MEMORY | MT_RW | MT_NS); + if (ret == 0) { + debugfs_initialized = true; + smc_ret = SMC_OK; + smc_resp = 0; + } + } + break; + + case VERSION: + smc_ret = SMC_OK; + smc_resp = DEBUGFS_VERSION; + break; + + case MOUNT: + ret = mount(parms.mount.srv, + parms.mount.where, + parms.mount.spec); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case OPEN: + ret = open(parms.open.fname, arg2); + if (ret >= 0) { + smc_ret = SMC_OK; + smc_resp = ret; + } + break; + + case CLOSE: + ret = close(arg2); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case READ: + ret = read(arg2, DEBUGFS_SHARED_BUF_VIRT, arg3); + if (ret >= 0) { + smc_ret = SMC_OK; + smc_resp = ret; + } + break; + + case SEEK: + ret = seek(arg2, arg3, arg4); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case BIND: + ret = bind(parms.bind.oldpath, parms.bind.newpath); + if (ret == 0) { + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + case STAT: + ret = stat(parms.stat.path, &parms.stat.dir); + if (ret == 0) { + memcpy((void *)DEBUGFS_SHARED_BUF_VIRT, &parms, + sizeof(union debugfs_parms)); + smc_ret = SMC_OK; + smc_resp = 0; + } + break; + + /* Not implemented */ + case CREATE: + /* Intentional fall-through */ + + /* Not implemented */ + case WRITE: + /* Intentional fall-through */ + + default: + smc_ret = SMC_UNK; + smc_resp = 0; + } + + spin_unlock(&debugfs_access_lock); + + SMC_RET2(handle, smc_ret, smc_resp); + + /* Not reached */ + return smc_ret; +} + +int debugfs_smc_setup(void) +{ + debugfs_initialized = false; + debugfs_access_lock.lock = 0; + + return 0; +} diff --git a/arm-trusted-firmware/lib/debugfs/dev.c b/arm-trusted-firmware/lib/debugfs/dev.c new file mode 100644 index 0000000..2fc1d40 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/dev.c @@ -0,0 +1,853 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include "dev.h" + +#define NR_MOUNT_POINTS 4 + +struct mount_point { + chan_t *new; + chan_t *old; +}; + +/* This array contains all the available channels of the filesystem. + * A file descriptor is the index of a specific channel in this array. + */ +static chan_t fdset[NR_CHANS]; + +/* This array contains all the available mount points of the filesystem. */ +static struct mount_point mount_points[NR_MOUNT_POINTS]; + +/* This variable stores the channel associated to the root directory. */ +static chan_t slash_channel; + +/* This function creates a channel from a device index and registers + * it to fdset. + */ +static chan_t *create_new_channel(unsigned char index) +{ + chan_t *channel = NULL; + int i; + + for (i = 0; i < NR_CHANS; i++) { + if (fdset[i].index == NODEV) { + channel = &fdset[i]; + channel->index = index; + break; + } + } + + return channel; +} + +/******************************************************************************* + * This function returns a pointer to an existing channel in fdset from a file + * descriptor. + ******************************************************************************/ +static chan_t *fd_to_channel(int fd) +{ + if ((fd < 0) || (fd >= NR_CHANS) || (fdset[fd].index == NODEV)) { + return NULL; + } + + return &fdset[fd]; +} + +/******************************************************************************* + * This function returns a file descriptor from a channel. + * The caller must be sure that the channel is registered in fdset. + ******************************************************************************/ +static int channel_to_fd(chan_t *channel) +{ + return (channel == NULL) ? -1 : (channel - fdset); +} + +/******************************************************************************* + * This function checks the validity of a mode. + ******************************************************************************/ +static bool is_valid_mode(int mode) +{ + if ((mode & O_READ) && (mode & (O_WRITE | O_RDWR))) { + return false; + } + if ((mode & O_WRITE) && (mode & (O_READ | O_RDWR))) { + return false; + } + if ((mode & O_RDWR) && (mode & (O_READ | O_WRITE))) { + return false; + } + + return true; +} + +/******************************************************************************* + * This function extracts the next part of the given path contained and puts it + * in token. It returns a pointer to the remainder of the path. + ******************************************************************************/ +static const char *next(const char *path, char *token) +{ + int index; + const char *cursor; + + while (*path == '/') { + ++path; + } + + index = 0; + cursor = path; + if (*path != '\0') { + while (*cursor != '/' && *cursor != '\0') { + if (index == NAMELEN) { + return NULL; + } + token[index++] = *cursor++; + } + } + token[index] = '\0'; + + return cursor; +} + +/******************************************************************************* + * This function returns the driver index in devtab of the driver + * identified by id. + ******************************************************************************/ +static int get_device_index(int id) +{ + int index; + dev_t * const *dp; + + for (index = 0, dp = devtab; *dp && (*dp)->id != id; ++dp) { + index++; + } + + if (*dp == NULL) { + return -1; + } + + return index; +} + +/******************************************************************************* + * This function clears a given channel fields + ******************************************************************************/ +static void channel_clear(chan_t *channel) +{ + channel->offset = 0; + channel->qid = 0; + channel->index = NODEV; + channel->dev = 0; + channel->mode = 0; +} + +/******************************************************************************* + * This function closes the channel pointed to by c. + ******************************************************************************/ +void channel_close(chan_t *channel) +{ + if (channel != NULL) { + channel_clear(channel); + } +} + +/******************************************************************************* + * This function copies data from src to dst after applying the offset of the + * channel c. nbytes bytes are expected to be copied unless the data goes over + * dst + len. + * It returns the actual number of bytes that were copied. + ******************************************************************************/ +int buf_to_channel(chan_t *channel, void *dst, void *src, int nbytes, long len) +{ + const char *addr = src; + + if ((channel == NULL) || (dst == NULL) || (src == NULL)) { + return 0; + } + + if (channel->offset >= len) { + return 0; + } + + if ((channel->offset + nbytes) > len) { + nbytes = len - channel->offset; + } + + memcpy(dst, addr + channel->offset, nbytes); + + channel->offset += nbytes; + + return nbytes; +} + +/******************************************************************************* + * This function checks whether a channel (identified by its device index and + * qid) is registered as a mount point. + * Returns a pointer to the channel it is mounted to when found, NULL otherwise. + ******************************************************************************/ +static chan_t *mount_point_to_channel(int index, qid_t qid) +{ + chan_t *channel; + struct mount_point *mp; + + for (mp = mount_points; mp < &mount_points[NR_MOUNT_POINTS]; mp++) { + channel = mp->new; + if (channel == NULL) { + continue; + } + + if ((channel->index == index) && (channel->qid == qid)) { + return mp->old; + } + } + + return NULL; +} + +/******************************************************************************* + * This function calls the attach function of the driver identified by id. + ******************************************************************************/ +chan_t *attach(int id, int dev) +{ + /* Get the devtab index for the driver identified by id */ + int index = get_device_index(id); + + if (index < 0) { + return NULL; + } + + return devtab[index]->attach(id, dev); +} + +/******************************************************************************* + * This function is the default implementation of the driver attach function. + * It creates a new channel and returns a pointer to it. + ******************************************************************************/ +chan_t *devattach(int id, int dev) +{ + chan_t *channel; + int index; + + index = get_device_index(id); + if (index < 0) { + return NULL; + } + + channel = create_new_channel(index); + if (channel == NULL) { + return NULL; + } + + channel->dev = dev; + channel->qid = CHDIR; + + return channel; +} + +/******************************************************************************* + * This function returns a channel given a path. + * It goes through the filesystem, from the root namespace ('/') or from a + * device namespace ('#'), switching channel on mount points. + ******************************************************************************/ +chan_t *path_to_channel(const char *path, int mode) +{ + int i, n; + const char *path_next; + chan_t *mnt, *channel; + char elem[NAMELEN]; + + if (path == NULL) { + return NULL; + } + + switch (path[0]) { + case '/': + channel = clone(&slash_channel, NULL); + path_next = path; + break; + case '#': + path_next = next(path + 1, elem); + if (path_next == NULL) { + goto noent; + } + + n = 0; + for (i = 1; (elem[i] >= '0') && (elem[i] <= '9'); i++) { + n += elem[i] - '0'; + } + + if (elem[i] != '\0') { + goto noent; + } + + channel = attach(elem[0], n); + break; + default: + return NULL; + } + + if (channel == NULL) { + return NULL; + } + + for (path_next = next(path_next, elem); *elem; + path_next = next(path_next, elem)) { + if ((channel->qid & CHDIR) == 0) { + goto notfound; + } + + if (devtab[channel->index]->walk(channel, elem) < 0) { + channel_close(channel); + goto notfound; + } + + mnt = mount_point_to_channel(channel->index, channel->qid); + if (mnt != NULL) { + clone(mnt, channel); + } + } + + if (path_next == NULL) { + goto notfound; + } + + /* TODO: check mode */ + return channel; + +notfound: + channel_close(channel); +noent: + return NULL; +} + +/******************************************************************************* + * This function calls the clone function of the driver associated to the + * channel c. + ******************************************************************************/ +chan_t *clone(chan_t *c, chan_t *nc) +{ + if (c->index == NODEV) { + return NULL; + } + + return devtab[c->index]->clone(c, nc); +} + +/******************************************************************************* + * This function is the default implementation of the driver clone function. + * It creates a new channel and returns a pointer to it. + * It clones channel into new_channel. + ******************************************************************************/ +chan_t *devclone(chan_t *channel, chan_t *new_channel) +{ + if (channel == NULL) { + return NULL; + } + + if (new_channel == NULL) { + new_channel = create_new_channel(channel->index); + if (new_channel == NULL) { + return NULL; + } + } + + new_channel->qid = channel->qid; + new_channel->dev = channel->dev; + new_channel->mode = channel->mode; + new_channel->offset = channel->offset; + new_channel->index = channel->index; + + return new_channel; +} + +/******************************************************************************* + * This function is the default implementation of the driver walk function. + * It goes through all the elements of tab using the gen function until a match + * is found with name. + * If a match is found, it copies the qid of the new directory. + ******************************************************************************/ +int devwalk(chan_t *channel, const char *name, const dirtab_t *tab, + int ntab, devgen_t *gen) +{ + int i; + dir_t dir; + + if ((channel == NULL) || (name == NULL) || (gen == NULL)) { + return -1; + } + + if ((name[0] == '.') && (name[1] == '\0')) { + return 1; + } + + for (i = 0; ; i++) { + switch ((*gen)(channel, tab, ntab, i, &dir)) { + case 0: + /* Intentional fall-through */ + case -1: + return -1; + case 1: + if (strncmp(name, dir.name, NAMELEN) != 0) { + continue; + } + channel->qid = dir.qid; + return 1; + } + } +} + +/******************************************************************************* + * This is a helper function which exposes the content of a directory, element + * by element. It is meant to be called until the end of the directory is + * reached or an error occurs. + * It returns -1 on error, 0 on end of directory and 1 when a new file is found. + ******************************************************************************/ +int dirread(chan_t *channel, dir_t *dir, const dirtab_t *tab, + int ntab, devgen_t *gen) +{ + int i, ret; + + if ((channel == NULL) || (dir == NULL) || (gen == NULL)) { + return -1; + } + + i = channel->offset/sizeof(dir_t); + ret = (*gen)(channel, tab, ntab, i, dir); + if (ret == 1) { + channel->offset += sizeof(dir_t); + } + + return ret; +} + +/******************************************************************************* + * This function sets the elements of dir. + ******************************************************************************/ +void make_dir_entry(chan_t *channel, dir_t *dir, + const char *name, long length, qid_t qid, unsigned int mode) +{ + if ((channel == NULL) || (dir == NULL) || (name == NULL)) { + return; + } + + strlcpy(dir->name, name, sizeof(dir->name)); + dir->length = length; + dir->qid = qid; + dir->mode = mode; + + if ((qid & CHDIR) != 0) { + dir->mode |= O_DIR; + } + + dir->index = channel->index; + dir->dev = channel->dev; +} + +/******************************************************************************* + * This function is the default implementation of the internal driver gen + * function. + * It copies and formats the information of the nth element of tab into dir. + ******************************************************************************/ +int devgen(chan_t *channel, const dirtab_t *tab, int ntab, int n, dir_t *dir) +{ + const dirtab_t *dp; + + if ((channel == NULL) || (dir == NULL) || (tab == NULL) || + (n >= ntab)) { + return 0; + } + + dp = &tab[n]; + make_dir_entry(channel, dir, dp->name, dp->length, dp->qid, dp->perm); + return 1; +} + +/******************************************************************************* + * This function returns a file descriptor identifying the channel associated to + * the given path. + ******************************************************************************/ +int open(const char *path, int mode) +{ + chan_t *channel; + + if (path == NULL) { + return -1; + } + + if (is_valid_mode(mode) == false) { + return -1; + } + + channel = path_to_channel(path, mode); + + return channel_to_fd(channel); +} + +/******************************************************************************* + * This function closes the channel identified by the file descriptor fd. + ******************************************************************************/ +int close(int fd) +{ + chan_t *channel; + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + channel_close(channel); + return 0; +} + +/******************************************************************************* + * This function is the default implementation of the driver stat function. + * It goes through all the elements of tab using the gen function until a match + * is found with file. + * If a match is found, dir contains the information file. + ******************************************************************************/ +int devstat(chan_t *dirc, const char *file, dir_t *dir, + const dirtab_t *tab, int ntab, devgen_t *gen) +{ + int i, r = 0; + chan_t *c, *mnt; + + if ((dirc == NULL) || (dir == NULL) || (gen == NULL)) { + return -1; + } + + c = path_to_channel(file, O_STAT); + if (c == NULL) { + return -1; + } + + for (i = 0; ; i++) { + switch ((*gen)(dirc, tab, ntab, i, dir)) { + case 0: + /* Intentional fall-through */ + case -1: + r = -1; + goto leave; + case 1: + mnt = mount_point_to_channel(dir->index, dir->qid); + if (mnt != NULL) { + dir->qid = mnt->qid; + dir->index = mnt->index; + } + + if ((dir->qid != c->qid) || (dir->index != c->index)) { + continue; + } + + goto leave; + } + } + +leave: + channel_close(c); + return r; +} + +/******************************************************************************* + * This function calls the stat function of the driver associated to the parent + * directory of the file in path. + * The result is stored in dir. + ******************************************************************************/ +int stat(const char *path, dir_t *dir) +{ + int r; + size_t len; + chan_t *channel; + char *p, dirname[PATHLEN]; + + if ((path == NULL) || (dir == NULL)) { + return -1; + } + + len = strlen(path); + if ((len + 1) > sizeof(dirname)) { + return -1; + } + + memcpy(dirname, path, len); + for (p = dirname + len; p > dirname; --p) { + if (*p != '/') { + break; + } + } + + p = memrchr(dirname, '/', p - dirname); + if (p == NULL) { + return -1; + } + + dirname[p - dirname + 1] = '\0'; + + channel = path_to_channel(dirname, O_STAT); + if (channel == NULL) { + return -1; + } + + r = devtab[channel->index]->stat(channel, path, dir); + channel_close(channel); + + return r; +} + +/******************************************************************************* + * This function calls the read function of the driver associated to fd. + * It fills buf with at most n bytes. + * It returns the number of bytes that were actually read. + ******************************************************************************/ +int read(int fd, void *buf, int n) +{ + chan_t *channel; + + if (buf == NULL) { + return -1; + } + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if (((channel->qid & CHDIR) != 0) && (n < sizeof(dir_t))) { + return -1; + } + + return devtab[channel->index]->read(channel, buf, n); +} + +/******************************************************************************* + * This function calls the write function of the driver associated to fd. + * It writes at most n bytes of buf. + * It returns the number of bytes that were actually written. + ******************************************************************************/ +int write(int fd, void *buf, int n) +{ + chan_t *channel; + + if (buf == NULL) { + return -1; + } + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if ((channel->qid & CHDIR) != 0) { + return -1; + } + + return devtab[channel->index]->write(channel, buf, n); +} + +/******************************************************************************* + * This function calls the seek function of the driver associated to fd. + * It applies the offset off according to the strategy whence. + ******************************************************************************/ +int seek(int fd, long off, int whence) +{ + chan_t *channel; + + channel = fd_to_channel(fd); + if (channel == NULL) { + return -1; + } + + if ((channel->qid & CHDIR) != 0) { + return -1; + } + + return devtab[channel->index]->seek(channel, off, whence); +} + +/******************************************************************************* + * This function is the default error implementation of the driver mount + * function. + ******************************************************************************/ +chan_t *deverrmount(chan_t *channel, const char *spec) +{ + return NULL; +} + +/******************************************************************************* + * This function is the default error implementation of the driver write + * function. + ******************************************************************************/ +int deverrwrite(chan_t *channel, void *buf, int n) +{ + return -1; +} + +/******************************************************************************* + * This function is the default error implementation of the driver seek + * function. + ******************************************************************************/ +int deverrseek(chan_t *channel, long off, int whence) +{ + return -1; +} + +/******************************************************************************* + * This function is the default implementation of the driver seek function. + * It applies the offset off according to the strategy whence to the channel c. + ******************************************************************************/ +int devseek(chan_t *channel, long off, int whence) +{ + switch (whence) { + case KSEEK_SET: + channel->offset = off; + break; + case KSEEK_CUR: + channel->offset += off; + break; + case KSEEK_END: + /* Not implemented */ + return -1; + } + + return 0; +} + +/******************************************************************************* + * This function registers the channel associated to the path new as a mount + * point for the channel c. + ******************************************************************************/ +static int add_mount_point(chan_t *channel, const char *new) +{ + int i; + chan_t *cn; + struct mount_point *mp; + + if (new == NULL) { + goto err0; + } + + cn = path_to_channel(new, O_READ); + if (cn == NULL) { + goto err0; + } + + if ((cn->qid & CHDIR) == 0) { + goto err1; + } + + for (i = NR_MOUNT_POINTS - 1; i >= 0; i--) { + mp = &mount_points[i]; + if (mp->new == NULL) { + break; + } + } + + if (i < 0) { + goto err1; + } + + mp->new = cn; + mp->old = channel; + + return 0; + +err1: + channel_close(cn); +err0: + return -1; +} + +/******************************************************************************* + * This function registers the path new as a mount point for the path old. + ******************************************************************************/ +int bind(const char *old, const char *new) +{ + chan_t *channel; + + channel = path_to_channel(old, O_BIND); + if (channel == NULL) { + return -1; + } + + if (add_mount_point(channel, new) < 0) { + channel_close(channel); + return -1; + } + + return 0; +} + +/******************************************************************************* + * This function calls the mount function of the driver associated to the path + * srv. + * It mounts the path srv on the path where. + ******************************************************************************/ +int mount(const char *srv, const char *where, const char *spec) +{ + chan_t *channel, *mount_point_chan; + int ret; + + channel = path_to_channel(srv, O_RDWR); + if (channel == NULL) { + goto err0; + } + + mount_point_chan = devtab[channel->index]->mount(channel, spec); + if (mount_point_chan == NULL) { + goto err1; + } + + ret = add_mount_point(mount_point_chan, where); + if (ret < 0) { + goto err2; + } + + channel_close(channel); + + return 0; + +err2: + channel_close(mount_point_chan); +err1: + channel_close(channel); +err0: + return -1; +} + +/******************************************************************************* + * This function initializes the device environment. + * It creates the '/' channel. + * It links the device drivers to the physical drivers. + ******************************************************************************/ +void debugfs_init(void) +{ + chan_t *channel, *cloned_channel; + + for (channel = fdset; channel < &fdset[NR_CHANS]; channel++) { + channel_clear(channel); + } + + channel = devattach('/', 0); + if (channel == NULL) { + panic(); + } + + cloned_channel = clone(channel, &slash_channel); + if (cloned_channel == NULL) { + panic(); + } + + channel_close(channel); + devlink(); +} + +__dead2 void devpanic(const char *cause) +{ + panic(); +} diff --git a/arm-trusted-firmware/lib/debugfs/dev.h b/arm-trusted-firmware/lib/debugfs/dev.h new file mode 100644 index 0000000..c142651 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/dev.h @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEV_H +#define DEV_H + +#include +#include +#include + +/* FIXME: need configurability */ +#define NR_CHANS 10 +#define NR_CONSS 1 +#define NR_BINDS 4 +#define NR_FILES 18 + +#define NODEV 255 +#define CHDIR (1 << 15) + +#define SYNCDEV 0 +#define SYNCALL 1 + +typedef struct dev dev_t; +typedef struct chan chan_t; +typedef struct dirtab dirtab_t; +typedef int devgen_t(chan_t *, const dirtab_t *, int, int, dir_t *); +typedef struct attr attr_t; + +enum { + DEV_ROOT_QROOT, + DEV_ROOT_QDEV, + DEV_ROOT_QFIP, + DEV_ROOT_QBLOBS, + DEV_ROOT_QBLOBCTL, + DEV_ROOT_QPSCI +}; + +/******************************************************************************* + * This structure contains the necessary information to represent a directory + * of the filesystem. + ******************************************************************************/ +struct dirtab { + char name[NAMELEN]; + qid_t qid; + long length; + unsigned char perm; + void *data; +}; + +/******************************************************************************* + * This structure defines the interface of device drivers. + * Each driver must implement a subset of those functions. + * It is possible to redirect to default implementations defined in dev.c. + ******************************************************************************/ +/* FIXME: comments for the callbacks */ +struct dev { + char id; + int (*stat)(chan_t *c, const char *file, dir_t *dir); + int (*walk)(chan_t *c, const char *name); + int (*read)(chan_t *c, void *buf, int n); + int (*write)(chan_t *c, void *buf, int n); + int (*seek)(chan_t *c, long off, int whence); + chan_t *(*clone)(chan_t *c, chan_t *nc); + chan_t *(*attach)(int id, int dev); + chan_t *(*mount)(chan_t *c, const char *spec); +}; + +/******************************************************************************* + * This structure defines the channel structure. + * A channel is a handle on an element of the filesystem. + ******************************************************************************/ +struct chan { + long offset; + qid_t qid; + unsigned char index; /* device index in devtab */ + unsigned char dev; + unsigned char mode; +}; + +/******************************************************************************* + * This structure defines an abstract argument passed to physical drivers from + * the configuration file. + ******************************************************************************/ +struct attr { + char *key; + char *value; +}; + +chan_t *path_to_channel(const char *path, int mode); +chan_t *clone(chan_t *c, chan_t *nc); +chan_t *attach(int id, int dev); +void channel_close(chan_t *c); +int buf_to_channel(chan_t *c, void *dst, void *src, int nbytes, long len); +int dirread(chan_t *c, dir_t *dir, const dirtab_t *tab, + int ntab, devgen_t *gen); +void make_dir_entry(chan_t *c, dir_t *dir, const char *name, long length, + qid_t qid, unsigned int mode); +void devlink(void); + +chan_t *devattach(int id, int dev); +int devseek(chan_t *c, long off, int whence); +chan_t *devclone(chan_t *c, chan_t *nc); +int devgen(chan_t *c, const dirtab_t *tab, int ntab, int n, dir_t *dir); +int devwalk(chan_t *c, const char *name, const dirtab_t *tab, int ntab, + devgen_t *gen); +int devstat(chan_t *dirc, const char *file, dir_t *dir, + const dirtab_t *tab, int ntab, devgen_t *gen); + +chan_t *deverrmount(chan_t *c, const char *spec); +int deverrwrite(chan_t *c, void *buf, int n); +int deverrseek(chan_t *c, long off, int whence); + +extern dev_t *const devtab[]; + +void __dead2 devpanic(const char *cause); + +#endif /* DEV_H */ diff --git a/arm-trusted-firmware/lib/debugfs/devc.c b/arm-trusted-firmware/lib/debugfs/devc.c new file mode 100644 index 0000000..1099a85 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devc.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +typedef struct dev dev_t; + +extern dev_t rootdevtab; +extern dev_t fipdevtab; + +dev_t *const devtab[] = { + &rootdevtab, + &fipdevtab, + 0 +}; + +void devlink(void) +{ +} diff --git a/arm-trusted-firmware/lib/debugfs/devfip.c b/arm-trusted-firmware/lib/debugfs/devfip.c new file mode 100644 index 0000000..85e6403 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devfip.c @@ -0,0 +1,321 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "dev.h" + +#define NR_FIPS 1 +#define STOC_HEADER (sizeof(fip_toc_header_t)) +#define STOC_ENTRY (sizeof(fip_toc_entry_t)) + +struct fipfile { + chan_t *c; + long offset[NR_FILES]; + long size[NR_FILES]; +}; + +struct fip_entry { + uuid_t uuid; + long long offset_address; + long long size; + long long flags; +}; + +struct uuidnames { + const char name[NAMELEN]; + const uuid_t uuid; +}; + +/******************************************************************************* + * This array links the FIP file names to their UUID. + * The elements are ordered according to the image number stored in + * tbbr_img_def.h, starting at index 1. + * + * TODO: this name to uuid binding will preferably be done using + * the coming Property Access Layer / Firmware CONFiguration feature. + ******************************************************************************/ +static const struct uuidnames uuidnames[] = { + {"", { {0}, {0}, {0}, 0, 0, {0} } }, + {"bl2.bin", UUID_TRUSTED_BOOT_FIRMWARE_BL2}, + {"scp-bl2.bin", UUID_SCP_FIRMWARE_SCP_BL2}, + {"bl31.bin", UUID_EL3_RUNTIME_FIRMWARE_BL31}, + {"bl32.bin", UUID_SECURE_PAYLOAD_BL32}, + {"bl33.bin", UUID_NON_TRUSTED_FIRMWARE_BL33}, + {"tb-fw.crt", UUID_TRUSTED_BOOT_FW_CERT}, + {"trstd-k.crt", UUID_TRUSTED_KEY_CERT}, + {"scp-fw-k.crt", UUID_SCP_FW_KEY_CERT}, + {"soc-fw-k.crt", UUID_SOC_FW_KEY_CERT}, + {"tos-fw-k.crt", UUID_TRUSTED_OS_FW_KEY_CERT}, + {"nt-fw-k.crt", UUID_NON_TRUSTED_FW_KEY_CERT}, + {"scp-fw-c.crt", UUID_SCP_FW_CONTENT_CERT}, + {"soc-fw-c.crt", UUID_SOC_FW_CONTENT_CERT}, + {"tos-fw-c.crt", UUID_TRUSTED_OS_FW_CONTENT_CERT}, + {"nt-fw-c.crt", UUID_NON_TRUSTED_FW_CONTENT_CERT}, + { }, + {"fwu.crt", UUID_TRUSTED_FWU_CERT}, + {"scp-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U}, + {"bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_BL2U}, + {"ns-bl2u.bin", UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U}, + {"bl32-xtr1.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA1}, + {"bl32-xtr2.bin", UUID_SECURE_PAYLOAD_BL32_EXTRA2}, + {"hw.cfg", UUID_HW_CONFIG}, + {"tb-fw.cfg", UUID_TB_FW_CONFIG}, + {"soc-fw.cfg", UUID_SOC_FW_CONFIG}, + {"tos-fw.cfg", UUID_TOS_FW_CONFIG}, + {"nt-fw.cfg", UUID_NT_FW_CONFIG}, + {"fw.cfg", UUID_FW_CONFIG}, + {"rot-k.crt", UUID_ROT_KEY_CERT}, + {"nt-k.crt", UUID_NON_TRUSTED_WORLD_KEY_CERT}, + {"sip-sp.crt", UUID_SIP_SECURE_PARTITION_CONTENT_CERT}, + {"plat-sp.crt", UUID_PLAT_SECURE_PARTITION_CONTENT_CERT} +}; + +/******************************************************************************* + * This array contains all the available FIP files. + ******************************************************************************/ +static struct fipfile archives[NR_FIPS]; + +/******************************************************************************* + * This variable stores the current number of registered FIP files. + ******************************************************************************/ +static int nfips; + +/******************************************************************************* + * This function parses the ToC of the FIP. + ******************************************************************************/ +static int get_entry(chan_t *c, struct fip_entry *entry) +{ + int n; + + n = devtab[c->index]->read(c, entry, sizeof(struct fip_entry)); + if (n <= 0) { + return n; + } + + if (n != sizeof(struct fip_entry)) { + return -1; + } + + if (entry->size == 0) { + return 0; + } + + return 1; +} + +/******************************************************************************* + * This function exposes the FIP images as files. + ******************************************************************************/ +static int fipgen(chan_t *c, const dirtab_t *tab, int ntab, int n, dir_t *dir) +{ + int i, r; + long off; + chan_t nc; + struct fip_entry entry; + struct fipfile *fip; + static const char unk[] = "unknown"; + + if (c->dev >= nfips) { + panic(); + } + + if (clone(archives[c->dev].c, &nc) == NULL) { + panic(); + } + + fip = &archives[nc.dev]; + + off = STOC_HEADER; + for (i = 0; i <= n; i++) { + if (fip->offset[i] == -1) { + return 0; + } + + if (devtab[nc.index]->seek(&nc, off, KSEEK_SET) < 0) { + return -1; + } + + r = get_entry(&nc, &entry); + if (r <= 0) { + return r; + } + + off += sizeof(entry); + } + + for (i = 1; i < NELEM(uuidnames); i++) { + if (memcmp(&uuidnames[i].uuid, + &entry.uuid, sizeof(uuid_t)) == 0) { + break; + } + } + + if (i < NELEM(uuidnames)) { + make_dir_entry(c, dir, uuidnames[i].name, + entry.size, n, O_READ); + } else { + // TODO: set name depending on uuid node value + make_dir_entry(c, dir, unk, entry.size, n, O_READ); + } + + return 1; +} + +static int fipwalk(chan_t *c, const char *name) +{ + return devwalk(c, name, NULL, 0, fipgen); +} + +static int fipstat(chan_t *c, const char *file, dir_t *dir) +{ + return devstat(c, file, dir, NULL, 0, fipgen); +} + +/******************************************************************************* + * This function copies at most n bytes of the FIP image referred by c into + * buf. + ******************************************************************************/ +static int fipread(chan_t *c, void *buf, int n) +{ + long off; + chan_t cs; + struct fipfile *fip; + long size; + + /* Only makes sense when using debug language */ + assert(c->qid != CHDIR); + + if ((c->dev >= nfips) || ((c->qid & CHDIR) != 0)) { + panic(); + } + + fip = &archives[c->dev]; + + if ((c->qid >= NR_FILES) || (fip->offset[c->qid] < 0)) { + panic(); + } + + if (clone(fip->c, &cs) == NULL) { + panic(); + } + + size = fip->size[c->qid]; + if (c->offset >= size) { + return 0; + } + + if (n < 0) { + return -1; + } + + if (n > (size - c->offset)) { + n = size - c->offset; + } + + off = fip->offset[c->qid] + c->offset; + if (devtab[cs.index]->seek(&cs, off, KSEEK_SET) < 0) { + return -1; + } + + n = devtab[cs.index]->read(&cs, buf, n); + if (n > 0) { + c->offset += n; + } + + return n; +} + +/******************************************************************************* + * This function parses the FIP spec and registers its images in order to + * expose them as files in the driver namespace. + * It acts as an initialization function for the FIP driver. + * It returns a pointer to the newly created channel. + ******************************************************************************/ +static chan_t *fipmount(chan_t *c, const char *spec) +{ + int r, n, t; + chan_t *cspec; + uint32_t hname; + struct fip_entry entry; + struct fipfile *fip; + dir_t dir; + + if (nfips == NR_FIPS) { + return NULL; + } + + fip = &archives[nfips]; + + for (n = 0; n < NR_FILES; n++) { + fip->offset[n] = -1; + } + + cspec = path_to_channel(spec, O_READ); + if (cspec == NULL) { + return NULL; + } + + fip->c = cspec; + + r = devtab[cspec->index]->read(cspec, &hname, sizeof(hname)); + if (r < 0) { + goto err; + } + + if ((r != sizeof(hname)) || (hname != TOC_HEADER_NAME)) { + goto err; + } + + if (stat(spec, &dir) < 0) { + goto err; + } + + t = cspec->index; + if (devtab[t]->seek(cspec, STOC_HEADER, KSEEK_SET) < 0) { + goto err; + } + + for (n = 0; n < NR_FILES; n++) { + switch (get_entry(cspec, &entry)) { + case 0: + return attach('F', nfips++); + case -1: + goto err; + default: + if ((entry.offset_address + entry.size) > dir.length) { + goto err; + } + + fip->offset[n] = entry.offset_address; + fip->size[n] = entry.size; + break; + } + } + +err: + channel_close(cspec); + return NULL; +} + +const dev_t fipdevtab = { + .id = 'F', + .stat = fipstat, + .clone = devclone, + .attach = devattach, + .walk = fipwalk, + .read = fipread, + .write = deverrwrite, + .mount = fipmount, + .seek = devseek +}; + diff --git a/arm-trusted-firmware/lib/debugfs/devroot.c b/arm-trusted-firmware/lib/debugfs/devroot.c new file mode 100644 index 0000000..9dd6c92 --- /dev/null +++ b/arm-trusted-firmware/lib/debugfs/devroot.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "blobs.h" +#include "dev.h" + +/******************************************************************************* + * This array contains the directories available from the root directory. + ******************************************************************************/ +static const dirtab_t dirtab[] = { + {"dev", CHDIR | DEV_ROOT_QDEV, 0, O_READ}, + {"blobs", CHDIR | DEV_ROOT_QBLOBS, 0, O_READ}, + {"fip", CHDIR | DEV_ROOT_QFIP, 0, O_READ} +}; + +static const dirtab_t devfstab[] = { +}; + +/******************************************************************************* + * This function exposes the elements of the root directory. + * It also exposes the content of the dev and blobs directories. + ******************************************************************************/ +static int rootgen(chan_t *channel, const dirtab_t *tab, int ntab, + int n, dir_t *dir) +{ + switch (channel->qid & ~CHDIR) { + case DEV_ROOT_QROOT: + tab = dirtab; + ntab = NELEM(dirtab); + break; + case DEV_ROOT_QDEV: + tab = devfstab; + ntab = NELEM(devfstab); + break; + case DEV_ROOT_QBLOBS: + tab = blobtab; + ntab = NELEM(blobtab); + break; + default: + return 0; + } + + return devgen(channel, tab, ntab, n, dir); +} + +static int rootwalk(chan_t *channel, const char *name) +{ + return devwalk(channel, name, NULL, 0, rootgen); +} + +/******************************************************************************* + * This function copies at most n bytes from the element referred by c into buf. + ******************************************************************************/ +static int rootread(chan_t *channel, void *buf, int size) +{ + const dirtab_t *dp; + dir_t *dir; + + if ((channel->qid & CHDIR) != 0) { + if (size < sizeof(dir_t)) { + return -1; + } + + dir = buf; + return dirread(channel, dir, NULL, 0, rootgen); + } + + /* Only makes sense when using debug language */ + assert(channel->qid != DEV_ROOT_QBLOBCTL); + + dp = &blobtab[channel->qid - DEV_ROOT_QBLOBCTL]; + return buf_to_channel(channel, buf, dp->data, size, dp->length); +} + +static int rootstat(chan_t *channel, const char *file, dir_t *dir) +{ + return devstat(channel, file, dir, NULL, 0, rootgen); +} + +const dev_t rootdevtab = { + .id = '/', + .stat = rootstat, + .clone = devclone, + .attach = devattach, + .walk = rootwalk, + .read = rootread, + .write = deverrwrite, + .mount = deverrmount, + .seek = devseek +}; diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c b/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c new file mode 100644 index 0000000..3ef378c --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload manages the context(s) corresponding to the secure state. + * It also uses this library to get access to the non-secure + * state cpu context pointers. + ******************************************************************************/ +void cm_init(void) +{ + /* + * The context management library has only global data to initialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * The following function initializes the cpu_context 'ctx' for + * first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + * + * The security state to initialize is determined by the SECURE attribute + * of the entry_point_info. + * + * The EE and ST attributes are used to configure the endianness and secure + * timer availability for the new execution context. + * + * To prepare the register state for entry call cm_prepare_el3_exit() and + * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to + * cm_el1_sysregs_context_restore(). + ******************************************************************************/ +void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) +{ + unsigned int security_state; + uint32_t scr, sctlr; + regs_t *reg_ctx; + + assert(ctx != NULL); + + security_state = GET_SECURITY_STATE(ep->h.attr); + + /* Clear any residual register values from the context */ + zeromem(ctx, sizeof(*ctx)); + + reg_ctx = get_regs_ctx(ctx); + + /* + * Base the context SCR on the current value, adjust for entry point + * specific requirements + */ + scr = read_scr(); + scr &= ~(SCR_NS_BIT | SCR_HCE_BIT); + + if (security_state != SECURE) + scr |= SCR_NS_BIT; + + if (security_state != SECURE) { + /* + * Set up SCTLR for the Non-secure context. + * + * SCTLR.EE: Endianness is taken from the entrypoint attributes. + * + * SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as + * required by PSCI specification) + * + * Set remaining SCTLR fields to their architecturally defined + * values. Some fields reset to an IMPLEMENTATION DEFINED value: + * + * SCTLR.TE: Set to zero so that exceptions to an Exception + * Level executing at PL1 are taken to A32 state. + * + * SCTLR.V: Set to zero to select the normal exception vectors + * with base address held in VBAR. + */ + assert(((ep->spsr >> SPSR_E_SHIFT) & SPSR_E_MASK) == + (EP_GET_EE(ep->h.attr) >> EP_EE_SHIFT)); + + sctlr = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U; + sctlr |= (SCTLR_RESET_VAL & ~(SCTLR_TE_BIT | SCTLR_V_BIT)); + write_ctx_reg(reg_ctx, CTX_NS_SCTLR, sctlr); + } + + /* + * The target exception level is based on the spsr mode requested. If + * execution is requested to hyp mode, HVC is enabled via SCR.HCE. + */ + if (GET_M32(ep->spsr) == MODE32_hyp) + scr |= SCR_HCE_BIT; + + /* + * Store the initialised values for SCTLR and SCR in the cpu_context. + * The Hyp mode registers are not part of the saved context and are + * set-up in cm_prepare_el3_exit(). + */ + write_ctx_reg(reg_ctx, CTX_SCR, scr); + write_ctx_reg(reg_ctx, CTX_LR, ep->pc); + write_ctx_reg(reg_ctx, CTX_SPSR, ep->spsr); + + /* + * Store the r0-r3 value from the entrypoint into the context + * Use memcpy as we are in control of the layout of the structures + */ + memcpy((void *)reg_ctx, (void *)&ep->args, sizeof(aapcs32_params_t)); +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Non-secure world. + * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise + * it is zero. + ******************************************************************************/ +static void enable_extensions_nonsecure(bool el2_unused) +{ +#if IMAGE_BL32 +#if ENABLE_AMU + amu_enable(el2_unused); +#endif + +#if ENABLE_SYS_REG_TRACE_FOR_NS + sys_reg_trace_enable(); +#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ + +#if ENABLE_TRF_FOR_NS + trf_enable(); +#endif /* ENABLE_TRF_FOR_NS */ +#endif +} + +/******************************************************************************* + * The following function initializes the cpu_context for a CPU specified by + * its `cpu_idx` for first use, and sets the initial entrypoint state as + * specified by the entry_point_info structure. + ******************************************************************************/ +void cm_init_context_by_index(unsigned int cpu_idx, + const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * The following function initializes the cpu_context for the current CPU + * for first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + ******************************************************************************/ +void cm_init_my_context(const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * Prepare the CPU system registers for first entry into secure or normal world + * + * If execution is requested to hyp mode, HSCTLR is initialized + * If execution is requested to non-secure PL1, and the CPU supports + * HYP mode then HYP mode is disabled by configuring all necessary HYP mode + * registers. + ******************************************************************************/ +void cm_prepare_el3_exit(uint32_t security_state) +{ + uint32_t hsctlr, scr; + cpu_context_t *ctx = cm_get_context(security_state); + bool el2_unused = false; + + assert(ctx != NULL); + + if (security_state == NON_SECURE) { + scr = read_ctx_reg(get_regs_ctx(ctx), CTX_SCR); + if ((scr & SCR_HCE_BIT) != 0U) { + /* Use SCTLR value to initialize HSCTLR */ + hsctlr = read_ctx_reg(get_regs_ctx(ctx), + CTX_NS_SCTLR); + hsctlr |= HSCTLR_RES1; + /* Temporarily set the NS bit to access HSCTLR */ + write_scr(read_scr() | SCR_NS_BIT); + /* + * Make sure the write to SCR is complete so that + * we can access HSCTLR + */ + isb(); + write_hsctlr(hsctlr); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } else if ((read_id_pfr1() & + (ID_PFR1_VIRTEXT_MASK << ID_PFR1_VIRTEXT_SHIFT)) != 0U) { + el2_unused = true; + + /* + * Set the NS bit to access NS copies of certain banked + * registers + */ + write_scr(read_scr() | SCR_NS_BIT); + isb(); + + /* + * Hyp / PL2 present but unused, need to disable safely. + * HSCTLR can be ignored in this case. + * + * Set HCR to its architectural reset value so that + * Non-secure operations do not trap to Hyp mode. + */ + write_hcr(HCR_RESET_VAL); + + /* + * Set HCPTR to its architectural reset value so that + * Non-secure access from EL1 or EL0 to trace and to + * Advanced SIMD and floating point functionality does + * not trap to Hyp mode. + */ + write_hcptr(HCPTR_RESET_VAL); + + /* + * Initialise CNTHCTL. All fields are architecturally + * UNKNOWN on reset and are set to zero except for + * field(s) listed below. + * + * CNTHCTL.PL1PCEN: Disable traps to Hyp mode of + * Non-secure EL0 and EL1 accessed to the physical + * timer registers. + * + * CNTHCTL.PL1PCTEN: Disable traps to Hyp mode of + * Non-secure EL0 and EL1 accessed to the physical + * counter registers. + */ + write_cnthctl(CNTHCTL_RESET_VAL | + PL1PCEN_BIT | PL1PCTEN_BIT); + + /* + * Initialise CNTVOFF to zero as it resets to an + * IMPLEMENTATION DEFINED value. + */ + write64_cntvoff(0); + + /* + * Set VPIDR and VMPIDR to match MIDR_EL1 and MPIDR + * respectively. + */ + write_vpidr(read_midr()); + write_vmpidr(read_mpidr()); + + /* + * Initialise VTTBR, setting all fields rather than + * relying on the hw. Some fields are architecturally + * UNKNOWN at reset. + * + * VTTBR.VMID: Set to zero which is the architecturally + * defined reset value. Even though EL1&0 stage 2 + * address translation is disabled, cache maintenance + * operations depend on the VMID. + * + * VTTBR.BADDR: Set to zero as EL1&0 stage 2 address + * translation is disabled. + */ + write64_vttbr(VTTBR_RESET_VAL & + ~((VTTBR_VMID_MASK << VTTBR_VMID_SHIFT) + | (VTTBR_BADDR_MASK << VTTBR_BADDR_SHIFT))); + + /* + * Initialise HDCR, setting all the fields rather than + * relying on hw. + * + * HDCR.HPMN: Set to value of PMCR.N which is the + * architecturally-defined reset value. + * + * HDCR.HLP: Set to one so that event counter + * overflow, that is recorded in PMOVSCLR[0-30], + * occurs on the increment that changes + * PMEVCNTR[63] from 1 to 0, when ARMv8.5-PMU is + * implemented. This bit is RES0 in versions of the + * architecture earlier than ARMv8.5, setting it to 1 + * doesn't have any effect on them. + * This bit is Reserved, UNK/SBZP in ARMv7. + * + * HDCR.HPME: Set to zero to disable EL2 Event + * counters. + */ +#if (ARM_ARCH_MAJOR > 7) + write_hdcr((HDCR_RESET_VAL | HDCR_HLP_BIT | + ((read_pmcr() & PMCR_N_BITS) >> + PMCR_N_SHIFT)) & ~HDCR_HPME_BIT); +#else + write_hdcr((HDCR_RESET_VAL | + ((read_pmcr() & PMCR_N_BITS) >> + PMCR_N_SHIFT)) & ~HDCR_HPME_BIT); +#endif + /* + * Set HSTR to its architectural reset value so that + * access to system registers in the cproc=1111 + * encoding space do not trap to Hyp mode. + */ + write_hstr(HSTR_RESET_VAL); + /* + * Set CNTHP_CTL to its architectural reset value to + * disable the EL2 physical timer and prevent timer + * interrupts. Some fields are architecturally UNKNOWN + * on reset and are set to zero. + */ + write_cnthp_ctl(CNTHP_CTL_RESET_VAL); + isb(); + + write_scr(read_scr() & ~SCR_NS_BIT); + isb(); + } + enable_extensions_nonsecure(el2_unused); + } +} diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S b/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S new file mode 100644 index 0000000..bdad2c1 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .globl _cpu_data + .globl _cpu_data_by_index + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data(void) + * + * Return the cpu_data structure for the current CPU. + * ----------------------------------------------------------------- + */ +func _cpu_data + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + bl plat_my_core_pos + pop {r12, lr} + b _cpu_data_by_index +endfunc _cpu_data + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index) + * + * Return the cpu_data structure for the CPU with given linear index + * + * This can be called without a valid stack. + * clobbers: r0, r1 + * ----------------------------------------------------------------- + */ +func _cpu_data_by_index + mov_imm r1, CPU_DATA_SIZE + mul r0, r0, r1 + ldr r1, =percpu_data + add r0, r0, r1 + bx lr +endfunc _cpu_data_by_index diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S b/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S new file mode 100644 index 0000000..c1c0612 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/context.S @@ -0,0 +1,1014 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#if CTX_INCLUDE_EL2_REGS + .global el2_sysregs_context_save + .global el2_sysregs_context_restore +#endif + + .global el1_sysregs_context_save + .global el1_sysregs_context_restore +#if CTX_INCLUDE_FPREGS + .global fpregs_context_save + .global fpregs_context_restore +#endif + .global prepare_el3_entry + .global restore_gp_pmcr_pauth_regs + .global save_and_update_ptw_el1_sys_regs + .global el3_exit + +#if CTX_INCLUDE_EL2_REGS + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x16 (temporary caller-saved registers) + * to save EL2 system register context. It assumes that + * 'x0' is pointing to a 'el2_sys_regs' structure where + * the register context will be saved. + * + * The following registers are not added. + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * ICH_LR_EL2 + * ----------------------------------------------------- + */ +func el2_sysregs_context_save + mrs x9, actlr_el2 + mrs x10, afsr0_el2 + stp x9, x10, [x0, #CTX_ACTLR_EL2] + + mrs x11, afsr1_el2 + mrs x12, amair_el2 + stp x11, x12, [x0, #CTX_AFSR1_EL2] + + mrs x13, cnthctl_el2 + mrs x14, cntvoff_el2 + stp x13, x14, [x0, #CTX_CNTHCTL_EL2] + + mrs x15, cptr_el2 + str x15, [x0, #CTX_CPTR_EL2] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x16, dbgvcr32_el2 + str x16, [x0, #CTX_DBGVCR32_EL2] +#endif + + mrs x9, elr_el2 + mrs x10, esr_el2 + stp x9, x10, [x0, #CTX_ELR_EL2] + + mrs x11, far_el2 + mrs x12, hacr_el2 + stp x11, x12, [x0, #CTX_FAR_EL2] + + mrs x13, hcr_el2 + mrs x14, hpfar_el2 + stp x13, x14, [x0, #CTX_HCR_EL2] + + mrs x15, hstr_el2 + mrs x16, ICC_SRE_EL2 + stp x15, x16, [x0, #CTX_HSTR_EL2] + + mrs x9, ICH_HCR_EL2 + mrs x10, ICH_VMCR_EL2 + stp x9, x10, [x0, #CTX_ICH_HCR_EL2] + + mrs x11, mair_el2 + mrs x12, mdcr_el2 + stp x11, x12, [x0, #CTX_MAIR_EL2] + +#if ENABLE_SPE_FOR_LOWER_ELS + mrs x13, PMSCR_EL2 + str x13, [x0, #CTX_PMSCR_EL2] +#endif + mrs x14, sctlr_el2 + str x14, [x0, #CTX_SCTLR_EL2] + + mrs x15, spsr_el2 + mrs x16, sp_el2 + stp x15, x16, [x0, #CTX_SPSR_EL2] + + mrs x9, tcr_el2 + mrs x10, tpidr_el2 + stp x9, x10, [x0, #CTX_TCR_EL2] + + mrs x11, ttbr0_el2 + mrs x12, vbar_el2 + stp x11, x12, [x0, #CTX_TTBR0_EL2] + + mrs x13, vmpidr_el2 + mrs x14, vpidr_el2 + stp x13, x14, [x0, #CTX_VMPIDR_EL2] + + mrs x15, vtcr_el2 + mrs x16, vttbr_el2 + stp x15, x16, [x0, #CTX_VTCR_EL2] + +#if CTX_INCLUDE_MTE_REGS + mrs x9, TFSR_EL2 + str x9, [x0, #CTX_TFSR_EL2] +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + mrs x10, MPAM2_EL2 + str x10, [x0, #CTX_MPAM2_EL2] + + mrs x11, MPAMHCR_EL2 + mrs x12, MPAMVPM0_EL2 + stp x11, x12, [x0, #CTX_MPAMHCR_EL2] + + mrs x13, MPAMVPM1_EL2 + mrs x14, MPAMVPM2_EL2 + stp x13, x14, [x0, #CTX_MPAMVPM1_EL2] + + mrs x15, MPAMVPM3_EL2 + mrs x16, MPAMVPM4_EL2 + stp x15, x16, [x0, #CTX_MPAMVPM3_EL2] + + mrs x9, MPAMVPM5_EL2 + mrs x10, MPAMVPM6_EL2 + stp x9, x10, [x0, #CTX_MPAMVPM5_EL2] + + mrs x11, MPAMVPM7_EL2 + mrs x12, MPAMVPMV_EL2 + stp x11, x12, [x0, #CTX_MPAMVPM7_EL2] +#endif + +#if ENABLE_FEAT_FGT + mrs x13, HDFGRTR_EL2 +#if ENABLE_FEAT_AMUv1 + mrs x14, HAFGRTR_EL2 + stp x13, x14, [x0, #CTX_HDFGRTR_EL2] +#else + str x13, [x0, #CTX_HDFGRTR_EL2] +#endif + mrs x15, HDFGWTR_EL2 + mrs x16, HFGITR_EL2 + stp x15, x16, [x0, #CTX_HDFGWTR_EL2] + + mrs x9, HFGRTR_EL2 + mrs x10, HFGWTR_EL2 + stp x9, x10, [x0, #CTX_HFGRTR_EL2] +#endif + +#if ENABLE_FEAT_ECV + mrs x11, CNTPOFF_EL2 + str x11, [x0, #CTX_CNTPOFF_EL2] +#endif + +#if ARM_ARCH_AT_LEAST(8, 4) + mrs x12, contextidr_el2 + str x12, [x0, #CTX_CONTEXTIDR_EL2] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x13, sder32_el2 + str x13, [x0, #CTX_SDER32_EL2] +#endif + mrs x14, ttbr1_el2 + mrs x15, vdisr_el2 + stp x14, x15, [x0, #CTX_TTBR1_EL2] + +#if CTX_INCLUDE_NEVE_REGS + mrs x16, vncr_el2 + str x16, [x0, #CTX_VNCR_EL2] +#endif + + mrs x9, vsesr_el2 + mrs x10, vstcr_el2 + stp x9, x10, [x0, #CTX_VSESR_EL2] + + mrs x11, vsttbr_el2 + mrs x12, TRFCR_EL2 + stp x11, x12, [x0, #CTX_VSTTBR_EL2] +#endif + +#if ARM_ARCH_AT_LEAST(8, 5) + mrs x13, scxtnum_el2 + str x13, [x0, #CTX_SCXTNUM_EL2] +#endif + +#if ENABLE_FEAT_HCX + mrs x14, hcrx_el2 + str x14, [x0, #CTX_HCRX_EL2] +#endif + + ret +endfunc el2_sysregs_context_save + + +/* ----------------------------------------------------- + * The following function strictly follows the AArch64 + * PCS to use x9-x16 (temporary caller-saved registers) + * to restore EL2 system register context. It assumes + * that 'x0' is pointing to a 'el2_sys_regs' structure + * from where the register context will be restored + + * The following registers are not restored + * AMEVCNTVOFF0_EL2 + * AMEVCNTVOFF1_EL2 + * ICH_AP0R_EL2 + * ICH_AP1R_EL2 + * ICH_LR_EL2 + * ----------------------------------------------------- + */ +func el2_sysregs_context_restore + ldp x9, x10, [x0, #CTX_ACTLR_EL2] + msr actlr_el2, x9 + msr afsr0_el2, x10 + + ldp x11, x12, [x0, #CTX_AFSR1_EL2] + msr afsr1_el2, x11 + msr amair_el2, x12 + + ldp x13, x14, [x0, #CTX_CNTHCTL_EL2] + msr cnthctl_el2, x13 + msr cntvoff_el2, x14 + + ldr x15, [x0, #CTX_CPTR_EL2] + msr cptr_el2, x15 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x16, [x0, #CTX_DBGVCR32_EL2] + msr dbgvcr32_el2, x16 +#endif + + ldp x9, x10, [x0, #CTX_ELR_EL2] + msr elr_el2, x9 + msr esr_el2, x10 + + ldp x11, x12, [x0, #CTX_FAR_EL2] + msr far_el2, x11 + msr hacr_el2, x12 + + ldp x13, x14, [x0, #CTX_HCR_EL2] + msr hcr_el2, x13 + msr hpfar_el2, x14 + + ldp x15, x16, [x0, #CTX_HSTR_EL2] + msr hstr_el2, x15 + msr ICC_SRE_EL2, x16 + + ldp x9, x10, [x0, #CTX_ICH_HCR_EL2] + msr ICH_HCR_EL2, x9 + msr ICH_VMCR_EL2, x10 + + ldp x11, x12, [x0, #CTX_MAIR_EL2] + msr mair_el2, x11 + msr mdcr_el2, x12 + +#if ENABLE_SPE_FOR_LOWER_ELS + ldr x13, [x0, #CTX_PMSCR_EL2] + msr PMSCR_EL2, x13 +#endif + ldr x14, [x0, #CTX_SCTLR_EL2] + msr sctlr_el2, x14 + + ldp x15, x16, [x0, #CTX_SPSR_EL2] + msr spsr_el2, x15 + msr sp_el2, x16 + + ldp x9, x10, [x0, #CTX_TCR_EL2] + msr tcr_el2, x9 + msr tpidr_el2, x10 + + ldp x11, x12, [x0, #CTX_TTBR0_EL2] + msr ttbr0_el2, x11 + msr vbar_el2, x12 + + ldp x13, x14, [x0, #CTX_VMPIDR_EL2] + msr vmpidr_el2, x13 + msr vpidr_el2, x14 + + ldp x15, x16, [x0, #CTX_VTCR_EL2] + msr vtcr_el2, x15 + msr vttbr_el2, x16 + +#if CTX_INCLUDE_MTE_REGS + ldr x9, [x0, #CTX_TFSR_EL2] + msr TFSR_EL2, x9 +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + ldr x10, [x0, #CTX_MPAM2_EL2] + msr MPAM2_EL2, x10 + + ldp x11, x12, [x0, #CTX_MPAMHCR_EL2] + msr MPAMHCR_EL2, x11 + msr MPAMVPM0_EL2, x12 + + ldp x13, x14, [x0, #CTX_MPAMVPM1_EL2] + msr MPAMVPM1_EL2, x13 + msr MPAMVPM2_EL2, x14 + + ldp x15, x16, [x0, #CTX_MPAMVPM3_EL2] + msr MPAMVPM3_EL2, x15 + msr MPAMVPM4_EL2, x16 + + ldp x9, x10, [x0, #CTX_MPAMVPM5_EL2] + msr MPAMVPM5_EL2, x9 + msr MPAMVPM6_EL2, x10 + + ldp x11, x12, [x0, #CTX_MPAMVPM7_EL2] + msr MPAMVPM7_EL2, x11 + msr MPAMVPMV_EL2, x12 +#endif + +#if ENABLE_FEAT_FGT +#if ENABLE_FEAT_AMUv1 + ldp x13, x14, [x0, #CTX_HDFGRTR_EL2] + msr HAFGRTR_EL2, x14 +#else + ldr x13, [x0, #CTX_HDFGRTR_EL2] +#endif + msr HDFGRTR_EL2, x13 + + ldp x15, x16, [x0, #CTX_HDFGWTR_EL2] + msr HDFGWTR_EL2, x15 + msr HFGITR_EL2, x16 + + ldp x9, x10, [x0, #CTX_HFGRTR_EL2] + msr HFGRTR_EL2, x9 + msr HFGWTR_EL2, x10 +#endif + +#if ENABLE_FEAT_ECV + ldr x11, [x0, #CTX_CNTPOFF_EL2] + msr CNTPOFF_EL2, x11 +#endif + +#if ARM_ARCH_AT_LEAST(8, 4) + ldr x12, [x0, #CTX_CONTEXTIDR_EL2] + msr contextidr_el2, x12 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x13, [x0, #CTX_SDER32_EL2] + msr sder32_el2, x13 +#endif + ldp x14, x15, [x0, #CTX_TTBR1_EL2] + msr ttbr1_el2, x14 + msr vdisr_el2, x15 + +#if CTX_INCLUDE_NEVE_REGS + ldr x16, [x0, #CTX_VNCR_EL2] + msr vncr_el2, x16 +#endif + + ldp x9, x10, [x0, #CTX_VSESR_EL2] + msr vsesr_el2, x9 + msr vstcr_el2, x10 + + ldp x11, x12, [x0, #CTX_VSTTBR_EL2] + msr vsttbr_el2, x11 + msr TRFCR_EL2, x12 +#endif + +#if ARM_ARCH_AT_LEAST(8, 5) + ldr x13, [x0, #CTX_SCXTNUM_EL2] + msr scxtnum_el2, x13 +#endif + +#if ENABLE_FEAT_HCX + ldr x14, [x0, #CTX_HCRX_EL2] + msr hcrx_el2, x14 +#endif + + ret +endfunc el2_sysregs_context_restore + +#endif /* CTX_INCLUDE_EL2_REGS */ + +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to save EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure where the register context will be saved. + * ------------------------------------------------------------------ + */ +func el1_sysregs_context_save + + mrs x9, spsr_el1 + mrs x10, elr_el1 + stp x9, x10, [x0, #CTX_SPSR_EL1] + +#if !ERRATA_SPECULATIVE_AT + mrs x15, sctlr_el1 + mrs x16, tcr_el1 + stp x15, x16, [x0, #CTX_SCTLR_EL1] +#endif + + mrs x17, cpacr_el1 + mrs x9, csselr_el1 + stp x17, x9, [x0, #CTX_CPACR_EL1] + + mrs x10, sp_el1 + mrs x11, esr_el1 + stp x10, x11, [x0, #CTX_SP_EL1] + + mrs x12, ttbr0_el1 + mrs x13, ttbr1_el1 + stp x12, x13, [x0, #CTX_TTBR0_EL1] + + mrs x14, mair_el1 + mrs x15, amair_el1 + stp x14, x15, [x0, #CTX_MAIR_EL1] + + mrs x16, actlr_el1 + mrs x17, tpidr_el1 + stp x16, x17, [x0, #CTX_ACTLR_EL1] + + mrs x9, tpidr_el0 + mrs x10, tpidrro_el0 + stp x9, x10, [x0, #CTX_TPIDR_EL0] + + mrs x13, par_el1 + mrs x14, far_el1 + stp x13, x14, [x0, #CTX_PAR_EL1] + + mrs x15, afsr0_el1 + mrs x16, afsr1_el1 + stp x15, x16, [x0, #CTX_AFSR0_EL1] + + mrs x17, contextidr_el1 + mrs x9, vbar_el1 + stp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + + /* Save AArch32 system registers if the build has instructed so */ +#if CTX_INCLUDE_AARCH32_REGS + mrs x11, spsr_abt + mrs x12, spsr_und + stp x11, x12, [x0, #CTX_SPSR_ABT] + + mrs x13, spsr_irq + mrs x14, spsr_fiq + stp x13, x14, [x0, #CTX_SPSR_IRQ] + + mrs x15, dacr32_el2 + mrs x16, ifsr32_el2 + stp x15, x16, [x0, #CTX_DACR32_EL2] +#endif + + /* Save NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + mrs x10, cntp_ctl_el0 + mrs x11, cntp_cval_el0 + stp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + + mrs x12, cntv_ctl_el0 + mrs x13, cntv_cval_el0 + stp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + + mrs x14, cntkctl_el1 + str x14, [x0, #CTX_CNTKCTL_EL1] +#endif + + /* Save MTE system registers if the build has instructed so */ +#if CTX_INCLUDE_MTE_REGS + mrs x15, TFSRE0_EL1 + mrs x16, TFSR_EL1 + stp x15, x16, [x0, #CTX_TFSRE0_EL1] + + mrs x9, RGSR_EL1 + mrs x10, GCR_EL1 + stp x9, x10, [x0, #CTX_RGSR_EL1] +#endif + + ret +endfunc el1_sysregs_context_save + +/* ------------------------------------------------------------------ + * The following function strictly follows the AArch64 PCS to use + * x9-x17 (temporary caller-saved registers) to restore EL1 system + * register context. It assumes that 'x0' is pointing to a + * 'el1_sys_regs' structure from where the register context will be + * restored + * ------------------------------------------------------------------ + */ +func el1_sysregs_context_restore + + ldp x9, x10, [x0, #CTX_SPSR_EL1] + msr spsr_el1, x9 + msr elr_el1, x10 + +#if !ERRATA_SPECULATIVE_AT + ldp x15, x16, [x0, #CTX_SCTLR_EL1] + msr sctlr_el1, x15 + msr tcr_el1, x16 +#endif + + ldp x17, x9, [x0, #CTX_CPACR_EL1] + msr cpacr_el1, x17 + msr csselr_el1, x9 + + ldp x10, x11, [x0, #CTX_SP_EL1] + msr sp_el1, x10 + msr esr_el1, x11 + + ldp x12, x13, [x0, #CTX_TTBR0_EL1] + msr ttbr0_el1, x12 + msr ttbr1_el1, x13 + + ldp x14, x15, [x0, #CTX_MAIR_EL1] + msr mair_el1, x14 + msr amair_el1, x15 + + ldp x16, x17, [x0, #CTX_ACTLR_EL1] + msr actlr_el1, x16 + msr tpidr_el1, x17 + + ldp x9, x10, [x0, #CTX_TPIDR_EL0] + msr tpidr_el0, x9 + msr tpidrro_el0, x10 + + ldp x13, x14, [x0, #CTX_PAR_EL1] + msr par_el1, x13 + msr far_el1, x14 + + ldp x15, x16, [x0, #CTX_AFSR0_EL1] + msr afsr0_el1, x15 + msr afsr1_el1, x16 + + ldp x17, x9, [x0, #CTX_CONTEXTIDR_EL1] + msr contextidr_el1, x17 + msr vbar_el1, x9 + + /* Restore AArch32 system registers if the build has instructed so */ +#if CTX_INCLUDE_AARCH32_REGS + ldp x11, x12, [x0, #CTX_SPSR_ABT] + msr spsr_abt, x11 + msr spsr_und, x12 + + ldp x13, x14, [x0, #CTX_SPSR_IRQ] + msr spsr_irq, x13 + msr spsr_fiq, x14 + + ldp x15, x16, [x0, #CTX_DACR32_EL2] + msr dacr32_el2, x15 + msr ifsr32_el2, x16 +#endif + /* Restore NS timer registers if the build has instructed so */ +#if NS_TIMER_SWITCH + ldp x10, x11, [x0, #CTX_CNTP_CTL_EL0] + msr cntp_ctl_el0, x10 + msr cntp_cval_el0, x11 + + ldp x12, x13, [x0, #CTX_CNTV_CTL_EL0] + msr cntv_ctl_el0, x12 + msr cntv_cval_el0, x13 + + ldr x14, [x0, #CTX_CNTKCTL_EL1] + msr cntkctl_el1, x14 +#endif + /* Restore MTE system registers if the build has instructed so */ +#if CTX_INCLUDE_MTE_REGS + ldp x11, x12, [x0, #CTX_TFSRE0_EL1] + msr TFSRE0_EL1, x11 + msr TFSR_EL1, x12 + + ldp x13, x14, [x0, #CTX_RGSR_EL1] + msr RGSR_EL1, x13 + msr GCR_EL1, x14 +#endif + + /* No explict ISB required here as ERET covers it */ + ret +endfunc el1_sysregs_context_restore + +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use + * x9-x17 (temporary caller-saved registers according to AArch64 PCS) + * to save floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure where the register context will + * be saved. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. + * + * TODO: Revisit when VFP is used in secure world + * ------------------------------------------------------------------ + */ +#if CTX_INCLUDE_FPREGS +func fpregs_context_save + stp q0, q1, [x0, #CTX_FP_Q0] + stp q2, q3, [x0, #CTX_FP_Q2] + stp q4, q5, [x0, #CTX_FP_Q4] + stp q6, q7, [x0, #CTX_FP_Q6] + stp q8, q9, [x0, #CTX_FP_Q8] + stp q10, q11, [x0, #CTX_FP_Q10] + stp q12, q13, [x0, #CTX_FP_Q12] + stp q14, q15, [x0, #CTX_FP_Q14] + stp q16, q17, [x0, #CTX_FP_Q16] + stp q18, q19, [x0, #CTX_FP_Q18] + stp q20, q21, [x0, #CTX_FP_Q20] + stp q22, q23, [x0, #CTX_FP_Q22] + stp q24, q25, [x0, #CTX_FP_Q24] + stp q26, q27, [x0, #CTX_FP_Q26] + stp q28, q29, [x0, #CTX_FP_Q28] + stp q30, q31, [x0, #CTX_FP_Q30] + + mrs x9, fpsr + str x9, [x0, #CTX_FP_FPSR] + + mrs x10, fpcr + str x10, [x0, #CTX_FP_FPCR] + +#if CTX_INCLUDE_AARCH32_REGS + mrs x11, fpexc32_el2 + str x11, [x0, #CTX_FP_FPEXC32_EL2] +#endif + ret +endfunc fpregs_context_save + +/* ------------------------------------------------------------------ + * The following function follows the aapcs_64 strictly to use x9-x17 + * (temporary caller-saved registers according to AArch64 PCS) to + * restore floating point register context. It assumes that 'x0' is + * pointing to a 'fp_regs' structure from where the register context + * will be restored. + * + * Access to VFP registers will trap if CPTR_EL3.TFP is set. + * However currently we don't use VFP registers nor set traps in + * Trusted Firmware, and assume it's cleared. + * + * TODO: Revisit when VFP is used in secure world + * ------------------------------------------------------------------ + */ +func fpregs_context_restore + ldp q0, q1, [x0, #CTX_FP_Q0] + ldp q2, q3, [x0, #CTX_FP_Q2] + ldp q4, q5, [x0, #CTX_FP_Q4] + ldp q6, q7, [x0, #CTX_FP_Q6] + ldp q8, q9, [x0, #CTX_FP_Q8] + ldp q10, q11, [x0, #CTX_FP_Q10] + ldp q12, q13, [x0, #CTX_FP_Q12] + ldp q14, q15, [x0, #CTX_FP_Q14] + ldp q16, q17, [x0, #CTX_FP_Q16] + ldp q18, q19, [x0, #CTX_FP_Q18] + ldp q20, q21, [x0, #CTX_FP_Q20] + ldp q22, q23, [x0, #CTX_FP_Q22] + ldp q24, q25, [x0, #CTX_FP_Q24] + ldp q26, q27, [x0, #CTX_FP_Q26] + ldp q28, q29, [x0, #CTX_FP_Q28] + ldp q30, q31, [x0, #CTX_FP_Q30] + + ldr x9, [x0, #CTX_FP_FPSR] + msr fpsr, x9 + + ldr x10, [x0, #CTX_FP_FPCR] + msr fpcr, x10 + +#if CTX_INCLUDE_AARCH32_REGS + ldr x11, [x0, #CTX_FP_FPEXC32_EL2] + msr fpexc32_el2, x11 +#endif + /* + * No explict ISB required here as ERET to + * switch to secure EL1 or non-secure world + * covers it + */ + + ret +endfunc fpregs_context_restore +#endif /* CTX_INCLUDE_FPREGS */ + + /* + * Set the PSTATE bits not set when the exception was taken as + * described in the AArch64.TakeException() pseudocode function + * in ARM DDI 0487F.c page J1-7635 to a default value. + */ + .macro set_unset_pstate_bits + /* + * If Data Independent Timing (DIT) functionality is implemented, + * always enable DIT in EL3 + */ +#if ENABLE_FEAT_DIT + mov x8, #DIT_BIT + msr DIT, x8 +#endif /* ENABLE_FEAT_DIT */ + .endm /* set_unset_pstate_bits */ + +/* ------------------------------------------------------------------ + * The following macro is used to save and restore all the general + * purpose and ARMv8.3-PAuth (if enabled) registers. + * It also checks if Secure Cycle Counter is not disabled in MDCR_EL3 + * when ARMv8.5-PMU is implemented, and if called from Non-secure + * state saves PMCR_EL0 and disables Cycle Counter. + * + * Ideally we would only save and restore the callee saved registers + * when a world switch occurs but that type of implementation is more + * complex. So currently we will always save and restore these + * registers on entry and exit of EL3. + * clobbers: x18 + * ------------------------------------------------------------------ + */ + .macro save_gp_pmcr_pauth_regs + stp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + stp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + stp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + stp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + stp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + stp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + stp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + stp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + stp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + stp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + stp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + stp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + stp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + stp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + stp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + mrs x18, sp_el0 + str x18, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0] + + /* ---------------------------------------------------------- + * Check if earlier initialization MDCR_EL3.SCCD/MCCD to 1 + * failed, meaning that FEAT_PMUv3p5/7 is not implemented and + * PMCR_EL0 should be saved in non-secure context. + * ---------------------------------------------------------- + */ + mov_imm x10, (MDCR_SCCD_BIT | MDCR_MCCD_BIT) + mrs x9, mdcr_el3 + tst x9, x10 + bne 1f + + /* Secure Cycle Counter is not disabled */ + mrs x9, pmcr_el0 + + /* Check caller's security state */ + mrs x10, scr_el3 + tst x10, #SCR_NS_BIT + beq 2f + + /* Save PMCR_EL0 if called from Non-secure state */ + str x9, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + + /* Disable cycle counter when event counting is prohibited */ +2: orr x9, x9, #PMCR_EL0_DP_BIT + msr pmcr_el0, x9 + isb +1: +#if CTX_INCLUDE_PAUTH_REGS + /* ---------------------------------------------------------- + * Save the ARMv8.3-PAuth keys as they are not banked + * by exception level + * ---------------------------------------------------------- + */ + add x19, sp, #CTX_PAUTH_REGS_OFFSET + + mrs x20, APIAKeyLo_EL1 /* x21:x20 = APIAKey */ + mrs x21, APIAKeyHi_EL1 + mrs x22, APIBKeyLo_EL1 /* x23:x22 = APIBKey */ + mrs x23, APIBKeyHi_EL1 + mrs x24, APDAKeyLo_EL1 /* x25:x24 = APDAKey */ + mrs x25, APDAKeyHi_EL1 + mrs x26, APDBKeyLo_EL1 /* x27:x26 = APDBKey */ + mrs x27, APDBKeyHi_EL1 + mrs x28, APGAKeyLo_EL1 /* x29:x28 = APGAKey */ + mrs x29, APGAKeyHi_EL1 + + stp x20, x21, [x19, #CTX_PACIAKEY_LO] + stp x22, x23, [x19, #CTX_PACIBKEY_LO] + stp x24, x25, [x19, #CTX_PACDAKEY_LO] + stp x26, x27, [x19, #CTX_PACDBKEY_LO] + stp x28, x29, [x19, #CTX_PACGAKEY_LO] +#endif /* CTX_INCLUDE_PAUTH_REGS */ + .endm /* save_gp_pmcr_pauth_regs */ + +/* ----------------------------------------------------------------- + * This function saves the context and sets the PSTATE to a known + * state, preparing entry to el3. + * Save all the general purpose and ARMv8.3-PAuth (if enabled) + * registers. + * Then set any of the PSTATE bits that are not set by hardware + * according to the Aarch64.TakeException pseudocode in the Arm + * Architecture Reference Manual to a default value for EL3. + * clobbers: x17 + * ----------------------------------------------------------------- + */ +func prepare_el3_entry + save_gp_pmcr_pauth_regs + /* + * Set the PSTATE bits not described in the Aarch64.TakeException + * pseudocode to their default values. + */ + set_unset_pstate_bits + ret +endfunc prepare_el3_entry + +/* ------------------------------------------------------------------ + * This function restores ARMv8.3-PAuth (if enabled) and all general + * purpose registers except x30 from the CPU context. + * x30 register must be explicitly restored by the caller. + * ------------------------------------------------------------------ + */ +func restore_gp_pmcr_pauth_regs +#if CTX_INCLUDE_PAUTH_REGS + /* Restore the ARMv8.3 PAuth keys */ + add x10, sp, #CTX_PAUTH_REGS_OFFSET + + ldp x0, x1, [x10, #CTX_PACIAKEY_LO] /* x1:x0 = APIAKey */ + ldp x2, x3, [x10, #CTX_PACIBKEY_LO] /* x3:x2 = APIBKey */ + ldp x4, x5, [x10, #CTX_PACDAKEY_LO] /* x5:x4 = APDAKey */ + ldp x6, x7, [x10, #CTX_PACDBKEY_LO] /* x7:x6 = APDBKey */ + ldp x8, x9, [x10, #CTX_PACGAKEY_LO] /* x9:x8 = APGAKey */ + + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + msr APIBKeyLo_EL1, x2 + msr APIBKeyHi_EL1, x3 + msr APDAKeyLo_EL1, x4 + msr APDAKeyHi_EL1, x5 + msr APDBKeyLo_EL1, x6 + msr APDBKeyHi_EL1, x7 + msr APGAKeyLo_EL1, x8 + msr APGAKeyHi_EL1, x9 +#endif /* CTX_INCLUDE_PAUTH_REGS */ + + /* ---------------------------------------------------------- + * Restore PMCR_EL0 when returning to Non-secure state if + * Secure Cycle Counter is not disabled in MDCR_EL3 when + * ARMv8.5-PMU is implemented. + * ---------------------------------------------------------- + */ + mrs x0, scr_el3 + tst x0, #SCR_NS_BIT + beq 2f + + /* ---------------------------------------------------------- + * Back to Non-secure state. + * Check if earlier initialization MDCR_EL3.SCCD/MCCD to 1 + * failed, meaning that FEAT_PMUv3p5/7 is not implemented and + * PMCR_EL0 should be restored from non-secure context. + * ---------------------------------------------------------- + */ + mov_imm x1, (MDCR_SCCD_BIT | MDCR_MCCD_BIT) + mrs x0, mdcr_el3 + tst x0, x1 + bne 2f + ldr x0, [sp, #CTX_EL3STATE_OFFSET + CTX_PMCR_EL0] + msr pmcr_el0, x0 +2: + ldp x0, x1, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X0] + ldp x2, x3, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X2] + ldp x4, x5, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X4] + ldp x6, x7, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X6] + ldp x8, x9, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X8] + ldp x10, x11, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X10] + ldp x12, x13, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X12] + ldp x14, x15, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X14] + ldp x16, x17, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X16] + ldp x18, x19, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X18] + ldp x20, x21, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X20] + ldp x22, x23, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X22] + ldp x24, x25, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X24] + ldp x26, x27, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X26] + ldr x28, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_SP_EL0] + msr sp_el0, x28 + ldp x28, x29, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_X28] + ret +endfunc restore_gp_pmcr_pauth_regs + +/* + * In case of ERRATA_SPECULATIVE_AT, save SCTLR_EL1 and TCR_EL1 + * registers and update EL1 registers to disable stage1 and stage2 + * page table walk + */ +func save_and_update_ptw_el1_sys_regs + /* ---------------------------------------------------------- + * Save only sctlr_el1 and tcr_el1 registers + * ---------------------------------------------------------- + */ + mrs x29, sctlr_el1 + str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_SCTLR_EL1)] + mrs x29, tcr_el1 + str x29, [sp, #(CTX_EL1_SYSREGS_OFFSET + CTX_TCR_EL1)] + + /* ------------------------------------------------------------ + * Must follow below order in order to disable page table + * walk for lower ELs (EL1 and EL0). First step ensures that + * page table walk is disabled for stage1 and second step + * ensures that page table walker should use TCR_EL1.EPDx + * bits to perform address translation. ISB ensures that CPU + * does these 2 steps in order. + * + * 1. Update TCR_EL1.EPDx bits to disable page table walk by + * stage1. + * 2. Enable MMU bit to avoid identity mapping via stage2 + * and force TCR_EL1.EPDx to be used by the page table + * walker. + * ------------------------------------------------------------ + */ + orr x29, x29, #(TCR_EPD0_BIT) + orr x29, x29, #(TCR_EPD1_BIT) + msr tcr_el1, x29 + isb + mrs x29, sctlr_el1 + orr x29, x29, #SCTLR_M_BIT + msr sctlr_el1, x29 + isb + + ret +endfunc save_and_update_ptw_el1_sys_regs + +/* ------------------------------------------------------------------ + * This routine assumes that the SP_EL3 is pointing to a valid + * context structure from where the gp regs and other special + * registers can be retrieved. + * ------------------------------------------------------------------ + */ +func el3_exit +#if ENABLE_ASSERTIONS + /* el3_exit assumes SP_EL0 on entry */ + mrs x17, spsel + cmp x17, #MODE_SP_EL0 + ASM_ASSERT(eq) +#endif + + /* ---------------------------------------------------------- + * Save the current SP_EL0 i.e. the EL3 runtime stack which + * will be used for handling the next SMC. + * Then switch to SP_EL3. + * ---------------------------------------------------------- + */ + mov x17, sp + msr spsel, #MODE_SP_ELX + str x17, [sp, #CTX_EL3STATE_OFFSET + CTX_RUNTIME_SP] + + /* ---------------------------------------------------------- + * Restore SPSR_EL3, ELR_EL3 and SCR_EL3 prior to ERET + * ---------------------------------------------------------- + */ + ldr x18, [sp, #CTX_EL3STATE_OFFSET + CTX_SCR_EL3] + ldp x16, x17, [sp, #CTX_EL3STATE_OFFSET + CTX_SPSR_EL3] + msr scr_el3, x18 + msr spsr_el3, x16 + msr elr_el3, x17 + +#if IMAGE_BL31 + /* ---------------------------------------------------------- + * Restore CPTR_EL3. + * ZCR is only restored if SVE is supported and enabled. + * Synchronization is required before zcr_el3 is addressed. + * ---------------------------------------------------------- + */ + ldp x19, x20, [sp, #CTX_EL3STATE_OFFSET + CTX_CPTR_EL3] + msr cptr_el3, x19 + + ands x19, x19, #CPTR_EZ_BIT + beq sve_not_enabled + + isb + msr S3_6_C1_C2_0, x20 /* zcr_el3 */ +sve_not_enabled: +#endif + +#if IMAGE_BL31 && DYNAMIC_WORKAROUND_CVE_2018_3639 + /* ---------------------------------------------------------- + * Restore mitigation state as it was on entry to EL3 + * ---------------------------------------------------------- + */ + ldr x17, [sp, #CTX_CVE_2018_3639_OFFSET + CTX_CVE_2018_3639_DISABLE] + cbz x17, 1f + blr x17 +1: +#endif + restore_ptw_el1_sys_regs + + /* ---------------------------------------------------------- + * Restore general purpose (including x30), PMCR_EL0 and + * ARMv8.3-PAuth registers. + * Exit EL3 via ERET to a lower exception level. + * ---------------------------------------------------------- + */ + bl restore_gp_pmcr_pauth_regs + ldr x30, [sp, #CTX_GPREGS_OFFSET + CTX_GPREG_LR] + +#if IMAGE_BL31 && RAS_EXTENSION + /* ---------------------------------------------------------- + * Issue Error Synchronization Barrier to synchronize SErrors + * before exiting EL3. We're running with EAs unmasked, so + * any synchronized errors would be taken immediately; + * therefore no need to inspect DISR_EL1 register. + * ---------------------------------------------------------- + */ + esb +#else + dsb sy +#endif +#ifdef IMAGE_BL31 + str xzr, [sp, #CTX_EL3STATE_OFFSET + CTX_IS_IN_EL3] +#endif + exception_return + +endfunc el3_exit diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c b/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c new file mode 100644 index 0000000..c69dc95 --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c @@ -0,0 +1,878 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static void manage_extensions_secure(cpu_context_t *ctx); + +/******************************************************************************* + * Context management library initialisation routine. This library is used by + * runtime services to share pointers to 'cpu_context' structures for the secure + * and non-secure states. Management of the structures and their associated + * memory is not done by the context management library e.g. the PSCI service + * manages the cpu context used for entry from and exit to the non-secure state. + * The Secure payload dispatcher service manages the context(s) corresponding to + * the secure state. It also uses this library to get access to the non-secure + * state cpu context pointers. + * Lastly, this library provides the api to make SP_EL3 point to the cpu context + * which will used for programming an entry into a lower EL. The same context + * will used to save state upon exception entry from that EL. + ******************************************************************************/ +void __init cm_init(void) +{ + /* + * The context management library has only global data to intialize, but + * that will be done when the BSS is zeroed out + */ +} + +/******************************************************************************* + * The following function initializes the cpu_context 'ctx' for + * first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + * + * The security state to initialize is determined by the SECURE attribute + * of the entry_point_info. + * + * The EE and ST attributes are used to configure the endianness and secure + * timer availability for the new execution context. + * + * To prepare the register state for entry call cm_prepare_el3_exit() and + * el3_exit(). For Secure-EL1 cm_prepare_el3_exit() is equivalent to + * cm_el1_sysregs_context_restore(). + ******************************************************************************/ +void cm_setup_context(cpu_context_t *ctx, const entry_point_info_t *ep) +{ + unsigned int security_state; + u_register_t scr_el3; + el3_state_t *state; + gp_regs_t *gp_regs; + u_register_t sctlr_elx, actlr_elx; + + assert(ctx != NULL); + + security_state = GET_SECURITY_STATE(ep->h.attr); + + /* Clear any residual register values from the context */ + zeromem(ctx, sizeof(*ctx)); + + /* + * SCR_EL3 was initialised during reset sequence in macro + * el3_arch_init_common. This code modifies the SCR_EL3 fields that + * affect the next EL. + * + * The following fields are initially set to zero and then updated to + * the required value depending on the state of the SPSR_EL3 and the + * Security state and entrypoint attributes of the next EL. + */ + scr_el3 = read_scr(); + scr_el3 &= ~(SCR_NS_BIT | SCR_RW_BIT | SCR_FIQ_BIT | SCR_IRQ_BIT | + SCR_ST_BIT | SCR_HCE_BIT); + +#if ENABLE_RME + /* When RME support is enabled, clear the NSE bit as well. */ + scr_el3 &= ~SCR_NSE_BIT; +#endif /* ENABLE_RME */ + + /* + * SCR_NS: Set the security state of the next EL. + */ + if (security_state == NON_SECURE) { + scr_el3 |= SCR_NS_BIT; + } + +#if ENABLE_RME + /* Check for realm state if RME support enabled. */ + if (security_state == REALM) { + scr_el3 |= SCR_NS_BIT | SCR_NSE_BIT | SCR_EnSCXT_BIT; + } +#endif /* ENABLE_RME */ + + /* + * SCR_EL3.RW: Set the execution state, AArch32 or AArch64, for next + * Exception level as specified by SPSR. + */ + if (GET_RW(ep->spsr) == MODE_RW_64) { + scr_el3 |= SCR_RW_BIT; + } + /* + * SCR_EL3.ST: Traps Secure EL1 accesses to the Counter-timer Physical + * Secure timer registers to EL3, from AArch64 state only, if specified + * by the entrypoint attributes. + */ + if (EP_GET_ST(ep->h.attr) != 0U) { + scr_el3 |= SCR_ST_BIT; + } + + /* + * If FEAT_HCX is enabled, enable access to HCRX_EL2 by setting + * SCR_EL3.HXEn. + */ +#if ENABLE_FEAT_HCX + scr_el3 |= SCR_HXEn_BIT; +#endif + +#if RAS_TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Trap Error record accesses. Accesses to the RAS ERR + * and RAS ERX registers from EL1 and EL2 are trapped to EL3. + */ + scr_el3 |= SCR_TERR_BIT; +#endif + +#if !HANDLE_EA_EL3_FIRST + /* + * SCR_EL3.EA: Do not route External Abort and SError Interrupt External + * to EL3 when executing at a lower EL. When executing at EL3, External + * Aborts are taken to EL3. + */ + scr_el3 &= ~SCR_EA_BIT; +#endif + +#if FAULT_INJECTION_SUPPORT + /* Enable fault injection from lower ELs */ + scr_el3 |= SCR_FIEN_BIT; +#endif + +#if !CTX_INCLUDE_PAUTH_REGS + /* + * If the pointer authentication registers aren't saved during world + * switches the value of the registers can be leaked from the Secure to + * the Non-secure world. To prevent this, rather than enabling pointer + * authentication everywhere, we only enable it in the Non-secure world. + * + * If the Secure world wants to use pointer authentication, + * CTX_INCLUDE_PAUTH_REGS must be set to 1. + */ + if (security_state == NON_SECURE) { + scr_el3 |= SCR_API_BIT | SCR_APK_BIT; + } +#endif /* !CTX_INCLUDE_PAUTH_REGS */ + +#if !CTX_INCLUDE_MTE_REGS || ENABLE_ASSERTIONS + /* Get Memory Tagging Extension support level */ + unsigned int mte = get_armv8_5_mte_support(); +#endif + /* + * Enable MTE support. Support is enabled unilaterally for the normal + * world, and only for the secure world when CTX_INCLUDE_MTE_REGS is + * set. + */ +#if CTX_INCLUDE_MTE_REGS + assert((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY)); + scr_el3 |= SCR_ATA_BIT; +#else + /* + * When MTE is only implemented at EL0, it can be enabled + * across both worlds as no MTE registers are used. + */ + if ((mte == MTE_IMPLEMENTED_EL0) || + /* + * When MTE is implemented at all ELs, it can be only enabled + * in Non-Secure world without register saving. + */ + (((mte == MTE_IMPLEMENTED_ELX) || (mte == MTE_IMPLEMENTED_ASY)) && + (security_state == NON_SECURE))) { + scr_el3 |= SCR_ATA_BIT; + } +#endif /* CTX_INCLUDE_MTE_REGS */ + +#ifdef IMAGE_BL31 + /* + * SCR_EL3.IRQ, SCR_EL3.FIQ: Enable the physical FIQ and IRQ routing as + * indicated by the interrupt routing model for BL31. + * + * TODO: The interrupt routing model code is not updated for REALM + * state. Use the default values of IRQ = FIQ = 0 for REALM security + * state for now. + */ + if (security_state != REALM) { + scr_el3 |= get_scr_el3_from_routing_model(security_state); + } +#endif + + /* Save the initialized value of CPTR_EL3 register */ + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, read_cptr_el3()); + if (security_state == SECURE) { + manage_extensions_secure(ctx); + } + + /* + * SCR_EL3.HCE: Enable HVC instructions if next execution state is + * AArch64 and next EL is EL2, or if next execution state is AArch32 and + * next mode is Hyp. + * SCR_EL3.FGTEn: Enable Fine Grained Virtualization Traps under the + * same conditions as HVC instructions and when the processor supports + * ARMv8.6-FGT. + * SCR_EL3.ECVEn: Enable Enhanced Counter Virtualization (ECV) + * CNTPOFF_EL2 register under the same conditions as HVC instructions + * and when the processor supports ECV. + */ + if (((GET_RW(ep->spsr) == MODE_RW_64) && (GET_EL(ep->spsr) == MODE_EL2)) + || ((GET_RW(ep->spsr) != MODE_RW_64) + && (GET_M32(ep->spsr) == MODE32_hyp))) { + scr_el3 |= SCR_HCE_BIT; + + if (is_armv8_6_fgt_present()) { + scr_el3 |= SCR_FGTEN_BIT; + } + + if (get_armv8_6_ecv_support() + == ID_AA64MMFR0_EL1_ECV_SELF_SYNCH) { + scr_el3 |= SCR_ECVEN_BIT; + } + } + + /* Enable S-EL2 if the next EL is EL2 and security state is secure */ + if ((security_state == SECURE) && (GET_EL(ep->spsr) == MODE_EL2)) { + if (GET_RW(ep->spsr) != MODE_RW_64) { + ERROR("S-EL2 can not be used in AArch32."); + panic(); + } + + scr_el3 |= SCR_EEL2_BIT; + } + + /* + * FEAT_AMUv1p1 virtual offset registers are only accessible from EL3 + * and EL2, when clear, this bit traps accesses from EL2 so we set it + * to 1 when EL2 is present. + */ + if (is_armv8_6_feat_amuv1p1_present() && + (el_implemented(2) != EL_IMPL_NONE)) { + scr_el3 |= SCR_AMVOFFEN_BIT; + } + + /* + * Initialise SCTLR_EL1 to the reset value corresponding to the target + * execution state setting all fields rather than relying of the hw. + * Some fields have architecturally UNKNOWN reset values and these are + * set to zero. + * + * SCTLR.EE: Endianness is taken from the entrypoint attributes. + * + * SCTLR.M, SCTLR.C and SCTLR.I: These fields must be zero (as + * required by PSCI specification) + */ + sctlr_elx = (EP_GET_EE(ep->h.attr) != 0U) ? SCTLR_EE_BIT : 0U; + if (GET_RW(ep->spsr) == MODE_RW_64) { + sctlr_elx |= SCTLR_EL1_RES1; + } else { + /* + * If the target execution state is AArch32 then the following + * fields need to be set. + * + * SCTRL_EL1.nTWE: Set to one so that EL0 execution of WFE + * instructions are not trapped to EL1. + * + * SCTLR_EL1.nTWI: Set to one so that EL0 execution of WFI + * instructions are not trapped to EL1. + * + * SCTLR_EL1.CP15BEN: Set to one to enable EL0 execution of the + * CP15DMB, CP15DSB, and CP15ISB instructions. + */ + sctlr_elx |= SCTLR_AARCH32_EL1_RES1 | SCTLR_CP15BEN_BIT + | SCTLR_NTWI_BIT | SCTLR_NTWE_BIT; + } + +#if ERRATA_A75_764081 + /* + * If workaround of errata 764081 for Cortex-A75 is used then set + * SCTLR_EL1.IESB to enable Implicit Error Synchronization Barrier. + */ + sctlr_elx |= SCTLR_IESB_BIT; +#endif + + /* Enable WFE trap delay in SCR_EL3 if supported and configured */ + if (is_armv8_6_twed_present()) { + uint32_t delay = plat_arm_set_twedel_scr_el3(); + + if (delay != TWED_DISABLED) { + /* Make sure delay value fits */ + assert((delay & ~SCR_TWEDEL_MASK) == 0U); + + /* Set delay in SCR_EL3 */ + scr_el3 &= ~(SCR_TWEDEL_MASK << SCR_TWEDEL_SHIFT); + scr_el3 |= ((delay & SCR_TWEDEL_MASK) + << SCR_TWEDEL_SHIFT); + + /* Enable WFE delay */ + scr_el3 |= SCR_TWEDEn_BIT; + } + } + + /* + * Store the initialised SCTLR_EL1 value in the cpu_context - SCTLR_EL2 + * and other EL2 registers are set up by cm_prepare_el3_exit() as they + * are not part of the stored cpu_context. + */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_elx); + + /* + * Base the context ACTLR_EL1 on the current value, as it is + * implementation defined. The context restore process will write + * the value from the context to the actual register and can cause + * problems for processor cores that don't expect certain bits to + * be zero. + */ + actlr_elx = read_actlr_el1(); + write_ctx_reg((get_el1_sysregs_ctx(ctx)), (CTX_ACTLR_EL1), (actlr_elx)); + + /* + * Populate EL3 state so that we've the right context + * before doing ERET + */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); + write_ctx_reg(state, CTX_ELR_EL3, ep->pc); + write_ctx_reg(state, CTX_SPSR_EL3, ep->spsr); + + /* + * Store the X0-X7 value from the entrypoint into the context + * Use memcpy as we are in control of the layout of the structures + */ + gp_regs = get_gpregs_ctx(ctx); + memcpy(gp_regs, (void *)&ep->args, sizeof(aapcs64_params_t)); +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Non-secure world. + * When EL2 is implemented but unused `el2_unused` is non-zero, otherwise + * it is zero. + ******************************************************************************/ +static void manage_extensions_nonsecure(bool el2_unused, cpu_context_t *ctx) +{ +#if IMAGE_BL31 +#if ENABLE_SPE_FOR_LOWER_ELS + spe_enable(el2_unused); +#endif + +#if ENABLE_AMU + amu_enable(el2_unused, ctx); +#endif + +#if ENABLE_SME_FOR_NS + /* Enable SME, SVE, and FPU/SIMD for non-secure world. */ + sme_enable(ctx); +#elif ENABLE_SVE_FOR_NS + /* Enable SVE and FPU/SIMD for non-secure world. */ + sve_enable(ctx); +#endif + +#if ENABLE_MPAM_FOR_LOWER_ELS + mpam_enable(el2_unused); +#endif + +#if ENABLE_TRBE_FOR_NS + trbe_enable(); +#endif /* ENABLE_TRBE_FOR_NS */ + +#if ENABLE_SYS_REG_TRACE_FOR_NS + sys_reg_trace_enable(ctx); +#endif /* ENABLE_SYS_REG_TRACE_FOR_NS */ + +#if ENABLE_TRF_FOR_NS + trf_enable(); +#endif /* ENABLE_TRF_FOR_NS */ +#endif +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Secure world. + ******************************************************************************/ +static void manage_extensions_secure(cpu_context_t *ctx) +{ +#if IMAGE_BL31 + #if ENABLE_SME_FOR_NS + #if ENABLE_SME_FOR_SWD + /* + * Enable SME, SVE, FPU/SIMD in secure context, secure manager must + * ensure SME, SVE, and FPU/SIMD context properly managed. + */ + sme_enable(ctx); + #else /* ENABLE_SME_FOR_SWD */ + /* + * Disable SME, SVE, FPU/SIMD in secure context so non-secure world can + * safely use the associated registers. + */ + sme_disable(ctx); + #endif /* ENABLE_SME_FOR_SWD */ + #elif ENABLE_SVE_FOR_NS + #if ENABLE_SVE_FOR_SWD + /* + * Enable SVE and FPU in secure context, secure manager must ensure that + * the SVE and FPU register contexts are properly managed. + */ + sve_enable(ctx); + #else /* ENABLE_SVE_FOR_SWD */ + /* + * Disable SVE and FPU in secure context so non-secure world can safely + * use them. + */ + sve_disable(ctx); + #endif /* ENABLE_SVE_FOR_SWD */ + #endif /* ENABLE_SVE_FOR_NS */ +#endif /* IMAGE_BL31 */ +} + +/******************************************************************************* + * The following function initializes the cpu_context for a CPU specified by + * its `cpu_idx` for first use, and sets the initial entrypoint state as + * specified by the entry_point_info structure. + ******************************************************************************/ +void cm_init_context_by_index(unsigned int cpu_idx, + const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context_by_index(cpu_idx, GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * The following function initializes the cpu_context for the current CPU + * for first use, and sets the initial entrypoint state as specified by the + * entry_point_info structure. + ******************************************************************************/ +void cm_init_my_context(const entry_point_info_t *ep) +{ + cpu_context_t *ctx; + ctx = cm_get_context(GET_SECURITY_STATE(ep->h.attr)); + cm_setup_context(ctx, ep); +} + +/******************************************************************************* + * Prepare the CPU system registers for first entry into realm, secure, or + * normal world. + * + * If execution is requested to EL2 or hyp mode, SCTLR_EL2 is initialized + * If execution is requested to non-secure EL1 or svc mode, and the CPU supports + * EL2 then EL2 is disabled by configuring all necessary EL2 registers. + * For all entries, the EL1 registers are initialized from the cpu_context + ******************************************************************************/ +void cm_prepare_el3_exit(uint32_t security_state) +{ + u_register_t sctlr_elx, scr_el3, mdcr_el2; + cpu_context_t *ctx = cm_get_context(security_state); + bool el2_unused = false; + uint64_t hcr_el2 = 0U; + + assert(ctx != NULL); + + if (security_state == NON_SECURE) { + scr_el3 = read_ctx_reg(get_el3state_ctx(ctx), + CTX_SCR_EL3); + if ((scr_el3 & SCR_HCE_BIT) != 0U) { + /* Use SCTLR_EL1.EE value to initialise sctlr_el2 */ + sctlr_elx = read_ctx_reg(get_el1_sysregs_ctx(ctx), + CTX_SCTLR_EL1); + sctlr_elx &= SCTLR_EE_BIT; + sctlr_elx |= SCTLR_EL2_RES1; +#if ERRATA_A75_764081 + /* + * If workaround of errata 764081 for Cortex-A75 is used + * then set SCTLR_EL2.IESB to enable Implicit Error + * Synchronization Barrier. + */ + sctlr_elx |= SCTLR_IESB_BIT; +#endif + write_sctlr_el2(sctlr_elx); + } else if (el_implemented(2) != EL_IMPL_NONE) { + el2_unused = true; + + /* + * EL2 present but unused, need to disable safely. + * SCTLR_EL2 can be ignored in this case. + * + * Set EL2 register width appropriately: Set HCR_EL2 + * field to match SCR_EL3.RW. + */ + if ((scr_el3 & SCR_RW_BIT) != 0U) + hcr_el2 |= HCR_RW_BIT; + + /* + * For Armv8.3 pointer authentication feature, disable + * traps to EL2 when accessing key registers or using + * pointer authentication instructions from lower ELs. + */ + hcr_el2 |= (HCR_API_BIT | HCR_APK_BIT); + + write_hcr_el2(hcr_el2); + + /* + * Initialise CPTR_EL2 setting all fields rather than + * relying on the hw. All fields have architecturally + * UNKNOWN reset values. + * + * CPTR_EL2.TCPAC: Set to zero so that Non-secure EL1 + * accesses to the CPACR_EL1 or CPACR from both + * Execution states do not trap to EL2. + * + * CPTR_EL2.TTA: Set to zero so that Non-secure System + * register accesses to the trace registers from both + * Execution states do not trap to EL2. + * If PE trace unit System registers are not implemented + * then this bit is reserved, and must be set to zero. + * + * CPTR_EL2.TFP: Set to zero so that Non-secure accesses + * to SIMD and floating-point functionality from both + * Execution states do not trap to EL2. + */ + write_cptr_el2(CPTR_EL2_RESET_VAL & + ~(CPTR_EL2_TCPAC_BIT | CPTR_EL2_TTA_BIT + | CPTR_EL2_TFP_BIT)); + + /* + * Initialise CNTHCTL_EL2. All fields are + * architecturally UNKNOWN on reset and are set to zero + * except for field(s) listed below. + * + * CNTHCTL_EL2.EL1PTEN: Set to one to disable traps to + * Hyp mode of Non-secure EL0 and EL1 accesses to the + * physical timer registers. + * + * CNTHCTL_EL2.EL1PCTEN: Set to one to disable traps to + * Hyp mode of Non-secure EL0 and EL1 accesses to the + * physical counter registers. + */ + write_cnthctl_el2(CNTHCTL_RESET_VAL | + EL1PCEN_BIT | EL1PCTEN_BIT); + + /* + * Initialise CNTVOFF_EL2 to zero as it resets to an + * architecturally UNKNOWN value. + */ + write_cntvoff_el2(0); + + /* + * Set VPIDR_EL2 and VMPIDR_EL2 to match MIDR_EL1 and + * MPIDR_EL1 respectively. + */ + write_vpidr_el2(read_midr_el1()); + write_vmpidr_el2(read_mpidr_el1()); + + /* + * Initialise VTTBR_EL2. All fields are architecturally + * UNKNOWN on reset. + * + * VTTBR_EL2.VMID: Set to zero. Even though EL1&0 stage + * 2 address translation is disabled, cache maintenance + * operations depend on the VMID. + * + * VTTBR_EL2.BADDR: Set to zero as EL1&0 stage 2 address + * translation is disabled. + */ + write_vttbr_el2(VTTBR_RESET_VAL & + ~((VTTBR_VMID_MASK << VTTBR_VMID_SHIFT) + | (VTTBR_BADDR_MASK << VTTBR_BADDR_SHIFT))); + + /* + * Initialise MDCR_EL2, setting all fields rather than + * relying on hw. Some fields are architecturally + * UNKNOWN on reset. + * + * MDCR_EL2.HLP: Set to one so that event counter + * overflow, that is recorded in PMOVSCLR_EL0[0-30], + * occurs on the increment that changes + * PMEVCNTR_EL0[63] from 1 to 0, when ARMv8.5-PMU is + * implemented. This bit is RES0 in versions of the + * architecture earlier than ARMv8.5, setting it to 1 + * doesn't have any effect on them. + * + * MDCR_EL2.TTRF: Set to zero so that access to Trace + * Filter Control register TRFCR_EL1 at EL1 is not + * trapped to EL2. This bit is RES0 in versions of + * the architecture earlier than ARMv8.4. + * + * MDCR_EL2.HPMD: Set to one so that event counting is + * prohibited at EL2. This bit is RES0 in versions of + * the architecture earlier than ARMv8.1, setting it + * to 1 doesn't have any effect on them. + * + * MDCR_EL2.TPMS: Set to zero so that accesses to + * Statistical Profiling control registers from EL1 + * do not trap to EL2. This bit is RES0 when SPE is + * not implemented. + * + * MDCR_EL2.TDRA: Set to zero so that Non-secure EL0 and + * EL1 System register accesses to the Debug ROM + * registers are not trapped to EL2. + * + * MDCR_EL2.TDOSA: Set to zero so that Non-secure EL1 + * System register accesses to the powerdown debug + * registers are not trapped to EL2. + * + * MDCR_EL2.TDA: Set to zero so that System register + * accesses to the debug registers do not trap to EL2. + * + * MDCR_EL2.TDE: Set to zero so that debug exceptions + * are not routed to EL2. + * + * MDCR_EL2.HPME: Set to zero to disable EL2 Performance + * Monitors. + * + * MDCR_EL2.TPM: Set to zero so that Non-secure EL0 and + * EL1 accesses to all Performance Monitors registers + * are not trapped to EL2. + * + * MDCR_EL2.TPMCR: Set to zero so that Non-secure EL0 + * and EL1 accesses to the PMCR_EL0 or PMCR are not + * trapped to EL2. + * + * MDCR_EL2.HPMN: Set to value of PMCR_EL0.N which is the + * architecturally-defined reset value. + * + * MDCR_EL2.E2TB: Set to zero so that the trace Buffer + * owning exception level is NS-EL1 and, tracing is + * prohibited at NS-EL2. These bits are RES0 when + * FEAT_TRBE is not implemented. + */ + mdcr_el2 = ((MDCR_EL2_RESET_VAL | MDCR_EL2_HLP | + MDCR_EL2_HPMD) | + ((read_pmcr_el0() & PMCR_EL0_N_BITS) + >> PMCR_EL0_N_SHIFT)) & + ~(MDCR_EL2_TTRF | MDCR_EL2_TPMS | + MDCR_EL2_TDRA_BIT | MDCR_EL2_TDOSA_BIT | + MDCR_EL2_TDA_BIT | MDCR_EL2_TDE_BIT | + MDCR_EL2_HPME_BIT | MDCR_EL2_TPM_BIT | + MDCR_EL2_TPMCR_BIT | + MDCR_EL2_E2TB(MDCR_EL2_E2TB_EL1)); + + write_mdcr_el2(mdcr_el2); + + /* + * Initialise HSTR_EL2. All fields are architecturally + * UNKNOWN on reset. + * + * HSTR_EL2.T: Set all these fields to zero so that + * Non-secure EL0 or EL1 accesses to System registers + * do not trap to EL2. + */ + write_hstr_el2(HSTR_EL2_RESET_VAL & ~(HSTR_EL2_T_MASK)); + /* + * Initialise CNTHP_CTL_EL2. All fields are + * architecturally UNKNOWN on reset. + * + * CNTHP_CTL_EL2:ENABLE: Set to zero to disable the EL2 + * physical timer and prevent timer interrupts. + */ + write_cnthp_ctl_el2(CNTHP_CTL_RESET_VAL & + ~(CNTHP_CTL_ENABLE_BIT)); + } + manage_extensions_nonsecure(el2_unused, ctx); + } + + cm_el1_sysregs_context_restore(security_state); + cm_set_next_eret_context(security_state); +} + +#if CTX_INCLUDE_EL2_REGS +/******************************************************************************* + * Save EL2 sysreg context + ******************************************************************************/ +void cm_el2_sysregs_context_save(uint32_t security_state) +{ + u_register_t scr_el3 = read_scr(); + + /* + * Always save the non-secure and realm EL2 context, only save the + * S-EL2 context if S-EL2 is enabled. + */ + if ((security_state != SECURE) || + ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el2_sysregs_context_save(get_el2_sysregs_ctx(ctx)); + } +} + +/******************************************************************************* + * Restore EL2 sysreg context + ******************************************************************************/ +void cm_el2_sysregs_context_restore(uint32_t security_state) +{ + u_register_t scr_el3 = read_scr(); + + /* + * Always restore the non-secure and realm EL2 context, only restore the + * S-EL2 context if S-EL2 is enabled. + */ + if ((security_state != SECURE) || + ((security_state == SECURE) && ((scr_el3 & SCR_EEL2_BIT) != 0U))) { + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el2_sysregs_context_restore(get_el2_sysregs_ctx(ctx)); + } +} +#endif /* CTX_INCLUDE_EL2_REGS */ + +/******************************************************************************* + * The next four functions are used by runtime services to save and restore + * EL1 context on the 'cpu_context' structure for the specified security + * state. + ******************************************************************************/ +void cm_el1_sysregs_context_save(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el1_sysregs_context_save(get_el1_sysregs_ctx(ctx)); + +#if IMAGE_BL31 + if (security_state == SECURE) + PUBLISH_EVENT(cm_exited_secure_world); + else + PUBLISH_EVENT(cm_exited_normal_world); +#endif +} + +void cm_el1_sysregs_context_restore(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + el1_sysregs_context_restore(get_el1_sysregs_ctx(ctx)); + +#if IMAGE_BL31 + if (security_state == SECURE) + PUBLISH_EVENT(cm_entering_secure_world); + else + PUBLISH_EVENT(cm_entering_normal_world); +#endif +} + +/******************************************************************************* + * This function populates ELR_EL3 member of 'cpu_context' pertaining to the + * given security state with the given entrypoint + ******************************************************************************/ +void cm_set_elr_el3(uint32_t security_state, uintptr_t entrypoint) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); +} + +/******************************************************************************* + * This function populates ELR_EL3 and SPSR_EL3 members of 'cpu_context' + * pertaining to the given security state + ******************************************************************************/ +void cm_set_elr_spsr_el3(uint32_t security_state, + uintptr_t entrypoint, uint32_t spsr) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + write_ctx_reg(state, CTX_ELR_EL3, entrypoint); + write_ctx_reg(state, CTX_SPSR_EL3, spsr); +} + +/******************************************************************************* + * This function updates a single bit in the SCR_EL3 member of the 'cpu_context' + * pertaining to the given security state using the value and bit position + * specified in the parameters. It preserves all other bits. + ******************************************************************************/ +void cm_write_scr_el3_bit(uint32_t security_state, + uint32_t bit_pos, + uint32_t value) +{ + cpu_context_t *ctx; + el3_state_t *state; + u_register_t scr_el3; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Ensure that the bit position is a valid one */ + assert(((1UL << bit_pos) & SCR_VALID_BIT_MASK) != 0U); + + /* Ensure that the 'value' is only a bit wide */ + assert(value <= 1U); + + /* + * Get the SCR_EL3 value from the cpu context, clear the desired bit + * and set it to its new value. + */ + state = get_el3state_ctx(ctx); + scr_el3 = read_ctx_reg(state, CTX_SCR_EL3); + scr_el3 &= ~(1UL << bit_pos); + scr_el3 |= (u_register_t)value << bit_pos; + write_ctx_reg(state, CTX_SCR_EL3, scr_el3); +} + +/******************************************************************************* + * This function retrieves SCR_EL3 member of 'cpu_context' pertaining to the + * given security state. + ******************************************************************************/ +u_register_t cm_get_scr_el3(uint32_t security_state) +{ + cpu_context_t *ctx; + el3_state_t *state; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + /* Populate EL3 state so that ERET jumps to the correct entry */ + state = get_el3state_ctx(ctx); + return read_ctx_reg(state, CTX_SCR_EL3); +} + +/******************************************************************************* + * This function is used to program the context that's used for exception + * return. This initializes the SP_EL3 to a pointer to a 'cpu_context' set for + * the required security state + ******************************************************************************/ +void cm_set_next_eret_context(uint32_t security_state) +{ + cpu_context_t *ctx; + + ctx = cm_get_context(security_state); + assert(ctx != NULL); + + cm_set_next_context(ctx); +} diff --git a/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S b/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S new file mode 100644 index 0000000..2392d6b --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.globl init_cpu_data_ptr +.globl _cpu_data_by_index + +/* ----------------------------------------------------------------- + * void init_cpu_data_ptr(void) + * + * Initialise the TPIDR_EL3 register to refer to the cpu_data_t + * for the calling CPU. This must be called before cm_get_cpu_data() + * + * This can be called without a valid stack. It assumes that + * plat_my_core_pos() does not clobber register x10. + * clobbers: x0, x1, x10 + * ----------------------------------------------------------------- + */ +func init_cpu_data_ptr + mov x10, x30 + bl plat_my_core_pos + bl _cpu_data_by_index + msr tpidr_el3, x0 + ret x10 +endfunc init_cpu_data_ptr + +/* ----------------------------------------------------------------- + * cpu_data_t *_cpu_data_by_index(uint32_t cpu_index) + * + * Return the cpu_data structure for the CPU with given linear index + * + * This can be called without a valid stack. + * clobbers: x0, x1 + * ----------------------------------------------------------------- + */ +func _cpu_data_by_index + mov_imm x1, CPU_DATA_SIZE + mul x0, x0, x1 + adrp x1, percpu_data + add x1, x1, :lo12:percpu_data + add x0, x0, x1 + ret +endfunc _cpu_data_by_index diff --git a/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c b/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c new file mode 100644 index 0000000..13d464c --- /dev/null +++ b/arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2014-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* The per_cpu_ptr_cache_t space allocation */ +cpu_data_t percpu_data[PLATFORM_CORE_COUNT]; diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c new file mode 100644 index 0000000..57b1158 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c @@ -0,0 +1,421 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../amu_private.h" +#include +#include +#include +#include +#include + +#include + +struct amu_ctx { + uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS]; +#endif + + uint16_t group0_enable; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint16_t group1_enable; +#endif +}; + +static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT]; + +CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS, + amu_ctx_group0_enable_cannot_represent_all_group0_counters); + +#if ENABLE_AMU_AUXILIARY_COUNTERS +CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS, + amu_ctx_group1_enable_cannot_represent_all_group1_counters); +#endif + +static inline __unused uint32_t read_id_pfr0_amu(void) +{ + return (read_id_pfr0() >> ID_PFR0_AMU_SHIFT) & + ID_PFR0_AMU_MASK; +} + +static inline __unused void write_hcptr_tam(uint32_t value) +{ + write_hcptr((read_hcptr() & ~TAM_BIT) | + ((value << TAM_SHIFT) & TAM_BIT)); +} + +static inline __unused void write_amcr_cg1rz(uint32_t value) +{ + write_amcr((read_amcr() & ~AMCR_CG1RZ_BIT) | + ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT)); +} + +static inline __unused uint32_t read_amcfgr_ncg(void) +{ + return (read_amcfgr() >> AMCFGR_NCG_SHIFT) & + AMCFGR_NCG_MASK; +} + +static inline __unused uint32_t read_amcgcr_cg0nc(void) +{ + return (read_amcgcr() >> AMCGCR_CG0NC_SHIFT) & + AMCGCR_CG0NC_MASK; +} + +static inline __unused uint32_t read_amcgcr_cg1nc(void) +{ + return (read_amcgcr() >> AMCGCR_CG1NC_SHIFT) & + AMCGCR_CG1NC_MASK; +} + +static inline __unused uint32_t read_amcntenset0_px(void) +{ + return (read_amcntenset0() >> AMCNTENSET0_Pn_SHIFT) & + AMCNTENSET0_Pn_MASK; +} + +static inline __unused uint32_t read_amcntenset1_px(void) +{ + return (read_amcntenset1() >> AMCNTENSET1_Pn_SHIFT) & + AMCNTENSET1_Pn_MASK; +} + +static inline __unused void write_amcntenset0_px(uint32_t px) +{ + uint32_t value = read_amcntenset0(); + + value &= ~AMCNTENSET0_Pn_MASK; + value |= (px << AMCNTENSET0_Pn_SHIFT) & + AMCNTENSET0_Pn_MASK; + + write_amcntenset0(value); +} + +static inline __unused void write_amcntenset1_px(uint32_t px) +{ + uint32_t value = read_amcntenset1(); + + value &= ~AMCNTENSET1_Pn_MASK; + value |= (px << AMCNTENSET1_Pn_SHIFT) & + AMCNTENSET1_Pn_MASK; + + write_amcntenset1(value); +} + +static inline __unused void write_amcntenclr0_px(uint32_t px) +{ + uint32_t value = read_amcntenclr0(); + + value &= ~AMCNTENCLR0_Pn_MASK; + value |= (px << AMCNTENCLR0_Pn_SHIFT) & AMCNTENCLR0_Pn_MASK; + + write_amcntenclr0(value); +} + +static inline __unused void write_amcntenclr1_px(uint32_t px) +{ + uint32_t value = read_amcntenclr1(); + + value &= ~AMCNTENCLR1_Pn_MASK; + value |= (px << AMCNTENCLR1_Pn_SHIFT) & AMCNTENCLR1_Pn_MASK; + + write_amcntenclr1(value); +} + +static __unused bool amu_supported(void) +{ + return read_id_pfr0_amu() >= ID_PFR0_AMU_V1; +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +static __unused bool amu_group1_supported(void) +{ + return read_amcfgr_ncg() > 0U; +} +#endif + +/* + * Enable counters. This function is meant to be invoked by the context + * management library before exiting from EL3. + */ +void amu_enable(bool el2_unused) +{ + uint32_t id_pfr0_amu; /* AMU version */ + + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + + uint32_t amcntenset0_px = 0x0; /* Group 0 enable mask */ + uint32_t amcntenset1_px = 0x0; /* Group 1 enable mask */ + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + /* + * If the AMU is unsupported, nothing needs to be done. + */ + + return; + } + + if (el2_unused) { + /* + * HCPTR.TAM: Set to zero so any accesses to the Activity + * Monitor registers do not trap to EL2. + */ + write_hcptr_tam(0U); + } + + /* + * Retrieve the number of architected counters. All of these counters + * are enabled by default. + */ + + amcgcr_cg0nc = read_amcgcr_cg0nc(); + amcntenset0_px = (UINT32_C(1) << (amcgcr_cg0nc)) - 1U; + + assert(amcgcr_cg0nc <= AMU_AMCGCR_CG0NC_MAX); + + /* + * The platform may opt to enable specific auxiliary counters. This can + * be done via the common FCONF getter, or via the platform-implemented + * function. + */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + const struct amu_topology *topology; + +#if ENABLE_AMU_FCONF + topology = FCONF_GET_PROPERTY(amu, config, topology); +#else + topology = plat_amu_topology(); +#endif /* ENABLE_AMU_FCONF */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + amcntenset1_el0_px = topology->cores[core_pos].enable; + } else { + ERROR("AMU: failed to generate AMU topology\n"); + } +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + + /* + * Enable the requested counters. + */ + + write_amcntenset0_px(amcntenset0_px); + + amcfgr_ncg = read_amcfgr_ncg(); + if (amcfgr_ncg > 0U) { + write_amcntenset1_px(amcntenset1_px); + +#if !ENABLE_AMU_AUXILIARY_COUNTERS + VERBOSE("AMU: auxiliary counters detected but support is disabled\n"); +#endif + } + + /* Initialize FEAT_AMUv1p1 features if present. */ + if (id_pfr0_amu < ID_PFR0_AMU_V1P1) { + return; + } + +#if AMU_RESTRICT_COUNTERS + /* + * FEAT_AMUv1p1 adds a register field to restrict access to group 1 + * counters at all but the highest implemented EL. This is controlled + * with the AMU_RESTRICT_COUNTERS compile time flag, when set, system + * register reads at lower ELs return zero. Reads from the memory + * mapped view are unaffected. + */ + VERBOSE("AMU group 1 counter access restricted.\n"); + write_amcr_cg1rz(1U); +#else + write_amcr_cg1rz(0U); +#endif +} + +/* Read the group 0 counter identified by the given `idx`. */ +static uint64_t amu_group0_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_cg0nc()); + + return amu_group0_cnt_read_internal(idx); +} + +/* Write the group 0 counter identified by the given `idx` with `val` */ +static void amu_group0_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_cg0nc()); + + amu_group0_cnt_write_internal(idx, val); + isb(); +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* Read the group 1 counter identified by the given `idx` */ +static uint64_t amu_group1_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_cg1nc()); + + return amu_group1_cnt_read_internal(idx); +} + +/* Write the group 1 counter identified by the given `idx` with `val` */ +static void amu_group1_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_cg1nc()); + + amu_group1_cnt_write_internal(idx, val); + isb(); +} +#endif + +static void *amu_context_save(const void *arg) +{ + uint32_t i; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint32_t id_pfr0_amu; /* AMU version */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ +#endif + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcgcr_cg0nc = read_amcgcr_cg0nc(); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcfgr_ncg = read_amcfgr_ncg(); + amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; +#endif + + /* + * Disable all AMU counters. + */ + + ctx->group0_enable = read_amcntenset0_px(); + write_amcntenclr0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_ncg > 0U) { + ctx->group1_enable = read_amcntenset1_px(); + write_amcntenclr1_px(ctx->group1_enable); + } +#endif + + /* + * Save the counters to the local context. + */ + + isb(); /* Ensure counters have been stopped */ + + for (i = 0U; i < amcgcr_cg0nc; i++) { + ctx->group0_cnts[i] = amu_group0_cnt_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_cg1nc; i++) { + ctx->group1_cnts[i] = amu_group1_cnt_read(i); + } +#endif + + return (void *)0; +} + +static void *amu_context_restore(const void *arg) +{ + uint32_t i; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint32_t id_pfr0_amu; /* AMU version */ + + uint32_t amcfgr_ncg; /* Number of counter groups */ + uint32_t amcgcr_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint32_t amcgcr_cg1nc; /* Number of group 1 counters */ +#endif + + id_pfr0_amu = read_id_pfr0_amu(); + if (id_pfr0_amu == ID_PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcfgr_ncg = read_amcfgr_ncg(); + amcgcr_cg0nc = read_amcgcr_cg0nc(); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcgcr_cg1nc = (amcfgr_ncg > 0U) ? read_amcgcr_cg1nc() : 0U; +#endif + + /* + * Sanity check that all counters were disabled when the context was + * previously saved. + */ + + assert(read_amcntenset0_px() == 0U); + + if (amcfgr_ncg > 0U) { + assert(read_amcntenset1_px() == 0U); + } + + /* + * Restore the counter values from the local context. + */ + + for (i = 0U; i < amcgcr_cg0nc; i++) { + amu_group0_cnt_write(i, ctx->group0_cnts[i]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_cg1nc; i++) { + amu_group1_cnt_write(i, ctx->group1_cnts[i]); + } +#endif + + /* + * Re-enable counters that were disabled during context save. + */ + + write_amcntenset0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_ncg > 0U) { + write_amcntenset1_px(ctx->group1_enable); + } +#endif + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S new file mode 100644 index 0000000..8ac7678 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S @@ -0,0 +1,271 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl amu_group0_cnt_read_internal + .globl amu_group0_cnt_write_internal + .globl amu_group1_cnt_read_internal + .globl amu_group1_cnt_write_internal + .globl amu_group1_set_evtype_internal + +/* + * uint64_t amu_group0_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `r0` and `r1`. + */ +func amu_group0_cnt_read_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 3] */ + mov r1, r0 + lsr r1, r1, #2 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 +1: + ldcopr16 r0, r1, AMEVCNTR00 /* index 0 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR01 /* index 1 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR02 /* index 2 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR03 /* index 3 */ + bx lr +endfunc amu_group0_cnt_read_internal + +/* + * void amu_group0_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`. + * `r1` is used as a scratch register. + */ +func amu_group0_cnt_write_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 3] */ + mov r1, r0 + lsr r1, r1, #2 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of stcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + stcopr16 r2, r3, AMEVCNTR00 /* index 0 */ + bx lr + stcopr16 r2, r3, AMEVCNTR01 /* index 1 */ + bx lr + stcopr16 r2, r3, AMEVCNTR02 /* index 2 */ + bx lr + stcopr16 r2, r3, AMEVCNTR03 /* index 3 */ + bx lr +endfunc amu_group0_cnt_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `r0` and `r1`. + */ +func amu_group1_cnt_read_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r1, r0 + lsr r1, r1, #4 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each ldcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + ldcopr16 r0, r1, AMEVCNTR10 /* index 0 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR11 /* index 1 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR12 /* index 2 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR13 /* index 3 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR14 /* index 4 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR15 /* index 5 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR16 /* index 6 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR17 /* index 7 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR18 /* index 8 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR19 /* index 9 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1A /* index 10 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1B /* index 11 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1C /* index 12 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1D /* index 13 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1E /* index 14 */ + bx lr + ldcopr16 r0, r1, AMEVCNTR1F /* index 15 */ + bx lr +endfunc amu_group1_cnt_read_internal + +/* + * void amu_group1_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + * `idx` is passed in `r0` and `val` is passed in `r2` and `r3`. + * `r1` is used as a scratch register. + */ +func amu_group1_cnt_write_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r1, r0 + lsr r1, r1, #4 + cmp r1, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of ldcopr16/bx lr instruction pair + * in the table below. + */ + adr r1, 1f + lsl r0, r0, #3 /* each stcopr16/bx lr sequence is 8 bytes */ + add r1, r1, r0 + bx r1 + +1: + stcopr16 r2, r3, AMEVCNTR10 /* index 0 */ + bx lr + stcopr16 r2, r3, AMEVCNTR11 /* index 1 */ + bx lr + stcopr16 r2, r3, AMEVCNTR12 /* index 2 */ + bx lr + stcopr16 r2, r3, AMEVCNTR13 /* index 3 */ + bx lr + stcopr16 r2, r3, AMEVCNTR14 /* index 4 */ + bx lr + stcopr16 r2, r3, AMEVCNTR15 /* index 5 */ + bx lr + stcopr16 r2, r3, AMEVCNTR16 /* index 6 */ + bx lr + stcopr16 r2, r3, AMEVCNTR17 /* index 7 */ + bx lr + stcopr16 r2, r3, AMEVCNTR18 /* index 8 */ + bx lr + stcopr16 r2, r3, AMEVCNTR19 /* index 9 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1A /* index 10 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1B /* index 11 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1C /* index 12 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1D /* index 13 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1E /* index 14 */ + bx lr + stcopr16 r2, r3, AMEVCNTR1F /* index 15 */ + bx lr +endfunc amu_group1_cnt_write_internal + +/* + * void amu_group1_set_evtype_internal(int idx, unsigned int val); + * + * Program the AMU event type register indexed by `idx` + * with the value `val`. + */ +func amu_group1_set_evtype_internal +#if ENABLE_ASSERTIONS + /* `idx` should be between [0, 15] */ + mov r2, r0 + lsr r2, r2, #4 + cmp r2, #0 + ASM_ASSERT(eq) + + /* val should be between [0, 65535] */ + mov r2, r1 + lsr r2, r2, #16 + cmp r2, #0 + ASM_ASSERT(eq) +#endif + + /* + * Given `idx` calculate address of stcopr/bx lr instruction pair + * in the table below. + */ + adr r2, 1f + lsl r0, r0, #3 /* each stcopr/bx lr sequence is 8 bytes */ + add r2, r2, r0 + bx r2 + +1: + stcopr r1, AMEVTYPER10 /* index 0 */ + bx lr + stcopr r1, AMEVTYPER11 /* index 1 */ + bx lr + stcopr r1, AMEVTYPER12 /* index 2 */ + bx lr + stcopr r1, AMEVTYPER13 /* index 3 */ + bx lr + stcopr r1, AMEVTYPER14 /* index 4 */ + bx lr + stcopr r1, AMEVTYPER15 /* index 5 */ + bx lr + stcopr r1, AMEVTYPER16 /* index 6 */ + bx lr + stcopr r1, AMEVTYPER17 /* index 7 */ + bx lr + stcopr r1, AMEVTYPER18 /* index 8 */ + bx lr + stcopr r1, AMEVTYPER19 /* index 9 */ + bx lr + stcopr r1, AMEVTYPER1A /* index 10 */ + bx lr + stcopr r1, AMEVTYPER1B /* index 11 */ + bx lr + stcopr r1, AMEVTYPER1C /* index 12 */ + bx lr + stcopr r1, AMEVTYPER1D /* index 13 */ + bx lr + stcopr r1, AMEVTYPER1E /* index 14 */ + bx lr + stcopr r1, AMEVTYPER1F /* index 15 */ + bx lr +endfunc amu_group1_set_evtype_internal +#endif diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c new file mode 100644 index 0000000..d329c3d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c @@ -0,0 +1,638 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include "../amu_private.h" +#include +#include +#include +#include +#include +#include + +#include + +#if ENABLE_AMU_FCONF +# include +# include +#endif + +#if ENABLE_MPMM +# include +#endif + +struct amu_ctx { + uint64_t group0_cnts[AMU_GROUP0_MAX_COUNTERS]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_cnts[AMU_GROUP1_MAX_COUNTERS]; +#endif + + /* Architected event counter 1 does not have an offset register */ + uint64_t group0_voffsets[AMU_GROUP0_MAX_COUNTERS - 1U]; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t group1_voffsets[AMU_GROUP1_MAX_COUNTERS]; +#endif + + uint16_t group0_enable; +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint16_t group1_enable; +#endif +}; + +static struct amu_ctx amu_ctxs_[PLATFORM_CORE_COUNT]; + +CASSERT((sizeof(amu_ctxs_[0].group0_enable) * CHAR_BIT) <= AMU_GROUP0_MAX_COUNTERS, + amu_ctx_group0_enable_cannot_represent_all_group0_counters); + +#if ENABLE_AMU_AUXILIARY_COUNTERS +CASSERT((sizeof(amu_ctxs_[0].group1_enable) * CHAR_BIT) <= AMU_GROUP1_MAX_COUNTERS, + amu_ctx_group1_enable_cannot_represent_all_group1_counters); +#endif + +static inline __unused uint64_t read_id_aa64pfr0_el1_amu(void) +{ + return (read_id_aa64pfr0_el1() >> ID_AA64PFR0_AMU_SHIFT) & + ID_AA64PFR0_AMU_MASK; +} + +static inline __unused uint64_t read_hcr_el2_amvoffen(void) +{ + return (read_hcr_el2() & HCR_AMVOFFEN_BIT) >> + HCR_AMVOFFEN_SHIFT; +} + +static inline __unused void write_cptr_el2_tam(uint64_t value) +{ + write_cptr_el2((read_cptr_el2() & ~CPTR_EL2_TAM_BIT) | + ((value << CPTR_EL2_TAM_SHIFT) & CPTR_EL2_TAM_BIT)); +} + +static inline __unused void write_cptr_el3_tam(cpu_context_t *ctx, uint64_t tam) +{ + uint64_t value = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3); + + value &= ~TAM_BIT; + value |= (tam << TAM_SHIFT) & TAM_BIT; + + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, value); +} + +static inline __unused void write_hcr_el2_amvoffen(uint64_t value) +{ + write_hcr_el2((read_hcr_el2() & ~HCR_AMVOFFEN_BIT) | + ((value << HCR_AMVOFFEN_SHIFT) & HCR_AMVOFFEN_BIT)); +} + +static inline __unused void write_amcr_el0_cg1rz(uint64_t value) +{ + write_amcr_el0((read_amcr_el0() & ~AMCR_CG1RZ_BIT) | + ((value << AMCR_CG1RZ_SHIFT) & AMCR_CG1RZ_BIT)); +} + +static inline __unused uint64_t read_amcfgr_el0_ncg(void) +{ + return (read_amcfgr_el0() >> AMCFGR_EL0_NCG_SHIFT) & + AMCFGR_EL0_NCG_MASK; +} + +static inline __unused uint64_t read_amcgcr_el0_cg0nc(void) +{ + return (read_amcgcr_el0() >> AMCGCR_EL0_CG0NC_SHIFT) & + AMCGCR_EL0_CG0NC_MASK; +} + +static inline __unused uint64_t read_amcg1idr_el0_voff(void) +{ + return (read_amcg1idr_el0() >> AMCG1IDR_VOFF_SHIFT) & + AMCG1IDR_VOFF_MASK; +} + +static inline __unused uint64_t read_amcgcr_el0_cg1nc(void) +{ + return (read_amcgcr_el0() >> AMCGCR_EL0_CG1NC_SHIFT) & + AMCGCR_EL0_CG1NC_MASK; +} + +static inline __unused uint64_t read_amcntenset0_el0_px(void) +{ + return (read_amcntenset0_el0() >> AMCNTENSET0_EL0_Pn_SHIFT) & + AMCNTENSET0_EL0_Pn_MASK; +} + +static inline __unused uint64_t read_amcntenset1_el0_px(void) +{ + return (read_amcntenset1_el0() >> AMCNTENSET1_EL0_Pn_SHIFT) & + AMCNTENSET1_EL0_Pn_MASK; +} + +static inline __unused void write_amcntenset0_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenset0_el0(); + + value &= ~AMCNTENSET0_EL0_Pn_MASK; + value |= (px << AMCNTENSET0_EL0_Pn_SHIFT) & AMCNTENSET0_EL0_Pn_MASK; + + write_amcntenset0_el0(value); +} + +static inline __unused void write_amcntenset1_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenset1_el0(); + + value &= ~AMCNTENSET1_EL0_Pn_MASK; + value |= (px << AMCNTENSET1_EL0_Pn_SHIFT) & AMCNTENSET1_EL0_Pn_MASK; + + write_amcntenset1_el0(value); +} + +static inline __unused void write_amcntenclr0_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenclr0_el0(); + + value &= ~AMCNTENCLR0_EL0_Pn_MASK; + value |= (px << AMCNTENCLR0_EL0_Pn_SHIFT) & AMCNTENCLR0_EL0_Pn_MASK; + + write_amcntenclr0_el0(value); +} + +static inline __unused void write_amcntenclr1_el0_px(uint64_t px) +{ + uint64_t value = read_amcntenclr1_el0(); + + value &= ~AMCNTENCLR1_EL0_Pn_MASK; + value |= (px << AMCNTENCLR1_EL0_Pn_SHIFT) & AMCNTENCLR1_EL0_Pn_MASK; + + write_amcntenclr1_el0(value); +} + +static __unused bool amu_supported(void) +{ + return read_id_aa64pfr0_el1_amu() >= ID_AA64PFR0_AMU_V1; +} + +static __unused bool amu_v1p1_supported(void) +{ + return read_id_aa64pfr0_el1_amu() >= ID_AA64PFR0_AMU_V1P1; +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +static __unused bool amu_group1_supported(void) +{ + return read_amcfgr_el0_ncg() > 0U; +} +#endif + +/* + * Enable counters. This function is meant to be invoked by the context + * management library before exiting from EL3. + */ +void amu_enable(bool el2_unused, cpu_context_t *ctx) +{ + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + + uint64_t amcntenset0_el0_px = 0x0; /* Group 0 enable mask */ + uint64_t amcntenset1_el0_px = 0x0; /* Group 1 enable mask */ + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + /* + * If the AMU is unsupported, nothing needs to be done. + */ + + return; + } + + if (el2_unused) { + /* + * CPTR_EL2.TAM: Set to zero so any accesses to the Activity + * Monitor registers do not trap to EL2. + */ + write_cptr_el2_tam(0U); + } + + /* + * Retrieve and update the CPTR_EL3 value from the context mentioned + * in 'ctx'. Set CPTR_EL3.TAM to zero so that any accesses to + * the Activity Monitor registers do not trap to EL3. + */ + write_cptr_el3_tam(ctx, 0U); + + /* + * Retrieve the number of architected counters. All of these counters + * are enabled by default. + */ + + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + amcntenset0_el0_px = (UINT64_C(1) << (amcgcr_el0_cg0nc)) - 1U; + + assert(amcgcr_el0_cg0nc <= AMU_AMCGCR_CG0NC_MAX); + + /* + * The platform may opt to enable specific auxiliary counters. This can + * be done via the common FCONF getter, or via the platform-implemented + * function. + */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + const struct amu_topology *topology; + +#if ENABLE_AMU_FCONF + topology = FCONF_GET_PROPERTY(amu, config, topology); +#else + topology = plat_amu_topology(); +#endif /* ENABLE_AMU_FCONF */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + amcntenset1_el0_px = topology->cores[core_pos].enable; + } else { + ERROR("AMU: failed to generate AMU topology\n"); + } +#endif /* ENABLE_AMU_AUXILIARY_COUNTERS */ + + /* + * Enable the requested counters. + */ + + write_amcntenset0_el0_px(amcntenset0_el0_px); + + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + if (amcfgr_el0_ncg > 0U) { + write_amcntenset1_el0_px(amcntenset1_el0_px); + +#if !ENABLE_AMU_AUXILIARY_COUNTERS + VERBOSE("AMU: auxiliary counters detected but support is disabled\n"); +#endif + } + + /* Initialize FEAT_AMUv1p1 features if present. */ + if (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) { + if (el2_unused) { + /* + * Make sure virtual offsets are disabled if EL2 not + * used. + */ + write_hcr_el2_amvoffen(0U); + } + +#if AMU_RESTRICT_COUNTERS + /* + * FEAT_AMUv1p1 adds a register field to restrict access to + * group 1 counters at all but the highest implemented EL. This + * is controlled with the `AMU_RESTRICT_COUNTERS` compile time + * flag, when set, system register reads at lower ELs return + * zero. Reads from the memory mapped view are unaffected. + */ + VERBOSE("AMU group 1 counter access restricted.\n"); + write_amcr_el0_cg1rz(1U); +#else + write_amcr_el0_cg1rz(0U); +#endif + } + +#if ENABLE_MPMM + mpmm_enable(); +#endif +} + +/* Read the group 0 counter identified by the given `idx`. */ +static uint64_t amu_group0_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + + return amu_group0_cnt_read_internal(idx); +} + +/* Write the group 0 counter identified by the given `idx` with `val` */ +static void amu_group0_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + + amu_group0_cnt_write_internal(idx, val); + isb(); +} + +/* + * Unlike with auxiliary counters, we cannot detect at runtime whether an + * architected counter supports a virtual offset. These are instead fixed + * according to FEAT_AMUv1p1, but this switch will need to be updated if later + * revisions of FEAT_AMU add additional architected counters. + */ +static bool amu_group0_voffset_supported(uint64_t idx) +{ + switch (idx) { + case 0U: + case 2U: + case 3U: + return true; + + case 1U: + return false; + + default: + ERROR("AMU: can't set up virtual offset for unknown " + "architected counter %" PRIu64 "!\n", idx); + + panic(); + } +} + +/* + * Read the group 0 offset register for a given index. Index must be 0, 2, + * or 3, the register for 1 does not exist. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static uint64_t amu_group0_voffset_read(unsigned int idx) +{ + assert(amu_v1p1_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + assert(idx != 1U); + + return amu_group0_voffset_read_internal(idx); +} + +/* + * Write the group 0 offset register for a given index. Index must be 0, 2, or + * 3, the register for 1 does not exist. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static void amu_group0_voffset_write(unsigned int idx, uint64_t val) +{ + assert(amu_v1p1_supported()); + assert(idx < read_amcgcr_el0_cg0nc()); + assert(idx != 1U); + + amu_group0_voffset_write_internal(idx, val); + isb(); +} + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* Read the group 1 counter identified by the given `idx` */ +static uint64_t amu_group1_cnt_read(unsigned int idx) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + + return amu_group1_cnt_read_internal(idx); +} + +/* Write the group 1 counter identified by the given `idx` with `val` */ +static void amu_group1_cnt_write(unsigned int idx, uint64_t val) +{ + assert(amu_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + + amu_group1_cnt_write_internal(idx, val); + isb(); +} + +/* + * Read the group 1 offset register for a given index. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static uint64_t amu_group1_voffset_read(unsigned int idx) +{ + assert(amu_v1p1_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U); + + return amu_group1_voffset_read_internal(idx); +} + +/* + * Write the group 1 offset register for a given index. + * + * Using this function requires FEAT_AMUv1p1 support. + */ +static void amu_group1_voffset_write(unsigned int idx, uint64_t val) +{ + assert(amu_v1p1_supported()); + assert(amu_group1_supported()); + assert(idx < read_amcgcr_el0_cg1nc()); + assert((read_amcg1idr_el0_voff() & (UINT64_C(1) << idx)) != 0U); + + amu_group1_voffset_write_internal(idx, val); + isb(); +} +#endif + +static void *amu_context_save(const void *arg) +{ + uint64_t i, j; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + uint64_t hcr_el2_amvoffen; /* AMU virtual offsets enabled */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */ + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */ +#endif + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + hcr_el2_amvoffen = (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) ? + read_hcr_el2_amvoffen() : 0U; + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U; + amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U; +#endif + + /* + * Disable all AMU counters. + */ + + ctx->group0_enable = read_amcntenset0_el0_px(); + write_amcntenclr0_el0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_el0_ncg > 0U) { + ctx->group1_enable = read_amcntenset1_el0_px(); + write_amcntenclr1_el0_px(ctx->group1_enable); + } +#endif + + /* + * Save the counters to the local context. + */ + + isb(); /* Ensure counters have been stopped */ + + for (i = 0U; i < amcgcr_el0_cg0nc; i++) { + ctx->group0_cnts[i] = amu_group0_cnt_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_el0_cg1nc; i++) { + ctx->group1_cnts[i] = amu_group1_cnt_read(i); + } +#endif + + /* + * Save virtual offsets for counters that offer them. + */ + + if (hcr_el2_amvoffen != 0U) { + for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) { + if (!amu_group0_voffset_supported(i)) { + continue; /* No virtual offset */ + } + + ctx->group0_voffsets[j++] = amu_group0_voffset_read(i); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) { + if ((amcg1idr_el0_voff >> i) & 1U) { + continue; /* No virtual offset */ + } + + ctx->group1_voffsets[j++] = amu_group1_voffset_read(i); + } +#endif + } + + return (void *)0; +} + +static void *amu_context_restore(const void *arg) +{ + uint64_t i, j; + + unsigned int core_pos; + struct amu_ctx *ctx; + + uint64_t id_aa64pfr0_el1_amu; /* AMU version */ + + uint64_t hcr_el2_amvoffen; /* AMU virtual offsets enabled */ + + uint64_t amcfgr_el0_ncg; /* Number of counter groups */ + uint64_t amcgcr_el0_cg0nc; /* Number of group 0 counters */ + +#if ENABLE_AMU_AUXILIARY_COUNTERS + uint64_t amcgcr_el0_cg1nc; /* Number of group 1 counters */ + uint64_t amcg1idr_el0_voff; /* Auxiliary counters with virtual offsets */ +#endif + + id_aa64pfr0_el1_amu = read_id_aa64pfr0_el1_amu(); + if (id_aa64pfr0_el1_amu == ID_AA64PFR0_AMU_NOT_SUPPORTED) { + return (void *)0; + } + + core_pos = plat_my_core_pos(); + ctx = &amu_ctxs_[core_pos]; + + amcfgr_el0_ncg = read_amcfgr_el0_ncg(); + amcgcr_el0_cg0nc = read_amcgcr_el0_cg0nc(); + + hcr_el2_amvoffen = (id_aa64pfr0_el1_amu >= ID_AA64PFR0_AMU_V1P1) ? + read_hcr_el2_amvoffen() : 0U; + +#if ENABLE_AMU_AUXILIARY_COUNTERS + amcgcr_el0_cg1nc = (amcfgr_el0_ncg > 0U) ? read_amcgcr_el0_cg1nc() : 0U; + amcg1idr_el0_voff = (hcr_el2_amvoffen != 0U) ? read_amcg1idr_el0_voff() : 0U; +#endif + + /* + * Sanity check that all counters were disabled when the context was + * previously saved. + */ + + assert(read_amcntenset0_el0_px() == 0U); + + if (amcfgr_el0_ncg > 0U) { + assert(read_amcntenset1_el0_px() == 0U); + } + + /* + * Restore the counter values from the local context. + */ + + for (i = 0U; i < amcgcr_el0_cg0nc; i++) { + amu_group0_cnt_write(i, ctx->group0_cnts[i]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U; i < amcgcr_el0_cg1nc; i++) { + amu_group1_cnt_write(i, ctx->group1_cnts[i]); + } +#endif + + /* + * Restore virtual offsets for counters that offer them. + */ + + if (hcr_el2_amvoffen != 0U) { + for (i = 0U, j = 0U; i < amcgcr_el0_cg0nc; i++) { + if (!amu_group0_voffset_supported(i)) { + continue; /* No virtual offset */ + } + + amu_group0_voffset_write(i, ctx->group0_voffsets[j++]); + } + +#if ENABLE_AMU_AUXILIARY_COUNTERS + for (i = 0U, j = 0U; i < amcgcr_el0_cg1nc; i++) { + if ((amcg1idr_el0_voff >> i) & 1U) { + continue; /* No virtual offset */ + } + + amu_group1_voffset_write(i, ctx->group1_voffsets[j++]); + } +#endif + } + + /* + * Re-enable counters that were disabled during context save. + */ + + write_amcntenset0_el0_px(ctx->group0_enable); + +#if ENABLE_AMU_AUXILIARY_COUNTERS + if (amcfgr_el0_ncg > 0) { + write_amcntenset1_el0_px(ctx->group1_enable); + } +#endif + +#if ENABLE_MPMM + mpmm_enable(); +#endif + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_start, amu_context_save); +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, amu_context_restore); diff --git a/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S new file mode 100644 index 0000000..0f6d799 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl amu_group0_cnt_read_internal + .globl amu_group0_cnt_write_internal + .globl amu_group1_cnt_read_internal + .globl amu_group1_cnt_write_internal + .globl amu_group1_set_evtype_internal + + /* FEAT_AMUv1p1 virtualisation offset register functions */ + .globl amu_group0_voffset_read_internal + .globl amu_group0_voffset_write_internal + .globl amu_group1_voffset_read_internal + .globl amu_group1_voffset_write_internal + +/* + * uint64_t amu_group0_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func amu_group0_cnt_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTR00_EL0 /* index 0 */ + read AMEVCNTR01_EL0 /* index 1 */ + read AMEVCNTR02_EL0 /* index 2 */ + read AMEVCNTR03_EL0 /* index 3 */ +endfunc amu_group0_cnt_read_internal + +/* + * void amu_group0_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func amu_group0_cnt_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTR00_EL0 /* index 0 */ + write AMEVCNTR01_EL0 /* index 1 */ + write AMEVCNTR02_EL0 /* index 2 */ + write AMEVCNTR03_EL0 /* index 3 */ +endfunc amu_group0_cnt_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_cnt_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU counter + * and return it in `x0`. + */ +func amu_group1_cnt_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTR10_EL0 /* index 0 */ + read AMEVCNTR11_EL0 /* index 1 */ + read AMEVCNTR12_EL0 /* index 2 */ + read AMEVCNTR13_EL0 /* index 3 */ + read AMEVCNTR14_EL0 /* index 4 */ + read AMEVCNTR15_EL0 /* index 5 */ + read AMEVCNTR16_EL0 /* index 6 */ + read AMEVCNTR17_EL0 /* index 7 */ + read AMEVCNTR18_EL0 /* index 8 */ + read AMEVCNTR19_EL0 /* index 9 */ + read AMEVCNTR1A_EL0 /* index 10 */ + read AMEVCNTR1B_EL0 /* index 11 */ + read AMEVCNTR1C_EL0 /* index 12 */ + read AMEVCNTR1D_EL0 /* index 13 */ + read AMEVCNTR1E_EL0 /* index 14 */ + read AMEVCNTR1F_EL0 /* index 15 */ +endfunc amu_group1_cnt_read_internal + +/* + * void amu_group1_cnt_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU counter. + */ +func amu_group1_cnt_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTR10_EL0 /* index 0 */ + write AMEVCNTR11_EL0 /* index 1 */ + write AMEVCNTR12_EL0 /* index 2 */ + write AMEVCNTR13_EL0 /* index 3 */ + write AMEVCNTR14_EL0 /* index 4 */ + write AMEVCNTR15_EL0 /* index 5 */ + write AMEVCNTR16_EL0 /* index 6 */ + write AMEVCNTR17_EL0 /* index 7 */ + write AMEVCNTR18_EL0 /* index 8 */ + write AMEVCNTR19_EL0 /* index 9 */ + write AMEVCNTR1A_EL0 /* index 10 */ + write AMEVCNTR1B_EL0 /* index 11 */ + write AMEVCNTR1C_EL0 /* index 12 */ + write AMEVCNTR1D_EL0 /* index 13 */ + write AMEVCNTR1E_EL0 /* index 14 */ + write AMEVCNTR1F_EL0 /* index 15 */ +endfunc amu_group1_cnt_write_internal + +/* + * void amu_group1_set_evtype_internal(int idx, unsigned int val); + * + * Program the AMU event type register indexed by `idx` + * with the value `val`. + */ +func amu_group1_set_evtype_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) + + /* val should be between [0, 65535] */ + tst x1, #~0xFFFF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of msr/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVTYPER10_EL0 /* index 0 */ + write AMEVTYPER11_EL0 /* index 1 */ + write AMEVTYPER12_EL0 /* index 2 */ + write AMEVTYPER13_EL0 /* index 3 */ + write AMEVTYPER14_EL0 /* index 4 */ + write AMEVTYPER15_EL0 /* index 5 */ + write AMEVTYPER16_EL0 /* index 6 */ + write AMEVTYPER17_EL0 /* index 7 */ + write AMEVTYPER18_EL0 /* index 8 */ + write AMEVTYPER19_EL0 /* index 9 */ + write AMEVTYPER1A_EL0 /* index 10 */ + write AMEVTYPER1B_EL0 /* index 11 */ + write AMEVTYPER1C_EL0 /* index 12 */ + write AMEVTYPER1D_EL0 /* index 13 */ + write AMEVTYPER1E_EL0 /* index 14 */ + write AMEVTYPER1F_EL0 /* index 15 */ +endfunc amu_group1_set_evtype_internal +#endif + +/* + * Accessor functions for virtual offset registers added with FEAT_AMUv1p1 + */ + +/* + * uint64_t amu_group0_voffset_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU virtual offset register + * and return it in `x0`. + */ +func amu_group0_voffset_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) + /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */ + cmp x0, #1 + ASM_ASSERT(ne) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTVOFF00_EL2 /* index 0 */ + .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */ +#if ENABLE_BTI + .skip 4 +#endif + read AMEVCNTVOFF02_EL2 /* index 2 */ + read AMEVCNTVOFF03_EL2 /* index 3 */ +endfunc amu_group0_voffset_read_internal + +/* + * void amu_group0_voffset_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU virtual offset register. + */ +func amu_group0_voffset_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~3 + ASM_ASSERT(eq) + /* Make sure idx != 1 since AMEVCNTVOFF01_EL2 does not exist */ + cmp x0, #1 + ASM_ASSERT(ne) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTVOFF00_EL2 /* index 0 */ + .skip 8 /* AMEVCNTVOFF01_EL2 does not exist */ +#if ENABLE_BTI + .skip 4 +#endif + write AMEVCNTVOFF02_EL2 /* index 2 */ + write AMEVCNTVOFF03_EL2 /* index 3 */ +endfunc amu_group0_voffset_write_internal + +#if ENABLE_AMU_AUXILIARY_COUNTERS +/* + * uint64_t amu_group1_voffset_read_internal(int idx); + * + * Given `idx`, read the corresponding AMU virtual offset register + * and return it in `x0`. + */ +func amu_group1_voffset_read_internal + adr x1, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x1, x1, x0, lsl #3 /* each mrs/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x1, x1, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x1 + +1: read AMEVCNTVOFF10_EL2 /* index 0 */ + read AMEVCNTVOFF11_EL2 /* index 1 */ + read AMEVCNTVOFF12_EL2 /* index 2 */ + read AMEVCNTVOFF13_EL2 /* index 3 */ + read AMEVCNTVOFF14_EL2 /* index 4 */ + read AMEVCNTVOFF15_EL2 /* index 5 */ + read AMEVCNTVOFF16_EL2 /* index 6 */ + read AMEVCNTVOFF17_EL2 /* index 7 */ + read AMEVCNTVOFF18_EL2 /* index 8 */ + read AMEVCNTVOFF19_EL2 /* index 9 */ + read AMEVCNTVOFF1A_EL2 /* index 10 */ + read AMEVCNTVOFF1B_EL2 /* index 11 */ + read AMEVCNTVOFF1C_EL2 /* index 12 */ + read AMEVCNTVOFF1D_EL2 /* index 13 */ + read AMEVCNTVOFF1E_EL2 /* index 14 */ + read AMEVCNTVOFF1F_EL2 /* index 15 */ +endfunc amu_group1_voffset_read_internal + +/* + * void amu_group1_voffset_write_internal(int idx, uint64_t val); + * + * Given `idx`, write `val` to the corresponding AMU virtual offset register. + */ +func amu_group1_voffset_write_internal + adr x2, 1f +#if ENABLE_ASSERTIONS + /* + * It can be dangerous to call this function with an + * out of bounds index. Ensure `idx` is valid. + */ + tst x0, #~0xF + ASM_ASSERT(eq) +#endif + /* + * Given `idx` calculate address of mrs/ret instruction pair + * in the table below. + */ + add x2, x2, x0, lsl #3 /* each msr/ret sequence is 8 bytes */ +#if ENABLE_BTI + add x2, x2, x0, lsl #2 /* + "bti j" instruction */ +#endif + br x2 + +1: write AMEVCNTVOFF10_EL2 /* index 0 */ + write AMEVCNTVOFF11_EL2 /* index 1 */ + write AMEVCNTVOFF12_EL2 /* index 2 */ + write AMEVCNTVOFF13_EL2 /* index 3 */ + write AMEVCNTVOFF14_EL2 /* index 4 */ + write AMEVCNTVOFF15_EL2 /* index 5 */ + write AMEVCNTVOFF16_EL2 /* index 6 */ + write AMEVCNTVOFF17_EL2 /* index 7 */ + write AMEVCNTVOFF18_EL2 /* index 8 */ + write AMEVCNTVOFF19_EL2 /* index 9 */ + write AMEVCNTVOFF1A_EL2 /* index 10 */ + write AMEVCNTVOFF1B_EL2 /* index 11 */ + write AMEVCNTVOFF1C_EL2 /* index 12 */ + write AMEVCNTVOFF1D_EL2 /* index 13 */ + write AMEVCNTVOFF1E_EL2 /* index 14 */ + write AMEVCNTVOFF1F_EL2 /* index 15 */ +endfunc amu_group1_voffset_write_internal +#endif diff --git a/arm-trusted-firmware/lib/extensions/amu/amu.mk b/arm-trusted-firmware/lib/extensions/amu/amu.mk new file mode 100644 index 0000000..0d203cb --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/amu.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/fconf/fconf.mk + +AMU_SOURCES := lib/extensions/amu/${ARCH}/amu.c \ + lib/extensions/amu/${ARCH}/amu_helpers.S + +ifneq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) + ifeq (${ENABLE_AMU},0) + $(error AMU auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) requires AMU support (`ENABLE_AMU`)) + endif +endif + +ifneq (${ENABLE_AMU_FCONF},0) + ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) + $(error AMU FCONF support (`ENABLE_AMU_FCONF`) is not necessary when auxiliary counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`) is disabled) + endif + + AMU_SOURCES += ${FCONF_AMU_SOURCES} +endif diff --git a/arm-trusted-firmware/lib/extensions/amu/amu_private.h b/arm-trusted-firmware/lib/extensions/amu/amu_private.h new file mode 100644 index 0000000..eb7ff0e --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/amu/amu_private.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AMU_PRIVATE_H +#define AMU_PRIVATE_H + +#include + +#include +#include +#include + +#include + +#define AMU_GROUP0_MAX_COUNTERS U(16) +#define AMU_GROUP1_MAX_COUNTERS U(16) + +#define AMU_AMCGCR_CG0NC_MAX U(16) + +uint64_t amu_group0_cnt_read_internal(unsigned int idx); +void amu_group0_cnt_write_internal(unsigned int idx, uint64_t val); + +uint64_t amu_group1_cnt_read_internal(unsigned int idx); +void amu_group1_cnt_write_internal(unsigned int idx, uint64_t val); +void amu_group1_set_evtype_internal(unsigned int idx, unsigned int val); + +#if __aarch64__ +uint64_t amu_group0_voffset_read_internal(unsigned int idx); +void amu_group0_voffset_write_internal(unsigned int idx, uint64_t val); + +uint64_t amu_group1_voffset_read_internal(unsigned int idx); +void amu_group1_voffset_write_internal(unsigned int idx, uint64_t val); +#endif + +#endif /* AMU_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/extensions/mpam/mpam.c b/arm-trusted-firmware/lib/extensions/mpam/mpam.c new file mode 100644 index 0000000..65601dd --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mpam/mpam.c @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +void mpam_enable(bool el2_unused) +{ + /* Check if MPAM is implemented */ + if (get_mpam_version() == 0U) { + return; + } + + /* + * Enable MPAM, and disable trapping to EL3 when lower ELs access their + * own MPAM registers. + */ + write_mpam3_el3(MPAM3_EL3_MPAMEN_BIT); + + /* + * If EL2 is implemented but unused, disable trapping to EL2 when lower + * ELs access their own MPAM registers. + * If EL2 is implemented and used, enable trapping to EL2. + */ + if (el2_unused) { + write_mpam2_el2(0ULL); + + if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) { + write_mpamhcr_el2(0ULL); + } + } else { + write_mpam2_el2(MPAM2_EL2_TRAPMPAM0EL1 | + MPAM2_EL2_TRAPMPAM1EL1); + + if ((read_mpamidr_el1() & MPAMIDR_HAS_HCR_BIT) != 0U) { + write_mpamhcr_el2(MPAMHCR_EL2_TRAP_MPAMIDR_EL1); + } + } +} diff --git a/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S b/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S new file mode 100644 index 0000000..834cee3 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global mtpmu_disable + +/* ------------------------------------------------------------- + * The functions in this file are called at entrypoint, before + * the CPU has decided whether this is a cold or a warm boot. + * Therefore there are no stack yet to rely on for a C function + * call. + * ------------------------------------------------------------- + */ + +/* + * bool mtpmu_supported(void) + * + * Return a boolean indicating whether FEAT_MTPMU is supported or not. + * + * Trash registers: r0. + */ +func mtpmu_supported + ldcopr r0, ID_DFR1 + and r0, r0, #(ID_DFR1_MTPMU_MASK >> ID_DFR1_MTPMU_SHIFT) + cmp r0, #ID_DFR1_MTPMU_SUPPORTED + mov r0, #0 + addeq r0, r0, #1 + bx lr +endfunc mtpmu_supported + +/* + * bool el_implemented(unsigned int el) + * + * Return a boolean indicating if the specified EL (2 or 3) is implemented. + * + * Trash registers: r0 + */ +func el_implemented + cmp r0, #3 + ldcopr r0, ID_PFR1 + lsreq r0, r0, #ID_PFR1_SEC_SHIFT + lsrne r0, r0, #ID_PFR1_VIRTEXT_SHIFT + /* + * ID_PFR1_VIRTEXT_MASK is the same as ID_PFR1_SEC_MASK + * so use any one of them + */ + and r0, r0, #ID_PFR1_VIRTEXT_MASK + cmp r0, #ID_PFR1_ELx_ENABLED + mov r0, #0 + addeq r0, r0, #1 + bx lr +endfunc el_implemented + +/* + * void mtpmu_disable(void) + * + * Disable mtpmu feature if supported. + * + * Trash register: r0, r1, r2 + */ +func mtpmu_disable + mov r2, lr + bl mtpmu_supported + cmp r0, #0 + bxeq r2 /* FEAT_MTPMU not supported */ + + /* FEAT_MTMPU Supported */ + mov r0, #3 + bl el_implemented + cmp r0, #0 + beq 1f + + /* EL3 implemented */ + ldcopr r0, SDCR + ldr r1, =SDCR_MTPME_BIT + bic r0, r0, r1 + stcopr r0, SDCR + + /* + * If EL3 is implemented, HDCR.MTPME is implemented as Res0 and + * FEAT_MTPMU is controlled only from EL3, so no need to perform + * any operations for EL2. + */ + isb + bx r2 +1: + /* EL3 not implemented */ + mov r0, #2 + bl el_implemented + cmp r0, #0 + bxeq r2 /* No EL2 or EL3 implemented */ + + /* EL2 implemented */ + ldcopr r0, HDCR + ldr r1, =HDCR_MTPME_BIT + orr r0, r0, r1 + stcopr r0, HDCR + isb + bx r2 +endfunc mtpmu_disable diff --git a/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S b/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S new file mode 100644 index 0000000..0a1d57b --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .global mtpmu_disable + +/* ------------------------------------------------------------- + * The functions in this file are called at entrypoint, before + * the CPU has decided whether this is a cold or a warm boot. + * Therefore there are no stack yet to rely on for a C function + * call. + * ------------------------------------------------------------- + */ + +/* + * bool mtpmu_supported(void) + * + * Return a boolean indicating whether FEAT_MTPMU is supported or not. + * + * Trash registers: x0, x1 + */ +func mtpmu_supported + mrs x0, id_aa64dfr0_el1 + mov_imm x1, ID_AA64DFR0_MTPMU_MASK + and x0, x1, x0, LSR #ID_AA64DFR0_MTPMU_SHIFT + cmp x0, ID_AA64DFR0_MTPMU_SUPPORTED + cset x0, eq + ret +endfunc mtpmu_supported + +/* + * bool el_implemented(unsigned int el_shift) + * + * Return a boolean indicating if the specified EL is implemented. + * The EL is represented as the bitmask shift on id_aa64pfr0_el1 register. + * + * Trash registers: x0, x1 + */ +func el_implemented + mrs x1, id_aa64pfr0_el1 + lsr x1, x1, x0 + cmp x1, #ID_AA64PFR0_ELX_MASK + cset x0, eq + ret +endfunc el_implemented + +/* + * void mtpmu_disable(void) + * + * Disable mtpmu feature if supported. + * + * Trash register: x0, x1, x30 + */ +func mtpmu_disable + mov x10, x30 + bl mtpmu_supported + cbz x0, exit_disable + + /* FEAT_MTMPU Supported */ + mov_imm x0, ID_AA64PFR0_EL3_SHIFT + bl el_implemented + cbz x0, 1f + + /* EL3 implemented */ + mrs x0, mdcr_el3 + mov_imm x1, MDCR_MTPME_BIT + bic x0, x0, x1 + msr mdcr_el3, x0 + + /* + * If EL3 is implemented, MDCR_EL2.MTPME is implemented as Res0 and + * FEAT_MTPMU is controlled only from EL3, so no need to perform + * any operations for EL2. + */ + isb +exit_disable: + ret x10 +1: + /* EL3 not implemented */ + mov_imm x0, ID_AA64PFR0_EL2_SHIFT + bl el_implemented + cbz x0, exit_disable + + /* EL2 implemented */ + mrs x0, mdcr_el2 + mov_imm x1, MDCR_EL2_MTPME + bic x0, x0, x1 + msr mdcr_el2, x0 + isb + ret x10 +endfunc mtpmu_disable diff --git a/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S b/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S new file mode 100644 index 0000000..d483c7d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global pauth_init_enable_el1 + .global pauth_disable_el1 + .global pauth_init_enable_el3 + .global pauth_disable_el3 + .globl pauth_load_bl31_apiakey + .globl pauth_load_bl1_apiakey_enable + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL1 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el1 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el1 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #(SCTLR_BT0_BIT | SCTLR_BT1_BIT) +#endif + msr sctlr_el1, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el1 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el1 + mrs x0, sctlr_el1 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el1, x0 + isb + ret +endfunc pauth_disable_el1 + +/* ------------------------------------------------------------- + * Program APIAKey_EL1 and enable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_init_enable_el3 + stp x29, x30, [sp, #-16]! + + /* Initialize platform key */ + bl plat_init_apkey + + /* Program instruction key A used by the Trusted Firmware */ + msr APIAKeyLo_EL1, x0 + msr APIAKeyHi_EL1, x1 + + /* Enable pointer authentication */ + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x0, x0, #SCTLR_BT_BIT +#endif + msr sctlr_el3, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc pauth_init_enable_el3 + +/* ------------------------------------------------------------- + * Disable pointer authentication in EL3 + * ------------------------------------------------------------- + */ +func pauth_disable_el3 + mrs x0, sctlr_el3 + bic x0, x0, #SCTLR_EnIA_BIT + msr sctlr_el3, x0 + isb + ret +endfunc pauth_disable_el3 + +/* ------------------------------------------------------------- + * The following functions strictly follow the AArch64 PCS + * to use x9-x17 (temporary caller-saved registers) to load + * the APIAKey_EL1 and enable pointer authentication. + * ------------------------------------------------------------- + */ +func pauth_load_bl31_apiakey + /* tpidr_el3 contains the address of cpu_data structure */ + mrs x9, tpidr_el3 + + /* Load apiakey from cpu_data */ + ldp x10, x11, [x9, #CPU_DATA_APIAKEY_OFFSET] + + /* Program instruction key A */ + msr APIAKeyLo_EL1, x10 + msr APIAKeyHi_EL1, x11 + isb + ret +endfunc pauth_load_bl31_apiakey + +func pauth_load_bl1_apiakey_enable + /* Load instruction key A used by the Trusted Firmware */ + adrp x9, bl1_apiakey + add x9, x9, :lo12:bl1_apiakey + ldp x10, x11, [x9] + + /* Program instruction key A */ + msr APIAKeyLo_EL1, x10 + msr APIAKeyHi_EL1, x11 + + /* Enable pointer authentication */ + mrs x9, sctlr_el3 + orr x9, x9, #SCTLR_EnIA_BIT + +#if ENABLE_BTI + /* Enable PAC branch type compatibility */ + bic x9, x9, #SCTLR_BT_BIT +#endif + msr sctlr_el3, x9 + isb + ret +endfunc pauth_load_bl1_apiakey_enable diff --git a/arm-trusted-firmware/lib/extensions/ras/ras_common.c b/arm-trusted-firmware/lib/extensions/ras/ras_common.c new file mode 100644 index 0000000..73fad54 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/ras/ras_common.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#ifndef PLAT_RAS_PRI +# error Platform must define RAS priority value +#endif + +/* + * Function to convert architecturally-defined primary error code SERR, + * bits[7:0] from ERRSTATUS to its corresponding error string. + */ +const char *ras_serr_to_str(unsigned int serr) +{ + const char *str[ERROR_STATUS_NUM_SERR] = { + "No error", + "IMPLEMENTATION DEFINED error", + "Data value from (non-associative) internal memory", + "IMPLEMENTATION DEFINED pin", + "Assertion failure", + "Error detected on internal data path", + "Data value from associative memory", + "Address/control value from associative memory", + "Data value from a TLB", + "Address/control value from a TLB", + "Data value from producer", + "Address/control value from producer", + "Data value from (non-associative) external memory", + "Illegal address (software fault)", + "Illegal access (software fault)", + "Illegal state (software fault)", + "Internal data register", + "Internal control register", + "Error response from slave", + "External timeout", + "Internal timeout", + "Deferred error from slave not supported at master" + }; + + /* + * All other values are reserved. Reserved values might be defined + * in a future version of the architecture + */ + if (serr >= ERROR_STATUS_NUM_SERR) + return "unknown SERR"; + + return str[serr]; +} + +/* Handler that receives External Aborts on RAS-capable systems */ +int ras_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + unsigned int i, n_handled = 0; + int probe_data, ret; + struct err_record_info *info; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .ea_reason = ea_reason, + .interrupt = 0, + .syndrome = (uint32_t) syndrome, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + for_each_err_record_info(i, info) { + assert(info->probe != NULL); + assert(info->handler != NULL); + + /* Continue probing until the record group signals no error */ + while (true) { + if (info->probe(info, &probe_data) == 0) + break; + + /* Handle error */ + ret = info->handler(info, probe_data, &err_data); + if (ret != 0) + return ret; + + n_handled++; + } + } + + return (n_handled != 0U) ? 1 : 0; +} + +#if EL3_EXCEPTION_HANDLING + +#ifndef PLAT_RAS_PRI +# error Platform must define RAS priority value +#endif + + +#if ENABLE_ASSERTIONS +static void assert_interrupts_sorted(void) +{ + unsigned int i, last; + struct ras_interrupt *start = ras_interrupt_mappings.intrs; + + if (ras_interrupt_mappings.num_intrs == 0UL) + return; + + last = start[0].intr_number; + for (i = 1; i < ras_interrupt_mappings.num_intrs; i++) { + assert(start[i].intr_number > last); + last = start[i].intr_number; + } +} +#endif + +/* + * Given an RAS interrupt number, locate the registered handler and call it. If + * no handler was found for the interrupt number, this function panics. + */ +static int ras_interrupt_handler(uint32_t intr_raw, uint32_t flags, + void *handle, void *cookie) +{ + struct ras_interrupt *ras_inrs = ras_interrupt_mappings.intrs; + struct ras_interrupt *selected = NULL; + int probe_data = 0; + int start, end, mid, ret __unused; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .interrupt = intr_raw, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + assert(ras_interrupt_mappings.num_intrs > 0UL); + + start = 0; + end = (int)ras_interrupt_mappings.num_intrs - 1; + while (start <= end) { + mid = ((end + start) / 2); + if (intr_raw == ras_inrs[mid].intr_number) { + selected = &ras_inrs[mid]; + break; + } else if (intr_raw < ras_inrs[mid].intr_number) { + /* Move left */ + end = mid - 1; + } else { + /* Move right */ + start = mid + 1; + } + } + + if (selected == NULL) { + ERROR("RAS interrupt %u has no handler!\n", intr_raw); + panic(); + } + + if (selected->err_record->probe != NULL) { + ret = selected->err_record->probe(selected->err_record, &probe_data); + assert(ret != 0); + } + + /* Call error handler for the record group */ + assert(selected->err_record->handler != NULL); + (void) selected->err_record->handler(selected->err_record, probe_data, + &err_data); + + return 0; +} +#endif + +void __init ras_init(void) +{ +#if EL3_EXCEPTION_HANDLING + +#if ENABLE_ASSERTIONS + /* Check RAS interrupts are sorted */ + assert_interrupts_sorted(); +#endif + + /* Register RAS priority handler */ + ehf_register_priority_handler(PLAT_RAS_PRI, ras_interrupt_handler); + +#endif /* EL3_EXCEPTION_HANDLING */ +} diff --git a/arm-trusted-firmware/lib/extensions/ras/std_err_record.c b/arm-trusted-firmware/lib/extensions/ras/std_err_record.c new file mode 100644 index 0000000..c03fbbe --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/ras/std_err_record.c @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* + * Probe for error in memory-mapped registers containing error records + * implemented Standard Error Record format. Upon detecting an error, set probe + * data to the index of the record in error, and return 1; otherwise, return 0. + */ +int ser_probe_memmap(uintptr_t base, unsigned int size_num_k, int *probe_data) +{ + unsigned int num_records, num_group_regs, i; + uint64_t gsr; + + assert(base != 0UL); + + /* Only 4K supported for now */ + assert(size_num_k == STD_ERR_NODE_SIZE_NUM_K); + + num_records = (unsigned int) + (mmio_read_32(ERR_DEVID(base, size_num_k)) & ERR_DEVID_MASK); + + /* A group register shows error status for 2^6 error records */ + num_group_regs = (num_records >> 6U) + 1U; + + /* Iterate through group registers to find a record in error */ + for (i = 0; i < num_group_regs; i++) { + gsr = mmio_read_64(ERR_GSR(base, size_num_k, i)); + if (gsr == 0ULL) + continue; + + /* Return the index of the record in error */ + if (probe_data != NULL) + *probe_data = (((int) (i << 6U)) + __builtin_ctzll(gsr)); + + return 1; + } + + return 0; +} + +/* + * Probe for error in System Registers where error records are implemented in + * Standard Error Record format. Upon detecting an error, set probe data to the + * index of the record in error, and return 1; otherwise, return 0. + */ +int ser_probe_sysreg(unsigned int idx_start, unsigned int num_idx, int *probe_data) +{ + unsigned int i; + uint64_t status; + unsigned int max_idx __unused = + ((unsigned int) read_erridr_el1()) & ERRIDR_MASK; + + assert(idx_start < max_idx); + assert(check_u32_overflow(idx_start, num_idx) == 0); + assert((idx_start + num_idx - 1U) < max_idx); + + for (i = 0; i < num_idx; i++) { + /* Select the error record */ + ser_sys_select_record(idx_start + i); + + /* Retrieve status register from the error record */ + status = read_erxstatus_el1(); + + /* Check for valid field in status */ + if (ERR_STATUS_GET_FIELD(status, V) != 0U) { + if (probe_data != NULL) + *probe_data = (int) i; + return 1; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/lib/extensions/sme/sme.c b/arm-trusted-firmware/lib/extensions/sme/sme.c new file mode 100644 index 0000000..1c2b984 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sme/sme.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +static bool feat_sme_supported(void) +{ + uint64_t features; + + features = read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SME_SHIFT; + return (features & ID_AA64PFR1_EL1_SME_MASK) != 0U; +} + +static bool feat_sme_fa64_supported(void) +{ + uint64_t features; + + features = read_id_aa64smfr0_el1(); + return (features & ID_AA64SMFR0_EL1_FA64_BIT) != 0U; +} + +void sme_enable(cpu_context_t *context) +{ + u_register_t reg; + u_register_t cptr_el3; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!feat_sme_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Enable SME in CPTR_EL3. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg |= ESM_BIT; + write_ctx_reg(state, CTX_CPTR_EL3, reg); + + /* Set the ENTP2 bit in SCR_EL3 to enable access to TPIDR2_EL0. */ + reg = read_ctx_reg(state, CTX_SCR_EL3); + reg |= SCR_ENTP2_BIT; + write_ctx_reg(state, CTX_SCR_EL3, reg); + + /* Set CPTR_EL3.ESM bit so we can write SMCR_EL3 without trapping. */ + cptr_el3 = read_cptr_el3(); + write_cptr_el3(cptr_el3 | ESM_BIT); + + /* + * Set the max LEN value and FA64 bit. This register is set up globally + * to be the least restrictive, then lower ELs can restrict as needed + * using SMCR_EL2 and SMCR_EL1. + */ + reg = SMCR_ELX_LEN_MASK; + if (feat_sme_fa64_supported()) { + VERBOSE("[SME] FA64 enabled\n"); + reg |= SMCR_ELX_FA64_BIT; + } + write_smcr_el3(reg); + + /* Reset CPTR_EL3 value. */ + write_cptr_el3(cptr_el3); + + /* Enable SVE/FPU in addition to SME. */ + sve_enable(context); +} + +void sme_disable(cpu_context_t *context) +{ + u_register_t reg; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!feat_sme_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Disable SME, SVE, and FPU since they all share registers. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg &= ~ESM_BIT; /* Trap SME */ + reg &= ~CPTR_EZ_BIT; /* Trap SVE */ + reg |= TFP_BIT; /* Trap FPU/SIMD */ + write_ctx_reg(state, CTX_CPTR_EL3, reg); + + /* Disable access to TPIDR2_EL0. */ + reg = read_ctx_reg(state, CTX_SCR_EL3); + reg &= ~SCR_ENTP2_BIT; + write_ctx_reg(state, CTX_SCR_EL3, reg); +} diff --git a/arm-trusted-firmware/lib/extensions/spe/spe.c b/arm-trusted-firmware/lib/extensions/spe/spe.c new file mode 100644 index 0000000..d747efc --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/spe/spe.c @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2017-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +static inline void psb_csync(void) +{ + /* + * The assembler does not yet understand the psb csync mnemonic + * so use the equivalent hint instruction. + */ + __asm__ volatile("hint #17"); +} + +bool spe_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_PMS_SHIFT; + return (features & ID_AA64DFR0_PMS_MASK) > 0ULL; +} + +void spe_enable(bool el2_unused) +{ + uint64_t v; + + if (!spe_supported()) + return; + + if (el2_unused) { + /* + * MDCR_EL2.TPMS (ARM v8.2): Do not trap statistical + * profiling controls to EL2. + * + * MDCR_EL2.E2PB (ARM v8.2): SPE enabled in Non-secure + * state. Accesses to profiling buffer controls at + * Non-secure EL1 are not trapped to EL2. + */ + v = read_mdcr_el2(); + v &= ~MDCR_EL2_TPMS; + v |= MDCR_EL2_E2PB(MDCR_EL2_E2PB_EL1); + write_mdcr_el2(v); + } + + /* + * MDCR_EL2.NSPB (ARM v8.2): SPE enabled in Non-secure state + * and disabled in secure state. Accesses to SPE registers at + * S-EL1 generate trap exceptions to EL3. + * + * MDCR_EL3.EnPMSN (ARM v8.7): Do not trap access to PMSNEVFR_EL1 + * register at NS-EL1 or NS-EL2 to EL3 if FEAT_SPEv1p2 is implemented. + * Setting this bit to 1 doesn't have any effect on it when + * FEAT_SPEv1p2 not implemented. + */ + v = read_mdcr_el3(); + v |= MDCR_NSPB(MDCR_NSPB_EL1) | MDCR_EnPMSN_BIT; + write_mdcr_el3(v); +} + +void spe_disable(void) +{ + uint64_t v; + + if (!spe_supported()) + return; + + /* Drain buffered data */ + psb_csync(); + dsbnsh(); + + /* Disable profiling buffer */ + v = read_pmblimitr_el1(); + v &= ~(1ULL << 0); + write_pmblimitr_el1(v); + isb(); +} + +static void *spe_drain_buffers_hook(const void *arg) +{ + if (!spe_supported()) + return (void *)-1; + + /* Drain buffered data */ + psb_csync(); + dsbnsh(); + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(cm_entering_secure_world, spe_drain_buffers_hook); diff --git a/arm-trusted-firmware/lib/extensions/sve/sve.c b/arm-trusted-firmware/lib/extensions/sve/sve.c new file mode 100644 index 0000000..aa8904b --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sve/sve.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * Converts SVE vector size restriction in bytes to LEN according to ZCR_EL3 documentation. + * VECTOR_SIZE = (LEN+1) * 128 + */ +#define CONVERT_SVE_LENGTH(x) (((x / 128) - 1)) + +static bool sve_supported(void) +{ + uint64_t features; + + features = read_id_aa64pfr0_el1() >> ID_AA64PFR0_SVE_SHIFT; + return (features & ID_AA64PFR0_SVE_MASK) == 1U; +} + +void sve_enable(cpu_context_t *context) +{ + u_register_t cptr_el3; + + if (!sve_supported()) { + return; + } + + cptr_el3 = read_ctx_reg(get_el3state_ctx(context), CTX_CPTR_EL3); + + /* Enable access to SVE functionality for all ELs. */ + cptr_el3 = (cptr_el3 | CPTR_EZ_BIT) & ~(TFP_BIT); + write_ctx_reg(get_el3state_ctx(context), CTX_CPTR_EL3, cptr_el3); + + /* Restrict maximum SVE vector length (SVE_VECTOR_LENGTH+1) * 128. */ + write_ctx_reg(get_el3state_ctx(context), CTX_ZCR_EL3, + (ZCR_EL3_LEN_MASK & CONVERT_SVE_LENGTH(512))); +} + +void sve_disable(cpu_context_t *context) +{ + u_register_t reg; + el3_state_t *state; + + /* Make sure SME is implemented in hardware before continuing. */ + if (!sve_supported()) { + return; + } + + /* Get the context state. */ + state = get_el3state_ctx(context); + + /* Disable SVE and FPU since they share registers. */ + reg = read_ctx_reg(state, CTX_CPTR_EL3); + reg &= ~CPTR_EZ_BIT; /* Trap SVE */ + reg |= TFP_BIT; /* Trap FPU/SIMD */ + write_ctx_reg(state, CTX_CPTR_EL3, reg); +} diff --git a/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c new file mode 100644 index 0000000..89b8029 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool sys_reg_trace_supported(void) +{ + uint32_t features; + + features = read_id_dfr0() >> ID_DFR0_COPTRC_SHIFT; + return ((features & ID_DFR0_COPTRC_MASK) == + ID_DFR0_COPTRC_SUPPORTED); +} + +void sys_reg_trace_enable(void) +{ + uint32_t val; + + if (sys_reg_trace_supported()) { + /* + * NSACR.NSTRCDIS = b0 + * enable NS system register access to implemented trace + * registers. + */ + val = read_nsacr(); + val &= ~NSTRCDIS_BIT; + write_nsacr(val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c new file mode 100644 index 0000000..960d698 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool sys_reg_trace_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEVER_SHIFT; + return ((features & ID_AA64DFR0_TRACEVER_MASK) == + ID_AA64DFR0_TRACEVER_SUPPORTED); +} + +void sys_reg_trace_enable(cpu_context_t *ctx) +{ + uint64_t val; + + if (sys_reg_trace_supported()) { + /* Retrieve CPTR_EL3 value from the given context 'ctx', + * and update CPTR_EL3.TTA bit to 0. + * This function is called while switching context to NS to + * allow system trace register access to NS-EL2 and NS-EL1 + * when NS-EL2 is implemented but not used. + */ + val = read_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3); + val &= ~TTA_BIT; + write_ctx_reg(get_el3state_ctx(ctx), CTX_CPTR_EL3, val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/trbe/trbe.c b/arm-trusted-firmware/lib/extensions/trbe/trbe.c new file mode 100644 index 0000000..9f754d5 --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trbe/trbe.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +static void tsb_csync(void) +{ + /* + * The assembler does not yet understand the tsb csync mnemonic + * so use the equivalent hint instruction. + */ + __asm__ volatile("hint #18"); +} + +static bool trbe_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEBUFFER_SHIFT; + return ((features & ID_AA64DFR0_TRACEBUFFER_MASK) == + ID_AA64DFR0_TRACEBUFFER_SUPPORTED); +} + +void trbe_enable(void) +{ + uint64_t val; + + if (trbe_supported()) { + /* + * MDCR_EL3.NSTB = 0b11 + * Allow access of trace buffer control registers from NS-EL1 + * and NS-EL2, tracing is prohibited in Secure and Realm state + * (if implemented). + */ + val = read_mdcr_el3(); + val |= MDCR_NSTB(MDCR_NSTB_EL1); + write_mdcr_el3(val); + } +} + +static void *trbe_drain_trace_buffers_hook(const void *arg __unused) +{ + if (trbe_supported()) { + /* + * Before switching from normal world to secure world + * the trace buffers need to be drained out to memory. This is + * required to avoid an invalid memory access when TTBR is switched + * for entry to S-EL1. + */ + tsb_csync(); + dsbnsh(); + } + + return (void *)0; +} + +SUBSCRIBE_TO_EVENT(cm_entering_secure_world, trbe_drain_trace_buffers_hook); diff --git a/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c b/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c new file mode 100644 index 0000000..834092d --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool trf_supported(void) +{ + uint32_t features; + + features = read_id_dfr0() >> ID_DFR0_TRACEFILT_SHIFT; + return ((features & ID_DFR0_TRACEFILT_MASK) == + ID_DFR0_TRACEFILT_SUPPORTED); +} + +void trf_enable(void) +{ + uint32_t val; + + if (trf_supported()) { + /* + * Allow access of trace filter control registers from + * non-monitor mode + */ + val = read_sdcr(); + val &= ~SDCR_TTRF_BIT; + write_sdcr(val); + } +} diff --git a/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c b/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c new file mode 100644 index 0000000..1da5dce --- /dev/null +++ b/arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static bool trf_supported(void) +{ + uint64_t features; + + features = read_id_aa64dfr0_el1() >> ID_AA64DFR0_TRACEFILT_SHIFT; + return ((features & ID_AA64DFR0_TRACEFILT_MASK) == + ID_AA64DFR0_TRACEFILT_SUPPORTED); +} + +void trf_enable(void) +{ + uint64_t val; + + if (trf_supported()) { + /* + * MDCR_EL3.TTRF = b0 + * Allow access of trace filter control registers from NS-EL2 + * and NS-EL1 when NS-EL2 is implemented but not used + */ + val = read_mdcr_el3(); + val &= ~MDCR_TTRF_BIT; + write_mdcr_el3(val); + } +} diff --git a/arm-trusted-firmware/lib/fconf/fconf.c b/arm-trusted-firmware/lib/fconf/fconf.c new file mode 100644 index 0000000..b1d6eaa --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf.c @@ -0,0 +1,78 @@ +/* + * Copyright (c) 2019-2022, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +int fconf_load_config(unsigned int image_id) +{ + int err; + const struct dyn_cfg_dtb_info_t *config_info; + + assert((image_id == FW_CONFIG_ID) || (image_id == TB_FW_CONFIG_ID)); + + image_info_t config_image_info = { + .h.type = (uint8_t)PARAM_IMAGE_BINARY, + .h.version = (uint8_t)VERSION_2, + .h.size = (uint16_t)sizeof(image_info_t), + .h.attr = 0 + }; + + config_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, image_id); + assert(config_info != NULL); + + config_image_info.image_base = config_info->config_addr; + config_image_info.image_max_size = config_info->config_max_size; + + VERBOSE("FCONF: Loading config with image ID: %u\n", image_id); + err = load_auth_image(image_id, &config_image_info); + if (err != 0) { + VERBOSE("Failed to load config %u\n", image_id); + return err; + } + + INFO("FCONF: Config file with image ID:%u loaded at address = 0x%lx\n", + image_id, config_image_info.image_base); + + return 0; +} + +void fconf_populate(const char *config_type, uintptr_t config) +{ + assert(config != 0UL); + + /* Check if the pointer to DTB is correct */ + if (fdt_check_header((void *)config) != 0) { + ERROR("FCONF: Invalid DTB file passed for %s\n", config_type); + panic(); + } + + INFO("FCONF: Reading %s firmware configuration file from: 0x%lx\n", config_type, config); + + /* Go through all registered populate functions */ + IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_START__, start); + IMPORT_SYM(struct fconf_populator *, __FCONF_POPULATOR_END__, end); + const struct fconf_populator *populator; + + for (populator = start; populator != end; populator++) { + assert((populator->info != NULL) && (populator->populate != NULL)); + + if (strcmp(populator->config_type, config_type) == 0) { + INFO("FCONF: Reading firmware configuration information for: %s\n", populator->info); + if (populator->populate(config) != 0) { + /* TODO: handle property miss */ + panic(); + } + } + } +} diff --git a/arm-trusted-firmware/lib/fconf/fconf.mk b/arm-trusted-firmware/lib/fconf/fconf.mk new file mode 100644 index 0000000..fb88910 --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2019-2021, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +FCONF_SOURCES := lib/fconf/fconf.c +FCONF_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_DYN_SOURCES := lib/fconf/fconf_dyn_cfg_getter.c +FCONF_DYN_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_AMU_SOURCES := lib/fconf/fconf_amu_getter.c +FCONF_AMU_SOURCES += ${FDT_WRAPPERS_SOURCES} + +FCONF_MPMM_SOURCES := lib/fconf/fconf_mpmm_getter.c +FCONF_MPMM_SOURCES += ${FDT_WRAPPERS_SOURCES} diff --git a/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c b/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c new file mode 100644 index 0000000..eff309c --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_amu_getter.c @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct fconf_amu_config fconf_amu_config; +static struct amu_topology fconf_amu_topology_; + +/* + * Populate the core-specific AMU structure with information retrieved from a + * device tree. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_amu_cpu_amu(const void *fdt, int parent, + struct amu_core *amu) +{ + int ret = 0; + int node = 0; + + fdt_for_each_subnode(node, fdt, parent) { + const char *name; + const char *value; + int len; + + uintptr_t idx = 0U; + + name = fdt_get_name(fdt, node, &len); + if (strncmp(name, "counter@", 8) != 0) { + continue; + } + + ret = fdt_get_reg_props_by_index(fdt, node, 0, &idx, NULL); + if (ret < 0) { + break; + } + + value = fdt_getprop(fdt, node, "enable-at-el3", &len); + if ((value == NULL) && (len != -FDT_ERR_NOTFOUND)) { + break; + } + + if (len != -FDT_ERR_NOTFOUND) { + amu->enable |= (1 << idx); + } + } + + if ((node < 0) && (node != -FDT_ERR_NOTFOUND)) { + return node; + } + + return ret; +} + +/* + * Within a `cpu` node, attempt to dereference the `amu` property, and populate + * the AMU information for the core. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_amu_cpu(const void *fdt, int node, uintptr_t mpidr) +{ + int ret; + int idx; + + uint32_t amu_phandle; + struct amu_core *amu; + + ret = fdt_read_uint32(fdt, node, "amu", &amu_phandle); + if (ret < 0) { + if (ret == -FDT_ERR_NOTFOUND) { + ret = 0; + } + + return ret; + } + + node = fdt_node_offset_by_phandle(fdt, amu_phandle); + if (node < 0) { + return node; + } + + idx = plat_core_pos_by_mpidr(mpidr); + if (idx < 0) { + return -FDT_ERR_BADVALUE; + } + + amu = &fconf_amu_topology_.cores[idx]; + + return fconf_populate_amu_cpu_amu(fdt, node, amu); +} + +/* + * Populates the global `amu_topology` structure based on what's described by + * the hardware configuration device tree blob. + * + * The device tree is expected to provide an `amu` property for each `cpu` node, + * like so: + * + * cpu@0 { + * amu = <&cpu0_amu>; + * }; + * + * amus { + * cpu0_amu: amu-0 { + * counters { + * #address-cells = <2>; + * #size-cells = <0>; + * + * counter@x,y { + * reg = ; // Group x, counter y + * }; + * }; + * }; + * }; + */ +static int fconf_populate_amu(uintptr_t config) +{ + int ret = fdtw_for_each_cpu( + (const void *)config, fconf_populate_amu_cpu); + if (ret == 0) { + fconf_amu_config.topology = &fconf_amu_topology_; + } else { + ERROR("FCONF: failed to parse AMU information: %d\n", ret); + } + + return ret; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, amu, fconf_populate_amu); diff --git a/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c b/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c new file mode 100644 index 0000000..ae59d8c --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_cot_getter.c @@ -0,0 +1,497 @@ +/* + * Copyright (c) 2020-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include MBEDTLS_CONFIG_FILE +#include +#include +#include +#include + +#include + +/* static structures used during authentication process */ +static auth_param_type_desc_t sig = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG, 0); +static auth_param_type_desc_t sig_alg = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_SIG_ALG, 0); +static auth_param_type_desc_t raw_data = AUTH_PARAM_TYPE_DESC( + AUTH_PARAM_RAW_DATA, 0); + +/* pointers to an array of CoT descriptors */ +static const auth_img_desc_t *cot_desc[MAX_NUMBER_IDS]; +/* array of CoT descriptors */ +static auth_img_desc_t auth_img_descs[MAX_NUMBER_IDS]; + +/* array of authentication methods structures */ +static auth_method_desc_t auth_methods[MAX_NUMBER_IDS * AUTH_METHOD_NUM]; +static OBJECT_POOL_ARRAY(auth_methods_pool, auth_methods); + +/* array of authentication params structures */ +static auth_param_desc_t auth_params[MAX_NUMBER_IDS * COT_MAX_VERIFIED_PARAMS]; +static OBJECT_POOL_ARRAY(auth_params_pool, auth_params); + +/* array of authentication param type structures */ +static auth_param_type_desc_t auth_param_type_descs[MAX_NUMBER_IDS]; +static OBJECT_POOL_ARRAY(auth_param_type_descs_pool, auth_param_type_descs); + +/* + * array of OIDs + * Object IDs are used to search hash, pk, counter values in certificate. + * As per binding we have below 2 combinations: + * 1. Certificates are validated using nv-cntr and pk + * 2. Raw images are authenticated using hash + * Hence in worst case, there are maximum 2 OIDs per image/certificate + */ +static unsigned char oids[(MAX_NUMBER_IDS * 2)][MAX_OID_NAME_LEN]; +static OBJECT_POOL_ARRAY(oid_pool, oids); + +/* An array of auth buffer which holds hashes and pk + * ToDo: Size decided with the current number of images and + * certificates which are available in CoT. Size of these buffers bound to + * increase in the future on the addition of images/certificates. + */ +static unsigned char hash_auth_bufs[20][HASH_DER_LEN]; +static OBJECT_POOL_ARRAY(hash_auth_buf_pool, hash_auth_bufs); +static unsigned char pk_auth_bufs[12][PK_DER_LEN]; +static OBJECT_POOL_ARRAY(pk_auth_buf_pool, pk_auth_bufs); + +/******************************************************************************* + * update_parent_auth_data() - Update authentication data structure + * @auth_desc[in]: Pointer to the auth image descriptor + * @type_desc[in]: Pointer to authentication parameter + * @auth_buf_size[in]: Buffer size to hold pk or hash + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int update_parent_auth_data(const auth_img_desc_t *auth_desc, + auth_param_type_desc_t *type_desc, + unsigned int auth_buf_size) +{ + unsigned int i; + auth_param_desc_t *auth_data = &auth_desc->authenticated_data[0]; + unsigned char *auth_buf; + + for (i = 0U; i < COT_MAX_VERIFIED_PARAMS; i++) { + if (auth_data[i].type_desc == type_desc) { + return 0; + } + if (auth_data[i].type_desc == NULL) { + break; + } + } + + if (auth_buf_size == HASH_DER_LEN) { + auth_buf = pool_alloc(&hash_auth_buf_pool); + } else if (auth_buf_size == PK_DER_LEN) { + auth_buf = pool_alloc(&pk_auth_buf_pool); + } else { + return -1; + } + + if (i < COT_MAX_VERIFIED_PARAMS) { + auth_data[i].type_desc = type_desc; + auth_data[i].data.ptr = auth_buf; + auth_data[i].data.len = auth_buf_size; + } else { + ERROR("Out of authentication data array\n"); + return -1; + } + + return 0; +} + +/******************************************************************************* + * get_auth_param_type_desc() - Get pointer of authentication parameter + * @img_id[in]: Image Id + * @type_desc[out]: Pointer to authentication parameter + * @buf_size[out]: Buffer size which hold hash/pk + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_auth_param_type_desc(unsigned int img_id, + auth_param_type_desc_t **type_desc, + unsigned int *buf_size) +{ + auth_method_desc_t *img_auth_method = NULL; + img_type_t type = auth_img_descs[img_id].img_type; + + if (type == IMG_CERT) { + img_auth_method = + &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_SIG]; + *type_desc = img_auth_method->param.sig.pk; + *buf_size = PK_DER_LEN; + } else if (type == IMG_RAW) { + img_auth_method = + &auth_img_descs[img_id].img_auth_methods[AUTH_METHOD_HASH]; + *type_desc = img_auth_method->param.hash.hash; + *buf_size = HASH_DER_LEN; + } else { + return -1; + } + + return 0; +} + +/******************************************************************************* + * set_auth_method() - Update global auth image descriptors with authentication + * method data + * @auth_method_type[in]: Type of authentication method + * @oid[in]: Object Idetifier for pk/hash search + * @auth_method[in]: Pointer to authentication method to set + ******************************************************************************/ +static void set_auth_method(auth_method_type_t auth_method_type, char *oid, + auth_method_desc_t *auth_method) +{ + auth_param_type_t auth_param_type = AUTH_PARAM_NONE; + auth_param_type_desc_t *auth_param_type_desc; + + assert(auth_method != NULL); + + auth_param_type_desc = pool_alloc(&auth_param_type_descs_pool); + auth_method->type = auth_method_type; + + if (auth_method_type == AUTH_METHOD_SIG) { + auth_param_type = AUTH_PARAM_PUB_KEY; + auth_method->param.sig.sig = &sig; + auth_method->param.sig.alg = &sig_alg; + auth_method->param.sig.data = &raw_data; + auth_method->param.sig.pk = auth_param_type_desc; + } else if (auth_method_type == AUTH_METHOD_HASH) { + auth_param_type = AUTH_PARAM_HASH; + auth_method->param.hash.data = &raw_data; + auth_method->param.hash.hash = auth_param_type_desc; + } else if (auth_method_type == AUTH_METHOD_NV_CTR) { + auth_param_type = AUTH_PARAM_NV_CTR; + auth_method->param.nv_ctr.cert_nv_ctr = auth_param_type_desc; + auth_method->param.nv_ctr.plat_nv_ctr = auth_param_type_desc; + } + + auth_param_type_desc->type = auth_param_type; + auth_param_type_desc->cookie = (void *)oid; +} + +/******************************************************************************* + * get_oid() - get object identifier from device tree + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @prop[in]: Property to read from the given node + * @oid[out]: Object Indentifier of key/hash/nv-counter in certificate + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_oid(const void *dtb, int node, const char *prop, char **oid) +{ + uint32_t phandle; + int rc; + + rc = fdt_read_uint32(dtb, node, prop, &phandle); + if (rc < 0) { + return rc; + } + + node = fdt_node_offset_by_phandle(dtb, phandle); + if (node < 0) { + return node; + } + + *oid = pool_alloc(&oid_pool); + rc = fdtw_read_string(dtb, node, "oid", *oid, MAX_OID_NAME_LEN); + + return rc; +} + +/******************************************************************************* + * populate_and_set_auth_methods() - Populate auth method parameters from + * device tree and set authentication method + * structure. + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @img_id[in]: Image identifier + * @type[in]: Type of image + * @root_certificate[in]:Root certificate (authenticated by ROTPK) + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_and_set_auth_methods(const void *dtb, int node, + unsigned int img_id, img_type_t type, + bool root_certificate) +{ + auth_method_type_t auth_method_type = AUTH_METHOD_NONE; + int rc; + char *oid = NULL; + + auth_method_desc_t *auth_method = pool_alloc_n(&auth_methods_pool, + AUTH_METHOD_NUM); + + /* + * This is as per binding document where certificates are + * verified by signature and images are verified by hash. + */ + if (type == IMG_CERT) { + if (root_certificate) { + oid = NULL; + } else { + rc = get_oid(dtb, node, "signing-key", &oid); + if (rc < 0) { + ERROR("FCONF: Can't read %s property\n", + "signing-key"); + return rc; + } + } + auth_method_type = AUTH_METHOD_SIG; + } else if (type == IMG_RAW) { + rc = get_oid(dtb, node, "hash", &oid); + if (rc < 0) { + ERROR("FCONF: Can't read %s property\n", + "hash"); + return rc; + } + auth_method_type = AUTH_METHOD_HASH; + } else { + return -1; + } + + set_auth_method(auth_method_type, oid, + &auth_method[auth_method_type]); + + /* Retrieve the optional property */ + rc = get_oid(dtb, node, "antirollback-counter", &oid); + if (rc == 0) { + auth_method_type = AUTH_METHOD_NV_CTR; + set_auth_method(auth_method_type, oid, + &auth_method[auth_method_type]); + } + + auth_img_descs[img_id].img_auth_methods = &auth_method[0]; + + return 0; +} + +/******************************************************************************* + * get_parent_img_id() - Get parent image id for given child node + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the child node + * @parent_img_id[out]: Image id of parent + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int get_parent_img_id(const void *dtb, int node, + unsigned int *parent_img_id) +{ + uint32_t phandle; + int err; + + err = fdt_read_uint32(dtb, node, "parent", &phandle); + if (err < 0) { + ERROR("FCONF: Could not read %s property in node\n", + "parent"); + return err; + } + + node = fdt_node_offset_by_phandle(dtb, phandle); + if (node < 0) { + ERROR("FCONF: Failed to locate node using its phandle\n"); + return node; + } + + err = fdt_read_uint32(dtb, node, "image-id", parent_img_id); + if (err < 0) { + ERROR("FCONF: Could not read %s property in node\n", + "image-id"); + } + + return err; +} + +/******************************************************************************* + * set_desc_data() - Update data in descriptor's structure + * @dtb[in]: Pointer to the device tree blob in memory + * @node[in]: Offset of the node + * @type[in]: Type of image (RAW/CERT) + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int set_desc_data(const void *dtb, int node, img_type_t type) +{ + int rc; + bool root_certificate = false; + unsigned int img_id, parent_img_id; + + rc = fdt_read_uint32(dtb, node, "image-id", &img_id); + if (rc < 0) { + ERROR("FCONF: Can't find property %s in node\n", + "image-id"); + return rc; + } + + if (fdt_getprop(dtb, node, "root-certificate", + NULL) != NULL) { + root_certificate = true; + } + + if (!root_certificate) { + rc = get_parent_img_id(dtb, node, &parent_img_id); + if (rc < 0) { + return rc; + } + auth_img_descs[img_id].parent = &auth_img_descs[parent_img_id]; + } + + auth_img_descs[img_id].img_id = img_id; + auth_img_descs[img_id].img_type = type; + + rc = populate_and_set_auth_methods(dtb, node, img_id, type, + root_certificate); + if (rc < 0) { + return rc; + } + + if (type == IMG_CERT) { + auth_param_desc_t *auth_param = + pool_alloc_n(&auth_params_pool, + COT_MAX_VERIFIED_PARAMS); + auth_img_descs[img_id].authenticated_data = &auth_param[0]; + } + + cot_desc[img_id] = &auth_img_descs[img_id]; + + return rc; +} + +/******************************************************************************* + * populate_manifest_descs() - Populate CoT descriptors and update global + * certificate structures + * @dtb[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_manifest_descs(const void *dtb) +{ + int node, child; + int rc; + + /* + * Assert the node offset points to "arm, cert-descs" + * compatible property + */ + const char *compatible_str = "arm, cert-descs"; + + 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 = set_desc_data(dtb, child, IMG_CERT); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +/******************************************************************************* + * populate_image_descs() - Populate CoT descriptors and update global + * image descriptor structures. + * @dtb[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int populate_image_descs(const void *dtb) +{ + int node, child; + int rc; + + /* + * Assert the node offset points to "arm, img-descs" + * compatible property + */ + const char *compatible_str = "arm, img-descs"; + + 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 = set_desc_data(dtb, child, IMG_RAW); + if (rc < 0) { + return rc; + } + } + + return 0; +} + +/******************************************************************************* + * fconf_populate_cot_descs() - Populate CoT descriptors and update global + * structures + * @config[in]: Pointer to the device tree blob in memory + * + * Return 0 on success or an error value otherwise. + ******************************************************************************/ +static int fconf_populate_cot_descs(uintptr_t config) +{ + auth_param_type_desc_t *type_desc = NULL; + unsigned int auth_buf_size = 0U; + int rc; + + /* As libfdt uses void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* populate manifest descs information */ + rc = populate_manifest_descs(dtb); + if (rc < 0) { + ERROR("FCONF: population of %s descs failed %d\n", + "manifest", rc); + return rc; + } + + /* populate image descs information */ + rc = populate_image_descs(dtb); + if (rc < 0) { + ERROR("FCONF: population of %s descs failed %d\n", + "images", rc); + return rc; + } + + /* update parent's authentication data */ + for (unsigned int i = 0U; i < MAX_NUMBER_IDS; i++) { + if (auth_img_descs[i].parent != NULL) { + rc = get_auth_param_type_desc(i, + &type_desc, + &auth_buf_size); + if (rc < 0) { + ERROR("FCONF: failed to get auth data %d\n", + rc); + return rc; + } + + rc = update_parent_auth_data(auth_img_descs[i].parent, + type_desc, + auth_buf_size); + if (rc < 0) { + ERROR("FCONF: auth data update failed %d\n", + rc); + return rc; + } + } + } + + return rc; +} + +FCONF_REGISTER_POPULATOR(TB_FW, cot_desc, fconf_populate_cot_descs); +REGISTER_COT(cot_desc); diff --git a/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c b/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c new file mode 100644 index 0000000..34623fb --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +/* We currently use FW, TB_FW, SOC_FW, TOS_FW, NT_FW and HW configs */ +#define MAX_DTB_INFO U(6) +/* + * Compile time assert if FW_CONFIG_ID is 0 which is more + * unlikely as 0 is a valid image ID for FIP as per the current + * code but still to avoid code breakage in case of unlikely + * event when image IDs get changed. + */ +CASSERT(FW_CONFIG_ID != U(0), assert_invalid_fw_config_id); + +static struct dyn_cfg_dtb_info_t dtb_infos[MAX_DTB_INFO]; +static OBJECT_POOL_ARRAY(dtb_info_pool, dtb_infos); + +/* + * This function is used to alloc memory for config information from + * global pool and set the configuration information. + */ +void set_config_info(uintptr_t config_addr, uint32_t config_max_size, + unsigned int config_id) +{ + struct dyn_cfg_dtb_info_t *dtb_info; + + dtb_info = pool_alloc(&dtb_info_pool); + dtb_info->config_addr = config_addr; + dtb_info->config_max_size = config_max_size; + dtb_info->config_id = config_id; +} + +/* Get index of the config_id image */ +unsigned int dyn_cfg_dtb_info_get_index(unsigned int config_id) +{ + unsigned int index; + + /* Positions index to the proper config-id */ + for (index = 0U; index < MAX_DTB_INFO; index++) { + if (dtb_infos[index].config_id == config_id) { + return index; + } + } + + return FCONF_INVALID_IDX; +} + +struct dyn_cfg_dtb_info_t *dyn_cfg_dtb_info_getter(unsigned int config_id) +{ + /* Positions index to the proper config-id */ + unsigned int index = dyn_cfg_dtb_info_get_index(config_id); + + if (index < MAX_DTB_INFO) { + return &dtb_infos[index]; + } + + WARN("FCONF: Invalid config id %u\n", config_id); + + return NULL; +} + +int fconf_populate_dtb_registry(uintptr_t config) +{ + int rc; + int node, child; + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* + * In case of BL1, fw_config dtb information is already + * populated in global dtb_infos array by 'set_fw_config_info' + * function, Below check is present to avoid re-population of + * fw_config information. + * + * Other BLs, satisfy below check and populate fw_config information + * in global dtb_infos array. + */ + if (dtb_infos[0].config_id == 0U) { + uint32_t config_max_size = fdt_totalsize(dtb); + set_config_info(config, config_max_size, FW_CONFIG_ID); + } + + /* Find the node offset point to "fconf,dyn_cfg-dtb_registry" compatible property */ + const char *compatible_str = "fconf,dyn_cfg-dtb_registry"; + 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; + } + + fdt_for_each_subnode(child, dtb, node) { + uint32_t config_max_size, config_id; + uintptr_t config_addr; + uint64_t val64; + + /* Read configuration dtb information */ + rc = fdt_read_uint64(dtb, child, "load-address", &val64); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + config_addr = (uintptr_t)val64; + + rc = fdt_read_uint32(dtb, child, "max-size", &config_max_size); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + + rc = fdt_read_uint32(dtb, child, "id", &config_id); + if (rc < 0) { + ERROR("FCONF: Incomplete configuration property in dtb-registry.\n"); + return rc; + } + + VERBOSE("FCONF: dyn_cfg.dtb_registry cell found with:\n"); + VERBOSE("\tload-address = %lx\n", config_addr); + VERBOSE("\tmax-size = 0x%x\n", config_max_size); + VERBOSE("\tconfig-id = %u\n", config_id); + + set_config_info(config_addr, config_max_size, config_id); + } + + if ((child < 0) && (child != -FDT_ERR_NOTFOUND)) { + ERROR("%d: fdt_for_each_subnode(): %d\n", __LINE__, node); + return child; + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(FW_CONFIG, dyn_cfg, fconf_populate_dtb_registry); diff --git a/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c b/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c new file mode 100644 index 0000000..02a566d --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include + +struct fconf_mpmm_config fconf_mpmm_config; +static struct mpmm_topology fconf_mpmm_topology; + +/* + * Within a `cpu` node, determine support for MPMM via the `supports-mpmm` + * property. + * + * Returns `0` on success, or a negative integer representing an error code. + */ +static int fconf_populate_mpmm_cpu(const void *fdt, int off, uintptr_t mpidr) +{ + int ret, len; + + int core_pos; + struct mpmm_core *core; + + core_pos = plat_core_pos_by_mpidr(mpidr); + if (core_pos < 0) { + return -FDT_ERR_BADVALUE; + } + + core = &fconf_mpmm_topology.cores[core_pos]; + + fdt_getprop(fdt, off, "supports-mpmm", &len); + if (len >= 0) { + core->supported = true; + ret = 0; + } else { + core->supported = false; + ret = len; + } + + return ret; +} + +/* + * Populates the global `fconf_mpmm_config` structure based on what's described + * by the hardware configuration device tree blob. + * + * The device tree is expected to provide a `supports-mpmm` property for each + * `cpu` node, like so: + * + * cpu@0 { + * supports-mpmm; + * }; + * + * This property indicates whether the core implements MPMM, as we cannot detect + * support for it dynamically. + */ +static int fconf_populate_mpmm(uintptr_t config) +{ + int ret = fdtw_for_each_cpu( + (const void *)config, fconf_populate_mpmm_cpu); + if (ret == 0) { + fconf_mpmm_config.topology = &fconf_mpmm_topology; + } else { + ERROR("FCONF: failed to configure MPMM: %d\n", ret); + } + + return ret; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, mpmm, fconf_populate_mpmm); diff --git a/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c b/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c new file mode 100644 index 0000000..6f043e6 --- /dev/null +++ b/arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include +#include +#include + +struct tbbr_dyn_config_t tbbr_dyn_config; + +int fconf_populate_tbbr_dyn_config(uintptr_t config) +{ + int err; + int node; + uint64_t val64; + uint32_t val32; + + /* As libfdt use void *, we can't avoid this cast */ + const void *dtb = (void *)config; + + /* Assert the node offset point to "arm,tb_fw" compatible property */ + const char *compatible_str = "arm,tb_fw"; + 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 disable_auth cell and read the value */ + err = fdt_read_uint32(dtb, node, "disable_auth", + &tbbr_dyn_config.disable_auth); + if (err < 0) { + WARN("FCONF: Read %s failed for `%s`\n", + "cell", "disable_auth"); + return err; + } + + /* Check if the value is boolean */ + if ((tbbr_dyn_config.disable_auth != 0U) && + (tbbr_dyn_config.disable_auth != 1U)) { + WARN("Invalid value for `%s` cell %d\n", + "disable_auth", tbbr_dyn_config.disable_auth); + return -1; + } + +#if defined(DYN_DISABLE_AUTH) + if (tbbr_dyn_config.disable_auth == 1) + dyn_disable_auth(); +#endif + + /* Retrieve the Mbed TLS heap details from the DTB */ + err = fdt_read_uint64(dtb, node, "mbedtls_heap_addr", &val64); + if (err < 0) { + ERROR("FCONF: Read %s failed for `%s`\n", + "cell", "mbedtls_heap_addr"); + return err; + } + tbbr_dyn_config.mbedtls_heap_addr = (void *)(uintptr_t)val64; + + err = fdt_read_uint32(dtb, node, "mbedtls_heap_size", &val32); + if (err < 0) { + ERROR("FCONF: Read %s failed for `%s`\n", + "cell", "mbedtls_heap_size"); + return err; + } + tbbr_dyn_config.mbedtls_heap_size = val32; + + VERBOSE("%s%s%s %d\n", "FCONF: `tbbr.", "disable_auth", + "` cell found with value =", tbbr_dyn_config.disable_auth); + VERBOSE("%s%s%s %p\n", "FCONF: `tbbr.", "mbedtls_heap_addr", + "` cell found with value =", tbbr_dyn_config.mbedtls_heap_addr); + VERBOSE("%s%s%s %zu\n", "FCONF: `tbbr.", "mbedtls_heap_size", + "` cell found with value =", tbbr_dyn_config.mbedtls_heap_size); + + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, tbbr, fconf_populate_tbbr_dyn_config); diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c new file mode 100644 index 0000000..d6fbc04 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.c @@ -0,0 +1,1255 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include "gpt_rme_private.h" +#include +#include +#include +#include + +#if !ENABLE_RME +#error "ENABLE_RME must be enabled to use the GPT library." +#endif + +/* + * Lookup T from PPS + * + * PPS Size T + * 0b000 4GB 32 + * 0b001 64GB 36 + * 0b010 1TB 40 + * 0b011 4TB 42 + * 0b100 16TB 44 + * 0b101 256TB 48 + * 0b110 4PB 52 + * + * See section 15.1.27 of the RME specification. + */ +static const gpt_t_val_e gpt_t_lookup[] = {PPS_4GB_T, PPS_64GB_T, + PPS_1TB_T, PPS_4TB_T, + PPS_16TB_T, PPS_256TB_T, + PPS_4PB_T}; + +/* + * Lookup P from PGS + * + * PGS Size P + * 0b00 4KB 12 + * 0b10 16KB 14 + * 0b01 64KB 16 + * + * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo. + * + * See section 15.1.27 of the RME specification. + */ +static const gpt_p_val_e gpt_p_lookup[] = {PGS_4KB_P, PGS_64KB_P, PGS_16KB_P}; + +/* + * This structure contains GPT configuration data. + */ +typedef struct { + uintptr_t plat_gpt_l0_base; + gpccr_pps_e pps; + gpt_t_val_e t; + gpccr_pgs_e pgs; + gpt_p_val_e p; +} gpt_config_t; + +static gpt_config_t gpt_config; + +/* These variables are used during initialization of the L1 tables. */ +static unsigned int gpt_next_l1_tbl_idx; +static uintptr_t gpt_l1_tbl; + +/* + * This function checks to see if a GPI value is valid. + * + * These are valid GPI values. + * GPT_GPI_NO_ACCESS U(0x0) + * GPT_GPI_SECURE U(0x8) + * GPT_GPI_NS U(0x9) + * GPT_GPI_ROOT U(0xA) + * GPT_GPI_REALM U(0xB) + * GPT_GPI_ANY U(0xF) + * + * Parameters + * gpi GPI to check for validity. + * + * Return + * true for a valid GPI, false for an invalid one. + */ +static bool gpt_is_gpi_valid(unsigned int gpi) +{ + if ((gpi == GPT_GPI_NO_ACCESS) || (gpi == GPT_GPI_ANY) || + ((gpi >= GPT_GPI_SECURE) && (gpi <= GPT_GPI_REALM))) { + return true; + } + return false; +} + +/* + * This function checks to see if two PAS regions overlap. + * + * Parameters + * base_1: base address of first PAS + * size_1: size of first PAS + * base_2: base address of second PAS + * size_2: size of second PAS + * + * Return + * True if PAS regions overlap, false if they do not. + */ +static bool gpt_check_pas_overlap(uintptr_t base_1, size_t size_1, + uintptr_t base_2, size_t size_2) +{ + if (((base_1 + size_1) > base_2) && ((base_2 + size_2) > base_1)) { + return true; + } + return false; +} + +/* + * This helper function checks to see if a PAS region from index 0 to + * (pas_idx - 1) occupies the L0 region at index l0_idx in the L0 table. + * + * Parameters + * l0_idx: Index of the L0 entry to check + * pas_regions: PAS region array + * pas_idx: Upper bound of the PAS array index. + * + * Return + * True if a PAS region occupies the L0 region in question, false if not. + */ +static bool gpt_does_previous_pas_exist_here(unsigned int l0_idx, + pas_region_t *pas_regions, + unsigned int pas_idx) +{ + /* Iterate over PAS regions up to pas_idx. */ + for (unsigned int i = 0U; i < pas_idx; i++) { + if (gpt_check_pas_overlap((GPT_L0GPTSZ_ACTUAL_SIZE * l0_idx), + GPT_L0GPTSZ_ACTUAL_SIZE, + pas_regions[i].base_pa, pas_regions[i].size)) { + return true; + } + } + return false; +} + +/* + * This function iterates over all of the PAS regions and checks them to ensure + * proper alignment of base and size, that the GPI is valid, and that no regions + * overlap. As a part of the overlap checks, this function checks existing L0 + * mappings against the new PAS regions in the event that gpt_init_pas_l1_tables + * is called multiple times to place L1 tables in different areas of memory. It + * also counts the number of L1 tables needed and returns it on success. + * + * Parameters + * *pas_regions Pointer to array of PAS region structures. + * pas_region_cnt Total number of PAS regions in the array. + * + * Return + * Negative Linux error code in the event of a failure, number of L1 regions + * required when successful. + */ +static int gpt_validate_pas_mappings(pas_region_t *pas_regions, + unsigned int pas_region_cnt) +{ + unsigned int idx; + unsigned int l1_cnt = 0U; + unsigned int pas_l1_cnt; + uint64_t *l0_desc = (uint64_t *)gpt_config.plat_gpt_l0_base; + + assert(pas_regions != NULL); + assert(pas_region_cnt != 0U); + + for (idx = 0U; idx < pas_region_cnt; idx++) { + /* Check for arithmetic overflow in region. */ + if ((ULONG_MAX - pas_regions[idx].base_pa) < + pas_regions[idx].size) { + ERROR("[GPT] Address overflow in PAS[%u]!\n", idx); + return -EOVERFLOW; + } + + /* Initial checks for PAS validity. */ + if (((pas_regions[idx].base_pa + pas_regions[idx].size) > + GPT_PPS_ACTUAL_SIZE(gpt_config.t)) || + !gpt_is_gpi_valid(GPT_PAS_ATTR_GPI(pas_regions[idx].attrs))) { + ERROR("[GPT] PAS[%u] is invalid!\n", idx); + return -EFAULT; + } + + /* + * Make sure this PAS does not overlap with another one. We + * start from idx + 1 instead of 0 since prior PAS mappings will + * have already checked themselves against this one. + */ + for (unsigned int i = idx + 1; i < pas_region_cnt; i++) { + if (gpt_check_pas_overlap(pas_regions[idx].base_pa, + pas_regions[idx].size, + pas_regions[i].base_pa, + pas_regions[i].size)) { + ERROR("[GPT] PAS[%u] overlaps with PAS[%u]\n", + i, idx); + return -EFAULT; + } + } + + /* + * Since this function can be called multiple times with + * separate L1 tables we need to check the existing L0 mapping + * to see if this PAS would fall into one that has already been + * initialized. + */ + for (unsigned int i = GPT_L0_IDX(pas_regions[idx].base_pa); + i <= GPT_L0_IDX(pas_regions[idx].base_pa + pas_regions[idx].size - 1); + i++) { + if ((GPT_L0_TYPE(l0_desc[i]) == GPT_L0_TYPE_BLK_DESC) && + (GPT_L0_BLKD_GPI(l0_desc[i]) == GPT_GPI_ANY)) { + /* This descriptor is unused so continue. */ + continue; + } + + /* + * This descriptor has been initialized in a previous + * call to this function so cannot be initialized again. + */ + ERROR("[GPT] PAS[%u] overlaps with previous L0[%d]!\n", + idx, i); + return -EFAULT; + } + + /* Check for block mapping (L0) type. */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_BLOCK) { + /* Make sure base and size are block-aligned. */ + if (!GPT_IS_L0_ALIGNED(pas_regions[idx].base_pa) || + !GPT_IS_L0_ALIGNED(pas_regions[idx].size)) { + ERROR("[GPT] PAS[%u] is not block-aligned!\n", + idx); + return -EFAULT; + } + + continue; + } + + /* Check for granule mapping (L1) type. */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_GRANULE) { + /* Make sure base and size are granule-aligned. */ + if (!GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].base_pa) || + !GPT_IS_L1_ALIGNED(gpt_config.p, pas_regions[idx].size)) { + ERROR("[GPT] PAS[%u] is not granule-aligned!\n", + idx); + return -EFAULT; + } + + /* Find how many L1 tables this PAS occupies. */ + pas_l1_cnt = (GPT_L0_IDX(pas_regions[idx].base_pa + + pas_regions[idx].size - 1) - + GPT_L0_IDX(pas_regions[idx].base_pa) + 1); + + /* + * This creates a situation where, if multiple PAS + * regions occupy the same table descriptor, we can get + * an artificially high total L1 table count. The way we + * handle this is by checking each PAS against those + * before it in the array, and if they both occupy the + * same PAS we subtract from pas_l1_cnt and only the + * first PAS in the array gets to count it. + */ + + /* + * If L1 count is greater than 1 we know the start and + * end PAs are in different L0 regions so we must check + * both for overlap against other PAS. + */ + if (pas_l1_cnt > 1) { + if (gpt_does_previous_pas_exist_here( + GPT_L0_IDX(pas_regions[idx].base_pa + + pas_regions[idx].size - 1), + pas_regions, idx)) { + pas_l1_cnt = pas_l1_cnt - 1; + } + } + + if (gpt_does_previous_pas_exist_here( + GPT_L0_IDX(pas_regions[idx].base_pa), + pas_regions, idx)) { + pas_l1_cnt = pas_l1_cnt - 1; + } + + l1_cnt += pas_l1_cnt; + continue; + } + + /* If execution reaches this point, mapping type is invalid. */ + ERROR("[GPT] PAS[%u] has invalid mapping type 0x%x.\n", idx, + GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs)); + return -EINVAL; + } + + return l1_cnt; +} + +/* + * This function validates L0 initialization parameters. + * + * Parameters + * l0_mem_base Base address of memory used for L0 tables. + * l1_mem_size Size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +static int gpt_validate_l0_params(gpccr_pps_e pps, uintptr_t l0_mem_base, + size_t l0_mem_size) +{ + size_t l0_alignment; + + /* + * Make sure PPS is valid and then store it since macros need this value + * to work. + */ + if (pps > GPT_PPS_MAX) { + ERROR("[GPT] Invalid PPS: 0x%x\n", pps); + return -EINVAL; + } + gpt_config.pps = pps; + gpt_config.t = gpt_t_lookup[pps]; + + /* Alignment must be the greater of 4k or l0 table size. */ + l0_alignment = PAGE_SIZE_4KB; + if (l0_alignment < GPT_L0_TABLE_SIZE(gpt_config.t)) { + l0_alignment = GPT_L0_TABLE_SIZE(gpt_config.t); + } + + /* Check base address. */ + if ((l0_mem_base == 0U) || ((l0_mem_base & (l0_alignment - 1)) != 0U)) { + ERROR("[GPT] Invalid L0 base address: 0x%lx\n", l0_mem_base); + return -EFAULT; + } + + /* Check size. */ + if (l0_mem_size < GPT_L0_TABLE_SIZE(gpt_config.t)) { + ERROR("[GPT] Inadequate L0 memory: need 0x%lx, have 0x%lx)\n", + GPT_L0_TABLE_SIZE(gpt_config.t), + l0_mem_size); + return -ENOMEM; + } + + return 0; +} + +/* + * In the event that L1 tables are needed, this function validates + * the L1 table generation parameters. + * + * Parameters + * l1_mem_base Base address of memory used for L1 table allocation. + * l1_mem_size Total size of memory available for L1 tables. + * l1_gpt_cnt Number of L1 tables needed. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +static int gpt_validate_l1_params(uintptr_t l1_mem_base, size_t l1_mem_size, + unsigned int l1_gpt_cnt) +{ + size_t l1_gpt_mem_sz; + + /* Check if the granularity is supported */ + if (!xlat_arch_is_granule_size_supported( + GPT_PGS_ACTUAL_SIZE(gpt_config.p))) { + return -EPERM; + } + + /* Make sure L1 tables are aligned to their size. */ + if ((l1_mem_base & (GPT_L1_TABLE_SIZE(gpt_config.p) - 1)) != 0U) { + ERROR("[GPT] Unaligned L1 GPT base address: 0x%lx\n", + l1_mem_base); + return -EFAULT; + } + + /* Get total memory needed for L1 tables. */ + l1_gpt_mem_sz = l1_gpt_cnt * GPT_L1_TABLE_SIZE(gpt_config.p); + + /* Check for overflow. */ + if ((l1_gpt_mem_sz / GPT_L1_TABLE_SIZE(gpt_config.p)) != l1_gpt_cnt) { + ERROR("[GPT] Overflow calculating L1 memory size.\n"); + return -ENOMEM; + } + + /* Make sure enough space was supplied. */ + if (l1_mem_size < l1_gpt_mem_sz) { + ERROR("[GPT] Inadequate memory for L1 GPTs. "); + ERROR(" Expected 0x%lx bytes. Got 0x%lx bytes\n", + l1_gpt_mem_sz, l1_mem_size); + return -ENOMEM; + } + + VERBOSE("[GPT] Requested 0x%lx bytes for L1 GPTs.\n", l1_gpt_mem_sz); + return 0; +} + +/* + * This function initializes L0 block descriptors (regions that cannot be + * transitioned at the granule level) according to the provided PAS. + * + * Parameters + * *pas Pointer to the structure defining the PAS region to + * initialize. + */ +static void gpt_generate_l0_blk_desc(pas_region_t *pas) +{ + uint64_t gpt_desc; + unsigned int end_idx; + unsigned int idx; + uint64_t *l0_gpt_arr; + + assert(gpt_config.plat_gpt_l0_base != 0U); + assert(pas != NULL); + + /* + * Checking of PAS parameters has already been done in + * gpt_validate_pas_mappings so no need to check the same things again. + */ + + l0_gpt_arr = (uint64_t *)gpt_config.plat_gpt_l0_base; + + /* Create the GPT Block descriptor for this PAS region */ + gpt_desc = GPT_L0_BLK_DESC(GPT_PAS_ATTR_GPI(pas->attrs)); + + /* Start index of this region in L0 GPTs */ + idx = GPT_L0_IDX(pas->base_pa); + + /* + * Determine number of L0 GPT descriptors covered by + * this PAS region and use the count to populate these + * descriptors. + */ + end_idx = GPT_L0_IDX(pas->base_pa + pas->size); + + /* Generate the needed block descriptors. */ + for (; idx < end_idx; idx++) { + l0_gpt_arr[idx] = gpt_desc; + VERBOSE("[GPT] L0 entry (BLOCK) index %u [%p]: GPI = 0x%" PRIx64 " (0x%" PRIx64 ")\n", + idx, &l0_gpt_arr[idx], + (gpt_desc >> GPT_L0_BLK_DESC_GPI_SHIFT) & + GPT_L0_BLK_DESC_GPI_MASK, l0_gpt_arr[idx]); + } +} + +/* + * Helper function to determine if the end physical address lies in the same L0 + * region as the current physical address. If true, the end physical address is + * returned else, the start address of the next region is returned. + * + * Parameters + * cur_pa Physical address of the current PA in the loop through + * the range. + * end_pa Physical address of the end PA in a PAS range. + * + * Return + * The PA of the end of the current range. + */ +static uintptr_t gpt_get_l1_end_pa(uintptr_t cur_pa, uintptr_t end_pa) +{ + uintptr_t cur_idx; + uintptr_t end_idx; + + cur_idx = GPT_L0_IDX(cur_pa); + end_idx = GPT_L0_IDX(end_pa); + + assert(cur_idx <= end_idx); + + if (cur_idx == end_idx) { + return end_pa; + } + + return (cur_idx + 1U) << GPT_L0_IDX_SHIFT; +} + +/* + * Helper function to fill out GPI entries in a single L1 table. This function + * fills out entire L1 descriptors at a time to save memory writes. + * + * Parameters + * gpi GPI to set this range to + * l1 Pointer to L1 table to fill out + * first Address of first granule in range. + * last Address of last granule in range (inclusive). + */ +static void gpt_fill_l1_tbl(uint64_t gpi, uint64_t *l1, uintptr_t first, + uintptr_t last) +{ + uint64_t gpi_field = GPT_BUILD_L1_DESC(gpi); + uint64_t gpi_mask = 0xFFFFFFFFFFFFFFFF; + + assert(first <= last); + assert((first & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U); + assert((last & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) == 0U); + assert(GPT_L0_IDX(first) == GPT_L0_IDX(last)); + assert(l1 != NULL); + + /* Shift the mask if we're starting in the middle of an L1 entry. */ + gpi_mask = gpi_mask << (GPT_L1_GPI_IDX(gpt_config.p, first) << 2); + + /* Fill out each L1 entry for this region. */ + for (unsigned int i = GPT_L1_IDX(gpt_config.p, first); + i <= GPT_L1_IDX(gpt_config.p, last); i++) { + /* Account for stopping in the middle of an L1 entry. */ + if (i == GPT_L1_IDX(gpt_config.p, last)) { + gpi_mask &= (gpi_mask >> ((15 - + GPT_L1_GPI_IDX(gpt_config.p, last)) << 2)); + } + + /* Write GPI values. */ + assert((l1[i] & gpi_mask) == + (GPT_BUILD_L1_DESC(GPT_GPI_ANY) & gpi_mask)); + l1[i] = (l1[i] & ~gpi_mask) | (gpi_mask & gpi_field); + + /* Reset mask. */ + gpi_mask = 0xFFFFFFFFFFFFFFFF; + } +} + +/* + * This function finds the next available unused L1 table and initializes all + * granules descriptor entries to GPI_ANY. This ensures that there are no chunks + * of GPI_NO_ACCESS (0b0000) memory floating around in the system in the + * event that a PAS region stops midway through an L1 table, thus guaranteeing + * that all memory not explicitly assigned is GPI_ANY. This function does not + * check for overflow conditions, that should be done by the caller. + * + * Return + * Pointer to the next available L1 table. + */ +static uint64_t *gpt_get_new_l1_tbl(void) +{ + /* Retrieve the next L1 table. */ + uint64_t *l1 = (uint64_t *)((uint64_t)(gpt_l1_tbl) + + (GPT_L1_TABLE_SIZE(gpt_config.p) * + gpt_next_l1_tbl_idx)); + + /* Increment L1 counter. */ + gpt_next_l1_tbl_idx++; + + /* Initialize all GPIs to GPT_GPI_ANY */ + for (unsigned int i = 0U; i < GPT_L1_ENTRY_COUNT(gpt_config.p); i++) { + l1[i] = GPT_BUILD_L1_DESC(GPT_GPI_ANY); + } + + return l1; +} + +/* + * When L1 tables are needed, this function creates the necessary L0 table + * descriptors and fills out the L1 table entries according to the supplied + * PAS range. + * + * Parameters + * *pas Pointer to the structure defining the PAS region. + */ +static void gpt_generate_l0_tbl_desc(pas_region_t *pas) +{ + uintptr_t end_pa; + uintptr_t cur_pa; + uintptr_t last_gran_pa; + uint64_t *l0_gpt_base; + uint64_t *l1_gpt_arr; + unsigned int l0_idx; + + assert(gpt_config.plat_gpt_l0_base != 0U); + assert(pas != NULL); + + /* + * Checking of PAS parameters has already been done in + * gpt_validate_pas_mappings so no need to check the same things again. + */ + + end_pa = pas->base_pa + pas->size; + l0_gpt_base = (uint64_t *)gpt_config.plat_gpt_l0_base; + + /* We start working from the granule at base PA */ + cur_pa = pas->base_pa; + + /* Iterate over each L0 region in this memory range. */ + for (l0_idx = GPT_L0_IDX(pas->base_pa); + l0_idx <= GPT_L0_IDX(end_pa - 1U); + l0_idx++) { + + /* + * See if the L0 entry is already a table descriptor or if we + * need to create one. + */ + if (GPT_L0_TYPE(l0_gpt_base[l0_idx]) == GPT_L0_TYPE_TBL_DESC) { + /* Get the L1 array from the L0 entry. */ + l1_gpt_arr = GPT_L0_TBLD_ADDR(l0_gpt_base[l0_idx]); + } else { + /* Get a new L1 table from the L1 memory space. */ + l1_gpt_arr = gpt_get_new_l1_tbl(); + + /* Fill out the L0 descriptor and flush it. */ + l0_gpt_base[l0_idx] = GPT_L0_TBL_DESC(l1_gpt_arr); + } + + VERBOSE("[GPT] L0 entry (TABLE) index %u [%p] ==> L1 Addr 0x%llx (0x%" PRIx64 ")\n", + l0_idx, &l0_gpt_base[l0_idx], + (unsigned long long)(l1_gpt_arr), + l0_gpt_base[l0_idx]); + + /* + * Determine the PA of the last granule in this L0 descriptor. + */ + last_gran_pa = gpt_get_l1_end_pa(cur_pa, end_pa) - + GPT_PGS_ACTUAL_SIZE(gpt_config.p); + + /* + * Fill up L1 GPT entries between these two addresses. This + * function needs the addresses of the first granule and last + * granule in the range. + */ + gpt_fill_l1_tbl(GPT_PAS_ATTR_GPI(pas->attrs), l1_gpt_arr, + cur_pa, last_gran_pa); + + /* Advance cur_pa to first granule in next L0 region. */ + cur_pa = gpt_get_l1_end_pa(cur_pa, end_pa); + } +} + +/* + * This function flushes a range of L0 descriptors used by a given PAS region + * array. There is a chance that some unmodified L0 descriptors would be flushed + * in the case that there are "holes" in an array of PAS regions but overall + * this should be faster than individually flushing each modified L0 descriptor + * as they are created. + * + * Parameters + * *pas Pointer to an array of PAS regions. + * pas_count Number of entries in the PAS array. + */ +static void flush_l0_for_pas_array(pas_region_t *pas, unsigned int pas_count) +{ + unsigned int idx; + unsigned int start_idx; + unsigned int end_idx; + uint64_t *l0 = (uint64_t *)gpt_config.plat_gpt_l0_base; + + assert(pas != NULL); + assert(pas_count > 0); + + /* Initial start and end values. */ + start_idx = GPT_L0_IDX(pas[0].base_pa); + end_idx = GPT_L0_IDX(pas[0].base_pa + pas[0].size - 1); + + /* Find lowest and highest L0 indices used in this PAS array. */ + for (idx = 1; idx < pas_count; idx++) { + if (GPT_L0_IDX(pas[idx].base_pa) < start_idx) { + start_idx = GPT_L0_IDX(pas[idx].base_pa); + } + if (GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1) > end_idx) { + end_idx = GPT_L0_IDX(pas[idx].base_pa + pas[idx].size - 1); + } + } + + /* + * Flush all covered L0 descriptors, add 1 because we need to include + * the end index value. + */ + flush_dcache_range((uintptr_t)&l0[start_idx], + ((end_idx + 1) - start_idx) * sizeof(uint64_t)); +} + +/* + * Public API to enable granule protection checks once the tables have all been + * initialized. This function is called at first initialization and then again + * later during warm boots of CPU cores. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_enable(void) +{ + u_register_t gpccr_el3; + + /* + * Granule tables must be initialised before enabling + * granule protection. + */ + if (gpt_config.plat_gpt_l0_base == 0U) { + ERROR("[GPT] Tables have not been initialized!\n"); + return -EPERM; + } + + /* Invalidate any stale TLB entries */ + tlbipaallos(); + dsb(); + + /* Write the base address of the L0 tables into GPTBR */ + write_gptbr_el3(((gpt_config.plat_gpt_l0_base >> GPTBR_BADDR_VAL_SHIFT) + >> GPTBR_BADDR_SHIFT) & GPTBR_BADDR_MASK); + + /* GPCCR_EL3.PPS */ + gpccr_el3 = SET_GPCCR_PPS(gpt_config.pps); + + /* GPCCR_EL3.PGS */ + gpccr_el3 |= SET_GPCCR_PGS(gpt_config.pgs); + + /* + * Since EL3 maps the L1 region as Inner shareable, use the same + * shareability attribute for GPC as well so that + * GPC fetches are visible to PEs + */ + gpccr_el3 |= SET_GPCCR_SH(GPCCR_SH_IS); + + /* Outer and Inner cacheability set to Normal memory, WB, RA, WA. */ + gpccr_el3 |= SET_GPCCR_ORGN(GPCCR_ORGN_WB_RA_WA); + gpccr_el3 |= SET_GPCCR_IRGN(GPCCR_IRGN_WB_RA_WA); + + /* Enable GPT */ + gpccr_el3 |= GPCCR_GPC_BIT; + + /* TODO: Configure GPCCR_EL3_GPCP for Fault control. */ + write_gpccr_el3(gpccr_el3); + isb(); + tlbipaallos(); + dsb(); + isb(); + + return 0; +} + +/* + * Public API to disable granule protection checks. + */ +void gpt_disable(void) +{ + u_register_t gpccr_el3 = read_gpccr_el3(); + + write_gpccr_el3(gpccr_el3 & ~GPCCR_GPC_BIT); + dsbsy(); + isb(); +} + +/* + * Public API that initializes the entire protected space to GPT_GPI_ANY using + * the L0 tables (block descriptors). Ideally, this function is invoked prior + * to DDR discovery and initialization. The MMU must be initialized before + * calling this function. + * + * Parameters + * pps PPS value to use for table generation + * l0_mem_base Base address of L0 tables in memory. + * l0_mem_size Total size of memory available for L0 tables. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_l0_tables(unsigned int pps, uintptr_t l0_mem_base, + size_t l0_mem_size) +{ + int ret; + uint64_t gpt_desc; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* Validate other parameters. */ + ret = gpt_validate_l0_params(pps, l0_mem_base, l0_mem_size); + if (ret != 0) { + return ret; + } + + /* Create the descriptor to initialize L0 entries with. */ + gpt_desc = GPT_L0_BLK_DESC(GPT_GPI_ANY); + + /* Iterate through all L0 entries */ + for (unsigned int i = 0U; i < GPT_L0_REGION_COUNT(gpt_config.t); i++) { + ((uint64_t *)l0_mem_base)[i] = gpt_desc; + } + + /* Flush updated L0 tables to memory. */ + flush_dcache_range((uintptr_t)l0_mem_base, + (size_t)GPT_L0_TABLE_SIZE(gpt_config.t)); + + /* Stash the L0 base address once initial setup is complete. */ + gpt_config.plat_gpt_l0_base = l0_mem_base; + + return 0; +} + +/* + * Public API that carves out PAS regions from the L0 tables and builds any L1 + * tables that are needed. This function ideally is run after DDR discovery and + * initialization. The L0 tables must have already been initialized to GPI_ANY + * when this function is called. + * + * This function can be called multiple times with different L1 memory ranges + * and PAS regions if it is desirable to place L1 tables in different locations + * in memory. (ex: you have multiple DDR banks and want to place the L1 tables + * in the DDR bank that they control) + * + * Parameters + * pgs PGS value to use for table generation. + * l1_mem_base Base address of memory used for L1 tables. + * l1_mem_size Total size of memory available for L1 tables. + * *pas_regions Pointer to PAS regions structure array. + * pas_count Total number of PAS regions. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_init_pas_l1_tables(gpccr_pgs_e pgs, uintptr_t l1_mem_base, + size_t l1_mem_size, pas_region_t *pas_regions, + unsigned int pas_count) +{ + int ret; + int l1_gpt_cnt; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* PGS is needed for gpt_validate_pas_mappings so check it now. */ + if (pgs > GPT_PGS_MAX) { + ERROR("[GPT] Invalid PGS: 0x%x\n", pgs); + return -EINVAL; + } + gpt_config.pgs = pgs; + gpt_config.p = gpt_p_lookup[pgs]; + + /* Make sure L0 tables have been initialized. */ + if (gpt_config.plat_gpt_l0_base == 0U) { + ERROR("[GPT] L0 tables must be initialized first!\n"); + return -EPERM; + } + + /* Check if L1 GPTs are required and how many. */ + l1_gpt_cnt = gpt_validate_pas_mappings(pas_regions, pas_count); + if (l1_gpt_cnt < 0) { + return l1_gpt_cnt; + } + + VERBOSE("[GPT] %u L1 GPTs requested.\n", l1_gpt_cnt); + + /* If L1 tables are needed then validate the L1 parameters. */ + if (l1_gpt_cnt > 0) { + ret = gpt_validate_l1_params(l1_mem_base, l1_mem_size, + l1_gpt_cnt); + if (ret != 0) { + return ret; + } + + /* Set up parameters for L1 table generation. */ + gpt_l1_tbl = l1_mem_base; + gpt_next_l1_tbl_idx = 0U; + } + + INFO("[GPT] Boot Configuration\n"); + INFO(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t); + INFO(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p); + INFO(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL); + INFO(" PAS count: 0x%x\n", pas_count); + INFO(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base); + + /* Generate the tables in memory. */ + for (unsigned int idx = 0U; idx < pas_count; idx++) { + INFO("[GPT] PAS[%u]: base 0x%lx, size 0x%lx, GPI 0x%x, type 0x%x\n", + idx, pas_regions[idx].base_pa, pas_regions[idx].size, + GPT_PAS_ATTR_GPI(pas_regions[idx].attrs), + GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs)); + + /* Check if a block or table descriptor is required */ + if (GPT_PAS_ATTR_MAP_TYPE(pas_regions[idx].attrs) == + GPT_PAS_ATTR_MAP_TYPE_BLOCK) { + gpt_generate_l0_blk_desc(&pas_regions[idx]); + + } else { + gpt_generate_l0_tbl_desc(&pas_regions[idx]); + } + } + + /* Flush modified L0 tables. */ + flush_l0_for_pas_array(pas_regions, pas_count); + + /* Flush L1 tables if needed. */ + if (l1_gpt_cnt > 0) { + flush_dcache_range(l1_mem_base, + GPT_L1_TABLE_SIZE(gpt_config.p) * + l1_gpt_cnt); + } + + /* Make sure that all the entries are written to the memory. */ + dsbishst(); + tlbipaallos(); + dsb(); + isb(); + + return 0; +} + +/* + * Public API to initialize the runtime gpt_config structure based on the values + * present in the GPTBR_EL3 and GPCCR_EL3 registers. GPT initialization + * typically happens in a bootloader stage prior to setting up the EL3 runtime + * environment for the granule transition service so this function detects the + * initialization from a previous stage. Granule protection checks must be + * enabled already or this function will return an error. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_runtime_init(void) +{ + u_register_t reg; + + /* Ensure that MMU and Data caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0U); + + /* Ensure GPC are already enabled. */ + if ((read_gpccr_el3() & GPCCR_GPC_BIT) == 0U) { + ERROR("[GPT] Granule protection checks are not enabled!\n"); + return -EPERM; + } + + /* + * Read the L0 table address from GPTBR, we don't need the L1 base + * address since those are included in the L0 tables as needed. + */ + reg = read_gptbr_el3(); + gpt_config.plat_gpt_l0_base = ((reg >> GPTBR_BADDR_SHIFT) & + GPTBR_BADDR_MASK) << + GPTBR_BADDR_VAL_SHIFT; + + /* Read GPCCR to get PGS and PPS values. */ + reg = read_gpccr_el3(); + gpt_config.pps = (reg >> GPCCR_PPS_SHIFT) & GPCCR_PPS_MASK; + gpt_config.t = gpt_t_lookup[gpt_config.pps]; + gpt_config.pgs = (reg >> GPCCR_PGS_SHIFT) & GPCCR_PGS_MASK; + gpt_config.p = gpt_p_lookup[gpt_config.pgs]; + + VERBOSE("[GPT] Runtime Configuration\n"); + VERBOSE(" PPS/T: 0x%x/%u\n", gpt_config.pps, gpt_config.t); + VERBOSE(" PGS/P: 0x%x/%u\n", gpt_config.pgs, gpt_config.p); + VERBOSE(" L0GPTSZ/S: 0x%x/%u\n", GPT_L0GPTSZ, GPT_S_VAL); + VERBOSE(" L0 base: 0x%lx\n", gpt_config.plat_gpt_l0_base); + + return 0; +} + +/* + * The L1 descriptors are protected by a spinlock to ensure that multiple + * CPUs do not attempt to change the descriptors at once. In the future it + * would be better to have separate spinlocks for each L1 descriptor. + */ +static spinlock_t gpt_lock; + +/* + * A helper to write the value (target_pas << gpi_shift) to the index of + * the gpt_l1_addr + */ +static inline void write_gpt(uint64_t *gpt_l1_desc, uint64_t *gpt_l1_addr, + unsigned int gpi_shift, unsigned int idx, + unsigned int target_pas) +{ + *gpt_l1_desc &= ~(GPT_L1_GRAN_DESC_GPI_MASK << gpi_shift); + *gpt_l1_desc |= ((uint64_t)target_pas << gpi_shift); + gpt_l1_addr[idx] = *gpt_l1_desc; +} + +/* + * Helper to retrieve the gpt_l1_* information from the base address + * returned in gpi_info + */ +static int get_gpi_params(uint64_t base, gpi_info_t *gpi_info) +{ + uint64_t gpt_l0_desc, *gpt_l0_base; + + gpt_l0_base = (uint64_t *)gpt_config.plat_gpt_l0_base; + gpt_l0_desc = gpt_l0_base[GPT_L0_IDX(base)]; + if (GPT_L0_TYPE(gpt_l0_desc) != GPT_L0_TYPE_TBL_DESC) { + VERBOSE("[GPT] Granule is not covered by a table descriptor!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + return -EINVAL; + } + + /* Get the table index and GPI shift from PA. */ + gpi_info->gpt_l1_addr = GPT_L0_TBLD_ADDR(gpt_l0_desc); + gpi_info->idx = GPT_L1_IDX(gpt_config.p, base); + gpi_info->gpi_shift = GPT_L1_GPI_IDX(gpt_config.p, base) << 2; + + gpi_info->gpt_l1_desc = (gpi_info->gpt_l1_addr)[gpi_info->idx]; + gpi_info->gpi = (gpi_info->gpt_l1_desc >> gpi_info->gpi_shift) & + GPT_L1_GRAN_DESC_GPI_MASK; + return 0; +} + +/* + * This function is the granule transition delegate service. When a granule + * transition request occurs it is routed to this function to have the request, + * if valid, fulfilled following A1.1.1 Delegate of RME supplement + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base Base address of the region to transition, must be + * aligned to granule size. + * size Size of region to transition, must be aligned to granule + * size. + * src_sec_state Security state of the caller. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_delegate_pas(uint64_t base, size_t size, unsigned int src_sec_state) +{ + gpi_info_t gpi_info; + uint64_t nse; + int res; + unsigned int target_pas; + + /* Ensure that the tables have been set up before taking requests. */ + assert(gpt_config.plat_gpt_l0_base != 0UL); + + /* Ensure that caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); + + /* Delegate request can only come from REALM or SECURE */ + assert(src_sec_state == SMC_FROM_REALM || + src_sec_state == SMC_FROM_SECURE); + + /* See if this is a single or a range of granule transition. */ + if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) { + return -EINVAL; + } + + /* Check that base and size are valid */ + if ((ULONG_MAX - base) < size) { + VERBOSE("[GPT] Transition request address overflow!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* Make sure base and size are valid. */ + if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + (size == 0UL) || + ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) { + VERBOSE("[GPT] Invalid granule transition address range!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + target_pas = GPT_GPI_REALM; + if (src_sec_state == SMC_FROM_SECURE) { + target_pas = GPT_GPI_SECURE; + } + + /* + * Access to L1 tables is controlled by a global lock to ensure + * that no more than one CPU is allowed to make changes at any + * given time. + */ + spin_lock(&gpt_lock); + res = get_gpi_params(base, &gpi_info); + if (res != 0) { + spin_unlock(&gpt_lock); + return res; + } + + /* Check that the current address is in NS state */ + if (gpi_info.gpi != GPT_GPI_NS) { + VERBOSE("[GPT] Only Granule in NS state can be delegated.\n"); + VERBOSE(" Caller: %u, Current GPI: %u\n", src_sec_state, + gpi_info.gpi); + spin_unlock(&gpt_lock); + return -EINVAL; + } + + if (src_sec_state == SMC_FROM_SECURE) { + nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT; + } else { + nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT; + } + + /* + * In order to maintain mutual distrust between Realm and Secure + * states, remove any data speculatively fetched into the target + * physical address space. Issue DC CIPAPA over address range + */ + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, target_pas); + dsboshst(); + + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT; + + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* Unlock access to the L1 tables. */ + spin_unlock(&gpt_lock); + + /* + * The isb() will be done as part of context + * synchronization when returning to lower EL + */ + VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n", + base, gpi_info.gpi, target_pas); + + return 0; +} + +/* + * This function is the granule transition undelegate service. When a granule + * transition request occurs it is routed to this function where the request is + * validated then fulfilled if possible. + * + * TODO: implement support for transitioning multiple granules at once. + * + * Parameters + * base Base address of the region to transition, must be + * aligned to granule size. + * size Size of region to transition, must be aligned to granule + * size. + * src_sec_state Security state of the caller. + * + * Return + * Negative Linux error code in the event of a failure, 0 for success. + */ +int gpt_undelegate_pas(uint64_t base, size_t size, unsigned int src_sec_state) +{ + gpi_info_t gpi_info; + uint64_t nse; + int res; + + /* Ensure that the tables have been set up before taking requests. */ + assert(gpt_config.plat_gpt_l0_base != 0UL); + + /* Ensure that MMU and caches are enabled. */ + assert((read_sctlr_el3() & SCTLR_C_BIT) != 0UL); + + /* Delegate request can only come from REALM or SECURE */ + assert(src_sec_state == SMC_FROM_REALM || + src_sec_state == SMC_FROM_SECURE); + + /* See if this is a single or a range of granule transition. */ + if (size != GPT_PGS_ACTUAL_SIZE(gpt_config.p)) { + return -EINVAL; + } + + /* Check that base and size are valid */ + if ((ULONG_MAX - base) < size) { + VERBOSE("[GPT] Transition request address overflow!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* Make sure base and size are valid. */ + if (((base & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + ((size & (GPT_PGS_ACTUAL_SIZE(gpt_config.p) - 1)) != 0UL) || + (size == 0UL) || + ((base + size) >= GPT_PPS_ACTUAL_SIZE(gpt_config.t))) { + VERBOSE("[GPT] Invalid granule transition address range!\n"); + VERBOSE(" Base=0x%" PRIx64 "\n", base); + VERBOSE(" Size=0x%lx\n", size); + return -EINVAL; + } + + /* + * Access to L1 tables is controlled by a global lock to ensure + * that no more than one CPU is allowed to make changes at any + * given time. + */ + spin_lock(&gpt_lock); + + res = get_gpi_params(base, &gpi_info); + if (res != 0) { + spin_unlock(&gpt_lock); + return res; + } + + /* Check that the current address is in the delegated state */ + if ((src_sec_state == SMC_FROM_REALM && + gpi_info.gpi != GPT_GPI_REALM) || + (src_sec_state == SMC_FROM_SECURE && + gpi_info.gpi != GPT_GPI_SECURE)) { + VERBOSE("[GPT] Only Granule in REALM or SECURE state can be undelegated.\n"); + VERBOSE(" Caller: %u, Current GPI: %u\n", src_sec_state, + gpi_info.gpi); + spin_unlock(&gpt_lock); + return -EINVAL; + } + + + /* In order to maintain mutual distrust between Realm and Secure + * states, remove access now, in order to guarantee that writes + * to the currently-accessible physical address space will not + * later become observable. + */ + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NO_ACCESS); + dsboshst(); + + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + if (src_sec_state == SMC_FROM_SECURE) { + nse = (uint64_t)GPT_NSE_SECURE << GPT_NSE_SHIFT; + } else { + nse = (uint64_t)GPT_NSE_REALM << GPT_NSE_SHIFT; + } + + /* Ensure that the scrubbed data has made it past the PoPA */ + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* + * Remove any data loaded speculatively + * in NS space from before the scrubbing + */ + nse = (uint64_t)GPT_NSE_NS << GPT_NSE_SHIFT; + + flush_dcache_to_popa_range(nse | base, + GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + + /* Clear existing GPI encoding and transition granule. */ + write_gpt(&gpi_info.gpt_l1_desc, gpi_info.gpt_l1_addr, + gpi_info.gpi_shift, gpi_info.idx, GPT_GPI_NS); + dsboshst(); + + /* Ensure that all agents observe the new NS configuration */ + gpt_tlbi_by_pa_ll(base, GPT_PGS_ACTUAL_SIZE(gpt_config.p)); + dsbosh(); + + /* Unlock access to the L1 tables. */ + spin_unlock(&gpt_lock); + + /* + * The isb() will be done as part of context + * synchronization when returning to lower EL + */ + VERBOSE("[GPT] Granule 0x%" PRIx64 ", GPI 0x%x->0x%x\n", + base, gpi_info.gpi, GPT_GPI_NS); + + return 0; +} diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk new file mode 100644 index 0000000..60176f4 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme.mk @@ -0,0 +1,8 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +GPT_LIB_SRCS := $(addprefix lib/gpt_rme/, \ + gpt_rme.c) diff --git a/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h b/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h new file mode 100644 index 0000000..3c817f3 --- /dev/null +++ b/arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef GPT_RME_PRIVATE_H +#define GPT_RME_PRIVATE_H + +#include +#include +#include + +/******************************************************************************/ +/* GPT descriptor definitions */ +/******************************************************************************/ + +/* GPT level 0 descriptor bit definitions. */ +#define GPT_L0_TYPE_MASK UL(0xF) +#define GPT_L0_TYPE_SHIFT U(0) + +/* For now, we don't support contiguous descriptors, only table and block. */ +#define GPT_L0_TYPE_TBL_DESC UL(0x3) +#define GPT_L0_TYPE_BLK_DESC UL(0x1) + +#define GPT_L0_TBL_DESC_L1ADDR_MASK UL(0xFFFFFFFFFF) +#define GPT_L0_TBL_DESC_L1ADDR_SHIFT U(12) + +#define GPT_L0_BLK_DESC_GPI_MASK UL(0xF) +#define GPT_L0_BLK_DESC_GPI_SHIFT U(4) + +/* GPT level 1 descriptor bit definitions */ +#define GPT_L1_GRAN_DESC_GPI_MASK UL(0xF) + +/* + * This macro fills out every GPI entry in a granules descriptor to the same + * value. + */ +#define GPT_BUILD_L1_DESC(_gpi) (((uint64_t)(_gpi) << 4*0) | \ + ((uint64_t)(_gpi) << 4*1) | \ + ((uint64_t)(_gpi) << 4*2) | \ + ((uint64_t)(_gpi) << 4*3) | \ + ((uint64_t)(_gpi) << 4*4) | \ + ((uint64_t)(_gpi) << 4*5) | \ + ((uint64_t)(_gpi) << 4*6) | \ + ((uint64_t)(_gpi) << 4*7) | \ + ((uint64_t)(_gpi) << 4*8) | \ + ((uint64_t)(_gpi) << 4*9) | \ + ((uint64_t)(_gpi) << 4*10) | \ + ((uint64_t)(_gpi) << 4*11) | \ + ((uint64_t)(_gpi) << 4*12) | \ + ((uint64_t)(_gpi) << 4*13) | \ + ((uint64_t)(_gpi) << 4*14) | \ + ((uint64_t)(_gpi) << 4*15)) + +/******************************************************************************/ +/* GPT platform configuration */ +/******************************************************************************/ + +/* This value comes from GPCCR_EL3 so no externally supplied definition. */ +#define GPT_L0GPTSZ ((unsigned int)((read_gpccr_el3() >> \ + GPCCR_L0GPTSZ_SHIFT) & GPCCR_L0GPTSZ_MASK)) + +/* The "S" value is directly related to L0GPTSZ */ +#define GPT_S_VAL (GPT_L0GPTSZ + 30U) + +/* + * Map PPS values to T values. + * + * PPS Size T + * 0b000 4GB 32 + * 0b001 64GB 36 + * 0b010 1TB 40 + * 0b011 4TB 42 + * 0b100 16TB 44 + * 0b101 256TB 48 + * 0b110 4PB 52 + * + * See section 15.1.27 of the RME specification. + */ +typedef enum { + PPS_4GB_T = 32U, + PPS_64GB_T = 36U, + PPS_1TB_T = 40U, + PPS_4TB_T = 42U, + PPS_16TB_T = 44U, + PPS_256TB_T = 48U, + PPS_4PB_T = 52U +} gpt_t_val_e; + +/* + * Map PGS values to P values. + * + * PGS Size P + * 0b00 4KB 12 + * 0b10 16KB 14 + * 0b01 64KB 16 + * + * Note that pgs=0b10 is 16KB and pgs=0b01 is 64KB, this is not a typo. + * + * See section 15.1.27 of the RME specification. + */ +typedef enum { + PGS_4KB_P = 12U, + PGS_16KB_P = 14U, + PGS_64KB_P = 16U +} gpt_p_val_e; + +/* + * Internal structure to retrieve the values from get_gpi_info(); + */ +typedef struct gpi_info { + uint64_t gpt_l1_desc; + uint64_t *gpt_l1_addr; + unsigned int idx; + unsigned int gpi_shift; + unsigned int gpi; +} gpi_info_t; + +/* Max valid value for PGS. */ +#define GPT_PGS_MAX (2U) + +/* Max valid value for PPS. */ +#define GPT_PPS_MAX (6U) + +/******************************************************************************/ +/* L0 address attribute macros */ +/******************************************************************************/ + +/* + * Width of the L0 index field. + * + * If S is greater than or equal to T then there is a single L0 region covering + * the entire protected space so there is no L0 index, so the width (and the + * derivative mask value) are both zero. If we don't specifically handle this + * special case we'll get a negative width value which does not make sense and + * would cause problems. + */ +#define GPT_L0_IDX_WIDTH(_t) (((_t) > GPT_S_VAL) ? \ + ((_t) - GPT_S_VAL) : (0U)) + +/* Bit shift for the L0 index field in a PA. */ +#define GPT_L0_IDX_SHIFT (GPT_S_VAL) + +/* + * Mask for the L0 index field, must be shifted. + * + * The value 0x3FFFFF is 22 bits wide which is the maximum possible width of the + * L0 index within a physical address. This is calculated by + * ((t_max - 1) - s_min + 1) where t_max is 52 for 4PB, the largest PPS, and + * s_min is 30 for 1GB, the smallest L0GPTSZ. + */ +#define GPT_L0_IDX_MASK(_t) (0x3FFFFFUL >> (22U - \ + (GPT_L0_IDX_WIDTH(_t)))) + +/* Total number of L0 regions. */ +#define GPT_L0_REGION_COUNT(_t) ((GPT_L0_IDX_MASK(_t)) + 1U) + +/* Total size of each GPT L0 region in bytes. */ +#define GPT_L0_REGION_SIZE (1UL << (GPT_L0_IDX_SHIFT)) + +/* Total size in bytes of the whole L0 table. */ +#define GPT_L0_TABLE_SIZE(_t) ((GPT_L0_REGION_COUNT(_t)) << 3U) + +/******************************************************************************/ +/* L1 address attribute macros */ +/******************************************************************************/ + +/* + * Width of the L1 index field. + * + * This field does not have a special case to handle widths less than zero like + * the L0 index field above since all valid combinations of PGS (p) and L0GPTSZ + * (s) will result in a positive width value. + */ +#define GPT_L1_IDX_WIDTH(_p) ((GPT_S_VAL - 1U) - ((_p) + 3U)) + +/* Bit shift for the L1 index field. */ +#define GPT_L1_IDX_SHIFT(_p) ((_p) + 4U) + +/* + * Mask for the L1 index field, must be shifted. + * + * The value 0x7FFFFF is 23 bits wide and is the maximum possible width of the + * L1 index within a physical address. It is calculated by + * ((s_max - 1) - (p_min + 4) + 1) where s_max is 39 for 512gb, the largest + * L0GPTSZ, and p_min is 12 for 4KB granules, the smallest PGS. + */ +#define GPT_L1_IDX_MASK(_p) (0x7FFFFFUL >> (23U - \ + (GPT_L1_IDX_WIDTH(_p)))) + +/* Bit shift for the index of the L1 GPI in a PA. */ +#define GPT_L1_GPI_IDX_SHIFT(_p) (_p) + +/* Mask for the index of the L1 GPI in a PA. */ +#define GPT_L1_GPI_IDX_MASK (0xF) + +/* Total number of entries in each L1 table. */ +#define GPT_L1_ENTRY_COUNT(_p) ((GPT_L1_IDX_MASK(_p)) + 1U) + +/* Total size in bytes of each L1 table. */ +#define GPT_L1_TABLE_SIZE(_p) ((GPT_L1_ENTRY_COUNT(_p)) << 3U) + +/******************************************************************************/ +/* General helper macros */ +/******************************************************************************/ + +/* Protected space actual size in bytes. */ +#define GPT_PPS_ACTUAL_SIZE(_t) (1UL << (_t)) + +/* Granule actual size in bytes. */ +#define GPT_PGS_ACTUAL_SIZE(_p) (1UL << (_p)) + +/* L0 GPT region size in bytes. */ +#define GPT_L0GPTSZ_ACTUAL_SIZE (1UL << GPT_S_VAL) + +/* Get the index of the L0 entry from a physical address. */ +#define GPT_L0_IDX(_pa) ((_pa) >> GPT_L0_IDX_SHIFT) + +/* + * This definition is used to determine if a physical address lies on an L0 + * region boundary. + */ +#define GPT_IS_L0_ALIGNED(_pa) (((_pa) & (GPT_L0_REGION_SIZE - U(1))) == U(0)) + +/* Get the type field from an L0 descriptor. */ +#define GPT_L0_TYPE(_desc) (((_desc) >> GPT_L0_TYPE_SHIFT) & \ + GPT_L0_TYPE_MASK) + +/* Create an L0 block descriptor. */ +#define GPT_L0_BLK_DESC(_gpi) (GPT_L0_TYPE_BLK_DESC | \ + (((_gpi) & GPT_L0_BLK_DESC_GPI_MASK) << \ + GPT_L0_BLK_DESC_GPI_SHIFT)) + +/* Create an L0 table descriptor with an L1 table address. */ +#define GPT_L0_TBL_DESC(_pa) (GPT_L0_TYPE_TBL_DESC | ((uint64_t)(_pa) & \ + (GPT_L0_TBL_DESC_L1ADDR_MASK << \ + GPT_L0_TBL_DESC_L1ADDR_SHIFT))) + +/* Get the GPI from an L0 block descriptor. */ +#define GPT_L0_BLKD_GPI(_desc) (((_desc) >> GPT_L0_BLK_DESC_GPI_SHIFT) & \ + GPT_L0_BLK_DESC_GPI_MASK) + +/* Get the L1 address from an L0 table descriptor. */ +#define GPT_L0_TBLD_ADDR(_desc) ((uint64_t *)(((_desc) & \ + (GPT_L0_TBL_DESC_L1ADDR_MASK << \ + GPT_L0_TBL_DESC_L1ADDR_SHIFT)))) + +/* Get the index into the L1 table from a physical address. */ +#define GPT_L1_IDX(_p, _pa) (((_pa) >> GPT_L1_IDX_SHIFT(_p)) & \ + GPT_L1_IDX_MASK(_p)) + +/* Get the index of the GPI within an L1 table entry from a physical address. */ +#define GPT_L1_GPI_IDX(_p, _pa) (((_pa) >> GPT_L1_GPI_IDX_SHIFT(_p)) & \ + GPT_L1_GPI_IDX_MASK) + +/* Determine if an address is granule-aligned. */ +#define GPT_IS_L1_ALIGNED(_p, _pa) (((_pa) & (GPT_PGS_ACTUAL_SIZE(_p) - U(1))) \ + == U(0)) + +#endif /* GPT_RME_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/libc/aarch32/memset.S b/arm-trusted-firmware/lib/libc/aarch32/memset.S new file mode 100644 index 0000000..880ba83 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/aarch32/memset.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .syntax unified + .global memset + +/* ----------------------------------------------------------------------- + * void *memset(void *dst, int val, size_t count) + * + * Copy the value of 'val' (converted to an unsigned char) into + * each of the first 'count' characters of the object pointed to by 'dst'. + * + * Returns the value of 'dst'. + * ----------------------------------------------------------------------- + */ +func memset + mov r12, r0 /* keep r0 */ + tst r0, #3 + beq aligned /* 4-bytes aligned */ + + /* Unaligned 'dst' */ +unaligned: + subs r2, r2, #1 + strbhs r1, [r12], #1 + bxls lr /* return if 0 */ + tst r12, #3 + bne unaligned /* continue while unaligned */ + + /* 4-bytes aligned */ +aligned:bfi r1, r1, #8, #8 /* propagate 'val' */ + bfi r1, r1, #16, #16 + + mov r3, r1 + + cmp r2, #16 + blo less_16 /* < 16 */ + + push {r4, lr} + mov r4, r1 + mov lr, r1 + +write_32: + subs r2, r2, #32 + stmiahs r12!, {r1, r3, r4, lr} + stmiahs r12!, {r1, r3, r4, lr} + bhi write_32 /* write 32 bytes in a loop */ + popeq {r4, pc} /* return if 0 */ + lsls r2, r2, #28 /* C = r2[4]; N = r2[3]; Z = r2[3:0] */ + stmiacs r12!, {r1, r3, r4, lr} /* write 16 bytes */ + popeq {r4, pc} /* return if 16 */ + stmiami r12!, {r1, r3} /* write 8 bytes */ + lsls r2, r2, #2 /* C = r2[2]; N = r2[1]; Z = r2[1:0] */ + strcs r1, [r12], #4 /* write 4 bytes */ + popeq {r4, pc} /* return if 8 or 4 */ + strhmi r1, [r12], #2 /* write 2 bytes */ + lsls r2, r2, #1 /* N = Z = r2[0] */ + strbmi r1, [r12] /* write 1 byte */ + pop {r4, pc} + +less_16:lsls r2, r2, #29 /* C = r2[3]; N = r2[2]; Z = r2[2:0] */ + stmiacs r12!, {r1, r3} /* write 8 bytes */ + bxeq lr /* return if 8 */ + strmi r1, [r12], #4 /* write 4 bytes */ + lsls r2, r2, #2 /* C = r2[1]; N = Z = r2[0] */ + strhcs r1, [r12], #2 /* write 2 bytes */ + strbmi r1, [r12] /* write 1 byte */ + bx lr + +endfunc memset diff --git a/arm-trusted-firmware/lib/libc/aarch64/memset.S b/arm-trusted-firmware/lib/libc/aarch64/memset.S new file mode 100644 index 0000000..0543704 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/aarch64/memset.S @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .global memset + +/* ----------------------------------------------------------------------- + * void *memset(void *dst, int val, size_t count) + * + * Copy the value of 'val' (converted to an unsigned char) into + * each of the first 'count' characters of the object pointed to by 'dst'. + * + * Returns the value of 'dst'. + * ----------------------------------------------------------------------- + */ +func memset + cbz x2, exit /* exit if 'count' = 0 */ + mov x3, x0 /* keep x0 */ + tst x0, #7 + b.eq aligned /* 8-bytes aligned */ + + /* Unaligned 'dst' */ +unaligned: + strb w1, [x3], #1 + subs x2, x2, #1 + b.eq exit /* exit if 0 */ + tst x3, #7 + b.ne unaligned /* continue while unaligned */ + + /* 8-bytes aligned */ +aligned:cbz x1, x1_zero + bfi w1, w1, #8, #8 /* propagate 'val' */ + bfi w1, w1, #16, #16 + bfi x1, x1, #32, #32 + +x1_zero:ands x4, x2, #~0x3f + b.eq less_64 + +write_64: + .rept 4 + stp x1, x1, [x3], #16 /* write 64 bytes in a loop */ + .endr + subs x4, x4, #64 + b.ne write_64 +less_64:tbz w2, #5, less_32 /* < 32 bytes */ + stp x1, x1, [x3], #16 /* write 32 bytes */ + stp x1, x1, [x3], #16 +less_32:tbz w2, #4, less_16 /* < 16 bytes */ + stp x1, x1, [x3], #16 /* write 16 bytes */ +less_16:tbz w2, #3, less_8 /* < 8 bytes */ + str x1, [x3], #8 /* write 8 bytes */ +less_8: tbz w2, #2, less_4 /* < 4 bytes */ + str w1, [x3], #4 /* write 4 bytes */ +less_4: tbz w2, #1, less_2 /* < 2 bytes */ + strh w1, [x3], #2 /* write 2 bytes */ +less_2: tbz w2, #0, exit + strb w1, [x3] /* write 1 byte */ +exit: ret + +endfunc memset diff --git a/arm-trusted-firmware/lib/libc/aarch64/setjmp.S b/arm-trusted-firmware/lib/libc/aarch64/setjmp.S new file mode 100644 index 0000000..9d9eb49 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/aarch64/setjmp.S @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl setjmp + .globl longjmp + +/* + * int setjmp(jmp_buf env); + */ +func setjmp + mov x7, sp + + stp x19, x20, [x0, #JMP_CTX_X19] + stp x21, x22, [x0, #JMP_CTX_X21] + stp x23, x24, [x0, #JMP_CTX_X23] + stp x25, x26, [x0, #JMP_CTX_X25] + stp x27, x28, [x0, #JMP_CTX_X27] + stp x29, x30, [x0, #JMP_CTX_X29] + stp x7, xzr, [x0, #JMP_CTX_SP] + + mov x0, #0 + ret +endfunc setjmp + + +/* + * void longjmp(jmp_buf env, int val); + */ +func longjmp + ldp x7, xzr, [x0, #JMP_CTX_SP] + +#if ENABLE_ASSERTIONS + /* + * Since we're unwinding the stack, assert that the stack being reset to + * is shallower. + */ + mov x19, sp + cmp x7, x19 + ASM_ASSERT(ge) +#endif + + ldp x19, x20, [x0, #JMP_CTX_X19] + ldp x21, x22, [x0, #JMP_CTX_X21] + ldp x23, x24, [x0, #JMP_CTX_X23] + ldp x25, x26, [x0, #JMP_CTX_X25] + ldp x27, x28, [x0, #JMP_CTX_X27] + ldp x29, x30, [x0, #JMP_CTX_X29] + + mov sp, x7 + + ands x0, x1, x1 /* Move val to x0 and set flags */ + cinc x0, x0, eq /* If val is 0, return 1 */ + ret +endfunc longjmp diff --git a/arm-trusted-firmware/lib/libc/abort.c b/arm-trusted-firmware/lib/libc/abort.c new file mode 100644 index 0000000..432b1d0 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/abort.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void abort(void) +{ + ERROR("ABORT\n"); + panic(); +} diff --git a/arm-trusted-firmware/lib/libc/assert.c b/arm-trusted-firmware/lib/libc/assert.c new file mode 100644 index 0000000..c199de6 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/assert.c @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +/* + * Only print the output if PLAT_LOG_LEVEL_ASSERT is higher or equal to + * LOG_LEVEL_INFO, which is the default value for builds with DEBUG=1. + */ + +#if PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_VERBOSE +void __dead2 __assert(const char *file, unsigned int line, + const char *assertion) +{ + printf("ASSERT: %s:%u:%s\n", file, line, assertion); + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#elif PLAT_LOG_LEVEL_ASSERT >= LOG_LEVEL_INFO +void __dead2 __assert(const char *file, unsigned int line) +{ + printf("ASSERT: %s:%u\n", file, line); + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#else +void __dead2 __assert(void) +{ + backtrace("assert"); + console_flush(); + plat_panic_handler(); +} +#endif diff --git a/arm-trusted-firmware/lib/libc/exit.c b/arm-trusted-firmware/lib/libc/exit.c new file mode 100644 index 0000000..f4ffe27 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/exit.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static void (*exitfun)(void); + +void exit(int status) +{ + if (exitfun != NULL) + (*exitfun)(); + for (;;) + ; +} + +int atexit(void (*fun)(void)) +{ + if (exitfun != NULL) + return -1; + exitfun = fun; + + return 0; +} diff --git a/arm-trusted-firmware/lib/libc/libc.mk b/arm-trusted-firmware/lib/libc/libc.mk new file mode 100644 index 0000000..b75d09c --- /dev/null +++ b/arm-trusted-firmware/lib/libc/libc.mk @@ -0,0 +1,41 @@ +# +# Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBC_SRCS := $(addprefix lib/libc/, \ + abort.c \ + assert.c \ + exit.c \ + memchr.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memrchr.c \ + memset.c \ + printf.c \ + putchar.c \ + puts.c \ + snprintf.c \ + strchr.c \ + strcmp.c \ + strlcat.c \ + strlcpy.c \ + strlen.c \ + strncmp.c \ + strnlen.c \ + strrchr.c \ + strtok.c \ + strtoul.c \ + strtoll.c \ + strtoull.c \ + strtol.c) + +ifeq (${ARCH},aarch64) +LIBC_SRCS += $(addprefix lib/libc/aarch64/, \ + setjmp.S) +endif + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ diff --git a/arm-trusted-firmware/lib/libc/libc_asm.mk b/arm-trusted-firmware/lib/libc/libc_asm.mk new file mode 100644 index 0000000..2f27265 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/libc_asm.mk @@ -0,0 +1,44 @@ +# +# Copyright (c) 2020-2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBC_SRCS := $(addprefix lib/libc/, \ + abort.c \ + assert.c \ + exit.c \ + memchr.c \ + memcmp.c \ + memcpy.c \ + memmove.c \ + memrchr.c \ + printf.c \ + putchar.c \ + puts.c \ + snprintf.c \ + strchr.c \ + strcmp.c \ + strlcat.c \ + strlcpy.c \ + strlen.c \ + strncmp.c \ + strnlen.c \ + strrchr.c \ + strtok.c \ + strtoul.c \ + strtoll.c \ + strtoull.c \ + strtol.c) + +ifeq (${ARCH},aarch64) +LIBC_SRCS += $(addprefix lib/libc/aarch64/, \ + memset.S \ + setjmp.S) +else +LIBC_SRCS += $(addprefix lib/libc/aarch32/, \ + memset.S) +endif + +INCLUDES += -Iinclude/lib/libc \ + -Iinclude/lib/libc/$(ARCH) \ diff --git a/arm-trusted-firmware/lib/libc/memchr.c b/arm-trusted-firmware/lib/libc/memchr.c new file mode 100644 index 0000000..8cbb715 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memchr.c @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void *memchr(const void *src, int c, size_t len) +{ + const unsigned char *s = src; + + while (len--) { + if (*s == (unsigned char)c) + return (void *) s; + s++; + } + + return NULL; +} diff --git a/arm-trusted-firmware/lib/libc/memcmp.c b/arm-trusted-firmware/lib/libc/memcmp.c new file mode 100644 index 0000000..cd5f0df --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memcmp.c @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +int memcmp(const void *s1, const void *s2, size_t len) +{ + const unsigned char *s = s1; + const unsigned char *d = s2; + unsigned char sc; + unsigned char dc; + + while (len--) { + sc = *s++; + dc = *d++; + if (sc - dc) + return (sc - dc); + } + + return 0; +} diff --git a/arm-trusted-firmware/lib/libc/memcpy.c b/arm-trusted-firmware/lib/libc/memcpy.c new file mode 100644 index 0000000..158df9b --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memcpy.c @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void *memcpy(void *dst, const void *src, size_t len) +{ + const char *s = src; + char *d = dst; + + while (len--) + *d++ = *s++; + + return dst; +} diff --git a/arm-trusted-firmware/lib/libc/memmove.c b/arm-trusted-firmware/lib/libc/memmove.c new file mode 100644 index 0000000..63acf26 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memmove.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void *memmove(void *dst, const void *src, size_t len) +{ + /* + * The following test makes use of unsigned arithmetic overflow to + * more efficiently test the condition !(src <= dst && dst < str+len). + * It also avoids the situation where the more explicit test would give + * incorrect results were the calculation str+len to overflow (though + * that issue is probably moot as such usage is probably undefined + * behaviour and a bug anyway. + */ + if ((size_t)dst - (size_t)src >= len) { + /* destination not in source data, so can safely use memcpy */ + return memcpy(dst, src, len); + } else { + /* copy backwards... */ + const char *end = dst; + const char *s = (const char *)src + len; + char *d = (char *)dst + len; + while (d != end) + *--d = *--s; + } + return dst; +} diff --git a/arm-trusted-firmware/lib/libc/memrchr.c b/arm-trusted-firmware/lib/libc/memrchr.c new file mode 100644 index 0000000..01caef3 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memrchr.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#undef memrchr + +void *memrchr(const void *src, int c, size_t len) +{ + const unsigned char *s = src + (len - 1); + + while (len--) { + if (*s == (unsigned char)c) { + return (void*) s; + } + + s--; + } + + return NULL; +} diff --git a/arm-trusted-firmware/lib/libc/memset.c b/arm-trusted-firmware/lib/libc/memset.c new file mode 100644 index 0000000..17f798c --- /dev/null +++ b/arm-trusted-firmware/lib/libc/memset.c @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void *memset(void *dst, int val, size_t count) +{ + uint8_t *ptr = dst; + uint64_t *ptr64; + uint64_t fill = (unsigned char)val; + + /* Simplify code below by making sure we write at least one byte. */ + if (count == 0U) { + return dst; + } + + /* Handle the first part, until the pointer becomes 64-bit aligned. */ + while (((uintptr_t)ptr & 7U) != 0U) { + *ptr = (uint8_t)val; + ptr++; + if (--count == 0U) { + return dst; + } + } + + /* Duplicate the fill byte to the rest of the 64-bit word. */ + fill |= fill << 8; + fill |= fill << 16; + fill |= fill << 32; + + /* Use 64-bit writes for as long as possible. */ + ptr64 = (uint64_t *)ptr; + for (; count >= 8U; count -= 8) { + *ptr64 = fill; + ptr64++; + } + + /* Handle the remaining part byte-per-byte. */ + ptr = (uint8_t *)ptr64; + while (count-- > 0U) { + *ptr = (uint8_t)val; + ptr++; + } + + return dst; +} diff --git a/arm-trusted-firmware/lib/libc/printf.c b/arm-trusted-firmware/lib/libc/printf.c new file mode 100644 index 0000000..45e153e --- /dev/null +++ b/arm-trusted-firmware/lib/libc/printf.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#define get_num_va_args(_args, _lcount) \ + (((_lcount) > 1) ? va_arg(_args, long long int) : \ + (((_lcount) == 1) ? va_arg(_args, long int) : \ + va_arg(_args, int))) + +#define get_unum_va_args(_args, _lcount) \ + (((_lcount) > 1) ? va_arg(_args, unsigned long long int) : \ + (((_lcount) == 1) ? va_arg(_args, unsigned long int) : \ + va_arg(_args, unsigned int))) + +static int string_print(const char *str) +{ + int count = 0; + + assert(str != NULL); + + for ( ; *str != '\0'; str++) { + (void)putchar(*str); + count++; + } + + return count; +} + +static int unsigned_num_print(unsigned long long int unum, unsigned int radix, + char padc, int padn) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0, count = 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); + + if (padn > 0) { + while (i < padn) { + (void)putchar(padc); + count++; + padn--; + } + } + + while (--i >= 0) { + (void)putchar(num_buf[i]); + count++; + } + + return count; +} + +/******************************************************************* + * Reduced format print for Trusted firmware. + * The following type specifiers are supported by this print + * %x - hexadecimal format + * %s - string format + * %d or %i - signed decimal format + * %u - unsigned decimal format + * %p - pointer format + * + * The following length specifiers are supported by this print + * %l - long int (64-bit on AArch64) + * %ll - long long int (64-bit on AArch64) + * %z - size_t sized integer formats (64 bit on AArch64) + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * + * The print exits on all other formats specifiers other than valid + * combinations of the above specifiers. + *******************************************************************/ +int vprintf(const char *fmt, va_list args) +{ + int l_count; + long long int num; + unsigned long long int unum; + char *str; + char padc = '\0'; /* Padding character */ + int padn; /* Number of characters to pad */ + int count = 0; /* Number of printed characters */ + + while (*fmt != '\0') { + l_count = 0; + padn = 0; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier */ +loop: + switch (*fmt) { + case '%': + (void)putchar('%'); + break; + case 'i': /* Fall through to next one */ + case 'd': + num = get_num_va_args(args, l_count); + if (num < 0) { + (void)putchar('-'); + unum = (unsigned long long int)-num; + padn--; + } else + unum = (unsigned long long int)num; + + count += unsigned_num_print(unum, 10, + padc, padn); + break; + case 's': + str = va_arg(args, char *); + count += string_print(str); + break; + case 'p': + unum = (uintptr_t)va_arg(args, void *); + if (unum > 0U) { + count += string_print("0x"); + padn -= 2; + } + + count += unsigned_num_print(unum, 16, + padc, padn); + break; + case 'x': + unum = get_unum_va_args(args, l_count); + count += unsigned_num_print(unum, 16, + padc, padn); + break; + case 'z': + if (sizeof(size_t) == 8U) + l_count = 2; + + fmt++; + goto loop; + case 'l': + l_count++; + fmt++; + goto loop; + case 'u': + unum = get_unum_va_args(args, l_count); + count += unsigned_num_print(unum, 10, + padc, padn); + break; + case '0': + padc = '0'; + padn = 0; + fmt++; + + for (;;) { + char ch = *fmt; + if ((ch < '0') || (ch > '9')) { + goto loop; + } + padn = (padn * 10) + (ch - '0'); + fmt++; + } + assert(0); /* Unreachable */ + default: + /* Exit on any other format specifier */ + return -1; + } + fmt++; + continue; + } + (void)putchar(*fmt); + fmt++; + count++; + } + + return count; +} + +int printf(const char *fmt, ...) +{ + int count; + va_list va; + + va_start(va, fmt); + count = vprintf(fmt, va); + va_end(va); + + return count; +} diff --git a/arm-trusted-firmware/lib/libc/putchar.c b/arm-trusted-firmware/lib/libc/putchar.c new file mode 100644 index 0000000..037e28a --- /dev/null +++ b/arm-trusted-firmware/lib/libc/putchar.c @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +int putchar(int c) +{ + int res; + if (console_putc((unsigned char)c) >= 0) + res = c; + else + res = EOF; + + return res; +} diff --git a/arm-trusted-firmware/lib/libc/puts.c b/arm-trusted-firmware/lib/libc/puts.c new file mode 100644 index 0000000..2a0ca11 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/puts.c @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +int puts(const char *s) +{ + int count = 0; + + while (*s != '\0') { + if (putchar(*s) == EOF) + return EOF; + s++; + count++; + } + + if (putchar('\n') == EOF) + return EOF; + + return count + 1; +} diff --git a/arm-trusted-firmware/lib/libc/snprintf.c b/arm-trusted-firmware/lib/libc/snprintf.c new file mode 100644 index 0000000..675d243 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/snprintf.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +#define CHECK_AND_PUT_CHAR(buf, size, chars_printed, ch) \ + do { \ + if ((chars_printed) < (size)) { \ + *(buf) = (ch); \ + (buf)++; \ + } \ + (chars_printed)++; \ + } while (false) + +static void string_print(char **s, size_t n, size_t *chars_printed, + const char *str) +{ + while (*str != '\0') { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, *str); + str++; + } +} + +static void unsigned_num_print(char **s, size_t n, size_t *chars_printed, + unsigned long long int unum, + unsigned int radix, char padc, int padn, + bool capitalise) +{ + /* Just need enough space to store 64 bit decimal integer */ + char num_buf[20]; + int i = 0; + int width; + unsigned int rem; + char ascii_a = capitalise ? 'A' : 'a'; + + if (radix < 10) { + ERROR("snprintf: unsupported radix '%u'.", radix); + plat_panic_handler(); + assert(0); /* Unreachable */ + } + + do { + rem = unum % radix; + if (rem < 10U) { + num_buf[i] = '0' + rem; + } else { + num_buf[i] = ascii_a + (rem - 10U); + } + i++; + unum /= radix; + } while (unum > 0U); + + width = i; + for (i = padn - width; i > 0; i--) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, padc); + } + for (i = width; i > 0; i--) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, num_buf[i - 1]); + } + for (i = width + padn; i < 0; i++) { + CHECK_AND_PUT_CHAR(*s, n, *chars_printed, padc); + } +} + +/******************************************************************* + * Reduced vsnprintf to be used for Trusted firmware. + * The following type specifiers are supported: + * + * %x (or %X) - hexadecimal format + * %d or %i - signed decimal format + * %s - string format + * %u - unsigned decimal format + * %p - pointer format + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * %NN - Left-pad the number or string with spaces (NN is a decimal number) + * %-NN - Right-pad the number or string with spaces (NN is a decimal number) + * + * The function panics on all other formats specifiers. + * + * It returns the number of characters that would be written if the + * buffer was big enough. If it returns a value lower than n, the + * whole string has been written. + *******************************************************************/ +int vsnprintf(char *s, size_t n, const char *fmt, va_list args) +{ + int num; + unsigned long long int unum; + char *str; + char padc; /* Padding character */ + int padn; /* Number of characters to pad */ + bool left; + bool capitalise; + size_t chars_printed = 0U; + + if (n == 0U) { + /* There isn't space for anything. */ + } else if (n == 1U) { + /* Buffer is too small to actually write anything else. */ + *s = '\0'; + n = 0U; + } else { + /* Reserve space for the terminator character. */ + n--; + } + + while (*fmt != '\0') { + left = false; + padc ='\0'; + padn = 0; + capitalise = false; + + if (*fmt == '%') { + fmt++; + /* Check the format specifier. */ +loop: + switch (*fmt) { + case '%': + CHECK_AND_PUT_CHAR(s, n, chars_printed, '%'); + break; + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + padc = (*fmt == '0') ? '0' : ' '; + for (padn = 0; *fmt >= '0' && *fmt <= '9'; fmt++) { + padn = (padn * 10) + (*fmt - '0'); + } + if (left) { + padn = -padn; + } + goto loop; + case '-': + left = true; + fmt++; + goto loop; + + case 'i': + case 'd': + num = va_arg(args, int); + + if (num < 0) { + CHECK_AND_PUT_CHAR(s, n, chars_printed, + '-'); + unum = (unsigned int)-num; + } else { + unum = (unsigned int)num; + } + + unsigned_num_print(&s, n, &chars_printed, + unum, 10, padc, padn, false); + break; + case 's': + str = va_arg(args, char *); + string_print(&s, n, &chars_printed, str); + break; + case 'u': + unum = va_arg(args, unsigned int); + unsigned_num_print(&s, n, &chars_printed, + unum, 10, padc, padn, false); + break; + case 'p': + unum = (uintptr_t)va_arg(args, void *); + if (unum > 0U) { + string_print(&s, n, &chars_printed, "0x"); + padn -= 2; + } + unsigned_num_print(&s, n, &chars_printed, + unum, 16, padc, padn, false); + break; + case 'X': + capitalise = true; + case 'x': + unum = va_arg(args, unsigned int); + unsigned_num_print(&s, n, &chars_printed, + unum, 16, padc, padn, + capitalise); + break; + + default: + /* Panic on any other format specifier. */ + ERROR("snprintf: specifier with ASCII code '%d' not supported.", + *fmt); + plat_panic_handler(); + assert(0); /* Unreachable */ + } + fmt++; + continue; + } + + CHECK_AND_PUT_CHAR(s, n, chars_printed, *fmt); + + fmt++; + } + + if (n > 0U) { + *s = '\0'; + } + + return (int)chars_printed; +} + +/******************************************************************* + * Reduced snprintf to be used for Trusted firmware. + * The following type specifiers are supported: + * + * %x (or %X) - hexadecimal format + * %d or %i - signed decimal format + * %s - string format + * %u - unsigned decimal format + * %p - pointer format + * + * The following padding specifiers are supported by this print + * %0NN - Left-pad the number with 0s (NN is a decimal number) + * %NN - Left-pad the number or string with spaces (NN is a decimal number) + * %-NN - Right-pad the number or string with spaces (NN is a decimal number) + * + * The function panics on all other formats specifiers. + * + * It returns the number of characters that would be written if the + * buffer was big enough. If it returns a value lower than n, the + * whole string has been written. + *******************************************************************/ +int snprintf(char *s, size_t n, const char *fmt, ...) +{ + int count; + va_list all_args; + + va_start(all_args, fmt); + count = vsnprintf(s, n, fmt, all_args); + va_end(all_args); + + return count; +} diff --git a/arm-trusted-firmware/lib/libc/strchr.c b/arm-trusted-firmware/lib/libc/strchr.c new file mode 100644 index 0000000..d94bb9e --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strchr.c @@ -0,0 +1,53 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include +#include + +char * +strchr(const char *p, int ch) +{ + char c; + + c = ch; + for (;; ++p) { + if (*p == c) + return ((char *)p); + if (*p == '\0') + return (NULL); + } + /* NOTREACHED */ +} diff --git a/arm-trusted-firmware/lib/libc/strcmp.c b/arm-trusted-firmware/lib/libc/strcmp.c new file mode 100644 index 0000000..b742f9b --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strcmp.c @@ -0,0 +1,52 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Chris Torek. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +/* + * Compare strings. + */ +int +strcmp(const char *s1, const char *s2) +{ + while (*s1 == *s2++) + if (*s1++ == '\0') + return (0); + return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1)); +} diff --git a/arm-trusted-firmware/lib/libc/strlcat.c b/arm-trusted-firmware/lib/libc/strlcat.c new file mode 100644 index 0000000..e60c863 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strlcat.c @@ -0,0 +1,56 @@ +/* $OpenBSD: strlcat.c,v 1.15 2015/03/02 21:41:08 millert Exp $ */ + +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1998, 2015 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include + +/* + * Appends src to string dst of size dsize (unlike strncat, dsize is the + * full size of dst, not space left). At most dsize-1 characters + * will be copied. Always NUL terminates (unless dsize <= strlen(dst)). + * Returns strlen(src) + MIN(dsize, strlen(initial dst)). + * If retval >= dsize, truncation occurred. + */ +size_t +strlcat(char * dst, const char * src, size_t dsize) +{ + const char *odst = dst; + const char *osrc = src; + size_t n = dsize; + size_t dlen; + + /* Find the end of dst and adjust bytes left but don't go past end. */ + while (n-- != 0 && *dst != '\0') + dst++; + dlen = dst - odst; + n = dsize - dlen; + + if (n-- == 0) + return(dlen + strlen(src)); + while (*src != '\0') { + if (n != 0) { + *dst++ = *src; + n--; + } + src++; + } + *dst = '\0'; + + return(dlen + (src - osrc)); /* count does not include NUL */ +} diff --git a/arm-trusted-firmware/lib/libc/strlcpy.c b/arm-trusted-firmware/lib/libc/strlcpy.c new file mode 100644 index 0000000..c4f39bb --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strlcpy.c @@ -0,0 +1,52 @@ +/* $OpenBSD: strlcpy.c,v 1.12 2015/01/15 03:54:12 millert Exp $ */ + +/* + * SPDX-License-Identifier: ISC + * + * Copyright (c) 1998, 2015 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + */ + +#include +#include + +/* + * Copy string src to buffer dst of size dsize. At most dsize-1 + * chars will be copied. Always NUL terminates (unless dsize == 0). + * Returns strlen(src); if retval >= dsize, truncation occurred. + */ +size_t +strlcpy(char * dst, const char * src, size_t dsize) +{ + const char *osrc = src; + size_t nleft = dsize; + + /* Copy as many bytes as will fit. */ + if (nleft != 0) { + while (--nleft != 0) { + if ((*dst++ = *src++) == '\0') + break; + } + } + + /* Not enough room in dst, add NUL and traverse rest of src. */ + if (nleft == 0) { + if (dsize != 0) + *dst = '\0'; /* NUL-terminate dst */ + while (*src++) + ; + } + + return(src - osrc - 1); /* count does not include NUL */ +} diff --git a/arm-trusted-firmware/lib/libc/strlen.c b/arm-trusted-firmware/lib/libc/strlen.c new file mode 100644 index 0000000..3c27630 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strlen.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +size_t strlen(const char *s) +{ + const char *cursor = s; + + while (*cursor) + cursor++; + + return cursor - s; +} diff --git a/arm-trusted-firmware/lib/libc/strncmp.c b/arm-trusted-firmware/lib/libc/strncmp.c new file mode 100644 index 0000000..ce9e5ed --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strncmp.c @@ -0,0 +1,53 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1989, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +int +strncmp(const char *s1, const char *s2, size_t n) +{ + + if (n == 0) + return (0); + do { + if (*s1 != *s2++) + return (*(const unsigned char *)s1 - + *(const unsigned char *)(s2 - 1)); + if (*s1++ == '\0') + break; + } while (--n != 0); + return (0); +} diff --git a/arm-trusted-firmware/lib/libc/strnlen.c b/arm-trusted-firmware/lib/libc/strnlen.c new file mode 100644 index 0000000..b944e95 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strnlen.c @@ -0,0 +1,46 @@ +/*- + * SPDX-License-Identifier: BSD-2-Clause-FreeBSD + * + * Copyright (c) 2009 David Schultz + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +/* + * Portions copyright (c) 2018, ARM Limited and Contributors. + * All rights reserved. + */ + +#include + +size_t +strnlen(const char *s, size_t maxlen) +{ + size_t len; + + for (len = 0; len < maxlen; len++, s++) { + if (!*s) + break; + } + return (len); +} diff --git a/arm-trusted-firmware/lib/libc/strrchr.c b/arm-trusted-firmware/lib/libc/strrchr.c new file mode 100644 index 0000000..cd435ff --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strrchr.c @@ -0,0 +1,49 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include + +char * +strrchr(const char *p, int ch) +{ + char *save; + char c; + + c = ch; + for (save = NULL;; ++p) { + if (*p == c) + save = (char *)p; + if (*p == '\0') + return (save); + } + /* NOTREACHED */ +} diff --git a/arm-trusted-firmware/lib/libc/strtok.c b/arm-trusted-firmware/lib/libc/strtok.c new file mode 100644 index 0000000..7e1a4d2 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strtok.c @@ -0,0 +1,83 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1998 Softweyr LLC. All rights reserved. + * + * strtok_r, from Berkeley strtok + * Oct 13, 1998 by Wes Peters + * + * Copyright (c) 1988, 1993 + * The Regents of the University of California. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notices, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notices, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE + * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED + * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include + +char * +strtok_r(char *s, const char *delim, char **last) +{ + char *spanp, *tok; + int c, sc; + + if (s == NULL && (s = *last) == NULL) + return (NULL); + + /* + * Skip (span) leading delimiters (s += strspn(s, delim), sort of). + */ +cont: + c = *s++; + for (spanp = (char *)delim; (sc = *spanp++) != 0;) { + if (c == sc) + goto cont; + } + + if (c == 0) { /* no non-delimiter characters */ + *last = NULL; + return (NULL); + } + tok = s - 1; + + /* + * Scan token (scan for delimiters: s += strcspn(s, delim), sort of). + * Note that delim must have one NUL; we stop if we see that, too. + */ + for (;;) { + c = *s++; + spanp = (char *)delim; + do { + if ((sc = *spanp++) == c) { + if (c == 0) + s = NULL; + else + s[-1] = '\0'; + *last = s; + return (tok); + } + } while (sc != 0); + } + /* NOTREACHED */ +} diff --git a/arm-trusted-firmware/lib/libc/strtol.c b/arm-trusted-firmware/lib/libc/strtol.c new file mode 100644 index 0000000..deb862c --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strtol.c @@ -0,0 +1,133 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to a long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long strtol(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for longs is + * [-2147483648..2147483647] and the input base is 10, + * cutoff will be set to 214748364 and cutlim to either + * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated + * a value > 214748364, or equal but the next digit is > 7 (or 8), + * the number is too big, and we will return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX + : LONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LONG_MIN : LONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/arm-trusted-firmware/lib/libc/strtoll.c b/arm-trusted-firmware/lib/libc/strtoll.c new file mode 100644 index 0000000..4e101e8 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strtoll.c @@ -0,0 +1,134 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to a long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +long long strtoll(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * Skip white space and pick up leading +/- sign if any. + * If base is 0, allow 0x for hex and 0 for octal, else + * assume decimal; if base is already 16, allow 0x. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + /* + * Compute the cutoff value between legal numbers and illegal + * numbers. That is the largest legal value, divided by the + * base. An input number that is greater than this value, if + * followed by a legal input character, is too big. One that + * is equal to this value may be valid or not; the limit + * between valid and invalid numbers is then based on the last + * digit. For instance, if the range for quads is + * [-9223372036854775808..9223372036854775807] and the input base + * is 10, cutoff will be set to 922337203685477580 and cutlim to + * either 7 (neg==0) or 8 (neg==1), meaning that if we have + * accumulated a value > 922337203685477580, or equal but the + * next digit is > 7 (or 8), the number is too big, and we will + * return a range error. + * + * Set 'any' if any `digits' consumed; make it negative to indicate + * overflow. + */ + cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX + : LLONG_MAX; + cutlim = cutoff % base; + cutoff /= base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = neg ? LLONG_MIN : LLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/arm-trusted-firmware/lib/libc/strtoul.c b/arm-trusted-firmware/lib/libc/strtoul.c new file mode 100644 index 0000000..b42fb14 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strtoul.c @@ -0,0 +1,112 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1990, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long strtoul(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long acc; + char c; + unsigned long cutoff; + int neg, any, cutlim; + + /* + * See strtol for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULONG_MAX / base; + cutlim = ULONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/arm-trusted-firmware/lib/libc/strtoull.c b/arm-trusted-firmware/lib/libc/strtoull.c new file mode 100644 index 0000000..2e65a43 --- /dev/null +++ b/arm-trusted-firmware/lib/libc/strtoull.c @@ -0,0 +1,112 @@ +/*- + * SPDX-License-Identifier: BSD-3-Clause + * + * Copyright (c) 1992, 1993 + * The Regents of the University of California. All rights reserved. + * + * Copyright (c) 2011 The FreeBSD Foundation + * All rights reserved. + * Portions of this software were developed by David Chisnall + * under sponsorship from the FreeBSD Foundation. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include + +/* + * Convert a string to an unsigned long long integer. + * + * Assumes that the upper and lower case + * alphabets and digits are each contiguous. + */ +unsigned long long strtoull(const char *nptr, char **endptr, int base) +{ + const char *s; + unsigned long long acc; + char c; + unsigned long long cutoff; + int neg, any, cutlim; + + /* + * See strtoq for comments as to the logic used. + */ + s = nptr; + do { + c = *s++; + } while (isspace((unsigned char)c)); + if (c == '-') { + neg = 1; + c = *s++; + } else { + neg = 0; + if (c == '+') + c = *s++; + } + if ((base == 0 || base == 16) && + c == '0' && (*s == 'x' || *s == 'X') && + ((s[1] >= '0' && s[1] <= '9') || + (s[1] >= 'A' && s[1] <= 'F') || + (s[1] >= 'a' && s[1] <= 'f'))) { + c = s[1]; + s += 2; + base = 16; + } + if (base == 0) + base = c == '0' ? 8 : 10; + acc = any = 0; + + cutoff = ULLONG_MAX / base; + cutlim = ULLONG_MAX % base; + for ( ; ; c = *s++) { + if (c >= '0' && c <= '9') + c -= '0'; + else if (c >= 'A' && c <= 'Z') + c -= 'A' - 10; + else if (c >= 'a' && c <= 'z') + c -= 'a' - 10; + else + break; + if (c >= base) + break; + if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim)) + any = -1; + else { + any = 1; + acc *= base; + acc += c; + } + } + if (any < 0) { + acc = ULLONG_MAX; + } else if (neg) + acc = -acc; + if (endptr != NULL) + *endptr = (char *)(any ? s - 1 : nptr); + return (acc); +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt.c b/arm-trusted-firmware/lib/libfdt/fdt.c new file mode 100644 index 0000000..6cf2fa0 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt.c @@ -0,0 +1,327 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/* + * Minimal sanity check for a read-only tree. fdt_ro_probe_() checks + * that the given buffer contains what appears to be a flattened + * device tree with sane information in its header. + */ +int32_t fdt_ro_probe_(const void *fdt) +{ + uint32_t totalsize = fdt_totalsize(fdt); + + if (can_assume(VALID_DTB)) + return totalsize; + + if (fdt_magic(fdt) == FDT_MAGIC) { + /* Complete tree */ + if (!can_assume(LATEST)) { + if (fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + if (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION) + return -FDT_ERR_BADVERSION; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + /* Unfinished sequential-write blob */ + if (!can_assume(VALID_INPUT) && fdt_size_dt_struct(fdt) == 0) + return -FDT_ERR_BADSTATE; + } else { + return -FDT_ERR_BADMAGIC; + } + + if (totalsize < INT32_MAX) + return totalsize; + else + return -FDT_ERR_TRUNCATED; +} + +static int check_off_(uint32_t hdrsize, uint32_t totalsize, uint32_t off) +{ + return (off >= hdrsize) && (off <= totalsize); +} + +static int check_block_(uint32_t hdrsize, uint32_t totalsize, + uint32_t base, uint32_t size) +{ + if (!check_off_(hdrsize, totalsize, base)) + return 0; /* block start out of bounds */ + if ((base + size) < base) + return 0; /* overflow */ + if (!check_off_(hdrsize, totalsize, base + size)) + return 0; /* block end out of bounds */ + return 1; +} + +size_t fdt_header_size_(uint32_t version) +{ + if (version <= 1) + return FDT_V1_SIZE; + else if (version <= 2) + return FDT_V2_SIZE; + else if (version <= 3) + return FDT_V3_SIZE; + else if (version <= 16) + return FDT_V16_SIZE; + else + return FDT_V17_SIZE; +} + +size_t fdt_header_size(const void *fdt) +{ + return can_assume(LATEST) ? FDT_V17_SIZE : + fdt_header_size_(fdt_version(fdt)); +} + +int fdt_check_header(const void *fdt) +{ + size_t hdrsize; + + if (fdt_magic(fdt) != FDT_MAGIC) + return -FDT_ERR_BADMAGIC; + if (!can_assume(LATEST)) { + if ((fdt_version(fdt) < FDT_FIRST_SUPPORTED_VERSION) + || (fdt_last_comp_version(fdt) > + FDT_LAST_SUPPORTED_VERSION)) + return -FDT_ERR_BADVERSION; + if (fdt_version(fdt) < fdt_last_comp_version(fdt)) + return -FDT_ERR_BADVERSION; + } + hdrsize = fdt_header_size(fdt); + if (!can_assume(VALID_DTB)) { + + if ((fdt_totalsize(fdt) < hdrsize) + || (fdt_totalsize(fdt) > INT_MAX)) + return -FDT_ERR_TRUNCATED; + + /* Bounds check memrsv block */ + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_mem_rsvmap(fdt))) + return -FDT_ERR_TRUNCATED; + } + + if (!can_assume(VALID_DTB)) { + /* Bounds check structure block */ + if (!can_assume(LATEST) && fdt_version(fdt) < 17) { + if (!check_off_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } else { + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_struct(fdt), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_TRUNCATED; + } + + /* Bounds check strings block */ + if (!check_block_(hdrsize, fdt_totalsize(fdt), + fdt_off_dt_strings(fdt), + fdt_size_dt_strings(fdt))) + return -FDT_ERR_TRUNCATED; + } + + return 0; +} + +const void *fdt_offset_ptr(const void *fdt, int offset, unsigned int len) +{ + unsigned int uoffset = offset; + unsigned int absoffset = offset + fdt_off_dt_struct(fdt); + + if (offset < 0) + return NULL; + + if (!can_assume(VALID_INPUT)) + if ((absoffset < uoffset) + || ((absoffset + len) < absoffset) + || (absoffset + len) > fdt_totalsize(fdt)) + return NULL; + + if (can_assume(LATEST) || fdt_version(fdt) >= 0x11) + if (((uoffset + len) < uoffset) + || ((offset + len) > fdt_size_dt_struct(fdt))) + return NULL; + + return fdt_offset_ptr_(fdt, offset); +} + +uint32_t fdt_next_tag(const void *fdt, int startoffset, int *nextoffset) +{ + const fdt32_t *tagp, *lenp; + uint32_t tag; + int offset = startoffset; + const char *p; + + *nextoffset = -FDT_ERR_TRUNCATED; + tagp = fdt_offset_ptr(fdt, offset, FDT_TAGSIZE); + if (!can_assume(VALID_DTB) && !tagp) + return FDT_END; /* premature end */ + tag = fdt32_to_cpu(*tagp); + offset += FDT_TAGSIZE; + + *nextoffset = -FDT_ERR_BADSTRUCTURE; + switch (tag) { + case FDT_BEGIN_NODE: + /* skip name */ + do { + p = fdt_offset_ptr(fdt, offset++, 1); + } while (p && (*p != '\0')); + if (!can_assume(VALID_DTB) && !p) + return FDT_END; /* premature end */ + break; + + case FDT_PROP: + lenp = fdt_offset_ptr(fdt, offset, sizeof(*lenp)); + if (!can_assume(VALID_DTB) && !lenp) + return FDT_END; /* premature end */ + /* skip-name offset, length and value */ + offset += sizeof(struct fdt_property) - FDT_TAGSIZE + + fdt32_to_cpu(*lenp); + if (!can_assume(LATEST) && + fdt_version(fdt) < 0x10 && fdt32_to_cpu(*lenp) >= 8 && + ((offset - fdt32_to_cpu(*lenp)) % 8) != 0) + offset += 4; + break; + + case FDT_END: + case FDT_END_NODE: + case FDT_NOP: + break; + + default: + return FDT_END; + } + + if (!fdt_offset_ptr(fdt, startoffset, offset - startoffset)) + return FDT_END; /* premature end */ + + *nextoffset = FDT_TAGALIGN(offset); + return tag; +} + +int fdt_check_node_offset_(const void *fdt, int offset) +{ + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_BEGIN_NODE) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_check_prop_offset_(const void *fdt, int offset) +{ + if (!can_assume(VALID_INPUT) + && ((offset < 0) || (offset % FDT_TAGSIZE))) + return -FDT_ERR_BADOFFSET; + + if (fdt_next_tag(fdt, offset, &offset) != FDT_PROP) + return -FDT_ERR_BADOFFSET; + + return offset; +} + +int fdt_next_node(const void *fdt, int offset, int *depth) +{ + int nextoffset = 0; + uint32_t tag; + + if (offset >= 0) + if ((nextoffset = fdt_check_node_offset_(fdt, offset)) < 0) + return nextoffset; + + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_PROP: + case FDT_NOP: + break; + + case FDT_BEGIN_NODE: + if (depth) + (*depth)++; + break; + + case FDT_END_NODE: + if (depth && ((--(*depth)) < 0)) + return nextoffset; + break; + + case FDT_END: + if ((nextoffset >= 0) + || ((nextoffset == -FDT_ERR_TRUNCATED) && !depth)) + return -FDT_ERR_NOTFOUND; + else + return nextoffset; + } + } while (tag != FDT_BEGIN_NODE); + + return offset; +} + +int fdt_first_subnode(const void *fdt, int offset) +{ + int depth = 0; + + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth != 1) + return -FDT_ERR_NOTFOUND; + + return offset; +} + +int fdt_next_subnode(const void *fdt, int offset) +{ + int depth = 1; + + /* + * With respect to the parent, the depth of the next subnode will be + * the same as the last. + */ + do { + offset = fdt_next_node(fdt, offset, &depth); + if (offset < 0 || depth < 1) + return -FDT_ERR_NOTFOUND; + } while (depth > 1); + + return offset; +} + +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s) +{ + int len = strlen(s) + 1; + const char *last = strtab + tabsize - len; + const char *p; + + for (p = strtab; p <= last; p++) + if (memcmp(p, s, len) == 0) + return p; + return NULL; +} + +int fdt_move(const void *fdt, void *buf, int bufsize) +{ + if (!can_assume(VALID_INPUT) && bufsize < 0) + return -FDT_ERR_NOSPACE; + + FDT_RO_PROBE(fdt); + + if (fdt_totalsize(fdt) > (unsigned int)bufsize) + return -FDT_ERR_NOSPACE; + + memmove(buf, fdt, fdt_totalsize(fdt)); + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_addresses.c b/arm-trusted-firmware/lib/libfdt/fdt_addresses.c new file mode 100644 index 0000000..9a82cd0 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_addresses.c @@ -0,0 +1,101 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2014 David Gibson + * Copyright (C) 2018 embedded brains GmbH + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_cells(const void *fdt, int nodeoffset, const char *name) +{ + const fdt32_t *c; + uint32_t val; + int len; + + c = fdt_getprop(fdt, nodeoffset, name, &len); + if (!c) + return len; + + if (len != sizeof(*c)) + return -FDT_ERR_BADNCELLS; + + val = fdt32_to_cpu(*c); + if (val > FDT_MAX_NCELLS) + return -FDT_ERR_BADNCELLS; + + return (int)val; +} + +int fdt_address_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#address-cells"); + if (val == 0) + return -FDT_ERR_BADNCELLS; + if (val == -FDT_ERR_NOTFOUND) + return 2; + return val; +} + +int fdt_size_cells(const void *fdt, int nodeoffset) +{ + int val; + + val = fdt_cells(fdt, nodeoffset, "#size-cells"); + if (val == -FDT_ERR_NOTFOUND) + return 1; + return val; +} + +/* This function assumes that [address|size]_cells is 1 or 2 */ +int fdt_appendprop_addrrange(void *fdt, int parent, int nodeoffset, + const char *name, uint64_t addr, uint64_t size) +{ + int addr_cells, size_cells, ret; + uint8_t data[sizeof(fdt64_t) * 2], *prop; + + ret = fdt_address_cells(fdt, parent); + if (ret < 0) + return ret; + addr_cells = ret; + + ret = fdt_size_cells(fdt, parent); + if (ret < 0) + return ret; + size_cells = ret; + + /* check validity of address */ + prop = data; + if (addr_cells == 1) { + if ((addr > UINT32_MAX) || ((UINT32_MAX + 1 - addr) < size)) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)addr); + } else if (addr_cells == 2) { + fdt64_st(prop, addr); + } else { + return -FDT_ERR_BADNCELLS; + } + + /* check validity of size */ + prop += addr_cells * sizeof(fdt32_t); + if (size_cells == 1) { + if (size > UINT32_MAX) + return -FDT_ERR_BADVALUE; + + fdt32_st(prop, (uint32_t)size); + } else if (size_cells == 2) { + fdt64_st(prop, size); + } else { + return -FDT_ERR_BADNCELLS; + } + + return fdt_appendprop(fdt, nodeoffset, name, data, + (addr_cells + size_cells) * sizeof(fdt32_t)); +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c b/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c new file mode 100644 index 0000000..49d54d4 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c @@ -0,0 +1,38 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2012 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_create_empty_tree(void *buf, int bufsize) +{ + int err; + + err = fdt_create(buf, bufsize); + if (err) + return err; + + err = fdt_finish_reservemap(buf); + if (err) + return err; + + err = fdt_begin_node(buf, ""); + if (err) + return err; + + err = fdt_end_node(buf); + if (err) + return err; + + err = fdt_finish(buf); + if (err) + return err; + + return fdt_open_into(buf, buf, bufsize); +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_overlay.c b/arm-trusted-firmware/lib/libfdt/fdt_overlay.c new file mode 100644 index 0000000..d217e79 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_overlay.c @@ -0,0 +1,882 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2016 Free Electrons + * Copyright (C) 2016 NextThing Co. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +/** + * overlay_get_target_phandle - retrieves the target phandle of a fragment + * @fdto: pointer to the device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * + * overlay_get_target_phandle() retrieves the target phandle of an + * overlay fragment when that fragment uses a phandle (target + * property) instead of a path (target-path property). + * + * returns: + * the phandle pointed by the target property + * 0, if the phandle was not found + * -1, if the phandle was malformed + */ +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) +{ + const fdt32_t *val; + int len; + + val = fdt_getprop(fdto, fragment, "target", &len); + if (!val) + return 0; + + if ((len != sizeof(*val)) || (fdt32_to_cpu(*val) == (uint32_t)-1)) + return (uint32_t)-1; + + return fdt32_to_cpu(*val); +} + +/** + * overlay_get_target - retrieves the offset of a fragment's target + * @fdt: Base device tree blob + * @fdto: Device tree overlay blob + * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) + * + * overlay_get_target() retrieves the target offset in the base + * device tree of a fragment, no matter how the actual targeting is + * done (through a phandle or a path) + * + * returns: + * the targeted node offset in the base device tree + * Negative error code on error + */ +static int overlay_get_target(const void *fdt, const void *fdto, + int fragment, char const **pathp) +{ + uint32_t phandle; + const char *path = NULL; + int path_len = 0, ret; + + /* Try first to do a phandle based lookup */ + phandle = overlay_get_target_phandle(fdto, fragment); + if (phandle == (uint32_t)-1) + return -FDT_ERR_BADPHANDLE; + + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle); + + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; + + /* return on error */ + if (ret < 0) + return ret; + + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL; + + return ret; +} + +/** + * overlay_phandle_add_offset - Increases a phandle by an offset + * @fdt: Base device tree blob + * @node: Device tree overlay blob + * @name: Name of the property to modify (phandle or linux,phandle) + * @delta: offset to apply + * + * overlay_phandle_add_offset() increments a node phandle by a given + * offset. + * + * returns: + * 0 on success. + * Negative error code on error + */ +static int overlay_phandle_add_offset(void *fdt, int node, + const char *name, uint32_t delta) +{ + const fdt32_t *val; + uint32_t adj_val; + int len; + + val = fdt_getprop(fdt, node, name, &len); + if (!val) + return len; + + if (len != sizeof(*val)) + return -FDT_ERR_BADPHANDLE; + + adj_val = fdt32_to_cpu(*val); + if ((adj_val + delta) < adj_val) + return -FDT_ERR_NOPHANDLES; + + adj_val += delta; + if (adj_val == (uint32_t)-1) + return -FDT_ERR_NOPHANDLES; + + return fdt_setprop_inplace_u32(fdt, node, name, adj_val); +} + +/** + * overlay_adjust_node_phandles - Offsets the phandles of a node + * @fdto: Device tree overlay blob + * @node: Offset of the node we want to adjust + * @delta: Offset to shift the phandles of + * + * overlay_adjust_node_phandles() adds a constant to all the phandles + * of a given node. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_node_phandles(void *fdto, int node, + uint32_t delta) +{ + int child; + int ret; + + ret = overlay_phandle_add_offset(fdto, node, "phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta); + if (ret && ret != -FDT_ERR_NOTFOUND) + return ret; + + fdt_for_each_subnode(child, fdto, node) { + ret = overlay_adjust_node_phandles(fdto, child, delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_adjust_local_phandles - Adjust the phandles of a whole overlay + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_adjust_local_phandles() adds a constant to all the + * phandles of an overlay. This is mainly use as part of the overlay + * application process, when we want to update all the overlay + * phandles to not conflict with the overlays of the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta) +{ + /* + * Start adjusting the phandles from the overlay root + */ + return overlay_adjust_node_phandles(fdto, 0, delta); +} + +/** + * overlay_update_local_node_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @tree_node: Node offset of the node to operate on + * @fixup_node: Node offset of the matching local fixups node + * @delta: Offset to shift the phandles of + * + * overlay_update_local_nodes_references() update the phandles + * pointing to a node within the device tree overlay by adding a + * constant delta. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_node_references(void *fdto, + int tree_node, + int fixup_node, + uint32_t delta) +{ + int fixup_prop; + int fixup_child; + int ret; + + fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) { + const fdt32_t *fixup_val; + const char *tree_val; + const char *name; + int fixup_len; + int tree_len; + int i; + + fixup_val = fdt_getprop_by_offset(fdto, fixup_prop, + &name, &fixup_len); + if (!fixup_val) + return fixup_len; + + if (fixup_len % sizeof(uint32_t)) + return -FDT_ERR_BADOVERLAY; + fixup_len /= sizeof(uint32_t); + + tree_val = fdt_getprop(fdto, tree_node, name, &tree_len); + if (!tree_val) { + if (tree_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + + return tree_len; + } + + for (i = 0; i < fixup_len; i++) { + fdt32_t adj_val; + uint32_t poffset; + + poffset = fdt32_to_cpu(fixup_val[i]); + + /* + * phandles to fixup can be unaligned. + * + * Use a memcpy for the architectures that do + * not support unaligned accesses. + */ + memcpy(&adj_val, tree_val + poffset, sizeof(adj_val)); + + adj_val = cpu_to_fdt32(fdt32_to_cpu(adj_val) + delta); + + ret = fdt_setprop_inplace_namelen_partial(fdto, + tree_node, + name, + strlen(name), + poffset, + &adj_val, + sizeof(adj_val)); + if (ret == -FDT_ERR_NOSPACE) + return -FDT_ERR_BADOVERLAY; + + if (ret) + return ret; + } + } + + fdt_for_each_subnode(fixup_child, fdto, fixup_node) { + const char *fixup_child_name = fdt_get_name(fdto, fixup_child, + NULL); + int tree_child; + + tree_child = fdt_subnode_offset(fdto, tree_node, + fixup_child_name); + if (tree_child == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (tree_child < 0) + return tree_child; + + ret = overlay_update_local_node_references(fdto, + tree_child, + fixup_child, + delta); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_update_local_references - Adjust the overlay references + * @fdto: Device tree overlay blob + * @delta: Offset to shift the phandles of + * + * overlay_update_local_references() update all the phandles pointing + * to a node within the device tree overlay by adding a constant + * delta to not conflict with the base overlay. + * + * This is mainly used as part of a device tree application process, + * where you want the device tree overlays phandles to not conflict + * with the ones from the base device tree before merging them. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_update_local_references(void *fdto, uint32_t delta) +{ + int fixups; + + fixups = fdt_path_offset(fdto, "/__local_fixups__"); + if (fixups < 0) { + /* There's no local phandles to adjust, bail out */ + if (fixups == -FDT_ERR_NOTFOUND) + return 0; + + return fixups; + } + + /* + * Update our local references from the root of the tree + */ + return overlay_update_local_node_references(fdto, 0, fixups, + delta); +} + +/** + * overlay_fixup_one_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @path: Path to a node holding a phandle in the overlay + * @path_len: number of path characters to consider + * @name: Name of the property holding the phandle reference in the overlay + * @name_len: number of name characters to consider + * @poffset: Offset within the overlay property where the phandle is stored + * @label: Label of the node referenced by the phandle + * + * overlay_fixup_one_phandle() resolves an overlay phandle pointing to + * a node in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_one_phandle(void *fdt, void *fdto, + int symbols_off, + const char *path, uint32_t path_len, + const char *name, uint32_t name_len, + int poffset, const char *label) +{ + const char *symbol_path; + uint32_t phandle; + fdt32_t phandle_prop; + int symbol_off, fixup_off; + int prop_len; + + if (symbols_off < 0) + return symbols_off; + + symbol_path = fdt_getprop(fdt, symbols_off, label, + &prop_len); + if (!symbol_path) + return prop_len; + + symbol_off = fdt_path_offset(fdt, symbol_path); + if (symbol_off < 0) + return symbol_off; + + phandle = fdt_get_phandle(fdt, symbol_off); + if (!phandle) + return -FDT_ERR_NOTFOUND; + + fixup_off = fdt_path_offset_namelen(fdto, path, path_len); + if (fixup_off == -FDT_ERR_NOTFOUND) + return -FDT_ERR_BADOVERLAY; + if (fixup_off < 0) + return fixup_off; + + phandle_prop = cpu_to_fdt32(phandle); + return fdt_setprop_inplace_namelen_partial(fdto, fixup_off, + name, name_len, poffset, + &phandle_prop, + sizeof(phandle_prop)); +}; + +/** + * overlay_fixup_phandle - Set an overlay phandle to the base one + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * @symbols_off: Node offset of the symbols node in the base device tree + * @property: Property offset in the overlay holding the list of fixups + * + * overlay_fixup_phandle() resolves all the overlay phandles pointed + * to in a __fixups__ property, and updates them to match the phandles + * in use in the base device tree. + * + * This is part of the device tree overlay application process, when + * you want all the phandles in the overlay to point to the actual + * base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off, + int property) +{ + const char *value; + const char *label; + int len; + + value = fdt_getprop_by_offset(fdto, property, + &label, &len); + if (!value) { + if (len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + + return len; + } + + do { + const char *path, *name, *fixup_end; + const char *fixup_str = value; + uint32_t path_len, name_len; + uint32_t fixup_len; + char *sep, *endptr; + int poffset, ret; + + fixup_end = memchr(value, '\0', len); + if (!fixup_end) + return -FDT_ERR_BADOVERLAY; + fixup_len = fixup_end - fixup_str; + + len -= fixup_len + 1; + value += fixup_len + 1; + + path = fixup_str; + sep = memchr(fixup_str, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + path_len = sep - path; + if (path_len == (fixup_len - 1)) + return -FDT_ERR_BADOVERLAY; + + fixup_len -= path_len + 1; + name = sep + 1; + sep = memchr(name, ':', fixup_len); + if (!sep || *sep != ':') + return -FDT_ERR_BADOVERLAY; + + name_len = sep - name; + if (!name_len) + return -FDT_ERR_BADOVERLAY; + + poffset = strtoul(sep + 1, &endptr, 10); + if ((*endptr != '\0') || (endptr <= (sep + 1))) + return -FDT_ERR_BADOVERLAY; + + ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off, + path, path_len, name, name_len, + poffset, label); + if (ret) + return ret; + } while (len > 0); + + return 0; +} + +/** + * overlay_fixup_phandles - Resolve the overlay phandles to the base + * device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_fixup_phandles() resolves all the overlay phandles pointing + * to nodes in the base device tree. + * + * This is one of the steps of the device tree overlay application + * process, when you want all the phandles in the overlay to point to + * the actual base dt nodes. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_fixup_phandles(void *fdt, void *fdto) +{ + int fixups_off, symbols_off; + int property; + + /* We can have overlays without any fixups */ + fixups_off = fdt_path_offset(fdto, "/__fixups__"); + if (fixups_off == -FDT_ERR_NOTFOUND) + return 0; /* nothing to do */ + if (fixups_off < 0) + return fixups_off; + + /* And base DTs without symbols */ + symbols_off = fdt_path_offset(fdt, "/__symbols__"); + if ((symbols_off < 0 && (symbols_off != -FDT_ERR_NOTFOUND))) + return symbols_off; + + fdt_for_each_property_offset(property, fdto, fixups_off) { + int ret; + + ret = overlay_fixup_phandle(fdt, fdto, symbols_off, property); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_apply_node - Merges a node into the base device tree + * @fdt: Base Device Tree blob + * @target: Node offset in the base device tree to apply the fragment to + * @fdto: Device tree overlay blob + * @node: Node offset in the overlay holding the changes to merge + * + * overlay_apply_node() merges a node into a target base device tree + * node pointed. + * + * This is part of the final step in the device tree overlay + * application process, when all the phandles have been adjusted and + * resolved and you just have to merge overlay into the base device + * tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_apply_node(void *fdt, int target, + void *fdto, int node) +{ + int property; + int subnode; + + fdt_for_each_property_offset(property, fdto, node) { + const char *name; + const void *prop; + int prop_len; + int ret; + + prop = fdt_getprop_by_offset(fdto, property, &name, + &prop_len); + if (prop_len == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + if (prop_len < 0) + return prop_len; + + ret = fdt_setprop(fdt, target, name, prop, prop_len); + if (ret) + return ret; + } + + fdt_for_each_subnode(subnode, fdto, node) { + const char *name = fdt_get_name(fdto, subnode, NULL); + int nnode; + int ret; + + nnode = fdt_add_subnode(fdt, target, name); + if (nnode == -FDT_ERR_EXISTS) { + nnode = fdt_subnode_offset(fdt, target, name); + if (nnode == -FDT_ERR_NOTFOUND) + return -FDT_ERR_INTERNAL; + } + + if (nnode < 0) + return nnode; + + ret = overlay_apply_node(fdt, nnode, fdto, subnode); + if (ret) + return ret; + } + + return 0; +} + +/** + * overlay_merge - Merge an overlay into its base device tree + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_merge() merges an overlay into its base device tree. + * + * This is the next to last step in the device tree overlay application + * process, when all the phandles have been adjusted and resolved and + * you just have to merge overlay into the base device tree. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_merge(void *fdt, void *fdto) +{ + int fragment; + + fdt_for_each_subnode(fragment, fdto, 0) { + int overlay; + int target; + int ret; + + /* + * Each fragments will have an __overlay__ node. If + * they don't, it's not supposed to be merged + */ + overlay = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (overlay == -FDT_ERR_NOTFOUND) + continue; + + if (overlay < 0) + return overlay; + + target = overlay_get_target(fdt, fdto, fragment, NULL); + if (target < 0) + return target; + + ret = overlay_apply_node(fdt, target, fdto, overlay); + if (ret) + return ret; + } + + return 0; +} + +static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * overlay_symbol_update - Update the symbols of base tree after a merge + * @fdt: Base Device Tree blob + * @fdto: Device tree overlay blob + * + * overlay_symbol_update() updates the symbols of the base tree with the + * symbols of the applied overlay + * + * This is the last step in the device tree overlay application + * process, allowing the reference of overlay symbols by subsequent + * overlay operations. + * + * returns: + * 0 on success + * Negative error code on failure + */ +static int overlay_symbol_update(void *fdt, void *fdto) +{ + int root_sym, ov_sym, prop, path_len, fragment, target; + int len, frag_name_len, ret, rel_path_len; + const char *s, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* iterate over each overlay symbol */ + fdt_for_each_property_offset(prop, fdto, ov_sym) { + path = fdt_getprop_by_offset(fdto, prop, &name, &path_len); + if (!path) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) > len && (memcmp(s, "/__overlay__/", len) == 0)) { + /* //__overlay__/ */ + rel_path = s + len; + rel_path_len = e - rel_path - 1; + } else if ((e - s) == len + && (memcmp(s, "/__overlay__", len - 1) == 0)) { + /* //__overlay__ */ + rel_path = ""; + rel_path_len = 0; + } else { + /* Symbol refers to something that won't end + * up in the target tree */ + continue; + } + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + +int fdt_overlay_apply(void *fdt, void *fdto) +{ + uint32_t delta; + int ret; + + FDT_RO_PROBE(fdt); + FDT_RO_PROBE(fdto); + + ret = fdt_find_max_phandle(fdt, &delta); + if (ret) + goto err; + + ret = overlay_adjust_local_phandles(fdto, delta); + if (ret) + goto err; + + ret = overlay_update_local_references(fdto, delta); + if (ret) + goto err; + + ret = overlay_fixup_phandles(fdt, fdto); + if (ret) + goto err; + + ret = overlay_merge(fdt, fdto); + if (ret) + goto err; + + ret = overlay_symbol_update(fdt, fdto); + if (ret) + goto err; + + /* + * The overlay has been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + return 0; + +err: + /* + * The overlay might have been damaged, erase its magic. + */ + fdt_set_magic(fdto, ~0); + + /* + * The base device tree might have been damaged, erase its + * magic. + */ + fdt_set_magic(fdt, ~0); + + return ret; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_ro.c b/arm-trusted-firmware/lib/libfdt/fdt_ro.c new file mode 100644 index 0000000..91cc6fe --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_ro.c @@ -0,0 +1,859 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_nodename_eq_(const void *fdt, int offset, + const char *s, int len) +{ + int olen; + const char *p = fdt_get_name(fdt, offset, &olen); + + if (!p || olen < len) + /* short match */ + return 0; + + if (memcmp(p, s, len) != 0) + return 0; + + if (p[len] == '\0') + return 1; + else if (!memchr(s, '@', len) && (p[len] == '@')) + return 1; + else + return 0; +} + +const char *fdt_get_string(const void *fdt, int stroffset, int *lenp) +{ + int32_t totalsize; + uint32_t absoffset; + size_t len; + int err; + const char *s, *n; + + if (can_assume(VALID_INPUT)) { + s = (const char *)fdt + fdt_off_dt_strings(fdt) + stroffset; + + if (lenp) + *lenp = strlen(s); + return s; + } + totalsize = fdt_ro_probe_(fdt); + err = totalsize; + if (totalsize < 0) + goto fail; + + err = -FDT_ERR_BADOFFSET; + absoffset = stroffset + fdt_off_dt_strings(fdt); + if (absoffset >= (unsigned)totalsize) + goto fail; + len = totalsize - absoffset; + + if (fdt_magic(fdt) == FDT_MAGIC) { + if (stroffset < 0) + goto fail; + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + if ((unsigned)stroffset >= fdt_size_dt_strings(fdt)) + goto fail; + if ((fdt_size_dt_strings(fdt) - stroffset) < len) + len = fdt_size_dt_strings(fdt) - stroffset; + } + } else if (fdt_magic(fdt) == FDT_SW_MAGIC) { + unsigned int sw_stroffset = -stroffset; + + if ((stroffset >= 0) || + (sw_stroffset > fdt_size_dt_strings(fdt))) + goto fail; + if (sw_stroffset < len) + len = sw_stroffset; + } else { + err = -FDT_ERR_INTERNAL; + goto fail; + } + + s = (const char *)fdt + absoffset; + n = memchr(s, '\0', len); + if (!n) { + /* missing terminating NULL */ + err = -FDT_ERR_TRUNCATED; + goto fail; + } + + if (lenp) + *lenp = n - s; + return s; + +fail: + if (lenp) + *lenp = err; + return NULL; +} + +const char *fdt_string(const void *fdt, int stroffset) +{ + return fdt_get_string(fdt, stroffset, NULL); +} + +static int fdt_string_eq_(const void *fdt, int stroffset, + const char *s, int len) +{ + int slen; + const char *p = fdt_get_string(fdt, stroffset, &slen); + + return p && (slen == len) && (memcmp(p, s, len) == 0); +} + +int fdt_find_max_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max = 0; + int offset = -1; + + while (true) { + uint32_t value; + + offset = fdt_next_node(fdt, offset, NULL); + if (offset < 0) { + if (offset == -FDT_ERR_NOTFOUND) + break; + + return offset; + } + + value = fdt_get_phandle(fdt, offset); + + if (value > max) + max = value; + } + + if (phandle) + *phandle = max; + + return 0; +} + +int fdt_generate_phandle(const void *fdt, uint32_t *phandle) +{ + uint32_t max; + int err; + + err = fdt_find_max_phandle(fdt, &max); + if (err < 0) + return err; + + if (max == FDT_MAX_PHANDLE) + return -FDT_ERR_NOPHANDLES; + + if (phandle) + *phandle = max + 1; + + return 0; +} + +static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n) +{ + unsigned int offset = n * sizeof(struct fdt_reserve_entry); + unsigned int absoffset = fdt_off_mem_rsvmap(fdt) + offset; + + if (!can_assume(VALID_INPUT)) { + if (absoffset < fdt_off_mem_rsvmap(fdt)) + return NULL; + if (absoffset > fdt_totalsize(fdt) - + sizeof(struct fdt_reserve_entry)) + return NULL; + } + return fdt_mem_rsv_(fdt, n); +} + +int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size) +{ + const struct fdt_reserve_entry *re; + + FDT_RO_PROBE(fdt); + re = fdt_mem_rsv(fdt, n); + if (!can_assume(VALID_INPUT) && !re) + return -FDT_ERR_BADOFFSET; + + *address = fdt64_ld(&re->address); + *size = fdt64_ld(&re->size); + return 0; +} + +int fdt_num_mem_rsv(const void *fdt) +{ + int i; + const struct fdt_reserve_entry *re; + + for (i = 0; (re = fdt_mem_rsv(fdt, i)) != NULL; i++) { + if (fdt64_ld(&re->size) == 0) + return i; + } + return -FDT_ERR_TRUNCATED; +} + +static int nextprop_(const void *fdt, int offset) +{ + uint32_t tag; + int nextoffset; + + do { + tag = fdt_next_tag(fdt, offset, &nextoffset); + + switch (tag) { + case FDT_END: + if (nextoffset >= 0) + return -FDT_ERR_BADSTRUCTURE; + else + return nextoffset; + + case FDT_PROP: + return offset; + } + offset = nextoffset; + } while (tag == FDT_NOP); + + return -FDT_ERR_NOTFOUND; +} + +int fdt_subnode_offset_namelen(const void *fdt, int offset, + const char *name, int namelen) +{ + int depth; + + FDT_RO_PROBE(fdt); + + for (depth = 0; + (offset >= 0) && (depth >= 0); + offset = fdt_next_node(fdt, offset, &depth)) + if ((depth == 1) + && fdt_nodename_eq_(fdt, offset, name, namelen)) + return offset; + + if (depth < 0) + return -FDT_ERR_NOTFOUND; + return offset; /* error */ +} + +int fdt_subnode_offset(const void *fdt, int parentoffset, + const char *name) +{ + return fdt_subnode_offset_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen) +{ + const char *end = path + namelen; + const char *p = path; + int offset = 0; + + FDT_RO_PROBE(fdt); + + /* see if we have an alias */ + if (*path != '/') { + const char *q = memchr(path, '/', end - p); + + if (!q) + q = end; + + p = fdt_get_alias_namelen(fdt, p, q - p); + if (!p) + return -FDT_ERR_BADPATH; + offset = fdt_path_offset(fdt, p); + + p = q; + } + + while (p < end) { + const char *q; + + while (*p == '/') { + p++; + if (p == end) + return offset; + } + q = memchr(p, '/', end - p); + if (! q) + q = end; + + offset = fdt_subnode_offset_namelen(fdt, offset, p, q-p); + if (offset < 0) + return offset; + + p = q; + } + + return offset; +} + +int fdt_path_offset(const void *fdt, const char *path) +{ + return fdt_path_offset_namelen(fdt, path, strlen(path)); +} + +const char *fdt_get_name(const void *fdt, int nodeoffset, int *len) +{ + const struct fdt_node_header *nh = fdt_offset_ptr_(fdt, nodeoffset); + const char *nameptr; + int err; + + if (((err = fdt_ro_probe_(fdt)) < 0) + || ((err = fdt_check_node_offset_(fdt, nodeoffset)) < 0)) + goto fail; + + nameptr = nh->name; + + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + /* + * For old FDT versions, match the naming conventions of V16: + * give only the leaf name (after all /). The actual tree + * contents are loosely checked. + */ + const char *leaf; + leaf = strrchr(nameptr, '/'); + if (leaf == NULL) { + err = -FDT_ERR_BADSTRUCTURE; + goto fail; + } + nameptr = leaf+1; + } + + if (len) + *len = strlen(nameptr); + + return nameptr; + + fail: + if (len) + *len = err; + return NULL; +} + +int fdt_first_property_offset(const void *fdt, int nodeoffset) +{ + int offset; + + if ((offset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +int fdt_next_property_offset(const void *fdt, int offset) +{ + if ((offset = fdt_check_prop_offset_(fdt, offset)) < 0) + return offset; + + return nextprop_(fdt, offset); +} + +static const struct fdt_property *fdt_get_property_by_offset_(const void *fdt, + int offset, + int *lenp) +{ + int err; + const struct fdt_property *prop; + + if (!can_assume(VALID_INPUT) && + (err = fdt_check_prop_offset_(fdt, offset)) < 0) { + if (lenp) + *lenp = err; + return NULL; + } + + prop = fdt_offset_ptr_(fdt, offset); + + if (lenp) + *lenp = fdt32_ld(&prop->len); + + return prop; +} + +const struct fdt_property *fdt_get_property_by_offset(const void *fdt, + int offset, + int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_by_offset_(fdt, offset, lenp); +} + +static const struct fdt_property *fdt_get_property_namelen_(const void *fdt, + int offset, + const char *name, + int namelen, + int *lenp, + int *poffset) +{ + for (offset = fdt_first_property_offset(fdt, offset); + (offset >= 0); + (offset = fdt_next_property_offset(fdt, offset))) { + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!can_assume(LIBFDT_FLAWLESS) && !prop) { + offset = -FDT_ERR_INTERNAL; + break; + } + if (fdt_string_eq_(fdt, fdt32_ld(&prop->nameoff), + name, namelen)) { + if (poffset) + *poffset = offset; + return prop; + } + } + + if (lenp) + *lenp = offset; + return NULL; +} + + +const struct fdt_property *fdt_get_property_namelen(const void *fdt, + int offset, + const char *name, + int namelen, int *lenp) +{ + /* Prior to version 16, properties may need realignment + * and this API does not work. fdt_getprop_*() will, however. */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10) { + if (lenp) + *lenp = -FDT_ERR_BADVERSION; + return NULL; + } + + return fdt_get_property_namelen_(fdt, offset, name, namelen, lenp, + NULL); +} + + +const struct fdt_property *fdt_get_property(const void *fdt, + int nodeoffset, + const char *name, int *lenp) +{ + return fdt_get_property_namelen(fdt, nodeoffset, name, + strlen(name), lenp); +} + +const void *fdt_getprop_namelen(const void *fdt, int nodeoffset, + const char *name, int namelen, int *lenp) +{ + int poffset; + const struct fdt_property *prop; + + prop = fdt_get_property_namelen_(fdt, nodeoffset, name, namelen, lenp, + &poffset); + if (!prop) + return NULL; + + /* Handle realignment */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (poffset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop_by_offset(const void *fdt, int offset, + const char **namep, int *lenp) +{ + const struct fdt_property *prop; + + prop = fdt_get_property_by_offset_(fdt, offset, lenp); + if (!prop) + return NULL; + if (namep) { + const char *name; + int namelen; + + if (!can_assume(VALID_INPUT)) { + name = fdt_get_string(fdt, fdt32_ld(&prop->nameoff), + &namelen); + if (!name) { + if (lenp) + *lenp = namelen; + return NULL; + } + *namep = name; + } else { + *namep = fdt_string(fdt, fdt32_ld(&prop->nameoff)); + } + } + + /* Handle realignment */ + if (!can_assume(LATEST) && fdt_version(fdt) < 0x10 && + (offset + sizeof(*prop)) % 8 && fdt32_ld(&prop->len) >= 8) + return prop->data + 4; + return prop->data; +} + +const void *fdt_getprop(const void *fdt, int nodeoffset, + const char *name, int *lenp) +{ + return fdt_getprop_namelen(fdt, nodeoffset, name, strlen(name), lenp); +} + +uint32_t fdt_get_phandle(const void *fdt, int nodeoffset) +{ + const fdt32_t *php; + int len; + + /* FIXME: This is a bit sub-optimal, since we potentially scan + * over all the properties twice. */ + php = fdt_getprop(fdt, nodeoffset, "phandle", &len); + if (!php || (len != sizeof(*php))) { + php = fdt_getprop(fdt, nodeoffset, "linux,phandle", &len); + if (!php || (len != sizeof(*php))) + return 0; + } + + return fdt32_ld(php); +} + +const char *fdt_get_alias_namelen(const void *fdt, + const char *name, int namelen) +{ + int aliasoffset; + + aliasoffset = fdt_path_offset(fdt, "/aliases"); + if (aliasoffset < 0) + return NULL; + + return fdt_getprop_namelen(fdt, aliasoffset, name, namelen, NULL); +} + +const char *fdt_get_alias(const void *fdt, const char *name) +{ + return fdt_get_alias_namelen(fdt, name, strlen(name)); +} + +int fdt_get_path(const void *fdt, int nodeoffset, char *buf, int buflen) +{ + int pdepth = 0, p = 0; + int offset, depth, namelen; + const char *name; + + FDT_RO_PROBE(fdt); + + if (buflen < 2) + return -FDT_ERR_NOSPACE; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + while (pdepth > depth) { + do { + p--; + } while (buf[p-1] != '/'); + pdepth--; + } + + if (pdepth >= depth) { + name = fdt_get_name(fdt, offset, &namelen); + if (!name) + return namelen; + if ((p + namelen + 1) <= buflen) { + memcpy(buf + p, name, namelen); + p += namelen; + buf[p++] = '/'; + pdepth++; + } + } + + if (offset == nodeoffset) { + if (pdepth < (depth + 1)) + return -FDT_ERR_NOSPACE; + + if (p > 1) /* special case so that root path is "/", not "" */ + p--; + buf[p] = '\0'; + return 0; + } + } + + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + + return offset; /* error from fdt_next_node() */ +} + +int fdt_supernode_atdepth_offset(const void *fdt, int nodeoffset, + int supernodedepth, int *nodedepth) +{ + int offset, depth; + int supernodeoffset = -FDT_ERR_INTERNAL; + + FDT_RO_PROBE(fdt); + + if (supernodedepth < 0) + return -FDT_ERR_NOTFOUND; + + for (offset = 0, depth = 0; + (offset >= 0) && (offset <= nodeoffset); + offset = fdt_next_node(fdt, offset, &depth)) { + if (depth == supernodedepth) + supernodeoffset = offset; + + if (offset == nodeoffset) { + if (nodedepth) + *nodedepth = depth; + + if (supernodedepth > depth) + return -FDT_ERR_NOTFOUND; + else + return supernodeoffset; + } + } + + if (!can_assume(VALID_INPUT)) { + if ((offset == -FDT_ERR_NOTFOUND) || (offset >= 0)) + return -FDT_ERR_BADOFFSET; + else if (offset == -FDT_ERR_BADOFFSET) + return -FDT_ERR_BADSTRUCTURE; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_depth(const void *fdt, int nodeoffset) +{ + int nodedepth; + int err; + + err = fdt_supernode_atdepth_offset(fdt, nodeoffset, 0, &nodedepth); + if (err) + return (can_assume(LIBFDT_FLAWLESS) || err < 0) ? err : + -FDT_ERR_INTERNAL; + return nodedepth; +} + +int fdt_parent_offset(const void *fdt, int nodeoffset) +{ + int nodedepth = fdt_node_depth(fdt, nodeoffset); + + if (nodedepth < 0) + return nodedepth; + return fdt_supernode_atdepth_offset(fdt, nodeoffset, + nodedepth - 1, NULL); +} + +int fdt_node_offset_by_prop_value(const void *fdt, int startoffset, + const char *propname, + const void *propval, int proplen) +{ + int offset; + const void *val; + int len; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_getprop(), then if that didn't + * find what we want, we scan over them again making our way + * to the next node. Still it's the easiest to implement + * approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + val = fdt_getprop(fdt, offset, propname, &len); + if (val && (len == proplen) + && (memcmp(val, propval, len) == 0)) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_node_offset_by_phandle(const void *fdt, uint32_t phandle) +{ + int offset; + + if ((phandle == 0) || (phandle == ~0U)) + return -FDT_ERR_BADPHANDLE; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we + * potentially scan each property of a node in + * fdt_get_phandle(), then if that didn't find what + * we want, we scan over them again making our way to the next + * node. Still it's the easiest to implement approach; + * performance can come later. */ + for (offset = fdt_next_node(fdt, -1, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + if (fdt_get_phandle(fdt, offset) == phandle) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} + +int fdt_stringlist_contains(const char *strlist, int listlen, const char *str) +{ + int len = strlen(str); + const char *p; + + while (listlen >= len) { + if (memcmp(str, strlist, len+1) == 0) + return 1; + p = memchr(strlist, '\0', listlen); + if (!p) + return 0; /* malformed strlist.. */ + listlen -= (p-strlist) + 1; + strlist = p + 1; + } + return 0; +} + +int fdt_stringlist_count(const void *fdt, int nodeoffset, const char *property) +{ + const char *list, *end; + int length, count = 0; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + list += length; + count++; + } + + return count; +} + +int fdt_stringlist_search(const void *fdt, int nodeoffset, const char *property, + const char *string) +{ + int length, len, idx = 0; + const char *list, *end; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) + return length; + + len = strlen(string) + 1; + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) + return -FDT_ERR_BADVALUE; + + if (length == len && memcmp(list, string, length) == 0) + return idx; + + list += length; + idx++; + } + + return -FDT_ERR_NOTFOUND; +} + +const char *fdt_stringlist_get(const void *fdt, int nodeoffset, + const char *property, int idx, + int *lenp) +{ + const char *list, *end; + int length; + + list = fdt_getprop(fdt, nodeoffset, property, &length); + if (!list) { + if (lenp) + *lenp = length; + + return NULL; + } + + end = list + length; + + while (list < end) { + length = strnlen(list, end - list) + 1; + + /* Abort if the last string isn't properly NUL-terminated. */ + if (list + length > end) { + if (lenp) + *lenp = -FDT_ERR_BADVALUE; + + return NULL; + } + + if (idx == 0) { + if (lenp) + *lenp = length - 1; + + return list; + } + + list += length; + idx--; + } + + if (lenp) + *lenp = -FDT_ERR_NOTFOUND; + + return NULL; +} + +int fdt_node_check_compatible(const void *fdt, int nodeoffset, + const char *compatible) +{ + const void *prop; + int len; + + prop = fdt_getprop(fdt, nodeoffset, "compatible", &len); + if (!prop) + return len; + + return !fdt_stringlist_contains(prop, len, compatible); +} + +int fdt_node_offset_by_compatible(const void *fdt, int startoffset, + const char *compatible) +{ + int offset, err; + + FDT_RO_PROBE(fdt); + + /* FIXME: The algorithm here is pretty horrible: we scan each + * property of a node in fdt_node_check_compatible(), then if + * that didn't find what we want, we scan over them again + * making our way to the next node. Still it's the easiest to + * implement approach; performance can come later. */ + for (offset = fdt_next_node(fdt, startoffset, NULL); + offset >= 0; + offset = fdt_next_node(fdt, offset, NULL)) { + err = fdt_node_check_compatible(fdt, offset, compatible); + if ((err < 0) && (err != -FDT_ERR_NOTFOUND)) + return err; + else if (err == 0) + return offset; + } + + return offset; /* error from fdt_next_node() */ +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_rw.c b/arm-trusted-firmware/lib/libfdt/fdt_rw.c new file mode 100644 index 0000000..68887b9 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_rw.c @@ -0,0 +1,492 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_blocks_misordered_(const void *fdt, + int mem_rsv_size, int struct_size) +{ + return (fdt_off_mem_rsvmap(fdt) < FDT_ALIGN(sizeof(struct fdt_header), 8)) + || (fdt_off_dt_struct(fdt) < + (fdt_off_mem_rsvmap(fdt) + mem_rsv_size)) + || (fdt_off_dt_strings(fdt) < + (fdt_off_dt_struct(fdt) + struct_size)) + || (fdt_totalsize(fdt) < + (fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt))); +} + +static int fdt_rw_probe_(void *fdt) +{ + if (can_assume(VALID_DTB)) + return 0; + FDT_RO_PROBE(fdt); + + if (!can_assume(LATEST) && fdt_version(fdt) < 17) + return -FDT_ERR_BADVERSION; + if (fdt_blocks_misordered_(fdt, sizeof(struct fdt_reserve_entry), + fdt_size_dt_struct(fdt))) + return -FDT_ERR_BADLAYOUT; + if (!can_assume(LATEST) && fdt_version(fdt) > 17) + fdt_set_version(fdt, 17); + + return 0; +} + +#define FDT_RW_PROBE(fdt) \ + { \ + int err_; \ + if ((err_ = fdt_rw_probe_(fdt)) != 0) \ + return err_; \ + } + +static inline unsigned int fdt_data_size_(void *fdt) +{ + return fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); +} + +static int fdt_splice_(void *fdt, void *splicepoint, int oldlen, int newlen) +{ + char *p = splicepoint; + unsigned int dsize = fdt_data_size_(fdt); + size_t soff = p - (char *)fdt; + + if ((oldlen < 0) || (soff + oldlen < soff) || (soff + oldlen > dsize)) + return -FDT_ERR_BADOFFSET; + if ((p < (char *)fdt) || (dsize + newlen < (unsigned)oldlen)) + return -FDT_ERR_BADOFFSET; + if (dsize - oldlen + newlen > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + memmove(p + newlen, p + oldlen, ((char *)fdt + dsize) - (p + oldlen)); + return 0; +} + +static int fdt_splice_mem_rsv_(void *fdt, struct fdt_reserve_entry *p, + int oldn, int newn) +{ + int delta = (newn - oldn) * sizeof(*p); + int err; + err = fdt_splice_(fdt, p, oldn * sizeof(*p), newn * sizeof(*p)); + if (err) + return err; + fdt_set_off_dt_struct(fdt, fdt_off_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +static int fdt_splice_struct_(void *fdt, void *p, + int oldlen, int newlen) +{ + int delta = newlen - oldlen; + int err; + + if ((err = fdt_splice_(fdt, p, oldlen, newlen))) + return err; + + fdt_set_size_dt_struct(fdt, fdt_size_dt_struct(fdt) + delta); + fdt_set_off_dt_strings(fdt, fdt_off_dt_strings(fdt) + delta); + return 0; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int newlen = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) - newlen); +} + +static int fdt_splice_string_(void *fdt, int newlen) +{ + void *p = (char *)fdt + + fdt_off_dt_strings(fdt) + fdt_size_dt_strings(fdt); + int err; + + if ((err = fdt_splice_(fdt, p, 0, newlen))) + return err; + + fdt_set_size_dt_strings(fdt, fdt_size_dt_strings(fdt) + newlen); + return 0; +} + +/** + * fdt_find_add_string_() - Find or allocate a string + * + * @fdt: pointer to the device tree to check/adjust + * @s: string to find/add + * @allocated: Set to 0 if the string was found, 1 if not found and so + * allocated. Ignored if can_assume(NO_ROLLBACK) + * @return offset of string in the string table (whether found or added) + */ +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_off_dt_strings(fdt); + const char *p; + char *new; + int len = strlen(s) + 1; + int err; + + if (!can_assume(NO_ROLLBACK)) + *allocated = 0; + + p = fdt_find_string_(strtab, fdt_size_dt_strings(fdt), s); + if (p) + /* found it */ + return (p - strtab); + + new = strtab + fdt_size_dt_strings(fdt); + err = fdt_splice_string_(fdt, len); + if (err) + return err; + + if (!can_assume(NO_ROLLBACK)) + *allocated = 1; + + memcpy(new, s, len); + return (new - strtab); +} + +int fdt_add_mem_rsv(void *fdt, uint64_t address, uint64_t size) +{ + struct fdt_reserve_entry *re; + int err; + + FDT_RW_PROBE(fdt); + + re = fdt_mem_rsv_w_(fdt, fdt_num_mem_rsv(fdt)); + err = fdt_splice_mem_rsv_(fdt, re, 0, 1); + if (err) + return err; + + re->address = cpu_to_fdt64(address); + re->size = cpu_to_fdt64(size); + return 0; +} + +int fdt_del_mem_rsv(void *fdt, int n) +{ + struct fdt_reserve_entry *re = fdt_mem_rsv_w_(fdt, n); + + FDT_RW_PROBE(fdt); + + if (n >= fdt_num_mem_rsv(fdt)) + return -FDT_ERR_NOTFOUND; + + return fdt_splice_mem_rsv_(fdt, re, 1, 0); +} + +static int fdt_resize_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int oldlen; + int err; + + *prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (!*prop) + return oldlen; + + if ((err = fdt_splice_struct_(fdt, (*prop)->data, FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(len)))) + return err; + + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +static int fdt_add_property_(void *fdt, int nodeoffset, const char *name, + int len, struct fdt_property **prop) +{ + int proplen; + int nextoffset; + int namestroff; + int err; + int allocated; + + if ((nextoffset = fdt_check_node_offset_(fdt, nodeoffset)) < 0) + return nextoffset; + + namestroff = fdt_find_add_string_(fdt, name, &allocated); + if (namestroff < 0) + return namestroff; + + *prop = fdt_offset_ptr_w_(fdt, nextoffset); + proplen = sizeof(**prop) + FDT_TAGALIGN(len); + + err = fdt_splice_struct_(fdt, *prop, 0, proplen); + if (err) { + /* Delete the string if we failed to add it */ + if (!can_assume(NO_ROLLBACK) && allocated) + fdt_del_last_string_(fdt, name); + return err; + } + + (*prop)->tag = cpu_to_fdt32(FDT_PROP); + (*prop)->nameoff = cpu_to_fdt32(namestroff); + (*prop)->len = cpu_to_fdt32(len); + return 0; +} + +int fdt_set_name(void *fdt, int nodeoffset, const char *name) +{ + char *namep; + int oldlen, newlen; + int err; + + FDT_RW_PROBE(fdt); + + namep = (char *)(uintptr_t)fdt_get_name(fdt, nodeoffset, &oldlen); + if (!namep) + return oldlen; + + newlen = strlen(name); + + err = fdt_splice_struct_(fdt, namep, FDT_TAGALIGN(oldlen+1), + FDT_TAGALIGN(newlen+1)); + if (err) + return err; + + memcpy(namep, name, newlen+1); + return 0; +} + +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) +{ + struct fdt_property *prop; + int err; + + FDT_RW_PROBE(fdt); + + err = fdt_resize_property_(fdt, nodeoffset, name, len, &prop); + if (err == -FDT_ERR_NOTFOUND) + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + + *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + + if (len) + memcpy(prop_data, val, len); + return 0; +} + +int fdt_appendprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + struct fdt_property *prop; + int err, oldlen, newlen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &oldlen); + if (prop) { + newlen = len + oldlen; + err = fdt_splice_struct_(fdt, prop->data, + FDT_TAGALIGN(oldlen), + FDT_TAGALIGN(newlen)); + if (err) + return err; + prop->len = cpu_to_fdt32(newlen); + memcpy(prop->data + oldlen, val, len); + } else { + err = fdt_add_property_(fdt, nodeoffset, name, len, &prop); + if (err) + return err; + memcpy(prop->data, val, len); + } + return 0; +} + +int fdt_delprop(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len, proplen; + + FDT_RW_PROBE(fdt); + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + proplen = sizeof(*prop) + FDT_TAGALIGN(len); + return fdt_splice_struct_(fdt, prop, proplen, 0); +} + +int fdt_add_subnode_namelen(void *fdt, int parentoffset, + const char *name, int namelen) +{ + struct fdt_node_header *nh; + int offset, nextoffset; + int nodelen; + int err; + uint32_t tag; + fdt32_t *endtag; + + FDT_RW_PROBE(fdt); + + offset = fdt_subnode_offset_namelen(fdt, parentoffset, name, namelen); + if (offset >= 0) + return -FDT_ERR_EXISTS; + else if (offset != -FDT_ERR_NOTFOUND) + return offset; + + /* Try to place the new node after the parent's properties */ + fdt_next_tag(fdt, parentoffset, &nextoffset); /* skip the BEGIN_NODE */ + do { + offset = nextoffset; + tag = fdt_next_tag(fdt, offset, &nextoffset); + } while ((tag == FDT_PROP) || (tag == FDT_NOP)); + + nh = fdt_offset_ptr_w_(fdt, offset); + nodelen = sizeof(*nh) + FDT_TAGALIGN(namelen+1) + FDT_TAGSIZE; + + err = fdt_splice_struct_(fdt, nh, 0, nodelen); + if (err) + return err; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memset(nh->name, 0, FDT_TAGALIGN(namelen+1)); + memcpy(nh->name, name, namelen); + endtag = (fdt32_t *)((char *)nh + nodelen - FDT_TAGSIZE); + *endtag = cpu_to_fdt32(FDT_END_NODE); + + return offset; +} + +int fdt_add_subnode(void *fdt, int parentoffset, const char *name) +{ + return fdt_add_subnode_namelen(fdt, parentoffset, name, strlen(name)); +} + +int fdt_del_node(void *fdt, int nodeoffset) +{ + int endoffset; + + FDT_RW_PROBE(fdt); + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + return fdt_splice_struct_(fdt, fdt_offset_ptr_w_(fdt, nodeoffset), + endoffset - nodeoffset, 0); +} + +static void fdt_packblocks_(const char *old, char *new, + int mem_rsv_size, int struct_size) +{ + int mem_rsv_off, struct_off, strings_off; + + mem_rsv_off = FDT_ALIGN(sizeof(struct fdt_header), 8); + struct_off = mem_rsv_off + mem_rsv_size; + strings_off = struct_off + struct_size; + + memmove(new + mem_rsv_off, old + fdt_off_mem_rsvmap(old), mem_rsv_size); + fdt_set_off_mem_rsvmap(new, mem_rsv_off); + + memmove(new + struct_off, old + fdt_off_dt_struct(old), struct_size); + fdt_set_off_dt_struct(new, struct_off); + fdt_set_size_dt_struct(new, struct_size); + + memmove(new + strings_off, old + fdt_off_dt_strings(old), + fdt_size_dt_strings(old)); + fdt_set_off_dt_strings(new, strings_off); + fdt_set_size_dt_strings(new, fdt_size_dt_strings(old)); +} + +int fdt_open_into(const void *fdt, void *buf, int bufsize) +{ + int err; + int mem_rsv_size, struct_size; + int newsize; + const char *fdtstart = fdt; + const char *fdtend = fdtstart + fdt_totalsize(fdt); + char *tmp; + + FDT_RO_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + + if (can_assume(LATEST) || fdt_version(fdt) >= 17) { + struct_size = fdt_size_dt_struct(fdt); + } else { + struct_size = 0; + while (fdt_next_tag(fdt, struct_size, &struct_size) != FDT_END) + ; + if (struct_size < 0) + return struct_size; + } + + if (can_assume(LIBFDT_ORDER) || + !fdt_blocks_misordered_(fdt, mem_rsv_size, struct_size)) { + /* no further work necessary */ + err = fdt_move(fdt, buf, bufsize); + if (err) + return err; + fdt_set_version(buf, 17); + fdt_set_size_dt_struct(buf, struct_size); + fdt_set_totalsize(buf, bufsize); + return 0; + } + + /* Need to reorder */ + newsize = FDT_ALIGN(sizeof(struct fdt_header), 8) + mem_rsv_size + + struct_size + fdt_size_dt_strings(fdt); + + if (bufsize < newsize) + return -FDT_ERR_NOSPACE; + + /* First attempt to build converted tree at beginning of buffer */ + tmp = buf; + /* But if that overlaps with the old tree... */ + if (((tmp + newsize) > fdtstart) && (tmp < fdtend)) { + /* Try right after the old tree instead */ + tmp = (char *)(uintptr_t)fdtend; + if ((tmp + newsize) > ((char *)buf + bufsize)) + return -FDT_ERR_NOSPACE; + } + + fdt_packblocks_(fdt, tmp, mem_rsv_size, struct_size); + memmove(buf, tmp, newsize); + + fdt_set_magic(buf, FDT_MAGIC); + fdt_set_totalsize(buf, bufsize); + fdt_set_version(buf, 17); + fdt_set_last_comp_version(buf, 16); + fdt_set_boot_cpuid_phys(buf, fdt_boot_cpuid_phys(fdt)); + + return 0; +} + +int fdt_pack(void *fdt) +{ + int mem_rsv_size; + + FDT_RW_PROBE(fdt); + + mem_rsv_size = (fdt_num_mem_rsv(fdt)+1) + * sizeof(struct fdt_reserve_entry); + fdt_packblocks_(fdt, fdt, mem_rsv_size, fdt_size_dt_struct(fdt)); + fdt_set_totalsize(fdt, fdt_data_size_(fdt)); + + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_strerror.c b/arm-trusted-firmware/lib/libfdt/fdt_strerror.c new file mode 100644 index 0000000..b435693 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_strerror.c @@ -0,0 +1,59 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +struct fdt_errtabent { + const char *str; +}; + +#define FDT_ERRTABENT(val) \ + [(val)] = { .str = #val, } + +static struct fdt_errtabent fdt_errtable[] = { + FDT_ERRTABENT(FDT_ERR_NOTFOUND), + FDT_ERRTABENT(FDT_ERR_EXISTS), + FDT_ERRTABENT(FDT_ERR_NOSPACE), + + FDT_ERRTABENT(FDT_ERR_BADOFFSET), + FDT_ERRTABENT(FDT_ERR_BADPATH), + FDT_ERRTABENT(FDT_ERR_BADPHANDLE), + FDT_ERRTABENT(FDT_ERR_BADSTATE), + + FDT_ERRTABENT(FDT_ERR_TRUNCATED), + FDT_ERRTABENT(FDT_ERR_BADMAGIC), + FDT_ERRTABENT(FDT_ERR_BADVERSION), + FDT_ERRTABENT(FDT_ERR_BADSTRUCTURE), + FDT_ERRTABENT(FDT_ERR_BADLAYOUT), + FDT_ERRTABENT(FDT_ERR_INTERNAL), + FDT_ERRTABENT(FDT_ERR_BADNCELLS), + FDT_ERRTABENT(FDT_ERR_BADVALUE), + FDT_ERRTABENT(FDT_ERR_BADOVERLAY), + FDT_ERRTABENT(FDT_ERR_NOPHANDLES), + FDT_ERRTABENT(FDT_ERR_BADFLAGS), +}; +#define FDT_ERRTABSIZE ((int)(sizeof(fdt_errtable) / sizeof(fdt_errtable[0]))) + +const char *fdt_strerror(int errval) +{ + if (errval > 0) + return ""; + else if (errval == 0) + return ""; + else if (-errval < FDT_ERRTABSIZE) { + const char *s = fdt_errtable[-errval].str; + + if (s) + return s; + } + + return ""; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_sw.c b/arm-trusted-firmware/lib/libfdt/fdt_sw.c new file mode 100644 index 0000000..68b543c --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_sw.c @@ -0,0 +1,384 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +static int fdt_sw_probe_(void *fdt) +{ + if (!can_assume(VALID_INPUT)) { + if (fdt_magic(fdt) == FDT_MAGIC) + return -FDT_ERR_BADSTATE; + else if (fdt_magic(fdt) != FDT_SW_MAGIC) + return -FDT_ERR_BADMAGIC; + } + + return 0; +} + +#define FDT_SW_PROBE(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_(fdt)) != 0) \ + return err; \ + } + +/* 'memrsv' state: Initial state after fdt_create() + * + * Allowed functions: + * fdt_add_reservemap_entry() + * fdt_finish_reservemap() [moves to 'struct' state] + */ +static int fdt_sw_probe_memrsv_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && fdt_off_dt_strings(fdt) != 0) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_MEMRSV(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_memrsv_(fdt)) != 0) \ + return err; \ + } + +/* 'struct' state: Enter this state after fdt_finish_reservemap() + * + * Allowed functions: + * fdt_begin_node() + * fdt_end_node() + * fdt_property*() + * fdt_finish() [moves to 'complete' state] + */ +static int fdt_sw_probe_struct_(void *fdt) +{ + int err = fdt_sw_probe_(fdt); + if (err) + return err; + + if (!can_assume(VALID_INPUT) && + fdt_off_dt_strings(fdt) != fdt_totalsize(fdt)) + return -FDT_ERR_BADSTATE; + return 0; +} + +#define FDT_SW_PROBE_STRUCT(fdt) \ + { \ + int err; \ + if ((err = fdt_sw_probe_struct_(fdt)) != 0) \ + return err; \ + } + +static inline uint32_t sw_flags(void *fdt) +{ + /* assert: (fdt_magic(fdt) == FDT_SW_MAGIC) */ + return fdt_last_comp_version(fdt); +} + +/* 'complete' state: Enter this state after fdt_finish() + * + * Allowed functions: none + */ + +static void *fdt_grab_space_(void *fdt, size_t len) +{ + unsigned int offset = fdt_size_dt_struct(fdt); + unsigned int spaceleft; + + spaceleft = fdt_totalsize(fdt) - fdt_off_dt_struct(fdt) + - fdt_size_dt_strings(fdt); + + if ((offset + len < offset) || (offset + len > spaceleft)) + return NULL; + + fdt_set_size_dt_struct(fdt, offset + len); + return fdt_offset_ptr_w_(fdt, offset); +} + +int fdt_create_with_flags(void *buf, int bufsize, uint32_t flags) +{ + const int hdrsize = FDT_ALIGN(sizeof(struct fdt_header), + sizeof(struct fdt_reserve_entry)); + void *fdt = buf; + + if (bufsize < hdrsize) + return -FDT_ERR_NOSPACE; + + if (flags & ~FDT_CREATE_FLAGS_ALL) + return -FDT_ERR_BADFLAGS; + + memset(buf, 0, bufsize); + + /* + * magic and last_comp_version keep intermediate state during the fdt + * creation process, which is replaced with the proper FDT format by + * fdt_finish(). + * + * flags should be accessed with sw_flags(). + */ + fdt_set_magic(fdt, FDT_SW_MAGIC); + fdt_set_version(fdt, FDT_LAST_SUPPORTED_VERSION); + fdt_set_last_comp_version(fdt, flags); + + fdt_set_totalsize(fdt, bufsize); + + fdt_set_off_mem_rsvmap(fdt, hdrsize); + fdt_set_off_dt_struct(fdt, fdt_off_mem_rsvmap(fdt)); + fdt_set_off_dt_strings(fdt, 0); + + return 0; +} + +int fdt_create(void *buf, int bufsize) +{ + return fdt_create_with_flags(buf, bufsize, 0); +} + +int fdt_resize(void *fdt, void *buf, int bufsize) +{ + size_t headsize, tailsize; + char *oldtail, *newtail; + + FDT_SW_PROBE(fdt); + + if (bufsize < 0) + return -FDT_ERR_NOSPACE; + + headsize = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + tailsize = fdt_size_dt_strings(fdt); + + if (!can_assume(VALID_DTB) && + headsize + tailsize > fdt_totalsize(fdt)) + return -FDT_ERR_INTERNAL; + + if ((headsize + tailsize) > (unsigned)bufsize) + return -FDT_ERR_NOSPACE; + + oldtail = (char *)fdt + fdt_totalsize(fdt) - tailsize; + newtail = (char *)buf + bufsize - tailsize; + + /* Two cases to avoid clobbering data if the old and new + * buffers partially overlap */ + if (buf <= fdt) { + memmove(buf, fdt, headsize); + memmove(newtail, oldtail, tailsize); + } else { + memmove(newtail, oldtail, tailsize); + memmove(buf, fdt, headsize); + } + + fdt_set_totalsize(buf, bufsize); + if (fdt_off_dt_strings(buf)) + fdt_set_off_dt_strings(buf, bufsize); + + return 0; +} + +int fdt_add_reservemap_entry(void *fdt, uint64_t addr, uint64_t size) +{ + struct fdt_reserve_entry *re; + int offset; + + FDT_SW_PROBE_MEMRSV(fdt); + + offset = fdt_off_dt_struct(fdt); + if ((offset + sizeof(*re)) > fdt_totalsize(fdt)) + return -FDT_ERR_NOSPACE; + + re = (struct fdt_reserve_entry *)((char *)fdt + offset); + re->address = cpu_to_fdt64(addr); + re->size = cpu_to_fdt64(size); + + fdt_set_off_dt_struct(fdt, offset + sizeof(*re)); + + return 0; +} + +int fdt_finish_reservemap(void *fdt) +{ + int err = fdt_add_reservemap_entry(fdt, 0, 0); + + if (err) + return err; + + fdt_set_off_dt_strings(fdt, fdt_totalsize(fdt)); + return 0; +} + +int fdt_begin_node(void *fdt, const char *name) +{ + struct fdt_node_header *nh; + int namelen; + + FDT_SW_PROBE_STRUCT(fdt); + + namelen = strlen(name) + 1; + nh = fdt_grab_space_(fdt, sizeof(*nh) + FDT_TAGALIGN(namelen)); + if (! nh) + return -FDT_ERR_NOSPACE; + + nh->tag = cpu_to_fdt32(FDT_BEGIN_NODE); + memcpy(nh->name, name, namelen); + return 0; +} + +int fdt_end_node(void *fdt) +{ + fdt32_t *en; + + FDT_SW_PROBE_STRUCT(fdt); + + en = fdt_grab_space_(fdt, FDT_TAGSIZE); + if (! en) + return -FDT_ERR_NOSPACE; + + *en = cpu_to_fdt32(FDT_END_NODE); + return 0; +} + +static int fdt_add_string_(void *fdt, const char *s) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + unsigned int strtabsize = fdt_size_dt_strings(fdt); + unsigned int len = strlen(s) + 1; + unsigned int struct_top, offset; + + offset = strtabsize + len; + struct_top = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + if (fdt_totalsize(fdt) - offset < struct_top) + return 0; /* no more room :( */ + + memcpy(strtab - offset, s, len); + fdt_set_size_dt_strings(fdt, strtabsize + len); + return -offset; +} + +/* Must only be used to roll back in case of error */ +static void fdt_del_last_string_(void *fdt, const char *s) +{ + int strtabsize = fdt_size_dt_strings(fdt); + int len = strlen(s) + 1; + + fdt_set_size_dt_strings(fdt, strtabsize - len); +} + +static int fdt_find_add_string_(void *fdt, const char *s, int *allocated) +{ + char *strtab = (char *)fdt + fdt_totalsize(fdt); + int strtabsize = fdt_size_dt_strings(fdt); + const char *p; + + *allocated = 0; + + p = fdt_find_string_(strtab - strtabsize, strtabsize, s); + if (p) + return p - strtab; + + *allocated = 1; + + return fdt_add_string_(fdt, s); +} + +int fdt_property_placeholder(void *fdt, const char *name, int len, void **valp) +{ + struct fdt_property *prop; + int nameoff; + int allocated; + + FDT_SW_PROBE_STRUCT(fdt); + + /* String de-duplication can be slow, _NO_NAME_DEDUP skips it */ + if (sw_flags(fdt) & FDT_CREATE_FLAG_NO_NAME_DEDUP) { + allocated = 1; + nameoff = fdt_add_string_(fdt, name); + } else { + nameoff = fdt_find_add_string_(fdt, name, &allocated); + } + if (nameoff == 0) + return -FDT_ERR_NOSPACE; + + prop = fdt_grab_space_(fdt, sizeof(*prop) + FDT_TAGALIGN(len)); + if (! prop) { + if (allocated) + fdt_del_last_string_(fdt, name); + return -FDT_ERR_NOSPACE; + } + + prop->tag = cpu_to_fdt32(FDT_PROP); + prop->nameoff = cpu_to_fdt32(nameoff); + prop->len = cpu_to_fdt32(len); + *valp = prop->data; + return 0; +} + +int fdt_property(void *fdt, const char *name, const void *val, int len) +{ + void *ptr; + int ret; + + ret = fdt_property_placeholder(fdt, name, len, &ptr); + if (ret) + return ret; + memcpy(ptr, val, len); + return 0; +} + +int fdt_finish(void *fdt) +{ + char *p = (char *)fdt; + fdt32_t *end; + int oldstroffset, newstroffset; + uint32_t tag; + int offset, nextoffset; + + FDT_SW_PROBE_STRUCT(fdt); + + /* Add terminator */ + end = fdt_grab_space_(fdt, sizeof(*end)); + if (! end) + return -FDT_ERR_NOSPACE; + *end = cpu_to_fdt32(FDT_END); + + /* Relocate the string table */ + oldstroffset = fdt_totalsize(fdt) - fdt_size_dt_strings(fdt); + newstroffset = fdt_off_dt_struct(fdt) + fdt_size_dt_struct(fdt); + memmove(p + newstroffset, p + oldstroffset, fdt_size_dt_strings(fdt)); + fdt_set_off_dt_strings(fdt, newstroffset); + + /* Walk the structure, correcting string offsets */ + offset = 0; + while ((tag = fdt_next_tag(fdt, offset, &nextoffset)) != FDT_END) { + if (tag == FDT_PROP) { + struct fdt_property *prop = + fdt_offset_ptr_w_(fdt, offset); + int nameoff; + + nameoff = fdt32_to_cpu(prop->nameoff); + nameoff += fdt_size_dt_strings(fdt); + prop->nameoff = cpu_to_fdt32(nameoff); + } + offset = nextoffset; + } + if (nextoffset < 0) + return nextoffset; + + /* Finally, adjust the header */ + fdt_set_totalsize(fdt, newstroffset + fdt_size_dt_strings(fdt)); + + /* And fix up fields that were keeping intermediate state. */ + fdt_set_last_comp_version(fdt, FDT_FIRST_SUPPORTED_VERSION); + fdt_set_magic(fdt, FDT_MAGIC); + + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/fdt_wip.c b/arm-trusted-firmware/lib/libfdt/fdt_wip.c new file mode 100644 index 0000000..c2d7566 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/fdt_wip.c @@ -0,0 +1,94 @@ +// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include "libfdt_env.h" + +#include +#include + +#include "libfdt_internal.h" + +int fdt_setprop_inplace_namelen_partial(void *fdt, int nodeoffset, + const char *name, int namelen, + uint32_t idx, const void *val, + int len) +{ + void *propval; + int proplen; + + propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen, + &proplen); + if (!propval) + return proplen; + + if ((unsigned)proplen < (len + idx)) + return -FDT_ERR_NOSPACE; + + memcpy((char *)propval + idx, val, len); + return 0; +} + +int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + const void *propval; + int proplen; + + propval = fdt_getprop(fdt, nodeoffset, name, &proplen); + if (!propval) + return proplen; + + if (proplen != len) + return -FDT_ERR_NOSPACE; + + return fdt_setprop_inplace_namelen_partial(fdt, nodeoffset, name, + strlen(name), 0, + val, len); +} + +static void fdt_nop_region_(void *start, int len) +{ + fdt32_t *p; + + for (p = start; (char *)p < ((char *)start + len); p++) + *p = cpu_to_fdt32(FDT_NOP); +} + +int fdt_nop_property(void *fdt, int nodeoffset, const char *name) +{ + struct fdt_property *prop; + int len; + + prop = fdt_get_property_w(fdt, nodeoffset, name, &len); + if (!prop) + return len; + + fdt_nop_region_(prop, len + sizeof(*prop)); + + return 0; +} + +int fdt_node_end_offset_(void *fdt, int offset) +{ + int depth = 0; + + while ((offset >= 0) && (depth >= 0)) + offset = fdt_next_node(fdt, offset, &depth); + + return offset; +} + +int fdt_nop_node(void *fdt, int nodeoffset) +{ + int endoffset; + + endoffset = fdt_node_end_offset_(fdt, nodeoffset); + if (endoffset < 0) + return endoffset; + + fdt_nop_region_(fdt_offset_ptr_w(fdt, nodeoffset, 0), + endoffset - nodeoffset); + return 0; +} diff --git a/arm-trusted-firmware/lib/libfdt/libfdt.mk b/arm-trusted-firmware/lib/libfdt/libfdt.mk new file mode 100644 index 0000000..1cbbd78 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/libfdt.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +LIBFDT_SRCS := $(addprefix lib/libfdt/, \ + fdt.c \ + fdt_addresses.c \ + fdt_empty_tree.c \ + fdt_ro.c \ + fdt_rw.c \ + fdt_strerror.c \ + fdt_sw.c \ + fdt_wip.c) \ + +INCLUDES += -Iinclude/lib/libfdt + +$(eval $(call MAKE_LIB,fdt)) diff --git a/arm-trusted-firmware/lib/libfdt/libfdt_internal.h b/arm-trusted-firmware/lib/libfdt/libfdt_internal.h new file mode 100644 index 0000000..d4e0bd4 --- /dev/null +++ b/arm-trusted-firmware/lib/libfdt/libfdt_internal.h @@ -0,0 +1,173 @@ +/* SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause) */ +#ifndef LIBFDT_INTERNAL_H +#define LIBFDT_INTERNAL_H +/* + * libfdt - Flat Device Tree manipulation + * Copyright (C) 2006 David Gibson, IBM Corporation. + */ +#include + +#define FDT_ALIGN(x, a) (((x) + (a) - 1) & ~((a) - 1)) +#define FDT_TAGALIGN(x) (FDT_ALIGN((x), FDT_TAGSIZE)) + +int32_t fdt_ro_probe_(const void *fdt); +#define FDT_RO_PROBE(fdt) \ + { \ + int32_t totalsize_; \ + if ((totalsize_ = fdt_ro_probe_(fdt)) < 0) \ + return totalsize_; \ + } + +int fdt_check_node_offset_(const void *fdt, int offset); +int fdt_check_prop_offset_(const void *fdt, int offset); +const char *fdt_find_string_(const char *strtab, int tabsize, const char *s); +int fdt_node_end_offset_(void *fdt, int nodeoffset); + +static inline const void *fdt_offset_ptr_(const void *fdt, int offset) +{ + return (const char *)fdt + fdt_off_dt_struct(fdt) + offset; +} + +static inline void *fdt_offset_ptr_w_(void *fdt, int offset) +{ + return (void *)(uintptr_t)fdt_offset_ptr_(fdt, offset); +} + +static inline const struct fdt_reserve_entry *fdt_mem_rsv_(const void *fdt, int n) +{ + const struct fdt_reserve_entry *rsv_table = + (const struct fdt_reserve_entry *) + ((const char *)fdt + fdt_off_mem_rsvmap(fdt)); + + return rsv_table + n; +} +static inline struct fdt_reserve_entry *fdt_mem_rsv_w_(void *fdt, int n) +{ + return (void *)(uintptr_t)fdt_mem_rsv_(fdt, n); +} + +#define FDT_SW_MAGIC (~FDT_MAGIC) + +/**********************************************************************/ +/* Checking controls */ +/**********************************************************************/ + +#ifndef FDT_ASSUME_MASK +#define FDT_ASSUME_MASK 0 +#endif + +/* + * Defines assumptions which can be enabled. Each of these can be enabled + * individually. For maximum safety, don't enable any assumptions! + * + * For minimal code size and no safety, use ASSUME_PERFECT at your own risk. + * You should have another method of validating the device tree, such as a + * signature or hash check before using libfdt. + * + * For situations where security is not a concern it may be safe to enable + * ASSUME_SANE. + */ +enum { + /* + * This does essentially no checks. Only the latest device-tree + * version is correctly handled. Inconsistencies or errors in the device + * tree may cause undefined behaviour or crashes. Invalid parameters + * passed to libfdt may do the same. + * + * If an error occurs when modifying the tree it may leave the tree in + * an intermediate (but valid) state. As an example, adding a property + * where there is insufficient space may result in the property name + * being added to the string table even though the property itself is + * not added to the struct section. + * + * Only use this if you have a fully validated device tree with + * the latest supported version and wish to minimise code size. + */ + ASSUME_PERFECT = 0xff, + + /* + * This assumes that the device tree is sane. i.e. header metadata + * and basic hierarchy are correct. + * + * With this assumption enabled, normal device trees produced by libfdt + * and the compiler should be handled safely. Malicious device trees and + * complete garbage may cause libfdt to behave badly or crash. Truncated + * device trees (e.g. those only partially loaded) can also cause + * problems. + * + * Note: Only checks that relate exclusively to the device tree itself + * (not the parameters passed to libfdt) are disabled by this + * assumption. This includes checking headers, tags and the like. + */ + ASSUME_VALID_DTB = 1 << 0, + + /* + * This builds on ASSUME_VALID_DTB and further assumes that libfdt + * functions are called with valid parameters, i.e. not trigger + * FDT_ERR_BADOFFSET or offsets that are out of bounds. It disables any + * extensive checking of parameters and the device tree, making various + * assumptions about correctness. + * + * It doesn't make sense to enable this assumption unless + * ASSUME_VALID_DTB is also enabled. + */ + ASSUME_VALID_INPUT = 1 << 1, + + /* + * This disables checks for device-tree version and removes all code + * which handles older versions. + * + * Only enable this if you know you have a device tree with the latest + * version. + */ + ASSUME_LATEST = 1 << 2, + + /* + * This assumes that it is OK for a failed addition to the device tree, + * due to lack of space or some other problem, to skip any rollback + * steps (such as dropping the property name from the string table). + * This is safe to enable in most circumstances, even though it may + * leave the tree in a sub-optimal state. + */ + ASSUME_NO_ROLLBACK = 1 << 3, + + /* + * This assumes that the device tree components appear in a 'convenient' + * order, i.e. the memory reservation block first, then the structure + * block and finally the string block. + * + * This order is not specified by the device-tree specification, + * but is expected by libfdt. The device-tree compiler always created + * device trees with this order. + * + * This assumption disables a check in fdt_open_into() and removes the + * ability to fix the problem there. This is safe if you know that the + * device tree is correctly ordered. See fdt_blocks_misordered_(). + */ + ASSUME_LIBFDT_ORDER = 1 << 4, + + /* + * This assumes that libfdt itself does not have any internal bugs. It + * drops certain checks that should never be needed unless libfdt has an + * undiscovered bug. + * + * This can generally be considered safe to enable. + */ + ASSUME_LIBFDT_FLAWLESS = 1 << 5, +}; + +/** + * can_assume_() - check if a particular assumption is enabled + * + * @mask: Mask to check (ASSUME_...) + * @return true if that assumption is enabled, else false + */ +static inline bool can_assume_(int mask) +{ + return FDT_ASSUME_MASK & mask; +} + +/** helper macros for checking assumptions */ +#define can_assume(_assume) can_assume_(ASSUME_ ## _assume) + +#endif /* LIBFDT_INTERNAL_H */ diff --git a/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c new file mode 100644 index 0000000..748eedd --- /dev/null +++ b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/* + * Functions in this file implement Bakery Algorithm for mutual exclusion with the + * bakery lock data structures in coherent memory. + * + * ARM architecture offers a family of exclusive access instructions to + * efficiently implement mutual exclusion with hardware support. However, as + * well as depending on external hardware, the these instructions have defined + * behavior only on certain memory types (cacheable and Normal memory in + * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases + * in trusted firmware are such that mutual exclusion implementation cannot + * expect that accesses to the lock have the specific type required by the + * architecture for these primitives to function (for example, not all + * contenders may have address translation enabled). + * + * This implementation does not use mutual exclusion primitives. It expects + * memory regions where the locks reside to be fully ordered and coherent + * (either by disabling address translation, or by assigning proper attributes + * when translation is enabled). + * + * Note that the ARM architecture guarantees single-copy atomicity for aligned + * accesses regardless of status of address translation. + */ + +#define assert_bakery_entry_valid(_entry, _bakery) do { \ + assert((_bakery) != NULL); \ + assert((_entry) < BAKERY_LOCK_MAX_CPUS); \ +} while (false) + +/* Obtain a ticket for a given CPU */ +static unsigned int bakery_get_ticket(bakery_lock_t *bakery, unsigned int me) +{ + unsigned int my_ticket, their_ticket; + unsigned int they; + + /* Prevent recursive acquisition */ + assert(bakery_ticket_number(bakery->lock_data[me]) == 0U); + + /* + * Flag that we're busy getting our ticket. All CPUs are iterated in the + * order of their ordinal position to decide the maximum ticket value + * observed so far. Our priority is set to be greater than the maximum + * observed priority + * + * Note that it's possible that more than one contender gets the same + * ticket value. That's OK as the lock is acquired based on the priority + * value, not the ticket value alone. + */ + my_ticket = 0U; + bakery->lock_data[me] = make_bakery_data(CHOOSING_TICKET, my_ticket); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + their_ticket = bakery_ticket_number(bakery->lock_data[they]); + if (their_ticket > my_ticket) + my_ticket = their_ticket; + } + + /* + * Compute ticket; then signal to other contenders waiting for us to + * finish calculating our ticket value that we're done + */ + ++my_ticket; + bakery->lock_data[me] = make_bakery_data(CHOSEN_TICKET, my_ticket); + + return my_ticket; +} + + +/* + * Acquire bakery lock + * + * Contending CPUs need first obtain a non-zero ticket and then calculate + * priority value. A contending CPU iterate over all other CPUs in the platform, + * which may be contending for the same lock, in the order of their ordinal + * position (CPU0, CPU1 and so on). A non-contending CPU will have its ticket + * (and priority) value as 0. The contending CPU compares its priority with that + * of others'. The CPU with the highest priority (lowest numerical value) + * acquires the lock + */ +void bakery_lock_get(bakery_lock_t *bakery) +{ + unsigned int they, me; + unsigned int my_ticket, my_prio, their_ticket; + unsigned int their_bakery_data; + + me = plat_my_core_pos(); + + assert_bakery_entry_valid(me, bakery); + + /* Get a ticket */ + my_ticket = bakery_get_ticket(bakery, me); + + /* + * Now that we got our ticket, compute our priority value, then compare + * with that of others, and proceed to acquire the lock + */ + my_prio = bakery_get_priority(my_ticket, me); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* Wait for the contender to get their ticket */ + do { + their_bakery_data = bakery->lock_data[they]; + } while (bakery_is_choosing(their_bakery_data)); + + /* + * If the other party is a contender, they'll have non-zero + * (valid) ticket value. If they do, compare priorities + */ + their_ticket = bakery_ticket_number(their_bakery_data); + if ((their_ticket != 0U) && + (bakery_get_priority(their_ticket, they) < my_prio)) { + /* + * They have higher priority (lower value). Wait for + * their ticket value to change (either release the lock + * to have it dropped to 0; or drop and probably content + * again for the same lock to have an even higher value) + */ + do { + wfe(); + } while (their_ticket == + bakery_ticket_number(bakery->lock_data[they])); + } + } + + /* + * Lock acquired. Ensure that any reads and writes from a shared + * resource in the critical section read/write values after the lock is + * acquired. + */ + dmbish(); +} + + +/* Release the lock and signal contenders */ +void bakery_lock_release(bakery_lock_t *bakery) +{ + unsigned int me = plat_my_core_pos(); + + assert_bakery_entry_valid(me, bakery); + assert(bakery_ticket_number(bakery->lock_data[me]) != 0U); + + /* + * Ensure that other observers see any stores in the critical section + * before releasing the lock. Also ensure all loads in the critical + * section are complete before releasing the lock. Release the lock by + * resetting ticket. Then signal other waiting contenders. + */ + dmbish(); + bakery->lock_data[me] = 0U; + + /* Required to ensure ordering of the following sev */ + dsb(); + sev(); +} diff --git a/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c new file mode 100644 index 0000000..7d35dea --- /dev/null +++ b/arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c @@ -0,0 +1,250 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include + +/* + * Functions in this file implement Bakery Algorithm for mutual exclusion with the + * bakery lock data structures in cacheable and Normal memory. + * + * ARM architecture offers a family of exclusive access instructions to + * efficiently implement mutual exclusion with hardware support. However, as + * well as depending on external hardware, these instructions have defined + * behavior only on certain memory types (cacheable and Normal memory in + * particular; see ARMv8 Architecture Reference Manual section B2.10). Use cases + * in trusted firmware are such that mutual exclusion implementation cannot + * expect that accesses to the lock have the specific type required by the + * architecture for these primitives to function (for example, not all + * contenders may have address translation enabled). + * + * This implementation does not use mutual exclusion primitives. It expects + * memory regions where the locks reside to be cacheable and Normal. + * + * Note that the ARM architecture guarantees single-copy atomicity for aligned + * accesses regardless of status of address translation. + */ + +#ifdef PLAT_PERCPU_BAKERY_LOCK_SIZE +/* + * Verify that the platform defined value for the per-cpu space for bakery locks is + * a multiple of the cache line size, to prevent multiple CPUs writing to the same + * bakery lock cache line + * + * Using this value, if provided, rather than the linker generated value results in + * more efficient code + */ +CASSERT((PLAT_PERCPU_BAKERY_LOCK_SIZE & (CACHE_WRITEBACK_GRANULE - 1)) == 0, \ + PLAT_PERCPU_BAKERY_LOCK_SIZE_not_cacheline_multiple); +#define PERCPU_BAKERY_LOCK_SIZE (PLAT_PERCPU_BAKERY_LOCK_SIZE) +#else +/* + * Use the linker defined symbol which has evaluated the size reqiurement. + * This is not as efficient as using a platform defined constant + */ +IMPORT_SYM(uintptr_t, __PERCPU_BAKERY_LOCK_START__, BAKERY_LOCK_START); +IMPORT_SYM(uintptr_t, __PERCPU_BAKERY_LOCK_END__, BAKERY_LOCK_END); +#define PERCPU_BAKERY_LOCK_SIZE (BAKERY_LOCK_END - BAKERY_LOCK_START) +#endif + +static inline bakery_lock_t *get_bakery_info(unsigned int cpu_ix, + bakery_lock_t *lock) +{ + return (bakery_info_t *)((uintptr_t)lock + + cpu_ix * PERCPU_BAKERY_LOCK_SIZE); +} + +static inline void write_cache_op(uintptr_t addr, bool cached) +{ + if (cached) + dccvac(addr); + else + dcivac(addr); + + dsbish(); +} + +static inline void read_cache_op(uintptr_t addr, bool cached) +{ + if (cached) + dccivac(addr); + + dmbish(); +} + +/* Helper function to check if the lock is acquired */ +static inline bool is_lock_acquired(const bakery_info_t *my_bakery_info, + bool is_cached) +{ + /* + * Even though lock data is updated only by the owning cpu and + * appropriate cache maintenance operations are performed, + * if the previous update was done when the cpu was not participating + * in coherency, then there is a chance that cache maintenance + * operations were not propagated to all the caches in the system. + * Hence do a `read_cache_op()` prior to read. + */ + read_cache_op((uintptr_t)my_bakery_info, is_cached); + return bakery_ticket_number(my_bakery_info->lock_data) != 0U; +} + +static unsigned int bakery_get_ticket(bakery_lock_t *lock, + unsigned int me, bool is_cached) +{ + unsigned int my_ticket, their_ticket; + unsigned int they; + bakery_info_t *my_bakery_info, *their_bakery_info; + + /* + * Obtain a reference to the bakery information for this cpu and ensure + * it is not NULL. + */ + my_bakery_info = get_bakery_info(me, lock); + assert(my_bakery_info != NULL); + + /* Prevent recursive acquisition.*/ + assert(!is_lock_acquired(my_bakery_info, is_cached)); + + /* + * Tell other contenders that we are through the bakery doorway i.e. + * going to allocate a ticket for this cpu. + */ + my_ticket = 0U; + my_bakery_info->lock_data = make_bakery_data(CHOOSING_TICKET, my_ticket); + + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + /* + * Iterate through the bakery information of each contender to allocate + * the highest ticket number for this cpu. + */ + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* + * Get a reference to the other contender's bakery info and + * ensure that a stale copy is not read. + */ + their_bakery_info = get_bakery_info(they, lock); + assert(their_bakery_info != NULL); + + read_cache_op((uintptr_t)their_bakery_info, is_cached); + + /* + * Update this cpu's ticket number if a higher ticket number is + * seen + */ + their_ticket = bakery_ticket_number(their_bakery_info->lock_data); + if (their_ticket > my_ticket) + my_ticket = their_ticket; + } + + /* + * Compute ticket; then signal to other contenders waiting for us to + * finish calculating our ticket value that we're done + */ + ++my_ticket; + my_bakery_info->lock_data = make_bakery_data(CHOSEN_TICKET, my_ticket); + + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + return my_ticket; +} + +void bakery_lock_get(bakery_lock_t *lock) +{ + unsigned int they, me; + unsigned int my_ticket, my_prio, their_ticket; + bakery_info_t *their_bakery_info; + unsigned int their_bakery_data; + bool is_cached; + + me = plat_my_core_pos(); + is_cached = is_dcache_enabled(); + + /* Get a ticket */ + my_ticket = bakery_get_ticket(lock, me, is_cached); + + /* + * Now that we got our ticket, compute our priority value, then compare + * with that of others, and proceed to acquire the lock + */ + my_prio = bakery_get_priority(my_ticket, me); + for (they = 0U; they < BAKERY_LOCK_MAX_CPUS; they++) { + if (me == they) + continue; + + /* + * Get a reference to the other contender's bakery info and + * ensure that a stale copy is not read. + */ + their_bakery_info = get_bakery_info(they, lock); + assert(their_bakery_info != NULL); + + /* Wait for the contender to get their ticket */ + do { + read_cache_op((uintptr_t)their_bakery_info, is_cached); + their_bakery_data = their_bakery_info->lock_data; + } while (bakery_is_choosing(their_bakery_data)); + + /* + * If the other party is a contender, they'll have non-zero + * (valid) ticket value. If they do, compare priorities + */ + their_ticket = bakery_ticket_number(their_bakery_data); + if (their_ticket && (bakery_get_priority(their_ticket, they) < my_prio)) { + /* + * They have higher priority (lower value). Wait for + * their ticket value to change (either release the lock + * to have it dropped to 0; or drop and probably content + * again for the same lock to have an even higher value) + */ + do { + wfe(); + read_cache_op((uintptr_t)their_bakery_info, is_cached); + } while (their_ticket + == bakery_ticket_number(their_bakery_info->lock_data)); + } + } + + /* + * Lock acquired. Ensure that any reads and writes from a shared + * resource in the critical section read/write values after the lock is + * acquired. + */ + dmbish(); +} + +void bakery_lock_release(bakery_lock_t *lock) +{ + bakery_info_t *my_bakery_info; + bool is_cached = is_dcache_enabled(); + + my_bakery_info = get_bakery_info(plat_my_core_pos(), lock); + + assert(is_lock_acquired(my_bakery_info, is_cached)); + + /* + * Ensure that other observers see any stores in the critical section + * before releasing the lock. Also ensure all loads in the critical + * section are complete before releasing the lock. Release the lock by + * resetting ticket. Then signal other waiting contenders. + */ + dmbish(); + my_bakery_info->lock_data = 0U; + write_cache_op((uintptr_t)my_bakery_info, is_cached); + + /* This sev is ordered by the dsbish in write_cahce_op */ + sev(); +} diff --git a/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S b/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S new file mode 100644 index 0000000..9492cc0 --- /dev/null +++ b/arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl spin_lock + .globl spin_unlock + +#if ARM_ARCH_AT_LEAST(8, 0) +/* + * According to the ARMv8-A Architecture Reference Manual, "when the global + * monitor for a PE changes from Exclusive Access state to Open Access state, + * an event is generated.". This applies to both AArch32 and AArch64 modes of + * ARMv8-A. As a result, no explicit SEV with unlock is required. + */ +#define COND_SEV() +#else +#define COND_SEV() sev +#endif + +func spin_lock + mov r2, #1 +1: + ldrex r1, [r0] + cmp r1, #0 + wfene + strexeq r1, r2, [r0] + cmpeq r1, #0 + bne 1b + dmb + bx lr +endfunc spin_lock + + +func spin_unlock + mov r1, #0 + stl r1, [r0] + COND_SEV() + bx lr +endfunc spin_unlock diff --git a/arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S b/arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S new file mode 100644 index 0000000..e941b8a --- /dev/null +++ b/arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl spin_lock + .globl spin_unlock + +#if USE_SPINLOCK_CAS +#if !ARM_ARCH_AT_LEAST(8, 1) +#error USE_SPINLOCK_CAS option requires at least an ARMv8.1 platform +#endif + +/* + * When compiled for ARMv8.1 or later, choose spin locks based on Compare and + * Swap instruction. + */ + +/* + * Acquire lock using Compare and Swap instruction. + * + * Compare for 0 with acquire semantics, and swap 1. If failed to acquire, use + * load exclusive semantics to monitor the address and enter WFE. + * + * void spin_lock(spinlock_t *lock); + */ +func spin_lock + mov w2, #1 +1: mov w1, wzr +2: casa w1, w2, [x0] + cbz w1, 3f + ldxr w1, [x0] + cbz w1, 2b + wfe + b 1b +3: + ret +endfunc spin_lock + +#else /* !USE_SPINLOCK_CAS */ + +/* + * Acquire lock using load-/store-exclusive instruction pair. + * + * void spin_lock(spinlock_t *lock); + */ +func spin_lock + mov w2, #1 + sevl +l1: wfe +l2: ldaxr w1, [x0] + cbnz w1, l1 + stxr w1, w2, [x0] + cbnz w1, l2 + ret +endfunc spin_lock + +#endif /* USE_SPINLOCK_CAS */ + +/* + * Release lock previously acquired by spin_lock. + * + * Use store-release to unconditionally clear the spinlock variable. + * Store operation generates an event to all cores waiting in WFE + * when address is monitored by the global monitor. + * + * void spin_unlock(spinlock_t *lock); + */ +func spin_unlock + stlr wzr, [x0] + ret +endfunc spin_unlock diff --git a/arm-trusted-firmware/lib/mpmm/mpmm.c b/arm-trusted-firmware/lib/mpmm/mpmm.c new file mode 100644 index 0000000..dc61cf6 --- /dev/null +++ b/arm-trusted-firmware/lib/mpmm/mpmm.c @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#if ENABLE_MPMM_FCONF +# include +# include +#endif + +static uint64_t read_cpuppmcr_el3_mpmmpinctl(void) +{ + return (read_cpuppmcr_el3() >> CPUPPMCR_EL3_MPMMPINCTL_SHIFT) & + CPUPPMCR_EL3_MPMMPINCTL_MASK; +} + +static void write_cpumpmmcr_el3_mpmm_en(uint64_t mpmm_en) +{ + uint64_t value = read_cpumpmmcr_el3(); + + value &= ~(CPUMPMMCR_EL3_MPMM_EN_MASK << CPUMPMMCR_EL3_MPMM_EN_SHIFT); + value |= (mpmm_en & CPUMPMMCR_EL3_MPMM_EN_MASK) << + CPUMPMMCR_EL3_MPMM_EN_SHIFT; + + write_cpumpmmcr_el3(value); +} + +static bool mpmm_supported(void) +{ + bool supported = false; + const struct mpmm_topology *topology; + +#if ENABLE_MPMM_FCONF + topology = FCONF_GET_PROPERTY(mpmm, config, topology); +#else + topology = plat_mpmm_topology(); +#endif /* ENABLE_MPMM_FCONF */ + + /* + * For the current core firstly try to find out if the platform + * configuration has claimed support for MPMM, then make sure that MPMM + * is controllable through the system registers. + */ + + if (topology != NULL) { + unsigned int core_pos = plat_my_core_pos(); + + supported = topology->cores[core_pos].supported && + (read_cpuppmcr_el3_mpmmpinctl() == 0U); + } else { + ERROR("MPMM: failed to generate MPMM topology\n"); + } + + return supported; +} + +/* Defaults to false */ +static bool mpmm_disable_for_errata; + +void mpmm_enable(void) +{ + if (mpmm_supported()) { + if (mpmm_disable_for_errata) { + WARN("MPMM: disabled by errata workaround\n"); + return; + } + write_cpumpmmcr_el3_mpmm_en(1U); + } +} + +/* + * This function is called from assembly code very early in BL31 so it must be + * small and simple. + */ +void mpmm_errata_disable(void) +{ + mpmm_disable_for_errata = true; +} diff --git a/arm-trusted-firmware/lib/mpmm/mpmm.mk b/arm-trusted-firmware/lib/mpmm/mpmm.mk new file mode 100644 index 0000000..826f925 --- /dev/null +++ b/arm-trusted-firmware/lib/mpmm/mpmm.mk @@ -0,0 +1,29 @@ +# +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include lib/extensions/amu/amu.mk +include lib/fconf/fconf.mk + +ifneq (${ENABLE_MPMM},0) + ifneq ($(ARCH),aarch64) + $(error MPMM support (`ENABLE_MPMM`) can only be enabled in AArch64 images (`ARCH`)) + endif + + ifeq (${ENABLE_AMU_AUXILIARY_COUNTERS},0) # For MPMM gear AMU counters + $(error MPMM support (`ENABLE_MPM`) requires auxiliary AMU counter support (`ENABLE_AMU_AUXILIARY_COUNTERS`)) + endif +endif + +MPMM_SOURCES := lib/mpmm/mpmm.c +MPMM_SOURCES += ${AMU_SOURCES} + +ifneq (${ENABLE_MPMM_FCONF},0) + ifeq (${ENABLE_MPMM},0) + $(error MPMM FCONF support (`ENABLE_MPMM_FCONF`) requires MPMM support (`ENABLE_MPMM`)) + endif + + MPMM_SOURCES += ${FCONF_MPMM_SOURCES} +endif diff --git a/arm-trusted-firmware/lib/optee/optee_utils.c b/arm-trusted-firmware/lib/optee/optee_utils.c new file mode 100644 index 0000000..72979cd --- /dev/null +++ b/arm-trusted-firmware/lib/optee/optee_utils.c @@ -0,0 +1,234 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * load_addr_hi and load_addr_lo: image load address. + * image_id: 0 - pager, 1 - paged + * size: image size in bytes. + */ +typedef struct optee_image { + uint32_t load_addr_hi; + uint32_t load_addr_lo; + uint32_t image_id; + uint32_t size; +} optee_image_t; + +#define OPTEE_PAGER_IMAGE_ID 0 +#define OPTEE_PAGED_IMAGE_ID 1 + +#define OPTEE_MAX_NUM_IMAGES 2u + +#define TEE_MAGIC_NUM_OPTEE 0x4554504f +/* + * magic: header magic number. + * version: OPTEE header version: + * 1 - not supported + * 2 - supported + * arch: OPTEE os architecture type: 0 - AARCH32, 1 - AARCH64. + * flags: unused currently. + * nb_images: number of images. + */ +typedef struct optee_header { + uint32_t magic; + uint8_t version; + uint8_t arch; + uint16_t flags; + uint32_t nb_images; + optee_image_t optee_image_list[]; +} optee_header_t; + +/******************************************************************************* + * Check if it is a valid tee header + * Return true if valid + * Return false if invalid + ******************************************************************************/ +static bool tee_validate_header(optee_header_t *header) +{ + if ((header->magic == TEE_MAGIC_NUM_OPTEE) && + (header->version == 2u) && + (header->nb_images > 0u) && + (header->nb_images <= OPTEE_MAX_NUM_IMAGES)) { + return true; + } + + return false; +} + +bool optee_header_is_valid(uintptr_t header_base) +{ + return tee_validate_header((optee_header_t *)header_base); +} + +/******************************************************************************* + * Parse the OPTEE image + * Return 0 on success or a negative error code otherwise. + ******************************************************************************/ +static int parse_optee_image(image_info_t *image_info, + optee_image_t *image) +{ + uintptr_t init_load_addr, free_end, requested_end; + size_t init_size; + + init_load_addr = ((uint64_t)image->load_addr_hi << 32) | + image->load_addr_lo; + init_size = image->size; + + /* + * image->load_addr_hi & image->load_addr_lo set to UINT32_MAX indicate + * loader decided address; take our pre-mapped area for current image + * since arm-tf could not allocate memory dynamically + */ + if ((image->load_addr_hi == UINT32_MAX) && + (image->load_addr_lo == UINT32_MAX)) { + init_load_addr = image_info->image_base; + } + + /* Check that the default end address doesn't overflow */ + if (check_uptr_overflow(image_info->image_base, + image_info->image_max_size - 1)) + return -1; + free_end = image_info->image_base + (image_info->image_max_size - 1); + + /* Check that the image end address doesn't overflow */ + if (check_uptr_overflow(init_load_addr, init_size - 1)) + return -1; + requested_end = init_load_addr + (init_size - 1); + /* + * Check that the requested RAM location is within reserved + * space for OPTEE. + */ + if (!((init_load_addr >= image_info->image_base) && + (requested_end <= free_end))) { + WARN("The load address in optee header %p - %p is not in reserved area: %p - %p.\n", + (void *)init_load_addr, + (void *)(init_load_addr + init_size), + (void *)image_info->image_base, + (void *)(image_info->image_base + + image_info->image_max_size)); + return -1; + } + + /* + * Remove the skip attr from image_info, the image will be loaded. + * The default attr in image_info is "IMAGE_ATTRIB_SKIP_LOADING", which + * mean the image will not be loaded. Here, we parse the header image to + * know that the extra image need to be loaded, so remove the skip attr. + */ + image_info->h.attr &= ~IMAGE_ATTRIB_SKIP_LOADING; + + /* Update image base and size of image_info */ + image_info->image_base = init_load_addr; + image_info->image_size = init_size; + + return 0; +} + +/******************************************************************************* + * Parse the OPTEE header + * Return 0 on success or a negative error code otherwise. + ******************************************************************************/ +int parse_optee_header(entry_point_info_t *header_ep, + image_info_t *pager_image_info, + image_info_t *paged_image_info) + +{ + optee_header_t *header; + uint32_t num; + int ret; + + assert(header_ep); + header = (optee_header_t *)header_ep->pc; + assert(header); + + /* Print the OPTEE header information */ + INFO("OPTEE ep=0x%x\n", (unsigned int)header_ep->pc); + INFO("OPTEE header info:\n"); + INFO(" magic=0x%x\n", header->magic); + INFO(" version=0x%x\n", header->version); + INFO(" arch=0x%x\n", header->arch); + INFO(" flags=0x%x\n", header->flags); + INFO(" nb_images=0x%x\n", header->nb_images); + + /* + * OPTEE image has 3 types: + * + * 1. Plain OPTEE bin without header. + * Original bin without header, return directly, + * BL32_EXTRA1_IMAGE_ID and BL32_EXTRA2_IMAGE_ID will be skipped. + * + * 2. OPTEE bin with header bin, but no paging. + * Header available and nb_images = 1, remove skip attr for + * BL32_EXTRA1_IMAGE_ID. BL32_EXTRA1_IMAGE_ID will be loaded, + * and BL32_EXTRA2_IMAGE_ID be skipped. + * + * 3. OPTEE image with paging support. + * Header available and nb_images = 2, there are 3 bins: header, + * pager and pageable. Remove skip attr for BL32_EXTRA1_IMAGE_ID + * and BL32_EXTRA2_IMAGE_ID to load pager and paged bin. + */ + if (!tee_validate_header(header)) { + INFO("Invalid OPTEE header, set legacy mode.\n"); +#ifdef __aarch64__ + header_ep->args.arg0 = MODE_RW_64; +#else + header_ep->args.arg0 = MODE_RW_32; +#endif + return 0; + } + + /* Parse OPTEE image */ + for (num = 0U; num < header->nb_images; num++) { + if (header->optee_image_list[num].image_id == + OPTEE_PAGER_IMAGE_ID) { + ret = parse_optee_image(pager_image_info, + &header->optee_image_list[num]); + } else if (header->optee_image_list[num].image_id == + OPTEE_PAGED_IMAGE_ID) { + ret = parse_optee_image(paged_image_info, + &header->optee_image_list[num]); + } else { + ERROR("Parse optee image failed.\n"); + return -1; + } + + if (ret != 0) + return -1; + } + + /* + * Update "pc" value which should comes from pager image. After the + * header image is parsed, it will be unuseful, and the actual + * execution image after BL31 is pager image. + */ + header_ep->pc = pager_image_info->image_base; + + /* + * The paged load address and size are populated in + * header image arguments so that can be read by the + * BL32 SPD. + */ + header_ep->args.arg1 = paged_image_info->image_base; + header_ep->args.arg2 = paged_image_info->image_size; + + /* Set OPTEE runtime arch - aarch32/aarch64 */ + if (header->arch == 0) { + header_ep->args.arg0 = MODE_RW_32; + } else { +#ifdef __aarch64__ + header_ep->args.arg0 = MODE_RW_64; +#else + ERROR("Cannot boot an AArch64 OP-TEE\n"); + return -1; +#endif + } + + return 0; +} diff --git a/arm-trusted-firmware/lib/pmf/pmf_main.c b/arm-trusted-firmware/lib/pmf/pmf_main.c new file mode 100644 index 0000000..131a055 --- /dev/null +++ b/arm-trusted-firmware/lib/pmf/pmf_main.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * The 'pmf_svc_descs' array holds the PMF service descriptors exported by + * services by placing them in the 'pmf_svc_descs' linker section. + * The 'pmf_svc_descs_indices' array holds the index of a descriptor in the + * 'pmf_svc_descs' array. The TIF[15:10] bits in the time-stamp id are used + * to get an index into the 'pmf_svc_descs_indices' array. This gives the + * index of the descriptor in the 'pmf_svc_descs' array which contains the + * service function pointers. + ******************************************************************************/ + +IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_START__, PMF_SVC_DESCS_START); +IMPORT_SYM(uintptr_t, __PMF_SVC_DESCS_END__, PMF_SVC_DESCS_END); +IMPORT_SYM(uintptr_t, __PMF_PERCPU_TIMESTAMP_END__, PMF_PERCPU_TIMESTAMP_END); +IMPORT_SYM(uintptr_t, __PMF_TIMESTAMP_START__, PMF_TIMESTAMP_ARRAY_START); + +#define PMF_PERCPU_TIMESTAMP_SIZE (PMF_PERCPU_TIMESTAMP_END - PMF_TIMESTAMP_ARRAY_START) + +#define PMF_SVC_DESCS_MAX 10 + +/* + * This is used to traverse through registered PMF services. + */ +static pmf_svc_desc_t *pmf_svc_descs; + +/* + * This array is used to store registered PMF services in sorted order. + */ +static int pmf_svc_descs_indices[PMF_SVC_DESCS_MAX]; + +/* + * This is used to track total number of successfully registered PMF services. + */ +static int pmf_num_services; + +/* + * This is the main PMF function that initialize registered + * PMF services and also sort them in ascending order. + */ +int pmf_setup(void) +{ + int rc, ii, jj = 0; + int pmf_svc_descs_num, temp_val; + + /* If no PMF services are registered then simply bail out */ + pmf_svc_descs_num = (PMF_SVC_DESCS_END - PMF_SVC_DESCS_START)/ + sizeof(pmf_svc_desc_t); + if (pmf_svc_descs_num == 0) + return 0; + + assert(pmf_svc_descs_num < PMF_SVC_DESCS_MAX); + + pmf_svc_descs = (pmf_svc_desc_t *) PMF_SVC_DESCS_START; + for (ii = 0; ii < pmf_svc_descs_num; ii++) { + + assert(pmf_svc_descs[ii].get_ts != NULL); + + /* + * Call the initialization routine for this + * PMF service, if it is defined. + */ + if (pmf_svc_descs[ii].init != NULL) { + rc = pmf_svc_descs[ii].init(); + if (rc != 0) { + WARN("Could not initialize PMF" + "service %s - skipping \n", + pmf_svc_descs[ii].name); + continue; + } + } + + /* Update the pmf_svc_descs_indices array */ + pmf_svc_descs_indices[jj++] = ii; + } + + pmf_num_services = jj; + + /* + * Sort the successfully registered PMF services + * according to service ID + */ + for (ii = 1; ii < pmf_num_services; ii++) { + for (jj = 0; jj < (pmf_num_services - ii); jj++) { + if ((pmf_svc_descs[jj].svc_config & PMF_SVC_ID_MASK) > + (pmf_svc_descs[jj + 1].svc_config & + PMF_SVC_ID_MASK)) { + temp_val = pmf_svc_descs_indices[jj]; + pmf_svc_descs_indices[jj] = + pmf_svc_descs_indices[jj+1]; + pmf_svc_descs_indices[jj+1] = temp_val; + } + } + } + + return 0; +} + +/* + * This function implements binary search to find registered + * PMF service based on Service ID provided in `tid` argument. + */ +static pmf_svc_desc_t *get_service(unsigned int tid) +{ + int low = 0; + int mid; + int high = pmf_num_services; + unsigned int svc_id = tid & PMF_SVC_ID_MASK; + int index; + unsigned int desc_svc_id; + + if (pmf_num_services == 0) + return NULL; + + assert(pmf_svc_descs != NULL); + + do { + mid = (low + high) / 2; + index = pmf_svc_descs_indices[mid]; + + desc_svc_id = pmf_svc_descs[index].svc_config & PMF_SVC_ID_MASK; + if (svc_id < desc_svc_id) + high = mid - 1; + if (svc_id > desc_svc_id) + low = mid + 1; + } while ((svc_id != desc_svc_id) && (low <= high)); + + /* + * Make sure the Service found supports the tid range. + */ + if ((svc_id == desc_svc_id) && ((tid & PMF_TID_MASK) < + (pmf_svc_descs[index].svc_config & PMF_TID_MASK))) + return (pmf_svc_desc_t *)&pmf_svc_descs[index]; + + return NULL; +} + +/* + * This function gets the time-stamp value for the PMF services + * registered for SMC interface based on `tid` and `mpidr`. + */ +int pmf_get_timestamp_smc(unsigned int tid, + u_register_t mpidr, + unsigned int flags, + unsigned long long *ts_value) +{ + pmf_svc_desc_t *svc_desc; + assert(ts_value != NULL); + + /* Search for registered service. */ + svc_desc = get_service(tid); + + if ((svc_desc == NULL) || (plat_core_pos_by_mpidr(mpidr) < 0)) { + *ts_value = 0; + return -EINVAL; + } else { + /* Call the service time-stamp handler. */ + *ts_value = svc_desc->get_ts(tid, mpidr, flags); + return 0; + } +} + +/* + * This function can be used to dump `ts` value for given `tid`. + * Assumption is that the console is already initialized. + */ +void __pmf_dump_timestamp(unsigned int tid, unsigned long long ts) +{ + printf("PMF:cpu %u tid %u ts %llu\n", + plat_my_core_pos(), tid, ts); +} + +/* + * This function calculate the address identified by + * `base_addr`, `tid` and `cpuid`. + */ +static inline uintptr_t calc_ts_addr(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid) +{ + assert(cpuid < PLATFORM_CORE_COUNT); + assert(base_addr >= PMF_TIMESTAMP_ARRAY_START); + assert(base_addr < ((PMF_TIMESTAMP_ARRAY_START + + PMF_PERCPU_TIMESTAMP_SIZE) - ((tid & PMF_TID_MASK) * + sizeof(unsigned long long)))); + + base_addr += ((cpuid * PMF_PERCPU_TIMESTAMP_SIZE) + + ((tid & PMF_TID_MASK) * sizeof(unsigned long long))); + + return base_addr; +} + +/* + * This function stores the `ts` value to the storage identified by + * `base_addr`, `tid` and current cpu id. + * Note: The timestamp addresses are cache line aligned per cpu + * and only the owning CPU would ever write into it. + */ +void __pmf_store_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts) +{ + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, plat_my_core_pos()); + *ts_addr = ts; +} + +/* + * This is the cached version of `pmf_store_my_timestamp` + * Note: The timestamp addresses are cache line aligned per cpu + * and only the owning CPU would ever write into it. + */ +void __pmf_store_timestamp_with_cache_maint(uintptr_t base_addr, + unsigned int tid, + unsigned long long ts) +{ + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, plat_my_core_pos()); + *ts_addr = ts; + flush_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long)); +} + +/* + * This function retrieves the `ts` value from the storage identified by + * `base_addr`, `tid` and `cpuid`. + * Note: The timestamp addresses are cache line aligned per cpu. + */ +unsigned long long __pmf_get_timestamp(uintptr_t base_addr, + unsigned int tid, + unsigned int cpuid, + unsigned int flags) +{ + assert(cpuid < PLATFORM_CORE_COUNT); + unsigned long long *ts_addr = (unsigned long long *)calc_ts_addr(base_addr, + tid, cpuid); + + if ((flags & PMF_CACHE_MAINT) != 0U) + inv_dcache_range((uintptr_t)ts_addr, sizeof(unsigned long long)); + + return *ts_addr; +} diff --git a/arm-trusted-firmware/lib/pmf/pmf_smc.c b/arm-trusted-firmware/lib/pmf/pmf_smc.c new file mode 100644 index 0000000..6d79502 --- /dev/null +++ b/arm-trusted-firmware/lib/pmf/pmf_smc.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * This function is responsible for handling all PMF SMC calls. + */ +uintptr_t pmf_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) +{ + int rc; + unsigned long long ts_value; + + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + + x1 = (uint32_t)x1; + x2 = (uint32_t)x2; + x3 = (uint32_t)x3; + + if (smc_fid == PMF_SMC_GET_TIMESTAMP_32) { + /* + * Return error code and the captured + * time-stamp to the caller. + * x0 --> error code. + * x1 - x2 --> time-stamp value. + */ + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); + SMC_RET3(handle, rc, (uint32_t)ts_value, + (uint32_t)(ts_value >> 32)); + } + } else { + if (smc_fid == PMF_SMC_GET_TIMESTAMP_64) { + /* + * Return error code and the captured + * time-stamp to the caller. + * x0 --> error code. + * x1 --> time-stamp value. + */ + rc = pmf_get_timestamp_smc((unsigned int)x1, x2, + (unsigned int)x3, &ts_value); + SMC_RET2(handle, rc, ts_value); + } + } + + WARN("Unimplemented PMF Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S b/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S new file mode 100644 index 0000000..5cc192e --- /dev/null +++ b/arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl psci_do_pwrdown_cache_maintenance + .globl psci_do_pwrup_cache_maintenance + .globl psci_power_down_wfi + +/* ----------------------------------------------------------------------- + * void psci_do_pwrdown_cache_maintenance(unsigned int power level); + * + * This function performs cache maintenance for the specified power + * level. The levels of cache affected are determined by the power + * level which is passed as the argument i.e. level 0 results + * in a flush of the L1 cache. Both the L1 and L2 caches are flushed + * for a higher power level. + * + * Additionally, this function also ensures that stack memory is correctly + * flushed out to avoid coherency issues due to a change in its memory + * attributes after the data cache is disabled. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrdown_cache_maintenance + push {r4, lr} + + /* ---------------------------------------------- + * Turn OFF cache and do stack maintenance + * prior to cpu operations . This sequence is + * different from AArch64 because in AArch32 the + * assembler routines for cpu operations utilize + * the stack whereas in AArch64 it doesn't. + * ---------------------------------------------- + */ + mov r4, r0 + bl do_stack_maintenance + + /* --------------------------------------------- + * Invoke CPU-specifc power down operations for + * the appropriate level + * --------------------------------------------- + */ + mov r0, r4 + pop {r4, lr} + b prepare_cpu_pwr_dwn +endfunc psci_do_pwrdown_cache_maintenance + + +/* ----------------------------------------------------------------------- + * void psci_do_pwrup_cache_maintenance(void); + * + * This function performs cache maintenance after this cpu is powered up. + * Currently, this involves managing the used stack memory before turning + * on the data cache. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrup_cache_maintenance + /* r12 is pushed to meet the 8 byte stack alignment requirement */ + push {r12, lr} + + /* --------------------------------------------- + * Ensure any inflight stack writes have made it + * to main memory. + * --------------------------------------------- + */ + dmb st + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in r1. Calculate and store the + * stack base address in r0. + * --------------------------------------------- + */ + bl plat_get_my_stack + mov r1, sp + sub r1, r0, r1 + mov r0, sp + bl inv_dcache_range + + /* --------------------------------------------- + * Enable the data cache. + * --------------------------------------------- + */ + ldcopr r0, SCTLR + orr r0, r0, #SCTLR_C_BIT + stcopr r0, SCTLR + isb + + pop {r12, pc} +endfunc psci_do_pwrup_cache_maintenance + + /* --------------------------------------------- + * void do_stack_maintenance(void) + * Do stack maintenance by flushing the used + * stack to the main memory and invalidating the + * remainder. + * --------------------------------------------- + */ +func do_stack_maintenance + push {r4, lr} + bl plat_get_my_stack + + /* Turn off the D-cache */ + ldcopr r1, SCTLR + bic r1, #SCTLR_C_BIT + stcopr r1, SCTLR + isb + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in r1. + * --------------------------------------------- + */ + mov r4, r0 + mov r1, sp + sub r1, r0, r1 + mov r0, sp + bl flush_dcache_range + + /* --------------------------------------------- + * Calculate and store the size of the unused + * stack memory in r1. Calculate and store the + * stack base address in r0. + * --------------------------------------------- + */ + sub r0, r4, #PLATFORM_STACK_SIZE + sub r1, sp, r0 + bl inv_dcache_range + + pop {r4, pc} +endfunc do_stack_maintenance + +/* ----------------------------------------------------------------------- + * This function is called to indicate to the power controller that it + * is safe to power down this cpu. It should not exit the wfi and will + * be released from reset upon power up. + * ----------------------------------------------------------------------- + */ +func psci_power_down_wfi + dsb sy // ensure write buffer empty + wfi + no_ret plat_panic_handler +endfunc psci_power_down_wfi diff --git a/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S b/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S new file mode 100644 index 0000000..add968a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S @@ -0,0 +1,130 @@ +/* + * Copyright (c) 2014-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .globl psci_do_pwrdown_cache_maintenance + .globl psci_do_pwrup_cache_maintenance + .globl psci_power_down_wfi + +/* ----------------------------------------------------------------------- + * void psci_do_pwrdown_cache_maintenance(unsigned int power level); + * + * This function performs cache maintenance for the specified power + * level. The levels of cache affected are determined by the power + * level which is passed as the argument i.e. level 0 results + * in a flush of the L1 cache. Both the L1 and L2 caches are flushed + * for a higher power level. + * + * Additionally, this function also ensures that stack memory is correctly + * flushed out to avoid coherency issues due to a change in its memory + * attributes after the data cache is disabled. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrdown_cache_maintenance + stp x29, x30, [sp,#-16]! + stp x19, x20, [sp,#-16]! + + /* --------------------------------------------- + * Invoke CPU-specific power down operations for + * the appropriate level + * --------------------------------------------- + */ + bl prepare_cpu_pwr_dwn + + /* --------------------------------------------- + * Do stack maintenance by flushing the used + * stack to the main memory and invalidating the + * remainder. + * --------------------------------------------- + */ + bl plat_get_my_stack + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in x1. + * --------------------------------------------- + */ + mov x19, x0 + mov x1, sp + sub x1, x0, x1 + mov x0, sp + bl flush_dcache_range + + /* --------------------------------------------- + * Calculate and store the size of the unused + * stack memory in x1. Calculate and store the + * stack base address in x0. + * --------------------------------------------- + */ + sub x0, x19, #PLATFORM_STACK_SIZE + sub x1, sp, x0 + bl inv_dcache_range + + ldp x19, x20, [sp], #16 + ldp x29, x30, [sp], #16 + ret +endfunc psci_do_pwrdown_cache_maintenance + + +/* ----------------------------------------------------------------------- + * void psci_do_pwrup_cache_maintenance(void); + * + * This function performs cache maintenance after this cpu is powered up. + * Currently, this involves managing the used stack memory before turning + * on the data cache. + * ----------------------------------------------------------------------- + */ +func psci_do_pwrup_cache_maintenance + stp x29, x30, [sp,#-16]! + + /* --------------------------------------------- + * Ensure any inflight stack writes have made it + * to main memory. + * --------------------------------------------- + */ + dmb st + + /* --------------------------------------------- + * Calculate and store the size of the used + * stack memory in x1. Calculate and store the + * stack base address in x0. + * --------------------------------------------- + */ + bl plat_get_my_stack + mov x1, sp + sub x1, x0, x1 + mov x0, sp + bl inv_dcache_range + + /* --------------------------------------------- + * Enable the data cache. + * --------------------------------------------- + */ + mrs x0, sctlr_el3 + orr x0, x0, #SCTLR_C_BIT + msr sctlr_el3, x0 + isb + + ldp x29, x30, [sp], #16 + ret +endfunc psci_do_pwrup_cache_maintenance + +/* ----------------------------------------------------------------------- + * void psci_power_down_wfi(void); + * This function is called to indicate to the power controller that it + * is safe to power down this cpu. It should not exit the wfi and will + * be released from reset upon power up. + * ----------------------------------------------------------------------- + */ +func psci_power_down_wfi + dsb sy // ensure write buffer empty + wfi + no_ret plat_panic_handler +endfunc psci_power_down_wfi diff --git a/arm-trusted-firmware/lib/psci/psci_common.c b/arm-trusted-firmware/lib/psci/psci_common.c new file mode 100644 index 0000000..b4a6897 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_common.c @@ -0,0 +1,1027 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/* + * SPD power management operations, expected to be supplied by the registered + * SPD on successful SP initialization + */ +const spd_pm_ops_t *psci_spd_pm; + +/* + * PSCI requested local power state map. This array is used to store the local + * power states requested by a CPU for power levels from level 1 to + * PLAT_MAX_PWR_LVL. It does not store the requested local power state for power + * level 0 (PSCI_CPU_PWR_LVL) as the requested and the target power state for a + * CPU are the same. + * + * During state coordination, the platform is passed an array containing the + * local states requested for a particular non cpu power domain by each cpu + * within the domain. + * + * TODO: Dense packing of the requested states will cause cache thrashing + * when multiple power domains write to it. If we allocate the requested + * states at each power level in a cache-line aligned per-domain memory, + * the cache thrashing can be avoided. + */ +static plat_local_state_t + psci_req_local_pwr_states[PLAT_MAX_PWR_LVL][PLATFORM_CORE_COUNT]; + +unsigned int psci_plat_core_count; + +/******************************************************************************* + * Arrays that hold the platform's power domain tree information for state + * management of power domains. + * Each node in the array 'psci_non_cpu_pd_nodes' corresponds to a power domain + * which is an ancestor of a CPU power domain. + * Each node in the array 'psci_cpu_pd_nodes' corresponds to a cpu power domain + ******************************************************************************/ +non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS] +#if USE_COHERENT_MEM +__section("tzfw_coherent_mem") +#endif +; + +/* Lock for PSCI state coordination */ +DEFINE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Pointer to functions exported by the platform to complete power mgmt. ops + ******************************************************************************/ +const plat_psci_ops_t *psci_plat_pm_ops; + +/****************************************************************************** + * Check that the maximum power level supported by the platform makes sense + *****************************************************************************/ +CASSERT((PLAT_MAX_PWR_LVL <= PSCI_MAX_PWR_LVL) && + (PLAT_MAX_PWR_LVL >= PSCI_CPU_PWR_LVL), + assert_platform_max_pwrlvl_check); + +/* + * The plat_local_state used by the platform is one of these types: RUN, + * RETENTION and OFF. The platform can define further sub-states for each type + * apart from RUN. This categorization is done to verify the sanity of the + * psci_power_state passed by the platform and to print debug information. The + * categorization is done on the basis of the following conditions: + * + * 1. If (plat_local_state == 0) then the category is STATE_TYPE_RUN. + * + * 2. If (0 < plat_local_state <= PLAT_MAX_RET_STATE), then the category is + * STATE_TYPE_RETN. + * + * 3. If (plat_local_state > PLAT_MAX_RET_STATE), then the category is + * STATE_TYPE_OFF. + */ +typedef enum plat_local_state_type { + STATE_TYPE_RUN = 0, + STATE_TYPE_RETN, + STATE_TYPE_OFF +} plat_local_state_type_t; + +/* Function used to categorize plat_local_state. */ +static plat_local_state_type_t find_local_state_type(plat_local_state_t state) +{ + if (state != 0U) { + if (state > PLAT_MAX_RET_STATE) { + return STATE_TYPE_OFF; + } else { + return STATE_TYPE_RETN; + } + } else { + return STATE_TYPE_RUN; + } +} + +/****************************************************************************** + * Check that the maximum retention level supported by the platform is less + * than the maximum off level. + *****************************************************************************/ +CASSERT(PLAT_MAX_RET_STATE < PLAT_MAX_OFF_STATE, + assert_platform_max_off_and_retn_state_check); + +/****************************************************************************** + * This function ensures that the power state parameter in a CPU_SUSPEND request + * is valid. If so, it returns the requested states for each power level. + *****************************************************************************/ +int psci_validate_power_state(unsigned int power_state, + psci_power_state_t *state_info) +{ + /* Check SBZ bits in power state are zero */ + if (psci_check_power_state(power_state) != 0U) + return PSCI_E_INVALID_PARAMS; + + assert(psci_plat_pm_ops->validate_power_state != NULL); + + /* Validate the power_state using platform pm_ops */ + return psci_plat_pm_ops->validate_power_state(power_state, state_info); +} + +/****************************************************************************** + * This function retrieves the `psci_power_state_t` for system suspend from + * the platform. + *****************************************************************************/ +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info) +{ + /* + * Assert that the required pm_ops hook is implemented to ensure that + * the capability detected during psci_setup() is valid. + */ + assert(psci_plat_pm_ops->get_sys_suspend_power_state != NULL); + + /* + * Query the platform for the power_state required for system suspend + */ + psci_plat_pm_ops->get_sys_suspend_power_state(state_info); +} + +/******************************************************************************* + * This function verifies that the all the other cores in the system have been + * turned OFF and the current CPU is the last running CPU in the system. + * Returns 1 (true) if the current CPU is the last ON CPU or 0 (false) + * otherwise. + ******************************************************************************/ +unsigned int psci_is_last_on_cpu(void) +{ + unsigned int cpu_idx, my_idx = plat_my_core_pos(); + + for (cpu_idx = 0; cpu_idx < psci_plat_core_count; + cpu_idx++) { + if (cpu_idx == my_idx) { + assert(psci_get_aff_info_state() == AFF_STATE_ON); + continue; + } + + if (psci_get_aff_info_state_by_idx(cpu_idx) != AFF_STATE_OFF) + return 0; + } + + return 1; +} + +/******************************************************************************* + * Routine to return the maximum power level to traverse to after a cpu has + * been physically powered up. It is expected to be called immediately after + * reset from assembler code. + ******************************************************************************/ +static unsigned int get_power_on_target_pwrlvl(void) +{ + unsigned int pwrlvl; + + /* + * Assume that this cpu was suspended and retrieve its target power + * level. If it is invalid then it could only have been turned off + * earlier. PLAT_MAX_PWR_LVL will be the highest power level a + * cpu can be turned off to. + */ + pwrlvl = psci_get_suspend_pwrlvl(); + if (pwrlvl == PSCI_INVALID_PWR_LVL) + pwrlvl = PLAT_MAX_PWR_LVL; + assert(pwrlvl < PSCI_INVALID_PWR_LVL); + return pwrlvl; +} + +/****************************************************************************** + * Helper function to update the requested local power state array. This array + * does not store the requested state for the CPU power level. Hence an + * assertion is added to prevent us from accessing the CPU power level. + *****************************************************************************/ +static void psci_set_req_local_pwr_state(unsigned int pwrlvl, + unsigned int cpu_idx, + plat_local_state_t req_pwr_state) +{ + assert(pwrlvl > PSCI_CPU_PWR_LVL); + if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) && + (cpu_idx < psci_plat_core_count)) { + psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx] = req_pwr_state; + } +} + +/****************************************************************************** + * This function initializes the psci_req_local_pwr_states. + *****************************************************************************/ +void __init psci_init_req_local_pwr_states(void) +{ + /* Initialize the requested state of all non CPU power domains as OFF */ + unsigned int pwrlvl; + unsigned int core; + + for (pwrlvl = 0U; pwrlvl < PLAT_MAX_PWR_LVL; pwrlvl++) { + for (core = 0; core < psci_plat_core_count; core++) { + psci_req_local_pwr_states[pwrlvl][core] = + PLAT_MAX_OFF_STATE; + } + } +} + +/****************************************************************************** + * Helper function to return a reference to an array containing the local power + * states requested by each cpu for a power domain at 'pwrlvl'. The size of the + * array will be the number of cpu power domains of which this power domain is + * an ancestor. These requested states will be used to determine a suitable + * target state for this power domain during psci state coordination. An + * assertion is added to prevent us from accessing the CPU power level. + *****************************************************************************/ +static plat_local_state_t *psci_get_req_local_pwr_states(unsigned int pwrlvl, + unsigned int cpu_idx) +{ + assert(pwrlvl > PSCI_CPU_PWR_LVL); + + if ((pwrlvl > PSCI_CPU_PWR_LVL) && (pwrlvl <= PLAT_MAX_PWR_LVL) && + (cpu_idx < psci_plat_core_count)) { + return &psci_req_local_pwr_states[pwrlvl - 1U][cpu_idx]; + } else + return NULL; +} + +/* + * psci_non_cpu_pd_nodes can be placed either in normal memory or coherent + * memory. + * + * With !USE_COHERENT_MEM, psci_non_cpu_pd_nodes is placed in normal memory, + * it's accessed by both cached and non-cached participants. To serve the common + * minimum, perform a cache flush before read and after write so that non-cached + * participants operate on latest data in main memory. + * + * When USE_COHERENT_MEM is used, psci_non_cpu_pd_nodes is placed in coherent + * memory. With HW_ASSISTED_COHERENCY, all PSCI participants are cache-coherent. + * In both cases, no cache operations are required. + */ + +/* + * Retrieve local state of non-CPU power domain node from a non-cached CPU, + * after any required cache maintenance operation. + */ +static plat_local_state_t get_non_cpu_pd_node_local_state( + unsigned int parent_idx) +{ +#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range( + (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx], + sizeof(psci_non_cpu_pd_nodes[parent_idx])); +#endif + return psci_non_cpu_pd_nodes[parent_idx].local_state; +} + +/* + * Update local state of non-CPU power domain node from a cached CPU; perform + * any required cache maintenance operation afterwards. + */ +static void set_non_cpu_pd_node_local_state(unsigned int parent_idx, + plat_local_state_t state) +{ + psci_non_cpu_pd_nodes[parent_idx].local_state = state; +#if !(USE_COHERENT_MEM || HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + flush_dcache_range( + (uintptr_t) &psci_non_cpu_pd_nodes[parent_idx], + sizeof(psci_non_cpu_pd_nodes[parent_idx])); +#endif +} + +/****************************************************************************** + * Helper function to return the current local power state of each power domain + * from the current cpu power domain to its ancestor at the 'end_pwrlvl'. This + * function will be called after a cpu is powered on to find the local state + * each power domain has emerged from. + *****************************************************************************/ +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state) +{ + unsigned int parent_idx, lvl; + plat_local_state_t *pd_state = target_state->pwr_domain_state; + + pd_state[PSCI_CPU_PWR_LVL] = psci_get_cpu_local_state(); + parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node; + + /* Copy the local power state from node to state_info */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + pd_state[lvl] = get_non_cpu_pd_node_local_state(parent_idx); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* Set the the higher levels to RUN */ + for (; lvl <= PLAT_MAX_PWR_LVL; lvl++) + target_state->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN; +} + +/****************************************************************************** + * Helper function to set the target local power state that each power domain + * from the current cpu power domain to its ancestor at the 'end_pwrlvl' will + * enter. This function will be called after coordination of requested power + * states has been done for each power level. + *****************************************************************************/ +static void psci_set_target_local_pwr_states(unsigned int end_pwrlvl, + const psci_power_state_t *target_state) +{ + unsigned int parent_idx, lvl; + const plat_local_state_t *pd_state = target_state->pwr_domain_state; + + psci_set_cpu_local_state(pd_state[PSCI_CPU_PWR_LVL]); + + /* + * Need to flush as local_state might be accessed with Data Cache + * disabled during power on + */ + psci_flush_cpu_data(psci_svc_cpu_data.local_state); + + parent_idx = psci_cpu_pd_nodes[plat_my_core_pos()].parent_node; + + /* Copy the local_state from state_info */ + for (lvl = 1U; lvl <= end_pwrlvl; lvl++) { + set_non_cpu_pd_node_local_state(parent_idx, pd_state[lvl]); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } +} + + +/******************************************************************************* + * PSCI helper function to get the parent nodes corresponding to a cpu_index. + ******************************************************************************/ +void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, + unsigned int end_lvl, + unsigned int *node_index) +{ + unsigned int parent_node = psci_cpu_pd_nodes[cpu_idx].parent_node; + unsigned int i; + unsigned int *node = node_index; + + for (i = PSCI_CPU_PWR_LVL + 1U; i <= end_lvl; i++) { + *node = parent_node; + node++; + parent_node = psci_non_cpu_pd_nodes[parent_node].parent_node; + } +} + +/****************************************************************************** + * This function is invoked post CPU power up and initialization. It sets the + * affinity info state, target power state and requested power state for the + * current CPU and all its ancestor power domains to RUN. + *****************************************************************************/ +void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl) +{ + unsigned int parent_idx, cpu_idx = plat_my_core_pos(), lvl; + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + /* Reset the local_state to RUN for the non cpu power domains. */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + set_non_cpu_pd_node_local_state(parent_idx, + PSCI_LOCAL_STATE_RUN); + psci_set_req_local_pwr_state(lvl, + cpu_idx, + PSCI_LOCAL_STATE_RUN); + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* Set the affinity info state to ON */ + psci_set_aff_info_state(AFF_STATE_ON); + + psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN); + psci_flush_cpu_data(psci_svc_cpu_data); +} + +/****************************************************************************** + * This function is passed the local power states requested for each power + * domain (state_info) between the current CPU domain and its ancestors until + * the target power level (end_pwrlvl). It updates the array of requested power + * states with this information. + * + * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it + * retrieves the states requested by all the cpus of which the power domain at + * that level is an ancestor. It passes this information to the platform to + * coordinate and return the target power state. If the target state for a level + * is RUN then subsequent levels are not considered. At the CPU level, state + * coordination is not required. Hence, the requested and the target states are + * the same. + * + * The 'state_info' is updated with the target state for each level between the + * CPU and the 'end_pwrlvl' and returned to the caller. + * + * This function will only be invoked with data cache enabled and while + * powering down a core. + *****************************************************************************/ +void psci_do_state_coordination(unsigned int end_pwrlvl, + psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx, cpu_idx = plat_my_core_pos(); + unsigned int start_idx; + unsigned int ncpus; + plat_local_state_t target_state, *req_states; + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + /* For level 0, the requested state will be equivalent + to target state */ + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + + /* First update the requested power state */ + psci_set_req_local_pwr_state(lvl, cpu_idx, + state_info->pwr_domain_state[lvl]); + + /* Get the requested power states for this power level */ + start_idx = psci_non_cpu_pd_nodes[parent_idx].cpu_start_idx; + req_states = psci_get_req_local_pwr_states(lvl, start_idx); + + /* + * Let the platform coordinate amongst the requested states at + * this power level and return the target local power state. + */ + ncpus = psci_non_cpu_pd_nodes[parent_idx].ncpus; + target_state = plat_get_target_pwr_state(lvl, + req_states, + ncpus); + + state_info->pwr_domain_state[lvl] = target_state; + + /* Break early if the negotiated target power state is RUN */ + if (is_local_state_run(state_info->pwr_domain_state[lvl]) != 0) + break; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + + /* + * This is for cases when we break out of the above loop early because + * the target power state is RUN at a power level < end_pwlvl. + * We update the requested power state from state_info and then + * set the target state as RUN. + */ + for (lvl = lvl + 1U; lvl <= end_pwrlvl; lvl++) { + psci_set_req_local_pwr_state(lvl, cpu_idx, + state_info->pwr_domain_state[lvl]); + state_info->pwr_domain_state[lvl] = PSCI_LOCAL_STATE_RUN; + + } + + /* Update the target state in the power domain nodes */ + psci_set_target_local_pwr_states(end_pwrlvl, state_info); +} + +/****************************************************************************** + * This function validates a suspend request by making sure that if a standby + * state is requested then no power level is turned off and the highest power + * level is placed in a standby/retention state. + * + * It also ensures that the state level X will enter is not shallower than the + * state level X + 1 will enter. + * + * This validation will be enabled only for DEBUG builds as the platform is + * expected to perform these validations as well. + *****************************************************************************/ +int psci_validate_suspend_req(const psci_power_state_t *state_info, + unsigned int is_power_down_state) +{ + unsigned int max_off_lvl, target_lvl, max_retn_lvl; + plat_local_state_t state; + plat_local_state_type_t req_state_type, deepest_state_type; + int i; + + /* Find the target suspend power level */ + target_lvl = psci_find_target_suspend_lvl(state_info); + if (target_lvl == PSCI_INVALID_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* All power domain levels are in a RUN state to begin with */ + deepest_state_type = STATE_TYPE_RUN; + + for (i = (int) target_lvl; i >= (int) PSCI_CPU_PWR_LVL; i--) { + state = state_info->pwr_domain_state[i]; + req_state_type = find_local_state_type(state); + + /* + * While traversing from the highest power level to the lowest, + * the state requested for lower levels has to be the same or + * deeper i.e. equal to or greater than the state at the higher + * levels. If this condition is true, then the requested state + * becomes the deepest state encountered so far. + */ + if (req_state_type < deepest_state_type) + return PSCI_E_INVALID_PARAMS; + deepest_state_type = req_state_type; + } + + /* Find the highest off power level */ + max_off_lvl = psci_find_max_off_lvl(state_info); + + /* The target_lvl is either equal to the max_off_lvl or max_retn_lvl */ + max_retn_lvl = PSCI_INVALID_PWR_LVL; + if (target_lvl != max_off_lvl) + max_retn_lvl = target_lvl; + + /* + * If this is not a request for a power down state then max off level + * has to be invalid and max retention level has to be a valid power + * level. + */ + if ((is_power_down_state == 0U) && + ((max_off_lvl != PSCI_INVALID_PWR_LVL) || + (max_retn_lvl == PSCI_INVALID_PWR_LVL))) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/****************************************************************************** + * This function finds the highest power level which will be powered down + * amongst all the power levels specified in the 'state_info' structure + *****************************************************************************/ +unsigned int psci_find_max_off_lvl(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_off(state_info->pwr_domain_state[i]) != 0) + return (unsigned int) i; + } + + return PSCI_INVALID_PWR_LVL; +} + +/****************************************************************************** + * This functions finds the level of the highest power domain which will be + * placed in a low power state during a suspend operation. + *****************************************************************************/ +unsigned int psci_find_target_suspend_lvl(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; +} + +/******************************************************************************* + * This function is passed the highest level in the topology tree that the + * operation should be applied to and a list of node indexes. It picks up locks + * from the node index list in order of increasing power domain level in the + * range specified. + ******************************************************************************/ +void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes) +{ + unsigned int parent_idx; + unsigned int level; + + /* No locking required for level 0. Hence start locking from level 1 */ + for (level = PSCI_CPU_PWR_LVL + 1U; level <= end_pwrlvl; level++) { + parent_idx = parent_nodes[level - 1U]; + psci_lock_get(&psci_non_cpu_pd_nodes[parent_idx]); + } +} + +/******************************************************************************* + * This function is passed the highest level in the topology tree that the + * operation should be applied to and a list of node indexes. It releases the + * locks in order of decreasing power domain level in the range specified. + ******************************************************************************/ +void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes) +{ + unsigned int parent_idx; + unsigned int level; + + /* Unlock top down. No unlocking required for level 0. */ + for (level = end_pwrlvl; level >= (PSCI_CPU_PWR_LVL + 1U); level--) { + parent_idx = parent_nodes[level - 1U]; + psci_lock_release(&psci_non_cpu_pd_nodes[parent_idx]); + } + + flush_dcache_range((uint64_t)psci_non_cpu_pd_nodes, + sizeof(non_cpu_pd_node_t) * PLATFORM_CORE_COUNT); +} + +/******************************************************************************* + * Simple routine to determine whether a mpidr is valid or not. + ******************************************************************************/ +int psci_validate_mpidr(u_register_t mpidr) +{ + if (plat_core_pos_by_mpidr(mpidr) < 0) + return PSCI_E_INVALID_PARAMS; + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * This function determines the full entrypoint information for the requested + * PSCI entrypoint on power on/resume and returns it. + ******************************************************************************/ +#ifdef __aarch64__ +static int psci_get_ns_ep_info(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + u_register_t ep_attr, sctlr; + unsigned int daif, ee, mode; + u_register_t ns_scr_el3 = read_scr_el3(); + u_register_t ns_sctlr_el1 = read_sctlr_el1(); + + sctlr = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? + read_sctlr_el2() : ns_sctlr_el1; + ee = 0; + + ep_attr = NON_SECURE | EP_ST_DISABLE; + if ((sctlr & SCTLR_EE_BIT) != 0U) { + ep_attr |= EP_EE_BIG; + ee = 1; + } + SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr); + + ep->pc = entrypoint; + zeromem(&ep->args, sizeof(ep->args)); + ep->args.arg0 = context_id; + + /* + * Figure out whether the cpu enters the non-secure address space + * in aarch32 or aarch64 + */ + if ((ns_scr_el3 & SCR_RW_BIT) != 0U) { + + /* + * Check whether a Thumb entry point has been provided for an + * aarch64 EL + */ + if ((entrypoint & 0x1UL) != 0UL) + return PSCI_E_INVALID_ADDRESS; + + mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? MODE_EL2 : MODE_EL1; + + ep->spsr = SPSR_64((uint64_t)mode, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } else { + + mode = ((ns_scr_el3 & SCR_HCE_BIT) != 0U) ? + MODE32_hyp : MODE32_svc; + + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT; + + ep->spsr = SPSR_MODE32((uint64_t)mode, entrypoint & 0x1, ee, + daif); + } + + return PSCI_E_SUCCESS; +} +#else /* !__aarch64__ */ +static int psci_get_ns_ep_info(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + u_register_t ep_attr; + unsigned int aif, ee, mode; + u_register_t scr = read_scr(); + u_register_t ns_sctlr, sctlr; + + /* Switch to non secure state */ + write_scr(scr | SCR_NS_BIT); + isb(); + ns_sctlr = read_sctlr(); + + sctlr = scr & SCR_HCE_BIT ? read_hsctlr() : ns_sctlr; + + /* Return to original state */ + write_scr(scr); + isb(); + ee = 0; + + ep_attr = NON_SECURE | EP_ST_DISABLE; + if (sctlr & SCTLR_EE_BIT) { + ep_attr |= EP_EE_BIG; + ee = 1; + } + SET_PARAM_HEAD(ep, PARAM_EP, VERSION_1, ep_attr); + + ep->pc = entrypoint; + zeromem(&ep->args, sizeof(ep->args)); + ep->args.arg0 = context_id; + + mode = scr & SCR_HCE_BIT ? MODE32_hyp : MODE32_svc; + + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + aif = SPSR_ABT_BIT | SPSR_IRQ_BIT | SPSR_FIQ_BIT; + + ep->spsr = SPSR_MODE32(mode, entrypoint & 0x1, ee, aif); + + return PSCI_E_SUCCESS; +} + +#endif /* __aarch64__ */ + +/******************************************************************************* + * This function validates the entrypoint with the platform layer if the + * appropriate pm_ops hook is exported by the platform and returns the + * 'entry_point_info'. + ******************************************************************************/ +int psci_validate_entry_point(entry_point_info_t *ep, + uintptr_t entrypoint, + u_register_t context_id) +{ + int rc; + + /* Validate the entrypoint using platform psci_ops */ + if (psci_plat_pm_ops->validate_ns_entrypoint != NULL) { + rc = psci_plat_pm_ops->validate_ns_entrypoint(entrypoint); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_ADDRESS; + } + + /* + * Verify and derive the re-entry information for + * the non-secure world from the non-secure state from + * where this call originated. + */ + rc = psci_get_ns_ep_info(ep, entrypoint, context_id); + return rc; +} + +/******************************************************************************* + * Generic handler which is called when a cpu is physically powered on. It + * traverses the node information and finds the highest power level powered + * off and performs generic, architectural, platform setup and state management + * to power on that power level and power levels below it. + * e.g. For a cpu that's been powered on, it will call the platform specific + * code to enable the gic cpu interface and for a cluster it will enable + * coherency at the interconnect level in addition to gic cpu interface. + ******************************************************************************/ +void psci_warmboot_entrypoint(void) +{ + unsigned int end_pwrlvl; + unsigned int cpu_idx = plat_my_core_pos(); + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + + /* + * Verify that we have been explicitly turned ON or resumed from + * suspend. + */ + if (psci_get_aff_info_state() == AFF_STATE_OFF) { + ERROR("Unexpected affinity info state.\n"); + panic(); + } + + /* + * Get the maximum power domain level to traverse to after this cpu + * has been physically powered up. + */ + end_pwrlvl = get_power_on_target_pwrlvl(); + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power level so + * that by the time all locks are taken, the system topology is snapshot + * and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); +#endif + + /* + * This CPU could be resuming from suspend or it could have just been + * turned on. To distinguish between these 2 cases, we examine the + * affinity state of the CPU: + * - If the affinity state is ON_PENDING then it has just been + * turned on. + * - Else it is resuming from suspend. + * + * Depending on the type of warm reset identified, choose the right set + * of power management handler and perform the generic, architecture + * and platform specific handling. + */ + if (psci_get_aff_info_state() == AFF_STATE_ON_PENDING) + psci_cpu_on_finish(cpu_idx, &state_info); + else + psci_cpu_suspend_finish(cpu_idx, &state_info); + + /* + * Set the requested and target state of this CPU and all the higher + * power domains which are ancestors of this CPU to run. + */ + psci_set_pwr_domains_to_run(end_pwrlvl); + +#if ENABLE_PSCI_STAT + /* + * Update PSCI stats. + * Caches are off when writing stats data on the power down path. + * Since caches are now enabled, it's necessary to do cache + * maintenance before reading that same data. + */ + psci_stats_update_pwr_up(end_pwrlvl, &state_info); +#endif + + /* + * This loop releases the lock corresponding to each power level + * in the reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); +} + +/******************************************************************************* + * This function initializes the set of hooks that PSCI invokes as part of power + * management operation. The power management hooks are expected to be provided + * by the SPD, after it finishes all its initialization + ******************************************************************************/ +void psci_register_spd_pm_hook(const spd_pm_ops_t *pm) +{ + assert(pm != NULL); + psci_spd_pm = pm; + + if (pm->svc_migrate != NULL) + psci_caps |= define_psci_cap(PSCI_MIG_AARCH64); + + if (pm->svc_migrate_info != NULL) + psci_caps |= define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) + | define_psci_cap(PSCI_MIG_INFO_TYPE); +} + +/******************************************************************************* + * This function invokes the migrate info hook in the spd_pm_ops. It performs + * the necessary return value validation. If the Secure Payload is UP and + * migrate capable, it returns the mpidr of the CPU on which the Secure payload + * is resident through the mpidr parameter. Else the value of the parameter on + * return is undefined. + ******************************************************************************/ +int psci_spd_migrate_info(u_register_t *mpidr) +{ + int rc; + + if ((psci_spd_pm == NULL) || (psci_spd_pm->svc_migrate_info == NULL)) + return PSCI_E_NOT_SUPPORTED; + + rc = psci_spd_pm->svc_migrate_info(mpidr); + + assert((rc == PSCI_TOS_UP_MIG_CAP) || (rc == PSCI_TOS_NOT_UP_MIG_CAP) || + (rc == PSCI_TOS_NOT_PRESENT_MP) || (rc == PSCI_E_NOT_SUPPORTED)); + + return rc; +} + + +/******************************************************************************* + * This function prints the state of all power domains present in the + * system + ******************************************************************************/ +void psci_print_power_domain_map(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_INFO + unsigned int idx; + plat_local_state_t state; + plat_local_state_type_t state_type; + + /* This array maps to the PSCI_STATE_X definitions in psci.h */ + static const char * const psci_state_type_str[] = { + "ON", + "RETENTION", + "OFF", + }; + + INFO("PSCI Power Domain Map:\n"); + for (idx = 0; idx < (PSCI_NUM_PWR_DOMAINS - psci_plat_core_count); + idx++) { + state_type = find_local_state_type( + psci_non_cpu_pd_nodes[idx].local_state); + INFO(" Domain Node : Level %u, parent_node %u," + " State %s (0x%x)\n", + psci_non_cpu_pd_nodes[idx].level, + psci_non_cpu_pd_nodes[idx].parent_node, + psci_state_type_str[state_type], + psci_non_cpu_pd_nodes[idx].local_state); + } + + for (idx = 0; idx < psci_plat_core_count; idx++) { + state = psci_get_cpu_local_state_by_idx(idx); + state_type = find_local_state_type(state); + INFO(" CPU Node : MPID 0x%llx, parent_node %u," + " State %s (0x%x)\n", + (unsigned long long)psci_cpu_pd_nodes[idx].mpidr, + psci_cpu_pd_nodes[idx].parent_node, + psci_state_type_str[state_type], + psci_get_cpu_local_state_by_idx(idx)); + } +#endif +} + +/****************************************************************************** + * Return whether any secondaries were powered up with CPU_ON call. A CPU that + * have ever been powered up would have set its MPDIR value to something other + * than PSCI_INVALID_MPIDR. Note that MPDIR isn't reset back to + * PSCI_INVALID_MPIDR when a CPU is powered down later, so the return value is + * meaningful only when called on the primary CPU during early boot. + *****************************************************************************/ +int psci_secondaries_brought_up(void) +{ + unsigned int idx, n_valid = 0U; + + for (idx = 0U; idx < ARRAY_SIZE(psci_cpu_pd_nodes); idx++) { + if (psci_cpu_pd_nodes[idx].mpidr != PSCI_INVALID_MPIDR) + n_valid++; + } + + assert(n_valid > 0U); + + return (n_valid > 1U) ? 1 : 0; +} + +/******************************************************************************* + * Initiate power down sequence, by calling power down operations registered for + * this CPU. + ******************************************************************************/ +void psci_do_pwrdown_sequence(unsigned int power_level) +{ +#if HW_ASSISTED_COHERENCY + /* + * With hardware-assisted coherency, the CPU drivers only initiate the + * power down sequence, without performing cache-maintenance operations + * in software. Data caches enabled both before and after this call. + */ + prepare_cpu_pwr_dwn(power_level); +#else + /* + * Without hardware-assisted coherency, the CPU drivers disable data + * caches, then perform cache-maintenance operations in software. + * + * This also calls prepare_cpu_pwr_dwn() to initiate power down + * sequence, but that function will return with data caches disabled. + * We must ensure that the stack memory is flushed out to memory before + * we start popping from it again. + */ + psci_do_pwrdown_cache_maintenance(power_level); +#endif +} + +/******************************************************************************* + * This function invokes the callback 'stop_func()' with the 'mpidr' of each + * online PE. Caller can pass suitable method to stop a remote core. + * + * 'wait_ms' is the timeout value in milliseconds for the other cores to + * transition to power down state. Passing '0' makes it non-blocking. + * + * The function returns 'PSCI_E_DENIED' if some cores failed to stop within the + * given timeout. + ******************************************************************************/ +int psci_stop_other_cores(unsigned int wait_ms, + void (*stop_func)(u_register_t mpidr)) +{ + unsigned int idx, this_cpu_idx; + + this_cpu_idx = plat_my_core_pos(); + + /* Invoke stop_func for each core */ + for (idx = 0U; idx < psci_plat_core_count; idx++) { + /* skip current CPU */ + if (idx == this_cpu_idx) { + continue; + } + + /* Check if the CPU is ON */ + if (psci_get_aff_info_state_by_idx(idx) == AFF_STATE_ON) { + (*stop_func)(psci_cpu_pd_nodes[idx].mpidr); + } + } + + /* Need to wait for other cores to shutdown */ + if (wait_ms != 0U) { + while ((wait_ms-- != 0U) && (psci_is_last_on_cpu() != 0U)) { + mdelay(1U); + } + + if (psci_is_last_on_cpu() != 0U) { + WARN("Failed to stop all cores!\n"); + psci_print_power_domain_map(); + return PSCI_E_DENIED; + } + } + + return PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/lib/psci/psci_lib.mk b/arm-trusted-firmware/lib/psci/psci_lib.mk new file mode 100644 index 0000000..1d4aac4 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_lib.mk @@ -0,0 +1,35 @@ +# +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PSCI_LIB_SOURCES := lib/el3_runtime/cpu_data_array.c \ + lib/el3_runtime/${ARCH}/cpu_data.S \ + lib/el3_runtime/${ARCH}/context_mgmt.c \ + lib/cpus/${ARCH}/cpu_helpers.S \ + lib/cpus/errata_report.c \ + lib/locks/exclusive/${ARCH}/spinlock.S \ + lib/psci/psci_off.c \ + lib/psci/psci_on.c \ + lib/psci/psci_suspend.c \ + lib/psci/psci_common.c \ + lib/psci/psci_main.c \ + lib/psci/psci_setup.c \ + lib/psci/psci_system_off.c \ + lib/psci/psci_mem_protect.c \ + lib/psci/${ARCH}/psci_helpers.S + +ifeq (${ARCH}, aarch64) +PSCI_LIB_SOURCES += lib/el3_runtime/aarch64/context.S +endif + +ifeq (${USE_COHERENT_MEM}, 1) +PSCI_LIB_SOURCES += lib/locks/bakery/bakery_lock_coherent.c +else +PSCI_LIB_SOURCES += lib/locks/bakery/bakery_lock_normal.c +endif + +ifeq (${ENABLE_PSCI_STAT}, 1) +PSCI_LIB_SOURCES += lib/psci/psci_stat.c +endif diff --git a/arm-trusted-firmware/lib/psci/psci_main.c b/arm-trusted-firmware/lib/psci/psci_main.c new file mode 100644 index 0000000..52a8b8a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_main.c @@ -0,0 +1,545 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/******************************************************************************* + * PSCI frontend api for servicing SMCs. Described in the PSCI spec. + ******************************************************************************/ +int psci_cpu_on(u_register_t target_cpu, + uintptr_t entrypoint, + u_register_t context_id) + +{ + int rc; + entry_point_info_t ep; + + /* Determine if the cpu exists of not */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + + /* + * To turn this cpu on, specify which power + * levels need to be turned on + */ + return psci_cpu_on_start(target_cpu, &ep); +} + +unsigned int psci_version(void) +{ + return PSCI_MAJOR_VER | PSCI_MINOR_VER; +} + +int psci_cpu_suspend(unsigned int power_state, + uintptr_t entrypoint, + u_register_t context_id) +{ + int rc; + unsigned int target_pwrlvl, is_power_down_state; + entry_point_info_t ep; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + plat_local_state_t cpu_pd_state; + + /* Validate the power_state parameter */ + rc = psci_validate_power_state(power_state, &state_info); + if (rc != PSCI_E_SUCCESS) { + assert(rc == PSCI_E_INVALID_PARAMS); + return rc; + } + + /* + * Get the value of the state type bit from the power state parameter. + */ + is_power_down_state = psci_get_pstate_type(power_state); + + /* Sanity check the requested suspend levels */ + assert(psci_validate_suspend_req(&state_info, is_power_down_state) + == PSCI_E_SUCCESS); + + target_pwrlvl = psci_find_target_suspend_lvl(&state_info); + if (target_pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for suspend operation\n"); + panic(); + } + + /* Fast path for CPU standby.*/ + if (is_cpu_standby_req(is_power_down_state, target_pwrlvl)) { + if (psci_plat_pm_ops->cpu_standby == NULL) + return PSCI_E_INVALID_PARAMS; + + /* + * Set the state of the CPU power domain to the platform + * specific retention state and enter the standby state. + */ + cpu_pd_state = state_info.pwr_domain_state[PSCI_CPU_PWR_LVL]; + psci_set_cpu_local_state(cpu_pd_state); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(&state_info); +#endif + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + psci_plat_pm_ops->cpu_standby(cpu_pd_state); + + /* Upon exit from standby, set the state back to RUN. */ + psci_set_cpu_local_state(PSCI_LOCAL_STATE_RUN); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); + + /* Update PSCI stats */ + psci_stats_update_pwr_up(PSCI_CPU_PWR_LVL, &state_info); +#endif + + return PSCI_E_SUCCESS; + } + + /* + * If a power down state has been requested, we need to verify entry + * point and program entry information. + */ + if (is_power_down_state != 0U) { + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + } + + /* + * Do what is needed to enter the power down state. Upon success, + * enter the final wfi which will power down this CPU. This function + * might return if the power down was abandoned for any reason, e.g. + * arrival of an interrupt + */ + psci_cpu_suspend_start(&ep, + target_pwrlvl, + &state_info, + is_power_down_state); + + return PSCI_E_SUCCESS; +} + + +int psci_system_suspend(uintptr_t entrypoint, u_register_t context_id) +{ + int rc; + psci_power_state_t state_info; + entry_point_info_t ep; + + /* Check if the current CPU is the last ON CPU in the system */ + if (psci_is_last_on_cpu() == 0U) + return PSCI_E_DENIED; + + /* Validate the entry point and get the entry_point_info */ + rc = psci_validate_entry_point(&ep, entrypoint, context_id); + if (rc != PSCI_E_SUCCESS) + return rc; + + /* Query the psci_power_state for system suspend */ + psci_query_sys_suspend_pwrstate(&state_info); + + /* + * Check if platform allows suspend to Highest power level + * (System level) + */ + if (psci_find_target_suspend_lvl(&state_info) < PLAT_MAX_PWR_LVL) + return PSCI_E_DENIED; + + /* Ensure that the psci_power_state makes sense */ + assert(psci_validate_suspend_req(&state_info, PSTATE_TYPE_POWERDOWN) + == PSCI_E_SUCCESS); + assert(is_local_state_off( + state_info.pwr_domain_state[PLAT_MAX_PWR_LVL]) != 0); + + /* + * Do what is needed to enter the system suspend state. This function + * might return if the power down was abandoned for any reason, e.g. + * arrival of an interrupt + */ + psci_cpu_suspend_start(&ep, + PLAT_MAX_PWR_LVL, + &state_info, + PSTATE_TYPE_POWERDOWN); + + return PSCI_E_SUCCESS; +} + +int psci_cpu_off(void) +{ + int rc; + unsigned int target_pwrlvl = PLAT_MAX_PWR_LVL; + + /* + * Do what is needed to power off this CPU and possible higher power + * levels if it able to do so. Upon success, enter the final wfi + * which will power down this CPU. + */ + rc = psci_do_cpu_off(target_pwrlvl); + + /* + * The only error cpu_off can return is E_DENIED. So check if that's + * indeed the case. + */ + assert(rc == PSCI_E_DENIED); + + return rc; +} + +int psci_affinity_info(u_register_t target_affinity, + unsigned int lowest_affinity_level) +{ + int ret; + unsigned int target_idx; + + /* We dont support level higher than PSCI_CPU_PWR_LVL */ + if (lowest_affinity_level > PSCI_CPU_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* Calculate the cpu index of the target */ + ret = plat_core_pos_by_mpidr(target_affinity); + if (ret == -1) { + return PSCI_E_INVALID_PARAMS; + } + target_idx = (unsigned int)ret; + + /* + * Generic management: + * Perform cache maintanence ahead of reading the target CPU state to + * ensure that the data is not stale. + * There is a theoretical edge case where the cache may contain stale + * data for the target CPU data - this can occur under the following + * conditions: + * - the target CPU is in another cluster from the current + * - the target CPU was the last CPU to shutdown on its cluster + * - the cluster was removed from coherency as part of the CPU shutdown + * + * In this case the cache maintenace that was performed as part of the + * target CPUs shutdown was not seen by the current CPU's cluster. And + * so the cache may contain stale data for the target CPU. + */ + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + return psci_get_aff_info_state_by_idx(target_idx); +} + +int psci_migrate(u_register_t target_cpu) +{ + int rc; + u_register_t resident_cpu_mpidr; + + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if (rc != PSCI_TOS_UP_MIG_CAP) + return (rc == PSCI_TOS_NOT_UP_MIG_CAP) ? + PSCI_E_DENIED : PSCI_E_NOT_SUPPORTED; + + /* + * Migrate should only be invoked on the CPU where + * the Secure OS is resident. + */ + if (resident_cpu_mpidr != read_mpidr_el1()) + return PSCI_E_NOT_PRESENT; + + /* Check the validity of the specified target cpu */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + assert((psci_spd_pm != NULL) && (psci_spd_pm->svc_migrate != NULL)); + + rc = psci_spd_pm->svc_migrate(read_mpidr_el1(), target_cpu); + assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL)); + + return rc; +} + +int psci_migrate_info_type(void) +{ + u_register_t resident_cpu_mpidr; + + return psci_spd_migrate_info(&resident_cpu_mpidr); +} + +u_register_t psci_migrate_info_up_cpu(void) +{ + u_register_t resident_cpu_mpidr; + int rc; + + /* + * Return value of this depends upon what + * psci_spd_migrate_info() returns. + */ + rc = psci_spd_migrate_info(&resident_cpu_mpidr); + if ((rc != PSCI_TOS_NOT_UP_MIG_CAP) && (rc != PSCI_TOS_UP_MIG_CAP)) + return (u_register_t)(register_t) PSCI_E_INVALID_PARAMS; + + return resident_cpu_mpidr; +} + +int psci_node_hw_state(u_register_t target_cpu, + unsigned int power_level) +{ + int rc; + + /* Validate target_cpu */ + rc = psci_validate_mpidr(target_cpu); + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Validate power_level against PLAT_MAX_PWR_LVL */ + if (power_level > PLAT_MAX_PWR_LVL) + return PSCI_E_INVALID_PARAMS; + + /* + * Dispatch this call to platform to query power controller, and pass on + * to the caller what it returns + */ + assert(psci_plat_pm_ops->get_node_hw_state != NULL); + rc = psci_plat_pm_ops->get_node_hw_state(target_cpu, power_level); + assert(((rc >= HW_ON) && (rc <= HW_STANDBY)) + || (rc == PSCI_E_NOT_SUPPORTED) + || (rc == PSCI_E_INVALID_PARAMS)); + return rc; +} + +int psci_features(unsigned int psci_fid) +{ + unsigned int local_caps = psci_caps; + + if (psci_fid == SMCCC_VERSION) + return PSCI_E_SUCCESS; + + /* Check if it is a 64 bit function */ + if (((psci_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_64) + local_caps &= PSCI_CAP_64BIT_MASK; + + /* Check for invalid fid */ + if (!(is_std_svc_call(psci_fid) && is_valid_fast_smc(psci_fid) + && is_psci_fid(psci_fid))) + return PSCI_E_NOT_SUPPORTED; + + + /* Check if the psci fid is supported or not */ + if ((local_caps & define_psci_cap(psci_fid)) == 0U) + return PSCI_E_NOT_SUPPORTED; + + /* Format the feature flags */ + if ((psci_fid == PSCI_CPU_SUSPEND_AARCH32) || + (psci_fid == PSCI_CPU_SUSPEND_AARCH64)) { + /* + * The trusted firmware does not support OS Initiated Mode. + */ + unsigned int ret = ((FF_PSTATE << FF_PSTATE_SHIFT) | + (((FF_SUPPORTS_OS_INIT_MODE == 1U) ? 0U : 1U) + << FF_MODE_SUPPORT_SHIFT)); + return (int) ret; + } + + /* Return 0 for all other fid's */ + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * PSCI top level handler for servicing SMCs. + ******************************************************************************/ +u_register_t psci_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; + + if (is_caller_secure(flags)) + return (u_register_t)SMC_UNK; + + /* Check the fid against the capabilities */ + if ((psci_caps & define_psci_cap(smc_fid)) == 0U) + return (u_register_t)SMC_UNK; + + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + /* 32-bit PSCI function, clear top parameter bits */ + + uint32_t r1 = (uint32_t)x1; + uint32_t r2 = (uint32_t)x2; + uint32_t r3 = (uint32_t)x3; + + switch (smc_fid) { + case PSCI_VERSION: + ret = (u_register_t)psci_version(); + break; + + case PSCI_CPU_OFF: + ret = (u_register_t)psci_cpu_off(); + break; + + case PSCI_CPU_SUSPEND_AARCH32: + ret = (u_register_t)psci_cpu_suspend(r1, r2, r3); + break; + + case PSCI_CPU_ON_AARCH32: + ret = (u_register_t)psci_cpu_on(r1, r2, r3); + break; + + case PSCI_AFFINITY_INFO_AARCH32: + ret = (u_register_t)psci_affinity_info(r1, r2); + break; + + case PSCI_MIG_AARCH32: + ret = (u_register_t)psci_migrate(r1); + break; + + case PSCI_MIG_INFO_TYPE: + ret = (u_register_t)psci_migrate_info_type(); + break; + + case PSCI_MIG_INFO_UP_CPU_AARCH32: + ret = psci_migrate_info_up_cpu(); + break; + + case PSCI_NODE_HW_STATE_AARCH32: + ret = (u_register_t)psci_node_hw_state(r1, r2); + break; + + case PSCI_SYSTEM_SUSPEND_AARCH32: + ret = (u_register_t)psci_system_suspend(r1, r2); + break; + + case PSCI_SYSTEM_OFF: + psci_system_off(); + /* We should never return from psci_system_off() */ + break; + + case PSCI_SYSTEM_RESET: + psci_system_reset(); + /* We should never return from psci_system_reset() */ + break; + + case PSCI_FEATURES: + ret = (u_register_t)psci_features(r1); + break; + +#if ENABLE_PSCI_STAT + case PSCI_STAT_RESIDENCY_AARCH32: + ret = psci_stat_residency(r1, r2); + break; + + case PSCI_STAT_COUNT_AARCH32: + ret = psci_stat_count(r1, r2); + break; +#endif + case PSCI_MEM_PROTECT: + ret = psci_mem_protect(r1); + break; + + case PSCI_MEM_CHK_RANGE_AARCH32: + ret = psci_mem_chk_range(r1, r2); + break; + + case PSCI_SYSTEM_RESET2_AARCH32: + /* We should never return from psci_system_reset2() */ + ret = psci_system_reset2(r1, r2); + break; + + default: + WARN("Unimplemented PSCI Call: 0x%x\n", smc_fid); + ret = (u_register_t)SMC_UNK; + break; + } + } else { + /* 64-bit PSCI function */ + + switch (smc_fid) { + case PSCI_CPU_SUSPEND_AARCH64: + ret = (u_register_t) + psci_cpu_suspend((unsigned int)x1, x2, x3); + break; + + case PSCI_CPU_ON_AARCH64: + ret = (u_register_t)psci_cpu_on(x1, x2, x3); + break; + + case PSCI_AFFINITY_INFO_AARCH64: + ret = (u_register_t) + psci_affinity_info(x1, (unsigned int)x2); + break; + + case PSCI_MIG_AARCH64: + ret = (u_register_t)psci_migrate(x1); + break; + + case PSCI_MIG_INFO_UP_CPU_AARCH64: + ret = psci_migrate_info_up_cpu(); + break; + + case PSCI_NODE_HW_STATE_AARCH64: + ret = (u_register_t)psci_node_hw_state( + x1, (unsigned int) x2); + break; + + case PSCI_SYSTEM_SUSPEND_AARCH64: + ret = (u_register_t)psci_system_suspend(x1, x2); + break; + +#if ENABLE_PSCI_STAT + case PSCI_STAT_RESIDENCY_AARCH64: + ret = psci_stat_residency(x1, (unsigned int) x2); + break; + + case PSCI_STAT_COUNT_AARCH64: + ret = psci_stat_count(x1, (unsigned int) x2); + break; +#endif + + case PSCI_MEM_CHK_RANGE_AARCH64: + ret = psci_mem_chk_range(x1, x2); + break; + + case PSCI_SYSTEM_RESET2_AARCH64: + /* We should never return from psci_system_reset2() */ + ret = psci_system_reset2((uint32_t) x1, x2); + break; + + default: + WARN("Unimplemented PSCI Call: 0x%x\n", smc_fid); + ret = (u_register_t)SMC_UNK; + break; + } + } + + return ret; +} diff --git a/arm-trusted-firmware/lib/psci/psci_mem_protect.c b/arm-trusted-firmware/lib/psci/psci_mem_protect.c new file mode 100644 index 0000000..481051f --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_mem_protect.c @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "psci_private.h" + +u_register_t psci_mem_protect(unsigned int enable) +{ + int val; + + assert(psci_plat_pm_ops->read_mem_protect != NULL); + assert(psci_plat_pm_ops->write_mem_protect != NULL); + + if (psci_plat_pm_ops->read_mem_protect(&val) < 0) + return (u_register_t) PSCI_E_NOT_SUPPORTED; + if (psci_plat_pm_ops->write_mem_protect(enable) < 0) + return (u_register_t) PSCI_E_NOT_SUPPORTED; + + return (val != 0) ? 1U : 0U; +} + +u_register_t psci_mem_chk_range(uintptr_t base, u_register_t length) +{ + int ret; + + assert(psci_plat_pm_ops->mem_protect_chk != NULL); + + if ((length == 0U) || check_uptr_overflow(base, length - 1U)) + return (u_register_t) PSCI_E_DENIED; + + ret = psci_plat_pm_ops->mem_protect_chk(base, length); + return (ret < 0) ? + (u_register_t) PSCI_E_DENIED : (u_register_t) PSCI_E_SUCCESS; +} diff --git a/arm-trusted-firmware/lib/psci/psci_off.c b/arm-trusted-firmware/lib/psci/psci_off.c new file mode 100644 index 0000000..5447045 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_off.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/****************************************************************************** + * Construct the psci_power_state to request power OFF at all power levels. + ******************************************************************************/ +static void psci_set_power_off_state(psci_power_state_t *state_info) +{ + unsigned int lvl; + + for (lvl = PSCI_CPU_PWR_LVL; lvl <= PLAT_MAX_PWR_LVL; lvl++) + state_info->pwr_domain_state[lvl] = PLAT_MAX_OFF_STATE; +} + +/****************************************************************************** + * Top level handler which is called when a cpu wants to power itself down. + * It's assumed that along with turning the cpu power domain off, power + * domains at higher levels will be turned off as far as possible. It finds + * the highest level where a domain has to be powered off by traversing the + * node information and then performs generic, architectural, platform setup + * and state management required to turn OFF that power domain and domains + * below it. e.g. For a cpu that's to be powered OFF, it could mean programming + * the power controller whereas for a cluster that's to be powered off, it will + * call the platform specific code which will disable coherency at the + * interconnect level if the cpu is the last in the cluster and also the + * program the power controller. + ******************************************************************************/ +int psci_do_cpu_off(unsigned int end_pwrlvl) +{ + int rc = PSCI_E_SUCCESS; + unsigned int idx = plat_my_core_pos(); + psci_power_state_t state_info; + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + + /* + * This function must only be called on platforms where the + * CPU_OFF platform hooks have been implemented. + */ + assert(psci_plat_pm_ops->pwr_domain_off != NULL); + + /* Construct the psci_power_state for CPU_OFF */ + psci_set_power_off_state(&state_info); + + /* + * Get the parent nodes here, this is important to do before we + * initiate the power down sequence as after that point the core may + * have exited coherency and its cache may be disabled, any access to + * shared memory after that (such as the parent node lookup in + * psci_cpu_pd_nodes) can cause coherency issues on some platforms. + */ + psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power + * level so that by the time all locks are taken, the system topology + * is snapshot and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Call the cpu off handler registered by the Secure Payload Dispatcher + * to let it do any bookkeeping. Assume that the SPD always reports an + * E_DENIED error if SP refuse to power down + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_off != NULL)) { + rc = psci_spd_pm->svc_off(0); + if (rc != 0) + goto exit; + } + + /* + * This function is passed the requested state info and + * it returns the negotiated state info for each power level upto + * the end level specified. + */ + psci_do_state_coordination(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + /* Update the last cpu for each level till end_pwrlvl */ + psci_stats_update_pwr_down(end_pwrlvl, &state_info); +#endif + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_CFLUSH, + PMF_CACHE_MAINT); +#endif + + /* + * Arch. management. Initiate power down sequence. + */ + psci_do_pwrdown_sequence(psci_find_max_off_lvl(&state_info)); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_CFLUSH, + PMF_NO_CACHE_MAINT); +#endif + + /* + * Plat. management: Perform platform specific actions to turn this + * cpu off e.g. exit cpu coherency, program the power controller etc. + */ + psci_plat_pm_ops->pwr_domain_off(&state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(&state_info); +#endif + +exit: + /* + * Release the locks corresponding to each power level in the + * reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Check if all actions needed to safely power down this cpu have + * successfully completed. + */ + if (rc == PSCI_E_SUCCESS) { + /* + * Set the affinity info state to OFF. When caches are disabled, + * this writes directly to main memory, so cache maintenance is + * required to ensure that later cached reads of aff_info_state + * return AFF_STATE_OFF. A dsbish() ensures ordering of the + * update to the affinity info state prior to cache line + * invalidation. + */ + psci_flush_cpu_data(psci_svc_cpu_data.aff_info_state); + psci_set_aff_info_state(AFF_STATE_OFF); + psci_dsbish(); + psci_inv_cpu_data(psci_svc_cpu_data.aff_info_state); + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Update the timestamp with cache off. We assume this + * timestamp can only be read from the current CPU and the + * timestamp cache line will be flushed before return to + * normal world on wakeup. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL) { + /* This function must not return */ + psci_plat_pm_ops->pwr_domain_pwr_down_wfi(&state_info); + } else { + /* + * Enter a wfi loop which will allow the power + * controller to physically power down this cpu. + */ + psci_power_down_wfi(); + } + } + + return rc; +} diff --git a/arm-trusted-firmware/lib/psci/psci_on.c b/arm-trusted-firmware/lib/psci/psci_on.c new file mode 100644 index 0000000..dd48e10 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_on.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/* + * Helper functions for the CPU level spinlocks + */ +static inline void psci_spin_lock_cpu(unsigned int idx) +{ + spin_lock(&psci_cpu_pd_nodes[idx].cpu_lock); +} + +static inline void psci_spin_unlock_cpu(unsigned int idx) +{ + spin_unlock(&psci_cpu_pd_nodes[idx].cpu_lock); +} + +/******************************************************************************* + * This function checks whether a cpu which has been requested to be turned on + * is OFF to begin with. + ******************************************************************************/ +static int cpu_on_validate_state(aff_info_state_t aff_state) +{ + if (aff_state == AFF_STATE_ON) + return PSCI_E_ALREADY_ON; + + if (aff_state == AFF_STATE_ON_PENDING) + return PSCI_E_ON_PENDING; + + assert(aff_state == AFF_STATE_OFF); + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Generic handler which is called to physically power on a cpu identified by + * its mpidr. It performs the generic, architectural, platform setup and state + * management to power on the target cpu e.g. it will ensure that + * enough information is stashed for it to resume execution in the non-secure + * security state. + * + * The state of all the relevant power domains are changed after calling the + * platform handler as it can return error. + ******************************************************************************/ +int psci_cpu_on_start(u_register_t target_cpu, + const entry_point_info_t *ep) +{ + int rc; + aff_info_state_t target_aff_state; + int ret = plat_core_pos_by_mpidr(target_cpu); + unsigned int target_idx = (unsigned int)ret; + + /* Calling function must supply valid input arguments */ + assert(ret >= 0); + assert(ep != NULL); + + + /* + * This function must only be called on platforms where the + * CPU_ON platform hooks have been implemented. + */ + assert((psci_plat_pm_ops->pwr_domain_on != NULL) && + (psci_plat_pm_ops->pwr_domain_on_finish != NULL)); + + /* Protect against multiple CPUs trying to turn ON the same target CPU */ + psci_spin_lock_cpu(target_idx); + + /* + * Generic management: Ensure that the cpu is off to be + * turned on. + * Perform cache maintanence ahead of reading the target CPU state to + * ensure that the data is not stale. + * There is a theoretical edge case where the cache may contain stale + * data for the target CPU data - this can occur under the following + * conditions: + * - the target CPU is in another cluster from the current + * - the target CPU was the last CPU to shutdown on its cluster + * - the cluster was removed from coherency as part of the CPU shutdown + * + * In this case the cache maintenace that was performed as part of the + * target CPUs shutdown was not seen by the current CPU's cluster. And + * so the cache may contain stale data for the target CPU. + */ + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + rc = cpu_on_validate_state(psci_get_aff_info_state_by_idx(target_idx)); + if (rc != PSCI_E_SUCCESS) + goto exit; + + /* + * Call the cpu on handler registered by the Secure Payload Dispatcher + * to let it do any bookeeping. If the handler encounters an error, it's + * expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_on != NULL)) + psci_spd_pm->svc_on(target_cpu); + + /* + * Set the Affinity info state of the target cpu to ON_PENDING. + * Flush aff_info_state as it will be accessed with caches + * turned OFF. + */ + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + /* + * The cache line invalidation by the target CPU after setting the + * state to OFF (see psci_do_cpu_off()), could cause the update to + * aff_info_state to be invalidated. Retry the update if the target + * CPU aff_info_state is not ON_PENDING. + */ + target_aff_state = psci_get_aff_info_state_by_idx(target_idx); + if (target_aff_state != AFF_STATE_ON_PENDING) { + assert(target_aff_state == AFF_STATE_OFF); + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_ON_PENDING); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + + assert(psci_get_aff_info_state_by_idx(target_idx) == + AFF_STATE_ON_PENDING); + } + + /* + * Perform generic, architecture and platform specific handling. + */ + /* + * Plat. management: Give the platform the current state + * of the target cpu to allow it to perform the necessary + * steps to power on. + */ + rc = psci_plat_pm_ops->pwr_domain_on(target_cpu); + assert((rc == PSCI_E_SUCCESS) || (rc == PSCI_E_INTERN_FAIL)); + + if (rc == PSCI_E_SUCCESS) + /* Store the re-entry information for the non-secure world. */ + cm_init_context_by_index(target_idx, ep); + else { + /* Restore the state on error. */ + psci_set_aff_info_state_by_idx(target_idx, AFF_STATE_OFF); + flush_cpu_data_by_index(target_idx, + psci_svc_cpu_data.aff_info_state); + } + +exit: + psci_spin_unlock_cpu(target_idx); + return rc; +} + +/******************************************************************************* + * The following function finish an earlier power on request. They + * are called by the common finisher routine in psci_common.c. The `state_info` + * is the psci_power_state from which this CPU has woken up from. + ******************************************************************************/ +void psci_cpu_on_finish(unsigned int cpu_idx, const psci_power_state_t *state_info) +{ + /* + * Plat. management: Perform the platform specific actions + * for this cpu e.g. enabling the gic or zeroing the mailbox + * register. The actual state of this cpu has already been + * changed. + */ + psci_plat_pm_ops->pwr_domain_on_finish(state_info); + +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* + * Arch. management: Enable data cache and manage stack memory + */ + psci_do_pwrup_cache_maintenance(); +#endif + + /* + * Plat. management: Perform any platform specific actions which + * can only be done with the cpu and the cluster guaranteed to + * be coherent. + */ + if (psci_plat_pm_ops->pwr_domain_on_finish_late != NULL) + psci_plat_pm_ops->pwr_domain_on_finish_late(state_info); + + /* + * All the platform specific actions for turning this cpu + * on have completed. Perform enough arch.initialization + * to run in the non-secure address space. + */ + psci_arch_setup(); + + /* + * Lock the CPU spin lock to make sure that the context initialization + * is done. Since the lock is only used in this function to create + * a synchronization point with cpu_on_start(), it can be released + * immediately. + */ + psci_spin_lock_cpu(cpu_idx); + psci_spin_unlock_cpu(cpu_idx); + + /* Ensure we have been explicitly woken up by another cpu */ + assert(psci_get_aff_info_state() == AFF_STATE_ON_PENDING); + + /* + * Call the cpu on finish handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_on_finish != NULL)) + psci_spd_pm->svc_on_finish(0); + + PUBLISH_EVENT(psci_cpu_on_finish); + + /* Populate the mpidr field within the cpu node array */ + /* This needs to be done only once */ + psci_cpu_pd_nodes[cpu_idx].mpidr = read_mpidr() & MPIDR_AFFINITY_MASK; + + /* + * Generic management: Now we just need to retrieve the + * information that we had stashed away during the cpu_on + * call to set this cpu on its way. + */ + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_private.h b/arm-trusted-firmware/lib/psci/psci_private.h new file mode 100644 index 0000000..72bd6bd --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_private.h @@ -0,0 +1,345 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSCI_PRIVATE_H +#define PSCI_PRIVATE_H + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * The PSCI capability which are provided by the generic code but does not + * depend on the platform or spd capabilities. + */ +#define PSCI_GENERIC_CAP \ + (define_psci_cap(PSCI_VERSION) | \ + define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \ + define_psci_cap(PSCI_FEATURES)) + +/* + * The PSCI capabilities mask for 64 bit functions. + */ +#define PSCI_CAP_64BIT_MASK \ + (define_psci_cap(PSCI_CPU_SUSPEND_AARCH64) | \ + define_psci_cap(PSCI_CPU_ON_AARCH64) | \ + define_psci_cap(PSCI_AFFINITY_INFO_AARCH64) | \ + define_psci_cap(PSCI_MIG_AARCH64) | \ + define_psci_cap(PSCI_MIG_INFO_UP_CPU_AARCH64) | \ + define_psci_cap(PSCI_NODE_HW_STATE_AARCH64) | \ + define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64) | \ + define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64) | \ + define_psci_cap(PSCI_STAT_COUNT_AARCH64) | \ + define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64) | \ + define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64)) + +/* Internally PSCI uses a uint16_t for various cpu indexes so + * define a limit to number of CPUs that can be initialised. + */ +#define PSCI_MAX_CPUS_INDEX 0xFFFFU + +/* + * Helper functions to get/set the fields of PSCI per-cpu data. + */ +static inline void psci_set_aff_info_state(aff_info_state_t aff_state) +{ + set_cpu_data(psci_svc_cpu_data.aff_info_state, aff_state); +} + +static inline aff_info_state_t psci_get_aff_info_state(void) +{ + return get_cpu_data(psci_svc_cpu_data.aff_info_state); +} + +static inline aff_info_state_t psci_get_aff_info_state_by_idx(unsigned int idx) +{ + return get_cpu_data_by_index(idx, + psci_svc_cpu_data.aff_info_state); +} + +static inline void psci_set_aff_info_state_by_idx(unsigned int idx, + aff_info_state_t aff_state) +{ + set_cpu_data_by_index(idx, + psci_svc_cpu_data.aff_info_state, aff_state); +} + +static inline unsigned int psci_get_suspend_pwrlvl(void) +{ + return get_cpu_data(psci_svc_cpu_data.target_pwrlvl); +} + +static inline void psci_set_suspend_pwrlvl(unsigned int target_lvl) +{ + set_cpu_data(psci_svc_cpu_data.target_pwrlvl, target_lvl); +} + +static inline void psci_set_cpu_local_state(plat_local_state_t state) +{ + set_cpu_data(psci_svc_cpu_data.local_state, state); +} + +static inline plat_local_state_t psci_get_cpu_local_state(void) +{ + return get_cpu_data(psci_svc_cpu_data.local_state); +} + +static inline plat_local_state_t psci_get_cpu_local_state_by_idx( + unsigned int idx) +{ + return get_cpu_data_by_index(idx, + psci_svc_cpu_data.local_state); +} + +/* Helper function to identify a CPU standby request in PSCI Suspend call */ +static inline bool is_cpu_standby_req(unsigned int is_power_down_state, + unsigned int retn_lvl) +{ + return (is_power_down_state == 0U) && (retn_lvl == 0U); +} + +/******************************************************************************* + * The following two data structures implement the power domain tree. The tree + * is used to track the state of all the nodes i.e. power domain instances + * described by the platform. The tree consists of nodes that describe CPU power + * domains i.e. leaf nodes and all other power domains which are parents of a + * CPU power domain i.e. non-leaf nodes. + ******************************************************************************/ +typedef struct non_cpu_pwr_domain_node { + /* + * Index of the first CPU power domain node level 0 which has this node + * as its parent. + */ + unsigned int cpu_start_idx; + + /* + * Number of CPU power domains which are siblings of the domain indexed + * by 'cpu_start_idx' i.e. all the domains in the range 'cpu_start_idx + * -> cpu_start_idx + ncpus' have this node as their parent. + */ + unsigned int ncpus; + + /* + * Index of the parent power domain node. + * TODO: Figure out whether to whether using pointer is more efficient. + */ + unsigned int parent_node; + + plat_local_state_t local_state; + + unsigned char level; + + /* For indexing the psci_lock array*/ + uint16_t lock_index; +} non_cpu_pd_node_t; + +typedef struct cpu_pwr_domain_node { + u_register_t mpidr; + + /* + * Index of the parent power domain node. + * TODO: Figure out whether to whether using pointer is more efficient. + */ + unsigned int parent_node; + + /* + * A CPU power domain does not require state coordination like its + * parent power domains. Hence this node does not include a bakery + * lock. A spinlock is required by the CPU_ON handler to prevent a race + * when multiple CPUs try to turn ON the same target CPU. + */ + spinlock_t cpu_lock; +} cpu_pd_node_t; + +/******************************************************************************* + * The following are helpers and declarations of locks. + ******************************************************************************/ +#if HW_ASSISTED_COHERENCY +/* + * On systems where participant CPUs are cache-coherent, we can use spinlocks + * instead of bakery locks. + */ +#define DEFINE_PSCI_LOCK(_name) spinlock_t _name +#define DECLARE_PSCI_LOCK(_name) extern DEFINE_PSCI_LOCK(_name) + +/* One lock is required per non-CPU power domain node */ +DECLARE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +/* + * On systems with hardware-assisted coherency, make PSCI cache operations NOP, + * as PSCI participants are cache-coherent, and there's no need for explicit + * cache maintenance operations or barriers to coordinate their state. + */ +static inline void psci_flush_dcache_range(uintptr_t __unused addr, + size_t __unused size) +{ + /* Empty */ +} + +#define psci_flush_cpu_data(member) +#define psci_inv_cpu_data(member) + +static inline void psci_dsbish(void) +{ + /* Empty */ +} + +static inline void psci_lock_get(non_cpu_pd_node_t *non_cpu_pd_node) +{ + spin_lock(&psci_locks[non_cpu_pd_node->lock_index]); +} + +static inline void psci_lock_release(non_cpu_pd_node_t *non_cpu_pd_node) +{ + spin_unlock(&psci_locks[non_cpu_pd_node->lock_index]); +} + +#else /* if HW_ASSISTED_COHERENCY == 0 */ +/* + * Use bakery locks for state coordination as not all PSCI participants are + * cache coherent. + */ +#define DEFINE_PSCI_LOCK(_name) DEFINE_BAKERY_LOCK(_name) +#define DECLARE_PSCI_LOCK(_name) DECLARE_BAKERY_LOCK(_name) + +/* One lock is required per non-CPU power domain node */ +DECLARE_PSCI_LOCK(psci_locks[PSCI_NUM_NON_CPU_PWR_DOMAINS]); + +/* + * If not all PSCI participants are cache-coherent, perform cache maintenance + * and issue barriers wherever required to coordinate state. + */ +static inline void psci_flush_dcache_range(uintptr_t addr, size_t size) +{ + flush_dcache_range(addr, size); +} + +#define psci_flush_cpu_data(member) flush_cpu_data(member) +#define psci_inv_cpu_data(member) inv_cpu_data(member) + +static inline void psci_dsbish(void) +{ + dsbish(); +} + +static inline void psci_lock_get(non_cpu_pd_node_t *non_cpu_pd_node) +{ + bakery_lock_get(&psci_locks[non_cpu_pd_node->lock_index]); +} + +static inline void psci_lock_release(non_cpu_pd_node_t *non_cpu_pd_node) +{ + bakery_lock_release(&psci_locks[non_cpu_pd_node->lock_index]); +} + +#endif /* HW_ASSISTED_COHERENCY */ + +static inline void psci_lock_init(non_cpu_pd_node_t *non_cpu_pd_node, + uint16_t idx) +{ + non_cpu_pd_node[idx].lock_index = idx; +} + +/******************************************************************************* + * Data prototypes + ******************************************************************************/ +extern const plat_psci_ops_t *psci_plat_pm_ops; +extern non_cpu_pd_node_t psci_non_cpu_pd_nodes[PSCI_NUM_NON_CPU_PWR_DOMAINS]; +extern cpu_pd_node_t psci_cpu_pd_nodes[PLATFORM_CORE_COUNT]; +extern unsigned int psci_caps; +extern unsigned int psci_plat_core_count; + +/******************************************************************************* + * SPD's power management hooks registered with PSCI + ******************************************************************************/ +extern const spd_pm_ops_t *psci_spd_pm; + +/******************************************************************************* + * Function prototypes + ******************************************************************************/ +/* Private exported functions from psci_common.c */ +int psci_validate_power_state(unsigned int power_state, + psci_power_state_t *state_info); +void psci_query_sys_suspend_pwrstate(psci_power_state_t *state_info); +int psci_validate_mpidr(u_register_t mpidr); +void psci_init_req_local_pwr_states(void); +void psci_get_target_local_pwr_states(unsigned int end_pwrlvl, + psci_power_state_t *target_state); +int psci_validate_entry_point(entry_point_info_t *ep, + uintptr_t entrypoint, u_register_t context_id); +void psci_get_parent_pwr_domain_nodes(unsigned int cpu_idx, + unsigned int end_lvl, + unsigned int *node_index); +void psci_do_state_coordination(unsigned int end_pwrlvl, + psci_power_state_t *state_info); +void psci_acquire_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes); +void psci_release_pwr_domain_locks(unsigned int end_pwrlvl, + const unsigned int *parent_nodes); +int psci_validate_suspend_req(const psci_power_state_t *state_info, + unsigned int is_power_down_state); +unsigned int psci_find_max_off_lvl(const psci_power_state_t *state_info); +unsigned int psci_find_target_suspend_lvl(const psci_power_state_t *state_info); +void psci_set_pwr_domains_to_run(unsigned int end_pwrlvl); +void psci_print_power_domain_map(void); +unsigned int psci_is_last_on_cpu(void); +int psci_spd_migrate_info(u_register_t *mpidr); +void psci_do_pwrdown_sequence(unsigned int power_level); + +/* + * CPU power down is directly called only when HW_ASSISTED_COHERENCY is + * available. Otherwise, this needs post-call stack maintenance, which is + * handled in assembly. + */ +void prepare_cpu_pwr_dwn(unsigned int power_level); + +/* Private exported functions from psci_on.c */ +int psci_cpu_on_start(u_register_t target_cpu, + const entry_point_info_t *ep); + +void psci_cpu_on_finish(unsigned int cpu_idx, const psci_power_state_t *state_info); + +/* Private exported functions from psci_off.c */ +int psci_do_cpu_off(unsigned int end_pwrlvl); + +/* Private exported functions from psci_suspend.c */ +void psci_cpu_suspend_start(const entry_point_info_t *ep, + unsigned int end_pwrlvl, + psci_power_state_t *state_info, + unsigned int is_power_down_state); + +void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info); + +/* Private exported functions from psci_helpers.S */ +void psci_do_pwrdown_cache_maintenance(unsigned int pwr_level); +void psci_do_pwrup_cache_maintenance(void); + +/* Private exported functions from psci_system_off.c */ +void __dead2 psci_system_off(void); +void __dead2 psci_system_reset(void); +u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie); + +/* Private exported functions from psci_stat.c */ +void psci_stats_update_pwr_down(unsigned int end_pwrlvl, + const psci_power_state_t *state_info); +void psci_stats_update_pwr_up(unsigned int end_pwrlvl, + const psci_power_state_t *state_info); +u_register_t psci_stat_residency(u_register_t target_cpu, + unsigned int power_state); +u_register_t psci_stat_count(u_register_t target_cpu, + unsigned int power_state); + +/* Private exported functions from psci_mem_protect.c */ +u_register_t psci_mem_protect(unsigned int enable); +u_register_t psci_mem_chk_range(uintptr_t base, u_register_t length); + +#endif /* PSCI_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/psci/psci_setup.c b/arm-trusted-firmware/lib/psci/psci_setup.c new file mode 100644 index 0000000..3cb4f7e --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_setup.c @@ -0,0 +1,315 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/* + * Check that PLATFORM_CORE_COUNT fits into the number of cores + * that can be represented by PSCI_MAX_CPUS_INDEX. + */ +CASSERT(PLATFORM_CORE_COUNT <= (PSCI_MAX_CPUS_INDEX + 1U), assert_psci_cores_overflow); + +/******************************************************************************* + * Per cpu non-secure contexts used to program the architectural state prior + * return to the normal world. + * TODO: Use the memory allocator to set aside memory for the contexts instead + * of relying on platform defined constants. + ******************************************************************************/ +static cpu_context_t psci_ns_context[PLATFORM_CORE_COUNT]; + +/****************************************************************************** + * Define the psci capability variable. + *****************************************************************************/ +unsigned int psci_caps; + +/******************************************************************************* + * Function which initializes the 'psci_non_cpu_pd_nodes' or the + * 'psci_cpu_pd_nodes' corresponding to the power level. + ******************************************************************************/ +static void __init psci_init_pwr_domain_node(uint16_t node_idx, + unsigned int parent_idx, + unsigned char level) +{ + if (level > PSCI_CPU_PWR_LVL) { + assert(node_idx < PSCI_NUM_NON_CPU_PWR_DOMAINS); + + psci_non_cpu_pd_nodes[node_idx].level = level; + psci_lock_init(psci_non_cpu_pd_nodes, node_idx); + psci_non_cpu_pd_nodes[node_idx].parent_node = parent_idx; + psci_non_cpu_pd_nodes[node_idx].local_state = + PLAT_MAX_OFF_STATE; + } else { + psci_cpu_data_t *svc_cpu_data; + + assert(node_idx < PLATFORM_CORE_COUNT); + + psci_cpu_pd_nodes[node_idx].parent_node = parent_idx; + + /* Initialize with an invalid mpidr */ + psci_cpu_pd_nodes[node_idx].mpidr = PSCI_INVALID_MPIDR; + + svc_cpu_data = + &(_cpu_data_by_index(node_idx)->psci_svc_cpu_data); + + /* Set the Affinity Info for the cores as OFF */ + svc_cpu_data->aff_info_state = AFF_STATE_OFF; + + /* Invalidate the suspend level for the cpu */ + svc_cpu_data->target_pwrlvl = PSCI_INVALID_PWR_LVL; + + /* Set the power state to OFF state */ + svc_cpu_data->local_state = PLAT_MAX_OFF_STATE; + + psci_flush_dcache_range((uintptr_t)svc_cpu_data, + sizeof(*svc_cpu_data)); + + cm_set_context_by_index(node_idx, + (void *) &psci_ns_context[node_idx], + NON_SECURE); + } +} + +/******************************************************************************* + * This functions updates cpu_start_idx and ncpus field for each of the node in + * psci_non_cpu_pd_nodes[]. It does so by comparing the parent nodes of each of + * the CPUs and check whether they match with the parent of the previous + * CPU. The basic assumption for this work is that children of the same parent + * are allocated adjacent indices. The platform should ensure this though proper + * mapping of the CPUs to indices via plat_core_pos_by_mpidr() and + * plat_my_core_pos() APIs. + *******************************************************************************/ +static void __init psci_update_pwrlvl_limits(void) +{ + unsigned int cpu_idx; + int j; + unsigned int nodes_idx[PLAT_MAX_PWR_LVL] = {0}; + unsigned int temp_index[PLAT_MAX_PWR_LVL]; + + for (cpu_idx = 0; cpu_idx < psci_plat_core_count; cpu_idx++) { + psci_get_parent_pwr_domain_nodes(cpu_idx, + PLAT_MAX_PWR_LVL, + temp_index); + for (j = (int)PLAT_MAX_PWR_LVL - 1; j >= 0; j--) { + if (temp_index[j] != nodes_idx[j]) { + nodes_idx[j] = temp_index[j]; + psci_non_cpu_pd_nodes[nodes_idx[j]].cpu_start_idx + = cpu_idx; + } + psci_non_cpu_pd_nodes[nodes_idx[j]].ncpus++; + } + } +} + +/******************************************************************************* + * Core routine to populate the power domain tree. The tree descriptor passed by + * the platform is populated breadth-first and the first entry in the map + * informs the number of root power domains. The parent nodes of the root nodes + * will point to an invalid entry(-1). + ******************************************************************************/ +static unsigned int __init populate_power_domain_tree(const unsigned char + *topology) +{ + unsigned int i, j = 0U, num_nodes_at_lvl = 1U, num_nodes_at_next_lvl; + unsigned int node_index = 0U, num_children; + unsigned int parent_node_index = 0U; + int level = (int)PLAT_MAX_PWR_LVL; + + /* + * For each level the inputs are: + * - number of nodes at this level in plat_array i.e. num_nodes_at_level + * This is the sum of values of nodes at the parent level. + * - Index of first entry at this level in the plat_array i.e. + * parent_node_index. + * - Index of first free entry in psci_non_cpu_pd_nodes[] or + * psci_cpu_pd_nodes[] i.e. node_index depending upon the level. + */ + while (level >= (int) PSCI_CPU_PWR_LVL) { + num_nodes_at_next_lvl = 0U; + /* + * For each entry (parent node) at this level in the plat_array: + * - Find the number of children + * - Allocate a node in a power domain array for each child + * - Set the parent of the child to the parent_node_index - 1 + * - Increment parent_node_index to point to the next parent + * - Accumulate the number of children at next level. + */ + for (i = 0U; i < num_nodes_at_lvl; i++) { + assert(parent_node_index <= + PSCI_NUM_NON_CPU_PWR_DOMAINS); + num_children = topology[parent_node_index]; + + for (j = node_index; + j < (node_index + num_children); j++) + psci_init_pwr_domain_node((uint16_t)j, + parent_node_index - 1U, + (unsigned char)level); + + node_index = j; + num_nodes_at_next_lvl += num_children; + parent_node_index++; + } + + num_nodes_at_lvl = num_nodes_at_next_lvl; + level--; + + /* Reset the index for the cpu power domain array */ + if (level == (int) PSCI_CPU_PWR_LVL) + node_index = 0; + } + + /* Validate the sanity of array exported by the platform */ + assert(j <= PLATFORM_CORE_COUNT); + return j; +} + +/******************************************************************************* + * This function does the architectural setup and takes the warm boot + * entry-point `mailbox_ep` as an argument. The function also initializes the + * power domain topology tree by querying the platform. The power domain nodes + * higher than the CPU are populated in the array psci_non_cpu_pd_nodes[] and + * the CPU power domains are populated in psci_cpu_pd_nodes[]. The platform + * exports its static topology map through the + * populate_power_domain_topology_tree() API. The algorithm populates the + * psci_non_cpu_pd_nodes and psci_cpu_pd_nodes iteratively by using this + * topology map. On a platform that implements two clusters of 2 cpus each, + * and supporting 3 domain levels, the populated psci_non_cpu_pd_nodes would + * look like this: + * + * --------------------------------------------------- + * | system node | cluster 0 node | cluster 1 node | + * --------------------------------------------------- + * + * And populated psci_cpu_pd_nodes would look like this : + * <- cpus cluster0 -><- cpus cluster1 -> + * ------------------------------------------------ + * | CPU 0 | CPU 1 | CPU 2 | CPU 3 | + * ------------------------------------------------ + ******************************************************************************/ +int __init psci_setup(const psci_lib_args_t *lib_args) +{ + const unsigned char *topology_tree; + + assert(VERIFY_PSCI_LIB_ARGS_V1(lib_args)); + + /* Do the Architectural initialization */ + psci_arch_setup(); + + /* Query the topology map from the platform */ + topology_tree = plat_get_power_domain_tree_desc(); + + /* Populate the power domain arrays using the platform topology map */ + psci_plat_core_count = populate_power_domain_tree(topology_tree); + + /* Update the CPU limits for each node in psci_non_cpu_pd_nodes */ + psci_update_pwrlvl_limits(); + + /* Populate the mpidr field of cpu node for this CPU */ + psci_cpu_pd_nodes[plat_my_core_pos()].mpidr = + read_mpidr() & MPIDR_AFFINITY_MASK; + + psci_init_req_local_pwr_states(); + + /* + * Set the requested and target state of this CPU and all the higher + * power domain levels for this CPU to run. + */ + psci_set_pwr_domains_to_run(PLAT_MAX_PWR_LVL); + + (void) plat_setup_psci_ops((uintptr_t)lib_args->mailbox_ep, + &psci_plat_pm_ops); + assert(psci_plat_pm_ops != NULL); + + /* + * Flush `psci_plat_pm_ops` as it will be accessed by secondary CPUs + * during warm boot, possibly before data cache is enabled. + */ + psci_flush_dcache_range((uintptr_t)&psci_plat_pm_ops, + sizeof(psci_plat_pm_ops)); + + /* Initialize the psci capability */ + psci_caps = PSCI_GENERIC_CAP; + + if (psci_plat_pm_ops->pwr_domain_off != NULL) + psci_caps |= define_psci_cap(PSCI_CPU_OFF); + if ((psci_plat_pm_ops->pwr_domain_on != NULL) && + (psci_plat_pm_ops->pwr_domain_on_finish != NULL)) + psci_caps |= define_psci_cap(PSCI_CPU_ON_AARCH64); + if ((psci_plat_pm_ops->pwr_domain_suspend != NULL) && + (psci_plat_pm_ops->pwr_domain_suspend_finish != NULL)) { + if (psci_plat_pm_ops->validate_power_state != NULL) + psci_caps |= define_psci_cap(PSCI_CPU_SUSPEND_AARCH64); + if (psci_plat_pm_ops->get_sys_suspend_power_state != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_SUSPEND_AARCH64); + } + if (psci_plat_pm_ops->system_off != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_OFF); + if (psci_plat_pm_ops->system_reset != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET); + if (psci_plat_pm_ops->get_node_hw_state != NULL) + psci_caps |= define_psci_cap(PSCI_NODE_HW_STATE_AARCH64); + if ((psci_plat_pm_ops->read_mem_protect != NULL) && + (psci_plat_pm_ops->write_mem_protect != NULL)) + psci_caps |= define_psci_cap(PSCI_MEM_PROTECT); + if (psci_plat_pm_ops->mem_protect_chk != NULL) + psci_caps |= define_psci_cap(PSCI_MEM_CHK_RANGE_AARCH64); + if (psci_plat_pm_ops->system_reset2 != NULL) + psci_caps |= define_psci_cap(PSCI_SYSTEM_RESET2_AARCH64); + +#if ENABLE_PSCI_STAT + psci_caps |= define_psci_cap(PSCI_STAT_RESIDENCY_AARCH64); + psci_caps |= define_psci_cap(PSCI_STAT_COUNT_AARCH64); +#endif + + return 0; +} + +/******************************************************************************* + * This duplicates what the primary cpu did after a cold boot in BL1. The same + * needs to be done when a cpu is hotplugged in. This function could also over- + * ride any EL3 setup done by BL1 as this code resides in rw memory. + ******************************************************************************/ +void psci_arch_setup(void) +{ +#if (ARM_ARCH_MAJOR > 7) || defined(ARMV7_SUPPORTS_GENERIC_TIMER) + /* Program the counter frequency */ + write_cntfrq_el0(plat_get_syscnt_freq2()); +#endif + + /* Initialize the cpu_ops pointer. */ + init_cpu_ops(); + + /* Having initialized cpu_ops, we can now print errata status */ + print_errata_status(); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ +} + +/****************************************************************************** + * PSCI Library interface to initialize the cpu context for the next non + * secure image during cold boot. The relevant registers in the cpu context + * need to be retrieved and programmed on return from this interface. + *****************************************************************************/ +void psci_prepare_next_non_secure_ctx(entry_point_info_t *next_image_info) +{ + assert(GET_SECURITY_STATE(next_image_info->h.attr) == NON_SECURE); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_stat.c b/arm-trusted-firmware/lib/psci/psci_stat.c new file mode 100644 index 0000000..ecef95a --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_stat.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include + +#include "psci_private.h" + +#ifndef PLAT_MAX_PWR_LVL_STATES +#define PLAT_MAX_PWR_LVL_STATES 2U +#endif + +/* Following structure is used for PSCI STAT */ +typedef struct psci_stat { + u_register_t residency; + u_register_t count; +} psci_stat_t; + +/* + * Following is used to keep track of the last cpu + * that goes to power down in non cpu power domains. + */ +static int last_cpu_in_non_cpu_pd[PSCI_NUM_NON_CPU_PWR_DOMAINS] = { + [0 ... PSCI_NUM_NON_CPU_PWR_DOMAINS - 1U] = -1}; + +/* + * Following are used to store PSCI STAT values for + * CPU and non CPU power domains. + */ +static psci_stat_t psci_cpu_stat[PLATFORM_CORE_COUNT] + [PLAT_MAX_PWR_LVL_STATES]; +static psci_stat_t psci_non_cpu_stat[PSCI_NUM_NON_CPU_PWR_DOMAINS] + [PLAT_MAX_PWR_LVL_STATES]; + +/* + * This functions returns the index into the `psci_stat_t` array given the + * local power state and power domain level. If the platform implements the + * `get_pwr_lvl_state_idx` pm hook, then that will be used to return the index. + */ +static int get_stat_idx(plat_local_state_t local_state, unsigned int pwr_lvl) +{ + int idx; + + if (psci_plat_pm_ops->get_pwr_lvl_state_idx == NULL) { + assert(PLAT_MAX_PWR_LVL_STATES == 2U); + if (is_local_state_retn(local_state) != 0) + return 0; + + assert(is_local_state_off(local_state) != 0); + return 1; + } + + idx = psci_plat_pm_ops->get_pwr_lvl_state_idx(local_state, pwr_lvl); + assert((idx >= 0) && (idx < (int) PLAT_MAX_PWR_LVL_STATES)); + return idx; +} + +/******************************************************************************* + * This function is passed the target local power states for each power + * domain (state_info) between the current CPU domain and its ancestors until + * the target power level (end_pwrlvl). + * + * Then, for each level (apart from the CPU level) until the 'end_pwrlvl', it + * updates the `last_cpu_in_non_cpu_pd[]` with last power down cpu id. + * + * This function will only be invoked with data cache enabled and while + * powering down a core. + ******************************************************************************/ +void psci_stats_update_pwr_down(unsigned int end_pwrlvl, + const psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx; + unsigned int cpu_idx = plat_my_core_pos(); + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + assert(state_info != NULL); + + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + + /* Break early if the target power state is RUN */ + if (is_local_state_run(state_info->pwr_domain_state[lvl]) != 0) + break; + + /* + * The power domain is entering a low power state, so this is + * the last CPU for this power domain + */ + last_cpu_in_non_cpu_pd[parent_idx] = (int)cpu_idx; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + +} + +/******************************************************************************* + * This function updates the PSCI STATS(residency time and count) for CPU + * and NON-CPU power domains. + * It is called with caches enabled and locks acquired(for NON-CPU domain) + ******************************************************************************/ +void psci_stats_update_pwr_up(unsigned int end_pwrlvl, + const psci_power_state_t *state_info) +{ + unsigned int lvl, parent_idx; + unsigned int cpu_idx = plat_my_core_pos(); + int stat_idx; + plat_local_state_t local_state; + u_register_t residency; + + assert(end_pwrlvl <= PLAT_MAX_PWR_LVL); + assert(state_info != NULL); + + /* Get the index into the stats array */ + local_state = state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]; + stat_idx = get_stat_idx(local_state, PSCI_CPU_PWR_LVL); + + /* Call into platform interface to calculate residency. */ + residency = plat_psci_stat_get_residency(PSCI_CPU_PWR_LVL, + state_info, cpu_idx); + + /* Update CPU stats. */ + psci_cpu_stat[cpu_idx][stat_idx].residency += residency; + psci_cpu_stat[cpu_idx][stat_idx].count++; + + /* + * Check what power domains above CPU were off + * prior to this CPU powering on. + */ + parent_idx = psci_cpu_pd_nodes[cpu_idx].parent_node; + /* Return early if this is the first power up. */ + if (last_cpu_in_non_cpu_pd[parent_idx] == -1) + return; + + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl <= end_pwrlvl; lvl++) { + local_state = state_info->pwr_domain_state[lvl]; + if (is_local_state_run(local_state) != 0) { + /* Break early */ + break; + } + + assert(last_cpu_in_non_cpu_pd[parent_idx] != -1); + + /* Call into platform interface to calculate residency. */ + residency = plat_psci_stat_get_residency(lvl, state_info, + (unsigned int)last_cpu_in_non_cpu_pd[parent_idx]); + + /* Initialize back to reset value */ + last_cpu_in_non_cpu_pd[parent_idx] = -1; + + /* Get the index into the stats array */ + stat_idx = get_stat_idx(local_state, lvl); + + /* Update non cpu stats */ + psci_non_cpu_stat[parent_idx][stat_idx].residency += residency; + psci_non_cpu_stat[parent_idx][stat_idx].count++; + + parent_idx = psci_non_cpu_pd_nodes[parent_idx].parent_node; + } + +} + +/******************************************************************************* + * This function returns the appropriate count and residency time of the + * local state for the highest power level expressed in the `power_state` + * for the node represented by `target_cpu`. + ******************************************************************************/ +static int psci_get_stat(u_register_t target_cpu, unsigned int power_state, + psci_stat_t *psci_stat) +{ + int rc; + unsigned int pwrlvl, lvl, parent_idx, target_idx; + int stat_idx; + psci_power_state_t state_info = { {PSCI_LOCAL_STATE_RUN} }; + plat_local_state_t local_state; + + /* Validate the target_cpu parameter and determine the cpu index */ + target_idx = (unsigned int) plat_core_pos_by_mpidr(target_cpu); + if (target_idx == (unsigned int) -1) + return PSCI_E_INVALID_PARAMS; + + /* Validate the power_state parameter */ + if (psci_plat_pm_ops->translate_power_state_by_mpidr == NULL) + rc = psci_validate_power_state(power_state, &state_info); + else + rc = psci_plat_pm_ops->translate_power_state_by_mpidr( + target_cpu, power_state, &state_info); + + if (rc != PSCI_E_SUCCESS) + return PSCI_E_INVALID_PARAMS; + + /* Find the highest power level */ + pwrlvl = psci_find_target_suspend_lvl(&state_info); + if (pwrlvl == PSCI_INVALID_PWR_LVL) { + ERROR("Invalid target power level for PSCI statistics operation\n"); + panic(); + } + + /* Get the index into the stats array */ + local_state = state_info.pwr_domain_state[pwrlvl]; + stat_idx = get_stat_idx(local_state, pwrlvl); + + if (pwrlvl > PSCI_CPU_PWR_LVL) { + /* Get the power domain index */ + parent_idx = SPECULATION_SAFE_VALUE(psci_cpu_pd_nodes[target_idx].parent_node); + for (lvl = PSCI_CPU_PWR_LVL + 1U; lvl < pwrlvl; lvl++) + parent_idx = SPECULATION_SAFE_VALUE(psci_non_cpu_pd_nodes[parent_idx].parent_node); + + /* Get the non cpu power domain stats */ + *psci_stat = psci_non_cpu_stat[parent_idx][stat_idx]; + } else { + /* Get the cpu power domain stats */ + *psci_stat = psci_cpu_stat[target_idx][stat_idx]; + } + + return PSCI_E_SUCCESS; +} + +/* This is the top level function for PSCI_STAT_RESIDENCY SMC. */ +u_register_t psci_stat_residency(u_register_t target_cpu, + unsigned int power_state) +{ + psci_stat_t psci_stat; + int rc = psci_get_stat(target_cpu, power_state, &psci_stat); + + if (rc == PSCI_E_SUCCESS) + return psci_stat.residency; + else + return 0; +} + +/* This is the top level function for PSCI_STAT_COUNT SMC. */ +u_register_t psci_stat_count(u_register_t target_cpu, + unsigned int power_state) +{ + psci_stat_t psci_stat; + int rc = psci_get_stat(target_cpu, power_state, &psci_stat); + + if (rc == PSCI_E_SUCCESS) + return psci_stat.count; + else + return 0; +} diff --git a/arm-trusted-firmware/lib/psci/psci_suspend.c b/arm-trusted-firmware/lib/psci/psci_suspend.c new file mode 100644 index 0000000..da9f328 --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_suspend.c @@ -0,0 +1,335 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "psci_private.h" + +/******************************************************************************* + * This function does generic and platform specific operations after a wake-up + * from standby/retention states at multiple power levels. + ******************************************************************************/ +static void psci_suspend_to_standby_finisher(unsigned int cpu_idx, + unsigned int end_pwrlvl) +{ + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + psci_power_state_t state_info; + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(cpu_idx, end_pwrlvl, parent_nodes); + + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * Find out which retention states this CPU has exited from until the + * 'end_pwrlvl'. The exit retention state could be deeper than the entry + * state as a result of state coordination amongst other CPUs post wfi. + */ + psci_get_target_local_pwr_states(end_pwrlvl, &state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_stop(&state_info); + psci_stats_update_pwr_up(end_pwrlvl, &state_info); +#endif + + /* + * Plat. management: Allow the platform to do operations + * on waking up from retention. + */ + psci_plat_pm_ops->pwr_domain_suspend_finish(&state_info); + + /* + * Set the requested and target state of this CPU and all the higher + * power domain levels for this CPU to run. + */ + psci_set_pwr_domains_to_run(end_pwrlvl); + + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); +} + +/******************************************************************************* + * This function does generic and platform specific suspend to power down + * operations. + ******************************************************************************/ +static void psci_suspend_to_pwrdown_start(unsigned int end_pwrlvl, + const entry_point_info_t *ep, + const psci_power_state_t *state_info) +{ + unsigned int max_off_lvl = psci_find_max_off_lvl(state_info); + + PUBLISH_EVENT(psci_suspend_pwrdown_start); + + /* Save PSCI target power level for the suspend finisher handler */ + psci_set_suspend_pwrlvl(end_pwrlvl); + + /* + * Flush the target power level as it might be accessed on power up with + * Data cache disabled. + */ + psci_flush_cpu_data(psci_svc_cpu_data.target_pwrlvl); + + /* + * Call the cpu suspend handler registered by the Secure Payload + * Dispatcher to let it do any book-keeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend != NULL)) + psci_spd_pm->svc_suspend(max_off_lvl); + +#if !HW_ASSISTED_COHERENCY + /* + * Plat. management: Allow the platform to perform any early + * actions required to power down the CPU. This might be useful for + * HW_ASSISTED_COHERENCY = 0 platforms that can safely perform these + * actions with data caches enabled. + */ + if (psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early != NULL) + psci_plat_pm_ops->pwr_domain_suspend_pwrdown_early(state_info); +#endif + + /* + * Store the re-entry information for the non-secure world. + */ + cm_init_my_context(ep); + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_CFLUSH, + PMF_CACHE_MAINT); +#endif + + /* + * Arch. management. Initiate power down sequence. + * TODO : Introduce a mechanism to query the cache level to flush + * and the cpu-ops power down to perform from the platform. + */ + psci_do_pwrdown_sequence(max_off_lvl); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_CFLUSH, + PMF_NO_CACHE_MAINT); +#endif +} + +/******************************************************************************* + * Top level handler which is called when a cpu wants to suspend its execution. + * It is assumed that along with suspending the cpu power domain, power domains + * at higher levels until the target power level will be suspended as well. It + * coordinates with the platform to negotiate the target state for each of + * the power domain level till the target power domain level. It then performs + * generic, architectural, platform setup and state management required to + * suspend that power domain level and power domain levels below it. + * e.g. For a cpu that's to be suspended, it could mean programming the + * power controller whereas for a cluster that's to be suspended, it will call + * the platform specific code which will disable coherency at the interconnect + * level if the cpu is the last in the cluster and also the program the power + * controller. + * + * All the required parameter checks are performed at the beginning and after + * the state transition has been done, no further error is expected and it is + * not possible to undo any of the actions taken beyond that point. + ******************************************************************************/ +void psci_cpu_suspend_start(const entry_point_info_t *ep, + unsigned int end_pwrlvl, + psci_power_state_t *state_info, + unsigned int is_power_down_state) +{ + int skip_wfi = 0; + unsigned int idx = plat_my_core_pos(); + unsigned int parent_nodes[PLAT_MAX_PWR_LVL] = {0}; + + /* + * This function must only be called on platforms where the + * CPU_SUSPEND platform hooks have been implemented. + */ + assert((psci_plat_pm_ops->pwr_domain_suspend != NULL) && + (psci_plat_pm_ops->pwr_domain_suspend_finish != NULL)); + + /* Get the parent nodes */ + psci_get_parent_pwr_domain_nodes(idx, end_pwrlvl, parent_nodes); + + /* + * This function acquires the lock corresponding to each power + * level so that by the time all locks are taken, the system topology + * is snapshot and state management can be done safely. + */ + psci_acquire_pwr_domain_locks(end_pwrlvl, parent_nodes); + + /* + * We check if there are any pending interrupts after the delay + * introduced by lock contention to increase the chances of early + * detection that a wake-up interrupt has fired. + */ + if (read_isr_el1() != 0U) { + skip_wfi = 1; + goto exit; + } + + /* + * This function is passed the requested state info and + * it returns the negotiated state info for each power level upto + * the end level specified. + */ + psci_do_state_coordination(end_pwrlvl, state_info); + +#if ENABLE_PSCI_STAT + /* Update the last cpu for each level till end_pwrlvl */ + psci_stats_update_pwr_down(end_pwrlvl, state_info); +#endif + + if (is_power_down_state != 0U) + psci_suspend_to_pwrdown_start(end_pwrlvl, ep, state_info); + + /* + * Plat. management: Allow the platform to perform the + * necessary actions to turn off this cpu e.g. set the + * platform defined mailbox with the psci entrypoint, + * program the power controller etc. + */ + psci_plat_pm_ops->pwr_domain_suspend(state_info); + +#if ENABLE_PSCI_STAT + plat_psci_stat_accounting_start(state_info); +#endif + +exit: + /* + * Release the locks corresponding to each power level in the + * reverse order to which they were acquired. + */ + psci_release_pwr_domain_locks(end_pwrlvl, parent_nodes); + + if (skip_wfi == 1) + return; + + if (is_power_down_state != 0U) { +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Update the timestamp with cache off. We assume this + * timestamp can only be read from the current CPU and the + * timestamp cache line will be flushed before return to + * normal world on wakeup. + */ + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* The function calls below must not return */ + if (psci_plat_pm_ops->pwr_domain_pwr_down_wfi != NULL) + psci_plat_pm_ops->pwr_domain_pwr_down_wfi(state_info); + else + psci_power_down_wfi(); + } + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* + * We will reach here if only retention/standby states have been + * requested at multiple power levels. This means that the cpu + * context will be preserved. + */ + wfi(); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_HW_LOW_PWR, + PMF_NO_CACHE_MAINT); +#endif + + /* + * After we wake up from context retaining suspend, call the + * context retaining suspend finisher. + */ + psci_suspend_to_standby_finisher(idx, end_pwrlvl); +} + +/******************************************************************************* + * The following functions finish an earlier suspend request. They + * are called by the common finisher routine in psci_common.c. The `state_info` + * is the psci_power_state from which this CPU has woken up from. + ******************************************************************************/ +void psci_cpu_suspend_finish(unsigned int cpu_idx, const psci_power_state_t *state_info) +{ + unsigned int counter_freq; + unsigned int max_off_lvl; + + /* Ensure we have been woken up from a suspended state */ + assert((psci_get_aff_info_state() == AFF_STATE_ON) && + (is_local_state_off( + state_info->pwr_domain_state[PSCI_CPU_PWR_LVL]) != 0)); + + /* + * Plat. management: Perform the platform specific actions + * before we change the state of the cpu e.g. enabling the + * gic or zeroing the mailbox register. If anything goes + * wrong then assert as there is no way to recover from this + * situation. + */ + psci_plat_pm_ops->pwr_domain_suspend_finish(state_info); + +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + /* Arch. management: Enable the data cache, stack memory maintenance. */ + psci_do_pwrup_cache_maintenance(); +#endif + + /* Re-init the cntfrq_el0 register */ + counter_freq = plat_get_syscnt_freq2(); + write_cntfrq_el0(counter_freq); + +#if ENABLE_PAUTH + /* Store APIAKey_EL1 key */ + set_cpu_data(apiakey[0], read_apiakeylo_el1()); + set_cpu_data(apiakey[1], read_apiakeyhi_el1()); +#endif /* ENABLE_PAUTH */ + + /* + * Call the cpu suspend finish handler registered by the Secure Payload + * Dispatcher to let it do any bookeeping. If the handler encounters an + * error, it's expected to assert within + */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_suspend_finish != NULL)) { + max_off_lvl = psci_find_max_off_lvl(state_info); + assert(max_off_lvl != PSCI_INVALID_PWR_LVL); + psci_spd_pm->svc_suspend_finish(max_off_lvl); + } + + /* Invalidate the suspend level for the cpu */ + psci_set_suspend_pwrlvl(PSCI_INVALID_PWR_LVL); + + PUBLISH_EVENT(psci_suspend_pwrdown_finish); + + /* + * Generic management: Now we just need to retrieve the + * information that we had stashed away during the suspend + * call to set this cpu on its way. + */ + cm_prepare_el3_exit(NON_SECURE); +} diff --git a/arm-trusted-firmware/lib/psci/psci_system_off.c b/arm-trusted-firmware/lib/psci/psci_system_off.c new file mode 100644 index 0000000..002392c --- /dev/null +++ b/arm-trusted-firmware/lib/psci/psci_system_off.c @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "psci_private.h" + +void __dead2 psci_system_off(void) +{ + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_off != NULL); + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_off != NULL)) { + psci_spd_pm->svc_system_off(); + } + + console_flush(); + + /* Call the platform specific hook */ + psci_plat_pm_ops->system_off(); + + /* This function does not return. We should never get here */ +} + +void __dead2 psci_system_reset(void) +{ + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_reset != NULL); + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_reset != NULL)) { + psci_spd_pm->svc_system_reset(); + } + + console_flush(); + + /* Call the platform specific hook */ + psci_plat_pm_ops->system_reset(); + + /* This function does not return. We should never get here */ +} + +u_register_t psci_system_reset2(uint32_t reset_type, u_register_t cookie) +{ + unsigned int is_vendor; + + psci_print_power_domain_map(); + + assert(psci_plat_pm_ops->system_reset2 != NULL); + + is_vendor = (reset_type >> PSCI_RESET2_TYPE_VENDOR_SHIFT) & 1U; + if (is_vendor == 0U) { + /* + * Only WARM_RESET is allowed for architectural type resets. + */ + if (reset_type != PSCI_RESET2_SYSTEM_WARM_RESET) + return (u_register_t) PSCI_E_INVALID_PARAMS; + if ((psci_plat_pm_ops->write_mem_protect != NULL) && + (psci_plat_pm_ops->write_mem_protect(0) < 0)) { + return (u_register_t) PSCI_E_NOT_SUPPORTED; + } + } + + /* Notify the Secure Payload Dispatcher */ + if ((psci_spd_pm != NULL) && (psci_spd_pm->svc_system_reset != NULL)) { + psci_spd_pm->svc_system_reset(); + } + console_flush(); + + return (u_register_t) + psci_plat_pm_ops->system_reset2((int) is_vendor, reset_type, + cookie); +} diff --git a/arm-trusted-firmware/lib/romlib/Makefile b/arm-trusted-firmware/lib/romlib/Makefile new file mode 100644 index 0000000..2ff480b --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/Makefile @@ -0,0 +1,98 @@ +# +# Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +AS = $(CROSS_COMPILE)as +AR = $(CROSS_COMPILE)ar +LD = $(CROSS_COMPILE)ld +OC = $(CROSS_COMPILE)objcopy +CPP = $(CROSS_COMPILE)cpp +ROMLIB_GEN = ./romlib_generator.py +BUILD_DIR = $(BUILD_PLAT)/romlib +LIB_DIR = $(BUILD_PLAT)/lib +WRAPPER_DIR = $(BUILD_PLAT)/libwrapper +LIBS = -lmbedtls -lfdt -lc +INC = $(INCLUDES:-I%=-I../../%) +PPFLAGS = $(INC) $(DEFINES) -P -x assembler-with-cpp -D__LINKER__ -MD -MP -MT $(BUILD_DIR)/romlib.ld +OBJS = $(BUILD_DIR)/jmptbl.o $(BUILD_DIR)/init.o +MAPFILE = $(BUILD_PLAT)/romlib/romlib.map + +ifneq ($(PLAT_DIR),) + WRAPPER_SOURCES = $(shell $(ROMLIB_GEN) genwrappers -b $(WRAPPER_DIR) --list ../../$(PLAT_DIR)/jmptbl.i) + WRAPPER_OBJS = $(WRAPPER_SOURCES:.s=.o) +endif + +V ?= 0 +ifeq ($(V),0) + Q := @ +else + Q := +endif + +LDFLAGS := --gc-sections -O1 +ifeq ($(DEBUG),1) + LDFLAGS += -Map=$(MAPFILE) +endif + +ifeq (${ARM_ARCH_MINOR},0) + ASFLAGS = -march=armv8-a +else + ASFLAGS = -march=armv8.${ARM_ARCH_MINOR}-a +endif + +.PHONY: all clean distclean + +all: $(BUILD_DIR)/romlib.bin $(LIB_DIR)/libwrappers.a + +%.o: %.s + @echo " AS $@" + $(Q)$(AS) $(ASFLAGS) -o $@ $< + +$(BUILD_DIR)/%.o: %.s + @echo " AS $@" + $(Q)$(AS) $(ASFLAGS) -o $@ $< + +$(BUILD_DIR)/romlib.ld: romlib.ld.S + @echo " PP $@" + $(Q)$(CPP) $(PPFLAGS) -o $@ romlib.ld.S + +$(BUILD_DIR)/romlib.elf: $(OBJS) $(BUILD_DIR)/romlib.ld + @echo " LD $@" + $(Q)$(LD) -T $(BUILD_DIR)/romlib.ld -L$(LIB_DIR) $(LDFLAGS) -o $@ $(OBJS) $(LIBS) + +$(BUILD_DIR)/romlib.bin: $(BUILD_DIR)/romlib.elf + @echo " BIN $@" + $(Q)$(OC) -O binary $(BUILD_DIR)/romlib.elf $@ + +$(WRAPPER_DIR)/jmpvar.s: $(BUILD_DIR)/romlib.elf + @echo " VAR $@" + $(Q)$(ROMLIB_GEN) genvar --output $@ $< + +$(LIB_DIR)/libwrappers.a: $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) + @echo " AR $@" + $(Q)$(AR) -rc $@ $(WRAPPER_DIR)/jmpvar.o $(WRAPPER_OBJS) + +$(BUILD_DIR)/jmptbl.i: ../../$(PLAT_DIR)/jmptbl.i + @echo " PRE $@" + $(Q)$(ROMLIB_GEN) pre --output $@ --deps $(BUILD_DIR)/jmptbl.d $< + +$(BUILD_DIR)/wrappers.stamp: $(BUILD_DIR)/jmptbl.i + @echo " WRP $<" + $(Q)$(ROMLIB_GEN) genwrappers --bti=$(ENABLE_BTI) -b $(WRAPPER_DIR) $< + @touch $@ + +$(WRAPPER_SOURCES): $(BUILD_DIR)/wrappers.stamp + +$(WRAPPER_OBJS): $(WRAPPER_SOURCES) $(BUILD_DIR)/wrappers.stamp + +$(BUILD_DIR)/jmptbl.s: $(BUILD_DIR)/jmptbl.i + @echo " TBL $@" + $(Q)$(ROMLIB_GEN) gentbl --output $@ --bti=$(ENABLE_BTI) $< + +clean: + @rm -f $(BUILD_DIR)/* + +-include $(BUILD_DIR)/romlib.d +-include $(BUILD_DIR)/jmptbl.d diff --git a/arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh b/arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh new file mode 100755 index 0000000..1e3f73a --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +set -e + +output="bl1_romlib.bin" + +# Set trap for removing temporary file +trap 'r=$?;rm -f $bin_path/$$.tmp;exit $r' EXIT HUP QUIT INT TERM + +# Read input parameters +for i +do + case $i in + -o) + output=$2 + shift 2 + ;; + --) + shift + break + ;; + -*) + echo usage: gen_combined_bl1_romlib.sh [-o output] path_to_build_directory >&2 + ;; + esac +done + + +bin_path=$1 +romlib_path=$1/romlib +bl1_file="$1/bl1/bl1.elf" +romlib_file="$1/romlib/romlib.elf" +bl1_end="" +romlib_begin="" + +# Get address of __BL1_ROM_END__ +bl1_end=`nm -a "$bl1_file" | +awk '$3 == "__BL1_ROM_END__" {print "0x"$1}'` + +# Get start address of romlib "text" section +romlib_begin=`nm -a "$romlib_file" | +awk '$3 == ".text" {print "0x"$1}'` + +# Character "U" will be read as "55" in hex when it is +# concatenated with bl1.bin. Generate combined BL1 and ROMLIB +# binary with filler bytes for juno +(cat $bin_path/bl1.bin + yes U | sed $(($romlib_begin - $bl1_end))q | tr -d '\n' + cat $bin_path/romlib/romlib.bin) > $bin_path/$$.tmp && +mv $bin_path/$$.tmp $bin_path/$output diff --git a/arm-trusted-firmware/lib/romlib/init.s b/arm-trusted-firmware/lib/romlib/init.s new file mode 100644 index 0000000..7d97e4d --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/init.s @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + .globl rom_lib_init + .extern __DATA_RAM_START__, __DATA_ROM_START__, __DATA_RAM_END__ + .extern memset, memcpy + +rom_lib_init: + cmp w0, #1 + mov w0, #0 + b.le 1f + ret + +1: stp x29, x30, [sp, #-16]! + adrp x0, __DATA_RAM_START__ + adrp x1, __DATA_ROM_START__ + add x1, x1, :lo12:__DATA_ROM_START__ + adrp x2, __DATA_RAM_END__ + add x2, x2, :lo12:__DATA_RAM_END__ + sub x2, x2, x0 + bl memcpy + + adrp x0,__BSS_START__ + add x0, x0, :lo12:__BSS_START__ + mov x1, #0 + adrp x2, __BSS_END__ + add x2, x2, :lo12:__BSS_END__ + sub x2, x2, x0 + bl memset + ldp x29, x30, [sp], #16 + + mov w0, #1 + ret diff --git a/arm-trusted-firmware/lib/romlib/jmptbl.i b/arm-trusted-firmware/lib/romlib/jmptbl.i new file mode 100644 index 0000000..33710f5 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/jmptbl.i @@ -0,0 +1,44 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# Format: +# lib function [patch] +# Add "patch" at the end of the line to patch a function. For example: +# mbedtls mbedtls_memory_buffer_alloc_init patch +# Holes can be introduced in the table by using a special keyword "reserved". +# Example: +# reserved reserved +# The jump table will contain an invalid instruction instead of branch + +rom rom_lib_init +fdt fdt_getprop_namelen +fdt fdt_setprop_inplace +fdt fdt_check_header +fdt fdt_node_offset_by_compatible +fdt fdt_setprop_inplace_namelen_partial +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/arm-trusted-firmware/lib/romlib/romlib.ld.S b/arm-trusted-firmware/lib/romlib/romlib.ld.S new file mode 100644 index 0000000..2aac4ad --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/romlib.ld.S @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +MEMORY { + ROM (rx): ORIGIN = ROMLIB_RO_BASE, LENGTH = ROMLIB_RO_LIMIT - ROMLIB_RO_BASE + RAM (rwx): ORIGIN = ROMLIB_RW_BASE, LENGTH = ROMLIB_RW_END - ROMLIB_RW_BASE +} + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(jmptbl) + +SECTIONS +{ + . = ROMLIB_RO_BASE; + .text : { + *jmptbl.o(.text) + *(.text*) + *(.rodata*) + } >ROM + + __DATA_ROM_START__ = LOADADDR(.data); + + .data : { + __DATA_RAM_START__ = .; + *(.data*) + __DATA_RAM_END__ = .; + } >RAM AT>ROM + + __DATA_SIZE__ = SIZEOF(.data); + + .bss : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + __BSS_SIZE__ = SIZEOF(.bss); +} diff --git a/arm-trusted-firmware/lib/romlib/romlib_generator.py b/arm-trusted-firmware/lib/romlib/romlib_generator.py new file mode 100755 index 0000000..0682dd4 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/romlib_generator.py @@ -0,0 +1,277 @@ +#!/usr/bin/env python3 +# Copyright (c) 2019, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +""" +This module contains a set of classes and a runner that can generate code for the romlib module +based on the templates in the 'templates' directory. +""" + +import argparse +import os +import re +import subprocess +import string +import sys + +class IndexFileParser: + """ + Parses the contents of the index file into the items and dependencies variables. It + also resolves included files in the index files recursively with circular inclusion detection. + """ + + def __init__(self): + self.items = [] + self.dependencies = {} + self.include_chain = [] + + def add_dependency(self, parent, dependency): + """ Adds a dependency into the dependencies variable. """ + if parent in self.dependencies: + self.dependencies[parent].append(dependency) + else: + self.dependencies[parent] = [dependency] + + def get_dependencies(self, parent): + """ Gets all the recursive dependencies of a parent file. """ + parent = os.path.normpath(parent) + if parent in self.dependencies: + direct_deps = self.dependencies[parent] + deps = direct_deps + for direct_dep in direct_deps: + deps += self.get_dependencies(direct_dep) + return deps + + return [] + + def parse(self, file_name): + """ Opens and parses index file. """ + file_name = os.path.normpath(file_name) + + if file_name not in self.include_chain: + self.include_chain.append(file_name) + self.dependencies[file_name] = [] + else: + raise Exception("Circular dependency detected: " + file_name) + + with open(file_name, "r") as index_file: + for line in index_file.readlines(): + line_elements = line.split() + + if line.startswith("#") or not line_elements: + # Comment or empty line + continue + + if line_elements[0] == "reserved": + # Reserved slot in the jump table + self.items.append({"type": "reserved"}) + elif line_elements[0] == "include" and len(line_elements) > 1: + # Include other index file + included_file = os.path.normpath(line_elements[1]) + self.add_dependency(file_name, included_file) + self.parse(included_file) + elif len(line_elements) > 1: + # Library function + library_name = line_elements[0] + function_name = line_elements[1] + patch = bool(len(line_elements) > 2 and line_elements[2] == "patch") + + self.items.append({"type": "function", "library_name": library_name, + "function_name": function_name, "patch": patch}) + else: + raise Exception("Invalid line: '" + line + "'") + + self.include_chain.pop() + +class RomlibApplication: + """ Base class of romlib applications. """ + TEMPLATE_DIR = os.path.dirname(os.path.realpath(__file__)) + "/templates/" + + def __init__(self, prog): + self.args = argparse.ArgumentParser(prog=prog, description=self.__doc__) + self.config = None + + def parse_arguments(self, argv): + """ Parses the arguments that should come from the command line arguments. """ + self.config = self.args.parse_args(argv) + + def build_template(self, name, mapping=None, remove_comment=False): + """ + Loads a template and builds it with the defined mapping. Template paths are always relative + to this script. + """ + + with open(self.TEMPLATE_DIR + name, "r") as template_file: + if remove_comment: + # Removing copyright comment to make the generated code more readable when the + # template is inserted multiple times into the output. + template_lines = template_file.readlines() + end_of_comment_line = 0 + for index, line in enumerate(template_lines): + if line.find("*/") != -1: + end_of_comment_line = index + break + template_data = "".join(template_lines[end_of_comment_line + 1:]) + else: + template_data = template_file.read() + + template = string.Template(template_data) + return template.substitute(mapping) + +class IndexPreprocessor(RomlibApplication): + """ Removes empty and comment lines from the index file and resolves includes. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--deps", help="Dependency file") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + After parsing the input index file it generates a clean output with all includes resolved. + Using --deps option it also outputs the dependencies in makefile format like gcc's with -M. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + for item in index_file_parser.items: + if item["type"] == "function": + patch = "\tpatch" if item["patch"] else "" + output_file.write( + item["library_name"] + "\t" + item["function_name"] + patch + "\n") + else: + output_file.write("reserved\n") + + if self.config.deps: + with open(self.config.deps, "w") as deps_file: + deps = [self.config.file] + index_file_parser.get_dependencies(self.config.file) + deps_file.write(self.config.output + ": " + " \\\n".join(deps) + "\n") + +class TableGenerator(RomlibApplication): + """ Generates the jump table by parsing the index file. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Inserts the jmptbl definition and the jump entries into the output file. Also can insert + BTI related code before entries if --bti option set. It can output a dependency file of the + included index files. This can be directly included in makefiles. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_header.S")) + bti = "_bti" if self.config.bti == 1 else "" + + for item in index_file_parser.items: + template_name = "jmptbl_entry_" + item["type"] + bti + ".S" + output_file.write(self.build_template(template_name, item, True)) + +class WrapperGenerator(RomlibApplication): + """ + Generates a wrapper function for each entry in the index file except for the ones that contain + the keyword patch. The generated wrapper file is called _.s. + """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-b", help="Build directory", default=".", metavar="build") + self.args.add_argument("--bti", help="Branch Target Identification", type=int) + self.args.add_argument("--list", help="Only list assembly files", action="store_true") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Iterates through the items in the parsed index file and builds the template for each entry. + """ + + index_file_parser = IndexFileParser() + index_file_parser.parse(self.config.file) + + bti = "_bti" if self.config.bti == 1 else "" + function_offset = 0 + files = [] + + for item_index in range(0, len(index_file_parser.items)): + item = index_file_parser.items[item_index] + + if item["type"] == "reserved" or item["patch"]: + continue + + asm = self.config.b + "/" + item["function_name"] + ".s" + if self.config.list: + # Only listing files + files.append(asm) + else: + with open(asm, "w") as asm_file: + # The jump instruction is 4 bytes but BTI requires and extra instruction so + # this makes it 8 bytes per entry. + function_offset = item_index * (8 if self.config.bti else 4) + + item["function_offset"] = function_offset + asm_file.write(self.build_template("wrapper" + bti + ".S", item)) + + if self.config.list: + print(" ".join(files)) + +class VariableGenerator(RomlibApplication): + """ Generates the jump table global variable with the absolute address in ROM. """ + + def __init__(self, prog): + RomlibApplication.__init__(self, prog) + + self.args.add_argument("-o", "--output", help="Output file", metavar="output", + default="jmpvar.s") + self.args.add_argument("file", help="Input file") + + def main(self): + """ + Runs nm -a command on the input file and inserts the address of the .text section into the + template as the ROM address of the jmp_table. + """ + symbols = subprocess.check_output(["nm", "-a", self.config.file]) + + matching_symbol = re.search("([0-9A-Fa-f]+) . \\.text", str(symbols)) + if not matching_symbol: + raise Exception("No '.text' section was found in %s" % self.config.file) + + mapping = {"jmptbl_address": matching_symbol.group(1)} + + with open(self.config.output, "w") as output_file: + output_file.write(self.build_template("jmptbl_glob_var.S", mapping)) + +if __name__ == "__main__": + APPS = {"genvar": VariableGenerator, "pre": IndexPreprocessor, + "gentbl": TableGenerator, "genwrappers": WrapperGenerator} + + if len(sys.argv) < 2 or sys.argv[1] not in APPS: + print("usage: romlib_generator.py [%s] [args]" % "|".join(APPS.keys()), file=sys.stderr) + sys.exit(1) + + APP = APPS[sys.argv[1]]("romlib_generator.py " + sys.argv[1]) + APP.parse_arguments(sys.argv[2:]) + try: + APP.main() + sys.exit(0) + except FileNotFoundError as file_not_found_error: + print(file_not_found_error, file=sys.stderr) + except subprocess.CalledProcessError as called_process_error: + print(called_process_error.output, file=sys.stderr) + + sys.exit(1) diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S new file mode 100644 index 0000000..a0f8456 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b ${function_name} diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S new file mode 100644 index 0000000..d96ee94 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b ${function_name} diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S new file mode 100644 index 0000000..a9b5f18 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S @@ -0,0 +1,6 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + b . diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S new file mode 100644 index 0000000..a9f0375 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S @@ -0,0 +1,7 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + bti j + b . diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S new file mode 100644 index 0000000..d306512 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S @@ -0,0 +1,9 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .data + .globl jmptbl + .align 4 +jmptbl: .quad 0x${jmptbl_address} diff --git a/arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S b/arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S new file mode 100644 index 0000000..72b8ce5 --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S @@ -0,0 +1,8 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .text + .globl jmptbl +jmptbl: diff --git a/arm-trusted-firmware/lib/romlib/templates/wrapper.S b/arm-trusted-firmware/lib/romlib/templates/wrapper.S new file mode 100644 index 0000000..734a68a --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/wrapper.S @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S b/arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S new file mode 100644 index 0000000..ba9b11c --- /dev/null +++ b/arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2019, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + .globl ${function_name} +${function_name}: + bti jc + ldr x17, =jmptbl + mov x16, #${function_offset} + ldr x17, [x17] + add x16, x16, x17 + br x16 diff --git a/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S b/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S new file mode 100644 index 0000000..aced3d1 --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl semihosting_call + +func semihosting_call + svc #0x123456 + bx lr +endfunc semihosting_call diff --git a/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S b/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S new file mode 100644 index 0000000..97d2bca --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl semihosting_call + +func semihosting_call + hlt #0xf000 + ret +endfunc semihosting_call diff --git a/arm-trusted-firmware/lib/semihosting/semihosting.c b/arm-trusted-firmware/lib/semihosting/semihosting.c new file mode 100644 index 0000000..e0845c1 --- /dev/null +++ b/arm-trusted-firmware/lib/semihosting/semihosting.c @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#ifndef SEMIHOSTING_SUPPORTED +#define SEMIHOSTING_SUPPORTED 1 +#endif + +long semihosting_call(unsigned long operation, uintptr_t system_block_address); + +typedef struct { + const char *file_name; + unsigned long mode; + size_t name_length; +} smh_file_open_block_t; + +typedef struct { + long handle; + uintptr_t buffer; + size_t length; +} smh_file_read_write_block_t; + +typedef struct { + long handle; + ssize_t location; +} smh_file_seek_block_t; + +typedef struct { + char *command_line; + size_t command_length; +} smh_system_block_t; + +long semihosting_connection_supported(void) +{ + return SEMIHOSTING_SUPPORTED; +} + +long semihosting_file_open(const char *file_name, size_t mode) +{ + smh_file_open_block_t open_block; + + open_block.file_name = file_name; + open_block.mode = mode; + open_block.name_length = strlen(file_name); + + return semihosting_call(SEMIHOSTING_SYS_OPEN, (uintptr_t)&open_block); +} + +long semihosting_file_seek(long file_handle, ssize_t offset) +{ + smh_file_seek_block_t seek_block; + long result; + + seek_block.handle = file_handle; + seek_block.location = offset; + + result = semihosting_call(SEMIHOSTING_SYS_SEEK, (uintptr_t)&seek_block); + + if (result != 0) { + result = semihosting_call(SEMIHOSTING_SYS_ERRNO, 0); + } + + return result; +} + +long semihosting_file_read(long file_handle, size_t *length, uintptr_t buffer) +{ + smh_file_read_write_block_t read_block; + long result = -EINVAL; + + if ((length == NULL) || (buffer == (uintptr_t)NULL)) { + return result; + } + + read_block.handle = file_handle; + read_block.buffer = buffer; + read_block.length = *length; + + result = semihosting_call(SEMIHOSTING_SYS_READ, (uintptr_t)&read_block); + + if (result == *length) { + return -EINVAL; + } else if (result < *length) { + *length -= result; + return 0; + } else { + return result; + } +} + +long semihosting_file_write(long file_handle, size_t *length, + const uintptr_t buffer) +{ + smh_file_read_write_block_t write_block; + long result = -EINVAL; + + if ((length == NULL) || (buffer == (uintptr_t)NULL)) { + return -EINVAL; + } + + write_block.handle = file_handle; + write_block.buffer = (uintptr_t)buffer; /* cast away const */ + write_block.length = *length; + + result = semihosting_call(SEMIHOSTING_SYS_WRITE, + (uintptr_t)&write_block); + + *length = result; + + return (result == 0) ? 0 : -EINVAL; +} + +long semihosting_file_close(long file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_CLOSE, (uintptr_t)&file_handle); +} + +long semihosting_file_length(long file_handle) +{ + return semihosting_call(SEMIHOSTING_SYS_FLEN, (uintptr_t)&file_handle); +} + +char semihosting_read_char(void) +{ + return semihosting_call(SEMIHOSTING_SYS_READC, 0); +} + +void semihosting_write_char(char character) +{ + semihosting_call(SEMIHOSTING_SYS_WRITEC, (uintptr_t)&character); +} + +void semihosting_write_string(char *string) +{ + semihosting_call(SEMIHOSTING_SYS_WRITE0, (uintptr_t)string); +} + +long semihosting_system(char *command_line) +{ + smh_system_block_t system_block; + + system_block.command_line = command_line; + system_block.command_length = strlen(command_line); + + return semihosting_call(SEMIHOSTING_SYS_SYSTEM, + (uintptr_t)&system_block); +} + +long semihosting_get_flen(const char *file_name) +{ + long file_handle; + long length; + + assert(semihosting_connection_supported() != 0); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) { + return file_handle; + } + + /* Find the length of the file */ + length = semihosting_file_length(file_handle); + + return (semihosting_file_close(file_handle) != 0) ? -1 : length; +} + +long semihosting_download_file(const char *file_name, + size_t buf_size, + uintptr_t buf) +{ + long ret = -EINVAL; + size_t length; + long file_handle; + + /* Null pointer check */ + if (buf == 0U) { + return ret; + } + + assert(semihosting_connection_supported() != 0); + + file_handle = semihosting_file_open(file_name, FOPEN_MODE_RB); + if (file_handle == -1) { + return ret; + } + + /* Find the actual length of the file */ + length = semihosting_file_length(file_handle); + if (length == (size_t)(-1)) { + goto semihosting_fail; + } + + /* Signal error if we do not have enough space for the file */ + if (length > buf_size) { + goto semihosting_fail; + } + + /* + * A successful read will return 0 in which case we pass back + * the actual number of bytes read. Else we pass a negative + * value indicating an error. + */ + ret = semihosting_file_read(file_handle, &length, buf); + if (ret != 0) { + goto semihosting_fail; + } else { + ret = (long)length; + } + +semihosting_fail: + semihosting_file_close(file_handle); + return ret; +} + +void semihosting_exit(uint32_t reason, uint32_t subcode) +{ +#ifdef __aarch64__ + uint64_t parameters[] = {reason, subcode}; + + (void)semihosting_call(SEMIHOSTING_SYS_EXIT, (uintptr_t)¶meters); +#else + /* The subcode is not supported on AArch32. */ + (void)semihosting_call(SEMIHOSTING_SYS_EXIT, reason); +#endif +} diff --git a/arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S b/arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S new file mode 100644 index 0000000..19b7525 --- /dev/null +++ b/arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl update_stack_protector_canary + +/* ----------------------------------------------------------------------- + * void update_stack_protector_canary(void) + * + * Change the value of the canary used for stack smashing attacks protection. + * Note: This must be called when it is safe to call C code, but this cannot be + * called by C code. Doing this will make the check fail when the calling + * function returns. + * ----------------------------------------------------------------------- + */ + +func update_stack_protector_canary + /* Use r4 as it is callee-saved */ + mov r4, lr + bl plat_get_stack_protector_canary + + /* Update the canary with the returned value */ + ldr r1, =__stack_chk_guard + str r0, [r1] + bx r4 +endfunc update_stack_protector_canary + + diff --git a/arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S b/arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S new file mode 100644 index 0000000..c2245d3 --- /dev/null +++ b/arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .globl update_stack_protector_canary + +/* ----------------------------------------------------------------------- + * void update_stack_protector_canary(void) + * + * Change the value of the canary used for stack smashing attacks protection. + * Note: This must be called when it is safe to call C code, but this cannot be + * called by C code. Doing this will make the check fail when the calling + * function returns. + * ----------------------------------------------------------------------- + */ + +func update_stack_protector_canary + /* Use x19 as it is callee-saved */ + mov x19, x30 + bl plat_get_stack_protector_canary + + /* Update the canary with the returned value */ + adrp x1, __stack_chk_guard + str x0, [x1, #:lo12:__stack_chk_guard] + ret x19 +endfunc update_stack_protector_canary + + diff --git a/arm-trusted-firmware/lib/stack_protector/stack_protector.c b/arm-trusted-firmware/lib/stack_protector/stack_protector.c new file mode 100644 index 0000000..3ff74fc --- /dev/null +++ b/arm-trusted-firmware/lib/stack_protector/stack_protector.c @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* + * Canary value used by the compiler runtime checks to detect stack corruption. + * + * Force the canary to be in .data to allow predictable memory layout relatively + * to the stacks. + */ +u_register_t __attribute__((section(".data.stack_protector_canary"))) + __stack_chk_guard = (u_register_t) 3288484550995823360ULL; + +/* + * Function called when the stack's canary check fails, which means the stack + * was corrupted. It must not return. + */ +void __dead2 __stack_chk_fail(void) +{ +#if DEBUG + ERROR("Stack corruption detected\n"); +#endif + panic(); +} + diff --git a/arm-trusted-firmware/lib/stack_protector/stack_protector.mk b/arm-trusted-firmware/lib/stack_protector/stack_protector.mk new file mode 100644 index 0000000..b5aba15 --- /dev/null +++ b/arm-trusted-firmware/lib/stack_protector/stack_protector.mk @@ -0,0 +1,28 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Boolean macro to be used in C code +STACK_PROTECTOR_ENABLED := 0 + +ifeq (${ENABLE_STACK_PROTECTOR},0) + ENABLE_STACK_PROTECTOR := none +endif + +ifeq (${ENABLE_STACK_PROTECTOR},none) + TF_CFLAGS += -fno-stack-protector +else + STACK_PROTECTOR_ENABLED := 1 + BL_COMMON_SOURCES += lib/stack_protector/stack_protector.c \ + lib/stack_protector/${ARCH}/asm_stack_protector.S + + ifeq (${ENABLE_STACK_PROTECTOR},default) + TF_CFLAGS += -fstack-protector + else + TF_CFLAGS += -fstack-protector-${ENABLE_STACK_PROTECTOR} + endif +endif + +$(eval $(call add_define,STACK_PROTECTOR_ENABLED)) diff --git a/arm-trusted-firmware/lib/utils/mem_region.c b/arm-trusted-firmware/lib/utils/mem_region.c new file mode 100644 index 0000000..fec086b --- /dev/null +++ b/arm-trusted-firmware/lib/utils/mem_region.c @@ -0,0 +1,139 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/* + * All the regions defined in mem_region_t must have the following properties + * + * - Any contiguous regions must be merged into a single entry. + * - The number of bytes of each region must be greater than zero. + * - The calculation of the highest address within the region (base + nbytes-1) + * doesn't produce an overflow. + * + * These conditions must be fulfilled by the caller and they aren't checked + * at runtime. + */ + +/* + * zero_normalmem all the regions defined in tbl. + * It assumes that MMU is enabled and the memory is Normal memory. + * tbl must be a valid pointer to a memory mem_region_t array, + * nregions is the size of the array. + */ +void clear_mem_regions(mem_region_t *tbl, size_t nregions) +{ + size_t i; + + assert(tbl != NULL); + assert(nregions > 0U); + + for (i = 0; i < nregions; i++) { + assert(tbl->nbytes > 0); + assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); + zero_normalmem((void *) (tbl->base), tbl->nbytes); + tbl++; + } +} + +#if defined(PLAT_XLAT_TABLES_DYNAMIC) +/* + * zero_normalmem all the regions defined in regions. + * It assumes that MMU is enabled and the memory is Normal memory. + * regions must be a valid pointer to a memory mem_region_t array, + * nregions is the size of the array. va is the virtual address + * where we want to map the physical pages that are going to + * be cleared, and chunk is the amount of memory mapped and + * cleared in every iteration. + */ +void clear_map_dyn_mem_regions(struct mem_region *regions, + size_t nregions, + uintptr_t va, + size_t chunk) +{ + uintptr_t begin; + int r; + size_t size; + const unsigned int attr = MT_MEMORY | MT_RW | MT_NS; + + assert(regions != NULL); + assert(nregions != 0U); + assert(chunk != 0U); + + for (unsigned int i = 0U; i < nregions; i++) { + begin = regions[i].base; + size = regions[i].nbytes; + if (((begin & (chunk-1U)) != 0U) || + ((size & (chunk-1U)) != 0U)) { + INFO("PSCI: Not correctly aligned region\n"); + panic(); + } + + while (size > 0U) { + r = mmap_add_dynamic_region(begin, va, chunk, attr); + if (r != 0) { + INFO("PSCI: %s failed with %d\n", + "mmap_add_dynamic_region", r); + panic(); + } + + zero_normalmem((void *)va, chunk); + + r = mmap_remove_dynamic_region(va, chunk); + if (r != 0) { + INFO("PSCI: %s failed with %d\n", + "mmap_remove_dynamic_region", r); + panic(); + } + + begin += chunk; + size -= chunk; + } + } +} +#endif + +/* + * This function checks that a region (addr + nbytes-1) of memory is totally + * covered by one of the regions defined in tbl. + * tbl must be a valid pointer to a memory mem_region_t array, nregions + * is the size of the array and the region described by addr and nbytes must + * not generate an overflow. + * Returns: + * -1 means that the region is not covered by any of the regions + * described in tbl. + * 0 the region (addr + nbytes-1) is covered by one of the regions described + * in tbl + */ +int mem_region_in_array_chk(mem_region_t *tbl, size_t nregions, + uintptr_t addr, size_t nbytes) +{ + uintptr_t region_start, region_end, start, end; + size_t i; + + assert(tbl != NULL); + assert(nbytes != 0U); + assert(!check_uptr_overflow(addr, nbytes-1)); + + region_start = addr; + region_end = addr + (nbytes - 1U); + for (i = 0U; i < nregions; i++) { + assert(tbl->nbytes > 0); + assert(!check_uptr_overflow(tbl->base, tbl->nbytes-1)); + start = tbl->base; + end = start + (tbl->nbytes - 1); + if ((region_start >= start) && (region_end <= end)) { + return 0; + } + tbl++; + } + + return -1; +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S b/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S new file mode 100644 index 0000000..3791f2d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .global enable_mpu_direct_el2 + + /* void enable_mmu_direct_el2(unsigned int flags) */ +func enable_mpu_direct_el2 +#if ENABLE_ASSERTIONS + mrs x1, sctlr_el2 + tst x1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + mov x7, x0 + adrp x0, mmu_cfg_params + add x0, x0, :lo12:mmu_cfg_params + + /* (MAIRs are already set up) */ + + /* TCR */ + ldr x2, [x0, #(MMU_CFG_TCR << 3)] + msr tcr_el2, x2 + + /* + * Ensure all translation table writes have drained into memory, the TLB + * invalidation is complete, and translation register writes are + * committed before enabling the MMU + */ + dsb ish + isb + + /* Set and clear required fields of SCTLR */ + mrs x4, sctlr_el2 + mov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT + orr x4, x4, x5 + + /* Additionally, amend SCTLR fields based on flags */ + bic x5, x4, #SCTLR_C_BIT + tst x7, #DISABLE_DCACHE + csel x4, x5, x4, ne + + msr sctlr_el2, x4 + isb + + ret +endfunc enable_mpu_direct_el2 diff --git a/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c b/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c new file mode 100644 index 0000000..5068eb8 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../xlat_mpu_private.h" +#include +#include +#include +#include +#include + +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + +#if ENABLE_ASSERTIONS +/* + * Return minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + uintptr_t ret; + + if (is_armv8_4_ttst_present()) { + ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST; + } else { + ret = MIN_VIRT_ADDR_SPACE_SIZE; + } + return ret; +} +#endif /* ENABLE_ASSERTIONS*/ + +bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx) +{ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1U); + return (read_sctlr_el1() & SCTLR_M_BIT) != 0U; + } else { + assert(xlat_arch_current_el() >= 2U); + return (read_sctlr_el2() & SCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + unsigned int el = get_current_el(); + + if (el == 1U) { + return (read_sctlr_el1() & SCTLR_C_BIT) != 0U; + } else { /* must be EL2 */ + return (read_sctlr_el2() & SCTLR_C_BIT) != 0U; + } +} + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + diff --git a/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk b/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk new file mode 100644 index 0000000..23f1d46 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/ro_xlat_mpu.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2021, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${USE_DEBUGFS}, 1) + $(error "Debugfs requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") +endif + +ifeq (${ARCH},aarch32) + $(error "The xlat_mpu library does not currently support AArch32.") +endif diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk new file mode 100644 index 0000000..041b91c --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XLAT_MPU_LIB_V1_SRCS := $(addprefix lib/xlat_mpu/, \ + ${ARCH}/enable_mpu.S \ + ${ARCH}/xlat_mpu_arch.c \ + xlat_mpu_context.c \ + xlat_mpu_core.c \ + xlat_mpu_utils.c) + +XLAT_MPU_LIB_V1 := 1 +$(eval $(call add_define,XLAT_MPU_LIB_V1)) + +ifeq (${ALLOW_XLAT_MPU}, 1) + include lib/xlat_mpu_v2/ro_xlat_mpu.mk +endif diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c new file mode 100644 index 0000000..28c463b --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "lib/xlat_mpu/xlat_mpu.h" +#include +#include +#include "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +/* + * MMU configuration register values for the active translation context. Used + * from the MMU assembly helpers. + */ +uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* + * Allocate and initialise the default translation context for the BL image + * currently executing. + */ +REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE); + +void mmap_add(const mmap_region_t *mm) +{ + mmap_add_ctx(&tf_xlat_ctx, mm); +} + +void __init init_xlat_tables(void) +{ + assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); + + unsigned int current_el = xlat_arch_current_el(); + + if (current_el == 1U) { + tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME; + } else { + assert(current_el == 2U); + tf_xlat_ctx.xlat_regime = EL2_REGIME; + } + /* Note: If EL3 is supported in future v8-R64, add EL3 assignment */ + init_xlat_tables_ctx(&tf_xlat_ctx); +} + +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr) +{ + return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr); +} + +void enable_mpu_el2(unsigned int flags) +{ + /* EL2 is strictly MPU on v8-R64, so no need for setup_mpu_cfg() */ + enable_mpu_direct_el2(flags); +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c new file mode 100644 index 0000000..6b4b0c2 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +/* Helper function that cleans the data cache only if it is enabled. */ +static inline __attribute__((unused)) + void xlat_clean_dcache_range(uintptr_t addr, size_t size) +{ + if (is_dcache_enabled()) { + clean_dcache_range(addr, size); + } +} + + + +/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */ +uint64_t prbar_attr_value(uint32_t attr) +{ + uint64_t retValue = UL(0); + uint64_t extract; /* temp var holding bit extracted from attr */ + + /* Extract and stuff SH: */ + extract = (uint64_t) ((attr >> MT_SHAREABILITY_SHIFT) + & MT_SHAREABILITY_MASK); + retValue |= (extract << PRBAR_SH_SHIFT); + + /* Extract and stuff AP: */ + extract = (uint64_t) ((attr >> MT_PERM_SHIFT) & MT_PERM_MASK); + if (extract == 0U) { + retValue |= (UL(2) << PRBAR_AP_SHIFT); + } else /* extract == 1 */ { + retValue |= (UL(0) << PRBAR_AP_SHIFT); + } + + /* Extract and stuff XN: */ + extract = (uint64_t) ((attr >> MT_EXECUTE_SHIFT) & MT_EXECUTE_MASK); + retValue |= (extract << PRBAR_XN_SHIFT); + /* However, also don't execute in peripheral space: */ + extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) & MT_TYPE_MASK); + if (extract == 0U) { + retValue |= (UL(1) << PRBAR_XN_SHIFT); + } + return retValue; +} + +/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */ +uint64_t prlar_attr_value(uint32_t attr) +{ + uint64_t retValue = UL(0); + uint64_t extract; /* temp var holding bit extracted from attr */ + + /* Extract and stuff AttrIndx: */ + extract = (uint64_t) ((attr >> MT_TYPE_SHIFT) + & MT_TYPE_MASK); + switch (extract) { + case UL(0): + retValue |= (UL(1) << PRLAR_ATTR_SHIFT); + break; + case UL(2): + /* 0, so OR in nothing */ + break; + case UL(3): + retValue |= (UL(2) << PRLAR_ATTR_SHIFT); + break; + default: + retValue |= (extract << PRLAR_ATTR_SHIFT); + break; + } + + /* Stuff EN: */ + retValue |= (UL(1) << PRLAR_EN_SHIFT); + + /* Force NS to 0 (Secure); v8-R64 only supports Secure: */ + extract = ~(1U << PRLAR_NS_SHIFT); + retValue &= extract; + + return retValue; +} + +/* + * Function that writes an MPU "translation" into the MPU registers. If not + * possible (e.g., if no more MPU regions available) boot is aborted. + */ +static void mpu_map_region(mmap_region_t *mm) +{ + uint64_t prenr_el2_value = 0UL; + uint64_t prbar_attrs = 0UL; + uint64_t prlar_attrs = 0UL; + int region_to_use = 0; + + /* If all MPU regions in use, then abort boot: */ + prenr_el2_value = read_prenr_el2(); + assert(prenr_el2_value != 0xffffffff); + + /* Find and select first-available MPU region (PRENR has an enable bit + * for each MPU region, 1 for in-use or 0 for unused): + */ + for (region_to_use = 0; region_to_use < N_MPU_REGIONS; + region_to_use++) { + if (((prenr_el2_value >> region_to_use) & 1) == 0) { + break; + } + } + write_prselr_el2((uint64_t) (region_to_use)); + isb(); + + /* Set base and limit addresses: */ + write_prbar_el2(mm->base_pa & PRBAR_PRLAR_ADDR_MASK); + write_prlar_el2((mm->base_pa + mm->size - 1UL) + & PRBAR_PRLAR_ADDR_MASK); + dsbsy(); + isb(); + + /* Set attributes: */ + prbar_attrs = prbar_attr_value(mm->attr); + write_prbar_el2(read_prbar_el2() | prbar_attrs); + prlar_attrs = prlar_attr_value(mm->attr); + write_prlar_el2(read_prlar_el2() | prlar_attrs); + dsbsy(); + isb(); + + /* Mark this MPU region as used: */ + prenr_el2_value |= (1 << region_to_use); + write_prenr_el2(prenr_el2_value); + isb(); +} + +/* + * Function that verifies that a region can be mapped. + * Returns: + * 0: Success, the mapping is allowed. + * EINVAL: Invalid values were used as arguments. + * ERANGE: The memory limits were surpassed. + * ENOMEM: There is not enough memory in the mmap array. + * EPERM: Region overlaps another one in an invalid way. + */ +static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + unsigned long long base_pa = mm->base_pa; + uintptr_t base_va = mm->base_va; + size_t size = mm->size; + + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + if (base_pa != base_va) { + return -EINVAL; /* MPU does not perform address translation */ + } + if ((base_pa % 64ULL) != 0ULL) { + return -EINVAL; /* MPU requires 64-byte alignment */ + } + /* Check for overflows */ + if ((base_pa > end_pa) || (base_va > end_va)) { + return -ERANGE; + } + if (end_pa > ctx->pa_max_address) { + return -ERANGE; + } + /* Check that there is space in the ctx->mmap array */ + if (ctx->mmap[ctx->mmap_num - 1].size != 0U) { + return -ENOMEM; + } + /* Check for PAs and VAs overlaps with all other regions */ + for (const mmap_region_t *mm_cursor = ctx->mmap; + mm_cursor->size != 0U; ++mm_cursor) { + + uintptr_t mm_cursor_end_va = + mm_cursor->base_va + mm_cursor->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm_cursor->base_va) && + (end_va <= mm_cursor_end_va)) || + ((mm_cursor->base_va >= base_va) && + (mm_cursor_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + * This can only be done with static regions. + */ + if (fully_overlapped_va) { + +#if PLAT_XLAT_TABLES_DYNAMIC + if (((mm->attr & MT_DYNAMIC) != 0U) || + ((mm_cursor->attr & MT_DYNAMIC) != 0U)) { + return -EPERM; + } +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + if ((mm_cursor->base_va - mm_cursor->base_pa) + != (base_va - base_pa)) { + return -EPERM; + } + if ((base_va == mm_cursor->base_va) && + (size == mm_cursor->size)) { + return -EPERM; + } + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_cursor_end_pa = + mm_cursor->base_pa + mm_cursor->size - 1U; + + bool separated_pa = (end_pa < mm_cursor->base_pa) || + (base_pa > mm_cursor_end_pa); + bool separated_va = (end_va < mm_cursor->base_va) || + (base_va > mm_cursor_end_va); + + if (!separated_va || !separated_pa) { + return -EPERM; + } + } + } + + return 0; +} + +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + mmap_region_t *mm_cursor = ctx->mmap, *mm_destination; + const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num; + const mmap_region_t *mm_last; + unsigned long long end_pa = mm->base_pa + mm->size - 1U; + uintptr_t end_va = mm->base_va + mm->size - 1U; + int ret; + + /* Ignore empty regions */ + if (mm->size == 0U) { + return; + } + + /* Static regions must be added before initializing the xlat tables. */ + assert(!ctx->initialized); + + ret = mmap_add_region_check(ctx, mm); + if (ret != 0) { + ERROR("mmap_add_region_check() failed. error %d\n", ret); + assert(false); + return; + } + + /* + * Find the last entry marker in the mmap + */ + mm_last = ctx->mmap; + while ((mm_last->size != 0U) && (mm_last < mm_end)) { + ++mm_last; + } + + /* + * Check if we have enough space in the memory mapping table. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_last->size == 0U); + + /* Make room for new region by moving other regions up by one place */ + mm_destination = mm_cursor + 1; + (void)memmove(mm_destination, mm_cursor, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check we haven't lost the empty sentinel from the end of the array. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_end->size == 0U); + + *mm_cursor = *mm; + + if (end_pa > ctx->max_pa) { + ctx->max_pa = end_pa; + } + if (end_va > ctx->max_va) { + ctx->max_va = end_va; + } +} + +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while (mm_cursor->granularity != 0U) { + mmap_add_region_ctx(ctx, mm_cursor); + mm_cursor++; + } +} + +void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) +{ + uint64_t mair = UL(0); + + assert(ctx != NULL); + assert(!ctx->initialized); + assert((ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL1_EL0_REGIME)); + /* Note: Add EL3_REGIME if EL3 is supported in future v8-R64 cores. */ + assert(!is_mpu_enabled_ctx(ctx)); + + mmap_region_t *mm = ctx->mmap; + + assert(ctx->va_max_address >= + (xlat_get_min_virt_addr_space_size() - 1U)); + assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U)); + + xlat_mmap_print(mm); + + /* All tables must be zeroed before mapping any region. */ + + for (unsigned int i = 0U; i < ctx->base_table_entries; i++) + ctx->base_table[i] = INVALID_DESC; + + /* Also mark all MPU regions as invalid in the MPU hardware itself: */ + write_prenr_el2(0); + /* Sufficient for current, max-32-region implementations. */ + dsbsy(); + isb(); + while (mm->size != 0U) { + if (read_prenr_el2() == ALL_MPU_EL2_REGIONS_USED) { + ERROR("Not enough MPU regions to map region:\n" + " VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n", + mm->base_va, mm->base_pa, mm->size, mm->attr); + panic(); + } else { +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)mm->base_va, + mm->size); +#endif + mpu_map_region(mm); + } + mm++; + } + + ctx->initialized = true; + + xlat_tables_print(ctx); + + /* Set attributes in the right indices of the MAIR */ + mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, + ATTR_NON_CACHEABLE_INDEX); + write_mair_el2(mair); + dsbsy(); + isb(); +} + +/* + * Function to wipe clean and disable all MPU regions. This function expects + * that the MPU has already been turned off, and caching concerns addressed, + * but it nevertheless also explicitly turns off the MPU. + */ +void clear_all_mpu_regions(void) +{ + uint64_t sctlr_el2_value = 0UL; + uint64_t region_n = 0UL; + + /* + * MPU should already be disabled, but explicitly disable it + * nevertheless: + */ + sctlr_el2_value = read_sctlr_el2() & ~(1UL); + write_sctlr_el2(sctlr_el2_value); + + /* Disable all regions: */ + write_prenr_el2(0UL); + + /* Sequence through all regions, zeroing them out and turning off: */ + for (region_n = 0UL; region_n < N_MPU_REGIONS; region_n++) { + write_prselr_el2(region_n); + isb(); + write_prbar_el2((uint64_t) 0); + write_prlar_el2((uint64_t) 0); + dsbsy(); + isb(); + } +} diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h new file mode 100644 index 0000000..e0e479d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_MPU_PRIVATE_H +#define XLAT_MPU_PRIVATE_H + +#include + +#include +#include + +#include + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Private shifts and masks to access fields of an mmap attribute + */ +/* Dynamic or static */ +#define MT_DYN_SHIFT U(31) + +/* + * Memory mapping private attributes + * + * Private attributes not exposed in the public header. + */ + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* Calculate region-attributes byte for PRBAR part of MPU-region descriptor: */ +uint64_t prbar_attr_value(uint32_t attr); +/* Calculate region-attributes byte for PRLAR part of MPU-region descriptor: */ +uint64_t prlar_attr_value(uint32_t attr); +/* Calculates the attr value for a given PRBAR and PRLAR entry value: */ +uint32_t region_attr(uint64_t prbar_attr, uint64_t prlar_attr); + +#define PRBAR_PRLAR_ADDR_MASK UL(0xffffffffffc0) + /* mask for PRBAR & PRLAR MPU-region field */ +/* MPU region attribute bit fields: */ +#define PRBAR_SH_SHIFT UL(4) +#define PRBAR_SH_MASK UL(0x3) +#define PRBAR_AP_SHIFT UL(2) +#define PRBAR_AP_MASK UL(0x3) +#define PRBAR_XN_SHIFT UL(1) +#define PRBAR_XN_MASK UL(0x3) +#define PRLAR_NS_SHIFT UL(4) +#define PRLAR_NS_MASK UL(0x3) +#define PRBAR_ATTR_SHIFT UL(0) +#define PRBAR_ATTR_MASK UL(0x3f) +#define PRLAR_ATTR_SHIFT UL(1) +#define PRLAR_ATTR_MASK UL(0x7) +#define PRLAR_EN_SHIFT UL(0) +#define PRLAR_EN_MASK UL(0x1) +/* Aspects of the source attributes not defined elsewhere: */ +#define MT_PERM_MASK UL(0x1) +#define MT_SEC_MASK UL(0x1) +#define MT_EXECUTE_MASK UL(0x3) +#define MT_TYPE_SHIFT UL(0) + +extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* + * Return the execute-never mask that will prevent instruction fetch at the + * given translation regime. + */ +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime); + +/* Print VA, PA, size and attributes of all regions in the mmap array. */ +void xlat_mmap_print(const mmap_region_t *mmap); + +/* + * Print the current state of the translation tables by reading them from + * memory. + */ +void xlat_tables_print(xlat_ctx_t *ctx); + +/* + * Returns a block/page table descriptor for the given level and attributes. + */ +uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, + unsigned long long addr_pa, unsigned int level); + +/* + * Architecture-specific initialization code. + */ + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +unsigned int xlat_arch_current_el(void); + +/* + * Returns true if the MMU of the translation regime managed by the given + * xlat_ctx_t is enabled, false otherwise. + */ +bool is_mpu_enabled_ctx(const xlat_ctx_t *ctx); + +/* + * Returns minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void); + +#endif /* XLAT_MPU_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c new file mode 100644 index 0000000..5400875 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include "xlat_mpu_private.h" + +#include +#include + +#warning "xlat_mpu library is currently experimental and its API may change in future." + + +void xlat_mmap_print(__unused const mmap_region_t *mmap) +{ + /* Empty */ +} + +#if LOG_LEVEL < LOG_LEVEL_VERBOSE + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + /* Empty */ +} + +#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +static void xlat_tables_print_internal(__unused xlat_ctx_t *ctx) +{ + int region_to_use = 0; + uintptr_t region_base; + size_t region_size; + uint64_t prenr_el2_value = 0U; + + /* + * Keep track of how many invalid descriptors are counted in a row. + * Whenever multiple invalid descriptors are found, only the first one + * is printed, and a line is added to inform about how many descriptors + * have been omitted. + */ + + /* + * TODO: Remove this WARN() and comment when these API calls are more + * completely implemented and tested! + */ + WARN("%s in this early version of xlat_mpu library may not produce reliable results!", + __func__); + + /* + * Sequence through all regions and print those in-use (PRENR has an + * enable bit for each MPU region, 1 for in-use or 0 for unused): + */ + prenr_el2_value = read_prenr_el2(); + for (region_to_use = 0; region_to_use < N_MPU_REGIONS; + region_to_use++) { + if (((prenr_el2_value >> region_to_use) & 1U) == 0U) { + continue; + } + region_base = read_prbar_el2() & PRBAR_PRLAR_ADDR_MASK; + region_size = read_prlar_el2() & PRBAR_PRLAR_ADDR_MASK; + printf("Address: 0x%llx, size: 0x%llx ", + (long long) region_base, + (long long) region_size); + } +} + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + xlat_tables_print_internal(ctx); +} + +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c new file mode 100644 index 0000000..7cd509d --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c @@ -0,0 +1,566 @@ +/* + * Copyright (c) 2016-2017, Linaro Limited. All rights reserved. + * Copyright (c) 2014-2020, Arm Limited. All rights reserved. + * Copyright (c) 2014, STMicroelectronics International N.V. + * All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#ifdef ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +#error "ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING flag is set. \ +This module is to be used when LPAE is not supported" +#endif + +CASSERT(PLAT_VIRT_ADDR_SPACE_SIZE == (1ULL << 32), invalid_vaddr_space_size); +CASSERT(PLAT_PHY_ADDR_SPACE_SIZE == (1ULL << 32), invalid_paddr_space_size); + +#define MMU32B_UNSET_DESC ~0UL +#define MMU32B_INVALID_DESC 0UL + +#define MT_UNKNOWN ~0U + +/* + * MMU related values + */ + +/* Sharable */ +#define MMU32B_TTB_S (1U << 1) + +/* Not Outer Sharable */ +#define MMU32B_TTB_NOS (1U << 5) + +/* Normal memory, Inner Non-cacheable */ +#define MMU32B_TTB_IRGN_NC 0U + +/* Normal memory, Inner Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WBWA (1U << 6) + +/* Normal memory, Inner Write-Through Cacheable */ +#define MMU32B_TTB_IRGN_WT 1U + +/* Normal memory, Inner Write-Back no Write-Allocate Cacheable */ +#define MMU32B_TTB_IRGN_WB (1U | (1U << 6)) + +/* Normal memory, Outer Write-Back Write-Allocate Cacheable */ +#define MMU32B_TTB_RNG_WBWA (1U << 3) + +#define MMU32B_DEFAULT_ATTRS \ + (MMU32B_TTB_S | MMU32B_TTB_NOS | \ + MMU32B_TTB_IRGN_WBWA | MMU32B_TTB_RNG_WBWA) + +/* armv7 memory mapping attributes: section mapping */ +#define SECTION_SECURE (0U << 19) +#define SECTION_NOTSECURE (1U << 19) +#define SECTION_SHARED (1U << 16) +#define SECTION_NOTGLOBAL (1U << 17) +#define SECTION_ACCESS_FLAG (1U << 10) +#define SECTION_UNPRIV (1U << 11) +#define SECTION_RO (1U << 15) +#define SECTION_TEX(tex) ((((tex) >> 2) << 12) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SECTION_DEVICE SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL SECTION_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SECTION_NORMAL_CACHED \ + SECTION_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) + +#define SECTION_XN (1U << 4) +#define SECTION_PXN (1U << 0) +#define SECTION_SECTION (2U << 0) + +#define SECTION_PT_NOTSECURE (1U << 3) +#define SECTION_PT_PT (1U << 0) + +#define SMALL_PAGE_SMALL_PAGE (1U << 1) +#define SMALL_PAGE_SHARED (1U << 10) +#define SMALL_PAGE_NOTGLOBAL (1U << 11) +#define SMALL_PAGE_TEX(tex) ((((tex) >> 2) << 6) | \ + ((((tex) >> 1) & 0x1) << 3) | \ + (((tex) & 0x1) << 2)) +#define SMALL_PAGE_DEVICE \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL \ + SMALL_PAGE_TEX(MMU32B_ATTR_DEVICE_INDEX) +#define SMALL_PAGE_NORMAL_CACHED \ + SMALL_PAGE_TEX(MMU32B_ATTR_IWBWA_OWBWA_INDEX) +#define SMALL_PAGE_ACCESS_FLAG (1U << 4) +#define SMALL_PAGE_UNPRIV (1U << 5) +#define SMALL_PAGE_RO (1U << 9) +#define SMALL_PAGE_XN (1U << 0) + +/* The TEX, C and B bits concatenated */ +#define MMU32B_ATTR_DEVICE_INDEX 0U +#define MMU32B_ATTR_IWBWA_OWBWA_INDEX 1U + +#define MMU32B_PRRR_IDX(idx, tr, nos) (((tr) << (2 * (idx))) | \ + ((uint32_t)(nos) << ((idx) + 24))) +#define MMU32B_NMRR_IDX(idx, ir, or) (((ir) << (2 * (idx))) | \ + ((uint32_t)(or) << (2 * (idx) + 16))) +#define MMU32B_PRRR_DS0 (1U << 16) +#define MMU32B_PRRR_DS1 (1U << 17) +#define MMU32B_PRRR_NS0 (1U << 18) +#define MMU32B_PRRR_NS1 (1U << 19) + +#define DACR_DOMAIN(num, perm) ((perm) << ((num) * 2)) +#define DACR_DOMAIN_PERM_NO_ACCESS 0U +#define DACR_DOMAIN_PERM_CLIENT 1U +#define DACR_DOMAIN_PERM_MANAGER 3U + +#define NUM_1MB_IN_4GB (1UL << 12) +#define NUM_4K_IN_1MB (1UL << 8) + +#define ONE_MB_SHIFT 20 + +/* mmu 32b integration */ +#define MMU32B_L1_TABLE_SIZE (NUM_1MB_IN_4GB * 4) +#define MMU32B_L2_TABLE_SIZE (NUM_4K_IN_1MB * 4) +#define MMU32B_L1_TABLE_ALIGN (1U << 14) +#define MMU32B_L2_TABLE_ALIGN (1U << 10) + +static unsigned int next_xlat; +static unsigned long long xlat_max_pa; +static uintptr_t xlat_max_va; + +static uint32_t mmu_l1_base[NUM_1MB_IN_4GB] + __aligned(MMU32B_L1_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +static uint32_t mmu_l2_base[MAX_XLAT_TABLES][NUM_4K_IN_1MB] + __aligned(MMU32B_L2_TABLE_ALIGN) __attribute__((section("xlat_table"))); + +/* + * Array of all memory regions stored in order of ascending base address. + * The list is terminated by the first entry with size == 0. + */ +static mmap_region_t mmap[MAX_MMAP_REGIONS + 1]; + +void print_mmap(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + mmap_region_t *mm = mmap; + + printf("init xlat - l1:%p l2:%p (%d)\n", + (void *)mmu_l1_base, (void *)mmu_l2_base, MAX_XLAT_TABLES); + printf("mmap:\n"); + while (mm->size) { + printf(" VA:%p PA:0x%llx size:0x%zx attr:0x%x\n", + (void *)mm->base_va, mm->base_pa, + mm->size, mm->attr); + ++mm; + }; + printf("\n"); +#endif +} + +void mmap_add(const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while ((mm_cursor->size != 0U) || (mm_cursor->attr != 0U)) { + mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, + mm_cursor->size, mm_cursor->attr); + mm_cursor++; + } +} + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t *mm = mmap; + const mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1U; + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + assert(IS_PAGE_ALIGNED(base_pa)); + assert(IS_PAGE_ALIGNED(base_va)); + assert(IS_PAGE_ALIGNED(size)); + + if (size == 0U) { + return; + } + + assert(base_pa < end_pa); /* Check for overflows */ + assert(base_va < end_va); + + assert((base_va + (uintptr_t)size - (uintptr_t)1) <= + (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert((base_pa + (unsigned long long)size - 1ULL) <= + (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + +#if ENABLE_ASSERTIONS + + /* Check for PAs and VAs overlaps with all other regions */ + for (mm = mmap; mm->size; ++mm) { + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm->base_va) && (end_va <= mm_end_va)) || + ((mm->base_va >= base_va) && (mm_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + */ + if (fully_overlapped_va) { + assert((mm->base_va - mm->base_pa) == + (base_va - base_pa)); + assert((base_va != mm->base_va) || (size != mm->size)); + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_end_pa = + mm->base_pa + mm->size - 1; + + bool separated_pa = (end_pa < mm->base_pa) || + (base_pa > mm_end_pa); + bool separated_va = (end_va < mm->base_va) || + (base_va > mm_end_va); + + assert(separated_va && separated_pa); + } + } + + mm = mmap; /* Restore pointer to the start of the array */ + +#endif /* ENABLE_ASSERTIONS */ + + /* Find correct place in mmap to insert new region */ + while ((mm->base_va < base_va) && (mm->size != 0U)) { + ++mm; + } + + /* + * If a section is contained inside another one with the same base + * address, it must be placed after the one it is contained in: + * + * 1st |-----------------------| + * 2nd |------------| + * 3rd |------| + * + * This is required for mmap_region_attr() to get the attributes of the + * small region correctly. + */ + while ((mm->base_va == base_va) && (mm->size > size)) { + ++mm; + } + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check we haven't lost the empty sentinal from the end of the array */ + assert(mm_last->size == 0U); + + mm->base_pa = base_pa; + mm->base_va = base_va; + mm->size = size; + mm->attr = attr; + + if (end_pa > xlat_max_pa) { + xlat_max_pa = end_pa; + } + if (end_va > xlat_max_va) { + xlat_max_va = end_va; + } +} + +/* map all memory as shared/global/domain0/no-usr access */ +static uint32_t mmap_desc(unsigned attr, unsigned int addr_pa, + unsigned int level) +{ + uint32_t desc; + + switch (level) { + case 1U: + assert((addr_pa & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U); + + desc = SECTION_SECTION | SECTION_SHARED; + + desc |= (attr & MT_NS) != 0U ? SECTION_NOTSECURE : 0U; + + desc |= SECTION_ACCESS_FLAG; + desc |= (attr & MT_RW) != 0U ? 0U : SECTION_RO; + + desc |= (attr & MT_MEMORY) != 0U ? + SECTION_NORMAL_CACHED : SECTION_DEVICE; + + if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) { + desc |= SECTION_XN; + } + break; + case 2U: + assert((addr_pa & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U); + + desc = SMALL_PAGE_SMALL_PAGE | SMALL_PAGE_SHARED; + + desc |= SMALL_PAGE_ACCESS_FLAG; + desc |= (attr & MT_RW) != 0U ? 0U : SMALL_PAGE_RO; + + desc |= (attr & MT_MEMORY) != 0U ? + SMALL_PAGE_NORMAL_CACHED : SMALL_PAGE_DEVICE; + + if (((attr & MT_RW) != 0U) || ((attr & MT_MEMORY) == 0U)) { + desc |= SMALL_PAGE_XN; + } + break; + default: + panic(); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only the non-lpae level 2 tables */ + if (level == 2U) { + printf(attr & MT_MEMORY ? "MEM" : "dev"); + printf(attr & MT_RW ? "-rw" : "-RO"); + printf(attr & MT_NS ? "-NS" : "-S"); + } +#endif + return desc | addr_pa; +} + +static unsigned int mmap_region_attr(const mmap_region_t *mm, uintptr_t base_va, + size_t size, unsigned int *attr) +{ + /* Don't assume that the area is contained in the first region */ + unsigned int ret = MT_UNKNOWN; + + /* + * Get attributes from last (innermost) region that contains the + * requested area. Don't stop as soon as one region doesn't contain it + * because there may be other internal regions that contain this area: + * + * |-----------------------------1-----------------------------| + * |----2----| |-------3-------| |----5----| + * |--4--| + * + * |---| <- Area we want the attributes of. + * + * In this example, the area is contained in regions 1, 3 and 4 but not + * in region 2. The loop shouldn't stop at region 2 as inner regions + * have priority over outer regions, it should stop at region 5. + */ + for ( ; ; ++mm) { + + if (mm->size == 0U) { + return ret; /* Reached end of list */ + } + + if (mm->base_va > (base_va + size - 1U)) { + return ret; /* Next region is after area so end */ + } + + if ((mm->base_va + mm->size - 1U) < base_va) { + continue; /* Next region has already been overtaken */ + } + + if ((ret == 0U) && (mm->attr == *attr)) { + continue; /* Region doesn't override attribs so skip */ + } + + if ((mm->base_va > base_va) || + ((mm->base_va + mm->size - 1U) < + (base_va + size - 1U))) { + return MT_UNKNOWN; /* Region doesn't fully cover area */ + } + + *attr = mm->attr; + ret = 0U; + } +} + +static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, + unsigned int base_va, + uint32_t *table, + unsigned int level) +{ + unsigned int level_size_shift = (level == 1U) ? + ONE_MB_SHIFT : FOUR_KB_SHIFT; + unsigned int level_size = 1U << level_size_shift; + unsigned int level_index_mask = (level == 1U) ? + (NUM_1MB_IN_4GB - 1) << ONE_MB_SHIFT : + (NUM_4K_IN_1MB - 1) << FOUR_KB_SHIFT; + + assert((level == 1U) || (level == 2U)); + + VERBOSE("init xlat table at %p (level%1u)\n", (void *)table, level); + + do { + uint32_t desc = MMU32B_UNSET_DESC; + + if (mm->base_va + mm->size <= base_va) { + /* Area now after the region so skip it */ + ++mm; + continue; + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2U) { + printf(" 0x%lx %x " + 6 - 2 * level, + base_va, level_size); + } +#endif + if (mm->base_va >= base_va + level_size) { + /* Next region is after area so nothing to map yet */ + desc = MMU32B_INVALID_DESC; + } else if ((mm->base_va <= base_va) && + (mm->base_va + mm->size) >= + (base_va + level_size)) { + /* Next region covers all of area */ + unsigned int attr = mm->attr; + unsigned int r = mmap_region_attr(mm, base_va, + level_size, &attr); + + if (r == 0U) { + desc = mmap_desc(attr, + base_va - mm->base_va + mm->base_pa, + level); + } + } + + if (desc == MMU32B_UNSET_DESC) { + uintptr_t xlat_table; + + /* + * Area not covered by a region so need finer table + * Reuse next level table if any (assert attrib matching). + * Otherwise allocate a xlat table. + */ + if (*table) { + assert((*table & 3) == SECTION_PT_PT); + assert(((*table & SECTION_PT_NOTSECURE) == 0U) + == ((mm->attr & MT_NS) == 0U)); + + xlat_table = (*table) & + ~(MMU32B_L1_TABLE_ALIGN - 1); + desc = *table; + } else { + xlat_table = (uintptr_t)mmu_l2_base + + next_xlat * MMU32B_L2_TABLE_SIZE; + next_xlat++; + assert(next_xlat <= MAX_XLAT_TABLES); + (void)memset((char *)xlat_table, 0, + MMU32B_L2_TABLE_SIZE); + + desc = xlat_table | SECTION_PT_PT; + desc |= (mm->attr & MT_NS) != 0U ? + SECTION_PT_NOTSECURE : 0; + } + /* Recurse to fill in new table */ + mm = init_xlation_table_inner(mm, base_va, + (uint32_t *)xlat_table, + level + 1); + } +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + /* dump only non-lpae level 2 tables content */ + if (level == 2U) { + printf("\n"); + } +#endif + *table++ = desc; + base_va += level_size; + } while ((mm->size != 0U) && ((base_va & level_index_mask) != 0U)); + + return mm; +} + +void init_xlat_tables(void) +{ + print_mmap(); + + assert(((unsigned int)mmu_l1_base & (MMU32B_L1_TABLE_ALIGN - 1)) == 0U); + assert(((unsigned int)mmu_l2_base & (MMU32B_L2_TABLE_ALIGN - 1)) == 0U); + + (void)memset(mmu_l1_base, 0, MMU32B_L1_TABLE_SIZE); + + init_xlation_table_inner(mmap, 0, (uint32_t *)mmu_l1_base, 1); + + VERBOSE("init xlat - max_va=%p, max_pa=%llx\n", + (void *)xlat_max_va, xlat_max_pa); + assert(xlat_max_pa <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1)); +} + +/******************************************************************************* + * Function for enabling the MMU in Secure PL1, assuming that the + * page-tables have already been created. + ******************************************************************************/ +void enable_mmu_svc_mon(unsigned int flags) +{ + unsigned int prrr; + unsigned int nmrr; + unsigned int sctlr; + + assert(IS_IN_SECURE()); + assert((read_sctlr() & SCTLR_M_BIT) == 0U); + + /* Enable Access flag (simplified access permissions) and TEX remap */ + write_sctlr(read_sctlr() | SCTLR_AFE_BIT | SCTLR_TRE_BIT); + + prrr = MMU32B_PRRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 1, 0) \ + | MMU32B_PRRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 2, 1); + nmrr = MMU32B_NMRR_IDX(MMU32B_ATTR_DEVICE_INDEX, 0, 0) \ + | MMU32B_NMRR_IDX(MMU32B_ATTR_IWBWA_OWBWA_INDEX, 1, 1); + + prrr |= MMU32B_PRRR_NS1 | MMU32B_PRRR_DS1; + + write_prrr(prrr); + write_nmrr(nmrr); + + /* Program Domain access control register: domain 0 only */ + write_dacr(DACR_DOMAIN(0, DACR_DOMAIN_PERM_CLIENT)); + + /* Invalidate TLBs at the current exception level */ + tlbiall(); + + /* set MMU base xlat table entry (use only TTBR0) */ + write_ttbr0((uint32_t)mmu_l1_base | MMU32B_DEFAULT_ATTRS); + write_ttbr1(0U); + + /* + * Ensure all translation table writes have drained + * into memory, the TLB invalidation is complete, + * and translation register writes are committed + * before enabling the MMU + */ + dsb(); + isb(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_M_BIT; +#ifdef ARMV7_SUPPORTS_VIRTUALIZATION + sctlr |= SCTLR_WXN_BIT; +#endif + + if ((flags & DISABLE_DCACHE) != 0U) { + sctlr &= ~SCTLR_C_BIT; + } else { + sctlr |= SCTLR_C_BIT; + } + + write_sctlr(sctlr); + + /* Ensure the MMU enable takes effect immediately */ + isb(); +} diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c new file mode 100644 index 0000000..4b01b9b --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c @@ -0,0 +1,141 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + +#define XLAT_TABLE_LEVEL_BASE \ + GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE) + +#define NUM_BASE_LEVEL_ENTRIES \ + GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) + +static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES] + __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); + +#if ENABLE_ASSERTIONS +static unsigned long long get_max_supported_pa(void) +{ + /* Physical address space size for long descriptor format. */ + return (1ULL << 40) - 1ULL; +} +#endif /* ENABLE_ASSERTIONS */ + +unsigned int xlat_arch_current_el(void) +{ + /* + * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, System, + * SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. + */ + return 3U; +} + +uint64_t xlat_arch_get_xn_desc(unsigned int el __unused) +{ + return UPPER_ATTRS(XN); +} + +void init_xlat_tables(void) +{ + unsigned long long max_pa; + uintptr_t max_va; + + assert(PLAT_VIRT_ADDR_SPACE_SIZE >= MIN_VIRT_ADDR_SPACE_SIZE); + assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE)); + + print_mmap(); + init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE, + &max_va, &max_pa); + + assert(max_va <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(max_pa <= (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + assert((PLAT_PHY_ADDR_SPACE_SIZE - 1U) <= get_max_supported_pa()); +} + +void enable_mmu_svc_mon(unsigned int flags) +{ + unsigned int mair0, ttbcr, sctlr; + uint64_t ttbr0; + + assert(IS_IN_SECURE()); + assert((read_sctlr() & SCTLR_M_BIT) == 0U); + + /* Set attributes in the right indices of the MAIR */ + mair0 = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair0 |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_IWBWA_OWBWA_NTR_INDEX); + mair0 |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, + ATTR_NON_CACHEABLE_INDEX); + write_mair0(mair0); + + /* Invalidate TLBs at the current exception level */ + tlbiall(); + + /* + * Set TTBCR bits as well. Set TTBR0 table properties. Disable TTBR1. + */ + int t0sz = 32 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE); + + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + ttbcr = TTBCR_EAE_BIT | + TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC | + TTBCR_RGN0_INNER_NC | (uint32_t) t0sz; + } else { + /* Inner & outer WBWA & shareable. */ + ttbcr = TTBCR_EAE_BIT | + TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA | + TTBCR_RGN0_INNER_WBA | (uint32_t) t0sz; + } + ttbcr |= TTBCR_EPD1_BIT; + write_ttbcr(ttbcr); + + /* Set TTBR0 bits as well */ + ttbr0 = (uintptr_t) base_xlation_table; + write64_ttbr0(ttbr0); + write64_ttbr1(0U); + + /* + * Ensure all translation table writes have drained + * into memory, the TLB invalidation is complete, + * and translation register writes are committed + * before enabling the MMU + */ + dsbish(); + isb(); + + sctlr = read_sctlr(); + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; + + if ((flags & DISABLE_DCACHE) != 0U) + sctlr &= ~SCTLR_C_BIT; + else + sctlr |= SCTLR_C_BIT; + + write_sctlr(sctlr); + + /* Ensure the MMU enable takes effect immediately */ + isb(); +} + +void enable_mmu_direct_svc_mon(unsigned int flags) +{ + enable_mmu_svc_mon(flags); +} diff --git a/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c b/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c new file mode 100644 index 0000000..dc167e3 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#define XLAT_TABLE_LEVEL_BASE \ + GET_XLAT_TABLE_LEVEL_BASE(PLAT_VIRT_ADDR_SPACE_SIZE) + +#define NUM_BASE_LEVEL_ENTRIES \ + GET_NUM_BASE_LEVEL_ENTRIES(PLAT_VIRT_ADDR_SPACE_SIZE) + +static uint64_t base_xlation_table[NUM_BASE_LEVEL_ENTRIES] + __aligned(NUM_BASE_LEVEL_ENTRIES * sizeof(uint64_t)); + +static unsigned long long tcr_ps_bits; + +static unsigned long long calc_physical_addr_size_bits( + unsigned long long max_addr) +{ + /* Physical address can't exceed 48 bits */ + assert((max_addr & ADDR_MASK_48_TO_63) == 0U); + + /* 48 bits address */ + if ((max_addr & ADDR_MASK_44_TO_47) != 0U) + return TCR_PS_BITS_256TB; + + /* 44 bits address */ + if ((max_addr & ADDR_MASK_42_TO_43) != 0U) + return TCR_PS_BITS_16TB; + + /* 42 bits address */ + if ((max_addr & ADDR_MASK_40_TO_41) != 0U) + return TCR_PS_BITS_4TB; + + /* 40 bits address */ + if ((max_addr & ADDR_MASK_36_TO_39) != 0U) + return TCR_PS_BITS_1TB; + + /* 36 bits address */ + if ((max_addr & ADDR_MASK_32_TO_35) != 0U) + return TCR_PS_BITS_64GB; + + return TCR_PS_BITS_4GB; +} + +#if ENABLE_ASSERTIONS +/* + * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is + * supported in ARMv8.2 onwards. + */ +static const unsigned int pa_range_bits_arr[] = { + PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, + PARANGE_0101, PARANGE_0110 +}; + +static unsigned long long get_max_supported_pa(void) +{ + u_register_t pa_range = read_id_aa64mmfr0_el1() & + ID_AA64MMFR0_EL1_PARANGE_MASK; + + /* All other values are reserved */ + assert(pa_range < ARRAY_SIZE(pa_range_bits_arr)); + + return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL; +} + +/* + * Return minimum virtual address space size supported by the architecture + */ +static uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + uintptr_t ret; + + if (is_armv8_4_ttst_present()) + ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST; + else + ret = MIN_VIRT_ADDR_SPACE_SIZE; + + return ret; +} +#endif /* ENABLE_ASSERTIONS */ + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + +uint64_t xlat_arch_get_xn_desc(unsigned int el) +{ + if (el == 3U) { + return UPPER_ATTRS(XN); + } else { + assert(el == 1U); + return UPPER_ATTRS(PXN); + } +} + +void init_xlat_tables(void) +{ + unsigned long long max_pa; + uintptr_t max_va; + + assert(PLAT_VIRT_ADDR_SPACE_SIZE >= + (xlat_get_min_virt_addr_space_size() - 1U)); + assert(PLAT_VIRT_ADDR_SPACE_SIZE <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(PLAT_VIRT_ADDR_SPACE_SIZE)); + + print_mmap(); + init_xlation_table(0U, base_xlation_table, XLAT_TABLE_LEVEL_BASE, + &max_va, &max_pa); + + assert(max_va <= (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(max_pa <= (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + assert((PLAT_PHY_ADDR_SPACE_SIZE - 1U) <= get_max_supported_pa()); + + tcr_ps_bits = calc_physical_addr_size_bits(max_pa); +} + +/******************************************************************************* + * Macro generating the code for the function enabling the MMU in the given + * exception level, assuming that the pagetables have already been created. + * + * _el: Exception level at which the function will run + * _tcr_extra: Extra bits to set in the TCR register. This mask will + * be OR'ed with the default TCR value. + * _tlbi_fct: Function to invalidate the TLBs at the current + * exception level + ******************************************************************************/ +#define DEFINE_ENABLE_MMU_EL(_el, _tcr_extra, _tlbi_fct) \ + void enable_mmu_el##_el(unsigned int flags) \ + { \ + uint64_t mair, tcr, ttbr; \ + uint32_t sctlr; \ + \ + assert(IS_IN_EL(_el)); \ + assert((read_sctlr_el##_el() & SCTLR_M_BIT) == 0U); \ + \ + /* Set attributes in the right indices of the MAIR */ \ + mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); \ + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, \ + ATTR_IWBWA_OWBWA_NTR_INDEX); \ + mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, \ + ATTR_NON_CACHEABLE_INDEX); \ + write_mair_el##_el(mair); \ + \ + /* Invalidate TLBs at the current exception level */ \ + _tlbi_fct(); \ + \ + /* Set TCR bits as well. */ \ + /* Set T0SZ to (64 - width of virtual address space) */ \ + int t0sz = 64 - __builtin_ctzll(PLAT_VIRT_ADDR_SPACE_SIZE);\ + \ + if ((flags & XLAT_TABLE_NC) != 0U) { \ + /* Inner & outer non-cacheable non-shareable. */\ + tcr = TCR_SH_NON_SHAREABLE | \ + TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC | \ + ((uint64_t)t0sz << TCR_T0SZ_SHIFT); \ + } else { \ + /* Inner & outer WBWA & shareable. */ \ + tcr = TCR_SH_INNER_SHAREABLE | \ + TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA | \ + ((uint64_t)t0sz << TCR_T0SZ_SHIFT); \ + } \ + tcr |= _tcr_extra; \ + write_tcr_el##_el(tcr); \ + \ + /* Set TTBR bits as well */ \ + ttbr = (uint64_t) base_xlation_table; \ + write_ttbr0_el##_el(ttbr); \ + \ + /* Ensure all translation table writes have drained */ \ + /* into memory, the TLB invalidation is complete, */ \ + /* and translation register writes are committed */ \ + /* before enabling the MMU */ \ + dsbish(); \ + isb(); \ + \ + sctlr = read_sctlr_el##_el(); \ + sctlr |= SCTLR_WXN_BIT | SCTLR_M_BIT; \ + \ + if ((flags & DISABLE_DCACHE) != 0U) \ + sctlr &= ~SCTLR_C_BIT; \ + else \ + sctlr |= SCTLR_C_BIT; \ + \ + write_sctlr_el##_el(sctlr); \ + \ + /* Ensure the MMU enable takes effect immediately */ \ + isb(); \ + } \ + \ + void enable_mmu_direct_el##_el(unsigned int flags) \ + { \ + enable_mmu_el##_el(flags); \ + } + +/* Define EL1 and EL3 variants of the function enabling the MMU */ +DEFINE_ENABLE_MMU_EL(1, + /* + * TCR_EL1.EPD1: Disable translation table walk for addresses + * that are translated using TTBR1_EL1. + */ + TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT), + tlbivmalle1) +DEFINE_ENABLE_MMU_EL(3, + TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT), + tlbialle3) diff --git a/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c new file mode 100644 index 0000000..23fe3f0 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c @@ -0,0 +1,417 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "xlat_tables_private.h" + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +#define LVL0_SPACER "" +#define LVL1_SPACER " " +#define LVL2_SPACER " " +#define LVL3_SPACER " " +#define get_level_spacer(level) \ + (((level) == U(0)) ? LVL0_SPACER : \ + (((level) == U(1)) ? LVL1_SPACER : \ + (((level) == U(2)) ? LVL2_SPACER : LVL3_SPACER))) +#define debug_print(...) printf(__VA_ARGS__) +#else +#define debug_print(...) ((void)0) +#endif + +#define UNSET_DESC ~0ULL +#define MT_UNKNOWN ~0U + +static uint64_t xlat_tables[MAX_XLAT_TABLES][XLAT_TABLE_ENTRIES] + __aligned(XLAT_TABLE_SIZE) __section("xlat_table"); + +static unsigned int next_xlat; +static unsigned long long xlat_max_pa; +static uintptr_t xlat_max_va; + +static uint64_t execute_never_mask; +static uint64_t ap1_mask; + +/* + * Array of all memory regions stored in order of ascending base address. + * The list is terminated by the first entry with size == 0. + */ +static mmap_region_t mmap[MAX_MMAP_REGIONS + 1]; + + +void print_mmap(void) +{ +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + debug_print("mmap:\n"); + mmap_region_t *mm = mmap; + while (mm->size != 0U) { + debug_print(" VA:%p PA:0x%llx size:0x%zx attr:0x%x\n", + (void *)mm->base_va, mm->base_pa, + mm->size, mm->attr); + ++mm; + }; + debug_print("\n"); +#endif +} + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t *mm = mmap; + const mmap_region_t *mm_last = mm + ARRAY_SIZE(mmap) - 1U; + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + assert(IS_PAGE_ALIGNED(base_pa)); + assert(IS_PAGE_ALIGNED(base_va)); + assert(IS_PAGE_ALIGNED(size)); + + if (size == 0U) + return; + + assert(base_pa < end_pa); /* Check for overflows */ + assert(base_va < end_va); + + assert((base_va + (uintptr_t)size - (uintptr_t)1) <= + (PLAT_VIRT_ADDR_SPACE_SIZE - 1U)); + assert((base_pa + (unsigned long long)size - 1ULL) <= + (PLAT_PHY_ADDR_SPACE_SIZE - 1U)); + +#if ENABLE_ASSERTIONS + + /* Check for PAs and VAs overlaps with all other regions */ + for (mm = mmap; mm->size; ++mm) { + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm->base_va) && (end_va <= mm_end_va)) || + ((mm->base_va >= base_va) && (mm_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + */ + if (fully_overlapped_va) { + assert((mm->base_va - mm->base_pa) == + (base_va - base_pa)); + assert((base_va != mm->base_va) || (size != mm->size)); + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_end_pa = + mm->base_pa + mm->size - 1; + + bool separated_pa = (end_pa < mm->base_pa) || + (base_pa > mm_end_pa); + bool separated_va = (end_va < mm->base_va) || + (base_va > mm_end_va); + + assert(separated_va && separated_pa); + } + } + + mm = mmap; /* Restore pointer to the start of the array */ + +#endif /* ENABLE_ASSERTIONS */ + + /* Find correct place in mmap to insert new region */ + while ((mm->base_va < base_va) && (mm->size != 0U)) + ++mm; + + /* + * If a section is contained inside another one with the same base + * address, it must be placed after the one it is contained in: + * + * 1st |-----------------------| + * 2nd |------------| + * 3rd |------| + * + * This is required for mmap_region_attr() to get the attributes of the + * small region correctly. + */ + while ((mm->base_va == base_va) && (mm->size > size)) + ++mm; + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm + 1, mm, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check we haven't lost the empty sentinal from the end of the array */ + assert(mm_last->size == 0U); + + mm->base_pa = base_pa; + mm->base_va = base_va; + mm->size = size; + mm->attr = attr; + + if (end_pa > xlat_max_pa) + xlat_max_pa = end_pa; + if (end_va > xlat_max_va) + xlat_max_va = end_va; +} + +void mmap_add(const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while ((mm_cursor->size != 0U) || (mm_cursor->attr != 0U)) { + mmap_add_region(mm_cursor->base_pa, mm_cursor->base_va, + mm_cursor->size, mm_cursor->attr); + mm_cursor++; + } +} + +static uint64_t mmap_desc(unsigned int attr, unsigned long long addr_pa, + unsigned int level) +{ + uint64_t desc; + int mem_type; + + /* Make sure that the granularity is fine enough to map this address. */ + assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0U); + + desc = addr_pa; + /* + * There are different translation table descriptors for level 3 and the + * rest. + */ + desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; + desc |= ((attr & MT_NS) != 0U) ? LOWER_ATTRS(NS) : 0U; + desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); + /* + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ + desc |= LOWER_ATTRS(ACCESS_FLAG); + desc |= ap1_mask; + + /* + * Deduce shareability domain and executability of the memory region + * from the memory type. + * + * Data accesses to device memory and non-cacheable normal memory are + * coherent for all observers in the system, and correspondingly are + * always treated as being Outer Shareable. Therefore, for these 2 types + * of memory, it is not strictly needed to set the shareability field + * in the translation tables. + */ + mem_type = MT_TYPE(attr); + if (mem_type == MT_DEVICE) { + desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH); + /* + * Always map device memory as execute-never. + * This is to avoid the possibility of a speculative instruction + * fetch, which could be an issue if this memory region + * corresponds to a read-sensitive peripheral. + */ + desc |= execute_never_mask; + + } else { /* Normal memory */ + /* + * Always map read-write normal memory as execute-never. + * This library assumes that it is used by software that does + * not self-modify its code, therefore R/W memory is reserved + * for data storage, which must not be executable. + * + * Note that setting the XN bit here is for consistency only. + * The function that enables the MMU sets the SCTLR_ELx.WXN bit, + * which makes any writable memory region to be treated as + * execute-never, regardless of the value of the XN bit in the + * translation table. + * + * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER + * attribute to figure out the value of the XN bit. + */ + if (((attr & MT_RW) != 0U) || ((attr & MT_EXECUTE_NEVER) != 0U)) { + desc |= execute_never_mask; + } + + if (mem_type == MT_MEMORY) { + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX | ISH); + } else { + assert(mem_type == MT_NON_CACHEABLE); + desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); + } + } + + debug_print((mem_type == MT_MEMORY) ? "MEM" : + ((mem_type == MT_NON_CACHEABLE) ? "NC" : "DEV")); + debug_print(((attr & MT_RW) != 0U) ? "-RW" : "-RO"); + debug_print(((attr & MT_NS) != 0U) ? "-NS" : "-S"); + debug_print(((attr & MT_EXECUTE_NEVER) != 0U) ? "-XN" : "-EXEC"); + return desc; +} + +/* + * Look for the innermost region that contains the area at `base_va` with size + * `size`. Populate *attr with the attributes of this region. + * + * On success, this function returns 0. + * If there are partial overlaps (meaning that a smaller size is needed) or if + * the region can't be found in the given area, it returns MT_UNKNOWN. In this + * case the value pointed by attr should be ignored by the caller. + */ +static unsigned int mmap_region_attr(const mmap_region_t *mm, uintptr_t base_va, + size_t size, unsigned int *attr) +{ + /* Don't assume that the area is contained in the first region */ + unsigned int ret = MT_UNKNOWN; + + /* + * Get attributes from last (innermost) region that contains the + * requested area. Don't stop as soon as one region doesn't contain it + * because there may be other internal regions that contain this area: + * + * |-----------------------------1-----------------------------| + * |----2----| |-------3-------| |----5----| + * |--4--| + * + * |---| <- Area we want the attributes of. + * + * In this example, the area is contained in regions 1, 3 and 4 but not + * in region 2. The loop shouldn't stop at region 2 as inner regions + * have priority over outer regions, it should stop at region 5. + */ + for ( ; ; ++mm) { + + if (mm->size == 0U) + return ret; /* Reached end of list */ + + if (mm->base_va > (base_va + size - 1U)) + return ret; /* Next region is after area so end */ + + if ((mm->base_va + mm->size - 1U) < base_va) + continue; /* Next region has already been overtaken */ + + if ((ret == 0U) && (mm->attr == *attr)) + continue; /* Region doesn't override attribs so skip */ + + if ((mm->base_va > base_va) || + ((mm->base_va + mm->size - 1U) < (base_va + size - 1U))) + return MT_UNKNOWN; /* Region doesn't fully cover area */ + + *attr = mm->attr; + ret = 0U; + } + return ret; +} + +static mmap_region_t *init_xlation_table_inner(mmap_region_t *mm, + uintptr_t base_va, + uint64_t *table, + unsigned int level) +{ + assert((level >= XLAT_TABLE_LEVEL_MIN) && + (level <= XLAT_TABLE_LEVEL_MAX)); + + unsigned int level_size_shift = + L0_XLAT_ADDRESS_SHIFT - level * XLAT_TABLE_ENTRIES_SHIFT; + u_register_t level_size = (u_register_t)1 << level_size_shift; + u_register_t level_index_mask = + ((u_register_t)XLAT_TABLE_ENTRIES_MASK) << level_size_shift; + + debug_print("New xlat table:\n"); + + do { + uint64_t desc = UNSET_DESC; + + if (mm->size == 0U) { + /* Done mapping regions; finish zeroing the table */ + desc = INVALID_DESC; + } else if ((mm->base_va + mm->size - 1U) < base_va) { + /* This area is after the region so get next region */ + ++mm; + continue; + } + + debug_print("%s VA:%p size:0x%llx ", get_level_spacer(level), + (void *)base_va, (unsigned long long)level_size); + + if (mm->base_va > (base_va + level_size - 1U)) { + /* Next region is after this area. Nothing to map yet */ + desc = INVALID_DESC; + /* Make sure that the current level allows block descriptors */ + } else if (level >= XLAT_BLOCK_LEVEL_MIN) { + /* + * Try to get attributes of this area. It will fail if + * there are partially overlapping regions. On success, + * it will return the innermost region's attributes. + */ + unsigned int attr; + unsigned int r = mmap_region_attr(mm, base_va, + level_size, &attr); + + if (r == 0U) { + desc = mmap_desc(attr, + base_va - mm->base_va + mm->base_pa, + level); + } + } + + if (desc == UNSET_DESC) { + /* Area not covered by a region so need finer table */ + uint64_t *new_table = xlat_tables[next_xlat]; + + next_xlat++; + assert(next_xlat <= MAX_XLAT_TABLES); + desc = TABLE_DESC | (uintptr_t)new_table; + + /* Recurse to fill in new table */ + mm = init_xlation_table_inner(mm, base_va, + new_table, level + 1U); + } + + debug_print("\n"); + + *table++ = desc; + base_va += level_size; + } while ((base_va & level_index_mask) && + ((base_va - 1U) < (PLAT_VIRT_ADDR_SPACE_SIZE - 1U))); + + return mm; +} + +void init_xlation_table(uintptr_t base_va, uint64_t *table, + unsigned int level, uintptr_t *max_va, + unsigned long long *max_pa) +{ + unsigned int el = xlat_arch_current_el(); + + execute_never_mask = xlat_arch_get_xn_desc(el); + + if (el == 3U) { + ap1_mask = LOWER_ATTRS(AP_ONE_VA_RANGE_RES1); + } else { + assert(el == 1U); + ap1_mask = 0ULL; + } + + init_xlation_table_inner(mmap, base_va, table, level); + *max_va = xlat_max_va; + *max_pa = xlat_max_pa; +} diff --git a/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h new file mode 100644 index 0000000..82bc70c --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_PRIVATE_H +#define XLAT_TABLES_PRIVATE_H + +#include + +#include +#include + +#if HW_ASSISTED_COHERENCY +#error xlat tables v2 must be used with HW_ASSISTED_COHERENCY +#endif + +CASSERT(CHECK_PHY_ADDR_SPACE_SIZE(PLAT_PHY_ADDR_SPACE_SIZE), + assert_valid_phy_addr_space_size); + +/* Alias to retain compatibility with the old #define name */ +#define XLAT_BLOCK_LEVEL_MIN MIN_LVL_BLOCK_DESC + +void print_mmap(void); + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +unsigned int xlat_arch_current_el(void); + +/* + * Returns the bit mask that has to be ORed to the rest of a translation table + * descriptor so that execution of code is prohibited at the given Exception + * Level. + */ +uint64_t xlat_arch_get_xn_desc(unsigned int el); + +void init_xlation_table(uintptr_t base_va, uint64_t *table, + unsigned int level, uintptr_t *max_va, + unsigned long long *max_pa); + +#endif /* XLAT_TABLES_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S new file mode 100644 index 0000000..f2fff36 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global enable_mmu_direct_svc_mon + .global enable_mmu_direct_hyp + + /* void enable_mmu_direct_svc_mon(unsigned int flags) */ +func enable_mmu_direct_svc_mon + /* Assert that MMU is turned off */ +#if ENABLE_ASSERTIONS + ldcopr r1, SCTLR + tst r1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + + /* Invalidate TLB entries */ + TLB_INVALIDATE(r0, TLBIALL) + + mov r3, r0 + ldr r0, =mmu_cfg_params + + /* MAIR0. Only the lower 32 bits are used. */ + ldr r1, [r0, #(MMU_CFG_MAIR << 3)] + stcopr r1, MAIR0 + + /* TTBCR. Only the lower 32 bits are used. */ + ldr r2, [r0, #(MMU_CFG_TCR << 3)] + stcopr r2, TTBCR + + /* TTBR0 */ + ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)] + ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)] + stcopr16 r1, r2, TTBR0_64 + + /* TTBR1 is unused right now; set it to 0. */ + mov r1, #0 + mov r2, #0 + stcopr16 r1, r2, TTBR1_64 + + /* + * Ensure all translation table writes have drained into memory, the TLB + * invalidation is complete, and translation register writes are + * committed before enabling the MMU + */ + dsb ish + isb + + /* Enable enable MMU by honoring flags */ + ldcopr r1, SCTLR + ldr r2, =(SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT) + orr r1, r1, r2 + + /* Clear C bit if requested */ + tst r3, #DISABLE_DCACHE + bicne r1, r1, #SCTLR_C_BIT + + stcopr r1, SCTLR + isb + + bx lr +endfunc enable_mmu_direct_svc_mon + + + /* void enable_mmu_direct_hyp(unsigned int flags) */ +func enable_mmu_direct_hyp + /* Assert that MMU is turned off */ +#if ENABLE_ASSERTIONS + ldcopr r1, HSCTLR + tst r1, #HSCTLR_M_BIT + ASM_ASSERT(eq) +#endif + + /* Invalidate TLB entries */ + TLB_INVALIDATE(r0, TLBIALL) + + mov r3, r0 + ldr r0, =mmu_cfg_params + + /* HMAIR0 */ + ldr r1, [r0, #(MMU_CFG_MAIR << 3)] + stcopr r1, HMAIR0 + + /* HTCR */ + ldr r2, [r0, #(MMU_CFG_TCR << 3)] + stcopr r2, HTCR + + /* HTTBR */ + ldr r1, [r0, #(MMU_CFG_TTBR0 << 3)] + ldr r2, [r0, #((MMU_CFG_TTBR0 << 3) + 4)] + stcopr16 r1, r2, HTTBR_64 + + /* + * Ensure all translation table writes have drained into memory, the TLB + * invalidation is complete, and translation register writes are + * committed before enabling the MMU + */ + dsb ish + isb + + /* Enable enable MMU by honoring flags */ + ldcopr r1, HSCTLR + ldr r2, =(HSCTLR_WXN_BIT | HSCTLR_C_BIT | HSCTLR_M_BIT) + orr r1, r1, r2 + + /* Clear C bit if requested */ + tst r3, #DISABLE_DCACHE + bicne r1, r1, #HSCTLR_C_BIT + + stcopr r1, HSCTLR + isb + + bx lr +endfunc enable_mmu_direct_hyp diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c new file mode 100644 index 0000000..a1a44af --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +#if (ARM_ARCH_MAJOR == 7) && !defined(ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING) +#error ARMv7 target does not support LPAE MMU descriptors +#endif + +/* + * Returns true if the provided granule size is supported, false otherwise. + */ +bool xlat_arch_is_granule_size_supported(size_t size) +{ + /* + * The library uses the long descriptor translation table format, which + * supports 4 KiB pages only. + */ + return size == PAGE_SIZE_4KB; +} + +size_t xlat_arch_get_max_supported_granule_size(void) +{ + return PAGE_SIZE_4KB; +} + +/* + * Determine the physical address space encoded in the 'attr' parameter. + * + * The physical address will fall into one of two spaces; secure or + * nonsecure. + */ +uint32_t xlat_arch_get_pas(uint32_t attr) +{ + uint32_t pas = MT_PAS(attr); + + if (pas == MT_NS) { + return LOWER_ATTRS(NS); + } else { /* MT_SECURE */ + return 0U; + } +} + +#if ENABLE_ASSERTIONS +unsigned long long xlat_arch_get_max_supported_pa(void) +{ + /* Physical address space size for long descriptor format. */ + return (1ULL << 40) - 1ULL; +} + +/* + * Return minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + return MIN_VIRT_ADDR_SPACE_SIZE; +} +#endif /* ENABLE_ASSERTIONS*/ + +bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx) +{ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() == 1U); + return (read_sctlr() & SCTLR_M_BIT) != 0U; + } else { + assert(ctx->xlat_regime == EL2_REGIME); + assert(xlat_arch_current_el() == 2U); + return (read_hsctlr() & HSCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + if (IS_IN_EL2()) { + return (read_hsctlr() & HSCTLR_C_BIT) != 0U; + } else { + return (read_sctlr() & SCTLR_C_BIT) != 0U; + } +} + +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) +{ + if (xlat_regime == EL1_EL0_REGIME) { + return UPPER_ATTRS(XN) | UPPER_ATTRS(PXN); + } else { + assert(xlat_regime == EL2_REGIME); + return UPPER_ATTRS(XN); + } +} + +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime) +{ + /* + * Ensure the translation table write has drained into memory before + * invalidating the TLB entry. + */ + dsbishst(); + + if (xlat_regime == EL1_EL0_REGIME) { + tlbimvaais(TLBI_ADDR(va)); + } else { + assert(xlat_regime == EL2_REGIME); + tlbimvahis(TLBI_ADDR(va)); + } +} + +void xlat_arch_tlbi_va_sync(void) +{ + /* Invalidate all entries from branch predictors. */ + bpiallis(); + + /* + * A TLB maintenance instruction can complete at any time after + * it is issued, but is only guaranteed to be complete after the + * execution of DSB by the PE that executed the TLB maintenance + * instruction. After the TLB invalidate instruction is + * complete, no new memory accesses using the invalidated TLB + * entries will be observed by any observer of the system + * domain. See section D4.8.2 of the ARMv8 (issue k), paragraph + * "Ordering and completion of TLB maintenance instructions". + */ + dsbish(); + + /* + * The effects of a completed TLB maintenance instruction are + * only guaranteed to be visible on the PE that executed the + * instruction after the execution of an ISB instruction by the + * PE that executed the TLB maintenance instruction. + */ + isb(); +} + +unsigned int xlat_arch_current_el(void) +{ + if (IS_IN_HYP()) { + return 2U; + } else { + assert(IS_IN_SVC() || IS_IN_MON()); + /* + * If EL3 is in AArch32 mode, all secure PL1 modes (Monitor, + * System, SVC, Abort, UND, IRQ and FIQ modes) execute at EL3. + * + * The PL1&0 translation regime in AArch32 behaves like the + * EL1&0 regime in AArch64 except for the XN bits, but we set + * and unset them at the same time, so there's no difference in + * practice. + */ + return 1U; + } +} + +/******************************************************************************* + * Function for enabling the MMU in PL1 or PL2, assuming that the page tables + * have already been created. + ******************************************************************************/ +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, __unused int xlat_regime) +{ + uint64_t mair, ttbr0; + uint32_t ttbcr; + + /* Set attributes in the right indices of the MAIR */ + mair = MAIR0_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR0_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, + ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR0_ATTR_SET(ATTR_NON_CACHEABLE, + ATTR_NON_CACHEABLE_INDEX); + + /* + * Configure the control register for stage 1 of the PL1&0 or EL2 + * translation regimes. + */ + + /* Use the Long-descriptor translation table format. */ + ttbcr = TTBCR_EAE_BIT; + + if (xlat_regime == EL1_EL0_REGIME) { + assert(IS_IN_SVC() || IS_IN_MON()); + /* + * Disable translation table walk for addresses that are + * translated using TTBR1. Therefore, only TTBR0 is used. + */ + ttbcr |= TTBCR_EPD1_BIT; + } else { + assert(xlat_regime == EL2_REGIME); + assert(IS_IN_HYP()); + + /* + * Set HTCR bits as well. Set HTTBR table properties + * as Inner & outer WBWA & shareable. + */ + ttbcr |= HTCR_RES1 | + HTCR_SH0_INNER_SHAREABLE | HTCR_RGN0_OUTER_WBA | + HTCR_RGN0_INNER_WBA; + } + + /* + * Limit the input address ranges and memory region sizes translated + * using TTBR0 to the given virtual address space size, if smaller than + * 32 bits. + */ + if (max_va != UINT32_MAX) { + uintptr_t virtual_addr_space_size = max_va + 1U; + + assert(virtual_addr_space_size >= + xlat_get_min_virt_addr_space_size()); + assert(IS_POWER_OF_TWO(virtual_addr_space_size)); + + /* + * __builtin_ctzll(0) is undefined but here we are guaranteed + * that virtual_addr_space_size is in the range [1, UINT32_MAX]. + */ + int t0sz = 32 - __builtin_ctzll(virtual_addr_space_size); + + ttbcr |= (uint32_t) t0sz; + } + + /* + * Set the cacheability and shareability attributes for memory + * associated with translation table walks using TTBR0. + */ + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + ttbcr |= TTBCR_SH0_NON_SHAREABLE | TTBCR_RGN0_OUTER_NC | + TTBCR_RGN0_INNER_NC; + } else { + /* Inner & outer WBWA & shareable. */ + ttbcr |= TTBCR_SH0_INNER_SHAREABLE | TTBCR_RGN0_OUTER_WBA | + TTBCR_RGN0_INNER_WBA; + } + + /* Set TTBR0 bits as well */ + ttbr0 = (uint64_t)(uintptr_t) base_table; + + if (is_armv8_2_ttcnp_present()) { + /* Enable CnP bit so as to share page tables with all PEs. */ + ttbr0 |= TTBR_CNP_BIT; + } + + /* Now populate MMU configuration */ + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = (uint64_t) ttbcr; + params[MMU_CFG_TTBR0] = ttbr0; +} diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S new file mode 100644 index 0000000..9f075e4 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .global enable_mmu_direct_el1 + .global enable_mmu_direct_el2 + .global enable_mmu_direct_el3 + + /* Macros to read and write to system register for a given EL. */ + .macro _msr reg_name, el, gp_reg + msr \reg_name\()_el\()\el, \gp_reg + .endm + + .macro _mrs gp_reg, reg_name, el + mrs \gp_reg, \reg_name\()_el\()\el + .endm + + .macro tlbi_invalidate_all el + .if \el == 1 + TLB_INVALIDATE(vmalle1) + .elseif \el == 2 + TLB_INVALIDATE(alle2) + .elseif \el == 3 + TLB_INVALIDATE(alle3) + .else + .error "EL must be 1, 2 or 3" + .endif + .endm + + /* void enable_mmu_direct_el(unsigned int flags) */ + .macro define_mmu_enable_func el + func enable_mmu_direct_\()el\el +#if ENABLE_ASSERTIONS + _mrs x1, sctlr, \el + tst x1, #SCTLR_M_BIT + ASM_ASSERT(eq) +#endif + /* Invalidate all TLB entries */ + tlbi_invalidate_all \el + + mov x7, x0 + adrp x0, mmu_cfg_params + add x0, x0, :lo12:mmu_cfg_params + + /* MAIR */ + ldr x1, [x0, #(MMU_CFG_MAIR << 3)] + _msr mair, \el, x1 + + /* TCR */ + ldr x2, [x0, #(MMU_CFG_TCR << 3)] + _msr tcr, \el, x2 + + /* TTBR */ + ldr x3, [x0, #(MMU_CFG_TTBR0 << 3)] + _msr ttbr0, \el, x3 + + /* + * Ensure all translation table writes have drained into memory, the TLB + * invalidation is complete, and translation register writes are + * committed before enabling the MMU + */ + dsb ish + isb + + /* Set and clear required fields of SCTLR */ + _mrs x4, sctlr, \el + mov_imm x5, SCTLR_WXN_BIT | SCTLR_C_BIT | SCTLR_M_BIT + orr x4, x4, x5 + + /* Additionally, amend SCTLR fields based on flags */ + bic x5, x4, #SCTLR_C_BIT + tst x7, #DISABLE_DCACHE + csel x4, x5, x4, ne + + _msr sctlr, \el, x4 + isb + + ret + endfunc enable_mmu_direct_\()el\el + .endm + + /* + * Define MMU-enabling functions for EL1, EL2 and EL3: + * + * enable_mmu_direct_el1 + * enable_mmu_direct_el2 + * enable_mmu_direct_el3 + */ + define_mmu_enable_func 1 + define_mmu_enable_func 2 + define_mmu_enable_func 3 diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c new file mode 100644 index 0000000..719110a --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c @@ -0,0 +1,324 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "../xlat_tables_private.h" + +/* + * Returns true if the provided granule size is supported, false otherwise. + */ +bool xlat_arch_is_granule_size_supported(size_t size) +{ + u_register_t id_aa64mmfr0_el1 = read_id_aa64mmfr0_el1(); + + if (size == PAGE_SIZE_4KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN4_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN4_MASK) == + ID_AA64MMFR0_EL1_TGRAN4_SUPPORTED; + } else if (size == PAGE_SIZE_16KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN16_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN16_MASK) == + ID_AA64MMFR0_EL1_TGRAN16_SUPPORTED; + } else if (size == PAGE_SIZE_64KB) { + return ((id_aa64mmfr0_el1 >> ID_AA64MMFR0_EL1_TGRAN64_SHIFT) & + ID_AA64MMFR0_EL1_TGRAN64_MASK) == + ID_AA64MMFR0_EL1_TGRAN64_SUPPORTED; + } else { + return 0; + } +} + +size_t xlat_arch_get_max_supported_granule_size(void) +{ + if (xlat_arch_is_granule_size_supported(PAGE_SIZE_64KB)) { + return PAGE_SIZE_64KB; + } else if (xlat_arch_is_granule_size_supported(PAGE_SIZE_16KB)) { + return PAGE_SIZE_16KB; + } else { + assert(xlat_arch_is_granule_size_supported(PAGE_SIZE_4KB)); + return PAGE_SIZE_4KB; + } +} + +/* + * Determine the physical address space encoded in the 'attr' parameter. + * + * The physical address will fall into one of four spaces; secure, + * nonsecure, root, or realm if RME is enabled, or one of two spaces; + * secure and nonsecure otherwise. + */ +uint32_t xlat_arch_get_pas(uint32_t attr) +{ + uint32_t pas = MT_PAS(attr); + + switch (pas) { +#if ENABLE_RME + /* TTD.NSE = 1 and TTD.NS = 1 for Realm PAS */ + case MT_REALM: + return LOWER_ATTRS(EL3_S1_NSE | NS); + /* TTD.NSE = 1 and TTD.NS = 0 for Root PAS */ + case MT_ROOT: + return LOWER_ATTRS(EL3_S1_NSE); +#endif + case MT_NS: + return LOWER_ATTRS(NS); + default: /* MT_SECURE */ + return 0U; + } +} + +unsigned long long tcr_physical_addr_size_bits(unsigned long long max_addr) +{ + /* Physical address can't exceed 48 bits */ + assert((max_addr & ADDR_MASK_48_TO_63) == 0U); + + /* 48 bits address */ + if ((max_addr & ADDR_MASK_44_TO_47) != 0U) + return TCR_PS_BITS_256TB; + + /* 44 bits address */ + if ((max_addr & ADDR_MASK_42_TO_43) != 0U) + return TCR_PS_BITS_16TB; + + /* 42 bits address */ + if ((max_addr & ADDR_MASK_40_TO_41) != 0U) + return TCR_PS_BITS_4TB; + + /* 40 bits address */ + if ((max_addr & ADDR_MASK_36_TO_39) != 0U) + return TCR_PS_BITS_1TB; + + /* 36 bits address */ + if ((max_addr & ADDR_MASK_32_TO_35) != 0U) + return TCR_PS_BITS_64GB; + + return TCR_PS_BITS_4GB; +} + +#if ENABLE_ASSERTIONS +/* + * Physical Address ranges supported in the AArch64 Memory Model. Value 0b110 is + * supported in ARMv8.2 onwards. + */ +static const unsigned int pa_range_bits_arr[] = { + PARANGE_0000, PARANGE_0001, PARANGE_0010, PARANGE_0011, PARANGE_0100, + PARANGE_0101, PARANGE_0110 +}; + +unsigned long long xlat_arch_get_max_supported_pa(void) +{ + u_register_t pa_range = read_id_aa64mmfr0_el1() & + ID_AA64MMFR0_EL1_PARANGE_MASK; + + /* All other values are reserved */ + assert(pa_range < ARRAY_SIZE(pa_range_bits_arr)); + + return (1ULL << pa_range_bits_arr[pa_range]) - 1ULL; +} + +/* + * Return minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void) +{ + uintptr_t ret; + + if (is_armv8_4_ttst_present()) + ret = MIN_VIRT_ADDR_SPACE_SIZE_TTST; + else + ret = MIN_VIRT_ADDR_SPACE_SIZE; + + return ret; +} +#endif /* ENABLE_ASSERTIONS*/ + +bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx) +{ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1U); + return (read_sctlr_el1() & SCTLR_M_BIT) != 0U; + } else if (ctx->xlat_regime == EL2_REGIME) { + assert(xlat_arch_current_el() >= 2U); + return (read_sctlr_el2() & SCTLR_M_BIT) != 0U; + } else { + assert(ctx->xlat_regime == EL3_REGIME); + assert(xlat_arch_current_el() >= 3U); + return (read_sctlr_el3() & SCTLR_M_BIT) != 0U; + } +} + +bool is_dcache_enabled(void) +{ + unsigned int el = get_current_el_maybe_constant(); + + if (el == 1U) { + return (read_sctlr_el1() & SCTLR_C_BIT) != 0U; + } else if (el == 2U) { + return (read_sctlr_el2() & SCTLR_C_BIT) != 0U; + } else { + return (read_sctlr_el3() & SCTLR_C_BIT) != 0U; + } +} + +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime) +{ + if (xlat_regime == EL1_EL0_REGIME) { + return UPPER_ATTRS(UXN) | UPPER_ATTRS(PXN); + } else { + assert((xlat_regime == EL2_REGIME) || + (xlat_regime == EL3_REGIME)); + return UPPER_ATTRS(XN); + } +} + +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime) +{ + /* + * Ensure the translation table write has drained into memory before + * invalidating the TLB entry. + */ + dsbishst(); + + /* + * This function only supports invalidation of TLB entries for the EL3 + * and EL1&0 translation regimes. + * + * Also, it is architecturally UNDEFINED to invalidate TLBs of a higher + * exception level (see section D4.9.2 of the ARM ARM rev B.a). + */ + if (xlat_regime == EL1_EL0_REGIME) { + assert(xlat_arch_current_el() >= 1U); + tlbivaae1is(TLBI_ADDR(va)); + } else if (xlat_regime == EL2_REGIME) { + assert(xlat_arch_current_el() >= 2U); + tlbivae2is(TLBI_ADDR(va)); + } else { + assert(xlat_regime == EL3_REGIME); + assert(xlat_arch_current_el() >= 3U); + tlbivae3is(TLBI_ADDR(va)); + } +} + +void xlat_arch_tlbi_va_sync(void) +{ + /* + * A TLB maintenance instruction can complete at any time after + * it is issued, but is only guaranteed to be complete after the + * execution of DSB by the PE that executed the TLB maintenance + * instruction. After the TLB invalidate instruction is + * complete, no new memory accesses using the invalidated TLB + * entries will be observed by any observer of the system + * domain. See section D4.8.2 of the ARMv8 (issue k), paragraph + * "Ordering and completion of TLB maintenance instructions". + */ + dsbish(); + + /* + * The effects of a completed TLB maintenance instruction are + * only guaranteed to be visible on the PE that executed the + * instruction after the execution of an ISB instruction by the + * PE that executed the TLB maintenance instruction. + */ + isb(); +} + +unsigned int xlat_arch_current_el(void) +{ + unsigned int el = (unsigned int)GET_EL(read_CurrentEl()); + + assert(el > 0U); + + return el; +} + +void setup_mmu_cfg(uint64_t *params, unsigned int flags, + const uint64_t *base_table, unsigned long long max_pa, + uintptr_t max_va, int xlat_regime) +{ + uint64_t mair, ttbr0, tcr; + uintptr_t virtual_addr_space_size; + + /* Set attributes in the right indices of the MAIR. */ + mair = MAIR_ATTR_SET(ATTR_DEVICE, ATTR_DEVICE_INDEX); + mair |= MAIR_ATTR_SET(ATTR_IWBWA_OWBWA_NTR, ATTR_IWBWA_OWBWA_NTR_INDEX); + mair |= MAIR_ATTR_SET(ATTR_NON_CACHEABLE, ATTR_NON_CACHEABLE_INDEX); + + /* + * Limit the input address ranges and memory region sizes translated + * using TTBR0 to the given virtual address space size. + */ + assert(max_va < ((uint64_t)UINTPTR_MAX)); + + virtual_addr_space_size = (uintptr_t)max_va + 1U; + + assert(virtual_addr_space_size >= + xlat_get_min_virt_addr_space_size()); + assert(virtual_addr_space_size <= MAX_VIRT_ADDR_SPACE_SIZE); + assert(IS_POWER_OF_TWO(virtual_addr_space_size)); + + /* + * __builtin_ctzll(0) is undefined but here we are guaranteed that + * virtual_addr_space_size is in the range [1,UINTPTR_MAX]. + */ + int t0sz = 64 - __builtin_ctzll(virtual_addr_space_size); + + tcr = (uint64_t)t0sz << TCR_T0SZ_SHIFT; + + /* + * Set the cacheability and shareability attributes for memory + * associated with translation table walks. + */ + if ((flags & XLAT_TABLE_NC) != 0U) { + /* Inner & outer non-cacheable non-shareable. */ + tcr |= TCR_SH_NON_SHAREABLE | + TCR_RGN_OUTER_NC | TCR_RGN_INNER_NC; + } else { + /* Inner & outer WBWA & shareable. */ + tcr |= TCR_SH_INNER_SHAREABLE | + TCR_RGN_OUTER_WBA | TCR_RGN_INNER_WBA; + } + + /* + * It is safer to restrict the max physical address accessible by the + * hardware as much as possible. + */ + unsigned long long tcr_ps_bits = tcr_physical_addr_size_bits(max_pa); + + if (xlat_regime == EL1_EL0_REGIME) { + /* + * TCR_EL1.EPD1: Disable translation table walk for addresses + * that are translated using TTBR1_EL1. + */ + tcr |= TCR_EPD1_BIT | (tcr_ps_bits << TCR_EL1_IPS_SHIFT); + } else if (xlat_regime == EL2_REGIME) { + tcr |= TCR_EL2_RES1 | (tcr_ps_bits << TCR_EL2_PS_SHIFT); + } else { + assert(xlat_regime == EL3_REGIME); + tcr |= TCR_EL3_RES1 | (tcr_ps_bits << TCR_EL3_PS_SHIFT); + } + + /* Set TTBR bits as well */ + ttbr0 = (uint64_t) base_table; + + if (is_armv8_2_ttcnp_present()) { + /* Enable CnP bit so as to share page tables with all PEs. */ + ttbr0 |= TTBR_CNP_BIT; + } + + params[MMU_CFG_MAIR] = mair; + params[MMU_CFG_TCR] = tcr; + params[MMU_CFG_TTBR0] = ttbr0; +} diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk b/arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk new file mode 100644 index 0000000..7991e1a --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/ro_xlat_tables.mk @@ -0,0 +1,37 @@ +# +# Copyright (c) 2020, ARM Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${USE_DEBUGFS}, 1) + $(error "Debugfs requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") +endif + +ifeq (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + $(error "RESET_TO_SP_MIN requires functionality from the dynamic \ + translation library and is incompatible with \ + ALLOW_RO_XLAT_TABLES.") + endif +else # if AArch64 + ifeq (${PLAT},tegra) + $(error "Tegra requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${RESET_TO_BL31},1) + $(error "RESET_TO_BL31 requires functionality from the dynamic \ + translation library and is incompatible with \ + ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${SPD},trusty) + $(error "Trusty requires functionality from the dynamic translation \ + library and is incompatible with ALLOW_RO_XLAT_TABLES.") + endif + ifeq (${SPM_MM},1) + $(error "SPM_MM requires functionality to change memory region \ + attributes, which is not possible once the translation tables \ + have been made read-only.") + endif +endif diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk new file mode 100644 index 0000000..bcc3e68 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +XLAT_TABLES_LIB_SRCS := $(addprefix lib/xlat_tables_v2/, \ + ${ARCH}/enable_mmu.S \ + ${ARCH}/xlat_tables_arch.c \ + xlat_tables_context.c \ + xlat_tables_core.c \ + xlat_tables_utils.c) + +XLAT_TABLES_LIB_V2 := 1 +$(eval $(call add_define,XLAT_TABLES_LIB_V2)) + +ifeq (${ALLOW_RO_XLAT_TABLES}, 1) + include lib/xlat_tables_v2/ro_xlat_tables.mk +endif diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c new file mode 100644 index 0000000..95dae88 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c @@ -0,0 +1,270 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include "xlat_tables_private.h" + +/* + * MMU configuration register values for the active translation context. Used + * from the MMU assembly helpers. + */ +uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* + * Allocate and initialise the default translation context for the BL image + * currently executing. + */ +REGISTER_XLAT_CONTEXT(tf, MAX_MMAP_REGIONS, MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE); + +void mmap_add_region(unsigned long long base_pa, uintptr_t base_va, size_t size, + unsigned int attr) +{ + mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); + + mmap_add_region_ctx(&tf_xlat_ctx, &mm); +} + +void mmap_add(const mmap_region_t *mm) +{ + mmap_add_ctx(&tf_xlat_ctx, mm); +} + +void mmap_add_region_alloc_va(unsigned long long base_pa, uintptr_t *base_va, + size_t size, unsigned int attr) +{ + mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); + + mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, &mm); + + *base_va = mm.base_va; +} + +void mmap_add_alloc_va(mmap_region_t *mm) +{ + while (mm->granularity != 0U) { + assert(mm->base_va == 0U); + mmap_add_region_alloc_va_ctx(&tf_xlat_ctx, mm); + mm++; + } +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +int mmap_add_dynamic_region(unsigned long long base_pa, uintptr_t base_va, + size_t size, unsigned int attr) +{ + mmap_region_t mm = MAP_REGION(base_pa, base_va, size, attr); + + return mmap_add_dynamic_region_ctx(&tf_xlat_ctx, &mm); +} + +int mmap_add_dynamic_region_alloc_va(unsigned long long base_pa, + uintptr_t *base_va, size_t size, + unsigned int attr) +{ + mmap_region_t mm = MAP_REGION_ALLOC_VA(base_pa, size, attr); + + int rc = mmap_add_dynamic_region_alloc_va_ctx(&tf_xlat_ctx, &mm); + + *base_va = mm.base_va; + + return rc; +} + + +int mmap_remove_dynamic_region(uintptr_t base_va, size_t size) +{ + return mmap_remove_dynamic_region_ctx(&tf_xlat_ctx, + base_va, size); +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +void __init init_xlat_tables(void) +{ + assert(tf_xlat_ctx.xlat_regime == EL_REGIME_INVALID); + + unsigned int current_el = xlat_arch_current_el(); + + if (current_el == 1U) { + tf_xlat_ctx.xlat_regime = EL1_EL0_REGIME; + } else if (current_el == 2U) { + tf_xlat_ctx.xlat_regime = EL2_REGIME; + } else { + assert(current_el == 3U); + tf_xlat_ctx.xlat_regime = EL3_REGIME; + } + + init_xlat_tables_ctx(&tf_xlat_ctx); +} + +int xlat_get_mem_attributes(uintptr_t base_va, uint32_t *attr) +{ + return xlat_get_mem_attributes_ctx(&tf_xlat_ctx, base_va, attr); +} + +int xlat_change_mem_attributes(uintptr_t base_va, size_t size, uint32_t attr) +{ + return xlat_change_mem_attributes_ctx(&tf_xlat_ctx, base_va, size, attr); +} + +#if PLAT_RO_XLAT_TABLES +/* Change the memory attributes of the descriptors which resolve the address + * range that belongs to the translation tables themselves, which are by default + * mapped as part of read-write data in the BL image's memory. + * + * Since the translation tables map themselves via these level 3 (page) + * descriptors, any change applied to them with the MMU on would introduce a + * chicken and egg problem because of the break-before-make sequence. + * Eventually, it would reach the descriptor that resolves the very table it + * belongs to and the invalidation (break step) would cause the subsequent write + * (make step) to it to generate an MMU fault. Therefore, the MMU is disabled + * before making the change. + * + * No assumption is made about what data this function needs, therefore all the + * caches are flushed in order to ensure coherency. A future optimization would + * be to only flush the required data to main memory. + */ +int xlat_make_tables_readonly(void) +{ + assert(tf_xlat_ctx.initialized == true); +#ifdef __aarch64__ + if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) { + disable_mmu_el1(); + } else if (tf_xlat_ctx.xlat_regime == EL3_REGIME) { + disable_mmu_el3(); + } else { + assert(tf_xlat_ctx.xlat_regime == EL2_REGIME); + return -1; + } + + /* Flush all caches. */ + dcsw_op_all(DCCISW); +#else /* !__aarch64__ */ + assert(tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME); + /* On AArch32, we flush the caches before disabling the MMU. The reason + * for this is that the dcsw_op_all AArch32 function pushes some + * registers onto the stack under the assumption that it is writing to + * cache, which is not true with the MMU off. This would result in the + * stack becoming corrupted and a wrong/junk value for the LR being + * restored at the end of the routine. + */ + dcsw_op_all(DC_OP_CISW); + disable_mmu_secure(); +#endif + + int rc = xlat_change_mem_attributes_ctx(&tf_xlat_ctx, + (uintptr_t)tf_xlat_ctx.tables, + tf_xlat_ctx.tables_num * XLAT_TABLE_SIZE, + MT_RO_DATA | MT_SECURE); + +#ifdef __aarch64__ + if (tf_xlat_ctx.xlat_regime == EL1_EL0_REGIME) { + enable_mmu_el1(0U); + } else { + assert(tf_xlat_ctx.xlat_regime == EL3_REGIME); + enable_mmu_el3(0U); + } +#else /* !__aarch64__ */ + enable_mmu_svc_mon(0U); +#endif + + if (rc == 0) { + tf_xlat_ctx.readonly_tables = true; + } + + return rc; +} +#endif /* PLAT_RO_XLAT_TABLES */ + +/* + * If dynamic allocation of new regions is disabled then by the time we call the + * function enabling the MMU, we'll have registered all the memory regions to + * map for the system's lifetime. Therefore, at this point we know the maximum + * physical address that will ever be mapped. + * + * If dynamic allocation is enabled then we can't make any such assumption + * because the maximum physical address could get pushed while adding a new + * region. Therefore, in this case we have to assume that the whole address + * space size might be mapped. + */ +#ifdef PLAT_XLAT_TABLES_DYNAMIC +#define MAX_PHYS_ADDR tf_xlat_ctx.pa_max_address +#else +#define MAX_PHYS_ADDR tf_xlat_ctx.max_pa +#endif + +#ifdef __aarch64__ + +void enable_mmu_el1(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); + enable_mmu_direct_el1(flags); +} + +void enable_mmu_el2(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL2_REGIME); + enable_mmu_direct_el2(flags); +} + +void enable_mmu_el3(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL3_REGIME); + enable_mmu_direct_el3(flags); +} + +void enable_mmu(unsigned int flags) +{ + switch (get_current_el_maybe_constant()) { + case 1: + enable_mmu_el1(flags); + break; + case 2: + enable_mmu_el2(flags); + break; + case 3: + enable_mmu_el3(flags); + break; + default: + panic(); + } +} + +#else /* !__aarch64__ */ + +void enable_mmu_svc_mon(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL1_EL0_REGIME); + enable_mmu_direct_svc_mon(flags); +} + +void enable_mmu_hyp(unsigned int flags) +{ + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, flags, + tf_xlat_ctx.base_table, MAX_PHYS_ADDR, + tf_xlat_ctx.va_max_address, EL2_REGIME); + enable_mmu_direct_hyp(flags); +} + +#endif /* __aarch64__ */ diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c new file mode 100644 index 0000000..de57184 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c @@ -0,0 +1,1244 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include "xlat_tables_private.h" + +/* Helper function that cleans the data cache only if it is enabled. */ +static inline __attribute__((unused)) void xlat_clean_dcache_range(uintptr_t addr, size_t size) +{ + if (is_dcache_enabled()) + clean_dcache_range(addr, size); +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +/* + * The following functions assume that they will be called using subtables only. + * The base table can't be unmapped, so it is not needed to do any special + * handling for it. + */ + +/* + * Returns the index of the array corresponding to the specified translation + * table. + */ +static int xlat_table_get_index(const xlat_ctx_t *ctx, const uint64_t *table) +{ + for (int i = 0; i < ctx->tables_num; i++) + if (ctx->tables[i] == table) + return i; + + /* + * Maybe we were asked to get the index of the base level table, which + * should never happen. + */ + assert(false); + + return -1; +} + +/* Returns a pointer to an empty translation table. */ +static uint64_t *xlat_table_get_empty(const xlat_ctx_t *ctx) +{ + for (int i = 0; i < ctx->tables_num; i++) + if (ctx->tables_mapped_regions[i] == 0) + return ctx->tables[i]; + + return NULL; +} + +/* Increments region count for a given table. */ +static void xlat_table_inc_regions_count(const xlat_ctx_t *ctx, + const uint64_t *table) +{ + int idx = xlat_table_get_index(ctx, table); + + ctx->tables_mapped_regions[idx]++; +} + +/* Decrements region count for a given table. */ +static void xlat_table_dec_regions_count(const xlat_ctx_t *ctx, + const uint64_t *table) +{ + int idx = xlat_table_get_index(ctx, table); + + ctx->tables_mapped_regions[idx]--; +} + +/* Returns 0 if the specified table isn't empty, otherwise 1. */ +static bool xlat_table_is_empty(const xlat_ctx_t *ctx, const uint64_t *table) +{ + return ctx->tables_mapped_regions[xlat_table_get_index(ctx, table)] == 0; +} + +#else /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* Returns a pointer to the first empty translation table. */ +static uint64_t *xlat_table_get_empty(xlat_ctx_t *ctx) +{ + assert(ctx->next_table < ctx->tables_num); + + return ctx->tables[ctx->next_table++]; +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * Returns a block/page table descriptor for the given level and attributes. + */ +uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, + unsigned long long addr_pa, unsigned int level) +{ + uint64_t desc; + uint32_t mem_type; + uint32_t shareability_type; + + /* Make sure that the granularity is fine enough to map this address. */ + assert((addr_pa & XLAT_BLOCK_MASK(level)) == 0U); + + desc = addr_pa; + /* + * There are different translation table descriptors for level 3 and the + * rest. + */ + desc |= (level == XLAT_TABLE_LEVEL_MAX) ? PAGE_DESC : BLOCK_DESC; + /* + * Always set the access flag, as this library assumes access flag + * faults aren't managed. + */ + desc |= LOWER_ATTRS(ACCESS_FLAG); + + /* Determine the physical address space this region belongs to. */ + desc |= xlat_arch_get_pas(attr); + + /* + * Deduce other fields of the descriptor based on the MT_RW memory + * region attributes. + */ + desc |= ((attr & MT_RW) != 0U) ? LOWER_ATTRS(AP_RW) : LOWER_ATTRS(AP_RO); + + /* + * Do not allow unprivileged access when the mapping is for a privileged + * EL. For translation regimes that do not have mappings for access for + * lower exception levels, set AP[2] to AP_NO_ACCESS_UNPRIVILEGED. + */ + if (ctx->xlat_regime == EL1_EL0_REGIME) { + if ((attr & MT_USER) != 0U) { + /* EL0 mapping requested, so we give User access */ + desc |= LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED); + } else { + /* EL1 mapping requested, no User access granted */ + desc |= LOWER_ATTRS(AP_NO_ACCESS_UNPRIVILEGED); + } + } else { + assert((ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL3_REGIME)); + desc |= LOWER_ATTRS(AP_ONE_VA_RANGE_RES1); + } + + /* + * Deduce shareability domain and executability of the memory region + * from the memory type of the attributes (MT_TYPE). + * + * Data accesses to device memory and non-cacheable normal memory are + * coherent for all observers in the system, and correspondingly are + * always treated as being Outer Shareable. Therefore, for these 2 types + * of memory, it is not strictly needed to set the shareability field + * in the translation tables. + */ + mem_type = MT_TYPE(attr); + if (mem_type == MT_DEVICE) { + desc |= LOWER_ATTRS(ATTR_DEVICE_INDEX | OSH); + /* + * Always map device memory as execute-never. + * This is to avoid the possibility of a speculative instruction + * fetch, which could be an issue if this memory region + * corresponds to a read-sensitive peripheral. + */ + desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + + } else { /* Normal memory */ + /* + * Always map read-write normal memory as execute-never. + * This library assumes that it is used by software that does + * not self-modify its code, therefore R/W memory is reserved + * for data storage, which must not be executable. + * + * Note that setting the XN bit here is for consistency only. + * The function that enables the MMU sets the SCTLR_ELx.WXN bit, + * which makes any writable memory region to be treated as + * execute-never, regardless of the value of the XN bit in the + * translation table. + * + * For read-only memory, rely on the MT_EXECUTE/MT_EXECUTE_NEVER + * attribute to figure out the value of the XN bit. The actual + * XN bit(s) to set in the descriptor depends on the context's + * translation regime and the policy applied in + * xlat_arch_regime_get_xn_desc(). + */ + if (((attr & MT_RW) != 0U) || ((attr & MT_EXECUTE_NEVER) != 0U)) { + desc |= xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + } + + shareability_type = MT_SHAREABILITY(attr); + if (mem_type == MT_MEMORY) { + desc |= LOWER_ATTRS(ATTR_IWBWA_OWBWA_NTR_INDEX); + if (shareability_type == MT_SHAREABILITY_NSH) { + desc |= LOWER_ATTRS(NSH); + } else if (shareability_type == MT_SHAREABILITY_OSH) { + desc |= LOWER_ATTRS(OSH); + } else { + desc |= LOWER_ATTRS(ISH); + } + + /* Check if Branch Target Identification is enabled */ +#if ENABLE_BTI + /* Set GP bit for block and page code entries + * if BTI mechanism is implemented. + */ + if (is_armv8_5_bti_present() && + ((attr & (MT_TYPE_MASK | MT_RW | + MT_EXECUTE_NEVER)) == MT_CODE)) { + desc |= GP; + } +#endif + } else { + assert(mem_type == MT_NON_CACHEABLE); + desc |= LOWER_ATTRS(ATTR_NON_CACHEABLE_INDEX | OSH); + } + } + + return desc; +} + +/* + * Enumeration of actions that can be made when mapping table entries depending + * on the previous value in that entry and information about the region being + * mapped. + */ +typedef enum { + + /* Do nothing */ + ACTION_NONE, + + /* Write a block (or page, if in level 3) entry. */ + ACTION_WRITE_BLOCK_ENTRY, + + /* + * Create a new table and write a table entry pointing to it. Recurse + * into it for further processing. + */ + ACTION_CREATE_NEW_TABLE, + + /* + * There is a table descriptor in this entry, read it and recurse into + * that table for further processing. + */ + ACTION_RECURSE_INTO_TABLE, + +} action_t; + +/* + * Function that returns the first VA of the table affected by the specified + * mmap region. + */ +static uintptr_t xlat_tables_find_start_va(mmap_region_t *mm, + const uintptr_t table_base_va, + const unsigned int level) +{ + uintptr_t table_idx_va; + + if (mm->base_va > table_base_va) { + /* Find the first index of the table affected by the region. */ + table_idx_va = mm->base_va & ~XLAT_BLOCK_MASK(level); + } else { + /* Start from the beginning of the table. */ + table_idx_va = table_base_va; + } + + return table_idx_va; +} + +/* + * Function that returns table index for the given VA and level arguments. + */ +static inline unsigned int xlat_tables_va_to_index(const uintptr_t table_base_va, + const uintptr_t va, + const unsigned int level) +{ + return (unsigned int)((va - table_base_va) >> XLAT_ADDR_SHIFT(level)); +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +/* + * From the given arguments, it decides which action to take when unmapping the + * specified region. + */ +static action_t xlat_tables_unmap_region_action(const mmap_region_t *mm, + const uintptr_t table_idx_va, const uintptr_t table_idx_end_va, + const unsigned int level, const uint64_t desc_type) +{ + action_t action; + uintptr_t region_end_va = mm->base_va + mm->size - 1U; + + if ((mm->base_va <= table_idx_va) && + (region_end_va >= table_idx_end_va)) { + /* Region covers all block */ + + if (level == 3U) { + /* + * Last level, only page descriptors allowed, + * erase it. + */ + assert(desc_type == PAGE_DESC); + + action = ACTION_WRITE_BLOCK_ENTRY; + } else { + /* + * Other levels can have table descriptors. If + * so, recurse into it and erase descriptors + * inside it as needed. If there is a block + * descriptor, just erase it. If an invalid + * descriptor is found, this table isn't + * actually mapped, which shouldn't happen. + */ + if (desc_type == TABLE_DESC) { + action = ACTION_RECURSE_INTO_TABLE; + } else { + assert(desc_type == BLOCK_DESC); + action = ACTION_WRITE_BLOCK_ENTRY; + } + } + + } else if ((mm->base_va <= table_idx_end_va) || + (region_end_va >= table_idx_va)) { + /* + * Region partially covers block. + * + * It can't happen in level 3. + * + * There must be a table descriptor here, if not there + * was a problem when mapping the region. + */ + assert(level < 3U); + assert(desc_type == TABLE_DESC); + + action = ACTION_RECURSE_INTO_TABLE; + } else { + /* The region doesn't cover the block at all */ + action = ACTION_NONE; + } + + return action; +} +/* + * Recursive function that writes to the translation tables and unmaps the + * specified region. + */ +static void xlat_tables_unmap_region(xlat_ctx_t *ctx, mmap_region_t *mm, + const uintptr_t table_base_va, + uint64_t *const table_base, + const unsigned int table_entries, + const unsigned int level) +{ + assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); + + uint64_t *subtable; + uint64_t desc; + + uintptr_t table_idx_va; + uintptr_t table_idx_end_va; /* End VA of this entry */ + + uintptr_t region_end_va = mm->base_va + mm->size - 1U; + + unsigned int table_idx; + + table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); + table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); + + while (table_idx < table_entries) { + + table_idx_end_va = table_idx_va + XLAT_BLOCK_SIZE(level) - 1U; + + desc = table_base[table_idx]; + uint64_t desc_type = desc & DESC_MASK; + + action_t action = xlat_tables_unmap_region_action(mm, + table_idx_va, table_idx_end_va, level, + desc_type); + + if (action == ACTION_WRITE_BLOCK_ENTRY) { + + table_base[table_idx] = INVALID_DESC; + xlat_arch_tlbi_va(table_idx_va, ctx->xlat_regime); + + } else if (action == ACTION_RECURSE_INTO_TABLE) { + + subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + + /* Recurse to write into subtable */ + xlat_tables_unmap_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + /* + * If the subtable is now empty, remove its reference. + */ + if (xlat_table_is_empty(ctx, subtable)) { + table_base[table_idx] = INVALID_DESC; + xlat_arch_tlbi_va(table_idx_va, + ctx->xlat_regime); + } + + } else { + assert(action == ACTION_NONE); + } + + table_idx++; + table_idx_va += XLAT_BLOCK_SIZE(level); + + /* If reached the end of the region, exit */ + if (region_end_va <= table_idx_va) + break; + } + + if (level > ctx->base_level) + xlat_table_dec_regions_count(ctx, table_base); +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +/* + * From the given arguments, it decides which action to take when mapping the + * specified region. + */ +static action_t xlat_tables_map_region_action(const mmap_region_t *mm, + unsigned int desc_type, unsigned long long dest_pa, + uintptr_t table_entry_base_va, unsigned int level) +{ + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + uintptr_t table_entry_end_va = + table_entry_base_va + XLAT_BLOCK_SIZE(level) - 1U; + + /* + * The descriptor types allowed depend on the current table level. + */ + + if ((mm->base_va <= table_entry_base_va) && + (mm_end_va >= table_entry_end_va)) { + + /* + * Table entry is covered by region + * -------------------------------- + * + * This means that this table entry can describe the whole + * translation with this granularity in principle. + */ + + if (level == 3U) { + /* + * Last level, only page descriptors are allowed. + */ + if (desc_type == PAGE_DESC) { + /* + * There's another region mapped here, don't + * overwrite. + */ + return ACTION_NONE; + } else { + assert(desc_type == INVALID_DESC); + return ACTION_WRITE_BLOCK_ENTRY; + } + + } else { + + /* + * Other levels. Table descriptors are allowed. Block + * descriptors too, but they have some limitations. + */ + + if (desc_type == TABLE_DESC) { + /* There's already a table, recurse into it. */ + return ACTION_RECURSE_INTO_TABLE; + + } else if (desc_type == INVALID_DESC) { + /* + * There's nothing mapped here, create a new + * entry. + * + * Check if the destination granularity allows + * us to use a block descriptor or we need a + * finer table for it. + * + * Also, check if the current level allows block + * descriptors. If not, create a table instead. + */ + if (((dest_pa & XLAT_BLOCK_MASK(level)) != 0U) + || (level < MIN_LVL_BLOCK_DESC) || + (mm->granularity < XLAT_BLOCK_SIZE(level))) + return ACTION_CREATE_NEW_TABLE; + else + return ACTION_WRITE_BLOCK_ENTRY; + + } else { + /* + * There's another region mapped here, don't + * overwrite. + */ + assert(desc_type == BLOCK_DESC); + + return ACTION_NONE; + } + } + + } else if ((mm->base_va <= table_entry_end_va) || + (mm_end_va >= table_entry_base_va)) { + + /* + * Region partially covers table entry + * ----------------------------------- + * + * This means that this table entry can't describe the whole + * translation, a finer table is needed. + + * There cannot be partial block overlaps in level 3. If that + * happens, some of the preliminary checks when adding the + * mmap region failed to detect that PA and VA must at least be + * aligned to PAGE_SIZE. + */ + assert(level < 3U); + + if (desc_type == INVALID_DESC) { + /* + * The block is not fully covered by the region. Create + * a new table, recurse into it and try to map the + * region with finer granularity. + */ + return ACTION_CREATE_NEW_TABLE; + + } else { + assert(desc_type == TABLE_DESC); + /* + * The block is not fully covered by the region, but + * there is already a table here. Recurse into it and + * try to map with finer granularity. + * + * PAGE_DESC for level 3 has the same value as + * TABLE_DESC, but this code can't run on a level 3 + * table because there can't be overlaps in level 3. + */ + return ACTION_RECURSE_INTO_TABLE; + } + } else { + + /* + * This table entry is outside of the region specified in the + * arguments, don't write anything to it. + */ + return ACTION_NONE; + } +} + +/* + * Recursive function that writes to the translation tables and maps the + * specified region. On success, it returns the VA of the last byte that was + * successfully mapped. On error, it returns the VA of the next entry that + * should have been mapped. + */ +static uintptr_t xlat_tables_map_region(xlat_ctx_t *ctx, mmap_region_t *mm, + uintptr_t table_base_va, + uint64_t *const table_base, + unsigned int table_entries, + unsigned int level) +{ + assert((level >= ctx->base_level) && (level <= XLAT_TABLE_LEVEL_MAX)); + + uintptr_t mm_end_va = mm->base_va + mm->size - 1U; + + uintptr_t table_idx_va; + unsigned long long table_idx_pa; + + uint64_t *subtable; + uint64_t desc; + + unsigned int table_idx; + + table_idx_va = xlat_tables_find_start_va(mm, table_base_va, level); + table_idx = xlat_tables_va_to_index(table_base_va, table_idx_va, level); + +#if PLAT_XLAT_TABLES_DYNAMIC + if (level > ctx->base_level) + xlat_table_inc_regions_count(ctx, table_base); +#endif + + while (table_idx < table_entries) { + + desc = table_base[table_idx]; + + table_idx_pa = mm->base_pa + table_idx_va - mm->base_va; + + action_t action = xlat_tables_map_region_action(mm, + (uint32_t)(desc & DESC_MASK), table_idx_pa, + table_idx_va, level); + + if (action == ACTION_WRITE_BLOCK_ENTRY) { + + table_base[table_idx] = + xlat_desc(ctx, (uint32_t)mm->attr, table_idx_pa, + level); + + } else if (action == ACTION_CREATE_NEW_TABLE) { + uintptr_t end_va; + + subtable = xlat_table_get_empty(ctx); + if (subtable == NULL) { + /* Not enough free tables to map this region */ + return table_idx_va; + } + + /* Point to new subtable from this one. */ + table_base[table_idx] = + TABLE_DESC | (uintptr_t)subtable; + + /* Recurse to write into subtable */ + end_va = xlat_tables_map_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + if (end_va != + (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) + return end_va; + + } else if (action == ACTION_RECURSE_INTO_TABLE) { + uintptr_t end_va; + + subtable = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + /* Recurse to write into subtable */ + end_va = xlat_tables_map_region(ctx, mm, table_idx_va, + subtable, XLAT_TABLE_ENTRIES, + level + 1U); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)subtable, + XLAT_TABLE_ENTRIES * sizeof(uint64_t)); +#endif + if (end_va != + (table_idx_va + XLAT_BLOCK_SIZE(level) - 1U)) + return end_va; + + } else { + + assert(action == ACTION_NONE); + + } + + table_idx++; + table_idx_va += XLAT_BLOCK_SIZE(level); + + /* If reached the end of the region, exit */ + if (mm_end_va <= table_idx_va) + break; + } + + return table_idx_va - 1U; +} + +/* + * Function that verifies that a region can be mapped. + * Returns: + * 0: Success, the mapping is allowed. + * EINVAL: Invalid values were used as arguments. + * ERANGE: The memory limits were surpassed. + * ENOMEM: There is not enough memory in the mmap array. + * EPERM: Region overlaps another one in an invalid way. + */ +static int mmap_add_region_check(const xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + unsigned long long base_pa = mm->base_pa; + uintptr_t base_va = mm->base_va; + size_t size = mm->size; + size_t granularity = mm->granularity; + + unsigned long long end_pa = base_pa + size - 1U; + uintptr_t end_va = base_va + size - 1U; + + if (!IS_PAGE_ALIGNED(base_pa) || !IS_PAGE_ALIGNED(base_va) || + !IS_PAGE_ALIGNED(size)) + return -EINVAL; + + if ((granularity != XLAT_BLOCK_SIZE(1U)) && + (granularity != XLAT_BLOCK_SIZE(2U)) && + (granularity != XLAT_BLOCK_SIZE(3U))) { + return -EINVAL; + } + + /* Check for overflows */ + if ((base_pa > end_pa) || (base_va > end_va)) + return -ERANGE; + + if (end_va > ctx->va_max_address) + return -ERANGE; + + if (end_pa > ctx->pa_max_address) + return -ERANGE; + + /* Check that there is space in the ctx->mmap array */ + if (ctx->mmap[ctx->mmap_num - 1].size != 0U) + return -ENOMEM; + + /* Check for PAs and VAs overlaps with all other regions */ + for (const mmap_region_t *mm_cursor = ctx->mmap; + mm_cursor->size != 0U; ++mm_cursor) { + + uintptr_t mm_cursor_end_va = mm_cursor->base_va + + mm_cursor->size - 1U; + + /* + * Check if one of the regions is completely inside the other + * one. + */ + bool fully_overlapped_va = + ((base_va >= mm_cursor->base_va) && + (end_va <= mm_cursor_end_va)) || + ((mm_cursor->base_va >= base_va) && + (mm_cursor_end_va <= end_va)); + + /* + * Full VA overlaps are only allowed if both regions are + * identity mapped (zero offset) or have the same VA to PA + * offset. Also, make sure that it's not the exact same area. + * This can only be done with static regions. + */ + if (fully_overlapped_va) { + +#if PLAT_XLAT_TABLES_DYNAMIC + if (((mm->attr & MT_DYNAMIC) != 0U) || + ((mm_cursor->attr & MT_DYNAMIC) != 0U)) + return -EPERM; +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + if ((mm_cursor->base_va - mm_cursor->base_pa) != + (base_va - base_pa)) + return -EPERM; + + if ((base_va == mm_cursor->base_va) && + (size == mm_cursor->size)) + return -EPERM; + + } else { + /* + * If the regions do not have fully overlapping VAs, + * then they must have fully separated VAs and PAs. + * Partial overlaps are not allowed + */ + + unsigned long long mm_cursor_end_pa = + mm_cursor->base_pa + mm_cursor->size - 1U; + + bool separated_pa = (end_pa < mm_cursor->base_pa) || + (base_pa > mm_cursor_end_pa); + bool separated_va = (end_va < mm_cursor->base_va) || + (base_va > mm_cursor_end_va); + + if (!separated_va || !separated_pa) + return -EPERM; + } + } + + return 0; +} + +void mmap_add_region_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + mmap_region_t *mm_cursor = ctx->mmap, *mm_destination; + const mmap_region_t *mm_end = ctx->mmap + ctx->mmap_num; + const mmap_region_t *mm_last; + unsigned long long end_pa = mm->base_pa + mm->size - 1U; + uintptr_t end_va = mm->base_va + mm->size - 1U; + int ret; + + /* Ignore empty regions */ + if (mm->size == 0U) + return; + + /* Static regions must be added before initializing the xlat tables. */ + assert(!ctx->initialized); + + ret = mmap_add_region_check(ctx, mm); + if (ret != 0) { + ERROR("mmap_add_region_check() failed. error %d\n", ret); + assert(false); + return; + } + + /* + * Find correct place in mmap to insert new region. + * + * 1 - Lower region VA end first. + * 2 - Smaller region size first. + * + * VA 0 0xFF + * + * 1st |------| + * 2nd |------------| + * 3rd |------| + * 4th |---| + * 5th |---| + * 6th |----------| + * 7th |-------------------------------------| + * + * This is required for overlapping regions only. It simplifies adding + * regions with the loop in xlat_tables_init_internal because the outer + * ones won't overwrite block or page descriptors of regions added + * previously. + * + * Overlapping is only allowed for static regions. + */ + + while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) + && (mm_cursor->size != 0U)) { + ++mm_cursor; + } + + while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && + (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { + ++mm_cursor; + } + + /* + * Find the last entry marker in the mmap + */ + mm_last = ctx->mmap; + while ((mm_last->size != 0U) && (mm_last < mm_end)) { + ++mm_last; + } + + /* + * Check if we have enough space in the memory mapping table. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_last->size == 0U); + + /* Make room for new region by moving other regions up by one place */ + mm_destination = mm_cursor + 1; + (void)memmove(mm_destination, mm_cursor, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check we haven't lost the empty sentinel from the end of the array. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_end->size == 0U); + + *mm_cursor = *mm; + + if (end_pa > ctx->max_pa) + ctx->max_pa = end_pa; + if (end_va > ctx->max_va) + ctx->max_va = end_va; +} + +/* + * Determine the table level closest to the initial lookup level that + * can describe this translation. Then, align base VA to the next block + * at the determined level. + */ +static void mmap_alloc_va_align_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + /* + * By or'ing the size and base PA the alignment will be the one + * corresponding to the smallest boundary of the two of them. + * + * There are three different cases. For example (for 4 KiB page size): + * + * +--------------+------------------++--------------+ + * | PA alignment | Size multiple of || VA alignment | + * +--------------+------------------++--------------+ + * | 2 MiB | 2 MiB || 2 MiB | (1) + * | 2 MiB | 4 KiB || 4 KiB | (2) + * | 4 KiB | 2 MiB || 4 KiB | (3) + * +--------------+------------------++--------------+ + * + * - In (1), it is possible to take advantage of the alignment of the PA + * and the size of the region to use a level 2 translation table + * instead of a level 3 one. + * + * - In (2), the size is smaller than a block entry of level 2, so it is + * needed to use a level 3 table to describe the region or the library + * will map more memory than the desired one. + * + * - In (3), even though the region has the size of one level 2 block + * entry, it isn't possible to describe the translation with a level 2 + * block entry because of the alignment of the base PA. + * + * Only bits 47:21 of a level 2 block descriptor are used by the MMU, + * bits 20:0 of the resulting address are 0 in this case. Because of + * this, the PA generated as result of this translation is aligned to + * 2 MiB. The PA that was requested to be mapped is aligned to 4 KiB, + * though, which means that the resulting translation is incorrect. + * The only way to prevent this is by using a finer granularity. + */ + unsigned long long align_check; + + align_check = mm->base_pa | (unsigned long long)mm->size; + + /* + * Assume it is always aligned to level 3. There's no need to check that + * level because its block size is PAGE_SIZE. The checks to verify that + * the addresses and size are aligned to PAGE_SIZE are inside + * mmap_add_region. + */ + for (unsigned int level = ctx->base_level; level <= 2U; ++level) { + + if ((align_check & XLAT_BLOCK_MASK(level)) != 0U) + continue; + + mm->base_va = round_up(mm->base_va, XLAT_BLOCK_SIZE(level)); + return; + } +} + +void mmap_add_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mm->base_va = ctx->max_va + 1UL; + + assert(mm->size > 0U); + + mmap_alloc_va_align_ctx(ctx, mm); + + /* Detect overflows. More checks are done in mmap_add_region_check(). */ + assert(mm->base_va > ctx->max_va); + + mmap_add_region_ctx(ctx, mm); +} + +void mmap_add_ctx(xlat_ctx_t *ctx, const mmap_region_t *mm) +{ + const mmap_region_t *mm_cursor = mm; + + while (mm_cursor->granularity != 0U) { + mmap_add_region_ctx(ctx, mm_cursor); + mm_cursor++; + } +} + +#if PLAT_XLAT_TABLES_DYNAMIC + +int mmap_add_dynamic_region_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mmap_region_t *mm_cursor = ctx->mmap; + const mmap_region_t *mm_last = mm_cursor + ctx->mmap_num; + unsigned long long end_pa = mm->base_pa + mm->size - 1U; + uintptr_t end_va = mm->base_va + mm->size - 1U; + int ret; + + /* Nothing to do */ + if (mm->size == 0U) + return 0; + + /* Now this region is a dynamic one */ + mm->attr |= MT_DYNAMIC; + + ret = mmap_add_region_check(ctx, mm); + if (ret != 0) + return ret; + + /* + * Find the adequate entry in the mmap array in the same way done for + * static regions in mmap_add_region_ctx(). + */ + + while (((mm_cursor->base_va + mm_cursor->size - 1U) < end_va) + && (mm_cursor->size != 0U)) { + ++mm_cursor; + } + + while (((mm_cursor->base_va + mm_cursor->size - 1U) == end_va) && + (mm_cursor->size != 0U) && (mm_cursor->size < mm->size)) { + ++mm_cursor; + } + + /* Make room for new region by moving other regions up by one place */ + (void)memmove(mm_cursor + 1U, mm_cursor, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check we haven't lost the empty sentinal from the end of the array. + * This shouldn't happen as we have checked in mmap_add_region_check + * that there is free space. + */ + assert(mm_last->size == 0U); + + *mm_cursor = *mm; + + /* + * Update the translation tables if the xlat tables are initialized. If + * not, this region will be mapped when they are initialized. + */ + if (ctx->initialized) { + end_va = xlat_tables_map_region(ctx, mm_cursor, + 0U, ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + /* Failed to map, remove mmap entry, unmap and return error. */ + if (end_va != (mm_cursor->base_va + mm_cursor->size - 1U)) { + (void)memmove(mm_cursor, mm_cursor + 1U, + (uintptr_t)mm_last - (uintptr_t)mm_cursor); + + /* + * Check if the mapping function actually managed to map + * anything. If not, just return now. + */ + if (mm->base_va >= end_va) + return -ENOMEM; + + /* + * Something went wrong after mapping some table + * entries, undo every change done up to this point. + */ + mmap_region_t unmap_mm = { + .base_pa = 0U, + .base_va = mm->base_va, + .size = end_va - mm->base_va, + .attr = 0U + }; + xlat_tables_unmap_region(ctx, &unmap_mm, 0U, + ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + return -ENOMEM; + } + + /* + * Make sure that all entries are written to the memory. There + * is no need to invalidate entries when mapping dynamic regions + * because new table/block/page descriptors only replace old + * invalid descriptors, that aren't TLB cached. + */ + dsbishst(); + } + + if (end_pa > ctx->max_pa) + ctx->max_pa = end_pa; + if (end_va > ctx->max_va) + ctx->max_va = end_va; + + return 0; +} + +int mmap_add_dynamic_region_alloc_va_ctx(xlat_ctx_t *ctx, mmap_region_t *mm) +{ + mm->base_va = ctx->max_va + 1UL; + + if (mm->size == 0U) + return 0; + + mmap_alloc_va_align_ctx(ctx, mm); + + /* Detect overflows. More checks are done in mmap_add_region_check(). */ + if (mm->base_va < ctx->max_va) { + return -ENOMEM; + } + + return mmap_add_dynamic_region_ctx(ctx, mm); +} + +/* + * Removes the region with given base Virtual Address and size from the given + * context. + * + * Returns: + * 0: Success. + * EINVAL: Invalid values were used as arguments (region not found). + * EPERM: Tried to remove a static region. + */ +int mmap_remove_dynamic_region_ctx(xlat_ctx_t *ctx, uintptr_t base_va, + size_t size) +{ + mmap_region_t *mm = ctx->mmap; + const mmap_region_t *mm_last = mm + ctx->mmap_num; + int update_max_va_needed = 0; + int update_max_pa_needed = 0; + + /* Check sanity of mmap array. */ + assert(mm[ctx->mmap_num].size == 0U); + + while (mm->size != 0U) { + if ((mm->base_va == base_va) && (mm->size == size)) + break; + ++mm; + } + + /* Check that the region was found */ + if (mm->size == 0U) + return -EINVAL; + + /* If the region is static it can't be removed */ + if ((mm->attr & MT_DYNAMIC) == 0U) + return -EPERM; + + /* Check if this region is using the top VAs or PAs. */ + if ((mm->base_va + mm->size - 1U) == ctx->max_va) + update_max_va_needed = 1; + if ((mm->base_pa + mm->size - 1U) == ctx->max_pa) + update_max_pa_needed = 1; + + /* Update the translation tables if needed */ + if (ctx->initialized) { + xlat_tables_unmap_region(ctx, mm, 0U, ctx->base_table, + ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + xlat_arch_tlbi_va_sync(); + } + + /* Remove this region by moving the rest down by one place. */ + (void)memmove(mm, mm + 1U, (uintptr_t)mm_last - (uintptr_t)mm); + + /* Check if we need to update the max VAs and PAs */ + if (update_max_va_needed == 1) { + ctx->max_va = 0U; + mm = ctx->mmap; + while (mm->size != 0U) { + if ((mm->base_va + mm->size - 1U) > ctx->max_va) + ctx->max_va = mm->base_va + mm->size - 1U; + ++mm; + } + } + + if (update_max_pa_needed == 1) { + ctx->max_pa = 0U; + mm = ctx->mmap; + while (mm->size != 0U) { + if ((mm->base_pa + mm->size - 1U) > ctx->max_pa) + ctx->max_pa = mm->base_pa + mm->size - 1U; + ++mm; + } + } + + return 0; +} + +void xlat_setup_dynamic_ctx(xlat_ctx_t *ctx, unsigned long long pa_max, + uintptr_t va_max, struct mmap_region *mmap, + unsigned int mmap_num, uint64_t **tables, + unsigned int tables_num, uint64_t *base_table, + int xlat_regime, int *mapped_regions) +{ + ctx->xlat_regime = xlat_regime; + + ctx->pa_max_address = pa_max; + ctx->va_max_address = va_max; + + ctx->mmap = mmap; + ctx->mmap_num = mmap_num; + memset(ctx->mmap, 0, sizeof(struct mmap_region) * mmap_num); + + ctx->tables = (void *) tables; + ctx->tables_num = tables_num; + + uintptr_t va_space_size = va_max + 1; + ctx->base_level = GET_XLAT_TABLE_LEVEL_BASE(va_space_size); + ctx->base_table = base_table; + ctx->base_table_entries = GET_NUM_BASE_LEVEL_ENTRIES(va_space_size); + + ctx->tables_mapped_regions = mapped_regions; + + ctx->max_pa = 0; + ctx->max_va = 0; + ctx->initialized = 0; +} + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +void __init init_xlat_tables_ctx(xlat_ctx_t *ctx) +{ + assert(ctx != NULL); + assert(!ctx->initialized); + assert((ctx->xlat_regime == EL3_REGIME) || + (ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL1_EL0_REGIME)); + assert(!is_mmu_enabled_ctx(ctx)); + + mmap_region_t *mm = ctx->mmap; + + assert(ctx->va_max_address >= + (xlat_get_min_virt_addr_space_size() - 1U)); + assert(ctx->va_max_address <= (MAX_VIRT_ADDR_SPACE_SIZE - 1U)); + assert(IS_POWER_OF_TWO(ctx->va_max_address + 1U)); + + xlat_mmap_print(mm); + + /* All tables must be zeroed before mapping any region. */ + + for (unsigned int i = 0U; i < ctx->base_table_entries; i++) + ctx->base_table[i] = INVALID_DESC; + + for (int j = 0; j < ctx->tables_num; j++) { +#if PLAT_XLAT_TABLES_DYNAMIC + ctx->tables_mapped_regions[j] = 0; +#endif + for (unsigned int i = 0U; i < XLAT_TABLE_ENTRIES; i++) + ctx->tables[j][i] = INVALID_DESC; + } + + while (mm->size != 0U) { + uintptr_t end_va = xlat_tables_map_region(ctx, mm, 0U, + ctx->base_table, ctx->base_table_entries, + ctx->base_level); +#if !(HW_ASSISTED_COHERENCY || WARMBOOT_ENABLE_DCACHE_EARLY) + xlat_clean_dcache_range((uintptr_t)ctx->base_table, + ctx->base_table_entries * sizeof(uint64_t)); +#endif + if (end_va != (mm->base_va + mm->size - 1U)) { + ERROR("Not enough memory to map region:\n" + " VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x\n", + mm->base_va, mm->base_pa, mm->size, mm->attr); + panic(); + } + + mm++; + } + + assert(ctx->pa_max_address <= xlat_arch_get_max_supported_pa()); + assert(ctx->max_va <= ctx->va_max_address); + assert(ctx->max_pa <= ctx->pa_max_address); + + ctx->initialized = true; + + xlat_tables_print(ctx); +} diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h new file mode 100644 index 0000000..42c9a43 --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef XLAT_TABLES_PRIVATE_H +#define XLAT_TABLES_PRIVATE_H + +#include + +#include + +#include + +#if PLAT_XLAT_TABLES_DYNAMIC +/* + * Private shifts and masks to access fields of an mmap attribute + */ +/* Dynamic or static */ +#define MT_DYN_SHIFT U(31) + +/* + * Memory mapping private attributes + * + * Private attributes not exposed in the public header. + */ + +/* + * Regions mapped before the MMU can't be unmapped dynamically (they are + * static) and regions mapped with MMU enabled can be unmapped. This + * behaviour can't be overridden. + * + * Static regions can overlap each other, dynamic regions can't. + */ +#define MT_STATIC (U(0) << MT_DYN_SHIFT) +#define MT_DYNAMIC (U(1) << MT_DYN_SHIFT) + +#endif /* PLAT_XLAT_TABLES_DYNAMIC */ + +extern uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + +/* Determine the physical address space encoded in the 'attr' parameter. */ +uint32_t xlat_arch_get_pas(uint32_t attr); + +/* + * Return the execute-never mask that will prevent instruction fetch at the + * given translation regime. + */ +uint64_t xlat_arch_regime_get_xn_desc(int xlat_regime); + +/* + * Invalidate all TLB entries that match the given virtual address. This + * operation applies to all PEs in the same Inner Shareable domain as the PE + * that executes this function. This functions must be called for every + * translation table entry that is modified. It only affects the specified + * translation regime. + * + * Note, however, that it is architecturally UNDEFINED to invalidate TLB entries + * pertaining to a higher exception level, e.g. invalidating EL3 entries from + * S-EL1. + */ +void xlat_arch_tlbi_va(uintptr_t va, int xlat_regime); + +/* + * This function has to be called at the end of any code that uses the function + * xlat_arch_tlbi_va(). + */ +void xlat_arch_tlbi_va_sync(void); + +/* Print VA, PA, size and attributes of all regions in the mmap array. */ +void xlat_mmap_print(const mmap_region_t *mmap); + +/* + * Print the current state of the translation tables by reading them from + * memory. + */ +void xlat_tables_print(xlat_ctx_t *ctx); + +/* + * Returns a block/page table descriptor for the given level and attributes. + */ +uint64_t xlat_desc(const xlat_ctx_t *ctx, uint32_t attr, + unsigned long long addr_pa, unsigned int level); + +/* + * Architecture-specific initialization code. + */ + +/* Returns the current Exception Level. The returned EL must be 1 or higher. */ +unsigned int xlat_arch_current_el(void); + +/* + * Return the maximum physical address supported by the hardware. + * This value depends on the execution state (AArch32/AArch64). + */ +unsigned long long xlat_arch_get_max_supported_pa(void); + +/* + * Returns true if the MMU of the translation regime managed by the given + * xlat_ctx_t is enabled, false otherwise. + */ +bool is_mmu_enabled_ctx(const xlat_ctx_t *ctx); + +/* + * Returns minimum virtual address space size supported by the architecture + */ +uintptr_t xlat_get_min_virt_addr_space_size(void); + +#endif /* XLAT_TABLES_PRIVATE_H */ diff --git a/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c new file mode 100644 index 0000000..38a375e --- /dev/null +++ b/arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c @@ -0,0 +1,592 @@ +/* + * Copyright (c) 2017-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include + +#include "xlat_tables_private.h" + +#if LOG_LEVEL < LOG_LEVEL_VERBOSE + +void xlat_mmap_print(__unused const mmap_region_t *mmap) +{ + /* Empty */ +} + +void xlat_tables_print(__unused xlat_ctx_t *ctx) +{ + /* Empty */ +} + +#else /* if LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +void xlat_mmap_print(const mmap_region_t *mmap) +{ + printf("mmap:\n"); + const mmap_region_t *mm = mmap; + + while (mm->size != 0U) { + printf(" VA:0x%lx PA:0x%llx size:0x%zx attr:0x%x granularity:0x%zx\n", + mm->base_va, mm->base_pa, mm->size, mm->attr, + mm->granularity); + ++mm; + }; + printf("\n"); +} + +/* Print the attributes of the specified block descriptor. */ +static void xlat_desc_print(const xlat_ctx_t *ctx, uint64_t desc) +{ + uint64_t mem_type_index = ATTR_INDEX_GET(desc); + int xlat_regime = ctx->xlat_regime; + + if (mem_type_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { + printf("MEM"); + } else if (mem_type_index == ATTR_NON_CACHEABLE_INDEX) { + printf("NC"); + } else { + assert(mem_type_index == ATTR_DEVICE_INDEX); + printf("DEV"); + } + + if ((xlat_regime == EL3_REGIME) || (xlat_regime == EL2_REGIME)) { + /* For EL3 and EL2 only check the AP[2] and XN bits. */ + printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); + printf(((desc & UPPER_ATTRS(XN)) != 0ULL) ? "-XN" : "-EXEC"); + } else { + assert(xlat_regime == EL1_EL0_REGIME); + /* + * For EL0 and EL1: + * - In AArch64 PXN and UXN can be set independently but in + * AArch32 there is no UXN (XN affects both privilege levels). + * For consistency, we set them simultaneously in both cases. + * - RO and RW permissions must be the same in EL1 and EL0. If + * EL0 can access that memory region, so can EL1, with the + * same permissions. + */ +#if ENABLE_ASSERTIONS + uint64_t xn_mask = xlat_arch_regime_get_xn_desc(EL1_EL0_REGIME); + uint64_t xn_perm = desc & xn_mask; + + assert((xn_perm == xn_mask) || (xn_perm == 0ULL)); +#endif + printf(((desc & LOWER_ATTRS(AP_RO)) != 0ULL) ? "-RO" : "-RW"); + /* Only check one of PXN and UXN, the other one is the same. */ + printf(((desc & UPPER_ATTRS(PXN)) != 0ULL) ? "-XN" : "-EXEC"); + /* + * Privileged regions can only be accessed from EL1, user + * regions can be accessed from EL1 and EL0. + */ + printf(((desc & LOWER_ATTRS(AP_ACCESS_UNPRIVILEGED)) != 0ULL) + ? "-USER" : "-PRIV"); + } + +#if ENABLE_RME + switch (desc & LOWER_ATTRS(EL3_S1_NSE | NS)) { + case 0ULL: + printf("-S"); + break; + case LOWER_ATTRS(NS): + printf("-NS"); + break; + case LOWER_ATTRS(EL3_S1_NSE): + printf("-RT"); + break; + default: /* LOWER_ATTRS(EL3_S1_NSE | NS) */ + printf("-RL"); + } +#else + printf(((LOWER_ATTRS(NS) & desc) != 0ULL) ? "-NS" : "-S"); +#endif + +#ifdef __aarch64__ + /* Check Guarded Page bit */ + if ((desc & GP) != 0ULL) { + printf("-GP"); + } +#endif +} + +static const char * const level_spacers[] = { + "[LV0] ", + " [LV1] ", + " [LV2] ", + " [LV3] " +}; + +static const char *invalid_descriptors_ommited = + "%s(%d invalid descriptors omitted)\n"; + +/* + * Recursive function that reads the translation tables passed as an argument + * and prints their status. + */ +static void xlat_tables_print_internal(xlat_ctx_t *ctx, uintptr_t table_base_va, + const uint64_t *table_base, unsigned int table_entries, + unsigned int level) +{ + assert(level <= XLAT_TABLE_LEVEL_MAX); + + uint64_t desc; + uintptr_t table_idx_va = table_base_va; + unsigned int table_idx = 0U; + size_t level_size = XLAT_BLOCK_SIZE(level); + + /* + * Keep track of how many invalid descriptors are counted in a row. + * Whenever multiple invalid descriptors are found, only the first one + * is printed, and a line is added to inform about how many descriptors + * have been omitted. + */ + int invalid_row_count = 0; + + while (table_idx < table_entries) { + + desc = table_base[table_idx]; + + if ((desc & DESC_MASK) == INVALID_DESC) { + + if (invalid_row_count == 0) { + printf("%sVA:0x%lx size:0x%zx\n", + level_spacers[level], + table_idx_va, level_size); + } + invalid_row_count++; + + } else { + + if (invalid_row_count > 1) { + printf(invalid_descriptors_ommited, + level_spacers[level], + invalid_row_count - 1); + } + invalid_row_count = 0; + + /* + * Check if this is a table or a block. Tables are only + * allowed in levels other than 3, but DESC_PAGE has the + * same value as DESC_TABLE, so we need to check. + */ + if (((desc & DESC_MASK) == TABLE_DESC) && + (level < XLAT_TABLE_LEVEL_MAX)) { + /* + * Do not print any PA for a table descriptor, + * as it doesn't directly map physical memory + * but instead points to the next translation + * table in the translation table walk. + */ + printf("%sVA:0x%lx size:0x%zx\n", + level_spacers[level], + table_idx_va, level_size); + + uintptr_t addr_inner = desc & TABLE_ADDR_MASK; + + xlat_tables_print_internal(ctx, table_idx_va, + (uint64_t *)addr_inner, + XLAT_TABLE_ENTRIES, level + 1U); + } else { + printf("%sVA:0x%lx PA:0x%" PRIx64 " size:0x%zx ", + level_spacers[level], table_idx_va, + (uint64_t)(desc & TABLE_ADDR_MASK), + level_size); + xlat_desc_print(ctx, desc); + printf("\n"); + } + } + + table_idx++; + table_idx_va += level_size; + } + + if (invalid_row_count > 1) { + printf(invalid_descriptors_ommited, + level_spacers[level], invalid_row_count - 1); + } +} + +void xlat_tables_print(xlat_ctx_t *ctx) +{ + const char *xlat_regime_str; + int used_page_tables; + + if (ctx->xlat_regime == EL1_EL0_REGIME) { + xlat_regime_str = "1&0"; + } else if (ctx->xlat_regime == EL2_REGIME) { + xlat_regime_str = "2"; + } else { + assert(ctx->xlat_regime == EL3_REGIME); + xlat_regime_str = "3"; + } + VERBOSE("Translation tables state:\n"); + VERBOSE(" Xlat regime: EL%s\n", xlat_regime_str); + VERBOSE(" Max allowed PA: 0x%llx\n", ctx->pa_max_address); + VERBOSE(" Max allowed VA: 0x%lx\n", ctx->va_max_address); + VERBOSE(" Max mapped PA: 0x%llx\n", ctx->max_pa); + VERBOSE(" Max mapped VA: 0x%lx\n", ctx->max_va); + + VERBOSE(" Initial lookup level: %u\n", ctx->base_level); + VERBOSE(" Entries @initial lookup level: %u\n", + ctx->base_table_entries); + +#if PLAT_XLAT_TABLES_DYNAMIC + used_page_tables = 0; + for (int i = 0; i < ctx->tables_num; ++i) { + if (ctx->tables_mapped_regions[i] != 0) + ++used_page_tables; + } +#else + used_page_tables = ctx->next_table; +#endif + VERBOSE(" Used %d sub-tables out of %d (spare: %d)\n", + used_page_tables, ctx->tables_num, + ctx->tables_num - used_page_tables); + + xlat_tables_print_internal(ctx, 0U, ctx->base_table, + ctx->base_table_entries, ctx->base_level); +} + +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + +/* + * Do a translation table walk to find the block or page descriptor that maps + * virtual_addr. + * + * On success, return the address of the descriptor within the translation + * table. Its lookup level is stored in '*out_level'. + * On error, return NULL. + * + * xlat_table_base + * Base address for the initial lookup level. + * xlat_table_base_entries + * Number of entries in the translation table for the initial lookup level. + * virt_addr_space_size + * Size in bytes of the virtual address space. + */ +static uint64_t *find_xlat_table_entry(uintptr_t virtual_addr, + void *xlat_table_base, + unsigned int xlat_table_base_entries, + unsigned long long virt_addr_space_size, + unsigned int *out_level) +{ + unsigned int start_level; + uint64_t *table; + unsigned int entries; + + start_level = GET_XLAT_TABLE_LEVEL_BASE(virt_addr_space_size); + + table = xlat_table_base; + entries = xlat_table_base_entries; + + for (unsigned int level = start_level; + level <= XLAT_TABLE_LEVEL_MAX; + ++level) { + uint64_t idx, desc, desc_type; + + idx = XLAT_TABLE_IDX(virtual_addr, level); + if (idx >= entries) { + WARN("Missing xlat table entry at address 0x%lx\n", + virtual_addr); + return NULL; + } + + desc = table[idx]; + desc_type = desc & DESC_MASK; + + if (desc_type == INVALID_DESC) { + VERBOSE("Invalid entry (memory not mapped)\n"); + return NULL; + } + + if (level == XLAT_TABLE_LEVEL_MAX) { + /* + * Only page descriptors allowed at the final lookup + * level. + */ + assert(desc_type == PAGE_DESC); + *out_level = level; + return &table[idx]; + } + + if (desc_type == BLOCK_DESC) { + *out_level = level; + return &table[idx]; + } + + assert(desc_type == TABLE_DESC); + table = (uint64_t *)(uintptr_t)(desc & TABLE_ADDR_MASK); + entries = XLAT_TABLE_ENTRIES; + } + + /* + * This shouldn't be reached, the translation table walk should end at + * most at level XLAT_TABLE_LEVEL_MAX and return from inside the loop. + */ + assert(false); + + return NULL; +} + + +static int xlat_get_mem_attributes_internal(const xlat_ctx_t *ctx, + uintptr_t base_va, uint32_t *attributes, uint64_t **table_entry, + unsigned long long *addr_pa, unsigned int *table_level) +{ + uint64_t *entry; + uint64_t desc; + unsigned int level; + unsigned long long virt_addr_space_size; + + /* + * Sanity-check arguments. + */ + assert(ctx != NULL); + assert(ctx->initialized); + assert((ctx->xlat_regime == EL1_EL0_REGIME) || + (ctx->xlat_regime == EL2_REGIME) || + (ctx->xlat_regime == EL3_REGIME)); + + virt_addr_space_size = (unsigned long long)ctx->va_max_address + 1ULL; + assert(virt_addr_space_size > 0U); + + entry = find_xlat_table_entry(base_va, + ctx->base_table, + ctx->base_table_entries, + virt_addr_space_size, + &level); + if (entry == NULL) { + WARN("Address 0x%lx is not mapped.\n", base_va); + return -EINVAL; + } + + if (addr_pa != NULL) { + *addr_pa = *entry & TABLE_ADDR_MASK; + } + + if (table_entry != NULL) { + *table_entry = entry; + } + + if (table_level != NULL) { + *table_level = level; + } + + desc = *entry; + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE + VERBOSE("Attributes: "); + xlat_desc_print(ctx, desc); + printf("\n"); +#endif /* LOG_LEVEL >= LOG_LEVEL_VERBOSE */ + + assert(attributes != NULL); + *attributes = 0U; + + uint64_t attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; + + if (attr_index == ATTR_IWBWA_OWBWA_NTR_INDEX) { + *attributes |= MT_MEMORY; + } else if (attr_index == ATTR_NON_CACHEABLE_INDEX) { + *attributes |= MT_NON_CACHEABLE; + } else { + assert(attr_index == ATTR_DEVICE_INDEX); + *attributes |= MT_DEVICE; + } + + uint64_t ap2_bit = (desc >> AP2_SHIFT) & 1U; + + if (ap2_bit == AP2_RW) + *attributes |= MT_RW; + + if (ctx->xlat_regime == EL1_EL0_REGIME) { + uint64_t ap1_bit = (desc >> AP1_SHIFT) & 1U; + + if (ap1_bit == AP1_ACCESS_UNPRIVILEGED) + *attributes |= MT_USER; + } + + uint64_t ns_bit = (desc >> NS_SHIFT) & 1U; + + if (ns_bit == 1U) + *attributes |= MT_NS; + + uint64_t xn_mask = xlat_arch_regime_get_xn_desc(ctx->xlat_regime); + + if ((desc & xn_mask) == xn_mask) { + *attributes |= MT_EXECUTE_NEVER; + } else { + assert((desc & xn_mask) == 0U); + } + + return 0; +} + + +int xlat_get_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + uint32_t *attr) +{ + return xlat_get_mem_attributes_internal(ctx, base_va, attr, + NULL, NULL, NULL); +} + + +int xlat_change_mem_attributes_ctx(const xlat_ctx_t *ctx, uintptr_t base_va, + size_t size, uint32_t attr) +{ + /* Note: This implementation isn't optimized. */ + + assert(ctx != NULL); + assert(ctx->initialized); + + unsigned long long virt_addr_space_size = + (unsigned long long)ctx->va_max_address + 1U; + assert(virt_addr_space_size > 0U); + + if (!IS_PAGE_ALIGNED(base_va)) { + WARN("%s: Address 0x%lx is not aligned on a page boundary.\n", + __func__, base_va); + return -EINVAL; + } + + if (size == 0U) { + WARN("%s: Size is 0.\n", __func__); + return -EINVAL; + } + + if ((size % PAGE_SIZE) != 0U) { + WARN("%s: Size 0x%zx is not a multiple of a page size.\n", + __func__, size); + return -EINVAL; + } + + if (((attr & MT_EXECUTE_NEVER) == 0U) && ((attr & MT_RW) != 0U)) { + WARN("%s: Mapping memory as read-write and executable not allowed.\n", + __func__); + return -EINVAL; + } + + size_t pages_count = size / PAGE_SIZE; + + VERBOSE("Changing memory attributes of %zu pages starting from address 0x%lx...\n", + pages_count, base_va); + + uintptr_t base_va_original = base_va; + + /* + * Sanity checks. + */ + for (unsigned int i = 0U; i < pages_count; ++i) { + const uint64_t *entry; + uint64_t desc, attr_index; + unsigned int level; + + entry = find_xlat_table_entry(base_va, + ctx->base_table, + ctx->base_table_entries, + virt_addr_space_size, + &level); + if (entry == NULL) { + WARN("Address 0x%lx is not mapped.\n", base_va); + return -EINVAL; + } + + desc = *entry; + + /* + * Check that all the required pages are mapped at page + * granularity. + */ + if (((desc & DESC_MASK) != PAGE_DESC) || + (level != XLAT_TABLE_LEVEL_MAX)) { + WARN("Address 0x%lx is not mapped at the right granularity.\n", + base_va); + WARN("Granularity is 0x%lx, should be 0x%lx.\n", + XLAT_BLOCK_SIZE(level), PAGE_SIZE); + return -EINVAL; + } + + /* + * If the region type is device, it shouldn't be executable. + */ + attr_index = (desc >> ATTR_INDEX_SHIFT) & ATTR_INDEX_MASK; + if (attr_index == ATTR_DEVICE_INDEX) { + if ((attr & MT_EXECUTE_NEVER) == 0U) { + WARN("Setting device memory as executable at address 0x%lx.", + base_va); + return -EINVAL; + } + } + + base_va += PAGE_SIZE; + } + + /* Restore original value. */ + base_va = base_va_original; + + for (unsigned int i = 0U; i < pages_count; ++i) { + + uint32_t old_attr = 0U, new_attr; + uint64_t *entry = NULL; + unsigned int level = 0U; + unsigned long long addr_pa = 0ULL; + + (void) xlat_get_mem_attributes_internal(ctx, base_va, &old_attr, + &entry, &addr_pa, &level); + + /* + * From attr, only MT_RO/MT_RW, MT_EXECUTE/MT_EXECUTE_NEVER and + * MT_USER/MT_PRIVILEGED are taken into account. Any other + * information is ignored. + */ + + /* Clean the old attributes so that they can be rebuilt. */ + new_attr = old_attr & ~(MT_RW | MT_EXECUTE_NEVER | MT_USER); + + /* + * Update attributes, but filter out the ones this function + * isn't allowed to change. + */ + new_attr |= attr & (MT_RW | MT_EXECUTE_NEVER | MT_USER); + + /* + * The break-before-make sequence requires writing an invalid + * descriptor and making sure that the system sees the change + * before writing the new descriptor. + */ + *entry = INVALID_DESC; +#if !HW_ASSISTED_COHERENCY + dccvac((uintptr_t)entry); +#endif + /* Invalidate any cached copy of this mapping in the TLBs. */ + xlat_arch_tlbi_va(base_va, ctx->xlat_regime); + + /* Ensure completion of the invalidation. */ + xlat_arch_tlbi_va_sync(); + + /* Write new descriptor */ + *entry = xlat_desc(ctx, new_attr, addr_pa, level); +#if !HW_ASSISTED_COHERENCY + dccvac((uintptr_t)entry); +#endif + base_va += PAGE_SIZE; + } + + /* Ensure that the last descriptor writen is seen by the system. */ + dsbish(); + + return 0; +} diff --git a/arm-trusted-firmware/lib/zlib/adler32.c b/arm-trusted-firmware/lib/zlib/adler32.c new file mode 100644 index 0000000..d0be438 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/adler32.c @@ -0,0 +1,186 @@ +/* adler32.c -- compute the Adler-32 checksum of a data stream + * Copyright (C) 1995-2011, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" + +local uLong adler32_combine_ OF((uLong adler1, uLong adler2, z_off64_t len2)); + +#define BASE 65521U /* largest prime smaller than 65536 */ +#define NMAX 5552 +/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */ + +#define DO1(buf,i) {adler += (buf)[i]; sum2 += adler;} +#define DO2(buf,i) DO1(buf,i); DO1(buf,i+1); +#define DO4(buf,i) DO2(buf,i); DO2(buf,i+2); +#define DO8(buf,i) DO4(buf,i); DO4(buf,i+4); +#define DO16(buf) DO8(buf,0); DO8(buf,8); + +/* use NO_DIVIDE if your processor does not do division in hardware -- + try it both ways to see which is faster */ +#ifdef NO_DIVIDE +/* note that this assumes BASE is 65521, where 65536 % 65521 == 15 + (thank you to John Reiser for pointing this out) */ +# define CHOP(a) \ + do { \ + unsigned long tmp = a >> 16; \ + a &= 0xffffUL; \ + a += (tmp << 4) - tmp; \ + } while (0) +# define MOD28(a) \ + do { \ + CHOP(a); \ + if (a >= BASE) a -= BASE; \ + } while (0) +# define MOD(a) \ + do { \ + CHOP(a); \ + MOD28(a); \ + } while (0) +# define MOD63(a) \ + do { /* this assumes a is not negative */ \ + z_off64_t tmp = a >> 32; \ + a &= 0xffffffffL; \ + a += (tmp << 8) - (tmp << 5) + tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + tmp = a >> 16; \ + a &= 0xffffL; \ + a += (tmp << 4) - tmp; \ + if (a >= BASE) a -= BASE; \ + } while (0) +#else +# define MOD(a) a %= BASE +# define MOD28(a) a %= BASE +# define MOD63(a) a %= BASE +#endif + +/* ========================================================================= */ +uLong ZEXPORT adler32_z(adler, buf, len) + uLong adler; + const Bytef *buf; + z_size_t len; +{ + unsigned long sum2; + unsigned n; + + /* split Adler-32 into component sums */ + sum2 = (adler >> 16) & 0xffff; + adler &= 0xffff; + + /* in case user likes doing a byte at a time, keep it fast */ + if (len == 1) { + adler += buf[0]; + if (adler >= BASE) + adler -= BASE; + sum2 += adler; + if (sum2 >= BASE) + sum2 -= BASE; + return adler | (sum2 << 16); + } + + /* initial Adler-32 value (deferred check for len == 1 speed) */ + if (buf == Z_NULL) + return 1L; + + /* in case short lengths are provided, keep it somewhat fast */ + if (len < 16) { + while (len--) { + adler += *buf++; + sum2 += adler; + } + if (adler >= BASE) + adler -= BASE; + MOD28(sum2); /* only added so many BASE's */ + return adler | (sum2 << 16); + } + + /* do length NMAX blocks -- requires just one modulo operation */ + while (len >= NMAX) { + len -= NMAX; + n = NMAX / 16; /* NMAX is divisible by 16 */ + do { + DO16(buf); /* 16 sums unrolled */ + buf += 16; + } while (--n); + MOD(adler); + MOD(sum2); + } + + /* do remaining bytes (less than NMAX, still just one modulo) */ + if (len) { /* avoid modulos if none remaining */ + while (len >= 16) { + len -= 16; + DO16(buf); + buf += 16; + } + while (len--) { + adler += *buf++; + sum2 += adler; + } + MOD(adler); + MOD(sum2); + } + + /* return recombined sums */ + return adler | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32(adler, buf, len) + uLong adler; + const Bytef *buf; + uInt len; +{ + return adler32_z(adler, buf, len); +} + +/* ========================================================================= */ +local uLong adler32_combine_(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + unsigned long sum1; + unsigned long sum2; + unsigned rem; + + /* for negative len, return invalid adler32 as a clue for debugging */ + if (len2 < 0) + return 0xffffffffUL; + + /* the derivation of this formula is left as an exercise for the reader */ + MOD63(len2); /* assumes len2 >= 0 */ + rem = (unsigned)len2; + sum1 = adler1 & 0xffff; + sum2 = rem * sum1; + MOD(sum2); + sum1 += (adler2 & 0xffff) + BASE - 1; + sum2 += ((adler1 >> 16) & 0xffff) + ((adler2 >> 16) & 0xffff) + BASE - rem; + if (sum1 >= BASE) sum1 -= BASE; + if (sum1 >= BASE) sum1 -= BASE; + if (sum2 >= ((unsigned long)BASE << 1)) sum2 -= ((unsigned long)BASE << 1); + if (sum2 >= BASE) sum2 -= BASE; + return sum1 | (sum2 << 16); +} + +/* ========================================================================= */ +uLong ZEXPORT adler32_combine(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} + +uLong ZEXPORT adler32_combine64(adler1, adler2, len2) + uLong adler1; + uLong adler2; + z_off64_t len2; +{ + return adler32_combine_(adler1, adler2, len2); +} diff --git a/arm-trusted-firmware/lib/zlib/crc32.c b/arm-trusted-firmware/lib/zlib/crc32.c new file mode 100644 index 0000000..9580440 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/crc32.c @@ -0,0 +1,442 @@ +/* crc32.c -- compute the CRC-32 of a data stream + * Copyright (C) 1995-2006, 2010, 2011, 2012, 2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + * + * Thanks to Rodney Brown for his contribution of faster + * CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing + * tables for updating the shift register in one step with three exclusive-ors + * instead of four steps with four exclusive-ors. This results in about a + * factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3. + */ + +/* @(#) $Id$ */ + +/* + Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore + protection on the static variables used to control the first-use generation + of the crc tables. Therefore, if you #define DYNAMIC_CRC_TABLE, you should + first call get_crc_table() to initialize the tables before allowing more than + one thread to use crc32(). + + DYNAMIC_CRC_TABLE and MAKECRCH can be #defined to write out crc32.h. + */ + +#ifdef MAKECRCH +# include +# ifndef DYNAMIC_CRC_TABLE +# define DYNAMIC_CRC_TABLE +# endif /* !DYNAMIC_CRC_TABLE */ +#endif /* MAKECRCH */ + +#include "zutil.h" /* for STDC and FAR definitions */ + +/* Definitions for doing the crc four data bytes at a time. */ +#if !defined(NOBYFOUR) && defined(Z_U4) +# define BYFOUR +#endif +#ifdef BYFOUR + local unsigned long crc32_little OF((unsigned long, + const unsigned char FAR *, z_size_t)); + local unsigned long crc32_big OF((unsigned long, + const unsigned char FAR *, z_size_t)); +# define TBLS 8 +#else +# define TBLS 1 +#endif /* BYFOUR */ + +/* Local functions for crc concatenation */ +local unsigned long gf2_matrix_times OF((unsigned long *mat, + unsigned long vec)); +local void gf2_matrix_square OF((unsigned long *square, unsigned long *mat)); +local uLong crc32_combine_ OF((uLong crc1, uLong crc2, z_off64_t len2)); + + +#ifdef DYNAMIC_CRC_TABLE + +local volatile int crc_table_empty = 1; +local z_crc_t FAR crc_table[TBLS][256]; +local void make_crc_table OF((void)); +#ifdef MAKECRCH + local void write_table OF((FILE *, const z_crc_t FAR *)); +#endif /* MAKECRCH */ +/* + Generate tables for a byte-wise 32-bit CRC calculation on the polynomial: + x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1. + + Polynomials over GF(2) are represented in binary, one bit per coefficient, + with the lowest powers in the most significant bit. Then adding polynomials + is just exclusive-or, and multiplying a polynomial by x is a right shift by + one. If we call the above polynomial p, and represent a byte as the + polynomial q, also with the lowest power in the most significant bit (so the + byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p, + where a mod b means the remainder after dividing a by b. + + This calculation is done using the shift-register method of multiplying and + taking the remainder. The register is initialized to zero, and for each + incoming bit, x^32 is added mod p to the register if the bit is a one (where + x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by + x (which is shifting right by one and adding x^32 mod p if the bit shifted + out is a one). We start with the highest power (least significant bit) of + q and repeat for all eight bits of q. + + The first table is simply the CRC of all possible eight bit values. This is + all the information needed to generate CRCs on data a byte at a time for all + combinations of CRC register values and incoming bytes. The remaining tables + allow for word-at-a-time CRC calculation for both big-endian and little- + endian machines, where a word is four bytes. +*/ +local void make_crc_table() +{ + z_crc_t c; + int n, k; + z_crc_t poly; /* polynomial exclusive-or pattern */ + /* terms of polynomial defining this crc (except x^32): */ + static volatile int first = 1; /* flag to limit concurrent making */ + static const unsigned char p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26}; + + /* See if another task is already doing this (not thread-safe, but better + than nothing -- significantly reduces duration of vulnerability in + case the advice about DYNAMIC_CRC_TABLE is ignored) */ + if (first) { + first = 0; + + /* make exclusive-or pattern from polynomial (0xedb88320UL) */ + poly = 0; + for (n = 0; n < (int)(sizeof(p)/sizeof(unsigned char)); n++) + poly |= (z_crc_t)1 << (31 - p[n]); + + /* generate a crc for every 8-bit value */ + for (n = 0; n < 256; n++) { + c = (z_crc_t)n; + for (k = 0; k < 8; k++) + c = c & 1 ? poly ^ (c >> 1) : c >> 1; + crc_table[0][n] = c; + } + +#ifdef BYFOUR + /* generate crc for each value followed by one, two, and three zeros, + and then the byte reversal of those as well as the first table */ + for (n = 0; n < 256; n++) { + c = crc_table[0][n]; + crc_table[4][n] = ZSWAP32(c); + for (k = 1; k < 4; k++) { + c = crc_table[0][c & 0xff] ^ (c >> 8); + crc_table[k][n] = c; + crc_table[k + 4][n] = ZSWAP32(c); + } + } +#endif /* BYFOUR */ + + crc_table_empty = 0; + } + else { /* not first */ + /* wait for the other guy to finish (not efficient, but rare) */ + while (crc_table_empty) + ; + } + +#ifdef MAKECRCH + /* write out CRC tables to crc32.h */ + { + FILE *out; + + out = fopen("crc32.h", "w"); + if (out == NULL) return; + fprintf(out, "/* crc32.h -- tables for rapid CRC calculation\n"); + fprintf(out, " * Generated automatically by crc32.c\n */\n\n"); + fprintf(out, "local const z_crc_t FAR "); + fprintf(out, "crc_table[TBLS][256] =\n{\n {\n"); + write_table(out, crc_table[0]); +# ifdef BYFOUR + fprintf(out, "#ifdef BYFOUR\n"); + for (k = 1; k < 8; k++) { + fprintf(out, " },\n {\n"); + write_table(out, crc_table[k]); + } + fprintf(out, "#endif\n"); +# endif /* BYFOUR */ + fprintf(out, " }\n};\n"); + fclose(out); + } +#endif /* MAKECRCH */ +} + +#ifdef MAKECRCH +local void write_table(out, table) + FILE *out; + const z_crc_t FAR *table; +{ + int n; + + for (n = 0; n < 256; n++) + fprintf(out, "%s0x%08lxUL%s", n % 5 ? "" : " ", + (unsigned long)(table[n]), + n == 255 ? "\n" : (n % 5 == 4 ? ",\n" : ", ")); +} +#endif /* MAKECRCH */ + +#else /* !DYNAMIC_CRC_TABLE */ +/* ======================================================================== + * Tables of CRC-32s of all single-byte values, made by make_crc_table(). + */ +#include "crc32.h" +#endif /* DYNAMIC_CRC_TABLE */ + +/* ========================================================================= + * This function can be used by asm versions of crc32() + */ +const z_crc_t FAR * ZEXPORT get_crc_table() +{ +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + return (const z_crc_t FAR *)crc_table; +} + +/* ========================================================================= */ +#define DO1 crc = crc_table[0][((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8) +#define DO8 DO1; DO1; DO1; DO1; DO1; DO1; DO1; DO1 + +/* ========================================================================= */ +unsigned long ZEXPORT crc32_z(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + if (buf == Z_NULL) return 0UL; + +#ifdef DYNAMIC_CRC_TABLE + if (crc_table_empty) + make_crc_table(); +#endif /* DYNAMIC_CRC_TABLE */ + +#ifdef BYFOUR + if (sizeof(void *) == sizeof(ptrdiff_t)) { + z_crc_t endian; + + endian = 1; + if (*((unsigned char *)(&endian))) + return crc32_little(crc, buf, len); + else + return crc32_big(crc, buf, len); + } +#endif /* BYFOUR */ + crc = crc ^ 0xffffffffUL; + while (len >= 8) { + DO8; + len -= 8; + } + if (len) do { + DO1; + } while (--len); + return crc ^ 0xffffffffUL; +} + +/* ========================================================================= */ +unsigned long ZEXPORT crc32(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + uInt len; +{ + return crc32_z(crc, buf, len); +} + +#ifdef BYFOUR + +/* + This BYFOUR code accesses the passed unsigned char * buffer with a 32-bit + integer pointer type. This violates the strict aliasing rule, where a + compiler can assume, for optimization purposes, that two pointers to + fundamentally different types won't ever point to the same memory. This can + manifest as a problem only if one of the pointers is written to. This code + only reads from those pointers. So long as this code remains isolated in + this compilation unit, there won't be a problem. For this reason, this code + should not be copied and pasted into a compilation unit in which other code + writes to the buffer that is passed to these routines. + */ + +/* ========================================================================= */ +#define DOLIT4 c ^= *buf4++; \ + c = crc_table[3][c & 0xff] ^ crc_table[2][(c >> 8) & 0xff] ^ \ + crc_table[1][(c >> 16) & 0xff] ^ crc_table[0][c >> 24] +#define DOLIT32 DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4; DOLIT4 + +/* ========================================================================= */ +local unsigned long crc32_little(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = (z_crc_t)crc; + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOLIT32; + len -= 32; + } + while (len >= 4) { + DOLIT4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[0][(c ^ *buf++) & 0xff] ^ (c >> 8); + } while (--len); + c = ~c; + return (unsigned long)c; +} + +/* ========================================================================= */ +#define DOBIG4 c ^= *buf4++; \ + c = crc_table[4][c & 0xff] ^ crc_table[5][(c >> 8) & 0xff] ^ \ + crc_table[6][(c >> 16) & 0xff] ^ crc_table[7][c >> 24] +#define DOBIG32 DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4; DOBIG4 + +/* ========================================================================= */ +local unsigned long crc32_big(crc, buf, len) + unsigned long crc; + const unsigned char FAR *buf; + z_size_t len; +{ + register z_crc_t c; + register const z_crc_t FAR *buf4; + + c = ZSWAP32((z_crc_t)crc); + c = ~c; + while (len && ((ptrdiff_t)buf & 3)) { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + len--; + } + + buf4 = (const z_crc_t FAR *)(const void FAR *)buf; + while (len >= 32) { + DOBIG32; + len -= 32; + } + while (len >= 4) { + DOBIG4; + len -= 4; + } + buf = (const unsigned char FAR *)buf4; + + if (len) do { + c = crc_table[4][(c >> 24) ^ *buf++] ^ (c << 8); + } while (--len); + c = ~c; + return (unsigned long)(ZSWAP32(c)); +} + +#endif /* BYFOUR */ + +#define GF2_DIM 32 /* dimension of GF(2) vectors (length of CRC) */ + +/* ========================================================================= */ +local unsigned long gf2_matrix_times(mat, vec) + unsigned long *mat; + unsigned long vec; +{ + unsigned long sum; + + sum = 0; + while (vec) { + if (vec & 1) + sum ^= *mat; + vec >>= 1; + mat++; + } + return sum; +} + +/* ========================================================================= */ +local void gf2_matrix_square(square, mat) + unsigned long *square; + unsigned long *mat; +{ + int n; + + for (n = 0; n < GF2_DIM; n++) + square[n] = gf2_matrix_times(mat, mat[n]); +} + +/* ========================================================================= */ +local uLong crc32_combine_(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + int n; + unsigned long row; + unsigned long even[GF2_DIM]; /* even-power-of-two zeros operator */ + unsigned long odd[GF2_DIM]; /* odd-power-of-two zeros operator */ + + /* degenerate case (also disallow negative lengths) */ + if (len2 <= 0) + return crc1; + + /* put operator for one zero bit in odd */ + odd[0] = 0xedb88320UL; /* CRC-32 polynomial */ + row = 1; + for (n = 1; n < GF2_DIM; n++) { + odd[n] = row; + row <<= 1; + } + + /* put operator for two zero bits in even */ + gf2_matrix_square(even, odd); + + /* put operator for four zero bits in odd */ + gf2_matrix_square(odd, even); + + /* apply len2 zeros to crc1 (first square will put the operator for one + zero byte, eight zero bits, in even) */ + do { + /* apply zeros operator for this bit of len2 */ + gf2_matrix_square(even, odd); + if (len2 & 1) + crc1 = gf2_matrix_times(even, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + if (len2 == 0) + break; + + /* another iteration of the loop with odd and even swapped */ + gf2_matrix_square(odd, even); + if (len2 & 1) + crc1 = gf2_matrix_times(odd, crc1); + len2 >>= 1; + + /* if no more bits set, then done */ + } while (len2 != 0); + + /* return combined crc */ + crc1 ^= crc2; + return crc1; +} + +/* ========================================================================= */ +uLong ZEXPORT crc32_combine(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} + +uLong ZEXPORT crc32_combine64(crc1, crc2, len2) + uLong crc1; + uLong crc2; + z_off64_t len2; +{ + return crc32_combine_(crc1, crc2, len2); +} diff --git a/arm-trusted-firmware/lib/zlib/crc32.h b/arm-trusted-firmware/lib/zlib/crc32.h new file mode 100644 index 0000000..9e0c778 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/crc32.h @@ -0,0 +1,441 @@ +/* crc32.h -- tables for rapid CRC calculation + * Generated automatically by crc32.c + */ + +local const z_crc_t FAR crc_table[TBLS][256] = +{ + { + 0x00000000UL, 0x77073096UL, 0xee0e612cUL, 0x990951baUL, 0x076dc419UL, + 0x706af48fUL, 0xe963a535UL, 0x9e6495a3UL, 0x0edb8832UL, 0x79dcb8a4UL, + 0xe0d5e91eUL, 0x97d2d988UL, 0x09b64c2bUL, 0x7eb17cbdUL, 0xe7b82d07UL, + 0x90bf1d91UL, 0x1db71064UL, 0x6ab020f2UL, 0xf3b97148UL, 0x84be41deUL, + 0x1adad47dUL, 0x6ddde4ebUL, 0xf4d4b551UL, 0x83d385c7UL, 0x136c9856UL, + 0x646ba8c0UL, 0xfd62f97aUL, 0x8a65c9ecUL, 0x14015c4fUL, 0x63066cd9UL, + 0xfa0f3d63UL, 0x8d080df5UL, 0x3b6e20c8UL, 0x4c69105eUL, 0xd56041e4UL, + 0xa2677172UL, 0x3c03e4d1UL, 0x4b04d447UL, 0xd20d85fdUL, 0xa50ab56bUL, + 0x35b5a8faUL, 0x42b2986cUL, 0xdbbbc9d6UL, 0xacbcf940UL, 0x32d86ce3UL, + 0x45df5c75UL, 0xdcd60dcfUL, 0xabd13d59UL, 0x26d930acUL, 0x51de003aUL, + 0xc8d75180UL, 0xbfd06116UL, 0x21b4f4b5UL, 0x56b3c423UL, 0xcfba9599UL, + 0xb8bda50fUL, 0x2802b89eUL, 0x5f058808UL, 0xc60cd9b2UL, 0xb10be924UL, + 0x2f6f7c87UL, 0x58684c11UL, 0xc1611dabUL, 0xb6662d3dUL, 0x76dc4190UL, + 0x01db7106UL, 0x98d220bcUL, 0xefd5102aUL, 0x71b18589UL, 0x06b6b51fUL, + 0x9fbfe4a5UL, 0xe8b8d433UL, 0x7807c9a2UL, 0x0f00f934UL, 0x9609a88eUL, + 0xe10e9818UL, 0x7f6a0dbbUL, 0x086d3d2dUL, 0x91646c97UL, 0xe6635c01UL, + 0x6b6b51f4UL, 0x1c6c6162UL, 0x856530d8UL, 0xf262004eUL, 0x6c0695edUL, + 0x1b01a57bUL, 0x8208f4c1UL, 0xf50fc457UL, 0x65b0d9c6UL, 0x12b7e950UL, + 0x8bbeb8eaUL, 0xfcb9887cUL, 0x62dd1ddfUL, 0x15da2d49UL, 0x8cd37cf3UL, + 0xfbd44c65UL, 0x4db26158UL, 0x3ab551ceUL, 0xa3bc0074UL, 0xd4bb30e2UL, + 0x4adfa541UL, 0x3dd895d7UL, 0xa4d1c46dUL, 0xd3d6f4fbUL, 0x4369e96aUL, + 0x346ed9fcUL, 0xad678846UL, 0xda60b8d0UL, 0x44042d73UL, 0x33031de5UL, + 0xaa0a4c5fUL, 0xdd0d7cc9UL, 0x5005713cUL, 0x270241aaUL, 0xbe0b1010UL, + 0xc90c2086UL, 0x5768b525UL, 0x206f85b3UL, 0xb966d409UL, 0xce61e49fUL, + 0x5edef90eUL, 0x29d9c998UL, 0xb0d09822UL, 0xc7d7a8b4UL, 0x59b33d17UL, + 0x2eb40d81UL, 0xb7bd5c3bUL, 0xc0ba6cadUL, 0xedb88320UL, 0x9abfb3b6UL, + 0x03b6e20cUL, 0x74b1d29aUL, 0xead54739UL, 0x9dd277afUL, 0x04db2615UL, + 0x73dc1683UL, 0xe3630b12UL, 0x94643b84UL, 0x0d6d6a3eUL, 0x7a6a5aa8UL, + 0xe40ecf0bUL, 0x9309ff9dUL, 0x0a00ae27UL, 0x7d079eb1UL, 0xf00f9344UL, + 0x8708a3d2UL, 0x1e01f268UL, 0x6906c2feUL, 0xf762575dUL, 0x806567cbUL, + 0x196c3671UL, 0x6e6b06e7UL, 0xfed41b76UL, 0x89d32be0UL, 0x10da7a5aUL, + 0x67dd4accUL, 0xf9b9df6fUL, 0x8ebeeff9UL, 0x17b7be43UL, 0x60b08ed5UL, + 0xd6d6a3e8UL, 0xa1d1937eUL, 0x38d8c2c4UL, 0x4fdff252UL, 0xd1bb67f1UL, + 0xa6bc5767UL, 0x3fb506ddUL, 0x48b2364bUL, 0xd80d2bdaUL, 0xaf0a1b4cUL, + 0x36034af6UL, 0x41047a60UL, 0xdf60efc3UL, 0xa867df55UL, 0x316e8eefUL, + 0x4669be79UL, 0xcb61b38cUL, 0xbc66831aUL, 0x256fd2a0UL, 0x5268e236UL, + 0xcc0c7795UL, 0xbb0b4703UL, 0x220216b9UL, 0x5505262fUL, 0xc5ba3bbeUL, + 0xb2bd0b28UL, 0x2bb45a92UL, 0x5cb36a04UL, 0xc2d7ffa7UL, 0xb5d0cf31UL, + 0x2cd99e8bUL, 0x5bdeae1dUL, 0x9b64c2b0UL, 0xec63f226UL, 0x756aa39cUL, + 0x026d930aUL, 0x9c0906a9UL, 0xeb0e363fUL, 0x72076785UL, 0x05005713UL, + 0x95bf4a82UL, 0xe2b87a14UL, 0x7bb12baeUL, 0x0cb61b38UL, 0x92d28e9bUL, + 0xe5d5be0dUL, 0x7cdcefb7UL, 0x0bdbdf21UL, 0x86d3d2d4UL, 0xf1d4e242UL, + 0x68ddb3f8UL, 0x1fda836eUL, 0x81be16cdUL, 0xf6b9265bUL, 0x6fb077e1UL, + 0x18b74777UL, 0x88085ae6UL, 0xff0f6a70UL, 0x66063bcaUL, 0x11010b5cUL, + 0x8f659effUL, 0xf862ae69UL, 0x616bffd3UL, 0x166ccf45UL, 0xa00ae278UL, + 0xd70dd2eeUL, 0x4e048354UL, 0x3903b3c2UL, 0xa7672661UL, 0xd06016f7UL, + 0x4969474dUL, 0x3e6e77dbUL, 0xaed16a4aUL, 0xd9d65adcUL, 0x40df0b66UL, + 0x37d83bf0UL, 0xa9bcae53UL, 0xdebb9ec5UL, 0x47b2cf7fUL, 0x30b5ffe9UL, + 0xbdbdf21cUL, 0xcabac28aUL, 0x53b39330UL, 0x24b4a3a6UL, 0xbad03605UL, + 0xcdd70693UL, 0x54de5729UL, 0x23d967bfUL, 0xb3667a2eUL, 0xc4614ab8UL, + 0x5d681b02UL, 0x2a6f2b94UL, 0xb40bbe37UL, 0xc30c8ea1UL, 0x5a05df1bUL, + 0x2d02ef8dUL +#ifdef BYFOUR + }, + { + 0x00000000UL, 0x191b3141UL, 0x32366282UL, 0x2b2d53c3UL, 0x646cc504UL, + 0x7d77f445UL, 0x565aa786UL, 0x4f4196c7UL, 0xc8d98a08UL, 0xd1c2bb49UL, + 0xfaefe88aUL, 0xe3f4d9cbUL, 0xacb54f0cUL, 0xb5ae7e4dUL, 0x9e832d8eUL, + 0x87981ccfUL, 0x4ac21251UL, 0x53d92310UL, 0x78f470d3UL, 0x61ef4192UL, + 0x2eaed755UL, 0x37b5e614UL, 0x1c98b5d7UL, 0x05838496UL, 0x821b9859UL, + 0x9b00a918UL, 0xb02dfadbUL, 0xa936cb9aUL, 0xe6775d5dUL, 0xff6c6c1cUL, + 0xd4413fdfUL, 0xcd5a0e9eUL, 0x958424a2UL, 0x8c9f15e3UL, 0xa7b24620UL, + 0xbea97761UL, 0xf1e8e1a6UL, 0xe8f3d0e7UL, 0xc3de8324UL, 0xdac5b265UL, + 0x5d5daeaaUL, 0x44469febUL, 0x6f6bcc28UL, 0x7670fd69UL, 0x39316baeUL, + 0x202a5aefUL, 0x0b07092cUL, 0x121c386dUL, 0xdf4636f3UL, 0xc65d07b2UL, + 0xed705471UL, 0xf46b6530UL, 0xbb2af3f7UL, 0xa231c2b6UL, 0x891c9175UL, + 0x9007a034UL, 0x179fbcfbUL, 0x0e848dbaUL, 0x25a9de79UL, 0x3cb2ef38UL, + 0x73f379ffUL, 0x6ae848beUL, 0x41c51b7dUL, 0x58de2a3cUL, 0xf0794f05UL, + 0xe9627e44UL, 0xc24f2d87UL, 0xdb541cc6UL, 0x94158a01UL, 0x8d0ebb40UL, + 0xa623e883UL, 0xbf38d9c2UL, 0x38a0c50dUL, 0x21bbf44cUL, 0x0a96a78fUL, + 0x138d96ceUL, 0x5ccc0009UL, 0x45d73148UL, 0x6efa628bUL, 0x77e153caUL, + 0xbabb5d54UL, 0xa3a06c15UL, 0x888d3fd6UL, 0x91960e97UL, 0xded79850UL, + 0xc7cca911UL, 0xece1fad2UL, 0xf5facb93UL, 0x7262d75cUL, 0x6b79e61dUL, + 0x4054b5deUL, 0x594f849fUL, 0x160e1258UL, 0x0f152319UL, 0x243870daUL, + 0x3d23419bUL, 0x65fd6ba7UL, 0x7ce65ae6UL, 0x57cb0925UL, 0x4ed03864UL, + 0x0191aea3UL, 0x188a9fe2UL, 0x33a7cc21UL, 0x2abcfd60UL, 0xad24e1afUL, + 0xb43fd0eeUL, 0x9f12832dUL, 0x8609b26cUL, 0xc94824abUL, 0xd05315eaUL, + 0xfb7e4629UL, 0xe2657768UL, 0x2f3f79f6UL, 0x362448b7UL, 0x1d091b74UL, + 0x04122a35UL, 0x4b53bcf2UL, 0x52488db3UL, 0x7965de70UL, 0x607eef31UL, + 0xe7e6f3feUL, 0xfefdc2bfUL, 0xd5d0917cUL, 0xcccba03dUL, 0x838a36faUL, + 0x9a9107bbUL, 0xb1bc5478UL, 0xa8a76539UL, 0x3b83984bUL, 0x2298a90aUL, + 0x09b5fac9UL, 0x10aecb88UL, 0x5fef5d4fUL, 0x46f46c0eUL, 0x6dd93fcdUL, + 0x74c20e8cUL, 0xf35a1243UL, 0xea412302UL, 0xc16c70c1UL, 0xd8774180UL, + 0x9736d747UL, 0x8e2de606UL, 0xa500b5c5UL, 0xbc1b8484UL, 0x71418a1aUL, + 0x685abb5bUL, 0x4377e898UL, 0x5a6cd9d9UL, 0x152d4f1eUL, 0x0c367e5fUL, + 0x271b2d9cUL, 0x3e001cddUL, 0xb9980012UL, 0xa0833153UL, 0x8bae6290UL, + 0x92b553d1UL, 0xddf4c516UL, 0xc4eff457UL, 0xefc2a794UL, 0xf6d996d5UL, + 0xae07bce9UL, 0xb71c8da8UL, 0x9c31de6bUL, 0x852aef2aUL, 0xca6b79edUL, + 0xd37048acUL, 0xf85d1b6fUL, 0xe1462a2eUL, 0x66de36e1UL, 0x7fc507a0UL, + 0x54e85463UL, 0x4df36522UL, 0x02b2f3e5UL, 0x1ba9c2a4UL, 0x30849167UL, + 0x299fa026UL, 0xe4c5aeb8UL, 0xfdde9ff9UL, 0xd6f3cc3aUL, 0xcfe8fd7bUL, + 0x80a96bbcUL, 0x99b25afdUL, 0xb29f093eUL, 0xab84387fUL, 0x2c1c24b0UL, + 0x350715f1UL, 0x1e2a4632UL, 0x07317773UL, 0x4870e1b4UL, 0x516bd0f5UL, + 0x7a468336UL, 0x635db277UL, 0xcbfad74eUL, 0xd2e1e60fUL, 0xf9ccb5ccUL, + 0xe0d7848dUL, 0xaf96124aUL, 0xb68d230bUL, 0x9da070c8UL, 0x84bb4189UL, + 0x03235d46UL, 0x1a386c07UL, 0x31153fc4UL, 0x280e0e85UL, 0x674f9842UL, + 0x7e54a903UL, 0x5579fac0UL, 0x4c62cb81UL, 0x8138c51fUL, 0x9823f45eUL, + 0xb30ea79dUL, 0xaa1596dcUL, 0xe554001bUL, 0xfc4f315aUL, 0xd7626299UL, + 0xce7953d8UL, 0x49e14f17UL, 0x50fa7e56UL, 0x7bd72d95UL, 0x62cc1cd4UL, + 0x2d8d8a13UL, 0x3496bb52UL, 0x1fbbe891UL, 0x06a0d9d0UL, 0x5e7ef3ecUL, + 0x4765c2adUL, 0x6c48916eUL, 0x7553a02fUL, 0x3a1236e8UL, 0x230907a9UL, + 0x0824546aUL, 0x113f652bUL, 0x96a779e4UL, 0x8fbc48a5UL, 0xa4911b66UL, + 0xbd8a2a27UL, 0xf2cbbce0UL, 0xebd08da1UL, 0xc0fdde62UL, 0xd9e6ef23UL, + 0x14bce1bdUL, 0x0da7d0fcUL, 0x268a833fUL, 0x3f91b27eUL, 0x70d024b9UL, + 0x69cb15f8UL, 0x42e6463bUL, 0x5bfd777aUL, 0xdc656bb5UL, 0xc57e5af4UL, + 0xee530937UL, 0xf7483876UL, 0xb809aeb1UL, 0xa1129ff0UL, 0x8a3fcc33UL, + 0x9324fd72UL + }, + { + 0x00000000UL, 0x01c26a37UL, 0x0384d46eUL, 0x0246be59UL, 0x0709a8dcUL, + 0x06cbc2ebUL, 0x048d7cb2UL, 0x054f1685UL, 0x0e1351b8UL, 0x0fd13b8fUL, + 0x0d9785d6UL, 0x0c55efe1UL, 0x091af964UL, 0x08d89353UL, 0x0a9e2d0aUL, + 0x0b5c473dUL, 0x1c26a370UL, 0x1de4c947UL, 0x1fa2771eUL, 0x1e601d29UL, + 0x1b2f0bacUL, 0x1aed619bUL, 0x18abdfc2UL, 0x1969b5f5UL, 0x1235f2c8UL, + 0x13f798ffUL, 0x11b126a6UL, 0x10734c91UL, 0x153c5a14UL, 0x14fe3023UL, + 0x16b88e7aUL, 0x177ae44dUL, 0x384d46e0UL, 0x398f2cd7UL, 0x3bc9928eUL, + 0x3a0bf8b9UL, 0x3f44ee3cUL, 0x3e86840bUL, 0x3cc03a52UL, 0x3d025065UL, + 0x365e1758UL, 0x379c7d6fUL, 0x35dac336UL, 0x3418a901UL, 0x3157bf84UL, + 0x3095d5b3UL, 0x32d36beaUL, 0x331101ddUL, 0x246be590UL, 0x25a98fa7UL, + 0x27ef31feUL, 0x262d5bc9UL, 0x23624d4cUL, 0x22a0277bUL, 0x20e69922UL, + 0x2124f315UL, 0x2a78b428UL, 0x2bbade1fUL, 0x29fc6046UL, 0x283e0a71UL, + 0x2d711cf4UL, 0x2cb376c3UL, 0x2ef5c89aUL, 0x2f37a2adUL, 0x709a8dc0UL, + 0x7158e7f7UL, 0x731e59aeUL, 0x72dc3399UL, 0x7793251cUL, 0x76514f2bUL, + 0x7417f172UL, 0x75d59b45UL, 0x7e89dc78UL, 0x7f4bb64fUL, 0x7d0d0816UL, + 0x7ccf6221UL, 0x798074a4UL, 0x78421e93UL, 0x7a04a0caUL, 0x7bc6cafdUL, + 0x6cbc2eb0UL, 0x6d7e4487UL, 0x6f38fadeUL, 0x6efa90e9UL, 0x6bb5866cUL, + 0x6a77ec5bUL, 0x68315202UL, 0x69f33835UL, 0x62af7f08UL, 0x636d153fUL, + 0x612bab66UL, 0x60e9c151UL, 0x65a6d7d4UL, 0x6464bde3UL, 0x662203baUL, + 0x67e0698dUL, 0x48d7cb20UL, 0x4915a117UL, 0x4b531f4eUL, 0x4a917579UL, + 0x4fde63fcUL, 0x4e1c09cbUL, 0x4c5ab792UL, 0x4d98dda5UL, 0x46c49a98UL, + 0x4706f0afUL, 0x45404ef6UL, 0x448224c1UL, 0x41cd3244UL, 0x400f5873UL, + 0x4249e62aUL, 0x438b8c1dUL, 0x54f16850UL, 0x55330267UL, 0x5775bc3eUL, + 0x56b7d609UL, 0x53f8c08cUL, 0x523aaabbUL, 0x507c14e2UL, 0x51be7ed5UL, + 0x5ae239e8UL, 0x5b2053dfUL, 0x5966ed86UL, 0x58a487b1UL, 0x5deb9134UL, + 0x5c29fb03UL, 0x5e6f455aUL, 0x5fad2f6dUL, 0xe1351b80UL, 0xe0f771b7UL, + 0xe2b1cfeeUL, 0xe373a5d9UL, 0xe63cb35cUL, 0xe7fed96bUL, 0xe5b86732UL, + 0xe47a0d05UL, 0xef264a38UL, 0xeee4200fUL, 0xeca29e56UL, 0xed60f461UL, + 0xe82fe2e4UL, 0xe9ed88d3UL, 0xebab368aUL, 0xea695cbdUL, 0xfd13b8f0UL, + 0xfcd1d2c7UL, 0xfe976c9eUL, 0xff5506a9UL, 0xfa1a102cUL, 0xfbd87a1bUL, + 0xf99ec442UL, 0xf85cae75UL, 0xf300e948UL, 0xf2c2837fUL, 0xf0843d26UL, + 0xf1465711UL, 0xf4094194UL, 0xf5cb2ba3UL, 0xf78d95faUL, 0xf64fffcdUL, + 0xd9785d60UL, 0xd8ba3757UL, 0xdafc890eUL, 0xdb3ee339UL, 0xde71f5bcUL, + 0xdfb39f8bUL, 0xddf521d2UL, 0xdc374be5UL, 0xd76b0cd8UL, 0xd6a966efUL, + 0xd4efd8b6UL, 0xd52db281UL, 0xd062a404UL, 0xd1a0ce33UL, 0xd3e6706aUL, + 0xd2241a5dUL, 0xc55efe10UL, 0xc49c9427UL, 0xc6da2a7eUL, 0xc7184049UL, + 0xc25756ccUL, 0xc3953cfbUL, 0xc1d382a2UL, 0xc011e895UL, 0xcb4dafa8UL, + 0xca8fc59fUL, 0xc8c97bc6UL, 0xc90b11f1UL, 0xcc440774UL, 0xcd866d43UL, + 0xcfc0d31aUL, 0xce02b92dUL, 0x91af9640UL, 0x906dfc77UL, 0x922b422eUL, + 0x93e92819UL, 0x96a63e9cUL, 0x976454abUL, 0x9522eaf2UL, 0x94e080c5UL, + 0x9fbcc7f8UL, 0x9e7eadcfUL, 0x9c381396UL, 0x9dfa79a1UL, 0x98b56f24UL, + 0x99770513UL, 0x9b31bb4aUL, 0x9af3d17dUL, 0x8d893530UL, 0x8c4b5f07UL, + 0x8e0de15eUL, 0x8fcf8b69UL, 0x8a809decUL, 0x8b42f7dbUL, 0x89044982UL, + 0x88c623b5UL, 0x839a6488UL, 0x82580ebfUL, 0x801eb0e6UL, 0x81dcdad1UL, + 0x8493cc54UL, 0x8551a663UL, 0x8717183aUL, 0x86d5720dUL, 0xa9e2d0a0UL, + 0xa820ba97UL, 0xaa6604ceUL, 0xaba46ef9UL, 0xaeeb787cUL, 0xaf29124bUL, + 0xad6fac12UL, 0xacadc625UL, 0xa7f18118UL, 0xa633eb2fUL, 0xa4755576UL, + 0xa5b73f41UL, 0xa0f829c4UL, 0xa13a43f3UL, 0xa37cfdaaUL, 0xa2be979dUL, + 0xb5c473d0UL, 0xb40619e7UL, 0xb640a7beUL, 0xb782cd89UL, 0xb2cddb0cUL, + 0xb30fb13bUL, 0xb1490f62UL, 0xb08b6555UL, 0xbbd72268UL, 0xba15485fUL, + 0xb853f606UL, 0xb9919c31UL, 0xbcde8ab4UL, 0xbd1ce083UL, 0xbf5a5edaUL, + 0xbe9834edUL + }, + { + 0x00000000UL, 0xb8bc6765UL, 0xaa09c88bUL, 0x12b5afeeUL, 0x8f629757UL, + 0x37def032UL, 0x256b5fdcUL, 0x9dd738b9UL, 0xc5b428efUL, 0x7d084f8aUL, + 0x6fbde064UL, 0xd7018701UL, 0x4ad6bfb8UL, 0xf26ad8ddUL, 0xe0df7733UL, + 0x58631056UL, 0x5019579fUL, 0xe8a530faUL, 0xfa109f14UL, 0x42acf871UL, + 0xdf7bc0c8UL, 0x67c7a7adUL, 0x75720843UL, 0xcdce6f26UL, 0x95ad7f70UL, + 0x2d111815UL, 0x3fa4b7fbUL, 0x8718d09eUL, 0x1acfe827UL, 0xa2738f42UL, + 0xb0c620acUL, 0x087a47c9UL, 0xa032af3eUL, 0x188ec85bUL, 0x0a3b67b5UL, + 0xb28700d0UL, 0x2f503869UL, 0x97ec5f0cUL, 0x8559f0e2UL, 0x3de59787UL, + 0x658687d1UL, 0xdd3ae0b4UL, 0xcf8f4f5aUL, 0x7733283fUL, 0xeae41086UL, + 0x525877e3UL, 0x40edd80dUL, 0xf851bf68UL, 0xf02bf8a1UL, 0x48979fc4UL, + 0x5a22302aUL, 0xe29e574fUL, 0x7f496ff6UL, 0xc7f50893UL, 0xd540a77dUL, + 0x6dfcc018UL, 0x359fd04eUL, 0x8d23b72bUL, 0x9f9618c5UL, 0x272a7fa0UL, + 0xbafd4719UL, 0x0241207cUL, 0x10f48f92UL, 0xa848e8f7UL, 0x9b14583dUL, + 0x23a83f58UL, 0x311d90b6UL, 0x89a1f7d3UL, 0x1476cf6aUL, 0xaccaa80fUL, + 0xbe7f07e1UL, 0x06c36084UL, 0x5ea070d2UL, 0xe61c17b7UL, 0xf4a9b859UL, + 0x4c15df3cUL, 0xd1c2e785UL, 0x697e80e0UL, 0x7bcb2f0eUL, 0xc377486bUL, + 0xcb0d0fa2UL, 0x73b168c7UL, 0x6104c729UL, 0xd9b8a04cUL, 0x446f98f5UL, + 0xfcd3ff90UL, 0xee66507eUL, 0x56da371bUL, 0x0eb9274dUL, 0xb6054028UL, + 0xa4b0efc6UL, 0x1c0c88a3UL, 0x81dbb01aUL, 0x3967d77fUL, 0x2bd27891UL, + 0x936e1ff4UL, 0x3b26f703UL, 0x839a9066UL, 0x912f3f88UL, 0x299358edUL, + 0xb4446054UL, 0x0cf80731UL, 0x1e4da8dfUL, 0xa6f1cfbaUL, 0xfe92dfecUL, + 0x462eb889UL, 0x549b1767UL, 0xec277002UL, 0x71f048bbUL, 0xc94c2fdeUL, + 0xdbf98030UL, 0x6345e755UL, 0x6b3fa09cUL, 0xd383c7f9UL, 0xc1366817UL, + 0x798a0f72UL, 0xe45d37cbUL, 0x5ce150aeUL, 0x4e54ff40UL, 0xf6e89825UL, + 0xae8b8873UL, 0x1637ef16UL, 0x048240f8UL, 0xbc3e279dUL, 0x21e91f24UL, + 0x99557841UL, 0x8be0d7afUL, 0x335cb0caUL, 0xed59b63bUL, 0x55e5d15eUL, + 0x47507eb0UL, 0xffec19d5UL, 0x623b216cUL, 0xda874609UL, 0xc832e9e7UL, + 0x708e8e82UL, 0x28ed9ed4UL, 0x9051f9b1UL, 0x82e4565fUL, 0x3a58313aUL, + 0xa78f0983UL, 0x1f336ee6UL, 0x0d86c108UL, 0xb53aa66dUL, 0xbd40e1a4UL, + 0x05fc86c1UL, 0x1749292fUL, 0xaff54e4aUL, 0x322276f3UL, 0x8a9e1196UL, + 0x982bbe78UL, 0x2097d91dUL, 0x78f4c94bUL, 0xc048ae2eUL, 0xd2fd01c0UL, + 0x6a4166a5UL, 0xf7965e1cUL, 0x4f2a3979UL, 0x5d9f9697UL, 0xe523f1f2UL, + 0x4d6b1905UL, 0xf5d77e60UL, 0xe762d18eUL, 0x5fdeb6ebUL, 0xc2098e52UL, + 0x7ab5e937UL, 0x680046d9UL, 0xd0bc21bcUL, 0x88df31eaUL, 0x3063568fUL, + 0x22d6f961UL, 0x9a6a9e04UL, 0x07bda6bdUL, 0xbf01c1d8UL, 0xadb46e36UL, + 0x15080953UL, 0x1d724e9aUL, 0xa5ce29ffUL, 0xb77b8611UL, 0x0fc7e174UL, + 0x9210d9cdUL, 0x2aacbea8UL, 0x38191146UL, 0x80a57623UL, 0xd8c66675UL, + 0x607a0110UL, 0x72cfaefeUL, 0xca73c99bUL, 0x57a4f122UL, 0xef189647UL, + 0xfdad39a9UL, 0x45115eccUL, 0x764dee06UL, 0xcef18963UL, 0xdc44268dUL, + 0x64f841e8UL, 0xf92f7951UL, 0x41931e34UL, 0x5326b1daUL, 0xeb9ad6bfUL, + 0xb3f9c6e9UL, 0x0b45a18cUL, 0x19f00e62UL, 0xa14c6907UL, 0x3c9b51beUL, + 0x842736dbUL, 0x96929935UL, 0x2e2efe50UL, 0x2654b999UL, 0x9ee8defcUL, + 0x8c5d7112UL, 0x34e11677UL, 0xa9362eceUL, 0x118a49abUL, 0x033fe645UL, + 0xbb838120UL, 0xe3e09176UL, 0x5b5cf613UL, 0x49e959fdUL, 0xf1553e98UL, + 0x6c820621UL, 0xd43e6144UL, 0xc68bceaaUL, 0x7e37a9cfUL, 0xd67f4138UL, + 0x6ec3265dUL, 0x7c7689b3UL, 0xc4caeed6UL, 0x591dd66fUL, 0xe1a1b10aUL, + 0xf3141ee4UL, 0x4ba87981UL, 0x13cb69d7UL, 0xab770eb2UL, 0xb9c2a15cUL, + 0x017ec639UL, 0x9ca9fe80UL, 0x241599e5UL, 0x36a0360bUL, 0x8e1c516eUL, + 0x866616a7UL, 0x3eda71c2UL, 0x2c6fde2cUL, 0x94d3b949UL, 0x090481f0UL, + 0xb1b8e695UL, 0xa30d497bUL, 0x1bb12e1eUL, 0x43d23e48UL, 0xfb6e592dUL, + 0xe9dbf6c3UL, 0x516791a6UL, 0xccb0a91fUL, 0x740cce7aUL, 0x66b96194UL, + 0xde0506f1UL + }, + { + 0x00000000UL, 0x96300777UL, 0x2c610eeeUL, 0xba510999UL, 0x19c46d07UL, + 0x8ff46a70UL, 0x35a563e9UL, 0xa395649eUL, 0x3288db0eUL, 0xa4b8dc79UL, + 0x1ee9d5e0UL, 0x88d9d297UL, 0x2b4cb609UL, 0xbd7cb17eUL, 0x072db8e7UL, + 0x911dbf90UL, 0x6410b71dUL, 0xf220b06aUL, 0x4871b9f3UL, 0xde41be84UL, + 0x7dd4da1aUL, 0xebe4dd6dUL, 0x51b5d4f4UL, 0xc785d383UL, 0x56986c13UL, + 0xc0a86b64UL, 0x7af962fdUL, 0xecc9658aUL, 0x4f5c0114UL, 0xd96c0663UL, + 0x633d0ffaUL, 0xf50d088dUL, 0xc8206e3bUL, 0x5e10694cUL, 0xe44160d5UL, + 0x727167a2UL, 0xd1e4033cUL, 0x47d4044bUL, 0xfd850dd2UL, 0x6bb50aa5UL, + 0xfaa8b535UL, 0x6c98b242UL, 0xd6c9bbdbUL, 0x40f9bcacUL, 0xe36cd832UL, + 0x755cdf45UL, 0xcf0dd6dcUL, 0x593dd1abUL, 0xac30d926UL, 0x3a00de51UL, + 0x8051d7c8UL, 0x1661d0bfUL, 0xb5f4b421UL, 0x23c4b356UL, 0x9995bacfUL, + 0x0fa5bdb8UL, 0x9eb80228UL, 0x0888055fUL, 0xb2d90cc6UL, 0x24e90bb1UL, + 0x877c6f2fUL, 0x114c6858UL, 0xab1d61c1UL, 0x3d2d66b6UL, 0x9041dc76UL, + 0x0671db01UL, 0xbc20d298UL, 0x2a10d5efUL, 0x8985b171UL, 0x1fb5b606UL, + 0xa5e4bf9fUL, 0x33d4b8e8UL, 0xa2c90778UL, 0x34f9000fUL, 0x8ea80996UL, + 0x18980ee1UL, 0xbb0d6a7fUL, 0x2d3d6d08UL, 0x976c6491UL, 0x015c63e6UL, + 0xf4516b6bUL, 0x62616c1cUL, 0xd8306585UL, 0x4e0062f2UL, 0xed95066cUL, + 0x7ba5011bUL, 0xc1f40882UL, 0x57c40ff5UL, 0xc6d9b065UL, 0x50e9b712UL, + 0xeab8be8bUL, 0x7c88b9fcUL, 0xdf1ddd62UL, 0x492dda15UL, 0xf37cd38cUL, + 0x654cd4fbUL, 0x5861b24dUL, 0xce51b53aUL, 0x7400bca3UL, 0xe230bbd4UL, + 0x41a5df4aUL, 0xd795d83dUL, 0x6dc4d1a4UL, 0xfbf4d6d3UL, 0x6ae96943UL, + 0xfcd96e34UL, 0x468867adUL, 0xd0b860daUL, 0x732d0444UL, 0xe51d0333UL, + 0x5f4c0aaaUL, 0xc97c0dddUL, 0x3c710550UL, 0xaa410227UL, 0x10100bbeUL, + 0x86200cc9UL, 0x25b56857UL, 0xb3856f20UL, 0x09d466b9UL, 0x9fe461ceUL, + 0x0ef9de5eUL, 0x98c9d929UL, 0x2298d0b0UL, 0xb4a8d7c7UL, 0x173db359UL, + 0x810db42eUL, 0x3b5cbdb7UL, 0xad6cbac0UL, 0x2083b8edUL, 0xb6b3bf9aUL, + 0x0ce2b603UL, 0x9ad2b174UL, 0x3947d5eaUL, 0xaf77d29dUL, 0x1526db04UL, + 0x8316dc73UL, 0x120b63e3UL, 0x843b6494UL, 0x3e6a6d0dUL, 0xa85a6a7aUL, + 0x0bcf0ee4UL, 0x9dff0993UL, 0x27ae000aUL, 0xb19e077dUL, 0x44930ff0UL, + 0xd2a30887UL, 0x68f2011eUL, 0xfec20669UL, 0x5d5762f7UL, 0xcb676580UL, + 0x71366c19UL, 0xe7066b6eUL, 0x761bd4feUL, 0xe02bd389UL, 0x5a7ada10UL, + 0xcc4add67UL, 0x6fdfb9f9UL, 0xf9efbe8eUL, 0x43beb717UL, 0xd58eb060UL, + 0xe8a3d6d6UL, 0x7e93d1a1UL, 0xc4c2d838UL, 0x52f2df4fUL, 0xf167bbd1UL, + 0x6757bca6UL, 0xdd06b53fUL, 0x4b36b248UL, 0xda2b0dd8UL, 0x4c1b0aafUL, + 0xf64a0336UL, 0x607a0441UL, 0xc3ef60dfUL, 0x55df67a8UL, 0xef8e6e31UL, + 0x79be6946UL, 0x8cb361cbUL, 0x1a8366bcUL, 0xa0d26f25UL, 0x36e26852UL, + 0x95770cccUL, 0x03470bbbUL, 0xb9160222UL, 0x2f260555UL, 0xbe3bbac5UL, + 0x280bbdb2UL, 0x925ab42bUL, 0x046ab35cUL, 0xa7ffd7c2UL, 0x31cfd0b5UL, + 0x8b9ed92cUL, 0x1daede5bUL, 0xb0c2649bUL, 0x26f263ecUL, 0x9ca36a75UL, + 0x0a936d02UL, 0xa906099cUL, 0x3f360eebUL, 0x85670772UL, 0x13570005UL, + 0x824abf95UL, 0x147ab8e2UL, 0xae2bb17bUL, 0x381bb60cUL, 0x9b8ed292UL, + 0x0dbed5e5UL, 0xb7efdc7cUL, 0x21dfdb0bUL, 0xd4d2d386UL, 0x42e2d4f1UL, + 0xf8b3dd68UL, 0x6e83da1fUL, 0xcd16be81UL, 0x5b26b9f6UL, 0xe177b06fUL, + 0x7747b718UL, 0xe65a0888UL, 0x706a0fffUL, 0xca3b0666UL, 0x5c0b0111UL, + 0xff9e658fUL, 0x69ae62f8UL, 0xd3ff6b61UL, 0x45cf6c16UL, 0x78e20aa0UL, + 0xeed20dd7UL, 0x5483044eUL, 0xc2b30339UL, 0x612667a7UL, 0xf71660d0UL, + 0x4d476949UL, 0xdb776e3eUL, 0x4a6ad1aeUL, 0xdc5ad6d9UL, 0x660bdf40UL, + 0xf03bd837UL, 0x53aebca9UL, 0xc59ebbdeUL, 0x7fcfb247UL, 0xe9ffb530UL, + 0x1cf2bdbdUL, 0x8ac2bacaUL, 0x3093b353UL, 0xa6a3b424UL, 0x0536d0baUL, + 0x9306d7cdUL, 0x2957de54UL, 0xbf67d923UL, 0x2e7a66b3UL, 0xb84a61c4UL, + 0x021b685dUL, 0x942b6f2aUL, 0x37be0bb4UL, 0xa18e0cc3UL, 0x1bdf055aUL, + 0x8def022dUL + }, + { + 0x00000000UL, 0x41311b19UL, 0x82623632UL, 0xc3532d2bUL, 0x04c56c64UL, + 0x45f4777dUL, 0x86a75a56UL, 0xc796414fUL, 0x088ad9c8UL, 0x49bbc2d1UL, + 0x8ae8effaUL, 0xcbd9f4e3UL, 0x0c4fb5acUL, 0x4d7eaeb5UL, 0x8e2d839eUL, + 0xcf1c9887UL, 0x5112c24aUL, 0x1023d953UL, 0xd370f478UL, 0x9241ef61UL, + 0x55d7ae2eUL, 0x14e6b537UL, 0xd7b5981cUL, 0x96848305UL, 0x59981b82UL, + 0x18a9009bUL, 0xdbfa2db0UL, 0x9acb36a9UL, 0x5d5d77e6UL, 0x1c6c6cffUL, + 0xdf3f41d4UL, 0x9e0e5acdUL, 0xa2248495UL, 0xe3159f8cUL, 0x2046b2a7UL, + 0x6177a9beUL, 0xa6e1e8f1UL, 0xe7d0f3e8UL, 0x2483dec3UL, 0x65b2c5daUL, + 0xaaae5d5dUL, 0xeb9f4644UL, 0x28cc6b6fUL, 0x69fd7076UL, 0xae6b3139UL, + 0xef5a2a20UL, 0x2c09070bUL, 0x6d381c12UL, 0xf33646dfUL, 0xb2075dc6UL, + 0x715470edUL, 0x30656bf4UL, 0xf7f32abbUL, 0xb6c231a2UL, 0x75911c89UL, + 0x34a00790UL, 0xfbbc9f17UL, 0xba8d840eUL, 0x79dea925UL, 0x38efb23cUL, + 0xff79f373UL, 0xbe48e86aUL, 0x7d1bc541UL, 0x3c2ade58UL, 0x054f79f0UL, + 0x447e62e9UL, 0x872d4fc2UL, 0xc61c54dbUL, 0x018a1594UL, 0x40bb0e8dUL, + 0x83e823a6UL, 0xc2d938bfUL, 0x0dc5a038UL, 0x4cf4bb21UL, 0x8fa7960aUL, + 0xce968d13UL, 0x0900cc5cUL, 0x4831d745UL, 0x8b62fa6eUL, 0xca53e177UL, + 0x545dbbbaUL, 0x156ca0a3UL, 0xd63f8d88UL, 0x970e9691UL, 0x5098d7deUL, + 0x11a9ccc7UL, 0xd2fae1ecUL, 0x93cbfaf5UL, 0x5cd76272UL, 0x1de6796bUL, + 0xdeb55440UL, 0x9f844f59UL, 0x58120e16UL, 0x1923150fUL, 0xda703824UL, + 0x9b41233dUL, 0xa76bfd65UL, 0xe65ae67cUL, 0x2509cb57UL, 0x6438d04eUL, + 0xa3ae9101UL, 0xe29f8a18UL, 0x21cca733UL, 0x60fdbc2aUL, 0xafe124adUL, + 0xeed03fb4UL, 0x2d83129fUL, 0x6cb20986UL, 0xab2448c9UL, 0xea1553d0UL, + 0x29467efbUL, 0x687765e2UL, 0xf6793f2fUL, 0xb7482436UL, 0x741b091dUL, + 0x352a1204UL, 0xf2bc534bUL, 0xb38d4852UL, 0x70de6579UL, 0x31ef7e60UL, + 0xfef3e6e7UL, 0xbfc2fdfeUL, 0x7c91d0d5UL, 0x3da0cbccUL, 0xfa368a83UL, + 0xbb07919aUL, 0x7854bcb1UL, 0x3965a7a8UL, 0x4b98833bUL, 0x0aa99822UL, + 0xc9fab509UL, 0x88cbae10UL, 0x4f5def5fUL, 0x0e6cf446UL, 0xcd3fd96dUL, + 0x8c0ec274UL, 0x43125af3UL, 0x022341eaUL, 0xc1706cc1UL, 0x804177d8UL, + 0x47d73697UL, 0x06e62d8eUL, 0xc5b500a5UL, 0x84841bbcUL, 0x1a8a4171UL, + 0x5bbb5a68UL, 0x98e87743UL, 0xd9d96c5aUL, 0x1e4f2d15UL, 0x5f7e360cUL, + 0x9c2d1b27UL, 0xdd1c003eUL, 0x120098b9UL, 0x533183a0UL, 0x9062ae8bUL, + 0xd153b592UL, 0x16c5f4ddUL, 0x57f4efc4UL, 0x94a7c2efUL, 0xd596d9f6UL, + 0xe9bc07aeUL, 0xa88d1cb7UL, 0x6bde319cUL, 0x2aef2a85UL, 0xed796bcaUL, + 0xac4870d3UL, 0x6f1b5df8UL, 0x2e2a46e1UL, 0xe136de66UL, 0xa007c57fUL, + 0x6354e854UL, 0x2265f34dUL, 0xe5f3b202UL, 0xa4c2a91bUL, 0x67918430UL, + 0x26a09f29UL, 0xb8aec5e4UL, 0xf99fdefdUL, 0x3accf3d6UL, 0x7bfde8cfUL, + 0xbc6ba980UL, 0xfd5ab299UL, 0x3e099fb2UL, 0x7f3884abUL, 0xb0241c2cUL, + 0xf1150735UL, 0x32462a1eUL, 0x73773107UL, 0xb4e17048UL, 0xf5d06b51UL, + 0x3683467aUL, 0x77b25d63UL, 0x4ed7facbUL, 0x0fe6e1d2UL, 0xccb5ccf9UL, + 0x8d84d7e0UL, 0x4a1296afUL, 0x0b238db6UL, 0xc870a09dUL, 0x8941bb84UL, + 0x465d2303UL, 0x076c381aUL, 0xc43f1531UL, 0x850e0e28UL, 0x42984f67UL, + 0x03a9547eUL, 0xc0fa7955UL, 0x81cb624cUL, 0x1fc53881UL, 0x5ef42398UL, + 0x9da70eb3UL, 0xdc9615aaUL, 0x1b0054e5UL, 0x5a314ffcUL, 0x996262d7UL, + 0xd85379ceUL, 0x174fe149UL, 0x567efa50UL, 0x952dd77bUL, 0xd41ccc62UL, + 0x138a8d2dUL, 0x52bb9634UL, 0x91e8bb1fUL, 0xd0d9a006UL, 0xecf37e5eUL, + 0xadc26547UL, 0x6e91486cUL, 0x2fa05375UL, 0xe836123aUL, 0xa9070923UL, + 0x6a542408UL, 0x2b653f11UL, 0xe479a796UL, 0xa548bc8fUL, 0x661b91a4UL, + 0x272a8abdUL, 0xe0bccbf2UL, 0xa18dd0ebUL, 0x62defdc0UL, 0x23efe6d9UL, + 0xbde1bc14UL, 0xfcd0a70dUL, 0x3f838a26UL, 0x7eb2913fUL, 0xb924d070UL, + 0xf815cb69UL, 0x3b46e642UL, 0x7a77fd5bUL, 0xb56b65dcUL, 0xf45a7ec5UL, + 0x370953eeUL, 0x763848f7UL, 0xb1ae09b8UL, 0xf09f12a1UL, 0x33cc3f8aUL, + 0x72fd2493UL + }, + { + 0x00000000UL, 0x376ac201UL, 0x6ed48403UL, 0x59be4602UL, 0xdca80907UL, + 0xebc2cb06UL, 0xb27c8d04UL, 0x85164f05UL, 0xb851130eUL, 0x8f3bd10fUL, + 0xd685970dUL, 0xe1ef550cUL, 0x64f91a09UL, 0x5393d808UL, 0x0a2d9e0aUL, + 0x3d475c0bUL, 0x70a3261cUL, 0x47c9e41dUL, 0x1e77a21fUL, 0x291d601eUL, + 0xac0b2f1bUL, 0x9b61ed1aUL, 0xc2dfab18UL, 0xf5b56919UL, 0xc8f23512UL, + 0xff98f713UL, 0xa626b111UL, 0x914c7310UL, 0x145a3c15UL, 0x2330fe14UL, + 0x7a8eb816UL, 0x4de47a17UL, 0xe0464d38UL, 0xd72c8f39UL, 0x8e92c93bUL, + 0xb9f80b3aUL, 0x3cee443fUL, 0x0b84863eUL, 0x523ac03cUL, 0x6550023dUL, + 0x58175e36UL, 0x6f7d9c37UL, 0x36c3da35UL, 0x01a91834UL, 0x84bf5731UL, + 0xb3d59530UL, 0xea6bd332UL, 0xdd011133UL, 0x90e56b24UL, 0xa78fa925UL, + 0xfe31ef27UL, 0xc95b2d26UL, 0x4c4d6223UL, 0x7b27a022UL, 0x2299e620UL, + 0x15f32421UL, 0x28b4782aUL, 0x1fdeba2bUL, 0x4660fc29UL, 0x710a3e28UL, + 0xf41c712dUL, 0xc376b32cUL, 0x9ac8f52eUL, 0xada2372fUL, 0xc08d9a70UL, + 0xf7e75871UL, 0xae591e73UL, 0x9933dc72UL, 0x1c259377UL, 0x2b4f5176UL, + 0x72f11774UL, 0x459bd575UL, 0x78dc897eUL, 0x4fb64b7fUL, 0x16080d7dUL, + 0x2162cf7cUL, 0xa4748079UL, 0x931e4278UL, 0xcaa0047aUL, 0xfdcac67bUL, + 0xb02ebc6cUL, 0x87447e6dUL, 0xdefa386fUL, 0xe990fa6eUL, 0x6c86b56bUL, + 0x5bec776aUL, 0x02523168UL, 0x3538f369UL, 0x087faf62UL, 0x3f156d63UL, + 0x66ab2b61UL, 0x51c1e960UL, 0xd4d7a665UL, 0xe3bd6464UL, 0xba032266UL, + 0x8d69e067UL, 0x20cbd748UL, 0x17a11549UL, 0x4e1f534bUL, 0x7975914aUL, + 0xfc63de4fUL, 0xcb091c4eUL, 0x92b75a4cUL, 0xa5dd984dUL, 0x989ac446UL, + 0xaff00647UL, 0xf64e4045UL, 0xc1248244UL, 0x4432cd41UL, 0x73580f40UL, + 0x2ae64942UL, 0x1d8c8b43UL, 0x5068f154UL, 0x67023355UL, 0x3ebc7557UL, + 0x09d6b756UL, 0x8cc0f853UL, 0xbbaa3a52UL, 0xe2147c50UL, 0xd57ebe51UL, + 0xe839e25aUL, 0xdf53205bUL, 0x86ed6659UL, 0xb187a458UL, 0x3491eb5dUL, + 0x03fb295cUL, 0x5a456f5eUL, 0x6d2fad5fUL, 0x801b35e1UL, 0xb771f7e0UL, + 0xeecfb1e2UL, 0xd9a573e3UL, 0x5cb33ce6UL, 0x6bd9fee7UL, 0x3267b8e5UL, + 0x050d7ae4UL, 0x384a26efUL, 0x0f20e4eeUL, 0x569ea2ecUL, 0x61f460edUL, + 0xe4e22fe8UL, 0xd388ede9UL, 0x8a36abebUL, 0xbd5c69eaUL, 0xf0b813fdUL, + 0xc7d2d1fcUL, 0x9e6c97feUL, 0xa90655ffUL, 0x2c101afaUL, 0x1b7ad8fbUL, + 0x42c49ef9UL, 0x75ae5cf8UL, 0x48e900f3UL, 0x7f83c2f2UL, 0x263d84f0UL, + 0x115746f1UL, 0x944109f4UL, 0xa32bcbf5UL, 0xfa958df7UL, 0xcdff4ff6UL, + 0x605d78d9UL, 0x5737bad8UL, 0x0e89fcdaUL, 0x39e33edbUL, 0xbcf571deUL, + 0x8b9fb3dfUL, 0xd221f5ddUL, 0xe54b37dcUL, 0xd80c6bd7UL, 0xef66a9d6UL, + 0xb6d8efd4UL, 0x81b22dd5UL, 0x04a462d0UL, 0x33cea0d1UL, 0x6a70e6d3UL, + 0x5d1a24d2UL, 0x10fe5ec5UL, 0x27949cc4UL, 0x7e2adac6UL, 0x494018c7UL, + 0xcc5657c2UL, 0xfb3c95c3UL, 0xa282d3c1UL, 0x95e811c0UL, 0xa8af4dcbUL, + 0x9fc58fcaUL, 0xc67bc9c8UL, 0xf1110bc9UL, 0x740744ccUL, 0x436d86cdUL, + 0x1ad3c0cfUL, 0x2db902ceUL, 0x4096af91UL, 0x77fc6d90UL, 0x2e422b92UL, + 0x1928e993UL, 0x9c3ea696UL, 0xab546497UL, 0xf2ea2295UL, 0xc580e094UL, + 0xf8c7bc9fUL, 0xcfad7e9eUL, 0x9613389cUL, 0xa179fa9dUL, 0x246fb598UL, + 0x13057799UL, 0x4abb319bUL, 0x7dd1f39aUL, 0x3035898dUL, 0x075f4b8cUL, + 0x5ee10d8eUL, 0x698bcf8fUL, 0xec9d808aUL, 0xdbf7428bUL, 0x82490489UL, + 0xb523c688UL, 0x88649a83UL, 0xbf0e5882UL, 0xe6b01e80UL, 0xd1dadc81UL, + 0x54cc9384UL, 0x63a65185UL, 0x3a181787UL, 0x0d72d586UL, 0xa0d0e2a9UL, + 0x97ba20a8UL, 0xce0466aaUL, 0xf96ea4abUL, 0x7c78ebaeUL, 0x4b1229afUL, + 0x12ac6fadUL, 0x25c6adacUL, 0x1881f1a7UL, 0x2feb33a6UL, 0x765575a4UL, + 0x413fb7a5UL, 0xc429f8a0UL, 0xf3433aa1UL, 0xaafd7ca3UL, 0x9d97bea2UL, + 0xd073c4b5UL, 0xe71906b4UL, 0xbea740b6UL, 0x89cd82b7UL, 0x0cdbcdb2UL, + 0x3bb10fb3UL, 0x620f49b1UL, 0x55658bb0UL, 0x6822d7bbUL, 0x5f4815baUL, + 0x06f653b8UL, 0x319c91b9UL, 0xb48adebcUL, 0x83e01cbdUL, 0xda5e5abfUL, + 0xed3498beUL + }, + { + 0x00000000UL, 0x6567bcb8UL, 0x8bc809aaUL, 0xeeafb512UL, 0x5797628fUL, + 0x32f0de37UL, 0xdc5f6b25UL, 0xb938d79dUL, 0xef28b4c5UL, 0x8a4f087dUL, + 0x64e0bd6fUL, 0x018701d7UL, 0xb8bfd64aUL, 0xddd86af2UL, 0x3377dfe0UL, + 0x56106358UL, 0x9f571950UL, 0xfa30a5e8UL, 0x149f10faUL, 0x71f8ac42UL, + 0xc8c07bdfUL, 0xada7c767UL, 0x43087275UL, 0x266fcecdUL, 0x707fad95UL, + 0x1518112dUL, 0xfbb7a43fUL, 0x9ed01887UL, 0x27e8cf1aUL, 0x428f73a2UL, + 0xac20c6b0UL, 0xc9477a08UL, 0x3eaf32a0UL, 0x5bc88e18UL, 0xb5673b0aUL, + 0xd00087b2UL, 0x6938502fUL, 0x0c5fec97UL, 0xe2f05985UL, 0x8797e53dUL, + 0xd1878665UL, 0xb4e03addUL, 0x5a4f8fcfUL, 0x3f283377UL, 0x8610e4eaUL, + 0xe3775852UL, 0x0dd8ed40UL, 0x68bf51f8UL, 0xa1f82bf0UL, 0xc49f9748UL, + 0x2a30225aUL, 0x4f579ee2UL, 0xf66f497fUL, 0x9308f5c7UL, 0x7da740d5UL, + 0x18c0fc6dUL, 0x4ed09f35UL, 0x2bb7238dUL, 0xc518969fUL, 0xa07f2a27UL, + 0x1947fdbaUL, 0x7c204102UL, 0x928ff410UL, 0xf7e848a8UL, 0x3d58149bUL, + 0x583fa823UL, 0xb6901d31UL, 0xd3f7a189UL, 0x6acf7614UL, 0x0fa8caacUL, + 0xe1077fbeUL, 0x8460c306UL, 0xd270a05eUL, 0xb7171ce6UL, 0x59b8a9f4UL, + 0x3cdf154cUL, 0x85e7c2d1UL, 0xe0807e69UL, 0x0e2fcb7bUL, 0x6b4877c3UL, + 0xa20f0dcbUL, 0xc768b173UL, 0x29c70461UL, 0x4ca0b8d9UL, 0xf5986f44UL, + 0x90ffd3fcUL, 0x7e5066eeUL, 0x1b37da56UL, 0x4d27b90eUL, 0x284005b6UL, + 0xc6efb0a4UL, 0xa3880c1cUL, 0x1ab0db81UL, 0x7fd76739UL, 0x9178d22bUL, + 0xf41f6e93UL, 0x03f7263bUL, 0x66909a83UL, 0x883f2f91UL, 0xed589329UL, + 0x546044b4UL, 0x3107f80cUL, 0xdfa84d1eUL, 0xbacff1a6UL, 0xecdf92feUL, + 0x89b82e46UL, 0x67179b54UL, 0x027027ecUL, 0xbb48f071UL, 0xde2f4cc9UL, + 0x3080f9dbUL, 0x55e74563UL, 0x9ca03f6bUL, 0xf9c783d3UL, 0x176836c1UL, + 0x720f8a79UL, 0xcb375de4UL, 0xae50e15cUL, 0x40ff544eUL, 0x2598e8f6UL, + 0x73888baeUL, 0x16ef3716UL, 0xf8408204UL, 0x9d273ebcUL, 0x241fe921UL, + 0x41785599UL, 0xafd7e08bUL, 0xcab05c33UL, 0x3bb659edUL, 0x5ed1e555UL, + 0xb07e5047UL, 0xd519ecffUL, 0x6c213b62UL, 0x094687daUL, 0xe7e932c8UL, + 0x828e8e70UL, 0xd49eed28UL, 0xb1f95190UL, 0x5f56e482UL, 0x3a31583aUL, + 0x83098fa7UL, 0xe66e331fUL, 0x08c1860dUL, 0x6da63ab5UL, 0xa4e140bdUL, + 0xc186fc05UL, 0x2f294917UL, 0x4a4ef5afUL, 0xf3762232UL, 0x96119e8aUL, + 0x78be2b98UL, 0x1dd99720UL, 0x4bc9f478UL, 0x2eae48c0UL, 0xc001fdd2UL, + 0xa566416aUL, 0x1c5e96f7UL, 0x79392a4fUL, 0x97969f5dUL, 0xf2f123e5UL, + 0x05196b4dUL, 0x607ed7f5UL, 0x8ed162e7UL, 0xebb6de5fUL, 0x528e09c2UL, + 0x37e9b57aUL, 0xd9460068UL, 0xbc21bcd0UL, 0xea31df88UL, 0x8f566330UL, + 0x61f9d622UL, 0x049e6a9aUL, 0xbda6bd07UL, 0xd8c101bfUL, 0x366eb4adUL, + 0x53090815UL, 0x9a4e721dUL, 0xff29cea5UL, 0x11867bb7UL, 0x74e1c70fUL, + 0xcdd91092UL, 0xa8beac2aUL, 0x46111938UL, 0x2376a580UL, 0x7566c6d8UL, + 0x10017a60UL, 0xfeaecf72UL, 0x9bc973caUL, 0x22f1a457UL, 0x479618efUL, + 0xa939adfdUL, 0xcc5e1145UL, 0x06ee4d76UL, 0x6389f1ceUL, 0x8d2644dcUL, + 0xe841f864UL, 0x51792ff9UL, 0x341e9341UL, 0xdab12653UL, 0xbfd69aebUL, + 0xe9c6f9b3UL, 0x8ca1450bUL, 0x620ef019UL, 0x07694ca1UL, 0xbe519b3cUL, + 0xdb362784UL, 0x35999296UL, 0x50fe2e2eUL, 0x99b95426UL, 0xfcdee89eUL, + 0x12715d8cUL, 0x7716e134UL, 0xce2e36a9UL, 0xab498a11UL, 0x45e63f03UL, + 0x208183bbUL, 0x7691e0e3UL, 0x13f65c5bUL, 0xfd59e949UL, 0x983e55f1UL, + 0x2106826cUL, 0x44613ed4UL, 0xaace8bc6UL, 0xcfa9377eUL, 0x38417fd6UL, + 0x5d26c36eUL, 0xb389767cUL, 0xd6eecac4UL, 0x6fd61d59UL, 0x0ab1a1e1UL, + 0xe41e14f3UL, 0x8179a84bUL, 0xd769cb13UL, 0xb20e77abUL, 0x5ca1c2b9UL, + 0x39c67e01UL, 0x80fea99cUL, 0xe5991524UL, 0x0b36a036UL, 0x6e511c8eUL, + 0xa7166686UL, 0xc271da3eUL, 0x2cde6f2cUL, 0x49b9d394UL, 0xf0810409UL, + 0x95e6b8b1UL, 0x7b490da3UL, 0x1e2eb11bUL, 0x483ed243UL, 0x2d596efbUL, + 0xc3f6dbe9UL, 0xa6916751UL, 0x1fa9b0ccUL, 0x7ace0c74UL, 0x9461b966UL, + 0xf10605deUL +#endif + } +}; diff --git a/arm-trusted-firmware/lib/zlib/inffast.c b/arm-trusted-firmware/lib/zlib/inffast.c new file mode 100644 index 0000000..0dbd1db --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffast.c @@ -0,0 +1,323 @@ +/* inffast.c -- fast decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef ASMINF +# pragma message("Assembler code may have bugs -- use at your own risk") +#else + +/* + Decode literal, length, and distance codes and write out the resulting + literal and match bytes until either not enough input or output is + available, an end-of-block is encountered, or a data error is encountered. + When large enough input and output buffers are supplied to inflate(), for + example, a 16K input buffer and a 64K output buffer, more than 95% of the + inflate execution time is spent in this routine. + + Entry assumptions: + + state->mode == LEN + strm->avail_in >= 6 + strm->avail_out >= 258 + start >= strm->avail_out + state->bits < 8 + + On return, state->mode is one of: + + LEN -- ran out of enough output space or enough available input + TYPE -- reached end of block code, inflate() to interpret next block + BAD -- error in block data + + Notes: + + - The maximum input bits used by a length/distance pair is 15 bits for the + length code, 5 bits for the length extra, 15 bits for the distance code, + and 13 bits for the distance extra. This totals 48 bits, or six bytes. + Therefore if strm->avail_in >= 6, then there is enough input to avoid + checking for available input while decoding. + + - The maximum bytes that a single length/distance pair can output is 258 + bytes, which is the maximum length that can be coded. inflate_fast() + requires strm->avail_out >= 258 for each loop to avoid checking for + output space. + */ +void ZLIB_INTERNAL inflate_fast(strm, start) +z_streamp strm; +unsigned start; /* inflate()'s starting value for strm->avail_out */ +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *in; /* local strm->next_in */ + z_const unsigned char FAR *last; /* have enough input while in < last */ + unsigned char FAR *out; /* local strm->next_out */ + unsigned char FAR *beg; /* inflate()'s initial strm->next_out */ + unsigned char FAR *end; /* while out < end, enough space available */ +#ifdef INFLATE_STRICT + unsigned dmax; /* maximum distance from zlib header */ +#endif + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if wsize != 0 */ + unsigned long hold; /* local strm->hold */ + unsigned bits; /* local strm->bits */ + code const FAR *lcode; /* local strm->lencode */ + code const FAR *dcode; /* local strm->distcode */ + unsigned lmask; /* mask for first level of length codes */ + unsigned dmask; /* mask for first level of distance codes */ + code here; /* retrieved table entry */ + unsigned op; /* code bits, operation, extra bits, or */ + /* window position, window bytes to copy */ + unsigned len; /* match length, unused bytes */ + unsigned dist; /* match distance */ + unsigned char FAR *from; /* where to copy match from */ + + /* copy state to local variables */ + state = (struct inflate_state FAR *)strm->state; + in = strm->next_in; + last = in + (strm->avail_in - 5); + out = strm->next_out; + beg = out - (start - strm->avail_out); + end = out + (strm->avail_out - 257); +#ifdef INFLATE_STRICT + dmax = state->dmax; +#endif + wsize = state->wsize; + whave = state->whave; + wnext = state->wnext; + window = state->window; + hold = state->hold; + bits = state->bits; + lcode = state->lencode; + dcode = state->distcode; + lmask = (1U << state->lenbits) - 1; + dmask = (1U << state->distbits) - 1; + + /* decode literals and length/distances until end-of-block or not enough + input data or output space */ + do { + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = lcode[hold & lmask]; + dolen: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op == 0) { /* literal */ + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + *out++ = (unsigned char)(here.val); + } + else if (op & 16) { /* length base */ + len = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (op) { + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + len += (unsigned)hold & ((1U << op) - 1); + hold >>= op; + bits -= op; + } + Tracevv((stderr, "inflate: length %u\n", len)); + if (bits < 15) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + here = dcode[hold & dmask]; + dodist: + op = (unsigned)(here.bits); + hold >>= op; + bits -= op; + op = (unsigned)(here.op); + if (op & 16) { /* distance base */ + dist = (unsigned)(here.val); + op &= 15; /* number of extra bits */ + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + if (bits < op) { + hold += (unsigned long)(*in++) << bits; + bits += 8; + } + } + dist += (unsigned)hold & ((1U << op) - 1); +#ifdef INFLATE_STRICT + if (dist > dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + hold >>= op; + bits -= op; + Tracevv((stderr, "inflate: distance %u\n", dist)); + op = (unsigned)(out - beg); /* max distance in output */ + if (dist > op) { /* see if copy from window */ + op = dist - op; /* distance back in window */ + if (op > whave) { + if (state->sane) { + strm->msg = + (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + if (len <= op - whave) { + do { + *out++ = 0; + } while (--len); + continue; + } + len -= op - whave; + do { + *out++ = 0; + } while (--op > whave); + if (op == 0) { + from = out - dist; + do { + *out++ = *from++; + } while (--len); + continue; + } +#endif + } + from = window; + if (wnext == 0) { /* very common case */ + from += wsize - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + else if (wnext < op) { /* wrap around window */ + from += wsize + wnext - op; + op -= wnext; + if (op < len) { /* some from end of window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = window; + if (wnext < len) { /* some from start of window */ + op = wnext; + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + } + else { /* contiguous in window */ + from += wnext - op; + if (op < len) { /* some from window */ + len -= op; + do { + *out++ = *from++; + } while (--op); + from = out - dist; /* rest from output */ + } + } + while (len > 2) { + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + else { + from = out - dist; /* copy direct from output */ + do { /* minimum length is three */ + *out++ = *from++; + *out++ = *from++; + *out++ = *from++; + len -= 3; + } while (len > 2); + if (len) { + *out++ = *from++; + if (len > 1) + *out++ = *from++; + } + } + } + else if ((op & 64) == 0) { /* 2nd level distance code */ + here = dcode[here.val + (hold & ((1U << op) - 1))]; + goto dodist; + } + else { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + } + else if ((op & 64) == 0) { /* 2nd level length code */ + here = lcode[here.val + (hold & ((1U << op) - 1))]; + goto dolen; + } + else if (op & 32) { /* end-of-block */ + Tracevv((stderr, "inflate: end of block\n")); + state->mode = TYPE; + break; + } + else { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + } while (in < last && out < end); + + /* return unused bytes (on entry, bits < 8, so in won't go too far back) */ + len = bits >> 3; + in -= len; + bits -= len << 3; + hold &= (1U << bits) - 1; + + /* update state and return */ + strm->next_in = in; + strm->next_out = out; + strm->avail_in = (unsigned)(in < last ? 5 + (last - in) : 5 - (in - last)); + strm->avail_out = (unsigned)(out < end ? + 257 + (end - out) : 257 - (out - end)); + state->hold = hold; + state->bits = bits; + return; +} + +/* + inflate_fast() speedups that turned out slower (on a PowerPC G3 750CXe): + - Using bit fields for code structure + - Different op definition to avoid & for extra bits (do & for table bits) + - Three separate decoding do-loops for direct, window, and wnext == 0 + - Special case for distance > 1 copies to do overlapped load and store copy + - Explicit branch predictions (based on measured branch probabilities) + - Deferring match copy and interspersed it with decoding subsequent codes + - Swapping literal/length else + - Swapping window/direct else + - Larger unrolled copy loops (three is about right) + - Moving len -= 3 statement into middle of loop + */ + +#endif /* !ASMINF */ diff --git a/arm-trusted-firmware/lib/zlib/inffast.h b/arm-trusted-firmware/lib/zlib/inffast.h new file mode 100644 index 0000000..e5c1aa4 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffast.h @@ -0,0 +1,11 @@ +/* inffast.h -- header to use inffast.c + * Copyright (C) 1995-2003, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +void ZLIB_INTERNAL inflate_fast OF((z_streamp strm, unsigned start)); diff --git a/arm-trusted-firmware/lib/zlib/inffixed.h b/arm-trusted-firmware/lib/zlib/inffixed.h new file mode 100644 index 0000000..d628327 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inffixed.h @@ -0,0 +1,94 @@ + /* inffixed.h -- table for decoding fixed codes + * Generated automatically by makefixed(). + */ + + /* WARNING: this file should *not* be used by applications. + It is part of the implementation of this library and is + subject to change. Applications should only use zlib.h. + */ + + static const code lenfix[512] = { + {96,7,0},{0,8,80},{0,8,16},{20,8,115},{18,7,31},{0,8,112},{0,8,48}, + {0,9,192},{16,7,10},{0,8,96},{0,8,32},{0,9,160},{0,8,0},{0,8,128}, + {0,8,64},{0,9,224},{16,7,6},{0,8,88},{0,8,24},{0,9,144},{19,7,59}, + {0,8,120},{0,8,56},{0,9,208},{17,7,17},{0,8,104},{0,8,40},{0,9,176}, + {0,8,8},{0,8,136},{0,8,72},{0,9,240},{16,7,4},{0,8,84},{0,8,20}, + {21,8,227},{19,7,43},{0,8,116},{0,8,52},{0,9,200},{17,7,13},{0,8,100}, + {0,8,36},{0,9,168},{0,8,4},{0,8,132},{0,8,68},{0,9,232},{16,7,8}, + {0,8,92},{0,8,28},{0,9,152},{20,7,83},{0,8,124},{0,8,60},{0,9,216}, + {18,7,23},{0,8,108},{0,8,44},{0,9,184},{0,8,12},{0,8,140},{0,8,76}, + {0,9,248},{16,7,3},{0,8,82},{0,8,18},{21,8,163},{19,7,35},{0,8,114}, + {0,8,50},{0,9,196},{17,7,11},{0,8,98},{0,8,34},{0,9,164},{0,8,2}, + {0,8,130},{0,8,66},{0,9,228},{16,7,7},{0,8,90},{0,8,26},{0,9,148}, + {20,7,67},{0,8,122},{0,8,58},{0,9,212},{18,7,19},{0,8,106},{0,8,42}, + {0,9,180},{0,8,10},{0,8,138},{0,8,74},{0,9,244},{16,7,5},{0,8,86}, + {0,8,22},{64,8,0},{19,7,51},{0,8,118},{0,8,54},{0,9,204},{17,7,15}, + {0,8,102},{0,8,38},{0,9,172},{0,8,6},{0,8,134},{0,8,70},{0,9,236}, + {16,7,9},{0,8,94},{0,8,30},{0,9,156},{20,7,99},{0,8,126},{0,8,62}, + {0,9,220},{18,7,27},{0,8,110},{0,8,46},{0,9,188},{0,8,14},{0,8,142}, + {0,8,78},{0,9,252},{96,7,0},{0,8,81},{0,8,17},{21,8,131},{18,7,31}, + {0,8,113},{0,8,49},{0,9,194},{16,7,10},{0,8,97},{0,8,33},{0,9,162}, + {0,8,1},{0,8,129},{0,8,65},{0,9,226},{16,7,6},{0,8,89},{0,8,25}, + {0,9,146},{19,7,59},{0,8,121},{0,8,57},{0,9,210},{17,7,17},{0,8,105}, + {0,8,41},{0,9,178},{0,8,9},{0,8,137},{0,8,73},{0,9,242},{16,7,4}, + {0,8,85},{0,8,21},{16,8,258},{19,7,43},{0,8,117},{0,8,53},{0,9,202}, + {17,7,13},{0,8,101},{0,8,37},{0,9,170},{0,8,5},{0,8,133},{0,8,69}, + {0,9,234},{16,7,8},{0,8,93},{0,8,29},{0,9,154},{20,7,83},{0,8,125}, + {0,8,61},{0,9,218},{18,7,23},{0,8,109},{0,8,45},{0,9,186},{0,8,13}, + {0,8,141},{0,8,77},{0,9,250},{16,7,3},{0,8,83},{0,8,19},{21,8,195}, + {19,7,35},{0,8,115},{0,8,51},{0,9,198},{17,7,11},{0,8,99},{0,8,35}, + {0,9,166},{0,8,3},{0,8,131},{0,8,67},{0,9,230},{16,7,7},{0,8,91}, + {0,8,27},{0,9,150},{20,7,67},{0,8,123},{0,8,59},{0,9,214},{18,7,19}, + {0,8,107},{0,8,43},{0,9,182},{0,8,11},{0,8,139},{0,8,75},{0,9,246}, + {16,7,5},{0,8,87},{0,8,23},{64,8,0},{19,7,51},{0,8,119},{0,8,55}, + {0,9,206},{17,7,15},{0,8,103},{0,8,39},{0,9,174},{0,8,7},{0,8,135}, + {0,8,71},{0,9,238},{16,7,9},{0,8,95},{0,8,31},{0,9,158},{20,7,99}, + {0,8,127},{0,8,63},{0,9,222},{18,7,27},{0,8,111},{0,8,47},{0,9,190}, + {0,8,15},{0,8,143},{0,8,79},{0,9,254},{96,7,0},{0,8,80},{0,8,16}, + {20,8,115},{18,7,31},{0,8,112},{0,8,48},{0,9,193},{16,7,10},{0,8,96}, + {0,8,32},{0,9,161},{0,8,0},{0,8,128},{0,8,64},{0,9,225},{16,7,6}, + {0,8,88},{0,8,24},{0,9,145},{19,7,59},{0,8,120},{0,8,56},{0,9,209}, + {17,7,17},{0,8,104},{0,8,40},{0,9,177},{0,8,8},{0,8,136},{0,8,72}, + {0,9,241},{16,7,4},{0,8,84},{0,8,20},{21,8,227},{19,7,43},{0,8,116}, + {0,8,52},{0,9,201},{17,7,13},{0,8,100},{0,8,36},{0,9,169},{0,8,4}, + {0,8,132},{0,8,68},{0,9,233},{16,7,8},{0,8,92},{0,8,28},{0,9,153}, + {20,7,83},{0,8,124},{0,8,60},{0,9,217},{18,7,23},{0,8,108},{0,8,44}, + {0,9,185},{0,8,12},{0,8,140},{0,8,76},{0,9,249},{16,7,3},{0,8,82}, + {0,8,18},{21,8,163},{19,7,35},{0,8,114},{0,8,50},{0,9,197},{17,7,11}, + {0,8,98},{0,8,34},{0,9,165},{0,8,2},{0,8,130},{0,8,66},{0,9,229}, + {16,7,7},{0,8,90},{0,8,26},{0,9,149},{20,7,67},{0,8,122},{0,8,58}, + {0,9,213},{18,7,19},{0,8,106},{0,8,42},{0,9,181},{0,8,10},{0,8,138}, + {0,8,74},{0,9,245},{16,7,5},{0,8,86},{0,8,22},{64,8,0},{19,7,51}, + {0,8,118},{0,8,54},{0,9,205},{17,7,15},{0,8,102},{0,8,38},{0,9,173}, + {0,8,6},{0,8,134},{0,8,70},{0,9,237},{16,7,9},{0,8,94},{0,8,30}, + {0,9,157},{20,7,99},{0,8,126},{0,8,62},{0,9,221},{18,7,27},{0,8,110}, + {0,8,46},{0,9,189},{0,8,14},{0,8,142},{0,8,78},{0,9,253},{96,7,0}, + {0,8,81},{0,8,17},{21,8,131},{18,7,31},{0,8,113},{0,8,49},{0,9,195}, + {16,7,10},{0,8,97},{0,8,33},{0,9,163},{0,8,1},{0,8,129},{0,8,65}, + {0,9,227},{16,7,6},{0,8,89},{0,8,25},{0,9,147},{19,7,59},{0,8,121}, + {0,8,57},{0,9,211},{17,7,17},{0,8,105},{0,8,41},{0,9,179},{0,8,9}, + {0,8,137},{0,8,73},{0,9,243},{16,7,4},{0,8,85},{0,8,21},{16,8,258}, + {19,7,43},{0,8,117},{0,8,53},{0,9,203},{17,7,13},{0,8,101},{0,8,37}, + {0,9,171},{0,8,5},{0,8,133},{0,8,69},{0,9,235},{16,7,8},{0,8,93}, + {0,8,29},{0,9,155},{20,7,83},{0,8,125},{0,8,61},{0,9,219},{18,7,23}, + {0,8,109},{0,8,45},{0,9,187},{0,8,13},{0,8,141},{0,8,77},{0,9,251}, + {16,7,3},{0,8,83},{0,8,19},{21,8,195},{19,7,35},{0,8,115},{0,8,51}, + {0,9,199},{17,7,11},{0,8,99},{0,8,35},{0,9,167},{0,8,3},{0,8,131}, + {0,8,67},{0,9,231},{16,7,7},{0,8,91},{0,8,27},{0,9,151},{20,7,67}, + {0,8,123},{0,8,59},{0,9,215},{18,7,19},{0,8,107},{0,8,43},{0,9,183}, + {0,8,11},{0,8,139},{0,8,75},{0,9,247},{16,7,5},{0,8,87},{0,8,23}, + {64,8,0},{19,7,51},{0,8,119},{0,8,55},{0,9,207},{17,7,15},{0,8,103}, + {0,8,39},{0,9,175},{0,8,7},{0,8,135},{0,8,71},{0,9,239},{16,7,9}, + {0,8,95},{0,8,31},{0,9,159},{20,7,99},{0,8,127},{0,8,63},{0,9,223}, + {18,7,27},{0,8,111},{0,8,47},{0,9,191},{0,8,15},{0,8,143},{0,8,79}, + {0,9,255} + }; + + static const code distfix[32] = { + {16,5,1},{23,5,257},{19,5,17},{27,5,4097},{17,5,5},{25,5,1025}, + {21,5,65},{29,5,16385},{16,5,3},{24,5,513},{20,5,33},{28,5,8193}, + {18,5,9},{26,5,2049},{22,5,129},{64,5,0},{16,5,2},{23,5,385}, + {19,5,25},{27,5,6145},{17,5,7},{25,5,1537},{21,5,97},{29,5,24577}, + {16,5,4},{24,5,769},{20,5,49},{28,5,12289},{18,5,13},{26,5,3073}, + {22,5,193},{64,5,0} + }; diff --git a/arm-trusted-firmware/lib/zlib/inflate.c b/arm-trusted-firmware/lib/zlib/inflate.c new file mode 100644 index 0000000..ac333e8 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inflate.c @@ -0,0 +1,1561 @@ +/* inflate.c -- zlib decompression + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* + * Change history: + * + * 1.2.beta0 24 Nov 2002 + * - First version -- complete rewrite of inflate to simplify code, avoid + * creation of window when not needed, minimize use of window when it is + * needed, make inffast.c even faster, implement gzip decoding, and to + * improve code readability and style over the previous zlib inflate code + * + * 1.2.beta1 25 Nov 2002 + * - Use pointers for available input and output checking in inffast.c + * - Remove input and output counters in inffast.c + * - Change inffast.c entry and loop from avail_in >= 7 to >= 6 + * - Remove unnecessary second byte pull from length extra in inffast.c + * - Unroll direct copy to three copies per loop in inffast.c + * + * 1.2.beta2 4 Dec 2002 + * - Change external routine names to reduce potential conflicts + * - Correct filename to inffixed.h for fixed tables in inflate.c + * - Make hbuf[] unsigned char to match parameter type in inflate.c + * - Change strm->next_out[-state->offset] to *(strm->next_out - state->offset) + * to avoid negation problem on Alphas (64 bit) in inflate.c + * + * 1.2.beta3 22 Dec 2002 + * - Add comments on state->bits assertion in inffast.c + * - Add comments on op field in inftrees.h + * - Fix bug in reuse of allocated window after inflateReset() + * - Remove bit fields--back to byte structure for speed + * - Remove distance extra == 0 check in inflate_fast()--only helps for lengths + * - Change post-increments to pre-increments in inflate_fast(), PPC biased? + * - Add compile time option, POSTINC, to use post-increments instead (Intel?) + * - Make MATCH copy in inflate() much faster for when inflate_fast() not used + * - Use local copies of stream next and avail values, as well as local bit + * buffer and bit count in inflate()--for speed when inflate_fast() not used + * + * 1.2.beta4 1 Jan 2003 + * - Split ptr - 257 statements in inflate_table() to avoid compiler warnings + * - Move a comment on output buffer sizes from inffast.c to inflate.c + * - Add comments in inffast.c to introduce the inflate_fast() routine + * - Rearrange window copies in inflate_fast() for speed and simplification + * - Unroll last copy for window match in inflate_fast() + * - Use local copies of window variables in inflate_fast() for speed + * - Pull out common wnext == 0 case for speed in inflate_fast() + * - Make op and len in inflate_fast() unsigned for consistency + * - Add FAR to lcode and dcode declarations in inflate_fast() + * - Simplified bad distance check in inflate_fast() + * - Added inflateBackInit(), inflateBack(), and inflateBackEnd() in new + * source file infback.c to provide a call-back interface to inflate for + * programs like gzip and unzip -- uses window as output buffer to avoid + * window copying + * + * 1.2.beta5 1 Jan 2003 + * - Improved inflateBack() interface to allow the caller to provide initial + * input in strm. + * - Fixed stored blocks bug in inflateBack() + * + * 1.2.beta6 4 Jan 2003 + * - Added comments in inffast.c on effectiveness of POSTINC + * - Typecasting all around to reduce compiler warnings + * - Changed loops from while (1) or do {} while (1) to for (;;), again to + * make compilers happy + * - Changed type of window in inflateBackInit() to unsigned char * + * + * 1.2.beta7 27 Jan 2003 + * - Changed many types to unsigned or unsigned short to avoid warnings + * - Added inflateCopy() function + * + * 1.2.0 9 Mar 2003 + * - Changed inflateBack() interface to provide separate opaque descriptors + * for the in() and out() functions + * - Changed inflateBack() argument and in_func typedef to swap the length + * and buffer address return values for the input function + * - Check next_in and next_out for Z_NULL on entry to inflate() + * + * The history for versions after 1.2.0 are in ChangeLog in zlib distribution. + */ + +#include "zutil.h" +#include "inftrees.h" +#include "inflate.h" +#include "inffast.h" + +#ifdef MAKEFIXED +# ifndef BUILDFIXED +# define BUILDFIXED +# endif +#endif + +/* function prototypes */ +local int inflateStateCheck OF((z_streamp strm)); +local void fixedtables OF((struct inflate_state FAR *state)); +local int updatewindow OF((z_streamp strm, const unsigned char FAR *end, + unsigned copy)); +#ifdef BUILDFIXED + void makefixed OF((void)); +#endif +local unsigned syncsearch OF((unsigned FAR *have, const unsigned char FAR *buf, + unsigned len)); + +local int inflateStateCheck(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (strm == Z_NULL || + strm->zalloc == (alloc_func)0 || strm->zfree == (free_func)0) + return 1; + state = (struct inflate_state FAR *)strm->state; + if (state == Z_NULL || state->strm != strm || + state->mode < HEAD || state->mode > SYNC) + return 1; + return 0; +} + +int ZEXPORT inflateResetKeep(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + strm->total_in = strm->total_out = state->total = 0; + strm->msg = Z_NULL; + if (state->wrap) /* to support ill-conceived Java test suite */ + strm->adler = state->wrap & 1; + state->mode = HEAD; + state->last = 0; + state->havedict = 0; + state->dmax = 32768U; + state->head = Z_NULL; + state->hold = 0; + state->bits = 0; + state->lencode = state->distcode = state->next = state->codes; + state->sane = 1; + state->back = -1; + Tracev((stderr, "inflate: reset\n")); + return Z_OK; +} + +int ZEXPORT inflateReset(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + state->wsize = 0; + state->whave = 0; + state->wnext = 0; + return inflateResetKeep(strm); +} + +int ZEXPORT inflateReset2(strm, windowBits) +z_streamp strm; +int windowBits; +{ + int wrap; + struct inflate_state FAR *state; + + /* get the state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* extract wrap request from windowBits parameter */ + if (windowBits < 0) { + wrap = 0; + windowBits = -windowBits; + } + else { + wrap = (windowBits >> 4) + 5; +#ifdef GUNZIP + if (windowBits < 48) + windowBits &= 15; +#endif + } + + /* set number of window bits, free window if different */ + if (windowBits && (windowBits < 8 || windowBits > 15)) + return Z_STREAM_ERROR; + if (state->window != Z_NULL && state->wbits != (unsigned)windowBits) { + ZFREE(strm, state->window); + state->window = Z_NULL; + } + + /* update state and reset the rest of it */ + state->wrap = wrap; + state->wbits = (unsigned)windowBits; + return inflateReset(strm); +} + +int ZEXPORT inflateInit2_(strm, windowBits, version, stream_size) +z_streamp strm; +int windowBits; +const char *version; +int stream_size; +{ + int ret; + struct inflate_state FAR *state; + + if (version == Z_NULL || version[0] != ZLIB_VERSION[0] || + stream_size != (int)(sizeof(z_stream))) + return Z_VERSION_ERROR; + if (strm == Z_NULL) return Z_STREAM_ERROR; + strm->msg = Z_NULL; /* in case we return an error */ + if (strm->zalloc == (alloc_func)0) { +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zalloc = zcalloc; + strm->opaque = (voidpf)0; +#endif + } + if (strm->zfree == (free_func)0) +#ifdef Z_SOLO + return Z_STREAM_ERROR; +#else + strm->zfree = zcfree; +#endif + state = (struct inflate_state FAR *) + ZALLOC(strm, 1, sizeof(struct inflate_state)); + if (state == Z_NULL) return Z_MEM_ERROR; + Tracev((stderr, "inflate: allocated\n")); + strm->state = (struct internal_state FAR *)state; + state->strm = strm; + state->window = Z_NULL; + state->mode = HEAD; /* to pass state test in inflateReset2() */ + ret = inflateReset2(strm, windowBits); + if (ret != Z_OK) { + ZFREE(strm, state); + strm->state = Z_NULL; + } + return ret; +} + +int ZEXPORT inflateInit_(strm, version, stream_size) +z_streamp strm; +const char *version; +int stream_size; +{ + return inflateInit2_(strm, DEF_WBITS, version, stream_size); +} + +int ZEXPORT inflatePrime(strm, bits, value) +z_streamp strm; +int bits; +int value; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (bits < 0) { + state->hold = 0; + state->bits = 0; + return Z_OK; + } + if (bits > 16 || state->bits + (uInt)bits > 32) return Z_STREAM_ERROR; + value &= (1L << bits) - 1; + state->hold += (unsigned)value << state->bits; + state->bits += (uInt)bits; + return Z_OK; +} + +/* + Return state with length and distance decoding tables and index sizes set to + fixed code decoding. Normally this returns fixed tables from inffixed.h. + If BUILDFIXED is defined, then instead this routine builds the tables the + first time it's called, and returns those tables the first time and + thereafter. This reduces the size of the code by about 2K bytes, in + exchange for a little execution time. However, BUILDFIXED should not be + used for threaded applications, since the rewriting of the tables and virgin + may not be thread-safe. + */ +local void fixedtables(state) +struct inflate_state FAR *state; +{ +#ifdef BUILDFIXED + static int virgin = 1; + static code *lenfix, *distfix; + static code fixed[544]; + + /* build fixed huffman tables if first call (may not be thread safe) */ + if (virgin) { + unsigned sym, bits; + static code *next; + + /* literal/length table */ + sym = 0; + while (sym < 144) state->lens[sym++] = 8; + while (sym < 256) state->lens[sym++] = 9; + while (sym < 280) state->lens[sym++] = 7; + while (sym < 288) state->lens[sym++] = 8; + next = fixed; + lenfix = next; + bits = 9; + inflate_table(LENS, state->lens, 288, &(next), &(bits), state->work); + + /* distance table */ + sym = 0; + while (sym < 32) state->lens[sym++] = 5; + distfix = next; + bits = 5; + inflate_table(DISTS, state->lens, 32, &(next), &(bits), state->work); + + /* do this just once */ + virgin = 0; + } +#else /* !BUILDFIXED */ +# include "inffixed.h" +#endif /* BUILDFIXED */ + state->lencode = lenfix; + state->lenbits = 9; + state->distcode = distfix; + state->distbits = 5; +} + +#ifdef MAKEFIXED +#include + +/* + Write out the inffixed.h that is #include'd above. Defining MAKEFIXED also + defines BUILDFIXED, so the tables are built on the fly. makefixed() writes + those tables to stdout, which would be piped to inffixed.h. A small program + can simply call makefixed to do this: + + void makefixed(void); + + int main(void) + { + makefixed(); + return 0; + } + + Then that can be linked with zlib built with MAKEFIXED defined and run: + + a.out > inffixed.h + */ +void makefixed() +{ + unsigned low, size; + struct inflate_state state; + + fixedtables(&state); + puts(" /* inffixed.h -- table for decoding fixed codes"); + puts(" * Generated automatically by makefixed()."); + puts(" */"); + puts(""); + puts(" /* WARNING: this file should *not* be used by applications."); + puts(" It is part of the implementation of this library and is"); + puts(" subject to change. Applications should only use zlib.h."); + puts(" */"); + puts(""); + size = 1U << 9; + printf(" static const code lenfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 7) == 0) printf("\n "); + printf("{%u,%u,%d}", (low & 127) == 99 ? 64 : state.lencode[low].op, + state.lencode[low].bits, state.lencode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); + size = 1U << 5; + printf("\n static const code distfix[%u] = {", size); + low = 0; + for (;;) { + if ((low % 6) == 0) printf("\n "); + printf("{%u,%u,%d}", state.distcode[low].op, state.distcode[low].bits, + state.distcode[low].val); + if (++low == size) break; + putchar(','); + } + puts("\n };"); +} +#endif /* MAKEFIXED */ + +/* + Update the window with the last wsize (normally 32K) bytes written before + returning. If window does not exist yet, create it. This is only called + when a window is already in use, or when output has been written during this + inflate call, but the end of the deflate stream has not been reached yet. + It is also called to create a window for dictionary data when a dictionary + is loaded. + + Providing output buffers larger than 32K to inflate() should provide a speed + advantage, since only the last 32K of output is copied to the sliding window + upon return from inflate(), and since all distances after the first 32K of + output will fall in the output data, making match copies simpler and faster. + The advantage may be dependent on the size of the processor's data caches. + */ +local int updatewindow(strm, end, copy) +z_streamp strm; +const Bytef *end; +unsigned copy; +{ + struct inflate_state FAR *state; + unsigned dist; + + state = (struct inflate_state FAR *)strm->state; + + /* if it hasn't been done already, allocate space for the window */ + if (state->window == Z_NULL) { + state->window = (unsigned char FAR *) + ZALLOC(strm, 1U << state->wbits, + sizeof(unsigned char)); + if (state->window == Z_NULL) return 1; + } + + /* if window not in use yet, initialize */ + if (state->wsize == 0) { + state->wsize = 1U << state->wbits; + state->wnext = 0; + state->whave = 0; + } + + /* copy state->wsize or less output bytes into the circular window */ + if (copy >= state->wsize) { + zmemcpy(state->window, end - state->wsize, state->wsize); + state->wnext = 0; + state->whave = state->wsize; + } + else { + dist = state->wsize - state->wnext; + if (dist > copy) dist = copy; + zmemcpy(state->window + state->wnext, end - copy, dist); + copy -= dist; + if (copy) { + zmemcpy(state->window, end - copy, copy); + state->wnext = copy; + state->whave = state->wsize; + } + else { + state->wnext += dist; + if (state->wnext == state->wsize) state->wnext = 0; + if (state->whave < state->wsize) state->whave += dist; + } + } + return 0; +} + +/* Macros for inflate(): */ + +/* check function to use adler32() for zlib or crc32() for gzip */ +#ifdef GUNZIP +# define UPDATE(check, buf, len) \ + (state->flags ? crc32(check, buf, len) : adler32(check, buf, len)) +#else +# define UPDATE(check, buf, len) adler32(check, buf, len) +#endif + +/* check macros for header crc */ +#ifdef GUNZIP +# define CRC2(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + check = crc32(check, hbuf, 2); \ + } while (0) + +# define CRC4(check, word) \ + do { \ + hbuf[0] = (unsigned char)(word); \ + hbuf[1] = (unsigned char)((word) >> 8); \ + hbuf[2] = (unsigned char)((word) >> 16); \ + hbuf[3] = (unsigned char)((word) >> 24); \ + check = crc32(check, hbuf, 4); \ + } while (0) +#endif + +/* Load registers with state in inflate() for speed */ +#define LOAD() \ + do { \ + put = strm->next_out; \ + left = strm->avail_out; \ + next = strm->next_in; \ + have = strm->avail_in; \ + hold = state->hold; \ + bits = state->bits; \ + } while (0) + +/* Restore state from registers in inflate() */ +#define RESTORE() \ + do { \ + strm->next_out = put; \ + strm->avail_out = left; \ + strm->next_in = next; \ + strm->avail_in = have; \ + state->hold = hold; \ + state->bits = bits; \ + } while (0) + +/* Clear the input bit accumulator */ +#define INITBITS() \ + do { \ + hold = 0; \ + bits = 0; \ + } while (0) + +/* Get a byte of input into the bit accumulator, or return from inflate() + if there is no input available. */ +#define PULLBYTE() \ + do { \ + if (have == 0) goto inf_leave; \ + have--; \ + hold += (unsigned long)(*next++) << bits; \ + bits += 8; \ + } while (0) + +/* Assure that there are at least n bits in the bit accumulator. If there is + not enough available input to do that, then return from inflate(). */ +#define NEEDBITS(n) \ + do { \ + while (bits < (unsigned)(n)) \ + PULLBYTE(); \ + } while (0) + +/* Return the low n bits of the bit accumulator (n < 16) */ +#define BITS(n) \ + ((unsigned)hold & ((1U << (n)) - 1)) + +/* Remove n bits from the bit accumulator */ +#define DROPBITS(n) \ + do { \ + hold >>= (n); \ + bits -= (unsigned)(n); \ + } while (0) + +/* Remove zero to seven bits as needed to go to a byte boundary */ +#define BYTEBITS() \ + do { \ + hold >>= bits & 7; \ + bits -= bits & 7; \ + } while (0) + +/* + inflate() uses a state machine to process as much input data and generate as + much output data as possible before returning. The state machine is + structured roughly as follows: + + for (;;) switch (state) { + ... + case STATEn: + if (not enough input data or output space to make progress) + return; + ... make progress ... + state = STATEm; + break; + ... + } + + so when inflate() is called again, the same case is attempted again, and + if the appropriate resources are provided, the machine proceeds to the + next state. The NEEDBITS() macro is usually the way the state evaluates + whether it can proceed or should return. NEEDBITS() does the return if + the requested bits are not available. The typical use of the BITS macros + is: + + NEEDBITS(n); + ... do something with BITS(n) ... + DROPBITS(n); + + where NEEDBITS(n) either returns from inflate() if there isn't enough + input left to load n bits into the accumulator, or it continues. BITS(n) + gives the low n bits in the accumulator. When done, DROPBITS(n) drops + the low n bits off the accumulator. INITBITS() clears the accumulator + and sets the number of available bits to zero. BYTEBITS() discards just + enough bits to put the accumulator on a byte boundary. After BYTEBITS() + and a NEEDBITS(8), then BITS(8) would return the next byte in the stream. + + NEEDBITS(n) uses PULLBYTE() to get an available byte of input, or to return + if there is no input available. The decoding of variable length codes uses + PULLBYTE() directly in order to pull just enough bytes to decode the next + code, and no more. + + Some states loop until they get enough input, making sure that enough + state information is maintained to continue the loop where it left off + if NEEDBITS() returns in the loop. For example, want, need, and keep + would all have to actually be part of the saved state in case NEEDBITS() + returns: + + case STATEw: + while (want < need) { + NEEDBITS(n); + keep[want++] = BITS(n); + DROPBITS(n); + } + state = STATEx; + case STATEx: + + As shown above, if the next state is also the next case, then the break + is omitted. + + A state may also return if there is not enough output space available to + complete that state. Those states are copying stored data, writing a + literal byte, and copying a matching string. + + When returning, a "goto inf_leave" is used to update the total counters, + update the check value, and determine whether any progress has been made + during that inflate() call in order to return the proper return code. + Progress is defined as a change in either strm->avail_in or strm->avail_out. + When there is a window, goto inf_leave will update the window with the last + output written. If a goto inf_leave occurs in the middle of decompression + and there is no window currently, goto inf_leave will create one and copy + output to the window for the next call of inflate(). + + In this implementation, the flush parameter of inflate() only affects the + return code (per zlib.h). inflate() always writes as much as possible to + strm->next_out, given the space available and the provided input--the effect + documented in zlib.h of Z_SYNC_FLUSH. Furthermore, inflate() always defers + the allocation of and copying into a sliding window until necessary, which + provides the effect documented in zlib.h for Z_FINISH when the entire input + stream available. So the only thing the flush parameter actually does is: + when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it + will return Z_BUF_ERROR if it has not reached the end of the stream. + */ + +int ZEXPORT inflate(strm, flush) +z_streamp strm; +int flush; +{ + struct inflate_state FAR *state; + z_const unsigned char FAR *next; /* next input */ + unsigned char FAR *put; /* next output */ + unsigned have, left; /* available input and output */ + unsigned long hold; /* bit buffer */ + unsigned bits; /* bits in bit buffer */ + unsigned in, out; /* save starting available input and output */ + unsigned copy; /* number of stored or match bytes to copy */ + unsigned char FAR *from; /* where to copy match bytes from */ + code here; /* current decoding table entry */ + code last; /* parent table entry */ + unsigned len; /* length to copy for repeats, bits to drop */ + int ret; /* return code */ +#ifdef GUNZIP + unsigned char hbuf[4]; /* buffer for gzip header crc calculation */ +#endif + static const unsigned short order[19] = /* permutation of code lengths */ + {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15}; + + if (inflateStateCheck(strm) || strm->next_out == Z_NULL || + (strm->next_in == Z_NULL && strm->avail_in != 0)) + return Z_STREAM_ERROR; + + state = (struct inflate_state FAR *)strm->state; + if (state->mode == TYPE) state->mode = TYPEDO; /* skip check */ + LOAD(); + in = have; + out = left; + ret = Z_OK; + for (;;) + switch (state->mode) { + case HEAD: + if (state->wrap == 0) { + state->mode = TYPEDO; + break; + } + NEEDBITS(16); +#ifdef GUNZIP + if ((state->wrap & 2) && hold == 0x8b1f) { /* gzip header */ + if (state->wbits == 0) + state->wbits = 15; + state->check = crc32(0L, Z_NULL, 0); + CRC2(state->check, hold); + INITBITS(); + state->mode = FLAGS; + break; + } + state->flags = 0; /* expect zlib header */ + if (state->head != Z_NULL) + state->head->done = -1; + if (!(state->wrap & 1) || /* check if zlib header allowed */ +#else + if ( +#endif + ((BITS(8) << 8) + (hold >> 8)) % 31) { + strm->msg = (char *)"incorrect header check"; + state->mode = BAD; + break; + } + if (BITS(4) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + DROPBITS(4); + len = BITS(4) + 8; + if (state->wbits == 0) + state->wbits = len; + if (len > 15 || len > state->wbits) { + strm->msg = (char *)"invalid window size"; + state->mode = BAD; + break; + } + state->dmax = 1U << len; + Tracev((stderr, "inflate: zlib header ok\n")); + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = hold & 0x200 ? DICTID : TYPE; + INITBITS(); + break; +#ifdef GUNZIP + case FLAGS: + NEEDBITS(16); + state->flags = (int)(hold); + if ((state->flags & 0xff) != Z_DEFLATED) { + strm->msg = (char *)"unknown compression method"; + state->mode = BAD; + break; + } + if (state->flags & 0xe000) { + strm->msg = (char *)"unknown header flags set"; + state->mode = BAD; + break; + } + if (state->head != Z_NULL) + state->head->text = (int)((hold >> 8) & 1); + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = TIME; + case TIME: + NEEDBITS(32); + if (state->head != Z_NULL) + state->head->time = hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC4(state->check, hold); + INITBITS(); + state->mode = OS; + case OS: + NEEDBITS(16); + if (state->head != Z_NULL) { + state->head->xflags = (int)(hold & 0xff); + state->head->os = (int)(hold >> 8); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + state->mode = EXLEN; + case EXLEN: + if (state->flags & 0x0400) { + NEEDBITS(16); + state->length = (unsigned)(hold); + if (state->head != Z_NULL) + state->head->extra_len = (unsigned)hold; + if ((state->flags & 0x0200) && (state->wrap & 4)) + CRC2(state->check, hold); + INITBITS(); + } + else if (state->head != Z_NULL) + state->head->extra = Z_NULL; + state->mode = EXTRA; + case EXTRA: + if (state->flags & 0x0400) { + copy = state->length; + if (copy > have) copy = have; + if (copy) { + if (state->head != Z_NULL && + state->head->extra != Z_NULL) { + len = state->head->extra_len - state->length; + zmemcpy(state->head->extra + len, next, + len + copy > state->head->extra_max ? + state->head->extra_max - len : copy); + } + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + state->length -= copy; + } + if (state->length) goto inf_leave; + } + state->length = 0; + state->mode = NAME; + case NAME: + if (state->flags & 0x0800) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->name != Z_NULL && + state->length < state->head->name_max) + state->head->name[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->name = Z_NULL; + state->length = 0; + state->mode = COMMENT; + case COMMENT: + if (state->flags & 0x1000) { + if (have == 0) goto inf_leave; + copy = 0; + do { + len = (unsigned)(next[copy++]); + if (state->head != Z_NULL && + state->head->comment != Z_NULL && + state->length < state->head->comm_max) + state->head->comment[state->length++] = (Bytef)len; + } while (len && copy < have); + if ((state->flags & 0x0200) && (state->wrap & 4)) + state->check = crc32(state->check, next, copy); + have -= copy; + next += copy; + if (len) goto inf_leave; + } + else if (state->head != Z_NULL) + state->head->comment = Z_NULL; + state->mode = HCRC; + case HCRC: + if (state->flags & 0x0200) { + NEEDBITS(16); + if ((state->wrap & 4) && hold != (state->check & 0xffff)) { + strm->msg = (char *)"header crc mismatch"; + state->mode = BAD; + break; + } + INITBITS(); + } + if (state->head != Z_NULL) { + state->head->hcrc = (int)((state->flags >> 9) & 1); + state->head->done = 1; + } + strm->adler = state->check = crc32(0L, Z_NULL, 0); + state->mode = TYPE; + break; +#endif + case DICTID: + NEEDBITS(32); + strm->adler = state->check = ZSWAP32(hold); + INITBITS(); + state->mode = DICT; + case DICT: + if (state->havedict == 0) { + RESTORE(); + return Z_NEED_DICT; + } + strm->adler = state->check = adler32(0L, Z_NULL, 0); + state->mode = TYPE; + case TYPE: + if (flush == Z_BLOCK || flush == Z_TREES) goto inf_leave; + case TYPEDO: + if (state->last) { + BYTEBITS(); + state->mode = CHECK; + break; + } + NEEDBITS(3); + state->last = BITS(1); + DROPBITS(1); + switch (BITS(2)) { + case 0: /* stored block */ + Tracev((stderr, "inflate: stored block%s\n", + state->last ? " (last)" : "")); + state->mode = STORED; + break; + case 1: /* fixed block */ + fixedtables(state); + Tracev((stderr, "inflate: fixed codes block%s\n", + state->last ? " (last)" : "")); + state->mode = LEN_; /* decode codes */ + if (flush == Z_TREES) { + DROPBITS(2); + goto inf_leave; + } + break; + case 2: /* dynamic block */ + Tracev((stderr, "inflate: dynamic codes block%s\n", + state->last ? " (last)" : "")); + state->mode = TABLE; + break; + case 3: + strm->msg = (char *)"invalid block type"; + state->mode = BAD; + } + DROPBITS(2); + break; + case STORED: + BYTEBITS(); /* go to byte boundary */ + NEEDBITS(32); + if ((hold & 0xffff) != ((hold >> 16) ^ 0xffff)) { + strm->msg = (char *)"invalid stored block lengths"; + state->mode = BAD; + break; + } + state->length = (unsigned)hold & 0xffff; + Tracev((stderr, "inflate: stored length %u\n", + state->length)); + INITBITS(); + state->mode = COPY_; + if (flush == Z_TREES) goto inf_leave; + case COPY_: + state->mode = COPY; + case COPY: + copy = state->length; + if (copy) { + if (copy > have) copy = have; + if (copy > left) copy = left; + if (copy == 0) goto inf_leave; + zmemcpy(put, next, copy); + have -= copy; + next += copy; + left -= copy; + put += copy; + state->length -= copy; + break; + } + Tracev((stderr, "inflate: stored end\n")); + state->mode = TYPE; + break; + case TABLE: + NEEDBITS(14); + state->nlen = BITS(5) + 257; + DROPBITS(5); + state->ndist = BITS(5) + 1; + DROPBITS(5); + state->ncode = BITS(4) + 4; + DROPBITS(4); +#ifndef PKZIP_BUG_WORKAROUND + if (state->nlen > 286 || state->ndist > 30) { + strm->msg = (char *)"too many length or distance symbols"; + state->mode = BAD; + break; + } +#endif + Tracev((stderr, "inflate: table sizes ok\n")); + state->have = 0; + state->mode = LENLENS; + case LENLENS: + while (state->have < state->ncode) { + NEEDBITS(3); + state->lens[order[state->have++]] = (unsigned short)BITS(3); + DROPBITS(3); + } + while (state->have < 19) + state->lens[order[state->have++]] = 0; + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 7; + ret = inflate_table(CODES, state->lens, 19, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid code lengths set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: code lengths ok\n")); + state->have = 0; + state->mode = CODELENS; + case CODELENS: + while (state->have < state->nlen + state->ndist) { + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.val < 16) { + DROPBITS(here.bits); + state->lens[state->have++] = here.val; + } + else { + if (here.val == 16) { + NEEDBITS(here.bits + 2); + DROPBITS(here.bits); + if (state->have == 0) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + len = state->lens[state->have - 1]; + copy = 3 + BITS(2); + DROPBITS(2); + } + else if (here.val == 17) { + NEEDBITS(here.bits + 3); + DROPBITS(here.bits); + len = 0; + copy = 3 + BITS(3); + DROPBITS(3); + } + else { + NEEDBITS(here.bits + 7); + DROPBITS(here.bits); + len = 0; + copy = 11 + BITS(7); + DROPBITS(7); + } + if (state->have + copy > state->nlen + state->ndist) { + strm->msg = (char *)"invalid bit length repeat"; + state->mode = BAD; + break; + } + while (copy--) + state->lens[state->have++] = (unsigned short)len; + } + } + + /* handle error breaks in while */ + if (state->mode == BAD) break; + + /* check for end-of-block code (better have one) */ + if (state->lens[256] == 0) { + strm->msg = (char *)"invalid code -- missing end-of-block"; + state->mode = BAD; + break; + } + + /* build code tables -- note: do not change the lenbits or distbits + values here (9 and 6) without reading the comments in inftrees.h + concerning the ENOUGH constants, which depend on those values */ + state->next = state->codes; + state->lencode = (const code FAR *)(state->next); + state->lenbits = 9; + ret = inflate_table(LENS, state->lens, state->nlen, &(state->next), + &(state->lenbits), state->work); + if (ret) { + strm->msg = (char *)"invalid literal/lengths set"; + state->mode = BAD; + break; + } + state->distcode = (const code FAR *)(state->next); + state->distbits = 6; + ret = inflate_table(DISTS, state->lens + state->nlen, state->ndist, + &(state->next), &(state->distbits), state->work); + if (ret) { + strm->msg = (char *)"invalid distances set"; + state->mode = BAD; + break; + } + Tracev((stderr, "inflate: codes ok\n")); + state->mode = LEN_; + if (flush == Z_TREES) goto inf_leave; + case LEN_: + state->mode = LEN; + case LEN: + if (have >= 6 && left >= 258) { + RESTORE(); + inflate_fast(strm, out); + LOAD(); + if (state->mode == TYPE) + state->back = -1; + break; + } + state->back = 0; + for (;;) { + here = state->lencode[BITS(state->lenbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if (here.op && (here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->lencode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + state->length = (unsigned)here.val; + if ((int)(here.op) == 0) { + Tracevv((stderr, here.val >= 0x20 && here.val < 0x7f ? + "inflate: literal '%c'\n" : + "inflate: literal 0x%02x\n", here.val)); + state->mode = LIT; + break; + } + if (here.op & 32) { + Tracevv((stderr, "inflate: end of block\n")); + state->back = -1; + state->mode = TYPE; + break; + } + if (here.op & 64) { + strm->msg = (char *)"invalid literal/length code"; + state->mode = BAD; + break; + } + state->extra = (unsigned)(here.op) & 15; + state->mode = LENEXT; + case LENEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->length += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } + Tracevv((stderr, "inflate: length %u\n", state->length)); + state->was = state->length; + state->mode = DIST; + case DIST: + for (;;) { + here = state->distcode[BITS(state->distbits)]; + if ((unsigned)(here.bits) <= bits) break; + PULLBYTE(); + } + if ((here.op & 0xf0) == 0) { + last = here; + for (;;) { + here = state->distcode[last.val + + (BITS(last.bits + last.op) >> last.bits)]; + if ((unsigned)(last.bits + here.bits) <= bits) break; + PULLBYTE(); + } + DROPBITS(last.bits); + state->back += last.bits; + } + DROPBITS(here.bits); + state->back += here.bits; + if (here.op & 64) { + strm->msg = (char *)"invalid distance code"; + state->mode = BAD; + break; + } + state->offset = (unsigned)here.val; + state->extra = (unsigned)(here.op) & 15; + state->mode = DISTEXT; + case DISTEXT: + if (state->extra) { + NEEDBITS(state->extra); + state->offset += BITS(state->extra); + DROPBITS(state->extra); + state->back += state->extra; + } +#ifdef INFLATE_STRICT + if (state->offset > state->dmax) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#endif + Tracevv((stderr, "inflate: distance %u\n", state->offset)); + state->mode = MATCH; + case MATCH: + if (left == 0) goto inf_leave; + copy = out - left; + if (state->offset > copy) { /* copy from window */ + copy = state->offset - copy; + if (copy > state->whave) { + if (state->sane) { + strm->msg = (char *)"invalid distance too far back"; + state->mode = BAD; + break; + } +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + Trace((stderr, "inflate.c too far\n")); + copy -= state->whave; + if (copy > state->length) copy = state->length; + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = 0; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; +#endif + } + if (copy > state->wnext) { + copy -= state->wnext; + from = state->window + (state->wsize - copy); + } + else + from = state->window + (state->wnext - copy); + if (copy > state->length) copy = state->length; + } + else { /* copy from output */ + from = put - state->offset; + copy = state->length; + } + if (copy > left) copy = left; + left -= copy; + state->length -= copy; + do { + *put++ = *from++; + } while (--copy); + if (state->length == 0) state->mode = LEN; + break; + case LIT: + if (left == 0) goto inf_leave; + *put++ = (unsigned char)(state->length); + left--; + state->mode = LEN; + break; + case CHECK: + if (state->wrap) { + NEEDBITS(32); + out -= left; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, put - out, out); + out = left; + if ((state->wrap & 4) && ( +#ifdef GUNZIP + state->flags ? hold : +#endif + ZSWAP32(hold)) != state->check) { + strm->msg = (char *)"incorrect data check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: check matches trailer\n")); + } +#ifdef GUNZIP + state->mode = LENGTH; + case LENGTH: + if (state->wrap && state->flags) { + NEEDBITS(32); + if (hold != (state->total & 0xffffffffUL)) { + strm->msg = (char *)"incorrect length check"; + state->mode = BAD; + break; + } + INITBITS(); + Tracev((stderr, "inflate: length matches trailer\n")); + } +#endif + state->mode = DONE; + case DONE: + ret = Z_STREAM_END; + goto inf_leave; + case BAD: + ret = Z_DATA_ERROR; + goto inf_leave; + case MEM: + return Z_MEM_ERROR; + case SYNC: + default: + return Z_STREAM_ERROR; + } + + /* + Return from inflate(), updating the total counts and the check value. + If there was no progress during the inflate() call, return a buffer + error. Call updatewindow() to create and/or update the window state. + Note: a memory error from inflate() is non-recoverable. + */ + inf_leave: + RESTORE(); + if (state->wsize || (out != strm->avail_out && state->mode < BAD && + (state->mode < CHECK || flush != Z_FINISH))) + if (updatewindow(strm, strm->next_out, out - strm->avail_out)) { + state->mode = MEM; + return Z_MEM_ERROR; + } + in -= strm->avail_in; + out -= strm->avail_out; + strm->total_in += in; + strm->total_out += out; + state->total += out; + if ((state->wrap & 4) && out) + strm->adler = state->check = + UPDATE(state->check, strm->next_out - out, out); + strm->data_type = (int)state->bits + (state->last ? 64 : 0) + + (state->mode == TYPE ? 128 : 0) + + (state->mode == LEN_ || state->mode == COPY_ ? 256 : 0); + if (((in == 0 && out == 0) || flush == Z_FINISH) && ret == Z_OK) + ret = Z_BUF_ERROR; + return ret; +} + +int ZEXPORT inflateEnd(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->window != Z_NULL) ZFREE(strm, state->window); + ZFREE(strm, strm->state); + strm->state = Z_NULL; + Tracev((stderr, "inflate: end\n")); + return Z_OK; +} + +int ZEXPORT inflateGetDictionary(strm, dictionary, dictLength) +z_streamp strm; +Bytef *dictionary; +uInt *dictLength; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + + /* copy dictionary */ + if (state->whave && dictionary != Z_NULL) { + zmemcpy(dictionary, state->window + state->wnext, + state->whave - state->wnext); + zmemcpy(dictionary + state->whave - state->wnext, + state->window, state->wnext); + } + if (dictLength != Z_NULL) + *dictLength = state->whave; + return Z_OK; +} + +int ZEXPORT inflateSetDictionary(strm, dictionary, dictLength) +z_streamp strm; +const Bytef *dictionary; +uInt dictLength; +{ + struct inflate_state FAR *state; + unsigned long dictid; + int ret; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (state->wrap != 0 && state->mode != DICT) + return Z_STREAM_ERROR; + + /* check for correct dictionary identifier */ + if (state->mode == DICT) { + dictid = adler32(0L, Z_NULL, 0); + dictid = adler32(dictid, dictionary, dictLength); + if (dictid != state->check) + return Z_DATA_ERROR; + } + + /* copy dictionary to window using updatewindow(), which will amend the + existing dictionary if appropriate */ + ret = updatewindow(strm, dictionary + dictLength, dictLength); + if (ret) { + state->mode = MEM; + return Z_MEM_ERROR; + } + state->havedict = 1; + Tracev((stderr, "inflate: dictionary set\n")); + return Z_OK; +} + +int ZEXPORT inflateGetHeader(strm, head) +z_streamp strm; +gz_headerp head; +{ + struct inflate_state FAR *state; + + /* check state */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if ((state->wrap & 2) == 0) return Z_STREAM_ERROR; + + /* save header structure */ + state->head = head; + head->done = 0; + return Z_OK; +} + +/* + Search buf[0..len-1] for the pattern: 0, 0, 0xff, 0xff. Return when found + or when out of input. When called, *have is the number of pattern bytes + found in order so far, in 0..3. On return *have is updated to the new + state. If on return *have equals four, then the pattern was found and the + return value is how many bytes were read including the last byte of the + pattern. If *have is less than four, then the pattern has not been found + yet and the return value is len. In the latter case, syncsearch() can be + called again with more data and the *have state. *have is initialized to + zero for the first call. + */ +local unsigned syncsearch(have, buf, len) +unsigned FAR *have; +const unsigned char FAR *buf; +unsigned len; +{ + unsigned got; + unsigned next; + + got = *have; + next = 0; + while (next < len && got < 4) { + if ((int)(buf[next]) == (got < 2 ? 0 : 0xff)) + got++; + else if (buf[next]) + got = 0; + else + got = 4 - got; + next++; + } + *have = got; + return next; +} + +int ZEXPORT inflateSync(strm) +z_streamp strm; +{ + unsigned len; /* number of bytes to look at or looked at */ + unsigned long in, out; /* temporary to save total_in and total_out */ + unsigned char buf[4]; /* to restore bit buffer to byte string */ + struct inflate_state FAR *state; + + /* check parameters */ + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (strm->avail_in == 0 && state->bits < 8) return Z_BUF_ERROR; + + /* if first time, start search in bit buffer */ + if (state->mode != SYNC) { + state->mode = SYNC; + state->hold <<= state->bits & 7; + state->bits -= state->bits & 7; + len = 0; + while (state->bits >= 8) { + buf[len++] = (unsigned char)(state->hold); + state->hold >>= 8; + state->bits -= 8; + } + state->have = 0; + syncsearch(&(state->have), buf, len); + } + + /* search available input */ + len = syncsearch(&(state->have), strm->next_in, strm->avail_in); + strm->avail_in -= len; + strm->next_in += len; + strm->total_in += len; + + /* return no joy or set up to restart inflate() on a new block */ + if (state->have != 4) return Z_DATA_ERROR; + in = strm->total_in; out = strm->total_out; + inflateReset(strm); + strm->total_in = in; strm->total_out = out; + state->mode = TYPE; + return Z_OK; +} + +/* + Returns true if inflate is currently at the end of a block generated by + Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP + implementation to provide an additional safety check. PPP uses + Z_SYNC_FLUSH but removes the length bytes of the resulting empty stored + block. When decompressing, PPP checks that at the end of input packet, + inflate is waiting for these length bytes. + */ +int ZEXPORT inflateSyncPoint(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + return state->mode == STORED && state->bits == 0; +} + +int ZEXPORT inflateCopy(dest, source) +z_streamp dest; +z_streamp source; +{ + struct inflate_state FAR *state; + struct inflate_state FAR *copy; + unsigned char FAR *window; + unsigned wsize; + + /* check input */ + if (inflateStateCheck(source) || dest == Z_NULL) + return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)source->state; + + /* allocate space */ + copy = (struct inflate_state FAR *) + ZALLOC(source, 1, sizeof(struct inflate_state)); + if (copy == Z_NULL) return Z_MEM_ERROR; + window = Z_NULL; + if (state->window != Z_NULL) { + window = (unsigned char FAR *) + ZALLOC(source, 1U << state->wbits, sizeof(unsigned char)); + if (window == Z_NULL) { + ZFREE(source, copy); + return Z_MEM_ERROR; + } + } + + /* copy state */ + zmemcpy((voidpf)dest, (voidpf)source, sizeof(z_stream)); + zmemcpy((voidpf)copy, (voidpf)state, sizeof(struct inflate_state)); + copy->strm = dest; + if (state->lencode >= state->codes && + state->lencode <= state->codes + ENOUGH - 1) { + copy->lencode = copy->codes + (state->lencode - state->codes); + copy->distcode = copy->codes + (state->distcode - state->codes); + } + copy->next = copy->codes + (state->next - state->codes); + if (window != Z_NULL) { + wsize = 1U << state->wbits; + zmemcpy(window, state->window, wsize); + } + copy->window = window; + dest->state = (struct internal_state FAR *)copy; + return Z_OK; +} + +int ZEXPORT inflateUndermine(strm, subvert) +z_streamp strm; +int subvert; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; +#ifdef INFLATE_ALLOW_INVALID_DISTANCE_TOOFAR_ARRR + state->sane = !subvert; + return Z_OK; +#else + (void)subvert; + state->sane = 1; + return Z_DATA_ERROR; +#endif +} + +int ZEXPORT inflateValidate(strm, check) +z_streamp strm; +int check; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) return Z_STREAM_ERROR; + state = (struct inflate_state FAR *)strm->state; + if (check) + state->wrap |= 4; + else + state->wrap &= ~4; + return Z_OK; +} + +long ZEXPORT inflateMark(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + + if (inflateStateCheck(strm)) + return -(1L << 16); + state = (struct inflate_state FAR *)strm->state; + return (long)(((unsigned long)((long)state->back)) << 16) + + (state->mode == COPY ? state->length : + (state->mode == MATCH ? state->was - state->length : 0)); +} + +unsigned long ZEXPORT inflateCodesUsed(strm) +z_streamp strm; +{ + struct inflate_state FAR *state; + if (inflateStateCheck(strm)) return (unsigned long)-1; + state = (struct inflate_state FAR *)strm->state; + return (unsigned long)(state->next - state->codes); +} diff --git a/arm-trusted-firmware/lib/zlib/inflate.h b/arm-trusted-firmware/lib/zlib/inflate.h new file mode 100644 index 0000000..a46cce6 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inflate.h @@ -0,0 +1,125 @@ +/* inflate.h -- internal inflate state definition + * Copyright (C) 1995-2016 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* define NO_GZIP when compiling if you want to disable gzip header and + trailer decoding by inflate(). NO_GZIP would be used to avoid linking in + the crc code when it is not needed. For shared libraries, gzip decoding + should be left enabled. */ +#ifndef NO_GZIP +# define GUNZIP +#endif + +/* Possible inflate modes between inflate() calls */ +typedef enum { + HEAD = 16180, /* i: waiting for magic header */ + FLAGS, /* i: waiting for method and flags (gzip) */ + TIME, /* i: waiting for modification time (gzip) */ + OS, /* i: waiting for extra flags and operating system (gzip) */ + EXLEN, /* i: waiting for extra length (gzip) */ + EXTRA, /* i: waiting for extra bytes (gzip) */ + NAME, /* i: waiting for end of file name (gzip) */ + COMMENT, /* i: waiting for end of comment (gzip) */ + HCRC, /* i: waiting for header crc (gzip) */ + DICTID, /* i: waiting for dictionary check value */ + DICT, /* waiting for inflateSetDictionary() call */ + TYPE, /* i: waiting for type bits, including last-flag bit */ + TYPEDO, /* i: same, but skip check to exit inflate on new block */ + STORED, /* i: waiting for stored size (length and complement) */ + COPY_, /* i/o: same as COPY below, but only first time in */ + COPY, /* i/o: waiting for input or output to copy stored block */ + TABLE, /* i: waiting for dynamic block table lengths */ + LENLENS, /* i: waiting for code length code lengths */ + CODELENS, /* i: waiting for length/lit and distance code lengths */ + LEN_, /* i: same as LEN below, but only first time in */ + LEN, /* i: waiting for length/lit/eob code */ + LENEXT, /* i: waiting for length extra bits */ + DIST, /* i: waiting for distance code */ + DISTEXT, /* i: waiting for distance extra bits */ + MATCH, /* o: waiting for output space to copy string */ + LIT, /* o: waiting for output space to write literal */ + CHECK, /* i: waiting for 32-bit check value */ + LENGTH, /* i: waiting for 32-bit length (gzip) */ + DONE, /* finished check, done -- remain here until reset */ + BAD, /* got a data error -- remain here until reset */ + MEM, /* got an inflate() memory error -- remain here until reset */ + SYNC /* looking for synchronization bytes to restart inflate() */ +} inflate_mode; + +/* + State transitions between above modes - + + (most modes can go to BAD or MEM on error -- not shown for clarity) + + Process header: + HEAD -> (gzip) or (zlib) or (raw) + (gzip) -> FLAGS -> TIME -> OS -> EXLEN -> EXTRA -> NAME -> COMMENT -> + HCRC -> TYPE + (zlib) -> DICTID or TYPE + DICTID -> DICT -> TYPE + (raw) -> TYPEDO + Read deflate blocks: + TYPE -> TYPEDO -> STORED or TABLE or LEN_ or CHECK + STORED -> COPY_ -> COPY -> TYPE + TABLE -> LENLENS -> CODELENS -> LEN_ + LEN_ -> LEN + Read deflate codes in fixed or dynamic block: + LEN -> LENEXT or LIT or TYPE + LENEXT -> DIST -> DISTEXT -> MATCH -> LEN + LIT -> LEN + Process trailer: + CHECK -> LENGTH -> DONE + */ + +/* State maintained between inflate() calls -- approximately 7K bytes, not + including the allocated sliding window, which is up to 32K bytes. */ +struct inflate_state { + z_streamp strm; /* pointer back to this zlib stream */ + inflate_mode mode; /* current inflate mode */ + int last; /* true if processing last block */ + int wrap; /* bit 0 true for zlib, bit 1 true for gzip, + bit 2 true to validate check value */ + int havedict; /* true if dictionary provided */ + int flags; /* gzip header method and flags (0 if zlib) */ + unsigned dmax; /* zlib header max distance (INFLATE_STRICT) */ + unsigned long check; /* protected copy of check value */ + unsigned long total; /* protected copy of output count */ + gz_headerp head; /* where to save gzip header information */ + /* sliding window */ + unsigned wbits; /* log base 2 of requested window size */ + unsigned wsize; /* window size or zero if not using window */ + unsigned whave; /* valid bytes in the window */ + unsigned wnext; /* window write index */ + unsigned char FAR *window; /* allocated sliding window, if needed */ + /* bit accumulator */ + unsigned long hold; /* input bit accumulator */ + unsigned bits; /* number of bits in "in" */ + /* for string and stored block copying */ + unsigned length; /* literal or length of data to copy */ + unsigned offset; /* distance back to copy string from */ + /* for table and code decoding */ + unsigned extra; /* extra bits needed */ + /* fixed and dynamic code tables */ + code const FAR *lencode; /* starting table for length/literal codes */ + code const FAR *distcode; /* starting table for distance codes */ + unsigned lenbits; /* index bits for lencode */ + unsigned distbits; /* index bits for distcode */ + /* dynamic table building */ + unsigned ncode; /* number of code length code lengths */ + unsigned nlen; /* number of length code lengths */ + unsigned ndist; /* number of distance code lengths */ + unsigned have; /* number of code lengths in lens[] */ + code FAR *next; /* next available space in codes[] */ + unsigned short lens[320]; /* temporary storage for code lengths */ + unsigned short work[288]; /* work area for code table building */ + code codes[ENOUGH]; /* space for code tables */ + int sane; /* if false, allow invalid distance too far */ + int back; /* bits back of last unprocessed length/lit */ + unsigned was; /* initial length of match */ +}; diff --git a/arm-trusted-firmware/lib/zlib/inftrees.c b/arm-trusted-firmware/lib/zlib/inftrees.c new file mode 100644 index 0000000..2ea08fc --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inftrees.c @@ -0,0 +1,304 @@ +/* inftrees.c -- generate Huffman trees for efficient decoding + * Copyright (C) 1995-2017 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +#include "zutil.h" +#include "inftrees.h" + +#define MAXBITS 15 + +const char inflate_copyright[] = + " inflate 1.2.11 Copyright 1995-2017 Mark Adler "; +/* + If you use the zlib library in a product, an acknowledgment is welcome + in the documentation of your product. If for some reason you cannot + include such an acknowledgment, I would appreciate that you keep this + copyright string in the executable of your product. + */ + +/* + Build a set of tables to decode the provided canonical Huffman code. + The code lengths are lens[0..codes-1]. The result starts at *table, + whose indices are 0..2^bits-1. work is a writable array of at least + lens shorts, which is used as a work area. type is the type of code + to be generated, CODES, LENS, or DISTS. On return, zero is success, + -1 is an invalid code, and +1 means that ENOUGH isn't enough. table + on return points to the next available entry's address. bits is the + requested root table index bits, and on return it is the actual root + table index bits. It will differ if the request is greater than the + longest code or if it is less than the shortest code. + */ +int ZLIB_INTERNAL inflate_table(type, lens, codes, table, bits, work) +codetype type; +unsigned short FAR *lens; +unsigned codes; +code FAR * FAR *table; +unsigned FAR *bits; +unsigned short FAR *work; +{ + unsigned len; /* a code's length in bits */ + unsigned sym; /* index of code symbols */ + unsigned min, max; /* minimum and maximum code lengths */ + unsigned root; /* number of index bits for root table */ + unsigned curr; /* number of index bits for current table */ + unsigned drop; /* code bits to drop for sub-table */ + int left; /* number of prefix codes available */ + unsigned used; /* code entries in table used */ + unsigned huff; /* Huffman code */ + unsigned incr; /* for incrementing code, index */ + unsigned fill; /* index for replicating entries */ + unsigned low; /* low bits for current root entry */ + unsigned mask; /* mask for low root bits */ + code here; /* table entry for duplication */ + code FAR *next; /* next available space in table */ + const unsigned short FAR *base; /* base value table to use */ + const unsigned short FAR *extra; /* extra bits table to use */ + unsigned match; /* use base and extra for symbol >= match */ + unsigned short count[MAXBITS+1]; /* number of codes of each length */ + unsigned short offs[MAXBITS+1]; /* offsets in table for each length */ + static const unsigned short lbase[31] = { /* Length codes 257..285 base */ + 3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31, + 35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0}; + static const unsigned short lext[31] = { /* Length codes 257..285 extra */ + 16, 16, 16, 16, 16, 16, 16, 16, 17, 17, 17, 17, 18, 18, 18, 18, + 19, 19, 19, 19, 20, 20, 20, 20, 21, 21, 21, 21, 16, 77, 202}; + static const unsigned short dbase[32] = { /* Distance codes 0..29 base */ + 1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193, + 257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145, + 8193, 12289, 16385, 24577, 0, 0}; + static const unsigned short dext[32] = { /* Distance codes 0..29 extra */ + 16, 16, 16, 16, 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, + 23, 23, 24, 24, 25, 25, 26, 26, 27, 27, + 28, 28, 29, 29, 64, 64}; + + /* + Process a set of code lengths to create a canonical Huffman code. The + code lengths are lens[0..codes-1]. Each length corresponds to the + symbols 0..codes-1. The Huffman code is generated by first sorting the + symbols by length from short to long, and retaining the symbol order + for codes with equal lengths. Then the code starts with all zero bits + for the first code of the shortest length, and the codes are integer + increments for the same length, and zeros are appended as the length + increases. For the deflate format, these bits are stored backwards + from their more natural integer increment ordering, and so when the + decoding tables are built in the large loop below, the integer codes + are incremented backwards. + + This routine assumes, but does not check, that all of the entries in + lens[] are in the range 0..MAXBITS. The caller must assure this. + 1..MAXBITS is interpreted as that code length. zero means that that + symbol does not occur in this code. + + The codes are sorted by computing a count of codes for each length, + creating from that a table of starting indices for each length in the + sorted table, and then entering the symbols in order in the sorted + table. The sorted table is work[], with that space being provided by + the caller. + + The length counts are used for other purposes as well, i.e. finding + the minimum and maximum length codes, determining if there are any + codes at all, checking for a valid set of lengths, and looking ahead + at length counts to determine sub-table sizes when building the + decoding tables. + */ + + /* accumulate lengths for codes (assumes lens[] all in 0..MAXBITS) */ + for (len = 0; len <= MAXBITS; len++) + count[len] = 0; + for (sym = 0; sym < codes; sym++) + count[lens[sym]]++; + + /* bound code lengths, force root to be within code lengths */ + root = *bits; + for (max = MAXBITS; max >= 1; max--) + if (count[max] != 0) break; + if (root > max) root = max; + if (max == 0) { /* no symbols to code at all */ + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)1; + here.val = (unsigned short)0; + *(*table)++ = here; /* make a table to force an error */ + *(*table)++ = here; + *bits = 1; + return 0; /* no symbols, but wait for decoding to report error */ + } + for (min = 1; min < max; min++) + if (count[min] != 0) break; + if (root < min) root = min; + + /* check for an over-subscribed or incomplete set of lengths */ + left = 1; + for (len = 1; len <= MAXBITS; len++) { + left <<= 1; + left -= count[len]; + if (left < 0) return -1; /* over-subscribed */ + } + if (left > 0 && (type == CODES || max != 1)) + return -1; /* incomplete set */ + + /* generate offsets into symbol table for each length for sorting */ + offs[1] = 0; + for (len = 1; len < MAXBITS; len++) + offs[len + 1] = offs[len] + count[len]; + + /* sort symbols by length, by symbol order within each length */ + for (sym = 0; sym < codes; sym++) + if (lens[sym] != 0) work[offs[lens[sym]]++] = (unsigned short)sym; + + /* + Create and fill in decoding tables. In this loop, the table being + filled is at next and has curr index bits. The code being used is huff + with length len. That code is converted to an index by dropping drop + bits off of the bottom. For codes where len is less than drop + curr, + those top drop + curr - len bits are incremented through all values to + fill the table with replicated entries. + + root is the number of index bits for the root table. When len exceeds + root, sub-tables are created pointed to by the root entry with an index + of the low root bits of huff. This is saved in low to check for when a + new sub-table should be started. drop is zero when the root table is + being filled, and drop is root when sub-tables are being filled. + + When a new sub-table is needed, it is necessary to look ahead in the + code lengths to determine what size sub-table is needed. The length + counts are used for this, and so count[] is decremented as codes are + entered in the tables. + + used keeps track of how many table entries have been allocated from the + provided *table space. It is checked for LENS and DIST tables against + the constants ENOUGH_LENS and ENOUGH_DISTS to guard against changes in + the initial root table size constants. See the comments in inftrees.h + for more information. + + sym increments through all symbols, and the loop terminates when + all codes of length max, i.e. all codes, have been processed. This + routine permits incomplete codes, so another loop after this one fills + in the rest of the decoding tables with invalid code markers. + */ + + /* set up for code type */ + switch (type) { + case CODES: + base = extra = work; /* dummy value--not used */ + match = 20; + break; + case LENS: + base = lbase; + extra = lext; + match = 257; + break; + default: /* DISTS */ + base = dbase; + extra = dext; + match = 0; + } + + /* initialize state for loop */ + huff = 0; /* starting code */ + sym = 0; /* starting code symbol */ + len = min; /* starting code length */ + next = *table; /* current table to fill in */ + curr = root; /* current table index bits */ + drop = 0; /* current bits to drop from code for index */ + low = (unsigned)(-1); /* trigger new sub-table when len > root */ + used = 1U << root; /* use root table entries */ + mask = used - 1; /* mask for comparing low */ + + /* check available table space */ + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* process all codes and make table entries */ + for (;;) { + /* create table entry */ + here.bits = (unsigned char)(len - drop); + if (work[sym] + 1U < match) { + here.op = (unsigned char)0; + here.val = work[sym]; + } + else if (work[sym] >= match) { + here.op = (unsigned char)(extra[work[sym] - match]); + here.val = base[work[sym] - match]; + } + else { + here.op = (unsigned char)(32 + 64); /* end of block */ + here.val = 0; + } + + /* replicate for those indices with low len bits equal to huff */ + incr = 1U << (len - drop); + fill = 1U << curr; + min = fill; /* save offset to next table */ + do { + fill -= incr; + next[(huff >> drop) + fill] = here; + } while (fill != 0); + + /* backwards increment the len-bit code huff */ + incr = 1U << (len - 1); + while (huff & incr) + incr >>= 1; + if (incr != 0) { + huff &= incr - 1; + huff += incr; + } + else + huff = 0; + + /* go to next symbol, update count, len */ + sym++; + if (--(count[len]) == 0) { + if (len == max) break; + len = lens[work[sym]]; + } + + /* create new sub-table if needed */ + if (len > root && (huff & mask) != low) { + /* if first time, transition to sub-tables */ + if (drop == 0) + drop = root; + + /* increment past last table */ + next += min; /* here min is 1 << curr */ + + /* determine length of next table */ + curr = len - drop; + left = (int)(1 << curr); + while (curr + drop < max) { + left -= count[curr + drop]; + if (left <= 0) break; + curr++; + left <<= 1; + } + + /* check for enough space */ + used += 1U << curr; + if ((type == LENS && used > ENOUGH_LENS) || + (type == DISTS && used > ENOUGH_DISTS)) + return 1; + + /* point entry in root table to sub-table */ + low = huff & mask; + (*table)[low].op = (unsigned char)curr; + (*table)[low].bits = (unsigned char)root; + (*table)[low].val = (unsigned short)(next - *table); + } + } + + /* fill in remaining table entry if code is incomplete (guaranteed to have + at most one remaining entry, since if the code is incomplete, the + maximum code length that was allowed to get this far is one bit) */ + if (huff != 0) { + here.op = (unsigned char)64; /* invalid code marker */ + here.bits = (unsigned char)(len - drop); + here.val = (unsigned short)0; + next[huff] = here; + } + + /* set return parameters */ + *table += used; + *bits = root; + return 0; +} diff --git a/arm-trusted-firmware/lib/zlib/inftrees.h b/arm-trusted-firmware/lib/zlib/inftrees.h new file mode 100644 index 0000000..baa53a0 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/inftrees.h @@ -0,0 +1,62 @@ +/* inftrees.h -- header to use inftrees.c + * Copyright (C) 1995-2005, 2010 Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* Structure for decoding tables. Each entry provides either the + information needed to do the operation requested by the code that + indexed that table entry, or it provides a pointer to another + table that indexes more bits of the code. op indicates whether + the entry is a pointer to another table, a literal, a length or + distance, an end-of-block, or an invalid code. For a table + pointer, the low four bits of op is the number of index bits of + that table. For a length or distance, the low four bits of op + is the number of extra bits to get after the code. bits is + the number of bits in this code or part of the code to drop off + of the bit buffer. val is the actual byte to output in the case + of a literal, the base length or distance, or the offset from + the current table to the next table. Each entry is four bytes. */ +typedef struct { + unsigned char op; /* operation, extra bits, table bits */ + unsigned char bits; /* bits in this part of the code */ + unsigned short val; /* offset in table or code value */ +} code; + +/* op values as set by inflate_table(): + 00000000 - literal + 0000tttt - table link, tttt != 0 is the number of table index bits + 0001eeee - length or distance, eeee is the number of extra bits + 01100000 - end of block + 01000000 - invalid code + */ + +/* Maximum size of the dynamic table. The maximum number of code structures is + 1444, which is the sum of 852 for literal/length codes and 592 for distance + codes. These values were found by exhaustive searches using the program + examples/enough.c found in the zlib distribtution. The arguments to that + program are the number of symbols, the initial root table size, and the + maximum bit length of a code. "enough 286 9 15" for literal/length codes + returns returns 852, and "enough 30 6 15" for distance codes returns 592. + The initial root table size (9 or 6) is found in the fifth argument of the + inflate_table() calls in inflate.c and infback.c. If the root table size is + changed, then these maximum sizes would be need to be recalculated and + updated. */ +#define ENOUGH_LENS 852 +#define ENOUGH_DISTS 592 +#define ENOUGH (ENOUGH_LENS+ENOUGH_DISTS) + +/* Type of code to build for inflate_table() */ +typedef enum { + CODES, + LENS, + DISTS +} codetype; + +int ZLIB_INTERNAL inflate_table OF((codetype type, unsigned short FAR *lens, + unsigned codes, code FAR * FAR *table, + unsigned FAR *bits, unsigned short FAR *work)); diff --git a/arm-trusted-firmware/lib/zlib/tf_gunzip.c b/arm-trusted-firmware/lib/zlib/tf_gunzip.c new file mode 100644 index 0000000..3ac80bc --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/tf_gunzip.c @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include "zutil.h" + +/* + * memory allocated by malloc() is supposed to be aligned for any built-in type + */ +#define ZALLOC_ALIGNMENT sizeof(void *) + +static uintptr_t zalloc_start; +static uintptr_t zalloc_end; +static uintptr_t zalloc_current; + +static void * ZLIB_INTERNAL zcalloc(void *opaque, unsigned int items, + unsigned int size) +{ + uintptr_t p, p_end; + + size *= items; + + p = round_up(zalloc_current, ZALLOC_ALIGNMENT); + p_end = p + size; + + if (p_end > zalloc_end) + return NULL; + + memset((void *)p, 0, size); + + zalloc_current = p_end; + + return (void *)p; +} + +static void ZLIB_INTERNAL zfree(void *opaque, void *ptr) +{ +} + +/* + * gunzip - decompress gzip data + * @in_buf: source of compressed input. Upon exit, the end of input. + * @in_len: length of in_buf + * @out_buf: destination of decompressed output. Upon exit, the end of output. + * @out_len: length of out_buf + * @work_buf: workspace + * @work_len: length of workspace + */ +int gunzip(uintptr_t *in_buf, size_t in_len, uintptr_t *out_buf, + size_t out_len, uintptr_t work_buf, size_t work_len) +{ + z_stream stream; + int zret, ret; + + zalloc_start = work_buf; + zalloc_end = work_buf + work_len; + zalloc_current = zalloc_start; + + stream.next_in = (typeof(stream.next_in))*in_buf; + stream.avail_in = in_len; + stream.next_out = (typeof(stream.next_out))*out_buf; + stream.avail_out = out_len; + stream.zalloc = zcalloc; + stream.zfree = zfree; + stream.opaque = (voidpf)0; + + zret = inflateInit(&stream); + if (zret != Z_OK) { + ERROR("zlib: inflate init failed (ret = %d)\n", zret); + return (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + zret = inflate(&stream, Z_NO_FLUSH); + if (zret == Z_STREAM_END) { + ret = 0; + } else { + if (stream.msg) + ERROR("%s\n", stream.msg); + ERROR("zlib: inflate failed (ret = %d)\n", zret); + ret = (zret == Z_MEM_ERROR) ? -ENOMEM : -EIO; + } + + VERBOSE("zlib: %lu byte input\n", stream.total_in); + VERBOSE("zlib: %lu byte output\n", stream.total_out); + + *in_buf = (uintptr_t)stream.next_in; + *out_buf = (uintptr_t)stream.next_out; + + inflateEnd(&stream); + + return ret; +} + +/* Wrapper function to calculate CRC + * @crc: previous accumulated CRC + * @buf: buffer base address + * @size: size of the buffer + * + * Return calculated CRC32 value + */ +uint32_t tf_crc32(uint32_t crc, const unsigned char *buf, size_t size) +{ + return (uint32_t)crc32((unsigned long)crc, buf, size); +} diff --git a/arm-trusted-firmware/lib/zlib/zconf.h b/arm-trusted-firmware/lib/zlib/zconf.h new file mode 100644 index 0000000..5e1d68a --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zconf.h @@ -0,0 +1,534 @@ +/* zconf.h -- configuration of the zlib compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#ifndef ZCONF_H +#define ZCONF_H + +/* + * If you *really* need a unique prefix for all types and library functions, + * compile with -DZ_PREFIX. The "standard" zlib should be compiled without it. + * Even better than compiling with -DZ_PREFIX would be to use configure to set + * this permanently in zconf.h using "./configure --zprefix". + */ +#ifdef Z_PREFIX /* may be set to #if 1 by ./configure */ +# define Z_PREFIX_SET + +/* all linked symbols and init macros */ +# define _dist_code z__dist_code +# define _length_code z__length_code +# define _tr_align z__tr_align +# define _tr_flush_bits z__tr_flush_bits +# define _tr_flush_block z__tr_flush_block +# define _tr_init z__tr_init +# define _tr_stored_block z__tr_stored_block +# define _tr_tally z__tr_tally +# define adler32 z_adler32 +# define adler32_combine z_adler32_combine +# define adler32_combine64 z_adler32_combine64 +# define adler32_z z_adler32_z +# ifndef Z_SOLO +# define compress z_compress +# define compress2 z_compress2 +# define compressBound z_compressBound +# endif +# define crc32 z_crc32 +# define crc32_combine z_crc32_combine +# define crc32_combine64 z_crc32_combine64 +# define crc32_z z_crc32_z +# define deflate z_deflate +# define deflateBound z_deflateBound +# define deflateCopy z_deflateCopy +# define deflateEnd z_deflateEnd +# define deflateGetDictionary z_deflateGetDictionary +# define deflateInit z_deflateInit +# define deflateInit2 z_deflateInit2 +# define deflateInit2_ z_deflateInit2_ +# define deflateInit_ z_deflateInit_ +# define deflateParams z_deflateParams +# define deflatePending z_deflatePending +# define deflatePrime z_deflatePrime +# define deflateReset z_deflateReset +# define deflateResetKeep z_deflateResetKeep +# define deflateSetDictionary z_deflateSetDictionary +# define deflateSetHeader z_deflateSetHeader +# define deflateTune z_deflateTune +# define deflate_copyright z_deflate_copyright +# define get_crc_table z_get_crc_table +# ifndef Z_SOLO +# define gz_error z_gz_error +# define gz_intmax z_gz_intmax +# define gz_strwinerror z_gz_strwinerror +# define gzbuffer z_gzbuffer +# define gzclearerr z_gzclearerr +# define gzclose z_gzclose +# define gzclose_r z_gzclose_r +# define gzclose_w z_gzclose_w +# define gzdirect z_gzdirect +# define gzdopen z_gzdopen +# define gzeof z_gzeof +# define gzerror z_gzerror +# define gzflush z_gzflush +# define gzfread z_gzfread +# define gzfwrite z_gzfwrite +# define gzgetc z_gzgetc +# define gzgetc_ z_gzgetc_ +# define gzgets z_gzgets +# define gzoffset z_gzoffset +# define gzoffset64 z_gzoffset64 +# define gzopen z_gzopen +# define gzopen64 z_gzopen64 +# ifdef _WIN32 +# define gzopen_w z_gzopen_w +# endif +# define gzprintf z_gzprintf +# define gzputc z_gzputc +# define gzputs z_gzputs +# define gzread z_gzread +# define gzrewind z_gzrewind +# define gzseek z_gzseek +# define gzseek64 z_gzseek64 +# define gzsetparams z_gzsetparams +# define gztell z_gztell +# define gztell64 z_gztell64 +# define gzungetc z_gzungetc +# define gzvprintf z_gzvprintf +# define gzwrite z_gzwrite +# endif +# define inflate z_inflate +# define inflateBack z_inflateBack +# define inflateBackEnd z_inflateBackEnd +# define inflateBackInit z_inflateBackInit +# define inflateBackInit_ z_inflateBackInit_ +# define inflateCodesUsed z_inflateCodesUsed +# define inflateCopy z_inflateCopy +# define inflateEnd z_inflateEnd +# define inflateGetDictionary z_inflateGetDictionary +# define inflateGetHeader z_inflateGetHeader +# define inflateInit z_inflateInit +# define inflateInit2 z_inflateInit2 +# define inflateInit2_ z_inflateInit2_ +# define inflateInit_ z_inflateInit_ +# define inflateMark z_inflateMark +# define inflatePrime z_inflatePrime +# define inflateReset z_inflateReset +# define inflateReset2 z_inflateReset2 +# define inflateResetKeep z_inflateResetKeep +# define inflateSetDictionary z_inflateSetDictionary +# define inflateSync z_inflateSync +# define inflateSyncPoint z_inflateSyncPoint +# define inflateUndermine z_inflateUndermine +# define inflateValidate z_inflateValidate +# define inflate_copyright z_inflate_copyright +# define inflate_fast z_inflate_fast +# define inflate_table z_inflate_table +# ifndef Z_SOLO +# define uncompress z_uncompress +# define uncompress2 z_uncompress2 +# endif +# define zError z_zError +# ifndef Z_SOLO +# define zcalloc z_zcalloc +# define zcfree z_zcfree +# endif +# define zlibCompileFlags z_zlibCompileFlags +# define zlibVersion z_zlibVersion + +/* all zlib typedefs in zlib.h and zconf.h */ +# define Byte z_Byte +# define Bytef z_Bytef +# define alloc_func z_alloc_func +# define charf z_charf +# define free_func z_free_func +# ifndef Z_SOLO +# define gzFile z_gzFile +# endif +# define gz_header z_gz_header +# define gz_headerp z_gz_headerp +# define in_func z_in_func +# define intf z_intf +# define out_func z_out_func +# define uInt z_uInt +# define uIntf z_uIntf +# define uLong z_uLong +# define uLongf z_uLongf +# define voidp z_voidp +# define voidpc z_voidpc +# define voidpf z_voidpf + +/* all zlib structs in zlib.h and zconf.h */ +# define gz_header_s z_gz_header_s +# define internal_state z_internal_state + +#endif + +#if defined(__MSDOS__) && !defined(MSDOS) +# define MSDOS +#endif +#if (defined(OS_2) || defined(__OS2__)) && !defined(OS2) +# define OS2 +#endif +#if defined(_WINDOWS) && !defined(WINDOWS) +# define WINDOWS +#endif +#if defined(_WIN32) || defined(_WIN32_WCE) || defined(__WIN32__) +# ifndef WIN32 +# define WIN32 +# endif +#endif +#if (defined(MSDOS) || defined(OS2) || defined(WINDOWS)) && !defined(WIN32) +# if !defined(__GNUC__) && !defined(__FLAT__) && !defined(__386__) +# ifndef SYS16BIT +# define SYS16BIT +# endif +# endif +#endif + +/* + * Compile with -DMAXSEG_64K if the alloc function cannot allocate more + * than 64k bytes at a time (needed on systems with 16-bit int). + */ +#ifdef SYS16BIT +# define MAXSEG_64K +#endif +#ifdef MSDOS +# define UNALIGNED_OK +#endif + +#ifdef __STDC_VERSION__ +# ifndef STDC +# define STDC +# endif +# if __STDC_VERSION__ >= 199901L +# ifndef STDC99 +# define STDC99 +# endif +# endif +#endif +#if !defined(STDC) && (defined(__STDC__) || defined(__cplusplus)) +# define STDC +#endif +#if !defined(STDC) && (defined(__GNUC__) || defined(__BORLANDC__)) +# define STDC +#endif +#if !defined(STDC) && (defined(MSDOS) || defined(WINDOWS) || defined(WIN32)) +# define STDC +#endif +#if !defined(STDC) && (defined(OS2) || defined(__HOS_AIX__)) +# define STDC +#endif + +#if defined(__OS400__) && !defined(STDC) /* iSeries (formerly AS/400). */ +# define STDC +#endif + +#ifndef STDC +# ifndef const /* cannot use !defined(STDC) && !defined(const) on Mac */ +# define const /* note: need a more gentle solution here */ +# endif +#endif + +#if defined(ZLIB_CONST) && !defined(z_const) +# define z_const const +#else +# define z_const +#endif + +#ifdef Z_SOLO + typedef unsigned long z_size_t; +#else +# define z_longlong long long +# if defined(NO_SIZE_T) + typedef unsigned NO_SIZE_T z_size_t; +# elif defined(STDC) +# include + typedef size_t z_size_t; +# else + typedef unsigned long z_size_t; +# endif +# undef z_longlong +#endif + +/* Maximum value for memLevel in deflateInit2 */ +#ifndef MAX_MEM_LEVEL +# ifdef MAXSEG_64K +# define MAX_MEM_LEVEL 8 +# else +# define MAX_MEM_LEVEL 9 +# endif +#endif + +/* Maximum value for windowBits in deflateInit2 and inflateInit2. + * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files + * created by gzip. (Files created by minigzip can still be extracted by + * gzip.) + */ +#ifndef MAX_WBITS +# define MAX_WBITS 15 /* 32K LZ77 window */ +#endif + +/* The memory requirements for deflate are (in bytes): + (1 << (windowBits+2)) + (1 << (memLevel+9)) + that is: 128K for windowBits=15 + 128K for memLevel = 8 (default values) + plus a few kilobytes for small objects. For example, if you want to reduce + the default memory requirements from 256K to 128K, compile with + make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7" + Of course this will generally degrade compression (there's no free lunch). + + The memory requirements for inflate are (in bytes) 1 << windowBits + that is, 32K for windowBits=15 (default value) plus about 7 kilobytes + for small objects. +*/ + + /* Type declarations */ + +#ifndef OF /* function prototypes */ +# ifdef STDC +# define OF(args) args +# else +# define OF(args) () +# endif +#endif + +#ifndef Z_ARG /* function prototypes for stdarg */ +# if defined(STDC) || defined(Z_HAVE_STDARG_H) +# define Z_ARG(args) args +# else +# define Z_ARG(args) () +# endif +#endif + +/* The following definitions for FAR are needed only for MSDOS mixed + * model programming (small or medium model with some far allocations). + * This was tested only with MSC; for other MSDOS compilers you may have + * to define NO_MEMCPY in zutil.h. If you don't need the mixed model, + * just define FAR to be empty. + */ +#ifdef SYS16BIT +# if defined(M_I86SM) || defined(M_I86MM) + /* MSC small or medium model */ +# define SMALL_MEDIUM +# ifdef _MSC_VER +# define FAR _far +# else +# define FAR far +# endif +# endif +# if (defined(__SMALL__) || defined(__MEDIUM__)) + /* Turbo C small or medium model */ +# define SMALL_MEDIUM +# ifdef __BORLANDC__ +# define FAR _far +# else +# define FAR far +# endif +# endif +#endif + +#if defined(WINDOWS) || defined(WIN32) + /* If building or using zlib as a DLL, define ZLIB_DLL. + * This is not mandatory, but it offers a little performance increase. + */ +# ifdef ZLIB_DLL +# if defined(WIN32) && (!defined(__BORLANDC__) || (__BORLANDC__ >= 0x500)) +# ifdef ZLIB_INTERNAL +# define ZEXTERN extern __declspec(dllexport) +# else +# define ZEXTERN extern __declspec(dllimport) +# endif +# endif +# endif /* ZLIB_DLL */ + /* If building or using zlib with the WINAPI/WINAPIV calling convention, + * define ZLIB_WINAPI. + * Caution: the standard ZLIB1.DLL is NOT compiled using ZLIB_WINAPI. + */ +# ifdef ZLIB_WINAPI +# ifdef FAR +# undef FAR +# endif +# include + /* No need for _export, use ZLIB.DEF instead. */ + /* For complete Windows compatibility, use WINAPI, not __stdcall. */ +# define ZEXPORT WINAPI +# ifdef WIN32 +# define ZEXPORTVA WINAPIV +# else +# define ZEXPORTVA FAR CDECL +# endif +# endif +#endif + +#if defined (__BEOS__) +# ifdef ZLIB_DLL +# ifdef ZLIB_INTERNAL +# define ZEXPORT __declspec(dllexport) +# define ZEXPORTVA __declspec(dllexport) +# else +# define ZEXPORT __declspec(dllimport) +# define ZEXPORTVA __declspec(dllimport) +# endif +# endif +#endif + +#ifndef ZEXTERN +# define ZEXTERN extern +#endif +#ifndef ZEXPORT +# define ZEXPORT +#endif +#ifndef ZEXPORTVA +# define ZEXPORTVA +#endif + +#ifndef FAR +# define FAR +#endif + +#if !defined(__MACTYPES__) +typedef unsigned char Byte; /* 8 bits */ +#endif +typedef unsigned int uInt; /* 16 bits or more */ +typedef unsigned long uLong; /* 32 bits or more */ + +#ifdef SMALL_MEDIUM + /* Borland C/C++ and some old MSC versions ignore FAR inside typedef */ +# define Bytef Byte FAR +#else + typedef Byte FAR Bytef; +#endif +typedef char FAR charf; +typedef int FAR intf; +typedef uInt FAR uIntf; +typedef uLong FAR uLongf; + +#ifdef STDC + typedef void const *voidpc; + typedef void FAR *voidpf; + typedef void *voidp; +#else + typedef Byte const *voidpc; + typedef Byte FAR *voidpf; + typedef Byte *voidp; +#endif + +#if !defined(Z_U4) && !defined(Z_SOLO) && defined(STDC) +# include +# if (UINT_MAX == 0xffffffffUL) +# define Z_U4 unsigned +# elif (ULONG_MAX == 0xffffffffUL) +# define Z_U4 unsigned long +# elif (USHRT_MAX == 0xffffffffUL) +# define Z_U4 unsigned short +# endif +#endif + +#ifdef Z_U4 + typedef Z_U4 z_crc_t; +#else + typedef unsigned long z_crc_t; +#endif + +#ifdef HAVE_UNISTD_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_UNISTD_H +#endif + +#ifdef HAVE_STDARG_H /* may be set to #if 1 by ./configure */ +# define Z_HAVE_STDARG_H +#endif + +#ifdef STDC +# ifndef Z_SOLO +# include /* for off_t */ +# endif +#endif + +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +# include /* for va_list */ +# endif +#endif + +#ifdef _WIN32 +# ifndef Z_SOLO +# include /* for wchar_t */ +# endif +#endif + +/* a little trick to accommodate both "#define _LARGEFILE64_SOURCE" and + * "#define _LARGEFILE64_SOURCE 1" as requesting 64-bit operations, (even + * though the former does not conform to the LFS document), but considering + * both "#undef _LARGEFILE64_SOURCE" and "#define _LARGEFILE64_SOURCE 0" as + * equivalently requesting no 64-bit operations + */ +#if defined(_LARGEFILE64_SOURCE) && -_LARGEFILE64_SOURCE - -1 == 1 +# undef _LARGEFILE64_SOURCE +#endif + +#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) +# define Z_HAVE_UNISTD_H +#endif +#ifndef Z_SOLO +# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) +# include /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ +# ifdef VMS +# include /* for off_t */ +# endif +# ifndef z_off_t +# define z_off_t off_t +# endif +# endif +#endif + +#if defined(_LFS64_LARGEFILE) && _LFS64_LARGEFILE-0 +# define Z_LFS64 +#endif + +#if defined(_LARGEFILE64_SOURCE) && defined(Z_LFS64) +# define Z_LARGE64 +#endif + +#if defined(_FILE_OFFSET_BITS) && _FILE_OFFSET_BITS-0 == 64 && defined(Z_LFS64) +# define Z_WANT64 +#endif + +#if !defined(SEEK_SET) && !defined(Z_SOLO) +# define SEEK_SET 0 /* Seek from beginning of file. */ +# define SEEK_CUR 1 /* Seek from current position. */ +# define SEEK_END 2 /* Set file pointer to EOF plus "offset" */ +#endif + +#ifndef z_off_t +# define z_off_t long +#endif + +#if !defined(_WIN32) && defined(Z_LARGE64) +# define z_off64_t off64_t +#else +# if defined(_WIN32) && !defined(__GNUC__) && !defined(Z_SOLO) +# define z_off64_t __int64 +# else +# define z_off64_t z_off_t +# endif +#endif + +/* MVS linker does not support external names larger than 8 bytes */ +#if defined(__MVS__) + #pragma map(deflateInit_,"DEIN") + #pragma map(deflateInit2_,"DEIN2") + #pragma map(deflateEnd,"DEEND") + #pragma map(deflateBound,"DEBND") + #pragma map(inflateInit_,"ININ") + #pragma map(inflateInit2_,"ININ2") + #pragma map(inflateEnd,"INEND") + #pragma map(inflateSync,"INSY") + #pragma map(inflateSetDictionary,"INSEDI") + #pragma map(compressBound,"CMBND") + #pragma map(inflate_table,"INTABL") + #pragma map(inflate_fast,"INFA") + #pragma map(inflate_copyright,"INCOPY") +#endif + +#endif /* ZCONF_H */ diff --git a/arm-trusted-firmware/lib/zlib/zlib.h b/arm-trusted-firmware/lib/zlib/zlib.h new file mode 100644 index 0000000..f09cdaf --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zlib.h @@ -0,0 +1,1912 @@ +/* zlib.h -- interface of the 'zlib' general purpose compression library + version 1.2.11, January 15th, 2017 + + Copyright (C) 1995-2017 Jean-loup Gailly and Mark Adler + + This software is provided 'as-is', without any express or implied + warranty. In no event will the authors be held liable for any damages + arising from the use of this software. + + Permission is granted to anyone to use this software for any purpose, + including commercial applications, and to alter it and redistribute it + freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; you must not + claim that you wrote the original software. If you use this software + in a product, an acknowledgment in the product documentation would be + appreciated but is not required. + 2. Altered source versions must be plainly marked as such, and must not be + misrepresented as being the original software. + 3. This notice may not be removed or altered from any source distribution. + + Jean-loup Gailly Mark Adler + jloup@gzip.org madler@alumni.caltech.edu + + + The data format used by the zlib library is described by RFCs (Request for + Comments) 1950 to 1952 in the files http://tools.ietf.org/html/rfc1950 + (zlib format), rfc1951 (deflate format) and rfc1952 (gzip format). +*/ + +#ifndef ZLIB_H +#define ZLIB_H + +#include "zconf.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define ZLIB_VERSION "1.2.11" +#define ZLIB_VERNUM 0x12b0 +#define ZLIB_VER_MAJOR 1 +#define ZLIB_VER_MINOR 2 +#define ZLIB_VER_REVISION 11 +#define ZLIB_VER_SUBREVISION 0 + +/* + The 'zlib' compression library provides in-memory compression and + decompression functions, including integrity checks of the uncompressed data. + This version of the library supports only one compression method (deflation) + but other algorithms will be added later and will have the same stream + interface. + + Compression can be done in a single step if the buffers are large enough, + or can be done by repeated calls of the compression function. In the latter + case, the application must provide more input and/or consume the output + (providing more output space) before each call. + + The compressed data format used by default by the in-memory functions is + the zlib format, which is a zlib wrapper documented in RFC 1950, wrapped + around a deflate stream, which is itself documented in RFC 1951. + + The library also supports reading and writing files in gzip (.gz) format + with an interface similar to that of stdio using the functions that start + with "gz". The gzip format is different from the zlib format. gzip is a + gzip wrapper, documented in RFC 1952, wrapped around a deflate stream. + + This library can optionally read and write gzip and raw deflate streams in + memory as well. + + The zlib format was designed to be compact and fast for use in memory + and on communications channels. The gzip format was designed for single- + file compression on file systems, has a larger header than zlib to maintain + directory information, and uses a different, slower check method than zlib. + + The library does not install any signal handler. The decoder checks + the consistency of the compressed data, so the library should never crash + even in the case of corrupted input. +*/ + +typedef voidpf (*alloc_func) OF((voidpf opaque, uInt items, uInt size)); +typedef void (*free_func) OF((voidpf opaque, voidpf address)); + +struct internal_state; + +typedef struct z_stream_s { + z_const Bytef *next_in; /* next input byte */ + uInt avail_in; /* number of bytes available at next_in */ + uLong total_in; /* total number of input bytes read so far */ + + Bytef *next_out; /* next output byte will go here */ + uInt avail_out; /* remaining free space at next_out */ + uLong total_out; /* total number of bytes output so far */ + + z_const char *msg; /* last error message, NULL if no error */ + struct internal_state FAR *state; /* not visible by applications */ + + alloc_func zalloc; /* used to allocate the internal state */ + free_func zfree; /* used to free the internal state */ + voidpf opaque; /* private data object passed to zalloc and zfree */ + + int data_type; /* best guess about the data type: binary or text + for deflate, or the decoding state for inflate */ + uLong adler; /* Adler-32 or CRC-32 value of the uncompressed data */ + uLong reserved; /* reserved for future use */ +} z_stream; + +typedef z_stream FAR *z_streamp; + +/* + gzip header information passed to and from zlib routines. See RFC 1952 + for more details on the meanings of these fields. +*/ +typedef struct gz_header_s { + int text; /* true if compressed data believed to be text */ + uLong time; /* modification time */ + int xflags; /* extra flags (not used when writing a gzip file) */ + int os; /* operating system */ + Bytef *extra; /* pointer to extra field or Z_NULL if none */ + uInt extra_len; /* extra field length (valid if extra != Z_NULL) */ + uInt extra_max; /* space at extra (only when reading header) */ + Bytef *name; /* pointer to zero-terminated file name or Z_NULL */ + uInt name_max; /* space at name (only when reading header) */ + Bytef *comment; /* pointer to zero-terminated comment or Z_NULL */ + uInt comm_max; /* space at comment (only when reading header) */ + int hcrc; /* true if there was or will be a header crc */ + int done; /* true when done reading gzip header (not used + when writing a gzip file) */ +} gz_header; + +typedef gz_header FAR *gz_headerp; + +/* + The application must update next_in and avail_in when avail_in has dropped + to zero. It must update next_out and avail_out when avail_out has dropped + to zero. The application must initialize zalloc, zfree and opaque before + calling the init function. All other fields are set by the compression + library and must not be updated by the application. + + The opaque value provided by the application will be passed as the first + parameter for calls of zalloc and zfree. This can be useful for custom + memory management. The compression library attaches no meaning to the + opaque value. + + zalloc must return Z_NULL if there is not enough memory for the object. + If zlib is used in a multi-threaded application, zalloc and zfree must be + thread safe. In that case, zlib is thread-safe. When zalloc and zfree are + Z_NULL on entry to the initialization function, they are set to internal + routines that use the standard library functions malloc() and free(). + + On 16-bit systems, the functions zalloc and zfree must be able to allocate + exactly 65536 bytes, but will not be required to allocate more than this if + the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS, pointers + returned by zalloc for objects of exactly 65536 bytes *must* have their + offset normalized to zero. The default allocation function provided by this + library ensures this (see zutil.c). To reduce memory requirements and avoid + any allocation of 64K objects, at the expense of compression ratio, compile + the library with -DMAX_WBITS=14 (see zconf.h). + + The fields total_in and total_out can be used for statistics or progress + reports. After compression, total_in holds the total size of the + uncompressed data and may be saved for use by the decompressor (particularly + if the decompressor wants to decompress everything in a single step). +*/ + + /* constants */ + +#define Z_NO_FLUSH 0 +#define Z_PARTIAL_FLUSH 1 +#define Z_SYNC_FLUSH 2 +#define Z_FULL_FLUSH 3 +#define Z_FINISH 4 +#define Z_BLOCK 5 +#define Z_TREES 6 +/* Allowed flush values; see deflate() and inflate() below for details */ + +#define Z_OK 0 +#define Z_STREAM_END 1 +#define Z_NEED_DICT 2 +#define Z_ERRNO (-1) +#define Z_STREAM_ERROR (-2) +#define Z_DATA_ERROR (-3) +#define Z_MEM_ERROR (-4) +#define Z_BUF_ERROR (-5) +#define Z_VERSION_ERROR (-6) +/* Return codes for the compression/decompression functions. Negative values + * are errors, positive values are used for special but normal events. + */ + +#define Z_NO_COMPRESSION 0 +#define Z_BEST_SPEED 1 +#define Z_BEST_COMPRESSION 9 +#define Z_DEFAULT_COMPRESSION (-1) +/* compression levels */ + +#define Z_FILTERED 1 +#define Z_HUFFMAN_ONLY 2 +#define Z_RLE 3 +#define Z_FIXED 4 +#define Z_DEFAULT_STRATEGY 0 +/* compression strategy; see deflateInit2() below for details */ + +#define Z_BINARY 0 +#define Z_TEXT 1 +#define Z_ASCII Z_TEXT /* for compatibility with 1.2.2 and earlier */ +#define Z_UNKNOWN 2 +/* Possible values of the data_type field for deflate() */ + +#define Z_DEFLATED 8 +/* The deflate compression method (the only one supported in this version) */ + +#define Z_NULL 0 /* for initializing zalloc, zfree, opaque */ + +#define zlib_version zlibVersion() +/* for compatibility with versions < 1.0.2 */ + + + /* basic functions */ + +ZEXTERN const char * ZEXPORT zlibVersion OF((void)); +/* The application can compare zlibVersion and ZLIB_VERSION for consistency. + If the first character differs, the library code actually used is not + compatible with the zlib.h header file used by the application. This check + is automatically made by deflateInit and inflateInit. + */ + +/* +ZEXTERN int ZEXPORT deflateInit OF((z_streamp strm, int level)); + + Initializes the internal stream state for compression. The fields + zalloc, zfree and opaque must be initialized before by the caller. If + zalloc and zfree are set to Z_NULL, deflateInit updates them to use default + allocation functions. + + The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9: + 1 gives best speed, 9 gives best compression, 0 gives no compression at all + (the input data is simply copied a block at a time). Z_DEFAULT_COMPRESSION + requests a default compromise between speed and compression (currently + equivalent to level 6). + + deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if level is not a valid compression level, or + Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible + with the version assumed by the caller (ZLIB_VERSION). msg is set to null + if there is no error message. deflateInit does not perform any compression: + this will be done by deflate(). +*/ + + +ZEXTERN int ZEXPORT deflate OF((z_streamp strm, int flush)); +/* + deflate compresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. deflate performs one or both of the + following actions: + + - Compress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), next_in and avail_in are updated and + processing will resume at this point for the next call of deflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. This action is forced if the parameter flush is non zero. + Forcing flush frequently degrades the compression ratio, so this parameter + should be set only when necessary. Some output may be provided even if + flush is zero. + + Before the call of deflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating avail_in or avail_out accordingly; avail_out should + never be zero before the call. The application can consume the compressed + output when it wants, for example when the output buffer is full (avail_out + == 0), or after each call of deflate(). If deflate returns Z_OK and with + zero avail_out, it must be called again after making room in the output + buffer because there might be more output pending. See deflatePending(), + which can be used if desired to determine whether or not there is more ouput + in that case. + + Normally the parameter flush is set to Z_NO_FLUSH, which allows deflate to + decide how much data to accumulate before producing output, in order to + maximize compression. + + If the parameter flush is set to Z_SYNC_FLUSH, all pending output is + flushed to the output buffer and the output is aligned on a byte boundary, so + that the decompressor can get all input data available so far. (In + particular avail_in is zero after the call if enough output space has been + provided before the call.) Flushing may degrade compression for some + compression algorithms and so it should be used only when necessary. This + completes the current deflate block and follows it with an empty stored block + that is three bits plus filler bits to the next byte, followed by four bytes + (00 00 ff ff). + + If flush is set to Z_PARTIAL_FLUSH, all pending output is flushed to the + output buffer, but the output is not aligned to a byte boundary. All of the + input data so far will be available to the decompressor, as for Z_SYNC_FLUSH. + This completes the current deflate block and follows it with an empty fixed + codes block that is 10 bits long. This assures that enough bytes are output + in order for the decompressor to finish the block before the empty fixed + codes block. + + If flush is set to Z_BLOCK, a deflate block is completed and emitted, as + for Z_SYNC_FLUSH, but the output is not aligned on a byte boundary, and up to + seven bits of the current block are held to be written as the next byte after + the next deflate block is completed. In this case, the decompressor may not + be provided enough bits at this point in order to complete decompression of + the data provided so far to the compressor. It may need to wait for the next + block to be emitted. This is for advanced applications that need to control + the emission of deflate blocks. + + If flush is set to Z_FULL_FLUSH, all output is flushed as with + Z_SYNC_FLUSH, and the compression state is reset so that decompression can + restart from this point if previous compressed data has been damaged or if + random access is desired. Using Z_FULL_FLUSH too often can seriously degrade + compression. + + If deflate returns with avail_out == 0, this function must be called again + with the same value of the flush parameter and more output space (updated + avail_out), until the flush is complete (deflate returns with non-zero + avail_out). In the case of a Z_FULL_FLUSH or Z_SYNC_FLUSH, make sure that + avail_out is greater than six to avoid repeated flush markers due to + avail_out == 0 on return. + + If the parameter flush is set to Z_FINISH, pending input is processed, + pending output is flushed and deflate returns with Z_STREAM_END if there was + enough output space. If deflate returns with Z_OK or Z_BUF_ERROR, this + function must be called again with Z_FINISH and more output space (updated + avail_out) but no more input data, until it returns with Z_STREAM_END or an + error. After deflate has returned Z_STREAM_END, the only possible operations + on the stream are deflateReset or deflateEnd. + + Z_FINISH can be used in the first deflate call after deflateInit if all the + compression is to be done in a single step. In order to complete in one + call, avail_out must be at least the value returned by deflateBound (see + below). Then deflate is guaranteed to return Z_STREAM_END. If not enough + output space is provided, deflate will not return Z_STREAM_END, and it must + be called again as described above. + + deflate() sets strm->adler to the Adler-32 checksum of all input read + so far (that is, total_in bytes). If a gzip stream is being generated, then + strm->adler will be the CRC-32 checksum of the input read so far. (See + deflateInit2 below.) + + deflate() may update strm->data_type if it can make a good guess about + the input data type (Z_BINARY or Z_TEXT). If in doubt, the data is + considered binary. This field is only for information purposes and does not + affect the compression algorithm in any manner. + + deflate() returns Z_OK if some progress has been made (more input + processed or more output produced), Z_STREAM_END if all input has been + consumed and all output has been produced (only when flush is set to + Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example + if next_in or next_out was Z_NULL or the state was inadvertently written over + by the application), or Z_BUF_ERROR if no progress is possible (for example + avail_in or avail_out was zero). Note that Z_BUF_ERROR is not fatal, and + deflate() can be called again with more input and more output space to + continue compressing. +*/ + + +ZEXTERN int ZEXPORT deflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the + stream state was inconsistent, Z_DATA_ERROR if the stream was freed + prematurely (some input or output was discarded). In the error case, msg + may be set but then points to a static string (which must not be + deallocated). +*/ + + +/* +ZEXTERN int ZEXPORT inflateInit OF((z_streamp strm)); + + Initializes the internal stream state for decompression. The fields + next_in, avail_in, zalloc, zfree and opaque must be initialized before by + the caller. In the current version of inflate, the provided input is not + read or consumed. The allocation of a sliding window will be deferred to + the first call of inflate (if the decompression does not complete on the + first call). If zalloc and zfree are set to Z_NULL, inflateInit updates + them to use default allocation functions. + + inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit does not perform any decompression. + Actual decompression will be done by inflate(). So next_in, and avail_in, + next_out, and avail_out are unused and unchanged. The current + implementation of inflateInit() does not process any header information -- + that is deferred until inflate() is called. +*/ + + +ZEXTERN int ZEXPORT inflate OF((z_streamp strm, int flush)); +/* + inflate decompresses as much data as possible, and stops when the input + buffer becomes empty or the output buffer becomes full. It may introduce + some output latency (reading input without producing any output) except when + forced to flush. + + The detailed semantics are as follows. inflate performs one or both of the + following actions: + + - Decompress more input starting at next_in and update next_in and avail_in + accordingly. If not all input can be processed (because there is not + enough room in the output buffer), then next_in and avail_in are updated + accordingly, and processing will resume at this point for the next call of + inflate(). + + - Generate more output starting at next_out and update next_out and avail_out + accordingly. inflate() provides as much output as possible, until there is + no more input data or no more space in the output buffer (see below about + the flush parameter). + + Before the call of inflate(), the application should ensure that at least + one of the actions is possible, by providing more input and/or consuming more + output, and updating the next_* and avail_* values accordingly. If the + caller of inflate() does not provide both available input and available + output space, it is possible that there will be no progress made. The + application can consume the uncompressed output when it wants, for example + when the output buffer is full (avail_out == 0), or after each call of + inflate(). If inflate returns Z_OK and with zero avail_out, it must be + called again after making room in the output buffer because there might be + more output pending. + + The flush parameter of inflate() can be Z_NO_FLUSH, Z_SYNC_FLUSH, Z_FINISH, + Z_BLOCK, or Z_TREES. Z_SYNC_FLUSH requests that inflate() flush as much + output as possible to the output buffer. Z_BLOCK requests that inflate() + stop if and when it gets to the next deflate block boundary. When decoding + the zlib or gzip format, this will cause inflate() to return immediately + after the header and before the first block. When doing a raw inflate, + inflate() will go ahead and process the first block, and will return when it + gets to the end of that block, or when it runs out of data. + + The Z_BLOCK option assists in appending to or combining deflate streams. + To assist in this, on return inflate() always sets strm->data_type to the + number of unused bits in the last byte taken from strm->next_in, plus 64 if + inflate() is currently decoding the last block in the deflate stream, plus + 128 if inflate() returned immediately after decoding an end-of-block code or + decoding the complete header up to just before the first byte of the deflate + stream. The end-of-block will not be indicated until all of the uncompressed + data from that block has been written to strm->next_out. The number of + unused bits may in general be greater than seven, except when bit 7 of + data_type is set, in which case the number of unused bits will be less than + eight. data_type is set as noted here every time inflate() returns for all + flush options, and so can be used to determine the amount of currently + consumed input in bits. + + The Z_TREES option behaves as Z_BLOCK does, but it also returns when the + end of each deflate block header is reached, before any actual data in that + block is decoded. This allows the caller to determine the length of the + deflate block header for later use in random access within a deflate block. + 256 is added to the value of strm->data_type when inflate() returns + immediately after reaching the end of the deflate block header. + + inflate() should normally be called until it returns Z_STREAM_END or an + error. However if all decompression is to be performed in a single step (a + single call of inflate), the parameter flush should be set to Z_FINISH. In + this case all pending input is processed and all pending output is flushed; + avail_out must be large enough to hold all of the uncompressed data for the + operation to complete. (The size of the uncompressed data may have been + saved by the compressor for this purpose.) The use of Z_FINISH is not + required to perform an inflation in one step. However it may be used to + inform inflate that a faster approach can be used for the single inflate() + call. Z_FINISH also informs inflate to not maintain a sliding window if the + stream completes, which reduces inflate's memory footprint. If the stream + does not complete, either because not all of the stream is provided or not + enough output space is provided, then a sliding window will be allocated and + inflate() can be called again to continue the operation as if Z_NO_FLUSH had + been used. + + In this implementation, inflate() always flushes as much output as + possible to the output buffer, and always uses the faster approach on the + first call. So the effects of the flush parameter in this implementation are + on the return value of inflate() as noted below, when inflate() returns early + when Z_BLOCK or Z_TREES is used, and when inflate() avoids the allocation of + memory for a sliding window when Z_FINISH is used. + + If a preset dictionary is needed after this call (see inflateSetDictionary + below), inflate sets strm->adler to the Adler-32 checksum of the dictionary + chosen by the compressor and returns Z_NEED_DICT; otherwise it sets + strm->adler to the Adler-32 checksum of all output produced so far (that is, + total_out bytes) and returns Z_OK, Z_STREAM_END or an error code as described + below. At the end of the stream, inflate() checks that its computed Adler-32 + checksum is equal to that saved by the compressor and returns Z_STREAM_END + only if the checksum is correct. + + inflate() can decompress and check either zlib-wrapped or gzip-wrapped + deflate data. The header type is detected automatically, if requested when + initializing with inflateInit2(). Any information contained in the gzip + header is not retained unless inflateGetHeader() is used. When processing + gzip-wrapped deflate data, strm->adler32 is set to the CRC-32 of the output + produced so far. The CRC-32 is checked against the gzip trailer, as is the + uncompressed length, modulo 2^32. + + inflate() returns Z_OK if some progress has been made (more input processed + or more output produced), Z_STREAM_END if the end of the compressed data has + been reached and all uncompressed output has been produced, Z_NEED_DICT if a + preset dictionary is needed at this point, Z_DATA_ERROR if the input data was + corrupted (input stream not conforming to the zlib format or incorrect check + value, in which case strm->msg points to a string with a more specific + error), Z_STREAM_ERROR if the stream structure was inconsistent (for example + next_in or next_out was Z_NULL, or the state was inadvertently written over + by the application), Z_MEM_ERROR if there was not enough memory, Z_BUF_ERROR + if no progress was possible or if there was not enough room in the output + buffer when Z_FINISH is used. Note that Z_BUF_ERROR is not fatal, and + inflate() can be called again with more input and more output space to + continue decompressing. If Z_DATA_ERROR is returned, the application may + then call inflateSync() to look for a good compression block if a partial + recovery of the data is to be attempted. +*/ + + +ZEXTERN int ZEXPORT inflateEnd OF((z_streamp strm)); +/* + All dynamically allocated data structures for this stream are freed. + This function discards any unprocessed input and does not flush any pending + output. + + inflateEnd returns Z_OK if success, or Z_STREAM_ERROR if the stream state + was inconsistent. +*/ + + + /* Advanced functions */ + +/* + The following functions are needed only in some special applications. +*/ + +/* +ZEXTERN int ZEXPORT deflateInit2 OF((z_streamp strm, + int level, + int method, + int windowBits, + int memLevel, + int strategy)); + + This is another version of deflateInit with more compression options. The + fields next_in, zalloc, zfree and opaque must be initialized before by the + caller. + + The method parameter is the compression method. It must be Z_DEFLATED in + this version of the library. + + The windowBits parameter is the base two logarithm of the window size + (the size of the history buffer). It should be in the range 8..15 for this + version of the library. Larger values of this parameter result in better + compression at the expense of memory usage. The default value is 15 if + deflateInit is used instead. + + For the current implementation of deflate(), a windowBits value of 8 (a + window size of 256 bytes) is not supported. As a result, a request for 8 + will result in 9 (a 512-byte window). In that case, providing 8 to + inflateInit2() will result in an error when the zlib header with 9 is + checked against the initialization of inflate(). The remedy is to not use 8 + with deflateInit2() with this initialization, or at least in that case use 9 + with inflateInit2(). + + windowBits can also be -8..-15 for raw deflate. In this case, -windowBits + determines the window size. deflate() will then generate raw deflate data + with no zlib header or trailer, and will not compute a check value. + + windowBits can also be greater than 15 for optional gzip encoding. Add + 16 to windowBits to write a simple gzip header and trailer around the + compressed data instead of a zlib wrapper. The gzip header will have no + file name, no extra data, no comment, no modification time (set to zero), no + header crc, and the operating system will be set to the appropriate value, + if the operating system was determined at compile time. If a gzip stream is + being written, strm->adler is a CRC-32 instead of an Adler-32. + + For raw deflate or gzip encoding, a request for a 256-byte window is + rejected as invalid, since only the zlib header provides a means of + transmitting the window size to the decompressor. + + The memLevel parameter specifies how much memory should be allocated + for the internal compression state. memLevel=1 uses minimum memory but is + slow and reduces compression ratio; memLevel=9 uses maximum memory for + optimal speed. The default value is 8. See zconf.h for total memory usage + as a function of windowBits and memLevel. + + The strategy parameter is used to tune the compression algorithm. Use the + value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a + filter (or predictor), Z_HUFFMAN_ONLY to force Huffman encoding only (no + string match), or Z_RLE to limit match distances to one (run-length + encoding). Filtered data consists mostly of small values with a somewhat + random distribution. In this case, the compression algorithm is tuned to + compress them better. The effect of Z_FILTERED is to force more Huffman + coding and less string matching; it is somewhat intermediate between + Z_DEFAULT_STRATEGY and Z_HUFFMAN_ONLY. Z_RLE is designed to be almost as + fast as Z_HUFFMAN_ONLY, but give better compression for PNG image data. The + strategy parameter only affects the compression ratio but not the + correctness of the compressed output even if it is not set appropriately. + Z_FIXED prevents the use of dynamic Huffman codes, allowing for a simpler + decoder for special applications. + + deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_STREAM_ERROR if any parameter is invalid (such as an invalid + method), or Z_VERSION_ERROR if the zlib library version (zlib_version) is + incompatible with the version assumed by the caller (ZLIB_VERSION). msg is + set to null if there is no error message. deflateInit2 does not perform any + compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the compression dictionary from the given byte sequence + without producing any compressed output. When using the zlib format, this + function must be called immediately after deflateInit, deflateInit2 or + deflateReset, and before any call of deflate. When doing raw deflate, this + function must be called either before any call of deflate, or immediately + after the completion of a deflate block, i.e. after all input has been + consumed and all output has been delivered when using any of the flush + options Z_BLOCK, Z_PARTIAL_FLUSH, Z_SYNC_FLUSH, or Z_FULL_FLUSH. The + compressor and decompressor must use exactly the same dictionary (see + inflateSetDictionary). + + The dictionary should consist of strings (byte sequences) that are likely + to be encountered later in the data to be compressed, with the most commonly + used strings preferably put towards the end of the dictionary. Using a + dictionary is most useful when the data to be compressed is short and can be + predicted with good accuracy; the data can then be compressed better than + with the default empty dictionary. + + Depending on the size of the compression data structures selected by + deflateInit or deflateInit2, a part of the dictionary may in effect be + discarded, for example if the dictionary is larger than the window size + provided in deflateInit or deflateInit2. Thus the strings most likely to be + useful should be put at the end of the dictionary, not at the front. In + addition, the current implementation of deflate will use at most the window + size minus 262 bytes of the provided dictionary. + + Upon return of this function, strm->adler is set to the Adler-32 value + of the dictionary; the decompressor may later use this value to determine + which dictionary has been used by the compressor. (The Adler-32 value + applies to the whole dictionary even if only a subset of the dictionary is + actually used by the compressor.) If a raw deflate was requested, then the + Adler-32 value is not computed and strm->adler is not set. + + deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent (for example if deflate has already been called for this stream + or if not at a block boundary for raw deflate). deflateSetDictionary does + not perform any compression: this will be done by deflate(). +*/ + +ZEXTERN int ZEXPORT deflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by deflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If deflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + deflateGetDictionary() may return a length less than the window size, even + when more than the window size in input has been provided. It may return up + to 258 bytes less in that case, due to how zlib's implementation of deflate + manages the sliding window and lookahead for matches, where matches can be + up to 258 bytes long. If the application needs the last window-size bytes of + input, then that would need to be saved by the application outside of zlib. + + deflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when several compression strategies will be + tried, for example when there are several ways of pre-processing the input + data with a filter. The streams that will be discarded should then be freed + by calling deflateEnd. Note that deflateCopy duplicates the internal + compression state which can be quite large, so this strategy is slow and can + consume lots of memory. + + deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT deflateReset OF((z_streamp strm)); +/* + This function is equivalent to deflateEnd followed by deflateInit, but + does not free and reallocate the internal compression state. The stream + will leave the compression level and any other attributes that may have been + set unchanged. + + deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT deflateParams OF((z_streamp strm, + int level, + int strategy)); +/* + Dynamically update the compression level and compression strategy. The + interpretation of level and strategy is as in deflateInit2(). This can be + used to switch between compression and straight copy of the input data, or + to switch to a different kind of input data requiring a different strategy. + If the compression approach (which is a function of the level) or the + strategy is changed, and if any input has been consumed in a previous + deflate() call, then the input available so far is compressed with the old + level and strategy using deflate(strm, Z_BLOCK). There are three approaches + for the compression levels 0, 1..3, and 4..9 respectively. The new level + and strategy will take effect at the next call of deflate(). + + If a deflate(strm, Z_BLOCK) is performed by deflateParams(), and it does + not have enough output space to complete, then the parameter change will not + take effect. In this case, deflateParams() can be called again with the + same parameters and more output space to try again. + + In order to assure a change in the parameters on the first try, the + deflate stream should be flushed using deflate() with Z_BLOCK or other flush + request until strm.avail_out is not zero, before calling deflateParams(). + Then no more input data should be provided before the deflateParams() call. + If this is done, the old level and strategy will be applied to the data + compressed before deflateParams(), and the new level and strategy will be + applied to the the data compressed after deflateParams(). + + deflateParams returns Z_OK on success, Z_STREAM_ERROR if the source stream + state was inconsistent or if a parameter was invalid, or Z_BUF_ERROR if + there was not enough output space to complete the compression of the + available input data before a change in the strategy or approach. Note that + in the case of a Z_BUF_ERROR, the parameters are not changed. A return + value of Z_BUF_ERROR is not fatal, in which case deflateParams() can be + retried with more output space. +*/ + +ZEXTERN int ZEXPORT deflateTune OF((z_streamp strm, + int good_length, + int max_lazy, + int nice_length, + int max_chain)); +/* + Fine tune deflate's internal compression parameters. This should only be + used by someone who understands the algorithm used by zlib's deflate for + searching for the best matching string, and even then only by the most + fanatic optimizer trying to squeeze out the last compressed bit for their + specific input data. Read the deflate.c source code for the meaning of the + max_lazy, good_length, nice_length, and max_chain parameters. + + deflateTune() can be called after deflateInit() or deflateInit2(), and + returns Z_OK on success, or Z_STREAM_ERROR for an invalid deflate stream. + */ + +ZEXTERN uLong ZEXPORT deflateBound OF((z_streamp strm, + uLong sourceLen)); +/* + deflateBound() returns an upper bound on the compressed size after + deflation of sourceLen bytes. It must be called after deflateInit() or + deflateInit2(), and after deflateSetHeader(), if used. This would be used + to allocate an output buffer for deflation in a single pass, and so would be + called before deflate(). If that first deflate() call is provided the + sourceLen input bytes, an output buffer allocated to the size returned by + deflateBound(), and the flush value Z_FINISH, then deflate() is guaranteed + to return Z_STREAM_END. Note that it is possible for the compressed size to + be larger than the value returned by deflateBound() if flush options other + than Z_FINISH or Z_NO_FLUSH are used. +*/ + +ZEXTERN int ZEXPORT deflatePending OF((z_streamp strm, + unsigned *pending, + int *bits)); +/* + deflatePending() returns the number of bytes and bits of output that have + been generated, but not yet provided in the available output. The bytes not + provided would be due to the available output space having being consumed. + The number of bits of output not provided are between 0 and 7, where they + await more bits to join them in order to fill out a full byte. If pending + or bits are Z_NULL, then those values are not set. + + deflatePending returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. + */ + +ZEXTERN int ZEXPORT deflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + deflatePrime() inserts bits in the deflate output stream. The intent + is that this function is used to start off the deflate output with the bits + leftover from a previous deflate stream when appending to it. As such, this + function can only be used for raw deflate, and must be used before the first + deflate() call after a deflateInit2() or deflateReset(). bits must be less + than or equal to 16, and that many of the least significant bits of value + will be inserted in the output. + + deflatePrime returns Z_OK if success, Z_BUF_ERROR if there was not enough + room in the internal buffer to insert the bits, or Z_STREAM_ERROR if the + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT deflateSetHeader OF((z_streamp strm, + gz_headerp head)); +/* + deflateSetHeader() provides gzip header information for when a gzip + stream is requested by deflateInit2(). deflateSetHeader() may be called + after deflateInit2() or deflateReset() and before the first call of + deflate(). The text, time, os, extra field, name, and comment information + in the provided gz_header structure are written to the gzip header (xflag is + ignored -- the extra flags are set according to the compression level). The + caller must assure that, if not Z_NULL, name and comment are terminated with + a zero byte, and that if extra is not Z_NULL, that extra_len bytes are + available there. If hcrc is true, a gzip header crc is included. Note that + the current versions of the command-line version of gzip (up through version + 1.3.x) do not support header crc's, and will report that it is a "multi-part + gzip file" and give up. + + If deflateSetHeader is not used, the default gzip header has text false, + the time set to zero, and os set to 255, with no extra, name, or comment + fields. The gzip header is returned to the default state by deflateReset(). + + deflateSetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateInit2 OF((z_streamp strm, + int windowBits)); + + This is another version of inflateInit with an extra parameter. The + fields next_in, avail_in, zalloc, zfree and opaque must be initialized + before by the caller. + + The windowBits parameter is the base two logarithm of the maximum window + size (the size of the history buffer). It should be in the range 8..15 for + this version of the library. The default value is 15 if inflateInit is used + instead. windowBits must be greater than or equal to the windowBits value + provided to deflateInit2() while compressing, or it must be equal to 15 if + deflateInit2() was not used. If a compressed stream with a larger window + size is given as input, inflate() will return with the error code + Z_DATA_ERROR instead of trying to allocate a larger window. + + windowBits can also be zero to request that inflate use the window size in + the zlib header of the compressed stream. + + windowBits can also be -8..-15 for raw inflate. In this case, -windowBits + determines the window size. inflate() will then process raw deflate data, + not looking for a zlib or gzip header, not generating a check value, and not + looking for any check values for comparison at the end of the stream. This + is for use with other formats that use the deflate compressed data format + such as zip. Those formats provide their own check values. If a custom + format is developed using the raw deflate format for compressed data, it is + recommended that a check value such as an Adler-32 or a CRC-32 be applied to + the uncompressed data as is done in the zlib, gzip, and zip formats. For + most applications, the zlib format should be used as is. Note that comments + above on the use in deflateInit2() applies to the magnitude of windowBits. + + windowBits can also be greater than 15 for optional gzip decoding. Add + 32 to windowBits to enable zlib and gzip decoding with automatic header + detection, or add 16 to decode only the gzip format (the zlib format will + return a Z_DATA_ERROR). If a gzip stream is being decoded, strm->adler is a + CRC-32 instead of an Adler-32. Unlike the gunzip utility and gzread() (see + below), inflate() will not automatically decode concatenated gzip streams. + inflate() will return Z_STREAM_END at the end of the gzip stream. The state + would need to be reset to continue decoding a subsequent gzip stream. + + inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_VERSION_ERROR if the zlib library version is incompatible with the + version assumed by the caller, or Z_STREAM_ERROR if the parameters are + invalid, such as a null pointer to the structure. msg is set to null if + there is no error message. inflateInit2 does not perform any decompression + apart from possibly reading the zlib header if present: actual decompression + will be done by inflate(). (So next_in and avail_in may be modified, but + next_out and avail_out are unused and unchanged.) The current implementation + of inflateInit2() does not process any header information -- that is + deferred until inflate() is called. +*/ + +ZEXTERN int ZEXPORT inflateSetDictionary OF((z_streamp strm, + const Bytef *dictionary, + uInt dictLength)); +/* + Initializes the decompression dictionary from the given uncompressed byte + sequence. This function must be called immediately after a call of inflate, + if that call returned Z_NEED_DICT. The dictionary chosen by the compressor + can be determined from the Adler-32 value returned by that call of inflate. + The compressor and decompressor must use exactly the same dictionary (see + deflateSetDictionary). For raw inflate, this function can be called at any + time to set the dictionary. If the provided dictionary is smaller than the + window and there is already data in the window, then the provided dictionary + will amend what's there. The application must insure that the dictionary + that was used for compression is provided. + + inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a + parameter is invalid (e.g. dictionary being Z_NULL) or the stream state is + inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the + expected one (incorrect Adler-32 value). inflateSetDictionary does not + perform any decompression: this will be done by subsequent calls of + inflate(). +*/ + +ZEXTERN int ZEXPORT inflateGetDictionary OF((z_streamp strm, + Bytef *dictionary, + uInt *dictLength)); +/* + Returns the sliding dictionary being maintained by inflate. dictLength is + set to the number of bytes in the dictionary, and that many bytes are copied + to dictionary. dictionary must have enough space, where 32768 bytes is + always enough. If inflateGetDictionary() is called with dictionary equal to + Z_NULL, then only the dictionary length is returned, and nothing is copied. + Similary, if dictLength is Z_NULL, then it is not set. + + inflateGetDictionary returns Z_OK on success, or Z_STREAM_ERROR if the + stream state is inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateSync OF((z_streamp strm)); +/* + Skips invalid compressed data until a possible full flush point (see above + for the description of deflate with Z_FULL_FLUSH) can be found, or until all + available input is skipped. No output is provided. + + inflateSync searches for a 00 00 FF FF pattern in the compressed data. + All full flush points have this pattern, but not all occurrences of this + pattern are full flush points. + + inflateSync returns Z_OK if a possible full flush point has been found, + Z_BUF_ERROR if no more input was provided, Z_DATA_ERROR if no flush point + has been found, or Z_STREAM_ERROR if the stream structure was inconsistent. + In the success case, the application may save the current current value of + total_in which indicates where valid compressed data was found. In the + error case, the application may repeatedly call inflateSync, providing more + input each time, until success or end of the input data. +*/ + +ZEXTERN int ZEXPORT inflateCopy OF((z_streamp dest, + z_streamp source)); +/* + Sets the destination stream as a complete copy of the source stream. + + This function can be useful when randomly accessing a large stream. The + first pass through the stream can periodically record the inflate state, + allowing restarting inflate at those points when randomly accessing the + stream. + + inflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_STREAM_ERROR if the source stream state was inconsistent + (such as zalloc being Z_NULL). msg is left unchanged in both source and + destination. +*/ + +ZEXTERN int ZEXPORT inflateReset OF((z_streamp strm)); +/* + This function is equivalent to inflateEnd followed by inflateInit, + but does not free and reallocate the internal decompression state. The + stream will keep attributes that may have been set by inflateInit2. + + inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL). +*/ + +ZEXTERN int ZEXPORT inflateReset2 OF((z_streamp strm, + int windowBits)); +/* + This function is the same as inflateReset, but it also permits changing + the wrap and window size requests. The windowBits parameter is interpreted + the same as it is for inflateInit2. If the window size is changed, then the + memory allocated for the window is freed, and the window will be reallocated + by inflate() if needed. + + inflateReset2 returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent (such as zalloc or state being Z_NULL), or if + the windowBits parameter is invalid. +*/ + +ZEXTERN int ZEXPORT inflatePrime OF((z_streamp strm, + int bits, + int value)); +/* + This function inserts bits in the inflate input stream. The intent is + that this function is used to start inflating at a bit position in the + middle of a byte. The provided bits will be used before any bytes are used + from next_in. This function should only be used with raw inflate, and + should be used before the first inflate() call after inflateInit2() or + inflateReset(). bits must be less than or equal to 16, and that many of the + least significant bits of value will be inserted in the input. + + If bits is negative, then the input stream bit buffer is emptied. Then + inflatePrime() can be called again to put bits in the buffer. This is used + to clear out bits leftover after feeding inflate a block description prior + to feeding inflate codes. + + inflatePrime returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +ZEXTERN long ZEXPORT inflateMark OF((z_streamp strm)); +/* + This function returns two values, one in the lower 16 bits of the return + value, and the other in the remaining upper bits, obtained by shifting the + return value down 16 bits. If the upper value is -1 and the lower value is + zero, then inflate() is currently decoding information outside of a block. + If the upper value is -1 and the lower value is non-zero, then inflate is in + the middle of a stored block, with the lower value equaling the number of + bytes from the input remaining to copy. If the upper value is not -1, then + it is the number of bits back from the current bit position in the input of + the code (literal or length/distance pair) currently being processed. In + that case the lower value is the number of bytes already emitted for that + code. + + A code is being processed if inflate is waiting for more input to complete + decoding of the code, or if it has completed decoding but is waiting for + more output space to write the literal or match data. + + inflateMark() is used to mark locations in the input data for random + access, which may be at bit positions, and to note those cases where the + output of a code may span boundaries of random access blocks. The current + location in the input stream can be determined from avail_in and data_type + as noted in the description for the Z_BLOCK flush parameter for inflate. + + inflateMark returns the value noted above, or -65536 if the provided + source stream state was inconsistent. +*/ + +ZEXTERN int ZEXPORT inflateGetHeader OF((z_streamp strm, + gz_headerp head)); +/* + inflateGetHeader() requests that gzip header information be stored in the + provided gz_header structure. inflateGetHeader() may be called after + inflateInit2() or inflateReset(), and before the first call of inflate(). + As inflate() processes the gzip stream, head->done is zero until the header + is completed, at which time head->done is set to one. If a zlib stream is + being decoded, then head->done is set to -1 to indicate that there will be + no gzip header information forthcoming. Note that Z_BLOCK or Z_TREES can be + used to force inflate() to return immediately after header processing is + complete and before any actual data is decompressed. + + The text, time, xflags, and os fields are filled in with the gzip header + contents. hcrc is set to true if there is a header CRC. (The header CRC + was valid if done is set to one.) If extra is not Z_NULL, then extra_max + contains the maximum number of bytes to write to extra. Once done is true, + extra_len contains the actual extra field length, and extra contains the + extra field, or that field truncated if extra_max is less than extra_len. + If name is not Z_NULL, then up to name_max characters are written there, + terminated with a zero unless the length is greater than name_max. If + comment is not Z_NULL, then up to comm_max characters are written there, + terminated with a zero unless the length is greater than comm_max. When any + of extra, name, or comment are not Z_NULL and the respective field is not + present in the header, then that field is set to Z_NULL to signal its + absence. This allows the use of deflateSetHeader() with the returned + structure to duplicate the header. However if those fields are set to + allocated memory, then the application will need to save those pointers + elsewhere so that they can be eventually freed. + + If inflateGetHeader is not used, then the header information is simply + discarded. The header is always checked for validity, including the header + CRC if present. inflateReset() will reset the process to discard the header + information. The application would need to call inflateGetHeader() again to + retrieve the header from the next gzip stream. + + inflateGetHeader returns Z_OK if success, or Z_STREAM_ERROR if the source + stream state was inconsistent. +*/ + +/* +ZEXTERN int ZEXPORT inflateBackInit OF((z_streamp strm, int windowBits, + unsigned char FAR *window)); + + Initialize the internal stream state for decompression using inflateBack() + calls. The fields zalloc, zfree and opaque in strm must be initialized + before the call. If zalloc and zfree are Z_NULL, then the default library- + derived memory allocation routines are used. windowBits is the base two + logarithm of the window size, in the range 8..15. window is a caller + supplied buffer of that size. Except for special applications where it is + assured that deflate was used with small window sizes, windowBits must be 15 + and a 32K byte window must be supplied to be able to decompress general + deflate streams. + + See inflateBack() for the usage of these routines. + + inflateBackInit will return Z_OK on success, Z_STREAM_ERROR if any of + the parameters are invalid, Z_MEM_ERROR if the internal state could not be + allocated, or Z_VERSION_ERROR if the version of the library does not match + the version of the header file. +*/ + +typedef unsigned (*in_func) OF((void FAR *, + z_const unsigned char FAR * FAR *)); +typedef int (*out_func) OF((void FAR *, unsigned char FAR *, unsigned)); + +ZEXTERN int ZEXPORT inflateBack OF((z_streamp strm, + in_func in, void FAR *in_desc, + out_func out, void FAR *out_desc)); +/* + inflateBack() does a raw inflate with a single call using a call-back + interface for input and output. This is potentially more efficient than + inflate() for file i/o applications, in that it avoids copying between the + output and the sliding window by simply making the window itself the output + buffer. inflate() can be faster on modern CPUs when used with large + buffers. inflateBack() trusts the application to not change the output + buffer passed by the output function, at least until inflateBack() returns. + + inflateBackInit() must be called first to allocate the internal state + and to initialize the state with the user-provided window buffer. + inflateBack() may then be used multiple times to inflate a complete, raw + deflate stream with each call. inflateBackEnd() is then called to free the + allocated state. + + A raw deflate stream is one with no zlib or gzip header or trailer. + This routine would normally be used in a utility that reads zip or gzip + files and writes out uncompressed files. The utility would decode the + header and process the trailer on its own, hence this routine expects only + the raw deflate stream to decompress. This is different from the default + behavior of inflate(), which expects a zlib header and trailer around the + deflate stream. + + inflateBack() uses two subroutines supplied by the caller that are then + called by inflateBack() for input and output. inflateBack() calls those + routines until it reads a complete deflate stream and writes out all of the + uncompressed data, or until it encounters an error. The function's + parameters and return types are defined above in the in_func and out_func + typedefs. inflateBack() will call in(in_desc, &buf) which should return the + number of bytes of provided input, and a pointer to that input in buf. If + there is no input available, in() must return zero -- buf is ignored in that + case -- and inflateBack() will return a buffer error. inflateBack() will + call out(out_desc, buf, len) to write the uncompressed data buf[0..len-1]. + out() should return zero on success, or non-zero on failure. If out() + returns non-zero, inflateBack() will return with an error. Neither in() nor + out() are permitted to change the contents of the window provided to + inflateBackInit(), which is also the buffer that out() uses to write from. + The length written by out() will be at most the window size. Any non-zero + amount of input may be provided by in(). + + For convenience, inflateBack() can be provided input on the first call by + setting strm->next_in and strm->avail_in. If that input is exhausted, then + in() will be called. Therefore strm->next_in must be initialized before + calling inflateBack(). If strm->next_in is Z_NULL, then in() will be called + immediately for input. If strm->next_in is not Z_NULL, then strm->avail_in + must also be initialized, and then if strm->avail_in is not zero, input will + initially be taken from strm->next_in[0 .. strm->avail_in - 1]. + + The in_desc and out_desc parameters of inflateBack() is passed as the + first parameter of in() and out() respectively when they are called. These + descriptors can be optionally used to pass any information that the caller- + supplied in() and out() functions need to do their job. + + On return, inflateBack() will set strm->next_in and strm->avail_in to + pass back any unused input that was provided by the last in() call. The + return values of inflateBack() can be Z_STREAM_END on success, Z_BUF_ERROR + if in() or out() returned an error, Z_DATA_ERROR if there was a format error + in the deflate stream (in which case strm->msg is set to indicate the nature + of the error), or Z_STREAM_ERROR if the stream was not properly initialized. + In the case of Z_BUF_ERROR, an input or output error can be distinguished + using strm->next_in which will be Z_NULL only if in() returned an error. If + strm->next_in is not Z_NULL, then the Z_BUF_ERROR was due to out() returning + non-zero. (in() will always be called before out(), so strm->next_in is + assured to be defined if out() returns non-zero.) Note that inflateBack() + cannot return Z_OK. +*/ + +ZEXTERN int ZEXPORT inflateBackEnd OF((z_streamp strm)); +/* + All memory allocated by inflateBackInit() is freed. + + inflateBackEnd() returns Z_OK on success, or Z_STREAM_ERROR if the stream + state was inconsistent. +*/ + +ZEXTERN uLong ZEXPORT zlibCompileFlags OF((void)); +/* Return flags indicating compile-time options. + + Type sizes, two bits each, 00 = 16 bits, 01 = 32, 10 = 64, 11 = other: + 1.0: size of uInt + 3.2: size of uLong + 5.4: size of voidpf (pointer) + 7.6: size of z_off_t + + Compiler, assembler, and debug options: + 8: ZLIB_DEBUG + 9: ASMV or ASMINF -- use ASM code + 10: ZLIB_WINAPI -- exported functions use the WINAPI calling convention + 11: 0 (reserved) + + One-time table building (smaller code, but not thread-safe if true): + 12: BUILDFIXED -- build static block decoding tables when needed + 13: DYNAMIC_CRC_TABLE -- build CRC calculation tables when needed + 14,15: 0 (reserved) + + Library content (indicates missing functionality): + 16: NO_GZCOMPRESS -- gz* functions cannot compress (to avoid linking + deflate code when not needed) + 17: NO_GZIP -- deflate can't write gzip streams, and inflate can't detect + and decode gzip streams (to avoid linking crc code) + 18-19: 0 (reserved) + + Operation variations (changes in library functionality): + 20: PKZIP_BUG_WORKAROUND -- slightly more permissive inflate + 21: FASTEST -- deflate algorithm with only one, lowest compression level + 22,23: 0 (reserved) + + The sprintf variant used by gzprintf (zero is best): + 24: 0 = vs*, 1 = s* -- 1 means limited to 20 arguments after the format + 25: 0 = *nprintf, 1 = *printf -- 1 means gzprintf() not secure! + 26: 0 = returns value, 1 = void -- 1 means inferred string length returned + + Remainder: + 27-31: 0 (reserved) + */ + +#ifndef Z_SOLO + + /* utility functions */ + +/* + The following utility functions are implemented on top of the basic + stream-oriented functions. To simplify the interface, some default options + are assumed (compression level and memory usage, standard memory allocation + functions). The source code of these utility functions can be modified if + you need special options. +*/ + +ZEXTERN int ZEXPORT compress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Compresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. compress() is equivalent to compress2() with a level + parameter of Z_DEFAULT_COMPRESSION. + + compress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer. +*/ + +ZEXTERN int ZEXPORT compress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen, + int level)); +/* + Compresses the source buffer into the destination buffer. The level + parameter has the same meaning as in deflateInit. sourceLen is the byte + length of the source buffer. Upon entry, destLen is the total size of the + destination buffer, which must be at least the value returned by + compressBound(sourceLen). Upon exit, destLen is the actual size of the + compressed data. + + compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough + memory, Z_BUF_ERROR if there was not enough room in the output buffer, + Z_STREAM_ERROR if the level parameter is invalid. +*/ + +ZEXTERN uLong ZEXPORT compressBound OF((uLong sourceLen)); +/* + compressBound() returns an upper bound on the compressed size after + compress() or compress2() on sourceLen bytes. It would be used before a + compress() or compress2() call to allocate the destination buffer. +*/ + +ZEXTERN int ZEXPORT uncompress OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong sourceLen)); +/* + Decompresses the source buffer into the destination buffer. sourceLen is + the byte length of the source buffer. Upon entry, destLen is the total size + of the destination buffer, which must be large enough to hold the entire + uncompressed data. (The size of the uncompressed data must have been saved + previously by the compressor and transmitted to the decompressor by some + mechanism outside the scope of this compression library.) Upon exit, destLen + is the actual size of the uncompressed data. + + uncompress returns Z_OK if success, Z_MEM_ERROR if there was not + enough memory, Z_BUF_ERROR if there was not enough room in the output + buffer, or Z_DATA_ERROR if the input data was corrupted or incomplete. In + the case where there is not enough room, uncompress() will fill the output + buffer with the uncompressed data up to that point. +*/ + +ZEXTERN int ZEXPORT uncompress2 OF((Bytef *dest, uLongf *destLen, + const Bytef *source, uLong *sourceLen)); +/* + Same as uncompress, except that sourceLen is a pointer, where the + length of the source is *sourceLen. On return, *sourceLen is the number of + source bytes consumed. +*/ + + /* gzip file access functions */ + +/* + This library supports reading and writing files in gzip (.gz) format with + an interface similar to that of stdio, using the functions that start with + "gz". The gzip format is different from the zlib format. gzip is a gzip + wrapper, documented in RFC 1952, wrapped around a deflate stream. +*/ + +typedef struct gzFile_s *gzFile; /* semi-opaque gzip file descriptor */ + +/* +ZEXTERN gzFile ZEXPORT gzopen OF((const char *path, const char *mode)); + + Opens a gzip (.gz) file for reading or writing. The mode parameter is as + in fopen ("rb" or "wb") but can also include a compression level ("wb9") or + a strategy: 'f' for filtered data as in "wb6f", 'h' for Huffman-only + compression as in "wb1h", 'R' for run-length encoding as in "wb1R", or 'F' + for fixed code compression as in "wb9F". (See the description of + deflateInit2 for more information about the strategy parameter.) 'T' will + request transparent writing or appending with no compression and not using + the gzip format. + + "a" can be used instead of "w" to request that the gzip stream that will + be written be appended to the file. "+" will result in an error, since + reading and writing to the same gzip file is not supported. The addition of + "x" when writing will create the file exclusively, which fails if the file + already exists. On systems that support it, the addition of "e" when + reading or writing will set the flag to close the file on an execve() call. + + These functions, as well as gzip, will read and decode a sequence of gzip + streams in a file. The append function of gzopen() can be used to create + such a file. (Also see gzflush() for another way to do this.) When + appending, gzopen does not test whether the file begins with a gzip stream, + nor does it look for the end of the gzip streams to begin appending. gzopen + will simply append a gzip stream to the existing file. + + gzopen can be used to read a file which is not in gzip format; in this + case gzread will directly read from the file without decompression. When + reading, this will be detected automatically by looking for the magic two- + byte gzip header. + + gzopen returns NULL if the file could not be opened, if there was + insufficient memory to allocate the gzFile state, or if an invalid mode was + specified (an 'r', 'w', or 'a' was not provided, or '+' was provided). + errno can be checked to determine if the reason gzopen failed was that the + file could not be opened. +*/ + +ZEXTERN gzFile ZEXPORT gzdopen OF((int fd, const char *mode)); +/* + gzdopen associates a gzFile with the file descriptor fd. File descriptors + are obtained from calls like open, dup, creat, pipe or fileno (if the file + has been previously opened with fopen). The mode parameter is as in gzopen. + + The next call of gzclose on the returned gzFile will also close the file + descriptor fd, just like fclose(fdopen(fd, mode)) closes the file descriptor + fd. If you want to keep fd open, use fd = dup(fd_keep); gz = gzdopen(fd, + mode);. The duplicated descriptor should be saved to avoid a leak, since + gzdopen does not close fd if it fails. If you are using fileno() to get the + file descriptor from a FILE *, then you will have to use dup() to avoid + double-close()ing the file descriptor. Both gzclose() and fclose() will + close the associated file descriptor, so they need to have different file + descriptors. + + gzdopen returns NULL if there was insufficient memory to allocate the + gzFile state, if an invalid mode was specified (an 'r', 'w', or 'a' was not + provided, or '+' was provided), or if fd is -1. The file descriptor is not + used until the next gz* read, write, seek, or close operation, so gzdopen + will not detect if fd is invalid (unless fd is -1). +*/ + +ZEXTERN int ZEXPORT gzbuffer OF((gzFile file, unsigned size)); +/* + Set the internal buffer size used by this library's functions. The + default buffer size is 8192 bytes. This function must be called after + gzopen() or gzdopen(), and before any other calls that read or write the + file. The buffer memory allocation is always deferred to the first read or + write. Three times that size in buffer space is allocated. A larger buffer + size of, for example, 64K or 128K bytes will noticeably increase the speed + of decompression (reading). + + The new buffer size also affects the maximum length for gzprintf(). + + gzbuffer() returns 0 on success, or -1 on failure, such as being called + too late. +*/ + +ZEXTERN int ZEXPORT gzsetparams OF((gzFile file, int level, int strategy)); +/* + Dynamically update the compression level or strategy. See the description + of deflateInit2 for the meaning of these parameters. Previously provided + data is flushed before the parameter change. + + gzsetparams returns Z_OK if success, Z_STREAM_ERROR if the file was not + opened for writing, Z_ERRNO if there is an error writing the flushed data, + or Z_MEM_ERROR if there is a memory allocation error. +*/ + +ZEXTERN int ZEXPORT gzread OF((gzFile file, voidp buf, unsigned len)); +/* + Reads the given number of uncompressed bytes from the compressed file. If + the input file is not in gzip format, gzread copies the given number of + bytes into the buffer directly from the file. + + After reaching the end of a gzip stream in the input, gzread will continue + to read, looking for another gzip stream. Any number of gzip streams may be + concatenated in the input file, and will all be decompressed by gzread(). + If something other than a gzip stream is encountered after a gzip stream, + that remaining trailing garbage is ignored (and no error is returned). + + gzread can be used to read a gzip file that is being concurrently written. + Upon reaching the end of the input, gzread will return with the available + data. If the error code returned by gzerror is Z_OK or Z_BUF_ERROR, then + gzclearerr can be used to clear the end of file indicator in order to permit + gzread to be tried again. Z_OK indicates that a gzip stream was completed + on the last gzread. Z_BUF_ERROR indicates that the input file ended in the + middle of a gzip stream. Note that gzread does not return -1 in the event + of an incomplete gzip stream. This error is deferred until gzclose(), which + will return Z_BUF_ERROR if the last gzread ended in the middle of a gzip + stream. Alternatively, gzerror can be used before gzclose to detect this + case. + + gzread returns the number of uncompressed bytes actually read, less than + len for end of file, or -1 for error. If len is too large to fit in an int, + then nothing is read, -1 is returned, and the error state is set to + Z_STREAM_ERROR. +*/ + +ZEXTERN z_size_t ZEXPORT gzfread OF((voidp buf, z_size_t size, z_size_t nitems, + gzFile file)); +/* + Read up to nitems items of size size from file to buf, otherwise operating + as gzread() does. This duplicates the interface of stdio's fread(), with + size_t request and return types. If the library defines size_t, then + z_size_t is identical to size_t. If not, then z_size_t is an unsigned + integer type that can contain a pointer. + + gzfread() returns the number of full items read of size size, or zero if + the end of the file was reached and a full item could not be read, or if + there was an error. gzerror() must be consulted if zero is returned in + order to determine if there was an error. If the multiplication of size and + nitems overflows, i.e. the product does not fit in a z_size_t, then nothing + is read, zero is returned, and the error state is set to Z_STREAM_ERROR. + + In the event that the end of file is reached and only a partial item is + available at the end, i.e. the remaining uncompressed data length is not a + multiple of size, then the final partial item is nevetheless read into buf + and the end-of-file flag is set. The length of the partial item read is not + provided, but could be inferred from the result of gztell(). This behavior + is the same as the behavior of fread() implementations in common libraries, + but it prevents the direct use of gzfread() to read a concurrently written + file, reseting and retrying on end-of-file, when size is not 1. +*/ + +ZEXTERN int ZEXPORT gzwrite OF((gzFile file, + voidpc buf, unsigned len)); +/* + Writes the given number of uncompressed bytes into the compressed file. + gzwrite returns the number of uncompressed bytes written or 0 in case of + error. +*/ + +ZEXTERN z_size_t ZEXPORT gzfwrite OF((voidpc buf, z_size_t size, + z_size_t nitems, gzFile file)); +/* + gzfwrite() writes nitems items of size size from buf to file, duplicating + the interface of stdio's fwrite(), with size_t request and return types. If + the library defines size_t, then z_size_t is identical to size_t. If not, + then z_size_t is an unsigned integer type that can contain a pointer. + + gzfwrite() returns the number of full items written of size size, or zero + if there was an error. If the multiplication of size and nitems overflows, + i.e. the product does not fit in a z_size_t, then nothing is written, zero + is returned, and the error state is set to Z_STREAM_ERROR. +*/ + +ZEXTERN int ZEXPORTVA gzprintf Z_ARG((gzFile file, const char *format, ...)); +/* + Converts, formats, and writes the arguments to the compressed file under + control of the format string, as in fprintf. gzprintf returns the number of + uncompressed bytes actually written, or a negative zlib error code in case + of error. The number of uncompressed bytes written is limited to 8191, or + one less than the buffer size given to gzbuffer(). The caller should assure + that this limit is not exceeded. If it is exceeded, then gzprintf() will + return an error (0) with nothing written. In this case, there may also be a + buffer overflow with unpredictable consequences, which is possible only if + zlib was compiled with the insecure functions sprintf() or vsprintf() + because the secure snprintf() or vsnprintf() functions were not available. + This can be determined using zlibCompileFlags(). +*/ + +ZEXTERN int ZEXPORT gzputs OF((gzFile file, const char *s)); +/* + Writes the given null-terminated string to the compressed file, excluding + the terminating null character. + + gzputs returns the number of characters written, or -1 in case of error. +*/ + +ZEXTERN char * ZEXPORT gzgets OF((gzFile file, char *buf, int len)); +/* + Reads bytes from the compressed file until len-1 characters are read, or a + newline character is read and transferred to buf, or an end-of-file + condition is encountered. If any characters are read or if len == 1, the + string is terminated with a null character. If no characters are read due + to an end-of-file or len < 1, then the buffer is left untouched. + + gzgets returns buf which is a null-terminated string, or it returns NULL + for end-of-file or in case of error. If there was an error, the contents at + buf are indeterminate. +*/ + +ZEXTERN int ZEXPORT gzputc OF((gzFile file, int c)); +/* + Writes c, converted to an unsigned char, into the compressed file. gzputc + returns the value that was written, or -1 in case of error. +*/ + +ZEXTERN int ZEXPORT gzgetc OF((gzFile file)); +/* + Reads one byte from the compressed file. gzgetc returns this byte or -1 + in case of end of file or error. This is implemented as a macro for speed. + As such, it does not do all of the checking the other functions do. I.e. + it does not check to see if file is NULL, nor whether the structure file + points to has been clobbered or not. +*/ + +ZEXTERN int ZEXPORT gzungetc OF((int c, gzFile file)); +/* + Push one character back onto the stream to be read as the first character + on the next read. At least one character of push-back is allowed. + gzungetc() returns the character pushed, or -1 on failure. gzungetc() will + fail if c is -1, and may fail if a character has been pushed but not read + yet. If gzungetc is used immediately after gzopen or gzdopen, at least the + output buffer size of pushed characters is allowed. (See gzbuffer above.) + The pushed character will be discarded if the stream is repositioned with + gzseek() or gzrewind(). +*/ + +ZEXTERN int ZEXPORT gzflush OF((gzFile file, int flush)); +/* + Flushes all pending output into the compressed file. The parameter flush + is as in the deflate() function. The return value is the zlib error number + (see function gzerror below). gzflush is only permitted when writing. + + If the flush parameter is Z_FINISH, the remaining data is written and the + gzip stream is completed in the output. If gzwrite() is called again, a new + gzip stream will be started in the output. gzread() is able to read such + concatenated gzip streams. + + gzflush should be called only when strictly necessary because it will + degrade compression if called too often. +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile file, + z_off_t offset, int whence)); + + Sets the starting position for the next gzread or gzwrite on the given + compressed file. The offset represents a number of bytes in the + uncompressed data stream. The whence parameter is defined as in lseek(2); + the value SEEK_END is not supported. + + If the file is opened for reading, this function is emulated but can be + extremely slow. If the file is opened for writing, only forward seeks are + supported; gzseek then compresses a sequence of zeroes up to the new + starting position. + + gzseek returns the resulting offset location as measured in bytes from + the beginning of the uncompressed stream, or -1 in case of error, in + particular if the file is opened for writing and the new starting position + would be before the current position. +*/ + +ZEXTERN int ZEXPORT gzrewind OF((gzFile file)); +/* + Rewinds the given file. This function is supported only for reading. + + gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gztell OF((gzFile file)); + + Returns the starting position for the next gzread or gzwrite on the given + compressed file. This position represents a number of bytes in the + uncompressed data stream, and is zero when starting, even if appending or + reading a gzip stream from the middle of a file using gzdopen(). + + gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR) +*/ + +/* +ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile file)); + + Returns the current offset in the file being read or written. This offset + includes the count of bytes that precede the gzip stream, for example when + appending or when using gzdopen() for reading. When reading, the offset + does not include as yet unused buffered input. This information can be used + for a progress indicator. On error, gzoffset() returns -1. +*/ + +ZEXTERN int ZEXPORT gzeof OF((gzFile file)); +/* + Returns true (1) if the end-of-file indicator has been set while reading, + false (0) otherwise. Note that the end-of-file indicator is set only if the + read tried to go past the end of the input, but came up short. Therefore, + just like feof(), gzeof() may return false even if there is no more data to + read, in the event that the last read request was for the exact number of + bytes remaining in the input file. This will happen if the input file size + is an exact multiple of the buffer size. + + If gzeof() returns true, then the read functions will return no more data, + unless the end-of-file indicator is reset by gzclearerr() and the input file + has grown since the previous end of file was detected. +*/ + +ZEXTERN int ZEXPORT gzdirect OF((gzFile file)); +/* + Returns true (1) if file is being copied directly while reading, or false + (0) if file is a gzip stream being decompressed. + + If the input file is empty, gzdirect() will return true, since the input + does not contain a gzip stream. + + If gzdirect() is used immediately after gzopen() or gzdopen() it will + cause buffers to be allocated to allow reading the file to determine if it + is a gzip file. Therefore if gzbuffer() is used, it should be called before + gzdirect(). + + When writing, gzdirect() returns true (1) if transparent writing was + requested ("wT" for the gzopen() mode), or false (0) otherwise. (Note: + gzdirect() is not needed when writing. Transparent writing must be + explicitly requested, so the application already knows the answer. When + linking statically, using gzdirect() will include all of the zlib code for + gzip file reading and decompression, which may not be desired.) +*/ + +ZEXTERN int ZEXPORT gzclose OF((gzFile file)); +/* + Flushes all pending output if necessary, closes the compressed file and + deallocates the (de)compression state. Note that once file is closed, you + cannot call gzerror with file, since its structures have been deallocated. + gzclose must not be called more than once on the same file, just as free + must not be called more than once on the same allocation. + + gzclose will return Z_STREAM_ERROR if file is not valid, Z_ERRNO on a + file operation error, Z_MEM_ERROR if out of memory, Z_BUF_ERROR if the + last read ended in the middle of a gzip stream, or Z_OK on success. +*/ + +ZEXTERN int ZEXPORT gzclose_r OF((gzFile file)); +ZEXTERN int ZEXPORT gzclose_w OF((gzFile file)); +/* + Same as gzclose(), but gzclose_r() is only for use when reading, and + gzclose_w() is only for use when writing or appending. The advantage to + using these instead of gzclose() is that they avoid linking in zlib + compression or decompression code that is not used when only reading or only + writing respectively. If gzclose() is used, then both compression and + decompression code will be included the application when linking to a static + zlib library. +*/ + +ZEXTERN const char * ZEXPORT gzerror OF((gzFile file, int *errnum)); +/* + Returns the error message for the last error which occurred on the given + compressed file. errnum is set to zlib error number. If an error occurred + in the file system and not in the compression library, errnum is set to + Z_ERRNO and the application may consult errno to get the exact error code. + + The application must not modify the returned string. Future calls to + this function may invalidate the previously returned string. If file is + closed, then the string previously returned by gzerror will no longer be + available. + + gzerror() should be used to distinguish errors from end-of-file for those + functions above that do not distinguish those cases in their return values. +*/ + +ZEXTERN void ZEXPORT gzclearerr OF((gzFile file)); +/* + Clears the error and end-of-file flags for file. This is analogous to the + clearerr() function in stdio. This is useful for continuing to read a gzip + file that is being written concurrently. +*/ + +#endif /* !Z_SOLO */ + + /* checksum functions */ + +/* + These functions are not related to compression but are exported + anyway because they might be useful in applications using the compression + library. +*/ + +ZEXTERN uLong ZEXPORT adler32 OF((uLong adler, const Bytef *buf, uInt len)); +/* + Update a running Adler-32 checksum with the bytes buf[0..len-1] and + return the updated checksum. If buf is Z_NULL, this function returns the + required initial value for the checksum. + + An Adler-32 checksum is almost as reliable as a CRC-32 but can be computed + much faster. + + Usage example: + + uLong adler = adler32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + adler = adler32(adler, buffer, length); + } + if (adler != original_adler) error(); +*/ + +ZEXTERN uLong ZEXPORT adler32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as adler32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT adler32_combine OF((uLong adler1, uLong adler2, + z_off_t len2)); + + Combine two Adler-32 checksums into one. For two sequences of bytes, seq1 + and seq2 with lengths len1 and len2, Adler-32 checksums were calculated for + each, adler1 and adler2. adler32_combine() returns the Adler-32 checksum of + seq1 and seq2 concatenated, requiring only adler1, adler2, and len2. Note + that the z_off_t type (like off_t) is a signed integer. If len2 is + negative, the result has no meaning or utility. +*/ + +ZEXTERN uLong ZEXPORT crc32 OF((uLong crc, const Bytef *buf, uInt len)); +/* + Update a running CRC-32 with the bytes buf[0..len-1] and return the + updated CRC-32. If buf is Z_NULL, this function returns the required + initial value for the crc. Pre- and post-conditioning (one's complement) is + performed within this function so it shouldn't be done by the application. + + Usage example: + + uLong crc = crc32(0L, Z_NULL, 0); + + while (read_buffer(buffer, length) != EOF) { + crc = crc32(crc, buffer, length); + } + if (crc != original_crc) error(); +*/ + +ZEXTERN uLong ZEXPORT crc32_z OF((uLong adler, const Bytef *buf, + z_size_t len)); +/* + Same as crc32(), but with a size_t length. +*/ + +/* +ZEXTERN uLong ZEXPORT crc32_combine OF((uLong crc1, uLong crc2, z_off_t len2)); + + Combine two CRC-32 check values into one. For two sequences of bytes, + seq1 and seq2 with lengths len1 and len2, CRC-32 check values were + calculated for each, crc1 and crc2. crc32_combine() returns the CRC-32 + check value of seq1 and seq2 concatenated, requiring only crc1, crc2, and + len2. +*/ + + + /* various hacks, don't look :) */ + +/* deflateInit and inflateInit are macros to allow checking the zlib version + * and the compiler's view of z_stream: + */ +ZEXTERN int ZEXPORT deflateInit_ OF((z_streamp strm, int level, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateInit_ OF((z_streamp strm, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT deflateInit2_ OF((z_streamp strm, int level, int method, + int windowBits, int memLevel, + int strategy, const char *version, + int stream_size)); +ZEXTERN int ZEXPORT inflateInit2_ OF((z_streamp strm, int windowBits, + const char *version, int stream_size)); +ZEXTERN int ZEXPORT inflateBackInit_ OF((z_streamp strm, int windowBits, + unsigned char FAR *window, + const char *version, + int stream_size)); +#ifdef Z_PREFIX_SET +# define z_deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define z_inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define z_inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#else +# define deflateInit(strm, level) \ + deflateInit_((strm), (level), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit(strm) \ + inflateInit_((strm), ZLIB_VERSION, (int)sizeof(z_stream)) +# define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \ + deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\ + (strategy), ZLIB_VERSION, (int)sizeof(z_stream)) +# define inflateInit2(strm, windowBits) \ + inflateInit2_((strm), (windowBits), ZLIB_VERSION, \ + (int)sizeof(z_stream)) +# define inflateBackInit(strm, windowBits, window) \ + inflateBackInit_((strm), (windowBits), (window), \ + ZLIB_VERSION, (int)sizeof(z_stream)) +#endif + +#ifndef Z_SOLO + +/* gzgetc() macro and its supporting function and exposed data structure. Note + * that the real internal state is much larger than the exposed structure. + * This abbreviated structure exposes just enough for the gzgetc() macro. The + * user should not mess with these exposed elements, since their names or + * behavior could change in the future, perhaps even capriciously. They can + * only be used by the gzgetc() macro. You have been warned. + */ +struct gzFile_s { + unsigned have; + unsigned char *next; + z_off64_t pos; +}; +ZEXTERN int ZEXPORT gzgetc_ OF((gzFile file)); /* backward compatibility */ +#ifdef Z_PREFIX_SET +# undef z_gzgetc +# define z_gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#else +# define gzgetc(g) \ + ((g)->have ? ((g)->have--, (g)->pos++, *((g)->next)++) : (gzgetc)(g)) +#endif + +/* provide 64-bit offset functions if _LARGEFILE64_SOURCE defined, and/or + * change the regular functions to 64 bits if _FILE_OFFSET_BITS is 64 (if + * both are true, the application gets the *64 functions, and the regular + * functions are changed to 64 bits) -- in case these are set on systems + * without large file support, _LFS64_LARGEFILE must also be true + */ +#ifdef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off64_t ZEXPORT gzseek64 OF((gzFile, z_off64_t, int)); + ZEXTERN z_off64_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off64_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off64_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off64_t)); +#endif + +#if !defined(ZLIB_INTERNAL) && defined(Z_WANT64) +# ifdef Z_PREFIX_SET +# define z_gzopen z_gzopen64 +# define z_gzseek z_gzseek64 +# define z_gztell z_gztell64 +# define z_gzoffset z_gzoffset64 +# define z_adler32_combine z_adler32_combine64 +# define z_crc32_combine z_crc32_combine64 +# else +# define gzopen gzopen64 +# define gzseek gzseek64 +# define gztell gztell64 +# define gzoffset gzoffset64 +# define adler32_combine adler32_combine64 +# define crc32_combine crc32_combine64 +# endif +# ifndef Z_LARGE64 + ZEXTERN gzFile ZEXPORT gzopen64 OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek64 OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell64 OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset64 OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +# endif +#else + ZEXTERN gzFile ZEXPORT gzopen OF((const char *, const char *)); + ZEXTERN z_off_t ZEXPORT gzseek OF((gzFile, z_off_t, int)); + ZEXTERN z_off_t ZEXPORT gztell OF((gzFile)); + ZEXTERN z_off_t ZEXPORT gzoffset OF((gzFile)); + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); +#endif + +#else /* Z_SOLO */ + + ZEXTERN uLong ZEXPORT adler32_combine OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine OF((uLong, uLong, z_off_t)); + +#endif /* !Z_SOLO */ + +/* undocumented functions */ +ZEXTERN const char * ZEXPORT zError OF((int)); +ZEXTERN int ZEXPORT inflateSyncPoint OF((z_streamp)); +ZEXTERN const z_crc_t FAR * ZEXPORT get_crc_table OF((void)); +ZEXTERN int ZEXPORT inflateUndermine OF((z_streamp, int)); +ZEXTERN int ZEXPORT inflateValidate OF((z_streamp, int)); +ZEXTERN unsigned long ZEXPORT inflateCodesUsed OF ((z_streamp)); +ZEXTERN int ZEXPORT inflateResetKeep OF((z_streamp)); +ZEXTERN int ZEXPORT deflateResetKeep OF((z_streamp)); +#if (defined(_WIN32) || defined(__CYGWIN__)) && !defined(Z_SOLO) +ZEXTERN gzFile ZEXPORT gzopen_w OF((const wchar_t *path, + const char *mode)); +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifndef Z_SOLO +ZEXTERN int ZEXPORTVA gzvprintf Z_ARG((gzFile file, + const char *format, + va_list va)); +# endif +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* ZLIB_H */ diff --git a/arm-trusted-firmware/lib/zlib/zlib.mk b/arm-trusted-firmware/lib/zlib/zlib.mk new file mode 100644 index 0000000..98d4efa --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zlib.mk @@ -0,0 +1,25 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ZLIB_PATH := lib/zlib + +# Imported from zlib 1.2.11 (do not modify them) +ZLIB_SOURCES := $(addprefix $(ZLIB_PATH)/, \ + adler32.c \ + crc32.c \ + inffast.c \ + inflate.c \ + inftrees.c \ + zutil.c) + +# Implemented for TF +ZLIB_SOURCES += $(addprefix $(ZLIB_PATH)/, \ + tf_gunzip.c) + +INCLUDES += -Iinclude/lib/zlib + +# REVISIT: the following flags need not be given globally +TF_CFLAGS += -DZ_SOLO -DDEF_WBITS=31 diff --git a/arm-trusted-firmware/lib/zlib/zutil.c b/arm-trusted-firmware/lib/zlib/zutil.c new file mode 100644 index 0000000..a76c6b0 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zutil.c @@ -0,0 +1,325 @@ +/* zutil.c -- target dependent utility functions for the compression library + * Copyright (C) 1995-2017 Jean-loup Gailly + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* @(#) $Id$ */ + +#include "zutil.h" +#ifndef Z_SOLO +# include "gzguts.h" +#endif + +z_const char * const z_errmsg[10] = { + (z_const char *)"need dictionary", /* Z_NEED_DICT 2 */ + (z_const char *)"stream end", /* Z_STREAM_END 1 */ + (z_const char *)"", /* Z_OK 0 */ + (z_const char *)"file error", /* Z_ERRNO (-1) */ + (z_const char *)"stream error", /* Z_STREAM_ERROR (-2) */ + (z_const char *)"data error", /* Z_DATA_ERROR (-3) */ + (z_const char *)"insufficient memory", /* Z_MEM_ERROR (-4) */ + (z_const char *)"buffer error", /* Z_BUF_ERROR (-5) */ + (z_const char *)"incompatible version",/* Z_VERSION_ERROR (-6) */ + (z_const char *)"" +}; + + +const char * ZEXPORT zlibVersion() +{ + return ZLIB_VERSION; +} + +uLong ZEXPORT zlibCompileFlags() +{ + uLong flags; + + flags = 0; + switch ((int)(sizeof(uInt))) { + case 2: break; + case 4: flags += 1; break; + case 8: flags += 2; break; + default: flags += 3; + } + switch ((int)(sizeof(uLong))) { + case 2: break; + case 4: flags += 1 << 2; break; + case 8: flags += 2 << 2; break; + default: flags += 3 << 2; + } + switch ((int)(sizeof(voidpf))) { + case 2: break; + case 4: flags += 1 << 4; break; + case 8: flags += 2 << 4; break; + default: flags += 3 << 4; + } + switch ((int)(sizeof(z_off_t))) { + case 2: break; + case 4: flags += 1 << 6; break; + case 8: flags += 2 << 6; break; + default: flags += 3 << 6; + } +#ifdef ZLIB_DEBUG + flags += 1 << 8; +#endif +#if defined(ASMV) || defined(ASMINF) + flags += 1 << 9; +#endif +#ifdef ZLIB_WINAPI + flags += 1 << 10; +#endif +#ifdef BUILDFIXED + flags += 1 << 12; +#endif +#ifdef DYNAMIC_CRC_TABLE + flags += 1 << 13; +#endif +#ifdef NO_GZCOMPRESS + flags += 1L << 16; +#endif +#ifdef NO_GZIP + flags += 1L << 17; +#endif +#ifdef PKZIP_BUG_WORKAROUND + flags += 1L << 20; +#endif +#ifdef FASTEST + flags += 1L << 21; +#endif +#if defined(STDC) || defined(Z_HAVE_STDARG_H) +# ifdef NO_vsnprintf + flags += 1L << 25; +# ifdef HAS_vsprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_vsnprintf_void + flags += 1L << 26; +# endif +# endif +#else + flags += 1L << 24; +# ifdef NO_snprintf + flags += 1L << 25; +# ifdef HAS_sprintf_void + flags += 1L << 26; +# endif +# else +# ifdef HAS_snprintf_void + flags += 1L << 26; +# endif +# endif +#endif + return flags; +} + +#ifdef ZLIB_DEBUG +#include +# ifndef verbose +# define verbose 0 +# endif +int ZLIB_INTERNAL z_verbose = verbose; + +void ZLIB_INTERNAL z_error (m) + char *m; +{ + fprintf(stderr, "%s\n", m); + exit(1); +} +#endif + +/* exported to allow conversion of error code to string for compress() and + * uncompress() + */ +const char * ZEXPORT zError(err) + int err; +{ + return ERR_MSG(err); +} + +#if defined(_WIN32_WCE) + /* The Microsoft C Run-Time Library for Windows CE doesn't have + * errno. We define it as a global variable to simplify porting. + * Its value is always 0 and should not be used. + */ + int errno = 0; +#endif + +#ifndef HAVE_MEMCPY + +void ZLIB_INTERNAL zmemcpy(dest, source, len) + Bytef* dest; + const Bytef* source; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = *source++; /* ??? to be unrolled */ + } while (--len != 0); +} + +int ZLIB_INTERNAL zmemcmp(s1, s2, len) + const Bytef* s1; + const Bytef* s2; + uInt len; +{ + uInt j; + + for (j = 0; j < len; j++) { + if (s1[j] != s2[j]) return 2*(s1[j] > s2[j])-1; + } + return 0; +} + +void ZLIB_INTERNAL zmemzero(dest, len) + Bytef* dest; + uInt len; +{ + if (len == 0) return; + do { + *dest++ = 0; /* ??? to be unrolled */ + } while (--len != 0); +} +#endif + +#ifndef Z_SOLO + +#ifdef SYS16BIT + +#ifdef __TURBOC__ +/* Turbo C in 16-bit mode */ + +# define MY_ZCALLOC + +/* Turbo C malloc() does not allow dynamic allocation of 64K bytes + * and farmalloc(64K) returns a pointer with an offset of 8, so we + * must fix the pointer. Warning: the pointer must be put back to its + * original form in order to free it, use zcfree(). + */ + +#define MAX_PTR 10 +/* 10*64K = 640K */ + +local int next_ptr = 0; + +typedef struct ptr_table_s { + voidpf org_ptr; + voidpf new_ptr; +} ptr_table; + +local ptr_table table[MAX_PTR]; +/* This table is used to remember the original form of pointers + * to large buffers (64K). Such pointers are normalized with a zero offset. + * Since MSDOS is not a preemptive multitasking OS, this table is not + * protected from concurrent access. This hack doesn't work anyway on + * a protected system like OS/2. Use Microsoft C instead. + */ + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, unsigned items, unsigned size) +{ + voidpf buf; + ulg bsize = (ulg)items*size; + + (void)opaque; + + /* If we allocate less than 65520 bytes, we assume that farmalloc + * will return a usable pointer which doesn't have to be normalized. + */ + if (bsize < 65520L) { + buf = farmalloc(bsize); + if (*(ush*)&buf != 0) return buf; + } else { + buf = farmalloc(bsize + 16L); + } + if (buf == NULL || next_ptr >= MAX_PTR) return NULL; + table[next_ptr].org_ptr = buf; + + /* Normalize the pointer to seg:0 */ + *((ush*)&buf+1) += ((ush)((uch*)buf-0) + 15) >> 4; + *(ush*)&buf = 0; + table[next_ptr++].new_ptr = buf; + return buf; +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + int n; + + (void)opaque; + + if (*(ush*)&ptr != 0) { /* object < 64K */ + farfree(ptr); + return; + } + /* Find the original pointer */ + for (n = 0; n < next_ptr; n++) { + if (ptr != table[n].new_ptr) continue; + + farfree(table[n].org_ptr); + while (++n < next_ptr) { + table[n-1] = table[n]; + } + next_ptr--; + return; + } + Assert(0, "zcfree: ptr not found"); +} + +#endif /* __TURBOC__ */ + + +#ifdef M_I86 +/* Microsoft C in 16-bit mode */ + +# define MY_ZCALLOC + +#if (!defined(_MSC_VER) || (_MSC_VER <= 600)) +# define _halloc halloc +# define _hfree hfree +#endif + +voidpf ZLIB_INTERNAL zcalloc (voidpf opaque, uInt items, uInt size) +{ + (void)opaque; + return _halloc((long)items, size); +} + +void ZLIB_INTERNAL zcfree (voidpf opaque, voidpf ptr) +{ + (void)opaque; + _hfree(ptr); +} + +#endif /* M_I86 */ + +#endif /* SYS16BIT */ + + +#ifndef MY_ZCALLOC /* Any system without a special alloc function */ + +#ifndef STDC +extern voidp malloc OF((uInt size)); +extern voidp calloc OF((uInt items, uInt size)); +extern void free OF((voidpf ptr)); +#endif + +voidpf ZLIB_INTERNAL zcalloc (opaque, items, size) + voidpf opaque; + unsigned items; + unsigned size; +{ + (void)opaque; + return sizeof(uInt) > 2 ? (voidpf)malloc(items * size) : + (voidpf)calloc(items, size); +} + +void ZLIB_INTERNAL zcfree (opaque, ptr) + voidpf opaque; + voidpf ptr; +{ + (void)opaque; + free(ptr); +} + +#endif /* MY_ZCALLOC */ + +#endif /* !Z_SOLO */ diff --git a/arm-trusted-firmware/lib/zlib/zutil.h b/arm-trusted-firmware/lib/zlib/zutil.h new file mode 100644 index 0000000..b079ea6 --- /dev/null +++ b/arm-trusted-firmware/lib/zlib/zutil.h @@ -0,0 +1,271 @@ +/* zutil.h -- internal interface and configuration of the compression library + * Copyright (C) 1995-2016 Jean-loup Gailly, Mark Adler + * For conditions of distribution and use, see copyright notice in zlib.h + */ + +/* WARNING: this file should *not* be used by applications. It is + part of the implementation of the compression library and is + subject to change. Applications should only use zlib.h. + */ + +/* @(#) $Id$ */ + +#ifndef ZUTIL_H +#define ZUTIL_H + +#ifdef HAVE_HIDDEN +# define ZLIB_INTERNAL __attribute__((visibility ("hidden"))) +#else +# define ZLIB_INTERNAL +#endif + +#include "zlib.h" + +#if defined(STDC) && !defined(Z_SOLO) +# if !(defined(_WIN32_WCE) && defined(_MSC_VER)) +# include +# endif +# include +# include +#endif + +#ifdef Z_SOLO + typedef long ptrdiff_t; /* guess -- will be caught if guess is wrong */ +#endif + +#ifndef local +# define local static +#endif +/* since "static" is used to mean two completely different things in C, we + define "local" for the non-static meaning of "static", for readability + (compile with -Dlocal if your debugger can't find static symbols) */ + +typedef unsigned char uch; +typedef uch FAR uchf; +typedef unsigned short ush; +typedef ush FAR ushf; +typedef unsigned long ulg; + +extern z_const char * const z_errmsg[10]; /* indexed by 2-zlib_error */ +/* (size given to avoid silly warnings with Visual C++) */ + +#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)] + +#define ERR_RETURN(strm,err) \ + return (strm->msg = ERR_MSG(err), (err)) +/* To be used only when the state is known to be valid */ + + /* common constants */ + +#ifndef DEF_WBITS +# define DEF_WBITS MAX_WBITS +#endif +/* default windowBits for decompression. MAX_WBITS is for compression only */ + +#if MAX_MEM_LEVEL >= 8 +# define DEF_MEM_LEVEL 8 +#else +# define DEF_MEM_LEVEL MAX_MEM_LEVEL +#endif +/* default memLevel */ + +#define STORED_BLOCK 0 +#define STATIC_TREES 1 +#define DYN_TREES 2 +/* The three kinds of block type */ + +#define MIN_MATCH 3 +#define MAX_MATCH 258 +/* The minimum and maximum match lengths */ + +#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */ + + /* target dependencies */ + +#if defined(MSDOS) || (defined(WINDOWS) && !defined(WIN32)) +# define OS_CODE 0x00 +# ifndef Z_SOLO +# if defined(__TURBOC__) || defined(__BORLANDC__) +# if (__STDC__ == 1) && (defined(__LARGE__) || defined(__COMPACT__)) + /* Allow compilation with ANSI keywords only enabled */ + void _Cdecl farfree( void *block ); + void *_Cdecl farmalloc( unsigned long nbytes ); +# else +# include +# endif +# else /* MSC or DJGPP */ +# include +# endif +# endif +#endif + +#ifdef AMIGA +# define OS_CODE 1 +#endif + +#if defined(VAXC) || defined(VMS) +# define OS_CODE 2 +# define F_OPEN(name, mode) \ + fopen((name), (mode), "mbc=60", "ctx=stm", "rfm=fix", "mrs=512") +#endif + +#ifdef __370__ +# if __TARGET_LIB__ < 0x20000000 +# define OS_CODE 4 +# elif __TARGET_LIB__ < 0x40000000 +# define OS_CODE 11 +# else +# define OS_CODE 8 +# endif +#endif + +#if defined(ATARI) || defined(atarist) +# define OS_CODE 5 +#endif + +#ifdef OS2 +# define OS_CODE 6 +# if defined(M_I86) && !defined(Z_SOLO) +# include +# endif +#endif + +#if defined(MACOS) || defined(TARGET_OS_MAC) +# define OS_CODE 7 +# ifndef Z_SOLO +# if defined(__MWERKS__) && __dest_os != __be_os && __dest_os != __win32_os +# include /* for fdopen */ +# else +# ifndef fdopen +# define fdopen(fd,mode) NULL /* No fdopen() */ +# endif +# endif +# endif +#endif + +#ifdef __acorn +# define OS_CODE 13 +#endif + +#if defined(WIN32) && !defined(__CYGWIN__) +# define OS_CODE 10 +#endif + +#ifdef _BEOS_ +# define OS_CODE 16 +#endif + +#ifdef __TOS_OS400__ +# define OS_CODE 18 +#endif + +#ifdef __APPLE__ +# define OS_CODE 19 +#endif + +#if defined(_BEOS_) || defined(RISCOS) +# define fdopen(fd,mode) NULL /* No fdopen() */ +#endif + +#if (defined(_MSC_VER) && (_MSC_VER > 600)) && !defined __INTERIX +# if defined(_WIN32_WCE) +# define fdopen(fd,mode) NULL /* No fdopen() */ +# ifndef _PTRDIFF_T_DEFINED + typedef int ptrdiff_t; +# define _PTRDIFF_T_DEFINED +# endif +# else +# define fdopen(fd,type) _fdopen(fd,type) +# endif +#endif + +#if defined(__BORLANDC__) && !defined(MSDOS) + #pragma warn -8004 + #pragma warn -8008 + #pragma warn -8066 +#endif + +/* provide prototypes for these when building zlib without LFS */ +#if !defined(_WIN32) && \ + (!defined(_LARGEFILE64_SOURCE) || _LFS64_LARGEFILE-0 == 0) + ZEXTERN uLong ZEXPORT adler32_combine64 OF((uLong, uLong, z_off_t)); + ZEXTERN uLong ZEXPORT crc32_combine64 OF((uLong, uLong, z_off_t)); +#endif + + /* common defaults */ + +#ifndef OS_CODE +# define OS_CODE 3 /* assume Unix */ +#endif + +#ifndef F_OPEN +# define F_OPEN(name, mode) fopen((name), (mode)) +#endif + + /* functions */ + +#if defined(pyr) || defined(Z_SOLO) +# define NO_MEMCPY +#endif +#if defined(SMALL_MEDIUM) && !defined(_MSC_VER) && !defined(__SC__) + /* Use our own functions for small and medium model with MSC <= 5.0. + * You may have to use the same strategy for Borland C (untested). + * The __SC__ check is for Symantec. + */ +# define NO_MEMCPY +#endif +#if defined(STDC) && !defined(HAVE_MEMCPY) && !defined(NO_MEMCPY) +# define HAVE_MEMCPY +#endif +#ifdef HAVE_MEMCPY +# ifdef SMALL_MEDIUM /* MSDOS small or medium model */ +# define zmemcpy _fmemcpy +# define zmemcmp _fmemcmp +# define zmemzero(dest, len) _fmemset(dest, 0, len) +# else +# define zmemcpy memcpy +# define zmemcmp memcmp +# define zmemzero(dest, len) memset(dest, 0, len) +# endif +#else + void ZLIB_INTERNAL zmemcpy OF((Bytef* dest, const Bytef* source, uInt len)); + int ZLIB_INTERNAL zmemcmp OF((const Bytef* s1, const Bytef* s2, uInt len)); + void ZLIB_INTERNAL zmemzero OF((Bytef* dest, uInt len)); +#endif + +/* Diagnostic functions */ +#ifdef ZLIB_DEBUG +# include + extern int ZLIB_INTERNAL z_verbose; + extern void ZLIB_INTERNAL z_error OF((char *m)); +# define Assert(cond,msg) {if(!(cond)) z_error(msg);} +# define Trace(x) {if (z_verbose>=0) fprintf x ;} +# define Tracev(x) {if (z_verbose>0) fprintf x ;} +# define Tracevv(x) {if (z_verbose>1) fprintf x ;} +# define Tracec(c,x) {if (z_verbose>0 && (c)) fprintf x ;} +# define Tracecv(c,x) {if (z_verbose>1 && (c)) fprintf x ;} +#else +# define Assert(cond,msg) +# define Trace(x) +# define Tracev(x) +# define Tracevv(x) +# define Tracec(c,x) +# define Tracecv(c,x) +#endif + +#ifndef Z_SOLO + voidpf ZLIB_INTERNAL zcalloc OF((voidpf opaque, unsigned items, + unsigned size)); + void ZLIB_INTERNAL zcfree OF((voidpf opaque, voidpf ptr)); +#endif + +#define ZALLOC(strm, items, size) \ + (*((strm)->zalloc))((strm)->opaque, (items), (size)) +#define ZFREE(strm, addr) (*((strm)->zfree))((strm)->opaque, (voidpf)(addr)) +#define TRY_FREE(s, p) {if (p) ZFREE(s, p);} + +/* Reverse the bytes in a 32-bit value */ +#define ZSWAP32(q) ((((q) >> 24) & 0xff) + (((q) >> 8) & 0xff00) + \ + (((q) & 0xff00) << 8) + (((q) & 0xff) << 24)) + +#endif /* ZUTIL_H */ diff --git a/arm-trusted-firmware/license.rst b/arm-trusted-firmware/license.rst new file mode 100644 index 0000000..3ec3b74 --- /dev/null +++ b/arm-trusted-firmware/license.rst @@ -0,0 +1 @@ +See docs/license.rst diff --git a/arm-trusted-firmware/licenses/LICENSE.MIT b/arm-trusted-firmware/licenses/LICENSE.MIT new file mode 100644 index 0000000..8aa2645 --- /dev/null +++ b/arm-trusted-firmware/licenses/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) [year] [fullname] + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/arm-trusted-firmware/make_helpers/armv7-a-cpus.mk b/arm-trusted-firmware/make_helpers/armv7-a-cpus.mk new file mode 100644 index 0000000..eec85cc --- /dev/null +++ b/arm-trusted-firmware/make_helpers/armv7-a-cpus.mk @@ -0,0 +1,58 @@ +# +# Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch32) +$(error ARM_ARCH_MAJOR=7 mandates ARCH=aarch32) +endif + +# For ARMv7, set march32 from platform directive ARMV7_CORTEX_Ax=yes +# and ARM_WITH_NEON=yes/no. +# +# GCC and Clang require -march=armv7-a for C-A9 and -march=armv7ve for C-A15. +# armClang requires -march=armv7-a for all ARMv7 Cortex-A. To comply with +# all, just drop -march and supply only -mcpu. + +# Platform can override march32-directive through MARCH32_DIRECTIVE +ifdef MARCH32_DIRECTIVE +march32-directive := $(MARCH32_DIRECTIVE) +else +march32-set-${ARM_CORTEX_A5} := -mcpu=cortex-a5 +march32-set-${ARM_CORTEX_A7} := -mcpu=cortex-a7 +march32-set-${ARM_CORTEX_A9} := -mcpu=cortex-a9 +march32-set-${ARM_CORTEX_A12} := -mcpu=cortex-a12 +march32-set-${ARM_CORTEX_A15} := -mcpu=cortex-a15 +march32-set-${ARM_CORTEX_A17} := -mcpu=cortex-a17 +march32-neon-$(ARM_WITH_NEON) := -mfpu=neon + +# default to -march=armv7-a as target directive +march32-set-yes ?= -march=armv7-a +march32-directive := ${march32-set-yes} ${march32-neon-yes} +endif + +# Platform may override these extension support directives: +# +# ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING +# Defined if core supports the Large Page Addressing extension. +# +# ARMV7_SUPPORTS_VIRTUALIZATION +# Defined if ARMv7 core supports the Virtualization extension. +# +# ARMV7_SUPPORTS_GENERIC_TIMER +# Defined if ARMv7 core supports the Generic Timer extension. + +ifeq ($(filter yes,$(ARM_CORTEX_A7) $(ARM_CORTEX_A12) $(ARM_CORTEX_A15) $(ARM_CORTEX_A17)),yes) +$(eval $(call add_defines,\ + $(sort \ + ARMV7_SUPPORTS_LARGE_PAGE_ADDRESSING \ + ARMV7_SUPPORTS_VIRTUALIZATION \ + ARMV7_SUPPORTS_GENERIC_TIMER \ + ARMV7_SUPPORTS_VFP \ +))) +endif + +ifeq ($(ARM_CORTEX_A5),yes) +$(eval $(call add_define,ARM_CORTEX_A5)) +endif diff --git a/arm-trusted-firmware/make_helpers/build_env.mk b/arm-trusted-firmware/make_helpers/build_env.mk new file mode 100644 index 0000000..83093bd --- /dev/null +++ b/arm-trusted-firmware/make_helpers/build_env.mk @@ -0,0 +1,72 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file contains the logic to identify and include any relevant +# build environment specific make include files. + +ifndef BUILD_ENV_MK + BUILD_ENV_MK := $(lastword $(MAKEFILE_LIST)) + + # Block possible built-in command definitions that are not fully portable. + # This traps occurences that need replacing with our OS portable macros + COPY := $$(error "Replace COPY with call to SHELL_COPY or SHELL_COPY_TREE.") + CP := $$(error "Replace CP with call to SHELL_COPY or SHELL_COPY_TREE.") + DEL := $$(error "Replace DEL with call to SHELL_DELETE.") + MD := $$(error "Replace MD with call to MAKE_PREREQ_DIR.") + MKDIR := $$(error "Replace MKDIR with call to MAKE_PREREQ_DIR.") + RD := $$(error "Replace RD with call to SHELL_REMOVE_DIR.") + RM := $$(error "Replace RM with call to SHELL_DELETE.") + RMDIR := $$(error "Replace RMDIR with call to SHELL_REMOVE_DIR.") + + ENV_FILE_TO_INCLUDE := unix.mk + ifdef OSTYPE + ifneq ($(findstring ${OSTYPE}, cygwin),) + ENV_FILE_TO_INCLUDE := cygwin.mk + else + ifneq ($(findstring ${OSTYPE}, MINGW32 mingw msys),) + ENV_FILE_TO_INCLUDE := msys.mk + endif + endif + else + ifdef MSYSTEM + # Although the MINGW MSYS shell sets OSTYPE as msys in its environment, + # it does not appear in the GNU make view of environment variables. + # We use MSYSTEM as an alternative, as that is seen by make + ifneq ($(findstring ${MSYSTEM}, MINGW32 mingw msys),) + OSTYPE ?= msys + ENV_FILE_TO_INCLUDE := msys.mk + endif + else + ifdef OS + ifneq ($(findstring ${OS}, Windows_NT),) + ENV_FILE_TO_INCLUDE := windows.mk + endif + endif + endif + endif + include ${MAKE_HELPERS_DIRECTORY}${ENV_FILE_TO_INCLUDE} + ENV_FILE_TO_INCLUDE := + + ifndef SHELL_COPY + $(error "SHELL_COPY not defined for build environment.") + endif + ifndef SHELL_COPY_TREE + $(error "SHELL_COPY_TREE not defined for build environment.") + endif + ifndef SHELL_DELETE_ALL + $(error "SHELL_DELETE_ALL not defined for build environment.") + endif + ifndef SHELL_DELETE + $(error "SHELL_DELETE not defined for build environment.") + endif + ifndef MAKE_PREREQ_DIR + $(error "MAKE_PREREQ_DIR not defined for build environment.") + endif + ifndef SHELL_REMOVE_DIR + $(error "SHELL_REMOVE_DIR not defined for build environment.") + endif + +endif diff --git a/arm-trusted-firmware/make_helpers/build_macros.mk b/arm-trusted-firmware/make_helpers/build_macros.mk new file mode 100644 index 0000000..12aaee6 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/build_macros.mk @@ -0,0 +1,614 @@ +# +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Report an error if the eval make function is not available. +$(eval eval_available := T) +ifneq (${eval_available},T) + $(error This makefile only works with a Make program that supports $$(eval)) +endif + +# Some utility macros for manipulating awkward (whitespace) characters. +blank := +space :=${blank} ${blank} + +# A user defined function to recursively search for a filename below a directory +# $1 is the directory root of the recursive search (blank for current directory). +# $2 is the file name to search for. +define rwildcard +$(strip $(foreach d,$(wildcard ${1}*),$(call rwildcard,${d}/,${2}) $(filter $(subst *,%,%${2}),${d}))) +endef + +# This table is used in converting lower case to upper case. +uppercase_table:=a,A b,B c,C d,D e,E f,F g,G h,H i,I j,J k,K l,L m,M n,N o,O p,P q,Q r,R s,S t,T u,U v,V w,W x,X y,Y z,Z + +# Internal macro used for converting lower case to upper case. +# $(1) = upper case table +# $(2) = String to convert +define uppercase_internal +$(if $(1),$$(subst $(firstword $(1)),$(call uppercase_internal,$(wordlist 2,$(words $(1)),$(1)),$(2))),$(2)) +endef + +# A macro for converting a string to upper case +# $(1) = String to convert +define uppercase +$(eval uppercase_result:=$(call uppercase_internal,$(uppercase_table),$(1)))$(uppercase_result) +endef + +# Convenience function for adding build definitions +# $(eval $(call add_define,FOO)) will have: +# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise +define add_define + DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),) +endef + + +# Convenience function for addding multiple build definitions +# $(eval $(call add_defines,FOO BOO)) +define add_defines + $(foreach def,$1,$(eval $(call add_define,$(def)))) +endef + +# Convenience function for adding build definitions +# $(eval $(call add_define_val,FOO,BAR)) will have: +# -DFOO=BAR +define add_define_val + DEFINES += -D$(1)=$(2) +endef + +# Convenience function for verifying option has a boolean value +# $(eval $(call assert_boolean,FOO)) will assert FOO is 0 or 1 +define assert_boolean + $(if $(filter-out 0 1,$($1)),$(error $1 must be boolean)) +endef + +# Convenience function for verifying options have boolean values +# $(eval $(call assert_booleans,FOO BOO)) will assert FOO and BOO for 0 or 1 values +define assert_booleans + $(foreach bool,$1,$(eval $(call assert_boolean,$(bool)))) +endef + +0-9 := 0 1 2 3 4 5 6 7 8 9 + +# Function to verify that a given option $(1) contains a numeric value +define assert_numeric +$(if $($(1)),,$(error $(1) must not be empty)) +$(eval __numeric := $($(1))) +$(foreach d,$(0-9),$(eval __numeric := $(subst $(d),,$(__numeric)))) +$(if $(__numeric),$(error $(1) must be numeric)) +endef + +# Convenience function for verifying options have numeric values +# $(eval $(call assert_numerics,FOO BOO)) will assert FOO and BOO contain numeric values +define assert_numerics + $(foreach num,$1,$(eval $(call assert_numeric,$(num)))) +endef + +# CREATE_SEQ is a recursive function to create sequence of numbers from 1 to +# $(2) and assign the sequence to $(1) +define CREATE_SEQ +$(if $(word $(2), $($(1))),\ + $(eval $(1) += $(words $($(1))))\ + $(eval $(1) := $(filter-out 0,$($(1)))),\ + $(eval $(1) += $(words $($(1))))\ + $(call CREATE_SEQ,$(1),$(2))\ +) +endef + +# IMG_LINKERFILE defines the linker script corresponding to a BL stage +# $(1) = BL stage +define IMG_LINKERFILE + ${BUILD_DIR}/$(1).ld +endef + +# IMG_MAPFILE defines the output file describing the memory map corresponding +# to a BL stage +# $(1) = BL stage +define IMG_MAPFILE + ${BUILD_DIR}/$(1).map +endef + +# IMG_ELF defines the elf file corresponding to a BL stage +# $(1) = BL stage +define IMG_ELF + ${BUILD_DIR}/$(1).elf +endef + +# IMG_DUMP defines the symbols dump file corresponding to a BL stage +# $(1) = BL stage +define IMG_DUMP + ${BUILD_DIR}/$(1).dump +endef + +# IMG_BIN defines the default image file corresponding to a BL stage +# $(1) = BL stage +define IMG_BIN + ${BUILD_PLAT}/$(1).bin +endef + +# IMG_ENC_BIN defines the default encrypted image file corresponding to a +# BL stage +# $(1) = BL stage +define IMG_ENC_BIN + ${BUILD_PLAT}/$(1)_enc.bin +endef + +# ENCRYPT_FW invokes enctool to encrypt firmware binary +# $(1) = input firmware binary +# $(2) = output encrypted firmware binary +define ENCRYPT_FW +$(2): $(1) enctool + $$(ECHO) " ENC $$<" + $$(Q)$$(ENCTOOL) $$(ENC_ARGS) -i $$< -o $$@ +endef + +# TOOL_ADD_PAYLOAD appends the command line arguments required by fiptool to +# package a new payload and/or by cert_create to generate certificate. +# Optionally, it adds the dependency on this payload +# $(1) = payload filename (i.e. bl31.bin) +# $(2) = command line option for the specified payload (i.e. --soc-fw) +# $(3) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin) +# $(4) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(5) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin) +define TOOL_ADD_PAYLOAD +ifneq ($(5),) + $(4)FIP_ARGS += $(2) $(5) + $(if $(3),$(4)CRT_DEPS += $(1)) +else + $(4)FIP_ARGS += $(2) $(1) + $(if $(3),$(4)CRT_DEPS += $(3)) +endif + $(if $(3),$(4)FIP_DEPS += $(3)) + $(4)CRT_ARGS += $(2) $(1) +endef + +# TOOL_ADD_IMG_PAYLOAD works like TOOL_ADD_PAYLOAD, but applies image filters +# before passing them to host tools if BL*_PRE_TOOL_FILTER is defined. +# $(1) = image_type (scp_bl2, bl33, etc.) +# $(2) = payload filepath (ex. build/fvp/release/bl31.bin) +# $(3) = command line option for the specified payload (ex. --soc-fw) +# $(4) = tool target dependency (optional) (ex. build/fvp/release/bl31.bin) +# $(5) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(6) = encrypted payload (optional) (ex. build/fvp/release/bl31_enc.bin) + +define TOOL_ADD_IMG_PAYLOAD + +$(eval PRE_TOOL_FILTER := $($(call uppercase,$(1))_PRE_TOOL_FILTER)) + +ifneq ($(PRE_TOOL_FILTER),) + +$(eval PROCESSED_PATH := $(BUILD_PLAT)/$(1).bin$($(PRE_TOOL_FILTER)_SUFFIX)) + +$(call $(PRE_TOOL_FILTER)_RULE,$(PROCESSED_PATH),$(2)) + +$(PROCESSED_PATH): $(4) + +$(call TOOL_ADD_PAYLOAD,$(PROCESSED_PATH),$(3),$(PROCESSED_PATH),$(5),$(6)) + +else +$(call TOOL_ADD_PAYLOAD,$(2),$(3),$(4),$(5),$(6)) +endif +endef + +# CERT_ADD_CMD_OPT adds a new command line option to the cert_create invocation +# $(1) = parameter filename +# $(2) = cert_create command line option for the specified parameter +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +define CERT_ADD_CMD_OPT + $(3)CRT_ARGS += $(2) $(1) +endef + +# TOOL_ADD_IMG allows the platform to specify an external image to be packed +# in the FIP and/or for which certificate is generated. It also adds a +# dependency on the image file, aborting the build if the file does not exist. +# $(1) = image_type (scp_bl2, bl33, etc.) +# $(2) = command line option for fiptool (--scp-fw, --nt-fw, etc) +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(4) = Image encryption flag (optional) (0, 1) +# Example: +# $(eval $(call TOOL_ADD_IMG,bl33,--nt-fw)) +define TOOL_ADD_IMG + # Build option to specify the image filename (SCP_BL2, BL33, etc) + # This is the uppercase form of the first parameter + $(eval _V := $(call uppercase,$(1))) + + # $(check_$(1)_cmd) variable is executed in the check_$(1) target and also + # is put into the ${CHECK_$(3)FIP_CMD} variable which is executed by the + # target ${BUILD_PLAT}/${$(3)FIP_NAME}. + $(eval check_$(1)_cmd := \ + $(if $(value $(_V)),,$$$$(error "Platform '${PLAT}' requires $(_V). Please set $(_V) to point to the right file")) \ + $(if $(wildcard $(value $(_V))),,$$$$(error '$(_V)=$(value $(_V))' was specified, but '$(value $(_V))' does not exist)) \ + ) + + $(3)CRT_DEPS += check_$(1) + CHECK_$(3)FIP_CMD += $$(check_$(1)_cmd) +ifeq ($(4),1) + $(eval ENC_BIN := ${BUILD_PLAT}/$(1)_enc.bin) + $(call ENCRYPT_FW,$(value $(_V)),$(ENC_BIN)) + $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(ENC_BIN),$(3), \ + $(ENC_BIN)) +else + $(call TOOL_ADD_IMG_PAYLOAD,$(1),$(value $(_V)),$(2),$(if $(wildcard $(value $(_V))),$(value $(_V)),FORCE),$(3)) +endif + +.PHONY: check_$(1) +check_$(1): + $(check_$(1)_cmd) +endef + +################################################################################ +# Generic image processing filters +################################################################################ + +# GZIP +define GZIP_RULE +$(1): $(2) + $(ECHO) " GZIP $$@" + $(Q)gzip -n -f -9 $$< --stdout > $$@ +endef + +GZIP_SUFFIX := .gz + +################################################################################ +# Auxiliary macros to build TF images from sources +################################################################################ + +MAKE_DEP = -Wp,-MD,$(DEP) -MT $$@ -MP + + +# MAKE_C_LIB builds a C source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.c) +# $(3) = library name +define MAKE_C_LIB +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs + $$(ECHO) " CC $$<" + $$(Q)$$(CC) $$(TF_CFLAGS) $$(CFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + +# MAKE_S_LIB builds an assembly source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.S) +# $(3) = library name +define MAKE_S_LIB +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | lib$(3)_dirs + $$(ECHO) " AS $$<" + $$(Q)$$(AS) $$(ASFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_C builds a C source file and generates the dependency file +# $(1) = output directory +# $(2) = source file (%.c) +# $(3) = BL stage +define MAKE_C + +$(eval OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) +$(eval BL_CFLAGS := $($(call uppercase,$(3))_CFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs + $$(ECHO) " CC $$<" + $$(Q)$$(CC) $$(LTO_CFLAGS) $$(TF_CFLAGS) $$(CFLAGS) $(BL_CPPFLAGS) $(BL_CFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_S builds an assembly source file and generates the dependency file +# $(1) = output directory +# $(2) = assembly file (%.S) +# $(3) = BL stage +define MAKE_S + +$(eval OBJ := $(1)/$(patsubst %.S,%.o,$(notdir $(2)))) +$(eval DEP := $(patsubst %.o,%.d,$(OBJ))) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) +$(eval BL_ASFLAGS := $($(call uppercase,$(3))_ASFLAGS)) + +$(OBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs + $$(ECHO) " AS $$<" + $$(Q)$$(AS) $$(ASFLAGS) $(BL_CPPFLAGS) $(BL_ASFLAGS) $(MAKE_DEP) -c $$< -o $$@ + +-include $(DEP) + +endef + + +# MAKE_LD generate the linker script using the C preprocessor +# $(1) = output linker script +# $(2) = input template +# $(3) = BL stage +define MAKE_LD + +$(eval DEP := $(1).d) +$(eval BL_CPPFLAGS := $($(call uppercase,$(3))_CPPFLAGS) -DIMAGE_$(call uppercase,$(3))) + +$(1): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | $(3)_dirs + $$(ECHO) " PP $$<" + $$(Q)$$(CPP) $$(CPPFLAGS) $(BL_CPPFLAGS) $(TF_CFLAGS_$(ARCH)) -P -x assembler-with-cpp -D__LINKER__ $(MAKE_DEP) -o $$@ $$< + +-include $(DEP) + +endef + +# MAKE_LIB_OBJS builds both C and assembly source files +# $(1) = output directory +# $(2) = list of source files +# $(3) = name of the library +define MAKE_LIB_OBJS + $(eval C_OBJS := $(filter %.c,$(2))) + $(eval REMAIN := $(filter-out %.c,$(2))) + $(eval $(foreach obj,$(C_OBJS),$(call MAKE_C_LIB,$(1),$(obj),$(3)))) + + $(eval S_OBJS := $(filter %.S,$(REMAIN))) + $(eval REMAIN := $(filter-out %.S,$(REMAIN))) + $(eval $(foreach obj,$(S_OBJS),$(call MAKE_S_LIB,$(1),$(obj),$(3)))) + + $(and $(REMAIN),$(error Unexpected source files present: $(REMAIN))) +endef + + +# MAKE_OBJS builds both C and assembly source files +# $(1) = output directory +# $(2) = list of source files (both C and assembly) +# $(3) = BL stage +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 + + +# 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 bear 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 + +# Allow overriding the timestamp, for example for reproducible builds, or to +# synchronize timestamps across multiple projects. +# This must be set to a C string (including quotes where applicable). +BUILD_MESSAGE_TIMESTAMP ?= __TIME__", "__DATE__ + +.PHONY: libraries + +# MAKE_LIB_DIRS macro defines the target for the directory where +# libraries are created +define MAKE_LIB_DIRS + $(eval LIB_DIR := ${BUILD_PLAT}/lib) + $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib) + $(eval LIBWRAPPER_DIR := ${BUILD_PLAT}/libwrapper) + $(eval $(call MAKE_PREREQ_DIR,${LIB_DIR},${BUILD_PLAT})) + $(eval $(call MAKE_PREREQ_DIR,${ROMLIB_DIR},${BUILD_PLAT})) + $(eval $(call MAKE_PREREQ_DIR,${LIBWRAPPER_DIR},${BUILD_PLAT})) +endef + +# MAKE_LIB macro defines the targets and options to build each BL image. +# Arguments: +# $(1) = Library name +define MAKE_LIB + $(eval BUILD_DIR := ${BUILD_PLAT}/lib$(1)) + $(eval LIB_DIR := ${BUILD_PLAT}/lib) + $(eval ROMLIB_DIR := ${BUILD_PLAT}/romlib) + $(eval SOURCES := $(LIB$(call uppercase,$(1))_SRCS)) + $(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES)))) + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT})) +$(eval $(call MAKE_LIB_OBJS,$(BUILD_DIR),$(SOURCES),$(1))) + +.PHONY : lib${1}_dirs +lib${1}_dirs: | ${BUILD_DIR} ${LIB_DIR} ${ROMLIB_DIR} ${LIBWRAPPER_DIR} +libraries: ${LIB_DIR}/lib$(1).a +ifneq ($(findstring armlink,$(notdir $(LD))),) +LDPATHS = --userlibpath=${LIB_DIR} +LDLIBS += --library=$(1) +else +LDPATHS = -L${LIB_DIR} +LDLIBS += -l$(1) +endif + +ifeq ($(USE_ROMLIB),1) +LIBWRAPPER = -lwrappers +endif + +all: ${LIB_DIR}/lib$(1).a + +${LIB_DIR}/lib$(1).a: $(OBJS) + $$(ECHO) " AR $$@" + $$(Q)$$(AR) cr $$@ $$? +endef + +# MAKE_BL macro defines the targets and options to build each BL image. +# Arguments: +# $(1) = BL stage +# $(2) = FIP command line option (if empty, image will not be included in the FIP) +# $(3) = FIP prefix (optional) (if FWU_, target is fwu_fip instead of fip) +# $(4) = BL encryption flag (optional) (0, 1) +define MAKE_BL + $(eval BUILD_DIR := ${BUILD_PLAT}/$(1)) + $(eval BL_SOURCES := $($(call uppercase,$(1))_SOURCES)) + $(eval SOURCES := $(BL_SOURCES) $(BL_COMMON_SOURCES) $(PLAT_BL_COMMON_SOURCES)) + $(eval OBJS := $(addprefix $(BUILD_DIR)/,$(call SOURCES_TO_OBJS,$(SOURCES)))) + $(eval LINKERFILE := $(call IMG_LINKERFILE,$(1))) + $(eval MAPFILE := $(call IMG_MAPFILE,$(1))) + $(eval ELF := $(call IMG_ELF,$(1))) + $(eval DUMP := $(call IMG_DUMP,$(1))) + $(eval BIN := $(call IMG_BIN,$(1))) + $(eval ENC_BIN := $(call IMG_ENC_BIN,$(1))) + $(eval BL_LINKERFILE := $($(call uppercase,$(1))_LINKERFILE)) + $(eval BL_LIBS := $($(call uppercase,$(1))_LIBS)) + # 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} ${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))) + +# Create generators for object directory structure + +$(eval $(call MAKE_PREREQ_DIR,${BUILD_DIR},${BUILD_PLAT})) + +$(eval $(foreach objd,${OBJ_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR}))) + +.PHONY : ${1}_dirs + +# We use order-only prerequisites to ensure that directories are created, +# but do not cause re-builds every time a file is written. +${1}_dirs: | ${OBJ_DIRS} + +$(eval $(call MAKE_OBJS,$(BUILD_DIR),$(SOURCES),$(1))) +$(eval $(call MAKE_LD,$(LINKERFILE),$(BL_LINKERFILE),$(1))) +$(eval BL_LDFLAGS := $($(call uppercase,$(1))_LDFLAGS)) + +ifeq ($(USE_ROMLIB),1) +$(ELF): romlib.bin +endif + +$(ELF): $(OBJS) $(LINKERFILE) | $(1)_dirs libraries $(BL_LIBS) + $$(ECHO) " LD $$@" +ifdef MAKE_BUILD_STRINGS + $(call MAKE_BUILD_STRINGS, $(BUILD_DIR)/build_message.o) +else + @echo 'const char build_message[] = "Built : "$(BUILD_MESSAGE_TIMESTAMP); \ + const char version_string[] = "${VERSION_STRING}";' | \ + $$(CC) $$(TF_CFLAGS) $$(CFLAGS) -xc -c - -o $(BUILD_DIR)/build_message.o +endif +ifneq ($(findstring armlink,$(notdir $(LD))),) + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) --entry=${1}_entrypoint \ + --predefine="-D__LINKER__=$(__LINKER__)" \ + --predefine="-DTF_CFLAGS=$(TF_CFLAGS)" \ + --map --list="$(MAPFILE)" --scatter=${PLAT_DIR}/scat/${1}.scat \ + $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) \ + $(BUILD_DIR)/build_message.o $(OBJS) +else ifneq ($(findstring gcc,$(notdir $(LD))),) + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) -Wl,-Map=$(MAPFILE) \ + -Wl,-T$(LINKERFILE) $(BUILD_DIR)/build_message.o \ + $(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) +else + $$(Q)$$(LD) -o $$@ $$(TF_LDFLAGS) $$(LDFLAGS) $(BL_LDFLAGS) -Map=$(MAPFILE) \ + --script $(LINKERFILE) $(BUILD_DIR)/build_message.o \ + $(OBJS) $(LDPATHS) $(LIBWRAPPER) $(LDLIBS) $(BL_LIBS) +endif +ifeq ($(DISABLE_BIN_GENERATION),1) + @${ECHO_BLANK_LINE} + @echo "Built $$@ successfully" + @${ECHO_BLANK_LINE} +endif + +$(DUMP): $(ELF) + $${ECHO} " OD $$@" + $${Q}$${OD} -dx $$< > $$@ + +$(BIN): $(ELF) + $${ECHO} " BIN $$@" + $$(Q)$$(OC) -O binary $$< $$@ + @${ECHO_BLANK_LINE} + @echo "Built $$@ successfully" + @${ECHO_BLANK_LINE} + +.PHONY: $(1) +ifeq ($(DISABLE_BIN_GENERATION),1) +$(1): $(ELF) $(DUMP) +else +$(1): $(BIN) $(DUMP) +endif + +all: $(1) + +ifeq ($(4),1) +$(call ENCRYPT_FW,$(BIN),$(ENC_BIN)) +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(ENC_BIN),$(3), \ + $(ENC_BIN))) +else +$(if $(2),$(call TOOL_ADD_IMG_PAYLOAD,$(1),$(BIN),--$(2),$(BIN),$(3))) +endif + +endef + +# Convert device tree source file names to matching blobs +# $(1) = input dts +define SOURCES_TO_DTBS + $(notdir $(patsubst %.dts,%.dtb,$(filter %.dts,$(1)))) +endef + +# MAKE_FDT_DIRS macro creates the prerequisite directories that host the +# FDT binaries +# $(1) = output directory +# $(2) = input dts +define MAKE_FDT_DIRS + $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) + $(eval TEMP_DTB_DIRS := $(sort $(dir ${DTBS}))) + # The $(dir ) function leaves a trailing / on the directory names + # Rip off the / to match directory names with make rule targets. + $(eval DTB_DIRS := $(patsubst %/,%,$(TEMP_DTB_DIRS))) + +$(eval $(foreach objd,${DTB_DIRS},$(call MAKE_PREREQ_DIR,${objd},${BUILD_DIR}))) + +fdt_dirs: ${DTB_DIRS} +endef + +# MAKE_DTB generate the Flattened device tree binary +# $(1) = output directory +# $(2) = input dts +define MAKE_DTB + +# List of DTB file(s) to generate, based on DTS file basename list +$(eval DOBJ := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) +# List of the pre-compiled DTS file(s) +$(eval DPRE := $(addprefix $(1)/,$(patsubst %.dts,%.pre.dts,$(notdir $(2))))) +# Dependencies of the pre-compiled DTS file(s) on its source and included files +$(eval DTSDEP := $(patsubst %.dtb,%.o.d,$(DOBJ))) +# Dependencies of the DT compilation on its pre-compiled DTS +$(eval DTBDEP := $(patsubst %.dtb,%.d,$(DOBJ))) + +$(DOBJ): $(2) $(filter-out %.d,$(MAKEFILE_LIST)) | fdt_dirs + $${ECHO} " CPP $$<" + $(eval DTBS := $(addprefix $(1)/,$(call SOURCES_TO_DTBS,$(2)))) + $$(Q)$$(PP) $$(DTC_CPPFLAGS) -MT $(DTBS) -MMD -MF $(DTSDEP) -o $(DPRE) $$< + $${ECHO} " DTC $$<" + $$(Q)$$(DTC) $$(DTC_FLAGS) -d $(DTBDEP) -o $$@ $(DPRE) + +-include $(DTBDEP) +-include $(DTSDEP) + +endef + +# MAKE_DTBS builds flattened device tree sources +# $(1) = output directory +# $(2) = list of flattened device tree source files +define MAKE_DTBS + $(eval DOBJS := $(filter %.dts,$(2))) + $(eval REMAIN := $(filter-out %.dts,$(2))) + $(and $(REMAIN),$(error FDT_SOURCES contain non-DTS files: $(REMAIN))) + $(eval $(foreach obj,$(DOBJS),$(call MAKE_DTB,$(1),$(obj)))) + + $(eval $(call MAKE_FDT_DIRS,$(1),$(2))) + +dtbs: $(DTBS) +all: dtbs +endef diff --git a/arm-trusted-firmware/make_helpers/cygwin.mk b/arm-trusted-firmware/make_helpers/cygwin.mk new file mode 100644 index 0000000..04a963f --- /dev/null +++ b/arm-trusted-firmware/make_helpers/cygwin.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +# OS specific definitions for builds in a Cygwin environment. +# Cygwin allows us to use unix style commands on a windows platform. + +ifndef CYGWIN_MK + CYGWIN_MK := $(lastword $(MAKEFILE_LIST)) + + include ${MAKE_HELPERS_DIRECTORY}unix.mk + + # In cygwin executable files have the Windows .exe extension type. + BIN_EXT := .exe + +endif diff --git a/arm-trusted-firmware/make_helpers/defaults.mk b/arm-trusted-firmware/make_helpers/defaults.mk new file mode 100644 index 0000000..910ffdf --- /dev/null +++ b/arm-trusted-firmware/make_helpers/defaults.mk @@ -0,0 +1,418 @@ +# +# Copyright (c) 2016-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Default, static values for build variables, listed in alphabetic order. +# Dependencies between build options, if any, are handled in the top-level +# Makefile, after this file is included. This ensures that the former is better +# poised to handle dependencies, as all build variables would have a default +# value by then. + +# Use T32 by default +AARCH32_INSTRUCTION_SET := T32 + +# The AArch32 Secure Payload to be built as BL32 image +AARCH32_SP := none + +# The Target build architecture. Supported values are: aarch64, aarch32. +ARCH := aarch64 + +# ARM Architecture feature modifiers: none by default +ARM_ARCH_FEATURE := none + +# ARM Architecture major and minor versions: 8.0 by default. +ARM_ARCH_MAJOR := 8 +ARM_ARCH_MINOR := 0 + +# Base commit to perform code check on +BASE_COMMIT := origin/master + +# Execute BL2 at EL3 +BL2_AT_EL3 := 0 + +# Only use SP packages if SP layout JSON is defined +BL2_ENABLE_SP_LOAD := 0 + +# BL2 image is stored in XIP memory, for now, this option is only supported +# when BL2_AT_EL3 is 1. +BL2_IN_XIP_MEM := 0 + +# Do dcache invalidate upon BL2 entry at EL3 +BL2_INV_DCACHE := 1 + +# Select the branch protection features to use. +BRANCH_PROTECTION := 0 + +# By default, consider that the platform may release several CPUs out of reset. +# The platform Makefile is free to override this value. +COLD_BOOT_SINGLE_CPU := 0 + +# Flag to compile in coreboot support code. Exclude by default. The coreboot +# Makefile system will set this when compiling TF as part of a coreboot image. +COREBOOT := 0 + +# For Chain of Trust +CREATE_KEYS := 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 := 1 + +# Include FP registers in cpu context +CTX_INCLUDE_FPREGS := 0 + +# Include pointer authentication (ARMv8.3-PAuth) registers in cpu context. This +# must be set to 1 if the platform wants to use this feature in the Secure +# world. It is not needed to use it in the Non-secure world. +CTX_INCLUDE_PAUTH_REGS := 0 + +# Include Nested virtualization control (Armv8.4-NV) registers in cpu context. +# This must be set to 1 if architecture implements Nested Virtualization +# Extension and platform wants to use this feature in the Secure world +CTX_INCLUDE_NEVE_REGS := 0 + +# Debug build +DEBUG := 0 + +# By default disable authenticated decryption support. +DECRYPTION_SUPPORT := none + +# Build platform +DEFAULT_PLAT := fvp + +# Disable the generation of the binary image (ELF only). +DISABLE_BIN_GENERATION := 0 + +# Disable MTPMU if FEAT_MTPMU is supported. Default is 0 to keep backwards +# compatibility. +DISABLE_MTPMU := 0 + +# Enable capability to disable authentication dynamically. Only meant for +# development platforms. +DYN_DISABLE_AUTH := 0 + +# Build option to enable MPAM for lower ELs +ENABLE_MPAM_FOR_LOWER_ELS := 0 + +# Enable the Maximum Power Mitigation Mechanism on supporting cores. +ENABLE_MPMM := 0 + +# Enable MPMM configuration via FCONF. +ENABLE_MPMM_FCONF := 0 + +# Flag to Enable Position Independant support (PIE) +ENABLE_PIE := 0 + +# Flag to enable Performance Measurement Framework +ENABLE_PMF := 0 + +# Flag to enable PSCI STATs functionality +ENABLE_PSCI_STAT := 0 + +# Flag to enable Realm Management Extension (FEAT_RME) +ENABLE_RME := 0 + +# Flag to enable runtime instrumentation using PMF +ENABLE_RUNTIME_INSTRUMENTATION := 0 + +# Flag to enable stack corruption protection +ENABLE_STACK_PROTECTOR := 0 + +# Flag to enable exception handling in EL3 +EL3_EXCEPTION_HANDLING := 0 + +# Flag to enable Branch Target Identification. +# Internal flag not meant for direct setting. +# Use BRANCH_PROTECTION to enable BTI. +ENABLE_BTI := 0 + +# Flag to enable Pointer Authentication. +# Internal flag not meant for direct setting. +# Use BRANCH_PROTECTION to enable PAUTH. +ENABLE_PAUTH := 0 + +# Flag to enable access to the HCRX_EL2 register by setting SCR_EL3.HXEn. +ENABLE_FEAT_HCX := 0 + +# Flag to enable access to the HAFGRTR_EL2 register +ENABLE_FEAT_AMUv1 := 0 + +# Flag to enable access to the HDFGRTR_EL2 register +ENABLE_FEAT_FGT := 0 + +# Flag to enable access to the CNTPOFF_EL2 register +ENABLE_FEAT_ECV := 0 + +# Flag to enable use of the DIT feature. +ENABLE_FEAT_DIT := 0 + +# By default BL31 encryption disabled +ENCRYPT_BL31 := 0 + +# By default BL32 encryption disabled +ENCRYPT_BL32 := 0 + +# Default dummy firmware encryption key +ENC_KEY := 1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef + +# Default dummy nonce for firmware encryption +ENC_NONCE := 1234567890abcdef12345678 + +# Build flag to treat usage of deprecated platform and framework APIs as error. +ERROR_DEPRECATED := 0 + +# Fault injection support +FAULT_INJECTION_SUPPORT := 0 + +# Byte alignment that each component in FIP is aligned to +FIP_ALIGN := 0 + +# Default FIP file name +FIP_NAME := fip.bin + +# Default FWU_FIP file name +FWU_FIP_NAME := fwu_fip.bin + +# By default firmware encryption with SSK +FW_ENC_STATUS := 0 + +# For Chain of Trust +GENERATE_COT := 0 + +# Hint platform interrupt control layer that Group 0 interrupts are for EL3. By +# default, they are for Secure EL1. +GICV2_G0_FOR_EL3 := 0 + +# Route External Aborts to EL3. Disabled by default; External Aborts are handled +# by lower ELs. +HANDLE_EA_EL3_FIRST := 0 + +# Secure hash algorithm flag, accepts 3 values: sha256, sha384 and sha512. +# The default value is sha256. +HASH_ALG := sha256 + +# Whether system coherency is managed in hardware, without explicit software +# operations. +HW_ASSISTED_COHERENCY := 0 + +# Set the default algorithm for the generation of Trusted Board Boot keys +KEY_ALG := rsa + +# Set the default key size in case KEY_ALG is rsa +ifeq ($(KEY_ALG),rsa) +KEY_SIZE := 2048 +endif + +# Option to build TF with Measured Boot support +MEASURED_BOOT := 0 + +# NS timer register save and restore +NS_TIMER_SWITCH := 0 + +# Include lib/libc in the final image +OVERRIDE_LIBC := 0 + +# Build PL011 UART driver in minimal generic UART mode +PL011_GENERIC_UART := 0 + +# By default, consider that the platform's reset address is not programmable. +# The platform Makefile is free to override this value. +PROGRAMMABLE_RESET_ADDRESS := 0 + +# Flag used to choose the power state format: Extended State-ID or Original +PSCI_EXTENDED_STATE_ID := 0 + +# Enable RAS support +RAS_EXTENSION := 0 + +# By default, BL1 acts as the reset handler, not BL31 +RESET_TO_BL31 := 0 + +# For Chain of Trust +SAVE_KEYS := 0 + +# Software Delegated Exception support +SDEI_SUPPORT := 0 + +# True Random Number firmware Interface +TRNG_SUPPORT := 0 + +# SMCCC PCI support +SMC_PCI_SUPPORT := 0 + +# Whether code and read-only data should be put on separate memory pages. The +# platform Makefile is free to override this value. +SEPARATE_CODE_AND_RODATA := 0 + +# Put NOBITS sections (.bss, stacks, page tables, and coherent memory) in a +# separate memory region, which may be discontiguous from the rest of BL31. +SEPARATE_NOBITS_REGION := 0 + +# Put BL2 NOLOAD sections (.bss, stacks, page tables) in a separate memory +# region, platform Makefile is free to override this value. +SEPARATE_BL2_NOLOAD_REGION := 0 + +# If the BL31 image initialisation code is recalimed after use for the secondary +# cores stack +RECLAIM_INIT_CODE := 0 + +# SPD choice +SPD := none + +# Enable the Management Mode (MM)-based Secure Partition Manager implementation +SPM_MM := 0 + +# Use SPM at S-EL2 as a default config for SPMD +SPMD_SPM_AT_SEL2 := 1 + +# Flag to introduce an infinite loop in BL1 just before it exits into the next +# image. This is meant to help debugging the post-BL2 phase. +SPIN_ON_BL1_EXIT := 0 + +# Flags to build TF with Trusted Boot support +TRUSTED_BOARD_BOOT := 0 + +# Build option to choose whether Trusted Firmware uses Coherent memory or not. +USE_COHERENT_MEM := 1 + +# Build option to add debugfs support +USE_DEBUGFS := 0 + +# Build option to fconf based io +ARM_IO_IN_DTB := 0 + +# Build option to support SDEI through fconf +SDEI_IN_FCONF := 0 + +# Build option to support Secure Interrupt descriptors through fconf +SEC_INT_DESC_IN_FCONF := 0 + +# Build option to choose whether Trusted Firmware uses library at ROM +USE_ROMLIB := 0 + +# Build option to choose whether the xlat tables of BL images can be read-only. +# Note that this only serves as a higher level option to PLAT_RO_XLAT_TABLES, +# which is the per BL-image option that actually enables the read-only tables +# API. The reason for having this additional option is to have a common high +# level makefile where we can check for incompatible features/build options. +ALLOW_RO_XLAT_TABLES := 0 + +# Chain of trust. +COT := tbbr + +# Use tbbr_oid.h instead of platform_oid.h +USE_TBBR_DEFS := 1 + +# Build verbosity +V := 0 + +# Whether to enable D-Cache early during warm boot. This is usually +# applicable for platforms wherein interconnect programming is not +# required to enable cache coherency after warm reset (eg: single cluster +# platforms). +WARMBOOT_ENABLE_DCACHE_EARLY := 0 + +# Build option to enable/disable the Statistical Profiling Extensions +ENABLE_SPE_FOR_LOWER_ELS := 1 + +# SPE is only supported on AArch64 so disable it on AArch32. +ifeq (${ARCH},aarch32) + override ENABLE_SPE_FOR_LOWER_ELS := 0 +endif + +# Include Memory Tagging Extension registers in cpu context. This must be set +# to 1 if the platform wants to use this feature in the Secure world and MTE is +# enabled at ELX. +CTX_INCLUDE_MTE_REGS := 0 + +ENABLE_AMU := 0 +ENABLE_AMU_AUXILIARY_COUNTERS := 0 +ENABLE_AMU_FCONF := 0 +AMU_RESTRICT_COUNTERS := 0 + +# Enable SVE for non-secure world by default +ENABLE_SVE_FOR_NS := 1 +# SVE is only supported on AArch64 so disable it on AArch32. +ifeq (${ARCH},aarch32) + override ENABLE_SVE_FOR_NS := 0 +endif +ENABLE_SVE_FOR_SWD := 0 + +# SME defaults to disabled +ENABLE_SME_FOR_NS := 0 +ENABLE_SME_FOR_SWD := 0 + +# If SME is enabled then force SVE off +ifeq (${ENABLE_SME_FOR_NS},1) + override ENABLE_SVE_FOR_NS := 0 + override ENABLE_SVE_FOR_SWD := 0 +endif + +SANITIZE_UB := off + +# For ARMv8.1 (AArch64) platforms, enabling this option selects the spinlock +# implementation variant using the ARMv8.1-LSE compare-and-swap instruction. +# Default: disabled +USE_SPINLOCK_CAS := 0 + +# Enable Link Time Optimization +ENABLE_LTO := 0 + +# Build flag to include EL2 registers in cpu context save and restore during +# S-EL2 firmware entry/exit. This flag is to be used with SPD=spmd option. +# Default is 0. +CTX_INCLUDE_EL2_REGS := 0 + +# Enable Memory tag extension which is supported for architecture greater +# than Armv8.5-A +# By default it is set to "no" +SUPPORT_STACK_MEMTAG := no + +# Select workaround for AT speculative behaviour. +ERRATA_SPECULATIVE_AT := 0 + +# Trap RAS error record access from lower EL +RAS_TRAP_LOWER_EL_ERR_ACCESS := 0 + +# Build option to create cot descriptors using fconf +COT_DESC_IN_DTB := 0 + +# Build option to provide openssl directory path +OPENSSL_DIR := /usr + +# Build option to use the SP804 timer instead of the generic one +USE_SP804_TIMER := 0 + +# Build option to define number of firmware banks, used in firmware update +# metadata structure. +NR_OF_FW_BANKS := 2 + +# Build option to define number of images in firmware bank, used in firmware +# update metadata structure. +NR_OF_IMAGES_IN_FW_BANK := 1 + +# Disable Firmware update support by default +PSA_FWU_SUPPORT := 0 + +# By default, disable access of trace buffer control registers from NS +# lower ELs i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused +# if FEAT_TRBE is implemented. +# Note FEAT_TRBE is only supported on AArch64 - therefore do not enable in +# AArch32. +ifneq (${ARCH},aarch32) + ENABLE_TRBE_FOR_NS := 0 +else + override ENABLE_TRBE_FOR_NS := 0 +endif + +# By default, disable access of trace system registers from NS lower +# ELs i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused if +# system register trace is implemented. +ENABLE_SYS_REG_TRACE_FOR_NS := 0 + +# By default, disable trace filter control registers access to NS +# lower ELs, i.e. NS-EL2, or NS-EL1 if NS-EL2 implemented but unused +# if FEAT_TRF is implemented. +ENABLE_TRF_FOR_NS := 0 diff --git a/arm-trusted-firmware/make_helpers/msys.mk b/arm-trusted-firmware/make_helpers/msys.mk new file mode 100644 index 0000000..7e60d57 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/msys.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +# OS specific definitions for builds in a Mingw32 MSYS environment. +# Mingw32 allows us to use some unix style commands on a windows platform. + +ifndef MSYS_MK + MSYS_MK := $(lastword $(MAKEFILE_LIST)) + + include ${MAKE_HELPERS_DIRECTORY}unix.mk + + # In MSYS executable files have the Windows .exe extension type. + BIN_EXT := .exe + +endif + diff --git a/arm-trusted-firmware/make_helpers/plat_helpers.mk b/arm-trusted-firmware/make_helpers/plat_helpers.mk new file mode 100644 index 0000000..a7ae9a2 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/plat_helpers.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################################################ +# Helpers for finding and referencing platform directories +################################################################################ + +ifndef PLAT_HELPERS_MK + PLAT_HELPERS_MK := $(lastword $(MAKEFILE_LIST)) + + ifeq (${PLAT},) + $(error "Error: Unknown platform. Please use PLAT= to specify the platform") + endif + + # TF_PLATFORM_ROOT can be overridden for when building tools directly + TF_PLATFORM_ROOT ?= plat/ + PLAT_MAKEFILE := platform.mk + + # Generate the platforms list by recursively searching for all directories + # under /plat containing a PLAT_MAKEFILE. Append each platform with a `|` + # char and strip out the final '|'. + ALL_PLATFORM_MK_FILES := $(call rwildcard,${TF_PLATFORM_ROOT},${PLAT_MAKEFILE}) + ALL_PLATFORM_DIRS := $(patsubst %/,%,$(dir ${ALL_PLATFORM_MK_FILES})) + ALL_PLATFORMS := $(sort $(notdir ${ALL_PLATFORM_DIRS})) + + PLAT_MAKEFILE_FULL := $(filter %/${PLAT}/${PLAT_MAKEFILE},${ALL_PLATFORM_MK_FILES}) + PLATFORM_LIST := $(subst ${space},|,${ALL_PLATFORMS}) + ifeq ($(PLAT_MAKEFILE_FULL),) + $(error "Error: Invalid platform. The following platforms are available: ${PLATFORM_LIST}") + endif + + # Record the directory where the platform make file was found. + PLAT_DIR := $(dir ${PLAT_MAKEFILE_FULL}) + +endif diff --git a/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk b/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk new file mode 100644 index 0000000..0a280b4 --- /dev/null +++ b/arm-trusted-firmware/make_helpers/tbbr/tbbr_tools.mk @@ -0,0 +1,115 @@ +# +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# This file defines the keys and certificates that must be created to establish +# a Chain of Trust following the TBBR document. These definitions include the +# command line options passed to the cert_create and fiptool commands. +# +# Expected environment: +# +# BUILD_PLAT: output directory +# NEED_BL2: indicates whether BL2 is needed by the platform +# NEED_BL32: indicates whether BL32 is needed by the platform +# BL2: image filename (optional). Default is IMG_BIN(2) (see macro IMG_BIN) +# SCP_BL2: image filename (optional). Default is IMG_BIN(30) +# BL31: image filename (optional). Default is IMG_BIN(31) +# BL32: image filename (optional). Default is IMG_BIN(32) +# BL33: image filename (optional). Default is IMG_BIN(33) +# +# Build options added by this file: +# +# KEY_ALG +# KEY_SIZE +# ROT_KEY +# PROT_KEY +# TRUSTED_WORLD_KEY +# NON_TRUSTED_WORLD_KEY +# SCP_BL2_KEY +# BL31_KEY +# BL32_KEY +# BL33_KEY +# + +# Certificate generation tool default parameters +TRUSTED_KEY_CERT ?= ${BUILD_PLAT}/trusted_key.crt +FWU_CERT := ${BUILD_PLAT}/fwu_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)) +$(eval $(call CERT_ADD_CMD_OPT,${NTFW_NVCTR_VAL},--ntfw-nvctr)) + +# Add Trusted Key certificate to the fiptool and cert_create command line options +$(eval $(call TOOL_ADD_PAYLOAD,${TRUSTED_KEY_CERT},--trusted-key-cert)) + +# Add fwu certificate to the fiptool and cert_create command line options +$(eval $(call TOOL_ADD_PAYLOAD,${FWU_CERT},--fwu-cert,,FWU_)) + +# 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))) +$(if ${KEY_ALG},$(eval $(call CERT_ADD_CMD_OPT,${KEY_ALG},--key-alg,FWU_))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size))) +$(if ${KEY_SIZE},$(eval $(call CERT_ADD_CMD_OPT,${KEY_SIZE},--key-size,FWU_))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg))) +$(if ${HASH_ALG},$(eval $(call CERT_ADD_CMD_OPT,${HASH_ALG},--hash-alg,FWU_))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key))) +$(if ${ROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${ROT_KEY},--rot-key,FWU_))) +$(if ${PROT_KEY},$(eval $(call CERT_ADD_CMD_OPT,${PROT_KEY},--prot-key))) +$(if ${TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${TRUSTED_WORLD_KEY},--trusted-world-key))) +$(if ${NON_TRUSTED_WORLD_KEY},$(eval $(call CERT_ADD_CMD_OPT,${NON_TRUSTED_WORLD_KEY},--non-trusted-world-key))) + + +# Add the BL2 CoT (image cert) +ifeq (${NEED_BL2},yes) +ifeq (${BL2_AT_EL3}, 0) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tb_fw.crt,--tb-fw-cert)) +endif +endif + +# Add the SCP_BL2 CoT (key cert + img cert) +ifneq (${SCP_BL2},) + $(if ${SCP_BL2_KEY},$(eval $(call CERT_ADD_CMD_OPT,${SCP_BL2_KEY},--scp-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_content.crt,--scp-fw-cert)) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/scp_fw_key.crt,--scp-fw-key-cert)) +endif + +ifeq (${ARCH},aarch64) +ifeq (${NEED_BL31},yes) +# Add the BL31 CoT (key cert + img cert) +$(if ${BL31_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL31_KEY},--soc-fw-key))) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_content.crt,--soc-fw-cert)) +$(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/soc_fw_key.crt,--soc-fw-key-cert)) +endif +endif + +# Add the BL32 CoT (key cert + img cert) +ifeq (${NEED_BL32},yes) + $(if ${BL32_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL32_KEY},--tos-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tos_fw_content.crt,--tos-fw-cert)) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/tos_fw_key.crt,--tos-fw-key-cert)) +endif + +# Add the BL33 CoT (key cert + img cert) +ifneq (${BL33},) + $(if ${BL33_KEY},$(eval $(call CERT_ADD_CMD_OPT,${BL33_KEY},--nt-fw-key))) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_content.crt,--nt-fw-cert)) +ifneq (${COT},dualroot) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/nt_fw_key.crt,--nt-fw-key-cert)) +endif +endif + +# Add SiP owned Secure Partitions CoT (image cert) +ifneq (${SP_LAYOUT_FILE},) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/sip_sp_content.crt,--sip-sp-cert)) +ifeq (${COT},dualroot) + $(eval $(call TOOL_ADD_PAYLOAD,${BUILD_PLAT}/plat_sp_content.crt,--plat-sp-cert)) +endif +endif diff --git a/arm-trusted-firmware/make_helpers/unix.mk b/arm-trusted-firmware/make_helpers/unix.mk new file mode 100644 index 0000000..545ddfd --- /dev/null +++ b/arm-trusted-firmware/make_helpers/unix.mk @@ -0,0 +1,60 @@ +# +# Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Trusted Firmware shell command definitions for a Unix style environment. + +ifndef UNIX_MK + UNIX_MK := $(lastword $(MAKEFILE_LIST)) + + ECHO_BLANK_LINE := echo + ECHO_QUIET := @\# + + DIR_DELIM := / + PATH_SEP := : + + # These defines provide Unix style equivalents of the shell commands + # required by the Trusted Firmware build environment. + + # ${1} is the file to be copied. + # ${2} is the destination file name. + define SHELL_COPY + ${Q}cp -f "${1}" "${2}" + endef + + # ${1} is the directory to be copied. + # ${2} is the destination directory path. + define SHELL_COPY_TREE + ${Q}cp -rf "${1}" "${2}" + endef + + # ${1} is the file to be deleted. + define SHELL_DELETE + -${Q}rm -f "${1}" + endef + + # ${1} is a space delimited list of files to be deleted. + # Note that we do not quote ${1}, as multiple parameters may be passed. + define SHELL_DELETE_ALL + -${Q}rm -rf ${1} + endef + + # ${1} is the directory to be generated. + # ${2} is optional, and allows a prerequisite to be specified. + # Do nothing if $1 == $2, to ignore self dependencies. + define MAKE_PREREQ_DIR + ifneq (${1},${2}) + +${1} : ${2} + ${Q}mkdir -p "${1}" + + endif + endef + + define SHELL_REMOVE_DIR + -${Q}rm -rf "${1}" + endef + +endif diff --git a/arm-trusted-firmware/make_helpers/windows.mk b/arm-trusted-firmware/make_helpers/windows.mk new file mode 100644 index 0000000..26ea88e --- /dev/null +++ b/arm-trusted-firmware/make_helpers/windows.mk @@ -0,0 +1,90 @@ +# +# Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# OS specific parts for builds in a Windows_NT environment. The +# environment variable OS is set to Windows_NT on all modern Windows platforms + +# Include generic windows command definitions. + +ifndef WINDOWS_MK + WINDOWS_MK := $(lastword $(MAKEFILE_LIST)) + + ECHO_BLANK_LINE := @cmd /c echo. + ECHO_QUIET := @rem + DIR_DELIM := $(strip \) + BIN_EXT := .exe + PATH_SEP := ; + + # For some Windows native commands there is a problem with the directory delimiter. + # Make uses / (slash) and the commands expect \ (backslash) + # We have to provide a means of translating these, so we define local functions. + + # ${1} is the file to be copied. + # ${2} is the destination file name. + define SHELL_COPY + $(eval tmp_from_file:=$(subst /,\,${1})) + $(eval tmp_to_file:=$(subst /,\,${2})) + copy "${tmp_from_file}" "${tmp_to_file}" + endef + + # ${1} is the directory to be copied. + # ${2} is the destination directory path. + define SHELL_COPY_TREE + $(eval tmp_from_dir:=$(subst /,\,${1})) + $(eval tmp_to_dir:=$(subst /,\,${2})) + xcopy /HIVE "${tmp_from_dir}" "${tmp_to_dir}" + endef + + # ${1} is the file to be deleted. + define SHELL_DELETE + $(eval tmp_del_file:=$(subst /,\,${*})) + -@if exist $(tmp_del_file) del /Q $(tmp_del_file) + endef + + # ${1} is a space delimited list of files to be deleted. + define SHELL_DELETE_ALL + $(eval $(foreach filename,$(wildcard ${1}),$(call DELETE_IF_THERE,${filename}))) + endef + + # ${1} is the directory to be generated. + # ${2} is optional, and allows prerequisites to be specified. + # Do nothing if $1 == $2, to ignore self dependencies. + define MAKE_PREREQ_DIR + ifneq (${1},${2}) + +${1} : ${2} + $(eval tmp_dir:=$(subst /,\,${1})) + -@if not exist "$(tmp_dir)" mkdir "${tmp_dir}" + + endif + endef + + # ${1} is the directory to be removed. + define SHELL_REMOVE_DIR + $(eval tmp_dir:=$(subst /,\,${1})) + -@if exist "$(tmp_dir)" rd /Q /S "$(tmp_dir)" + endef + +endif + +# Because git is not available from CMD.EXE, we need to avoid +# the BUILD_STRING generation which uses git. +# For now we use "development build". +# This can be overridden from the command line or environment. +BUILD_STRING ?= development build + +# The DOS echo shell command does not strip ' characters from the command +# parameters before printing. We therefore use an alternative method invoked +# by defining the MAKE_BUILD_STRINGS macro. +BUILT_TIME_DATE_STRING = const char build_message[] = "Built : "${BUILD_MESSAGE_TIMESTAMP}; +VERSION_STRING_MESSAGE = const char version_string[] = "${VERSION_STRING}"; +define MAKE_BUILD_STRINGS + @echo $$(BUILT_TIME_DATE_STRING) $$(VERSION_STRING_MESSAGE) | \ + $$(CC) $$(TF_CFLAGS) $$(CFLAGS) -x c -c - -o $1 +endef + +MSVC_NMAKE := nmake.exe + diff --git a/arm-trusted-firmware/package-lock.json b/arm-trusted-firmware/package-lock.json new file mode 100644 index 0000000..469c5f5 --- /dev/null +++ b/arm-trusted-firmware/package-lock.json @@ -0,0 +1,7330 @@ +{ + "name": "trusted-firmware-a", + "version": "2.6.0", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "trusted-firmware-a", + "version": "2.6.0", + "hasInstallScript": true, + "license": "BSD-3-Clause", + "devDependencies": { + "@commitlint/cli": "^16.1.0", + "@commitlint/config-conventional": "^16.0.0", + "@commitlint/cz-commitlint": "^16.1.0", + "commitizen": "^4.2.4", + "conventional-changelog-tf-a": "file:tools/conventional-changelog-tf-a", + "husky": "^7.0.4", + "js-yaml": "^4.1.0", + "standard-version": "^9.3.2" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "dependencies": { + "@babel/highlight": "^7.12.13" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "node_modules/@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "dependencies": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + } + }, + "node_modules/@babel/highlight/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/@babel/highlight/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/@babel/highlight/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/@babel/highlight/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/@commitlint/cli": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-16.1.0.tgz", + "integrity": "sha512-x5L1knvA3isRWBRVQx+Q6D45pA9139a2aZQYpxkljMG0dj4UHZkCnsYWpnGalxPxASI7nrI0KedKfS2YeQ55cQ==", + "dev": true, + "dependencies": { + "@commitlint/format": "^16.0.0", + "@commitlint/lint": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/read": "^16.0.0", + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + }, + "bin": { + "commitlint": "cli.js" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-conventional": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.0.0.tgz", + "integrity": "sha512-mN7J8KlKFn0kROd+q9PB01sfDx/8K/R25yITspL1No8PB4oj9M1p77xWjP80hPydqZG9OvQq+anXK3ZWeR7s3g==", + "dev": true, + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.3.1" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/config-validator": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-16.1.0.tgz", + "integrity": "sha512-2cHeZPNTuf1JWbMqyA46MkExor5HMSgv8JrdmzEakUbJHUreh35/wN00FJf57qGs134exQW2thiSQ1IJUsVx2Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "ajv": "^6.12.6" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/cz-commitlint": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cz-commitlint/-/cz-commitlint-16.1.0.tgz", + "integrity": "sha512-TThglfXEBW8TZ99dvaeto1c6hU25ONqL9qkENle2+1OFI64NgbICjLsJq7SVzJd4Jn/yZDp4xNqoV53WJPJ9aA==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.1.0", + "lodash": "^4.17.21", + "word-wrap": "^1.2.3" + }, + "engines": { + "node": ">= 10" + }, + "peerDependencies": { + "commitizen": "^4.0.3", + "inquirer": "^8.0.0" + } + }, + "node_modules/@commitlint/ensure": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-16.0.0.tgz", + "integrity": "sha512-WdMySU8DCTaq3JPf0tZFCKIUhqxaL54mjduNhu8v4D2AMUVIIQKYMGyvXn94k8begeW6iJkTf9cXBArayskE7Q==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/execute-rule": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-16.0.0.tgz", + "integrity": "sha512-8edcCibmBb386x5JTHSPHINwA5L0xPkHQFY8TAuDEt5QyRZY/o5DF8OPHSa5Hx2xJvGaxxuIz4UtAT6IiRDYkw==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/format": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-16.0.0.tgz", + "integrity": "sha512-9yp5NCquXL1jVMKL0ZkRwJf/UHdebvCcMvICuZV00NQGYSAL89O398nhqrqxlbjBhM5EZVq0VGcV5+7r3D4zAA==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/is-ignored": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-16.0.0.tgz", + "integrity": "sha512-gmAQcwIGC/R/Lp0CEb2b5bfGC7MT5rPe09N8kOGjO/NcdNmfFSZMquwrvNJsq9hnAP0skRdHIsqwlkENkN4Lag==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "semver": "7.3.5" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/lint": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-16.0.0.tgz", + "integrity": "sha512-HNl15bRC0h+pLzbMzQC3tM0j1aESXsLYhElqKnXcf5mnCBkBkHzu6WwJW8rZbfxX+YwJmNljN62cPhmdBo8x0A==", + "dev": true, + "dependencies": { + "@commitlint/is-ignored": "^16.0.0", + "@commitlint/parse": "^16.0.0", + "@commitlint/rules": "^16.0.0", + "@commitlint/types": "^16.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/load": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-16.1.0.tgz", + "integrity": "sha512-MtlEhKjP8jAF85jjX4mw8DUUwCxKsCgAc865hhpnwxjrfBcmGP7Up2AFE/M3ZMGDmSl1X1TMybQk/zohj8Cqdg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/execute-rule": "^16.0.0", + "@commitlint/resolve-extends": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^1.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "typescript": "^4.4.3" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/message": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.0.0.tgz", + "integrity": "sha512-CmK2074SH1Ws6kFMEKOKH/7hMekGVbOD6vb4alCOo2+33ZSLUIX8iNkDYyrw38Jwg6yWUhLjyQLUxREeV+QIUA==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/parse": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-16.0.0.tgz", + "integrity": "sha512-F9EjFlMw4MYgBEqoRrWZZKQBzdiJzPBI0qFDFqwUvfQsMmXEREZ242T4R5bFwLINWaALFLHEIa/FXEPa6QxCag==", + "dev": true, + "dependencies": { + "@commitlint/types": "^16.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/read": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-16.0.0.tgz", + "integrity": "sha512-H4T2zsfmYQK9B+JtoQaCXWBHUhgIJyOzWZjSfuIV9Ce69/OgHoffNpLZPF2lX6yKuDrS1SQFhI/kUCjVc/e4ew==", + "dev": true, + "dependencies": { + "@commitlint/top-level": "^16.0.0", + "@commitlint/types": "^16.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/resolve-extends": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-16.1.0.tgz", + "integrity": "sha512-8182s6AFoUFX6+FT1PgQDt15nO2ogdR/EN8SYVAdhNXw1rLz8kT5saB/ICw567GuRAUgFTUMGCXy3ctMOXPEDg==", + "dev": true, + "dependencies": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/types": "^16.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/rules": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-16.0.0.tgz", + "integrity": "sha512-AOl0y2SBTdJ1bvIv8nwHvQKRT/jC1xb09C5VZwzHoT8sE8F54KDeEzPCwHQFgUcWdGLyS10kkOTAH2MyA8EIlg==", + "dev": true, + "dependencies": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/message": "^16.0.0", + "@commitlint/to-lines": "^16.0.0", + "@commitlint/types": "^16.0.0", + "execa": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/to-lines": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-16.0.0.tgz", + "integrity": "sha512-iN/qU38TCKU7uKOg6RXLpD49wNiuI0TqMqybHbjefUeP/Jmzxa8ishryj0uLyVdrAl1ZjGeD1ukXGMTtvqz8iA==", + "dev": true, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/top-level": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-16.0.0.tgz", + "integrity": "sha512-/Jt6NLxyFkpjL5O0jxurZPCHURZAm7cQCqikgPCwqPAH0TLgwqdHjnYipl8J+AGnAMGDip4FNLoYrtgIpZGBYw==", + "dev": true, + "dependencies": { + "find-up": "^5.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@commitlint/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-16.0.0.tgz", + "integrity": "sha512-+0FvYOAS39bJ4aKjnYn/7FD4DfWkmQ6G/06I4F0Gvu4KS5twirEg8mIcLhmeRDOOKn4Tp8PwpLwBiSA6npEMQA==", + "dev": true, + "dependencies": { + "chalk": "^4.0.0" + }, + "engines": { + "node": ">=v12" + } + }, + "node_modules/@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true, + "engines": { + "node": ">= 12" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-consumer": "0.8.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "node_modules/@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "node_modules/@types/node": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", + "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==", + "dev": true, + "peer": true + }, + "node_modules/@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "node_modules/@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "node_modules/acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "node_modules/array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true, + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "node_modules/cachedir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", + "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "dependencies": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "peer": true, + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "peer": true, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "peer": true, + "engines": { + "node": ">= 10" + } + }, + "node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "peer": true, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/commitizen": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", + "dev": true, + "dependencies": { + "cachedir": "2.2.0", + "cz-conventional-changelog": "3.2.0", + "dedent": "0.7.0", + "detect-indent": "6.0.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "8.1.0", + "glob": "7.1.4", + "inquirer": "6.5.2", + "is-utf8": "^0.2.1", + "lodash": "^4.17.20", + "minimist": "1.2.5", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1" + }, + "bin": { + "commitizen": "bin/commitizen", + "cz": "bin/git-cz", + "git-cz": "bin/git-cz" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/commitizen/node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/commitizen/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "node_modules/commitizen/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/commitizen/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/commitizen/node_modules/cz-conventional-changelog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", + "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", + "dev": true, + "dependencies": { + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@commitlint/load": ">6.1.1" + } + }, + "node_modules/commitizen/node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/commitizen/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/commitizen/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/commitizen/node_modules/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "node_modules/commitizen/node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/commitizen/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/commitizen/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/commitizen/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "node_modules/commitizen/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true, + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "dependencies": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "engines": [ + "node >= 6.0" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/conventional-changelog": { + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", + "dev": true, + "dependencies": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true + }, + "node_modules/conventional-changelog-conventionalcommits": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", + "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "dependencies": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-core/node_modules/find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "dependencies": { + "locate-path": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/conventional-changelog-core/node_modules/locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "dependencies": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "dependencies": { + "p-try": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "dependencies": { + "p-limit": "^1.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "dependencies": { + "pify": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "dependencies": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "dependencies": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/conventional-changelog-core/node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/conventional-changelog-core/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "dependencies": { + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "dependencies": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-tf-a": { + "resolved": "tools/conventional-changelog-tf-a", + "link": true + }, + "node_modules/conventional-changelog-writer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", + "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", + "dev": true, + "dependencies": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-changelog-writer": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-changelog-writer/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "node_modules/conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "dependencies": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-commits-parser": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", + "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", + "dev": true, + "dependencies": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "conventional-commits-parser": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "dependencies": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + }, + "bin": { + "conventional-recommended-bump": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "node_modules/cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "dependencies": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cosmiconfig-typescript-loader": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.4.tgz", + "integrity": "sha512-ulv2dvwurP/MZAIthXm69bO7EzzIUThZ6RJ1qXhdlXM6to3F+IKBL/17EnhYSG52A5N1KcAUu66vSG/3/77KrA==", + "dev": true, + "dependencies": { + "cosmiconfig": "^7", + "ts-node": "^10.4.0" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + }, + "peerDependencies": { + "@types/node": "*", + "cosmiconfig": ">=7", + "typescript": ">=3" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true, + "engines": { + "node": "*" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "dependencies": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "node_modules/defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "peer": true, + "dependencies": { + "clone": "^1.0.2" + } + }, + "node_modules/detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true, + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "dependencies": { + "is-obj": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "dependencies": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/dotgitignore/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/dotgitignore/node_modules/path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "dependencies": { + "homedir-polyfill": "^1.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "dev": true, + "dependencies": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "node_modules/find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "dependencies": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "dependencies": { + "null-check": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true, + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "dependencies": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "bin": { + "get-pkg-repo": "src/cli.js" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-pkg-repo/node_modules/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "node_modules/get-pkg-repo/node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/get-pkg-repo/node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/get-pkg-repo/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/git-raw-commits": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", + "dev": true, + "dependencies": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + }, + "bin": { + "git-raw-commits": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "dependencies": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "dependencies": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "bin": { + "git-semver-tags": "cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/git-semver-tags/node_modules/semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "dependencies": { + "ini": "^1.3.2" + } + }, + "node_modules/glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "dependencies": { + "ini": "^1.3.4" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "dependencies": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "node_modules/handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "dependencies": { + "parse-passwd": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true, + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true, + "bin": { + "husky": "lib/bin.js" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/typicode" + } + }, + "node_modules/iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "peer": true + }, + "node_modules/import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "node_modules/inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "peer": true, + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "node_modules/is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "dependencies": { + "has": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "dependencies": { + "text-extensions": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "peer": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "node_modules/is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "node_modules/json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true, + "engines": [ + "node >= 0.2.0" + ] + }, + "node_modules/JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "dependencies": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + }, + "bin": { + "JSONStream": "bin.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "node_modules/load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "dependencies": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/load-json-file/node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, + "node_modules/lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "node_modules/map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "dependencies": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "node_modules/micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "dependencies": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "node_modules/minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "dependencies": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "peer": true + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "node_modules/normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "peer": true, + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "node_modules/punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true, + "engines": { + "node": ">=0.6.0", + "teleport": ">=0.2.0" + } + }, + "node_modules/quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "dependencies": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "dependencies": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/read-pkg-up/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg-up/node_modules/type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/read-pkg/node_modules/hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "node_modules/read-pkg/node_modules/normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "dependencies": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "node_modules/read-pkg/node_modules/semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true, + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/read-pkg/node_modules/type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "dependencies": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "dependencies": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "dependencies": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "dependencies": { + "global-dirs": "^0.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "peer": true, + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "peer": true, + "dependencies": { + "tslib": "~2.1.0" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "dependencies": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "node_modules/spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "dependencies": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "node_modules/spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "node_modules/split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "dependencies": { + "through": "2" + }, + "engines": { + "node": "*" + } + }, + "node_modules/split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "dependencies": { + "readable-stream": "^3.0.0" + } + }, + "node_modules/standard-version": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", + "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", + "dev": true, + "dependencies": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.24", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.1", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "fs-access": "^1.0.1", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "bin": { + "standard-version": "bin/cli.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/standard-version/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/standard-version/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "node_modules/standard-version/node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/standard-version/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "dependencies": { + "safe-buffer": "~5.2.0" + } + }, + "node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "dev": true + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "dependencies": { + "min-indent": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "node_modules/through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "dependencies": { + "readable-stream": "3" + } + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/ts-node": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "dev": true, + "dependencies": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true, + "peer": true + }, + "node_modules/type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "node_modules/typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/uglify-js": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", + "dev": true, + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "node_modules/validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "dependencies": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "peer": true, + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true, + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, + "node_modules/yargs": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "dev": true, + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true, + "engines": { + "node": ">=10" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "tools/conventional-changelog-tf-a": { + "version": "2.6.0", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } + } + }, + "dependencies": { + "@babel/code-frame": { + "version": "7.12.13", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.13.tgz", + "integrity": "sha512-HV1Cm0Q3ZrpCR93tkWOYiuYIgLxZXZFVG2VgK+MBWjUqZTundupbfx2aXarXuw5Ko5aMcjtJgbSs4vUGBS5v6g==", + "dev": true, + "requires": { + "@babel/highlight": "^7.12.13" + } + }, + "@babel/helper-validator-identifier": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.14.0.tgz", + "integrity": "sha512-V3ts7zMSu5lfiwWDVWzRDGIN+lnCEUdaXgtVHJgLb1rGaA6jMrtB9EmE7L18foXJIE8Un/A/h6NJfGQp/e1J4A==", + "dev": true + }, + "@babel/highlight": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.14.0.tgz", + "integrity": "sha512-YSCOwxvTYEIMSGaBQb5kDDsCopDdiUGsqpatp3fOlI4+2HQSkTmEVWnVuySdAC5EWCqSWWTv0ib63RjR7dTBdg==", + "dev": true, + "requires": { + "@babel/helper-validator-identifier": "^7.14.0", + "chalk": "^2.0.0", + "js-tokens": "^4.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } + } + }, + "@commitlint/cli": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cli/-/cli-16.1.0.tgz", + "integrity": "sha512-x5L1knvA3isRWBRVQx+Q6D45pA9139a2aZQYpxkljMG0dj4UHZkCnsYWpnGalxPxASI7nrI0KedKfS2YeQ55cQ==", + "dev": true, + "requires": { + "@commitlint/format": "^16.0.0", + "@commitlint/lint": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/read": "^16.0.0", + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19", + "resolve-from": "5.0.0", + "resolve-global": "1.0.0", + "yargs": "^17.0.0" + } + }, + "@commitlint/config-conventional": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-conventional/-/config-conventional-16.0.0.tgz", + "integrity": "sha512-mN7J8KlKFn0kROd+q9PB01sfDx/8K/R25yITspL1No8PB4oj9M1p77xWjP80hPydqZG9OvQq+anXK3ZWeR7s3g==", + "dev": true, + "requires": { + "conventional-changelog-conventionalcommits": "^4.3.1" + } + }, + "@commitlint/config-validator": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/config-validator/-/config-validator-16.1.0.tgz", + "integrity": "sha512-2cHeZPNTuf1JWbMqyA46MkExor5HMSgv8JrdmzEakUbJHUreh35/wN00FJf57qGs134exQW2thiSQ1IJUsVx2Q==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "ajv": "^6.12.6" + } + }, + "@commitlint/cz-commitlint": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/cz-commitlint/-/cz-commitlint-16.1.0.tgz", + "integrity": "sha512-TThglfXEBW8TZ99dvaeto1c6hU25ONqL9qkENle2+1OFI64NgbICjLsJq7SVzJd4Jn/yZDp4xNqoV53WJPJ9aA==", + "dev": true, + "requires": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/load": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.1.0", + "lodash": "^4.17.21", + "word-wrap": "^1.2.3" + } + }, + "@commitlint/ensure": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/ensure/-/ensure-16.0.0.tgz", + "integrity": "sha512-WdMySU8DCTaq3JPf0tZFCKIUhqxaL54mjduNhu8v4D2AMUVIIQKYMGyvXn94k8begeW6iJkTf9cXBArayskE7Q==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "lodash": "^4.17.19" + } + }, + "@commitlint/execute-rule": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/execute-rule/-/execute-rule-16.0.0.tgz", + "integrity": "sha512-8edcCibmBb386x5JTHSPHINwA5L0xPkHQFY8TAuDEt5QyRZY/o5DF8OPHSa5Hx2xJvGaxxuIz4UtAT6IiRDYkw==", + "dev": true + }, + "@commitlint/format": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/format/-/format-16.0.0.tgz", + "integrity": "sha512-9yp5NCquXL1jVMKL0ZkRwJf/UHdebvCcMvICuZV00NQGYSAL89O398nhqrqxlbjBhM5EZVq0VGcV5+7r3D4zAA==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0" + } + }, + "@commitlint/is-ignored": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/is-ignored/-/is-ignored-16.0.0.tgz", + "integrity": "sha512-gmAQcwIGC/R/Lp0CEb2b5bfGC7MT5rPe09N8kOGjO/NcdNmfFSZMquwrvNJsq9hnAP0skRdHIsqwlkENkN4Lag==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "semver": "7.3.5" + } + }, + "@commitlint/lint": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/lint/-/lint-16.0.0.tgz", + "integrity": "sha512-HNl15bRC0h+pLzbMzQC3tM0j1aESXsLYhElqKnXcf5mnCBkBkHzu6WwJW8rZbfxX+YwJmNljN62cPhmdBo8x0A==", + "dev": true, + "requires": { + "@commitlint/is-ignored": "^16.0.0", + "@commitlint/parse": "^16.0.0", + "@commitlint/rules": "^16.0.0", + "@commitlint/types": "^16.0.0" + } + }, + "@commitlint/load": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/load/-/load-16.1.0.tgz", + "integrity": "sha512-MtlEhKjP8jAF85jjX4mw8DUUwCxKsCgAc865hhpnwxjrfBcmGP7Up2AFE/M3ZMGDmSl1X1TMybQk/zohj8Cqdg==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/execute-rule": "^16.0.0", + "@commitlint/resolve-extends": "^16.1.0", + "@commitlint/types": "^16.0.0", + "chalk": "^4.0.0", + "cosmiconfig": "^7.0.0", + "cosmiconfig-typescript-loader": "^1.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "typescript": "^4.4.3" + } + }, + "@commitlint/message": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/message/-/message-16.0.0.tgz", + "integrity": "sha512-CmK2074SH1Ws6kFMEKOKH/7hMekGVbOD6vb4alCOo2+33ZSLUIX8iNkDYyrw38Jwg6yWUhLjyQLUxREeV+QIUA==", + "dev": true + }, + "@commitlint/parse": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/parse/-/parse-16.0.0.tgz", + "integrity": "sha512-F9EjFlMw4MYgBEqoRrWZZKQBzdiJzPBI0qFDFqwUvfQsMmXEREZ242T4R5bFwLINWaALFLHEIa/FXEPa6QxCag==", + "dev": true, + "requires": { + "@commitlint/types": "^16.0.0", + "conventional-changelog-angular": "^5.0.11", + "conventional-commits-parser": "^3.2.2" + } + }, + "@commitlint/read": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/read/-/read-16.0.0.tgz", + "integrity": "sha512-H4T2zsfmYQK9B+JtoQaCXWBHUhgIJyOzWZjSfuIV9Ce69/OgHoffNpLZPF2lX6yKuDrS1SQFhI/kUCjVc/e4ew==", + "dev": true, + "requires": { + "@commitlint/top-level": "^16.0.0", + "@commitlint/types": "^16.0.0", + "fs-extra": "^10.0.0", + "git-raw-commits": "^2.0.0" + } + }, + "@commitlint/resolve-extends": { + "version": "16.1.0", + "resolved": "https://registry.npmjs.org/@commitlint/resolve-extends/-/resolve-extends-16.1.0.tgz", + "integrity": "sha512-8182s6AFoUFX6+FT1PgQDt15nO2ogdR/EN8SYVAdhNXw1rLz8kT5saB/ICw567GuRAUgFTUMGCXy3ctMOXPEDg==", + "dev": true, + "requires": { + "@commitlint/config-validator": "^16.1.0", + "@commitlint/types": "^16.0.0", + "import-fresh": "^3.0.0", + "lodash": "^4.17.19", + "resolve-from": "^5.0.0", + "resolve-global": "^1.0.0" + } + }, + "@commitlint/rules": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/rules/-/rules-16.0.0.tgz", + "integrity": "sha512-AOl0y2SBTdJ1bvIv8nwHvQKRT/jC1xb09C5VZwzHoT8sE8F54KDeEzPCwHQFgUcWdGLyS10kkOTAH2MyA8EIlg==", + "dev": true, + "requires": { + "@commitlint/ensure": "^16.0.0", + "@commitlint/message": "^16.0.0", + "@commitlint/to-lines": "^16.0.0", + "@commitlint/types": "^16.0.0", + "execa": "^5.0.0" + } + }, + "@commitlint/to-lines": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/to-lines/-/to-lines-16.0.0.tgz", + "integrity": "sha512-iN/qU38TCKU7uKOg6RXLpD49wNiuI0TqMqybHbjefUeP/Jmzxa8ishryj0uLyVdrAl1ZjGeD1ukXGMTtvqz8iA==", + "dev": true + }, + "@commitlint/top-level": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/top-level/-/top-level-16.0.0.tgz", + "integrity": "sha512-/Jt6NLxyFkpjL5O0jxurZPCHURZAm7cQCqikgPCwqPAH0TLgwqdHjnYipl8J+AGnAMGDip4FNLoYrtgIpZGBYw==", + "dev": true, + "requires": { + "find-up": "^5.0.0" + } + }, + "@commitlint/types": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/@commitlint/types/-/types-16.0.0.tgz", + "integrity": "sha512-+0FvYOAS39bJ4aKjnYn/7FD4DfWkmQ6G/06I4F0Gvu4KS5twirEg8mIcLhmeRDOOKn4Tp8PwpLwBiSA6npEMQA==", + "dev": true, + "requires": { + "chalk": "^4.0.0" + } + }, + "@cspotcode/source-map-consumer": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-consumer/-/source-map-consumer-0.8.0.tgz", + "integrity": "sha512-41qniHzTU8yAGbCp04ohlmSrZf8bkf/iJsl3V0dRGsQN/5GFfx+LbCSsCpp2gqrqjTVg/K6O8ycoV35JIwAzAg==", + "dev": true + }, + "@cspotcode/source-map-support": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.7.0.tgz", + "integrity": "sha512-X4xqRHqN8ACt2aHVe51OxeA2HjbcL4MqFqXkrmQszJ1NOUuUu5u6Vqx/0lZSVNku7velL5FC/s5uEAj1lsBMhA==", + "dev": true, + "requires": { + "@cspotcode/source-map-consumer": "0.8.0" + } + }, + "@hutson/parse-repository-url": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/@hutson/parse-repository-url/-/parse-repository-url-3.0.2.tgz", + "integrity": "sha512-H9XAx3hc0BQHY6l+IFSWHDySypcXsvsuLhgYLUGywmJ5pswRVQJUHpOsobnLYp2ZUaUlKiKDrgWWhosOwAEM8Q==", + "dev": true + }, + "@tsconfig/node10": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.8.tgz", + "integrity": "sha512-6XFfSQmMgq0CFLY1MslA/CPUfhIL919M1rMsa5lP2P097N2Wd1sSX0tx1u4olM16fLNhtHZpRhedZJphNJqmZg==", + "dev": true + }, + "@tsconfig/node12": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.9.tgz", + "integrity": "sha512-/yBMcem+fbvhSREH+s14YJi18sp7J9jpuhYByADT2rypfajMZZN4WQ6zBGgBKp53NKmqI36wFYDb3yaMPurITw==", + "dev": true + }, + "@tsconfig/node14": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.1.tgz", + "integrity": "sha512-509r2+yARFfHHE7T6Puu2jjkoycftovhXRqW328PDXTVGKihlb1P8Z9mMZH04ebyajfRY7dedfGynlrFHJUQCg==", + "dev": true + }, + "@tsconfig/node16": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", + "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==", + "dev": true + }, + "@types/minimist": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz", + "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==", + "dev": true + }, + "@types/node": { + "version": "17.0.10", + "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.10.tgz", + "integrity": "sha512-S/3xB4KzyFxYGCppyDt68yzBU9ysL88lSdIah4D6cptdcltc4NCPCAMc0+PCpg/lLIyC7IPvj2Z52OJWeIUkog==", + "dev": true, + "peer": true + }, + "@types/normalize-package-data": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", + "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", + "dev": true + }, + "@types/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==", + "dev": true + }, + "acorn": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.7.0.tgz", + "integrity": "sha512-V/LGr1APy+PXIwKebEWrkZPwoeoF+w1jiOBUmuxuiUIaOHtob8Qc9BTrYo7VuI5fR8tqsy+buA2WFooR5olqvQ==", + "dev": true + }, + "acorn-walk": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.2.0.tgz", + "integrity": "sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA==", + "dev": true + }, + "add-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/add-stream/-/add-stream-1.0.0.tgz", + "integrity": "sha1-anmQQ3ynNtXhKI25K9MmbV9csqo=", + "dev": true + }, + "ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "requires": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "peer": true, + "requires": { + "type-fest": "^0.21.3" + }, + "dependencies": { + "type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "peer": true + } + } + }, + "ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true + }, + "ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "requires": { + "color-convert": "^2.0.1" + } + }, + "arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==", + "dev": true + }, + "argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true + }, + "array-ify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-ify/-/array-ify-1.0.0.tgz", + "integrity": "sha1-nlKHYrSpBmrRY6aWKjZEGOlibs4=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, + "base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "dev": true, + "peer": true + }, + "bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "dev": true, + "peer": true, + "requires": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "requires": { + "fill-range": "^7.0.1" + } + }, + "buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "dev": true, + "peer": true, + "requires": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "dev": true + }, + "cachedir": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.2.0.tgz", + "integrity": "sha512-VvxA0xhNqIIfg0V9AmJkDg91DaJwryutH5rVEZAhcNi4iJFj9f+QxmAjgK1LT9I8OgToX27fypX6/MeCXVbBjQ==", + "dev": true + }, + "callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true + }, + "camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "dev": true + }, + "camelcase-keys": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-6.2.2.tgz", + "integrity": "sha512-YrwaA0vEKazPBkn0ipTiMpSajYDSe+KjQfrjhcBMxJt/znbvlHd8Pw/Vamaz5EB4Wfhs3SUR3Z9mwRu/P3s3Yg==", + "dev": true, + "requires": { + "camelcase": "^5.3.1", + "map-obj": "^4.0.0", + "quick-lru": "^4.0.1" + } + }, + "chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "requires": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "peer": true, + "requires": { + "restore-cursor": "^3.1.0" + } + }, + "cli-spinners": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz", + "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==", + "dev": true, + "peer": true + }, + "cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "peer": true + }, + "cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dev": true, + "requires": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4=", + "dev": true, + "peer": true + }, + "color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "requires": { + "color-name": "~1.1.4" + } + }, + "color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "commitizen": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/commitizen/-/commitizen-4.2.4.tgz", + "integrity": "sha512-LlZChbDzg3Ir3O2S7jSo/cgWp5/QwylQVr59K4xayVq8S4/RdKzSyJkghAiZZHfhh5t4pxunUoyeg0ml1q/7aw==", + "dev": true, + "requires": { + "cachedir": "2.2.0", + "cz-conventional-changelog": "3.2.0", + "dedent": "0.7.0", + "detect-indent": "6.0.0", + "find-node-modules": "^2.1.2", + "find-root": "1.1.0", + "fs-extra": "8.1.0", + "glob": "7.1.4", + "inquirer": "6.5.2", + "is-utf8": "^0.2.1", + "lodash": "^4.17.20", + "minimist": "1.2.5", + "strip-bom": "4.0.0", + "strip-json-comments": "3.0.1" + }, + "dependencies": { + "ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "dev": true + }, + "ansi-regex": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz", + "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==", + "dev": true + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==", + "dev": true + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "cz-conventional-changelog": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cz-conventional-changelog/-/cz-conventional-changelog-3.2.0.tgz", + "integrity": "sha512-yAYxeGpVi27hqIilG1nh4A9Bnx4J3Ov+eXy4koL3drrR+IO9GaWPsKjik20ht608Asqi8TQPf0mczhEeyAtMzg==", + "dev": true, + "requires": { + "@commitlint/load": ">6.1.1", + "chalk": "^2.4.1", + "commitizen": "^4.0.3", + "conventional-commit-types": "^3.0.0", + "lodash.map": "^4.5.1", + "longest": "^2.0.1", + "word-wrap": "^1.0.3" + } + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dev": true, + "requires": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + } + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "dev": true + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dev": true, + "requires": { + "ansi-regex": "^4.1.0" + } + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "dev": true + } + } + }, + "compare-func": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/compare-func/-/compare-func-2.0.0.tgz", + "integrity": "sha512-zHig5N+tPWARooBnb0Zx1MFcdfpyJrfTJ3Y5L+IFvUm8rM74hHz66z0gw0x4tijh5CorKkKUCnW82R2vmpeCRA==", + "dev": true, + "requires": { + "array-ify": "^1.0.0", + "dot-prop": "^5.1.0" + } + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=", + "dev": true + }, + "concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "dev": true, + "requires": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" + } + }, + "conventional-changelog": { + "version": "3.1.24", + "resolved": "https://registry.npmjs.org/conventional-changelog/-/conventional-changelog-3.1.24.tgz", + "integrity": "sha512-ed6k8PO00UVvhExYohroVPXcOJ/K1N0/drJHx/faTH37OIZthlecuLIRX/T6uOp682CAoVoFpu+sSEaeuH6Asg==", + "dev": true, + "requires": { + "conventional-changelog-angular": "^5.0.12", + "conventional-changelog-atom": "^2.0.8", + "conventional-changelog-codemirror": "^2.0.8", + "conventional-changelog-conventionalcommits": "^4.5.0", + "conventional-changelog-core": "^4.2.1", + "conventional-changelog-ember": "^2.0.9", + "conventional-changelog-eslint": "^3.0.9", + "conventional-changelog-express": "^2.0.6", + "conventional-changelog-jquery": "^3.0.11", + "conventional-changelog-jshint": "^2.0.9", + "conventional-changelog-preset-loader": "^2.3.4" + } + }, + "conventional-changelog-angular": { + "version": "5.0.13", + "resolved": "https://registry.npmjs.org/conventional-changelog-angular/-/conventional-changelog-angular-5.0.13.tgz", + "integrity": "sha512-i/gipMxs7s8L/QeuavPF2hLnJgH6pEZAttySB6aiQLWcX3puWDL3ACVmvBhJGxnAy52Qc15ua26BufY6KpmrVA==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-atom": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-atom/-/conventional-changelog-atom-2.0.8.tgz", + "integrity": "sha512-xo6v46icsFTK3bb7dY/8m2qvc8sZemRgdqLb/bjpBsH2UyOS8rKNTgcb5025Hri6IpANPApbXMg15QLb1LJpBw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-codemirror": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/conventional-changelog-codemirror/-/conventional-changelog-codemirror-2.0.8.tgz", + "integrity": "sha512-z5DAsn3uj1Vfp7po3gpt2Boc+Bdwmw2++ZHa5Ak9k0UKsYAO5mH1UBTN0qSCuJZREIhX6WU4E1p3IW2oRCNzQw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-config-spec": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-config-spec/-/conventional-changelog-config-spec-2.1.0.tgz", + "integrity": "sha512-IpVePh16EbbB02V+UA+HQnnPIohgXvJRxHcS5+Uwk4AT5LjzCZJm5sp/yqs5C6KZJ1jMsV4paEV13BN1pvDuxQ==", + "dev": true + }, + "conventional-changelog-conventionalcommits": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/conventional-changelog-conventionalcommits/-/conventional-changelog-conventionalcommits-4.6.1.tgz", + "integrity": "sha512-lzWJpPZhbM1R0PIzkwzGBCnAkH5RKJzJfFQZcl/D+2lsJxAwGnDKBqn/F4C1RD31GJNn8NuKWQzAZDAVXPp2Mw==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "lodash": "^4.17.15", + "q": "^1.5.1" + } + }, + "conventional-changelog-core": { + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-core/-/conventional-changelog-core-4.2.4.tgz", + "integrity": "sha512-gDVS+zVJHE2v4SLc6B0sLsPiloR0ygU7HaDW14aNJE1v4SlqJPILPl/aJC7YdtRE4CybBf8gDwObBvKha8Xlyg==", + "dev": true, + "requires": { + "add-stream": "^1.0.0", + "conventional-changelog-writer": "^5.0.0", + "conventional-commits-parser": "^3.2.0", + "dateformat": "^3.0.0", + "get-pkg-repo": "^4.0.0", + "git-raw-commits": "^2.0.8", + "git-remote-origin-url": "^2.0.0", + "git-semver-tags": "^4.1.1", + "lodash": "^4.17.15", + "normalize-package-data": "^3.0.0", + "q": "^1.5.1", + "read-pkg": "^3.0.0", + "read-pkg-up": "^3.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "dev": true, + "requires": { + "locate-path": "^2.0.0" + } + }, + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "dev": true, + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "dev": true, + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "dev": true, + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=", + "dev": true + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + }, + "path-type": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz", + "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==", + "dev": true, + "requires": { + "pify": "^3.0.0" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "read-pkg": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz", + "integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=", + "dev": true, + "requires": { + "load-json-file": "^4.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^3.0.0" + }, + "dependencies": { + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + } + } + }, + "read-pkg-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz", + "integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=", + "dev": true, + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^3.0.0" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + } + } + }, + "conventional-changelog-ember": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-ember/-/conventional-changelog-ember-2.0.9.tgz", + "integrity": "sha512-ulzIReoZEvZCBDhcNYfDIsLTHzYHc7awh+eI44ZtV5cx6LVxLlVtEmcO+2/kGIHGtw+qVabJYjdI5cJOQgXh1A==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-eslint": { + "version": "3.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-eslint/-/conventional-changelog-eslint-3.0.9.tgz", + "integrity": "sha512-6NpUCMgU8qmWmyAMSZO5NrRd7rTgErjrm4VASam2u5jrZS0n38V7Y9CzTtLT2qwz5xEChDR4BduoWIr8TfwvXA==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-express": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/conventional-changelog-express/-/conventional-changelog-express-2.0.6.tgz", + "integrity": "sha512-SDez2f3iVJw6V563O3pRtNwXtQaSmEfTCaTBPCqn0oG0mfkq0rX4hHBq5P7De2MncoRixrALj3u3oQsNK+Q0pQ==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jquery": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/conventional-changelog-jquery/-/conventional-changelog-jquery-3.0.11.tgz", + "integrity": "sha512-x8AWz5/Td55F7+o/9LQ6cQIPwrCjfJQ5Zmfqi8thwUEKHstEn4kTIofXub7plf1xvFA2TqhZlq7fy5OmV6BOMw==", + "dev": true, + "requires": { + "q": "^1.5.1" + } + }, + "conventional-changelog-jshint": { + "version": "2.0.9", + "resolved": "https://registry.npmjs.org/conventional-changelog-jshint/-/conventional-changelog-jshint-2.0.9.tgz", + "integrity": "sha512-wMLdaIzq6TNnMHMy31hql02OEQ8nCQfExw1SE0hYL5KvU+JCTuPaDO+7JiogGT2gJAxiUGATdtYYfh+nT+6riA==", + "dev": true, + "requires": { + "compare-func": "^2.0.0", + "q": "^1.5.1" + } + }, + "conventional-changelog-preset-loader": { + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/conventional-changelog-preset-loader/-/conventional-changelog-preset-loader-2.3.4.tgz", + "integrity": "sha512-GEKRWkrSAZeTq5+YjUZOYxdHq+ci4dNwHvpaBC3+ENalzFWuCWa9EZXSuZBpkr72sMdKB+1fyDV4takK1Lf58g==", + "dev": true + }, + "conventional-changelog-tf-a": { + "version": "file:tools/conventional-changelog-tf-a", + "requires": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } + }, + "conventional-changelog-writer": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/conventional-changelog-writer/-/conventional-changelog-writer-5.0.0.tgz", + "integrity": "sha512-HnDh9QHLNWfL6E1uHz6krZEQOgm8hN7z/m7tT16xwd802fwgMN0Wqd7AQYVkhpsjDUx/99oo+nGgvKF657XP5g==", + "dev": true, + "requires": { + "conventional-commits-filter": "^2.0.7", + "dateformat": "^3.0.0", + "handlebars": "^4.7.6", + "json-stringify-safe": "^5.0.1", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "semver": "^6.0.0", + "split": "^1.0.0", + "through2": "^4.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "conventional-commit-types": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/conventional-commit-types/-/conventional-commit-types-3.0.0.tgz", + "integrity": "sha512-SmmCYnOniSsAa9GqWOeLqc179lfr5TRu5b4QFDkbsrJ5TZjPJx85wtOr3zn+1dbeNiXDKGPbZ72IKbPhLXh/Lg==", + "dev": true + }, + "conventional-commits-filter": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/conventional-commits-filter/-/conventional-commits-filter-2.0.7.tgz", + "integrity": "sha512-ASS9SamOP4TbCClsRHxIHXRfcGCnIoQqkvAzCSbZzTFLfcTqJVugB0agRgsEELsqaeWgsXv513eS116wnlSSPA==", + "dev": true, + "requires": { + "lodash.ismatch": "^4.4.0", + "modify-values": "^1.0.0" + } + }, + "conventional-commits-parser": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/conventional-commits-parser/-/conventional-commits-parser-3.2.3.tgz", + "integrity": "sha512-YyRDR7On9H07ICFpRm/igcdjIqebXbvf4Cff+Pf0BrBys1i1EOzx9iFXNlAbdrLAR8jf7bkUYkDAr8pEy0q4Pw==", + "dev": true, + "requires": { + "is-text-path": "^1.0.1", + "JSONStream": "^1.0.4", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "conventional-recommended-bump": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/conventional-recommended-bump/-/conventional-recommended-bump-6.1.0.tgz", + "integrity": "sha512-uiApbSiNGM/kkdL9GTOLAqC4hbptObFo4wW2QRyHsKciGAfQuLU1ShZ1BIVI/+K2BE/W1AWYQMCXAsv4dyKPaw==", + "dev": true, + "requires": { + "concat-stream": "^2.0.0", + "conventional-changelog-preset-loader": "^2.3.4", + "conventional-commits-filter": "^2.0.7", + "conventional-commits-parser": "^3.2.0", + "git-raw-commits": "^2.0.8", + "git-semver-tags": "^4.1.1", + "meow": "^8.0.0", + "q": "^1.5.1" + } + }, + "core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "dev": true + }, + "cosmiconfig": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz", + "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==", + "dev": true, + "requires": { + "@types/parse-json": "^4.0.0", + "import-fresh": "^3.2.1", + "parse-json": "^5.0.0", + "path-type": "^4.0.0", + "yaml": "^1.10.0" + } + }, + "cosmiconfig-typescript-loader": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/cosmiconfig-typescript-loader/-/cosmiconfig-typescript-loader-1.0.4.tgz", + "integrity": "sha512-ulv2dvwurP/MZAIthXm69bO7EzzIUThZ6RJ1qXhdlXM6to3F+IKBL/17EnhYSG52A5N1KcAUu66vSG/3/77KrA==", + "dev": true, + "requires": { + "cosmiconfig": "^7", + "ts-node": "^10.4.0" + } + }, + "create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "dev": true + }, + "cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "requires": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "dependencies": { + "which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + } + } + }, + "dargs": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/dargs/-/dargs-7.0.0.tgz", + "integrity": "sha512-2iy1EkLdlBzQGvbweYRFxmFath8+K7+AKB0TlhHWkNuH+TmovaMH/Wp7V7R4u7f4SnX3OgLsU9t1NI9ioDnUpg==", + "dev": true + }, + "dateformat": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-3.0.3.tgz", + "integrity": "sha512-jyCETtSl3VMZMWeRo7iY1FL19ges1t55hMo5yaam4Jrsm5EPL89UQkoQRyiI+Yf4k8r2ZpdngkV8hr1lIdjb3Q==", + "dev": true + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=", + "dev": true + }, + "decamelize-keys": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.0.tgz", + "integrity": "sha1-0XGoeTMlKAfrPLYdwcFEXQeN8tk=", + "dev": true, + "requires": { + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" + }, + "dependencies": { + "map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha1-2TPOuSBdgr3PSIb2dCvcK03qFG0=", + "dev": true + } + } + }, + "dedent": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", + "integrity": "sha1-JJXduvbrh0q7Dhvp3yLS5aVEMmw=", + "dev": true + }, + "defaults": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz", + "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", + "dev": true, + "peer": true, + "requires": { + "clone": "^1.0.2" + } + }, + "detect-file": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/detect-file/-/detect-file-1.0.0.tgz", + "integrity": "sha1-8NZtA2cqglyxtzvbP+YjEMjlUrc=", + "dev": true + }, + "detect-indent": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/detect-indent/-/detect-indent-6.0.0.tgz", + "integrity": "sha512-oSyFlqaTHCItVRGK5RmrmjB+CmaMOW7IaNA/kdxqhoa6d17j/5ce9O9eWXmV/KEdRwqpQA+Vqe8a8Bsybu4YnA==", + "dev": true + }, + "detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true + }, + "diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "dev": true + }, + "dot-prop": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz", + "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==", + "dev": true, + "requires": { + "is-obj": "^2.0.0" + } + }, + "dotgitignore": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/dotgitignore/-/dotgitignore-2.1.0.tgz", + "integrity": "sha512-sCm11ak2oY6DglEPpCB8TixLjWAxd3kJTs6UIcSasNYxXdFPV+YKlye92c8H4kKFqV5qYMIh7d+cYecEg0dIkA==", + "dev": true, + "requires": { + "find-up": "^3.0.0", + "minimatch": "^3.0.4" + }, + "dependencies": { + "find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "dev": true, + "requires": { + "locate-path": "^3.0.0" + } + }, + "locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "dev": true, + "requires": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "dev": true, + "requires": { + "p-limit": "^2.0.0" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=", + "dev": true + } + } + }, + "emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "dev": true + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=", + "dev": true + }, + "execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "dev": true, + "requires": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + } + }, + "expand-tilde": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/expand-tilde/-/expand-tilde-2.0.2.tgz", + "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", + "dev": true, + "requires": { + "homedir-polyfill": "^1.0.1" + } + }, + "external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + } + }, + "fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true + }, + "fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true + }, + "figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "find-node-modules": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/find-node-modules/-/find-node-modules-2.1.2.tgz", + "integrity": "sha512-x+3P4mbtRPlSiVE1Qco0Z4YLU8WFiFcuWTf3m75OV9Uzcfs2Bg+O9N+r/K0AnmINBW06KpfqKwYJbFlFq4qNug==", + "dev": true, + "requires": { + "findup-sync": "^4.0.0", + "merge": "^2.1.0" + } + }, + "find-root": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz", + "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==", + "dev": true + }, + "find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "requires": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + } + }, + "findup-sync": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/findup-sync/-/findup-sync-4.0.0.tgz", + "integrity": "sha512-6jvvn/12IC4quLBL1KNokxC7wWTvYncaVUYSoxWw7YykPLuRrnv4qdHcSOywOI5RpkOVGeQRtWM8/q+G6W6qfQ==", + "dev": true, + "requires": { + "detect-file": "^1.0.0", + "is-glob": "^4.0.0", + "micromatch": "^4.0.2", + "resolve-dir": "^1.0.1" + } + }, + "fs-access": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/fs-access/-/fs-access-1.0.1.tgz", + "integrity": "sha1-1qh/JiJxzv6+wwxVNAf7mV2od3o=", + "dev": true, + "requires": { + "null-check": "^1.0.0" + } + }, + "fs-extra": { + "version": "10.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz", + "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", + "dev": true + }, + "function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "dev": true + }, + "get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "dev": true + }, + "get-pkg-repo": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/get-pkg-repo/-/get-pkg-repo-4.2.1.tgz", + "integrity": "sha512-2+QbHjFRfGB74v/pYWjd5OhU3TDIC2Gv/YKUTk/tCvAz0pkn/Mz6P3uByuBimLOcPvN2jYdScl3xGFSrx0jEcA==", + "dev": true, + "requires": { + "@hutson/parse-repository-url": "^3.0.0", + "hosted-git-info": "^4.0.0", + "through2": "^2.0.0", + "yargs": "^16.2.0" + }, + "dependencies": { + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", + "dev": true + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "dev": true, + "requires": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "dev": true + }, + "git-raw-commits": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.10.tgz", + "integrity": "sha512-sHhX5lsbG9SOO6yXdlwgEMQ/ljIn7qMpAbJZCGfXX2fq5T8M5SrDnpYk9/4HswTildcIqatsWa91vty6VhWSaQ==", + "dev": true, + "requires": { + "dargs": "^7.0.0", + "lodash": "^4.17.15", + "meow": "^8.0.0", + "split2": "^3.0.0", + "through2": "^4.0.0" + } + }, + "git-remote-origin-url": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/git-remote-origin-url/-/git-remote-origin-url-2.0.0.tgz", + "integrity": "sha1-UoJlna4hBxRaERJhEq0yFuxfpl8=", + "dev": true, + "requires": { + "gitconfiglocal": "^1.0.0", + "pify": "^2.3.0" + } + }, + "git-semver-tags": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/git-semver-tags/-/git-semver-tags-4.1.1.tgz", + "integrity": "sha512-OWyMt5zBe7xFs8vglMmhM9lRQzCWL3WjHtxNNfJTMngGym7pC1kh8sP6jevfydJ6LP3ZvGxfb6ABYgPUM0mtsA==", + "dev": true, + "requires": { + "meow": "^8.0.0", + "semver": "^6.0.0" + }, + "dependencies": { + "semver": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz", + "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==", + "dev": true + } + } + }, + "gitconfiglocal": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gitconfiglocal/-/gitconfiglocal-1.0.0.tgz", + "integrity": "sha1-QdBF84UaXqiPA/JMocYXgRRGS5s=", + "dev": true, + "requires": { + "ini": "^1.3.2" + } + }, + "glob": { + "version": "7.1.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.4.tgz", + "integrity": "sha512-hkLPepehmnKk41pUGm3sYxoFs/umurYfYJCerbXEyFIWcAzvpipAgVkBqqT9RBKMGjnq6kMuyYwha6csxbiM1A==", + "dev": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "global-dirs": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-0.1.1.tgz", + "integrity": "sha1-sxnA3UYH81PzvpzKTHL8FIxJ9EU=", + "dev": true, + "requires": { + "ini": "^1.3.4" + } + }, + "global-modules": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-1.0.0.tgz", + "integrity": "sha512-sKzpEkf11GpOFuw0Zzjzmt4B4UZwjOcG757PPvrfhxcLFbq0wpsgpOqxpxtxFiCG4DtG93M6XRVbF2oGdev7bg==", + "dev": true, + "requires": { + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" + } + }, + "global-prefix": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-1.0.2.tgz", + "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "graceful-fs": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.6.tgz", + "integrity": "sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ==", + "dev": true + }, + "handlebars": { + "version": "4.7.7", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.7.tgz", + "integrity": "sha512-aAcXm5OAfE/8IXkcZvCepKU3VzW1/39Fb5ZuqMtgI/hT8X2YgoMvBY5dLhq/cpOvw7Lk1nK/UF71aLG/ZnVYRA==", + "dev": true, + "requires": { + "minimist": "^1.2.5", + "neo-async": "^2.6.0", + "source-map": "^0.6.1", + "uglify-js": "^3.1.4", + "wordwrap": "^1.0.0" + } + }, + "hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true + }, + "has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dev": true, + "requires": { + "function-bind": "^1.1.1" + } + }, + "has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true + }, + "homedir-polyfill": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/homedir-polyfill/-/homedir-polyfill-1.0.3.tgz", + "integrity": "sha512-eSmmWE5bZTK2Nou4g0AI3zZ9rswp7GRKoKXS1BLUkvPviOqs4YTN1djQIqrXy9k5gEtdLPy86JjRwsNM9tnDcA==", + "dev": true, + "requires": { + "parse-passwd": "^1.0.0" + } + }, + "hosted-git-info": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.0.2.tgz", + "integrity": "sha512-c9OGXbZ3guC/xOlCg1Ci/VgWlwsqDv1yMQL1CWqXDL0hDjXuNcq0zuR4xqPSuasI3kqFDhqSyTjREz5gzq0fXg==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "human-signals": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz", + "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==", + "dev": true + }, + "husky": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/husky/-/husky-7.0.4.tgz", + "integrity": "sha512-vbaCKN2QLtP/vD4yvs6iz6hBEo6wkSzs8HpRah1Z6aGmF2KW5PdYuAd7uX5a+OyBZHBhd+TFLqgjUgytQr4RvQ==", + "dev": true + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "dev": true, + "peer": true + }, + "import-fresh": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", + "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", + "dev": true, + "requires": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "dependencies": { + "resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true + } + } + }, + "indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "dev": true + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "dev": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", + "dev": true + }, + "ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "dev": true + }, + "inquirer": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.0.tgz", + "integrity": "sha512-0crLweprevJ02tTuA6ThpoAERAGyVILC4sS74uib58Xf/zSr1/ZWtmm7D5CI+bSQEaA04f0K7idaHpQbSWgiVQ==", + "dev": true, + "peer": true, + "requires": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.2.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6" + } + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=", + "dev": true + }, + "is-core-module": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz", + "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==", + "dev": true, + "requires": { + "has": "^1.0.3" + } + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true + }, + "is-glob": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.1.tgz", + "integrity": "sha512-5G0tKtBTFImOqDnLB2hG6Bp2qcKEFduo4tZu9MT/H6NQv/ghhy30o55ufafxJ/LdH79LLs2Kfrn85TLKyA7BUg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "peer": true + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, + "is-obj": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz", + "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==", + "dev": true + }, + "is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4=", + "dev": true + }, + "is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "dev": true + }, + "is-text-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-text-path/-/is-text-path-1.0.1.tgz", + "integrity": "sha1-Thqg+1G/vLPpJogAE5cgLBd1tm4=", + "dev": true, + "requires": { + "text-extensions": "^1.0.0" + } + }, + "is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "peer": true + }, + "is-utf8": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", + "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", + "dev": true + }, + "is-windows": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", + "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", + "dev": true + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dev": true, + "requires": { + "argparse": "^2.0.1" + } + }, + "json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "dev": true + }, + "json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=", + "dev": true + }, + "jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^2.0.0" + } + }, + "jsonparse": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/jsonparse/-/jsonparse-1.3.1.tgz", + "integrity": "sha1-P02uSpH6wxX3EGL4UhzCOfE2YoA=", + "dev": true + }, + "JSONStream": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/JSONStream/-/JSONStream-1.3.5.tgz", + "integrity": "sha512-E+iruNOY8VV9s4JEbe1aNEm6MiszPRr/UfcHMz0TQh1BXSxHK+ASV1R6W4HpjBhSeS+54PIsAMCBmwD06LLsqQ==", + "dev": true, + "requires": { + "jsonparse": "^1.2.0", + "through": ">=2.2.7 <3" + } + }, + "kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "dev": true + }, + "lines-and-columns": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.1.6.tgz", + "integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA=", + "dev": true + }, + "load-json-file": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz", + "integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=", + "dev": true, + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^4.0.0", + "pify": "^3.0.0", + "strip-bom": "^3.0.0" + }, + "dependencies": { + "parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=", + "dev": true, + "requires": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + } + }, + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=", + "dev": true + } + } + }, + "locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "requires": { + "p-locate": "^5.0.0" + } + }, + "lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "lodash.ismatch": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.ismatch/-/lodash.ismatch-4.4.0.tgz", + "integrity": "sha1-dWy1FQyjum8RCFp4hJZF8Yj4Xzc=", + "dev": true + }, + "lodash.map": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/lodash.map/-/lodash.map-4.6.0.tgz", + "integrity": "sha1-dx7Hg540c9nEzeKLGTlMNWL09tM=", + "dev": true + }, + "log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "peer": true, + "requires": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + } + }, + "longest": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-2.0.1.tgz", + "integrity": "sha1-eB4YMpaqlPbU2RbcM10NF676I/g=", + "dev": true + }, + "lru-cache": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "dev": true, + "requires": { + "yallist": "^4.0.0" + } + }, + "make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==", + "dev": true + }, + "map-obj": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", + "integrity": "sha512-hdN1wVrZbb29eBGiGjJbeP8JbKjq1urkHJ/LIP/NY48MZ1QVXUsQBV1G1zvYFHn1XE06cwjBsOI2K3Ulnj1YXQ==", + "dev": true + }, + "meow": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/meow/-/meow-8.1.2.tgz", + "integrity": "sha512-r85E3NdZ+mpYk1C6RjPFEMSE+s1iZMuHtsHAqY0DT3jZczl0diWUZ8g6oU7h0M9cD2EL+PzaYghhCLzR0ZNn5Q==", + "dev": true, + "requires": { + "@types/minimist": "^1.2.0", + "camelcase-keys": "^6.2.2", + "decamelize-keys": "^1.1.0", + "hard-rejection": "^2.1.0", + "minimist-options": "4.1.0", + "normalize-package-data": "^3.0.0", + "read-pkg-up": "^7.0.1", + "redent": "^3.0.0", + "trim-newlines": "^3.0.0", + "type-fest": "^0.18.0", + "yargs-parser": "^20.2.3" + } + }, + "merge": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz", + "integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w==", + "dev": true + }, + "merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true + }, + "micromatch": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz", + "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==", + "dev": true, + "requires": { + "braces": "^3.0.1", + "picomatch": "^2.2.3" + } + }, + "mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true + }, + "min-indent": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", + "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", + "dev": true + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==", + "dev": true + }, + "minimist-options": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/minimist-options/-/minimist-options-4.1.0.tgz", + "integrity": "sha512-Q4r8ghd80yhO/0j1O3B2BjweX3fiHg9cdOwjJd2J76Q135c+NDxGCqdYKQ1SKBuFfgWbAUzBfvYjPUEeNgqN1A==", + "dev": true, + "requires": { + "arrify": "^1.0.1", + "is-plain-obj": "^1.1.0", + "kind-of": "^6.0.3" + } + }, + "modify-values": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/modify-values/-/modify-values-1.0.1.tgz", + "integrity": "sha512-xV2bxeN6F7oYjZWTe/YPAy6MN2M+sL4u/Rlm2AHCIVGfo2p1yGmBHQ6vHehl4bRTZBdHu3TSkWdYgkwpYzAGSw==", + "dev": true + }, + "mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "peer": true + }, + "neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "dev": true + }, + "normalize-package-data": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-3.0.3.tgz", + "integrity": "sha512-p2W1sgqij3zMMyRC067Dg16bfzVH+w7hyegmpIvZ4JNjqtGOVAIvLmjBx3yP7YTe9vKJgkoNOPjwQGogDoMXFA==", + "dev": true, + "requires": { + "hosted-git-info": "^4.0.1", + "is-core-module": "^2.5.0", + "semver": "^7.3.4", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "dev": true, + "requires": { + "path-key": "^3.0.0" + } + }, + "null-check": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/null-check/-/null-check-1.0.0.tgz", + "integrity": "sha1-l33/1xdgErnsMNKjnbXPcqBDnt0=", + "dev": true + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "requires": { + "mimic-fn": "^2.1.0" + } + }, + "ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "peer": true, + "requires": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", + "dev": true + }, + "p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "requires": { + "yocto-queue": "^0.1.0" + } + }, + "p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "requires": { + "p-limit": "^3.0.2" + } + }, + "p-try": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", + "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", + "dev": true + }, + "parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "requires": { + "callsites": "^3.0.0" + } + }, + "parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + } + }, + "parse-passwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/parse-passwd/-/parse-passwd-1.0.0.tgz", + "integrity": "sha1-bVuTSkVpk7I9N/QKOC1vFmao5cY=", + "dev": true + }, + "path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", + "dev": true + }, + "path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true + }, + "path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", + "dev": true + }, + "path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true + }, + "picomatch": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.2.3.tgz", + "integrity": "sha512-KpELjfwcCDUb9PeigTs2mBJzXUPzAuP2oPcA989He8Rte0+YUAjw1JVedDhuTKPkHjSYzMN3npC9luThGYEKdg==", + "dev": true + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=", + "dev": true + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==", + "dev": true + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + }, + "q": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz", + "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc=", + "dev": true + }, + "quick-lru": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-4.0.1.tgz", + "integrity": "sha512-ARhCpm70fzdcvNQfPoy49IaanKkTlRWF2JMzqhcJbhSFRZv7nPTvZJdcY7301IPmvW+/p0RgIWnQDLJxifsQ7g==", + "dev": true + }, + "read-pkg": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", + "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", + "dev": true, + "requires": { + "@types/normalize-package-data": "^2.4.0", + "normalize-package-data": "^2.5.0", + "parse-json": "^5.0.0", + "type-fest": "^0.6.0" + }, + "dependencies": { + "hosted-git-info": { + "version": "2.8.9", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", + "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "dev": true + }, + "normalize-package-data": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", + "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", + "dev": true, + "requires": { + "hosted-git-info": "^2.1.4", + "resolve": "^1.10.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==", + "dev": true + }, + "type-fest": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", + "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", + "dev": true + } + } + }, + "read-pkg-up": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", + "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", + "dev": true, + "requires": { + "find-up": "^4.1.0", + "read-pkg": "^5.2.0", + "type-fest": "^0.8.1" + }, + "dependencies": { + "find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "requires": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + } + }, + "locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "requires": { + "p-locate": "^4.1.0" + } + }, + "p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "requires": { + "p-try": "^2.0.0" + } + }, + "p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "requires": { + "p-limit": "^2.2.0" + } + }, + "type-fest": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", + "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", + "dev": true + } + } + }, + "readable-stream": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz", + "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==", + "dev": true, + "requires": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + } + }, + "redent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz", + "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==", + "dev": true, + "requires": { + "indent-string": "^4.0.0", + "strip-indent": "^3.0.0" + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=", + "dev": true + }, + "resolve": { + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz", + "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==", + "dev": true, + "requires": { + "is-core-module": "^2.2.0", + "path-parse": "^1.0.6" + } + }, + "resolve-dir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-dir/-/resolve-dir-1.0.1.tgz", + "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", + "dev": true, + "requires": { + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" + } + }, + "resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "dev": true + }, + "resolve-global": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/resolve-global/-/resolve-global-1.0.0.tgz", + "integrity": "sha512-zFa12V4OLtT5XUX/Q4VLvTfBf+Ok0SPc1FNGM/z9ctUdiU618qwKpWnd0CHs3+RqROfyEg/DhuHbMWYqcgljEw==", + "dev": true, + "requires": { + "global-dirs": "^0.1.1" + } + }, + "restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "peer": true, + "requires": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + } + }, + "run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "dev": true + }, + "rxjs": { + "version": "7.4.0", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.4.0.tgz", + "integrity": "sha512-7SQDi7xeTMCJpqViXh8gL/lebcwlp3d831F05+9B44A4B0WfsEwUQHR64gsH1kvJ+Ep/J9K2+n1hVl1CsGN23w==", + "dev": true, + "peer": true, + "requires": { + "tslib": "~2.1.0" + } + }, + "safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "semver": { + "version": "7.3.5", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.3.5.tgz", + "integrity": "sha512-PoeGJYh8HK4BTO/a9Tf6ZG3veo/A7ZVsYrSA6J8ny9nb3B1VrpkuN+z9OE5wfE5p6H4LchYZsegiQgbJD94ZFQ==", + "dev": true, + "requires": { + "lru-cache": "^6.0.0" + } + }, + "shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "requires": { + "shebang-regex": "^3.0.0" + } + }, + "shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true + }, + "signal-exit": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.3.tgz", + "integrity": "sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA==", + "dev": true + }, + "source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true + }, + "spdx-correct": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", + "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", + "dev": true, + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", + "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "dev": true + }, + "spdx-expression-parse": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", + "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "dev": true, + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.10.tgz", + "integrity": "sha512-oie3/+gKf7QtpitB0LYLETe+k8SifzsX4KixvpOsbI6S0kRiRQ5MKOio8eMSAKQ17N06+wdEOXRiId+zOxo0hA==", + "dev": true + }, + "split": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split/-/split-1.0.1.tgz", + "integrity": "sha512-mTyOoPbrivtXnwnIxZRFYRrPNtEFKlpB2fvjSnCQUiAA6qAZzqwna5envK4uk6OIeP17CsdF3rSBGYVBsU0Tkg==", + "dev": true, + "requires": { + "through": "2" + } + }, + "split2": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", + "integrity": "sha512-9NThjpgZnifTkJpzTZ7Eue85S49QwpNhZTq6GRJwObb6jnLFNGB7Qm73V5HewTROPyxD0C29xqmaI68bQtV+hg==", + "dev": true, + "requires": { + "readable-stream": "^3.0.0" + } + }, + "standard-version": { + "version": "9.3.2", + "resolved": "https://registry.npmjs.org/standard-version/-/standard-version-9.3.2.tgz", + "integrity": "sha512-u1rfKP4o4ew7Yjbfycv80aNMN2feTiqseAhUhrrx2XtdQGmu7gucpziXe68Z4YfHVqlxVEzo4aUA0Iu3VQOTgQ==", + "dev": true, + "requires": { + "chalk": "^2.4.2", + "conventional-changelog": "3.1.24", + "conventional-changelog-config-spec": "2.1.0", + "conventional-changelog-conventionalcommits": "4.6.1", + "conventional-recommended-bump": "6.1.0", + "detect-indent": "^6.0.0", + "detect-newline": "^3.1.0", + "dotgitignore": "^2.1.0", + "figures": "^3.1.0", + "find-up": "^5.0.0", + "fs-access": "^1.0.1", + "git-semver-tags": "^4.0.0", + "semver": "^7.1.1", + "stringify-package": "^1.0.1", + "yargs": "^16.0.0" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dev": true, + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=", + "dev": true + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + }, + "yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + } + } + }, + "string_decoder": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", + "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", + "dev": true, + "requires": { + "safe-buffer": "~5.2.0" + } + }, + "string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "requires": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + } + }, + "stringify-package": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/stringify-package/-/stringify-package-1.0.1.tgz", + "integrity": "sha512-sa4DUQsYciMP1xhKWGuFM04fB0LG/9DlluZoSVywUMRNvzid6XucHK0/90xGxRoHrAaROrcHK1aPKaijCtSrhg==", + "dev": true + }, + "strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "requires": { + "ansi-regex": "^5.0.1" + } + }, + "strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true + }, + "strip-final-newline": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", + "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "dev": true + }, + "strip-indent": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", + "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "dev": true, + "requires": { + "min-indent": "^1.0.0" + } + }, + "strip-json-comments": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.0.1.tgz", + "integrity": "sha512-VTyMAUfdm047mwKl+u79WIdrZxtFtn+nBxHeb844XBQ9uMNTuTHdx2hc5RiAJYqwTj3wc/xe5HLSdJSkJ+WfZw==", + "dev": true + }, + "supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "requires": { + "has-flag": "^4.0.0" + } + }, + "text-extensions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/text-extensions/-/text-extensions-1.9.0.tgz", + "integrity": "sha512-wiBrwC1EhBelW12Zy26JeOUkQ5mRu+5o8rpsJk5+2t+Y5vE7e842qtZDQ2g1NpX/29HdyFeJ4nSIhI47ENSxlQ==", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "through2": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/through2/-/through2-4.0.2.tgz", + "integrity": "sha512-iOqSav00cVxEEICeD7TjLB1sueEL+81Wpzp2bY17uZjZN0pWZPuo4suZ/61VujxmqSGFfgOcNuTZ85QJwNZQpw==", + "dev": true, + "requires": { + "readable-stream": "3" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, + "trim-newlines": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/trim-newlines/-/trim-newlines-3.0.1.tgz", + "integrity": "sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==", + "dev": true + }, + "ts-node": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.4.0.tgz", + "integrity": "sha512-g0FlPvvCXSIO1JDF6S232P5jPYqBkRL9qly81ZgAOSU7rwI0stphCgd2kLiCrU9DjQCrJMWEqcNSjQL02s6d8A==", + "dev": true, + "requires": { + "@cspotcode/source-map-support": "0.7.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "yn": "3.1.1" + } + }, + "tslib": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.1.0.tgz", + "integrity": "sha512-hcVC3wYEziELGGmEEXue7D75zbwIIVUMWAVbHItGPx0ziyXxrOMQx4rQEVEV45Ut/1IotuEvwqPopzIOkDMf0A==", + "dev": true, + "peer": true + }, + "type-fest": { + "version": "0.18.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.18.1.tgz", + "integrity": "sha512-OIAYXk8+ISY+qTOwkHtKqzAuxchoMiD9Udx+FSGQDuiRR+PJKJHc2NJAXlbhkGwTt/4/nKZxELY1w3ReWOL8mw==", + "dev": true + }, + "typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c=", + "dev": true + }, + "typescript": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", + "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "dev": true + }, + "uglify-js": { + "version": "3.14.3", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.14.3.tgz", + "integrity": "sha512-mic3aOdiq01DuSVx0TseaEzMIVqebMZ0Z3vaeDhFEh9bsc24hV1TFvN74reA2vs08D0ZWfNjAcJ3UbVLaBss+g==", + "dev": true, + "optional": true + }, + "universalify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", + "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "dev": true + }, + "uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", + "dev": true + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "dev": true, + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g=", + "dev": true, + "peer": true, + "requires": { + "defaults": "^1.0.3" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "requires": { + "isexe": "^2.0.0" + } + }, + "word-wrap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz", + "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==", + "dev": true + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "requires": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", + "dev": true + }, + "xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "dev": true + }, + "y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "dev": true + }, + "yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", + "dev": true + }, + "yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "dev": true + }, + "yargs": { + "version": "17.2.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.2.1.tgz", + "integrity": "sha512-XfR8du6ua4K6uLGm5S6fA+FIJom/MdJcFNVY8geLlp2v8GYbOXD4EB1tPNZsRn4vBzKGMgb5DRZMeWuFc2GO8Q==", + "dev": true, + "requires": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + } + }, + "yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "dev": true + }, + "yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "dev": true + }, + "yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true + } + } +} diff --git a/arm-trusted-firmware/package.json b/arm-trusted-firmware/package.json new file mode 100644 index 0000000..e5cd924 --- /dev/null +++ b/arm-trusted-firmware/package.json @@ -0,0 +1,23 @@ +{ + "name": "trusted-firmware-a", + "version": "2.6.0", + "license": "BSD-3-Clause", + "private": true, + "scripts": { + "postinstall": "husky install", + "release": "standard-version" + }, + "engines": { + "node": ">=16.0.0" + }, + "devDependencies": { + "@commitlint/cli": "^16.1.0", + "@commitlint/config-conventional": "^16.0.0", + "@commitlint/cz-commitlint": "^16.1.0", + "commitizen": "^4.2.4", + "conventional-changelog-tf-a": "file:tools/conventional-changelog-tf-a", + "husky": "^7.0.4", + "js-yaml": "^4.1.0", + "standard-version": "^9.3.2" + } +} diff --git a/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk b/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk new file mode 100644 index 0000000..34fdaf6 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/allwinner-common.mk @@ -0,0 +1,96 @@ +# +# 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}/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)) + +# 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/arm-trusted-firmware/plat/allwinner/common/arisc_off.S b/arm-trusted-firmware/plat/allwinner/common/arisc_off.S new file mode 100644 index 0000000..ed10832 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/arisc_off.S @@ -0,0 +1,115 @@ +# turn_off_core.S +# +# Copyright (c) 2018, Andre Przywara +# 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/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h b/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h new file mode 100644 index 0000000..d03f2d1 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h @@ -0,0 +1,28 @@ +/* + * Copyright (C) 2018 Icenowy Zheng + * + * 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/arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S b/arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S new file mode 100644 index 0000000..77f183d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h b/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h new file mode 100644 index 0000000..49951e0 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/platform_def.h @@ -0,0 +1,83 @@ +/* + * 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 +#include +#include + +#include + +#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) + +#define PLAT_MAX_PWR_LVL_STATES U(2) +#define PLAT_MAX_RET_STATE U(1) +#define PLAT_MAX_OFF_STATE U(2) + +#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/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h new file mode 100644 index 0000000..ec50887 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h @@ -0,0 +1,23 @@ +/* + * 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 + +#endif /* SUNXI_DEF_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h new file mode 100644 index 0000000..6cf4670 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h @@ -0,0 +1,52 @@ +/* + * 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 + +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 +int sunxi_set_scpi_psci_ops(const plat_psci_ops_t **psci_ops); +#else +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); + +#ifdef SUNXI_BL31_IN_DRAM +void sunxi_prepare_dtb(void *fdt); +#else +static inline void sunxi_prepare_dtb(void *fdt) +{ +} +#endif + +#endif /* SUNXI_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/allwinner/common/plat_helpers.S b/arm-trusted-firmware/plat/allwinner/common/plat_helpers.S new file mode 100644 index 0000000..b00c7ae --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c new file mode 100644 index 0000000..14049e8 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c @@ -0,0 +1,199 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + + +static entry_point_info_t bl32_image_ep_info; +static entry_point_info_t bl33_image_ep_info; + +static console_t console; + +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++) { + uint32_t *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 = (void *)((char *)u_boot_base + u_boot_base[i + 1]); + + if (fdt_check_header(dtb_base) != 0) + continue; + + return dtb_base; + } + + return NULL; +} + +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(); + void *fdt; + + 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(); + + fdt = 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); + + sunxi_prepare_dtb(fdt); + + INFO("BL31: Platform setup done\n"); +} + +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/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c new file mode 100644 index 0000000..82410b1 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_common.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include + +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; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c new file mode 100644 index 0000000..46e7090 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c new file mode 100644 index 0000000..148f50e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c new file mode 100644 index 0000000..eb1b7e7 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#include +#include + +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"); + } else { + INFO("PSCI: Suspend is unavailable\n"); + sunxi_set_native_psci_ops(psci_ops); + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c new file mode 100644 index 0000000..eb37daa --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * 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 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 inline scpi_power_state_t scpi_map_state(plat_local_state_t psci_state) +{ + if (is_local_state_run(psci_state)) { + return scpi_power_on; + } + if (is_local_state_retn(psci_state)) { + return scpi_power_retention; + } + return scpi_power_off; +} + +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(), + scpi_map_state(cpu_pwr_state), + scpi_map_state(cluster_pwr_state), + scpi_map_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 type = psci_get_pstate_type(power_state); + + assert(req_state != NULL); + + if (power_level > PLAT_MAX_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + + if (type == PSTATE_TYPE_STANDBY) { + /* Only one retention power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + /* The SoC cannot be suspended without losing state */ + if (power_level == SYSTEM_PWR_LVL) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_RET_STATE; + } + } else { + /* Only one off power state is supported. */ + if (psci_get_pstate_id(power_state) > 0) { + return PSCI_E_INVALID_PARAMS; + } + for (unsigned int i = 0; i <= power_level; ++i) { + req_state->pwr_domain_state[i] = PLAT_MAX_OFF_STATE; + } + } + /* Higher power domain levels should all remain running */ + for (unsigned int i = power_level + 1; 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/arm-trusted-firmware/plat/allwinner/common/sunxi_security.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_security.c new file mode 100644 index 0000000..98b91c3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c b/arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c new file mode 100644 index 0000000..45be1e0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h new file mode 100644 index 0000000..ae436ca --- /dev/null +++ b/arm-trusted-firmware/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, */ + 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/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h new file mode 100644 index 0000000..2a24886 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h new file mode 100644 index 0000000..aed3585 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h new file mode 100644 index 0000000..6d10921 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h new file mode 100644 index 0000000..5ba7e18 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_a64/platform.mk new file mode 100644 index 0000000..e3c7c52 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c new file mode 100644 index 0000000..a35b9dd --- /dev/null +++ b/arm-trusted-firmware/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 + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h new file mode 100644 index 0000000..85fbb90 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h new file mode 100644 index 0000000..5bfda5d --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h new file mode 100644 index 0000000..58216d8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h new file mode 100644 index 0000000..0f5965b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_h6/platform.mk new file mode 100644 index 0000000..e13e8cb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c new file mode 100644 index 0000000..d298e6b --- /dev/null +++ b/arm-trusted-firmware/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 + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h new file mode 100644 index 0000000..85fbb90 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h new file mode 100644 index 0000000..dab663b --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h new file mode 100644 index 0000000..3b4f4a0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h new file mode 100644 index 0000000..0f5965b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk new file mode 100644 index 0000000..fc09af7 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/platform.mk @@ -0,0 +1,24 @@ +# +# Copyright (c) 2017-2020, ARM Limited. All rights reserved. +# +# 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 "H616 does not support SCPI PSCI ops") +endif + +BL31_SOURCES += drivers/allwinner/axp/axp805.c \ + drivers/allwinner/sunxi_rsb.c \ + common/fdt_fixup.c \ + ${AW_PLAT}/${PLAT}/prepare_dtb.c + +$(eval $(call add_define,SUNXI_BL31_IN_DRAM)) diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c b/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c new file mode 100644 index 0000000..e94b0b4 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +void sunxi_prepare_dtb(void *fdt) +{ + int ret; + + if (fdt == NULL || fdt_check_header(fdt) != 0) { + return; + } + ret = fdt_open_into(fdt, fdt, 0x100000); + if (ret < 0) { + ERROR("Preparing devicetree at %p: error %d\n", fdt, ret); + return; + } + + /* 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"); + return; + } + + ret = fdt_pack(fdt); + if (ret < 0) { + ERROR("Failed to pack devicetree at %p: error %d\n", + fdt, ret); + } else { + clean_dcache_range((uintptr_t)fdt, fdt_blob_size(fdt)); + INFO("Changed devicetree to reserve BL31 memory.\n"); + } +} diff --git a/arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c new file mode 100644 index 0000000..dd6ebba --- /dev/null +++ b/arm-trusted-firmware/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 + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h new file mode 100644 index 0000000..0e6b543 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h new file mode 100644 index 0000000..9478f32 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h new file mode 100644 index 0000000..a4469b5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h b/arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h new file mode 100644 index 0000000..2c87bca --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk b/arm-trusted-firmware/plat/allwinner/sun50i_r329/platform.mk new file mode 100644 index 0000000..05d7cde --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c b/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c new file mode 100644 index 0000000..96a24d5 --- /dev/null +++ b/arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021 Sipeed + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c new file mode 100644 index 0000000..8cc9d69 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/axg/axg_common.c b/arm-trusted-firmware/plat/amlogic/axg/axg_common.c new file mode 100644 index 0000000..870daf4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/axg/axg_def.h b/arm-trusted-firmware/plat/amlogic/axg/axg_def.h new file mode 100644 index 0000000..d90681a --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/axg/axg_pm.c b/arm-trusted-firmware/plat/amlogic/axg/axg_pm.c new file mode 100644 index 0000000..e67f263 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h new file mode 100644 index 0000000..c97687e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/amlogic/axg/platform.mk b/arm-trusted-firmware/plat/amlogic/axg/platform.mk new file mode 100644 index 0000000..3560b0c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S b/arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S new file mode 100644 index 0000000..159c7d1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/amlogic/common/aml_console.c b/arm-trusted-firmware/plat/amlogic/common/aml_console.c new file mode 100644 index 0000000..e21d707 --- /dev/null +++ b/arm-trusted-firmware/plat/amlogic/common/aml_console.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2019, Carlo Caione + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/common/aml_efuse.c b/arm-trusted-firmware/plat/amlogic/common/aml_efuse.c new file mode 100644 index 0000000..00884eb --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/amlogic/common/aml_mhu.c b/arm-trusted-firmware/plat/amlogic/common/aml_mhu.c new file mode 100644 index 0000000..001686a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/amlogic/common/aml_scpi.c b/arm-trusted-firmware/plat/amlogic/common/aml_scpi.c new file mode 100644 index 0000000..c8a6772 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c b/arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c new file mode 100644 index 0000000..ab4c015 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/common/aml_thermal.c b/arm-trusted-firmware/plat/amlogic/common/aml_thermal.c new file mode 100644 index 0000000..53ed103 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/amlogic/common/aml_topology.c b/arm-trusted-firmware/plat/amlogic/common/aml_topology.c new file mode 100644 index 0000000..0a04c11 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/common/include/aml_private.h b/arm-trusted-firmware/plat/amlogic/common/include/aml_private.h new file mode 100644 index 0000000..724f382 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S b/arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S new file mode 100644 index 0000000..d620fcf --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +.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/arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c new file mode 100644 index 0000000..77057a1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c new file mode 100644 index 0000000..e74ed04 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h b/arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h new file mode 100644 index 0000000..d032815 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c b/arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c new file mode 100644 index 0000000..c9fe3e9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h new file mode 100644 index 0000000..23d816d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/amlogic/g12a/platform.mk b/arm-trusted-firmware/plat/amlogic/g12a/platform.mk new file mode 100644 index 0000000..b0c91b0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c new file mode 100644 index 0000000..cc7a1c4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c new file mode 100644 index 0000000..260a347 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h new file mode 100644 index 0000000..fa5e4fa --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c b/arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c new file mode 100644 index 0000000..48bff7b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h new file mode 100644 index 0000000..a5cbe78 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/amlogic/gxbb/platform.mk b/arm-trusted-firmware/plat/amlogic/gxbb/platform.mk new file mode 100644 index 0000000..62384d2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c new file mode 100644 index 0000000..f581dd1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c new file mode 100644 index 0000000..e1d7bfb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h b/arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h new file mode 100644 index 0000000..f30eb28 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c b/arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c new file mode 100644 index 0000000..433140b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h b/arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h new file mode 100644 index 0000000..ec64d68 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/amlogic/gxl/platform.mk b/arm-trusted-firmware/plat/amlogic/gxl/platform.mk new file mode 100644 index 0000000..641d177 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c new file mode 100644 index 0000000..629c928 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c new file mode 100644 index 0000000..1979c50 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c new file mode 100644 index 0000000..a4a0cff --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c new file mode 100644 index 0000000..feb9fdf --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * a5ds error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c new file mode 100644 index 0000000..7774002 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h new file mode 100644 index 0000000..f577249 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c new file mode 100644 index 0000000..5593ae0 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c b/arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c new file mode 100644 index 0000000..94fa71f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S b/arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S new file mode 100644 index 0000000..ed7ad9c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts new file mode 100644 index 0000000..b9ff8bf --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x2001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x01000000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h new file mode 100644 index 0000000..9f3df1e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/a5ds/platform.mk b/arm-trusted-firmware/plat/arm/board/a5ds/platform.mk new file mode 100644 index 0000000..4f87306 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c new file mode 100644 index 0000000..a951dc7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + +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/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk b/arm-trusted-firmware/plat/arm/board/a5ds/sp_min/sp_min-a5ds.mk new file mode 100644 index 0000000..4b0c97d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S new file mode 100644 index 0000000..20120c9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include "../fpga_private.h" + +#include + + .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/arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S new file mode 100644 index 0000000..d8254e5 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c new file mode 100644 index 0000000..e1b3abb --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fpga_private.h" +#include +#include + +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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c new file mode 100644 index 0000000..8c1da62 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h new file mode 100644 index 0000000..2884ea6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c new file mode 100644 index 0000000..e06a9da --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c new file mode 100644 index 0000000..a306a23 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include "fpga_private.h" +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h new file mode 100644 index 0000000..84d651c --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c b/arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c new file mode 100644 index 0000000..7fead86 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include "fpga_private.h" +#include +#include + +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/arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S new file mode 100644 index 0000000..44cddeb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h new file mode 100644 index 0000000..2350d87 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#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/arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S new file mode 100644 index 0000000..f4c08ef --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +.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/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk b/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk new file mode 100644 index 0000000..084532c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/arm_fpga/platform.mk @@ -0,0 +1,130 @@ +# +# Copyright (c) 2021, 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_makalu.S \ + lib/cpus/aarch64/cortex_makalu_elp_arm.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/arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S b/arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S new file mode 100644 index 0000000..cd66c79 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +.text +.global _start + +_start: + mov_imm x1, BL31_BASE /* beginning of DRAM */ + mov_imm x0, FPGA_PRELOADED_DTB_BASE + br x1 diff --git a/arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S b/arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S new file mode 100644 index 0000000..8c63693 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S b/arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S new file mode 100644 index 0000000..cde6b00 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..66cc3e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(ARM_COT_tbbr) +#include +#elif defined(ARM_COT_dualroot) +#include +#endif + +#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; + } +} +#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/arm-trusted-firmware/plat/arm/board/common/board_common.mk b/arm-trusted-firmware/plat/arm/board/common/board_common.mk new file mode 100644 index 0000000..5cdf1bf --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/board_common.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2015-2020, 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)) + +# 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 ${CRYPTO_ALG} -in $< -pubout -outform DER | 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 + +endif diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/README b/arm-trusted-firmware/plat/arm/board/common/protpk/README new file mode 100644 index 0000000..3aca180 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S new file mode 100644 index 0000000..2688cbb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin new file mode 100644 index 0000000..587da66 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin @@ -0,0 +1 @@ +œó6{W*…`Ÿtíve×·§è£ €¾PžÆK{9 \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem b/arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem new file mode 100644 index 0000000..eeaad9e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S new file mode 100644 index 0000000..06e2a06 --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der new file mode 100644 index 0000000000000000000000000000000000000000..254787720cfd07278a7dd446f9feec5e06f1d431 GIT binary patch literal 91 zcmXqrG!SNE*J|@PXUoLM#sOw9GqN)~F|f>j=CRkr;^Cqtp9>y_?AG59<;C;=Q2Xrz vzZ+lv{5iF@ZUIj{*OdoJUQ^=V1l77EpO~Nc>)7eK?BKOJN2l;gwM_&7S+Xee literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin new file mode 100644 index 0000000..c5e123a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin @@ -0,0 +1 @@ +.@¿nù»˜1q = ýÑÌiJ˜ë‹ ° †Nl \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der new file mode 100644 index 0000000000000000000000000000000000000000..661f8998df780e571477691d8d53c2bbec19ae16 GIT binary patch literal 294 zcmV+>0ondAf&n5h4F(A+hDe6@4FLfG1potr0S^E$f&mHwf&l>l%Pe5kjbqdYd49(h zmc30RPOOIJw{hdeR14=69K9(T!9RMo0;;Pv#Mw4!Y~p3Zo3Xz=s8%M+{R9EJtUgpS z%6VS9vIXh}Sn_nb;q-^V844d}2X};np&al3C|T#jXniIiL+e&!^EoltD^aPuPtf+> zmE2!j!R?T5>?o0b7wveE^kApN$4^l0T@yMXD{#eOdk7(AI?aMsjCx0`iRh(BNHN(R zM&*Tun4smrrfR(hwp99JrTKdtiAy*L70s{d60nnC)o&W#< literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin new file mode 100644 index 0000000..7653f7e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin @@ -0,0 +1 @@ +°ó‚ —Ø:7zrGì2sé’2âIYö^‹JJFØ"šÚ \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem new file mode 100644 index 0000000..fb328e3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem b/arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem new file mode 100644 index 0000000..71410ec --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c new file mode 100644 index 0000000..3ee396c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c new file mode 100644 index 0000000..376799f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * corstone1000 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S new file mode 100644 index 0000000..cbe27c3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c new file mode 100644 index 0000000..a96baae --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c new file mode 100644 index 0000000..98dea79 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c new file mode 100644 index 0000000..c88201b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c new file mode 100644 index 0000000..393235e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c new file mode 100644 index 0000000..5351896 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c new file mode 100644 index 0000000..cec7332 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts new file mode 100644 index 0000000..8e49ab8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h new file mode 100644 index 0000000..2523d72 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h @@ -0,0 +1,436 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +#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 + * + * + * + * partition size: sizeof(meminfo_t) = 16 bytes + * + * content: memory info area used by the next BL + * + * + * + * partition size: 4080 bytes + * + * + * + * partition size: 4 KB + * + * content: + * + * Area where BL2 copies the images descriptors + * + * = + * + * partition size: 688 KB + * + * content: + * + * BL32 (optee-os) + * + * = 0x20ae000 + * + * partition size: 8 KB + * + * content: + * + * BL32 config (TOS_FW_CONFIG) + * + * + * + * partition size: 140 KB + * + * content: + * + * BL31 + * + * + * + * partition size: 4 KB + * + * content: + * + * MCUBOOT data needed to verify TF-A BL2 + * + * + * + * partition size: 176 KB + * + * content: + * + * BL2 + * + * = + 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/arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S new file mode 100644 index 0000000..9334201 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk b/arm-trusted-firmware/plat/arm/board/corstone1000/platform.mk new file mode 100644 index 0000000..d891691 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S new file mode 100644 index 0000000..c713f4f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c new file mode 100644 index 0000000..629f076 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2019-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c new file mode 100644 index 0000000..4884ea5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c new file mode 100644 index 0000000..39b2fc9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c new file mode 100644 index 0000000..6fd09da --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c new file mode 100644 index 0000000..904f5ab --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c new file mode 100644 index 0000000..2231d11 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "mhu.h" +#include +#include + +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/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h new file mode 100644 index 0000000..3808746 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019-2020, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MHU_H +#define 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 /* MHU_H */ diff --git a/arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h new file mode 100644 index 0000000..57b0551 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk b/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk new file mode 100644 index 0000000..9a8d38c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/corstone700/platform.mk @@ -0,0 +1,63 @@ +# +# Copyright (c) 2019-2020, 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/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/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c new file mode 100644 index 0000000..2fc0e0d --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk b/arm-trusted-firmware/plat/arm/board/corstone700/sp_min/sp_min-corstone700.mk new file mode 100644 index 0000000..75dc0f1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S new file mode 100644 index 0000000..9985c1d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S new file mode 100644 index 0000000..8efc238 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c b/arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c new file mode 100644 index 0000000..759f6d0 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c new file mode 100644 index 0000000..45e3b7e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c b/arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c new file mode 100644 index 0000000..e258015 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +#include + +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/arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi b/arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi new file mode 100644 index 0000000..47af672 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts new file mode 100644 index 0000000..c26b519 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x1800>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x01000000>; + id = ; + }; + + /* + * 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 = ; + }; + +/* 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 = ; + }; +#endif + + nt_fw-config { + load-address = <0x0 0x80000000>; + max-size = <0x200>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts new file mode 100644 index 0000000..8f32b98 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts new file mode 100644 index 0000000..7ab980b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts new file mode 100644 index 0000000..21a6073 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts @@ -0,0 +1,85 @@ +/* + * 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 = "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 */ + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..041dade --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts new file mode 100644 index 0000000..cf4ef2d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2020-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/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"; + 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 = ; +}; + +&non_trusted_nv_counter { + reg = ; +}; +#endif diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts new file mode 100644 index 0000000..7bed6cb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts new file mode 100644 index 0000000..b803340 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2020-2021, 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 = <0x1000>; + 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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c new file mode 100644 index 0000000..5468555 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/* 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 */ +}; + +void bl1_plat_mboot_init(void) +{ + event_log_init(event_log, event_log + sizeof(event_log)); + event_log_write_header(); +} + +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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c new file mode 100644 index 0000000..59fc0f3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c new file mode 100644 index 0000000..7def56a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c new file mode 100644 index 0000000..1f38278 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +/* 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}, + + { CRITICAL_DATA_ID, EVLOG_CRITICAL_DATA_STRING, PCR_1 }, + + { EVLOG_INVALID_ID, NULL, (unsigned int)(-1) } /* Terminator */ +}; + +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); +} + +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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c new file mode 100644 index 0000000..5a17a0d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2013-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; + + arm_bl_params = arm_get_next_bl_params(); + +#if __aarch64__ && !BL2_AT_EL3 + 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 = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; +#endif /* __aarch64__ && !BL2_AT_EL3 */ + + return arm_bl_params; +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c new file mode 100644 index 0000000..fd73767 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c new file mode 100644 index 0000000..a94a4f4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fvp_private.h" + +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; + } +#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) +{ + 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. + */ +#if !RESET_TO_BL31 && !BL2_AT_EL3 + /* 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); +#endif +} + +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/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c new file mode 100644 index 0000000..d8d19de --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c @@ -0,0 +1,517 @@ +/* + * Copyright (c) 2013-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if SPM_MM +#include +#endif + +#include +#include +#include + +#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 +#if defined(SPD_spmd) + ARM_MAP_TRUSTED_DRAM, +#endif +#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 + 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 + /* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */ + ARM_DTB_DRAM_NS, +#if ENABLE_RME + ARM_MAP_GPT_L1_DRAM, +#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, + /* Required by fconf APIs to read HW_CONFIG dtb loaded into DRAM */ + ARM_DTB_DRAM_NS, + {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); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c new file mode 100644 index 0000000..6a403d9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +extern event_log_metadata_t fvp_event_log_metadata[]; + +const event_log_metadata_t *plat_event_log_get_metadata(void) +{ + return fvp_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/arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c new file mode 100644 index 0000000..1a6cd42 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h b/arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h new file mode 100644 index 0000000..831eb35 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c new file mode 100644 index 0000000..1f9f0dd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2019-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +/* + * 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(); +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c new file mode 100644 index 0000000..8f3e7b7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c new file mode 100644 index 0000000..4eef51c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c new file mode 100644 index 0000000..5463f33 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/* Using hardcoded token values for AEM FVP */ +static uint8_t platform_token[] = { + 0xD2, 0x84, 0x40, 0xA0, 0x59, 0x08, 0xB1, 0xD9, + 0x61, 0xA8, 0xA9, 0x0A, 0x58, 0x40, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, + 0x01, 0x24, 0xFA, 0x58, 0x40, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, + 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0x3A, 0x00, 0x01, + 0x25, 0x00, 0x58, 0x41, 0x01, 0x0B, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, + 0xBB, 0xBB, 0xBB, 0xBB, 0xBB, 0x12, 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, 0x0B, 0x58, 0x19, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0x3A, 0x00, 0x01, 0x24, 0xF7, 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, 0x3A, 0x00, 0x01, 0x25, 0x01, + 0x78, 0x18, 0x68, 0x74, 0x74, 0x70, 0x73, 0x3A, + 0x2F, 0x2F, 0x63, 0x63, 0x61, 0x5F, 0x76, 0x65, + 0x72, 0x69, 0x66, 0x69, 0x65, 0x72, 0x2E, 0x6F, + 0x72, 0x67, 0x3A, 0x00, 0x01, 0x24, 0xF9, 0x19, + 0x30, 0x00, 0x3A, 0x00, 0x01, 0x24, 0xFD, 0x8D, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0xA4, 0x02, 0x58, 0x40, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC, + 0xCC, 0xCC, 0xCC, 0xCC, 0x05, 0x58, 0x40, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, + 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0xDD, 0x04, + 0x65, 0x31, 0x2E, 0x30, 0x2E, 0x30, 0x06, 0x08, + 0x58, 0x40, 0xD3, 0x8A, 0x41, 0xA6, 0xC1, 0x29, + 0x98, 0x18, 0xB5, 0x16, 0x9C, 0x21, 0x78, 0xB7, + 0x92, 0xF8, 0x26, 0x82, 0x76, 0x2F, 0x26, 0x45, + 0x21, 0x6D, 0x0C, 0x21, 0x06, 0xF4, 0xB5, 0xE3, + 0xA8, 0x07, 0xD1, 0xD6, 0x8C, 0x73, 0xA5, 0xC8, + 0x16, 0xD8, 0x30, 0x68, 0xC0, 0xA4, 0x77, 0xE2, + 0x1E, 0xD2, 0x17, 0x86, 0xC3, 0x68, 0x82, 0xDD, + 0x21, 0x1B, 0xA3, 0xE2, 0xC7, 0xF7, 0x06, 0x33, + 0xB0, 0x3A +}; + +int plat_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/arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c new file mode 100644 index 0000000..6b9d618 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h b/arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h new file mode 100644 index 0000000..3590370 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c new file mode 100644 index 0000000..b32f557 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +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_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/arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c new file mode 100644 index 0000000..573d92e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c new file mode 100644 index 0000000..e940a12 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c new file mode 100644 index 0000000..80cfbd5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c new file mode 100644 index 0000000..1ea37f7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h new file mode 100644 index 0000000..ca85f7a --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h new file mode 100644 index 0000000..0824c35 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h b/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h new file mode 100644 index 0000000..3010d21 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#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]; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S b/arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S new file mode 100644 index 0000000..7c8bf06 --- /dev/null +++ b/arm-trusted-firmware/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 + +#if RECLAIM_INIT_CODE +#include +#endif /* RECLAIM_INIT_CODE */ + +#endif /* PLAT_LD_S */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S new file mode 100644 index 0000000..57f5924 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h new file mode 100644 index 0000000..5e5ddce --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h @@ -0,0 +1,363 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#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) +/* + * 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 +# if ENABLE_RME +# define MAX_XLAT_TABLES 11 +# else +# define MAX_XLAT_TABLES 9 +# endif +# define PLAT_SP_IMAGE_MMAP_REGIONS 30 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 10 +# else +# define PLAT_ARM_MMAP_ENTRIES 9 +# if USE_DEBUGFS +# if ENABLE_RME +# define MAX_XLAT_TABLES 10 +# else +# define MAX_XLAT_TABLES 8 +# endif +# else +# if ENABLE_RME +# define MAX_XLAT_TABLES 9 +# else +# define MAX_XLAT_TABLES 7 +# endif +# endif +# endif +#elif defined(IMAGE_BL32) +# define PLAT_ARM_MMAP_ENTRIES 9 +# define MAX_XLAT_TABLES 6 +#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) +#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) +# define PLATFORM_STACK_SIZE UL(0x800) +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE UL(0x440) +#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) + +/* 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) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i b/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i new file mode 100644 index 0000000..b72bdab --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i @@ -0,0 +1,61 @@ +# +# Copyright (c) 2018-2020, 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 +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/arm-trusted-firmware/plat/arm/board/fvp/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp/platform.mk new file mode 100644 index 0000000..c9f5551 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/platform.mk @@ -0,0 +1,401 @@ +# +# 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_demeter.S \ + lib/cpus/aarch64/cortex_a78_ae.S \ + lib/cpus/aarch64/cortex_a510.S \ + lib/cpus/aarch64/cortex_a710.S \ + lib/cpus/aarch64/cortex_makalu.S \ + lib/cpus/aarch64/cortex_makalu_elp_arm.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_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 (${ARCH},aarch32) + ifeq (${RESET_TO_SP_MIN},1) + BL32_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +else # AArch64 + ifeq (${RESET_TO_BL31},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif + ifeq (${SPD},trusty) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC + endif +endif + +ifeq (${ENABLE_RME},1) + BL31_CPPFLAGS += -DPLAT_XLAT_TABLES_DYNAMIC +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 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 +BL2_SOURCES += plat/arm/board/fvp/fvp_common_measured_boot.c \ + plat/arm/board/fvp/fvp_bl2_measured_boot.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 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 diff --git a/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c new file mode 100644 index 0000000..763b42a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include "../fvp_private.h" + +uintptr_t hw_config_dtb; + +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 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(); + + hw_config_dtb = arg2; +} + +void sp_min_plat_arch_setup(void) +{ + 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. + */ +#if !RESET_TO_SP_MIN && !BL2_AT_EL3 + assert(hw_config_dtb != 0U); + + INFO("SP_MIN FCONF: HW_CONFIG address = %p\n", (void *)hw_config_dtb); + fconf_populate("HW_CONFIG", hw_config_dtb); +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk new file mode 100644 index 0000000..0d8cca5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp/sp_min/sp_min-fvp.mk @@ -0,0 +1,38 @@ +# +# Copyright (c) 2016-2021, 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 \ + 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/arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/trp/trp-fvp.mk new file mode 100644 index 0000000..a450541 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c b/arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c new file mode 100644 index 0000000..3c8a963 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk b/arm-trusted-firmware/plat/arm/board/fvp/tsp/tsp-fvp.mk new file mode 100644 index 0000000..ab3f225 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c new file mode 100644 index 0000000..ae6af6c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S new file mode 100644 index 0000000..15f4c43 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S new file mode 100644 index 0000000..43c2e01 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c new file mode 100644 index 0000000..841a176 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include "../../../../bl1/bl1_private.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + + +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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c new file mode 100644 index 0000000..68872c1 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c @@ -0,0 +1,247 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include + +#include "fvp_r_private.h" +#include +#include +#include +#include +#include + +#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, 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c new file mode 100644 index 0000000..edcf658 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fvp_r_private.h" +#include +#include +#include +#include + + +/* 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c new file mode 100644 index 0000000..d172d2d --- /dev/null +++ b/arm-trusted-firmware/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 + +/************************************************************ + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S new file mode 100644 index 0000000..88f0a29 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h new file mode 100644 index 0000000..eda39cf --- /dev/null +++ b/arm-trusted-firmware/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 + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c new file mode 100644 index 0000000..7ee752b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S new file mode 100644 index 0000000..ba85777 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include + + + .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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c new file mode 100644 index 0000000..3b44828 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S new file mode 100644 index 0000000..67ad164 --- /dev/null +++ b/arm-trusted-firmware/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 + + .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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h new file mode 100644 index 0000000..48f6e89 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c new file mode 100644 index 0000000..69b6312 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c new file mode 100644 index 0000000..de0b28f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + + +/* + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h b/arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h new file mode 100644 index 0000000..92bf484 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h new file mode 100644 index 0000000..ea3a258 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* 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 +#include + + +/* 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/arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp_r/platform.mk new file mode 100644 index 0000000..93b5cf2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S b/arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S new file mode 100644 index 0000000..78f6c68 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts new file mode 100644 index 0000000..6e5691b --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x80001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x01000000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts new file mode 100644 index 0000000..c66186f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c new file mode 100644 index 0000000..736cf42 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c new file mode 100644 index 0000000..4ccae27 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c new file mode 100644 index 0000000..768dad5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h new file mode 100644 index 0000000..98de5f6 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c new file mode 100644 index 0000000..8d35688 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * FVP VE error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c new file mode 100644 index 0000000..a4d627b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h new file mode 100644 index 0000000..5d396bc --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ + +void fvp_ve_config_setup(void); + +#endif /* FVP_VE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c new file mode 100644 index 0000000..24465cb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c new file mode 100644 index 0000000..51cc9da --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h new file mode 100644 index 0000000..bd8ef6a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk b/arm-trusted-firmware/plat/arm/board/fvp_ve/platform.mk new file mode 100644 index 0000000..f7eace8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c new file mode 100644 index 0000000..e6a1bbe --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk b/arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/sp_min-fvp_ve.mk new file mode 100644 index 0000000..4ca810d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S b/arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S new file mode 100644 index 0000000..8f9561c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S b/arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S new file mode 100644 index 0000000..c94fa3e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts new file mode 100644 index 0000000..4b88efe --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + hw-config { + load-address = <0x0 0x82000000>; + max-size = <0x8000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts new file mode 100644 index 0000000..80cfa3e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S new file mode 100644 index 0000000..ec94a4f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h new file mode 100644 index 0000000..d61ba5d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h @@ -0,0 +1,319 @@ +/* + * 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 +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#include + +#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 + +/* + * Since free SRAM space is scant, enable the ASSERTION message size + * optimization by fixing the PLAT_LOG_LEVEL_ASSERT to LOG_LEVEL_INFO (40). + */ +#define PLAT_LOG_LEVEL_ASSERT 40 + +/* 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/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i b/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i new file mode 100644 index 0000000..393a648 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/juno/jmptbl.i @@ -0,0 +1,60 @@ +# +# Copyright (c) 2018-2020, 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 +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/arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c new file mode 100644 index 0000000..a9d5cc3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c new file mode 100644 index 0000000..849acd6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include + +#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 = ¶m_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/arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c new file mode 100644 index 0000000..7a0a6d9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/arm/board/juno/juno_common.c b/arm-trusted-firmware/plat/arm/board/juno/juno_common.c new file mode 100644 index 0000000..038f604 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/juno/juno_def.h b/arm-trusted-firmware/plat/arm/board/juno/juno_def.h new file mode 100644 index 0000000..ddf99dc --- /dev/null +++ b/arm-trusted-firmware/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 + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/juno/juno_err.c b/arm-trusted-firmware/plat/arm/board/juno/juno_err.c new file mode 100644 index 0000000..02d751e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/juno/juno_pm.c b/arm-trusted-firmware/plat/arm/board/juno/juno_pm.c new file mode 100644 index 0000000..cc80651 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/juno/juno_security.c b/arm-trusted-firmware/plat/arm/board/juno/juno_security.c new file mode 100644 index 0000000..654a7f1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c b/arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c new file mode 100644 index 0000000..3924af8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/juno/juno_topology.c b/arm-trusted-firmware/plat/arm/board/juno/juno_topology.c new file mode 100644 index 0000000..075f512 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/juno/juno_trng.c b/arm-trusted-firmware/plat/arm/board/juno/juno_trng.c new file mode 100644 index 0000000..09552a6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c new file mode 100644 index 0000000..25a7470 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h b/arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h new file mode 100644 index 0000000..4186d02 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/juno/platform.mk b/arm-trusted-firmware/plat/arm/board/juno/platform.mk new file mode 100644 index 0000000..2c84eb3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk b/arm-trusted-firmware/plat/arm/board/juno/sp_min/sp_min-juno.mk new file mode 100644 index 0000000..b3471c1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk b/arm-trusted-firmware/plat/arm/board/juno/tsp/tsp-juno.mk new file mode 100644 index 0000000..be75c4d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S b/arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S new file mode 100644 index 0000000..60470a8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include + + .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/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts new file mode 100644 index 0000000..c47bae5 --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts new file mode 100644 index 0000000..e730d34 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts new file mode 100644 index 0000000..305a818 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S new file mode 100644 index 0000000..195be84 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h new file mode 100644 index 0000000..08e2d60 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c new file mode 100644 index 0000000..9155542 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * Perform any BL1 specific platform actions. + ******************************************************************************/ + +void soc_css_init_nic400(void) +{ +} + +void soc_css_init_pcie(void) +{ +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c new file mode 100644 index 0000000..0d4b6d0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +void bl2_platform_setup(void) +{ +#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 DDR memory range 0x80000000 - 0xFFFFFFFF during BL2 stage, + * as BL33 binary cannot be copied to DDR memory before enabling ECC. + * Rest of the DDR memory space is zeroed out during BL31 stage. + */ + 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); +#endif + arm_bl2_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c new file mode 100644 index 0000000..e418518 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c @@ -0,0 +1,243 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "morello_def.h" +#include + +#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); + +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); +} + +#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 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 bl31_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(); + } + + arm_bl31_platform_setup(); + +#ifdef TARGET_PLATFORM_SOC + dmc_ecc_setup(&plat_info); +#endif +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_def.h b/arm-trusted-firmware/plat/arm/board/morello/morello_def.h new file mode 100644 index 0000000..f154924 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/morello_err.c b/arm-trusted-firmware/plat/arm/board/morello/morello_err.c new file mode 100644 index 0000000..4d20a09 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * morello error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c b/arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c new file mode 100644 index 0000000..52d46f3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include "morello_def.h" +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c b/arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c new file mode 100644 index 0000000..d941bfe --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c b/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c new file mode 100644 index 0000000..42e5171 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/morello_plat.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include "morello_def.h" + +/* + * Table of regions to map using the MMU. + * Replace or extend the below regions as required + */ +#if IMAGE_BL1 || IMAGE_BL31 +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_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + MORELLO_MAP_DEVICE, + MORELLO_MAP_NS_SRAM, + ARM_MAP_DRAM1, +#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/arm-trusted-firmware/plat/arm/board/morello/morello_security.c b/arm-trusted-firmware/plat/arm/board/morello/morello_security.c new file mode 100644 index 0000000..a388a80 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/morello/morello_topology.c b/arm-trusted-firmware/plat/arm/board/morello/morello_topology.c new file mode 100644 index 0000000..ef2f753 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c new file mode 100644 index 0000000..f9bc009 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/morello/platform.mk b/arm-trusted-firmware/plat/arm/board/morello/platform.mk new file mode 100644 index 0000000..86047e3 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/morello/platform.mk @@ -0,0 +1,108 @@ +# +# Copyright (c) 2020-2021, 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 + +# 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/arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S b/arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S new file mode 100644 index 0000000..3da55b6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S new file mode 100644 index 0000000..521bcc3 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h new file mode 100644 index 0000000..cc07852 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE 0x2A400000 +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ 50000000 + +#define PLAT_ARM_RUN_UART_BASE 0x2A410000 +#define PLAT_ARM_RUN_UART_CLK_IN_HZ 50000000 + +#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) + +/* 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 + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00080000 /* 512 KB */ +#define PLAT_ARM_MAX_BL31_SIZE 0X20000 + +/******************************************************************************* + * 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. + */ +#define PLAT_ARM_MMAP_ENTRIES 9 +#define MAX_XLAT_TABLES 10 + +#define PLATFORM_STACK_SIZE 0x400 + +#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 + +#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/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c new file mode 100644 index 0000000..d7003e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "n1sdp_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 + * - slave_count + * - Local DDR size in GB, DDR memory in master board + * - Remote DDR size in GB, DDR memory in slave board + */ +struct n1sdp_plat_info { + bool multichip_mode; + uint8_t slave_count; + uint8_t local_ddr_size; + uint8_t remote_ddr_size; +} __packed; + +/* + * BL33 image information structure stored in SDS. + * This structure holds the source & destination addresses and + * the size of the BL33 image which will be loaded by BL31. + */ +struct n1sdp_bl33_info { + uint32_t bl33_src_addr; + uint32_t bl33_dst_addr; + uint32_t bl33_size; +}; + +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. BL33 binary cannot be copied to DDR memory + * before enabling ECC so copy_bl33 function is added to copy BL33 binary + * from IOFPGA-DDR3 memory to main DDR4 memory. + */ + +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 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 copy_bl33(uint32_t src, uint32_t dst, uint32_t size) +{ + uint32_t i; + + INFO("Copying BL33 to DDR memory\n"); + for (i = 0; i < size; i = i + 8) + mmio_write_64((dst + i), mmio_read_64(src + i)); + + for (i = 0; i < size; i = i + 8) { + if (mmio_read_64(src + i) != mmio_read_64(dst + i)) { + ERROR("Copy failed!\n"); + panic(); + } + } +} + +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; + struct n1sdp_bl33_info bl33_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.slave_count > N1SDP_MAX_SLAVE_COUNT)) { + ERROR("platform info SDS is corrupted\n"); + panic(); + } + + if (plat_info.multichip_mode) { + n1sdp_multichip_data.chip_count = plat_info.slave_count + 1; + n1sdp_bl31_multichip_setup(); + } + arm_bl31_platform_setup(); + + dmc_ecc_setup(plat_info.local_ddr_size); + + /* 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); + + ret = sds_struct_read(N1SDP_SDS_BL33_INFO_STRUCT_ID, + N1SDP_SDS_BL33_INFO_OFFSET, + &bl33_info, + N1SDP_SDS_BL33_INFO_SIZE, + SDS_ACCESS_MODE_NON_CACHED); + if (ret != SDS_OK) { + ERROR("Error getting BL33 info from SDS\n"); + panic(); + } + copy_bl33(bl33_info.bl33_src_addr, + bl33_info.bl33_dst_addr, + bl33_info.bl33_size); + /* + * Pass platform information to BL33. This method is followed as + * currently there is no BL1/BL2 involved in boot flow of N1SDP. + * When TBBR is implemented for N1SDP, this method should be removed + * and platform information should be passed to BL33 using NT_FW_CONFIG + * passing mechanism. + */ + mmio_write_32(N1SDP_PLATFORM_INFO_BASE, *(uint32_t *)&plat_info); +} diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h new file mode 100644 index 0000000..30e29a7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. 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_SLAVE_COUNT 16 + +/* SDS BL33 image information defines */ +#define N1SDP_SDS_BL33_INFO_STRUCT_ID 9 +#define N1SDP_SDS_BL33_INFO_OFFSET 0 +#define N1SDP_SDS_BL33_INFO_SIZE 12 + +/* 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 + +/* Base address of non-secure SRAM where Platform information will be filled */ +#define N1SDP_PLATFORM_INFO_BASE 0x06008000 + +#endif /* N1SDP_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c new file mode 100644 index 0000000..908f41c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c new file mode 100644 index 0000000..951a562 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "n1sdp_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, + N1SDP_MAP_DEVICE, + N1SDP_MAP_NS_SRAM, + ARM_MAP_DRAM1, + ARM_MAP_DRAM2, + N1SDP_MAP_REMOTE_DEVICE, + N1SDP_MAP_REMOTE_DRAM1, + N1SDP_MAP_REMOTE_DRAM2, + {0} +}; + +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/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c new file mode 100644 index 0000000..d2a187b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c b/arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c new file mode 100644 index 0000000..5c2db71 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk b/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk new file mode 100644 index 0000000..f20397a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/n1sdp/platform.mk @@ -0,0 +1,76 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. 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 += drivers/arm/sbsa/sbsa.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 + +# TF-A not required to load the SCP Images +override CSS_LOAD_SCP_IMAGES := 0 + +# BL1/BL2 Image not a part of the capsule Image for n1sdp +override NEED_BL1 := no +override NEED_BL2 := no +override NEED_BL2U := no + +#TFA for n1sdp starts from BL31 +override RESET_TO_BL31 := 1 + +# 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/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts new file mode 100644 index 0000000..69fb0d4 --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts new file mode 100644 index 0000000..0af821e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts new file mode 100644 index 0000000..dba91e5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h new file mode 100644 index 0000000..a9b30a4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include +#include + +#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 + +/* + * 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 + +/* 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/arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk b/arm-trusted-firmware/plat/arm/board/rde1edge/platform.mk new file mode 100644 index 0000000..0f9dd49 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c new file mode 100644 index 0000000..c72c18c --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * rde1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c new file mode 100644 index 0000000..44d818a --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c new file mode 100644 index 0000000..35f81d1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c new file mode 100644 index 0000000..a16283e --- /dev/null +++ b/arm-trusted-firmware/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 + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts new file mode 100644 index 0000000..d3b7fba --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; + diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts new file mode 100644 index 0000000..68366c5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts new file mode 100644 index 0000000..257ef4a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h new file mode 100644 index 0000000..a61b0d5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h @@ -0,0 +1,49 @@ +/* + * 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 + +#include +#include + +#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) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#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 + +/* 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/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk b/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk new file mode 100644 index 0000000..22ab312 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn1edge/platform.mk @@ -0,0 +1,73 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# 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/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c new file mode 100644 index 0000000..46d318c --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * rdn1edge error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c new file mode 100644 index 0000000..1dbbf26 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c new file mode 100644 index 0000000..4943532 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c new file mode 100644 index 0000000..5bbea69 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts new file mode 100644 index 0000000..bbc36fc --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_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-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>; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h new file mode 100644 index 0000000..e4015f7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#include + +#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 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 << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42) +#endif +#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 + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk b/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk new file mode 100644 index 0000000..b882dc8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdn2/platform.mk @@ -0,0 +1,86 @@ +# Copyright (c) 2020-2021, 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 + +#Enable GIC Multichip Extension only for Multichip Platforms +ifeq (${CSS_SGI_PLATFORM_VARIANT}, 2) +GICV3_IMPL_GIC600_MULTICHIP := 1 +endif + +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_demeter.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/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c new file mode 100644 index 0000000..802ac21 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * rdn2 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c new file mode 100644 index 0000000..8cf1929 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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, 479}, + #if CSS_SGI_CHIP_COUNT > 1 + {0, 0}, + #endif + #if CSS_SGI_CHIP_COUNT > 2 + {0, 0}, + #endif + #if CSS_SGI_CHIP_COUNT > 3 + {0, 0}, + #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/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c new file mode 100644 index 0000000..dff6a19 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c new file mode 100644 index 0000000..89300f8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts new file mode 100644 index 0000000..62ba2c3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h new file mode 100644 index 0000000..5b98b4e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h @@ -0,0 +1,65 @@ +/* + * 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 + +#include + +#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)) + +/* + * Physical and virtual address space limits for MMU in AARCH64 & AARCH32 modes + */ +#ifdef __aarch64__ +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 42) +#define PLAT_VIRT_ADDR_SPACE_SIZE (1ULL << 42) +#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/arm-trusted-firmware/plat/arm/board/rdv1/platform.mk b/arm-trusted-firmware/plat/arm/board/rdv1/platform.mk new file mode 100644 index 0000000..11f5212 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c new file mode 100644 index 0000000..68f9a3e --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * rdv1 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (1) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c new file mode 100644 index 0000000..ab5251e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c new file mode 100644 index 0000000..1247db8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c new file mode 100644 index 0000000..ab64fd8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts new file mode 100644 index 0000000..9c9cefe --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts new file mode 100644 index 0000000..71c7db3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h new file mode 100644 index 0000000..12ce806 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2020-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#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) + +/* 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/arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk b/arm-trusted-firmware/plat/arm/board/rdv1mc/platform.mk new file mode 100644 index 0000000..df0b09a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c new file mode 100644 index 0000000..755a503 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * rdv1mc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c new file mode 100644 index 0000000..d859400 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c new file mode 100644 index 0000000..adc0bf8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c new file mode 100644 index 0000000..4486e5c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts new file mode 100644 index 0000000..84fc1ad --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + + nt_fw-config { + load-address = <0x0 0xFEF00000>; + max-size = <0x0100000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts new file mode 100644 index 0000000..260247a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h new file mode 100644 index 0000000..72d5f7c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h @@ -0,0 +1,46 @@ +/* + * 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 + +#include +#include + +#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 + +/* + * 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 + +/* 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/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk b/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk new file mode 100644 index 0000000..0761b77 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgi575/platform.mk @@ -0,0 +1,65 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +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/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c new file mode 100644 index 0000000..21bfcb7 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * sgi575 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c new file mode 100644 index 0000000..dc294e6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c new file mode 100644 index 0000000..17d07d1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c new file mode 100644 index 0000000..f7c3856 --- /dev/null +++ b/arm-trusted-firmware/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 + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts new file mode 100644 index 0000000..5d478e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x200>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts new file mode 100644 index 0000000..49eda27 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_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/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h new file mode 100644 index 0000000..e83cd57 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLAT_MAX_CPUS_PER_CLUSTER U(8) +#define PLAT_MAX_PE_PER_CPU U(1) + +#define PLAT_ARM_DRAM2_BASE ULL(0x880000000) +#define PLAT_ARM_DRAM2_SIZE ULL(0x180000000) + +/* + * 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_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk b/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk new file mode 100644 index 0000000..f8df1a7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/platform.mk @@ -0,0 +1,39 @@ +# +# 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/sgm/sgm-common.mk + +SGM775_BASE= plat/arm/board/sgm775 + +# Add the FDT_SOURCES and options for Dynamic Config +FDT_SOURCES += ${SGM775_BASE}/fdts/${PLAT}_fw_config.dts \ + ${SGM775_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})) + +PLAT_INCLUDES +=-I${SGM775_BASE}/include/ + +BL1_SOURCES += ${SGM775_BASE}/sgm775_err.c + +BL2_SOURCES += lib/utils/mem_region.c \ + ${SGM775_BASE}/sgm775_err.c \ + plat/arm/common/arm_nor_psci_mem_protect.c + +BL31_SOURCES += 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 += ${SGM775_BASE}/sgm775_trusted_boot.c +BL2_SOURCES += ${SGM775_BASE}/sgm775_trusted_boot.c +endif diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c new file mode 100644 index 0000000..dc114f0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2019-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * sgm775 error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c new file mode 100644 index 0000000..4592b8f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk b/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk new file mode 100644 index 0000000..129b586 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/sgm775/tsp/tsp-sgm775.mk @@ -0,0 +1,7 @@ +# +# Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include plat/arm/css/sgm/tsp/tsp-sgm.mk \ No newline at end of file diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts new file mode 100644 index 0000000..a84c7f8 --- /dev/null +++ b/arm-trusted-firmware/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 + +/dts-v1/; + +/ { + dtb-registry { + compatible = "fconf,dyn_cfg-dtb_registry"; + + tb_fw-config { + load-address = <0x0 0x4001300>; + max-size = <0x400>; + id = ; + }; + + tos_fw-config { + load-address = <0x0 0x04001700>; + max-size = <0x1000>; + id = ; + }; + + hw-config { + load-address = <0x0 0x83000000>; + max-size = <0x8000>; + id = ; + }; + }; +}; diff --git a/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts new file mode 100644 index 0000000..d3a5e1a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts new file mode 100644 index 0000000..92e2ddd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts new file mode 100644 index 0000000..4c6ccef --- /dev/null +++ b/arm-trusted-firmware/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 + +/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/arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S b/arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S new file mode 100644 index 0000000..6006fa5 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h b/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h new file mode 100644 index 0000000..745d91c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h @@ -0,0 +1,277 @@ +/* + * Copyright (c) 2020-2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 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 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. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x20000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0x14000 +#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 0x3F000 + +/* + * 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 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 + +#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_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) + +#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 + +/* + * 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/arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S b/arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S new file mode 100644 index 0000000..5f54856 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h b/arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h new file mode 100644 index 0000000..28c0308 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/board/tc/platform.mk b/arm-trusted-firmware/plat/arm/board/tc/platform.mk new file mode 100644 index 0000000..3acd88e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/board/tc/platform.mk @@ -0,0 +1,161 @@ +# Copyright (c) 2021, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +include common/fdt_wrappers.mk + +ifeq ($(filter ${TARGET_PLATFORM}, 0 1),) + $(error TARGET_PLATFORM must be 0 or 1) +endif + +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 := 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/ + +# Common CPU libraries +TC_CPU_SOURCES := lib/cpus/aarch64/cortex_a510.S + +# CPU libraries for TARGET_PLATFORM=0 +ifeq (${TARGET_PLATFORM}, 0) +TC_CPU_SOURCES += 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_makalu.S \ + lib/cpus/aarch64/cortex_makalu_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 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/arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c b/arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c new file mode 100644 index 0000000..74ef569 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include + +/******************************************************************************* + * 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 = ¶m_node->ep_info; + ep_info->args.arg1 = (uint32_t)fw_config_base; + + return arm_bl_params; +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c b/arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c new file mode 100644 index 0000000..0523ef8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/board/tc/tc_err.c b/arm-trusted-firmware/plat/arm/board/tc/tc_err.c new file mode 100644 index 0000000..9ed7e92 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * tc error handler + */ +void __dead2 plat_arm_error_handler(int err) +{ + while (true) { + wfi(); + } +} diff --git a/arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c b/arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c new file mode 100644 index 0000000..e2fc4e1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/board/tc/tc_plat.c b/arm-trusted-firmware/plat/arm/board/tc/tc_plat.c new file mode 100644 index 0000000..a9668e1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if SPM_MM +#include +#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 +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/arm-trusted-firmware/plat/arm/board/tc/tc_security.c b/arm-trusted-firmware/plat/arm/board/tc/tc_security.c new file mode 100644 index 0000000..6a34501 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/arm/board/tc/tc_topology.c b/arm-trusted-firmware/plat/arm/board/tc/tc_topology.c new file mode 100644 index 0000000..9e18da6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c b/arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c new file mode 100644 index 0000000..614f7e2 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c new file mode 100644 index 0000000..78360b0 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S b/arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S new file mode 100644 index 0000000..1da2d4c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c new file mode 100644 index 0000000..0666e57 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S b/arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S new file mode 100644 index 0000000..b470781 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c new file mode 100644 index 0000000..7cea8a0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c b/arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c new file mode 100644 index 0000000..3c74a46 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#if SDEI_IN_FCONF +#include +#endif +#include +#include + + +#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/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c b/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c new file mode 100644 index 0000000..bed929a --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c @@ -0,0 +1,180 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/* + * 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(NON_SECURE); + + /* + * 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/arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c b/arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c new file mode 100644 index 0000000..ce2c356 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c new file mode 100644 index 0000000..73338cb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c @@ -0,0 +1,257 @@ +/* + * Copyright (c) 2015-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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, 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/arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c new file mode 100644 index 0000000..97b5a88 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c new file mode 100644 index 0000000..08c014d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if ENABLE_RME +#include +#endif /* ENABLE_RME */ +#ifdef SPD_opteed +#include +#endif +#include +#if ENABLE_RME +#include +#endif /* ENABLE_RME */ +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c new file mode 100644 index 0000000..3614c7d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c b/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c new file mode 100644 index 0000000..a6f7df5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c @@ -0,0 +1,427 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#if ENABLE_RME +#include +#endif +#include +#include +#include +#include +#include + +/* + * 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); + +#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/arm-trusted-firmware/plat/arm/common/arm_cci.c b/arm-trusted-firmware/plat/arm/common/arm_cci.c new file mode 100644 index 0000000..3795fc5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/common/arm_ccn.c b/arm-trusted-firmware/plat/arm/common/arm_ccn.c new file mode 100644 index 0000000..2e681ca --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/common/arm_common.c b/arm-trusted-firmware/plat/arm/common/arm_common.c new file mode 100644 index 0000000..946b732 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_common.c @@ -0,0 +1,239 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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 + diff --git a/arm-trusted-firmware/plat/arm/common/arm_common.mk b/arm-trusted-firmware/plat/arm/common/arm_common.mk new file mode 100644 index 0000000..6d7aa2d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_common.mk @@ -0,0 +1,429 @@ +# +# 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)) + +# 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 Ethos-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_MINOR},0) + BL2_CPPFLAGS += -march=armv8-a+crc +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 + +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 + $(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. +ifeq (${MEASURED_BOOT},1) + MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk + $(info Including ${MEASURED_BOOT_MK}) + include ${MEASURED_BOOT_MK} + + BL1_SOURCES += ${EVENT_LOG_SOURCES} + BL2_SOURCES += ${EVENT_LOG_SOURCES} +endif + +ifneq ($(filter 1,${MEASURED_BOOT} ${TRUSTED_BOARD_BOOT}),) + CRYPTO_SOURCES := drivers/auth/crypto_mod.c \ + lib/fconf/fconf_tbbr_getter.c + BL1_SOURCES += ${CRYPTO_SOURCES} + BL2_SOURCES += ${CRYPTO_SOURCES} + + # 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/arm-trusted-firmware/plat/arm/common/arm_console.c b/arm-trusted-firmware/plat/arm/common/arm_console.c new file mode 100644 index 0000000..51830c9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c new file mode 100644 index 0000000..7abd1cd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c @@ -0,0 +1,205 @@ +/* + * Copyright (c) 2018-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#if CRYPTO_SUPPORT +#include +#endif /* CRYPTO_SUPPORT */ +#include +#include +#include + +#include +#include + +#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 + + /* 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; + 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 from TB_FW_CONFIG */ + cfg_mem_params = get_bl_mem_params_node(config_ids[i]); + if (cfg_mem_params == NULL) { + VERBOSE("%sHW_CONFIG in bl_mem_params_node\n", + "Couldn't find "); + continue; + } + + dtb_info = FCONF_GET_PROPERTY(dyn_cfg, dtb, config_ids[i]); + if (dtb_info == NULL) { + VERBOSE("%sconfig_id %d load info in TB_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)) { + continue; + } +#ifdef BL31_BASE + /* Ensure the configs don't overlap with BL31 */ + if ((image_base >= BL31_BASE) && + (image_base <= BL31_LIMIT)) { + continue; + } +#endif + /* Ensure the configs are loaded in a valid address */ + if (image_base < ARM_BL_RAM_BASE) { + 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)) { + 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; + } +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c new file mode 100644 index 0000000..6a2a6f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c @@ -0,0 +1,368 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#if MEASURED_BOOT +#include +#endif +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/arm_err.c b/arm-trusted-firmware/plat/arm/common/arm_err.c new file mode 100644 index 0000000..f80ba78 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_err.c @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +void __dead2 plat_error_handler(int err) +{ + plat_arm_error_handler(err); +} diff --git a/arm-trusted-firmware/plat/arm/common/arm_gicv2.c b/arm-trusted-firmware/plat/arm/common/arm_gicv2.c new file mode 100644 index 0000000..80a845f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/common/arm_gicv3.c b/arm-trusted-firmware/plat/arm/common/arm_gicv3.c new file mode 100644 index 0000000..4a3a22e --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/arm_gicv3.c @@ -0,0 +1,246 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/arm/common/arm_image_load.c b/arm-trusted-firmware/plat/arm/common/arm_image_load.c new file mode 100644 index 0000000..c411c6c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#if defined(SPD_spmd) +#include +#endif +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/arm_io_storage.c b/arm-trusted-firmware/plat/arm/common/arm_io_storage.c new file mode 100644 index 0000000..19ee1b0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c b/arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c new file mode 100644 index 0000000..1fa234d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/common/arm_pm.c b/arm-trusted-firmware/plat/arm/common/arm_pm.c new file mode 100644 index 0000000..5434c94 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_sip_svc.c b/arm-trusted-firmware/plat/arm/common/arm_sip_svc.c new file mode 100644 index 0000000..6456c78 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_topology.c b/arm-trusted-firmware/plat/arm/common/arm_topology.c new file mode 100644 index 0000000..c9993a7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/common/arm_tzc400.c b/arm-trusted-firmware/plat/arm/common/arm_tzc400.c new file mode 100644 index 0000000..370ef0a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c b/arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c new file mode 100644 index 0000000..e9f897f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c new file mode 100644 index 0000000..aea2f38 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2019-2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + [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 + [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(21) +#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 + {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/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c b/arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c new file mode 100644 index 0000000..18c83c7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c new file mode 100644 index 0000000..0af1a20 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +struct ethosn_config_t ethosn_config = {.num_cores = 0}; + +static uint8_t fdt_node_get_status(const void *fdt, int node) +{ + int len; + uint8_t status = ETHOSN_STATUS_DISABLED; + 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)) { + status = ETHOSN_STATUS_ENABLED; + } + + return status; +} + +int fconf_populate_ethosn_config(uintptr_t config) +{ + int ethosn_node; + const void *hw_conf_dtb = (const void *)config; + + /* Find offset to node with 'ethosn' compatible property */ + INFO("Probing Arm Ethos-N NPU\n"); + uint32_t total_core_count = 0U; + + fdt_for_each_compatible_node(hw_conf_dtb, ethosn_node, "ethosn") { + int sub_node; + uint8_t ethosn_status; + uint32_t device_core_count = 0U; + + /* If the Arm Ethos-N NPU is disabled the core check can be skipped */ + ethosn_status = fdt_node_get_status(hw_conf_dtb, ethosn_node); + if (ethosn_status == ETHOSN_STATUS_DISABLED) { + continue; + } + + fdt_for_each_subnode(sub_node, hw_conf_dtb, ethosn_node) { + int err; + uintptr_t core_addr; + uint8_t core_status; + + if (total_core_count >= ETHOSN_CORE_NUM_MAX) { + ERROR("FCONF: Reached max number of Arm Ethos-N NPU cores\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + /* Check that the sub node is "ethosn-core" compatible */ + if (fdt_node_check_compatible(hw_conf_dtb, + sub_node, + "ethosn-core") != 0) { + /* Ignore incompatible sub node */ + continue; + } + + core_status = fdt_node_get_status(hw_conf_dtb, sub_node); + if (core_status == ETHOSN_STATUS_DISABLED) { + continue; + } + + err = fdt_get_reg_props_by_index(hw_conf_dtb, + ethosn_node, + device_core_count, + &core_addr, + NULL); + if (err < 0) { + ERROR( + "FCONF: Failed to read reg property for Arm Ethos-N NPU core %u\n", + device_core_count); + return err; + } + + INFO("NPU core probed at address 0x%lx\n", core_addr); + ethosn_config.core[total_core_count].addr = core_addr; + total_core_count++; + device_core_count++; + } + + if ((sub_node < 0) && (sub_node != -FDT_ERR_NOTFOUND)) { + ERROR("FCONF: Failed to parse sub nodes\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + if (device_core_count == 0U) { + ERROR( + "FCONF: Enabled Arm Ethos-N NPU device must have at least one enabled core\n"); + return -FDT_ERR_BADSTRUCTURE; + } + } + + if (total_core_count == 0U) { + ERROR("FCONF: Can't find 'ethosn' compatible node in dtb\n"); + return -FDT_ERR_BADSTRUCTURE; + } + + ethosn_config.num_cores = total_core_count; + + INFO("%d NPU core%s probed\n", + ethosn_config.num_cores, + ethosn_config.num_cores > 1 ? "s" : ""); + + return 0; +} + +FCONF_REGISTER_POPULATOR(HW_CONFIG, ethosn_config, fconf_populate_ethosn_config); diff --git a/arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c new file mode 100644 index 0000000..8d645ef --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +#include + +/******************************************************************************* + * 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, ®, 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/arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c new file mode 100644 index 0000000..c26e316 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c b/arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c new file mode 100644 index 0000000..f28be24 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min.mk new file mode 100644 index 0000000..dbd451c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c b/arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c new file mode 100644 index 0000000..f15c137 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk b/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk new file mode 100644 index 0000000..997111f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/trp/arm_trp.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2021, 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 diff --git a/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c b/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c new file mode 100644 index 0000000..8e48293 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Initialize the UART + ******************************************************************************/ +static console_t arm_trp_runtime_console; + +void arm_trp_early_platform_setup(void) +{ + /* + * Initialize a different console than already in use to display + * messages from trp + */ + int 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(void) +{ + arm_trp_early_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp.mk new file mode 100644 index 0000000..4ad77c6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c b/arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c new file mode 100644 index 0000000..a4da8c3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S b/arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S new file mode 100644 index 0000000..d47e13d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S b/arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S new file mode 100644 index 0000000..01669be --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c new file mode 100644 index 0000000..596cc3d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c new file mode 100644 index 0000000..002c6eb --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c b/arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c new file mode 100644 index 0000000..15cf4f6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/css/common/css_common.mk b/arm-trusted-firmware/plat/arm/css/common/css_common.mk new file mode 100644 index 0000000..2fbbe45 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_common.mk @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015-2018, 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/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)) + diff --git a/arm-trusted-firmware/plat/arm/css/common/css_pm.c b/arm-trusted-firmware/plat/arm/css/common/css_pm.c new file mode 100644 index 0000000..926b8ec --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/css_pm.c @@ -0,0 +1,362 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* 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(); +} + +/******************************************************************************* + * 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); +} + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/arm/css/common/css_topology.c b/arm-trusted-firmware/plat/arm/css/common/css_topology.c new file mode 100644 index 0000000..8aca744 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk b/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk new file mode 100644 index 0000000..6523a16 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/common/sp_min/css_sp_min.mk @@ -0,0 +1,21 @@ +# +# 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/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/arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S b/arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S new file mode 100644 index 0000000..ced59e8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S b/arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S new file mode 100644 index 0000000..521bcc3 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h new file mode 100644 index 0000000..c9c8c04 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h @@ -0,0 +1,261 @@ +/* + * Copyright (c) 2018-2021, 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 +#include +#include +#include +#include +#include + +#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 0x00040000 /* 256 KB */ + +/* Remote chip address offset (4TB per chip) */ +#define CSS_SGI_REMOTE_CHIP_MEM_OFFSET(n) ((ULL(1) << 42) * (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 9 +# define PLAT_SP_IMAGE_MAX_XLAT_TABLES 11 +# 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 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 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 + */ +#define PLAT_ARM_MAX_BL31_SIZE 0x3B000 + +/* + * 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_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} + +#endif /* SGI_BASE_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h new file mode 100644 index 0000000..e939163 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h new file mode 100644 index 0000000..a5fbded --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h new file mode 100644 index 0000000..e69a684 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h new file mode 100644 index 0000000..f380122 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h new file mode 100644 index 0000000..639b687 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021, 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 +#include + +/* + * 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) + +/* PL011 UART related constants */ +#define SOC_CSS_UART1_BASE UL(0x0ef80000) +#define SOC_CSS_UART0_BASE UL(0x0ef70000) + +/* Memory controller */ +#define SOC_MEMCNTRL_BASE UL(0x10000000) +#define SOC_MEMCNTRL_SIZE UL(0x10000000) + +#define SOC_CSS_UART0_CLK_IN_HZ UL(7372800) +#define SOC_CSS_UART1_CLK_IN_HZ UL(7372800) + +/* 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 + +#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) + +/* UART related constants */ +#define PLAT_ARM_BOOT_UART_BASE SOC_CSS_UART0_BASE +#define PLAT_ARM_BOOT_UART_CLK_IN_HZ SOC_CSS_UART0_CLK_IN_HZ + +#define PLAT_ARM_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_RUN_UART_CLK_IN_HZ SOC_CSS_UART1_CLK_IN_HZ + +#define PLAT_ARM_SP_MIN_RUN_UART_BASE SOC_CSS_UART1_BASE +#define PLAT_ARM_SP_MIN_RUN_UART_CLK_IN_HZ SOC_CSS_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 + +#endif /* SGI_SOC_CSS_DEF_V2_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h new file mode 100644 index 0000000..405d62f --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2020-2021, 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 +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h new file mode 100644 index 0000000..20dd682 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h new file mode 100644 index 0000000..41467f7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2018-2020, 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-Edmunds */ +#define RD_EDMUNDS_SID_VER_PART_NUM 0x07F2 +#define RD_EDMUNDS_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/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk b/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk new file mode 100644 index 0000000..f56fe35 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi-common.mk @@ -0,0 +1,84 @@ +# +# Copyright (c) 2018-2021, 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 := 0 + +CSS_SGI_CHIP_COUNT := 1 + +CSS_SGI_PLATFORM_VARIANT := 0 + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +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 + +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_BL31_IN_DRAM := 1 +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/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c new file mode 100644 index 0000000..99f2f20 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +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_EDMUNDS_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 +} + +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/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c new file mode 100644 index 0000000..09f3b72 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * This function inserts Platform information via device tree nodes as, + * system-id { + * platform-id = <0>; + * config-id = <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; + + 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; + } + + 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/arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c new file mode 100644 index 0000000..e9cd812 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c new file mode 100644 index 0000000..20c52e9 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2018-2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if SPM_MM +#include +#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, + 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/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c new file mode 100644 index 0000000..1a2a966 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c @@ -0,0 +1,174 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#if SPM_MM +#include +#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_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/arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c new file mode 100644 index 0000000..4f03ac4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c b/arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c new file mode 100644 index 0000000..1c3b5bf --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S b/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S new file mode 100644 index 0000000..32ca1bb --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + + .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 FVP. + * + * (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 + /* + * 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 + lsr 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 + jump_if_cpu_midr CORTEX_A75_MIDR, A75 + jump_if_cpu_midr CORTEX_A55_MIDR, A55 + 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 +A55: + mrs x0, CORTEX_A55_CPUPWRCTLR_EL1 + bic x0, x0, #CORTEX_A55_CORE_PWRDN_EN_MASK + msr CORTEX_A55_CPUPWRCTLR_EL1, x0 + isb + ret +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts b/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts new file mode 100644 index 0000000..54b2423 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_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/; + +/ { + /* Platform Config */ + tb_fw-config { + compatible = "arm,tb_fw"; + hw_config_addr = <0x0 0x83000000>; + hw_config_max_size = <0x01000000>; + /* + * 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/arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S b/arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S new file mode 100644 index 0000000..715ded2 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/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 +#include + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h new file mode 100644 index 0000000..2d8e677 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h @@ -0,0 +1,242 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_BASE_PLATFORM_DEF_H +#define SGM_BASE_PLATFORM_DEF_H + +#include +#include +#include +#include +#include +#include +#include +#include + +/* CPU topology */ +#define PLAT_ARM_CLUSTER_COUNT U(1) +#define PLAT_ARM_CLUSTER_CORE_COUNT U(8) +#define PLATFORM_CORE_COUNT PLAT_ARM_CLUSTER_CORE_COUNT + +#define PLAT_MAX_PWR_LVL ARM_PWR_LVL2 +#define PLAT_NUM_PWR_DOMAINS (ARM_SYSTEM_COUNT + \ + PLAT_ARM_CLUSTER_COUNT + \ + PLATFORM_CORE_COUNT) + +/* + * 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) \ + CSS_G1S_IRQ_PROPS(grp), \ + ARM_G1S_IRQ_PROPS(grp) + +#define PLAT_ARM_G0_IRQ_PROPS(grp) ARM_G0_IRQ_PROPS(grp) + +/* GIC related constants */ +#define PLAT_ARM_GICD_BASE 0x30000000 +#define PLAT_ARM_GICR_BASE 0x300C0000 +#define PLAT_ARM_GICC_BASE 0x2c000000 + +#define CSS_GIC_SIZE 0x00200000 + +#define CSS_MAP_GIC_DEVICE MAP_REGION_FLAT( \ + PLAT_ARM_GICD_BASE, \ + CSS_GIC_SIZE, \ + MT_DEVICE | MT_RW | MT_SECURE) + +/* 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_PLAT_PART_NUM \ + GET_SSC_VERSION_PART_NUM(mmio_read_32(SSC_VERSION)) +/* Returns the configuration number of the platform */ +#define GET_PLAT_CONFIG_NUM \ + GET_SSC_VERSION_CONFIG(mmio_read_32(SSC_VERSION)) +#endif /* __ASSEMBLER__ */ + + +/************************************************************************* + * Definitions common to all SGM CSS based platforms + *************************************************************************/ + +/* TZC-400 related constants */ +#define PLAT_ARM_TZC_BASE 0x2a500000 +#define TZC_NSAID_ALL_AP 0 /* Note: Same as default NSAID!! */ +#define TZC_NSAID_HDLCD0 2 +#define TZC_NSAID_HDLCD1 3 +#define TZC_NSAID_GPU 9 +#define TZC_NSAID_VIDEO 10 +#define TZC_NSAID_DISP0 11 +#define TZC_NSAID_DISP1 12 + + +/************************************************************************* + * Required platform porting definitions common to all SGM CSS based + * platforms + *************************************************************************/ + +#define PLAT_ARM_TRUSTED_SRAM_SIZE 0x00040000 /* 256 KB */ + +/* MHU related constants */ +#define PLAT_CSS_MHU_BASE 0x2b1f0000 + +#define PLAT_ARM_TRUSTED_ROM_BASE 0x00000000 +#define PLAT_ARM_TRUSTED_ROM_SIZE 0x00080000 + +#define PLAT_ARM_CCI_BASE 0x2a000000 + +/* Cluster to CCI slave mapping */ +#define PLAT_ARM_CCI_CLUSTER0_SL_IFACE_IX 6 +#define PLAT_ARM_CCI_CLUSTER1_SL_IFACE_IX 5 + +/* System timer related constants */ +#define PLAT_ARM_NSTIMER_FRAME_ID 0 + +/* TZC related constants */ +#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_HDLCD1) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_GPU) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_VIDEO) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_DISP0) | \ + TZC_REGION_ACCESS_RDWR(TZC_NSAID_DISP1)) + +/* Display Processor register definitions to setup the NSAIDs */ +#define MALI_DP_BASE 0x2cc00000 +#define DP_NPROT_NSAID_OFFSET 0x1000c +#define W_NPROT_NSAID_SHIFT 24 +#define LS_NPORT_NSAID_SHIFT 12 + +/* + * Base address of the first memory region used for communication between AP + * and SCP. Used by the BootOverMHU 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. 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 + 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 + +/* + * Most platform porting definitions provided by included headers + */ + +/* + * 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) +# define PLAT_ARM_MMAP_ENTRIES 8 +# define MAX_XLAT_TABLES 5 +#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 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 0xB000 + +/* + * 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. + */ +#if TRUSTED_BOARD_BOOT +# define PLAT_ARM_MAX_BL2_SIZE 0x1D000 +#else +# define PLAT_ARM_MAX_BL2_SIZE 0x12000 +#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 0x3B000 + +/* + * 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) +# define PLATFORM_STACK_SIZE 0x400 +#elif defined(IMAGE_BL32) +# define PLATFORM_STACK_SIZE 0x440 +#endif + +/******************************************************************************* + * 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) + +/* System power domain level */ +#define CSS_SYSTEM_PWR_DMN_LVL ARM_PWR_LVL2 + +/* Number of SCMI channels on the platform */ +#define PLAT_ARM_SCMI_CHANNEL_COUNT U(1) + +#endif /* SGM_BASE_PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h new file mode 100644 index 0000000..29b98d4 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_PLAT_CONFIG_H +#define SGM_PLAT_CONFIG_H + +#include +#include + +/* The type of interconnect */ +typedef enum { + ARM_CCI = 0, + ARM_CCN, + ARM_CMN +} css_inteconn_type_t; + +typedef ccn_desc_t inteconn_desc_t; + +/* Interconnect configurations */ +typedef struct css_inteconn_config { + css_inteconn_type_t ip_type; + const inteconn_desc_t *plat_inteconn_desc; +} css_inteconn_config_t; + +/* Topology configurations */ +typedef struct css_topology { + const unsigned char *power_tree; + unsigned int plat_cluster_core_count; +} css_topology_t; + +typedef struct css_plat_config { + const gicv3_driver_data_t *gic_data; + const css_inteconn_config_t *inteconn; + const css_topology_t *topology; +} css_plat_config_t; + +void plat_config_init(void); +css_plat_config_t *get_plat_config(void); + +#endif /* SGM_PLAT_CONFIG_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h new file mode 100644 index 0000000..859ddb5 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SGM_VARIANT_H +#define SGM_VARIANT_H + +/* SSC_VERSION values for sgm */ +#define SGM775_SSC_VER_PART_NUM 0x0790 + +/* DMC configuration for sgm */ +#define SGM_DMC_SIZE 0x40000 +#define SGM775_DMC_COUNT 4 + +#endif /* SGM_VARIANT_H */ diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk b/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk new file mode 100644 index 0000000..5b954f8 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm-common.mk @@ -0,0 +1,76 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CSS_USE_SCMI_SDS_DRIVER := 1 + +CSS_SGM_BASE := plat/arm/css/sgm + +PLAT_INCLUDES := -I${CSS_SGM_BASE}/include + +PLAT_BL_COMMON_SOURCES := ${CSS_SGM_BASE}/sgm_mmap_config.c \ + ${CSS_SGM_BASE}/aarch64/css_sgm_helpers.S + +SECURITY_SOURCES := drivers/arm/tzc/tzc_dmc500.c \ + plat/arm/common/arm_tzc_dmc500.c \ + ${CSS_SGM_BASE}/sgm_security.c + +SGM_CPU_SOURCES := lib/cpus/aarch64/cortex_a55.S \ + lib/cpus/aarch64/cortex_a75.S + +INTERCONNECT_SOURCES := ${CSS_SGM_BASE}/sgm_interconnect.c + +# GIC-600 configuration +GICV3_SUPPORT_GIC600 := 1 + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +SGM_GIC_SOURCES := ${GICV3_SOURCES} \ + plat/common/plat_gicv3.c \ + plat/arm/common/arm_gicv3.c + +BL1_SOURCES += $(SGM_CPU_SOURCES) \ + ${INTERCONNECT_SOURCES} \ + ${CSS_SGM_BASE}/sgm_bl1_setup.c \ + ${CSS_SGM_BASE}/sgm_plat_config.c \ + drivers/arm/sp805/sp805.c + +BL2_SOURCES += ${SECURITY_SOURCES} \ + ${CSS_SGM_BASE}/sgm_plat_config.c + +BL2U_SOURCES += ${SECURITY_SOURCES} + +BL31_SOURCES += $(SGM_CPU_SOURCES) \ + ${INTERCONNECT_SOURCES} \ + ${SECURITY_SOURCES} \ + ${SGM_GIC_SOURCES} \ + ${CSS_SGM_BASE}/sgm_topology.c \ + ${CSS_SGM_BASE}/sgm_bl31_setup.c \ + ${CSS_SGM_BASE}/sgm_plat_config.c + +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 + +# sgm uses CCI-500 as Cache Coherent Interconnect +ARM_CCI_PRODUCT_ID := 500 + +# 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 + +override ARM_PLAT_MT := 1 + +$(eval $(call add_define,SGM_PLAT)) + +include plat/arm/common/arm_common.mk +include plat/arm/board/common/board_common.mk +include plat/arm/css/common/css_common.mk +include plat/arm/soc/common/soc_css.mk diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c new file mode 100644 index 0000000..5fd9655 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +void bl1_early_platform_setup(void) +{ + + /* Initialize the console before anything else */ + arm_bl1_early_platform_setup(); + + /* Initialize the platform configuration structure */ + plat_config_init(); + +#if !HW_ASSISTED_COHERENCY + /* + * 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(); +#endif +} + +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/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c new file mode 100644 index 0000000..907e9fd --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include + +static scmi_channel_plat_info_t sgm775_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 &sgm775_scmi_plat_info; +} + +void bl31_early_platform_setup2(u_register_t arg0, u_register_t arg1, + u_register_t arg2, u_register_t arg3) +{ + uint32_t plat_version; + bl_params_node_t *bl_params; + + bl_params = ((bl_params_t *)arg0)->head; + + /* Initialize the platform configuration structure */ + plat_config_init(); + + while (bl_params) { + if (bl_params->image_id == BL33_IMAGE_ID) { + plat_version = mmio_read_32(SSC_VERSION); + bl_params->ep_info->args.arg2 = plat_version; + break; + } + + bl_params = bl_params->next_params_info; + } + + arm_bl31_early_platform_setup((void *)arg0, arg1, arg2, (void *)arg3); +} + +const plat_psci_ops_t *plat_arm_psci_override_pm_ops(plat_psci_ops_t *ops) +{ + return css_scmi_override_pm_ops(ops); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c new file mode 100644 index 0000000..5b45341 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +/* + * As the SGM platform 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 __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/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c new file mode 100644 index 0000000..e5b4b03 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include + +/* + * 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, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, +#if TRUSTED_BOARD_BOOT + ARM_MAP_NS_DRAM1, +#endif + {0} +}; +#endif +#if IMAGE_BL2 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_FLASH0_RO, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + ARM_MAP_NS_DRAM1, +#ifdef SPD_tspd + ARM_MAP_TSP_SEC_MEM, +#endif +#ifdef SPD_opteed + ARM_OPTEE_PAGEABLE_LOAD_MEM, +#endif +#if TRUSTED_BOARD_BOOT && !BL2_AT_EL3 + ARM_MAP_BL1_RW, +#endif + {0} +}; +#endif +#if IMAGE_BL2U +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL31 +const mmap_region_t plat_arm_mmap[] = { + ARM_MAP_SHARED_RAM, + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif +#if IMAGE_BL32 +const mmap_region_t plat_arm_mmap[] = { + V2M_MAP_IOFPGA, + CSS_MAP_DEVICE, + CSS_MAP_GIC_DEVICE, + SOC_CSS_MAP_DEVICE, + {0} +}; +#endif + +ARM_CASSERT_MMAP + +const mmap_region_t *plat_arm_get_mmap(void) +{ + return plat_arm_mmap; +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c new file mode 100644 index 0000000..eed3631 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include + +#include +#include + +static css_plat_config_t *css_plat_info; + +/* Interconnect */ +const css_inteconn_config_t sgm_inteconn = { + .ip_type = ARM_CCI, + .plat_inteconn_desc = NULL +}; + +/* Special definition for SGM775 */ +/* Topology configuration for SGM775 */ +const unsigned char sgm775_power_domain_tree_desc[] = { + /* No of root nodes */ + ARM_SYSTEM_COUNT, + /* No of children for the root node */ + PLAT_ARM_CLUSTER_COUNT, + /* No of children for the first cluster node */ + PLAT_ARM_CLUSTER_CORE_COUNT, +}; + +const css_topology_t sgm775_topology = { + .power_tree = sgm775_power_domain_tree_desc, + .plat_cluster_core_count = PLAT_ARM_CLUSTER_CORE_COUNT +}; + +/* Configuration structure for SGM775 */ +css_plat_config_t sgm775_config = { + .inteconn = &sgm_inteconn, + .topology = &sgm775_topology +}; + +/******************************************************************************* + * This function initializes the platform structure. + ******************************************************************************/ +void plat_config_init(void) +{ + /* Get the platform configurations */ + switch (GET_PLAT_PART_NUM) { + case SGM775_SSC_VER_PART_NUM: + css_plat_info = &sgm775_config; + + break; + default: + ERROR("Not a valid sgm variant!\n"); + panic(); + } +} + +/******************************************************************************* + * This function returns the platform structure pointer. + ******************************************************************************/ +css_plat_config_t *get_plat_config(void) +{ + assert(css_plat_info != NULL); + return css_plat_info; +} + +#if 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/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c new file mode 100644 index 0000000..21d5306 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +/* Is populated with the DMC-500 controllers base addresses */ +static tzc_dmc500_driver_data_t plat_driver_data; + +void plat_sgm_dp_security_setup(void) +{ + unsigned int nprot_nsaid; + + /* + * At reset the Mali display processors start with NSAIDs set to zero + * so the firmware must set them up to the expected values for ARM sgm + * platforms. + */ + + nprot_nsaid = mmio_read_32(MALI_DP_BASE + DP_NPROT_NSAID_OFFSET); + nprot_nsaid &= ~((0xF << W_NPROT_NSAID_SHIFT) | + (0xF << LS_NPORT_NSAID_SHIFT)); + nprot_nsaid |= ((TZC_NSAID_DISP1 << W_NPROT_NSAID_SHIFT) | + (TZC_NSAID_DISP0 << LS_NPORT_NSAID_SHIFT)); + mmio_write_32(MALI_DP_BASE + DP_NPROT_NSAID_OFFSET, nprot_nsaid); +} + +void plat_arm_security_setup(void) +{ + unsigned int i; + unsigned int part_num = GET_PLAT_PART_NUM; + + INFO("part_num: 0x%x\n", part_num); + + /* + * Initialise plat_driver_data with platform specific DMC_BASE + * addresses + */ + switch (part_num) { + case SGM775_SSC_VER_PART_NUM: + for (i = 0; i < SGM775_DMC_COUNT; i++) + plat_driver_data.dmc_base[i] = PLAT_ARM_TZC_BASE + + SGM_DMC_SIZE * i; + plat_driver_data.dmc_count = SGM775_DMC_COUNT; + break; + default: + /* Unexpected platform */ + ERROR("Unexpected platform\n"); + panic(); + } + /* Initialize the TrustZone Controller in DMC-500 */ + arm_tzc_dmc500_setup(&plat_driver_data, NULL); + + /* Do DP NSAID setup */ + plat_sgm_dp_security_setup(); + /* Do ARM CSS SoC security setup */ + soc_css_security_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c b/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c new file mode 100644 index 0000000..2d9552d --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/******************************************************************************* + * This function returns the topology tree information. + ******************************************************************************/ +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return get_plat_config()->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 get_plat_config()->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/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c b/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c new file mode 100644 index 0000000..5f40c4c --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +void tsp_early_platform_setup(void) +{ + /* Initialize the platform configuration structure */ + plat_config_init(); + + arm_tsp_early_platform_setup(); +} diff --git a/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk b/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk new file mode 100644 index 0000000..de5e5b7 --- /dev/null +++ b/arm-trusted-firmware/plat/arm/css/sgm/tsp/tsp-sgm.mk @@ -0,0 +1,11 @@ +# +# Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +BL32_SOURCES += ${SGM_GIC_SOURCES} \ + ${CSS_SGM_BASE}/sgm_plat_config.c \ + plat/arm/css/sgm/tsp/sgm_tsp_setup.c + +include plat/arm/common/tsp/arm_tsp.mk diff --git a/arm-trusted-firmware/plat/arm/soc/common/soc_css.mk b/arm-trusted-firmware/plat/arm/soc/common/soc_css.mk new file mode 100644 index 0000000..8cad2a5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c b/arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c new file mode 100644 index 0000000..4f6bf61 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/common/bcm_console.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_console.c new file mode 100644 index 0000000..5f20094 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c new file mode 100644 index 0000000..093157e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c @@ -0,0 +1,268 @@ +/* + * Copyright (c) 2018 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c new file mode 100644 index 0000000..89e7bff --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c @@ -0,0 +1,133 @@ +/* + * Copyright 2019-2020 Broadcom. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h b/arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h new file mode 100644 index 0000000..6f21a68 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c b/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c new file mode 100644 index 0000000..da18c31 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c @@ -0,0 +1,625 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/brcm/board/common/board_common.c b/arm-trusted-firmware/plat/brcm/board/common/board_common.c new file mode 100644 index 0000000..2f764ab --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/board_common.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/board_common.mk b/arm-trusted-firmware/plat/brcm/board/common/board_common.mk new file mode 100644 index 0000000..24a27ed --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c b/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c new file mode 100644 index 0000000..af42b86 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c @@ -0,0 +1,12 @@ +/* + * Copyright 2015 - 2020 Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +void tls_exit(int code) +{ + INFO("%s: 0x%x\n", __func__, code); +} diff --git a/arm-trusted-firmware/plat/brcm/board/common/chip_id.h b/arm-trusted-firmware/plat/brcm/board/common/chip_id.h new file mode 100644 index 0000000..842ac1f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h new file mode 100644 index 0000000..8aa7fd4 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMN_PLAT_DEF_H +#define CMN_PLAT_DEF_H + +#include + +#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) + +/* Print file and line number on assert */ +#define PLAT_LOG_LEVEL_ASSERT LOG_LEVEL_INFO + +/* + * 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/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h new file mode 100644 index 0000000..178c843 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c new file mode 100644 index 0000000..c80d5dd --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h b/arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h new file mode 100644 index 0000000..f74863d --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/brcm/board/common/err.c b/arm-trusted-firmware/plat/brcm/board/common/err.c new file mode 100644 index 0000000..1fc73c4 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/err.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c b/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c new file mode 100644 index 0000000..95e12ed --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/plat_setup.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/brcm/board/common/platform_common.c b/arm-trusted-firmware/plat/brcm/board/common/platform_common.c new file mode 100644 index 0000000..f4c9a73 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/platform_common.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c new file mode 100644 index 0000000..06e5b33 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/common/sbl_util.h b/arm-trusted-firmware/plat/brcm/board/common/sbl_util.h new file mode 100644 index 0000000..0747389 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#define SBL_DISABLED 0 +#define SBL_ENABLED 1 + +int sbl_status(void); + +#endif /* #ifdef SBL_UTIL_H */ diff --git a/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c b/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c new file mode 100644 index 0000000..7e33a94 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/common/timer_sync.c @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S new file mode 100644 index 0000000..9a2039d --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2015-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include + + .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/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t-ns3.mk new file mode 100644 index 0000000..5164eeb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk b/arm-trusted-firmware/plat/brcm/board/stingray/bcm958742t.mk new file mode 100644 index 0000000..5e164b8 --- /dev/null +++ b/arm-trusted-firmware/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 := "" +$(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/arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h new file mode 100644 index 0000000..b2427cf --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c new file mode 100644 index 0000000..74d2077 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h new file mode 100644 index 0000000..8508653 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c new file mode 100644 index 0000000..1184928 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +#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< + +#include + +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h b/arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h new file mode 100644 index 0000000..5033683 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c new file mode 100644 index 0000000..2b7c53b --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c @@ -0,0 +1,375 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c new file mode 100644 index 0000000..4a84141 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c @@ -0,0 +1,296 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include "sr_usb.h" +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c new file mode 100644 index 0000000..54c98e1 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c @@ -0,0 +1,601 @@ +/* + * Copyright (c) 2019 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h new file mode 100644 index 0000000..1dac48c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h new file mode 100644 index 0000000..8901259 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h new file mode 100644 index 0000000..ebc2bb6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h new file mode 100644 index 0000000..0c135b1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h new file mode 100644 index 0000000..c52ff0a --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h new file mode 100644 index 0000000..83493ab --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h new file mode 100644 index 0000000..e7b2985 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h new file mode 100644 index 0000000..04dd640 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h new file mode 100644 index 0000000..c64c8a6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h new file mode 100644 index 0000000..ae1af2e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S b/arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S new file mode 100644 index 0000000..dccd54a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h new file mode 100644 index 0000000..4742124 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include "sr_def.h" +#include + +/* + * 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/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h new file mode 100644 index 0000000..0389f38 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h new file mode 100644 index 0000000..5b5309f --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h new file mode 100644 index 0000000..806ef56 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h new file mode 100644 index 0000000..c39b18c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h new file mode 100644 index 0000000..e08904e --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h new file mode 100644 index 0000000..277836e --- /dev/null +++ b/arm-trusted-firmware/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 +#endif + +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h new file mode 100644 index 0000000..b3fc735 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h new file mode 100644 index 0000000..6e971ce --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h new file mode 100644 index 0000000..1f15bb0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h b/arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h new file mode 100644 index 0000000..7d83182 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/platform.mk b/arm-trusted-firmware/plat/brcm/board/stingray/platform.mk new file mode 100644 index 0000000..aa2fe86 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c new file mode 100644 index 0000000..b2c8aec --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c @@ -0,0 +1,743 @@ +/* + * Copyright (c) 2016-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#ifdef USE_GPIO +#include +#include +#endif +#include +#include +#include +#include +#ifdef USE_DDR +#include +#else +#include +#endif +#if DRIVER_OCOTP_ENABLE +#include +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c new file mode 100644 index 0000000..04df6a0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c @@ -0,0 +1,1071 @@ +/* + * Copyright (c) 2015 - 2021, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef USE_USB +#include +#endif +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c new file mode 100644 index 0000000..5e07fac --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c new file mode 100644 index 0000000..5725a2e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c @@ -0,0 +1,477 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c new file mode 100644 index 0000000..9141d3e --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c @@ -0,0 +1,355 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c new file mode 100644 index 0000000..de8b995 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c @@ -0,0 +1,536 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c new file mode 100644 index 0000000..58ea9e2 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c new file mode 100644 index 0000000..89f76d0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c @@ -0,0 +1,911 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c new file mode 100644 index 0000000..44af4b0 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c @@ -0,0 +1,267 @@ +/* + * Copyright (c) 2017 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c new file mode 100644 index 0000000..a5ac2e7 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2015 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef USE_PAXC +#include +#endif +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c new file mode 100644 index 0000000..2aa9519 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2017-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c new file mode 100644 index 0000000..1d82cef --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c @@ -0,0 +1,227 @@ +/* + * Copyright (c) 2017-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c new file mode 100644 index 0000000..aa2b71a --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c new file mode 100644 index 0000000..7380e09 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#include +#include + +/* 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), + ®_d230); + paxb_pmi_read(core_idx, + PMI_ADDR_LANE0(DSC_SM_CTL22), + ®_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), + ®_d230); + paxb_pmi_read(core_idx, + PMI_ADDR_LANE1(DSC_SM_CTL22), + ®_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/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c new file mode 100644 index 0000000..24718e5 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2019-2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c b/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c new file mode 100644 index 0000000..07b12a7 --- /dev/null +++ b/arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2016 - 2020, Broadcom + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c new file mode 100644 index 0000000..f711354 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c new file mode 100644 index 0000000..9a7153b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c b/arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c new file mode 100644 index 0000000..d3fa83d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/common/brcm_ccn.c b/arm-trusted-firmware/plat/brcm/common/brcm_ccn.c new file mode 100644 index 0000000..9396aaa --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +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/arm-trusted-firmware/plat/brcm/common/brcm_common.c b/arm-trusted-firmware/plat/brcm/common/brcm_common.c new file mode 100644 index 0000000..f23719d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c b/arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c new file mode 100644 index 0000000..c4137c0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/* 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/arm-trusted-firmware/plat/brcm/common/brcm_image_load.c b/arm-trusted-firmware/plat/brcm/common/brcm_image_load.c new file mode 100644 index 0000000..ba02bda --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c b/arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c new file mode 100644 index 0000000..66ec292 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/brcm/common/brcm_mhu.c b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.c new file mode 100644 index 0000000..56f44e0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/brcm/common/brcm_mhu.h b/arm-trusted-firmware/plat/brcm/common/brcm_mhu.h new file mode 100644 index 0000000..6c89a34 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/brcm/common/brcm_scpi.c b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.c new file mode 100644 index 0000000..0a703cb --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/brcm/common/brcm_scpi.h b/arm-trusted-firmware/plat/brcm/common/brcm_scpi.h new file mode 100644 index 0000000..f3b658f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S b/arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S new file mode 100644 index 0000000..ea04f56 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/common/aarch32/plat_common.c b/arm-trusted-firmware/plat/common/aarch32/plat_common.c new file mode 100644 index 0000000..2c1a8fa --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c b/arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c new file mode 100644 index 0000000..9493587 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S b/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S new file mode 100644 index 0000000..5b9cb59 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch32/platform_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + + .weak plat_report_exception + .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_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/arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S b/arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S new file mode 100644 index 0000000..6c3d08d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S b/arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S new file mode 100644 index 0000000..836c13a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S b/arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S new file mode 100644 index 0000000..e2950f5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/common/aarch64/plat_common.c b/arm-trusted-firmware/plat/common/aarch64/plat_common.c new file mode 100644 index 0000000..38a5786 --- /dev/null +++ b/arm-trusted-firmware/plat/common/aarch64/plat_common.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#if RAS_EXTENSION +#include +#endif +#include +#include +#include + +/* + * 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 +#pragma weak plat_arm_set_twedel_scr_el3 + +#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 + +#if !ENABLE_BACKTRACE +static const char *get_el_str(unsigned int el) +{ + if (el == MODE_EL3) { + return "EL3"; + } else if (el == MODE_EL2) { + return "EL2"; + } + return "S-EL1"; +} +#endif /* !ENABLE_BACKTRACE */ + +/* 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 + /* Skip backtrace for lower EL */ + if (level != MODE_EL3) { + console_flush(); + do_panic(); + } +#endif + panic(); +} + +/******************************************************************************* + * In v8.6+ platforms with delayed trapping of WFE this hook sets the delay. It + * is a weak function definition so can be overridden depending on the + * requirements of a platform. The only hook provided is for the TWED fields + * in SCR_EL3, the TWED fields in HCR_EL2, SCTLR_EL2, and SCTLR_EL1 should be + * configured as needed in lower exception levels. + ******************************************************************************/ + +uint32_t plat_arm_set_twedel_scr_el3(void) +{ + return TWED_DISABLED; +} diff --git a/arm-trusted-firmware/plat/common/aarch64/plat_ehf.c b/arm-trusted-firmware/plat/common/aarch64/plat_ehf.c new file mode 100644 index 0000000..da76884 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* + * 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/arm-trusted-firmware/plat/common/aarch64/platform_helpers.S b/arm-trusted-firmware/plat/common/aarch64/platform_helpers.S new file mode 100644 index 0000000..bc650c9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S b/arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S new file mode 100644 index 0000000..c0668ea --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S b/arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S new file mode 100644 index 0000000..c6e5e2d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + + .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/arm-trusted-firmware/plat/common/plat_bl1_common.c b/arm-trusted-firmware/plat/common/plat_bl1_common.c new file mode 100644 index 0000000..bcf9f89 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/common/plat_bl_common.c b/arm-trusted-firmware/plat/common/plat_bl_common.c new file mode 100644 index 0000000..89b77ba --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/common/plat_gicv2.c b/arm-trusted-firmware/plat/common/plat_gicv2.c new file mode 100644 index 0000000..4c76f1b --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_gicv2.c @@ -0,0 +1,301 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +/* + * 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_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, id); +#else + assert(false); +#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/arm-trusted-firmware/plat/common/plat_gicv3.c b/arm-trusted-firmware/plat/common/plat_gicv3.c new file mode 100644 index 0000000..4a8a7ee --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_gicv3.c @@ -0,0 +1,342 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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_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_secure_g0_sgi((unsigned int)sgi_num, 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/arm-trusted-firmware/plat/common/plat_log_common.c b/arm-trusted-firmware/plat/common/plat_log_common.c new file mode 100644 index 0000000..66b9758 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/common/plat_psci_common.c b/arm-trusted-firmware/plat/common/plat_psci_common.c new file mode 100644 index 0000000..c32e59f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/common/plat_spmd_manifest.c b/arm-trusted-firmware/plat/common/plat_spmd_manifest.c new file mode 100644 index 0000000..7f7d796 --- /dev/null +++ b/arm-trusted-firmware/plat/common/plat_spmd_manifest.c @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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, manifest_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; + } + + manifest_size = fdt_totalsize(pm_addr); + + /* Map more memory for larger manifest */ + if (manifest_size > mapped_size) { + /* unmap the smaller sized manifest */ + rc = mmap_remove_dynamic_region(pm_base_align, mapped_size); + if (rc != 0) { + ERROR("Error while unmapping previous SPM Core manifest (%d).\n", + rc); + return rc; + } + + /* align size to multiple of PAGE_SIZE */ + mapped_size = page_align(manifest_size, UP); + + /* map the manifest with a larger size */ + rc = mmap_add_dynamic_region( + (unsigned long long)pm_base_align, + pm_base_align, + mapped_size, + MT_RO_DATA); + if (rc != 0) { + ERROR("Error while mapping larger SPM Core manifest (%d).\n", rc); + return rc; + } + } + + 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, mapped_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/arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c b/arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c new file mode 100644 index 0000000..12ab0a9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#if USE_TBBR_DEFS +#include +#else +#include +#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/arm-trusted-firmware/plat/common/ubsan.c b/arm-trusted-firmware/plat/common/ubsan.c new file mode 100644 index 0000000..45b0f7c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c new file mode 100644 index 0000000..702fc2d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S b/arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S new file mode 100644 index 0000000..82a404a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c new file mode 100644 index 0000000..31ff820 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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(¶ms, 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(¶ms, &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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c new file mode 100644 index 0000000..4e013a0 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include /* also includes hikey_def.h and hikey_layout.h*/ + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c new file mode 100644 index 0000000..a90f12c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include /* also includes hikey_def.h and hikey_layout.h*/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SPD_opteed +#include +#endif +#include + +#include +#include +#include +#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(¶ms, 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(¶ms, &mmc_info); + + hikey_io_setup(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c new file mode 100644 index 0000000..7d008e7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c new file mode 100644 index 0000000..d062de4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c new file mode 100644 index 0000000..cd9e9a2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c new file mode 100644 index 0000000..fd610d8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c new file mode 100644 index 0000000..05c1e7f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h new file mode 100644 index 0000000..b75bc72 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S new file mode 100644 index 0000000..f308eee --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c new file mode 100644 index 0000000..4b95939 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c new file mode 100644 index 0000000..b7dda8d --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c b/arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c new file mode 100644 index 0000000..7890eb7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c new file mode 100644 index 0000000..22a67fd --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c new file mode 100644 index 0000000..43ee0b2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c new file mode 100644 index 0000000..ac83bd8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c new file mode 100644 index 0000000..e2e3db7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S new file mode 100644 index 0000000..62542f2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c b/arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c new file mode 100644 index 0000000..3cd1bd0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h new file mode 100644 index 0000000..f67ee5c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h new file mode 100644 index 0000000..a43db68 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h new file mode 100644 index 0000000..614eba2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h new file mode 100644 index 0000000..77236e8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h new file mode 100644 index 0000000..05620ea --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h new file mode 100644 index 0000000..404405b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h new file mode 100644 index 0000000..fc991f8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h new file mode 100644 index 0000000..590700d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h new file mode 100644 index 0000000..4b8dc53 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h new file mode 100644 index 0000000..b0c0ae8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h new file mode 100644 index 0000000..731c51a --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h new file mode 100644 index 0000000..cbb4651 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h new file mode 100644 index 0000000..a1fad7a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h new file mode 100644 index 0000000..f93e418 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S new file mode 100644 index 0000000..9cd276a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +.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/arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h new file mode 100644 index 0000000..04ea71f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include /* 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/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk b/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk new file mode 100644 index 0000000..18197cf --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey/platform.mk @@ -0,0 +1,168 @@ +# +# Copyright (c) 2017-2020, 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 + +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 genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + 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/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c new file mode 100644 index 0000000..612a7f2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#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, + MAP_TSP_MEM, + {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/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S b/arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S new file mode 100644 index 0000000..5381369 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c new file mode 100644 index 0000000..a6a4949 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +#include +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c new file mode 100644 index 0000000..91d8033 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#include <../hikey960_def.h> +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h new file mode 100644 index 0000000..e0cb381 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c new file mode 100644 index 0000000..0a2d062 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c new file mode 100644 index 0000000..ba236d2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * 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, + }, +# 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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c new file mode 100644 index 0000000..c1c2a8c --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c @@ -0,0 +1,325 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef SPD_opteed +#include +#endif + +#include +#include "hikey960_def.h" +#include "hikey960_private.h" + +#define BL2_RW_BASE (BL_CODE_END) + +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) { +#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) +{ + /* 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(); +} diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c new file mode 100644 index 0000000..f5f8ffe --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#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; + +/****************************************************************************** + * 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; + + 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())); + + /* + * 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) +{ + 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); + } +} + +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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c new file mode 100644 index 0000000..3c4a164 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c new file mode 100644 index 0000000..1e1126f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h new file mode 100644 index 0000000..9651d78 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_DEF_H +#define HIKEY960_DEF_H + +#include +#include + +#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 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 0x3F000000 + +#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 */ + +#endif /* HIKEY960_DEF_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c new file mode 100644 index 0000000..57cb1b2 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c new file mode 100644 index 0000000..e1c5845 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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), +}; + +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, +}; + +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 + }, + [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; +} + +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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c new file mode 100644 index 0000000..b9ae313 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c new file mode 100644 index 0000000..f836508 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h new file mode 100644 index 0000000..54bf501 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef HIKEY960_PRIVATE_H +#define HIKEY960_PRIVATE_H + +#include + +/* + * 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); +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); + +#endif /* HIKEY960_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S new file mode 100644 index 0000000..f230ed6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c new file mode 100644 index 0000000..ed4da3b --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c b/arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c new file mode 100644 index 0000000..a242bb1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h new file mode 100644 index 0000000..17b495f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h new file mode 100644 index 0000000..eb5a6c5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h new file mode 100644 index 0000000..dc9e813 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h new file mode 100644 index 0000000..cadc4a4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h new file mode 100644 index 0000000..6a97968 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S new file mode 100644 index 0000000..8765562 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +.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/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h new file mode 100644 index 0000000..215eebe --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h @@ -0,0 +1,142 @@ +/* + * 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 +#include + +#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 << 32) +#define PLAT_PHY_ADDR_SPACE_SIZE (1ULL << 32) + +#if defined(IMAGE_BL1) || defined(IMAGE_BL31) || defined(IMAGE_BL32) +#define MAX_XLAT_TABLES 3 +#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/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk b/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk new file mode 100644 index 0000000..fc2c209 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/hikey960/platform.mk @@ -0,0 +1,158 @@ +# +# Copyright (c) 2017-2020, 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 \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/hisilicon/hikey960/aarch64/hikey960_common.c \ + plat/hisilicon/hikey960/hikey960_boardid.c + +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 + +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 genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + 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 diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c new file mode 100644 index 0000000..fcd0a8b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S b/arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S new file mode 100644 index 0000000..063ee64 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c new file mode 100644 index 0000000..acc1f0e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¶ms, &mmc_info); +#endif + + plat_io_setup(); +} + +unsigned int bl1_plat_get_next_image_id(void) +{ + return BL2_IMAGE_ID; +} diff --git a/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..f683d75 --- /dev/null +++ b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c new file mode 100644 index 0000000..ee46772 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¶ms, &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/arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c b/arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c new file mode 100644 index 0000000..fe60ddc --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h new file mode 100644 index 0000000..e31f4b3 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S new file mode 100644 index 0000000..82d10c1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h new file mode 100644 index 0000000..a34f138 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h new file mode 100644 index 0000000..ce0fbbc --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h b/arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h new file mode 100644 index 0000000..03047f9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c new file mode 100644 index 0000000..67ebca1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c new file mode 100644 index 0000000..a17e0f1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c b/arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c new file mode 100644 index 0000000..764008e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/hisilicon/poplar/platform.mk b/arm-trusted-firmware/plat/hisilicon/poplar/platform.mk new file mode 100644 index 0000000..b5d9867 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c new file mode 100644 index 0000000..59f7b76 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c b/arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c new file mode 100644 index 0000000..0ab1ca4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S b/arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S new file mode 100644 index 0000000..1a1229a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/imx7_clock.c b/arm-trusted-firmware/plat/imx/common/imx7_clock.c new file mode 100644 index 0000000..6bd2e0e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/imx/common/imx8_helpers.S b/arm-trusted-firmware/plat/imx/common/imx8_helpers.S new file mode 100644 index 0000000..19293bf --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/imx/common/imx8_psci.c b/arm-trusted-firmware/plat/imx/common/imx8_psci.c new file mode 100644 index 0000000..91d3370 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx8_topology.c b/arm-trusted-firmware/plat/imx/common/imx8_topology.c new file mode 100644 index 0000000..5e14d17 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_aips.c b/arm-trusted-firmware/plat/imx/common/imx_aips.c new file mode 100644 index 0000000..532d9c0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_caam.c b/arm-trusted-firmware/plat/imx/common/imx_caam.c new file mode 100644 index 0000000..d9c141f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +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/arm-trusted-firmware/plat/imx/common/imx_clock.c b/arm-trusted-firmware/plat/imx/common/imx_clock.c new file mode 100644 index 0000000..743de55 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_csu.c b/arm-trusted-firmware/plat/imx/common/imx_csu.c new file mode 100644 index 0000000..7e165d9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_ehf.c b/arm-trusted-firmware/plat/imx/common/imx_ehf.c new file mode 100644 index 0000000..a9396cd --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_ehf.c @@ -0,0 +1,22 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +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/arm-trusted-firmware/plat/imx/common/imx_io_mux.c b/arm-trusted-firmware/plat/imx/common/imx_io_mux.c new file mode 100644 index 0000000..75de5d1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_io_storage.c b/arm-trusted-firmware/plat/imx/common/imx_io_storage.c new file mode 100644 index 0000000..bb35662 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/imx/common/imx_sdei.c b/arm-trusted-firmware/plat/imx/common/imx_sdei.c new file mode 100644 index 0000000..4b6033f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c b/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c new file mode 100644 index 0000000..d4b3425 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_sip_handler.c @@ -0,0 +1,255 @@ +/* + * Copyright 2019 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c b/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c new file mode 100644 index 0000000..fd54820 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/imx_sip_svc.c @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +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_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 + 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/arm-trusted-firmware/plat/imx/common/imx_snvs.c b/arm-trusted-firmware/plat/imx/common/imx_snvs.c new file mode 100644 index 0000000..9b3a737 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/imx_uart_console.S b/arm-trusted-firmware/plat/imx/common/imx_uart_console.S new file mode 100644 index 0000000..ceeb3a7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/imx_wdog.c b/arm-trusted-firmware/plat/imx/common/imx_wdog.c new file mode 100644 index 0000000..af6d767 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h b/arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h new file mode 100644 index 0000000..264c295 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h b/arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h new file mode 100644 index 0000000..26470e0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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 + +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/arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h b/arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h new file mode 100644 index 0000000..a5c1d2c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h b/arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h new file mode 100644 index 0000000..5445aa1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/include/imx_aips.h b/arm-trusted-firmware/plat/imx/common/include/imx_aips.h new file mode 100644 index 0000000..1d41fe0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/common/include/imx_caam.h b/arm-trusted-firmware/plat/imx/common/include/imx_caam.h new file mode 100644 index 0000000..61005b5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/common/include/imx_clock.h b/arm-trusted-firmware/plat/imx/common/include/imx_clock.h new file mode 100644 index 0000000..d75dcff --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/imx/common/include/imx_csu.h b/arm-trusted-firmware/plat/imx/common/include/imx_csu.h new file mode 100644 index 0000000..879d10b --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/imx/common/include/imx_hab.h b/arm-trusted-firmware/plat/imx/common/include/imx_hab.h new file mode 100644 index 0000000..22c0742 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h b/arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h new file mode 100644 index 0000000..d588cfd --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h b/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h new file mode 100644 index 0000000..6c7a760 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2015-2019, 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_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_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_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_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_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/arm-trusted-firmware/plat/imx/common/include/imx_snvs.h b/arm-trusted-firmware/plat/imx/common/include/imx_snvs.h new file mode 100644 index 0000000..565c451 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/imx/common/include/imx_uart.h b/arm-trusted-firmware/plat/imx/common/include/imx_uart.h new file mode 100644 index 0000000..6c4d62f --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/common/include/imx_wdog.h b/arm-trusted-firmware/plat/imx/common/include/imx_wdog.h new file mode 100644 index 0000000..75a729a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/imx/common/include/plat_imx8.h b/arm-trusted-firmware/plat/imx/common/include/plat_imx8.h new file mode 100644 index 0000000..be99b97 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/imx/common/include/plat_macros.S b/arm-trusted-firmware/plat/imx/common/include/plat_macros.S new file mode 100644 index 0000000..30cce0a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/include/sci/sci.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci.h new file mode 100644 index 0000000..2c45bb8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#endif /* SCI_H */ diff --git a/arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h new file mode 100644 index 0000000..39e9012 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h new file mode 100644 index 0000000..60dbc27 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h new file mode 100644 index 0000000..a169f88 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h b/arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h new file mode 100644 index 0000000..6ade01c --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h new file mode 100644 index 0000000..d9dd49d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h new file mode 100644 index 0000000..dc23eed --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h new file mode 100644 index 0000000..76ca5c4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h new file mode 100644 index 0000000..df1bc40 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h b/arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h new file mode 100644 index 0000000..f8423ab --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/imx/common/lpuart_console.S b/arm-trusted-firmware/plat/imx/common/lpuart_console.S new file mode 100644 index 0000000..ff01e35 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c b/arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c new file mode 100644 index 0000000..150e81e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c new file mode 100644 index 0000000..66e956d --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h b/arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h new file mode 100644 index 0000000..7885219 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/common/sci/ipc.c b/arm-trusted-firmware/plat/imx/common/sci/ipc.c new file mode 100644 index 0000000..5769119 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/sci/sci_api.mk b/arm-trusted-firmware/plat/imx/common/sci/sci_api.mk new file mode 100644 index 0000000..92c7190 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c new file mode 100644 index 0000000..080de6a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h new file mode 100644 index 0000000..03b1a51 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c new file mode 100644 index 0000000..319d469 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h new file mode 100644 index 0000000..8e9c4bb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c new file mode 100644 index 0000000..66a57a1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h new file mode 100644 index 0000000..8bad3c7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c new file mode 100644 index 0000000..16771a5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#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/arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h new file mode 100644 index 0000000..45d05f9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h new file mode 100644 index 0000000..6716399 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c b/arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c new file mode 100644 index 0000000..a82be96 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#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/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk b/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk new file mode 100644 index 0000000..fdde9a9 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx7/common/imx7.mk @@ -0,0 +1,112 @@ +# +# Copyright (c) 2018-2020, 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 genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + 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/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c new file mode 100644 index 0000000..4e5028c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c new file mode 100644 index 0000000..f9b2983 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S b/arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S new file mode 100644 index 0000000..661fd29 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c new file mode 100644 index 0000000..c3e47b9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S b/arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S new file mode 100644 index 0000000..8bd53c2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c new file mode 100644 index 0000000..cd27128 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h b/arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h new file mode 100644 index 0000000..d92a2d1 --- /dev/null +++ b/arm-trusted-firmware/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 + + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h b/arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h new file mode 100644 index 0000000..2a34c6a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h b/arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h new file mode 100644 index 0000000..3c7e20f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h new file mode 100644 index 0000000..5f2975d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c new file mode 100644 index 0000000..2df96ae --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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(¶ms, 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(¶ms, &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/arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk b/arm-trusted-firmware/plat/imx/imx7/picopi/platform.mk new file mode 100644 index 0000000..5901001 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h new file mode 100644 index 0000000..683e50d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk b/arm-trusted-firmware/plat/imx/imx7/warp7/platform.mk new file mode 100644 index 0000000..ea0f001 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c new file mode 100644 index 0000000..ec13ade --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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(¶ms, 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(¶ms, &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/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c b/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c new file mode 100644 index 0000000..1e55f05 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/gpc_common.c @@ -0,0 +1,252 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +static uint32_t gpc_imr_offset[] = { IMR1_CORE0_A53, IMR1_CORE1_A53, IMR1_CORE2_A53, IMR1_CORE3_A53, }; + +DEFINE_BAKERY_LOCK(gpc_lock); + +#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)); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c new file mode 100644 index 0000000..478005e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +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 */ + 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/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c new file mode 100644 index 0000000..8b2fdd6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c @@ -0,0 +1,200 @@ +/* + * Copyright (c) 2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, Linaro. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#if MEASURED_BOOT +#include +#endif +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c new file mode 100644 index 0000000..3a03069 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c new file mode 100644 index 0000000..ec61606 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include "./include/imx8m_measured_boot.h" +#include +#include + +/* 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/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c b/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c new file mode 100644 index 0000000..9dfd311 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c @@ -0,0 +1,249 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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_BASE; + + 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_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))) { + 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); +} + +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_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) +{ + mmio_write_32(IMX_SNVS_BASE + SNVS_LPCR, SNVS_LPCR_SRTC_ENV | + SNVS_LPCR_DP_EN | SNVS_LPCR_TOP); + + 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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c new file mode 100644 index 0000000..ab59292 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c @@ -0,0 +1,91 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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); + + /* enable all the power domain by default */ + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c new file mode 100644 index 0000000..c39dd93 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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(¶ms, &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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c new file mode 100644 index 0000000..e44345d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c new file mode 100644 index 0000000..40110d7 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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 */ + {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(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + + /* 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); + + imx8m_caam_init(); + + 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); + + /* + * 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); + +#ifdef SPD_opteed + /* 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; +#endif + + bl31_tzc380_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); +#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 + mmap_add(imx_mmap); + + init_xlat_tables(); + + 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); + + 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; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c new file mode 100644 index 0000000..815d3a2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S new file mode 100644 index 0000000..544ee8a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c new file mode 100644 index 0000000..a4384d7 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h new file mode 100644 index 0000000..1a4eae5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h new file mode 100644 index 0000000..5e0ef97 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h new file mode 100644 index 0000000..300ef9e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#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_LIMIT U(0x940000) +#define BL31_BASE U(0x900000) +#define BL31_LIMIT U(0x920000) +#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) +#define BL31_LIMIT U(0x940000) +#endif + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) +#define PLAT_NS_IMAGE_SIZE U(0x00200000) + +/* 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(0xC00000) +#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_ROM_BASE U(0x0) + +#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 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 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/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk new file mode 100644 index 0000000..cd8de89 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mm/platform.mk @@ -0,0 +1,165 @@ +# +# Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +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_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_aipstz.c \ + plat/imx/imx8m/imx_rdc.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 \ + plat/imx/common/imx_ehf.c \ + plat/imx/common/imx_sdei.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_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 \ + ${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 genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +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 := 1 +SDEI_SUPPORT := 1 + +ifeq (${MEASURED_BOOT},1) + MEASURED_BOOT_MK := drivers/measured_boot/event_log/event_log.mk + $(info Including ${MEASURED_BOOT_MK}) + include ${MEASURED_BOOT_MK} + +BL2_SOURCES += plat/imx/imx8m/imx8m_measured_boot.c \ + plat/imx/imx8m/imx8m_dyn_cfg_helpers.c \ + ${EVENT_LOG_SOURCES} + +endif diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c new file mode 100644 index 0000000..37d4226 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c @@ -0,0 +1,94 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#define CCGR(x) (0x4000 + (x) * 0x10) + +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); + + /* enable all the power domain by default */ + for (i = 0; i < 103; i++) + mmio_write_32(IMX_CCM_BASE + CCGR(i), 0x3); + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x485); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c new file mode 100644 index 0000000..d4705ee --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static const mmap_region_t imx_mmap[] = { + GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_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(0x1, DID1), + + /* peripherals domain permission */ + + /* 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 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; + 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); + + imx8m_caam_init(); + + 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); + + /* + * 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); + +#ifdef SPD_opteed + /* 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; +#endif + + bl31_tzc380_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); +#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 + mmap_add(imx_mmap); + + init_xlat_tables(); + + 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); + + 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; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c new file mode 100644 index 0000000..f541fc1 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c @@ -0,0 +1,44 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h new file mode 100644 index 0000000..8a81368 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h new file mode 100644 index 0000000..9c46d8d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h @@ -0,0 +1,140 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#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_LIMIT U(0x980000) + +/* non-secure uboot base */ +#define PLAT_NS_IMAGE_OFFSET U(0x40200000) + +/* 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(0xC00000) +#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_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 */ + +#endif /* platform_def.h */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk new file mode 100644 index 0000000..2087089 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mn/platform.mk @@ -0,0 +1,61 @@ +# +# Copyright 2019-2020 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_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_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.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 \ + plat/imx/common/imx_ehf.c \ + plat/imx/common/imx_sdei.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 \ + ${IMX_GIC_SOURCES} \ + ${XLAT_TABLES_LIB_SRCS} + +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 := 1 +SDEI_SUPPORT := 1 diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c new file mode 100644 index 0000000..d660e3d --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c @@ -0,0 +1,379 @@ +/* + * Copyright 2019-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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, +}; + +/* PU domain, add some hole to minimize the uboot change */ +static struct imx_pwr_domain pu_domains[20] = { + [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; + } + } + } +} + +static 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; + + 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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c new file mode 100644 index 0000000..08cbeeb --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c @@ -0,0 +1,117 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include "imx8mp_private.h" +#include +#include +#include +#include +#include +#include + + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c new file mode 100644 index 0000000..f2f6808 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c new file mode 100644 index 0000000..22fbd5e --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c @@ -0,0 +1,187 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +static const mmap_region_t imx_mmap[] = { + GIC_MAP, AIPS_MAP, OCRAM_S_MAP, DDRC_MAP, + NOC_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(0x1, DID1), + + /* peripherals domain permission */ + + /* memory region */ + + /* 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 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); + + imx8m_caam_init(); + + 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); + + /* + * 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); + +#ifdef SPD_opteed + /* 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; +#endif + + bl31_tzc380_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); +#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 + mmap_add(imx_mmap); + + init_xlat_tables(); + + 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); + + 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; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c new file mode 100644 index 0000000..bc7b246 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c @@ -0,0 +1,44 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S new file mode 100644 index 0000000..a4c7ce1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c new file mode 100644 index 0000000..5d1a6c2 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h new file mode 100644 index 0000000..7909937 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h new file mode 100644 index 0000000..0a02334 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h new file mode 100644 index 0000000..486c1ee --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h @@ -0,0 +1,180 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include +#include + +#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_LIMIT U(0x990000) +#define BL31_BASE U(0x950000) +#define BL31_LIMIT U(0x970000) +#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) +#define BL31_LIMIT U(0x990000) +#endif + +#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) + +/* 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_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 */ + +#endif /* platform_def.h */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk new file mode 100644 index 0000000..823b5d6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mp/platform.mk @@ -0,0 +1,153 @@ +# +# Copyright 2019-2020 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_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_aipstz.c \ + plat/imx/imx8m/imx_rdc.c \ + plat/imx/imx8m/imx8m_caam.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_ehf.c \ + plat/imx/common/imx_sdei.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_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 genrsa 2048 > $@ 2>/dev/null; \ + fi + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif + +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 := 1 +SDEI_SUPPORT := 1 diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c new file mode 100644 index 0000000..367c941 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c @@ -0,0 +1,181 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/* 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); + + /* enable all the power domain by default */ + mmio_write_32(IMX_GPC_BASE + PU_PGC_UP_TRG, 0x3fcf); +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c new file mode 100644 index 0000000..05b5970 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c @@ -0,0 +1,217 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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); + + imx8m_caam_init(); + +#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 + /* + * 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); + +#ifdef SPD_opteed + /* 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; +#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); + + 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; +} diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c new file mode 100644 index 0000000..662017d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h new file mode 100644 index 0000000..f171bd9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h new file mode 100644 index 0000000..6d6a865 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h @@ -0,0 +1,126 @@ +/* + * Copyright (c) 2018-2019, 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) + +/* 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 4 +#define MAX_MMAP_REGIONS 14 + +#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 8000000 /* 8MHz */ + +#define DEBUG_CONSOLE 0 +#define IMX_WDOG_B_RESET diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk new file mode 100644 index 0000000..5461010 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx8mq/platform.mk @@ -0,0 +1,51 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +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/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_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 \ + ${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)) diff --git a/arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c b/arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c new file mode 100644 index 0000000..ecf8b1d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c b/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c new file mode 100644 index 0000000..85de191 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +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/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h b/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h new file mode 100644 index 0000000..29b8ecf --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/gpc.h @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX8M_GPC_H +#define IMX8M_GPC_H + +#include + +/* 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); + +#endif /*IMX8M_GPC_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h new file mode 100644 index 0000000..84725b1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#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/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h new file mode 100644 index 0000000..2ec0c46 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +int imx8m_set_nt_fw_info(size_t log_size, uintptr_t *ns_log_addr); + +#endif /* IMX8M_MEASURED_BOOT_H */ diff --git a/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h new file mode 100644 index 0000000..7d14d11 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h new file mode 100644 index 0000000..7616862 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h b/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h new file mode 100644 index 0000000..e25b0e6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2019, NXP. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef IMX_RDC_H +#define IMX_RDC_H + +#include + +#include + +#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/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c new file mode 100644 index 0000000..d9c9110 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c @@ -0,0 +1,415 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c b/arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c new file mode 100644 index 0000000..bdba37c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h new file mode 100644 index 0000000..671c77f --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h b/arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h new file mode 100644 index 0000000..d16d051 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8qm/platform.mk b/arm-trusted-firmware/plat/imx/imx8qm/platform.mk new file mode 100644 index 0000000..f35fa00 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qm/platform.mk @@ -0,0 +1,48 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +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/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + lib/cpus/aarch64/cortex_a53.S \ + lib/cpus/aarch64/cortex_a72.S \ + drivers/arm/cci/cci.c \ + ${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/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c new file mode 100644 index 0000000..3739cd6 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c @@ -0,0 +1,383 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c b/arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c new file mode 100644 index 0000000..aab3a2d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h b/arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h new file mode 100644 index 0000000..b880e1b --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h b/arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h new file mode 100644 index 0000000..b7fe0e8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/imx/imx8qx/platform.mk b/arm-trusted-firmware/plat/imx/imx8qx/platform.mk new file mode 100644 index 0000000..b25be07 --- /dev/null +++ b/arm-trusted-firmware/plat/imx/imx8qx/platform.mk @@ -0,0 +1,40 @@ +# +# Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +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/xlat_tables/xlat_tables_common.c \ + lib/xlat_tables/aarch64/xlat_tables.c \ + lib/cpus/aarch64/cortex_a35.S \ + ${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/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c new file mode 100644 index 0000000..6e67502 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c @@ -0,0 +1,186 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_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_UART0_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(); +} + + +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(¶ms, &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/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c new file mode 100644 index 0000000..168236b --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#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_UART0_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); +} + +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/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h new file mode 100644 index 0000000..20667f0 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019, 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/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h new file mode 100644 index 0000000..3746d92 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h new file mode 100644 index 0000000..00f4ca5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h new file mode 100644 index 0000000..22db3e2 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef AGX_NOC_H +#define AGX_NOC_H + + +#define AXI_AP (1<<0) +#define FPGA2SOC (1<<16) +#define MPU (1<<24) +#define AGX_NOC_PER_SCR_NAND 0xffd21000 +#define AGX_NOC_PER_SCR_NAND_DATA 0xffd21004 +#define AGX_NOC_PER_SCR_USB0 0xffd2100c +#define AGX_NOC_PER_SCR_USB1 0xffd21010 +#define AGX_NOC_PER_SCR_SPI_M0 0xffd2101c +#define AGX_NOC_PER_SCR_SPI_M1 0xffd21020 +#define AGX_NOC_PER_SCR_SPI_S0 0xffd21024 +#define AGX_NOC_PER_SCR_SPI_S1 0xffd21028 +#define AGX_NOC_PER_SCR_EMAC0 0xffd2102c +#define AGX_NOC_PER_SCR_EMAC1 0xffd21030 +#define AGX_NOC_PER_SCR_EMAC2 0xffd21034 +#define AGX_NOC_PER_SCR_SDMMC 0xffd21040 +#define AGX_NOC_PER_SCR_GPIO0 0xffd21044 +#define AGX_NOC_PER_SCR_GPIO1 0xffd21048 +#define AGX_NOC_PER_SCR_I2C0 0xffd21050 +#define AGX_NOC_PER_SCR_I2C1 0xffd21058 +#define AGX_NOC_PER_SCR_I2C2 0xffd2105c +#define AGX_NOC_PER_SCR_I2C3 0xffd21060 +#define AGX_NOC_PER_SCR_SP_TIMER0 0xffd21064 +#define AGX_NOC_PER_SCR_SP_TIMER1 0xffd21068 +#define AGX_NOC_PER_SCR_UART0 0xffd2106c +#define AGX_NOC_PER_SCR_UART1 0xffd21070 + + +#define AGX_NOC_SYS_SCR_DMA_ECC 0xffd21108 +#define AGX_NOC_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define AGX_NOC_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define AGX_NOC_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define AGX_NOC_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define AGX_NOC_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define AGX_NOC_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define AGX_NOC_SYS_SCR_NAND_ECC 0xffd2112c +#define AGX_NOC_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define AGX_NOC_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define AGX_NOC_SYS_SCR_OCRAM_ECC 0xffd21138 +#define AGX_NOC_SYS_SCR_SDMMC_ECC 0xffd21140 +#define AGX_NOC_SYS_SCR_USB0_ECC 0xffd21144 +#define AGX_NOC_SYS_SCR_USB1_ECC 0xffd21148 +#define AGX_NOC_SYS_SCR_CLK_MGR 0xffd2114c +#define AGX_NOC_SYS_SCR_IO_MGR 0xffd21154 +#define AGX_NOC_SYS_SCR_RST_MGR 0xffd21158 +#define AGX_NOC_SYS_SCR_SYS_MGR 0xffd2115c +#define AGX_NOC_SYS_SCR_OSC0_TIMER 0xffd21160 +#define AGX_NOC_SYS_SCR_OSC1_TIMER 0xffd21164 +#define AGX_NOC_SYS_SCR_WATCHDOG0 0xffd21168 +#define AGX_NOC_SYS_SCR_WATCHDOG1 0xffd2116c +#define AGX_NOC_SYS_SCR_WATCHDOG2 0xffd21170 +#define AGX_NOC_SYS_SCR_WATCHDOG3 0xffd21174 +#define AGX_NOC_SYS_SCR_DAP 0xffd21178 +#define AGX_NOC_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define AGX_NOC_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define AGX_CCU_NOC_BRIDGE_CPU0_RAM 0xf7004688 +#define AGX_CCU_NOC_BRIDGE_IOM_RAM 0xf7004688 + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h new file mode 100644 index 0000000..fe01062 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h new file mode 100644 index 0000000..9c87e45 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h @@ -0,0 +1,33 @@ +/* + * 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 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_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 + +#endif /* PLAT_SOCFPGA_DEF_H */ + diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk b/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk new file mode 100644 index 0000000..10a3eec --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/platform.mk @@ -0,0 +1,78 @@ +# +# 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/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_handoff.c \ + plat/intel/soc/common/soc/socfpga_mailbox.c \ + plat/intel/soc/common/soc/socfpga_reset_manager.c \ + plat/intel/soc/common/soc/socfpga_system_manager.c \ + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c \ + plat/intel/soc/common/drivers/ccu/ncore_ccu.c + +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/common/socfpga_psci.c \ + plat/intel/soc/common/socfpga_sip_svc.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 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c new file mode 100644 index 0000000..4efd713 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c @@ -0,0 +1,389 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#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; +} diff --git a/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c new file mode 100644 index 0000000..2aabe87 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c new file mode 100644 index 0000000..e05d92a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c b/arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c new file mode 100644 index 0000000..0b908cf --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..5cb9b69 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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, PLAT_UART0_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, PLAT_UART0_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/arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c new file mode 100644 index 0000000..b79a63c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..4f75665 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c new file mode 100644 index 0000000..d4716cf --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c @@ -0,0 +1,131 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h new file mode 100644 index 0000000..3f662ff --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c new file mode 100644 index 0000000..cecf560 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h new file mode 100644 index 0000000..cfef585 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c new file mode 100644 index 0000000..651189b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h b/arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h new file mode 100644 index 0000000..2c72463 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S b/arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S new file mode 100644 index 0000000..43db9a2 --- /dev/null +++ b/arm-trusted-firmware/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 + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h b/arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h new file mode 100644 index 0000000..7859493 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +/* Platform Type */ +#define PLAT_SOCFPGA_STRATIX10 1 +#define PLAT_SOCFPGA_AGILEX 2 +#define PLAT_SOCFPGA_N5X 3 + +/* 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 + +#ifndef SIMICS_BUILD +#define PLAT_BAUDRATE (115200) +#define PLAT_UART_CLOCK (100000000) + +#else +#define PLAT_BAUDRATE (4800) +#define PLAT_UART_CLOCK (76800) + +#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_FREQ_IN_MHZ (400) + +#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/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h new file mode 100644 index 0000000..5b98006 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h new file mode 100644 index 0000000..ff10d36 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h @@ -0,0 +1,41 @@ +/* + * 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_RANDOM_BYTE_SIZE (FCS_RANDOM_WORD_SIZE * 4U) +#define FCS_PROV_DATA_BYTE_SIZE (FCS_PROV_DATA_WORD_SIZE * 4U) + +#define FCS_CRYPTION_DATA_0 0x10100 + +/* FCS Payload Structure */ + +typedef struct fcs_crypt_payload_t { + uint32_t first_word; + uint32_t src_addr; + uint32_t src_size; + uint32_t dst_addr; + uint32_t dst_size; +} fcs_crypt_payload; + +/* Functions Definitions */ + +uint32_t intel_fcs_random_number_gen(uint64_t addr, uint64_t *ret_size, + uint32_t *mbox_error); +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_cryption(uint32_t mode, uint32_t src_addr, + uint32_t src_size, uint32_t dst_addr, + uint32_t dst_size, uint32_t *send_id); + +#endif /* SOCFPGA_FCS_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h new file mode 100644 index 0000000..ba0f7f3 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h new file mode 100644 index 0000000..6b7e0fc --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h @@ -0,0 +1,175 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SOCFPGA_MBOX_H +#define SOCFPGA_MBOX_H + +#include + + +#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 + + +/* 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_REBOOT_HPS 0x47 + +/* Reconfiguration Commands */ +#define MBOX_CONFIG_STATUS 0x04 +#define MBOX_RECONFIG 0x06 +#define MBOX_RECONFIG_DATA 0x08 +#define MBOX_RECONFIG_STATUS 0x09 + +/* 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_ENCRYPT_REQ 0x7E +#define MBOX_FCS_DECRYPT_REQ 0x7F +#define MBOX_FCS_RANDOM_GEN 0x80 + +/* 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 + +/* 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_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) & 0x00000fff) +#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) + +/* RSU Macros */ +#define RSU_VERSION_ACMF BIT(8) +#define RSU_VERSION_ACMF_MASK 0xff00 + + +/* 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_read_response(uint32_t *job_id, uint32_t *response, + unsigned int *resp_len); +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); + +#endif /* SOCFPGA_MBOX_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h new file mode 100644 index 0000000..ca38f62 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2019, 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); + +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/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h new file mode 100644 index 0000000..a976df7 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h @@ -0,0 +1,108 @@ +/* + * 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" + + +/* Register Mapping */ + +#define SOCFPGA_RSTMGR_STAT 0x000 +#define SOCFPGA_RSTMGR_HDSKEN 0x010 +#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_BRGMODRST_SOC2FPGA 0x1 +#define RSTMGR_BRGMODRST_LWHPS2FPGA 0x2 +#define RSTMGR_BRGMODRST_FPGA2SOC 0x4 +#define RSTMGR_BRGMODRST_F2SSDRAM1 0x10 +#define RSTMGR_BRGMODRST_F2SSDRAM2 0x20 +#define RSTMGR_BRGMODRST_MPFE 0x40 +#define RSTMGR_BRGMODRST_DDRSCH 0x40 + +/* 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(void); +int socfpga_bridges_disable(void); + +#endif /* SOCFPGA_RESETMANAGER_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h new file mode 100644 index 0000000..0db71e2 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h @@ -0,0 +1,87 @@ +/* + * 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_ERROR 0x4 +#define INTEL_SIP_SMC_RSU_ERROR 0x7 + +/* SiP mailbox error code */ +#define GENERIC_RESPONSE_ERROR 0x3FF + +/* SMC SiP service function identifier */ + +/* 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 + +/* 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 + + +/* ECC */ +#define INTEL_SIP_SMC_ECC_DBE 0xC200000D + +/* Send Mailbox Command */ +#define INTEL_SIP_SMC_MBOX_SEND_CMD 0xC200001E + + +/* SiP Definitions */ + +/* 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) + +/* 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 0 +#define SIP_SVC_VERSION_MINOR 1 + + +/* Structure Definitions */ +struct fpga_config_info { + uint32_t addr; + int size; + int size_written; + uint32_t write_requested; + int subblocks_sent; + int block_number; +}; + +/* Function Definitions */ + +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); + +#endif /* SOCFPGA_SIP_SVC_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h new file mode 100644 index 0000000..2b13f1f --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h @@ -0,0 +1,126 @@ +/* + * 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(0) +#define IDLE_DATA_SOC2FPGA BIT(4) +#define IDLE_DATA_MASK (IDLE_DATA_LWSOC2FPGA | IDLE_DATA_SOC2FPGA) + +#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 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)) + +#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 + +#define SOCFPGA_CCU_NOC_CPU0_RAMSPACE0_0 0xf7004688 +#define SOCFPGA_CCU_NOC_IOM_RAMSPACE0_0 0xf7018628 + +void enable_ns_peripheral_access(void); +void enable_ns_bridge_access(void); + +#endif /* SOCFPGA_SYSTEMMANAGER_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c new file mode 100644 index 0000000..c4e06a6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c new file mode 100644 index 0000000..fe5461b --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c @@ -0,0 +1,120 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include "socfpga_fcs.h" +#include "socfpga_mailbox.h" +#include "socfpga_sip_svc.h" + +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; +} + +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; + } + + status = mailbox_send_cmd_async(send_id, MBOX_CMD_VAB_SRC_CERT, + (uint32_t *)addr, size / MBOX_WORD_BYTE, + CMD_DIRECT); + + 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_cryption(uint32_t mode, uint32_t src_addr, + uint32_t src_size, uint32_t dst_addr, + uint32_t dst_size, uint32_t *send_id) +{ + int status; + uint32_t cmd; + + 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; + } + + fcs_crypt_payload payload = { + FCS_CRYPTION_DATA_0, + src_addr, + src_size, + dst_addr, + dst_size }; + + if (mode != 0U) { + cmd = MBOX_FCS_ENCRYPT_REQ; + } else { + cmd = MBOX_FCS_DECRYPT_REQ; + } + + status = mailbox_send_cmd_async(send_id, cmd, (uint32_t *) &payload, + sizeof(fcs_crypt_payload) / MBOX_WORD_BYTE, + CMD_INDIRECT); + inv_dcache_range(dst_addr, dst_size); + + if (status < 0) { + return INTEL_SIP_SMC_STATUS_REJECTED; + } + + return INTEL_SIP_SMC_STATUS_OK; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c new file mode 100644 index 0000000..cacfd53 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c new file mode 100644 index 0000000..4bb3a96 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c new file mode 100644 index 0000000..be900c9 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c @@ -0,0 +1,529 @@ +/* + * Copyright (c) 2020-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "socfpga_mailbox.h" +#include "socfpga_sip_svc.h" + + +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_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(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; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c new file mode 100644 index 0000000..b0de60e --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2019-2022, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#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 = 1000; + + while (time_out--) { + if ((mmio_read_32(addr) & mask) == match) { + return 0; + } + } + return -ETIMEDOUT; +} + +int socfpga_bridges_enable(void) +{ + /* Clear idle request */ + mmio_setbits_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_CLR), ~0); + + /* De-assert all bridges */ + mmio_clrbits_32(SOCFPGA_RSTMGR(BRGMODRST), ~0); + + /* Wait until idle ack becomes 0 */ + return poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK), + IDLE_DATA_MASK, 0); +} + +int socfpga_bridges_disable(void) +{ + /* Set idle request */ + mmio_write_32(SOCFPGA_SYSMGR(NOC_IDLEREQ_SET), ~0); + + /* Enable NOC timeout */ + mmio_setbits_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 1); + + /* Wait until each idle ack bit toggle to 1 */ + if (poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLEACK), + IDLE_DATA_MASK, IDLE_DATA_MASK)) + return -ETIMEDOUT; + + /* Wait until each idle status bit toggle to 1 */ + if (poll_idle_status(SOCFPGA_SYSMGR(NOC_IDLESTATUS), + IDLE_DATA_MASK, IDLE_DATA_MASK)) + return -ETIMEDOUT; + + /* Assert all bridges */ +#if PLATFORM_MODEL == PLAT_SOCFPGA_STRATIX10 + mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), + ~(RSTMGR_FIELD(BRG, DDRSCH) | RSTMGR_FIELD(BRG, FPGA2SOC))); +#else + mmio_setbits_32(SOCFPGA_RSTMGR(BRGMODRST), + ~(RSTMGR_FIELD(BRG, MPFE) | RSTMGR_FIELD(BRG, FPGA2SOC))); +#endif + + /* Disable NOC timeout */ + mmio_clrbits_32(SOCFPGA_SYSMGR(NOC_TIMEOUT), 1); + + return 0; +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c new file mode 100644 index 0000000..a64053c --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c @@ -0,0 +1,107 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#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 + mmio_clrbits_32(SOCFPGA_CCU_NOC_CPU0_RAMSPACE0_0, 0x03); + mmio_clrbits_32(SOCFPGA_CCU_NOC_IOM_RAMSPACE0_0, 0x03); + + mmio_write_32(SOCFPGA_SYSMGR(SDMMC), SYSMGR_SDMMC_DRVSEL(3)); +#endif + +} + +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); +} diff --git a/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c new file mode 100644 index 0000000..c55cc9d --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#define SOCFPGA_GLOBAL_TIMER 0xffd01000 +#define SOCFPGA_GLOBAL_TIMER_EN 0x3 + +/******************************************************************** + * 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()); +} + +static const timer_ops_t plat_timer_ops = { + .get_timer_value = socfpga_get_timer_value, + .clk_mult = 1, + .clk_div = PLAT_SYS_COUNTER_FREQ_IN_MHZ, +}; + +void socfpga_delay_timer_init(void) +{ + timer_init(&plat_timer_ops); + 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/arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c new file mode 100644 index 0000000..a5c3279 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c new file mode 100644 index 0000000..5fd6559 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c new file mode 100644 index 0000000..14cd9e0 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c @@ -0,0 +1,567 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#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 int current_block, current_buffer; +static int read_block, max_blocks, is_partial_reconfig; +static uint32_t send_id, rcv_id; +static uint32_t bytes_per_block, blocks_submitted; + + +/* 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(uint32_t query_type) +{ + uint32_t ret; + + if (query_type == 1) + ret = intel_mailbox_get_config_status(MBOX_CONFIG_STATUS, false); + else + ret = intel_mailbox_get_config_status(MBOX_RECONFIG_STATUS, true); + + if (ret) { + if (ret == MBOX_CFGSTAT_STATE_CONFIG) + return INTEL_SIP_SMC_STATUS_BUSY; + else + return INTEL_SIP_SMC_STATUS_ERROR; + } + + if (query_type != 1) { + /* full reconfiguration */ + if (!is_partial_reconfig) + socfpga_bridges_enable(); /* Enable bridge */ + } + + 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(); + 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 config_type) +{ + uint32_t argument = 0x1; + uint32_t response[3]; + int status = 0; + unsigned int size = 0; + unsigned int resp_len = ARRAY_SIZE(response); + + is_partial_reconfig = config_type; + + 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) + return status; + + 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; + + /* full reconfiguration */ + if (!is_partial_reconfig) { + /* Disable bridge */ + socfpga_bridges_disable(); + } + + return 0; +} + +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) +{ + 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; +} + +/* Mailbox services */ +static uint32_t intel_mbox_send_cmd(uint32_t cmd, uint32_t *args, + unsigned int len, + uint32_t urgent, uint32_t *response, + unsigned int resp_len, int *mbox_status, + unsigned int *len_in_resp) +{ + *len_in_resp = 0; + *mbox_status = 0; + + 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, + response, &resp_len); + + if (status < 0) { + *mbox_status = -status; + return INTEL_SIP_SMC_STATUS_ERROR; + } + + *mbox_status = 0; + *len_in_resp = resp_len; + return INTEL_SIP_SMC_STATUS_OK; +} + +/* + * 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 retval = 0; + uint32_t completed_addr[3]; + uint64_t rsu_respbuf[9]; + int status = INTEL_SIP_SMC_STATUS_OK; + int mbox_status; + unsigned int len_in_resp; + u_register_t x5, x6; + + 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(x1); + 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_ECC_DBE: + status = intel_ecc_dbe_notification(x1); + SMC_RET1(handle, status); + + 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, + (uint32_t *)x5, x6, &mbox_status, + &len_in_resp); + SMC_RET3(handle, status, mbox_status, len_in_resp); + + default: + return socfpga_sip_handler(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/arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c new file mode 100644 index 0000000..a2f2c18 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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 = ®ister_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 = ®ister_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/arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c b/arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c new file mode 100644 index 0000000..ca1a91e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c new file mode 100644 index 0000000..2a8daa6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#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_UART0_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/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h new file mode 100644 index 0000000..9186852 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h @@ -0,0 +1,32 @@ +/* + * 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 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_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) + +#endif /* PLAT_SOCFPGA_DEF_H */ diff --git a/arm-trusted-firmware/plat/intel/soc/n5x/platform.mk b/arm-trusted-firmware/plat/intel/soc/n5x/platform.mk new file mode 100644 index 0000000..b72bcc4 --- /dev/null +++ b/arm-trusted-firmware/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_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 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c new file mode 100644 index 0000000..a8026ea --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c @@ -0,0 +1,182 @@ +/* + * Copyright (c) 2019-2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "qspi/cadence_qspi.h" +#include "socfpga_emac.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_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_UART0_BASE, get_uart_clk(), PLAT_BAUDRATE, + &console); + + socfpga_emac_init(); + socfpga_delay_timer_init(); + init_hard_memory_controller(); + mailbox_init(); + + if (!intel_mailbox_is_fpga_not_ready()) + socfpga_bridges_enable(); +} + + +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(¶ms, &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/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c b/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c new file mode 100644 index 0000000..128a808 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2019-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2020, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "socfpga_mailbox.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_UART0_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); +} + +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/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h new file mode 100644 index 0000000..acc700a --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2019, 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_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); + +#endif diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h new file mode 100644 index 0000000..155b279 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h new file mode 100644 index 0000000..3e1e527 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define AXI_AP (1<<0) +#define FPGA2SOC (1<<16) +#define MPU (1<<24) +#define S10_NOC_PER_SCR_NAND 0xffd21000 +#define S10_NOC_PER_SCR_NAND_DATA 0xffd21004 +#define S10_NOC_PER_SCR_USB0 0xffd2100c +#define S10_NOC_PER_SCR_USB1 0xffd21010 +#define S10_NOC_PER_SCR_SPI_M0 0xffd2101c +#define S10_NOC_PER_SCR_SPI_M1 0xffd21020 +#define S10_NOC_PER_SCR_SPI_S0 0xffd21024 +#define S10_NOC_PER_SCR_SPI_S1 0xffd21028 +#define S10_NOC_PER_SCR_EMAC0 0xffd2102c +#define S10_NOC_PER_SCR_EMAC1 0xffd21030 +#define S10_NOC_PER_SCR_EMAC2 0xffd21034 +#define S10_NOC_PER_SCR_SDMMC 0xffd21040 +#define S10_NOC_PER_SCR_GPIO0 0xffd21044 +#define S10_NOC_PER_SCR_GPIO1 0xffd21048 +#define S10_NOC_PER_SCR_I2C0 0xffd21050 +#define S10_NOC_PER_SCR_I2C1 0xffd21058 +#define S10_NOC_PER_SCR_I2C2 0xffd2105c +#define S10_NOC_PER_SCR_I2C3 0xffd21060 +#define S10_NOC_PER_SCR_SP_TIMER0 0xffd21064 +#define S10_NOC_PER_SCR_SP_TIMER1 0xffd21068 +#define S10_NOC_PER_SCR_UART0 0xffd2106c +#define S10_NOC_PER_SCR_UART1 0xffd21070 + + +#define S10_NOC_SYS_SCR_DMA_ECC 0xffd21108 +#define S10_NOC_SYS_SCR_EMAC0RX_ECC 0xffd2110c +#define S10_NOC_SYS_SCR_EMAC0TX_ECC 0xffd21110 +#define S10_NOC_SYS_SCR_EMAC1RX_ECC 0xffd21114 +#define S10_NOC_SYS_SCR_EMAC1TX_ECC 0xffd21118 +#define S10_NOC_SYS_SCR_EMAC2RX_ECC 0xffd2111c +#define S10_NOC_SYS_SCR_EMAC2TX_ECC 0xffd21120 +#define S10_NOC_SYS_SCR_NAND_ECC 0xffd2112c +#define S10_NOC_SYS_SCR_NAND_READ_ECC 0xffd21130 +#define S10_NOC_SYS_SCR_NAND_WRITE_ECC 0xffd21134 +#define S10_NOC_SYS_SCR_OCRAM_ECC 0xffd21138 +#define S10_NOC_SYS_SCR_SDMMC_ECC 0xffd21140 +#define S10_NOC_SYS_SCR_USB0_ECC 0xffd21144 +#define S10_NOC_SYS_SCR_USB1_ECC 0xffd21148 +#define S10_NOC_SYS_SCR_CLK_MGR 0xffd2114c +#define S10_NOC_SYS_SCR_IO_MGR 0xffd21154 +#define S10_NOC_SYS_SCR_RST_MGR 0xffd21158 +#define S10_NOC_SYS_SCR_SYS_MGR 0xffd2115c +#define S10_NOC_SYS_SCR_OSC0_TIMER 0xffd21160 +#define S10_NOC_SYS_SCR_OSC1_TIMER 0xffd21164 +#define S10_NOC_SYS_SCR_WATCHDOG0 0xffd21168 +#define S10_NOC_SYS_SCR_WATCHDOG1 0xffd2116c +#define S10_NOC_SYS_SCR_WATCHDOG2 0xffd21170 +#define S10_NOC_SYS_SCR_WATCHDOG3 0xffd21174 +#define S10_NOC_SYS_SCR_DAP 0xffd21178 +#define S10_NOC_SYS_SCR_L4_NOC_PROBES 0xffd21190 +#define S10_NOC_SYS_SCR_L4_NOC_QOS 0xffd21194 + +#define S10_CCU_NOC_BRIDGE_CPU0_RAM 0xf7004688 +#define S10_CCU_NOC_BRIDGE_IOM_RAM 0xf7004688 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h new file mode 100644 index 0000000..82367d7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h b/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h new file mode 100644 index 0000000..b84a567 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * 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 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_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 + + +#endif /* PLATSOCFPGA_DEF_H */ + diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk b/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk new file mode 100644 index 0000000..d9d88d4 --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/platform.mk @@ -0,0 +1,74 @@ +# +# 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 + +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_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/soc/socfpga_system_manager.c \ + plat/intel/soc/common/drivers/qspi/cadence_qspi.c \ + plat/intel/soc/common/drivers/wdt/watchdog.c + +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/bl31_plat_setup.c \ + plat/intel/soc/common/socfpga_psci.c \ + plat/intel/soc/common/socfpga_sip_svc.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 +SIMICS_BUILD := 0 +USE_COHERENT_MEM := 1 diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c new file mode 100644 index 0000000..1e092de --- /dev/null +++ b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c @@ -0,0 +1,309 @@ +/* + * Copyright (c) 2019, Intel Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#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; +} diff --git a/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c new file mode 100644 index 0000000..ac756ab --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c b/arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c new file mode 100644 index 0000000..7fb4711 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c new file mode 100644 index 0000000..247f73b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h new file mode 100644 index 0000000..dad1085 --- /dev/null +++ b/arm-trusted-firmware/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 + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c new file mode 100644 index 0000000..6862a86 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a3k/a3700/platform.mk new file mode 100644 index 0000000..050af41 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_common.mk new file mode 100644 index 0000000..d0e8688 --- /dev/null +++ b/arm-trusted-firmware/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),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 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 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c new file mode 100644 index 0000000..bc12845 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2019 Repk repk@triplefau.lt + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include +#include +#include +#include +#include + +#define A53_SERR_INT_AXI_SLVERR_ON_EXTERNAL_ACCESS 0xbf000002 + +#if !ENABLE_BACKTRACE +static const char *get_el_str(unsigned int el) +{ + if (el == MODE_EL3) { + return "EL3"; + } else if (el == MODE_EL2) { + return "EL2"; + } + return "S-EL1"; +} +#endif /* !ENABLE_BACKTRACE */ + +/* + * This source file with custom plat_ea_handler function is compiled only when + * building TF-A with compile option HANDLE_EA_EL3_FIRST=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/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c new file mode 100644 index 0000000..e8ac5fc --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S new file mode 100644 index 0000000..f79516f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c new file mode 100644 index 0000000..6351285 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..90d76f0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c new file mode 100644 index 0000000..f105d59 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c new file mode 100644 index 0000000..9d7b3a9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +/* 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 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h new file mode 100644 index 0000000..4d45e15 --- /dev/null +++ b/arm-trusted-firmware/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 + + +#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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h new file mode 100644 index 0000000..44dbb9f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h new file mode 100644 index 0000000..254f78c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h new file mode 100644 index 0000000..26a0137 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +void dram_win_map_build(struct dram_win_map *win_map); +void cpu_wins_init(void); + +#endif /* DRAM_WIN_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h new file mode 100644 index 0000000..42ef30b --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S new file mode 100644 index 0000000..f689b4f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* --------------------------------------------- + * 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h b/arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h new file mode 100644 index 0000000..f19d96b --- /dev/null +++ b/arm-trusted-firmware/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 +#endif /* __ASSEMBLER__ */ + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c new file mode 100644 index 0000000..fea7f81 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c new file mode 100644 index 0000000..3bf3d96 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c new file mode 100644 index 0000000..56f091f --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c @@ -0,0 +1,35 @@ +/* + * Copyright (C) 2021 Marek Behun + * + * Based on plat/marvell/armada/common/marvell_cci.c + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include + +#include + +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/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c b/arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c new file mode 100644 index 0000000..e2d15ab --- /dev/null +++ b/arm-trusted-firmware/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 +#ifdef USE_CCI +#include +#endif +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c new file mode 100644 index 0000000..355770b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c new file mode 100644 index 0000000..a409261 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h new file mode 100644 index 0000000..72bca12 --- /dev/null +++ b/arm-trusted-firmware/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 + +#define CP_COUNT 1 /* A70x0 has single CP0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/platform.mk new file mode 100644 index 0000000..39eb712 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c new file mode 100644 index 0000000..9c8c97e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c new file mode 100644 index 0000000..3b68e91 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h new file mode 100644 index 0000000..cedf323 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/platform.mk new file mode 100644 index 0000000..39eb712 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c new file mode 100644 index 0000000..68d335b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c new file mode 100644 index 0000000..1ed6323 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h new file mode 100644 index 0000000..ab76c31 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h new file mode 100644 index 0000000..768f735 --- /dev/null +++ b/arm-trusted-firmware/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 + +#define CP_COUNT 1 /* A70x0 has single CP0 */ + +#endif /* MVEBU_DEF_H */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/platform.mk new file mode 100644 index 0000000..2495591 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c new file mode 100644 index 0000000..47bc0a8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c new file mode 100644 index 0000000..4ccda14 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h new file mode 100644 index 0000000..afa3be1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/platform.mk new file mode 100644 index 0000000..115dd4a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c new file mode 100644 index 0000000..85c931c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c new file mode 100644 index 0000000..75a1b0c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/platform.mk new file mode 100644 index 0000000..115dd4a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c new file mode 100644 index 0000000..1d8e9d2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c new file mode 100644 index 0000000..0edc977 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/* + * If bootrom is currently at BLE there's no need to include the memory + * maps structure at this point + */ +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c new file mode 100644 index 0000000..eb00874 --- /dev/null +++ b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2020 Sartura Ltd. + * Author: Luka Kovacic + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include + +/***************************************************************************** + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h new file mode 100644 index 0000000..3fa119a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/platform.mk new file mode 100644 index 0000000..3378d53 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/a8k_common.mk new file mode 100644 index 0000000..4d8a87f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c new file mode 100644 index 0000000..4332a76 --- /dev/null +++ b/arm-trusted-firmware/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 + + +/* 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c new file mode 100644 index 0000000..d576514 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..fadc4c2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S new file mode 100644 index 0000000..d7a0592 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.mk new file mode 100644 index 0000000..160e98f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c new file mode 100644 index 0000000..5b3acec --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S new file mode 100644 index 0000000..a48d546 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h new file mode 100644 index 0000000..3a0fd4b --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h new file mode 100644 index 0000000..e19036a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h new file mode 100644 index 0000000..e03c448 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S new file mode 100644 index 0000000..8faccf0 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * Required platform porting macros + * (Provided by included headers) + */ +.macro plat_crash_print_regs +.endm + +#endif /* PLAT_MACROS_S */ diff --git a/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h new file mode 100644 index 0000000..45860ba --- /dev/null +++ b/arm-trusted-firmware/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 +#endif /* __ASSEMBLER__ */ + +#include +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_a8k.mk new file mode 100644 index 0000000..315fc87 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c new file mode 100644 index 0000000..dee2d5b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include +#include /* 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c new file mode 100644 index 0000000..52a8929 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h new file mode 100644 index 0000000..6956461 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c new file mode 100644 index 0000000..a070583 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h b/arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h new file mode 100644 index 0000000..1dfa9fa --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c new file mode 100644 index 0000000..f9521c8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c new file mode 100644 index 0000000..db85cce --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#if MSS_SUPPORT +#include +#include +#include +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c new file mode 100644 index 0000000..9c5ee15 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c new file mode 100644 index 0000000..9ea9276 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#if MSS_SUPPORT +#include +#endif +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c new file mode 100644 index 0000000..e02a893 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#if MSS_SUPPORT +#include + +#ifdef PM_TRACE_ENABLE +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c b/arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c new file mode 100644 index 0000000..a2fc0d0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c new file mode 100644 index 0000000..8d909dc --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c new file mode 100644 index 0000000..21a62d4 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S b/arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S new file mode 100644 index 0000000..3038ec0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#ifndef PLAT_a3700 +#include +#include +#endif +#include +#include + + .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/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c new file mode 100644 index 0000000..7b7cef3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c new file mode 100644 index 0000000..3dfa82e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#ifdef SPD_opteed +#include +#endif +#include +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c new file mode 100644 index 0000000..26ba906 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#ifdef USE_CCI +#include +#endif +#include +#include + +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c new file mode 100644 index 0000000..80351ae --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk b/arm-trusted-firmware/plat/marvell/armada/common/marvell_common.mk new file mode 100644 index 0000000..f0e6edf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c new file mode 100644 index 0000000..ef54bff --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +#include + +#ifdef PLAT_a3700 +#include +#define PLAT_MARVELL_UART_CLK_IN_HZ (get_ref_clk() * 1000000) +#define console_marvell_register console_a3700_register +#else +#include +#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/arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c new file mode 100644 index 0000000..7340996 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +#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/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c new file mode 100644 index 0000000..2505c9f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c new file mode 100644 index 0000000..0bd5545 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c new file mode 100644 index 0000000..be16b08 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c new file mode 100644 index 0000000..2627ba4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c new file mode 100644 index 0000000..3c675b2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c b/arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c new file mode 100644 index 0000000..a40ff6f --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c b/arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c new file mode 100644 index 0000000..c4c5c0e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#include +#include + +#include "comphy/phy-comphy-cp110.h" +#include "secure_dfx_access/dfx.h" +#include "ddr_phy_access.h" +#include + +/* #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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_common.mk new file mode 100644 index 0000000..4ab4359 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c new file mode 100644 index 0000000..70ccfa5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h new file mode 100644 index 0000000..bcb4b2d --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h new file mode 100644 index 0000000..5d68ac7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h new file mode 100644 index 0000000..90913b0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c new file mode 100644 index 0000000..fbede1b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h b/arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h new file mode 100644 index 0000000..d65354a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c b/arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c new file mode 100644 index 0000000..2539752 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#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/arm-trusted-firmware/plat/marvell/marvell.mk b/arm-trusted-firmware/plat/marvell/marvell.mk new file mode 100644 index 0000000..b6a2b99 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c new file mode 100644 index 0000000..82ce07b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c new file mode 100644 index 0000000..fbacf54 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h new file mode 100644 index 0000000..6b55407 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h new file mode 100644 index 0000000..490be73 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/platform.mk new file mode 100644 index 0000000..1e2716d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c new file mode 100644 index 0000000..5bae8eb --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk b/arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/platform.mk new file mode 100644 index 0000000..ee55455 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c new file mode 100644 index 0000000..27ee6aa --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include + +/* OEM Service UUID */ +DEFINE_SVC_UUID2(oem_svc_uid, + 0xd0ad43b9, 0x9b06, 0xe411, 0x91, 0x91, + 0x08, 0x00, 0x20, 0x0c, 0x9a, 0x66); + +/* Setup OEM Services */ +static int32_t oem_svc_setup(void) +{ + /* + * Invoke related module setup from here + */ + + return 0; +} + +/******************************************************************************* + * OEM top level handler for servicing SMCs. + ******************************************************************************/ +uintptr_t oem_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) +{ + WARN("Unimplemented OEM Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); +} + +/* + * Top-level OEM Service SMC handler. This handler will in turn dispatch + * calls to related SMC handler + */ +uintptr_t oem_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) +{ + /* + * Dispatch OEM calls to OEM Common handler and return its return value + */ + if (is_oem_fid(smc_fid)) { + return oem_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + switch (smc_fid) { + case OEM_SVC_CALL_COUNT: + /* + * Return the number of OEM Service Calls. + */ + SMC_RET1(handle, OEM_SVC_NUM_CALLS); + + case OEM_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, oem_svc_uid); + + case OEM_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, OEM_VERSION_MAJOR, OEM_VERSION_MINOR); + + default: + WARN("Unimplemented OEM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register OEM Service Calls as runtime service */ +DECLARE_RT_SVC( + oem_svc, + OEN_OEM_START, + OEN_OEM_END, + SMC_TYPE_FAST, + oem_svc_setup, + oem_svc_smc_handler +); diff --git a/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h new file mode 100644 index 0000000..76f7c24 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OEM_SVC_H +#define OEM_SVC_H + +/******************************************************************************* + * Defines for runtime services func ids + ******************************************************************************/ +/* + * Number of OEM calls (above) implemented. + */ +#define OEM_SVC_NUM_CALLS 3 + +/******************************************************************************* + * Defines for OEM Service queries + ******************************************************************************/ +/* 0x83000000 - 0x8300FEFF is OEM service calls */ +#define OEM_SVC_CALL_COUNT 0x8300ff00 +#define OEM_SVC_UID 0x8300ff01 +/* 0x8300ff02 is reserved */ +#define OEM_SVC_VERSION 0x8300ff03 +/* 0x8300ff04 - 0x8300FFFF is reserved for future expansion */ + +/* OEM Service Calls version numbers */ +#define OEM_VERSION_MAJOR 0x0 +#define OEM_VERSION_MINOR 0x1 + +/* The macros below are used to identify OEM calls from the SMC function ID */ +/* SMC32 ID range from 0x83000000 to 0x83000FFF */ +/* SMC64 ID range from 0xC3000000 to 0xC3000FFF */ +#define OEM_FID_MASK 0xf000u +#define OEM_FID_VALUE 0u +#define is_oem_fid(_fid) \ + (((_fid) & OEM_FID_MASK) == OEM_FID_VALUE) + +#define OEM_SVC_E_SUCCESS 0 +#define OEM_SVC_E_NOT_SUPPORTED -1 +#define OEM_SVC_E_INVALID_PARAMS -2 + +#endif /* OEM_SVC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c new file mode 100644 index 0000000..ae8d697 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "../drivers/arm/gic/v3/gicv3_private.h" +#include +#include +#include + +#include +#include +#include +#include +#include + +#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); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h new file mode 100644 index 0000000..c4ab44f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GIC_V3_H +#define MT_GIC_V3_H + +#include +#include + +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); + +#endif /* MT_GIC_V3_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c new file mode 100644 index 0000000..89977a5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c @@ -0,0 +1,298 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + *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, +}; + +void mt_gpio_init(void) +{ + gpio_init(&mtgpio_ops); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h new file mode 100644 index 0000000..bf51055 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_GPIO_COMMON_H +#define MT_GPIO_COMMON_H + +#include +#include + +#include + +/* 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; +}; + +void mt_gpio_init(void); +uintptr_t mt_gpio_find_reg_addr(uint32_t pin); +#endif /* MT_GPIO_COMMON_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c new file mode 100644 index 0000000..e3cfd46 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* 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, + ®_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/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c new file mode 100644 index 0000000..d9a79c4 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c new file mode 100644 index 0000000..cad12a0 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2019, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c new file mode 100644 index 0000000..124bc8f --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + +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/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h new file mode 100644 index 0000000..04726e3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2020, 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/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c new file mode 100644 index 0000000..0860885 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + +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; +} + +void mt_systimer_init(void) +{ + /* 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); +} diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h new file mode 100644 index 0000000..b353177 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h @@ -0,0 +1,35 @@ +/* + * 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 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); +void mt_systimer_init(void); + +#endif /* MT_TIMER_H */ diff --git a/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S new file mode 100644 index 0000000..7a946f9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S @@ -0,0 +1,163 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c new file mode 100644 index 0000000..b940eb3 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h new file mode 100644 index 0000000..ac8b94d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef UART_H +#define UART_H + +#include + +/* 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/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h new file mode 100644 index 0000000..da7c7a1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2015, 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/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c new file mode 100644 index 0000000..f3148fe --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h new file mode 100644 index 0000000..39759f1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_LP_RM_H +#define MT_LP_RM_H + +#include + +#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/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c new file mode 100644 index 0000000..9cf7144 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c @@ -0,0 +1,549 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h new file mode 100644 index 0000000..6e63bb8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h @@ -0,0 +1,122 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_MT_CIRQ_H +#define PLAT_MT_CIRQ_H + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c new file mode 100644 index 0000000..142b5c9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +struct atf_arg_t gteearg; + +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 (0 == (smc_fid & SMC_AARCH64_BIT)) { + *px1 = *px1 & SMC32_PARAM_MASK; + *px2 = *px2 & SMC32_PARAM_MASK; + *px3 = *px3 & SMC32_PARAM_MASK; + *px4 = *px4 & SMC32_PARAM_MASK; + } +} + +#if MTK_SIP_KERNEL_BOOT_ENABLE +static struct kernel_info k_info; + +static void save_kernel_info(uint64_t pc, + uint64_t r0, + uint64_t r1, + uint64_t k32_64) +{ + k_info.k32_64 = k32_64; + k_info.pc = pc; + + if (LINUX_KERNEL_32 == k32_64) { + /* for 32 bits kernel */ + k_info.r0 = 0; + /* machtype */ + k_info.r1 = r0; + /* tags */ + k_info.r2 = r1; + } else { + /* for 64 bits kernel */ + k_info.r0 = r0; + k_info.r1 = r1; + } +} + +uint64_t get_kernel_info_pc(void) +{ + return k_info.pc; +} + +uint64_t get_kernel_info_r0(void) +{ + return k_info.r0; +} + +uint64_t get_kernel_info_r1(void) +{ + return k_info.r1; +} + +uint64_t get_kernel_info_r2(void) +{ + return k_info.r2; +} + +void boot_to_kernel(uint64_t x1, uint64_t x2, uint64_t x3, uint64_t x4) +{ + static uint8_t kernel_boot_once_flag; + /* only support in booting flow */ + if (0 == kernel_boot_once_flag) { + kernel_boot_once_flag = 1; + + console_init(gteearg.atf_log_port, + UART_CLOCK, UART_BAUDRATE); + INFO("save kernel info\n"); + save_kernel_info(x1, x2, x3, x4); + bl31_prepare_kernel_entry(x4); + INFO("el3_exit\n"); + console_uninit(); + } +} +#endif + +uint32_t plat_get_spsr_for_bl33_entry(void) +{ + unsigned int mode; + uint32_t spsr; + unsigned int ee; + unsigned long daif; + + INFO("Secondary bootloader is AArch32\n"); + mode = MODE32_svc; + ee = 0; + /* + * TODO: Choose async. exception bits if HYP mode is not + * implemented according to the values of SCR.{AW, FW} bits + */ + daif = DAIF_ABT_BIT | DAIF_IRQ_BIT | DAIF_FIQ_BIT; + + spsr = SPSR_MODE32(mode, 0, ee, daif); + return spsr; +} + +/***************************************************************************** + * 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/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h new file mode 100644 index 0000000..919c173 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MTK_PLAT_COMMON_H +#define MTK_PLAT_COMMON_H + +#include + +#include +#include + +/******************************************************************************* + * Function and variable prototypes + ******************************************************************************/ +#define DEVINFO_SIZE 4 +#define LINUX_KERNEL_32 0 +#define SMC32_PARAM_MASK (0xFFFFFFFF) + +#define JEDEC_MTK_BKID U(4) +#define JEDEC_MTK_MFID U(0x26) + +struct atf_arg_t { + unsigned int atf_magic; + unsigned int tee_support; + unsigned int tee_entry; + unsigned int tee_boot_arg_addr; + unsigned int hwuid[4]; /* HW Unique id for t-base used */ + unsigned int HRID[2]; /* HW random id for t-base used */ + unsigned int atf_log_port; + unsigned int atf_log_baudrate; + unsigned int atf_log_buf_start; + unsigned int atf_log_buf_size; + unsigned int atf_irq_num; + unsigned int devinfo[DEVINFO_SIZE]; + unsigned int atf_aee_debug_buf_start; + unsigned int atf_aee_debug_buf_size; +}; + +struct kernel_info { + uint64_t pc; + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t k32_64; +}; + +struct mtk_bl_param_t { + uint64_t bootarg_loc; + uint64_t bootarg_size; + uint64_t bl33_start_addr; + uint64_t tee_info_addr; +}; + +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/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c new file mode 100644 index 0000000..dab0d45 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h new file mode 100644 index 0000000..74b17b6 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef MTK_SIP_SVC_H +#define MTK_SIP_SVC_H + +#include + +/* SMC function IDs for SiP Service queries */ +#define SIP_SVC_CALL_COUNT 0x8200ff00 +#define SIP_SVC_UID 0x8200ff01 +/* 0x8200ff02 is reserved */ +#define SIP_SVC_VERSION 0x8200ff03 + +/* Mediatek SiP Service Calls version numbers */ +#define MTK_SIP_SVC_VERSION_MAJOR 0x0 +#define MTK_SIP_SVC_VERSION_MINOR 0x1 + +#define SMC_AARCH64_BIT 0x40000000 + +/* Number of Mediatek SiP Calls implemented */ +#define MTK_COMMON_SIP_NUM_CALLS 4 + +/* Mediatek SiP Service Calls function IDs */ +#define MTK_SIP_SET_AUTHORIZED_SECURE_REG 0x82000001 + +/* For MTK SMC from Secure OS */ +/* 0x82000000 - 0x820000FF & 0xC2000000 - 0xC20000FF */ +#define MTK_SIP_KERNEL_BOOT_AARCH32 0x82000200 +#define MTK_SIP_KERNEL_BOOT_AARCH64 0xC2000200 + +/* VCORE */ +#define MTK_SIP_VCORE_CONTROL_ARCH32 0x82000506 +#define MTK_SIP_VCORE_CONTROL_ARCH64 0xC2000506 + +/* APUSYS SMC call */ +#define MTK_SIP_APUSYS_CONTROL_AARCH32 0x8200051E +#define MTK_SIP_APUSYS_CONTROL_AARCH64 0xC200051E + +/* 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 +}; + +/* + * 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/arm-trusted-firmware/plat/mediatek/common/params_setup.c b/arm-trusted-firmware/plat/mediatek/common/params_setup.c new file mode 100644 index 0000000..a9df13e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/common/plat_params.h b/arm-trusted-firmware/plat/mediatek/common/plat_params.h new file mode 100644 index 0000000..828c3dc --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S new file mode 100644 index 0000000..aaddb2b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S @@ -0,0 +1,148 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + + .globl plat_secondary_cold_boot_setup + .globl plat_report_exception + .globl platform_is_primary_cpu + .globl plat_crash_console_init + .globl plat_crash_console_putc + .globl plat_crash_console_flush + .globl platform_mem_init + + + .macro crash_ram_log + /* + * Check teearg->atf_log_buf_size. + * Exit if atf_log_buf_size equals 0 + */ + adr x2, ptr_atf_crash_flag + ldr x2, [x2] + /* exit if ptr_atf_crash_flag equals NULL */ + cbz x2, exit_putc + + /* + * set atf crash magic number + */ +1: + adr x2, ptr_atf_crash_flag + ldr x2, [x2] + mov_imm x1, 0xdead1abf + /* p_atf_log_ctrl->atf_crash_flag = 0xdead1abf */ + str w1, [x2] + /* can't use w3 return addr, w4, start of buffer addr */ + ldr w2, [x2] + cmp w2, w1 + b.ne 1b + + /* + * get cpu id + */ + mrs x1, mpidr_el1 + /* refer to platform_get_core_pos */ + and x2, x1, #MPIDR_CPU_MASK + and x1, x1, #MPIDR_CLUSTER_MASK + /* x1 = cpu id (cpu id = aff0 + aff1*4 ) */ + add x1, x2, x1, LSR #6 + + adr x2, ptr_atf_except_write_pos_per_cpu + ldr x2, [x2] + /* + * plus (cpu_id * 8)--> + * &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] + * x2 = &p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]; + */ + add x2, x2, x1, LSL # 3 + /* log write */ + /* w1 = p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] */ + ldr x1, [x2] + /* *x1 = w0--> + * *(p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id]) = c) + */ + strb w0, [x1] + /* w1++ */ + add x1, x1, #1 + /* p_atf_log_ctrl->atf_except_write_pos_per_cpu[cpu_id] = w1 */ + str x1, [x2] +exit_putc: + .endm + + /* ----------------------------------------------------- + * 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 + /* Do 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, #PLAT_PRIMARY_CPU + cset x0, eq + ret +endfunc platform_is_primary_cpu + + /* --------------------------------------------- + * 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, UART0_BASE + mov_imm x1, UART_CLOCK + mov_imm x2, UART_BAUDRATE + b console_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 + * --------------------------------------------- + */ +func plat_crash_console_putc + mov_imm x1, UART0_BASE + b console_core_putc + ret +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, UART0_BASE + b console_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 + ret +endfunc platform_mem_init + diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S b/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S new file mode 100644 index 0000000..3d881fc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +OUTPUT_FORMAT(PLATFORM_LINKER_FORMAT) +OUTPUT_ARCH(PLATFORM_LINKER_ARCH) +ENTRY(bl31_entrypoint) + + +MEMORY { + RAM (rwx): ORIGIN = BL31_BASE, LENGTH = BL31_TZRAM_SIZE + RAM2 (rwx): ORIGIN = TZRAM2_BASE, LENGTH = TZRAM2_SIZE +} + + +SECTIONS +{ + . = BL31_BASE; + + ASSERT(. == ALIGN(2048), + "vector base is not aligned on a 2K boundary.") + + __RO_START__ = .; + vector . : { + *(.vectors) + } >RAM + + ASSERT(. == ALIGN(PAGE_SIZE), + "BL31_BASE address is not aligned on a page boundary.") + + ro . : { + *bl31_entrypoint.o(.text*) + *(.text*) + *(.rodata*) + + RODATA_COMMON + + __RO_END_UNALIGNED__ = .; + /* + * Memory page(s) mapped to this section will be marked as read-only, + * executable. No RW data from the next section must creep in. + * Ensure the rest of the current memory page is unused. + */ + . = ALIGN(PAGE_SIZE); + __RO_END__ = .; + } >RAM + + ASSERT(__CPU_OPS_END__ > __CPU_OPS_START__, + "cpu_ops not defined for this platform.") + + /* + * Define a linker symbol to mark start of the RW memory area for this + * image. + */ + __RW_START__ = . ; + + DATA_SECTION >RAM + +#ifdef BL31_PROGBITS_LIMIT + ASSERT(. <= BL31_PROGBITS_LIMIT, "BL3-1 progbits has exceeded its limit.") +#endif + + STACK_SECTION >RAM + BSS_SECTION >RAM + __RW_END__ = __BSS_END__; + + ASSERT(. <= BL31_LIMIT, "BL3-1 image has exceeded its limit.") + + XLAT_TABLE_SECTION >RAM2 + +#if USE_COHERENT_MEM + /* + * 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 (NOLOAD) : ALIGN(PAGE_SIZE) { + __COHERENT_RAM_START__ = .; + /* + * 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_END_UNALIGNED__ = .; + /* + * 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. + */ + . = ALIGN(PAGE_SIZE); + __COHERENT_RAM_END__ = .; + } >RAM2 +#endif + + /* + * Define a linker symbol to mark end of the RW memory area for this + * image. + */ + __BL31_END__ = .; + + __BSS_SIZE__ = SIZEOF(.bss); +#if USE_COHERENT_MEM + __COHERENT_RAM_UNALIGNED_SIZE__ = + __COHERENT_RAM_END_UNALIGNED__ - __COHERENT_RAM_START__; +#endif + + ASSERT(. <= TZRAM2_LIMIT, "TZRAM2 image has exceeded its limit.") +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c new file mode 100644 index 0000000..2051fe7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c @@ -0,0 +1,449 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Declarations of linker defined symbols which will help us find the layout + * of trusted SRAM + ******************************************************************************/ +/* + * The next 2 constants identify the extents of the code & RO data region. + * These addresses are used by the MMU setup code and therefore they must be + * page-aligned. It is the responsibility of the linker script to ensure that + * __RO_START__ and __RO_END__ linker symbols refer to page-aligned addresses. + */ +IMPORT_SYM(unsigned long, __RO_START__, BL31_RO_BASE); +IMPORT_SYM(unsigned long, __RO_END__, BL31_RO_LIMIT); + +/* + * 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; + +static const int cci_map[] = { + PLAT_MT_CCI_CLUSTER0_SL_IFACE_IX, + PLAT_MT_CCI_CLUSTER1_SL_IFACE_IX +}; + +static uint32_t cci_map_length = ARRAY_SIZE(cci_map); + +/* Table of regions to map using the MMU. */ +static 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(RAM_CONSOLE_BASE & ~(PAGE_SIZE_MASK), RAM_CONSOLE_SIZE, + MT_DEVICE | MT_RW | MT_NS), + { 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, cci_map_length); +} + +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())); +} + + +static void platform_setup_cpu(void) +{ + /* setup big cores */ + mmio_write_32((uintptr_t)&mt6795_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)&mt6795_mcucfg->mp1_miscdbg, MP1_AINACTS); + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_clkenm_div, + MP1_SW_CG_GEN); + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_rst_ctl, + MP1_L2RSTDISABLE); + + /* set big cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_cpucfg, + MP1_CPUCFG_64BIT); + + /* set LITTLE cores arm64 boot mode */ + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_rv_addr[0].rv_addr_hw, + MP0_CPUCFG_64BIT); +} + +/******************************************************************************* + * 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 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) +{ + struct mtk_bl_param_t *pmtk_bl_param = (struct mtk_bl_param_t *)arg0; + struct atf_arg_t *teearg; + unsigned long long normal_base; + unsigned long long atf_base; + + assert(pmtk_bl_param != NULL); + /* + * Mediatek preloader(i.e, BL2) is in 32 bit state, high 32bits + * of 64 bit GP registers are UNKNOWN if CPU warm reset from 32 bit + * to 64 bit state. So we need to clear high 32bit, + * which may be random value. + */ + pmtk_bl_param = + (struct mtk_bl_param_t *)((uint64_t)pmtk_bl_param & 0x00000000ffffffff); + + teearg = (struct atf_arg_t *)pmtk_bl_param->tee_info_addr; + + console_init(teearg->atf_log_port, UART_CLOCK, UART_BAUDRATE); + memcpy((void *)>eearg, (void *)teearg, sizeof(struct atf_arg_t)); + + normal_base = 0; + /* in ATF boot time, timer for cntpct_el0 is not initialized + * so it will not count now. + */ + atf_base = read_cntpct_el0(); + sched_clock_init(normal_base, atf_base); + + VERBOSE("bl31_setup\n"); + + /* Populate entry point information for BL3-2 and BL3-3 */ + 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; + + SET_PARAM_HEAD(&bl33_image_ep_info, + PARAM_EP, + VERSION_1, + 0); + /* + * Tell BL3-1 where the non-trusted software image + * is located and the entry state information + */ + /* BL33_START_ADDRESS */ + bl33_image_ep_info.pc = pmtk_bl_param->bl33_start_addr; + bl33_image_ep_info.spsr = plat_get_spsr_for_bl33_entry(); + bl33_image_ep_info.args.arg4 = pmtk_bl_param->bootarg_loc; + bl33_image_ep_info.args.arg5 = pmtk_bl_param->bootarg_size; + SET_SECURITY_STATE(bl33_image_ep_info.h.attr, NON_SECURE); +} +/******************************************************************************* + * Perform any BL3-1 platform setup code + ******************************************************************************/ + +void bl31_platform_setup(void) +{ + platform_setup_cpu(); + + generic_delay_timer_init(); + + plat_mt_gic_driver_init(); + /* Initialize the gic cpu and distributor interfaces */ + plat_mt_gic_init(); + + /* Topologies are best known to the platform. */ + mt_setup_topology(); +} +/******************************************************************************* + * Perform the very early platform specific architectural setup here. At the + * moment this is only intializes the mmu in a quick and dirty way. + * Init MTK propiartary log buffer control field. + ******************************************************************************/ +void bl31_plat_arch_setup(void) +{ + /* Enable non-secure access to CCI-400 registers */ + mmio_write_32(CCI400_BASE + CCI_SEC_ACCESS_OFFSET, 0x1); + + plat_cci_init(); + plat_cci_enable(); + + if (gteearg.atf_log_buf_size != 0) { + INFO("mmap atf buffer : 0x%x, 0x%x\n\r", + gteearg.atf_log_buf_start, + gteearg.atf_log_buf_size); + + mmap_add_region( + gteearg.atf_log_buf_start & + ~(PAGE_SIZE_2MB_MASK), + gteearg.atf_log_buf_start & + ~(PAGE_SIZE_2MB_MASK), + PAGE_SIZE_2MB, + MT_DEVICE | MT_RW | MT_NS); + + INFO("mmap atf buffer (force 2MB aligned):0x%x, 0x%x\n", + (gteearg.atf_log_buf_start & ~(PAGE_SIZE_2MB_MASK)), + PAGE_SIZE_2MB); + } + /* + * add TZRAM_BASE to memory map + * then set RO and COHERENT to different attribute + */ + plat_configure_mmu_el3( + (TZRAM_BASE & ~(PAGE_SIZE_MASK)), + (TZRAM_SIZE & ~(PAGE_SIZE_MASK)), + (BL31_RO_BASE & ~(PAGE_SIZE_MASK)), + BL31_RO_LIMIT, + BL_COHERENT_RAM_BASE, + BL_COHERENT_RAM_END); + /* Initialize for ATF log buffer */ + if (gteearg.atf_log_buf_size != 0) { + gteearg.atf_aee_debug_buf_size = ATF_AEE_BUFFER_SIZE; + gteearg.atf_aee_debug_buf_start = + gteearg.atf_log_buf_start + + gteearg.atf_log_buf_size - ATF_AEE_BUFFER_SIZE; + INFO("ATF log service is registered (0x%x, aee:0x%x)\n", + gteearg.atf_log_buf_start, + gteearg.atf_aee_debug_buf_start); + } else{ + gteearg.atf_aee_debug_buf_size = 0; + gteearg.atf_aee_debug_buf_start = 0; + } + + /* Platform code before bl31_main */ + /* compatible to the earlier chipset */ + + /* Show to ATF log buffer & UART */ + INFO("BL3-1: %s\n", version_string); + INFO("BL3-1: %s\n", build_message); + +} +#if 0 +/* MTK Define */ +#define ACTLR_CPUECTLR_BIT (1 << 1) + +void enable_ns_access_to_cpuectlr(void) +{ + unsigned int next_actlr; + + + /* ACTLR_EL1 do not implement CUPECTLR */ + next_actlr = read_actlr_el2(); + next_actlr |= ACTLR_CPUECTLR_BIT; + write_actlr_el2(next_actlr); + + next_actlr = read_actlr_el3(); + next_actlr |= ACTLR_CPUECTLR_BIT; + write_actlr_el3(next_actlr); +} +#endif +/******************************************************************************* + * This function prepare boot argument for 64 bit kernel entry + ******************************************************************************/ +static entry_point_info_t *bl31_plat_get_next_kernel64_ep_info(void) +{ + entry_point_info_t *next_image_info; + unsigned int mode; + + mode = 0; + + /* Kernel image is always non-secured */ + next_image_info = &bl33_image_ep_info; + + /* Figure out what mode we enter the non-secure world in */ + if (el_implemented(2) != EL_IMPL_NONE) { + INFO("Kernel_EL2\n"); + mode = MODE_EL2; + } else{ + INFO("Kernel_EL1\n"); + mode = MODE_EL1; + } + + INFO("Kernel is 64Bit\n"); + next_image_info->spsr = + SPSR_64(mode, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + next_image_info->pc = get_kernel_info_pc(); + next_image_info->args.arg0 = get_kernel_info_r0(); + next_image_info->args.arg1 = get_kernel_info_r1(); + + INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx\n", + next_image_info->pc, + next_image_info->args.arg0, + next_image_info->args.arg1); + + + SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); + + /* 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; +} + +/******************************************************************************* + * This function prepare boot argument for 32 bit kernel entry + ******************************************************************************/ +static entry_point_info_t *bl31_plat_get_next_kernel32_ep_info(void) +{ + entry_point_info_t *next_image_info; + unsigned int mode; + + mode = 0; + + /* Kernel image is always non-secured */ + next_image_info = &bl33_image_ep_info; + + /* Figure out what mode we enter the non-secure world in */ + mode = MODE32_hyp; + /* + * TODO: Consider the possibility of specifying the SPSR in + * the FIP ToC and allowing the platform to have a say as + * well. + */ + + INFO("Kernel is 32Bit\n"); + 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->pc = get_kernel_info_pc(); + next_image_info->args.arg0 = get_kernel_info_r0(); + next_image_info->args.arg1 = get_kernel_info_r1(); + next_image_info->args.arg2 = get_kernel_info_r2(); + + INFO("pc=0x%lx, r0=0x%lx, r1=0x%lx, r2=0x%lx\n", + next_image_info->pc, + next_image_info->args.arg0, + next_image_info->args.arg1, + next_image_info->args.arg2); + + + SET_SECURITY_STATE(next_image_info->h.attr, NON_SECURE); + + /* 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; +} + +/******************************************************************************* + * This function prepare boot argument for kernel entrypoint + ******************************************************************************/ +void bl31_prepare_kernel_entry(uint64_t k32_64) +{ + entry_point_info_t *next_image_info; + uint32_t image_type; + + /* Determine which image to execute next */ + /* image_type = bl31_get_next_image_type(); */ + image_type = NON_SECURE; + + /* Program EL3 registers to enable entry into the next EL */ + if (k32_64 == 0) + next_image_info = bl31_plat_get_next_kernel32_ep_info(); + else + next_image_info = bl31_plat_get_next_kernel64_ep_info(); + + assert(next_image_info); + assert(image_type == GET_SECURITY_STATE(next_image_info->h.attr)); + + INFO("BL3-1: Preparing for EL3 exit to %s world, Kernel\n", + (image_type == SECURE) ? "secure" : "normal"); + INFO("BL3-1: Next image address = 0x%llx\n", + (unsigned long long) next_image_info->pc); + INFO("BL3-1: Next image spsr = 0x%x\n", next_image_info->spsr); + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(image_type); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c new file mode 100644 index 0000000..3696f8e --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#include + +#define CPUXGPT_BASE 0x10200000 +#define INDEX_BASE (CPUXGPT_BASE+0x0674) +#define CTL_BASE (CPUXGPT_BASE+0x0670) + +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; + + cval = (((read_cntpct_el0() - atf_time_base)*1000)/ + SYS_COUNTER_FREQ_IN_MHZ) + normal_time_base; + return cval; +} + +/* + * Return: 0 - Trying to disable the CPUXGPT control bit, + * and not allowed to disable it. + * Return: 1 - reg_addr is not realted to disable the control bit. + */ +unsigned char check_cpuxgpt_write_permission(unsigned int reg_addr, + unsigned int reg_value) +{ + unsigned int idx; + unsigned int ctl_val; + + if (reg_addr == CTL_BASE) { + idx = mmio_read_32(INDEX_BASE); + + /* idx 0: CPUXGPT system control */ + if (idx == 0) { + ctl_val = mmio_read_32(CTL_BASE); + if (ctl_val & 1) { + /* + * if enable bit already set, + * then bit 0 is not allow to set as 0 + */ + if (!(reg_value & 1)) + return 0; + } + } + } + return 1; +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h new file mode 100644 index 0000000..84df081 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MT_CPUXGPT_H +#define MT_CPUXGPT_H + +/* REG */ +#define INDEX_CTL_REG 0x000 +#define INDEX_STA_REG 0x004 +#define INDEX_CNT_L_INIT 0x008 +#define INDEX_CNT_H_INIT 0x00C + +/* CTL_REG SET */ +#define EN_CPUXGPT 0x01 +#define EN_AHLT_DEBUG 0x02 +#define CLK_DIV1 (0x1 << 8) +#define CLK_DIV2 (0x2 << 8) +#define CLK_DIV4 (0x4 << 8) +#define CLK_DIV_MASK (~(0x7<<8)) + +void generic_timer_backup(void); +void sched_clock_init(uint64_t normal_base, uint64_t atf_base); +uint64_t sched_clock(void); + +#endif /* MT_CPUXGPT_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h new file mode 100644 index 0000000..21c5394 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h @@ -0,0 +1,155 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MCUCFG_H +#define MCUCFG_H + +#include + +#include + +struct mt6795_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 mt6795_mcucfg_regs *const mt6795_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 +}; + +#endif /* MCUCFG_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S new file mode 100644 index 0000000..d198fdc --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +.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_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: + .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, (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/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h new file mode 100644 index 0000000..f7450ca --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include + +#include + +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_mt_gic.c */ +void plat_mt_gic_init(void); + +/* Declarations for plat_topology.c */ +int mt_setup_topology(void); +void plat_delay_timer_init(void); + +void plat_mt_gic_driver_init(void); +void plat_mt_gic_init(void); +void plat_mt_gic_cpuif_enable(void); +void plat_mt_gic_cpuif_disable(void); +void plat_mt_gic_pcpu_init(void); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h new file mode 100644 index 0000000..b9a1363 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h @@ -0,0 +1,15 @@ +/* + * 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 0 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h new file mode 100644 index 0000000..b353a3d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h @@ -0,0 +1,238 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +#define PLAT_PRIMARY_CPU 0x0 + +/* Special value used to verify platform parameters from BL2 to BL3-1 */ +#define MT_BL31_PLAT_PARAM_VAL 0x0f1e2d3c4b5a6978ULL + +#define IO_PHYS (0x10000000) +#define INFRACFG_AO_BASE (IO_PHYS + 0x1000) +#define MCUCFG_BASE (IO_PHYS + 0x200000) +#define PERI_BASE (IO_PHYS + 0x1000000) + + +#define GPIO_BASE (IO_PHYS + 0x370000) +#define SPM_BASE (IO_PHYS + 0x6000) +#define RGU_BASE (MCUCFG_BASE + 0x11000) +#define PMIC_WRAP_BASE (IO_PHYS + 0x10000) + +#define TRNG_base (MCUCFG_BASE + 0x230000) +#define MT_GIC_BASE (0x10220000) +#define MCU_SYS_SIZE (0x700000) +#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 (PERI_BASE) +#define MTK_DEV_RNG1_SIZE 0x4000000 + +/******************************************************************************* + * UART related constants + ******************************************************************************/ +#define UART0_BASE (PERI_BASE + 0x2000) + +#define UART_BAUDRATE (921600) +#define UART_CLOCK (26000000) + +/******************************************************************************* + * System counter frequency related constants + ******************************************************************************/ +#define SYS_COUNTER_FREQ_IN_TICKS 13000000 +#define SYS_COUNTER_FREQ_IN_MHZ (SYS_COUNTER_FREQ_IN_TICKS/1000000) + +/******************************************************************************* + * 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 (MT_GIC_BASE + 0x200000) +#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 + +/******************************************************************************* + * WDT Registers + ******************************************************************************/ +#define MTK_WDT_BASE (RGU_BASE) +#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_DEBUG_CTL (MTK_WDT_BASE+0x0040) + +/*WDT_STATUS*/ +#define MTK_WDT_STATUS_HWWDT_RST (0x80000000) +#define MTK_WDT_STATUS_SWWDT_RST (0x40000000) +#define MTK_WDT_STATUS_IRQWDT_RST (0x20000000) +#define MTK_WDT_STATUS_DEBUGWDT_RST (0x00080000) +#define MTK_WDT_STATUS_SPMWDT_RST (0x0002) +#define MTK_WDT_STATUS_SPM_THERMAL_RST (0x0001) +#define MTK_WDT_STATUS_THERMAL_DIRECT_RST (1<<18) +#define MTK_WDT_STATUS_SECURITY_RST (1<<28) + +#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) + +/* 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 MT_IRQ_SEC_SGI_5 + +/******************************************************************************* + * 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 PLAT_MAX_PWR_LVL U(2) /* MPIDR_AFFLVL2 */ + +#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) + +/******************************************************************************* + * Platform memory map related constants + ******************************************************************************/ +/* ATF Argument */ +#define ATF_ARG_SIZE (0x800) + +/* TF txet, ro, rw, internal SRAM, Size: release: 80KB, debug: 92KB */ +#define TZRAM_BASE (0x110000) +#if DEBUG +#define TZRAM_SIZE (0x1C400) +#else +#define TZRAM_SIZE (0x1C400) +#endif +#define TZRAM2_BASE 0x00100000 +#define TZRAM2_SIZE 0xDC00 +#define TZRAM2_LIMIT (TZRAM2_BASE + TZRAM2_SIZE) + +#define RAM_CONSOLE_BASE 0x0012D000 +#define RAM_CONSOLE_SIZE 0x00001000 +/******************************************************************************* + * 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 BSS1_STACK_LIMIT (TZRAM_BASE + TZRAM_SIZE) +#define BL31_TZRAM_SIZE (TZRAM_SIZE - ATF_ARG_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 7 +#define MAX_MMAP_REGIONS 16 + + +/******************************************************************************* + * CCI-400 related constants + ******************************************************************************/ +#define CCI400_BASE 0x10390000 +#define CCI400_SL_IFACE_CLUSTER0 4 +#define CCI400_SL_IFACE_CLUSTER1 3 +#define CCI400_SL_IFACE_INDEX(mpidr) (mpidr & MPIDR_CLUSTER_MASK ? \ + CCI400_SL_IFACE_CLUSTER1 : \ + CCI400_SL_IFACE_CLUSTER0) +#define CCI_SEC_ACCESS_OFFSET (0x8) + + +/******************************************************************************* + * 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 BL32_BASE (0x0) + +/* + * Load address of BL3-3 for this platform port + */ +#define LK_SIZE_LIMIT (0x100000) +#define PLAT_MTK_NS_IMAGE_OFFSET (0x41E00000) +/* 16KB */ +#define ATF_AEE_BUFFER_SIZE (0x4000) +#define PAGE_SIZE_2MB_MASK (PAGE_SIZE_2MB - 1) +#define IS_PAGE_2MB_ALIGNED(addr) (((addr) & PAGE_SIZE_2MB_MASK) == 0) +#define PAGE_SIZE_2MB (1 << PAGE_SIZE_2MB_SHIFT) +#define PAGE_SIZE_2MB_SHIFT TWO_MB_SHIFT + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h new file mode 100644 index 0000000..8c98dbd --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2016, 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/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h new file mode 100644 index 0000000..625418a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2016, 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/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h b/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h new file mode 100644 index 0000000..5227e1d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2016, 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 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_SYSPWREQ (1 << 24) +#define WAKE_SRC_SEJ (1 << 27) +#define WAKE_SRC_ALL_MD32 (1 << 28) +#define WAKE_SRC_CPU_IRQ (1 << 29) + +#endif /* SPM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c new file mode 100644 index 0000000..965b653 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c new file mode 100644 index 0000000..20cb26d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +static const interrupt_prop_t g0_interrupt_props[] = { + INTR_PROP_DESC(FIQ_SMP_CALL_SGI, GIC_HIGHEST_SEC_PRIORITY, + GICV2_INTR_GROUP0, GIC_INTR_CFG_LEVEL), +}; + +gicv2_driver_data_t arm_gic_data = { + .gicd_base = BASE_GICD_BASE, + .gicc_base = BASE_GICC_BASE, + .interrupt_props = g0_interrupt_props, + .interrupt_props_num = ARRAY_SIZE(g0_interrupt_props), +}; + +void plat_mt_gic_driver_init(void) +{ + gicv2_driver_init(&arm_gic_data); +} + +void plat_mt_gic_init(void) +{ + gicv2_distif_init(); + gicv2_pcpu_distif_init(); + gicv2_cpuif_enable(); +} + +void plat_mt_gic_cpuif_enable(void) +{ + gicv2_cpuif_enable(); +} + +void plat_mt_gic_cpuif_disable(void) +{ + gicv2_cpuif_disable(); +} + +void plat_mt_gic_pcpu_init(void) +{ + gicv2_pcpu_distif_init(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c new file mode 100644 index 0000000..0dfbd18 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c @@ -0,0 +1,473 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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 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_cntp_ctl_el0(); + + write_cntp_ctl_el0(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); +} + +/******************************************************************************* +* Private function which is used to determine if any platform actions +* should be performed for the specified affinity instance given its +* state. Nothing needs to be done if the 'state' is not off or if this is not +* the highest affinity level which will enter the 'state'. +*******************************************************************************/ +static int32_t plat_do_plat_actions(unsigned int afflvl, unsigned int state) +{ + unsigned int max_phys_off_afflvl; + + assert(afflvl <= MPIDR_AFFLVL2); + + if (state != PSCI_STATE_OFF) + return -EAGAIN; + + /* + * Find the highest affinity level which will be suspended and postpone + * all the platform specific actions until that level is hit. + */ + max_phys_off_afflvl = psci_get_max_phys_off_afflvl(); + assert(max_phys_off_afflvl != PSCI_INVALID_DATA); + if (afflvl != max_phys_off_afflvl) + return -EAGAIN; + + return 0; +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to enter + * standby. + ******************************************************************************/ +static void plat_affinst_standby(unsigned int power_state) +{ + unsigned int target_afflvl; + + /* Sanity check the requested state */ + target_afflvl = psci_get_pstate_afflvl(power_state); + + /* + * It's possible to enter standby only on affinity level 0 i.e. a cpu + * on the MTK_platform. Ignore any other affinity level. + */ + if (target_afflvl == MPIDR_AFFLVL0) { + /* + * Enter standby state. dsb is good practice before using wfi + * to enter low power states. + */ + dsb(); + wfi(); + } +} + +/******************************************************************************* + * MTK_platform handler called when an affinity instance is about to be turned + * on. The level and mpidr determine the affinity instance. + ******************************************************************************/ +static int plat_affinst_on(unsigned long mpidr, + unsigned long sec_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + int rc = PSCI_E_SUCCESS; + unsigned long cpu_id; + unsigned long cluster_id; + uintptr_t rv; + + /* + * It's possible to turn on only affinity level 0 i.e. a cpu + * on the MTK_platform. Ignore any other affinity level. + */ + if (afflvl != MPIDR_AFFLVL0) + return rc; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, sec_entrypoint); + INFO("mt_on[%ld:%ld], entry %x\n", + cluster_id, cpu_id, mmio_read_32(rv)); + + 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_affinst_off(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + /* Prevent interrupts from spuriously waking up this cpu */ + plat_mt_gic_cpuif_disable(); + + trace_power_flow(mpidr, CPU_DOWN); + + if (afflvl != MPIDR_AFFLVL0) { + /* 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_affinst_suspend(unsigned long sec_entrypoint, + unsigned int afflvl, + unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + unsigned long cluster_id; + unsigned long cpu_id; + uintptr_t rv; + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + cpu_id = mpidr & MPIDR_CPU_MASK; + cluster_id = mpidr & MPIDR_CLUSTER_MASK; + + if (cluster_id) + rv = (uintptr_t)&mt6795_mcucfg->mp1_rv_addr[cpu_id].rv_addr_lw; + else + rv = (uintptr_t)&mt6795_mcucfg->mp0_rv_addr[cpu_id].rv_addr_lw; + + mmio_write_32(rv, sec_entrypoint); + + if (afflvl >= MPIDR_AFFLVL0) + mt_platform_save_context(mpidr); + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + /* Disable coherency if this cluster is to be turned off */ + plat_cci_disable(); + disable_scu(mpidr); + + trace_power_flow(mpidr, CLUSTER_SUSPEND); + } + + if (afflvl >= MPIDR_AFFLVL2) { + /* Prevent interrupts from spuriously waking up this cpu */ + plat_mt_gic_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. + ******************************************************************************/ +static void plat_affinst_on_finish(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + enable_scu(mpidr); + + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + trace_power_flow(mpidr, CLUSTER_UP); + } + + /* Enable the gic cpu interface */ + plat_mt_gic_cpuif_enable(); + plat_mt_gic_pcpu_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_affinst_suspend_finish(unsigned int afflvl, unsigned int state) +{ + unsigned long mpidr = read_mpidr_el1(); + + /* Determine if any platform actions need to be executed. */ + if (plat_do_plat_actions(afflvl, state) == -EAGAIN) + return; + + if (afflvl >= MPIDR_AFFLVL2) { + /* Enable the gic cpu interface */ + plat_mt_gic_init(); + plat_mt_gic_cpuif_enable(); + } + + /* Perform the common cluster specific operations */ + if (afflvl >= MPIDR_AFFLVL1) { + enable_scu(mpidr); + + /* Enable coherency if this cluster was off */ + plat_cci_enable(); + trace_power_flow(mpidr, CLUSTER_UP); + } + + if (afflvl >= MPIDR_AFFLVL0) + mt_platform_restore_context(mpidr); + + plat_mt_gic_pcpu_init(); +} + +static unsigned int plat_get_sys_suspend_power_state(void) +{ + /* StateID: 0, StateType: 1(power down), PowerLevel: 2(system) */ + return psci_make_powerstate(0, 1, 2); +} + +/******************************************************************************* + * MTK handlers to shutdown/reboot the system + ******************************************************************************/ +static void __dead2 plat_system_off(void) +{ + INFO("MTK System Off\n"); + 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"); + + mmio_clrbits_32(MTK_WDT_BASE, + (MTK_WDT_MODE_DUAL_MODE | MTK_WDT_MODE_IRQ)); + mmio_setbits_32(MTK_WDT_BASE, (MTK_WDT_MODE_KEY | MTK_WDT_MODE_EXTEN)); + mmio_setbits_32(MTK_WDT_SWRST, MTK_WDT_SWRST_KEY); + + wfi(); + ERROR("MTK System Reset: operation not handled.\n"); + panic(); +} + +/******************************************************************************* + * Export the platform handlers to enable psci to invoke them + ******************************************************************************/ +static const plat_pm_ops_t plat_plat_pm_ops = { + .affinst_standby = plat_affinst_standby, + .affinst_on = plat_affinst_on, + .affinst_off = plat_affinst_off, + .affinst_suspend = plat_affinst_suspend, + .affinst_on_finish = plat_affinst_on_finish, + .affinst_suspend_finish = plat_affinst_suspend_finish, + .system_off = plat_system_off, + .system_reset = plat_system_reset, + .get_sys_suspend_power_state = plat_get_sys_suspend_power_state, +}; + +/******************************************************************************* + * Export the platform specific power ops & initialize the mtk_platform power + * controller + ******************************************************************************/ +int platform_setup_pm(const plat_pm_ops_t **plat_ops) +{ + *plat_ops = &plat_plat_pm_ops; + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c new file mode 100644 index 0000000..7425d26 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +unsigned int plat_get_aff_count(unsigned int aff_lvl, unsigned long mpidr) +{ + /* Report 1 (absent) instance at levels higher that the cluster level */ + if (aff_lvl > MPIDR_AFFLVL1) + return PLATFORM_SYSTEM_COUNT; + + if (aff_lvl == MPIDR_AFFLVL1) + return PLATFORM_CLUSTER_COUNT; + + return mpidr & 0x100 ? PLATFORM_CLUSTER1_CORE_COUNT : + PLATFORM_CLUSTER0_CORE_COUNT; +} + +unsigned int plat_get_aff_state(unsigned int aff_lvl, unsigned long mpidr) +{ + return aff_lvl <= MPIDR_AFFLVL2 ? PSCI_AFF_PRESENT : PSCI_AFF_ABSENT; +} + +int mt_setup_topology(void) +{ + /* [TODO] Make topology configurable via SCC */ + return 0; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk b/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk new file mode 100644 index 0000000..4ab692d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/platform.mk @@ -0,0 +1,67 @@ +# +# Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MTK_PLAT := plat/mediatek +MTK_PLAT_SOC := ${MTK_PLAT}/${PLAT} + +# Add OEM customized codes +OEMS := true +MTK_SIP_KERNEL_BOOT_ENABLE := 1 + + +ifneq (${OEMS},none) + OEMS_INCLUDES := -I${MTK_PLAT}/common/custom/ + OEMS_SOURCES := ${MTK_PLAT}/common/custom/oem_svc.c +endif + +PLAT_INCLUDES := -I${MTK_PLAT}/common/ \ + -I${MTK_PLAT}/common/drivers/uart \ + -I${MTK_PLAT_SOC}/ \ + -I${MTK_PLAT_SOC}/drivers/timer/ \ + -I${MTK_PLAT_SOC}/include/ \ + -Iinclude/plat/arm/common/ \ + ${OEMS_INCLUDES} + +PLAT_BL_COMMON_SOURCES := lib/xlat_tables/aarch64/xlat_tables.c \ + lib/xlat_tables/xlat_tables_common.c \ + plat/common/plat_gic.c + +BL31_SOURCES += drivers/arm/cci/cci.c \ + drivers/delay_timer/generic_delay_timer.c \ + 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 \ + drivers/console/aarch64/console.S \ + drivers/delay_timer/delay_timer.c \ + lib/cpus/aarch64/cortex_a53.S \ + ${MTK_PLAT_SOC}/bl31_plat_setup.c \ + ${MTK_PLAT_SOC}/plat_mt_gic.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/drivers/uart/8250_console.S \ + ${MTK_PLAT_SOC}/aarch64/plat_helpers.S \ + ${MTK_PLAT_SOC}/drivers/timer/mt_cpuxgpt.c \ + ${MTK_PLAT_SOC}/plat_delay_timer.c \ + ${MTK_PLAT_SOC}/plat_pm.c \ + ${MTK_PLAT_SOC}/plat_topology.c \ + ${MTK_PLAT_SOC}/power_tracer.c \ + ${MTK_PLAT_SOC}/scu.c \ + ${OEMS_SOURCES} + +# Enable workarounds for selected Cortex-A53 erratas. +ERRATA_A53_826319 := 1 +ERRATA_A53_836870 := 1 + +WORKAROUND_CVE_2017_5715 := 0 + +# indicate the reset vector address can be programmed +PROGRAMMABLE_RESET_ADDRESS := 1 + +$(eval $(call add_define,MTK_SIP_KERNEL_BOOT_ENABLE)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c b/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c new file mode 100644 index 0000000..64d086d --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#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/arm-trusted-firmware/plat/mediatek/mt6795/scu.c b/arm-trusted-firmware/plat/mediatek/mt6795/scu.c new file mode 100644 index 0000000..3b74527 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt6795/scu.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +void disable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_setbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} + +void enable_scu(unsigned long mpidr) +{ + if (mpidr & MPIDR_CLUSTER_MASK) + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp1_miscdbg, + MP1_ACINACTM); + else + mmio_clrbits_32((uintptr_t)&mt6795_mcucfg->mp0_axi_config, + MP0_ACINACTM); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S new file mode 100644 index 0000000..095dfc5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c new file mode 100644 index 0000000..a2dbe3e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c new file mode 100644 index 0000000..bd7d0b0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c new file mode 100644 index 0000000..bfb3082 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h new file mode 100644 index 0000000..1a691a6 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c new file mode 100644 index 0000000..452ac22 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h new file mode 100644 index 0000000..1e58027 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..0dffc23 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c new file mode 100644 index 0000000..587886c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h new file mode 100644 index 0000000..f60a4c1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c new file mode 100644 index 0000000..1caab3b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h new file mode 100644 index 0000000..0c05410 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c new file mode 100644 index 0000000..b2b9ada --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h new file mode 100644 index 0000000..00849a2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c new file mode 100644 index 0000000..ea5f2bb --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h new file mode 100644 index 0000000..7f3f96e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c new file mode 100644 index 0000000..838455d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h new file mode 100644 index 0000000..b00faa9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c new file mode 100644 index 0000000..174a24d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h new file mode 100644 index 0000000..8c0fe83 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c new file mode 100644 index 0000000..40f57ee --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h b/arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h new file mode 100644 index 0000000..7262a57 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h new file mode 100644 index 0000000..dedbc08 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h new file mode 100644 index 0000000..378b4da --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S new file mode 100644 index 0000000..ac9fb16 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +.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/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h new file mode 100644 index 0000000..cd92d34 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h new file mode 100644 index 0000000..ce9951a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h new file mode 100644 index 0000000..d340422 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h new file mode 100644 index 0000000..195366d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h new file mode 100644 index 0000000..b1e9424 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c new file mode 100644 index 0000000..80b9010 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c new file mode 100644 index 0000000..e72a343 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include /* generic_timer_backup() */ +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c new file mode 100644 index 0000000..da9b91d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c new file mode 100644 index 0000000..23e7d2d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk new file mode 100644 index 0000000..f62802c --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8173/platform.mk @@ -0,0 +1,74 @@ +# +# Copyright (c) 2015-2017, 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/ \ + -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/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.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/arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c b/arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c new file mode 100644 index 0000000..d1fcf9f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8173/scu.c b/arm-trusted-firmware/plat/mediatek/mt8173/scu.c new file mode 100644 index 0000000..2524d72 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S new file mode 100644 index 0000000..5c39633 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c new file mode 100644 index 0000000..31d1339 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c new file mode 100644 index 0000000..7dac8a4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c new file mode 100644 index 0000000..9d76aa5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h new file mode 100644 index 0000000..042a8ff --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..56d2ce2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..b67ea56 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..61aaeef --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + *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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..9461c54 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h new file mode 100644 index 0000000..4e1fd2b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c new file mode 100644 index 0000000..29eebcb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h new file mode 100644 index 0000000..9a40df1 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c new file mode 100644 index 0000000..cbe7f0a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h new file mode 100644 index 0000000..863e7da --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c new file mode 100644 index 0000000..b0f898e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h new file mode 100644 index 0000000..f19f9f6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..679c5e4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c new file mode 100644 index 0000000..a821c1b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h new file mode 100644 index 0000000..66686b4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c new file mode 100644 index 0000000..d6d2344 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h new file mode 100644 index 0000000..b2e83dc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c new file mode 100644 index 0000000..ce85272 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h new file mode 100644 index 0000000..194d347 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c new file mode 100644 index 0000000..b9ac19f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h new file mode 100644 index 0000000..e127c2e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..ac8e1b4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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_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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..4cf3bcf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..2228e63 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c new file mode 100644 index 0000000..6e76124 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h new file mode 100644 index 0000000..2c2cc10 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c new file mode 100644 index 0000000..0da4815 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h b/arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h new file mode 100644 index 0000000..0b8edc5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h new file mode 100644 index 0000000..6b03818 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h new file mode 100644 index 0000000..b6fc29b --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h new file mode 100644 index 0000000..afa9b63 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h new file mode 100644 index 0000000..c9d73cc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S new file mode 100644 index 0000000..cac7769 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +.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/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h new file mode 100644 index 0000000..0853934 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h new file mode 100644 index 0000000..25ccfbc --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h new file mode 100644 index 0000000..c93be64 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h new file mode 100644 index 0000000..96b80c5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h new file mode 100644 index 0000000..3f1ac86 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c new file mode 100644 index 0000000..8ee77f1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c new file mode 100644 index 0000000..2f0b67d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c new file mode 100644 index 0000000..35792b2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include "../drivers/arm/gic/v3/gicv3_private.h" +#include "plat_private.h" +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c new file mode 100644 index 0000000..6094a17 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +/* mediatek platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c new file mode 100644 index 0000000..7b1dd03 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk new file mode 100644 index 0000000..1615cf9 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8183/platform.mk @@ -0,0 +1,89 @@ +# +# Copyright (c) 2019, 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/drivers/uart/ \ + -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/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/params_setup.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/arm-trusted-firmware/plat/mediatek/mt8183/scu.c b/arm-trusted-firmware/plat/mediatek/mt8183/scu.c new file mode 100644 index 0000000..c4f1c3f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S new file mode 100644 index 0000000..35b293f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c new file mode 100644 index 0000000..021cab7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c new file mode 100644 index 0000000..5fc6b6e --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..5dde5c5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..6abcff4 --- /dev/null +++ b/arm-trusted-firmware/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 + +void dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..ae0e964 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..ba76594 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..ade0837 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..1901ec9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..989ecf1 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c @@ -0,0 +1,100 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#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) +{ + /* TODO: more setting for EMI MPU. */ +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..415146e --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..134476a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..4430a58 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..8c012e7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h new file mode 100644 index 0000000..83a7a53 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..2b0f071 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..488b1d1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..42b2808 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..c313438 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..0103612 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..0e6444a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c new file mode 100644 index 0000000..4f7ab13 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h new file mode 100644 index 0000000..91ccb19 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..e837456 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#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 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 +}; + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c new file mode 100644 index 0000000..4fcf58e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h new file mode 100644 index 0000000..b48dbb9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/build.mk new file mode 100644 index 0000000..72a2b6b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..66fbe91 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#endif + +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..c47cf1f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..b281734 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..dfacba9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..4977de1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c new file mode 100644 index 0000000..8ad50e2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "mt_spm_extern.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h new file mode 100644 index 0000000..0e21b5e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..a420e16 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..24c39ba --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..a6ea977 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..e7ef346 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..53be3b6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c new file mode 100644 index 0000000..608d9f9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h new file mode 100644 index 0000000..5bcbaff --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..04776c8 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..7196190 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..f228961 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..8cf2062 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..849ffb7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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(75000), }, + ._[CMD_2] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(70000), }, + ._[CMD_3] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(65000), }, + ._[CMD_4] = { BUCK_VCORE_ELR0_66, VOLT_TO_PMIC_VAL_66(60000), }, + ._[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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..219b8d3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..f85ee3b --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..d370daf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..df533a6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..f7c066a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..fb51e69 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..4fe1b12 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..89aa163 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..0b85c60 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..198bac5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#define MT_SPM_SSPM_MBOX_OFF(x) (SSPM_MBOX_3_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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h new file mode 100644 index 0000000..eb2db33 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h new file mode 100644 index 0000000..d007939 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..91ef096 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..768599b --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..472b54c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h new file mode 100644 index 0000000..78a01a8 --- /dev/null +++ b/arm-trusted-firmware/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 +#endif /* __ASSEMBLER__ */ + +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h new file mode 100644 index 0000000..9761e79 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h new file mode 100644 index 0000000..ebc9fa0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S new file mode 100644 index 0000000..39727ea --- /dev/null +++ b/arm-trusted-firmware/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 + +.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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h new file mode 100644 index 0000000..12ea9d7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h new file mode 100644 index 0000000..ec70e4b --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h new file mode 100644 index 0000000..7ef2b85 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h new file mode 100644 index 0000000..9e3726b --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2021, 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 (2) + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 (0x82000205) +#define MTK_SIP_KERNEL_DFD_AARCH64 (0xC2000205) + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h new file mode 100644 index 0000000..f0fb442 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h new file mode 100644 index 0000000..b8b877a --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, 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_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) + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h new file mode 100644 index 0000000..3e8c3e2 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h @@ -0,0 +1,25 @@ +/* + * 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_BASE (IO_PHYS + 0x440000) /* SSPM view: 0x30040000 */ +#define SSPM_CFGREG_ADDR(ofs) (SSPM_CFGREG_BASE + (ofs)) + +#define SSPM_MCDI_SHARE_SRAM (IO_PHYS + 0x420000) +#define SSPM_MBOX_3_BASE (IO_PHYS + 0x480000) + +#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/arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c new file mode 100644 index 0000000..e125c99 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c new file mode 100644 index 0000000..cb66218 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2021-2022, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#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_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + 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; + default: + ERROR("%s: unhandled SMC (0x%x)\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c new file mode 100644 index 0000000..bc95c64 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk new file mode 100644 index 0000000..b6d9ca8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8186/platform.mk @@ -0,0 +1,104 @@ +# +# 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/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/lpm/ \ + -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/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.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/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S new file mode 100644 index 0000000..99274de --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c new file mode 100644 index 0000000..fc98871 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Platform Includes */ +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c new file mode 100644 index 0000000..c3cb9a5 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c new file mode 100644 index 0000000..782aa5f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h new file mode 100644 index 0000000..95fac4a --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c new file mode 100644 index 0000000..245d512 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h new file mode 100644 index 0000000..ff7a9fa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h new file mode 100644 index 0000000..b392d6a --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..dd8bf4e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..ee98d0e --- /dev/null +++ b/arm-trusted-firmware/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 + +bool dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..15a700c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..1cf7834 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c new file mode 100644 index 0000000..b11f272 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h new file mode 100644 index 0000000..9033a0f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..69c395e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..7f0f4b5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..26bed29 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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(®ion_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(®ion_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(®ion_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(®ion_info); + + dump_emi_mpu_regions(); +} + diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..0b15431 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..c78332d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..d3aa24d --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..b483c36 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..f8c51a1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..19dd6a2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..e74d3e7 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..cbed967 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..1635b67 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..f3545aa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c new file mode 100644 index 0000000..cca4413 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h new file mode 100644 index 0000000..aac22af --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..ae892ed --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#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 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; +}; + +#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_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h new file mode 100644 index 0000000..92c71bc --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/************************************************ + * 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c new file mode 100644 index 0000000..f1d8493 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/build.mk new file mode 100644 index 0000000..4153603 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..f66b8ec --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#include +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..9618f3b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..34293c4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..aeb778a --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..8d76d63 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c new file mode 100644 index 0000000..f4505b6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h new file mode 100644 index 0000000..b147fe2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..2d67fdf --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..91ebdd9 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..f9e6654 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..c5e97db --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..a3409f7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..3540ec2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..3d42cf1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..40be027 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/************************************** + * 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..1d0f783 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..4e5f6a0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..6e20916 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..fba011d --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..30194eb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..3eb73d4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..08bbad2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..f74ea80 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..f4e0c48 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..66be7ee --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..452ae90 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..e0ba037 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h new file mode 100644 index 0000000..ab46b86 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h new file mode 100644 index 0000000..6c5cbed --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..7ccebd6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..7ed2e62 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..ad78295 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h new file mode 100644 index 0000000..046cf73 --- /dev/null +++ b/arm-trusted-firmware/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 +#endif /* __ASSEMBLER__ */ + +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h new file mode 100644 index 0000000..9b550ee --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S new file mode 100644 index 0000000..7d17e36 --- /dev/null +++ b/arm-trusted-firmware/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 + +.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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h new file mode 100644 index 0000000..deaac97 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h new file mode 100644 index 0000000..a2881ce --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h new file mode 100644 index 0000000..42ca415 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h new file mode 100644 index 0000000..f68a4ea --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h @@ -0,0 +1,19 @@ +/* + * 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 2 + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205 +#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205 + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h new file mode 100644 index 0000000..ec377b5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h new file mode 100644 index 0000000..a9c7bc8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c new file mode 100644 index 0000000..018e418 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +/* platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c new file mode 100644 index 0000000..353faf8 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#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_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + 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/arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c new file mode 100644 index 0000000..8c1231a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* Platform Includes */ +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk new file mode 100644 index 0000000..cbdaadd --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8192/platform.mk @@ -0,0 +1,99 @@ +# +# Copyright (c) 2020, 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/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/lpm/ \ + -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/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.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/pmic/pmic.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/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S new file mode 100644 index 0000000..a973f4d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c new file mode 100644 index 0000000..2b95171 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c b/arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c new file mode 100644 index 0000000..dff6670 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Project Includes */ +#include +#include +#include +#include +#include +#include + +/* Platform Includes */ +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c new file mode 100644 index 0000000..0eb8d4a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c new file mode 100644 index 0000000..465054d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h new file mode 100644 index 0000000..3b27c1b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h new file mode 100644 index 0000000..6663ad9 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c new file mode 100644 index 0000000..3ed26a1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h new file mode 100644 index 0000000..639abd3 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c new file mode 100644 index 0000000..aed0833 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h new file mode 100644 index 0000000..cb65b85 --- /dev/null +++ b/arm-trusted-firmware/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 + +bool dcm_set_default(void); + +#endif /* #ifndef MTK_DCM_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c new file mode 100644 index 0000000..a1a3720 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h new file mode 100644 index 0000000..e5743af --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c new file mode 100644 index 0000000..c083318 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h new file mode 100644 index 0000000..2a7e979 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c new file mode 100644 index 0000000..5930cd5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +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; +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h new file mode 100644 index 0000000..8157598 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c new file mode 100644 index 0000000..794e21e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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(®ion_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(®ion_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(®ion_info); + + dump_emi_mpu_regions(); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h new file mode 100644 index 0000000..415146e --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c new file mode 100644 index 0000000..daab84c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h new file mode 100644 index 0000000..88b4706 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c new file mode 100644 index 0000000..5a80d95 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c new file mode 100644 index 0000000..f8c51a1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h new file mode 100644 index 0000000..19dd6a2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c new file mode 100644 index 0000000..4147184 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h new file mode 100644 index 0000000..b86e17e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c new file mode 100644 index 0000000..c14e83b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h new file mode 100644 index 0000000..f3545aa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c new file mode 100644 index 0000000..cca4413 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +void pmic_power_off(void) +{ + pwrap_write(PMIC_PWRHOLD, 0x0); +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h new file mode 100644 index 0000000..aac22af --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2020, 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h new file mode 100644 index 0000000..39e78f5 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PMIC_WRAP_INIT_H +#define PMIC_WRAP_INIT_H + +#include + +#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 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; +}; + +#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_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h new file mode 100644 index 0000000..341cf86 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef MTK_PTP3_COMMON_H +#define MTK_PTP3_COMMON_H + +#include +#include + +/************************************************ + * 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 + +/************************************************ + * register read/write + ************************************************/ +#define ptp3_write(addr, val) mmio_write_32((uintptr_t)addr, val) +#define ptp3_clrsetbits(addr, clear, set) \ + mmio_clrsetbits_32((uintptr_t)addr, clear, set) + +/************************************************ + * config enum + ************************************************/ +enum PTP3_CFG { + PTP3_CFG_ADDR, + PTP3_CFG_VALUE, + NR_PTP3_CFG, +}; + +/************************************ + * prototype + ************************************/ +extern void ptp3_core_init(unsigned int core); +extern void ptp3_core_unInit(unsigned int core); + +#endif /* MTK_PTP3_COMMON_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c new file mode 100644 index 0000000..540cb33 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c @@ -0,0 +1,137 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. \ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#define PTP3_CORE_OFT(core) (0x800 * (core)) + +/************************************************ + * 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}; + +static void ptp3_init(unsigned int core) +{ + unsigned int i, addr, value; + + if (core < PTP3_CFG_CPU_START_ID_B) { + ptp3_clrsetbits(ptp3_cfg1[0][PTP3_CFG_ADDR], PTP3_CFG1_MASK, + ptp3_cfg1[0][PTP3_CFG_VALUE]); + } else { + ptp3_clrsetbits(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]; + + ptp3_write(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]; + } + ptp3_write(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]; + + ptp3_write(addr, value & PTP3_CFG3_MASK1); + ptp3_write(addr, value & PTP3_CFG3_MASK2); + ptp3_write(addr, value & PTP3_CFG3_MASK3); + } else { + addr = ptp3_cfg3_ext[PTP3_CFG_ADDR] + PTP3_CORE_OFT(core); + value = ptp3_cfg3_ext[PTP3_CFG_VALUE]; + + ptp3_write(addr, value & PTP3_CFG3_MASK1); + ptp3_write(addr, value & PTP3_CFG3_MASK2); + ptp3_write(addr, value & PTP3_CFG3_MASK3); + } +} + +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(); +} + +void pdp_init(unsigned int pdp_cpu, unsigned int en) +{ + if ((pdp_cpu >= PTP3_CFG_CPU_START_ID_B) && + (pdp_cpu < NR_PTP3_CFG_CPU)) { + pdp_proc_ARM_write(pdp_cpu); + } +} + +static void dt_proc_ARM_write(unsigned int dt_n) +{ + unsigned long v = 0; + + dsb(); + __asm__ volatile ("mrs %0, S3_6_C15_C2_0" : "=r" (v)); + v |= (UL(0x0) << 33); + v |= (UL(0x0) << 32); + __asm__ volatile ("msr S3_6_C15_C2_0, %0" : : "r" (v)); + dsb(); +} + +void dt_init(unsigned int dt_cpu, unsigned int en) +{ + if ((dt_cpu >= PTP3_CFG_CPU_START_ID_B) && + (dt_cpu < NR_PTP3_CFG_CPU)) { + dt_proc_ARM_write(dt_cpu); + } +} +void ptp3_core_init(unsigned int core) +{ + /* init for ptp3 */ + ptp3_init(core); + /* init for pdp */ + pdp_init(core, 1); + /* init for dt */ + dt_init(core, 1); +} + +void ptp3_core_unInit(unsigned int core) +{ + /* TBD */ +} diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/build.mk new file mode 100644 index 0000000..28b2d07 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c new file mode 100644 index 0000000..d2ad282 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c @@ -0,0 +1,241 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef ATF_PLAT_CIRQ_UNSUPPORT +#include +#include +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c new file mode 100644 index 0000000..cf71350 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c new file mode 100644 index 0000000..bd24ddd --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h new file mode 100644 index 0000000..9e74ace --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c new file mode 100644 index 0000000..662f85e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c new file mode 100644 index 0000000..f708bf5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h new file mode 100644 index 0000000..bc57b61 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c new file mode 100644 index 0000000..c80faf5 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h new file mode 100644 index 0000000..e471b55 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c new file mode 100644 index 0000000..7f33408 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h new file mode 100644 index 0000000..aa627e7 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h new file mode 100644 index 0000000..944c227 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c new file mode 100644 index 0000000..4bafe95 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h new file mode 100644 index 0000000..7f6fb0c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c new file mode 100644 index 0000000..2647d9f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +/************************************** + * 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h new file mode 100644 index 0000000..5ac7c91 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c new file mode 100644 index 0000000..9da644c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h new file mode 100644 index 0000000..53fdda2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h new file mode 100644 index 0000000..d8b9b29 --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h new file mode 100644 index 0000000..26250ba --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c new file mode 100644 index 0000000..d018953 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h new file mode 100644 index 0000000..69c5230 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c new file mode 100644 index 0000000..6a85b5c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h new file mode 100644 index 0000000..b08fcce --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h new file mode 100644 index 0000000..ee3738d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h new file mode 100644 index 0000000..6847e77 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c new file mode 100644 index 0000000..a755a38 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h new file mode 100644 index 0000000..fa77b95 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h new file mode 100644 index 0000000..2639b7e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c new file mode 100644 index 0000000..9b332a0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h new file mode 100644 index 0000000..34e93d0 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h b/arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h new file mode 100644 index 0000000..bf4092e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h new file mode 100644 index 0000000..046cf73 --- /dev/null +++ b/arm-trusted-firmware/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 +#endif /* __ASSEMBLER__ */ + +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h new file mode 100644 index 0000000..ebc9fa0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S new file mode 100644 index 0000000..39727ea --- /dev/null +++ b/arm-trusted-firmware/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 + +.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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h new file mode 100644 index 0000000..347f358 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h new file mode 100644 index 0000000..a2881ce --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h new file mode 100644 index 0000000..7ef2b85 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h new file mode 100644 index 0000000..5562a67 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h @@ -0,0 +1,27 @@ +/* + * 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 6 + +/* DFD */ +#define MTK_SIP_KERNEL_DFD_AARCH32 0x82000205 +#define MTK_SIP_KERNEL_DFD_AARCH64 0xC2000205 + +/* DP/eDP */ +#define MTK_SIP_DP_CONTROL_AARCH32 0x82000523 +#define MTK_SIP_DP_CONTROL_AARCH64 0xC2000523 + +/* APUSYS SMC call */ +#define MTK_SIP_APUSYS_CONTROL_AARCH32 0x8200051E +#define MTK_SIP_APUSYS_CONTROL_AARCH64 0xC200051E + +#endif /* PLAT_SIP_CALLS_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h new file mode 100644 index 0000000..d4f2f83 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2021, 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/arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h b/arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h new file mode 100644 index 0000000..a9c7bc8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#endif /* RTC_H */ diff --git a/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c new file mode 100644 index 0000000..b77ab27 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c @@ -0,0 +1,403 @@ +/* + * Copyright (c) 2021, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* common headers */ +#include + +#include +#include +#include +#include + +/* platform specific headers */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c new file mode 100644 index 0000000..7d3c512 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2020, MediaTek Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#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_ARCH32: + case MTK_SIP_VCORE_CONTROL_ARCH64: + 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/arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c b/arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c new file mode 100644 index 0000000..bc95c64 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk b/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk new file mode 100644 index 0000000..a81c093 --- /dev/null +++ b/arm-trusted-firmware/plat/mediatek/mt8195/platform.mk @@ -0,0 +1,108 @@ +# +# Copyright (c) 2021, 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/drivers/gic600/ \ + -I${MTK_PLAT}/common/drivers/gpio/ \ + -I${MTK_PLAT}/common/drivers/rtc/ \ + -I${MTK_PLAT}/common/drivers/timer/ \ + -I${MTK_PLAT}/common/drivers/uart/ \ + -I${MTK_PLAT}/common/lpm/ \ + -I${MTK_PLAT_SOC}/drivers/apusys/ \ + -I${MTK_PLAT_SOC}/drivers/dcm \ + -I${MTK_PLAT_SOC}/drivers/dfd \ + -I${MTK_PLAT_SOC}/drivers/dp/ \ + -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/drivers/gic600/mt_gic_v3.c \ + ${MTK_PLAT}/common/drivers/gpio/mtgpio_common.c \ + ${MTK_PLAT}/common/drivers/pmic_wrap/pmic_wrap_init_v2.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_common.c \ + ${MTK_PLAT}/common/drivers/rtc/rtc_mt6359p.c \ + ${MTK_PLAT}/common/drivers/timer/mt_timer.c \ + ${MTK_PLAT}/common/drivers/uart/uart.c \ + ${MTK_PLAT}/common/lpm/mt_lp_rm.c \ + ${MTK_PLAT}/common/mtk_cirq.c \ + ${MTK_PLAT}/common/mtk_plat_common.c \ + ${MTK_PLAT}/common/mtk_sip_svc.c \ + ${MTK_PLAT}/common/params_setup.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/dp/mt_dp.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/pmic/pmic.c \ + ${MTK_PLAT_SOC}/drivers/ptp3/mtk_ptp3_main.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/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S new file mode 100644 index 0000000..d630f1f --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S @@ -0,0 +1,453 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + +#if !ENABLE_PIE + /* ---------------------------------------------------- + * 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, __STACKS_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: +#endif + + /* ----------------------------------- + * 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 + +/* Helper macro for CoreId calculation */ +#define PLATFORM_MAX_CPUS_PER_SOCKET (PLATFORM_CLUSTER_COUNT * \ + PLATFORM_MAX_CPUS_PER_CLUSTER) + + /* ------------------------------------------------------ + * 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-x4 + * ------------------------------------------------------ + */ +func plat_core_pos_by_mpidr + lsr x1, x0, #TEGRA_CORE_AFFINITY + and x1, x1, #MPIDR_AFFLVL_MASK /* core id */ + lsr x2, x0, #TEGRA_CLUSTER_AFFINITY + and x2, x2, #MPIDR_AFFLVL_MASK /* cluster id */ +#ifdef PLATFORM_SOCKET_COUNT + lsr x3, x0, #TEGRA_SOCKET_AFFINITY + and x3, x3, #MPIDR_AFFLVL_MASK /* socket id */ +#endif + /* 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 + +#ifdef PLATFORM_SOCKET_COUNT + /* socket_id >= PLATFORM_SOCKET_COUNT */ + cmp x3, #(PLATFORM_SOCKET_COUNT - 1) + b.gt 1f +#endif + + /* CorePos = CoreId + (ClusterId * cpus per cluster) */ + mov x4, #PLATFORM_MAX_CPUS_PER_CLUSTER + mul x4, x4, x2 + add x0, x1, x4 + +#ifdef PLATFORM_SOCKET_COUNT + /* CorePos = CoreId + (SocketId * cpus per socket) */ + mov x1, #PLATFORM_MAX_CPUS_PER_SOCKET + mov x1, #84 + mul x3, x3, x1 + add x0, x0, x3 +#endif + +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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c new file mode 100644 index 0000000..431e685 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c @@ -0,0 +1,348 @@ +/* + * 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 +#include +#include +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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; + + /* + * 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; + + /* + * 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); + + /* 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk new file mode 100644 index 0000000..2607a06 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_common.mk @@ -0,0 +1,55 @@ +# +# 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 + +# Enable support for GIC600 +GICV3_SUPPORT_GIC600 := 1 +GICV3_OVERRIDE_DISTIF_PWR_OPS := 1 + +# 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 + +BL31_SOURCES += drivers/delay_timer/delay_timer.c \ + drivers/io/io_storage.c \ + plat/common/aarch64/crash_console_helpers.S \ + ${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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c new file mode 100644 index 0000000..d9547c4 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c new file mode 100644 index 0000000..5309d98 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if ENABLE_WDT_LEGACY_FIQ_HANDLING +#include +#endif +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c new file mode 100644 index 0000000..7ff0954 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include + +static unsigned int tegra_target_masks[PLATFORM_CORE_COUNT]; + +/* Help function to register platform specific structure base address */ +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr) +{ + ; /* do nohting */ +} + +/****************************************************************************** + * 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(); +} + +/****************************************************************************** + * Tegra helper to save & restore the GICv2 on resume from CPU or system suspend + *****************************************************************************/ +void tegra_gic_save(uint32_t pstate_id) +{ + ; /* do nohting */ +} + +void tegra_gic_restore(uint32_t pstate_id) +{ + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + gicv2_distif_init(); + } + tegra_gic_pcpu_init(); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c new file mode 100644 index 0000000..31d7ef5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c @@ -0,0 +1,218 @@ +/* + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include +#include +#include + +/* 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] = { + TEGRA_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 *tegra_gicr_frames = gicr_base_addrs; + +/* + * We save and restore the GICv3 context on CPU suspend and system suspend. + */ +static gicv3_redist_ctx_t rdist_ctx; +static gicv3_dist_ctx_t dist_ctx; + +/* Pointers to platform specific structs to save the context */ +static gicv3_redist_ctx_t *plat_redist_ctx; +static gicv3_dist_ctx_t *plat_dist_ctx; + +/* Help function to register platform specific structure base address */ +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr) +{ + assert(redist_ptr != NULL); + assert(dist_ptr != NULL); + plat_redist_ctx = (gicv3_redist_ctx_t *)redist_ptr; + plat_dist_ctx = (gicv3_dist_ctx_t *)dist_ptr; +} + +/* + * Override default implementation of 'arm_gicv3_distif_pre_save' + * and 'arm_gicv3_distif_post_restore' functions. + */ +void arm_gicv3_distif_pre_save(unsigned int rdist_proc_num) +{ + ; /* do nothing */ +} + +void arm_gicv3_distif_post_restore(unsigned int rdist_proc_num) +{ + ; /* do nothing */ +} + +static unsigned int plat_tegra_mpidr_to_core_pos(unsigned long mpidr) +{ + return (unsigned int)plat_core_pos_by_mpidr(mpidr); +} + +/* + * 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 tegra_gicv3_override_gicr_frames(const uintptr_t *plat_gicr_frames) +{ + assert(plat_gicr_frames != NULL); + tegra_gicr_frames = plat_gicr_frames; +} + +/****************************************************************************** + * 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 = 0U; + 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); + + if (gicv3_rdistif_probe(tegra_gicr_frames[0]) == -1) { + ERROR("No GICR base frame found for Primary CPU\n"); + panic(); + } +} + +/****************************************************************************** + * 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) +{ + int result; + const uintptr_t *gicr_frames = tegra_gicr_frames; + + do { + result = gicv3_rdistif_probe(*gicr_frames); + + /* If the probe is successful, no need to proceed further */ + if (result == 0) { + break; + } + + gicr_frames++; + } while (*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()); + gicv3_cpuif_enable(plat_my_core_pos()); +} + +/****************************************************************************** + * Tegra helper to save & restore the GICv3 on resume from CPU or system suspend + *****************************************************************************/ +void tegra_gic_save(uint32_t pstate_id) +{ + gicv3_redist_ctx_t *local_rdist_base; + gicv3_dist_ctx_t *local_dist_base; + + /* + * Check the platform redist and dist ctx, + * if they are not NULL, use platform specific + * structures to do the save. + */ + local_rdist_base = (plat_redist_ctx == NULL) ? &rdist_ctx : plat_redist_ctx; + local_dist_base = (plat_dist_ctx == NULL) ? &dist_ctx : plat_dist_ctx; + + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + /* + * Save the GIC Redistributors and ITS contexts before the + * Distributor context. we only need to save the context of the CPU + * that is issuing the CPU or SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_save(plat_my_core_pos(), local_rdist_base); + + /* Save the GIC Distributor context */ + gicv3_distif_save(local_dist_base); + } + + /* + * 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 tegra_gic_restore(uint32_t pstate_id) +{ + gicv3_redist_ctx_t *local_rdist_base; + gicv3_dist_ctx_t *local_dist_base; + + /* + * Check the platform redist and dist ctx, + * if they are not NULL, use platform specific + * structures to do the restore. + */ + local_rdist_base = (plat_redist_ctx == NULL) ? &rdist_ctx : plat_redist_ctx; + local_dist_base = (plat_dist_ctx == NULL) ? &dist_ctx : plat_dist_ctx; + + if (pstate_id == PSTATE_ID_SOC_POWERDN) { + /* Restore the GIC Distributor context */ + gicv3_distif_init_restore(local_dist_base); + + /* + * Restore the GIC Redistributor and ITS contexts after the + * Distributor context. we only need to restore the context of the CPU + * that is issuing the CPU or SYSTEM SUSPEND call, i.e. the current CPU. + */ + gicv3_rdistif_init_restore(plat_my_core_pos(), local_rdist_base); + } + + /* Re-enable the GIC CPU interface*/ + gicv3_cpuif_enable(plat_my_core_pos()); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c new file mode 100644 index 0000000..21641aa --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c new file mode 100644 index 0000000..bd7d871 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#define TEGRA_APKEY_FIXED_PATTERN U(0x55AAAA5555AAAA55) + +/* + * This is only a toy implementation to generate a fixed 128-bit key + * from sp, x30 and fix 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 fixed_pattern = TEGRA_APKEY_FIXED_PATTERN; + + /* Generate 128-bit key */ + uint64_t key_lo = (return_addr << 13) ^ frame_addr ^ fixed_pattern; + uint64_t key_hi = (frame_addr << 15) ^ return_addr ^ fixed_pattern; + + return ((uint128_t)(key_hi) << 64) | key_lo; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c new file mode 100644 index 0000000..2888ee2 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c @@ -0,0 +1,369 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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_VSP, + 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) +#define TEGRA_PRE_SI_VSP U(9) + +/* + * 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); +} + +bool tegra_chipid_is_t239(void) +{ + uint32_t chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + return ((chip_id == TEGRA_CHIPID_TEGRA23) && + (tegra_get_chipid_major() == 0x9U)); +} + +/* + * Read platform type from HIDREV major and minor bits. + */ + +static tegra_platform_t from_hidrev_major_minor_rev(void) +{ + uint32_t major = tegra_get_chipid_major(); + uint32_t minor = tegra_get_chipid_minor(); + tegra_platform_t ret; + + 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 { + /* Actual silicon platforms have a non-zero major version */ + ret = TEGRA_PLATFORM_SILICON; + } + + return ret; +} + +/* + * Read platform type from HIDREV pre_si bits. + */ + +static tegra_platform_t from_hidrev_pre_si_platform(void) +{ + uint32_t pre_si_platform = tegra_get_chipid_pre_si_platform(); + tegra_platform_t ret; + + 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; + + /* + * The VSP pre-si development platform. + */ + case TEGRA_PRE_SI_VSP: + ret = TEGRA_PLATFORM_VSP; + break; + + default: + ret = TEGRA_PLATFORM_MAX; + break; + } + } else { + /* Actual silicon platforms have a non-zero major version */ + ret = TEGRA_PLATFORM_SILICON; + } + + return ret; +} + +/* + * Read the chip ID value and derive the platform + */ +static tegra_platform_t tegra_get_platform(void) +{ + tegra_platform_t ret; + uint32_t chip_id; + + /* get the chip_id/major/minor chip ID values */ + chip_id = (tegra_get_chipid() >> CHIP_ID_SHIFT) & CHIP_ID_MASK; + + switch (chip_id) { + case TEGRA_CHIPID_TEGRA13: + case TEGRA_CHIPID_TEGRA18: + case TEGRA_CHIPID_TEGRA21: + ret = from_hidrev_major_minor_rev(); + break; + + /* For chip id T194 and later */ + default: + ret = from_hidrev_pre_si_platform(); + break; + } + + 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); +} + +bool tegra_platform_is_vsp(void) +{ + return ((tegra_get_platform() == TEGRA_PLATFORM_VSP) ? 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c new file mode 100644 index 0000000..4a15019 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c @@ -0,0 +1,335 @@ +/* + * 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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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(); + + /* save GIC Re-distributor and Distributor context */ + tegra_gic_save(target_state->pwr_domain_state[PLAT_MAX_PWR_LVL]); +} + +/******************************************************************************* + * 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. Restore the GIC global distributor and + * GIC cpu interfaces. + */ + tegra_gic_restore(PSTATE_ID_SOC_POWERDN); + + /* 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 if (target_state->pwr_domain_state[MPIDR_AFFLVL0] == PSTATE_ID_CORE_POWERDN) { + /* + * Restore the GIC cpu and distributor interfaces + */ + tegra_gic_restore(PSTATE_ID_CORE_POWERDN); + } 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c new file mode 100644 index 0000000..9241b81 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c new file mode 100644 index 0000000..80a2c4d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c b/arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c new file mode 100644 index 0000000..f6c459a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c new file mode 100644 index 0000000..d7db604 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c new file mode 100644 index 0000000..f1ed1e4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c @@ -0,0 +1,367 @@ +/* + * Copyright (c) 2017-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(); + 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); + dsbsy(); + assert(memcmp(p_fdata, p_out, (size_t)size_out) == 0); + + /* 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 { + p_fdata = f_in->data; + (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; + struct bpmp_ipc_platform_data *bpmp_ipc; + + /* 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__); + + /* get bpmp_ipc data */ + bpmp_ipc = plat_get_bpmp_ipc_data(); + if (bpmp_ipc == NULL) { + ERROR("%s: bpmp_ipc interface is not supported\n", __func__); + return -ENOTSUP; + } + + msg_size = tegra_ivc_align(IVC_CMD_SZ_BYTES); + frame_size = (uint32_t)tegra_ivc_total_queue_size(msg_size); + if (frame_size > bpmp_ipc->bpmp_ipc_map_size) { + ERROR("%s: carveout size is not sufficient\n", __func__); + return -EINVAL; + } + + error = tegra_ivc_init(&ivc_ccplex_bpmp_channel, + (uint32_t)bpmp_ipc->bpmp_ipc_rx_base, + (uint32_t)bpmp_ipc->bpmp_ipc_tx_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; + struct cmd_clk_is_en_resp resp = { 0 }; + + /* 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); + } + + /* prepare the MRQ_CLK command to check if clk is actually enabled */ + req.cmd_and_id = make_mrq_clk_cmd(CMD_CLK_IS_ENABLED, clk_id); + + ret = tegra_bpmp_ipc_send_req_atomic(MRQ_CLK, &req, (uint32_t)sizeof(req), + &resp, (uint32_t)sizeof(resp)); + if (resp.state == 0) { + ERROR("%s: clock enable 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h new file mode 100644 index 0000000..e02c508 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h @@ -0,0 +1,142 @@ +/* + * Copyright (c) 2017-2021, 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; +}; + +struct __attribute__((packed)) cmd_clk_is_en_resp { + /** + * @brief The state of the clock that has been succesfully + * requested with CMD_CLK_ENABLE or CMD_CLK_DISABLE by the + * master invoking the command earlier. + * + * The state may not reflect the physical state of the clock + * if there are some other masters requesting it to be + * enabled. + * + * Value 0 is disabled, all other values indicate enabled. + */ + int32_t state; +}; + +/** + * 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c new file mode 100644 index 0000000..d964fc0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include + +#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 + * 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 + * EST ACK + * 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h b/arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h new file mode 100644 index 0000000..1b31821 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c new file mode 100644 index 0000000..8f55554 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c new file mode 100644 index 0000000..d68cdfd --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c new file mode 100644 index 0000000..b3dcd2a --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c new file mode 100644 index 0000000..4c38b56 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c @@ -0,0 +1,334 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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"); + + /* allow platforms to program custom memory controller settings */ + plat_memctrl_setup(); +} + +/* + * 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/arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c new file mode 100644 index 0000000..6c5a73b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c new file mode 100644 index 0000000..53f47e0 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/* + * This function writes SC7 entry opcode to notify PSC from CCPLEX. + * The protocol is to write the command to the MBOX and then trigger + * a doorbell. + */ +void tegra_psc_notify_sc7_entry(void) +{ + INFO("%s: send SC7 opcode to PSC\n", __func__); + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_IN), + PSC_MBOX_TZ_OPCODE_ENTER_SC7); + + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_EXT_CTRL), + (PSC_MBOX_OUT_DONE | PSC_MBOX_IN_VALID)); +} + +/* + * This funciton read back the ACKs from PSC mailbox and verify their values. + * The PSC mailbox should return the OPCODE in out0 and return 0 in out1 for + * PSC operation done. + */ +void tegra_psc_wait_for_ack(void) +{ + uint32_t timeout_count = PSC_MBOX_ACK_TIMEOUT_MAX_USEC; + uint32_t val, out_valid; + + do { + if (timeout_count-- == 0U) { + ERROR("!! %s: PSC handshake fail !!", __func__); + panic(); + } + + udelay(1U); + + out_valid = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + + PSC_MBOX_TZ_PSC_CTRL); + + } while (PSC_MBOX_OUT_VALID != (out_valid & PSC_MBOX_OUT_VALID)); + + INFO("%s: PSC handshake done\n", __func__); + + /* Get first ACK from PSC_MBOX_TZ_OUT_0 */ + val = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_OUT_0); + assert(val == PSC_MBOX_TZ_OPCODE_ENTER_SC7); + + /* Get second ACK from PSC_MBOX_TZ_OUT_1 */ + val = mmio_read_32(TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_OUT_1); + assert(val == PSC_MBOX_SC7_ENTRY_PASS); + + /* Trigger MBOX_OUT_DONE, notify PSC handshake finish */ + mmio_write_32((TEGRA_PSC_MBOX_TZ_BASE + PSC_MBOX_TZ_EXT_CTRL), + PSC_MBOX_OUT_DONE); +} + diff --git a/arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c new file mode 100644 index 0000000..4189b00 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S b/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S new file mode 100644 index 0000000..7040386 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include + +#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 + /* save x3 as it will get clobbered */ + adr x2, spe_console_stack + str x3, [x2] + + /* 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] + + /* restore x3 */ + adr x2, spe_console_stack + ldr x3, [x2] + mov x2, #0 + ret +putc_error: + mov w0, #-1 + + /* restore x3 */ + adr x2, spe_console_stack + ldr x3, [x2] + mov x2, #0 + 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 + + /* scratch space to store x3 register from console_core_putc */ + .data + .align 3 +spe_console_stack: + .quad 0 diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h new file mode 100644 index 0000000..dc3fb6b --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h new file mode 100644 index 0000000..0595a29 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h @@ -0,0 +1,58 @@ +/* + * 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 +#include +#include + + +/* + * Struct describing bpmp_ipc channel info + */ +struct bpmp_ipc_platform_data { + uint64_t bpmp_ipc_tx_base; + uint64_t bpmp_ipc_rx_base; + uint32_t bpmp_ipc_map_size; +}; + +/** + * 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); + +/** + * Handler to get bpmp_ipc channel info. + */ +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void); + +#endif /* BPMP_IPC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h new file mode 100644 index 0000000..e5ab600 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h new file mode 100644 index 0000000..a59df37 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h new file mode 100644 index 0000000..5f1bb4f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h new file mode 100644 index 0000000..cc85095 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h new file mode 100644 index 0000000..8e9f198 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h new file mode 100644 index 0000000..9af3027 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/******************************************************************************* + * 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 + +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 + +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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h new file mode 100644 index 0000000..8752b84 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h new file mode 100644 index 0000000..87a0194 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PSC_MAILBOX_H +#define PSC_MAILBOX_H + +void tegra_psc_notify_sc7_entry(void); +void tegra_psc_wait_for_ack(void); + +#endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h new file mode 100644 index 0000000..5ae6257 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h new file mode 100644 index 0000000..32fc6f9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h @@ -0,0 +1,90 @@ +/* + * 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 + +#include +#include + +#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 */ +#define TEGRA_SMMU0 0U +#define TEGRA_SMMU1 1U +#define 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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h new file mode 100644 index 0000000..e0f8714 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* + * 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/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h new file mode 100644 index 0000000..22923d6 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_GIC_H +#define TEGRA_GIC_H + +#include + +/******************************************************************************* + * 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; + +/******************************************************************************* + * Function 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); +void tegra_gic_save(uint32_t pstate_id); +void tegra_gic_restore(uint32_t pstate_id); +void tegra_gic_register_ctx_ptr(uintptr_t *redist_ptr, uintptr_t *dist_ptr); + +/* Tegra GICv3 function declarations */ +void tegra_gicv3_override_gicr_frames(const uintptr_t *plat_gicr_frames); + +#endif /* TEGRA_GIC_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h b/arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h new file mode 100644 index 0000000..684c872 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S b/arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S new file mode 100644 index 0000000..2dc3b41 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +.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/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h new file mode 100644 index 0000000..6672683 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +#include + +/******************************************************************************* + * 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 +#ifndef PLATFORM_STACK_SIZE +#define PLATFORM_STACK_SIZE U(0x400) +#endif +#endif + +#define TEGRA_PRIMARY_CPU U(0x0) + +/******************************************************************************* + * 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 (PLAT_BL31_BASE + TZDRAM_SIZE) + +/******************************************************************************* + * BL31 specific defines. + ******************************************************************************/ +#define BL31_BASE PLAT_BL31_BASE +#define BL31_LIMIT (PLAT_BL31_BASE + BL31_SIZE) +#define BL32_BASE (PLAT_BL31_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/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h new file mode 100644 index 0000000..4514e14 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h new file mode 100644 index 0000000..06cecc5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h @@ -0,0 +1,338 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * Platform specific macros. + ******************************************************************************/ +#define BL31_SIZE U(0x40000) + +/* Platform power domain constants */ +#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)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h new file mode 100644 index 0000000..fa44772 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h new file mode 100644 index 0000000..c5a51e9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h new file mode 100644 index 0000000..336461a --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Implementation defined RAS error and corresponding error message */ +struct ras_error { + const char *error_msg; + /* IERR(bits[15:8]) from ERRSTATUS */ + 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 _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 ERRCTLR + * + * This macro will be used to collect all defined ERR_CTRL bits for each node + * defined by _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/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h new file mode 100644 index 0000000..795d07d --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h @@ -0,0 +1,337 @@ +/* + * Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * 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) + +/* Platform power domain constants */ +#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)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h new file mode 100644 index 0000000..a351321 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h @@ -0,0 +1,306 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_DEF_H +#define TEGRA_DEF_H + +#include + +/******************************************************************************* + * 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) + +/******************************************************************************* + * Platform power domain constants + ******************************************************************************/ +#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)) + + /* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF0_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF1_SHIFT + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h new file mode 100644 index 0000000..168ba5b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h @@ -0,0 +1,14 @@ +/* + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA234_PRIVATE +#define TEGRA234_PRIVATE + +void tegra234_ras_init_common(void); +void tegra234_ras_init_my_cluster(void); +int tegra234_ras_inject_fault(uint64_t base, uint64_t pfgcdn, uint64_t pfgctl); + +#endif /* TEGRA234_PRIVATE */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h new file mode 100644 index 0000000..fb4b0f1 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h @@ -0,0 +1,463 @@ +/* + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA234_RAS_PRIVATE +#define TEGRA234_RAS_PRIVATE + +#include + +/* RAS error record base addresses */ +#define TEGRA234_RAS_CCPMU_BASE U(0x0E001000) +#define TEGRA234_RAS_CMU_CLOCKS_BASE U(0x0E003000) +#define TEGRA234_RAS_IH_BASE U(0x0E006000) +#define TEGRA234_RAS_IST_CLUSTER0_BASE U(0x0E009000) +#define TEGRA234_RAS_IST_CLUSTER1_BASE U(0x0E00A000) +#define TEGRA234_RAS_IST_CLUSTER2_BASE U(0x0E00B000) +#define TEGRA234_RAS_IOB_BASE U(0x0E010000) +#define TEGRA234_RAS_SNOC_BASE U(0x0E011000) +#define TEGRA234_RAS_SCC_SLICE0_BASE U(0x0E012000) +#define TEGRA234_RAS_SCC_SLICE1_BASE U(0x0E013000) +#define TEGRA234_RAS_SCC_SLICE2_BASE U(0x0E014000) +#define TEGRA234_RAS_SCC_SLICE3_BASE U(0x0E015000) +#define TEGRA234_RAS_SCC_SLICE4_BASE U(0x0E016000) +#define TEGRA234_RAS_SCC_SLICE5_BASE U(0x0E017000) +#define TEGRA234_RAS_SCC_SLICE6_BASE U(0x0E018000) +#define TEGRA234_RAS_SCC_SLICE7_BASE U(0x0E019000) +#define TEGRA234_RAS_ACI_CLUSTER0_BASE U(0x0E01A000) +#define TEGRA234_RAS_ACI_CLUSTER1_BASE U(0x0E01B000) +#define TEGRA234_RAS_ACI_CLUSTER2_BASE U(0x0E01C000) +#define TEGRA234_RAS_CL0_CORE0_BASE U(0x0E030000) +#define TEGRA234_RAS_CL0_CORE1_BASE U(0x0E031000) +#define TEGRA234_RAS_CL0_CORE2_BASE U(0x0E032000) +#define TEGRA234_RAS_CL0_CORE3_BASE U(0x0E033000) +#define TEGRA234_RAS_CL0_CORE_LS_PAIR1_BASE U(0x0E034000) +#define TEGRA234_RAS_CL0_CORE_LS_PAIR2_BASE U(0x0E035000) +#define TEGRA234_RAS_CL0_DSU_LS_PRIMARY_BASE U(0x0E036000) +#define TEGRA234_RAS_CL0_DSU_LS_SECONDARY_BASE U(0x0E037000) +#define TEGRA234_RAS_CL0_DSU_IFP_BASE U(0x0E038000) +#define TEGRA234_RAS_CL1_CORE0_BASE U(0x0E040000) +#define TEGRA234_RAS_CL1_CORE1_BASE U(0x0E041000) +#define TEGRA234_RAS_CL1_CORE2_BASE U(0x0E042000) +#define TEGRA234_RAS_CL1_CORE3_BASE U(0x0E043000) +#define TEGRA234_RAS_CL1_CORE_LS_PAIR1_BASE U(0x0E044000) +#define TEGRA234_RAS_CL1_CORE_LS_PAIR2_BASE U(0x0E045000) +#define TEGRA234_RAS_CL1_DSU_LS_PRIMARY_BASE U(0x0E046000) +#define TEGRA234_RAS_CL1_DSU_LS_SECONDARY_BASE U(0x0E047000) +#define TEGRA234_RAS_CL1_DSU_IFP_BASE U(0x0E048000) +#define TEGRA234_RAS_CL2_CORE0_BASE U(0x0E050000) +#define TEGRA234_RAS_CL2_CORE1_BASE U(0x0E051000) +#define TEGRA234_RAS_CL2_CORE2_BASE U(0x0E052000) +#define TEGRA234_RAS_CL2_CORE3_BASE U(0x0E053000) +#define TEGRA234_RAS_CL2_CORE_LS_PAIR1_BASE U(0x0E054000) +#define TEGRA234_RAS_CL2_CORE_LS_PAIR2_BASE U(0x0E055000) +#define TEGRA234_RAS_CL2_DSU_LS_PRIMARY_BASE U(0x0E056000) +#define TEGRA234_RAS_CL2_DSU_LS_SECONDARY_BASE U(0x0E057000) +#define TEGRA234_RAS_CL2_DSU_IFP_BASE U(0x0E058000) + +/* IH RAS status masks */ +#define TEGRA234_IH_STATUS_MASK_CMU (BIT(1) | BIT(0)) +#define TEGRA234_IH_STATUS_MASK_SCF (BIT(3) | BIT(2)) +#define TEGRA234_IH_STATUS_MASK_CL0 (BIT(4) | BIT(8) | BIT(9) | \ + BIT(16) | BIT(17) | \ + (ULL(0xFF) << 24)) +#define TEGRA234_IH_STATUS_MASK_CL1 (BIT(5) | BIT(10) | BIT(11) | \ + BIT(18) | BIT(19) | \ + (ULL(0xFF) << 32)) +#define TEGRA234_IH_STATUS_MASK_CL2 (BIT(6) | BIT(12) | BIT(13) | \ + BIT(20) | BIT(21) | \ + (ULL(0xFF) << 40)) + +/* Implementation defined RAS error and corresponding error message */ +struct ras_error { + const char *error_msg; + /* IERR(bits[15:8]) from ERRSTATUS */ + uint8_t error_code; +}; + +/* RAS error node-specific auxiliary data */ +struct ras_aux_data { + /* name of the current RAS node */ + const char *name; + /* + * pointer to null-terminated ras_error array to convert error + * code to msg + */ + const struct ras_error *error_records; + /* + * Number of error records + */ + unsigned int num_err_records; + /* + * function to return value which needs to be programmed into + * ERRCTLR to enable uncorrectable RAS errors for current + * node + */ + uint64_t (*get_ue_mask)(void); + /* + * function to return value which needs to be programmed into + * ERRCTLR to enable corrected RAS errors for the current + * node + */ + uint64_t (*get_ce_mask)(void); +}; + +/* CCPMU Uncorrectable RAS ERROR */ +#define CCPMU_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CCPMU, 42, 0x0A, "IL1 Parity Error") \ + X(CCPMU, 41, 0x09, "Invalid uOp Error") \ + X(CCPMU, 40, 0x08, "MCE Request Error") \ + X(CCPMU, 39, 0x07, "MCE Request Timeout Error") \ + X(CCPMU, 38, 0x06, "CRAB Master Error") \ + X(CCPMU, 37, 0x05, "uCode Error") \ + X(CCPMU, 36, 0x04, "ARI Request NS Error") \ + X(CCPMU, 35, 0x03, "CCPMU unit Lockable CREG Error") \ + X(CCPMU, 34, 0x02, "CCPMU RAS Lockable CREG Error") \ + X(CCPMU, 33, 0x01, "DC Lockable CREG Error") \ + X(CCPMU, 32, 0x00, "CMULA lockable CREG Error") + +/* Empty CCPMU Corrected RAS ERROR */ +#define CCPMU_CORR_RAS_ERROR_LIST(X) + +/* CMU Clocks Uncorrectable RAS ERROR */ +#define CMU_CLOCKS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CMU_CLOCKS, 41, 0x09, "Cluster2 FMON Error") \ + X(CMU_CLOCKS, 40, 0x08, "Cluster2 Core FMON Error") \ + X(CMU_CLOCKS, 39, 0x07, "Cluster1 FMON Error") \ + X(CMU_CLOCKS, 38, 0x06, "Cluster1 Core FMON Error") \ + X(CMU_CLOCKS, 37, 0x05, "Cluster0 FMON Error") \ + X(CMU_CLOCKS, 36, 0x04, "Cluster0 Core FMON Error") \ + X(CMU_CLOCKS, 35, 0x03, "LUT0 Parity Error") \ + X(CMU_CLOCKS, 34, 0x02, "LUT1 Parity Error") \ + X(CMU_CLOCKS, 33, 0x01, "ADC0 VMON Error") \ + X(CMU_CLOCKS, 32, 0x00, "Lock Error") + +/* Empty CMU Clocks Corrected RAS ERROR */ +#define CMU_CLOCKS_CORR_RAS_ERROR_LIST(X) + +/* IH Uncorrectable RAS ERROR */ +#define IH_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IH, 35, 0x03, "RAS MUX Error") \ + X(IH, 34, 0x02, "GIC FMU Error") \ + X(IH, 33, 0x01, "Unit lockable CREG Error") \ + X(IH, 32, 0x00, "RAS lockable CREG Error") + +/* Empty IH Corrected RAS ERROR */ +#define IH_CORR_RAS_ERROR_LIST(X) + +/* IST Uncorrectable RAS ERROR */ +#define IST_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IST, 50, 0x12, "Lock Error") \ + X(IST, 49, 0x11, "MCE Error") \ + X(IST, 48, 0x10, "MISR Mismatch Error") \ + X(IST, 47, 0x0F, "Security Error") \ + X(IST, 46, 0x0E, "RAM Data Error") \ + X(IST, 45, 0x0D, "JTAG Controller Error") \ + X(IST, 44, 0x0C, "Timeout Error") \ + X(IST, 43, 0x0B, "LBIST Controller Error") \ + X(IST, 42, 0x0A, "DMA Error") \ + X(IST, 41, 0x09, "ECC Security Error") + +/* IST Corrected RAS ERROR */ +#define IST_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IST, 40, 0x08, "MCE Error") \ + X(IST, 39, 0x07, "MISR Mismatch Error") \ + X(IST, 38, 0x06, "Security Error") \ + X(IST, 37, 0x05, "RAM Data Error") \ + X(IST, 36, 0x04, "JTAG Controller Error") \ + X(IST, 35, 0x03, "Timeout Error") \ + X(IST, 34, 0x02, "LBIST Controller Error") \ + X(IST, 33, 0x01, "DMA Error") \ + X(IST, 32, 0x00, "ECC Security Error") + +/* IOB Uncorrectable RAS ERROR */ +#define IOB_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IOB, 47, 0x0F, "APB Response Parity Error") \ + X(IOB, 46, 0x0E, "IHI Write Data Ready Error") \ + X(IOB, 45, 0x0D, "IHI Write Address Ready Error") \ + X(IOB, 44, 0x0C, "IHI Read Address Ready Error") \ + X(IOB, 43, 0x0B, "IHI Write Response Parity Error") \ + X(IOB, 42, 0x0A, "IHI Read Data Parity Error") \ + X(IOB, 41, 0x09, "Request Parity Error") \ + X(IOB, 40, 0x08, "PutData Parity Error") \ + X(IOB, 39, 0x07, "PutData Uncorrectable ECC Error") \ + X(IOB, 38, 0x06, "CBB Interface Error") \ + X(IOB, 37, 0x05, "ARM MMCRAB Access Error") \ + X(IOB, 36, 0x04, "APB Interface Error") \ + X(IOB, 35, 0x03, "IHI (GIC ACE-Lite) Interface Error") \ + X(IOB, 34, 0x02, "Trickbox Interface Error") \ + X(IOB, 33, 0x01, "Lock Error") + +/* IOB Corrected RAS ERROR */ +#define IOB_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(IOB, 32, 0x00, "Putdata Corrected ECC Error") + +/* SNOC Uncorrectable RAS ERROR */ +#define SNOC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SNOC, 47, 0x0F, "MCF MSI Error") \ + X(SNOC, 46, 0x0E, "MISC IST CPE Access Error") \ + X(SNOC, 45, 0x0D, "MISC MMIO Access Error") \ + X(SNOC, 44, 0x0C, "MISC MMP Access Error") \ + X(SNOC, 43, 0x0B, "MISC Response Parity Error") \ + X(SNOC, 42, 0x0A, "MISC FillData Parity Error") \ + X(SNOC, 41, 0x09, "MISC FillData Uncorrectable ECC Error") \ + X(SNOC, 40, 0x08, "DVMU Parity Error") \ + X(SNOC, 39, 0x07, "DVMU Timeout Error") \ + X(SNOC, 38, 0x06, "CPE Request Error") \ + X(SNOC, 37, 0x05, "CPE Response Error") \ + X(SNOC, 36, 0x04, "CPE Timeout Error") \ + X(SNOC, 35, 0x03, "Carveout Uncorrectable Error") \ + X(SNOC, 34, 0x02, "Lockable CREG Error") + +/* SNOC Corrected RAS ERROR */ +#define SNOC_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SNOC, 33, 0x01, "MISC FillData Corrected ECC Error") \ + X(SNOC, 32, 0x00, "Carveout Corrected Error") + +/* SCC Uncorrectable RAS ERROR */ +#define SCC_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCC, 51, 0x13, "SNOC Interface Parity Error") \ + X(SCC, 50, 0x12, "MCF Interface Parity Error") \ + X(SCC, 49, 0x11, "L3 Tag Parity Error") \ + X(SCC, 48, 0x10, "L2 Dir Parity Error") \ + X(SCC, 47, 0x0F, "URT Parity Error") \ + X(SCC, 46, 0x0E, "SWAT Parity Error") \ + X(SCC, 45, 0x0D, "L3 Data Parity Error") \ + X(SCC, 44, 0x0C, "URT FC Error") \ + X(SCC, 43, 0x0B, "SWAT FC Error") \ + X(SCC, 42, 0x0A, "Uncorrected ECC Error") \ + X(SCC, 41, 0x09, "Address Range Error") \ + X(SCC, 40, 0x08, "Unsupported Request Error") \ + X(SCC, 39, 0x07, "Multiple Hit CAM Error") \ + X(SCC, 38, 0x06, "Multiple Hit Tag Error") \ + X(SCC, 37, 0x05, "Protocol Error") \ + X(SCC, 36, 0x04, "Timeout Error") \ + X(SCC, 35, 0x03, "Destination Error") \ + X(SCC, 34, 0x02, "URT FC Timeout Error") \ + X(SCC, 33, 0x01, "SWAT FC Timeout Error") \ + X(SCC, 32, 0x00, "Lock Error") + +/* SCC Corrected RAS ERROR */ +#define SCC_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(SCC, 52, 0x14, "Corrected ECC Error") + +/* ACI Uncorrectable RAS ERROR */ +#define ACI_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(ACI, 49, 0x11, "Uncorrectable ECC Error") \ + X(ACI, 48, 0x10, "MST ADB error") \ + X(ACI, 47, 0x0F, "AXI FuSa Error") \ + X(ACI, 46, 0x0E, "AXI Parity Error") \ + X(ACI, 45, 0x0D, "SNOC Write Error") \ + X(ACI, 44, 0x0C, "ACE AW Decode Error") \ + X(ACI, 43, 0x0B, "Unexpected WU Error") \ + X(ACI, 42, 0x0A, "Snoop Error") \ + X(ACI, 41, 0x09, "FillWrite Error") \ + X(ACI, 40, 0x08, "DVM Error") \ + X(ACI, 39, 0x07, "ACE Parity Error") \ + X(ACI, 38, 0x06, "Internal ACI parity Error") \ + X(ACI, 37, 0x05, "AR decode Error") \ + X(ACI, 36, 0x04, "SNOC Protocol Error") \ + X(ACI, 35, 0x03, "Internal ACI FIFO Error") \ + X(ACI, 34, 0x02, "SNOC Parity Error") \ + X(ACI, 33, 0x01, "Lockable CREG Error") + +/* ACI Corrected RAS ERROR */ +#define ACI_CORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(ACI, 32, 0x00, "SNOC Corrected ECC Error") + +/* CORE DCLS Uncorrectable RAS ERROR */ +#define CORE_DCLS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(CORE_DCLS, 48, 0x10, "Redundant Clock, Power and Reset logic error") \ + X(CORE_DCLS, 47, 0x0F, "Redundant System Register Timer logic error") \ + X(CORE_DCLS, 46, 0x0E, "Redundant EVENT logic error") \ + X(CORE_DCLS, 45, 0x0D, "Redundant Timestamp logic error") \ + X(CORE_DCLS, 44, 0x0C, "Redundant APB group error") \ + X(CORE_DCLS, 42, 0x0A, "Redundant GIC group error") \ + X(CORE_DCLS, 41, 0x09, "Redundant CHI logic error") \ + X(CORE_DCLS, 40, 0x08, "Primary Clock, Power and Reset logic error") \ + X(CORE_DCLS, 39, 0x07, "Primary System Register Timer logic error") \ + X(CORE_DCLS, 38, 0x06, "Primary Event logic error") \ + X(CORE_DCLS, 37, 0x05, "Primary Timestamp logic error") \ + X(CORE_DCLS, 36, 0x04, "Primary APB group error") \ + X(CORE_DCLS, 35, 0x03, "Primary ATB group error") \ + X(CORE_DCLS, 34, 0x02, "Primary GIC group error") \ + X(CORE_DCLS, 33, 0x01, "Primary CHI logic error") \ + X(CORE_DCLS, 32, 0x00, "Lock error") + +/* Empty CORE DCLS Corrected RAS ERROR */ +#define CORE_DCLS_CORR_RAS_ERROR_LIST(X) + +/* DSU DCLS Uncorrectable RAS ERROR */ +#define DSU_DCLS_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(DSU_DCLS, 57, 0x19, "Illegal mode (CEMODE=0) error") \ + X(DSU_DCLS, 56, 0x18, "Core3 HM DCLS error") \ + X(DSU_DCLS, 55, 0x17, "Core2 HM DCLS error") \ + X(DSU_DCLS, 54, 0x16, "Core1 HM DCLS error") \ + X(DSU_DCLS, 53, 0x15, "Core0 HM DCLS error") \ + X(DSU_DCLS, 52, 0x14, "SB DBG group in DCLSFAULT vector") \ + X(DSU_DCLS, 51, 0x13, "SB GIC group in DCLSFAULT vector") \ + X(DSU_DCLS, 50, 0x12, "SB ATB group in DCLSFAULT vector") \ + X(DSU_DCLS, 49, 0x11, "SB EVENT group in DCLSFAULT vector") \ + X(DSU_DCLS, 48, 0x10, "SB CPM PERIPHCLK in DCLSFAULT vector") \ + X(DSU_DCLS, 47, 0x0F, "SB CPM SCLK in DCLSFAULT vector") \ + X(DSU_DCLS, 46, 0x0E, "SB slice in DCLSFAULT vector") \ + X(DSU_DCLS, 45, 0x0D, "SCU LTDB RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 44, 0x0C, "SCU VICTIM RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 43, 0x0B, "SCU DATA RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 42, 0x0A, "SCU SF RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 41, 0x09, "SCU TAG RAM in DCLSFAULT vector") \ + X(DSU_DCLS, 37, 0x05, "SCU MISC group in DCLSFAULT vector") \ + X(DSU_DCLS, 34, 0x02, "ACE Master 1 in DCLSFAULT vector") \ + X(DSU_DCLS, 33, 0x01, "ACE Master 0 in DCLSFAULT vector") \ + X(DSU_DCLS, 32, 0x00, "Lock Error") + +/* Empty DSU DCLS Corrected RAS ERROR */ +#define DSU_DCLS_CORR_RAS_ERROR_LIST(X) + +/* DSU_IFP Uncorrectable RAS ERROR */ +#define DSU_IFP_UNCORR_RAS_ERROR_LIST(X) \ + /* Name, ERR_CTRL, IERR, ISA Desc */ \ + X(DSU_IFP, 60, 0x1C, "Errors on POD reset output - it raises error if POD asserts the reset") \ + X(DSU_IFP, 59, 0x1B, "Errors on AXI4 Stream. Flagged for ADB, parity and redundancy errors") \ + X(DSU_IFP, 58, 0x1A, "NV defined core RAS pinned out interface error") \ + X(DSU_IFP, 57, 0x19, "NV defined cluster RAS interrupt interface error") \ + X(DSU_IFP, 56, 0x18, "NV defined cluster reqack interface error") \ + X(DSU_IFP, 55, 0x17, "NV defined core status interface error") \ + X(DSU_IFP, 54, 0x16, "NV defined cluster config interface error") \ + X(DSU_IFP, 53, 0x15, "NV defined cluster power management interface error") \ + X(DSU_IFP, 52, 0x14, "Miscellaneous interface parity error") \ + X(DSU_IFP, 51, 0x13, "Clock/Power related interface parity error") \ + X(DSU_IFP, 49, 0x11, "GIC interface parity error") \ + X(DSU_IFP, 44, 0x0C, "ACE Master 1 interface parity error") \ + X(DSU_IFP, 43, 0x0B, "ACE Master 0 interface parity error") \ + X(DSU_IFP, 42, 0x0A, "Miscellaneous interface parity error") \ + X(DSU_IFP, 41, 0x09, "Clock/Power related interface parity error") \ + X(DSU_IFP, 39, 0x07, "GIC interface parity error") \ + X(DSU_IFP, 34, 0x02, "ACE Master 1 interface parity error") \ + X(DSU_IFP, 33, 0x01, "ACE Master 0 interface parity error") \ + X(DSU_IFP, 32, 0x00, "Lock error") + +/* Empty DSU_IFP Corrected RAS ERROR */ +#define DSU_IFP_CORR_RAS_ERROR_LIST(X) + +/* Empty GIC600_FMU Uncorrected RAS ERROR */ +#define GIC600_FMU_UNCORR_RAS_ERROR_LIST(X) + +/* Empty GIC600_FMU Corrected RAS ERROR */ +#define GIC600_FMU_CORR_RAS_ERROR_LIST(X) + +/* + * Define one ras_error entry. + * + * This macro wille be used to to generate ras_error records for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ONE_RAS_ERROR_MSG(unit, err_ctrl_bit, ierr, msg) \ + { \ + .error_msg = (msg), \ + .error_code = (ierr) \ + }, + +/* + * Set one implementation defined bit in ERRCTLR + * + * This macro will be used to collect all defined ERR_CTRL bits for each node + * defined by _UNCORR_RAS_ERROR_LIST macro. + */ +#define DEFINE_ENABLE_BIT(unit, err_ctrl_bit, ierr, msg) \ + do { \ + val |= (1ULL << err_ctrl_bit##U); \ + } while (0); + +/* Represent one RAS node with 0 or more error bits (ERR_CTLR) enabled */ +#define DEFINE_ONE_RAS_NODE(node) \ +static struct ras_error node##_uncorr_ras_errors[] = { \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ONE_RAS_ERROR_MSG) \ +}; \ +static inline uint64_t node##_get_ue_mask(void) \ +{ \ + uint64_t val = 0ULL; \ + node##_UNCORR_RAS_ERROR_LIST(DEFINE_ENABLE_BIT) \ + return val; \ +}; \ +static inline uint64_t node##_get_ce_mask(void) \ +{ \ + uint64_t val = 0ULL; \ + node##_CORR_RAS_ERROR_LIST(DEFINE_ENABLE_BIT) \ + return val; \ +} + +#define DEFINE_ONE_RAS_AUX_DATA(node) \ +static struct ras_aux_data node##_aux_data = { \ + .name = #node, \ + .error_records = node##_uncorr_ras_errors, \ + .num_err_records = ARRAY_SIZE(node##_uncorr_ras_errors), \ + .get_ue_mask = &node##_get_ue_mask, \ + .get_ce_mask = &node##_get_ce_mask \ + } + +/* + * ERRFR bits[63:32], it indicates supported RAS errors which can be enabled + * by setting corresponding bits in ERRCTLR + */ +#define ERR_FR_EN_BITS_MASK U(0xFFFFFFFF00000000) + +/* IH RAS MUX registers */ +#define IH_RAS_MUX_BASE U(0x0E005000) +#define CORE0_RAS_GENERAL_MASK U(0x000) +#define CORE0_RAS_GENERAL_ENABLE U(0x008) +#define CORE0_RAS_INSTATUS U(0x010) +#define CORE0_RAS_INSTATUS_CLR U(0x018) +#define RAS_GLOBAL_EN U(0x820) + +/* IH RAS MUX register settings */ +#define ENB_ALL_INTR_SOURCES U(0x0000FFFFFF3F3F7F) +#define IH_INTR_ROUTING_ENABLED (BIT(17) | BIT(16)| U(0xFFF)) + +/* Per core offset to get to the core's IH registers */ +#define PER_CORE_IH_OFFSET U(0x28) + +static inline uint64_t ih_read_ras_intstatus(int core) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_INSTATUS; + return mmio_read_64(IH_RAS_MUX_BASE + offset); +} + +static inline void ih_write_intstatus_clr(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_INSTATUS_CLR; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); +} + +static inline void ih_write_ras_general_mask(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_GENERAL_MASK; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); + assert(mmio_read_64(IH_RAS_MUX_BASE + offset) == val); +} + +static inline void ih_write_ras_general_enb(int core, uint64_t val) +{ + uint32_t offset = (PER_CORE_IH_OFFSET * core) + CORE0_RAS_GENERAL_ENABLE; + mmio_write_64(IH_RAS_MUX_BASE + offset, val); + assert(mmio_read_64(IH_RAS_MUX_BASE + offset) == val); +} + +#endif /* TEGRA234_RAS_PRIVATE */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h new file mode 100644 index 0000000..4c3d308 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2018-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEGRA_DEF_H__ +#define __TEGRA_DEF_H__ + +#include + +/******************************************************************************* + * Platform BL31 specific defines. + ******************************************************************************/ +#define BL31_SIZE U(0x80000) + +/* Platform power domain constants*/ +#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)) + +/* Tegra CORE and CLUSTER affinity values */ +#define TEGRA_CORE_AFFINITY MPIDR_AFF1_SHIFT +#define TEGRA_CLUSTER_AFFINITY MPIDR_AFF2_SHIFT + +/******************************************************************************* + * 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 TEGRA234_RAS_PPI_ERI U(16) +#define TEGRA234_RAS_PPI_FHI U(17) +#define TEGRA234_TOP_WDT_IRQ U(49) +#define TEGRA234_AON_WDT_IRQ U(50) +#define PLATFORM_FIQ_PPI_WDT TEGRA234_TOP_WDT_IRQ + +/******************************************************************************* + * Clock identifier for the SE device + ******************************************************************************/ +#define TEGRA234_CLK_SEU1 U(336) +#define TEGRA_CLK_SE TEGRA234_CLK_SEU1 + +/******************************************************************************* + * 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) + +/******************************************************************************* + * Tegra General Purpose Centralised DMA constants + ******************************************************************************/ +#define TEGRA_GPCDMA_BASE U(0x02600000) + +/******************************************************************************* + * Tegra Memory Controller constants + ******************************************************************************/ +#define TEGRA_MC_STREAMID_BASE U(0x02C00000) +#define TEGRA_MC_STREAMID_LIMIT U(0x02C0FFFF) +#define TEGRA_MC_BASE U(0x02C10000) +#define TEGRA_MC_LIMIT U(0x02C1FFFF) + +/* 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) + +/* CCPLEX-BPMP IPC carveout (MC_SECURITY_CARVEOUT18) configuration registers */ +#define MC_CCPLEX_BPMP_IPC_BASE_LO U(0x23c4) +#define MC_CCPLEX_BPMP_IPC_BASE_HI U(0x23c8) + +/* 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) + +/******************************************************************************* + * Tegra Fuse Controller related constants + ******************************************************************************/ +#define TEGRA_FUSE_BASE U(0x03810000) +#define SECURITY_MODE U(0x1A0) +#define OPT_SUBREVISION U(0x248) +#define SUBREVISION_MASK U(0xF) + +/******************************************************************************* + * Security Engine related constants + ******************************************************************************/ +#define TEGRA_RNG1_BASE U(0x03B70000) +#define NV_NVRNG_R_CTRL U(0x8C) +#define SW_ENGINE_ENABLED BIT_32(2) + +#define TEGRA_SE0_BASE U(0x03B50000) +#define TEGRA_PKA1_BASE U(0x03AD0000) + +/******************************************************************************* + * 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(0x0C6B0000) +#define TEGRA_TMRUS_SIZE U(0x10000) + +/******************************************************************************* + * Tegra Power Mgmt Controller constants + ******************************************************************************/ +#define TEGRA_PMC_BASE U(0x0C360000) +#define TEGRA_PMC_SIZE U(0x1000) + +/******************************************************************************* + * Tegra scratch registers constants + ******************************************************************************/ +#define TEGRA_SCRATCH_BASE U(0x0C390000) +#define SECURE_SCRATCH_RSV28_LO U(0x144) +#define SECURE_SCRATCH_RSV28_HI U(0x148) +#define SECURE_SCRATCH_RSV33_LO U(0x16C) +#define SECURE_SCRATCH_RSV33_HI U(0x170) +#define SECURE_SCRATCH_RSV34_LO U(0x174) +#define SECURE_SCRATCH_RSV34_HI U(0x178) +#define SECURE_SCRATCH_RSV41_LO U(0x1AC) +#define SECURE_SCRATCH_RSV97 U(0x36C) +#define SECURE_SCRATCH_RSV99_LO U(0x37C) +#define SECURE_SCRATCH_RSV99_HI U(0x380) + +#define SCRATCH_BL31_PARAMS_HI_ADDR SECURE_SCRATCH_RSV33_HI +#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_RSV33_LO +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR SECURE_SCRATCH_RSV34_HI +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK U(0xFFFF) +#define SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT U(0) +#define SCRATCH_BL31_PLAT_PARAMS_LO_ADDR SECURE_SCRATCH_RSV34_LO +#define SCRATCH_IST_CLK_ENABLE SECURE_SCRATCH_RSV41_LO +#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_RSV28_LO +#define SCRATCH_RESET_VECTOR_HI SECURE_SCRATCH_RSV28_HI + +/******************************************************************************* + * Tegra AON Fabric constants + ******************************************************************************/ +#define TEGRA_AON_FABRIC_FIREWALL_BASE U(0x0C630000) +#define AON_FIREWALL_ARF_0_WRITE_CTL U(0x8) +#define WRITE_CTL_MSTRID_TZ_BIT BIT(0) +#define WRITE_CTL_MSTRID_BPMP_FW_BIT BIT(3) +#define AON_FIREWALL_ARF_0_CTL U(0x10) +#define ARF_CTL_OWNER_BPMP_FW U(3) + +/******************************************************************************* + * Tegra Memory Mapped Control Register Access Bus constants + ******************************************************************************/ +#define TEGRA_MMCRAB_BASE U(0x0E000000) + +/******************************************************************************* + * MCE apertures used by the ARI interface + * + * Aperture 0 - cluster0 Cpu0 + * Aperture 1 - cluster0 Cpu1 + * Aperture 2 - cluster0 Cpu2 + * Aperture 3 - cluster0 Cpu3 + * Aperture 4 - cluster1 Cpu0 + * Aperture 5 - cluster1 Cpu1 + * Aperture 6 - cluster1 Cpu2 + * Aperture 7 - cluster1 Cpu3 + * Aperture 8 - cluster2 Cpu0 + * Aperture 9 - cluster2 Cpu1 + * Aperture 10 - cluster2 Cpu2 + * Aperture 11 - cluster2 Cpu3 + ******************************************************************************/ +#define MCE_ARI_APERTURE_0_OFFSET U(0x200000) +#define MCE_ARI_APERTURE_1_OFFSET U(0x210000) +#define MCE_ARI_APERTURE_2_OFFSET U(0x220000) +#define MCE_ARI_APERTURE_3_OFFSET U(0x230000) +#define MCE_ARI_APERTURE_4_OFFSET U(0x240000) +#define MCE_ARI_APERTURE_5_OFFSET U(0x250000) +#define MCE_ARI_APERTURE_6_OFFSET U(0x260000) +#define MCE_ARI_APERTURE_7_OFFSET U(0x270000) +#define MCE_ARI_APERTURE_8_OFFSET U(0x280000) +#define MCE_ARI_APERTURE_9_OFFSET U(0x290000) +#define MCE_ARI_APERTURE_10_OFFSET U(0x2A0000) +#define MCE_ARI_APERTURE_11_OFFSET U(0x2B0000) + +/******************************************************************************* + * GICv3 constants + ******************************************************************************/ +#define TEGRA_GICD_BASE U(0x0F400000) +#define TEGRA_GICR_BASE U(0x0F440000) +#define TEGRA_GICFMU_BASE U(0x0F7F0000) + +/******************************************************************************* + * Tegra SMMU Controller constants + ******************************************************************************/ +#define TEGRA_SMMU0_BASE U(0x12000000) +#define TEGRA_SMMU1_BASE U(0x11000000) +#define TEGRA_SMMU2_BASE U(0x10000000) +#define TEGRA_SMMU3_BASE U(0x07000000) +#define TEGRA_SMMU4_BASE U(0x08000000) + +/******************************************************************************* + * Tegra PSC mailbox + ******************************************************************************/ +#define TEGRA_PSC_MBOX_TZ_BASE U(0x0E830000) +#define PSC_MBOX_TZ_EXT_CTRL U(0x0004) +#define PSC_MBOX_TZ_PSC_CTRL U(0x0008) +#define PSC_MBOX_TZ_IN U(0x0800) +#define PSC_MBOX_TZ_OUT_0 U(0x1000) +#define PSC_MBOX_TZ_OUT_1 U(0x1004) +#define PSC_MBOX_OUT_DONE U(0x10) +#define PSC_MBOX_IN_VALID U(0x1) +#define PSC_MBOX_IN_DONE U(0x10) +#define PSC_MBOX_OUT_VALID U(0x1) +#define PSC_MBOX_TZ_OPCODE_ENTER_SC7 U(0x53433745) +#define PSC_MBOX_SC7_ENTRY_PASS U(0x0) +#define PSC_MBOX_ACK_TIMEOUT_MAX_USEC U(50) + + +/******************************************************************************* + * RAS records + ******************************************************************************/ +#define TEGRA_CCPMU_RAS_BASE U(0x0E001000) +#define TEGRA_RAS_CL0_CORE0_BASE U(0x0E030000) +#define TEGRA_RAS_CL1_CORE0_BASE U(0x0E040000) +#define TEGRA_RAS_CL2_CORE0_BASE U(0x0E050000) + +/******************************************************************************* + * Tegra TZRAM constants + ******************************************************************************/ +#define TEGRA_TZRAM_BASE U(0x50000000) +#define TEGRA_TZRAM_SIZE U(0x40000) + +/******************************************************************************* + * Tegra CCPLEX-BPMP IPC constants + ******************************************************************************/ +#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(0x0) +#define TEGRA_GPU_RESET_GPU_SET_OFFSET U(0x4) +#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(0x207FFFFFFF) + +/******************************************************************************* + * 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) + +/******************************************************************************* + * Tegra SYSRAM base and limit. + ******************************************************************************/ +#define TEGRA_SYSRAM_BASE U(0x40000000) +#define TEGRA_SYSRAM_SIZE U(0x10000000) + +/******************************************************************************* + * Tegra Debug APB base address and ETM related constants + ******************************************************************************/ +#define TEGRA_DBGAPB_BASE ULL(0x209F0000) +#define TEGRA_TRCPRGCTLR_OFFSET U(0x4) +#define TRCPRGCTLR_EN_BIT BIT_32(0) + +#endif /* __TEGRA_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h new file mode 100644 index 0000000..8dc5603 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h @@ -0,0 +1,685 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __TEGRA_MC_DEF_H__ +#define __TEGRA_MC_DEF_H__ + +/******************************************************************************* + * Memory Controller Order_id registers + ******************************************************************************/ +#define MC_CLIENT_ORDER_ID_9 U(0x2a24) +#define MC_CLIENT_ORDER_ID_9_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_9_XUSB_HOSTW_MASK (0x3U << 12) +#define MC_CLIENT_ORDER_ID_9_XUSB_HOSTW_ORDER_ID (3U << 12) + +#define MC_CLIENT_ORDER_ID_27 U(0x2a6c) +#define MC_CLIENT_ORDER_ID_27_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_27_PCIE0W_MASK (0x3U << 4) +#define MC_CLIENT_ORDER_ID_27_PCIE0W_ORDER_ID (2U << 4) + +#define MC_CLIENT_ORDER_ID_28 U(0x2a70) +#define MC_CLIENT_ORDER_ID_28_RESET_VAL 0x00000000U +#define MC_CLIENT_ORDER_ID_28_PCIE4W_MASK (0x3U << 4) +#define MC_CLIENT_ORDER_ID_28_PCIE4W_ORDER_ID (3U << 4) +#define MC_CLIENT_ORDER_ID_28_PCIE5W_MASK (0x3U << 12) +#define MC_CLIENT_ORDER_ID_28_PCIE5W_ORDER_ID (1U << 12) + +#define mc_client_order_id(val, id, client) \ + ((val & ~MC_CLIENT_ORDER_ID_##id##_##client##_MASK) | \ + MC_CLIENT_ORDER_ID_##id##_##client##_ORDER_ID) + +/******************************************************************************* + * Memory Controller's VC ID configuration registers + ******************************************************************************/ +#define VC_NISO 0U +#define VC_SISO 1U +#define VC_ISO 2U + +#define MC_HUB_PC_VC_ID_0 U(0x2a78) +#define MC_HUB_PC_VC_ID_0_RESET_VAL 0x00020100U +#define MC_HUB_PC_VC_ID_0_APB_VC_ID_MASK (0x3U << 8) +#define MC_HUB_PC_VC_ID_0_APB_VC_ID (VC_NISO << 8) + +#define MC_HUB_PC_VC_ID_2 U(0x2a80) +#define MC_HUB_PC_VC_ID_2_RESET_VAL 0x10001000U +#define MC_HUB_PC_VC_ID_2_SD_VC_ID_MASK (0x3U << 28) +#define MC_HUB_PC_VC_ID_2_SD_VC_ID (VC_NISO << 28) + +#define MC_HUB_PC_VC_ID_4 U(0x2a88) +#define MC_HUB_PC_VC_ID_4_RESET_VAL 0x10020011U +#define MC_HUB_PC_VC_ID_4_NIC_VC_ID_MASK (0x3U << 28) +#define MC_HUB_PC_VC_ID_4_NIC_VC_ID (VC_NISO << 28) + +#define MC_HUB_PC_VC_ID_12 U(0x2aa8) +#define MC_HUB_PC_VC_ID_12_RESET_VAL 0x11001011U +#define MC_HUB_PC_VC_ID_12_UFSHCPC2_VC_ID_MASK (0x3U << 12) +#define MC_HUB_PC_VC_ID_12_UFSHCPC2_VC_ID (VC_NISO << 12) + +#define mc_hub_vc_id(val, id, client) \ + ((val & ~MC_HUB_PC_VC_ID_##id##_##client##_VC_ID_MASK) | \ + MC_HUB_PC_VC_ID_##id##_##client##_VC_ID) + +/******************************************************************************* + * 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 0x20200000U +#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_ORDERED (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG1_PCFIFO_SATAW_MASK (1U << 29) + +#define MC_PCFIFO_CLIENT_CONFIG2 0xdd8U +#define MC_PCFIFO_CLIENT_CONFIG2_RESET_VAL 0x00002800U +#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_ORDERED (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_XUSB_DEVW_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_TSECSWR_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG2_PCFIFO_TSECSWR_MASK (1U << 21) + +#define MC_PCFIFO_CLIENT_CONFIG3 0xddcU +#define MC_PCFIFO_CLIENT_CONFIG3_RESET_VAL 0x08000080U +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWA_UNORDERED (0U << 4) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWA_MASK (1U << 4) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCW_UNORDERED (0U << 6) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCW_MASK (1U << 6) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_UNORDERED (0U << 7) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_SDMMCWAB_MASK (1U << 7) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_VICSWR_UNORDERED (0U << 13) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_VICSWR_MASK (1U << 13) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_APEW_UNORDERED (0U << 27) +#define MC_PCFIFO_CLIENT_CONFIG3_PCFIFO_APEW_MASK (1U << 27) + +#define MC_PCFIFO_CLIENT_CONFIG4 0xde0U +#define MC_PCFIFO_CLIENT_CONFIG4_RESET_VAL 0x5552a022U +#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_TSECSWRB_UNORDERED (0U << 7) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_TSECSWRB_MASK (1U << 7) +#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_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_BPMPW_UNORDERED (0U << 20) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_BPMPW_MASK (1U << 20) +#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_AONW_UNORDERED (0U << 24) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_AONW_MASK (1U << 24) +#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_SCEW_UNORDERED (0U << 28) +#define MC_PCFIFO_CLIENT_CONFIG4_PCFIFO_SCEW_MASK (1U << 28) +#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 0x20000001U +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_UNORDERED (0U << 0) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_APEDMAW_MASK (1U << 0) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_VIFALW_UNORDERED (0U << 30) +#define MC_PCFIFO_CLIENT_CONFIG5_PCFIFO_VIFALW_MASK (1U << 30) + +#define MC_PCFIFO_CLIENT_CONFIG6 0xb90U +#define MC_PCFIFO_CLIENT_CONFIG6_RESET_VAL 0xaa280000U +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEW_UNORDERED (0U << 19) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEW_MASK (1U << 19) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEDMAW_UNORDERED (0U << 21) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_RCEDMAW_MASK (1U << 21) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE0W_UNORDERED (0U << 25) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE0W_MASK (1U << 25) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE1W_ORDERED (1U << 27) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE1W_MASK (1U << 27) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE2W_ORDERED (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE2W_MASK (1U << 29) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE3W_ORDERED (1U << 31) +#define MC_PCFIFO_CLIENT_CONFIG6_PCFIFO_PCIE3W_MASK (1U << 31) + +#define MC_PCFIFO_CLIENT_CONFIG7 0xaccU +#define MC_PCFIFO_CLIENT_CONFIG7_RESET_VAL 0x0000000aU +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE4W_UNORDERED (0U << 1) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE4W_MASK (1U << 1) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE5W_UNORDERED (0U << 3) +#define MC_PCFIFO_CLIENT_CONFIG7_PCFIFO_PCIE5W_MASK (1U << 3) + +/******************************************************************************* + * StreamID to indicate no SMMU translations (requests to be steered on the + * SMMU bypass path) + ******************************************************************************/ +#define MC_STREAM_ID_MAX 0x7FU + +/******************************************************************************* + * Stream ID Override Config registers + ******************************************************************************/ +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDA 0x660U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD 0xe0U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSWR 0x3f8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDA1 0x758U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDC 0x640U +#define MC_STREAMID_OVERRIDE_CFG_DLA0RDA 0x5f0U +#define MC_STREAMID_OVERRIDE_CFG_BPMPR 0x498U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAR 0x4f8U +#define MC_STREAMID_OVERRIDE_CFG_AXISR 0x460U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRD 0x2a0U +#define MC_STREAMID_OVERRIDE_CFG_DLA0FALRDB 0x5f8U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SRD1 0x788U +#define MC_STREAMID_OVERRIDE_CFG_MPCOREW 0x1c8U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSRD1 0x780U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTR 0x250U +#define MC_STREAMID_OVERRIDE_CFG_MIU1R 0x540U +#define MC_STREAMID_OVERRIDE_CFG_MIU0R 0x530U +#define MC_STREAMID_OVERRIDE_CFG_PCIE1W 0x6d8U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRA 0x678U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_HOSTW 0x258U +#define MC_STREAMID_OVERRIDE_CFG_AXIAPW 0x418U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWAB 0x338U +#define MC_STREAMID_OVERRIDE_CFG_SATAW 0x1e8U +#define MC_STREAMID_OVERRIDE_CFG_DLA0WRA 0x600U +#define MC_STREAMID_OVERRIDE_CFG_PCIE3R 0x6f0U +#define MC_STREAMID_OVERRIDE_CFG_MIU3W 0x588U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAR 0x4e8U +#define MC_STREAMID_OVERRIDE_CFG_HOST1XDMAR 0xb0U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCWA 0x320U +#define MC_STREAMID_OVERRIDE_CFG_MIU2R 0x570U +#define MC_STREAMID_OVERRIDE_CFG_APEDMAW 0x500U +#define MC_STREAMID_OVERRIDE_CFG_PCIE2AW 0x6e8U +#define MC_STREAMID_OVERRIDE_CFG_SESWR 0x408U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDB1 0x770U +#define MC_STREAMID_OVERRIDE_CFG_AXISW 0x468U +#define MC_STREAMID_OVERRIDE_CFG_DLA1FALRDB 0x618U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAW 0x4d0U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWRB 0x438U +#define MC_STREAMID_OVERRIDE_CFG_ISPWB 0x238U +#define MC_STREAMID_OVERRIDE_CFG_HDAR 0xa8U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRA 0x300U +#define MC_STREAMID_OVERRIDE_CFG_ETRW 0x428U +#define MC_STREAMID_OVERRIDE_CFG_RCEDMAW 0x6a8U +#define MC_STREAMID_OVERRIDE_CFG_TSECSWR 0x2a8U +#define MC_STREAMID_OVERRIDE_CFG_ETRR 0x420U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCR 0x310U +#define MC_STREAMID_OVERRIDE_CFG_NVJPGSRD 0x3f0U +#define MC_STREAMID_OVERRIDE_CFG_AONDMAR 0x4c8U +#define MC_STREAMID_OVERRIDE_CFG_SCER 0x4d8U +#define MC_STREAMID_OVERRIDE_CFG_MIU5W 0x7e8U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SRD 0x6b0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE4R 0x700U +#define MC_STREAMID_OVERRIDE_CFG_ISPWA 0x230U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0W 0x6c8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5R1 0x778U +#define MC_STREAMID_OVERRIDE_CFG_DLA1RDA 0x610U +#define MC_STREAMID_OVERRIDE_CFG_VICSWR 0x368U +#define MC_STREAMID_OVERRIDE_CFG_SESRD 0x400U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCW 0x330U +#define MC_STREAMID_OVERRIDE_CFG_SDMMCRAB 0x318U +#define MC_STREAMID_OVERRIDE_CFG_ISPFALW 0x720U +#define MC_STREAMID_OVERRIDE_CFG_EQOSW 0x478U +#define MC_STREAMID_OVERRIDE_CFG_RCEDMAR 0x6a0U +#define MC_STREAMID_OVERRIDE_CFG_RCER 0x690U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSWR 0x3c8U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCR 0x480U +#define MC_STREAMID_OVERRIDE_CFG_PCIE4W 0x708U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD 0x360U +#define MC_STREAMID_OVERRIDE_CFG_APER 0x3d0U +#define MC_STREAMID_OVERRIDE_CFG_MIU7R 0x8U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD 0x7c8U +#define MC_STREAMID_OVERRIDE_CFG_MIU7W 0x10U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDA1 0x768U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRC 0x688U +#define MC_STREAMID_OVERRIDE_CFG_AONW 0x4c0U +#define MC_STREAMID_OVERRIDE_CFG_MIU4W 0x598U +#define MC_STREAMID_OVERRIDE_CFG_HDAW 0x1a8U +#define MC_STREAMID_OVERRIDE_CFG_BPMPW 0x4a0U +#define MC_STREAMID_OVERRIDE_CFG_DLA1WRA 0x620U +#define MC_STREAMID_OVERRIDE_CFG_DLA0RDA1 0x748U +#define MC_STREAMID_OVERRIDE_CFG_MIU1W 0x548U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR1 0x508U +#define MC_STREAMID_OVERRIDE_CFG_VICSRD1 0x510U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAW 0x4b0U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SWR 0x7d8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRC 0x658U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5R 0x710U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVR 0x260U +#define MC_STREAMID_OVERRIDE_CFG_UFSHCW 0x488U +#define MC_STREAMID_OVERRIDE_CFG_PVA1WRB 0x680U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRB 0x650U +#define MC_STREAMID_OVERRIDE_CFG_DLA1FALWRB 0x628U +#define MC_STREAMID_OVERRIDE_CFG_NVENC1SWR 0x6b8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0R 0x6c0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE3W 0x6f8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDA 0x630U +#define MC_STREAMID_OVERRIDE_CFG_MIU6W 0x7f8U +#define MC_STREAMID_OVERRIDE_CFG_PCIE1R 0x6d0U +#define MC_STREAMID_OVERRIDE_CFG_NVDEC1SRD1 0x7d0U +#define MC_STREAMID_OVERRIDE_CFG_DLA0FALWRB 0x608U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDC 0x670U +#define MC_STREAMID_OVERRIDE_CFG_MIU0W 0x538U +#define MC_STREAMID_OVERRIDE_CFG_MIU2W 0x578U +#define MC_STREAMID_OVERRIDE_CFG_MPCORER 0x138U +#define MC_STREAMID_OVERRIDE_CFG_AXIAPR 0x410U +#define MC_STREAMID_OVERRIDE_CFG_AONR 0x4b8U +#define MC_STREAMID_OVERRIDE_CFG_BPMPDMAR 0x4a8U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDB 0x638U +#define MC_STREAMID_OVERRIDE_CFG_VIFALW 0x5e8U +#define MC_STREAMID_OVERRIDE_CFG_MIU6R 0x7f0U +#define MC_STREAMID_OVERRIDE_CFG_EQOSR 0x470U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD 0x3c0U +#define MC_STREAMID_OVERRIDE_CFG_TSECSRDB 0x430U +#define MC_STREAMID_OVERRIDE_CFG_NVDECSRD1 0x518U +#define MC_STREAMID_OVERRIDE_CFG_PVA0RDB1 0x760U +#define MC_STREAMID_OVERRIDE_CFG_PCIE0R1 0x798U +#define MC_STREAMID_OVERRIDE_CFG_SCEDMAW 0x4f0U +#define MC_STREAMID_OVERRIDE_CFG_APEW 0x3d8U +#define MC_STREAMID_OVERRIDE_CFG_MIU5R 0x7e0U +#define MC_STREAMID_OVERRIDE_CFG_DLA1RDA1 0x750U +#define MC_STREAMID_OVERRIDE_CFG_PVA0WRA 0x648U +#define MC_STREAMID_OVERRIDE_CFG_ISPFALR 0x228U +#define MC_STREAMID_OVERRIDE_CFG_PTCR 0x0U +#define MC_STREAMID_OVERRIDE_CFG_MIU4R 0x590U +#define MC_STREAMID_OVERRIDE_CFG_ISPRA 0x220U +#define MC_STREAMID_OVERRIDE_CFG_VIFALR 0x5e0U +#define MC_STREAMID_OVERRIDE_CFG_PCIE2AR 0x6e0U +#define MC_STREAMID_OVERRIDE_CFG_RCEW 0x698U +#define MC_STREAMID_OVERRIDE_CFG_ISPRA1 0x790U +#define MC_STREAMID_OVERRIDE_CFG_SCEW 0x4e0U +#define MC_STREAMID_OVERRIDE_CFG_MIU3R 0x580U +#define MC_STREAMID_OVERRIDE_CFG_XUSB_DEVW 0x268U +#define MC_STREAMID_OVERRIDE_CFG_SATAR 0xf8U +#define MC_STREAMID_OVERRIDE_CFG_NVDISPLAYR 0x490U +#define MC_STREAMID_OVERRIDE_CFG_PVA1RDB 0x668U +#define MC_STREAMID_OVERRIDE_CFG_VIW 0x390U +#define MC_STREAMID_OVERRIDE_CFG_NVENCSWR 0x158U +#define MC_STREAMID_OVERRIDE_CFG_PCIE5W 0x718U + +/******************************************************************************* + * 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_DLA1WRA 0x1624U +#define MC_TXN_OVERRIDE_CONFIG_PCIE1W 0x16dcU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDC 0x1644U +#define MC_TXN_OVERRIDE_CONFIG_PTCR 0x1000U +#define MC_TXN_OVERRIDE_CONFIG_EQOSW 0x1478U +#define MC_TXN_OVERRIDE_CONFIG_MPCOREW 0x11c8U +#define MC_TXN_OVERRIDE_CONFIG_DLA1FALWRB 0x162cU +#define MC_TXN_OVERRIDE_CONFIG_AXISR 0x1460U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRB 0x1654U +#define MC_TXN_OVERRIDE_CONFIG_MIU6R 0x17f4U +#define MC_TXN_OVERRIDE_CONFIG_MIU5R 0x17e4U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD1 0x1784U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0R 0x16c4U +#define MC_TXN_OVERRIDE_CONFIG_EQOSR 0x1470U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSRD 0x10e0U +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SRD1 0x178cU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDB1 0x1774U +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SWR 0x16bcU +#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_PCIE5R 0x1714U +#define MC_TXN_OVERRIDE_CONFIG_AXISW 0x1468U +#define MC_TXN_OVERRIDE_CONFIG_MIU6W 0x17fcU +#define MC_TXN_OVERRIDE_CONFIG_UFSHCR 0x1480U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0R1 0x179cU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDB1 0x1764U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWR 0x12a8U +#define MC_TXN_OVERRIDE_CONFIG_MIU7R 0x1008U +#define MC_TXN_OVERRIDE_CONFIG_SATAR 0x10f8U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTW 0x1258U +#define MC_TXN_OVERRIDE_CONFIG_DLA0RDA 0x15f4U +#define MC_TXN_OVERRIDE_CONFIG_TSECSWRB 0x1438U +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SWR 0x17dcU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDA1 0x176cU +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDB 0x166cU +#define MC_TXN_OVERRIDE_CONFIG_AONDMAW 0x14d0U +#define MC_TXN_OVERRIDE_CONFIG_AONW 0x14c0U +#define MC_TXN_OVERRIDE_CONFIG_ETRR 0x1420U +#define MC_TXN_OVERRIDE_CONFIG_PCIE2AW 0x16ecU +#define MC_TXN_OVERRIDE_CONFIG_PCIE1R 0x16d4U +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDC 0x1674U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRA 0x164cU +#define MC_TXN_OVERRIDE_CONFIG_TSECSRDB 0x1430U +#define MC_TXN_OVERRIDE_CONFIG_MIU1W 0x1548U +#define MC_TXN_OVERRIDE_CONFIG_PCIE0W 0x16ccU +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SRD 0x17ccU +#define MC_TXN_OVERRIDE_CONFIG_MIU7W 0x1010U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD1 0x1518U +#define MC_TXN_OVERRIDE_CONFIG_MIU3R 0x1580U +#define MC_TXN_OVERRIDE_CONFIG_MIU3W 0x158cU +#define MC_TXN_OVERRIDE_CONFIG_XUSB_HOSTR 0x1250U +#define MC_TXN_OVERRIDE_CONFIG_SESRD 0x1400U +#define MC_TXN_OVERRIDE_CONFIG_SCER 0x14d8U +#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_PVA0RDA 0x1634U +#define MC_TXN_OVERRIDE_CONFIG_AONDMAR 0x14c8U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCWAB 0x1338U +#define MC_TXN_OVERRIDE_CONFIG_ISPFALR 0x1228U +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDA1 0x175cU +#define MC_TXN_OVERRIDE_CONFIG_NVENC1SRD 0x16b4U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR1 0x1508U +#define MC_TXN_OVERRIDE_CONFIG_PVA1RDA 0x1664U +#define MC_TXN_OVERRIDE_CONFIG_DLA0RDA1 0x174cU +#define MC_TXN_OVERRIDE_CONFIG_ISPWB 0x1238U +#define MC_TXN_OVERRIDE_CONFIG_APEW 0x13d8U +#define MC_TXN_OVERRIDE_CONFIG_AXIAPR 0x1410U +#define MC_TXN_OVERRIDE_CONFIG_PCIE2AR 0x16e4U +#define MC_TXN_OVERRIDE_CONFIG_ISPFALW 0x1724U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCR 0x1310U +#define MC_TXN_OVERRIDE_CONFIG_MIU2W 0x1578U +#define MC_TXN_OVERRIDE_CONFIG_RCER 0x1694U +#define MC_TXN_OVERRIDE_CONFIG_PCIE4W 0x170cU +#define MC_TXN_OVERRIDE_CONFIG_BPMPW 0x14a0U +#define MC_TXN_OVERRIDE_CONFIG_NVDISPLAYR 0x1490U +#define MC_TXN_OVERRIDE_CONFIG_ISPRA 0x1220U +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSWR 0x13f8U +#define MC_TXN_OVERRIDE_CONFIG_VICSRD 0x1360U +#define MC_TXN_OVERRIDE_CONFIG_NVDEC1SRD1 0x17d4U +#define MC_TXN_OVERRIDE_CONFIG_DLA1RDA 0x1614U +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAW 0x14f0U +#define MC_TXN_OVERRIDE_CONFIG_SDMMCW 0x1330U +#define MC_TXN_OVERRIDE_CONFIG_DLA1FALRDB 0x161cU +#define MC_TXN_OVERRIDE_CONFIG_APEDMAR 0x14f8U +#define MC_TXN_OVERRIDE_CONFIG_RCEW 0x169cU +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRAB 0x1318U +#define MC_TXN_OVERRIDE_CONFIG_DLA0WRA 0x1604U +#define MC_TXN_OVERRIDE_CONFIG_VIFALR 0x15e4U +#define MC_TXN_OVERRIDE_CONFIG_PCIE3R 0x16f4U +#define MC_TXN_OVERRIDE_CONFIG_MIU1R 0x1540U +#define MC_TXN_OVERRIDE_CONFIG_PCIE5W 0x171cU +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVR 0x1260U +#define MC_TXN_OVERRIDE_CONFIG_MIU0W 0x1538U +#define MC_TXN_OVERRIDE_CONFIG_DLA0FALWRB 0x160cU +#define MC_TXN_OVERRIDE_CONFIG_VIFALW 0x15ecU +#define MC_TXN_OVERRIDE_CONFIG_DLA0FALRDB 0x15fcU +#define MC_TXN_OVERRIDE_CONFIG_PCIE3W 0x16fcU +#define MC_TXN_OVERRIDE_CONFIG_MIU0R 0x1530U +#define MC_TXN_OVERRIDE_CONFIG_PVA0WRC 0x165cU +#define MC_TXN_OVERRIDE_CONFIG_SCEDMAR 0x14e8U +#define MC_TXN_OVERRIDE_CONFIG_APEDMAW 0x1500U +#define MC_TXN_OVERRIDE_CONFIG_HOST1XDMAR 0x10b0U +#define MC_TXN_OVERRIDE_CONFIG_SESWR 0x1408U +#define MC_TXN_OVERRIDE_CONFIG_AXIAPW 0x1418U +#define MC_TXN_OVERRIDE_CONFIG_MIU4R 0x1594U +#define MC_TXN_OVERRIDE_CONFIG_MIU4W 0x159cU +#define MC_TXN_OVERRIDE_CONFIG_NVJPGSRD 0x13f0U +#define MC_TXN_OVERRIDE_CONFIG_NVDECSRD 0x13c0U +#define MC_TXN_OVERRIDE_CONFIG_BPMPDMAW 0x14b0U +#define MC_TXN_OVERRIDE_CONFIG_APER 0x13d0U +#define MC_TXN_OVERRIDE_CONFIG_DLA1RDA1 0x1754U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRB 0x1684U +#define MC_TXN_OVERRIDE_CONFIG_ISPWA 0x1230U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRC 0x168cU +#define MC_TXN_OVERRIDE_CONFIG_RCEDMAR 0x16a4U +#define MC_TXN_OVERRIDE_CONFIG_ISPRA1 0x1794U +#define MC_TXN_OVERRIDE_CONFIG_AONR 0x14b8U +#define MC_TXN_OVERRIDE_CONFIG_RCEDMAW 0x16acU +#define MC_TXN_OVERRIDE_CONFIG_UFSHCW 0x1488U +#define MC_TXN_OVERRIDE_CONFIG_ETRW 0x1428U +#define MC_TXN_OVERRIDE_CONFIG_SATAW 0x11e8U +#define MC_TXN_OVERRIDE_CONFIG_VICSWR 0x1368U +#define MC_TXN_OVERRIDE_CONFIG_NVENCSWR 0x1158U +#define MC_TXN_OVERRIDE_CONFIG_PCIE5R1 0x177cU +#define MC_TXN_OVERRIDE_CONFIG_PVA0RDB 0x163cU +#define MC_TXN_OVERRIDE_CONFIG_SDMMCRA 0x1300U +#define MC_TXN_OVERRIDE_CONFIG_PVA1WRA 0x167cU +#define MC_TXN_OVERRIDE_CONFIG_MIU5W 0x17ecU +#define MC_TXN_OVERRIDE_CONFIG_BPMPR 0x1498U +#define MC_TXN_OVERRIDE_CONFIG_MIU2R 0x1570U +#define MC_TXN_OVERRIDE_CONFIG_XUSB_DEVW 0x1268U +#define MC_TXN_OVERRIDE_CONFIG_TSECSRD 0x12a0U +#define MC_TXN_OVERRIDE_CONFIG_PCIE4R 0x1704U +#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 << 17) +#define MC_CLIENT_HOTRESET_CTRL1_EQOS_FLUSH_ENB (1U << 18) +#define MC_CLIENT_HOTRESET_CTRL1_UFSHC_FLUSH_ENB (1U << 19) +#define MC_CLIENT_HOTRESET_CTRL1_NVDISPLAY_FLUSH_ENB (1U << 20) +#define MC_CLIENT_HOTRESET_CTRL1_BPMP_FLUSH_ENB (1U << 21) +#define MC_CLIENT_HOTRESET_CTRL1_AON_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL1_SCE_FLUSH_ENB (1U << 23) +#define MC_CLIENT_HOTRESET_CTRL1_VIFAL_FLUSH_ENB (1U << 26) +#define MC_CLIENT_HOTRESET_CTRL1_RCE_FLUSH_ENB (1U << 31) +#define MC_CLIENT_HOTRESET_STATUS1 0x974U +#define MC_CLIENT_HOTRESET_CTRL2 0x97cU +#define MC_CLIENT_HOTRESET_CTRL2_RESET_VAL 0U +#define MC_CLIENT_HOTRESET_CTRL2_RCEDMA_FLUSH_ENB (1U << 0) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE_FLUSH_ENB (1U << 2) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE5A_FLUSH_ENB (1U << 4) +#define MC_CLIENT_HOTRESET_CTRL2_AONDMA_FLUSH_ENB (1U << 9) +#define MC_CLIENT_HOTRESET_CTRL2_BPMPDMA_FLUSH_ENB (1U << 10) +#define MC_CLIENT_HOTRESET_CTRL2_SCEDMA_FLUSH_ENB (1U << 11) +#define MC_CLIENT_HOTRESET_CTRL2_APEDMA_FLUSH_ENB (1U << 14) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE3A_FLUSH_ENB (1U << 16) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE3_FLUSH_ENB (1U << 17) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE0A_FLUSH_ENB (1U << 22) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE0A2_FLUSH_ENB (1U << 23) +#define MC_CLIENT_HOTRESET_CTRL2_PCIE4A_FLUSH_ENB (1U << 25) +#define MC_CLIENT_HOTRESET_STATUS2 0x1898U + +#define MC_COALESCE_CTRL 0x2930U +#define MC_COALESCE_CTRL_COALESCER_ENABLE (1U << 31) +#define MC_COALESCE_CONFIG_6_0 0x294cU +#define MC_COALESCE_CONFIG_6_0_PVA0RDC_COALESCER_ENABLED (1U << 8) +#define MC_COALESCE_CONFIG_6_0_PVA1RDC_COALESCER_ENABLED (1U << 14) + +/******************************************************************************* + * Tegra TSA Controller constants + ******************************************************************************/ +#define TEGRA_TSA_BASE U(0x02000000) + +#define TSA_CONFIG_STATIC0_CSR_RESET_R 0x20000000U +#define TSA_CONFIG_STATIC0_CSW_RESET_W 0x20001000U +#define TSA_CONFIG_STATIC0_CSW_RESET_SO_DEV 0x20001000U + +#define TSA_CONFIG_STATIC0_CSW_PCIE1W 0x1004U +#define TSA_CONFIG_STATIC0_CSW_PCIE2AW 0x1008U +#define TSA_CONFIG_STATIC0_CSW_PCIE3W 0x100cU +#define TSA_CONFIG_STATIC0_CSW_PCIE4W 0x1028U +#define TSA_CONFIG_STATIC0_CSW_XUSB_DEVW 0x2004U +#define TSA_CONFIG_STATIC0_CSR_SATAR 0x2010U +#define TSA_CONFIG_STATIC0_CSW_SATAW 0x2014U +#define TSA_CONFIG_STATIC0_CSW_PCIE0W 0x2020U +#define TSA_CONFIG_STATIC0_CSW_XUSB_HOSTW 0x202cU +#define TSA_CONFIG_STATIC0_CSW_NVENC1SWR 0x3004U +#define TSA_CONFIG_STATIC0_CSW_NVENCSWR 0x3010U +#define TSA_CONFIG_STATIC0_CSW_NVDEC1SWR 0x4004U +#define TSA_CONFIG_STATIC0_CSR_ISPFALR 0x4010U +#define TSA_CONFIG_STATIC0_CSW_ISPWA 0x4014U +#define TSA_CONFIG_STATIC0_CSW_ISPWB 0x4018U +#define TSA_CONFIG_STATIC0_CSW_ISPFALW 0x401cU +#define TSA_CONFIG_STATIC0_CSW_NVDECSWR 0x5004U +#define TSA_CONFIG_STATIC0_CSR_EQOSR 0x5010U +#define TSA_CONFIG_STATIC0_CSW_EQOSW 0x5014U +#define TSA_CONFIG_STATIC0_CSR_SDMMCRAB 0x5020U +#define TSA_CONFIG_STATIC0_CSW_SDMMCWAB 0x5024U +#define TSA_CONFIG_STATIC0_CSW_UFSHCW 0x6004U +#define TSA_CONFIG_STATIC0_CSR_SDMMCR 0x6010U +#define TSA_CONFIG_STATIC0_CSR_SDMMCRA 0x6014U +#define TSA_CONFIG_STATIC0_CSW_SDMMCW 0x6018U +#define TSA_CONFIG_STATIC0_CSW_SDMMCWA 0x601cU +#define TSA_CONFIG_STATIC0_CSR_RCER 0x6030U +#define TSA_CONFIG_STATIC0_CSR_RCEDMAR 0x6034U +#define TSA_CONFIG_STATIC0_CSW_RCEW 0x6038U +#define TSA_CONFIG_STATIC0_CSW_RCEDMAW 0x603cU +#define TSA_CONFIG_STATIC0_CSR_SCER 0x6050U +#define TSA_CONFIG_STATIC0_CSR_SCEDMAR 0x6054U +#define TSA_CONFIG_STATIC0_CSW_SCEW 0x6058U +#define TSA_CONFIG_STATIC0_CSW_SCEDMAW 0x605cU +#define TSA_CONFIG_STATIC0_CSR_AXIAPR 0x7004U +#define TSA_CONFIG_STATIC0_CSR_ETRR 0x7008U +#define TSA_CONFIG_STATIC0_CSR_HOST1XDMAR 0x700cU +#define TSA_CONFIG_STATIC0_CSW_AXIAPW 0x7010U +#define TSA_CONFIG_STATIC0_CSW_ETRW 0x7014U +#define TSA_CONFIG_STATIC0_CSR_NVJPGSRD 0x8004U +#define TSA_CONFIG_STATIC0_CSW_NVJPGSWR 0x8008U +#define TSA_CONFIG_STATIC0_CSR_AXISR 0x8014U +#define TSA_CONFIG_STATIC0_CSW_AXISW 0x8018U +#define TSA_CONFIG_STATIC0_CSR_BPMPR 0x9004U +#define TSA_CONFIG_STATIC0_CSR_BPMPDMAR 0x9008U +#define TSA_CONFIG_STATIC0_CSW_BPMPW 0x900cU +#define TSA_CONFIG_STATIC0_CSW_BPMPDMAW 0x9010U +#define TSA_CONFIG_STATIC0_CSR_SESRD 0x9024U +#define TSA_CONFIG_STATIC0_CSR_TSECSRD 0x9028U +#define TSA_CONFIG_STATIC0_CSR_TSECSRDB 0x902cU +#define TSA_CONFIG_STATIC0_CSW_SESWR 0x9030U +#define TSA_CONFIG_STATIC0_CSW_TSECSWR 0x9034U +#define TSA_CONFIG_STATIC0_CSW_TSECSWRB 0x9038U +#define TSA_CONFIG_STATIC0_CSW_PCIE5W 0xb004U +#define TSA_CONFIG_STATIC0_CSW_VICSWR 0xc004U +#define TSA_CONFIG_STATIC0_CSR_APER 0xd004U +#define TSA_CONFIG_STATIC0_CSR_APEDMAR 0xd008U +#define TSA_CONFIG_STATIC0_CSW_APEW 0xd00cU +#define TSA_CONFIG_STATIC0_CSW_APEDMAW 0xd010U +#define TSA_CONFIG_STATIC0_CSR_HDAR 0xf004U +#define TSA_CONFIG_STATIC0_CSW_HDAW 0xf008U +#define TSA_CONFIG_STATIC0_CSR_NVDISPLAYR 0xf014U +#define TSA_CONFIG_STATIC0_CSR_VIFALR 0x10004U +#define TSA_CONFIG_STATIC0_CSW_VIW 0x10008U +#define TSA_CONFIG_STATIC0_CSW_VIFALW 0x1000cU +#define TSA_CONFIG_STATIC0_CSR_AONR 0x12004U +#define TSA_CONFIG_STATIC0_CSR_AONDMAR 0x12008U +#define TSA_CONFIG_STATIC0_CSW_AONW 0x1200cU +#define TSA_CONFIG_STATIC0_CSW_AONDMAW 0x12010U +#define TSA_CONFIG_STATIC0_CSR_PCIE1R 0x14004U +#define TSA_CONFIG_STATIC0_CSR_PCIE2AR 0x14008U +#define TSA_CONFIG_STATIC0_CSR_PCIE3R 0x1400cU +#define TSA_CONFIG_STATIC0_CSR_PCIE4R 0x14028U +#define TSA_CONFIG_STATIC0_CSR_XUSB_DEVR 0x15004U +#define TSA_CONFIG_STATIC0_CSR_XUSB_HOSTR 0x15010U +#define TSA_CONFIG_STATIC0_CSR_UFSHCR 0x16004U +#define TSA_CONFIG_STATIC0_CSW_DLA1WRA 0x18004U +#define TSA_CONFIG_STATIC0_CSR_DLA1FALRDB 0x18010U +#define TSA_CONFIG_STATIC0_CSW_DLA1FALWRB 0x18014U +#define TSA_CONFIG_STATIC0_CSW_DLA0WRA 0x19004U +#define TSA_CONFIG_STATIC0_CSR_DLA0FALRDB 0x19010U +#define TSA_CONFIG_STATIC0_CSW_DLA0FALWRB 0x19014U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDC 0x1a004U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRC 0x1a008U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRA 0x1a014U +#define TSA_CONFIG_STATIC0_CSW_PVA1WRB 0x1a020U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRB 0x1b004U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDC 0x1b010U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRC 0x1b014U +#define TSA_CONFIG_STATIC0_CSW_PVA0WRA 0x1b020U +#define TSA_CONFIG_STATIC0_CSR_NVENC1SRD 0x1d004U +#define TSA_CONFIG_STATIC0_CSR_NVENCSRD 0x1d010U +#define TSA_CONFIG_STATIC0_CSR_NVDEC1SRD 0x1e004U +#define TSA_CONFIG_STATIC0_CSR_ISPRA 0x1e010U +#define TSA_CONFIG_STATIC0_CSR_NVDECSRD 0x1f004U +#define TSA_CONFIG_STATIC0_CSR_PCIE0R 0x21004U +#define TSA_CONFIG_STATIC0_CSR_PCIE5R 0x23004U +#define TSA_CONFIG_STATIC0_CSR_VICSRD 0x24004U +#define TSA_CONFIG_STATIC0_CSR_DLA1RDA 0x26004U +#define TSA_CONFIG_STATIC0_CSR_DLA0RDA 0x27004U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDA 0x28004U +#define TSA_CONFIG_STATIC0_CSR_PVA1RDB 0x28010U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDB 0x29004U +#define TSA_CONFIG_STATIC0_CSR_PVA0RDA 0x29010U + +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_MASK (ULL(0x3) << 11) +#define TSA_CONFIG_CSW_MEMTYPE_OVERRIDE_PASTHRU (ULL(0) << 11) + +#define TSA_CONFIG_CSW_SO_DEV_HUBID_MASK (ULL(0x3) << 15) +#define TSA_CONFIG_CSW_SO_DEV_HUB2 (ULL(2) << 15) + +#define REORDER_DEPTH_LIMIT 16 +#define TSA_CONFIG_CSW_REORDER_DEPTH_LIMIT_MASK (ULL(0x7FF) << 21) +#define reorder_depth_limit(limit) (ULL(limit) << 21) + +#define tsa_read_32(client) \ + mmio_read_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client) + +#define mc_set_tsa_hub2(val, client) \ + { \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + ((val & ~TSA_CONFIG_CSW_SO_DEV_HUBID_MASK) | \ + TSA_CONFIG_CSW_SO_DEV_HUB2)); \ + } + +#define mc_set_tsa_depth_limit(limit, client) \ + { \ + uint32_t val = mmio_read_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client); \ + mmio_write_32(TEGRA_TSA_BASE + TSA_CONFIG_STATIC0_CSW_##client, \ + ((val & ~TSA_CONFIG_CSW_REORDER_DEPTH_LIMIT_MASK) | \ + reorder_depth_limit(limit))); \ + } +#endif /* __TEGRA_MC_DEF_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h new file mode 100644 index 0000000..2cf375a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h @@ -0,0 +1,73 @@ +/* + * 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 +#include +#include + +/******************************************************************************* + * 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) +#define TEGRA_CHIPID_TEGRA23 U(0x23) + +/******************************************************************************* + * 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); +bool tegra_chipid_is_t239(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); +bool tegra_platform_is_vsp(void); + +#endif /* __ASSEMBLER__ */ + +#endif /* TEGRA_PLATFORM_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h new file mode 100644 index 0000000..2fe4ffd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TEGRA_PRIVATE_H +#define TEGRA_PRIVATE_H + +#include +#include + +#include +#include +#include +#include +#include + +#include + +/******************************************************************************* + * 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 */ +bool plat_is_secondary_present(u_register_t mpidr); +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/arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c b/arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c new file mode 100644 index 0000000..dd76a4e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/platform.mk b/arm-trusted-firmware/plat/nvidia/tegra/platform.mk new file mode 100644 index 0000000..804c20f --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/platform.mk @@ -0,0 +1,111 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, 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 + +# Do not trap accesses to Error System registers from EL1 or EL2. +TEGRA_TRAP_LOWER_EL_ERR_ACCESS ?= 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 ${SOC_DIR}/platform_${TARGET_SOC}.mk + +# SPM dispatcher +ifeq (${SPD},spmd) +# include device tree helper library +include lib/libfdt/libfdt.mk +# sources to support spmd +BL31_SOURCES += plat/common/plat_spmd_manifest.c \ + common/fdt_wrappers.c \ + ${LIBFDT_SRCS} +endif + +$(eval $(call add_define,ENABLE_TEGRA_WDT_LEGACY_FIQ_HANDLING)) +$(eval $(call add_define,RELOCATE_BL32_IMAGE)) +$(eval $(call add_define,TEGRA_TRAP_LOWER_EL_ERR_ACCESS)) + +# 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 \ + strncmp.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/arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat b/arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat new file mode 100644 index 0000000..2d6d2b3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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 + + __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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h new file mode 100644 index 0000000..203f61a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h new file mode 100644 index 0000000..ecfb3f4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 0000000..e3591ce --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c new file mode 100644 index 0000000..a57bc11 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c new file mode 100644 index 0000000..aebaceb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c new file mode 100644 index 0000000..cbc9aa3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c new file mode 100644 index 0000000..dad94fd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c @@ -0,0 +1,276 @@ +/* + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h new file mode 100644 index 0000000..7aa0dd6 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c new file mode 100644 index 0000000..a104f33 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c @@ -0,0 +1,715 @@ +/* + * 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 + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +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); + } + + /* + * 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); + + /* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c new file mode 100644 index 0000000..af4182e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c new file mode 100644 index 0000000..fbb550a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c new file mode 100644 index 0000000..78613e5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c @@ -0,0 +1,422 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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) +{ + const plat_params_from_bl2_t *params_from_bl2 = bl31_get_plat_params(); + int ret; + + /* Initialize SMMU registers */ + tegra_smmu_init(); + + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(params_from_bl2->tzdram_base, + params_from_bl2->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); +} + +/* 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(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + bpmp_ipc.bpmp_ipc_tx_base = TEGRA_BPMP_IPC_TX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_rx_base = TEGRA_BPMP_IPC_RX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c new file mode 100644 index 0000000..4de8a9e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c new file mode 100644 index 0000000..f1bc235 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S new file mode 100644 index 0000000..2fc2046 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk new file mode 100644 index 0000000..4ad02a7 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t186/platform_t186.mk @@ -0,0 +1,80 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, 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 +PLAT_BL31_BASE := 0x30000000 +$(eval $(call add_define,PLAT_BL31_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)) + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h new file mode 100644 index 0000000..ef16980 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h new file mode 100644 index 0000000..7de55a7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h new file mode 100644 index 0000000..7a68a43 --- /dev/null +++ b/arm-trusted-firmware/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 + +/** + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S new file mode 100644 index 0000000..3c47208 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c new file mode 100644 index 0000000..af1c0aa --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c new file mode 100644 index 0000000..f76ab14 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c new file mode 100644 index 0000000..31b0e26 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h new file mode 100644 index 0000000..fc118aa --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c new file mode 100644 index 0000000..2182699 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2019-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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) +{ + /* + * 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); +} + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c new file mode 100644 index 0000000..60cd4a9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c @@ -0,0 +1,527 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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); + } + +#if TEGRA_TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Error register(ER*_EL1) accesses from EL1 or EL2 + * generate a Trap exception to EL3. + */ + scr_el3 = (uint32_t)read_scr(); + scr_el3 |= SCR_TERR_BIT; + write_scr(scr_el3); +#endif + +#if ENABLE_TEGRA_PERFMON + /* + * Enable Uncore Perfmon counters to aid in debugging. + * + * When set, events are allowed to be counted in the NVIDIA-specific + * Performance Monitors extension. + */ + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_SPME; + write_actlr_el3(actlr_elx); +#endif + + 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c new file mode 100644 index 0000000..ec9d86c --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c @@ -0,0 +1,492 @@ +/* + * Copyright (c) 2020-2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* + * ERRFR bits[63:32], it indicates supported RAS errors which can be enabled + * by setting corresponding bits in ERRCTLR + */ +#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++) { + + /* ERRCTLR 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 ERRSTATUS 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c new file mode 100644 index 0000000..9e33cfb --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c @@ -0,0 +1,83 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +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; + int ret; + + INFO("Setting up secondary CPU boot\n"); + + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(params_from_bl2->tzdram_base, + params_from_bl2->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); + + 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c new file mode 100644 index 0000000..af5cf70 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c @@ -0,0 +1,488 @@ +/* + * Copyright (c) 2019-2020, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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); + } + +#if TRAP_LOWER_EL_ERR_ACCESS + /* + * SCR_EL3.TERR: Error register(ER*_EL1) accesses from EL1 or EL2 + * generate a Trap exception to EL3. + */ + scr_el3 = (uint32_t)read_scr(); + scr_el3 |= SCR_TERR_BIT; + write_scr(scr_el3); +#endif + +#if ENABLE_TEGRA_PERFMON + /* + * Enable Uncore Perfmon counters to aid in debugging. + * + * When set, events are allowed to be counted in the NVIDIA-specific + * Performance Monitors extension. + */ + actlr_elx = read_actlr_el3(); + actlr_elx |= DENVER_CPU_ENABLE_SPME; + write_actlr_el3(actlr_elx); +#endif +} + +/* 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) +{ + /* Initialize SMMU registers */ + tegra_smmu_init(); + +#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(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + bpmp_ipc.bpmp_ipc_tx_base = TEGRA_BPMP_IPC_TX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_rx_base = TEGRA_BPMP_IPC_RX_PHYS_BASE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c new file mode 100644 index 0000000..35f7302 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c new file mode 100644 index 0000000..310e951 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S new file mode 100644 index 0000000..0ff5407 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk new file mode 100644 index 0000000..a184b4a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t194/platform_t194.mk @@ -0,0 +1,91 @@ +# +# 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_TEGRA_PERFMON ?= 1 +$(eval $(call add_define,ENABLE_TEGRA_PERFMON)) + +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 +PLAT_BL31_BASE := 0x40000000 +$(eval $(call add_define,PLAT_BL31_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 := 1 +RAS_EXTENSION := 1 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h new file mode 100644 index 0000000..c44b0fc --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c new file mode 100644 index 0000000..4860858 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c new file mode 100644 index 0000000..7f73ea5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c new file mode 100644 index 0000000..e0242cf --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c new file mode 100644 index 0000000..19b41ed --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c @@ -0,0 +1,327 @@ +/* + * 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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); + } + + if (tegra_chipid_is_t210_b01()) { + /* map TZDRAM used by BL31 as coherent memory */ + ret = mmap_add_dynamic_region(plat_params->tzdram_base, + plat_params->tzdram_base, + BL31_SIZE, + MT_DEVICE | MT_RW | MT_SECURE); + assert(ret == 0); + } +} + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c new file mode 100644 index 0000000..e3484be --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk new file mode 100644 index 0000000..9770eb1 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t210/platform_t210.mk @@ -0,0 +1,65 @@ +# +# Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. +# Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_BL31_BASE := 0xFF800000 +$(eval $(call add_define,PLAT_BL31_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 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +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/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h new file mode 100644 index 0000000..6a4a716 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __MCE_PRIVATE_H__ +#define __MCE_PRIVATE_H__ + +#include +#include + +/******************************************************************************* + * 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 SYSTEM_CSTATE_MASK 0xFU +#define SYSTEM_CSTATE_SHIFT 16U + +/******************************************************************************* + * 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 + +/******************************************************************************* + * 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) + +/******************************************************************************* + * CLUSTER_CONFIG ARI macros + ******************************************************************************/ +#define CLUSTER_MODE_SHIFT(cluster) ((cluster) << 1U) +#define CLUSTER_MODE_MASK 0x3U +#define CLUSTER_MODE_DISABLED 0U +#define CLUSTER_MODE_SPLIT 1U +#define CLUSTER_MODE_HYBRID 2U +#define CLUSTER_MODE_LOCK 3U + +/* declarations for ARI handler functions */ +/* Function from NS world */ +uint64_t ari_get_version(uint32_t ari_base); +uint32_t ari_num_cores(uint32_t ari_base); +uint32_t ari_cluster_present_map(uint32_t ari_base); +uint32_t ari_ccplex_cache_clean(uint32_t ari_base); +uint32_t ari_ccplex_cache_clean_and_invalidate(uint32_t ari_base); +/* Function for secure world */ +#if DEBUG +uint32_t ari_core_debug_recovery(uint32_t ari_base, uint32_t core_id, bool core_warm_reset); +uint32_t ari_dsu_debug_recovery(uint32_t ari_base, uint32_t cluster_id, bool cluster_warm_reset); +uint32_t ari_ccplex_latic_on(uint32_t ari_base); +#endif +uint32_t ari_online_core(uint32_t ari_base, uint32_t core); +uint32_t ari_enter_cstate(uint32_t ari_base, uint32_t wake_time); +uint32_t ari_trigger_online_ist(uint32_t ari_base, uint32_t slice_id); +uint32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mas); +bool ari_is_sc7_allowed(uint32_t ari_base); +void ari_enable_strict_checking_mode(uint32_t ari_base); +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx); + +void ari_system_shutdown(uint32_t ari_base); +void ari_system_reboot(uint32_t ari_base); + +/* MCE helper functions */ +void mce_clean_and_invalidate_caches(void); +void mce_enable_strict_checking(void); +uint32_t mce_enter_debug_recovery_mode(uint32_t core_id); +void mce_system_shutdown(void); +void mce_system_reboot(void); +uint32_t mce_num_cores(void); +bool mce_is_cluster_present(unsigned int id); +bool mce_is_cluster_in_lock_mode(unsigned int id); +bool mce_is_cluster_in_split_mode(unsigned int id); +bool mce_is_cluster_in_hybrid_mode(unsigned int id); + +#endif /* __MCE_PRIVATE_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h new file mode 100644 index 0000000..c0df0e4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef __SE_H__ +#define __SE_H__ + +int32_t tegra_se_suspend(void); +void tegra_se_resume(void); + +#endif /* __SE_H__ */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h new file mode 100644 index 0000000..db91da5 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h @@ -0,0 +1,265 @@ +// ----------------------------------------------------------------------- +// +// Copyright (c) 2019-2021 NVIDIA Corporation - All Rights Reserved +// +// This source module contains confidential and proprietary information +// of NVIDIA Corporation. It is not to be disclosed or used except +// in accordance with applicable agreements. This copyright notice does +// not evidence any actual or intended publication of such source code. +// +// ----------------------------------------------------------------------- +#ifndef T234_ARI_H +#define T234_ARI_H +/* ARI Version numbers */ +#define TEGRA_ARI_VERSION_MAJOR 8UL +#define TEGRA_ARI_VERSION_MINOR 1UL + +/* + * ARI Request IDs + * + * TODO: RENUMBER range before finalization + * NOTE: for documentation purposes, only documenting gaps + * in ranges, to indicate that we know about the missing ids + * + * Require NO LAB Locks + * range from 0 - 31 + */ +#define TEGRA_ARI_VERSION 0UL +#define TEGRA_ARI_ECHO 1UL +#define TEGRA_ARI_NUM_CORES 2UL +#define TEGRA_ARI_CSTATE_STAT_QUERY 3UL +#define TEGRA_ARI_CLUSTER_CONFIG 4UL +/* Undefined 5 - 28 */ +/* + * Debug Only ARIs at the end of the NO LAB Lock Range + */ +#define TEGRA_ARI_CORE_DEBUG_RECOVERY 29UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY 30UL +#define TEGRA_ARI_CLUSTER_WARM_RESET 31UL +/* + * Require CORE LAB Lock -- obtained by MTM from ARI + * range from 32 - 63 + */ +/* UNDEFINED 32 */ +/* UNDEFINED 33 */ +#define TEGRA_ARI_ONLINE_CORE 34UL +#define TEGRA_ARI_ENTER_CSTATE 35UL +#define TEGRA_ARI_PRETRIGGER_ONLINE_IST 36UL +#define TEGRA_ARI_TRIGGER_ONLINE_IST 37UL +#define TEGRA_ARI_ONLINE_IST_STATUS 38UL +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS 39UL +/* + * Require CLUSTER and CORE LAB Lock -- obtained by MTM from ARI + * range from 64 - 95 + */ +/* UNDEFINED 64 */ +#define TEGRA_ARI_NVFREQ_REQ 65UL +#define TEGRA_ARI_NVFREQ_FEEDBACK 66UL +#define TEGRA_ARI_CLUSTER_ATCLKEN 67UL +/* + * Require CCPLEX, CLUSTER and CORE LAB Lock -- obtained by MTM from ARI + * range from 96 - 127 + */ +#define TEGRA_ARI_CCPLEX_CACHE_CONTROL 96UL +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN 97UL +/* UNDEFINED 98 */ +#define TEGRA_ARI_CCPLEX_LATIC_ON 99UL +#define TEGRA_ARI_UPDATE_CROSSOVER 100UL +#define TEGRA_ARI_VALIDATE_ONLINE_IST 101UL +#define TEGRA_ARI_CCPLEX_SHUTDOWN 102UL +/* UNDEFINED 103 */ +#define TEGRA_ARI_CSTATE_INFO 104UL +#define TEGRA_ARI_IS_SC7_ALLOWED 105UL +/* UNDEFINED 106 */ +/* UNDEFINED 107 */ +#define TEGRA_ARI_SECURITY_CONFIG 108UL +#define TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS 109UL +#define TEGRA_ARI_DDA_CONTROL 110UL +#define TEGRA_ARI_PERFMON 111UL +#define TEGRA_ARI_DEBUG_CONFIG 112UL +#define TEGRA_ARI_CCPLEX_ERROR_RECOVERY_RESET 114UL + +/* EVENT MASKS */ +#define TEGRA_ARI_EVENT_CORE_OFF_MASK (1UL<<0) +#define TEGRA_ARI_EVENT_CORE_OFF_EMU_MASK (1UL<<1) +#define TEGRA_ARI_EVENT_WAKE_REQUEST_MASK (1UL<<2) + +//////////////////////////////////////////////////// +// +// Defines for ARI Parameters +// +// TEGRA_ARI_VERSION NONE +// TEGRA_ARI_ECHO NONE +// TEGRA_ARI_NUM_CORES NONE +// TEGRA_ARI_CLUSTER_CONFIG +#define TEGRA_ARI_CLUSTER0_CONFIG_FLOORSWEPT 0UL +#define TEGRA_ARI_CLUSTER0_CONFIG_SPLIT 1UL +#define TEGRA_ARI_CLUSTER0_CONFIG_HYBRID 2UL +#define TEGRA_ARI_CLUSTER0_CONFIG_LOCK 3UL +#define TEGRA_ARI_CLUSTER1_CONFIG_FLOORSWEPT (0UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_SPLIT (1UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_HYBRID (2UL<<2) +#define TEGRA_ARI_CLUSTER1_CONFIG_LOCK (3UL<<2) +#define TEGRA_ARI_CLUSTER2_CONFIG_FLOORSWEPT (0UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_SPLIT (1UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_HYBRID (2UL<<4) +#define TEGRA_ARI_CLUSTER2_CONFIG_LOCK (3UL<<4) +// TEGRA_ARI_CSTATE_STAT_QUERY +#define TEGRA_ARI_STAT_QUERY_SC7_ENTRIES 1UL +#define TEGRA_ARI_STAT_QUERY_CC7_ENTRIES 6UL +#define TEGRA_ARI_STAT_QUERY_C7_ENTRIES 14UL +#define TEGRA_ARI_STAT_QUERY_SC7_ENTRY_TIME_SUM 60UL +#define TEGRA_ARI_STAT_QUERY_CC7_ENTRY_TIME_SUM 61UL +#define TEGRA_ARI_STAT_QUERY_C7_ENTRY_TIME_SUM 64UL +#define TEGRA_ARI_STAT_QUERY_SC7_EXIT_TIME_SUM 70UL +#define TEGRA_ARI_STAT_QUERY_CC7_EXIT_TIME_SUM 71UL +#define TEGRA_ARI_STAT_QUERY_C7_EXIT_TIME_SUM 74UL + +// TEGRA_ARI_CORE_DEBUG_RECOVERY +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RCWR_NONE 0UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RCWR_WARM_RESET (1UL<<4) + +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_SUCCESS 0UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_DENIED 1UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_BUSY 2UL +#define TEGRA_ARI_CORE_DEBUG_RECOVERY_RESULT_OFF 3UL + +// TEGRA_ARI_DSU_DEBUG_RECOVERY +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RCWR_NONE 0UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RCWR_WARM_RESET (1UL<<2) + +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_SUCCESS 0UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_DENIED 1UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_BUSY 2UL +#define TEGRA_ARI_DSU_DEBUG_RECOVERY_RESULT_OFF 3UL + +// TEGRA_ARI_CLUSTER_WARM_RESET NONE +// TEGRA_ARI_ONLINE_CORE NONE +// TEGRA_ARI_ENTER_CSTATE +#define TEGRA_ARI_ENTER_CSTATE_WAKE_TIME_NO_WAKE (0xffffffffUL) + +// TEGRA_ARI_TRIGGER_ONLINE_IST +#define TEGRA_ARI_TRIGGER_ONLINE_IST_SELECT_PLL_NAFLL 0UL +#define TEGRA_ARI_TRIGGER_ONLINE_IST_SELECT_PLL_PLLX1 1UL + +// TEGRA_ARI_ONLINE_IST_STATUS +#define TEGRA_ARI_ONLINE_IST_STATUS_RESET 0UL +#define TEGRA_ARI_ONLINE_IST_STATUS_TEST_PASS 1UL +#define TEGRA_ARI_ONLINE_IST_STATUS_TEST_FAIL 2UL + +// TEGRA_ARI_ONLINE_IST_DMA_STATUS +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS_PENDING_TRANSACTIONS_FALSE 0UL +#define TEGRA_ARI_ONLINE_IST_DMA_STATUS_PENDING_TRANSACTIONS_TRUE 1UL + +// TEGRA_ARI_NVFREQ_REQ +#define TEGRA_ARI_NVFREQ_REQ_CORE_NDIV_WRITE_EN (1UL<<15) +#define TEGRA_ARI_NVFREQ_REQ_DSU_NDIV_WRITE_EN (1UL<<15) + +// TEGRA_ARI_NVFREQ_FEEDBACK NONE +// TEGRA_ARI_CLUSTER_ATCLKEN +#define TEGRA_ARI_CLUSTER_ATCLKEN_DISABLE 0UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_ENABLE 1UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_SUCCESS 0UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_FAILURE 1UL +#define TEGRA_ARI_CLUSTER_ATCLKEN_RESULT_NONE 2UL + +// TEGRA_ARI_CCPLEX_CACHE_CONTROL +#define TEGRA_ARI_CCPLEX_CACHE_CONTROL_WRITE_EN (1UL<<15) + +// TEGRA_ARI_CCPLEX_CACHE_CLEAN +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN_NO_INVAL 0UL +#define TEGRA_ARI_CCPLEX_CACHE_CLEAN_INVAL 1UL + +// TEGRA_ARI_CCPLEX_LATIC_ON NONE +// TEGRA_ARI_UPDATE_CROSSOVER +#define TEGRA_ARI_CROSSOVER_C7_LOWER_BOUND 0UL +#define TEGRA_ARI_CROSSOVER_CC7_LOWER_BOUND 1UL +// TEGRA_ARI_VALIDATE_ONLINE_IST +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_SUCCESS 0UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_INELIGIBLE 1UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER0_FAILED 2UL +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_SUCCESS (0UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_INELIGIBLE (1UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER1_FAILED (2UL<<2) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_SUCCESS (0UL<<4) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_INELIGIBLE (1UL<<4) +#define TEGRA_ARI_VALIDATE_OIST_CLUSTER2_FAILED (2UL<<4) +// TEGRA_ARI_CCPLEX_SHUTDOWN +#define TEGRA_ARI_CCPLEX_SHUTDOWN_POWER_OFF 0UL +#define TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT 1UL + +// TEGRA_ARI_CSTATE_INFO +#define TEGRA_ARI_CSTATE_INFO_CLUSTER_CC1 1UL +#define TEGRA_ARI_CSTATE_INFO_CLUSTER_CC7 7UL +#define TEGRA_ARI_CSTATE_INFO_SYSTEM_SC0 (0UL<<16) +#define TEGRA_ARI_CSTATE_INFO_SYSTEM_SC7 (7UL<<16) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_CLUSTER (1UL<<7) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_SYSTEM (1UL<<23) +#define TEGRA_ARI_CSTATE_INFO_UPDATE_WAKE_MASK (1UL<<31) + +// TEGRA_ARI_IS_SC7_ALLOWED +#define TEGRA_ARI_IS_SC7_ALLOWED_FALSE 0UL +#define TEGRA_ARI_IS_SC7_ALLOWED_TRUE 1UL + +// TEGRA_ARI_SECURITY_CONFIG +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_DISABLE 0UL +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE 1UL +#define TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK (1UL<<1) +#define TEGRA_ARI_SECURITY_CONFIG_WRITE_EN (1UL<<2) + +// TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS +#define TEGRA_ARI_CARVEOUT_ALL 0UL +#define TEGRA_ARI_CARVEOUT_GSC_NONE 0xFFFFUL +#define TEGRA_ARI_CARVEOUT_GSC_IST 31UL +#define TEGRA_ARI_CARVEOUT_SBS (1UL<<16) +#define TEGRA_ARI_CARVEOUT_VPR (1UL<<17) +// TEGRA_ARI_DDA_CONTROL +#define DDA_SNOC_MCF 0U +#define DDA_MCF_ORD1 1U +#define DDA_MCF_ORD2 2U +#define DDA_MCF_ORD3 3U +#define DDA_MCF_ISO 4U +#define DDA_MCF_SISO 5U +#define DDA_MCF_NISO 6U +#define DDA_MCF_NISO_REMOTE 7U +#define DDA_L3CTRL_ISO 8U +#define DDA_L3CTRL_SISO 9U +#define DDA_L3CTRL_NISO 10U +#define DDA_L3CTRL_NISO_REMOTE 11U +#define DDA_L3CTRL_L3FILL 12U +#define DDA_L3CTRL_L3WR 13U +#define DDA_L3CTRL_RSP_L3RD_DMA 14U +#define DDA_L3CTRL_RSP_MCFRD_DMA 15U +#define DDA_L3CTRL_GLOBAL 16U +#define DDA_L3CTRL_LL 17U +#define DDA_L3CTRL_L3D 18U +#define DDA_L3CTRL_FCM_RD 19U +#define DDA_L3CTRL_FCM_WR 20U +#define DDA_SNOC_GLOBAL_CTRL 21U +#define DDA_SNOC_CLIENT_REQ_CTRL 22U +#define DDA_SNOC_CLIENT_REPLENTISH_CTRL 23U + +#define TEGRA_ARI_DDA_CONTROL_DDA_REG_WRITE_EN (1UL<<15) + +// TEGRA_ARI_PERFMON NONE +// TEGRA_ARI_DEBUG_CONFIG +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP0 (0UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP1 (1UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_CP0CP1 (2UL<<2) +#define TEGRA_ARI_DEBUG_CONFIG_NOTIFY_ON_DCLS_FAULT_DISABLE (3UL<<2) + +// TEGRA_ARI_CCPLEX_ERROR_RECOVERY_RESET NONE +// Primary ERROR CODES - valid in RSP_LO +#define TEGRA_ARI_ERROR_SW 1UL +// not defined 2UL +// not defined 3UL +// not defined 4UL +// not defined 5UL +// not defined 6UL +#define TEGRA_ARI_ERROR_RESERVED 7UL +#define TEGRA_ARI_ERROR_OUT_OF_RANGE 8UL +#define TEGRA_ARI_ERROR_RESTRICTED 9UL +#define TEGRA_ARI_ERROR_NONSECURE 10UL +// Secondary ERROR CODES - valid in RSP_HI +// none currently defined +#endif /* T234_ARI_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c new file mode 100644 index 0000000..12007f4 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c @@ -0,0 +1,628 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/****************************************************************************** + * Custom macros + *****************************************************************************/ +#define ID_AFR0_EL1_CACHE_OPS_SHIFT 12U +#define ID_AFR0_EL1_CACHE_OPS_MASK 0xFU + +#define CORE_WARM_RESET_SHIFT 4U +#define CLUSTER_WARM_RESET_SHIFT 2U + +#define CLUSTER_CONFIG_MASK 0x3FU + +/****************************************************************************** + * Globals + *****************************************************************************/ +static uint32_t cluster_bitmap = U(0xDEADF00D); + +/****************************************************************************** + * Register offsets for ARI request/results + *****************************************************************************/ +#define ARI_REQUEST 0x0U +#define ARI_REQUEST_EVENT_MASK 0x8U +#define ARI_STATUS 0x10U +#define ARI_REQUEST_DATA_LO 0x18U +#define ARI_REQUEST_DATA_HI 0x20U +#define ARI_RESPONSE_DATA_LO 0x28U +#define ARI_RESPONSE_DATA_HI 0x30U + +/* Status values for the current request */ +#define ARI_REQ_PENDING 1U +#define ARI_REQ_ONGOING 2U +/* Request status */ +#define ARI_REQ_STATUS_MASK 0xFCU +#define ARI_REQ_NO_ERROR 0U +#define ARI_REQ_REQUEST_KILLED 1U +#define ARI_REQ_NS_ERROR 2U +#define ARI_REQ_EXECUTION_ERROR 0x3FU +/* Request control bits */ +#define ARI_REQUEST_VALID_BIT (1U << 8) +#define ARI_REQUEST_KILL_BIT (1U << 9) +#define ARI_REQUEST_NS_BIT (1U << 31) + +/* 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_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 void ari_request_send_command(uint32_t ari_base, uint32_t evt_mask, + uint32_t req, uint32_t lo, uint32_t hi) +{ + 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); +} + +static uint32_t ari_request_wait(uint32_t ari_base, uint32_t evt_mask, + uint32_t req, uint32_t lo, uint32_t hi) +{ + uint32_t retries = ARI_MAX_RETRY_COUNT; + uint32_t status; + uint32_t ret = 0U; + + /* + * For each ARI command, the registers that are not used are listed + * as "Must be set to 0", MCE firmware enforce a check for it. + * Clear response lo/hi data before sending out command. + */ + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_LO); + ari_write_32(ari_base, 0, ARI_RESPONSE_DATA_HI); + + /* program the request, event_mask, hi and lo registers */ + ari_request_send_command(ari_base, evt_mask, req, lo, hi); + + /* + * For commands that have an event trigger, we should stop + * ARI_STATUS polling, since MCE is waiting for SW to trigger + * the event. + */ + /* For shutdown/reboot commands, use function ari_request_send_command() */ + if (evt_mask == 0U) { + /* + * 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 | + ARI_REQ_STATUS_MASK)) == 0U) { + break; + } + + if ((status & ARI_REQ_STATUS_MASK) != 0U) { + ret = ((status & ARI_REQ_STATUS_MASK) >> 2); + ERROR("ARI request get error: 0x%x\n", ret); + return ret; + } + + /* 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\n", req); + assert(retries != 0U); + } + } + + return 0; +} + +/* + * Reports the major and minor version of this interface. + * ari_base: ari base for current CPU. + * version: [63:32] Major version, [31:0] Minor version. + */ +uint64_t ari_get_version(uint32_t ari_base) +{ + uint64_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, (uint32_t)TEGRA_ARI_VERSION, 0, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + ret |= ((uint64_t)ari_get_response_high(ari_base) << 32); + } else { + ERROR("ARI request %s fail!\n", __func__); + } + + return ret; +} + +/* + * return a bit-vector indicating which cores on the ccplex are enabled or + * non-floorswept. + * ari_base: ari base for current CPU. + * num_cores: [15:0] bit-vector indicating which cores on the ccplex are enabled. + */ +uint32_t ari_num_cores(uint32_t ari_base) +{ + uint32_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_NUM_CORES, 0, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + } else { + ERROR("ARI request %s fail!\n", __func__); + } + + return (ret & 0xFFFFU); +} + +/* + * Return a bit-vector indicating which clusters on the ccplex are enabled or + * non-floorswept. + * + * ari_base: ari base for current CPU. + * + * Return bit-vector indicating which clusters on the ccplex are enabled. + */ +uint32_t ari_cluster_present_map(uint32_t ari_base) +{ + uint32_t ret; + + if (cluster_bitmap != U(0xDEADF00D)) { + return cluster_bitmap; + } + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CLUSTER_CONFIG, 0U, 0U); + if (ret == 0U) { + cluster_bitmap = ari_get_response_low(ari_base); + cluster_bitmap &= (CLUSTER_CONFIG_MASK); + } else { + ERROR("ARI request %s failed\n", __func__); + } + + return cluster_bitmap; +} + +#if DEBUG +/* + * MCE SW will initiate the warm reset sequence to Warm Reset the requested + * cluster. This ARI call is intended to be used in conjunction with + * TEGRA_ARI_CORE_DEBUG_RECOVERY and TEGRA_ARI_DSU_DEBUG_RECOVERY to allow + * the debugger to enable the DBGRM mode for the entire cluster. + * ari_base: ari base for current CPU. + * cluster_id: Cluster ID for the target cluster. Valid values are 0-2. + * ret: error status, 0 indicate no error. + */ +static uint32_t ari_cluster_warm_reset(uint32_t ari_base, uint32_t cluster_id) +{ + uint32_t ret; + + assert(cluster_id < PLATFORM_CLUSTER_COUNT); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CLUSTER_WARM_RESET, + cluster_id, 0); + + if (ret != 0U) { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * attempt to transition the specified core into the DEBUG_RECOVERY Mode (DBGRM) + * ari_base: ari base for current CPU. + * core_id: Core ID of Target Core to put into DBRGM + * core_warm_reset: Request Cluster Warm Reset + * 0 – No Cluster Warm Reset + * 1 – Warm Reset Cluster after successful transition of core to DBGRM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + * if the ARI Request register Status field has been set to 0x3f, + * the ret value will be + * ret: [31:0] + * error code indicate information about the error + */ +uint32_t ari_core_debug_recovery(uint32_t ari_base, uint32_t core_id, + bool core_warm_reset) +{ + uint32_t request, ret; + + assert(core_id < + (PLATFORM_CLUSTER_COUNT * PLATFORM_MAX_CPUS_PER_CLUSTER)); + + request = ((uint32_t)core_warm_reset << CORE_WARM_RESET_SHIFT) + | core_id; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_CORE_DEBUG_RECOVERY, + request, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + if (core_warm_reset && (ret == 0)) { + ret = ari_cluster_warm_reset(ari_base, + (core_id / PLATFORM_MAX_CPUS_PER_CLUSTER)); + } + } else { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * attempt to transition the specified DSU into the DEBUG_RECOVERY Mode (DBGRM). + * ari_base: ari base for current CPU. + * cluster_id: Cluster ID for the target DSU. Valid values are 0-2. + * cluster_warm_reset: Request Cluster Warm Reset + * 0 – No Cluster Warm Reset + * 1 – Warm Reset Cluster after successful transition of core to DBGRM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + * if the ARI Request register Status field has been set to 0x3f, + * the ret value will be + * ret: [31:0] + * error code indicate information about the error + */ +uint32_t ari_dsu_debug_recovery(uint32_t ari_base, uint32_t cluster_id, + bool cluster_warm_reset) +{ + uint32_t request, ret; + + assert(cluster_id < PLATFORM_CLUSTER_COUNT); + + request = ((uint32_t)cluster_warm_reset << CLUSTER_WARM_RESET_SHIFT) + | cluster_id; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_DSU_DEBUG_RECOVERY, + request, 0); + + if (ret == 0U) { + ret = ari_get_response_low(ari_base); + if (cluster_warm_reset && (ret == 0)) { + ret = ari_cluster_warm_reset(ari_base, cluster_id); + } + } else { + ERROR("ARI request %s fail!\n", __func__); + if (ret == ARI_REQ_EXECUTION_ERROR) { + ret = ari_get_response_low(ari_base); + } + } + + return ret; +} + +/* + * MCE SW will enable the CCLA for internal debugging. This will cause an MCE + * assert if used on a production fused part. + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_latic_on(uint32_t ari_base) +{ + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_LATIC_ON, 0, 0); + +} +#endif + +/* + * Initiate an SCF level Cache Clean + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_cache_clean(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_CACHE_CLEAN, + TEGRA_ARI_CCPLEX_CACHE_CLEAN_NO_INVAL, 0); +} + +/* + * Initiate an SCF level Cache invalidate and Clean + * ari_base: ari base for current CPU. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_ccplex_cache_clean_and_invalidate(uint32_t ari_base) +{ + /* clean the previous response state */ + ari_clobber_response(ari_base); + + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CCPLEX_CACHE_CLEAN, + TEGRA_ARI_CCPLEX_CACHE_CLEAN_INVAL, 0); +} + +/* + * This function will request for the BPMP to power down the CCPLEX. + * This can be used to either reboot or power off the system. + * ari_base: ari base for current CPU. + * type: 0 — Power Off SOC + * 1 — Reboot SOC + */ +static void ari_ccplex_shutdown(uint32_t ari_base, uint32_t type) +{ + /* sanity check for type */ + assert(type <= TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + ari_request_send_command(ari_base, 0U, TEGRA_ARI_CCPLEX_SHUTDOWN, + type, 0); +} + +/* + * This request allows updating of CLUSTER_CSTATE, CCPLEX_CSTATE and + * SYSTEM_CSTATE values. + * ari_base: ari base for current CPU. + * cluster: cluster CSTATE + * 1 — Auto-CC1 (reset value) + * 7 — CC7 + * update_cluster: 0 — Ignore value in Cluster CSTATE field + * 1 — Value in Cluster CSTATE field is valid and + * should be updated + * system: system CSTATE + * 0 << 16 — SC0 (reset value) + * 7 << 16 — SC7 + * update_system: 0 — Ignore value in system CSTATE field + * 1 — Value in system CSTATE field is valid and + * should be updated + * wake_mask: Mask of events to wake from low power states. + * update_wake_mask: 0 — Ignore value in Wake Mask field + * 1 — Value in Wake Mask Field is valid and should be updated + * ret: error status, 0 indicate no error. + */ +uint32_t ari_update_cstate_info(uint32_t ari_base, uint32_t cluster, + uint32_t system, uint32_t wake_mask, uint8_t update_wake_mask) +{ + uint32_t val = 0; + + /* update CLUSTER_CSTATE? */ + if (cluster != 0U) { + val |= (cluster & CLUSTER_CSTATE_MASK) | + TEGRA_ARI_CSTATE_INFO_UPDATE_CLUSTER; + } + + /* update SYSTEM_CSTATE? */ + if (system != 0U) { + val |= ((system & SYSTEM_CSTATE_MASK) << SYSTEM_CSTATE_SHIFT) | + TEGRA_ARI_CSTATE_INFO_UPDATE_SYSTEM ; + } + + /* update wake mask value? */ + if (update_wake_mask != 0U) { + val |= TEGRA_ARI_CSTATE_INFO_UPDATE_WAKE_MASK; + } + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* set the updated cstate info */ + return ari_request_wait(ari_base, 0U, TEGRA_ARI_CSTATE_INFO, + val, wake_mask); +} + +/* + * Return a non-zero value if the CCPLEX is able to enter SC7 + * ari_base: ari base for current CPU. + * result: 0 — System is not allowed to enter SC7 and may reenter running state. + * 1 – System may enter SC7 and is committed to proceed to enter SC7. + */ +bool ari_is_sc7_allowed(uint32_t ari_base) +{ + bool result; + uint32_t ret; + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* issue command to check if SC7 is allowed */ + ret = ari_request_wait(ari_base, 0U, TEGRA_ARI_IS_SC7_ALLOWED, 0, 0); + if (ret != 0) { + ERROR("%s: failed (%d)\n", __func__, ret); + result = false; + } else { + /* 1 = SC7 allowed, 0 = SC7 not allowed */ + result = (bool)ari_get_response_low(ari_base); + } + + return result; +} + +/* + * Wake an offlined logical core. Note that a core is offlined by entering + * a C-state where the WAKE_MASK is all 0. + * ari_base: ari base for current CPU. + * core: MPIDR Linear Core ID of the core to bring online. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_online_core(uint32_t ari_base, uint32_t core) +{ + assert(core < + (PLATFORM_CLUSTER_COUNT * PLATFORM_MAX_CPUS_PER_CLUSTER)); + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* get a core online */ + return ari_request_wait(ari_base, 0U, TEGRA_ARI_ONLINE_CORE, core, 0U); +} + +/* + * MC GSC (General Security Carveout) register values are expected to be + * changed by TrustZone ARM code after boot. + * ari_base: ari base for current CPU. + * gsc_idx: The enumerated GSC value to be copied from the SOC into the CCPLEX + * !! only support GSC_VPR now !! + * ret: error status, 0 indicate no error. + */ +int32_t ari_update_ccplex_gsc(uint32_t ari_base, uint32_t gsc_idx) +{ + /* sanity check GSC ID */ + if (gsc_idx != TEGRA_ARI_CARVEOUT_VPR) { + return -EINVAL; + } + + /* 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. + */ + return ari_request_wait(ari_base, 0U, + TEGRA_ARI_UPDATE_CCPLEX_CARVEOUTS, gsc_idx, 0U); +} + + +/* + * Set the power state for a core + * ari_base: ari base for current CPU. + * wake_time: Time in TSC ticks until the core is expected to get a wake event. + * 0 indicates the core is expected to wake immediately. + * 0xffffffff indicates that the core is not expected + * to get a wake event. + * ret: error status, 0 indicate no error. + */ +uint32_t ari_enter_cstate(uint32_t ari_base, uint32_t wake_time) +{ +/* + * should have C1 state according CCPLEX_Power_Management_GFD + * but only wake_time as input parameter in MCE_ISS. + */ + + /* time (TSC ticks) until the core is expected to get a wake event */ + + /* clean the previous response state */ + ari_clobber_response(ari_base); + + /* send the command and do not wait for the ARI to complete*/ + ari_request_send_command(ari_base, TEGRA_ARI_EVENT_CORE_OFF_MASK, + TEGRA_ARI_ENTER_CSTATE, wake_time, 0); + + return 0; +} + +#if ENABLE_STRICT_CHECKING_MODE +/* + * Enable strict checking mode and verify the result. + * ari_base: ari base for current CPU. + */ +void ari_enable_strict_checking_mode(uint32_t ari_base) +{ + uint32_t params; + uint32_t ret = 0U; + + /* Clean the previous response state */ + ari_clobber_response(ari_base); + + /* Enable the strict checking mode + * Lock the strict enable bit. + * Once the bit is set, write to strict_en bit will be ignored + */ + params = TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE + | TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK + | TEGRA_ARI_SECURITY_CONFIG_WRITE_EN; + ret = ari_request_wait(ari_base, 0, TEGRA_ARI_SECURITY_CONFIG, + params, 0); + if (ret == 0) { + params = ari_get_response_low(ari_base); + } + + assert(params == (TEGRA_ARI_SECURITY_CONFIG_STRICT_EN_ENABLE + | TEGRA_ARI_SECURITY_CONFIG_STRICT_LOCK)); +} +#endif + +/* + * Request a reboot + */ +void ari_system_reboot(uint32_t ari_base) +{ + ari_ccplex_shutdown(ari_base, TEGRA_ARI_CCPLEX_SHUTDOWN_REBOOT); +} + +/* + * Request a shutdown + */ +void ari_system_shutdown(uint32_t ari_base) +{ + ari_ccplex_shutdown(ari_base, TEGRA_ARI_CCPLEX_SHUTDOWN_POWER_OFF); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c new file mode 100644 index 0000000..11236dd --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c @@ -0,0 +1,501 @@ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Global variable to save the cluster bitmap */ +static uint32_t cluster_present_bitmap = 0xDEADFEED; + +/* Global variable to save the core present bitmap */ +static uint32_t core_present_bitmap = 0xDEADFEED; + +/* Global variable to save the unsupported platform list */ +static uint32_t tegra_unsupported_platform_bitmap = U(0xDEADBEEF); + +/* Table to hold the per-CPU ARI base address and function handlers */ +static uint32_t mce_cfg_table[PLATFORM_CLUSTER_COUNT][PLATFORM_MAX_CPUS_PER_CLUSTER] = { + { + /* cluster 0 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_1_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_2_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_3_OFFSET), + }, + { + /* cluster 1 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_4_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_5_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_6_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_7_OFFSET), + }, + { + /* cluster 2 */ + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_8_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_9_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_10_OFFSET), + (TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_11_OFFSET), + } + +}; + +static uint32_t mce_get_curr_cpu_ari_base(void) +{ + u_register_t mpidr = read_mpidr(); + u_register_t cpu_id, cluster_id; + + cluster_id = (mpidr >> (u_register_t)MPIDR_AFF2_SHIFT) & + (u_register_t)MPIDR_AFFLVL_MASK; + + assert(cluster_id <= PLATFORM_CLUSTER_COUNT); + + cpu_id = (mpidr >> (u_register_t)MPIDR_AFF1_SHIFT) & + (u_register_t)MPIDR_AFFLVL_MASK; + + assert(cpu_id <= PLATFORM_MAX_CPUS_PER_CLUSTER); + + return mce_cfg_table[cluster_id][cpu_id]; +} + +/* Handler to check if MCE firmware is supported */ +static bool mce_firmware_not_supported(void) +{ + /* Check if this platform is supported */ + if (tegra_unsupported_platform_bitmap != U(0xDEADBEEF)) { + return !(tegra_unsupported_platform_bitmap == 0U); + } + + /* + * If the current platform is one of the unsupported ones, + * add it to the bitmap + */ + tegra_unsupported_platform_bitmap = tegra_platform_is_linsim() | + (tegra_platform_is_virt_dev_kit() << 1U) | + (tegra_platform_is_vsp() << 2U); + + return !(tegra_unsupported_platform_bitmap == 0U); +} + +/****************************************************************************** + * 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; + uint32_t cpu_ari_base; + + /* 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 = ari_enter_cstate(cpu_ari_base, (uint32_t)arg0); + if (ret < 0) { + ERROR("%s: enter_cstate failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_IS_SC7_ALLOWED: + ret = ari_is_sc7_allowed((uint32_t)cpu_ari_base); + if (ret < 0) { + ERROR("%s: is_sc7_allowed failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ONLINE_CORE: + ret = ari_online_core(cpu_ari_base, (uint32_t)arg0); + if (ret < 0) { + ERROR("%s: online_core failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ROC_FLUSH_CACHE: + ret = ari_ccplex_cache_clean_and_invalidate(cpu_ari_base); + if (ret < 0) { + ERROR("%s: flush cache failed(%d)\n", __func__, ret); + } + + break; + + case (uint64_t)MCE_CMD_ROC_CLEAN_CACHE: + ret = ari_ccplex_cache_clean(cpu_ari_base); + if (ret < 0) { + ERROR("%s: clean cache failed(%d)\n", __func__, ret); + } + + 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. + */ + ari_ccplex_latic_on(cpu_ari_base); + + break; +#endif + + 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 = 0; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + ret = -EINVAL; + } else { + ret = ari_update_ccplex_gsc(mce_get_curr_cpu_ari_base(), + TEGRA_ARI_CARVEOUT_VPR); + } + + return ret; +} + +/****************************************************************************** + * Handler to update carveout values for TZDRAM aperture + *****************************************************************************/ +int32_t mce_update_gsc_tzdram(void) +{ + /* This function is not required for T23x. + * Return 0 to avoid compile error. + */ + return 0; +} + +/****************************************************************************** + * 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 */ + ari_update_cstate_info(mce_get_curr_cpu_ari_base(), cstate->cluster, + 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 = ari_get_version(mce_get_curr_cpu_ari_base()); + major = (uint32_t)version; + minor = (uint32_t)(version >> 32); + + INFO("MCE Version - HW=%d:%d, SW=%ld:%ld\n", major, minor, + TEGRA_ARI_VERSION_MAJOR, TEGRA_ARI_VERSION_MINOR); + + /* + * Verify that the MCE firmware version and the interface header + * match + */ + if (major != (uint32_t)TEGRA_ARI_VERSION_MAJOR) { + ERROR("MCE major version mismatch\n"); + panic(); + } + + if (minor < (uint32_t)TEGRA_ARI_VERSION_MINOR) { + ERROR("MCE minor version mismatch\n"); + panic(); + } +} + +/****************************************************************************** + * Handler to issue SCF flush - Clean and invalidate caches + *****************************************************************************/ +void mce_clean_and_invalidate_caches(void) +{ + int32_t ret = 0; + + /* + * MCE firmware is not running on simulation platforms. + */ + if (mce_firmware_not_supported()) { + return; + } + + ret = ari_ccplex_cache_clean_and_invalidate(mce_get_curr_cpu_ari_base()); + if (ret < 0) { + ERROR("%s: flush cache_trbits failed(%d)\n", __func__, + ret); + } +} + +#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(); + * + */ + if ((sctlr & (uint64_t)SCTLR_M_BIT) == (uint64_t)SCTLR_M_BIT) { + tlbialle1is(); + tlbialle3is(); + dsbsy(); + } + + /* + * Step2: SCF flush - Clean and invalidate caches and clear the + * TR-bits + */ + ret = ari_ccplex_cache_clean_and_invalidate(mce_get_curr_cpu_ari_base()); + 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. + */ + ari_enable_strict_checking_mode(mce_get_curr_cpu_ari_base()); + } +} +#endif + +#if DEBUG +/* + * attempt to transition the specified core into the DEBUG_RECOVERY Mode (DBGRM) + * core_id: Core ID of Target Core to put into DBRGM + * ret: [1:0] + * 0 – Success. P-Channel returned ACCEPT. + * 1 – Deny. P-Channel returned Deny. + * 2 – Busy. P-Channel for core is currently in a handshake. + * 3 – Off. DSU is unpowered and cannot accept P-Channel requests. + */ +uint32_t mce_enter_debug_recovery_mode(uint32_t core_id) +{ + uint32_t ret; + uint32_t ari_base = mce_get_curr_cpu_ari_base(); + + /* transition the specified core into the DEBUG_RECOVERY Mode */ + ret = ari_core_debug_recovery(ari_base, core_id, false); + if (ret == 0U) { + /* transition the specified DSU into the DEBUG_RECOVERY + * and Warm Reset the requested cluster + */ + ret = ari_dsu_debug_recovery(ari_base, + (core_id / PLATFORM_MAX_CPUS_PER_CLUSTER), true); + } + + return ret; +} +#endif + +/****************************************************************************** + * Handler to power down the entire system + *****************************************************************************/ +void mce_system_shutdown(void) +{ + ari_system_shutdown(mce_get_curr_cpu_ari_base()); +} + +/****************************************************************************** + * Handler to reboot the entire system + *****************************************************************************/ +void mce_system_reboot(void) +{ + ari_system_reboot(mce_get_curr_cpu_ari_base()); +} + +/****************************************************************************** + * Return number of CPU cores + *****************************************************************************/ +uint32_t mce_num_cores(void) +{ + uint32_t num_cores = 1U; + + if (mce_firmware_not_supported()) + return num_cores; + + /* Issue ARI if bitmap is uninitialized */ + if (core_present_bitmap == 0xDEADFEED) { + core_present_bitmap = ari_num_cores(mce_get_curr_cpu_ari_base()); + } + + for (int i = 1; i < PLATFORM_CORE_COUNT; i++) { + if (core_present_bitmap & BIT(i)) + num_cores++; + } + + return num_cores; +} + +/****************************************************************************** + * Return true if a cluster is present + *****************************************************************************/ +bool mce_is_cluster_present(unsigned int id) +{ + unsigned int mode; + + /* Sanity check cluster id */ + if (id >= PLATFORM_CLUSTER_COUNT) { + return false; + } + + /* Cluster 0 is always present */ + if (mce_firmware_not_supported() && (id == 0U)) { + return true; + } + + /* Without MCE support we cannot assume the presence of other clusters */ + if (mce_firmware_not_supported() && (id != 0U)) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + /* Any mode other than "disabled" means the cluster is present */ + return (mode != CLUSTER_MODE_DISABLED); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in lock mode + *****************************************************************************/ +bool mce_is_cluster_in_lock_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_LOCK); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in split mode + *****************************************************************************/ +bool mce_is_cluster_in_split_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_SPLIT); +} + +/****************************************************************************** + * Return true if a cluster is configured to run in hybrid mode + *****************************************************************************/ +bool mce_is_cluster_in_hybrid_mode(unsigned int id) +{ + unsigned int mode; + + /* Sanity checks */ + if ((id >= PLATFORM_CLUSTER_COUNT) || mce_firmware_not_supported()) { + return false; + } + + /* Issue ARI if the bitmap is uninitialized */ + if (cluster_present_bitmap == 0xDEADFEED) { + cluster_present_bitmap = ari_cluster_present_map(mce_get_curr_cpu_ari_base()); + } + + /* Extract the mode */ + mode = (cluster_present_bitmap >> CLUSTER_MODE_SHIFT(id)) & CLUSTER_MODE_MASK; + + return (mode != CLUSTER_MODE_HYBRID); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c new file mode 100644 index 0000000..00a8df2 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c @@ -0,0 +1,250 @@ +/* + * Copyright (c) 2020-2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "se_private.h" + +/******************************************************************************* + * Constants and Macros + ******************************************************************************/ +#define MAX_TIMEOUT_MS U(100) /* Timeout in 100ms */ +#define SE_CTX_SAVE 0U /* Macro for save ctx operation */ +#define SE_CTX_RESTORE 1U /* Macro for restore ctx operation */ +#define SE_SC7_STATUS_ALL_ENGINE_RDY U(0x5F) /* SC7_STATUS value to denote all engine ready */ + +/* + * Check that SE operation has completed after kickoff. + * + * This function is invoked after an SE operation has been started, + * and it checks SE_SC7_STATUS = IDLE + */ +static bool tegra_se_is_operation_complete(void) +{ + uint32_t val = 0U, timeout = 0U; + int32_t ret = 0; + bool se_is_busy = false; + + /* + * Poll the status register to check if the operation + * completed. + */ + do { + val = tegra_se_read_32(SE0_SC7_STATUS); + + se_is_busy = ((val & SE0_SC7_STATUS_BUSY) != 0U); + + /* sleep until SE finishes */ + if (se_is_busy) { + mdelay(1); + timeout++; + } + + } while (se_is_busy && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: Atomic context save operation failed!\n", + __func__); + ret = -ECANCELED; + } + + /* check for context save/restore errors - START_ERROR/INTEGRITY_ERROR */ + val = tegra_se_read_32(SE0_INT_STATUS); + + if ((val & SE0_SC7_CTX_START_ERROR) || (val & SE0_SC7_CTX_INTEGRITY_ERROR)) { + ERROR("CTX START_ERROR/INTEGRITY_ERROR 0x%x\n", val); + 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 = false; + + /* Wait for previous operation to finish */ + do { + val = tegra_se_read_32(SE0_SC7_STATUS); + se_is_ready = (val == SE_SC7_STATUS_ALL_ENGINE_RDY); + + /* 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; + } + return (ret == 0); +} + +/* + * do softreset for SE0 engine to clear the HW flag before the context save. + */ +static void tegra_se_softreset(void) +{ + uint32_t val = SE0_SOFTRESET_TRUE, timeout = 0U; + + /* trigger SE0 softreset */ + tegra_se_write_32(SE0_SOFTRESET, SE0_SOFTRESET_TRUE); + + /* Wait for softreset to finish */ + do { + val = tegra_se_read_32(SE0_SOFTRESET); + + /* sleep until SE is ready */ + mdelay(1); + timeout++; + + } while ((val != SE0_SOFTRESET_FALSE) && (timeout < MAX_TIMEOUT_MS)); + + if (timeout == MAX_TIMEOUT_MS) { + ERROR("%s: SE softreset fail !\n", __func__); + } +} + +/* Function to perform the context save/restore sequence */ +static int32_t tegra_se_program_ctx_ops(uint32_t ctx_op) +{ + int32_t ret = -ECANCELED; + uint32_t se_int_state, val; + + /* Sequence for context save is as below - + * 0. set SE0_SOFTRESET to true and polling it until it change to false. + * This will clear the HW flag to default + * 1. Start NVRNG engine by setting SW_ENGINE_ENABLED in NV_NVRNG_R_CTRL0_0 + * 2. Check if all SE engine is ready by checking SE0_SC7_STATUS_0==0x5F, + * if not by 100ms report timeout. + * 3. Enable SC7_CTX_START_ERROR and SC7_CTX_INTEGRITY_ERROR in SE0_INT_ENABLE register. + * 4. Issue CTX_SAVE by setting SE0_SC7_CTRL bit 0 to 0. + * 5. Check if SE0_SC7_STATUS_0.bit31 shows busy (or) + * SE0_INT_STATUS.SC7_CTX_START_ERROR (or) + * SE0_INT_STATUS.C7_CTX_INTEGRITY_ERROR then report error. + * 6. Clear SE0_INT_STATUS and restore SE0_INT_ENABLE settings. + * Sequence for context restore is same as above but in set#4, + * issue CTX_RESTORE by setting SE0_SC7_CTRL bit 0 to 1 + */ + + if (ctx_op == SE_CTX_SAVE) { + tegra_se_softreset(); + } + + /* Start NVRNG engine */ + val = tegra_rng1_read_32(NV_NVRNG_R_CTRL); + tegra_rng_write_32(NV_NVRNG_R_CTRL, (val | SW_ENGINE_ENABLED)); + + /* Check if SE is in idle state */ + if (!tegra_se_is_ready()) + return ret; + + /* Save SE0_INT_ENABLE and enable SC7 ctx related error report */ + se_int_state = tegra_se_read_32(SE0_INT_ENABLE); + val = SE0_SC7_CTX_START_ERROR | SE0_SC7_CTX_INTEGRITY_ERROR; + tegra_se_write_32(SE0_INT_ENABLE, val); + + /* Perform ctx save/restore */ + if (ctx_op == SE_CTX_SAVE) { + /* Issue context save command */ + tegra_se_write_32(SE0_SC7_CTRL, SE0_SC7_CMD_START_CTX_SAVE); + } else { + /* Issue context restore command */ + tegra_se_write_32(SE0_SC7_CTRL, SE0_SC7_CMD_START_CTX_RESTORE); + } + + /* Check if operation complete and for errors*/ + if (tegra_se_is_operation_complete()) { + INFO("%s: context save/restore done.\n", __func__); + ret = 0; + } else { + ERROR("%s: context save/restore failed.\n", __func__); + } + + /* Clear SE0_INT_STATUS and restore SE0_INT_ENABLE */ + tegra_se_write_32(SE0_INT_STATUS, 0); + tegra_se_write_32(SE0_INT_ENABLE, se_int_state); + + return ret; +} + +static int32_t tegra_se_save_context(void) +{ + return tegra_se_program_ctx_ops(SE_CTX_SAVE); +} + +static int32_t tegra_se_restore_context(void) +{ + return tegra_se_program_ctx_ops(SE_CTX_RESTORE); +} + +/* + * Handler to power down the SE hardware blocks. 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(TEGRA_CLK_SE); + assert(ret == 0); + + /* Issue SE context save */ + ret = tegra_se_save_context(); + assert(ret == 0); + + /* Disable SE clock after SE context save */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA_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(TEGRA_CLK_SE); + assert(ret == 0); + + /* Issue SE context restore */ + ret = tegra_se_restore_context(); + assert(ret == 0); + + /* Disable SE clock after SE context restore */ + ret = tegra_bpmp_ipc_disable_clock(TEGRA_CLK_SE); + assert(ret == 0); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h new file mode 100644 index 0000000..5f4c57c --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SE_PRIVATE_H +#define SE_PRIVATE_H + +#include + +/* Control register to trigger SC7 context save/restore operation */ +#define SE0_SC7_CTRL U(0xBC) +#define SE0_SC7_CTRL_OP_BIT BIT_32(0) +#define SE0_SC7_CMD_START_CTX_SAVE (U(0) << 0) +#define SE0_SC7_CMD_START_CTX_RESTORE (U(1) << 0) + +/* Status register to report SC7 context-save/restore status */ +#define SE0_SC7_STATUS U(0xC0) +#define SE0_SC7_STATUS_BUSY BIT_32(31) +#define SE0_SC7_STATE_SAVE_CTX_VAL (U(0x2) << 7) +#define SE0_SC7_STATE_RESTORE_CTX_VAL (U(0x6) << 7) + +/* Interrupt register to enable/disable for SE engine */ +#define SE0_INT_ENABLE U(0x88) +#define SE0_SC7_CTX_START_ERROR BIT_32(6) +#define SE0_SC7_CTX_INTEGRITY_ERROR BIT_32(7) + +/* Interrupt status register */ +#define SE0_INT_STATUS U(0x8C) + +/* Software reset register to reset SE engine */ +#define SE0_SOFTRESET U(0x60) +#define SE0_SOFTRESET_FALSE U(0) +#define SE0_SOFTRESET_TRUE U(1) + +/******************************************************************************* + * 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); +} + +static inline uint32_t tegra_rng1_read_32(uint32_t offset) +{ + return mmio_read_32((uint32_t)(TEGRA_RNG1_BASE + offset)); +} + +static inline void tegra_rng_write_32(uint32_t offset, uint32_t val) +{ + mmio_write_32((uint32_t)(TEGRA_RNG1_BASE + offset), val); +} + +#endif /* SE_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c new file mode 100644 index 0000000..78c66a9 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +/******************************************************************************* + * Handler to restore platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_restore(void) +{ + ; /* do nothing */ +} + +/******************************************************************************* + * Handler to program platform specific settings to the memory controller + ******************************************************************************/ +void plat_memctrl_setup(void) +{ + ; /* 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, size_in_bytes >> 20); + + /* + * MCE propagates the security configuration values across the + * CCPLEX. + */ + (void)mce_update_gsc_tzdram(); + } +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c new file mode 100644 index 0000000..6a5649a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c @@ -0,0 +1,450 @@ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* state id mask */ +#define TEGRA234_STATE_ID_MASK 0xFU +/* constants to get power state's wake time */ +#define TEGRA234_WAKE_TIME_MASK 0x0FFFFFF0U +#define TEGRA234_WAKE_TIME_SHIFT 4U +/* default core wake mask for CPU_SUSPEND + * WAKE_REQUEST 2:2 Per Core (GIC provides a wake request interface that + * is used to indicate when an interrupt is received that + * is required to wake a core from a low power state.) + */ +#define TEGRA234_CORE_WAKE_MASK 0x4U + +extern bool tegra234_fake_system_suspend; + +static struct t234_psci_percpu_data { + uint32_t wake_time; +} __aligned(CACHE_WRITEBACK_GRANULE) t234_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) & TEGRA234_STATE_ID_MASK; + uint32_t cpu = plat_my_core_pos(); + int32_t ret = PSCI_E_SUCCESS; + + /* save the core wake time (in TSC ticks)*/ + t234_percpu_data[cpu].wake_time = (power_state & TEGRA234_WAKE_TIME_MASK) + << TEGRA234_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 CC7. + */ + clean_dcache_range((uint64_t)&t234_percpu_data[cpu], + sizeof(t234_percpu_data[cpu])); + + /* Sanity check the requested state id */ + switch (state_id) { + case PSTATE_ID_CORE_POWERDN: + + /* 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 val; + uint32_t cpu = plat_my_core_pos(); + int32_t ret; + + /* get the state ID */ + pwr_domain_state = target_state->pwr_domain_state; + stateid_afflvl0 = pwr_domain_state[MPIDR_AFFLVL0] & + TEGRA234_STATE_ID_MASK; + stateid_afflvl2 = pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA234_STATE_ID_MASK; + + if (stateid_afflvl0 == PSTATE_ID_CORE_POWERDN) { + + /* Enter CPU powerdown */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + t234_percpu_data[cpu].wake_time, + 0U, 0U); + + } else if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + if (!tegra234_fake_system_suspend) { + /* + * Before entering SC7 state, the ARM Trusted Firmware shall issue + * a SC7 entry request to the PSC. + */ + tegra_psc_notify_sc7_entry(); + + /* + * 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); + } + + /* Allow BPMP write access to AOTZRAM powergate controls */ + val = mmio_read_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_WRITE_CTL); + val |= (WRITE_CTL_MSTRID_BPMP_FW_BIT | WRITE_CTL_MSTRID_TZ_BIT); + mmio_write_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_WRITE_CTL, + val); + val = mmio_read_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_CTL); + val |= ARF_CTL_OWNER_BPMP_FW; + mmio_write_32(TEGRA_AON_FABRIC_FIREWALL_BASE + AON_FIREWALL_ARF_0_CTL, + val); + } + + } 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_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 = plat_my_core_pos() % PLATFORM_MAX_CPUS_PER_CLUSTER; + 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 = TEGRA234_CORE_WAKE_MASK; + cstate_info.update_wake_mask = 1; + mce_update_cstate_info(&cstate_info); + } + + /* 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 CC7 state and turn off wake mask */ + cstate_info.cluster = TEGRA_ARI_CSTATE_INFO_CLUSTER_CC7; + mce_update_cstate_info(&cstate_info); + + } else { + + /* Turn off wake_mask */ + cstate_info.wake_mask = 0; + 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_suspend_pwrdown_early(const psci_power_state_t *target_state) +{ + return PSCI_E_NOT_SUPPORTED; +} + +int32_t tegra_soc_pwr_domain_power_down_wfi(const psci_power_state_t *target_state) +{ + uint32_t rmr_el3; + uint8_t stateid_afflvl2; + uint32_t val; + mce_cstate_info_t cstate_info = { 0 }; + + /* get the state ID */ + stateid_afflvl2 = target_state->pwr_domain_state[PLAT_MAX_PWR_LVL] & + TEGRA234_STATE_ID_MASK; + + /* + * If we are in fake system suspend mode, ensure we start doing + * procedures that help in looping back towards system suspend exit + * instead of calling WFI by requesting a warm reset. + */ + if (stateid_afflvl2 == PSTATE_ID_SOC_POWERDN) { + if (tegra234_fake_system_suspend) { + rmr_el3 = read_rmr_el3(); + write_rmr_el3(rmr_el3 | RMR_WARM_RESET_CPU); + wfi(); + panic(); + } + + /* + * Before executing wfi instruction to enter SC7 state, + * the ARM Trusted Firmware shall confirm that the PSC + * has completed its SC7 entry sequence. + */ + tegra_psc_wait_for_ack(); + + /* SCF flush - Clean and invalidate caches */ + mce_clean_and_invalidate_caches(); + + /* Prepare for system suspend */ + cstate_info.cluster = PSTATE_ID_CORE_POWERDN; + cstate_info.system = PSTATE_ID_CORE_POWERDN; + mce_update_cstate_info(&cstate_info); + + do { + val = (uint32_t)mce_command_handler( + (uint32_t)MCE_CMD_IS_SC7_ALLOWED, + 0U, 0U, 0U); + } while (val == 0U); + + /* Instruct the MCE to enter system suspend state */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + MCE_CORE_SLEEP_TIME_INFINITE, 0U, 0U); + } + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_on(u_register_t mpidr) +{ + uint64_t target_cpu = plat_core_pos_by_mpidr(mpidr); + + if (target_cpu >= PLATFORM_CORE_COUNT) { + ERROR("%s: unsupported CPU (0x%x)\n", __func__ , (uint32_t)target_cpu); + return PSCI_E_NOT_PRESENT; + } + + (void)mce_command_handler((uint64_t)MCE_CMD_ONLINE_CORE, target_cpu, 0U, 0U); + + return PSCI_E_SUCCESS; +} + +/******************************************************************************* + * Enable write access to cluster PMU register + ******************************************************************************/ +static void tegra_enable_cluster_pmu_writes(void) +{ + uint64_t actlr_elx; + + /** + * ARM DSU PMU driver in linux kernel requires write access to CLUSTERPM* + * registers. These registers are protected by CLUSTERPMUEN bit in ACTLR + * register. Linux kernel is in EL2, so ACTLR_EL3.CLUSTERPMUEN bit needs to + * be set, which will allow writes in EL2/EL1secure. + */ + + /* Enable write in EL2 */ + actlr_elx = read_actlr_el3(); + actlr_elx |= CORTEX_A78_AE_ACTLR_CLUSTERPMUEN_BIT; + write_actlr_el3(actlr_elx); +} + +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 }; + uint32_t val = 0U; + uint32_t __unused cluster_id = ((uint32_t)read_mpidr() >> + MPIDR_AFF2_SHIFT) & MPIDR_AFFLVL_MASK; + uint32_t __unused smen; + +#if RAS_EXTENSION + /* Enable RAS handling for the cluster specific nodes */ + tegra234_ras_init_my_cluster(); +#endif + + /* + * Program the following bits to '1'. + * + * Bit 0: Enable interleaving normal Non-cacheable transactions between + * master interfaces like Cacheable transactions. + * Bit 14: Enables sending WriteEvict transactions on the ACE or CHI + * master for UniqueClean evictions. + */ + val = read_clusterectlr_el1(); + write_clusterectlr_el1(val | DSU_WRITEEVICT_BIT | DSU_NC_CTRL_BIT); + + /* + * Reset power state info for CPUs when onlining. We set + * deepest power when offlining or suspending a core, so + * reset the power state when the CPU powers back on. + */ + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + cstate_info.cluster = TEGRA_ARI_CSTATE_INFO_CLUSTER_CC1; + mce_update_cstate_info(&cstate_info); + } + + /* + * Enable write access to cluster PMU register if ODM_PRODUCTION + * fuse is 0. + */ + if (mmio_read_32(TEGRA_FUSE_BASE + SECURITY_MODE) == 0U) { + tegra_enable_cluster_pmu_writes(); + } + + /* + * 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 + + if (!tegra234_fake_system_suspend) { + /* Resume SE, RNG1 and PKA1 */ + tegra_se_resume(); + } + +#if RAS_EXTENSION + /* Enable RAS handling for all the common nodes */ + tegra234_ras_init_common(); +#endif + NOTICE("%s: exited SC7 successfully. Entering normal world.\n", __func__); + } + +#if GICV3_SUPPORT_GIC600AE_FMU + if (tegra_platform_is_silicon() || tegra_platform_is_fpga()) { + /* disable the GICFMU SMID 0xB after cluster power on */ + if (stateid_afflvl0 != PSTATE_ID_CORE_POWERDN) { + smen = ((FMU_BLK_PPI0 + cluster_id) << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + } + } +#endif + + return PSCI_E_SUCCESS; +} + +int32_t tegra_soc_pwr_domain_off(const psci_power_state_t *target_state) +{ + (void)target_state; + + /* Turn off CPU */ + (void)mce_command_handler((uint64_t)MCE_CMD_ENTER_CSTATE, + MCE_CORE_SLEEP_TIME_INFINITE, 0U, 0U); + + 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/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c new file mode 100644 index 0000000..596f47b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c @@ -0,0 +1,679 @@ +/* + * Copyright (c) 2020-2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +DEFINE_BAKERY_LOCK(tegra234_ras_lock); + +/* Forward declarations */ +static int32_t tegra234_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data __unused); +static int32_t tegra234_ras_record_probe(const struct err_record_info *info, + int *probe_data); +static int32_t tegra234_gic_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *const data __unused); +static int32_t tegra234_gic_ras_record_probe(const struct err_record_info *info, + int *probe_data); + +/* Global variables */ +static bool ehf_handler_registered; + +/******************************************************************************* + * Tegra234 RAS nodes + ******************************************************************************/ +DEFINE_ONE_RAS_NODE(CCPMU); +DEFINE_ONE_RAS_AUX_DATA(CCPMU); +DEFINE_ONE_RAS_NODE(CMU_CLOCKS); +DEFINE_ONE_RAS_AUX_DATA(CMU_CLOCKS); +DEFINE_ONE_RAS_NODE(IH); +DEFINE_ONE_RAS_AUX_DATA(IH); +DEFINE_ONE_RAS_NODE(IST); +DEFINE_ONE_RAS_AUX_DATA(IST); +DEFINE_ONE_RAS_NODE(IOB); +DEFINE_ONE_RAS_AUX_DATA(IOB); +DEFINE_ONE_RAS_NODE(SNOC); +DEFINE_ONE_RAS_AUX_DATA(SNOC); +DEFINE_ONE_RAS_NODE(SCC); +DEFINE_ONE_RAS_AUX_DATA(SCC); +DEFINE_ONE_RAS_NODE(ACI); +DEFINE_ONE_RAS_AUX_DATA(ACI); +DEFINE_ONE_RAS_NODE(CORE_DCLS); +DEFINE_ONE_RAS_AUX_DATA(CORE_DCLS); +DEFINE_ONE_RAS_NODE(GIC600_FMU); +DEFINE_ONE_RAS_AUX_DATA(GIC600_FMU); + +/* + * We have same probe and handler for each error record group, use a macro to + * simply the record definition. + */ +#define ADD_ONE_ERR_GROUP(base_addr, size_num_k, aux_data) \ + ERR_RECORD_MEMMAP_V1((base_addr), (size_num_k), \ + &tegra234_ras_record_probe, \ + &tegra234_ras_record_handler, \ + aux_data) + +#define ADD_GICFMU_ERR_GROUP(base_addr, size_num_k, aux_data) \ + ERR_RECORD_MEMMAP_V1(TEGRA_GICFMU_BASE, 4, \ + &tegra234_gic_ras_record_probe, \ + &tegra234_gic_ras_record_handler, \ + aux_data) + +static struct err_record_info tegra234_ras_records_common[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CCPMU_BASE, 4, &CCPMU_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CMU_CLOCKS_BASE, 4, &CMU_CLOCKS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IH_BASE, 4, &IH_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IOB_BASE, 4, &IOB_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SNOC_BASE, 4, &SNOC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE0_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE1_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE2_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE3_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE4_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE5_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE6_BASE, 4, &SCC_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_SCC_SLICE7_BASE, 4, &SCC_aux_data), + ADD_GICFMU_ERR_GROUP(TEGRA_GICFMU_BASE, 4, &GIC600_FMU_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster0[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER0_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER0_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL0_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster1[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER1_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER1_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL1_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +static struct err_record_info tegra234_ras_records_cluster2[] = { + ADD_ONE_ERR_GROUP(TEGRA234_RAS_IST_CLUSTER2_BASE, 4, &IST_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_ACI_CLUSTER2_BASE, 4, &ACI_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE0_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE2_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE3_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE_LS_PAIR1_BASE, 4, &CORE_DCLS_aux_data), + ADD_ONE_ERR_GROUP(TEGRA234_RAS_CL2_CORE_LS_PAIR2_BASE, 4, &CORE_DCLS_aux_data) +}; + +/* Register the common error record to get past RAS driver compilation */ +REGISTER_ERR_RECORD_INFO(tegra234_ras_records_common); + +/******************************************************************************* + * Helper functions + ******************************************************************************/ + +/* Check if IST is enabled for the platform */ +static bool is_ist_enabled(void) +{ + uint32_t val = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_IST_CLK_ENABLE); + return ((val & BIT(0)) == 1U); +} + +/* + * Helper function to check if the given error record is supported by + * the platform + */ +static bool is_err_record_supported(struct err_record_info *record) +{ + const struct ras_aux_data *aux_data = + (const struct ras_aux_data *)record->aux_data; + + /* + * Skip IST, if it is disabled for the platform + */ + if (!is_ist_enabled() && !strncmp(aux_data->name, "IST", strlen("IST"))) { + return false; + } + + /* + * Skip CORE_DCLS nodes if the cluster is running in split + * or hybrid mode + */ + if ((mce_is_cluster_in_split_mode(0) || mce_is_cluster_in_hybrid_mode(0)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + if ((mce_is_cluster_in_split_mode(1) || mce_is_cluster_in_hybrid_mode(1)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + if ((mce_is_cluster_in_split_mode(2) || mce_is_cluster_in_hybrid_mode(2)) && + (!strncmp(aux_data->name, "CORE_DCLS", strlen("CORE_DCLS")))) { + return false; + } + + return true; +} + +/******************************************************************************* + * Error handling functions + ******************************************************************************/ +/* Function to handle error from one given node */ +static int32_t tegra234_ras_node_handler(uint32_t base, const char *name, + const struct ras_error *errors, unsigned int num_errors) +{ + bool found = false; + uint64_t val = 0U; + uint32_t ierr = 0U, serr = 0U; + uint64_t status = mmio_read_64(base + ERR_STATUS(0)); + uint64_t addr = mmio_read_64(base + ERR_ADDR(0)); + uint64_t misc0 = mmio_read_64(base + ERR_MISC0(0)); + uint64_t misc1 = mmio_read_64(base + ERR_MISC1(0)); + uint64_t misc2 = mmio_read_64(base + ERR_MISC2(0)); + uint64_t misc3 = mmio_read_64(base + ERR_MISC3(0)); + + /* + * repeat until we have ERRSTATUS value consistent with + * the syndrome recorded for that error + */ + while (mmio_read_64(base + ERR_STATUS(0)) != status) { + status = mmio_read_64(base + ERR_STATUS(0)); + addr = mmio_read_64(base + ERR_ADDR(0)); + misc0 = mmio_read_64(base + ERR_MISC0(0)); + misc1 = mmio_read_64(base + ERR_MISC1(0)); + misc2 = mmio_read_64(base + ERR_MISC2(0)); + misc3 = mmio_read_64(base + ERR_MISC3(0)); + } + + /* not a valid error. */ + if (ERR_STATUS_GET_FIELD(status, V) == 0U) { + return 0; + } + + /* extract IERR and SERR from ERRSTATUS */ + ierr = (uint32_t)ERR_STATUS_GET_FIELD(status, IERR); + serr = (uint32_t)ERR_STATUS_GET_FIELD(status, SERR); + + /* + * POD Reset SERR value should be a 1 indicating an + * "implementation defined" error. But it incorrectly + * reports 8'd14, which indicates "illegal access (s/w + * faults)". + * + * If IERR = 28, SERR = 14 change the SERR to 1 as a + * work around. + */ + if (!strncmp(name, "DSU_IFP", strlen("DSU_IFP")) && + ((ierr == U(28)) && (serr == U(14)))) { + serr = U(1); + } + + /* + * Ideally, IST CREG lock errors should have a SERR value + * of 14, but it is incorrectly reported as 1. + * + * If IERR = 18, SERR = 1 change the SERR to 14 as a + * work around. + */ + if (!strncmp(name, "IST", strlen("IST")) && + ((ierr == U(18)) && (serr == U(1)))) { + serr = U(14); + } + + ERR_STATUS_SET_FIELD(val, V, 1); + + ERROR("**************************************\n"); + ERROR("RAS %s Error in %s, base=0x%x:\n", + (ERR_STATUS_GET_FIELD(status, UE) != 0U) ? "Uncorrectable" : + "Corrected", name, base); + ERROR("\tStatus = 0x%" PRIx64 "\n", status); + + ERROR("SERR = %s: 0x%x\n", ras_serr_to_str(serr), serr); + + /* 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; i < num_errors; 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); + } + + /* 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); + } + + } else { + /* For corrected error, simply clear it. */ + ERR_STATUS_SET_FIELD(val, CE, 1); + } + + /* Miscellaneous Register Valid. */ + if (ERR_STATUS_GET_FIELD(status, MV) != 0U) { + ERROR("\tMISC0 = 0x%" PRIx64 "\n", misc0); + ERROR("\tMISC1 = 0x%" PRIx64 "\n", misc1); + ERROR("\tMISC2 = 0x%" PRIx64 "\n", misc2); + ERROR("\tMISC3 = 0x%" PRIx64 "\n", misc3); + ERR_STATUS_SET_FIELD(val, MV, 1); + } + + /* Address Valid. */ + if (ERR_STATUS_GET_FIELD(status, AV) != 0U) { + ERROR("\tADDR = 0x%" PRIx64 "\n", addr); + 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); + } + + ERROR("**************************************\n"); + + /* Write to clear reported error records */ + mmio_write_64(base + ERR_STATUS(0), val); + mmio_write_64(base + ERR_MISC0(0), 0); + mmio_write_64(base + ERR_MISC1(0), 0); + mmio_write_64(base + ERR_ADDR(0), 0); + + /* error handled */ + return 0; +} + +/* Function to handle one error node from an error record group. */ +static int32_t tegra234_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *data __unused) +{ + const struct ras_aux_data *aux_data = info->aux_data; + uint32_t base = info->memmap.base_addr; + + /* make sure that we have valid error record info */ + assert(aux_data->error_records != NULL); + + return tegra234_ras_node_handler(base, aux_data->name, + aux_data->error_records, aux_data->num_err_records); +} + +/* Function to probe an error from error record group. */ +static int32_t tegra234_ras_record_probe(const struct err_record_info *info, + int *probe_data) +{ + return ser_probe_memmap(info->memmap.base_addr, info->memmap.size_num_k, probe_data); +} + +/* Function to handle one error node from an error record group. */ +static int32_t tegra234_gic_ras_record_handler(const struct err_record_info *info, + int probe_data, const struct err_handler_data *data __unused) +{ + return gic600_fmu_ras_handler(info->memmap.base_addr, probe_data); +} + +/* Function to probe an error from error record group. */ +static int32_t tegra234_gic_ras_record_probe(const struct err_record_info *info, + int *probe_data) +{ + return gic600_fmu_probe(info->memmap.base_addr, probe_data); +} + +/* + * Given an RAS interrupt number, locate the registered handler and call it. If + * no handler was found for the interrupt number, this function panics. + */ +static int tegra234_ras_handler(uint32_t intr_raw, uint32_t flags, + void *handle, void *cookie) +{ + uint64_t intr_status = ih_read_ras_intstatus(plat_my_core_pos()); + struct err_record_info *selected = NULL; + int probe_data = 0; + int ret; + uint32_t num_records = 0U; + + const struct err_handler_data err_data = { + .version = ERR_HANDLER_VERSION, + .interrupt = intr_raw, + .flags = flags, + .cookie = cookie, + .handle = handle + }; + + VERBOSE("%s: irq=%d, intr_status=0x%" PRIx64 "\n", __func__, intr_raw, intr_status); + + /* INTR_STATUS will be '0' for secondary cores */ + if (intr_status == 0) + return 0; + + if ((intr_status & TEGRA234_IH_STATUS_MASK_CMU) != 0U) { + selected = tegra234_ras_records_common; + num_records = ARRAY_SIZE(tegra234_ras_records_common); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_SCF) != 0U) { + selected = tegra234_ras_records_common; + num_records = ARRAY_SIZE(tegra234_ras_records_common); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL0) != 0U) { + selected = tegra234_ras_records_cluster0; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster0); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL1) != 0U) { + selected = tegra234_ras_records_cluster1; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster1); + } else if ((intr_status & TEGRA234_IH_STATUS_MASK_CL2) != 0U) { + selected = tegra234_ras_records_cluster2; + num_records = ARRAY_SIZE(tegra234_ras_records_cluster2); + } + + assert(selected != NULL); + + /* check all the error records */ + while (num_records-- > 0U) { + + /* Check if the platform supports this error record */ + if (!is_err_record_supported(selected)) { + /* next error record */ + selected++; + continue; + } + + /* Is this record valid? */ + ret = selected->probe(selected, &probe_data); + + /* Call error handler for the record group */ + if (ret != 0) { + + /* serialize RAS record accesses across CPUs */ + bakery_lock_get(&tegra234_ras_lock); + + /* Invoke handler for the RAS node */ + selected->handler(selected, probe_data, &err_data); + + bakery_lock_release(&tegra234_ras_lock); + + /* Clear interrupt status */ + ih_write_intstatus_clr(plat_my_core_pos(), intr_status); + + /* + * 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_raw); + + ret = sdei_dispatch_event(TEGRA_SDEI_EP_EVENT_0 + + plat_my_core_pos()); + if (ret != 0) + ERROR("sdei_dispatch_event returned %d\n", ret); + } + + /* next error record */ + selected++; + } + + return 0; +} + +/******************************************************************************* + * This function is invoked by the RAS framework for the platform to handle an + * External Abort received at EL3. + ******************************************************************************/ +void plat_ea_handler(unsigned int ea_reason, uint64_t syndrome, void *cookie, + void *handle, uint64_t flags) +{ + ERROR("Exception reason=%u syndrome=0x%" PRIx64 "\n", ea_reason, syndrome); + +#if RAS_EXTENSION + tegra234_ras_handler(0, flags, handle, cookie); +#else + ERROR("Unhandled External Abort received on 0x%lx at EL3!\n", + read_mpidr_el1()); + panic(); +#endif +} + +/******************************************************************************* + * This function is invoked when an External Abort is received while executing + * in EL3. + ******************************************************************************/ +void plat_handle_el3_ea(void) +{ + uint64_t syndrome = read_esr_el3(); + uint32_t flags = read_scr_el3() & SCR_NS_BIT; + + ERROR("Exception reason=%u syndrome=0x%" PRIx64 "\n", ERROR_EA_ASYNC, syndrome); + +#if RAS_EXTENSION + tegra234_ras_handler(0, flags, NULL, NULL); +#else + ERROR("Unhandled External Abort received on 0x%lx at EL3!\n", + read_mpidr_el1()); + panic(); +#endif +} + +static void enable_error_detection_for_group(struct err_record_info *group, + uint32_t num_of_entries) +{ + struct err_record_info *info; + + for (info = group; num_of_entries > 0; num_of_entries--, info++) { + + /* Check if the platform supports this error record */ + if (!is_err_record_supported(info)) { + continue; + } + + uint32_t base = info->memmap.base_addr; + const struct ras_aux_data *aux_data = (const struct ras_aux_data *)info->aux_data; + /* ERRCTLR register value. */ + uint64_t err_ctlr = 0ULL; + /* all supported errors for this node. */ + uint64_t err_fr; + /* uncorrectable errors */ + uint64_t uncorr_errs; + /* correctable errors */ + uint64_t corr_errs; + + /* + * Skip GIC600_FMU init here, as it is done later by + * the platform + */ + if (!strncmp(aux_data->name, "GIC600_FMU", strlen("GIC600_FMU"))) { + continue; + } + + /* + * Catch error if something is wrong with the RAS aux data + * record table. + */ + assert(aux_data != NULL); + assert(aux_data->get_ue_mask != NULL); + assert(aux_data->get_ce_mask != NULL); + + /* Read the errors supported by the node */ + err_fr = mmio_read_64(base + ERR_FR(0)) & ERR_FR_EN_BITS_MASK; + uncorr_errs = aux_data->get_ue_mask(); + corr_errs = aux_data->get_ce_mask(); + + VERBOSE("[%s] ERRFR=0x%" PRIx64 ", expected=0x%" PRIx64 "\n", aux_data->name, + err_fr, uncorr_errs | corr_errs); + + /* enable error reporting and logging */ + ERR_CTLR_ENABLE_FIELD(err_ctlr, ED); + + /* uncorrected error recovery interrupt enable */ + if ((uncorr_errs & err_fr) != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctlr, UI); + } + + /* fault handling interrupt for corrected errors enable */ + if ((corr_errs & err_fr) != 0ULL) { + ERR_CTLR_ENABLE_FIELD(err_ctlr, CFI); + } + + /* enable all the supported errors */ + err_ctlr |= (err_fr & (uncorr_errs | corr_errs)); + + /* enable specified errors, or set to 0 if no supported error */ + VERBOSE("[%s] ERRCTLR=0x%" PRIx64 "\n", aux_data->name, err_ctlr); + mmio_write_64(base + ERR_CTLR(0), err_ctlr); + + /* Assert if all errors have not been enabled */ + err_ctlr &= ERR_FR_EN_BITS_MASK; + assert((mmio_read_64(base + ERR_CTLR(0)) & ERR_FR_EN_BITS_MASK) == err_ctlr); + } +} + +/* + * Function to enable reporting for RAS error records common to all clusters + * + * Uncorrectable and correctged errors are set to report as interrupts. + */ +void tegra234_ras_init_common(void) +{ + uint32_t i; + + /* RAS is only supported by limited platforms */ + if (!tegra_platform_is_fpga() && !tegra_platform_is_silicon()) { + return; + } + + /* all FHI/ERI bits must be enabled for all cores */ + for (i = 0; i < PLATFORM_CORE_COUNT; i++) { + ih_write_ras_general_enb(i, ENB_ALL_INTR_SOURCES); + ih_write_ras_general_mask(i, 0); + } + + /* Enable RAS error detection and reporting for common group */ + enable_error_detection_for_group(tegra234_ras_records_common, + ARRAY_SIZE(tegra234_ras_records_common)); + + /* install common interrupt handler */ + if (!ehf_handler_registered) { + ehf_register_priority_handler(PLAT_RAS_PRI, tegra234_ras_handler); + ehf_handler_registered = true; + } + + VERBOSE("RAS handling enabled for common nodes\n"); +} + +/* Struct to describe the RAS error records for CPU clusters */ +typedef struct err_record_desc { + struct err_record_info *record; + uint32_t num_entries; +} err_record_desc_t; + +/* + * Function to enable reporting for RAS error records for a given cluster + * + * Uncorrectable and correctged errors are set to report as interrupts. + */ +void tegra234_ras_init_my_cluster(void) +{ + int id = MPIDR_AFFLVL2_VAL(read_mpidr()); + err_record_desc_t list[] = { + { + .record = tegra234_ras_records_cluster0, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster0) + }, + { + .record = tegra234_ras_records_cluster1, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster1) + }, + { + .record = tegra234_ras_records_cluster2, + .num_entries = ARRAY_SIZE(tegra234_ras_records_cluster2) + } + }; + + assert(id < ARRAY_SIZE(list)); + + /* RAS is only supported by limited platforms */ + if (!tegra_platform_is_fpga() && !tegra_platform_is_silicon()) { + return; + } + + /* Enable RAS error detection and reporting for the cluster */ + if (mce_is_cluster_present(id)) { + enable_error_detection_for_group(list[id].record, list[id].num_entries); + } + + VERBOSE("RAS handling enabled for cluster%d\n", id); +} + +#if DEBUG + +#define ERR_MISC0_CEC_SHIFT U(32) +#define ERR_MISC0_CEC_VALUE ULL(0x7F7F) +#define ERR_PFGCTL U(0x808) +#define ERR_PFGCDN U(0x810) + +int tegra234_ras_inject_fault(uint64_t base, uint64_t pfgcdn, uint64_t pfgctl) +{ + uint64_t errctlr, val; + + if ((base < TEGRA234_RAS_CCPMU_BASE) || + (base > TEGRA234_RAS_CL2_DSU_IFP_BASE)) { + /* No record found */ + return -EINVAL; + } + + /* Set ERRMISC0.CEC bits */ + val = mmio_read_64(base + ERR_MISC0(0)); + val |= (ERR_MISC0_CEC_VALUE << ERR_MISC0_CEC_SHIFT); + mmio_write_64(base + ERR_MISC0(0), val); + + errctlr = mmio_read_64(base + ERR_CTLR(0)); + errctlr &= ERR_FR_EN_BITS_MASK; + + if ((pfgctl & errctlr) == 0U) + return -ENOTSUP; + + VERBOSE("%s: PFGCDN=0x%" PRIx64 ", PFGCTL=0x%" PRIx64 "\n", __func__, + pfgcdn, pfgctl); + mmio_write_64(base + ERR_PFGCDN, pfgcdn); + mmio_write_64(base + ERR_PFGCTL, pfgctl); + + return 0; +} +#endif diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c new file mode 100644 index 0000000..2022bce --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/******************************************************************************* + * Setup secondary CPU vectors + ******************************************************************************/ +void plat_secondary_setup(void) +{ + uint64_t reset_addr = (uint64_t)tegra_secure_entrypoint; + + INFO("Setting up secondary CPU boot\n"); + + /* save reset vector to be used during SYSTEM_SUSPEND exit */ + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_LO, + (uint32_t)reset_addr); + mmio_write_32(TEGRA_SCRATCH_BASE + SCRATCH_RESET_VECTOR_HI, + (uint32_t)(reset_addr >> 32)); +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c new file mode 100644 index 0000000..a62659b --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c @@ -0,0 +1,569 @@ +/* + * Copyright (c) 2021-2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* ID for spe-console */ +#define TEGRA_CONSOLE_SPE_ID 0xFE +/* MCE aperture start address */ +#define TEGRA_MCE_ARI0_BASE TEGRA_MMCRAB_BASE + MCE_ARI_APERTURE_0_OFFSET + +/* CPU Extended control EL1 register */ +DEFINE_RENAME_SYSREG_READ_FUNC(cpuectlr_el1, CORTEX_A76_CPUECTLR_EL1) + +/******************************************************************************* + * 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_TSA_BASE, 0x20000U, /* 128KB */ + (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_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_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_FUSE_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 +#if !ENABLE_CONSOLE_SPE + MAP_REGION_FLAT(TEGRA_UARTC_BASE, 0x20000U, /* 128KB - UART C, G */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_SCRATCH_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_AON_FABRIC_FIREWALL_BASE, 0x1000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + 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_MCE_ARI0_BASE, 0xc0000U, /* 64KB*12 */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICD_BASE, 0x10000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_GICR_BASE, 0x200000U, /* 2MB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#if GICV3_SUPPORT_GIC600AE_FMU + MAP_REGION_FLAT(TEGRA_GICFMU_BASE, 0x10000U, /* 4KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), +#endif + MAP_REGION_FLAT(TEGRA_CAR_RESET_BASE, 0x10000U, /* 64KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_CCPMU_RAS_BASE, 0x1D000U, /* 116KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL0_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL1_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_RAS_CL2_CORE0_BASE, 0x9000U, /* 36KB */ + (uint8_t)MT_DEVICE | (uint8_t)MT_RW | (uint8_t)MT_SECURE), + MAP_REGION_FLAT(TEGRA_PSC_MBOX_TZ_BASE, 0x2000U, /* 8KB */ + (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 TEGRA234_MAX_UART_PORTS 6 + +/******************************************************************************* + * This variable holds the UART port base addresses + ******************************************************************************/ +static uint32_t tegra234_uart_addresses[TEGRA234_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, +}; +#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 < TEGRA234_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(tegra234_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 +} + +/******************************************************************************* + * Handler for early platform setup + ******************************************************************************/ +void plat_early_platform_setup(void) +{ + uint32_t __unused val; + + /* sanity check MCE firmware compatibility */ + mce_verify_firmware_version(); + + /* SCF flush - Clean and invalidate caches */ + mce_clean_and_invalidate_caches(); + +#if RAS_EXTENSION + /* Enable RAS handling for all the common nodes */ + tegra234_ras_init_common(); +#endif + + /* + * Number of physical cores should be less than PLATFOM_CORE_COUNT + */ + assert(PLATFORM_CORE_COUNT >= mce_num_cores()); + +#if !DEBUG + /* + * check ETM settings + * Assert if the TRCPRGCTLR.EN bit is not set. + */ + val = mmio_read_32(TEGRA_DBGAPB_BASE + TEGRA_TRCPRGCTLR_OFFSET); + assert((val & TRCPRGCTLR_EN_BIT) == TRCPRGCTLR_EN_BIT); +#endif + + /* + * Program the following bits to '1'. + * + * Bit 0: Enable interleaving normal Non-cacheable transactions between + * master interfaces like Cacheable transactions. + * Bit 14: Enables sending WriteEvict transactions on the ACE or CHI + * master for UniqueClean evictions. + */ + val = read_clusterectlr_el1(); + write_clusterectlr_el1(val | DSU_WRITEEVICT_BIT | DSU_NC_CTRL_BIT); +} + +/****************************************************************************** + * On a GICv3 system, use Group0 interrupts as secure interrupts + *****************************************************************************/ +static const interrupt_prop_t tegra234_interrupt_props[] = { + INTR_PROP_DESC(TEGRA234_RAS_PPI_ERI, PLAT_RAS_PRI, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(TEGRA234_RAS_PPI_FHI, PLAT_RAS_PRI, + INTR_GROUP0, GIC_INTR_CFG_LEVEL), + INTR_PROP_DESC(TEGRA_SDEI_SGI_PRIVATE, PLAT_SDEI_CRITICAL_PRI, + INTR_GROUP0, GIC_INTR_CFG_EDGE), + INTR_PROP_DESC(TEGRA234_TOP_WDT_IRQ, PLAT_TEGRA_WDT_PRIO, + INTR_GROUP0, GIC_INTR_CFG_EDGE) +}; + +/******************************************************************************* + * Initialize the GIC and SGIs + ******************************************************************************/ +void plat_gic_setup(void) +{ + /* Tegra234 contains GICD, SPI Collator, Wake Request, PPI0-PPI2 blocks */ + uint64_t tegra234_gic600_fmu_blks = BIT(FMU_BLK_GICD) | BIT(FMU_BLK_SPICOL) | + BIT(FMU_BLK_WAKERQ) | BIT(FMU_BLK_PPI0) | BIT(FMU_BLK_PPI1) | + BIT(FMU_BLK_PPI2); + uint32_t smen; + + tegra_gic_setup(tegra234_interrupt_props, ARRAY_SIZE(tegra234_interrupt_props)); + + /* initialize the GICD and GICR */ + tegra_gic_init(); + +#if GICV3_SUPPORT_GIC600AE_FMU + /* initialize the Fault Management Unit */ + if (tegra_platform_is_fpga() || tegra_platform_is_silicon()) { + gic600_fmu_init(TEGRA_GICFMU_BASE, tegra234_gic600_fmu_blks, + true, true); + + /* + * The PPI0/1/2 block SMID 0xB causes spurious RAS errors. + * As a workaround, disable the SMID for these blocks. + */ + smen = (FMU_BLK_PPI0 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + + smen = (FMU_BLK_PPI1 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + + smen = (FMU_BLK_PPI2 << FMU_SMEN_BLK_SHIFT) | + (0xb << FMU_SMEN_SMID_SHIFT); + gic_fmu_write_smen(TEGRA_GICFMU_BASE, smen); + } +#endif + /* + * 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 reg; + uint64_t val; + + reg = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PARAMS_HI_ADDR); + val = ((uint64_t)reg & SCRATCH_BL31_PARAMS_HI_ADDR_MASK) >> + SCRATCH_BL31_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= (uint64_t)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) +{ + uint32_t reg; + uint64_t val; + + reg = mmio_read_32(TEGRA_SCRATCH_BASE + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR); + val = ((uint64_t)reg & SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_MASK) >> + SCRATCH_BL31_PLAT_PARAMS_HI_ADDR_SHIFT; + val <<= 32; + val |= (uint64_t)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) +{ + uint32_t ret; + struct bpmp_ipc_platform_data *bpmp_ipc_data = plat_get_bpmp_ipc_data(); + +#if ENABLE_STRICT_CHECKING_MODE + /* + * Enable strict checking after programming the GSC for + * enabling TZSRAM and TZDRAM + */ + mce_enable_strict_checking(); +#endif + + /* memmap bpmp_ipc_tz addr */ + if (bpmp_ipc_data != NULL) { + ret = mmap_add_dynamic_region(bpmp_ipc_data->bpmp_ipc_tx_base, /* PA */ + bpmp_ipc_data->bpmp_ipc_tx_base, /* VA */ + (TEGRA_BPMP_IPC_CH_MAP_SIZE * 2), /* 8KB size */ + MT_DEVICE | MT_RW | MT_SECURE); /* attrs */ + assert(ret == 0); + } +} + +/******************************************************************************* + * Handler to indicate support for System Suspend + ******************************************************************************/ +bool plat_supports_system_suspend(void) +{ + return true; +} + +/******************************************************************************* + * Platform specific FIQ handler. + * Return true if `irq_num` number is handled by this function. + ******************************************************************************/ +bool plat_fiq_handler(uint32_t irq_num) +{ + return false; +} + +/******************************************************************************* + * Platform handler to verify system regsiter settings before completing + * boot + ******************************************************************************/ +void plat_verify_sysreg_settings(void) +{ + uint64_t mask, val; + + /* + * Check SCTLR_EL3 settings + * Assert for the below incorrect settings + * 1. WXN bit is not '1'. + * 2. EE bit is not '0'. + * 3. SA bit is not '1'. + * 4. A bit is not '1'. + * 5. SSBS is not '0'. + */ + mask = SCTLR_WXN_BIT | SCTLR_EE_BIT | SCTLR_SA_BIT | SCTLR_A_BIT | SCTLR_DSSBS_BIT; + val = read_sctlr_el3() & mask; + assert(val == (SCTLR_WXN_BIT | SCTLR_SA_BIT | SCTLR_A_BIT)); + + /* + * Check SCR_EL3 settings + * Assert for the below incorrect settings + * 1. TWE bit is not '0'. + * 2. TWI bit is not '0'. + * 3. SIF bit is not '1'. + * 4. SMD bit is not '0'. + * 5. EA bit is not '1'. + */ + mask = SCR_SIF_BIT | SCR_TWE_BIT | SCR_TWI_BIT | SCR_SMD_BIT; + val = read_scr() & mask; + assert(val == SCR_SIF_BIT); +#if HANDLE_EA_EL3_FIRST + mask = SCR_EA_BIT; + val = read_scr() & mask; + assert(val == SCR_EA_BIT); +#endif + + /* + * Check MDCR_EL3 settings + * Assert for the below incorrect settings + * 1. SDD bit is not '1'. + * 2. TDOSA bit is not '0'. + * 3. TDA bit is not '0' + * 4. TPM bit nis ot '0'. + */ + mask = MDCR_SDD_BIT | MDCR_TDOSA_BIT | MDCR_TDA_BIT | MDCR_TPM_BIT; + val = read_mdcr_el3() & mask; + assert(val == MDCR_SDD_BIT); + + /* + * Check CPTR_EL3 settings + * Assert for the below incorrect settings + * 1. TCPAC bit is not '0'. + * 2. TTA bit is not '0'. + * 3. TFP bit is not '0'. + */ + mask = TCPAC_BIT | TTA_BIT | TFP_BIT; + assert((read_cptr_el3() & mask) == 0U); + + /* + * Check CPTR_read_cntfrq_el0 settings + * Assert for incorrect value. + */ + assert(read_cntfrq_el0() == plat_get_syscnt_freq2()); + + /* + * Check PMCR_EL0 settings + * Assert for the below incorrect settings + * 1. LC is not '1' + * 2. DP is not '1' + * 3. X is not '0' + * 4. D is not '0' + */ + mask = PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT | PMCR_EL0_X_BIT | PMCR_EL0_D_BIT; + val = read_pmcr_el0() & mask; + assert(val == (PMCR_EL0_LC_BIT | PMCR_EL0_DP_BIT)); + + /* + * Check daif settings + * Assert if External Aborts and SError Interrupts + * in 'daif' register are disabled. + */ + assert((read_daif() & DAIF_ABT_BIT) == 0U); + + /* + * Check Write streaming settings + * Assert if the write streaming is disabled + * NOTE:WS_THR_XX = b11 indicates write stream disable + */ + val = (uint64_t)read_cpuectlr_el1(); + assert((val & WS_THR_DISABLE_ALL) != WS_THR_DISABLE_ALL); +} + +/******************************************************************************* + * 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 system register settings */ + plat_verify_sysreg_settings(); + + /* + * SCF flush - Clean and invalidate caches before jumping to the + * non-secure world payload. + */ + mce_clean_and_invalidate_caches(); +} + +/******************************************************************************* + * Return pointer to the bpmp_ipc_data + ******************************************************************************/ +static struct bpmp_ipc_platform_data bpmp_ipc; +struct bpmp_ipc_platform_data *plat_get_bpmp_ipc_data(void) +{ + uint64_t rx_end_addr; + uint64_t sysram_end_addr; + + /* + * BPMP FW is not supported on QT/VSP platforms. Disable BPMP_IPC + * interface. + */ + if (tegra_platform_is_qt() || tegra_platform_is_vsp()) { + return NULL; + } + + bpmp_ipc.bpmp_ipc_tx_base = (((uint64_t)mmio_read_32(TEGRA_MC_BASE + + MC_CCPLEX_BPMP_IPC_BASE_HI) << 32) + | mmio_read_32(TEGRA_MC_BASE + MC_CCPLEX_BPMP_IPC_BASE_LO)); + bpmp_ipc.bpmp_ipc_rx_base = bpmp_ipc.bpmp_ipc_tx_base + TEGRA_BPMP_IPC_CH_MAP_SIZE; + bpmp_ipc.bpmp_ipc_map_size = TEGRA_BPMP_IPC_CH_MAP_SIZE; + + /* + * Disable BPMP_IPC interface if TX/RX shared memory is not present. + */ + if ((bpmp_ipc.bpmp_ipc_tx_base == 0U) || (bpmp_ipc.bpmp_ipc_rx_base == 0U) || + (bpmp_ipc.bpmp_ipc_map_size == 0U)) { + WARN("BPMP_IPC TX/RX memory is uninitialized\n"); + return NULL; + } + + /* + * Assert with the tx_base (or) rx end address is not with in sysram range. + */ + rx_end_addr = bpmp_ipc.bpmp_ipc_rx_base + TEGRA_BPMP_IPC_CH_MAP_SIZE; + sysram_end_addr = TEGRA_SYSRAM_BASE + TEGRA_SYSRAM_SIZE; + assert((bpmp_ipc.bpmp_ipc_tx_base >= TEGRA_SYSRAM_BASE) && (rx_end_addr < sysram_end_addr)); + + return &bpmp_ipc; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c new file mode 100644 index 0000000..0bb3779 --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +/* + * tegra_fake_system_suspend acts as a boolean variable controlling whether + * we are going to take fake system suspend code or normal system suspend code + * path. This variable is set inside the sip call handlers, when the kernel + * requests a SIP call to set the suspend debug flags. + */ +bool tegra234_fake_system_suspend = false; + +/******************************************************************************* + * Tegra234 SiP SMCs + ******************************************************************************/ +#define TEGRA_SIP_WRITE_PFG_REGS 0xC200FF01 +#define TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND 0xC2FFFE03 + +/******************************************************************************* + * 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; + + (void)x1; + (void)x4; + (void)cookie; + (void)flags; + + switch (smc_fid) { +#if RAS_EXTENSION && DEBUG + case TEGRA_SIP_WRITE_PFG_REGS: + ret = tegra234_ras_inject_fault(x1, x2, x3); + break; +#endif + case TEGRA_SIP_ENABLE_FAKE_SYSTEM_SUSPEND: + /* + * System suspend fake mode is set if we are on FPGA and we make + * a debug SIP call. This mode ensures that we exercise debug + * path instead of the regular code path to suit the pre-silicon + * platform needs. These include replacing the call to WFI by + * a warm reset request. + */ + if (tegra_platform_is_fpga() || tegra_platform_is_virt_dev_kit()) { + tegra234_fake_system_suspend = true; + } else { + /* + * Set to not support if we are not on FPGA or VDK. + */ + ret = -ENOTSUP; + } + + break; + default: + ret = -ENOTSUP; + break; + } + + return ret; +} diff --git a/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk new file mode 100644 index 0000000..78e309a --- /dev/null +++ b/arm-trusted-firmware/plat/nvidia/tegra/soc/t234/platform_t234.mk @@ -0,0 +1,106 @@ +# +# Copyright (c) 2021-2023, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# platform configs +ENABLE_CONSOLE_SPE := 1 +$(eval $(call add_define,ENABLE_CONSOLE_SPE)) + +ENABLE_STRICT_CHECKING_MODE := 0 +$(eval $(call add_define,ENABLE_STRICT_CHECKING_MODE)) + +USE_GPC_DMA := 0 +$(eval $(call add_define,USE_GPC_DMA)) + +RESET_TO_BL31 := 1 + +COLD_BOOT_SINGLE_CPU := 1 + +# platform settings +PLAT_BL31_BASE := 0x50000000 +$(eval $(call add_define,PLAT_BL31_BASE)) + +PLATFORM_CLUSTER_COUNT := 3 +$(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)) + +WORKAROUND_CVE_2017_5715 := 0 + +DYNAMIC_WORKAROUND_CVE_2018_3639 := 1 + +# Flag to apply erratum 2466780 workaround during reset. +ERRATA_A78_AE_2466780 := 1 + +# Flag to apply erratum 2743093 workaround during pwrdown sequence. +ERRATA_A78_AE_2743093 := 1 + +# Flag to apply erratum 2743229 workaround during reset. +ERRATA_A78_AE_2743229 := 1 + +CTX_INCLUDE_AARCH32_REGS := 0 + +HW_ASSISTED_COHERENCY := 1 + +# Keep RAS disabled until latest DSIM support is released +RAS_EXTENSION := 1 +HANDLE_EA_EL3_FIRST := 1 + +# Enable secure only access to GICT and GICP registers. +GICV3_RESTRICT_GICT_GICP_ACCESS := 1 +$(eval $(call add_define,GICV3_RESTRICT_GICT_GICP_ACCESS)) + +# Enable GIC600AE Fault Management Unit +GICV3_SUPPORT_GIC600AE_FMU := 1 + +# include common makefiles +include plat/nvidia/tegra/common/tegra_common.mk + +# platform files +PLAT_INCLUDES += -Iplat/nvidia/tegra/include/t234 \ + -I${SOC_DIR}/drivers/include + +BL31_SOURCES += ${TEGRA_GICv3_SOURCES} \ + lib/cpus/aarch64/cortex_a78_ae.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}/psc/psc_mailbox.c \ + ${SOC_DIR}/drivers/mce/mce.c \ + ${SOC_DIR}/drivers/mce/ari.c \ + ${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 + +ifeq (${ENABLE_CONSOLE_SPE}, 1) +BL31_SOURCES += ${TEGRA_DRIVERS}/spe/shared_console.S +else +BL31_SOURCES += drivers/ti/uart/aarch64/16550_console.S +endif + +# Pointer Authentication sources +ifeq (${ENABLE_PAUTH},1) +CTX_INCLUDE_PAUTH_REGS := 1 +BL31_SOURCES += plat/nvidia/tegra/common/tegra_pauth.c \ + lib/extensions/pauth/pauth_helpers.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 diff --git a/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S b/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S new file mode 100644 index 0000000..cc91540 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S @@ -0,0 +1,558 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S b/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S new file mode 100644 index 0000000..311dce1 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S @@ -0,0 +1,220 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include + + + .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/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h new file mode 100644 index 0000000..65aef14 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h new file mode 100644 index 0000000..9856f70 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h new file mode 100644 index 0000000..bbd6041 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_fip_io.mk new file mode 100644 index 0000000..7d673ba --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c new file mode 100644 index 0000000..fc3c4a4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#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/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h new file mode 100644 index 0000000..6df3902 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse.mk new file mode 100644 index 0000000..d8f5ae6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h new file mode 100644 index 0000000..e8775d0 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c b/arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c new file mode 100644 index 0000000..017ffcf --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fuse_io.h" +#include +#include +#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/arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk b/arm-trusted-firmware/plat/nxp/common/img_loadr/img_loadr.mk new file mode 100644 index 0000000..f64b1fa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c new file mode 100644 index 0000000..c185c36 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c @@ -0,0 +1,79 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include + +#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 + 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); +#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/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h b/arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h new file mode 100644 index 0000000..6f9de32 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h new file mode 100644 index 0000000..6296aef --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h new file mode 100644 index 0000000..928ac05 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h new file mode 100644 index 0000000..8d64f04 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h new file mode 100644 index 0000000..8e68367 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h new file mode 100644 index 0000000..0a4228b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h b/arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h new file mode 100644 index 0000000..1edd28d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h b/arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h new file mode 100644 index 0000000..43320bb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk b/arm-trusted-firmware/plat/nxp/common/nv_storage/nv_storage.mk new file mode 100644 index 0000000..dddba5f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c new file mode 100644 index 0000000..7ec4fdb --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c @@ -0,0 +1,120 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#ifndef NXP_COINED_BB +#include +#include +#include +#endif +#include +#ifdef NXP_COINED_BB +#include +#else +#include +#endif + +#include + +/*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/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h b/arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h new file mode 100644 index 0000000..1f5264a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S b/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S new file mode 100644 index 0000000..ec53341 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S @@ -0,0 +1,71 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +.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/arm-trusted-firmware/plat/nxp/common/ocram/ocram.h b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.h new file mode 100644 index 0000000..479de61 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk b/arm-trusted-firmware/plat/nxp/common/ocram/ocram.mk new file mode 100644 index 0000000..c77bd4a --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_build_macros.mk new file mode 100644 index 0000000..bba5e36 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/plat_common_def.mk new file mode 100644 index 0000000..86dacf8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk b/arm-trusted-firmware/plat/nxp/common/plat_make_helper/soc_common_def.mk new file mode 100644 index 0000000..52f2867 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S b/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S new file mode 100644 index 0000000..ec69aea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S @@ -0,0 +1,1155 @@ + +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +#include +#include + + +#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/arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h b/arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h new file mode 100644 index 0000000..7fc48fb --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + /* 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/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c b/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c new file mode 100644 index 0000000..9281e97 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c @@ -0,0 +1,475 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#ifdef NXP_WARM_BOOT +#include +#endif + +#include + +#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/arm-trusted-firmware/plat/nxp/common/psci/psci.mk b/arm-trusted-firmware/plat/nxp/common/psci/psci.mk new file mode 100644 index 0000000..a2791c2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c new file mode 100644 index 0000000..7463d47 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#ifdef CSF_HEADER_PREPENDED +#include +#endif +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nxp/common/setup/common.mk b/arm-trusted-firmware/plat/nxp/common/setup/common.mk new file mode 100644 index 0000000..1fcf1d0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/setup/core.mk b/arm-trusted-firmware/plat/nxp/common/setup/core.mk new file mode 100644 index 0000000..82ce30e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h b/arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h new file mode 100644 index 0000000..dd20d43 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h b/arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h new file mode 100644 index 0000000..7dbddfb --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h b/arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h new file mode 100644 index 0000000..2a7771b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + + +#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/arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h new file mode 100644 index 0000000..e13f45c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +#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/arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S b/arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S new file mode 100644 index 0000000..69a3b08 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c new file mode 100644 index 0000000..a4cbaef --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c @@ -0,0 +1,303 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#include +#include +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include +#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/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c new file mode 100644 index 0000000..bd0ab4f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c @@ -0,0 +1,212 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#ifdef LS_EL3_INTERRUPT_HANDLER +#include +#endif +#include +#include + +/* + * 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/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c new file mode 100644 index 0000000..e7ae060 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_common.c @@ -0,0 +1,264 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 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_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); + + /* 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_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); + } + +#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_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); + } +#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/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c new file mode 100644 index 0000000..845cd15 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_err.c @@ -0,0 +1,55 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include + +#if TRUSTED_BOARD_BOOT +#include +#include +#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/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c new file mode 100644 index 0000000..259ab31 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c @@ -0,0 +1,33 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c new file mode 100644 index 0000000..a81cb2b --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c @@ -0,0 +1,66 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c new file mode 100644 index 0000000..7f01e72 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c @@ -0,0 +1,556 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef FLEXSPI_NOR_BOOT +#include +#endif +#if defined(NAND_BOOT) +#include +#endif +#if defined(NOR_BOOT) +#include +#endif +#if defined(QSPI_BOOT) +#include +#endif +#if defined(SD_BOOT) || defined(EMMC_BOOT) +#include +#endif +#include + +#ifdef CONFIG_DDR_FIP_IMAGE +#include +#endif +#ifdef POLICY_FUSE_PROVISION +#include +#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/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c b/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c new file mode 100644 index 0000000..ab78f88 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c @@ -0,0 +1,22 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +#include + +#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/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S b/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S new file mode 100644 index 0000000..6a47cbf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S @@ -0,0 +1,152 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +.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/arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h b/arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h new file mode 100644 index 0000000..d9e61e9 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c b/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c new file mode 100644 index 0000000..1c8668e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c @@ -0,0 +1,194 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk b/arm-trusted-firmware/plat/nxp/common/sip_svc/sipsvc.mk new file mode 100644 index 0000000..c3a57de --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c new file mode 100644 index 0000000..55ef604 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c @@ -0,0 +1,59 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h new file mode 100644 index 0000000..ab67995 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata.mk new file mode 100644 index 0000000..3deef3d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c new file mode 100644 index 0000000..e8c0f64 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c @@ -0,0 +1,42 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c new file mode 100644 index 0000000..d31a4d7 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c @@ -0,0 +1,14 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +void erratum_a009660(void) +{ + mmio_write_32(NXP_SCFG_ADDR + 0x20c, 0x63b20042); +} diff --git a/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c new file mode 100644 index 0000000..3dcbdc8 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c @@ -0,0 +1,26 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include + +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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c new file mode 100644 index 0000000..ba4f71f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c @@ -0,0 +1,201 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +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/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h b/arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h new file mode 100644 index 0000000..f6741e2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c b/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c new file mode 100644 index 0000000..8f38f3e --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c @@ -0,0 +1,81 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + * + */ + +#include + +#include +#include +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S b/arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S new file mode 100644 index 0000000..8e084d1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk b/arm-trusted-firmware/plat/nxp/common/tbbr/tbbr.mk new file mode 100644 index 0000000..7edcfbc --- /dev/null +++ b/arm-trusted-firmware/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 genrsa 2048 > $@ 2>/dev/null; \ + fi + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + 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/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c b/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c new file mode 100644 index 0000000..ec87674 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c @@ -0,0 +1,105 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c new file mode 100644 index 0000000..966a73c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c @@ -0,0 +1,121 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#ifndef NXP_COINED_BB +#include +#include +#include +#endif +#include +#include +#ifdef NXP_COINED_BB +#include +#endif + +#include +#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/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h b/arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h new file mode 100644 index 0000000..e0c39c5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk b/arm-trusted-firmware/plat/nxp/common/warm_reset/warm_reset.mk new file mode 100644 index 0000000..236004f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S new file mode 100644 index 0000000..404c39e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include +#include + + .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/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S new file mode 100644 index 0000000..ec67529 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +.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/arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h new file mode 100644 index 0000000..b1d044a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* + * 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/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c new file mode 100644 index 0000000..d82be51 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c @@ -0,0 +1,185 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include + +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h new file mode 100644 index 0000000..63c0219 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + + +#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/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.mk new file mode 100644 index 0000000..c455000 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h new file mode 100644 index 0000000..bbad293 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h new file mode 100644 index 0000000..67a8b45 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c new file mode 100644 index 0000000..2fb353f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c @@ -0,0 +1,432 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#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/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def new file mode 100644 index 0000000..c23c1bb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.mk new file mode 100644 index 0000000..92d8e98 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S new file mode 100644 index 0000000..a1baf79 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S @@ -0,0 +1,1637 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S new file mode 100644 index 0000000..bc88886 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S @@ -0,0 +1,70 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + + .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/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h new file mode 100644 index 0000000..423c454 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h new file mode 100644 index 0000000..e018102 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c new file mode 100644 index 0000000..2231c18 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c @@ -0,0 +1,159 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#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: MT40A512M8HX-093E */ +struct dimm_params ddr_raw_timing = { + .n_ranks = U(1), + .rank_density = ULL(2147483648), + .capacity = ULL(2147483648), + .primary_sdram_width = U(32), + .n_row_addr = U(15), + .n_col_addr = U(10), + .bank_group_bits = U(2), + .burst_lengths_bitmask = U(0x0c), + .tckmin_x_ps = 938, + .tckmax_ps = 1500, + .caslat_x = U(0x000DFA00), + .taa_ps = 13500, + .trcd_ps = 13500, + .trp_ps = 13500, + .tras_ps = 33000, + .trc_ps = 46500, + .twr_ps = 15000, + .trfc1_ps = 260000, + .trfc2_ps = 160000, + .trfc4_ps = 110000, + .tfaw_ps = 21000, + .trrds_ps = 3700, + .trrdl_ps = 5300, + .tccdl_ps = 5355, + .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/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h new file mode 100644 index 0000000..249f457 --- /dev/null +++ b/arm-trusted-firmware/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 +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c new file mode 100644 index 0000000..65d508c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.mk new file mode 100644 index 0000000..5d23356 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h new file mode 100644 index 0000000..4721a32 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h new file mode 100644 index 0000000..843b5e2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c new file mode 100644 index 0000000..7badf8c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c @@ -0,0 +1,435 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +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/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def new file mode 100644 index 0000000..b174bd6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.mk new file mode 100644 index 0000000..b6ce14e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S new file mode 100644 index 0000000..daa0542 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S @@ -0,0 +1,937 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S new file mode 100644 index 0000000..d2a48ea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S @@ -0,0 +1,92 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + + .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/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h new file mode 100644 index 0000000..25c1964 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h new file mode 100644 index 0000000..67810c3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c new file mode 100644 index 0000000..3d561c7 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c @@ -0,0 +1,177 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h new file mode 100644 index 0000000..5134a00 --- /dev/null +++ b/arm-trusted-firmware/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 +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.mk new file mode 100644 index 0000000..1f7fad6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c new file mode 100644 index 0000000..6d1707c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c @@ -0,0 +1,90 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h new file mode 100644 index 0000000..aa69a66 --- /dev/null +++ b/arm-trusted-firmware/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 +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.mk new file mode 100644 index 0000000..9600b93 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c new file mode 100644 index 0000000..b9940cf --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c @@ -0,0 +1,267 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h new file mode 100644 index 0000000..b5e66ae --- /dev/null +++ b/arm-trusted-firmware/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 +/* + * Required without TBBR. + * To include the defines for DDR PHY Images. + */ +#include + +#include "policy.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c new file mode 100644 index 0000000..cef920f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2020-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.mk new file mode 100644 index 0000000..32e6db5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h new file mode 100644 index 0000000..7f98bb1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h new file mode 100644 index 0000000..c6c325f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c new file mode 100644 index 0000000..d17e672 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c @@ -0,0 +1,395 @@ +/* + * Copyright 2018-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +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/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def new file mode 100644 index 0000000..e6b37c0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.mk new file mode 100644 index 0000000..8207dcd --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S new file mode 100644 index 0000000..0c6b7ea --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S @@ -0,0 +1,1817 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +.section .text, "ax" + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S new file mode 100644 index 0000000..890cf81 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + + .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/arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h new file mode 100644 index 0000000..eb36c2e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c new file mode 100644 index 0000000..b7397ba --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c @@ -0,0 +1,84 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h new file mode 100644 index 0000000..ebd3a26 --- /dev/null +++ b/arm-trusted-firmware/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 +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.mk new file mode 100644 index 0000000..97ccf26 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h new file mode 100644 index 0000000..0eaafae --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c new file mode 100644 index 0000000..c88583f --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c @@ -0,0 +1,86 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h new file mode 100644 index 0000000..a6b14fe --- /dev/null +++ b/arm-trusted-firmware/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 +/* + * Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c new file mode 100644 index 0000000..8b3eada --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c @@ -0,0 +1,28 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.mk new file mode 100644 index 0000000..6884faf --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h new file mode 100644 index 0000000..7daf1c0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h new file mode 100644 index 0000000..af206f9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c new file mode 100644 index 0000000..5f9f313 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c @@ -0,0 +1,397 @@ +/* + * Copyright 2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#ifdef CONFIG_OCRAM_ECC_EN +#include +#endif +#include +#include +#include + +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/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def new file mode 100644 index 0000000..25d0847 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.mk new file mode 100644 index 0000000..83ac9d0 --- /dev/null +++ b/arm-trusted-firmware/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__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/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S new file mode 100644 index 0000000..cc679f2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include +#include + +.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/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S new file mode 100644 index 0000000..c364dec --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S @@ -0,0 +1,77 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include + +#include + +.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/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S b/arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S new file mode 100644 index 0000000..9dec3f2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#ifndef NXP_COINED_BB +#include +#include +#endif +#include +#ifdef NXP_COINED_BB +#include +#endif + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_fip.mk new file mode 100644 index 0000000..f14a9e8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_sb.mk new file mode 100644 index 0000000..c11651e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/ddr_tbbr.mk new file mode 100644 index 0000000..deb475b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h new file mode 100644 index 0000000..7cc4a03 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c new file mode 100644 index 0000000..d44733c --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c @@ -0,0 +1,355 @@ +/* + * Copyright 2018-2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h new file mode 100644 index 0000000..f480f92 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.mk new file mode 100644 index 0000000..226b22b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h new file mode 100644 index 0000000..05d23e2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c new file mode 100644 index 0000000..8669b1d --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c @@ -0,0 +1,212 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h new file mode 100644 index 0000000..02f51e7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c new file mode 100644 index 0000000..b00adb5 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.mk new file mode 100644 index 0000000..ffb5fad --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h new file mode 100644 index 0000000..6660998 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h new file mode 100644 index 0000000..19ad6db --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c new file mode 100644 index 0000000..73bcc93 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c @@ -0,0 +1,354 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#include "plat_common.h" +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h new file mode 100644 index 0000000..de2d244 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +/* Required without TBBR. + * To include the defines for DDR PHY + * Images. + */ +#include + +#include +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c new file mode 100644 index 0000000..7622cf0 --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c @@ -0,0 +1,29 @@ +/* + * Copyright 2020 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.mk new file mode 100644 index 0000000..2b4712c --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h new file mode 100644 index 0000000..5fa774e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h b/arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h new file mode 100644 index 0000000..1095f38 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c new file mode 100644 index 0000000..2209fda --- /dev/null +++ b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c @@ -0,0 +1,509 @@ +/* + * Copyright 2018-2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef I2C_INIT +#include +#endif +#include +#include +#include +#ifdef POLICY_FUSE_PROVISION +#include +#endif +#if TRUSTED_BOARD_BOOT +#include +#endif +#include +#include +#include +#include +#include +#if defined(NXP_SFP_ENABLED) +#include +#endif + +#include +#include +#include "plat_common.h" +#ifdef NXP_NV_SW_MAINT_LAST_EXEC_DATA +#include +#endif +#ifdef NXP_WARM_BOOT +#include +#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/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def new file mode 100644 index 0000000..81d6744 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk b/arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.mk new file mode 100644 index 0000000..75a3af2 --- /dev/null +++ b/arm-trusted-firmware/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__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/arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S b/arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S new file mode 100644 index 0000000..5e346d5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..08b2817 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/qemu/common/include/plat_macros.S b/arm-trusted-firmware/plat/qemu/common/include/plat_macros.S new file mode 100644 index 0000000..b6cdb07 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c new file mode 100644 index 0000000..67f3327 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c new file mode 100644 index 0000000..5af3a22 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c new file mode 100644 index 0000000..2c0da15 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c b/arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c new file mode 100644 index 0000000..4f60eb1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/qemu_common.c b/arm-trusted-firmware/plat/qemu/common/qemu_common.c new file mode 100644 index 0000000..47ec791 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_common.c @@ -0,0 +1,163 @@ + +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#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 + + diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_console.c b/arm-trusted-firmware/plat/qemu/common/qemu_console.c new file mode 100644 index 0000000..1f00f8a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c b/arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c new file mode 100644 index 0000000..2c358ea --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c b/arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c new file mode 100644 index 0000000..0d35446 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +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/arm-trusted-firmware/plat/qemu/common/qemu_image_load.c b/arm-trusted-firmware/plat/qemu/common/qemu_image_load.c new file mode 100644 index 0000000..9970d1d --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c b/arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c new file mode 100644 index 0000000..1107e44 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/qemu/common/qemu_pm.c b/arm-trusted-firmware/plat/qemu/common/qemu_pm.c new file mode 100644 index 0000000..c2b5091 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/qemu_private.h b/arm-trusted-firmware/plat/qemu/common/qemu_private.h new file mode 100644 index 0000000..4dc62f5 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_private.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2015-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef QEMU_PRIVATE_H +#define QEMU_PRIVATE_H + +#include + +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); + +#endif /* QEMU_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S b/arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S new file mode 100644 index 0000000..5d1b83f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qemu/common/qemu_spm.c b/arm-trusted-firmware/plat/qemu/common/qemu_spm.c new file mode 100644 index 0000000..c66f47e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c b/arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c new file mode 100644 index 0000000..fd46e26 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +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/arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c b/arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c new file mode 100644 index 0000000..15ce3d6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c b/arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c new file mode 100644 index 0000000..1ef7e43 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/common/qemu_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 + +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; +} + +int plat_get_mbedtls_heap(void **heap_addr, size_t *heap_size) +{ + return get_mbedtls_heap_helper(heap_addr, heap_size); +} diff --git a/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min-qemu.mk new file mode 100644 index 0000000..e93a0c2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c b/arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c new file mode 100644 index 0000000..7ec657b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/qemu/common/topology.c b/arm-trusted-firmware/plat/qemu/common/topology.c new file mode 100644 index 0000000..6352706 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +#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/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h b/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h new file mode 100644 index 0000000..c02eff9 --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h @@ -0,0 +1,273 @@ +/* + * 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 +#include +#include +#include + +/* 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 0x00060000 + +#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 - 0x20000) +#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) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qemu/qemu/platform.mk b/arm-trusted-firmware/plat/qemu/qemu/platform.mk new file mode 100644 index 0000000..a8f978a --- /dev/null +++ b/arm-trusted-firmware/plat/qemu/qemu/platform.mk @@ -0,0 +1,232 @@ +# +# Copyright (c) 2013-2021, 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) + + 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_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 + + 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 genrsa 2048 > $@ 2>/dev/null + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +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/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)) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 diff --git a/arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h b/arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h new file mode 100644 index 0000000..d971ebe --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* 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/arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk b/arm-trusted-firmware/plat/qemu/qemu_sbsa/platform.mk new file mode 100644 index 0000000..5a6b1e1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c new file mode 100644 index 0000000..8d1e1d4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h new file mode 100644 index 0000000..a9f4601 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c b/arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c new file mode 100644 index 0000000..bd8d16b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#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/arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S b/arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S new file mode 100644 index 0000000..2e292fb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +.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/arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h b/arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h new file mode 100644 index 0000000..c95e4c0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h b/arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h new file mode 100644 index 0000000..3316f7b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h b/arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h new file mode 100644 index 0000000..59bde86 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h b/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h new file mode 100644 index 0000000..4d9d320 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/inc/qti_plat.h @@ -0,0 +1,56 @@ +/* + * 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 + +#include +#include +#include +#include + +/* + * 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, + uintptr_t coh_start, uintptr_t coh_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); + +#endif /* QTI_PLAT_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_rng.h b/arm-trusted-firmware/plat/qti/common/inc/qti_rng.h new file mode 100644 index 0000000..62c31f3 --- /dev/null +++ b/arm-trusted-firmware/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 + +int qti_rng_get_data(uint8_t *out, uint32_t out_len); + +#endif /* QTI_RNG_H */ diff --git a/arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h b/arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h new file mode 100644 index 0000000..c5a65d6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h b/arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h new file mode 100644 index 0000000..362f740 --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S new file mode 100644 index 0000000..c1ea7b3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S @@ -0,0 +1,88 @@ +/* + * 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 +#include +#include +#include +#include + +#include + + .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 + + /* Serialize CPUSS boot setup. Multi core enter simultaneously. */ + ldr x0, =g_qti_cpuss_boot_lock + bl spin_lock + + /* pass cold boot status. */ + ldr w0, g_qti_bl31_cold_booted + /* Execuete CPUSS boot set up on every core. */ + bl qtiseclib_cpuss_reset_asm + + ldr x0, =g_qti_cpuss_boot_lock + bl spin_unlock + + ret x18 +endfunc plat_reset_handler diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S new file mode 100644 index 0000000..a1b40c8 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S @@ -0,0 +1,83 @@ +/* + * 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 +#include +#include + +#include +#include + + .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 + + ret x19 + +endfunc qti_kryo4_gold_reset_func + +/* ---------------------------------------------------- + * The CPU Ops core power down function for Kryo-3 Gold + * ---------------------------------------------------- + */ +func qti_kryo4_gold_core_pwr_dwn + ret +endfunc qti_kryo4_gold_core_pwr_dwn + +/* ------------------------------------------------------- + * 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 qti_kryo4_gold, QTI_KRYO4_GOLD_MIDR, \ + qti_kryo4_gold_reset_func, \ + qti_kryo4_gold_core_pwr_dwn, \ + qti_kryo4_gold_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S new file mode 100644 index 0000000..183eeb0 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S @@ -0,0 +1,79 @@ +/* + * 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 +#include +#include + +#include +#include + + .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 + + ret x19 + +endfunc qti_kryo4_silver_reset_func + +/* ------------------------------------------------------ + * The CPU Ops core power down function for Kryo-3 Silver + * ------------------------------------------------------ + */ +func qti_kryo4_silver_core_pwr_dwn + ret +endfunc qti_kryo4_silver_core_pwr_dwn + +/* --------------------------------------------------------- + * 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, \ + qti_kryo4_silver_core_pwr_dwn, \ + qti_kryo4_silver_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S new file mode 100644 index 0000000..db1a304 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S @@ -0,0 +1,83 @@ +/* + * 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 +#include +#include + +#include +#include + + .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 + + ret x19 + +endfunc qti_kryo6_gold_reset_func + +/* ---------------------------------------------------- + * The CPU Ops core power down function for Kryo-3 Gold + * ---------------------------------------------------- + */ +func qti_kryo6_gold_core_pwr_dwn + ret +endfunc qti_kryo6_gold_core_pwr_dwn + +/* ------------------------------------------------------- + * 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, \ + qti_kryo6_gold_core_pwr_dwn, \ + qti_kryo6_gold_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S new file mode 100644 index 0000000..2d189f2 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S @@ -0,0 +1,79 @@ +/* + * 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 +#include +#include + +#include +#include + + .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 + + ret x19 + +endfunc qti_kryo6_silver_reset_func + +/* ------------------------------------------------------ + * The CPU Ops core power down function for Kryo-3 Silver + * ------------------------------------------------------ + */ +func qti_kryo6_silver_core_pwr_dwn + ret +endfunc qti_kryo6_silver_core_pwr_dwn + +/* --------------------------------------------------------- + * 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, \ + qti_kryo6_silver_core_pwr_dwn, \ + qti_kryo6_silver_cluster_pwr_dwn diff --git a/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S b/arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S new file mode 100644 index 0000000..2eb33d9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c b/arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c new file mode 100644 index 0000000..208345c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c b/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c new file mode 100644 index 0000000..b2bc543 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c @@ -0,0 +1,155 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +/* + * 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; + +/* + * Lock variable to serialize cpuss reset execution. + */ +spinlock_t g_qti_cpuss_boot_lock __attribute__ ((section("tzfw_coherent_mem"), + aligned(CACHE_WRITEBACK_GRANULE))) = {0x0}; + +/* + * 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 __attribute__ ((section("tzfw_coherent_mem"))) = 0x0; + +/******************************************************************************* + * 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(BL_CODE_BASE, + BL_COHERENT_RAM_END - BL_CODE_BASE, + BL_CODE_BASE, + BL_CODE_END, + BL_RO_DATA_BASE, + BL_RO_DATA_END, + BL_COHERENT_RAM_BASE, BL_COHERENT_RAM_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/arm-trusted-firmware/plat/qti/common/src/qti_common.c b/arm-trusted-firmware/plat/qti/common/src/qti_common.c new file mode 100644 index 0000000..da0eaec --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_common.c @@ -0,0 +1,194 @@ +/* + * 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 +#include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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, + uintptr_t coh_start, uintptr_t coh_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); + + /* 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); + + /* 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) +{ + uint32_t soc_version = (QTI_SOC_VERSION & QTI_SOC_VERSION_MASK); + uint32_t jep106az_code = (JEDEC_QTI_BKID << QTI_SOC_CONTINUATION_SHIFT) + | (JEDEC_QTI_MFID << QTI_SOC_IDENTIFICATION_SHIFT); + 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/arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c b/arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c new file mode 100644 index 0000000..f00267a --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c b/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c new file mode 100644 index 0000000..89cd7b5 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c @@ -0,0 +1,65 @@ +/* + * 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 +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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); + + /* 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/arm-trusted-firmware/plat/qti/common/src/qti_pm.c b/arm-trusted-firmware/plat/qti/common/src/qti_pm.c new file mode 100644 index 0000000..5f1b7aa --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/qti/common/src/qti_rng.c b/arm-trusted-firmware/plat/qti/common/src/qti_rng.c new file mode 100644 index 0000000..f63f3b8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +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/arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c b/arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c new file mode 100644 index 0000000..572830f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/qti/common/src/qti_syscall.c b/arm-trusted-firmware/plat/qti/common/src/qti_syscall.c new file mode 100644 index 0000000..d8e5be9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* + * 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/arm-trusted-firmware/plat/qti/common/src/qti_topology.c b/arm-trusted-firmware/plat/qti/common/src/qti_topology.c new file mode 100644 index 0000000..bf2e3f3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/qti/common/src/spmi_arb.c b/arm-trusted-firmware/plat/qti/common/src/spmi_arb.c new file mode 100644 index 0000000..4213ed1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#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/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S b/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S new file mode 100644 index 0000000..dad9968 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#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/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S b/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S new file mode 100644 index 0000000..c69c193 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S @@ -0,0 +1,154 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * Based on aarch64/skeleton_console.S: + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +/* 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/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h b/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h new file mode 100644 index 0000000..406ae6b --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * 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/arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S b/arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S new file mode 100644 index 0000000..552add2 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + + /* --------------------------------------------- + * 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/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h b/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h new file mode 100644 index 0000000..bfade70 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include + +/* + * 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 to avoid a failing assert(). + */ +#define GICD_PIDR2_GICV2 U(0xFD8) + +#endif /* PLATFORM_DEF_H */ diff --git a/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h b/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h new file mode 100644 index 0000000..0f09ba8 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * 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/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c new file mode 100644 index 0000000..638cd09 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "msm8916_gicv2.h" +#include +#include +#include + +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/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c new file mode 100644 index 0000000..b3f51f6 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c @@ -0,0 +1,66 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c new file mode 100644 index 0000000..25a6628 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include "msm8916_gicv2.h" +#include + +#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/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h new file mode 100644 index 0000000..99db0d3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * 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/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c new file mode 100644 index 0000000..6891e38 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h new file mode 100644 index 0000000..5473bfa --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2021, Stephan Gerhold + * + * 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/arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c b/arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c new file mode 100644 index 0000000..4d0ed8f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/qti/msm8916/platform.mk b/arm-trusted-firmware/plat/qti/msm8916/platform.mk new file mode 100644 index 0000000..e516cea --- /dev/null +++ b/arm-trusted-firmware/plat/qti/msm8916/platform.mk @@ -0,0 +1,62 @@ +# +# Copyright (c) 2021, Stephan Gerhold +# +# 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/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h new file mode 100644 index 0000000..deef41c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h new file mode 100644 index 0000000..2afefe1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h new file mode 100644 index 0000000..babed1b --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +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/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h new file mode 100644 index 0000000..3ecee20 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h b/arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h new file mode 100644 index 0000000..b3d309f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c new file mode 100644 index 0000000..c4cd259 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c new file mode 100644 index 0000000..9c93d51 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* + * 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) +{ +} + +/* + * 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/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h b/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h new file mode 100644 index 0000000..e3dc811 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h @@ -0,0 +1,199 @@ +/* + * 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 + +#include +#include + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* + * 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 U(0x7180) +#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/arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h new file mode 100644 index 0000000..f50234f --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h b/arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h new file mode 100644 index 0000000..3de636d --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/qti/sc7180/platform.mk b/arm-trusted-firmware/plat/qti/sc7180/platform.mk new file mode 100644 index 0000000..141e2c3 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7180/platform.mk @@ -0,0 +1,119 @@ +# +# 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 := 1 +WARMBOOT_ENABLE_DCACHE_EARLY := 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 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} \ + +BL31_SOURCES += ${QTI_BL31_SOURCES} \ + ${PSCI_SOURCES} \ + ${GIC_SOURCES} \ + ${TIMER_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/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h b/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h new file mode 100644 index 0000000..da7eddc --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h @@ -0,0 +1,199 @@ +/* + * 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 + +#include +#include + +/*----------------------------------------------------------------------------*/ + +/*----------------------------------------------------------------------------*/ +/* + * 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 U(0x7280) +#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/arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h new file mode 100644 index 0000000..0f41fd6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h b/arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h new file mode 100644 index 0000000..058c5b5 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/qti/sc7280/platform.mk b/arm-trusted-firmware/plat/qti/sc7280/platform.mk new file mode 100644 index 0000000..bc2c221 --- /dev/null +++ b/arm-trusted-firmware/plat/qti/sc7280/platform.mk @@ -0,0 +1,119 @@ +# +# 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 := 1 +WARMBOOT_ENABLE_DCACHE_EARLY := 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} \ + +BL31_SOURCES += ${QTI_BL31_SOURCES} \ + ${PSCI_SOURCES} \ + ${GIC_SOURCES} \ + ${TIMER_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/arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..21c3bed --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c new file mode 100644 index 0000000..b0a88cb --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c b/arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c new file mode 100644 index 0000000..a545f71 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c b/arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c new file mode 100644 index 0000000..d9a4b8e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c b/arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c new file mode 100644 index 0000000..bf2706d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c b/arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c new file mode 100644 index 0000000..2f8b001 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c b/arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c new file mode 100644 index 0000000..60960d4 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/common.mk b/arm-trusted-firmware/plat/renesas/common/common.mk new file mode 100644 index 0000000..aef0ad1 --- /dev/null +++ b/arm-trusted-firmware/plat/renesas/common/common.mk @@ -0,0 +1,144 @@ +# +# 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 := 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 +include drivers/auth/mbedtls/mbedtls_crypto.mk +PLAT_BL_COMMON_SOURCES += ${XLAT_TABLES_LIB_SRCS} diff --git a/arm-trusted-firmware/plat/renesas/common/include/plat.ld.S b/arm-trusted-firmware/plat/renesas/common/include/plat.ld.S new file mode 100644 index 0000000..7aef324 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/renesas/common/include/plat_macros.S b/arm-trusted-firmware/plat/renesas/common/include/plat_macros.S new file mode 100644 index 0000000..927cd39 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/include/platform_def.h b/arm-trusted-firmware/plat/renesas/common/include/platform_def.h new file mode 100644 index 0000000..ab071ec --- /dev/null +++ b/arm-trusted-firmware/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 +#endif + +#include + +#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/arm-trusted-firmware/plat/renesas/common/include/rcar_def.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_def.h new file mode 100644 index 0000000..2cd26ed --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/renesas/common/include/rcar_private.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_private.h new file mode 100644 index 0000000..36f4ca5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +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/arm-trusted-firmware/plat/renesas/common/include/rcar_version.h b/arm-trusted-firmware/plat/renesas/common/include/rcar_version.h new file mode 100644 index 0000000..5a0ca31 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h new file mode 100644 index 0000000..36cd58b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h new file mode 100644 index 0000000..5d2bb9e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h b/arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h new file mode 100644 index 0000000..5f49e52 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/renesas/common/plat_image_load.c b/arm-trusted-firmware/plat/renesas/common/plat_image_load.c new file mode 100644 index 0000000..9d814a6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +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/arm-trusted-firmware/plat/renesas/common/plat_pm.c b/arm-trusted-firmware/plat/renesas/common/plat_pm.c new file mode 100644 index 0000000..9810596 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/renesas/common/plat_storage.c b/arm-trusted-firmware/plat/renesas/common/plat_storage.c new file mode 100644 index 0000000..6524561 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include "io_common.h" +#include "io_memdrv.h" +#include "io_emmcdrv.h" +#include "io_private.h" +#include "io_rcar.h" +#include + +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/arm-trusted-firmware/plat/renesas/common/plat_topology.c b/arm-trusted-firmware/plat/renesas/common/plat_topology.c new file mode 100644 index 0000000..0d5880d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/renesas/common/rcar_common.c b/arm-trusted-firmware/plat/renesas/common/rcar_common.c new file mode 100644 index 0000000..df4c30c --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include + +#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 + +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/arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c b/arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c new file mode 100644 index 0000000..bbfa169 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if RCAR_GEN3_BL33_GZIP == 1 +#include +#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(¶ms->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(¶ms->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, "rpc@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/arm-trusted-firmware/plat/renesas/rcar/platform.mk b/arm-trusted-firmware/plat/renesas/rcar/platform.mk new file mode 100644 index 0000000..670d499 --- /dev/null +++ b/arm-trusted-firmware/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= 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/arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c b/arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c new file mode 100644 index 0000000..e9dbd20 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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(¶ms->bl32_ep_info, &bl_mem_params->ep_info, + sizeof(entry_point_info_t)); + break; + case BL33_IMAGE_ID: + memcpy(¶ms->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/arm-trusted-firmware/plat/renesas/rzg/platform.mk b/arm-trusted-firmware/plat/renesas/rzg/platform.mk new file mode 100644 index 0000000..f37d7d0 --- /dev/null +++ b/arm-trusted-firmware/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= 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/arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S b/arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S new file mode 100644 index 0000000..475c297 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c b/arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c new file mode 100644 index 0000000..9030951 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S b/arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S new file mode 100644 index 0000000..a05ae54 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..4af052b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c b/arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c new file mode 100644 index 0000000..81e8520 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S b/arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S new file mode 100644 index 0000000..d91ee0e --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c b/arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c new file mode 100644 index 0000000..98ef415 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c new file mode 100644 index 0000000..e89fe1e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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 + * ----------------------------------------------------------------------------- + * | | | | + * ----------------------------------------------------------------------------- + * | 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/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h b/arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h new file mode 100644 index 0000000..25c93a1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h b/arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h new file mode 100644 index 0000000..5359f73 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S b/arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S new file mode 100644 index 0000000..691beeb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +.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/arm-trusted-firmware/plat/rockchip/common/include/plat_params.h b/arm-trusted-firmware/plat/rockchip/common/include/plat_params.h new file mode 100644 index 0000000..95b850f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#endif /* PLAT_PARAMS_H */ diff --git a/arm-trusted-firmware/plat/rockchip/common/include/plat_private.h b/arm-trusted-firmware/plat/rockchip/common/include/plat_private.h new file mode 100644 index 0000000..990d106 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h b/arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h new file mode 100644 index 0000000..340d653 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/common/params_setup.c b/arm-trusted-firmware/plat/rockchip/common/params_setup.c new file mode 100644 index 0000000..aec53ee --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 uint8_t fdt_buffer[FDT_BUFFER_SIZE]; + +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 {{{...}}} + * 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/arm-trusted-firmware/plat/rockchip/common/plat_pm.c b/arm-trusted-firmware/plat/rockchip/common/plat_pm.c new file mode 100644 index 0000000..6926887 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/rockchip/common/plat_topology.c b/arm-trusted-firmware/plat/rockchip/common/plat_topology.c new file mode 100644 index 0000000..4987eeb --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S new file mode 100644 index 0000000..6cea2ea --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h b/arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h new file mode 100644 index 0000000..34af29a --- /dev/null +++ b/arm-trusted-firmware/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 void *sys_sleep_flag_sram; + +#endif /* __ASSEMBLER__ */ + +#endif diff --git a/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c new file mode 100644 index 0000000..8db2b30 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c new file mode 100644 index 0000000..edae2ef --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +/****************************************************************************** + * 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/arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c new file mode 100644 index 0000000..27ef042 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c b/arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c new file mode 100644 index 0000000..1898977 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c b/arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c new file mode 100644 index 0000000..0237b16 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..a757621 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +.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/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c new file mode 100644 index 0000000..5f4e64f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h new file mode 100644 index 0000000..416d1c1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c new file mode 100644 index 0000000..144f945 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +/** + * 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/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h new file mode 100644 index 0000000..498027d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c new file mode 100644 index 0000000..200563d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h new file mode 100644 index 0000000..648d18b --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S new file mode 100644 index 0000000..44cca0d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h new file mode 100644 index 0000000..7b6a6a8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h new file mode 100644 index 0000000..a11f84f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c new file mode 100644 index 0000000..a4b8e55 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/rockchip/px30/platform.mk b/arm-trusted-firmware/plat/rockchip/px30/platform.mk new file mode 100644 index 0000000..d14ffc4 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/px30/px30_def.h b/arm-trusted-firmware/plat/rockchip/px30/px30_def.h new file mode 100644 index 0000000..efe789e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..2003749 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +.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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c new file mode 100644 index 0000000..d6d7098 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h new file mode 100644 index 0000000..06d5528 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c new file mode 100644 index 0000000..25e1cca --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h new file mode 100644 index 0000000..6c0b2b7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c new file mode 100644 index 0000000..36f410b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h new file mode 100644 index 0000000..b96c4dc --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S b/arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S new file mode 100644 index 0000000..2878437 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h new file mode 100644 index 0000000..85ec3fb --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h b/arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h new file mode 100644 index 0000000..ffdb2f3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3288/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3288/platform.mk new file mode 100644 index 0000000..b8dd195 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h b/arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h new file mode 100644 index 0000000..7bff865 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk b/arm-trusted-firmware/plat/rockchip/rk3288/sp_min/sp_min-rk3288.mk new file mode 100644 index 0000000..befdca3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..cd604d2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +.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/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c new file mode 100644 index 0000000..a17fef9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h new file mode 100644 index 0000000..dfb8912 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c new file mode 100644 index 0000000..306308f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h new file mode 100644 index 0000000..e8cbc09 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S new file mode 100644 index 0000000..e9bb3a2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h new file mode 100644 index 0000000..6579756 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rockchip/rk3328/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3328/platform.mk new file mode 100644 index 0000000..5b4766d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h b/arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h new file mode 100644 index 0000000..60055e8 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c new file mode 100644 index 0000000..fa98eb3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h new file mode 100644 index 0000000..6663bcb --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin new file mode 100644 index 0000000..cecd694 --- /dev/null +++ b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin @@ -0,0 +1,461 @@ + 0x14000088, + 0xd10043ff, + 0x5283ffe1, + 0x52824902, + 0x1b020400, + 0x530d7c00, + 0xb9000fe0, + 0xb9400fe0, + 0x340000a0, + 0xb9400fe0, + 0x51000401, + 0xb9000fe1, + 0x35ffffa0, + 0x910043ff, + 0xd65f03c0, + 0x340000e2, + 0xb9400023, + 0xb9000003, + 0x91001021, + 0x91001000, + 0x51000442, + 0x35ffff62, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x7100043f, + 0x54000320, + 0x52800021, + 0x52800082, + 0xb9400fe3, + 0x34000143, + 0x71000c7f, + 0x54000100, + 0x7100147f, + 0x54000161, + 0xb9000402, + 0xb9400803, + 0x12000863, + 0x71000c7f, + 0x54ffffa1, + 0xb9000401, + 0xb9400803, + 0x12000863, + 0x7100047f, + 0x54ffffa1, + 0xb9400803, + 0x12000863, + 0xb9000fe3, + 0xb9400fe3, + 0x7100047f, + 0x54fffd61, + 0x910043ff, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x7100143f, + 0x54000400, + 0x52800021, + 0x52800042, + 0x52800063, + 0xb9400fe4, + 0x340000c4, + 0x7100049f, + 0x54000120, + 0x71000c9f, + 0x54000180, + 0x14000010, + 0xb9000401, + 0xb9400804, + 0x12000884, + 0x7100049f, + 0x54ffffa1, + 0xb9000402, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0xb9000403, + 0xb9400804, + 0x12000884, + 0x7100149f, + 0x54ffffa1, + 0xb9400804, + 0x12000884, + 0xb9000fe4, + 0xb9400fe4, + 0x7100149f, + 0x54fffca1, + 0x910043ff, + 0xd65f03c0, + 0xd10043ff, + 0xb9400801, + 0x12000821, + 0xb9000fe1, + 0xb9400fe1, + 0x71000c3f, + 0x54000400, + 0x52800021, + 0x52800042, + 0x52800083, + 0xb9400fe4, + 0x34000164, + 0x7100049f, + 0x540001c0, + 0x7100149f, + 0x54000221, + 0xb9000403, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0x1400000b, + 0xb9000401, + 0xb9400804, + 0x12000884, + 0x7100049f, + 0x54ffffa1, + 0xb9000402, + 0xb9400804, + 0x12000884, + 0x71000c9f, + 0x54ffffa1, + 0xb9400804, + 0x12000884, + 0xb9000fe4, + 0xb9400fe4, + 0x71000c9f, + 0x54fffca1, + 0x910043ff, + 0xd65f03c0, + 0xd10103ff, + 0xa9037bfd, + 0x9100c3fd, + 0xa9025ff6, + 0xa90157f4, + 0xf90007f3, + 0xaa0003f3, + 0xb9400674, + 0xb9411276, + 0xb941c660, + 0xb941aa75, + 0x7100041f, + 0x54000261, + 0xb9418e60, + 0x321f0000, + 0xb903b6c0, + 0xb9418a60, + 0xb903b2c0, + 0xb9419260, + 0xb903bac0, + 0xb9418e60, + 0x121e7800, + 0xb903b6c0, + 0xb941ca60, + 0xb941ce61, + 0xb941d262, + 0xb9400003, + 0xa030023, + 0x6b22407f, + 0x54ffffa0, + 0x1400003b, + 0xb941d660, + 0x7100041f, + 0x54000701, + 0xb941da60, + 0x3100041f, + 0x54000080, + 0xb941de61, + 0x53007c00, + 0xb9000001, + 0xb941e660, + 0x3100041f, + 0x54000080, + 0xb941ea61, + 0x53007c00, + 0xb9000001, + 0xb941f260, + 0x3100041f, + 0x54000120, + 0xaa1f03e1, + 0x53007c00, + 0x9107d262, + 0xb8616843, + 0xb8216803, + 0x91001021, + 0xf100203f, + 0x54ffff81, + 0x52800020, + 0x97ffff3f, + 0xb941e660, + 0x3100041f, + 0x54000080, + 0xb941ee61, + 0x53007c00, + 0xb9000001, + 0x52800020, + 0x97ffff37, + 0xb9420660, + 0x3100041f, + 0x54000100, + 0xb9420a61, + 0xb9420e62, + 0x53007c00, + 0xb9400003, + 0xa030023, + 0x6b22407f, + 0x54ffffa1, + 0xb9421260, + 0x3100041f, + 0x54000080, + 0xb9421661, + 0x53007c00, + 0xb9000001, + 0xb941da60, + 0x3100041f, + 0x54000080, + 0xb941e261, + 0x53007c00, + 0xb9000001, + 0xb9419660, + 0xb903bec0, + 0xb9422a60, + 0x34000400, + 0xb9422e61, + 0x53007c17, + 0xb90002e1, + 0x52800140, + 0x97ffff18, + 0xb9423260, + 0xb90002e0, + 0x52800140, + 0x97ffff14, + 0xb9423660, + 0xb90002e0, + 0x52800140, + 0x97ffff10, + 0xb9423a60, + 0x34000220, + 0x53007c17, + 0xb94002e0, + 0x121c7400, + 0xb90002e0, + 0x52800020, + 0x97ffff08, + 0xb94002e0, + 0x321e0000, + 0xb90002e0, + 0x528000a0, + 0x97ffff03, + 0xb94002e0, + 0x321d0000, + 0xb90002e0, + 0x52800020, + 0x97fffefe, + 0xb9412a60, + 0xb9004ec0, + 0xb9412e60, + 0xb90052c0, + 0xb9413e60, + 0xb9009ac0, + 0xb9414260, + 0xb9009ec0, + 0xb9415260, + 0xb900dac0, + 0xb9415660, + 0xb900dec0, + 0xb9416660, + 0xb9011ac0, + 0xb9416a60, + 0xb9011ec0, + 0xb9417a60, + 0xb9015ac0, + 0xb9417e60, + 0xb9015ec0, + 0xb9418660, + 0xb90292c0, + 0xb9414660, + 0xb900a2c0, + 0xb9415a60, + 0xb900e2c0, + 0xb9416e60, + 0xb90122c0, + 0xb9418260, + 0xb90162c0, + 0xb9411660, + 0xb90002c0, + 0xb9411a60, + 0xb90006c0, + 0xb9411e60, + 0xb9002ec0, + 0xb9412260, + 0xb90032c0, + 0xb9412660, + 0xb90046c0, + 0xb9413260, + 0xb9005ac0, + 0xb9413660, + 0xb90082c0, + 0xb9413a60, + 0xb90086c0, + 0xb9414a60, + 0xb900c2c0, + 0xb9414e60, + 0xb900c6c0, + 0xb9415e60, + 0xb90102c0, + 0xb9416260, + 0xb90106c0, + 0xb9417260, + 0xb90142c0, + 0xb9417660, + 0xb90146c0, + 0x52800040, + 0xb9000ac0, + 0xb9411261, + 0xb9419a60, + 0xb900b020, + 0xb9419a60, + 0xb900b420, + 0xb9419e60, + 0xb900f020, + 0xb9419e60, + 0xb900f420, + 0xb941a260, + 0xb9013020, + 0xb941a260, + 0xb9013420, + 0xb941a660, + 0xb9017020, + 0xb941a662, + 0xaa1f03e0, + 0xb9017422, + 0x91008261, + 0xb8606822, + 0x8b000283, + 0xb900c062, + 0x91001000, + 0xf102301f, + 0x54ffff61, + 0xb9400a60, + 0xb9000280, + 0xb9400e60, + 0xb9005280, + 0xb9401260, + 0xb9007e80, + 0xb9401660, + 0xb9008280, + 0xb9401a60, + 0xb9008680, + 0xb940ae60, + 0xb9024280, + 0xb940b260, + 0xb9024680, + 0xb940b660, + 0xb9024a80, + 0xb940ba60, + 0xb9024e80, + 0xb940be60, + 0xb9025280, + 0xb940c260, + 0xb9025680, + 0xb940c660, + 0xb9025a80, + 0xb940ca60, + 0xb9026280, + 0xb940ce60, + 0xb9026680, + 0xb940d260, + 0xb9027280, + 0xb940d660, + 0xb9027680, + 0xb940da60, + 0xb9027a80, + 0xb940de60, + 0xb9027e80, + 0xb940e260, + 0xb9028280, + 0xb940e660, + 0xb9028680, + 0xb940ea60, + 0xb9028a80, + 0xb940ee60, + 0xb9029280, + 0xb940f260, + 0xb9029680, + 0xb940f660, + 0xb9029a80, + 0xb940fa60, + 0xb902c680, + 0xb940fe60, + 0xb902ca80, + 0xb9410260, + 0xb902d280, + 0xb9410660, + 0xb902d680, + 0xb9410a60, + 0xb902da80, + 0xb9410e60, + 0xb902f280, + 0xb9422260, + 0x3100041f, + 0x540000c0, + 0xb9422661, + 0x53007c00, + 0xb9000001, + 0x52800020, + 0x97fffe65, + 0x52800020, + 0xb9004680, + 0xb9404a80, + 0x3607ffe0, + 0xb941ae60, + 0xb9000aa0, + 0xb941b260, + 0xb9000ea0, + 0xb941b660, + 0xb90012a0, + 0xb941ba60, + 0xb90016a0, + 0xb941be60, + 0xb9003aa0, + 0xb941c260, + 0xb9003ea0, + 0xb9422260, + 0x3100041f, + 0x54000080, + 0x53007c00, + 0x320083e1, + 0xb9000001, + 0xaa1403e0, + 0x97fffe84, + 0xb9421a60, + 0x3100041f, + 0x54000100, + 0x53007c00, + 0xb9421e61, + 0xb9400002, + 0x2a010041, + 0xb9000001, + 0x52800020, + 0x97fffe43, + 0xaa1403e0, + 0x97fffea0, + 0xb9422260, + 0x3100041f, + 0x54000080, + 0x53007c00, + 0x52a00021, + 0xb9000001, + 0xf94007f3, + 0xa94157f4, + 0xa9425ff6, + 0xa9437bfd, + 0x910103ff, + 0xd65f03c0, diff --git a/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..399f61c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +.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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c new file mode 100644 index 0000000..e277a18 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h new file mode 100644 index 0000000..b4d4807 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c new file mode 100644 index 0000000..7d51bb8 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h new file mode 100644 index 0000000..6c7a01b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S new file mode 100644 index 0000000..e9bb3a2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h new file mode 100644 index 0000000..519a025 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c new file mode 100644 index 0000000..5918d58 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3368/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3368/platform.mk new file mode 100644 index 0000000..e6c62de --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h b/arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h new file mode 100644 index 0000000..4b0fbab --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c new file mode 100644 index 0000000..a8773f4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include + +#include + +__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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h new file mode 100644 index 0000000..c5cbae2 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin new file mode 100644 index 0000000000000000000000000000000000000000..28db923669fe63812c25f016753df10558334fee GIT binary patch literal 864 zcmYjPOH30{6g@Ll2;;=)Bu-b5CqMNDwlcHagN$&9d(o>REW*hMTkQWNsMb3&0+2adX0ey{a*Wn4e&5ft?j@ zyJ&;mt?E(OBFNZD9K^d|e>uiH4tqYpm?W>2v6r~gohPp97lRA5Fb2t+DfXumz3z8`ePWbml3>Ga5=(y?DM4)2_6c;AJw7*KkiH3KKtsC!MF z?l^J*dSrq5BJ+qdE+bB_)SW&VVolfd$Pc9LOc(Mx=Q1DOibDDbH&*`mg*fltYJ+!$ z9CN!UgWEAVv>TH#=nb%zrS~n)c02h-K;tD)Fv-2lGsHdta)0~&Del2L2sf1H_*=uX z=s7^npyHBekf-#c><8Y3<&@+I??}yvMREA{3Qq#FBRq$A$!J#M?7_Dkpsvi_A9uUC zI%5y;;6SAJ`JX&rw0bW@@sn`w=D{W5@vBJo4Z?^FAaHdV`b6Sh<#b}&Jd^PK)KBiK>Hm7ifhGFR zsrmjY)_3x#75b5{KZU(FrPbVZoRC_AkoZd0%){OP0&Y4QX8-^I literal 0 HcmV?d00001 diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c new file mode 100644 index 0000000..816372b --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#include +#include +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h new file mode 100644 index 0000000..172b2a7 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c new file mode 100644 index 0000000..42b6294 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +__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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h new file mode 100644 index 0000000..5572b16 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c new file mode 100644 index 0000000..3cdb7a2 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include + +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h new file mode 100644 index 0000000..9cda22c --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c new file mode 100644 index 0000000..a8b1c32 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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)¶ms_ctl[1], + CTL_REG_NUM - 1); + mmio_write_32(CTL_REG(ch, 0), params_ctl[0]); + sram_regcpy(PI_REG(ch, 0), (uintptr_t)¶ms_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)¶ms_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)¶ms_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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h new file mode 100644 index 0000000..1389944 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c new file mode 100644 index 0000000..724968f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile new file mode 100644 index 0000000..79e09f0 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h new file mode 100644 index 0000000..d431437 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* Registers base address for M0 */ +#define MMIO_BASE 0x40000000 + +#endif /* ADDRESSMAP_H */ diff --git a/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h new file mode 100644 index 0000000..2e90694 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c new file mode 100644 index 0000000..84e8884 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S new file mode 100644 index 0000000..bfe054e --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c new file mode 100644 index 0000000..dfd8af2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c new file mode 100644 index 0000000..5af8caa --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c new file mode 100644 index 0000000..9ad2fa2 --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c new file mode 100644 index 0000000..cad76ac --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h new file mode 100644 index 0000000..7542e22 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S new file mode 100644 index 0000000..546c09a --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c new file mode 100644 index 0000000..3084c4f --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h new file mode 100644 index 0000000..bb7de50 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c new file mode 100644 index 0000000..25596b1 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c new file mode 100644 index 0000000..11c1565 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h new file mode 100644 index 0000000..d665392 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c new file mode 100644 index 0000000..13c83ca --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h new file mode 100644 index 0000000..e31c999 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c new file mode 100644 index 0000000..98b5ad6 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h b/arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h new file mode 100644 index 0000000..8daa5bb --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h new file mode 100644 index 0000000..dc1c703 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S new file mode 100644 index 0000000..cfa912f --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h new file mode 100644 index 0000000..66c4868 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h new file mode 100644 index 0000000..78269b6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h new file mode 100644 index 0000000..84a31b2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h new file mode 100644 index 0000000..6e7e8ba --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h new file mode 100644 index 0000000..4d4ebf6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h new file mode 100644 index 0000000..a5311c9 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h new file mode 100644 index 0000000..0160453 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h new file mode 100644 index 0000000..2968d5b --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h b/arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h new file mode 100644 index 0000000..43e785e --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c b/arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c new file mode 100644 index 0000000..ce8476c --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/rockchip/rk3399/platform.mk b/arm-trusted-firmware/plat/rockchip/rk3399/platform.mk new file mode 100644 index 0000000..aba67c2 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h b/arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h new file mode 100644 index 0000000..ba83242 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S b/arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S new file mode 100644 index 0000000..f045e21 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + + .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/arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h b/arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h new file mode 100644 index 0000000..ddf239e --- /dev/null +++ b/arm-trusted-firmware/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 + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rpi/common/rpi3_common.c b/arm-trusted-firmware/plat/rpi/common/rpi3_common.c new file mode 100644 index 0000000..ef88bf1 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c b/arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c new file mode 100644 index 0000000..5394c6f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c b/arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c new file mode 100644 index 0000000..49c6a76 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c b/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c new file mode 100644 index 0000000..86c61f7 --- /dev/null +++ b/arm-trusted-firmware/plat/rpi/common/rpi3_pm.c @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include + +#ifdef RPI_HAVE_GIC +#include +#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 +} + +void __dead2 plat_secondary_cold_boot_setup(void); + +static void __dead2 +rpi3_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 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) + ; +} + +/******************************************************************************* + * 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_pwr_down_wfi = rpi3_pwr_domain_pwr_down_wfi, + .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/arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S b/arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S new file mode 100644 index 0000000..1c17b21 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c b/arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c new file mode 100644 index 0000000..aae5fac --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/rpi/common/rpi3_topology.c b/arm-trusted-firmware/plat/rpi/common/rpi3_topology.c new file mode 100644 index 0000000..3747287 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +#include + +/* 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/arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c b/arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c new file mode 100644 index 0000000..f6c669f --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c new file mode 100644 index 0000000..715aec4 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S b/arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S new file mode 100644 index 0000000..c0c3967 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h b/arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h new file mode 100644 index 0000000..f44d1f5 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h b/arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h new file mode 100644 index 0000000..2aecab3 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/rpi/rpi3/platform.mk b/arm-trusted-firmware/plat/rpi/rpi3/platform.mk new file mode 100644 index 0000000..6c23923 --- /dev/null +++ b/arm-trusted-firmware/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 genrsa 2048 > $@ 2>/dev/null + + $(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + openssl dgst -sha256 -binary > $@ 2>/dev/null +endif diff --git a/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c new file mode 100644 index 0000000..3ac30e0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c new file mode 100644 index 0000000..db71817 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* 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(¶ms, 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(¶ms, &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/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c new file mode 100644 index 0000000..5915753 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +#include +#include +#include +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c b/arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c new file mode 100644 index 0000000..e7c1e2b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +#include + +#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/arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S b/arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S new file mode 100644 index 0000000..246358d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S b/arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S new file mode 100644 index 0000000..9262fad --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S b/arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S new file mode 100644 index 0000000..6007d03 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h b/arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h new file mode 100644 index 0000000..6787ebf --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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/arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h b/arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h new file mode 100644 index 0000000..0430d46 --- /dev/null +++ b/arm-trusted-firmware/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 + +/* + * 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/arm-trusted-firmware/plat/rpi/rpi4/platform.mk b/arm-trusted-firmware/plat/rpi/rpi4/platform.mk new file mode 100644 index 0000000..528eb1d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c new file mode 100644 index 0000000..2fb4d3d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include + +/* + * 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/arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c b/arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c new file mode 100644 index 0000000..7d1ca5c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c new file mode 100644 index 0000000..925ed97 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#include +#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/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h b/arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h new file mode 100644 index 0000000..f6b5cc3 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c new file mode 100644 index 0000000..0e99256 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c new file mode 100644 index 0000000..e494022 --- /dev/null +++ b/arm-trusted-firmware/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 +#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/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c new file mode 100644 index 0000000..0cb75a0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h b/arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h new file mode 100644 index 0000000..eb6ce5c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/* + * 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/arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S b/arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S new file mode 100644 index 0000000..af7a172 --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S b/arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S new file mode 100644 index 0000000..932b21d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h b/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h new file mode 100644 index 0000000..49ffbf9 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLATFORM_DEF_H +#define PLATFORM_DEF_H + +#include +#include + +/* 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 + +#define PLATFORM_STACK_SIZE 0x400 + +#define BL31_BASE 0x04000000 +#define BL31_SIZE 0x00080000 +#define BL31_LIMIT (BL31_BASE + BL31_SIZE) + +#define BL32_BASE 0xfc000000 +#define BL32_SIZE 0x03c00000 +#define BL32_LIMIT (BL32_BASE + BL32_SIZE) + +#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/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h b/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h new file mode 100644 index 0000000..b09d22a --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SQ_COMMON_H +#define SQ_COMMON_H + +#include + +#include +#include + +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); + +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/arm-trusted-firmware/plat/socionext/synquacer/platform.mk b/arm-trusted-firmware/plat/socionext/synquacer/platform.mk new file mode 100644 index 0000000..dcd5d31 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/platform.mk @@ -0,0 +1,69 @@ +# +# Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +override RESET_TO_BL31 := 1 +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 +# Enable SCMI support +SQ_USE_SCMI_DRIVER ?= 0 + +# 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 \ + ${XLAT_TABLES_LIB_SRCS} + +# Include GICv3 driver files +include drivers/arm/gic/v3/gicv3.mk + +BL31_SOURCES += drivers/arm/ccn/ccn.c \ + ${GICV3_SOURCES} \ + lib/cpus/aarch64/cortex_a53.S \ + 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)/sq_xlat_setup.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/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c new file mode 100644 index 0000000..a7a0ce0 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +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; +} + +/******************************************************************************* + * 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); +} + +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 + {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/arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c new file mode 100644 index 0000000..fa6ea87 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +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/arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c new file mode 100644 index 0000000..05318e3 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S b/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S new file mode 100644 index 0000000..7a2d97b --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S @@ -0,0 +1,110 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + + .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 + ldr x0, sq_sec_entrypoint + + /* 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/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c new file mode 100644 index 0000000..3062f63 --- /dev/null +++ b/arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c @@ -0,0 +1,207 @@ +/* + * Copyright (c) 2018-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#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) +{ + sq_sec_entrypoint = sec_entrypoint; + flush_dcache_range((uint64_t)&sq_sec_entrypoint, + sizeof(sq_sec_entrypoint)); + + *psci_ops = &sq_psci_ops; + + return 0; +} diff --git a/arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c new file mode 100644 index 0000000..7bea111 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +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/arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c new file mode 100644 index 0000000..359997a --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include + +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/arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c b/arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c new file mode 100644 index 0000000..5d1669d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S b/arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S new file mode 100644 index 0000000..d6d2579 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h b/arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h new file mode 100644 index 0000000..b23386d --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/platform.mk b/arm-trusted-firmware/plat/socionext/uniphier/platform.mk new file mode 100644 index 0000000..6edd181 --- /dev/null +++ b/arm-trusted-firmware/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 genrsa 2048 > $@ 2>/dev/null + +$(ROTPK_HASH): $(ROT_KEY) + @echo " OPENSSL $@" + $(Q)openssl rsa -in $< -pubout -outform DER 2>/dev/null |\ + 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/arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk b/arm-trusted-firmware/plat/socionext/uniphier/tsp/tsp-uniphier.mk new file mode 100644 index 0000000..54d4f51 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c new file mode 100644 index 0000000..4bbb259 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier.h b/arm-trusted-firmware/plat/socionext/uniphier/uniphier.h new file mode 100644 index 0000000..ee520ad --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c new file mode 100644 index 0000000..4524610 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include +#include +#ifdef UNIPHIER_DECOMPRESS_GZIP +#include +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c new file mode 100644 index 0000000..c2baebd --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c new file mode 100644 index 0000000..36a9908 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c new file mode 100644 index 0000000..3ca1768 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S new file mode 100644 index 0000000..48927f4 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h new file mode 100644 index 0000000..e35fc88 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c new file mode 100644 index 0000000..9fda26e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c new file mode 100644 index 0000000..b3d23cb --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c new file mode 100644 index 0000000..266efe7 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S new file mode 100644 index 0000000..105cf9e --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c new file mode 100644 index 0000000..dd62d1e --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c new file mode 100644 index 0000000..92e15b0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c new file mode 100644 index 0000000..71cb96c --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c new file mode 100644 index 0000000..a371705 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S new file mode 100644 index 0000000..21c44b6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c new file mode 100644 index 0000000..8a12d5d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S new file mode 100644 index 0000000..d6cb9ff --- /dev/null +++ b/arm-trusted-firmware/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 +#include + + .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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c new file mode 100644 index 0000000..0e7a2d1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c new file mode 100644 index 0000000..1937843 --- /dev/null +++ b/arm-trusted-firmware/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 + +unsigned int plat_get_syscnt_freq2(void) +{ + return 50000000; +} diff --git a/arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c new file mode 100644 index 0000000..e31ca03 --- /dev/null +++ b/arm-trusted-firmware/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 + +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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c new file mode 100644 index 0000000..c106c98 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c new file mode 100644 index 0000000..7469ad1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c b/arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c new file mode 100644 index 0000000..5043f4b --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include + +#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/arm-trusted-firmware/plat/st/common/bl2_io_storage.c b/arm-trusted-firmware/plat/st/common/bl2_io_storage.c new file mode 100644 index 0000000..e129dfd --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/bl2_io_storage.c @@ -0,0 +1,598 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* IO devices */ +uintptr_t fip_dev_handle; +uintptr_t storage_dev_handle; + +static const io_dev_connector_t *fip_dev_con; + +#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); +} + +int open_storage(const uintptr_t spec) +{ + return io_dev_init(storage_dev_handle, 0); +} + +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(¶ms, 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; + } + + params.device_info = &mmc_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); + panic(); + } + + /* Open MMC as a block device to read GPT table */ + 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); +} +#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); + + 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_SD: + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_EMMC: + 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; + + partition_init(GPT_IMAGE_ID); + 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); + + 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 +/* + * Eventually, this function will return the + * boot index to be passed on to the Update + * Agent after performing certain checks like + * a watchdog timeout, or Auth failure while + * trying to load from a certain bank. + * For now, since we do not have that logic + * implemented, just pass the active_index + * read from the metadata. + */ +uint32_t plat_fwu_get_boot_idx(void) +{ + const struct fwu_metadata *metadata; + + metadata = fwu_get_metadata(); + + return metadata->active_index; +} + +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/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c b/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c new file mode 100644 index 0000000..4391195 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c @@ -0,0 +1,667 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/* IO devices */ +#ifndef AARCH32_SP_OPTEE +static const io_dev_connector_t *dummy_dev_con; +static uintptr_t dummy_dev_handle; +static uintptr_t dummy_dev_spec; +#endif + +static uintptr_t image_dev_handle; +static uintptr_t storage_dev_handle; + +#if STM32MP_SDMMC || STM32MP_EMMC +static struct mmc_device_info mmc_info; +static io_block_spec_t gpt_block_spec = { + .offset = 0U, + .length = 34U * MMC_BLOCK_SIZE, /* Size of GPT table */ +}; + +static uint32_t block_buffer[MMC_BLOCK_SIZE] __aligned(MMC_BLOCK_SIZE); + +static const 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, +}; + +#if STM32MP_EMMC_BOOT +static io_block_spec_t emmc_boot_ssbl_block_spec = { + .offset = PLAT_EMMC_BOOT_SSBL_OFFSET, + .length = MMC_BLOCK_SIZE, /* We are interested only in first 4 bytes */ +}; + +static const io_block_dev_spec_t mmc_block_dev_boot_part_spec = { + /* It's used as temp buffer in block driver */ + .buffer = { + .offset = (size_t)&block_buffer, + .length = MMC_BLOCK_SIZE, + }, + .ops = { + .read = mmc_boot_part_read_blocks, + .write = NULL, + }, + .block_size = MMC_BLOCK_SIZE, +}; +#endif + +static struct io_mmc_dev_spec mmc_device_spec = { + .use_boot_part = false, +}; + +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, + }, +}; + +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, + }, +}; +#endif + +#if STM32MP_SPI_NAND || STM32MP_SPI_NOR +static const io_dev_connector_t *spi_dev_con; +#endif + +#ifdef AARCH32_SP_OPTEE +static const struct stm32image_part_info optee_header_partition_spec = { + .name = OPTEE_HEADER_IMAGE_NAME, + .binary_type = OPTEE_HEADER_BINARY_TYPE, +}; + +static const struct stm32image_part_info optee_core_partition_spec = { + .name = OPTEE_CORE_IMAGE_NAME, + .binary_type = OPTEE_CORE_BINARY_TYPE, +}; + +static const struct stm32image_part_info optee_paged_partition_spec = { + .name = OPTEE_PAGED_IMAGE_NAME, + .binary_type = OPTEE_PAGED_BINARY_TYPE, +}; +#else +static const io_block_spec_t bl32_block_spec = { + .offset = BL32_BASE, + .length = STM32MP_BL32_SIZE +}; +#endif + +static const struct stm32image_part_info bl33_partition_spec = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, +}; + +enum { + IMG_IDX_BL33, +#ifdef AARCH32_SP_OPTEE + IMG_IDX_OPTEE_HEADER, + IMG_IDX_OPTEE_CORE, + IMG_IDX_OPTEE_PAGED, +#endif + IMG_IDX_NUM +}; + +static struct stm32image_device_info stm32image_dev_info_spec __unused = { + .lba_size = MMC_BLOCK_SIZE, + .part_info[IMG_IDX_BL33] = { + .name = BL33_IMAGE_NAME, + .binary_type = BL33_BINARY_TYPE, + }, +#ifdef AARCH32_SP_OPTEE + .part_info[IMG_IDX_OPTEE_HEADER] = { + .name = OPTEE_HEADER_IMAGE_NAME, + .binary_type = OPTEE_HEADER_BINARY_TYPE, + }, + .part_info[IMG_IDX_OPTEE_CORE] = { + .name = OPTEE_CORE_IMAGE_NAME, + .binary_type = OPTEE_CORE_BINARY_TYPE, + }, + .part_info[IMG_IDX_OPTEE_PAGED] = { + .name = OPTEE_PAGED_IMAGE_NAME, + .binary_type = OPTEE_PAGED_BINARY_TYPE, + }, +#endif +}; + +static io_block_spec_t stm32image_block_spec = { + .offset = 0U, + .length = 0U, +}; + +static const io_dev_connector_t *stm32image_dev_con __unused; + +#ifndef AARCH32_SP_OPTEE +static int open_dummy(const uintptr_t spec); +#endif +static int open_image(const uintptr_t spec); +static int open_storage(const uintptr_t spec); + +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[] = { +#ifdef AARCH32_SP_OPTEE + [BL32_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_header_partition_spec, + .check = open_image + }, + [BL32_EXTRA1_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_core_partition_spec, + .check = open_image + }, + [BL32_EXTRA2_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&optee_paged_partition_spec, + .check = open_image + }, +#else + [BL32_IMAGE_ID] = { + .dev_handle = &dummy_dev_handle, + .image_spec = (uintptr_t)&bl32_block_spec, + .check = open_dummy + }, +#endif + [BL33_IMAGE_ID] = { + .dev_handle = &image_dev_handle, + .image_spec = (uintptr_t)&bl33_partition_spec, + .check = open_image + }, +#if STM32MP_SDMMC || STM32MP_EMMC + [GPT_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&gpt_block_spec, + .check = open_storage + }, +#endif + [STM32_IMAGE_ID] = { + .dev_handle = &storage_dev_handle, + .image_spec = (uintptr_t)&stm32image_block_spec, + .check = open_storage + } +}; + +#ifndef AARCH32_SP_OPTEE +static int open_dummy(const uintptr_t spec) +{ + return io_dev_init(dummy_dev_handle, 0); +} +#endif + +static int open_image(const uintptr_t spec) +{ + return io_dev_init(image_dev_handle, 0); +} + +static 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_ssbl_header(void) +{ + uint32_t magic = 0U; + int io_result; + size_t bytes_read; + + 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_boot_part_spec, + &storage_dev_handle); + assert(io_result == 0); + + io_result = io_open(storage_dev_handle, (uintptr_t)&emmc_boot_ssbl_block_spec, + &image_dev_handle); + assert(io_result == 0); + + io_result = io_read(image_dev_handle, (uintptr_t)&magic, sizeof(magic), + &bytes_read); + assert(io_result == 0); + assert(bytes_read == sizeof(magic)); + + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); + + 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; + default: + ERROR("Boot interface not found\n"); + panic(); + break; + } + + if (boot_context->boot_interface_instance != 0U) { + INFO(" Instance %d\n", boot_context->boot_interface_instance); + } +} + +static void stm32image_io_setup(void) +{ + int io_result __unused; + + io_result = register_io_dev_stm32image(&stm32image_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(stm32image_dev_con, + (uintptr_t)&stm32image_dev_info_spec, + &image_dev_handle); + assert(io_result == 0); +} + +#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; + uint8_t idx; + struct stm32image_part_info *part; + struct stm32_sdmmc2_params params; + const partition_entry_t *entry __unused; + uint32_t magic __unused; + + zeromem(¶ms, 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; + } + + params.device_info = &mmc_info; + if (stm32_sdmmc2_mmc_init(¶ms) != 0) { + ERROR("SDMMC%u init failed\n", boot_interface_instance); + panic(); + } + + stm32image_dev_info_spec.device_size = + stm32_sdmmc2_mmc_get_device_size(); + +#if STM32MP_EMMC_BOOT + if (mmc_dev_type == MMC_IS_EMMC) { + magic = get_boot_part_ssbl_header(); + + if (magic == BOOT_API_IMAGE_HEADER_MAGIC_NB) { + VERBOSE("%s, header found, jump to emmc load\n", __func__); + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = PLAT_EMMC_BOOT_SSBL_OFFSET; + part->bkp_offset = 0U; + mmc_device_spec.use_boot_part = true; + + goto emmc_boot; + } else { + WARN("%s: Can't find STM32 header on a boot partition\n", __func__); + } + } +#endif + + /* Open MMC as a block device to read GPT table */ + 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); + + partition_init(GPT_IMAGE_ID); + + io_result = io_dev_close(storage_dev_handle); + assert(io_result == 0); + + for (idx = 0U; idx < IMG_IDX_NUM; idx++) { + part = &stm32image_dev_info_spec.part_info[idx]; + entry = get_partition_entry(part->name); + if (entry == NULL) { + ERROR("Partition %s not found\n", part->name); + panic(); + } + + part->part_offset = entry->start; + part->bkp_offset = 0U; + } + +#if STM32MP_EMMC_BOOT +emmc_boot: +#endif + /* + * Re-open MMC with io_mmc, for better perfs compared to + * io_block. + */ + io_result = register_io_dev_mmc(&mmc_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(mmc_dev_con, (uintptr_t)&mmc_device_spec, + &storage_dev_handle); + assert(io_result == 0); +} +#endif /* STM32MP_SDMMC || STM32MP_EMMC */ + +#if STM32MP_SPI_NOR +static void boot_spi_nor(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + 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); + + stm32image_dev_info_spec.device_size = spi_nor_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_BL33_OFFSET; + part->bkp_offset = 0U; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEH_OFFSET; + part->bkp_offset = 0U; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEED_OFFSET; + part->bkp_offset = 0U; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NOR_TEEX_OFFSET; + part->bkp_offset = 0U; +#endif +} +#endif /* STM32MP_SPI_NOR */ + +#if STM32MP_RAW_NAND +static void boot_fmc2_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + 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); + + stm32image_dev_info_spec.device_size = nand_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = nand_dev_spec.erase_size; +#endif +} +#endif /* STM32MP_RAW_NAND */ + +#if STM32MP_SPI_NAND +static void boot_spi_nand(boot_api_context_t *boot_context) +{ + int io_result __unused; + uint8_t idx; + struct stm32image_part_info *part; + + 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); + + stm32image_dev_info_spec.device_size = + spi_nand_dev_spec.device_size; + + idx = IMG_IDX_BL33; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_BL33_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + +#ifdef AARCH32_SP_OPTEE + idx = IMG_IDX_OPTEE_HEADER; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEH_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_PAGED; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEED_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; + + idx = IMG_IDX_OPTEE_CORE; + part = &stm32image_dev_info_spec.part_info[idx]; + part->part_offset = STM32MP_NAND_TEEX_OFFSET; + part->bkp_offset = spi_nand_dev_spec.erase_size; +#endif +} +#endif /* STM32MP_SPI_NAND */ + +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); + } + +#ifndef AARCH32_SP_OPTEE + io_result = register_io_dev_dummy(&dummy_dev_con); + assert(io_result == 0); + + io_result = io_dev_open(dummy_dev_con, dummy_dev_spec, + &dummy_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); + stm32image_io_setup(); + 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); + stm32image_io_setup(); + break; +#endif +#if STM32MP_SPI_NOR + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NOR_QSPI: + dmbsy(); + boot_spi_nor(boot_context); + stm32image_io_setup(); + break; +#endif +#if STM32MP_RAW_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_FMC: + dmbsy(); + boot_fmc2_nand(boot_context); + stm32image_io_setup(); + break; +#endif +#if STM32MP_SPI_NAND + case BOOT_API_CTX_BOOT_INTERFACE_SEL_FLASH_NAND_QSPI: + dmbsy(); + boot_spi_nand(boot_context); + stm32image_io_setup(); + break; +#endif + + default: + ERROR("Boot interface %d not supported\n", + boot_context->boot_interface_selected); + panic(); + break; + } +} + +/* + * 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; + + assert(image_id < ARRAY_SIZE(policies)); + + policy = &policies[image_id]; + rc = policy->check(policy->image_spec); + if (rc == 0) { + *image_spec = policy->image_spec; + *dev_handle = *(policy->dev_handle); + } + + return rc; +} diff --git a/arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h b/arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h new file mode 100644 index 0000000..0f5a64d --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* 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/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h new file mode 100644 index 0000000..3075d18 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_AUTH_H +#define STM32MP_AUTH_H + +struct stm32mp_auth_ops { + uint32_t (*check_key)(uint8_t *pubkey_in, uint8_t *pubkey_out); + uint32_t (*verify_signature)(uint8_t *hash_in, uint8_t *pubkey_in, + uint8_t *signature, uint32_t ecc_algo); +}; + +void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr); +int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer); + +#endif /* STM32MP_AUTH_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h new file mode 100644 index 0000000..d8d1c13 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_common.h @@ -0,0 +1,134 @@ +/* + * Copyright (C) 2018-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP_COMMON_H +#define STM32MP_COMMON_H + +#include + +#include + +#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); + +#if STM32MP_USE_STM32IMAGE +/* + * Check that the STM32 header of a .stm32 binary image is valid + * @param header: pointer to the stm32 image header + * @param buffer: address of the binary image (payload) + * @return: 0 on success, negative value in case of error + */ +int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer); +#endif /* STM32MP_USE_STM32IMAGE */ + +/* 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); + +#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT +void stm32mp1_fwu_set_boot_idx(void); +#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */ + +#endif /* STM32MP_COMMON_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h new file mode 100644 index 0000000..b7bf1d0 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h new file mode 100644 index 0000000..490560f --- /dev/null +++ b/arm-trusted-firmware/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 + +#define STM32MP_FIP_GUID \ + EFI_GUID(0x19d5df83, 0x11b0, 0x457b, \ + 0xbe, 0x2c, 0x75, 0x59, 0xc1, 0x31, 0x42, 0xa5) + +#endif /* STM32MP_EFI_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h new file mode 100644 index 0000000..18884ae --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h new file mode 100644 index 0000000..989c890 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef STM32MP_IO_STORAGE_H +#define STM32MP_IO_STORAGE_H + +#include + +#include + +/* IO devices handle */ +extern uintptr_t storage_dev_handle; +extern uintptr_t fip_dev_handle; + +extern io_block_spec_t image_block_spec; + +/* Function declarations */ +int open_fip(const uintptr_t spec); +int open_storage(const uintptr_t spec); + +#endif /* STM32MP_IO_STORAGE_H */ diff --git a/arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h b/arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h new file mode 100644 index 0000000..13f4b13 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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/arm-trusted-firmware/plat/st/common/include/usb_dfu.h b/arm-trusted-firmware/plat/st/common/include/usb_dfu.h new file mode 100644 index 0000000..f7d4245 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#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/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c new file mode 100644 index 0000000..46ac9cf --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c @@ -0,0 +1,521 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +/* 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 = U(115200), + .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, + .over_sampling = STM32_UART_OVERSAMPLING_16, + .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/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c new file mode 100644 index 0000000..19a6bba --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c @@ -0,0 +1,196 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/st/common/stm32mp_auth.c b/arm-trusted-firmware/plat/st/common/stm32mp_auth.c new file mode 100644 index 0000000..97fbffa --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_auth.c @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include + +static const struct stm32mp_auth_ops *auth_ops; + +void stm32mp_init_auth(struct stm32mp_auth_ops *init_ptr) +{ + if ((init_ptr == NULL) || + (init_ptr->check_key == NULL) || + (init_ptr->verify_signature == NULL) || + (stm32_hash_register() != 0)) { + panic(); + } + + auth_ops = init_ptr; +} + +int stm32mp_auth_image(boot_api_image_header_t *header, uintptr_t buffer) +{ + int ret; + uint8_t image_hash[BOOT_API_SHA256_DIGEST_SIZE_IN_BYTES]; + uint32_t header_skip_cksum = sizeof(header->magic) + + sizeof(header->image_signature) + + sizeof(header->payload_checksum); + + /* Check Security Status */ + if (!stm32mp_is_closed_device()) { + if (header->option_flags != 0U) { + WARN("Skip signature check (header option)\n"); + return 0; + } + INFO("Check signature on Open device\n"); + } + + if (auth_ops == NULL) { + ERROR("Device doesn't support image authentication\n"); + return -EOPNOTSUPP; + } + + ret = mmap_add_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_BASE, + STM32MP_ROM_SIZE_2MB_ALIGNED, MT_CODE | MT_SECURE); + if (ret != 0) { + return ret; + } + + /* Check Public Key */ + if (auth_ops->check_key(header->ecc_pubk, NULL) != BOOT_API_RETURN_OK) { + ret = -EINVAL; + goto err; + } + + /* Compute end of header hash and payload hash */ + stm32_hash_init(HASH_SHA256); + + ret = stm32_hash_update((uint8_t *)&header->header_version, + sizeof(boot_api_image_header_t) - + header_skip_cksum); + if (ret != 0) { + ERROR("Hash of header failed, %i\n", ret); + goto err; + } + + ret = stm32_hash_final_update((uint8_t *)buffer, + header->image_length, image_hash); + if (ret != 0) { + ERROR("Hash of payload failed\n"); + goto err; + } + + /* Verify signature */ + if (auth_ops->verify_signature(image_hash, header->ecc_pubk, + header->image_signature, + header->ecc_algo_type) != + BOOT_API_RETURN_OK) { + ret = -EINVAL; + } + +err: + mmap_remove_dynamic_region(STM32MP_ROM_BASE, STM32MP_ROM_SIZE_2MB_ALIGNED); + return ret; +} diff --git a/arm-trusted-firmware/plat/st/common/stm32mp_common.c b/arm-trusted-firmware/plat/st/common/stm32mp_common.c new file mode 100644 index 0000000..d922d3c --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_common.c @@ -0,0 +1,313 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#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; +} + +#if STM32MP_USE_STM32IMAGE +int stm32mp_check_header(boot_api_image_header_t *header, uintptr_t buffer) +{ + uint32_t i; + uint32_t img_checksum = 0U; + + /* + * Check header/payload validity: + * - Header magic + * - Header version + * - Payload checksum + */ + if (header->magic != BOOT_API_IMAGE_HEADER_MAGIC_NB) { + ERROR("Header magic\n"); + return -EINVAL; + } + + if ((header->header_version & HEADER_VERSION_MAJOR_MASK) != + (BOOT_API_HEADER_VERSION & HEADER_VERSION_MAJOR_MASK)) { + ERROR("Header version\n"); + return -EINVAL; + } + + for (i = 0U; i < header->image_length; i++) { + img_checksum += *(uint8_t *)(buffer + i); + } + + if (header->payload_checksum != img_checksum) { + ERROR("Checksum: 0x%x (awaited: 0x%x)\n", img_checksum, + header->payload_checksum); + return -EINVAL; + } + + return 0; +} +#endif /* STM32MP_USE_STM32IMAGE */ + +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) +{ + plat_crash_console_init(); + set_console(STM32MP_DEBUG_USART_BASE, STM32MP_DEBUG_USART_CLK_FRQ); +} +#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/arm-trusted-firmware/plat/st/common/stm32mp_dt.c b/arm-trusted-firmware/plat/st/common/stm32mp_dt.c new file mode 100644 index 0000000..ea71571 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_dt.c @@ -0,0 +1,447 @@ +/* + * Copyright (c) 2017-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +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 index, len; + const fdt32_t *cuint; + + if ((name == NULL) || (otp == NULL)) { + return -FDT_ERR_BADVALUE; + } + + node = fdt_node_offset_by_compatible(fdt, -1, DT_NVMEM_LAYOUT_COMPAT); + if (node < 0) { + return node; + } + + index = fdt_stringlist_search(fdt, node, "nvmem-cell-names", name); + if (index < 0) { + return index; + } + + cuint = fdt_getprop(fdt, node, "nvmem-cells", &len); + if (cuint == NULL) { + return -FDT_ERR_NOTFOUND; + } + + if ((index * (int)sizeof(uint32_t)) > len) { + return -FDT_ERR_BADVALUE; + } + + cuint += index; + + node = fdt_node_offset_by_phandle(fdt, fdt32_to_cpu(*cuint)); + if (node < 0) { + ERROR("Malformed nvmem_layout node: ignored\n"); + return node; + } + + cuint = fdt_getprop(fdt, node, "reg", &len); + if ((cuint == NULL) || (len != (2 * (int)sizeof(uint32_t)))) { + ERROR("Malformed nvmem_layout node: ignored\n"); + return -FDT_ERR_BADVALUE; + } + + if (fdt32_to_cpu(*cuint) % sizeof(uint32_t)) { + ERROR("Misaligned nvmem_layout element: ignored\n"); + 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/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c b/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c new file mode 100644 index 0000000..ca71958 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c @@ -0,0 +1,145 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +#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 + }, +#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 FCONF_ST_IO_UUID_NUMBER U(8) + +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"}, + {NT_FW_CONFIG_ID, "nt_fw_cfg_uuid"}, +}; + +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; + policies[load_info[i].image_id].dev_handle = &fip_dev_handle; + policies[load_info[i].image_id].check = open_fip; + } + + return 0; +} + +FCONF_REGISTER_POPULATOR(TB_FW, stm32mp_io, fconf_populate_stm32mp_io_policies); diff --git a/arm-trusted-firmware/plat/st/common/usb_dfu.c b/arm-trusted-firmware/plat/st/common/usb_dfu.c new file mode 100644 index 0000000..8bb0994 --- /dev/null +++ b/arm-trusted-firmware/plat/st/common/usb_dfu.c @@ -0,0 +1,538 @@ +/* + * Copyright (c) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include + +/* 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/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c new file mode 100644 index 0000000..88d0f8a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#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 + +#if STM32MP15 +static struct stm32mp_auth_ops stm32mp1_auth_ops; +#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 STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE + INFO("BL2 runs OP-TEE setup\n"); +#else + INFO("BL2 runs SP_MIN setup\n"); +#endif +#endif /* STM32MP_USE_STM32IMAGE */ +} + +#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); + +#if STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE + mmap_add_region(STM32MP_OPTEE_BASE, STM32MP_OPTEE_BASE, + STM32MP_OPTEE_SIZE, + MT_MEMORY | MT_RW | MT_SECURE); +#else + /* Prevent corruption of preloaded BL32 */ + mmap_add_region(BL32_BASE, BL32_BASE, + BL32_LIMIT - BL32_BASE, + MT_RO_DATA | MT_SECURE); +#endif +#endif /* STM32MP_USE_STM32IMAGE */ + + /* 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); + +#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 (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 STM32MP15 + if (stm32mp_is_auth_supported()) { + stm32mp1_auth_ops.check_key = + boot_context->bootrom_ecdsa_check_key; + stm32mp1_auth_ops.verify_signature = + boot_context->bootrom_ecdsa_verify_signature; + + stm32mp_init_auth(&stm32mp1_auth_ops); + } +#endif + + stm32mp1_arch_security_setup(); + + print_reset_reason(); + +#if STM32MP15 + update_monotonic_counter(); +#endif + + stm32mp1_syscfg_enable_io_compensation_finish(); + +#if !STM32MP_USE_STM32IMAGE + fconf_populate("TB_FW", STM32MP_DTB_BASE); +#endif /* !STM32MP_USE_STM32IMAGE */ + + 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; +#if !STM32MP_USE_STM32IMAGE + 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, + }; +#endif /* !STM32MP_USE_STM32IMAGE */ + + assert(bl_mem_params != NULL); + + switch (image_id) { +#if !STM32MP_USE_STM32IMAGE + case FW_CONFIG_ID: + /* Set global DTB info for fixed fw_config information */ + set_config_info(STM32MP_FW_CONFIG_BASE, 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); + 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); + 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; +#endif /* !STM32MP_USE_STM32IMAGE */ + + case BL32_IMAGE_ID: + if (optee_header_is_valid(bl_mem_params->image_info.image_base)) { + /* 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); + paged_mem_params = get_bl_mem_params_node(BL32_EXTRA2_IMAGE_ID); + assert((pager_mem_params != NULL) && (paged_mem_params != NULL)); + +#if STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) + /* Set OP-TEE extra image load areas at run-time */ + pager_mem_params->image_info.image_base = STM32MP_OPTEE_BASE; + pager_mem_params->image_info.image_max_size = STM32MP_OPTEE_SIZE; + + 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; +#endif /* STM32MP_USE_STM32IMAGE && defined(AARCH32_SP_OPTEE) */ + + err = parse_optee_header(&bl_mem_params->ep_info, + &pager_mem_params->image_info, + &paged_mem_params->image_info); + if (err) { + ERROR("OPTEE header parse error.\n"); + panic(); + } + + /* Set optee boot info from parsed header data */ + bl_mem_params->ep_info.args.arg0 = paged_mem_params->image_info.image_base; + bl_mem_params->ep_info.args.arg1 = 0; /* Unused */ + bl_mem_params->ep_info.args.arg2 = 0; /* No DT supported */ + } else { +#if !STM32MP_USE_STM32IMAGE + 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); + bl_mem_params->image_info.image_max_size += + tos_fw_mem_params->image_info.image_max_size; +#endif /* !STM32MP_USE_STM32IMAGE */ + 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 !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT + stm32mp1_fwu_set_boot_idx(); +#endif /* !STM32MP_USE_STM32IMAGE && 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/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h b/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h new file mode 100644 index 0000000..7638418 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h @@ -0,0 +1,373 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOOT_API_H +#define BOOT_API_H + +#include +#include + +/* + * 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 check key + * - ECDSA verify signature + * - ECDSA verify signature and go + */ + uint32_t (*bootrom_ecdsa_check_key)(uint8_t *pubkey_in, + uint8_t *pubkey_out); + uint32_t (*bootrom_ecdsa_verify_signature)(uint8_t *hash_in, + uint8_t *pubkey_in, + uint8_t *signature, + uint32_t ecc_algo); + uint32_t (*bootrom_ecdsa_verify_and_go)(uint8_t *hash_in, + uint8_t *pub_key_in, + uint8_t *signature, + uint32_t ecc_algo, + uint32_t *entry_in); +#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]; +#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; + +#endif /* BOOT_API_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h b/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h new file mode 100644 index 0000000..8ecb4c3 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h @@ -0,0 +1,235 @@ +/* + * 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 +#include +#include +#include + +#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 + +#if STM32MP_USE_STM32IMAGE +#ifdef AARCH32_SP_OPTEE +#define OPTEE_HEADER_IMAGE_NAME "teeh" +#define OPTEE_CORE_IMAGE_NAME "teex" +#define OPTEE_PAGED_IMAGE_NAME "teed" +#define OPTEE_HEADER_BINARY_TYPE U(0x20) +#define OPTEE_CORE_BINARY_TYPE U(0x21) +#define OPTEE_PAGED_BINARY_TYPE U(0x22) +#endif + +/* SSBL = second stage boot loader */ +#define BL33_IMAGE_NAME "ssbl" +#define BL33_BINARY_TYPE U(0x0) +#else /* STM32MP_USE_STM32IMAGE */ +#define FIP_IMAGE_NAME "fip" +#define METADATA_PART_1 "metadata1" +#define METADATA_PART_2 "metadata2" + +#endif /* STM32MP_USE_STM32IMAGE */ + +#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 STM32MP_USE_STM32IMAGE || 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 /* STM32MP_USE_STM32IMAGE || 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_BASE (STM32MP_DDR_BASE + U(0x08000000)) +#define DWL_BUFFER_SIZE U(0x08000000) + +/* + * 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/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h new file mode 100644 index 0000000..3663bce --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h new file mode 100644 index 0000000..23934e9 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h @@ -0,0 +1,42 @@ +/* + * 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 + +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); + +#if STM32MP_USE_STM32IMAGE +uint32_t stm32mp_get_ddr_ns_size(void); +#endif /* STM32MP_USE_STM32IMAGE */ + +void stm32mp1_init_scmi_server(void); +#endif /* STM32MP1_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h new file mode 100644 index 0000000..3f6367e --- /dev/null +++ b/arm-trusted-firmware/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 + +#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/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h b/arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h new file mode 100644 index 0000000..52088de --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c new file mode 100644 index 0000000..7963c4a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c @@ -0,0 +1,132 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/******************************************************************************* + * 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, + }, + /* 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, + }, + + /* 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/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c new file mode 100644 index 0000000..4fce55a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include + +/******************************************************************************* + * 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 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), + + /* Updated at runtime if OP-TEE is loaded */ + .ep_info.pc = STM32MP_BL32_BASE, + + .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_PLAT_SETUP), + + /* Updated at runtime if OP-TEE is loaded */ + .image_info.image_base = STM32MP_BL32_BASE, + .image_info.image_max_size = STM32MP_BL32_SIZE, + + .next_handoff_image_id = BL33_IMAGE_ID, + }, + +#if defined(AARCH32_SP_OPTEE) + /* 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, + }, + /* 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 /* AARCH32_SP_OPTEE */ + + /* 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 = PLAT_STM32MP_NS_IMAGE_OFFSET, + .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, 0U), + + .image_info.image_base = PLAT_STM32MP_NS_IMAGE_OFFSET, + .image_info.image_max_size = STM32MP_DDR_MAX_SIZE - + (PLAT_STM32MP_NS_IMAGE_OFFSET - STM32MP_DDR_BASE), + + .next_handoff_image_id = INVALID_IMAGE_ID, + } +}; + +REGISTER_BL_IMAGE_DESCS(bl2_mem_params_descs) diff --git a/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c b/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c new file mode 100644 index 0000000..36a3a1c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include + +/******************************************************************************* + * 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) +{ +#if STM32MP_USE_STM32IMAGE + bl_mem_params_node_t *bl33 = get_bl_mem_params_node(BL33_IMAGE_ID); + uint32_t ddr_ns_size = stm32mp_get_ddr_ns_size(); + + /* Max size is non-secure DDR end address minus image_base */ + bl33->image_info.image_max_size = STM32MP_DDR_BASE + ddr_ns_size - + bl33->image_info.image_base; +#endif /* STM32MP_USE_STM32IMAGE */ + + 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/arm-trusted-firmware/plat/st/stm32mp1/platform.mk b/arm-trusted-firmware/plat/st/stm32mp1/platform.mk new file mode 100644 index 0000000..9e732d6 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/platform.mk @@ -0,0 +1,494 @@ +# +# 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_UART_BAUDRATE ?= 115200 + +# Allow TF-A to concatenate BL2 & BL32 binaries in a single file, +# share DTB file between BL2 and BL32 +# If it is set to 0, then FIP is used +STM32MP_USE_STM32IMAGE ?= 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) +# DDR controller with single AXI port and 16-bit interface +STM32MP_DDR_DUAL_AXI_PORT:= 0 +STM32MP_DDR_32BIT_INTERFACE:= 0 + +# 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 +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 + +ifeq (${PSA_FWU_SUPPORT},1) +ifneq (${STM32MP_USE_STM32IMAGE},1) +# Number of banks of updatable firmware +NR_OF_FW_BANKS := 2 +NR_OF_IMAGES_IN_FW_BANK := 1 + +# Number of TF-A copies in the device +STM32_TF_A_COPIES := 2 +STM32_BL33_PARTS_NUM := 2 +STM32_RUNTIME_PARTS_NUM := 4 +else +$(error FWU Feature enabled only with FIP images) +endif +else +# Number of TF-A copies in the device +STM32_TF_A_COPIES := 2 +STM32_BL33_PARTS_NUM := 1 +ifeq ($(AARCH32_SP),optee) +STM32_RUNTIME_PARTS_NUM := 3 +else ifeq ($(STM32MP_USE_STM32IMAGE),1) +STM32_RUNTIME_PARTS_NUM := 0 +else +STM32_RUNTIME_PARTS_NUM := 1 +endif +endif +PLAT_PARTITION_MAX_ENTRIES := $(shell echo $$(($(STM32_TF_A_COPIES) + \ + $(STM32_BL33_PARTS_NUM) + \ + $(STM32_RUNTIME_PARTS_NUM)))) + +# 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 + +# Device tree +ifeq ($(STM32MP13),1) +BL2_DTSI := stm32mp13-bl2.dtsi +FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) +else +ifeq ($(STM32MP_USE_STM32IMAGE),1) +ifeq ($(AARCH32_SP),optee) +BL2_DTSI := stm32mp15-bl2.dtsi +FDT_SOURCES := $(addprefix ${BUILD_PLAT}/fdts/, $(patsubst %.dtb,%-bl2.dts,$(DTB_FILE_NAME))) +else +FDT_SOURCES := $(addprefix fdts/, $(patsubst %.dtb,%.dts,$(DTB_FILE_NAME))) +endif +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 +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"))) +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 + +ifneq (${STM32MP_USE_STM32IMAGE},1) +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 ($(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)) +endif +ifneq ($(BL32_EXTRA2),) +$(eval $(call TOOL_ADD_IMG,BL32_EXTRA2,--tos-fw-extra2)) +endif +endif +endif + +# Enable flags for C files +$(eval $(call assert_booleans,\ + $(sort \ + PLAT_XLAT_TABLES_DYNAMIC \ + STM32MP_DDR_32BIT_INTERFACE \ + STM32MP_DDR_DUAL_AXI_PORT \ + STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ + STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ + STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ + STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ + STM32MP_USE_STM32IMAGE \ + STM32MP13 \ + STM32MP15 \ +))) + +$(eval $(call assert_numerics,\ + $(sort \ + PLAT_PARTITION_MAX_ENTRIES \ + STM32_TF_A_COPIES \ + STM32_TF_VERSION \ + STM32MP_UART_BAUDRATE \ +))) + +$(eval $(call add_defines,\ + $(sort \ + PLAT_PARTITION_MAX_ENTRIES \ + PLAT_XLAT_TABLES_DYNAMIC \ + STM32_TF_A_COPIES \ + STM32_TF_VERSION \ + STM32MP_DDR_32BIT_INTERFACE \ + STM32MP_DDR_DUAL_AXI_PORT \ + STM32MP_EARLY_CONSOLE \ + STM32MP_EMMC \ + STM32MP_EMMC_BOOT \ + STM32MP_RAW_NAND \ + STM32MP_SDMMC \ + STM32MP_SPI_NAND \ + STM32MP_SPI_NOR \ + STM32MP_UART_BAUDRATE \ + STM32MP_UART_PROGRAMMER \ + STM32MP_USB_PROGRAMMER \ + STM32MP_USE_STM32IMAGE \ + STM32MP13 \ + STM32MP15 \ +))) + +# Include paths and source files +PLAT_INCLUDES := -Iplat/st/common/include/ +PLAT_INCLUDES += -Iplat/st/stm32mp1/include/ + +ifeq (${STM32MP_USE_STM32IMAGE},1) +include common/fdt_wrappers.mk +else +include lib/fconf/fconf.mk +endif +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 +else +PLAT_BL_COMMON_SOURCES += drivers/st/clk/stm32mp1_clk.c +endif + +ifneq (${STM32MP_USE_STM32IMAGE},1) +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 +else +BL2_SOURCES += ${FDT_WRAPPERS_SOURCES} + +BL2_SOURCES += drivers/io/io_dummy.c \ + drivers/st/io/io_stm32image.c \ + plat/st/common/bl2_stm32_io_storage.c \ + plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c \ + plat/st/stm32mp1/stm32mp1_security.c +endif + +ifeq (${PSA_FWU_SUPPORT},1) +include lib/zlib/zlib.mk +include drivers/fwu/fwu.mk + +BL2_SOURCES += $(ZLIB_SOURCES) +endif + +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 + + +ifeq ($(STM32MP15),1) +BL2_SOURCES += plat/st/common/stm32mp_auth.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) +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}),) +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 + +ifeq ($(STM32MP_USE_STM32IMAGE)-$(AARCH32_SP),1-sp_min) +${BUILD_PLAT}/stm32mp1-%.o: ${BUILD_PLAT}/fdts/%.dtb plat/st/stm32mp1/stm32mp1.S bl2 ${BL32_DEP} + @echo " AS stm32mp1.S" + ${Q}${AS} ${ASFLAGS} ${TF_CFLAGS} \ + -DDTB_BIN_PATH=\"$<\" \ + -c $(word 2,$^) -o $@ +else +# 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 $@ +endif + +$(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/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c new file mode 100644 index 0000000..1fb44b4 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h b/arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h new file mode 100644 index 0000000..06752ef --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c new file mode 100644 index 0000000..ed8a448 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include + +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk new file mode 100644 index 0000000..c3fc2cb --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min-stm32mp1.mk @@ -0,0 +1,55 @@ +# +# 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 + +ifneq ($(STM32MP_USE_STM32IMAGE),1) +override ENABLE_PIE := 1 +BL32_CFLAGS += -fpie -DENABLE_PIE +BL32_LDFLAGS += $(PIE_LDFLAGS) +endif + +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/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c new file mode 100644 index 0000000..8106795 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c @@ -0,0 +1,197 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +/****************************************************************************** + * 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) +{ + 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", 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; +#if STM32MP_USE_STM32IMAGE + uintptr_t dt_addr = STM32MP_DTB_BASE; +#else + uintptr_t dt_addr = arg1; +#endif + + /* 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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S new file mode 100644 index 0000000..85caa0a --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#if STM32MP_USE_STM32IMAGE +#ifdef BL32_BIN_PATH +.section .bl32_image +.incbin BL32_BIN_PATH +#endif +#endif /* STM32MP_USE_STM32IMAGE */ + +.section .bl2_image +.incbin BL2_BIN_PATH + +.section .dtb_image +.incbin DTB_BIN_PATH diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S new file mode 100644 index 0000000..2254fee --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S @@ -0,0 +1,87 @@ +/* + * 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 +#include + +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. + */ +#if STM32MP_USE_STM32IMAGE + . = ( STM32MP_DTB_BASE - STM32MP_BINARY_BASE ); +#else + . = ( STM32MP_BL2_DTB_BASE - STM32MP_BINARY_BASE ); +#endif /* STM32MP_USE_STM32IMAGE */ + __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__ = .; + +#if STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) + /* + * bl32 will be settled by bl2. + * The strongest and only alignment constraint is 8 words to simplify + * memraise8 assembly code. + */ + . = ( STM32MP_BL32_BASE - STM32MP_BINARY_BASE ); + __BL32_IMAGE_START__ = .; + *(.bl32_image*) + __BL32_IMAGE_END__ = .; +#endif /* STM32MP_USE_STM32IMAGE && !defined(AARCH32_SP_OPTEE) */ + + __DATA_END__ = .; + } >RAM + + __TF_END__ = .; + +} +#endif /* STM32MP1_LD_S */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c new file mode 100644 index 0000000..b05de1c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2019-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#if STM32MP_RAW_NAND || STM32MP_SPI_NAND +static int get_data_from_otp(struct nand_device *nand_dev, bool is_slc) +{ + uint32_t nand_param; + + /* 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) { + return 0; + } + + if ((nand_param & NAND_PARAM_STORED_IN_OTP) == 0U) { + goto ecc; + } + + /* 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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c new file mode 100644 index 0000000..08e332a --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h new file mode 100644 index 0000000..d869978 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h @@ -0,0 +1,636 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#ifndef __ASSEMBLER__ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#endif + +#if !STM32MP_USE_STM32IMAGE +#include "stm32mp1_fip_def.h" +#else /* STM32MP_USE_STM32IMAGE */ +#include "stm32mp1_stm32image_def.h" +#endif /* STM32MP_USE_STM32IMAGE */ + +/******************************************************************************* + * 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_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 + +#define STM32MP_BL33_BASE (STM32MP_DDR_BASE + U(0x100000)) +#define STM32MP_BL33_MAX_SIZE U(0x400000) + +/* Define maximum page size for NAND devices */ +#define PLATFORM_MTD_MAX_PAGE_SIZE U(0x1000) + +/******************************************************************************* + * 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 + ******************************************************************************/ +#define USART1_BASE U(0x5C000000) +#define USART2_BASE U(0x4000E000) +#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" +#define NAND_OTP "nand_otp" +#define MONOTONIC_OTP "monotonic_otp" +#define UID_OTP "uid_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 blocs) */ +#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) + +/* MONOTONIC OTP */ +#define MAX_MONOTONIC_VALUE 32 + +/* UID OTP */ +#define UID_WORD_NB U(3) + +/******************************************************************************* + * STM32MP1 TAMP + ******************************************************************************/ +#define TAMP_BASE U(0x5C00A000) +#define TAMP_BKP_REGISTER_BASE (TAMP_BASE + U(0x100)) + +#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_NVMEM_LAYOUT_COMPAT "st,stm32-nvmem-layout" +#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" + +#endif /* STM32MP1_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c new file mode 100644 index 0000000..f2568ab --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h new file mode 100644 index 0000000..7a277fd --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h @@ -0,0 +1,106 @@ +/* + * Copyright (C) 2021-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_FIP_DEF_H +#define STM32MP1_FIP_DEF_H + +#define STM32MP_DDR_S_SIZE U(0x01E00000) /* 30 MB */ +#define STM32MP_DDR_SHMEM_SIZE U(0x00200000) /* 2 MB */ + +#if STM32MP13 +#define STM32MP_BL2_RO_SIZE U(0x00015000) /* 84 KB */ +#define STM32MP_BL2_SIZE U(0x00017000) /* 92 KB for BL2 */ +#define STM32MP_BL2_DTB_SIZE U(0x00004000) /* 16 KB for DTB */ +#endif /* STM32MP13 */ +#if STM32MP15 +#define STM32MP_BL2_RO_SIZE U(0x00011000) /* 68 KB */ +#define STM32MP_BL2_SIZE U(0x00016000) /* 88 KB for BL2 */ +#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 MTD devices + ******************************************************************************/ +#define STM32MP_NOR_FIP_OFFSET U(0x00080000) +#define STM32MP_NAND_FIP_OFFSET U(0x00200000) + +#endif /* STM32MP1_FIP_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c new file mode 100644 index 0000000..851a9cf --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +#include +#include +#include +#include +#include +#include + +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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S new file mode 100644 index 0000000..cac9752 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S @@ -0,0 +1,269 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include + +#define GPIO_TX_SHIFT (DEBUG_UART_TX_GPIO_PORT << 1) + + .globl platform_mem_init + .globl plat_report_exception + .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 + +func plat_report_exception +#if DEBUG + mov r8, lr + + /* Test if an abort occurred */ + cmp r0, #MODE32_abt + bne undef_inst_lbl + ldr r4, =abort_str + bl asm_print_str + mrs r4, lr_abt + sub r4, r4, #4 + b print_exception_info + +undef_inst_lbl: + /* 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 + + bx r8 +#else + bx lr +#endif +endfunc plat_report_exception + +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" +abort_str: + .asciz "\nAbort at: 0x" +undefined_str: + .asciz "\nUndefined instruction at: 0x" +exception_start_str: + .asciz "\nException mode=0x" +exception_end_str: + .asciz " at: 0x" +end_error_str: + .asciz "\n\r" +#endif diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c new file mode 100644 index 0000000..3892151 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +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, 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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c new file mode 100644 index 0000000..a9b9f4c --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c @@ -0,0 +1,740 @@ +/* + * Copyright (c) 2015-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include + +/* 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 U(0x0000FF00) +#define TAMP_BOOT_MODE_ITF_SHIFT 8 + +#define TAMP_BOOT_COUNTER_REG_ID U(21) + +#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) +{ + 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 STM32MP15 + case GPIO_BANK_J: + case GPIO_BANK_K: +#endif + return fdt_path_offset(fdt, "/soc/pin-controller"); +#if STM32MP15 + case GPIO_BANK_Z: + return fdt_path_offset(fdt, "/soc/pin-controller-z"); +#endif + default: + panic(); + } +} + +#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; + 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 + +#if STM32MP_USE_STM32IMAGE +/* Get the non-secure DDR size */ +uint32_t stm32mp_get_ddr_ns_size(void) +{ + static uint32_t ddr_ns_size; + uint32_t ddr_size; + + if (ddr_ns_size != 0U) { + return ddr_ns_size; + } + + ddr_size = dt_get_ddr_size(); + if ((ddr_size <= (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE)) || + (ddr_size > STM32MP_DDR_MAX_SIZE)) { + panic(); + } + + ddr_ns_size = ddr_size - (STM32MP_DDR_S_SIZE + STM32MP_DDR_SHMEM_SIZE); + + return ddr_ns_size; +} +#endif /* STM32MP_USE_STM32IMAGE */ + +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; +} + +#if !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT +void stm32mp1_fwu_set_boot_idx(void) +{ + clk_enable(RTCAPB); + mmio_write_32(tamp_bkpr(TAMP_BOOT_COUNTER_REG_ID), + plat_fwu_get_boot_idx()); + clk_disable(RTCAPB); +} +#endif /* !STM32MP_USE_STM32IMAGE && PSA_FWU_SUPPORT */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c new file mode 100644 index 0000000..98585dc --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c new file mode 100644 index 0000000..c84bffc --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include +#include +#include +#include +#include +#include +#include + +static unsigned int region_nb; + +static void init_tzc400_begin(unsigned int region0_attr) +{ + tzc400_init(STM32MP1_TZC_BASE); + tzc400_disable_filters(); + + /* Region 0 set to cover all DRAM at 0xC000_0000 */ + tzc400_configure_region0(region0_attr, 0); + + region_nb = 1U; +} + +static void init_tzc400_end(unsigned int action) +{ + tzc400_set_action(action); + tzc400_enable_filters(); +} + +static void tzc400_add_region(unsigned long long region_base, + unsigned long long region_top, bool sec) +{ + unsigned int sec_attr; + unsigned int nsaid_permissions; + + if (sec) { + sec_attr = TZC_REGION_S_RDWR; + nsaid_permissions = 0; + } else { + sec_attr = TZC_REGION_S_NONE; + nsaid_permissions = TZC_REGION_NSEC_ALL_ACCESS_RDWR; + } + + tzc400_configure_region(STM32MP1_FILTER_BIT_ALL, region_nb, region_base, + region_top, sec_attr, nsaid_permissions); + + region_nb++; +} + +/******************************************************************************* + * Initialize the TrustZone Controller. Configure Region 0 with Secure RW access + * and allow Non-Secure masters full access. + ******************************************************************************/ +static void init_tzc400(void) +{ + unsigned long long region_base, region_top; + unsigned long long ddr_base = STM32MP_DDR_BASE; + unsigned long long ddr_ns_size = + (unsigned long long)stm32mp_get_ddr_ns_size(); + unsigned long long ddr_ns_top = ddr_base + (ddr_ns_size - 1U); + unsigned long long ddr_top __unused; + + init_tzc400_begin(TZC_REGION_S_NONE); + + /* + * Region 1 set to cover all non-secure DRAM at 0xC000_0000. Apply the + * same configuration to all filters in the TZC. + */ + region_base = ddr_base; + region_top = ddr_ns_top; + tzc400_add_region(region_base, region_top, false); + +#ifdef AARCH32_SP_OPTEE + /* Region 2 set to cover all secure DRAM. */ + region_base = region_top + 1U; + region_top += STM32MP_DDR_S_SIZE; + tzc400_add_region(region_base, region_top, true); + + ddr_top = STM32MP_DDR_BASE + dt_get_ddr_size() - 1U; + if (region_top < ddr_top) { + /* Region 3 set to cover non-secure memory DRAM after BL32. */ + region_base = region_top + 1U; + region_top = ddr_top; + tzc400_add_region(region_base, region_top, false); + } +#endif + + /* + * Raise an interrupt (secure FIQ) if a NS device tries to access + * secure memory + */ + init_tzc400_end(TZC_ACTION_INT); +} + +/******************************************************************************* + * Initialize the TrustZone Controller. + * Early initialization create only one region with full access to secure. + * This setting is used before and during DDR initialization. + ******************************************************************************/ +static void early_init_tzc400(void) +{ + clk_enable(TZC1); + clk_enable(TZC2); + + /* Region 0 set to cover all DRAM secure at 0xC000_0000 */ + init_tzc400_begin(TZC_REGION_S_RDWR); + + /* Raise an exception if a NS device tries to access secure memory */ + init_tzc400_end(TZC_ACTION_ERR); +} + +/******************************************************************************* + * Initialize the secure environment. At this moment only the TrustZone + * Controller is initialized. + ******************************************************************************/ +void stm32mp1_arch_security_setup(void) +{ + early_init_tzc400(); +} + +/******************************************************************************* + * Initialize the secure environment. At this moment only the TrustZone + * Controller is initialized. + ******************************************************************************/ +void stm32mp1_security_setup(void) +{ + init_tzc400(); +} diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c new file mode 100644 index 0000000..a0ca697 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include + +#include +#include + +/* + * 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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c new file mode 100644 index 0000000..14e8e16 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h new file mode 100644 index 0000000..8efa342 --- /dev/null +++ b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2021, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef STM32MP1_STM32IMAGE_DEF_H +#define STM32MP1_STM32IMAGE_DEF_H + +#ifdef AARCH32_SP_OPTEE +#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(0) +#define STM32MP_DDR_SHMEM_SIZE U(0) +#endif + +#define STM32MP_BL2_SIZE U(0x0001C000) /* 112 KB for BL2 */ +#define STM32MP_DTB_SIZE U(0x00006000) /* 24 KB for DTB */ + +#ifdef AARCH32_SP_OPTEE +#define STM32MP_BL32_BASE STM32MP_SEC_SYSRAM_BASE + +#define STM32MP_BL2_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE) + +/* OP-TEE loads from SYSRAM base to BL2 DTB start address */ +#define STM32MP_OPTEE_BASE STM32MP_BL32_BASE +#define STM32MP_OPTEE_SIZE (STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL2_SIZE - STM32MP_DTB_SIZE) +#define STM32MP_BL32_SIZE STM32MP_OPTEE_SIZE +#else /* AARCH32_SP_OPTEE */ +#define STM32MP_BL32_SIZE U(0x00019000) /* 96 KB for BL32 */ + +#define STM32MP_BL32_BASE (STM32MP_SEC_SYSRAM_BASE + \ + STM32MP_SEC_SYSRAM_SIZE - \ + STM32MP_BL32_SIZE) + +#define STM32MP_BL2_BASE (STM32MP_BL32_BASE - \ + STM32MP_BL2_SIZE) +#endif /* AARCH32_SP_OPTEE */ + +/* DTB initialization value */ +#define STM32MP_DTB_BASE (STM32MP_BL2_BASE - \ + STM32MP_DTB_SIZE) + +/* + * MAX_MMAP_REGIONS is usually: + * BL stm32mp1_mmap size + mmap regions in *_plat_arch_setup + */ +#if defined(IMAGE_BL32) +#define MAX_MMAP_REGIONS 6 +#endif + +/******************************************************************************* + * STM32MP1 RAW partition offset for MTD devices + ******************************************************************************/ +#define STM32MP_NOR_BL33_OFFSET U(0x00080000) +#ifdef AARCH32_SP_OPTEE +#define STM32MP_NOR_TEEH_OFFSET U(0x00280000) +#define STM32MP_NOR_TEED_OFFSET U(0x002C0000) +#define STM32MP_NOR_TEEX_OFFSET U(0x00300000) +#endif + +#define STM32MP_NAND_BL33_OFFSET U(0x00200000) +#ifdef AARCH32_SP_OPTEE +#define STM32MP_NAND_TEEH_OFFSET U(0x00600000) +#define STM32MP_NAND_TEED_OFFSET U(0x00680000) +#define STM32MP_NAND_TEEX_OFFSET U(0x00700000) +#endif + +#endif /* STM32MP1_STM32IMAGE_DEF_H */ diff --git a/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c new file mode 100644 index 0000000..ff79428 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* + * 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", ®u_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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c new file mode 100644 index 0000000..59a0c17 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +/* 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/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c b/arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c new file mode 100644 index 0000000..0fe2d24 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/ti/k3/board/generic/board.mk b/arm-trusted-firmware/plat/ti/k3/board/generic/board.mk new file mode 100644 index 0000000..ef74cd6 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h b/arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h new file mode 100644 index 0000000..4ff687c --- /dev/null +++ b/arm-trusted-firmware/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 + +/* 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/arm-trusted-firmware/plat/ti/k3/board/lite/board.mk b/arm-trusted-firmware/plat/ti/k3/board/lite/board.mk new file mode 100644 index 0000000..76246be --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h b/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h new file mode 100644 index 0000000..18b7f42 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef BOARD_DEF_H +#define BOARD_DEF_H + +#include + +/* 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(0x0001c000) /* 112k */ + +#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/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c new file mode 100644 index 0000000..a0bfdee --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h new file mode 100644 index 0000000..f4b0b4b --- /dev/null +++ b/arm-trusted-firmware/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 + +/** + * 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/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c new file mode 100644 index 0000000..2c3313c --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c @@ -0,0 +1,1688 @@ +/* + * Texas Instruments System Control Interface 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 +#include +#include +#include + +#include + +#include +#include + +#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_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/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h new file mode 100644 index 0000000..c7b09b3 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h @@ -0,0 +1,216 @@ +/* + * Texas Instruments System Control Interface API + * Based on Linux and U-Boot implementation + * + * Copyright (C) 2018 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TI_SCI_H +#define TI_SCI_H + +#include +#include + +/** + * 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); + +/** + * 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/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h new file mode 100644 index 0000000..310bf45 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h @@ -0,0 +1,709 @@ +/* + * 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 Texas Instruments Incorporated - http://www.ti.com/ + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TI_SCI_PROTOCOL_H +#define TI_SCI_PROTOCOL_H + +#include + +/* 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 + +/* 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; + +#endif /* TI_SCI_PROTOCOL_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c b/arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c new file mode 100644 index 0000000..457c95d --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/ti/k3/common/k3_console.c b/arm-trusted-firmware/plat/ti/k3/common/k3_console.c new file mode 100644 index 0000000..8c44c17 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include + +#include + +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/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c b/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c new file mode 100644 index 0000000..1932eaa --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include + +/* The GICv3 driver only needs to be initialized in EL3 */ +uintptr_t rdistif_base_addrs[PLATFORM_CORE_COUNT]; + +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()); +} diff --git a/arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S b/arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S new file mode 100644 index 0000000..f4f7d18 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include + +#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/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c b/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c new file mode 100644 index 0000000..0500740 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/k3_psci.c @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +#include +#include +#include + +#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; +} + +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, + .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/arm-trusted-firmware/plat/ti/k3/common/k3_topology.c b/arm-trusted-firmware/plat/ti/k3/common/k3_topology.c new file mode 100644 index 0000000..139f1fd --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* 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/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk b/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk new file mode 100644 index 0000000..ab7366b --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/common/plat_common.mk @@ -0,0 +1,91 @@ +# +# Copyright (c) 2017-2020, 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 := 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)) + +# 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/arm-trusted-firmware/plat/ti/k3/include/k3_console.h b/arm-trusted-firmware/plat/ti/k3/include/k3_console.h new file mode 100644 index 0000000..6376ab3 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h b/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h new file mode 100644 index 0000000..2329a16 --- /dev/null +++ b/arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h @@ -0,0 +1,18 @@ +/* + * 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 + +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); + +#endif /* K3_GICV3_H */ diff --git a/arm-trusted-firmware/plat/ti/k3/include/plat_macros.S b/arm-trusted-firmware/plat/ti/k3/include/plat_macros.S new file mode 100644 index 0000000..38056b5 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/ti/k3/include/platform_def.h b/arm-trusted-firmware/plat/ti/k3/include/platform_def.h new file mode 100644 index 0000000..81a383a --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/ti/k3/platform.mk b/arm-trusted-firmware/plat/ti/k3/platform.mk new file mode 100644 index 0000000..2de21aa --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/xilinx/common/include/ipi.h b/arm-trusted-firmware/plat/xilinx/common/include/ipi.h new file mode 100644 index 0000000..483902e --- /dev/null +++ b/arm-trusted-firmware/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 + +/********************************************************************* + * IPI mailbox status macros + ********************************************************************/ +#define IPI_MB_STATUS_IDLE 0 +#define IPI_MB_STATUS_SEND_PENDING 1 +#define IPI_MB_STATUS_RECV_PENDING 2 + +/********************************************************************* + * IPI mailbox call is secure or not macros + ********************************************************************/ +#define IPI_MB_CALL_NOTSECURE 0 +#define IPI_MB_CALL_SECURE 1 + +/********************************************************************* + * 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_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/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h b/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h new file mode 100644 index 0000000..66e7933 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_STARTUP_H +#define PLAT_STARTUP_H + +/* For FSBL handover */ +enum fsbl_handoff { + FSBL_HANDOFF_SUCCESS = 0, + FSBL_HANDOFF_NO_STRUCT, + FSBL_HANDOFF_INVAL_STRUCT, + FSBL_HANDOFF_TOO_MANY_PARTS +}; + +enum fsbl_handoff fsbl_atf_handover(entry_point_info_t *bl32_image_ep_info, + entry_point_info_t *bl33_image_ep_info, + uint64_t atf_handoff_addr); + +#endif /* PLAT_STARTUP_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h new file mode 100644 index 0000000..e91bb8f --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_client.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. 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, unsigned int 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; + +#ifndef VERSAL_PLATFORM +enum pm_ret_status set_ocm_retention(void); +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 + +#endif /* PM_CLIENT_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h new file mode 100644 index 0000000..0c24a36 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_common.h @@ -0,0 +1,57 @@ +/* + * 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 +#include + +#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 */ + +/** + * 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 unsigned int pwrdn_mask; + const struct pm_ipi *ipi; +}; + +const struct pm_proc *pm_get_proc(unsigned int cpuid); + +#endif /* PM_COMMON_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h b/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h new file mode 100644 index 0000000..8c7738d --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_IPI_H +#define PM_IPI_H + +#include +#include "pm_common.h" + +#define IPI_BLOCKING 1 +#define IPI_NON_BLOCKING 0 + +int 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], + unsigned int *value, size_t count); +void pm_ipi_buff_read_callb(unsigned int *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/arm-trusted-firmware/plat/xilinx/common/ipi.c b/arm-trusted-firmware/plat/xilinx/common/ipi.c new file mode 100644 index 0000000..0b8020b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/ipi.c @@ -0,0 +1,216 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Xilinx IPI agent registers access management + */ + +#include +#include + +#include +#include +#include +#include + +#include +#include +#include + +/********************************************************************* + * 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; + + 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 = 0; + 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/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c new file mode 100644 index 0000000..f531158 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#include +#include +#include + +#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, void *cookie, + void *handle, uint64_t flags) +{ + int ret; + uint32_t ipi_local_id; + uint32_t ipi_remote_id; + unsigned int 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: + { + int 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: + { + int 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/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h b/arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h new file mode 100644 index 0000000..10682d8 --- /dev/null +++ b/arm-trusted-firmware/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 + +/********************************************************************* + * 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, void *cookie, void *handle, + uint64_t flags); + +#endif /* IPI_MAILBOX_SVC_H */ diff --git a/arm-trusted-firmware/plat/xilinx/common/plat_startup.c b/arm-trusted-firmware/plat/xilinx/common/plat_startup.c new file mode 100644 index 0000000..f02f41e --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/plat_startup.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2014-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include + + +/* + * 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 0 +#define FSBL_FLAGS_ESTATE_MASK (1 << FSBL_FLAGS_ESTATE_SHIFT) +#define FSBL_FLAGS_ESTATE_A64 0 +#define FSBL_FLAGS_ESTATE_A32 1 + +#define FSBL_FLAGS_ENDIAN_SHIFT 1 +#define FSBL_FLAGS_ENDIAN_MASK (1 << FSBL_FLAGS_ENDIAN_SHIFT) +#define FSBL_FLAGS_ENDIAN_LE 0 +#define FSBL_FLAGS_ENDIAN_BE 1 + +#define FSBL_FLAGS_TZ_SHIFT 2 +#define FSBL_FLAGS_TZ_MASK (1 << FSBL_FLAGS_TZ_SHIFT) +#define FSBL_FLAGS_NON_SECURE 0 +#define FSBL_FLAGS_SECURE 1 + +#define FSBL_FLAGS_EL_SHIFT 3 +#define FSBL_FLAGS_EL_MASK (3 << FSBL_FLAGS_EL_SHIFT) +#define FSBL_FLAGS_EL0 0 +#define FSBL_FLAGS_EL1 1 +#define FSBL_FLAGS_EL2 2 +#define FSBL_FLAGS_EL3 3 + +#define FSBL_FLAGS_CPU_SHIFT 5 +#define FSBL_FLAGS_CPU_MASK (3 << FSBL_FLAGS_CPU_SHIFT) +#define FSBL_FLAGS_A53_0 0 +#define FSBL_FLAGS_A53_1 1 +#define FSBL_FLAGS_A53_2 2 +#define FSBL_FLAGS_A53_3 3 + +#define FSBL_MAX_PARTITIONS 8 + +/* 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]; +}; + +/** + * @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 int 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 int 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 int 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 int 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 int 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; + assert((atf_handoff_addr < BL31_BASE) || + (atf_handoff_addr > (uint64_t)&__BL31_END__)); + 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; + int target_estate, target_secure; + int target_cpu, 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/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c b/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c new file mode 100644 index 0000000..03a7278 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c @@ -0,0 +1,291 @@ +/* + * Copyright (c) 2013-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include +#include +#include +#include + +#include "pm_ipi.h" + +#define ERROR_CODE_MASK 0xFFFFU + +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 + */ +int 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); + + return 0; +} + +/** + * 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) +{ + unsigned int offset = 0; + 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, + unsigned int *value, size_t count) +{ + size_t i; +#if IPI_CRC_CHECK + size_t j; + unsigned int 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(unsigned int *value, size_t count) +{ + size_t i; +#if IPI_CRC_CHECK + size_t j; + unsigned int response_payload[PAYLOAD_ARG_CNT]; +#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], + unsigned int *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) +{ + int 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, 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/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c new file mode 100644 index 0000000..897ed59 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include + +/* + * 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(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + return VERSAL_CPU_CLOCK; +} + diff --git a/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S b/arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S new file mode 100644 index 0000000..26eb052 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + + .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/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c b/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c new file mode 100644 index 0000000..78bfc29 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +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; + + if (VERSAL_CONSOLE_IS(pl011) || (VERSAL_CONSOLE_IS(pl011_1))) { + static console_t versal_runtime_console; + /* Initialize the console to provide early debug support */ + int rc = console_pl011_register((unsigned long)VERSAL_UART_BASE, + (unsigned int)VERSAL_UART_CLOCK, + (unsigned int)VERSAL_UART_BAUDRATE, + &versal_runtime_console); + if (rc == 0) { + panic(); + } + + console_set_scope(&versal_runtime_console, (unsigned int)(CONSOLE_FLAG_BOOT | + CONSOLE_FLAG_RUNTIME)); + } else if (VERSAL_CONSOLE_IS(dcc)) { + /* Initialize the dcc console for debug */ + int 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); + + 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 interrupt_type_handler_t type_el3_interrupt_handler; + +int request_intr_type_el3(uint32_t id, interrupt_type_handler_t handler) +{ + /* Validate 'handler'*/ + if (handler == NULL) { + return -EINVAL; + } + + type_el3_interrupt_handler = 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(); + /* Currently we support one interrupt */ + if (intr_id != PLAT_VERSAL_IPI_IRQ) { + WARN("Unexpected interrupt call: 0x%x\n", intr_id); + return 0; + } + + handler = type_el3_interrupt_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/arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h new file mode 100644 index 0000000..36a4380 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/********************************************************************* + * 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/arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S b/arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S new file mode 100644 index 0000000..3a52212 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h new file mode 100644 index 0000000..22c9d11 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h @@ -0,0 +1,26 @@ +/* + * 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 +#include +#include "pm_defs.h" + +#define NON_SECURE_FLAG 1U +#define SECURE_FLAG 0U + +#define VERSAL_TZ_VERSION_MAJOR 1 +#define VERSAL_TZ_VERSION_MINOR 0 +#define VERSAL_TZ_VERSION ((VERSAL_TZ_VERSION_MAJOR << 16) | \ + VERSAL_TZ_VERSION_MINOR) +#endif /* PLAT_PM_COMMON_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h b/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h new file mode 100644 index 0000000..d12d13a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PLAT_PRIVATE_H +#define PLAT_PRIVATE_H + +#include +#include + +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); + +unsigned int versal_calc_core_pos(u_register_t mpidr); +/* + * 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); + +#endif /* PLAT_PRIVATE_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h b/arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h new file mode 100644 index 0000000..83e5083 --- /dev/null +++ b/arm-trusted-firmware/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 +#include "versal_def.h" + +/******************************************************************************* + * Generic platform constants + ******************************************************************************/ + +/* Size of cacheable stacks */ +#define PLATFORM_STACK_SIZE 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/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h b/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h new file mode 100644 index 0000000..9372954 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2018-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef VERSAL_DEF_H +#define VERSAL_DEF_H + +#include +#include + +/* 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_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 + +/* CRL */ +#define VERSAL_CRL 0xFF5E0000 +#define VERSAL_CRL_TIMESTAMP_REF_CTRL (VERSAL_CRL + 0x14C) +#define VERSAL_CRL_RST_TIMESTAMP_OFFSET (VERSAL_CRL + 0x348) + +#define VERSAL_CRL_APB_TIMESTAMP_REF_CTRL_CLKACT_BIT (1 << 25) + +/* IOU SCNTRS */ +#define VERSAL_IOU_SCNTRS 0xFF140000 +#define VERSAL_IOU_SCNTRS_COUNTER_CONTROL_REG (VERSAL_IOU_SCNTRS + 0x0) +#define VERSAL_IOU_SCNTRS_BASE_FREQ (VERSAL_IOU_SCNTRS + 0x20) + +#define VERSAL_IOU_SCNTRS_CONTROL_EN 1 + +/******************************************************************************* + * 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 +#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/arm-trusted-firmware/plat/xilinx/versal/plat_psci.c b/arm-trusted-firmware/plat/xilinx/versal/plat_psci.c new file mode 100644 index 0000000..eb05e58 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +#include "pm_api_sys.h" +#include "pm_client.h" + +static uintptr_t versal_sec_entry; + +static int versal_pwr_domain_on(u_register_t mpidr) +{ + int 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((unsigned int)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) +{ + unsigned int state; + unsigned int 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) +{ + unsigned int 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) +{ + unsigned int 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 int versal_validate_power_state(unsigned int power_state, + psci_power_state_t *req_state) +{ + VERBOSE("%s: power_state: 0x%x\n", __func__, power_state); + + unsigned 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) != 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. + ******************************************************************************/ +int 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/arm-trusted-firmware/plat/xilinx/versal/plat_topology.c b/arm-trusted-firmware/plat/xilinx/versal/plat_topology.c new file mode 100644 index 0000000..66d4fae --- /dev/null +++ b/arm-trusted-firmware/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 + +static const unsigned char plat_power_domain_tree_desc[] = {1, PLATFORM_CORE_COUNT}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/plat_versal.c b/arm-trusted-firmware/plat/xilinx/versal/plat_versal.c new file mode 100644 index 0000000..54c35b6 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +int 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 (int)versal_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/platform.mk b/arm-trusted-firmware/plat/xilinx/versal/platform.mk new file mode 100644 index 0000000..a8b2c94 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/platform.mk @@ -0,0 +1,94 @@ +# 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 + +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/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c new file mode 100644 index 0000000..534d910 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c @@ -0,0 +1,1133 @@ +/* + * Copyright (c) 2019-2021, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* + * Versal system level PM-API functions and communication with PMC via + * IPI interrupts + */ + +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_defs.h" +#include "pm_svc_main.h" +#include "../drivers/arm/gic/v3/gicv3_private.h" + +/********************************************************************* + * Target module IDs macros + ********************************************************************/ +#define LIBPM_MODULE_ID 0x2U +#define LOADER_MODULE_ID 0x7U + +#define MODE 0x80000000U +/* default shutdown/reboot scope is system(2) */ +static unsigned int pm_shutdown_scope = XPM_SHUTDOWN_SUBTYPE_RST_SYSTEM; + +/** + * pm_get_shutdown_scope() - Get the currently set shutdown scope + * + * @return Shutdown scope value + */ +unsigned int pm_get_shutdown_scope(void) +{ + return pm_shutdown_scope; +} + +/** + * 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)); \ +} + +/* PM API functions */ + +/** + * pm_get_api_version() - Get version number of PMC PM firmware + * @version Returns 32-bit version number of PMC Power Management Firmware + * @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_get_api_version(unsigned int *version, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_API_VERSION); + return pm_ipi_send_sync(primary_proc, payload, version, 1); +} + +/** + * pm_init_finalize() - Call to notify PMC PM firmware that master has power + * management enabled and that it has finished its + * initialization + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Status returned by the PMU firmware + */ +enum pm_ret_status pm_init_finalize(uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMU */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_INIT_FINALIZE); + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * 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, + unsigned int latency, + unsigned int state, + uintptr_t address, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + unsigned int 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, + unsigned int latency, unsigned int 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_request_device() - Request a device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @qos Required Quality of Service + * @ack Flag to specify whether acknowledge 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_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_REQUEST_DEVICE, + device_id, capabilities, qos, ack); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_release_device() - Release a device + * @device_id Device ID + * @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_release_device(uint32_t device_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RELEASE_DEVICE, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_set_requirement() - Set requirement for the device + * @device_id Device ID + * @capabilities Requested capabilities for the device + * @latency Requested maximum latency + * @qos Required Quality of Service + * @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_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_SET_REQUIREMENT, + device_id, capabilities, latency, qos); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_get_device_status() - Get device's status + * @device_id Device ID + * @response Buffer to store device status response + * @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_get_device_status(uint32_t device_id, uint32_t *response, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_GET_DEVICE_STATUS, + device_id); + + return pm_ipi_send_sync(primary_proc, payload, response, 3); +} + +/** + * pm_reset_assert() - Assert/De-assert reset + * @reset Reset ID + * @assert Assert (1) or de-assert (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_reset_assert(uint32_t reset, bool assert, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_RESET_ASSERT, reset, + assert); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_reset_get_status() - Get current status of a reset line + * @reset Reset ID + * @status Returns current status of selected reset ID + * @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_reset_get_status(uint32_t reset, uint32_t *status, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_RESET_ASSERT, + reset); + + return pm_ipi_send_sync(primary_proc, payload, status, 1); +} + +/** + * 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 + * + * Read value from ipi buffer response buffer. + */ +void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag) +{ + /* Return if interrupt is not from PMU */ + if (pm_ipi_irq_status(primary_proc) == 0) { + return; + } + + pm_ipi_buff_read_callb(data, count); + pm_ipi_irq_clear(primary_proc); +} + +/** + * pm_pinctrl_request() - Request a pin + * @pin Pin ID + * @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_pinctrl_request(uint32_t pin, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_REQUEST, + pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_release() - Release a pin + * @pin Pin ID + * @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_pinctrl_release(uint32_t pin, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_PINCTRL_RELEASE, + pin); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_set_function() - Set pin function + * @pin Pin ID + * @function Function ID + * @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_pinctrl_set_function(uint32_t pin, uint32_t function, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_SET_FUNCTION, pin, function) + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_function() - Get function set on the pin + * @pin Pin ID + * @function Function set on the pin + * @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_pinctrl_get_function(uint32_t pin, uint32_t *function, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, + PM_PINCTRL_SET_FUNCTION, pin); + + return pm_ipi_send_sync(primary_proc, payload, function, 1); +} + +/** + * pm_pinctrl_set_pin_param() - Set configuration parameter for the pin + * @pin Pin ID + * @param Parameter ID + * @value 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_pinctrl_set_pin_param(uint32_t pin, 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_PINCTRL_CONFIG_PARAM_SET, pin, param, value); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_pinctrl_get_pin_param() - Get configuration parameter value for the pin + * @pin Pin ID + * @param Parameter ID + * @value Buffer to store 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_pinctrl_get_pin_param(uint32_t pin, 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_PINCTRL_CONFIG_PARAM_GET, pin, param); + + return pm_ipi_send_sync(primary_proc, payload, value, 1); +} + +/** + * pm_clock_enable() - Enable the clock + * @clk_id Clock ID + * @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_clock_enable(uint32_t clk_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_ENABLE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_disable() - Disable the clock + * @clk_id Clock ID + * @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_clock_disable(uint32_t clk_id, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_DISABLE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_state() - Get clock status + * @clk_id Clock ID + * @state: Buffer to store clock status (1: Enabled, 0:Disabled) + * @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_clock_get_state(uint32_t clk_id, uint32_t *state, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETSTATE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, state, 1); +} + +/** + * pm_clock_set_divider() - Set divider for the clock + * @clk_id Clock ID + * @divider Divider 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_clock_set_divider(uint32_t clk_id, uint32_t divider, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETDIVIDER, + clk_id, divider); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_divider() - Get divider value for the clock + * @clk_id Clock ID + * @divider: Buffer to store clock divider 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_clock_get_divider(uint32_t clk_id, uint32_t *divider, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETDIVIDER, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, divider, 1); +} + +/** + * pm_clock_set_parent() - Set parent for the clock + * @clk_id Clock ID + * @parent Parent ID + * @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_clock_set_parent(uint32_t clk_id, uint32_t parent, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_SETPARENT, + clk_id, parent); + + return pm_ipi_send_sync(primary_proc, payload, NULL, 0); +} + +/** + * pm_clock_get_parent() - Get parent value for the clock + * @clk_id Clock ID + * @parent: Buffer to store clock parent 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_clock_get_parent(uint32_t clk_id, uint32_t *parent, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETPARENT, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, parent, 1); +} +/** + * pm_clock_get_rate() - Get the rate value for the clock + * @clk_id Clock ID + * @rate: Buffer to store clock rate 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_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, PM_CLOCK_GETRATE, + clk_id); + + return pm_ipi_send_sync(primary_proc, payload, clk_rate, 2); +} + +/** + * pm_pll_set_param() - Set PLL parameter + * @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 + * @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 + * @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 + * @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 +* @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 +* +* This function returns requested data. +*/ +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; + 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, flag); + if (PM_RET_SUCCESS == ret) { + fw_api_version = version & 0xFFFFU; + if ((2U == fw_api_version) && + ((XPM_QID_CLOCK_GET_NAME == qid) || + (XPM_QID_PINCTRL_GET_FUNCTION_NAME == qid))) { + ret = pm_ipi_send_sync(primary_proc, payload, data, 8); + 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, 4); + } + } + return ret; +} +/** + * pm_api_ioctl() - PM IOCTL API for device control and configs + * @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 + * @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 success or error+reason + */ +enum pm_ret_status pm_api_ioctl(uint32_t device_id, uint32_t ioctl_id, + uint32_t arg1, uint32_t arg2, uint32_t *value, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + 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 */ + if (pm_register_sgi(arg1) != 0) { + return PM_RET_ERROR_ARGS; + } + gicd_write_irouter(gicv3_driver_data->gicd_base, + (unsigned int)PLAT_VERSAL_IPI_IRQ, MODE); + ret = PM_RET_SUCCESS; + break; + default: + /* Send request to the PMC */ + PM_PACK_PAYLOAD5(payload, LIBPM_MODULE_ID, flag, PM_IOCTL, + device_id, ioctl_id, arg1, arg2); + ret = pm_ipi_send_sync(primary_proc, payload, value, 1); + break; + } + + 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_get_chipid() - Read silicon ID registers + * @value Buffer for return values. Must be large enough + * to hold 8 bytes. + * @flag 0 - Call from secure source + * 1 - Call from non-secure source + * + * @return Returns silicon ID registers + */ +enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD1(payload, LIBPM_MODULE_ID, flag, PM_GET_CHIPID); + + return pm_ipi_send_sync(primary_proc, payload, value, 2); +} + +/** + * pm_feature_check() - Returns the supported API version if supported + * @api_id API ID to check + * @value Returned supported API version + * @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_feature_check(uint32_t api_id, unsigned int *version, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT], fw_api_version; + enum pm_ret_status status = PM_RET_ERROR_NOFEATURE; + + switch (api_id) { + case PM_GET_CALLBACK_DATA: + case PM_GET_TRUSTZONE_VERSION: + case PM_LOAD_PDI: + *version = (PM_API_BASE_VERSION << 16); + status = PM_RET_SUCCESS; + break; + case PM_GET_API_VERSION: + case PM_GET_DEVICE_STATUS: + case PM_GET_OP_CHARACTERISTIC: + case PM_REQ_SUSPEND: + case PM_SELF_SUSPEND: + case PM_FORCE_POWERDOWN: + case PM_ABORT_SUSPEND: + case PM_REQ_WAKEUP: + case PM_SET_WAKEUP_SOURCE: + case PM_SYSTEM_SHUTDOWN: + case PM_REQUEST_DEVICE: + case PM_RELEASE_DEVICE: + case PM_SET_REQUIREMENT: + case PM_RESET_ASSERT: + case PM_RESET_GET_STATUS: + case PM_GET_CHIPID: + case PM_PINCTRL_REQUEST: + case PM_PINCTRL_RELEASE: + case PM_PINCTRL_GET_FUNCTION: + case PM_PINCTRL_SET_FUNCTION: + case PM_PINCTRL_CONFIG_PARAM_GET: + case PM_PINCTRL_CONFIG_PARAM_SET: + case PM_IOCTL: + 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_CLOCK_GETRATE: + case PM_PLL_SET_PARAMETER: + case PM_PLL_GET_PARAMETER: + case PM_PLL_SET_MODE: + case PM_PLL_GET_MODE: + case PM_FEATURE_CHECK: + case PM_INIT_FINALIZE: + case PM_SET_MAX_LATENCY: + case PM_REGISTER_NOTIFIER: + *version = (PM_API_BASE_VERSION << 16); + status = PM_RET_SUCCESS; + break; + case PM_QUERY_DATA: + *version = (PM_API_QUERY_DATA_VERSION << 16); + status = PM_RET_SUCCESS; + break; + default: + *version = 0U; + status = PM_RET_ERROR_NOFEATURE; + break; + } + + if (status != PM_RET_SUCCESS) { + goto done; + } + + PM_PACK_PAYLOAD2(payload, LIBPM_MODULE_ID, flag, + PM_FEATURE_CHECK, api_id); + + status = pm_ipi_send_sync(primary_proc, payload, &fw_api_version, 1); + if (status != PM_RET_SUCCESS) { + goto done; + } + + *version |= fw_api_version; + + status = PM_RET_SUCCESS; + +done: + return status; +} + +/** + * 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_get_op_characteristic() - PM call to request operating characteristics + * of a device + * @device_id Device id + * @type Type of the operating characteristic + * (power, temperature and latency) + * @result Returns the operating characteristic for the requested device, + * specified by the type + * @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_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result, uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, + PM_GET_OP_CHARACTERISTIC, device_id, type); + return pm_ipi_send_sync(primary_proc, payload, result, 1); +} + +/** + * pm_set_max_latency() - PM call to change in the maximum wake-up latency + * requirements for a specific device currently + * used by that CPU. + * @device_id Device ID + * @latency Latency 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_set_max_latency(uint32_t device_id, uint32_t latency, + uint32_t flag) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + + /* Send request to the PMC */ + PM_PACK_PAYLOAD3(payload, LIBPM_MODULE_ID, flag, PM_SET_MAX_LATENCY, + device_id, latency); + + 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/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h new file mode 100644 index 0000000..5a92704 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h @@ -0,0 +1,99 @@ +/* + * Copyright (c) 2019-2020, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_API_SYS_H +#define PM_API_SYS_H + +#include +#include "pm_defs.h" + +/********************************************************** + * PM API function declarations + **********************************************************/ + +enum pm_ret_status pm_get_api_version(unsigned int *version, uint32_t flag); +enum pm_ret_status pm_init_finalize(uint32_t flag); +enum pm_ret_status pm_self_suspend(uint32_t nid, + unsigned int latency, + unsigned int 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, + unsigned int latency, + unsigned int 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); +enum pm_ret_status pm_request_device(uint32_t device_id, uint32_t capabilities, + uint32_t qos, uint32_t ack, uint32_t flag); +enum pm_ret_status pm_release_device(uint32_t device_id, uint32_t flag); +enum pm_ret_status pm_set_requirement(uint32_t device_id, uint32_t capabilities, + uint32_t latency, uint32_t qos, + uint32_t flag); +enum pm_ret_status pm_get_device_status(uint32_t device_id, uint32_t *response, + uint32_t flag); +enum pm_ret_status pm_reset_assert(uint32_t reset, bool assert, uint32_t flag); +enum pm_ret_status pm_reset_get_status(uint32_t reset, uint32_t *status, + uint32_t flag); +void pm_get_callbackdata(uint32_t *data, size_t count, uint32_t flag); +enum pm_ret_status pm_pinctrl_request(uint32_t pin, uint32_t flag); +enum pm_ret_status pm_pinctrl_release(uint32_t pin, uint32_t flag); +enum pm_ret_status pm_pinctrl_set_function(uint32_t pin, uint32_t function, + uint32_t flag); +enum pm_ret_status pm_pinctrl_get_function(uint32_t pin, uint32_t *function, + uint32_t flag); +enum pm_ret_status pm_pinctrl_set_pin_param(uint32_t pin, uint32_t param, + uint32_t value, uint32_t flag); +enum pm_ret_status pm_pinctrl_get_pin_param(uint32_t pin, uint32_t param, + uint32_t *value, uint32_t flag); +enum pm_ret_status pm_clock_enable(uint32_t clk_id, uint32_t flag); +enum pm_ret_status pm_clock_disable(uint32_t clk_id, uint32_t flag); +enum pm_ret_status pm_clock_get_state(uint32_t clk_id, uint32_t *state, + uint32_t flag); +enum pm_ret_status pm_clock_set_divider(uint32_t clk_id, uint32_t divider, + uint32_t flag); +enum pm_ret_status pm_clock_get_divider(uint32_t clk_id, uint32_t *divider, + uint32_t flag); +enum pm_ret_status pm_clock_set_parent(uint32_t clk_id, uint32_t parent, + uint32_t flag); +enum pm_ret_status pm_clock_get_parent(uint32_t clk_id, uint32_t *parent, + uint32_t flag); +enum pm_ret_status pm_clock_get_rate(uint32_t clk_id, uint32_t *clk_rate, + uint32_t flag); +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 *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); +unsigned int pm_get_shutdown_scope(void); +enum pm_ret_status pm_get_chipid(uint32_t *value, uint32_t flag); +enum pm_ret_status pm_feature_check(uint32_t api_id, unsigned int *version, + 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_get_op_characteristic(uint32_t device_id, + enum pm_opchar_type type, + uint32_t *result, uint32_t flag); +enum pm_ret_status pm_set_max_latency(uint32_t device_id, uint32_t latency, + 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); +#endif /* PM_API_SYS_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c new file mode 100644 index 0000000..4c1d340 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2019-2021, 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.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(unsigned int 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) && + (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] = (uint8_t)(!ret); + } + } + } +} + +/** + * 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, unsigned int 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 unsigned int 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) +{ + unsigned int 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(unsigned int cpuid) +{ + if (cpuid < ARRAY_SIZE(pm_procs_all)) { + return &pm_procs_all[cpuid]; + } + + return NULL; +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h new file mode 100644 index 0000000..08b46e2 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2019-2021, 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 + +/* PM API Versions */ +#define PM_API_BASE_VERSION 1U + +#define PM_API_QUERY_DATA_VERSION 2U + +/* PM API ids */ +#define PM_GET_API_VERSION 1U +#define PM_GET_DEVICE_STATUS 3U +#define PM_GET_OP_CHARACTERISTIC 4U +#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_REQUEST_DEVICE 13U +#define PM_RELEASE_DEVICE 14U +#define PM_SET_REQUIREMENT 15U +#define PM_SET_MAX_LATENCY 16U +#define PM_RESET_ASSERT 17U +#define PM_RESET_GET_STATUS 18U +#define PM_INIT_FINALIZE 21U +#define PM_GET_CHIPID 24U +#define PM_PINCTRL_REQUEST 28U +#define PM_PINCTRL_RELEASE 29U +#define PM_PINCTRL_GET_FUNCTION 30U +#define PM_PINCTRL_SET_FUNCTION 31U +#define PM_PINCTRL_CONFIG_PARAM_GET 32U +#define PM_PINCTRL_CONFIG_PARAM_SET 33U +#define PM_IOCTL 34U +#define PM_QUERY_DATA 35U +#define PM_CLOCK_ENABLE 36U +#define PM_CLOCK_DISABLE 37U +#define PM_CLOCK_GETSTATE 38U +#define PM_CLOCK_SETDIVIDER 39U +#define PM_CLOCK_GETDIVIDER 40U +#define PM_CLOCK_SETRATE 41U +#define PM_CLOCK_GETRATE 42U +#define PM_CLOCK_SETPARENT 43U +#define PM_CLOCK_GETPARENT 44U +#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 + +/* 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/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h new file mode 100644 index 0000000..1b82ec7 --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c new file mode 100644 index 0000000..b082acb --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c @@ -0,0 +1,436 @@ +/* + * Copyright (c) 2019-2021, Xilinx, 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 +#include +#include +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_ipi.h" +#include + +#define XSCUGIC_SGIR_EL1_INITID_SHIFT 24U +#define INVALID_SGI 0xFFU +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 unsigned int sgi = (unsigned int)INVALID_SGI; + +static uint64_t ipi_fiq_handler(uint32_t id, uint32_t flags, void *handle, + void *cookie) +{ + unsigned int cpu; + unsigned int reg; + + (void)plat_ic_acknowledge_interrupt(); + cpu = plat_my_core_pos() + 1U; + + if ((unsigned int)sgi != (unsigned int)INVALID_SGI) { + reg = (cpu | ((unsigned int)sgi << (unsigned int)XSCUGIC_SGIR_EL1_INITID_SHIFT)); + write_icc_asgi1r_el1(reg); + } + + /* 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. + * @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. + * + */ +int pm_register_sgi(unsigned int sgi_num) +{ + if ((unsigned int)sgi != (unsigned int)INVALID_SGI) { + return -EBUSY; + } + + if (sgi_num >= GICV3_MAX_SGI_TARGETS) { + return -EINVAL; + } + + sgi = (unsigned int)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. + */ +int pm_setup(void) +{ + int status, ret = 0; + + status = pm_ipi_init(primary_proc); + + if (status < 0) { + INFO("BL31: PM Service Init Failed, Error Code %d!\n", status); + ret = status; + } else { + 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"); + } + 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, void *cookie, void *handle, uint64_t flags) +{ + enum pm_ret_status ret; + + uint32_t pm_arg[4]; + uint32_t security_flag = SECURE_FLAG; + + /* Handle case where PM wasn't initialized properly */ + if (pm_up == false) { + 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); + + /* + * 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; + } + + switch (smc_fid & FUNCID_NUM_MASK) { + /* PM API Functions */ + 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, (uint64_t)ret); + + case PM_FORCE_POWERDOWN: + ret = pm_force_powerdown(pm_arg[0], pm_arg[1], security_flag); + 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], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_ABORT_SUSPEND: + ret = pm_abort_suspend(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_SYSTEM_SHUTDOWN: + ret = pm_system_shutdown(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQ_WAKEUP: + ret = pm_req_wakeup(pm_arg[0], pm_arg[1], pm_arg[2], pm_arg[3], + security_flag); + 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], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_REQUEST_DEVICE: + ret = pm_request_device(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RELEASE_DEVICE: + ret = pm_release_device(pm_arg[0], security_flag); + 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], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_API_VERSION: + { + uint32_t api_version; + + ret = pm_get_api_version(&api_version, security_flag); + SMC_RET1(handle, (u_register_t)PM_RET_SUCCESS | + ((u_register_t)api_version << 32)); + } + + case PM_GET_DEVICE_STATUS: + { + uint32_t buff[3]; + + ret = pm_get_device_status(pm_arg[0], buff, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)buff[0] << 32), + (u_register_t)buff[1] | ((u_register_t)buff[2] << 32)); + } + + case PM_RESET_ASSERT: + ret = pm_reset_assert(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_RESET_GET_STATUS: + { + uint32_t reset_status; + + ret = pm_reset_get_status(pm_arg[0], &reset_status, + security_flag); + SMC_RET1(handle, (u_register_t)ret | + ((u_register_t)reset_status << 32)); + } + + case PM_INIT_FINALIZE: + ret = pm_init_finalize(security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_GET_CALLBACK_DATA: + { + uint32_t result[4] = {0}; + + pm_get_callbackdata(result, ARRAY_SIZE(result), security_flag); + SMC_RET2(handle, + (u_register_t)result[0] | ((u_register_t)result[1] << 32), + (u_register_t)result[2] | ((u_register_t)result[3] << 32)); + } + + case PM_PINCTRL_REQUEST: + ret = pm_pinctrl_request(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_RELEASE: + ret = pm_pinctrl_release(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_GET_FUNCTION: + { + uint32_t value = 0; + + ret = pm_pinctrl_get_function(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_PINCTRL_SET_FUNCTION: + ret = pm_pinctrl_set_function(pm_arg[0], pm_arg[1], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PINCTRL_CONFIG_PARAM_GET: + { + uint32_t value; + + ret = pm_pinctrl_get_pin_param(pm_arg[0], pm_arg[1], &value, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_PINCTRL_CONFIG_PARAM_SET: + ret = pm_pinctrl_set_pin_param(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_IOCTL: + { + uint32_t value; + + ret = pm_api_ioctl(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_QUERY_DATA: + { + uint32_t data[8] = { 0 }; + + ret = pm_query_data(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], data, security_flag); + + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)data[0] << 32), + (u_register_t)data[1] | ((u_register_t)data[2] << 32)); + + } + case PM_CLOCK_ENABLE: + ret = pm_clock_enable(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_DISABLE: + ret = pm_clock_disable(pm_arg[0], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETSTATE: + { + uint32_t value; + + ret = pm_clock_get_state(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_SETDIVIDER: + ret = pm_clock_set_divider(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETDIVIDER: + { + uint32_t value; + + ret = pm_clock_get_divider(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_SETPARENT: + ret = pm_clock_set_parent(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_CLOCK_GETPARENT: + { + uint32_t value; + + ret = pm_clock_get_parent(pm_arg[0], &value, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value) << 32); + } + + case PM_CLOCK_GETRATE: + { + uint32_t rate[2] = { 0 }; + + ret = pm_clock_get_rate(pm_arg[0], rate, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)rate[0] << 32), + (u_register_t)rate[1] | ((u_register_t)0U << 32)); + } + + case PM_PLL_SET_PARAMETER: + ret = pm_pll_set_param(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_PARAMETER: + { + uint32_t value; + + ret = pm_pll_get_param(pm_arg[0], pm_arg[1], &value, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)value << 32)); + } + + case PM_PLL_SET_MODE: + ret = pm_pll_set_mode(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (uint64_t)ret); + + case PM_PLL_GET_MODE: + { + uint32_t mode; + + ret = pm_pll_get_mode(pm_arg[0], &mode, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)mode << 32)); + } + + case PM_GET_TRUSTZONE_VERSION: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)VERSAL_TZ_VERSION << 32)); + + case PM_GET_CHIPID: + { + uint32_t result[2]; + + ret = pm_get_chipid(result, security_flag); + SMC_RET2(handle, (u_register_t)ret | ((u_register_t)result[0] << 32), + (u_register_t)result[1] | ((u_register_t)0U << 32)); + } + + case PM_FEATURE_CHECK: + { + uint32_t version; + + ret = pm_feature_check(pm_arg[0], &version, security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)version << 32)); + } + + case PM_LOAD_PDI: + { + ret = pm_load_pdi(pm_arg[0], pm_arg[1], pm_arg[2], + security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + case PM_GET_OP_CHARACTERISTIC: + { + uint32_t result; + + ret = pm_get_op_characteristic(pm_arg[0], pm_arg[1], &result, + security_flag); + SMC_RET1(handle, (u_register_t)ret | ((u_register_t)result << 32)); + } + + case PM_SET_MAX_LATENCY: + { + ret = pm_set_max_latency(pm_arg[0], pm_arg[1], security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + case PM_REGISTER_NOTIFIER: + { + ret = pm_register_notifier(pm_arg[0], pm_arg[1], pm_arg[2], + pm_arg[3], security_flag); + SMC_RET1(handle, (u_register_t)ret); + } + + default: + WARN("Unimplemented PM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h new file mode 100644 index 0000000..4f8dc2b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h @@ -0,0 +1,18 @@ +/* + * Copyright (c) 2019, Xilinx, Inc. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PM_SVC_MAIN_H +#define PM_SVC_MAIN_H + +#include + +int pm_setup(void); +uint64_t pm_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); + +int pm_register_sgi(unsigned int sgi_num); +#endif /* PM_SVC_MAIN_H */ diff --git a/arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c b/arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c new file mode 100644 index 0000000..6f2ff94 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#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/arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c b/arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c new file mode 100644 index 0000000..08e7cf9 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +/****************************************************************************** + * 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 unsigned int 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/arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c b/arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c new file mode 100644 index 0000000..f99af82 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* 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/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c new file mode 100644 index 0000000..fae73cf --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c @@ -0,0 +1,380 @@ +/* + * Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#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 unsigned int 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; +} + +unsigned int 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 { + unsigned int id; + unsigned int 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_XCK26 0x4724093 + +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)) { + if (chipid[0] == SILICON_ID_XCK26) { + return "XCK26"; + } else { + return "XCZUUNKN"; + } + } + + if (!zynqmp_devices[i].evexists) + return zynqmp_devices[i].name; + + if (ver & ZYNQMP_PL_STATUS_MASK) + 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 unsigned int 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 + 1; +} + +static void zynqmp_print_platform_name(void) +{ + unsigned int ver = zynqmp_get_silicon_ver(); + unsigned int 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; + } + + NOTICE("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 + +unsigned int 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(); +} + +unsigned int plat_get_syscnt_freq2(void) +{ + unsigned int ver = zynqmp_get_silicon_ver(); + + if (ver == ZYNQMP_CSU_VERSION_QEMU) + return 65000000; + else + return mmio_read_32(IOU_SCNTRS_BASEFREQ); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S b/arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S new file mode 100644 index 0000000..d8439f7 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + + .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/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c new file mode 100644 index 0000000..58eee3a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c @@ -0,0 +1,263 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include + +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. 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 */ + int rc = console_dcc_register(); + if (rc == 0) { + panic(); + } + } + /* 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) { + VERBOSE("BL31: Secure code at 0x%lx\n", bl32_image_ep_info.pc); + } + if (bl33_image_ep_info.pc) { + 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 0x%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/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h new file mode 100644 index 0000000..bccd2f1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +/********************************************************************* + * 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 8 + +#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/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S new file mode 100644 index 0000000..bf1ff82 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#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/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h new file mode 100644 index 0000000..a57aebe --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#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/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h new file mode 100644 index 0000000..288cc53 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include +#include +#include + +void zynqmp_config_setup(void); + +unsigned int zynqmp_calc_core_pos(u_register_t mpidr); + +/* ZynqMP specific functions */ +unsigned int zynqmp_get_uart_clk(void); +unsigned int 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/arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h new file mode 100644 index 0000000..1c4daa1 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include + +#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 0xfffea000 +# define BL31_LIMIT 0x100000000 +#else +# define BL31_BASE 0x1000 +# define BL31_LIMIT 0x7ffff +#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 0x60000000 +# define BL32_LIMIT 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 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 0x100000 +#define XILINX_OF_BOARD_DTB_MAX_SIZE 0x200000 +#define PLAT_DDR_LOWMEM_MAX 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/arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h b/arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h new file mode 100644 index 0000000..7e58391 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#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 0xFF260000 +#define IOU_SCNTRS_BASEFREQ (IOU_SCNTRS_BASE + 0x20) + +/* APU registers and bitfields */ +#define APU_BASE 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 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 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 0xF9010000 +#define BASE_GICC_BASE 0xF9020000 +#define BASE_GICH_BASE 0xF9040000 +#define BASE_GICV_BASE 0xF9060000 + +#if ZYNQMP_WDT_RESTART +#define IRQ_SEC_IPI_APU 67 +#define IRQ_TTC3_1 77 +#define TTC3_BASE_ADDR 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 0xFF000000 +#define ZYNQMP_UART1_BASE 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 0xFF0 +#define ZYNQMP_RTL_VER_SHIFT 4 + +#define ZYNQMP_PS_VER_MASK 0xF +#define ZYNQMP_PS_VER_SHIFT 0 + +#define ZYNQMP_CSU_BASEADDR 0xFFCA0000 +#define ZYNQMP_CSU_IDCODE_OFFSET 0x40 + +#define ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT 0 +#define ZYNQMP_CSU_IDCODE_XILINX_ID_MASK (0xFFF << \ + ZYNQMP_CSU_IDCODE_XILINX_ID_SHIFT) +#define ZYNQMP_CSU_IDCODE_XILINX_ID 0x093 + +#define ZYNQMP_CSU_IDCODE_SVD_SHIFT 12 +#define ZYNQMP_CSU_IDCODE_SVD_MASK (0x7 << \ + ZYNQMP_CSU_IDCODE_SVD_SHIFT) +#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT 15 +#define ZYNQMP_CSU_IDCODE_DEVICE_CODE_MASK (0xF << \ + ZYNQMP_CSU_IDCODE_DEVICE_CODE_SHIFT) +#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT 19 +#define ZYNQMP_CSU_IDCODE_SUB_FAMILY_MASK (0x3 << \ + ZYNQMP_CSU_IDCODE_SUB_FAMILY_SHIFT) +#define ZYNQMP_CSU_IDCODE_FAMILY_SHIFT 21 +#define ZYNQMP_CSU_IDCODE_FAMILY_MASK (0x7F << \ + ZYNQMP_CSU_IDCODE_FAMILY_SHIFT) +#define ZYNQMP_CSU_IDCODE_FAMILY 0x23 + +#define ZYNQMP_CSU_IDCODE_REVISION_SHIFT 28 +#define ZYNQMP_CSU_IDCODE_REVISION_MASK (0xF << \ + ZYNQMP_CSU_IDCODE_REVISION_SHIFT) +#define ZYNQMP_CSU_IDCODE_REVISION 0 + +#define ZYNQMP_CSU_VERSION_OFFSET 0x44 + +/* Efuse */ +#define EFUSE_BASEADDR 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 0xFFC80000 + +/* RSA-CORE Module Base Address*/ +#define RSA_CORE_BASE 0xFFCE0000 + +#endif /* ZYNQMP_DEF_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c new file mode 100644 index 0000000..b2b473a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include "pm_api_sys.h" +#include "pm_client.h" + +uintptr_t zynqmp_sec_entry; + +void zynqmp_cpu_standby(plat_local_state_t cpu_state) +{ + VERBOSE("%s: cpu_state: 0x%x\n", __func__, cpu_state); + + dsb(); + wfi(); +} + +static int zynqmp_pwr_domain_on(u_register_t mpidr) +{ + unsigned int 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) +{ + unsigned int 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) +{ + unsigned int state; + unsigned int 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) +{ + unsigned int 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(); +} + +int zynqmp_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; +} + +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/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c new file mode 100644 index 0000000..aab24aa --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +static const unsigned char plat_power_domain_tree_desc[] = {1, 4}; + +const unsigned char *plat_get_power_domain_tree_desc(void) +{ + return plat_power_domain_tree_desc; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c b/arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c new file mode 100644 index 0000000..58a52a3 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +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 zynqmp_calc_core_pos(mpidr); +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk b/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk new file mode 100644 index 0000000..620bf6c --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/platform.mk @@ -0,0 +1,125 @@ +# +# Copyright (c) 2013-2021, ARM Limited and Contributors. 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 GICV2_G0_FOR_EL3 := 1 +override WARMBOOT_ENABLE_DCACHE_EARLY := 1 + +EL3_EXCEPTION_HANDLING := $(SDEI_SUPPORT) + +# Do not enable SVE +ENABLE_SVE_FOR_NS := 0 + +WORKAROUND_CVE_2017_5715 := 0 + +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 + +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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c new file mode 100644 index 0000000..4109830 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c @@ -0,0 +1,3010 @@ +/* + * 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 +#include + +#include +#include +#include + +#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 U(6) + +#define CLK_PARENTS_ID_LEN U(16) +#define CLK_TOPOLOGY_NODE_OFFSET U(16) +#define CLK_TOPOLOGY_PAYLOAD_LEN U(12) +#define CLK_PARENTS_PAYLOAD_LEN U(12) +#define CLK_TYPE_SHIFT U(2) +#define CLK_CLKFLAGS_SHIFT U(8) +#define CLK_TYPEFLAGS_SHIFT U(24) +#define CLK_TYPEFLAGS2_SHIFT U(4) +#define CLK_TYPEFLAGS_BITS_MASK U(0xFF) +#define CLK_TYPEFLAGS2_BITS_MASK U(0x0F00) +#define CLK_TYPEFLAGS_BITS U(8) + +#define CLK_EXTERNAL_PARENT (PARENT_CLK_EXTERNAL << CLK_PARENTS_ID_LEN) + +#define NA_MULT U(0) +#define NA_DIV U(0) +#define NA_SHIFT U(0) +#define NA_WIDTH U(0) +#define NA_CLK_FLAGS U(0) +#define NA_TYPE_FLAGS U(0) + +/* PLL nodes related definitions */ +#define PLL_PRESRC_MUX_SHIFT U(20) +#define PLL_PRESRC_MUX_WIDTH U(3) +#define PLL_POSTSRC_MUX_SHIFT U(24) +#define PLL_POSTSRC_MUX_WIDTH U(3) +#define PLL_DIV2_MUX_SHIFT U(16) +#define PLL_DIV2_MUX_WIDTH U(1) +#define PLL_BYPASS_MUX_SHIFT U(3) +#define PLL_BYPASS_MUX_WIDTH U(1) + +/* Peripheral nodes related definitions */ +/* Peripheral Clocks */ +#define PERIPH_MUX_SHIFT U(0) +#define PERIPH_MUX_WIDTH U(3) +#define PERIPH_DIV1_SHIFT U(8) +#define PERIPH_DIV1_WIDTH U(6) +#define PERIPH_DIV2_SHIFT U(16) +#define PERIPH_DIV2_WIDTH U(6) +#define PERIPH_GATE_SHIFT U(24) +#define PERIPH_GATE_WIDTH U(1) + +#define USB_GATE_SHIFT U(25) + +/* 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 U(1) +#define PLL_FRAC_OFFSET U(8) +#define PLL_FRAC_MODE U(1) +#define PLL_INT_MODE U(0) +#define PLL_FRAC_MODE_MASK U(0x80000000) +#define PLL_FRAC_MODE_SHIFT U(31) +#define PLL_FRAC_DATA_MASK U(0xFFFF) +#define PLL_FRAC_DATA_SHIFT U(0) +#define PLL_FBDIV_MASK U(0x7F00) +#define PLL_FBDIV_WIDTH U(7) +#define PLL_FBDIV_SHIFT U(8) + +#define CLK_PLL_RESET_ASSERT U(1) +#define CLK_PLL_RESET_RELEASE U(2) +#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; + unsigned int control_reg; + unsigned int 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 = ×tamp_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(unsigned int clock_id) +{ + unsigned int i; + + for (i = 0; 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 unsigned int pm_clock_type(unsigned int 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(unsigned int *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(unsigned int 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(unsigned int clock_id, + unsigned int index, + uint32_t *topology) +{ + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int 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(unsigned int clock_id, + uint32_t *mul, + uint32_t *div) +{ + struct pm_clock_node *clock_nodes; + uint8_t num_nodes; + unsigned int 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(unsigned int clock_id, + unsigned int index, + uint32_t *parents) +{ + unsigned int 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 < 3; 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(unsigned int 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 = (1 << (BIT(nodes[i].width) - 1)); + } else { + *max_div = BIT(nodes[i].width) - 1; + } + 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) + 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) + 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, + unsigned int *state) +{ + enum pm_ret_status status; + enum pm_pll_mode mode; + + if (!pll || !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, + unsigned int parent_index) +{ + if (!pll) + 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, + unsigned int *parent_index) +{ + if (!pll) + 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, + unsigned int mode) +{ + struct pm_pll *pll = pm_clock_get_pll(clock_id); + + if (!pll || (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, + unsigned int *mode) +{ + struct pm_pll *pll = pm_clock_get_pll(clock_id); + + if (!pll || !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(unsigned int 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(unsigned int 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; + } + } + + return 0; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h new file mode 100644 index 0000000..5efd63f --- /dev/null +++ b/arm-trusted-firmware/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 + +#include "pm_common.h" + +#define CLK_NAME_LEN U(15) +#define MAX_PARENTS U(100) +#define CLK_NA_PARENT -1 +#define CLK_DUMMY_PARENT -2 + +/* Flags for parent id */ +#define PARENT_CLK_SELF U(0) +#define PARENT_CLK_NODE1 U(1) +#define PARENT_CLK_NODE2 U(2) +#define PARENT_CLK_NODE3 U(3) +#define PARENT_CLK_NODE4 U(4) +#define PARENT_CLK_EXTERNAL U(5) +#define PARENT_CLK_MIO0_MIO77 U(6) + +#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, + CLK_RPLL, + CLK_APLL, + CLK_DPLL, + CLK_VPLL, + CLK_IOPLL_TO_FPD, + CLK_RPLL_TO_FPD, + CLK_APLL_TO_LPD, + CLK_DPLL_TO_LPD, + CLK_VPLL_TO_LPD, + CLK_ACPU, + CLK_ACPU_HALF, + CLK_DBG_FPD, + CLK_DBG_LPD, + CLK_DBG_TRACE, + CLK_DBG_TSTMP, + CLK_DP_VIDEO_REF, + CLK_DP_AUDIO_REF, + CLK_DP_STC_REF, + CLK_GDMA_REF, + CLK_DPDMA_REF, + CLK_DDR_REF, + CLK_SATA_REF, + CLK_PCIE_REF, + CLK_GPU_REF, + CLK_GPU_PP0_REF, + CLK_GPU_PP1_REF, + CLK_TOPSW_MAIN, + CLK_TOPSW_LSBUS, + CLK_GTGREF0_REF, + CLK_LPD_SWITCH, + CLK_LPD_LSBUS, + CLK_USB0_BUS_REF, + CLK_USB1_BUS_REF, + CLK_USB3_DUAL_REF, + CLK_USB0, + CLK_USB1, + CLK_CPU_R5, + CLK_CPU_R5_CORE, + CLK_CSU_SPB, + CLK_CSU_PLL, + CLK_PCAP, + CLK_IOU_SWITCH, + CLK_GEM_TSU_REF, + CLK_GEM_TSU, + CLK_GEM0_TX, + CLK_GEM1_TX, + CLK_GEM2_TX, + CLK_GEM3_TX, + CLK_GEM0_RX, + CLK_GEM1_RX, + CLK_GEM2_RX, + CLK_GEM3_RX, + CLK_QSPI_REF, + CLK_SDIO0_REF, + CLK_SDIO1_REF, + CLK_UART0_REF, + CLK_UART1_REF, + CLK_SPI0_REF, + CLK_SPI1_REF, + CLK_NAND_REF, + CLK_I2C0_REF, + CLK_I2C1_REF, + CLK_CAN0_REF, + CLK_CAN1_REF, + CLK_CAN0, + CLK_CAN1, + CLK_DLL_REF, + CLK_ADMA_REF, + CLK_TIMESTAMP_REF, + CLK_AMS_REF, + CLK_PL0_REF, + CLK_PL1_REF, + CLK_PL2_REF, + CLK_PL3_REF, + CLK_FPD_WDT, + CLK_IOPLL_INT, + CLK_IOPLL_PRE_SRC, + CLK_IOPLL_HALF, + CLK_IOPLL_INT_MUX, + CLK_IOPLL_POST_SRC, + CLK_RPLL_INT, + CLK_RPLL_PRE_SRC, + CLK_RPLL_HALF, + CLK_RPLL_INT_MUX, + CLK_RPLL_POST_SRC, + CLK_APLL_INT, + CLK_APLL_PRE_SRC, + CLK_APLL_HALF, + CLK_APLL_INT_MUX, + CLK_APLL_POST_SRC, + CLK_DPLL_INT, + CLK_DPLL_PRE_SRC, + CLK_DPLL_HALF, + CLK_DPLL_INT_MUX, + CLK_DPLL_POST_SRC, + CLK_VPLL_INT, + CLK_VPLL_PRE_SRC, + CLK_VPLL_HALF, + CLK_VPLL_INT_MUX, + CLK_VPLL_POST_SRC, + CLK_CAN0_MIO, + CLK_CAN1_MIO, + CLK_ACPU_FULL, + CLK_GEM0_REF, + CLK_GEM1_REF, + CLK_GEM2_REF, + CLK_GEM3_REF, + CLK_GEM0_REF_UNGATED, + CLK_GEM1_REF_UNGATED, + CLK_GEM2_REF_UNGATED, + CLK_GEM3_REF_UNGATED, + CLK_LPD_WDT, + END_OF_OUTPUT_CLKS, +}; + +#define CLK_MAX_OUTPUT_CLK (unsigned int)(END_OF_OUTPUT_CLKS) + +//External clock ids +enum { + EXT_CLK_PSS_REF = END_OF_OUTPUT_CLKS, + EXT_CLK_VIDEO, + EXT_CLK_PSS_ALT_REF, + EXT_CLK_AUX_REF, + EXT_CLK_GT_CRX_REF, + EXT_CLK_SWDT0, + EXT_CLK_SWDT1, + EXT_CLK_GEM0_TX_EMIO, + EXT_CLK_GEM1_TX_EMIO, + EXT_CLK_GEM2_TX_EMIO, + EXT_CLK_GEM3_TX_EMIO, + EXT_CLK_GEM0_RX_EMIO, + EXT_CLK_GEM1_RX_EMIO, + EXT_CLK_GEM2_RX_EMIO, + EXT_CLK_GEM3_RX_EMIO, + EXT_CLK_MIO50_OR_MIO51, + 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, + END_OF_CLKS, +}; + +#define CLK_MAX (unsigned int)(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(unsigned int clock_id, enum pm_clock_div_id div_id); + +void pm_api_clock_get_name(unsigned int clock_id, char *name); +enum pm_ret_status pm_api_clock_get_num_clocks(unsigned int *nclocks); +enum pm_ret_status pm_api_clock_get_topology(unsigned int clock_id, + unsigned int index, + uint32_t *topology); +enum pm_ret_status pm_api_clock_get_fixedfactor_params(unsigned int clock_id, + uint32_t *mul, + uint32_t *div); +enum pm_ret_status pm_api_clock_get_parents(unsigned int clock_id, + unsigned int index, + uint32_t *parents); +enum pm_ret_status pm_api_clock_get_attributes(unsigned int 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(unsigned int 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, + unsigned int *state); +enum pm_ret_status pm_clock_pll_set_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int parent_index); +enum pm_ret_status pm_clock_pll_get_parent(struct pm_pll *pll, + enum clock_id clock_id, + unsigned int *parent_index); +enum pm_ret_status pm_clock_set_pll_mode(enum clock_id clock_id, + unsigned int mode); +enum pm_ret_status pm_clock_get_pll_mode(enum clock_id clock_id, + unsigned int *mode); + +#endif /* PM_API_CLOCK_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c new file mode 100644 index 0000000..a87681b --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c @@ -0,0 +1,734 @@ +/* + * 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 +#include +#include +#include +#include + +#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(unsigned int *mode) +{ + unsigned int val; + + val = mmio_read_32(ZYNQMP_RPU_GLBL_CNTL); + val &= ZYNQMP_SLSPLIT_MASK; + if (val == 0) + *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(unsigned int mode) +{ + unsigned int 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, + unsigned int value) +{ + unsigned int 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(unsigned int value) +{ + unsigned int 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(unsigned int type, + unsigned int 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, + unsigned int value) +{ + unsigned int 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, + unsigned int type) +{ + unsigned int 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, + unsigned int value) +{ + unsigned int shift; + enum pm_ret_status ret; + unsigned int 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) == 0) { + 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 == 0) + 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 + (unsigned int pll, unsigned int 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 + (unsigned int pll, unsigned int *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 + (unsigned int pll, unsigned int 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 + (unsigned int pll, unsigned int *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(unsigned int index, + unsigned int 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(unsigned int index, + unsigned int *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(unsigned int index, + unsigned int 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(unsigned int index, + unsigned int value) +{ + unsigned int mask; + unsigned int regarr[] = {0xFD360000, + 0xFD360014, + 0xFD370000, + 0xFD370014, + 0xFD380000, + 0xFD380014, + 0xFD390000, + 0xFD390014, + 0xFD3a0000, + 0xFD3a0014, + 0xFD3b0000, + 0xFD3b0014, + 0xFF9b0000, + 0xFF9b0014, + 0xFD615000, + 0xFF419000, + }; + + 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(unsigned int index, + unsigned int *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(unsigned int 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, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *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; + int 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 / 32] |= BIT(ioctl_id % 32); + } + } + + return PM_RET_SUCCESS; +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h new file mode 100644 index 0000000..0c5f33f --- /dev/null +++ b/arm-trusted-firmware/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, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value); +enum pm_ret_status atf_ioctl_bitmask(uint32_t *bit_mask); +#endif /* PM_API_IOCTL_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c new file mode 100644 index 0000000..9a6b497 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c @@ -0,0 +1,2677 @@ +/* + * 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 + +#include +#include + +#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 (*groups)[]; + uint8_t regval; +}; + +/* Max groups for one pin */ +#define MAX_PIN_GROUPS U(13) + +struct zynqmp_pin_group { + uint16_t (*groups)[]; +}; + +static struct pinctrl_function pinctrl_functions[MAX_FUNCTION] = { + [PINCTRL_FUNC_CAN0] = { + .name = "can0", + .regval = 0x20, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_CAN1] = { + .name = "can1", + .regval = 0x20, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET0] = { + .name = "ethernet0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET1] = { + .name = "ethernet1", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET1_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET2] = { + .name = "ethernet2", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET2_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_ETHERNET3] = { + .name = "ethernet3", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_ETHERNET3_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_GEMTSU0] = { + .name = "gemtsu0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_GEMTSU0_0, + PINCTRL_GRP_GEMTSU0_1, + PINCTRL_GRP_GEMTSU0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_GPIO0] = { + .name = "gpio0", + .regval = 0x00, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_I2C0] = { + .name = "i2c0", + .regval = 0x40, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_I2C1] = { + .name = "i2c1", + .regval = 0x40, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO0] = { + .name = "mdio0", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO1] = { + .name = "mdio1", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO1_0, + PINCTRL_GRP_MDIO1_1, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO2] = { + .name = "mdio2", + .regval = 0xa0, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO2_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_MDIO3] = { + .name = "mdio3", + .regval = 0xc0, + .groups = &((uint16_t []) { + PINCTRL_GRP_MDIO3_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI0] = { + .name = "qspi0", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI_FBCLK] = { + .name = "qspi_fbclk", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_FBCLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_QSPI_SS] = { + .name = "qspi_ss", + .regval = 0x02, + .groups = &((uint16_t []) { + PINCTRL_GRP_QSPI_SS, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI0] = { + .name = "spi0", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI0_0, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_SPI0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI1] = { + .name = "spi1", + .regval = 0x80, + .groups = &((uint16_t []) { + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_SPI1_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI0_SS] = { + .name = "spi0_ss", + .regval = 0x80, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SPI1_SS] = { + .name = "spi1_ss", + .regval = 0x80, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0] = { + .name = "sdio0", + .regval = 0x08, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_PC] = { + .name = "sdio0_pc", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_PC, + PINCTRL_GRP_SDIO0_1_PC, + PINCTRL_GRP_SDIO0_2_PC, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_CD] = { + .name = "sdio0_cd", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_CD, + PINCTRL_GRP_SDIO0_1_CD, + PINCTRL_GRP_SDIO0_2_CD, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO0_WP] = { + .name = "sdio0_wp", + .regval = 0x08, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO0_0_WP, + PINCTRL_GRP_SDIO0_1_WP, + PINCTRL_GRP_SDIO0_2_WP, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1] = { + .name = "sdio1", + .regval = 0x10, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_PC] = { + .name = "sdio1_pc", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_PC, + PINCTRL_GRP_SDIO1_1_PC, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_CD] = { + .name = "sdio1_cd", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_CD, + PINCTRL_GRP_SDIO1_1_CD, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SDIO1_WP] = { + .name = "sdio1_wp", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_SDIO1_0_WP, + PINCTRL_GRP_SDIO1_1_WP, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0] = { + .name = "nand0", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_CE] = { + .name = "nand0_ce", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_CE, + PINCTRL_GRP_NAND0_1_CE, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_RB] = { + .name = "nand0_rb", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_NAND0_1_RB, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_NAND0_DQS] = { + .name = "nand0_dqs", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_NAND0_0_DQS, + PINCTRL_GRP_NAND0_1_DQS, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC0_CLK] = { + .name = "ttc0_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC0_WAV] = { + .name = "ttc0_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC1_CLK] = { + .name = "ttc1_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC1_WAV] = { + .name = "ttc1_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC2_CLK] = { + .name = "ttc2_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC2_WAV] = { + .name = "ttc2_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC3_CLK] = { + .name = "ttc3_clk", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TTC3_WAV] = { + .name = "ttc3_wav", + .regval = 0xa0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_UART0] = { + .name = "uart0", + .regval = 0xc0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_UART1] = { + .name = "uart1", + .regval = 0xc0, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_USB0] = { + .name = "usb0", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_USB0_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_USB1] = { + .name = "usb1", + .regval = 0x04, + .groups = &((uint16_t []) { + PINCTRL_GRP_USB1_0, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT0_CLK] = { + .name = "swdt0_clk", + .regval = 0x60, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT0_RST] = { + .name = "swdt0_rst", + .regval = 0x60, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT1_CLK] = { + .name = "swdt1_clk", + .regval = 0x60, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_SWDT1_RST] = { + .name = "swdt1_rst", + .regval = 0x60, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PMU0] = { + .name = "pmu0", + .regval = 0x08, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PCIE0] = { + .name = "pcie0", + .regval = 0x04, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_CSU0] = { + .name = "csu0", + .regval = 0x18, + .groups = &((uint16_t []) { + 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, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_DPAUX0] = { + .name = "dpaux0", + .regval = 0x18, + .groups = &((uint16_t []) { + PINCTRL_GRP_DPAUX0_0, + PINCTRL_GRP_DPAUX0_1, + PINCTRL_GRP_DPAUX0_2, + PINCTRL_GRP_DPAUX0_3, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_PJTAG0] = { + .name = "pjtag0", + .regval = 0x60, + .groups = &((uint16_t []) { + PINCTRL_GRP_PJTAG0_0, + PINCTRL_GRP_PJTAG0_1, + PINCTRL_GRP_PJTAG0_2, + PINCTRL_GRP_PJTAG0_3, + PINCTRL_GRP_PJTAG0_4, + PINCTRL_GRP_PJTAG0_5, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TRACE0] = { + .name = "trace0", + .regval = 0xe0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TRACE0_0, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_TRACE0_2, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TRACE0_CLK] = { + .name = "trace0_clk", + .regval = 0xe0, + .groups = &((uint16_t []) { + PINCTRL_GRP_TRACE0_0_CLK, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_TRACE0_2_CLK, + END_OF_GROUPS, + }), + }, + [PINCTRL_FUNC_TESTSCAN0] = { + .name = "testscan0", + .regval = 0x10, + .groups = &((uint16_t []) { + PINCTRL_GRP_TESTSCAN0_0, + END_OF_GROUPS, + }), + }, +}; + +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(unsigned int *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(unsigned int *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(unsigned int fid, + unsigned int *ngroups) +{ + int i = 0; + uint16_t *grps; + + if (fid >= MAX_FUNCTION) + return PM_RET_ERROR_ARGS; + + *ngroups = 0; + + grps = *pinctrl_functions[fid].groups; + if (grps == NULL) + return PM_RET_SUCCESS; + + while (grps[i++] != (uint16_t)END_OF_GROUPS) + (*ngroups)++; + + 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(unsigned int 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(unsigned int fid, + unsigned int index, + uint16_t *groups) +{ + unsigned int i; + uint16_t *grps; + + if (fid >= MAX_FUNCTION) + return PM_RET_ERROR_ARGS; + + memset(groups, END_OF_GROUPS, GROUPS_PAYLOAD_LEN); + + grps = *pinctrl_functions[fid].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; +} + +/** + * 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(unsigned int pin, + unsigned int index, + uint16_t *groups) +{ + unsigned int 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) + 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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h new file mode 100644 index 0000000..2b8fca3 --- /dev/null +++ b/arm-trusted-firmware/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 U(16) +#define GROUPS_PAYLOAD_LEN U(12) +#define NUM_GROUPS_PER_RESP U(6) +#define END_OF_FUNCTION "END_OF_FUNCTION" +#define END_OF_GROUPS -1 +#define PINCTRL_GRP_RESERVED -2 + +//pinctrl function ids +enum { + PINCTRL_FUNC_CAN0, + PINCTRL_FUNC_CAN1, + PINCTRL_FUNC_ETHERNET0, + PINCTRL_FUNC_ETHERNET1, + PINCTRL_FUNC_ETHERNET2, + PINCTRL_FUNC_ETHERNET3, + PINCTRL_FUNC_GEMTSU0, + PINCTRL_FUNC_GPIO0, + PINCTRL_FUNC_I2C0, + PINCTRL_FUNC_I2C1, + PINCTRL_FUNC_MDIO0, + PINCTRL_FUNC_MDIO1, + PINCTRL_FUNC_MDIO2, + PINCTRL_FUNC_MDIO3, + PINCTRL_FUNC_QSPI0, + PINCTRL_FUNC_QSPI_FBCLK, + PINCTRL_FUNC_QSPI_SS, + PINCTRL_FUNC_SPI0, + PINCTRL_FUNC_SPI1, + PINCTRL_FUNC_SPI0_SS, + PINCTRL_FUNC_SPI1_SS, + PINCTRL_FUNC_SDIO0, + PINCTRL_FUNC_SDIO0_PC, + PINCTRL_FUNC_SDIO0_CD, + PINCTRL_FUNC_SDIO0_WP, + PINCTRL_FUNC_SDIO1, + PINCTRL_FUNC_SDIO1_PC, + PINCTRL_FUNC_SDIO1_CD, + PINCTRL_FUNC_SDIO1_WP, + PINCTRL_FUNC_NAND0, + PINCTRL_FUNC_NAND0_CE, + PINCTRL_FUNC_NAND0_RB, + PINCTRL_FUNC_NAND0_DQS, + PINCTRL_FUNC_TTC0_CLK, + PINCTRL_FUNC_TTC0_WAV, + PINCTRL_FUNC_TTC1_CLK, + PINCTRL_FUNC_TTC1_WAV, + PINCTRL_FUNC_TTC2_CLK, + PINCTRL_FUNC_TTC2_WAV, + PINCTRL_FUNC_TTC3_CLK, + PINCTRL_FUNC_TTC3_WAV, + PINCTRL_FUNC_UART0, + PINCTRL_FUNC_UART1, + PINCTRL_FUNC_USB0, + PINCTRL_FUNC_USB1, + PINCTRL_FUNC_SWDT0_CLK, + PINCTRL_FUNC_SWDT0_RST, + PINCTRL_FUNC_SWDT1_CLK, + PINCTRL_FUNC_SWDT1_RST, + PINCTRL_FUNC_PMU0, + PINCTRL_FUNC_PCIE0, + PINCTRL_FUNC_CSU0, + PINCTRL_FUNC_DPAUX0, + PINCTRL_FUNC_PJTAG0, + PINCTRL_FUNC_TRACE0, + PINCTRL_FUNC_TRACE0_CLK, + PINCTRL_FUNC_TESTSCAN0, + END_FUNCTION, +}; + +#define MAX_FUNCTION (unsigned int)(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, +}; + +#define MAX_PIN (unsigned int)(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_0_SS0, + PINCTRL_GRP_SPI0_0_SS1, + PINCTRL_GRP_SPI0_0_SS2, + PINCTRL_GRP_SPI0_1, + PINCTRL_GRP_SPI0_1_SS0, + PINCTRL_GRP_SPI0_1_SS1, + PINCTRL_GRP_SPI0_1_SS2, + PINCTRL_GRP_SPI0_2, + PINCTRL_GRP_SPI0_2_SS0, + PINCTRL_GRP_SPI0_2_SS1, + PINCTRL_GRP_SPI0_2_SS2, + PINCTRL_GRP_SPI0_3, + PINCTRL_GRP_SPI0_3_SS0, + PINCTRL_GRP_SPI0_3_SS1, + PINCTRL_GRP_SPI0_3_SS2, + PINCTRL_GRP_SPI0_4, + PINCTRL_GRP_SPI0_4_SS0, + PINCTRL_GRP_SPI0_4_SS1, + PINCTRL_GRP_SPI0_4_SS2, + PINCTRL_GRP_SPI0_5, + PINCTRL_GRP_SPI0_5_SS0, + PINCTRL_GRP_SPI0_5_SS1, + PINCTRL_GRP_SPI0_5_SS2, + PINCTRL_GRP_SPI1_0, + PINCTRL_GRP_SPI1_0_SS0, + PINCTRL_GRP_SPI1_0_SS1, + PINCTRL_GRP_SPI1_0_SS2, + PINCTRL_GRP_SPI1_1, + PINCTRL_GRP_SPI1_1_SS0, + PINCTRL_GRP_SPI1_1_SS1, + PINCTRL_GRP_SPI1_1_SS2, + PINCTRL_GRP_SPI1_2, + PINCTRL_GRP_SPI1_2_SS0, + PINCTRL_GRP_SPI1_2_SS1, + PINCTRL_GRP_SPI1_2_SS2, + PINCTRL_GRP_SPI1_3, + PINCTRL_GRP_SPI1_3_SS0, + PINCTRL_GRP_SPI1_3_SS1, + PINCTRL_GRP_SPI1_3_SS2, + PINCTRL_GRP_SPI1_4, + PINCTRL_GRP_SPI1_4_SS0, + PINCTRL_GRP_SPI1_4_SS1, + PINCTRL_GRP_SPI1_4_SS2, + PINCTRL_GRP_SPI1_5, + 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_0_CD, + PINCTRL_GRP_SDIO0_0_WP, + PINCTRL_GRP_SDIO0_1_PC, + PINCTRL_GRP_SDIO0_1_CD, + PINCTRL_GRP_SDIO0_1_WP, + PINCTRL_GRP_SDIO0_2_PC, + PINCTRL_GRP_SDIO0_2_CD, + 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_0_CD, + PINCTRL_GRP_SDIO1_0_WP, + PINCTRL_GRP_SDIO1_1_PC, + PINCTRL_GRP_SDIO1_1_CD, + PINCTRL_GRP_SDIO1_1_WP, + PINCTRL_GRP_NAND0_0, + PINCTRL_GRP_NAND0_0_CE, + PINCTRL_GRP_NAND0_0_RB, + PINCTRL_GRP_NAND0_0_DQS, + PINCTRL_GRP_NAND0_1_CE, + PINCTRL_GRP_NAND0_1_RB, + 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_0_WAV, + PINCTRL_GRP_TTC0_1_CLK, + PINCTRL_GRP_TTC0_1_WAV, + PINCTRL_GRP_TTC0_2_CLK, + PINCTRL_GRP_TTC0_2_WAV, + PINCTRL_GRP_TTC0_3_CLK, + PINCTRL_GRP_TTC0_3_WAV, + PINCTRL_GRP_TTC0_4_CLK, + PINCTRL_GRP_TTC0_4_WAV, + PINCTRL_GRP_TTC0_5_CLK, + PINCTRL_GRP_TTC0_5_WAV, + PINCTRL_GRP_TTC0_6_CLK, + PINCTRL_GRP_TTC0_6_WAV, + PINCTRL_GRP_TTC0_7_CLK, + PINCTRL_GRP_TTC0_7_WAV, + PINCTRL_GRP_TTC0_8_CLK, + PINCTRL_GRP_TTC0_8_WAV, + PINCTRL_GRP_TTC1_0_CLK, + PINCTRL_GRP_TTC1_0_WAV, + PINCTRL_GRP_TTC1_1_CLK, + PINCTRL_GRP_TTC1_1_WAV, + PINCTRL_GRP_TTC1_2_CLK, + PINCTRL_GRP_TTC1_2_WAV, + PINCTRL_GRP_TTC1_3_CLK, + PINCTRL_GRP_TTC1_3_WAV, + PINCTRL_GRP_TTC1_4_CLK, + PINCTRL_GRP_TTC1_4_WAV, + PINCTRL_GRP_TTC1_5_CLK, + PINCTRL_GRP_TTC1_5_WAV, + PINCTRL_GRP_TTC1_6_CLK, + PINCTRL_GRP_TTC1_6_WAV, + PINCTRL_GRP_TTC1_7_CLK, + PINCTRL_GRP_TTC1_7_WAV, + PINCTRL_GRP_TTC1_8_CLK, + PINCTRL_GRP_TTC1_8_WAV, + PINCTRL_GRP_TTC2_0_CLK, + PINCTRL_GRP_TTC2_0_WAV, + PINCTRL_GRP_TTC2_1_CLK, + PINCTRL_GRP_TTC2_1_WAV, + PINCTRL_GRP_TTC2_2_CLK, + PINCTRL_GRP_TTC2_2_WAV, + PINCTRL_GRP_TTC2_3_CLK, + PINCTRL_GRP_TTC2_3_WAV, + PINCTRL_GRP_TTC2_4_CLK, + PINCTRL_GRP_TTC2_4_WAV, + PINCTRL_GRP_TTC2_5_CLK, + PINCTRL_GRP_TTC2_5_WAV, + PINCTRL_GRP_TTC2_6_CLK, + PINCTRL_GRP_TTC2_6_WAV, + PINCTRL_GRP_TTC2_7_CLK, + PINCTRL_GRP_TTC2_7_WAV, + PINCTRL_GRP_TTC2_8_CLK, + PINCTRL_GRP_TTC2_8_WAV, + PINCTRL_GRP_TTC3_0_CLK, + PINCTRL_GRP_TTC3_0_WAV, + PINCTRL_GRP_TTC3_1_CLK, + PINCTRL_GRP_TTC3_1_WAV, + PINCTRL_GRP_TTC3_2_CLK, + PINCTRL_GRP_TTC3_2_WAV, + PINCTRL_GRP_TTC3_3_CLK, + PINCTRL_GRP_TTC3_3_WAV, + PINCTRL_GRP_TTC3_4_CLK, + PINCTRL_GRP_TTC3_4_WAV, + PINCTRL_GRP_TTC3_5_CLK, + PINCTRL_GRP_TTC3_5_WAV, + PINCTRL_GRP_TTC3_6_CLK, + PINCTRL_GRP_TTC3_6_WAV, + PINCTRL_GRP_TTC3_7_CLK, + PINCTRL_GRP_TTC3_7_WAV, + PINCTRL_GRP_TTC3_8_CLK, + PINCTRL_GRP_TTC3_8_WAV, + PINCTRL_GRP_SWDT0_0_CLK, + PINCTRL_GRP_SWDT0_0_RST, + PINCTRL_GRP_SWDT0_1_CLK, + PINCTRL_GRP_SWDT0_1_RST, + PINCTRL_GRP_SWDT0_2_CLK, + PINCTRL_GRP_SWDT0_2_RST, + PINCTRL_GRP_SWDT0_3_CLK, + PINCTRL_GRP_SWDT0_3_RST, + PINCTRL_GRP_SWDT0_4_CLK, + PINCTRL_GRP_SWDT0_4_RST, + PINCTRL_GRP_SWDT0_5_CLK, + PINCTRL_GRP_SWDT0_5_RST, + PINCTRL_GRP_SWDT0_6_CLK, + PINCTRL_GRP_SWDT0_6_RST, + PINCTRL_GRP_SWDT0_7_CLK, + PINCTRL_GRP_SWDT0_7_RST, + PINCTRL_GRP_SWDT0_8_CLK, + PINCTRL_GRP_SWDT0_8_RST, + PINCTRL_GRP_SWDT0_9_CLK, + PINCTRL_GRP_SWDT0_9_RST, + PINCTRL_GRP_SWDT0_10_CLK, + PINCTRL_GRP_SWDT0_10_RST, + PINCTRL_GRP_SWDT0_11_CLK, + PINCTRL_GRP_SWDT0_11_RST, + PINCTRL_GRP_SWDT0_12_CLK, + PINCTRL_GRP_SWDT0_12_RST, + PINCTRL_GRP_SWDT1_0_CLK, + PINCTRL_GRP_SWDT1_0_RST, + PINCTRL_GRP_SWDT1_1_CLK, + PINCTRL_GRP_SWDT1_1_RST, + PINCTRL_GRP_SWDT1_2_CLK, + PINCTRL_GRP_SWDT1_2_RST, + PINCTRL_GRP_SWDT1_3_CLK, + PINCTRL_GRP_SWDT1_3_RST, + PINCTRL_GRP_SWDT1_4_CLK, + PINCTRL_GRP_SWDT1_4_RST, + PINCTRL_GRP_SWDT1_5_CLK, + PINCTRL_GRP_SWDT1_5_RST, + PINCTRL_GRP_SWDT1_6_CLK, + PINCTRL_GRP_SWDT1_6_RST, + PINCTRL_GRP_SWDT1_7_CLK, + PINCTRL_GRP_SWDT1_7_RST, + PINCTRL_GRP_SWDT1_8_CLK, + PINCTRL_GRP_SWDT1_8_RST, + PINCTRL_GRP_SWDT1_9_CLK, + PINCTRL_GRP_SWDT1_9_RST, + PINCTRL_GRP_SWDT1_10_CLK, + PINCTRL_GRP_SWDT1_10_RST, + PINCTRL_GRP_SWDT1_11_CLK, + PINCTRL_GRP_SWDT1_11_RST, + PINCTRL_GRP_SWDT1_12_CLK, + 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_0_CLK, + PINCTRL_GRP_TRACE0_1, + PINCTRL_GRP_TRACE0_1_CLK, + PINCTRL_GRP_TRACE0_2, + 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(unsigned int fid, char *name); +enum pm_ret_status pm_api_pinctrl_get_function_groups(unsigned int fid, + unsigned int index, + uint16_t *groups); +enum pm_ret_status pm_api_pinctrl_get_pin_groups(unsigned int pin, + unsigned int index, + uint16_t *groups); +enum pm_ret_status pm_api_pinctrl_get_num_pins(unsigned int *npins); +enum pm_ret_status pm_api_pinctrl_get_num_functions(unsigned int *nfuncs); +enum pm_ret_status pm_api_pinctrl_get_num_func_groups(unsigned int fid, + unsigned int *ngroups); +#endif /* PM_API_PINCTRL_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c new file mode 100644 index 0000000..f9af451 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c @@ -0,0 +1,1804 @@ +/* + * 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 +#include + +#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 unsigned int pm_shutdown_scope = PMF_SHUTDOWN_SUBTYPE_SYSTEM; + +/** + * pm_get_shutdown_scope() - Get the currently set shutdown scope + * + * @return Shutdown scope value + */ +unsigned int 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, + unsigned int latency, + unsigned int state, + uintptr_t address) +{ + uint32_t payload[PAYLOAD_ARG_CNT]; + unsigned int 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, + unsigned int latency, unsigned int 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, + unsigned int 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, + unsigned int 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(unsigned int type, unsigned int 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, + unsigned int capabilities, + unsigned int 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, + unsigned int capabilities, + unsigned int 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(unsigned int *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, + unsigned int mask, + unsigned int 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, unsigned int *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(unsigned int *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, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *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(unsigned int 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(unsigned int 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(unsigned int clock_id, + unsigned int 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(unsigned int 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(unsigned int clock_id, + unsigned int 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(unsigned int 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(unsigned int clock_id, + unsigned char 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(unsigned int 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(unsigned int 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(unsigned int clock_id, + unsigned int *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(unsigned int clock_id, + unsigned int 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(unsigned int clock_id, + unsigned int *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(unsigned int 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(unsigned int 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(unsigned int clock_id, + unsigned int 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(unsigned int clock_id, + unsigned int *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(unsigned int 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(unsigned int 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(unsigned int fid, + unsigned int 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(unsigned int pin_id, + unsigned int 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, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *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); + } +} + +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, + unsigned int 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, + unsigned int *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(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *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"); + } + 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(unsigned int *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(unsigned int *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(unsigned int *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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h new file mode 100644 index 0000000..48b3877 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h @@ -0,0 +1,212 @@ +/* + * 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 + +#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 nid, + enum pm_request_ack ack, + unsigned int latency, + unsigned int state); + +enum pm_ret_status pm_self_suspend(enum pm_node_id nid, + unsigned int latency, + unsigned int state, + uintptr_t address); + +enum pm_ret_status pm_force_powerdown(enum pm_node_id nid, + 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 nid, + unsigned int 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, + unsigned int enable); + +enum pm_ret_status pm_system_shutdown(unsigned int type, unsigned int subtype); + +enum pm_ret_status pm_init_suspend_cb(enum pm_suspend_reason reason, + unsigned int latency, + unsigned int state, + unsigned int timeout); + +/* API functions for managing PM Slaves */ +enum pm_ret_status pm_req_node(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack); + +enum pm_ret_status pm_set_requirement(enum pm_node_id nid, + unsigned int capabilities, + unsigned int qos, + enum pm_request_ack ack); + +/* Miscellaneous API functions */ +enum pm_ret_status pm_get_api_version(unsigned int *version); +enum pm_ret_status pm_get_node_status(enum pm_node_id node, + uint32_t *ret_buff); +enum pm_ret_status pm_acknowledge_cb(enum pm_node_id nid, + enum pm_ret_status status, + unsigned int oppoint); +enum pm_ret_status pm_notify_cb(enum pm_node_id nid, + unsigned int event, + unsigned int oppoint); + +/* Direct-Control API functions */ +enum pm_ret_status pm_mmio_write(uintptr_t address, + unsigned int mask, + unsigned int value); +enum pm_ret_status pm_mmio_read(uintptr_t address, unsigned int *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(unsigned int *value); + +enum pm_ret_status pm_get_chipid(uint32_t *value); +enum pm_ret_status pm_secure_rsaaes(uint32_t address_high, + uint32_t address_low, + uint32_t size, + uint32_t flags); +unsigned int 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, + unsigned int ioctl_id, + unsigned int arg1, + unsigned int arg2, + unsigned int *value); +enum pm_ret_status pm_clock_enable(unsigned int clock_id); +enum pm_ret_status pm_clock_disable(unsigned int clock_id); +enum pm_ret_status pm_clock_getstate(unsigned int clock_id, + unsigned int *state); +enum pm_ret_status pm_clock_setdivider(unsigned int clock_id, + unsigned int divider); +enum pm_ret_status pm_clock_getdivider(unsigned int clock_id, + unsigned int *divider); +enum pm_ret_status pm_clock_setrate(unsigned int clock_id, + uint64_t rate); +enum pm_ret_status pm_clock_getrate(unsigned int clock_id, + uint64_t *rate); +enum pm_ret_status pm_clock_setparent(unsigned int clock_id, + unsigned int parent_id); +enum pm_ret_status pm_clock_getparent(unsigned int clock_id, + unsigned int *parent_id); +void pm_query_data(enum pm_query_id qid, unsigned int arg1, unsigned int arg2, + unsigned int arg3, unsigned int *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(unsigned int register_access_id, + unsigned int address, + unsigned int mask, + unsigned int value, + unsigned int *out); +enum pm_ret_status pm_pll_set_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int value); +enum pm_ret_status pm_pll_get_parameter(enum pm_node_id nid, + enum pm_pll_param param_id, + unsigned int *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(unsigned int *value); +enum pm_ret_status em_remove_action(unsigned int *value); +enum pm_ret_status em_send_errors(unsigned int *value); +enum pm_ret_status pm_feature_config(unsigned int ioctl_id, + unsigned int config_id, + unsigned int value, + unsigned int *response); +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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c new file mode 100644 index 0000000..163e891 --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c @@ -0,0 +1,344 @@ +/* + * 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 +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include "pm_api_sys.h" +#include "pm_client.h" +#include "pm_ipi.h" + +#define IRQ_MAX 84 +#define NUM_GICD_ISENABLER ((IRQ_MAX >> 5) + 1) +#define UNDEFINED_CPUID (~0) + +#define PM_SUSPEND_MODE_STD 0 +#define PM_SUSPEND_MODE_POWER_OFF 1 + +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 + 1] = { + 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(unsigned int 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]; + uintptr_t isenabler1 = BASE_GICD_BASE + GICD_ISENABLER + 4; + + /* 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, 1); + /** + * 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 = 0; 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) + 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) && + (!pm_wakeup_nodes_set[node])) { + ret = pm_set_wakeup_source(NODE_APU, node, 1); + pm_wakeup_nodes_set[node] = !ret; + } + } + } +} + +/** + * 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(unsigned int 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 unsigned int 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, unsigned int 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) +{ + unsigned int 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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h new file mode 100644 index 0000000..8eb197a --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h @@ -0,0 +1,361 @@ +/* + * 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 1 +#define PM_VERSION_MINOR 1 + +#define PM_VERSION ((PM_VERSION_MAJOR << 16) | 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_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_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, + PM_RET_ERROR_NO_FEATURE = 2008 +}; + +/** + * @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/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c new file mode 100644 index 0000000..d88e5fa --- /dev/null +++ b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c @@ -0,0 +1,612 @@ +/* + * 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 + +#include +#if ZYNQMP_WDT_RESTART +#include +#include +#include +#include +#include +#endif + +#include +#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); + } + + 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. + */ +int pm_setup(void) +{ + int status, ret; + + status = pm_ipi_init(primary_proc); + + ret = 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 & 0xFFFF); + return -EINVAL; + } + +#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, void *cookie, void *handle, uint64_t flags) +{ + enum pm_ret_status ret; + uint32_t payload[PAYLOAD_ARG_CNT]; + + uint32_t pm_arg[4]; + uint32_t result[PAYLOAD_ARG_CNT]; + uint32_t api_id; + + /* Handle case where PM wasn't initialized properly */ + if (!pm_up) + 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 */ + unsigned int set_addr = pm_arg[1] & 0x1; + uint64_t address = (uint64_t)pm_arg[2] << 32; + + address |= pm_arg[1] & (~0x1); + 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) { + /* + * 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 = 1; + } + 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; + + 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; + + 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; + + 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; + + 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; + + 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; + + ret = pm_clock_getparent(pm_arg[0], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case PM_GET_TRUSTZONE_VERSION: + SMC_RET1(handle, (uint64_t)PM_RET_SUCCESS | + ((uint64_t)ZYNQMP_TZ_VERSION << 32)); + + 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] << 32), + result[1]); + } + + case PM_FPGA_READ: + { + uint32_t value; + + 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) << 32); + } + + case PM_SECURE_AES: + { + uint32_t value; + + ret = pm_aes_engine(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + 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; + + ret = pm_pll_get_parameter(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value << 32)); + } + + 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; + + ret = pm_pll_get_mode(pm_arg[0], &mode); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)mode << 32)); + } + + case PM_REGISTER_ACCESS: + { + uint32_t value; + + 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) << 32); + } + + case PM_EFUSE_ACCESS: + { + uint32_t value; + + ret = pm_efuse_access(pm_arg[0], pm_arg[1], &value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + 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] << 32, + (uint64_t)ret_payload[1] | (uint64_t)ret_payload[2] << 32); + } + + case PM_FEATURE_CHECK: + { + uint32_t version; + 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 << 32), + (uint64_t)bit_mask[0] | ((uint64_t)bit_mask[1] << 32)); + } + + 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] << 32), + (uint64_t)result[1] | ((uint64_t)result[2] << 32)); + } +} + +/** + * 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, 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) << 32); + } + + case EM_REMOVE_ACTION: + { + uint32_t value; + + ret = em_remove_action(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + case EM_SEND_ERRORS: + { + uint32_t value; + + ret = em_send_errors(&value); + SMC_RET1(handle, (uint64_t)ret | ((uint64_t)value) << 32); + } + + default: + WARN("Unimplemented EM Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h b/arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h new file mode 100644 index 0000000..abadd40 --- /dev/null +++ b/arm-trusted-firmware/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" + +int pm_setup(void); +uint64_t pm_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); + +uint64_t em_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); +#endif /* PM_SVC_MAIN_H */ diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c new file mode 100644 index 0000000..114da33 --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include "ipi_mailbox_svc.h" +#include "pm_svc_main.h" + +/* SMC function IDs for SiP Service queries */ +#define ZYNQMP_SIP_SVC_CALL_COUNT 0x8200ff00 +#define ZYNQMP_SIP_SVC_UID 0x8200ff01 +#define ZYNQMP_SIP_SVC_VERSION 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. + */ +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, + SMC_TYPE_FAST, + sip_svc_setup, + sip_svc_smc_handler); diff --git a/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp-zynqmp.mk new file mode 100644 index 0000000..318b01d --- /dev/null +++ b/arm-trusted-firmware/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/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c b/arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c new file mode 100644 index 0000000..352ba82 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include +#include +#include +#include + +/******************************************************************************* + * 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/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c new file mode 100644 index 0000000..fbf1ed0 --- /dev/null +++ b/arm-trusted-firmware/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 + +#include + +/* + * 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/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c new file mode 100644 index 0000000..f57369f --- /dev/null +++ b/arm-trusted-firmware/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 +#include + +#include +#include +#include +#include + +#include +#include +#include + +/* Zynqmp ipi configuration table */ +const static struct ipi_config zynqmp_ipi_table[] = { + /* APU IPI */ + { + .ipi_bit_mask = 0x1, + .ipi_reg_base = 0xFF300000, + .secure_only = 0, + }, + /* RPU0 IPI */ + { + .ipi_bit_mask = 0x100, + .ipi_reg_base = 0xFF310000, + .secure_only = 0, + }, + /* RPU1 IPI */ + { + .ipi_bit_mask = 0x200, + .ipi_reg_base = 0xFF320000, + .secure_only = 0, + }, + /* PMU0 IPI */ + { + .ipi_bit_mask = 0x10000, + .ipi_reg_base = 0xFF330000, + .secure_only = IPI_SECURE_MASK, + }, + /* PMU1 IPI */ + { + .ipi_bit_mask = 0x20000, + .ipi_reg_base = 0xFF331000, + .secure_only = 0, + }, + /* PMU2 IPI */ + { + .ipi_bit_mask = 0x40000, + .ipi_reg_base = 0xFF332000, + .secure_only = IPI_SECURE_MASK, + }, + /* PMU3 IPI */ + { + .ipi_bit_mask = 0x80000, + .ipi_reg_base = 0xFF333000, + .secure_only = IPI_SECURE_MASK, + }, + /* PL0 IPI */ + { + .ipi_bit_mask = 0x1000000, + .ipi_reg_base = 0xFF340000, + .secure_only = 0, + }, + /* PL1 IPI */ + { + .ipi_bit_mask = 0x2000000, + .ipi_reg_base = 0xFF350000, + .secure_only = 0, + }, + /* PL2 IPI */ + { + .ipi_bit_mask = 0x4000000, + .ipi_reg_base = 0xFF360000, + .secure_only = 0, + }, + /* PL3 IPI */ + { + .ipi_bit_mask = 0x8000000, + .ipi_reg_base = 0xFF370000, + .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/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c b/arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c new file mode 100644 index 0000000..7e92b58 --- /dev/null +++ b/arm-trusted-firmware/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 +#include +#include + +#include +#include + +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); diff --git a/arm-trusted-firmware/readme.rst b/arm-trusted-firmware/readme.rst new file mode 100644 index 0000000..148d477 --- /dev/null +++ b/arm-trusted-firmware/readme.rst @@ -0,0 +1,51 @@ +Trusted Firmware-A +================== + +Trusted Firmware-A (TF-A) is a reference implementation of secure world software +for `Arm A-Profile architectures`_ (Armv8-A and Armv7-A), including an Exception +Level 3 (EL3) `Secure Monitor`_. It provides a suitable starting point for +productization of secure world boot and runtime firmware, in either the AArch32 +or AArch64 execution states. + +TF-A implements Arm interface standards, including: + +- `Power State Coordination Interface (PSCI)`_ +- `Trusted Board Boot Requirements CLIENT (TBBR-CLIENT)`_ +- `SMC Calling Convention`_ +- `System Control and Management Interface (SCMI)`_ +- `Software Delegated Exception Interface (SDEI)`_ + +The code is designed to be portable and reusable across hardware platforms and +software models that are based on the Armv8-A and Armv7-A architectures. + +In collaboration with interested parties, we will continue to enhance TF-A +with reference implementations of Arm standards to benefit developers working +with Armv7-A and Armv8-A TrustZone technology. + +Users are encouraged to do their own security validation, including penetration +testing, on any secure world code derived from TF-A. + +More Info and Documentation +--------------------------- + +To find out more about Trusted Firmware-A, please `view the full documentation`_ +that is available through `trustedfirmware.org`_. + +-------------- + +*Copyright (c) 2013-2019, Arm Limited and Contributors. All rights reserved.* + +.. _Armv7-A and Armv8-A: https://developer.arm.com/products/architecture/a-profile +.. _Secure Monitor: http://www.arm.com/products/processors/technologies/trustzone/tee-smc.php +.. _Power State Coordination Interface (PSCI): PSCI_ +.. _PSCI: http://infocenter.arm.com/help/topic/com.arm.doc.den0022d/Power_State_Coordination_Interface_PDD_v1_1_DEN0022D.pdf +.. _Trusted Board Boot Requirements CLIENT (TBBR-CLIENT): https://developer.arm.com/docs/den0006/latest/trusted-board-boot-requirements-client-tbbr-client-armv8-a +.. _SMC Calling Convention: http://infocenter.arm.com/help/topic/com.arm.doc.den0028b/ARM_DEN0028B_SMC_Calling_Convention.pdf +.. _System Control and Management Interface (SCMI): SCMI_ +.. _SCMI: http://infocenter.arm.com/help/topic/com.arm.doc.den0056a/DEN0056A_System_Control_and_Management_Interface.pdf +.. _Software Delegated Exception Interface (SDEI): SDEI_ +.. _SDEI: http://infocenter.arm.com/help/topic/com.arm.doc.den0054a/ARM_DEN0054A_Software_Delegated_Exception_Interface.pdf +.. _Arm A-Profile architectures: https://developer.arm.com/architectures/cpu-architecture/a-profile +.. _view the full documentation: https://www.trustedfirmware.org/docs/tf-a +.. _trustedfirmware.org: http://www.trustedfirmware.org + diff --git a/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c b/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c new file mode 100644 index 0000000..742f6cd --- /dev/null +++ b/arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c @@ -0,0 +1,195 @@ +/* + * Copyright (c) 2018-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Arm Arch Service UUID */ +static uuid_t arm_arch_svc_uid = { + {0xb7, 0xe0, 0xe2, 0x4d}, + {0xf0, 0x3d}, + {0x42, 0x8d}, + 0x9c, 0x1d, + {0x87, 0xf6, 0x93, 0x84, 0x76, 0xd9} +}; + +static int32_t smccc_version(void) +{ + return MAKE_SMCCC_VERSION(SMCCC_MAJOR_VERSION, SMCCC_MINOR_VERSION); +} + +static int32_t smccc_arch_features(u_register_t arg1) +{ + switch (arg1) { + case SMCCC_VERSION: + case SMCCC_ARCH_FEATURES: + return SMC_ARCH_CALL_SUCCESS; + case SMCCC_ARCH_SOC_ID: + return plat_is_smccc_feature_available(arg1); +#if WORKAROUND_CVE_2017_5715 + case SMCCC_ARCH_WORKAROUND_1: + if (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES) + return 1; + return 0; /* ERRATA_APPLIES || ERRATA_MISSING */ +#endif + +#if WORKAROUND_CVE_2018_3639 + case SMCCC_ARCH_WORKAROUND_2: { +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + unsigned long long ssbs; + + /* + * Firmware doesn't have to carry out dynamic workaround if the + * PE implements architectural Speculation Store Bypass Safe + * (SSBS) feature. + */ + ssbs = (read_id_aa64pfr1_el1() >> ID_AA64PFR1_EL1_SSBS_SHIFT) & + ID_AA64PFR1_EL1_SSBS_MASK; + + /* + * If architectural SSBS is available on this PE, no firmware + * mitigation via SMCCC_ARCH_WORKAROUND_2 is required. + */ + if (ssbs != SSBS_UNAVAILABLE) + return 1; + + /* + * On a platform where at least one CPU requires + * dynamic mitigation but others are either unaffected + * or permanently mitigated, report the latter as not + * needing dynamic mitigation. + */ + if (wa_cve_2018_3639_get_disable_ptr() == NULL) + return 1; + /* + * If we get here, this CPU requires dynamic mitigation + * so report it as such. + */ + return 0; +#else + /* Either the CPUs are unaffected or permanently mitigated */ + return SMC_ARCH_CALL_NOT_REQUIRED; +#endif + } +#endif + +#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715) + case SMCCC_ARCH_WORKAROUND_3: + /* + * SMCCC_ARCH_WORKAROUND_3 should also take into account + * CVE-2017-5715 since this SMC can be used instead of + * SMCCC_ARCH_WORKAROUND_1. + */ + if ((check_smccc_arch_wa3_applies() == ERRATA_NOT_APPLIES) && + (check_wa_cve_2017_5715() == ERRATA_NOT_APPLIES)) { + return 1; + } + return 0; /* ERRATA_APPLIES || ERRATA_MISSING */ +#endif + + /* Fallthrough */ + + default: + return SMC_UNK; + } +} + +/* return soc revision or soc version on success otherwise + * return invalid parameter */ +static int32_t smccc_arch_id(u_register_t arg1) +{ + if (arg1 == SMCCC_GET_SOC_REVISION) { + return plat_get_soc_revision(); + } + if (arg1 == SMCCC_GET_SOC_VERSION) { + return plat_get_soc_version(); + } + return SMC_ARCH_CALL_INVAL_PARAM; +} + +/* + * Top-level Arm Architectural Service SMC handler. + */ +static uintptr_t arm_arch_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) +{ + switch (smc_fid) { + case SMCCC_VERSION: + SMC_RET1(handle, smccc_version()); + case SMCCC_ARCH_FEATURES: + SMC_RET1(handle, smccc_arch_features(x1)); + case SMCCC_ARCH_SOC_ID: + SMC_RET1(handle, smccc_arch_id(x1)); + + case ARM_ARCH_SVC_CALL_COUNT: + /* Return the number of Arm Arch Calls. */ + SMC_RET1(handle, ARM_ARCH_SVC_COUNT); + case ARM_ARCH_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_arch_svc_uid); + case ARM_ARCH_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, ARM_ARCH_SVC_VERSION_MAJOR, ARM_ARCH_SVC_VERSION_MINOR); + +#if WORKAROUND_CVE_2017_5715 + case SMCCC_ARCH_WORKAROUND_1: + /* + * The workaround has already been applied on affected PEs + * during entry to EL3. On unaffected PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif +#if WORKAROUND_CVE_2018_3639 + case SMCCC_ARCH_WORKAROUND_2: + /* + * The workaround has already been applied on affected PEs + * requiring dynamic mitigation during entry to EL3. + * On unaffected or statically mitigated PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif +#if (WORKAROUND_CVE_2022_23960 || WORKAROUND_CVE_2017_5715) + case SMCCC_ARCH_WORKAROUND_3: + /* + * The workaround has already been applied on affected PEs + * during entry to EL3. On unaffected PEs, this function + * has no effect. + */ + SMC_RET0(handle); +#endif + default: + WARN("Unimplemented Arm Architecture Service Call: 0x%x \n", + smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC( + arm_arch_svc, + OEN_ARM_START, + OEN_ARM_END, + SMC_TYPE_FAST, + NULL, + arm_arch_svc_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/opteed/opteed.mk b/arm-trusted-firmware/services/spd/opteed/opteed.mk new file mode 100644 index 0000000..643b054 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed.mk @@ -0,0 +1,18 @@ +# +# Copyright (c) 2013-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +OPTEED_DIR := services/spd/opteed +SPD_INCLUDES := + +SPD_SOURCES := services/spd/opteed/opteed_common.c \ + services/spd/opteed/opteed_helpers.S \ + services/spd/opteed/opteed_main.c \ + services/spd/opteed/opteed_pm.c + +NEED_BL32 := yes + +# required so that optee code can control access to the timer registers +NS_TIMER_SWITCH := 1 diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_common.c b/arm-trusted-firmware/services/spd/opteed/opteed_common.c new file mode 100644 index 0000000..f913e11 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_common.c @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, NVIDIA CORPORATION. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include + +#include "opteed_private.h" + +/******************************************************************************* + * Given a OPTEE entrypoint info pointer, entry point PC, register width, + * cpu id & pointer to a context data structure, this function will + * initialize OPTEE context and entry point info for OPTEE. + ******************************************************************************/ +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, + uint32_t rw, uint64_t pc, + uint64_t pageable_part, uint64_t mem_limit, + uint64_t dt_addr, optee_context_t *optee_ctx) +{ + uint32_t ep_attr; + + /* Passing a NULL context is a critical programming error */ + assert(optee_ctx); + assert(optee_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + optee_ctx->mpidr = read_mpidr_el1(); + optee_ctx->state = 0; + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + cm_set_context(&optee_ctx->cpu_ctx, SECURE); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(optee_entry_point, PARAM_EP, VERSION_1, ep_attr); + optee_entry_point->pc = pc; + if (rw == OPTEE_AARCH64) + optee_entry_point->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + else + optee_entry_point->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + zeromem(&optee_entry_point->args, sizeof(optee_entry_point->args)); + optee_entry_point->args.arg0 = pageable_part; + optee_entry_point->args.arg1 = mem_limit; + optee_entry_point->args.arg2 = dt_addr; +} + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Applies the S-EL1 system register context from optee_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the optee_ctx->cpu_ctx are used to enter the OPTEE image. + ******************************************************************************/ +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx) +{ + uint64_t rc; + + assert(optee_ctx != NULL); + assert(optee_ctx->c_rt_ctx == 0); + + /* Save the Non-Secure EL1 system register context */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = opteed_enter_sp(&optee_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + optee_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + + +/******************************************************************************* + * This function takes an OPTEE context pointer and: + * 1. Saves the S-EL1 system register context tp optee_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using the reference to this state saved in opteed_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret) +{ + assert(optee_ctx != NULL); + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &optee_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + /* Apply the Non-Secure EL1 system register context and switch to it */ + cm_el1_sysregs_context_restore(NON_SECURE); + + assert(optee_ctx->c_rt_ctx != 0); + opteed_exit_sp(optee_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S b/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S new file mode 100644 index 0000000..075a71b --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_helpers.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "opteed_private.h" + + .global opteed_enter_sp + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func opteed_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #OPTEED_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #OPTEED_C_RT_CTX_X19] + stp x21, x22, [sp, #OPTEED_C_RT_CTX_X21] + stp x23, x24, [sp, #OPTEED_C_RT_CTX_X23] + stp x25, x26, [sp, #OPTEED_C_RT_CTX_X25] + stp x27, x28, [sp, #OPTEED_C_RT_CTX_X27] + stp x29, x30, [sp, #OPTEED_C_RT_CTX_X29] + + /* --------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into OPTEE. + * --------------------------------------------- + */ + b el3_exit +endfunc opteed_enter_sp + + /* --------------------------------------------- + * This function is called 'x0' pointing to a C + * runtime context saved in opteed_enter_sp(). It + * restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * --------------------------------------------- + */ + .global opteed_exit_sp +func opteed_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(OPTEED_C_RT_CTX_X19 - OPTEED_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(OPTEED_C_RT_CTX_X21 - OPTEED_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(OPTEED_C_RT_CTX_X23 - OPTEED_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(OPTEED_C_RT_CTX_X25 - OPTEED_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(OPTEED_C_RT_CTX_X27 - OPTEED_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(OPTEED_C_RT_CTX_X29 - OPTEED_C_RT_CTX_SIZE)] + + /* --------------------------------------------- + * This should take us back to the instruction + * after the call to the last opteed_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * --------------------------------------------- + */ + mov x0, x1 + ret +endfunc opteed_exit_sp diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_main.c b/arm-trusted-firmware/services/spd/opteed/opteed_main.c new file mode 100644 index 0000000..160a693 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_main.c @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "opteed_private.h" +#include "teesmc_opteed.h" +#include "teesmc_opteed_macros.h" + +/******************************************************************************* + * Address of the entrypoint vector table in OPTEE. It is + * initialised once on the primary core after a cold boot. + ******************************************************************************/ +struct optee_vectors *optee_vector_table; + +/******************************************************************************* + * Array to keep track of per-cpu OPTEE state + ******************************************************************************/ +optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +uint32_t opteed_rw; + +static int32_t opteed_init(void); + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the + * OPTEED. It validates the interrupt and upon success arranges entry into + * the OPTEE at 'optee_fiq_entry()' for handling the interrupt. + ******************************************************************************/ +static uint64_t opteed_sel1_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + uint32_t linear_id; + optee_context_t *optee_ctx; + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the OPTEE */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to this cpu's OPTEE context */ + linear_id = plat_my_core_pos(); + optee_ctx = &opteed_sp_context[linear_id]; + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + cm_set_elr_el3(SECURE, (uint64_t)&optee_vector_table->fiq_entry); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* + * Tell the OPTEE that it has to handle an FIQ (synchronously). + * Also the instruction in normal world where the interrupt was + * generated is passed for debugging purposes. It is safe to + * retrieve this address from ELR_EL3 as the secure context will + * not take effect until el3_exit(). + */ + SMC_RET1(&optee_ctx->cpu_ctx, read_elr_el3()); +} + +/******************************************************************************* + * OPTEE Dispatcher setup. The OPTEED finds out the OPTEE entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into OPTEE for its initialization. + ******************************************************************************/ +static int32_t opteed_setup(void) +{ + entry_point_info_t *optee_ep_info; + uint32_t linear_id; + uint64_t opteed_pageable_part; + uint64_t opteed_mem_limit; + uint64_t dt_addr; + + linear_id = plat_my_core_pos(); + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. TODO: Add support to + * conditionally include the SPD service + */ + optee_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!optee_ep_info) { + WARN("No OPTEE provided by BL2 boot loader, Booting device" + " without OPTEE initialization. SMC`s destined for OPTEE" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!optee_ep_info->pc) + return 1; + + opteed_rw = optee_ep_info->args.arg0; + opteed_pageable_part = optee_ep_info->args.arg1; + opteed_mem_limit = optee_ep_info->args.arg2; + dt_addr = optee_ep_info->args.arg3; + + opteed_init_optee_ep_state(optee_ep_info, + opteed_rw, + optee_ep_info->pc, + opteed_pageable_part, + opteed_mem_limit, + dt_addr, + &opteed_sp_context[linear_id]); + + /* + * All OPTEED initialization done. Now register our init function with + * BL31 for deferred invocation + */ + bl31_register_bl32_init(&opteed_init); + + return 0; +} + +/******************************************************************************* + * This function passes control to the OPTEE image (BL32) for the first time + * on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by opteed_setup() which can be directly + * used. It also assumes that a valid non-secure context has been + * initialised by PSCI so it does not need to save and restore any + * non-secure state. This function performs a synchronous entry into + * OPTEE. OPTEE passes control back to this routine through a SMC. + ******************************************************************************/ +static int32_t opteed_init(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t *optee_entry_point; + uint64_t rc; + + /* + * Get information about the OPTEE (BL32) image. Its + * absence is a critical failure. + */ + optee_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(optee_entry_point); + + cm_init_my_context(optee_entry_point); + + /* + * Arrange for an entry into OPTEE. It will be returned via + * OPTEE_ENTRY_DONE case + */ + rc = opteed_synchronous_sp_entry(optee_ctx); + assert(rc != 0); + + return rc; +} + + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure + * payload to delegate work and return results back to the non-secure + * state. Lastly it will also return any information that OPTEE needs to do + * the work assigned to it. + ******************************************************************************/ +static uintptr_t opteed_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) +{ + cpu_context_t *ns_cpu_context; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + uint64_t rc; + + /* + * Determine which security state this SMC originated from + */ + + if (is_caller_non_secure(flags)) { + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * We are done stashing the non-secure context. Ask the + * OPTEE to do the work now. + */ + + /* + * Verify if there is a valid context to use, copy the + * operation type and parameters to the secure context + * and jump to the fast smc entry point in the secure + * payload. Entry into S-EL1 will take place upon exit + * from this function. + */ + assert(&optee_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* Set appropriate entry for SMC. + * We expect OPTEE to manage the PSTATE.I and PSTATE.F + * flags as appropriate. + */ + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vector_table->fast_smc_entry); + } else { + cm_set_elr_el3(SECURE, (uint64_t) + &optee_vector_table->yield_smc_entry); + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X4, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X4)); + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X5, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X5)); + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X6, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X6)); + /* Propagate hypervisor client ID */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X7, + read_ctx_reg(get_gpregs_ctx(handle), + CTX_GPREG_X7)); + + SMC_RET4(&optee_ctx->cpu_ctx, smc_fid, x1, x2, x3); + } + + /* + * Returning from OPTEE + */ + + switch (smc_fid) { + /* + * OPTEE has finished initialising itself after a cold boot + */ + case TEESMC_OPTEED_RETURN_ENTRY_DONE: + /* + * Stash the OPTEE entry points information. This is done + * only once on the primary cpu + */ + assert(optee_vector_table == NULL); + optee_vector_table = (optee_vectors_t *) x1; + + if (optee_vector_table) { + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); + + /* + * OPTEE has been successfully initialized. + * Register power management hooks with PSCI + */ + psci_register_spd_pm_hook(&opteed_pm); + + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + opteed_sel1_interrupt_handler, + flags); + if (rc) + panic(); + } + + /* + * OPTEE reports completion. The OPTEED must have initiated + * the original request through a synchronous entry into + * OPTEE. Jump back to the original C runtime context. + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + break; + + + /* + * These function IDs is used only by OP-TEE to indicate it has + * finished: + * 1. turning itself on in response to an earlier psci + * cpu_on request + * 2. resuming itself after an earlier psci cpu_suspend + * request. + */ + case TEESMC_OPTEED_RETURN_ON_DONE: + case TEESMC_OPTEED_RETURN_RESUME_DONE: + + + /* + * These function IDs is used only by the SP to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. turning itself off in response to an earlier psci + * cpu_off request. + */ + case TEESMC_OPTEED_RETURN_OFF_DONE: + case TEESMC_OPTEED_RETURN_SUSPEND_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE: + case TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE: + + /* + * OPTEE reports completion. The OPTEED must have initiated the + * original request through a synchronous entry into OPTEE. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + opteed_synchronous_sp_exit(optee_ctx, x1); + break; + + /* + * OPTEE is returning from a call or being preempted from a call, in + * either case execution should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_CALL_DONE: + /* + * This is the result from the secure client of an + * earlier request. The results are in x0-x3. Copy it + * into the non-secure context, save the secure state + * and return to the non-secure state. + */ + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET4(ns_cpu_context, x1, x2, x3, x4); + + /* + * OPTEE has finished handling a S-EL1 FIQ interrupt. Execution + * should resume in the normal world. + */ + case TEESMC_OPTEED_RETURN_FIQ_DONE: + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since OPTEE was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0((uint64_t) ns_cpu_context); + + default: + panic(); + } +} + +/* Define an OPTEED runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + opteed_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + opteed_setup, + opteed_smc_handler +); + +/* Define an OPTEED runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + opteed_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + opteed_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_pm.c b/arm-trusted-firmware/services/spd/opteed/opteed_pm.c new file mode 100644 index 0000000..719eeb7 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_pm.c @@ -0,0 +1,223 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include + +#include "opteed_private.h" + +/******************************************************************************* + * The target cpu is being turned on. Allow the OPTEED/OPTEE to perform any + * actions needed. Nothing at the moment. + ******************************************************************************/ +static void opteed_cpu_on_handler(u_register_t target_cpu) +{ +} + +/******************************************************************************* + * This cpu is being turned off. Allow the OPTEED/OPTEE to perform any actions + * needed + ******************************************************************************/ +static int32_t opteed_cpu_off_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point and enter OPTEE */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_off_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* + * Reset OPTEE's context for a fresh start when this cpu is turned on + * subsequently. + */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_OFF); + + return 0; +} + +/******************************************************************************* + * This cpu is being suspended. S-EL1 state must have been saved in the + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static void opteed_cpu_suspend_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), CTX_GPREG_X0, + max_off_pwrlvl); + + /* Program the entry point and enter OPTEE */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_suspend_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_SUSPEND); +} + +/******************************************************************************* + * This cpu has been turned on. Enter OPTEE to initialise S-EL1 and other bits + * before passing control back to the Secure Monitor. Entry in S-El1 is done + * after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void opteed_cpu_on_finish_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + entry_point_info_t optee_on_entrypoint; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_OFF); + + opteed_init_optee_ep_state(&optee_on_entrypoint, opteed_rw, + (uint64_t)&optee_vector_table->cpu_on_entry, + 0, 0, 0, optee_ctx); + + /* Initialise this cpu's secure context */ + cm_init_my_context(&optee_on_entrypoint); + + /* Enter OPTEE */ + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * This cpu has resumed from suspend. The OPTEED saved the OPTEE context when it + * completed the preceding suspend call. Use that context to program an entry + * into OPTEE to allow it to do any remaining book keeping + ******************************************************************************/ +static void opteed_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_SUSPEND); + + /* Program the entry point, max_off_pwrlvl and enter the SP */ + write_ctx_reg(get_gpregs_ctx(&optee_ctx->cpu_ctx), + CTX_GPREG_X0, + max_off_pwrlvl); + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->cpu_resume_entry); + rc = opteed_synchronous_sp_entry(optee_ctx); + + /* + * Read the response from OPTEE. A non-zero return means that + * something went wrong while communicating with OPTEE. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state OPTEE is in */ + set_optee_pstate(optee_ctx->state, OPTEE_PSTATE_ON); +} + +/******************************************************************************* + * Return the type of OPTEE the OPTEED is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable OPTEE. + ******************************************************************************/ +static int32_t opteed_cpu_migrate_info(u_register_t *resident_cpu) +{ + return OPTEE_MIGRATE_INFO; +} + +/******************************************************************************* + * System is about to be switched off. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_off(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_off_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the shutdown anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + +/******************************************************************************* + * System is about to be reset. Allow the OPTEED/OPTEE to perform + * any actions needed. + ******************************************************************************/ +static void opteed_system_reset(void) +{ + uint32_t linear_id = plat_my_core_pos(); + optee_context_t *optee_ctx = &opteed_sp_context[linear_id]; + + assert(optee_vector_table); + assert(get_optee_pstate(optee_ctx->state) == OPTEE_PSTATE_ON); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &optee_vector_table->system_reset_entry); + + /* Enter OPTEE. We do not care about the return value because we + * must continue the reset anyway */ + opteed_synchronous_sp_entry(optee_ctx); +} + + +/******************************************************************************* + * Structure populated by the OPTEE Dispatcher to be given a chance to + * perform any OPTEE bookkeeping before PSCI executes a power mgmt. + * operation. + ******************************************************************************/ +const spd_pm_ops_t opteed_pm = { + .svc_on = opteed_cpu_on_handler, + .svc_off = opteed_cpu_off_handler, + .svc_suspend = opteed_cpu_suspend_handler, + .svc_on_finish = opteed_cpu_on_finish_handler, + .svc_suspend_finish = opteed_cpu_suspend_finish_handler, + .svc_migrate = NULL, + .svc_migrate_info = opteed_cpu_migrate_info, + .svc_system_off = opteed_system_off, + .svc_system_reset = opteed_system_reset, +}; diff --git a/arm-trusted-firmware/services/spd/opteed/opteed_private.h b/arm-trusted-firmware/services/spd/opteed/opteed_private.h new file mode 100644 index 0000000..242154f --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/opteed_private.h @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef OPTEED_PRIVATE_H +#define OPTEED_PRIVATE_H + +#include + +#include +#include +#include +#include + +/******************************************************************************* + * OPTEE PM state information e.g. OPTEE is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags + ******************************************************************************/ +#define OPTEE_PSTATE_OFF 0 +#define OPTEE_PSTATE_ON 1 +#define OPTEE_PSTATE_SUSPEND 2 +#define OPTEE_PSTATE_SHIFT 0 +#define OPTEE_PSTATE_MASK 0x3 +#define get_optee_pstate(state) ((state >> OPTEE_PSTATE_SHIFT) & \ + OPTEE_PSTATE_MASK) +#define clr_optee_pstate(state) (state &= ~(OPTEE_PSTATE_MASK \ + << OPTEE_PSTATE_SHIFT)) +#define set_optee_pstate(st, pst) do { \ + clr_optee_pstate(st); \ + st |= (pst & OPTEE_PSTATE_MASK) << \ + OPTEE_PSTATE_SHIFT; \ + } while (0) + + +/******************************************************************************* + * OPTEE execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define OPTEE_AARCH32 MODE_RW_32 +#define OPTEE_AARCH64 MODE_RW_64 + +/******************************************************************************* + * The OPTEED should know the type of OPTEE + ******************************************************************************/ +#define OPTEE_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP +#define OPTEE_TYPE_UPM PSCI_TOS_UP_MIG_CAP +#define OPTEE_TYPE_MP PSCI_TOS_NOT_PRESENT_MP + +/******************************************************************************* + * OPTEE migrate type information as known to the OPTEED. We assume that + * the OPTEED is dealing with an MP Secure Payload. + ******************************************************************************/ +#define OPTEE_MIGRATE_INFO OPTEE_TYPE_MP + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define OPTEED_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define OPTEED_C_RT_CTX_X19 0x0 +#define OPTEED_C_RT_CTX_X20 0x8 +#define OPTEED_C_RT_CTX_X21 0x10 +#define OPTEED_C_RT_CTX_X22 0x18 +#define OPTEED_C_RT_CTX_X23 0x20 +#define OPTEED_C_RT_CTX_X24 0x28 +#define OPTEED_C_RT_CTX_X25 0x30 +#define OPTEED_C_RT_CTX_X26 0x38 +#define OPTEED_C_RT_CTX_X27 0x40 +#define OPTEED_C_RT_CTX_X28 0x48 +#define OPTEED_C_RT_CTX_X29 0x50 +#define OPTEED_C_RT_CTX_X30 0x58 +#define OPTEED_C_RT_CTX_SIZE 0x60 +#define OPTEED_C_RT_CTX_ENTRIES (OPTEED_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +typedef uint32_t optee_vector_isn_t; + +typedef struct optee_vectors { + optee_vector_isn_t yield_smc_entry; + optee_vector_isn_t fast_smc_entry; + optee_vector_isn_t cpu_on_entry; + optee_vector_isn_t cpu_off_entry; + optee_vector_isn_t cpu_resume_entry; + optee_vector_isn_t cpu_suspend_entry; + optee_vector_isn_t fiq_entry; + optee_vector_isn_t system_off_entry; + optee_vector_isn_t system_reset_entry; +} optee_vectors_t; + +/* + * The number of arguments to save during a SMC call for OPTEE. + * Currently only x1 and x2 are used by OPTEE. + */ +#define OPTEE_NUM_ARGS 0x2 + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, OPTEED_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(OPTEED_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_spd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the OPTEED to maintain the per-cpu state of OPTEE. + * 'state' - collection of flags to track OPTEE state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into OPTEE. + * 'cpu_ctx' - space to maintain OPTEE architectural state + ******************************************************************************/ +typedef struct optee_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} optee_context_t; + +/* OPTEED power management handlers */ +extern const spd_pm_ops_t opteed_pm; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +struct optee_vectors; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t opteed_enter_sp(uint64_t *c_rt_ctx); +void __dead2 opteed_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t opteed_synchronous_sp_entry(optee_context_t *optee_ctx); +void __dead2 opteed_synchronous_sp_exit(optee_context_t *optee_ctx, uint64_t ret); +void opteed_init_optee_ep_state(struct entry_point_info *optee_entry_point, + uint32_t rw, + uint64_t pc, + uint64_t pageable_part, + uint64_t mem_limit, + uint64_t dt_addr, + optee_context_t *optee_ctx); + +extern optee_context_t opteed_sp_context[OPTEED_CORE_COUNT]; +extern uint32_t opteed_rw; +extern struct optee_vectors *optee_vector_table; +#endif /*__ASSEMBLER__*/ + +#endif /* OPTEED_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h new file mode 100644 index 0000000..c82b58a --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h @@ -0,0 +1,123 @@ +/* + * Copyright (c) 2014-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* Copyright (c) 2014, Linaro Limited. All rights reserved. */ + +#ifndef TEESMC_OPTEED_H +#define TEESMC_OPTEED_H + +/* + * This file specifies SMC function IDs used when returning from TEE to the + * secure monitor. + * + * All SMC Function IDs indicates SMC32 Calling Convention but will carry + * full 64 bit values in the argument registers if invoked from Aarch64 + * mode. This violates the SMC Calling Convention, but since this + * convention only coveres API towards Normal World it's something that + * only concerns the OP-TEE Dispatcher in Trusted Firmware-A and OP-TEE + * OS at Secure EL1. + */ + +/* + * Issued when returning from initial entry. + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ENTRY_DONE + * r1/x1 Pointer to entry vector + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE 0 +#define TEESMC_OPTEED_RETURN_ENTRY_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ENTRY_DONE) + + + +/* + * Issued when returning from "cpu_on" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_ON_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_ON_DONE 1 +#define TEESMC_OPTEED_RETURN_ON_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_ON_DONE) + +/* + * Issued when returning from "cpu_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_OFF_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE 2 +#define TEESMC_OPTEED_RETURN_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_OFF_DONE) + +/* + * Issued when returning from "cpu_suspend" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SUSPEND_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE 3 +#define TEESMC_OPTEED_RETURN_SUSPEND_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SUSPEND_DONE) + +/* + * Issued when returning from "cpu_resume" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_RESUME_DONE + * r1/x1 0 on success and anything else to indicate error condition + */ +#define TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE 4 +#define TEESMC_OPTEED_RETURN_RESUME_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_RESUME_DONE) + +/* + * Issued when returning from "std_smc" or "fast_smc" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_CALL_DONE + * r1-4/x1-4 Return value 0-3 which will passed to normal world in + * r0-3/x0-3 + */ +#define TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE 5 +#define TEESMC_OPTEED_RETURN_CALL_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_CALL_DONE) + +/* + * Issued when returning from "fiq" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_FIQ_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE 6 +#define TEESMC_OPTEED_RETURN_FIQ_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_FIQ_DONE) + +/* + * Issued when returning from "system_off" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE 7 +#define TEESMC_OPTEED_RETURN_SYSTEM_OFF_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_OFF_DONE) + +/* + * Issued when returning from "system_reset" vector + * + * Register usage: + * r0/x0 SMC Function ID, TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE + */ +#define TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE 8 +#define TEESMC_OPTEED_RETURN_SYSTEM_RESET_DONE \ + TEESMC_OPTEED_RV(TEESMC_OPTEED_FUNCID_RETURN_SYSTEM_RESET_DONE) + +#endif /*TEESMC_OPTEED_H*/ diff --git a/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h new file mode 100644 index 0000000..9d8a169 --- /dev/null +++ b/arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef TEESMC_OPTEED_MACROS_H +#define TEESMC_OPTEED_MACROS_H + +#include + +#define TEESMC_OPTEED_RV(func_num) \ + ((SMC_TYPE_FAST << FUNCID_TYPE_SHIFT) | \ + ((SMC_32) << FUNCID_CC_SHIFT) | \ + (62 << FUNCID_OEN_SHIFT) | \ + ((func_num) & FUNCID_NUM_MASK)) + +#endif /* TEESMC_OPTEED_MACROS_H */ diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd.mk b/arm-trusted-firmware/services/spd/tlkd/tlkd.mk new file mode 100644 index 0000000..56de0a6 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd.mk @@ -0,0 +1,14 @@ +# +# Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifeq (${ERROR_DEPRECATED},0) +SPD_INCLUDES := -Iinclude/bl32/payloads +endif + +SPD_SOURCES := services/spd/tlkd/tlkd_common.c \ + services/spd/tlkd/tlkd_helpers.S \ + services/spd/tlkd/tlkd_main.c \ + services/spd/tlkd/tlkd_pm.c diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c new file mode 100644 index 0000000..820bd8a --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_common.c @@ -0,0 +1,165 @@ +/* + * Copyright (c) 2015-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include + +#include "tlkd_private.h" + +#define AT_MASK 3 + +/******************************************************************************* + * This function helps the SP to translate NS/S virtual addresses. + ******************************************************************************/ +uint64_t tlkd_va_translate(uintptr_t va, int type) +{ + uint64_t pa; + + if (type & TLK_TRANSLATE_NS_VADDR) { + + /* save secure context */ + cm_el1_sysregs_context_save(SECURE); + + /* restore non-secure context */ + cm_el1_sysregs_context_restore(NON_SECURE); + + /* switch NS bit to start using 64-bit, non-secure mappings */ + write_scr(cm_get_scr_el3(NON_SECURE)); + isb(); + } + + int at = type & AT_MASK; + switch (at) { + case 0: + AT(ats12e1r, va); + break; + case 1: + AT(ats12e1w, va); + break; + case 2: + AT(ats12e0r, va); + break; + case 3: + AT(ats12e0w, va); + break; + default: + assert(0); /* Unreachable */ + break; + } + + /* get the (NS/S) physical address */ + isb(); + pa = read_par_el1(); + + /* Restore secure state */ + if (type & TLK_TRANSLATE_NS_VADDR) { + + /* restore secure context */ + cm_el1_sysregs_context_restore(SECURE); + + /* switch NS bit to start using 32-bit, secure mappings */ + write_scr(cm_get_scr_el3(SECURE)); + isb(); + } + + return pa; +} + +/******************************************************************************* + * Given a secure payload entrypoint, register width, cpu id & pointer to a + * context data structure, this function will create a secure context ready for + * programming an entry into the secure payload. + ******************************************************************************/ +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx) +{ + uint32_t ep_attr, spsr; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + assert(tlk_entry_point); + assert(pc); + + /* Associate this context with the cpu specified */ + tlk_ctx->mpidr = read_mpidr_el1(); + clr_yield_smc_active_flag(tlk_ctx->state); + cm_set_context(&tlk_ctx->cpu_ctx, SECURE); + + if (rw == SP_AARCH64) + spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS); + else + spsr = SPSR_MODE32(MODE32_svc, + SPSR_T_ARM, + read_sctlr_el3() & SCTLR_EE_BIT, + DISABLE_ALL_EXCEPTIONS); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(tlk_entry_point, PARAM_EP, VERSION_1, ep_attr); + + tlk_entry_point->pc = pc; + tlk_entry_point->spsr = spsr; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Applies the S-EL1 system register context from tlk_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the tlk_ctx->cpu_ctx are used to enter the secure payload image. + ******************************************************************************/ +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx) +{ + uint64_t rc; + + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = tlkd_enter_sp(&tlk_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + tlk_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + +/******************************************************************************* + * This function takes a TLK context pointer and: + * 1. Saves the S-EL1 system register context to tlk_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using reference to this state saved in tlkd_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, uint64_t ret) +{ + /* Passing a NULL context is a critical programming error */ + assert(tlk_ctx); + + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tlk_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(tlk_ctx->c_rt_ctx != 0); + tlkd_exit_sp(tlk_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S b/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S new file mode 100644 index 0000000..6e616a6 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "tlkd_private.h" + + .global tlkd_enter_sp + .global tlkd_exit_sp + + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func tlkd_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #TLKD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #TLKD_C_RT_CTX_X19] + stp x21, x22, [sp, #TLKD_C_RT_CTX_X21] + stp x23, x24, [sp, #TLKD_C_RT_CTX_X23] + stp x25, x26, [sp, #TLKD_C_RT_CTX_X25] + stp x27, x28, [sp, #TLKD_C_RT_CTX_X27] + stp x29, x30, [sp, #TLKD_C_RT_CTX_X29] + + /* ---------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into the secure payload. + * ---------------------------------------------- + */ + b el3_exit +endfunc tlkd_enter_sp + + /* ---------------------------------------------- + * This function is called with 'x0' pointing to + * a C runtime context saved in tlkd_enter_sp(). + * It restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * ---------------------------------------------- + */ +func tlkd_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(TLKD_C_RT_CTX_X19 - TLKD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(TLKD_C_RT_CTX_X21 - TLKD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(TLKD_C_RT_CTX_X23 - TLKD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(TLKD_C_RT_CTX_X25 - TLKD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(TLKD_C_RT_CTX_X27 - TLKD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(TLKD_C_RT_CTX_X29 - TLKD_C_RT_CTX_SIZE)] + + /* ------------------------------------------------ + * This should take us back to the instruction + * after the call to the last tlkd_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * ------------------------------------------------ + */ + mov x0, x1 + ret +endfunc tlkd_exit_sp diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c new file mode 100644 index 0000000..e426fac --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_main.c @@ -0,0 +1,558 @@ +/* + * 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 + */ + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tlkd_private.h" + +extern const spd_pm_ops_t tlkd_pm_ops; + +/******************************************************************************* + * Per-cpu Secure Payload state + ******************************************************************************/ +tlk_context_t tlk_ctx; + +/******************************************************************************* + * CPU number on which TLK booted up + ******************************************************************************/ +static uint32_t boot_cpu; + +/* TLK UID: RFC-4122 compliant UUID (version-5, sha-1) */ +DEFINE_SVC_UUID2(tlk_uuid, + 0xc9e911bd, 0xba2b, 0xee52, 0xb1, 0x72, + 0x46, 0x1f, 0xba, 0x97, 0x7f, 0x63); + +static int32_t tlkd_init(void); + +/******************************************************************************* + * Secure Payload Dispatcher's timer interrupt handler + ******************************************************************************/ +static uint64_t tlkd_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + cpu_context_t *s_cpu_context; + int irq = plat_ic_get_pending_interrupt_id(); + + /* acknowledge the interrupt and mark it complete */ + (void)plat_ic_acknowledge_interrupt(); + plat_ic_end_of_interrupt(irq); + + /* + * Disable the routing of NS interrupts from secure world to + * EL3 while interrupted on this core. + */ + disable_intr_rm_local(INTR_TYPE_S_EL1, SECURE); + + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + assert(handle == cm_get_context(NON_SECURE)); + + /* Save non-secure state */ + cm_el1_sysregs_context_save(NON_SECURE); + + /* Get a reference to the secure context */ + s_cpu_context = cm_get_context(SECURE); + assert(s_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Provide the IRQ number to the SPD */ + SMC_RET4(s_cpu_context, (uint32_t)TLK_IRQ_FIRED, 0, (uint32_t)irq, 0); +} + +/******************************************************************************* + * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into the SP for its initialisation. + ******************************************************************************/ +static int32_t tlkd_setup(void) +{ + entry_point_info_t *tlk_ep_info; + uint32_t flags; + int32_t ret; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!tlk_ep_info) { + WARN("No SP provided. Booting device without SP" + " initialization. SMC`s destined for SP" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!tlk_ep_info->pc) + return 1; + + /* + * Inspect the SP image's SPSR and determine it's execution state + * i.e whether AArch32 or AArch64. + */ + tlkd_init_tlk_ep_state(tlk_ep_info, + (tlk_ep_info->spsr >> MODE_RW_SHIFT) & MODE_RW_MASK, + tlk_ep_info->pc, + &tlk_ctx); + + /* get a list of all S-EL1 IRQs from the platform */ + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tlkd_interrupt_handler, + flags); + if (ret != 0) { + ERROR("failed to register tlkd interrupt handler (%d)\n", ret); + } + + /* + * All TLK SPD initialization done. Now register our init function + * with BL31 for deferred invocation + */ + bl31_register_bl32_init(&tlkd_init); + + /* get a list of all S-EL1 IRQs from the platform */ + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tlkd_interrupt_handler, + flags); + if (ret != 0) { + ERROR("failed to register tlkd interrupt handler (%d)\n", ret); + } + + return 0; +} + +/******************************************************************************* + * This function passes control to the Secure Payload image (BL32) for the first + * time on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by tlkd_setup() which can be directly + * used. This function performs a synchronous entry into the Secure payload. + * The SP passes control back to this routine through a SMC. + ******************************************************************************/ +static int32_t tlkd_init(void) +{ + entry_point_info_t *tlk_entry_point; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tlk_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(tlk_entry_point); + + cm_init_my_context(tlk_entry_point); + + /* + * TLK runs only on a single CPU. Store the value of the boot + * CPU for sanity checking later. + */ + boot_cpu = plat_my_core_pos(); + + /* + * Arrange for an entry into the test secure payload. + */ + return tlkd_synchronous_sp_entry(&tlk_ctx); +} + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure payload + * to delegate work and return results back to the non-secure state. Lastly it + * will also return any information that the secure payload needs to do the + * work assigned to it. + ******************************************************************************/ +static uintptr_t tlkd_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) +{ + cpu_context_t *ns_cpu_context; + gp_regs_t *gp_regs; + uint32_t ns; + uint64_t par; + + /* Passing a NULL context is a critical programming error */ + assert(handle); + + /* These SMCs are only supported by a single CPU */ + if (boot_cpu != plat_my_core_pos()) + SMC_RET1(handle, SMC_UNK); + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + switch (smc_fid) { + + /* + * This function ID is used by SP to indicate that it was + * preempted by a non-secure world IRQ. + */ + case TLK_PREEMPTED: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET1(ns_cpu_context, x1); + + /* + * This is a request from the non-secure context to: + * + * a. register shared memory with the SP for storing it's + * activity logs. + * b. register shared memory with the SP for passing args + * required for maintaining sessions with the Trusted + * Applications. + * c. register shared persistent buffers for secure storage + * d. register NS DRAM ranges passed by Cboot + * e. register Root of Trust parameters from Cboot for Verified Boot + * f. open/close sessions + * g. issue commands to the Trusted Apps + * h. resume the preempted yielding SMC call. + */ + case TLK_REGISTER_LOGBUF: + case TLK_REGISTER_REQBUF: + case TLK_SS_REGISTER_HANDLER: + case TLK_REGISTER_NS_DRAM_RANGES: + case TLK_SET_ROOT_OF_TRUST: + case TLK_OPEN_TA_SESSION: + case TLK_CLOSE_TA_SESSION: + case TLK_TA_LAUNCH_OP: + case TLK_TA_SEND_EVENT: + case TLK_RESUME_FID: + case TLK_SET_BL_VERSION: + case TLK_LOCK_BL_INTERFACE: + case TLK_BL_RPMB_SERVICE: + + if (!ns) + SMC_RET1(handle, SMC_UNK); + + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* + * Check if we are already processing a yielding SMC + * call. Of all the supported fids, only the "resume" + * fid expects the flag to be set. + */ + if (smc_fid == TLK_RESUME_FID) { + if (!get_yield_smc_active_flag(tlk_ctx.state)) + SMC_RET1(handle, SMC_UNK); + } else { + if (get_yield_smc_active_flag(tlk_ctx.state)) + SMC_RET1(handle, SMC_UNK); + } + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * Verify if there is a valid context to use. + */ + assert(&tlk_ctx.cpu_ctx == cm_get_context(SECURE)); + + /* + * Mark the SP state as active. + */ + set_yield_smc_active_flag(tlk_ctx.state); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* + * TLK is a 32-bit Trusted OS and so expects the SMC + * arguments via r0-r7. TLK expects the monitor frame + * registers to be 64-bits long. Hence, we pass x0 in + * r0-r1, x1 in r2-r3, x3 in r4-r5 and x4 in r6-r7. + * + * As smc_fid is a uint32 value, r1 contains 0. + */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X4, (uint32_t)x2); + write_ctx_reg(gp_regs, CTX_GPREG_X5, (uint32_t)(x2 >> 32)); + write_ctx_reg(gp_regs, CTX_GPREG_X6, (uint32_t)x3); + write_ctx_reg(gp_regs, CTX_GPREG_X7, (uint32_t)(x3 >> 32)); + SMC_RET4(&tlk_ctx.cpu_ctx, smc_fid, 0, (uint32_t)x1, + (uint32_t)(x1 >> 32)); + + /* + * Translate NS/EL1-S virtual addresses. + * + * x1 = virtual address + * x3 = type (NS/S) + * + * Returns PA:lo in r0, PA:hi in r1. + */ + case TLK_VA_TRANSLATE: + + /* Should be invoked only by secure world */ + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* NS virtual addresses are 64-bit long */ + if (x3 & TLK_TRANSLATE_NS_VADDR) + x1 = (uint32_t)x1 | (x2 << 32); + + if (!x1) + SMC_RET1(handle, SMC_UNK); + + /* + * TODO: Sanity check x1. This would require platform + * support. + */ + + /* virtual address and type: ns/s */ + par = tlkd_va_translate(x1, x3); + + /* return physical address in r0-r1 */ + SMC_RET4(handle, (uint32_t)par, (uint32_t)(par >> 32), 0, 0); + + /* + * This is a request from the SP to mark completion of + * a yielding function ID. + */ + case TLK_REQUEST_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * Mark the SP state as inactive. + */ + clr_yield_smc_active_flag(tlk_ctx.state); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * This is a request completion SMC and we must switch to + * the non-secure world to pass the result. + */ + cm_el1_sysregs_context_save(SECURE); + + /* + * We are done stashing the secure context. Switch to the + * non-secure context and return the result. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + SMC_RET1(ns_cpu_context, x1); + + /* + * This function ID is used only by the SP to indicate it has + * finished initialising itself after a cold boot + */ + case TLK_ENTRY_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * SP has been successfully initialized. Register power + * management hooks with PSCI + */ + psci_register_spd_pm_hook(&tlkd_pm_ops); + + /* + * TLK reports completion. The SPD must have initiated + * the original request through a synchronous entry + * into the SP. Jump back to the original C runtime + * context. + */ + tlkd_synchronous_sp_exit(&tlk_ctx, x1); + break; + + /* + * These function IDs are used only by TLK to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. resuming itself after an earlier psci cpu_suspend + * request. + * 3. powering down after an earlier psci system_off/system_reset + * request. + */ + case TLK_SUSPEND_DONE: + case TLK_RESUME_DONE: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * TLK reports completion. TLKD must have initiated the + * original request through a synchronous entry into the SP. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + tlkd_synchronous_sp_exit(&tlk_ctx, x1); + break; + + /* + * This function ID is used by SP to indicate that it has completed + * handling the secure interrupt. + */ + case TLK_IRQ_DONE: + + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + + /* save secure world context */ + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the SP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0(ns_cpu_context); + + /* + * Return the number of service function IDs implemented to + * provide service to non-secure + */ + case TOS_CALL_COUNT: + SMC_RET1(handle, TLK_NUM_FID); + + /* + * Return TLK's UID to the caller + */ + case TOS_UID: + SMC_UUID_RET(handle, tlk_uuid); + + /* + * Return the version of current implementation + */ + case TOS_CALL_VERSION: + SMC_RET2(handle, TLK_VERSION_MAJOR, TLK_VERSION_MINOR); + + default: + WARN("%s: Unhandled SMC: 0x%x\n", __func__, smc_fid); + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + tlkd_setup, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + tlkd_tos_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tlkd_tap_fast, + + OEN_TAP_START, + OEN_TAP_END, + SMC_TYPE_FAST, + NULL, + tlkd_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + tlkd_tap_std, + + OEN_TAP_START, + OEN_TAP_END, + SMC_TYPE_YIELD, + NULL, + tlkd_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c b/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c new file mode 100644 index 0000000..ed5bf77 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2020, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "tlkd_private.h" + +extern tlk_context_t tlk_ctx; + +#define MPIDR_CPU0 0x80000000 + +/******************************************************************************* + * Return the type of payload TLKD is dealing with. Report the current + * resident cpu (mpidr format) if it is a UP/UP migratable payload. + ******************************************************************************/ +static int32_t cpu_migrate_info(u_register_t *resident_cpu) +{ + /* the payload runs only on CPU0 */ + *resident_cpu = MPIDR_CPU0; + + /* Uniprocessor, not migrate capable payload */ + return PSCI_TOS_NOT_UP_MIG_CAP; +} + +/******************************************************************************* + * This cpu is being suspended. Inform TLK of the SYSTEM_SUSPEND event, so + * that it can pass this information to its Trusted Apps. + ******************************************************************************/ +static void cpu_suspend_handler(u_register_t suspend_level) +{ + gp_regs_t *gp_regs; + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int32_t rc = 0; + + /* + * TLK runs only on CPU0 and suspends its Trusted Apps during + * SYSTEM_SUSPEND. It has no role to play during CPU_SUSPEND. + */ + if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) + return; + + /* pass system suspend event to TLK */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_SUSPEND); + + /* Program the entry point and enter TLK */ + rc = tlkd_synchronous_sp_entry(&tlk_ctx); + + /* + * Read the response from TLK. A non-zero return means that + * something went wrong while communicating with it. + */ + if (rc != 0) + panic(); +} + +/******************************************************************************* + * This cpu is being resumed. Inform TLK of the SYSTEM_SUSPEND exit, so + * that it can pass this information to its Trusted Apps. + ******************************************************************************/ +static void cpu_resume_handler(u_register_t suspend_level) +{ + gp_regs_t *gp_regs; + int cpu = read_mpidr() & MPIDR_CPU_MASK; + int32_t rc = 0; + + /* + * TLK runs only on CPU0 and resumes its Trusted Apps during + * SYSTEM_SUSPEND exit. It has no role to play during CPU_SUSPEND + * exit. + */ + if ((cpu != 0) || (suspend_level != PLAT_MAX_PWR_LVL)) + return; + + /* pass system resume event to TLK */ + gp_regs = get_gpregs_ctx(&tlk_ctx.cpu_ctx); + write_ctx_reg(gp_regs, CTX_GPREG_X0, TLK_SYSTEM_RESUME); + + /* Program the entry point and enter TLK */ + rc = tlkd_synchronous_sp_entry(&tlk_ctx); + + /* + * Read the response from TLK. A non-zero return means that + * something went wrong while communicating with it. + */ + if (rc != 0) + panic(); +} + +/******************************************************************************* + * Structure populated by the Dispatcher to be given a chance to perform any + * bookkeeping before PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t tlkd_pm_ops = { + .svc_migrate_info = cpu_migrate_info, + .svc_suspend = cpu_suspend_handler, + .svc_suspend_finish = cpu_resume_handler, +}; diff --git a/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h b/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h new file mode 100644 index 0000000..5d5d0e8 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tlkd/tlkd_private.h @@ -0,0 +1,124 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TLKD_PRIVATE_H +#define TLKD_PRIVATE_H + +#include + +#include +#include +#include +#include + +/* + * This flag is used by the TLKD to determine if the SP is servicing a yielding + * SMC request prior to programming the next entry into the SP e.g. if SP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the SP was + * previously doing arrives, then this flag will be help the TLKD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define YIELD_SMC_ACTIVE_FLAG_SHIFT 2 +#define YIELD_SMC_ACTIVE_FLAG_MASK 1 +#define get_yield_smc_active_flag(state) \ + (((state) >> YIELD_SMC_ACTIVE_FLAG_SHIFT) \ + & YIELD_SMC_ACTIVE_FLAG_MASK) +#define set_yield_smc_active_flag(state) ((state) |= \ + (1 << YIELD_SMC_ACTIVE_FLAG_SHIFT)) +#define clr_yield_smc_active_flag(state) ((state) &= \ + ~(YIELD_SMC_ACTIVE_FLAG_MASK \ + << YIELD_SMC_ACTIVE_FLAG_SHIFT)) + +/******************************************************************************* + * Translate virtual address received from the NS world + ******************************************************************************/ +#define TLK_TRANSLATE_NS_VADDR 4 + +/******************************************************************************* + * Secure Payload execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define SP_AARCH32 MODE_RW_32 +#define SP_AARCH64 MODE_RW_64 + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define TLKD_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define TLKD_C_RT_CTX_X19 0x0 +#define TLKD_C_RT_CTX_X20 0x8 +#define TLKD_C_RT_CTX_X21 0x10 +#define TLKD_C_RT_CTX_X22 0x18 +#define TLKD_C_RT_CTX_X23 0x20 +#define TLKD_C_RT_CTX_X24 0x28 +#define TLKD_C_RT_CTX_X25 0x30 +#define TLKD_C_RT_CTX_X26 0x38 +#define TLKD_C_RT_CTX_X27 0x40 +#define TLKD_C_RT_CTX_X28 0x48 +#define TLKD_C_RT_CTX_X29 0x50 +#define TLKD_C_RT_CTX_X30 0x58 +#define TLKD_C_RT_CTX_SIZE 0x60 +#define TLKD_C_RT_CTX_ENTRIES (TLKD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, TLKD_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TLKD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_tlkd_c_rt_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the SPD to maintain the per-cpu state of the SP. + * 'state' - collection of flags to track SP state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into the SP. + * 'cpu_ctx' - space to maintain SP architectural state + * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations + * which will queried using the TSP_GET_ARGS SMC by TSP. + ******************************************************************************/ +typedef struct tlk_context { + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; +} tlk_context_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t tlkd_va_translate(uintptr_t va, int type); +uint64_t tlkd_enter_sp(uint64_t *c_rt_ctx); +void __dead2 tlkd_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t tlkd_synchronous_sp_entry(tlk_context_t *tlk_ctx); +void __dead2 tlkd_synchronous_sp_exit(tlk_context_t *tlk_ctx, + uint64_t ret); +void tlkd_init_tlk_ep_state(struct entry_point_info *tlk_entry_point, + uint32_t rw, + uint64_t pc, + tlk_context_t *tlk_ctx); + +#endif /*__ASSEMBLER__*/ + +#endif /* TLKD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c new file mode 100644 index 0000000..5c3a628 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include + +#include "generic-arm64-smcall.h" + +#ifndef PLAT_ARM_GICD_BASE +#ifdef GICD_BASE +#define PLAT_ARM_GICD_BASE GICD_BASE +#define PLAT_ARM_GICC_BASE GICC_BASE +#ifdef GICR_BASE +#define PLAT_ARM_GICR_BASE GICR_BASE +#endif +#else +#error PLAT_ARM_GICD_BASE or GICD_BASE must be defined +#endif +#endif + +#ifndef PLAT_ARM_GICR_BASE +#define PLAT_ARM_GICR_BASE SMC_UNK +#endif + +int trusty_disable_serial_debug; + +struct dputc_state { + char linebuf[128]; + unsigned l; +}; + +static struct dputc_state dputc_state[2]; + +static void trusty_dputc(char ch, int secure) +{ + unsigned i; + struct dputc_state *s = &dputc_state[!secure]; + + if (trusty_disable_serial_debug) + return; + + s->linebuf[s->l++] = ch; + if (s->l == sizeof(s->linebuf) || ch == '\n') { + if (secure) + printf("secure os: "); + else + printf("non-secure os: "); + for (i = 0; i < s->l; i++) { + putchar(s->linebuf[i]); + } + if (ch != '\n') { + printf(" <...>\n"); + } + s->l = 0; + } +} + +static uint64_t trusty_get_reg_base(uint32_t reg) +{ + switch (reg) { + case SMC_GET_GIC_BASE_GICD: + return PLAT_ARM_GICD_BASE; + + case SMC_GET_GIC_BASE_GICC: + return PLAT_ARM_GICC_BASE; + + case SMC_GET_GIC_BASE_GICR: + return PLAT_ARM_GICR_BASE; + + default: + NOTICE("%s(0x%x) unknown reg\n", __func__, reg); + return SMC_UNK; + } +} + +static uintptr_t trusty_generic_platform_smc(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 SMC_FC_DEBUG_PUTC: + trusty_dputc(x1, is_caller_secure(flags)); + SMC_RET1(handle, 0); + + case SMC_FC_GET_REG_BASE: + case SMC_FC64_GET_REG_BASE: + SMC_RET1(handle, trusty_get_reg_base(x1)); + + default: + NOTICE("%s(0x%x, 0x%lx) unknown smc\n", __func__, smc_fid, x1); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + trusty_fast, + + SMC_ENTITY_PLATFORM_MONITOR, + SMC_ENTITY_PLATFORM_MONITOR, + SMC_TYPE_FAST, + NULL, + trusty_generic_platform_smc +); + diff --git a/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h new file mode 100644 index 0000000..ac03469 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "smcall.h" + +#define SMC_ENTITY_PLATFORM_MONITOR 61 + +/* + * SMC calls implemented by EL3 monitor + */ + +/* + * Write character in r1 to debug console + */ +#define SMC_FC_DEBUG_PUTC SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x0) + +/* + * Get register base address + * r1: SMC_GET_GIC_BASE_GICD or SMC_GET_GIC_BASE_GICC + */ +#define SMC_GET_GIC_BASE_GICD 0 +#define SMC_GET_GIC_BASE_GICC 1 +#define SMC_GET_GIC_BASE_GICR 2 +#define SMC_FC_GET_REG_BASE SMC_FASTCALL_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) +#define SMC_FC64_GET_REG_BASE SMC_FASTCALL64_NR(SMC_ENTITY_PLATFORM_MONITOR, 0x1) diff --git a/arm-trusted-firmware/services/spd/trusty/sm_err.h b/arm-trusted-firmware/services/spd/trusty/sm_err.h new file mode 100644 index 0000000..80a8748 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/sm_err.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SM_ERR_H +#define SM_ERR_H + +/* Errors from the secure monitor */ +#define SM_ERR_UNDEFINED_SMC 0xFFFFFFFF /* Unknown SMC (defined by ARM DEN 0028A(0.9.0) */ +#define SM_ERR_INVALID_PARAMETERS -2 +#define SM_ERR_INTERRUPTED -3 /* Got interrupted. Call back with restart SMC */ +#define SM_ERR_UNEXPECTED_RESTART -4 /* Got an restart SMC when we didn't expect it */ +#define SM_ERR_BUSY -5 /* Temporarily busy. Call back with original args */ +#define SM_ERR_INTERLEAVED_SMC -6 /* Got a trusted_service SMC when a restart SMC is required */ +#define SM_ERR_INTERNAL_FAILURE -7 /* Unknown error */ +#define SM_ERR_NOT_SUPPORTED -8 +#define SM_ERR_NOT_ALLOWED -9 /* SMC call not allowed */ +#define SM_ERR_END_OF_INPUT -10 + +#endif /* SM_ERR_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/smcall.h b/arm-trusted-firmware/services/spd/trusty/smcall.h new file mode 100644 index 0000000..c66f7db --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/smcall.h @@ -0,0 +1,82 @@ +/* + * 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 SMCALL_H +#define SMCALL_H + +#define SMC_NUM_ENTITIES 64U +#define SMC_NUM_ARGS 4U +#define SMC_NUM_PARAMS (SMC_NUM_ARGS - 1U) + +#define SMC_IS_FASTCALL(smc_nr) ((smc_nr) & 0x80000000U) +#define SMC_IS_SMC64(smc_nr) ((smc_nr) & 0x40000000U) +#define SMC_ENTITY(smc_nr) (((smc_nr) & 0x3F000000U) >> 24U) +#define SMC_FUNCTION(smc_nr) ((smc_nr) & 0x0000FFFFU) + +#define SMC_NR(entity, fn, fastcall, smc64) \ + (((((uint32_t)(fastcall)) & 0x1U) << 31U) | \ + (((smc64) & 0x1U) << 30U) | \ + (((entity) & 0x3FU) << 24U) | \ + ((fn) & 0xFFFFU)) + +#define SMC_FASTCALL_NR(entity, fn) SMC_NR((entity), (fn), 1U, 0U) +#define SMC_FASTCALL64_NR(entity, fn) SMC_NR((entity), (fn), 1U, 1U) +#define SMC_YIELDCALL_NR(entity, fn) SMC_NR((entity), (fn), 0U, 0U) +#define SMC_YIELDCALL64_NR(entity, fn) SMC_NR((entity), (fn), 0U, 1U) + +#define SMC_ENTITY_ARCH 0U /* ARM Architecture calls */ +#define SMC_ENTITY_CPU 1U /* CPU Service calls */ +#define SMC_ENTITY_SIP 2U /* SIP Service calls */ +#define SMC_ENTITY_OEM 3U /* OEM Service calls */ +#define SMC_ENTITY_STD 4U /* Standard Service calls */ +#define SMC_ENTITY_RESERVED 5U /* Reserved for future use */ +#define SMC_ENTITY_TRUSTED_APP 48U /* Trusted Application calls */ +#define SMC_ENTITY_TRUSTED_OS 50U /* Trusted OS calls */ +#define SMC_ENTITY_LOGGING 51U /* Used for secure -> nonsecure logging */ +#define SMC_ENTITY_SECURE_MONITOR 60U /* Trusted OS calls internal to secure monitor */ + +/* FC = Fast call, YC = Yielding call */ +#define SMC_YC_RESTART_LAST SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) +#define SMC_YC_NOP SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1U) + +/* + * Return from secure os to non-secure os with return value in r1 + */ +#define SMC_YC_NS_RETURN SMC_YIELDCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) + +#define SMC_FC_RESERVED SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 0U) +#define SMC_FC_FIQ_EXIT SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 1U) +#define SMC_FC_REQUEST_FIQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 2U) +#define SMC_FC_GET_NEXT_IRQ SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 3U) +#define SMC_FC_FIQ_ENTER SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 4U) + +#define SMC_FC64_SET_FIQ_HANDLER SMC_FASTCALL64_NR(SMC_ENTITY_SECURE_MONITOR, 5U) +#define SMC_FC64_GET_FIQ_REGS SMC_FASTCALL64_NR (SMC_ENTITY_SECURE_MONITOR, 6U) + +#define SMC_FC_CPU_SUSPEND SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 7U) +#define SMC_FC_CPU_RESUME SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 8U) + +#define SMC_FC_AARCH_SWITCH SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 9U) +#define SMC_FC_GET_VERSION_STR SMC_FASTCALL_NR (SMC_ENTITY_SECURE_MONITOR, 10U) + +/* Trusted OS entity calls */ +#define SMC_YC_VIRTIO_GET_DESCR SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 20U) +#define SMC_YC_VIRTIO_START SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 21U) +#define SMC_YC_VIRTIO_STOP SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 22U) + +#define SMC_YC_VDEV_RESET SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 23U) +#define SMC_YC_VDEV_KICK_VQ SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 24U) +#define SMC_YC_SET_ROT_PARAMS SMC_YIELDCALL_NR(SMC_ENTITY_TRUSTED_OS, 65535U) + +/* + * Standard Trusted OS Function IDs that fall under Trusted OS call range + * according to SMC calling convention + */ +#define SMC_FC64_GET_UUID SMC_FASTCALL64_NR(63U, 0xFF01U) /* Implementation UID */ +#define SMC_FC_GET_UUID SMC_FASTCALL_NR(63U, 0xFF01U) /* Implementation.UID */ + +#endif /* SMCALL_H */ diff --git a/arm-trusted-firmware/services/spd/trusty/trusty.c b/arm-trusted-firmware/services/spd/trusty/trusty.c new file mode 100644 index 0000000..7daebcd --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty.c @@ -0,0 +1,541 @@ +/* + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sm_err.h" +#include "smcall.h" + +/* Trusty UID: RFC-4122 compliant UUID version 4 */ +DEFINE_SVC_UUID2(trusty_uuid, + 0x40ee25f0, 0xa2bc, 0x304c, 0x8c, 0x4c, + 0xa1, 0x73, 0xc5, 0x7d, 0x8a, 0xf1); + +/* macro to check if Hypervisor is enabled in the HCR_EL2 register */ +#define HYP_ENABLE_FLAG 0x286001U + +/* length of Trusty's input parameters (in bytes) */ +#define TRUSTY_PARAMS_LEN_BYTES (4096U * 2) + +struct trusty_stack { + uint8_t space[PLATFORM_STACK_SIZE] __aligned(16); + uint32_t end; +}; + +struct trusty_cpu_ctx { + cpu_context_t cpu_ctx; + void *saved_sp; + uint32_t saved_security_state; + int32_t fiq_handler_active; + uint64_t fiq_handler_pc; + uint64_t fiq_handler_cpsr; + uint64_t fiq_handler_sp; + uint64_t fiq_pc; + uint64_t fiq_cpsr; + uint64_t fiq_sp_el1; + gp_regs_t fiq_gpregs; + struct trusty_stack secure_stack; +}; + +struct smc_args { + uint64_t r0; + uint64_t r1; + uint64_t r2; + uint64_t r3; + uint64_t r4; + uint64_t r5; + uint64_t r6; + uint64_t r7; +}; + +static struct trusty_cpu_ctx trusty_cpu_ctx[PLATFORM_CORE_COUNT]; + +struct smc_args trusty_init_context_stack(void **sp, void *new_stack); +struct smc_args trusty_context_switch_helper(void **sp, void *smc_params); + +static uint32_t current_vmid; + +static struct trusty_cpu_ctx *get_trusty_ctx(void) +{ + return &trusty_cpu_ctx[plat_my_core_pos()]; +} + +static bool is_hypervisor_mode(void) +{ + uint64_t hcr = read_hcr(); + + return ((hcr & HYP_ENABLE_FLAG) != 0U) ? true : false; +} + +static struct smc_args trusty_context_switch(uint32_t security_state, uint64_t r0, + uint64_t r1, uint64_t r2, uint64_t r3) +{ + struct smc_args args, ret_args; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + struct trusty_cpu_ctx *ctx_smc; + + assert(ctx->saved_security_state != security_state); + + args.r7 = 0; + if (is_hypervisor_mode()) { + /* According to the ARM DEN0028A spec, VMID is stored in x7 */ + ctx_smc = cm_get_context(NON_SECURE); + assert(ctx_smc != NULL); + args.r7 = SMC_GET_GP(ctx_smc, CTX_GPREG_X7); + } + /* r4, r5, r6 reserved for future use. */ + args.r6 = 0; + args.r5 = 0; + args.r4 = 0; + args.r3 = r3; + args.r2 = r2; + args.r1 = r1; + args.r0 = r0; + + /* + * To avoid the additional overhead in PSCI flow, skip FP context + * saving/restoring in case of CPU suspend and resume, assuming that + * when it's needed the PSCI caller has preserved FP context before + * going here. + */ + if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) + fpregs_context_save(get_fpregs_ctx(cm_get_context(security_state))); + cm_el1_sysregs_context_save(security_state); + + ctx->saved_security_state = security_state; + ret_args = trusty_context_switch_helper(&ctx->saved_sp, &args); + + assert(ctx->saved_security_state == ((security_state == 0U) ? 1U : 0U)); + + cm_el1_sysregs_context_restore(security_state); + if (r0 != SMC_FC_CPU_SUSPEND && r0 != SMC_FC_CPU_RESUME) + fpregs_context_restore(get_fpregs_ctx(cm_get_context(security_state))); + + cm_set_next_eret_context(security_state); + + return ret_args; +} + +static uint64_t trusty_fiq_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + struct smc_args ret; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + assert(!is_caller_secure(flags)); + + ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_ENTER, 0, 0, 0); + if (ret.r0 != 0U) { + SMC_RET0(handle); + } + + if (ctx->fiq_handler_active != 0) { + INFO("%s: fiq handler already active\n", __func__); + SMC_RET0(handle); + } + + ctx->fiq_handler_active = 1; + (void)memcpy(&ctx->fiq_gpregs, get_gpregs_ctx(handle), sizeof(ctx->fiq_gpregs)); + ctx->fiq_pc = SMC_GET_EL3(handle, CTX_ELR_EL3); + ctx->fiq_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); + ctx->fiq_sp_el1 = read_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1); + + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_handler_sp); + cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_handler_pc, (uint32_t)ctx->fiq_handler_cpsr); + + SMC_RET0(handle); +} + +static uint64_t trusty_set_fiq_handler(void *handle, uint64_t cpu, + uint64_t handler, uint64_t stack) +{ + struct trusty_cpu_ctx *ctx; + + if (cpu >= (uint64_t)PLATFORM_CORE_COUNT) { + ERROR("%s: cpu %" PRId64 " >= %d\n", __func__, cpu, PLATFORM_CORE_COUNT); + return (uint64_t)SM_ERR_INVALID_PARAMETERS; + } + + ctx = &trusty_cpu_ctx[cpu]; + ctx->fiq_handler_pc = handler; + ctx->fiq_handler_cpsr = SMC_GET_EL3(handle, CTX_SPSR_EL3); + ctx->fiq_handler_sp = stack; + + SMC_RET1(handle, 0); +} + +static uint64_t trusty_get_fiq_regs(void *handle) +{ + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + uint64_t sp_el0 = read_ctx_reg(&ctx->fiq_gpregs, CTX_GPREG_SP_EL0); + + SMC_RET4(handle, ctx->fiq_pc, ctx->fiq_cpsr, sp_el0, ctx->fiq_sp_el1); +} + +static uint64_t trusty_fiq_exit(void *handle, uint64_t x1, uint64_t x2, uint64_t x3) +{ + struct smc_args ret; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + if (ctx->fiq_handler_active == 0) { + NOTICE("%s: fiq handler not active\n", __func__); + SMC_RET1(handle, (uint64_t)SM_ERR_INVALID_PARAMETERS); + } + + ret = trusty_context_switch(NON_SECURE, SMC_FC_FIQ_EXIT, 0, 0, 0); + if (ret.r0 != 1U) { + INFO("%s(%p) SMC_FC_FIQ_EXIT returned unexpected value, %" PRId64 "\n", + __func__, handle, ret.r0); + } + + /* + * Restore register state to state recorded on fiq entry. + * + * x0, sp_el1, pc and cpsr need to be restored because el1 cannot + * restore them. + * + * x1-x4 and x8-x17 need to be restored here because smc_handler64 + * corrupts them (el1 code also restored them). + */ + (void)memcpy(get_gpregs_ctx(handle), &ctx->fiq_gpregs, sizeof(ctx->fiq_gpregs)); + ctx->fiq_handler_active = 0; + write_ctx_reg(get_el1_sysregs_ctx(handle), CTX_SP_EL1, ctx->fiq_sp_el1); + cm_set_elr_spsr_el3(NON_SECURE, ctx->fiq_pc, (uint32_t)ctx->fiq_cpsr); + + SMC_RET0(handle); +} + +static uintptr_t trusty_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) +{ + struct smc_args ret; + uint32_t vmid = 0U; + entry_point_info_t *ep_info = bl31_plat_get_next_image_ep_info(SECURE); + + /* + * Return success for SET_ROT_PARAMS if Trusty is not present, as + * Verified Boot is not even supported and returning success here + * would not compromise the boot process. + */ + if ((ep_info == NULL) && (smc_fid == SMC_YC_SET_ROT_PARAMS)) { + SMC_RET1(handle, 0); + } else if (ep_info == NULL) { + SMC_RET1(handle, SMC_UNK); + } else { + ; /* do nothing */ + } + + if (is_caller_secure(flags)) { + if (smc_fid == SMC_YC_NS_RETURN) { + ret = trusty_context_switch(SECURE, x1, 0, 0, 0); + SMC_RET8(handle, ret.r0, ret.r1, ret.r2, ret.r3, + ret.r4, ret.r5, ret.r6, ret.r7); + } + INFO("%s (0x%x, 0x%lx, 0x%lx, 0x%lx, 0x%lx, %p, %p, 0x%lx) \ + cpu %d, unknown smc\n", + __func__, smc_fid, x1, x2, x3, x4, cookie, handle, flags, + plat_my_core_pos()); + SMC_RET1(handle, SMC_UNK); + } else { + switch (smc_fid) { + case SMC_FC64_GET_UUID: + case SMC_FC_GET_UUID: + /* provide the UUID for the service to the client */ + SMC_UUID_RET(handle, trusty_uuid); + break; + case SMC_FC64_SET_FIQ_HANDLER: + return trusty_set_fiq_handler(handle, x1, x2, x3); + case SMC_FC64_GET_FIQ_REGS: + return trusty_get_fiq_regs(handle); + case SMC_FC_FIQ_EXIT: + return trusty_fiq_exit(handle, x1, x2, x3); + default: + /* Not all OENs greater than SMC_ENTITY_SECURE_MONITOR are supported */ + if (SMC_ENTITY(smc_fid) > SMC_ENTITY_SECURE_MONITOR) { + VERBOSE("%s: unsupported SMC FID (0x%x)\n", __func__, smc_fid); + SMC_RET1(handle, SMC_UNK); + } + + if (is_hypervisor_mode()) + vmid = SMC_GET_GP(handle, CTX_GPREG_X7); + + if ((current_vmid != 0) && (current_vmid != vmid)) { + /* This message will cause SMC mechanism + * abnormal in multi-guest environment. + * Change it to WARN in case you need it. + */ + VERBOSE("Previous SMC not finished.\n"); + SMC_RET1(handle, SM_ERR_BUSY); + } + current_vmid = vmid; + ret = trusty_context_switch(NON_SECURE, smc_fid, x1, + x2, x3); + current_vmid = 0; + SMC_RET1(handle, ret.r0); + } + } +} + +static int32_t trusty_init(void) +{ + entry_point_info_t *ep_info; + struct smc_args zero_args = {0}; + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + uint32_t cpu = plat_my_core_pos(); + uint64_t reg_width = GET_RW(read_ctx_reg(get_el3state_ctx(&ctx->cpu_ctx), + CTX_SPSR_EL3)); + + /* + * Get information about the Trusty image. Its absence is a critical + * failure. + */ + ep_info = bl31_plat_get_next_image_ep_info(SECURE); + assert(ep_info != NULL); + + fpregs_context_save(get_fpregs_ctx(cm_get_context(NON_SECURE))); + cm_el1_sysregs_context_save(NON_SECURE); + + cm_set_context(&ctx->cpu_ctx, SECURE); + cm_init_my_context(ep_info); + + /* + * Adjust secondary cpu entry point for 32 bit images to the + * end of exception vectors + */ + if ((cpu != 0U) && (reg_width == MODE_RW_32)) { + INFO("trusty: cpu %d, adjust entry point to 0x%lx\n", + cpu, ep_info->pc + (1U << 5)); + cm_set_elr_el3(SECURE, ep_info->pc + (1U << 5)); + } + + cm_el1_sysregs_context_restore(SECURE); + fpregs_context_restore(get_fpregs_ctx(cm_get_context(SECURE))); + cm_set_next_eret_context(SECURE); + + ctx->saved_security_state = ~0U; /* initial saved state is invalid */ + (void)trusty_init_context_stack(&ctx->saved_sp, &ctx->secure_stack.end); + + (void)trusty_context_switch_helper(&ctx->saved_sp, &zero_args); + + cm_el1_sysregs_context_restore(NON_SECURE); + fpregs_context_restore(get_fpregs_ctx(cm_get_context(NON_SECURE))); + cm_set_next_eret_context(NON_SECURE); + + return 1; +} + +static void trusty_cpu_suspend(uint32_t off) +{ + struct smc_args ret; + + ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_SUSPEND, off, 0, 0); + if (ret.r0 != 0U) { + INFO("%s: cpu %d, SMC_FC_CPU_SUSPEND returned unexpected value, %" PRId64 "\n", + __func__, plat_my_core_pos(), ret.r0); + } +} + +static void trusty_cpu_resume(uint32_t on) +{ + struct smc_args ret; + + ret = trusty_context_switch(NON_SECURE, SMC_FC_CPU_RESUME, on, 0, 0); + if (ret.r0 != 0U) { + INFO("%s: cpu %d, SMC_FC_CPU_RESUME returned unexpected value, %" PRId64 "\n", + __func__, plat_my_core_pos(), ret.r0); + } +} + +static int32_t trusty_cpu_off_handler(u_register_t max_off_lvl) +{ + trusty_cpu_suspend(max_off_lvl); + + return 0; +} + +static void trusty_cpu_on_finish_handler(u_register_t max_off_lvl) +{ + struct trusty_cpu_ctx *ctx = get_trusty_ctx(); + + if (ctx->saved_sp == NULL) { + (void)trusty_init(); + } else { + trusty_cpu_resume(max_off_lvl); + } +} + +static void trusty_cpu_suspend_handler(u_register_t max_off_lvl) +{ + trusty_cpu_suspend(max_off_lvl); +} + +static void trusty_cpu_suspend_finish_handler(u_register_t max_off_lvl) +{ + trusty_cpu_resume(max_off_lvl); +} + +static const spd_pm_ops_t trusty_pm = { + .svc_off = trusty_cpu_off_handler, + .svc_suspend = trusty_cpu_suspend_handler, + .svc_on_finish = trusty_cpu_on_finish_handler, + .svc_suspend_finish = trusty_cpu_suspend_finish_handler, +}; + +void plat_trusty_set_boot_args(aapcs64_params_t *args); + +#if !defined(TSP_SEC_MEM_SIZE) && defined(BL32_MEM_SIZE) +#define TSP_SEC_MEM_SIZE BL32_MEM_SIZE +#endif + +#ifdef TSP_SEC_MEM_SIZE +#pragma weak plat_trusty_set_boot_args +void plat_trusty_set_boot_args(aapcs64_params_t *args) +{ + args->arg0 = TSP_SEC_MEM_SIZE; +} +#endif + +static int32_t trusty_setup(void) +{ + entry_point_info_t *ep_info; + uint32_t instr; + uint32_t flags; + int32_t ret; + bool aarch32 = false; + + /* Get trusty's entry point info */ + ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (ep_info == NULL) { + VERBOSE("Trusty image missing.\n"); + return -1; + } + + /* memmap first page of trusty's code memory before peeking */ + ret = mmap_add_dynamic_region(ep_info->pc, /* PA */ + ep_info->pc, /* VA */ + PAGE_SIZE, /* size */ + MT_SECURE | MT_RW_DATA); /* attrs */ + assert(ret == 0); + + /* peek into trusty's code to see if we have a 32-bit or 64-bit image */ + instr = *(uint32_t *)ep_info->pc; + + if (instr >> 24 == 0xeaU) { + INFO("trusty: Found 32 bit image\n"); + aarch32 = true; + } else if (instr >> 8 == 0xd53810U || instr >> 16 == 0x9400U) { + INFO("trusty: Found 64 bit image\n"); + } else { + ERROR("trusty: Found unknown image, 0x%x\n", instr); + return -1; + } + + /* unmap trusty's memory page */ + (void)mmap_remove_dynamic_region(ep_info->pc, PAGE_SIZE); + + SET_PARAM_HEAD(ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + if (!aarch32) + ep_info->spsr = SPSR_64(MODE_EL1, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + else + ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + (void)memset(&ep_info->args, 0, sizeof(ep_info->args)); + plat_trusty_set_boot_args(&ep_info->args); + + /* register init handler */ + bl31_register_bl32_init(trusty_init); + + /* register power management hooks */ + psci_register_spd_pm_hook(&trusty_pm); + + /* register interrupt handler */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + ret = register_interrupt_type_handler(INTR_TYPE_S_EL1, + trusty_fiq_handler, + flags); + if (ret != 0) { + VERBOSE("trusty: failed to register fiq handler, ret = %d\n", ret); + } + + if (aarch32) { + entry_point_info_t *ns_ep_info; + uint32_t spsr; + + ns_ep_info = bl31_plat_get_next_image_ep_info(NON_SECURE); + if (ns_ep_info == NULL) { + NOTICE("Trusty: non-secure image missing.\n"); + return -1; + } + spsr = ns_ep_info->spsr; + if (GET_RW(spsr) == MODE_RW_64 && GET_EL(spsr) == MODE_EL2) { + spsr &= ~(MODE_EL_MASK << MODE_EL_SHIFT); + spsr |= MODE_EL1 << MODE_EL_SHIFT; + } + if (GET_RW(spsr) == MODE_RW_32 && GET_M32(spsr) == MODE32_hyp) { + spsr &= ~(MODE32_MASK << MODE32_SHIFT); + spsr |= MODE32_svc << MODE32_SHIFT; + } + if (spsr != ns_ep_info->spsr) { + NOTICE("Trusty: Switch bl33 from EL2 to EL1 (spsr 0x%x -> 0x%x)\n", + ns_ep_info->spsr, spsr); + ns_ep_info->spsr = spsr; + } + } + + return 0; +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + trusty_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + trusty_setup, + trusty_smc_handler +); + +/* Define a SPD runtime service descriptor for yielding SMC calls */ +DECLARE_RT_SVC( + trusty_std, + + OEN_TAP_START, + SMC_ENTITY_SECURE_MONITOR, + SMC_TYPE_YIELD, + NULL, + trusty_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/trusty/trusty.mk b/arm-trusted-firmware/services/spd/trusty/trusty.mk new file mode 100644 index 0000000..43b80bb --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty.mk @@ -0,0 +1,18 @@ +# +# Copyright (c) 2016-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +SPD_INCLUDES := + +SPD_SOURCES := services/spd/trusty/trusty.c \ + services/spd/trusty/trusty_helpers.S + +ifeq (${TRUSTY_SPD_WITH_GENERIC_SERVICES},1) +SPD_SOURCES += services/spd/trusty/generic-arm64-smcall.c +endif + +NEED_BL32 := yes + +CTX_INCLUDE_FPREGS := 1 diff --git a/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S b/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S new file mode 100644 index 0000000..da5cb57 --- /dev/null +++ b/arm-trusted-firmware/services/spd/trusty/trusty_helpers.S @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +.macro push ra, rb, sp=sp + stp \ra, \rb, [\sp,#-16]! +.endm + +.macro pop ra, rb, sp=sp + ldp \ra, \rb, [\sp], #16 +.endm + + .global trusty_context_switch_helper +func trusty_context_switch_helper + push x8, xzr + push x19, x20 + push x21, x22 + push x23, x24 + push x25, x26 + push x27, x28 + push x29, x30 + + mov x9, sp + ldr x10, [x0] + mov sp, x10 + str x9, [x0] + + pop x29, x30 + pop x27, x28 + pop x25, x26 + pop x23, x24 + pop x21, x22 + pop x19, x20 + pop x8, xzr + + ldr x2, [x1] + ldr x3, [x1, #0x08] + ldr x4, [x1, #0x10] + ldr x5, [x1, #0x18] + ldr x6, [x1, #0x20] + ldr x7, [x1, #0x28] + ldr x10, [x1, #0x30] + ldr x11, [x1, #0x38] + + stp x2, x3, [x8] + stp x4, x5, [x8, #16] + stp x6, x7, [x8, #32] + stp x10, x11, [x8, #48] + + ret +endfunc trusty_context_switch_helper + + .global trusty_init_context_stack +func trusty_init_context_stack + push x8, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + push xzr, xzr, x1 + adr x9, el3_exit + push xzr, x9, x1 + str x1, [x0] + ret +endfunc trusty_init_context_stack diff --git a/arm-trusted-firmware/services/spd/tspd/tspd.mk b/arm-trusted-firmware/services/spd/tspd/tspd.mk new file mode 100644 index 0000000..bda8338 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd.mk @@ -0,0 +1,46 @@ +# +# Copyright (c) 2013-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +TSPD_DIR := services/spd/tspd + +ifeq (${ERROR_DEPRECATED},0) +SPD_INCLUDES := -Iinclude/bl32/tsp +endif + +SPD_SOURCES := services/spd/tspd/tspd_common.c \ + services/spd/tspd/tspd_helpers.S \ + services/spd/tspd/tspd_main.c \ + services/spd/tspd/tspd_pm.c + +# This dispatcher is paired with a Test Secure Payload source and we intend to +# build the Test Secure Payload along with this dispatcher. +# +# In cases where an associated Secure Payload lies outside this build +# system/source tree, the the dispatcher Makefile can either invoke an external +# build command or assume it pre-built + +BL32_ROOT := bl32/tsp + +# Include SP's Makefile. The assumption is that the TSP's build system is +# compatible with that of Trusted Firmware, and it'll add and populate necessary +# build targets and variables +include ${BL32_ROOT}/tsp.mk + +# Let the top-level Makefile know that we intend to build the SP from source +NEED_BL32 := yes + +# Flag used to enable routing of non-secure interrupts to EL3 when they are +# generated while the code is executing in S-EL1/0. +TSP_NS_INTR_ASYNC_PREEMPT := 0 + +ifeq ($(EL3_EXCEPTION_HANDLING),1) +ifeq ($(TSP_NS_INTR_ASYNC_PREEMPT),0) +$(error When EL3_EXCEPTION_HANDLING=1, TSP_NS_INTR_ASYNC_PREEMPT must also be 1) +endif +endif + +$(eval $(call assert_boolean,TSP_NS_INTR_ASYNC_PREEMPT)) +$(eval $(call add_define,TSP_NS_INTR_ASYNC_PREEMPT)) diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_common.c b/arm-trusted-firmware/services/spd/tspd/tspd_common.c new file mode 100644 index 0000000..063fd01 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_common.c @@ -0,0 +1,140 @@ +/* + * Copyright (c) 2013-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * Given a secure payload entrypoint info pointer, entry point PC, register + * width, cpu id & pointer to a context data structure, this function will + * initialize tsp context and entry point info for the secure payload + ******************************************************************************/ +void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point, + uint32_t rw, + uint64_t pc, + tsp_context_t *tsp_ctx) +{ + uint32_t ep_attr; + + /* Passing a NULL context is a critical programming error */ + assert(tsp_ctx); + assert(tsp_entry_point); + assert(pc); + + /* + * We support AArch64 TSP for now. + * TODO: Add support for AArch32 TSP + */ + assert(rw == TSP_AARCH64); + + /* Associate this context with the cpu specified */ + tsp_ctx->mpidr = read_mpidr_el1(); + tsp_ctx->state = 0; + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); + clr_yield_smc_active_flag(tsp_ctx->state); + + cm_set_context(&tsp_ctx->cpu_ctx, SECURE); + + /* initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if (read_sctlr_el3() & SCTLR_EE_BIT) + ep_attr |= EP_EE_BIG; + SET_PARAM_HEAD(tsp_entry_point, PARAM_EP, VERSION_1, ep_attr); + + tsp_entry_point->pc = pc; + tsp_entry_point->spsr = SPSR_64(MODE_EL1, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + zeromem(&tsp_entry_point->args, sizeof(tsp_entry_point->args)); +} + +/******************************************************************************* + * This function takes an SP context pointer and: + * 1. Applies the S-EL1 system register context from tsp_ctx->cpu_ctx. + * 2. Saves the current C runtime state (callee saved registers) on the stack + * frame and saves a reference to this state. + * 3. Calls el3_exit() so that the EL3 system and general purpose registers + * from the tsp_ctx->cpu_ctx are used to enter the secure payload image. + ******************************************************************************/ +uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx) +{ + uint64_t rc; + + assert(tsp_ctx != NULL); + assert(tsp_ctx->c_rt_ctx == 0); + + /* Apply the Secure EL1 system register context and switch to it */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + rc = tspd_enter_sp(&tsp_ctx->c_rt_ctx); +#if ENABLE_ASSERTIONS + tsp_ctx->c_rt_ctx = 0; +#endif + + return rc; +} + + +/******************************************************************************* + * This function takes an SP context pointer and: + * 1. Saves the S-EL1 system register context tp tsp_ctx->cpu_ctx. + * 2. Restores the current C runtime state (callee saved registers) from the + * stack frame using the reference to this state saved in tspd_enter_sp(). + * 3. It does not need to save any general purpose or EL3 system register state + * as the generic smc entry routine should have saved those. + ******************************************************************************/ +void tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret) +{ + assert(tsp_ctx != NULL); + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + assert(tsp_ctx->c_rt_ctx != 0); + tspd_exit_sp(tsp_ctx->c_rt_ctx, ret); + + /* Should never reach here */ + assert(0); +} + +/******************************************************************************* + * This function takes an SP context pointer and abort any preempted SMC + * request. + * Return 1 if there was a preempted SMC request, 0 otherwise. + ******************************************************************************/ +int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx) +{ + if (!get_yield_smc_active_flag(tsp_ctx->state)) + return 0; + + /* Abort any preempted SMC request */ + clr_yield_smc_active_flag(tsp_ctx->state); + + /* + * Arrange for an entry into the test secure payload. It will + * be returned via TSP_ABORT_DONE case in tspd_smc_handler. + */ + cm_set_elr_el3(SECURE, + (uint64_t) &tsp_vectors->abort_yield_smc_entry); + uint64_t rc = tspd_synchronous_sp_entry(tsp_ctx); + + if (rc != 0) + panic(); + + return 1; +} + diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S b/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S new file mode 100644 index 0000000..f15d66b --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_helpers.S @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2013-2014, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "tspd_private.h" + + .global tspd_enter_sp + /* --------------------------------------------- + * This function is called with SP_EL0 as stack. + * Here we stash our EL3 callee-saved registers + * on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where + * the address of the C runtime context is to be + * saved. + * --------------------------------------------- + */ +func tspd_enter_sp + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #TSPD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #TSPD_C_RT_CTX_X19] + stp x21, x22, [sp, #TSPD_C_RT_CTX_X21] + stp x23, x24, [sp, #TSPD_C_RT_CTX_X23] + stp x25, x26, [sp, #TSPD_C_RT_CTX_X25] + stp x27, x28, [sp, #TSPD_C_RT_CTX_X27] + stp x29, x30, [sp, #TSPD_C_RT_CTX_X29] + + /* --------------------------------------------- + * Everything is setup now. el3_exit() will + * use the secure context to restore to the + * general purpose and EL3 system registers to + * ERET into the secure payload. + * --------------------------------------------- + */ + b el3_exit +endfunc tspd_enter_sp + + /* --------------------------------------------- + * This function is called 'x0' pointing to a C + * runtime context saved in tspd_enter_sp(). It + * restores the saved registers and jumps to + * that runtime with 'x0' as the new sp. This + * destroys the C runtime context that had been + * built on the stack below the saved context by + * the caller. Later the second parameter 'x1' + * is passed as return value to the caller + * --------------------------------------------- + */ + .global tspd_exit_sp +func tspd_exit_sp + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(TSPD_C_RT_CTX_X19 - TSPD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(TSPD_C_RT_CTX_X21 - TSPD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(TSPD_C_RT_CTX_X23 - TSPD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(TSPD_C_RT_CTX_X25 - TSPD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(TSPD_C_RT_CTX_X27 - TSPD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(TSPD_C_RT_CTX_X29 - TSPD_C_RT_CTX_SIZE)] + + /* --------------------------------------------- + * This should take us back to the instruction + * after the call to the last tspd_enter_sp(). + * Place the second parameter to x0 so that the + * caller will see it as a return value from the + * original entry call + * --------------------------------------------- + */ + mov x0, x1 + ret +endfunc tspd_exit_sp diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_main.c b/arm-trusted-firmware/services/spd/tspd/tspd_main.c new file mode 100644 index 0000000..6cb4992 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_main.c @@ -0,0 +1,819 @@ +/* + * Copyright (c) 2013-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +/******************************************************************************* + * This is the Secure Payload Dispatcher (SPD). The dispatcher is meant to be a + * plug-in component to the Secure Monitor, registered as a runtime service. The + * SPD is expected to be a functional extension of the Secure Payload (SP) that + * executes in Secure EL1. The Secure Monitor will delegate all SMCs targeting + * the Trusted OS/Applications range to the dispatcher. The SPD will either + * handle the request locally or delegate it to the Secure Payload. It is also + * responsible for initialising and maintaining communication with the SP. + ******************************************************************************/ +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * Address of the entrypoint vector table in the Secure Payload. It is + * initialised once on the primary core after a cold boot. + ******************************************************************************/ +tsp_vectors_t *tsp_vectors; + +/******************************************************************************* + * Array to keep track of per-cpu Secure Payload state + ******************************************************************************/ +tsp_context_t tspd_sp_context[TSPD_CORE_COUNT]; + + +/* TSP UID */ +DEFINE_SVC_UUID2(tsp_uuid, + 0xa056305b, 0x9132, 0x7b42, 0x98, 0x11, + 0x71, 0x68, 0xca, 0x50, 0xf3, 0xfa); + +int32_t tspd_init(void); + +/* + * This helper function handles Secure EL1 preemption. The preemption could be + * due Non Secure interrupts or EL3 interrupts. In both the cases we context + * switch to the normal world and in case of EL3 interrupts, it will again be + * routed to EL3 which will get handled at the exception vectors. + */ +uint64_t tspd_handle_sp_preemption(void *handle) +{ + cpu_context_t *ns_cpu_context; + + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * To allow Secure EL1 interrupt handler to re-enter TSP while TSP + * is preempted, the secure system register context which will get + * overwritten must be additionally saved. This is currently done + * by the TSPD S-EL1 interrupt handler. + */ + + /* + * Restore non-secure state. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* + * The TSP was preempted during execution of a Yielding SMC Call. + * Return back to the normal world with SMC_PREEMPTED as error + * code in x0. + */ + SMC_RET1(ns_cpu_context, SMC_PREEMPTED); +} + +/******************************************************************************* + * This function is the handler registered for S-EL1 interrupts by the TSPD. It + * validates the interrupt and upon success arranges entry into the TSP at + * 'tsp_sel1_intr_entry()' for handling the interrupt. + * Typically, interrupts for a specific security state get handled in the same + * security execption level if the execution is in the same security state. For + * example, if a non-secure interrupt gets fired when CPU is executing in NS-EL2 + * it gets handled in the non-secure world. + * However, interrupts belonging to the opposite security state typically demand + * a world(context) switch. This is inline with the security principle which + * states a secure interrupt has to be handled in the secure world. + * Hence, the TSPD in EL3 expects the context(handle) for a secure interrupt to + * be non-secure and vice versa. + * However, a race condition between non-secure and secure interrupts can lead to + * a scenario where the above assumptions do not hold true. This is demonstrated + * below through Note 1. + ******************************************************************************/ +static uint64_t tspd_sel1_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + uint32_t linear_id; + tsp_context_t *tsp_ctx; + + /* Get a reference to this cpu's TSP context */ + linear_id = plat_my_core_pos(); + tsp_ctx = &tspd_sp_context[linear_id]; + +#if TSP_NS_INTR_ASYNC_PREEMPT + + /* + * Note 1: + * Under the current interrupt routing model, interrupts from other + * world are routed to EL3 when TSP_NS_INTR_ASYNC_PREEMPT is enabled. + * Consider the following scenario: + * 1/ A non-secure payload(like tftf) requests a secure service from + * TSP by invoking a yielding SMC call. + * 2/ Later, execution jumps to TSP in S-EL1 with the help of TSP + * Dispatcher in Secure Monitor(EL3). + * 3/ While CPU is executing TSP, a Non-secure interrupt gets fired. + * this demands a context switch to the non-secure world through + * secure monitor. + * 4/ Consequently, TSP in S-EL1 get asynchronously pre-empted and + * execution switches to secure monitor(EL3). + * 5/ EL3 tries to triage the (Non-secure) interrupt based on the + * highest pending interrupt. + * 6/ However, while the NS Interrupt was pending, secure timer gets + * fired which makes a S-EL1 interrupt to be pending. + * 7/ Hence, execution jumps to this companion handler of S-EL1 + * interrupt (i.e., tspd_sel1_interrupt_handler) even though the TSP + * was pre-empted due to non-secure interrupt. + * 8/ The above sequence of events explain how TSP was pre-empted by + * S-EL1 interrupt indirectly in an asynchronous way. + * 9/ Hence, we track the TSP pre-emption by S-EL1 interrupt using a + * boolean variable per each core. + * 10/ This helps us to indicate that SMC call for TSP service was + * pre-empted when execution resumes in non-secure world. + */ + + /* Check the security state when the exception was generated */ + if (get_interrupt_src_ss(flags) == NON_SECURE) { + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the TSP */ + cm_el1_sysregs_context_save(NON_SECURE); + tsp_ctx->preempted_by_sel1_intr = false; + } else { + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(SECURE)); + + /* Save the secure context before entering the TSP for S-EL1 + * interrupt handling + */ + cm_el1_sysregs_context_save(SECURE); + tsp_ctx->preempted_by_sel1_intr = true; + } +#else + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering the TSP */ + cm_el1_sysregs_context_save(NON_SECURE); +#endif + + assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* + * Determine if the TSP was previously preempted. Its last known + * context has to be preserved in this case. + * The TSP should return control to the TSPD after handling this + * S-EL1 interrupt. Preserve essential EL3 context to allow entry into + * the TSP at the S-EL1 interrupt entry point using the 'cpu_context' + * structure. There is no need to save the secure system register + * context since the TSP is supposed to preserve it during S-EL1 + * interrupt handling. + */ + if (get_yield_smc_active_flag(tsp_ctx->state)) { + tsp_ctx->saved_spsr_el3 = (uint32_t)SMC_GET_EL3(&tsp_ctx->cpu_ctx, + CTX_SPSR_EL3); + tsp_ctx->saved_elr_el3 = SMC_GET_EL3(&tsp_ctx->cpu_ctx, + CTX_ELR_EL3); +#if TSP_NS_INTR_ASYNC_PREEMPT + memcpy(&tsp_ctx->sp_ctx, &tsp_ctx->cpu_ctx, TSPD_SP_CTX_SIZE); +#endif + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_elr_spsr_el3(SECURE, (uint64_t) &tsp_vectors->sel1_intr_entry, + SPSR_64(MODE_EL1, MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); + + cm_set_next_eret_context(SECURE); + + /* + * Tell the TSP that it has to handle a S-EL1 interrupt synchronously. + * Also the instruction in normal world where the interrupt was + * generated is passed for debugging purposes. It is safe to retrieve + * this address from ELR_EL3 as the secure context will not take effect + * until el3_exit(). + */ + SMC_RET2(&tsp_ctx->cpu_ctx, TSP_HANDLE_SEL1_INTR_AND_RETURN, read_elr_el3()); +} + +#if TSP_NS_INTR_ASYNC_PREEMPT +/******************************************************************************* + * This function is the handler registered for Non secure interrupts by the + * TSPD. It validates the interrupt and upon success arranges entry into the + * normal world for handling the interrupt. + ******************************************************************************/ +static uint64_t tspd_ns_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + /* Check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == SECURE); + + /* + * Disable the routing of NS interrupts from secure world to EL3 while + * interrupted on this core. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); + + return tspd_handle_sp_preemption(handle); +} +#endif + +/******************************************************************************* + * Secure Payload Dispatcher setup. The SPD finds out the SP entrypoint and type + * (aarch32/aarch64) if not already known and initialises the context for entry + * into the SP for its initialisation. + ******************************************************************************/ +static int32_t tspd_setup(void) +{ + entry_point_info_t *tsp_ep_info; + uint32_t linear_id; + + linear_id = plat_my_core_pos(); + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. TODO: Add support to + * conditionally include the SPD service + */ + tsp_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (!tsp_ep_info) { + WARN("No TSP provided by BL2 boot loader, Booting device" + " without TSP initialization. SMC`s destined for TSP" + " will return SMC_UNK\n"); + return 1; + } + + /* + * If there's no valid entry point for SP, we return a non-zero value + * signalling failure initializing the service. We bail out without + * registering any handlers + */ + if (!tsp_ep_info->pc) + return 1; + + /* + * We could inspect the SP image and determine its execution + * state i.e whether AArch32 or AArch64. Assuming it's AArch64 + * for the time being. + */ + tspd_init_tsp_ep_state(tsp_ep_info, + TSP_AARCH64, + tsp_ep_info->pc, + &tspd_sp_context[linear_id]); + +#if TSP_INIT_ASYNC + bl31_set_next_image_type(SECURE); +#else + /* + * All TSPD initialization done. Now register our init function with + * BL31 for deferred invocation + */ + bl31_register_bl32_init(&tspd_init); +#endif + return 0; +} + +/******************************************************************************* + * This function passes control to the Secure Payload image (BL32) for the first + * time on the primary cpu after a cold boot. It assumes that a valid secure + * context has already been created by tspd_setup() which can be directly used. + * It also assumes that a valid non-secure context has been initialised by PSCI + * so it does not need to save and restore any non-secure state. This function + * performs a synchronous entry into the Secure payload. The SP passes control + * back to this routine through a SMC. + ******************************************************************************/ +int32_t tspd_init(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + entry_point_info_t *tsp_entry_point; + uint64_t rc; + + /* + * Get information about the Secure Payload (BL32) image. Its + * absence is a critical failure. + */ + tsp_entry_point = bl31_plat_get_next_image_ep_info(SECURE); + assert(tsp_entry_point); + + cm_init_my_context(tsp_entry_point); + + /* + * Arrange for an entry into the test secure payload. It will be + * returned via TSP_ENTRY_DONE case + */ + rc = tspd_synchronous_sp_entry(tsp_ctx); + assert(rc != 0); + + return rc; +} + + +/******************************************************************************* + * This function is responsible for handling all SMCs in the Trusted OS/App + * range from the non-secure state as defined in the SMC Calling Convention + * Document. It is also responsible for communicating with the Secure payload + * to delegate work and return results back to the non-secure state. Lastly it + * will also return any information that the secure payload needs to do the + * work assigned to it. + ******************************************************************************/ +static uintptr_t tspd_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) +{ + cpu_context_t *ns_cpu_context; + uint32_t linear_id = plat_my_core_pos(), ns; + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + uint64_t rc; +#if TSP_INIT_ASYNC + entry_point_info_t *next_image_info; +#endif + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + switch (smc_fid) { + + /* + * This function ID is used by TSP to indicate that it was + * preempted by a normal world IRQ. + * + */ + case TSP_PREEMPTED: + if (ns) + SMC_RET1(handle, SMC_UNK); + + return tspd_handle_sp_preemption(handle); + + /* + * This function ID is used only by the TSP to indicate that it has + * finished handling a S-EL1 interrupt or was preempted by a higher + * priority pending EL3 interrupt. Execution should resume + * in the normal world. + */ + case TSP_HANDLED_S_EL1_INTR: + if (ns) + SMC_RET1(handle, SMC_UNK); + + assert(handle == cm_get_context(SECURE)); + + /* + * Restore the relevant EL3 state which saved to service + * this SMC. + */ + if (get_yield_smc_active_flag(tsp_ctx->state)) { + SMC_SET_EL3(&tsp_ctx->cpu_ctx, + CTX_SPSR_EL3, + tsp_ctx->saved_spsr_el3); + SMC_SET_EL3(&tsp_ctx->cpu_ctx, + CTX_ELR_EL3, + tsp_ctx->saved_elr_el3); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Need to restore the previously interrupted + * secure context. + */ + memcpy(&tsp_ctx->cpu_ctx, &tsp_ctx->sp_ctx, + TSPD_SP_CTX_SIZE); +#endif + } + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* + * Restore non-secure state. There is no need to save the + * secure system register context since the TSP was supposed + * to preserve it during S-EL1 interrupt handling. + */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* Refer to Note 1 in function tspd_sel1_interrupt_handler()*/ +#if TSP_NS_INTR_ASYNC_PREEMPT + if (tsp_ctx->preempted_by_sel1_intr) { + /* Reset the flag */ + tsp_ctx->preempted_by_sel1_intr = false; + + SMC_RET1(ns_cpu_context, SMC_PREEMPTED); + } else { + SMC_RET0((uint64_t) ns_cpu_context); + } +#else + SMC_RET0((uint64_t) ns_cpu_context); +#endif + + + /* + * This function ID is used only by the SP to indicate it has + * finished initialising itself after a cold boot + */ + case TSP_ENTRY_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * Stash the SP entry points information. This is done + * only once on the primary cpu + */ + assert(tsp_vectors == NULL); + tsp_vectors = (tsp_vectors_t *) x1; + + if (tsp_vectors) { + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); + + /* + * TSP has been successfully initialized. Register power + * management hooks with PSCI + */ + psci_register_spd_pm_hook(&tspd_pm); + + /* + * Register an interrupt handler for S-EL1 interrupts + * when generated during code executing in the + * non-secure state. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + tspd_sel1_interrupt_handler, + flags); + if (rc) + panic(); + +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Register an interrupt handler for NS interrupts when + * generated during code executing in secure state are + * routed to EL3. + */ + flags = 0; + set_interrupt_rm_flag(flags, SECURE); + + rc = register_interrupt_type_handler(INTR_TYPE_NS, + tspd_ns_interrupt_handler, + flags); + if (rc) + panic(); + + /* + * Disable the NS interrupt locally. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + } + + +#if TSP_INIT_ASYNC + /* Save the Secure EL1 system register context */ + assert(cm_get_context(SECURE) == &tsp_ctx->cpu_ctx); + cm_el1_sysregs_context_save(SECURE); + + /* Program EL3 registers to enable entry into the next EL */ + next_image_info = bl31_plat_get_next_image_ep_info(NON_SECURE); + assert(next_image_info); + assert(NON_SECURE == + GET_SECURITY_STATE(next_image_info->h.attr)); + + cm_init_my_context(next_image_info); + cm_prepare_el3_exit(NON_SECURE); + SMC_RET0(cm_get_context(NON_SECURE)); +#else + /* + * SP reports completion. The SPD must have initiated + * the original request through a synchronous entry + * into the SP. Jump back to the original C runtime + * context. + */ + tspd_synchronous_sp_exit(tsp_ctx, x1); + break; +#endif + /* + * This function ID is used only by the SP to indicate it has finished + * aborting a preempted Yielding SMC Call. + */ + case TSP_ABORT_DONE: + + /* + * These function IDs are used only by the SP to indicate it has + * finished: + * 1. turning itself on in response to an earlier psci + * cpu_on request + * 2. resuming itself after an earlier psci cpu_suspend + * request. + */ + case TSP_ON_DONE: + case TSP_RESUME_DONE: + + /* + * These function IDs are used only by the SP to indicate it has + * finished: + * 1. suspending itself after an earlier psci cpu_suspend + * request. + * 2. turning itself off in response to an earlier psci + * cpu_off request. + */ + case TSP_OFF_DONE: + case TSP_SUSPEND_DONE: + case TSP_SYSTEM_OFF_DONE: + case TSP_SYSTEM_RESET_DONE: + if (ns) + SMC_RET1(handle, SMC_UNK); + + /* + * SP reports completion. The SPD must have initiated the + * original request through a synchronous entry into the SP. + * Jump back to the original C runtime context, and pass x1 as + * return value to the caller + */ + tspd_synchronous_sp_exit(tsp_ctx, x1); + break; + + /* + * Request from non-secure client to perform an + * arithmetic operation or response from secure + * payload to an earlier request. + */ + case TSP_FAST_FID(TSP_ADD): + case TSP_FAST_FID(TSP_SUB): + case TSP_FAST_FID(TSP_MUL): + case TSP_FAST_FID(TSP_DIV): + + case TSP_YIELD_FID(TSP_ADD): + case TSP_YIELD_FID(TSP_SUB): + case TSP_YIELD_FID(TSP_MUL): + case TSP_YIELD_FID(TSP_DIV): + /* + * Request from non-secure client to perform a check + * of the DIT PSTATE bit. + */ + case TSP_YIELD_FID(TSP_CHECK_DIT): + if (ns) { + /* + * This is a fresh request from the non-secure client. + * The parameters are in x1 and x2. Figure out which + * registers need to be preserved, save the non-secure + * state and send the request to the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Check if we are already preempted */ + if (get_yield_smc_active_flag(tsp_ctx->state)) + SMC_RET1(handle, SMC_UNK); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* Save x1 and x2 for use by TSP_GET_ARGS call below */ + store_tsp_args(tsp_ctx, x1, x2); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ + + /* + * Verify if there is a valid context to use, copy the + * operation type and parameters to the secure context + * and jump to the fast smc entry point in the secure + * payload. Entry into S-EL1 will take place upon exit + * from this function. + */ + assert(&tsp_ctx->cpu_ctx == cm_get_context(SECURE)); + + /* Set appropriate entry for SMC. + * We expect the TSP to manage the PSTATE.I and PSTATE.F + * flags as appropriate. + */ + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_FAST) { + cm_set_elr_el3(SECURE, (uint64_t) + &tsp_vectors->fast_smc_entry); + } else { + set_yield_smc_active_flag(tsp_ctx->state); + cm_set_elr_el3(SECURE, (uint64_t) + &tsp_vectors->yield_smc_entry); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Enable the routing of NS interrupts to EL3 + * during processing of a Yielding SMC Call on + * this core. + */ + enable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + +#if EL3_EXCEPTION_HANDLING + /* + * With EL3 exception handling, while an SMC is + * being processed, Non-secure interrupts can't + * preempt Secure execution. However, for + * yielding SMCs, we want preemption to happen; + * so explicitly allow NS preemption in this + * case, and supply the preemption return code + * for TSP. + */ + ehf_allow_ns_preemption(TSP_PREEMPTED); +#endif + } + + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + SMC_RET3(&tsp_ctx->cpu_ctx, smc_fid, x1, x2); + } else { + /* + * This is the result from the secure client of an + * earlier request. The results are in x1-x3. Copy it + * into the non-secure context, save the secure state + * and return to the non-secure state. + */ + assert(handle == cm_get_context(SECURE)); + cm_el1_sysregs_context_save(SECURE); + + /* Get a reference to the non-secure context */ + ns_cpu_context = cm_get_context(NON_SECURE); + assert(ns_cpu_context); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + if (GET_SMC_TYPE(smc_fid) == SMC_TYPE_YIELD) { + clr_yield_smc_active_flag(tsp_ctx->state); +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Disable the routing of NS interrupts to EL3 + * after processing of a Yielding SMC Call on + * this core is finished. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + } + + SMC_RET3(ns_cpu_context, x1, x2, x3); + } + assert(0); /* Unreachable */ + + /* + * Request from the non-secure world to abort a preempted Yielding SMC + * Call. + */ + case TSP_FID_ABORT: + /* ABORT should only be invoked by normal world */ + if (!ns) { + assert(0); + break; + } + + assert(handle == cm_get_context(NON_SECURE)); + cm_el1_sysregs_context_save(NON_SECURE); + + /* Abort the preempted SMC request */ + if (!tspd_abort_preempted_smc(tsp_ctx)) { + /* + * If there was no preempted SMC to abort, return + * SMC_UNK. + * + * Restoring the NON_SECURE context is not necessary as + * the synchronous entry did not take place if the + * return code of tspd_abort_preempted_smc is zero. + */ + cm_set_next_eret_context(NON_SECURE); + break; + } + + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + SMC_RET1(handle, SMC_OK); + + /* + * Request from non secure world to resume the preempted + * Yielding SMC Call. + */ + case TSP_FID_RESUME: + /* RESUME should be invoked only by normal world */ + if (!ns) { + assert(0); + break; + } + + /* + * This is a resume request from the non-secure client. + * save the non-secure state and send the request to + * the secure payload. + */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Check if we are already preempted before resume */ + if (!get_yield_smc_active_flag(tsp_ctx->state)) + SMC_RET1(handle, SMC_UNK); + + cm_el1_sysregs_context_save(NON_SECURE); + + /* + * We are done stashing the non-secure context. Ask the + * secure payload to do the work now. + */ +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Enable the routing of NS interrupts to EL3 during resumption + * of a Yielding SMC Call on this core. + */ + enable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + +#if EL3_EXCEPTION_HANDLING + /* + * Allow the resumed yielding SMC processing to be preempted by + * Non-secure interrupts. Also, supply the preemption return + * code for TSP. + */ + ehf_allow_ns_preemption(TSP_PREEMPTED); +#endif + + /* We just need to return to the preempted point in + * TSP and the execution will resume as normal. + */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + SMC_RET0(&tsp_ctx->cpu_ctx); + + /* + * This is a request from the secure payload for more arguments + * for an ongoing arithmetic operation requested by the + * non-secure world. Simply return the arguments from the non- + * secure client in the original call. + */ + case TSP_GET_ARGS: + if (ns) + SMC_RET1(handle, SMC_UNK); + + get_tsp_args(tsp_ctx, x1, x2); + SMC_RET2(handle, x1, x2); + + case TOS_CALL_COUNT: + /* + * Return the number of service function IDs implemented to + * provide service to non-secure + */ + SMC_RET1(handle, TSP_NUM_FID); + + case TOS_UID: + /* Return TSP UID to the caller */ + SMC_UUID_RET(handle, tsp_uuid); + + case TOS_CALL_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, TSP_VERSION_MAJOR, TSP_VERSION_MINOR); + + default: + break; + } + + SMC_RET1(handle, SMC_UNK); +} + +/* Define a SPD runtime service descriptor for fast SMC calls */ +DECLARE_RT_SVC( + tspd_fast, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_FAST, + tspd_setup, + tspd_smc_handler +); + +/* Define a SPD runtime service descriptor for Yielding SMC Calls */ +DECLARE_RT_SVC( + tspd_std, + + OEN_TOS_START, + OEN_TOS_END, + SMC_TYPE_YIELD, + NULL, + tspd_smc_handler +); diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_pm.c b/arm-trusted-firmware/services/spd/tspd/tspd_pm.c new file mode 100644 index 0000000..b95ee8f --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_pm.c @@ -0,0 +1,254 @@ +/* + * Copyright (c) 2013-2016, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include +#include +#include +#include +#include +#include + +#include "tspd_private.h" + +/******************************************************************************* + * The target cpu is being turned on. Allow the TSPD/TSP to perform any actions + * needed. Nothing at the moment. + ******************************************************************************/ +static void tspd_cpu_on_handler(u_register_t target_cpu) +{ +} + +/******************************************************************************* + * This cpu is being turned off. Allow the TSPD/TSP to perform any actions + * needed + ******************************************************************************/ +static int32_t tspd_cpu_off_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point and enter the TSP */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_off_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc != 0) + panic(); + + /* + * Reset TSP's context for a fresh start when this cpu is turned on + * subsequently. + */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_OFF); + + return 0; +} + +/******************************************************************************* + * This cpu is being suspended. S-EL1 state must have been saved in the + * resident cpu (mpidr format) if it is a UP/UP migratable TSP. + ******************************************************************************/ +static void tspd_cpu_suspend_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point and enter the TSP */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_suspend_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc) + panic(); + + /* Update its context to reflect the state the TSP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_SUSPEND); +} + +/******************************************************************************* + * This cpu has been turned on. Enter the TSP to initialise S-EL1 and other bits + * before passing control back to the Secure Monitor. Entry in S-EL1 is done + * after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void tspd_cpu_on_finish_handler(u_register_t unused) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + entry_point_info_t tsp_on_entrypoint; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_OFF); + + tspd_init_tsp_ep_state(&tsp_on_entrypoint, + TSP_AARCH64, + (uint64_t) &tsp_vectors->cpu_on_entry, + tsp_ctx); + + /* Initialise this cpu's secure context */ + cm_init_my_context(&tsp_on_entrypoint); + +#if TSP_NS_INTR_ASYNC_PREEMPT + /* + * Disable the NS interrupt locally since it will be enabled globally + * within cm_init_my_context. + */ + disable_intr_rm_local(INTR_TYPE_NS, SECURE); +#endif + + /* Enter the TSP */ + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the SP. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state the SP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); +} + +/******************************************************************************* + * This cpu has resumed from suspend. The SPD saved the TSP context when it + * completed the preceding suspend call. Use that context to program an entry + * into the TSP to allow it to do any remaining book keeping + ******************************************************************************/ +static void tspd_cpu_suspend_finish_handler(u_register_t max_off_pwrlvl) +{ + int32_t rc = 0; + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_SUSPEND); + + /* Program the entry point, max_off_pwrlvl and enter the SP */ + write_ctx_reg(get_gpregs_ctx(&tsp_ctx->cpu_ctx), + CTX_GPREG_X0, + max_off_pwrlvl); + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->cpu_resume_entry); + rc = tspd_synchronous_sp_entry(tsp_ctx); + + /* + * Read the response from the TSP. A non-zero return means that + * something went wrong while communicating with the TSP. + */ + if (rc != 0) + panic(); + + /* Update its context to reflect the state the SP is in */ + set_tsp_pstate(tsp_ctx->state, TSP_PSTATE_ON); +} + +/******************************************************************************* + * Return the type of TSP the TSPD is dealing with. Report the current resident + * cpu (mpidr format) if it is a UP/UP migratable TSP. + ******************************************************************************/ +static int32_t tspd_cpu_migrate_info(u_register_t *resident_cpu) +{ + return TSP_MIGRATE_INFO; +} + +/******************************************************************************* + * System is about to be switched off. Allow the TSPD/TSP to perform + * any actions needed. + ******************************************************************************/ +static void tspd_system_off(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_off_entry); + + /* Enter the TSP. We do not care about the return value because we + * must continue the shutdown anyway */ + tspd_synchronous_sp_entry(tsp_ctx); +} + +/******************************************************************************* + * System is about to be reset. Allow the TSPD/TSP to perform + * any actions needed. + ******************************************************************************/ +static void tspd_system_reset(void) +{ + uint32_t linear_id = plat_my_core_pos(); + tsp_context_t *tsp_ctx = &tspd_sp_context[linear_id]; + + assert(tsp_vectors); + assert(get_tsp_pstate(tsp_ctx->state) == TSP_PSTATE_ON); + + /* + * Abort any preempted SMC request before overwriting the SECURE + * context. + */ + tspd_abort_preempted_smc(tsp_ctx); + + /* Program the entry point */ + cm_set_elr_el3(SECURE, (uint64_t) &tsp_vectors->system_reset_entry); + + /* + * Enter the TSP. We do not care about the return value because we + * must continue the reset anyway + */ + tspd_synchronous_sp_entry(tsp_ctx); +} + +/******************************************************************************* + * Structure populated by the TSP Dispatcher to be given a chance to perform any + * TSP bookkeeping before PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t tspd_pm = { + .svc_on = tspd_cpu_on_handler, + .svc_off = tspd_cpu_off_handler, + .svc_suspend = tspd_cpu_suspend_handler, + .svc_on_finish = tspd_cpu_on_finish_handler, + .svc_suspend_finish = tspd_cpu_suspend_finish_handler, + .svc_migrate = NULL, + .svc_migrate_info = tspd_cpu_migrate_info, + .svc_system_off = tspd_system_off, + .svc_system_reset = tspd_system_reset +}; diff --git a/arm-trusted-firmware/services/spd/tspd/tspd_private.h b/arm-trusted-firmware/services/spd/tspd/tspd_private.h new file mode 100644 index 0000000..d6c03c9 --- /dev/null +++ b/arm-trusted-firmware/services/spd/tspd/tspd_private.h @@ -0,0 +1,233 @@ +/* + * Copyright (c) 2013-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TSPD_PRIVATE_H +#define TSPD_PRIVATE_H + +#include + +#include +#include +#include +#include + +/******************************************************************************* + * Secure Payload PM state information e.g. SP is suspended, uninitialised etc + * and macros to access the state information in the per-cpu 'state' flags + ******************************************************************************/ +#define TSP_PSTATE_OFF 0 +#define TSP_PSTATE_ON 1 +#define TSP_PSTATE_SUSPEND 2 +#define TSP_PSTATE_SHIFT 0 +#define TSP_PSTATE_MASK 0x3 +#define get_tsp_pstate(state) ((state >> TSP_PSTATE_SHIFT) & TSP_PSTATE_MASK) +#define clr_tsp_pstate(state) (state &= ~(TSP_PSTATE_MASK \ + << TSP_PSTATE_SHIFT)) +#define set_tsp_pstate(st, pst) do { \ + clr_tsp_pstate(st); \ + st |= (pst & TSP_PSTATE_MASK) << \ + TSP_PSTATE_SHIFT; \ + } while (0); + + +/* + * This flag is used by the TSPD to determine if the TSP is servicing a yielding + * SMC request prior to programming the next entry into the TSP e.g. if TSP + * execution is preempted by a non-secure interrupt and handed control to the + * normal world. If another request which is distinct from what the TSP was + * previously doing arrives, then this flag will be help the TSPD to either + * reject the new request or service it while ensuring that the previous context + * is not corrupted. + */ +#define YIELD_SMC_ACTIVE_FLAG_SHIFT 2 +#define YIELD_SMC_ACTIVE_FLAG_MASK 1 +#define get_yield_smc_active_flag(state) \ + ((state >> YIELD_SMC_ACTIVE_FLAG_SHIFT) \ + & YIELD_SMC_ACTIVE_FLAG_MASK) +#define set_yield_smc_active_flag(state) (state |= \ + 1 << YIELD_SMC_ACTIVE_FLAG_SHIFT) +#define clr_yield_smc_active_flag(state) (state &= \ + ~(YIELD_SMC_ACTIVE_FLAG_MASK \ + << YIELD_SMC_ACTIVE_FLAG_SHIFT)) + +/******************************************************************************* + * Secure Payload execution state information i.e. aarch32 or aarch64 + ******************************************************************************/ +#define TSP_AARCH32 MODE_RW_32 +#define TSP_AARCH64 MODE_RW_64 + +/******************************************************************************* + * The SPD should know the type of Secure Payload. + ******************************************************************************/ +#define TSP_TYPE_UP PSCI_TOS_NOT_UP_MIG_CAP +#define TSP_TYPE_UPM PSCI_TOS_UP_MIG_CAP +#define TSP_TYPE_MP PSCI_TOS_NOT_PRESENT_MP + +/******************************************************************************* + * Secure Payload migrate type information as known to the SPD. We assume that + * the SPD is dealing with an MP Secure Payload. + ******************************************************************************/ +#define TSP_MIGRATE_INFO TSP_TYPE_MP + +/******************************************************************************* + * Number of cpus that the present on this platform. TODO: Rely on a topology + * tree to determine this in the future to avoid assumptions about mpidr + * allocation + ******************************************************************************/ +#define TSPD_CORE_COUNT PLATFORM_CORE_COUNT + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define TSPD_C_RT_CTX_X19 0x0 +#define TSPD_C_RT_CTX_X20 0x8 +#define TSPD_C_RT_CTX_X21 0x10 +#define TSPD_C_RT_CTX_X22 0x18 +#define TSPD_C_RT_CTX_X23 0x20 +#define TSPD_C_RT_CTX_X24 0x28 +#define TSPD_C_RT_CTX_X25 0x30 +#define TSPD_C_RT_CTX_X26 0x38 +#define TSPD_C_RT_CTX_X27 0x40 +#define TSPD_C_RT_CTX_X28 0x48 +#define TSPD_C_RT_CTX_X29 0x50 +#define TSPD_C_RT_CTX_X30 0x58 +#define TSPD_C_RT_CTX_SIZE 0x60 +#define TSPD_C_RT_CTX_ENTRIES (TSPD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +/******************************************************************************* + * Constants that allow assembler code to preserve caller-saved registers of the + * SP context while performing a TSP preemption. + * Note: These offsets have to match with the offsets for the corresponding + * registers in cpu_context as we are using memcpy to copy the values from + * cpu_context to sp_ctx. + ******************************************************************************/ +#define TSPD_SP_CTX_X0 0x0 +#define TSPD_SP_CTX_X1 0x8 +#define TSPD_SP_CTX_X2 0x10 +#define TSPD_SP_CTX_X3 0x18 +#define TSPD_SP_CTX_X4 0x20 +#define TSPD_SP_CTX_X5 0x28 +#define TSPD_SP_CTX_X6 0x30 +#define TSPD_SP_CTX_X7 0x38 +#define TSPD_SP_CTX_X8 0x40 +#define TSPD_SP_CTX_X9 0x48 +#define TSPD_SP_CTX_X10 0x50 +#define TSPD_SP_CTX_X11 0x58 +#define TSPD_SP_CTX_X12 0x60 +#define TSPD_SP_CTX_X13 0x68 +#define TSPD_SP_CTX_X14 0x70 +#define TSPD_SP_CTX_X15 0x78 +#define TSPD_SP_CTX_X16 0x80 +#define TSPD_SP_CTX_X17 0x88 +#define TSPD_SP_CTX_SIZE 0x90 +#define TSPD_SP_CTX_ENTRIES (TSPD_SP_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include + +/* + * The number of arguments to save during a SMC call for TSP. + * Currently only x1 and x2 are used by TSP. + */ +#define TSP_NUM_ARGS 0x2 + +/* AArch64 callee saved general purpose register context structure. */ +DEFINE_REG_STRUCT(c_rt_regs, TSPD_C_RT_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TSPD_C_RT_CTX_SIZE == sizeof(c_rt_regs_t), \ + assert_spd_c_rt_regs_size_mismatch); + +/* SEL1 Secure payload (SP) caller saved register context structure. */ +DEFINE_REG_STRUCT(sp_ctx_regs, TSPD_SP_CTX_ENTRIES); + +/* + * Compile time assertion to ensure that both the compiler and linker + * have the same double word aligned view of the size of the C runtime + * register context. + */ +CASSERT(TSPD_SP_CTX_SIZE == sizeof(sp_ctx_regs_t), \ + assert_spd_sp_regs_size_mismatch); + +/******************************************************************************* + * Structure which helps the SPD to maintain the per-cpu state of the SP. + * 'saved_spsr_el3' - temporary copy to allow S-EL1 interrupt handling when + * the TSP has been preempted. + * 'saved_elr_el3' - temporary copy to allow S-EL1 interrupt handling when + * the TSP has been preempted. + * 'state' - collection of flags to track SP state e.g. on/off + * 'mpidr' - mpidr to associate a context with a cpu + * 'c_rt_ctx' - stack address to restore C runtime context from after + * returning from a synchronous entry into the SP. + * 'cpu_ctx' - space to maintain SP architectural state + * 'saved_tsp_args' - space to store arguments for TSP arithmetic operations + * which will queried using the TSP_GET_ARGS SMC by TSP. + * 'sp_ctx' - space to save the SEL1 Secure Payload(SP) caller saved + * register context after it has been preempted by an EL3 + * routed NS interrupt and when a Secure Interrupt is taken + * to SP. + ******************************************************************************/ +typedef struct tsp_context { + uint64_t saved_elr_el3; + uint32_t saved_spsr_el3; + uint32_t state; + uint64_t mpidr; + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + uint64_t saved_tsp_args[TSP_NUM_ARGS]; +#if TSP_NS_INTR_ASYNC_PREEMPT + sp_ctx_regs_t sp_ctx; + bool preempted_by_sel1_intr; +#endif +} tsp_context_t; + +/* Helper macros to store and retrieve tsp args from tsp_context */ +#define store_tsp_args(_tsp_ctx, _x1, _x2) do {\ + _tsp_ctx->saved_tsp_args[0] = _x1;\ + _tsp_ctx->saved_tsp_args[1] = _x2;\ + } while (0) + +#define get_tsp_args(_tsp_ctx, _x1, _x2) do {\ + _x1 = _tsp_ctx->saved_tsp_args[0];\ + _x2 = _tsp_ctx->saved_tsp_args[1];\ + } while (0) + +/* TSPD power management handlers */ +extern const spd_pm_ops_t tspd_pm; + +/******************************************************************************* + * Forward declarations + ******************************************************************************/ +typedef struct tsp_vectors tsp_vectors_t; + +/******************************************************************************* + * Function & Data prototypes + ******************************************************************************/ +uint64_t tspd_enter_sp(uint64_t *c_rt_ctx); +void __dead2 tspd_exit_sp(uint64_t c_rt_ctx, uint64_t ret); +uint64_t tspd_synchronous_sp_entry(tsp_context_t *tsp_ctx); +void __dead2 tspd_synchronous_sp_exit(tsp_context_t *tsp_ctx, uint64_t ret); +void tspd_init_tsp_ep_state(struct entry_point_info *tsp_entry_point, + uint32_t rw, + uint64_t pc, + tsp_context_t *tsp_ctx); +int tspd_abort_preempted_smc(tsp_context_t *tsp_ctx); + +uint64_t tspd_handle_sp_preemption(void *handle); + +extern tsp_context_t tspd_sp_context[TSPD_CORE_COUNT]; +extern tsp_vectors_t *tsp_vectors; +#endif /*__ASSEMBLER__*/ + +#endif /* TSPD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/pci_svc.c b/arm-trusted-firmware/services/std_svc/pci_svc.c new file mode 100644 index 0000000..a02b8a7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/pci_svc.c @@ -0,0 +1,113 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include + +static uint64_t validate_rw_addr_sz(uint32_t addr, uint64_t off, uint64_t sz) +{ + uint32_t nseg; + uint32_t ret; + uint32_t start_end_bus; + + ret = pci_get_bus_for_seg(PCI_ADDR_SEG(addr), &start_end_bus, &nseg); + + if (ret != SMC_PCI_CALL_SUCCESS) { + return SMC_PCI_CALL_INVAL_PARAM; + } + switch (sz) { + case SMC_PCI_SZ_8BIT: + case SMC_PCI_SZ_16BIT: + case SMC_PCI_SZ_32BIT: + break; + default: + return SMC_PCI_CALL_INVAL_PARAM; + } + if ((off + sz) > (PCI_OFFSET_MASK + 1U)) { + return SMC_PCI_CALL_INVAL_PARAM; + } + return SMC_PCI_CALL_SUCCESS; +} + +uint64_t pci_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 SMC_PCI_VERSION: { + pcie_version ver; + + ver.major = 1U; + ver.minor = 0U; + SMC_RET4(handle, ver.val, 0U, 0U, 0U); + } + case SMC_PCI_FEATURES: + switch (x1) { + case SMC_PCI_VERSION: + case SMC_PCI_FEATURES: + case SMC_PCI_READ: + case SMC_PCI_WRITE: + case SMC_PCI_SEG_INFO: + SMC_RET1(handle, SMC_PCI_CALL_SUCCESS); + default: + SMC_RET1(handle, SMC_PCI_CALL_NOT_SUPPORTED); + } + break; + case SMC_PCI_READ: { + uint32_t ret; + + if (validate_rw_addr_sz(x1, x2, x3) != SMC_PCI_CALL_SUCCESS) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } + if (x4 != 0U) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } + if (pci_read_config(x1, x2, x3, &ret) != 0U) { + SMC_RET2(handle, SMC_PCI_CALL_INVAL_PARAM, 0U); + } else { + SMC_RET2(handle, SMC_PCI_CALL_SUCCESS, ret); + } + break; + } + case SMC_PCI_WRITE: { + uint32_t ret; + + if (validate_rw_addr_sz(x1, x2, x3) != SMC_PCI_CALL_SUCCESS) { + SMC_RET1(handle, SMC_PCI_CALL_INVAL_PARAM); + } + ret = pci_write_config(x1, x2, x3, x4); + SMC_RET1(handle, ret); + break; + } + case SMC_PCI_SEG_INFO: { + uint32_t nseg; + uint32_t ret; + uint32_t start_end_bus; + + if ((x2 != 0U) || (x3 != 0U) || (x4 != 0U)) { + SMC_RET3(handle, SMC_PCI_CALL_INVAL_PARAM, 0U, 0U); + } + ret = pci_get_bus_for_seg(x1, &start_end_bus, &nseg); + SMC_RET3(handle, ret, start_end_bus, nseg); + break; + } + default: + /* should be unreachable */ + WARN("Unimplemented PCI Service Call: 0x%x\n", smc_fid); + SMC_RET1(handle, SMC_PCI_CALL_NOT_SUPPORTED); + } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S b/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S new file mode 100644 index 0000000..6229baf --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "../rmmd_private.h" +#include + + .global rmmd_rmm_enter + .global rmmd_rmm_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func rmmd_rmm_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #RMMD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #RMMD_C_RT_CTX_X19] + stp x21, x22, [sp, #RMMD_C_RT_CTX_X21] + stp x23, x24, [sp, #RMMD_C_RT_CTX_X23] + stp x25, x26, [sp, #RMMD_C_RT_CTX_X25] + stp x27, x28, [sp, #RMMD_C_RT_CTX_X27] + stp x29, x30, [sp, #RMMD_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc rmmd_rmm_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context. + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func rmmd_rmm_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(RMMD_C_RT_CTX_X19 - RMMD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(RMMD_C_RT_CTX_X21 - RMMD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(RMMD_C_RT_CTX_X23 - RMMD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(RMMD_C_RT_CTX_X25 - RMMD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(RMMD_C_RT_CTX_X27 - RMMD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(RMMD_C_RT_CTX_X29 - RMMD_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last rmmd_rmm_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc rmmd_rmm_exit diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk b/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk new file mode 100644 index 0000000..bcf54e1 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd.mk @@ -0,0 +1,19 @@ +# +# Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch64) + $(error "Error: RMMD is only supported on aarch64.") +endif + +include services/std_svc/rmmd/trp/trp.mk + +RMMD_SOURCES += $(addprefix services/std_svc/rmmd/, \ + ${ARCH}/rmmd_helpers.S \ + rmmd_main.c \ + rmmd_attest.c) + +# Let the top-level Makefile know that we intend to include RMM image +NEED_RMM := yes diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c new file mode 100644 index 0000000..0432ec3 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c @@ -0,0 +1,166 @@ +/* + * Copyright (c) 2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include +#include "rmmd_private.h" +#include + +static spinlock_t lock; + +/* For printing Realm attestation token hash */ +#define DIGITS_PER_BYTE 2UL +#define LENGTH_OF_TERMINATING_ZERO_IN_BYTES 1UL +#define BYTES_PER_LINE_BASE 4UL + +static void print_challenge(uint8_t *hash, size_t hash_size) +{ + size_t leftover; + /* + * bytes_per_line is always a power of two, so it can be used to + * construct mask with it when it is necessary to count remainder. + * + */ + const size_t bytes_per_line = 1 << BYTES_PER_LINE_BASE; + char hash_text[(1 << BYTES_PER_LINE_BASE) * DIGITS_PER_BYTE + + LENGTH_OF_TERMINATING_ZERO_IN_BYTES]; + const char hex_chars[] = {'0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'}; + unsigned int i; + + for (i = 0U; i < hash_size; ++i) { + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE] = + hex_chars[hash[i] >> 4]; + hash_text[(i & (bytes_per_line - 1)) * DIGITS_PER_BYTE + 1] = + hex_chars[hash[i] & 0x0f]; + if (((i + 1) & (bytes_per_line - 1)) == 0U) { + hash_text[bytes_per_line * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", + (i >> BYTES_PER_LINE_BASE) + 1, hash_text); + } + } + + leftover = (size_t)i & (bytes_per_line - 1); + + if (leftover != 0UL) { + hash_text[leftover * DIGITS_PER_BYTE] = '\0'; + VERBOSE("hash part %u = %s\n", (i >> BYTES_PER_LINE_BASE) + 1, + hash_text); + } +} + +/* + * TODO: Have different error codes for different errors so that the caller can + * differentiate various error cases. + */ +int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, uint64_t challenge_hash_len) +{ + int err; + uintptr_t va; + uint8_t temp_buf[SHA512_DIGEST_SIZE]; + + /* + * TODO: Currently we don't validate incoming buf_pa. This is a + * prototype and we will need to allocate static buffer for EL3-RMM + * communication. + */ + + /* We need a page of buffer to pass data */ + if (*buf_len != PAGE_SIZE) { + ERROR("Invalid buffer length\n"); + return RMMD_ERR_INVAL; + } + + if ((challenge_hash_len != SHA256_DIGEST_SIZE) && + (challenge_hash_len != SHA384_DIGEST_SIZE) && + (challenge_hash_len != SHA512_DIGEST_SIZE)) { + ERROR("Invalid hash size: %lu\n", challenge_hash_len); + return RMMD_ERR_INVAL; + } + + spin_lock(&lock); + + /* Map the buffer that was provided by the RMM. */ + err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE, + MT_RW_DATA | MT_REALM); + if (err != 0) { + ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n" + , err, (void *)buf_pa); + spin_unlock(&lock); + return RMMD_ERR_NOMEM; + } + + (void)memcpy(temp_buf, (void *)va, challenge_hash_len); + + print_challenge((uint8_t *)temp_buf, challenge_hash_len); + + /* Get the platform token. */ + err = plat_get_cca_attest_token(va, + buf_len, (uintptr_t)temp_buf, challenge_hash_len); + + if (err != 0) { + ERROR("Failed to get platform token: %d.\n", err); + err = RMMD_ERR_UNK; + } + + /* Unmap RMM memory. */ + (void)mmap_remove_dynamic_region(va, PAGE_SIZE); + spin_unlock(&lock); + + return err; +} + +int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len, + uint64_t ecc_curve) +{ + int err; + uintptr_t va; + + /* + * TODO: Currently we don't validate incoming buf_pa. This is a + * prototype and we will need to allocate static buffer for EL3-RMM + * communication. + */ + + /* We need a page of buffer to pass data */ + if (*buf_len != PAGE_SIZE) { + ERROR("Invalid buffer length\n"); + return RMMD_ERR_INVAL; + } + + if (ecc_curve != ATTEST_KEY_CURVE_ECC_SECP384R1) { + ERROR("Invalid ECC curve specified\n"); + return RMMD_ERR_INVAL; + } + + spin_lock(&lock); + + /* Map the buffer that was provided by the RMM. */ + err = mmap_add_dynamic_region_alloc_va(buf_pa, &va, PAGE_SIZE, + MT_RW_DATA | MT_REALM); + if (err != 0) { + ERROR("mmap_add_dynamic_region_alloc_va failed: %d (%p).\n" + , err, (void *)buf_pa); + spin_unlock(&lock); + return RMMD_ERR_NOMEM; + } + + /* Get the Realm attestation key. */ + err = plat_get_cca_realm_attest_key(va, buf_len, (unsigned int)ecc_curve); + if (err != 0) { + ERROR("Failed to get attestation key: %d.\n", err); + err = RMMD_ERR_UNK; + } + + /* Unmap RMM memory. */ + (void)mmap_remove_dynamic_region(va, PAGE_SIZE); + spin_unlock(&lock); + + return err; +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h new file mode 100644 index 0000000..d7a743d --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2021, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_INITIAL_CONTEXT_H +#define RMMD_INITIAL_CONTEXT_H + +#include + +/* + * SPSR_EL2 + * M=0x9 (0b1001 EL2h) + * M[4]=0 + * DAIF=0xF Exceptions masked on entry. + * BTYPE=0 BTI not yet supported. + * SSBS=0 Not yet supported. + * IL=0 Not an illegal exception return. + * SS=0 Not single stepping. + * PAN=1 RMM shouldn't access realm memory. + * UAO=0 + * DIT=0 + * TCO=0 + * NZCV=0 + */ +#define REALM_SPSR_EL2 ( \ + SPSR_M_EL2H | \ + (0xF << SPSR_DAIF_SHIFT) | \ + SPSR_PAN_BIT \ + ) + +#endif /* RMMD_INITIAL_CONTEXT_H */ diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c new file mode 100644 index 0000000..cf5ff7b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rmmd_initial_context.h" +#include "rmmd_private.h" + +/******************************************************************************* + * RMM context information. + ******************************************************************************/ +rmmd_rmm_context_t rmm_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * RMM entry point information. Discovered on the primary core and reused + * on secondary cores. + ******************************************************************************/ +static entry_point_info_t *rmm_ep_info; + +/******************************************************************************* + * Static function declaration. + ******************************************************************************/ +static int32_t rmm_init(void); + +/******************************************************************************* + * This function takes an RMM context pointer and performs a synchronous entry + * into it. + ******************************************************************************/ +uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *rmm_ctx) +{ + uint64_t rc; + + assert(rmm_ctx != NULL); + + cm_set_context(&(rmm_ctx->cpu_ctx), REALM); + + /* Save the current el1/el2 context before loading realm context. */ + cm_el1_sysregs_context_save(NON_SECURE); + cm_el2_sysregs_context_save(NON_SECURE); + + /* Restore the realm context assigned above */ + cm_el1_sysregs_context_restore(REALM); + cm_el2_sysregs_context_restore(REALM); + cm_set_next_eret_context(REALM); + + /* Enter RMM */ + rc = rmmd_rmm_enter(&rmm_ctx->c_rt_ctx); + + /* Save realm context */ + cm_el1_sysregs_context_save(REALM); + cm_el2_sysregs_context_save(REALM); + + /* Restore the el1/el2 context again. */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_el2_sysregs_context_restore(NON_SECURE); + + return rc; +} + +/******************************************************************************* + * This function returns to the place where rmmd_rmm_sync_entry() was + * called originally. + ******************************************************************************/ +__dead2 void rmmd_rmm_sync_exit(uint64_t rc) +{ + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + + /* Get context of the RMM in use by this CPU. */ + assert(cm_get_context(REALM) == &(ctx->cpu_ctx)); + + /* + * The RMMD must have initiated the original request through a + * synchronous entry into RMM. Jump back to the original C runtime + * context with the value of rc in x0; + */ + rmmd_rmm_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +static void rmm_el2_context_init(el2_sysregs_t *regs) +{ + regs->ctx_regs[CTX_SPSR_EL2 >> 3] = REALM_SPSR_EL2; + regs->ctx_regs[CTX_SCTLR_EL2 >> 3] = SCTLR_EL2_RES1; +} + +/******************************************************************************* + * Enable architecture extensions on first entry to Realm world. + ******************************************************************************/ +static void manage_extensions_realm(cpu_context_t *ctx) +{ +#if ENABLE_SVE_FOR_NS + /* + * Enable SVE and FPU in realm context when it is enabled for NS. + * Realm manager must ensure that the SVE and FPU register + * contexts are properly managed. + */ + sve_enable(ctx); +#else + /* + * Disable SVE and FPU in realm context when it is disabled for NS. + */ + sve_disable(ctx); +#endif /* ENABLE_SVE_FOR_NS */ +} + +/******************************************************************************* + * Jump to the RMM for the first time. + ******************************************************************************/ +static int32_t rmm_init(void) +{ + + uint64_t rc; + + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + + INFO("RMM init start.\n"); + ctx->state = RMM_STATE_RESET; + + /* Enable architecture extensions */ + manage_extensions_realm(&ctx->cpu_ctx); + + /* Initialize RMM EL2 context. */ + rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); + + rc = rmmd_rmm_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("RMM initialisation failed 0x%" PRIx64 "\n", rc); + panic(); + } + + ctx->state = RMM_STATE_IDLE; + INFO("RMM init end.\n"); + + return 1; +} + +/******************************************************************************* + * Load and read RMM manifest, setup RMM. + ******************************************************************************/ +int rmmd_setup(void) +{ + uint32_t ep_attr; + unsigned int linear_id = plat_my_core_pos(); + rmmd_rmm_context_t *rmm_ctx = &rmm_context[linear_id]; + + /* Make sure RME is supported. */ + assert(get_armv9_2_feat_rme_support() != 0U); + + rmm_ep_info = bl31_plat_get_next_image_ep_info(REALM); + if (rmm_ep_info == NULL) { + WARN("No RMM image provided by BL2 boot loader, Booting " + "device without RMM initialization. SMCs destined for " + "RMM will return SMC_UNK\n"); + return -ENOENT; + } + + /* Under no circumstances will this parameter be 0 */ + assert(rmm_ep_info->pc == RMM_BASE); + + /* Initialise an entrypoint to set up the CPU context */ + ep_attr = EP_REALM; + if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0U) { + ep_attr |= EP_EE_BIG; + } + + SET_PARAM_HEAD(rmm_ep_info, PARAM_EP, VERSION_1, ep_attr); + rmm_ep_info->spsr = SPSR_64(MODE_EL2, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + /* Initialise RMM context with this entry point information */ + cm_setup_context(&rmm_ctx->cpu_ctx, rmm_ep_info); + + INFO("RMM setup done.\n"); + + /* Register init function for deferred init. */ + bl31_register_rmm_init(&rmm_init); + + return 0; +} + +/******************************************************************************* + * Forward SMC to the other security state + ******************************************************************************/ +static uint64_t rmmd_smc_forward(uint32_t src_sec_state, + uint32_t dst_sec_state, uint64_t x0, + uint64_t x1, uint64_t x2, uint64_t x3, + uint64_t x4, void *handle) +{ + /* Save incoming security state */ + cm_el1_sysregs_context_save(src_sec_state); + cm_el2_sysregs_context_save(src_sec_state); + + /* Restore outgoing security state */ + cm_el1_sysregs_context_restore(dst_sec_state); + cm_el2_sysregs_context_restore(dst_sec_state); + cm_set_next_eret_context(dst_sec_state); + + /* + * As per SMCCCv1.1, we need to preserve x4 to x7 unless + * being used as return args. Hence we differentiate the + * onward and backward path. Support upto 8 args in the + * onward path and 4 args in return path. + */ + if (src_sec_state == NON_SECURE) { + SMC_RET8(cm_get_context(dst_sec_state), x0, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + } else { + SMC_RET4(cm_get_context(dst_sec_state), x0, x1, x2, x3); + } +} + +/******************************************************************************* + * This function handles all SMCs in the range reserved for RMI. Each call is + * either forwarded to the other security state or handled by the RMM dispatcher + ******************************************************************************/ +uint64_t rmmd_rmi_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + rmmd_rmm_context_t *ctx = &rmm_context[plat_my_core_pos()]; + uint32_t src_sec_state; + + /* Determine which security state this SMC originated from */ + src_sec_state = caller_sec_state(flags); + + /* RMI must not be invoked by the Secure world */ + if (src_sec_state == SMC_FROM_SECURE) { + WARN("RMMD: RMI invoked by secure world.\n"); + SMC_RET1(handle, SMC_UNK); + } + + /* + * Forward an RMI call from the Normal world to the Realm world as it + * is. + */ + if (src_sec_state == SMC_FROM_NON_SECURE) { + VERBOSE("RMMD: RMI call from non-secure world.\n"); + return rmmd_smc_forward(NON_SECURE, REALM, smc_fid, + x1, x2, x3, x4, handle); + } + + if (src_sec_state != SMC_FROM_REALM) { + SMC_RET1(handle, SMC_UNK); + } + + switch (smc_fid) { + case RMMD_RMI_REQ_COMPLETE: + if (ctx->state == RMM_STATE_RESET) { + VERBOSE("RMMD: running rmmd_rmm_sync_exit\n"); + rmmd_rmm_sync_exit(x1); + } + + return rmmd_smc_forward(REALM, NON_SECURE, x1, + x2, x3, x4, 0, handle); + + default: + WARN("RMMD: Unsupported RMM call 0x%08x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/******************************************************************************* + * This cpu has been turned on. Enter RMM to initialise R-EL2. Entry into RMM + * is done after initialising minimal architectural state that guarantees safe + * execution. + ******************************************************************************/ +static void *rmmd_cpu_on_finish_handler(const void *arg) +{ + int32_t rc; + uint32_t linear_id = plat_my_core_pos(); + rmmd_rmm_context_t *ctx = &rmm_context[linear_id]; + + ctx->state = RMM_STATE_RESET; + + /* Initialise RMM context with this entry point information */ + cm_setup_context(&ctx->cpu_ctx, rmm_ep_info); + + /* Enable architecture extensions */ + manage_extensions_realm(&ctx->cpu_ctx); + + /* Initialize RMM EL2 context. */ + rmm_el2_context_init(&ctx->cpu_ctx.el2_sysregs_ctx); + + rc = rmmd_rmm_sync_entry(ctx); + if (rc != 0) { + ERROR("RMM initialisation failed (%d) on CPU%d\n", rc, + linear_id); + panic(); + } + + ctx->state = RMM_STATE_IDLE; + return NULL; +} + +/* Subscribe to PSCI CPU on to initialize RMM on secondary */ +SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, rmmd_cpu_on_finish_handler); + +/* Convert GPT lib error to RMMD GTS error */ +static int gpt_to_gts_error(int error, uint32_t smc_fid, uint64_t address) +{ + int ret; + + if (error == 0) { + return RMMD_OK; + } + + if (error == -EINVAL) { + ret = RMMD_ERR_BAD_ADDR; + } else { + /* This is the only other error code we expect */ + assert(error == -EPERM); + ret = RMMD_ERR_BAD_PAS; + } + + ERROR("RMMD: PAS Transition failed. GPT ret = %d, PA: 0x%"PRIx64 ", FID = 0x%x\n", + error, address, smc_fid); + return ret; +} + +/******************************************************************************* + * This function handles RMM-EL3 interface SMCs + ******************************************************************************/ +uint64_t rmmd_rmm_el3_handler(uint32_t smc_fid, uint64_t x1, uint64_t x2, + uint64_t x3, uint64_t x4, void *cookie, + void *handle, uint64_t flags) +{ + uint32_t src_sec_state; + int ret; + + /* Determine which security state this SMC originated from */ + src_sec_state = caller_sec_state(flags); + + if (src_sec_state != SMC_FROM_REALM) { + WARN("RMMD: RMM-EL3 call originated from secure or normal world\n"); + SMC_RET1(handle, SMC_UNK); + } + + switch (smc_fid) { + case RMMD_GTSI_DELEGATE: + ret = gpt_delegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); + SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); + case RMMD_GTSI_UNDELEGATE: + ret = gpt_undelegate_pas(x1, PAGE_SIZE_4KB, SMC_FROM_REALM); + SMC_RET1(handle, gpt_to_gts_error(ret, smc_fid, x1)); + case RMMD_ATTEST_GET_PLAT_TOKEN: + ret = rmmd_attest_get_platform_token(x1, &x2, x3); + SMC_RET2(handle, ret, x2); + case RMMD_ATTEST_GET_REALM_KEY: + ret = rmmd_attest_get_signing_key(x1, &x2, x3); + SMC_RET2(handle, ret, x2); + default: + WARN("RMMD: Unsupported RMM-EL3 call 0x%08x\n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h new file mode 100644 index 0000000..73df2b8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2021-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef RMMD_PRIVATE_H +#define RMMD_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define RMMD_C_RT_CTX_X19 0x0 +#define RMMD_C_RT_CTX_X20 0x8 +#define RMMD_C_RT_CTX_X21 0x10 +#define RMMD_C_RT_CTX_X22 0x18 +#define RMMD_C_RT_CTX_X23 0x20 +#define RMMD_C_RT_CTX_X24 0x28 +#define RMMD_C_RT_CTX_X25 0x30 +#define RMMD_C_RT_CTX_X26 0x38 +#define RMMD_C_RT_CTX_X27 0x40 +#define RMMD_C_RT_CTX_X28 0x48 +#define RMMD_C_RT_CTX_X29 0x50 +#define RMMD_C_RT_CTX_X30 0x58 + +#define RMMD_C_RT_CTX_SIZE 0x60 +#define RMMD_C_RT_CTX_ENTRIES (RMMD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ +#include + +typedef enum rmm_state { + RMM_STATE_RESET = 0, + RMM_STATE_IDLE +} rmm_state_t; + +/* + * Data structure used by the RMM dispatcher (RMMD) in EL3 to track context of + * the RMM at R-EL2. + */ +typedef struct rmmd_rmm_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + rmm_state_t state; +} rmmd_rmm_context_t; + +/* Functions used to enter/exit the RMM synchronously */ +uint64_t rmmd_rmm_sync_entry(rmmd_rmm_context_t *ctx); +__dead2 void rmmd_rmm_sync_exit(uint64_t rc); + +/* Functions implementing attestation utilities for RMM */ +int rmmd_attest_get_platform_token(uint64_t buf_pa, uint64_t *buf_len, + uint64_t challenge_hash_len); +int rmmd_attest_get_signing_key(uint64_t buf_pa, uint64_t *buf_len, + uint64_t ecc_curve); + +/* Assembly helpers */ +uint64_t rmmd_rmm_enter(uint64_t *c_rt_ctx); +void __dead2 rmmd_rmm_exit(uint64_t c_rt_ctx, uint64_t ret); + +/* Reference to PM ops for the RMMD */ +extern const spd_pm_ops_t rmmd_pm; + +#endif /* __ASSEMBLER__ */ + +#endif /* RMMD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds b/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds new file mode 100644 index 0000000..2b7f383 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds @@ -0,0 +1,71 @@ +/* + * (C) COPYRIGHT 2021 Arm Limited or its affiliates. + * ALL RIGHTS RESERVED + */ + +#include +#include + +/* Mapped using 4K pages, requires us to align different sections with + * different property at the same granularity. */ +PAGE_SIZE_4K = 4096; + +OUTPUT_FORMAT("elf64-littleaarch64") +OUTPUT_ARCH(aarch64) +ENTRY(trp_head) + +MEMORY { + RAM (rwx): ORIGIN = RMM_BASE, LENGTH = RMM_LIMIT - RMM_BASE +} + + +SECTIONS +{ + . = RMM_BASE; + + .text : { + *(.head.text) + . = ALIGN(8); + *(.text*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + .rodata : { + *(.rodata*) + } >RAM + + . = ALIGN(PAGE_SIZE_4K); + + __RW_START__ = . ; + + .data : { + *(.data*) + } >RAM + + .bss (NOLOAD) : { + __BSS_START__ = .; + *(.bss*) + __BSS_END__ = .; + } >RAM + __BSS_SIZE__ = SIZEOF(.bss); + + + STACK_SECTION >RAM + + + /* + * Define a linker symbol to mark the end of the RW memory area for this + * image. + */ + __RW_END__ = .; + __RMM_END__ = .; + + + /DISCARD/ : { *(.dynstr*) } + /DISCARD/ : { *(.dynamic*) } + /DISCARD/ : { *(.plt*) } + /DISCARD/ : { *(.interp*) } + /DISCARD/ : { *(.gnu*) } + /DISCARD/ : { *(.note*) } +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk new file mode 100644 index 0000000..a4f6e03 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp.mk @@ -0,0 +1,20 @@ +# +# Copyright (c) 2021 Arm Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +RMM_SOURCES += services/std_svc/rmmd/trp/trp_entry.S \ + services/std_svc/rmmd/trp/trp_main.c + +RMM_LINKERFILE := services/std_svc/rmmd/trp/linker.lds + +# Include the platform-specific TRP Makefile +# If no platform-specific TRP Makefile exists, it means TRP is not supported +# on this platform. +TRP_PLAT_MAKEFILE := $(wildcard ${PLAT_DIR}/trp/trp-${PLAT}.mk) +ifeq (,${TRP_PLAT_MAKEFILE}) + $(error TRP is not supported on platform ${PLAT}) +else + include ${TRP_PLAT_MAKEFILE} +endif diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S new file mode 100644 index 0000000..1b03c9f --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2021-2022, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "trp_private.h" + +.global trp_head +.global trp_smc + +.section ".head.text", "ax" + + /* --------------------------------------------- + * Populate the params in x0-x7 from the pointer + * to the smc args structure in x0. + * --------------------------------------------- + */ + .macro restore_args_call_smc + ldp x6, x7, [x0, #TRP_ARG6] + ldp x4, x5, [x0, #TRP_ARG4] + ldp x2, x3, [x0, #TRP_ARG2] + ldp x0, x1, [x0, #TRP_ARG0] + smc #0 + .endm + + /* --------------------------------------------- + * Entry point for TRP + * --------------------------------------------- + */ +trp_head: + bl plat_set_my_stack + + /* + * Find out whether this is a cold or warm boot + */ + ldr x1, cold_boot_flag + cbz x1, warm_boot + + /* + * Update cold boot flag to indicate cold boot is done + */ + adr x2, cold_boot_flag + str xzr, [x2] + + + /* --------------------------------------------- + * Zero out BSS section + * --------------------------------------------- + */ + ldr x0, =__BSS_START__ + ldr x1, =__BSS_SIZE__ + bl zeromem + + bl trp_setup + + bl trp_main +warm_boot: + mov_imm x0, RMMD_RMI_REQ_COMPLETE + mov x1, xzr + smc #0 + b trp_handler + + /* + * Flag to mark if it is a cold boot. + * 1: cold boot, 0: warmboot. + */ +.align 3 +cold_boot_flag: + .dword 1 + + /* --------------------------------------------- + * Direct SMC call to BL31 service provided by + * RMM Dispatcher + * --------------------------------------------- + */ +func trp_smc + restore_args_call_smc + ret +endfunc trp_smc + + /* --------------------------------------------- + * RMI call handler + * --------------------------------------------- + */ +func trp_handler + bl trp_rmi_handler + restore_args_call_smc + b trp_handler +endfunc trp_handler diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c new file mode 100644 index 0000000..2e3f076 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + + +#include +#include +#include +#include + +#include +#include "trp_private.h" + +/******************************************************************************* + * Per cpu data structure to populate parameters for an SMC in C code and use + * a pointer to this structure in assembler code to populate x0-x7 + ******************************************************************************/ +static trp_args_t trp_smc_args[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * Set the arguments for SMC call + ******************************************************************************/ +static trp_args_t *set_smc_args(uint64_t arg0, + uint64_t arg1, + uint64_t arg2, + uint64_t arg3, + uint64_t arg4, + uint64_t arg5, + uint64_t arg6, + uint64_t arg7) +{ + uint32_t linear_id; + trp_args_t *pcpu_smc_args; + + /* + * Return to Secure Monitor by raising an SMC. The results of the + * service are passed as an arguments to the SMC + */ + linear_id = plat_my_core_pos(); + pcpu_smc_args = &trp_smc_args[linear_id]; + write_trp_arg(pcpu_smc_args, TRP_ARG0, arg0); + write_trp_arg(pcpu_smc_args, TRP_ARG1, arg1); + write_trp_arg(pcpu_smc_args, TRP_ARG2, arg2); + write_trp_arg(pcpu_smc_args, TRP_ARG3, arg3); + write_trp_arg(pcpu_smc_args, TRP_ARG4, arg4); + write_trp_arg(pcpu_smc_args, TRP_ARG5, arg5); + write_trp_arg(pcpu_smc_args, TRP_ARG6, arg6); + write_trp_arg(pcpu_smc_args, TRP_ARG7, arg7); + + return pcpu_smc_args; +} + +/******************************************************************************* + * Setup function for TRP. + ******************************************************************************/ +void trp_setup(void) +{ + /* Perform early platform-specific setup */ + trp_early_platform_setup(); +} + +/* Main function for TRP */ +void trp_main(void) +{ + NOTICE("TRP: %s\n", version_string); + NOTICE("TRP: %s\n", build_message); + INFO("TRP: Memory base : 0x%lx\n", (unsigned long)RMM_BASE); + INFO("TRP: Total size : 0x%lx bytes\n", (unsigned long)(RMM_END + - RMM_BASE)); +} + +/******************************************************************************* + * Returning RMI version back to Normal World + ******************************************************************************/ +static trp_args_t *trp_ret_rmi_version(void) +{ + VERBOSE("RMM version is %u.%u\n", RMI_ABI_VERSION_MAJOR, + RMI_ABI_VERSION_MINOR); + return set_smc_args(RMMD_RMI_REQ_COMPLETE, RMI_ABI_VERSION, + 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Transitioning granule of NON-SECURE type to REALM type + ******************************************************************************/ +static trp_args_t *trp_asc_mark_realm(unsigned long long x1) +{ + unsigned long long ret; + + VERBOSE("Delegating granule 0x%llx\n", x1); + ret = trp_smc(set_smc_args(RMMD_GTSI_DELEGATE, x1, 0, 0, 0, 0, 0, 0)); + + if (ret != 0ULL) { + ERROR("Granule transition from NON-SECURE type to REALM type " + "failed 0x%llx\n", ret); + } + return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Transitioning granule of REALM type to NON-SECURE type + ******************************************************************************/ +static trp_args_t *trp_asc_mark_nonsecure(unsigned long long x1) +{ + unsigned long long ret; + + VERBOSE("Undelegating granule 0x%llx\n", x1); + ret = trp_smc(set_smc_args(RMMD_GTSI_UNDELEGATE, x1, 0, 0, 0, 0, 0, 0)); + + if (ret != 0ULL) { + ERROR("Granule transition from REALM type to NON-SECURE type " + "failed 0x%llx\n", ret); + } + return set_smc_args(RMMD_RMI_REQ_COMPLETE, ret, 0, 0, 0, 0, 0, 0); +} + +/******************************************************************************* + * Main RMI SMC handler function + ******************************************************************************/ +trp_args_t *trp_rmi_handler(unsigned long fid, unsigned long long x1) +{ + switch (fid) { + case RMI_RMM_REQ_VERSION: + return trp_ret_rmi_version(); + case RMI_RMM_GRANULE_DELEGATE: + return trp_asc_mark_realm(x1); + case RMI_RMM_GRANULE_UNDELEGATE: + return trp_asc_mark_nonsecure(x1); + default: + ERROR("Invalid SMC code to %s, FID %lu\n", __func__, fid); + } + return set_smc_args(SMC_UNK, 0, 0, 0, 0, 0, 0, 0); +} diff --git a/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h new file mode 100644 index 0000000..43a4a4b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2021-2022, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRP_PRIVATE_H +#define TRP_PRIVATE_H + +/* Definitions to help the assembler access the SMC/ERET args structure */ +#define TRP_ARGS_SIZE TRP_ARGS_END +#define TRP_ARG0 0x0 +#define TRP_ARG1 0x8 +#define TRP_ARG2 0x10 +#define TRP_ARG3 0x18 +#define TRP_ARG4 0x20 +#define TRP_ARG5 0x28 +#define TRP_ARG6 0x30 +#define TRP_ARG7 0x38 +#define TRP_ARGS_END 0x40 + +#ifndef __ASSEMBLER__ + +#include + +/* Data structure to hold SMC arguments */ +typedef struct trp_args { + uint64_t regs[TRP_ARGS_END >> 3]; +} __aligned(CACHE_WRITEBACK_GRANULE) trp_args_t; + +#define write_trp_arg(args, offset, val) (((args)->regs[offset >> 3]) \ + = val) + +/* RMI handled by TRP */ +#define RMI_FNUM_VERSION_REQ U(0x150) + +#define RMI_FNUM_GRANULE_DELEGATE U(0x151) +#define RMI_FNUM_GRANULE_UNDELEGATE U(0x152) + +#define RMI_RMM_REQ_VERSION RMM_FID(SMC_64, RMI_FNUM_VERSION_REQ) + +#define RMI_RMM_GRANULE_DELEGATE RMM_FID(SMC_64, \ + RMI_FNUM_GRANULE_DELEGATE) +#define RMI_RMM_GRANULE_UNDELEGATE RMM_FID(SMC_64, \ + RMI_FNUM_GRANULE_UNDELEGATE) + +/* Definitions for RMI VERSION */ +#define RMI_ABI_VERSION_MAJOR U(0x0) +#define RMI_ABI_VERSION_MINOR U(0x0) +#define RMI_ABI_VERSION ((RMI_ABI_VERSION_MAJOR << 16) | \ + RMI_ABI_VERSION_MINOR) + +/* Helper to issue SMC calls to BL31 */ +uint64_t trp_smc(trp_args_t *); + +/* The main function to executed only by Primary CPU */ +void trp_main(void); + +/* Setup TRP. Executed only by Primary CPU */ +void trp_setup(void); + +#endif /* __ASSEMBLER__ */ +#endif /* TRP_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S b/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S new file mode 100644 index 0000000..8449e4b --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + + .globl begin_sdei_synchronous_dispatch + +/* + * void begin_sdei_synchronous_dispatch(jmp_buf *buffer); + * + * Begin SDEI dispatch synchronously by setting up a jump point, and exiting + * EL3. This jump point is jumped to by the dispatcher after the event is + * completed by the client. + */ +func begin_sdei_synchronous_dispatch + stp x30, xzr, [sp, #-16]! + bl setjmp + cbz x0, 1f + ldp x30, xzr, [sp], #16 + ret +1: + b el3_exit +endfunc begin_sdei_synchronous_dispatch diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c new file mode 100644 index 0000000..0b608e1 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_event.c @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "sdei_private.h" + +#define MAP_OFF(_map, _mapping) ((_map) - (_mapping)->map) + +/* + * Get SDEI entry with the given mapping: on success, returns pointer to SDEI + * entry. On error, returns NULL. + * + * Both shared and private maps are stored in single-dimensional array. Private + * event entries are kept for each PE forming a 2D array. + */ +sdei_entry_t *get_event_entry(sdei_ev_map_t *map) +{ + const sdei_mapping_t *mapping; + sdei_entry_t *cpu_priv_base; + unsigned int base_idx; + long int idx; + + if (is_event_private(map)) { + /* + * For a private map, find the index of the mapping in the + * array. + */ + mapping = SDEI_PRIVATE_MAPPING(); + idx = MAP_OFF(map, mapping); + + /* Base of private mappings for this CPU */ + base_idx = plat_my_core_pos() * ((unsigned int) mapping->num_maps); + cpu_priv_base = &sdei_private_event_table[base_idx]; + + /* + * Return the address of the entry at the same index in the + * per-CPU event entry. + */ + return &cpu_priv_base[idx]; + } else { + mapping = SDEI_SHARED_MAPPING(); + idx = MAP_OFF(map, mapping); + + return &sdei_shared_event_table[idx]; + } +} + +/* + * Find event mapping for a given interrupt number: On success, returns pointer + * to the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i; + + /* + * Look for a match in private and shared mappings, as requested. This + * is a linear search. However, if the mappings are required to be + * sorted, for large maps, we could consider binary search. + */ + mapping = shared ? SDEI_SHARED_MAPPING() : SDEI_PRIVATE_MAPPING(); + iterate_mapping(mapping, i, map) { + if (map->intr == intr_num) + return map; + } + + return NULL; +} + +/* + * Find event mapping for a given event number: On success returns pointer to + * the event mapping. On error, returns NULL. + */ +sdei_ev_map_t *find_event_map(int ev_num) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + unsigned int i, j; + + /* + * Iterate through mappings to find a match. This is a linear search. + * However, if the mappings are required to be sorted, for large maps, + * we could consider binary search. + */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + if (map->ev_num == ev_num) + return map; + } + } + + return NULL; +} diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c new file mode 100644 index 0000000..87a1fb7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c @@ -0,0 +1,774 @@ +/* + * Copyright (c) 2017-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdei_private.h" + +/* x0-x17 GPREGS context */ +#define SDEI_SAVED_GPREGS 18U + +/* Maximum preemption nesting levels: Critical priority and Normal priority */ +#define MAX_EVENT_NESTING 2U + +/* Per-CPU SDEI state access macro */ +#define sdei_get_this_pe_state() (&cpu_state[plat_my_core_pos()]) + +/* Structure to store information about an outstanding dispatch */ +typedef struct sdei_dispatch_context { + sdei_ev_map_t *map; + uint64_t x[SDEI_SAVED_GPREGS]; + jmp_buf *dispatch_jmp; + + /* Exception state registers */ + uint64_t elr_el3; + uint64_t spsr_el3; + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + /* CVE-2018-3639 mitigation state */ + uint64_t disable_cve_2018_3639; +#endif +} sdei_dispatch_context_t; + +/* Per-CPU SDEI state data */ +typedef struct sdei_cpu_state { + sdei_dispatch_context_t dispatch_stack[MAX_EVENT_NESTING]; + unsigned short stack_top; /* Empty ascending */ + bool pe_masked; + bool pending_enables; +} sdei_cpu_state_t; + +/* SDEI states for all cores in the system */ +static sdei_cpu_state_t cpu_state[PLATFORM_CORE_COUNT]; + +int64_t sdei_pe_mask(void) +{ + int64_t ret = 0; + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + /* + * Return value indicates whether this call had any effect in the mask + * status of this PE. + */ + if (!state->pe_masked) { + state->pe_masked = true; + ret = 1; + } + + return ret; +} + +void sdei_pe_unmask(void) +{ + unsigned int i; + sdei_ev_map_t *map; + sdei_entry_t *se; + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + uint64_t my_mpidr = read_mpidr_el1() & MPIDR_AFFINITY_MASK; + + /* + * If there are pending enables, iterate through the private mappings + * and enable those bound maps that are in enabled state. Also, iterate + * through shared mappings and enable interrupts of events that are + * targeted to this PE. + */ + if (state->pending_enables) { + for_each_private_map(i, map) { + se = get_event_entry(map); + if (is_map_bound(map) && GET_EV_STATE(se, ENABLED)) + plat_ic_enable_interrupt(map->intr); + } + + for_each_shared_map(i, map) { + se = get_event_entry(map); + + sdei_map_lock(map); + if (is_map_bound(map) && GET_EV_STATE(se, ENABLED) && + (se->reg_flags == SDEI_REGF_RM_PE) && + (se->affinity == my_mpidr)) { + plat_ic_enable_interrupt(map->intr); + } + sdei_map_unlock(map); + } + } + + state->pending_enables = false; + state->pe_masked = false; +} + +/* Push a dispatch context to the dispatch stack */ +static sdei_dispatch_context_t *push_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + sdei_dispatch_context_t *disp_ctx; + + /* Cannot have more than max events */ + assert(state->stack_top < MAX_EVENT_NESTING); + + disp_ctx = &state->dispatch_stack[state->stack_top]; + state->stack_top++; + + return disp_ctx; +} + +/* Pop a dispatch context to the dispatch stack */ +static sdei_dispatch_context_t *pop_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + if (state->stack_top == 0U) + return NULL; + + assert(state->stack_top <= MAX_EVENT_NESTING); + + state->stack_top--; + + return &state->dispatch_stack[state->stack_top]; +} + +/* Retrieve the context at the top of dispatch stack */ +static sdei_dispatch_context_t *get_outstanding_dispatch(void) +{ + sdei_cpu_state_t *state = sdei_get_this_pe_state(); + + if (state->stack_top == 0U) + return NULL; + + assert(state->stack_top <= MAX_EVENT_NESTING); + + return &state->dispatch_stack[state->stack_top - 1U]; +} + +static sdei_dispatch_context_t *save_event_ctx(sdei_ev_map_t *map, + void *tgt_ctx) +{ + sdei_dispatch_context_t *disp_ctx; + const gp_regs_t *tgt_gpregs; + const el3_state_t *tgt_el3; + + assert(tgt_ctx != NULL); + tgt_gpregs = get_gpregs_ctx(tgt_ctx); + tgt_el3 = get_el3state_ctx(tgt_ctx); + + disp_ctx = push_dispatch(); + assert(disp_ctx != NULL); + disp_ctx->map = map; + + /* Save general purpose and exception registers */ + memcpy(disp_ctx->x, tgt_gpregs, sizeof(disp_ctx->x)); + disp_ctx->spsr_el3 = read_ctx_reg(tgt_el3, CTX_SPSR_EL3); + disp_ctx->elr_el3 = read_ctx_reg(tgt_el3, CTX_ELR_EL3); + + return disp_ctx; +} + +static void restore_event_ctx(const sdei_dispatch_context_t *disp_ctx, void *tgt_ctx) +{ + gp_regs_t *tgt_gpregs; + el3_state_t *tgt_el3; + + assert(tgt_ctx != NULL); + tgt_gpregs = get_gpregs_ctx(tgt_ctx); + tgt_el3 = get_el3state_ctx(tgt_ctx); + + CASSERT(sizeof(disp_ctx->x) == (SDEI_SAVED_GPREGS * sizeof(uint64_t)), + foo); + + /* Restore general purpose and exception registers */ + memcpy(tgt_gpregs, disp_ctx->x, sizeof(disp_ctx->x)); + write_ctx_reg(tgt_el3, CTX_SPSR_EL3, disp_ctx->spsr_el3); + write_ctx_reg(tgt_el3, CTX_ELR_EL3, disp_ctx->elr_el3); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(tgt_ctx); + + /* Restore CVE-2018-3639 mitigation state */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, + disp_ctx->disable_cve_2018_3639); +#endif +} + +static void save_secure_context(void) +{ + cm_el1_sysregs_context_save(SECURE); +} + +/* Restore Secure context and arrange to resume it at the next ERET */ +static void restore_and_resume_secure_context(void) +{ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); +} + +/* + * Restore Non-secure context and arrange to resume it at the next ERET. Return + * pointer to the Non-secure context. + */ +static cpu_context_t *restore_and_resume_ns_context(void) +{ + cpu_context_t *ns_ctx; + + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + ns_ctx = cm_get_context(NON_SECURE); + assert(ns_ctx != NULL); + + return ns_ctx; +} + +/* + * Prepare for ERET: + * - Set the ELR to the registered handler address + * - Set the SPSR register as described in the SDEI documentation and + * the AArch64.TakeException() pseudocode function in + * ARM DDI 0487F.c page J1-7635 + */ + +static void sdei_set_elr_spsr(sdei_entry_t *se, sdei_dispatch_context_t *disp_ctx) +{ + unsigned int client_el = sdei_client_el(); + u_register_t sdei_spsr = SPSR_64(client_el, MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + + u_register_t interrupted_pstate = disp_ctx->spsr_el3; + + /* Check the SPAN bit in the client el SCTLR */ + u_register_t client_el_sctlr; + + if (client_el == MODE_EL2) { + client_el_sctlr = read_sctlr_el2(); + } else { + client_el_sctlr = read_sctlr_el1(); + } + + /* + * Check whether to force the PAN bit or use the value in the + * interrupted EL according to the check described in + * TakeException. Since the client can only be Non-Secure + * EL2 or El1 some of the conditions in ElIsInHost() we know + * will always be True. + * When the client_el is EL2 we know that there will be a SPAN + * bit in SCTLR_EL2 as we have already checked for the condition + * HCR_EL2.E2H = 1 and HCR_EL2.TGE = 1 + */ + u_register_t hcr_el2 = read_hcr(); + bool el_is_in_host = is_armv8_1_vhe_present() && + (hcr_el2 & HCR_TGE_BIT) && + (hcr_el2 & HCR_E2H_BIT); + + if (is_armv8_1_pan_present() && + ((client_el == MODE_EL1) || + (client_el == MODE_EL2 && el_is_in_host)) && + ((client_el_sctlr & SCTLR_SPAN_BIT) == 0U)) { + sdei_spsr |= SPSR_PAN_BIT; + } else { + sdei_spsr |= (interrupted_pstate & SPSR_PAN_BIT); + } + + /* If SSBS is implemented, take the value from the client el SCTLR */ + u_register_t ssbs_enabled = (read_id_aa64pfr1_el1() + >> ID_AA64PFR1_EL1_SSBS_SHIFT) + & ID_AA64PFR1_EL1_SSBS_MASK; + if (ssbs_enabled != SSBS_UNAVAILABLE) { + u_register_t ssbs_bit = ((client_el_sctlr & SCTLR_DSSBS_BIT) + >> SCTLR_DSSBS_SHIFT) + << SPSR_SSBS_SHIFT_AARCH64; + sdei_spsr |= ssbs_bit; + } + + /* If MTE is implemented in the client el set the TCO bit */ + if (get_armv8_5_mte_support() >= MTE_IMPLEMENTED_ELX) { + sdei_spsr |= SPSR_TCO_BIT_AARCH64; + } + + /* Take the DIT field from the pstate of the interrupted el */ + sdei_spsr |= (interrupted_pstate & SPSR_DIT_BIT); + + cm_set_elr_spsr_el3(NON_SECURE, (uintptr_t) se->ep, sdei_spsr); +} + +/* + * Populate the Non-secure context so that the next ERET will dispatch to the + * SDEI client. + */ +static void setup_ns_dispatch(sdei_ev_map_t *map, sdei_entry_t *se, + cpu_context_t *ctx, jmp_buf *dispatch_jmp) +{ + sdei_dispatch_context_t *disp_ctx; + + /* Push the event and context */ + disp_ctx = save_event_ctx(map, ctx); + + /* + * Setup handler arguments: + * + * - x0: Event number + * - x1: Handler argument supplied at the time of event registration + * - x2: Interrupted PC + * - x3: Interrupted SPSR + */ + SMC_SET_GP(ctx, CTX_GPREG_X0, (uint64_t) map->ev_num); + SMC_SET_GP(ctx, CTX_GPREG_X1, se->arg); + SMC_SET_GP(ctx, CTX_GPREG_X2, disp_ctx->elr_el3); + SMC_SET_GP(ctx, CTX_GPREG_X3, disp_ctx->spsr_el3); + + /* Setup the elr and spsr register to prepare for ERET */ + sdei_set_elr_spsr(se, disp_ctx); + +#if DYNAMIC_WORKAROUND_CVE_2018_3639 + cve_2018_3639_t *tgt_cve_2018_3639; + tgt_cve_2018_3639 = get_cve_2018_3639_ctx(ctx); + + /* Save CVE-2018-3639 mitigation state */ + disp_ctx->disable_cve_2018_3639 = read_ctx_reg(tgt_cve_2018_3639, + CTX_CVE_2018_3639_DISABLE); + + /* Force SDEI handler to execute with mitigation enabled by default */ + write_ctx_reg(tgt_cve_2018_3639, CTX_CVE_2018_3639_DISABLE, 0); +#endif + + disp_ctx->dispatch_jmp = dispatch_jmp; +} + +/* Handle a triggered SDEI interrupt while events were masked on this PE */ +static void handle_masked_trigger(sdei_ev_map_t *map, sdei_entry_t *se, + sdei_cpu_state_t *state, unsigned int intr_raw) +{ + uint64_t my_mpidr __unused = (read_mpidr_el1() & MPIDR_AFFINITY_MASK); + bool disable = false; + + /* Nothing to do for event 0 */ + if (map->ev_num == SDEI_EVENT_0) + return; + + /* + * For a private event, or for a shared event specifically routed to + * this CPU, we disable interrupt, leave the interrupt pending, and do + * EOI. + */ + if (is_event_private(map) || (se->reg_flags == SDEI_REGF_RM_PE)) + disable = true; + + if (se->reg_flags == SDEI_REGF_RM_PE) + assert(se->affinity == my_mpidr); + + if (disable) { + plat_ic_disable_interrupt(map->intr); + plat_ic_set_interrupt_pending(map->intr); + plat_ic_end_of_interrupt(intr_raw); + state->pending_enables = true; + + return; + } + + /* + * We just received a shared event with routing set to ANY PE. The + * interrupt can't be delegated on this PE as SDEI events are masked. + * However, because its routing mode is ANY, it is possible that the + * event can be delegated on any other PE that hasn't masked events. + * Therefore, we set the interrupt back pending so as to give other + * suitable PEs a chance of handling it. + */ + assert(plat_ic_is_spi(map->intr) != 0); + plat_ic_set_interrupt_pending(map->intr); + + /* + * Leaving the same interrupt pending also means that the same interrupt + * can target this PE again as soon as this PE leaves EL3. Whether and + * how often that happens depends on the implementation of GIC. + * + * We therefore call a platform handler to resolve this situation. + */ + plat_sdei_handle_masked_trigger(my_mpidr, map->intr); + + /* This PE is masked. We EOI the interrupt, as it can't be delegated */ + plat_ic_end_of_interrupt(intr_raw); +} + +/* SDEI main interrupt handler */ +int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie) +{ + sdei_entry_t *se; + cpu_context_t *ctx; + sdei_ev_map_t *map; + const sdei_dispatch_context_t *disp_ctx; + unsigned int sec_state; + sdei_cpu_state_t *state; + uint32_t intr; + jmp_buf dispatch_jmp; + const uint64_t mpidr = read_mpidr_el1(); + + /* + * To handle an event, the following conditions must be true: + * + * 1. Event must be signalled + * 2. Event must be enabled + * 3. This PE must be a target PE for the event + * 4. PE must be unmasked for SDEI + * 5. If this is a normal event, no event must be running + * 6. If this is a critical event, no critical event must be running + * + * (1) and (2) are true when this function is running + * (3) is enforced in GIC by selecting the appropriate routing option + * (4) is satisfied by client calling PE_UNMASK + * (5) and (6) is enforced using interrupt priority, the RPR, in GIC: + * - Normal SDEI events belong to Normal SDE priority class + * - Critical SDEI events belong to Critical CSDE priority class + * + * The interrupt has already been acknowledged, and therefore is active, + * so no other PE can handle this event while we are at it. + * + * Find if this is an SDEI interrupt. There must be an event mapped to + * this interrupt + */ + intr = plat_ic_get_interrupt_id(intr_raw); + map = find_event_map_by_intr(intr, (plat_ic_is_spi(intr) != 0)); + if (map == NULL) { + ERROR("No SDEI map for interrupt %u\n", intr); + panic(); + } + + /* + * Received interrupt number must either correspond to event 0, or must + * be bound interrupt. + */ + assert((map->ev_num == SDEI_EVENT_0) || is_map_bound(map)); + + se = get_event_entry(map); + state = sdei_get_this_pe_state(); + + if (state->pe_masked) { + /* + * Interrupts received while this PE was masked can't be + * dispatched. + */ + SDEI_LOG("interrupt %u on %" PRIx64 " while PE masked\n", + map->intr, mpidr); + if (is_event_shared(map)) + sdei_map_lock(map); + + handle_masked_trigger(map, se, state, intr_raw); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return 0; + } + + /* Insert load barrier for signalled SDEI event */ + if (map->ev_num == SDEI_EVENT_0) + dmbld(); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* Assert shared event routed to this PE had been configured so */ + if (is_event_shared(map) && (se->reg_flags == SDEI_REGF_RM_PE)) { + assert(se->affinity == (mpidr & MPIDR_AFFINITY_MASK)); + } + + if (!can_sdei_state_trans(se, DO_DISPATCH)) { + SDEI_LOG("SDEI event 0x%x can't be dispatched; state=0x%x\n", + map->ev_num, se->state); + + /* + * If the event is registered, leave the interrupt pending so + * that it's delivered when the event is enabled. + */ + if (GET_EV_STATE(se, REGISTERED)) + plat_ic_set_interrupt_pending(map->intr); + + /* + * The interrupt was disabled or unregistered after the handler + * started to execute, which means now the interrupt is already + * disabled and we just need to EOI the interrupt. + */ + plat_ic_end_of_interrupt(intr_raw); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return 0; + } + + disp_ctx = get_outstanding_dispatch(); + if (is_event_critical(map)) { + /* + * If this event is Critical, and if there's an outstanding + * dispatch, assert the latter is a Normal dispatch. Critical + * events can preempt an outstanding Normal event dispatch. + */ + if (disp_ctx != NULL) + assert(is_event_normal(disp_ctx->map)); + } else { + /* + * If this event is Normal, assert that there are no outstanding + * dispatches. Normal events can't preempt any outstanding event + * dispatches. + */ + assert(disp_ctx == NULL); + } + + sec_state = get_interrupt_src_ss(flags); + + if (is_event_shared(map)) + sdei_map_unlock(map); + + SDEI_LOG("ACK %" PRIx64 ", ev:0x%x ss:%d spsr:%lx ELR:%lx\n", + mpidr, map->ev_num, sec_state, read_spsr_el3(), read_elr_el3()); + + ctx = handle; + + /* + * Check if we interrupted secure state. Perform a context switch so + * that we can delegate to NS. + */ + if (sec_state == SECURE) { + save_secure_context(); + ctx = restore_and_resume_ns_context(); + } + + /* Synchronously dispatch event */ + setup_ns_dispatch(map, se, ctx, &dispatch_jmp); + begin_sdei_synchronous_dispatch(&dispatch_jmp); + + /* + * We reach here when client completes the event. + * + * If the cause of dispatch originally interrupted the Secure world, + * resume Secure. + * + * No need to save the Non-secure context ahead of a world switch: the + * Non-secure context was fully saved before dispatch, and has been + * returned to its pre-dispatch state. + */ + if (sec_state == SECURE) + restore_and_resume_secure_context(); + + /* + * The event was dispatched after receiving SDEI interrupt. With + * the event handling completed, EOI the corresponding + * interrupt. + */ + if ((map->ev_num != SDEI_EVENT_0) && !is_map_bound(map)) { + ERROR("Invalid SDEI mapping: ev=0x%x\n", map->ev_num); + panic(); + } + plat_ic_end_of_interrupt(intr_raw); + + return 0; +} + +/* + * Explicitly dispatch the given SDEI event. + * + * When calling this API, the caller must be prepared for the SDEI dispatcher to + * restore and make Non-secure context as active. This call returns only after + * the client has completed the dispatch. Then, the Non-secure context will be + * active, and the following ERET will return to Non-secure. + * + * Should the caller require re-entry to Secure, it must restore the Secure + * context and program registers for ERET. + */ +int sdei_dispatch_event(int ev_num) +{ + sdei_entry_t *se; + sdei_ev_map_t *map; + cpu_context_t *ns_ctx; + sdei_dispatch_context_t *disp_ctx; + sdei_cpu_state_t *state; + jmp_buf dispatch_jmp; + + /* Can't dispatch if events are masked on this PE */ + state = sdei_get_this_pe_state(); + if (state->pe_masked) + return -1; + + /* Event 0 can't be dispatched */ + if (ev_num == SDEI_EVENT_0) + return -1; + + /* Locate mapping corresponding to this event */ + map = find_event_map(ev_num); + if (map == NULL) + return -1; + + /* Only explicit events can be dispatched */ + if (!is_map_explicit(map)) + return -1; + + /* Examine state of dispatch stack */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx != NULL) { + /* + * There's an outstanding dispatch. If the outstanding dispatch + * is critical, no more dispatches are possible. + */ + if (is_event_critical(disp_ctx->map)) + return -1; + + /* + * If the outstanding dispatch is Normal, only critical events + * can be dispatched. + */ + if (is_event_normal(map)) + return -1; + } + + se = get_event_entry(map); + if (!can_sdei_state_trans(se, DO_DISPATCH)) + return -1; + + /* + * Prepare for NS dispatch by restoring the Non-secure context and + * marking that as active. + */ + ns_ctx = restore_and_resume_ns_context(); + + /* Activate the priority corresponding to the event being dispatched */ + ehf_activate_priority(sdei_event_priority(map)); + + /* Dispatch event synchronously */ + setup_ns_dispatch(map, se, ns_ctx, &dispatch_jmp); + begin_sdei_synchronous_dispatch(&dispatch_jmp); + + /* + * We reach here when client completes the event. + * + * Deactivate the priority level that was activated at the time of + * explicit dispatch. + */ + ehf_deactivate_priority(sdei_event_priority(map)); + + return 0; +} + +static void end_sdei_synchronous_dispatch(jmp_buf *buffer) +{ + longjmp(*buffer, 1); +} + +int sdei_event_complete(bool resume, uint64_t pc) +{ + sdei_dispatch_context_t *disp_ctx; + sdei_entry_t *se; + sdei_ev_map_t *map; + cpu_context_t *ctx; + sdei_action_t act; + unsigned int client_el = sdei_client_el(); + + /* Return error if called without an active event */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx == NULL) + return SDEI_EDENY; + + /* Validate resumption point */ + if (resume && (plat_sdei_validate_entry_point(pc, client_el) != 0)) + return SDEI_EDENY; + + map = disp_ctx->map; + assert(map != NULL); + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + act = resume ? DO_COMPLETE_RESUME : DO_COMPLETE; + if (!can_sdei_state_trans(se, act)) { + if (is_event_shared(map)) + sdei_map_unlock(map); + return SDEI_EDENY; + } + + if (is_event_shared(map)) + sdei_map_unlock(map); + + /* Having done sanity checks, pop dispatch */ + (void) pop_dispatch(); + + SDEI_LOG("EOI:%lx, %d spsr:%lx elr:%lx\n", read_mpidr_el1(), + map->ev_num, read_spsr_el3(), read_elr_el3()); + + /* + * Restore Non-secure to how it was originally interrupted. Once done, + * it's up-to-date with the saved copy. + */ + ctx = cm_get_context(NON_SECURE); + restore_event_ctx(disp_ctx, ctx); + + if (resume) { + /* + * Complete-and-resume call. Prepare the Non-secure context + * (currently active) for complete and resume. + */ + cm_set_elr_spsr_el3(NON_SECURE, pc, SPSR_64(client_el, + MODE_SP_ELX, DISABLE_ALL_EXCEPTIONS)); + + /* + * Make it look as if a synchronous exception were taken at the + * supplied Non-secure resumption point. Populate SPSR and + * ELR_ELx so that an ERET from there works as expected. + * + * The assumption is that the client, if necessary, would have + * saved any live content in these registers before making this + * call. + */ + if (client_el == MODE_EL2) { + write_elr_el2(disp_ctx->elr_el3); + write_spsr_el2(disp_ctx->spsr_el3); + } else { + /* EL1 */ + write_elr_el1(disp_ctx->elr_el3); + write_spsr_el1(disp_ctx->spsr_el3); + } + } + + /* End the outstanding dispatch */ + end_sdei_synchronous_dispatch(disp_ctx->dispatch_jmp); + + return 0; +} + +int64_t sdei_event_context(void *handle, unsigned int param) +{ + sdei_dispatch_context_t *disp_ctx; + + if (param >= SDEI_SAVED_GPREGS) + return SDEI_EINVAL; + + /* Get outstanding dispatch on this CPU */ + disp_ctx = get_outstanding_dispatch(); + if (disp_ctx == NULL) + return SDEI_EDENY; + + assert(disp_ctx->map != NULL); + + if (!can_sdei_state_trans(get_event_entry(disp_ctx->map), DO_CONTEXT)) + return SDEI_EDENY; + + /* + * No locking is required for the Running status as this is the only CPU + * which can complete the event + */ + + return (int64_t) disp_ctx->x[param]; +} diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c new file mode 100644 index 0000000..44178ed --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_main.c @@ -0,0 +1,1114 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "sdei_private.h" + +#define MAJOR_VERSION 1ULL +#define MINOR_VERSION 0ULL +#define VENDOR_VERSION 0ULL + +#define MAKE_SDEI_VERSION(_major, _minor, _vendor) \ + ((((_major)) << 48ULL) | (((_minor)) << 32ULL) | (_vendor)) + +#define LOWEST_INTR_PRIORITY 0xff + +#define is_valid_affinity(_mpidr) (plat_core_pos_by_mpidr(_mpidr) >= 0) + +CASSERT(PLAT_SDEI_CRITICAL_PRI < PLAT_SDEI_NORMAL_PRI, + sdei_critical_must_have_higher_priority); + +static unsigned int num_dyn_priv_slots, num_dyn_shrd_slots; + +/* Initialise SDEI map entries */ +static void init_map(sdei_ev_map_t *map) +{ + map->reg_count = 0; +} + +/* Convert mapping to SDEI class */ +static sdei_class_t map_to_class(sdei_ev_map_t *map) +{ + return is_event_critical(map) ? SDEI_CRITICAL : SDEI_NORMAL; +} + +/* Clear SDEI event entries except state */ +static void clear_event_entries(sdei_entry_t *se) +{ + se->ep = 0; + se->arg = 0; + se->affinity = 0; + se->reg_flags = 0; +} + +/* Perform CPU-specific state initialisation */ +static void *sdei_cpu_on_init(const void *arg) +{ + unsigned int i; + sdei_ev_map_t *map; + sdei_entry_t *se; + + /* Initialize private mappings on this CPU */ + for_each_private_map(i, map) { + se = get_event_entry(map); + clear_event_entries(se); + se->state = 0; + } + + SDEI_LOG("Private events initialized on %lx\n", read_mpidr_el1()); + + /* All PEs start with SDEI events masked */ + (void) sdei_pe_mask(); + + return NULL; +} + +/* CPU initialisation after wakeup from suspend */ +static void *sdei_cpu_wakeup_init(const void *arg) +{ + SDEI_LOG("Events masked on %lx\n", read_mpidr_el1()); + + /* All PEs wake up with SDEI events masked */ + sdei_pe_mask(); + + return 0; +} + +/* Initialise an SDEI class */ +static void sdei_class_init(sdei_class_t class) +{ + unsigned int i; + bool zero_found __unused = false; + int ev_num_so_far __unused; + sdei_ev_map_t *map; + + /* Sanity check and configuration of shared events */ + ev_num_so_far = -1; + for_each_shared_map(i, map) { +#if ENABLE_ASSERTIONS + /* Ensure mappings are sorted */ + assert((ev_num_so_far < 0) || (map->ev_num > ev_num_so_far)); + + ev_num_so_far = map->ev_num; + + /* Event 0 must not be shared */ + assert(map->ev_num != SDEI_EVENT_0); + + /* Check for valid event */ + assert(map->ev_num >= 0); + + /* Make sure it's a shared event */ + assert(is_event_shared(map)); + + /* No shared mapping should have signalable property */ + assert(!is_event_signalable(map)); + + /* Shared mappings can't be explicit */ + assert(!is_map_explicit(map)); +#endif + + /* Skip initializing the wrong priority */ + if (map_to_class(map) != class) + continue; + + /* Platform events are always bound, so set the bound flag */ + if (is_map_dynamic(map)) { + assert(map->intr == SDEI_DYN_IRQ); + assert(is_event_normal(map)); + num_dyn_shrd_slots++; + } else { + /* Shared mappings must be bound to shared interrupt */ + assert(plat_ic_is_spi(map->intr) != 0); + set_map_bound(map); + } + + init_map(map); + } + + /* Sanity check and configuration of private events for this CPU */ + ev_num_so_far = -1; + for_each_private_map(i, map) { +#if ENABLE_ASSERTIONS + /* Ensure mappings are sorted */ + assert((ev_num_so_far < 0) || (map->ev_num > ev_num_so_far)); + + ev_num_so_far = map->ev_num; + + if (map->ev_num == SDEI_EVENT_0) { + zero_found = true; + + /* Event 0 must be a Secure SGI */ + assert(is_secure_sgi(map->intr)); + + /* + * Event 0 can have only have signalable flag (apart + * from being private + */ + assert(map->map_flags == (SDEI_MAPF_SIGNALABLE | + SDEI_MAPF_PRIVATE)); + } else { + /* No other mapping should have signalable property */ + assert(!is_event_signalable(map)); + } + + /* Check for valid event */ + assert(map->ev_num >= 0); + + /* Make sure it's a private event */ + assert(is_event_private(map)); + + /* + * Other than priority, explicit events can only have explicit + * and private flags set. + */ + if (is_map_explicit(map)) { + assert((map->map_flags | SDEI_MAPF_CRITICAL) == + (SDEI_MAPF_EXPLICIT | SDEI_MAPF_PRIVATE + | SDEI_MAPF_CRITICAL)); + } +#endif + + /* Skip initializing the wrong priority */ + if (map_to_class(map) != class) + continue; + + /* Platform events are always bound, so set the bound flag */ + if (map->ev_num != SDEI_EVENT_0) { + if (is_map_dynamic(map)) { + assert(map->intr == SDEI_DYN_IRQ); + assert(is_event_normal(map)); + num_dyn_priv_slots++; + } else if (is_map_explicit(map)) { + /* + * Explicit mappings don't have a backing + * SDEI interrupt, but verify that anyway. + */ + assert(map->intr == SDEI_DYN_IRQ); + } else { + /* + * Private mappings must be bound to private + * interrupt. + */ + assert(plat_ic_is_ppi((unsigned) map->intr) != 0); + set_map_bound(map); + } + } + + init_map(map); + } + + /* Ensure event 0 is in the mapping */ + assert(zero_found); + + (void) sdei_cpu_on_init(NULL); +} + +/* SDEI dispatcher initialisation */ +void sdei_init(void) +{ + plat_sdei_setup(); + sdei_class_init(SDEI_CRITICAL); + sdei_class_init(SDEI_NORMAL); + + /* Register priority level handlers */ + ehf_register_priority_handler(PLAT_SDEI_CRITICAL_PRI, + sdei_intr_handler); + ehf_register_priority_handler(PLAT_SDEI_NORMAL_PRI, + sdei_intr_handler); +} + +/* Populate SDEI event entry */ +static void set_sdei_entry(sdei_entry_t *se, uint64_t ep, uint64_t arg, + unsigned int flags, uint64_t affinity) +{ + assert(se != NULL); + + se->ep = ep; + se->arg = arg; + se->affinity = (affinity & MPIDR_AFFINITY_MASK); + se->reg_flags = flags; +} + +static uint64_t sdei_version(void) +{ + return MAKE_SDEI_VERSION(MAJOR_VERSION, MINOR_VERSION, VENDOR_VERSION); +} + +/* Validate flags and MPIDR values for REGISTER and ROUTING_SET calls */ +static int validate_flags(uint64_t flags, uint64_t mpidr) +{ + /* Validate flags */ + switch (flags) { + case SDEI_REGF_RM_PE: + if (!is_valid_affinity(mpidr)) + return SDEI_EINVAL; + break; + case SDEI_REGF_RM_ANY: + break; + default: + /* Unknown flags */ + return SDEI_EINVAL; + } + + return 0; +} + +/* Set routing of an SDEI event */ +static int sdei_event_routing_set(int ev_num, uint64_t flags, uint64_t mpidr) +{ + int ret; + unsigned int routing; + sdei_ev_map_t *map; + sdei_entry_t *se; + + ret = validate_flags(flags, mpidr); + if (ret != 0) + return ret; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + /* The event must not be private */ + if (is_event_private(map)) + return SDEI_EINVAL; + + se = get_event_entry(map); + + sdei_map_lock(map); + + if (!is_map_bound(map) || is_event_private(map)) { + ret = SDEI_EINVAL; + goto finish; + } + + if (!can_sdei_state_trans(se, DO_ROUTING)) { + ret = SDEI_EDENY; + goto finish; + } + + /* Choose appropriate routing */ + routing = (unsigned int) ((flags == SDEI_REGF_RM_ANY) ? + INTR_ROUTING_MODE_ANY : INTR_ROUTING_MODE_PE); + + /* Update event registration flag */ + se->reg_flags = (unsigned int) flags; + if (flags == SDEI_REGF_RM_PE) { + se->affinity = (mpidr & MPIDR_AFFINITY_MASK); + } + + /* + * ROUTING_SET is permissible only when event composite state is + * 'registered, disabled, and not running'. This means that the + * interrupt is currently disabled, and not active. + */ + plat_ic_set_spi_routing(map->intr, routing, (u_register_t) mpidr); + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Register handler and argument for an SDEI event */ +static int64_t sdei_event_register(int ev_num, + uint64_t ep, + uint64_t arg, + uint64_t flags, + uint64_t mpidr) +{ + int ret; + unsigned int routing; + sdei_entry_t *se; + sdei_ev_map_t *map; + sdei_state_t backup_state; + + if ((ep == 0U) || (plat_sdei_validate_entry_point( + ep, sdei_client_el()) != 0)) { + return SDEI_EINVAL; + } + + ret = validate_flags(flags, mpidr); + if (ret != 0) + return ret; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + /* Private events always target the PE */ + if (is_event_private(map)) { + /* + * SDEI internally handles private events in the same manner + * as public events with routing mode=RM_PE, since the routing + * mode flag and affinity fields are not used when registering + * a private event, set them here. + */ + flags = SDEI_REGF_RM_PE; + /* + * Kernel may pass 0 as mpidr, as we set flags to + * SDEI_REGF_RM_PE, so set mpidr also. + */ + mpidr = read_mpidr_el1(); + } + + se = get_event_entry(map); + + /* + * Even though register operation is per-event (additionally for private + * events, registration is required individually), it has to be + * serialised with respect to bind/release, which are global operations. + * So we hold the lock throughout, unconditionally. + */ + sdei_map_lock(map); + + backup_state = se->state; + if (!can_sdei_state_trans(se, DO_REGISTER)) + goto fallback; + + /* + * When registering for dynamic events, make sure it's been bound + * already. This has to be the case as, without binding, the client + * can't know about the event number to register for. + */ + if (is_map_dynamic(map) && !is_map_bound(map)) + goto fallback; + + if (is_event_private(map)) { + /* Multiple calls to register are possible for private events */ + assert(map->reg_count >= 0); + } else { + /* Only single call to register is possible for shared events */ + assert(map->reg_count == 0); + } + + if (is_map_bound(map)) { + /* Meanwhile, did any PE ACK the interrupt? */ + if (plat_ic_get_interrupt_active(map->intr) != 0U) + goto fallback; + + /* The interrupt must currently owned by Non-secure */ + if (plat_ic_get_interrupt_type(map->intr) != INTR_TYPE_NS) + goto fallback; + + /* + * Disable forwarding of new interrupt triggers to CPU + * interface. + */ + plat_ic_disable_interrupt(map->intr); + + /* + * Any events that are triggered after register and before + * enable should remain pending. Clear any previous interrupt + * triggers which are pending (except for SGIs). This has no + * affect on level-triggered interrupts. + */ + if (ev_num != SDEI_EVENT_0) + plat_ic_clear_interrupt_pending(map->intr); + + /* Map interrupt to EL3 and program the correct priority */ + plat_ic_set_interrupt_type(map->intr, INTR_TYPE_EL3); + + /* Program the appropriate interrupt priority */ + plat_ic_set_interrupt_priority(map->intr, sdei_event_priority(map)); + + /* + * Set the routing mode for shared event as requested. We + * already ensure that shared events get bound to SPIs. + */ + if (is_event_shared(map)) { + routing = (unsigned int) ((flags == SDEI_REGF_RM_ANY) ? + INTR_ROUTING_MODE_ANY : INTR_ROUTING_MODE_PE); + plat_ic_set_spi_routing(map->intr, routing, + (u_register_t) mpidr); + } + } + + /* Populate event entries */ + set_sdei_entry(se, ep, arg, (unsigned int) flags, mpidr); + + /* Increment register count */ + map->reg_count++; + + sdei_map_unlock(map); + + return 0; + +fallback: + /* Reinstate previous state */ + se->state = backup_state; + + sdei_map_unlock(map); + + return SDEI_EDENY; +} + +/* Enable SDEI event */ +static int64_t sdei_event_enable(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + int ret; + bool before, after; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + ret = SDEI_EDENY; + + if (is_event_shared(map)) + sdei_map_lock(map); + + before = GET_EV_STATE(se, ENABLED); + if (!can_sdei_state_trans(se, DO_ENABLE)) + goto finish; + after = GET_EV_STATE(se, ENABLED); + + /* + * Enable interrupt for bound events only if there's a change in enabled + * state. + */ + if (is_map_bound(map) && (!before && after)) + plat_ic_enable_interrupt(map->intr); + + ret = 0; + +finish: + if (is_event_shared(map)) + sdei_map_unlock(map); + + return ret; +} + +/* Disable SDEI event */ +static int sdei_event_disable(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + int ret; + bool before, after; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + ret = SDEI_EDENY; + + if (is_event_shared(map)) + sdei_map_lock(map); + + before = GET_EV_STATE(se, ENABLED); + if (!can_sdei_state_trans(se, DO_DISABLE)) + goto finish; + after = GET_EV_STATE(se, ENABLED); + + /* + * Disable interrupt for bound events only if there's a change in + * enabled state. + */ + if (is_map_bound(map) && (before && !after)) + plat_ic_disable_interrupt(map->intr); + + ret = 0; + +finish: + if (is_event_shared(map)) + sdei_map_unlock(map); + + return ret; +} + +/* Query SDEI event information */ +static int64_t sdei_event_get_info(int ev_num, int info) +{ + sdei_entry_t *se; + sdei_ev_map_t *map; + + uint64_t flags; + bool registered; + uint64_t affinity; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* Sample state under lock */ + registered = GET_EV_STATE(se, REGISTERED); + flags = se->reg_flags; + affinity = se->affinity; + + if (is_event_shared(map)) + sdei_map_unlock(map); + + switch (info) { + case SDEI_INFO_EV_TYPE: + return is_event_shared(map); + + case SDEI_INFO_EV_NOT_SIGNALED: + return !is_event_signalable(map); + + case SDEI_INFO_EV_PRIORITY: + return is_event_critical(map); + + case SDEI_INFO_EV_ROUTING_MODE: + if (!is_event_shared(map)) + return SDEI_EINVAL; + if (!registered) + return SDEI_EDENY; + return (flags == SDEI_REGF_RM_PE); + + case SDEI_INFO_EV_ROUTING_AFF: + if (!is_event_shared(map)) + return SDEI_EINVAL; + if (!registered) + return SDEI_EDENY; + if (flags != SDEI_REGF_RM_PE) + return SDEI_EINVAL; + return affinity; + + default: + return SDEI_EINVAL; + } +} + +/* Unregister an SDEI event */ +static int sdei_event_unregister(int ev_num) +{ + int ret = 0; + sdei_entry_t *se; + sdei_ev_map_t *map; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + /* + * Even though unregister operation is per-event (additionally for + * private events, unregistration is required individually), it has to + * be serialised with respect to bind/release, which are global + * operations. So we hold the lock throughout, unconditionally. + */ + sdei_map_lock(map); + + if (!can_sdei_state_trans(se, DO_UNREGISTER)) { + /* + * Even if the call is invalid, and the handler is running (for + * example, having unregistered from a running handler earlier), + * return pending error code; otherwise, return deny. + */ + ret = GET_EV_STATE(se, RUNNING) ? SDEI_EPEND : SDEI_EDENY; + + goto finish; + } + + map->reg_count--; + if (is_event_private(map)) { + /* Multiple calls to register are possible for private events */ + assert(map->reg_count >= 0); + } else { + /* Only single call to register is possible for shared events */ + assert(map->reg_count == 0); + } + + if (is_map_bound(map)) { + plat_ic_disable_interrupt(map->intr); + + /* + * Clear pending interrupt. Skip for SGIs as they may not be + * cleared on interrupt controllers. + */ + if (ev_num != SDEI_EVENT_0) + plat_ic_clear_interrupt_pending(map->intr); + + assert(plat_ic_get_interrupt_type(map->intr) == INTR_TYPE_EL3); + plat_ic_set_interrupt_type(map->intr, INTR_TYPE_NS); + plat_ic_set_interrupt_priority(map->intr, LOWEST_INTR_PRIORITY); + } + + clear_event_entries(se); + + /* + * If the handler is running at the time of unregister, return the + * pending error code. + */ + if (GET_EV_STATE(se, RUNNING)) + ret = SDEI_EPEND; + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Query status of an SDEI event */ +static int sdei_event_status(int ev_num) +{ + sdei_ev_map_t *map; + sdei_entry_t *se; + sdei_state_t state; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + se = get_event_entry(map); + + if (is_event_shared(map)) + sdei_map_lock(map); + + /* State value directly maps to the expected return format */ + state = se->state; + + if (is_event_shared(map)) + sdei_map_unlock(map); + + return (int) state; +} + +/* Bind an SDEI event to an interrupt */ +static int sdei_interrupt_bind(unsigned int intr_num) +{ + sdei_ev_map_t *map; + bool retry = true, shared_mapping; + + /* SGIs are not allowed to be bound */ + if (plat_ic_is_sgi(intr_num) != 0) + return SDEI_EINVAL; + + shared_mapping = (plat_ic_is_spi(intr_num) != 0); + do { + /* + * Bail out if there is already an event for this interrupt, + * either platform-defined or dynamic. + */ + map = find_event_map_by_intr(intr_num, shared_mapping); + if (map != NULL) { + if (is_map_dynamic(map)) { + if (is_map_bound(map)) { + /* + * Dynamic event, already bound. Return + * event number. + */ + return map->ev_num; + } + } else { + /* Binding non-dynamic event */ + return SDEI_EINVAL; + } + } + + /* + * The interrupt is not bound yet. Try to find a free slot to + * bind it. Free dynamic mappings have their interrupt set as + * SDEI_DYN_IRQ. + */ + map = find_event_map_by_intr(SDEI_DYN_IRQ, shared_mapping); + if (map == NULL) + return SDEI_ENOMEM; + + /* The returned mapping must be dynamic */ + assert(is_map_dynamic(map)); + + /* + * We cannot assert for bound maps here, as we might be racing + * with another bind. + */ + + /* The requested interrupt must already belong to NS */ + if (plat_ic_get_interrupt_type(intr_num) != INTR_TYPE_NS) + return SDEI_EDENY; + + /* + * Interrupt programming and ownership transfer are deferred + * until register. + */ + + sdei_map_lock(map); + if (!is_map_bound(map)) { + map->intr = intr_num; + set_map_bound(map); + retry = false; + } + sdei_map_unlock(map); + } while (retry); + + return map->ev_num; +} + +/* Release a bound SDEI event previously to an interrupt */ +static int sdei_interrupt_release(int ev_num) +{ + int ret = 0; + sdei_ev_map_t *map; + sdei_entry_t *se; + + /* Check if valid event number */ + map = find_event_map(ev_num); + if (map == NULL) + return SDEI_EINVAL; + + if (!is_map_dynamic(map)) + return SDEI_EINVAL; + + se = get_event_entry(map); + + sdei_map_lock(map); + + /* Event must have been unregistered before release */ + if (map->reg_count != 0) { + ret = SDEI_EDENY; + goto finish; + } + + /* + * Interrupt release never causes the state to change. We only check + * whether it's permissible or not. + */ + if (!can_sdei_state_trans(se, DO_RELEASE)) { + ret = SDEI_EDENY; + goto finish; + } + + if (is_map_bound(map)) { + /* + * Deny release if the interrupt is active, which means it's + * probably being acknowledged and handled elsewhere. + */ + if (plat_ic_get_interrupt_active(map->intr) != 0U) { + ret = SDEI_EDENY; + goto finish; + } + + /* + * Interrupt programming and ownership transfer are already done + * during unregister. + */ + + map->intr = SDEI_DYN_IRQ; + clr_map_bound(map); + } else { + SDEI_LOG("Error release bound:%d cnt:%d\n", is_map_bound(map), + map->reg_count); + ret = SDEI_EINVAL; + } + +finish: + sdei_map_unlock(map); + + return ret; +} + +/* Perform reset of private SDEI events */ +static int sdei_private_reset(void) +{ + sdei_ev_map_t *map; + int ret = 0, final_ret = 0; + unsigned int i; + + /* Unregister all private events */ + for_each_private_map(i, map) { + /* + * The unregister can fail if the event is not registered, which + * is allowed, and a deny will be returned. But if the event is + * running or unregister pending, the call fails. + */ + ret = sdei_event_unregister(map->ev_num); + if ((ret == SDEI_EPEND) && (final_ret == 0)) + final_ret = SDEI_EDENY; + } + + return final_ret; +} + +/* Perform reset of shared SDEI events */ +static int sdei_shared_reset(void) +{ + const sdei_mapping_t *mapping; + sdei_ev_map_t *map; + int ret = 0, final_ret = 0; + unsigned int i, j; + + /* Unregister all shared events */ + for_each_shared_map(i, map) { + /* + * The unregister can fail if the event is not registered, which + * is allowed, and a deny will be returned. But if the event is + * running or unregister pending, the call fails. + */ + ret = sdei_event_unregister(map->ev_num); + if ((ret == SDEI_EPEND) && (final_ret == 0)) + final_ret = SDEI_EDENY; + } + + if (final_ret != 0) + return final_ret; + + /* + * Loop through both private and shared mappings, and release all + * bindings. + */ + for_each_mapping_type(i, mapping) { + iterate_mapping(mapping, j, map) { + /* + * Release bindings for mappings that are dynamic and + * bound. + */ + if (is_map_dynamic(map) && is_map_bound(map)) { + /* + * Any failure to release would mean there is at + * least a PE registered for the event. + */ + ret = sdei_interrupt_release(map->ev_num); + if ((ret != 0) && (final_ret == 0)) + final_ret = ret; + } + } + } + + return final_ret; +} + +/* Send a signal to another SDEI client PE */ +static int sdei_signal(int ev_num, uint64_t target_pe) +{ + sdei_ev_map_t *map; + + /* Only event 0 can be signalled */ + if (ev_num != SDEI_EVENT_0) + return SDEI_EINVAL; + + /* Find mapping for event 0 */ + map = find_event_map(SDEI_EVENT_0); + if (map == NULL) + return SDEI_EINVAL; + + /* The event must be signalable */ + if (!is_event_signalable(map)) + return SDEI_EINVAL; + + /* Validate target */ + if (plat_core_pos_by_mpidr(target_pe) < 0) + return SDEI_EINVAL; + + /* Raise SGI. Platform will validate target_pe */ + plat_ic_raise_el3_sgi((int) map->intr, (u_register_t) target_pe); + + return 0; +} + +/* Query SDEI dispatcher features */ +static uint64_t sdei_features(unsigned int feature) +{ + if (feature == SDEI_FEATURE_BIND_SLOTS) { + return FEATURE_BIND_SLOTS(num_dyn_priv_slots, + num_dyn_shrd_slots); + } + + return (uint64_t) SDEI_EINVAL; +} + +/* SDEI top level handler for servicing SMCs */ +uint64_t sdei_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) +{ + + uint64_t x5; + unsigned int ss = (unsigned int) get_interrupt_src_ss(flags); + int64_t ret; + bool resume = false; + cpu_context_t *ctx = handle; + int ev_num = (int) x1; + + if (ss != NON_SECURE) + SMC_RET1(ctx, SMC_UNK); + + /* Verify the caller EL */ + if (GET_EL(read_spsr_el3()) != sdei_client_el()) + SMC_RET1(ctx, SMC_UNK); + + switch (smc_fid) { + case SDEI_VERSION: + SDEI_LOG("> VER\n"); + ret = (int64_t) sdei_version(); + SDEI_LOG("< VER:%" PRIx64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_REGISTER: + x5 = SMC_GET_GP(ctx, CTX_GPREG_X5); + SDEI_LOG("> REG(n:%d e:%" PRIx64 " a:%" PRIx64 " f:%x m:%" PRIx64 "\n", ev_num, + x2, x3, (int) x4, x5); + ret = sdei_event_register(ev_num, x2, x3, x4, x5); + SDEI_LOG("< REG:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_ENABLE: + SDEI_LOG("> ENABLE(n:%d)\n", (int) x1); + ret = sdei_event_enable(ev_num); + SDEI_LOG("< ENABLE:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_DISABLE: + SDEI_LOG("> DISABLE(n:0x%x)\n", ev_num); + ret = sdei_event_disable(ev_num); + SDEI_LOG("< DISABLE:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_CONTEXT: + SDEI_LOG("> CTX(p:%d):%lx\n", (int) x1, read_mpidr_el1()); + ret = sdei_event_context(ctx, (unsigned int) x1); + SDEI_LOG("< CTX:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_COMPLETE_AND_RESUME: + resume = true; + /* Fallthrough */ + + case SDEI_EVENT_COMPLETE: + SDEI_LOG("> COMPLETE(r:%u sta/ep:%" PRIx64 "):%lx\n", + (unsigned int) resume, x1, read_mpidr_el1()); + ret = sdei_event_complete(resume, x1); + SDEI_LOG("< COMPLETE:%" PRIx64 "\n", ret); + + /* + * Set error code only if the call failed. If the call + * succeeded, we discard the dispatched context, and restore the + * interrupted context to a pristine condition, and therefore + * shouldn't be modified. We don't return to the caller in this + * case anyway. + */ + if (ret != 0) + SMC_RET1(ctx, ret); + + SMC_RET0(ctx); + + case SDEI_EVENT_STATUS: + SDEI_LOG("> STAT(n:0x%x)\n", ev_num); + ret = sdei_event_status(ev_num); + SDEI_LOG("< STAT:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_GET_INFO: + SDEI_LOG("> INFO(n:0x%x, %d)\n", ev_num, (int) x2); + ret = sdei_event_get_info(ev_num, (int) x2); + SDEI_LOG("< INFO:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_UNREGISTER: + SDEI_LOG("> UNREG(n:0x%x)\n", ev_num); + ret = sdei_event_unregister(ev_num); + SDEI_LOG("< UNREG:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_PE_UNMASK: + SDEI_LOG("> UNMASK:%lx\n", read_mpidr_el1()); + sdei_pe_unmask(); + SDEI_LOG("< UNMASK:%d\n", 0); + SMC_RET1(ctx, 0); + + case SDEI_PE_MASK: + SDEI_LOG("> MASK:%lx\n", read_mpidr_el1()); + ret = sdei_pe_mask(); + SDEI_LOG("< MASK:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_INTERRUPT_BIND: + SDEI_LOG("> BIND(%d)\n", (int) x1); + ret = sdei_interrupt_bind((unsigned int) x1); + SDEI_LOG("< BIND:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_INTERRUPT_RELEASE: + SDEI_LOG("> REL(0x%x)\n", ev_num); + ret = sdei_interrupt_release(ev_num); + SDEI_LOG("< REL:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_SHARED_RESET: + SDEI_LOG("> S_RESET():%lx\n", read_mpidr_el1()); + ret = sdei_shared_reset(); + SDEI_LOG("< S_RESET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_PRIVATE_RESET: + SDEI_LOG("> P_RESET():%lx\n", read_mpidr_el1()); + ret = sdei_private_reset(); + SDEI_LOG("< P_RESET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_ROUTING_SET: + SDEI_LOG("> ROUTE_SET(n:%d f:%" PRIx64 " aff:%" PRIx64 ")\n", ev_num, x2, x3); + ret = sdei_event_routing_set(ev_num, x2, x3); + SDEI_LOG("< ROUTE_SET:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_FEATURES: + SDEI_LOG("> FTRS(f:%" PRIx64 ")\n", x1); + ret = (int64_t) sdei_features((unsigned int) x1); + SDEI_LOG("< FTRS:%" PRIx64 "\n", ret); + SMC_RET1(ctx, ret); + + case SDEI_EVENT_SIGNAL: + SDEI_LOG("> SIGNAL(e:%d t:%" PRIx64 ")\n", ev_num, x2); + ret = sdei_signal(ev_num, x2); + SDEI_LOG("< SIGNAL:%" PRId64 "\n", ret); + SMC_RET1(ctx, ret); + + default: + /* Do nothing in default case */ + break; + } + + WARN("Unimplemented SDEI Call: 0x%x\n", smc_fid); + SMC_RET1(ctx, SMC_UNK); +} + +/* Subscribe to PSCI CPU on to initialize per-CPU SDEI configuration */ +SUBSCRIBE_TO_EVENT(psci_cpu_on_finish, sdei_cpu_on_init); + +/* Subscribe to PSCI CPU suspend finisher for per-CPU configuration */ +SUBSCRIBE_TO_EVENT(psci_suspend_pwrdown_finish, sdei_cpu_wakeup_init); diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h b/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h new file mode 100644 index 0000000..44a7301 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_private.h @@ -0,0 +1,248 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SDEI_PRIVATE_H +#define SDEI_PRIVATE_H + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#ifndef __aarch64__ +# error SDEI is implemented only for AArch64 systems +#endif + +#ifndef PLAT_SDEI_CRITICAL_PRI +# error Platform must define SDEI critical priority value +#endif + +#ifndef PLAT_SDEI_NORMAL_PRI +# error Platform must define SDEI normal priority value +#endif + +/* Output SDEI logs as verbose */ +#define SDEI_LOG(...) VERBOSE("SDEI: " __VA_ARGS__) + +/* SDEI handler unregistered state. This is the default state. */ +#define SDEI_STATE_UNREGISTERED 0U + +/* SDE event status values in bit position */ +#define SDEI_STATF_REGISTERED 0U +#define SDEI_STATF_ENABLED 1U +#define SDEI_STATF_RUNNING 2U + +/* SDEI SMC error codes */ +#define SDEI_EINVAL (-2) +#define SDEI_EDENY (-3) +#define SDEI_EPEND (-5) +#define SDEI_ENOMEM (-10) + +/* + * 'info' parameter to SDEI_EVENT_GET_INFO SMC. + * + * Note that the SDEI v1.0 specification mistakenly enumerates the + * SDEI_INFO_EV_SIGNALED as SDEI_INFO_SIGNALED. This will be corrected in a + * future version. + */ +#define SDEI_INFO_EV_TYPE 0 +#define SDEI_INFO_EV_NOT_SIGNALED 1 +#define SDEI_INFO_EV_PRIORITY 2 +#define SDEI_INFO_EV_ROUTING_MODE 3 +#define SDEI_INFO_EV_ROUTING_AFF 4 + +#define SDEI_PRIVATE_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_PRIV_]) +#define SDEI_SHARED_MAPPING() (&sdei_global_mappings[SDEI_MAP_IDX_SHRD_]) + +#define for_each_mapping_type(_i, _mapping) \ + for ((_i) = 0, (_mapping) = &sdei_global_mappings[(_i)]; \ + (_i) < SDEI_MAP_IDX_MAX_; \ + (_i)++, (_mapping) = &sdei_global_mappings[(_i)]) + +#define iterate_mapping(_mapping, _i, _map) \ + for ((_map) = (_mapping)->map, (_i) = 0; \ + (_i) < (_mapping)->num_maps; \ + (_i)++, (_map)++) + +#define for_each_private_map(_i, _map) \ + iterate_mapping(SDEI_PRIVATE_MAPPING(), _i, _map) + +#define for_each_shared_map(_i, _map) \ + iterate_mapping(SDEI_SHARED_MAPPING(), _i, _map) + +/* SDEI_FEATURES */ +#define SDEI_FEATURE_BIND_SLOTS 0U +#define BIND_SLOTS_MASK 0xffffU +#define FEATURES_SHARED_SLOTS_SHIFT 16U +#define FEATURES_PRIVATE_SLOTS_SHIFT 0U +#define FEATURE_BIND_SLOTS(_priv, _shrd) \ + (((((uint64_t) (_priv)) & BIND_SLOTS_MASK) << FEATURES_PRIVATE_SLOTS_SHIFT) | \ + ((((uint64_t) (_shrd)) & BIND_SLOTS_MASK) << FEATURES_SHARED_SLOTS_SHIFT)) + +#define GET_EV_STATE(_e, _s) get_ev_state_bit(_e, SDEI_STATF_##_s) +#define SET_EV_STATE(_e, _s) clr_ev_state_bit(_e->state, SDEI_STATF_##_s) + +static inline bool is_event_private(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_PRIVATE_SHIFT_)) != 0U); +} + +static inline bool is_event_shared(sdei_ev_map_t *map) +{ + return !is_event_private(map); +} + +static inline bool is_event_critical(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_CRITICAL_SHIFT_)) != 0U); +} + +static inline bool is_event_normal(sdei_ev_map_t *map) +{ + return !is_event_critical(map); +} + +static inline bool is_event_signalable(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_SIGNALABLE_SHIFT_)) != 0U); +} + +static inline bool is_map_dynamic(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_DYNAMIC_SHIFT_)) != 0U); +} + +/* + * Checks whether an event is associated with an interrupt. Static events always + * return true, and dynamic events return whether SDEI_INTERRUPT_BIND had been + * called on them. This can be used on both static or dynamic events to check + * for an associated interrupt. + */ +static inline bool is_map_bound(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_BOUND_SHIFT_)) != 0U); +} + +static inline void set_map_bound(sdei_ev_map_t *map) +{ + map->map_flags |= BIT_32(SDEI_MAPF_BOUND_SHIFT_); +} + +static inline bool is_map_explicit(sdei_ev_map_t *map) +{ + return ((map->map_flags & BIT_32(SDEI_MAPF_EXPLICIT_SHIFT_)) != 0U); +} + +static inline void clr_map_bound(sdei_ev_map_t *map) +{ + map->map_flags &= ~BIT_32(SDEI_MAPF_BOUND_SHIFT_); +} + +static inline bool is_secure_sgi(unsigned int intr) +{ + return ((plat_ic_is_sgi(intr) != 0) && + (plat_ic_get_interrupt_type(intr) == INTR_TYPE_EL3)); +} + +/* + * Determine EL of the client. If EL2 is implemented (hence the enabled HCE + * bit), deem EL2; otherwise, deem EL1. + */ +static inline unsigned int sdei_client_el(void) +{ + cpu_context_t *ns_ctx = cm_get_context(NON_SECURE); + el3_state_t *el3_ctx = get_el3state_ctx(ns_ctx); + + return ((read_ctx_reg(el3_ctx, CTX_SCR_EL3) & SCR_HCE_BIT) != 0U) ? + MODE_EL2 : MODE_EL1; +} + +static inline unsigned int sdei_event_priority(sdei_ev_map_t *map) +{ + return (unsigned int) (is_event_critical(map) ? PLAT_SDEI_CRITICAL_PRI : + PLAT_SDEI_NORMAL_PRI); +} + +static inline bool get_ev_state_bit(sdei_entry_t *se, unsigned int bit_no) +{ + return ((se->state & BIT_32(bit_no)) != 0U); +} + +static inline void clr_ev_state_bit(sdei_entry_t *se, unsigned int bit_no) +{ + se->state &= ~BIT_32(bit_no); +} + +/* SDEI actions for state transition */ +typedef enum { + /* + * Actions resulting from client requests. These directly map to SMC + * calls. Note that the state table columns are listed in this order + * too. + */ + DO_REGISTER = 0, + DO_RELEASE = 1, + DO_ENABLE = 2, + DO_DISABLE = 3, + DO_UNREGISTER = 4, + DO_ROUTING = 5, + DO_CONTEXT = 6, + DO_COMPLETE = 7, + DO_COMPLETE_RESUME = 8, + + /* Action for event dispatch */ + DO_DISPATCH = 9, + + DO_MAX, +} sdei_action_t; + +typedef enum { + SDEI_NORMAL, + SDEI_CRITICAL +} sdei_class_t; + +static inline void sdei_map_lock(sdei_ev_map_t *map) +{ + spin_lock(&map->lock); +} + +static inline void sdei_map_unlock(sdei_ev_map_t *map) +{ + spin_unlock(&map->lock); +} + +extern const sdei_mapping_t sdei_global_mappings[]; +extern sdei_entry_t sdei_private_event_table[]; +extern sdei_entry_t sdei_shared_event_table[]; + +void init_sdei_state(void); + +sdei_ev_map_t *find_event_map_by_intr(unsigned int intr_num, bool shared); +sdei_ev_map_t *find_event_map(int ev_num); +sdei_entry_t *get_event_entry(sdei_ev_map_t *map); + +int64_t sdei_event_context(void *handle, unsigned int param); +int sdei_event_complete(bool resume, uint64_t pc); + +void sdei_pe_unmask(void); +int64_t sdei_pe_mask(void); + +int sdei_intr_handler(uint32_t intr_raw, uint32_t flags, void *handle, + void *cookie); +bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act); +void begin_sdei_synchronous_dispatch(jmp_buf *buffer); + +#endif /* SDEI_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c b/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c new file mode 100644 index 0000000..1b448e6 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/sdei/sdei_state.c @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include + +#include "sdei_private.h" + +/* Aliases for SDEI handler states: 'R'unning, 'E'nabled, and re'G'istered */ +#define r_ 0U +#define R_ (1u << SDEI_STATF_RUNNING) + +#define e_ 0U +#define E_ (1u << SDEI_STATF_ENABLED) + +#define g_ 0U +#define G_ (1u << SDEI_STATF_REGISTERED) + +/* All possible composite handler states */ +#define reg_ (r_ | e_ | g_) +#define reG_ (r_ | e_ | G_) +#define rEg_ (r_ | E_ | g_) +#define rEG_ (r_ | E_ | G_) +#define Reg_ (R_ | e_ | g_) +#define ReG_ (R_ | e_ | G_) +#define REg_ (R_ | E_ | g_) +#define REG_ (R_ | E_ | G_) + +#define MAX_STATES (REG_ + 1u) + +/* Invalid state */ +#define SDEI_STATE_INVALID ((sdei_state_t) (-1)) + +/* No change in state */ +#define SDEI_STATE_NOP ((sdei_state_t) (-2)) + +#define X___ SDEI_STATE_INVALID +#define NOP_ SDEI_STATE_NOP + +/* Ensure special states don't overlap with valid ones */ +CASSERT(X___ > REG_, sdei_state_overlap_invalid); +CASSERT(NOP_ > REG_, sdei_state_overlap_nop); + +/* + * SDEI handler state machine: refer to sections 6.1 and 6.1.2 of the SDEI v1.0 + * specification (ARM DEN0054A). + * + * Not all calls contribute to handler state transition. This table is also used + * to validate whether a call is permissible at a given handler state: + * + * - X___ denotes a forbidden transition; + * - NOP_ denotes a permitted transition, but there's no change in state; + * - Otherwise, XXX_ gives the new state. + * + * DISP[atch] is a transition added for the implementation, but is not mentioned + * in the spec. + * + * Those calls that the spec mentions as can be made any time don't picture in + * this table. + */ + +static const sdei_state_t sdei_state_table[MAX_STATES][DO_MAX] = { +/* + * Action: REG REL ENA DISA UREG ROUT CTX COMP COMPR DISP + * Notes: [3] [1] [3] [3][4] [2] + */ + /* Handler unregistered, disabled, and not running. This is the default state. */ +/* 0 */ [reg_] = { reG_, NOP_, X___, X___, X___, X___, X___, X___, X___, X___, }, + + /* Handler unregistered and running */ +/* 4 */ [Reg_] = { X___, X___, X___, X___, X___, X___, NOP_, reg_, reg_, X___, }, + + /* Handler registered */ +/* 1 */ [reG_] = { X___, X___, rEG_, NOP_, reg_, NOP_, X___, X___, X___, X___, }, + + /* Handler registered and running */ +/* 5 */ [ReG_] = { X___, X___, REG_, NOP_, Reg_, X___, NOP_, reG_, reG_, X___, }, + + /* Handler registered and enabled */ +/* 3 */ [rEG_] = { X___, X___, NOP_, reG_, reg_, X___, X___, X___, X___, REG_, }, + + /* Handler registered, enabled, and running */ +/* 7 */ [REG_] = { X___, X___, NOP_, ReG_, Reg_, X___, NOP_, rEG_, rEG_, X___, }, + + /* + * Invalid states: no valid transition would leave the handler in these + * states; and no transition from these states is possible either. + */ + + /* + * Handler can't be enabled without being registered. I.e., XEg is + * impossible. + */ +/* 2 */ [rEg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, +/* 6 */ [REg_] = { X___, X___, X___, X___, X___, X___, X___, X___, X___, X___, }, +}; + +/* + * [1] Unregister will always also disable the event, so the new state will have + * Xeg. + * [2] Event is considered for dispatch only when it's both registered and + * enabled. + * [3] Never causes change in state. + * [4] Only allowed when running. + */ + +/* + * Given an action, transition the state of an event by looking up the state + * table above: + * + * - Return false for invalid transition; + * - Return true for valid transition that causes no change in state; + * - Otherwise, update state and return true. + * + * This function assumes that the caller holds necessary locks. If the + * transition has constrains other than the state table describes, the caller is + * expected to restore the previous state. See sdei_event_register() for + * example. + */ +bool can_sdei_state_trans(sdei_entry_t *se, sdei_action_t act) +{ + sdei_state_t next; + + assert(act < DO_MAX); + if (se->state >= MAX_STATES) { + WARN(" event state invalid: %x\n", se->state); + return false; + } + + next = sdei_state_table[se->state][act]; + switch (next) { + case SDEI_STATE_INVALID: + return false; + + case SDEI_STATE_NOP: + return true; + + default: + /* Valid transition. Update state. */ + SDEI_LOG(" event state 0x%x => 0x%x\n", se->state, next); + se->state = next; + + return true; + } +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S new file mode 100644 index 0000000..2c3aaf7 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "../spm_mm_private.h" + + .global spm_secure_partition_enter + .global spm_secure_partition_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func spm_secure_partition_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #SP_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #SP_C_RT_CTX_X19] + stp x21, x22, [sp, #SP_C_RT_CTX_X21] + stp x23, x24, [sp, #SP_C_RT_CTX_X23] + stp x25, x26, [sp, #SP_C_RT_CTX_X25] + stp x27, x28, [sp, #SP_C_RT_CTX_X27] + stp x29, x30, [sp, #SP_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc spm_secure_partition_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context + * saved in spm_secure_partition_enter(). + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func spm_secure_partition_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(SP_C_RT_CTX_X19 - SP_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(SP_C_RT_CTX_X21 - SP_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(SP_C_RT_CTX_X23 - SP_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(SP_C_RT_CTX_X25 - SP_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(SP_C_RT_CTX_X27 - SP_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(SP_C_RT_CTX_X29 - SP_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last spm_secure_partition_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc spm_secure_partition_exit diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S new file mode 100644 index 0000000..be4084c --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S @@ -0,0 +1,128 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +/* ----------------------------------------------------------------------------- + * Very simple stackless exception handlers used by the spm shim layer. + * ----------------------------------------------------------------------------- + */ + .globl spm_shim_exceptions_ptr + +vector_base spm_shim_exceptions_ptr, .spm_shim_exceptions + + /* ----------------------------------------------------- + * Current EL with SP0 : 0x0 - 0x200 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSP0, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionSP0 + +vector_entry IrqSP0, .spm_shim_exceptions + b . +end_vector_entry IrqSP0 + +vector_entry FiqSP0, .spm_shim_exceptions + b . +end_vector_entry FiqSP0 + +vector_entry SErrorSP0, .spm_shim_exceptions + b . +end_vector_entry SErrorSP0 + + /* ----------------------------------------------------- + * Current EL with SPx: 0x200 - 0x400 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionSPx, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionSPx + +vector_entry IrqSPx, .spm_shim_exceptions + b . +end_vector_entry IrqSPx + +vector_entry FiqSPx, .spm_shim_exceptions + b . +end_vector_entry FiqSPx + +vector_entry SErrorSPx, .spm_shim_exceptions + b . +end_vector_entry SErrorSPx + + /* ----------------------------------------------------- + * Lower EL using AArch64 : 0x400 - 0x600. No exceptions + * are handled since secure_partition does not implement + * a lower EL + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA64, .spm_shim_exceptions + msr tpidr_el1, x30 + mrs x30, esr_el1 + ubfx x30, x30, #ESR_EC_SHIFT, #ESR_EC_LENGTH + + cmp x30, #EC_AARCH64_SVC + b.eq do_smc + + cmp x30, #EC_AARCH32_SVC + b.eq do_smc + + cmp x30, #EC_AARCH64_SYS + b.eq handle_sys_trap + + /* Fail in all the other cases */ + b panic + + /* --------------------------------------------- + * Tell SPM that we are done initialising + * --------------------------------------------- + */ +do_smc: + mrs x30, tpidr_el1 + smc #0 + exception_return + + /* AArch64 system instructions trap are handled as a panic for now */ +handle_sys_trap: +panic: + b panic +end_vector_entry SynchronousExceptionA64 + +vector_entry IrqA64, .spm_shim_exceptions + b . +end_vector_entry IrqA64 + +vector_entry FiqA64, .spm_shim_exceptions + b . +end_vector_entry FiqA64 + +vector_entry SErrorA64, .spm_shim_exceptions + b . +end_vector_entry SErrorA64 + + /* ----------------------------------------------------- + * Lower EL using AArch32 : 0x600 - 0x800 + * ----------------------------------------------------- + */ +vector_entry SynchronousExceptionA32, .spm_shim_exceptions + b . +end_vector_entry SynchronousExceptionA32 + +vector_entry IrqA32, .spm_shim_exceptions + b . +end_vector_entry IrqA32 + +vector_entry FiqA32, .spm_shim_exceptions + b . +end_vector_entry FiqA32 + +vector_entry SErrorA32, .spm_shim_exceptions + b . +end_vector_entry SErrorA32 diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk new file mode 100644 index 0000000..a87bdd8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm.mk @@ -0,0 +1,32 @@ +# +# Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${SPD},none) + $(error "Error: SPD and SPM_MM are incompatible build options.") +endif +ifneq (${ARCH},aarch64) + $(error "Error: SPM_MM is only supported on aarch64.") +endif +ifeq (${ENABLE_SVE_FOR_NS},1) + $(error "Error: SPM_MM is not compatible with ENABLE_SVE_FOR_NS") +endif +ifeq (${ENABLE_SME_FOR_NS},1) + $(error "Error: SPM_MM is not compatible with ENABLE_SME_FOR_NS") +endif + +SPM_SOURCES := $(addprefix services/std_svc/spm_mm/, \ + ${ARCH}/spm_mm_helpers.S \ + ${ARCH}/spm_mm_shim_exceptions.S \ + spm_mm_main.c \ + spm_mm_setup.c \ + spm_mm_xlat.c) + + +# Let the top-level Makefile know that we intend to include a BL32 image +NEED_BL32 := yes + +# required so that SPM code executing at S-EL0 can access the timer registers +NS_TIMER_SWITCH := 1 diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c new file mode 100644 index 0000000..14c0038 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c @@ -0,0 +1,353 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_mm_private.h" + +/******************************************************************************* + * Secure Partition context information. + ******************************************************************************/ +static sp_context_t sp_ctx; + +/******************************************************************************* + * Set state of a Secure Partition context. + ******************************************************************************/ +void sp_state_set(sp_context_t *sp_ptr, sp_state_t state) +{ + spin_lock(&(sp_ptr->state_lock)); + sp_ptr->state = state; + spin_unlock(&(sp_ptr->state_lock)); +} + +/******************************************************************************* + * Wait until the state of a Secure Partition is the specified one and change it + * to the desired state. + ******************************************************************************/ +void sp_state_wait_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) +{ + int success = 0; + + while (success == 0) { + spin_lock(&(sp_ptr->state_lock)); + + if (sp_ptr->state == from) { + sp_ptr->state = to; + + success = 1; + } + + spin_unlock(&(sp_ptr->state_lock)); + } +} + +/******************************************************************************* + * Check if the state of a Secure Partition is the specified one and, if so, + * change it to the desired state. Returns 0 on success, -1 on error. + ******************************************************************************/ +int sp_state_try_switch(sp_context_t *sp_ptr, sp_state_t from, sp_state_t to) +{ + int ret = -1; + + spin_lock(&(sp_ptr->state_lock)); + + if (sp_ptr->state == from) { + sp_ptr->state = to; + + ret = 0; + } + + spin_unlock(&(sp_ptr->state_lock)); + + return ret; +} + +/******************************************************************************* + * This function takes an SP context pointer and performs a synchronous entry + * into it. + ******************************************************************************/ +static uint64_t spm_sp_synchronous_entry(sp_context_t *ctx) +{ + uint64_t rc; + + assert(ctx != NULL); + + /* Assign the context of the SP to this CPU */ + cm_set_context(&(ctx->cpu_ctx), SECURE); + + /* Restore the context assigned above */ + cm_el1_sysregs_context_restore(SECURE); + cm_set_next_eret_context(SECURE); + + /* Invalidate TLBs at EL1. */ + tlbivmalle1(); + dsbish(); + + /* Enter Secure Partition */ + rc = spm_secure_partition_enter(&ctx->c_rt_ctx); + + /* Save secure state */ + cm_el1_sysregs_context_save(SECURE); + + return rc; +} + +/******************************************************************************* + * This function returns to the place where spm_sp_synchronous_entry() was + * called originally. + ******************************************************************************/ +__dead2 static void spm_sp_synchronous_exit(uint64_t rc) +{ + sp_context_t *ctx = &sp_ctx; + + /* + * The SPM must have initiated the original request through a + * synchronous entry into the secure partition. Jump back to the + * original C runtime context with the value of rc in x0; + */ + spm_secure_partition_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +/******************************************************************************* + * Jump to each Secure Partition for the first time. + ******************************************************************************/ +static int32_t spm_init(void) +{ + uint64_t rc; + sp_context_t *ctx; + + INFO("Secure Partition init...\n"); + + ctx = &sp_ctx; + + ctx->state = SP_STATE_RESET; + + rc = spm_sp_synchronous_entry(ctx); + assert(rc == 0); + + ctx->state = SP_STATE_IDLE; + + INFO("Secure Partition initialized.\n"); + + return !rc; +} + +/******************************************************************************* + * Initialize contexts of all Secure Partitions. + ******************************************************************************/ +int32_t spm_mm_setup(void) +{ + sp_context_t *ctx; + + /* Disable MMU at EL1 (initialized by BL2) */ + disable_mmu_icache_el1(); + + /* Initialize context of the SP */ + INFO("Secure Partition context setup start...\n"); + + ctx = &sp_ctx; + + /* Assign translation tables context. */ + ctx->xlat_ctx_handle = spm_get_sp_xlat_context(); + + spm_sp_setup(ctx); + + /* Register init function for deferred init. */ + bl31_register_bl32_init(&spm_init); + + INFO("Secure Partition setup done.\n"); + + return 0; +} + +/******************************************************************************* + * Function to perform a call to a Secure Partition. + ******************************************************************************/ +uint64_t spm_mm_sp_call(uint32_t smc_fid, uint64_t x1, uint64_t x2, uint64_t x3) +{ + uint64_t rc; + sp_context_t *sp_ptr = &sp_ctx; + + /* Wait until the Secure Partition is idle and set it to busy. */ + sp_state_wait_switch(sp_ptr, SP_STATE_IDLE, SP_STATE_BUSY); + + /* Set values for registers on SP entry */ + cpu_context_t *cpu_ctx = &(sp_ptr->cpu_ctx); + + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X0, smc_fid); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X1, x1); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X2, x2); + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X3, x3); + + /* Jump to the Secure Partition. */ + rc = spm_sp_synchronous_entry(sp_ptr); + + /* Flag Secure Partition as idle. */ + assert(sp_ptr->state == SP_STATE_BUSY); + sp_state_set(sp_ptr, SP_STATE_IDLE); + + return rc; +} + +/******************************************************************************* + * MM_COMMUNICATE handler + ******************************************************************************/ +static uint64_t mm_communicate(uint32_t smc_fid, uint64_t mm_cookie, + uint64_t comm_buffer_address, + uint64_t comm_size_address, void *handle) +{ + uint64_t rc; + + /* Cookie. Reserved for future use. It must be zero. */ + if (mm_cookie != 0U) { + ERROR("MM_COMMUNICATE: cookie is not zero\n"); + SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); + } + + if (comm_buffer_address == 0U) { + ERROR("MM_COMMUNICATE: comm_buffer_address is zero\n"); + SMC_RET1(handle, SPM_MM_INVALID_PARAMETER); + } + + if (comm_size_address != 0U) { + VERBOSE("MM_COMMUNICATE: comm_size_address is not 0 as recommended.\n"); + } + + /* + * The current secure partition design mandates + * - at any point, only a single core can be + * executing in the secure partiton. + * - a core cannot be preempted by an interrupt + * while executing in secure partition. + * Raise the running priority of the core to the + * interrupt level configured for secure partition + * so as to block any interrupt from preempting this + * core. + */ + ehf_activate_priority(PLAT_SP_PRI); + + /* Save the Normal world context */ + cm_el1_sysregs_context_save(NON_SECURE); + + rc = spm_mm_sp_call(smc_fid, comm_buffer_address, comm_size_address, + plat_my_core_pos()); + + /* Restore non-secure state */ + cm_el1_sysregs_context_restore(NON_SECURE); + cm_set_next_eret_context(NON_SECURE); + + /* + * Exited from secure partition. This core can take + * interrupts now. + */ + ehf_deactivate_priority(PLAT_SP_PRI); + + SMC_RET1(handle, rc); +} + +/******************************************************************************* + * Secure Partition Manager SMC handler. + ******************************************************************************/ +uint64_t spm_mm_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) +{ + unsigned int ns; + + /* Determine which security state this SMC originated from */ + ns = is_caller_non_secure(flags); + + if (ns == SMC_FROM_SECURE) { + + /* Handle SMCs from Secure world. */ + + assert(handle == cm_get_context(SECURE)); + + /* Make next ERET jump to S-EL0 instead of S-EL1. */ + cm_set_elr_spsr_el3(SECURE, read_elr_el1(), read_spsr_el1()); + + switch (smc_fid) { + + case SPM_MM_VERSION_AARCH32: + SMC_RET1(handle, SPM_MM_VERSION_COMPILED); + + case MM_SP_EVENT_COMPLETE_AARCH64: + spm_sp_synchronous_exit(x1); + + case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: + INFO("Received MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 SMC\n"); + + if (sp_ctx.state != SP_STATE_RESET) { + WARN("MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64 is available at boot time only\n"); + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + } + SMC_RET1(handle, + spm_memory_attributes_get_smc_handler( + &sp_ctx, x1)); + + case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: + INFO("Received MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 SMC\n"); + + if (sp_ctx.state != SP_STATE_RESET) { + WARN("MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64 is available at boot time only\n"); + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + } + SMC_RET1(handle, + spm_memory_attributes_set_smc_handler( + &sp_ctx, x1, x2, x3)); + default: + break; + } + } else { + + /* Handle SMCs from Non-secure world. */ + + assert(handle == cm_get_context(NON_SECURE)); + + switch (smc_fid) { + + case MM_VERSION_AARCH32: + SMC_RET1(handle, MM_VERSION_COMPILED); + + case MM_COMMUNICATE_AARCH32: + case MM_COMMUNICATE_AARCH64: + return mm_communicate(smc_fid, x1, x2, x3, handle); + + case MM_SP_MEMORY_ATTRIBUTES_GET_AARCH64: + case MM_SP_MEMORY_ATTRIBUTES_SET_AARCH64: + /* SMC interfaces reserved for secure callers. */ + SMC_RET1(handle, SPM_MM_NOT_SUPPORTED); + + default: + break; + } + } + + SMC_RET1(handle, SMC_UNK); +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h new file mode 100644 index 0000000..45b4789 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_PRIVATE_H +#define SPM_MM_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define SP_C_RT_CTX_X19 0x0 +#define SP_C_RT_CTX_X20 0x8 +#define SP_C_RT_CTX_X21 0x10 +#define SP_C_RT_CTX_X22 0x18 +#define SP_C_RT_CTX_X23 0x20 +#define SP_C_RT_CTX_X24 0x28 +#define SP_C_RT_CTX_X25 0x30 +#define SP_C_RT_CTX_X26 0x38 +#define SP_C_RT_CTX_X27 0x40 +#define SP_C_RT_CTX_X28 0x48 +#define SP_C_RT_CTX_X29 0x50 +#define SP_C_RT_CTX_X30 0x58 + +#define SP_C_RT_CTX_SIZE 0x60 +#define SP_C_RT_CTX_ENTRIES (SP_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ + +#include + +#include +#include + +typedef enum sp_state { + SP_STATE_RESET = 0, + SP_STATE_IDLE, + SP_STATE_BUSY +} sp_state_t; + +typedef struct sp_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + xlat_ctx_t *xlat_ctx_handle; + + sp_state_t state; + spinlock_t state_lock; +} sp_context_t; + +/* Assembly helpers */ +uint64_t spm_secure_partition_enter(uint64_t *c_rt_ctx); +void __dead2 spm_secure_partition_exit(uint64_t c_rt_ctx, uint64_t ret); + +void spm_sp_setup(sp_context_t *sp_ctx); + +xlat_ctx_t *spm_get_sp_xlat_context(void); + +int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, + uintptr_t base_va); +int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, + u_register_t page_address, + u_register_t pages_count, + u_register_t smc_attributes); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPM_MM_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c new file mode 100644 index 0000000..9d681c2 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c @@ -0,0 +1,259 @@ +/* + * Copyright (c) 2017-2020, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2021, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_mm_private.h" +#include "spm_mm_shim_private.h" + +/* Setup context of the Secure Partition */ +void spm_sp_setup(sp_context_t *sp_ctx) +{ + cpu_context_t *ctx = &(sp_ctx->cpu_ctx); + + /* Pointer to the MP information from the platform port. */ + const spm_mm_boot_info_t *sp_boot_info = + plat_get_secure_partition_boot_info(NULL); + + /* + * Initialize CPU context + * ---------------------- + */ + + entry_point_info_t ep_info = {0}; + + SET_PARAM_HEAD(&ep_info, PARAM_EP, VERSION_1, SECURE | EP_ST_ENABLE); + + /* Setup entrypoint and SPSR */ + ep_info.pc = sp_boot_info->sp_image_base; + ep_info.spsr = SPSR_64(MODE_EL0, MODE_SP_EL0, DISABLE_ALL_EXCEPTIONS); + + /* + * X0: Virtual address of a buffer shared between EL3 and Secure EL0. + * The buffer will be mapped in the Secure EL1 translation regime + * with Normal IS WBWA attributes and RO data and Execute Never + * instruction access permissions. + * + * X1: Size of the buffer in bytes + * + * X2: cookie value (Implementation Defined) + * + * X3: cookie value (Implementation Defined) + * + * X4 to X7 = 0 + */ + ep_info.args.arg0 = sp_boot_info->sp_shared_buf_base; + ep_info.args.arg1 = sp_boot_info->sp_shared_buf_size; + ep_info.args.arg2 = PLAT_SPM_COOKIE_0; + ep_info.args.arg3 = PLAT_SPM_COOKIE_1; + + cm_setup_context(ctx, &ep_info); + + /* + * SP_EL0: A non-zero value will indicate to the SP that the SPM has + * initialized the stack pointer for the current CPU through + * implementation defined means. The value will be 0 otherwise. + */ + write_ctx_reg(get_gpregs_ctx(ctx), CTX_GPREG_SP_EL0, + sp_boot_info->sp_stack_base + sp_boot_info->sp_pcpu_stack_size); + + /* + * Setup translation tables + * ------------------------ + */ + +#if ENABLE_ASSERTIONS + + /* Get max granularity supported by the platform. */ + unsigned int max_granule = xlat_arch_get_max_supported_granule_size(); + + VERBOSE("Max translation granule size supported: %u KiB\n", + max_granule / 1024U); + + unsigned int max_granule_mask = max_granule - 1U; + + /* Base must be aligned to the max granularity */ + assert((sp_boot_info->sp_ns_comm_buf_base & max_granule_mask) == 0); + + /* Size must be a multiple of the max granularity */ + assert((sp_boot_info->sp_ns_comm_buf_size & max_granule_mask) == 0); + +#endif /* ENABLE_ASSERTIONS */ + + /* This region contains the exception vectors used at S-EL1. */ + const mmap_region_t sel1_exception_vectors = + MAP_REGION_FLAT(SPM_SHIM_EXCEPTIONS_START, + SPM_SHIM_EXCEPTIONS_SIZE, + MT_CODE | MT_SECURE | MT_PRIVILEGED); + mmap_add_region_ctx(sp_ctx->xlat_ctx_handle, + &sel1_exception_vectors); + + mmap_add_ctx(sp_ctx->xlat_ctx_handle, + plat_get_secure_partition_mmap(NULL)); + + init_xlat_tables_ctx(sp_ctx->xlat_ctx_handle); + + /* + * MMU-related registers + * --------------------- + */ + xlat_ctx_t *xlat_ctx = sp_ctx->xlat_ctx_handle; + + uint64_t mmu_cfg_params[MMU_CFG_PARAM_MAX]; + + setup_mmu_cfg((uint64_t *)&mmu_cfg_params, 0, xlat_ctx->base_table, + xlat_ctx->pa_max_address, xlat_ctx->va_max_address, + EL1_EL0_REGIME); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_MAIR_EL1, + mmu_cfg_params[MMU_CFG_MAIR]); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TCR_EL1, + mmu_cfg_params[MMU_CFG_TCR]); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_TTBR0_EL1, + mmu_cfg_params[MMU_CFG_TTBR0]); + + /* Setup SCTLR_EL1 */ + u_register_t sctlr_el1 = read_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1); + + sctlr_el1 |= + /*SCTLR_EL1_RES1 |*/ + /* Don't trap DC CVAU, DC CIVAC, DC CVAC, DC CVAP, or IC IVAU */ + SCTLR_UCI_BIT | + /* RW regions at xlat regime EL1&0 are forced to be XN. */ + SCTLR_WXN_BIT | + /* Don't trap to EL1 execution of WFI or WFE at EL0. */ + SCTLR_NTWI_BIT | SCTLR_NTWE_BIT | + /* Don't trap to EL1 accesses to CTR_EL0 from EL0. */ + SCTLR_UCT_BIT | + /* Don't trap to EL1 execution of DZ ZVA at EL0. */ + SCTLR_DZE_BIT | + /* Enable SP Alignment check for EL0 */ + SCTLR_SA0_BIT | + /* Don't change PSTATE.PAN on taking an exception to EL1 */ + SCTLR_SPAN_BIT | + /* Allow cacheable data and instr. accesses to normal memory. */ + SCTLR_C_BIT | SCTLR_I_BIT | + /* Enable MMU. */ + SCTLR_M_BIT + ; + + sctlr_el1 &= ~( + /* Explicit data accesses at EL0 are little-endian. */ + SCTLR_E0E_BIT | + /* + * Alignment fault checking disabled when at EL1 and EL0 as + * the UEFI spec permits unaligned accesses. + */ + SCTLR_A_BIT | + /* Accesses to DAIF from EL0 are trapped to EL1. */ + SCTLR_UMA_BIT + ); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_SCTLR_EL1, sctlr_el1); + + /* + * Setup other system registers + * ---------------------------- + */ + + /* Shim Exception Vector Base Address */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_VBAR_EL1, + SPM_SHIM_EXCEPTIONS_PTR); + + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CNTKCTL_EL1, + EL0PTEN_BIT | EL0VTEN_BIT | EL0PCTEN_BIT | EL0VCTEN_BIT); + + /* + * FPEN: Allow the Secure Partition to access FP/SIMD registers. + * Note that SPM will not do any saving/restoring of these registers on + * behalf of the SP. This falls under the SP's responsibility. + * TTA: Enable access to trace registers. + * ZEN (v8.2): Trap SVE instructions and access to SVE registers. + */ + write_ctx_reg(get_el1_sysregs_ctx(ctx), CTX_CPACR_EL1, + CPACR_EL1_FPEN(CPACR_EL1_FP_TRAP_NONE)); + + /* + * Prepare information in buffer shared between EL3 and S-EL0 + * ---------------------------------------------------------- + */ + + void *shared_buf_ptr = (void *) sp_boot_info->sp_shared_buf_base; + + /* Copy the boot information into the shared buffer with the SP. */ + assert((uintptr_t)shared_buf_ptr + sizeof(spm_mm_boot_info_t) + <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size)); + + assert(sp_boot_info->sp_shared_buf_base <= + (UINTPTR_MAX - sp_boot_info->sp_shared_buf_size + 1)); + + assert(sp_boot_info != NULL); + + memcpy((void *) shared_buf_ptr, (const void *) sp_boot_info, + sizeof(spm_mm_boot_info_t)); + + /* Pointer to the MP information from the platform port. */ + spm_mm_mp_info_t *sp_mp_info = + ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info; + + assert(sp_mp_info != NULL); + + /* + * Point the shared buffer MP information pointer to where the info will + * be populated, just after the boot info. + */ + ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info = + (spm_mm_mp_info_t *) ((uintptr_t)shared_buf_ptr + + sizeof(spm_mm_boot_info_t)); + + /* + * Update the shared buffer pointer to where the MP information for the + * payload will be populated + */ + shared_buf_ptr = ((spm_mm_boot_info_t *) shared_buf_ptr)->mp_info; + + /* + * Copy the cpu information into the shared buffer area after the boot + * information. + */ + assert(sp_boot_info->num_cpus <= PLATFORM_CORE_COUNT); + + assert((uintptr_t)shared_buf_ptr + <= (sp_boot_info->sp_shared_buf_base + sp_boot_info->sp_shared_buf_size - + (sp_boot_info->num_cpus * sizeof(*sp_mp_info)))); + + memcpy(shared_buf_ptr, (const void *) sp_mp_info, + sp_boot_info->num_cpus * sizeof(*sp_mp_info)); + + /* + * Calculate the linear indices of cores in boot information for the + * secure partition and flag the primary CPU + */ + sp_mp_info = (spm_mm_mp_info_t *) shared_buf_ptr; + + for (unsigned int index = 0; index < sp_boot_info->num_cpus; index++) { + u_register_t mpidr = sp_mp_info[index].mpidr; + + sp_mp_info[index].linear_id = plat_core_pos_by_mpidr(mpidr); + if (plat_my_core_pos() == sp_mp_info[index].linear_id) + sp_mp_info[index].flags |= MP_INFO_FLAG_PRIMARY_CPU; + } +} diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h new file mode 100644 index 0000000..0c8d894 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2017-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPM_MM_SHIM_PRIVATE_H +#define SPM_MM_SHIM_PRIVATE_H + +#include + +#include + +/* Assembly source */ +IMPORT_SYM(uintptr_t, spm_shim_exceptions_ptr, SPM_SHIM_EXCEPTIONS_PTR); + +/* Linker symbols */ +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_START__, SPM_SHIM_EXCEPTIONS_START); +IMPORT_SYM(uintptr_t, __SPM_SHIM_EXCEPTIONS_END__, SPM_SHIM_EXCEPTIONS_END); + +/* Definitions */ + +#define SPM_SHIM_EXCEPTIONS_SIZE \ + (SPM_SHIM_EXCEPTIONS_END - SPM_SHIM_EXCEPTIONS_START) + +#endif /* SPM_MM_SHIM_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c new file mode 100644 index 0000000..eae597c --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2018-2019, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "spm_mm_private.h" +#include "spm_mm_shim_private.h" + +/* Place translation tables by default along with the ones used by BL31. */ +#ifndef PLAT_SP_IMAGE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_XLAT_SECTION_NAME "xlat_table" +#endif +#ifndef PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME +#define PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME ".bss" +#endif + +/* Allocate and initialise the translation context for the secure partitions. */ +REGISTER_XLAT_CONTEXT2(sp, + PLAT_SP_IMAGE_MMAP_REGIONS, + PLAT_SP_IMAGE_MAX_XLAT_TABLES, + PLAT_VIRT_ADDR_SPACE_SIZE, PLAT_PHY_ADDR_SPACE_SIZE, + EL1_EL0_REGIME, PLAT_SP_IMAGE_XLAT_SECTION_NAME, + PLAT_SP_IMAGE_BASE_XLAT_SECTION_NAME); + +/* Lock used for SP_MEMORY_ATTRIBUTES_GET and SP_MEMORY_ATTRIBUTES_SET */ +static spinlock_t mem_attr_smc_lock; + +/* Get handle of Secure Partition translation context */ +xlat_ctx_t *spm_get_sp_xlat_context(void) +{ + return &sp_xlat_ctx; +}; + +/* + * Attributes are encoded using a different format in the SMC interface than in + * the Trusted Firmware, where the mmap_attr_t enum type is used. This function + * converts an attributes value from the SMC format to the mmap_attr_t format by + * setting MT_RW/MT_RO, MT_USER/MT_PRIVILEGED and MT_EXECUTE/MT_EXECUTE_NEVER. + * The other fields are left as 0 because they are ignored by the function + * xlat_change_mem_attributes_ctx(). + */ +static unsigned int smc_attr_to_mmap_attr(unsigned int attributes) +{ + unsigned int tf_attr = 0U; + + unsigned int access = (attributes & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + >> MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW) { + tf_attr |= MT_RW | MT_USER; + } else if (access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO) { + tf_attr |= MT_RO | MT_USER; + } else { + /* Other values are reserved. */ + assert(access == MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS); + /* The only requirement is that there's no access from EL0 */ + tf_attr |= MT_RO | MT_PRIVILEGED; + } + + if ((attributes & MM_SP_MEMORY_ATTRIBUTES_NON_EXEC) == 0) { + tf_attr |= MT_EXECUTE; + } else { + tf_attr |= MT_EXECUTE_NEVER; + } + + return tf_attr; +} + +/* + * This function converts attributes from the Trusted Firmware format into the + * SMC interface format. + */ +static unsigned int smc_mmap_to_smc_attr(unsigned int attr) +{ + unsigned int smc_attr = 0U; + + unsigned int data_access; + + if ((attr & MT_USER) == 0) { + /* No access from EL0. */ + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_NOACCESS; + } else { + if ((attr & MT_RW) != 0) { + assert(MT_TYPE(attr) != MT_DEVICE); + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RW; + } else { + data_access = MM_SP_MEMORY_ATTRIBUTES_ACCESS_RO; + } + } + + smc_attr |= (data_access & MM_SP_MEMORY_ATTRIBUTES_ACCESS_MASK) + << MM_SP_MEMORY_ATTRIBUTES_ACCESS_SHIFT; + + if ((attr & MT_EXECUTE_NEVER) != 0U) { + smc_attr |= MM_SP_MEMORY_ATTRIBUTES_NON_EXEC; + } + + return smc_attr; +} + +int32_t spm_memory_attributes_get_smc_handler(sp_context_t *sp_ctx, + uintptr_t base_va) +{ + uint32_t attributes; + + spin_lock(&mem_attr_smc_lock); + + int rc = xlat_get_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, &attributes); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_get_mem_attributes_ctx() into SPM. */ + assert((rc == 0) || (rc == -EINVAL)); + + if (rc == 0) { + return (int32_t) smc_mmap_to_smc_attr(attributes); + } else { + return SPM_MM_INVALID_PARAMETER; + } +} + +int spm_memory_attributes_set_smc_handler(sp_context_t *sp_ctx, + u_register_t page_address, + u_register_t pages_count, + u_register_t smc_attributes) +{ + uintptr_t base_va = (uintptr_t) page_address; + size_t size = (size_t) (pages_count * PAGE_SIZE); + uint32_t attributes = (uint32_t) smc_attributes; + + INFO(" Start address : 0x%lx\n", base_va); + INFO(" Number of pages: %i (%zi bytes)\n", (int) pages_count, size); + INFO(" Attributes : 0x%x\n", attributes); + + spin_lock(&mem_attr_smc_lock); + + int ret = xlat_change_mem_attributes_ctx(sp_ctx->xlat_ctx_handle, + base_va, size, + smc_attr_to_mmap_attr(attributes)); + + spin_unlock(&mem_attr_smc_lock); + + /* Convert error codes of xlat_change_mem_attributes_ctx() into SPM. */ + assert((ret == 0) || (ret == -EINVAL)); + + return (ret == 0) ? SPM_MM_SUCCESS : SPM_MM_INVALID_PARAMETER; +} diff --git a/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S b/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S new file mode 100644 index 0000000..d7bffca --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include "../spmd_private.h" + + .global spmd_spm_core_enter + .global spmd_spm_core_exit + + /* --------------------------------------------------------------------- + * This function is called with SP_EL0 as stack. Here we stash our EL3 + * callee-saved registers on to the stack as a part of saving the C + * runtime and enter the secure payload. + * 'x0' contains a pointer to the memory where the address of the C + * runtime context is to be saved. + * --------------------------------------------------------------------- + */ +func spmd_spm_core_enter + /* Make space for the registers that we're going to save */ + mov x3, sp + str x3, [x0, #0] + sub sp, sp, #SPMD_C_RT_CTX_SIZE + + /* Save callee-saved registers on to the stack */ + stp x19, x20, [sp, #SPMD_C_RT_CTX_X19] + stp x21, x22, [sp, #SPMD_C_RT_CTX_X21] + stp x23, x24, [sp, #SPMD_C_RT_CTX_X23] + stp x25, x26, [sp, #SPMD_C_RT_CTX_X25] + stp x27, x28, [sp, #SPMD_C_RT_CTX_X27] + stp x29, x30, [sp, #SPMD_C_RT_CTX_X29] + + /* --------------------------------------------------------------------- + * Everything is setup now. el3_exit() will use the secure context to + * restore to the general purpose and EL3 system registers to ERET + * into the secure payload. + * --------------------------------------------------------------------- + */ + b el3_exit +endfunc spmd_spm_core_enter + + /* --------------------------------------------------------------------- + * This function is called with 'x0' pointing to a C runtime context. + * It restores the saved registers and jumps to that runtime with 'x0' + * as the new SP register. This destroys the C runtime context that had + * been built on the stack below the saved context by the caller. Later + * the second parameter 'x1' is passed as a return value to the caller. + * --------------------------------------------------------------------- + */ +func spmd_spm_core_exit + /* Restore the previous stack */ + mov sp, x0 + + /* Restore callee-saved registers on to the stack */ + ldp x19, x20, [x0, #(SPMD_C_RT_CTX_X19 - SPMD_C_RT_CTX_SIZE)] + ldp x21, x22, [x0, #(SPMD_C_RT_CTX_X21 - SPMD_C_RT_CTX_SIZE)] + ldp x23, x24, [x0, #(SPMD_C_RT_CTX_X23 - SPMD_C_RT_CTX_SIZE)] + ldp x25, x26, [x0, #(SPMD_C_RT_CTX_X25 - SPMD_C_RT_CTX_SIZE)] + ldp x27, x28, [x0, #(SPMD_C_RT_CTX_X27 - SPMD_C_RT_CTX_SIZE)] + ldp x29, x30, [x0, #(SPMD_C_RT_CTX_X29 - SPMD_C_RT_CTX_SIZE)] + + /* --------------------------------------------------------------------- + * This should take us back to the instruction after the call to the + * last spm_secure_partition_enter().* Place the second parameter to x0 + * so that the caller will see it as a return value from the original + * entry call. + * --------------------------------------------------------------------- + */ + mov x0, x1 + ret +endfunc spmd_spm_core_exit diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd.mk b/arm-trusted-firmware/services/std_svc/spmd/spmd.mk new file mode 100644 index 0000000..8efbdc8 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd.mk @@ -0,0 +1,26 @@ +# +# Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +ifneq (${ARCH},aarch64) + $(error "Error: SPMD is only supported on aarch64.") +endif + +ifeq (${ENABLE_SME_FOR_NS},1) + $(error "Error: SPMD is not compatible with ENABLE_SME_FOR_NS") +endif + +SPMD_SOURCES += $(addprefix services/std_svc/spmd/, \ + ${ARCH}/spmd_helpers.S \ + spmd_pm.c \ + spmd_main.c) + +# Let the top-level Makefile know that we intend to include a BL32 image +NEED_BL32 := yes + +# Enable dynamic memory mapping +# The SPMD component maps the SPMC DTB within BL31 virtual space. +PLAT_XLAT_TABLES_DYNAMIC := 1 +$(eval $(call add_define,PLAT_XLAT_TABLES_DYNAMIC)) diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c b/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c new file mode 100644 index 0000000..b767396 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_main.c @@ -0,0 +1,839 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2022, NVIDIA Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "spmd_private.h" + +/******************************************************************************* + * SPM Core context information. + ******************************************************************************/ +static spmd_spm_core_context_t spm_core_context[PLATFORM_CORE_COUNT]; + +/******************************************************************************* + * SPM Core attribute information read from its manifest. + ******************************************************************************/ +static spmc_manifest_attribute_t spmc_attrs; + +/******************************************************************************* + * SPM Core entry point information. Discovered on the primary core and reused + * on secondary cores. + ******************************************************************************/ +static entry_point_info_t *spmc_ep_info; + +/******************************************************************************* + * SPM Core context on CPU based on mpidr. + ******************************************************************************/ +spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr) +{ + int core_idx = plat_core_pos_by_mpidr(mpidr); + + if (core_idx < 0) { + ERROR("Invalid mpidr: %" PRIx64 ", returned ID: %d\n", mpidr, core_idx); + panic(); + } + + return &spm_core_context[core_idx]; +} + +/******************************************************************************* + * SPM Core context on current CPU get helper. + ******************************************************************************/ +spmd_spm_core_context_t *spmd_get_context(void) +{ + return spmd_get_context_by_mpidr(read_mpidr()); +} + +/******************************************************************************* + * SPM Core ID getter. + ******************************************************************************/ +uint16_t spmd_spmc_id_get(void) +{ + return spmc_attrs.spmc_id; +} + +/******************************************************************************* + * Static function declaration. + ******************************************************************************/ +static int32_t spmd_init(void); +static int spmd_spmc_init(void *pm_addr); +static uint64_t spmd_ffa_error_return(void *handle, + int error_code); +static uint64_t spmd_smc_forward(uint32_t smc_fid, + bool secure_origin, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *handle); + +/****************************************************************************** + * Builds an SPMD to SPMC direct message request. + *****************************************************************************/ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target_func, + unsigned long long message) +{ + write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_MSG_SEND_DIRECT_REQ_SMC32); + write_ctx_reg(gpregs, CTX_GPREG_X1, + (SPMD_DIRECT_MSG_ENDPOINT_ID << FFA_DIRECT_MSG_SOURCE_SHIFT) | + spmd_spmc_id_get()); + write_ctx_reg(gpregs, CTX_GPREG_X2, BIT(31) | target_func); + write_ctx_reg(gpregs, CTX_GPREG_X3, message); +} + + +/******************************************************************************* + * This function takes an SPMC context pointer and performs a synchronous + * SPMC entry. + ******************************************************************************/ +uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *spmc_ctx) +{ + uint64_t rc; + + assert(spmc_ctx != NULL); + + cm_set_context(&(spmc_ctx->cpu_ctx), SECURE); + + /* Restore the context assigned above */ +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_restore(SECURE); +#else + cm_el1_sysregs_context_restore(SECURE); +#endif + cm_set_next_eret_context(SECURE); + + /* Enter SPMC */ + rc = spmd_spm_core_enter(&spmc_ctx->c_rt_ctx); + + /* Save secure state */ +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(SECURE); +#else + cm_el1_sysregs_context_save(SECURE); +#endif + + return rc; +} + +/******************************************************************************* + * This function returns to the place where spmd_spm_core_sync_entry() was + * called originally. + ******************************************************************************/ +__dead2 void spmd_spm_core_sync_exit(uint64_t rc) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + + /* Get current CPU context from SPMC context */ + assert(cm_get_context(SECURE) == &(ctx->cpu_ctx)); + + /* + * The SPMD must have initiated the original request through a + * synchronous entry into SPMC. Jump back to the original C runtime + * context with the value of rc in x0; + */ + spmd_spm_core_exit(ctx->c_rt_ctx, rc); + + panic(); +} + +/******************************************************************************* + * Jump to the SPM Core for the first time. + ******************************************************************************/ +static int32_t spmd_init(void) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + uint64_t rc; + + VERBOSE("SPM Core init start.\n"); + + /* Primary boot core enters the SPMC for initialization. */ + ctx->state = SPMC_STATE_ON_PENDING; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("SPMC initialisation failed 0x%" PRIx64 "\n", rc); + return 0; + } + + ctx->state = SPMC_STATE_ON; + + VERBOSE("SPM Core init end.\n"); + + return 1; +} + +/******************************************************************************* + * spmd_secure_interrupt_handler + * Enter the SPMC for further handling of the secure interrupt by the SPMC + * itself or a Secure Partition. + ******************************************************************************/ +static uint64_t spmd_secure_interrupt_handler(uint32_t id, + uint32_t flags, + void *handle, + void *cookie) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); + unsigned int linear_id = plat_my_core_pos(); + int64_t rc; + + /* Sanity check the security state when the exception was generated */ + assert(get_interrupt_src_ss(flags) == NON_SECURE); + + /* Sanity check the pointer to this cpu's context */ + assert(handle == cm_get_context(NON_SECURE)); + + /* Save the non-secure context before entering SPMC */ + cm_el1_sysregs_context_save(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(NON_SECURE); +#endif + + /* Convey the event to the SPMC through the FFA_INTERRUPT interface. */ + write_ctx_reg(gpregs, CTX_GPREG_X0, FFA_INTERRUPT); + write_ctx_reg(gpregs, CTX_GPREG_X1, 0); + write_ctx_reg(gpregs, CTX_GPREG_X2, 0); + write_ctx_reg(gpregs, CTX_GPREG_X3, 0); + write_ctx_reg(gpregs, CTX_GPREG_X4, 0); + write_ctx_reg(gpregs, CTX_GPREG_X5, 0); + write_ctx_reg(gpregs, CTX_GPREG_X6, 0); + write_ctx_reg(gpregs, CTX_GPREG_X7, 0); + + /* Mark current core as handling a secure interrupt. */ + ctx->secure_interrupt_ongoing = true; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRId64 ") on CPU%u\n", __func__, rc, linear_id); + } + + ctx->secure_interrupt_ongoing = false; + + cm_el1_sysregs_context_restore(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_restore(NON_SECURE); +#endif + cm_set_next_eret_context(NON_SECURE); + + SMC_RET0(&ctx->cpu_ctx); +} + +/******************************************************************************* + * Loads SPMC manifest and inits SPMC. + ******************************************************************************/ +static int spmd_spmc_init(void *pm_addr) +{ + cpu_context_t *cpu_ctx; + unsigned int core_id; + uint32_t ep_attr, flags; + int rc; + + /* Load the SPM Core manifest */ + rc = plat_spm_core_manifest_load(&spmc_attrs, pm_addr); + if (rc != 0) { + WARN("No or invalid SPM Core manifest image provided by BL2\n"); + return rc; + } + + /* + * Ensure that the SPM Core version is compatible with the SPM + * Dispatcher version. + */ + if ((spmc_attrs.major_version != FFA_VERSION_MAJOR) || + (spmc_attrs.minor_version > FFA_VERSION_MINOR)) { + WARN("Unsupported FFA version (%u.%u)\n", + spmc_attrs.major_version, spmc_attrs.minor_version); + return -EINVAL; + } + + VERBOSE("FFA version (%u.%u)\n", spmc_attrs.major_version, + spmc_attrs.minor_version); + + VERBOSE("SPM Core run time EL%x.\n", + SPMD_SPM_AT_SEL2 ? MODE_EL2 : MODE_EL1); + + /* Validate the SPMC ID, Ensure high bit is set */ + if (((spmc_attrs.spmc_id >> SPMC_SECURE_ID_SHIFT) & + SPMC_SECURE_ID_MASK) == 0U) { + WARN("Invalid ID (0x%x) for SPMC.\n", spmc_attrs.spmc_id); + return -EINVAL; + } + + /* Validate the SPM Core execution state */ + if ((spmc_attrs.exec_state != MODE_RW_64) && + (spmc_attrs.exec_state != MODE_RW_32)) { + WARN("Unsupported %s%x.\n", "SPM Core execution state 0x", + spmc_attrs.exec_state); + return -EINVAL; + } + + VERBOSE("%s%x.\n", "SPM Core execution state 0x", + spmc_attrs.exec_state); + +#if SPMD_SPM_AT_SEL2 + /* Ensure manifest has not requested AArch32 state in S-EL2 */ + if (spmc_attrs.exec_state == MODE_RW_32) { + WARN("AArch32 state at S-EL2 is not supported.\n"); + return -EINVAL; + } + + /* + * Check if S-EL2 is supported on this system if S-EL2 + * is required for SPM + */ + if (!is_armv8_4_sel2_present()) { + WARN("SPM Core run time S-EL2 is not supported.\n"); + return -EINVAL; + } +#endif /* SPMD_SPM_AT_SEL2 */ + + /* Initialise an entrypoint to set up the CPU context */ + ep_attr = SECURE | EP_ST_ENABLE; + if ((read_sctlr_el3() & SCTLR_EE_BIT) != 0ULL) { + ep_attr |= EP_EE_BIG; + } + + SET_PARAM_HEAD(spmc_ep_info, PARAM_EP, VERSION_1, ep_attr); + + /* + * Populate SPSR for SPM Core based upon validated parameters from the + * manifest. + */ + if (spmc_attrs.exec_state == MODE_RW_32) { + spmc_ep_info->spsr = SPSR_MODE32(MODE32_svc, SPSR_T_ARM, + SPSR_E_LITTLE, + DAIF_FIQ_BIT | + DAIF_IRQ_BIT | + DAIF_ABT_BIT); + } else { + +#if SPMD_SPM_AT_SEL2 + static const uint32_t runtime_el = MODE_EL2; +#else + static const uint32_t runtime_el = MODE_EL1; +#endif + spmc_ep_info->spsr = SPSR_64(runtime_el, + MODE_SP_ELX, + DISABLE_ALL_EXCEPTIONS); + } + + /* Set an initial SPMC context state for all cores. */ + for (core_id = 0U; core_id < PLATFORM_CORE_COUNT; core_id++) { + spm_core_context[core_id].state = SPMC_STATE_OFF; + + /* Setup an initial cpu context for the SPMC. */ + cpu_ctx = &spm_core_context[core_id].cpu_ctx; + cm_setup_context(cpu_ctx, spmc_ep_info); + + /* + * Pass the core linear ID to the SPMC through x4. + * (TF-A implementation defined behavior helping + * a legacy TOS migration to adopt FF-A). + */ + write_ctx_reg(get_gpregs_ctx(cpu_ctx), CTX_GPREG_X4, core_id); + } + + /* Register power management hooks with PSCI */ + psci_register_spd_pm_hook(&spmd_pm); + + /* Register init function for deferred init. */ + bl31_register_bl32_init(&spmd_init); + + INFO("SPM Core setup done.\n"); + + /* + * Register an interrupt handler routing secure interrupts to SPMD + * while the NWd is running. + */ + flags = 0; + set_interrupt_rm_flag(flags, NON_SECURE); + rc = register_interrupt_type_handler(INTR_TYPE_S_EL1, + spmd_secure_interrupt_handler, + flags); + if (rc != 0) { + panic(); + } + + return 0; +} + +/******************************************************************************* + * Initialize context of SPM Core. + ******************************************************************************/ +int spmd_setup(void) +{ + void *spmc_manifest; + int rc; + + spmc_ep_info = bl31_plat_get_next_image_ep_info(SECURE); + if (spmc_ep_info == NULL) { + WARN("No SPM Core image provided by BL2 boot loader.\n"); + return -EINVAL; + } + + /* Under no circumstances will this parameter be 0 */ + assert(spmc_ep_info->pc != 0ULL); + + /* + * Check if BL32 ep_info has a reference to 'tos_fw_config'. This will + * be used as a manifest for the SPM Core at the next lower EL/mode. + */ + spmc_manifest = (void *)spmc_ep_info->args.arg0; + if (spmc_manifest == NULL) { + ERROR("Invalid or absent SPM Core manifest.\n"); + return -EINVAL; + } + + /* Load manifest, init SPMC */ + rc = spmd_spmc_init(spmc_manifest); + if (rc != 0) { + WARN("Booting device without SPM initialization.\n"); + } + + return rc; +} + +/******************************************************************************* + * Forward SMC to the other security state + ******************************************************************************/ +static uint64_t spmd_smc_forward(uint32_t smc_fid, + bool secure_origin, + uint64_t x1, + uint64_t x2, + uint64_t x3, + uint64_t x4, + void *handle) +{ + unsigned int secure_state_in = (secure_origin) ? SECURE : NON_SECURE; + unsigned int secure_state_out = (!secure_origin) ? SECURE : NON_SECURE; + + /* Save incoming security state */ +#if SPMD_SPM_AT_SEL2 + if (secure_state_in == NON_SECURE) { + cm_el1_sysregs_context_save(secure_state_in); + } + cm_el2_sysregs_context_save(secure_state_in); +#else + cm_el1_sysregs_context_save(secure_state_in); +#endif + + /* Restore outgoing security state */ +#if SPMD_SPM_AT_SEL2 + if (secure_state_out == NON_SECURE) { + cm_el1_sysregs_context_restore(secure_state_out); + } + cm_el2_sysregs_context_restore(secure_state_out); +#else + cm_el1_sysregs_context_restore(secure_state_out); +#endif + cm_set_next_eret_context(secure_state_out); + + SMC_RET8(cm_get_context(secure_state_out), smc_fid, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); +} + +/******************************************************************************* + * Return FFA_ERROR with specified error code + ******************************************************************************/ +static uint64_t spmd_ffa_error_return(void *handle, int error_code) +{ + SMC_RET8(handle, (uint32_t) FFA_ERROR, + FFA_TARGET_INFO_MBZ, (uint32_t)error_code, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ); +} + +/******************************************************************************* + * spmd_check_address_in_binary_image + ******************************************************************************/ +bool spmd_check_address_in_binary_image(uint64_t address) +{ + assert(!check_uptr_overflow(spmc_attrs.load_address, spmc_attrs.binary_size)); + + return ((address >= spmc_attrs.load_address) && + (address < (spmc_attrs.load_address + spmc_attrs.binary_size))); +} + +/****************************************************************************** + * spmd_is_spmc_message + *****************************************************************************/ +static bool spmd_is_spmc_message(unsigned int ep) +{ + return ((ffa_endpoint_destination(ep) == SPMD_DIRECT_MSG_ENDPOINT_ID) + && (ffa_endpoint_source(ep) == spmc_attrs.spmc_id)); +} + +/****************************************************************************** + * spmd_handle_spmc_message + *****************************************************************************/ +static int spmd_handle_spmc_message(unsigned long long msg, + unsigned long long parm1, unsigned long long parm2, + unsigned long long parm3, unsigned long long parm4) +{ + VERBOSE("%s %llx %llx %llx %llx %llx\n", __func__, + msg, parm1, parm2, parm3, parm4); + + return -EINVAL; +} + +/******************************************************************************* + * This function handles all SMCs in the range reserved for FFA. Each call is + * either forwarded to the other security state or handled by the SPM dispatcher + ******************************************************************************/ +uint64_t spmd_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) +{ + unsigned int linear_id = plat_my_core_pos(); + spmd_spm_core_context_t *ctx = spmd_get_context(); + bool secure_origin; + int32_t ret; + uint32_t input_version; + + /* Return error if SPMC init failed */ + if ((ctx->state == SPMC_STATE_RESET) || (ctx->state == SPMC_STATE_OFF)) { + WARN("SPM: SPMC not initialized\n"); + return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); + } + + /* Determine which security state this SMC originated from */ + secure_origin = is_caller_secure(flags); + + VERBOSE("SPM(%u): 0x%x 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 + " 0x%" PRIx64 " 0x%" PRIx64 " 0x%" PRIx64 "\n", + linear_id, smc_fid, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + switch (smc_fid) { + case FFA_ERROR: + /* + * Check if this is the first invocation of this interface on + * this CPU. If so, then indicate that the SPM Core initialised + * unsuccessfully. + */ + if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { + spmd_spm_core_sync_exit(x2); + } + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_VERSION: + input_version = (uint32_t)(0xFFFFFFFF & x1); + /* + * If caller is secure and SPMC was initialized, + * return FFA_VERSION of SPMD. + * If caller is non secure and SPMC was initialized, + * return SPMC's version. + * Sanity check to "input_version". + */ + if ((input_version & FFA_VERSION_BIT31_MASK) || + (ctx->state == SPMC_STATE_RESET)) { + ret = FFA_ERROR_NOT_SUPPORTED; + } else if (!secure_origin) { + gp_regs_t *gpregs = get_gpregs_ctx(&ctx->cpu_ctx); + uint64_t rc; + + if (spmc_attrs.major_version == 1 && + spmc_attrs.minor_version == 0) { + ret = MAKE_FFA_VERSION(spmc_attrs.major_version, + spmc_attrs.minor_version); + SMC_RET8(handle, (uint32_t)ret, + FFA_TARGET_INFO_MBZ, + FFA_TARGET_INFO_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + break; + } + /* Save non-secure system registers context */ + cm_el1_sysregs_context_save(NON_SECURE); +#if SPMD_SPM_AT_SEL2 + cm_el2_sysregs_context_save(NON_SECURE); +#endif + + /* + * The incoming request has FFA_VERSION as X0 smc_fid + * and requested version in x1. Prepare a direct request + * from SPMD to SPMC with FFA_VERSION framework function + * identifier in X2 and requested version in X3. + */ + spmd_build_spmc_message(gpregs, + SPMD_FWK_MSG_FFA_VERSION_REQ, + input_version); + + rc = spmd_spm_core_sync_entry(ctx); + + if ((rc != 0ULL) || + (SMC_GET_GP(gpregs, CTX_GPREG_X0) != + FFA_MSG_SEND_DIRECT_RESP_SMC32) || + (SMC_GET_GP(gpregs, CTX_GPREG_X2) != + (SPMD_FWK_MSG_BIT | + SPMD_FWK_MSG_FFA_VERSION_RESP))) { + ERROR("Failed to forward FFA_VERSION\n"); + ret = FFA_ERROR_NOT_SUPPORTED; + } else { + ret = SMC_GET_GP(gpregs, CTX_GPREG_X3); + } + + /* + * Return here after SPMC has handled FFA_VERSION. + * The returned SPMC version is held in X3. + * Forward this version in X0 to the non-secure caller. + */ + return spmd_smc_forward(ret, true, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, gpregs); + } else { + ret = MAKE_FFA_VERSION(FFA_VERSION_MAJOR, + FFA_VERSION_MINOR); + } + + SMC_RET8(handle, (uint32_t)ret, FFA_TARGET_INFO_MBZ, + FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, FFA_PARAM_MBZ); + break; /* not reached */ + + case FFA_FEATURES: + /* + * This is an optional interface. Do the minimal checks and + * forward to SPM Core which will handle it if implemented. + */ + + /* Forward SMC from Normal world to the SPM Core */ + if (!secure_origin) { + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + + /* + * Return success if call was from secure world i.e. all + * FFA functions are supported. This is essentially a + * nop. + */ + SMC_RET8(handle, FFA_SUCCESS_SMC32, x1, x2, x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + break; /* not reached */ + + case FFA_ID_GET: + /* + * Returns the ID of the calling FFA component. + */ + if (!secure_origin) { + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, FFA_NS_ENDPOINT_ID, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + + break; /* not reached */ + + case FFA_SECONDARY_EP_REGISTER_SMC64: + if (secure_origin) { + ret = spmd_pm_secondary_ep_register(x1); + + if (ret < 0) { + SMC_RET8(handle, FFA_ERROR_SMC64, + FFA_TARGET_INFO_MBZ, ret, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } else { + SMC_RET8(handle, FFA_SUCCESS_SMC64, + FFA_TARGET_INFO_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + } + + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + break; /* Not reached */ + + case FFA_SPM_ID_GET: + if (MAKE_FFA_VERSION(1, 1) > FFA_VERSION_COMPILED) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + /* + * Returns the ID of the SPMC or SPMD depending on the FF-A + * instance where this function is invoked + */ + if (!secure_origin) { + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, spmc_attrs.spmc_id, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, SPMD_DIRECT_MSG_ENDPOINT_ID, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + + break; /* not reached */ + + case FFA_MSG_SEND_DIRECT_REQ_SMC32: + if (secure_origin && spmd_is_spmc_message(x1)) { + ret = spmd_handle_spmc_message(x3, x4, + SMC_GET_GP(handle, CTX_GPREG_X5), + SMC_GET_GP(handle, CTX_GPREG_X6), + SMC_GET_GP(handle, CTX_GPREG_X7)); + + SMC_RET8(handle, FFA_SUCCESS_SMC32, + FFA_TARGET_INFO_MBZ, ret, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ, FFA_PARAM_MBZ, + FFA_PARAM_MBZ); + } else { + /* Forward direct message to the other world */ + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + break; /* Not reached */ + + case FFA_MSG_SEND_DIRECT_RESP_SMC32: + if (secure_origin && spmd_is_spmc_message(x1)) { + spmd_spm_core_sync_exit(0ULL); + } else { + /* Forward direct message to the other world */ + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + } + break; /* Not reached */ + + case FFA_RX_RELEASE: + case FFA_RXTX_MAP_SMC32: + case FFA_RXTX_MAP_SMC64: + case FFA_RXTX_UNMAP: + case FFA_PARTITION_INFO_GET: +#if MAKE_FFA_VERSION(1, 1) <= FFA_VERSION_COMPILED + case FFA_NOTIFICATION_BITMAP_CREATE: + case FFA_NOTIFICATION_BITMAP_DESTROY: + case FFA_NOTIFICATION_BIND: + case FFA_NOTIFICATION_UNBIND: + case FFA_NOTIFICATION_SET: + case FFA_NOTIFICATION_GET: + case FFA_NOTIFICATION_INFO_GET: + case FFA_NOTIFICATION_INFO_GET_SMC64: + case FFA_MSG_SEND2: +#endif + case FFA_MSG_RUN: + /* + * Above calls should be invoked only by the Normal world and + * must not be forwarded from Secure world to Normal world. + */ + if (secure_origin) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + /* Fall through to forward the call to the other world */ + case FFA_MSG_SEND: + case FFA_MSG_SEND_DIRECT_REQ_SMC64: + case FFA_MSG_SEND_DIRECT_RESP_SMC64: + case FFA_MEM_DONATE_SMC32: + case FFA_MEM_DONATE_SMC64: + case FFA_MEM_LEND_SMC32: + case FFA_MEM_LEND_SMC64: + case FFA_MEM_SHARE_SMC32: + case FFA_MEM_SHARE_SMC64: + case FFA_MEM_RETRIEVE_REQ_SMC32: + case FFA_MEM_RETRIEVE_REQ_SMC64: + case FFA_MEM_RETRIEVE_RESP: + case FFA_MEM_RELINQUISH: + case FFA_MEM_RECLAIM: + case FFA_SUCCESS_SMC32: + case FFA_SUCCESS_SMC64: + /* + * TODO: Assume that no requests originate from EL3 at the + * moment. This will change if a SP service is required in + * response to secure interrupts targeted to EL3. Until then + * simply forward the call to the Normal world. + */ + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_MSG_WAIT: + /* + * Check if this is the first invocation of this interface on + * this CPU from the Secure world. If so, then indicate that the + * SPM Core initialised successfully. + */ + if (secure_origin && (ctx->state == SPMC_STATE_ON_PENDING)) { + spmd_spm_core_sync_exit(0ULL); + } + + /* Fall through to forward the call to the other world */ + case FFA_INTERRUPT: + case FFA_MSG_YIELD: + /* This interface must be invoked only by the Secure world */ + if (!secure_origin) { + return spmd_ffa_error_return(handle, + FFA_ERROR_NOT_SUPPORTED); + } + + return spmd_smc_forward(smc_fid, secure_origin, + x1, x2, x3, x4, handle); + break; /* not reached */ + + case FFA_NORMAL_WORLD_RESUME: + if (secure_origin && ctx->secure_interrupt_ongoing) { + spmd_spm_core_sync_exit(0ULL); + } else { + return spmd_ffa_error_return(handle, FFA_ERROR_DENIED); + } + break; /* Not reached */ + + default: + WARN("SPM: Unsupported call 0x%08x\n", smc_fid); + return spmd_ffa_error_return(handle, FFA_ERROR_NOT_SUPPORTED); + } +} diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c b/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c new file mode 100644 index 0000000..b719161 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2020-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include "spmd_private.h" + +static struct { + bool secondary_ep_locked; + uintptr_t secondary_ep; + spinlock_t lock; +} g_spmd_pm; + +/******************************************************************************* + * spmd_pm_secondary_ep_register + ******************************************************************************/ +int spmd_pm_secondary_ep_register(uintptr_t entry_point) +{ + int ret = FFA_ERROR_INVALID_PARAMETER; + + spin_lock(&g_spmd_pm.lock); + + if (g_spmd_pm.secondary_ep_locked == true) { + goto out; + } + + /* + * Check entry_point address is a PA within + * load_address <= entry_point < load_address + binary_size + */ + if (!spmd_check_address_in_binary_image(entry_point)) { + ERROR("%s entry point is not within image boundaries\n", + __func__); + goto out; + } + + g_spmd_pm.secondary_ep = entry_point; + g_spmd_pm.secondary_ep_locked = true; + + VERBOSE("%s %lx\n", __func__, entry_point); + + ret = 0; + +out: + spin_unlock(&g_spmd_pm.lock); + + return ret; +} + +/******************************************************************************* + * This CPU has been turned on. Enter SPMC to initialise S-EL1 or S-EL2. As part + * of the SPMC initialization path, they will initialize any SPs that they + * manage. Entry into SPMC is done after initialising minimal architectural + * state that guarantees safe execution. + ******************************************************************************/ +static void spmd_cpu_on_finish_handler(u_register_t unused) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + unsigned int linear_id = plat_my_core_pos(); + el3_state_t *el3_state; + uintptr_t entry_point; + uint64_t rc; + + assert(ctx != NULL); + assert(ctx->state != SPMC_STATE_ON); + + spin_lock(&g_spmd_pm.lock); + + /* + * Leave the possibility that the SPMC does not call + * FFA_SECONDARY_EP_REGISTER in which case re-use the + * primary core address for booting secondary cores. + */ + if (g_spmd_pm.secondary_ep_locked == true) { + /* + * The CPU context has already been initialized at boot time + * (in spmd_spmc_init by a call to cm_setup_context). Adjust + * below the target core entry point based on the address + * passed to by FFA_SECONDARY_EP_REGISTER. + */ + entry_point = g_spmd_pm.secondary_ep; + el3_state = get_el3state_ctx(&ctx->cpu_ctx); + write_ctx_reg(el3_state, CTX_ELR_EL3, entry_point); + } + + spin_unlock(&g_spmd_pm.lock); + + /* Mark CPU as initiating ON operation. */ + ctx->state = SPMC_STATE_ON_PENDING; + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRIu64 ") on CPU%u\n", __func__, rc, + linear_id); + ctx->state = SPMC_STATE_OFF; + return; + } + + ctx->state = SPMC_STATE_ON; + + VERBOSE("CPU %u on!\n", linear_id); +} + +/******************************************************************************* + * spmd_cpu_off_handler + ******************************************************************************/ +static int32_t spmd_cpu_off_handler(u_register_t unused) +{ + spmd_spm_core_context_t *ctx = spmd_get_context(); + unsigned int linear_id = plat_my_core_pos(); + int64_t rc; + + assert(ctx != NULL); + assert(ctx->state != SPMC_STATE_OFF); + + /* Build an SPMD to SPMC direct message request. */ + spmd_build_spmc_message(get_gpregs_ctx(&ctx->cpu_ctx), + SPMD_FWK_MSG_PSCI, PSCI_CPU_OFF); + + rc = spmd_spm_core_sync_entry(ctx); + if (rc != 0ULL) { + ERROR("%s failed (%" PRIu64 ") on CPU%u\n", __func__, rc, linear_id); + } + + /* Expect a direct message response from the SPMC. */ + u_register_t ffa_resp_func = read_ctx_reg(get_gpregs_ctx(&ctx->cpu_ctx), + CTX_GPREG_X0); + if (ffa_resp_func != FFA_MSG_SEND_DIRECT_RESP_SMC32) { + ERROR("%s invalid SPMC response (%lx).\n", + __func__, ffa_resp_func); + return -EINVAL; + } + + ctx->state = SPMC_STATE_OFF; + + VERBOSE("CPU %u off!\n", linear_id); + + return 0; +} + +/******************************************************************************* + * Structure populated by the SPM Dispatcher to perform any bookkeeping before + * PSCI executes a power mgmt. operation. + ******************************************************************************/ +const spd_pm_ops_t spmd_pm = { + .svc_on_finish = spmd_cpu_on_finish_handler, + .svc_off = spmd_cpu_off_handler +}; diff --git a/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h b/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h new file mode 100644 index 0000000..4cd6a74 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/spmd/spmd_private.h @@ -0,0 +1,105 @@ +/* + * Copyright (c) 2019-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SPMD_PRIVATE_H +#define SPMD_PRIVATE_H + +#include + +/******************************************************************************* + * Constants that allow assembler code to preserve callee-saved registers of the + * C runtime context while performing a security state switch. + ******************************************************************************/ +#define SPMD_C_RT_CTX_X19 0x0 +#define SPMD_C_RT_CTX_X20 0x8 +#define SPMD_C_RT_CTX_X21 0x10 +#define SPMD_C_RT_CTX_X22 0x18 +#define SPMD_C_RT_CTX_X23 0x20 +#define SPMD_C_RT_CTX_X24 0x28 +#define SPMD_C_RT_CTX_X25 0x30 +#define SPMD_C_RT_CTX_X26 0x38 +#define SPMD_C_RT_CTX_X27 0x40 +#define SPMD_C_RT_CTX_X28 0x48 +#define SPMD_C_RT_CTX_X29 0x50 +#define SPMD_C_RT_CTX_X30 0x58 + +#define SPMD_C_RT_CTX_SIZE 0x60 +#define SPMD_C_RT_CTX_ENTRIES (SPMD_C_RT_CTX_SIZE >> DWORD_SHIFT) + +#ifndef __ASSEMBLER__ +#include +#include +#include +#include + +typedef enum spmc_state { + SPMC_STATE_RESET = 0, + SPMC_STATE_OFF, + SPMC_STATE_ON_PENDING, + SPMC_STATE_ON +} spmc_state_t; + +/* + * Data structure used by the SPM dispatcher (SPMD) in EL3 to track context of + * the SPM core (SPMC) at the next lower EL. + */ +typedef struct spmd_spm_core_context { + uint64_t c_rt_ctx; + cpu_context_t cpu_ctx; + spmc_state_t state; + bool secure_interrupt_ongoing; +} spmd_spm_core_context_t; + +/* + * Reserve ID for NS physical FFA Endpoint. + */ +#define FFA_NS_ENDPOINT_ID U(0) + +/* Mask and shift to check valid secure FF-A Endpoint ID. */ +#define SPMC_SECURE_ID_MASK U(1) +#define SPMC_SECURE_ID_SHIFT U(15) + +#define SPMD_DIRECT_MSG_ENDPOINT_ID U(FFA_ENDPOINT_ID_MAX - 1) + +/* Define SPMD target function IDs for framework messages to the SPMC */ +#define SPMD_FWK_MSG_BIT BIT(31) +#define SPMD_FWK_MSG_PSCI U(0) +#define SPMD_FWK_MSG_FFA_VERSION_REQ U(0x8) +#define SPMD_FWK_MSG_FFA_VERSION_RESP U(0x9) + +/* Function to build SPMD to SPMC message */ +void spmd_build_spmc_message(gp_regs_t *gpregs, uint8_t target, + unsigned long long message); + +/* Functions used to enter/exit SPMC synchronously */ +uint64_t spmd_spm_core_sync_entry(spmd_spm_core_context_t *ctx); +__dead2 void spmd_spm_core_sync_exit(uint64_t rc); + +/* Assembly helpers */ +uint64_t spmd_spm_core_enter(uint64_t *c_rt_ctx); +void __dead2 spmd_spm_core_exit(uint64_t c_rt_ctx, uint64_t ret); + +/* SPMD SPD power management handlers */ +extern const spd_pm_ops_t spmd_pm; + +/* SPMC entry point information helper */ +entry_point_info_t *spmd_spmc_ep_info_get(void); + +/* SPMC ID getter */ +uint16_t spmd_spmc_id_get(void); + +/* SPMC context on CPU based on mpidr */ +spmd_spm_core_context_t *spmd_get_context_by_mpidr(uint64_t mpidr); + +/* SPMC context on current CPU get helper */ +spmd_spm_core_context_t *spmd_get_context(void); + +int spmd_pm_secondary_ep_register(uintptr_t entry_point); +bool spmd_check_address_in_binary_image(uint64_t address); + +#endif /* __ASSEMBLER__ */ + +#endif /* SPMD_PRIVATE_H */ diff --git a/arm-trusted-firmware/services/std_svc/std_svc_setup.c b/arm-trusted-firmware/services/std_svc/std_svc_setup.c new file mode 100644 index 0000000..9452c17 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/std_svc_setup.c @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2014-2022, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Standard Service UUID */ +static uuid_t arm_svc_uid = { + {0x5b, 0x90, 0x8d, 0x10}, + {0x63, 0xf8}, + {0xe8, 0x47}, + 0xae, 0x2d, + {0xc0, 0xfb, 0x56, 0x41, 0xf6, 0xe2} +}; + +/* Setup Standard Services */ +static int32_t std_svc_setup(void) +{ + uintptr_t svc_arg; + int ret = 0; + + svc_arg = get_arm_std_svc_args(PSCI_FID_MASK); + assert(svc_arg); + + /* + * PSCI is one of the specifications implemented as a Standard Service. + * The `psci_setup()` also does EL3 architectural setup. + */ + if (psci_setup((const psci_lib_args_t *)svc_arg) != PSCI_E_SUCCESS) { + ret = 1; + } + +#if SPM_MM + if (spm_mm_setup() != 0) { + ret = 1; + } +#endif + +#if defined(SPD_spmd) + if (spmd_setup() != 0) { + WARN("SPMD setup failed. Continuing boot.\n"); + } +#endif + +#if ENABLE_RME + if (rmmd_setup() != 0) { + ret = 1; + } +#endif + +#if SDEI_SUPPORT + /* SDEI initialisation */ + sdei_init(); +#endif + + trng_setup(); + + return ret; +} + +/* + * Top-level Standard Service SMC handler. This handler will in turn dispatch + * calls to PSCI SMC handler + */ +static uintptr_t std_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) +{ + if (((smc_fid >> FUNCID_CC_SHIFT) & FUNCID_CC_MASK) == SMC_32) { + /* 32-bit SMC function, clear top parameter bits */ + + x1 &= UINT32_MAX; + x2 &= UINT32_MAX; + x3 &= UINT32_MAX; + x4 &= UINT32_MAX; + } + + /* + * Dispatch PSCI calls to PSCI SMC handler and return its return + * value + */ + if (is_psci_fid(smc_fid)) { + uint64_t ret; + +#if ENABLE_RUNTIME_INSTRUMENTATION + + /* + * Flush cache line so that even if CPU power down happens + * the timestamp update is reflected in memory. + */ + PMF_WRITE_TIMESTAMP(rt_instr_svc, + RT_INSTR_ENTER_PSCI, + PMF_CACHE_MAINT, + get_cpu_data(cpu_data_pmf_ts[CPU_DATA_PMF_TS0_IDX])); +#endif + + ret = psci_smc_handler(smc_fid, x1, x2, x3, x4, + cookie, handle, flags); + +#if ENABLE_RUNTIME_INSTRUMENTATION + PMF_CAPTURE_TIMESTAMP(rt_instr_svc, + RT_INSTR_EXIT_PSCI, + PMF_NO_CACHE_MAINT); +#endif + + SMC_RET1(handle, ret); + } + +#if SPM_MM + /* + * Dispatch SPM calls to SPM SMC handler and return its return + * value + */ + if (is_spm_mm_fid(smc_fid)) { + return spm_mm_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if defined(SPD_spmd) + /* + * Dispatch FFA calls to the FFA SMC handler implemented by the SPM + * dispatcher and return its return value + */ + if (is_ffa_fid(smc_fid)) { + return spmd_smc_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if SDEI_SUPPORT + if (is_sdei_fid(smc_fid)) { + return sdei_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif + +#if TRNG_SUPPORT + if (is_trng_fid(smc_fid)) { + return trng_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif +#if ENABLE_RME + + if (is_rmmd_el3_fid(smc_fid)) { + return rmmd_rmm_el3_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } + + if (is_rmi_fid(smc_fid)) { + return rmmd_rmi_handler(smc_fid, x1, x2, x3, x4, cookie, + handle, flags); + } +#endif + +#if SMC_PCI_SUPPORT + if (is_pci_fid(smc_fid)) { + return pci_smc_handler(smc_fid, x1, x2, x3, x4, cookie, handle, + flags); + } +#endif + + switch (smc_fid) { + case ARM_STD_SVC_CALL_COUNT: + /* + * Return the number of Standard Service Calls. PSCI is the only + * standard service implemented; so return number of PSCI calls + */ + SMC_RET1(handle, PSCI_NUM_CALLS); + + case ARM_STD_SVC_UID: + /* Return UID to the caller */ + SMC_UUID_RET(handle, arm_svc_uid); + + case ARM_STD_SVC_VERSION: + /* Return the version of current implementation */ + SMC_RET2(handle, STD_SVC_VERSION_MAJOR, STD_SVC_VERSION_MINOR); + + default: + VERBOSE("Unimplemented Standard Service Call: 0x%x \n", smc_fid); + SMC_RET1(handle, SMC_UNK); + } +} + +/* Register Standard Service Calls as runtime service */ +DECLARE_RT_SVC( + std_svc, + + OEN_STD_START, + OEN_STD_END, + SMC_TYPE_FAST, + std_svc_setup, + std_svc_smc_handler +); diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c new file mode 100644 index 0000000..ac13b1d --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2021, ARM Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include + +/* + * # Entropy pool + * Note that the TRNG Firmware interface can request up to 192 bits of entropy + * in a single call or three 64bit words per call. We have 4 words in the pool + * so that when we have 1-63 bits in the pool, and we have a request for + * 192 bits of entropy, we don't have to throw out the leftover 1-63 bits of + * entropy. + */ +#define WORDS_IN_POOL (4) +static uint64_t entropy[WORDS_IN_POOL]; +/* index in bits of the first bit of usable entropy */ +static uint32_t entropy_bit_index; +/* then number of valid bits in the entropy pool */ +static uint32_t entropy_bit_size; + +static spinlock_t trng_pool_lock; + +#define BITS_PER_WORD (sizeof(entropy[0]) * 8) +#define BITS_IN_POOL (WORDS_IN_POOL * BITS_PER_WORD) +#define ENTROPY_MIN_WORD (entropy_bit_index / BITS_PER_WORD) +#define ENTROPY_FREE_BIT (entropy_bit_size + entropy_bit_index) +#define _ENTROPY_FREE_WORD (ENTROPY_FREE_BIT / BITS_PER_WORD) +#define ENTROPY_FREE_INDEX (_ENTROPY_FREE_WORD % WORDS_IN_POOL) +/* ENTROPY_WORD_INDEX(0) includes leftover bits in the lower bits */ +#define ENTROPY_WORD_INDEX(i) ((ENTROPY_MIN_WORD + i) % WORDS_IN_POOL) + +/* + * Fill the entropy pool until we have at least as many bits as requested. + * Returns true after filling the pool, and false if the entropy source is out + * of entropy and the pool could not be filled. + * Assumes locks are taken. + */ +static bool trng_fill_entropy(uint32_t nbits) +{ + while (nbits > entropy_bit_size) { + bool valid = plat_get_entropy(&entropy[ENTROPY_FREE_INDEX]); + + if (valid) { + entropy_bit_size += BITS_PER_WORD; + assert(entropy_bit_size <= BITS_IN_POOL); + } else { + return false; + } + } + return true; +} + +/* + * Pack entropy into the out buffer, filling and taking locks as needed. + * Returns true on success, false on failure. + * + * Note: out must have enough space for nbits of entropy + */ +bool trng_pack_entropy(uint32_t nbits, uint64_t *out) +{ + bool success = true; + + spin_lock(&trng_pool_lock); + + if (!trng_fill_entropy(nbits)) { + success = false; + goto out; + } + + const unsigned int rshift = entropy_bit_index % BITS_PER_WORD; + const unsigned int lshift = BITS_PER_WORD - rshift; + const int to_fill = ((nbits + BITS_PER_WORD - 1) / BITS_PER_WORD); + int word_i; + + for (word_i = 0; word_i < to_fill; word_i++) { + /* + * Repack the entropy from the pool into the passed in out + * buffer. This takes the lower bits from the valid upper bits + * of word_i and the upper bits from the lower bits of + * (word_i + 1). + * + * I found the following diagram useful. note: `e` represents + * valid entropy, ` ` represents invalid bits (not entropy) and + * `x` represents valid entropy that must not end up in the + * packed word. + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * | [e,e,e,e,e,e,e,e] | + * | |--out[word_i]--| | + * lshift|---| |--rshift---| + * + * ==== Which is implemented as ==== + * + * |---------entropy pool----------| + * C var |--(word_i + 1)-|----word_i-----| + * bit idx |7 6 5 4 3 2 1 0|7 6 5 4 3 2 1 0| + * [x,x,e,e,e,e,e,e|e,e, , , , , , ] + * C expr << lshift >> rshift + * bit idx 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,0,0|0,0,0,0,0,0,e,e] + * ==== bit-wise or ==== + * 5 4 3 2 1 0 7 6 + * [e,e,e,e,e,e,e,e] + */ + out[word_i] = 0; + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i)] >> rshift; + + /* + * Note that a shift of 64 bits is treated as a shift of 0 bits. + * When the shift amount is the same as the BITS_PER_WORD, we + * don't want to include the next word of entropy, so we skip + * the `|=` operation. + */ + if (lshift != BITS_PER_WORD) { + out[word_i] |= entropy[ENTROPY_WORD_INDEX(word_i + 1)] + << lshift; + } + } + const uint64_t mask = ~0ULL >> (BITS_PER_WORD - (nbits % BITS_PER_WORD)); + + out[to_fill - 1] &= mask; + + entropy_bit_index = (entropy_bit_index + nbits) % BITS_IN_POOL; + entropy_bit_size -= nbits; + +out: + spin_unlock(&trng_pool_lock); + + return success; +} + +void trng_entropy_pool_setup(void) +{ + int i; + + for (i = 0; i < WORDS_IN_POOL; i++) { + entropy[i] = 0; + } + entropy_bit_index = 0; + entropy_bit_size = 0; +} diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h new file mode 100644 index 0000000..fab2367 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TRNG_ENTROPY_POOL_H +#define TRNG_ENTROPY_POOL_H + +#include +#include + +bool trng_pack_entropy(uint32_t nbits, uint64_t *out); +void trng_entropy_pool_setup(void); + +#endif /* TRNG_ENTROPY_POOL_H */ diff --git a/arm-trusted-firmware/services/std_svc/trng/trng_main.c b/arm-trusted-firmware/services/std_svc/trng/trng_main.c new file mode 100644 index 0000000..38aa649 --- /dev/null +++ b/arm-trusted-firmware/services/std_svc/trng/trng_main.c @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include + +#include + +#include "trng_entropy_pool.h" + +static const uuid_t uuid_null; + +/* handle the RND call in SMC 32 bit mode */ +static uintptr_t trng_rnd32(uint32_t nbits, void *handle) +{ + uint32_t mask = ~0U; + uint64_t ent[2]; + + if (nbits == 0U || nbits > 96U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + if ((nbits % 32U) != 0U) { + mask >>= 32U - (nbits % 32U); + } + + switch ((nbits - 1U) / 32U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, (ent[0] >> 32) & mask, + ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[1] & mask, + (ent[0] >> 32) & 0xFFFFFFFF, ent[0] & 0xFFFFFFFF); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +/* handle the RND call in SMC 64 bit mode */ +static uintptr_t trng_rnd64(uint32_t nbits, void *handle) +{ + uint64_t mask = ~0ULL; + uint64_t ent[3]; + + if (nbits == 0U || nbits > 192U) { + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + } + + if (!trng_pack_entropy(nbits, &ent[0])) { + SMC_RET1(handle, TRNG_E_NO_ENTROPY); + } + + /* Mask off higher bits if only part of register requested */ + if ((nbits % 64U) != 0U) { + mask >>= 64U - (nbits % 64U); + } + + switch ((nbits - 1U) / 64U) { + case 0: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, 0, ent[0] & mask); + break; /* unreachable */ + case 1: + SMC_RET4(handle, TRNG_E_SUCCESS, 0, ent[1] & mask, ent[0]); + break; /* unreachable */ + case 2: + SMC_RET4(handle, TRNG_E_SUCCESS, ent[2] & mask, ent[1], ent[0]); + break; /* unreachable */ + default: + SMC_RET1(handle, TRNG_E_INVALID_PARAMS); + break; /* unreachable */ + } +} + +void trng_setup(void) +{ + trng_entropy_pool_setup(); + plat_entropy_setup(); +} + +/* Predicate indicating that a function id is part of TRNG */ +bool is_trng_fid(uint32_t smc_fid) +{ + return ((smc_fid == ARM_TRNG_VERSION) || + (smc_fid == ARM_TRNG_FEATURES) || + (smc_fid == ARM_TRNG_GET_UUID) || + (smc_fid == ARM_TRNG_RND32) || + (smc_fid == ARM_TRNG_RND64)); +} + +uintptr_t trng_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) +{ + if (!memcmp(&plat_trng_uuid, &uuid_null, sizeof(uuid_t))) { + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + } + + switch (smc_fid) { + case ARM_TRNG_VERSION: + SMC_RET1(handle, MAKE_SMCCC_VERSION( + TRNG_VERSION_MAJOR, TRNG_VERSION_MINOR + )); + break; /* unreachable */ + case ARM_TRNG_FEATURES: + if (is_trng_fid((uint32_t)x1)) { + SMC_RET1(handle, TRNG_E_SUCCESS); + } else { + SMC_RET1(handle, TRNG_E_NOT_SUPPORTED); + } + break; /* unreachable */ + case ARM_TRNG_GET_UUID: + SMC_UUID_RET(handle, plat_trng_uuid); + break; /* unreachable */ + case ARM_TRNG_RND32: + return trng_rnd32((uint32_t)x1, handle); + case ARM_TRNG_RND64: + return trng_rnd64((uint32_t)x1, handle); + default: + WARN("Unimplemented TRNG Service Call: 0x%x\n", + smc_fid); + SMC_RET1(handle, TRNG_E_NOT_IMPLEMENTED); + break; /* unreachable */ + } +} diff --git a/arm-trusted-firmware/tools/amlogic/Makefile b/arm-trusted-firmware/tools/amlogic/Makefile new file mode 100644 index 0000000..1a1d1f8 --- /dev/null +++ b/arm-trusted-firmware/tools/amlogic/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (C) 2019 Remi Pommarel +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses +# +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +PROJECT := doimage${BIN_EXT} +OBJECTS := doimage.o +V := 0 + +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCC := gcc + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) + +distclean: clean diff --git a/arm-trusted-firmware/tools/amlogic/doimage.c b/arm-trusted-firmware/tools/amlogic/doimage.c new file mode 100644 index 0000000..b304038 --- /dev/null +++ b/arm-trusted-firmware/tools/amlogic/doimage.c @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2019, Remi Pommarel + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#include +#include +#include +#include +#include +#include + +#define DEFAULT_PROGNAME "doimage" +#define PROGNAME(argc, argv) (((argc) >= 1) ? ((argv)[0]) : DEFAULT_PROGNAME) + +#define BL31_MAGIC 0x12348765 +#define BL31_LOADADDR 0x05100000 +#define BUFLEN 512 + +static inline void usage(char const *prog) +{ + fprintf(stderr, "Usage: %s \n", prog); +} + +static inline int fdwrite(int fd, uint8_t *data, size_t len) +{ + ssize_t nr; + size_t l; + int ret = -1; + + for (l = 0; l < len; l += nr) { + nr = write(fd, data + l, len - l); + if (nr < 0) { + perror("Cannot write to bl31.img"); + goto out; + } + } + + ret = 0; +out: + return ret; +} + +int main(int argc, char **argv) +{ + int fin, fout, ret = -1; + ssize_t len; + uint32_t data; + uint8_t buf[BUFLEN]; + + if (argc != 3) { + usage(PROGNAME(argc, argv)); + goto out; + } + + fin = open(argv[1], O_RDONLY); + if (fin < 0) { + perror("Cannot open bl31.bin"); + goto out; + } + + fout = open(argv[2], O_WRONLY | O_CREAT, 0660); + if (fout < 0) { + perror("Cannot open bl31.img"); + goto closefin; + } + + data = htole32(BL31_MAGIC); + if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0) + goto closefout; + + lseek(fout, 8, SEEK_SET); + data = htole32(BL31_LOADADDR); + if (fdwrite(fout, (uint8_t *)&data, sizeof(data)) < 0) + goto closefout; + + lseek(fout, 0x200, SEEK_SET); + while ((len = read(fin, buf, sizeof(buf))) > 0) + if (fdwrite(fout, buf, len) < 0) + goto closefout; + if (len < 0) { + perror("Cannot read bl31.bin"); + goto closefout; + } + + ret = 0; + +closefout: + close(fout); +closefin: + close(fin); +out: + return ret; +} diff --git a/arm-trusted-firmware/tools/cert_create/Makefile b/arm-trusted-firmware/tools/cert_create/Makefile new file mode 100644 index 0000000..77d2007 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/Makefile @@ -0,0 +1,90 @@ +# +# Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT := none +V ?= 0 +DEBUG := 0 +CRTTOOL ?= cert_create${BIN_EXT} +BINARY := $(notdir ${CRTTOOL}) +OPENSSL_DIR := /usr +COT := tbbr + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +ifneq (${PLAT},none) +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk +PLAT_CERT_CREATE_HELPER_MK := ${PLAT_DIR}/cert_create_tbbr.mk +endif + +# Common source files. +OBJECTS := src/cert.o \ + src/cmd_opt.o \ + src/ext.o \ + src/key.o \ + src/main.o \ + src/sha.o + +# Chain of trust. +ifeq (${COT},tbbr) + include src/tbbr/tbbr.mk +else ifeq (${COT},dualroot) + include src/dualroot/cot.mk +else + $(error Unknown chain of trust ${COT}) +endif + +ifneq (,$(wildcard ${PLAT_CERT_CREATE_HELPER_MK})) +include ${PLAT_CERT_CREATE_HELPER_MK} +endif + +HOSTCCFLAGS := -Wall -std=c99 + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 +else + HOSTCCFLAGS += -O2 -DLOG_LEVEL=20 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCCFLAGS += ${DEFINES} + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INC_DIR += -I ./include -I ${PLAT_INCLUDE} -I ${OPENSSL_DIR}/include +LIB_DIR := -L ${OPENSSL_DIR}/lib +LIB := -lssl -lcrypto + +HOSTCC ?= gcc + +.PHONY: all clean realclean + +all: ${BINARY} + +${BINARY}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__; \ + const char platform_msg[] = "${PLAT_MSG}";' | \ + ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o + ${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@ + +%.o: %.c + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS}) + +realclean: clean + $(call SHELL_DELETE,${BINARY}) + diff --git a/arm-trusted-firmware/tools/cert_create/include/cert.h b/arm-trusted-firmware/tools/cert_create/include/cert.h new file mode 100644 index 0000000..e63b474 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/cert.h @@ -0,0 +1,76 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CERT_H +#define CERT_H + +#include +#include +#include "ext.h" +#include "key.h" + +#define CERT_MAX_EXT 9 + +/* + * This structure contains information related to the generation of the + * certificates. All these fields must be known and specified at build time + * except for the file name, which is picked up from the command line at + * run time. + * + * One instance of this structure must be created for each of the certificates + * present in the chain of trust. + * + * If the issuer points to this same instance, the generated certificate will + * be self-signed. + */ +typedef struct cert_s cert_t; +struct cert_s { + int id; /* Unique identifier */ + + const char *opt; /* Command line option to pass filename */ + const char *fn; /* Filename to save the certificate */ + const char *cn; /* Subject CN (Company Name) */ + const char *help_msg; /* Help message */ + + /* These fields must be defined statically */ + int key; /* Key to be signed */ + int issuer; /* Issuer certificate */ + int ext[CERT_MAX_EXT]; /* Certificate extensions */ + int num_ext; /* Number of extensions in the certificate */ + + X509 *x; /* X509 certificate container */ +}; + +/* Exported API */ +int cert_init(void); +cert_t *cert_get_by_opt(const char *opt); +int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value); +int cert_new( + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk); + +/* Macro to register the certificates used in the CoT */ +#define REGISTER_COT(_certs) \ + cert_t *def_certs = &_certs[0]; \ + const unsigned int num_def_certs = sizeof(_certs)/sizeof(_certs[0]) + +/* Macro to register the platform defined certificates used in the CoT */ +#define PLAT_REGISTER_COT(_pdef_certs) \ + cert_t *pdef_certs = &_pdef_certs[0]; \ + const unsigned int num_pdef_certs = sizeof(_pdef_certs)/sizeof(_pdef_certs[0]) + +/* Exported variables */ +extern cert_t *def_certs; +extern const unsigned int num_def_certs; +extern cert_t *pdef_certs; +extern const unsigned int num_pdef_certs; + +extern cert_t *certs; +extern unsigned int num_certs; +#endif /* CERT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/cmd_opt.h b/arm-trusted-firmware/tools/cert_create/include/cmd_opt.h new file mode 100644 index 0000000..10df00e --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/cmd_opt.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMD_OPT_H +#define CMD_OPT_H + +#include + +#define CMD_OPT_MAX_NUM 64 + +/* Supported long command line option types */ +enum { + CMD_OPT_CERT, + CMD_OPT_KEY, + CMD_OPT_EXT +}; + +/* Structure to define a command line option */ +typedef struct cmd_opt_s { + struct option long_opt; + const char *help_msg; +} cmd_opt_t; + +/* Exported API*/ +void cmd_opt_add(const cmd_opt_t *cmd_opt); +const struct option *cmd_opt_get_array(void); +const char *cmd_opt_get_name(int idx); +const char *cmd_opt_get_help_msg(int idx); + +#endif /* CMD_OPT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/debug.h b/arm-trusted-firmware/tools/cert_create/include/debug.h new file mode 100644 index 0000000..ee8f1f5 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/debug.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE 0 +#define LOG_LEVEL_ERROR 10 +#define LOG_LEVEL_NOTICE 20 +#define LOG_LEVEL_WARNING 30 +#define LOG_LEVEL_INFO 40 +#define LOG_LEVEL_VERBOSE 50 + + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) printf("NOTICE: " __VA_ARGS__) +#else +# define NOTICE(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) printf("ERROR: " __VA_ARGS__) +#else +# define ERROR(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) printf("WARNING: " __VA_ARGS__) +#else +# define WARN(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) printf("INFO: " __VA_ARGS__) +#else +# define INFO(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) printf("VERBOSE: " __VA_ARGS__) +#else +# define VERBOSE(...) +#endif + +#endif /* DEBUG_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h b/arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h new file mode 100644 index 0000000..3e50c89 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DUALROOT_COT_H +#define DUALROOT_COT_H + +/* Certificates. */ +enum { + /* Certificates owned by the silicon provider. */ + TRUSTED_BOOT_FW_CERT, + TRUSTED_KEY_CERT, + SCP_FW_KEY_CERT, + SCP_FW_CONTENT_CERT, + SOC_FW_KEY_CERT, + SOC_FW_CONTENT_CERT, + TRUSTED_OS_FW_KEY_CERT, + TRUSTED_OS_FW_CONTENT_CERT, + SIP_SECURE_PARTITION_CONTENT_CERT, + FWU_CERT, + + /* Certificates owned by the platform owner. */ + NON_TRUSTED_FW_CONTENT_CERT, + PLAT_SECURE_PARTITION_CONTENT_CERT, +}; + +/* Certificate extensions. */ +enum { + /* Extensions used in certificates owned by the silicon provider. */ + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT, + TRUSTED_WORLD_PK_EXT, + SCP_FW_CONTENT_CERT_PK_EXT, + SCP_FW_HASH_EXT, + SOC_FW_CONTENT_CERT_PK_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT, + + /* Extensions used in certificates owned by the platform owner. */ + PROT_PK_EXT, + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, +}; + +/* Keys. */ +enum { + /* Keys owned by the silicon provider. */ + ROT_KEY, + TRUSTED_WORLD_KEY, + SCP_FW_CONTENT_CERT_KEY, + SOC_FW_CONTENT_CERT_KEY, + TRUSTED_OS_FW_CONTENT_CERT_KEY, + + /* Keys owned by the platform owner. */ + PROT_KEY, +}; + +#endif /* DUALROOT_COT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/ext.h b/arm-trusted-firmware/tools/cert_create/include/ext.h new file mode 100644 index 0000000..e900a6d --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/ext.h @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef EXT_H +#define EXT_H + +#include +#include "key.h" + +/* Extension types supported */ +enum ext_type_e { + EXT_TYPE_NVCOUNTER, + EXT_TYPE_PKEY, + EXT_TYPE_HASH +}; + +/* NV-Counter types */ +enum nvctr_type_e { + NVCTR_TYPE_TFW, + NVCTR_TYPE_NTFW +}; + +/* + * This structure contains the relevant information to create the extensions + * to be included in the certificates. This extensions will be used to + * establish the chain of trust. + */ +typedef struct ext_s { + const char *oid; /* OID of the extension */ + const char *sn; /* Short name */ + const char *ln; /* Long description */ + const char *opt; /* Command line option to specify data */ + const char *help_msg; /* Help message */ + const char *arg; /* Argument passed from command line */ + int asn1_type; /* OpenSSL ASN1 type of the extension data. + * Supported types are: + * - V_ASN1_INTEGER + * - V_ASN1_OCTET_STRING + */ + int type; /* See ext_type_e */ + + /* Extension attributes (depends on extension type) */ + union { + int nvctr_type; /* See nvctr_type_e */ + int key; /* Index into array of registered public keys */ + } attr; + + int alias; /* In case OpenSSL provides an standard + * extension of the same type, add the new + * extension as an alias of this one + */ + + X509V3_EXT_METHOD method; /* This field may be used to define a custom + * function to print the contents of the + * extension */ + + int optional; /* This field may be used optionally to exclude an image */ +} ext_t; + +enum { + EXT_NON_CRIT = 0, + EXT_CRIT = !EXT_NON_CRIT, +}; + +/* Exported API */ +int ext_init(void); +ext_t *ext_get_by_opt(const char *opt); +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len); +X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value); +X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k); + +/* Macro to register the extensions used in the CoT */ +#define REGISTER_EXTENSIONS(_ext) \ + ext_t *def_extensions = &_ext[0]; \ + const unsigned int num_def_extensions = sizeof(_ext)/sizeof(_ext[0]) + +/* Macro to register the platform defined extensions used in the CoT */ +#define PLAT_REGISTER_EXTENSIONS(_pdef_ext) \ + ext_t *pdef_extensions = &_pdef_ext[0]; \ + const unsigned int num_pdef_extensions = sizeof(_pdef_ext)/sizeof(_pdef_ext[0]) + +/* Exported variables */ +extern ext_t *def_extensions; +extern const unsigned int num_def_extensions; +extern ext_t *pdef_extensions; +extern const unsigned int num_pdef_extensions; + +extern ext_t *extensions; +extern unsigned int num_extensions; +#endif /* EXT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/key.h b/arm-trusted-firmware/tools/cert_create/include/key.h new file mode 100644 index 0000000..128e7f7 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/key.h @@ -0,0 +1,92 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef KEY_H +#define KEY_H + +#include + +/* Error codes */ +enum { + KEY_ERR_NONE, + KEY_ERR_MALLOC, + KEY_ERR_FILENAME, + KEY_ERR_OPEN, + KEY_ERR_LOAD +}; + +/* Supported key algorithms */ +enum { + KEY_ALG_RSA, /* RSA PSS as defined by PKCS#1 v2.1 (default) */ +#ifndef OPENSSL_NO_EC + KEY_ALG_ECDSA, +#endif /* OPENSSL_NO_EC */ + KEY_ALG_MAX_NUM +}; + +/* Maximum number of valid key sizes per algorithm */ +#define KEY_SIZE_MAX_NUM 4 + +/* Supported hash algorithms */ +enum{ + HASH_ALG_SHA256, + HASH_ALG_SHA384, + HASH_ALG_SHA512, +}; + +/* Supported key sizes */ +/* NOTE: the first item in each array is the default key size */ +static const unsigned int KEY_SIZES[KEY_ALG_MAX_NUM][KEY_SIZE_MAX_NUM] = { + { 2048, 1024, 3072, 4096 }, /* KEY_ALG_RSA */ +#ifndef OPENSSL_NO_EC + {} /* KEY_ALG_ECDSA */ +#endif /* OPENSSL_NO_EC */ +}; + +/* + * This structure contains the relevant information to create the keys + * required to sign the certificates. + * + * One instance of this structure must be created for each key, usually in an + * array fashion. The filename is obtained at run time from the command line + * parameters + */ +typedef struct key_s { + int id; /* Key id */ + const char *opt; /* Command line option to specify a key */ + const char *help_msg; /* Help message */ + const char *desc; /* Key description (debug purposes) */ + char *fn; /* Filename to load/store the key */ + EVP_PKEY *key; /* Key container */ +} key_t; + +/* Exported API */ +int key_init(void); +key_t *key_get_by_opt(const char *opt); +int key_new(key_t *key); +int key_create(key_t *key, int type, int key_bits); +int key_load(key_t *key, unsigned int *err_code); +int key_store(key_t *key); + +/* Macro to register the keys used in the CoT */ +#define REGISTER_KEYS(_keys) \ + key_t *def_keys = &_keys[0]; \ + const unsigned int num_def_keys = sizeof(_keys)/sizeof(_keys[0]) + +/* Macro to register the platform defined keys used in the CoT */ +#define PLAT_REGISTER_KEYS(_pdef_keys) \ + key_t *pdef_keys = &_pdef_keys[0]; \ + const unsigned int num_pdef_keys = sizeof(_pdef_keys)/sizeof(_pdef_keys[0]) + +/* Exported variables */ +extern key_t *def_keys; +extern const unsigned int num_def_keys; +extern key_t *pdef_keys; +extern const unsigned int num_pdef_keys; + +extern key_t *keys; +extern unsigned int num_keys; +#endif /* KEY_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/sha.h b/arm-trusted-firmware/tools/cert_create/include/sha.h new file mode 100644 index 0000000..4c55f37 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/sha.h @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef SHA_H +#define SHA_H + +int sha_file(int md_alg, const char *filename, unsigned char *md); + +#endif /* SHA_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h new file mode 100644 index 0000000..e5fa3a2 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBB_CERT_H +#define TBB_CERT_H + +#include "cert.h" + +/* + * Enumerate the certificates that are used to establish the chain of trust + */ +enum { + TRUSTED_BOOT_FW_CERT, + TRUSTED_KEY_CERT, + SCP_FW_KEY_CERT, + SCP_FW_CONTENT_CERT, + SOC_FW_KEY_CERT, + SOC_FW_CONTENT_CERT, + TRUSTED_OS_FW_KEY_CERT, + TRUSTED_OS_FW_CONTENT_CERT, + NON_TRUSTED_FW_KEY_CERT, + NON_TRUSTED_FW_CONTENT_CERT, + SIP_SECURE_PARTITION_CONTENT_CERT, + FWU_CERT +}; + +#endif /* TBB_CERT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h new file mode 100644 index 0000000..692b2d4 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +#ifndef TBB_EXT_H +#define TBB_EXT_H + +#include "ext.h" + +/* TBBR extensions */ +enum { + TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT, + TRUSTED_WORLD_PK_EXT, + NON_TRUSTED_WORLD_PK_EXT, + SCP_FW_CONTENT_CERT_PK_EXT, + SCP_FW_HASH_EXT, + SOC_FW_CONTENT_CERT_PK_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT +}; + +#endif /* TBB_EXT_H */ diff --git a/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h new file mode 100644 index 0000000..47ad1de --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBB_KEY_H +#define TBB_KEY_H + +#include "key.h" + +/* + * Enumerate the keys that are used to establish the chain of trust + */ +enum { + ROT_KEY, + TRUSTED_WORLD_KEY, + NON_TRUSTED_WORLD_KEY, + SCP_FW_CONTENT_CERT_KEY, + SOC_FW_CONTENT_CERT_KEY, + TRUSTED_OS_FW_CONTENT_CERT_KEY, + NON_TRUSTED_FW_CONTENT_CERT_KEY +}; + +#endif /* TBB_KEY_H */ diff --git a/arm-trusted-firmware/tools/cert_create/src/cert.c b/arm-trusted-firmware/tools/cert_create/src/cert.c new file mode 100644 index 0000000..4b35d73 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/cert.c @@ -0,0 +1,274 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "key.h" +#include "sha.h" + +#define SERIAL_RAND_BITS 64 +#define RSA_SALT_LEN 32 + +cert_t *certs; +unsigned int num_certs; + +int rand_serial(BIGNUM *b, ASN1_INTEGER *ai) +{ + BIGNUM *btmp; + int ret = 0; + if (b) + btmp = b; + else + btmp = BN_new(); + + if (!btmp) + return 0; + + if (!BN_pseudo_rand(btmp, SERIAL_RAND_BITS, 0, 0)) + goto error; + if (ai && !BN_to_ASN1_INTEGER(btmp, ai)) + goto error; + + ret = 1; + +error: + + if (!b) + BN_free(btmp); + + return ret; +} +const EVP_MD *get_digest(int alg) +{ + switch (alg) { + case HASH_ALG_SHA256: + return EVP_sha256(); + case HASH_ALG_SHA384: + return EVP_sha384(); + case HASH_ALG_SHA512: + return EVP_sha512(); + default: + return NULL; + } +} + +int cert_add_ext(X509 *issuer, X509 *subject, int nid, char *value) +{ + X509_EXTENSION *ex; + X509V3_CTX ctx; + + /* No configuration database */ + X509V3_set_ctx_nodb(&ctx); + + /* Set issuer and subject certificates in the context */ + X509V3_set_ctx(&ctx, issuer, subject, NULL, NULL, 0); + ex = X509V3_EXT_conf_nid(NULL, &ctx, nid, value); + if (!ex) { + ERR_print_errors_fp(stdout); + return 0; + } + + X509_add_ext(subject, ex, -1); + X509_EXTENSION_free(ex); + + return 1; +} + +int cert_new( + int md_alg, + cert_t *cert, + int days, + int ca, + STACK_OF(X509_EXTENSION) * sk) +{ + EVP_PKEY *pkey = keys[cert->key].key; + cert_t *issuer_cert = &certs[cert->issuer]; + EVP_PKEY *ikey = keys[issuer_cert->key].key; + X509 *issuer = issuer_cert->x; + X509 *x; + X509_EXTENSION *ex; + X509_NAME *name; + ASN1_INTEGER *sno; + int i, num, rc = 0; + EVP_MD_CTX *mdCtx; + EVP_PKEY_CTX *pKeyCtx = NULL; + + /* Create the certificate structure */ + x = X509_new(); + if (!x) { + return 0; + } + + /* If we do not have a key, use the issuer key (the certificate will + * become self signed). This happens in content certificates. */ + if (!pkey) { + pkey = ikey; + } + + /* If we do not have an issuer certificate, use our own (the certificate + * will become self signed) */ + if (!issuer) { + issuer = x; + } + + mdCtx = EVP_MD_CTX_create(); + if (mdCtx == NULL) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* Sign the certificate with the issuer key */ + if (!EVP_DigestSignInit(mdCtx, &pKeyCtx, get_digest(md_alg), NULL, ikey)) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* + * Set additional parameters if issuing public key algorithm is RSA. + * This is not required for ECDSA. + */ + if (EVP_PKEY_base_id(ikey) == EVP_PKEY_RSA) { + if (!EVP_PKEY_CTX_set_rsa_padding(pKeyCtx, RSA_PKCS1_PSS_PADDING)) { + ERR_print_errors_fp(stdout); + goto END; + } + + if (!EVP_PKEY_CTX_set_rsa_pss_saltlen(pKeyCtx, RSA_SALT_LEN)) { + ERR_print_errors_fp(stdout); + goto END; + } + + if (!EVP_PKEY_CTX_set_rsa_mgf1_md(pKeyCtx, get_digest(md_alg))) { + ERR_print_errors_fp(stdout); + goto END; + } + } + + /* x509.v3 */ + X509_set_version(x, 2); + + /* Random serial number */ + sno = ASN1_INTEGER_new(); + rand_serial(NULL, sno); + X509_set_serialNumber(x, sno); + ASN1_INTEGER_free(sno); + + X509_gmtime_adj(X509_get_notBefore(x), 0); + X509_gmtime_adj(X509_get_notAfter(x), (long)60*60*24*days); + X509_set_pubkey(x, pkey); + + /* Subject name */ + name = X509_get_subject_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)cert->cn, -1, -1, 0); + X509_set_subject_name(x, name); + + /* Issuer name */ + name = X509_get_issuer_name(x); + X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, + (const unsigned char *)issuer_cert->cn, -1, -1, 0); + X509_set_issuer_name(x, name); + + /* Add various extensions: standard extensions */ + cert_add_ext(issuer, x, NID_subject_key_identifier, "hash"); + cert_add_ext(issuer, x, NID_authority_key_identifier, "keyid:always"); + if (ca) { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:TRUE"); + cert_add_ext(issuer, x, NID_key_usage, "keyCertSign"); + } else { + cert_add_ext(issuer, x, NID_basic_constraints, "CA:FALSE"); + } + + /* Add custom extensions */ + if (sk != NULL) { + num = sk_X509_EXTENSION_num(sk); + for (i = 0; i < num; i++) { + ex = sk_X509_EXTENSION_value(sk, i); + X509_add_ext(x, ex, -1); + } + } + + if (!X509_sign_ctx(x, mdCtx)) { + ERR_print_errors_fp(stdout); + goto END; + } + + /* X509 certificate signed successfully */ + rc = 1; + cert->x = x; + +END: + EVP_MD_CTX_destroy(mdCtx); + return rc; +} + +int cert_init(void) +{ + cmd_opt_t cmd_opt; + cert_t *cert; + unsigned int i; + + certs = malloc((num_def_certs * sizeof(def_certs[0])) +#ifdef PDEF_CERTS + + (num_pdef_certs * sizeof(pdef_certs[0])) +#endif + ); + if (certs == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&certs[0], &def_certs[0], + (num_def_certs * sizeof(def_certs[0]))); + +#ifdef PDEF_CERTS + memcpy(&certs[num_def_certs], &pdef_certs[0], + (num_pdef_certs * sizeof(pdef_certs[0]))); + + num_certs = num_def_certs + num_pdef_certs; +#else + num_certs = num_def_certs; +#endif + + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + cmd_opt.long_opt.name = cert->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_CERT; + cmd_opt.help_msg = cert->help_msg; + cmd_opt_add(&cmd_opt); + } + + return 0; +} + +cert_t *cert_get_by_opt(const char *opt) +{ + cert_t *cert; + unsigned int i; + + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + if (0 == strcmp(cert->opt, opt)) { + return cert; + } + } + + return NULL; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/cmd_opt.c b/arm-trusted-firmware/tools/cert_create/src/cmd_opt.c new file mode 100644 index 0000000..64180d1 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/cmd_opt.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "debug.h" + +/* Command line options */ +static struct option long_opt[CMD_OPT_MAX_NUM+1]; +static const char *help_msg[CMD_OPT_MAX_NUM+1]; +static int num_reg_opt; + +void cmd_opt_add(const cmd_opt_t *cmd_opt) +{ + assert(cmd_opt != NULL); + + if (num_reg_opt >= CMD_OPT_MAX_NUM) { + ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n"); + exit(1); + } + + long_opt[num_reg_opt].name = cmd_opt->long_opt.name; + long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg; + long_opt[num_reg_opt].flag = 0; + long_opt[num_reg_opt].val = cmd_opt->long_opt.val; + + help_msg[num_reg_opt] = cmd_opt->help_msg; + + num_reg_opt++; +} + +const struct option *cmd_opt_get_array(void) +{ + return long_opt; +} + +const char *cmd_opt_get_name(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return long_opt[idx].name; +} + +const char *cmd_opt_get_help_msg(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return help_msg[idx]; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c new file mode 100644 index 0000000..4dd4cf0 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c @@ -0,0 +1,583 @@ +/* + * Copyright (c) 2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "cert.h" +#include "ext.h" +#include "key.h" + +#include "dualroot/cot.h" + +/* + * Certificates used in the chain of trust. + * + * All certificates are self-signed so the issuer certificate field points to + * itself. + */ +static cert_t cot_certs[] = { + [TRUSTED_BOOT_FW_CERT] = { + .id = TRUSTED_BOOT_FW_CERT, + .opt = "tb-fw-cert", + .help_msg = "Trusted Boot FW Certificate (output file)", + .cn = "Trusted Boot FW Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_BOOT_FW_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT + }, + .num_ext = 5 + }, + + [TRUSTED_KEY_CERT] = { + .id = TRUSTED_KEY_CERT, + .opt = "trusted-key-cert", + .help_msg = "Trusted Key Certificate (output file)", + .cn = "Trusted Key Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_WORLD_PK_EXT, + }, + .num_ext = 2 + }, + + [SCP_FW_KEY_CERT] = { + .id = SCP_FW_KEY_CERT, + .opt = "scp-fw-key-cert", + .help_msg = "SCP Firmware Key Certificate (output file)", + .cn = "SCP Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SCP_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [SCP_FW_CONTENT_CERT] = { + .id = SCP_FW_CONTENT_CERT, + .opt = "scp-fw-cert", + .help_msg = "SCP Firmware Content Certificate (output file)", + .cn = "SCP Firmware Content Certificate", + .key = SCP_FW_CONTENT_CERT_KEY, + .issuer = SCP_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_HASH_EXT + }, + .num_ext = 2 + }, + + [SOC_FW_KEY_CERT] = { + .id = SOC_FW_KEY_CERT, + .opt = "soc-fw-key-cert", + .help_msg = "SoC Firmware Key Certificate (output file)", + .cn = "SoC Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SOC_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [SOC_FW_CONTENT_CERT] = { + .id = SOC_FW_CONTENT_CERT, + .opt = "soc-fw-cert", + .help_msg = "SoC Firmware Content Certificate (output file)", + .cn = "SoC Firmware Content Certificate", + .key = SOC_FW_CONTENT_CERT_KEY, + .issuer = SOC_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + + [TRUSTED_OS_FW_KEY_CERT] = { + .id = TRUSTED_OS_FW_KEY_CERT, + .opt = "tos-fw-key-cert", + .help_msg = "Trusted OS Firmware Key Certificate (output file)", + .cn = "Trusted OS Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = TRUSTED_OS_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + + [TRUSTED_OS_FW_CONTENT_CERT] = { + .id = TRUSTED_OS_FW_CONTENT_CERT, + .opt = "tos-fw-cert", + .help_msg = "Trusted OS Firmware Content Certificate (output file)", + .cn = "Trusted OS Firmware Content Certificate", + .key = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .issuer = TRUSTED_OS_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + }, + .num_ext = 5 + }, + + [SIP_SECURE_PARTITION_CONTENT_CERT] = { + .id = SIP_SECURE_PARTITION_CONTENT_CERT, + .opt = "sip-sp-cert", + .help_msg = "SiP owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "SiP owned Secure Partition Content Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SIP_SECURE_PARTITION_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + }, + .num_ext = 5 + }, + + [PLAT_SECURE_PARTITION_CONTENT_CERT] = { + .id = PLAT_SECURE_PARTITION_CONTENT_CERT, + .opt = "plat-sp-cert", + .help_msg = "Platform owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "Platform owned Secure Partition Content Certificate", + .key = PROT_KEY, + .issuer = PLAT_SECURE_PARTITION_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + PROT_PK_EXT, + }, + .num_ext = 6 + }, + + [FWU_CERT] = { + .id = FWU_CERT, + .opt = "fwu-cert", + .help_msg = "Firmware Update Certificate (output file)", + .cn = "Firmware Update Certificate", + .key = ROT_KEY, + .issuer = FWU_CERT, + .ext = { + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT + }, + .num_ext = 3 + }, + + [NON_TRUSTED_FW_CONTENT_CERT] = { + .id = NON_TRUSTED_FW_CONTENT_CERT, + .opt = "nt-fw-cert", + .help_msg = "Non-Trusted Firmware Content Certificate (output file)", + .cn = "Non-Trusted Firmware Content Certificate", + .key = PROT_KEY, + .issuer = NON_TRUSTED_FW_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + PROT_PK_EXT, + }, + .num_ext = 4 + }, +}; + +REGISTER_COT(cot_certs); + + +/* Certificate extensions. */ +static ext_t cot_ext[] = { + [TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = TRUSTED_FW_NVCOUNTER_OID, + .opt = "tfw-nvctr", + .help_msg = "Trusted Firmware Non-Volatile counter value", + .sn = "TrustedWorldNVCounter", + .ln = "Trusted World Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_TFW + }, + + [TRUSTED_BOOT_FW_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_HASH_OID, + .opt = "tb-fw", + .help_msg = "Trusted Boot Firmware image file", + .sn = "TrustedBootFirmwareHash", + .ln = "Trusted Boot Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID, + .opt = "tb-fw-config", + .help_msg = "Trusted Boot Firmware Config file", + .sn = "TrustedBootFirmwareConfigHash", + .ln = "Trusted Boot Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [HW_CONFIG_HASH_EXT] = { + .oid = HW_CONFIG_HASH_OID, + .opt = "hw-config", + .help_msg = "HW Config file", + .sn = "HWConfigHash", + .ln = "HW Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [FW_CONFIG_HASH_EXT] = { + .oid = FW_CONFIG_HASH_OID, + .opt = "fw-config", + .help_msg = "Firmware Config file", + .sn = "FirmwareConfigHash", + .ln = "Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_WORLD_PK_EXT] = { + .oid = TRUSTED_WORLD_PK_OID, + .sn = "TrustedWorldPublicKey", + .ln = "Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_WORLD_KEY + }, + + [SCP_FW_CONTENT_CERT_PK_EXT] = { + .oid = SCP_FW_CONTENT_CERT_PK_OID, + .sn = "SCPFirmwareContentCertPK", + .ln = "SCP Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SCP_FW_CONTENT_CERT_KEY + }, + + [SCP_FW_HASH_EXT] = { + .oid = SCP_FW_HASH_OID, + .opt = "scp-fw", + .help_msg = "SCP Firmware image file", + .sn = "SCPFirmwareHash", + .ln = "SCP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [SOC_FW_CONTENT_CERT_PK_EXT] = { + .oid = SOC_FW_CONTENT_CERT_PK_OID, + .sn = "SoCFirmwareContentCertPK", + .ln = "SoC Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SOC_FW_CONTENT_CERT_KEY + }, + + [SOC_AP_FW_HASH_EXT] = { + .oid = SOC_AP_FW_HASH_OID, + .opt = "soc-fw", + .help_msg = "SoC AP Firmware image file", + .sn = "SoCAPFirmwareHash", + .ln = "SoC AP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [SOC_FW_CONFIG_HASH_EXT] = { + .oid = SOC_FW_CONFIG_HASH_OID, + .opt = "soc-fw-config", + .help_msg = "SoC Firmware Config file", + .sn = "SocFirmwareConfigHash", + .ln = "SoC Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = { + .oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID, + .sn = "TrustedOSFirmwareContentCertPK", + .ln = "Trusted OS Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY + }, + + [TRUSTED_OS_FW_HASH_EXT] = { + .oid = TRUSTED_OS_FW_HASH_OID, + .opt = "tos-fw", + .help_msg = "Trusted OS image file", + .sn = "TrustedOSHash", + .ln = "Trusted OS hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [TRUSTED_OS_FW_EXTRA1_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA1_HASH_OID, + .opt = "tos-fw-extra1", + .help_msg = "Trusted OS Extra1 image file", + .sn = "TrustedOSExtra1Hash", + .ln = "Trusted OS Extra1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_EXTRA2_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA2_HASH_OID, + .opt = "tos-fw-extra2", + .help_msg = "Trusted OS Extra2 image file", + .sn = "TrustedOSExtra2Hash", + .ln = "Trusted OS Extra2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [TRUSTED_OS_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_OS_FW_CONFIG_HASH_OID, + .opt = "tos-fw-config", + .help_msg = "Trusted OS Firmware Config file", + .sn = "TrustedOSFirmwareConfigHash", + .ln = "Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [SP_PKG1_HASH_EXT] = { + .oid = SP_PKG1_HASH_OID, + .opt = "sp-pkg1", + .help_msg = "Secure Partition Package1 file", + .sn = "SPPkg1Hash", + .ln = "SP Pkg1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG2_HASH_EXT] = { + .oid = SP_PKG2_HASH_OID, + .opt = "sp-pkg2", + .help_msg = "Secure Partition Package2 file", + .sn = "SPPkg2Hash", + .ln = "SP Pkg2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG3_HASH_EXT] = { + .oid = SP_PKG3_HASH_OID, + .opt = "sp-pkg3", + .help_msg = "Secure Partition Package3 file", + .sn = "SPPkg3Hash", + .ln = "SP Pkg3 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG4_HASH_EXT] = { + .oid = SP_PKG4_HASH_OID, + .opt = "sp-pkg4", + .help_msg = "Secure Partition Package4 file", + .sn = "SPPkg4Hash", + .ln = "SP Pkg4 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG5_HASH_EXT] = { + .oid = SP_PKG5_HASH_OID, + .opt = "sp-pkg5", + .help_msg = "Secure Partition Package5 file", + .sn = "SPPkg5Hash", + .ln = "SP Pkg5 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG6_HASH_EXT] = { + .oid = SP_PKG6_HASH_OID, + .opt = "sp-pkg6", + .help_msg = "Secure Partition Package6 file", + .sn = "SPPkg6Hash", + .ln = "SP Pkg6 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG7_HASH_EXT] = { + .oid = SP_PKG7_HASH_OID, + .opt = "sp-pkg7", + .help_msg = "Secure Partition Package7 file", + .sn = "SPPkg7Hash", + .ln = "SP Pkg7 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG8_HASH_EXT] = { + .oid = SP_PKG8_HASH_OID, + .opt = "sp-pkg8", + .help_msg = "Secure Partition Package8 file", + .sn = "SPPkg8Hash", + .ln = "SP Pkg8 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [SCP_FWU_CFG_HASH_EXT] = { + .oid = SCP_FWU_CFG_HASH_OID, + .opt = "scp-fwu-cfg", + .help_msg = "SCP Firmware Update Config image file", + .sn = "SCPFWUpdateConfig", + .ln = "SCP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [AP_FWU_CFG_HASH_EXT] = { + .oid = AP_FWU_CFG_HASH_OID, + .opt = "ap-fwu-cfg", + .help_msg = "AP Firmware Update Config image file", + .sn = "APFWUpdateConfig", + .ln = "AP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [FWU_HASH_EXT] = { + .oid = FWU_HASH_OID, + .opt = "fwu", + .help_msg = "Firmware Updater image file", + .sn = "FWUpdaterHash", + .ln = "Firmware Updater hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + + [PROT_PK_EXT] = { + .oid = PROT_PK_OID, + .sn = "PlatformRoTKey", + .ln = "Platform Root of Trust Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = PROT_KEY + }, + + [NON_TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = NON_TRUSTED_FW_NVCOUNTER_OID, + .opt = "ntfw-nvctr", + .help_msg = "Non-Trusted Firmware Non-Volatile counter value", + .sn = "NormalWorldNVCounter", + .ln = "Non-Trusted Firmware Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_NTFW + }, + + [NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = { + .oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID, + .opt = "nt-fw", + .help_msg = "Non-Trusted World Bootloader image file", + .sn = "NonTrustedWorldBootloaderHash", + .ln = "Non-Trusted World hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + + [NON_TRUSTED_FW_CONFIG_HASH_EXT] = { + .oid = NON_TRUSTED_FW_CONFIG_HASH_OID, + .opt = "nt-fw-config", + .help_msg = "Non Trusted OS Firmware Config file", + .sn = "NonTrustedOSFirmwareConfigHash", + .ln = "Non-Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, +}; + +REGISTER_EXTENSIONS(cot_ext); + + +/* Keys used to establish the chain of trust. */ +static key_t cot_keys[] = { + [ROT_KEY] = { + .id = ROT_KEY, + .opt = "rot-key", + .help_msg = "Root Of Trust key (input/output file)", + .desc = "Root Of Trust key" + }, + + [TRUSTED_WORLD_KEY] = { + .id = TRUSTED_WORLD_KEY, + .opt = "trusted-world-key", + .help_msg = "Trusted World key (input/output file)", + .desc = "Trusted World key" + }, + + [SCP_FW_CONTENT_CERT_KEY] = { + .id = SCP_FW_CONTENT_CERT_KEY, + .opt = "scp-fw-key", + .help_msg = "SCP Firmware Content Certificate key (input/output file)", + .desc = "SCP Firmware Content Certificate key" + }, + + [SOC_FW_CONTENT_CERT_KEY] = { + .id = SOC_FW_CONTENT_CERT_KEY, + .opt = "soc-fw-key", + .help_msg = "SoC Firmware Content Certificate key (input/output file)", + .desc = "SoC Firmware Content Certificate key" + }, + + [TRUSTED_OS_FW_CONTENT_CERT_KEY] = { + .id = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .opt = "tos-fw-key", + .help_msg = "Trusted OS Firmware Content Certificate key (input/output file)", + .desc = "Trusted OS Firmware Content Certificate key" + }, + + [PROT_KEY] = { + .id = PROT_KEY, + .opt = "prot-key", + .help_msg = "Platform Root of Trust key", + .desc = "Platform Root of Trust key" + }, +}; + +REGISTER_KEYS(cot_keys); diff --git a/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk new file mode 100644 index 0000000..a572484 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/dualroot/cot.mk @@ -0,0 +1,10 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +PLAT_MSG := Dual root of trust +PLAT_INCLUDE := ../../include/tools_share + +OBJECTS += src/dualroot/cot.o diff --git a/arm-trusted-firmware/tools/cert_create/src/ext.c b/arm-trusted-firmware/tools/cert_create/src/ext.c new file mode 100644 index 0000000..2882123 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/ext.c @@ -0,0 +1,317 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "cmd_opt.h" +#include "debug.h" +#include "ext.h" + +ext_t *extensions; +unsigned int num_extensions; + +DECLARE_ASN1_ITEM(ASN1_INTEGER) +DECLARE_ASN1_ITEM(X509_ALGOR) +DECLARE_ASN1_ITEM(ASN1_OCTET_STRING) + +typedef struct { + X509_ALGOR *hashAlgorithm; + ASN1_OCTET_STRING *dataHash; +} HASH; + +ASN1_SEQUENCE(HASH) = { + ASN1_SIMPLE(HASH, hashAlgorithm, X509_ALGOR), + ASN1_SIMPLE(HASH, dataHash, ASN1_OCTET_STRING), +} ASN1_SEQUENCE_END(HASH) + +DECLARE_ASN1_FUNCTIONS(HASH) +IMPLEMENT_ASN1_FUNCTIONS(HASH) + +/* + * This function adds the CoT extensions to the internal extension list + * maintained by OpenSSL so they can be used later. + * + * It also initializes the methods to print the contents of the extension. If an + * alias is specified in the CoT extension, we reuse the methods of the alias. + * Otherwise, only methods for V_ASN1_INTEGER and V_ASN1_OCTET_STRING are + * provided. Any other type will be printed as a raw ascii string. + * + * Return: 0 = success, Otherwise: error + */ +int ext_init(void) +{ + cmd_opt_t cmd_opt; + ext_t *ext; + X509V3_EXT_METHOD *m; + int nid, ret; + unsigned int i; + + extensions = malloc((num_def_extensions * sizeof(def_extensions[0])) +#ifdef PDEF_EXTS + + (num_pdef_extensions * sizeof(pdef_extensions[0])) +#endif + ); + if (extensions == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&extensions[0], &def_extensions[0], + (num_def_extensions * sizeof(def_extensions[0]))); +#ifdef PDEF_EXTS + memcpy(&extensions[num_def_extensions], &pdef_extensions[0], + (num_pdef_extensions * sizeof(pdef_extensions[0]))); + num_extensions = num_def_extensions + num_pdef_extensions; +#else + num_extensions = num_def_extensions; +#endif + + for (i = 0; i < num_extensions; i++) { + ext = &extensions[i]; + /* Register command line option */ + if (ext->opt) { + cmd_opt.long_opt.name = ext->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_EXT; + cmd_opt.help_msg = ext->help_msg; + cmd_opt_add(&cmd_opt); + } + /* Register the extension OID in OpenSSL */ + if (ext->oid == NULL) { + continue; + } + nid = OBJ_create(ext->oid, ext->sn, ext->ln); + if (ext->alias) { + X509V3_EXT_add_alias(nid, ext->alias); + } else { + m = &ext->method; + memset(m, 0x0, sizeof(X509V3_EXT_METHOD)); + switch (ext->asn1_type) { + case V_ASN1_INTEGER: + m->it = ASN1_ITEM_ref(ASN1_INTEGER); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_INTEGER; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_INTEGER; + break; + case V_ASN1_OCTET_STRING: + m->it = ASN1_ITEM_ref(ASN1_OCTET_STRING); + m->i2s = (X509V3_EXT_I2S)i2s_ASN1_OCTET_STRING; + m->s2i = (X509V3_EXT_S2I)s2i_ASN1_OCTET_STRING; + break; + default: + continue; + } + m->ext_nid = nid; + ret = X509V3_EXT_add(m); + if (!ret) { + ERR_print_errors_fp(stdout); + return 1; + } + } + } + return 0; +} + +/* + * Create a new extension + * + * Extension ::= SEQUENCE { + * id OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * value OCTET STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * data: extension data. This data will be encapsulated in an Octet String + * + * Return: Extension address, NULL if error + */ +static +X509_EXTENSION *ext_new(int nid, int crit, unsigned char *data, int len) +{ + X509_EXTENSION *ex; + ASN1_OCTET_STRING *ext_data; + + /* Octet string containing the extension data */ + ext_data = ASN1_OCTET_STRING_new(); + ASN1_OCTET_STRING_set(ext_data, data, len); + + /* Create the extension */ + ex = X509_EXTENSION_create_by_NID(NULL, nid, crit, ext_data); + + /* The extension makes a copy of the data, so we can free this object */ + ASN1_OCTET_STRING_free(ext_data); + + return ex; +} + +/* + * Creates a x509v3 extension containing a hash + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm AlgorithmIdentifier, + * digest OCTET STRING + * } + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL + * } + * + * Parameters: + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * md: hash algorithm + * buf: pointer to the buffer that contains the hash + * len: size of the hash in bytes + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_hash(int nid, int crit, const EVP_MD *md, + unsigned char *buf, size_t len) +{ + X509_EXTENSION *ex; + HASH *hash; + ASN1_OBJECT *algorithm; + unsigned char *p = NULL; + int sz; + + /* HASH structure containing algorithm + hash */ + hash = HASH_new(); + if (hash == NULL) { + return NULL; + } + + /* OBJECT_IDENTIFIER with hash algorithm */ + algorithm = OBJ_nid2obj(EVP_MD_type(md)); + if (algorithm == NULL) { + HASH_free(hash); + return NULL; + } + + /* Create X509_ALGOR */ + hash->hashAlgorithm->algorithm = algorithm; + hash->hashAlgorithm->parameter = ASN1_TYPE_new(); + ASN1_TYPE_set(hash->hashAlgorithm->parameter, V_ASN1_NULL, NULL); + + /* OCTET_STRING with the actual hash */ + ASN1_OCTET_STRING_set(hash->dataHash, buf, len); + + /* DER encoded HASH */ + sz = i2d_HASH(hash, &p); + if ((sz <= 0) || (p == NULL)) { + HASH_free(hash); + return NULL; + } + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + OPENSSL_free(p); + HASH_free(hash); + + return ex; +} + +/* + * Creates a x509v3 extension containing a nvcounter encapsulated in an ASN1 + * Integer + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * value: nvcounter value + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_nvcounter(int nid, int crit, int value) +{ + X509_EXTENSION *ex; + ASN1_INTEGER *counter; + unsigned char *p = NULL; + int sz; + + /* Encode counter */ + counter = ASN1_INTEGER_new(); + ASN1_INTEGER_set(counter, value); + sz = i2d_ASN1_INTEGER(counter, &p); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Free objects */ + OPENSSL_free(p); + ASN1_INTEGER_free(counter); + + return ex; +} + +/* + * Creates a x509v3 extension containing a public key in DER format: + * + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + * + * Parameters: + * pex: OpenSSL extension pointer (output parameter) + * nid: extension identifier + * crit: extension critical (EXT_NON_CRIT, EXT_CRIT) + * k: key + * + * Return: Extension address, NULL if error + */ +X509_EXTENSION *ext_new_key(int nid, int crit, EVP_PKEY *k) +{ + X509_EXTENSION *ex; + unsigned char *p; + int sz; + + /* Encode key */ + BIO *mem = BIO_new(BIO_s_mem()); + if (i2d_PUBKEY_bio(mem, k) <= 0) { + ERR_print_errors_fp(stderr); + return NULL; + } + p = (unsigned char *)OPENSSL_malloc(4096); + sz = BIO_read(mem, p, 4096); + + /* Create the extension */ + ex = ext_new(nid, crit, p, sz); + + /* Clean up */ + BIO_free(mem); + OPENSSL_free(p); + + return ex; +} + +ext_t *ext_get_by_opt(const char *opt) +{ + ext_t *ext; + unsigned int i; + + /* Sequential search. This is not a performance concern since the number + * of extensions is bounded and the code runs on a host machine */ + for (i = 0; i < num_extensions; i++) { + ext = &extensions[i]; + if (ext->opt && !strcmp(ext->opt, opt)) { + return ext; + } + } + + return NULL; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/key.c b/arm-trusted-firmware/tools/cert_create/src/key.c new file mode 100644 index 0000000..6435975 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/key.c @@ -0,0 +1,240 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "key.h" +#include "sha.h" + +#define MAX_FILENAME_LEN 1024 + +key_t *keys; +unsigned int num_keys; + +/* + * Create a new key container + */ +int key_new(key_t *key) +{ + /* Create key pair container */ + key->key = EVP_PKEY_new(); + if (key->key == NULL) { + return 0; + } + + return 1; +} + +static int key_create_rsa(key_t *key, int key_bits) +{ + BIGNUM *e; + RSA *rsa = NULL; + + e = BN_new(); + if (e == NULL) { + printf("Cannot create RSA exponent\n"); + goto err; + } + + if (!BN_set_word(e, RSA_F4)) { + printf("Cannot assign RSA exponent\n"); + goto err; + } + + rsa = RSA_new(); + if (rsa == NULL) { + printf("Cannot create RSA key\n"); + goto err; + } + + if (!RSA_generate_key_ex(rsa, key_bits, e, NULL)) { + printf("Cannot generate RSA key\n"); + goto err; + } + + if (!EVP_PKEY_assign_RSA(key->key, rsa)) { + printf("Cannot assign RSA key\n"); + goto err; + } + + BN_free(e); + return 1; +err: + RSA_free(rsa); + BN_free(e); + return 0; +} + +#ifndef OPENSSL_NO_EC +static int key_create_ecdsa(key_t *key, int key_bits) +{ + EC_KEY *ec; + + ec = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + if (ec == NULL) { + printf("Cannot create EC key\n"); + goto err; + } + if (!EC_KEY_generate_key(ec)) { + printf("Cannot generate EC key\n"); + goto err; + } + EC_KEY_set_flags(ec, EC_PKEY_NO_PARAMETERS); + EC_KEY_set_asn1_flag(ec, OPENSSL_EC_NAMED_CURVE); + if (!EVP_PKEY_assign_EC_KEY(key->key, ec)) { + printf("Cannot assign EC key\n"); + goto err; + } + + return 1; +err: + EC_KEY_free(ec); + return 0; +} +#endif /* OPENSSL_NO_EC */ + +typedef int (*key_create_fn_t)(key_t *key, int key_bits); +static const key_create_fn_t key_create_fn[KEY_ALG_MAX_NUM] = { + key_create_rsa, /* KEY_ALG_RSA */ +#ifndef OPENSSL_NO_EC + key_create_ecdsa, /* KEY_ALG_ECDSA */ +#endif /* OPENSSL_NO_EC */ +}; + +int key_create(key_t *key, int type, int key_bits) +{ + if (type >= KEY_ALG_MAX_NUM) { + printf("Invalid key type\n"); + return 0; + } + + if (key_create_fn[type]) { + return key_create_fn[type](key, key_bits); + } + + return 0; +} + +int key_load(key_t *key, unsigned int *err_code) +{ + FILE *fp; + EVP_PKEY *k; + + if (key->fn) { + /* Load key from file */ + fp = fopen(key->fn, "r"); + if (fp) { + k = PEM_read_PrivateKey(fp, &key->key, NULL, NULL); + fclose(fp); + if (k) { + *err_code = KEY_ERR_NONE; + return 1; + } else { + ERROR("Cannot load key from %s\n", key->fn); + *err_code = KEY_ERR_LOAD; + } + } else { + WARN("Cannot open file %s\n", key->fn); + *err_code = KEY_ERR_OPEN; + } + } else { + WARN("Key filename not specified\n"); + *err_code = KEY_ERR_FILENAME; + } + + return 0; +} + +int key_store(key_t *key) +{ + FILE *fp; + + if (key->fn) { + fp = fopen(key->fn, "w"); + if (fp) { + PEM_write_PrivateKey(fp, key->key, + NULL, NULL, 0, NULL, NULL); + fclose(fp); + return 1; + } else { + ERROR("Cannot create file %s\n", key->fn); + } + } else { + ERROR("Key filename not specified\n"); + } + + return 0; +} + +int key_init(void) +{ + cmd_opt_t cmd_opt; + key_t *key; + unsigned int i; + + keys = malloc((num_def_keys * sizeof(def_keys[0])) +#ifdef PDEF_KEYS + + (num_pdef_keys * sizeof(pdef_keys[0])) +#endif + ); + + if (keys == NULL) { + ERROR("%s:%d Failed to allocate memory.\n", __func__, __LINE__); + return 1; + } + + memcpy(&keys[0], &def_keys[0], (num_def_keys * sizeof(def_keys[0]))); +#ifdef PDEF_KEYS + memcpy(&keys[num_def_keys], &pdef_keys[0], + (num_pdef_keys * sizeof(pdef_keys[0]))); + + num_keys = num_def_keys + num_pdef_keys; +#else + num_keys = num_def_keys; +#endif + ; + + for (i = 0; i < num_keys; i++) { + key = &keys[i]; + if (key->opt != NULL) { + cmd_opt.long_opt.name = key->opt; + cmd_opt.long_opt.has_arg = required_argument; + cmd_opt.long_opt.flag = NULL; + cmd_opt.long_opt.val = CMD_OPT_KEY; + cmd_opt.help_msg = key->help_msg; + cmd_opt_add(&cmd_opt); + } + } + + return 0; +} + +key_t *key_get_by_opt(const char *opt) +{ + key_t *key; + unsigned int i; + + /* Sequential search. This is not a performance concern since the number + * of keys is bounded and the code runs on a host machine */ + for (i = 0; i < num_keys; i++) { + key = &keys[i]; + if (0 == strcmp(key->opt, opt)) { + return key; + } + } + + return NULL; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/main.c b/arm-trusted-firmware/tools/cert_create/src/main.c new file mode 100644 index 0000000..b39378c --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/main.c @@ -0,0 +1,634 @@ +/* + * Copyright (c) 2015-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include + +#include "cert.h" +#include "cmd_opt.h" +#include "debug.h" +#include "ext.h" +#include "key.h" +#include "sha.h" + +/* + * Helper macros to simplify the code. This macro assigns the return value of + * the 'fn' function to 'v' and exits if the value is NULL. + */ +#define CHECK_NULL(v, fn) \ + do { \ + v = fn; \ + if (v == NULL) { \ + ERROR("NULL object at %s:%d\n", __FILE__, __LINE__); \ + exit(1); \ + } \ + } while (0) + +/* + * This macro assigns the NID corresponding to 'oid' to 'v' and exits if the + * NID is undefined. + */ +#define CHECK_OID(v, oid) \ + do { \ + v = OBJ_txt2nid(oid); \ + if (v == NID_undef) { \ + ERROR("Cannot find extension %s\n", oid); \ + exit(1); \ + } \ + } while (0) + +#define MAX_FILENAME_LEN 1024 +#define VAL_DAYS 7300 +#define ID_TO_BIT_MASK(id) (1 << id) +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) +#define HELP_OPT_MAX_LEN 128 + +/* Global options */ +static int key_alg; +static int hash_alg; +static int key_size; +static int new_keys; +static int save_keys; +static int print_cert; + +/* Info messages created in the Makefile */ +extern const char build_msg[]; +extern const char platform_msg[]; + + +static char *strdup(const char *str) +{ + int n = strlen(str) + 1; + char *dup = malloc(n); + if (dup) { + strcpy(dup, str); + } + return dup; +} + +static const char *key_algs_str[] = { + [KEY_ALG_RSA] = "rsa", +#ifndef OPENSSL_NO_EC + [KEY_ALG_ECDSA] = "ecdsa" +#endif /* OPENSSL_NO_EC */ +}; + +static const char *hash_algs_str[] = { + [HASH_ALG_SHA256] = "sha256", + [HASH_ALG_SHA384] = "sha384", + [HASH_ALG_SHA512] = "sha512", +}; + +static void print_help(const char *cmd, const struct option *long_opt) +{ + int rem, i = 0; + const struct option *opt; + char line[HELP_OPT_MAX_LEN]; + char *p; + + assert(cmd != NULL); + assert(long_opt != NULL); + + printf("\n\n"); + printf("The certificate generation tool loads the binary images and\n" + "optionally the RSA keys, and outputs the key and content\n" + "certificates properly signed to implement the chain of trust.\n" + "If keys are provided, they must be in PEM format.\n" + "Certificates are generated in DER format.\n"); + printf("\n"); + printf("Usage:\n"); + printf("\t%s [OPTIONS]\n\n", cmd); + + printf("Available options:\n"); + opt = long_opt; + while (opt->name) { + p = line; + rem = HELP_OPT_MAX_LEN; + if (isalpha(opt->val)) { + /* Short format */ + sprintf(p, "-%c,", (char)opt->val); + p += 3; + rem -= 3; + } + snprintf(p, rem, "--%s %s", opt->name, + (opt->has_arg == required_argument) ? "" : ""); + printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); + opt++; + i++; + } + printf("\n"); +} + +static int get_key_alg(const char *key_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (0 == strcmp(key_alg_str, key_algs_str[i])) { + return i; + } + } + + return -1; +} + +static int get_key_size(const char *key_size_str) +{ + char *end; + long key_size; + + key_size = strtol(key_size_str, &end, 10); + if (*end != '\0') + return -1; + + return key_size; +} + +static int get_hash_alg(const char *hash_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(hash_algs_str) ; i++) { + if (0 == strcmp(hash_alg_str, hash_algs_str[i])) { + return i; + } + } + + return -1; +} + +static void check_cmd_params(void) +{ + cert_t *cert; + ext_t *ext; + key_t *key; + int i, j; + bool valid_size; + + /* Only save new keys */ + if (save_keys && !new_keys) { + ERROR("Only new keys can be saved to disk\n"); + exit(1); + } + + /* Validate key-size */ + valid_size = false; + for (i = 0; i < KEY_SIZE_MAX_NUM; i++) { + if (key_size == KEY_SIZES[key_alg][i]) { + valid_size = true; + break; + } + } + if (!valid_size) { + ERROR("'%d' is not a valid key size for '%s'\n", + key_size, key_algs_str[key_alg]); + NOTICE("Valid sizes are: "); + for (i = 0; i < KEY_SIZE_MAX_NUM && + KEY_SIZES[key_alg][i] != 0; i++) { + printf("%d ", KEY_SIZES[key_alg][i]); + } + printf("\n"); + exit(1); + } + + /* Check that all required options have been specified in the + * command line */ + for (i = 0; i < num_certs; i++) { + cert = &certs[i]; + if (cert->fn == NULL) { + /* Certificate not requested. Skip to the next one */ + continue; + } + + /* Check that all parameters required to create this certificate + * have been specified in the command line */ + for (j = 0; j < cert->num_ext; j++) { + ext = &extensions[cert->ext[j]]; + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + /* Counter value must be specified */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Value for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + case EXT_TYPE_PKEY: + /* Key filename must be specified */ + key = &keys[ext->attr.key]; + if (!new_keys && key->fn == NULL) { + ERROR("Key '%s' required by '%s' not " + "specified\n", key->desc, + cert->cn); + exit(1); + } + break; + case EXT_TYPE_HASH: + /* + * Binary image must be specified + * unless it is explicitly made optional. + */ + if ((!ext->optional) && (ext->arg == NULL)) { + ERROR("Image for '%s' not specified\n", + ext->ln); + exit(1); + } + break; + default: + ERROR("Unknown extension type '%d' in '%s'\n", + ext->type, ext->ln); + exit(1); + break; + } + } + } +} + +/* Common command line options */ +static const cmd_opt_t common_cmd_opt[] = { + { + { "help", no_argument, NULL, 'h' }, + "Print this message and exit" + }, + { + { "key-alg", required_argument, NULL, 'a' }, + "Key algorithm: 'rsa' (default)- RSAPSS scheme as per PKCS#1 v2.1, 'ecdsa'" + }, + { + { "key-size", required_argument, NULL, 'b' }, + "Key size (for supported algorithms)." + }, + { + { "hash-alg", required_argument, NULL, 's' }, + "Hash algorithm : 'sha256' (default), 'sha384', 'sha512'" + }, + { + { "save-keys", no_argument, NULL, 'k' }, + "Save key pairs into files. Filenames must be provided" + }, + { + { "new-keys", no_argument, NULL, 'n' }, + "Generate new key pairs if no key files are provided" + }, + { + { "print-cert", no_argument, NULL, 'p' }, + "Print the certificates in the standard output" + } +}; + +int main(int argc, char *argv[]) +{ + STACK_OF(X509_EXTENSION) * sk; + X509_EXTENSION *cert_ext = NULL; + ext_t *ext; + key_t *key; + cert_t *cert; + FILE *file; + int i, j, ext_nid, nvctr; + int c, opt_idx = 0; + const struct option *cmd_opt; + const char *cur_opt; + unsigned int err_code; + unsigned char md[SHA512_DIGEST_LENGTH]; + unsigned int md_len; + const EVP_MD *md_info; + + NOTICE("CoT Generation Tool: %s\n", build_msg); + NOTICE("Target platform: %s\n", platform_msg); + + /* Set default options */ + key_alg = KEY_ALG_RSA; + hash_alg = HASH_ALG_SHA256; + key_size = -1; + + /* Add common command line options */ + for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { + cmd_opt_add(&common_cmd_opt[i]); + } + + /* Initialize the certificates */ + if (cert_init() != 0) { + ERROR("Cannot initialize certificates\n"); + exit(1); + } + + /* Initialize the keys */ + if (key_init() != 0) { + ERROR("Cannot initialize keys\n"); + exit(1); + } + + /* Initialize the new types and register OIDs for the extensions */ + if (ext_init() != 0) { + ERROR("Cannot initialize extensions\n"); + exit(1); + } + + /* Get the command line options populated during the initialization */ + cmd_opt = cmd_opt_get_array(); + + while (1) { + /* getopt_long stores the option index here. */ + c = getopt_long(argc, argv, "a:b:hknps:", cmd_opt, &opt_idx); + + /* Detect the end of the options. */ + if (c == -1) { + break; + } + + switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; + case 'b': + key_size = get_key_size(optarg); + if (key_size <= 0) { + ERROR("Invalid key size '%s'\n", optarg); + exit(1); + } + break; + case 'h': + print_help(argv[0], cmd_opt); + exit(0); + case 'k': + save_keys = 1; + break; + case 'n': + new_keys = 1; + break; + case 'p': + print_cert = 1; + break; + case 's': + hash_alg = get_hash_alg(optarg); + if (hash_alg < 0) { + ERROR("Invalid hash algorithm '%s'\n", optarg); + exit(1); + } + break; + case CMD_OPT_EXT: + cur_opt = cmd_opt_get_name(opt_idx); + ext = ext_get_by_opt(cur_opt); + ext->arg = strdup(optarg); + break; + case CMD_OPT_KEY: + cur_opt = cmd_opt_get_name(opt_idx); + key = key_get_by_opt(cur_opt); + key->fn = strdup(optarg); + break; + case CMD_OPT_CERT: + cur_opt = cmd_opt_get_name(opt_idx); + cert = cert_get_by_opt(cur_opt); + cert->fn = strdup(optarg); + break; + case '?': + default: + print_help(argv[0], cmd_opt); + exit(1); + } + } + + /* Select a reasonable default key-size */ + if (key_size == -1) { + key_size = KEY_SIZES[key_alg][0]; + } + + /* Check command line arguments */ + check_cmd_params(); + + /* Indicate SHA as image hash algorithm in the certificate + * extension */ + if (hash_alg == HASH_ALG_SHA384) { + md_info = EVP_sha384(); + md_len = SHA384_DIGEST_LENGTH; + } else if (hash_alg == HASH_ALG_SHA512) { + md_info = EVP_sha512(); + md_len = SHA512_DIGEST_LENGTH; + } else { + md_info = EVP_sha256(); + md_len = SHA256_DIGEST_LENGTH; + } + + /* Load private keys from files (or generate new ones) */ + for (i = 0 ; i < num_keys ; i++) { + if (!key_new(&keys[i])) { + ERROR("Failed to allocate key container\n"); + exit(1); + } + + /* First try to load the key from disk */ + if (key_load(&keys[i], &err_code)) { + /* Key loaded successfully */ + continue; + } + + /* Key not loaded. Check the error code */ + if (err_code == KEY_ERR_LOAD) { + /* File exists, but it does not contain a valid private + * key. Abort. */ + ERROR("Error loading '%s'\n", keys[i].fn); + exit(1); + } + + /* File does not exist, could not be opened or no filename was + * given */ + if (new_keys) { + /* Try to create a new key */ + NOTICE("Creating new key for '%s'\n", keys[i].desc); + if (!key_create(&keys[i], key_alg, key_size)) { + ERROR("Error creating key '%s'\n", keys[i].desc); + exit(1); + } + } else { + if (err_code == KEY_ERR_OPEN) { + ERROR("Error opening '%s'\n", keys[i].fn); + } else { + ERROR("Key '%s' not specified\n", keys[i].desc); + } + exit(1); + } + } + + /* Create the certificates */ + for (i = 0 ; i < num_certs ; i++) { + + cert = &certs[i]; + + if (cert->fn == NULL) { + /* Certificate not requested. Skip to the next one */ + continue; + } + + /* Create a new stack of extensions. This stack will be used + * to create the certificate */ + CHECK_NULL(sk, sk_X509_EXTENSION_new_null()); + + for (j = 0 ; j < cert->num_ext ; j++) { + + ext = &extensions[cert->ext[j]]; + + /* Get OpenSSL internal ID for this extension */ + CHECK_OID(ext_nid, ext->oid); + + /* + * Three types of extensions are currently supported: + * - EXT_TYPE_NVCOUNTER + * - EXT_TYPE_HASH + * - EXT_TYPE_PKEY + */ + switch (ext->type) { + case EXT_TYPE_NVCOUNTER: + if (ext->optional && ext->arg == NULL) { + /* Skip this NVCounter */ + continue; + } else { + /* Checked by `check_cmd_params` */ + assert(ext->arg != NULL); + nvctr = atoi(ext->arg); + CHECK_NULL(cert_ext, ext_new_nvcounter(ext_nid, + EXT_CRIT, nvctr)); + } + break; + case EXT_TYPE_HASH: + if (ext->arg == NULL) { + if (ext->optional) { + /* Include a hash filled with zeros */ + memset(md, 0x0, SHA512_DIGEST_LENGTH); + } else { + /* Do not include this hash in the certificate */ + continue; + } + } else { + /* Calculate the hash of the file */ + if (!sha_file(hash_alg, ext->arg, md)) { + ERROR("Cannot calculate hash of %s\n", + ext->arg); + exit(1); + } + } + CHECK_NULL(cert_ext, ext_new_hash(ext_nid, + EXT_CRIT, md_info, md, + md_len)); + break; + case EXT_TYPE_PKEY: + CHECK_NULL(cert_ext, ext_new_key(ext_nid, + EXT_CRIT, keys[ext->attr.key].key)); + break; + default: + ERROR("Unknown extension type '%d' in %s\n", + ext->type, cert->cn); + exit(1); + } + + /* Push the extension into the stack */ + sk_X509_EXTENSION_push(sk, cert_ext); + } + + /* Create certificate. Signed with corresponding key */ + if (!cert_new(hash_alg, cert, VAL_DAYS, 0, sk)) { + ERROR("Cannot create %s\n", cert->cn); + exit(1); + } + + for (cert_ext = sk_X509_EXTENSION_pop(sk); cert_ext != NULL; + cert_ext = sk_X509_EXTENSION_pop(sk)) { + X509_EXTENSION_free(cert_ext); + } + + sk_X509_EXTENSION_free(sk); + } + + + /* Print the certificates */ + if (print_cert) { + for (i = 0 ; i < num_certs ; i++) { + if (!certs[i].x) { + continue; + } + printf("\n\n=====================================\n\n"); + X509_print_fp(stdout, certs[i].x); + } + } + + /* Save created certificates to files */ + for (i = 0 ; i < num_certs ; i++) { + if (certs[i].x && certs[i].fn) { + file = fopen(certs[i].fn, "w"); + if (file != NULL) { + i2d_X509_fp(file, certs[i].x); + fclose(file); + } else { + ERROR("Cannot create file %s\n", certs[i].fn); + } + } + } + + /* Save keys */ + if (save_keys) { + for (i = 0 ; i < num_keys ; i++) { + if (!key_store(&keys[i])) { + ERROR("Cannot save %s\n", keys[i].desc); + } + } + } + + /* If we got here, then we must have filled the key array completely. + * We can then safely call free on all of the keys in the array + */ + for (i = 0; i < num_keys; i++) { + EVP_PKEY_free(keys[i].key); + } + +#ifndef OPENSSL_NO_ENGINE + ENGINE_cleanup(); +#endif + CRYPTO_cleanup_all_ex_data(); + + + /* We allocated strings through strdup, so now we have to free them */ + for (i = 0; i < num_keys; i++) { + if (keys[i].fn != NULL) { + void *ptr = keys[i].fn; + + keys[i].fn = NULL; + free(ptr); + } + } + for (i = 0; i < num_extensions; i++) { + if (extensions[i].arg != NULL) { + void *ptr = (void *)extensions[i].arg; + + extensions[i].arg = NULL; + free(ptr); + } + } + for (i = 0; i < num_certs; i++) { + if (certs[i].fn != NULL) { + void *ptr = (void *)certs[i].fn; + + certs[i].fn = NULL; + free(ptr); + } + } + + return 0; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/sha.c b/arm-trusted-firmware/tools/cert_create/src/sha.c new file mode 100644 index 0000000..3d977fb --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/sha.c @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2015-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include "debug.h" +#include "key.h" + +#define BUFFER_SIZE 256 + +int sha_file(int md_alg, const char *filename, unsigned char *md) +{ + FILE *inFile; + SHA256_CTX shaContext; + SHA512_CTX sha512Context; + int bytes; + unsigned char data[BUFFER_SIZE]; + + if ((filename == NULL) || (md == NULL)) { + ERROR("%s(): NULL argument\n", __FUNCTION__); + return 0; + } + + inFile = fopen(filename, "rb"); + if (inFile == NULL) { + ERROR("Cannot read %s\n", filename); + return 0; + } + + if (md_alg == HASH_ALG_SHA384) { + SHA384_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA384_Update(&sha512Context, data, bytes); + } + SHA384_Final(md, &sha512Context); + } else if (md_alg == HASH_ALG_SHA512) { + SHA512_Init(&sha512Context); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA512_Update(&sha512Context, data, bytes); + } + SHA512_Final(md, &sha512Context); + } else { + SHA256_Init(&shaContext); + while ((bytes = fread(data, 1, BUFFER_SIZE, inFile)) != 0) { + SHA256_Update(&shaContext, data, bytes); + } + SHA256_Final(md, &shaContext); + } + + fclose(inFile); + return 1; +} diff --git a/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c new file mode 100644 index 0000000..f4fe63d --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c @@ -0,0 +1,206 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "tbbr/tbb_cert.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" + +/* + * Certificates used in the chain of trust + * + * The order of the certificates must follow the enumeration specified in + * tbb_cert.h. All certificates are self-signed, so the issuer certificate + * field points to itself. + */ +static cert_t tbb_certs[] = { + [TRUSTED_BOOT_FW_CERT] = { + .id = TRUSTED_BOOT_FW_CERT, + .opt = "tb-fw-cert", + .help_msg = "Trusted Boot FW Certificate (output file)", + .fn = NULL, + .cn = "Trusted Boot FW Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_BOOT_FW_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_BOOT_FW_HASH_EXT, + TRUSTED_BOOT_FW_CONFIG_HASH_EXT, + HW_CONFIG_HASH_EXT, + FW_CONFIG_HASH_EXT + }, + .num_ext = 5 + }, + [TRUSTED_KEY_CERT] = { + .id = TRUSTED_KEY_CERT, + .opt = "trusted-key-cert", + .help_msg = "Trusted Key Certificate (output file)", + .fn = NULL, + .cn = "Trusted Key Certificate", + .key = ROT_KEY, + .issuer = TRUSTED_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_WORLD_PK_EXT, + NON_TRUSTED_WORLD_PK_EXT + }, + .num_ext = 3 + }, + [SCP_FW_KEY_CERT] = { + .id = SCP_FW_KEY_CERT, + .opt = "scp-fw-key-cert", + .help_msg = "SCP Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "SCP Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SCP_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [SCP_FW_CONTENT_CERT] = { + .id = SCP_FW_CONTENT_CERT, + .opt = "scp-fw-cert", + .help_msg = "SCP Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "SCP Firmware Content Certificate", + .key = SCP_FW_CONTENT_CERT_KEY, + .issuer = SCP_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SCP_FW_HASH_EXT + }, + .num_ext = 2 + }, + [SOC_FW_KEY_CERT] = { + .id = SOC_FW_KEY_CERT, + .opt = "soc-fw-key-cert", + .help_msg = "SoC Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "SoC Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SOC_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [SOC_FW_CONTENT_CERT] = { + .id = SOC_FW_CONTENT_CERT, + .opt = "soc-fw-cert", + .help_msg = "SoC Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "SoC Firmware Content Certificate", + .key = SOC_FW_CONTENT_CERT_KEY, + .issuer = SOC_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SOC_AP_FW_HASH_EXT, + SOC_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + [TRUSTED_OS_FW_KEY_CERT] = { + .id = TRUSTED_OS_FW_KEY_CERT, + .opt = "tos-fw-key-cert", + .help_msg = "Trusted OS Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "Trusted OS Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = TRUSTED_OS_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [TRUSTED_OS_FW_CONTENT_CERT] = { + .id = TRUSTED_OS_FW_CONTENT_CERT, + .opt = "tos-fw-cert", + .help_msg = "Trusted OS Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "Trusted OS Firmware Content Certificate", + .key = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .issuer = TRUSTED_OS_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + TRUSTED_OS_FW_HASH_EXT, + TRUSTED_OS_FW_EXTRA1_HASH_EXT, + TRUSTED_OS_FW_EXTRA2_HASH_EXT, + TRUSTED_OS_FW_CONFIG_HASH_EXT, + }, + .num_ext = 5 + }, + [NON_TRUSTED_FW_KEY_CERT] = { + .id = NON_TRUSTED_FW_KEY_CERT, + .opt = "nt-fw-key-cert", + .help_msg = "Non-Trusted Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "Non-Trusted Firmware Key Certificate", + .key = NON_TRUSTED_WORLD_KEY, + .issuer = NON_TRUSTED_FW_KEY_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_FW_CONTENT_CERT_PK_EXT + }, + .num_ext = 2 + }, + [NON_TRUSTED_FW_CONTENT_CERT] = { + .id = NON_TRUSTED_FW_CONTENT_CERT, + .opt = "nt-fw-cert", + .help_msg = "Non-Trusted Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "Non-Trusted Firmware Content Certificate", + .key = NON_TRUSTED_FW_CONTENT_CERT_KEY, + .issuer = NON_TRUSTED_FW_CONTENT_CERT, + .ext = { + NON_TRUSTED_FW_NVCOUNTER_EXT, + NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT, + NON_TRUSTED_FW_CONFIG_HASH_EXT, + }, + .num_ext = 3 + }, + [SIP_SECURE_PARTITION_CONTENT_CERT] = { + .id = SIP_SECURE_PARTITION_CONTENT_CERT, + .opt = "sip-sp-cert", + .help_msg = "SiP owned Secure Partition Content Certificate (output file)", + .fn = NULL, + .cn = "SiP owned Secure Partition Content Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = SIP_SECURE_PARTITION_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + SP_PKG1_HASH_EXT, + SP_PKG2_HASH_EXT, + SP_PKG3_HASH_EXT, + SP_PKG4_HASH_EXT, + SP_PKG5_HASH_EXT, + SP_PKG6_HASH_EXT, + SP_PKG7_HASH_EXT, + SP_PKG8_HASH_EXT, + }, + .num_ext = 9 + }, + [FWU_CERT] = { + .id = FWU_CERT, + .opt = "fwu-cert", + .help_msg = "Firmware Update Certificate (output file)", + .fn = NULL, + .cn = "Firmware Update Certificate", + .key = ROT_KEY, + .issuer = FWU_CERT, + .ext = { + SCP_FWU_CFG_HASH_EXT, + AP_FWU_CFG_HASH_EXT, + FWU_HASH_EXT + }, + .num_ext = 3 + } +}; + +REGISTER_COT(tbb_certs); diff --git a/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c new file mode 100644 index 0000000..60bafb4 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c @@ -0,0 +1,328 @@ +/* + * Copyright (c) 2015-2020, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +#include "ext.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" + +static ext_t tbb_ext[] = { + [TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = TRUSTED_FW_NVCOUNTER_OID, + .opt = "tfw-nvctr", + .help_msg = "Trusted Firmware Non-Volatile counter value", + .sn = "TrustedWorldNVCounter", + .ln = "Trusted World Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_TFW + }, + [NON_TRUSTED_FW_NVCOUNTER_EXT] = { + .oid = NON_TRUSTED_FW_NVCOUNTER_OID, + .opt = "ntfw-nvctr", + .help_msg = "Non-Trusted Firmware Non-Volatile counter value", + .sn = "NormalWorldNVCounter", + .ln = "Non-Trusted Firmware Non-Volatile counter", + .asn1_type = V_ASN1_INTEGER, + .type = EXT_TYPE_NVCOUNTER, + .attr.nvctr_type = NVCTR_TYPE_NTFW + }, + [TRUSTED_BOOT_FW_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_HASH_OID, + .opt = "tb-fw", + .help_msg = "Trusted Boot Firmware image file", + .sn = "TrustedBootFirmwareHash", + .ln = "Trusted Boot Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [TRUSTED_BOOT_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_BOOT_FW_CONFIG_HASH_OID, + .opt = "tb-fw-config", + .help_msg = "Trusted Boot Firmware Config file", + .sn = "TrustedBootFirmwareConfigHash", + .ln = "Trusted Boot Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [HW_CONFIG_HASH_EXT] = { + .oid = HW_CONFIG_HASH_OID, + .opt = "hw-config", + .help_msg = "HW Config file", + .sn = "HWConfigHash", + .ln = "HW Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [FW_CONFIG_HASH_EXT] = { + .oid = FW_CONFIG_HASH_OID, + .opt = "fw-config", + .help_msg = "Firmware Config file", + .sn = "FirmwareConfigHash", + .ln = "Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_WORLD_PK_EXT] = { + .oid = TRUSTED_WORLD_PK_OID, + .sn = "TrustedWorldPublicKey", + .ln = "Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_WORLD_KEY + }, + [NON_TRUSTED_WORLD_PK_EXT] = { + .oid = NON_TRUSTED_WORLD_PK_OID, + .sn = "NonTrustedWorldPublicKey", + .ln = "Non-Trusted World Public Key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = NON_TRUSTED_WORLD_KEY + }, + [SCP_FW_CONTENT_CERT_PK_EXT] = { + .oid = SCP_FW_CONTENT_CERT_PK_OID, + .sn = "SCPFirmwareContentCertPK", + .ln = "SCP Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SCP_FW_CONTENT_CERT_KEY + }, + [SCP_FW_HASH_EXT] = { + .oid = SCP_FW_HASH_OID, + .opt = "scp-fw", + .help_msg = "SCP Firmware image file", + .sn = "SCPFirmwareHash", + .ln = "SCP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [SOC_FW_CONTENT_CERT_PK_EXT] = { + .oid = SOC_FW_CONTENT_CERT_PK_OID, + .sn = "SoCFirmwareContentCertPK", + .ln = "SoC Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = SOC_FW_CONTENT_CERT_KEY + }, + [SOC_AP_FW_HASH_EXT] = { + .oid = SOC_AP_FW_HASH_OID, + .opt = "soc-fw", + .help_msg = "SoC AP Firmware image file", + .sn = "SoCAPFirmwareHash", + .ln = "SoC AP Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [SOC_FW_CONFIG_HASH_EXT] = { + .oid = SOC_FW_CONFIG_HASH_OID, + .opt = "soc-fw-config", + .help_msg = "SoC Firmware Config file", + .sn = "SocFirmwareConfigHash", + .ln = "SoC Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_CONTENT_CERT_PK_EXT] = { + .oid = TRUSTED_OS_FW_CONTENT_CERT_PK_OID, + .sn = "TrustedOSFirmwareContentCertPK", + .ln = "Trusted OS Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = TRUSTED_OS_FW_CONTENT_CERT_KEY + }, + [TRUSTED_OS_FW_HASH_EXT] = { + .oid = TRUSTED_OS_FW_HASH_OID, + .opt = "tos-fw", + .help_msg = "Trusted OS image file", + .sn = "TrustedOSHash", + .ln = "Trusted OS hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [TRUSTED_OS_FW_EXTRA1_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA1_HASH_OID, + .opt = "tos-fw-extra1", + .help_msg = "Trusted OS Extra1 image file", + .sn = "TrustedOSExtra1Hash", + .ln = "Trusted OS Extra1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_EXTRA2_HASH_EXT] = { + .oid = TRUSTED_OS_FW_EXTRA2_HASH_OID, + .opt = "tos-fw-extra2", + .help_msg = "Trusted OS Extra2 image file", + .sn = "TrustedOSExtra2Hash", + .ln = "Trusted OS Extra2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [TRUSTED_OS_FW_CONFIG_HASH_EXT] = { + .oid = TRUSTED_OS_FW_CONFIG_HASH_OID, + .opt = "tos-fw-config", + .help_msg = "Trusted OS Firmware Config file", + .sn = "TrustedOSFirmwareConfigHash", + .ln = "Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [NON_TRUSTED_FW_CONTENT_CERT_PK_EXT] = { + .oid = NON_TRUSTED_FW_CONTENT_CERT_PK_OID, + .sn = "NonTrustedFirmwareContentCertPK", + .ln = "Non-Trusted Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = NON_TRUSTED_FW_CONTENT_CERT_KEY + }, + [NON_TRUSTED_WORLD_BOOTLOADER_HASH_EXT] = { + .oid = NON_TRUSTED_WORLD_BOOTLOADER_HASH_OID, + .opt = "nt-fw", + .help_msg = "Non-Trusted World Bootloader image file", + .sn = "NonTrustedWorldBootloaderHash", + .ln = "Non-Trusted World hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [NON_TRUSTED_FW_CONFIG_HASH_EXT] = { + .oid = NON_TRUSTED_FW_CONFIG_HASH_OID, + .opt = "nt-fw-config", + .help_msg = "Non Trusted OS Firmware Config file", + .sn = "NonTrustedOSFirmwareConfigHash", + .ln = "Non-Trusted OS Firmware Config hash", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG1_HASH_EXT] = { + .oid = SP_PKG1_HASH_OID, + .opt = "sp-pkg1", + .help_msg = "Secure Partition Package1 file", + .sn = "SPPkg1Hash", + .ln = "SP Pkg1 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG2_HASH_EXT] = { + .oid = SP_PKG2_HASH_OID, + .opt = "sp-pkg2", + .help_msg = "Secure Partition Package2 file", + .sn = "SPPkg2Hash", + .ln = "SP Pkg2 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG3_HASH_EXT] = { + .oid = SP_PKG3_HASH_OID, + .opt = "sp-pkg3", + .help_msg = "Secure Partition Package3 file", + .sn = "SPPkg3Hash", + .ln = "SP Pkg3 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG4_HASH_EXT] = { + .oid = SP_PKG4_HASH_OID, + .opt = "sp-pkg4", + .help_msg = "Secure Partition Package4 file", + .sn = "SPPkg4Hash", + .ln = "SP Pkg4 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG5_HASH_EXT] = { + .oid = SP_PKG5_HASH_OID, + .opt = "sp-pkg5", + .help_msg = "Secure Partition Package5 file", + .sn = "SPPkg5Hash", + .ln = "SP Pkg5 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG6_HASH_EXT] = { + .oid = SP_PKG6_HASH_OID, + .opt = "sp-pkg6", + .help_msg = "Secure Partition Package6 file", + .sn = "SPPkg6Hash", + .ln = "SP Pkg6 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG7_HASH_EXT] = { + .oid = SP_PKG7_HASH_OID, + .opt = "sp-pkg7", + .help_msg = "Secure Partition Package7 file", + .sn = "SPPkg7Hash", + .ln = "SP Pkg7 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SP_PKG8_HASH_EXT] = { + .oid = SP_PKG8_HASH_OID, + .opt = "sp-pkg8", + .help_msg = "Secure Partition Package8 file", + .sn = "SPPkg8Hash", + .ln = "SP Pkg8 hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [SCP_FWU_CFG_HASH_EXT] = { + .oid = SCP_FWU_CFG_HASH_OID, + .opt = "scp-fwu-cfg", + .help_msg = "SCP Firmware Update Config image file", + .sn = "SCPFWUpdateConfig", + .ln = "SCP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [AP_FWU_CFG_HASH_EXT] = { + .oid = AP_FWU_CFG_HASH_OID, + .opt = "ap-fwu-cfg", + .help_msg = "AP Firmware Update Config image file", + .sn = "APFWUpdateConfig", + .ln = "AP Firmware Update Config hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + }, + [FWU_HASH_EXT] = { + .oid = FWU_HASH_OID, + .opt = "fwu", + .help_msg = "Firmware Updater image file", + .sn = "FWUpdaterHash", + .ln = "Firmware Updater hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH, + .optional = 1 + } +}; + +REGISTER_EXTENSIONS(tbb_ext); diff --git a/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c new file mode 100644 index 0000000..a81f0e4 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include "tbbr/tbb_key.h" + +/* + * Keys used to establish the chain of trust + * + * The order of the keys must follow the enumeration specified in tbb_key.h + */ +static key_t tbb_keys[] = { + [ROT_KEY] = { + .id = ROT_KEY, + .opt = "rot-key", + .help_msg = "Root Of Trust key (input/output file)", + .desc = "Root Of Trust key" + }, + [TRUSTED_WORLD_KEY] = { + .id = TRUSTED_WORLD_KEY, + .opt = "trusted-world-key", + .help_msg = "Trusted World key (input/output file)", + .desc = "Trusted World key" + }, + [NON_TRUSTED_WORLD_KEY] = { + .id = NON_TRUSTED_WORLD_KEY, + .opt = "non-trusted-world-key", + .help_msg = "Non Trusted World key (input/output file)", + .desc = "Non Trusted World key" + }, + [SCP_FW_CONTENT_CERT_KEY] = { + .id = SCP_FW_CONTENT_CERT_KEY, + .opt = "scp-fw-key", + .help_msg = "SCP Firmware Content Certificate key (input/output file)", + .desc = "SCP Firmware Content Certificate key" + }, + [SOC_FW_CONTENT_CERT_KEY] = { + .id = SOC_FW_CONTENT_CERT_KEY, + .opt = "soc-fw-key", + .help_msg = "SoC Firmware Content Certificate key (input/output file)", + .desc = "SoC Firmware Content Certificate key" + }, + [TRUSTED_OS_FW_CONTENT_CERT_KEY] = { + .id = TRUSTED_OS_FW_CONTENT_CERT_KEY, + .opt = "tos-fw-key", + .help_msg = "Trusted OS Firmware Content Certificate key (input/output file)", + .desc = "Trusted OS Firmware Content Certificate key" + }, + [NON_TRUSTED_FW_CONTENT_CERT_KEY] = { + .id = NON_TRUSTED_FW_CONTENT_CERT_KEY, + .opt = "nt-fw-key", + .help_msg = "Non Trusted Firmware Content Certificate key (input/output file)", + .desc = "Non Trusted Firmware Content Certificate key" + } +}; + +REGISTER_KEYS(tbb_keys); diff --git a/arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk new file mode 100644 index 0000000..ee82d31 --- /dev/null +++ b/arm-trusted-firmware/tools/cert_create/src/tbbr/tbbr.mk @@ -0,0 +1,29 @@ +# +# Copyright (c) 2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +USE_TBBR_DEFS := 1 +$(eval $(call add_define,USE_TBBR_DEFS)) + +ifeq (${USE_TBBR_DEFS},1) +# In this case, cert_tool is platform-independent +PLAT_MSG := TBBR Generic +PLAT_INCLUDE := ../../include/tools_share +else +PLAT_MSG := ${PLAT} + +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk + +PLAT_INCLUDE := $(wildcard ${PLAT_DIR}include) + +ifeq ($(PLAT_INCLUDE),) + $(error "Error: Invalid platform '${PLAT}' has no include directory.") +endif +endif + +OBJECTS += src/tbbr/tbb_cert.o \ + src/tbbr/tbb_ext.o \ + src/tbbr/tbb_key.o diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js b/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js new file mode 100644 index 0000000..2a9d5b4 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js @@ -0,0 +1,222 @@ +/* + * Copyright (c) 2021, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +/* eslint-env es6 */ + +"use strict"; + +const Handlebars = require("handlebars"); +const Q = require("q"); +const _ = require("lodash"); + +const ccConventionalChangelog = require("conventional-changelog-conventionalcommits/conventional-changelog"); +const ccParserOpts = require("conventional-changelog-conventionalcommits/parser-opts"); +const ccRecommendedBumpOpts = require("conventional-changelog-conventionalcommits/conventional-recommended-bump"); +const ccWriterOpts = require("conventional-changelog-conventionalcommits/writer-opts"); + +const execa = require("execa"); + +const readFileSync = require("fs").readFileSync; +const resolve = require("path").resolve; + +/* + * Register a Handlebars helper that lets us generate Markdown lists that can support multi-line + * strings. This is driven by inconsistent formatting of breaking changes, which may be multiple + * lines long and can terminate the list early unintentionally. + */ +Handlebars.registerHelper("tf-a-mdlist", function (indent, options) { + const spaces = new Array(indent + 1).join(" "); + const first = spaces + "- "; + const nth = spaces + " "; + + return first + options.fn(this).replace(/\n(?!\s*\n)/gm, `\n${nth}`).trim() + "\n"; +}); + +/* + * Register a Handlebars helper that concatenates multiple variables. We use this to generate the + * title for the section partials. + */ +Handlebars.registerHelper("tf-a-concat", function () { + let argv = Array.prototype.slice.call(arguments, 0); + + argv.pop(); + + return argv.join(""); +}); + +function writerOpts(config) { + /* + * Flatten the configuration's sections list. This helps us iterate over all of the sections + * when we don't care about the hierarchy. + */ + + const flattenSections = function (sections) { + return sections.flatMap(section => { + const subsections = flattenSections(section.sections || []); + + return [section].concat(subsections); + }) + }; + + const flattenedSections = flattenSections(config.sections); + + /* + * Register a helper to return a restructured version of the note groups that includes notes + * categorized by their section. + */ + Handlebars.registerHelper("tf-a-notes", function (noteGroups, options) { + const generateTemplateData = function (sections, notes) { + return (sections || []).flatMap(section => { + const templateData = { + title: section.title, + sections: generateTemplateData(section.sections, notes), + notes: notes.filter(note => section.scopes?.includes(note.commit.scope)), + }; + + /* + * Don't return a section if it contains no notes and no sub-sections. + */ + if ((templateData.sections.length == 0) && (templateData.notes.length == 0)) { + return []; + } + + return [templateData]; + }); + }; + + return noteGroups.map(noteGroup => { + return { + title: noteGroup.title, + sections: generateTemplateData(config.sections, noteGroup.notes), + notes: noteGroup.notes.filter(note => + !flattenedSections.some(section => section.scopes?.includes(note.commit.scope))), + }; + }); + }); + + /* + * Register a helper to return a restructured version of the commit groups that includes commits + * categorized by their section. + */ + Handlebars.registerHelper("tf-a-commits", function (commitGroups, options) { + const generateTemplateData = function (sections, commits) { + return (sections || []).flatMap(section => { + const templateData = { + title: section.title, + sections: generateTemplateData(section.sections, commits), + commits: commits.filter(commit => section.scopes?.includes(commit.scope)), + }; + + /* + * Don't return a section if it contains no notes and no sub-sections. + */ + if ((templateData.sections.length == 0) && (templateData.commits.length == 0)) { + return []; + } + + return [templateData]; + }); + }; + + return commitGroups.map(commitGroup => { + return { + title: commitGroup.title, + sections: generateTemplateData(config.sections, commitGroup.commits), + commits: commitGroup.commits.filter(commit => + !flattenedSections.some(section => section.scopes?.includes(commit.scope))), + }; + }); + }); + + const writerOpts = ccWriterOpts(config) + .then(writerOpts => { + const ccWriterOptsTransform = writerOpts.transform; + + /* + * These configuration properties can't be injected directly into the template because + * they themselves are templates. Instead, we register them as partials, which allows + * them to be evaluated as part of the templates they're used in. + */ + Handlebars.registerPartial("commitUrl", config.commitUrlFormat); + Handlebars.registerPartial("compareUrl", config.compareUrlFormat); + Handlebars.registerPartial("issueUrl", config.issueUrlFormat); + + /* + * Register the partials that allow us to recursively create changelog sections. + */ + + const notePartial = readFileSync(resolve(__dirname, "./templates/note.hbs"), "utf-8"); + const noteSectionPartial = readFileSync(resolve(__dirname, "./templates/note-section.hbs"), "utf-8"); + const commitSectionPartial = readFileSync(resolve(__dirname, "./templates/commit-section.hbs"), "utf-8"); + + Handlebars.registerPartial("tf-a-note", notePartial); + Handlebars.registerPartial("tf-a-note-section", noteSectionPartial); + Handlebars.registerPartial("tf-a-commit-section", commitSectionPartial); + + /* + * Override the base templates so that we can generate a changelog that looks at least + * similar to the pre-Conventional Commits TF-A changelog. + */ + writerOpts.mainTemplate = readFileSync(resolve(__dirname, "./templates/template.hbs"), "utf-8"); + writerOpts.headerPartial = readFileSync(resolve(__dirname, "./templates/header.hbs"), "utf-8"); + writerOpts.commitPartial = readFileSync(resolve(__dirname, "./templates/commit.hbs"), "utf-8"); + writerOpts.footerPartial = readFileSync(resolve(__dirname, "./templates/footer.hbs"), "utf-8"); + + writerOpts.transform = function (commit, context) { + /* + * Fix up commit trailers, which for some reason are not correctly recognized and + * end up showing up in the breaking changes. + */ + + commit.notes.forEach(note => { + const trailers = execa.sync("git", ["interpret-trailers", "--parse"], { + input: note.text + }).stdout; + + note.text = note.text.replace(trailers, "").trim(); + }); + + return ccWriterOptsTransform(commit, context); + }; + + return writerOpts; + }); + + return writerOpts; +} + +module.exports = function (parameter) { + const config = parameter || {}; + + return Q.all([ + ccConventionalChangelog(config), + ccParserOpts(config), + ccRecommendedBumpOpts(config), + writerOpts(config) + ]).spread(( + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + ) => { + if (_.isFunction(parameter)) { + return parameter(null, { + gitRawCommitsOpts: { noMerges: null }, + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + }); + } else { + return { + conventionalChangelog, + parserOpts, + recommendedBumpOpts, + writerOpts + }; + } + }); +}; diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json b/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json new file mode 100644 index 0000000..404ef90 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json @@ -0,0 +1,13 @@ +{ + "name": "conventional-changelog-tf-a", + "version": "2.6.0", + "license": "BSD-3-Clause", + "private": true, + "main": "index.js", + "dependencies": { + "conventional-changelog-conventionalcommits": "^4.6.1", + "execa": "^5.1.1", + "lodash": "^4.17.21", + "q": "^1.5.1" + } +} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs new file mode 100644 index 0000000..86b3335 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs @@ -0,0 +1,17 @@ +{{#if title ~}} +{{ header }} + +{{#if commits.length ~}} + {{#each commits ~}} + {{#tf-a-mdlist 0}}{{> commit root=@root showScope=../topLevel }}{{/tf-a-mdlist ~}} + {{/each}} + +{{/if ~}} + +{{#if sections.length ~}} + {{#each sections ~}} + {{#tf-a-mdlist 0}}{{> tf-a-commit-section root=@root header=(tf-a-concat "**" title "**") }}{{/tf-a-mdlist}} + {{/each}} +{{/if ~}} + +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs new file mode 100644 index 0000000..faf264a --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs @@ -0,0 +1,15 @@ +{{#if scope }} + {{~#if showScope }}**{{ scope }}:** {{/if}} +{{~/if}} + +{{~#if subject }} + {{~ subject }} +{{~else}} + {{~ header }} +{{~/if}} + +{{~#if hash }} {{#if @root.linkReferences ~}} + ([{{ shortHash }}]({{> commitUrl root=@root }})) +{{~else}} + {{~ shortHash }} +{{~/if}}{{~/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs new file mode 100644 index 0000000..e69de29 diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs new file mode 100644 index 0000000..67cb297 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs @@ -0,0 +1,13 @@ +{{#if isPatch~}} + ### +{{~else~}} + ## +{{~/if}} {{#if @root.linkCompare~}} + [{{version}}]({{> compareUrl root=@root}}) +{{~else}} + {{~version}} +{{~/if}} +{{~#if title}} "{{title}}" +{{~/if}} +{{~#if date}} ({{date}}) +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs new file mode 100644 index 0000000..f501c96 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs @@ -0,0 +1,13 @@ +{{ header }} + +{{#if notes.length ~}} + {{#each notes ~}} + {{#tf-a-mdlist 0}}{{> tf-a-note root=@root showScope=../topLevel }}{{/tf-a-mdlist}} + {{/each ~}} +{{/if ~}} + +{{#if sections.length ~}} + {{#each sections ~}} + {{#tf-a-mdlist 0}}{{> tf-a-note-section root=@root header=(tf-a-concat "**" title "**") }}{{/tf-a-mdlist}} + {{/each~}} +{{/if}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs new file mode 100644 index 0000000..c780ee8 --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs @@ -0,0 +1,3 @@ +{{ text }} + +**See:** {{#with commit }}{{> commit root=@root showScope=../showScope }}{{/with}} diff --git a/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs new file mode 100644 index 0000000..95fb68c --- /dev/null +++ b/arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs @@ -0,0 +1,9 @@ +{{> header }} + +{{#each (tf-a-notes noteGroups) ~}} +{{> tf-a-note-section root=@root header=(tf-a-concat "### âš  " title) topLevel=true }} +{{/each ~}} + +{{#each (tf-a-commits commitGroups) ~}} +{{> tf-a-commit-section root=@root header=(tf-a-concat "### " title) topLevel=true }} +{{/each ~}} diff --git a/arm-trusted-firmware/tools/encrypt_fw/Makefile b/arm-trusted-firmware/tools/encrypt_fw/Makefile new file mode 100644 index 0000000..96dff23 --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/Makefile @@ -0,0 +1,65 @@ +# +# Copyright (c) 2019-2020, Linaro Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +V ?= 0 +BUILD_INFO ?= 1 +DEBUG := 0 +ENCTOOL ?= encrypt_fw${BIN_EXT} +BINARY := $(notdir ${ENCTOOL}) +OPENSSL_DIR := /usr + +OBJECTS := src/encrypt.o \ + src/cmd_opt.o \ + src/main.o + +HOSTCCFLAGS := -Wall -std=c99 + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG -DLOG_LEVEL=40 +else +ifeq (${BUILD_INFO},1) + HOSTCCFLAGS += -O2 -DLOG_LEVEL=20 +else + HOSTCCFLAGS += -O2 -DLOG_LEVEL=10 +endif +endif +ifeq (${V},0) + Q := @ +else + Q := +endif + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INC_DIR := -I ./include -I ../../include/tools_share -I ${OPENSSL_DIR}/include +LIB_DIR := -L ${OPENSSL_DIR}/lib +LIB := -lssl -lcrypto + +HOSTCC ?= gcc + +.PHONY: all clean realclean + +all: ${BINARY} + +${BINARY}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + @echo 'const char build_msg[] = "Built : "__TIME__", "__DATE__;' | \ + ${HOSTCC} -c ${HOSTCCFLAGS} -xc - -o src/build_msg.o + ${Q}${HOSTCC} src/build_msg.o ${OBJECTS} ${LIB_DIR} ${LIB} -o $@ + +%.o: %.c + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INC_DIR} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, src/build_msg.o ${OBJECTS}) + +realclean: clean + $(call SHELL_DELETE,${BINARY}) diff --git a/arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h b/arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h new file mode 100644 index 0000000..bd7d31f --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h @@ -0,0 +1,32 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef CMD_OPT_H +#define CMD_OPT_H + +#include + +#define CMD_OPT_MAX_NUM 64 + +/* Supported long command line option types */ +enum { + CMD_OPT_FW +}; + +/* Structure to define a command line option */ +typedef struct cmd_opt_s { + struct option long_opt; + const char *help_msg; +} cmd_opt_t; + +/* Exported API*/ +void cmd_opt_add(const cmd_opt_t *cmd_opt); +const struct option *cmd_opt_get_array(void); +const char *cmd_opt_get_name(int idx); +const char *cmd_opt_get_help_msg(int idx); + +#endif /* CMD_OPT_H */ diff --git a/arm-trusted-firmware/tools/encrypt_fw/include/debug.h b/arm-trusted-firmware/tools/encrypt_fw/include/debug.h new file mode 100644 index 0000000..ee8f1f5 --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/include/debug.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef DEBUG_H +#define DEBUG_H + +#include + +/* The log output macros print output to the console. These macros produce + * compiled log output only if the LOG_LEVEL defined in the makefile (or the + * make command line) is greater or equal than the level required for that + * type of log output. + * The format expected is the same as for printf(). For example: + * INFO("Info %s.\n", "message") -> INFO: Info message. + * WARN("Warning %s.\n", "message") -> WARNING: Warning message. + */ + +#define LOG_LEVEL_NONE 0 +#define LOG_LEVEL_ERROR 10 +#define LOG_LEVEL_NOTICE 20 +#define LOG_LEVEL_WARNING 30 +#define LOG_LEVEL_INFO 40 +#define LOG_LEVEL_VERBOSE 50 + + +#if LOG_LEVEL >= LOG_LEVEL_NOTICE +# define NOTICE(...) printf("NOTICE: " __VA_ARGS__) +#else +# define NOTICE(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_ERROR +# define ERROR(...) printf("ERROR: " __VA_ARGS__) +#else +# define ERROR(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_WARNING +# define WARN(...) printf("WARNING: " __VA_ARGS__) +#else +# define WARN(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_INFO +# define INFO(...) printf("INFO: " __VA_ARGS__) +#else +# define INFO(...) +#endif + +#if LOG_LEVEL >= LOG_LEVEL_VERBOSE +# define VERBOSE(...) printf("VERBOSE: " __VA_ARGS__) +#else +# define VERBOSE(...) +#endif + +#endif /* DEBUG_H */ diff --git a/arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h b/arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h new file mode 100644 index 0000000..25d3011 --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef ENCRYPT_H +#define ENCRYPT_H + +/* Supported key algorithms */ +enum { + KEY_ALG_GCM /* AES-GCM (default) */ +}; + +int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string, + char *nonce_string, const char *ip_name, const char *op_name); + +#endif /* ENCRYPT_H */ diff --git a/arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c b/arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c new file mode 100644 index 0000000..64180d1 --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include "debug.h" + +/* Command line options */ +static struct option long_opt[CMD_OPT_MAX_NUM+1]; +static const char *help_msg[CMD_OPT_MAX_NUM+1]; +static int num_reg_opt; + +void cmd_opt_add(const cmd_opt_t *cmd_opt) +{ + assert(cmd_opt != NULL); + + if (num_reg_opt >= CMD_OPT_MAX_NUM) { + ERROR("Out of memory. Please increase CMD_OPT_MAX_NUM\n"); + exit(1); + } + + long_opt[num_reg_opt].name = cmd_opt->long_opt.name; + long_opt[num_reg_opt].has_arg = cmd_opt->long_opt.has_arg; + long_opt[num_reg_opt].flag = 0; + long_opt[num_reg_opt].val = cmd_opt->long_opt.val; + + help_msg[num_reg_opt] = cmd_opt->help_msg; + + num_reg_opt++; +} + +const struct option *cmd_opt_get_array(void) +{ + return long_opt; +} + +const char *cmd_opt_get_name(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return long_opt[idx].name; +} + +const char *cmd_opt_get_help_msg(int idx) +{ + if (idx >= num_reg_opt) { + return NULL; + } + + return help_msg[idx]; +} diff --git a/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c b/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c new file mode 100644 index 0000000..18a514c --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include "debug.h" +#include "encrypt.h" + +#define BUFFER_SIZE 256 +#define IV_SIZE 12 +#define IV_STRING_SIZE 24 +#define TAG_SIZE 16 +#define KEY_SIZE 32 +#define KEY_STRING_SIZE 64 + +static int gcm_encrypt(unsigned short fw_enc_status, char *key_string, + char *nonce_string, const char *ip_name, + const char *op_name) +{ + FILE *ip_file; + FILE *op_file; + EVP_CIPHER_CTX *ctx; + unsigned char data[BUFFER_SIZE], enc_data[BUFFER_SIZE]; + unsigned char key[KEY_SIZE], iv[IV_SIZE], tag[TAG_SIZE]; + int bytes, enc_len = 0, i, j, ret = 0; + struct fw_enc_hdr header; + + memset(&header, 0, sizeof(struct fw_enc_hdr)); + + if (strlen(key_string) != KEY_STRING_SIZE) { + ERROR("Unsupported key size: %lu\n", strlen(key_string)); + return -1; + } + + for (i = 0, j = 0; i < KEY_SIZE; i++, j += 2) { + if (sscanf(&key_string[j], "%02hhx", &key[i]) != 1) { + ERROR("Incorrect key format\n"); + return -1; + } + } + + if (strlen(nonce_string) != IV_STRING_SIZE) { + ERROR("Unsupported IV size: %lu\n", strlen(nonce_string)); + return -1; + } + + for (i = 0, j = 0; i < IV_SIZE; i++, j += 2) { + if (sscanf(&nonce_string[j], "%02hhx", &iv[i]) != 1) { + ERROR("Incorrect IV format\n"); + return -1; + } + } + + ip_file = fopen(ip_name, "rb"); + if (ip_file == NULL) { + ERROR("Cannot read %s\n", ip_name); + return -1; + } + + op_file = fopen(op_name, "wb"); + if (op_file == NULL) { + ERROR("Cannot write %s\n", op_name); + fclose(ip_file); + return -1; + } + + ret = fseek(op_file, sizeof(struct fw_enc_hdr), SEEK_SET); + if (ret) { + ERROR("fseek failed\n"); + goto out_file; + } + + ctx = EVP_CIPHER_CTX_new(); + if (ctx == NULL) { + ERROR("EVP_CIPHER_CTX_new failed\n"); + ret = -1; + goto out_file; + } + + ret = EVP_EncryptInit_ex(ctx, EVP_aes_256_gcm(), NULL, NULL, NULL); + if (ret != 1) { + ERROR("EVP_EncryptInit_ex failed\n"); + ret = -1; + goto out; + } + + ret = EVP_EncryptInit_ex(ctx, NULL, NULL, key, iv); + if (ret != 1) { + ERROR("EVP_EncryptInit_ex failed\n"); + goto out; + } + + while ((bytes = fread(data, 1, BUFFER_SIZE, ip_file)) != 0) { + ret = EVP_EncryptUpdate(ctx, enc_data, &enc_len, data, bytes); + if (ret != 1) { + ERROR("EVP_EncryptUpdate failed\n"); + ret = -1; + goto out; + } + + fwrite(enc_data, 1, enc_len, op_file); + } + + ret = EVP_EncryptFinal_ex(ctx, enc_data, &enc_len); + if (ret != 1) { + ERROR("EVP_EncryptFinal_ex failed\n"); + ret = -1; + goto out; + } + + ret = EVP_CIPHER_CTX_ctrl(ctx, EVP_CTRL_GCM_GET_TAG, TAG_SIZE, tag); + if (ret != 1) { + ERROR("EVP_CIPHER_CTX_ctrl failed\n"); + ret = -1; + goto out; + } + + header.magic = ENC_HEADER_MAGIC; + header.flags |= fw_enc_status & FW_ENC_STATUS_FLAG_MASK; + header.dec_algo = KEY_ALG_GCM; + header.iv_len = IV_SIZE; + header.tag_len = TAG_SIZE; + memcpy(header.iv, iv, IV_SIZE); + memcpy(header.tag, tag, TAG_SIZE); + + ret = fseek(op_file, 0, SEEK_SET); + if (ret) { + ERROR("fseek failed\n"); + goto out; + } + + fwrite(&header, 1, sizeof(struct fw_enc_hdr), op_file); + +out: + EVP_CIPHER_CTX_free(ctx); + +out_file: + fclose(ip_file); + fclose(op_file); + + /* + * EVP_* APIs returns 1 as success but enctool considers + * 0 as success. + */ + if (ret == 1) + ret = 0; + + return ret; +} + +int encrypt_file(unsigned short fw_enc_status, int enc_alg, char *key_string, + char *nonce_string, const char *ip_name, const char *op_name) +{ + switch (enc_alg) { + case KEY_ALG_GCM: + return gcm_encrypt(fw_enc_status, key_string, nonce_string, + ip_name, op_name); + default: + return -1; + } +} diff --git a/arm-trusted-firmware/tools/encrypt_fw/src/main.c b/arm-trusted-firmware/tools/encrypt_fw/src/main.c new file mode 100644 index 0000000..39b7af7 --- /dev/null +++ b/arm-trusted-firmware/tools/encrypt_fw/src/main.c @@ -0,0 +1,224 @@ +/* + * Copyright (c) 2019, Linaro Limited. All rights reserved. + * Author: Sumit Garg + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "cmd_opt.h" +#include "debug.h" +#include "encrypt.h" +#include "firmware_encrypted.h" + +#define NUM_ELEM(x) ((sizeof(x)) / (sizeof(x[0]))) +#define HELP_OPT_MAX_LEN 128 + +/* Global options */ + +/* Info messages created in the Makefile */ +extern const char build_msg[]; + +static char *key_algs_str[] = { + [KEY_ALG_GCM] = "gcm", +}; + +static void print_help(const char *cmd, const struct option *long_opt) +{ + int rem, i = 0; + const struct option *opt; + char line[HELP_OPT_MAX_LEN]; + char *p; + + assert(cmd != NULL); + assert(long_opt != NULL); + + printf("\n\n"); + printf("The firmware encryption tool loads the binary image and\n" + "outputs encrypted binary image using an encryption key\n" + "provided as an input hex string.\n"); + printf("\n"); + printf("Usage:\n"); + printf("\t%s [OPTIONS]\n\n", cmd); + + printf("Available options:\n"); + opt = long_opt; + while (opt->name) { + p = line; + rem = HELP_OPT_MAX_LEN; + if (isalpha(opt->val)) { + /* Short format */ + sprintf(p, "-%c,", (char)opt->val); + p += 3; + rem -= 3; + } + snprintf(p, rem, "--%s %s", opt->name, + (opt->has_arg == required_argument) ? "" : ""); + printf("\t%-32s %s\n", line, cmd_opt_get_help_msg(i)); + opt++; + i++; + } + printf("\n"); +} + +static int get_key_alg(const char *key_alg_str) +{ + int i; + + for (i = 0 ; i < NUM_ELEM(key_algs_str) ; i++) { + if (strcmp(key_alg_str, key_algs_str[i]) == 0) { + return i; + } + } + + return -1; +} + +static void parse_fw_enc_status_flag(const char *arg, + unsigned short *fw_enc_status) +{ + unsigned long flag; + char *endptr; + + flag = strtoul(arg, &endptr, 16); + if (*endptr != '\0' || flag > FW_ENC_WITH_BSSK) { + ERROR("Invalid fw_enc_status flag '%s'\n", arg); + exit(1); + } + + *fw_enc_status = flag & FW_ENC_STATUS_FLAG_MASK; +} + +/* Common command line options */ +static const cmd_opt_t common_cmd_opt[] = { + { + { "help", no_argument, NULL, 'h' }, + "Print this message and exit" + }, + { + { "fw-enc-status", required_argument, NULL, 'f' }, + "Firmware encryption status flag (with SSK=0 or BSSK=1)." + }, + { + { "key-alg", required_argument, NULL, 'a' }, + "Encryption key algorithm: 'gcm' (default)" + }, + { + { "key", required_argument, NULL, 'k' }, + "Encryption key (for supported algorithm)." + }, + { + { "nonce", required_argument, NULL, 'n' }, + "Nonce or Initialization Vector (for supported algorithm)." + }, + { + { "in", required_argument, NULL, 'i' }, + "Input filename to be encrypted." + }, + { + { "out", required_argument, NULL, 'o' }, + "Encrypted output filename." + }, +}; + +int main(int argc, char *argv[]) +{ + int i, key_alg, ret; + int c, opt_idx = 0; + const struct option *cmd_opt; + char *key = NULL; + char *nonce = NULL; + char *in_fn = NULL; + char *out_fn = NULL; + unsigned short fw_enc_status = 0; + + NOTICE("Firmware Encryption Tool: %s\n", build_msg); + + /* Set default options */ + key_alg = KEY_ALG_GCM; + + /* Add common command line options */ + for (i = 0; i < NUM_ELEM(common_cmd_opt); i++) { + cmd_opt_add(&common_cmd_opt[i]); + } + + /* Get the command line options populated during the initialization */ + cmd_opt = cmd_opt_get_array(); + + while (1) { + /* getopt_long stores the option index here. */ + c = getopt_long(argc, argv, "a:f:hi:k:n:o:", cmd_opt, &opt_idx); + + /* Detect the end of the options. */ + if (c == -1) { + break; + } + + switch (c) { + case 'a': + key_alg = get_key_alg(optarg); + if (key_alg < 0) { + ERROR("Invalid key algorithm '%s'\n", optarg); + exit(1); + } + break; + case 'f': + parse_fw_enc_status_flag(optarg, &fw_enc_status); + break; + case 'k': + key = optarg; + break; + case 'i': + in_fn = optarg; + break; + case 'o': + out_fn = optarg; + break; + case 'n': + nonce = optarg; + break; + case 'h': + print_help(argv[0], cmd_opt); + exit(0); + case '?': + default: + print_help(argv[0], cmd_opt); + exit(1); + } + } + + if (!key) { + ERROR("Key must not be NULL\n"); + exit(1); + } + + if (!nonce) { + ERROR("Nonce must not be NULL\n"); + exit(1); + } + + if (!in_fn) { + ERROR("Input filename must not be NULL\n"); + exit(1); + } + + if (!out_fn) { + ERROR("Output filename must not be NULL\n"); + exit(1); + } + + ret = encrypt_file(fw_enc_status, key_alg, key, nonce, in_fn, out_fn); + + CRYPTO_cleanup_all_ex_data(); + + return ret; +} diff --git a/arm-trusted-firmware/tools/fiptool/Makefile b/arm-trusted-firmware/tools/fiptool/Makefile new file mode 100644 index 0000000..7c2a083 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/Makefile @@ -0,0 +1,63 @@ +# +# Copyright (c) 2014-2021, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +FIPTOOL ?= fiptool${BIN_EXT} +PROJECT := $(notdir ${FIPTOOL}) +OBJECTS := fiptool.o tbbr_config.o +V ?= 0 +OPENSSL_DIR := /usr + + +override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif +LDLIBS := -L${OPENSSL_DIR}/lib -lcrypto + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := -I../../include/tools_share -I${OPENSSL_DIR}/include + +HOSTCC ?= gcc + +ifneq (${PLAT},) +TF_PLATFORM_ROOT := ../../plat/ +include ${MAKE_HELPERS_DIRECTORY}plat_helpers.mk +PLAT_FIPTOOL_HELPER_MK := ${PLAT_DIR}/plat_fiptool.mk +endif + +ifneq (,$(wildcard ${PLAT_FIPTOOL_HELPER_MK})) +include ${PLAT_FIPTOOL_HELPER_MK} +endif + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${CPPFLAGS} ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) diff --git a/arm-trusted-firmware/tools/fiptool/Makefile.msvc b/arm-trusted-firmware/tools/fiptool/Makefile.msvc new file mode 100644 index 0000000..9081bc6 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/Makefile.msvc @@ -0,0 +1,37 @@ +# +# Copyright (c) 2019-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +CC = cl.exe +LD = link.exe + +# FIPTOOLPATH and FIPTOOL are passed from the main makefile. + +OBJECTS = $(FIPTOOLPATH)\fiptool.obj \ + $(FIPTOOLPATH)\tbbr_config.obj \ + $(FIPTOOLPATH)\win_posix.obj + +INC = -I$(FIPTOOLPATH) -Iinclude\tools_share + +CFLAGS = $(CFLAGS) /nologo /Za /Zi /c /O2 /MT + +all: $(FIPTOOL) + +$(FIPTOOL): $(OBJECTS) + $(LD) /nologo /INCREMENTAL:NO /debug /nodefaultlib:libc.lib /out:$@ $(LIBS) $** + +.PHONY: clean realclean + +clean: + -@del /f /q $(OBJECTS) > nul + -@del /f /q $(FIPTOOLPATH)\*.pdb > nul + +realclean: + -@del /f /q $(OBJECTS) > nul + -@del /f /q $(FIPTOOLPATH)\*.pdb > nul + -@del /f /q $(FIPTOOL) > nul + +.c.obj: + $(CC) -c $(CFLAGS) $(INC) $< -Fo$@ diff --git a/arm-trusted-firmware/tools/fiptool/fiptool b/arm-trusted-firmware/tools/fiptool/fiptool new file mode 100755 index 0000000000000000000000000000000000000000..bc9aa55273cbb0d4148ee22d14f3b279d07584a6 GIT binary patch literal 56112 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 eGPO< +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fiptool.h" +#include "tbbr_config.h" + +#define OPT_TOC_ENTRY 0 +#define OPT_PLAT_TOC_FLAGS 1 +#define OPT_ALIGN 2 + +static int info_cmd(int argc, char *argv[]); +static void info_usage(int); +static int create_cmd(int argc, char *argv[]); +static void create_usage(int); +static int update_cmd(int argc, char *argv[]); +static void update_usage(int); +static int unpack_cmd(int argc, char *argv[]); +static void unpack_usage(int); +static int remove_cmd(int argc, char *argv[]); +static void remove_usage(int); +static int version_cmd(int argc, char *argv[]); +static void version_usage(int); +static int help_cmd(int argc, char *argv[]); +static void usage(void); + +/* Available subcommands. */ +static cmd_t cmds[] = { + { .name = "info", .handler = info_cmd, .usage = info_usage }, + { .name = "create", .handler = create_cmd, .usage = create_usage }, + { .name = "update", .handler = update_cmd, .usage = update_usage }, + { .name = "unpack", .handler = unpack_cmd, .usage = unpack_usage }, + { .name = "remove", .handler = remove_cmd, .usage = remove_usage }, + { .name = "version", .handler = version_cmd, .usage = version_usage }, + { .name = "help", .handler = help_cmd, .usage = NULL }, +}; + +static image_desc_t *image_desc_head; +static size_t nr_image_descs; +static const uuid_t uuid_null; +static int verbose; + +static void vlog(int prio, const char *msg, va_list ap) +{ + char *prefix[] = { "DEBUG", "WARN", "ERROR" }; + + fprintf(stderr, "%s: ", prefix[prio]); + vfprintf(stderr, msg, ap); + fputc('\n', stderr); +} + +static void log_dbgx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_DBG, msg, ap); + va_end(ap); +} + +static void log_warnx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_WARN, msg, ap); + va_end(ap); +} + +static void log_err(const char *msg, ...) +{ + char buf[512]; + va_list ap; + + va_start(ap, msg); + snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno)); + vlog(LOG_ERR, buf, ap); + va_end(ap); + exit(1); +} + +static void log_errx(const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + vlog(LOG_ERR, msg, ap); + va_end(ap); + exit(1); +} + +static char *xstrdup(const char *s, const char *msg) +{ + char *d; + + d = strdup(s); + if (d == NULL) + log_errx("strdup: %s", msg); + return d; +} + +static void *xmalloc(size_t size, const char *msg) +{ + void *d; + + d = malloc(size); + if (d == NULL) + log_errx("malloc: %s", msg); + return d; +} + +static void *xzalloc(size_t size, const char *msg) +{ + return memset(xmalloc(size, msg), 0, size); +} + +static void xfwrite(void *buf, size_t size, FILE *fp, const char *filename) +{ + if (fwrite(buf, 1, size, fp) != size) + log_errx("Failed to write %s", filename); +} + +static image_desc_t *new_image_desc(const uuid_t *uuid, + const char *name, const char *cmdline_name) +{ + image_desc_t *desc; + + desc = xzalloc(sizeof(*desc), + "failed to allocate memory for image descriptor"); + memcpy(&desc->uuid, uuid, sizeof(uuid_t)); + desc->name = xstrdup(name, + "failed to allocate memory for image name"); + desc->cmdline_name = xstrdup(cmdline_name, + "failed to allocate memory for image command line name"); + desc->action = DO_UNSPEC; + return desc; +} + +static void set_image_desc_action(image_desc_t *desc, int action, + const char *arg) +{ + assert(desc != NULL); + + if (desc->action_arg != (char *)DO_UNSPEC) + free(desc->action_arg); + desc->action = action; + desc->action_arg = NULL; + if (arg != NULL) + desc->action_arg = xstrdup(arg, + "failed to allocate memory for argument"); +} + +static void free_image_desc(image_desc_t *desc) +{ + free(desc->name); + free(desc->cmdline_name); + free(desc->action_arg); + if (desc->image) { + free(desc->image->buffer); + free(desc->image); + } + free(desc); +} + +static void add_image_desc(image_desc_t *desc) +{ + image_desc_t **p = &image_desc_head; + + while (*p) + p = &(*p)->next; + + assert(*p == NULL); + *p = desc; + nr_image_descs++; +} + +static void free_image_descs(void) +{ + image_desc_t *desc = image_desc_head, *tmp; + + while (desc != NULL) { + tmp = desc->next; + free_image_desc(desc); + desc = tmp; + nr_image_descs--; + } + assert(nr_image_descs == 0); +} + +static void fill_image_descs(void) +{ + toc_entry_t *toc_entry; + + for (toc_entry = toc_entries; + toc_entry->cmdline_name != NULL; + toc_entry++) { + image_desc_t *desc; + + desc = new_image_desc(&toc_entry->uuid, + toc_entry->name, + toc_entry->cmdline_name); + add_image_desc(desc); + } +#ifdef PLAT_DEF_FIP_UUID + for (toc_entry = plat_def_toc_entries; + toc_entry->cmdline_name != NULL; + toc_entry++) { + image_desc_t *desc; + + desc = new_image_desc(&toc_entry->uuid, + toc_entry->name, + toc_entry->cmdline_name); + add_image_desc(desc); + } +#endif +} + +static image_desc_t *lookup_image_desc_from_uuid(const uuid_t *uuid) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (memcmp(&desc->uuid, uuid, sizeof(uuid_t)) == 0) + return desc; + return NULL; +} + +static image_desc_t *lookup_image_desc_from_opt(const char *opt) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (strcmp(desc->cmdline_name, opt) == 0) + return desc; + return NULL; +} + +static void uuid_to_str(char *s, size_t len, const uuid_t *u) +{ + assert(len >= (_UUID_STR_LEN + 1)); + + snprintf(s, len, + "%02X%02X%02X%02X-%02X%02X-%02X%02X-%04X-%04X%04X%04X", + u->time_low[0], u->time_low[1], u->time_low[2], u->time_low[3], + u->time_mid[0], u->time_mid[1], + u->time_hi_and_version[0], u->time_hi_and_version[1], + (u->clock_seq_hi_and_reserved << 8) | u->clock_seq_low, + (u->node[0] << 8) | u->node[1], + (u->node[2] << 8) | u->node[3], + (u->node[4] << 8) | u->node[5]); +} + +static void uuid_from_str(uuid_t *u, const char *s) +{ + int n; + + if (s == NULL) + log_errx("UUID cannot be NULL"); + if (strlen(s) != _UUID_STR_LEN) + log_errx("Invalid UUID: %s", s); + + n = sscanf(s, + "%2hhx%2hhx%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx", + &u->time_low[0], &u->time_low[1], &u->time_low[2], &u->time_low[3], + &u->time_mid[0], &u->time_mid[1], + &u->time_hi_and_version[0], &u->time_hi_and_version[1], + &u->clock_seq_hi_and_reserved, &u->clock_seq_low, + &u->node[0], &u->node[1], + &u->node[2], &u->node[3], + &u->node[4], &u->node[5]); + /* + * Given the format specifier above, we expect 16 items to be scanned + * for a properly formatted UUID. + */ + if (n != 16) + log_errx("Invalid UUID: %s", s); +} + +static int parse_fip(const char *filename, fip_toc_header_t *toc_header_out) +{ + struct BLD_PLAT_STAT st; + FILE *fp; + char *buf, *bufend; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + int terminated = 0; + + fp = fopen(filename, "rb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (fstat(fileno(fp), &st) == -1) + log_err("fstat %s", filename); + + buf = xmalloc(st.st_size, "failed to load file into memory"); + if (fread(buf, 1, st.st_size, fp) != st.st_size) + log_errx("Failed to read %s", filename); + bufend = buf + st.st_size; + fclose(fp); + + if (st.st_size < sizeof(fip_toc_header_t)) + log_errx("FIP %s is truncated", filename); + + toc_header = (fip_toc_header_t *)buf; + toc_entry = (fip_toc_entry_t *)(toc_header + 1); + + if (toc_header->name != TOC_HEADER_NAME) + log_errx("%s is not a FIP file", filename); + + /* Return the ToC header if the caller wants it. */ + if (toc_header_out != NULL) + *toc_header_out = *toc_header; + + /* Walk through each ToC entry in the file. */ + while ((char *)toc_entry + sizeof(*toc_entry) - 1 < bufend) { + image_t *image; + image_desc_t *desc; + + /* Found the ToC terminator, we are done. */ + if (memcmp(&toc_entry->uuid, &uuid_null, sizeof(uuid_t)) == 0) { + terminated = 1; + break; + } + + /* + * Build a new image out of the ToC entry and add it to the + * table of images. + */ + image = xzalloc(sizeof(*image), + "failed to allocate memory for image"); + image->toc_e = *toc_entry; + image->buffer = xmalloc(toc_entry->size, + "failed to allocate image buffer, is FIP file corrupted?"); + /* Overflow checks before memory copy. */ + if (toc_entry->size > (uint64_t)-1 - toc_entry->offset_address) + log_errx("FIP %s is corrupted", filename); + if (toc_entry->size + toc_entry->offset_address > st.st_size) + log_errx("FIP %s is corrupted", filename); + + memcpy(image->buffer, buf + toc_entry->offset_address, + toc_entry->size); + + /* If this is an unknown image, create a descriptor for it. */ + desc = lookup_image_desc_from_uuid(&toc_entry->uuid); + if (desc == NULL) { + char name[_UUID_STR_LEN + 1], filename[PATH_MAX]; + + uuid_to_str(name, sizeof(name), &toc_entry->uuid); + snprintf(filename, sizeof(filename), "%s%s", + name, ".bin"); + desc = new_image_desc(&toc_entry->uuid, name, "blob"); + desc->action = DO_UNPACK; + desc->action_arg = xstrdup(filename, + "failed to allocate memory for blob filename"); + add_image_desc(desc); + } + + assert(desc->image == NULL); + desc->image = image; + + toc_entry++; + } + + if (terminated == 0) + log_errx("FIP %s does not have a ToC terminator entry", + filename); + free(buf); + return 0; +} + +static image_t *read_image_from_file(const uuid_t *uuid, const char *filename) +{ + struct BLD_PLAT_STAT st; + image_t *image; + FILE *fp; + + assert(uuid != NULL); + assert(filename != NULL); + + fp = fopen(filename, "rb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (fstat(fileno(fp), &st) == -1) + log_errx("fstat %s", filename); + + image = xzalloc(sizeof(*image), "failed to allocate memory for image"); + image->toc_e.uuid = *uuid; + image->buffer = xmalloc(st.st_size, "failed to allocate image buffer"); + if (fread(image->buffer, 1, st.st_size, fp) != st.st_size) + log_errx("Failed to read %s", filename); + image->toc_e.size = st.st_size; + + fclose(fp); + return image; +} + +static int write_image_to_file(const image_t *image, const char *filename) +{ + FILE *fp; + + fp = fopen(filename, "wb"); + if (fp == NULL) + log_err("fopen"); + xfwrite(image->buffer, image->toc_e.size, fp, filename); + fclose(fp); + return 0; +} + +static struct option *add_opt(struct option *opts, size_t *nr_opts, + const char *name, int has_arg, int val) +{ + opts = realloc(opts, (*nr_opts + 1) * sizeof(*opts)); + if (opts == NULL) + log_err("realloc"); + opts[*nr_opts].name = name; + opts[*nr_opts].has_arg = has_arg; + opts[*nr_opts].flag = NULL; + opts[*nr_opts].val = val; + ++*nr_opts; + return opts; +} + +static struct option *fill_common_opts(struct option *opts, size_t *nr_opts, + int has_arg) +{ + image_desc_t *desc; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + opts = add_opt(opts, nr_opts, desc->cmdline_name, has_arg, + OPT_TOC_ENTRY); + return opts; +} + +static void md_print(const unsigned char *md, size_t len) +{ + size_t i; + + for (i = 0; i < len; i++) + printf("%02x", md[i]); +} + +static int info_cmd(int argc, char *argv[]) +{ + image_desc_t *desc; + fip_toc_header_t toc_header; + + if (argc != 2) + info_usage(EXIT_FAILURE); + argc--, argv++; + + parse_fip(argv[0], &toc_header); + + if (verbose) { + log_dbgx("toc_header[name]: 0x%llX", + (unsigned long long)toc_header.name); + log_dbgx("toc_header[serial_number]: 0x%llX", + (unsigned long long)toc_header.serial_number); + log_dbgx("toc_header[flags]: 0x%llX", + (unsigned long long)toc_header.flags); + } + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL) + continue; + printf("%s: offset=0x%llX, size=0x%llX, cmdline=\"--%s\"", + desc->name, + (unsigned long long)image->toc_e.offset_address, + (unsigned long long)image->toc_e.size, + desc->cmdline_name); +#ifndef _MSC_VER /* We don't have SHA256 for Visual Studio. */ + if (verbose) { + unsigned char md[SHA256_DIGEST_LENGTH]; + + SHA256(image->buffer, image->toc_e.size, md); + printf(", sha256="); + md_print(md, sizeof(md)); + } +#endif + putchar('\n'); + } + + return 0; +} + +static void info_usage(int exit_status) +{ + printf("fiptool info FIP_FILENAME\n"); + exit(exit_status); +} + +static int pack_images(const char *filename, uint64_t toc_flags, unsigned long align) +{ + FILE *fp; + image_desc_t *desc; + fip_toc_header_t *toc_header; + fip_toc_entry_t *toc_entry; + char *buf; + uint64_t entry_offset, buf_size, payload_size = 0, pad_size; + size_t nr_images = 0; + + for (desc = image_desc_head; desc != NULL; desc = desc->next) + if (desc->image != NULL) + nr_images++; + + buf_size = sizeof(fip_toc_header_t) + + sizeof(fip_toc_entry_t) * (nr_images + 1); + buf = calloc(1, buf_size); + if (buf == NULL) + log_err("calloc"); + + /* Build up header and ToC entries from the image table. */ + toc_header = (fip_toc_header_t *)buf; + toc_header->name = TOC_HEADER_NAME; + toc_header->serial_number = TOC_HEADER_SERIAL_NUMBER; + toc_header->flags = toc_flags; + + toc_entry = (fip_toc_entry_t *)(toc_header + 1); + + entry_offset = buf_size; + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL || (image->toc_e.size == 0ULL)) + continue; + payload_size += image->toc_e.size; + entry_offset = (entry_offset + align - 1) & ~(align - 1); + image->toc_e.offset_address = entry_offset; + *toc_entry++ = image->toc_e; + entry_offset += image->toc_e.size; + } + + /* + * Append a null uuid entry to mark the end of ToC entries. + * NOTE the offset address for the last toc_entry must match the fip + * size. + */ + memset(toc_entry, 0, sizeof(*toc_entry)); + toc_entry->offset_address = (entry_offset + align - 1) & ~(align - 1); + + /* Generate the FIP file. */ + fp = fopen(filename, "wb"); + if (fp == NULL) + log_err("fopen %s", filename); + + if (verbose) + log_dbgx("Metadata size: %zu bytes", buf_size); + + xfwrite(buf, buf_size, fp, filename); + + if (verbose) + log_dbgx("Payload size: %zu bytes", payload_size); + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image = desc->image; + + if (image == NULL) + continue; + if (fseek(fp, image->toc_e.offset_address, SEEK_SET)) + log_errx("Failed to set file position"); + + xfwrite(image->buffer, image->toc_e.size, fp, filename); + } + + if (fseek(fp, entry_offset, SEEK_SET)) + log_errx("Failed to set file position"); + + pad_size = toc_entry->offset_address - entry_offset; + while (pad_size--) + fputc(0x0, fp); + + free(buf); + fclose(fp); + return 0; +} + +/* + * This function is shared between the create and update subcommands. + * The difference between the two subcommands is that when the FIP file + * is created, the parsing of an existing FIP is skipped. This results + * in update_fip() creating the new FIP file from scratch because the + * internal image table is not populated. + */ +static void update_fip(void) +{ + image_desc_t *desc; + + /* Add or replace images in the FIP file. */ + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + image_t *image; + + if (desc->action != DO_PACK) + continue; + + image = read_image_from_file(&desc->uuid, + desc->action_arg); + if (desc->image != NULL) { + if (verbose) { + log_dbgx("Replacing %s with %s", + desc->cmdline_name, + desc->action_arg); + } + free(desc->image); + desc->image = image; + } else { + if (verbose) + log_dbgx("Adding image %s", + desc->action_arg); + desc->image = image; + } + } +} + +static void parse_plat_toc_flags(const char *arg, unsigned long long *toc_flags) +{ + unsigned long long flags; + char *endptr; + + errno = 0; + flags = strtoull(arg, &endptr, 16); + if (*endptr != '\0' || flags > UINT16_MAX || errno != 0) + log_errx("Invalid platform ToC flags: %s", arg); + /* Platform ToC flags is a 16-bit field occupying bits [32-47]. */ + *toc_flags |= flags << 32; +} + +static int is_power_of_2(unsigned long x) +{ + return x && !(x & (x - 1)); +} + +static unsigned long get_image_align(char *arg) +{ + char *endptr; + unsigned long align; + + errno = 0; + align = strtoul(arg, &endptr, 0); + if (*endptr != '\0' || !is_power_of_2(align) || errno != 0) + log_errx("Invalid alignment: %s", arg); + + return align; +} + +static void parse_blob_opt(char *arg, uuid_t *uuid, char *filename, size_t len) +{ + char *p; + + for (p = strtok(arg, ","); p != NULL; p = strtok(NULL, ",")) { + if (strncmp(p, "uuid=", strlen("uuid=")) == 0) { + p += strlen("uuid="); + uuid_from_str(uuid, p); + } else if (strncmp(p, "file=", strlen("file=")) == 0) { + p += strlen("file="); + snprintf(filename, len, "%s", p); + } + } +} + +static int create_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + unsigned long long toc_flags = 0; + unsigned long align = 1; + + if (argc < 2) + create_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, + OPT_PLAT_TOC_FLAGS); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_PACK, optarg); + break; + } + case OPT_PLAT_TOC_FLAGS: + parse_plat_toc_flags(optarg, &toc_flags); + break; + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + create_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_PACK, filename); + break; + } + default: + create_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + create_usage(EXIT_SUCCESS); + + update_fip(); + + pack_images(argv[0], toc_flags, align); + return 0; +} + +static void create_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool create [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...,file=...\tAdd an image with the given UUID pointed to by file.\n"); + printf(" --plat-toc-flags \t16-bit platform specific flag field occupying bits 32-47 in 64-bit ToC header.\n"); + printf("\n"); + printf("Specific images are packed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int update_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outfile[PATH_MAX] = { 0 }; + fip_toc_header_t toc_header = { 0 }; + unsigned long long toc_flags = 0; + unsigned long align = 1; + int pflag = 0; + + if (argc < 2) + update_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, "plat-toc-flags", required_argument, + OPT_PLAT_TOC_FLAGS); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:o:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_PACK, optarg); + break; + } + case OPT_PLAT_TOC_FLAGS: + parse_plat_toc_flags(optarg, &toc_flags); + pflag = 1; + break; + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + update_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_PACK, filename); + break; + } + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'o': + snprintf(outfile, sizeof(outfile), "%s", optarg); + break; + default: + update_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + update_usage(EXIT_SUCCESS); + + if (outfile[0] == '\0') + snprintf(outfile, sizeof(outfile), "%s", argv[0]); + + if (access(argv[0], F_OK) == 0) + parse_fip(argv[0], &toc_header); + + if (pflag) + toc_header.flags &= ~(0xffffULL << 32); + toc_flags = (toc_header.flags |= toc_flags); + + update_fip(); + + pack_images(outfile, toc_flags, align); + return 0; +} + +static void update_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool update [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \t\tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...,file=...\tAdd or update an image with the given UUID pointed to by file.\n"); + printf(" --out FIP_FILENAME\t\tSet an alternative output FIP file.\n"); + printf(" --plat-toc-flags \t16-bit platform specific flag field occupying bits 32-47 in 64-bit ToC header.\n"); + printf("\n"); + printf("Specific images are packed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int unpack_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outdir[PATH_MAX] = { 0 }; + image_desc_t *desc; + int fflag = 0; + int unpack_all = 1; + + if (argc < 2) + unpack_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, required_argument); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_UNPACK, optarg); + unpack_all = 0; + break; + } + case 'b': { + char name[_UUID_STR_LEN + 1]; + char filename[PATH_MAX] = { 0 }; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0 || + filename[0] == '\0') + unpack_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_UNPACK, filename); + unpack_all = 0; + break; + } + case 'f': + fflag = 1; + break; + case 'o': + snprintf(outdir, sizeof(outdir), "%s", optarg); + break; + default: + unpack_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + unpack_usage(EXIT_SUCCESS); + + parse_fip(argv[0], NULL); + + if (outdir[0] != '\0') + if (chdir(outdir) == -1) + log_err("chdir %s", outdir); + + /* Unpack all specified images. */ + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + char file[PATH_MAX]; + image_t *image = desc->image; + + if (!unpack_all && desc->action != DO_UNPACK) + continue; + + /* Build filename. */ + if (desc->action_arg == NULL) + snprintf(file, sizeof(file), "%s.bin", + desc->cmdline_name); + else + snprintf(file, sizeof(file), "%s", + desc->action_arg); + + if (image == NULL) { + if (!unpack_all) + log_warnx("%s does not exist in %s", + file, argv[0]); + continue; + } + + if (access(file, F_OK) != 0 || fflag) { + if (verbose) + log_dbgx("Unpacking %s", file); + write_image_to_file(image, file); + } else { + log_warnx("File %s already exists, use --force to overwrite it", + file); + } + } + + return 0; +} + +static void unpack_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool unpack [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --blob uuid=...,file=...\tUnpack an image with the given UUID to file.\n"); + printf(" --force\t\t\tIf the output file already exists, use --force to overwrite it.\n"); + printf(" --out path\t\t\tSet the output directory path.\n"); + printf("\n"); + printf("Specific images are unpacked with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s FILENAME\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + printf("\n"); + printf("If no options are provided, all images will be unpacked.\n"); + exit(exit_status); +} + +static int remove_cmd(int argc, char *argv[]) +{ + struct option *opts = NULL; + size_t nr_opts = 0; + char outfile[PATH_MAX] = { 0 }; + fip_toc_header_t toc_header; + image_desc_t *desc; + unsigned long align = 1; + int fflag = 0; + + if (argc < 2) + remove_usage(EXIT_FAILURE); + + opts = fill_common_opts(opts, &nr_opts, no_argument); + opts = add_opt(opts, &nr_opts, "align", required_argument, OPT_ALIGN); + opts = add_opt(opts, &nr_opts, "blob", required_argument, 'b'); + opts = add_opt(opts, &nr_opts, "force", no_argument, 'f'); + opts = add_opt(opts, &nr_opts, "out", required_argument, 'o'); + opts = add_opt(opts, &nr_opts, NULL, 0, 0); + + while (1) { + int c, opt_index = 0; + + c = getopt_long(argc, argv, "b:fo:", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case OPT_TOC_ENTRY: { + image_desc_t *desc; + + desc = lookup_image_desc_from_opt(opts[opt_index].name); + set_image_desc_action(desc, DO_REMOVE, NULL); + break; + } + case OPT_ALIGN: + align = get_image_align(optarg); + break; + case 'b': { + char name[_UUID_STR_LEN + 1], filename[PATH_MAX]; + uuid_t uuid = uuid_null; + image_desc_t *desc; + + parse_blob_opt(optarg, &uuid, + filename, sizeof(filename)); + + if (memcmp(&uuid, &uuid_null, sizeof(uuid_t)) == 0) + remove_usage(EXIT_FAILURE); + + desc = lookup_image_desc_from_uuid(&uuid); + if (desc == NULL) { + uuid_to_str(name, sizeof(name), &uuid); + desc = new_image_desc(&uuid, name, "blob"); + add_image_desc(desc); + } + set_image_desc_action(desc, DO_REMOVE, NULL); + break; + } + case 'f': + fflag = 1; + break; + case 'o': + snprintf(outfile, sizeof(outfile), "%s", optarg); + break; + default: + remove_usage(EXIT_FAILURE); + } + } + argc -= optind; + argv += optind; + free(opts); + + if (argc == 0) + remove_usage(EXIT_SUCCESS); + + if (outfile[0] != '\0' && access(outfile, F_OK) == 0 && !fflag) + log_errx("File %s already exists, use --force to overwrite it", + outfile); + + if (outfile[0] == '\0') + snprintf(outfile, sizeof(outfile), "%s", argv[0]); + + parse_fip(argv[0], &toc_header); + + for (desc = image_desc_head; desc != NULL; desc = desc->next) { + if (desc->action != DO_REMOVE) + continue; + + if (desc->image != NULL) { + if (verbose) + log_dbgx("Removing %s", + desc->cmdline_name); + free(desc->image); + desc->image = NULL; + } else { + log_warnx("%s does not exist in %s", + desc->cmdline_name, argv[0]); + } + } + + pack_images(outfile, toc_header.flags, align); + return 0; +} + +static void remove_usage(int exit_status) +{ + toc_entry_t *toc_entry = toc_entries; + + printf("fiptool remove [opts] FIP_FILENAME\n"); + printf("\n"); + printf("Options:\n"); + printf(" --align \tEach image is aligned to (default: 1).\n"); + printf(" --blob uuid=...\tRemove an image with the given UUID.\n"); + printf(" --force\t\tIf the output FIP file already exists, use --force to overwrite it.\n"); + printf(" --out FIP_FILENAME\tSet an alternative output FIP file.\n"); + printf("\n"); + printf("Specific images are removed with the following options:\n"); + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#ifdef PLAT_DEF_FIP_UUID + toc_entry = plat_def_toc_entries; + for (; toc_entry->cmdline_name != NULL; toc_entry++) + printf(" --%-16s\t%s\n", toc_entry->cmdline_name, + toc_entry->name); +#endif + exit(exit_status); +} + +static int version_cmd(int argc, char *argv[]) +{ +#ifdef VERSION + puts(VERSION); +#else + /* If built from fiptool directory, VERSION is not set. */ + puts("Unknown version"); +#endif + return 0; +} + +static void version_usage(int exit_status) +{ + printf("fiptool version\n"); + exit(exit_status); +} + +static int help_cmd(int argc, char *argv[]) +{ + int i; + + if (argc < 2) + usage(); + argc--, argv++; + + for (i = 0; i < NELEM(cmds); i++) { + if (strcmp(cmds[i].name, argv[0]) == 0 && + cmds[i].usage != NULL) + cmds[i].usage(EXIT_SUCCESS); + } + if (i == NELEM(cmds)) + printf("No help for subcommand '%s'\n", argv[0]); + return 0; +} + +static void usage(void) +{ + printf("usage: fiptool [--verbose] []\n"); + printf("Global options supported:\n"); + printf(" --verbose\tEnable verbose output for all commands.\n"); + printf("\n"); + printf("Commands supported:\n"); + printf(" info\t\tList images contained in FIP.\n"); + printf(" create\tCreate a new FIP with the given images.\n"); + printf(" update\tUpdate an existing FIP with the given images.\n"); + printf(" unpack\tUnpack images from FIP.\n"); + printf(" remove\tRemove images from FIP.\n"); + printf(" version\tShow fiptool version.\n"); + printf(" help\t\tShow help for given command.\n"); + exit(EXIT_SUCCESS); +} + +int main(int argc, char *argv[]) +{ + int i, ret = 0; + + while (1) { + int c, opt_index = 0; + static struct option opts[] = { + { "verbose", no_argument, NULL, 'v' }, + { NULL, no_argument, NULL, 0 } + }; + + /* + * Set POSIX mode so getopt stops at the first non-option + * which is the subcommand. + */ + c = getopt_long(argc, argv, "+v", opts, &opt_index); + if (c == -1) + break; + + switch (c) { + case 'v': + verbose = 1; + break; + default: + usage(); + } + } + argc -= optind; + argv += optind; + /* Reset optind for subsequent getopt processing. */ + optind = 0; + + if (argc == 0) + usage(); + + fill_image_descs(); + for (i = 0; i < NELEM(cmds); i++) { + if (strcmp(cmds[i].name, argv[0]) == 0) { + ret = cmds[i].handler(argc, argv); + break; + } + } + if (i == NELEM(cmds)) + usage(); + free_image_descs(); + return ret; +} diff --git a/arm-trusted-firmware/tools/fiptool/fiptool.h b/arm-trusted-firmware/tools/fiptool/fiptool.h new file mode 100644 index 0000000..88c4a7e --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/fiptool.h @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef FIPTOOL_H +#define FIPTOOL_H + +#include +#include + +#include +#include + +#include "fiptool_platform.h" + +#define NELEM(x) (sizeof (x) / sizeof *(x)) + +enum { + DO_UNSPEC = 0, + DO_PACK = 1, + DO_UNPACK = 2, + DO_REMOVE = 3 +}; + +enum { + LOG_DBG, + LOG_WARN, + LOG_ERR +}; + +typedef struct image_desc { + uuid_t uuid; + char *name; + char *cmdline_name; + int action; + char *action_arg; + struct image *image; + struct image_desc *next; +} image_desc_t; + +typedef struct image { + struct fip_toc_entry toc_e; + void *buffer; +} image_t; + +typedef struct cmd { + char *name; + int (*handler)(int, char **); + void (*usage)(int); +} cmd_t; + +#endif /* FIPTOOL_H */ diff --git a/arm-trusted-firmware/tools/fiptool/fiptool_platform.h b/arm-trusted-firmware/tools/fiptool/fiptool_platform.h new file mode 100644 index 0000000..9bfa298 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/fiptool_platform.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2016-2018, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ +/* + * Build platform specific handling. + * This allows for builds on non-Posix platforms + * e.g. Visual Studio on Windows + */ + +#ifndef FIPTOOL_PLATFORM_H +#define FIPTOOL_PLATFORM_H + +#ifndef _MSC_VER + +/* Not Visual Studio, so include Posix Headers. */ +# include +# include +# include + +# define BLD_PLAT_STAT stat + +#else + +/* Visual Studio. */ +# include "win_posix.h" + +#endif + +#endif /* FIPTOOL_PLATFORM_H */ diff --git a/arm-trusted-firmware/tools/fiptool/tbbr_config.c b/arm-trusted-firmware/tools/fiptool/tbbr_config.c new file mode 100644 index 0000000..4998bb2 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/tbbr_config.c @@ -0,0 +1,179 @@ +/* + * Copyright (c) 2016-2021, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "tbbr_config.h" + +/* The images used depends on the platform. */ +toc_entry_t toc_entries[] = { + { + .name = "SCP Firmware Updater Configuration FWU SCP_BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_SCP_BL2U, + .cmdline_name = "scp-fwu-cfg" + }, + { + .name = "AP Firmware Updater Configuration BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_BL2U, + .cmdline_name = "ap-fwu-cfg" + }, + { + .name = "Firmware Updater NS_BL2U", + .uuid = UUID_TRUSTED_UPDATE_FIRMWARE_NS_BL2U, + .cmdline_name = "fwu" + }, + { + .name = "Non-Trusted Firmware Updater certificate", + .uuid = UUID_TRUSTED_FWU_CERT, + .cmdline_name = "fwu-cert" + }, + { + .name = "Trusted Boot Firmware BL2", + .uuid = UUID_TRUSTED_BOOT_FIRMWARE_BL2, + .cmdline_name = "tb-fw" + }, + { + .name = "SCP Firmware SCP_BL2", + .uuid = UUID_SCP_FIRMWARE_SCP_BL2, + .cmdline_name = "scp-fw" + }, + { + .name = "EL3 Runtime Firmware BL31", + .uuid = UUID_EL3_RUNTIME_FIRMWARE_BL31, + .cmdline_name = "soc-fw" + }, + { + .name = "Secure Payload BL32 (Trusted OS)", + .uuid = UUID_SECURE_PAYLOAD_BL32, + .cmdline_name = "tos-fw" + }, + { + .name = "Secure Payload BL32 Extra1 (Trusted OS Extra1)", + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA1, + .cmdline_name = "tos-fw-extra1" + }, + { + .name = "Secure Payload BL32 Extra2 (Trusted OS Extra2)", + .uuid = UUID_SECURE_PAYLOAD_BL32_EXTRA2, + .cmdline_name = "tos-fw-extra2" + }, + { + .name = "Non-Trusted Firmware BL33", + .uuid = UUID_NON_TRUSTED_FIRMWARE_BL33, + .cmdline_name = "nt-fw" + }, + { + .name = "Realm Monitor Management Firmware", + .uuid = UUID_REALM_MONITOR_MGMT_FIRMWARE, + .cmdline_name = "rmm-fw" + }, + /* Dynamic Configs */ + { + .name = "FW_CONFIG", + .uuid = UUID_FW_CONFIG, + .cmdline_name = "fw-config" + }, + { + .name = "HW_CONFIG", + .uuid = UUID_HW_CONFIG, + .cmdline_name = "hw-config" + }, + { + .name = "TB_FW_CONFIG", + .uuid = UUID_TB_FW_CONFIG, + .cmdline_name = "tb-fw-config" + }, + { + .name = "SOC_FW_CONFIG", + .uuid = UUID_SOC_FW_CONFIG, + .cmdline_name = "soc-fw-config" + }, + { + .name = "TOS_FW_CONFIG", + .uuid = UUID_TOS_FW_CONFIG, + .cmdline_name = "tos-fw-config" + }, + { + .name = "NT_FW_CONFIG", + .uuid = UUID_NT_FW_CONFIG, + .cmdline_name = "nt-fw-config" + }, + /* Key Certificates */ + { + .name = "Root Of Trust key certificate", + .uuid = UUID_ROT_KEY_CERT, + .cmdline_name = "rot-cert" + }, + { + .name = "Trusted key certificate", + .uuid = UUID_TRUSTED_KEY_CERT, + .cmdline_name = "trusted-key-cert" + }, + { + .name = "SCP Firmware key certificate", + .uuid = UUID_SCP_FW_KEY_CERT, + .cmdline_name = "scp-fw-key-cert" + }, + { + .name = "SoC Firmware key certificate", + .uuid = UUID_SOC_FW_KEY_CERT, + .cmdline_name = "soc-fw-key-cert" + }, + { + .name = "Trusted OS Firmware key certificate", + .uuid = UUID_TRUSTED_OS_FW_KEY_CERT, + .cmdline_name = "tos-fw-key-cert" + }, + { + .name = "Non-Trusted Firmware key certificate", + .uuid = UUID_NON_TRUSTED_FW_KEY_CERT, + .cmdline_name = "nt-fw-key-cert" + }, + + /* Content certificates */ + { + .name = "Trusted Boot Firmware BL2 certificate", + .uuid = UUID_TRUSTED_BOOT_FW_CERT, + .cmdline_name = "tb-fw-cert" + }, + { + .name = "SCP Firmware content certificate", + .uuid = UUID_SCP_FW_CONTENT_CERT, + .cmdline_name = "scp-fw-cert" + }, + { + .name = "SoC Firmware content certificate", + .uuid = UUID_SOC_FW_CONTENT_CERT, + .cmdline_name = "soc-fw-cert" + }, + { + .name = "Trusted OS Firmware content certificate", + .uuid = UUID_TRUSTED_OS_FW_CONTENT_CERT, + .cmdline_name = "tos-fw-cert" + }, + { + .name = "Non-Trusted Firmware content certificate", + .uuid = UUID_NON_TRUSTED_FW_CONTENT_CERT, + .cmdline_name = "nt-fw-cert" + }, + { + .name = "SiP owned Secure Partition content certificate", + .uuid = UUID_SIP_SECURE_PARTITION_CONTENT_CERT, + .cmdline_name = "sip-sp-cert" + }, + { + .name = "Platform owned Secure Partition content certificate", + .uuid = UUID_PLAT_SECURE_PARTITION_CONTENT_CERT, + .cmdline_name = "plat-sp-cert" + }, + { + .name = NULL, + .uuid = { {0} }, + .cmdline_name = NULL, + } +}; diff --git a/arm-trusted-firmware/tools/fiptool/tbbr_config.h b/arm-trusted-firmware/tools/fiptool/tbbr_config.h new file mode 100644 index 0000000..b926ff0 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/tbbr_config.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2016-2017, ARM Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef TBBR_CONFIG_H +#define TBBR_CONFIG_H + +#include + +#include + +#define TOC_HEADER_SERIAL_NUMBER 0x12345678 + +typedef struct toc_entry { + char *name; + uuid_t uuid; + char *cmdline_name; +} toc_entry_t; + +extern toc_entry_t toc_entries[]; + +#ifdef PLAT_DEF_FIP_UUID +extern toc_entry_t plat_def_toc_entries[]; +#endif + +#endif /* TBBR_CONFIG_H */ diff --git a/arm-trusted-firmware/tools/fiptool/win_posix.c b/arm-trusted-firmware/tools/fiptool/win_posix.c new file mode 100644 index 0000000..33b44d4 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/win_posix.c @@ -0,0 +1,318 @@ +/* + * Copyright (c) 2017 - 2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include "win_posix.h" + +/* + * This variable is set by getopt to the index of the next element of the + * argv array to be processed. Once getopt has found all of the option + * arguments, you can use this variable to determine where the remaining + * non-option arguments begin. The initial value of this variable is 1. + */ +int optind = 1; + +/* + * If the value of this variable is nonzero, then getopt prints an error + * message to the standard error stream if it encounters an unknown option + * default character or an option with a missing required argument. + * If you set this variable to zero, getopt does not print any messages, + * but it still returns the character ? to indicate an error. + */ +const int opterr; /* = 0; */ +/* const because we do not implement error printing.*/ +/* Not initialised to conform with the coding standard. */ + +/* + * When getopt encounters an unknown option character or an option with a + * missing required argument, it stores that option character in this + * variable. + */ +int optopt; /* = 0; */ + +/* + * This variable is set by getopt to point at the value of the option + * argument, for those options that accept arguments. + */ +char *optarg; /* = 0; */ + +enum return_flags { + RET_ERROR = -1, + RET_END_OPT_LIST = -1, + RET_NO_PARAM = '?', + RET_NO_PARAM2 = ':', + RET_UNKNOWN_OPT = '?' +}; + +/* + * Common initialisation on entry. + */ +static +void getopt_init(void) +{ + optarg = (char *)0; + optopt = 0; + /* optind may be zero with some POSIX uses. + * For our purposes we just change it to 1. + */ + if (optind == 0) + optind = 1; +} + +/* + * Common handling for a single letter option. + */ +static +int getopt_1char(int argc, + char *const argv[], + const char *const opstring, + const int optchar) +{ + size_t nlen = (opstring == 0) ? 0 : strlen(opstring); + size_t loptn; + + for (loptn = 0; loptn < nlen; loptn++) { + if (optchar == opstring[loptn]) { + if (opstring[loptn + 1] == ':') { + /* Option has argument */ + if (optind < argc) { + /* Found argument. */ + assert(argv != 0); + optind++; + optarg = argv[optind++]; + return optchar; + } + /* Missing argument. */ + if (opstring[loptn + 2] == ':') { + /* OK if optional "x::". */ + optind++; + return optchar; + } + /* Actual missing value. */ + optopt = optchar; + return ((opstring[0] == ':') + ? RET_NO_PARAM2 + : RET_NO_PARAM); + } + /* No argument, just return option char */ + optind++; + return optchar; + } + } + /* + * If getopt finds an option character in argv that was not included in + * options, ... it returns '?' and sets the external variable optopt to + * the actual option character. + */ + optopt = optchar; + return RET_UNKNOWN_OPT; +} + +int getopt(int argc, + char *argv[], + char *opstring) +{ + int result = RET_END_OPT_LIST; + size_t argn = 0; + size_t nlen = strlen(opstring); + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = (const char *)argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) + result = getopt_1char(argc, argv, opstring, arg[1]); + } + + return result; +} + +/* + * Match an argument value against an option name. + * Note that we only match over the shorter length of the pair, to allow + * for abbreviation or say --match=value + * Long option names may be abbreviated if the abbreviation is unique or an + * exact match for some defined option. This function does not check that the + * abbreviations are unique and should be handled by the caller. + * A long option may take a parameter, of the form --opt=param or --opt param. +*/ +static +int optmatch(const char *argval, const char *optname) +{ + int result = 0; + + while ((result == 0) && (*optname != 0) && (*argval != 0)) + result = (*argval++) - (*optname++); + return result; +} + +/* Handling for a single long option. */ +static +int getopt_1long(const int argc, + char *const argv[], + const struct option *const longopts, + const char *const optname, + int *const indexptr) +{ + int result = RET_UNKNOWN_OPT; + size_t loptn = 0; + bool match_found = false; + + /* + * Long option names may be abbreviated if the abbreviation + * is unique or an exact match for some defined option. + * To handle this: + * - First search for an exact match. + * - If exact match was not found search for a abbreviated match. + * By doing this an incorrect option selection can be avoided. + */ + + /* 1. Search for an exact match. */ + while (longopts[loptn].name != NULL) { + if (strcmp(optname, longopts[loptn].name) == 0) { + match_found = true; + break; + } + ++loptn; + } + + /* 2. If exact match was not found search for a abbreviated match. */ + if (!match_found) { + loptn = 0; + while (longopts[loptn].name != NULL) { + if (optmatch(optname, longopts[loptn].name) == 0) { + match_found = true; + break; + } + ++loptn; + } + } + + if (match_found) { + /* We found a match. */ + result = longopts[loptn].val; + if (indexptr != 0) { + *indexptr = loptn; + } + switch (longopts[loptn].has_arg) { + case required_argument: + if ((optind + 1) >= argc) { + /* Missing argument. */ + optopt = result; + return RET_NO_PARAM; + } + /* Fallthrough to get option value. */ + + case optional_argument: + if ((argc - optind) > 0) { + /* Found argument. */ + optarg = argv[++optind]; + } + /* Fallthrough to handle flag. */ + + case no_argument: + optind++; + if (longopts[loptn].flag != 0) { + *longopts[loptn].flag = result; + result = 0; + } + break; + + } + return result; + } + + /* + * If getopt finds an option character in argv that was not included + * in options, ... it returns '?' and sets the external variable + * optopt to the actual option character. + */ + return RET_UNKNOWN_OPT; +} + +/* + * getopt_long gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * (single letter) as for getopt, or longer names (preceded by --). + */ +int getopt_long(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr) +{ + int result = RET_END_OPT_LIST; + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) { + if (arg[1] == '-') { + /* Looks like a long option. */ + result = getopt_1long(argc, + argv, + longopts, + &arg[2], + indexptr); + } else { + result = getopt_1char(argc, + argv, + shortopts, + arg[1]); + } + } + } + return result; +} + +/* + * getopt_long_only gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * or long as for getopt_long, but the long names may have a single '-' + * prefix too. + */ +int getopt_long_only(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr) +{ + int result = RET_END_OPT_LIST; + + getopt_init(); + /* If we have an argument left to play with */ + if ((argc > optind) && (argv != 0)) { + const char *arg = argv[optind]; + + if ((arg != 0) && (arg[0] == '-')) { + if (arg[1] == '-') { + /* Looks like a long option. */ + result = getopt_1long(argc, + argv, + longopts, + &arg[2], + indexptr); + } else { + result = getopt_1long(argc, + argv, + longopts, + &arg[1], + indexptr); + if (result == RET_UNKNOWN_OPT) { + result = getopt_1char(argc, + argv, + shortopts, + arg[1]); + } + } + } + } + return result; +} diff --git a/arm-trusted-firmware/tools/fiptool/win_posix.h b/arm-trusted-firmware/tools/fiptool/win_posix.h new file mode 100644 index 0000000..6f0d8e6 --- /dev/null +++ b/arm-trusted-firmware/tools/fiptool/win_posix.h @@ -0,0 +1,188 @@ +/* + * Copyright (c) 2017-2020, Arm Limited and Contributors. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef WIN_POSIX_H +#define WIN_POSIX_H + +#define _CRT_SECURE_NO_WARNINGS + +#include +#include +#include +#include +#include + +#include +#include + +#include "uuid.h" + +/* Derive or provide Windows equivalents of Posix/GCC/Unix stuff. */ +#ifndef PATH_MAX +# ifdef MAX_PATH +# define PATH_MAX MAX_PATH +# else +# ifdef _MAX_PATH +# define MAX_PATH _MAX_PATH +# define PATH_MAX _MAX_PATH +# else +# define PATH_MAX 260 +# endif +# endif +#endif + +#ifndef _CRT_SECURE_NO_WARNINGS +# define _CRT_SECURE_NO_WARNINGS 1 +#endif + +/* + * Platform specific names. + * + * Visual Studio deprecates a number of POSIX functions and only provides + * ISO C++ compliant alternatives (distinguished by their '_' prefix). + * These macros help provide a stopgap for that. + */ + +/* fileno cannot be an inline function, because _fileno is a macro. */ +#define fileno(fileptr) _fileno(fileptr) + +/* _fstat uses the _stat structure, not stat. */ +#define BLD_PLAT_STAT _stat + +/* Define flag values for _access. */ +#define F_OK 0 + + +/* getopt implementation for Windows: Data. */ + +/* Legitimate values for option.has_arg. */ +enum has_arg_values { + no_argument, /* No argument value required */ + required_argument, /* value must be specified. */ + optional_argument /* value may be specified. */ +}; + +/* Long option table entry for get_opt_long. */ +struct option { + /* The name of the option. */ + const char *name; + + /* + * Indicates whether the option takes an argument. + * Possible values: see has_arg_values above. + */ + int has_arg; + + /* If not null, when option present, *flag is set to val. */ + int *flag; + + /* + * The value associated with this option to return + * (and save in *flag when not null) + */ + int val; +}; + +/* + * This variable is set by getopt to point at the value of the option + * argument, for those options that accept arguments. + */ +extern char *optarg; + +/* + * When this variable is not zero, getopt emits an error message to stderr + * if it encounters an unspecified option, or a missing argument. + * Otherwise no message is reported. + */ +extern const int opterr; /* const as NOT used in this implementation. */ + +/* + * This variable is set by getopt to the index of the next element of the + * argv array to be processed. Once getopt has found all of the option + * arguments, you can use this variable to determine where the remaining + * non-option arguments begin. The initial value of this variable is 1. + */ +extern int optind; + +/* + * When getopt encounters an unknown option character or an option with a + * missing required argument, it stores that option character in this + * variable. + */ +extern int optopt; + + +/* + * Platform specific names. + * + * Visual Studio deprecates a number of POSIX functions and only provides + * ISO C++ compliant alternatives (distinguished by their '_' prefix). + * These inline functions provide a stopgap for that. + */ + +inline int access(const char *path, int mode) +{ + return _access(path, mode); +} + +inline int chdir(const char *s) +{ + return _chdir(s); +} + +inline int fstat(int fd, struct _stat *buffer) +{ + return _fstat(fd, buffer); +} + +inline char *strdup(const char *s) +{ + return _strdup(s); +} + +/* + * getopt implementation for Windows: Functions. + * + * Windows does not have the getopt family of functions, as it normally + * uses '/' instead of '-' as the command line option delimiter. + * These functions provide a Windows version that uses '-', which precludes + * using '-' as the intial letter of a program argument. + * This is not seen as a problem in the specific instance of fiptool, + * and enables existing makefiles to work on a Windows build environment. + */ + +/* + * The getopt function gets the next option argument from the argument list + * specified by the argv and argc arguments. + */ +int getopt(int argc, + char *argv[], + char *options); + +/* + * getopt_long gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * (single letter) as for getopt, or longer names (preceded by --). + */ +int getopt_long(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr); + +/* + * getopt_long_only gets the next option argument from the argument list + * specified by the argv and argc arguments. Options may be either short + * or long as for getopt_long, but the long names may have a single '-' + * prefix, too. + */ +int getopt_long_only(int argc, + char *argv[], + const char *shortopts, + const struct option *longopts, + int *indexptr); + +#endif /* WIN_POSIX_H */ diff --git a/arm-trusted-firmware/tools/marvell/doimage/Makefile b/arm-trusted-firmware/tools/marvell/doimage/Makefile new file mode 100644 index 0000000..9f0d89d --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/Makefile @@ -0,0 +1,48 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +PROJECT = doimage +OBJECTS = doimage.o + +HOSTCCFLAGS = -Wall -Werror +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${MARVELL_SECURE_BOOT},1) +DOIMAGE_CC_FLAGS := -DCONFIG_MVEBU_SECURE_BOOT +DOIMAGE_LD_FLAGS := -lconfig -lmbedtls -lmbedcrypto -lmbedx509 +endif + +HOSTCCFLAGS += ${DOIMAGE_CC_FLAGS} + +# Make soft links and include from local directory otherwise wrong headers +# could get pulled in from firmware tree. +INCLUDE_PATHS = -I. + +HOSTCC ?= gcc +RM := rm -rf + +.PHONY: all clean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} ${DOIMAGE_LD_FLAGS} -o $@ + @echo + @echo "Built $@ successfully" + @echo + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + ${Q}${RM} ${PROJECT} + ${Q}${RM} ${OBJECTS} diff --git a/arm-trusted-firmware/tools/marvell/doimage/doimage.c b/arm-trusted-firmware/tools/marvell/doimage/doimage.c new file mode 100644 index 0000000..e08b820 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/doimage.c @@ -0,0 +1,1764 @@ +/* + * Copyright (C) 2018 Marvell International Ltd. + * + * SPDX-License-Identifier: BSD-3-Clause + * https://spdx.org/licenses + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef CONFIG_MVEBU_SECURE_BOOT +#include /* for parsing config file */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +/* mbedTLS stuff */ +#if defined(MBEDTLS_BIGNUM_C) && defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_SHA256_C) && \ + defined(MBEDTLS_PK_PARSE_C) && defined(MBEDTLS_FS_IO) && \ + defined(MBEDTLS_CTR_DRBG_C) +#include +#include +#include +#include +#include +#include +#include +#else +#error "Bad mbedTLS configuration!" +#endif +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + +#define MAX_FILENAME 256 +#define CSK_ARR_SZ 16 +#define CSK_ARR_EMPTY_FILE "*" +#define AES_KEY_BIT_LEN 256 +#define AES_KEY_BYTE_LEN (AES_KEY_BIT_LEN >> 3) +#define AES_BLOCK_SZ 16 +#define RSA_SIGN_BYTE_LEN 256 +#define MAX_RSA_DER_BYTE_LEN 524 +/* Number of address pairs in control array */ +#define CP_CTRL_EL_ARRAY_SZ 32 + +#define VERSION_STRING "Marvell(C) doimage utility version 3.3" + +/* A8K definitions */ + +/* Extension header types */ +#define EXT_TYPE_SECURITY 0x1 +#define EXT_TYPE_BINARY 0x2 + +#define MAIN_HDR_MAGIC 0xB105B002 + +/* PROLOG alignment considerations: + * 128B: To allow supporting XMODEM protocol. + * 8KB: To align the boot image to the largest NAND page size, and simplify + * the read operations from NAND. + * We choose the largest page size, in order to use a single image for all + * NAND page sizes. + */ +#define PROLOG_ALIGNMENT (8 << 10) + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +typedef struct _main_header { + uint32_t magic; /* 0-3 */ + uint32_t prolog_size; /* 4-7 */ + uint32_t prolog_checksum; /* 8-11 */ + uint32_t boot_image_size; /* 12-15 */ + uint32_t boot_image_checksum; /* 16-19 */ + uint32_t rsrvd0; /* 20-23 */ + uint32_t load_addr; /* 24-27 */ + uint32_t exec_addr; /* 28-31 */ + uint8_t uart_cfg; /* 32 */ + uint8_t baudrate; /* 33 */ + uint8_t ext_count; /* 34 */ + uint8_t aux_flags; /* 35 */ + uint32_t io_arg_0; /* 36-39 */ + uint32_t io_arg_1; /* 40-43 */ + uint32_t io_arg_2; /* 43-47 */ + uint32_t io_arg_3; /* 48-51 */ + uint32_t rsrvd1; /* 52-55 */ + uint32_t rsrvd2; /* 56-59 */ + uint32_t rsrvd3; /* 60-63 */ +} header_t; + +typedef struct _ext_header { + uint8_t type; + uint8_t offset; + uint16_t reserved; + uint32_t size; +} ext_header_t; + +typedef struct _sec_entry { + uint8_t kak_key[MAX_RSA_DER_BYTE_LEN]; + uint32_t jtag_delay; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_en; + uint32_t encrypt_en; + uint32_t efuse_dis; + uint8_t header_sign[RSA_SIGN_BYTE_LEN]; + uint8_t image_sign[RSA_SIGN_BYTE_LEN]; + uint8_t csk_keys[CSK_ARR_SZ][MAX_RSA_DER_BYTE_LEN]; + uint8_t csk_sign[RSA_SIGN_BYTE_LEN]; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; +} sec_entry_t; + +/* A8K definitions end */ + +/* UART argument bitfield */ +#define UART_MODE_UNMODIFIED 0x0 +#define UART_MODE_DISABLE 0x1 +#define UART_MODE_UPDATE 0x2 + +#define uart_set_mode(arg, mode) (arg |= (mode & 0x3)) + +typedef struct _sec_options { +#ifdef CONFIG_MVEBU_SECURE_BOOT + char aes_key_file[MAX_FILENAME+1]; + char kak_key_file[MAX_FILENAME+1]; + char csk_key_file[CSK_ARR_SZ][MAX_FILENAME+1]; + uint32_t box_id; + uint32_t flash_id; + uint32_t jtag_delay; + uint8_t csk_index; + uint8_t jtag_enable; + uint8_t efuse_disable; + uint32_t cp_ctrl_arr[CP_CTRL_EL_ARRAY_SZ]; + uint32_t cp_efuse_arr[CP_CTRL_EL_ARRAY_SZ]; + mbedtls_pk_context kak_pk; + mbedtls_pk_context csk_pk[CSK_ARR_SZ]; + uint8_t aes_key[AES_KEY_BYTE_LEN]; + uint8_t *encrypted_image; + uint32_t enc_image_sz; +#endif +} sec_options; + +typedef struct _options { + char bin_ext_file[MAX_FILENAME+1]; + char sec_cfg_file[MAX_FILENAME+1]; + sec_options *sec_opts; + uint32_t load_addr; + uint32_t exec_addr; + uint32_t baudrate; + uint8_t disable_print; + int8_t key_index; /* For header signatures verification only */ + uint32_t nfc_io_args; +} options_t; + +void usage_err(char *msg) +{ + fprintf(stderr, "Error: %s\n", msg); + fprintf(stderr, "run 'doimage -h' to get usage information\n"); + exit(-1); +} + +void usage(void) +{ + printf("\n\n%s\n\n", VERSION_STRING); + printf("Usage: doimage [options] [output_file]\n"); + printf("create bootrom image from u-boot and boot extensions\n\n"); + + printf("Arguments\n"); + printf(" input_file name of boot image file.\n"); + printf(" if -p is used, name of the bootrom image file"); + printf(" to parse.\n"); + printf(" output_file name of output bootrom image file\n"); + + printf("\nOptions\n"); + printf(" -s target SOC name. supports a8020,a7020\n"); + printf(" different SOCs may have different boot image\n"); + printf(" format so it's mandatory to know the target SOC\n"); + printf(" -i boot I/F name. supports nand, spi, nor\n"); + printf(" This affects certain parameters coded in the\n"); + printf(" image header\n"); + printf(" -l boot image load address. default is 0x0\n"); + printf(" -e boot image entry address. default is 0x0\n"); + printf(" -b binary extension image file.\n"); + printf(" This image is executed before the boot image.\n"); + printf(" This is typically used to initialize the memory "); + printf(" controller.\n"); + printf(" Currently supports only a single file.\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -c Make trusted boot image using parameters\n"); + printf(" from the configuration file.\n"); +#endif + printf(" -p Parse and display a pre-built boot image\n"); +#ifdef CONFIG_MVEBU_SECURE_BOOT + printf(" -k Key index for RSA signatures verification\n"); + printf(" when parsing the boot image\n"); +#endif + printf(" -m Disable prints of bootrom and binary extension\n"); + printf(" -u UART baudrate used for bootrom prints.\n"); + printf(" Must be multiple of 1200\n"); + printf(" -h Show this help message\n"); + printf(" IO-ROM NFC-NAND boot parameters:\n"); + printf(" -n NAND device block size in KB [Default is 64KB].\n"); + printf(" -t NAND cell technology (SLC [Default] or MLC)\n"); + + exit(-1); +} + +/* globals */ +static options_t opts = { + .bin_ext_file = "NA", + .sec_cfg_file = "NA", + .sec_opts = 0, + .load_addr = 0x0, + .exec_addr = 0x0, + .disable_print = 0, + .baudrate = 0, + .key_index = -1, +}; + +int get_file_size(char *filename) +{ + struct stat st; + + if (stat(filename, &st) == 0) + return st.st_size; + + return -1; +} + +uint32_t checksum32(uint32_t *start, int len) +{ + uint32_t sum = 0; + uint32_t *startp = start; + + do { + sum += *startp; + startp++; + len -= 4; + } while (len > 0); + + return sum; +} + +/******************************************************************************* + * create_rsa_signature (memory buffer content) + * Create RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Private Key + * INPUT: + * pk_ctx Private Key context + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * For instance a private key file name. + * OUTPUT: + * signature RSA-2048 signature + * RETURN: + * 0 on success + */ +#ifdef CONFIG_MVEBU_SECURE_BOOT +int create_rsa_signature(mbedtls_pk_context *pk_ctx, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + unsigned char hash[32]; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + int rval; + + /* Not sure this is required, + * but it's safer to start with empty buffers + */ + memset(hash, 0, sizeof(hash)); + memset(buf, 0, sizeof(buf)); + + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto sign_exit; + } + + /* The PK context should be already initialized. + * Set the padding type for this PK context + */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(*pk_ctx), + MBEDTLS_RSA_PKCS_V21, MBEDTLS_MD_SHA256); + + /* First compute the SHA256 hash for the input blob */ + mbedtls_sha256_ret(input, ilen, hash, 0); + + /* Then calculate the hash signature */ + rval = mbedtls_rsa_rsassa_pss_sign(mbedtls_pk_rsa(*pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PRIVATE, + MBEDTLS_MD_SHA256, 0, hash, buf); + if (rval != 0) { + fprintf(stderr, + "Failed to create RSA signature for %s. Error %d\n", + pers, rval); + goto sign_exit; + } + memcpy(signature, buf, 256); + +sign_exit: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + + return rval; +} /* end of create_rsa_signature */ + +/******************************************************************************* + * verify_rsa_signature (memory buffer content) + * Verify RSASSA-PSS/SHA-256 signature for memory buffer + * using RSA Public Key + * INPUT: + * pub_key Public Key buffer + * ilen Public Key buffer length + * input memory buffer + * ilen buffer length + * pers personalization string for seeding the RNG. + * signature RSA-2048 signature + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_rsa_signature(const unsigned char *pub_key, + size_t klen, + const unsigned char *input, + size_t ilen, + const char *pers, + uint8_t *signature) +{ + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + mbedtls_pk_context pk_ctx; + unsigned char hash[32]; + int rval; + unsigned char *pkey = (unsigned char *)pub_key; + + /* Not sure this is required, + * but it's safer to start with empty buffer + */ + memset(hash, 0, sizeof(hash)); + + mbedtls_pk_init(&pk_ctx); + mbedtls_ctr_drbg_init(&ctr_drbg); + mbedtls_entropy_init(&entropy); + + /* Seed the random number generator */ + rval = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, + (const unsigned char *)pers, strlen(pers)); + if (rval != 0) { + fprintf(stderr, " Failed in ctr_drbg_init call (%d)!\n", rval); + goto verify_exit; + } + + /* Check ability to read the public key */ + rval = mbedtls_pk_parse_subpubkey(&pkey, pub_key + klen, &pk_ctx); + if (rval != 0) { + fprintf(stderr, " Failed in pk_parse_public_key (%#x)!\n", + rval); + goto verify_exit; + } + + /* Set the padding type for the new PK context */ + mbedtls_rsa_set_padding(mbedtls_pk_rsa(pk_ctx), + MBEDTLS_RSA_PKCS_V21, + MBEDTLS_MD_SHA256); + + /* Compute the SHA256 hash for the input buffer */ + mbedtls_sha256_ret(input, ilen, hash, 0); + + rval = mbedtls_rsa_rsassa_pss_verify(mbedtls_pk_rsa(pk_ctx), + mbedtls_ctr_drbg_random, + &ctr_drbg, + MBEDTLS_RSA_PUBLIC, + MBEDTLS_MD_SHA256, 0, + hash, signature); + if (rval != 0) + fprintf(stderr, "Failed to verify signature (%d)!\n", rval); + +verify_exit: + + mbedtls_pk_free(&pk_ctx); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_entropy_free(&entropy); + return rval; +} /* end of verify_rsa_signature */ + +/******************************************************************************* + * image_encrypt + * Encrypt image buffer using AES-256-CBC scheme. + * The resulting image is saved into opts.sec_opts->encrypted_image + * and the adjusted image size into opts.sec_opts->enc_image_sz + * First AES_BLOCK_SZ bytes of the output image contain IV + * INPUT: + * buf Source buffer to encrypt + * blen Source buffer length + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int image_encrypt(uint8_t *buf, uint32_t blen) +{ + struct timeval tv; + char *ptmp = (char *)&tv; + unsigned char digest[32]; + unsigned char IV[AES_BLOCK_SZ]; + int i, k; + mbedtls_aes_context aes_ctx; + int rval = -1; + uint8_t *test_img = 0; + + if (AES_BLOCK_SZ > 32) { + fprintf(stderr, "Unsupported AES block size %d\n", + AES_BLOCK_SZ); + return rval; + } + + mbedtls_aes_init(&aes_ctx); + memset(IV, 0, AES_BLOCK_SZ); + memset(digest, 0, 32); + + /* Generate initialization vector and init the AES engine + * Use file name XOR current time and finally SHA-256 + * [0...AES_BLOCK_SZ-1] + */ + k = strlen(opts.sec_opts->aes_key_file); + if (k > AES_BLOCK_SZ) + k = AES_BLOCK_SZ; + memcpy(IV, opts.sec_opts->aes_key_file, k); + gettimeofday(&tv, 0); + + for (i = 0, k = 0; i < AES_BLOCK_SZ; i++, + k = (k+1) % sizeof(struct timeval)) + IV[i] ^= ptmp[k]; + + /* compute SHA-256 digest of the results + * and use it as the init vector (IV) + */ + mbedtls_sha256_ret(IV, AES_BLOCK_SZ, digest, 0); + memcpy(IV, digest, AES_BLOCK_SZ); + mbedtls_aes_setkey_enc(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + /* The output image has to include extra space for IV + * and to be aligned to the AES block size. + * The input image buffer has to be already aligned to AES_BLOCK_SZ + * and padded with zeroes + */ + opts.sec_opts->enc_image_sz = (blen + 2 * AES_BLOCK_SZ - 1) & + ~(AES_BLOCK_SZ - 1); + opts.sec_opts->encrypted_image = calloc(opts.sec_opts->enc_image_sz, 1); + if (opts.sec_opts->encrypted_image == 0) { + fprintf(stderr, "Failed to allocate encrypted image!\n"); + goto encrypt_exit; + } + + /* Put IV into the output buffer next to the encrypted image + * Since the IV is modified by the encryption function, + * this should be done now + */ + memcpy(opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_ENCRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, buf, opts.sec_opts->encrypted_image); + if (rval != 0) { + fprintf(stderr, "Failed to encrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + mbedtls_aes_free(&aes_ctx); + + /* Try to decrypt the image and compare it with the original data */ + mbedtls_aes_init(&aes_ctx); + mbedtls_aes_setkey_dec(&aes_ctx, opts.sec_opts->aes_key, + AES_KEY_BIT_LEN); + + test_img = calloc(opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, 1); + if (test_img == 0) { + fprintf(stderr, "Failed to allocate test image!d\n"); + rval = -1; + goto encrypt_exit; + } + + memcpy(IV, opts.sec_opts->encrypted_image + + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + AES_BLOCK_SZ); + rval = mbedtls_aes_crypt_cbc(&aes_ctx, MBEDTLS_AES_DECRYPT, + opts.sec_opts->enc_image_sz - AES_BLOCK_SZ, + IV, opts.sec_opts->encrypted_image, test_img); + if (rval != 0) { + fprintf(stderr, "Failed to decrypt the image! Error %d\n", + rval); + goto encrypt_exit; + } + + for (i = 0; i < blen; i++) { + if (buf[i] != test_img[i]) { + fprintf(stderr, "Failed to compare the image after"); + fprintf(stderr, " decryption! Byte count is %d\n", i); + rval = -1; + goto encrypt_exit; + } + } + +encrypt_exit: + + mbedtls_aes_free(&aes_ctx); + if (test_img) + free(test_img); + + return rval; +} /* end of image_encrypt */ + +/******************************************************************************* + * verify_secure_header_signatures + * Verify CSK array, header and image signatures and print results + * INPUT: + * main_hdr Main header + * sec_ext Secure extension + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int verify_secure_header_signatures(header_t *main_hdr, sec_entry_t *sec_ext) +{ + uint8_t *image = (uint8_t *)main_hdr + main_hdr->prolog_size; + uint8_t signature[RSA_SIGN_BYTE_LEN]; + int rval = -1; + + /* Save headers signature and reset it in the secure header */ + memcpy(signature, sec_ext->header_sign, RSA_SIGN_BYTE_LEN); + memset(sec_ext->header_sign, 0, RSA_SIGN_BYTE_LEN); + + fprintf(stdout, "\nCheck RSA Signatures\n"); + fprintf(stdout, "#########################\n"); + fprintf(stdout, "CSK Block Signature: "); + if (verify_rsa_signature(sec_ext->kak_key, + MAX_RSA_DER_BYTE_LEN, + &sec_ext->csk_keys[0][0], + sizeof(sec_ext->csk_keys), + "CSK Block Signature: ", + sec_ext->csk_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + if (opts.key_index != -1) { + fprintf(stdout, "Image Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + image, main_hdr->boot_image_size, + "Image Signature: ", + sec_ext->image_sign) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + + fprintf(stdout, "Header Signature: "); + if (verify_rsa_signature(sec_ext->csk_keys[opts.key_index], + MAX_RSA_DER_BYTE_LEN, + (uint8_t *)main_hdr, + main_hdr->prolog_size, + "Header Signature: ", + signature) != 0) { + fprintf(stdout, "ERROR\n"); + goto ver_error; + } + fprintf(stdout, "OK\n"); + } else { + fprintf(stdout, "SKIP Image and Header Signatures"); + fprintf(stdout, " check (undefined key index)\n"); + } + + rval = 0; + +ver_error: + memcpy(sec_ext->header_sign, signature, RSA_SIGN_BYTE_LEN); + return rval; +} + +/******************************************************************************* + * verify_and_copy_file_name_entry + * INPUT: + * element_name + * element + * OUTPUT: + * copy_to + * RETURN: + * 0 on success + */ +int verify_and_copy_file_name_entry(const char *element_name, + const char *element, char *copy_to) +{ + int element_length = strlen(element); + + if (element_length >= MAX_FILENAME) { + fprintf(stderr, "The file name %s for %s is too long (%d). ", + element, element_name, element_length); + fprintf(stderr, "Maximum allowed %d characters!\n", + MAX_FILENAME); + return -1; + } else if (element_length == 0) { + fprintf(stderr, "The file name for %s is empty!\n", + element_name); + return -1; + } + memcpy(copy_to, element, element_length); + + return 0; +} + +/******************************************************************************* + * parse_sec_config_file + * Read the secure boot configuration from a file + * into internal structures + * INPUT: + * filename File name + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int parse_sec_config_file(char *filename) +{ + config_t sec_cfg; + int array_sz, element, rval = -1; + const char *cfg_string; + int32_t cfg_int32; + const config_setting_t *csk_array, *control_array; + sec_options *sec_opt = 0; + + config_init(&sec_cfg); + + if (config_read_file(&sec_cfg, filename) != CONFIG_TRUE) { + fprintf(stderr, "Failed to read data from config file "); + fprintf(stderr, "%s\n\t%s at line %d\n", + filename, config_error_text(&sec_cfg), + config_error_line(&sec_cfg)); + goto exit_parse; + } + + sec_opt = (sec_options *)calloc(sizeof(sec_options), 1); + if (sec_opt == 0) { + fprintf(stderr, + "Cannot allocate memory for secure boot options!\n"); + goto exit_parse; + } + + /* KAK file name */ + if (config_lookup_string(&sec_cfg, "kak_key_file", + &cfg_string) != CONFIG_TRUE) { + fprintf(stderr, "The \"kak_key_file\" undefined!\n"); + goto exit_parse; + } + if (verify_and_copy_file_name_entry("kak_key_file", + cfg_string, sec_opt->kak_key_file)) + goto exit_parse; + + + /* AES file name - can be empty/undefined */ + if (config_lookup_string(&sec_cfg, "aes_key_file", + &cfg_string) == CONFIG_TRUE) { + if (verify_and_copy_file_name_entry("aes_key_file", + cfg_string, + sec_opt->aes_key_file)) + goto exit_parse; + } + + /* CSK file names array */ + csk_array = config_lookup(&sec_cfg, "csk_key_file"); + if (csk_array == NULL) { + fprintf(stderr, "The \"csk_key_file\" undefined!\n"); + goto exit_parse; + } + array_sz = config_setting_length(csk_array); + if (array_sz > CSK_ARR_SZ) { + fprintf(stderr, "The \"csk_key_file\" array is too big! "); + fprintf(stderr, "Only first %d elements will be used\n", + CSK_ARR_SZ); + array_sz = CSK_ARR_SZ; + } else if (array_sz == 0) { + fprintf(stderr, "The \"csk_key_file\" array is empty!\n"); + goto exit_parse; + } + + for (element = 0; element < array_sz; element++) { + cfg_string = config_setting_get_string_elem(csk_array, element); + if (verify_and_copy_file_name_entry( + "csk_key_file", cfg_string, + sec_opt->csk_key_file[element])) { + fprintf(stderr, "Bad csk_key_file[%d] entry!\n", + element); + goto exit_parse; + } + } + + /* JTAG options */ + if (config_lookup_bool(&sec_cfg, "jtag.enable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.enable\" element. "); + fprintf(stderr, "Using default - FALSE\n"); + cfg_int32 = 0; + } + sec_opt->jtag_enable = cfg_int32; + + if (config_lookup_int(&sec_cfg, "jtag.delay", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"jtag.delay\" element. "); + fprintf(stderr, "Using default - 0us\n"); + cfg_int32 = 0; + } + sec_opt->jtag_delay = cfg_int32; + + /* eFUSE option */ + if (config_lookup_bool(&sec_cfg, "efuse_disable", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"efuse_disable\" element. "); + fprintf(stderr, "Using default - TRUE\n"); + cfg_int32 = 1; + } + sec_opt->efuse_disable = cfg_int32; + + /* Box ID option */ + if (config_lookup_int(&sec_cfg, "box_id", &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"box_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->box_id = cfg_int32; + + /* Flash ID option */ + if (config_lookup_int(&sec_cfg, "flash_id", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->flash_id = cfg_int32; + + /* CSK index option */ + if (config_lookup_int(&sec_cfg, "csk_key_index", + &cfg_int32) != CONFIG_TRUE) { + fprintf(stderr, "Error obtaining \"flash_id\" element. "); + fprintf(stderr, "Using default - 0x0\n"); + cfg_int32 = 0; + } + sec_opt->csk_index = cfg_int32; + + /* Secure boot control array */ + control_array = config_lookup(&sec_cfg, "control"); + if (control_array != NULL) { + array_sz = config_setting_length(control_array); + if (array_sz == 0) + fprintf(stderr, "The \"control\" array is empty!\n"); + } else { + fprintf(stderr, "The \"control\" is undefined!\n"); + array_sz = 0; + } + + for (element = 0; element < CP_CTRL_EL_ARRAY_SZ; element++) { + sec_opt->cp_ctrl_arr[element] = + config_setting_get_int_elem(control_array, element * 2); + sec_opt->cp_efuse_arr[element] = + config_setting_get_int_elem(control_array, + element * 2 + 1); + } + + opts.sec_opts = sec_opt; + rval = 0; + +exit_parse: + config_destroy(&sec_cfg); + if (sec_opt && (rval != 0)) + free(sec_opt); + return rval; +} /* end of parse_sec_config_file */ + +int format_sec_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + sec_entry_t sec_ext; + int index; + int written; + +#define DER_BUF_SZ 1600 + + /* First, parse the configuration file */ + if (parse_sec_config_file(filename)) { + fprintf(stderr, + "failed parsing configuration file %s\n", filename); + return 1; + } + + /* Everything except signatures can be created at this stage */ + header.type = EXT_TYPE_SECURITY; + header.offset = 0; + header.size = sizeof(sec_entry_t); + header.reserved = 0; + + /* Bring up RSA context and read private keys from their files */ + for (index = 0; index < (CSK_ARR_SZ + 1); index++) { + /* for every private key file */ + mbedtls_pk_context *pk_ctx = (index == CSK_ARR_SZ) ? + &opts.sec_opts->kak_pk : + &opts.sec_opts->csk_pk[index]; + char *fname = (index == CSK_ARR_SZ) ? + opts.sec_opts->kak_key_file : + opts.sec_opts->csk_key_file[index]; + uint8_t *out_der_key = (index == CSK_ARR_SZ) ? + sec_ext.kak_key : + sec_ext.csk_keys[index]; + size_t output_len; + unsigned char output_buf[DER_BUF_SZ]; + unsigned char *der_buf_start; + + /* Handle invalid/reserved file names */ + if (strncmp(CSK_ARR_EMPTY_FILE, fname, + strlen(CSK_ARR_EMPTY_FILE)) == 0) { + if (opts.sec_opts->csk_index == index) { + fprintf(stderr, + "CSK file with index %d cannot be %s\n", + index, CSK_ARR_EMPTY_FILE); + return 1; + } else if (index == CSK_ARR_SZ) { + fprintf(stderr, "KAK file name cannot be %s\n", + CSK_ARR_EMPTY_FILE); + return 1; + } + /* this key will be empty in CSK array */ + continue; + } + + mbedtls_pk_init(pk_ctx); + /* Read the private RSA key into the context + * and verify it (no password) + */ + if (mbedtls_pk_parse_keyfile(pk_ctx, fname, "") != 0) { + fprintf(stderr, + "Cannot read RSA private key file %s\n", fname); + return 1; + } + + /* Create a public key out of private one + * and store it in DER format + */ + output_len = mbedtls_pk_write_pubkey_der(pk_ctx, + output_buf, + DER_BUF_SZ); + if (output_len < 0) { + fprintf(stderr, + "Failed to create DER coded PUB key (%s)\n", + fname); + return 1; + } + + /* Data in the output buffer is aligned to the buffer end */ + der_buf_start = output_buf + sizeof(output_buf) - output_len; + /* In the header DER data is aligned + * to the start of appropriate field + */ + bzero(out_der_key, MAX_RSA_DER_BYTE_LEN); + memcpy(out_der_key, der_buf_start, output_len); + + } /* for every private key file */ + + /* The CSK block signature can be created here */ + if (create_rsa_signature(&opts.sec_opts->kak_pk, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to sign CSK keys block!\n"); + return 1; + } + + /* Check that everything is correct */ + if (verify_rsa_signature(sec_ext.kak_key, + MAX_RSA_DER_BYTE_LEN, + &sec_ext.csk_keys[0][0], + sizeof(sec_ext.csk_keys), + opts.sec_opts->kak_key_file, + sec_ext.csk_sign) != 0) { + fprintf(stderr, "Failed to verify CSK keys block signature!\n"); + return 1; + } + + /* AES encryption stuff */ + if (strlen(opts.sec_opts->aes_key_file) != 0) { + FILE *in_fd; + + in_fd = fopen(opts.sec_opts->aes_key_file, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "Failed to open AES key file %s\n", + opts.sec_opts->aes_key_file); + return 1; + } + + /* Read the AES key in ASCII format byte by byte */ + for (index = 0; index < AES_KEY_BYTE_LEN; index++) { + if (fscanf(in_fd, "%02hhx", + opts.sec_opts->aes_key + index) != 1) { + fprintf(stderr, + "Failed to read AES key byte %d ", + index); + fprintf(stderr, + "from file %s\n", + opts.sec_opts->aes_key_file); + fclose(in_fd); + return 1; + } + } + fclose(in_fd); + sec_ext.encrypt_en = 1; + } else { + sec_ext.encrypt_en = 0; + } + + /* Fill the rest of the trusted boot extension fields */ + sec_ext.box_id = opts.sec_opts->box_id; + sec_ext.flash_id = opts.sec_opts->flash_id; + sec_ext.efuse_dis = opts.sec_opts->efuse_disable; + sec_ext.jtag_delay = opts.sec_opts->jtag_delay; + sec_ext.jtag_en = opts.sec_opts->jtag_enable; + + memcpy(sec_ext.cp_ctrl_arr, + opts.sec_opts->cp_ctrl_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + memcpy(sec_ext.cp_efuse_arr, + opts.sec_opts->cp_efuse_arr, + sizeof(uint32_t) * CP_CTRL_EL_ARRAY_SZ); + + /* Write the resulting extension to file + * (image and header signature fields are still empty) + */ + + /* Write extension header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension header to the file\n"); + return 1; + } + /* Write extension body */ + written = fwrite(&sec_ext, sizeof(sec_entry_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Failed to write SEC extension body to the file\n"); + return 1; + } + + return 0; +} + +/******************************************************************************* + * finalize_secure_ext + * Make final changes to secure extension - calculate image and header + * signatures and encrypt the image if needed. + * The main header checksum and image size fields updated accordingly + * INPUT: + * header Main header + * prolog_buf the entire prolog buffer + * prolog_size prolog buffer length + * image_buf buffer containing the input binary image + * image_size image buffer size. + * OUTPUT: + * none + * RETURN: + * 0 on success + */ +int finalize_secure_ext(header_t *header, + uint8_t *prolog_buf, uint32_t prolog_size, + uint8_t *image_buf, int image_size) +{ + int cur_ext, offset; + uint8_t *final_image = image_buf; + uint32_t final_image_sz = image_size; + uint8_t hdr_sign[RSA_SIGN_BYTE_LEN]; + sec_entry_t *sec_ext = 0; + + /* Find the Trusted Boot Header between available extensions */ + for (cur_ext = 0, offset = sizeof(header_t); + cur_ext < header->ext_count; cur_ext++) { + ext_header_t *ext_hdr = (ext_header_t *)(prolog_buf + offset); + + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_ext = (sec_entry_t *)(prolog_buf + offset + + sizeof(ext_header_t) + ext_hdr->offset); + break; + } + + offset += sizeof(ext_header_t); + /* If offset is Zero, the extension follows its header */ + if (ext_hdr->offset == 0) + offset += ext_hdr->size; + } + + if (sec_ext == 0) { + fprintf(stderr, "Error: No Trusted Boot extension found!\n"); + return -1; + } + + if (sec_ext->encrypt_en) { + /* Encrypt the image if needed */ + fprintf(stdout, "Encrypting the image...\n"); + + if (image_encrypt(image_buf, image_size) != 0) { + fprintf(stderr, "Failed to encrypt the image!\n"); + return -1; + } + + /* Image size and checksum should be updated after encryption. + * This way the image could be verified by the BootROM + * before decryption. + */ + final_image = opts.sec_opts->encrypted_image; + final_image_sz = opts.sec_opts->enc_image_sz; + + header->boot_image_size = final_image_sz; + header->boot_image_checksum = + checksum32((uint32_t *)final_image, final_image_sz); + } /* AES encryption */ + + /* Create the image signature first, since it will be later + * signed along with the header signature + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to sign image!\n"); + return -1; + } + /* Check that the image signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + final_image, final_image_sz, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + sec_ext->image_sign) != 0) { + fprintf(stderr, "Failed to verify image signature!\n"); + return -1; + } + + /* Sign the headers and all the extensions block + * when the header signature field is empty + */ + if (create_rsa_signature(&opts.sec_opts->csk_pk[ + opts.sec_opts->csk_index], + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to sign header!\n"); + return -1; + } + /* Check that the header signature is correct */ + if (verify_rsa_signature(sec_ext->csk_keys[opts.sec_opts->csk_index], + MAX_RSA_DER_BYTE_LEN, + prolog_buf, prolog_size, + opts.sec_opts->csk_key_file[ + opts.sec_opts->csk_index], + hdr_sign) != 0) { + fprintf(stderr, "Failed to verify header signature!\n"); + return -1; + } + + /* Finally, copy the header signature into the trusted boot extension */ + memcpy(sec_ext->header_sign, hdr_sign, RSA_SIGN_BYTE_LEN); + + return 0; +} + +#endif /* CONFIG_MVEBU_SECURE_BOOT */ + + +#define FMT_HEX 0 +#define FMT_DEC 1 +#define FMT_BIN 2 +#define FMT_NONE 3 + +void do_print_field(unsigned int value, char *name, + int start, int size, int format) +{ + fprintf(stdout, "[0x%05x : 0x%05x] %-26s", + start, start + size - 1, name); + + switch (format) { + case FMT_HEX: + printf("0x%x\n", value); + break; + case FMT_DEC: + printf("%d\n", value); + break; + default: + printf("\n"); + break; + } +} + +#define print_field(st, type, field, hex, base) \ + do_print_field((int)st->field, #field, \ + base + offsetof(type, field), sizeof(st->field), hex) + +int print_header(uint8_t *buf, int base) +{ + header_t *main_hdr; + + main_hdr = (header_t *)buf; + + fprintf(stdout, "########### Header ##############\n"); + print_field(main_hdr, header_t, magic, FMT_HEX, base); + print_field(main_hdr, header_t, prolog_size, FMT_DEC, base); + print_field(main_hdr, header_t, prolog_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, boot_image_size, FMT_DEC, base); + print_field(main_hdr, header_t, boot_image_checksum, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd0, FMT_HEX, base); + print_field(main_hdr, header_t, load_addr, FMT_HEX, base); + print_field(main_hdr, header_t, exec_addr, FMT_HEX, base); + print_field(main_hdr, header_t, uart_cfg, FMT_HEX, base); + print_field(main_hdr, header_t, baudrate, FMT_HEX, base); + print_field(main_hdr, header_t, ext_count, FMT_DEC, base); + print_field(main_hdr, header_t, aux_flags, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_0, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_1, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_2, FMT_HEX, base); + print_field(main_hdr, header_t, io_arg_3, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd1, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd2, FMT_HEX, base); + print_field(main_hdr, header_t, rsrvd3, FMT_HEX, base); + + return sizeof(header_t); +} + +int print_ext_hdr(ext_header_t *ext_hdr, int base) +{ + print_field(ext_hdr, ext_header_t, type, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, offset, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, reserved, FMT_HEX, base); + print_field(ext_hdr, ext_header_t, size, FMT_DEC, base); + + return base + sizeof(ext_header_t); +} + +void print_sec_ext(ext_header_t *ext_hdr, int base) +{ + sec_entry_t *sec_entry; + uint32_t new_base; + + fprintf(stdout, "\n########### Secure extension ###########\n"); + + new_base = print_ext_hdr(ext_hdr, base); + + sec_entry = (sec_entry_t *)(ext_hdr + 1); + + do_print_field(0, "KAK key", new_base, MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += MAX_RSA_DER_BYTE_LEN; + print_field(sec_entry, sec_entry_t, jtag_delay, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, box_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, flash_id, FMT_HEX, base); + print_field(sec_entry, sec_entry_t, encrypt_en, FMT_DEC, base); + print_field(sec_entry, sec_entry_t, efuse_dis, FMT_DEC, base); + new_base += 6 * sizeof(uint32_t); + do_print_field(0, "header signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "image signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "CSK keys", new_base, + CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN, FMT_NONE); + new_base += CSK_ARR_SZ * MAX_RSA_DER_BYTE_LEN; + do_print_field(0, "CSK block signature", + new_base, RSA_SIGN_BYTE_LEN, FMT_NONE); + new_base += RSA_SIGN_BYTE_LEN; + do_print_field(0, "control", new_base, + CP_CTRL_EL_ARRAY_SZ * 2, FMT_NONE); + +} + +void print_bin_ext(ext_header_t *ext_hdr, int base) +{ + fprintf(stdout, "\n########### Binary extension ###########\n"); + base = print_ext_hdr(ext_hdr, base); + do_print_field(0, "binary image", base, ext_hdr->size, FMT_NONE); +} + +int print_extension(void *buf, int base, int count, int ext_size) +{ + ext_header_t *ext_hdr = buf; + int pad = ext_size; + int curr_size; + + while (count--) { + if (ext_hdr->type == EXT_TYPE_BINARY) + print_bin_ext(ext_hdr, base); + else if (ext_hdr->type == EXT_TYPE_SECURITY) + print_sec_ext(ext_hdr, base); + + curr_size = sizeof(ext_header_t) + ext_hdr->size; + base += curr_size; + pad -= curr_size; + ext_hdr = (ext_header_t *)((uintptr_t)ext_hdr + curr_size); + } + + if (pad) + do_print_field(0, "padding", base, pad, FMT_NONE); + + return ext_size; +} + +int parse_image(uint8_t *buf, int size) +{ + int base = 0; + int ret = 1; + header_t *main_hdr; + uint32_t checksum, prolog_checksum; + + + fprintf(stdout, + "################### Prolog Start ######################\n\n"); + main_hdr = (header_t *)buf; + base += print_header(buf, base); + + if (main_hdr->ext_count) + base += print_extension(buf + base, base, + main_hdr->ext_count, + main_hdr->prolog_size - + sizeof(header_t)); + + if (base < main_hdr->prolog_size) { + fprintf(stdout, "\n########### Padding ##############\n"); + do_print_field(0, "prolog padding", + base, main_hdr->prolog_size - base, FMT_HEX); + base = main_hdr->prolog_size; + } + fprintf(stdout, + "\n################### Prolog End ######################\n"); + + fprintf(stdout, + "\n################### Boot image ######################\n"); + + do_print_field(0, "boot image", base, size - base - 4, FMT_NONE); + + fprintf(stdout, + "################### Image end ########################\n"); + + /* Check sanity for certain values */ + printf("\nChecking values:\n"); + + if (main_hdr->magic == MAIN_HDR_MAGIC) { + fprintf(stdout, "Headers magic: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: HEADER MAGIC 0x%08x != 0x%08x\n", + main_hdr->magic, MAIN_HDR_MAGIC); + goto error; + } + + /* headers checksum */ + /* clear the checksum field in header to calculate checksum */ + prolog_checksum = main_hdr->prolog_checksum; + main_hdr->prolog_checksum = 0; + checksum = checksum32((uint32_t *)buf, main_hdr->prolog_size); + + if (checksum == prolog_checksum) { + fprintf(stdout, "Headers checksum: OK!\n"); + } else { + fprintf(stderr, + "\n***** ERROR: BAD HEADER CHECKSUM 0x%08x != 0x%08x\n", + checksum, prolog_checksum); + goto error; + } + + /* boot image checksum */ + checksum = checksum32((uint32_t *)(buf + main_hdr->prolog_size), + main_hdr->boot_image_size); + if (checksum == main_hdr->boot_image_checksum) { + fprintf(stdout, "Image checksum: OK!\n"); + } else { + fprintf(stderr, + "\n****** ERROR: BAD IMAGE CHECKSUM 0x%08x != 0x%08x\n", + checksum, main_hdr->boot_image_checksum); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* RSA signatures */ + if (main_hdr->ext_count) { + uint8_t ext_num = main_hdr->ext_count; + ext_header_t *ext_hdr = (ext_header_t *)(main_hdr + 1); + unsigned char hash[32]; + int i; + + while (ext_num--) { + if (ext_hdr->type == EXT_TYPE_SECURITY) { + sec_entry_t *sec_entry = + (sec_entry_t *)(ext_hdr + 1); + + ret = verify_secure_header_signatures( + main_hdr, sec_entry); + if (ret != 0) { + fprintf(stderr, + "\n****** FAILED TO VERIFY "); + fprintf(stderr, + "RSA SIGNATURES ********\n"); + goto error; + } + + mbedtls_sha256_ret(sec_entry->kak_key, + MAX_RSA_DER_BYTE_LEN, hash, 0); + fprintf(stdout, + ">>>>>>>>>> KAK KEY HASH >>>>>>>>>>\n"); + fprintf(stdout, "SHA256: "); + for (i = 0; i < 32; i++) + fprintf(stdout, "%02X", hash[i]); + + fprintf(stdout, + "\n<<<<<<<<< KAK KEY HASH <<<<<<<<<\n"); + + break; + } + ext_hdr = + (ext_header_t *)((uint8_t *)(ext_hdr + 1) + + ext_hdr->size); + } + } +#endif + + ret = 0; +error: + return ret; +} + +int format_bin_ext(char *filename, FILE *out_fd) +{ + ext_header_t header; + FILE *in_fd; + int size, written; + int aligned_size, pad_bytes; + char c; + + in_fd = fopen(filename, "rb"); + if (in_fd == NULL) { + fprintf(stderr, "failed to open bin extension file %s\n", + filename); + return 1; + } + + size = get_file_size(filename); + if (size <= 0) { + fprintf(stderr, "bin extension file size is bad\n"); + return 1; + } + + /* Align extension size to 8 bytes */ + aligned_size = (size + 7) & (~7); + pad_bytes = aligned_size - size; + + header.type = EXT_TYPE_BINARY; + header.offset = 0; + header.size = aligned_size; + header.reserved = 0; + + /* Write header */ + written = fwrite(&header, sizeof(ext_header_t), 1, out_fd); + if (written != 1) { + fprintf(stderr, "failed writing header to extension file\n"); + return 1; + } + + /* Write image */ + while (size--) { + c = getc(in_fd); + fputc(c, out_fd); + } + + while (pad_bytes--) + fputc(0, out_fd); + + fclose(in_fd); + + return 0; +} + +/* **************************************** + * + * Write all extensions (binary, secure + * extensions) to file + * + * ****************************************/ + +int format_extensions(char *ext_filename) +{ + FILE *out_fd; + int ret = 0; + + out_fd = fopen(ext_filename, "wb"); + if (out_fd == NULL) { + fprintf(stderr, "failed to open extension output file %s", + ext_filename); + return 1; + } + + if (strncmp(opts.bin_ext_file, "NA", MAX_FILENAME)) { + if (format_bin_ext(opts.bin_ext_file, out_fd)) { + ret = 1; + goto error; + } + } +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (strncmp(opts.sec_cfg_file, "NA", MAX_FILENAME)) { + if (format_sec_ext(opts.sec_cfg_file, out_fd)) { + ret = 1; + goto error; + } + } +#endif + +error: + fflush(out_fd); + fclose(out_fd); + return ret; +} + +void update_uart(header_t *header) +{ + header->uart_cfg = 0; + header->baudrate = 0; + + if (opts.disable_print) + uart_set_mode(header->uart_cfg, UART_MODE_DISABLE); + + if (opts.baudrate) + header->baudrate = (opts.baudrate / 1200); +} + +/* **************************************** + * + * Write the image prolog, i.e. + * main header and extensions, to file + * + * ****************************************/ + +int write_prolog(int ext_cnt, char *ext_filename, + uint8_t *image_buf, int image_size, FILE *out_fd) +{ + header_t *header; + int main_hdr_size = sizeof(header_t); + int prolog_size = main_hdr_size; + FILE *ext_fd; + char *buf; + int written, read; + int ret = 1; + + + if (ext_cnt) + prolog_size += get_file_size(ext_filename); + + prolog_size = ((prolog_size + PROLOG_ALIGNMENT) & + (~(PROLOG_ALIGNMENT-1))); + + /* Allocate a zeroed buffer to zero the padding bytes */ + buf = calloc(prolog_size, 1); + if (buf == NULL) { + fprintf(stderr, "Error: failed allocating checksum buffer\n"); + return 1; + } + + header = (header_t *)buf; + header->magic = MAIN_HDR_MAGIC; + header->prolog_size = prolog_size; + header->load_addr = opts.load_addr; + header->exec_addr = opts.exec_addr; + header->io_arg_0 = opts.nfc_io_args; + header->ext_count = ext_cnt; + header->aux_flags = 0; + header->boot_image_size = (image_size + 3) & (~0x3); + header->boot_image_checksum = checksum32((uint32_t *)image_buf, + image_size); + + update_uart(header); + + /* Populate buffer with main header and extensions */ + if (ext_cnt) { + ext_fd = fopen(ext_filename, "rb"); + if (ext_fd == NULL) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + + read = fread(&buf[main_hdr_size], + get_file_size(ext_filename), 1, ext_fd); + if (read != 1) { + fprintf(stderr, + "Error: failed to open extensions file\n"); + goto error; + } + +#ifdef CONFIG_MVEBU_SECURE_BOOT + /* Secure boot mode? */ + if (opts.sec_opts != 0) { + ret = finalize_secure_ext(header, (uint8_t *)buf, + prolog_size, image_buf, + image_size); + if (ret != 0) { + fprintf(stderr, "Error: failed to handle "); + fprintf(stderr, "secure extension!\n"); + goto error; + } + } /* secure boot mode */ +#endif + } + + /* Update the total prolog checksum */ + header->prolog_checksum = checksum32((uint32_t *)buf, prolog_size); + + /* Now spill everything to output file */ + written = fwrite(buf, prolog_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, + "Error: failed to write prolog to output file\n"); + goto error; + } + + ret = 0; + +error: + free(buf); + return ret; +} + +int write_boot_image(uint8_t *buf, uint32_t image_size, FILE *out_fd) +{ + int written; + + written = fwrite(buf, image_size, 1, out_fd); + if (written != 1) { + fprintf(stderr, "Error: Failed to write boot image\n"); + goto error; + } + + return 0; +error: + return 1; +} + +int main(int argc, char *argv[]) +{ + char in_file[MAX_FILENAME+1] = { 0 }; + char out_file[MAX_FILENAME+1] = { 0 }; + char ext_file[MAX_FILENAME+1] = { 0 }; + FILE *in_fd = NULL; + FILE *out_fd = NULL; + int parse = 0; + int ext_cnt = 0; + int opt; + int ret = 0; + int image_size, file_size; + uint8_t *image_buf = NULL; + int read; + size_t len; + uint32_t nand_block_size_kb, mlc_nand; + + /* Create temporary file for building extensions + * Use process ID for allowing multiple parallel runs + */ + snprintf(ext_file, MAX_FILENAME, "/tmp/ext_file-%x", getpid()); + + while ((opt = getopt(argc, argv, "hpms:i:l:e:a:b:u:n:t:c:k:")) != -1) { + switch (opt) { + case 'h': + usage(); + break; + case 'l': + opts.load_addr = strtoul(optarg, NULL, 0); + break; + case 'e': + opts.exec_addr = strtoul(optarg, NULL, 0); + break; + case 'm': + opts.disable_print = 1; + break; + case 'u': + opts.baudrate = strtoul(optarg, NULL, 0); + break; + case 'b': + strncpy(opts.bin_ext_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'p': + parse = 1; + break; + case 'n': + nand_block_size_kb = strtoul(optarg, NULL, 0); + opts.nfc_io_args |= (nand_block_size_kb / 64); + break; + case 't': + mlc_nand = 0; + if (!strncmp("MLC", optarg, 3)) + mlc_nand = 1; + opts.nfc_io_args |= (mlc_nand << 8); + break; +#ifdef CONFIG_MVEBU_SECURE_BOOT + case 'c': /* SEC extension */ + strncpy(opts.sec_cfg_file, optarg, MAX_FILENAME); + ext_cnt++; + break; + case 'k': + opts.key_index = strtoul(optarg, NULL, 0); + break; +#endif + default: /* '?' */ + usage_err("Unknown argument"); + exit(EXIT_FAILURE); + } + } + + /* Check validity of inputes */ + if (opts.load_addr % 8) + usage_err("Load address must be 8 bytes aligned"); + + if (opts.baudrate % 1200) + usage_err("Baudrate must be a multiple of 1200"); + + /* The remaining arguments are the input + * and potentially output file + */ + /* Input file must exist so exit if not */ + if (optind >= argc) + usage_err("missing input file name"); + + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(in_file, argv[optind], len); + optind++; + + /* Output file must exist in non parse mode */ + if (optind < argc) { + len = strlen(argv[optind]); + if (len > MAX_FILENAME) + usage_err("file name too long"); + memcpy(out_file, argv[optind], len); + } else if (!parse) + usage_err("missing output file name"); + + /* open the input file */ + in_fd = fopen(in_file, "rb"); + if (in_fd == NULL) { + printf("Error: Failed to open input file %s\n", in_file); + goto main_exit; + } + + /* Read the input file to buffer + * Always align the image to 16 byte boundary + */ + file_size = get_file_size(in_file); + image_size = (file_size + AES_BLOCK_SZ - 1) & ~(AES_BLOCK_SZ - 1); + image_buf = calloc(image_size, 1); + if (image_buf == NULL) { + fprintf(stderr, "Error: failed allocating input buffer\n"); + return 1; + } + + read = fread(image_buf, file_size, 1, in_fd); + if (read != 1) { + fprintf(stderr, "Error: failed to read input file\n"); + goto main_exit; + } + + /* Parse the input image and leave */ + if (parse) { + if (opts.key_index >= CSK_ARR_SZ) { + fprintf(stderr, + "Wrong key IDX value. Valid values 0 - %d\n", + CSK_ARR_SZ - 1); + goto main_exit; + } + ret = parse_image(image_buf, image_size); + goto main_exit; + } + + /* Create a blob file from all extensions */ + if (ext_cnt) { + ret = format_extensions(ext_file); + if (ret) + goto main_exit; + } + + out_fd = fopen(out_file, "wb"); + if (out_fd == NULL) { + fprintf(stderr, + "Error: Failed to open output file %s\n", out_file); + goto main_exit; + } + + ret = write_prolog(ext_cnt, ext_file, image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts && (opts.sec_opts->encrypted_image != 0) && + (opts.sec_opts->enc_image_sz != 0)) { + ret = write_boot_image(opts.sec_opts->encrypted_image, + opts.sec_opts->enc_image_sz, out_fd); + } else +#endif + ret = write_boot_image(image_buf, image_size, out_fd); + if (ret) + goto main_exit; + +main_exit: + if (in_fd) + fclose(in_fd); + + if (out_fd) + fclose(out_fd); + + if (image_buf) + free(image_buf); + + unlink(ext_file); + +#ifdef CONFIG_MVEBU_SECURE_BOOT + if (opts.sec_opts) { + if (opts.sec_opts->encrypted_image) + free(opts.sec_opts->encrypted_image); + free(opts.sec_opts); + } +#endif + exit(ret); +} diff --git a/arm-trusted-firmware/tools/marvell/doimage/doimage.mk b/arm-trusted-firmware/tools/marvell/doimage/doimage.mk new file mode 100644 index 0000000..2b751d4 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/doimage.mk @@ -0,0 +1,15 @@ +# +# Copyright (C) 2018 Marvell International Ltd. +# +# SPDX-License-Identifier: BSD-3-Clause +# https://spdx.org/licenses + +DOIMAGE_FLAGS ?= -l 0x4100000 -e 0x4100000 + + +#NAND params +#Open and update the below when using NAND as a boot device. + +CONFIG_MVEBU_NAND_BLOCK_SIZE := 256 +CONFIG_MVEBU_NAND_CELL_TYPE := SLC +NAND_DOIMAGE_FLAGS := -t $(CONFIG_MVEBU_NAND_CELL_TYPE) -n $(CONFIG_MVEBU_NAND_BLOCK_SIZE) diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt b/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt new file mode 100644 index 0000000..3e8a888 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/aes_key.txt @@ -0,0 +1 @@ +ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890ABCDEF1234567890 diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key new file mode 100644 index 0000000..0840c2a --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAm6jN6o2zQmtyUlvfkfDbSjPJ7Vlpp/KgK/eznoVBBsDIZakX +cIgf8TSLpNVkc+ZE0f/n8X7mEZIyjuSBObLOm9vbkoZcR7DlKUL7RNNOUCv55Ozl +hQwrzpH/uIyIJTvmek29G5wroi0wGbPoxzhelIRTjVCibleBWhYCmZQ6SIRmTY8L +JT8VkX8I/Mhu62DjvxF3BnV6pXuh/FdgDN7MbldzM8Y+GOxVGi5Kcm5WHY7eyMxl +4Y0Yko31Xv7T1PcXahVBIciT+11w+fLc4wQuCJ6GUf9JbzQ0ZllY/FdRG0AhuRMH +zN0jAc/sKrIFoAErED6qlcoQg0vl7gmWN5x+2wIDAQABAoIBACtnPFOkw1FH6I6y +c3qcMGlWW33FKsLb0nGwFfOjsGgTpU1Dgver3UxCnJWPsvzmPlZYBvK9saVAoLxb +VvUhuJ6ZBXar5FtRJfUFak7cpL+SI5IDxFP++tAUwbtR5DyNoUyFFK/4Mep8sybX +lZbHTwgWhb2nuEMQP09BR+RPAplpcitkIoPkhmbGfbt9Hsd25I3bb5Z9R4S/2Rcf +7tmaxndQamij7/pUI7xtd8L6cMESJGIWrgEt/MaT2z8nNPE3EDctDSlH9yKqA2O7 +/LTfrxNDnw5gGRtOgahloThKljVM6pQa4mi91FufD67pHwnKn8urNbt8/3AWg6uU +x4FzZdECgYEA0k2UYzBM+dU6T1bZZ176YI0cZrP1tbf/JwnZGHicQYS7lPLAqgfO +u5oRQzuDimOXaV4xCPBO2nadd6aBxbZTXaglR7GG2uCHX6w2DnOr8/d66YTErTVV +u7/Bf8gMKT9mM4rWPrOEXfXfF0fvcpkBQ+QDynIB37tx/mj2lXRkLx0CgYEAvXuX +Dbe2QgSK0ajrcH7YJyx3RVx9RonOqL4yjCVCELmaDQd307Ef3j+gkd59XIewm+HA +mPyeWEUd8EzH+UvjckfKFuF2I4lEUUWtVZTa7me7mvsFqeEOu5KusD4+Hs+B9Kqd +3Evqcpj2lcMBI519Hvr9BTKfDBcH1EUos6A9rFcCgYAxsyPeTQvj/wBIv72hMFD7 +gF2159GpoFIsZ6dmoRpMYZHzIWtmw3GX5FEwEmCD1AV0YU41TpVUC7QrEq6Yiv4o +pBQrXUkBcQ6NDaW4xJ1eip4Bkd7pEDGyrR6NlDlLhjAg/i6joskla3XNirKL4pzp +7nj23vqSZToLZcLgjyEeAQKBgD5EvDo80j9VwMzvpxecB6qv+S4pG94vcWOQxYm6 +wMBATjjT6HP/9EoUPM9S/32F9er0QFfGRL8bT6Blix4I62Dl6KqmQy2gcXwH2tOS +DHRmUIe40H6oQDAyHwg6HC4B4WInI6N+qzgnvnku0VQD8FdbAgVQQmY1t1PxulN1 +aG8XAoGAPWAr4i8KkVAx4wLlMF8E/ecKcsX1J0+UuKket7Dvk7xJfwtkSLPeV8Bp +HuoHXMM3KYoZ93Hlto5rAT1VQhYuj7heU10v+9UtYTFHgaitptYmxovoCKKiZICl +48aPUI377e5jQ6RhhGYy8ltKsJ80K1T9DIkThJPSS+9NAI+jrmg= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key new file mode 100644 index 0000000..91d1aeb --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAgwHXB0AaIhT15Z9lHpQ2YT1W8i4oMvvRiLGQCrba5l7BJ03E +ct0x3zagNKZEnpNndT4EAy98ihkhwVlUhxZCparJ2L3JsTs5RgV0wyQkQzwMLM8g +QI5EMmJCgFAVRHmVICOsisGGfNVUHjGdGwPOipyQCsX2MAm3E139VpB7NYj+Q4IR +4kvcb+59LZxKuRJTFKRDIqMGJu98P/ga70+YLXPCBPKSfnZnUppuaI86jF1E6xt8 +o7YtfEPCHDd2LXxKPZ670OapVqwo0t7ZSzEG63NkLp56FXc1OpfC69C8VPiZ8JqW +wxvS/vL8MMCxsBnjSuqnmOAbcNR2GFtUwJOGwwIDAQABAoIBAFcfoiDwQHDp/531 +ownzBzcj0+67Q4Ckd3SwoVp+wJTz7wB0d3DsKX6IlYJuELRk0yjlVUXJDsnIbOpo +vg4Yf7otGo9JqBh1imFGv6AHKRaNmIs0M/66nh/juNYcbAhd0w7MqrKcgRQDyy1J +UXHl1jXYaPLBNDg+PcJjf1dSPp4axzmW2Pk2rXnJCsPcZXL/0YmEvqhfOze0GdjR +hOkbbr6MPPVM66tA00xSwg9XEYJvHtwH6oB0rnANM8ieNK1mtcWkTU5di17CCrjS +ohIhXQrdVpxt549EJoUqEFSgo8OOMm2npDbFrjlukb5euakvMacwoT1te79blSKf +hrTvjgECgYEA0VqoFL0Vqe1qleikYDJ7S5xcv1oruEV31TeuBhDuf0c4PADCnBrV +/RnCEYuXs6wCk60chHg5s0jxg+nGbiY6jRTHkJLRU3ZhDtrtfidEZ78GRzFF3shl +Uzt7dHkKK1ZdiMH4sWzyRLom91TKWMrNKC1AD7v4/zjEXy6phall3ZcCgYEAoDJa +0dIKvVCS6dM2E2kMqi/45mJqsJzFvYL1s4mbma/BAC47bBju/YEse90x+iIi3Gg/ +NoXmNfGPrtgdl+/J/Y6Pohxf/e7gGN71tYVETzgc2Jv09wqmzmTjCmo3wyepyWf+ +pIAE39kdhwnqXVw5xwOG1N3xrQ9TomOO+1QiXbUCgYAF84TJqiJehUA9aLKbhXPZ +z2UXj3GkuFzSs9V/mKWe+qBPnFnr5BtnKX9JzmUOl3ovRoGEBoLlZNJwxIl+ghmx +/wA5TOMkcz4JFRIhPu6D4HtGNNFepuWyewNkaThvyPG5vIHcUVOFvqDy8PcblRBF +7xteFyLZ5nw2lHX/NbSOmwKBgFxLZqPIPcPArkPlGhyow1Ex/lbNkOZcDFkZIHHl +8C3lYm62NCodW2PWjkh2shqInEkcDn9dObsOh1eWz8X/swJQplQhwPROMfJiUnHY +a/iwPX5WrBXAn0X+Pgh8FdBsA5g0QDOKRkSplCd/APX08pzEXWQ60siAMhE3BuOq +H3qZAoGAVnzFidlXuyn+fbNaNVepK9hbuoxHHbzYYWSkpi+73EchN8kXktC+AdEf +owr9TPILbwWWJyisa3wW4xdbMifCgVLTedWZpZ09BENVqC+7g7ksX0pNMGYuFLOh +Td7mFAgmclxG5UiKexajOLjjdnAsJyrDaNKhHn8NQNN6L93N0sE= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key new file mode 100644 index 0000000..ea47ac5 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEogIBAAKCAQEAjxTSTh57/5njUpE200+Qb3ySAn8lKeufgaa0K2Xc6Ri7lDZR +ZJ2BPuQZV4lYGqgWUf0IOzNf2WnE2lPfVnLMx08h7NhBqJ83yJVajpr+itnOmW+r +M7h76TFyuna1xz2kw1uhgI5Y4FRnJ4Cg4AexCSyViXSzEN/7LQwxa5z5WGDiNX5N +3/tgjGu+dzSMOiIQhXwIcK/XaiQNm3WHqqnAhPb5Q9IBuuqBfpZoFfH4XmbFWrC8 +neSMMMxX5Ti9pKhLd1EsiaP0aUNQlF8gNWuC/tNaf+OCtwVelVa3sGSRjRFe06VQ +sAE9oyXKri11yD5Dwp1xXivbpOrf7xjUe5gILwIDAQABAoIBABTr94CCxqDucKYP +I9QsSzNyJKuGyfliQdWkea3q3C2ddzhJ5QbwXQjEM8xwAdkMAQ+GD2EQtxBEfgtq +vjqW2MjAEnbefGNavL5w0GgP0+6bwLEA+ii67iuAFoWbfCMhKWmDiY8RwX8z+E13 +ao63sTRlN4x86v4pskG5CbTxpCg+8m7KklLns4SwRGf5gGQcgKRtNSR5nE4g2UNl +dghbDdNlvUncm4zxUcTh0kquhF5Tef5w+6L7W8Hv9Pky3b1c2OK1BMhJlxYrtt69 +/zhIJs89CLx5ACfam+DT/xs0uUiuRQq/e1CCQLCnUO02JqpeN/schtDCd0ZWhbtB +nT7fwTECgYEAx+COhys+7AZI0U+PeuTkI86GUsWHoBislXThxbxyGvMFjgyADZD+ +q/XEGAcxd4eTA1fr0Q9cLuuHZubjGQ7+OIXMZ6arXUsrmMrjRu3kHO+y6K6r4s8j +5bxN/iQ0bymUtJRfJSLI172plszusiPWhCL5+yhYlNoh4mNZJuJnzXkCgYEAt0Gz +07P19YPsxk5ow7ZnSNOMOkkEPP0SuHHWekMIK9KMjiRUSygOAk07zTL7MUoFn9Gy +Prfi0ybFArNhIa4Xio3Fbjfig7rGgaApK4Y3d9A/CGPv/Nj7C2OTepqlEzRLmU9e +Xw5yhbccCydXLyAYFAET2XHsmbewpvHyeYUSoOcCgYBRMJEUrOdhPmhDxZqVo/Zb +6R887gnaaUtpZlHzXUnIUqEWA1PcruIT/b/KttlMIWEBQayDfkbGtFuK3AyxeBqh +4Q+XpucC/W7XIMrTW/yGGIPG6nTdq6B8SFIyAojeArjp5T8Eua11nRAPNm1bJR2V +DRQYBlp9FGIhMJPdLKhXmQKBgGeywSyR0COfBHPu2K+u3uFB/D7bJI/ScS54FHLY +zZ3mpeylOCHTR6IbzDRAng31Ihue0KtW6P6tGJx/nv4tAltAADFvZDlAjqW5WLKt +X2PoLlL0IlBFBEIclc6yBalJVWIqnG9TwJBT3oWdPGOJWLaxKWdJZSZS4J6HmLsV +B0aPAoGAduLsOt8C5z48jPqmJxyPwsmT0Q424FccPMcvGOJ13yxq3xNsfAsbmg9l +L2i/ktE0wCMA+Pm7cuFgxwD7xTr67POZgt9022KsOSonjPsIn24UQeP46vAX/Qtx +Qf3sfvzf57vNy2Hybe38T8RsVOZla+v/QctfSfmb8Y95XL/SZzA= +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key new file mode 100644 index 0000000..e40a864 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAlA/T/5IMTPTu+k5PeesB2oeP80Y6nq0ls8vXLul0TVEJoJ+O +InbPYNqYPu4dbQQg/u8qp8BeXm2ujtJbBTcdn0jKIiDTKYEnlsGfUt9GHnuuzvFh +rORSKuAolUqvo/zcSCo1uykaFvSuyTovSPlwllzSixD9XBbHfn3kXneiIUa45vsJ +AyjTn2qCJt0WgvX42NTxH6Q/OWLeOuKTyRHf25eabucIv77KYy0mlEPq5jjiV5AJ +gl5F1h5G8n07JCIWjkZ2QV4wr+Hv9uGNaSb0WGppBp4CbdQa0eUI75cKzz4WXqds +HZaYiX/a8YC+EUfvqDD02vKREIKFL/1zL53P/wIDAQABAoIBAGzBj5w7oBNrGpr7 +qL9KEyt8xg0Q+gAR+Q6vXRlVXBtquiKk8Jd6I+vlxUz8RNsN3FrGPNPJpse/0yeP +dlJHYNfedLNK3zCucPD4uln6LRw5B3d0sKV5dK2Px9+ZY5iWJQxRDPS0RTi1dCnV +NmRo7P1Vo0WJLkFVbiYIvRVy1MGRfF9ejN41G6U4MoBAQ9WqLp+JasUMTspZI49a +z8tOiJPT94MHBwbKnz8Mcq8sy02LR7U5h82+0T7JoRVix/OXiOoiQExNjZ9yGar0 +wBnl0SL1UW5UUaYzbyNH0mlMXLD+qowbDZM2pBWPfqXK+CMOsL6STIwnns7lY+ZJ +ILbaVmECgYEA2kQXE1PZ25A87a81wCEld402WJ2KegrZC719EWv+xeoS72Ji8uv7 +V0PxVGJQOcG1N+dzJ5tN59SQ/NvVTrjwqNUxQqsygmWq/TcfGb9ONZRmyzcehYLb +m4xTjqJKQ6Kwm5SoaCYmzEb/xaeLwLS9HmR9MdB1dxtDOLpjaK/8qPECgYEArait +QhgaknlxG8pcAimPsEUrLHYWSFRE/MUk4+YvZg/5+YJ8csvY0SO2h0tF/ARwUrdI +DaLEifHm4vqgN03K/0gqj7TKxcNlV16PvVx7Vz97xejdqdHZLDfAo4lcotsgvFQW +zIqoQGGPLf6WhFixZ8mEYj8xnmzLGPvHQmf1h+8CgYEA0LDl917nIN4qw4ARPqDy +t/pXCienrcUNfgIxwSSnNwj2DdjejzI+4VNfPbW6y16BLPCp1CbUOGOwNXTj4R9H +S8Z8ESirZK5c7Tt1CyM1XlmEZ61OC43w+CsWAXz+0OiPQFLFKr+/vPXtvEjUgO7P +HG4sniKZDccNYQIl5oTOaaECgYAPU4u3AZmWw9EPutRT/IcJ75DX47Qjvgw4os2W +r4IPZ+mP88w39XW1P4mkdyg+DcY8BqD9Uxg1dHwEHEp3lw4LabsX48Thn1UaWOYm +uDrKgHfUB7FIg5S/Kkx+ImliliRVerZoZvRiejnAvW9bTtiZaFeetCUU7lUeZ1o2 +qiYpUQKBgHQDfdDhguBGPKpkJ7pVwHkJA/lyRWaN1hwplw4TvX2oH14NsHg5Q5Fd +lHqHFs2Ry/6X3bKgF0E6q4cx0V1Xnnj9sGsemlrHdiSxplDYRQql7X5OeYPGF/Bg +ZTTG8rDwy+ey6EP9BZUb03hISx/LyMynOzjGl6uOcdAcy2d9Vno0 +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key b/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key new file mode 100644 index 0000000..dfceaba --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEowIBAAKCAQEAsj2cHcrE2pdyCqNr+oVcQULiRx6RivkrhLl2DTqWXpP33BPm +MP0W0X0z98X7E3kZO+JIGRZ8q+6AWmUpL+53aOGItNeUgT7jQKViPJIo9ZcEnv/n +PJqdgDd4xFhnwYMgq8uVYN9IPfaKDwB3EoOqjNox2JholUVxvLw6W8DAC8La3zwb +0hiqtIlirQOQ/KaTHxC6dPYkrai+jSK5uAX7Vt8RKYg5qfDxSdZckmC2xVKYURhV +bZAlyKki4h6f8CwYCJMQDpHL6mVYCuJ1Ju/OJEXvthDKD0CD2hwILhksdey3qMOC +I5lHSO1b+sTvnVHGs65wI7A+ZYwnadMNvS9e2QIDAQABAoIBAH2uu9q2FEEe8SdX +PNiWGQtbojsL7wzTzj/0lq2VVlqyc+AXmAWLMP/fDTn1vKlqhsSXNseZ96c0sgUL +uBM4T7MA9WivauQH+C6pb6/OUFt8daG4SNGPJOg4NUweGmt1jyAUmeyJBWPL6GXT +qiK//Q78/JECRxyaryyqfWwdak3flzfwONBJ03tQ9EO+L7hf9gAP7OYnAsuNp+Bz +tj1xzNMumYYYiHvsEXx8UTe8HGrmYuO53ZY5fBLGB6Jj7hRlAHNfcdVDvvoBU5cI +Zwi+5YsBuSP2Hr9Gt2Odu+KitH3gFdS0HIiDh44AT+Trj29NMANFDfkDbVHUmE0q +YBL75NECgYEA2E+fJzdaYyyPIcvQgVM8g52hltR5IRgJICND3NOdB/Zb2teBGZh+ +1XJ6ZqQMDcOQZo0CMbX9UNRnf3NU55k48/EEITxCgUJTx/WdfJeTVlWGspt5+U/r +hDnQmkePdU1en63+u9eqsla9+VhLwU3fl/pIOpsBAnoEzs3hMQZ1G0cCgYEA0vHH +ilm3AztIoZlH3wgDAl2Gu5/YopqEofKA8G4Jp89rlkk919P/GNjEc6575wjgztDB +0Xab+H7Nqxjs3HqQX/DTTuAxzAggBg3j/ijpHnmjrCHLeMT5ciyH+EH5Bg///cLq ++Cwn7aOWuSK1hGdDYxUycHylAYZXXFJzmEIEhN8CgYEA1qTrwPZkctTckyS0GiCG +g/P/TLQ6HmTDaWiVBqPVxvjn3RjLuqJf+V5Hp2JRs7bDq39xFfMJExQyP34qWkbp +BOe8uV4agDlY+ar4Q5IFWj40EzfEqWhsxCC6pt0rtbK4mqsFg1BWyfDZQnwjcAXe +QejRk5YMQnDiJHSXaRaHTjECgYAv6ecvD624ODEJM63VhRZZ5TCDUY19caeKuXB8 +LCJZUY3Ydw5rBaY92I7Wz90o3yVhFJ3RnCVVTkgdAu5aLiS5BhSZJ+dntri/Z0xQ +IK7C01JP+OUkq2kVe/Pued28eMnms+13LWBsY+oKZ03foyz1Ro1Ma6N3MzKIr9m9 +zdEE9QKBgECfoh0xE2T/cbJrtH0mwMCUM6eMVGq+yQBKNvuuPg6kaQUsah1n1rp6 +OyvjwRAXdhshszEzNTX1WTT6/i+vZX277Ax50pPo9UhQ9kVteVt1frN6+u5sy07V +fg1f2+m0iFx4BD/irU0fzSyfGE+QkBnmXFBUNSYjp2PSqYIdufmW +-----END RSA PRIVATE KEY----- diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg new file mode 100644 index 0000000..459f731 --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A7K - one CP, two register values +control = [0xF2441920, 0xF2441940]; diff --git a/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg new file mode 100644 index 0000000..a849dff --- /dev/null +++ b/arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg @@ -0,0 +1,29 @@ +# Trusted boot image extension definitions + +kak_key_file = "tools/doimage/secure/kak_priv_pem.key"; + +# CSK keys array - 16 entries total. +# Only a key with csk_key_index will be used for signing the image +# use "*" string instead of file name for specifying an empty key +csk_key_file = ["tools/doimage/secure/csk_priv_pem0.key", + "tools/doimage/secure/csk_priv_pem1.key", + "tools/doimage/secure/csk_priv_pem2.key", + "tools/doimage/secure/csk_priv_pem3.key", + "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*", "*"]; + +# index of CSK key in the array. Valid range is 0 to 15 +csk_key_index = 3; + +# AES-256 symmetric key for image encryption +aes_key_file = "tools/doimage/secure/aes_key.txt"; + +efuse_disable = false; +jtag = { enable = true; delay = 20; }; + +box_id = 0xdeadbeef; +flash_id = 0xbaddf00d; + +# SecureBootControl and EfuseBurnControl registers array +# Two register addresses for each connected CP +# A8K - two CP, four register values +control = [0xF2441920, 0xF2441940, 0xF4441920, 0xF4441940]; diff --git a/arm-trusted-firmware/tools/memory/print_memory_map.py b/arm-trusted-firmware/tools/memory/print_memory_map.py new file mode 100755 index 0000000..8a84018 --- /dev/null +++ b/arm-trusted-firmware/tools/memory/print_memory_map.py @@ -0,0 +1,79 @@ +#!/usr/bin/env python3 +# +# Copyright (c) 2019-2020, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +import re +import os +import sys +import operator + +# List of folder/map to parse +bl_images = ['bl1', 'bl2', 'bl31'] + +# List of symbols to search for +blx_symbols = ['__BL1_RAM_START__', '__BL1_RAM_END__', + '__BL2_END__', + '__BL31_END__', + '__TEXT_START__', '__TEXT_END__', + '__RODATA_START__', '__RODATA_END__', + '__DATA_START__', '__DATA_END__', + '__STACKS_START__', '__STACKS_END__', + '__BSS_END', + '__COHERENT_RAM_START__', '__COHERENT_RAM_END__', + ] + +# Regex to extract address from map file +address_pattern = re.compile(r"\b0x\w*") + +# List of found element: [address, symbol, file] +address_list = [] + +# Get the directory from command line or use a default one +inverted_print = True +if len(sys.argv) >= 2: + build_dir = sys.argv[1] + if len(sys.argv) >= 3: + inverted_print = sys.argv[2] == '0' +else: + build_dir = 'build/fvp/debug' + +# Extract all the required symbols from the map files +for image in bl_images: + file_path = os.path.join(build_dir, image, '{}.map'.format(image)) + if os.path.isfile(file_path): + with open (file_path, 'rt') as mapfile: + for line in mapfile: + for symbol in blx_symbols: + # Regex to find symbol definition + line_pattern = re.compile(r"\b0x\w*\s*" + symbol + "\s= .") + match = line_pattern.search(line) + if match: + # Extract address from line + match = address_pattern.search(line) + if match: + address_list.append([match.group(0), symbol, image]) + +# Sort by address +address_list.sort(key=operator.itemgetter(0)) + +# Invert list for lower address at bottom +if inverted_print: + address_list = reversed(address_list) + +# Generate memory view +print('{:-^93}'.format('Memory Map from: ' + build_dir)) +for address in address_list: + if "bl1" in address[2]: + print(address[0], '+{:-^22}+ |{:^22}| |{:^22}|'.format(address[1], '', '')) + elif "bl2" in address[2]: + print(address[0], '|{:^22}| +{:-^22}+ |{:^22}|'.format('', address[1], '')) + elif "bl31" in address[2]: + print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1])) + else: + print(address[0], '|{:^22}| |{:^22}| +{:-^22}+'.format('', '', address[1])) + +print('{:^20}{:_^22} {:_^22} {:_^22}'.format('', '', '', '')) +print('{:^20}{:^22} {:^22} {:^22}'.format('address', 'bl1', 'bl2', 'bl31')) diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk b/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk new file mode 100644 index 0000000..e3b2e91 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/cert_create_tbbr.mk @@ -0,0 +1,31 @@ +# +# Copyright 2021 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +# Compile time defines used by NXP platforms + +PLAT_DEF_OID := yes + +ifeq (${PLAT_DEF_OID},yes) + +$(eval $(call add_define, PLAT_DEF_OID)) +$(eval $(call add_define, PDEF_KEYS)) +$(eval $(call add_define, PDEF_CERTS)) +$(eval $(call add_define, PDEF_EXTS)) + + +INC_DIR += -I../../plat/nxp/common/fip_handler/common/ + +PDEF_CERT_TOOL_PATH := ../nxp/cert_create_helper +PLAT_INCLUDE += -I${PDEF_CERT_TOOL_PATH}/include + +PLAT_OBJECTS += ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_cert.o \ + ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_ext.o \ + ${PDEF_CERT_TOOL_PATH}/src/pdef_tbb_key.o + +$(shell rm ${PLAT_OBJECTS}) + +OBJECTS += ${PLAT_OBJECTS} +endif diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h new file mode 100644 index 0000000..f185619 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h @@ -0,0 +1,21 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_CERT_H +#define PDEF_TBB_CERT_H + +#include + +/* + * Enumerate the certificates that are used to establish the chain of trust + */ +enum { + DDR_FW_KEY_CERT = FWU_CERT + 1, + DDR_UDIMM_FW_CONTENT_CERT, + DDR_RDIMM_FW_CONTENT_CERT +}; + +#endif /* PDEF_TBB_CERT_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h new file mode 100644 index 0000000..5fb349c --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h @@ -0,0 +1,25 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_EXT_H +#define PDEF_TBB_EXT_H + +#include + +/* Plat Defined TBBR extensions */ +enum { + DDR_FW_CONTENT_CERT_PK_EXT = FWU_HASH_EXT + 1, + DDR_IMEM_UDIMM_1D_HASH_EXT, + DDR_IMEM_UDIMM_2D_HASH_EXT, + DDR_DMEM_UDIMM_1D_HASH_EXT, + DDR_DMEM_UDIMM_2D_HASH_EXT, + DDR_IMEM_RDIMM_1D_HASH_EXT, + DDR_IMEM_RDIMM_2D_HASH_EXT, + DDR_DMEM_RDIMM_1D_HASH_EXT, + DDR_DMEM_RDIMM_2D_HASH_EXT +}; + +#endif /* PDEF_TBB_EXT_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h new file mode 100644 index 0000000..b26b651 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h @@ -0,0 +1,18 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#ifndef PDEF_TBB_KEY_H +#define PDEF_TBB_KEY_H + +#include + +/* + * Enumerate the pltform defined keys that are used to establish the chain of trust + */ +enum { + DDR_FW_CONTENT_KEY = NON_TRUSTED_FW_CONTENT_CERT_KEY + 1, +}; +#endif /* PDEF_TBB_KEY_H */ diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c new file mode 100644 index 0000000..40bd928 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c @@ -0,0 +1,62 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include + +static cert_t pdef_tbb_certs[] = { + [DDR_FW_KEY_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_FW_KEY_CERT, + .opt = "ddr-fw-key-cert", + .help_msg = "DDR Firmware Key Certificate (output file)", + .fn = NULL, + .cn = "DDR Firmware Key Certificate", + .key = TRUSTED_WORLD_KEY, + .issuer = DDR_FW_KEY_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_FW_CONTENT_CERT_PK_EXT, + }, + .num_ext = 2 + }, + [DDR_UDIMM_FW_CONTENT_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_UDIMM_FW_CONTENT_CERT, + .opt = "ddr-udimm-fw-cert", + .help_msg = "DDR UDIMM Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "DDR UDIMM Firmware Content Certificate", + .key = DDR_FW_CONTENT_KEY, + .issuer = DDR_UDIMM_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_IMEM_UDIMM_1D_HASH_EXT, + DDR_IMEM_UDIMM_2D_HASH_EXT, + DDR_DMEM_UDIMM_1D_HASH_EXT, + DDR_DMEM_UDIMM_2D_HASH_EXT, + }, + .num_ext = 5 + }, + [DDR_RDIMM_FW_CONTENT_CERT - DDR_FW_KEY_CERT] = { + .id = DDR_RDIMM_FW_CONTENT_CERT, + .opt = "ddr-rdimm-fw-cert", + .help_msg = "DDR RDIMM Firmware Content Certificate (output file)", + .fn = NULL, + .cn = "DDR RDIMM Firmware Content Certificate", + .key = DDR_FW_CONTENT_KEY, + .issuer = DDR_RDIMM_FW_CONTENT_CERT, + .ext = { + TRUSTED_FW_NVCOUNTER_EXT, + DDR_IMEM_RDIMM_1D_HASH_EXT, + DDR_IMEM_RDIMM_2D_HASH_EXT, + DDR_DMEM_RDIMM_1D_HASH_EXT, + DDR_DMEM_RDIMM_2D_HASH_EXT, + }, + .num_ext = 5 + } +}; + +PLAT_REGISTER_COT(pdef_tbb_certs); diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c new file mode 100644 index 0000000..f6da6dd --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c @@ -0,0 +1,108 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include + +#if USE_TBBR_DEFS +#include +#else +#include +#endif + +#include "ext.h" +#include "tbbr/tbb_ext.h" +#include "tbbr/tbb_key.h" + +#include +#include + +static ext_t pdef_tbb_ext[] = { + [DDR_FW_CONTENT_CERT_PK_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_FW_CONTENT_CERT_PK_OID, + .sn = "DDR FirmwareContentCertPK", + .ln = "DDR Firmware content certificate public key", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_PKEY, + .attr.key = DDR_FW_CONTENT_KEY + }, + [DDR_IMEM_UDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_UDIMM_1D_HASH_OID, + .opt = "ddr-immem-udimm-1d", + .help_msg = "DDR Firmware IMEM UDIMM 1D image file", + .sn = "DDR UDIMM IMEM 1D FirmwareHash", + .ln = "DDR UDIMM IMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_UDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_UDIMM_2D_HASH_OID, + .opt = "ddr-immem-udimm-2d", + .help_msg = "DDR Firmware IMEM UDIMM 2D image file", + .sn = "DDR UDIMM IMEM 2D FirmwareHash", + .ln = "DDR UDIMM IMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_UDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_UDIMM_1D_HASH_OID, + .opt = "ddr-dmmem-udimm-1d", + .help_msg = "DDR Firmware DMEM UDIMM 1D image file", + .sn = "DDR UDIMM DMEM 1D FirmwareHash", + .ln = "DDR UDIMM DMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_UDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_UDIMM_2D_HASH_OID, + .opt = "ddr-dmmem-udimm-2d", + .help_msg = "DDR Firmware DMEM UDIMM 2D image file", + .sn = "DDR UDIMM DMEM 2D FirmwareHash", + .ln = "DDR UDIMM DMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_RDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_RDIMM_1D_HASH_OID, + .opt = "ddr-immem-rdimm-1d", + .help_msg = "DDR Firmware IMEM RDIMM 1D image file", + .sn = "DDR RDIMM IMEM 1D FirmwareHash", + .ln = "DDR RDIMM IMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_IMEM_RDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_IMEM_RDIMM_2D_HASH_OID, + .opt = "ddr-immem-rdimm-2d", + .help_msg = "DDR Firmware IMEM RDIMM 2D image file", + .sn = "DDR RDIMM IMEM 2D FirmwareHash", + .ln = "DDR RDIMM IMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_RDIMM_1D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_RDIMM_1D_HASH_OID, + .opt = "ddr-dmmem-rdimm-1d", + .help_msg = "DDR Firmware DMEM RDIMM 1D image file", + .sn = "DDR RDIMM DMEM 1D FirmwareHash", + .ln = "DDR RDIMM DMEM 1D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + }, + [DDR_DMEM_RDIMM_2D_HASH_EXT - DDR_FW_CONTENT_CERT_PK_EXT] = { + .oid = DDR_DMEM_RDIMM_2D_HASH_OID, + .opt = "ddr-dmmem-rdimm-2d", + .help_msg = "DDR Firmware DMEM RDIMM 2D image file", + .sn = "DDR RDIMM DMEM 2D FirmwareHash", + .ln = "DDR RDIMM DMEM 2D Firmware hash (SHA256)", + .asn1_type = V_ASN1_OCTET_STRING, + .type = EXT_TYPE_HASH + } +}; + +PLAT_REGISTER_EXTENSIONS(pdef_tbb_ext); diff --git a/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c new file mode 100644 index 0000000..cf2ebda --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c @@ -0,0 +1,18 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +static key_t pdef_tbb_keys[] = { + [DDR_FW_CONTENT_KEY - DDR_FW_CONTENT_KEY] = { + .id = DDR_FW_CONTENT_KEY, + .opt = "ddr-fw-key", + .help_msg = "DDR Firmware Content Certificate key (input/output file)", + .desc = "DDR Firmware Content Certificate key" + } +}; + +PLAT_REGISTER_KEYS(pdef_tbb_keys); diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/Makefile b/arm-trusted-firmware/tools/nxp/create_pbl/Makefile new file mode 100644 index 0000000..f971a74 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/Makefile @@ -0,0 +1,61 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MAKE_HELPERS_DIRECTORY := ../../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +PROJECT_1 := create_pbl${BIN_EXT} +OBJECTS_1 := create_pbl.o +PROJECT_2 := byte_swap${BIN_EXT} +OBJECTS_2 := byte_swap.o +V ?= 0 + +override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 +CFLAGS := -Wall -Werror -pedantic -std=c99 +ifeq (${DEBUG},1) + CFLAGS += -g -O0 -DDEBUG +else + CFLAGS += -O2 +endif +LDLIBS := + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := + +HOSTCC ?= gcc +CC = gcc + +.PHONY: all clean distclean + +all: create_pbl byte_swap + +${PROJECT_1}: ${OBJECTS_1} Makefile + @echo " LD $@" + ${Q}${HOSTCC} ${OBJECTS_1} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +${PROJECT_2}: ${OBJECTS_2} Makefile + @echo " LD $@" + ${Q}${HOSTCC} ${OBJECTS_2} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c %.h Makefile + @echo " CC $<" + ${Q}${HOSTCC} -c ${CPPFLAGS} ${CFLAGS} ${INCLUDE_PATHS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT_1} ${OBJECTS_1}) + $(call SHELL_DELETE_ALL, ${PROJECT_2} ${OBJECTS_2}) diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/README b/arm-trusted-firmware/tools/nxp/create_pbl/README new file mode 100644 index 0000000..3b6f854 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/README @@ -0,0 +1,65 @@ +Description: +------------ +Tool 'create_pbl' is a standalone tool to create the PBL images. + where, + On the basis of Chassis, + RCW image is placed first followed by the, + PBI commands to copy the, + Input BL2 image stored on the, + Specified boot source (QSPI or SD or NOR) to the, + Specified destination address. + + +Usage in standalone way: +----------------------- + +./create_pbl [options] (mentioned below): + + -r - name of RCW binary file. + -i - file to be added to rcw file. + -c - SoC numeric identifier, may be one of + 1012,1023,1026.1028, + 1043,1046,1088,2080, + 2088,2160 + -b - Boot source id string, may be one of + "qspi", "nor", "nand", "sd", "emmc" + -d
- Destination address where BL2 + image is to be copied + -o - Name of PBL image generated + as an output of the tool. + -e
- [Optional] Entry Point Address + of the BL2.bin + -f
- BL2 image offset + on Boot Source for block copy. + command for chassis >=3.) + (Must for Ch3, Ignored for Ch2) + -h Help. + -s Secure boot. + + -s secure boot + -c SoC Number (see description above) + -b Boot source. + -r RCW binary file. + -i Input file that is to be added to rcw file. + -o Name of output file + -f Source Offset (Block Copy) + -d Destination address to which file has to be copied + -h Help. + +Example: + ./create_pbl -r -i -c -b -d -o + + + +Usage at compilation time: +-------------------------------- + + make pbl RCW=/ + +Example: QSPI Boot For LS1046ARDB- + + make PLAT=ls1046rdb all fip BOOT_MODE=qspi SPD=opteed BL32=tee.bin BL33=u-boot-ls1046.bin pbl RCW=/home/pankaj/flexbuild/packages/firmware/dash-rcw/ls1046ardb/RR_FFSSPPPN_1133_5506/rcw_1600_qspiboot.bin + +Example: QSPI Boot For LX2160ARDB- + + make PLAT=lx2160ardb all fip BOOT_MODE=flexspi_nor SPD=opteed BL32=tee_lx2.bin BL33=u-boot_lx2160.bin pbl RCW=plat/nxp/soc-lx2160/lx2160ardb/rcw_1900_600_1600_19_5_2.bin diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c b/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c new file mode 100644 index 0000000..1d0bfce --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c @@ -0,0 +1,113 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include + +#include +#include + +#define NUM_MEM_BLOCK 1 +#define FOUR_BYTE_ALIGN 4 +#define EIGHT_BYTE_ALIGN 8 +#define SIZE_TWO_PBL_CMD 24 + +#define SUCCESS 0 +#define FAILURE -1 +#define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24)| \ + (((word) & 0x00ff0000) >> 8) | \ + (((word) & 0x0000ff00) << 8) | \ + (((word) & 0x000000ff) << 24)) + + +/* + * Returns: + * SUCCESS, on successful byte swapping. + * FAILURE, on failure. + */ +int do_byteswap(FILE *fp) +{ + int bytes = 0; + uint32_t upper_byte; + uint32_t lower_byte; + uint32_t pad = 0U; + /* Carries number of Padding bytes to be appended to + * make file size 8 byte aligned. + */ + int append_bytes; + int ret = FAILURE; + + fseek(fp, 0L, SEEK_END); + bytes = ftell(fp); + + append_bytes = EIGHT_BYTE_ALIGN - (bytes % EIGHT_BYTE_ALIGN); + if (append_bytes != 0) { + if (fwrite(&pad, append_bytes, NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error in appending padding bytes.\n", + __func__); + goto byteswap_err; + } + bytes += append_bytes; + } + + rewind(fp); + while (bytes > 0) { + if ((fread(&upper_byte, sizeof(upper_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) && (feof(fp) == 0)) { + printf("%s: Error reading upper bytes.\n", __func__); + goto byteswap_err; + } + if ((fread(&lower_byte, sizeof(lower_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) && (feof(fp) == 0)) { + printf("%s: Error reading lower bytes.\n", __func__); + goto byteswap_err; + } + fseek(fp, -8L, SEEK_CUR); + upper_byte = BYTE_SWAP_32(upper_byte); + lower_byte = BYTE_SWAP_32(lower_byte); + if (fwrite(&lower_byte, sizeof(lower_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error writing lower bytes.\n", __func__); + goto byteswap_err; + } + if (fwrite(&upper_byte, sizeof(upper_byte), NUM_MEM_BLOCK, fp) + != NUM_MEM_BLOCK) { + printf("%s: Error writing upper bytes.\n", __func__); + goto byteswap_err; + } + bytes -= EIGHT_BYTE_ALIGN; + } + ret = SUCCESS; + +byteswap_err: + return ret; +} + +int main(int argc, char **argv) +{ + FILE *fp = NULL; + int ret = 0; + + if (argc > 2) { + printf("Usage format is byteswap "); + return -1; + } + + fp = fopen(argv[1], "rb+"); + if (fp == NULL) { + printf("%s: Error opening the input file: %s\n", + __func__, argv[1]); + return -1; + } + + ret = do_byteswap(fp); + fclose(fp); + return ret; +} diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c new file mode 100644 index 0000000..9457a00 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c @@ -0,0 +1,998 @@ +/* + * Copyright 2021-2022 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + * + */ + +#include +#include +#include +#include +#include + +#include +#include + +#define NUM_MEM_BLOCK 1 +#define FOUR_BYTE_ALIGN 4 +#define EIGHT_BYTE_ALIGN 8 +#define SIZE_TWO_PBL_CMD 24 + +/* Define for add_boot_ptr_cmd() */ +#define BOOTPTR_ADDR 0x09570604 +#define CSF_ADDR_SB 0x09ee0200 +/* CCSR write command to address 0x1e00400 i.e BOOTLOCPTR */ +#define BOOTPTR_ADDR_CH3 0x31e00400 +/* Load CSF header command */ +#define CSF_ADDR_SB_CH3 0x80220000 + +#define MAND_ARG_MASK 0xFFF3 +#define ARG_INIT_MASK 0xFF00 +#define RCW_FILE_NAME_ARG_MASK 0x0080 +#define IN_FILE_NAME_ARG_MASK 0x0040 +#define CHASSIS_ARG_MASK 0x0020 +#define BOOT_SRC_ARG_MASK 0x0010 +#define ENTRY_POINT_ADDR_ARG_MASK 0x0008 +#define BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK 0x0004 +#define BL2_BIN_CPY_DEST_ADDR_ARG_MASK 0x0002 +#define OP_FILE_NAME_ARG_MASK 0x0001 + +/* Define for add_cpy_cmd() */ +#define OFFSET_MASK 0x00ffffff +#define WRITE_CMD_BASE 0x81000000 +#define MAX_PBI_DATA_LEN_BYTE 64 + +/* 140 Bytes = Preamble + LOAD RCW command + RCW (128 bytes) + Checksum */ +#define CHS3_CRC_PAYLOAD_START_OFFSET 140 + +#define PBI_CRC_POLYNOMIAL 0x04c11db7 + +typedef enum { + CHASSIS_UNKNOWN, + CHASSIS_2, + CHASSIS_3, + CHASSIS_3_2, + CHASSIS_MAX /* must be last item in list */ +} chassis_t; + +typedef enum { + UNKNOWN_BOOT = 0, + IFC_NOR_BOOT, + IFC_NAND_BOOT, + QSPI_BOOT, + SD_BOOT, + EMMC_BOOT, + FLXSPI_NOR_BOOT, + FLXSPI_NAND_BOOT, + FLXSPI_NAND4K_BOOT, + MAX_BOOT /* must be last item in list */ +} boot_src_t; + +/* Base Addresses where PBL image is copied depending on the boot source. + * Boot address map varies as per Chassis architecture. + */ +#define BASE_ADDR_UNDEFINED 0xFFFFFFFF +#define BASE_ADDR_QSPI 0x20000000 +#define BASE_ADDR_SD 0x00001000 +#define BASE_ADDR_IFC_NOR 0x30000000 +#define BASE_ADDR_EMMC 0x00001000 +#define BASE_ADDR_FLX_NOR 0x20000000 +#define BASE_ADDR_NAND 0x20000000 + +uint32_t base_addr_ch3[MAX_BOOT] = { + BASE_ADDR_UNDEFINED, + BASE_ADDR_IFC_NOR, + BASE_ADDR_UNDEFINED, /*IFC NAND */ + BASE_ADDR_QSPI, + BASE_ADDR_SD, + BASE_ADDR_EMMC, + BASE_ADDR_UNDEFINED, /*FLXSPI NOR */ + BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ + BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ +}; + +uint32_t base_addr_ch32[MAX_BOOT] = { + BASE_ADDR_UNDEFINED, + BASE_ADDR_UNDEFINED, /* IFC NOR */ + BASE_ADDR_UNDEFINED, /* IFC NAND */ + BASE_ADDR_UNDEFINED, /* QSPI */ + BASE_ADDR_SD, + BASE_ADDR_EMMC, + BASE_ADDR_FLX_NOR, + BASE_ADDR_UNDEFINED, /*FLXSPI NAND 2K */ + BASE_ADDR_UNDEFINED /*FLXSPI NAND 4K */ +}; + +/* for Chassis 3 */ +uint32_t blk_cpy_hdr_map_ch3[] = { + + 0, /* Unknown Boot Source */ + 0x80000020, /* NOR_BOOT */ + 0x0, /* NAND_BOOT */ + 0x80000062, /* QSPI_BOOT */ + 0x80000040, /* SD_BOOT */ + 0x80000041, /* EMMC_BOOT */ + 0x0, /* FLEXSPI NOR_BOOT */ + 0x0, /* FLEX SPI NAND2K BOOT */ + 0x0, /* CHASIS3_2_NAND4K_BOOT */ +}; + +uint32_t blk_cpy_hdr_map_ch32[] = { + 0, /* Unknown Boot Source */ + 0x0, /* NOR_BOOT */ + 0x0, /* NAND_BOOT */ + 0x0, /* QSPI_BOOT */ + 0x80000008, /* SD_BOOT */ + 0x80000009, /* EMMC_BOOT */ + 0x8000000F, /* FLEXSPI NOR_BOOT */ + 0x8000000C, /* FLEX SPI NAND2K BOOT */ + 0x8000000D, /* CHASIS3_2_NAND4K_BOOT */ +}; + +char *boot_src_string[] = { + "UNKNOWN_BOOT", + "IFC_NOR_BOOT", + "IFC_NAND_BOOT", + "QSPI_BOOT", + "SD_BOOT", + "EMMC_BOOT", + "FLXSPI_NOR_BOOT", + "FLXSPI_NAND_BOOT", + "FLXSPI_NAND4K_BOOT", +}; + +enum stop_command { + STOP_COMMAND = 0, + CRC_STOP_COMMAND +}; + +/* Structure will get populated in the main function + * as part of parsing the command line arguments. + * All member parameters are mandatory except: + * -ep + * -src_addr + */ +struct pbl_image { + char *rcw_nm; /* Input RCW File */ + char *sec_imgnm; /* Input BL2 binary */ + char *imagefile; /* Generated output file */ + boot_src_t boot_src; /* Boot Source - QSPI, SD, NOR, NAND etc */ + uint32_t src_addr; /* Source Address */ + uint32_t addr; /* Load address */ + uint32_t ep; /* Entry point default is load address */ + chassis_t chassis; /* Chassis type */ +} pblimg; + +#define SUCCESS 0 +#define FAILURE -1 +#define CRC_STOP_CMD_ARM 0x08610040 +#define CRC_STOP_CMD_ARM_CH3 0x808f0000 +#define STOP_CMD_ARM_CH3 0x80ff0000 +#define BYTE_SWAP_32(word) ((((word) & 0xff000000) >> 24)| \ + (((word) & 0x00ff0000) >> 8) | \ + (((word) & 0x0000ff00) << 8) | \ + (((word) & 0x000000ff) << 24)) + +#define PBI_LEN_MASK 0xFFF00000 +#define PBI_LEN_SHIFT 20 +#define NUM_RCW_WORD 35 +#define PBI_LEN_ADD 6 + +#define MAX_CRC_ENTRIES 256 + +/* SoC numeric identifier */ +#define SOC_LS1012 1012 +#define SOC_LS1023 1023 +#define SOC_LS1026 1026 +#define SOC_LS1028 1028 +#define SOC_LS1043 1043 +#define SOC_LS1046 1046 +#define SOC_LS1088 1088 +#define SOC_LS2080 2080 +#define SOC_LS2088 2088 +#define SOC_LX2160 2160 + +static uint32_t pbl_size; +bool sb_flag; + +/*************************************************************************** + * Description : CRC32 Lookup Table + ***************************************************************************/ +static uint32_t crc32_lookup[] = { + 0x00000000, 0x77073096, 0xEE0E612C, 0x990951BA, + 0x076DC419, 0x706AF48F, 0xE963A535, 0x9E6495A3, + 0x0EDB8832, 0x79DCB8A4, 0xE0D5E91E, 0x97D2D988, + 0x09B64C2B, 0x7EB17CBD, 0xE7B82D07, 0x90BF1D91, + 0x1DB71064, 0x6AB020F2, 0xF3B97148, 0x84BE41DE, + 0x1ADAD47D, 0x6DDDE4EB, 0xF4D4B551, 0x83D385C7, + 0x136C9856, 0x646BA8C0, 0xFD62F97A, 0x8A65C9EC, + 0x14015C4F, 0x63066CD9, 0xFA0F3D63, 0x8D080DF5, + 0x3B6E20C8, 0x4C69105E, 0xD56041E4, 0xA2677172, + 0x3C03E4D1, 0x4B04D447, 0xD20D85FD, 0xA50AB56B, + 0x35B5A8FA, 0x42B2986C, 0xDBBBC9D6, 0xACBCF940, + 0x32D86CE3, 0x45DF5C75, 0xDCD60DCF, 0xABD13D59, + 0x26D930AC, 0x51DE003A, 0xC8D75180, 0xBFD06116, + 0x21B4F4B5, 0x56B3C423, 0xCFBA9599, 0xB8BDA50F, + 0x2802B89E, 0x5F058808, 0xC60CD9B2, 0xB10BE924, + 0x2F6F7C87, 0x58684C11, 0xC1611DAB, 0xB6662D3D, + 0x76DC4190, 0x01DB7106, 0x98D220BC, 0xEFD5102A, + 0x71B18589, 0x06B6B51F, 0x9FBFE4A5, 0xE8B8D433, + 0x7807C9A2, 0x0F00F934, 0x9609A88E, 0xE10E9818, + 0x7F6A0DBB, 0x086D3D2D, 0x91646C97, 0xE6635C01, + 0x6B6B51F4, 0x1C6C6162, 0x856530D8, 0xF262004E, + 0x6C0695ED, 0x1B01A57B, 0x8208F4C1, 0xF50FC457, + 0x65B0D9C6, 0x12B7E950, 0x8BBEB8EA, 0xFCB9887C, + 0x62DD1DDF, 0x15DA2D49, 0x8CD37CF3, 0xFBD44C65, + 0x4DB26158, 0x3AB551CE, 0xA3BC0074, 0xD4BB30E2, + 0x4ADFA541, 0x3DD895D7, 0xA4D1C46D, 0xD3D6F4FB, + 0x4369E96A, 0x346ED9FC, 0xAD678846, 0xDA60B8D0, + 0x44042D73, 0x33031DE5, 0xAA0A4C5F, 0xDD0D7CC9, + 0x5005713C, 0x270241AA, 0xBE0B1010, 0xC90C2086, + 0x5768B525, 0x206F85B3, 0xB966D409, 0xCE61E49F, + 0x5EDEF90E, 0x29D9C998, 0xB0D09822, 0xC7D7A8B4, + 0x59B33D17, 0x2EB40D81, 0xB7BD5C3B, 0xC0BA6CAD, + 0xEDB88320, 0x9ABFB3B6, 0x03B6E20C, 0x74B1D29A, + 0xEAD54739, 0x9DD277AF, 0x04DB2615, 0x73DC1683, + 0xE3630B12, 0x94643B84, 0x0D6D6A3E, 0x7A6A5AA8, + 0xE40ECF0B, 0x9309FF9D, 0x0A00AE27, 0x7D079EB1, + 0xF00F9344, 0x8708A3D2, 0x1E01F268, 0x6906C2FE, + 0xF762575D, 0x806567CB, 0x196C3671, 0x6E6B06E7, + 0xFED41B76, 0x89D32BE0, 0x10DA7A5A, 0x67DD4ACC, + 0xF9B9DF6F, 0x8EBEEFF9, 0x17B7BE43, 0x60B08ED5, + 0xD6D6A3E8, 0xA1D1937E, 0x38D8C2C4, 0x4FDFF252, + 0xD1BB67F1, 0xA6BC5767, 0x3FB506DD, 0x48B2364B, + 0xD80D2BDA, 0xAF0A1B4C, 0x36034AF6, 0x41047A60, + 0xDF60EFC3, 0xA867DF55, 0x316E8EEF, 0x4669BE79, + 0xCB61B38C, 0xBC66831A, 0x256FD2A0, 0x5268E236, + 0xCC0C7795, 0xBB0B4703, 0x220216B9, 0x5505262F, + 0xC5BA3BBE, 0xB2BD0B28, 0x2BB45A92, 0x5CB36A04, + 0xC2D7FFA7, 0xB5D0CF31, 0x2CD99E8B, 0x5BDEAE1D, + 0x9B64C2B0, 0xEC63F226, 0x756AA39C, 0x026D930A, + 0x9C0906A9, 0xEB0E363F, 0x72076785, 0x05005713, + 0x95BF4A82, 0xE2B87A14, 0x7BB12BAE, 0x0CB61B38, + 0x92D28E9B, 0xE5D5BE0D, 0x7CDCEFB7, 0x0BDBDF21, + 0x86D3D2D4, 0xF1D4E242, 0x68DDB3F8, 0x1FDA836E, + 0x81BE16CD, 0xF6B9265B, 0x6FB077E1, 0x18B74777, + 0x88085AE6, 0xFF0F6A70, 0x66063BCA, 0x11010B5C, + 0x8F659EFF, 0xF862AE69, 0x616BFFD3, 0x166CCF45, + 0xA00AE278, 0xD70DD2EE, 0x4E048354, 0x3903B3C2, + 0xA7672661, 0xD06016F7, 0x4969474D, 0x3E6E77DB, + 0xAED16A4A, 0xD9D65ADC, 0x40DF0B66, 0x37D83BF0, + 0xA9BCAE53, 0xDEBB9EC5, 0x47B2CF7F, 0x30B5FFE9, + 0xBDBDF21C, 0xCABAC28A, 0x53B39330, 0x24B4A3A6, + 0xBAD03605, 0xCDD70693, 0x54DE5729, 0x23D967BF, + 0xB3667A2E, 0xC4614AB8, 0x5D681B02, 0x2A6F2B94, + 0xB40BBE37, 0xC30C8EA1, 0x5A05DF1B, 0x2D02EF8D + }; + + +static void print_usage(void) +{ + printf("\nCorrect Usage of Tool is:\n"); + printf("\n ./create_pbl [options] (mentioned below):\n\n"); + printf("\t-r - name of RCW binary file.\n"); + printf("\t-i - file to be added to rcw file.\n"); + printf("\t-c - Chassis Architecture (=2 or =3\n"); + printf("\t or =4 for 3.2).\n"); + printf("\t-b - Boot source.\n"); + printf("\t-d
- Destination address where BL2\n"); + printf("\t image is to be copied\n"); + printf("\t-o - Name of PBL image generated\n"); + printf("\t as an output of the tool.\n"); + printf("\t-f
- BL2 image Src Offset\n"); + printf("\t on Boot Source for block copy.\n"); + printf("\t command for chassis >=3.)\n"); + printf("\t-e
- [Optional] Entry Point Address\n"); + printf("\t of the BL2.bin\n"); + printf("\t-s Secure Boot.\n"); + printf("\t-h Help.\n"); + printf("\n\n"); + exit(0); + +} + +/*************************************************************************** + * Function : crypto_calculate_checksum() + * Arguments : data - Pointer to FILE + * num - Number of 32 bit words for checksum + * Return : Checksum Value + * Description : Calculate Checksum over the data + ***************************************************************************/ +uint32_t crypto_calculate_checksum(FILE *fp_rcw_pbi_op, uint32_t num) +{ + uint32_t i; + uint64_t sum = 0; + uint32_t word; + + fseek(fp_rcw_pbi_op, 0L, SEEK_SET); + for (i = 0; i < num ; i++) { + if ((fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_op)) + < NUM_MEM_BLOCK) { + printf("%s: Error reading word.\n", __func__); + return FAILURE; + } + sum = sum + word; + sum = sum & 0xFFFFFFFF; + } + return (uint32_t)sum; +} + +/*************************************************************************** + * Function : add_pbi_stop_cmd + * Arguments : fp_rcw_pbi_op - output rcw_pbi file pointer + * Return : SUCCESS or FAILURE + * Description : This function insert pbi stop command. + ***************************************************************************/ +int add_pbi_stop_cmd(FILE *fp_rcw_pbi_op, enum stop_command flag) +{ + int ret = FAILURE; + int32_t pbi_stop_cmd; + uint32_t pbi_crc = 0xffffffff, i, j, c; + uint32_t crc_table[MAX_CRC_ENTRIES]; + uint8_t data; + + switch (pblimg.chassis) { + case CHASSIS_2: + pbi_stop_cmd = BYTE_SWAP_32(CRC_STOP_CMD_ARM); + break; + case CHASSIS_3: + case CHASSIS_3_2: + /* Based on flag add the corresponsding cmd + * -- stop cmd or stop with CRC cmd + */ + if (flag == CRC_STOP_COMMAND) { + pbi_stop_cmd = CRC_STOP_CMD_ARM_CH3; + } else { + pbi_stop_cmd = STOP_CMD_ARM_CH3; + } + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + default: + printf("Internal Error: Invalid Chassis val = %d.\n", + pblimg.chassis); + goto pbi_stop_err; + } + + if (fwrite(&pbi_stop_cmd, sizeof(pbi_stop_cmd), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI STOP CMD\n", __func__); + goto pbi_stop_err; + } + + if (flag == CRC_STOP_COMMAND) { + for (i = 0; i < MAX_CRC_ENTRIES; i++) { + c = i << 24; + for (j = 0; j < 8; j++) { + c = (c & 0x80000000) ? + PBI_CRC_POLYNOMIAL ^ (c << 1) : c << 1; + } + + crc_table[i] = c; + } + } + + switch (pblimg.chassis) { + case CHASSIS_2: + /* Chassis 2: CRC is calculated on RCW + PBL cmd.*/ + fseek(fp_rcw_pbi_op, 0L, SEEK_SET); + break; + case CHASSIS_3: + case CHASSIS_3_2: + /* Chassis 3: CRC is calculated on PBL cmd only. */ + fseek(fp_rcw_pbi_op, CHS3_CRC_PAYLOAD_START_OFFSET, SEEK_SET); + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + printf("%s: Unknown Chassis.\n", __func__); + goto pbi_stop_err; + } + + while ((fread(&data, sizeof(data), NUM_MEM_BLOCK, fp_rcw_pbi_op)) + == NUM_MEM_BLOCK) { + if (flag == CRC_STOP_COMMAND) { + if (pblimg.chassis == CHASSIS_2) { + pbi_crc = crc_table + [((pbi_crc >> 24) ^ (data)) & 0xff] ^ + (pbi_crc << 8); + } else { + pbi_crc = (pbi_crc >> 8) ^ + crc32_lookup[((pbi_crc) ^ + (data)) & 0xff]; + } + } + } + + switch (pblimg.chassis) { + case CHASSIS_2: + pbi_crc = BYTE_SWAP_32(pbi_crc); + break; + case CHASSIS_3: + case CHASSIS_3_2: + if (flag == CRC_STOP_COMMAND) { + pbi_crc = pbi_crc ^ 0xFFFFFFFF; + } else { + pbi_crc = 0x00000000; + } + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + printf("%s: Unknown Chassis.\n", __func__); + goto pbi_stop_err; + } + + if (fwrite(&pbi_crc, sizeof(pbi_crc), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI PBI CRC\n", __func__); + goto pbi_stop_err; + } + ret = SUCCESS; + +pbi_stop_err: + return ret; +} + +/* + * Returns: + * File size in bytes, on Success. + * FAILURE, on failure. + */ +int get_filesize(const char *c) +{ + FILE *fp; + int ret = FAILURE; + + fp = fopen(c, "rb"); + if (fp == NULL) { + fprintf(stderr, "%s: Error in opening the file: %s\n", + __func__, c); + goto filesize_err; + } + + fseek(fp, 0L, SEEK_END); + ret = ftell(fp); + fclose(fp); + +filesize_err: + return ret; +} + +/*************************************************************************** + * Function : get_bootptr + * Arguments : fp_rcw_pbi_op - Pointer to output file + * Return : SUCCESS or FAILURE + * Description : Add bootptr pbi command to output file + ***************************************************************************/ +int add_boot_ptr_cmd(FILE *fp_rcw_pbi_op) +{ + uint32_t bootptr_addr; + int ret = FAILURE; + + switch (pblimg.chassis) { + case CHASSIS_2: + if (sb_flag == true) + bootptr_addr = BYTE_SWAP_32(CSF_ADDR_SB); + else + bootptr_addr = BYTE_SWAP_32(BOOTPTR_ADDR); + pblimg.ep = BYTE_SWAP_32(pblimg.ep); + break; + case CHASSIS_3: + case CHASSIS_3_2: + if (sb_flag == true) + bootptr_addr = CSF_ADDR_SB_CH3; + else + bootptr_addr = BOOTPTR_ADDR_CH3; + break; + case CHASSIS_UNKNOWN: + case CHASSIS_MAX: + default: + printf("Internal Error: Invalid Chassis val = %d.\n", + pblimg.chassis); + goto bootptr_err; + } + + if (fwrite(&bootptr_addr, sizeof(bootptr_addr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI Words:[%d].\n", + __func__, ret); + goto bootptr_err; + } + + if (pblimg.ep != 0) { + if (fwrite(&pblimg.ep, sizeof(pblimg.ep), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in Writing PBI Words\n", __func__); + goto bootptr_err; + } + } + + printf("\nBoot Location Pointer= 0x%x\n", + pblimg.chassis == CHASSIS_2 ? BYTE_SWAP_32(pblimg.ep) : + pblimg.ep); + ret = SUCCESS; + +bootptr_err: + return ret; +} + +/*************************************************************************** + * Function : add_blk_cpy_cmd + * Arguments : pbi_word - pointer to pbi commands + * args - Command line args flag. + * Return : SUCCESS or FAILURE + * Description : Add pbi commands for block copy cmd in pbi_words + ***************************************************************************/ +int add_blk_cpy_cmd(FILE *fp_rcw_pbi_op, uint16_t args) +{ + uint32_t blk_cpy_hdr; + uint32_t file_size, new_file_size; + uint32_t align = 4; + int ret = FAILURE; + int num_pad_bytes = 0; + + if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) { + printf("ERROR: Offset not specified for Block Copy Cmd.\n"); + printf("\tSee Usage and use -f option\n"); + goto blk_copy_err; + } + + switch (pblimg.chassis) { + case CHASSIS_3: + /* Block copy command */ + blk_cpy_hdr = blk_cpy_hdr_map_ch3[pblimg.boot_src]; + pblimg.src_addr += base_addr_ch3[pblimg.boot_src]; + break; + case CHASSIS_3_2: + /* Block copy command */ + blk_cpy_hdr = blk_cpy_hdr_map_ch32[pblimg.boot_src]; + pblimg.src_addr += base_addr_ch32[pblimg.boot_src]; + break; + default: + printf("%s: Error invalid chassis type for this command.\n", + __func__); + goto blk_copy_err; + } + + file_size = get_filesize(pblimg.sec_imgnm); + if (file_size > 0) { + new_file_size = (file_size + (file_size % align)); + + /* Add Block copy command */ + if (fwrite(&blk_cpy_hdr, sizeof(blk_cpy_hdr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing blk_cpy_hdr to the file.\n", + __func__); + goto blk_copy_err; + } + + if ((args & BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK) == 0) + num_pad_bytes = pblimg.src_addr % 4; + + /* Add Src address word */ + if (fwrite(&pblimg.src_addr + num_pad_bytes, + sizeof(pblimg.src_addr), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing BLK SRC Addr to the file.\n", + __func__); + goto blk_copy_err; + } + + /* Add Dest address word */ + if (fwrite(&pblimg.addr, sizeof(pblimg.addr), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing DST Addr to the file.\n", + __func__); + goto blk_copy_err; + } + + /* Add size */ + if (fwrite(&new_file_size, sizeof(new_file_size), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing size to the file.\n", + __func__); + goto blk_copy_err; + } + } + + ret = SUCCESS; + +blk_copy_err: + return ret; +} + +/*************************************************************************** + * Function : add_cpy_cmd + * Arguments : pbi_word - pointer to pbi commands + * Return : SUCCESS or FAILURE + * Description : Append pbi commands for copying BL2 image to the + * load address stored in pbl_image.addr + ***************************************************************************/ +int add_cpy_cmd(FILE *fp_rcw_pbi_op) +{ + uint32_t ALTCBAR_ADDRESS = BYTE_SWAP_32(0x09570158); + uint32_t WAIT_CMD_WRITE_ADDRESS = BYTE_SWAP_32(0x096100c0); + uint32_t WAIT_CMD = BYTE_SWAP_32(0x000FFFFF); + int file_size; + uint32_t pbi_cmd, altcbar; + uint8_t pbi_data[MAX_PBI_DATA_LEN_BYTE]; + uint32_t dst_offset; + FILE *fp_img = NULL; + int ret = FAILURE; + + altcbar = pblimg.addr; + dst_offset = pblimg.addr; + fp_img = fopen(pblimg.sec_imgnm, "rb"); + if (fp_img == NULL) { + printf("%s: Error in opening the file: %s\n", __func__, + pblimg.sec_imgnm); + goto add_cpy_err; + } + file_size = get_filesize(pblimg.sec_imgnm); + altcbar = 0xfff00000 & altcbar; + altcbar = BYTE_SWAP_32(altcbar >> 16); + if (fwrite(&ALTCBAR_ADDRESS, sizeof(ALTCBAR_ADDRESS), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in writing address of ALTCFG CMD.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&altcbar, sizeof(altcbar), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in writing ALTCFG CMD.\n", __func__); + goto add_cpy_err; + } + if (fwrite(&WAIT_CMD_WRITE_ADDRESS, sizeof(WAIT_CMD_WRITE_ADDRESS), + NUM_MEM_BLOCK, fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error in writing address of WAIT_CMD.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&WAIT_CMD, sizeof(WAIT_CMD), NUM_MEM_BLOCK, fp_rcw_pbi_op) + != NUM_MEM_BLOCK) { + printf("%s: Error in writing WAIT_CMD.\n", __func__); + goto add_cpy_err; + } + do { + memset(pbi_data, 0, MAX_PBI_DATA_LEN_BYTE); + + ret = fread(&pbi_data, MAX_PBI_DATA_LEN_BYTE, + NUM_MEM_BLOCK, fp_img); + if ((ret != NUM_MEM_BLOCK) && (!feof(fp_img))) { + printf("%s: Error writing ALTCFG Word: [%d].\n", + __func__, ret); + goto add_cpy_err; + } + + dst_offset &= OFFSET_MASK; + pbi_cmd = WRITE_CMD_BASE | dst_offset; + pbi_cmd = BYTE_SWAP_32(pbi_cmd); + if (fwrite(&pbi_cmd, sizeof(pbi_cmd), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing ALTCFG Word write cmd.\n", + __func__); + goto add_cpy_err; + } + if (fwrite(&pbi_data, MAX_PBI_DATA_LEN_BYTE, NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: Error writing ALTCFG_Word.\n", __func__); + goto add_cpy_err; + } + dst_offset += MAX_PBI_DATA_LEN_BYTE; + file_size -= MAX_PBI_DATA_LEN_BYTE; + } while (!feof(fp_img)); + + ret = SUCCESS; + +add_cpy_err: + if (fp_img != NULL) { + fclose(fp_img); + } + return ret; +} + +int main(int argc, char **argv) +{ + FILE *file = NULL; + char *ptr; + int opt; + int tmp; + uint16_t args = ARG_INIT_MASK; + FILE *fp_rcw_pbi_ip = NULL, *fp_rcw_pbi_op = NULL; + uint32_t word, word_1; + int ret = FAILURE; + bool bootptr_flag = false; + enum stop_command flag_stop_cmd = CRC_STOP_COMMAND; + + /* Initializing the global structure to zero. */ + memset(&pblimg, 0x0, sizeof(struct pbl_image)); + + while ((opt = getopt(argc, argv, + ":b:f:r:i:e:d:c:o:h:s")) != -1) { + switch (opt) { + case 'd': + pblimg.addr = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, "CMD Error: invalid load or destination address %s\n", optarg); + goto exit_main; + } + args |= BL2_BIN_CPY_DEST_ADDR_ARG_MASK; + break; + case 'r': + pblimg.rcw_nm = optarg; + file = fopen(pblimg.rcw_nm, "r"); + if (file == NULL) { + printf("CMD Error: Opening the RCW File.\n"); + goto exit_main; + } else { + args |= RCW_FILE_NAME_ARG_MASK; + fclose(file); + } + break; + case 'e': + bootptr_flag = true; + pblimg.ep = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, + "CMD Error: Invalid entry point %s\n", optarg); + goto exit_main; + } + break; + case 'h': + print_usage(); + break; + case 'i': + pblimg.sec_imgnm = optarg; + file = fopen(pblimg.sec_imgnm, "r"); + if (file == NULL) { + printf("CMD Error: Opening Input file.\n"); + goto exit_main; + } else { + args |= IN_FILE_NAME_ARG_MASK; + fclose(file); + } + break; + case 'c': + tmp = atoi(optarg); + switch (tmp) { + case SOC_LS1012: + case SOC_LS1023: + case SOC_LS1026: + case SOC_LS1043: + case SOC_LS1046: + pblimg.chassis = CHASSIS_2; + break; + case SOC_LS1088: + case SOC_LS2080: + case SOC_LS2088: + pblimg.chassis = CHASSIS_3; + break; + case SOC_LS1028: + case SOC_LX2160: + pblimg.chassis = CHASSIS_3_2; + break; + default: + printf("CMD Error: Invalid SoC Val = %d.\n", tmp); + goto exit_main; + } + + args |= CHASSIS_ARG_MASK; + break; + case 'o': + pblimg.imagefile = optarg; + args |= OP_FILE_NAME_ARG_MASK; + break; + case 's': + sb_flag = true; + break; + case 'b': + if (strcmp(optarg, "qspi") == 0) { + pblimg.boot_src = QSPI_BOOT; + } else if (strcmp(optarg, "nor") == 0) { + pblimg.boot_src = IFC_NOR_BOOT; + } else if (strcmp(optarg, "nand") == 0) { + pblimg.boot_src = IFC_NAND_BOOT; + } else if (strcmp(optarg, "sd") == 0) { + pblimg.boot_src = SD_BOOT; + } else if (strcmp(optarg, "emmc") == 0) { + pblimg.boot_src = EMMC_BOOT; + } else if (strcmp(optarg, "flexspi_nor") == 0) { + pblimg.boot_src = FLXSPI_NOR_BOOT; + } else if (strcmp(optarg, "flexspi_nand") == 0) { + pblimg.boot_src = FLXSPI_NAND_BOOT; + } else if (strcmp(optarg, "flexspi_nand2k") == 0) { + pblimg.boot_src = FLXSPI_NAND4K_BOOT; + } else { + printf("CMD Error: Invalid boot source.\n"); + goto exit_main; + } + args |= BOOT_SRC_ARG_MASK; + break; + case 'f': + pblimg.src_addr = strtoull(optarg, &ptr, 16); + if (*ptr != 0) { + fprintf(stderr, + "CMD Error: Invalid src offset %s\n", optarg); + goto exit_main; + } + args |= BL2_BIN_STRG_LOC_BOOT_SRC_ARG_MASK; + break; + default: + /* issue a warning and skip the unknown arg */ + printf("Cmd Warning: Invalid Arg = %c.\n", opt); + } + } + + if ((args & MAND_ARG_MASK) != MAND_ARG_MASK) { + print_usage(); + } + + fp_rcw_pbi_ip = fopen(pblimg.rcw_nm, "rb"); + if (fp_rcw_pbi_ip == NULL) { + printf("%s: Error in opening the rcw file: %s\n", + __func__, pblimg.rcw_nm); + goto exit_main; + } + + fp_rcw_pbi_op = fopen(pblimg.imagefile, "wb+"); + if (fp_rcw_pbi_op == NULL) { + printf("%s: Error opening the input file: %s\n", + __func__, pblimg.imagefile); + goto exit_main; + } + + printf("\nInput Boot Source: %s\n", boot_src_string[pblimg.boot_src]); + printf("Input RCW File: %s\n", pblimg.rcw_nm); + printf("Input BL2 Binary File: %s\n", pblimg.sec_imgnm); + printf("Input load address for BL2 Binary File: 0x%x\n", pblimg.addr); + + printf("Chassis Type: %d\n", pblimg.chassis); + switch (pblimg.chassis) { + case CHASSIS_2: + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) + != NUM_MEM_BLOCK) { + printf("%s: Error in reading word from the rcw file.\n", + __func__); + goto exit_main; + } + while (BYTE_SWAP_32(word) != 0x08610040) { + if (BYTE_SWAP_32(word) == 0x09550000 + || BYTE_SWAP_32(word) == 0x000f400c) { + break; + } + if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: [CH2] Error in Writing PBI Words\n", + __func__); + goto exit_main; + } + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { + printf("%s: [CH2] Error in Reading PBI Words\n", + __func__); + goto exit_main; + } + } + + if (bootptr_flag == true) { + /* Add command to set boot_loc ptr */ + ret = add_boot_ptr_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + goto exit_main; + } + } + + /* Write acs write commands to output file */ + ret = add_cpy_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + goto exit_main; + } + + /* Add stop command after adding pbi commands + * For Chasis 2.0 platforms it is always CRC & + * Stop command + */ + flag_stop_cmd = CRC_STOP_COMMAND; + ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); + if (ret != SUCCESS) { + goto exit_main; + } + + break; + + case CHASSIS_3: + case CHASSIS_3_2: + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, fp_rcw_pbi_ip) + != NUM_MEM_BLOCK) { + printf("%s: Error reading PBI Cmd.\n", __func__); + goto exit_main; + } + while (word != 0x808f0000 && word != 0x80ff0000) { + pbl_size++; + /* 11th words in RCW has PBL length. Update it + * with new length. 2 comamnds get added + * Block copy + CCSR Write/CSF header write + */ + if (pbl_size == 11) { + word_1 = (word & PBI_LEN_MASK) + + (PBI_LEN_ADD << 20); + word = word & ~PBI_LEN_MASK; + word = word | word_1; + } + /* Update the CRC command */ + /* Check load command.. + * add a check if command is Stop with CRC + * or stop without checksum + */ + if (pbl_size == 35) { + word = crypto_calculate_checksum(fp_rcw_pbi_op, + NUM_RCW_WORD - 1); + if (word == FAILURE) { + goto exit_main; + } + } + if (fwrite(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_op) != NUM_MEM_BLOCK) { + printf("%s: [CH3] Error in Writing PBI Words\n", + __func__); + goto exit_main; + } + if (fread(&word, sizeof(word), NUM_MEM_BLOCK, + fp_rcw_pbi_ip) != NUM_MEM_BLOCK) { + printf("%s: [CH3] Error in Reading PBI Words\n", + __func__); + goto exit_main; + } + + if (word == CRC_STOP_CMD_ARM_CH3) { + flag_stop_cmd = CRC_STOP_COMMAND; + } else if (word == STOP_CMD_ARM_CH3) { + flag_stop_cmd = STOP_COMMAND; + } + } + if (bootptr_flag == true) { + /* Add command to set boot_loc ptr */ + ret = add_boot_ptr_cmd(fp_rcw_pbi_op); + if (ret != SUCCESS) { + printf("%s: add_boot_ptr_cmd return failure.\n", + __func__); + goto exit_main; + } + } + + /* Write acs write commands to output file */ + ret = add_blk_cpy_cmd(fp_rcw_pbi_op, args); + if (ret != SUCCESS) { + printf("%s: Function add_blk_cpy_cmd return failure.\n", + __func__); + goto exit_main; + } + + /* Add stop command after adding pbi commands */ + ret = add_pbi_stop_cmd(fp_rcw_pbi_op, flag_stop_cmd); + if (ret != SUCCESS) { + goto exit_main; + } + + break; + + default: + printf("%s: Unknown chassis type.\n", + __func__); + } + + if (ret == SUCCESS) { + printf("Output file successfully created with name: %s\n\n", + pblimg.imagefile); + } + +exit_main: + if (fp_rcw_pbi_op != NULL) { + fclose(fp_rcw_pbi_op); + } + if (fp_rcw_pbi_ip != NULL) { + fclose(fp_rcw_pbi_ip); + } + + return ret; +} diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk new file mode 100644 index 0000000..305c049 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.mk @@ -0,0 +1,52 @@ +# +# Copyright 2018-2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +#SWAP is required for Chassis 2 platforms - LS102, ls1043 and ls1046 for QSPI +ifeq (${SOC},ls1046a) +SOC_NUM := 1046a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1043a) +SOC_NUM := 1043a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1012a) +SOC_NUM := 1012a +SWAP = 1 +CH = 2 +else ifeq (${SOC},ls1088a) +SOC_NUM := 1088a +CH = 3 +else ifeq (${SOC},ls2088a) +SOC_NUM := 2088a +CH = 3 +else ifeq (${SOC},lx2160a) +SOC_NUM := 2160a +CH = 3 +else ifeq (${SOC},ls1028a) +SOC_NUM := 1028a +CH = 3 +else +$(error "Check SOC Not defined in create_pbl.mk.") +endif + +ifeq (${CH},2) + +include ${CREATE_PBL_TOOL_PATH}/pbl_ch2.mk + +endif #CH2 + +ifeq (${CH},3) + +include ${CREATE_PBL_TOOL_PATH}/pbl_ch3.mk + +endif #CH3 diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk new file mode 100644 index 0000000..e6f1d8b --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch2.mk @@ -0,0 +1,60 @@ +# +# Copyright 2020 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +.PHONY: pbl +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(SECURE_BOOT),yes) +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # Generate header for bl2.bin + $(Q)$(CST_DIR)/create_hdr_isbc --in ${BUILD_PLAT}/bl2.bin --out ${BUILD_PLAT}/hdr_bl2 ${BL2_INPUT_FILE} + # Compile create_pbl tool + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH};\ + # Add bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE}\ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl ;\ + # Add header to RCW + ${CREATE_PBL} -r ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -i ${BUILD_PLAT}/hdr_bl2 -b ${BOOT_MODE} -c ${SOC_NUM} \ + -d ${BL2_HDR_LOC} -e ${BL2_HDR_LOC} -o ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl -s;\ + rm ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl +# Swapping of RCW is required for QSPi Chassis 2 devices +ifeq (${BOOT_MODE}, qspi) +ifeq ($(SWAP),1) + ${Q}echo "Byteswapping RCW for QSPI" + ${BYTE_SWAP} ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl; +endif # SWAP +endif # BOOT_MODE + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +else # NON SECURE_BOOT +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # -a option appends the image for Chassis 3 devices in case of non secure boot + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH}; + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl ; +# Swapping of RCW is required for QSPi Chassis 2 devices +ifeq (${BOOT_MODE}, qspi) +ifeq ($(SWAP),1) + ${Q}echo "Byteswapping RCW for QSPI" + ${BYTE_SWAP} ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl; +endif # SWAP +endif # BOOT_MODE + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +endif # SECURE_BOOT + + + diff --git a/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk new file mode 100644 index 0000000..9283474 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/create_pbl/pbl_ch3.mk @@ -0,0 +1,71 @@ +# +# Copyright 2018-2022 NXP +# +# SPDX-License-Identifier: BSD-3-Clause +# +# +SHELL=/bin/bash + +CREATE_PBL ?= ${CREATE_PBL_TOOL_PATH}/create_pbl${BIN_EXT} +BYTE_SWAP ?= ${CREATE_PBL_TOOL_PATH}/byte_swap${BIN_EXT} + +HOST_GCC := gcc + +BL2_SRC_OFFSET ?= 0x9000 +BL2_HDR_SRC_OFFSET ?= 0x5000 +bl2_hdr_loc=$(shell echo $$(( $(BL2_HDR_SRC_OFFSET) / 1024 ))) +bl2_loc=$(shell echo $$(( $(BL2_SRC_OFFSET) / 1024 ))) + +.PHONY: pbl +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(SECURE_BOOT),yes) +pbl: ${BUILD_PLAT}/bl2.bin +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + # Generate header for bl2.bin + $(Q)$(CST_DIR)/create_hdr_isbc --in ${BUILD_PLAT}/bl2.bin --out ${BUILD_PLAT}/hdr_bl2 ${BL2_INPUT_FILE} + + # Compile create_pbl tool + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH};\ + + # Add Block Copy command for bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE}\ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -f ${BL2_SRC_OFFSET};\ + + # Add Block Copy command and Load CSF header command to RCW + ${CREATE_PBL} -r ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -i ${BUILD_PLAT}/hdr_bl2 -b ${BOOT_MODE} -c ${SOC_NUM} \ + -d ${BL2_HDR_LOC} -e ${BL2_HDR_LOC} -s -f ${BL2_HDR_SRC_OFFSET} \ + -o ${BUILD_PLAT}/rcw_sec.pbl + + # Sign and add "Load Security Header command to PBI commands + $(Q)$(CST_DIR)/create_hdr_pbi --out ${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl --in ${BUILD_PLAT}/rcw_sec.pbl ${PBI_INPUT_FILE} + + # Append the bl2_hdr to the RCW image + @echo "${bl2_hdr_loc}" + dd if=${BUILD_PLAT}/hdr_bl2 of=${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl bs=1K seek=${bl2_hdr_loc} + + # Append the bl2.bin to the RCW image + @echo "${bl2_loc}" + dd if=${BUILD_PLAT}/bl2.bin of=${BUILD_PLAT}/bl2_${BOOT_MODE}_sec.pbl bs=1K seek=${bl2_loc} + + rm ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +else #SECURE_BOOT +ifeq ($(RCW),"") + ${Q}echo "Platform ${PLAT} requires rcw file. Please set RCW to point to the right RCW file for boot mode ${BOOT_MODE}" +else + ${Q}${MAKE} CPPFLAGS="-DVERSION='\"${VERSION_STRING}\"'" --no-print-directory -C ${CREATE_PBL_TOOL_PATH}; + + # Add Block Copy command and populate boot loc ptrfor bl2.bin to RCW + ${CREATE_PBL} -r ${RCW} -i ${BUILD_PLAT}/bl2.bin -b ${BOOT_MODE} -c ${SOC_NUM} -d ${BL2_BASE} -e ${BL2_BASE} \ + -o ${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl -f ${BL2_SRC_OFFSET}; + + # Append the bl2.bin to the RCW image + @echo "bl2_loc is ${bl2_loc} KB" + dd if=${BUILD_PLAT}/bl2.bin of=${BUILD_PLAT}/bl2_${BOOT_MODE}.pbl bs=1K seek=${bl2_loc} + + cd ${CREATE_PBL_TOOL_PATH}; ${MAKE} clean ; cd -; +endif +endif # SECURE_BOOT diff --git a/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c new file mode 100644 index 0000000..fdb4b93 --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c @@ -0,0 +1,90 @@ +/* + * Copyright 2021 NXP + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#include + +#include "tbbr_config.h" + +toc_entry_t plat_def_toc_entries[] = { + /* DDR PHY firmwares */ + { + .name = "DDR UDIMM PHY IMEM 1d FW", + .uuid = UUID_DDR_IMEM_UDIMM_1D, + .cmdline_name = "ddr-immem-udimm-1d" + }, + { + .name = "DDR UDIMM PHY IMEM 2d FW", + .uuid = UUID_DDR_IMEM_UDIMM_2D, + .cmdline_name = "ddr-immem-udimm-2d" + }, + { + .name = "DDR UDIMM PHY DMEM 1d FW", + .uuid = UUID_DDR_DMEM_UDIMM_1D, + .cmdline_name = "ddr-dmmem-udimm-1d" + }, + { + .name = "DDR UDIMM PHY DMEM 2d FW", + .uuid = UUID_DDR_DMEM_UDIMM_2D, + .cmdline_name = "ddr-dmmem-udimm-2d" + }, + { + .name = "DDR RDIMM PHY IMEM 1d FW", + .uuid = UUID_DDR_IMEM_RDIMM_1D, + .cmdline_name = "ddr-immem-rdimm-1d" + }, + { + .name = "DDR RDIMM PHY IMEM 2d FW", + .uuid = UUID_DDR_IMEM_RDIMM_2D, + .cmdline_name = "ddr-immem-rdimm-2d" + }, + { + .name = "DDR RDIMM PHY DMEM 1d FW", + .uuid = UUID_DDR_DMEM_RDIMM_1D, + .cmdline_name = "ddr-dmmem-rdimm-1d" + }, + { + .name = "DDR RDIMM PHY DMEM 2d FW", + .uuid = UUID_DDR_DMEM_RDIMM_2D, + .cmdline_name = "ddr-dmmem-rdimm-2d" + }, + { + .name = "FUSE PROV FW", + .uuid = UUID_FUSE_PROV, + .cmdline_name = "fuse-prov" + }, + { + .name = "FUSE UPGRADE FW", + .uuid = UUID_FUSE_UP, + .cmdline_name = "fuse-upgrade" + }, + + /* Key Certificates */ + { + .name = "DDR Firmware key certificate", + .uuid = UUID_DDR_FW_KEY_CERT, + .cmdline_name = "ddr-fw-key-cert" + }, + + /* Content certificates */ + { + .name = "DDR UDIMM Firmware content certificate", + .uuid = UUID_DDR_UDIMM_FW_CONTENT_CERT, + .cmdline_name = "ddr-udimm-fw-cert" + }, + { + .name = "DDR RDIMM Firmware content certificate", + .uuid = UUID_DDR_RDIMM_FW_CONTENT_CERT, + .cmdline_name = "ddr-rdimm-fw-cert" + }, + + { + .name = NULL, + .uuid = { {0} }, + .cmdline_name = NULL, + } +}; diff --git a/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk new file mode 100644 index 0000000..ca2962a --- /dev/null +++ b/arm-trusted-firmware/tools/nxp/plat_fiptool/plat_fiptool.mk @@ -0,0 +1,33 @@ +# +# Copyright (c) 2021, NXP. 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_CONFIG_FILE_NAME := plat_def_uuid_config + +PLAT_DEF_UUID_CONFIG_FILE_PATH := ../nxp/plat_fiptool + +PLAT_DEF_OID := yes +PLAT_DEF_UUID := yes +PLAT_DEF_UUID_OID_CONFIG_PATH := ../../plat/nxp/common/fip_handler/common + + +INCLUDE_PATHS += -I${PLAT_DEF_UUID_OID_CONFIG_PATH} \ + -I./ +# Clean the stale object file. +$(shell rm ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o) + +ifeq (${PLAT_DEF_OID},yes) +HOSTCCFLAGS += -DPLAT_DEF_OID +endif + +ifeq (${PLAT_DEF_UUID},yes) +HOSTCCFLAGS += -DPLAT_DEF_FIP_UUID +PLAT_OBJECTS += ${PLAT_DEF_UUID_CONFIG_FILE_PATH}/${PLAT_DEF_UUID_CONFIG_FILE_NAME}.o +endif + +OBJECTS += ${PLAT_OBJECTS} diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile b/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile new file mode 100644 index 0000000..d585754 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile @@ -0,0 +1,121 @@ +# +# Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################### +# makefile +################################################### + +#output file name +FILE_NAME_SA0 = bootparam_sa0 +FILE_NAME_SA6 = cert_header_sa6 + +OUTPUT_FILE_SA0 = $(FILE_NAME_SA0).elf +OUTPUT_FILE_SA6 = $(FILE_NAME_SA6).elf + +#object file name +OBJ_FILE_SA0 = sa0.o +OBJ_FILE_SA6 = sa6.o + +#linker script name +MEMORY_DEF_SA0 = sa0.ld.S +MEMORY_DEF_SA6 = sa6.ld.S + +################################################### +# Convenience function for adding build definitions +# $(eval $(call add_define,FOO)) will have: +# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise +define add_define +DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),) +endef + +# Process RCAR_SA0_SIZE flag +ifndef RCAR_SA0_SIZE +RCAR_SA0_SIZE := 1 +else +ifeq (${RCAR_SA0_SIZE},0) +RCAR_SA0_SIZE := 0 +else +RCAR_SA0_SIZE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA0_SIZE)) + +# Process RCAR_SA6_TYPE flag +ifndef RCAR_SA6_TYPE +RCAR_SA6_TYPE := 0 +else +ifeq (${RCAR_SA6_TYPE},0) +RCAR_SA6_TYPE := 0 +else +RCAR_SA6_TYPE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA6_TYPE)) + +# Handle different VMA adjustment on D3 +ifeq (${RCAR_LSI},${RCAR_D3}) +RCAR_VMA_ADJUST_ADDR := 0xE6320000 +else +RCAR_VMA_ADJUST_ADDR := 0xE6312000 +endif +$(eval $(call add_define,RCAR_VMA_ADJUST_ADDR)) + + +################################################### + +#c compiler +CC = $(CROSS_COMPILE)gcc +CFLAGS += ${DEFINES} +CFLAGS += -I../../include/lib/stdlib + +#Linker +LD = $(CROSS_COMPILE)ld + +#objcopy +objcopy = $(CROSS_COMPILE)objcopy + +#clean +CL = rm -f + +################################################### +.SUFFIXES : .s .c .o + +################################################### +# command + +.PHONY: all +all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6) +################################################### +# Linker +################################################### +$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) + $(LD) $(OBJ_FILE_SA0) \ + -T $(MEMORY_DEF_SA0) \ + -o $(OUTPUT_FILE_SA0) \ + -Map $(FILE_NAME_SA0).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin + +$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) + $(LD) $(OBJ_FILE_SA6) \ + -T $(MEMORY_DEF_SA6) \ + -o $(OUTPUT_FILE_SA6) \ + -Map $(FILE_NAME_SA6).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin + +################################################### +# Compile +################################################### + +%.o:../%.c + $(CC) -c -I $< -o $@ + +.PHONY: clean +clean: + $(CL) *.bin *.map *.srec *.elf *.o diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c new file mode 100644 index 0000000..79354ec --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2015-2018, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_SA0_SIZE_SMALL (0) /* for E3/D3 */ +#define RCAR_SA0_SIZE_NORMAL (1) /* for H3/M3/M3N */ + +#define BL2_ADDRESS (0xE6304000) /* BL2 start address */ + +#if (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) +#define BL2_SIZE (80*1024/4) /* BL2 size is 80KB(0x00005000) */ +#else /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ +#define BL2_SIZE (170*1024/4) /* BL2 size is 170KB(0x0000AA00) */ +#endif /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ + +/* SA0 */ +/* 0x00000000 */ +const unsigned int __attribute__ ((section (".sa0_bootrom"))) bootrom_paramA = 0x00000100; +/* 0x00000080 (Map Type 3 for eMMC Boot)*/ +/* 0x000001D4 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_addr3"))) bl2dst_addr3 = BL2_ADDRESS; +/* 0x000002E4 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_size3"))) bl2dst_size3 = BL2_SIZE; +/* 0x00000C00 (Map Type 1 for HyperFlash/QSPI Flash Boot)*/ +/* 0x00000D54 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_addr1"))) bl2dst_addr1 = BL2_ADDRESS; +/* 0x00000E64 */ +const unsigned int __attribute__ ((section (".sa0_bl2dst_size1"))) bl2dst_size1 = BL2_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S new file mode 100644 index 0000000..98fee23 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa0_bootrom)) + /* Map Type 3 for eMMC Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x000001D4; /* H'00000080 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr3)) + /* A-side IPL content cert "Size" */ + . = 0x000002E4; /* H'00000080 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size3)) + /* Map Type 1 for HyperFlash/QSPI Flash Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x00000D54; /* H'00000C00 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr1)) + /* A-side IPL content cert "Size" */ + . = 0x00000E64; /* H'00000C00 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size1)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c new file mode 100644 index 0000000..8fafdad --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c @@ -0,0 +1,185 @@ +/* + * Copyright (c) 2015-2021, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define RCAR_SA6_TYPE_HYPERFLASH (0) +#define RCAR_SA6_TYPE_EMMC (1) + +#if (RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH) + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on flash for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x001C0000U) +/* Reserved */ +#define RCAR_BL31_PARTITION (0x00000000U) +/* Source address on flash for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Reserved */ +#define RCAR_BL32_PARTITION (0x00000000U) +/* Source address on flash for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00640000U) +/* Reserved */ +#define RCAR_BL33_PARTITION (0x00000000U) +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL332_PARTITION (0x00000000U) +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL333_PARTITION (0x00000000U) +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL334_PARTITION (0x00000000U) +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL335_PARTITION (0x00000000U) +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL336_PARTITION (0x00000000U) +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL337_PARTITION (0x00000000U) +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL338_PARTITION (0x00000000U) + +#else /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH */ + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on eMMC for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x00040000U) +/* Source partition on eMMC for BL31 */ +#define RCAR_BL31_PARTITION (0x00000001U) +/* Source address on eMMC for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Source partition on eMMC for BL32 */ +#define RCAR_BL32_PARTITION (0x00000001U) +/* Source address on eMMC for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00000000U) +/* Source partition on eMMC for BL33 */ +#define RCAR_BL33_PARTITION (0x00000002U) +/* Reserved */ +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +#define RCAR_BL332_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +#define RCAR_BL333_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +#define RCAR_BL334_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +#define RCAR_BL335_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +#define RCAR_BL336_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +#define RCAR_BL337_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +#define RCAR_BL338_PARTITION (0x00000000U) + +#endif /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_HYPERFLASH */ + +/* Destination address for BL31 */ +#define RCAR_BL31DST_ADDRESS (0x44000000U) +#define RCAR_BL31DST_ADDRESSH (0x00000000U) +/* Destination size for BL31 */ +#define RCAR_BL31DST_SIZE (0x00004000U) +/* Destination address for BL32 */ +#define RCAR_BL32DST_ADDRESS (0x44100000U) +#define RCAR_BL32DST_ADDRESSH (0x00000000U) +/* Destination size for BL32 */ +#define RCAR_BL32DST_SIZE (0x00080000U) +/* Destination address for BL33 */ +#define RCAR_BL33DST_ADDRESS (0x50000000U) +#define RCAR_BL33DST_ADDRESSH (0x00000000U) +/* Destination size for BL33 */ +#define RCAR_BL33DST_SIZE (0x00040000U) +/* Reserved */ +#define RCAR_BL332DST_ADDRESS (0x00000000U) +#define RCAR_BL332DST_ADDRESSH (0x00000000U) +#define RCAR_BL332DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL333DST_ADDRESS (0x00000000U) +#define RCAR_BL333DST_ADDRESSH (0x00000000U) +#define RCAR_BL333DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL334DST_ADDRESS (0x00000000U) +#define RCAR_BL334DST_ADDRESSH (0x00000000U) +#define RCAR_BL334DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL335DST_ADDRESS (0x00000000U) +#define RCAR_BL335DST_ADDRESSH (0x00000000U) +#define RCAR_BL335DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL336DST_ADDRESS (0x00000000U) +#define RCAR_BL336DST_ADDRESSH (0x00000000U) +#define RCAR_BL336DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL337DST_ADDRESS (0x00000000U) +#define RCAR_BL337DST_ADDRESSH (0x00000000U) +#define RCAR_BL337DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL338DST_ADDRESS (0x00000000U) +#define RCAR_BL338DST_ADDRESSH (0x00000000U) +#define RCAR_BL338DST_SIZE (0x00000000U) + +/* SA6 */ +const uint64_t __attribute__ ((section (".sa6_image_num"))) image_num = RCAR_IMAGE_NUM; +const uint64_t __attribute__ ((section (".sa6_bl31src_addr"))) bl31src_addr = RCAR_BL31SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl31partition"))) bl31partition = RCAR_BL31_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl32src_addr"))) bl32src_addr = RCAR_BL32SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl32partition"))) bl32partition = RCAR_BL32_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl33src_addr"))) bl33src_addr = RCAR_BL33SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl33partition"))) bl33partition = RCAR_BL33_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl332src_addr"))) bl332src_addr = RCAR_BL332SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl332partition")))bl332partition = RCAR_BL332_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl333src_addr"))) bl333src_addr = RCAR_BL333SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl333partition")))bl333partition = RCAR_BL333_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl334src_addr"))) bl334src_addr = RCAR_BL334SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl334partition")))bl334partition = RCAR_BL334_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl335src_addr"))) bl335src_addr = RCAR_BL335SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl335partition")))bl335partition = RCAR_BL335_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl336src_addr"))) bl336src_addr = RCAR_BL336SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl336partition")))bl336partition = RCAR_BL336_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl337src_addr"))) bl337src_addr = RCAR_BL337SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl337partition")))bl337partition = RCAR_BL337_PARTITION; +const uint64_t __attribute__ ((section (".sa6_bl338src_addr"))) bl338src_addr = RCAR_BL338SRC_ADDRESS; +const uint64_t __attribute__ ((section (".sa6_bl338partition")))bl338partition = RCAR_BL338_PARTITION; +const uint32_t __attribute__ ((section (".sa6_bl31dst_addr"))) bl31dst_addr = RCAR_BL31DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl31dst_addrh"))) bl31dst_addrh = RCAR_BL31DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl31dst_size"))) bl31dst_size = RCAR_BL31DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl32dst_addr"))) bl32dst_addr = RCAR_BL32DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl32dst_addrh"))) bl32dst_addrh = RCAR_BL32DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl32dst_size"))) bl32dst_size = RCAR_BL32DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl33dst_addr"))) bl33dst_addr = RCAR_BL33DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl33dst_addrh"))) bl33dst_addrh = RCAR_BL33DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl33dst_size"))) bl33dst_size = RCAR_BL33DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl332dst_addr"))) bl332dst_addr = RCAR_BL332DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl332dst_addrh")))bl332dst_addrh = RCAR_BL332DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl332dst_size"))) bl332dst_size = RCAR_BL332DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl333dst_addr"))) bl333dst_addr = RCAR_BL333DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl333dst_addrh")))bl333dst_addrh = RCAR_BL333DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl333dst_size"))) bl333dst_size = RCAR_BL333DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl334dst_addr"))) bl334dst_addr = RCAR_BL334DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl334dst_addrh")))bl334dst_addrh = RCAR_BL334DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl334dst_size"))) bl334dst_size = RCAR_BL334DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl335dst_addr"))) bl335dst_addr = RCAR_BL335DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl335dst_addrh")))bl335dst_addrh = RCAR_BL335DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl335dst_size"))) bl335dst_size = RCAR_BL335DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl336dst_addr"))) bl336dst_addr = RCAR_BL336DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl336dst_addrh")))bl336dst_addrh = RCAR_BL336DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl336dst_size"))) bl336dst_size = RCAR_BL336DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl337dst_addr"))) bl337dst_addr = RCAR_BL337DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl337dst_addrh")))bl337dst_addrh = RCAR_BL337DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl337dst_size"))) bl337dst_size = RCAR_BL337DST_SIZE; +const uint32_t __attribute__ ((section (".sa6_bl338dst_addr"))) bl338dst_addr = RCAR_BL338DST_ADDRESS; +const uint32_t __attribute__ ((section (".sa6_bl338dst_addrh")))bl338dst_addrh = RCAR_BL338DST_ADDRESSH; +const uint32_t __attribute__ ((section (".sa6_bl338dst_size"))) bl338dst_size = RCAR_BL338DST_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S new file mode 100644 index 0000000..9ca0c1d --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2015-2017, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa6_image_num)) + . = 0x00000008; + KEEP(*(.sa6_bl31src_addr)) + . = 0x00000010; + KEEP(*(.sa6_bl31partition)) + . = 0x00000018; + KEEP(*(.sa6_bl32src_addr)) + . = 0x00000020; + KEEP(*(.sa6_bl32partition)) + . = 0x00000028; + KEEP(*(.sa6_bl33src_addr)) + . = 0x00000030; + KEEP(*(.sa6_bl33partition)) + . = 0x00000038; + KEEP(*(.sa6_bl332src_addr)) + . = 0x00000040; + KEEP(*(.sa6_bl332partition)) + . = 0x00000048; + KEEP(*(.sa6_bl333src_addr)) + . = 0x00000050; + KEEP(*(.sa6_bl333partition)) + . = 0x00000058; + KEEP(*(.sa6_bl334src_addr)) + . = 0x00000060; + KEEP(*(.sa6_bl334partition)) + . = 0x00000068; + KEEP(*(.sa6_bl335src_addr)) + . = 0x00000070; + KEEP(*(.sa6_bl335partition)) + . = 0x00000078; + KEEP(*(.sa6_bl336src_addr)) + . = 0x00000080; + KEEP(*(.sa6_bl336partition)) + . = 0x00000088; + KEEP(*(.sa6_bl337src_addr)) + . = 0x00000090; + KEEP(*(.sa6_bl337partition)) + . = 0x00000098; + KEEP(*(.sa6_bl338src_addr)) + . = 0x000000A0; + KEEP(*(.sa6_bl338partition)) + . = 0x00000554; + KEEP(*(.sa6_bl31dst_addr)) + . = 0x00000558; + KEEP(*(.sa6_bl31dst_addrh)) + . = 0x00000664; + KEEP(*(.sa6_bl31dst_size)) + . = 0x00000D54; + KEEP(*(.sa6_bl32dst_addr)) + . = 0x00000D58; + KEEP(*(.sa6_bl32dst_addrh)) + . = 0x00000E64; + KEEP(*(.sa6_bl32dst_size)) + . = 0x00001554; + KEEP(*(.sa6_bl33dst_addr)) + . = 0x00001558; + KEEP(*(.sa6_bl33dst_addrh)) + . = 0x00001664; + KEEP(*(.sa6_bl33dst_size)) + . = 0x00001D54; + KEEP(*(.sa6_bl332dst_addr)) + . = 0x00001D58; + KEEP(*(.sa6_bl332dst_addrh)) + . = 0x00001E64; + KEEP(*(.sa6_bl332dst_size)) + . = 0x00002554; + KEEP(*(.sa6_bl333dst_addr)) + . = 0x00002558; + KEEP(*(.sa6_bl333dst_addrh)) + . = 0x00002664; + KEEP(*(.sa6_bl333dst_size)) + . = 0x00002D54; + KEEP(*(.sa6_bl334dst_addr)) + . = 0x00002D58; + KEEP(*(.sa6_bl334dst_addrh)) + . = 0x00002E64; + KEEP(*(.sa6_bl334dst_size)) + . = 0x00003554; + KEEP(*(.sa6_bl335dst_addr)) + . = 0x00003558; + KEEP(*(.sa6_bl335dst_addrh)) + . = 0x00003664; + KEEP(*(.sa6_bl335dst_size)) + . = 0x00003D54; + KEEP(*(.sa6_bl336dst_addr)) + . = 0x00003D58; + KEEP(*(.sa6_bl336dst_addrh)) + . = 0x00003E64; + KEEP(*(.sa6_bl336dst_size)) + . = 0x00004554; + KEEP(*(.sa6_bl337dst_addr)) + . = 0x00004558; + KEEP(*(.sa6_bl337dst_addrh)) + . = 0x00004664; + KEEP(*(.sa6_bl337dst_size)) + . = 0x00004D54; + KEEP(*(.sa6_bl338dst_addr)) + . = 0x00004D58; + KEEP(*(.sa6_bl338dst_addrh)) + . = 0x00004E64; + KEEP(*(.sa6_bl338dst_size)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile b/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile new file mode 100644 index 0000000..2d438b9 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile @@ -0,0 +1,118 @@ +# +# Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +################################################### +# makefile +################################################### + +#output file name +FILE_NAME_SA0 = bootparam_sa0 +FILE_NAME_SA6 = cert_header_sa6 + +OUTPUT_FILE_SA0 = $(FILE_NAME_SA0).elf +OUTPUT_FILE_SA6 = $(FILE_NAME_SA6).elf + +#object file name +OBJ_FILE_SA0 = sa0.o +OBJ_FILE_SA6 = sa6.o + +#linker script name +MEMORY_DEF_SA0 = sa0.ld.S +MEMORY_DEF_SA6 = sa6.ld.S + +################################################### +# Convenience function for adding build definitions +# $(eval $(call add_define,FOO)) will have: +# -DFOO if $(FOO) is empty; -DFOO=$(FOO) otherwise +define add_define +DEFINES += -D$(1)$(if $(value $(1)),=$(value $(1)),) +endef + +# Process RCAR_SA0_SIZE flag +ifndef RCAR_SA0_SIZE +RCAR_SA0_SIZE := 1 +else +ifeq (${RCAR_SA0_SIZE},0) +RCAR_SA0_SIZE := 0 +else +RCAR_SA0_SIZE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA0_SIZE)) + +# Process RCAR_SA6_TYPE flag +ifndef RCAR_SA6_TYPE +RCAR_SA6_TYPE := 0 +else +ifeq (${RCAR_SA6_TYPE},0) +RCAR_SA6_TYPE := 0 +else +RCAR_SA6_TYPE := 1 +endif +endif +$(eval $(call add_define,RCAR_SA6_TYPE)) + +RCAR_VMA_ADJUST_ADDR := 0xE6320000 +$(eval $(call add_define,RCAR_VMA_ADJUST_ADDR)) + + +################################################### + +#c compiler +CC = $(CROSS_COMPILE)gcc +CFLAGS += ${DEFINES} +CFLAGS += -nostdinc \ + -I../../../include/lib/libc \ + -I../../../include/lib/libc/aarch64 + +#Linker +LD = $(CROSS_COMPILE)ld + +#objcopy +objcopy = $(CROSS_COMPILE)objcopy + +#clean +CL = rm -f + +################################################### +.SUFFIXES : .s .c .o + +################################################### +# command + +.PHONY: all +all: $(OUTPUT_FILE_SA0) $(OUTPUT_FILE_SA6) +################################################### +# Linker +################################################### +$(OUTPUT_FILE_SA0) : $(MEMORY_DEF_SA0) $(OBJ_FILE_SA0) + $(LD) $(OBJ_FILE_SA0) \ + -T $(MEMORY_DEF_SA0) \ + -o $(OUTPUT_FILE_SA0) \ + -Map $(FILE_NAME_SA0).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA0) $(FILE_NAME_SA0).bin + +$(OUTPUT_FILE_SA6) : $(MEMORY_DEF_SA6) $(OBJ_FILE_SA6) + $(LD) $(OBJ_FILE_SA6) \ + -T $(MEMORY_DEF_SA6) \ + -o $(OUTPUT_FILE_SA6) \ + -Map $(FILE_NAME_SA6).map \ + + $(objcopy) -O srec --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).srec + $(objcopy) -O binary --adjust-vma=$(RCAR_VMA_ADJUST_ADDR) --srec-forceS3 $(OUTPUT_FILE_SA6) $(FILE_NAME_SA6).bin + +################################################### +# Compile +################################################### + +%.o:../%.c + $(CC) -c -I $< -o $@ + +.PHONY: clean +clean: + $(CL) *.bin *.map *.srec *.elf *.o diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c new file mode 100644 index 0000000..763d3a5 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c @@ -0,0 +1,30 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#define RCAR_SA0_SIZE_SMALL (0) /* for RZ/G2E */ +#define RCAR_SA0_SIZE_NORMAL (1) /* for RZ/G2[HMN] */ + +#define BL2_ADDRESS (0xE6304000) /* BL2 start address */ + +#if (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) +#define BL2_SIZE (80*1024/4) /* BL2 size is 80KB(0x00005000) */ +#else /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ +#define BL2_SIZE (170*1024/4) /* BL2 size is 170KB(0x0000AA00) */ +#endif /* (RCAR_SA0_SIZE == RCAR_SA0_SIZE_SMALL) */ + +/* SA0 */ +/* 0x00000000 */ +const unsigned int __attribute__ ((section(".sa0_bootrom"))) bootrom_paramA = 0x00000100; +/* 0x00000080 (Map Type 3 for eMMC Boot)*/ +/* 0x000001D4 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_addr3"))) bl2dst_addr3 = BL2_ADDRESS; +/* 0x000002E4 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_size3"))) bl2dst_size3 = BL2_SIZE; +/* 0x00000C00 (Map Type 1 for HyperFlash/QSPI Flash Boot)*/ +/* 0x00000D54 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_addr1"))) bl2dst_addr1 = BL2_ADDRESS; +/* 0x00000E64 */ +const unsigned int __attribute__ ((section(".sa0_bl2dst_size1"))) bl2dst_size1 = BL2_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S new file mode 100644 index 0000000..23e2b23 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa0_bootrom)) + /* Map Type 3 for eMMC Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x000001D4; /* H'00000080 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr3)) + /* A-side IPL content cert "Size" */ + . = 0x000002E4; /* H'00000080 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size3)) + /* Map Type 1 for HyperFlash/QSPI Flash Boot */ + /* A-side IPL content cert "Start Address" */ + . = 0x00000D54; /* H'00000C00 + H'00000154 */ + KEEP(*(.sa0_bl2dst_addr1)) + /* A-side IPL content cert "Size" */ + . = 0x00000E64; /* H'00000C00 + H'00000264 */ + KEEP(*(.sa0_bl2dst_size1)) + } + +} diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c new file mode 100644 index 0000000..76e3dc5 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c @@ -0,0 +1,236 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include + +#define RCAR_SA6_TYPE_QSPIFLASH (0) +#define RCAR_SA6_TYPE_EMMC (1) + +#if (RCAR_SA6_TYPE == RCAR_SA6_TYPE_QSPIFLASH) + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on flash for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x001C0000U) +/* Reserved */ +#define RCAR_BL31_PARTITION (0x00000000U) +/* Source address on flash for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Reserved */ +#define RCAR_BL32_PARTITION (0x00000000U) +/* Source address on flash for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00300000U) +/* Reserved */ +#define RCAR_BL33_PARTITION (0x00000000U) +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL332_PARTITION (0x00000000U) +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL333_PARTITION (0x00000000U) +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL334_PARTITION (0x00000000U) +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL335_PARTITION (0x00000000U) +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL336_PARTITION (0x00000000U) +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL337_PARTITION (0x00000000U) +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +/* Reserved */ +#define RCAR_BL338_PARTITION (0x00000000U) + +#else /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_EMMC */ + +/* Number of content cert for Non-secure Target Program(BL33x) */ +#define RCAR_IMAGE_NUM (0x00000001U) +/* Source address on eMMC for BL31 */ +#define RCAR_BL31SRC_ADDRESS (0x00040000U) +/* Source partition on eMMC for BL31 */ +#define RCAR_BL31_PARTITION (0x00000001U) +/* Source address on eMMC for BL32 */ +#define RCAR_BL32SRC_ADDRESS (0x00200000U) +/* Source partition on eMMC for BL32 */ +#define RCAR_BL32_PARTITION (0x00000001U) +/* Source address on eMMC for BL33 */ +#define RCAR_BL33SRC_ADDRESS (0x00000000U) +/* Source partition on eMMC for BL33 */ +#define RCAR_BL33_PARTITION (0x00000002U) +/* Reserved */ +#define RCAR_BL332SRC_ADDRESS (0x00000000U) +#define RCAR_BL332_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL333SRC_ADDRESS (0x00000000U) +#define RCAR_BL333_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL334SRC_ADDRESS (0x00000000U) +#define RCAR_BL334_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL335SRC_ADDRESS (0x00000000U) +#define RCAR_BL335_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL336SRC_ADDRESS (0x00000000U) +#define RCAR_BL336_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL337SRC_ADDRESS (0x00000000U) +#define RCAR_BL337_PARTITION (0x00000000U) +/* Reserved */ +#define RCAR_BL338SRC_ADDRESS (0x00000000U) +#define RCAR_BL338_PARTITION (0x00000000U) + +#endif /* RCAR_SA6_TYPE == RCAR_SA6_TYPE_QSPIFLASH */ + +/* Destination address for BL31 */ +#define RCAR_BL31DST_ADDRESS (0x44000000U) +#define RCAR_BL31DST_ADDRESSH (0x00000000U) +/* Destination size for BL31 */ +#define RCAR_BL31DST_SIZE (0x00004000U) +/* Destination address for BL32 */ +#define RCAR_BL32DST_ADDRESS (0x44100000U) +#define RCAR_BL32DST_ADDRESSH (0x00000000U) +/* Destination size for BL32 */ +#define RCAR_BL32DST_SIZE (0x00040000U) +/* Destination address for BL33 */ +#define RCAR_BL33DST_ADDRESS (0x50000000U) +#define RCAR_BL33DST_ADDRESSH (0x00000000U) +/* Destination size for BL33 */ +#define RCAR_BL33DST_SIZE (0x00040000U) +/* Reserved */ +#define RCAR_BL332DST_ADDRESS (0x00000000U) +#define RCAR_BL332DST_ADDRESSH (0x00000000U) +#define RCAR_BL332DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL333DST_ADDRESS (0x00000000U) +#define RCAR_BL333DST_ADDRESSH (0x00000000U) +#define RCAR_BL333DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL334DST_ADDRESS (0x00000000U) +#define RCAR_BL334DST_ADDRESSH (0x00000000U) +#define RCAR_BL334DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL335DST_ADDRESS (0x00000000U) +#define RCAR_BL335DST_ADDRESSH (0x00000000U) +#define RCAR_BL335DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL336DST_ADDRESS (0x00000000U) +#define RCAR_BL336DST_ADDRESSH (0x00000000U) +#define RCAR_BL336DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL337DST_ADDRESS (0x00000000U) +#define RCAR_BL337DST_ADDRESSH (0x00000000U) +#define RCAR_BL337DST_SIZE (0x00000000U) +/* Reserved */ +#define RCAR_BL338DST_ADDRESS (0x00000000U) +#define RCAR_BL338DST_ADDRESSH (0x00000000U) +#define RCAR_BL338DST_SIZE (0x00000000U) + +/* SA6 */ +const uint64_t __attribute__ ((section(".sa6_image_num"))) + image_num = RCAR_IMAGE_NUM; +const uint64_t __attribute__ ((section(".sa6_bl31src_addr"))) + bl31src_addr = RCAR_BL31SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl31partition"))) + bl31partition = RCAR_BL31_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl32src_addr"))) + bl32src_addr = RCAR_BL32SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl32partition"))) + bl32partition = RCAR_BL32_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl33src_addr"))) + bl33src_addr = RCAR_BL33SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl33partition"))) + bl33partition = RCAR_BL33_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl332src_addr"))) + bl332src_addr = RCAR_BL332SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl332partition"))) + bl332partition = RCAR_BL332_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl333src_addr"))) + bl333src_addr = RCAR_BL333SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl333partition"))) + bl333partition = RCAR_BL333_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl334src_addr"))) + bl334src_addr = RCAR_BL334SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl334partition"))) + bl334partition = RCAR_BL334_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl335src_addr"))) + bl335src_addr = RCAR_BL335SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl335partition"))) + bl335partition = RCAR_BL335_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl336src_addr"))) + bl336src_addr = RCAR_BL336SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl336partition"))) + bl336partition = RCAR_BL336_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl337src_addr"))) + bl337src_addr = RCAR_BL337SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl337partition"))) + bl337partition = RCAR_BL337_PARTITION; +const uint64_t __attribute__ ((section(".sa6_bl338src_addr"))) + bl338src_addr = RCAR_BL338SRC_ADDRESS; +const uint64_t __attribute__ ((section(".sa6_bl338partition"))) + bl338partition = RCAR_BL338_PARTITION; +const uint32_t __attribute__ ((section(".sa6_bl31dst_addr"))) + bl31dst_addr = RCAR_BL31DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl31dst_addrh"))) + bl31dst_addrh = RCAR_BL31DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl31dst_size"))) + bl31dst_size = RCAR_BL31DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl32dst_addr"))) + bl32dst_addr = RCAR_BL32DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl32dst_addrh"))) + bl32dst_addrh = RCAR_BL32DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl32dst_size"))) + bl32dst_size = RCAR_BL32DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl33dst_addr"))) + bl33dst_addr = RCAR_BL33DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl33dst_addrh"))) + bl33dst_addrh = RCAR_BL33DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl33dst_size"))) + bl33dst_size = RCAR_BL33DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl332dst_addr"))) + bl332dst_addr = RCAR_BL332DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl332dst_addrh"))) + bl332dst_addrh = RCAR_BL332DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl332dst_size"))) + bl332dst_size = RCAR_BL332DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl333dst_addr"))) + bl333dst_addr = RCAR_BL333DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl333dst_addrh"))) + bl333dst_addrh = RCAR_BL333DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl333dst_size"))) + bl333dst_size = RCAR_BL333DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl334dst_addr"))) + bl334dst_addr = RCAR_BL334DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl334dst_addrh"))) + bl334dst_addrh = RCAR_BL334DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl334dst_size"))) + bl334dst_size = RCAR_BL334DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl335dst_addr"))) + bl335dst_addr = RCAR_BL335DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl335dst_addrh"))) + bl335dst_addrh = RCAR_BL335DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl335dst_size"))) + bl335dst_size = RCAR_BL335DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl336dst_addr"))) + bl336dst_addr = RCAR_BL336DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl336dst_addrh"))) + bl336dst_addrh = RCAR_BL336DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl336dst_size"))) + bl336dst_size = RCAR_BL336DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl337dst_addr"))) + bl337dst_addr = RCAR_BL337DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl337dst_addrh"))) + bl337dst_addrh = RCAR_BL337DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl337dst_size"))) + bl337dst_size = RCAR_BL337DST_SIZE; +const uint32_t __attribute__ ((section(".sa6_bl338dst_addr"))) + bl338dst_addr = RCAR_BL338DST_ADDRESS; +const uint32_t __attribute__ ((section(".sa6_bl338dst_addrh"))) + bl338dst_addrh = RCAR_BL338DST_ADDRESSH; +const uint32_t __attribute__ ((section(".sa6_bl338dst_size"))) + bl338dst_size = RCAR_BL338DST_SIZE; diff --git a/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S new file mode 100644 index 0000000..efe40b0 --- /dev/null +++ b/arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S @@ -0,0 +1,114 @@ +/* + * Copyright (c) 2020, Renesas Electronics Corporation. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +SECTIONS +{ + . = 0x00000000; + .rodata : { + KEEP(*(.sa6_image_num)) + . = 0x00000008; + KEEP(*(.sa6_bl31src_addr)) + . = 0x00000010; + KEEP(*(.sa6_bl31partition)) + . = 0x00000018; + KEEP(*(.sa6_bl32src_addr)) + . = 0x00000020; + KEEP(*(.sa6_bl32partition)) + . = 0x00000028; + KEEP(*(.sa6_bl33src_addr)) + . = 0x00000030; + KEEP(*(.sa6_bl33partition)) + . = 0x00000038; + KEEP(*(.sa6_bl332src_addr)) + . = 0x00000040; + KEEP(*(.sa6_bl332partition)) + . = 0x00000048; + KEEP(*(.sa6_bl333src_addr)) + . = 0x00000050; + KEEP(*(.sa6_bl333partition)) + . = 0x00000058; + KEEP(*(.sa6_bl334src_addr)) + . = 0x00000060; + KEEP(*(.sa6_bl334partition)) + . = 0x00000068; + KEEP(*(.sa6_bl335src_addr)) + . = 0x00000070; + KEEP(*(.sa6_bl335partition)) + . = 0x00000078; + KEEP(*(.sa6_bl336src_addr)) + . = 0x00000080; + KEEP(*(.sa6_bl336partition)) + . = 0x00000088; + KEEP(*(.sa6_bl337src_addr)) + . = 0x00000090; + KEEP(*(.sa6_bl337partition)) + . = 0x00000098; + KEEP(*(.sa6_bl338src_addr)) + . = 0x000000A0; + KEEP(*(.sa6_bl338partition)) + . = 0x00000554; + KEEP(*(.sa6_bl31dst_addr)) + . = 0x00000558; + KEEP(*(.sa6_bl31dst_addrh)) + . = 0x00000664; + KEEP(*(.sa6_bl31dst_size)) + . = 0x00000D54; + KEEP(*(.sa6_bl32dst_addr)) + . = 0x00000D58; + KEEP(*(.sa6_bl32dst_addrh)) + . = 0x00000E64; + KEEP(*(.sa6_bl32dst_size)) + . = 0x00001554; + KEEP(*(.sa6_bl33dst_addr)) + . = 0x00001558; + KEEP(*(.sa6_bl33dst_addrh)) + . = 0x00001664; + KEEP(*(.sa6_bl33dst_size)) + . = 0x00001D54; + KEEP(*(.sa6_bl332dst_addr)) + . = 0x00001D58; + KEEP(*(.sa6_bl332dst_addrh)) + . = 0x00001E64; + KEEP(*(.sa6_bl332dst_size)) + . = 0x00002554; + KEEP(*(.sa6_bl333dst_addr)) + . = 0x00002558; + KEEP(*(.sa6_bl333dst_addrh)) + . = 0x00002664; + KEEP(*(.sa6_bl333dst_size)) + . = 0x00002D54; + KEEP(*(.sa6_bl334dst_addr)) + . = 0x00002D58; + KEEP(*(.sa6_bl334dst_addrh)) + . = 0x00002E64; + KEEP(*(.sa6_bl334dst_size)) + . = 0x00003554; + KEEP(*(.sa6_bl335dst_addr)) + . = 0x00003558; + KEEP(*(.sa6_bl335dst_addrh)) + . = 0x00003664; + KEEP(*(.sa6_bl335dst_size)) + . = 0x00003D54; + KEEP(*(.sa6_bl336dst_addr)) + . = 0x00003D58; + KEEP(*(.sa6_bl336dst_addrh)) + . = 0x00003E64; + KEEP(*(.sa6_bl336dst_size)) + . = 0x00004554; + KEEP(*(.sa6_bl337dst_addr)) + . = 0x00004558; + KEEP(*(.sa6_bl337dst_addrh)) + . = 0x00004664; + KEEP(*(.sa6_bl337dst_size)) + . = 0x00004D54; + KEEP(*(.sa6_bl338dst_addr)) + . = 0x00004D58; + KEEP(*(.sa6_bl338dst_addrh)) + . = 0x00004E64; + KEEP(*(.sa6_bl338dst_size)) + } + +} diff --git a/arm-trusted-firmware/tools/sptool/Makefile b/arm-trusted-firmware/tools/sptool/Makefile new file mode 100644 index 0000000..ae42f32 --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/Makefile @@ -0,0 +1,60 @@ +# +# Copyright (c) 2018-2020, Arm Limited. All rights reserved. +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +SPTOOL ?= sptool${BIN_EXT} +BUILD_DIR = $(dir $(SPTOOL))/ +SOURCES := $(wildcard *.c) +V ?= 0 + +override CPPFLAGS += -D_GNU_SOURCE -D_XOPEN_SOURCE=700 +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +INCLUDE_PATHS := -I../../include/tools_share + +HOSTCC ?= gcc + +.PHONY: all clean distclean + +all: ${SPTOOL} + +HOST_OBJS := + +define MAKE_HOST_OBJS +$(eval HOST_OBJ := $(1)/$(patsubst %.c,%.o,$(notdir $(2)))) + +$(HOST_OBJ): $(2) + @echo " HOSTCC $$<" + $${Q}$${HOSTCC} -c $${CPPFLAGS} ${HOSTCCFLAGS} $${INCLUDE_PATHS} $$< -o $$@ +HOST_OBJS += $(HOST_OBJ) +endef + +$(eval $(call MAKE_HOST_OBJS, $(BUILD_DIR), $(SOURCES))) + +${SPTOOL}: ${HOST_OBJS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${HOST_OBJS} -o $@ ${LDLIBS} + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +clean: + $(call SHELL_DELETE_ALL, ${HOST_OBJS} ${SPTOOL}) diff --git a/arm-trusted-firmware/tools/sptool/Makefile.tmk b/arm-trusted-firmware/tools/sptool/Makefile.tmk new file mode 100644 index 0000000..af164ea --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/Makefile.tmk @@ -0,0 +1,30 @@ +################################### tell Emacs this is a -*- makefile-gmake -*- +# +# Copyright (c) 2021, NVIDIA CORPORATION. All rights reserved. +# +# NVIDIA CORPORATION and its licensors retain all intellectual property +# and proprietary rights in and to this software, related documentation +# and any modifications thereto. Any use, reproduction, disclosure or +# distribution of this software and related documentation without an express +# license agreement from NVIDIA CORPORATION is strictly prohibited. +# +# tmake for component "sptool" +# +############################################################################### + +ifdef NV_COMPONENT_FLAG_STATIC_EXECUTABLE_SECTION +include $(NV_BUILD_START_COMPONENT) + +NV_COMPONENT_NAME := sptool +NV_COMPONENT_SOURCES := sptool.c + +NV_COMPONENT_INCLUDES := ../../include/tools_share + +include $(NV_BUILD_STATIC_EXECUTABLE) +endif + +# Local Variables: +# indent-tabs-mode: t +# tab-width: 8 +# End: +# vi: set tabstop=8 noexpandtab: diff --git a/arm-trusted-firmware/tools/sptool/sp_mk_generator.py b/arm-trusted-firmware/tools/sptool/sp_mk_generator.py new file mode 100755 index 0000000..82d5c1b --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/sp_mk_generator.py @@ -0,0 +1,157 @@ +#!/usr/bin/python3 +# Copyright (c) 2020-2022, Arm Limited. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause + +""" +This script is invoked by Make system and generates secure partition makefile. +It expects platform provided secure partition layout file which contains list +of Secure Partition Images and Partition manifests(PM). +Layout file can exist outside of TF-A tree and the paths of Image and PM files +must be relative to it. + +This script parses the layout file and generates a make file which updates +FDT_SOURCES, FIP_ARGS, CRT_ARGS and SPTOOL_ARGS which are used in later build +steps. +If the SP entry in the layout file has a "uuid" field the scripts gets the UUID +from there, otherwise it parses the associated partition manifest and extracts +the UUID from there. + +param1: Generated mk file "sp_gen.mk" +param2: "SP_LAYOUT_FILE", json file containing platform provided information +param3: plat out directory +param4: CoT parameter + +Generated "sp_gen.mk" file contains triplet of following information for each +Secure Partition entry + FDT_SOURCES += sp1.dts + SPTOOL_ARGS += -i sp1.bin:sp1.dtb -o sp1.pkg + FIP_ARGS += --blob uuid=XXXXX-XXX...,file=sp1.pkg + CRT_ARGS += --sp-pkg1 sp1.pkg + +A typical SP_LAYOUT_FILE file will look like +{ + "SP1" : { + "image": "sp1.bin", + "pm": "test/sp1.dts" + }, + + "SP2" : { + "image": "sp2.bin", + "pm": "test/sp2.dts", + "uuid": "1b1820fe-48f7-4175-8999-d51da00b7c9f" + } + + ... +} + +""" + +import getopt +import json +import os +import re +import sys +import uuid + +with open(sys.argv[2],'r') as in_file: + data = json.load(in_file) +json_file = os.path.abspath(sys.argv[2]) +json_dir = os.path.dirname(json_file) +gen_file = os.path.abspath(sys.argv[1]) +out_dir = os.path.abspath(sys.argv[3]) +dtb_dir = out_dir + "/fdts/" +MAX_SP = 8 +dualroot = sys.argv[4].lower() == "dualroot" +split = int(MAX_SP / 2) +print(dtb_dir) +platform_count = 1 +sip_count = 1 + +with open(gen_file, 'w') as out_file: + for idx, key in enumerate(data.keys()): + + pkg_num = idx + 1 + + if (pkg_num > MAX_SP): + print("WARNING: Too many secure partitions\n") + exit(-1) + + if dualroot: + owner = data[key].get('owner') + if owner == "Plat": + if (platform_count > split): + print("WARNING: Maximum Secure partitions by Plat " + + "have been exceeded (" + str(split) + ")\n") + exit(-1) + pkg_num = split + platform_count + platform_count += 1 + elif (sip_count > split): + print("WARNING: Maximum Secure partitions by SiP " + + "have been exceeded (" + str(split) + ")\n") + exit(-1) + else: + pkg_num = sip_count + sip_count += 1 + + """ + Append FDT_SOURCES + """ + dts = os.path.join(json_dir, data[key]['pm']) + dtb = dtb_dir + os.path.basename(data[key]['pm'][:-1] + "b") + out_file.write("FDT_SOURCES += " + dts + "\n") + + """ + Update SPTOOL_ARGS + """ + dst = out_dir + "/" + key + ".pkg" + src = [ json_dir + "/" + data[key]['image'] , dtb ] + out_file.write("SPTOOL_ARGS += -i " + ":".join(src) + " -o " + dst + "\n") + + if "uuid" in data[key]: + """ + Extract the UUID from the JSON file if the SP entry has a 'uuid' field + """ + uuid_std = uuid.UUID(data[key]['uuid']) + else: + """ + Extract uuid from partition manifest + """ + pm_file = open(dts) + for line in pm_file: + if "uuid" in line: + # re.findall returns a list of string tuples. + # uuid_hex is the first item in this list representing the four + # uuid hex integers from the manifest uuid field. The heading + # '0x' of the hexadecimal representation is stripped out. + # e.g. uuid = <0x1e67b5b4 0xe14f904a 0x13fb1fb8 0xcbdae1da>; + # uuid_hex = ('1e67b5b4', 'e14f904a', '13fb1fb8', 'cbdae1da') + uuid_hex = re.findall(r'0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+) 0x([0-9a-f]+)', line)[0]; + + # uuid_hex is a list of four hex string values + if len(uuid_hex) != 4: + print("ERROR: malformed UUID") + exit(-1) + + # The uuid field in SP manifest is the little endian representation + # mapped to arguments as described in SMCCC section 5.3. + # Convert each unsigned integer value to a big endian representation + # required by fiptool. + y=list(map(bytearray.fromhex, uuid_hex)) + z=(int.from_bytes(y[0], byteorder='little', signed=False), + int.from_bytes(y[1], byteorder='little', signed=False), + int.from_bytes(y[2], byteorder='little', signed=False), + int.from_bytes(y[3], byteorder='little', signed=False)) + uuid_std = uuid.UUID(f'{z[0]:08x}{z[1]:08x}{z[2]:08x}{z[3]:08x}') + + """ + Append FIP_ARGS + """ + out_file.write("FIP_ARGS += --blob uuid=" + str(uuid_std) + ",file=" + dst + "\n") + + """ + Append CRT_ARGS + """ + + out_file.write("CRT_ARGS += --sp-pkg" + str(pkg_num) + " " + dst + "\n") + out_file.write("\n") diff --git a/arm-trusted-firmware/tools/sptool/sptool.c b/arm-trusted-firmware/tools/sptool/sptool.c new file mode 100644 index 0000000..38baa2c --- /dev/null +++ b/arm-trusted-firmware/tools/sptool/sptool.c @@ -0,0 +1,360 @@ +/* + * Copyright (c) 2018-2020, Arm Limited. All rights reserved. + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "sptool.h" + +#define PAGE_SIZE 4096 + +/* + * Entry describing Secure Partition package. + */ +struct sp_pkg_info { + /* Location of the files in the host's RAM. */ + void *img_data, *pm_data; + + /* Size of the files. */ + uint32_t img_size, pm_size; + + /* Location of the binary files inside the package output file */ + uint32_t img_offset, pm_offset; +}; + +/* + * List of input provided by user + */ +struct arg_list { + char *usr_input; + struct arg_list *next; +}; + +/* Align an address to a power-of-two boundary. */ +static unsigned int align_to(unsigned int address, unsigned int boundary) +{ + unsigned int mask = boundary - 1U; + + if ((address & mask) != 0U) + return (address + boundary) & ~mask; + else + return address; +} + +/* Allocate a memory area of 'size' bytes and zero it. */ +static void *xzalloc(size_t size, const char *msg) +{ + void *d; + + d = malloc(size); + if (d == NULL) { + fprintf(stderr, "error: malloc: %s\n", msg); + exit(1); + } + + memset(d, 0, size); + + return d; +} + +/* + * Write 'size' bytes from 'buf' into the specified file stream. + * Exit the program on error. + */ +static void xfwrite(void *buf, size_t size, FILE *fp) +{ + if (fwrite(buf, 1, size, fp) != size) { + fprintf(stderr, "error: Failed to write to output file.\n"); + exit(1); + } +} + +/* + * Set the file position indicator for the specified file stream. + * Exit the program on error. + */ +static void xfseek(FILE *fp, long offset, int whence) +{ + if (fseek(fp, offset, whence) != 0) { + fprintf(stderr, "error: Failed to set file to offset 0x%lx (%d).\n", + offset, whence); + perror(NULL); + exit(1); + } +} + +/* + * Free SP package structure + */ +static void cleanup(struct sp_pkg_info *sp) +{ + + if (sp != NULL) { + if (sp->img_data != NULL) { + free(sp->img_data); + } + + if (sp->pm_data != NULL) { + free(sp->pm_data); + } + + free(sp); + + } +} + +/* + * Free argument list structure + */ +static void freelist(struct arg_list *head) +{ + struct arg_list *tmp; + + while (head != NULL) { + tmp = head; + head = head->next; + free(tmp); + } +} + +/* + * Append user inputs in argument list structure + */ +static void append_user_input(struct arg_list **head, char *args) +{ + struct arg_list *tmp = *head; + + if (tmp == NULL) { + tmp = xzalloc(sizeof(struct arg_list), + "Failed to allocate arg_list struct"); + tmp->usr_input = args; + *head = tmp; + } else { + while (tmp->next != NULL) { + tmp = tmp->next; + } + tmp->next = xzalloc(sizeof(struct arg_list), + "Failed to allocate arg_list struct"); + tmp = tmp->next; + tmp->usr_input = args; + } +} + +/* + * Allocate a buffer big enough to store the content of the specified file and + * load the file into it. Fill 'size' with the file size. Exit the program on + * error. + */ +static void load_file(const char *path, void **ptr, uint32_t *size) +{ + FILE *f = fopen(path, "rb"); + if (f == NULL) { + fprintf(stderr, "error: %s couldn't be opened.\n", path); + exit(1); + } + + xfseek(f, 0, SEEK_END); + *size = ftell(f); + if (*size == 0) { + fprintf(stderr, "error: Size of %s is 0\n", path); + exit(1); + } + + rewind(f); + + *ptr = malloc(*size); + if (*ptr == NULL) { + fprintf(stderr, "error: Not enough memory to load %s\n", path); + exit(1); + } + + if (fread(*ptr, *size, 1, f) != 1) { + fprintf(stderr, "error: Couldn't read %s\n", path); + exit(1); + } + + fclose(f); +} + +/* + * Parse the string containing input payloads and fill in the + * SP Package data structure. + */ +static void load_sp_pm(char *path, struct sp_pkg_info **sp_out) +{ + struct sp_pkg_info *sp_pkg; + + char *split_mark = strstr(path, ":"); + + *split_mark = '\0'; + + char *sp_path = path; + char *pm_path = split_mark + 1; + + sp_pkg = xzalloc(sizeof(struct sp_pkg_info), + "Failed to allocate sp_pkg_info struct"); + + load_file(pm_path, &sp_pkg->pm_data, &sp_pkg->pm_size); + printf("\nLoaded SP Manifest file %s (%u bytes)\n", pm_path, sp_pkg->pm_size); + + load_file(sp_path, &sp_pkg->img_data, &sp_pkg->img_size); + printf("Loaded SP Image file %s (%u bytes)\n", sp_path, sp_pkg->img_size); + + *sp_out = sp_pkg; +} + +/* + * Write SP package data structure into output file. + */ +static void output_write(const char *path, struct sp_pkg_info *sp, bool header) +{ + struct sp_pkg_header sp_header_info; + unsigned int file_ptr = 0; + + FILE *f = fopen(path, "wb"); + if (f == NULL) { + fprintf(stderr, "error: Failed to open %s\n", path); + exit(1); + } + + /* Reserve Header size */ + if (header) { + file_ptr = sizeof(struct sp_pkg_header); + } + + /* Save partition manifest */ + xfseek(f, file_ptr, SEEK_SET); + printf("Writing SP Manifest at offset 0x%x (%u bytes)\n", + file_ptr, sp->pm_size); + + sp->pm_offset = file_ptr; + xfwrite(sp->pm_data, sp->pm_size, f); + + /* Save partition image aligned to Page size */ + file_ptr = align_to((sp->pm_offset + sp->pm_size), PAGE_SIZE); + xfseek(f, file_ptr, SEEK_SET); + printf("Writing SP Image at offset 0x%x (%u bytes)\n", + file_ptr, sp->img_size); + + sp->img_offset = file_ptr; + xfwrite(sp->img_data, sp->img_size, f); + + /* Finally, write header, if needed */ + if (header) { + sp_header_info.magic = SECURE_PARTITION_MAGIC; + sp_header_info.version = 0x1; + sp_header_info.img_offset = sp->img_offset; + sp_header_info.img_size = sp->img_size; + sp_header_info.pm_offset = sp->pm_offset; + sp_header_info.pm_size = sp->pm_size; + + xfseek(f, 0, SEEK_SET); + + printf("Writing package header\n"); + + xfwrite(&sp_header_info, sizeof(struct sp_pkg_header), f); + } + + /* All information has been written now */ + printf("\nsptool: Built Secure Partition blob %s\n", path); + + fclose(f); +} + +static void usage(void) +{ + printf("usage: sptool "); +#ifdef VERSION + printf(VERSION); +#else + /* If built from sptool directory, VERSION is not set. */ + printf("version unknown"); +#endif + printf(" []\n\n"); + + printf("This tool takes as input set of image binary files and the\n" + "partition manifest blobs as input and generates set of\n" + "output package files\n" + "Usage example: sptool -i sp1.bin:sp1.dtb -o sp1.pkg\n" + " -i sp2.bin:sp2.dtb -o sp2.pkg ...\n\n"); + printf("Commands supported:\n"); + printf(" -o Set output file path.\n"); + printf(" -i Add Secure Partition image and\n" + " Manifest blob (specified in two paths\n" + " separated by a colon).\n"); + printf(" -n Generate package without header\n"); + printf(" -h Show this message.\n"); + exit(1); +} + +int main(int argc, char *argv[]) +{ + struct sp_pkg_info *sp_pkg = NULL; + struct arg_list *in_head = NULL; + struct arg_list *out_head = NULL; + struct arg_list *in_list = NULL; + struct arg_list *out_list = NULL; + unsigned int match_counter = 0; + bool need_header = true; + + int ch; + + if (argc <= 1) { + fprintf(stderr, "error: File paths must be provided.\n\n"); + usage(); + return 1; + } + + while ((ch = getopt(argc, argv, "hni:o:")) != -1) { + switch (ch) { + case 'i': + append_user_input(&in_head, optarg); + match_counter++; + break; + case 'o': + append_user_input(&out_head, optarg); + match_counter--; + break; + case 'n': + need_header = false; + break; + case 'h': + default: + usage(); + } + } + + if (match_counter) { + fprintf(stderr, "error: Input/Output count mismatch.\n\n"); + freelist(in_head); + freelist(out_head); + usage(); + return 1; + } + + in_list = in_head; + out_list = out_head; + while (in_list != NULL) { + load_sp_pm(in_list->usr_input, &sp_pkg); + output_write(out_list->usr_input, sp_pkg, need_header); + in_list = in_list->next; + out_list = out_list->next; + } + + argc -= optind; + argv += optind; + + cleanup(sp_pkg); + freelist(in_head); + freelist(out_head); + + return 0; +} diff --git a/arm-trusted-firmware/tools/stm32image/Makefile b/arm-trusted-firmware/tools/stm32image/Makefile new file mode 100644 index 0000000..9c9b7b5 --- /dev/null +++ b/arm-trusted-firmware/tools/stm32image/Makefile @@ -0,0 +1,49 @@ +# +# Copyright (c) 2017-2018, ARM Limited and Contributors. All rights reserved. +# +# SPDX-License-Identifier: BSD-3-Clause +# + +MAKE_HELPERS_DIRECTORY := ../../make_helpers/ +include ${MAKE_HELPERS_DIRECTORY}build_macros.mk +include ${MAKE_HELPERS_DIRECTORY}build_env.mk + +PROJECT := stm32image${BIN_EXT} +OBJECTS := stm32image.o +V := 0 + +HOSTCCFLAGS := -Wall -Werror -pedantic -std=c99 -D_GNU_SOURCE + +ifeq (${DEBUG},1) + HOSTCCFLAGS += -g -O0 -DDEBUG +else + HOSTCCFLAGS += -O2 +endif + +ifeq (${V},0) + Q := @ +else + Q := +endif + +HOSTCC := gcc + +.PHONY: all clean distclean + +all: ${PROJECT} + +${PROJECT}: ${OBJECTS} Makefile + @echo " HOSTLD $@" + ${Q}${HOSTCC} ${OBJECTS} -o $@ + @${ECHO_BLANK_LINE} + @echo "Built $@ successfully" + @${ECHO_BLANK_LINE} + +%.o: %.c Makefile + @echo " HOSTCC $<" + ${Q}${HOSTCC} -c ${HOSTCCFLAGS} $< -o $@ + +clean: + $(call SHELL_DELETE_ALL, ${PROJECT} ${OBJECTS}) + +distclean: clean diff --git a/arm-trusted-firmware/tools/stm32image/stm32image.c b/arm-trusted-firmware/tools/stm32image/stm32image.c new file mode 100644 index 0000000..bd4720c --- /dev/null +++ b/arm-trusted-firmware/tools/stm32image/stm32image.c @@ -0,0 +1,361 @@ +/* + * Copyright (c) 2017-2022, STMicroelectronics - All Rights Reserved + * + * SPDX-License-Identifier: BSD-3-Clause + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Magic = 'S' 'T' 'M' 0x32 */ +#define HEADER_MAGIC __be32_to_cpu(0x53544D32) +#define VER_MAJOR 2 +#define VER_MINOR 1 +#define VER_VARIANT 0 +#define HEADER_VERSION_V1 0x1 +#define HEADER_VERSION_V2 0x2 +#define PADDING_HEADER_MAGIC __be32_to_cpu(0x5354FFFF) +#define PADDING_HEADER_FLAG (1 << 31) +#define PADDING_HEADER_LENGTH 0x180 + +struct stm32_header_v1 { + uint32_t magic_number; + uint8_t image_signature[64]; + uint32_t image_checksum; + uint8_t header_version[4]; + uint32_t image_length; + uint32_t image_entry_point; + uint32_t reserved1; + uint32_t load_address; + uint32_t reserved2; + uint32_t version_number; + uint32_t option_flags; + uint32_t ecdsa_algorithm; + uint8_t ecdsa_public_key[64]; + uint8_t padding[83]; + uint8_t binary_type; +}; + +struct stm32_header_v2 { + uint32_t magic_number; + uint8_t image_signature[64]; + uint32_t image_checksum; + uint8_t header_version[4]; + uint32_t image_length; + uint32_t image_entry_point; + uint32_t reserved1; + uint32_t load_address; + uint32_t reserved2; + uint32_t version_number; + uint32_t extension_flags; + uint32_t extension_headers_length; + uint32_t binary_type; + uint8_t padding[16]; + uint32_t extension_header_type; + uint32_t extension_header_length; + uint8_t extension_padding[376]; +}; + +static void stm32image_default_header(void *ptr) +{ + struct stm32_header_v1 *header = (struct stm32_header_v1 *)ptr; + + if (!header) { + return; + } + + header->magic_number = HEADER_MAGIC; + header->version_number = __cpu_to_le32(0); +} + +static uint32_t stm32image_checksum(void *start, uint32_t len, + uint32_t header_size) +{ + uint32_t csum = 0; + uint8_t *p; + + if (len < header_size) { + return 0; + } + + p = (unsigned char *)start + header_size; + len -= header_size; + + while (len > 0) { + csum += *p; + p++; + len--; + } + + return csum; +} + +static void stm32image_print_header(const void *ptr) +{ + struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; + struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; + + printf("Image Type : ST Microelectronics STM32 V%d.%d\n", + stm32hdr->header_version[VER_MAJOR], + stm32hdr->header_version[VER_MINOR]); + printf("Image Size : %lu bytes\n", + (unsigned long)__le32_to_cpu(stm32hdr->image_length)); + printf("Image Load : 0x%08x\n", + __le32_to_cpu(stm32hdr->load_address)); + printf("Entry Point : 0x%08x\n", + __le32_to_cpu(stm32hdr->image_entry_point)); + printf("Checksum : 0x%08x\n", + __le32_to_cpu(stm32hdr->image_checksum)); + + switch (stm32hdr->header_version[VER_MAJOR]) { + case HEADER_VERSION_V1: + printf("Option : 0x%08x\n", + __le32_to_cpu(stm32hdr->option_flags)); + break; + + case HEADER_VERSION_V2: + printf("Extension : 0x%08x\n", + __le32_to_cpu(stm32hdr_v2->extension_flags)); + break; + + default: + printf("Incorrect header version\n"); + } + + printf("Version : 0x%08x\n", + __le32_to_cpu(stm32hdr->version_number)); +} + +static int stm32image_set_header(void *ptr, struct stat *sbuf, int ifd, + uint32_t loadaddr, uint32_t ep, uint32_t ver, + uint32_t major, uint32_t minor, + uint32_t binary_type, uint32_t header_size) +{ + struct stm32_header_v1 *stm32hdr = (struct stm32_header_v1 *)ptr; + struct stm32_header_v2 *stm32hdr_v2 = (struct stm32_header_v2 *)ptr; + uint32_t ext_size = 0U; + uint32_t ext_flags = 0U; + + stm32image_default_header(ptr); + + stm32hdr->header_version[VER_MAJOR] = major; + stm32hdr->header_version[VER_MINOR] = minor; + stm32hdr->load_address = __cpu_to_le32(loadaddr); + stm32hdr->image_entry_point = __cpu_to_le32(ep); + stm32hdr->image_length = __cpu_to_le32((uint32_t)sbuf->st_size - + header_size); + stm32hdr->image_checksum = + __cpu_to_le32(stm32image_checksum(ptr, sbuf->st_size, + header_size)); + + switch (stm32hdr->header_version[VER_MAJOR]) { + case HEADER_VERSION_V1: + /* Default option for header v1 : bit0 => no signature */ + stm32hdr->option_flags = __cpu_to_le32(0x00000001); + stm32hdr->ecdsa_algorithm = __cpu_to_le32(1); + stm32hdr->binary_type = (uint8_t)binary_type; + break; + + case HEADER_VERSION_V2: + stm32hdr_v2->binary_type = binary_type; + ext_size += PADDING_HEADER_LENGTH; + ext_flags |= PADDING_HEADER_FLAG; + stm32hdr_v2->extension_flags = + __cpu_to_le32(ext_flags); + stm32hdr_v2->extension_headers_length = + __cpu_to_le32(ext_size); + stm32hdr_v2->extension_header_type = PADDING_HEADER_MAGIC; + stm32hdr_v2->extension_header_length = + __cpu_to_le32(PADDING_HEADER_LENGTH); + break; + + default: + return -1; + } + + stm32hdr->version_number = __cpu_to_le32(ver); + + return 0; +} + +static int stm32image_create_header_file(char *srcname, char *destname, + uint32_t loadaddr, uint32_t entry, + uint32_t version, uint32_t major, + uint32_t minor, uint32_t binary_type) +{ + int src_fd, dest_fd, header_size; + struct stat sbuf; + unsigned char *ptr; + void *stm32image_header; + + dest_fd = open(destname, O_RDWR | O_CREAT | O_TRUNC | O_APPEND, 0666); + if (dest_fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", destname, + strerror(errno)); + return -1; + } + + src_fd = open(srcname, O_RDONLY); + if (src_fd == -1) { + fprintf(stderr, "Can't open %s: %s\n", srcname, + strerror(errno)); + return -1; + } + + if (fstat(src_fd, &sbuf) < 0) { + return -1; + } + + ptr = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, src_fd, 0); + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't read %s\n", srcname); + return -1; + } + + switch (major) { + case HEADER_VERSION_V1: + stm32image_header = malloc(sizeof(struct stm32_header_v1)); + header_size = sizeof(struct stm32_header_v1); + break; + + case HEADER_VERSION_V2: + stm32image_header = malloc(sizeof(struct stm32_header_v2)); + header_size = sizeof(struct stm32_header_v2); + break; + + default: + return -1; + } + + memset(stm32image_header, 0, header_size); + if (write(dest_fd, stm32image_header, header_size) != + header_size) { + fprintf(stderr, "Write error %s: %s\n", destname, + strerror(errno)); + free(stm32image_header); + return -1; + } + + free(stm32image_header); + + if (write(dest_fd, ptr, sbuf.st_size) != sbuf.st_size) { + fprintf(stderr, "Write error on %s: %s\n", destname, + strerror(errno)); + return -1; + } + + munmap((void *)ptr, sbuf.st_size); + close(src_fd); + + if (fstat(dest_fd, &sbuf) < 0) { + return -1; + } + + ptr = mmap(0, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_SHARED, + dest_fd, 0); + + if (ptr == MAP_FAILED) { + fprintf(stderr, "Can't write %s\n", destname); + return -1; + } + + if (stm32image_set_header(ptr, &sbuf, dest_fd, loadaddr, + entry, version, major, minor, + binary_type, header_size) != 0) { + return -1; + } + + stm32image_print_header(ptr); + + munmap((void *)ptr, sbuf.st_size); + close(dest_fd); + return 0; +} + +int main(int argc, char *argv[]) +{ + int opt; + int loadaddr = -1; + int entry = -1; + int err = 0; + int version = 0; + int binary_type = -1; + int major = HEADER_VERSION_V2; + int minor = 0; + char *dest = NULL; + char *src = NULL; + + while ((opt = getopt(argc, argv, ":b:s:d:l:e:v:m:n:")) != -1) { + switch (opt) { + case 'b': + binary_type = strtol(optarg, NULL, 0); + break; + case 's': + src = optarg; + break; + case 'd': + dest = optarg; + break; + case 'l': + loadaddr = strtol(optarg, NULL, 0); + break; + case 'e': + entry = strtol(optarg, NULL, 0); + break; + case 'v': + version = strtol(optarg, NULL, 0); + break; + case 'm': + major = strtol(optarg, NULL, 0); + break; + case 'n': + minor = strtol(optarg, NULL, 0); + break; + default: + fprintf(stderr, + "Usage : %s [-s srcfile] [-d destfile] [-l loadaddr] [-e entry_point] [-m major] [-n minor] [-b binary_type]\n", + argv[0]); + return -1; + } + } + + if (!src) { + fprintf(stderr, "Missing -s option\n"); + return -1; + } + + if (!dest) { + fprintf(stderr, "Missing -d option\n"); + return -1; + } + + if (loadaddr == -1) { + fprintf(stderr, "Missing -l option\n"); + return -1; + } + + if (entry == -1) { + fprintf(stderr, "Missing -e option\n"); + return -1; + } + + if (binary_type == -1) { + fprintf(stderr, "Missing -b option\n"); + return -1; + } + + err = stm32image_create_header_file(src, dest, loadaddr, + entry, version, major, minor, + binary_type); + + return err; +} diff --git a/atf_and_optee_README.txt b/atf_and_optee_README.txt new file mode 100644 index 0000000..591edda --- /dev/null +++ b/atf_and_optee_README.txt @@ -0,0 +1,127 @@ +********************************************************************** +NVIDIA Jetson Linux (L4T) OP-TEE Package +********************************************************************** + +---------------------------------------------------------------------- +Introduction +---------------------------------------------------------------------- +This package contains the necessary files and instructions to build a +trusted OS image based on ATF and OP-TEE for these Jetson devices: +- Jetson Xavier NX +- Jetson AGX Xavier series +- Jetson AGX Orin series + +---------------------------------------------------------------------- +Prerequisites +---------------------------------------------------------------------- +Please refer to the link below to install build prerequisites, e.g. +python3-pycryptodome and python3-pyelftools, in your build machine. + +https://optee.readthedocs.io/en/latest/building/prerequisites.html + +---------------------------------------------------------------------- +Placeholders used in this document +---------------------------------------------------------------------- +This document uses a placeholder, "", to indicate Jetson platforms. +Its possible values are: +- 194 +- 234 +Choose the platform value according to your Jetson board to build different +trusted OS images and DTBs. + +---------------------------------------------------------------------- +Toolchain +---------------------------------------------------------------------- +Download the toolchain from Jetson release page according to your L4T version: + +https://developer.nvidia.com/embedded/jetson-linux-archive + +Set environment variable CROSS_COMPILE_AARCH64_PATH to point to the aarch64 +toolchain. For example, if the aarch64 toolchain directory is +/toolchain/aarch64--glibc--stable-2022.03-1/, then set +the CROSS_COMPILE_AARCH64_PATH with the command below. + +export CROSS_COMPILE_AARCH64_PATH=/toolchain/aarch64--glibc--stable-2022.03-1 + +Then set environment variable CROSS_COMPILE_AARCH64 with the command +below. + +export CROSS_COMPILE_AARCH64=/toolchain/aarch64--glibc--stable-2022.03-1/bin/aarch64-buildroot-linux-gnu- + +---------------------------------------------------------------------- +UEFI StMM image +---------------------------------------------------------------------- +A UEFI StMM image is required when building OP-TEE. The image is usually at: + +For the Jetson AGX Xavier series and the Jetson Xavier NX: +/bootloader/standalonemm_optee_t194.bin + +For the Jetson AGX Orin series: +/bootloader/standalonemm_optee_t234.bin + +Set the environment variable "UEFI_STMM_PATH" to let the OP-TEE build script +know where the image is: + +export UEFI_STMM_PATH= + +---------------------------------------------------------------------- +Building the OP-TEE source code +---------------------------------------------------------------------- +Execute this command to build the OP-TEE source package: + +./optee_src_build.sh -p t + +---------------------------------------------------------------------- +Building the OP-TEE dtb +---------------------------------------------------------------------- +Execute this command to build OP-TEE dtb: + +dtc -I dts -O dtb -o ./optee/tegra-optee.dtb ./optee/tegra-optee.dts + +---------------------------------------------------------------------- +Building the ATF source code with OP-TEE SPD +---------------------------------------------------------------------- +1. Extract the ATF source package. + mkdir atf_build + tar -I lbzip2 -C atf_build -xpf atf_src.tbz2 + +2. Build the ATF source code: + cd atf_build/arm-trusted-firmware + make BUILD_BASE=./build \ + CROSS_COMPILE="${CROSS_COMPILE_AARCH64}" \ + DEBUG=0 LOG_LEVEL=20 PLAT=tegra SPD=opteed TARGET_SOC=t V=0 + cd ../.. + +---------------------------------------------------------------------- +Generating the tos.img with ATF and OP-TEE images +---------------------------------------------------------------------- +1. Get gen_tos_part_img.py. It's usually in the directory + /nv_tegra/tos-scripts/ of BSP package. + +2. Generate the tos.img with the commands: + ./gen_tos_part_img.py \ + --monitor ./atf_build/arm-trusted-firmware/build/tegra/t/release/bl31.bin \ + --os ./optee/build/t/core/tee-raw.bin \ + --dtb ./optee/tegra-optee.dtb \ + --tostype optee \ + ./tos.img + +---------------------------------------------------------------------- +Verifying the Image +---------------------------------------------------------------------- +To verify the image: +1. Replace the default TOS image file with the newly generated TOS + image. The default TOS image file is located at: + /bootloader/tos-optee_t.img + +2. Perform either of these tasks: + - Flash the system as normal. + This is useful for flashing a new system or replacing the + entire operating system. + - Re-flash the TOS image using these partition flash commands: + sudo ./flash.sh -k mmcblk0p1 + ex: + sudo ./flash.sh -k secure-os jetson-xavier-nx-devkit mmcblk0p1 + sudo ./flash.sh -k A_secure-os jetson-agx-orin-devkit mmcblk0p1 + +3. Copy all the files under ./optee/install/t to the target. diff --git a/commitFile.txt b/commitFile.txt new file mode 100644 index 0000000..b3d62f9 --- /dev/null +++ b/commitFile.txt @@ -0,0 +1,3601 @@ +Updating prebuilts and/or headers + +e8aa3af98539680668d37659b7ba8f7e2becb16b - nvbuild.sh +d15f50688485e11293e0d0bd66d73655e79f7718 - nvcommon_build.sh +55bcfa0a03639a375c3f87b1d3286f526c41b207 - arm-trusted-firmware/.versionrc.js +5f8311228df51d284e4efc6c89e9d193dde99d11 - arm-trusted-firmware/.editorconfig +2b66445d7d00314222c238ee2f233a099ac6d838 - arm-trusted-firmware/.commitlintrc.js +1156a747abe8e5f2a639fe82c7e9b4b8c128428c - arm-trusted-firmware/package-lock.json +d2180c4f81067554a4fa86baaebf7cd7722d0706 - arm-trusted-firmware/Makefile +c10d9e3662b48b6da5c81ce00879a16fd8cf3d60 - arm-trusted-firmware/.cz.json +2d62a7583b85631859c4143f08e0dc332e1cb87e - arm-trusted-firmware/.gitreview +da14c19baefee3959f7c02f68db6cbe8c25d408e - arm-trusted-firmware/readme.rst +7f3fadaf80e3c4745d24cb1a5881c7c5f4d898ba - arm-trusted-firmware/.checkpatch.conf +2da4fc2430e852f43b1ec376e4783a1d4658c039 - arm-trusted-firmware/package.json +1684b8fa062fcf155fb678c6e112cf5436423ba2 - arm-trusted-firmware/changelog.yaml +d8da3627085908a5f974b45528b85dc0a41a8b75 - arm-trusted-firmware/license.rst +5c6a4c08a854ddd3d464e6d96f605ff5e28fcf28 - arm-trusted-firmware/bl31/ehf.c +75c196ade8ef57a9775c286e3c2f88b52c492e67 - arm-trusted-firmware/bl31/bl31_context_mgmt.c +ae44163001e4ade4c2e29f6afb43316e7584ee41 - arm-trusted-firmware/bl31/interrupt_mgmt.c +ccc40b094b337f6e60b8a4f2a7470ab4c1264f4f - arm-trusted-firmware/bl31/bl31_main.c +57600ae63b254bd5341c3728038049d1e9526b9a - arm-trusted-firmware/bl31/bl31.ld.S +64b21af0df86a3f591cbf9889b0990e313980048 - arm-trusted-firmware/bl31/aarch64/ea_delegate.S +7c846b0cc5af2d57b0a9ccac7bb940b95f682bce - arm-trusted-firmware/bl31/aarch64/crash_reporting.S +a6aee212d05e2c649a137adf37160a8d24360040 - arm-trusted-firmware/bl31/aarch64/runtime_exceptions.S +86ee5f1020a1ae3e8788204817e6b6fcb0da5922 - arm-trusted-firmware/bl31/aarch64/bl31_entrypoint.S +2c87153926f8a458cffc9a435e15571ba721c2fa - arm-trusted-firmware/licenses/LICENSE.MIT +8887d0d62a1b5248423fbc54ee536be3e5131d91 - arm-trusted-firmware/services/spd/opteed/opteed_private.h +04de846e914d22f5925ba665f709fd3b0793ea5c - arm-trusted-firmware/services/spd/opteed/teesmc_opteed.h +c7af1a7de6cb5d79bf42271e846f04a18df96b63 - arm-trusted-firmware/services/spd/opteed/opteed_pm.c +c8ea87fefa1ecd86c162a85206e9427be8c93afb - arm-trusted-firmware/services/spd/opteed/opteed_helpers.S +b4e16e85997824311dd82861c4c22d6ed046b817 - arm-trusted-firmware/services/spd/opteed/opteed_main.c +e6df3878f8d4759c9f52ea98cbd0d6303bd2983b - arm-trusted-firmware/services/spd/opteed/teesmc_opteed_macros.h +4577f90d8a829f8cb934271e6991bd34844e1854 - arm-trusted-firmware/services/spd/opteed/opteed_common.c +c41250dd18f5502066bab243f1a2f33acf9079f5 - arm-trusted-firmware/services/spd/tspd/tspd_private.h +36db67e2b644b85662e0440abdf6bb464032dfb1 - arm-trusted-firmware/services/spd/tspd/tspd_main.c +d68051c573aae1f65601f9c9307d095259f8de63 - arm-trusted-firmware/services/spd/tspd/tspd_pm.c +45855bd72493c075e03c590cfade6075e5656654 - arm-trusted-firmware/services/spd/tspd/tspd_common.c +f9cf95e919ab4903bc80205e402547ddebe078a8 - arm-trusted-firmware/services/spd/tspd/tspd_helpers.S +61ff410fd8dae3d3ecffc63595125321444d53c7 - arm-trusted-firmware/services/spd/tlkd/tlkd_main.c +176e5bf39535fbb39c81b2deb17ee470cac87159 - arm-trusted-firmware/services/spd/tlkd/tlkd_pm.c +c213fbde43c8075e8fe28297dd6934f2f7c5f6fa - arm-trusted-firmware/services/spd/tlkd/tlkd_common.c +e4543798b8feb237167dc8c495b7aeb079d1b290 - arm-trusted-firmware/services/spd/tlkd/tlkd_private.h +14bc8b1de264fc27498c195073dcf7c1dd736c4d - arm-trusted-firmware/services/spd/tlkd/tlkd_helpers.S +cb38cd65497ea7679a3c5ced33d2e833c2f82797 - arm-trusted-firmware/services/spd/trusty/trusty.c +ba437dffc2a576e12cd8b8b5e8331a43244754b0 - arm-trusted-firmware/services/spd/trusty/trusty_helpers.S +405a4e398e27192766391869719c952a77d4e789 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.c +912f672668f3beed13a6a55a3fab7666e147ea6c - arm-trusted-firmware/services/spd/trusty/sm_err.h +2bbaae4a856f5eba1f98688458729049af38a448 - arm-trusted-firmware/services/spd/trusty/generic-arm64-smcall.h +55c35f079c4fec17128f7c644425b13fd516f2e8 - arm-trusted-firmware/services/spd/trusty/smcall.h +32f05b17684cd616a34fd51c98e75162d384217a - arm-trusted-firmware/services/arm_arch_svc/arm_arch_svc_setup.c +250540ab4306221c494658c2239ffed65aa3fbd9 - arm-trusted-firmware/services/std_svc/pci_svc.c +bc64867c51e6a4f26dc11e07d3be01304f8b78e3 - arm-trusted-firmware/services/std_svc/std_svc_setup.c +3e424bb10206165d477d92627a1a6d8955152b74 - arm-trusted-firmware/services/std_svc/spmd/spmd_private.h +6da223d4cbc8ff07b002a40446860274397aa283 - arm-trusted-firmware/services/std_svc/spmd/spmd_main.c +eb2fb622fab718a44678ea1273fb7df9d3dd49be - arm-trusted-firmware/services/std_svc/spmd/spmd_pm.c +eb5c9e4113243964f83a249807ed07711dc6f145 - arm-trusted-firmware/services/std_svc/spmd/aarch64/spmd_helpers.S +45b49532e2610460e0fba1e6cbf18573f216da9e - arm-trusted-firmware/services/std_svc/rmmd/rmmd_attest.c +26be0a6e880962cffc338be91ad0f344e8aee9ef - arm-trusted-firmware/services/std_svc/rmmd/rmmd_initial_context.h +5d93ba8b111b69b7ef12b9a1ce621d9740284e41 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_main.c +4268337ed8b89db9b3ad75537a8f1e2a008fc949 - arm-trusted-firmware/services/std_svc/rmmd/rmmd_private.h +51c4bc5d5a6c9b18e2f3f2c951d3f8abe0869ba2 - arm-trusted-firmware/services/std_svc/rmmd/aarch64/rmmd_helpers.S +06bef6d6d25e76eef2278253f480a4afbaebabf3 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_entry.S +6b1ef22efba95bff3270de056f0a4e2484528dee - arm-trusted-firmware/services/std_svc/rmmd/trp/linker.lds +83a9c2e476136e139d80cac740c65fee111c0ba6 - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_private.h +ca2e1ed2396b9c004b00095f04cbe848e743043d - arm-trusted-firmware/services/std_svc/rmmd/trp/trp_main.c +2fd31858f771c3fa2d49ac883b8e3bb8486cebae - arm-trusted-firmware/services/std_svc/sdei/sdei_event.c +e020a86b0568edbbb8e8a93f2cee43fc4812d475 - arm-trusted-firmware/services/std_svc/sdei/sdei_intr_mgmt.c +0a593d9b9aca3739ab4d94c4aa2ecdf7481ad305 - arm-trusted-firmware/services/std_svc/sdei/sdei_main.c +b8207b17922c0b2192565df4c3bc9e1e9e726afa - arm-trusted-firmware/services/std_svc/sdei/sdei_state.c +36f054958b6c01f03eed070113b49903ce936a5d - arm-trusted-firmware/services/std_svc/sdei/sdei_private.h +ed3a4e16186524a88ed19aa95176bc233b0928fe - arm-trusted-firmware/services/std_svc/sdei/sdei_dispatch.S +0f3a50749094ad519b427c0a9c94db4f8dd32988 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.c +99c265f55fed0f586d388c5654338897d9e296e6 - arm-trusted-firmware/services/std_svc/trng/trng_main.c +c53e4b9cdb4eaee27196d9759c484c4faeaf7d06 - arm-trusted-firmware/services/std_svc/trng/trng_entropy_pool.h +e3e6228d6ff51d8d1940c9d13b884a9699bc1a6e - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_shim_private.h +5ddc8c374ed249405453ffb9dd8519ddc8a7a34b - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_xlat.c +79d13846ac86474d81cf97529b0dcb9876156531 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_main.c +27e07360421aaf616722735cfdc19c90d91af4a0 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_setup.c +9f72d160e0732ed98d19b7f82e62c8434b043846 - arm-trusted-firmware/services/std_svc/spm_mm/spm_mm_private.h +f3b6abb1b262ca29c81fe896193453e05ae2fd50 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_helpers.S +92bbf065b55bbb16728230902e84c1ae124cdd26 - arm-trusted-firmware/services/std_svc/spm_mm/aarch64/spm_mm_shim_exceptions.S +358ff3e13baa8507b20744e31468185b03077531 - arm-trusted-firmware/common/bl_common.c +91cec99e37b1e7e986e62eb3474f5b0d63516507 - arm-trusted-firmware/common/image_decompress.c +4e8e81d22968abbb440726d3094bc3a5bbab94c6 - arm-trusted-firmware/common/tf_crc32.c +567e84803ece6e7ea1401d347ecba84600dea543 - arm-trusted-firmware/common/uuid.c +bb6318e6a4526a2e75ed8f74f629b22fad67317e - arm-trusted-firmware/common/fdt_wrappers.c +d1831078ebc7756a3c141537c4f33b00ce2ffca0 - arm-trusted-firmware/common/fdt_fixup.c +54620aa80f910434a484672d917861106ecc2df1 - arm-trusted-firmware/common/runtime_svc.c +f4efa0610d34dd7e2935e65e54d8226cf36f94ff - arm-trusted-firmware/common/desc_image_load.c +3ccdb5028aa976066c06527a27303c4a0db57ead - arm-trusted-firmware/common/tf_log.c +b21d0924c4f52357b3815446ebd25cc4f58ad622 - arm-trusted-firmware/common/aarch64/early_exceptions.S +5354886f2c074fe74f50056321be3516724c7536 - arm-trusted-firmware/common/aarch64/debug.S +e1451e78efe19651d81b93634da02b524c4ebcab - arm-trusted-firmware/common/backtrace/backtrace.c +8ce1f388b3852351c1fa8d8001d14910363ee672 - arm-trusted-firmware/common/aarch32/debug.S +d006178768f88929b34ddd8b6f7caf6ffb1577b4 - arm-trusted-firmware/bl1/bl1_main.c +20113f49289a58e42b03525ea9427f94e093f58f - arm-trusted-firmware/bl1/bl1_private.h +653f6de57d95cb1d74a23acc6389ab9292ef0451 - arm-trusted-firmware/bl1/bl1_fwu.c +f34fa7c71b4b146c22d99ea5e88650c232833b2b - arm-trusted-firmware/bl1/bl1.ld.S +587ecb158bf5940ddc7f95250a8802df39806ef0 - arm-trusted-firmware/bl1/aarch64/bl1_context_mgmt.c +d6181e93a353f492a54a5222fe53d793cc6d46d7 - arm-trusted-firmware/bl1/aarch64/bl1_exceptions.S +5c5e2355ca375fa98ae30f56bcf2f57ea7056c71 - arm-trusted-firmware/bl1/aarch64/bl1_entrypoint.S +284a0afe619de982f2bd1d4b1c625831ef7b3b5e - arm-trusted-firmware/bl1/aarch64/bl1_arch_setup.c +095ac3b2483b968f263618a4bd6cdd8d6f66d321 - arm-trusted-firmware/bl1/aarch32/bl1_context_mgmt.c +32bd99d2c29b908009a4aea495162f0bb76949db - arm-trusted-firmware/bl1/aarch32/bl1_exceptions.S +6ef2d19cb4ab43cba39eb87d49604192b1f3b2bd - arm-trusted-firmware/bl1/aarch32/bl1_entrypoint.S +8d6e2008e280f848fb14017ba5ba559a10724421 - arm-trusted-firmware/bl1/aarch32/bl1_arch_setup.c +85b2afc44851dc57e79c264641730d0e2eca3016 - arm-trusted-firmware/bl1/tbbr/tbbr_img_desc.c +3793e73034176c719a8160e57d2216f834867aea - arm-trusted-firmware/drivers/scmi-msg/base.h +d0830b0dd0dcad2627d7e25042e0b04f9172507d - arm-trusted-firmware/drivers/scmi-msg/common.h +9a06fcf18608dead4701ec10a63da3ace748fe3d - arm-trusted-firmware/drivers/scmi-msg/smt.c +6854b6e16a5d00e32471a842ac82a42307f4fd25 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.h +6494de9c4e6d28e03514a090db2224f8b96327ba - arm-trusted-firmware/drivers/scmi-msg/power_domain.h +ed00d8b9bd19e5b6e1f8ecd2721a613d1a9043ef - arm-trusted-firmware/drivers/scmi-msg/power_domain.c +a9219fa6261f43e472c7b1655189ae66022de0e2 - arm-trusted-firmware/drivers/scmi-msg/clock.h +20129a454f6019ae086f0fc760ccbe6441c75105 - arm-trusted-firmware/drivers/scmi-msg/clock.c +51f712caca20f1532dbd7a569fab515695f574f9 - arm-trusted-firmware/drivers/scmi-msg/reset_domain.c +0f8a382f7d1dc362cfb9bf7d2a7189987b1bd9f4 - arm-trusted-firmware/drivers/scmi-msg/entry.c +5d761434daa9ee97981a3e3264d4196b1b9710f7 - arm-trusted-firmware/drivers/scmi-msg/base.c +d53b18f9aba437cc5d23117338ddac6edd9ba447 - arm-trusted-firmware/drivers/clk/clk.c +f1d5a7ca46b231b4291d715aa7312bc93c8c8d3c - arm-trusted-firmware/drivers/cadence/uart/aarch64/cdns_console.S +a8b2be0d9781815f941f3b5c54c06d66869ebbb8 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv3.c +cbb35d75dea21db6209d5ab41ce216af0acbd5f3 - arm-trusted-firmware/drivers/nxp/gic/ls_gicv2.c +7da82df0c542d1d8ae8e69affe9e30ba233590a2 - arm-trusted-firmware/drivers/nxp/sd/sd_mmc.c +d354d19d9f42611b3ad0f293660bac71ee3a801c - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.h +0c3739bdd3d04953083299f803b7c30e40e3fa93 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.h +af21526870ded933cf4e5455fdd2935a82cea61b - arm-trusted-firmware/drivers/nxp/flexspi/nor/flexspi_nor.c +ce75912d66d9d45c7fb5514c2d883363346b1a48 - arm-trusted-firmware/drivers/nxp/flexspi/nor/fspi.c +396f26a188a6fb1077b280cdc459ee52ac4dec89 - arm-trusted-firmware/drivers/nxp/flexspi/nor/test_fspi.c +a4736e2e943ff2c95ee55ab5550d95dbf4e9fae5 - arm-trusted-firmware/drivers/nxp/interconnect/ls_cci.c +fa805a963aca474eb7b99d376fc23bf898fe4457 - arm-trusted-firmware/drivers/nxp/interconnect/ls_ccn.c +d4cf1b07b3a081078c4e7da1e354adc42f41f7ca - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_hw_specific.c +e4343fd48fd3beed200fd430ec2f84482e7171bf - arm-trusted-firmware/drivers/nxp/crypto/caam/src/hw_key_blob.c +bb9ccbfadb1dba83a0035f9bf7b3d22a48fa01ff - arm-trusted-firmware/drivers/nxp/crypto/caam/src/sec_jr_driver.c +ba408ad853e9ef0e53ce8319419a8b3d8a3da7ed - arm-trusted-firmware/drivers/nxp/crypto/caam/src/jobdesc.c +32d20982227d5346d95e069f256ec3556d52ecfe - arm-trusted-firmware/drivers/nxp/crypto/caam/src/rng.c +eeaa299335bd10e0531ff65d6a24c6a4da294057 - arm-trusted-firmware/drivers/nxp/crypto/caam/src/caam.c +ff23fd02b2c8ce84423f099d2b1bea12faf82aec - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/nxp_crypto.c +eb5515126eb5fa4bef2f7976e79e3f9fd0944afa - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/rsa.c +02475a8e210c6615aa5138943337551fc8b9087f - arm-trusted-firmware/drivers/nxp/crypto/caam/src/auth/hash.c +f29d54b17cb5dd1f602641d092227c883cb6a57b - arm-trusted-firmware/drivers/nxp/csu/csu.c +bf7712fb75e6373abf6791b46d9a4563fd00feb7 - arm-trusted-firmware/drivers/nxp/timer/nxp_timer.c +1d31a2492e42b2087d68ef756a91274f671987c7 - arm-trusted-firmware/drivers/nxp/dcfg/dcfg.c +5579fdab0db3121aceafcaf39eab316e0253aee3 - arm-trusted-firmware/drivers/nxp/sec_mon/snvs.c +3976af866b0f1353ade3d95b9d4ef92a7a2169ea - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc.h +c7adb94bca0f7e2a86394a503007aacd278de299 - arm-trusted-firmware/drivers/nxp/ifc/nand/ifc_nand.c +85860d4c7284e5f15ce31d18787f687d6bde61b8 - arm-trusted-firmware/drivers/nxp/ifc/nor/ifc_nor.c +9b849f025149e6cf51b2500c8f70b38703ed5078 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch2 +9489f5c75aa894fc166bb99b848883d0413170cb - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3_2 +753107ce7c270d602a0018c1cabb0ef8e7d3c54a - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_blx_ch3 +58bff9b3422ffad20520362a80a6f322da632da3 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch2 +8b7ec36599206f1c121cf2a9565bc043b6049dba - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/csf_hdr_parser.c +cb8400c786b03ab4685825c49454f7915622e629 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/plat_img_parser.c +e9bddb61157fc79a6db73771f3abc44b0fa2180e - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3_2 +aaaf596468de0e2b0f1fd9df798408ccae3ec67c - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/cot.c +bc6fe6b33a974e9a9e2ae522e3ac00b9f7ff4967 - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_pbi_ch3 +dd7d454c97e1855bb1c228cacfecb6238f4e487d - arm-trusted-firmware/drivers/nxp/auth/csf_hdr_parser/input_bl2_ch3 +5a7943b124da3fea7995adb004eff6a0b928e921 - arm-trusted-firmware/drivers/nxp/auth/tbbr/tbbr_cot.c +06049b8071d1258dcc7829e02727d935c561fa1a - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc380.c +73a87390ee3b46e2b5587087457d8a10a6f4cd35 - arm-trusted-firmware/drivers/nxp/tzc/plat_tzc400.c +d3e9bd0226d74dffd59af6ef1c8f029ca195db90 - arm-trusted-firmware/drivers/nxp/console/console_16550.c +f15b111b5f8ec4a947c36b642e6c6331bb5331a4 - arm-trusted-firmware/drivers/nxp/console/console_pl011.c +5128d83df7b28a2a4bd817b834e17b74206a84d7 - arm-trusted-firmware/drivers/nxp/console/16550_console.S +fed7a4d64f892002dd30f1e1bf50d5fbf537281d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/dimm.c +33929846548a6a6731c652caf6050b64dea2f9d7 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddrc.c +59117917987eb057fe4003d4da4c3125ea76dbc9 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/ddr.c +442cb1d00ad113cbdc5ce076abc56124655dbe2d - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/regs.c +eaefee9029f7ccfd854a5813aae54ad816808645 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/utility.c +e083ea048179544e9c8e52f7a48d7c315f03a475 - arm-trusted-firmware/drivers/nxp/ddr/nxp-ddr/README.odt +7547f7a2396ef42e0140f69a68424c714c210b19 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.c +9c36d85b72ea62f1b3e6d8df34efe02d50c468ca - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/pie.h +ac55bbcc1387d5092bdce1d236686694d82f2a87 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/ddr4fw.h +7c05bf68f35c9cbbeb751db67f075cc1bc864b72 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/messages.h +8ced20b50814e640a734b45571534428a03235aa - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/input.h +f222d8d69c33519c4908bafaaeb6a2482f35bb20 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/phy.h +aac92f8b51eb5a99b8c6c1b861b65d8ed56c92b9 - arm-trusted-firmware/drivers/nxp/ddr/phy-gen2/csr.h +d9b4015568e26bddf900e57b2034588011dc76fe - arm-trusted-firmware/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.c +6ba34d8cf6a1e66a6b8781b632305c8192f8c47f - arm-trusted-firmware/drivers/nxp/ddr/phy-gen1/phy.c +7e7c03a074969dc0547afeb5dbe289ae008dae93 - arm-trusted-firmware/drivers/nxp/qspi/qspi.c +45cce82acdd1f75c2e31f56de0a27738ec712b09 - arm-trusted-firmware/drivers/nxp/gpio/nxp_gpio.c +1c9fa968ab5e023d06dcdbe0d3d12847d4e13273 - arm-trusted-firmware/drivers/nxp/pmu/pmu.c +e87ea077dcc89cfad504b38c454094873eb4bbae - arm-trusted-firmware/drivers/nxp/sfp/sfp.c +904d53ac1f2e9c98f1e176eae19be267e985db33 - arm-trusted-firmware/drivers/nxp/sfp/fuse_prov.c +3a182ddb4f6fa33eaf8b5ae0c60f6bdf113f4fcc - arm-trusted-firmware/drivers/nxp/i2c/i2c.c +b0d5b078d9666eb577b6d96327526056a9c5ff46 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.h +e7fdf9ac8aa8e62e2b82e935887ea9fa71277e50 - arm-trusted-firmware/drivers/imx/timer/imx_gpt.c +d92351086a1b0b0b82cfa7bab9e352d5725339d7 - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.c +11d6bed45c0c1633f53d1a14e935db95a494322d - arm-trusted-firmware/drivers/imx/usdhc/imx_usdhc.h +30ead9b9f8c8e8a0d0443291726c90dcc10f24ef - arm-trusted-firmware/drivers/imx/uart/imx_uart.c +2b9b4163928ad22b375942df6a419ac25791d15b - arm-trusted-firmware/drivers/imx/uart/imx_crash_uart.S +bf6cd6123996ffba448042a934561a9845514132 - arm-trusted-firmware/drivers/imx/uart/imx_uart.h +7ff3e84af33c3fcf6ee55936d6400a52d52203b4 - arm-trusted-firmware/drivers/mentor/i2c/mi2cv.c +c841aaad58e92f728c90bb7cab1771d2578be18a - arm-trusted-firmware/drivers/allwinner/sunxi_msgbox.c +5dda361745c9b337192dcd67fc63865e04a3a8a5 - arm-trusted-firmware/drivers/allwinner/sunxi_rsb.c +304398c75526a767b8b3caaeb5722e41955e9803 - arm-trusted-firmware/drivers/allwinner/axp/common.c +f3f36bb92d56df7e9785cc98f6b13594df6404c0 - arm-trusted-firmware/drivers/allwinner/axp/axp803.c +956dadae6d826687fecfa1b522fd8b5c4fdfc764 - arm-trusted-firmware/drivers/allwinner/axp/axp805.c +a5328f6dfd065a9ddc6acad1d5ea28176f33e623 - arm-trusted-firmware/drivers/delay_timer/delay_timer.c +0d32873988a7299902bc11961218f9034c494f5b - arm-trusted-firmware/drivers/delay_timer/generic_delay_timer.c +53e86084002c599472f206bebfee855f6de44547 - arm-trusted-firmware/drivers/amlogic/crypto/sha_dma.c +4e52ca94a347a31cef85fc1cbbd480490ff065b1 - arm-trusted-firmware/drivers/amlogic/console/aarch64/meson_console.S +340b2a1703f14c42abdade167ac06919ec7deed5 - arm-trusted-firmware/drivers/brcm/chimp.c +99056505e9afb98d0bf6b55cbc9c64814734d610 - arm-trusted-firmware/drivers/brcm/sotp.c +e8c6d05d166788f91925b45e27853f92f98251e5 - arm-trusted-firmware/drivers/brcm/scp.c +490663a4660be758e46f4878a43d7cb947b072e0 - arm-trusted-firmware/drivers/brcm/spi_sf.c +2f55d6018c61491a206aef1e089af2001db52b87 - arm-trusted-firmware/drivers/brcm/rng.c +9b9a1876a8dd35bdd34baeedd3e531617f4b2e03 - arm-trusted-firmware/drivers/brcm/iproc_gpio.c +9156a544c31c11073920be56fe54eb346a8b018b - arm-trusted-firmware/drivers/brcm/ocotp.c +df0910b2680c7694f0b75737fda7682a8712fb64 - arm-trusted-firmware/drivers/brcm/spi_flash.c +de63fe21caac7ce499c3a244965fca77766a1d19 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.h +653b6a961a19436e1cdba80c2b3b153c1d89a954 - arm-trusted-firmware/drivers/brcm/spi/iproc_qspi.c +2dc1c9032a1e64aa390c69bcdf0a42359e402b5a - arm-trusted-firmware/drivers/brcm/spi/iproc_spi.c +c9c8847417d95e3ba03ff5c005edbe8a088cee14 - arm-trusted-firmware/drivers/brcm/mdio/mdio.c +a70c96d7324a040b39217a657625b8b369ed65f9 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcmd.c +f9de2aeddc61d9a8b63a2bb3d10edd5e5459ac61 - arm-trusted-firmware/drivers/brcm/emmc/emmc_chal_sd.c +1e16b849ee30029570c17198cc65dd8c232fbd53 - arm-trusted-firmware/drivers/brcm/emmc/emmc_csl_sdcard.c +d89024f769cfa2a2d90ab6fb83691b494227d848 - arm-trusted-firmware/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.c +26f0937fbff1f7b2effe7d035d4e6d2c2a9c463f - arm-trusted-firmware/drivers/brcm/i2c/i2c.c +279f67f2161b938ba13883aeab4439e24b76eaf2 - arm-trusted-firmware/drivers/mmc/mmc.c +2e8560e1fee7e0d9ba844f802772a8be3e6be7ad - arm-trusted-firmware/drivers/measured_boot/event_log/event_log.c +150bd08bfbcc1de20e05b6d07950021df0a46322 - arm-trusted-firmware/drivers/measured_boot/event_log/event_print.c +3325b2a520df18fb8bd8859eafba82aa1c89eec1 - arm-trusted-firmware/drivers/rambus/trng_ip_76.c +8e0afaebcd5d1ed41d30457bdb8543f3617640eb - arm-trusted-firmware/drivers/synopsys/emmc/dw_mmc.c +1d5e94fb3b734e7c9eb7b1628230f3d140a8e958 - arm-trusted-firmware/drivers/synopsys/ufs/dw_ufs.c +366c422651f720b64f0d606e537b12713c405d8e - arm-trusted-firmware/drivers/fwu/fwu.c +e5c3d888d354f7edd20c09b85d55293a3302d4ad - arm-trusted-firmware/drivers/partition/partition.c +05e51189eff0f94ffa7616efa4a5cd4c11a90a81 - arm-trusted-firmware/drivers/partition/gpt.c +bb264060cf147f5fd4feae216d66ad8c9c66f891 - arm-trusted-firmware/drivers/io/io_fip.c +78ab979470824d9703736ca6da3735d7c11fcba1 - arm-trusted-firmware/drivers/io/io_mtd.c +88a6a7b48a8b3da04a2a2bb9d5bcb70f03c372d3 - arm-trusted-firmware/drivers/io/io_encrypted.c +fe0286bc53aeb4cae686fb9d63d9ffe2283cf119 - arm-trusted-firmware/drivers/io/io_dummy.c +a28c85766eedc583fd38c5f1cb94aa9d5caf8935 - arm-trusted-firmware/drivers/io/io_block.c +858e3130488ef425faa5341098347a0cd446a49d - arm-trusted-firmware/drivers/io/io_memmap.c +2975f82e852f74ac877b00bfa9bcaa8c3baec7e2 - arm-trusted-firmware/drivers/io/io_storage.c +78d0bb21fe92f684f28119691c173b36006dbbb5 - arm-trusted-firmware/drivers/io/io_semihosting.c +5bf3028d91229a2bab7d9be2fbf3db5b63dbdac5 - arm-trusted-firmware/drivers/cfi/v2m/v2m_flash.c +46c3bb0a303498f1a79fd2bc48b1becffddbfd71 - arm-trusted-firmware/drivers/mtd/spi-mem/spi_mem.c +47003ec4d5650ecd811ae9fe4404621c369f61c6 - arm-trusted-firmware/drivers/mtd/nand/raw_nand.c +010e3cc7bf5be7ac20119f77ab261bdf528f2d2d - arm-trusted-firmware/drivers/mtd/nand/core.c +122bf5d15d1cdbcad5bee82566c57049e3fc5bb5 - arm-trusted-firmware/drivers/mtd/nand/spi_nand.c +eefd56420faeb9d836077b23eea175eb7e022871 - arm-trusted-firmware/drivers/mtd/nor/spi_nor.c +b601addd7e20d9e7f019014eac336024a1e57b8f - arm-trusted-firmware/drivers/ufs/ufs.c +1fa3c347f937895d6e5869cff641faf35158d0e0 - arm-trusted-firmware/drivers/intel/soc/stratix10/io/s10_memmap_qspi.c +639d42262958e84f1bd83a574ec62649802513a1 - arm-trusted-firmware/drivers/auth/img_parser_mod.c +c16134fe5a7698bda76781fff2f959b23e9effe3 - arm-trusted-firmware/drivers/auth/auth_mod.c +a7feb170a20eb5ee10c9d197dc0097785f67943b - arm-trusted-firmware/drivers/auth/crypto_mod.c +bb94b0069937941cd0d158f609df28bc66e7f7df - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_crypto.c +aa57938a1ca87b1c2d69b27e2cb210dd52b72f92 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_common.c +ca516c7a1c11d4ea7d2a36636ad140645e6b3ef0 - arm-trusted-firmware/drivers/auth/mbedtls/mbedtls_x509_parser.c +ea1ff4dd6466dd5bba2280092f7ad0037f0e3791 - arm-trusted-firmware/drivers/auth/dualroot/cot.c +98690b7915852b4a6a1950623e848b467186a09e - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1_r64.c +62b38ec608a3b1763bbd31827be93360dc10c4d3 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl2.c +fbcbbd0aa417147f5e544e91c47edef162f6aa41 - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_common.c +efedb0eaa10e440edf6b73b4b2df6a6d164066da - arm-trusted-firmware/drivers/auth/tbbr/tbbr_cot_bl1.c +0931c7209af239bcc95387de431d932bf01175ec - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_plat_helpers.c +1527e9ad692eabc3e379a8f7f0a4eecc68b9f9bb - arm-trusted-firmware/drivers/auth/cryptocell/712/cryptocell_crypto.c +6e817c6fdbf62d3e636fe69752f1f0bb9281c3a8 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_plat_helpers.c +07632d2568b5990250c7539319c93e9b64c05004 - arm-trusted-firmware/drivers/auth/cryptocell/713/cryptocell_crypto.c +2802b6fb340525ddb96baca00341a6a25f703c74 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.h +4186c27c3850565f08118234f39f3224a0094fb6 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_common.h +fa11d997720f3e8e38a41e393a485385f56a4981 - arm-trusted-firmware/drivers/renesas/rzg/qos/qos_init.c +4fc3b8212dd33e6a33a9bbf4b96d0ffdb7032083 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt390.h +7262dc7de38f8216be32a2cf973c4077da6a5ced - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.h +e074216ecbdf97f24cb3e12cc7f5d8e5c99721b5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt390.h +1ebeec74f28d94d33ad88f9e3cb8abeb2ff4462b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat390.h +49c7e8143b952aa89509efb296f2a3d848f1fcf1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.h +3ebe3831af51ff6dd31f04c19ed726ea47d12ffb - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_qoswt195.h +ba3202740e2551524bc86abc295cc82374fea770 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat195.h +17c66fa0e8ef76563d00547c6c281d4fcd025dbf - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10_mstat.h +4120c27434066995e75487d1311e78e2dcf57cb3 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v10.c +5cf260b6fef6d9a6c0ddbe6c45bed9d54daf027e - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.c +c9bbbceaf55fd9cdcf0943b427f8b302c902199f - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_qoswt195.h +ae6bc783ddb0cb6feec22e234a5383965ad75a8b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30.h +046e1d3b18c291d99e7f1f95658f5a6bb9f7c207 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v30_mstat390.h +8146506bb0d47e4499b692d8a0b0d168c697db9a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11.c +d1c7d38c66ff34e537261485132cb0beb3ab4765 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2M/qos_init_g2m_v11_mstat195.h +0d2a4685c4bd34d6ec121270bc38ec212c7b1e0a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt390.h +2e4f2532cb1b9aee27f82677a76fc8598ae3e720 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_qoswt195.h +05c9d8b400726b0d87a72783f40f17a2a061c31b - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.h +6a2add07f71f904a80881847adbb4576860c245d - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat195.h +a084e9fcbfdc195d063eee7f1561a5b311238aa2 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_v30.c +6bfed6bf0d3eb45780762fbb929d5d57eaeaaedd - arm-trusted-firmware/drivers/renesas/rzg/qos/G2H/qos_init_g2h_mstat390.h +d0a732f21ab78828c622303f2eb7f2ab8e85c92a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat780.h +98bd2a7be1d0dcdf1cc534ac4dfa0adf7b3bd752 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.c +635fa9d52596ee34cf2cbf85617657684fb653c1 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10.h +d1016ddc5354d7e63a3ef654ae6899c8c078ce00 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2E/qos_init_g2e_v10_mstat390.h +33416277d7d82e170d6f1d7ef205870c003c8aff - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat195.h +282efe9d196e496f3be41e3be701e9dc02c1bfc5 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt390.h +330b138c5e24e14484fbdcc38db468c06168918a - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_mstat390.h +80605fd39dfaf3536b1da46e80b450127a5ac723 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.c +7c37eb45f9f11ee9f370e775f741dd1075944a69 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10.h +3ca890e94b8943ef7719c09f20c3a71ad9e60295 - arm-trusted-firmware/drivers/renesas/rzg/qos/G2N/qos_init_g2n_v10_qoswt195.h +fe1e1e2a68a2409c85008f78bb7f4048be6dc1c9 - arm-trusted-firmware/drivers/renesas/rzg/board/board.c +8ae500671f7227739bb3b389ee74418bae4974ee - arm-trusted-firmware/drivers/renesas/rzg/board/board.h +45854b76c28a405b83a3ad2f7975038a6a8a34c1 - arm-trusted-firmware/drivers/renesas/rzg/pfc/pfc_init.c +fb75fabcb7a5cccd23dafcb83996362d131b28e4 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.c +3e16dde8ddd77df4368ed97df8dedfcd363f2195 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2M/pfc_init_g2m.h +08bed1ad3f35993a6b63c3a553c0cd1f817cdf72 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.h +313d480f7fd9b09de41195d3fe75df7e06b8fad2 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2H/pfc_init_g2h.c +fa65175525fa82bac340b43f6d95f68574a6cd59 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.h +987d099de106542df3c8adb7613b27edcfd5cb76 - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2E/pfc_init_g2e.c +42cec83a589b1e8282a06dc496c09fa4d8019bdf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.h +9850cfe7fffb94712b5526ba4dd947a9cec6efbf - arm-trusted-firmware/drivers/renesas/rzg/pfc/G2N/pfc_init_g2n.c +96023687d119cdc2a88f0f96847b71070be44d0e - arm-trusted-firmware/drivers/renesas/common/common.c +d4b40e69b2bea69f35d8d12ed25d623c4bafc89e - arm-trusted-firmware/drivers/renesas/common/pfc_regs.h +eb5eaa562bc901bbcea6e5e722e629a4ffe14fa3 - arm-trusted-firmware/drivers/renesas/common/ddr_regs.h +b31c95edffddbecf9d51e7ba6d57f59b07381718 - arm-trusted-firmware/drivers/renesas/common/qos_reg.h +8e9c2ed157c641c0bec372759c5f0d1a29495392 - arm-trusted-firmware/drivers/renesas/common/watchdog/swdt.c +f6c548f6ac120c9eae0551d5ca111a654a28e241 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.c +04d76f4dff98e3290cc3b56689eea7eae6973401 - arm-trusted-firmware/drivers/renesas/common/avs/avs_driver.h +197394f4b9c3387bbbe8ade40aed6fd5ba67cd49 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.c +81389d507ab4f6c15c8302b9d4a550e929350170 - arm-trusted-firmware/drivers/renesas/common/iic_dvfs/iic_dvfs.h +ba0424f1fb02f541d26148c808ee8576203fae19 - arm-trusted-firmware/drivers/renesas/common/dma/dma_driver.c +db6311bc705a8c1d60a616425947adcee84d1063 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.h +724917ae7e24d07722880d4b74d6a9730336be06 - arm-trusted-firmware/drivers/renesas/common/delay/micro_delay.c +648595ebf99d157ff5bec437919b34a18258b411 - arm-trusted-firmware/drivers/renesas/common/scif/scif.S +23d0235cda981605fc638d9031316ff71003ea9f - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_driver.c +5737620466366563b17443ac716f582a4a0e1e8b - arm-trusted-firmware/drivers/renesas/common/rpc/rpc_registers.h +7c0cd66835bf24e2086572d390e9e42847b2cc7c - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.h +7e6776a062962247d7356aa2a4e3db30e8ec9a35 - arm-trusted-firmware/drivers/renesas/common/io/io_common.h +d954a56fdaa915b42433e7f02b933ff5a7f4d553 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.h +2a9a321a7d2d3f302f63914ea61c0b24ef77ae46 - arm-trusted-firmware/drivers/renesas/common/io/io_memdrv.c +94592c6b00d8f46906214144913018912da2cdb1 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.h +cc69cc1cdbf38f685bfb8c4e843841fc12c17072 - arm-trusted-firmware/drivers/renesas/common/io/io_private.h +ff8a273a7c0157436d3d58824bb0822c1e4c8880 - arm-trusted-firmware/drivers/renesas/common/io/io_emmcdrv.c +4c9c3edfff804648e78fdb6173511fedc8d655c9 - arm-trusted-firmware/drivers/renesas/common/io/io_rcar.c +b95edfb86992c01b146085a6a3a6fa260f62cfb1 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_config.h +1f0175831d01e9a83091abf339b764707fa15732 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_interrupt.c +da6c00a918a45fb21f34a94a1153a619126f856e - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_init.c +53d888462033b6fd9f510352b7ef5a997db98215 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_std.h +1806c4fed1e8009245193be345f42a0bc99a88ff - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_cmd.c +d18f211fb0f471b7b72797133ccf3a89ff3fe561 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_mount.c +e38e56acce60e8f8ba79bf52ebdccbfbb84e60e7 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_utility.c +7526f3b1661670d99bae978d76b826697f8eafcc - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_registers.h +e3d0fe455add19648ab1dab17abbf8a036851187 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_read.c +9c78d4764ec4942f586af7e70fa2906b79718e72 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_def.h +ae1066faf4581bdf2b74fc79c6880b4541c50262 - arm-trusted-firmware/drivers/renesas/common/emmc/emmc_hal.h +3a2172abc0cd0c826ca5c1f958e47c616e2d0c2c - arm-trusted-firmware/drivers/renesas/common/auth/auth_mod.c +f81a020bdd63ac732719bf014ffb749bc0f35bba - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.h +e285ce8fb65a4579da74f1406d12000d292f45ad - arm-trusted-firmware/drivers/renesas/common/console/rcar_printf.c +26bba8a723b7f85d907e8da853e41cb0ec1bc46c - arm-trusted-firmware/drivers/renesas/common/console/rcar_console.S +3567bb0ce5e977a1fe4ee5a8fed4db8dc67ccca3 - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.h +bbe9ec354aa9a66731a4a68b1214e7c88433e78e - arm-trusted-firmware/drivers/renesas/common/ddr/boot_init_dram.h +f6092db4bdf15b55332ebf36fb13af42ee1b8f8e - arm-trusted-firmware/drivers/renesas/common/ddr/dram_sub_func.c +24c58c71c66617770ef83cfba554a31128de8f35 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_d3.c +55a51a3127d0a24e084fc5ad73c0ddc5d5b2fe3b - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/boot_init_dram_regdef.h +b5212a79f0a8c1abb0c5088b5730968747253bd9 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_v3m.c +f5798c0927729a362f779e583438e52a2da51faf - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_a/ddr_init_e3.c +b014a41cf8b77ed434dc0aaeae7efd1a154065c4 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/ddr_regdef.h +94ab11fdbe4c8a942cb23f6604e8a013e0c6c083 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_config.c +178140849c7796c20b8a14ef9af086d4ffb485f1 - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram_regdef.h +1f8f7c4a456ce374f80860dcefeb3a1eed7e1b7d - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3n.h +d8448100b460ddc591a2eefae6d2d0abecab166a - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_m3.h +e40feff18e0868d48c4bdcc23024fa824eb612ad - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3ver2.h +56a16c8b12428935f7d194f7bdbda33ebc432e4f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/init_dram_tbl_h3.h +fe75f352b6a7e1643f0857f578e85a4c301d504f - arm-trusted-firmware/drivers/renesas/common/ddr/ddr_b/boot_init_dram.c +fe518460e8298941fd3ff47df2330afba56085ca - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.c +08b9d46b2389e6316b27218e1e80071e3891915b - arm-trusted-firmware/drivers/renesas/common/rom/rom_api.h +c11df9b69a5d8144823fe6b09c8aee8c6dac3579 - arm-trusted-firmware/drivers/renesas/common/pwrc/call_sram.S +11290dbdcaf0fc67e9947d59e3177ac503f1276c - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.c +6173062885150750f1c102edb35796e50d6a012a - arm-trusted-firmware/drivers/renesas/common/pwrc/pwrc.h +ba3873513a76a74ceff9f6818187870191d1faba - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.h +c2b1735bd5896fe759c99cc8b22c392af5bb841b - arm-trusted-firmware/drivers/renesas/rcar/cpld/ulcb_cpld.c +50775f0e3315375d2b392a52b57df2e19834d985 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.h +cb0d0e4e929b276e850cc30884ddfd8846a9048f - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_common.h +bab2ef59fc4f4088c90466ebb4823889a1bf3996 - arm-trusted-firmware/drivers/renesas/rcar/qos/qos_init.c +bd60292a364659d7f11eeecac384213969357c04 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat195.h +700940ac5d64f4902064fbf6670e6e59150d9fd0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.h +f5fd4a9a5d50b214bc6ebdebed3c35ae0f1f2be4 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt195.h +8eea8028ec6b2cd4e6e1c5e0a8d8fd9af01ff4fd - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat390.h +f0db0106cc97b359f7a0ab316784658b79e9d544 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt390.h +12e645da3e7fc81893eb36796412a928fc06e57e - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30.c +7131d3227d06785258892fe7a42df3c91cc8c9f9 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.h +824a3717d01b009cea509c61015e64d1722fc212 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10_mstat.h +a6934a3af85414d49cca5e5d99e162bbe9ca133b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.h +f8c08f7eee854de735ce3c60a3e23d3f74fd73f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_mstat195.h +23507b41fbfc9c3a39c4c3f5daf7562d67d10b1b - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_mstat390.h +6ea58175e376d869ac3c2a4f103d934df3c2c465 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat195.h +7c805660400d6f609148f8124439843b39232355 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.c +59c0f7639b01b8af843d8142eb013348e6a1ba18 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30_qoswt195.h +7329eefcfc343e2cafffcbc3a208b34789e57968 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3n_v30.h +b7890473a9576eca8081825037d037349512add5 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v10.c +8dbbe234d937dcc1acc85648ecf831824fb5fa48 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.c +bc682493eeddc9cec3b24b5dd37418a00e0c064a - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20_qoswt390.h +dae17d610957cce3799fa9c9946c0196c67d46ac - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11_mstat.h +8623a6e816d06c37ce20ab1b6e410fc23c052d43 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_mstat390.h +504bd76520d259ea03e8b93380c763a3c17ffeb0 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt390.h +630b48fd35a697ed4d1daa03bfc67d0d299a2776 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v11.h +811eb1fecd60de207e7c92a5986acb80e7ecf0f3 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v30_qoswt195.h +8b5287985d180436c31df99d29c586fa8ddf0f26 - arm-trusted-firmware/drivers/renesas/rcar/qos/H3/qos_init_h3_v20.c +6dea13df81dd5a2913039ff42dcb9216eb922586 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat390.h +114cb09f888b76f0b1356fb126a483be754d2cd6 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.c +81d4efe56b1d9f4c44c942700d01a9ede1677bae - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10_mstat780.h +48f7ee0d258f661040d23d898a98d0bc9c066613 - arm-trusted-firmware/drivers/renesas/rcar/qos/E3/qos_init_e3_v10.h +d50c2a6a6c4e4910f4fabd7c774ce1986b97ea19 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.c +21ada158d24d4473b1e20f73c499f4d5600e3c8b - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m_mstat.h +70405034a321bd4ced206115508ab438f2f536f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/V3M/qos_init_v3m.h +f1b2a6505d48a1a6566f88c1e80b4f27cb09896e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat195.h +8c12bb78bc33032ca8926351b3eedbe5b2b4c81b - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.c +8aa68f57355243a72231c3848caec899565cf5da - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.h +7e2114420402542982a251fc6b54152f32b0dd88 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11.c +10f2fc91f336438e4f2073ea1a665d5d67fb79c7 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.c +77f8e84524f8a31cd4e5261eca8974eec4bd131a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat390.h +2717b8ac46d4da69ba6b99a7f25097f9e314aad3 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_mstat390.h +2a066b2fcd7583651082fa57bbf12dfe4352326f - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10_mstat.h +a3a502f90241a6c8f8be7ed9af2e0b6cfe9e59e5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt390.h +7cbcad70fd46dc5761bb14b31f104d6806752af8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30_qoswt195.h +758dc7396c31d1186836e5ed6c7cafd0a678b4f6 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v30.h +6b699b1443429c5428b8a7056804ed3da10f02f8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt195.h +bf20ed2160ab9535cba30cc680a7bf881b5a442a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_qoswt390.h +a6126e66f35f584f38379a6ee5529fed08edf8d8 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v11_mstat195.h +ec016158b5c3b5502240e5835181cf7929e6fb5e - arm-trusted-firmware/drivers/renesas/rcar/qos/M3/qos_init_m3_v10.h +aa7f8d7b49fdee6efbfc48acf8e8bddb01fd52a4 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt195.h +4c577e5e3e00506da4ab89990b8dae561786e20a - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_qoswt390.h +3d6b988f34914a47bf479526f1f10849a2ae3ae5 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.c +96354da81a56cb6373ff756124b8eee42409bfca - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat390.h +60944cd086bb0354e4747ae185b5149ae3f85f72 - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10.h +2bb5c4f7c8795b5aeecf3a8997f515c4890514ae - arm-trusted-firmware/drivers/renesas/rcar/qos/M3N/qos_init_m3n_v10_mstat195.h +fb1b1122066b12b184582d53d643246b1a414b3b - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.c +b8ba25ef62d360d72dd17d26934062bc0eeea376 - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3_mstat.h +c2f5bcbfd3751341e871e36cd4d2f278b2a4150d - arm-trusted-firmware/drivers/renesas/rcar/qos/D3/qos_init_d3.h +cf8b9626df3b3f81ae4674acc1f379aaf9eea1b5 - arm-trusted-firmware/drivers/renesas/rcar/board/board.c +ef114d85e930b49c92bef6398031e37cb6afcbb3 - arm-trusted-firmware/drivers/renesas/rcar/board/board.h +3ae8c8947fe42e322d70fb7903ada181bfd006ed - arm-trusted-firmware/drivers/renesas/rcar/pfc/pfc_init.c +7a112959b420ec60382c2d5688ddced8ca0affd4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.c +5eda21c234b108bb6ed5b65d5e58825ec9ac0210 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.h +8472797f3f7c7a334dd21719d4dd718c5df01e47 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v2.h +83dad15a244674be1d30dc0200428aa0e82090e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/H3/pfc_init_h3_v1.c +c7dfaadbc4d96d1fceadc4fae5536b1e1a9cdd59 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.c +c248864592a61213518c8881be85e4f65fe0a3a2 - arm-trusted-firmware/drivers/renesas/rcar/pfc/E3/pfc_init_e3.h +b9d9644305cbbf1e06e176a46903dd18819761a4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.h +cc2f31ac87f68592bc44f9d3435c79d99e7dc0e6 - arm-trusted-firmware/drivers/renesas/rcar/pfc/V3M/pfc_init_v3m.c +6fb897befbc4164b71d8975b2d5322b9e77412b4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.c +3802b683cd17e49eba932611e33205446291cde4 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3/pfc_init_m3.h +1a2dd6951973faf90ec734331605c3fb336bde9f - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.h +ed9b151f951387e31b4a9fc5a26f0d4621beaf13 - arm-trusted-firmware/drivers/renesas/rcar/pfc/M3N/pfc_init_m3n.c +a7f9c2cb5010e2bfe1f501830a449d314d447ce7 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.h +6465a6a55c524b8ffb1dca351757b9d96e79d203 - arm-trusted-firmware/drivers/renesas/rcar/pfc/D3/pfc_init_d3.c +c83fb1312ae05c6e624572806f085c6919f189af - arm-trusted-firmware/drivers/coreboot/cbmem_console/aarch64/cbmem_console.S +1a38fc90bd2ad3b33e7c09de2e338d2f993efe99 - arm-trusted-firmware/drivers/console/multi_console.c +48cb55cb2ee35cd09c7a0759acecc0e5facfe576 - arm-trusted-firmware/drivers/console/aarch64/skeleton_console.S +b837201998c7093cf24c9131e39734b99ab455be - arm-trusted-firmware/drivers/console/aarch32/skeleton_console.S +c8524aa6f76d32913ffaffda10350b753e429b5b - arm-trusted-firmware/drivers/marvell/ddr_phy_access.c +77e98f136f88749eb01cf7092f9d086cae652384 - arm-trusted-firmware/drivers/marvell/thermal.c +f00e9719e8be0259cb5e171298f2ffb0d09c4fef - arm-trusted-firmware/drivers/marvell/gwin.c +e082e89bfcb90fcea87099285d6eb142fff1f589 - arm-trusted-firmware/drivers/marvell/io_win.c +857ba1731ec174905f4cccd68d02bdd3abf08b6e - arm-trusted-firmware/drivers/marvell/amb_adec.c +b724830f0762dc7701cc9fd88c863c7b53f405c5 - arm-trusted-firmware/drivers/marvell/iob.c +e352b30931747ba506a85329d7c6fe69935dd5b0 - arm-trusted-firmware/drivers/marvell/ccu.c +a275b56587e6c0c05df6a7985ad0cf0e2216e4f8 - arm-trusted-firmware/drivers/marvell/comphy.h +6dc9f5af1b3c165888d4faae36b6da72adb6faf0 - arm-trusted-firmware/drivers/marvell/cache_llc.c +c523b2dcff8e39c5cacc416584d42aa530a93315 - arm-trusted-firmware/drivers/marvell/mci.c +6256615787b3a1bb1f9b4fc3d64794006722b859 - arm-trusted-firmware/drivers/marvell/ap807_clocks_init.c +d0ef41df34b7a9ed1d587f10727ba0ee57d04c83 - arm-trusted-firmware/drivers/marvell/ddr_phy_access.h +6426cc04f9e4ae36d19a6624130d17fd035ba491 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.h +282cbabd8ee584e3d6c2657cd202c11bbbf31685 - arm-trusted-firmware/drivers/marvell/mc_trustzone/mc_trustzone.c +cd9af6970ea49226ec63b2b04d0b06b86d503eae - arm-trusted-firmware/drivers/marvell/mochi/apn806_setup.c +bb5f60fb041d3fbc6812ce56b8976c686be8105a - arm-trusted-firmware/drivers/marvell/mochi/ap807_setup.c +9a1f55dbc2fc4e8ca97f9af3e7d435f1bddfd83c - arm-trusted-firmware/drivers/marvell/mochi/cp110_setup.c +db0bb43d5c002bc3633403571c9e8c06da7c0ead - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.h +4fc44238fa459de070b3ffae100986f736c5e3d2 - arm-trusted-firmware/drivers/marvell/comphy/phy-default-porting-layer.h +041d0631d9cb0fe39ee3d1f8d20629d3d2225f86 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.h +1ceb9ca7a78559ee70cb2833d391d99c2ccb3334 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-common.h +52740dfd3574268d954c81e6a708c55188bca7e1 - arm-trusted-firmware/drivers/marvell/comphy/comphy-cp110.h +6b20ef2ea4fdeded083ed64a100d2e10cc8c4fdb - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-3700.c +dc409874b01f2f616b65f4f9e8497ba172fb2535 - arm-trusted-firmware/drivers/marvell/comphy/phy-comphy-cp110.c +02f2c79a0efffc643c301848b83a26b232291cec - arm-trusted-firmware/drivers/marvell/uart/a3700_console.S +10ce6fa5d5bbc4205013818f591e235cbcadccd1 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.h +f89de6e4fae5d6f6d1778f6c5a92d7f25ab403b9 - arm-trusted-firmware/drivers/marvell/mg_conf_cm3/mg_conf_cm3.c +e586fb95d55e301bd75a1db9d6ac7b843f45984f - arm-trusted-firmware/drivers/marvell/secure_dfx_access/misc_dfx.c +5a1bf4459a810008901d22e77f2e66c2af4ca7f9 - arm-trusted-firmware/drivers/marvell/secure_dfx_access/dfx.h +12a1ccf32210f9e1106d8d27942f264ab96f58fd - arm-trusted-firmware/drivers/marvell/secure_dfx_access/armada_thermal.c +627856de3e6c6e4ff2ba2bf3dc3803a13f08d1bb - arm-trusted-firmware/drivers/gpio/gpio.c +b98ff0dbd7f6535bc154869089df5f242b23f799 - arm-trusted-firmware/drivers/ti/uart/aarch64/16550_console.S +cf240f037fbcd65fb3db19fb6994d2f4aaaa52f9 - arm-trusted-firmware/drivers/ti/uart/aarch32/16550_console.S +0fc051c6d2c2e54cfe39b37cf1a1f85f883f31e3 - arm-trusted-firmware/drivers/usb/usb_device.c +5506b6895fb8d1c468b2bcaeb55a18fba8ecdcff - arm-trusted-firmware/drivers/rpi3/rng/rpi3_rng.c +ecd654f25b5590f6fd4dfb3c349577da03a78337 - arm-trusted-firmware/drivers/rpi3/sdhost/rpi3_sdhost.c +1529e10e42582df4a41e7632598e85d97dd59ebb - arm-trusted-firmware/drivers/rpi3/mailbox/rpi3_mbox.c +9383db5e25bb3e3bb240d302eb1e2c81b067f1fd - arm-trusted-firmware/drivers/rpi3/gpio/rpi3_gpio.c +c8a2a84e6453323aa9b1b1cd2a29c6ad56036b5e - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.h +abd5092c485b60d2dc6d910618e64227d766ff87 - arm-trusted-firmware/drivers/st/clk/clk-stm32-core.c +09b3e4f32ad36ab93f598fd53971e18cdb4eed9f - arm-trusted-firmware/drivers/st/clk/stm32mp_clkfunc.c +f0d5a528ed1a6d54f39bc84a21586d25029d60b2 - arm-trusted-firmware/drivers/st/clk/clk-stm32mp13.c +6bf9357dbb7589b0078e1896de5a58f760761979 - arm-trusted-firmware/drivers/st/clk/stm32mp1_clk.c +dc5909c790f8267bcb9bbc047b904810550cb78b - arm-trusted-firmware/drivers/st/pmic/stpmic1.c +31f2612aff5d24d64b3826cbe5c7a9f93ff7eb70 - arm-trusted-firmware/drivers/st/pmic/stm32mp_pmic.c +a9d894b2465b17dff1217d99ed6752861aadc069 - arm-trusted-firmware/drivers/st/iwdg/stm32_iwdg.c +2f6084a9d8f84bf599746cd3288b02a0d4755d3c - arm-trusted-firmware/drivers/st/bsec/bsec2.c +943095f905fcfc655c86f6aca5d3287192546feb - arm-trusted-firmware/drivers/st/spi/stm32_qspi.c +f73a865d9abd49d6a37720d4000b86bc1f6b362c - arm-trusted-firmware/drivers/st/mmc/stm32_sdmmc2.c +f71262877fdd2511c5cd086021c2af9d763f9ec1 - arm-trusted-firmware/drivers/st/crypto/stm32_hash.c +1c77b842fc094c883b8e6abc3522e2a5ed4ebb3d - arm-trusted-firmware/drivers/st/regulator/regulator_core.c +f01b87c2b668e9cc15338565f21d115dbeaf62cc - arm-trusted-firmware/drivers/st/regulator/regulator_fixed.c +27adf1000d6bd7ce04979d79256995a5fbb83b5f - arm-trusted-firmware/drivers/st/io/io_stm32image.c +baededfb86b8f337d27173f84b9cc1bac0556f62 - arm-trusted-firmware/drivers/st/io/io_mmc.c +67125c1a18a170ed78552d01772ae577463e506a - arm-trusted-firmware/drivers/st/uart/stm32_uart.c +ab1a40e17764664876964683ffac32bd86def125 - arm-trusted-firmware/drivers/st/uart/aarch32/stm32_console.S +6b50346722811da8d96bca6f539f0d5e772d467e - arm-trusted-firmware/drivers/st/reset/stm32mp1_reset.c +76ef733f3d1d7b8a934c301f2e05724663827f36 - arm-trusted-firmware/drivers/st/etzpc/etzpc.c +d45d152334200ea2acdee930619eff5f1fbbfb5a - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr.c +9e30ea137b7c1d34dfae32a3c5180396f6fa8bb1 - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ram.c +f5e59973fc84a601316882610f6aa00a70ec8e1f - arm-trusted-firmware/drivers/st/ddr/stm32mp_ram.c +88fb79719982f0a2687d7f693109e940e3cdba9f - arm-trusted-firmware/drivers/st/ddr/stm32mp1_ddr_helpers.c +5ed9e1be8f844737db535ecd2e049e7d820af601 - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr_test.c +4a37a23560ebb26a66cba83a6a77aafee65a783a - arm-trusted-firmware/drivers/st/ddr/stm32mp_ddr.c +5324162d65037588a526042c0e40fab08cab0e73 - arm-trusted-firmware/drivers/st/gpio/stm32_gpio.c +07bb0b5fe46d4ebca6c6e1feee9d8a9e7d83d6a5 - arm-trusted-firmware/drivers/st/usb/stm32mp1_usb.c +def00bc3c52b54611ea6f11a6f5206cf0b3cc08a - arm-trusted-firmware/drivers/st/fmc/stm32_fmc2_nand.c +9d7512560e4e1f8767fd18a115db9ee7ff100448 - arm-trusted-firmware/drivers/st/i2c/stm32_i2c.c +1c35b7e5adf1b63d6732729e7c2113d1ea1a74fe - arm-trusted-firmware/drivers/arm/smmu/smmu_v3.c +28b6eb0d5d5856997722ea707dd42c5ad7448dd1 - arm-trusted-firmware/drivers/arm/gic/common/gic_common_private.h +47db01b738865c987fa5dbb3656b6b1dab2df5d7 - arm-trusted-firmware/drivers/arm/gic/common/gic_common.c +0325f0421798955c9df7f963bd6f917152f3f9fc - arm-trusted-firmware/drivers/arm/gic/v2/gicdv2_helpers.c +20000ccb435ae8423c5a2294ecb47fd7961e90f2 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_helpers.c +ff4e151fab3e5a027139f8ccb78ada694380998a - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_main.c +8f83171e122be92a8d5e4b0c5ecb35e4918ead83 - arm-trusted-firmware/drivers/arm/gic/v2/gicv2_private.h +0cdfd59744b1db36c123258d6ed80a21b369e0cc - arm-trusted-firmware/drivers/arm/gic/v3/arm_gicv3_common.c +209b5b0ef79ee3104941281500febec4c3fa7e19 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip_private.h +51bb1f43fbcc00eb3e6ca46f5ac069a6a4af19db - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_private.h +702d95a03697ab01bc50559d686681042cec6d16 - arm-trusted-firmware/drivers/arm/gic/v3/gic600_multichip.c +457472881d1edadb4da2a64ec3252636e576b054 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu.c +e1cdb7a1b79c3634ed881efd97a423fca6741350 - arm-trusted-firmware/drivers/arm/gic/v3/gicdv3_helpers.c +1b9888584629f7d2bc9379be5294ff21dd7cf240 - arm-trusted-firmware/drivers/arm/gic/v3/gic600ae_fmu_helpers.c +d424887230b1ad1f25384d0cc4cdf433911a1004 - arm-trusted-firmware/drivers/arm/gic/v3/gic-x00.c +ba14a8e6c0af402979f522f4672707b451266d44 - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_helpers.c +d830753dc30671474545841791bb3ec230bcb2bf - arm-trusted-firmware/drivers/arm/gic/v3/gicv3_main.c +73bb04bd3b4d9fbaec23c129c93b2e89e276c7d5 - arm-trusted-firmware/drivers/arm/gic/v3/gicrv3_helpers.c +4d212a96f8ab9a54d15002b53f16df7bcd046e6c - arm-trusted-firmware/drivers/arm/ethosn/ethosn_smc.c +79f4ef16ca7e0a07b86de03a9a04dcb9c6c3673d - arm-trusted-firmware/drivers/arm/ccn/ccn_private.h +9cb6b217ac9499219fd1bb05530709e1ed53c3ff - arm-trusted-firmware/drivers/arm/ccn/ccn.c +960e4d083c1d4f31df54f443dbe23554889af0de - arm-trusted-firmware/drivers/arm/pl061/pl061_gpio.c +7aaa9f31ec7c9d36e48fb2d95a6b3895cbef43ae - arm-trusted-firmware/drivers/arm/css/scp/css_bom_bootloader.c +cd0ed71ff125804ccf8f2d187005ce075bc2b8e6 - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scmi.c +80686a47331e2b609be783462ef53eb0ad73279e - arm-trusted-firmware/drivers/arm/css/scp/css_pm_scpi.c +4faf8ddbac2e8bfc4ab77ba7365ff0c50187a2d4 - arm-trusted-firmware/drivers/arm/css/scp/css_sds.c +12e2ef4efff1bfd584d3424cee31bbcbaf0f9a1c - arm-trusted-firmware/drivers/arm/css/scmi/scmi_private.h +1530ff134d89ce18b2380b7d03828ec84c8eca25 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_common.c +e76c3b0b1252232e7854b8af9db8a9ce94192cd1 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_pwr_dmn_proto.c +50defd7dfa4e38cf230f830fa7e03358ccfcdbb0 - arm-trusted-firmware/drivers/arm/css/scmi/scmi_sys_pwr_proto.c +b81d931e597cde97768e39fdad4325133c31b76d - arm-trusted-firmware/drivers/arm/css/scmi/scmi_ap_core_proto.c +13cf0f0a02adf3ae0f9e2bdbe493ba7c9b58ddf5 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.c +e4a68362e5109d4e46f1d720d9b02c8fb20a88c1 - arm-trusted-firmware/drivers/arm/css/scmi/vendor/scmi_sq.h +9b45f1ebc9a189e59d1fdade91bde81f2ea110c0 - arm-trusted-firmware/drivers/arm/css/scpi/css_scpi.c +595853f3864138408a5e5b51034dd366cc9a3b7a - arm-trusted-firmware/drivers/arm/css/sds/sds.c +9fdd5749ba87bd5ded91306fd6826fa2cf990806 - arm-trusted-firmware/drivers/arm/css/sds/sds_private.h +e609accbdf6501d2f83400b84b7690aaa2bca38a - arm-trusted-firmware/drivers/arm/css/sds/aarch64/sds_helpers.S +f55aeff6049754049ad1b23958094a7dd255200f - arm-trusted-firmware/drivers/arm/css/sds/aarch32/sds_helpers.S +6dfee94cccd0efeaeda770f83e1d10227886d137 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu.c +4f259f1ca4437445346bfd338702c7c257c31470 - arm-trusted-firmware/drivers/arm/css/mhu/css_mhu_doorbell.c +fcdbc7d1ba6dd59840b82ac787ebf67cf36fe4eb - arm-trusted-firmware/drivers/arm/sp805/sp805.c +c0c5af62081f2d6628a6de94cd6a9507723228e3 - arm-trusted-firmware/drivers/arm/pl011/aarch64/pl011_console.S +91c557c46edc8be3bd2e4c2efcf9ef8693a9fc0e - arm-trusted-firmware/drivers/arm/pl011/aarch32/pl011_console.S +3777989a45b625cf209fc89bcf8a91a468f52a3a - arm-trusted-firmware/drivers/arm/scu/scu.c +1c897f5bd19b9a4c18e905afda282375cbf4f5ba - arm-trusted-firmware/drivers/arm/sp804/sp804_delay_timer.c +64e24a32626429bd2dad6a02c91a123b79fe7528 - arm-trusted-firmware/drivers/arm/dcc/dcc_console.c +9697dd84615aa7c7da7ffe22eb0e3a38c6ace390 - arm-trusted-firmware/drivers/arm/sbsa/sbsa.c +668315548e4d6f930b744983a6542e01f81caae2 - arm-trusted-firmware/drivers/arm/fvp/fvp_pwrc.c +ed924dc3ed7f91ecff8a2e441fa5152d9fe2b9de - arm-trusted-firmware/drivers/arm/tzc/tzc_common_private.h +73c05b4fdb011d3783f2f3f3ed7285ca58a63cc9 - arm-trusted-firmware/drivers/arm/tzc/tzc400.c +b2e58e1a761614ee8bb95e48797500fcd9f66c4c - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc500.c +0e845129705069d3fce0df742ab8d56a7966edbc - arm-trusted-firmware/drivers/arm/tzc/tzc_dmc620.c +d0a784c19a578becbc821a36080372d78af9b3b5 - arm-trusted-firmware/drivers/arm/tzc/tzc380.c +57712978c67a02cb381ba1e9203dc26e762d8b43 - arm-trusted-firmware/drivers/arm/dsu/ppu.c +a9cab74a3aa9f59289ec4dac11558cb1e6e3c2a4 - arm-trusted-firmware/drivers/arm/cci/cci.c +bf48b15b9f75300c1f11366746538bd62a99a5ef - arm-trusted-firmware/bl32/tsp/tsp.ld.S +f2cd83bdbfed353fb47e384608fd41f7b78fc98c - arm-trusted-firmware/bl32/tsp/tsp_main.c +227ccd758b1cf98d27e14ac1ebd5e3b21275d6a1 - arm-trusted-firmware/bl32/tsp/tsp_interrupt.c +f9227b30f6aa21bbf4a178697c37fa714ec54eb7 - arm-trusted-firmware/bl32/tsp/tsp_private.h +6727eccb78b649034342ffa087bb189e40734608 - arm-trusted-firmware/bl32/tsp/tsp_timer.c +8d77cc1453037a319f4a5da2e5b77b37bb406277 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_request.S +e94cc0b80bb21c55fc68026d8a981988414ab611 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_exceptions.S +18772624eeb332566bd8dfe2279187bec9b89fe0 - arm-trusted-firmware/bl32/tsp/aarch64/tsp_entrypoint.S +68e3f9565c5bf338271a1445ca22507fb2afc5af - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_icache_inv.S +333a280c5264ca6c42b06d977d15e2fd4809f2d9 - arm-trusted-firmware/bl32/sp_min/sp_min_main.c +abbd0cb6ee3ce9ca8584fa872468754316b868ce - arm-trusted-firmware/bl32/sp_min/sp_min_private.h +5ef0dab419f42df9935d7fbc4e30baa8ea83d75e - arm-trusted-firmware/bl32/sp_min/wa_cve_2017_5715_bpiall.S +b224dca2e5ea95c46e1062767709b1bb1d7d766c - arm-trusted-firmware/bl32/sp_min/sp_min.ld.S +c1854f51280eb002548e763a01a8af613c615ee2 - arm-trusted-firmware/bl32/sp_min/aarch32/entrypoint.S +0cd1ab24947e0ea5ce307a171756d88683d36cde - arm-trusted-firmware/bl2u/bl2u_main.c +2d32dba27247198d6cd35d150dc8eeba3c8ed8ff - arm-trusted-firmware/bl2u/bl2u.ld.S +1df1aad13ba7e2ed5cb1ae4a6200d169a1715578 - arm-trusted-firmware/bl2u/aarch64/bl2u_entrypoint.S +738660771364acfab975427664536a581abb78df - arm-trusted-firmware/bl2u/aarch32/bl2u_entrypoint.S +4e66ff242f442cdfb5239bef53026c402990b912 - arm-trusted-firmware/docs/change-log.md +d2e89e46ca5ae89064b0a9b0d7983272a60e60a6 - arm-trusted-firmware/docs/conf.py +cdd7c87e02f5cae26200b35f5869f20aa1a526cc - arm-trusted-firmware/docs/Makefile +0b30444600f51212f5be53588f4f68cba0bf92fe - arm-trusted-firmware/docs/glossary.rst +ea9ab85da5d526fc32f3436878dc80c33fbbe334 - arm-trusted-firmware/docs/index.rst +0677c6b28a895fccae194309f759b9f4e0f4c9f5 - arm-trusted-firmware/docs/requirements.in +0b02d28e0d9881fab1b08360d2d9bbef021685c0 - arm-trusted-firmware/docs/license.rst +ff8ad4850057cbaba3caddae15b9429bb9c42b66 - arm-trusted-firmware/docs/perf/tsp.rst +3e1557ac89eff3ea7cb96e090dcc6cd147117008 - arm-trusted-firmware/docs/perf/psci-performance-juno.rst +840dcafe1996d0299a5922474d7980b6d2eb779c - arm-trusted-firmware/docs/perf/performance-monitoring-unit.rst +a19b41fb4dbff6144a8b5f04eb7c296b63c442d6 - arm-trusted-firmware/docs/perf/index.rst +add0156b84b7d9f7760db313170bf81a672a66a6 - arm-trusted-firmware/docs/resources/TrustedFirmware-Logo_standard-white.png +02a0166ec0c907a8725efa2ff467ea4d5984a35c - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_sp.png +80b81639bb1aa78723d3635f0359764c595e38c8 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.png +66f1f1fd09b5146cb2a5e1c538de29ea7f88ed7e - arm-trusted-firmware/docs/resources/diagrams/fwu_states.png +d9a6dc06e1a28c0235940539e527ac285c179342 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_boot_type_check.png +7c4678ac4952c496df4536445b336d96139b0066 - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-swd.png +19e287ff6d7c25917fd56356da40bee3e5ef120e - arm-trusted-firmware/docs/resources/diagrams/sec-int-handling.png +04a65e98eceabb17ea534a6dea187021477a1fb2 - arm-trusted-firmware/docs/resources/diagrams/int_handling.dia +d10eb3ff6f8cf071330205ec0d59126d79f939f4 - arm-trusted-firmware/docs/resources/diagrams/non-sec-int-handling.png +4d2668ab5814fb9b799f65b69b427db29952658b - arm-trusted-firmware/docs/resources/diagrams/ffa-secure-interrupt-handling-nwd.png +961fd0fc52b27792b27c6cc8b9f210be8959e285 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-managed-exit.png +a0ca882a9a47bf5642759780b006f69f3c667fff - arm-trusted-firmware/docs/resources/diagrams/context_management_abs.png +ada526023821d5e57e3e1aa979b38d2c8708227e - arm-trusted-firmware/docs/resources/diagrams/ff-a-spm-sel2.png +10d343a1dfde1e76a19cfc7a0f8a9ca28710ee17 - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_cpu_check.png +4ab0332c836fdf5e5596c2b7ecc6ea4bccb62b8c - arm-trusted-firmware/docs/resources/diagrams/reset_code_no_checks.png +165d02fd6baf4c31ce0c1b034477b6596c724abe - arm-trusted-firmware/docs/resources/diagrams/Makefile +64d840596ae8dbdfb803bfdd471e3d4e7955ca82 - arm-trusted-firmware/docs/resources/diagrams/fwu_flow.png +84f99bb590f5c8748bc6e47f3e7bd4bf5890447d - arm-trusted-firmware/docs/resources/diagrams/xlat_align.png +77da82b847d9c9a0cecaa2e43e40dac166a66399 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_structure.png +aacd72a3c084647a884d67147510a1b0c26d8359 - arm-trusted-firmware/docs/resources/diagrams/reset_code_flow.dia +9bd9241452f165fcc7e5018bf8a24204767fa036 - arm-trusted-firmware/docs/resources/diagrams/ffa-ns-interrupt-handling-sp-preemption.png +c279d33545695cac4327bf14a8d84b4237dc8387 - arm-trusted-firmware/docs/resources/diagrams/MMU-600.png +08ebe00cb9823cd55d80c05b4aaaa64c103093ce - arm-trusted-firmware/docs/resources/diagrams/xlat_align.dia +40ffa83fe202970879802b809b75c10ed360c7d4 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.png +40dca2e6d5cf7cdc88398bf5e2df39f3fce31bab - arm-trusted-firmware/docs/resources/diagrams/spm-threat-model-trust-boundaries.png +2417a250f3f2552f5e881830e947024a92e55adf - arm-trusted-firmware/docs/resources/diagrams/arm-cca-software-arch.png +763017cfa85171acb7422b0f8ef1c40ba69443a3 - arm-trusted-firmware/docs/resources/diagrams/rt-svc-descs-layout.png +2e886fd02f6b39a545824f0819608260e0671c14 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_existing.png +d2522911e613a4005eb1e10931779a1bb350a363 - arm-trusted-firmware/docs/resources/diagrams/FIP_in_a_GPT_image.png +17e11d01f23f073cec01fb44acaa3c976495e982 - arm-trusted-firmware/docs/resources/diagrams/cmake_framework_workflow.png +d5775195107610d6a67d5d7f8af6590e4e53e570 - arm-trusted-firmware/docs/resources/diagrams/default_reset_code.png +a68fd21bb442987ce7a67e0eb08d150b81bfe901 - arm-trusted-firmware/docs/resources/diagrams/secure_sw_stack_tos.png +b42c9e2672802e26c9137df29eff6a1c68652ea6 - arm-trusted-firmware/docs/resources/diagrams/context_mgmt_proposed.png +c05984305daded35b5f3a14ea3c5ac88319f4292 - arm-trusted-firmware/docs/resources/diagrams/romlib_design.dia +1586bdc989b8698512851e436d39fed8ad375030 - arm-trusted-firmware/docs/resources/diagrams/romlib_wrapper.dia +a6a4256584fddbb776f1e274748edeff4289cf4a - arm-trusted-firmware/docs/resources/diagrams/psci-suspend-sequence.png +ad73cbcd10b1b5e45ca3a01df6c435b345686322 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.svg +2c5f1b895b01d75ebe2fd874d61f728fe18fca4a - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.xml +4eb0b99548ee5cdbff9d0e01b3455c7c1e1af275 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ehf.xml +a2eed4587b5987e97e3f8207a2c9783c5e322c90 - arm-trusted-firmware/docs/resources/diagrams/draw.io/ras.svg +cde708741ffdd39f92d8670aea4a93ef451cd611 - arm-trusted-firmware/docs/resources/diagrams/plantuml/spm_dfd.puml +0cbedd3989e3d4fc11c3401d7b250d8b14411c50 - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_explicit_dispatch.puml +9e7994a98a6d3531ff8f3c7e16b9e27ae0240805 - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_arm_class_diagram.puml +2c516abafcee77f3889360526590d0764a35d61c - arm-trusted-firmware/docs/resources/diagrams/plantuml/bl2-loading-sp.puml +7ca50157b91a940fdcd61fed7da54e93501b2c3e - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_framework_usage_overview.puml +89429fb35fc54ad81b4aab0c9d5860b228aab347 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl2_populate.puml +0130e90e98cac66f9ac28a56d8fa17af801ead7a - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_init_and_check.puml +695a4bfc3f0c50586104d10e16a8527c37f3541f - arm-trusted-firmware/docs/resources/diagrams/plantuml/io_dev_registration.puml +e357fbb8d83445182b61abea380d1885e484c4cb - arm-trusted-firmware/docs/resources/diagrams/plantuml/tfa_dfd.puml +732ce8b12943c9ca218e89a1aa3eae1379952d12 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fip-secure-partitions.puml +853a892ccba3dedfcb4491b7ad449b46d6a4d47c - arm-trusted-firmware/docs/resources/diagrams/plantuml/sdei_general.puml +7eb6ecf49d5ec8a975cccdc3aeb0d994e07362a0 - arm-trusted-firmware/docs/resources/diagrams/plantuml/fconf_bl1_load_config.puml +1441246fa837376cb589e45510656ca210e18bb6 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-9.rst +266a8326bc618859a7a18572589b40f197ed1a82 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-6.rst +63e67342811855c2803be11bca43aa4c60543575 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-8.rst +5a8ee89be8b54261b0e207ca882fab66cb4db5b9 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-2.rst +fab06483aeca0f68846039c9146a6d828ab12518 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-7.rst +1b8c8e49a1eac7ac65f01b730ef3d22dee6de50f - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-5.rst +48c2d42e738237365f9158ca022d56408ef538e9 - arm-trusted-firmware/docs/security_advisories/index.rst +939eb2b8d82c68d6c9a4e8c1271bd83151818553 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-1.rst +b748a01e82c3ad35dacc68ae9295e4553d57beab - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-3.rst +e03dee87868096ffa7982026e20837ddfc9a6aa3 - arm-trusted-firmware/docs/security_advisories/security-advisory-tfv-4.rst +96e5d7607dc9d3c5db2cc3e15eb9b771a429b761 - arm-trusted-firmware/docs/getting_started/build-options.rst +da2d29864297e0b06dc8f7ac1d17288a078ae5c6 - arm-trusted-firmware/docs/getting_started/psci-lib-integration-guide.rst +6914f4b323e042c91ae58018d9217b08f655997d - arm-trusted-firmware/docs/getting_started/image-terminology.rst +6cc854b04d58541fc0e9043f88c7ece6a68c925d - arm-trusted-firmware/docs/getting_started/tools-build.rst +34beaf5d32a409eabaabd8b492f4ffb95daf2b70 - arm-trusted-firmware/docs/getting_started/index.rst +32237d53d0db21dee6eedd6143e60e46dec6d79e - arm-trusted-firmware/docs/getting_started/docs-build.rst +6ea980565b00e400d102f63072c110d6471b0818 - arm-trusted-firmware/docs/getting_started/initial-build.rst +97122206fcc716ab5581232da8de4685ba9e7df9 - arm-trusted-firmware/docs/getting_started/rt-svc-writers-guide.rst +9c961219684a654a9367ffdf4856dd21080cfc97 - arm-trusted-firmware/docs/getting_started/porting-guide.rst +e95ba49d1a46a2db605b69f5425a6bc6069d9a41 - arm-trusted-firmware/docs/getting_started/prerequisites.rst +3fe053ce17752ae01f7d815a5df51f4887d2749f - arm-trusted-firmware/docs/_static/css/custom.css +a3f0b5a39e2120fdbcad8de599b7c1a18345cfcc - arm-trusted-firmware/docs/design/alt-boot-flows.rst +f880dd25cbf380065e9d345752376e40bc756664 - arm-trusted-firmware/docs/design/interrupt-framework-design.rst +9937a50f3bac7c0a981d42b12b0308be265050ba - arm-trusted-firmware/docs/design/cpu-specific-build-macros.rst +b5b729e65177f7baad24fd693c9b5a9993c50776 - arm-trusted-firmware/docs/design/firmware-design.rst +ff4749d1e71cf1665bbc340e11787c971b395fbc - arm-trusted-firmware/docs/design/trusted-board-boot-build.rst +af63c8f1c70b2c589dba26872e3ba5244236722f - arm-trusted-firmware/docs/design/reset-design.rst +d789165adbc9c0e0ace7d7326f1cf7512fa63c88 - arm-trusted-firmware/docs/design/index.rst +6e60dedac282498dc34de3ebcecd6f0119e7348d - arm-trusted-firmware/docs/design/trusted-board-boot.rst +ffda28459589a0ec22cacc12c5b92103ed64fbbc - arm-trusted-firmware/docs/design/auth-framework.rst +b15afee5cbc5225a2ef2f709e9761fa2cd73d65e - arm-trusted-firmware/docs/design/psci-pd-tree.rst +11abe92eab64d997319223639ad2693b7f7c8535 - arm-trusted-firmware/docs/components/arm-sip-service.rst +75d075c879040f97f06e2a7b3b6bd34df86b48ac - arm-trusted-firmware/docs/components/activity-monitors.rst +3018701b7ef2e5eca172d3608726f506c4b22909 - arm-trusted-firmware/docs/components/debugfs-design.rst +a4af3a93464aafab3bb5428082fa9dec58ed73b5 - arm-trusted-firmware/docs/components/ras.rst +72ac59432a0693df36a09334d6f57a6f9491189f - arm-trusted-firmware/docs/components/granule-protection-tables-design.rst +ec0ac249385853eeb84cc0e4151f612b9d23cadf - arm-trusted-firmware/docs/components/ffa-manifest-binding.rst +8a1dffa8292f295ef5014ac04a74011b4aeea398 - arm-trusted-firmware/docs/components/exception-handling.rst +d2201aab60e237cccd20ad636c8ad4224d7f0571 - arm-trusted-firmware/docs/components/romlib-design.rst +9db58fa601138b8e16c395f19913a1f106be570c - arm-trusted-firmware/docs/components/realm-management-extension.rst +963a2ee9d3bf60564d3ab545fed12694fec33fff - arm-trusted-firmware/docs/components/cot-binding.rst +193002dc879b3270f34cff05228d20d88d099fce - arm-trusted-firmware/docs/components/index.rst +b8d62ed8d8e52992c481b3f032a11c132ddc32ca - arm-trusted-firmware/docs/components/mpmm.rst +164b5be074959cef709b8de7cd264d2b720e0386 - arm-trusted-firmware/docs/components/secure-partition-manager.rst +5064b1a7d15e72b127c8fbacf8f11b087446958a - arm-trusted-firmware/docs/components/secure-partition-manager-mm.rst +aca3aea7df00338e307623d4735b027b76f48985 - arm-trusted-firmware/docs/components/platform-interrupt-controller-API.rst +ca2c86b55376dc70e6bbbb76058286ac38e35ba0 - arm-trusted-firmware/docs/components/sdei.rst +602d20bd46337be44a23550620a7a1f748130fb9 - arm-trusted-firmware/docs/components/xlat-tables-lib-v2-design.rst +e267bb8c86ec7cc1d683daacbb53bd387881178d - arm-trusted-firmware/docs/components/firmware-update.rst +1d91355dae9ce87dd6d332bfe96019333abb6da0 - arm-trusted-firmware/docs/components/fconf/fconf_properties.rst +d795da44f403a2a0bc4010ba95915fcabbef3c31 - arm-trusted-firmware/docs/components/fconf/amu-bindings.rst +10529cbd50c1b2a10d7bf7669a515a30f564db2c - arm-trusted-firmware/docs/components/fconf/mpmm-bindings.rst +c3411adb08049c0735f5b9be29bc976bbcde69c8 - arm-trusted-firmware/docs/components/fconf/index.rst +e289a8345f0c801d0e1d079b94c6752a31a28396 - arm-trusted-firmware/docs/components/measured_boot/event_log.rst +f39c4c5b080cb5537f0260d9f3e477e02aa63bfa - arm-trusted-firmware/docs/components/measured_boot/index.rst +68d992f28a446b0ffe6adad209b6189f9f0dd6a9 - arm-trusted-firmware/docs/components/spd/trusty-dispatcher.rst +e583074d9e81fffee8804f560b145fa486f1aba8 - arm-trusted-firmware/docs/components/spd/optee-dispatcher.rst +ee5cface9280894c7d9860dccb78eda3849c9cab - arm-trusted-firmware/docs/components/spd/index.rst +5d7421fde74010efb451e6e515079f37ec3227e2 - arm-trusted-firmware/docs/components/spd/tlk-dispatcher.rst +53f0692ccc04d5d659e88ac1dc1080af6dcda94d - arm-trusted-firmware/docs/plat/qti.rst +f8d9d0b4336229fecb1a12937b0f1a9b6060aa0b - arm-trusted-firmware/docs/plat/xilinx-versal.rst +2a492964dd82db785e381f828fae2b2a729f6749 - arm-trusted-firmware/docs/plat/meson-gxbb.rst +1fb07134c685f21246757d77653a8c6bb12d949c - arm-trusted-firmware/docs/plat/socionext-uniphier.rst +8b88e9d6cfe72a03efd7e226122d5cd33334fe66 - arm-trusted-firmware/docs/plat/ti-k3.rst +2ed0c805bd3cba59619101f0918aeac59d4e6fd3 - arm-trusted-firmware/docs/plat/rcar-gen3.rst +b54be1ac4f13d0a724629f301e245bbcc4379d44 - arm-trusted-firmware/docs/plat/nvidia-tegra.rst +a970558632482b93ee96aba756982061d20ea4e8 - arm-trusted-firmware/docs/plat/intel-agilex.rst +12b7c2db7722b49705438fabf8b96c0943d163bd - arm-trusted-firmware/docs/plat/meson-g12a.rst +15d03048959cdd154b540a3b91f7aa6b48f7a7ef - arm-trusted-firmware/docs/plat/allwinner.rst +ddffb1cc078fd2d3c58ed8cde2b32388ccd532c9 - arm-trusted-firmware/docs/plat/meson-gxl.rst +a6c4746123e21eba44253912da4e92f0fd31a6cc - arm-trusted-firmware/docs/plat/rz-g2.rst +0db6c8e13659db1d29238baa7d8a870a4e821546 - arm-trusted-firmware/docs/plat/stm32mp1.rst +a928b648d0677930c926401b40e335f052e97be5 - arm-trusted-firmware/docs/plat/mt8195.rst +9085fb1504d30c5d3e75304a86dfa8a1225967b3 - arm-trusted-firmware/docs/plat/qemu.rst +d714f1279de4aa5eb4519255578a2718fc8e3a1e - arm-trusted-firmware/docs/plat/imx8m.rst +4905e051c0a996867dcc2389b8bd5430b0741699 - arm-trusted-firmware/docs/plat/imx8.rst +9e85f6fbc5306c4b0604e98de5fcbddb385c4ce1 - arm-trusted-firmware/docs/plat/mt8192.rst +df909307e45e07ec88f455e8ef27abedd18e3592 - arm-trusted-firmware/docs/plat/rockchip.rst +f2bbe77ac618ba9be663de2bba3cee62eaf17f60 - arm-trusted-firmware/docs/plat/mt8186.rst +a06622efc4dca7ce03e6ea2e305e8a0b8d422bef - arm-trusted-firmware/docs/plat/deprecated.rst +45f03fd73a50f2fe124a2bd1d70fb40243ba0e82 - arm-trusted-firmware/docs/plat/warp7.rst +028d90ceedfb507b0ee1532f28cb8842f1f5b19f - arm-trusted-firmware/docs/plat/index.rst +84cb8ce1de6f042d0693d8a1a4bb2265ef8a7ed0 - arm-trusted-firmware/docs/plat/meson-axg.rst +080191f60f9e441f7527257b977a2c8f6d8c5533 - arm-trusted-firmware/docs/plat/poplar.rst +9bfeb07c04a47aacac6ae649f75799c894e74067 - arm-trusted-firmware/docs/plat/mt8183.rst +05664e895ce6375be6ad98e9576013d1209cb012 - arm-trusted-firmware/docs/plat/hikey.rst +a80443b8a04209092463f6005843be7eb0dc832d - arm-trusted-firmware/docs/plat/rpi3.rst +556090a5f980031e56bccbb5c6d93f41384aad09 - arm-trusted-firmware/docs/plat/intel-stratix10.rst +d0ad3f088b7307bd002023c2fcda2de07a36f40f - arm-trusted-firmware/docs/plat/synquacer.rst +3cefd2238957aeadfec4d578846bb38b56ca5c26 - arm-trusted-firmware/docs/plat/hikey960.rst +ed1a65471d042b402028616f2e38ed56b42dc891 - arm-trusted-firmware/docs/plat/qti-msm8916.rst +25ec8ee5167ea3d60afe26566de20782ee6aa44c - arm-trusted-firmware/docs/plat/qemu-sbsa.rst +4b9ecd5b7418c0a333435d823205f0569bf5e668 - arm-trusted-firmware/docs/plat/xilinx-zynqmp.rst +01b97fb19ab7a8e8baa5a1a96d35f2cb5dc0a05c - arm-trusted-firmware/docs/plat/rpi4.rst +de25efbc7acce27ba0385c2c51a59fbc0f7f7124 - arm-trusted-firmware/docs/plat/brcm-stingray.rst +ed3ec7c6e5baceda79c359ce661ac80dbf660d61 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-tbbr.rst +231fc05a0b2de9270bfe513d92b37243b1cc9601 - arm-trusted-firmware/docs/plat/nxp/nxp-ls-fuse-prov.rst +5d7bd6f5908ace2c36015e0535f2deacac9a2956 - arm-trusted-firmware/docs/plat/nxp/index.rst +7b3072f9759a1fe276a22dcb70d936006608d299 - arm-trusted-firmware/docs/plat/nxp/nxp-layerscape.rst +e5e2720a56dd4b68568aae99f664a7478121e8cf - arm-trusted-firmware/docs/plat/marvell/index.rst +5315af3195d5a7c46ec750dccbf4f684c0df4e81 - arm-trusted-firmware/docs/plat/marvell/armada/porting.rst +c143e2ca6a4cf9f94d9017f083b9d5dac2a5167d - arm-trusted-firmware/docs/plat/marvell/armada/build.rst +3b71f880342eddec219418df7f6e6034cce505b5 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-ccu.rst +30afe5cabdcd30362317ee05e9fc4203912e1e30 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-a8k-addr-map.rst +4496a36f12db50b8075c93550ad2b7a23c24e490 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-io-win.rst +0af03a25bc9938840be478afe1f0c3375e852dc7 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-iob.rst +bcb055e4f5b81eda0adb88f8b79f78b72b1332b9 - arm-trusted-firmware/docs/plat/marvell/armada/misc/mvebu-amb.rst +aa2be0dce19adf3702025c84d42587a8d1febeb0 - arm-trusted-firmware/docs/plat/arm/index.rst +3abb2d351f8ba63685ce15c862339db9da2d3ce2 - arm-trusted-firmware/docs/plat/arm/arm-build-options.rst +839b91011a0ebdde7ac9b056ab0a3b087ef11114 - arm-trusted-firmware/docs/plat/arm/fvp-ve/index.rst +09ec3654ccddcc7942d92d28d1cf1ccc973ba893 - arm-trusted-firmware/docs/plat/arm/tc/index.rst +e2a46aa8e82f95847753a68a0be016142edd63d4 - arm-trusted-firmware/docs/plat/arm/juno/index.rst +a845be9736fc1cfcd3cefda5b6a0bde2419f9bc0 - arm-trusted-firmware/docs/plat/arm/fvp_r/index.rst +dc03d6c732257847d92bd05db0e2b93163870fd7 - arm-trusted-firmware/docs/plat/arm/corstone1000/index.rst +b2ee822aa3f35f04c12fdc9ab44cd66e70b96f38 - arm-trusted-firmware/docs/plat/arm/fvp/index.rst +46e0aef67518d4e85f7b3f9dc17b5e3a36fc9640 - arm-trusted-firmware/docs/plat/arm/morello/index.rst +b10bad88c8647f9ecfe8b3bad163830573cfbdc0 - arm-trusted-firmware/docs/plat/arm/arm_fpga/index.rst +5d47110e0bea04401c509ac372927b21ea650e12 - arm-trusted-firmware/docs/process/contributing.rst +bfb4f8dc9ec952cc5582f0a704de50db89072cf8 - arm-trusted-firmware/docs/process/code-review-guidelines.rst +3f4a6d7ff70fb05d5b604632a17c4f84f8c5ab3a - arm-trusted-firmware/docs/process/faq.rst +2e72ba549eae51afb536d262d8daa4d81aa9a18a - arm-trusted-firmware/docs/process/coding-guidelines.rst +b69510d5984b9f3bc4ecb789acab9ba5308eb6b6 - arm-trusted-firmware/docs/process/index.rst +9fcde12a65498faac5c43825aec87d7fd0f2ecb2 - arm-trusted-firmware/docs/process/security-hardening.rst +642d7817092741083f4726c2c178f0c3d0e9bba2 - arm-trusted-firmware/docs/process/security.rst +3a4d85651ee64cc9eeb924af2325478bcf1f71e2 - arm-trusted-firmware/docs/process/coding-style.rst +0f5d2a3f45d1b5b5a634ea677c87983ab7a5e769 - arm-trusted-firmware/docs/process/platform-compatibility-policy.rst +947dfc47181528100c27204431008074dead97a4 - arm-trusted-firmware/docs/process/commit-style.rst +6fd5a13007e2c86b56b83ed08af9e4343890c44d - arm-trusted-firmware/docs/threat_model/threat_model_fvp_r.rst +125013620e921736b4b48b912f62657eb06ae363 - arm-trusted-firmware/docs/threat_model/threat_model_spm.rst +6370cee0ae902a8040401edd8f2ce7aa0d67a170 - arm-trusted-firmware/docs/threat_model/threat_model.rst +c39c2e4ba3f12fbad74aac5304a27e5b3c3fc272 - arm-trusted-firmware/docs/threat_model/index.rst +3c9105f13eb03be1b0c0035eb88daafdd219f4a1 - arm-trusted-firmware/docs/design_documents/context_mgmt_rework.rst +b5585102476dfaccde6a472ab5485236468a4d14 - arm-trusted-firmware/docs/design_documents/cmake_framework.rst +1cf19041279928d9215bdd8c91a1559b37e426b4 - arm-trusted-firmware/docs/design_documents/measured_boot_poc.rst +458dad419f00db20225a3987ea193db385391688 - arm-trusted-firmware/docs/design_documents/index.rst +3d4d6eeef77d8e11c9b5da38bf3008531d4cdff8 - arm-trusted-firmware/docs/about/acknowledgements.rst +4717f5ce955ade54d71c40eb4edc26c2ae63540a - arm-trusted-firmware/docs/about/release-information.rst +d0aa75e869685b4dadea831588e9175113411e43 - arm-trusted-firmware/docs/about/features.rst +bd485ae1fd78b7134ac1b633b73d320c4de37262 - arm-trusted-firmware/docs/about/index.rst +b797ee1a8501bb526a8f4e22f7bf644d83ffc96d - arm-trusted-firmware/docs/about/maintainers.rst +15453cf4faa84e1c067c1b9125f90e625547f47d - arm-trusted-firmware/docs/about/contact.rst +d04e79c7e2d1ff0546074efcfda2290f20c1c923 - arm-trusted-firmware/.husky/commit-msg +fd32ceb86780ba4682d238401c5bdc6c51f6652f - arm-trusted-firmware/.husky/prepare-commit-msg.cz +edf09f8f672ed108a22d57c3be9c64c542957347 - arm-trusted-firmware/.husky/commit-msg.commitlint +201f68ff32e77e6400dc5624a726bb46fafe1ac3 - arm-trusted-firmware/.husky/commit-msg.gerrit +11dae66f5031e4fc368d8b20d11916dbcc90b1c0 - arm-trusted-firmware/.husky/prepare-commit-msg +3a094362be710094e9435bc1e4d7eebfa468338d - arm-trusted-firmware/bl2/bl2_el3.ld.S +88bbfcb3f9b827bdab7f16cdfe892b2aa1470576 - arm-trusted-firmware/bl2/bl2_image_load_v2.c +0b07a71ab893d39e7884f11f46b95245ab0cf303 - arm-trusted-firmware/bl2/bl2.ld.S +991c05cee7a30247e2edcade94405aef95480121 - arm-trusted-firmware/bl2/bl2_private.h +d8756b1a7295709e6757c7dbfc53741267823e2a - arm-trusted-firmware/bl2/bl2_main.c +62ef4221f56feaf0907dbe17cad47a9bab86bf03 - arm-trusted-firmware/bl2/aarch64/bl2_el3_exceptions.S +c426fa02b617581d2495667828e9430110cf713a - arm-trusted-firmware/bl2/aarch64/bl2_entrypoint.S +247751d71fb2863f439cc217ac18c219dbf15453 - arm-trusted-firmware/bl2/aarch64/bl2_run_next_image.S +776c1699268eee43ba9230cb7e785e298e56a233 - arm-trusted-firmware/bl2/aarch64/bl2_arch_setup.c +a34048b4cc67bca14b7594e2c1a53b4c0376d779 - arm-trusted-firmware/bl2/aarch64/bl2_el3_entrypoint.S +777576955f2ae3959035c33791a33835fe6578f4 - arm-trusted-firmware/bl2/aarch64/bl2_rme_entrypoint.S +e514ace46685e16066700af9ec41ffbfa825b369 - arm-trusted-firmware/bl2/aarch32/bl2_el3_exceptions.S +e7ec4f132c5a2ca9bb5f999f47079e4d473e77d9 - arm-trusted-firmware/bl2/aarch32/bl2_entrypoint.S +f64693060b1ef904b4abfc04b8480a0f458494c5 - arm-trusted-firmware/bl2/aarch32/bl2_run_next_image.S +2534665e628b7612c3896fed4e659f3351601296 - arm-trusted-firmware/bl2/aarch32/bl2_arch_setup.c +aac463ba1d35408d94f960ade6d2db95d68455ab - arm-trusted-firmware/bl2/aarch32/bl2_el3_entrypoint.S +b296aa0c1c6575bc1a961fcbf21420aa5e6c0d3b - arm-trusted-firmware/include/bl31/bl31.h +89971e627f1aaad3902b29c72eef83520766be40 - arm-trusted-firmware/include/bl31/ea_handle.h +40a0dcdf3add2805bf312c4548d2ee377fc8e4db - arm-trusted-firmware/include/bl31/ehf.h +6d533c4b5b87dfa62fc19f93ea9a2a7d91fa7e0a - arm-trusted-firmware/include/bl31/interrupt_mgmt.h +f237c837e7f3ca6eb78a837961cc378136eb56a4 - arm-trusted-firmware/include/dt-bindings/soc/stm32mp15-tzc400.h +5c7d53dffc9e4dbe1b29a7a3f2c66a36954dd32d - arm-trusted-firmware/include/dt-bindings/soc/stm32mp13-tzc400.h +4b89cad3c01b7767a5a3a13de49705b2cb3e7f9e - arm-trusted-firmware/include/dt-bindings/soc/st,stm32-etzpc.h +e0d1075d19bd35b9bf189dad00ef6b45991c1bf0 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clks.h +fd1e043f322c708de5aa529250ef0ca7430cc508 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clksrc.h +bd297c8c069baf4894e271462ecd0387ca142d2b - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clksrc.h +f8dfb28848429d1ddd93107a95f47d8c6701e359 - arm-trusted-firmware/include/dt-bindings/clock/stm32mp13-clks.h +080c331a370bfcf9f9ce11ccdc89838ea7fd401c - arm-trusted-firmware/include/dt-bindings/clock/stm32mp1-clksrc.h +f28db646c8bdd11bb9593e0d241d924482a7d3ad - arm-trusted-firmware/include/dt-bindings/clock/stm32mp15-clks.h +b7307a0a106f93b2429fa105547d42bc65f8afc2 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp15-resets.h +0ca59c4b41f2264bcc0d4b45550b8a587211aece - arm-trusted-firmware/include/dt-bindings/reset/stm32mp13-resets.h +c5098c5b107f74cd689ca039a39721bc1ecb7523 - arm-trusted-firmware/include/dt-bindings/reset/stm32mp1-resets.h +7efe8c0a3fbb4e9b29850fac16b475c45925c6e3 - arm-trusted-firmware/include/dt-bindings/pinctrl/stm32-pinfunc.h +56af3734637f9dcf2f75c88aad9614e515be1570 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/arm-gic.h +3a4737826d5e90e262be765553886dc9b2cad966 - arm-trusted-firmware/include/dt-bindings/interrupt-controller/irq.h +eda413e9067c54fd7cb0718642eb3cb770fb5c79 - arm-trusted-firmware/include/services/ffa_svc.h +53e733abf11ec08954e5e64474973896323d428b - arm-trusted-firmware/include/services/arm_arch_svc.h +bd59ae9370224873185cfa4dfc1459db223f86d3 - arm-trusted-firmware/include/services/spm_core_manifest.h +d02d80eef605a92cc293597811496a9801e4761b - arm-trusted-firmware/include/services/rmmd_svc.h +583482e243ae52386041c084650c8579a1f113ab - arm-trusted-firmware/include/services/std_svc.h +3b7a4c6d6c8ce3c42694e589dd7dd5d4ed7a4ced - arm-trusted-firmware/include/services/spm_mm_svc.h +18b02402ab43e28399a4a595544148f960b65c9c - arm-trusted-firmware/include/services/sdei.h +30872b92c4859ac9f8e3a28f996c947b74edbb61 - arm-trusted-firmware/include/services/spmd_svc.h +f9e8e6beb1285dc1b188488dc9a217ba805b04e1 - arm-trusted-firmware/include/services/pci_svc.h +6b3525de0de5c707191677733b6c49dba80eed96 - arm-trusted-firmware/include/services/sdei_flags.h +d3bd4cf8e1c91ab4b8019456b7e19c3fd4675567 - arm-trusted-firmware/include/services/spm_mm_partition.h +5d3f25945b7e037c8732ee7c4702366e6ceef5a0 - arm-trusted-firmware/include/services/trng_svc.h +1f0f251429978e8646a05d91d3f3263364aac596 - arm-trusted-firmware/include/services/trp/platform_trp.h +718add17082d7b0f4631c4aa87879e2dbc634426 - arm-trusted-firmware/include/common/fdt_wrappers.h +b46a10bce55c312c93a16f506296f5642158a823 - arm-trusted-firmware/include/common/asm_macros_common.S +dc31b12d8e0fe348d049aab169721695d6414bc2 - arm-trusted-firmware/include/common/bl_common.h +835fd8c82abcfae1bf3c5dceb1123a8b2bfd587d - arm-trusted-firmware/include/common/ep_info.h +1fb3546ddcbbdb34f1bd8c5532fde531ed03e4fd - arm-trusted-firmware/include/common/runtime_svc.h +1d8edfcfadd6f5b8724ad6ef3530f09bac04d2b9 - arm-trusted-firmware/include/common/fdt_fixup.h +561b168245611d5de641a636b5d632f02dcab868 - arm-trusted-firmware/include/common/debug.h +816190a2de110539cf90ed91f279563c0bca9a18 - arm-trusted-firmware/include/common/uuid.h +9398e9281edb3916d9f8b25e4ac909538f93d5da - arm-trusted-firmware/include/common/interrupt_props.h +b0aadb059bd035c38b54ce8f2f7690b49b417e5a - arm-trusted-firmware/include/common/param_header.h +0adc1932137e9f09ebf8948f60d0bb0258ad0249 - arm-trusted-firmware/include/common/tf_crc32.h +cbf9eec4b4cde89881d2efe44be1dde85d9b6b0d - arm-trusted-firmware/include/common/bl_common.ld.h +9acd7a0a005acdb9eb6ee122677ee9528b36b6e0 - arm-trusted-firmware/include/common/nv_cntr_ids.h +f3ec87cdd303cc80ab1975ee4c970c1d72f2a1d9 - arm-trusted-firmware/include/common/desc_image_load.h +3061ebcc5cc39e9b66461188d5eccd5bef4173d0 - arm-trusted-firmware/include/common/image_decompress.h +5afd89832d7eb27979b6864884c4c5564a60279d - arm-trusted-firmware/include/common/romlib.h +22b063584c188624815fe5a57f199b9bde282c6a - arm-trusted-firmware/include/common/tbbr/tbbr_img_def.h +b1bbf25afc02647d5cf3c2de70985599ed6bf6ea - arm-trusted-firmware/include/common/tbbr/cot_def.h +1d2a96df860280e160ab95e4e51e622a5f546aba - arm-trusted-firmware/include/arch/aarch64/arch_features.h +87e9fceb27f38ccf307b534c37594e96103b391f - arm-trusted-firmware/include/arch/aarch64/arch.h +40e8dcbc93cae746d0a5db7109f8c2d55204cc36 - arm-trusted-firmware/include/arch/aarch64/asm_macros.S +04b3308044a6768acf0bad187fc2b69cb69a1fe4 - arm-trusted-firmware/include/arch/aarch64/assert_macros.S +ad144423428ec92ff7791f7e65475d8179b74ef7 - arm-trusted-firmware/include/arch/aarch64/el3_common_macros.S +d35ee46e0adae54b398a7fca1dfb048e883b5ad1 - arm-trusted-firmware/include/arch/aarch64/el2_common_macros.S +ed984eb0f0ed8079b711d378fe82a35a98c45803 - arm-trusted-firmware/include/arch/aarch64/smccc_helpers.h +3b667906d524c05d363bb8341f5241bbe7d80fe4 - arm-trusted-firmware/include/arch/aarch64/arch_helpers.h +82b34ecc6637bf3745fec6a4d1cbc29e06e8e19e - arm-trusted-firmware/include/arch/aarch64/console_macros.S +6a8e3ed67bce468bf878dee9e257722a13c705de - arm-trusted-firmware/include/arch/aarch32/arch_features.h +1ac6bbd72fd5efcdea46d665f3b42539e55d19af - arm-trusted-firmware/include/arch/aarch32/smccc_macros.S +e2b5aa5f3ed136a6b09905c047bcd4bba696b753 - arm-trusted-firmware/include/arch/aarch32/arch.h +c2be1c93cd54c4e39aaf2aaa3a0efde1a237ae5d - arm-trusted-firmware/include/arch/aarch32/asm_macros.S +7473145f94c25355b413a071f083825a5bbf2ce8 - arm-trusted-firmware/include/arch/aarch32/assert_macros.S +19edcf9b1fb1a08230c93e3bfa026e7b33cd3ac9 - arm-trusted-firmware/include/arch/aarch32/el3_common_macros.S +0e8c93e8e2069b7b80576b88757ad99a54dabc15 - arm-trusted-firmware/include/arch/aarch32/smccc_helpers.h +68d3700bd1027d9b9ce6280954972329e2653b9e - arm-trusted-firmware/include/arch/aarch32/arch_helpers.h +707cddbbe6226e2efc883af7013f08afced5a708 - arm-trusted-firmware/include/arch/aarch32/console_macros.S +2953c9cd650429f472333ef0f7cb9ab6c69488c0 - arm-trusted-firmware/include/bl1/bl1.h +f3d565fadbf6176b3034b8359d22fa8c03772f95 - arm-trusted-firmware/include/bl1/tbbr/tbbr_img_desc.h +c8f57a02330fc21d063cbfa19b558cbd20de2787 - arm-trusted-firmware/include/drivers/generic_delay_timer.h +c6f581c377a1a1670d1dd54c360deded41593d6f - arm-trusted-firmware/include/drivers/delay_timer.h +3fdd5f2bbd8585722f7176499884e963fcc1806f - arm-trusted-firmware/include/drivers/console.h +3d13f3cbff61918c53bb0a76876155dc82337fe5 - arm-trusted-firmware/include/drivers/console_assertions.h +e52b9017a122dbf25d5764491104335c6a166dd2 - arm-trusted-firmware/include/drivers/usb_device.h +8709de3c5655138d78511772539fb29a8b660364 - arm-trusted-firmware/include/drivers/scmi-msg.h +32b681b12e18f054ea32d70a554e9c07ff59e4f5 - arm-trusted-firmware/include/drivers/spi_nor.h +d73de0ba3c3a5f28ea6d778b2dcb3ccc7d76c74e - arm-trusted-firmware/include/drivers/mmc.h +1e85ce64c0bc0c37f1c87dab8859540aadd4d842 - arm-trusted-firmware/include/drivers/raw_nand.h +061a6a5d58a19fa40602dcb1c9d1042a206ad73e - arm-trusted-firmware/include/drivers/spi_mem.h +58d9040bd23a07f657047c01fbc92a62b9b04d45 - arm-trusted-firmware/include/drivers/clk.h +42c0f53bb57374cb007e6d5c3d4d536db4069f15 - arm-trusted-firmware/include/drivers/nand.h +b11f7ad45072a13e91bd01040adca94742f7cff1 - arm-trusted-firmware/include/drivers/gpio.h +beb3e629b953dd33bc44df27d3f0b251af4a75e5 - arm-trusted-firmware/include/drivers/scmi.h +9148c938d74351967390c1286566f167d1915b59 - arm-trusted-firmware/include/drivers/ufs.h +80ffbe42c480534b02989a02a37fe24a316746dc - arm-trusted-firmware/include/drivers/spi_nand.h +bb163896fcf9655f45d24b8676ea0a79a6c28272 - arm-trusted-firmware/include/drivers/dw_ufs.h +41a9e785cff8ee17c58544900ad2cf351862fb31 - arm-trusted-firmware/include/drivers/cadence/cdns_uart.h +ccb0701fec1000c00375edbf0318bdce6617b109 - arm-trusted-firmware/include/drivers/nxp/smmu/nxp_smmu.h +3e33fa498602a762c87ce6d18b27e00fd4d9e153 - arm-trusted-firmware/include/drivers/nxp/gic/gicv3/plat_gic.h +141c6ec9750c86044338eb19ee622331b9a6c0d8 - arm-trusted-firmware/include/drivers/nxp/gic/gicv2/plat_gic.h +aabedc9062342279b677c72861038190cfa65939 - arm-trusted-firmware/include/drivers/nxp/sd/sd_mmc.h +7989591e2a2162069486ebab7e2728208c51b5c2 - arm-trusted-firmware/include/drivers/nxp/flexspi/fspi_api.h +69289264b7a28a5ce23aa04ce828d8b4af255860 - arm-trusted-firmware/include/drivers/nxp/flexspi/xspi_error_codes.h +ce837ddd809c0d8f381cefc82d212e9a1a20209b - arm-trusted-firmware/include/drivers/nxp/flexspi/flash_info.h +eb200bcc06472d689f3a7419f0710c4c3d8ce0c5 - arm-trusted-firmware/include/drivers/nxp/interconnect/ls_interconnect.h +460f93da77ff4c52f61d06eca41dc83c56a92b6d - arm-trusted-firmware/include/drivers/nxp/crypto/caam/rsa.h +66189a3d70ccfb57441e34458abfc9cd72c29d19 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_hw_specific.h +fc12ffe1d77603728f2c875a296218ae6cddb095 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam_io.h +91adf35b394ad394248624343b9c5b19fa0c2b09 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jobdesc.h +bf836adf23266f3749b5e68af59a31d0ac0ea00a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/jr_driver_config.h +57d421cf90453e8aa05285508bc43ed0e325a7a7 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/hash.h +2c95c38a7f65a3ef7eb3992c7136879ef75e4c7a - arm-trusted-firmware/include/drivers/nxp/crypto/caam/caam.h +8308e3c4607508799254cc82d52ec5d4aba905e2 - arm-trusted-firmware/include/drivers/nxp/crypto/caam/sec_jr_driver.h +2388bdc4442c2695122e844d49738f95b18a84cf - arm-trusted-firmware/include/drivers/nxp/csu/csu.h +46896393ac73e49d174031ad9db2b897a5a53cd5 - arm-trusted-firmware/include/drivers/nxp/timer/nxp_timer.h +95b4d87dfcfc29bdf2b6cd0bbb06749112243507 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch3.h +060901911b3564bae52c8476be0a91ea019b2283 - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg_lsch2.h +99694a5f2e9c541d163aa4fc3bae8f07cdd32b4c - arm-trusted-firmware/include/drivers/nxp/dcfg/dcfg.h +e81281948e932f6635309e0cc817672144dd5cc1 - arm-trusted-firmware/include/drivers/nxp/dcfg/scfg.h +3d4947f956585eb9cfe3b8245ad4c1749cdc72b1 - arm-trusted-firmware/include/drivers/nxp/sec_mon/snvs.h +7f0601b767be7522d2b3b053924b860224900737 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nor.h +cd9ce08e3ca357e9ac083fd384e2ffd154288032 - arm-trusted-firmware/include/drivers/nxp/ifc/ifc_nand.h +4453a2af06ed170ae6c69f42b415c69314fd3d9b - arm-trusted-firmware/include/drivers/nxp/auth/csf_hdr_parser/csf_hdr.h +225ffbb6a71c970da33f40390a7828768770c824 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc380.h +b0e9643a90314ef89452944214806403f53b7b54 - arm-trusted-firmware/include/drivers/nxp/tzc/plat_tzc400.h +4229b536f33d8f4775076953d8c91ea47ad378a5 - arm-trusted-firmware/include/drivers/nxp/console/plat_console.h +3b20fa259fde3f160db7996e9571edfc5ab34bc5 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr_io.h +90e8213c057c2449b5ba645b49e85458c0dc2e43 - arm-trusted-firmware/include/drivers/nxp/ddr/dimm.h +a38ba636dc7402ba5f0f12fac9db9813190a8c39 - arm-trusted-firmware/include/drivers/nxp/ddr/regs.h +2b66abb34254db06ee8c88f5e0596c908b2d2026 - arm-trusted-firmware/include/drivers/nxp/ddr/utility.h +d0fc8c7cc714365c4b36dc3b12083432b0173dd3 - arm-trusted-firmware/include/drivers/nxp/ddr/immap.h +190e1845f17fd2f9c9e7fdcb31f62f22735c2401 - arm-trusted-firmware/include/drivers/nxp/ddr/ddr.h +f76687e9c42877c6684b9f0f42809be11e898f2e - arm-trusted-firmware/include/drivers/nxp/ddr/opts.h +d8d9fce57d178fdfd41f5be63879bfa85d2e2e15 - arm-trusted-firmware/include/drivers/nxp/ddr/fsl-mmdc/fsl_mmdc.h +07aabe0c38fbe8ae82313542589e8b6013f0a704 - arm-trusted-firmware/include/drivers/nxp/qspi/qspi.h +26748e486ff05a3ed33d842cba65e4fecc362aae - arm-trusted-firmware/include/drivers/nxp/gpio/nxp_gpio.h +56618eda200d872addc06447897a8b7ec619ffb8 - arm-trusted-firmware/include/drivers/nxp/pmu/pmu.h +3584254639e10b77ffd6ccf07f7a59923b337ffe - arm-trusted-firmware/include/drivers/nxp/sfp/sfp_error_codes.h +b6baa4f2facaae8fcb1873db219796f86e62cbbf - arm-trusted-firmware/include/drivers/nxp/sfp/fuse_prov.h +f75c54f08edcc8069804184e40a6d8a74d3d1b42 - arm-trusted-firmware/include/drivers/nxp/sfp/sfp.h +be8a6b00a6db26fef151d90020cd12c856e4cacd - arm-trusted-firmware/include/drivers/nxp/i2c/i2c.h +490bae640af8d15a10cc4a530a23cd51226ca709 - arm-trusted-firmware/include/drivers/mentor/mi2cv.h +1fad8ad24347aab9e6da6d46f5cf581f938d2ab8 - arm-trusted-firmware/include/drivers/allwinner/axp.h +0601d762e1bfda8d93d085ea44202fdbff2d1ad9 - arm-trusted-firmware/include/drivers/allwinner/sunxi_rsb.h +1c35b8d1dd99e2556585b97e6c5f472b95565fd0 - arm-trusted-firmware/include/drivers/amlogic/meson_console.h +598adf21c9089a664c913fb3faf852fa36dddef8 - arm-trusted-firmware/include/drivers/amlogic/crypto/sha_dma.h +04cc0e519d24a6729fbf6f89e981eaf992fe19d5 - arm-trusted-firmware/include/drivers/brcm/sf.h +2a62cccb75603f1abe573a211d9b149826e87356 - arm-trusted-firmware/include/drivers/brcm/chimp_nv_defs.h +2dedb1c6a08bb98fab574fbb49becf23a0a40b3d - arm-trusted-firmware/include/drivers/brcm/dmu.h +3b8d411ed511e8d5f5cd285a04229eb0779c2609 - arm-trusted-firmware/include/drivers/brcm/iproc_gpio.h +907603dcc9f90f3393201ab4a2a5c8ce32f61543 - arm-trusted-firmware/include/drivers/brcm/sotp.h +542f2f80df9c9b264f0bfc9387e38e99ad2a9e7b - arm-trusted-firmware/include/drivers/brcm/spi_flash.h +823fbabdd578bbfbf92d8a2d68e8d7d2c3f652cd - arm-trusted-firmware/include/drivers/brcm/spi.h +f1e9babc3d5e854ba472c64f889f2fb01138cff0 - arm-trusted-firmware/include/drivers/brcm/chimp.h +67ec9883d9b0ac3959b68dcf32dbf8d8fbc84bc8 - arm-trusted-firmware/include/drivers/brcm/scp.h +8c4e00a589a41eac59a1e3f7743e362f874b80cd - arm-trusted-firmware/include/drivers/brcm/fru.h +5afc35a13cf962ad7cd0f15b0532bbe11c7ad17a - arm-trusted-firmware/include/drivers/brcm/ocotp.h +5632d0130d0787f77618a2ca64d09d7bc3d2433b - arm-trusted-firmware/include/drivers/brcm/usbh_xhci_regs.h +281ab6dc0343aa92cc689456d9b8b56e7e853961 - arm-trusted-firmware/include/drivers/brcm/mdio/mdio.h +5e1781b653944c224e65bec032fae482c1925591 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdprot.h +5657b1337210a575a742026dfa31f3136b5bb625 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_types.h +d6123ce1d15ed92eb457d0e0d13d66841deb34ea - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_pboot_hal_memory_drv.h +40a4365490452d1db063c69f305c46be1d20e9f5 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_chal_sd.h +af14073522c90e3d69b0abc31fd3a2820dc54d47 - arm-trusted-firmware/include/drivers/brcm/emmc/bcm_emmc.h +c3be01e418a0c44f650529178aabc99c5fdbef33 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_api.h +eafab2881a9d078ab544df13644c4b47b0670003 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sdcmd.h +869edd881664c3e2332d5b2e6765e7dacbb0afb7 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_brcm_rdb_sd4_top.h +38ad4c8652f178df916a5a1622fad23851187ba2 - arm-trusted-firmware/include/drivers/brcm/emmc/emmc_csl_sd.h +ba4c82c4f42cf7c6060c7266d23de675e741a191 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c_regs.h +829056e15314b731c22b87d62a2c8606e72e1fb8 - arm-trusted-firmware/include/drivers/brcm/i2c/i2c.h +b5e8788fcbe8f7e5a29ea20b0496f5b331fe6b4b - arm-trusted-firmware/include/drivers/measured_boot/event_log/tcg.h +bf12d4c88947dab864a8f411bd8b3d752bcece3f - arm-trusted-firmware/include/drivers/measured_boot/event_log/event_log.h +ddd09be972db2607bb424326a6c8fbb441dbfec2 - arm-trusted-firmware/include/drivers/rambus/trng_ip_76.h +95f57bdb58eaa0c98d1495b69af4481368294101 - arm-trusted-firmware/include/drivers/synopsys/dw_mmc.h +89a898543325d24449f04f9b4f73ab80fe43615a - arm-trusted-firmware/include/drivers/fwu/fwu_metadata.h +bd8eab4d0a2394ab277d17b70d1de2839a83ce04 - arm-trusted-firmware/include/drivers/fwu/fwu.h +53d9f7bd2b149b510835abe889d7520b7f40b916 - arm-trusted-firmware/include/drivers/partition/gpt.h +526e7a59fda5b797d17357c6594325b695dae294 - arm-trusted-firmware/include/drivers/partition/partition.h +bd4bb47e71397b065ce00f2af2e6c24b3a8e1d45 - arm-trusted-firmware/include/drivers/partition/efi.h +1c27aa6ecf64d9c63f2e200bb4b4f34c1493e6b4 - arm-trusted-firmware/include/drivers/partition/mbr.h +e65ada86295c449ba40e5e0d4d1558b8c57e24c5 - arm-trusted-firmware/include/drivers/io/io_mtd.h +53a57c8d46bdf6e3119f7da34bfab0df1ea5be9c - arm-trusted-firmware/include/drivers/io/io_storage.h +fe49b84f7431a3680d29420770e6c5a8e81abd5c - arm-trusted-firmware/include/drivers/io/io_encrypted.h +37187b6d387c4c5065ca5fcf7fb76e54527943c2 - arm-trusted-firmware/include/drivers/io/io_dummy.h +10532a6db736e62308718e7ed4602bcdad21e3e0 - arm-trusted-firmware/include/drivers/io/io_block.h +d44cfbded1853f569ae63d99598504a959d6be61 - arm-trusted-firmware/include/drivers/io/io_fip.h +ea2dcfb76c08ec6fec8d8a369642b152753b0780 - arm-trusted-firmware/include/drivers/io/io_driver.h +65ea10cb954a4eafbc5c1b0e1f4118cece4ff74b - arm-trusted-firmware/include/drivers/io/io_semihosting.h +f255bd6542ce1b5d70e6f1e8d795bf29367099a7 - arm-trusted-firmware/include/drivers/io/io_memmap.h +04830d2bd9eaac4d5ab2cf414e66ae7439c3832d - arm-trusted-firmware/include/drivers/cfi/v2m_flash.h +2a6f91687b0799d7e9d7d79ea9480d7b0f57c185 - arm-trusted-firmware/include/drivers/auth/crypto_mod.h +c7235a5c0dc2db938ba5586b4a94294d0c1cef98 - arm-trusted-firmware/include/drivers/auth/img_parser_mod.h +21f2b4221f273c0afed79420c75126131f6cbd5a - arm-trusted-firmware/include/drivers/auth/tbbr_cot_common.h +125b1a75a3651ff04f7dd19ba665ccb6846f3a0b - arm-trusted-firmware/include/drivers/auth/auth_common.h +487e2e7025ad4207cb2dc1e52045c91796c5f00d - arm-trusted-firmware/include/drivers/auth/auth_mod.h +317b0bab814dd8e2cce909a57a2c8be90b0f5273 - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_config.h +8990234b68caadc3262242514364a5e4326b0c2f - arm-trusted-firmware/include/drivers/auth/mbedtls/mbedtls_common.h +6092827f0eb5f3c784b6a1da04df8d26918b01c5 - arm-trusted-firmware/include/drivers/renesas/rcar/console/console.h +8d5bb836b8836f486476f20753a83ca09d64567e - arm-trusted-firmware/include/drivers/coreboot/cbmem_console.h +a3de98e4cc085d3cf7d5d52931b5b3623d0a619f - arm-trusted-firmware/include/drivers/marvell/mci.h +2a16f04ed2b2358e61aa3683ec3d1f2b3960dd2b - arm-trusted-firmware/include/drivers/marvell/cache_llc.h +15475b1e40e5c5bddbfabed61f7f24162136b1f7 - arm-trusted-firmware/include/drivers/marvell/amb_adec.h +000c88b50b95ab8b54fed58ab9f840b9bb69e06c - arm-trusted-firmware/include/drivers/marvell/i2c.h +69f49992d9c55ee0e777a11643d0b52001cb7622 - arm-trusted-firmware/include/drivers/marvell/aro.h +9b00b75ebe2ac0600a4eb5f6e9b76c2c77e19a94 - arm-trusted-firmware/include/drivers/marvell/ap807_clocks_init.h +7f1222ae6a5838bc830b1300ab199a3d42290790 - arm-trusted-firmware/include/drivers/marvell/addr_map.h +6fb4915c93922ffd80c2b7082f5219b13d64a4a9 - arm-trusted-firmware/include/drivers/marvell/iob.h +5c2e0ca868faae2060e6a9f3bf20896783564942 - arm-trusted-firmware/include/drivers/marvell/ccu.h +02710fe143b7937c1b4fad8c1e757146513ac135 - arm-trusted-firmware/include/drivers/marvell/io_win.h +d7bc8fa93e6253a8b9ef6c39613ea88489703b1f - arm-trusted-firmware/include/drivers/marvell/gwin.h +fd4a5e7af241c3b0572f5c9e81decf1868f17fb4 - arm-trusted-firmware/include/drivers/marvell/thermal.h +80057d817a90e75ad1e4eab0e4c81c6a62aa3911 - arm-trusted-firmware/include/drivers/marvell/mochi/cp110_setup.h +9fe146fde5aec71f5cc47d07590e1f76602bc9cc - arm-trusted-firmware/include/drivers/marvell/mochi/ap_setup.h +1bd923068f35229b4648825afdbe2d5ee74ba4fe - arm-trusted-firmware/include/drivers/marvell/uart/a3700_console.h +d9fee9976962b8d9daffbf4d4cb1e7400e14c745 - arm-trusted-firmware/include/drivers/ti/uart/uart_16550.h +898f43097b2545ca29358b143d6e97761f1dbce4 - arm-trusted-firmware/include/drivers/rpi3/rng/rpi3_rng.h +d3887ee8e4681e5e21d22c78756f8bb537359ef0 - arm-trusted-firmware/include/drivers/rpi3/sdhost/rpi3_sdhost.h +8865e3a5b086a9f57937f94373c1488796422a75 - arm-trusted-firmware/include/drivers/rpi3/mailbox/rpi3_mbox.h +affa2c8404660a48bcd956f29a50e79120b1cc3b - arm-trusted-firmware/include/drivers/rpi3/gpio/rpi3_gpio.h +a832f792f5fc9564b02d96f85430f190c3f57417 - arm-trusted-firmware/include/drivers/st/stm32mp_clkfunc.h +431e908bb797e10b7839fe28a0ace7d8a9e7bf99 - arm-trusted-firmware/include/drivers/st/stm32mp1_ram.h +eae4fb4ef015039f57a757e732fbfa815bc9aeb1 - arm-trusted-firmware/include/drivers/st/bsec2_reg.h +16d36c74e72bc40e7ba15ea25ce38621a3dc3a9e - arm-trusted-firmware/include/drivers/st/stm32_console.h +ae8d33f6e04e5baf46e8b00b1613dca79c462e1b - arm-trusted-firmware/include/drivers/st/stm32mp_pmic.h +b0e57331d216261ea6ec7814666ae64bd884dc05 - arm-trusted-firmware/include/drivers/st/io_mmc.h +51b50b86f5dea96ef59764df60f2d64a45d54bf1 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr.h +eaf998cd31b2112d0a61198a5a7f14d484217251 - arm-trusted-firmware/include/drivers/st/regulator.h +1b6f5d6f48fb0ceab8d15c6308e31e78e85bddba - arm-trusted-firmware/include/drivers/st/stm32_uart_regs.h +173981f3ca549df6d0e56fd0a16e4a055b9151eb - arm-trusted-firmware/include/drivers/st/stm32mp15_rcc.h +4cdb146eb6fe5439dec2c5039a903ed5baee6aa6 - arm-trusted-firmware/include/drivers/st/stm32mp_reset.h +b6eb16d19f62ff88852eab346d51d719944f14ed - arm-trusted-firmware/include/drivers/st/stm32_i2c.h +4b9518a5dba55fc1c78dc216a36ce0bb0e045155 - arm-trusted-firmware/include/drivers/st/stm32_uart.h +b6caa41ecb428bd2e6752e1a1f5a0c2ef3fcc953 - arm-trusted-firmware/include/drivers/st/io_stm32image.h +c13f39e45ffdff80cfe87c12423322a15b959794 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_regs.h +f2ca7edf66b0d71fec9b893659707c7675f9d0a6 - arm-trusted-firmware/include/drivers/st/regulator_fixed.h +58a87d375953ce331a480d18ecbe92da88b221df - arm-trusted-firmware/include/drivers/st/bsec.h +6c00673ea5fb61808caf3b77e422043972ecafc7 - arm-trusted-firmware/include/drivers/st/stm32_qspi.h +156ba43b85065027d400a1287fa794a828df162b - arm-trusted-firmware/include/drivers/st/stm32mp1_clk.h +7574c3687634e56e414a47e0fb3f5a5d7b1fc708 - arm-trusted-firmware/include/drivers/st/stm32_gpio.h +e02eff807301ff7775369975495cad2a2082972f - arm-trusted-firmware/include/drivers/st/stm32mp13_rcc.h +86a1ad6cd3ce837f820ba6c1b9f6ee7182e74956 - arm-trusted-firmware/include/drivers/st/stm32_fmc2_nand.h +91bfb605e20bff6aead18279afab90eed7856ddd - arm-trusted-firmware/include/drivers/st/stm32mp1_pwr.h +e6aa4130f95dc7da0f3a94482c2ee3325afdf0a0 - arm-trusted-firmware/include/drivers/st/stm32mp_ddr.h +967e02371bf07f76cf015635f5a50c0956176296 - arm-trusted-firmware/include/drivers/st/stm32mp1_usb.h +1735a240af4b99862e6cb202fc034231abeb53bd - arm-trusted-firmware/include/drivers/st/stm32mp_ddr_test.h +ac1cd6d311e2280721ba62f9e82c10322f6dad41 - arm-trusted-firmware/include/drivers/st/stm32mp_ram.h +cfbc99b7bba5966e33409c31f9f47cb7de63f66f - arm-trusted-firmware/include/drivers/st/stm32_hash.h +ff21abb6526ad91314e2f7cc58fa6fd6546c926f - arm-trusted-firmware/include/drivers/st/stm32_sdmmc2.h +45a56579470aa4ad7e007373a068f3285f046de0 - arm-trusted-firmware/include/drivers/st/stpmic1.h +bcfc65cd26c42c404b6482da16cdacf6e95c5733 - arm-trusted-firmware/include/drivers/st/stm32_iwdg.h +e86b4fde780cfae34213629b58ff8e1efd1eed73 - arm-trusted-firmware/include/drivers/st/stm32mp_ddrctrl_regs.h +e545051ef77d33ec66036fa94f2d53b51253d436 - arm-trusted-firmware/include/drivers/st/stm32mp1_ddr_helpers.h +cacf83dd6e129df0a9ffedbd38bfb757074d1240 - arm-trusted-firmware/include/drivers/st/etzpc.h +ec0355e035856ac49891ebbbfb6b249439fe6bc2 - arm-trusted-firmware/include/drivers/st/stm32mp1_rcc.h +f18d30ed876fb854340d329c32144778921ba136 - arm-trusted-firmware/include/drivers/arm/tzc380.h +cd54a5c35b74beeacb16c618204bb31eaa33126b - arm-trusted-firmware/include/drivers/arm/gic_common.h +0f5d3819208e8ad3ef2356f332aceaa4239dd8b3 - arm-trusted-firmware/include/drivers/arm/arm_gicv3_common.h +c269f40255323bed655d0c076e5fc771bee91550 - arm-trusted-firmware/include/drivers/arm/cci.h +ea619e78dc1630857e7bca57a8fb64b7d45583ba - arm-trusted-firmware/include/drivers/arm/pl061_gpio.h +3d28678861c6be73909a9fafa1e03dc8bed75dd5 - arm-trusted-firmware/include/drivers/arm/dsu.h +84502e34dabd2a899d93664cb540910ed8183f7a - arm-trusted-firmware/include/drivers/arm/gicv2.h +cad3fc32b992ec321fb47398d69df28d800ddfda - arm-trusted-firmware/include/drivers/arm/gic600_multichip.h +3c63f525fa4ab772695c59df263364d15f606582 - arm-trusted-firmware/include/drivers/arm/sp804_delay_timer.h +be5093d8f8d48610060e70ed9a8ee5602ad6739b - arm-trusted-firmware/include/drivers/arm/tzc_dmc620.h +1f2f3ae5b2636732d8a2b76e04392deacdc51203 - arm-trusted-firmware/include/drivers/arm/ccn.h +dcca36bec1c965c6413ab49729c23a771108058e - arm-trusted-firmware/include/drivers/arm/sbsa.h +eb064e58fc5aaf99768b3c9f167e6a369c5d51b2 - arm-trusted-firmware/include/drivers/arm/pl011.h +742d685c4e3046c1a64e99c18d00be7f1f9066fa - arm-trusted-firmware/include/drivers/arm/ethosn.h +2fa5a8cfd7f005b8d48960df0fa9dab5568d8059 - arm-trusted-firmware/include/drivers/arm/dcc.h +abaea50a4f3861dfaa3f55cba235dc00114b68f4 - arm-trusted-firmware/include/drivers/arm/sp805.h +c313d8aea2aa56300528293ebb42d4b35d46b18c - arm-trusted-firmware/include/drivers/arm/nic_400.h +0282c52c2cf6a737b53c9bcebcd089c5bf35ab24 - arm-trusted-firmware/include/drivers/arm/tzc_dmc500.h +8d3c051e8ba42150549dab299eca67bf73caf21d - arm-trusted-firmware/include/drivers/arm/tzc_common.h +8971a6e6b857b7b1e6544d6c3c9a52ca567a9e11 - arm-trusted-firmware/include/drivers/arm/scu.h +e133eeee905e96159734525bddeb5951f44fe0c3 - arm-trusted-firmware/include/drivers/arm/gicv3.h +7ca64097543e0475ded88ff1b0c756ea3e68dce4 - arm-trusted-firmware/include/drivers/arm/tzc400.h +ea5359158383d2c575b976cf638b586aa030cc49 - arm-trusted-firmware/include/drivers/arm/gic600ae_fmu.h +93e88fa1b74eaf244a0d0a7346c849ee43adbfee - arm-trusted-firmware/include/drivers/arm/smmu_v3.h +cb3a4608dbc689332bbeee2134f523d78ea6fcb8 - arm-trusted-firmware/include/drivers/arm/css/css_scp.h +c4e97cf187b8de349d494ab89ca4f5c1a83aadc7 - arm-trusted-firmware/include/drivers/arm/css/css_scpi.h +fdc34a2731639423ad5caeb5261f3207a4183cb1 - arm-trusted-firmware/include/drivers/arm/css/css_mhu.h +2199dceebbe76121f35942566cde95a239340491 - arm-trusted-firmware/include/drivers/arm/css/sds.h +faa54f13bf1956078c447ae298b4696adc11ec16 - arm-trusted-firmware/include/drivers/arm/css/css_mhu_doorbell.h +644885f6d536f0b9fecf9b19db5324cebdb1cd00 - arm-trusted-firmware/include/drivers/arm/css/scmi.h +749ed7a2a602879315a2a407faa53d9fcc6f4242 - arm-trusted-firmware/include/drivers/arm/fvp/fvp_pwrc.h +7d87f35690f4d41b9739eb995465900a8070b7d9 - arm-trusted-firmware/include/drivers/arm/cryptocell/cc_rotpk.h +3ffecadd4db08d4069780170baac205025ed7194 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/rsa.h +e14a50e8d5c68b36920485b6db04f106817437e3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_crypto_boot_defs.h +d82ceff72eee2f6f805404b84357273d1eb09561 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/sbrom_bsv_api.h +10652996fa07e69877d9fb73449f7ab46d59ffa3 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/util.h +260990d658ffc91bafbece3081bb60c30618fa38 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm_otp.h +fc07b65f9cc014a0b1524b0068e8beccf88374cc - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_sb_plat.h +e610cb68e48f78caf111024d142af863b6398636 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/crypto_driver.h +5d04efda071e5940b11e2d270b3dae82a55dc93d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_sec_defs.h +6e4f8a88b84a4ce3b762b6c7f14ac5fec8744012 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_gen_defs.h +4639b7108f03bef1a92e980f8ee8eff03be1d869 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/secureboot_base_func.h +c55427770d64593e3cf15b3ed93e6488363b575d - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types.h +d73a1ca5bfea93a55e5c13b2b3f2051e3c0d7c12 - arm-trusted-firmware/include/drivers/arm/cryptocell/712/cc_pal_types_plat.h +49417191c51d1d9274572285c8ba5a8c8146e57f - arm-trusted-firmware/include/drivers/arm/cryptocell/712/nvm.h +5ff025817e96abd32dab9c26c2d10d5116b211f8 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_api.h +93088698293330d0f56eaabb73e01615b19fed64 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pka_hw_plat_defs.h +fb12a0265111fe6f1b941f06d20f54b9439c689a - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_error.h +a182cb9bf34d396f46abd93062d06ce6ee8889c1 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_address_defs.h +bf88a456fd40edb9bb68b2450d6251cda06f2465 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_sec_defs.h +a8d2ea546937a35c7f822dd9e1a7e8eb3fd4438f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_boot_defs.h +f48f4abf712cac68d01844cb146aa3c6e787e97c - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_defs.h +a9419e34fbc18ae5da0ef1566f5febc0cf829211 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types.h +513b5a19f2f0b580cf670eca60e57e793cac539f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_crypto_asym_api.h +13f5321936540bd85461ffa7ef611ca5d4082977 - arm-trusted-firmware/include/drivers/arm/cryptocell/713/cc_pal_types_plat.h +b69f3dd73cff9fd442b44ed25f2edbb0bc3baa5f - arm-trusted-firmware/include/drivers/arm/cryptocell/713/bsv_api.h +cb4a166015b83acf19a78617be8e774abc6e1798 - arm-trusted-firmware/include/bl32/payloads/tlk.h +61531a0b7ca81943d7aebe7d3183f30c4b6b42b7 - arm-trusted-firmware/include/bl32/tsp/platform_tsp.h +dc1975b639c5dc6b8eee34ada66bffcbd10d3047 - arm-trusted-firmware/include/bl32/tsp/tsp.h +0978d63d1beeeb3f432496ea56acf6f3cf4d2072 - arm-trusted-firmware/include/bl32/sp_min/platform_sp_min.h +11335e71ce700055225b4223bb4218122db63853 - arm-trusted-firmware/include/bl2u/bl2u.h +76f24b5df32a33ff953257acc268f140bef007d8 - arm-trusted-firmware/include/bl2/bl2.h +cf5f556d440245d73b0f784be4662e7cd634f39b - arm-trusted-firmware/include/lib/coreboot.h +9637b2573e1df004bff5258027eee07e6d532cf9 - arm-trusted-firmware/include/lib/cassert.h +7ffbca071dbd690b9d0ac30e6b388a848c55cc16 - arm-trusted-firmware/include/lib/semihosting.h +90db5a8e9962b61142ef6eed7165cb5967d686be - arm-trusted-firmware/include/lib/optee_utils.h +f68ef15137b41ae5e5fd646d5b7624ff9843b770 - arm-trusted-firmware/include/lib/smccc.h +1f698e99c775d463461fd358a896217604420ef6 - arm-trusted-firmware/include/lib/runtime_instr.h +0b8f22e03d35106f8213bb63f81feeefe40d0675 - arm-trusted-firmware/include/lib/bakery_lock.h +de7b34ae4f5c2aa97efbb717d681f3f79f6b3a80 - arm-trusted-firmware/include/lib/mmio.h +b1522d52a6103e87ea31e7207f54208dd2c5a6af - arm-trusted-firmware/include/lib/debugfs.h +94cb452f38b47933f36d4af26e71b749a5ce2efc - arm-trusted-firmware/include/lib/utils_def.h +73dc3acb5868e207313dcdae4f6884d5c179faaa - arm-trusted-firmware/include/lib/utils.h +06aee725316857addfb02415a55463647ed20701 - arm-trusted-firmware/include/lib/object_pool.h +ed4976b8261e1ee44f4a2b7952563b6db8e63406 - arm-trusted-firmware/include/lib/spinlock.h +fcc42874d57314ab77ad7f2a2c1b2eb3862a576b - arm-trusted-firmware/include/lib/extensions/amu.h +802b885838cc683c33d5bdf0db010936d1d60c40 - arm-trusted-firmware/include/lib/extensions/sys_reg_trace.h +d9ddc757d1632d6d25a30937684cae6ef3ee6a50 - arm-trusted-firmware/include/lib/extensions/spe.h +cc7362066d33e226e7e9996002c683aeb7291017 - arm-trusted-firmware/include/lib/extensions/trf.h +09511d96743a49bd6a8ce53a10a7a63f66fa69eb - arm-trusted-firmware/include/lib/extensions/ras.h +49864e971e8571d9d0cb63bce06594f6c8b5d684 - arm-trusted-firmware/include/lib/extensions/mpam.h +b60784e6b65f97973b6399350a6bb41d508cb993 - arm-trusted-firmware/include/lib/extensions/ras_arch.h +08342ec02a973e05865c7a200258f0949f7e0948 - arm-trusted-firmware/include/lib/extensions/trbe.h +5e43959b0322424d6c58374b9bf52ca3435e88c1 - arm-trusted-firmware/include/lib/extensions/sme.h +a3c002de51adf7dd52647cf5c6e3f6e119634fc9 - arm-trusted-firmware/include/lib/extensions/pauth.h +84ebabfad9a6aea5b36eca181ecacd9f81feaf8b - arm-trusted-firmware/include/lib/extensions/sve.h +46afc6f495640a910a40703306195c7a6c3a0833 - arm-trusted-firmware/include/lib/extensions/twed.h +1c0e9271a240a44ae26fe23c9d0bf4f2aefdbaa8 - arm-trusted-firmware/include/lib/psci/psci.h +03fe8d1844f9117cf59adf7bb69cbcef990c16c3 - arm-trusted-firmware/include/lib/psci/psci_lib.h +84b28157b2cc81f5a9aa46c6edf2de6083f696bd - arm-trusted-firmware/include/lib/gpt_rme/gpt_rme.h +c90d25bb7b217171ad9437ee0bc8d4e0c5c7f4d3 - arm-trusted-firmware/include/lib/libfdt/libfdt_env.h +ec87fea0386b1dcc840a14b66f68bb20746774d2 - arm-trusted-firmware/include/lib/libfdt/libfdt.h +26e37a910f19c0fe0293821c838312e998579df1 - arm-trusted-firmware/include/lib/libfdt/fdt.h +a9be03deeaf86090c4056f6844a1dafec0a14683 - arm-trusted-firmware/include/lib/xlat_mpu/xlat_mpu.h +ff1f378cc136ea5bf58c5fe0df726e1d809c7efb - arm-trusted-firmware/include/lib/zlib/tf_gunzip.h +531877858c00a04ba41ba7d211235fcad2bf2f77 - arm-trusted-firmware/include/lib/fconf/fconf_mpmm_getter.h +1cc2ff30d9d45589c3c7fa34a79ab141314e4974 - arm-trusted-firmware/include/lib/fconf/fconf_amu_getter.h +fad98eab51c54e641e9db5451eceb044f426276c - arm-trusted-firmware/include/lib/fconf/fconf_tbbr_getter.h +d152cc84bd5ddb5c62bb91fe605ebd55b28b2585 - arm-trusted-firmware/include/lib/fconf/fconf.h +b61fcbdcf35b00e7cf2a5c7feff04fc5d28e7e6c - arm-trusted-firmware/include/lib/fconf/fconf_dyn_cfg_getter.h +0f9c6bddf555b127d0deea955abd911c85bc89b9 - arm-trusted-firmware/include/lib/mpmm/mpmm.h +58569d6f8289cc5c665cc6dd3455a31057e6209f - arm-trusted-firmware/include/lib/cpus/wa_cve_2018_3639.h +55da8ccc24cdd5cabba3e346f04694958ca9b84a - arm-trusted-firmware/include/lib/cpus/wa_cve_2022_23960.h +d44192225758ac451b1c5bc5111f98c453327523 - arm-trusted-firmware/include/lib/cpus/wa_cve_2017_5715.h +7a7b59a035c26b0ced83b40114b596358f1bd2c4 - arm-trusted-firmware/include/lib/cpus/errata_report.h +3f7b45d32e48e60ee32229b7e8f5860b6e67747e - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a72.h +055e82d4e76261ce1a2108d14cea7176cf18c0a9 - arm-trusted-firmware/include/lib/cpus/aarch64/dsu_def.h +b58c922be5d4bad0866dbb86570d6f9e94310f89 - arm-trusted-firmware/include/lib/cpus/aarch64/rainier.h +7de432330be3e8f54c1e573f4ab59d51806e7365 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hayes.h +ed260f8199efb4c6b1d32218c83039568c4ef425 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65.h +82d90eaba5c3e4a0d0d67cdc9bb41cf9f9d2aa35 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a710.h +70560b6cca33e37badb4f0e52e2781166227184c - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a55.h +42b29f7ea79198fbf5aa69a3aa080de56572fa3a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_demeter.h +32b8e77c476293848bb5884355c7faf95069f8c8 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78c.h +e762cbd4ef8859eb8d8ebd03899ec10c085ce1b5 - arm-trusted-firmware/include/lib/cpus/aarch64/cpuamu.h +efc8411aa80d03690795c5caab5213f739c3dae2 - arm-trusted-firmware/include/lib/cpus/aarch64/generic.h +b2ba28f5ae615b85d1e4f9417e53743767f749e5 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a510.h +3c127123c7f793221554840dbafc9aecc3acb322 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_v1.h +43952567938e0452e6f1cd65b6fab276d3b628e0 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_hunter.h +b9a6a19c148f0fb9ef9b3e03b113a48c319f50ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78.h +9a1b5aa467e9d2d3b68dbfdc3d96397743562185 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_e1.h +4f1b3a7c5699c6ae409698b593edbc6ac8d2a861 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a73.h +309db7cc6a48f2dfc2fc82dad3300ad2825efae6 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a75.h +7c2b1650f6c338afe9ce5b81aaf9c15b6c358c98 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu.h +fee71b3ac82a2185c4d87e46ee0883cd51017f0f - arm-trusted-firmware/include/lib/cpus/aarch64/denver.h +e7bf4db6f79577db296e4c8444c731b2e3af4822 - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_poseidon.h +26f966576d1ba5fe1e871578dea3ea004be5ee67 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76ae.h +7f4a54bf5113ee54ee16d5400921730610b81a5f - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a78_ae.h +80bf6905c50e6839862d8fc71c9406f081533252 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_x2.h +cecb6b77ddae233e9012f44da229b0f25904b481 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a65ae.h +fe7e88bb537bded4caa68969291e0f7582e7abe1 - arm-trusted-firmware/include/lib/cpus/aarch64/qemu_max.h +fb525a4bddf12d5307fdd7d77fe2c90783b76d85 - arm-trusted-firmware/include/lib/cpus/aarch64/aem_generic.h +22958de97bf4027cc040fc0ac360db1706c214e9 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_makalu_elp_arm.h +316e8929890c4678843eeb9c9f055e3d7b37419b - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a53.h +84e558d38ecba4e5f4d2f894a9291c5037ce66ed - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a57.h +e06ae7d94772d2e7df59aaed91759743f3614979 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a76.h +6f80e2ceb55f9179c0e8b9d91d249e62d6b1face - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n_common.h +44559a7bdfb73f25458f7ca2b0e8c8785ef8827f - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a35.h +31b87fd75812c21215587c76fc574207c546b735 - arm-trusted-firmware/include/lib/cpus/aarch64/cortex_a77.h +b5de08d6bad3b4fa6d103de5fdccbe1dd027b1e2 - arm-trusted-firmware/include/lib/cpus/aarch64/cpu_macros.S +e67d118e55ce590ff3f6428280713a78b8eed58a - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n2.h +03c06290a053bfb539077f235d6cbd00efa9839f - arm-trusted-firmware/include/lib/cpus/aarch64/neoverse_n1.h +7c549b2ab4e1d1d0e0a845e601e8778c8c5016d1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a72.h +4f8e78fb1d10bb5da1ae6792f2775a2e3d34e739 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a5.h +b3f572f2b6af62ea012727754cd52c72ab76a8cb - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a9.h +bb26a1dad2c7e0bc860a422313a21fe96c5818e7 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a7.h +b4398b2cbe8c44396c14071dd547d3b4ae231f11 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a15.h +f05e12dd19967571232d263c83c6898dc9f9c9b1 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a17.h +7246c771a29d42ce8df39025143fedec1f1d22ea - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a12.h +964ef94b44f29b27af9693592b55d5e045c68898 - arm-trusted-firmware/include/lib/cpus/aarch32/aem_generic.h +ab3b500c80e0bf48a6fa1b8aa0cedb3451312f73 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a53.h +4f2016b0ee0a27a62e127a3e9e49889a8cb0d63e - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a57.h +a90685421214c1862d537af563def9b63894e740 - arm-trusted-firmware/include/lib/cpus/aarch32/cortex_a32.h +b28242a3c70922add954edac6ef6a6cc27eef33f - arm-trusted-firmware/include/lib/cpus/aarch32/cpu_macros.S +cfcb8f035cda18f894c8ee194d3136fc61406fe0 - arm-trusted-firmware/include/lib/el3_runtime/pubsub_events.h +db010d01a2298bde5d192dc8ca42d487ad8023ac - arm-trusted-firmware/include/lib/el3_runtime/pubsub.h +df57266f0878fdff7b3180dfc258dae3ca1859cc - arm-trusted-firmware/include/lib/el3_runtime/context_mgmt.h +926a8f99c7871413aa6c48ee91bcacf8ea07e438 - arm-trusted-firmware/include/lib/el3_runtime/cpu_data.h +38bab004d095d8c31cc1bb191af9e3c4ee45ca02 - arm-trusted-firmware/include/lib/el3_runtime/aarch64/context.h +9c3df6c4d9ecf03368ef7a5cd150157123c12ed1 - arm-trusted-firmware/include/lib/el3_runtime/aarch32/context.h +147505a24c5c0680f8c21cd8b77aaa1ed3d9af0f - arm-trusted-firmware/include/lib/xlat_tables/xlat_mmu_helpers.h +748f4763c6956e3a05b07a06f88394f925375806 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2.h +a5b742f0a88671c56d4acb2c9f41a2859ccfe63c - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_v2_helpers.h +0ea4285dd4504af01f2379c11c6b04292b5224d0 - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables.h +ffd6aa77c205ba28fc3cdedfdf92ad949a1d2c4e - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_compat.h +64b082be684d2e9aac73592fc4658c81ded65fcc - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_defs.h +d096d2c939939ac7e3ce5358c63127a2e48fc66d - arm-trusted-firmware/include/lib/xlat_tables/xlat_tables_arch.h +135853a26b41e70bb03df6feaa46157020f24f43 - arm-trusted-firmware/include/lib/xlat_tables/aarch64/xlat_tables_aarch64.h +ef0a81e88f09c2c6ce252f01c0405fa13cf09822 - arm-trusted-firmware/include/lib/xlat_tables/aarch32/xlat_tables_aarch32.h +9b838f7bd9f2c4493efedef614f584d30c32546d - arm-trusted-firmware/include/lib/pmf/pmf.h +bf81e2d1db65ed903ef83af8c902a2c570f7d8d7 - arm-trusted-firmware/include/lib/pmf/pmf_helpers.h +2e8bf007844002145509b02185c1cfb380c086c7 - arm-trusted-firmware/include/lib/pmf/aarch64/pmf_asm_macros.S +be45471818b5fb856ed0fc1c303a3439ac749d6c - arm-trusted-firmware/include/lib/pmf/aarch32/pmf_asm_macros.S +72f4645c807c6915c0628b0d200b18fba404f91c - arm-trusted-firmware/include/lib/bl_aux_params/bl_aux_params.h +2f17e8f91531cbdb0dcb5638ffe35b4fc35169f4 - arm-trusted-firmware/include/lib/libc/endian.h +28d598da1ead2bf6ee9fd764635deb7d1a082fc9 - arm-trusted-firmware/include/lib/libc/stdbool.h +05293dcd9dcd66e6fbc14019807633a277c3a53f - arm-trusted-firmware/include/lib/libc/time.h +96064295890c1e484dfcf96039b0cf5c4babd361 - arm-trusted-firmware/include/lib/libc/setjmp.h +5e084e86fa5e4b5fdac774d1aa00b279f68d3c40 - arm-trusted-firmware/include/lib/libc/inttypes.h +b37dff6a9fa0fe100e6e204676f60358dfde29eb - arm-trusted-firmware/include/lib/libc/stdlib.h +81fc18b0518ed12942398f24157b26767f2b5d58 - arm-trusted-firmware/include/lib/libc/stdio.h +83a3b49d103b8453fb98b0625c759bf39c09803e - arm-trusted-firmware/include/lib/libc/assert.h +1f519accd161baa49f478a735728f1b81dd9a443 - arm-trusted-firmware/include/lib/libc/stdarg.h +d0d4318e609c76661d8f0144b559d4c7e5c43cce - arm-trusted-firmware/include/lib/libc/limits.h +0d835510f380ad8267995f98edca212d0c2d8f72 - arm-trusted-firmware/include/lib/libc/errno.h +3ad9051758ee29a3d96abe5881f5a7740eb10550 - arm-trusted-firmware/include/lib/libc/cdefs.h +fec91d22fe696952ba93c2d1ed6cedfa714a5a7e - arm-trusted-firmware/include/lib/libc/stdint.h +167e84c7f69dda6dbee48fff38839436941dfe1c - arm-trusted-firmware/include/lib/libc/stddef.h +de263df3e964aac45b0a9be4096eb2a12c63d72b - arm-trusted-firmware/include/lib/libc/arm_acle.h +38027460aea214583844c4cb07db44077673acc5 - arm-trusted-firmware/include/lib/libc/string.h +8741dd9ddf232520a7e68bd21382fd53539b8c5b - arm-trusted-firmware/include/lib/libc/aarch64/stdio_.h +94f633f89b9ae70068fb70432456057bd04bb750 - arm-trusted-firmware/include/lib/libc/aarch64/endian_.h +dec49d90238a3dc066022d9268b1172c93e6bd29 - arm-trusted-firmware/include/lib/libc/aarch64/inttypes_.h +81dc661e625cc7228b67c09aea60df34e729c283 - arm-trusted-firmware/include/lib/libc/aarch64/stdint_.h +a0ec98e34e93c55ac6fc9241cbaed06bc372bb39 - arm-trusted-firmware/include/lib/libc/aarch64/stddef_.h +c881950de56de06d14e10e06d219c0ad40613034 - arm-trusted-firmware/include/lib/libc/aarch64/setjmp_.h +e3ba7ed7d41ae3a8c9dd07d94f7bbef48adf165a - arm-trusted-firmware/include/lib/libc/aarch64/limits_.h +8eaba3f90b7b124e01dd67a505f4e8dac6d42826 - arm-trusted-firmware/include/lib/libc/aarch32/stdio_.h +5d60818c76a8f8d0645d40e13fb9c6bba183e2ac - arm-trusted-firmware/include/lib/libc/aarch32/endian_.h +5504c60845bc40c22309d19ad3a370854542606b - arm-trusted-firmware/include/lib/libc/aarch32/inttypes_.h +99fb55bd4f7021bebc906bdfbf7f2e0a32e198f9 - arm-trusted-firmware/include/lib/libc/aarch32/stdint_.h +4ffa8f28ee204e4445f86ee9e68903c66fb5487d - arm-trusted-firmware/include/lib/libc/aarch32/stddef_.h +c6119d73104bf3ae1d27bac47db49a0fbbdcd112 - arm-trusted-firmware/include/lib/libc/aarch32/limits_.h +d33d416f27b0a754a92dea111013ae91e9fe09fc - arm-trusted-firmware/include/plat/common/platform.h +ec1ba9f6e5e5199a8174963440c8673120fd65e0 - arm-trusted-firmware/include/plat/common/common_def.h +9cd1950e6a5ff8b2dcd0143c1dfe498c7804a1f0 - arm-trusted-firmware/include/plat/common/plat_trng.h +0ad5bfa2837c10aafe72e696c238db4ebd82794f - arm-trusted-firmware/include/plat/brcm/common/plat_brcm.h +5d91bb2b767050d467d072d4e6d7036d8c71d06a - arm-trusted-firmware/include/plat/brcm/common/bcm_elog.h +e639b2614ce8c77a52995ee2da45fe54fbb8dc2e - arm-trusted-firmware/include/plat/brcm/common/brcm_def.h +d7f8e1c595627094eb1807e5f15cbb7674cb02d5 - arm-trusted-firmware/include/plat/brcm/common/bcm_console.h +dc4318dff472842b4c63c7b87f23c3688def3c5a - arm-trusted-firmware/include/plat/marvell/armada/common/mvebu.h +9dd486928223e599a25bc6f13b414fc57c242b36 - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_pm.h +8cdfa6f8ca1d681ba760da2fe49c8f365ef0dcbe - arm-trusted-firmware/include/plat/marvell/armada/common/marvell_plat_priv.h +e2d034b7bbecdf28360fcf107159eae0bf87de48 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/cci_macros.S +b7faf2c71aa5d9ab793eadfeb28cd9effe284930 - arm-trusted-firmware/include/plat/marvell/armada/common/aarch64/marvell_macros.S +98c1515593c3e784076edd107c7aa20f26d00900 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/marvell_def.h +618289fd2c98548dbc401a283df9d3c6386ce002 - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/plat_marvell.h +71dfe89c5f0b7453c5e1af8a81c440aea8ecb34b - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/board_marvell_def.h +e6b0db0b8079bfb25c6c3257a0bc6403591a354f - arm-trusted-firmware/include/plat/marvell/armada/a3k/common/armada_common.h +36e0657b50b40ad54b3ef6b8b6848377fa423ee2 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/marvell_def.h +6e72bb219cdd7c32b97b3df3a2fd695dab5d6fc4 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_pm_trace.h +8d91b9ddc816f6cc8b89cdde08ef32b86e76f779 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/plat_marvell.h +79fec062b150f074e53c3a4b1987aea42e5a4eff - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/board_marvell_def.h +5eb5b60a95f1d5821d119a38a870719cd6345ca8 - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/armada_common.h +48923d6fcb9d9e02790b158b5eaf6edb34db109d - arm-trusted-firmware/include/plat/marvell/armada/a8k/common/efuse_def.h +64f1e7c2408515cbabe2321cf6584901213dcf2b - arm-trusted-firmware/include/plat/arm/soc/common/soc_css.h +a4c302b222e019205abf65fd01745d571d810ce7 - arm-trusted-firmware/include/plat/arm/soc/common/soc_css_def.h +b6516d7703c189ab60f935aae9db8c643bb2d84b - arm-trusted-firmware/include/plat/arm/common/plat_arm.h +0afd9c0926d88821488dcd5686914fd1ccee3763 - arm-trusted-firmware/include/plat/arm/common/fconf_sdei_getter.h +eb2f94f2fc7e75343b6ebf27607b356ad90cdb7f - arm-trusted-firmware/include/plat/arm/common/arm_fconf_getter.h +62a021ac07cc197af73c3a77f81b2e3c269b7cb0 - arm-trusted-firmware/include/plat/arm/common/fconf_ethosn_getter.h +1fd41daca5740b134bd9df3d981f66ab2fea4f52 - arm-trusted-firmware/include/plat/arm/common/arm_reclaim_init.ld.S +971368d067997c8cf7b990346646cedab7fb9189 - arm-trusted-firmware/include/plat/arm/common/fconf_nv_cntr_getter.h +88fe915ca8ec7f1f3499a57f534e1396c6b7c98e - arm-trusted-firmware/include/plat/arm/common/smccc_def.h +fdc727288dd453b4dcf18b744fc052a039bed405 - arm-trusted-firmware/include/plat/arm/common/arm_dyn_cfg_helpers.h +b9070936733be0fa95be33772381b15e63ef79b2 - arm-trusted-firmware/include/plat/arm/common/arm_sip_svc.h +44ce8058a0b197c5c89e419bcebc0ddcd8434c36 - arm-trusted-firmware/include/plat/arm/common/arm_spm_def.h +9437b8c5d8cf84ec02a69c03b1658cfe00ce9a70 - arm-trusted-firmware/include/plat/arm/common/arm_tzc_dram.ld.S +85db4d68c709e11a4b63da0a434f5aeeef2aadec - arm-trusted-firmware/include/plat/arm/common/arm_fconf_io_storage.h +32a205b639eaf056873e852af9f2f925782878ef - arm-trusted-firmware/include/plat/arm/common/fconf_arm_sp_getter.h +36a2614776249ab76e9c86d1f08fd0057bab8263 - arm-trusted-firmware/include/plat/arm/common/arm_config.h +76e5f8f29adea5aef863105a24eb9d29d8be3952 - arm-trusted-firmware/include/plat/arm/common/arm_def.h +f0fb541bb623a169168129c94b788f2a409ffb5b - arm-trusted-firmware/include/plat/arm/common/fconf_sec_intr_config.h +bcb4189176bf949ae7ccbb1fb72c9d29b366f7e4 - arm-trusted-firmware/include/plat/arm/common/arm_pas_def.h +657f1176fd4f82dc1155d86438b6fbf624d2747a - arm-trusted-firmware/include/plat/arm/common/aarch64/cci_macros.S +3bb163e8411b70a5b6f5913631e64392b3154151 - arm-trusted-firmware/include/plat/arm/common/aarch64/arm_macros.S +0081d14a9dd87bdab5919da6391eb2275fa7e94a - arm-trusted-firmware/include/plat/arm/css/common/css_def.h +68405ab09471b8d13fcf6f7e2b8f07a8012d11b8 - arm-trusted-firmware/include/plat/arm/css/common/css_pm.h +406bbb095f6bf7f140e7814e98b0ea99062ad767 - arm-trusted-firmware/include/plat/arm/css/common/aarch64/css_macros.S +fe0efb2292b7b971908fcd44d634894276a51f1c - arm-trusted-firmware/include/plat/arm/board/common/v2m_def.h +81ed90e8c99ac6343426728d9299d8ad48305d39 - arm-trusted-firmware/include/plat/arm/board/common/board_css_def.h +40577c7bc2464cf873f1f2708e2db8112b51374f - arm-trusted-firmware/include/plat/arm/board/fvp_r/fvp_r_bl1.h +e1699b761cd12de148f701d78db5c24eb3aa7251 - arm-trusted-firmware/include/export/README +45ecabce41da084db92b27dd88e6e89f30506036 - arm-trusted-firmware/include/export/common/ep_info_exp.h +91e15bef63bb89bfd921b4d01d17b37dbeff291b - arm-trusted-firmware/include/export/common/bl_common_exp.h +60669a2cabdf40b63773d538d47861c1a584f800 - arm-trusted-firmware/include/export/common/param_header_exp.h +c2a9a69314ba3b3f2369c8c876b39d8acda1b018 - arm-trusted-firmware/include/export/common/tbbr/tbbr_img_def_exp.h +9367cefce0520648ccdaad1fe3a402422becdf55 - arm-trusted-firmware/include/export/drivers/gpio_exp.h +5091c9e14c49f9799bc9985442295e882a14d3b0 - arm-trusted-firmware/include/export/lib/utils_def_exp.h +72b925e2450734e1991799db8cc30f6a8609462a - arm-trusted-firmware/include/export/lib/bl_aux_params/bl_aux_params_exp.h +9bb9fdc2ec0963a6cbbd0188ae70e368e67755f2 - arm-trusted-firmware/include/export/plat/mediatek/common/plat_params_exp.h +dcd0ca426668c19ab921df2fefbf2d83ca5afdd8 - arm-trusted-firmware/include/export/plat/rockchip/common/plat_params_exp.h +a628d4b48c67b17cc32449aacf6052a52eea1705 - arm-trusted-firmware/include/tools_share/uuid.h +1fda7d8e566efd28aaedd2f5d1ae43b5bf4d2705 - arm-trusted-firmware/include/tools_share/tbbr_oid.h +58d6bf8cd75f220139c010d1d5fb6e0a96d4564a - arm-trusted-firmware/include/tools_share/dualroot_oid.h +b279cf845b5ea6ce93f6563029c2dfbe6f85a541 - arm-trusted-firmware/include/tools_share/firmware_encrypted.h +3e0251958205aa29f860e4627e7f29098e266f1d - arm-trusted-firmware/include/tools_share/firmware_image_package.h +5219a8b9ae1ae1722063974c9bedee960cfa351f - arm-trusted-firmware/include/tools_share/sptool.h +7185228489bf2c4e562f37a9f927cbc31c18ced1 - arm-trusted-firmware/lib/aarch64/cache_helpers.S +da63c15641cb6cf532770db54efc30b3f8122a7c - arm-trusted-firmware/lib/aarch64/misc_helpers.S +96718b39d24ee4ca5fd1eb4f87d53c45c9e4f079 - arm-trusted-firmware/lib/aarch64/armclang_printf.S +4ef2e504a667d7529f6e9f0629c04db77435a28a - arm-trusted-firmware/lib/utils/mem_region.c +da13fbd30292be6162a14bb7866fc3da5fce2c10 - arm-trusted-firmware/lib/extensions/sve/sve.c +afd6141e2e07c1fd692c8e845ce6e65899fbbb7d - arm-trusted-firmware/lib/extensions/amu/amu_private.h +7f3f609a1bb0c4b5287f43cd817a535c4e497353 - arm-trusted-firmware/lib/extensions/amu/aarch64/amu_helpers.S +896aead96745f721f995de07ec7a83fc77ffc33f - arm-trusted-firmware/lib/extensions/amu/aarch64/amu.c +3dbb067dc92b40dd63f5ee3b50d0e88978e7e528 - arm-trusted-firmware/lib/extensions/amu/aarch32/amu_helpers.S +21d2bec3b0a822561dc68c9dab32b97d35ea848a - arm-trusted-firmware/lib/extensions/amu/aarch32/amu.c +1e8ea4b9d81a41c874fd1c0e7b3915a5337cf966 - arm-trusted-firmware/lib/extensions/mtpmu/aarch64/mtpmu.S +aee505d9d1071c6c819d07bc02c1e963cf8c6025 - arm-trusted-firmware/lib/extensions/mtpmu/aarch32/mtpmu.S +4125c51fd3f075d4d291f56b53175ca0683e12eb - arm-trusted-firmware/lib/extensions/spe/spe.c +672dc9ce8ca19e9bad297552bb38f03725d544b2 - arm-trusted-firmware/lib/extensions/mpam/mpam.c +20945ff7a4f02b5797f9043d0dd1dcb655476c0b - arm-trusted-firmware/lib/extensions/sme/sme.c +ba76ca96162e88bc6bc13591b4dbe2d955320a45 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch64/sys_reg_trace.c +ecb8e335fe4a2681e714ea9d5c5f2b8f5e1a8e07 - arm-trusted-firmware/lib/extensions/sys_reg_trace/aarch32/sys_reg_trace.c +ebe5066f50de32f019ea11419b6ef11da4604812 - arm-trusted-firmware/lib/extensions/pauth/pauth_helpers.S +785751601e97ed8f6b006cbe5a6e26dac81addf3 - arm-trusted-firmware/lib/extensions/ras/ras_common.c +9b56d2cedbd5417e75959a7c83b6361dc3c48f6e - arm-trusted-firmware/lib/extensions/ras/std_err_record.c +1acd16a1b33cf990f1093d8f0ba9c0ebd7a6f719 - arm-trusted-firmware/lib/extensions/trbe/trbe.c +e3dc484cb8d981ceb0cdc03a7bdb8f24e2f9ae85 - arm-trusted-firmware/lib/extensions/trf/aarch64/trf.c +5ccbd178b5c5eb953d97ca519229837a0537e821 - arm-trusted-firmware/lib/extensions/trf/aarch32/trf.c +70011c90369b5b9a9d55faec233e60b90b31801e - arm-trusted-firmware/lib/locks/exclusive/aarch64/spinlock.S +edf2b7a02784eccffa70a8f06817929dd1a8f993 - arm-trusted-firmware/lib/locks/exclusive/aarch32/spinlock.S +b3453819b2250ed7f47a81d57ce565f8d644ddaa - arm-trusted-firmware/lib/locks/bakery/bakery_lock_normal.c +cf339f00e977a47612e93384a6a0b8e73d731c21 - arm-trusted-firmware/lib/locks/bakery/bakery_lock_coherent.c +ddcc3c9570f910954693aa27a5b355d4a84f2ac5 - arm-trusted-firmware/lib/psci/psci_off.c +dc70197a71b51add43f68a1708e572069b991b10 - arm-trusted-firmware/lib/psci/psci_common.c +96cf95201b14289b9fd8994f635436bd603c2e2c - arm-trusted-firmware/lib/psci/psci_stat.c +70484461d77679b66812b09dd8b56cb0c17acaf9 - arm-trusted-firmware/lib/psci/psci_mem_protect.c +829a7e8232b3efde8c6ad84aff7745c16582da77 - arm-trusted-firmware/lib/psci/psci_system_off.c +bb2c6a22fccb6b37506ba1b0bc6ca6db53f60051 - arm-trusted-firmware/lib/psci/psci_suspend.c +dc79080304d8fd3b4fee3f3ab53559b3a1008d90 - arm-trusted-firmware/lib/psci/psci_private.h +268386d92529e4c7ffed1ece69a88ebc933c34e2 - arm-trusted-firmware/lib/psci/psci_main.c +741cb1ca4722a4062052f5ec8cbb9d6f1d4ee468 - arm-trusted-firmware/lib/psci/psci_setup.c +a45af64e61c40345d7034444490e7fd33b52606e - arm-trusted-firmware/lib/psci/psci_on.c +2c7b752ae78666bc171dbc6858abbe2c9cff4013 - arm-trusted-firmware/lib/psci/aarch64/psci_helpers.S +e3019770bfa11512ec7d2d6785e37d28c72cd2c9 - arm-trusted-firmware/lib/psci/aarch32/psci_helpers.S +ecf8ba50075277e075334d8bf2192d3a03b4d713 - arm-trusted-firmware/lib/gpt_rme/gpt_rme.c +edbe27a26695b90b039ea42ae87e3756c047631a - arm-trusted-firmware/lib/gpt_rme/gpt_rme_private.h +7b5870894878b452bb2f89fe98f1e15591a599b9 - arm-trusted-firmware/lib/semihosting/semihosting.c +79d2f0e3c6477c7632a9d7b9d01b42625bf0cbb3 - arm-trusted-firmware/lib/semihosting/aarch64/semihosting_call.S +bed75bc5da772504027fb7c033a1c918acc82c48 - arm-trusted-firmware/lib/semihosting/aarch32/semihosting_call.S +3af779f4c2869b4f4f96ca46039bbe9311cfefa4 - arm-trusted-firmware/lib/libfdt/fdt_rw.c +d63d474ccc4d93be45267b9c0a32c3c88c4f42cf - arm-trusted-firmware/lib/libfdt/fdt_overlay.c +c3bed95f695f7f9780ea064580ce245fa8dc6611 - arm-trusted-firmware/lib/libfdt/fdt_ro.c +3aae059b21ecd4f923c8f399d4c2dd101ce03502 - arm-trusted-firmware/lib/libfdt/libfdt_internal.h +c7bf913dd7eabfba85f363d7a05851e84c786828 - arm-trusted-firmware/lib/libfdt/fdt.c +c16e3571ab87b0ea9f8067989a5b0f97251ff8cb - arm-trusted-firmware/lib/libfdt/fdt_wip.c +e01b7a0052b837a4650f2c9ac75ad38c40edc583 - arm-trusted-firmware/lib/libfdt/fdt_empty_tree.c +6db863ac215fcf8880798469701f80b2fc197bcc - arm-trusted-firmware/lib/libfdt/fdt_strerror.c +55fc5d2ffcba07e29948822d0b12e4bf5546b8b8 - arm-trusted-firmware/lib/libfdt/fdt_addresses.c +e6ac4a37689f70dd9fd01a67cabe4439d66dc4ea - arm-trusted-firmware/lib/libfdt/fdt_sw.c +655c16e59bc70c4782c58f76a458853aeb35f2f1 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_utils.c +3da3d4c987ce40660bb10580236ee870f603a567 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_core.c +c8e552a0ec8c6fbc0008de98e8cc7e6ac08f1980 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_context.c +6d8e14259a3bddae74927623e68b6e95a578b3a2 - arm-trusted-firmware/lib/xlat_mpu/xlat_mpu_private.h +97a06786c9d53286c3d0d861d9e6578551650e5e - arm-trusted-firmware/lib/xlat_mpu/aarch64/enable_mpu.S +250ce42c1d1df6103d9a7eb84f739a52570e85c9 - arm-trusted-firmware/lib/xlat_mpu/aarch64/xlat_mpu_arch.c +c3816ecbb18ec120734f1bea8e79ea2ce6e4f631 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_core.c +eaf23114b5279a2e5177c2d4a103265159f839d9 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_private.h +499b3843cd918ded79d9b4067c70be77235a831e - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_context.c +c56014f913bcddf7eb4618bc48a2d7e188df93e8 - arm-trusted-firmware/lib/xlat_tables_v2/xlat_tables_utils.c +48fbcd0295e7c9d2581d235e6c80eced4a10a422 - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/xlat_tables_arch.c +21604c58893e3fda032bac4d88417fff189d89ca - arm-trusted-firmware/lib/xlat_tables_v2/aarch64/enable_mmu.S +990536d736898528cf4565171fb83f57604dd3d8 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/xlat_tables_arch.c +ade75a712dde9020d79686a61994595c14f73163 - arm-trusted-firmware/lib/xlat_tables_v2/aarch32/enable_mmu.S +5c1fdfd96d90cc2df42b24e37dc31a193219049b - arm-trusted-firmware/lib/optee/optee_utils.c +f32dab3880d47eca1b71c308cf6542b32941b23c - arm-trusted-firmware/lib/zlib/zutil.h +8770ab43c9050b824c646f6e6cee8b3c0628cbda - arm-trusted-firmware/lib/zlib/inffixed.h +628d8395fc7f67e6d7a9a6cecba64f6594d64eb9 - arm-trusted-firmware/lib/zlib/inflate.h +db9e88b8332953972c9120c73389fa2ce03dd8f8 - arm-trusted-firmware/lib/zlib/crc32.h +a152b76b78f9245ca67db2729de72d51ecc234b0 - arm-trusted-firmware/lib/zlib/inftrees.c +3c63a7707d83991f3e074391c047b3136ff3e558 - arm-trusted-firmware/lib/zlib/inftrees.h +2f1fcc93488ac84acf984415b6ea0bd63c72aa49 - arm-trusted-firmware/lib/zlib/zutil.c +6c1114794db137af50f9b060aaade1a1a35ed784 - arm-trusted-firmware/lib/zlib/adler32.c +d5cfffd5a037697867a78566d583e73f6d0f91b9 - arm-trusted-firmware/lib/zlib/inflate.c +fe2fdfb8f51d9f84881cc453ba64f60e3d7c9cbc - arm-trusted-firmware/lib/zlib/inffast.c +4fc803c43a562b2b92a97e22300754ddfe44c603 - arm-trusted-firmware/lib/zlib/inffast.h +473b29ab06e2be461fe4aa74952fcb9bd08d9fa0 - arm-trusted-firmware/lib/zlib/zlib.h +0ef05b0d12bf2cfbbf1aa84cff0e8dcf4fc5b731 - arm-trusted-firmware/lib/zlib/zconf.h +88ea76a1b42bfc247680dd50b450923858f945fe - arm-trusted-firmware/lib/zlib/crc32.c +8bb206723f10a7635c07f3e77abad21e4e47f520 - arm-trusted-firmware/lib/zlib/tf_gunzip.c +bcf80bf32003cb4ebf4b71fd3b62b2ec5210ba95 - arm-trusted-firmware/lib/fconf/fconf_tbbr_getter.c +18fdfde595d6c7a6409f3d91382d81f736bf775d - arm-trusted-firmware/lib/fconf/fconf_mpmm_getter.c +1720429b89e9cc8c7b5f6bde6381dcd8f1e4bf0b - arm-trusted-firmware/lib/fconf/fconf_dyn_cfg_getter.c +fd4c5030299c6c43d7dcde650254301c4a185c84 - arm-trusted-firmware/lib/fconf/fconf.c +3567bc768ff2f143e4933244eb221b010bd91f80 - arm-trusted-firmware/lib/fconf/fconf_amu_getter.c +06052beb76737879a3430c42f32068e7630ce940 - arm-trusted-firmware/lib/fconf/fconf_cot_getter.c +3c63f678cd78b3c4c10b6d13ffb32f245deb8ef6 - arm-trusted-firmware/lib/stack_protector/stack_protector.c +7c77f07a1d4fda36a4af38ed18da2e22607b53e9 - arm-trusted-firmware/lib/stack_protector/aarch64/asm_stack_protector.S +c50c9ce39f46bbbfebd47c8645445585727f5b7d - arm-trusted-firmware/lib/stack_protector/aarch32/asm_stack_protector.S +35242ceafb8e7c1ac58158cde6672b601b1a88f9 - arm-trusted-firmware/lib/mpmm/mpmm.c +3ac2e5a07791e75f8ed81d0c1088a639a14142de - arm-trusted-firmware/lib/cpus/errata_report.c +23b71740924a2f46a4a3766dc7863240494c0c3e - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78c.S +d16bad3d9e6b6ed0a164467a3b25e5174c38de83 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_demeter.S +67a71ce51804d2c0c43d0c5b928b429383691702 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a55.S +62e253dfa61bf57bc7c8af97146dc643070630b6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75_pubsub.c +03c0a2d3e033df508520b527dd03c5487d139556 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76ae.S +6c5232d349afaa099b1de4b8274de771a075d0ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a57.S +27cb3501d1a82bf7a2962df5e632ceddc6099479 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb.S +f382f5af3fd88a0d159f0fc27bf3ff89e6e6517b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n_common.S +4076b184f1c8b586d8b7e9c16daffa08e81812c6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a73.S +3a0842db6538fada52fd0764e2942e9edcfa61e5 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65ae.S +8753b581e7bd70b0612f529761cb2e2f789d26ce - arm-trusted-firmware/lib/cpus/aarch64/cortex_a75.S +6256de3b0f8cb82f4629e83dce1ebf3f3d101147 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a510.S +e0dbf2ba5bb288d057c7b39ac8c9217a8e9ef501 - arm-trusted-firmware/lib/cpus/aarch64/dsu_helpers.S +6c59fcd106e14d7120f6a715ba57542d71f097d9 - arm-trusted-firmware/lib/cpus/aarch64/rainier.S +08801af78758ca580f3619f48f0d2b72b843b8b3 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_v1.S +50d6608eb167f02f6eef1948d919c767b8687797 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a76.S +7cd2af73210355f0e23d3b78612b61f25b37cc87 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a710.S +9745ddbfe3bad71ac283cf7afe3f3a58848729fe - arm-trusted-firmware/lib/cpus/aarch64/generic.S +87817fd4d0f4db7bb9527cfe0b1107c39d33bd8b - arm-trusted-firmware/lib/cpus/aarch64/cortex_a72.S +2395220984e4ebe2e10ec3658f908b7a208fb99a - arm-trusted-firmware/lib/cpus/aarch64/cortex_a35.S +0dc9a7f3f035cf6c322da9c77eacf5cdfd5be43b - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_bpiall.S +bb044127b0f5b6908597c1915659ebabb4b9d8ff - arm-trusted-firmware/lib/cpus/aarch64/neoverse_e1.S +dd46ea61bba696867fb1ab60d0f54a5955c1f181 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a65.S +4605a62d489dd9762cd96aedcfc0fe6101c14072 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n2.S +c2e3731d8a04eb0fe71b450fe59df2cca99da824 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu.S +f751bc5c9ebc637d2973b137fe4020a9d2b49ef6 - arm-trusted-firmware/lib/cpus/aarch64/cortex_hunter.S +7ff21ebdc83ea3c05558a7c0798f1424648d5a34 - arm-trusted-firmware/lib/cpus/aarch64/qemu_max.S +e448fa0b2d060a91a00ce5b1747f0bb4963d83e4 - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1.S +e314809e018d3bcc1cb805e4412443d918934828 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu_helpers.S +b6f5469c320d8cea71ed93f0779eb1706255e014 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78.S +5f3bf45f19baa196f8537ea9fa6db1c00692c35f - arm-trusted-firmware/lib/cpus/aarch64/aem_generic.S +366cfe2c271409694f391a9092ce58f0d69d8eec - arm-trusted-firmware/lib/cpus/aarch64/neoverse_poseidon.S +0183572f056c98431e9ee40e1ca22f149c8d1995 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a53.S +ce5deaffb5280914ff04e13a3c1e8d5e0a12e9b0 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a78_ae.S +527f0453b6bcc1e3cdbc68d25c5949e9c6d90d21 - arm-trusted-firmware/lib/cpus/aarch64/denver.S +f245d765bc664b16acec02a6040885c8a59f9a54 - arm-trusted-firmware/lib/cpus/aarch64/cpu_helpers.S +814012a88912a712842aaaf04053a1a8fc46c29c - arm-trusted-firmware/lib/cpus/aarch64/cortex_hayes.S +006dee1e8ead4bf3e5c48a7374813cd8b78ae362 - arm-trusted-firmware/lib/cpus/aarch64/cortex_x2.S +5e64126fe122470b5f906cbd26adc7b19c2b1cbd - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2022_23960_bhb_vector.S +516e5e5482ec47fb50a91b19c7c8d86572bd9844 - arm-trusted-firmware/lib/cpus/aarch64/wa_cve_2017_5715_mmu.S +fd801851b71a05fbc5920f6815d5ab8025a7f156 - arm-trusted-firmware/lib/cpus/aarch64/cpuamu.c +edb24154359f6a874c199325c9d7072c4dedba3b - arm-trusted-firmware/lib/cpus/aarch64/neoverse_n1_pubsub.c +b6caa69a2838b35a3268cac6784f7f42060028c3 - arm-trusted-firmware/lib/cpus/aarch64/cortex_makalu_elp_arm.S +4a3f95b9caa66e146e1a7057c238ce166bc17ae0 - arm-trusted-firmware/lib/cpus/aarch64/cortex_a77.S +4bd6136e7c566e86577b42f173af618fff3ec5ce - arm-trusted-firmware/lib/cpus/aarch32/cortex_a17.S +dd4d708971e42cb6726bd6bcaeaaeb1ea62cc302 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a7.S +28602f5410ff8b383fbca1c3d420dd85e9e2e12c - arm-trusted-firmware/lib/cpus/aarch32/cortex_a57.S +531b8790149c59c6d2a7528e480dc52235a0b5f3 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a32.S +d132a84afe31b0339e4451e7df450856572fd2fa - arm-trusted-firmware/lib/cpus/aarch32/cortex_a72.S +dcc4327691c3788d4ca00df40256542be520f4a6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a15.S +70588b0d27cc22a3c28dcf235cb80cb80658e875 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a5.S +504aecaaa931ada33617064d0c95d4514d583971 - arm-trusted-firmware/lib/cpus/aarch32/aem_generic.S +0011de1efcc751a018cb652d35bf6dfb77ee5da5 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a53.S +33d1e02fb1f40c2b2147fdf1911b9f6d0de2592d - arm-trusted-firmware/lib/cpus/aarch32/cpu_helpers.S +bbcb12f3afb37a6763f26ed91a5859a16a9185f6 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a12.S +698a71205b1dfcca91b0dc7e75cd8633685859b4 - arm-trusted-firmware/lib/cpus/aarch32/cortex_a9.S +dfe9d1459f2afc808df76389971581e7cd156c05 - arm-trusted-firmware/lib/compiler-rt/LICENSE.TXT +58b4cf2c8174eb2d106886b7cb8a016d40b2d753 - arm-trusted-firmware/lib/compiler-rt/builtins/udivmoddi4.c +dd068590d2ed1fd41f248aa09a898df9da988c07 - arm-trusted-firmware/lib/compiler-rt/builtins/divmoddi4.c +eb176115541305cb488d2be70cf8c519c16b494e - arm-trusted-firmware/lib/compiler-rt/builtins/int_math.h +35e2f5c84e2e03c6a63abe1dcf1494fcf8ef9d7d - arm-trusted-firmware/lib/compiler-rt/builtins/divdi3.c +32a243925b1b44cce203fbb02b0a15210edf2c34 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountsi2.c +abf726b9d10381fc90d5c11654d391de96b8d950 - arm-trusted-firmware/lib/compiler-rt/builtins/int_types.h +e6b7517bd52e7cd7c50262aa9efbd0f8ae19a1c5 - arm-trusted-firmware/lib/compiler-rt/builtins/assembly.h +f0a970815c4d8d2aac30a5da63d63cc4c5ad824f - arm-trusted-firmware/lib/compiler-rt/builtins/int_lib.h +3a299c5cc089640cd5a4723e9f7ef8eb172386e0 - arm-trusted-firmware/lib/compiler-rt/builtins/popcountdi2.c +46a423cd744769dbf4c8a9bace21b176a9e737df - arm-trusted-firmware/lib/compiler-rt/builtins/lshrdi3.c +0740d888a28b420885866b396a4b4c3787fa5d9b - arm-trusted-firmware/lib/compiler-rt/builtins/int_endianness.h +393af562fe70f1bc9366014f2afdaa0318c8e72a - arm-trusted-firmware/lib/compiler-rt/builtins/ctzdi2.c +fa64ca197ba53f0e818a0f087349634fbd54640f - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_uldivmod.S +534e0612fc60e5acdbd99194724c762a645b1a4c - arm-trusted-firmware/lib/compiler-rt/builtins/arm/aeabi_ldivmod.S +14efe65532640ad904e16c0fcfdf2a0aa8ef7892 - arm-trusted-firmware/lib/aarch32/cache_helpers.S +c975d8abfe42e48d68e0e592ba3989ae3f7f0853 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod_a32.S +8a00fe14195497b3dfb4323af7775b79c89a645c - arm-trusted-firmware/lib/aarch32/misc_helpers.S +50b2fea23411834a7cdb5cb61cc8559bcfd872b1 - arm-trusted-firmware/lib/aarch32/armclang_printf.S +00169552baea8da03759257b44162edf097abcd0 - arm-trusted-firmware/lib/aarch32/arm32_aeabi_divmod.c +a9efa4120656b54bbfaf91befd1a82dafb8640a0 - arm-trusted-firmware/lib/romlib/romlib_generator.py +3a7bca01cf9d3b67b9d93fec625c4591ad106379 - arm-trusted-firmware/lib/romlib/Makefile +bc8857833413ad776fefee7b3a4fe3ad74c7cd04 - arm-trusted-firmware/lib/romlib/gen_combined_bl1_romlib.sh +0b4fe827956659566fa763cd1b1e15b1cdb505b6 - arm-trusted-firmware/lib/romlib/jmptbl.i +aca0167af243d551e7068e10251ccc62e1b800ea - arm-trusted-firmware/lib/romlib/init.s +1a7d8adbdd571058f2d7cdf2dad5d51e735dfe8d - arm-trusted-firmware/lib/romlib/romlib.ld.S +5c8a013e889e7653f0cbff1346cd13128ff2fd69 - arm-trusted-firmware/lib/romlib/templates/wrapper.S +f9c9050fd5c89b246d718f406a9d9a13f3388a5e - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved.S +b022feb15f3e84d4eefd318657af38a3a523e363 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function_bti.S +fa26b89e848f7affd6fd3be71153b55961fbf971 - arm-trusted-firmware/lib/romlib/templates/jmptbl_glob_var.S +e0406a34add19465d2ace2d60bc6c5048bf0a9ff - arm-trusted-firmware/lib/romlib/templates/wrapper_bti.S +8bd9f16af17fc4a81e921654d50217d6ba334d4f - arm-trusted-firmware/lib/romlib/templates/jmptbl_header.S +56fc8c8a2950a0303783ced6bd0e388176043a47 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_function.S +91d0e6f060cd659ba73d0db8886497a823814c65 - arm-trusted-firmware/lib/romlib/templates/jmptbl_entry_reserved_bti.S +2e63b0dd99041f913d992fc557f39d47f05937cc - arm-trusted-firmware/lib/coreboot/coreboot_table.c +ccbf0a74a73d6eb9563cb282272e41c9decadde5 - arm-trusted-firmware/lib/el3_runtime/cpu_data_array.c +0407aded26aa40484ccde01e8562c2db1c2ff939 - arm-trusted-firmware/lib/el3_runtime/aarch64/context.S +648e98ef419ac30a1fdfe6e9fdef5a45f6fb8926 - arm-trusted-firmware/lib/el3_runtime/aarch64/context_mgmt.c +a748c18c9c1bed5bfa7ad7bc2d42f1241b4eeb59 - arm-trusted-firmware/lib/el3_runtime/aarch64/cpu_data.S +72331f73e0f3f6540837815f472f78059a7fe275 - arm-trusted-firmware/lib/el3_runtime/aarch32/context_mgmt.c +c16b6a90e04aa66123dde223fa202f33ab70aa51 - arm-trusted-firmware/lib/el3_runtime/aarch32/cpu_data.S +489fa8c2a31654d4ab05e281acbabb0f8a64608d - arm-trusted-firmware/lib/xlat_tables/xlat_tables_private.h +57633f55f011eec32b09f4867a18db8725ad24d4 - arm-trusted-firmware/lib/xlat_tables/xlat_tables_common.c +83fd34388e89c93efcad1998551854558c28ad99 - arm-trusted-firmware/lib/xlat_tables/aarch64/xlat_tables.c +08dd595ae97e585c165a02faaeecbc5c0615ecca - arm-trusted-firmware/lib/xlat_tables/aarch32/nonlpae_tables.c +bb710f3b156b87d08faaffa4bfdb60074c5bf5b0 - arm-trusted-firmware/lib/xlat_tables/aarch32/xlat_tables.c +b3f793c7bec8ccc037a4cb9796f2bcd15f5bf4eb - arm-trusted-firmware/lib/pmf/pmf_main.c +6b60742d3e420cad2de83925c184cc98fd66505b - arm-trusted-firmware/lib/pmf/pmf_smc.c +886c1e8212ddafb0663811837c76ce60a9afb42a - arm-trusted-firmware/lib/bl_aux_params/bl_aux_params.c +78982645d4d3008984c9307ee68bfa8eeb1a43a7 - arm-trusted-firmware/lib/debugfs/blobs.h +8102f862edb5ab07783993999c8781385e261628 - arm-trusted-firmware/lib/debugfs/dev.c +5260672b27f35a4368d3be1f6ee66ec91d4beb26 - arm-trusted-firmware/lib/debugfs/dev.h +9802d55cbbaff09010b37afad6d494d8e755eae2 - arm-trusted-firmware/lib/debugfs/devroot.c +758f3be3354709a4f69ee89cacf0db10dd68c75c - arm-trusted-firmware/lib/debugfs/debugfs_smc.c +7c85c537adcb24f5e03d6c71424a2618815086e3 - arm-trusted-firmware/lib/debugfs/devc.c +db9f0e301c7178c315a1c6e72358bae572ce85db - arm-trusted-firmware/lib/debugfs/devfip.c +0e11c2ba3c9318cdcc4c28e3e3663337046128b8 - arm-trusted-firmware/lib/libc/memchr.c +c72f1f1842a78fb427805c7447d370fc148dc89f - arm-trusted-firmware/lib/libc/strtoul.c +76e2ba1d1196be96fef786c3d7c5130fdac79ca7 - arm-trusted-firmware/lib/libc/snprintf.c +06782e2bb8b5e2b70cd089f061be9c1a08621523 - arm-trusted-firmware/lib/libc/memrchr.c +a13fb76d1efd1532d6265ca7e3753be123c5fbef - arm-trusted-firmware/lib/libc/strnlen.c +07dbfb512cae53c03504d60ec4b02bfc74c2af8a - arm-trusted-firmware/lib/libc/strtol.c +f5fe2af7f4f0cad25866aa2422d946f47a11943e - arm-trusted-firmware/lib/libc/abort.c +c64e54b9d37e79c6a5ddf5440518980b4d8023d6 - arm-trusted-firmware/lib/libc/strrchr.c +1a98830ccfe805a879a87ff7eb90306cb197e72d - arm-trusted-firmware/lib/libc/strcmp.c +315e4d792f50e1a2f37ec14616fb2aaeaa866ae8 - arm-trusted-firmware/lib/libc/strncmp.c +8cd93cb80d43bbeeabb3a74bdc1e89d4e0821e6e - arm-trusted-firmware/lib/libc/printf.c +57ac7674f717f57cdd099f4ac2b3be174f71bdda - arm-trusted-firmware/lib/libc/assert.c +82032c79de7b24a84341c8bd5d72baba75337f1e - arm-trusted-firmware/lib/libc/strtoull.c +be9487ae2df331c4b6d1e8eb831fe36f80300829 - arm-trusted-firmware/lib/libc/strlcpy.c +44c32455e06c8ee38e1d4774fa8f70de1d9e3f00 - arm-trusted-firmware/lib/libc/memcmp.c +e99c723c3292973758d597558fd929976df82eff - arm-trusted-firmware/lib/libc/strlen.c +e7eb31dbd9893d98f8ab6cbef6a11143aa052581 - arm-trusted-firmware/lib/libc/strtok.c +0a99e4e59337ea7c2c2fe6dd428552019fc1f053 - arm-trusted-firmware/lib/libc/memset.c +cf851bb6ce469797f295f4789ce50110b175893f - arm-trusted-firmware/lib/libc/memcpy.c +0e2d7fd7063f4e253b3719a95edcfeb99d34044d - arm-trusted-firmware/lib/libc/putchar.c +6d62f8972d334e9b7016abfa5fd60039fd045392 - arm-trusted-firmware/lib/libc/strlcat.c +e68d6a0053ae9810517f220d26386a2ae6290766 - arm-trusted-firmware/lib/libc/exit.c +2e041624618747b95a70ac92007814f04d42907c - arm-trusted-firmware/lib/libc/strchr.c +a1876df5c0fef0a62bc57d6a13bab2234ad7b1ea - arm-trusted-firmware/lib/libc/memmove.c +045917a873ae9e6ad3f96e3d127eb474b0f0baf9 - arm-trusted-firmware/lib/libc/puts.c +8c9668a348c3ffbe4509aa2246941450a7b0de00 - arm-trusted-firmware/lib/libc/strtoll.c +fd7697000146d99611e6aaf57e0f3856602daf6b - arm-trusted-firmware/lib/libc/aarch64/setjmp.S +02977fbcda3d55ed39cafa721d2bd2a901f0c637 - arm-trusted-firmware/lib/libc/aarch64/memset.S +75786d0b78f57474b1c6f960b2c8ecbc07ba830b - arm-trusted-firmware/lib/libc/aarch32/memset.S +d317228143780c8f627a6814a3ca1ab9f1a0d69b - arm-trusted-firmware/fdts/stm32mp13-fw-config.dtsi +2a8ccec8476f0d4af01036dc6ecb636d1f2a1387 - arm-trusted-firmware/fdts/stm32mp13xf.dtsi +6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xd.dtsi +38c31e8b06ea5253a26b8393737ad72d81e1757d - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-1t.dts +60954c960886d3c55a4f3e819b0ad2411afe194c - arm-trusted-firmware/fdts/stm32mp15-fw-config.dtsi +195376b3fa6a4af6db8e90af65ae62d649d506c1 - arm-trusted-firmware/fdts/fvp-defs-dynamiq.dtsi +abbe0e5a7c63995c207b1995649e3a6ed6b4221a - arm-trusted-firmware/fdts/stm32mp15xc.dtsi +f92cb32ea29e10232721e9d596972e82444c21d2 - arm-trusted-firmware/fdts/stm32mp15xxad-pinctrl.dtsi +ae59f1caa51f25a19cb7bc925c819f7b663c9ccf - arm-trusted-firmware/fdts/stm32mp157c-odyssey-som.dtsi +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157d-dk1-fw-config.dts +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157f-dk2-fw-config.dts +a6ef63af22c25465b4276c77535b30d8baaa1ea4 - arm-trusted-firmware/fdts/arm_fpga.dts +d49435eb3b8dae9e0f687d74ac1343c3f6931d7b - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32.dts +a2179d252faf4859c7a7e68d3ba75a0955f53d37 - arm-trusted-firmware/fdts/stm32mp157c-odyssey.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ev1-fw-config.dts +094f752c659ba4c70dae4bfdd3041ffdc45d6451 - arm-trusted-firmware/fdts/corstone700.dtsi +6b86a9e9c6c06841937a884fcc7b91e67ce3b81c - arm-trusted-firmware/fdts/stm32mp13xa.dtsi +4fa3b6d4bddfb09bf8b8ac8f78bc5806a1063cf6 - arm-trusted-firmware/fdts/stm32mp157c-dk2.dts +397204dbf3a8d4f16b213cdf8810bb0c8409a3ea - arm-trusted-firmware/fdts/stm32mp151.dtsi +c028d02d6d68dfd3c16c8ea9c6e247c72a911abc - arm-trusted-firmware/fdts/fvp-foundation-motherboard.dtsi +e61da20036fff26e3a39b09bcb92733e6c4c3743 - arm-trusted-firmware/fdts/fvp-base-gicv2-psci.dts +fb6d607b811f2e027c9859345cf86eb565d31c20 - arm-trusted-firmware/fdts/stm32mp15xx-osd32.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ed1-fw-config.dts +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157a-dk1-fw-config.dts +20769b04e4fa588ef10d7460a5b4a9061c70ebfa - arm-trusted-firmware/fdts/corstone700_fvp.dts +ee5b8fc8401ffbd14d01f615b14a1bc2c6bc90ba - arm-trusted-firmware/fdts/stm32mp13xc.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ev1-fw-config.dts +9082edd5658eb851151f8944760e3c2741fea749 - arm-trusted-firmware/fdts/rtsm_ve-motherboard.dtsi +3cafe4429688d04735324b0c1ac24d6fd6df075c - arm-trusted-firmware/fdts/fvp-base-gicv2-psci-aarch32.dts +910ac0ace6638b52d04843f12c3f0f521eb4f4e5 - arm-trusted-firmware/fdts/corstone700_fpga.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157c-ev1-fw-config.dts +7b3fc7115bcdc0c82b7a2cf02a4089f67d2402b9 - arm-trusted-firmware/fdts/stm32mp13-pinctrl.dtsi +841830f5b4fb33dd8e11325e65d3e1ba854144f9 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A7x1.dts +4d121467e71a4bd15241201c1c23fbb169901959 - arm-trusted-firmware/fdts/a5ds.dts +09fc90f32545b712b63ea42e925122cabd78c262 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-2t.dts +fafc1a46bd195774df21a32f1e87a087f14e2c67 - arm-trusted-firmware/fdts/stm32mp15-ddr3-2x4Gb-1066-binG.dtsi +390a6cef77d9095a9c98b9abe19eaaa6eedbdb73 - arm-trusted-firmware/fdts/stm32mp15-ddr3-1x4Gb-1066-binG.dtsi +c551d6d75e35b8e119cd5b31bb7d421eb5007e04 - arm-trusted-firmware/fdts/rtsm_ve-motherboard-aarch32.dtsi +3ebcaa602aafc62742776533b737f3eafdbcbeea - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-common.dtsi +b724eb6fc96a68bbfe8f165c465341bbbf27bb27 - arm-trusted-firmware/fdts/stm32mp13-bl2.dtsi +59f777f521b3de55f482d1b9623951a1dc5c0046 - arm-trusted-firmware/fdts/stm32mp157c-ev1.dts +f99071420aca4da5f493b73afa3d3777206e23d7 - arm-trusted-firmware/fdts/n1sdp-single-chip.dts +901a3c633890935dc0ef5dda27689fe471371d5b - arm-trusted-firmware/fdts/stm32mp15-bl32.dtsi +721faf693f101ff246d85ebc2d1772b555d84f20 - arm-trusted-firmware/fdts/stm32mp157c-ed1.dts +7afa8c643fcfe1d0d506c90c0ab7ced868c73040 - arm-trusted-firmware/fdts/stm32mp15xx-dkx.dtsi +44c1cab21fcc9907b2d084dbac303eff0dfa00b3 - arm-trusted-firmware/fdts/fvp-ve-Cortex-A5x1.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ev1-fw-config.dts +ddb3d9266ce77ac3e0746820b562a07f35eafb01 - arm-trusted-firmware/fdts/n1sdp.dtsi +122430dfffc3d549a6991bc3154850d76b80c2bb - arm-trusted-firmware/fdts/stm32mp157a-dk1.dts +5061d53c21f2dec61bb9fb74fac882b6142d8931 - arm-trusted-firmware/fdts/juno-ethosn.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157f-ed1-fw-config.dts +44c646e57eb44bcfd7927514911f6cefb465cb23 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci.dts +79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-odyssey-fw-config.dts +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157d-ed1-fw-config.dts +a61a77e18f14a9ba0916b5d0c1d4c7b0e07d1441 - arm-trusted-firmware/fdts/stm32mp15xxac-pinctrl.dtsi +0e25cc4f38da64563038297dac19b2cc042284f8 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-common.dtsi +10bae29f18be4785b789ca4c08398643163c76be - arm-trusted-firmware/fdts/cot_descriptors.dtsi +dd88ca9bc617b6bb318f6b74c35655db6ecff39d - arm-trusted-firmware/fdts/stm32mp135f-dk.dts +2d9983ae7b41417977f671f99eec7d6c8f5a99be - arm-trusted-firmware/fdts/stm32mp15xxaa-pinctrl.dtsi +c1a285215a44ab5a76667a51c9a7d2ce06e50659 - arm-trusted-firmware/fdts/morello.dtsi +394dc09a932c8f74fe7aff7d429da06d4bd07878 - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-aarch32-1t.dts +c1d24ce6492d52d78484c4b3cf9d2466dbf9c0b0 - arm-trusted-firmware/fdts/stm32mp157.dtsi +f7ba40a101d1f02c70445a0d783a347ed212cf03 - arm-trusted-firmware/fdts/stm32mp157c-dk2-fw-config.dts +c49dfbfab50db6d0014130e8d213b6a8113c9525 - arm-trusted-firmware/fdts/stm32mp153.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-avenger96-fw-config.dts +0fec14d4dc8c75bbdea73be1457f5ed47458cb9a - arm-trusted-firmware/fdts/fvp-foundation-gicv2-psci.dts +ec214ebb9287a791def27fb1b8d74fceb843657f - arm-trusted-firmware/fdts/stm32mp135.dtsi +992348633a6518e2d0464e4afe90c22c87a617a6 - arm-trusted-firmware/fdts/stm32mp13-ddr3-1x4Gb-1066-binF.dtsi +dc0b8b61bededc06878dfb1e763b36611ea2382a - arm-trusted-firmware/fdts/stm32mp15-bl2.dtsi +3340a6810424caf1eeec960dce9e7f673eca4150 - arm-trusted-firmware/fdts/stm32mp157a-avenger96.dts +fdc05334cd630b63cf2fd11add62d6580489d832 - arm-trusted-firmware/fdts/stm32mp13-ddr.dtsi +d9fadc7223cf3f5db0bfb1f4830e0bf0fbf138ad - arm-trusted-firmware/fdts/stm32mp15-pinctrl.dtsi +c078bf1220e11a54b0ae9d20bf948f1f4cb30d37 - arm-trusted-firmware/fdts/stm32mp15-ddr.dtsi +fec2d89a3727359109737596ca7c4c1165b7de38 - arm-trusted-firmware/fdts/n1sdp-multi-chip.dts +dc880b2cbd39cde08860e8ebf3cb4b92bbb21748 - arm-trusted-firmware/fdts/stm32mp15xxab-pinctrl.dtsi +bbe441adbb4706bbc2d792a33b888f441d489177 - arm-trusted-firmware/fdts/juno.dts +c67b47c8582f0a092e22ed701f7ad5d9469dd6b4 - arm-trusted-firmware/fdts/fvp-defs.dtsi +d0ca311ee090d9d69c82273e0e6f4d65bb330554 - arm-trusted-firmware/fdts/stm32mp157a-ed1-fw-config.dts +ee1bb06de6ee0eba0fe695f5c7f9dbc12abb6f3e - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq-common.dtsi +9ba3e2b8e2ffe38d252977d731187a52eac72c6b - arm-trusted-firmware/fdts/stm32mp133.dtsi +dbed6c5c0e011af658818b570feee9c093e65a26 - arm-trusted-firmware/fdts/stm32mp135f-dk-fw-config.dts +d72046fed6d7327744da75b395f335791022bfc4 - arm-trusted-firmware/fdts/morello-fvp.dts +708bcdeda398c49482ebc2c3bf4b25f2c71a1e3a - arm-trusted-firmware/fdts/fvp-base-gicv3-psci-dynamiq.dts +2f05be7afa52d4db4c62e213a91e5efc3908193a - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1.dts +3b4d8cfb55f06ed3418c0539f4d5d2bc33168635 - arm-trusted-firmware/fdts/stm32mp131.dtsi +d6f0de7f00f3c5d3fc07703cda887ee3d8ea1d2e - arm-trusted-firmware/fdts/tc.dts +6c3fed10148b793fe9f9c4f44b878ccc12d99c3e - arm-trusted-firmware/fdts/morello-soc.dts +79d8f41f2a5afa474094fe763ef4ee39909d283b - arm-trusted-firmware/fdts/stm32mp157c-lxa-mc1-fw-config.dts +5d5ddb74e5499f300b5d1800520a4651078d347b - arm-trusted-firmware/fdts/fvp-foundation-gicv3-psci.dts +ee87af83d314b14a8d8a41acb7fa47c97f7dda56 - arm-trusted-firmware/tools/nxp/plat_fiptool/plat_def_uuid_config.c +d66ad3c8e97d38face17234980203ac71836e11f - arm-trusted-firmware/tools/nxp/create_pbl/byte_swap.c +6883483605723caec745103ffaafc790ec284c8d - arm-trusted-firmware/tools/nxp/create_pbl/create_pbl.c +294a1e169dc8c2e940e56cad57a08e5d4adb3b9f - arm-trusted-firmware/tools/nxp/create_pbl/Makefile +2ec990b299f9fd69d0e0a85e98faba9055f56bab - arm-trusted-firmware/tools/nxp/create_pbl/README +621d8ec57a445f0149ebb8b216ef913ed05f8754 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_key.h +46fb0f5a24245e631af2a4690c0d7202204c0e54 - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_cert.h +3d16696dce452bf99b18bdd1a964fe7ad191477b - arm-trusted-firmware/tools/nxp/cert_create_helper/include/pdef_tbb_ext.h +f328e450c8ae941e8109578f1721860acbfafbbe - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_cert.c +506a53ab2e813a5ce578765b25e1e3fe0f1e643e - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_key.c +4065b3a492865b1f4525586a648df384bf7c961a - arm-trusted-firmware/tools/nxp/cert_create_helper/src/pdef_tbb_ext.c +12473d63d565d1782e4e3273a27c29c04adaf86f - arm-trusted-firmware/tools/amlogic/doimage.c +58ef2523c26b02365fb70cb1cebc29cba026be23 - arm-trusted-firmware/tools/amlogic/Makefile +495a7786c563fdb9134410b75a95c3e1c3149eb3 - arm-trusted-firmware/tools/memory/print_memory_map.py +30931543e94deea26c28007433bf6d837f1839aa - arm-trusted-firmware/tools/fiptool/tbbr_config.h +6dcc9e2c01e4d8e4c0b531154c0598192ba190c7 - arm-trusted-firmware/tools/fiptool/fiptool_platform.h +12207fca29ab69b8fccc71ef7a95f9d551ec744f - arm-trusted-firmware/tools/fiptool/win_posix.c +02dcc44205d31ccd5e69fd5008848cebfa14b775 - arm-trusted-firmware/tools/fiptool/tbbr_config.c +2b824a81f75e43fe0eb8f52e822974093ad0f246 - arm-trusted-firmware/tools/fiptool/fiptool +d47913d50cdf551a4f0677629c59c1464b96f606 - arm-trusted-firmware/tools/fiptool/Makefile.msvc +022ce17862a03fb1b68881c15cc964cd56706532 - arm-trusted-firmware/tools/fiptool/Makefile +158eb04fba82028aacc8b3cc3884314b37d8a862 - arm-trusted-firmware/tools/fiptool/fiptool.c +ff33081f63178813dd9c9235d17538954c29d7c6 - arm-trusted-firmware/tools/fiptool/fiptool.h +323e507fdf87c7d4a94d0bbbaa72bd905c2d641d - arm-trusted-firmware/tools/fiptool/win_posix.h +638ff14128d59a95756979954071615bb74eb3c4 - arm-trusted-firmware/tools/cert_create/Makefile +491ae06a09039151d3d2fbccaf89bf4de779dd5a - arm-trusted-firmware/tools/cert_create/include/ext.h +843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/cert_create/include/debug.h +0a307fbdd842fe9ae8212a2362b356addf0a38df - arm-trusted-firmware/tools/cert_create/include/sha.h +26baf6654b744217670bc74a0372533b7a9347d9 - arm-trusted-firmware/tools/cert_create/include/key.h +f5c9fe91b01c2e36483376d6f0ef0c2794343406 - arm-trusted-firmware/tools/cert_create/include/cert.h +134c6c14b6a384f0e036827b128d4adf08612d9a - arm-trusted-firmware/tools/cert_create/include/cmd_opt.h +596785e69869c848d5fdb306b8084f282876abe7 - arm-trusted-firmware/tools/cert_create/include/dualroot/cot.h +728ba9b1bbfe33e0ca3e33eb166f04922947e3e3 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_key.h +a015fcfd89d3e63781911e5134884343975d6284 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_cert.h +0c696ba78f7d568469b58576262a035b3074ae67 - arm-trusted-firmware/tools/cert_create/include/tbbr/tbb_ext.h +1188485867e47cb5d105325c1736aafc8f6b0073 - arm-trusted-firmware/tools/cert_create/src/sha.c +ba404574148313fc2ff134ae8bf798150a5cd0d5 - arm-trusted-firmware/tools/cert_create/src/cert.c +82813403f6e7250a54d55d8c1409be0c9c3538e0 - arm-trusted-firmware/tools/cert_create/src/ext.c +a485a01a7aa89b241a4a2b28b2fbe50c469d51c4 - arm-trusted-firmware/tools/cert_create/src/main.c +29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/cert_create/src/cmd_opt.c +718afca8b5d04a3f76605646abacc1e597be801b - arm-trusted-firmware/tools/cert_create/src/key.c +87b7868a92308d1b74bbf003f8fb00f89c405d2c - arm-trusted-firmware/tools/cert_create/src/dualroot/cot.c +a71f6edc951824d84282d7f0262e1ebd260a5a38 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_cert.c +c5571efb1999abfd481ddccdf9cfa8db65d5e440 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_key.c +11fe1d417bcbf3a47d588f48d738d47a156b9c49 - arm-trusted-firmware/tools/cert_create/src/tbbr/tbb_ext.c +1474476f05acda23a8bb1e859fcc314baf5a4fda - arm-trusted-firmware/tools/stm32image/Makefile +75e7e633ff5fcf6dca970eef0c2acd786d23f188 - arm-trusted-firmware/tools/stm32image/stm32image.c +9bdff25d946a2c61d8312e1f53c49802d66d3577 - arm-trusted-firmware/tools/conventional-changelog-tf-a/index.js +e9b252cbfa9bd844023146ac38470829ac72342a - arm-trusted-firmware/tools/conventional-changelog-tf-a/package.json +5e9ebb4c1ffaf478200ddbd8bd5bbef2b0f2d2f6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit-section.hbs +da39a3ee5e6b4b0d3255bfef95601890afd80709 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/footer.hbs +99f27ae0dfb07952b2130a819e32599cfc2d78c6 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/header.hbs +85453d72f48122ba14bd00512fac19ef0fc42d07 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/template.hbs +bdd671375b10dbdabd4f1f87941d3071e275ff64 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/commit.hbs +1d1032e5160d84f70af7f7ab6dddaf003244f768 - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note-section.hbs +65198bc7a494eba7c91745808f3ada1e3034659a - arm-trusted-firmware/tools/conventional-changelog-tf-a/templates/note.hbs +6a4752c84a78127a0b99ece7396ae317661ac61a - arm-trusted-firmware/tools/sptool/sp_mk_generator.py +37ff8b0160a90437e9b84efce7ef73833b96eb39 - arm-trusted-firmware/tools/sptool/Makefile.tmk +4a137ea4eb638729bda39a72491cc6519fc26da5 - arm-trusted-firmware/tools/sptool/Makefile +ee49dbe19d032c60cf3e963764253c2d808b9de5 - arm-trusted-firmware/tools/sptool/sptool.c +ba6ab775fd9474718d717b35f4220e716f7b7ae6 - arm-trusted-firmware/tools/renesas/rcar_layout_create/makefile +c6acebe37afdaba95dbaf9f814eb4bba5dd989a9 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.ld.S +a728eb1898ea80778d60fcf57b727f977c29ec98 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.ld.S +b4ecd67c81a19d47e59f9a72dd81fc392fff3aea - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa6.c +213e1746ba029a55b6baf19ac0d8863713811b64 - arm-trusted-firmware/tools/renesas/rcar_layout_create/sa0.c +3d9335fb1238d08df68e2770f69a0e1bec960069 - arm-trusted-firmware/tools/renesas/rzg_layout_create/makefile +8c2b63db003e2e330f2af95b94c2132bc2fc9725 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.ld.S +01000b7d50599a58601322b9a12174d81bd80571 - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.ld.S +4085a8d4104eac744977d5ec6feacf08b8a1283a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa6.c +f51f929a6294d60d681b03dbf0f3f1fe0835fa3a - arm-trusted-firmware/tools/renesas/rzg_layout_create/sa0.c +0ec11eeb14668d925e198fc42145f8b0fd3d02d8 - arm-trusted-firmware/tools/marvell/doimage/doimage.c +2bbefb66f05e50612c3b0d215f0bd185e076cf20 - arm-trusted-firmware/tools/marvell/doimage/Makefile +f35a6333e76f3fb2bed05bad996a131317f5ac9d - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem3.key +954bc6cdf269e0eaa9581057657a1e2bf9621f38 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem0.key +c8f9244b21f28bb382b1befed8dce13e4eae06f9 - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem2.key +8fc012a12a4398216ad6fd4b97199ccd159711e5 - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_7K.cfg +8602871bb27d59d5b5ce180448e1ceb232027bad - arm-trusted-firmware/tools/marvell/doimage/secure/csk_priv_pem1.key +f848ecb51058182d4c908f7c9a88561dbdce34bd - arm-trusted-firmware/tools/marvell/doimage/secure/kak_priv_pem.key +5b6535dd6c94832d3113588ea938b9526b06b0fc - arm-trusted-firmware/tools/marvell/doimage/secure/sec_img_8K.cfg +105f766aba0c8abdca2e88e258a34b28a656edd4 - arm-trusted-firmware/tools/encrypt_fw/Makefile +f37ed62897799b6165569c0842904eb6fe5d21d5 - arm-trusted-firmware/tools/encrypt_fw/include/encrypt.h +843248736f6bce43a9ac3f11f9bfa6a094face5a - arm-trusted-firmware/tools/encrypt_fw/include/debug.h +08dcc81abf0dd5a951f1d7cb36e2d05628055bec - arm-trusted-firmware/tools/encrypt_fw/include/cmd_opt.h +5093ed93e150e683b735ad26979460536e2419f3 - arm-trusted-firmware/tools/encrypt_fw/src/main.c +93d36734d229d79068472d13bb173cb9b1537d9d - arm-trusted-firmware/tools/encrypt_fw/src/encrypt.c +29f5f62fba8f9c0fb9e528df8a7c5f9a264d9bad - arm-trusted-firmware/tools/encrypt_fw/src/cmd_opt.c +7c0bab3200267e448b5ee45b83104d2923cc17c8 - arm-trusted-firmware/plat/xilinx/common/ipi.c +05d21184a6dd62749ada768285e6b39b3dc5a1d4 - arm-trusted-firmware/plat/xilinx/common/plat_startup.c +e7cc80e40c4b2aff0799c9db4c351cf1179cf347 - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.c +453e987cd3b0c17b8ae79a6a0794d4fb44adcc3f - arm-trusted-firmware/plat/xilinx/common/ipi_mailbox_service/ipi_mailbox_svc.h +f5cda3dcfb0f4452e442cc526b8178b413b5a17a - arm-trusted-firmware/plat/xilinx/common/pm_service/pm_ipi.c +3946a8e5b6578610dbcd1b1c9bb2ac02e357fd1a - arm-trusted-firmware/plat/xilinx/common/include/ipi.h +8ccd5942908d27505a9e0d68679df731210d75ca - arm-trusted-firmware/plat/xilinx/common/include/plat_startup.h +604b0f5de53a36f974ce1926152c895a54796482 - arm-trusted-firmware/plat/xilinx/common/include/pm_client.h +c879e06a73baec6538ce2dece09ae7a976f972df - arm-trusted-firmware/plat/xilinx/common/include/pm_ipi.h +3f5242b1d910a45ff664bc128a6e749aa019592c - arm-trusted-firmware/plat/xilinx/common/include/pm_common.h +04dac5fd40da85ec2a19ccf681ff7f4b708b31bc - arm-trusted-firmware/plat/xilinx/versal/plat_versal.c +d25ef41e434700921c3427ff0dac7aba4b81e1ba - arm-trusted-firmware/plat/xilinx/versal/versal_ipi.c +d959b29c70b303c44eca6045c664945b0fe74852 - arm-trusted-firmware/plat/xilinx/versal/plat_topology.c +b01dcfd7b061210199bce3d5632bc39be25a89fb - arm-trusted-firmware/plat/xilinx/versal/plat_psci.c +f241ecfc0ce4c6677cbaca2991578232a4c20ad7 - arm-trusted-firmware/plat/xilinx/versal/sip_svc_setup.c +415d7b76162c6a447101507b3181aa7434887756 - arm-trusted-firmware/plat/xilinx/versal/bl31_versal_setup.c +0f5013cb9f4dd7864aec9fdc3febb4a88c603b5f - arm-trusted-firmware/plat/xilinx/versal/versal_gicv3.c +6b87bc415258116316a3b89d124ff4be9d5fd944 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_helpers.S +14340733608cc8031286a97ddc48222bc0ae7bb5 - arm-trusted-firmware/plat/xilinx/versal/aarch64/versal_common.c +cb6dce6031f613ae2ad69be266bc3eb2a5095a0d - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.h +cfb673b998f65ad17832a2c1f376daa4ab836ebd - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_client.c +939082dd0654e1c9d5097e4b088ada2eefc3cc46 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.c +67797b5d7b79d4fe75c894faa289f6d4deac5929 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_node.h +6aca4366f91416b1541836b7a999ff0873c61e53 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_svc_main.c +a984b65e29e3ddb17d3c124890861519e0a53788 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_defs.h +06ac8403ef4a152a6d5257c08766c878afc2c3e2 - arm-trusted-firmware/plat/xilinx/versal/pm_service/pm_api_sys.h +3efa1f0d849fb9568699ae3cc5e7cf111f1b8158 - arm-trusted-firmware/plat/xilinx/versal/include/versal_def.h +34e333d135956229875de69051e5d541a789cb2d - arm-trusted-firmware/plat/xilinx/versal/include/plat_private.h +d43cd481e9d0acc960fc0f51fbeb274b0ec28712 - arm-trusted-firmware/plat/xilinx/versal/include/plat_macros.S +50268618a09434af24c4a339c20a1b7b4a2e4901 - arm-trusted-firmware/plat/xilinx/versal/include/plat_ipi.h +f22539e2e0c54efb87ad926699ecb40a60fb024d - arm-trusted-firmware/plat/xilinx/versal/include/plat_pm_common.h +23d939fae06d7a162821162cec379264613379ad - arm-trusted-firmware/plat/xilinx/versal/include/platform_def.h +91da7e2e2aedb93811b290946f5b62a4b99a6e6e - arm-trusted-firmware/plat/xilinx/zynqmp/bl31_zynqmp_setup.c +eed49df98140b8681bbbff7a1c514734c884b8aa - arm-trusted-firmware/plat/xilinx/zynqmp/plat_zynqmp.c +fc6886e5619aabaff7153e268ba005d385a73e3a - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ipi.c +fdef05d43dd39fc9b4d18e7933fadc3d7b388c0b - arm-trusted-firmware/plat/xilinx/zynqmp/plat_topology.c +e5c72cd4f7db3ba2c52afa5ea2a6f81048fa8876 - arm-trusted-firmware/plat/xilinx/zynqmp/plat_psci.c +614b7c2d4fab5909e7df0076f873699e84b1737a - arm-trusted-firmware/plat/xilinx/zynqmp/sip_svc_setup.c +4018dd905c37ab4e205c88450ef0d6b0a1d45041 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_sdei.c +9eafad8129f35d9d02d9cc93d60e653c41e3b321 - arm-trusted-firmware/plat/xilinx/zynqmp/zynqmp_ehf.c +e9430970a771c9add648211e2c05e63b0b2bf71b - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_common.c +bca57ae928a46e00c62d44205c7238c103d89723 - arm-trusted-firmware/plat/xilinx/zynqmp/aarch64/zynqmp_helpers.S +cd3edf132c54e7b51bf04235b10d9de35394acda - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.c +e1e42c17e346cb2bdd9bcedf9491e65dcf5a101f - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.h +6a34f58d5ec913711c12c58c945dfa18659b999a - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_clock.h +4738dfbb7a3a9789e0e520c2d4c7f83b635e3e9b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.h +7bfba4ae2b47e068f8f5ed8aeed42daad00743c8 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_client.c +4b8489810a7c5bd8524f87d7c37edf02b747ab48 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.c +620a7d35e7cfe3a416c79ab84094934f41b3821e - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.c +4cadaaf7eb5f5f047bac44095d19052727b55a02 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_pinctrl.c +d55e25c027a7950b3a7d34551ba2af0a05e70ac4 - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_svc_main.c +63045bc978271095cfdd4cb91e9d2c3d416cdb6b - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_defs.h +d6d44bea498c26d61f58d11284635f45c0d747fa - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_sys.h +4a69759072ab900e304081d6a5542761b628115d - arm-trusted-firmware/plat/xilinx/zynqmp/pm_service/pm_api_ioctl.h +04358429a766678c1ea60bc976430714db3fac40 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_private.h +8ede155c56692751835019579474fd5fbda5ba26 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_macros.S +6d98421b38c7e24ec53977e85b4776275af5d9c5 - arm-trusted-firmware/plat/xilinx/zynqmp/include/zynqmp_def.h +719fc3fa9d14be22cfb4a79dd8838b27fef9f247 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_ipi.h +fcc8c8052c715326e932fd7e210fe0beefa2d175 - arm-trusted-firmware/plat/xilinx/zynqmp/include/plat_pm_common.h +606bd0aedd3a81bf175ef81f028eae35e7511725 - arm-trusted-firmware/plat/xilinx/zynqmp/include/platform_def.h +f82a0ba91d921f8782dbacd326cf93f93d406ff3 - arm-trusted-firmware/plat/xilinx/zynqmp/tsp/tsp_plat_setup.c +2c5220969ad934f5e3904f8b72774332826fb89d - arm-trusted-firmware/plat/nxp/common/aarch64/ls_helpers.S +fdb986fc3069c5b8c185c58c199bc5e56a6d1655 - arm-trusted-firmware/plat/nxp/common/aarch64/bl31_data.S +cb4accb6830f44fe050021fd6e32cca1a8acf7ee - arm-trusted-firmware/plat/nxp/common/setup/ls_bl31_setup.c +d736c2075e7e15a400e61a1db310a4d1b43bffd2 - arm-trusted-firmware/plat/nxp/common/setup/ls_image_load.c +475644583f7d46ef814913dcdcfddfa706f9f9bb - arm-trusted-firmware/plat/nxp/common/setup/ls_io_storage.c +7159132c839b1d3568d7b7b03da30f6d03e5336e - arm-trusted-firmware/plat/nxp/common/setup/ls_interrupt_mgmt.c +98e57da5931c557522da93cce9fe3bfb911d2cb0 - arm-trusted-firmware/plat/nxp/common/setup/ls_err.c +6694d9cc9520a800f00a344d9cc1c534b6e88d91 - arm-trusted-firmware/plat/nxp/common/setup/ls_bl2_el3_setup.c +e0dfec4c8847e15aeb7a774844188ab382bdd027 - arm-trusted-firmware/plat/nxp/common/setup/ls_stack_protector.c +91c2c52722651995a236e3f10e11504b1d87e098 - arm-trusted-firmware/plat/nxp/common/setup/ls_common.c +8094976b2b7aa5bbc113bbc852215f8e0513c202 - arm-trusted-firmware/plat/nxp/common/setup/aarch64/ls_bl2_mem_params_desc.c +52c5991d0ead354cd375910f00aefc81953d5681 - arm-trusted-firmware/plat/nxp/common/setup/include/plat_common.h +c8d60b0a7cea607dac9dc88673f41a4be9285d2e - arm-trusted-firmware/plat/nxp/common/setup/include/plat_macros.S +9e4c6090807eed8550b5e6acaf048f870d04011b - arm-trusted-firmware/plat/nxp/common/setup/include/bl31_data.h +4f9b26944e2ce37da586a62bdec3d03549edca60 - arm-trusted-firmware/plat/nxp/common/setup/include/mmu_def.h +7deb5f8e4cedbb8f2f2faed66426dac4607d7f04 - arm-trusted-firmware/plat/nxp/common/setup/include/ls_interrupt_mgmt.h +6edca4ab32d5c19db4706b176997f9bc4f085702 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.h +ac50f0a2929a3c77c87203013245a30bab6a20b2 - arm-trusted-firmware/plat/nxp/common/img_loadr/load_img.c +3b5918338beab36f0f06c2b7e82c7f49a7b351bf - arm-trusted-firmware/plat/nxp/common/psci/plat_psci.c +11b25502ea937dd88b3986d358aad3eff9f39c71 - arm-trusted-firmware/plat/nxp/common/psci/aarch64/psci_utils.S +187a0bff6625818b129b5ab42039158f8126ddb3 - arm-trusted-firmware/plat/nxp/common/psci/include/plat_psci.h +08360ed6a8b3d051a5cad1cb6e001cf1600b7ac8 - arm-trusted-firmware/plat/nxp/common/ocram/ocram.h +5e45989256d4cb803eb129882666969d3d952ac6 - arm-trusted-firmware/plat/nxp/common/ocram/aarch64/ocram.S +f71b1c56189f5904469d9e69c7b5206a4bd12454 - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_reset.c +48b1c6e031a18037fbc338e8d3f6d0efbe6c0eca - arm-trusted-firmware/plat/nxp/common/warm_reset/plat_warm_rst.h +9c72b3ecd5d5982e63db876f7dfefb7cbac10bea - arm-trusted-firmware/plat/nxp/common/sip_svc/sip_svc.c +be62a5510efe4bb10130935015fc6c12d3b02ed4 - arm-trusted-firmware/plat/nxp/common/sip_svc/aarch64/sipsvc.S +27f86d14fd5ce72d0aaa417b4c893049acc97e1c - arm-trusted-firmware/plat/nxp/common/sip_svc/include/sipsvc.h +3a09baff31a554c63552bd51f6adea91aa05d3c1 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.h +193a96b82a70ef052d501107a7358ccca4890c12 - arm-trusted-firmware/plat/nxp/common/nv_storage/plat_nv_storage.c +9670a30b894318a795c85e5ee63edbe979b023b6 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/platform_oid.h +5898658243b0a5f981f4c051061be8d7f7ff3a7f - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_def_fip_uuid.h +fc286a6d896799156121d56095076ee1765cdd18 - arm-trusted-firmware/plat/nxp/common/fip_handler/common/plat_tbbr_img_def.h +e41af019a383e1c29f6cfe79b98e6812ee9e71e8 - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io_storage.c +0f0ae89b60dfac27f5f00ac6c76a3c1fbbf30e8c - arm-trusted-firmware/plat/nxp/common/fip_handler/fuse_fip/fuse_io.h +96bd522ef14fb5ff8a4247a028501ef7c4367f3a - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.h +97667263a954ff77c695a93ec98b767bccf035cd - arm-trusted-firmware/plat/nxp/common/fip_handler/ddr_fip/ddr_io_storage.c +dcfd794664af1da07e241e7f44705b02a86955bb - arm-trusted-firmware/plat/nxp/common/include/default/plat_default_def.h +1c0daba5be7bb7055a56df067ffc86d62af94382 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_base_addr.h +962eb919fbdac8edf23f3cca5303772adc4690b0 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3_2/soc_default_helper_macros.h +3b4e4e380dbab1bf4ad037c20f705b6e42b5d992 - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_base_addr.h +9fecb13f267ce5c792719b3969ef19e96064d75a - arm-trusted-firmware/plat/nxp/common/include/default/ch_3/soc_default_helper_macros.h +2941f6674d8de1d2b22c22b91db3b63996c45d80 - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_base_addr.h +764ceec06291ed492b81348c85ad37e77f32eb3a - arm-trusted-firmware/plat/nxp/common/include/default/ch_2/soc_default_helper_macros.h +254c94ec21e9680a13a88c1c24d884bfb8b9479c - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a008850.c +c693c689d519e4697e033a4df6e7da75ecaca5b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a050426.c +5f62419793539e6fbda55df6e2b3fa9e0b21b776 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.h +492965693fd60a384d16d12de2ecd89c7f522702 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_list.h +2e0e20e6baddb412ce97b52be66cd32d6f8f367f - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a010539.c +f925bc09cf5f24b92110d8e7eb81b6948bc855b7 - arm-trusted-firmware/plat/nxp/common/soc_errata/errata.c +0b417a1d9881a05757a25db89aa6739867cc6cff - arm-trusted-firmware/plat/nxp/common/soc_errata/errata_a009660.c +9b61ef7f7b42a7a2448ff56ef3a4dde77d0a3c6a - arm-trusted-firmware/plat/nxp/common/tbbr/csf_tbbr.c +99de11a8e1d6aa0d67bff400dc27222a3f67bda3 - arm-trusted-firmware/plat/nxp/common/tbbr/x509_tbbr.c +003b4e0c6ab04fb9bd51037a2c976e8e9a1e90dc - arm-trusted-firmware/plat/nxp/common/tbbr/nxp_rotpk.S +1fc45a1f2166ae38c534bcf389857b89c441c5af - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.c +0f6a22f1e28fcb385608a72a297b0cbd67935113 - arm-trusted-firmware/plat/nxp/soc-ls1088a/soc.def +492d3f0900343c093e718ba1816eb94bfc3931e9 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a.S +764c8c04a6189e6992612672f9e41abde5000248 - arm-trusted-firmware/plat/nxp/soc-ls1088a/aarch64/ls1088a_helpers.S +a7f75b9047c373fb59a317bd6d2995d70aa0aefa - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/policy.h +3328578a5401038f068eded4991d6a403c5276b7 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/plat_def.h +344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform.c +11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/platform_def.h +e9f8a604d5a2d30bd7a467c0b5624df132c867ee - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088aqds/ddr_init.c +992637daa6e8a443c6f0a176079ce731d593f699 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/policy.h +9c8add03dd402a33b546ebe338030483a6e30892 - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/plat_def.h +344959df5ba88c1bf9ce847e6735395045c1253c - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform.c +11e2d32b094714041c63cf972054b12b7c0db04e - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/platform_def.h +30d19335e7872d98487de84b2cc1cfad32bc26ad - arm-trusted-firmware/plat/nxp/soc-ls1088a/ls1088ardb/ddr_init.c +d1bd24409a0956382d617f97af627e582ec04d5c - arm-trusted-firmware/plat/nxp/soc-ls1088a/include/soc.h +b971fa529d2080fd471b3ef7ec4466a972529aee - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.c +189fa51ba04371ccab55ac105b7dfe77c07f3552 - arm-trusted-firmware/plat/nxp/soc-lx2160a/soc.def +ed1f52b1a3d4ce48135556f32d8667c7367494d8 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_helpers.S +63c93614b627d3a013d8176aa4248010115eecf0 - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a_warm_rst.S +3e9660b08500144943aee803a37816f45307d66b - arm-trusted-firmware/plat/nxp/soc-lx2160a/aarch64/lx2160a.S +e7b379eaa610c82050a0e57c194b10a794f23d91 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/policy.h +f53ad9b2677286b07fdbc25c8c257e4891f15607 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/plat_def.h +b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform.c +0fe0002fb83ef9fcbbed68caa9cea3b775bfc529 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/platform_def.h +764850c7f4814c83fc8b48d4a353c5ae2836edf6 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160ardb/ddr_init.c +353f72fa699efe7dc63602a04a220dd43adb85ba - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/policy.h +2881529cc073176412af0c380690bab77add20c5 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/plat_def.h +b52ff38c67c39f3dc4731b38d094152cb31b4ccd - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform.c +c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/platform_def.h +d07e54f7cdb54922dac5c758dd79b5adb4d9e93f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2160aqds/ddr_init.c +f856b32032e096e20ae0a454ad54d4fd64dfca0c - arm-trusted-firmware/plat/nxp/soc-lx2160a/include/soc.h +ab191a3fce41d791a52ed732c81fa4c127537b13 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/policy.h +6701efe4878d9b4a7d1035d7d747426951d04e8b - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/plat_def.h +85eb1ecc310643c5e3edb3761897745f5f4eaa6a - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform.c +c515220a4c8200d4212a8d951e49a9022e7bef2f - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/platform_def.h +e8ecd59dc257f4918515a132b0c4787bc1890021 - arm-trusted-firmware/plat/nxp/soc-lx2160a/lx2162aqds/ddr_init.c +07fb6c57566e19aa44ef34559874dfd995b582b6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.c +059b1c4ea6e6b540b7b01bdeb7153b4dfcacdb1b - arm-trusted-firmware/plat/nxp/soc-ls1043a/soc.def +b132e33ac02b41bfdd0b2ba27b1e5432e0f7ef08 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a_helpers.S +18db50ef3d11821179318d84b45c532d3b107226 - arm-trusted-firmware/plat/nxp/soc-ls1043a/aarch64/ls1043a.S +2e5c9db35f0a8446aa2a2a08f75f1488255df745 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/policy.h +60033abedd63947cfda10bf00d77951046e244c2 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/plat_def.h +859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform.c +802c1d23237eb5cc83388950a75fa13d076b0dbf - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/platform_def.h +2d532dcfca962bd50e2721dc90a3c5e8f3ef4c00 - arm-trusted-firmware/plat/nxp/soc-ls1043a/ls1043ardb/ddr_init.c +69427e6f64ce96dfa6842364a758359b8fa821c6 - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/ns_access.h +9b815992ca7df805a51a7cdece2e7c074a0958fb - arm-trusted-firmware/plat/nxp/soc-ls1043a/include/soc.h +7101b940d392636f546086caa2626d9a940d9eac - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.c +490b7dbb3b819d5251283d9069f177092c665489 - arm-trusted-firmware/plat/nxp/soc-ls1028a/soc.def +033fd89d203e44c446aba6134e51e46a7d9cf324 - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a_helpers.S +e436d0bfcc7b7c83db0242b6ffefad0a2985a81e - arm-trusted-firmware/plat/nxp/soc-ls1028a/aarch64/ls1028a.S +b435bed7113e72930be88bfe8f61e7da61994418 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/policy.h +264c5f8c566b8945850048aceba967dd8fd1e72b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/plat_def.h +859878633110369cd34a10f6683227f6b49d0006 - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform.c +daffee032773c1420ec3c8da52a5bc9db4610aaa - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/platform_def.h +3268f346c7eb1578007b13a160c4c3d08efe2c0b - arm-trusted-firmware/plat/nxp/soc-ls1028a/ls1028ardb/ddr_init.c +d78024dda44030bb2c60a6c6f0f31b0cdf79c510 - arm-trusted-firmware/plat/nxp/soc-ls1028a/include/soc.h +8539e94b825c242859fa5c4a3c03901703c386f0 - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.c +1e814209bd02d7457755dcf4493b05a3794c811c - arm-trusted-firmware/plat/nxp/soc-ls1046a/soc.def +8cc150d9e1c9199572b24d0af559c82e4db71320 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a.S +06d4dda248389e306ea0cf1688bc9944d1511d03 - arm-trusted-firmware/plat/nxp/soc-ls1046a/aarch64/ls1046a_helpers.S +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/policy.h +686ad098c68cbf424bb3e89e451ab64b8183a91c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/platform_def.h +2ea7db20f6633e1dbecd9a70ed4cac89d97c2a76 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046ardb/ddr_init.c +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/policy.h +39ce8f1f0afc76a2d1a98e86df076ef84d185da3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/platform_def.h +60e78557693ed12515227f051b8f55baf47ce8ae - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046aqds/ddr_init.c +0fb5432862f668e38f9bbce3af181371cdecf0cd - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/policy.h +dc407d2ead98e6d20e59ac0b6c5e75116a82ddd3 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/plat_def.h +5da46b775851344c65928890c699d7ff047606b2 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform.c +0f38703d163bd042c7827eaddb04ea092b30a478 - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/platform_def.h +945ec23ee2ba0c79a5e6140d043290e9afde9b2c - arm-trusted-firmware/plat/nxp/soc-ls1046a/ls1046afrwy/ddr_init.c +bfdacfdea0aa10e1ece5ae2925625ce34328672a - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/ns_access.h +9ed3d544ff5ab2cfa0ea13d1fb3b59534eb90e14 - arm-trusted-firmware/plat/nxp/soc-ls1046a/include/soc.h +1e1f92bc6f801c91fde3bbe4ce99b62beb0eb7d2 - arm-trusted-firmware/plat/imx/imx7/warp7/warp7_bl2_el3_setup.c +42143dbacac34a118b7b86673774e843e7e84fd8 - arm-trusted-firmware/plat/imx/imx7/warp7/include/platform_def.h +1e876f487cd25f4a6cd08d0a21926f5405676a07 - arm-trusted-firmware/plat/imx/imx7/picopi/picopi_bl2_el3_setup.c +1b13f9e313e75353b45d6528629485488b180345 - arm-trusted-firmware/plat/imx/imx7/picopi/include/platform_def.h +8403135be33e11a4b696e90b5b253465b6838682 - arm-trusted-firmware/plat/imx/imx7/common/imx7_helpers.S +81ea2015e04bbc53b7d42589a21821a183fc1c8a - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_el3_common.c +3bba3282b340c9896990c2ffcbf10d5bfb0070b2 - arm-trusted-firmware/plat/imx/imx7/common/imx7_rotpk.S +4d406209e8b278e9730968baee57f5106d424aef - arm-trusted-firmware/plat/imx/imx7/common/imx7_trusted_boot.c +7b5d73ec9d9c7e14fd48653c6e018d432654101d - arm-trusted-firmware/plat/imx/imx7/common/imx7_bl2_mem_params_desc.c +bffe5bd7851f8d028c92d9d68dba7806be5bd662 - arm-trusted-firmware/plat/imx/imx7/common/imx7_image_load.c +10003f2e608d5073c076ab1a446f4ba07c06086d - arm-trusted-firmware/plat/imx/imx7/include/imx7_def.h +d4e968db5e699bc36032dfe35d7fada27142c699 - arm-trusted-firmware/plat/imx/imx7/include/imx_hab_arch.h +1027e5173d316fd6d9dd6588b9666b53ed9d1116 - arm-trusted-firmware/plat/imx/imx7/include/imx_regs.h +9026b30dd1244e0fa2416dac0e9f2b92c11bc83e - arm-trusted-firmware/plat/imx/common/lpuart_console.S +829a4463f8628c61fcb335a0dbd747a6050c8192 - arm-trusted-firmware/plat/imx/common/imx_sip_svc.c +03ff82e03dc9eb60e02c6e23f0c199fdd1753c9c - arm-trusted-firmware/plat/imx/common/imx_aips.c +83187f1c90615deae51e2febc0506394e8d4d444 - arm-trusted-firmware/plat/imx/common/imx_sip_handler.c +c014188b6f4a48f9dc6d6fed678081f02f8d8e86 - arm-trusted-firmware/plat/imx/common/plat_imx8_gic.c +e03b60801f58711597b0bb457ecf6e3e84c9f44e - arm-trusted-firmware/plat/imx/common/imx8_psci.c +5225b741c941cba9f489d347aae2707d99896d7d - arm-trusted-firmware/plat/imx/common/imx_csu.c +1901b0c4a5e19926a9e1b5ae437ebbeb0dc0d181 - arm-trusted-firmware/plat/imx/common/imx7_clock.c +ad339798ed1c81b2dfda72cc1cefaae7acb622d9 - arm-trusted-firmware/plat/imx/common/imx_io_storage.c +e7ef15bdf83a7d4e3ca78dd0d0e9daf56414e55e - arm-trusted-firmware/plat/imx/common/imx_caam.c +f30799014ffd50a32b0d021473b50cf5c4a28634 - arm-trusted-firmware/plat/imx/common/imx_clock.c +da4b81f475ec53f2578ba031cd1f30f759bc5dde - arm-trusted-firmware/plat/imx/common/imx_snvs.c +1b219401b9b5eb5bd8c83fa92fc68c591d48a3da - arm-trusted-firmware/plat/imx/common/imx_io_mux.c +b26cdffd75a0ba04b4a312520443d0c77b388242 - arm-trusted-firmware/plat/imx/common/imx8_topology.c +97029bcef11b7a8598834c9717cec7a5655b895a - arm-trusted-firmware/plat/imx/common/imx8_helpers.S +561b0822ac98206dceac588b536d745fc70829d9 - arm-trusted-firmware/plat/imx/common/imx_ehf.c +6ac985911e7e26d13c75d48a04457fbcb209b62f - arm-trusted-firmware/plat/imx/common/imx_sdei.c +ac923dd7af0d3485eceae86115ea73150575ac4f - arm-trusted-firmware/plat/imx/common/imx_wdog.c +d93d2cf3c9aafc65833374f51376f03bc2387ecd - arm-trusted-firmware/plat/imx/common/imx_uart_console.S +36d5f07566aad340b6ec06b01cfbe631023ca7f5 - arm-trusted-firmware/plat/imx/common/include/imx_wdog.h +a3a14f38cbc846da3bc2498cf8e07b62479aa62a - arm-trusted-firmware/plat/imx/common/include/imx_snvs.h +8830c18819f942388c5badcb2c19eaea2ae058dd - arm-trusted-firmware/plat/imx/common/include/imx_caam.h +0b633d6b19c3fd7cb43c433d74b84ede423bab4f - arm-trusted-firmware/plat/imx/common/include/imx_hab.h +8ae002187ace1e1358c7af1e06ef7957179939f5 - arm-trusted-firmware/plat/imx/common/include/plat_macros.S +bddfe7c6dc079e9f45c4a41601888d27f5d29c48 - arm-trusted-firmware/plat/imx/common/include/imx_csu.h +28b31b74552131c2ba5875fb7db44b22ca16b722 - arm-trusted-firmware/plat/imx/common/include/imx8qx_pads.h +2e84528c7d6b12beb2c64505a14d73bcfb03ef87 - arm-trusted-firmware/plat/imx/common/include/imx_aips.h +a5fcaffa0e69f234b0620f32d3556bf79ace50f1 - arm-trusted-firmware/plat/imx/common/include/imx8_iomux.h +816bfc02478ff083b5f3557753a4d0d4f2f32c9e - arm-trusted-firmware/plat/imx/common/include/imx8_lpuart.h +b9d688fac07189d434ac636324a632e9bf78825c - arm-trusted-firmware/plat/imx/common/include/imx_clock.h +f5724b26de0d68b4b37e1d580c6e30842eacd6c0 - arm-trusted-firmware/plat/imx/common/include/plat_imx8.h +efda9e3617b99df89057880a566725ab2a7be20d - arm-trusted-firmware/plat/imx/common/include/imx_sip_svc.h +24f8d34fd7865c2235d12e87791c7ae77d55d281 - arm-trusted-firmware/plat/imx/common/include/imx_io_mux.h +6f89a14dc12ddacabad367a7e69d8bf469274ec4 - arm-trusted-firmware/plat/imx/common/include/imx_uart.h +1d847530cd83143e4a50b94c5499ee8c11f9d3e1 - arm-trusted-firmware/plat/imx/common/include/imx8qm_pads.h +8a65436d5e0b335e9003a30f2da5f7892d23dc05 - arm-trusted-firmware/plat/imx/common/include/sci/sci_scfw.h +f6e6cd4d5b145f5abd0aa4d840fd7757d4b02c04 - arm-trusted-firmware/plat/imx/common/include/sci/sci_rpc.h +19674e70669fa3f7fb7e509377e445f7fd4c7be4 - arm-trusted-firmware/plat/imx/common/include/sci/sci.h +cc9366b07e946d7946bdfeae628f8a6c7ac3bed3 - arm-trusted-firmware/plat/imx/common/include/sci/sci_ipc.h +daeb14deb7c4f498330bb44186346cd1ac4eef92 - arm-trusted-firmware/plat/imx/common/include/sci/sci_types.h +70210ef96ff1f0ccd4e790bb79a148f1bf02efcc - arm-trusted-firmware/plat/imx/common/include/sci/svc/rm/sci_rm_api.h +4be7f4400810802474258ed3e4b8f7a73170db33 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pad/sci_pad_api.h +cf9e73e1a62f99ecb17abeeda5efbdad0f7b1c21 - arm-trusted-firmware/plat/imx/common/include/sci/svc/misc/sci_misc_api.h +d3b138328cc81b7fe0a830b3cec8bd87f7d62835 - arm-trusted-firmware/plat/imx/common/include/sci/svc/pm/sci_pm_api.h +2507eeb7a0cd662322ea96553146f0f0dc8c6e45 - arm-trusted-firmware/plat/imx/common/include/sci/svc/timer/sci_timer_api.h +8169135849017c45a81b2c0447e940e3e5396145 - arm-trusted-firmware/plat/imx/common/aarch32/imx_uart_console.S +985fca791927ad8088399ab8840bcbcfb8277a6e - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.c +f2ab11050d68bdc711e7c18f9437fba728ab77bb - arm-trusted-firmware/plat/imx/common/sci/imx8_mu.h +8c98c79db7801610b0bf01e1ea680ec8347be4f2 - arm-trusted-firmware/plat/imx/common/sci/ipc.c +fdc0fc24ee38df2fd92f2f039664af39724513e7 - arm-trusted-firmware/plat/imx/common/sci/svc/rm/rm_rpc_clnt.c +9162637c3ad8ef97f19a264c504c58d5886f9d7c - arm-trusted-firmware/plat/imx/common/sci/svc/rm/sci_rm_rpc.h +a593348ba8dcf5a3577bb48cd9d9ab7fe88c6df7 - arm-trusted-firmware/plat/imx/common/sci/svc/pad/pad_rpc_clnt.c +53b961e268ec00956cf3635d8561601e5c5bf70b - arm-trusted-firmware/plat/imx/common/sci/svc/pad/sci_pad_rpc.h +65f1e12aab1c7815ccb98973525d32d30e635a1d - arm-trusted-firmware/plat/imx/common/sci/svc/misc/misc_rpc_clnt.c +1dc0e610322825b6f58ac08670b99a4598bc01f1 - arm-trusted-firmware/plat/imx/common/sci/svc/misc/sci_misc_rpc.h +ada89ab08a1bfb90ad5b0e5ffb325268ddbc837e - arm-trusted-firmware/plat/imx/common/sci/svc/pm/pm_rpc_clnt.c +99d10095088dddbbe81826dbf7827bdc9c6bffb8 - arm-trusted-firmware/plat/imx/common/sci/svc/pm/sci_pm_rpc.h +3f381087336a847b53323f6828aa61478b46a2cc - arm-trusted-firmware/plat/imx/common/sci/svc/timer/sci_timer_rpc.h +30cf1dfdd48ef57921bbd93789aaedbebd754c55 - arm-trusted-firmware/plat/imx/common/sci/svc/timer/timer_rpc_clnt.c +7bd8d4e39f1f3905630b08a16be851097fa5ab67 - arm-trusted-firmware/plat/imx/imx8m/imx_rdc.c +10fb6753c1ece21522f45f372d0cbf3b416b5190 - arm-trusted-firmware/plat/imx/imx8m/imx_aipstz.c +51949e20cb7aee1a68f0cc5eaa46f0eb3012c2dc - arm-trusted-firmware/plat/imx/imx8m/gpc_common.c +ceb0518eca09618b3b642b96d4fb43d950bdfabb - arm-trusted-firmware/plat/imx/imx8m/imx8m_psci_common.c +996e00079997c54373e5acb4a6f39bfe8cbe346e - arm-trusted-firmware/plat/imx/imx8m/imx8m_image_load.c +3065b6071ec153725ca0d9782a393ffd3f24745d - arm-trusted-firmware/plat/imx/imx8m/imx8m_caam.c +6253f7542bd4e5a6244779068845d717f8eca3f6 - arm-trusted-firmware/plat/imx/imx8m/imx8m_measured_boot.c +ee448951c5f07c67e8c374cb6a4077c505070081 - arm-trusted-firmware/plat/imx/imx8m/imx8m_dyn_cfg_helpers.c +a2af87335b959f57d6de74f40740b48de27a802e - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_psci.c +461d439b6ee554e1dce2786de8e131e60083bca6 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/imx8mq_bl31_setup.c +ff7748fc70a67a41bd452b895f531d103d0b3cfa - arm-trusted-firmware/plat/imx/imx8m/imx8mq/gpc.c +d1fa70b45e2971a3e4103d0b2ff864ec706c5af5 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/gpc_reg.h +2db42326b731e92225ca5c389557d0b944e8d3a7 - arm-trusted-firmware/plat/imx/imx8m/imx8mq/include/platform_def.h +3fcc366713e1667476479363fd2d0fb74144e491 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_mem_params_desc.c +f9007785b7de40f327bd11a83c710c297b45e4ab - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_trusted_boot.c +060756d07ff95fa2e15ef2cab742c6f6fdfdc5e3 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_rotpk.S +5e7971c14f77e2f2450badad4a156ca33a9eb89f - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl2_el3_setup.c +a3afe5951fdd7ba0d6e5b64214a2183800a80132 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_bl31_setup.c +0e0933de6793e323f4c77e12a89455776a0dfe57 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/imx8mm_psci.c +1bb0ea0358213dbd45eb953fdbb45234606078d0 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/gpc.c +0f9e1a9d6497a3ad4e415d483905f2ef16aaa423 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/imx8mm_private.h +4a704d5f5cc4958ad509fe9771d30d6632cb1a0a - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/gpc_reg.h +c81f2809571226d121ea1917bdbfe06afcd9b523 - arm-trusted-firmware/plat/imx/imx8m/imx8mm/include/platform_def.h +e7ded5d1571dcf2246b5480dea7517bbc0e45a87 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_psci.c +629b2fa411eef0f016ff98ec22caee2012cdf650 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/imx8mn_bl31_setup.c +d50646f42ed68bca258b692593812b18c635dbb0 - arm-trusted-firmware/plat/imx/imx8m/imx8mn/gpc.c +82259d3c2b7d974ad94a42c37f37e0a8f0ce576f - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/gpc_reg.h +a6e3b2e69300fabcd3a505525cc5d48d88345f7a - arm-trusted-firmware/plat/imx/imx8m/imx8mn/include/platform_def.h +47de7cdf356158f2b651bafb8659187db3a13e65 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_measured_boot.h +4bc0eb69bf40f2ac07200a788f79ad6e9ec8b3f2 - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_psci.h +dbc9dbdd5e6269f4f08553a771a33f13a1fa884a - arm-trusted-firmware/plat/imx/imx8m/include/imx_rdc.h +3bc736f072705dfa2d00383fe60d8497b3676fcc - arm-trusted-firmware/plat/imx/imx8m/include/imx8m_caam.h +a70728dd56a39269eebea0b5d96e9e82765e1e7a - arm-trusted-firmware/plat/imx/imx8m/include/gpc.h +5ec5413514abe79264b0bed81c75f811d2621d46 - arm-trusted-firmware/plat/imx/imx8m/include/imx_aipstz.h +0efee336c964d1973fec201980455aee08396081 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_trusted_boot.c +be1935709a939c0480bc4cc27058482508f2596b - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_mem_params_desc.c +f822b4b589b5d418d0ea960b764bd311a32466ea - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl31_setup.c +49f3d2caa5e653fc6cdd99c140ff61ad9d83c9c0 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/gpc.c +3d38c99169530f67aeba8526bd7cd4559981a349 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_bl2_el3_setup.c +169ab98f3d4cd7620ffef0d78f7c2329be9c1586 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_psci.c +97a556f1fc780240a2ad81127c295bd39a0c6512 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/imx8mp_rotpk.S +c65d55a5e1a73f615b9fe213427e4605f4b3806c - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/imx8mp_private.h +df0e3b50430ac47d2263ca8e0a4b83d46c8c0193 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/gpc_reg.h +f7d6a1f75a510179a6e4a7084b3d70dd9bba5734 - arm-trusted-firmware/plat/imx/imx8m/imx8mp/include/platform_def.h +399d2117be7573ef7ddc5afb0364b90fc66d9bb6 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_bl31_setup.c +b9316c7a608b29b530aaf325e401e06f62647525 - arm-trusted-firmware/plat/imx/imx8qx/imx8qx_psci.c +06458d5a3b748df586e9ba2064614354842c162f - arm-trusted-firmware/plat/imx/imx8qx/include/sec_rsrc.h +5f45eb6e98ea9c90548afd5ee153f8d14c105e48 - arm-trusted-firmware/plat/imx/imx8qx/include/platform_def.h +9561f3046a19b5489e0aa9025135c8bb6a7d2582 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_bl31_setup.c +08a0687e7c3b77de90198dc7e5d8ca2ec448ae90 - arm-trusted-firmware/plat/imx/imx8qm/imx8qm_psci.c +6beb54a392291f2d54d207842b2620c7c344af8e - arm-trusted-firmware/plat/imx/imx8qm/include/sec_rsrc.h +1fdf9dd0a1e00cee360596ce35842f77598cbf1e - arm-trusted-firmware/plat/imx/imx8qm/include/platform_def.h +54eb696ef592336053f52bc556f47122b4e94fdc - arm-trusted-firmware/plat/rpi/rpi4/rpi4_pci_svc.c +793e163b5e60486c53f3ff36c98ab1c8f144a1bd - arm-trusted-firmware/plat/rpi/rpi4/rpi4_bl31_setup.c +5e76d520f8ea85f6710a605e2c9a4db0d1a66640 - arm-trusted-firmware/plat/rpi/rpi4/aarch64/armstub8_header.S +b1c50f058d68ea165b6dd5f45af97d2b1dd33e64 - arm-trusted-firmware/plat/rpi/rpi4/include/plat_macros.S +6a73f5496572d65332bbf4a50c3c9d4faa9af438 - arm-trusted-firmware/plat/rpi/rpi4/include/platform_def.h +e2412e3cbdcc8daaecfab85f295ee3456cf1f98d - arm-trusted-firmware/plat/rpi/rpi4/include/rpi_hw.h +4d8d91a23a19a15ff7c18f8e6e523c26cd453f2f - arm-trusted-firmware/plat/rpi/rpi4/include/plat.ld.S +11c87bf8a084123bf9a431cc289a66e23112bade - arm-trusted-firmware/plat/rpi/common/rpi3_rotpk.S +e621f46501a2d1856f297145947d1c8d89d5f990 - arm-trusted-firmware/plat/rpi/common/rpi3_image_load.c +d2d1fd0fffc8a200fd42f1b74c8c7d54c483f219 - arm-trusted-firmware/plat/rpi/common/rpi3_trusted_boot.c +41feb9d914df818ac88209ee1569e1701d794248 - arm-trusted-firmware/plat/rpi/common/rpi3_common.c +46c13e3cff3d9c29a733d01629589bd31b37eb5e - arm-trusted-firmware/plat/rpi/common/rpi3_stack_protector.c +dc79372e77a81c53ff2886832f206db2f63873b7 - arm-trusted-firmware/plat/rpi/common/rpi3_topology.c +854bc00d3c5fce60726920c1e5b1b7cd9352568a - arm-trusted-firmware/plat/rpi/common/rpi3_io_storage.c +2880e20e8241800797f95dadcd5a206d82ba45ed - arm-trusted-firmware/plat/rpi/common/rpi3_pm.c +d2456dd752e5376ca6049639fe93ef04bd5aa04f - arm-trusted-firmware/plat/rpi/common/aarch64/plat_helpers.S +c3a79cfd4e400e0a2dfa7ee5e27e50f1bcd8464b - arm-trusted-firmware/plat/rpi/common/include/rpi_shared.h +fd5000ab9d2eac8341e267b879e1ef29eaebf5d7 - arm-trusted-firmware/plat/rpi/rpi3/rpi_mbox_board.c +052815ff6a9d47f47e57d320313a74f10c8a34d3 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl31_setup.c +20b2e08539e950f86d86538ed688408f90574454 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl2_setup.c +d9b070fbdda2cab75cc45e6dddd9a31f84baf594 - arm-trusted-firmware/plat/rpi/rpi3/rpi3_bl1_setup.c +5a79ec05194636d3850044f358b4673a3f0b9fa0 - arm-trusted-firmware/plat/rpi/rpi3/aarch64/rpi3_bl2_mem_params_desc.c +64987d2484ce3d48cc4431fee2de9e375235bb5a - arm-trusted-firmware/plat/rpi/rpi3/include/plat_macros.S +7aeb3415e697151619997c1c184f380eb310be78 - arm-trusted-firmware/plat/rpi/rpi3/include/platform_def.h +94001fd4bfa1b8e08f4d51f437c7b006362f24fd - arm-trusted-firmware/plat/rpi/rpi3/include/rpi_hw.h +c2785b4c0937862f1abb7251642a4028a913504d - arm-trusted-firmware/plat/allwinner/sun50i_h6/sunxi_power.c +2514153e63bbcc5513712db8766fd278fa3b0d44 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_mmap.h +3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_spc.h +0b8b7ce5f06e24ad7b853125e17507934dfc45e5 - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_cpucfg.h +1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h6/include/sunxi_ccu.h +704da3ea1b61d5106a6172712ecf6a80b1528bf0 - arm-trusted-firmware/plat/allwinner/common/arisc_off.S +e602a60b0fabfe8e91ecf654c16701712b20c3f1 - arm-trusted-firmware/plat/allwinner/common/sunxi_native_pm.c +a5e148901e32cb7feaef9ffbd00f43a2a661ea0c - arm-trusted-firmware/plat/allwinner/common/sunxi_common.c +a7dce777afe91e3a8d68aaa84d55530a9b3b66b4 - arm-trusted-firmware/plat/allwinner/common/sunxi_bl31_setup.c +385e3bbf7c85ef4e96b553e0f9760bfef1e94a3a - arm-trusted-firmware/plat/allwinner/common/sunxi_pm.c +f2bc1957fa87b9880744d070c964b7803c7bf295 - arm-trusted-firmware/plat/allwinner/common/sunxi_topology.c +b832fd1c1d7bc307d2c3698bf00ee15b93de8cb8 - arm-trusted-firmware/plat/allwinner/common/sunxi_cpu_ops.c +a9a0eca6a5cca079ee8007e0afa7f0ffd7a0cf1c - arm-trusted-firmware/plat/allwinner/common/sunxi_scpi_pm.c +0ded87657ff47f0fe5896f1ab1d6d2f9b34f0429 - arm-trusted-firmware/plat/allwinner/common/plat_helpers.S +a44feb979fffb71189cf9943a6d99946305122e2 - arm-trusted-firmware/plat/allwinner/common/sunxi_security.c +711ef06aa592d857ab47ecd0a9b7870c6fa1a5da - arm-trusted-firmware/plat/allwinner/common/include/sunxi_def.h +7d746a44b6a3bbaa1c3e923de0abdfc40393712e - arm-trusted-firmware/plat/allwinner/common/include/plat_macros.S +77455765d6d80bf4a48d7744bf6f4770b7369215 - arm-trusted-firmware/plat/allwinner/common/include/mentor_i2c_plat.h +cc00c1c7f46a2a8af976c1c0fb59681803b68d1c - arm-trusted-firmware/plat/allwinner/common/include/sunxi_private.h +4333584318d0a967851853f5fcd6c5287277246c - arm-trusted-firmware/plat/allwinner/common/include/platform_def.h +3fa3a563994fcf2710324634950265fc8f9d7850 - arm-trusted-firmware/plat/allwinner/sun50i_r329/sunxi_power.c +d430caf710295e9e77a240b785740fdde6705e26 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_mmap.h +1acbdb220cff8edffa7cc7fd4808f71574b90966 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_spc.h +f8fae43c9902bbf818480c6633e05fc6b751aabd - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_cpucfg.h +2870bd5728ae0e5857fadde22b048a6fcf6ee2d3 - arm-trusted-firmware/plat/allwinner/sun50i_r329/include/sunxi_ccu.h +a38730b258e2c37f114fdb3c923369bade8e7a1a - arm-trusted-firmware/plat/allwinner/sun50i_a64/sunxi_power.c +54ee3b911a552e2cd6e3802820f5cf3e09575a01 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/core_off_arisc.h +3f4f908a2f0a6a7660d40d79215077ee248f740e - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_mmap.h +2c5ad97e48086e62d1d58d1d8289ac4ab3153179 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_spc.h +a462f612d127344fc711a68e3751b31b2b7ce938 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_cpucfg.h +65eec287284371a887adc4c9aa1952c26be66df7 - arm-trusted-firmware/plat/allwinner/sun50i_a64/include/sunxi_ccu.h +786942614a650ccd6930f2bd19bb42b2b539e1f9 - arm-trusted-firmware/plat/allwinner/sun50i_h616/sunxi_power.c +d9eff8a29c53d38215c1d261922df8494c88d5aa - arm-trusted-firmware/plat/allwinner/sun50i_h616/prepare_dtb.c +2b80f35aa1746d608c2eac4eec351c292e0298f0 - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_mmap.h +3dde76eb498c889851714b3d8e6749211c62bbec - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_spc.h +0ba24eb82465b3d3ad4e293692984b972663d57c - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_cpucfg.h +1590f260f1febbedf931a1596cea2d2e437ea92b - arm-trusted-firmware/plat/allwinner/sun50i_h616/include/sunxi_ccu.h +1c810633809eed169ef7ae47da01b6326b111a64 - arm-trusted-firmware/plat/amlogic/common/aml_console.c +887d16c962bbfdec5ddb366c33ffec0ad5697447 - arm-trusted-firmware/plat/amlogic/common/aml_thermal.c +f1168dcf0c90f4d7a3456d82b909e287a16875ed - arm-trusted-firmware/plat/amlogic/common/aml_topology.c +1b86970e6e211ba1548f3469a4682db7c31577f1 - arm-trusted-firmware/plat/amlogic/common/aml_mhu.c +fa91c2d51bbe34be89ba41e055f4e78eba6ac67e - arm-trusted-firmware/plat/amlogic/common/aml_efuse.c +2321fbf75d8e96d90a1b6f6a14160c91b949cabc - arm-trusted-firmware/plat/amlogic/common/aml_scpi.c +22fc306f5f9b6613312023233481baaf99493614 - arm-trusted-firmware/plat/amlogic/common/aml_sip_svc.c +61752908966c74b637938d2fa11e73c5d5373d9d - arm-trusted-firmware/plat/amlogic/common/aarch64/aml_helpers.S +74bc476713af13ff5ee94c7bdad6c5763f99e9af - arm-trusted-firmware/plat/amlogic/common/include/plat_macros.S +5240bdc42061a821a089cae1eeca3fb799e6aa1c - arm-trusted-firmware/plat/amlogic/common/include/aml_private.h +5ce07f2865d514a3a8979c638337a338fa110f74 - arm-trusted-firmware/plat/amlogic/gxl/gxl_pm.c +68a18488494ea52a108462ec30b6833447e75e62 - arm-trusted-firmware/plat/amlogic/gxl/gxl_def.h +550ec6753c2e8a5f41a920ea9bfffec47ae78dc8 - arm-trusted-firmware/plat/amlogic/gxl/gxl_bl31_setup.c +8b93edbe34b51b737299797607de4e6ff0003917 - arm-trusted-firmware/plat/amlogic/gxl/gxl_common.c +22603b51918b7c1f721eee33d26629b16cff6683 - arm-trusted-firmware/plat/amlogic/gxl/include/platform_def.h +fe8712d8d4a3787c6c2456ffcc2cc468b12bfd7e - arm-trusted-firmware/plat/amlogic/g12a/g12a_bl31_setup.c +495f096204283e82b03abed56414e3d1a29f9b6f - arm-trusted-firmware/plat/amlogic/g12a/g12a_def.h +03a70925292deabd473bf5ffcd0d0d95dd70456e - arm-trusted-firmware/plat/amlogic/g12a/g12a_pm.c +28726387d3750ce4724f9147e5e173131ee7164f - arm-trusted-firmware/plat/amlogic/g12a/g12a_common.c +8e1154709ae343cd8d783739b29005ea2b9a7c7f - arm-trusted-firmware/plat/amlogic/g12a/include/platform_def.h +3389361e87f5cd5e4f7e606599032c3aa3a41b72 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_def.h +704885551348b4b44d9b7b092aafc3c54533b7e0 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_bl31_setup.c +25d4db1b1e385a2e45f4ffea43edbfc8bf4fef89 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_common.c +80fbc4757d8f389dc885b90a5eef8c0c4f6e23c2 - arm-trusted-firmware/plat/amlogic/gxbb/gxbb_pm.c +d558f98c64955249d21b9227149b68808cb3e358 - arm-trusted-firmware/plat/amlogic/gxbb/include/platform_def.h +7fdb79ffddbe1ee7f1b2c543a1eaa07f2671a2ca - arm-trusted-firmware/plat/amlogic/axg/axg_pm.c +c60f26b9eb14d703065a758062f9c76e4e70f8ed - arm-trusted-firmware/plat/amlogic/axg/axg_def.h +3667781fa0058dcdd1cff5587b45c798978c7966 - arm-trusted-firmware/plat/amlogic/axg/axg_bl31_setup.c +d3c822e681ab6d5016ae06adb88ca9aeb6073aba - arm-trusted-firmware/plat/amlogic/axg/axg_common.c +faf31bdcea206b83c40fbe2d878c14fa8327a37a - arm-trusted-firmware/plat/amlogic/axg/include/platform_def.h +5e22516412e81af7bbc52e0e460447cf2d1d63f3 - arm-trusted-firmware/plat/common/plat_log_common.c +cd74e2d1ac7f09f4ced54eecf4bed38f973bbdfb - arm-trusted-firmware/plat/common/plat_gicv3.c +c7afb73f40f0759cd775aec59723f92f7dd54435 - arm-trusted-firmware/plat/common/plat_bl1_common.c +ebb8418a3c0ba1d0d9362005c17fc4a3fb03cf1f - arm-trusted-firmware/plat/common/plat_gicv2.c +dd38f3a1079a17328d48c8cb719713d4de7361a6 - arm-trusted-firmware/plat/common/ubsan.c +ca3750949173b2315d20907e7c6da4a66f32a5cf - arm-trusted-firmware/plat/common/plat_bl_common.c +8020a28923a271101b29516f4997bb7a1b8a6708 - arm-trusted-firmware/plat/common/plat_spmd_manifest.c +ec9195d2ba3b66b6f4258c18a36b14a5cf41ac55 - arm-trusted-firmware/plat/common/plat_psci_common.c +6ae1755d17b7040c038dd8b2e6c6880e2bb60394 - arm-trusted-firmware/plat/common/aarch64/plat_common.c +8be9392135f6389b22910a9e22011c2e5abc6708 - arm-trusted-firmware/plat/common/aarch64/crash_console_helpers.S +8bf3a22931bb5a18034f1275429068834943cb9e - arm-trusted-firmware/plat/common/aarch64/plat_ehf.c +53568d8d4a43005d8a1be8a379cf0f4b7ddc5637 - arm-trusted-firmware/plat/common/aarch64/platform_helpers.S +1fe60996e262523b671b678aa41a510a2cfa2ce9 - arm-trusted-firmware/plat/common/aarch64/platform_up_stack.S +785a7be686f124f8b30c5f96bbdc9670988f49c2 - arm-trusted-firmware/plat/common/aarch64/platform_mp_stack.S +05ebeff6ee2416ab2697799fb338367a03b0ba75 - arm-trusted-firmware/plat/common/aarch32/plat_common.c +c8eab49f9d5326ffc974d2ba7c05bd411df90eb1 - arm-trusted-firmware/plat/common/aarch32/crash_console_helpers.S +01fc909940aee253c9e140248811b8c4fc5d25b4 - arm-trusted-firmware/plat/common/aarch32/platform_helpers.S +f742befce701fed79ec16b324c92409b36838226 - arm-trusted-firmware/plat/common/aarch32/plat_sp_min_common.c +79f7a0e7df796600cfad4b11f4bf7dbafb65a4ea - arm-trusted-firmware/plat/common/aarch32/platform_up_stack.S +578b46ce0ccf74ba18ce1747df871537294d4ddf - arm-trusted-firmware/plat/common/aarch32/platform_mp_stack.S +36144ebe1637da9185e2256593f8aa7307d0cccb - arm-trusted-firmware/plat/common/tbbr/plat_tbbr.c +43da4a7bd6435c6cc7d733e6363a59cacabb9ef5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.c +c02bbae941528cbae0665016d62e54bfffb74444 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_setup.c +389238486613bb86c6032f788a4605c782e7475c - arm-trusted-firmware/plat/brcm/common/brcm_gicv3.c +48faf64df1848d8493a3f273494ea883a4aafb0c - arm-trusted-firmware/plat/brcm/common/brcm_common.c +9b8db7387e47af68fc183fe909d3060d65438cb2 - arm-trusted-firmware/plat/brcm/common/brcm_io_storage.c +d083c67e189d3cd3712a827a23e28d0aaf2964d1 - arm-trusted-firmware/plat/brcm/common/brcm_bl31_setup.c +02ea7c4006c2910720bf4a85c3766c293d4cb8e5 - arm-trusted-firmware/plat/brcm/common/brcm_mhu.h +2ef6d891873792dd5af17cc1091f369c0865c70d - arm-trusted-firmware/plat/brcm/common/brcm_image_load.c +6d6865834cfc5ce82506bf1ef6df2e3cb196e028 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.c +7c0af43209d486bb7d9b76b244d3fc5ec97b4328 - arm-trusted-firmware/plat/brcm/common/brcm_bl2_mem_params_desc.c +303c81103a6ebbdf9e4afc16b17d17195a5b9238 - arm-trusted-firmware/plat/brcm/common/brcm_scpi.h +43088754fcc9a1fcbb6308988d79eca0c2771d5a - arm-trusted-firmware/plat/brcm/common/brcm_ccn.c +a794cd95a890c951acc5192426abc008b4213a8f - arm-trusted-firmware/plat/brcm/board/common/chip_id.h +eeff346a4c2b6893ad0fa417570e747058627c11 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.h +2d3a08ac4729a455bffd5c4c70365350fec69e23 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.h +779be799404c9562032c8c586f3a3b23835ad722 - arm-trusted-firmware/plat/brcm/board/common/board_arm_trusted_boot.c +801bb1cdab4baf3440ac23728e6190881af4264f - arm-trusted-firmware/plat/brcm/board/common/bcm_elog_ddr.c +c0ecc823e4de1814edd6bf48321b6317c448b16d - arm-trusted-firmware/plat/brcm/board/common/sbl_util.c +2cf7d5accbb22d89a3c89c768604f667a23bef52 - arm-trusted-firmware/plat/brcm/board/common/sbl_util.h +dfc2e7fae9dd66b664758412e1f4c06762246ed6 - arm-trusted-firmware/plat/brcm/board/common/cmn_sec.c +5f45cc70d813bf16880f4f1f4a246ad6114fbb78 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_util.h +aaa8593ded989c77280d5a16f541eefd45c62067 - arm-trusted-firmware/plat/brcm/board/common/cmn_plat_def.h +eca89f1edcb0c3fc702ac123a55821cde16106bb - arm-trusted-firmware/plat/brcm/board/common/err.c +9eda9f547bdfb6e83ef3c8d82d849e1e4cb68252 - arm-trusted-firmware/plat/brcm/board/common/brcm_mbedtls.c +b2a5352558dc92001c80e614a9b293a1eb19573a - arm-trusted-firmware/plat/brcm/board/common/plat_setup.c +a731b4badf1cf5a90a0ab197b39a2723e4c85dd9 - arm-trusted-firmware/plat/brcm/board/common/platform_common.c +9635661f5e56e9ab172dcec943257465bf36e634 - arm-trusted-firmware/plat/brcm/board/common/bcm_elog.c +500e36754a0240001fe7b400bf8d4806a06de6ee - arm-trusted-firmware/plat/brcm/board/common/timer_sync.c +c124ba5ec6d9fc3e8f1f0b72d3852473ab67e998 - arm-trusted-firmware/plat/brcm/board/common/board_common.c +515e3aecc5237dcc8197e4e8ed7fd7d15765d808 - arm-trusted-firmware/plat/brcm/board/common/bcm_console.c +ac2b64132debec3b54ae614c64dac69067b39291 - arm-trusted-firmware/plat/brcm/board/stingray/aarch64/plat_helpers.S +b4637f982a40118b9d83d3908d0b189d3524bce0 - arm-trusted-firmware/plat/brcm/board/stingray/driver/plat_emmc.c +4573848f39ea4bfceb55e0932f0494af8b890d1d - arm-trusted-firmware/plat/brcm/board/stingray/driver/sr_usb.h +7cc68c731d1d4e967a6b258c94afef74800e2c27 - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb.c +483849480279e54ca28e4177fea05d6bd3cd36d7 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ihost_pll_config.c +1071f5589a11aaf7354868d034e149b27d48adc6 - arm-trusted-firmware/plat/brcm/board/stingray/driver/swreg.c +13bbb4dc261e840997a59d4e914f071835d33fab - arm-trusted-firmware/plat/brcm/board/stingray/driver/usb_phy.c +eed068af90592502021f8e15b556ae302cd8db87 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ddr/soc/include/board_family.h +d0dacd8fc79f78cee10bd8513550abf93624afe2 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.c +46e832c20411ea4d2bcbcf1cc8968149375047f4 - arm-trusted-firmware/plat/brcm/board/stingray/driver/ext_sram_init/ext_sram_init.h +76dbcdb10f12f01d94b3c70d2f8562b0cc8b233a - arm-trusted-firmware/plat/brcm/board/stingray/include/paxb.h +a6bea74c09e847241ba6a156aff89b12670cc98b - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_cmd.h +2c4acf78dfd7c25c281471b6717273ff7920fea8 - arm-trusted-firmware/plat/brcm/board/stingray/include/ncsi.h +4bc4735b9e7c2a5eab8ae91a28d110dd24a42d75 - arm-trusted-firmware/plat/brcm/board/stingray/include/sdio.h +eeabf0e8e4cda99b503b2ea41298aff2d87e1278 - arm-trusted-firmware/plat/brcm/board/stingray/include/ddr_init.h +cc26d153c04427651e12bf00d19497e5bd8cb7a3 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_usb.h +1dea9a2af71a56fe60929b854a2c73220603d2be - arm-trusted-firmware/plat/brcm/board/stingray/include/timer_sync.h +10104d7d5d9eeeb545dea9ac306deb2c5cf46036 - arm-trusted-firmware/plat/brcm/board/stingray/include/plat_macros.S +b0a1c672d4d7095f6e7ec5305e084cb3a29a790e - arm-trusted-firmware/plat/brcm/board/stingray/include/bl33_info.h +bd25c5d9d7605649bc1d1dee9a734ccb130101c3 - arm-trusted-firmware/plat/brcm/board/stingray/include/fsx.h +8c57e437d9f4b2b49f005f899624af9b47121102 - arm-trusted-firmware/plat/brcm/board/stingray/include/crmu_def.h +90c98d478915f89433c419b06613a52965aeeef6 - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_utils.h +2817bede11ad2da4d5612a155f5a76e30b62de62 - arm-trusted-firmware/plat/brcm/board/stingray/include/paxc.h +bbaec5f331d8cf8f24898a8d172190c5f7940b6a - arm-trusted-firmware/plat/brcm/board/stingray/include/ihost_pm.h +491a5116f054df365b530dc8b09613f1178c2d8a - arm-trusted-firmware/plat/brcm/board/stingray/include/sr_def.h +e7629876236e444ee69e40c96440f3f24b16fefe - arm-trusted-firmware/plat/brcm/board/stingray/include/usb_phy.h +0ef862af40a95d70feda6b8367e6e7452e90099b - arm-trusted-firmware/plat/brcm/board/stingray/include/board_info.h +2ef5c016a1130291e30fb58c1e1b397bb15a531c - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_sotp.h +d823df9c59408673229302e557a65ad1c404e047 - arm-trusted-firmware/plat/brcm/board/stingray/include/platform_def.h +9765542d155d4fc37ee167eda672c6a33030ca8c - arm-trusted-firmware/plat/brcm/board/stingray/include/iommu.h +0228e24fbe8ff775ac7a709f272d375a8e7aa3bf - arm-trusted-firmware/plat/brcm/board/stingray/include/scp_utils.h +1e67ee0873eb29816b418096b514d39c3aeb7d27 - arm-trusted-firmware/plat/brcm/board/stingray/include/swreg.h +77916c4c9e55da373b1b66dba19dfed0034cde48 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl31_setup.c +52a5e5247c12940390abe486ab490a1d8929feb4 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxb.c +863c6f32899af28cd9a60fb273bdc02a29100114 - arm-trusted-firmware/plat/brcm/board/stingray/src/sr_paxb_phy.c +0283858faf5651d4db16f0e4b8bcaadd40bcabe1 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_cmd.c +d746f7070f366ac250b3766606d2de76a6192436 - arm-trusted-firmware/plat/brcm/board/stingray/src/fsx.c +e9f5650def0bf0c03c50ad69056cf6ff9d71a715 - arm-trusted-firmware/plat/brcm/board/stingray/src/tz_sec.c +d15b82eea2aaa023805036e829ee46cd08ea72ed - arm-trusted-firmware/plat/brcm/board/stingray/src/iommu.c +f89deabe82fe9129f1dde3fb24e57c940e008913 - arm-trusted-firmware/plat/brcm/board/stingray/src/bl2_setup.c +085cb8e4f6dd01efc01f633680e7db315718c304 - arm-trusted-firmware/plat/brcm/board/stingray/src/ihost_pm.c +072e5bc5c72a860c50c3413898b60dd18931b100 - arm-trusted-firmware/plat/brcm/board/stingray/src/ncsi.c +c01d8b9f9c48a1185129c492ab1f8ce1134ed892 - arm-trusted-firmware/plat/brcm/board/stingray/src/scp_utils.c +1fd2e7122a0c63a14a64215ae5750097f050841b - arm-trusted-firmware/plat/brcm/board/stingray/src/brcm_pm_ops.c +062b1d173f23bc015ebb5c790f890e5f2a6934e1 - arm-trusted-firmware/plat/brcm/board/stingray/src/paxc.c +78d2915d5c3a6c4b75eb97c897cd4e58b4d5b962 - arm-trusted-firmware/plat/brcm/board/stingray/src/topology.c +9b0afdae90ec3159bd428d4b9f586d84a0cb55b3 - arm-trusted-firmware/plat/brcm/board/stingray/src/sdio.c +75de08bf7cc548fc88463a459efa719ce9dae276 - arm-trusted-firmware/plat/brcm/board/stingray/src/pm.c +16002a1a28f7ec581aae95aba10964655f89c5dc - arm-trusted-firmware/plat/qemu/common/qemu_pm.c +c154631e1880ac14882cbb7ec28846bcac331126 - arm-trusted-firmware/plat/qemu/common/qemu_bl31_setup.c +95a9e39672a85b16243df6db511e352e068b90ee - arm-trusted-firmware/plat/qemu/common/qemu_bl1_setup.c +00fcc8b29bf97f9ede1c2dfbe40db7ef83c72695 - arm-trusted-firmware/plat/qemu/common/qemu_spmd_manifest.c +2085009221c46e8e62ac297e819084f4b6087615 - arm-trusted-firmware/plat/qemu/common/qemu_rotpk.S +8ebb840a06cb6dddf6c0fd5fe4a612f832842576 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_mem_params_desc.c +ec654aff1a7a4e282bbbe2dc13b2042b9534eb61 - arm-trusted-firmware/plat/qemu/common/qemu_gicv3.c +d78bd11a3e46b66140586c01d9f834a788316251 - arm-trusted-firmware/plat/qemu/common/qemu_gicv2.c +2154f29a91decb99dc45f21e790dd6e0d1da88e1 - arm-trusted-firmware/plat/qemu/common/qemu_private.h +ce499ea5552f0a580d2d730cd86b20a544fb4759 - arm-trusted-firmware/plat/qemu/common/qemu_console.c +fcbaa96813c363c3db4933b80039d532e1252dc7 - arm-trusted-firmware/plat/qemu/common/qemu_io_storage.c +51d8305f79f4736a224811e549fd92ffee6e2134 - arm-trusted-firmware/plat/qemu/common/qemu_spm.c +a58c658f18083c55761b946dd01b034df662dada - arm-trusted-firmware/plat/qemu/common/topology.c +854064daf74a72113baf3004985576f30ed85540 - arm-trusted-firmware/plat/qemu/common/qemu_image_load.c +3ca3d10548276087940fd7af8f274b1b68378322 - arm-trusted-firmware/plat/qemu/common/qemu_stack_protector.c +3a64a36aaab153d084cd63cb8041cb8e4554c206 - arm-trusted-firmware/plat/qemu/common/qemu_common.c +21efcb8ca3eeadb04af0ad8b5dbff0a548221482 - arm-trusted-firmware/plat/qemu/common/qemu_bl2_setup.c +b70358ad6ace724f6125a704a64bd882bb7e5e13 - arm-trusted-firmware/plat/qemu/common/qemu_trusted_boot.c +fe635c884df368ae689c259f9ac0787b17064bb4 - arm-trusted-firmware/plat/qemu/common/aarch64/plat_helpers.S +f58716f140fa8f450f8073fca6f98a8eda79bbc2 - arm-trusted-firmware/plat/qemu/common/include/plat_macros.S +674a4514924db14c06277e39651b46250347d7a4 - arm-trusted-firmware/plat/qemu/common/aarch32/plat_helpers.S +553cd30299445b034280689989176963a39f2b4d - arm-trusted-firmware/plat/qemu/common/sp_min/sp_min_setup.c +dc0cb18de3dee5963f78466b58e002bc816d526b - arm-trusted-firmware/plat/qemu/qemu/include/platform_def.h +f2efe87ffe7cd41bf5ac442c75b40fb2593a8fbb - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_topology.c +a3366d3ea9b4a5a823b365b0a4fe16dd24af7388 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_private.h +151cea63605746875bff4fceaa296485033aa280 - arm-trusted-firmware/plat/qemu/qemu_sbsa/sbsa_pm.c +46b611bd4d5b4370f104fdcc62cf5da040ec7970 - arm-trusted-firmware/plat/qemu/qemu_sbsa/include/platform_def.h +e4e4584414cea9a632b613da62b76c3999974c0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.h +006db753e22b1119a67d4f76bd213bf3de08be09 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_gicv3.c +30d16489f342eed522b276128737ad41acb82ba9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_helpers.S +69a2371870f65a855d9ff7c728f2e9c32882aa2c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl2_setup.c +21ef9559c64415fef54f3373f28fde4fa86d92d3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_topology.c +2b022afd58ed2221e8abc99099867eab0c42c326 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_emmc.c +d342acec84b75ea4f64204404f0a54b4158920e1 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_usb.c +26621302eaceca62d3b0e8224c6c14d5ea08df38 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_xlat_setup.c +5fa3e198d6ad7a764cb058e6e88fa12a0d8ffe85 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_nand.c +ab09cd5d8d3222857a607791bee8b31359314aa9 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_bl31_setup.c +91e3ef5fbfd42b725b57f2608d1934a5c717de3b - arm-trusted-firmware/plat/socionext/uniphier/uniphier_tbbr.c +516680ab29649a33ea07ffa922f3b18448e61e55 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_psci.c +05b8fac4f5d6b8cee9465b541e992f27f071fe8f - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console.S +7518b6009c736b543504a3f84be4cbd20e8d9f0c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_scp.c +eca523ec19dc113ddd19b9427a6651cd6ebe6bb3 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_soc_info.c +ad344a675d5f4bf3287a6e32451b462c3ea7d29c - arm-trusted-firmware/plat/socionext/uniphier/uniphier_rotpk.S +8a0a08bd7b9292bd5b334bc91ad422838eb83118 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_cci.c +7cb14fc4ccfe79fe8ffb080b91337e263775111d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_syscnt.c +d94b79f813abf374eef409d04968fce943a3ef84 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_boot_device.c +30db57b3d947cfae86d4cb1fbd7d79f7365fe01d - arm-trusted-firmware/plat/socionext/uniphier/uniphier_smp.S +dd16d7be9af0988718096ec4af552732207ad390 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_console_setup.c +98c1438c270db5db7bd6f971cb928420df53c1b7 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_image_desc.c +456820f5853d3f1676ee19bf63b9c360ed9a80a8 - arm-trusted-firmware/plat/socionext/uniphier/uniphier_io_storage.c +b445ddffd2167b6758d19874673ec99f3f2a1d30 - arm-trusted-firmware/plat/socionext/uniphier/uniphier.h +8bea3f2da202b83b97d9b86e32cb50d5c17cae7e - arm-trusted-firmware/plat/socionext/uniphier/include/plat_macros.S +e35ee40c042c15de97496be4f1d9c81b960cc3da - arm-trusted-firmware/plat/socionext/uniphier/include/platform_def.h +d181839ef722d36e8a51c126deb67a2eae64c527 - arm-trusted-firmware/plat/socionext/uniphier/tsp/uniphier_tsp_setup.c +72b5553a5bdc53509ecf17a4d93cbfa1e3d06c8c - arm-trusted-firmware/plat/socionext/synquacer/sq_helpers.S +f43a62ef3a99346a097b8813441539c5354436fc - arm-trusted-firmware/plat/socionext/synquacer/sq_ccn.c +9b1262ca8c6950227a294b789fb3e53dfa2086b1 - arm-trusted-firmware/plat/socionext/synquacer/sq_topology.c +8286dff95425dddb9a5b25ffda50460831781793 - arm-trusted-firmware/plat/socionext/synquacer/sq_xlat_setup.c +a32f17d7db01cfb7a14811a914ba2066581d29a1 - arm-trusted-firmware/plat/socionext/synquacer/sq_spm.c +3db81e971dc630ca534efcd02840b2ee0fc01794 - arm-trusted-firmware/plat/socionext/synquacer/sq_psci.c +f9ac11a5c154783dbbb6fbdf6485867b754f511e - arm-trusted-firmware/plat/socionext/synquacer/sq_bl31_setup.c +b60ee8850906f76ada82b2db19c8656ed9c12d9a - arm-trusted-firmware/plat/socionext/synquacer/sq_gicv3.c +e431465e90b8b68ce2922ff400c2e6953eaeea9d - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scmi.c +f57f50699d6a8f3902d4673f01ec3ff0d6931d29 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scp/sq_scp.c +f8fe95fbe1e35e8c328ec5a197b76c329feda4bd - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.h +b6784404cec981a185e6f44ef689f28b7d9513e3 - arm-trusted-firmware/plat/socionext/synquacer/drivers/scpi/sq_scpi.c +ebfc7926ca7e342e5cec3fed564e68be76a80fdd - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.h +961c660b9e7a5641523d5d23b5396c2a2a67746e - arm-trusted-firmware/plat/socionext/synquacer/drivers/mhu/sq_mhu.c +09ba9cfb7c8be52484c3cff427668fc7d2524219 - arm-trusted-firmware/plat/socionext/synquacer/include/sq_common.h +9f24e8fcbc08c61f43c8041c0464cae65fe01ce8 - arm-trusted-firmware/plat/socionext/synquacer/include/plat_macros.S +25666183a169e48e144659003b018f40881b4590 - arm-trusted-firmware/plat/socionext/synquacer/include/platform_def.h +ef74e9cda94f07bf3061b037195287d609c0c6b4 - arm-trusted-firmware/plat/socionext/synquacer/include/plat.ld.S +09dd0d32acc68693a9cc4e6edda975b30b997a7d - arm-trusted-firmware/plat/hisilicon/poplar/plat_pm.c +4df6d997a517a03b7120733e3ff6f1a2634caa47 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_setup.c +077745456537a78c6a462ecaf23835c3ac381a92 - arm-trusted-firmware/plat/hisilicon/poplar/bl2_plat_mem_params_desc.c +5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/poplar/poplar_image_load.c +43b6cb88b4528db3610c0591b417afee9f8e086f - arm-trusted-firmware/plat/hisilicon/poplar/plat_storage.c +942f440e430db3a0fb9bafcb2877fa0f2b2b2206 - arm-trusted-firmware/plat/hisilicon/poplar/plat_topology.c +166469bcfd5bac8ca50e33d23d40607d532f7a9f - arm-trusted-firmware/plat/hisilicon/poplar/bl1_plat_setup.c +706af98521027fbfb3cb50742e9203904186ccfb - arm-trusted-firmware/plat/hisilicon/poplar/poplar_gicv2.c +575e7801ee2435ca3d3bc588117235189cba8fa2 - arm-trusted-firmware/plat/hisilicon/poplar/bl31_plat_setup.c +5b726e62a784d7660009ac2235ebf2d76dc809ad - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/poplar_helpers.S +ef034cd3245b78dec24c714d8ffbb7e9b490427c - arm-trusted-firmware/plat/hisilicon/poplar/aarch64/platform_common.c +54bc2fcf8fb31777a2eee36c5b61246cc0fa0a17 - arm-trusted-firmware/plat/hisilicon/poplar/include/poplar_layout.h +2bc481728aac66acbe669f76aa6dd84c3f4e88a7 - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_private.h +7309b02ef23609fb839b029b295bffaf714cdc1a - arm-trusted-firmware/plat/hisilicon/poplar/include/plat_macros.S +e8d837174e3274ddbcd923af88d3e19e1af8c06a - arm-trusted-firmware/plat/hisilicon/poplar/include/platform_def.h +5333986fb9d6df5ca3e50aad616e8c1422eafdd2 - arm-trusted-firmware/plat/hisilicon/poplar/include/hi3798cv200.h +b8ddcea3e66690f3932ae009921566fe249feccd - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc_sram.S +1975a45f73616d0ceb03dab4a9397cbabc1e66ce - arm-trusted-firmware/plat/hisilicon/hikey/hisi_pwrc.c +0aace28e8f75168d13d7274d81f1f906cc1b2cae - arm-trusted-firmware/plat/hisilicon/hikey/hikey_rotpk.S +030496606ff67ba16f47be9282a04338261e38ea - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_mem_params_desc.c +126933334b9ebdde11859016f3bbcc6ac9bbef88 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_mcu.c +3f90b73f27ba47848db784621dd350e6a5ec54d9 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_tbbr.c +e90b7c0a59b785560e233605f2968b642d26fcdb - arm-trusted-firmware/plat/hisilicon/hikey/hisi_sip_svc.c +bca37120bec0db88310c0e711220bd8301c8b932 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_pm.c +1dc25162c504805b378176ceb2a1fac39b8fa3e2 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_ddr.c +b0603f49d7b1252e6774be83ed95232695f1f263 - arm-trusted-firmware/plat/hisilicon/hikey/hisi_ipc.c +e5479e33302a43e627013dbe10bbcca8ccdbf8b5 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl31_setup.c +33f9c2d61b7aa3242f22100ba2694ba2709f7a1b - arm-trusted-firmware/plat/hisilicon/hikey/hikey_topology.c +cfc7af573fbb40bb702a616d8f0bf02b017a3e0b - arm-trusted-firmware/plat/hisilicon/hikey/hisi_dvfs.c +5366b77beffc310cab412735a4e4f43185e171c6 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_image_load.c +132b89dc419b19bfabb3eb2450a5e74317faea11 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_io_storage.c +8b11d0569d254ee10c03b8e7dfaebf823b7b1746 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl_common.c +1b333e35df79afc9319c45ded87fe22b1e5547fc - arm-trusted-firmware/plat/hisilicon/hikey/hikey_security.c +0472150350a0f6a23e8750e0fe14991d176d1a04 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl1_setup.c +a68989337ee4c06cf76f89d69cfc5c3aca210b00 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_private.h +0071214b6af7f5e24aa92d4e7849c79c3818ed05 - arm-trusted-firmware/plat/hisilicon/hikey/hikey_bl2_setup.c +f3431f5300aefc0065b1e6ad9f3e996878027bff - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_common.c +f4fe9f99f519b213b8d23015c37b2e4013ebb066 - arm-trusted-firmware/plat/hisilicon/hikey/aarch64/hikey_helpers.S +fff863e589a15845fe768ee9bd16a482d5946db7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_ao.h +ee2004c34a377b43d61f3fde4201ea86e1834fc7 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_pwrc.h +31f012031e8dec3fe5dab7afc9ab89deffb7fe7c - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pmctrl.h +79f261b3e512eb92ef04e1b172276ba95108b6ac - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_ipc.h +659dfae8f25d18bef4e2ac3c9b2cc07bbd255dd4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_acpu.h +98509207554ab836b38f580d203793668061ce40 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sip_svc.h +5da379773f07f291d897ea36a13ac008c78bbbe4 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_pin.h +4619ff482dfa91c976c3d58153ac694dd92a0abf - arm-trusted-firmware/plat/hisilicon/hikey/include/plat_macros.S +e0f40190a4d2a13086e9b7c951d5301f744dd767 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220.h +42137e1b1e1f31a2b92b351765982cc8bcf28601 - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6220_regs_peri.h +b9c87b1b0f989e816c65163d00ead7cd68b4b6bc - arm-trusted-firmware/plat/hisilicon/hikey/include/hi6553.h +e2fd2bbe14a506ac8ab6eb8f4c65dd34827b33a8 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_def.h +379cc0fd2c6486a2bfc850d19190835961783f16 - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_sram_map.h +eb1ee8f26e0a9e1d174893e2a80e0ea2be070df3 - arm-trusted-firmware/plat/hisilicon/hikey/include/platform_def.h +c54b714045ab12cfcff4363f00ce94952a40e2d6 - arm-trusted-firmware/plat/hisilicon/hikey/include/hikey_layout.h +95b6af34fbda29b2cef5ecaa3ecf9deb1f7a48cb - arm-trusted-firmware/plat/hisilicon/hikey/include/hisi_mcu.h +39568f02d9e541a653aaa3d8503e9976203e27b5 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_setup.c +0cd271eb1db1372ebacbc89a1ab7e6b858522177 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_topology.c +19471da73d6d6e0316b89091e8034b65252676ea - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl1_setup.c +e7130fd49b764ab203b1f70d8c04929b17c338a1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_tbbr.c +df960717d8f3e8b3111b85c464d02214767ffe67 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_rotpk.S +9921f6f68c3b333297fb84f0c74626e02e31182e - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl2_mem_params_desc.c +3b43870e172a97e6682dc9e7adeb7ee54b219ce1 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_mcu_load.c +b4ec4794171dff334edac55b287dbba42365301a - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl_common.c +6c598ab11230d9af7684a342f64de0ef3aafd2e7 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_bl31_setup.c +92c35daf2b450ff28a8d64da226b020489472149 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_def.h +e521b7127c97a6dc50d62a6fb23613467dfa5c91 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_boardid.c +a012da0cb3423fd96bd536ca33852c8fba58ac2d - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_private.h +755c811030252ea484722f83c6773b03bcd1aecf - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_image_load.c +e5d1ee45233d19ae915b7dcde9d177ac30ff3c59 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_pm.c +1178b52937b1f59d49a4b24807fedf6800893f18 - arm-trusted-firmware/plat/hisilicon/hikey960/hikey960_io_storage.c +33e4f92c8882961c556666d4e463a0cd932589bb - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_helpers.S +00786f6204973e7255b3183326d7e2fb8a54f0a2 - arm-trusted-firmware/plat/hisilicon/hikey960/aarch64/hikey960_common.c +168bc920b2828c8478a977c1e6b9e597791c0e45 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.c +4a0475ff7dac46ea547e623a9a83071f69b5a4b7 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/pwrc/hisi_pwrc.h +4abee183dc860ea0fe600bb9b19e3c4a0a3d6773 - arm-trusted-firmware/plat/hisilicon/hikey960/drivers/ipc/hisi_ipc.c +9b6172a308464c71e87f1f420cb1df10ceb7bfb4 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hisi_ipc.h +201bc8884be1cfb9b4f87f3fcc6ccf3aeec268d8 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_hkadc.h +390e28e24c8915a9f956b1a1de0cafa7306bf9ed - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660.h +930c77f84c5ef2c7971e52015e58fd9c314fbba5 - arm-trusted-firmware/plat/hisilicon/hikey960/include/plat_macros.S +ce594eaab37f132b152875858c98ea6a8cf2f005 - arm-trusted-firmware/plat/hisilicon/hikey960/include/platform_def.h +d8da79f1ebd9b100b4d3dc915552f3d086d5eda9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_mem_map.h +b1be891afebf5d255da6f6dcb865725241f566b9 - arm-trusted-firmware/plat/hisilicon/hikey960/include/hi3660_crg.h +8274c219bcba2090fe7e6e628abe65c7c3780d33 - arm-trusted-firmware/plat/mediatek/mt8183/plat_pm.c +3cb5ee19a3d0915879c602a240e4affb4a0d7c94 - arm-trusted-firmware/plat/mediatek/mt8183/plat_debug.c +03b9e95dd87fe5cdd436743fb8f5f59d4b2f2de3 - arm-trusted-firmware/plat/mediatek/mt8183/plat_topology.c +2f1976dda894f28a35f0cc50623e070a354d044c - arm-trusted-firmware/plat/mediatek/mt8183/scu.c +e9bb8f5dfe42b8cfdd770db2301155ad00d93617 - arm-trusted-firmware/plat/mediatek/mt8183/plat_mt_gic.c +7a7fbf6ac91e6e9ff86ac7350e8de64f834b5997 - arm-trusted-firmware/plat/mediatek/mt8183/plat_dcm.c +9065f62c97422538ddfd15c89806f2869ffb98c5 - arm-trusted-firmware/plat/mediatek/mt8183/bl31_plat_setup.c +c7ae3ce6e37f4d27b8733d9c3b1bafa8add40a8b - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/platform_common.c +c5295d987eeadbc7fa82ddedb5266f20e7dd3cec - arm-trusted-firmware/plat/mediatek/mt8183/aarch64/plat_helpers.S +214f922545d6899c3e5621df156f1712ebb3c009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic_wrap_init.h +ddd6d454dc5e0a1dead801b5cb856c7f27a8065e - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.h +1d535ab7f8d2fb5131a0ce0e6a7b11c4a188a009 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/pmic/pmic.c +51b89484342a85c2ee1e944fbbfc08a8bc663f63 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.h +4ab8cc9c4d3ff197639f9b78f7b860ebb8879967 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcsi/mcsi.c +edd71b3e0aaea146cfadebca131cd7e6ee13d303 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.h +888e5c6480da8cc9f0dd6d5febc12f7d0a8a16fd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/rtc/rtc.c +264db153102d726c6a9455244b40d552d0960af2 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.h +ed39e8ba2090c26070e12def3287c0ff46721987 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/devapc/devapc.c +316277d91acd7098ec6ac153e95c932aca46d3c5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.h +2e1849b9de23cbd064f9e90e4c83cd761e284e18 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc.c +96ac9c853839aff7b9c19b8ce2bdd09ffee2c87d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spmc/mtspmc_private.h +1f21078b5dce77d5939c39ae046fcf15cf1bcc4d - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.h +23040542c3bf819fe42a45ea51427b1a39edfab5 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/timer/mt_timer.c +0bae9ef296eeb3bf9ed2342aa58b2d505dc8f04f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.h +7ac4fd4d1072962002d4b4a7439a7fc6fea85b48 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/mcdi/mtk_mcdi.c +b26d910796c32c24b2519666922a9991a16d3562 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.c +fe16bd5deb42a8c0e902c3a7547e11d7d5afa0bd - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.c +8156e8c4b7f219c9590cfcb2338d845c2b0c71b6 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_pmic_wrap.h +fdbc0bcded1a96ceeb994c74a3a48eec3af06df3 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.c +e92a0c648e09b96cd906a5e008c418d7d61fd577 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm.h +f1a812bc872a1ac1c695c5485fba1a135307986c - arm-trusted-firmware/plat/mediatek/mt8183/drivers/spm/spm_suspend.h +645f76b92e2714b452ae24edcd6a40cfa879ea61 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.h +fb3c91bb75b7fe6fff5323ead8dc73efc07f1289 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/sspm/sspm.c +346960934a0779649e0412ae87abde963086ff8a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.c +3a86fc89605145b3faa5aa385e8f7a11851b424a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio.h +94b038f0c7b76069f4f85185a375d4d2aa61a74f - arm-trusted-firmware/plat/mediatek/mt8183/drivers/gpio/mtgpio_cfg.h +62325eff3c956aa9ca90b298e958e8ed5941a8a4 - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.c +88c148094b3fac4149258b8fe4786fe4ac3f8f3a - arm-trusted-firmware/plat/mediatek/mt8183/drivers/emi_mpu/emi_mpu.h +a52a6337e1e29bc64b0d301f31d88c42981a1105 - arm-trusted-firmware/plat/mediatek/mt8183/include/sspm_reg.h +01e8de6953d79923463ea639e7d8e218ecdbc8e6 - arm-trusted-firmware/plat/mediatek/mt8183/include/power_tracer.h +a4d241e1fe6a38acfd38a895dc29d0d3762c185f - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_private.h +f7b9354cce893182c4203079dc774a9b048d05d7 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_macros.S +97a99a4b4542d549efbe9122362e0ee8fcac89fa - arm-trusted-firmware/plat/mediatek/mt8183/include/mt_gic_v3.h +16b7a7f8d62f9bc9d06c01d5e72b2ef5653e7455 - arm-trusted-firmware/plat/mediatek/mt8183/include/mcucfg.h +447f690a22efc00539cd931fc1d9aba592997a19 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_dcm.h +387e06d0f2e4f36818ebd660cd1c4d429222a6fa - arm-trusted-firmware/plat/mediatek/mt8183/include/platform_def.h +9ff5bdd1f6610dc5e442304399c97ab95361e3a3 - arm-trusted-firmware/plat/mediatek/mt8183/include/scu.h +58b0e33d4a7460c72049a50f5cb8e8af5a5260d9 - arm-trusted-firmware/plat/mediatek/mt8183/include/plat_debug.h +9d567134def757007ff0196e1a84e96ff6772d7b - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.h +4f1e69980b6fa0691ac24f320f777fa5f690c987 - arm-trusted-firmware/plat/mediatek/common/params_setup.c +4fc10ec9bb95247b13ba3d9b9edeafbb42ba4037 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.c +ffdbbcc522937a13b7f658754005673d0257f6dc - arm-trusted-firmware/plat/mediatek/common/mtk_sip_svc.c +311eaf7d7a3b040aee08231328317674a1db9975 - arm-trusted-firmware/plat/mediatek/common/mtk_cirq.h +7858c40d5378047a8869189376fb70d934ed6f9b - arm-trusted-firmware/plat/mediatek/common/plat_params.h +91005aeae3d9de06561b65ab2fcbec18472bcdd3 - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.h +561bde7d3dcce4eb570c0798866c49ac31db4cec - arm-trusted-firmware/plat/mediatek/common/mtk_plat_common.c +c272dea0838b85718c51563a46b3274a684e1b83 - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.c +32e5d4c9af02cbaf4603a45ee6ecc742ae4e1a0c - arm-trusted-firmware/plat/mediatek/common/lpm/mt_lp_rm.h +eca4fbb32aaba0013f15b702c44892eef43998c1 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.c +47b4f5bd98692841b45386f4ac1971904a86e5ef - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_mt6359p.h +126307a49e31392042c3224d14fd15ba85a79b43 - arm-trusted-firmware/plat/mediatek/common/drivers/rtc/rtc_common.c +a439bfc1e0a18de64b665a1f9f1612c6c723b298 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init.c +a183db6162649664bca3e1e3a7650f0c641ce3d0 - arm-trusted-firmware/plat/mediatek/common/drivers/pmic_wrap/pmic_wrap_init_v2.c +ea57c5163cb9ad847760738ed46363d3b3e03dd0 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.c +c78b2291f89f3cb41916e636890a3b8263cb6250 - arm-trusted-firmware/plat/mediatek/common/drivers/gic600/mt_gic_v3.h +7370797acadbb4e47f7b8f407834dbb4c932cc16 - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.h +8cd2ff88ff29bd0f9f3b205a057f4c9bd9601adf - arm-trusted-firmware/plat/mediatek/common/drivers/timer/mt_timer.c +bcc701f742bbbd6ccfbbc58e60fc17bd7ea2743d - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.h +db4a5136746026996b722adcae43bef2530ca8bf - arm-trusted-firmware/plat/mediatek/common/drivers/uart/8250_console.S +72586b214f5212b1d0cb120063c07e8eca22b38a - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart.c +13f55b9e347d50eacc00a183d743c28419be6dea - arm-trusted-firmware/plat/mediatek/common/drivers/uart/uart8250.h +990b19477486a12883414d383890f2bebcebbd2a - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.c +7203181ede278ce1fd73cf8b9f9204b6cd508282 - arm-trusted-firmware/plat/mediatek/common/drivers/gpio/mtgpio_common.h +37f3112de6efd829353735288a329458891db6f4 - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.h +dbff628762b596a369e7a96908226677ec6143ce - arm-trusted-firmware/plat/mediatek/common/custom/oem_svc.c +cdd4db5d5ea83958ff89700a430e1c54729bbe76 - arm-trusted-firmware/plat/mediatek/mt6795/plat_pm.c +2e61bf89860dc6368d6608e4d8447e685d7d88ce - arm-trusted-firmware/plat/mediatek/mt6795/plat_topology.c +975fa62263fb56cfc6d4832599aa8a421fbef3ea - arm-trusted-firmware/plat/mediatek/mt6795/scu.c +9a2cc2f4d94dcff8028cd56e4bcd01da0dbd4a6e - arm-trusted-firmware/plat/mediatek/mt6795/plat_mt_gic.c +f42fa6a617844b8c56879c8b1f3c34ae4b77aa8d - arm-trusted-firmware/plat/mediatek/mt6795/bl31_plat_setup.c +e957b0cc082fc56d3b25fafcedf71e23b8fffcdb - arm-trusted-firmware/plat/mediatek/mt6795/plat_delay_timer.c +41b33f806ea4e94c4dc6f91cf13b8fe2dd08272b - arm-trusted-firmware/plat/mediatek/mt6795/bl31.ld.S +c9da62c4ac9c51366c26ca27dccdc85fb8840e6e - arm-trusted-firmware/plat/mediatek/mt6795/power_tracer.c +5c5ff1370ff35d42d3c4d77b913247276a4bde02 - arm-trusted-firmware/plat/mediatek/mt6795/aarch64/plat_helpers.S +affbb4d9599159566bd93871905eb54cfd7075d7 - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.h +b9ba707119860e36bdab2e1517f34832022480ec - arm-trusted-firmware/plat/mediatek/mt6795/drivers/timer/mt_cpuxgpt.c +524f765609b42d6239efa9fbe9d123e031c011b2 - arm-trusted-firmware/plat/mediatek/mt6795/include/power_tracer.h +817e6a410e02d0889f5f69f3da13113cfb9648b7 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_private.h +46009c0467b0d5f5a2b78837653ac6c1d8154100 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_macros.S +f2440de976c6c344fcd2cb08353d0bbcf16d8e98 - arm-trusted-firmware/plat/mediatek/mt6795/include/plat_sip_calls.h +9f36f3e719ea61b6f45d4f3e36e813e42cdac8e6 - arm-trusted-firmware/plat/mediatek/mt6795/include/mcucfg.h +948df1ebf0176a6b28197dd1f5a96ef7b3407200 - arm-trusted-firmware/plat/mediatek/mt6795/include/platform_def.h +dd9bcb0a34eb0f2806dd3d2764341217a12fca53 - arm-trusted-firmware/plat/mediatek/mt6795/include/scu.h +c585fe19743e984a106c899e16d61ef97416376c - arm-trusted-firmware/plat/mediatek/mt6795/include/spm.h +e90649554240f75d20e82bcaf1d5fc7f72308d84 - arm-trusted-firmware/plat/mediatek/mt8173/plat_pm.c +abe0c66165b32a2f3dee830062f153c3c29738ce - arm-trusted-firmware/plat/mediatek/mt8173/plat_sip_calls.c +322049a08a3981e4c34fb6991314537e02662946 - arm-trusted-firmware/plat/mediatek/mt8173/plat_topology.c +9b148285683f9f62babcdd92b4cbb3edf8d47275 - arm-trusted-firmware/plat/mediatek/mt8173/scu.c +6a2d3a421c077dcc608a94317ecf55a80c640d76 - arm-trusted-firmware/plat/mediatek/mt8173/plat_mt_gic.c +b49fda8c23d477e92d842bb950e93962c77a82cd - arm-trusted-firmware/plat/mediatek/mt8173/bl31_plat_setup.c +5b0d461df0d4936d87d5a3b87846da17b5bffdcd - arm-trusted-firmware/plat/mediatek/mt8173/power_tracer.c +314689d0bbe7b2567ccd667c6f70815679729e1f - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/platform_common.c +fefea9a047dc27fa97fc660c62bc2a4b68539b35 - arm-trusted-firmware/plat/mediatek/mt8173/aarch64/plat_helpers.S +27cbf1f064da3e18b5cd7c0e83fb1c9da349e00e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/pmic/pmic_wrap_init.h +42adaa32fd22643561c090086db64c635fd6d686 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.h +b7e2ebfeb39fa655c846358a6439c708fba4b6d5 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/rtc/rtc.c +0f16bd582feb0391ddd3b4685fab51a7e11667ca - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.c +4535129d635202f3bf1b447e411bd1c7eda5f7db - arm-trusted-firmware/plat/mediatek/mt8173/drivers/crypt/crypt.h +bb6c45f6edb308171b205123bd682e3db84ec58f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.h +d86950fce5e4e2f48f1efc48472289033367e47e - arm-trusted-firmware/plat/mediatek/mt8173/drivers/timer/mt_cpuxgpt.c +9e687cd54be9aa08265355e1079ba5f6cd2a93cc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.h +4af6a675f41b6d5566fcc13863c1507f5fe28f7f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/mtcmos/mtcmos.c +4398c8e27acb0bc2b28771ed5c1a0689971fac4f - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.c +f6fe2ef42009b0fa69b3957d63488b6192072275 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.h +d73f4f2080ec7098103c5209a4c302f80535dc77 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_hotplug.c +b18c4af2e0471a0d5de267ac5c1e4a52b1c94ea6 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.c +f3ba2dabf2cabb2644ae09476c62fee2023d6abc - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.c +8ffb063b98ca22c66f9f96260216a31b1de20519 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_mcdi.h +0f38df7cc1b225ffb568e7df5c4981b0d29ee7ae - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm.h +9623b67d4f2dfac8dcc78ed711172fcb5f85511d - arm-trusted-firmware/plat/mediatek/mt8173/drivers/spm/spm_suspend.h +3160163c493937b3bb0298d50d918627d0d0e4e4 - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.h +27287e7e69b6a6be66a87cf9e294f25a682e92fe - arm-trusted-firmware/plat/mediatek/mt8173/drivers/wdt/wdt.c +fb0128ee719cdbc40fa546319e2635e3e19f1e11 - arm-trusted-firmware/plat/mediatek/mt8173/include/power_tracer.h +3d43facf8bc958241dcaddfa4cd6f9e61362c87e - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_private.h +95875d234df9d7f7a86bfda389367f298611eb38 - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_macros.S +755906af584459bc7964059a3022e624d4743b62 - arm-trusted-firmware/plat/mediatek/mt8173/include/mt8173_def.h +12c0bb5878f5671aeb4bc9ea733ddd80cdb960da - arm-trusted-firmware/plat/mediatek/mt8173/include/plat_sip_calls.h +7848197b715dc7fd355b6bc2d2232123facb9994 - arm-trusted-firmware/plat/mediatek/mt8173/include/mcucfg.h +2bd6a37616bcda8ee48aa9917c65801ceeea804e - arm-trusted-firmware/plat/mediatek/mt8173/include/platform_def.h +89bb4015a4309bd60ed5dc2f32033dd0a4f603cc - arm-trusted-firmware/plat/mediatek/mt8173/include/scu.h +6bf419a65264c179e6faecb78b2c7f31faccfa6d - arm-trusted-firmware/plat/mediatek/mt8195/plat_pm.c +94708cfb8fd54fdc9e58c01699e1e9e8c26341e5 - arm-trusted-firmware/plat/mediatek/mt8195/plat_sip_calls.c +02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8195/plat_topology.c +f6cbc785839b2fde5bb8c3d87190641b45997d2b - arm-trusted-firmware/plat/mediatek/mt8195/bl31_plat_setup.c +343bb93fce6c58d4c3497e7f662303320ea1ac83 - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/platform_common.c +1e5bead24560b23256aa9e306e5a4ece724bd6af - arm-trusted-firmware/plat/mediatek/mt8195/aarch64/plat_helpers.S +79002203788efcbfc1db666914278df3cae585a4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic_wrap_init.h +71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.h +b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/pmic/pmic.c +c925ae2549008a58fda62b34de221dd620c70d96 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.c +5785dfb24000631b8d3ec2c8363f0de46908d763 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupll.c +dace58b25824fbc880b58670389d47358981547f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/mtk_apusys.h +e37292ff38e07fc925308e8d725c49e48fa0a085 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl_def.h +fb86370251784e4a48a2bfe74baf2d7c56f3701b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.h +98090ad034ce904969ba1583467f8e5ef565d2d8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/apusys/apupwr_clkctl.c +17199f9bb411ca8735cf2bc4b22e8baa7bc2d152 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.c +4168e0d14bbe98c0b575d2e572fdb4b73586f8c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dfd/plat_dfd.h +d83f926ab5ef0f16323281a34f12b358f3af50be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.h +b6ba63645f7269f8d27b087a36b742340630864b - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.c +b1174b8477d0e126d9a35147161079391bf09ab0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm.h +79890abe09ae9210d94ce3c0f27c8e1d61ed6fae - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dcm/mtk_dcm_utils.c +e1b4cce4c465228019f6128073e4634dce0d2986 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.h +cb6cde28e9dcb269b456216c0e1b8d55c8ea996f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc.c +f70563982bec81cd15b17e693da41e7d1f469c6d - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spmc/mtspmc_private.h +31705f56afab7b0bfb866eaec7cd621c05f6004e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_common.h +1616d5f796bb92042ec501e01ff39403df39936e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/ptp3/mtk_ptp3_main.c +f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.h +670e89ed3e54a8fcab5f9bdc69b0710229d556a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.h +c4e2a5509c4bbef64807d58ddfea984f66031f26 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm.c +368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_cpu_pm_cpc.c +73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.h +77b795f3ba595013340ed1473935df13b18992f0 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_mcdi.c +3940dbadf2f6737dbe71207e2be2245fc24a2cf8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/mcdi/mt_lp_irqremain.c +79676f45e5439628bef50912dcfdb60c2ab34e8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.c +9aafb1c8544431a32f3d664beca24b47d9489f1f - arm-trusted-firmware/plat/mediatek/mt8195/drivers/dp/mt_dp.h +b24e7e4ca2cd9b25fdbad93fed94631f347b78f8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.c +1c5969bf63da110696877497bf7bb035238af2c3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_resource_req.h +33b92edafecacba8aed5f6b12c0b051740d4aa8e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.c +445db7752ab6359cd4ddfebded67f1dc59603220 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/pcm_def.h +f438fe8befd240fc23c7cc48c7e77e1e1a3cc0c8 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.c +c5542e49f5d3326418606d161d9490c9dc3c7bcf - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_reg.h +6ef0f4493d19b357c77df1b5cd49696a5263d102 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.c +28a7ecc5d35653b1b3e42ad19c1d1526f8b4ba13 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.c +416b58dbb44fb50ec9cbdda2b4af6cc04bd48d20 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm.h +a2ab35d6915d2ac73d85c1068d973a0d3514da41 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.h +d655b93e0b18efc8d5ac80ceae4a282c70d79c8a - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_cond.h +3e3b62df98d3d83eb2016c9d8dd1f67a641e95e4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_conservation.h +c997c26d9a441b3b550fa191f122a33d669d38b4 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.c +618680bf1155ee1bdf7f67df15cfeefeded70e66 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_pmic_wrap.h +0a4ed6a9c901c1bc5b75371aa26917fe6d9b243e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_vcorefs.h +c13822b4c2268325ef4398fbd0d28eacdfb59602 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.c +1e9fb5aa9c1bd6bfedf0be53b9f529290a141a9e - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_internal.h +709be723f3bb2b8be34dabc19ffec007a928b060 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/sleep_def.h +1209a457ffc9d4ceeebf3f3e24300146fecbd276 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_constraint.h +2516c5016c27a7706bfb86cea698a6741d845eef - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_suspend.c +d21496a22308580c07df11ebe7adf41f274bfd59 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/mt_spm_idle.h +73de5db2e94313670371f83a648fe95de097e7f7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_intc.h +85497a05edddd868fbe7322a3621d2b7c88c9814 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_sspm_notifier.c +e3e6596065738a8b19bfde088f92c7a4bf51b851 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/notifier/mt_spm_notifier.h +a3456911635f8af4f989688a8a1ae80de5256fb3 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_syspll.c +c24f82eb4ee80d7945922eac27dac514db2a49ac - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_dram.c +98f55522313c18575ac3b999f71ef98dd128d004 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_internal.h +6b5af500b6156d7283e6f315ae2fd1c33e95eeab - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_bus26m.c +872b3910dfca5bff8749f70e72fba760cf6289c7 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +49758ae69918fd8c1b52c54bc298f1f3e80fe1b9 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.c +cd5607156fa9256dbf860561db48d3e74c800295 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/gpio/mtgpio.h +1a8e74d1db7ceb847a8217c94620d6a73c28e8ba - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.c +35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8195/drivers/emi_mpu/emi_mpu.h +d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_private.h +1244ea062e485744ad8d59bf66ba3a455bec7f13 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_mtk_lpm.h +4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_macros.S +97ba7557af145fe931feafea204357431b957299 - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_sip_calls.h +5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8195/include/rtc.h +af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8195/include/mcucfg.h +cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_pm.h +de6346b18cb5bf3c6727a99f6cc0d9a62be9f071 - arm-trusted-firmware/plat/mediatek/mt8195/include/platform_def.h +9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8195/include/plat_helpers.h +e1863524c093ea2e6d043b9f6c7dc1e219f08467 - arm-trusted-firmware/plat/mediatek/mt8192/plat_pm.c +0aaf3b723ed86200d3e2c0e83641074ae213c44c - arm-trusted-firmware/plat/mediatek/mt8192/plat_sip_calls.c +653b82370d0b1ad6cebef8b6d7072051e934caa0 - arm-trusted-firmware/plat/mediatek/mt8192/plat_topology.c +5d84153e66efa37728948b5b1fe281913f5ea657 - arm-trusted-firmware/plat/mediatek/mt8192/bl31_plat_setup.c +5c6677206ac7ea4573dbb96868e106a55445d4f9 - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/platform_common.c +4a2ec93e8013a56c39ca18d0e283fc9cccb43b1c - arm-trusted-firmware/plat/mediatek/mt8192/aarch64/plat_helpers.S +9d5ed44c58a8c942270d1e8cd54ff65f463b2336 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic_wrap_init.h +71ca46ab2b7ecd281fc67a339d97f4e58be53669 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.h +b4f867a53f8b97e3d04d472c2edbbcadc2c85240 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/pmic/pmic.c +1b68266c3c155960dc03cba027a4d430c74473bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.c +cb930a7db51e4c8871ab7fcfa242466c2a8b36df - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.h +f7c1784f7532b244fe2bbca846d710d03061bed6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc_def.h +45377afc42584fa85f873fca2cd0e157c1a16b37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys.h +f5cfe3883759a648f72458b1bd84bf01d3bb1657 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/apusys/mtk_apusys_apc.c +9b42c233c5ba1e6b8a384b28424da455c27a53a6 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.c +89fce0253e363a84cec3e3957ac8d951a80ebe74 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dfd/plat_dfd.h +31d2ee83370c6c53704ab1a6ef9b905297491333 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.h +f1eb5fa4f4de22b769d0667ea9bea00613216cf9 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/devapc/devapc.c +6710f6e1dfa15b331f9d813a5003b5198af81c04 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.h +0652a5c416f4dd969f772d9774e55501993af032 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.c +a84fa1ee247e2005166d9018df2bcc75e63deaab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm.h +51222b809151abb01db2556abfba262c93f7f0e1 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/dcm/mtk_dcm_utils.c +b434a3c4454f2c705b0f3b7c565d85e147e7a7dc - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.h +cc63207972ae473d6a68bc41f3aa23093730183f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc.c +d42c9ba8c699033bed7f64376149e25aaf0ba27b - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spmc/mtspmc_private.h +2dd99ac3ceb6063e89c9c016bf2e965abd2636c0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_common.h +30341bebf59f92502ed0e0f772ffd6ff3f4691aa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/ptp3/mtk_ptp3_main.c +f8540b0d0f9d75dd733f6683d68945b2408cb0be - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.h +6158a4631af76550355215276ddfb61772f11c91 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.h +c42e69a4b160aed3d646987f867de63fd6542f09 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm.c +368d6d264c555843d3708e20700f8851e215df63 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_cpu_pm_cpc.c +73a75da66496e41636460ff121095c03a41ba9a7 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.h +965dec0900511bac7618f812c33f95620e3b1068 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_mcdi.c +0d3626281b65260b4b2e49cac33cf6bece32999f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/mcdi/mt_lp_irqremain.c +9fc0480b22dccdbb2dad940666ba124a785ed285 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.c +6c9c6446695fbbb9ef086f4f783aae57f24ff6af - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_resource_req.h +b2f984f7c8707ce9470fc25ae8af0f7a041f1602 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.c +26edcaa081665198f705a5d6e4a606c0b4e00689 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/pcm_def.h +4b3e251e2f0c0e4796105e6d25927067e14a2a6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.c +aa2819aa55d76d63f05809805f6ebf6f84fb8f71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_reg.h +9858935fcdc71e5145d69b0d6b65410dfc4c6dd0 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.c +bb750dd896f8785a87ba62867b0e862dbb4199c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.c +dd32e9eb6d0e8f5083df2bf5abfe28fcaf6f2c5c - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm.h +0f8fcf83ec923d192f61376370dd90635259a378 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.h +e3a261adfa46ae2657a455b7d25b7af56bb62a37 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_cond.h +1f598d0b85f3b211c05adb41726664e4a2bbddc5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_conservation.h +1637cf9d86b35aef31283240a30095022c0476cf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.c +c7e5e4cde0a05fa756e3fc6cd32654be3343cecb - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_pmic_wrap.h +e5e46ff7c9820b84c61e6bf2afdad854e42c6985 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_vcorefs.h +9bd59c04a5dabacf5a9ce010eefebd393e814115 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.c +905a72478cd919c732be2d3f3c066d27f34b489e - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_internal.h +9479c40f7955d1b8da21fece7877b3f970886a62 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/sleep_def.h +a65ccd601ba3861f13ec19d1ec6cc79d4295961d - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_constraint.h +ab677ba0b11817e784f6008456b3501b7438cfbf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_suspend.c +ec2b85d104ef0ad52faf88881e864e93c37e0ffa - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/mt_spm_idle.h +d2d41012d692a8857c6f842bcf2eb065142a90c2 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_intc.h +ca56b6a499c7e44f09c1f020859f9e7d51b014a3 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_sspm_notifier.c +067d8c516f8ce37edb7c8228d9d7fc4ba15ad7ed - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/notifier/mt_spm_notifier.h +1e038ef0b716c1ba013366f2d656026ff4bacd71 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_syspll.c +345b11fdc0c85e312ed8e6a8643339d691fadf6f - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_dram.c +b656247e4733dfab4d7db4f7361cd1b15a0c14bf - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_internal.h +8a1fe395632b1a162c7b9e75d46be042d64f5230 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_bus26m.c +eefb0e4293a309d3eae668a9f4fff6b9d45d3597 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +fa7a5c1599cac3c19ca4cd64215b1938313806c5 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.c +319ec69ebc8189c0b9500805069cb9eab1288242 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/gpio/mtgpio.h +7494ace1b19166bbf26931bbcce0c574629ee2ab - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.c +a0c85124251b9cdae75734966ce95891397ca477 - arm-trusted-firmware/plat/mediatek/mt8192/drivers/emi_mpu/emi_mpu.h +a6ce0baf4ebd3c81556e0945c2649f2efae6c879 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_private.h +c080e0d9285c2d3fd252d1b5d80f857f7b5f7ca5 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_mtk_lpm.h +166890efce4ba83ab0783f4b56821c8576731a31 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_macros.S +5a59b5db38b291cdbebf71aa758859f99c35a751 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_sip_calls.h +5fdb5614708d12a66d8b58741f2e38c49b7690aa - arm-trusted-firmware/plat/mediatek/mt8192/include/rtc.h +af49cf4a43c7cf77fcfa20fe09d7197390bf3969 - arm-trusted-firmware/plat/mediatek/mt8192/include/mcucfg.h +cfc60d518acd24b2043bf29a48105110ad3068aa - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_pm.h +555f92b188335e740adcafa8f411f751f8aa9102 - arm-trusted-firmware/plat/mediatek/mt8192/include/platform_def.h +d3155938568a3ee3a31e1df08de79e5bf68dc877 - arm-trusted-firmware/plat/mediatek/mt8192/include/plat_helpers.h +98b250fb48fc293e489948124f342093ba6dd423 - arm-trusted-firmware/plat/mediatek/mt8186/plat_pm.c +5317d798df3fa15f8fa7b2c33ba670b0a1ecfe42 - arm-trusted-firmware/plat/mediatek/mt8186/plat_sip_calls.c +02f0daaeeb8c59d391a631dd2f7624e598748e99 - arm-trusted-firmware/plat/mediatek/mt8186/plat_topology.c +e30b233c6a0d10cb0d058f63a7d68bced2033d08 - arm-trusted-firmware/plat/mediatek/mt8186/bl31_plat_setup.c +e55a87f7c47f362fafe9a61204603c0aacd71ab9 - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/platform_common.c +2c9ea17eea925548d393c14f7f51d8bc2fbccdcf - arm-trusted-firmware/plat/mediatek/mt8186/aarch64/plat_helpers.S +1e1932554b5dee8b5c9f6e42584b440f694fe206 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic_wrap_init.h +60b16e786121e9076be12c5a78ec91c7e33801be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.h +8fdeee52467e248a082f45d92512e951f2611360 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/pmic/pmic.c +d2b7ae5854f6cb1abfe5c55f52385c86fe6752f0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.c +f0e1185e7fac539c5d2edbf5893678d2ca131f70 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dfd/plat_dfd.h +9114133093483da052525a109b5ca5242a14cdc7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.h +0bf3be2cc82c84d28437a838ec18ee32b52448a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/rtc/rtc.c +982ba0c3e5b8772dbcb65fe9ec04f07cd66c03e3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.h +3880fbedb01ad739666ead858ff32c11692d7ab0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.c +8836e6535eaf80d79c28bc7e61f796c61f019c9a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm.h +26687de903046dca0b5e9750e8a59b9355a29ec0 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/dcm/mtk_dcm_utils.c +514a984bcec8f805fbc3fc8b0213b8603009b717 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.h +97a67051462aa2dc020abb4c615ec1b8d55798dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc.c +acd408521525ea61a78ab71ab790b33f6c8835a5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spmc/mtspmc_private.h +68d0d1df925010bde7b53a36dd82ab05a0cc23dc - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.h +680305a5142d3cda1b9ccc1bba0d1ca8dbf42b0e - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.h +63bd27946e361d2e05b681e47abfc894e0b23e88 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.c +3de0a5c82b6c6679381b6c8887a23b11e1ee49e5 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm_cpc.c +391c8bd0413603fab7961273368ae142ef2e605d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.h +0950b022f226cf400c633b938956424ef62156a9 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_mcdi.c +b5dccfb4fbab4600a1576c8b74b6e2062cd13c6c - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_lp_irqremain.c +63d1221a97ab18b30010ef6dd666592c84488052 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/mcdi/mt_cpu_pm.h +2f14e2189e22b58a7f814523923a82b761565793 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.c +a6cfe8969863b9001520ec912315467a2b1213e8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.c +c493de6825dedbe205476271578675f186aad0a2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_resource_req.h +5ff4457e67f619c9e7562f12b5fd4772a6d34ada - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.c +1b4a0d65fcaaccb28afc897aef9a76972b99b9f2 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/pcm_def.h +c6cd4eccdc73fc94fe1d36f9c0d24adf82f6b762 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.c +85a883d9102bcbda2f8b172b3428fa270a259858 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_reg.h +8e4cded7b48b70c4d63171d01619ea77582a15d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.c +6afbc58701e19d1e4b949615eca0a6fee5c0eec7 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.c +9842a9ba9c2a948191518a1dcac7efa316141dd3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm.h +714e06306174609b86f6dfecb362e5d307815984 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.h +23822f16c7741b8a82e6c1b2bf37723c9b661d23 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_cond.h +ff8ca308a59e802f869d16233f792ae0e6d19a52 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_conservation.h +be59b0efd4cc9ca4eb6570a3a2fe1d3f0f812fc6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.c +c3913ece4d63b48d8aaa43aaaa4f7c5927073b30 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_pmic_wrap.h +6fad70943b4e7bc9042ec608eca4905531b622d8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_vcorefs.h +ed2f1e43ce8ff9065b95a274256a78d34d08b184 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.c +2915d56fef4019217f23aeab0ebcf0ff98b2818d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_internal.h +302fea6e0fc2351dbc6ccda1ed9190941f2c0250 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/sleep_def.h +d252e68c77c34429d934422da1ce46e64553c23d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_constraint.h +b196a520bf04181913710fa0ad6c7e98df814be6 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_suspend.c +8d4291524d054f1b355580fb4254843ee94015f3 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_extern.h +0c0e64bb4e502f8b06cddf4f5701a2004dae88bb - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/mt_spm_idle.h +ec1e10ba1585046d426fcca0c8d6a0452015786a - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_intc.h +27ef52baeedbc36413879fd421b276824b21ad58 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_sspm_notifier.c +3b25bdf185a1377c793c31e212d50a0027fda91d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/notifier/mt_spm_notifier.h +6dd95a8f29a4eb734a92736d768d92a35ce910f8 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_syspll.c +d7be908565309c39ef0e37d464011c7340c16d6d - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_dram.c +6dea64a1dcb62407a4021b892e2da1cdc50af221 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_internal.h +3035aa1efec0b288548d3a91426946653dc24b80 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_bus26m.c +97b36bd56cf9603b43fd2acace9ae94457d14776 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/spm/constraints/mt_spm_rc_cpu_buck_ldo.c +1cd2b844b96d5646b2f021f2b7a50358af7908a1 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.c +175403c002e2bae8b4b5f15356300cbbf3a37aac - arm-trusted-firmware/plat/mediatek/mt8186/drivers/gpio/mtgpio.h +a0e2a71a095891a57e56e7e285c8f94dc9d312be - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.c +35dc8ecb34f8b16c7fc40797709568394bfa2700 - arm-trusted-firmware/plat/mediatek/mt8186/drivers/emi_mpu/emi_mpu.h +85515b62d8aa7cf44ac7f0b5a705f9507bc7da21 - arm-trusted-firmware/plat/mediatek/mt8186/include/mt_spm_resource_req.h +b7a9f887a8578d015d21dcfd1b009adab66f1f2b - arm-trusted-firmware/plat/mediatek/mt8186/include/sspm_reg.h +d923270912bbaad8959a73f39f933db6c98a49ce - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_private.h +80a7b771023f421a796b8da96a4d42a7672cb817 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_mtk_lpm.h +4b7558ac17d450a33285d28478f8d8596edbb1b5 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_macros.S +567114b72dbc9398566aaf0389041fb7e12ecb12 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_sip_calls.h +f3091cf7bfc468b69812a8ad31b9b5d768775e88 - arm-trusted-firmware/plat/mediatek/mt8186/include/mcucfg.h +c02f1fbfaf33a5bbf3351dff53710e6e70a59e74 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_pm.h +9d9e1a21208cd3b5491a40bacb421776e8c1b680 - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_uart.h +e4b12c87945362986c13896e2349ab872d556c61 - arm-trusted-firmware/plat/mediatek/mt8186/include/platform_def.h +9ba9b4651c7e04ead5846597f6564fab10d8de4a - arm-trusted-firmware/plat/mediatek/mt8186/include/plat_helpers.h +3b21be43300990b373aae5fc9fe86650293e6465 - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.h +ec2741df6c60880f2d8d7c157dcda59d0c50eacd - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.c +180bf4b2deb975b6753f7b845e0055ea91a2aa13 - arm-trusted-firmware/plat/qti/msm8916/msm8916_topology.c +6e7e984a8e5dfab7008759c759d8244470f3dae2 - arm-trusted-firmware/plat/qti/msm8916/msm8916_cpu_boot.c +e08f230adb59004c64e07444599554c275f1643a - arm-trusted-firmware/plat/qti/msm8916/msm8916_pm.h +455f78881f3e452bc906dd8e2dd74d7e668f33dd - arm-trusted-firmware/plat/qti/msm8916/msm8916_gicv2.c +2cfbd336aca6ffd917aac7811b326bc53c734d1c - arm-trusted-firmware/plat/qti/msm8916/msm8916_bl31_setup.c +91be000247752e30dfd222eef60029b13936f320 - arm-trusted-firmware/plat/qti/msm8916/aarch64/msm8916_helpers.S +fd14d1c817b69bd4a42046e3a208b999bffc7e36 - arm-trusted-firmware/plat/qti/msm8916/aarch64/uartdm_console.S +8150ca146a9314d5192e1e394975bb932029bd0b - arm-trusted-firmware/plat/qti/msm8916/include/uartdm_console.h +e1247a97415e84032dab91e8daa6df51645413ac - arm-trusted-firmware/plat/qti/msm8916/include/plat_macros.S +07c3221b9d62d08349ed7bc9f4f1e779f524ec32 - arm-trusted-firmware/plat/qti/msm8916/include/msm8916_mmap.h +d2d25cc01ae69fbf7368f681a6be32083570007e - arm-trusted-firmware/plat/qti/msm8916/include/platform_def.h +8b0399819af138f97f2f4270408c66b5d23b6052 - arm-trusted-firmware/plat/qti/sc7280/inc/qti_rng_io.h +d99874d76998c7025371fc6e19def1521bfacc2d - arm-trusted-firmware/plat/qti/sc7280/inc/qti_secure_io_cfg.h +a0b63dda5b240d0c16799712543a79c70bd462d0 - arm-trusted-firmware/plat/qti/sc7280/inc/platform_def.h +e6926afd75dc641585601bff95a258034095c6e1 - arm-trusted-firmware/plat/qti/common/src/qti_interrupt_svc.c +bea1c249fdc7e365ba7e5d773a7e312de9345fb8 - arm-trusted-firmware/plat/qti/common/src/spmi_arb.c +ac89500a8d77a91b9b24a426b3394744bf74efb5 - arm-trusted-firmware/plat/qti/common/src/qti_topology.c +f12c8a79f6141094db1aac3d48ac6ea34800ff6d - arm-trusted-firmware/plat/qti/common/src/qti_stack_protector.c +7fc1d5b81ce41fbda7e5fda0ba2e22acdf4d5934 - arm-trusted-firmware/plat/qti/common/src/qti_pm.c +aeecda36338ac151632b50ce13795833a9f6ce3b - arm-trusted-firmware/plat/qti/common/src/pm_ps_hold.c +26a9cbddd8b9a236e5d0f3550807554e23563f18 - arm-trusted-firmware/plat/qti/common/src/qti_gic_v3.c +a78d1e23bb28b3815e1e4ed90be36d9a18730edc - arm-trusted-firmware/plat/qti/common/src/qti_bl31_setup.c +825f74a7f38dc32847afc499110e74db3937935f - arm-trusted-firmware/plat/qti/common/src/qti_syscall.c +f3b7fa7c62db7248cf8b50316244b8239596f267 - arm-trusted-firmware/plat/qti/common/src/qti_rng.c +d3fde1360e9da45d7d4f06fa00208544d41ad202 - arm-trusted-firmware/plat/qti/common/src/qti_common.c +7547a5ef92ec4ac40eed5a73041ef25902042bf2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_uart_console.S +b6ee5b136c1d386d21bdb0c3944363930ea1c5d2 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_helpers.S +3d127b0f585eb4f2bfaaccd2f04f814fca7770c4 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_silver.S +35b43eea9fc4e1679a0349180b49fa1bb96e59b7 - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_gold.S +b6f69f64118c04b6b54e760cf7005ec1594689fc - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo4_silver.S +a32c3f1d46d7c6cdcb2fa977d2899c8ff2bebb7a - arm-trusted-firmware/plat/qti/common/src/aarch64/qti_kryo6_gold.S +1d172cb4df58b173035b99b5855545b25fd764be - arm-trusted-firmware/plat/qti/common/inc/qti_uart_console.h +0b01452153b97f032c89b81698730bd0211ee4cf - arm-trusted-firmware/plat/qti/common/inc/qti_rng.h +2c7d5721030a2353cd649ad2cf4da49242ed3195 - arm-trusted-firmware/plat/qti/common/inc/qti_cpu.h +a492ca7a1a6a0dc9b988c09a6838be72f3a00cc3 - arm-trusted-firmware/plat/qti/common/inc/qti_board_def.h +af87d6c46e8e3304b92c90ed0111bb3066bac8e1 - arm-trusted-firmware/plat/qti/common/inc/qti_interrupt_svc.h +f00660ee7d40d5826515fe5266e50d2172c12bc1 - arm-trusted-firmware/plat/qti/common/inc/spmi_arb.h +3030765ef51687943e02ca761d6d518826a6c438 - arm-trusted-firmware/plat/qti/common/inc/qti_plat.h +5901fe33e7d63a4a03e1b95469b48c8299d178f6 - arm-trusted-firmware/plat/qti/common/inc/aarch64/plat_macros.S +576c57f662c322a2eac3565e848ea0179d7290a1 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_rng_io.h +ce8e6c97e3af86cafccb6b9ffe857b9c1ec62598 - arm-trusted-firmware/plat/qti/sc7180/inc/qti_secure_io_cfg.h +3591e68af17680a9c8b78bffb866c93838cc5b18 - arm-trusted-firmware/plat/qti/sc7180/inc/platform_def.h +0c6b7067545771534db6e2eae7bdf7694a939d12 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_interface_stub.c +4e66aa575523181fefb5720d798a257e98a26003 - arm-trusted-firmware/plat/qti/qtiseclib/src/qtiseclib_cb_interface.c +a28527a439c34c2ff37a3bd1ace46fb9ddb4f357 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_cb_interface.h +5db76531814dda261416dc016b511d807c3a4ba5 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_defs.h +186065ea9c6a4a2d16c200d4d07466514f5a1c29 - arm-trusted-firmware/plat/qti/qtiseclib/inc/qtiseclib_interface.h +3e4d34962a59227a5d8d494f35e80b77fdf8d61e - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7280/qtiseclib_defs_plat.h +885aa0bbda57cb30366ac8f9ea09f3f8e7ad31da - arm-trusted-firmware/plat/qti/qtiseclib/inc/sc7180/qtiseclib_defs_plat.h +4bbfc2267980533e77f9d529ab7d174d48d90403 - arm-trusted-firmware/plat/intel/soc/agilex/bl2_plat_setup.c +f1e4a10f906499fc859ce623d4571dc63e7d5273 - arm-trusted-firmware/plat/intel/soc/agilex/bl31_plat_setup.c +3c317104013baa1af66596ba8f1eef175f48843d - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_mmc.c +3a9e2ef84999f167350febae7da7117e414fdaaf - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_clock_manager.c +0701baf6d3a2c6d67485a189fa41e9c33fd20ca4 - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_memory_controller.c +f28f931b63cba463d5ec189bc42550444729edad - arm-trusted-firmware/plat/intel/soc/agilex/soc/agilex_pinmux.c +592af310a2153553607e67158a137e3b7d297c79 - arm-trusted-firmware/plat/intel/soc/agilex/include/socfpga_plat_def.h +c3fe6580aad543effa72713fb4d54e4fdcd7f76e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_noc.h +2cbef8a830bfec6a533910d7a00ca01de32629c3 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_mmc.h +e61cd2fc029895773c3e7781028ff30b7d863cb7 - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_pinmux.h +a86635994a276adad357b7b9a9408af38860c61c - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_memory_controller.h +fc798b0a8b41f3e6053be0d0669917e2a704807e - arm-trusted-firmware/plat/intel/soc/agilex/include/agilex_clock_manager.h +659bce34ee85d1001adb313d9a639d66d3a89deb - arm-trusted-firmware/plat/intel/soc/common/socfpga_image_load.c +a73994ba0863a0c9119b3e80c2f95fd3a67881de - arm-trusted-firmware/plat/intel/soc/common/bl2_plat_mem_params_desc.c +98e7e0c1e8b661cfd05aacfbfc969aea710cf145 - arm-trusted-firmware/plat/intel/soc/common/socfpga_psci.c +b1605e3612529c3ef25860a30a92276b1762eff8 - arm-trusted-firmware/plat/intel/soc/common/socfpga_delay_timer.c +23e53289a40f4fdd5705ffc560d18e9e3086e32e - arm-trusted-firmware/plat/intel/soc/common/socfpga_sip_svc.c +0c8169624b733658b1eee7afa553ac38e2f2660d - arm-trusted-firmware/plat/intel/soc/common/socfpga_storage.c +cc4b0a911ae0f00cfc94310c6a9d60716e9a1064 - arm-trusted-firmware/plat/intel/soc/common/socfpga_topology.c +c93b1e05180647b1752b51838d7b935bf554e073 - arm-trusted-firmware/plat/intel/soc/common/aarch64/platform_common.c +ee464010f7478ad28450e239244175a97360cef4 - arm-trusted-firmware/plat/intel/soc/common/aarch64/plat_helpers.S +6a4cfd87ff051f635d35973a9d14d941e0dc377e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_system_manager.c +46033ef6c11ee3af5452b7fdf9b90c20050c0be8 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_reset_manager.c +23d9dff6e9c23385b4ccea7791e18d709f29f6d0 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_handoff.c +30326906ea4956c9a459d8a32363b2ca3de50733 - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_mailbox.c +dbb5c27c52afd2347aa5d78b423a051d694a5c1e - arm-trusted-firmware/plat/intel/soc/common/soc/socfpga_emac.c +41479908d06f853d367898b86dda07763652f4c7 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.c +c9354b6d74c4a24fae2207b5b999882056d88e91 - arm-trusted-firmware/plat/intel/soc/common/drivers/qspi/cadence_qspi.h +4a2ceded30ce0c9be27082dc3e0a0f646e41c555 - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.c +5e8868245cddc9cd3bff4ded0c90d2f8b356920d - arm-trusted-firmware/plat/intel/soc/common/drivers/ccu/ncore_ccu.h +5c64677609f95ebafb78a49847ca9c07c1a3aa87 - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.h +c72a5bba918c6067f6a77a639c42bc477c71de2c - arm-trusted-firmware/plat/intel/soc/common/drivers/wdt/watchdog.c +c02cf900011574561e4a40f32b4328ee9b4fc2dc - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_fcs.h +55418579bc9725e40a61a81af232a46218f27291 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_private.h +ffac73fe826ff46223b2ddaebd9e7206528dfe33 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_emac.h +3eb20b0d72778ce95cdd02e0732ff2485fdcbe49 - arm-trusted-firmware/plat/intel/soc/common/include/plat_macros.S +b117623bbdd5a56a0ff191770082cd80e5b860e4 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_mailbox.h +3886a4a113d64631d91373640cc1e9d6ad0f9de5 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_handoff.h +987353d4fcf33b0589d816a77ed534bd4b0ee784 - arm-trusted-firmware/plat/intel/soc/common/include/platform_def.h +90cc387dc45aa325c65a5f792054dbf87337d0c0 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_reset_manager.h +04e0e1415877c38b1d5b29fd0db73a6ec1bbc63c - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_system_manager.h +f10900dcc55350c0601a0fcddce82a8d8faeb902 - arm-trusted-firmware/plat/intel/soc/common/include/socfpga_sip_svc.h +def81ce5e821eeb00d79cf3474f11987dd6f1d5a - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_fcs.c +8b1c7bd1975b587b7b972a8471ba45698080074c - arm-trusted-firmware/plat/intel/soc/common/sip/socfpga_sip_ecc.c +2f22a31fb6bf835c01bd19bb362bba1c8a3e4918 - arm-trusted-firmware/plat/intel/soc/stratix10/bl2_plat_setup.c +66cbb2ab82f32d934dc4d303b958c70750303ca6 - arm-trusted-firmware/plat/intel/soc/stratix10/bl31_plat_setup.c +70667783807950b851233233349f9cadef62b70d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_memory_controller.c +4f2d7ac1b88723a36765c17fe3b6b524622ee49d - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_clock_manager.c +5a527e1803e29b659091fe8cf586adaf527a55dd - arm-trusted-firmware/plat/intel/soc/stratix10/soc/s10_pinmux.c +05acb6f9fd3967467369875212f706741e9434c3 - arm-trusted-firmware/plat/intel/soc/stratix10/include/socfpga_plat_def.h +db28b2738f48c2d2751af6dee5456298ec578706 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_memory_controller.h +2a726cacb7d9a01adbb5c593a0bf7a6f0e9d2c18 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_clock_manager.h +fbf4ab727479f904a0ae30ca600e339277fc9c11 - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_pinmux.h +327e01f2a345b7d3b00f949c0785a60e4c03889f - arm-trusted-firmware/plat/intel/soc/stratix10/include/s10_noc.h +1e8b5a5e05d44ab9f8f3bcbdc873885fc49c39de - arm-trusted-firmware/plat/intel/soc/n5x/bl31_plat_setup.c +956551e3f043e449ce36fb1696d99d2ae5b925d3 - arm-trusted-firmware/plat/intel/soc/n5x/include/socfpga_plat_def.h +3d01d365783ad5b2ce0f76df72a4a10db3d9a10d - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_memctrl.c +8ba47e3eaf73ff3181e4874c764119b46c88baf2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_ras.c +4597342fc7f0ad8d99af644fbdc636abdee5edd3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_psci_handlers.c +e6ee29b4c786d6d279e82a4066d13703168bd28e - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_sip_calls.c +b0c855a9e2b50bbe03f42d79ccd6a555853cfefa - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_setup.c +c2cd522ab9668274cd7bf26fde63e9dbc9a94f28 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/plat_secondary.c +7641a42485d020517c692c523a29fe5be4136651 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se_private.h +cc8a8d368611f86cdf1901163b06c0975be5ad93 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/se/se.c +81037a214c1511f91f65b5793f9d5fc3668f3c79 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/ari.c +ed3d0d97c20ace9c41ddac5ef51f81f75d2e7d59 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/mce/mce.c +78e0e7699170ceb53b16257c0ef0c15fe08ba4ea - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/mce_private.h +46decb1b646ffba87d49eb22447f8e56ed5e0d44 - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/t234_ari.h +08aec0d0be276f69ddac5a77363f59f1ef42d88b - arm-trusted-firmware/plat/nvidia/tegra/soc/t234/drivers/include/se.h +595bafd552b05d81a25e9916fe91779e18beddda - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_memctrl.c +d893793283c93ce6c488a51940c01574780f7333 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_trampoline.S +c55c5c502ca4117b327d32cc3fef8203d3c64731 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_ras.c +d1917ee3fc59b85d699e80636d7ddd7d4c99320d - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_psci_handlers.c +d5aef4c8d30794a496c1c3bd18d000991bbae988 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_sip_calls.c +84d20d5a07d53e649a1b8d130f5d4fdf6ba8f65a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_setup.c +ba0a312824b0782a438e265e86a6e9d7638032db - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_smmu.c +6d0c46a965f769a08b399225be6c77aa18f3a773 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/plat_secondary.c +fa7909d4e0ccdeee6f0765cf68a95899ac8aec1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se_private.h +b3fb31a094585eeb27ecc82ba69416ca4d66b171 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/se/se.c +0cdfadd153db5ee7d515adb01dd35d62e546226a - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/nvg.c +ccebfe25a0f4bc54b5d08685ce74082118f713e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/mce.c +99d5d980ae032fa2dfb6e9da5fe48dd600b2a896 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/mce/aarch64/nvg_helpers.S +8cec2a63b748c24a5fab3c7c47f114b8147894c4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/mce_private.h +ee3f4b7a69c6c3dd475a88c55076077415fc76b7 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/t194_nvg.h +298abb9097e851023b914f09fe36c8cdaf367e22 - arm-trusted-firmware/plat/nvidia/tegra/soc/t194/drivers/include/se.h +89808197706a2d7c9eedc24ca7666ded83f0e84a - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_psci_handlers.c +ec24a0077b010c615c5e3a083e901d444aae2f20 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_sip_calls.c +bee19a74bce67a4d58e2f4deecb801e1a65bf631 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_setup.c +1ac68857bdb8a88c7770c006dfd2be48670a7011 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/plat_secondary.c +17ad1d9d60e3f6debc0329a42e28178fdd497e1f - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/se_private.h +3b606d0fba33a0ea6729510a467dcb03e9750140 - arm-trusted-firmware/plat/nvidia/tegra/soc/t210/drivers/se/security_engine.c +c7611d91a504dd3fe52ee769f9fa2d4f469010a8 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_memctrl.c +0dd6e3b7ed73b5e77f6ebc89320058cde70900c2 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_trampoline.S +1cd4aab41ecfa796a41aecfc70e543cd82e2da72 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_psci_handlers.c +106e68f73e09c8f51c620c0dd840b42ea6dbd67f - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_sip_calls.c +d4052416878640cdb19e93edd44e4a7413289b6c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_setup.c +5b9c61a07970be31ce559c1b2c78acc41d5223e3 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_smmu.c +bf02f90c1795b9e26f314ab310c0ba4e389257e4 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/plat_secondary.c +d96974438f18123824bf23413d2d0d75452fb4da - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se_private.h +326d37fa1c2f92a2e56baf3391479c3dd1365396 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/se/se.c +4588d011d8dbc1073379954dcdfb1c437cf9d4ce - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/nvg.c +cde1d7e2f8c3e1513d4828b37df69223bfb780be - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/ari.c +0a76eef9a0cb2d3c1fffc2a886eab6fdabb34997 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/mce.c +015badf34dbdf2955bc1dc9f4b22627bde8f9f9c - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/mce/aarch64/nvg_helpers.S +34e8d1c4e060805a3f55969aabbd211dc6b08fbd - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/mce_private.h +34309aaec4559a7c2094873802490b96b9cf9dc1 - arm-trusted-firmware/plat/nvidia/tegra/soc/t186/drivers/include/t18x_ari.h +ce1df43aa2a9700b9c00f14be842646284b3ee3d - arm-trusted-firmware/plat/nvidia/tegra/scat/bl31.scat +348ad39495b7209e9858421f7bd1a02f9712a410 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pauth.c +97542646c951833f68e49c013c2d309b885aab65 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv2.c +bbb547cc93729fd63ae5da22480a94dc84ad6fbf - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sip_calls.c +7832f9e627bdeb224b72a22840b7b4cd3354b962 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_stack_protector.c +9a23652352c01545d80c980df50b0d1965df8131 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_gicv3.c +c7104ef4a0ccb4a2ceb01951a0c8442349cf4ca7 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_delay_timer.c +c97649b9bd33d9e7f4268f6ddc79d603a3a317f2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_fiq_glue.c +ab066b0f80239a20f5613a9c2bf4862d9c02e2c2 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_bl31_setup.c +8617ceef396a9a7f9b5e9e1a4866cede187f6ba6 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_sdei.c +6356a0b128a435ef5faa1bb6922a5fcc571926ea - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_platform.c +0c5a65d7362595eff6d472ba23ccde7af61d9ce8 - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_io_storage.c +e531e11712693e6095f810484cb2f8332646c1dc - arm-trusted-firmware/plat/nvidia/tegra/common/tegra_pm.c +e73b702494b764ebb0f546aae9de484a69c968f3 - arm-trusted-firmware/plat/nvidia/tegra/common/aarch64/tegra_helpers.S +d25c56f572cf7b3618f7567d502c1ee11dec2bae - arm-trusted-firmware/plat/nvidia/tegra/drivers/smmu/smmu.c +8d9b8ebe2f8407dfc849bee6942b55d0a9c76d41 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp/bpmp.c +58fc3b165ee7a61397eef3e9f2065858876ce9de - arm-trusted-firmware/plat/nvidia/tegra/drivers/spe/shared_console.S +4d04fd613146842b18904061da84f5958c44b16b - arm-trusted-firmware/plat/nvidia/tegra/drivers/flowctrl/flowctrl.c +fb218e655fd6a3d77f969fce9cd6cb5dd0a6c5b2 - arm-trusted-firmware/plat/nvidia/tegra/drivers/gpcdma/gpcdma.c +2a6016cc527d04ca332373c0d14542d5176aebf8 - arm-trusted-firmware/plat/nvidia/tegra/drivers/psc/psc_mailbox.c +0f53c08fb6e10d933fd28d9f021ccfb0e48212fe - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v2.c +4dbec584881036aa37e59b66185d958a695a455d - arm-trusted-firmware/plat/nvidia/tegra/drivers/memctrl/memctrl_v1.c +6f1dca2fba8be7758cfe4395226b2e4be820e3f1 - arm-trusted-firmware/plat/nvidia/tegra/drivers/pmc/pmc.c +bbc86d9dee6c505651fa862133b686ea1e1af43e - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.c +ecf2d932f335bc64d226c7d6502806590af552b6 - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.c +91900a1e10f18554bc4c6b9f13d0e247da31062d - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/intf.h +458bed9c52c48caaa9c30822f0d20359e56e044f - arm-trusted-firmware/plat/nvidia/tegra/drivers/bpmp_ipc/ivc.h +e8e7dbe2842bffabc62ef459d5f4b037b5fc122a - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_private.h +949736009adf4b730b592ef786e3d66eaf769d8c - arm-trusted-firmware/plat/nvidia/tegra/include/plat_macros.S +61343b0647173b58eec236e5f6781f95ee64f5d2 - arm-trusted-firmware/plat/nvidia/tegra/include/tegra_platform.h +11b45c0f4e3d96795a403b588930c354305a52d1 - arm-trusted-firmware/plat/nvidia/tegra/include/platform_def.h +b76d085fd8bf62b29b2651fb2baafb167bbb3f37 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_mc_def.h +2aec61855e1e16a88683b573ae88e337484a01cb - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_ras_private.h +21b9ecfaf14f5a5aed16e18cf1643f78e890a096 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra234_private.h +624f3a27eab52b8c97c1d391c9bf0aba2a48ff48 - arm-trusted-firmware/plat/nvidia/tegra/include/t234/tegra_def.h +2693485a6a4c24984696bab65e09494c4af953a6 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/psc_mailbox.h +7eee98bf96c4e615e71244fad2270fe3ac7bca96 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/spe.h +b01b1d6699848ec430ef6c7ff1fa536c611ac8d8 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp.h +ecb6bb2512f5f946927baadc3238cacaf9e9c42f - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/flowctrl.h +dd094069cb1a5bb53cf55c4e87b2364925c1e25c - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/mce.h +eccbd7dbdb2b149abd38a48ddd5f6b0f292373b7 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v2.h +fa073698981deb8685410d390184a2fea2477d8d - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/smmu.h +0005633528a5228ce544a5fe3fc8b984d26eff95 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/gpcdma.h +97366374236e04da0a203c6df1ed7e93325e40f5 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl.h +d6acbb5f1eb851fbab413c7209bfba21509b4d31 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/memctrl_v1.h +e4e77bfcd8d045ecce243b060298bf229cbf3941 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/security_engine.h +4aa146b81da8a061bda6540907c37d5ec6569962 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/tegra_gic.h +1ad3acb2c35dab529632e51cfd8a1977d0a3e495 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/pmc.h +d99d1382679e0a53fedf1afb4781358524154b54 - arm-trusted-firmware/plat/nvidia/tegra/include/drivers/bpmp_ipc.h +0770b19832587bf494cdf6a16cf0af55ef4e3eba - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_private.h +65dcb16996ba6f5480b25b088c00618a8401e2b0 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra194_ras_private.h +249831518e8554837fb8750d200cb4b786c2d683 - arm-trusted-firmware/plat/nvidia/tegra/include/t194/tegra_def.h +412a883e42794de7909b0a3076864c06874a0764 - arm-trusted-firmware/plat/nvidia/tegra/include/t210/tegra_def.h +68ec103aabc7cf1ba96e9f802589f232bf63e8fb - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra186_private.h +80ba76cba14e63964ee35830536886c24581020c - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_mc_def.h +00ba4a09814b790749853248a68f57c1bf5d8a77 - arm-trusted-firmware/plat/nvidia/tegra/include/t186/tegra_def.h +fc8ce0bab3e269ab289babbc37c5ffea6c1105c1 - arm-trusted-firmware/plat/nvidia/tegra/include/lib/profiler.h +fbecdf95d5fb90503336b712a6955a36a635aac0 - arm-trusted-firmware/plat/nvidia/tegra/lib/debug/profiler.c +d9c373f0351531965e8097178bbc13ede3af7485 - arm-trusted-firmware/plat/renesas/rzg/bl2_plat_setup.c +ffd1e457886f1089d9c344f701ec17dc97f8f074 - arm-trusted-firmware/plat/renesas/common/rcar_common.c +716e1c7c79baa403b9c5d0ef120f23d8cac8e802 - arm-trusted-firmware/plat/renesas/common/plat_pm.c +514484b073de3f03a0c25885d1947529d0863273 - arm-trusted-firmware/plat/renesas/common/bl2_secure_setting.c +ea086669ab75f559b2e65b291fea3af158c18bd2 - arm-trusted-firmware/plat/renesas/common/bl2_plat_mem_params_desc.c +ae71ad3a55f0e9c013697f9775e6c12c0ff7bd74 - arm-trusted-firmware/plat/renesas/common/bl2_cpg_init.c +d414d4d769295e5a493cf3e77c9c51626ee0e6fb - arm-trusted-firmware/plat/renesas/common/bl2_interrupt_error.c +12b42e58567a9ecd3d1d63318cb5ec7011a41573 - arm-trusted-firmware/plat/renesas/common/plat_storage.c +a977937122b0a3096d2974c21e1d01713d54ef5b - arm-trusted-firmware/plat/renesas/common/plat_topology.c +5f9406be82d4cf619e442556228de3e2d1283e39 - arm-trusted-firmware/plat/renesas/common/plat_image_load.c +9e2b414041c35052396135ebdc28539af32c2593 - arm-trusted-firmware/plat/renesas/common/bl31_plat_setup.c +3c4b66c3e0e2ea740399f2ac87b9c61af5c45031 - arm-trusted-firmware/plat/renesas/common/aarch64/platform_common.c +2b4770445484da2ea7c1061c5e772905f5f9eda9 - arm-trusted-firmware/plat/renesas/common/aarch64/plat_helpers.S +f99514b828a7a7fe6f0063a291c023d74a2c9bd2 - arm-trusted-firmware/plat/renesas/common/include/rcar_def.h +72226e12e556432cb547181aa73e0d55c5c8777f - arm-trusted-firmware/plat/renesas/common/include/plat_macros.S +2f021b7dce5115d413267052dd5b471ceff900cf - arm-trusted-firmware/plat/renesas/common/include/rcar_private.h +aa601d2e26e65cab57efac1579ef07d5a4966f23 - arm-trusted-firmware/plat/renesas/common/include/rcar_version.h +939b904cc911a51e5bfd33fc817d5c5b22e55400 - arm-trusted-firmware/plat/renesas/common/include/platform_def.h +f4aa97332efbbc8e20e48e338443fd3b9c208830 - arm-trusted-firmware/plat/renesas/common/include/plat.ld.S +64ef91e2bf3528ac94c8eb79c5c3f80113257721 - arm-trusted-firmware/plat/renesas/common/include/registers/lifec_registers.h +f5943232ea7fe8a4717cdaa5d1f371ec634c8074 - arm-trusted-firmware/plat/renesas/common/include/registers/cpg_registers.h +f773e9cbe28c8c27bd7013b66cd612cd63f790fc - arm-trusted-firmware/plat/renesas/common/include/registers/axi_registers.h +954d720bbb952517040ea8c1648e94dcd01de552 - arm-trusted-firmware/plat/renesas/rcar/bl2_plat_setup.c +65b77a7dbb8e28f892af2bf3b76eff17c87a9cbd - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/mvebu_def.h +147f2e7e737cb6a5eb1dd98a0deed8c0462d2041 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/marvell_plat_config.c +a1f884a99e9e14ac83551e73429b0cf7a2c5aa0d - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/dram_port.c +2311f962795291fdd649a3acb3d3fcee85e19d11 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130/board/phy-porting-layer.h +60baba93a9e38f989d8f3fdfb045849d1edc2d69 - arm-trusted-firmware/plat/marvell/octeontx/otx2/t91/t9130_cex7_eval/board/marvell_plat_config.c +79f7407103c1059afb212382689fff9c6a4f4350 - arm-trusted-firmware/plat/marvell/armada/common/marvell_io_storage.c +6ea11f2ef3d7978e714cdf621aeb7c8719c7edf3 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl1_setup.c +e8797c2639ec349e76fc1946c984275c010e4cc0 - arm-trusted-firmware/plat/marvell/armada/common/marvell_console.c +2c689ed8bfb3abf1dc9ea37ffaa8aa9479649eac - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl31_setup.c +c785e8c07a0fa5d01b9ecf8eee873f7a18697e3a - arm-trusted-firmware/plat/marvell/armada/common/mrvl_sip_svc.c +5f97ccaef3ab26b2710ad26fb0fdbd9facfd0b7d - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv3.c +59510c739cc2d9619a9a5c21e1cbf1bb05094867 - arm-trusted-firmware/plat/marvell/armada/common/marvell_pm.c +69ee13cde36accbde0f355f89f9cc2b5d1aa2cb9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_image_load.c +9fa0f4b8209945eb39ccee90bcc305efbe10f211 - arm-trusted-firmware/plat/marvell/armada/common/marvell_gicv2.c +c6e2fab47d050265fe94d5ce57fd1a3a684da2c9 - arm-trusted-firmware/plat/marvell/armada/common/marvell_topology.c +db23baf6374a79472a4b930f1fd68144d4f314a1 - arm-trusted-firmware/plat/marvell/armada/common/marvell_bl2_setup.c +0ff28a152c1c0997120e1e3a5fe654f1ae19ac60 - arm-trusted-firmware/plat/marvell/armada/common/marvell_cci.c +1a879218f61e83b5068e40a2b093fdb4ab851a4d - arm-trusted-firmware/plat/marvell/armada/common/marvell_ddr_info.c +ea896d0f1d011e14c4411020d73d083c22eac783 - arm-trusted-firmware/plat/marvell/armada/common/plat_delay_timer.c +daa5b1a54bfa63c73acf8429940662cd450f1eb9 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_bl2_mem_params_desc.c +a71cc21b90eb5b1d29b125e9c98c3e50f9a145bc - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_helpers.S +0842c4cae12a7c22367b83357a2c824d060dee67 - arm-trusted-firmware/plat/marvell/armada/common/aarch64/marvell_common.c +872e517062b5b548f6de42424dfb8290309f6773 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.h +5cecfb1042c66b79c4c4c9bc5961fd91b34c880f - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bl2_format.h +44573513efade3da9aa2ca94c3d4069a8af646fd - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_mem.h +0bb02e303d4c696fe34379bc2d5dd9f2fe16229d - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_scp_bootloader.c +56e5fda520a793a37c7e8daa1ecfe2354b26e99e - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.c +42d2fb2461687118d1f9e79ed2ae2a274cc91c45 - arm-trusted-firmware/plat/marvell/armada/common/mss/mss_ipc_drv.h +d00c0cf869839d6cd370b5b6c58e8d066705e2e1 - arm-trusted-firmware/plat/marvell/armada/a3k/common/marvell_plat_config.c +40c2d9f804ed183a8befa38d61bdd2164d711b34 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_pm.c +344f94187e37e08b2f532eb66281e7e28e7702c5 - arm-trusted-firmware/plat/marvell/armada/a3k/common/io_addr_dec.c +f1d76afaec515fb65236190a9aced6e0ae2b4d8b - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_ea.c +4e66aa51fabafab21b8e01fa4f3d49fc8fe6a97e - arm-trusted-firmware/plat/marvell/armada/a3k/common/a3700_sip_svc.c +f0aaac82be8c1b465622b1b82d8514de62c2e937 - arm-trusted-firmware/plat/marvell/armada/a3k/common/dram_win.c +a8ca841fb42e9bb5a9c071732f25138003b82d96 - arm-trusted-firmware/plat/marvell/armada/a3k/common/plat_cci.c +1b64a7198143a5ec5cbe075762bfc0f47e7eded0 - arm-trusted-firmware/plat/marvell/armada/a3k/common/cm3_system_reset.c +6a97369a4a693cf002e5f5f6ece32516e5978068 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_common.c +80f0ae31f4c2b57b330b01be44b293f6aa2cef72 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/a3700_clock.S +965bc32da1f0ff9aa830bcede48eaca19cbe3b29 - arm-trusted-firmware/plat/marvell/armada/a3k/common/aarch64/plat_helpers.S +12bd9050e1d74b888a3866cf8ff79d17103fd0f2 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/plat_macros.S +6c89be0e3e7e102687ce8d216227785edce4db33 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/ddr_info.h +0e8b8f431e24f28a92fcd4fb9d46eb87a1113db4 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/io_addr_dec.h +71cc1316bcad08255d76ad0ad858f47d681be60d - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_plat_def.h +58c7ff47a2230af870313a655dcab4f22dd64957 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/dram_win.h +61ab3a7cf4de99459f74b40ee4aa7c4c063f92ab - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/platform_def.h +6a269296c2d98fb8f6f4c1736696c4e6081cbc88 - arm-trusted-firmware/plat/marvell/armada/a3k/common/include/a3700_pm.h +2cecd73b6df5a49196420939a6810672640ce165 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/mvebu_def.h +716620282caf3210c15f6795e996035311a8ddd8 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/plat_bl31_setup.c +8f4af50a0df849dd31970be55e943ee4302b0472 - arm-trusted-firmware/plat/marvell/armada/a3k/a3700/board/pm_src.c +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/mvebu_def.h +f1c6500edd19c1540f562c4ea2dba8443a7cd419 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/marvell_plat_config.c +4d33d263a3f05c3d8f3400a45afc2dd7f1792669 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/dram_port.c +7bdf0ea1da45eaab8f21dca700b29582ccc57d0a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_puzzle/board/system_power.c +266ed9c2a714504a190f6bdd10db0d40815a428a - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm.c +3f6403fd39850e34f4c3bd674ccf8170f74af43d - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl31_setup.c +bc3edb20ef2a7baebacce2c631f800cb6d206bbc - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_bl1_setup.c +f1e7a83b618d37eb2df8dcc4cff814b934a4ab74 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_thermal.c +c96d4c2fac061ca1e3be3600ee8748de11d20ed0 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_pm_trace.c +4f7afd096359c9aad1f7852029a643db033fe7c7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/plat_ble_setup.c +01f390bd22a88039e1fc5f2d062ca126dae34478 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/a8k_common.c +4b2131b48e6b858b49e7e4d819172c5bc729f213 - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_arch_config.c +919f5232edc5f6c3ec1670dedf5bf25fbb59356f - arm-trusted-firmware/plat/marvell/armada/a8k/common/aarch64/plat_helpers.S +97ae958df0c9d8f54ff36a7803fe0ba27434e45c - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.h +9acdf9fa5a506b13c376584f49b42a4f437af6c5 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl2_setup.c +392f1834ac5b4679e9ae724c7cf1f3a20c0e566a - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_bl31_setup.c +cc11d9f29f29d9c9366f3e6c66183d38e3031ab7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_pm_ipc.c +f83bec0cc962f915447a4582455414387713f7ac - arm-trusted-firmware/plat/marvell/armada/a8k/common/mss/mss_defs.h +86c5d3b710ba9b63aaf82c0f9dc1606c22176f45 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/plat_macros.S +9fe71c8db281a9fc253c959e2bf8d7ed5b59f658 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/ddr_info.h +0f1625972d53fdedca61514318bdfd1ca806ac51 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/a8k_plat_def.h +3145664e80460f27bc2fd8cda127e916e518678f - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/mentor_i2c_plat.h +eb840b0d5bb6e8cbd42b1ab32b72baec165926e7 - arm-trusted-firmware/plat/marvell/armada/a8k/common/include/platform_def.h +29b7013d6e080d93a60b3780f10310e29aaa6bbb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_main.c +04e2455b39d088cb56ccb73dac9c842fb6f6b7eb - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble.ld.S +8d8ccf9d72fb421744052b95f2dc698844542a67 - arm-trusted-firmware/plat/marvell/armada/a8k/common/ble/ble_mem.S +29e2e91f84a20d0c2f220e0eba6c447909e5aab4 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/mvebu_def.h +e26cc9cf2cffd853101d24b0e6cade82ff5f5cbe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/marvell_plat_config.c +8211399dfbf7994faafa28d85d5d232265c000fe - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/dram_port.c +99aea1bcabb4f6d0d7452ad42116629d21bb2b61 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_mochabin/board/phy-porting-layer.h +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/mvebu_def.h +027eab15e763f75779fca4721b6612e1cef0f74a - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/marvell_plat_config.c +c0c43ed673f4f38bd78a3d145c4ff0f553bf3032 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/dram_port.c +80de920eee6f0214b1cfb2cf104cd6d295bb478b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0/board/phy-porting-layer.h +b79710e67347483f51ba3aa8fcb25a7f7dbb5083 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/mvebu_def.h +a3184b54f314a3880b11bd80e9ace2a825e4e251 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/marvell_plat_config.c +e0382b98cbf2ae3613453ec924646d5af8b1f11e - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0/board/dram_port.c +9a52294343831155772b4411f11af6c989dbd182 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/mvebu_def.h +586996360a2bcce38bf90fa0b1b7a20a45c6e26b - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/marvell_plat_config.c +25524fffee705cfc27dd670e05523c5de9ef0ed6 - arm-trusted-firmware/plat/marvell/armada/a8k/a80x0_mcbin/board/dram_port.c +c7d9738b5d030b72c12bb9649d2dfb58e180b5b8 - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/mvebu_def.h +8eca9aa01df9af91fe07386e941d7557eae7d0ce - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/marvell_plat_config.c +eecb4e28621a6ea2bbe58371406ef5f58590424c - arm-trusted-firmware/plat/marvell/armada/a8k/a70x0_amc/board/dram_port.c +0b8ef1037611c38ba89966b1da4ef153e47b4fb4 - arm-trusted-firmware/plat/rockchip/rk3368/rk3368_def.h +524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3368/plat_sip_calls.c +22974ca90d72fb96f260417ace863c692dad5cdc - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.c +cb622b7fdee1e5387ed783d371b6cfdd0400df92 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/soc/soc.h +edac1a959247a82db5f820097a9f8ded6c4665b4 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.c +7a2d810a3f11780033972a9b1f3f2eb09adddfc5 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/rk3368_ddr_reg_resume_V1.05.bin +a4fe0b238351912e5a3b7e1de16ea4b470dbcfe0 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/ddr/ddr_rk3368.h +985e72c79b58499d32fbf6ef6f46a741c6356e9d - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.h +859692a896bf24f76093c6cc1a923f3bd7f06c49 - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/pmu.c +0ea97dd2ed72ec48826e4668463b1067b1e3e91a - arm-trusted-firmware/plat/rockchip/rk3368/drivers/pmu/plat_pmu_macros.S +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3368/include/plat_sip_calls.h +5817c26932930a69f20037fcfd33b6f700e518a0 - arm-trusted-firmware/plat/rockchip/rk3368/include/platform_def.h +c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3368/include/plat.ld.S +9213c21ad6f4d071ef85303d7f16f295b02bc212 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv2.c +85d08d7cf74717daed56a0770f3c79bca90280dc - arm-trusted-firmware/plat/rockchip/common/plat_pm.c +4761873c26add12f8bff6e22a79c209ce1923023 - arm-trusted-firmware/plat/rockchip/common/params_setup.c +32f9de1c486103a42cf6a9d291f42989b42a98e4 - arm-trusted-firmware/plat/rockchip/common/plat_topology.c +1f63c15382d48351f3d1c1709e7428545ce2cb72 - arm-trusted-firmware/plat/rockchip/common/rockchip_sip_svc.c +3bb10820f3cac4793d72ccd0dbaa9513b9945d80 - arm-trusted-firmware/plat/rockchip/common/rockchip_gicv3.c +4a1355d1645ef943a89aa54999041bd5a970c764 - arm-trusted-firmware/plat/rockchip/common/rockchip_stack_protector.c +91be87581dcd25681be045b39eb7934ec59a6fa9 - arm-trusted-firmware/plat/rockchip/common/sp_min_plat_setup.c +d30876af46d1b3b1d2c18f43fa7894f8fda3c5f8 - arm-trusted-firmware/plat/rockchip/common/bl31_plat_setup.c +258f177b9b9412883f714cff3406818288eca04f - arm-trusted-firmware/plat/rockchip/common/aarch64/pmu_sram_cpus_on.S +47fca1d947e59a046afce81911f7f552c72c6ab5 - arm-trusted-firmware/plat/rockchip/common/aarch64/platform_common.c +aceb5792fbe22f18f421f2a754469db4f6f62cac - arm-trusted-firmware/plat/rockchip/common/aarch64/plat_helpers.S +e40967392bea64496e752401f887b55eae946bf3 - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.h +5c96dda447934109fef22dbfc20108fea56100fe - arm-trusted-firmware/plat/rockchip/common/drivers/parameter/ddr_parameter.c +5b690165e56aee2f4e71841059154598362ce876 - arm-trusted-firmware/plat/rockchip/common/drivers/pmu/pmu_com.h +5c6218088ea95aa4cdcffbabdfabcf2054405b9a - arm-trusted-firmware/plat/rockchip/common/include/plat_private.h +2360baef8c09eed0a7d7ca2b2f97f9405c9bfd92 - arm-trusted-firmware/plat/rockchip/common/include/plat_macros.S +c08e0dba86277197d207590daf335b7a863f4f32 - arm-trusted-firmware/plat/rockchip/common/include/rockchip_sip_svc.h +e0b9109d2e15ba78290c67b35d231cc82990137e - arm-trusted-firmware/plat/rockchip/common/include/plat_params.h +ba0fb41c4b6e827fc3092feb1e41d096daa7e77c - arm-trusted-firmware/plat/rockchip/common/aarch32/pmu_sram_cpus_on.S +505eeb07bdc39ad3e19a4f6676774af764d3c300 - arm-trusted-firmware/plat/rockchip/common/aarch32/platform_common.c +63a3ba51a470fe12e6026880ee67d6de178f8590 - arm-trusted-firmware/plat/rockchip/common/aarch32/plat_helpers.S +23b124a5b49de1ae84aecc76669a8e76f9579f93 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.h +4db0b70aecaf5352c4deda76075a44c7ed772f91 - arm-trusted-firmware/plat/rockchip/common/pmusram/cpus_on_fixed_addr.S +ef5a8ce281d95041b91f8f165ef782642d022de2 - arm-trusted-firmware/plat/rockchip/px30/px30_def.h +6fd13eff5a2d17a6f2e651b3eba6211a93d3522f - arm-trusted-firmware/plat/rockchip/px30/plat_sip_calls.c +288f8f52c9a5423576d1fd403f776da8e5906395 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.c +dbc0dd67905cb60b55ff82d4f1d8bf96a7ec2514 - arm-trusted-firmware/plat/rockchip/px30/drivers/soc/soc.h +7129bd0759914b2bdbe0af12743e79277b990a3d - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.h +e5df7e7476f59e23d9c3c1097c64bad93fb273ca - arm-trusted-firmware/plat/rockchip/px30/drivers/secure/secure.c +6940e4242af969ec608caab6d93dd03364b78580 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.h +338871ee4d601414cf6ab0c718cb19938c37c7b5 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/pmu.c +4661321c301694bb1cfb029693c60d50387885d6 - arm-trusted-firmware/plat/rockchip/px30/drivers/pmu/plat_pmu_macros.S +4abb3f49d90cc7242ff9d366432f9423ed190c44 - arm-trusted-firmware/plat/rockchip/px30/include/plat_sip_calls.h +8b1c4b26a5cf109ec97a2bd711e46dc76c20891c - arm-trusted-firmware/plat/rockchip/px30/include/platform_def.h +be822c3b60a3f8f4215925d9c6aa8ff3d90ab56b - arm-trusted-firmware/plat/rockchip/px30/include/plat.ld.S +80988c6b4c1d5c128f556b4704d2a13dca1b94ac - arm-trusted-firmware/plat/rockchip/rk3399/plat_sip_calls.c +07fcff2e4785739f2818730be2df2798395d6dd0 - arm-trusted-firmware/plat/rockchip/rk3399/rk3399_def.h +f10fc723b4f781fa92f52d189e12ab2599f2be33 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.c +d6f6a92953b02dda92949d05699b4a8c09ec1ab6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/soc/soc.h +81bb90565c30ebb1d2a2074e665099c5df4b3f16 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.c +912b3ac53149ee0912cdc571503cbe6f5d9e5e31 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pwm/pwm.h +1a0ef7b5013eea98c8892cc73f9acf7aadc6542b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.c +cc96ce897ce3dfd398d571f73d60df020e312a7f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram.h +fde45271c5e9a03975a13a19aa58f7ce1627247b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.c +d4edbc276d8a41ceabeabd135ee44750077267fb - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.h +91fa17de464bf17060f5d782d3addc2d250f2bcf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dfs.h +341cf7780e76c0eed9bb587ced84821148eaeba4 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/dram_spec_timing.c +455f3ca45423a7d3a17a25fa9a199ee6f33accdf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.c +8bb28c62f323cba1149703071fa6c9cd723e7681 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dram/suspend.h +2f72933afb37b859ea9a98d233ab11f81301c9db - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/Makefile +98a096aced18ab4c9a4b3ab325773ed273acd4cd - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/addressmap.h +222366fd88fa37c34896b96be4724020febaf122 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/include/rk3399_mcu.h +3832f35bf0192ab6299ed6f72d97ea798c64ec01 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/dram.c +c651d2e10f915a285792aa7e66836e66a3fb3b68 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/startup.c +249a2bba707f4aae60e76e4d2ca07180426f3657 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/stopwatch.c +9cfa6b80558dac90724c830c7c2b792099232962 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/rk3399m0.ld.S +15ccafa1fb201c2bdc50eb32beb4d9331e95424b - arm-trusted-firmware/plat/rockchip/rk3399/drivers/m0/src/suspend.c +34cef331645617d77f27ee050065b2678b021605 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.h +12d0e498bcf7645b6d17eda0b6c88f9c68345720 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/secure/secure.c +0e0164a1fd25ccd71404f643551fc197b6d3545f - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.h +8af098c906ff4222b7fb1b8a8e528a842931e11a - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/cdn_dp.c +e4ba052fe71c1dbb0fd712a9e23751995fa17236 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/dp/hdcp.bin +1761d34cf2fa35e5eaf8e4707cde5f3fec7345ce - arm-trusted-firmware/plat/rockchip/rk3399/drivers/gpio/rk3399_gpio.c +a203f9155033bc4a154799d63ebe669baadb7c82 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu_fw.c +8080df60a96f3ccb59e64a8c4468c29298a40160 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.c +fdf96b7b34ebbd88b6c053c20c493dfcd5d2eec6 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/m0_ctl.h +26f96f6bfc5d8cd2811341eaa144693019daa5cf - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.h +21c19d18b927a98e453d2dd32fa075e1556c8d10 - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/pmu.c +4f34aa4fe829a116338b7c8cb363091b98b1df1c - arm-trusted-firmware/plat/rockchip/rk3399/drivers/pmu/plat_pmu_macros.S +735db5fedc39c83875dd50d345431e840a75ce95 - arm-trusted-firmware/plat/rockchip/rk3399/include/addressmap.h +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3399/include/plat_sip_calls.h +d037385198294976c392eaac15722c2bc43171e6 - arm-trusted-firmware/plat/rockchip/rk3399/include/platform_def.h +33691c33d59c3cbf5321efb5e9cf1ce6f908b1b3 - arm-trusted-firmware/plat/rockchip/rk3399/include/plat.ld.S +e27f9ab0eb7cc700bac4af81ef063675ddea3d16 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_regs.h +f61d8134dfdbc2de01b130177e3623bfc96e582b - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/dram_regs.h +514bb50a35bc277734414a501833d9cf9103b613 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/misc_regs.h +a3ec096942a7038a658d2de2da28c8d7772e2601 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/pmu_bits.h +dffb716056a5cfe4289bde5769bacd0a9c517467 - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/bl31_param.h +37de06dae36b2c9133dfa3db58b9403eca97534e - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/m0_param.h +d3a8c566b07530d947493f642a829c2173e7eb3c - arm-trusted-firmware/plat/rockchip/rk3399/include/shared/addressmap_shared.h +9eb41f0b086d93dd52f10cd88c871e9f872da485 - arm-trusted-firmware/plat/rockchip/rk3328/rk3328_def.h +aa37703bdb16d2d93c4cb6a1c3f5740f10400717 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.c +888b9ca7b2dca798b061df341269bb1bf0cdc6a2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/soc/soc.h +75d3fb351c1418d28d1be951921dde7cac623d53 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.h +d6fb6002e2f08bc736d1fbcfef5f7d518331e24a - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/pmu.c +74e69a5d06c7c10f8fd04052bfd92c89a6b685c2 - arm-trusted-firmware/plat/rockchip/rk3328/drivers/pmu/plat_pmu_macros.S +d0cf327dcd15f8fc85f2c3c93e82fd6199973f0b - arm-trusted-firmware/plat/rockchip/rk3328/include/platform_def.h +c03dbe37ab69ed71bbbc9100b47ff77d3c1f19e9 - arm-trusted-firmware/plat/rockchip/rk3328/include/plat.ld.S +524ab6d6a8a79e76857af71a8c36886929a16243 - arm-trusted-firmware/plat/rockchip/rk3288/plat_sip_calls.c +7d9851bfe1b3a6bff1b3fe3a5a42152bdbbdd641 - arm-trusted-firmware/plat/rockchip/rk3288/rk3288_def.h +408d92dc22d97bff7148a2338e91746328b4bb4f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.c +00a800ecdcad577d80ed2968cfee8abc2ff260d0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/soc/soc.h +70ecc34e2c4236edbd52a088d6dc72300d1038e0 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.h +90e4b5914845f3238bde4617bcf04acabfc52406 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/secure/secure.c +53d9e3936b39e758560745d492d1473ac9c98278 - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.h +bcf5a24d5d284bc2b87c3b5299a9f548df4bc95f - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/pmu.c +db1ef060ee221e9b61acbb781c42ed42e926b26e - arm-trusted-firmware/plat/rockchip/rk3288/drivers/pmu/plat_pmu_macros.S +0454e2aefd623a64760090a825f3cb0c26b0a3ca - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sip_calls.h +58f0ccc10fae70932566781c7c34457a239e027c - arm-trusted-firmware/plat/rockchip/rk3288/include/plat_sp_min.ld.S +0a2a001f434d83ab306c453b6d60f886a0b59a96 - arm-trusted-firmware/plat/rockchip/rk3288/include/platform_def.h +1321792bce42c44c3fed91fea86cceca52486ffa - arm-trusted-firmware/plat/rockchip/rk3288/include/shared/bl32_param.h +a5a361643c76bc6ad4e5bf4bef498e6de89c4065 - arm-trusted-firmware/plat/ti/k3/common/k3_gicv3.c +4677f1e48833ef10dc9d9ed492dfe849c8466b05 - arm-trusted-firmware/plat/ti/k3/common/k3_console.c +170634ac25c995303394743ee26ab4f2265800ca - arm-trusted-firmware/plat/ti/k3/common/k3_topology.c +96d874b239805cfedc0fadfd9f07eed0e423a919 - arm-trusted-firmware/plat/ti/k3/common/k3_helpers.S +55b3083cc472c5a3e1808d642b6c6516d19c34be - arm-trusted-firmware/plat/ti/k3/common/k3_psci.c +fd1bbe596ff44d2104431c2924e172d0ef4c5b34 - arm-trusted-firmware/plat/ti/k3/common/k3_bl31_setup.c +d3624f3dc097829d1b9f6b277bd1aebe77963d97 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.c +27b2ba24623a62aa30daea138411571e17aeb579 - arm-trusted-firmware/plat/ti/k3/common/drivers/sec_proxy/sec_proxy.h +55f8380907084a69006d5211123aef60fc51400d - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci_protocol.h +3ebfed887a97b672cad608bc064e08075f4e2a29 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.h +e81feb55a2328c2ec32fadd561eaf24eb58ae202 - arm-trusted-firmware/plat/ti/k3/common/drivers/ti_sci/ti_sci.c +da89ff4506058f3e90a127f4e7d79a7d86057bfd - arm-trusted-firmware/plat/ti/k3/include/plat_macros.S +015fe87701fa82cd48501c2915505c611e20e933 - arm-trusted-firmware/plat/ti/k3/include/k3_gicv3.h +33ec06e0674715932071745b37498c738414ee8f - arm-trusted-firmware/plat/ti/k3/include/platform_def.h +f2111ae0b834107dddf37cb4846a7065472db0fe - arm-trusted-firmware/plat/ti/k3/include/k3_console.h +c82ee96d8fb1841fd3068f489a697625a217aebe - arm-trusted-firmware/plat/ti/k3/board/lite/include/board_def.h +85bfc710f2f6c79b7c0e025f6f6e653d16f39bb7 - arm-trusted-firmware/plat/ti/k3/board/generic/include/board_def.h +3139c2b0c93ae17696224f59b5486f65e1649dc7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_gic.c +6a49ad3765ad1a5c42b66eea4f7aeed6c721fdc2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stm32image_def.h +c0910ed9fa547ff95728b0592ee3be13b3615d98 - arm-trusted-firmware/plat/st/stm32mp1/bl2_plat_setup.c +10b1e53e6d0c0b259d531d284d6b2f64978ff33d - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_boot_device.c +f171c1cd88d3ea2070a747ca519f7d6b9e8257f5 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_usb_dfu.c +743906eebddff48371349626564704fa54fcdd27 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.ld.S +dacc55b49253b5d86f120fe7e2ed1de0aaadadcc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_private.c +7b00ed042c247bac94b4766cb42dddc0e21764fc - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_scmi.c +4ee1c481f43d2f2b9798ffc1f9c6cafa4d1cc371 - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_stm32_mem_params_desc.c +c7727e6a5eb36a39432103f9641b5d1c522fb1a7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_def.h +77c94644e0ef95316e08e0a339fb16a856ae5d97 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_dbgmcu.c +9ad0a2f43f8a0c69c26073e06425579f59986e7b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_pm.c +e53bc6a3ed66be157fcca494d961241c4a067815 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_security.c +ec9fe0a8eec79fee1d3dd34bf1a969b8f0b93f4a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_shared_resources.c +82d557ad976b6dfd8dcdce69b68986e9be70cd5a - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1.S +0f0baced38fb65393cd300bdc024b68e707f5f4b - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_topology.c +b900c2f6ef836a0f77c00c851815a09220d8c5e3 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fconf_firewall.c +71c56ab2e235cc9495de74461f1e2035229c09c0 - arm-trusted-firmware/plat/st/stm32mp1/plat_image_load.c +d0b4272a97d261d88b6bff05bd2162e0d939ffbb - arm-trusted-firmware/plat/st/stm32mp1/plat_bl2_mem_params_desc.c +43753b990fdb953ffc38ef29474ef4af453444b7 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_stack_protector.c +3cdcc47dcc28c6e6de2c940df01b5c91d95af92c - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_helper.S +edb672bfa3c76059c60544793fb08658398cb3b2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_fip_def.h +58a5d9c283fcb21c6328e65dda44190d07fe6bb2 - arm-trusted-firmware/plat/st/stm32mp1/stm32mp1_syscfg.c +406790007d4d597b108faf9871360acfa7cdcf23 - arm-trusted-firmware/plat/st/stm32mp1/services/stm32mp1_svc_setup.c +89ab811529f632c51fa5e732be395bac1ea89887 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.c +3b882920ab056c9bbc38be63b2715e1d796109c4 - arm-trusted-firmware/plat/st/stm32mp1/services/bsec_svc.h +34bda94b3b92d9b971e0e52f26c98293f35800df - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_private.h +7eaf59b974175885a0dfccf0b42c774580444f92 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_smc.h +d12872b893bf8db2b51b7243dd638bf34e9d6cfa - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_dbgmcu.h +6d6391c62306978263be31d559221680ed9b6025 - arm-trusted-firmware/plat/st/stm32mp1/include/stm32mp1_shared_resources.h +0cbf680fead56b073a247b36589a06e814bf8995 - arm-trusted-firmware/plat/st/stm32mp1/include/boot_api.h +6a9fdf66f28b06f20ed4b08bed769e38d88e5995 - arm-trusted-firmware/plat/st/stm32mp1/include/platform_def.h +86477b53739886930268a20a1950ef8cb2a1c279 - arm-trusted-firmware/plat/st/stm32mp1/sp_min/sp_min_setup.c +ad3aca5d4f9af9d21c376f972399e2cbbb7102e8 - arm-trusted-firmware/plat/st/common/bl2_stm32_io_storage.c +46faa99b227394b11051186b86a163d67c081adc - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_usb.c +356f823bccc7081e026233c6fb511c0602208101 - arm-trusted-firmware/plat/st/common/usb_dfu.c +278442fbef0471df0addfc2b3ce1b10552541e65 - arm-trusted-firmware/plat/st/common/stm32cubeprogrammer_uart.c +0d0e487dbff201564fae2a5f2e0bc45059a3ad3d - arm-trusted-firmware/plat/st/common/stm32mp_common.c +79d69f4be6d9e1fc494884f41f92bede1b67c8ff - arm-trusted-firmware/plat/st/common/stm32mp_dt.c +a0bc3acc4ac585d95f9023d8859733edb1ff9c9a - arm-trusted-firmware/plat/st/common/stm32mp_auth.c +7a33a3419c93c0bbb21a2c8df792965674477cbf - arm-trusted-firmware/plat/st/common/bl2_io_storage.c +b6a6f8374d7f3eadc9cd9b6ad93f62ed12f6851f - arm-trusted-firmware/plat/st/common/stm32mp_fconf_io.c +2a0d6172df32ead3a019d2cbc33e260c3aeba294 - arm-trusted-firmware/plat/st/common/include/stm32mp_common.h +a48402444da4bcb7bce60d2e3f9972f07bebc8a4 - arm-trusted-firmware/plat/st/common/include/stm32mp_dt.h +8c442ea195baf9461f2165bae528286c5a71e7ca - arm-trusted-firmware/plat/st/common/include/stm32mp_io_storage.h +b270dbb723f5c002dbf393eb752ccb946afc5baf - arm-trusted-firmware/plat/st/common/include/stm32mp_shared_resources.h +4ca9fb0296b649411cecd45263ecadb41540d6e4 - arm-trusted-firmware/plat/st/common/include/stm32mp_fconf_getter.h +af93ef4188fb3950141bc4c2a6e971e965e5c071 - arm-trusted-firmware/plat/st/common/include/stm32mp_auth.h +1125720a4a5573b7f8197d2dabdf308f51407896 - arm-trusted-firmware/plat/st/common/include/stm32mp_efi.h +8bb1550cf77c8680e05ba46ad44ab77ff26bb8f3 - arm-trusted-firmware/plat/st/common/include/usb_dfu.h +dd7ae18098736e737a0482a59de65f64d5edd503 - arm-trusted-firmware/plat/st/common/include/stm32cubeprogrammer.h +08fffa1ca580eaca04a26cfc974edd901c2997b1 - arm-trusted-firmware/plat/arm/soc/common/soc_css_security.c +667de698f76e8d0b6d6f1b85f8012f3bed27e925 - arm-trusted-firmware/plat/arm/common/arm_ccn.c +9b812991736d46b06d462799a31eb49ffae96260 - arm-trusted-firmware/plat/arm/common/arm_gicv2.c +c3c969f538ef3f3853d867a2c9c020723e5adc66 - arm-trusted-firmware/plat/arm/common/arm_tzc_dmc500.c +1f2643d0dcc34c7b46895a5dd300de2674cc1274 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg_helpers.c +8d5a41b0cad025e83538d4508b8de54c96dd6be8 - arm-trusted-firmware/plat/arm/common/arm_pm.c +e460d7f371f1102e3c39114a43c606937f3c9f92 - arm-trusted-firmware/plat/arm/common/arm_common.c +9ac215f26148ab94b630463319c086d3e8b88c31 - arm-trusted-firmware/plat/arm/common/arm_bl2_el3_setup.c +e58481ddddf7e4632598a6ca543bfc9fcb6a7c48 - arm-trusted-firmware/plat/arm/common/arm_dyn_cfg.c +61b4b6215ec4cf4e050d7a14359bfdc2b64e2d8e - arm-trusted-firmware/plat/arm/common/arm_sip_svc.c +53d385569ada7ff06030853184930078d8a2e4d8 - arm-trusted-firmware/plat/arm/common/arm_cci.c +3b628c17fd98697338a0997a380df8a81c7d2e66 - arm-trusted-firmware/plat/arm/common/arm_bl2u_setup.c +bb20b499eb4fed681f076d21eeabaaf686b1c7fe - arm-trusted-firmware/plat/arm/common/arm_bl2_setup.c +abdb20c16e5bae6df0e447b4a356eb5b9ed3eda0 - arm-trusted-firmware/plat/arm/common/arm_bl1_fwu.c +d2c7c17798553c8d4e29f9b1bcad9e2754c97e6d - arm-trusted-firmware/plat/arm/common/arm_err.c +5f8fb896e304dbb204531641566de21b2e53a426 - arm-trusted-firmware/plat/arm/common/arm_tzc400.c +842368bd1a44c1ece633a1254dc3cdaa4983c6ae - arm-trusted-firmware/plat/arm/common/arm_topology.c +f2f3b9e0893c37d6ecae1332b3df925e9ab4d30f - arm-trusted-firmware/plat/arm/common/arm_console.c +70afb2dd0a66c2a2b6eb5bfaf16df448d90e029d - arm-trusted-firmware/plat/arm/common/arm_io_storage.c +420e2c07ae07c6152cc914a3b464ec17f2f92843 - arm-trusted-firmware/plat/arm/common/arm_bl31_setup.c +6e9da80beed8b267a6c15c88f8b25e81d8b7bda4 - arm-trusted-firmware/plat/arm/common/arm_bl1_setup.c +845db666afafcf708e365edd5461d9071f72c738 - arm-trusted-firmware/plat/arm/common/arm_gicv3.c +dd2c481628c54d07d905a85f08e527943473d31b - arm-trusted-firmware/plat/arm/common/arm_nor_psci_mem_protect.c +d663fd87f45498acaee1a4325d0e44e561dd102a - arm-trusted-firmware/plat/arm/common/arm_image_load.c +6ee204b0e2a5012ad4dcef1cfe9fe884590bfb8c - arm-trusted-firmware/plat/arm/common/aarch64/execution_state_switch.c +1177013eddcf476b6a6d1f3367ae319363663450 - arm-trusted-firmware/plat/arm/common/aarch64/arm_pauth.c +425d4b8c29564ce790babb9ea3fcc7ad80224fc6 - arm-trusted-firmware/plat/arm/common/aarch64/arm_bl2_mem_params_desc.c +cc6a2551546758984d250e491c5c077149044f98 - arm-trusted-firmware/plat/arm/common/aarch64/arm_helpers.S +8543903cea745c6c6709fd524622d3d5d3fd8df2 - arm-trusted-firmware/plat/arm/common/aarch64/arm_sdei.c +17e3af5dfebbe4a8933589c7b3c67e14faa7dc12 - arm-trusted-firmware/plat/arm/common/trp/arm_trp_setup.c +361186531a919bdc7825945fec639bf0db44800f - arm-trusted-firmware/plat/arm/common/fconf/fconf_nv_cntr_getter.c +dce55e77a6a4b9da7a42be37f5bba717d0c353e0 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sdei_getter.c +ac62b3ab6e132e1747dbd2ffd6f40a72b4270235 - arm-trusted-firmware/plat/arm/common/fconf/fconf_sec_intr_config.c +a666a9d920e0637f17e51eff519cc94c115b1ef7 - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_io.c +fc971d9e587662fd23f35aa2dfbf0abf23c9da74 - arm-trusted-firmware/plat/arm/common/fconf/fconf_ethosn_getter.c +3ddfbb8ae3448f315371d7a3a814bea1d055cd3a - arm-trusted-firmware/plat/arm/common/fconf/arm_fconf_sp.c +cacda44b3716b65a5c30eedd17ed5a1335b8597b - arm-trusted-firmware/plat/arm/common/tsp/arm_tsp_setup.c +43a64183c368a80bc24e370c93889989a49bfca3 - arm-trusted-firmware/plat/arm/common/aarch32/arm_bl2_mem_params_desc.c +8c6171b381cfc6eca906ce2f7e2e6658895380ca - arm-trusted-firmware/plat/arm/common/aarch32/arm_helpers.S +3237cf84bb44f0cc5b45b74d69d2934525543135 - arm-trusted-firmware/plat/arm/common/sp_min/arm_sp_min_setup.c +5072fa161b5fff3742a05eb8b9def551087be013 - arm-trusted-firmware/plat/arm/css/sgm/sgm_interconnect.c +bf1abf676327ef4b5c2fbe971bf5c59f9eea2511 - arm-trusted-firmware/plat/arm/css/sgm/sgm_security.c +6986ea7e2525388afa6171359d9f0c71de119e6e - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl1_setup.c +fc6ffe0f853fbf9871294d23c034cf4eb00a0b99 - arm-trusted-firmware/plat/arm/css/sgm/sgm_mmap_config.c +fb1634b97815fe2a2d9fcc807b394bdf1a034423 - arm-trusted-firmware/plat/arm/css/sgm/sgm_bl31_setup.c +408a01ed446d78cc578fa633ca47d7068ede3735 - arm-trusted-firmware/plat/arm/css/sgm/sgm_topology.c +6a32e8055bf1477d80b315a472542bc3c28106d5 - arm-trusted-firmware/plat/arm/css/sgm/sgm_plat_config.c +d55a2717a5f47927531e46527bd40fb912dd16f2 - arm-trusted-firmware/plat/arm/css/sgm/aarch64/css_sgm_helpers.S +883fce52c6e023b9718833ef01eff53d740f4b22 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_plat_config.h +21772c91952bd2813284b444505fc85183bed867 - arm-trusted-firmware/plat/arm/css/sgm/include/plat_macros.S +c9020cce76399dabf8d4bf04257761ee38ea4d60 - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_variant.h +6c95a3344c3a15036b1db884d62a972e802699ed - arm-trusted-firmware/plat/arm/css/sgm/include/sgm_base_platform_def.h +00d4810ce12b4356434c80bbf98203811ee07a32 - arm-trusted-firmware/plat/arm/css/sgm/fdts/sgm_tb_fw_config.dts +5e82b47a941edb5ba37196b7aefe2a54e3bd2f81 - arm-trusted-firmware/plat/arm/css/sgm/tsp/sgm_tsp_setup.c +da446db6b40b974a31d66ba55f23047f28d3f748 - arm-trusted-firmware/plat/arm/css/sgi/sgi_interconnect.c +a12ad9fe2e578f1c9186976a41033a398307aba6 - arm-trusted-firmware/plat/arm/css/sgi/sgi_ras.c +5c168081100ace91d38be064d9d21551630d21c0 - arm-trusted-firmware/plat/arm/css/sgi/sgi_image_load.c +c6341f0f666b8a901520e32310b18a323af9f925 - arm-trusted-firmware/plat/arm/css/sgi/sgi_topology.c +31824343e1235090b12b73c827b8cbf02ba4d0e4 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat_v2.c +7a79c4c409726322831974860de49b71547d6feb - arm-trusted-firmware/plat/arm/css/sgi/sgi_bl31_setup.c +b33a69c22fcc5e0d8abd886b78b557633834d721 - arm-trusted-firmware/plat/arm/css/sgi/sgi_plat.c +aeb8a1b51452a7c1b9088cd2cc5f0c6ab2590b45 - arm-trusted-firmware/plat/arm/css/sgi/aarch64/sgi_helper.S +b30c67527c7802085733426c8c113a7ab2492ce8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_plat.h +3bb8192919eea022c0cfa99a7d87f8ecd4588256 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_base_platform_def.h +468e61508695c6dc9df856865e295b59c32a54e3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def.h +b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/css/sgi/include/plat_macros.S +f340bb1f1f4dcfde1ab65f3d67e26a33025f37a6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_sdei.h +5972e7acb9e93b201406ff9cf0cbab522f942eb3 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_ras.h +4e4ddcdd110f807b8dcbd6b440a4b4f5c2f9e83b - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_variant.h +c388d0822e5ef0bf97db4c66ab46d4088421f0e6 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_dmc620_tzc_regions.h +7617a0e9164a7f90465861eedd913dabf15379f8 - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_css_def_v2.h +138c1bc36bb3c91d2b2d9f5ac1702aa0975c850c - arm-trusted-firmware/plat/arm/css/sgi/include/sgi_soc_platform_def_v2.h +f00b456e46701cc6a1e2b31fdd93091805ab0809 - arm-trusted-firmware/plat/arm/css/common/css_bl1_setup.c +3bc7caa521ce87bd672c20940f330d81613afdc1 - arm-trusted-firmware/plat/arm/css/common/css_topology.c +75cc05419580aa9e613157ed0cacf5e0447c7d7b - arm-trusted-firmware/plat/arm/css/common/css_bl2u_setup.c +c788e65cad1a1e84654d127315052a3bcbd35225 - arm-trusted-firmware/plat/arm/css/common/css_pm.c +e35946648a3f4e38af67096b19e7cbe49324a3e2 - arm-trusted-firmware/plat/arm/css/common/css_bl2_setup.c +3ddcf64aa2f7a53edf4016ea4d4c636a371f4516 - arm-trusted-firmware/plat/arm/css/common/aarch64/css_helpers.S +29476751ce928c5170b93c840f4fd925619fb9f9 - arm-trusted-firmware/plat/arm/css/common/aarch32/css_helpers.S +795d97596b09631253539c8a66fa49d5d422d01d - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_topology.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_trusted_boot.c +3693a7e757b2541552b2c91c91a0dba2d6a0a8de - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_security.c +73d0e620495671f0ffa9cfdd536e8f3c97f6e384 - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_err.c +1cc6a4959dd00202735100b426201a00f18764ec - arm-trusted-firmware/plat/arm/board/rdn2/rdn2_plat.c +f8bee970c03b0a4da0d79dcc8895e970ff34ffa1 - arm-trusted-firmware/plat/arm/board/rdn2/include/platform_def.h +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_fw_config.dts +ed25350e5c803bac231eea3f950d3e7e5aee01d2 - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdn2/fdts/rdn2_tb_fw_config.dts +e12be214b71705c426b59f867e2c1e12d74eb660 - arm-trusted-firmware/plat/arm/board/tc/tc_topology.c +ded1714043a17b1985c18754683ddcc8a2954d2a - arm-trusted-firmware/plat/arm/board/tc/tc_bl2_setup.c +4335b9a6f68fb49824b223397621a29f3d1030c9 - arm-trusted-firmware/plat/arm/board/tc/tc_interconnect.c +868cf0c3ac2a02db664b5bb1dc788646d79823a0 - arm-trusted-firmware/plat/arm/board/tc/tc_plat.c +ae19b2b5534ecfc11125374e36d9e8f859a89eda - arm-trusted-firmware/plat/arm/board/tc/tc_security.c +1f68f4b41cf660f6aecbd9c91cffd25b5da791a9 - arm-trusted-firmware/plat/arm/board/tc/tc_err.c +e359fea3cdefe52d1384eaf4e3657d1a8639ce5c - arm-trusted-firmware/plat/arm/board/tc/tc_trusted_boot.c +28488a6123a3f6e963e45167297c24b033c4ea20 - arm-trusted-firmware/plat/arm/board/tc/tc_bl31_setup.c +8ad72d03b3ba43d1683a1303fee28ea1c7be281d - arm-trusted-firmware/plat/arm/board/tc/include/tc_helpers.S +12e15891d91866e073604872dd843da7a55ab1ca - arm-trusted-firmware/plat/arm/board/tc/include/plat_macros.S +9660ea0d565256c4b8a124a3b15c393be1d5f9b0 - arm-trusted-firmware/plat/arm/board/tc/include/tc_plat.h +fbb9a21e701abf6a427a0a7a4f52bdfac2d65ae5 - arm-trusted-firmware/plat/arm/board/tc/include/platform_def.h +46c4eb5b1105e6fcf9a5ebc8bb219b4f6250ef79 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_fw_config.dts +6d8e682b0e92f3c4b0317af9db0cf378942f0637 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_optee_sp_manifest.dts +dd7dfe59caab52d2698deda4e52c6508f481ea7a - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_spmc_manifest.dts +b6a0718fcdad5e07263ed41c89641a47d843eb14 - arm-trusted-firmware/plat/arm/board/tc/fdts/tc_tb_fw_config.dts +ae7769a5c9c26af057b45ea638e7d3e8f7905d63 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_err.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgm775/sgm775_trusted_boot.c +20df07965dd541c0c14b55f71c827c0b992b608c - arm-trusted-firmware/plat/arm/board/sgm775/include/platform_def.h +673d2aca63b2cddcb1fc087b3849b8459c60178a - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgm775/fdts/sgm775_tb_fw_config.dts +0edacdd0dc4a2af6f50c21ccdf98244fe72c6730 - arm-trusted-firmware/plat/arm/board/common/board_arm_trusted_boot.c +885dbc360b97a82697b2978ae8f5665ba4878080 - arm-trusted-firmware/plat/arm/board/common/aarch64/board_arm_helpers.S +f63762c7a16038a4bc3a046a89d815cf9ae9089b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_rsa.pem +b48500f3591ea941f29e3cb482855cd947d886c3 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa_sha256.bin +99b2edcf01ed68e8e25f2687d31ef61f0531f26f - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa.der +2b0cf90adf32af769b93e85764f195737286be65 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_rsa_sha256.bin +c4cd605f9796351468c8e3427ec60a3ab5966a93 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_dev_rotpk.S +b22a3e04b7c492d96f48978250bd02b1de04304b - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotpk_ecdsa.der +64194de14ee2424df1ca72d388c407f3d0c16184 - arm-trusted-firmware/plat/arm/board/common/rotpk/arm_rotprivk_ecdsa.pem +aa5febfe9cf8a923785e2509c54c7e03032167e7 - arm-trusted-firmware/plat/arm/board/common/protpk/README +ce90ae54534188e8ed455e84da4ee7656807dc45 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_dev_protpk.S +a819075a49fd85dede74b56ddededf2f4c046f07 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protprivk_rsa.pem +cdb90754cb9118d6571aad9c3846b2c410f708d1 - arm-trusted-firmware/plat/arm/board/common/protpk/arm_protpk_rsa_sha256.bin +d7941a7e9ec8fa11c4dd7580b57e1543e335d61b - arm-trusted-firmware/plat/arm/board/common/aarch32/board_arm_helpers.S +0b886935846ab1d278829932851b6cc492f106cc - arm-trusted-firmware/plat/arm/board/juno/juno_bl31_setup.c +53c5a79a63bf1f5551016da97e29bf8702e32ad3 - arm-trusted-firmware/plat/arm/board/juno/juno_def.h +ebbb9c3ccbc5ea001a213d0ba5a9b7744bd561dc - arm-trusted-firmware/plat/arm/board/juno/juno_tzmp1_def.h +6cea3743018f1d02cac51c8d78a92561ea46ce14 - arm-trusted-firmware/plat/arm/board/juno/juno_bl2_setup.c +49553a7fbab54730a1b3de994aa92810c35025da - arm-trusted-firmware/plat/arm/board/juno/jmptbl.i +d784833f267d4a24f2a529767e8892a4aa11df9d - arm-trusted-firmware/plat/arm/board/juno/juno_common.c +905aac590f6fdf10096fd3e0f4bb661a2953acfb - arm-trusted-firmware/plat/arm/board/juno/juno_bl1_setup.c +8a5716ff7852804effaf5810a335e69d3a788a50 - arm-trusted-firmware/plat/arm/board/juno/juno_trng.c +07f098d234d16533d40b505e91dbb1aae1712650 - arm-trusted-firmware/plat/arm/board/juno/juno_security.c +17d854b860806d6ad8af6ee63952524a3bcbd9e9 - arm-trusted-firmware/plat/arm/board/juno/juno_pm.c +419b6382a2607911be10024a6287e69289234326 - arm-trusted-firmware/plat/arm/board/juno/juno_topology.c +0ff3d7a6c51d9752cc2a86bb19e800a94245eea2 - arm-trusted-firmware/plat/arm/board/juno/juno_stack_protector.c +bef868e2dcb239da5ba7d1787c2f790e1f31d33a - arm-trusted-firmware/plat/arm/board/juno/juno_err.c +50963e02933b9165b4b2c2a4b8ce7f8cc758df7d - arm-trusted-firmware/plat/arm/board/juno/juno_trusted_boot.c +4780ddabb988fa673f07503011a00242d2ea9faa - arm-trusted-firmware/plat/arm/board/juno/aarch64/juno_helpers.S +53f8c45c8436fb9bb4378cd8782a0b7d8037e5d2 - arm-trusted-firmware/plat/arm/board/juno/include/plat_macros.S +821681f18e15e60a3d540f06924deb6c691c2d7b - arm-trusted-firmware/plat/arm/board/juno/include/platform_def.h +dfc9edcda0daf49b40451e94c30405aa901ef204 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_fw_config.dts +805360ecd38e071b1f2e9b60704130be813557e2 - arm-trusted-firmware/plat/arm/board/juno/fdts/juno_tb_fw_config.dts +319dfb0515299119770970eb5953825ab7abd95c - arm-trusted-firmware/plat/arm/board/juno/aarch32/juno_helpers.S +e3d086dd3e36ff5fd58f3282c011f6394739185c - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_def.h +4497a7586471f072a94ff5a066931c86dcb6fd2d - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_security.c +e902fc33536870bb2460962782828919e301f53a - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_plat.c +7d80d6700188f44364662e46113af9036afedcbc - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_topology.c +7104250da7bca258ddb0bf081570d32f8900092b - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_interconnect.c +5a64604c368489c4585ba4e01e129b3687e5d8ff - arm-trusted-firmware/plat/arm/board/n1sdp/n1sdp_bl31_setup.c +4b16feb977654bc82a89a104dc5b31b167bf17d1 - arm-trusted-firmware/plat/arm/board/n1sdp/aarch64/n1sdp_helper.S +b45c063aa1fdf9280c52020500ae6e83d71244c5 - arm-trusted-firmware/plat/arm/board/n1sdp/include/plat_macros.S +eaeab6f905d711a8fa04d0ce9d2c2ec485934eaf - arm-trusted-firmware/plat/arm/board/n1sdp/include/platform_def.h +af1f8d5af2ee91ba0dd180c42a7b8f73b7543474 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_security.c +6733f3383940d86208b8239c1d08d9221c2c2929 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_common.c +a924444b8053fdd6d907961d26d25ef0d3a207f7 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_topology.c +300e69aa5df2f362bc3ddf1c430fe3fab03f11da - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_def.h +4a175994a02eeb79a8ccc76f0b3be5ac2d45771d - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_private.h +b0261bd454617bc33a79aa98dcfa987149992300 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl1_setup.c +87d9fc22d1228a7faf0c17443f9d5afd194e4334 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_err.c +b370460e14d8e464d9f852b0e3f18cf2dca4950b - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_pm.c +103c2c1d17da9dfaab63bca2f61e6bd21aa82c19 - arm-trusted-firmware/plat/arm/board/fvp_ve/fvp_ve_bl2_setup.c +19f1b6fffc9b7e4d8a55730d5dc6740b06415c71 - arm-trusted-firmware/plat/arm/board/fvp_ve/include/platform_def.h +996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_tb_fw_config.dts +a857b4f74c6a05502271795dcd7a71f24a024b41 - arm-trusted-firmware/plat/arm/board/fvp_ve/fdts/fvp_ve_fw_config.dts +2ff5ebca71b32318bae21e3dbb7699236b9cbe61 - arm-trusted-firmware/plat/arm/board/fvp_ve/aarch32/fvp_ve_helpers.S +d56cac77b62eee0ed50166d2264e0a00c8fe4ffa - arm-trusted-firmware/plat/arm/board/fvp_ve/sp_min/fvp_ve_sp_min_setup.c +cdf2af8fe7e5ba8b9ff36e04a33ebff2cf20f79b - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl2_setup.c +007839db0f0e5c02b3362ce770b02771a47faa27 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_topology.c +f2a71185ac9189cbe4310e27a7ead8d40c23c377 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_pm.c +c8bea252a67bd4f3ad0910e3dadd0b76dc62c7f3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_private.h +7d714f8f2b3f7274c9d2e73eaa5d46215c7d3911 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_err.c +be0cd4f5f48b5eb3a64885536643645036173809 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_common.c +c6fdde231ff1fe0ddb8f585bd3fead2a7f2f0f46 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_security.c +fabc6650d0d7860d4d615e5e997c72bed71aecb3 - arm-trusted-firmware/plat/arm/board/a5ds/a5ds_bl1_setup.c +189ef1e9d436f631711b2a4bd2e75efb635a322a - arm-trusted-firmware/plat/arm/board/a5ds/include/platform_def.h +996afef966d673534a7502180616ba362cdb0d9c - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_tb_fw_config.dts +adc821bdac8aebcefb26e3f8cd54497b3b8dfab4 - arm-trusted-firmware/plat/arm/board/a5ds/fdts/a5ds_fw_config.dts +142d4bce7860550461e2498ba8c9f4ebb17d902d - arm-trusted-firmware/plat/arm/board/a5ds/aarch32/a5ds_helpers.S +a8eb0724c2056ed80453ea31aa3ebc822e93ffa2 - arm-trusted-firmware/plat/arm/board/a5ds/sp_min/a5ds_sp_min_setup.c +b20640f66687a9edf5c361b2cf32bf1244777ecd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_context_mgmt.c +181e66fa9c41732917a323ee0fe465da3b5ce36d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_stack_protector.c +efd5139ee502cdc5570d9ec338ee84b3410067fd - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_misc_helpers.S +e985480b9d1aa1426a500f3c4869a1f32bb8b422 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_io_storage.c +860f2b3b1633322a3865add4e226f457c1a7237d - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_exceptions.S +93cd93fd9277603c0a72cf1c730d6486a6247262 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_setup.c +b5fe2445bbd4cfd3d360d2d930d9358c4eed5555 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_trusted_boot.c +5f78d5ae0c4547371279bfc19196f01fb454e3b6 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_arch_setup.c +2ce9cd0a5ef399a537316089ff1451da165bdd42 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_entrypoint.S +1f85fcf3a3d2c0bd5a8c5e848a4841400b54f9fe - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_private.h +486d3021b7aeeb557efb82cafa7337d3d3041fb7 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_bl1_main.c +8e7bab3de835fbccc87f8d20b8acecc011d4fcaa - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_debug.S +b1777d180724d85711393cf136ad5b34e80ce86a - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_def.h +deb3a6a31fba479e597c0ae722532692996e2372 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_common.c +db240cab0da9aaf6298ede4c8418abd28744a258 - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_err.c +61fa6bbfd2f41f1cc6fe1c4caacb1fa09461692c - arm-trusted-firmware/plat/arm/board/fvp_r/fvp_r_helpers.S +e9c7e8c62f6a1ac8f4b8f79ebb080765f9244fbe - arm-trusted-firmware/plat/arm/board/fvp_r/include/fvp_r_arch_helpers.h +5356ccdf1172f23b213522e8c204e511fd9b8841 - arm-trusted-firmware/plat/arm/board/fvp_r/include/platform_def.h +1c209493074be7ae85b1aafe237784f10e2b7093 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_topology.c +daecdf40f28b13596b217b424164a59b35baa192 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_plat.c +07a42e98f0211f264decd0d40369a5a22999a7a4 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_err.c +39dd88b06678aa7f03906487a206a758c69bb621 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_security.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1/rdv1_trusted_boot.c +5a4591bc131dd662dddfaa201c233dc2e6f0a9a0 - arm-trusted-firmware/plat/arm/board/rdv1/include/platform_def.h +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_fw_config.dts +4eee465e298e33cc2776504ed671b987022fb333 - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1/fdts/rdv1_tb_fw_config.dts +3d1a55d785180dd11beb8473207268d04543695a - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_helpers.S +ed51f976efc9644368dd64840ed3d158c086650e - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_stack_protector.c +90dbd482aecd4e6be49f62fed93a4b38e4d79784 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_plat.c +df9742f665da99900fe4a3fdc0b6fbcc02209a0f - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_pm.c +8908fa02b1140f0d45e9bdcc3d5552190eb3af41 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_security.c +5f0ac09b373c85fd1d635fb4f06ea45011389b19 - arm-trusted-firmware/plat/arm/board/corstone700/common/corstone700_topology.c +688520959b3077ac47e6c17fd87614f5400ec96f - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.c +9f9f59bab890a50e0444edf12481248060aa9c1b - arm-trusted-firmware/plat/arm/board/corstone700/common/drivers/mhu/mhu.h +3c1fd619c9a1da90f7af84b9c6e1b8eceb5e7a20 - arm-trusted-firmware/plat/arm/board/corstone700/common/include/platform_def.h +d2cf1d7868d3a048734caa91b018fb43f56c36dd - arm-trusted-firmware/plat/arm/board/corstone700/sp_min/corstone700_sp_min_setup.c +bb5bde77d451942a4effe8cd36463c1dfc1df462 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_plat.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_trusted_boot.c +4e3d6ef9cbb8925d20f8946cbf6f998ea3c4eb8f - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_err.c +79e40d92dcde7f9d17195a4a63d0608730af9c4b - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_topology.c +aa3d4b5a511124fc6ae5cd9244633af5ae0ab4a9 - arm-trusted-firmware/plat/arm/board/rde1edge/rde1edge_security.c +7be90ba89049185165cc3d60d523a66fd7a1a0bf - arm-trusted-firmware/plat/arm/board/rde1edge/include/platform_def.h +e5b638c1ab3d0ee37ca9b8702ee4262358c3559b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_fw_config.dts +0397a242841f6193faacaba41c8326032a1e7729 - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_tb_fw_config.dts +1477905828689906107808c1098cccb0a22dc73b - arm-trusted-firmware/plat/arm/board/rde1edge/fdts/rde1edge_nt_fw_config.dts +d4a49ec110e03192903aeabeae1df36bca1cae8a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_plat.c +3f70fab8ee8fcd7926df2c977d9380f53cbbb9f6 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_security.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_trusted_boot.c +04538cf26382d09d8e2c07c0b46f13a5b099236a - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_topology.c +584cb4b05aeec673c6c04da7c3885037b079afa4 - arm-trusted-firmware/plat/arm/board/rdv1mc/rdv1mc_err.c +05ecf6ab819a6a6ca826e872d3c1fa6a21c7e7ef - arm-trusted-firmware/plat/arm/board/rdv1mc/include/platform_def.h +c139b0b044ff0f3122d7f6e5b65703bc3fbee8d2 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_nt_fw_config.dts +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_tb_fw_config.dts +3fa6109549ac24e3e9727ec6cfc9c34111cf53c9 - arm-trusted-firmware/plat/arm/board/rdv1mc/fdts/rdv1mc_fw_config.dts +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_trusted_boot.c +95aa905a5aa0734b8993eaf65aa91924c6ba1ccd - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_topology.c +3aff6d693c63d2b2dc58205e075552c4f14e24c2 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_security.c +e717578fd539b138146efa385134192a8aa4055c - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_plat.c +4bcbaa1f0a092433b2d017ed4941be94943fa552 - arm-trusted-firmware/plat/arm/board/sgi575/sgi575_err.c +127adaf6d9d5f7353a1893a6f2904417a96def85 - arm-trusted-firmware/plat/arm/board/sgi575/include/platform_def.h +77c37592e064ebc47319196a2468d4a75a6ff7de - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_tb_fw_config.dts +a19b040188761f8bccb0937f9f397e3b191c143e - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_nt_fw_config.dts +9f8fd7d90d63ffe6d71473664ec09b7aa4cdf607 - arm-trusted-firmware/plat/arm/board/sgi575/fdts/sgi575_fw_config.dts +0e3644e6d15833cfd15ee928af181e156ec27e8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_trusted_boot.c +810d8a4c9a7dff63b504d43fa4691f19cdf86b3b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_bl2_mem_params_desc.c +fbb932100f4228bb8fe153a58d84898837188f8b - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_err.c +b9f80852b169e9c137876fadebe0782792162fe4 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_security.c +dd206cc4d7ea74d0dcace11dc6c64faf0d687b8a - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_plat.c +c10b97a1764fe4c02c0a7ae81b0a75313edeed05 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_helpers.S +5562bd387d6506e0db4a62fe23b24cd1c5046754 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_stack_protector.c +7bc7cf637e9751cbed26e48c65722c070a0f9d36 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_pm.c +1e7fe4ccc25d366dfe5f6a14851dab68001bdb13 - arm-trusted-firmware/plat/arm/board/corstone1000/common/corstone1000_topology.c +a5086b67555acbdb3f4c3b25f837cbb372b0102a - arm-trusted-firmware/plat/arm/board/corstone1000/common/include/platform_def.h +16e3686521725b2e8cf355c2d990811fc260a02c - arm-trusted-firmware/plat/arm/board/corstone1000/common/fdts/corstone1000_spmc_manifest.dts +70913ecf05a6e846d99d63213b643de746a371e8 - arm-trusted-firmware/plat/arm/board/corstone1000/include/plat_macros.S +86c2465abfadc0a5dfe9b561b0f5675db8fee013 - arm-trusted-firmware/plat/arm/board/fvp/fvp_stack_protector.c +39be04c7a0d7f7559902b8813b1ded035b592985 - arm-trusted-firmware/plat/arm/board/fvp/fvp_gicv3.c +19591a34444effbe25bc3245bb68e6462bda0024 - arm-trusted-firmware/plat/arm/board/fvp/fvp_pm.c +1570105ddfc280d36e64641b556bc2da9a0529dc - arm-trusted-firmware/plat/arm/board/fvp/fvp_security.c +10c7154aeb64129154f13657841ad8f9aee6af85 - arm-trusted-firmware/plat/arm/board/fvp/fvp_trusted_boot.c +a6d08d07ea1ba1184a912ed5ef6a6287291ff743 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_setup.c +b4b38f929ba25c093b95fc92938eb9b58213a4b8 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_measured_boot.c +a1e4c883f6912bad1724268901a148f96250854a - arm-trusted-firmware/plat/arm/board/fvp/fvp_realm_attest_key.c +fa75b4ccee6e6d8604b819da30a1ed892db70b15 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl1_setup.c +87220bf30d58a155c2f10f38418d094db212e5b6 - arm-trusted-firmware/plat/arm/board/fvp/fvp_private.h +df0b10a5b65cf57a485f5eb846e0cfa7e64c429b - arm-trusted-firmware/plat/arm/board/fvp/fvp_io_storage.c +d25e9c719859733739581faecd38cfa80443aa83 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_measured_boot.c +71418933f8bb76fa971723d4cb9bc6748a009f33 - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2_el3_setup.c +d62b302ac0bf1976ed0084160aeba061e325a6c3 - arm-trusted-firmware/plat/arm/board/fvp/fvp_plat_attest_token.c +a3147836e6e11bb9b651753fee98a99b2f81062b - arm-trusted-firmware/plat/arm/board/fvp/fvp_common.c +394a425b1d229fbbad1173c1371edc737857d5f2 - arm-trusted-firmware/plat/arm/board/fvp/jmptbl.i +0c3494f4c7e2590865b69abf91d4b49be1ea469d - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl31_setup.c +20e8179e5c61147fc2d627dbb503babac430603c - arm-trusted-firmware/plat/arm/board/fvp/fvp_def.h +6f76c4d8ae1abb640a62785bfc535bcb485f9511 - arm-trusted-firmware/plat/arm/board/fvp/fvp_topology.c +aed35e7aa732be73eef26face244c3acdee67640 - arm-trusted-firmware/plat/arm/board/fvp/fvp_console.c +223e1339e343160feab72cff7621103ada50dbc9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_common_measured_boot.c +1924351967826f1ad9898254b30419ba2e7fb9cc - arm-trusted-firmware/plat/arm/board/fvp/fvp_bl2u_setup.c +0a86ad28b6ae96f93bdbcc32be32335d3e8250e9 - arm-trusted-firmware/plat/arm/board/fvp/fvp_err.c +d5a6187ffa8ab68518e9d896c2d50bbf600d68cd - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_helpers.S +3f4bcd29ccbf7cd09dfe8275846469b38db62e2f - arm-trusted-firmware/plat/arm/board/fvp/aarch64/fvp_ras.c +83e404fdd5bc4dda0b68b92d365d6e9b047f13d3 - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_nt_config_getter.c +10fc5531e7b7d5ac9ffba191f525b64179843eae - arm-trusted-firmware/plat/arm/board/fvp/fconf/fconf_hw_config_getter.c +84180022623ad574044b9436e62202ee5635c6ae - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_hw_config_getter.h +aed581dcf8acf86f277ecf028cc1eec4f0c081fc - arm-trusted-firmware/plat/arm/board/fvp/include/plat_macros.S +12b7439bee5ead5da71eb5a42a9c5cc493f9c7fc - arm-trusted-firmware/plat/arm/board/fvp/include/fvp_critical_data.h +aaff5cd1241ce58ab9627da89fb4860390a0864b - arm-trusted-firmware/plat/arm/board/fvp/include/fconf_nt_config_getter.h +c7af81d092cd74c1eba0402a02368b53f801c235 - arm-trusted-firmware/plat/arm/board/fvp/include/platform_def.h +1f6772f1b9358e6acc890bc4475a57f68cebc72d - arm-trusted-firmware/plat/arm/board/fvp/include/plat.ld.S +df9f20c998402fb612824aeec7d618e97e023cb8 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_optee_sp_manifest.dts +7dd67253d1f53292fbdd750b1360cace93220e02 - arm-trusted-firmware/plat/arm/board/fvp/fdts/optee_sp_manifest.dts +aba68daa32f394274fa0c7b3ebb2d77514e105da - arm-trusted-firmware/plat/arm/board/fvp/fdts/event_log.dtsi +33a1a8c0c5e1f8f806d0dbe69adab509f55301be - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_nt_fw_config.dts +5601a00daf6c8ba481f1addc03652d97efe84a3c - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_soc_fw_config.dts +b8ba7eb0ce440dedebafa08a9e3ffde066832d0a - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_fw_config.dts +b1406e98f75e782442a0fdfe50c8aad26cf5aeb5 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_spmc_manifest.dts +26761d08528feec31bb15a854b65dd46629135fe - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tsp_fw_config.dts +43a2362473fca426e3a62517552c20c2a629a563 - arm-trusted-firmware/plat/arm/board/fvp/fdts/fvp_tb_fw_config.dts +b59b8589b390aaea5c26a9621713fe3d78e47e8b - arm-trusted-firmware/plat/arm/board/fvp/tsp/fvp_tsp_setup.c +2c7ccf1e47b4fdac9dc7745e506f4194cce2e498 - arm-trusted-firmware/plat/arm/board/fvp/aarch32/fvp_helpers.S +6adce62f756dc0792fb3a4d6aa6cec60e0b54117 - arm-trusted-firmware/plat/arm/board/fvp/sp_min/fvp_sp_min_setup.c +561594e99d3e16d7826006d518e141e9a58eadec - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_security.c +ba9b8a6b4b36804eb8c8aee5b17845c85db8a845 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_plat.c +851570d1add4283d5a01ff4893f1558decb2d6e9 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_topology.c +7d37a6f29bbe666c9db7538d4d7a123d1ab40b17 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_err.c +866a21334d0661b2dde96c9ea5c2e2c99e649ab3 - arm-trusted-firmware/plat/arm/board/rdn1edge/rdn1edge_trusted_boot.c +97f84a745ae8fccb804dc7e0ba50b85d46ed4198 - arm-trusted-firmware/plat/arm/board/rdn1edge/include/platform_def.h +5d0744ed59fc75ba7204d9d0083fbc0cd64e74d6 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_fw_config.dts +869fa43b401d5d394651f9d1bd9eb784b7ebb14d - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_tb_fw_config.dts +a87583e95c695a2bf6af550cd6fbbffb3eae3961 - arm-trusted-firmware/plat/arm/board/rdn1edge/fdts/rdn1edge_nt_fw_config.dts +d115cd145587e366c9c6d02d47cc7ea610f7791f - arm-trusted-firmware/plat/arm/board/morello/morello_security.c +c855687b5adb537f1a56e37496a708864bd72650 - arm-trusted-firmware/plat/arm/board/morello/morello_bl1_setup.c +275ff8fd1cb66a02cc8ca9b9494035d3aa7f8ebf - arm-trusted-firmware/plat/arm/board/morello/morello_image_load.c +59b5177c9b302f117bea58642d758d747224eaed - arm-trusted-firmware/plat/arm/board/morello/morello_interconnect.c +ab6ec67031b519490edd2bdd7efb973f91af2453 - arm-trusted-firmware/plat/arm/board/morello/morello_bl31_setup.c +846d7f92ffe6c368d0d0b85ffa36409b0dd04caf - arm-trusted-firmware/plat/arm/board/morello/morello_trusted_boot.c +021dca0ec2928f72c45e98a602338d8a2bb08cc2 - arm-trusted-firmware/plat/arm/board/morello/morello_err.c +710e4ce5fe08ed123d1977361a4bbf49dff07ba9 - arm-trusted-firmware/plat/arm/board/morello/morello_def.h +eae232f83e8fef4997f24f4cce1d598178a8eab0 - arm-trusted-firmware/plat/arm/board/morello/morello_plat.c +9e616a8e89120ae9b614d9bae16f0de9aa886778 - arm-trusted-firmware/plat/arm/board/morello/morello_bl2_setup.c +0105670429d8a205bc698cf69de09044501a55a1 - arm-trusted-firmware/plat/arm/board/morello/morello_topology.c +1c3ff5d4d35a2aa211380dea2b252236f3dae0b1 - arm-trusted-firmware/plat/arm/board/morello/aarch64/morello_helper.S +5361abb465b0253014c38facafec374dd284699a - arm-trusted-firmware/plat/arm/board/morello/include/plat_macros.S +e1eb7e2194a62fcfa63e0d92da3567386d98a24d - arm-trusted-firmware/plat/arm/board/morello/include/platform_def.h +a95b1476c52a6213400f2402811d15e5d82d7d83 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_tb_fw_config.dts +bf30791c97940cf78bee90bb458a53b2480a4154 - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_nt_fw_config.dts +9c4c899115425303ba08c836c2a6ca740418160b - arm-trusted-firmware/plat/arm/board/morello/fdts/morello_fw_config.dts +0ca4a4d2749cd227831e57d361b8c16ee0f3cf03 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_gicv3.c +ef779e5f985f2ebef6d66a83442695603c463465 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_def.h +bdf16498e248d1d87d012aca5001940fb8328395 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_private.h +15269f87cab6dfa65ce9cbaacbb13ee9cf2af583 - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_pm.c +86553039cac69d2003776608e4a3172af5f6263d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_console.c +1cfbd3237d5138875eda5a3f57ebd08f452c4992 - arm-trusted-firmware/plat/arm/board/arm_fpga/kernel_trampoline.S +70fd1afdd7b31d55ddd95d7018ba66095315083e - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_topology.c +89a8aeb02e2a9467d783383e96d830647443b99d - arm-trusted-firmware/plat/arm/board/arm_fpga/fpga_bl31_setup.c +78391ad4c170cb70d2db6ad5639108f4f6020dc6 - arm-trusted-firmware/plat/arm/board/arm_fpga/rom_trampoline.S +fe445cbd11196fc3c69cdcbc6be5cdbc4354026b - arm-trusted-firmware/plat/arm/board/arm_fpga/build_axf.ld.S +205b5febc22c83179a2fc6c9005499ef61e8f347 - arm-trusted-firmware/plat/arm/board/arm_fpga/aarch64/fpga_helpers.S +87820ef2083d1576c3d29546b46fb922eafa3737 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/plat_macros.S +6631f2221faec011381242d2e2011d9eda3e9780 - arm-trusted-firmware/plat/arm/board/arm_fpga/include/platform_def.h diff --git a/nvbuild.sh b/nvbuild.sh new file mode 100755 index 0000000..8648626 --- /dev/null +++ b/nvbuild.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +# Copyright (c) 2019-2022, NVIDIA CORPORATION. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# * Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# * Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# * Neither the name of NVIDIA CORPORATION nor the names of its +# contributors may be used to endorse or promote products derived +# from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR +# CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +# PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR +# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY +# OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +# This script builds atf sources in this directory. +# Usage: ./${SCRIPT_NAME}.sh [OPTIONS] +set -e + +# shellcheck disable=SC2046 +SCRIPT_DIR="$(dirname $(readlink -f "${0}"))" +SCRIPT_NAME="$(basename "${0}")" + +source "${SCRIPT_DIR}/nvcommon_build.sh" + +function usage { + cat <